From a0ba505f9bce1f49604a7faa8e9de466176db280 Mon Sep 17 00:00:00 2001 From: multipleof4 Date: Tue, 9 Sep 2025 09:51:13 -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 7d59d0c..494223b 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":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 +[{"id":"cjnh9pp","name":"Agent","pinned":false,"avatar":"data:image/webp;base64,UklGRj4NAABXRUJQVlA4WAoAAAAwAAAAfwAAfwAASUNDUMgBAAAAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADZBTFBIGwgAAAGwRdu2aUvSPC8iXbZt27Zt20Y6s2wzIsq2bdu2bVc93L3m+Nhr73vuuSe+6iciJkD/j/2ooLf8bn/zEtNtAMd+ZEHbmN7YT7zc1PHLYVD7vlGB9wcG8Ds0ojEwfwC+p8YdAuDB8zYAhNJhTzHGLvHCRDqjDR+bNYCTqg6WfWolATxrxgBUB2MmMnDAbBVAkkwaD1d+bFROZPBcvQYYJFHHoP7HA3H6SoBnCviQJFcaEcDVFYF5CrAkA5/QmF+ifrkkQ8wSMEgGLqyRFwD3kgTM0SchpGcDV9P4BiQZYoYMJ5WAhVYJWBrAMwSWXg5otcAZpYADZ+ebieFpo20kv4CQfg4xO4bdEqCxgUqANACzAwzaCzGWgY9VBQ6R5ikkw33GOSm1q//C76TF/AxQEo1q8mtKugMUKeCWM3MEWGKUXaY+5SfAkpS8Br41Mx+BH4wxnNgmlQR8L7H0UPDMBDxWA1g6rvzn7U964nN+WxYmj0GSHgQkSCeFmBnDMdoNocNY1lbTQPLQjQHKzAR5KPocB6jXwEBzbmj6LuCPRUT4U/fQ8nTHvLy6Kibd0gqdlAXAKWYF+K2kxFppAJYEeE4OgpA0JFrxBiBJwJy8ACxJQGjljTIv+7IBivZ3sZ/aM6WhEfPybIjM0ynz8kxAkiahhufl0eApuSrzcgggaQBWd8oG8yLAkiaxD0KSIWbljQARkwC8CADNa4WBd63MNG83M7qGSb0y8tAMD4MGYFXXgaLPLrPvq5//3Bc++5T1qws8bEUBjxoM6v0Z+Xdm4XEQyw3DMHQACnBXNMosCBiWuISpfVDyb/jdv4Ghq8CznvWC2diC6NtNOwEM/En1B+MrVYAkcPW7+PuaCbhel8ERAficV7w8+abqlwLWgaZBvH4XwCfW7HPgLkA13VdXfU06LSnofMx6CWCJU2vQlVqOtyq9DGBX/rXqZ7ryx4ErrJeA6Gt6B7DagCXDndW+rPm99DlgzW4BbLbk1gCgvrdp3J+vn74JREvviojgBgJQ7/uAofG2CL+ycSHghuv2GepWfiBLyeAkyCMBdrTuTtjsMiMIqOhtDGsXcCXqOPtQ3cvUsYzh35IMWBoMWNL7IdbtP4Bklv2dDG49Nwog6Z2A0oOBr0sCYvvR63QugPNIB7hPEoAzUxdJwMky3RaQFKRrRHpjSfqHEx8rSaSRkD4uCbWd7F43gw18QumgJsBXgOdnVvpg2O57gurBawRwoAB2kjbAG/R1cEb2RHhpx8/hw4libQLgR5KoezYAX1aSgbJvAM6TXAOiI+DumdfD5KoNuHVlANX/o/udksAdgKSrkU4u6K30G4DsIwBK6bekgD83DJYUSUzrr7RjAPZU2gtwkCQAKzVYHUg6IbCVGJAkwH88l6YcpOWNgqI3gRNdDOAqArDSl4IlCBVXIel/AGVRAN4ryWBNOqj9rkESWDI4kQxEpRx4p4ZK0icBSfoj7eMkCRim9HnyN6kGpA2gIVN/SXmApeuDq4CoNEQSSgFPKAA+dRj8M3GlAGfXy8gOBSQ9C14o6UtgdQ7qNLxnMgCWBCQlUcAHq+8Cfj9AQrYDV5UEbEi6f5Zf7hmSzghMBeBCSiKJ7PWAJAOWzg0g6etgSQpQhgSU1o0BS4AnEoDqjZbhhJJkCBkI1QDXEXCdapFdnN53SPoivZrm94yHRFCSL8JjqgEIgL0dBBTVznSixBWS3KOJAq9Ty8nhsF0pyF0dngBKaQjjH0svcQI8QPozMEzEYHVEsgGLRJUCfru9vW14VfXdlpMBrLoaBCFJp7KmCgw9JRFEdjVbejtt6cuERiit9IfVdL8KRaOQ5ZWBULeJRK1HN46YlvFtJxEbB+1eCkiGllwKYE0bUHuAaLjv+VAkGboOh7e2Fpmkb0FMazcsOgQlM30B55VUYFfPJ+E+iSA6NLmPQuk4IziL5STpo/DvHoNa7mNaAUd1PAkiM/hsHWSC6Hg7Y3lqBdQZ8JhM1N7aqM4GkZnk6KCODnrK1KLPoOZVqrp8TP+DLyQGnc4mt5rRF1PzaNLDFq7yISl0xq/Uabhfx3/hRpOij776fdGAeFvQdJxI/UdCdDwenjQxdxwEZZn6v5G0fW+NCO64MmxNjI6AZ40h6dQOMJTPa2SgQxATiw5A4w9gjW946hq5dQi4cimLxSJKKWWxWJRMULKzudSLxWJnsSiLb0rajT0HAcdJCpb98VIsfagkQ5endKcugySxdKzsWpJ24Dw9TOnJ8PYxBrUPHEmdP4YrS4r1+R8cM4Y6D17ZL+Gq2dlanlbAiVZzUFeM8ge4miTD2VtlcmrTUd7XKAGlVTrK47PDgo5ztjyt0uUOwIsrmjTGAPyDWxTSa2XnaQXsnpDH6x2r95qSAs7b2oEHTgiPo3BSnnYi8Bi7wkk86E9wjcqcq/Uy/OIpMZIkl+tIOhiiFR2SFL6UpN/A1So4b+twWKwJS+QHdpUl8l/BtbJzt04MMSl3eCyv5jdw1aU0tehgrFjNX+AqkgqcfwY8ypnArRgl4MqSWMbTOWyUAG9tbe8sdra2F4Z9rdIR25vbm9ubWzthkKSA83YxnaNhs4PsSiyrpT7LklEZzr8e74BndzjT5/s8dESm0mc1zrsehvuNIB2+Z8+eF77w+S947nOuqXaPdMSL9u3ds/eFe1/wlF1qnbPDE9Mo40LpGNFw7o6YpwFiFQHn6ihTWgDzsAMX6GBKYnZN7Ql9bQqeVmpN+aThFGNwjW1snGLjGtvGtpPAKa6xcR6b+r9GAFZQOCAsAwAAsBAAnQEqgACAAD5tNJRHpCMiISeVWfCADYlpEUBK1AIFJcuHbHHDUDSI/qmvB1A/4304f3A9iAWCi9gFrkteBRZtqzu4iC0pYqoJ2ybRQngB7lkRVKbWe4oqO+FUAiGgNCD0eWMpgd4aJPkDe/N9MvmIptaBway3vKDRJ2+b4wd+I0/qRUTvbaKz/XVpAAD++/1bg0Oi661NeMgjfcuKgsBwnTwfhVqQo0NskPHqvTwFau6dFpdGM1pGJ8RT1JmHo3BaOiwhmHb6663Pi5zCvbQc+RrV654T1uCKVD3QGGZBvdjJ/7GDofJeMN2CKrQFB5vSFV6LSQE9nCt0aZHNnJ0U/KxBbEiFXeMLdteIKCkMhMzwZgC0wNVKMgl62cq2T1dFm+1y26iLYGr+iZpbvnQvidrNC3MKksFSl9SObAMUsLmfmn5Y90lAx/WCtBa+JLHZVF8Fg4T69nLzw16IDSJorBOPAh5Tb03hGS9N5AXCDOnLHVNSoDd4eU0D1PdGc9QQBDTVBt1CgpOTipAlkOX18R/Vt4p8cRUsOiNYNP6iZrIlzt8iyJTtSTGEqImuCD0ALlGJ6KxhADDWCGrxP1u+vd5/xwGUumh2SQlFbSfPs1yQZTWNOFWA6z4JPR3DxIeuaZEcG6TbpsJjmNIYXqq/oCE6ErkmHVwxYELkiAQKtdNIgdluxMdvGeZ74OFSvl5DRexx9xRcL9jOY+Ux0ItLFzez9vSUF3/MbRzgNUKTxegHTjCZKYEAW7138I/jWvvFlqCZRN/n2f9L6zh2UF1lNcIObYmsYFJbEYt4Hb1WdPeqtOyFmER3fw+c8y/Ut8/KEi+HHzcn1egb+rTL0oBIqx1w2nLK9dRJxcGjAriBjItJhcyYIUKdPKrHmEmFYGZ6KRZymYdWfBJ5r+MTTfMgm1/ZvzAfsy7USZh1oAvtYiLym/5JRgqgCoXnjxeC4VmpCFrcGVtrlOnFc3Oq8mTNrokUjYeHttU6A2hxp+dyMBerm5vsDEdqBCRS3w7C9Duv+pv1UkGgBJqYXgF1Qa8//kCXv10gFz8yICcLfc96rk3IGwGrsUAAAAA=","url":"gh://sune-org/store/agent.sune","updatedAt":1757436673764,"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)); $watch('logs',()=>this.saveLogs());\n this.$nextTick(()=>{this.scrollConsole(); try{window.lucide?.createIcons?.()}catch{}}); 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); this.log('AUTO','Input set')}catch(e){ this.log('ERROR','Set input failed: '+(e?.message||e)) } };\n const sendNow=()=>{ try{\n const form=$('#composer')[0], btn=document.getElementById('sendBtn');\n if(btn && btn.getAttribute('type')==='submit'){ btn.click(); this.log('AUTO','Clicked #sendBtn (DOM)') }\n else if($('#sendBtn').length){ $('#sendBtn').trigger('click'); this.log('AUTO','Triggered #sendBtn click') }\n else if(form?.requestSubmit){ form.requestSubmit(); this.log('AUTO','Form.requestSubmit()') }\n else { $('#composer').trigger('submit'); this.log('AUTO','Triggered form submit') }\n window.haptic?.();\n }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);\n if(window.state?.busy){ this.log('BLOCK','Still busy, retrying'); 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