@lelouchhe/webagent 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.html CHANGED
@@ -41,6 +41,6 @@
41
41
  </div>
42
42
  <div id="status-bar"></div>
43
43
 
44
- <script src="/js/app.C4WRSLDF.js"></script>
44
+ <script src="/js/app.6BGATUZ7.js"></script>
45
45
  </body>
46
46
  </html>
@@ -7,4 +7,4 @@ var ue=class extends Error{name="ApiError";status;constructor(t,s){super(s),this
7
7
  `):null}return null}function Q(e,t=!1){let s=document.createElement("div");return s.className="bash-block",s.innerHTML=`<span class="bash-cmd${t?" running":""}">${p(e)}</span><div class="bash-output"></div>`,s.querySelector(".bash-cmd").addEventListener("click",()=>{let i=s.querySelector(".bash-output");i.style.display==="none"?i.style.display="block":i.classList.contains("has-content")&&(i.style.display="none")}),E(s),t&&(n.currentBashEl=s),s}function Y(e,t,s){if(!e)return;let i=e.querySelector(".bash-cmd");i.classList.remove("running");let r="";if(s?r=`[signal: ${s}]`:t!==0&&t!=null&&(r=`[exit: ${t}]`),r){let a=document.createElement("span");a.className=`bash-exit ${t===0?"ok":"fail"}`,a.textContent=r,i.after(a)}e===n.currentBashEl&&(n.currentBashEl=null)}var mt={auto:"\u25D1",light:"\u2600",dark:"\u263E"},Ue=["auto","light","dark"];function Ke(){return localStorage.getItem("theme")||"auto"}function Ve(e){document.documentElement.setAttribute("data-theme",e),o.themeBtn.textContent=mt[e],o.themeBtn.title=`Theme: ${e}`,localStorage.setItem("theme",e)}o.themeBtn.onclick=()=>{let e=Ke();Ve(Ue[(Ue.indexOf(e)+1)%3])};Ve(Ke());var we={task_complete:"\u2714",read:"cat",edit:"edit",execute:"exec",search:"find",delete:"rm"},ve="run",Ie={pending:"\u25CB",in_progress:"\u25C9",completed:"\u25CF"};function Ge(e){return n.replayTarget?.querySelector(`[id="${e}"]`)??document.getElementById(e)}function gt(e){return n.replayTarget?.querySelector(e)??document.querySelector(e)}var Je="webagent_notify_tip_shown",Qe="webagent_notify_tip_denied_shown";function ht(){if(typeof Notification>"u"||n.replayInProgress)return;let e=Notification.permission;if(e!=="granted"){if(e==="denied"){if(localStorage.getItem(Qe))return;localStorage.setItem(Qe,"1"),c("tip: notifications are blocked \u2014 allow in browser site settings to enable");return}localStorage.getItem(Je)||(localStorage.setItem(Je,"1"),c("tip: use /notify to enable background notifications"))}}function ae(){n.pendingPromptDone&&(n.pendingToolCallIds.size>0||n.pendingPermissionRequestIds.size>0||(D(),k(),P(),I(!1),n.pendingPromptDone=!1,ht()))}function yt(){for(let e of n.pendingToolCallIds){let t=document.getElementById(`tc-${e}`);if(!t)continue;t.className="tool-call failed";let s=t.querySelector(".icon");s&&(s.textContent="\u2717")}for(let e of n.pendingPermissionRequestIds){let t=document.querySelector(`.permission[data-request-id="${e}"]`);if(!t||!t.querySelector("button"))continue;let i=t.querySelector(".title")?.textContent||"\u26BF";t.innerHTML=`<span style="opacity:0.5">${p(i)} \u2014 cancelled</span>`}n.pendingToolCallIds.clear(),n.pendingPermissionRequestIds.clear()}function wt(){for(let e of n.pendingToolCallIds){let t=document.getElementById(`tc-${e}`);if(!t)continue;t.className="tool-call completed";let s=t.querySelector(".icon");s&&(s.textContent="\u2713")}n.pendingToolCallIds.clear(),n.pendingPermissionRequestIds.clear()}function be(e){if(Array.isArray(e))return{events:e,streaming:{thinking:!1,assistant:!1}};let t=e;return{events:t.events??[],streaming:t.streaming??{thinking:!1,assistant:!1},total:typeof t.total=="number"?t.total:void 0,hasMore:typeof t.hasMore=="boolean"?t.hasMore:void 0}}var Ye=200;async function N(e){n.replayInProgress=!0,n.replayQueue=[];try{let t=await fetch(`/api/v1/sessions/${e}/events?limit=${Ye}`);if(!t.ok)return!1;let s=await t.json(),{events:i,streaming:r,hasMore:a}=be(s),l=document.createDocumentFragment(),d=Ee(i);n.replayTarget=l;for(let u=0;u<i.length;u++){let f=JSON.parse(i[u].data);ke(i[u].type,f,i,u,d)}return n.replayTarget=null,o.messages.style.display="none",o.messages.appendChild(l),o.messages.style.display="",i.length&&(n.lastEventSeq=i[i.length-1].seq,n.oldestLoadedSeq=i[0].seq),n.hasMoreHistory=a===!0,n.hasMoreHistory&&vt(),ze(),Se(i,r),!0}catch{return!1}finally{n.replayTarget=null,n.replayInProgress=!1,Xe()}}function Se(e,t){if(t.thinking&&e.length){for(let s=e.length-1;s>=0;s--)if(e[s].type==="thinking"){let i=JSON.parse(e[s].data),r=o.messages.querySelectorAll(".thinking"),a=r[r.length-1];if(a){n.currentThinkingEl=a,n.currentThinkingText=i.text;let l=a.querySelector("summary");l&&(l.textContent="\u283F thinking...",l.classList.add("active"))}break}}if(t.assistant&&e.length){for(let s=e.length-1;s>=0;s--)if(e[s].type==="assistant_message"){let i=JSON.parse(e[s].data),r=o.messages.querySelectorAll(".msg.assistant"),a=r[r.length-1];a&&(n.currentAssistantEl=a,n.currentAssistantText=i.text);break}}}function ze(){let e=o.messages.querySelector("[data-sync-boundary]");e&&e.removeAttribute("data-sync-boundary");let t=o.messages.lastElementChild;t&&t.setAttribute("data-sync-boundary","")}async function Te(e){n.replayInProgress=!0,n.replayQueue=[];try{let t=`/api/v1/sessions/${e}/events?after=${n.lastEventSeq}`,s=await fetch(t);if(!s.ok)return!1;let i=await s.json(),{events:r,streaming:a}=be(i),l=o.messages.querySelector("[data-sync-boundary]");if(l)for(;l.nextElementSibling;)l.nextElementSibling.remove();if(n.currentAssistantEl=null,n.currentAssistantText="",n.currentThinkingEl=null,n.currentThinkingText="",n.currentBashEl=null,r.length===0)return Se(r,a),!0;let d=document.createDocumentFragment(),u=Ee(r);n.replayTarget=d;for(let f=0;f<r.length;f++){let g=JSON.parse(r[f].data);ke(r[f].type,g,r,f,u)}return n.replayTarget=null,o.messages.appendChild(d),n.lastEventSeq=r[r.length-1].seq,ze(),Se(r,a),!0}catch{return!1}finally{n.replayTarget=null,n.replayInProgress=!1,Xe()}}var z=null;function vt(){le();let e=document.createElement("div");e.id="history-sentinel",e.className="history-sentinel",e.textContent="\u2191 loading\u2026",o.messages.prepend(e),typeof IntersectionObserver=="function"&&(z=new IntersectionObserver(t=>{t[0]?.isIntersecting&&!n.loadingOlderEvents&&n.hasMoreHistory&&n.sessionId&&It(n.sessionId)},{root:o.messages,rootMargin:"200px 0px 0px 0px"}),z.observe(e))}function le(){z&&(z.disconnect(),z=null),document.getElementById("history-sentinel")?.remove()}Re(le);async function It(e){if(n.loadingOlderEvents||!n.hasMoreHistory||n.oldestLoadedSeq<=0)return!1;n.loadingOlderEvents=!0;try{let t=await fetch(`/api/v1/sessions/${e}/events?limit=${Ye}&before=${n.oldestLoadedSeq}`);if(!t.ok||e!==n.sessionId)return!1;let s=await t.json(),{events:i,hasMore:r}=be(s);if(i.length===0)return n.hasMoreHistory=!1,le(),!0;let a=document.createDocumentFragment(),l=Ee(i);n.replayTarget=a;for(let g=0;g<i.length;g++){let v=JSON.parse(i[g].data);ke(i[g].type,v,i,g,l)}n.replayTarget=null;let d=o.messages,u=d.scrollHeight,f=document.getElementById("history-sentinel");return f?f.after(a):d.prepend(a),d.scrollTop+=d.scrollHeight-u,n.oldestLoadedSeq=i[0].seq,n.hasMoreHistory=r===!0,n.hasMoreHistory||le(),!0}catch{return!1}finally{n.loadingOlderEvents=!1}}function Ze(){for(let[e,t]of n.unconfirmedPermissions){let s=document.querySelector(`.permission[data-request-id="${e}"]`);if(!s||!s.querySelector("button")){n.unconfirmedPermissions.delete(e);continue}t.denied?se(t.sessionId,e).catch(()=>{}):ne(t.sessionId,e,t.optionId).catch(()=>{});let i=s.dataset.title?`\u26BF ${p(s.dataset.title)}`:"\u26BF";s.innerHTML=`<span style="opacity:0.5">${i} \u2014 ${p(t.optionName)}</span>`,n.unconfirmedPermissions.delete(e)}}function Ee(e){let t=new Set;for(let s of e)s.type==="permission_response"&&t.add(JSON.parse(s.data).requestId);return{toolCalls:new Map,permissions:new Map,resolvedPermissions:t,currentBashEl:null}}function ke(e,t,s,i,r){switch(e){case"user_message":{let a=R("user",t.text);if(t.images)for(let l of t.images){let d=document.createElement("img");d.className="user-image",d.src=l.path,a.appendChild(d)}break}case"assistant_message":{let l=(n.replayTarget||o.messages).lastElementChild;if(l&&l.classList.contains("msg")&&l.classList.contains("assistant")){let f=(l.getAttribute("data-raw")||"")+t.text;l.setAttribute("data-raw",f),l.innerHTML=re(f);break}R("assistant",t.text).setAttribute("data-raw",t.text);break}case"thinking":{let l=(n.replayTarget||o.messages).lastElementChild;if(l&&l.classList.contains("thinking")){let u=l.querySelector(".thinking-content");if(u){u.textContent+=`
8
8
  `+t.text;break}}let d=document.createElement("details");d.className="thinking",d.innerHTML=`<summary>\u283F thought</summary><div class="thinking-content">${p(t.text)}</div>`,E(d);break}case"tool_call":{let a=we[t.kind]||ve,l=document.createElement("div");l.className="tool-call",l.id=`tc-${t.id}`,l.dataset.kind=t.kind;let d=`<span class="icon">${a}</span> ${p(t.title)}`,u=t.rawInput;u&&u.command?d+=`<span class="tc-detail">$ ${p(u.command)}</span>`:u&&u.path&&(d+=`<span class="tc-detail">${p(u.path)}</span>`),l.innerHTML=d;let f=t.kind==="edit"?ye(u):null;if(f){let v=document.createElement("details");v.innerHTML=`<summary>diff</summary><div class="diff-view">${f}</div>`,l.appendChild(v)}let g=l.querySelector(".tc-detail");g&&l.addEventListener("click",v=>{v.target.closest("details")||g.classList.toggle("expanded")}),E(l),r&&r.toolCalls.set(t.id,l);break}case"tool_call_update":{let a=r?r.toolCalls.get(t.id):Ge(`tc-${t.id}`);if(a){let l=t.status==="completed"?"\u2713":t.status==="failed"?"\u2717":"\u2026";a.className=`tool-call ${t.status}`;let d=a.querySelector(".icon");if(d&&(d.textContent=l),t.content&&t.content.length&&!a.querySelector("details")&&!a.querySelector(".tc-summary")){let u=t.content.map(f=>f.type==="terminal"?`[terminal ${f.terminalId}]`:f.content?.text?f.content.text:Array.isArray(f.content)?f.content.map(g=>g.text||"").join(""):"").filter(Boolean).join(`
9
9
  `);if(u)if(a.dataset.kind==="task_complete"){let f=document.createElement("div");f.className="tc-summary",f.textContent=u,a.appendChild(f)}else{let f=document.createElement("details");f.innerHTML=`<summary>output</summary><div class="tc-content">${p(u)}</div>`,a.appendChild(f)}}}(t.status==="completed"||t.status==="failed")&&n.pendingToolCallIds.delete(t.id);break}case"plan":{let a=document.createElement("div");a.className="plan",a.innerHTML='<div class="plan-title">\u2015 plan</div>'+(t.entries||[]).map(l=>`<div class="plan-entry">${Ie[l.status]||"?"} ${p(l.content)}</div>`).join(""),E(a);break}case"permission_request":{let a=document.createElement("div");a.className="permission",a.dataset.requestId=t.requestId,a.dataset.title=t.title||"",a.innerHTML=`<span class="title" style="opacity:0.5">\u26BF ${p(t.title)}</span> `,!(r?r.resolvedPermissions.has(t.requestId):s&&s.slice(i+1).some(d=>d.type==="permission_response"&&JSON.parse(d.data).requestId===t.requestId))&&t.options&&(a.querySelector(".title").style.opacity="1",t.options.forEach(d=>{let u=document.createElement("button"),f=(d.kind||"").includes("allow");u.className=f?"allow":"deny",u.textContent=d.name,u.onclick=()=>{(d.kind||"").includes("reject")||(d.kind||"").includes("deny")?se(n.sessionId,t.requestId).catch(()=>{}):ne(n.sessionId,t.requestId,d.optionId).catch(()=>{}),a.innerHTML=`<span style="opacity:0.5">\u26BF ${p(t.title)} \u2014 ${p(d.name)}</span>`},a.appendChild(u)})),E(a),r&&r.permissions.set(t.requestId,a);break}case"permission_response":{let a=r?r.permissions.get(t.requestId):gt(`.permission[data-request-id="${t.requestId}"]`);if(a){let l=a.dataset.title?`\u26BF ${a.dataset.title}`:"\u26BF",d=t.optionName||(t.denied?"denied":"allowed");a.innerHTML=`<span style="opacity:0.5">${p(l)} \u2014 ${p(d)}</span>`}break}case"bash_command":{let a=Q(t.command,!1);r?r.currentBashEl=a:a.id="bash-replay-pending";break}case"bash_result":{let a=r?r.currentBashEl:Ge("bash-replay-pending");if(a){if(r||a.removeAttribute("id"),t.output){let l=a.querySelector(".bash-output");l&&(l.textContent=t.output,l.classList.add("has-content"))}Y(a,t.code,t.signal),r&&(r.currentBashEl=null)}break}case"prompt_done":n.pendingToolCallIds.clear(),n.pendingPermissionRequestIds.clear(),n.pendingPromptDone=!1,I(!1);break}}function Xe(){let e=n.replayQueue;n.replayQueue=[];for(let t of e)St(t)||C(t)}function St(e){switch(e.type){case"tool_call":return!!document.getElementById(`tc-${e.id}`);case"permission_request":return!!document.querySelector(`.permission[data-request-id="${e.requestId}"]`);case"thought_chunk":return!!n.currentThinkingEl;case"message_chunk":return!!n.currentAssistantEl;default:return!1}}function C(e){if(n.replayInProgress){console.log("[handleEvent-DEBUG] QUEUED (replayInProgress):",e.type),n.replayQueue.push(e);return}if(!(e.sessionId&&e.type!=="session_created"&&e.type!=="session_deleted"&&(!n.sessionId||e.sessionId!==n.sessionId)))switch(e.type){case"connected":e.cancelTimeout!=null&&(n.cancelTimeout=e.cancelTimeout);break;case"session_created":if(!n.awaitingNewSession&&n.sessionId&&e.sessionId!==n.sessionId)break;if(n.awaitingNewSession=!1,n.sessionId=e.sessionId,n.sessionCwd=e.cwd||n.sessionCwd,n.sessionTitle=e.title||null,e.configOptions?.length&&me(e.configOptions),Fe(n.sessionId),n.clientId&&V(n.clientId,!document.hidden,n.sessionId).catch(()=>{}),oe(n.sessionId,n.sessionTitle),B("connected","connected"),o.input.disabled=!1,o.sendBtn.disabled=!1,o.input.placeholder="Message or ?",I(!!e.busyKind),n.newTurnStarted=!1,e.busyKind==="bash"){let t=document.getElementById("bash-replay-pending");t&&(t.removeAttribute("id"),t.querySelector(".bash-cmd")?.classList.add("running"),n.currentBashEl=t)}else n.currentBashEl=null;o.messages.children.length===0&&c(`Session created: ${n.sessionTitle||e.sessionId.slice(0,8)+"\u2026"}`),O();break;case"user_message":{if(n.sentMessageForSession===e.sessionId){n.sentMessageForSession=null;break}if(k(),P(),n.newTurnStarted=!0,n.turnEnded=!1,e.sessionId===n.sessionId){let t=R("user",e.text);if(e.images)for(let s of e.images){let i=document.createElement("img");i.className="user-image",i.src=s.path,t.appendChild(i)}}break}case"message_chunk":if(n.turnEnded)break;D(),k(),n.currentAssistantEl||(n.currentAssistantEl=R("assistant",""),n.currentAssistantText=""),n.currentAssistantText+=e.text,n.currentAssistantEl.innerHTML=re(n.currentAssistantText),S();break;case"thought_chunk":if(n.turnEnded)break;D(),n.currentThinkingEl||(n.currentThinkingEl=document.createElement("details"),n.currentThinkingEl.className="thinking",n.currentThinkingEl.innerHTML='<summary class="active">\u283F thinking...</summary><div class="thinking-content"></div>',n.currentThinkingText="",E(n.currentThinkingEl)),n.currentThinkingText+=e.text,n.currentThinkingEl.querySelector(".thinking-content").textContent=n.currentThinkingText,S();break;case"tool_call":{if(n.turnEnded)break;n.pendingToolCallIds.add(e.id),I(!0),D(),k(),P();let t=we[e.kind]||ve,s=document.createElement("div");s.className="tool-call",s.id=`tc-${e.id}`,s.dataset.kind=e.kind;let i=`<span class="icon">${t}</span> ${p(e.title)}`,r=e.rawInput;r&&r.command?i+=`<span class="tc-detail">$ ${p(r.command)}</span>`:r&&r.path&&(i+=`<span class="tc-detail">${p(r.path)}</span>`),s.innerHTML=i;let a=e.kind==="edit"?ye(r):null;if(a){let d=document.createElement("details");d.innerHTML=`<summary>diff</summary><div class="diff-view">${a}</div>`,s.appendChild(d)}let l=s.querySelector(".tc-detail");l&&s.addEventListener("click",d=>{d.target.closest("details")||l.classList.toggle("expanded")}),E(s);break}case"tool_call_update":{let t=document.getElementById(`tc-${e.id}`);if((e.status==="completed"||e.status==="failed")&&n.pendingToolCallIds.delete(e.id),t){let s=e.status==="completed"?"\u2713":e.status==="failed"?"\u2717":"\u2026";t.className=`tool-call ${e.status}`;let i=t.querySelector(".icon");if(i&&(i.textContent=s),e.content&&e.content.length&&!t.querySelector("details")&&!t.querySelector(".tc-summary")){let r=e.content.map(a=>a.type==="terminal"?`[terminal ${a.terminalId}]`:a.content?.text?a.content.text:Array.isArray(a.content)?a.content.map(l=>l.text||"").join(""):"").filter(Boolean).join(`
10
- `);if(r)if(t.dataset.kind==="task_complete"){let a=document.createElement("div");a.className="tc-summary",a.textContent=r,t.appendChild(a)}else{let a=document.createElement("details");a.innerHTML=`<summary>output</summary><div class="tc-content">${p(r)}</div>`,t.appendChild(a)}}}ae(),S();break}case"plan":{k(),P();let t=document.createElement("div");t.className="plan",t.innerHTML='<div class="plan-title">\u2015 plan</div>'+e.entries.map(s=>`<div class="plan-entry">${Ie[s.status]||"?"} ${p(s.content)}</div>`).join(""),E(t);break}case"permission_request":{if(n.turnEnded||document.querySelector(`.permission[data-request-id="${e.requestId}"]`))break;n.pendingPermissionRequestIds.add(e.requestId),I(!0),k();let t=document.createElement("div");t.className="permission",t.dataset.requestId=e.requestId,t.dataset.title=e.title||"",t.innerHTML=`<span class="title">\u26BF ${p(e.title)}</span> `,e.options.forEach(s=>{let i=document.createElement("button"),r=(s.kind||"").includes("allow");i.className=r?"allow":"deny",i.textContent=s.name,i.onclick=()=>{let a=(s.kind||"").includes("reject")||(s.kind||"").includes("deny");a?se(n.sessionId,e.requestId).catch(()=>{}):ne(n.sessionId,e.requestId,s.optionId).catch(()=>{}),n.pendingPermissionRequestIds.delete(e.requestId),n.unconfirmedPermissions.set(e.requestId,{sessionId:n.sessionId,optionId:s.optionId,optionName:s.name,denied:a}),t.innerHTML=`<span style="opacity:0.5">\u26BF ${p(e.title)} \u2014 ${p(s.name)}</span>`,ae()},t.appendChild(i)}),E(t);break}case"permission_resolved":{n.pendingPermissionRequestIds.delete(e.requestId),n.unconfirmedPermissions.delete(e.requestId);let t=document.querySelector(`.permission[data-request-id="${e.requestId}"]`);if(e.sessionId===n.sessionId&&t){let s=t.dataset.title?`\u26BF ${t.dataset.title}`:"\u26BF",i=e.optionName||(e.denied?"denied":"allowed");t.innerHTML=`<span style="opacity:0.5">${p(s)} \u2014 ${p(i)}</span>`}ae();break}case"bash_command":{if(n.sentBashForSession===e.sessionId){n.sentBashForSession=null;break}e.sessionId===n.sessionId&&(Q(e.command,!0),I(!0));break}case"bash_output":{if(e.sessionId!==n.sessionId)break;if(n.currentBashEl){let t=n.currentBashEl.querySelector(".bash-output");if(e.stream==="stderr"){let s=document.createElement("span");s.className="stderr",s.textContent=e.text,t.appendChild(s)}else t.appendChild(document.createTextNode(e.text));t.classList.add("has-content"),t.scrollTop=t.scrollHeight,S()}break}case"bash_done":{if(e.sessionId!==n.sessionId)break;Y(n.currentBashEl,e.code,e.signal),e.error&&c(`err: ${e.error}`),I(!1);break}case"prompt_done":{if(J(),e.stopReason==="cancelled"&&n.newTurnStarted){n.newTurnStarted=!1,k(),P();break}n.newTurnStarted=!1,e.stopReason==="cancelled"?yt():wt(),n.turnEnded=!0,n.pendingPromptDone=!0,ae();break}case"session_deleted":e.sessionId===n.sessionId&&(c("warn: This session has been deleted."),o.input.disabled=!0,o.sendBtn.disabled=!0,o.input.placeholder="Session deleted");break;case"session_expired":y(),c("warn: Previous session expired, created new one."),M();break;case"config_set":{Oe(e.configId,e.value);let t=x(e.configId),s=t?.name||e.configId,i=t?.options.find(r=>r.value===e.value)?.name||e.value;c(`ok: ${s}: ${i}`),e.configId==="mode"&&_(),O();break}case"config_option_update":e.configOptions?.length&&me(e.configOptions);break;case"session_title_updated":e.sessionId===n.sessionId&&(n.sessionTitle=e.title,oe(n.sessionId,n.sessionTitle));break;case"error":n.awaitingNewSession=!1,n.pendingToolCallIds.clear(),n.pendingPermissionRequestIds.clear(),n.pendingPromptDone=!1,D(),k(),P(),c(`err: ${e.message}`),I(!1);break}}async function bt(){try{let e=await navigator.serviceWorker?.ready;if(!e)return;let t=await fetch("/api/beta/push/vapid-key");if(!t.ok)return;let{publicKey:s}=await t.json(),r=(await e.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:Et(s)})).toJSON();await fetch("/api/beta/push/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({endpoint:r.endpoint,keys:r.keys,clientId:n.clientId})})}catch(e){console.error("[push] subscribe failed:",e)}}async function Tt(){try{let e=await navigator.serviceWorker?.ready;if(!e)return;let t=await e.pushManager.getSubscription();if(!t)return;let s=t.endpoint;await t.unsubscribe(),await fetch("/api/beta/push/unsubscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({endpoint:s})})}catch(e){console.error("[push] unsubscribe failed:",e)}}function Et(e){let t="=".repeat((4-e.length%4)%4),s=(e+t).replace(/-/g,"+").replace(/_/g,"/"),i=atob(s),r=new Uint8Array(i.length);for(let a=0;a<i.length;a++)r[a]=i.charCodeAt(a);return r}async function Ce(){try{let e=await navigator.serviceWorker?.ready;return e?await e.pushManager.getSubscription()!==null:!1}catch{return!1}}async function Me(e){let t=e.split(/\s+/),s=t[0].toLowerCase(),i=t.slice(1).join(" ").trim();switch(s){case"/new":return y(),c("Creating new session\u2026"),M({cwd:i||n.sessionCwd}),!0;case"/pwd":return c(`\u{1F4C1} ${n.sessionCwd||"unknown"}`),!0;case"/rename":{if(!n.sessionId)return c("err: No active session"),!0;if(!i)return c(`Current: ${n.sessionTitle||"(untitled)"}`),c("Usage: /rename <new title>"),!0;try{await qe(n.sessionId,i),c(`Renamed \u2192 ${i}`)}catch{c("err: Failed to rename session")}return!0}case"/sessions":return c("Removed. Use /switch to see all sessions."),!0;case"/exit":{if(!n.sessionId)return c("warn: No active session"),!0;let r=n.sessionId;try{let l=(await te()).find(d=>d.id!==r);if(n.busy&&G(),pe(r).catch(()=>{}),L=null,l){n.sessionSwitchGen++;let d=n.sessionSwitchGen;y(),n.sessionId=null;let[u]=await Promise.all([$(l.id),N(l.id)]);if(d!==n.sessionSwitchGen)return!0;C({type:"session_created",sessionId:u.id,cwd:u.cwd,title:u.title,configOptions:u.configOptions,busyKind:u.busyKind}),S(!0)}else y(),n.sessionId=null,c("Creating new session\u2026"),M({inheritFromSessionId:null})}catch{c("err: Failed to exit session")}return!0}case"/prune":{try{let l=(await(await fetch("/api/v1/sessions")).json()).filter(d=>d.id!==n.sessionId);if(l.length===0)return c("No other sessions to prune."),!0;for(let d of l)pe(d.id).catch(()=>{});L=null,c(`Pruned ${l.length} session(s).`)}catch{c("err: Failed to prune sessions")}return!0}case"/switch":{if(!i)return c("Usage: /switch <title or id prefix>"),!0;try{let a=await(await fetch("/api/v1/sessions")).json(),l=i.toLowerCase(),d=a.find(g=>g.id.startsWith(i)||g.title&&g.title.toLowerCase().includes(l));if(!d)return c(`err: No session matching "${i}"`),!0;n.sessionSwitchGen++;let u=n.sessionSwitchGen;y(),n.sessionId=null;let[f]=await Promise.all([$(d.id),N(d.id)]);if(u!==n.sessionSwitchGen)return!0;C({type:"session_created",sessionId:f.id,cwd:f.cwd,title:f.title,configOptions:f.configOptions,busyKind:f.busyKind}),S(!0)}catch{y(),n.sessionId=null,c("err: Failed to switch session")}return!0}case"/cancel":return n.busy?(G(),c("^C")):c("Nothing to cancel."),!0;case"/help":case"?":{let r=[];n.serverVersion&&r.push(`WebAgent ${n.serverVersion}`),n.agentName&&n.agentVersion&&r.push(`${n.agentName} ${n.agentVersion}`),r.length&&c(r.join(" \xB7 ")),c("? \u2014 Show help"),c("/help \u2014 Show help (alias)"),c("!<command> \u2014 Run bash command");for(let a of et){let l=a.args?`${a.cmd} ${a.args}`:a.cmd;c(`${l} \u2014 ${a.desc}`)}c("--- Shortcuts ---");for(let a of kt)c(`${a.key} \u2014 ${a.desc}`);c("--- Tips ---");for(let a of Ct)c(a.text);return!0}case"/model":case"/mode":case"/think":{let a={"/model":"model","/mode":"mode","/think":"reasoning_effort"}[s],l=x(a);if(!i){let v=l?.options.find(ee=>ee.value===l.currentValue)?.name||l?.currentValue||"unknown";return c(`${l?.name||a}: ${v}`),c(`Type ${s} + space to pick from list`),!0}if(!l)return c(`err: ${s.slice(1)} is not available.`),!0;let d=i.trim(),u=v=>v.toLowerCase().replace(/[\s_]+/g,"-"),f=u(d),g=l.options.find(v=>u(v.value)===f||u(v.name)===f);if(!g){let v=l.options.filter(ee=>u(ee.value).includes(f)||u(ee.name).includes(f));if(v.length===1)g=v[0];else if(v.length>1)return c(`err: Ambiguous "${i}". Type ${s} + space to see options.`),!0}return g?(l.currentValue=g.value,_(),O(),c(`${l.name} \u2192 ${g.name}`),await K(n.sessionId,a,g.value).catch(()=>{}),!0):(c(`err: Unknown "${i}". Type ${s} + space to see options.`),!0)}case"/notify":{if(typeof Notification>"u")return c("err: notifications not supported in this browser"),!0;let r=i.toLowerCase();if(r==="on"){if(Notification.permission==="denied")return c("notify: blocked \u2014 allow in browser site settings to enable"),!0;if(Notification.permission!=="granted"&&await Notification.requestPermission()!=="granted")return c("notify: blocked \u2014 allow in browser site settings to enable"),!0;let l=await Ce();return await bt(),c(l?"notify: already enabled":"notify: enabled"),!0}if(r==="off")return await Tt(),c("notify: disabled"),!0;let a=Notification.permission;return a==="denied"?c("notify: blocked \u2014 allow in browser site settings to enable"):a==="granted"&&await Ce()?c("notify: enabled"):c("notify: off \u2014 use /notify on to enable"),!0}default:return!1}}var et=[{cmd:"/cancel",args:"",desc:"Cancel current response"},{cmd:"/exit",args:"",desc:"Close current session"},{cmd:"/mode",args:"[name]",desc:"Pick or switch mode"},{cmd:"/model",args:"[name]",desc:"Pick or switch model"},{cmd:"/new",args:"[cwd]",desc:"New session"},{cmd:"/notify",args:"[on|off]",desc:"Toggle background notifications"},{cmd:"/prune",args:"",desc:"Delete all sessions except current"},{cmd:"/pwd",args:"",desc:"Show working directory"},{cmd:"/rename",args:"<new title>",desc:"Rename current session"},{cmd:"/switch",args:"<title|id>",desc:"Switch to session"},{cmd:"/think",args:"[level]",desc:"Pick or switch reasoning effort"}],kt=[{key:"Enter",desc:"Send message"},{key:"Shift+Enter",desc:"New line"},{key:"^C",desc:"Cancel current response"},{key:"^M",desc:"Cycle mode (Agent \u2192 Plan \u2192 Autopilot)"},{key:"^U",desc:"Upload image"}],Ct=[{text:"Tap \u276F prompt to cycle mode"}],b=-1,m=[],w="commands",Z=null,L=null,W=null,xe=!1;function Le(){let e=o.input.value;if(W!==null){if(e===W)return;W=null}let t=e.match(/^\/new /);if(t){let l=e.slice(t[0].length).toLowerCase();Mt(l);return}let s=e.match(/^\/switch /);if(s){let l=e.slice(s[0].length).toLowerCase();xt(l,"switch");return}let i=e.match(/^\/(model|mode|think) /);if(i){let d={model:"model",mode:"mode",think:"reasoning_effort"}[i[1]],u=e.slice(i[0].length).toLowerCase();Lt(d,u);return}let r=e.match(/^\/notify /);if(r){let l=e.slice(r[0].length).toLowerCase();Pt(l);return}if(!e.startsWith("/")||e.includes(" ")){h();return}w="commands";let a=e.toLowerCase();if(m=et.filter(l=>l.cmd.startsWith(a)),m.length===0){h();return}b=0,F(),o.slashMenu.classList.add("active")}async function xt(e,t="switch"){if(!L)try{L=await(await fetch("/api/v1/sessions")).json(),setTimeout(()=>{L=null},5e3)}catch{return}if(w=t,m=L.filter(i=>e?i.title&&i.title.toLowerCase().includes(e)||i.id.startsWith(e):!0),m.length===0){h();return}b=0,F(),o.slashMenu.classList.add("active")}async function Mt(e){if(!L)try{L=await(await fetch("/api/v1/sessions")).json(),setTimeout(()=>{L=null},5e3)}catch{return}w="new";let t=new Map;for(let i of L){let r=t.get(i.cwd);(!r||(i.last_active_at||i.created_at)>r.time)&&t.set(i.cwd,{cwd:i.cwd,time:i.last_active_at||i.created_at})}let s=[...t.values()].sort((i,r)=>r.time.localeCompare(i.time));if(e&&(s=s.filter(i=>i.cwd.toLowerCase().includes(e))),m=s,m.length===0){h();return}b=0,F(),o.slashMenu.classList.add("active")}function Lt(e,t){let s=x(e);if(!s){h();return}if(w="config",Z=e,m=s.options.filter(i=>t?i.value.toLowerCase().includes(t)||i.name.toLowerCase().includes(t):!0),m.length===0){h();return}b=0,F(),o.slashMenu.classList.add("active")}var $t=[{value:"on",name:"on",desc:"Enable background notifications"},{value:"off",name:"off",desc:"Disable background notifications"}];async function Pt(e){if(w="notify",m=$t.filter(i=>e?i.value.includes(e)||i.name.includes(e):!0),m.length===0){h();return}xe=await Ce();let t=xe?"on":"off",s=m.findIndex(i=>i.value===t);b=s>=0?s:0,F(),o.slashMenu.classList.add("active")}function F(){if(w==="new"){let t=(n.sessionCwd||"").toLowerCase();o.slashMenu.innerHTML=m.map((s,i)=>{let r=s.cwd.toLowerCase()===t;return`<div class="slash-item${i===b?" selected":""}" data-idx="${i}"><span class="slash-cmd"${r?' style="color:var(--green)"':""}>${p((r?"* ":" ")+s.cwd)}</span></div>`}).join("")}else if(w==="config"){let t=ie(Z)?.toLowerCase()||"";o.slashMenu.innerHTML=m.map((s,i)=>{let r=s.value.toLowerCase()===t;return`<div class="slash-item${i===b?" selected":""}" data-idx="${i}"><span class="slash-cmd"${r?' style="color:var(--green)"':""}>${p((r?"* ":" ")+s.name)}</span></div>`}).join("")}else if(w==="notify"){let t=xe?"on":"off";o.slashMenu.innerHTML=m.map((s,i)=>{let r=s.value===t;return`<div class="slash-item${i===b?" selected":""}" data-idx="${i}"><span class="slash-cmd"${r?' style="color:var(--green)"':""}>${p((r?"* ":" ")+s.name)}</span><span class="slash-desc">${p(s.desc)}</span></div>`}).join("")}else w==="switch"?o.slashMenu.innerHTML=m.map((t,s)=>{let i=t.id===n.sessionId,r=i?"* ":" ",a=t.title||t.id.slice(0,8)+"\u2026",l=We(t.last_active_at||t.created_at);return`<div class="slash-item${s===b?" selected":""}" data-idx="${s}"><span class="slash-cmd"${i?' style="color:var(--green)"':""}>${p(r+a)}</span><span class="slash-desc">${p(t.cwd)} (${p(l)})</span></div>`}).join(""):o.slashMenu.innerHTML=m.map((t,s)=>{let i=t.args?`${t.cmd} ${t.args}`:t.cmd;return`<div class="slash-item${s===b?" selected":""}" data-idx="${s}"><span class="slash-cmd">${p(i)}</span><span class="slash-desc">${p(t.desc)}</span></div>`}).join("");let e=o.slashMenu.querySelector(".selected");e&&e.scrollIntoView({block:"nearest"})}function h(){o.slashMenu.classList.remove("active"),b=-1,m=[],w="commands",W=o.input.value}function Ht(e){if(!(e<0||e>=m.length)){if(w==="commands"){let t=m[e];o.input.value=t.cmd+(t.args?" ":""),h(),o.input.focus(),["/new","/switch","/model","/mode","/think","/notify"].includes(t.cmd)&&(W=null,Le())}else if(w==="config"){let t=m[e],s={model:"/model",mode:"/mode",reasoning_effort:"/think"}[Z]||`/${Z}`;o.input.value=`${s} ${t.name}`,h(),o.input.focus()}else if(w==="notify"){let t=m[e];o.input.value=`/notify ${t.value}`,h(),o.input.focus()}else if(w==="new"){let t=m[e];o.input.value=`/new ${t.cwd}`,h(),o.input.focus()}else if(w==="switch"){let t=m[e];o.input.value=`/switch ${t.title||t.id}`,h(),o.input.focus()}}}async function _t(e){if(!(e<0||e>=m.length))if(w==="new"){let t=m[e];o.input.value="",h(),y(),c("Creating new session\u2026"),M({cwd:t.cwd})}else if(w==="config"){let t=m[e],s=Z,i=x(s);o.input.value="",h(),i&&(i.currentValue=t.value),_(),O(),c(`${i?.name||s} \u2192 ${t.name}`),await K(n.sessionId,s,t.value).catch(()=>{})}else if(w==="switch"){let t=m[e];o.input.value="",h(),y(),n.sessionId=null,c("Switching\u2026"),Promise.all([$(t.id),N(t.id)]).then(([s,i])=>{C({type:"session_created",sessionId:s.id,cwd:s.cwd,title:s.title,configOptions:s.configOptions,busyKind:s.busyKind}),i&&S(!0)}).catch(()=>{y(),n.sessionId=null,c("err: Failed to switch session")})}else if(w==="notify"){let t=m[e];o.input.value=`/notify ${t.value}`,h(),Me(o.input.value),o.input.value=""}else{let t=m[e];o.input.value=t.cmd+(t.args?" ":""),h(),o.input.focus(),["/new","/switch","/model","/mode","/think","/notify"].includes(t.cmd)&&(W=null,Le())}}function tt(e){return o.slashMenu.classList.contains("active")?e.key==="ArrowDown"?(b=(b+1)%m.length,F(),!0):e.key==="ArrowUp"?(b=(b-1+m.length)%m.length,F(),!0):e.key==="Tab"?(Ht(b),!0):!1:!1}o.slashMenu.addEventListener("mousedown",e=>{e.preventDefault();let t=e.target.closest(".slash-item");t&&_t(Number(t.dataset.idx))});o.input.addEventListener("input",()=>{Le(),o.inputArea.classList.toggle("bash-mode",o.input.value.startsWith("!"))});function nt(e){return new Promise(t=>{let s=new FileReader;s.onload=()=>{let i=s.result.split(",")[1];t({data:i,mimeType:e.type,previewUrl:s.result})},s.readAsDataURL(e)})}function st(e){n.pendingImages.push(e),ce(),o.input.focus()}function ce(){if(o.attachPreview.innerHTML="",n.pendingImages.length===0){o.attachPreview.classList.remove("active");return}o.attachPreview.classList.add("active"),n.pendingImages.forEach((e,t)=>{let s=document.createElement("span");s.className="attach-thumb",s.innerHTML=`<img src="${e.previewUrl}"><button class="remove">\xD7</button>`,s.querySelector(".remove").addEventListener("click",()=>{n.pendingImages.splice(t,1),ce()}),o.attachPreview.appendChild(s)})}o.attachBtn.onclick=()=>o.fileInput.click();o.fileInput.onchange=async()=>{for(let e of o.fileInput.files)e.type.startsWith("image/")&&st(await nt(e));o.fileInput.value=""};o.input.addEventListener("paste",async e=>{for(let t of e.clipboardData.items)t.type.startsWith("image/")&&(e.preventDefault(),st(await nt(t.getAsFile())))});var H=document.createElement("div");H.id="lightbox-overlay";var X=document.createElement("img");H.appendChild(X);document.body.appendChild(H);var de=1,Nt=.5,qt=5;function Bt(){return H.classList.contains("active")}function Ot(e){X.src=e,de=1,X.style.transform="",H.classList.add("active")}function it(){H.classList.remove("active"),X.src=""}document.getElementById("messages").addEventListener("click",e=>{let t=e.target;t.tagName==="IMG"&&t.classList.contains("user-image")&&Ot(t.src)});H.addEventListener("click",e=>{e.target===H&&it()});document.addEventListener("keydown",e=>{e.key==="Escape"&&Bt()&&it()});H.addEventListener("wheel",e=>{e.preventDefault();let t=e.deltaY>0?-.15:.15;de=Math.min(qt,Math.max(Nt,de+t)),X.style.transform=`scale(${de})`},{passive:!1});function $e(){return n.clientId!==null}n._onCancelTimeout=()=>c("warn: Agent not responding to cancel");function ot(){let e=o.input.value.trim();if(!e&&n.pendingImages.length===0)return;if((e.startsWith("/")||e==="?"||e.startsWith("? "))&&n.pendingImages.length===0){o.input.value="",o.input.style.height="auto",lt(),Me(e);return}if(e.startsWith("!")&&n.pendingImages.length===0){let i=e.slice(1).trim();if(!i)return;if(!n.sessionId){c("warn: Session not ready yet, please wait\u2026");return}if(!$e()){c("warn: Not connected, please retry");return}o.input.value="",o.input.style.height="auto",o.inputArea.classList.remove("bash-mode"),Q(i,!0),n.sentBashForSession=n.sessionId,Be(n.sessionId,i).catch(()=>{}),I(!0);return}if(n.busy)return;if(o.input.value="",o.input.style.height="auto",o.inputArea.classList.remove("bash-mode"),!n.sessionId){c("warn: Session not ready yet, please wait\u2026");return}if(!$e()){c("warn: Not connected, please retry");return}let t=R("user",e||"(image)");for(let i of n.pendingImages){let r=document.createElement("img");r.className="user-image",r.src=i.previewUrl,t.appendChild(r)}let s=n.pendingImages.slice();n.pendingImages.length=0,ce(),s.length>0?Promise.all(s.map(i=>fetch(`/api/v1/sessions/${n.sessionId}/images`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({data:i.data,mimeType:i.mimeType})}).then(r=>r.json()).then(r=>({data:i.data,mimeType:i.mimeType,path:r.url})))).then(i=>{if(!$e()){t.remove(),c("warn: Not connected, please retry"),I(!1);return}fe(n.sessionId,e||"What is in this image?",i.map(r=>({data:r.data,mimeType:r.mimeType,path:r.path}))).catch(()=>{})}):fe(n.sessionId,e).catch(()=>{}),n.turnEnded=!1,n.sentMessageForSession=n.sessionId,I(!0),je()}function rt(){G()&&c("^C")}function at(){let e=o.input.value.trim();return e.startsWith("/")||e.startsWith("!")||e==="?"||e.startsWith("? ")}function lt(){n.busy&&(at()?(o.sendBtn.textContent="\u21B5",o.sendBtn.title="Send (Enter)",o.sendBtn.classList.remove("cancel")):(o.sendBtn.textContent="^C",o.sendBtn.title="Cancel (Ctrl+C)",o.sendBtn.classList.add("cancel")))}o.sendBtn.onclick=()=>{n.busy&&!at()?rt():ot()};o.input.addEventListener("keydown",e=>{if(tt(e)){e.preventDefault();return}if(e.key==="Enter"&&!e.shiftKey){e.preventDefault(),h(),ot();return}if(e.key==="u"&&(e.ctrlKey||e.metaKey)&&!e.shiftKey){e.preventDefault(),o.fileInput.click();return}});document.addEventListener("keydown",e=>{if(e.key==="c"&&(e.ctrlKey||e.metaKey)&&!e.shiftKey&&n.busy&&!(window.getSelection()?.toString()||o.input.selectionStart!==o.input.selectionEnd)){e.preventDefault(),rt();return}e.key==="Escape"&&o.slashMenu.classList.contains("active")&&(e.preventDefault(),h(),o.input.focus())});function ct(){let e=x("mode");if(!e||!e.options.length)return;let t=e.options.findIndex(i=>i.value===e.currentValue),s=e.options[(t+1)%e.options.length];e.currentValue=s.value,K(n.sessionId,"mode",s.value).catch(()=>{}),c(`Mode \u2192 ${s.name}`),_()}document.addEventListener("keydown",e=>{e.key==="m"&&(e.ctrlKey||e.metaKey)&&!e.shiftKey&&(e.preventDefault(),ct())});o.prompt.addEventListener("click",ct);o.input.addEventListener("input",lt);o.input.addEventListener("input",()=>{o.input.style.height="auto",o.input.style.height=Math.min(o.input.scrollHeight,200)+"px"});async function At(e){try{let t=await navigator.serviceWorker?.ready;if(!t)return;let s=await t.pushManager.getSubscription();if(!s)return;await fetch("/api/beta/push/register-client",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientId:e,endpoint:s.endpoint})})}catch{}}function He(){B("connecting","connecting");let e=new EventSource("/api/v1/events/stream");n.eventSource=e,e.onmessage=async t=>{let s=JSON.parse(t.data);if(s.type==="connected"){n.clientId=s.clientId,V(s.clientId,!document.hidden,n.sessionId??void 0).catch(()=>{}),At(s.clientId);return}C(s)},e.onerror=()=>{e.close(),Dt(),setTimeout(He,3e3)},Rt()}async function Rt(){B("connecting","session loading");let e=n.sessionSwitchGen,t=De();if(t&&t===n.sessionId&&n.lastEventSeq>0){if(await Pe(t,!0,e),e!==n.sessionSwitchGen)return;Ze(),S(!1);return}if(t){if(y(),await Pe(t,!1,e),e!==n.sessionSwitchGen)return;S(!0);return}try{let s=await te();if(e!==n.sessionSwitchGen)return;if(s.length>0){if(y(),await Pe(s[0].id,!1,e),e!==n.sessionSwitchGen)return;S(!0);return}}catch{}e===n.sessionSwitchGen&&M()}async function Pe(e,t,s){if(t){try{let i=await $(e);if(s!==n.sessionSwitchGen)return;C({type:"session_created",sessionId:i.id,cwd:i.cwd,title:i.title,configOptions:i.configOptions,busyKind:i.busyKind})}catch{if(s!==n.sessionSwitchGen)return;y(),c("warn: Previous session expired, created new one."),M();return}if(s!==n.sessionSwitchGen)return;await Te(e)}else{n.sessionId=null;let i=N(e),r;try{let[a,l]=await Promise.all([$(e),i]);if(s!==n.sessionSwitchGen)return;r=a,l||c("warn: Failed to load history.")}catch{if(s!==n.sessionSwitchGen)return;y(),c("warn: Previous session expired, created new one."),M();return}C({type:"session_created",sessionId:r.id,cwd:r.cwd,title:r.title,configOptions:r.configOptions,busyKind:r.busyKind})}}function Dt(){B("disconnected","disconnected"),n.eventSource=null,n.clientId=null,k(),P(),n.currentBashEl&&Y(n.currentBashEl,null,"disconnected"),n.pendingToolCallIds.clear(),n.pendingPermissionRequestIds.clear(),n.pendingPromptDone=!1,n.turnEnded=!1,J(),I(!1)}document.addEventListener("visibilitychange",()=>{n.clientId&&V(n.clientId,!document.hidden,n.sessionId??void 0).catch(()=>{}),!document.hidden&&n.sessionId&&n.lastEventSeq>0&&!n.replayInProgress&&Te(n.sessionId).then(()=>S(!1))});He();fetch("/api/v1/version").then(e=>e.json()).then(e=>{typeof e.server=="string"&&(n.serverVersion=e.server);let t=e.agent;t&&(n.agentName=t.name??null,n.agentVersion=t.version??null)}).catch(()=>{});"serviceWorker"in navigator&&(navigator.serviceWorker.register("/sw.js"),navigator.serviceWorker.addEventListener("message",e=>{if(e.data?.type==="navigate"&&e.data.sessionId){let t=e.data.sessionId;if(n.sessionId===t)return;n.sessionSwitchGen++;let s=n.sessionSwitchGen;history.replaceState(null,"",`#${t}`),y(),n.sessionId=null,c("Switching\u2026"),Promise.all([$(t),N(t)]).then(([i,r])=>{s===n.sessionSwitchGen&&(C({type:"session_created",sessionId:i.id,cwd:i.cwd,title:i.title,configOptions:i.configOptions,busyKind:i.busyKind}),r&&S(!0))}).catch(()=>{y(),n.sessionId=null,c("err: Failed to switch session")})}}));
10
+ `);if(r)if(t.dataset.kind==="task_complete"){let a=document.createElement("div");a.className="tc-summary",a.textContent=r,t.appendChild(a)}else{let a=document.createElement("details");a.innerHTML=`<summary>output</summary><div class="tc-content">${p(r)}</div>`,t.appendChild(a)}}}ae(),S();break}case"plan":{k(),P();let t=document.createElement("div");t.className="plan",t.innerHTML='<div class="plan-title">\u2015 plan</div>'+e.entries.map(s=>`<div class="plan-entry">${Ie[s.status]||"?"} ${p(s.content)}</div>`).join(""),E(t);break}case"permission_request":{if(n.turnEnded||document.querySelector(`.permission[data-request-id="${e.requestId}"]`))break;n.pendingPermissionRequestIds.add(e.requestId),I(!0),k();let t=document.createElement("div");t.className="permission",t.dataset.requestId=e.requestId,t.dataset.title=e.title||"",t.innerHTML=`<span class="title">\u26BF ${p(e.title)}</span> `,e.options.forEach(s=>{let i=document.createElement("button"),r=(s.kind||"").includes("allow");i.className=r?"allow":"deny",i.textContent=s.name,i.onclick=()=>{let a=(s.kind||"").includes("reject")||(s.kind||"").includes("deny");a?se(n.sessionId,e.requestId).catch(()=>{}):ne(n.sessionId,e.requestId,s.optionId).catch(()=>{}),n.pendingPermissionRequestIds.delete(e.requestId),n.unconfirmedPermissions.set(e.requestId,{sessionId:n.sessionId,optionId:s.optionId,optionName:s.name,denied:a}),t.innerHTML=`<span style="opacity:0.5">\u26BF ${p(e.title)} \u2014 ${p(s.name)}</span>`,ae()},t.appendChild(i)}),E(t);break}case"permission_resolved":{n.pendingPermissionRequestIds.delete(e.requestId),n.unconfirmedPermissions.delete(e.requestId);let t=document.querySelector(`.permission[data-request-id="${e.requestId}"]`);if(e.sessionId===n.sessionId&&t){let s=t.dataset.title?`\u26BF ${t.dataset.title}`:"\u26BF",i=e.optionName||(e.denied?"denied":"allowed");t.innerHTML=`<span style="opacity:0.5">${p(s)} \u2014 ${p(i)}</span>`}ae();break}case"bash_command":{if(n.sentBashForSession===e.sessionId){n.sentBashForSession=null;break}e.sessionId===n.sessionId&&(Q(e.command,!0),I(!0));break}case"bash_output":{if(e.sessionId!==n.sessionId)break;if(n.currentBashEl){let t=n.currentBashEl.querySelector(".bash-output");if(e.stream==="stderr"){let s=document.createElement("span");s.className="stderr",s.textContent=e.text,t.appendChild(s)}else t.appendChild(document.createTextNode(e.text));t.classList.add("has-content"),t.scrollTop=t.scrollHeight,S()}break}case"bash_done":{if(e.sessionId!==n.sessionId)break;Y(n.currentBashEl,e.code,e.signal),e.error&&c(`err: ${e.error}`),I(!1);break}case"prompt_done":{if(J(),e.stopReason==="cancelled"&&n.newTurnStarted){n.newTurnStarted=!1,k(),P();break}n.newTurnStarted=!1,e.stopReason==="cancelled"?yt():wt(),n.turnEnded=!0,n.pendingPromptDone=!0,ae();break}case"session_deleted":e.sessionId===n.sessionId&&(c("warn: This session has been deleted."),o.input.disabled=!0,o.sendBtn.disabled=!0,o.input.placeholder="Session deleted");break;case"session_expired":y(),c("warn: Previous session expired, created new one."),M();break;case"config_set":{Oe(e.configId,e.value);let t=x(e.configId),s=t?.name||e.configId,i=t?.options.find(r=>r.value===e.value)?.name||e.value;c(`ok: ${s}: ${i}`),e.configId==="mode"&&_(),O();break}case"config_option_update":e.configOptions?.length&&me(e.configOptions);break;case"session_title_updated":e.sessionId===n.sessionId&&(n.sessionTitle=e.title,oe(n.sessionId,n.sessionTitle));break;case"error":n.awaitingNewSession=!1,n.pendingToolCallIds.clear(),n.pendingPermissionRequestIds.clear(),n.pendingPromptDone=!1,D(),k(),P(),c(`err: ${e.message}`),I(!1);break}}async function bt(){try{let e=await navigator.serviceWorker?.ready;if(!e)return;let t=await fetch("/api/beta/push/vapid-key");if(!t.ok)return;let{publicKey:s}=await t.json(),r=(await e.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:Et(s)})).toJSON();await fetch("/api/beta/push/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({endpoint:r.endpoint,keys:r.keys,clientId:n.clientId})})}catch(e){console.error("[push] subscribe failed:",e)}}async function Tt(){try{let e=await navigator.serviceWorker?.ready;if(!e)return;let t=await e.pushManager.getSubscription();if(!t)return;let s=t.endpoint;await t.unsubscribe(),await fetch("/api/beta/push/unsubscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({endpoint:s})})}catch(e){console.error("[push] unsubscribe failed:",e)}}function Et(e){let t="=".repeat((4-e.length%4)%4),s=(e+t).replace(/-/g,"+").replace(/_/g,"/"),i=atob(s),r=new Uint8Array(i.length);for(let a=0;a<i.length;a++)r[a]=i.charCodeAt(a);return r}async function Ce(){try{let e=await navigator.serviceWorker?.ready;return e?await e.pushManager.getSubscription()!==null:!1}catch{return!1}}async function Me(e){let t=e.split(/\s+/),s=t[0].toLowerCase(),i=t.slice(1).join(" ").trim();switch(s){case"/new":return y(),c("Creating new session\u2026"),M({cwd:i||n.sessionCwd}),!0;case"/pwd":return c(`\u{1F4C1} ${n.sessionCwd||"unknown"}`),!0;case"/rename":{if(!n.sessionId)return c("err: No active session"),!0;if(!i)return c(`Current: ${n.sessionTitle||"(untitled)"}`),c("Usage: /rename <new title>"),!0;try{await qe(n.sessionId,i),c(`Renamed \u2192 ${i}`)}catch{c("err: Failed to rename session")}return!0}case"/sessions":return c("Removed. Use /switch to see all sessions."),!0;case"/exit":{if(!n.sessionId)return c("warn: No active session"),!0;let r=n.sessionId;try{let l=(await te()).find(d=>d.id!==r);if(n.busy&&G(),pe(r).catch(()=>{}),L=null,l){n.sessionSwitchGen++;let d=n.sessionSwitchGen;y(),n.sessionId=null;let[u]=await Promise.all([$(l.id),N(l.id)]);if(d!==n.sessionSwitchGen)return!0;C({type:"session_created",sessionId:u.id,cwd:u.cwd,title:u.title,configOptions:u.configOptions,busyKind:u.busyKind}),S(!0)}else y(),n.sessionId=null,c("Creating new session\u2026"),M({inheritFromSessionId:null})}catch{c("err: Failed to exit session")}return!0}case"/prune":{try{let l=(await(await fetch("/api/v1/sessions")).json()).filter(d=>d.id!==n.sessionId);if(l.length===0)return c("No other sessions to prune."),!0;await Promise.all(l.map(d=>pe(d.id).catch(()=>{}))),L=null,c(`Pruned ${l.length} session(s).`)}catch{c("err: Failed to prune sessions")}return!0}case"/switch":{if(!i)return c("Usage: /switch <title or id prefix>"),!0;try{let a=await(await fetch("/api/v1/sessions")).json(),l=i.toLowerCase(),d=a.find(g=>g.id.startsWith(i)||g.title&&g.title.toLowerCase().includes(l));if(!d)return c(`err: No session matching "${i}"`),!0;n.sessionSwitchGen++;let u=n.sessionSwitchGen;y(),n.sessionId=null;let[f]=await Promise.all([$(d.id),N(d.id)]);if(u!==n.sessionSwitchGen)return!0;C({type:"session_created",sessionId:f.id,cwd:f.cwd,title:f.title,configOptions:f.configOptions,busyKind:f.busyKind}),S(!0)}catch{y(),n.sessionId=null,c("err: Failed to switch session")}return!0}case"/cancel":return n.busy?(G(),c("^C")):c("Nothing to cancel."),!0;case"/help":case"?":{let r=[];n.serverVersion&&r.push(`WebAgent ${n.serverVersion}`),n.agentName&&n.agentVersion&&r.push(`${n.agentName} ${n.agentVersion}`),r.length&&c(r.join(" \xB7 ")),c("? \u2014 Show help"),c("/help \u2014 Show help (alias)"),c("!<command> \u2014 Run bash command");for(let a of et){let l=a.args?`${a.cmd} ${a.args}`:a.cmd;c(`${l} \u2014 ${a.desc}`)}c("--- Shortcuts ---");for(let a of kt)c(`${a.key} \u2014 ${a.desc}`);c("--- Tips ---");for(let a of Ct)c(a.text);return!0}case"/model":case"/mode":case"/think":{let a={"/model":"model","/mode":"mode","/think":"reasoning_effort"}[s],l=x(a);if(!i){let v=l?.options.find(ee=>ee.value===l.currentValue)?.name||l?.currentValue||"unknown";return c(`${l?.name||a}: ${v}`),c(`Type ${s} + space to pick from list`),!0}if(!l)return c(`err: ${s.slice(1)} is not available.`),!0;let d=i.trim(),u=v=>v.toLowerCase().replace(/[\s_]+/g,"-"),f=u(d),g=l.options.find(v=>u(v.value)===f||u(v.name)===f);if(!g){let v=l.options.filter(ee=>u(ee.value).includes(f)||u(ee.name).includes(f));if(v.length===1)g=v[0];else if(v.length>1)return c(`err: Ambiguous "${i}". Type ${s} + space to see options.`),!0}return g?(l.currentValue=g.value,_(),O(),c(`${l.name} \u2192 ${g.name}`),await K(n.sessionId,a,g.value).catch(()=>{}),!0):(c(`err: Unknown "${i}". Type ${s} + space to see options.`),!0)}case"/notify":{if(typeof Notification>"u")return c("err: notifications not supported in this browser"),!0;let r=i.toLowerCase();if(r==="on"){if(Notification.permission==="denied")return c("notify: blocked \u2014 allow in browser site settings to enable"),!0;if(Notification.permission!=="granted"&&await Notification.requestPermission()!=="granted")return c("notify: blocked \u2014 allow in browser site settings to enable"),!0;let l=await Ce();return await bt(),c(l?"notify: already enabled":"notify: enabled"),!0}if(r==="off")return await Tt(),c("notify: disabled"),!0;let a=Notification.permission;return a==="denied"?c("notify: blocked \u2014 allow in browser site settings to enable"):a==="granted"&&await Ce()?c("notify: enabled"):c("notify: off \u2014 use /notify on to enable"),!0}default:return!1}}var et=[{cmd:"/cancel",args:"",desc:"Cancel current response"},{cmd:"/exit",args:"",desc:"Close current session"},{cmd:"/mode",args:"[name]",desc:"Pick or switch mode"},{cmd:"/model",args:"[name]",desc:"Pick or switch model"},{cmd:"/new",args:"[cwd]",desc:"New session"},{cmd:"/notify",args:"[on|off]",desc:"Toggle background notifications"},{cmd:"/prune",args:"",desc:"Delete all sessions except current"},{cmd:"/pwd",args:"",desc:"Show working directory"},{cmd:"/rename",args:"<new title>",desc:"Rename current session"},{cmd:"/switch",args:"<title|id>",desc:"Switch to session"},{cmd:"/think",args:"[level]",desc:"Pick or switch reasoning effort"}],kt=[{key:"Enter",desc:"Send message"},{key:"Shift+Enter",desc:"New line"},{key:"^C",desc:"Cancel current response"},{key:"^M",desc:"Cycle mode (Agent \u2192 Plan \u2192 Autopilot)"},{key:"^U",desc:"Upload image"}],Ct=[{text:"Tap \u276F prompt to cycle mode"}],b=-1,m=[],w="commands",Z=null,L=null,W=null,xe=!1;function Le(){let e=o.input.value;if(W!==null){if(e===W)return;W=null}let t=e.match(/^\/new /);if(t){let l=e.slice(t[0].length).toLowerCase();Mt(l);return}let s=e.match(/^\/switch /);if(s){let l=e.slice(s[0].length).toLowerCase();xt(l,"switch");return}let i=e.match(/^\/(model|mode|think) /);if(i){let d={model:"model",mode:"mode",think:"reasoning_effort"}[i[1]],u=e.slice(i[0].length).toLowerCase();Lt(d,u);return}let r=e.match(/^\/notify /);if(r){let l=e.slice(r[0].length).toLowerCase();Pt(l);return}if(!e.startsWith("/")||e.includes(" ")){h();return}w="commands";let a=e.toLowerCase();if(m=et.filter(l=>l.cmd.startsWith(a)),m.length===0){h();return}b=0,F(),o.slashMenu.classList.add("active")}async function xt(e,t="switch"){if(!L)try{L=await(await fetch("/api/v1/sessions")).json(),setTimeout(()=>{L=null},5e3)}catch{return}if(w=t,m=L.filter(i=>e?i.title&&i.title.toLowerCase().includes(e)||i.id.startsWith(e):!0),m.length===0){h();return}b=0,F(),o.slashMenu.classList.add("active")}async function Mt(e){if(!L)try{L=await(await fetch("/api/v1/sessions")).json(),setTimeout(()=>{L=null},5e3)}catch{return}w="new";let t=new Map;for(let i of L){let r=t.get(i.cwd);(!r||(i.last_active_at||i.created_at)>r.time)&&t.set(i.cwd,{cwd:i.cwd,time:i.last_active_at||i.created_at})}let s=[...t.values()].sort((i,r)=>r.time.localeCompare(i.time));if(e&&(s=s.filter(i=>i.cwd.toLowerCase().includes(e))),m=s,m.length===0){h();return}b=0,F(),o.slashMenu.classList.add("active")}function Lt(e,t){let s=x(e);if(!s){h();return}if(w="config",Z=e,m=s.options.filter(i=>t?i.value.toLowerCase().includes(t)||i.name.toLowerCase().includes(t):!0),m.length===0){h();return}b=0,F(),o.slashMenu.classList.add("active")}var $t=[{value:"on",name:"on",desc:"Enable background notifications"},{value:"off",name:"off",desc:"Disable background notifications"}];async function Pt(e){if(w="notify",m=$t.filter(i=>e?i.value.includes(e)||i.name.includes(e):!0),m.length===0){h();return}xe=await Ce();let t=xe?"on":"off",s=m.findIndex(i=>i.value===t);b=s>=0?s:0,F(),o.slashMenu.classList.add("active")}function F(){if(w==="new"){let t=(n.sessionCwd||"").toLowerCase();o.slashMenu.innerHTML=m.map((s,i)=>{let r=s.cwd.toLowerCase()===t;return`<div class="slash-item${i===b?" selected":""}" data-idx="${i}"><span class="slash-cmd"${r?' style="color:var(--green)"':""}>${p((r?"* ":" ")+s.cwd)}</span></div>`}).join("")}else if(w==="config"){let t=ie(Z)?.toLowerCase()||"";o.slashMenu.innerHTML=m.map((s,i)=>{let r=s.value.toLowerCase()===t;return`<div class="slash-item${i===b?" selected":""}" data-idx="${i}"><span class="slash-cmd"${r?' style="color:var(--green)"':""}>${p((r?"* ":" ")+s.name)}</span></div>`}).join("")}else if(w==="notify"){let t=xe?"on":"off";o.slashMenu.innerHTML=m.map((s,i)=>{let r=s.value===t;return`<div class="slash-item${i===b?" selected":""}" data-idx="${i}"><span class="slash-cmd"${r?' style="color:var(--green)"':""}>${p((r?"* ":" ")+s.name)}</span><span class="slash-desc">${p(s.desc)}</span></div>`}).join("")}else w==="switch"?o.slashMenu.innerHTML=m.map((t,s)=>{let i=t.id===n.sessionId,r=i?"* ":" ",a=t.title||t.id.slice(0,8)+"\u2026",l=We(t.last_active_at||t.created_at);return`<div class="slash-item${s===b?" selected":""}" data-idx="${s}"><span class="slash-cmd"${i?' style="color:var(--green)"':""}>${p(r+a)}</span><span class="slash-desc">${p(t.cwd)} (${p(l)})</span></div>`}).join(""):o.slashMenu.innerHTML=m.map((t,s)=>{let i=t.args?`${t.cmd} ${t.args}`:t.cmd;return`<div class="slash-item${s===b?" selected":""}" data-idx="${s}"><span class="slash-cmd">${p(i)}</span><span class="slash-desc">${p(t.desc)}</span></div>`}).join("");let e=o.slashMenu.querySelector(".selected");e&&e.scrollIntoView({block:"nearest"})}function h(){o.slashMenu.classList.remove("active"),b=-1,m=[],w="commands",W=o.input.value}function Ht(e){if(!(e<0||e>=m.length)){if(w==="commands"){let t=m[e];o.input.value=t.cmd+(t.args?" ":""),h(),o.input.focus(),["/new","/switch","/model","/mode","/think","/notify"].includes(t.cmd)&&(W=null,Le())}else if(w==="config"){let t=m[e],s={model:"/model",mode:"/mode",reasoning_effort:"/think"}[Z]||`/${Z}`;o.input.value=`${s} ${t.name}`,h(),o.input.focus()}else if(w==="notify"){let t=m[e];o.input.value=`/notify ${t.value}`,h(),o.input.focus()}else if(w==="new"){let t=m[e];o.input.value=`/new ${t.cwd}`,h(),o.input.focus()}else if(w==="switch"){let t=m[e];o.input.value=`/switch ${t.title||t.id}`,h(),o.input.focus()}}}async function _t(e){if(!(e<0||e>=m.length))if(w==="new"){let t=m[e];o.input.value="",h(),y(),c("Creating new session\u2026"),M({cwd:t.cwd})}else if(w==="config"){let t=m[e],s=Z,i=x(s);o.input.value="",h(),i&&(i.currentValue=t.value),_(),O(),c(`${i?.name||s} \u2192 ${t.name}`),await K(n.sessionId,s,t.value).catch(()=>{})}else if(w==="switch"){let t=m[e];o.input.value="",h(),y(),n.sessionId=null,c("Switching\u2026"),Promise.all([$(t.id),N(t.id)]).then(([s,i])=>{C({type:"session_created",sessionId:s.id,cwd:s.cwd,title:s.title,configOptions:s.configOptions,busyKind:s.busyKind}),i&&S(!0)}).catch(()=>{y(),n.sessionId=null,c("err: Failed to switch session")})}else if(w==="notify"){let t=m[e];o.input.value=`/notify ${t.value}`,h(),Me(o.input.value),o.input.value=""}else{let t=m[e];o.input.value=t.cmd+(t.args?" ":""),h(),o.input.focus(),["/new","/switch","/model","/mode","/think","/notify"].includes(t.cmd)&&(W=null,Le())}}function tt(e){return o.slashMenu.classList.contains("active")?e.key==="ArrowDown"?(b=(b+1)%m.length,F(),!0):e.key==="ArrowUp"?(b=(b-1+m.length)%m.length,F(),!0):e.key==="Tab"?(Ht(b),!0):!1:!1}o.slashMenu.addEventListener("mousedown",e=>{e.preventDefault();let t=e.target.closest(".slash-item");t&&_t(Number(t.dataset.idx))});o.input.addEventListener("input",()=>{Le(),o.inputArea.classList.toggle("bash-mode",o.input.value.startsWith("!"))});function nt(e){return new Promise(t=>{let s=new FileReader;s.onload=()=>{let i=s.result.split(",")[1];t({data:i,mimeType:e.type,previewUrl:s.result})},s.readAsDataURL(e)})}function st(e){n.pendingImages.push(e),ce(),o.input.focus()}function ce(){if(o.attachPreview.innerHTML="",n.pendingImages.length===0){o.attachPreview.classList.remove("active");return}o.attachPreview.classList.add("active"),n.pendingImages.forEach((e,t)=>{let s=document.createElement("span");s.className="attach-thumb",s.innerHTML=`<img src="${e.previewUrl}"><button class="remove">\xD7</button>`,s.querySelector(".remove").addEventListener("click",()=>{n.pendingImages.splice(t,1),ce()}),o.attachPreview.appendChild(s)})}o.attachBtn.onclick=()=>o.fileInput.click();o.fileInput.onchange=async()=>{for(let e of o.fileInput.files)e.type.startsWith("image/")&&st(await nt(e));o.fileInput.value=""};o.input.addEventListener("paste",async e=>{for(let t of e.clipboardData.items)t.type.startsWith("image/")&&(e.preventDefault(),st(await nt(t.getAsFile())))});var H=document.createElement("div");H.id="lightbox-overlay";var X=document.createElement("img");H.appendChild(X);document.body.appendChild(H);var de=1,Nt=.5,qt=5;function Bt(){return H.classList.contains("active")}function Ot(e){X.src=e,de=1,X.style.transform="",H.classList.add("active")}function it(){H.classList.remove("active"),X.src=""}document.getElementById("messages").addEventListener("click",e=>{let t=e.target;t.tagName==="IMG"&&t.classList.contains("user-image")&&Ot(t.src)});H.addEventListener("click",e=>{e.target===H&&it()});document.addEventListener("keydown",e=>{e.key==="Escape"&&Bt()&&it()});H.addEventListener("wheel",e=>{e.preventDefault();let t=e.deltaY>0?-.15:.15;de=Math.min(qt,Math.max(Nt,de+t)),X.style.transform=`scale(${de})`},{passive:!1});function $e(){return n.clientId!==null}n._onCancelTimeout=()=>c("warn: Agent not responding to cancel");function ot(){let e=o.input.value.trim();if(!e&&n.pendingImages.length===0)return;if((e.startsWith("/")||e==="?"||e.startsWith("? "))&&n.pendingImages.length===0){o.input.value="",o.input.style.height="auto",lt(),Me(e);return}if(e.startsWith("!")&&n.pendingImages.length===0){let i=e.slice(1).trim();if(!i)return;if(!n.sessionId){c("warn: Session not ready yet, please wait\u2026");return}if(!$e()){c("warn: Not connected, please retry");return}o.input.value="",o.input.style.height="auto",o.inputArea.classList.remove("bash-mode"),Q(i,!0),n.sentBashForSession=n.sessionId,Be(n.sessionId,i).catch(()=>{}),I(!0);return}if(n.busy)return;if(o.input.value="",o.input.style.height="auto",o.inputArea.classList.remove("bash-mode"),!n.sessionId){c("warn: Session not ready yet, please wait\u2026");return}if(!$e()){c("warn: Not connected, please retry");return}let t=R("user",e||"(image)");for(let i of n.pendingImages){let r=document.createElement("img");r.className="user-image",r.src=i.previewUrl,t.appendChild(r)}let s=n.pendingImages.slice();n.pendingImages.length=0,ce(),s.length>0?Promise.all(s.map(i=>fetch(`/api/v1/sessions/${n.sessionId}/images`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({data:i.data,mimeType:i.mimeType})}).then(r=>r.json()).then(r=>({data:i.data,mimeType:i.mimeType,path:r.url})))).then(i=>{if(!$e()){t.remove(),c("warn: Not connected, please retry"),I(!1);return}fe(n.sessionId,e||"What is in this image?",i.map(r=>({data:r.data,mimeType:r.mimeType,path:r.path}))).catch(()=>{})}):fe(n.sessionId,e).catch(()=>{}),n.turnEnded=!1,n.sentMessageForSession=n.sessionId,I(!0),je()}function rt(){G()&&c("^C")}function at(){let e=o.input.value.trim();return e.startsWith("/")||e.startsWith("!")||e==="?"||e.startsWith("? ")}function lt(){n.busy&&(at()?(o.sendBtn.textContent="\u21B5",o.sendBtn.title="Send (Enter)",o.sendBtn.classList.remove("cancel")):(o.sendBtn.textContent="^C",o.sendBtn.title="Cancel (Ctrl+C)",o.sendBtn.classList.add("cancel")))}o.sendBtn.onclick=()=>{n.busy&&!at()?rt():ot()};o.input.addEventListener("keydown",e=>{if(tt(e)){e.preventDefault();return}if(e.key==="Enter"&&!e.shiftKey){e.preventDefault(),h(),ot();return}if(e.key==="u"&&(e.ctrlKey||e.metaKey)&&!e.shiftKey){e.preventDefault(),o.fileInput.click();return}});document.addEventListener("keydown",e=>{if(e.key==="c"&&(e.ctrlKey||e.metaKey)&&!e.shiftKey&&n.busy&&!(window.getSelection()?.toString()||o.input.selectionStart!==o.input.selectionEnd)){e.preventDefault(),rt();return}e.key==="Escape"&&o.slashMenu.classList.contains("active")&&(e.preventDefault(),h(),o.input.focus())});function ct(){let e=x("mode");if(!e||!e.options.length)return;let t=e.options.findIndex(i=>i.value===e.currentValue),s=e.options[(t+1)%e.options.length];e.currentValue=s.value,K(n.sessionId,"mode",s.value).catch(()=>{}),c(`Mode \u2192 ${s.name}`),_()}document.addEventListener("keydown",e=>{e.key==="m"&&(e.ctrlKey||e.metaKey)&&!e.shiftKey&&(e.preventDefault(),ct())});o.prompt.addEventListener("click",ct);o.input.addEventListener("input",lt);o.input.addEventListener("input",()=>{o.input.style.height="auto",o.input.style.height=Math.min(o.input.scrollHeight,200)+"px"});async function At(e){try{let t=await navigator.serviceWorker?.ready;if(!t)return;let s=await t.pushManager.getSubscription();if(!s)return;await fetch("/api/beta/push/register-client",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientId:e,endpoint:s.endpoint})})}catch{}}function He(){B("connecting","connecting");let e=new EventSource("/api/v1/events/stream");n.eventSource=e,e.onmessage=async t=>{let s=JSON.parse(t.data);if(s.type==="connected"){n.clientId=s.clientId,V(s.clientId,!document.hidden,n.sessionId??void 0).catch(()=>{}),At(s.clientId);return}C(s)},e.onerror=()=>{e.close(),Dt(),setTimeout(He,3e3)},Rt()}async function Rt(){B("connecting","session loading");let e=n.sessionSwitchGen,t=De();if(t&&t===n.sessionId&&n.lastEventSeq>0){if(await Pe(t,!0,e),e!==n.sessionSwitchGen)return;Ze(),S(!1);return}if(t){if(y(),await Pe(t,!1,e),e!==n.sessionSwitchGen)return;S(!0);return}try{let s=await te();if(e!==n.sessionSwitchGen)return;if(s.length>0){if(y(),await Pe(s[0].id,!1,e),e!==n.sessionSwitchGen)return;S(!0);return}}catch{}e===n.sessionSwitchGen&&M()}async function Pe(e,t,s){if(t){try{let i=await $(e);if(s!==n.sessionSwitchGen)return;C({type:"session_created",sessionId:i.id,cwd:i.cwd,title:i.title,configOptions:i.configOptions,busyKind:i.busyKind})}catch{if(s!==n.sessionSwitchGen)return;y(),c("warn: Previous session expired, created new one."),M();return}if(s!==n.sessionSwitchGen)return;await Te(e)}else{n.sessionId=null;let i=N(e),r;try{let[a,l]=await Promise.all([$(e),i]);if(s!==n.sessionSwitchGen)return;r=a,l||c("warn: Failed to load history.")}catch{if(s!==n.sessionSwitchGen)return;y(),c("warn: Previous session expired, created new one."),M();return}C({type:"session_created",sessionId:r.id,cwd:r.cwd,title:r.title,configOptions:r.configOptions,busyKind:r.busyKind})}}function Dt(){B("disconnected","disconnected"),n.eventSource=null,n.clientId=null,k(),P(),n.currentBashEl&&Y(n.currentBashEl,null,"disconnected"),n.pendingToolCallIds.clear(),n.pendingPermissionRequestIds.clear(),n.pendingPromptDone=!1,n.turnEnded=!1,J(),I(!1)}document.addEventListener("visibilitychange",()=>{n.clientId&&V(n.clientId,!document.hidden,n.sessionId??void 0).catch(()=>{}),!document.hidden&&n.sessionId&&n.lastEventSeq>0&&!n.replayInProgress&&Te(n.sessionId).then(()=>S(!1))});He();fetch("/api/v1/version").then(e=>e.json()).then(e=>{typeof e.server=="string"&&(n.serverVersion=e.server);let t=e.agent;t&&(n.agentName=t.name??null,n.agentVersion=t.version??null)}).catch(()=>{});"serviceWorker"in navigator&&(navigator.serviceWorker.register("/sw.js"),navigator.serviceWorker.addEventListener("message",e=>{if(e.data?.type==="navigate"&&e.data.sessionId){let t=e.data.sessionId;if(n.sessionId===t)return;n.sessionSwitchGen++;let s=n.sessionSwitchGen;history.replaceState(null,"",`#${t}`),y(),n.sessionId=null,c("Switching\u2026"),Promise.all([$(t),N(t)]).then(([i,r])=>{s===n.sessionSwitchGen&&(C({type:"session_created",sessionId:i.id,cwd:i.cwd,title:i.title,configOptions:i.configOptions,busyKind:i.busyKind}),r&&S(!0))}).catch(()=>{y(),n.sessionId=null,c("err: Failed to switch session")})}}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lelouchhe/webagent",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "A terminal-style web UI for ACP-compatible agents",
5
5
  "type": "module",
6
6
  "license": "MIT",