mirror of
https://github.com/sune-org/store.git
synced 2026-01-13 16:17:58 +00:00
1 line
17 KiB
JSON
1 line
17 KiB
JSON
[{"id":"cjnh9pp","name":"Agent","pinned":false,"avatar":"data:image/webp;base64,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","url":"gh://sune-org/store/agent.sune","updatedAt":1757429818443,"settings":{"model":"g:gemini-2.5-flash","temperature":"","top_p":"","top_k":"","frequency_penalty":"","repetition_penalty":"","min_p":"","top_a":"","verbosity":"","reasoning_effort":"default","system_prompt":"You are an agent. Depending on the task, you may return partial html (preferred) or JavaScript. If returning html realize that you are inserting into already existing html. Tailwind, lucide, dom-cash, alpinejs are available. When you return code, it runs immediately.\n\nAccessing individual API keys:\nwindow.USER.apiKeyOpenRouter\nwindow.USER.apiKeyOpenAI\nwindow.USER.apiKeyGoogle\nwindow.USER.apiKeyCloudflare\nwindow.USER.githubToken","html":"<div class=\"p-3 sm:p-4\">\n <div\n x-data=\"{\n // UI\n isActive:false,\n isConsoleOpen:false,\n version:'v0.5.1',\n\n // Logs\n logs:[],\n storageKey:`sune_agent_panel_active_${window.SUNE.id}`,\n logStorageKey:`sune_agent_panel_logs_${window.SUNE.id}`,\n\n // De-dupe\n ns:'',\n processed:new Set(),\n processedKey:`sune_agent_processed_${window.SUNE.id}`,\n\n // Mount info\n mountId:'agent-runtime',\n\n // Sune switch handling\n currentSuneId: window.SUNE?.id || '',\n idPoll:null,\n\n init(){\n // Restore UI + logs\n this.isActive = localStorage.getItem(this.storageKey)==='true';\n this.logs = JSON.parse(localStorage.getItem(this.logStorageKey)||'[]');\n\n // Restore processed keys\n try{ this.processed = new Set(JSON.parse(localStorage.getItem(this.processedKey)||'[]')) }catch{ this.processed = new Set() }\n\n // Namespace per sune and bind once\n this.currentSuneId = window.SUNE?.id || '';\n this.ns = `.sag-${this.currentSuneId}`;\n this.bindComposer();\n\n // Persist\n $watch('isActive', v=>localStorage.setItem(this.storageKey, v));\n $watch('logs', v=>localStorage.setItem(this.logStorageKey, JSON.stringify(v)));\n\n // Watch Sune switching\n this.startSuneWatcher();\n\n this.$nextTick(()=>this.scrollConsole());\n },\n\n bindComposer(){\n const $c=$('#composer');\n // Ensure previous handlers for this ns are cleared before rebinding\n $c.off(`sune:newSuneResponse${this.ns}`).on(`sune:newSuneResponse${this.ns}`, e=>this.handleResponse(e));\n $c.off(`submit${this.ns}`).on(`submit${this.ns}`, ()=>this.injectContext());\n // Optional platform event for switching (if emitted)\n $c.off(`sune:changed${this.ns}`).on(`sune:changed${this.ns}`, e=>this.onSuneChanged(e?.detail?.id||window.SUNE?.id));\n },\n\n startSuneWatcher(){\n try{ clearInterval(this.idPoll) }catch{};\n this.idPoll=setInterval(()=>{ const id=window.SUNE?.id; if(id && id!==this.currentSuneId) this.onSuneChanged(id) },500);\n },\n\n onSuneChanged(newId){\n if(!newId || newId===this.currentSuneId) return;\n try{ $('#composer').off(`.sag-${this.currentSuneId}`) }catch{};\n const prev=this.currentSuneId; this.currentSuneId=newId; this.ns=`.sag-${newId}`;\n this.storageKey=`sune_agent_panel_active_${newId}`;\n this.logStorageKey=`sune_agent_panel_logs_${newId}`;\n this.processedKey=`sune_agent_processed_${newId}`;\n // Reload per-Sune state\n this.isActive = localStorage.getItem(this.storageKey)==='true';\n this.logs = JSON.parse(localStorage.getItem(this.logStorageKey)||'[]');\n try{ this.processed = new Set(JSON.parse(localStorage.getItem(this.processedKey)||'[]')) }catch{ this.processed = new Set() }\n // Cleanup canvas to avoid bleed\n this.clearCanvas();\n // Rebind for new Sune\n this.bindComposer();\n this.log('SYS',`Switched Sune ${prev||'-'} -> ${newId}`);\n },\n\n // ------------- Utils -------------\n saveProcessed(){ try{ localStorage.setItem(this.processedKey, JSON.stringify([...this.processed].slice(-200))) }catch{} },\n markProcessed(k){ this.processed.add(k); this.saveProcessed() },\n hasProcessed(k){ return this.processed.has(k) },\n hash(s){ let h=0; for(let i=0;i<s.length;i++) h=((h<<5)-h)+s.charCodeAt(i)|0; return 'h'+(h>>>0).toString(16) },\n uid(){ return Date.now().toString(36)+Math.random().toString(36).slice(2,6) },\n\n log(type,msg){\n const ts=new Date().toLocaleTimeString();\n this.logs.push(`[${ts} ${type}] ${msg}`);\n if(this.logs.length>50) this.logs.shift();\n this.$nextTick(()=>this.scrollConsole());\n },\n scrollConsole(){ const el=this.$refs.console; if(el) el.scrollTop=el.scrollHeight },\n\n ensureMount(){\n const host=document.getElementById('suneHtml');\n if(!host){ this.log('WARN','#suneHtml not found'); return null }\n host.classList.remove('hidden');\n let mount=host.querySelector('#'+this.mountId);\n if(!mount){\n mount=document.createElement('div');\n mount.id=this.mountId;\n mount.className='agent-runtime space-y-2 p-2';\n host.appendChild(mount);\n }\n return mount;\n },\n\n injectHTMLBlock(html){\n const mount=this.ensureMount();\n if(!mount) return;\n const wrapId='agent-block-'+this.uid();\n // Build fragment\n const tpl=document.createElement('template');\n tpl.innerHTML=html;\n const frag=tpl.content.cloneNode(true);\n // Wrap to scope script execution and later cleanup\n const wrap=document.createElement('div');\n wrap.setAttribute('data-agent-block', wrapId);\n wrap.className='rounded-lg border border-gray-200 bg-white/50 p-2';\n wrap.appendChild(frag);\n mount.appendChild(wrap);\n\n // Recreate scripts after DOM insertion to ensure execution\n const runScripts=container=>{\n const scripts=[...container.querySelectorAll('script')];\n scripts.forEach(old=>{\n const s=document.createElement('script');\n // copy attributes (type, src, async, defer, etc.)\n [...old.attributes].forEach(a=>s.setAttribute(a.name,a.value));\n // inline code\n s.textContent=old.textContent||'';\n // replace to trigger execution\n old.parentNode?.replaceChild(s, old);\n });\n };\n runScripts(wrap);\n\n // Re-init Alpine within the newly added chunk\n try{ window.Alpine?.initTree?.(wrap) }catch(e){ this.log('WARN','Alpine init failed: '+(e?.message||'unknown')) }\n\n // Refresh Lucide icons if available\n try{ window.lucide?.createIcons?.() }catch{}\n\n this.log('HTML','Appended HTML to #suneHtml');\n },\n\n executeJSBlock(code){\n this.log('EXEC','Running JS block...');\n try{\n (new Function(code)).call(window);\n this.log('DONE','JS executed.');\n }catch(err){\n console.error('[Sune Agent] JS Execution Error:',err);\n this.log('ERROR', err?.message||'Execution failed');\n window.SUNE?.log?.(`Agent Error: ${err?.message||'Execution failed'}`);\n }\n },\n\n // ------------- Agent flow -------------\n handleResponse(e){\n if(!this.isActive) return;\n const msg=e?.detail?.message;\n if(!msg || msg.role!=='assistant' || !Array.isArray(msg.content)) return;\n\n // Ignore events not for current Sune if id present\n const curId=this.currentSuneId||window.SUNE?.id;\n const evtId=e?.detail?.suneId||e?.detail?.sune?.id||msg?.suneId||msg?.sune?.id;\n if(evtId && evtId!==curId){ this.log('SKIP',`Ignored event for ${evtId}`); return }\n\n const txt=msg.content.map(p=>p?.type==='text'?p.text:'').join('\\n');\n const msgKey=msg.id || this.hash(txt);\n\n // Avoid reprocessing same assistant message\n if(this.hasProcessed(msgKey)){ this.log('SKIP',`Already processed ${msgKey}`); return }\n\n // JS fences\n const reJS=/```(?:javascript|js)\\n([\\s\\S]*?)\\n```/gi;\n // HTML fences\n const reHTML=/```(?:html|htm)\\n([\\s\\S]*?)\\n```/gi;\n\n let any=false;\n\n // Execute JS blocks\n let mJS; \n while((mJS=reJS.exec(txt))!==null){\n const code=(mJS[1]||'').trim(); \n if(!code) continue;\n any=true;\n this.executeJSBlock(code);\n }\n\n // Inject HTML blocks\n let mHTML;\n while((mHTML=reHTML.exec(txt))!==null){\n const html=(mHTML[1]||'').trim();\n if(!html) continue;\n any=true;\n this.injectHTMLBlock(html);\n }\n\n if(any){\n this.markProcessed(msgKey);\n }\n },\n\n // ------------- Actions -------------\n injectContext(){\n if(!this.isActive || !this.logs.length) return;\n const input=$('#input'); const cur=String(input.val()||'');\n if(!cur.trim()) return;\n input.val(`[AGENT LOGS]\\n${this.logs.join('\\n')}\\n[/AGENT LOGS]\\n\\n`+cur);\n this.log('INFO','Injected logs into context for next message.');\n },\n\n clearLogs(){ this.logs=[]; this.log('INFO','Console cleared.') },\n\n clearExecHistory(){ this.processed.clear(); this.saveProcessed(); this.log('INFO','Execution history cleared.') },\n\n clearCanvas(){\n const mount=document.querySelector('#'+this.mountId);\n if(mount){ mount.innerHTML=''; this.log('INFO','Cleared injected HTML canvas.') }\n }\n }\"\n x-init=\"init()\"\n class=\"mx-auto w-full max-w-3xl rounded-xl border border-gray-200 bg-white p-3 shadow-sm\"\n >\n <div class=\"flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-2\">\n <i data-lucide=\"brain-circuit\" class=\"h-5 w-5 text-gray-600\"></i>\n <span class=\"text-sm font-medium text-gray-800\">Agent Control</span>\n </div>\n <span class=\"text-xs text-gray-400\" x-text=\"version\"></span>\n </div>\n\n <div class=\"mt-3 flex items-center justify-between rounded-lg bg-gray-100 p-2\">\n <label class=\"cursor-pointer text-sm text-gray-700\" x-text=\"isActive ? 'Status: Active' : 'Status: Inactive'\"></label>\n <button\n type=\"button\"\n role=\"switch\"\n :aria-checked=\"isActive\"\n @click=\"isActive=!isActive; log('SYS', isActive ? 'Agent Activated' : 'Agent Deactivated')\"\n :class=\"isActive ? 'bg-black' : 'bg-gray-300'\"\n class=\"relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none\"\n >\n <span :class=\"isActive ? 'translate-x-5' : 'translate-x-0'\" class=\"pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out\"></span>\n </button>\n </div>\n\n <div class=\"mt-2 border-t border-gray-200 pt-2\">\n <button @click=\"isConsoleOpen=!isConsoleOpen\" class=\"flex w-full items-center justify-between text-left text-sm font-medium text-gray-600 hover:text-black\">\n <span>Console</span>\n <i data-lucide=\"chevron-down\" class=\"h-4 w-4 transition-transform\" :class=\"isConsoleOpen && 'rotate-180'\"></i>\n </button>\n\n <div x-show=\"isConsoleOpen\" x-transition class=\"mt-2\">\n <pre x-ref=\"console\" class=\"max-h-48 overflow-y-auto rounded-md bg-gray-900 p-2 text-xs font-mono leading-relaxed text-white\" x-text=\"logs.join('\\n') || 'Console is empty.'\"></pre>\n <div class=\"mt-2 grid grid-cols-3 gap-2\">\n <button @click=\"clearLogs()\" class=\"flex items-center justify-center gap-2 rounded-md bg-gray-100 px-3 py-1.5 text-xs text-gray-600 hover:bg-gray-200\">\n <i data-lucide=\"trash-2\" class=\"h-3 w-3\"></i> Clear Logs\n </button>\n <button @click=\"clearExecHistory()\" class=\"flex items-center justify-center gap-2 rounded-md bg-gray-100 px-3 py-1.5 text-xs text-gray-600 hover:bg-gray-200\">\n <i data-lucide=\"rotate-ccw\" class=\"h-3 w-3\"></i> Forget Executions\n </button>\n <button @click=\"clearCanvas()\" class=\"flex items-center justify-center gap-2 rounded-md bg-gray-100 px-3 py-1.5 text-xs text-gray-600 hover:bg-gray-200\">\n <i data-lucide=\"eraser\" class=\"h-3 w-3\"></i> Clear Canvas\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n","extension_html":"<sune src='https://raw.githubusercontent.com/sune-org/store/refs/heads/main/sync.sune' private />","hide_composer":false},"storage":{}}] |