From 4c7ea3133e709a040c7a3c381858c6d24eaeaea5 Mon Sep 17 00:00:00 2001 From: multipleof4 Date: Tue, 9 Sep 2025 08:38:35 -0700 Subject: [PATCH] Sync: Update sune 'Agent' --- agent.sune | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent.sune b/agent.sune index 810e617..2d4d785 100644 --- a/agent.sune +++ b/agent.sune @@ -1 +1 @@ -[{"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":"
\n 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>>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
\n
\n \n Agent Control\n
\n \n
\n\n
\n \n \n \n \n
\n\n
\n \n\n
\n
\n        
\n \n \n \n
\n
\n
\n
\n\n","extension_html":"","hide_composer":false},"storage":{}}] \ No newline at end of file +[{"id":"cjnh9pp","name":"Agent","pinned":false,"avatar":"data:image/webp;base64,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","url":"gh://sune-org/store/agent.sune","updatedAt":1757432316131,"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 a live 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 in triple backticks, it runs immediately.\nAccessing individual API keys:\nwindow.USER.apiKeyOpenRouter\nwindow.USER.apiKeyOpenAI\nwindow.USER.apiKeyGoogle\nwindow.USER.apiKeyCloudflare\nwindow.USER.githubToken\nYou can use this command to pass information to the next chat, for example when you need to know the return value of something, put it here and the next user chat will output it:\n```js\nwindow.USER.log(str)\n```\nTypically when you send your response, the chat is concluded. If required anywhere in your response put <3 as in the heart of the conversation needs to stay alive for another round. The <3 will ensure the conversation doesnt end.","html":"
\n 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>>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
\n
\n \n Agent Control\n
\n \n
\n\n
\n \n \n \n \n
\n\n
\n \n\n
\n
\n        
\n \n \n \n
\n
\n
\n
\n\n","extension_html":"","hide_composer":false},"storage":{}}] \ No newline at end of file