From 2714f3b65ecfe49bea3d939158d62055b71a1cb3 Mon Sep 17 00:00:00 2001 From: multipleof4 Date: Tue, 9 Sep 2025 09:41:00 -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 2d4d785..7d59d0c 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":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 +[{"id":"cjnh9pp","name":"Agent","pinned":false,"avatar":"data:image/webp;base64,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","url":"gh://sune-org/store/agent.sune","updatedAt":1757436061485,"settings":{"model":"or:z-ai/glm-4.5","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',()=>this.saveLogs());\n this.$nextTick(()=>{this.scrollConsole(); try{window.lucide?.createIcons?.()}catch{}})\n this.log('SYS',`Agent ready on ${this.currentSuneId}`);\n },\n\n // -------- Per-sune state --------\n restorePerSune(){\n try{this.isActive=localStorage.getItem(this.storageKey)==='true'}catch{}; \n try{this.logs=JSON.parse(localStorage.getItem(this.logStorageKey)||'[]')}catch{this.logs=[]};\n try{this.processed=new Set(JSON.parse(localStorage.getItem(this.processedKey)||'[]'))}catch{this.processed=new Set()};\n },\n updateKeysFor(id){\n this.currentSuneId=id||window.SUNE?.id||''; this.ns=`.sag-${this.currentSuneId}`;\n this.storageKey=`sune_agent_panel_active_${this.currentSuneId}`; \n this.logStorageKey=`sune_agent_panel_logs_${this.currentSuneId}`;\n this.processedKey=`sune_agent_processed_${this.currentSuneId}`;\n },\n\n // -------- Composer binding --------\n bindComposer(){\n const $c=$('#composer'); $c.off(`sune:newSuneResponse${this.ns}`).on(`sune:newSuneResponse${this.ns}`,e=>this.onSuneResponse(e));\n $c.off(`submit${this.ns}`).on(`submit${this.ns}`,()=>this.injectContext());\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)},333);\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.updateKeysFor(newId); this.restorePerSune(); this.clearCanvas(); this.bindComposer();\n this.log('SYS',`Switched Sune ${prev||'-'} -> ${newId}`);\n },\n\n // -------- Utils --------\n saveLogs(){ try{localStorage.setItem(this.logStorageKey,JSON.stringify(this.logs.slice(-200)))}catch{} },\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 log(t,m){ const ts=new Date().toLocaleTimeString(); this.logs.push(`[${ts} ${t}] ${m}`); if(this.logs.length>200)this.logs.shift(); this.$nextTick(()=>this.scrollConsole()) },\n scrollConsole(){ const el=this.$refs.console; if(el) el.scrollTop=el.scrollHeight },\n\n ensureMount(){\n const host=document.getElementById('suneHtml'); if(!host){this.log('WARN','#suneHtml not found');return null}\n host.classList.remove('hidden'); let mount=host.querySelector('#'+this.mountId);\n if(!mount){ mount=document.createElement('div'); mount.id=this.mountId; mount.className='agent-runtime space-y-2 p-2'; host.appendChild(mount) }\n return mount;\n },\n\n // -------- HTML / JS exec --------\n injectHTMLBlock(html){\n const mount=this.ensureMount(); if(!mount)return; const wrap=document.createElement('div'); wrap.setAttribute('data-agent-block',this.uid()); wrap.className='rounded-lg border border-gray-200 bg-white/50 p-2'; wrap.innerHTML=html; mount.appendChild(wrap);\n [...wrap.querySelectorAll('script')].forEach(old=>{const s=document.createElement('script');[...old.attributes].forEach(a=>s.setAttribute(a.name,a.value)); s.textContent=old.textContent||''; old.parentNode?.replaceChild(s,old)});\n try{ window.Alpine?.initTree?.(wrap) }catch(e){ this.log('WARN','Alpine init failed: '+(e?.message||'unknown')) }\n try{ window.lucide?.createIcons?.() }catch{}\n this.log('HTML','Injected HTML block');\n },\n\n executeJSBlock(code){\n this.log('EXEC','Running JS block'); try{ (new Function(code)).call(window); this.log('DONE','JS executed') }catch(err){ console.error('[Sune Agent] JS Execution Error:',err); this.log('ERROR',err?.message||'Execution failed'); window.SUNE?.log?.('Agent Error: '+(err?.message||'Execution failed')) }\n },\n\n // -------- Auto Next: core --------\n async autoAskNext(msgId){\n const key=`auto:${msgId||this.uid()}`; if(this.hasProcessed(key)) return this.log('SKIP','Auto-send already processed for '+(msgId||'-'));\n const setVal=v=>{ try{$('#input').val(v)}catch{} }, sendNow=()=>{ try{ const f=$('#composer')[0]; const sb=$('#sendBtn'); if(sb.attr('type')==='submit') sb.click(); else if(f?.requestSubmit) f.requestSubmit(); else $('#composer').trigger('submit'); window.haptic?.() }catch(e){ this.log('ERROR','Dispatch failed: '+(e?.message||e)) } };\n const waitIdle=ms=>new Promise(r=>{let t=Date.now(),i=setInterval(()=>{if(!window.state?.busy||Date.now()-t>ms){clearInterval(i);r()}},50)});\n this.log('AUTO','Triggering auto-send: What’s next?'); setVal('What’s next?'); await waitIdle(4000); if(window.state?.busy){this.log('BLOCK','Still busy, retrying send'); await waitIdle(4000)}\n if(window.state?.busy){ this.log('FAIL','Aborted: still busy after wait'); return }\n sendNow(); this.markProcessed(key); this.log('AUTO','Auto-send dispatched');\n },\n\n // -------- Event handling --------\n onSuneResponse(e){\n if(!this.isActive) return this.log('SKIP','Inactive; ignoring response');\n const msg=e?.detail?.message; if(!msg||msg.role!=='assistant'||!Array.isArray(msg.content)) return;\n const txt=(window.partsToText(msg.content)||'')+'\\n'+(window.partsToText(window.SUNE?.lastReply?.content||'')||'');\n // Fenced blocks\n let any=false,m; const reJS=/```(?:javascript|js)\\n([\\s\\S]*?)\\n```/gi,reHTML=/```(?:html|htm)\\n([\\s\\S]*?)\\n```/gi, msgKey=msg.id||this.hash(txt);\n if(!this.hasProcessed(msgKey)){ while((m=reJS.exec(txt))!==null){ if((m[1]||'').trim()){ any=true; this.executeJSBlock((m[1]||'').trim()) } } while((m=reHTML.exec(txt))!==null){ if((m[1]||'').trim()){ any=true; this.injectHTMLBlock((m[1]||'').trim()) } } if(any){ this.markProcessed(msgKey); this.log('PROC','Executed blocks for '+msgKey) } }\n // Auto next if '<3' anywhere in reply text\n if(/<3/.test(txt)){ this.log('MATCH','Found <3 in reply; scheduling auto-send'); this.autoAskNext(msg.id||msgKey) } else this.log('MISS','No <3 in reply');\n },\n\n // -------- Actions --------\n injectContext(){\n if(!this.isActive||!this.logs.length) return;\n const input=$('#input'),cur=String(input.val()||''); if(!cur.trim()) return; input.val(`[AGENT LOGS]\\n${this.logs.join('\\n')}\\n[/AGENT LOGS]\\n\\n`+cur);\n this.log('INFO','Injected logs into context');\n },\n clearLogs(){ this.logs=[]; this.saveLogs(); this.log('SYS','Console cleared') },\n clearExecHistory(){ this.processed.clear(); this.saveProcessed(); this.log('SYS','Execution history cleared') },\n clearCanvas(){ const mount=document.querySelector('#'+this.mountId); if(mount){ mount.innerHTML=''; this.log('SYS','Cleared injected HTML canvas') } }\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