tmux-weblink 2.2.8 → 2.2.9

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.
@@ -1,40 +1,40 @@
1
- var dn=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function Ye(e){return e.replace(/\x1b\[\?1049[hl]/g,"")}function de(e){return e.replace(dn,"")}var Me;function un(){return Me||(document.querySelector("link[data-tmux-web-xterm-css]")?Me=Promise.resolve():(Me=new Promise(e=>{let t=document.createElement("link");t.rel="stylesheet",t.href="/assets/xterm.css",t.setAttribute("data-tmux-web-xterm-css",""),t.addEventListener("load",()=>e(),{once:!0}),t.addEventListener("error",()=>e(),{once:!0}),document.head.appendChild(t)}),Me))}var pn=class Pt{terminal;fitAddon;container;constructor(t,n,s){this.container=t,this.terminal=n,this.fitAddon=s,this.terminal.loadAddon(this.fitAddon),this.terminal.open(t)}static async create(t,n,s){let[{Terminal:l},{FitAddon:r}]=await Promise.all([import("./xterm-BXEES47M.js"),import("./addon-fit-D5N335P2.js"),un()]),c=new l({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:n,convertEol:!1,smoothScrollDuration:120,theme:s});return new Pt(t,c,new r)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(t){return new Promise(n=>this.terminal.write(t,n))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(t,n=!1){this.terminal.scrollToLine(Math.max(0,t),n)}scrollLines(t){let n=this.terminal.buffer?.active;this.terminal.scrollLines(t)}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){let t=mn(this.container);if(t.width<=0||t.height<=0)return!1;let n=this.terminal._core?._renderService?.dimensions?.css?.cell;if(!n?.width||!n?.height)return this.fitAddon.fit(),!0;let s=n.width,l=n.height,r=this.terminal.element?.querySelector(".xterm-viewport"),c=r?Math.max(0,r.offsetWidth-r.clientWidth):0,o=Math.max(2,Math.floor((t.width-c)/s)),u=Math.max(2,Math.floor(t.height/l));return(o!==this.terminal.cols||u!==this.terminal.rows)&&this.terminal.resize(o,u),!0}focus(){this.terminal.focus()}pasteText(t){this.terminal.paste(t)}input(t){this.terminal.input(t,!1)}onData(t){this.terminal.onData(t),this.terminal.onBinary(t)}onResize(t){this.terminal.onResize(t)}onScroll(t){this.terminal.onScroll(t)}attachCustomKeyEventHandler(t){this.terminal.attachCustomKeyEventHandler(t)}isFocused(){let t=document.activeElement;return t?t===this.container||t===this.terminal.textarea||this.container.contains(t)||!!t.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(t,n){let s=this.terminal.buffer.active,[l,r]=t<=n?[t,n]:[n,t],c=s.viewportY,o=[];for(let u=l;u<=r;u++){let p=s.getLine(c+u);o.push(p?p.translateToString(!0):"")}return o.join(`
2
- `)}selectRows(t,n){let s=this.terminal.buffer.active,[l,r]=t<=n?[t,n]:[n,t];this.terminal.selectLines(s.viewportY+l,s.viewportY+r)}selectCells(t,n,s,l){let r=this.terminal.buffer.active,c=Math.min(n,l),o=Math.max(n,l);if(c===o){let u=Math.min(t,s),p=Math.max(t,s);this.terminal.select(u,r.viewportY+c,p-u+1)}else this.terminal.selectLines(r.viewportY+c,r.viewportY+o)}getCellsText(t,n,s,l){let r=this.terminal.buffer.active,c=Math.min(n,l),o=Math.max(n,l),u=n<l?t:n>l?s:Math.min(t,s),p=n<l?s:n>l?t:Math.max(t,s),S=r.viewportY,E=[];for(let H=c;H<=o;H++){let I=r.getLine(S+H);if(!I){E.push("");continue}let P=H===c?u:0,_e=H===o?p:this.terminal.cols-1,Z="";for(let T=P;T<=_e;T++){let W=I.getCell(T);W&&(Z+=W.getChars())}E.push(Z.replace(/\s+$/,""))}return E.join(`
3
- `)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}};function mn(e){let t=e.getBoundingClientRect(),n=window.visualViewport;return n?{width:Math.min(t.width,n.width),height:Math.max(0,Math.min(t.height,n.height-Math.max(0,t.top)))}:t}function fn(e,t,n){return e.innerHTML="",e.classList.add("terminal-pending"),(async()=>{let s=await pn.create(e,n.scrollback,n.theme),l,r=0,c,o=null,u=0,p=0,S=.2,E=10,H=.95,I=.04;function P(){u&&(cancelAnimationFrame(u),u=0),p=0}function _e(a){if(P(),Math.abs(a)<S)return;p=Math.max(-E,Math.min(E,a));let i=()=>{if(z){u=0;return}let d=e.querySelector(".xterm-rows > div"),m=d?d.getBoundingClientRect().height:16,b=m>0?Math.round(p*16/m):p>0?1:-1;b===0&&(b=p>0?1:-1);let A=s.viewportY()-b,K=s.baseY(),ce=Math.max(0,Math.min(A,K));if(s.scrollToLine(ce,!0),p*=H,ce!==A){u=0;return}if(Math.abs(p)<I){u=0;return}u=requestAnimationFrame(i)};u=requestAnimationFrame(i)}let Z=0,T="connecting",W=0,ne=!1,Le=[],G="",z=!1,se=1e3,Rt=location.protocol==="https:"?"wss:":"ws:",jt=n.wsBase||"/ws",zt=Rt+"//"+location.host+jt+"/"+encodeURIComponent(t),_t="/api/session/"+encodeURIComponent(t)+"/upload",Ot=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function Ut(){return Le.join("")+G}async function Wt(a,i=0){let d=a?s.viewportY():0,m=de(Ut());if(s.reset(),!m){a||s.scrollToBottom();return}await s.write(m),a?s.scrollToLine(i+d):s.scrollToBottom()}function Y(a){l?.readyState===WebSocket.OPEN&&l.send(JSON.stringify(a))}function Yt(a){let i;try{i=JSON.parse(a)}catch{T==="live"&&(G+=a,s.write(de(a)));return}if(i.type==="auth.required"){let d=localStorage.getItem("tmux-web-token");d?Y({type:"auth.token",token:d}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(i.type==="attach_failed"&&typeof i.message=="string"){Ee=!0,T="dead",s.reset(),s.write(`\r
1
+ var dn=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function qe(e){return e.replace(/\x1b\[\?1049[hl]/g,"")}function de(e){return e.replace(dn,"")}var Be;function un(){return Be||(document.querySelector("link[data-tmux-web-xterm-css]")?Be=Promise.resolve():(Be=new Promise(e=>{let t=document.createElement("link");t.rel="stylesheet",t.href="/assets/xterm.css",t.setAttribute("data-tmux-web-xterm-css",""),t.addEventListener("load",()=>e(),{once:!0}),t.addEventListener("error",()=>e(),{once:!0}),document.head.appendChild(t)}),Be))}var pn=class Pt{terminal;fitAddon;container;constructor(t,n,s){this.container=t,this.terminal=n,this.fitAddon=s,this.terminal.loadAddon(this.fitAddon),this.terminal.open(t)}static async create(t,n,s){let[{Terminal:l},{FitAddon:r}]=await Promise.all([import("./xterm-BXEES47M.js"),import("./addon-fit-D5N335P2.js"),un()]),c=new l({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:n,convertEol:!1,smoothScrollDuration:120,theme:s});return new Pt(t,c,new r)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(t){return new Promise(n=>this.terminal.write(t,n))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(t,n=!1){this.terminal.scrollToLine(Math.max(0,t),n)}scrollLines(t){let n=this.terminal.buffer?.active;this.terminal.scrollLines(t)}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){let t=mn(this.container);if(t.width<=0||t.height<=0)return!1;let n=this.terminal._core?._renderService?.dimensions?.css?.cell;if(!n?.width||!n?.height)return this.fitAddon.fit(),!0;let s=n.width,l=n.height,r=this.terminal.element?.querySelector(".xterm-viewport"),c=r?Math.max(0,r.offsetWidth-r.clientWidth):0,o=Math.max(2,Math.floor((t.width-c)/s)),u=Math.max(2,Math.floor(t.height/l));return(o!==this.terminal.cols||u!==this.terminal.rows)&&this.terminal.resize(o,u),!0}focus(){this.terminal.focus()}pasteText(t){this.terminal.paste(t)}input(t){this.terminal.input(t,!1)}onData(t){this.terminal.onData(t),this.terminal.onBinary(t)}onResize(t){this.terminal.onResize(t)}onScroll(t){this.terminal.onScroll(t)}attachCustomKeyEventHandler(t){this.terminal.attachCustomKeyEventHandler(t)}isFocused(){let t=document.activeElement;return t?t===this.container||t===this.terminal.textarea||this.container.contains(t)||!!t.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(t,n){let s=this.terminal.buffer.active,[l,r]=t<=n?[t,n]:[n,t],c=s.viewportY,o=[];for(let u=l;u<=r;u++){let p=s.getLine(c+u);o.push(p?p.translateToString(!0):"")}return o.join(`
2
+ `)}selectRows(t,n){let s=this.terminal.buffer.active,[l,r]=t<=n?[t,n]:[n,t];this.terminal.selectLines(s.viewportY+l,s.viewportY+r)}selectCells(t,n,s,l){let r=this.terminal.buffer.active,c=Math.min(n,l),o=Math.max(n,l);if(c===o){let u=Math.min(t,s),p=Math.max(t,s);this.terminal.select(u,r.viewportY+c,p-u+1)}else this.terminal.selectLines(r.viewportY+c,r.viewportY+o)}getCellsText(t,n,s,l){let r=this.terminal.buffer.active,c=Math.min(n,l),o=Math.max(n,l),u=n<l?t:n>l?s:Math.min(t,s),p=n<l?s:n>l?t:Math.max(t,s),k=r.viewportY,L=[];for(let H=c;H<=o;H++){let B=r.getLine(k+H);if(!B){L.push("");continue}let P=H===c?u:0,We=H===o?p:this.terminal.cols-1,Z="";for(let S=P;S<=We;S++){let U=B.getCell(S);U&&(Z+=U.getChars())}L.push(Z.replace(/\s+$/,""))}return L.join(`
3
+ `)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}};function mn(e){let t=e.getBoundingClientRect(),n=window.visualViewport;return n?{width:Math.min(t.width,n.width),height:Math.max(0,Math.min(t.height,n.height-Math.max(0,t.top)))}:t}function fn(e,t,n){return e.innerHTML="",e.classList.add("terminal-pending"),(async()=>{let s=await pn.create(e,n.scrollback,n.theme),l,r=0,c,o=null,u=0,p=0,k=.2,L=10,H=.95,B=.04;function P(){u&&(cancelAnimationFrame(u),u=0),p=0}function We(a){if(P(),Math.abs(a)<k)return;p=Math.max(-L,Math.min(L,a));let i=()=>{if(z){u=0;return}let d=e.querySelector(".xterm-rows > div"),m=d?d.getBoundingClientRect().height:16,b=m>0?Math.round(p*16/m):p>0?1:-1;b===0&&(b=p>0?1:-1);let A=s.viewportY()-b,K=s.baseY(),ce=Math.max(0,Math.min(A,K));if(s.scrollToLine(ce,!0),p*=H,ce!==A){u=0;return}if(Math.abs(p)<B){u=0;return}u=requestAnimationFrame(i)};u=requestAnimationFrame(i)}let Z=0,S="connecting",U=0,ne=!1,Ee=[],G="",z=!1,se=1e3,Rt=location.protocol==="https:"?"wss:":"ws:",jt=n.wsBase||"/ws",zt=Rt+"//"+location.host+jt+"/"+encodeURIComponent(t),_t="/api/session/"+encodeURIComponent(t)+"/upload",Wt=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function Ot(){return Ee.join("")+G}async function Ut(a,i=0){let d=a?s.viewportY():0,m=de(Ot());if(s.reset(),!m){a||s.scrollToBottom();return}await s.write(m),a?s.scrollToLine(i+d):s.scrollToBottom()}function Y(a){l?.readyState===WebSocket.OPEN&&l.send(JSON.stringify(a))}function Yt(a){let i;try{i=JSON.parse(a)}catch{S==="live"&&(G+=a,s.write(de(a)));return}if(i.type==="auth.required"){let d=localStorage.getItem("tmux-web-token");d?Y({type:"auth.token",token:d}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(i.type==="attach_failed"&&typeof i.message=="string"){Ce=!0,S="dead",s.reset(),s.write(`\r
4
4
  \x1B[31m`+de(i.message)+`\x1B[0m\r
5
- `).then(()=>{Ce();try{l?.close()}catch{}});return}if(i.type==="auth.ok"){i.token&&localStorage.setItem("tmux-web-token",i.token),se=1e3,q(),Y({type:"resize",cols:s.cols,rows:s.rows}),M();return}if(i.type==="auth.failed"){if(i.permanentLock||i.retryAfterMs&&i.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(i.message);return}return}if(i.type==="snapshot"&&typeof i.data=="string"){let d=Ye(de(i.data));Le=[d],G="",W=typeof i.lines=="number"?i.lines:n.terminal.initialLines,T="live",s.reset(),q(),Y({type:"resize",cols:s.cols,rows:s.rows}),s.write(d).then(()=>s.scrollToBottom());return}if(i.type==="window_changed"&&typeof i.activeIndex=="number"){let d=new URL(location.href);d.searchParams.get("window")!==String(i.activeIndex)&&(d.searchParams.set("window",String(i.activeIndex)),history.replaceState(history.state,"",d)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:i.windows}));return}if(i.type==="history"&&typeof i.data=="string"){i.lines>0&&i.data?(Le.unshift(Ye(i.data)),W+=i.lines,Wt(!0,i.lines).finally(()=>{ne=!1})):ne=!1;return}if(i.type==="data"&&typeof i.data=="string"){let d=Ye(de(i.data));if(T==="connecting"){T="live",G=d,s.write(d);return}T==="live"&&(G+=d,s.write(d))}}let Ee=!1;function nt(){if(Ee)return;let a=zt,i=localStorage.getItem("tmux-web-token");i&&(a+=(a.includes("?")?"&":"?")+"token="+encodeURIComponent(i)),a+=(a.includes("?")?"&":"?")+"cols="+s.cols+"&rows="+s.rows,l=new WebSocket(a),l.onopen=()=>{T="connecting",W=0,ne=!1,Le=[],G="",s.reset(),se=1e3},l.onmessage=d=>{typeof d.data=="string"&&Yt(d.data)},l.onclose=()=>{z||(T="connecting",!Ee&&setTimeout(()=>{se=Math.min(se*2,1e4),!z&&!Ee&&nt()},se))},l.onerror=()=>l?.close()}function xe(a){Y({type:"input",data:a})}function q(){return s.fit()}function Ce(){e.classList.remove("terminal-pending")}function M(){r&&cancelAnimationFrame(r),c&&clearTimeout(c),q(),r=requestAnimationFrame(()=>{r=0,q()&&Ce()}),c=setTimeout(()=>{q()&&Ce()},120)}function qt(){M(),setTimeout(M,50),setTimeout(M,150),setTimeout(M,300)}function st(a){return typeof a=="string"&&a.startsWith("image/")}function at(a){return a?.files?.length?a.files[0]??null:null}function Kt(a){if(!a?.items)return null;for(let i=0;i<a.items.length;i++){let d=a.items[i];if(d?.kind==="file"&&st(d.type))return d.getAsFile()}return null}async function Vt(a){let i=new FormData,d=a instanceof File&&a.name?a.name:"upload";i.append("file",a,d);let m=localStorage.getItem("tmux-web-token"),b={};m&&(b.Authorization="Bearer "+m);let A=await fetch(_t,{method:"POST",body:i,headers:b});if(!A.ok){let ce="upload failed";try{let ut=await A.json();ut.error&&(ce=ut.error)}catch{}throw new Error(ce)}let K=await A.json();if(!K.path)throw new Error("no path in response");return K.path}async function Oe(a){try{let i=await Vt(a);xe(i)}catch{}}s.onData(a=>xe(a)),s.onResize(({cols:a,rows:i})=>Y({type:"resize",cols:a,rows:i})),s.onScroll(()=>{T!=="live"||ne||!s.isNearScrollbackTop()||(ne=!0,Y({type:"load_history",before:W}))});let ae=!1,ie=!1,w=null,x=null,oe=document.createElement("div");oe.className="terminal-copy-banner",oe.innerHTML='<strong>Copy mode</strong><span class="hint">drag to copy \xB7 Esc exits</span>',oe.hidden=!0,e.appendChild(oe);let R=document.createElement("div");R.className="terminal-copy-banner terminal-copy-toast",R.textContent="Copied",R.hidden=!0,e.appendChild(R);function it(a,i){let d=e.querySelector(".xterm-screen, canvas"),m=(d&&d.getBoundingClientRect().width>0?d:e).getBoundingClientRect(),b=m.height>0&&s.rows>0?m.height/s.rows:18,A=m.width>0&&s.cols>0?m.width/s.cols:9;return{row:Math.max(0,Math.min(s.rows-1,Math.floor((i-m.top)/b))),col:Math.max(0,Math.min(s.cols-1,Math.floor((a-m.left)/A)))}}async function ke(a){if(!a)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(a);return}}catch{}let i=document.createElement("textarea");i.value=a,i.style.position="fixed",i.style.opacity="0",i.style.pointerEvents="none",document.body.appendChild(i),i.focus(),i.select();try{document.execCommand("copy")}catch{}i.remove()}let le;function Se(){R.hidden=!1,le&&clearTimeout(le),le=setTimeout(()=>{R.hidden=!0},1e3)}function Q(a){ae=a,oe.hidden=!a,e.classList.toggle("terminal-copy-mode-active",a),a&&s.focus()}function ot(){Q(!ae)}function Jt(a){z||a.button!==0||ie||(ae||a.shiftKey)&&(a.preventDefault(),a.stopPropagation(),ie=!0,w=it(a.clientX,a.clientY),x=w,s.selectCells(w.col,w.row,x.col,x.row),document.addEventListener("mousemove",Ue,!0),document.addEventListener("mouseup",We,!0))}function Ue(a){z||!ie||!w||(a.preventDefault(),a.stopPropagation(),x=it(a.clientX,a.clientY),s.selectCells(w.col,w.row,x.col,x.row))}function We(a){if(z||!ie||!w||!x)return;a.preventDefault(),a.stopPropagation(),document.removeEventListener("mousemove",Ue,!0),document.removeEventListener("mouseup",We,!0),ie=!1;let i=s.getCellsText(w.col,w.row,x.col,x.row);w=null,x=null,s.clearSelection(),Q(!1),i&&(R.textContent="\u5DF2\u590D\u5236",ke(i).then(Se)),s.focus()}e.addEventListener("mousedown",Jt,!0),document.addEventListener("keydown",Xt,!0);function Xt(a){if(!(z||!s.isFocused()||a.defaultPrevented||a.isComposing)){if(ae){if(a.key==="Escape"){a.preventDefault(),a.stopPropagation(),w=null,x=null,s.clearSelection(),Q(!1);return}if(a.key==="Enter"||(a.ctrlKey||a.metaKey)&&a.code==="KeyC"){a.preventDefault(),a.stopPropagation(),ke(s.getScreenText()).then(Se),Q(!1);return}}if(a.altKey&&a.code==="KeyC"&&!a.ctrlKey&&!a.metaKey){if(a.preventDefault(),a.stopPropagation(),w&&x){let i=s.getCellsText(w.col,w.row,x.col,x.row);w=null,x=null,s.clearSelection(),Q(!1),i&&(R.textContent="Copied",ke(i).then(Se))}else{let i=s.getSelection();i?(s.clearSelection(),R.textContent="Copied",ke(i).then(Se)):ot()}return}if((a.ctrlKey||a.metaKey)&&a.code==="KeyV"){a.preventDefault(),a.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){let i=await navigator.clipboard.read();for(let d of i)for(let m of d.types)if(st(m)){let b=await d.getType(m);await Oe(b);return}}}catch{}try{let i=await navigator.clipboard?.readText();i&&s.pasteText(lt(i))}catch{}})();return}}}let Te=0;function lt(a){return a.split(`\r
5
+ `).then(()=>{ke();try{l?.close()}catch{}});return}if(i.type==="auth.ok"){i.token&&localStorage.setItem("tmux-web-token",i.token),se=1e3,q(),Y({type:"resize",cols:s.cols,rows:s.rows}),T();return}if(i.type==="auth.failed"){if(i.permanentLock||i.retryAfterMs&&i.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(i.message);return}return}if(i.type==="snapshot"&&typeof i.data=="string"){let d=qe(de(i.data));Ee=[d],G="",U=typeof i.lines=="number"?i.lines:n.terminal.initialLines,S="live",s.reset(),q(),Y({type:"resize",cols:s.cols,rows:s.rows}),s.write(d).then(()=>s.scrollToBottom());return}if(i.type==="window_changed"&&typeof i.activeIndex=="number"){let d=new URL(location.href);d.searchParams.get("window")!==String(i.activeIndex)&&(d.searchParams.set("window",String(i.activeIndex)),history.replaceState(history.state,"",d)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:i.windows}));return}if(i.type==="history"&&typeof i.data=="string"){i.lines>0&&i.data?(Ee.unshift(qe(i.data)),U+=i.lines,Ut(!0,i.lines).finally(()=>{ne=!1})):ne=!1;return}if(i.type==="data"&&typeof i.data=="string"){let d=qe(de(i.data));if(S==="connecting"){S="live",G=d,s.write(d);return}S==="live"&&(G+=d,s.write(d))}}let Ce=!1;function st(){if(Ce)return;let a=zt,i=localStorage.getItem("tmux-web-token");i&&(a+=(a.includes("?")?"&":"?")+"token="+encodeURIComponent(i)),a+=(a.includes("?")?"&":"?")+"cols="+s.cols+"&rows="+s.rows,l=new WebSocket(a),l.onopen=()=>{S="connecting",U=0,ne=!1,Ee=[],G="",s.reset(),se=1e3},l.onmessage=d=>{typeof d.data=="string"&&Yt(d.data)},l.onclose=()=>{z||(S="connecting",!Ce&&setTimeout(()=>{se=Math.min(se*2,1e4),!z&&!Ce&&st()},se))},l.onerror=()=>l?.close()}function xe(a){Y({type:"input",data:a})}function q(){return s.fit()}function ke(){e.classList.remove("terminal-pending")}function T(){r&&cancelAnimationFrame(r),c&&clearTimeout(c),q(),r=requestAnimationFrame(()=>{r=0,q()&&ke()}),c=setTimeout(()=>{q()&&ke()},120)}function qt(){T(),setTimeout(T,50),setTimeout(T,150),setTimeout(T,300)}function at(a){return typeof a=="string"&&a.startsWith("image/")}function it(a){return a?.files?.length?a.files[0]??null:null}function Kt(a){if(!a?.items)return null;for(let i=0;i<a.items.length;i++){let d=a.items[i];if(d?.kind==="file"&&at(d.type))return d.getAsFile()}return null}async function Vt(a){let i=new FormData,d=a instanceof File&&a.name?a.name:"upload";i.append("file",a,d);let m=localStorage.getItem("tmux-web-token"),b={};m&&(b.Authorization="Bearer "+m);let A=await fetch(_t,{method:"POST",body:i,headers:b});if(!A.ok){let ce="upload failed";try{let pt=await A.json();pt.error&&(ce=pt.error)}catch{}throw new Error(ce)}let K=await A.json();if(!K.path)throw new Error("no path in response");return K.path}async function Oe(a){try{let i=await Vt(a);xe(i)}catch{}}s.onData(a=>xe(a)),s.onResize(({cols:a,rows:i})=>Y({type:"resize",cols:a,rows:i})),s.onScroll(()=>{S!=="live"||ne||!s.isNearScrollbackTop()||(ne=!0,Y({type:"load_history",before:U}))});let ae=!1,ie=!1,w=null,E=null,oe=document.createElement("div");oe.className="terminal-copy-banner",oe.innerHTML='<strong>Copy mode</strong><span class="hint">drag to copy \xB7 Esc exits</span>',oe.hidden=!0,e.appendChild(oe);let R=document.createElement("div");R.className="terminal-copy-banner terminal-copy-toast",R.textContent="Copied",R.hidden=!0,e.appendChild(R);function ot(a,i){let d=e.querySelector(".xterm-screen, canvas"),m=(d&&d.getBoundingClientRect().width>0?d:e).getBoundingClientRect(),b=m.height>0&&s.rows>0?m.height/s.rows:18,A=m.width>0&&s.cols>0?m.width/s.cols:9;return{row:Math.max(0,Math.min(s.rows-1,Math.floor((i-m.top)/b))),col:Math.max(0,Math.min(s.cols-1,Math.floor((a-m.left)/A)))}}async function Se(a){if(!a)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(a);return}}catch{}let i=document.createElement("textarea");i.value=a,i.style.position="fixed",i.style.opacity="0",i.style.pointerEvents="none",document.body.appendChild(i),i.focus(),i.select();try{document.execCommand("copy")}catch{}i.remove()}let le;function Te(){R.hidden=!1,le&&clearTimeout(le),le=setTimeout(()=>{R.hidden=!0},1e3)}function Q(a){ae=a,oe.hidden=!a,e.classList.toggle("terminal-copy-mode-active",a),a&&s.focus()}function lt(){Q(!ae)}function Jt(a){z||a.button!==0||ie||(ae||a.shiftKey)&&(a.preventDefault(),a.stopPropagation(),ie=!0,w=ot(a.clientX,a.clientY),E=w,s.selectCells(w.col,w.row,E.col,E.row),document.addEventListener("mousemove",Ue,!0),document.addEventListener("mouseup",Ye,!0))}function Ue(a){z||!ie||!w||(a.preventDefault(),a.stopPropagation(),E=ot(a.clientX,a.clientY),s.selectCells(w.col,w.row,E.col,E.row))}function Ye(a){if(z||!ie||!w||!E)return;a.preventDefault(),a.stopPropagation(),document.removeEventListener("mousemove",Ue,!0),document.removeEventListener("mouseup",Ye,!0),ie=!1;let i=s.getCellsText(w.col,w.row,E.col,E.row);w=null,E=null,s.clearSelection(),Q(!1),i&&(R.textContent="\u5DF2\u590D\u5236",Se(i).then(Te)),s.focus()}e.addEventListener("mousedown",Jt,!0),document.addEventListener("keydown",Xt,!0);function Xt(a){if(!(z||!s.isFocused()||a.defaultPrevented||a.isComposing)){if(ae){if(a.key==="Escape"){a.preventDefault(),a.stopPropagation(),w=null,E=null,s.clearSelection(),Q(!1);return}if(a.key==="Enter"||(a.ctrlKey||a.metaKey)&&a.code==="KeyC"){a.preventDefault(),a.stopPropagation(),Se(s.getScreenText()).then(Te),Q(!1);return}}if(a.altKey&&a.code==="KeyC"&&!a.ctrlKey&&!a.metaKey){if(a.preventDefault(),a.stopPropagation(),w&&E){let i=s.getCellsText(w.col,w.row,E.col,E.row);w=null,E=null,s.clearSelection(),Q(!1),i&&(R.textContent="Copied",Se(i).then(Te))}else{let i=s.getSelection();i?(s.clearSelection(),R.textContent="Copied",Se(i).then(Te)):lt()}return}if((a.ctrlKey||a.metaKey)&&a.code==="KeyV"){a.preventDefault(),a.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){let i=await navigator.clipboard.read();for(let d of i)for(let m of d.types)if(at(m)){let b=await d.getType(m);await Oe(b);return}}}catch{}try{let i=await navigator.clipboard?.readText();i&&s.pasteText(rt(i))}catch{}})();return}}}let Me=0;function rt(a){return a.split(`\r
6
6
  `).join(`
7
7
  `).split(`
8
- `).join("\r")}async function Zt(a){let i=Kt(a.clipboardData);if(i){a.preventDefault(),a.stopPropagation();let b=Date.now();if(b-Te<50)return;Te=b,await Oe(i);return}let d=a.clipboardData?.getData("text/plain");if(!d)return;a.preventDefault(),a.stopPropagation();let m=Date.now();m-Te<50||(Te=m,s.pasteText(lt(d)))}let re=0;function Gt(a){a.preventDefault(),re++,at(a.dataTransfer)&&e.classList.add("terminal-drag-over")}function Qt(a){a.preventDefault(),a.dataTransfer&&(a.dataTransfer.dropEffect="copy")}function en(a){a.preventDefault(),re--,re<=0&&(re=0,e.classList.remove("terminal-drag-over"))}async function tn(a){a.preventDefault(),re=0,e.classList.remove("terminal-drag-over");let i=at(a.dataTransfer);i&&await Oe(i)}function rt(a){!Ot||a.key!=="Escape"||ae||a.defaultPrevented||a.repeat||a.metaKey||a.ctrlKey||a.altKey||s.isFocused()&&(a.preventDefault(),a.stopPropagation(),xe("\x1B"))}e.addEventListener("paste",Zt),e.addEventListener("dragenter",Gt),e.addEventListener("dragover",Qt),e.addEventListener("dragleave",en),e.addEventListener("drop",tn),document.addEventListener("keydown",rt,!0);function nn(a){if(a.touches.length!==1){o=null;return}let i=a.touches[0];i&&(P(),o={startX:i.clientX,startY:i.clientY,lastX:i.clientX,lastY:i.clientY,lastT:performance.now(),velocity:0,scrolling:!1},a.stopPropagation())}function sn(a){if(!o||a.touches.length!==1)return;let i=a.touches[0];if(!i)return;let d=i.clientY-o.startY,m=i.clientX-o.startX;if(!o.scrolling){if(Math.abs(d)<8||Math.abs(d)<Math.abs(m))return;o.scrolling=!0,Z=Date.now()+500}a.preventDefault(),a.stopPropagation();let b=performance.now(),A=i.clientY-o.lastY,K=b-o.lastT;K>0&&(o.velocity=A/K),rn(-A),o.lastX=i.clientX,o.lastY=i.clientY,o.lastT=b}function an(a){if(!o)return;let i=o.scrolling,d=o.velocity;if(o=null,a.stopPropagation(),!i){s.focus();return}Z=Date.now()+500,a.preventDefault(),d&&_e(d)}function on(a){o=null,P(),a.stopPropagation()}function ln(a){a.pointerType==="touch"&&Date.now()<Z&&(a.preventDefault(),a.stopPropagation())}function rn(a){let i=e.querySelector(".xterm-rows > div"),d=i?i.getBoundingClientRect().height:16,m=d>0?Math.round(a/d):a>0?1:-1;m===0&&(m=a>0?1:-1),s.scrollLines(m)}e.addEventListener("touchstart",nn,{passive:!0,capture:!0}),e.addEventListener("touchmove",sn,{passive:!1,capture:!0}),e.addEventListener("touchend",an,{passive:!1,capture:!0}),e.addEventListener("touchcancel",on,{passive:!0,capture:!0}),e.addEventListener("pointerup",ln,!0);function ct(){M()}window.addEventListener("resize",ct),window.visualViewport?.addEventListener("resize",M),window.visualViewport?.addEventListener("scroll",M);let dt=new ResizeObserver(()=>M());dt.observe(e),document.fonts?.ready.then(()=>{M(),setTimeout(M,50),setTimeout(M,200)}),e.addEventListener("focusin",qt,!0);async function cn(){if(document.fonts?.ready)try{await Promise.race([document.fonts.ready,new Promise(a=>setTimeout(a,1e3))])}catch{}}return requestAnimationFrame(()=>{q()&&Ce(),(async()=>(await cn(),q()&&Y({type:"resize",cols:s.cols,rows:s.rows}),nt(),M()))()}),{destroy(){if(z=!0,P(),Q(!1),le&&clearTimeout(le),document.removeEventListener("mousemove",Ue,!0),document.removeEventListener("mouseup",We,!0),l){try{l.close(1e3,"session switch")}catch{}l=void 0}e.innerHTML="",e.classList.remove("terminal-pending"),window.removeEventListener("resize",ct),dt.disconnect(),document.removeEventListener("keydown",rt,!0)},focus(){s.focus()},sendInput(a){xe(a)},toggleCopyMode(){ot()}}})()}var ue=window.__TMUX_WEB_SHELL__,v=null,g=null,pt=typeof window.__TMUX_WEB_SCOPE__?.agentId=="string"?window.__TMUX_WEB_SCOPE__.agentId:null,L=pt;window.__tmuxWebScopeAgent=pt;var qe="sessions",_="",Ie="",Be="",mt="";function C(e){return L?"/a/"+encodeURIComponent(L)+e:e}var f=document.getElementById("sidebar-content"),V=document.getElementById("main-placeholder"),B=document.getElementById("terminal-container"),pe=document.getElementById("file-editor"),hn=document.getElementById("fe-path"),F=document.getElementById("fe-status"),me=document.getElementById("fe-content"),J=document.getElementById("fe-save"),vn=document.getElementById("fe-delete"),gn=document.getElementById("fe-back"),ft=document.getElementById("fe-new-name"),yn=document.getElementById("fe-new-btn"),Ke=document.getElementById("settings-backdrop"),ht=document.getElementById("settings-popover"),vt=document.querySelector(".sidebar");function wn(){return window.matchMedia("(max-width: 640px)").matches}function Ve(){wn()&&vt.classList.add("collapsed")}function gt(){vt.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{gt(),yt("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{gt(),yt("files")});function yt(e){qe=e,document.querySelectorAll(".mode-btn").forEach(n=>n.classList.remove("active"));let t=document.getElementById(e==="sessions"?"mode-sessions":"mode-files");t&&t.classList.add("active"),e==="sessions"?(Je="",O()):An()}var Je="";async function O(){if(qe!=="sessions")return;try{let t=await(await fetch("/api/sidebar/sessions")).json(),n=JSON.stringify({recent:t.recent,agents:t.agents,tombstones:t.tombstones});if(n===Je)return;Je=n,Cn(t)}catch{f.innerHTML+='<div class="file-tree-empty">Failed to load sessions</div>'}let e=document.getElementById("ns-btn");e&&e.addEventListener("click",()=>{let t=window.__openNewSessionModal;typeof t=="function"?t():document.getElementById("new-session-modal")?.classList.add("open")}),tt()}var wt="tmux-web-sidebar-group-collapsed";function bt(){try{return new Set(JSON.parse(localStorage.getItem(wt)||"[]"))}catch{return new Set}}function bn(e){try{localStorage.setItem(wt,JSON.stringify([...e]))}catch{}}function Ln(e,t,n){if(!e)return"\u2026";let s=n&&(e===n||e.startsWith(n+"/"))?"~"+e.slice(n.length):e,l=s.split("/").filter(Boolean);if(l.length===0)return e;for(let r=1;r<=l.length;r++){let c=l.slice(-r).join("/");if(!t.some(o=>!o||o===e?!1:(n&&(o===n||o.startsWith(n+"/"))?"~"+o.slice(n.length):o).split("/").filter(Boolean).slice(-r).join("/")===c))return c}return s}function Lt(e,t,n,s=!0){let l=new Map;for(let o of e){let u=o.path||"";l.has(u)||l.set(u,[]),l.get(u).push(o)}let r=[...l.keys()],c=bt();for(let[o,u]of l){let p=Ln(o,r,t),S=c.has(o),E=document.createElement("div");E.className="session-group-header"+(S?" collapsed":""),E.title=o||"No working directory",E.innerHTML=`<span class="sg-folder">&#128193;</span><span class="sg-label">${h(p)}</span>`,E.addEventListener("click",()=>{let I=bt(),P=E.nextElementSibling;I.has(o)?(I.delete(o),E.classList.remove("collapsed"),P?.classList.remove("collapsed")):(I.add(o),E.classList.add("collapsed"),P?.classList.add("collapsed")),bn(I)});let H=document.createElement("div");H.className="session-group-body"+(S?" collapsed":"");for(let I of u)H.appendChild(n?En(I,n,s):xn(I));f.appendChild(E),f.appendChild(H)}}function En(e,t,n){let s=document.createElement("div");return s.className="session-item"+(e.name===g&&L===t?" active":"")+(n?"":" session-offline"),s.setAttribute("data-session",e.name),s.setAttribute("data-agent",t),s.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${e.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
9
- <span>${h(e.name)}</span>${n?"":'<span class="meta">offline</span>'}`,n&&s.addEventListener("click",l=>{l.target.closest(".session-edit-btn")||fe(e.name,t)}),s}function xn(e){let t=document.createElement("div");t.className="session-item"+(e.name===g&&!L?" active":""),t.setAttribute("data-session",e.name),t.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${e.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
8
+ `).join("\r")}async function Zt(a){let i=Kt(a.clipboardData);if(i){a.preventDefault(),a.stopPropagation();let b=Date.now();if(b-Me<50)return;Me=b,await Oe(i);return}let d=a.clipboardData?.getData("text/plain");if(!d)return;a.preventDefault(),a.stopPropagation();let m=Date.now();m-Me<50||(Me=m,s.pasteText(rt(d)))}let re=0;function Gt(a){a.preventDefault(),re++,it(a.dataTransfer)&&e.classList.add("terminal-drag-over")}function Qt(a){a.preventDefault(),a.dataTransfer&&(a.dataTransfer.dropEffect="copy")}function en(a){a.preventDefault(),re--,re<=0&&(re=0,e.classList.remove("terminal-drag-over"))}async function tn(a){a.preventDefault(),re=0,e.classList.remove("terminal-drag-over");let i=it(a.dataTransfer);i&&await Oe(i)}function ct(a){!Wt||a.key!=="Escape"||ae||a.defaultPrevented||a.repeat||a.metaKey||a.ctrlKey||a.altKey||s.isFocused()&&(a.preventDefault(),a.stopPropagation(),xe("\x1B"))}e.addEventListener("paste",Zt),e.addEventListener("dragenter",Gt),e.addEventListener("dragover",Qt),e.addEventListener("dragleave",en),e.addEventListener("drop",tn),document.addEventListener("keydown",ct,!0);function nn(a){if(a.touches.length!==1){o=null;return}let i=a.touches[0];i&&(P(),o={startX:i.clientX,startY:i.clientY,lastX:i.clientX,lastY:i.clientY,lastT:performance.now(),velocity:0,scrolling:!1},a.stopPropagation())}function sn(a){if(!o||a.touches.length!==1)return;let i=a.touches[0];if(!i)return;let d=i.clientY-o.startY,m=i.clientX-o.startX;if(!o.scrolling){if(Math.abs(d)<8||Math.abs(d)<Math.abs(m))return;o.scrolling=!0,Z=Date.now()+500}a.preventDefault(),a.stopPropagation();let b=performance.now(),A=i.clientY-o.lastY,K=b-o.lastT;K>0&&(o.velocity=A/K),rn(-A),o.lastX=i.clientX,o.lastY=i.clientY,o.lastT=b}function an(a){if(!o)return;let i=o.scrolling,d=o.velocity;if(o=null,a.stopPropagation(),!i){s.focus();return}Z=Date.now()+500,a.preventDefault(),d&&We(d)}function on(a){o=null,P(),a.stopPropagation()}function ln(a){a.pointerType==="touch"&&Date.now()<Z&&(a.preventDefault(),a.stopPropagation())}function rn(a){let i=e.querySelector(".xterm-rows > div"),d=i?i.getBoundingClientRect().height:16,m=d>0?Math.round(a/d):a>0?1:-1;m===0&&(m=a>0?1:-1),s.scrollLines(m)}e.addEventListener("touchstart",nn,{passive:!0,capture:!0}),e.addEventListener("touchmove",sn,{passive:!1,capture:!0}),e.addEventListener("touchend",an,{passive:!1,capture:!0}),e.addEventListener("touchcancel",on,{passive:!0,capture:!0}),e.addEventListener("pointerup",ln,!0);function dt(){T()}window.addEventListener("resize",dt),window.visualViewport?.addEventListener("resize",T),window.visualViewport?.addEventListener("scroll",T);let ut=new ResizeObserver(()=>T());ut.observe(e),document.fonts?.ready.then(()=>{T(),setTimeout(T,50),setTimeout(T,200)}),e.addEventListener("focusin",qt,!0);async function cn(){if(document.fonts?.ready)try{await Promise.race([document.fonts.ready,new Promise(a=>setTimeout(a,1e3))])}catch{}}return requestAnimationFrame(()=>{q()&&ke(),(async()=>(await cn(),q()&&Y({type:"resize",cols:s.cols,rows:s.rows}),st(),T()))()}),{destroy(){if(z=!0,P(),Q(!1),le&&clearTimeout(le),document.removeEventListener("mousemove",Ue,!0),document.removeEventListener("mouseup",Ye,!0),l){try{l.close(1e3,"session switch")}catch{}l=void 0}e.innerHTML="",e.classList.remove("terminal-pending"),window.removeEventListener("resize",dt),ut.disconnect(),document.removeEventListener("keydown",ct,!0)},focus(){s.focus()},sendInput(a){xe(a)},toggleCopyMode(){lt()}}})()}var ue=window.__TMUX_WEB_SHELL__,v=null,g=null,pe=typeof window.__TMUX_WEB_SCOPE__?.agentId=="string"?window.__TMUX_WEB_SCOPE__.agentId:null,M=pe;window.__tmuxWebScopeAgent=pe;var Ke="sessions",_="",Ie="",De="",mt="";function C(e){return M?"/a/"+encodeURIComponent(M)+e:e}var f=document.getElementById("sidebar-content"),V=document.getElementById("main-placeholder"),I=document.getElementById("terminal-container"),me=document.getElementById("file-editor"),hn=document.getElementById("fe-path"),F=document.getElementById("fe-status"),fe=document.getElementById("fe-content"),J=document.getElementById("fe-save"),vn=document.getElementById("fe-delete"),gn=document.getElementById("fe-back"),ft=document.getElementById("fe-new-name"),yn=document.getElementById("fe-new-btn"),Ve=document.getElementById("settings-backdrop"),ht=document.getElementById("settings-popover"),vt=document.querySelector(".sidebar");function wn(){return window.matchMedia("(max-width: 640px)").matches}function Je(){wn()&&vt.classList.add("collapsed")}function gt(){vt.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{gt(),yt("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{gt(),yt("files")});function yt(e){Ke=e,document.querySelectorAll(".mode-btn").forEach(n=>n.classList.remove("active"));let t=document.getElementById(e==="sessions"?"mode-sessions":"mode-files");t&&t.classList.add("active"),e==="sessions"?(Xe="",W()):An()}var Xe="";async function W(){if(Ke!=="sessions")return;try{let t=await(await fetch("/api/sidebar/sessions")).json(),n=JSON.stringify({recent:t.recent,agents:t.agents,tombstones:t.tombstones});if(n===Xe)return;Xe=n,xn(t)}catch{f.innerHTML+='<div class="file-tree-empty">Failed to load sessions</div>'}let e=document.getElementById("ns-btn");e&&e.addEventListener("click",()=>{let t=window.__openNewSessionModal;typeof t=="function"?t():document.getElementById("new-session-modal")?.classList.add("open")}),nt()}var wt="tmux-web-sidebar-group-collapsed";function bt(){try{return new Set(JSON.parse(localStorage.getItem(wt)||"[]"))}catch{return new Set}}function bn(e){try{localStorage.setItem(wt,JSON.stringify([...e]))}catch{}}function Ln(e,t,n){if(!e)return"\u2026";let s=n&&(e===n||e.startsWith(n+"/"))?"~"+e.slice(n.length):e,l=s.split("/").filter(Boolean);if(l.length===0)return e;for(let r=1;r<=l.length;r++){let c=l.slice(-r).join("/");if(!t.some(o=>!o||o===e?!1:(n&&(o===n||o.startsWith(n+"/"))?"~"+o.slice(n.length):o).split("/").filter(Boolean).slice(-r).join("/")===c))return c}return s}function Lt(e,t,n,s=!0){let l=new Map;for(let o of e){let u=o.path||"";l.has(u)||l.set(u,[]),l.get(u).push(o)}let r=[...l.keys()],c=bt();for(let[o,u]of l){let p=Ln(o,r,t),k=c.has(o),L=document.createElement("div");L.className="session-group-header"+(k?" collapsed":""),L.title=o||"No working directory",L.innerHTML=`<span class="sg-folder">&#128193;</span><span class="sg-label">${h(p)}</span>`,L.addEventListener("click",()=>{let B=bt(),P=L.nextElementSibling;B.has(o)?(B.delete(o),L.classList.remove("collapsed"),P?.classList.remove("collapsed")):(B.add(o),L.classList.add("collapsed"),P?.classList.add("collapsed")),bn(B)});let H=document.createElement("div");H.className="session-group-body"+(k?" collapsed":"");for(let B of u)H.appendChild(n?En(B,n,s):Cn(B));f.appendChild(L),f.appendChild(H)}}function En(e,t,n){let s=document.createElement("div");return s.className="session-item"+(e.name===g&&M===t?" active":"")+(n?"":" session-offline"),s.setAttribute("data-session",e.name),s.setAttribute("data-agent",t),s.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${e.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
9
+ <span>${h(e.name)}</span>${n?"":'<span class="meta">offline</span>'}`,n&&s.addEventListener("click",l=>{l.target.closest(".session-edit-btn")||he(e.name,t)}),s}function Cn(e){let t=document.createElement("div");t.className="session-item"+(e.name===g&&!M?" active":""),t.setAttribute("data-session",e.name),t.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${e.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
10
10
  <span>${h(e.name)}</span>
11
11
  <button class="session-edit-btn" data-session="${h(e.name)}" title="Edit session"><svg viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg></button>
12
- `,t.addEventListener("click",s=>{s.target.closest(".session-edit-btn")||fe(e.name)});let n=t.querySelector(".session-edit-btn");return n&&n.addEventListener("click",s=>{s.stopPropagation(),Ht(e.name,n)}),t}function Cn(e){f.innerHTML='<button class="new-session-sidebar-btn" id="ns-btn">+ New Session</button>';let t=e.recent||[],n=document.createElement("div");n.className="sidebar-section-label"+(L?" clickable":""),n.textContent=L?"\u2190 \u8FD4\u56DE\u672C\u673A":"\u672C\u673A",L&&(n.title="Back to hub",n.addEventListener("click",()=>{window.location.href="/"})),f.appendChild(n),Lt(t,e.home);let s=e.agents||[];for(let r of s){if(!r.sessions||r.sessions.length===0)continue;let c=r.agentId===L,o=document.createElement("div");o.className="sidebar-section-label machine-label"+(r.online?"":" agent-offline-label")+(!c&&r.online?" clickable":""),o.textContent=r.agentName+(r.online?"":" (offline)"),!c&&r.online&&(o.title="\u6253\u5F00 "+r.agentName,o.addEventListener("click",()=>{window.location.href="/a/"+encodeURIComponent(r.agentId)+"/"})),f.appendChild(o),Lt(r.sessions,e.home,r.agentId,r.online)}let l=e.tombstones||[];if(l.length>0){let r=document.createElement("div");r.className="sidebar-section-label tombstone-label",r.textContent="\u5931\u6548\u4F1A\u8BDD",f.appendChild(r);for(let c of l){let o=document.createElement("div");o.className="session-item session-tombstone",o.setAttribute("data-session",c.name),c.agentId&&o.setAttribute("data-agent",c.agentId);let u=c.agentId?c.agentOnline?" (agent)":" (agent \u79BB\u7EBF)":"";o.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"></svg>
12
+ `,t.addEventListener("click",s=>{s.target.closest(".session-edit-btn")||he(e.name)});let n=t.querySelector(".session-edit-btn");return n&&n.addEventListener("click",s=>{s.stopPropagation(),Ht(e.name,n)}),t}function xn(e){f.innerHTML='<button class="new-session-sidebar-btn" id="ns-btn">+ New Session</button>';let t=e.recent||[],n=document.createElement("div");n.className="sidebar-section-label"+(pe?" clickable":""),n.textContent=pe?"\u2190 \u8FD4\u56DE\u672C\u673A":"\u672C\u673A",pe&&(n.title="Back to hub",n.addEventListener("click",()=>{window.location.href="/"})),f.appendChild(n),Lt(t,e.home);let s=e.agents||[];for(let r of s){if(!r.sessions||r.sessions.length===0)continue;let c=r.agentId===M,o=document.createElement("div");o.className="sidebar-section-label machine-label"+(r.online?"":" agent-offline-label")+(!c&&r.online?" clickable":""),o.textContent=r.agentName+(r.online?"":" (offline)"),!c&&r.online&&(o.title="\u6253\u5F00 "+r.agentName,o.addEventListener("click",()=>{window.location.href="/a/"+encodeURIComponent(r.agentId)+"/"})),f.appendChild(o),Lt(r.sessions,e.home,r.agentId,r.online)}let l=e.tombstones||[];if(l.length>0){let r=document.createElement("div");r.className="sidebar-section-label tombstone-label",r.textContent="\u5931\u6548\u4F1A\u8BDD",f.appendChild(r);for(let c of l){let o=document.createElement("div");o.className="session-item session-tombstone",o.setAttribute("data-session",c.name),c.agentId&&o.setAttribute("data-agent",c.agentId);let u=c.agentId?c.agentOnline?" (agent)":" (agent \u79BB\u7EBF)":"";o.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"></svg>
13
13
  <span>${h(c.name)}</span><span class="meta">\u5931\u6548${u}</span>
14
- <button class="session-edit-btn" data-session="${h(c.name)}" title="\u6062\u590D\u4F1A\u8BDD"><svg viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg></button>`;let p=o.querySelector(".session-edit-btn");p&&p.addEventListener("click",S=>{S.stopPropagation(),Ht(c.name,p,{tombstone:!0,agentId:c.agentId})}),f.appendChild(o)}}}function h(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function fe(e,t){if(!(g===e&&v&&L===(t||null))){pe.style.display="none",V.style.display="none",B.style.display="",B.classList.add("terminal-pending"),Ve(),v&&(Re(),v.destroy(),v=null),g=e,L=t||null,window.__tmuxWebScopeAgent=L,window.__tmuxWebCurrentSession=g,Yn(e,t);for(let n of f.querySelectorAll(".session-item"))n.classList.toggle("active",n.getAttribute("data-session")===e&&(n.getAttribute("data-agent")||null)===L);try{v=await fn(B,e,{terminal:ue.terminal,scrollback:ue.scrollback,theme:ue.theme,wsBase:L?"/ws/a/"+encodeURIComponent(L):ue.wsBase||"/ws"}),Dt()}catch(n){console.error("[shell] terminal init failed:",n);let s=n&&typeof n=="object"&&"message"in n?n.message:String(n);B.textContent="Failed to open terminal for "+e+": "+s,B.classList.remove("terminal-pending")}}}var De=[],y=null,Et=!1;function kn(e){if(!y||!y.files.length)return null;let t=y.repoRoot;if(!t||!e.startsWith(t))return null;let n=e.slice(t.length+1);for(let s of y.files)if(s.path===n)return s.status;return null}async function Sn(e){Et=!0;try{let t=await fetch(C("/api/git/status?path="+encodeURIComponent(e)));t.ok?y=await t.json():y=null}catch{y=null}finally{Et=!1}}function Tn(){if(!y||!y.branch)return"";let{branch:e,linesAdded:t,linesRemoved:n}=y,s=`<div class="sidebar-git"><div class="git-branch-badge">
14
+ <button class="session-edit-btn" data-session="${h(c.name)}" title="\u6062\u590D\u4F1A\u8BDD"><svg viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg></button>`;let p=o.querySelector(".session-edit-btn");p&&p.addEventListener("click",k=>{k.stopPropagation(),Ht(c.name,p,{tombstone:!0,agentId:c.agentId})}),f.appendChild(o)}}}function h(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function he(e,t){if(!(g===e&&v&&M===(t||null))){me.style.display="none",V.style.display="none",I.style.display="",I.classList.add("terminal-pending"),Je(),v&&(je(),v.destroy(),v=null),g=e,M=t||null,window.__tmuxWebScopeAgent=M,window.__tmuxWebCurrentSession=g,Yn(e,t);for(let n of f.querySelectorAll(".session-item"))n.classList.toggle("active",n.getAttribute("data-session")===e&&(n.getAttribute("data-agent")||null)===M);try{v=await fn(I,e,{terminal:ue.terminal,scrollback:ue.scrollback,theme:ue.theme,wsBase:M?"/ws/a/"+encodeURIComponent(M):ue.wsBase||"/ws"}),Dt()}catch(n){console.error("[shell] terminal init failed:",n);let s=n&&typeof n=="object"&&"message"in n?n.message:String(n);I.textContent="Failed to open terminal for "+e+": "+s,I.classList.remove("terminal-pending")}}}var He=[],y=null,Et=!1;function kn(e){if(!y||!y.files.length)return null;let t=y.repoRoot;if(!t||!e.startsWith(t))return null;let n=e.slice(t.length+1);for(let s of y.files)if(s.path===n)return s.status;return null}async function Sn(e){Et=!0;try{let t=await fetch(C("/api/git/status?path="+encodeURIComponent(e)));t.ok?y=await t.json():y=null}catch{y=null}finally{Et=!1}}function Tn(){if(!y||!y.branch)return"";let{branch:e,linesAdded:t,linesRemoved:n}=y,s=`<div class="sidebar-git"><div class="git-branch-badge">
15
15
  <svg viewBox="0 0 16 16" fill="currentColor"><path d="M11.63 1.22a.75.75 0 00-1.06 0L5.99 5.8 4.12 3.93a.75.75 0 10-1.06 1.06L4.93 6.87A3.5 3.5 0 003 10.09v3.16a.75.75 0 001 0v-3.16a2.5 2.5 0 012.5-2.5h.27l-1.06 1.06a.75.75 0 001.06 1.06l2.37-2.38a.75.75 0 000-1.06L7.59 5.27l4.04-4.05a.75.75 0 000-1.06L11.63 1.22zM3.25 13.94a.75.75 0 01-.75-.75v-.69a.75.75 0 011.5 0v.69c0 .414-.336.75-.75.75z"/></svg>
16
- ${h(e)}</div>`;return(t>0||n>0)&&(s+=`<div class="git-diff-stats">+<span class="add">${t}</span> <span class="del">-${n}</span></div>`),s+"</div>"}f.addEventListener("click",e=>{e.target.closest(".sidebar-git")&&ee&&y&&(e.stopPropagation(),Tt())});var he=document.getElementById("header-git"),xt=document.getElementById("git-diff-view"),Ct=document.getElementById("gd-path"),He=document.getElementById("gd-status"),Ae=document.getElementById("gd-content"),Mn=document.getElementById("gd-back"),ee=null;function ve(e){if(!e||!e.branch){he.style.display="none",ee=null;return}ee=e.repoRoot;let{branch:t,linesAdded:n,linesRemoved:s}=e,l=`<span class="branch">${h(t)}</span>`;(n>0||s>0)&&(l+=`<span class="sep">\xB7</span>+<span class="diff-add">${n}</span> <span class="diff-del">-${s}</span>`),he.innerHTML=l,he.style.display="block"}he.addEventListener("click",e=>{ee&&y&&(e.stopPropagation(),Tt())});var k=document.getElementById("git-popover"),Fe=document.getElementById("git-popover-backdrop");function Xe(){let e=he.getBoundingClientRect();k.style.top=e.bottom+4+"px",k.style.left=Math.max(8,Math.min(e.left,window.innerWidth-400))+"px"}function kt(){let e=ee,t=document.getElementById("git-popover-browse");t&&t.addEventListener("click",()=>{if($e(),e){qe="files",document.querySelectorAll(".mode-btn").forEach(s=>s.classList.remove("active"));let n=document.getElementById("mode-files");n&&n.classList.add("active"),U(e)}})}var St="";function Tt(){if(!y)return;let e=y.files||[];if(!e.length)k.innerHTML=`<div class="git-popover-header">No changes \u2014 clean working tree</div>
16
+ ${h(e)}</div>`;return(t>0||n>0)&&(s+=`<div class="git-diff-stats">+<span class="add">${t}</span> <span class="del">-${n}</span></div>`),s+"</div>"}f.addEventListener("click",e=>{e.target.closest(".sidebar-git")&&ee&&y&&(e.stopPropagation(),Tt())});var ve=document.getElementById("header-git"),Ct=document.getElementById("git-diff-view"),xt=document.getElementById("gd-path"),Ae=document.getElementById("gd-status"),Fe=document.getElementById("gd-content"),Mn=document.getElementById("gd-back"),ee=null;function ge(e){if(!e||!e.branch){ve.style.display="none",ee=null;return}ee=e.repoRoot;let{branch:t,linesAdded:n,linesRemoved:s}=e,l=`<span class="branch">${h(t)}</span>`;(n>0||s>0)&&(l+=`<span class="sep">\xB7</span>+<span class="diff-add">${n}</span> <span class="diff-del">-${s}</span>`),ve.innerHTML=l,ve.style.display="block"}ve.addEventListener("click",e=>{ee&&y&&(e.stopPropagation(),Tt())});var x=document.getElementById("git-popover"),Ne=document.getElementById("git-popover-backdrop");function Ze(){let e=ve.getBoundingClientRect();x.style.top=e.bottom+4+"px",x.style.left=Math.max(8,Math.min(e.left,window.innerWidth-400))+"px"}function kt(){let e=ee,t=document.getElementById("git-popover-browse");t&&t.addEventListener("click",()=>{if(Pe(),e){Ke="files",document.querySelectorAll(".mode-btn").forEach(s=>s.classList.remove("active"));let n=document.getElementById("mode-files");n&&n.classList.add("active"),O(e)}})}var St="";function Tt(){if(!y)return;let e=y.files||[];if(!e.length)x.innerHTML=`<div class="git-popover-header">No changes \u2014 clean working tree</div>
17
17
  <div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>`;else{let t=`<div class="git-popover-header">${e.length} file${e.length>1?"s":""} changed</div>`;for(let n=0;n<e.length;n++){let s=e[n],l=s.additions||0,r=s.deletions||0,c="";switch(s.status){case"M":c='<span class="git-file-status M">M</span>';break;case"A":c='<span class="git-file-status A">A</span>';break;case"D":c='<span class="git-file-status D">D</span>';break;case"?":c='<span class="git-file-status ?">?</span>';break;case"R":c='<span class="git-file-status R">R</span>';break}t+=`<div class="git-popover-item" data-idx="${n}">
18
18
  ${c}<span class="file-path">${h(s.path)}</span>
19
19
  <span class="file-add">${l>0?"+"+l:""}</span>
20
20
  <span class="file-del">${r>0?"-"+r:""}</span>
21
- </div>`}t+='<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>',St=t,k.innerHTML=t,k.querySelectorAll(".git-popover-item").forEach(n=>{let s=parseInt(n.dataset.idx||"0",10),l=e[s];!l||l.status==="D"||(n.classList.add("clickable"),n.style.cursor="pointer",n.addEventListener("click",()=>It(l.path)))})}Xe(),k.classList.add("open"),Fe.classList.add("open"),kt()}function In(){return window.innerWidth>=1024}function Mt(e,t){let n=(e+(t&&e?`
21
+ </div>`}t+='<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>',St=t,x.innerHTML=t,x.querySelectorAll(".git-popover-item").forEach(n=>{let s=parseInt(n.dataset.idx||"0",10),l=e[s];!l||l.status==="D"||(n.classList.add("clickable"),n.style.cursor="pointer",n.addEventListener("click",()=>Bt(l.path)))})}Ze(),x.classList.add("open"),Ne.classList.add("open"),kt()}function Bn(){return window.innerWidth>=1024}function Mt(e,t){let n=(e+(t&&e?`
22
22
  `:"")+t).split(`
23
- `),s="",l=0,r=0;for(let c of n){let o=c;if(o.startsWith("@@")){let u=o.match(/@@\s+-(\d+)[^+]*\+(\d+)/);u&&(l=parseInt(u[1],10)-1,r=parseInt(u[2],10)-1),s+=`<div class="diff-line hunk"><span class="ln-body">${h(o)}</span></div>`;continue}if(o.startsWith("diff --git")||o.startsWith("index ")||o.startsWith("--- ")||o.startsWith("+++ ")||o.startsWith("new file")||o.startsWith("deleted file")){o.startsWith("diff --git")&&(s+=`<div class="diff-line header"><span class="ln-body">${h(o)}</span></div>`);continue}if(o.startsWith("+"))r++,s+=`<div class="diff-line add"><span class="ln-no">${r}</span><span class="ln-body">${h(o)}</span></div>`;else if(o.startsWith("-"))l++,s+=`<div class="diff-line del"><span class="ln-no">${l}</span><span class="ln-body">${h(o)}</span></div>`;else if(o.startsWith("\\"))s+=`<div class="diff-line"><span class="ln-body">${h(o)}</span></div>`;else{if(!o&&!l&&!r)continue;l++,r++,s+=`<div class="diff-line"><span class="ln-no">${l}</span><span class="ln-no" style="margin-right:12px">${r}</span><span class="ln-body">${h(o)}</span></div>`}}return{html:s,lineCount:n.length}}var Ne=null;async function It(e){let t=ee;if(t)if($e(),In()){B.style.display="none",v&&(Re(),v.destroy(),v=null,Ne=g,g=null),ve(null),pe.style.display="none",V.style.display="none",xt.style.display="flex",Ct.textContent=e,He.textContent="Loading\u2026",Ae.innerHTML="";try{let n=await fetch(C("/api/git/diff?path="+encodeURIComponent(t)+"&file="+encodeURIComponent(e)));if(!n.ok)throw new Error(await n.text());let s=await n.json();Dn(e,s.diff,s.stagedDiff)}catch(n){let s=n instanceof Error?n.message:String(n);He.textContent="Error",Ae.innerHTML=`<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">Error: ${h(s)}</div>`}}else{k.innerHTML=`<div class="git-diff-view"><div class="diff-header">
23
+ `),s="",l=0,r=0;for(let c of n){let o=c;if(o.startsWith("@@")){let u=o.match(/@@\s+-(\d+)[^+]*\+(\d+)/);u&&(l=parseInt(u[1],10)-1,r=parseInt(u[2],10)-1),s+=`<div class="diff-line hunk"><span class="ln-body">${h(o)}</span></div>`;continue}if(o.startsWith("diff --git")||o.startsWith("index ")||o.startsWith("--- ")||o.startsWith("+++ ")||o.startsWith("new file")||o.startsWith("deleted file")){o.startsWith("diff --git")&&(s+=`<div class="diff-line header"><span class="ln-body">${h(o)}</span></div>`);continue}if(o.startsWith("+"))r++,s+=`<div class="diff-line add"><span class="ln-no">${r}</span><span class="ln-body">${h(o)}</span></div>`;else if(o.startsWith("-"))l++,s+=`<div class="diff-line del"><span class="ln-no">${l}</span><span class="ln-body">${h(o)}</span></div>`;else if(o.startsWith("\\"))s+=`<div class="diff-line"><span class="ln-body">${h(o)}</span></div>`;else{if(!o&&!l&&!r)continue;l++,r++,s+=`<div class="diff-line"><span class="ln-no">${l}</span><span class="ln-no" style="margin-right:12px">${r}</span><span class="ln-body">${h(o)}</span></div>`}}return{html:s,lineCount:n.length}}var $e=null;async function Bt(e){let t=ee;if(t)if(Pe(),Bn()){I.style.display="none",v&&(je(),v.destroy(),v=null,$e=g,g=null),ge(null),me.style.display="none",V.style.display="none",Ct.style.display="flex",xt.textContent=e,Ae.textContent="Loading\u2026",Fe.innerHTML="";try{let n=await fetch(C("/api/git/diff?path="+encodeURIComponent(t)+"&file="+encodeURIComponent(e)));if(!n.ok)throw new Error(await n.text());let s=await n.json();Dn(e,s.diff,s.stagedDiff)}catch(n){let s=n instanceof Error?n.message:String(n);Ae.textContent="Error",Fe.innerHTML=`<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">Error: ${h(s)}</div>`}}else{x.innerHTML=`<div class="git-diff-view"><div class="diff-header">
24
24
  <button class="diff-back">\u2190 Back</button>
25
25
  <span class="diff-filename">${h(e)}</span>
26
26
  <span class="diff-loading">Loading\u2026</span>
27
- </div></div>`,Xe(),k.classList.add("open"),Fe.classList.add("open");try{let n=await fetch(C("/api/git/diff?path="+encodeURIComponent(t)+"&file="+encodeURIComponent(e)));if(!n.ok)throw new Error(await n.text());let s=await n.json();Bn(e,s.diff,s.stagedDiff)}catch(n){let s=n instanceof Error?n.message:String(n);k.innerHTML=`<div class="git-diff-view"><div class="diff-header">
27
+ </div></div>`,Ze(),x.classList.add("open"),Ne.classList.add("open");try{let n=await fetch(C("/api/git/diff?path="+encodeURIComponent(t)+"&file="+encodeURIComponent(e)));if(!n.ok)throw new Error(await n.text());let s=await n.json();In(e,s.diff,s.stagedDiff)}catch(n){let s=n instanceof Error?n.message:String(n);x.innerHTML=`<div class="git-diff-view"><div class="diff-header">
28
28
  <button class="diff-back">\u2190 Back</button>
29
29
  <span class="diff-filename">${h(e)}</span>
30
- </div><div class="diff-empty">Error loading diff: ${h(s)}</div></div>`}}}function Bn(e,t,n){if(!t&&!n){k.innerHTML=`<div class="git-diff-view"><div class="diff-header">
30
+ </div><div class="diff-empty">Error loading diff: ${h(s)}</div></div>`}}}function In(e,t,n){if(!t&&!n){x.innerHTML=`<div class="git-diff-view"><div class="diff-header">
31
31
  <button class="diff-back">\u2190 Back</button>
32
32
  <span class="diff-filename">${h(e)}</span>
33
- </div><div class="diff-empty">No diff content available</div></div>`;return}let{html:s,lineCount:l}=Mt(t,n);k.innerHTML=`<div class="git-diff-view"><div class="diff-header">
33
+ </div><div class="diff-empty">No diff content available</div></div>`;return}let{html:s,lineCount:l}=Mt(t,n);x.innerHTML=`<div class="git-diff-view"><div class="diff-header">
34
34
  <button class="diff-back">\u2190 Back</button>
35
35
  <span class="diff-filename">${h(e)}</span>
36
36
  <span class="diff-filesize">${l} lines</span>
37
- </div><div class="diff-content">${s}</div></div>`,k.querySelector(".diff-back")?.addEventListener("click",()=>{k.innerHTML=St,Xe(),y&&k.querySelectorAll(".git-popover-item").forEach(r=>{let c=parseInt(r.dataset.idx||"0",10),o=y.files[c];!o||o.status==="D"||(r.style.cursor="pointer",r.addEventListener("click",()=>It(o.path)))}),kt()})}function Dn(e,t,n){if(!t&&!n){He.textContent="No diff",Ae.innerHTML='<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">No diff content available</div>';return}let{html:s,lineCount:l}=Mt(t,n);Ct.textContent=e,He.textContent=l+" lines",Ae.innerHTML=s}function Hn(){xt.style.display="none",Ne?(B.style.display="",B.classList.add("terminal-pending"),fe(Ne),Ne=null):g?(B.style.display="",B.classList.add("terminal-pending"),Dt()):V.style.display="flex"}Mn.addEventListener("click",Hn);function $e(){k.classList.remove("open"),Fe.classList.remove("open")}Fe.addEventListener("click",$e),document.addEventListener("keydown",e=>{e.key==="Escape"&&($e(),ze())});async function Bt(e){try{let t=await(await fetch("/api/fs/session-path?session="+encodeURIComponent(e))).json();if(t.path){let n=await fetch("/api/git/status?path="+encodeURIComponent(t.path));if(n.ok){let s=await n.json();y=s,ve(s);return}}}catch{}y=null,ve(null)}var Pe=null;function Dt(){Re(),g&&(Bt(g),Pe=setInterval(()=>{g&&Bt(g)},3e4))}function Re(){Pe&&(clearInterval(Pe),Pe=null)}function An(){if(De=ue.fsRoots||[],De.length===0){if(g){Fn(g);return}f.innerHTML='<div class="file-tree-info">Open a session first, then switch to Files to browse its directory.</div>';return}f.innerHTML="";for(let e of De){let t=document.createElement("div");t.className="file-tree-item",t.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${h(e)}`,t.addEventListener("click",()=>U(e)),f.appendChild(t)}}async function Fn(e){f.innerHTML='<div class="file-tree-empty">Loading...</div>';try{let t=await(await fetch(C("/api/fs/session-path?session="+encodeURIComponent(e)))).json();t.path?U(t.path):f.innerHTML='<div class="file-tree-info">Could not determine session directory.</div>'}catch{f.innerHTML='<div class="file-tree-error">Failed to get session directory</div>'}}async function U(e){_=e,f.innerHTML='<div class="file-tree-empty">Loading...</div>';let t=Sn(e);try{let n=await(await fetch(C("/api/fs/list?path="+encodeURIComponent(e)))).json();await t,f.innerHTML="",ve(y),f.innerHTML+=Tn();let s=Nn(e);if(s&&!De.some(r=>e===r)){let r=document.createElement("div");r.className="file-tree-item",r.innerHTML="..",r.addEventListener("click",()=>U(s)),f.appendChild(r)}if(n.dirs)for(let r of n.dirs){let c=r.split("/").pop()||r.split("\\").pop(),o=document.createElement("div");o.className="file-tree-item",o.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${h(c)}`,o.addEventListener("click",()=>U(r)),f.appendChild(o)}else f.innerHTML="";let l=n.files||[];for(let r of l){let c=r.split("/").pop()||r.split("\\").pop(),o=kn(r),u="",p="";if(o)switch(o){case"M":u="git-mod",p='<span class="git-file-status M">M</span>';break;case"A":u="git-add",p='<span class="git-file-status A">A</span>';break;case"D":u="git-del",p='<span class="git-file-status D">D</span>';break;case"?":u="git-untracked",p='<span class="git-file-status ?">?</span>';break;case"R":u="git-mod",p='<span class="git-file-status R">R</span>';break}let S=document.createElement("div");S.className="file-tree-item file"+(u?" "+u:""),S.innerHTML=`<span class="file-icon">\u{1F4C4}</span> ${p}${h(c)}`,S.addEventListener("click",()=>$n(r)),f.appendChild(S)}}catch{f.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function Nn(e){let t=e.lastIndexOf("/");return t<=0?null:e.substring(0,t)}async function $n(e){Ie=e,B.style.display="none",v&&(Re(),v.destroy(),v=null,g=null),ve(null),Ve(),V.style.display="none",pe.style.display="flex",hn.textContent=e,F.textContent="Loading...",J.style.display="none";try{let t=await fetch(C("/api/file?path="+encodeURIComponent(e)));if(!t.ok){let s=await t.json();F.textContent=s.error||"Failed to load",me.value="";return}let n=await t.json();me.value=n.content,Be=n.content,mt=n.content,F.textContent=n.size+" bytes",J.style.display=""}catch{F.textContent="Failed to load",me.value=""}}me.addEventListener("input",()=>{Be=me.value}),J.addEventListener("click",async()=>{J.textContent="Saving...",J.disabled=!0;try{let e=await fetch(C("/api/file"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:Ie,content:Be})});if(!e.ok){let t=await e.json();F.textContent=t.error||"Save failed";return}mt=Be,F.textContent="Saved"}catch{F.textContent="Save failed"}finally{J.disabled=!1,J.textContent="Save"}}),vn.addEventListener("click",async()=>{if(confirm("Delete "+Ie+"?"))try{let e=await fetch(C("/api/file/delete"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:Ie})});if(!e.ok){let t=await e.json();F.textContent=t.error||"Delete failed";return}pe.style.display="none",V.style.display="flex",_&&U(_)}catch{F.textContent="Delete failed"}}),gn.addEventListener("click",()=>{pe.style.display="none",V.style.display="flex",_&&U(_)}),yn.addEventListener("click",async()=>{let e=ft.value.trim();if(!e)return;let t=_+"/"+e;try{let n=await fetch(C("/api/file/touch"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!n.ok){let s=await n.json();F.textContent=s.error||"Create failed";return}ft.value="",_&&U(_)}catch{F.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{let e=ht.classList.toggle("open");Ke.classList.toggle("open",e)}),Ke.addEventListener("click",()=>{ht.classList.remove("open"),Ke.classList.remove("open")});var D="",j=!1,je,ge=document.createElement("div");ge.className="session-popover-backdrop",document.body.appendChild(ge);var N=document.createElement("div");N.id="session-popover",N.className="session-popover",N.style.display="none",N.innerHTML=`<div class="sp-field">
37
+ </div><div class="diff-content">${s}</div></div>`,x.querySelector(".diff-back")?.addEventListener("click",()=>{x.innerHTML=St,Ze(),y&&x.querySelectorAll(".git-popover-item").forEach(r=>{let c=parseInt(r.dataset.idx||"0",10),o=y.files[c];!o||o.status==="D"||(r.style.cursor="pointer",r.addEventListener("click",()=>Bt(o.path)))}),kt()})}function Dn(e,t,n){if(!t&&!n){Ae.textContent="No diff",Fe.innerHTML='<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">No diff content available</div>';return}let{html:s,lineCount:l}=Mt(t,n);xt.textContent=e,Ae.textContent=l+" lines",Fe.innerHTML=s}function Hn(){Ct.style.display="none",$e?(I.style.display="",I.classList.add("terminal-pending"),he($e),$e=null):g?(I.style.display="",I.classList.add("terminal-pending"),Dt()):V.style.display="flex"}Mn.addEventListener("click",Hn);function Pe(){x.classList.remove("open"),Ne.classList.remove("open")}Ne.addEventListener("click",Pe),document.addEventListener("keydown",e=>{e.key==="Escape"&&(Pe(),_e())});async function It(e){try{let t=await(await fetch("/api/fs/session-path?session="+encodeURIComponent(e))).json();if(t.path){let n=await fetch("/api/git/status?path="+encodeURIComponent(t.path));if(n.ok){let s=await n.json();y=s,ge(s);return}}}catch{}y=null,ge(null)}var Re=null;function Dt(){je(),g&&(It(g),Re=setInterval(()=>{g&&It(g)},3e4))}function je(){Re&&(clearInterval(Re),Re=null)}function An(){if(He=ue.fsRoots||[],He.length===0){if(g){Fn(g);return}f.innerHTML='<div class="file-tree-info">Open a session first, then switch to Files to browse its directory.</div>';return}f.innerHTML="";for(let e of He){let t=document.createElement("div");t.className="file-tree-item",t.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${h(e)}`,t.addEventListener("click",()=>O(e)),f.appendChild(t)}}async function Fn(e){f.innerHTML='<div class="file-tree-empty">Loading...</div>';try{let t=await(await fetch(C("/api/fs/session-path?session="+encodeURIComponent(e)))).json();t.path?O(t.path):f.innerHTML='<div class="file-tree-info">Could not determine session directory.</div>'}catch{f.innerHTML='<div class="file-tree-error">Failed to get session directory</div>'}}async function O(e){_=e,f.innerHTML='<div class="file-tree-empty">Loading...</div>';let t=Sn(e);try{let n=await(await fetch(C("/api/fs/list?path="+encodeURIComponent(e)))).json();await t,f.innerHTML="",ge(y),f.innerHTML+=Tn();let s=Nn(e);if(s&&!He.some(r=>e===r)){let r=document.createElement("div");r.className="file-tree-item",r.innerHTML="..",r.addEventListener("click",()=>O(s)),f.appendChild(r)}if(n.dirs)for(let r of n.dirs){let c=r.split("/").pop()||r.split("\\").pop(),o=document.createElement("div");o.className="file-tree-item",o.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${h(c)}`,o.addEventListener("click",()=>O(r)),f.appendChild(o)}else f.innerHTML="";let l=n.files||[];for(let r of l){let c=r.split("/").pop()||r.split("\\").pop(),o=kn(r),u="",p="";if(o)switch(o){case"M":u="git-mod",p='<span class="git-file-status M">M</span>';break;case"A":u="git-add",p='<span class="git-file-status A">A</span>';break;case"D":u="git-del",p='<span class="git-file-status D">D</span>';break;case"?":u="git-untracked",p='<span class="git-file-status ?">?</span>';break;case"R":u="git-mod",p='<span class="git-file-status R">R</span>';break}let k=document.createElement("div");k.className="file-tree-item file"+(u?" "+u:""),k.innerHTML=`<span class="file-icon">\u{1F4C4}</span> ${p}${h(c)}`,k.addEventListener("click",()=>$n(r)),f.appendChild(k)}}catch{f.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function Nn(e){let t=e.lastIndexOf("/");return t<=0?null:e.substring(0,t)}async function $n(e){Ie=e,I.style.display="none",v&&(je(),v.destroy(),v=null,g=null),ge(null),Je(),V.style.display="none",me.style.display="flex",hn.textContent=e,F.textContent="Loading...",J.style.display="none";try{let t=await fetch(C("/api/file?path="+encodeURIComponent(e)));if(!t.ok){let s=await t.json();F.textContent=s.error||"Failed to load",fe.value="";return}let n=await t.json();fe.value=n.content,De=n.content,mt=n.content,F.textContent=n.size+" bytes",J.style.display=""}catch{F.textContent="Failed to load",fe.value=""}}fe.addEventListener("input",()=>{De=fe.value}),J.addEventListener("click",async()=>{J.textContent="Saving...",J.disabled=!0;try{let e=await fetch(C("/api/file"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:Ie,content:De})});if(!e.ok){let t=await e.json();F.textContent=t.error||"Save failed";return}mt=De,F.textContent="Saved"}catch{F.textContent="Save failed"}finally{J.disabled=!1,J.textContent="Save"}}),vn.addEventListener("click",async()=>{if(confirm("Delete "+Ie+"?"))try{let e=await fetch(C("/api/file/delete"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:Ie})});if(!e.ok){let t=await e.json();F.textContent=t.error||"Delete failed";return}me.style.display="none",V.style.display="flex",_&&O(_)}catch{F.textContent="Delete failed"}}),gn.addEventListener("click",()=>{me.style.display="none",V.style.display="flex",_&&O(_)}),yn.addEventListener("click",async()=>{let e=ft.value.trim();if(!e)return;let t=_+"/"+e;try{let n=await fetch(C("/api/file/touch"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!n.ok){let s=await n.json();F.textContent=s.error||"Create failed";return}ft.value="",_&&O(_)}catch{F.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{let e=ht.classList.toggle("open");Ve.classList.toggle("open",e)}),Ve.addEventListener("click",()=>{ht.classList.remove("open"),Ve.classList.remove("open")});var D="",j=!1,ze,ye=document.createElement("div");ye.className="session-popover-backdrop",document.body.appendChild(ye);var N=document.createElement("div");N.id="session-popover",N.className="session-popover",N.style.display="none",N.innerHTML=`<div class="sp-field">
38
38
  <label>Rename session</label>
39
39
  <input type="text" id="sp-name" />
40
40
  </div>
@@ -44,5 +44,5 @@ var dn=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function
44
44
  </div>
45
45
  <hr class="sp-divider" />
46
46
  <button class="btn primary" id="sp-rebuild" style="display:none">\u91CD\u5EFA\u540C\u540D\u540C\u8DEF\u5F84 session</button>
47
- <button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(N);function Pn(e){let t=e.getBoundingClientRect();N.style.top=t.bottom+4+"px",N.style.left=Math.max(8,Math.min(t.left,window.innerWidth-240))+"px"}function Ht(e,t,n){D=e,j=!!n?.tombstone,je=n?.agentId;let s=document.getElementById("sp-name");s.value=e;let l=N.querySelector(".sp-field label");l.textContent=j?"\u91CD\u547D\u540D (\u4EC5\u8BB0\u5F55\uFF0C\u4E0D\u91CD\u5EFA)":"Rename session";let r=document.getElementById("sp-rebuild");r.style.display=j?"":"none";let c=document.getElementById("sp-delete");c.textContent=j?"\u5220\u9664\u5931\u6548\u8BB0\u5F55 (\u5893\u7891\u6D88\u5931)":"Delete session";let o=document.getElementById("sp-save");o.textContent=j?"\u91CD\u547D\u540D":"Save",ge.classList.add("open"),N.style.display="block",Pn(t),setTimeout(()=>s.focus(),50)}function X(){ge.classList.remove("open"),N.style.display="none"}ge.addEventListener("click",X),document.getElementById("sp-save").addEventListener("click",async()=>{let e=document.getElementById("sp-name").value.trim();if(!e||e===D){X();return}try{let t=j?{oldName:D,newName:e,agentId:je}:{oldName:D,newName:e};if(!(await fetch(C(j?"/api/sessions/rename-tombstone":"/api/sessions/rename"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})).ok)return;X(),O(),!j&&g===D&&fe(e)}catch{}}),document.getElementById("sp-rebuild").addEventListener("click",async()=>{if(confirm('\u91CD\u5EFA\u4F1A\u8BDD "'+D+'" (\u540C\u540D\u540C\u8DEF\u5F84\uFF0C\u5185\u5BB9\u4E3A\u7A7A)\uFF1F'))try{let e=await fetch(C("/api/sessions/rebuild"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D,agentId:je})});if(!e.ok){let t=await e.json();alert(t.error||"\u91CD\u5EFA\u5931\u8D25");return}X(),O()}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(j){if(!confirm('\u5220\u9664\u5931\u6548\u8BB0\u5F55 "'+D+'"\uFF1F'))return;try{if(!(await fetch(C("/api/sessions/dismiss"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D,agentId:je})})).ok)return;X(),O()}catch{}return}if(confirm('Delete session "'+D+'"?'))try{if(!(await fetch(C("/api/sessions/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D})})).ok)return;X(),g===D&&(v&&(v.destroy(),v=null),g=null,B.style.display="none",V.style.display="flex"),O()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",X);var Rn={esc:"\x1B",tab:" ","s-tab":"\x1B[Z",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",space:" ",enter:"\r","ctrl-r":"","ctrl-c":"",btw:"/btw ",yes:"yes\r"};document.getElementById("mobile-keys").addEventListener("click",e=>{let t=e.target.closest("button[data-key]");if(!t||!v)return;let n=Rn[t.dataset.key];n&&(v.sendInput(n),v.focus())});var $=document.getElementById("mk-input"),At=document.getElementById("mk-send");function Ft(){if(!$||!v)return;let e=$.value;e&&(v.sendInput(e+"\r"),$.value="",$.rows=1,v.focus())}if($&&($.addEventListener("input",()=>{$.rows=1;let e=$.value.split(`
48
- `).length;$.rows=Math.min(e,4)}),$.addEventListener("keydown",e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),Ft())})),At&&At.addEventListener("click",Ft),window.visualViewport){let e=document.querySelector(".app-layout"),t=()=>{e&&(e.style.height=window.visualViewport.height+"px"),window.scrollTo(0,0),document.documentElement.scrollTop=0,document.body.scrollTop=0};window.visualViewport.addEventListener("resize",t),window.addEventListener("orientationchange",()=>setTimeout(t,100)),document.addEventListener("touchstart",()=>{(window.scrollY>0||document.documentElement.scrollTop>0)&&window.scrollTo(0,0)},{passive:!0})}var Ze=document.getElementById("process-panel"),ye=document.getElementById("proc-list"),jn=document.getElementById("proc-close"),Ge=document.getElementById("proc-backdrop"),zn=document.getElementById("header-ram");function _n(){ye.innerHTML='<div class="proc-empty">Loading\u2026</div>',fetch(C("/api/system/processes")).then(e=>e.json()).then(e=>{if(!Array.isArray(e)||!e.length){ye.innerHTML='<div class="proc-empty">No processes</div>';return}let t="";for(let n of e){let s=n.rss,l=s<1048576?(s/1024).toFixed(0)+"K":(s/1048576).toFixed(1)+"M";t+='<div class="proc-row" data-pid="'+n.pid+'"><span class="proc-mem">'+n.mem+'%</span><span class="proc-rss">'+l+'</span><span class="proc-cmd" title="'+h(n.command)+'">'+h(n.command)+'</span><button class="proc-kill" title="Kill PID '+n.pid+'">&times;</button></div>'}ye.innerHTML=t;for(let n of ye.querySelectorAll(".proc-row")){let s=n.querySelector(".proc-kill");s&&s.addEventListener("click",l=>{let r=l.target.closest(".proc-row");!r||!confirm("Kill PID "+r.dataset.pid+"?")||fetch(C("/api/system/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({pid:parseInt(r.dataset.pid,10)})}).then(c=>c.json()).then(c=>{c.ok?r.style.opacity="0.3":alert("Failed: "+(c.error||"unknown"))}).catch(()=>alert("Network error"))})}}).catch(()=>{ye.innerHTML='<div class="proc-empty">Failed to load</div>'})}function On(){Ze.classList.add("open"),Ge.classList.add("open"),_n()}function ze(){Ze.classList.remove("open"),Ge.classList.remove("open")}zn.addEventListener("click",e=>{e.stopPropagation(),Ze.classList.contains("open")?ze():On()}),jn.addEventListener("click",ze),Ge.addEventListener("click",ze);var Un=2e3,we=null,Qe=null,te=new Map,be=new Map;function Nt(e,t){return(t?"a:"+t+":":"l:")+e}function Wn(e,t,n){let s=Nt(e,t),l=be.get(s),r=e===g&&(t??null)===L,c=n==="idle"&&l?.state==="working";be.set(s,{session:e,agentId:t,state:n,doneUntil:c?Date.now()+Un:void 0,unread:c?!r:!1});let o=t?'.session-item[data-agent="'+CSS.escape(t)+'"][data-session="'+CSS.escape(e)+'"]':'.session-item[data-session="'+CSS.escape(e)+'"]:not([data-agent])',u=f.querySelector(o);u&&et(u,s,be.get(s))}function et(e,t,n){let s=te.get(t);s&&(clearTimeout(s),te.delete(t)),e.classList.remove("working","just-done");let l=n.session===g&&(n.agentId??null)===L;n.state==="working"?e.classList.add("working"):l&&n.doneUntil&&Date.now()<n.doneUntil?(e.classList.add("just-done"),te.set(t,setTimeout(()=>{e.classList.remove("just-done"),te.delete(t)},Math.max(0,n.doneUntil-Date.now())))):!l&&n.unread&&e.classList.add("just-done")}function tt(){for(let[e,t]of be){let n=t.agentId?'.session-item[data-agent="'+CSS.escape(t.agentId)+'"][data-session="'+CSS.escape(t.session)+'"]':'.session-item[data-session="'+CSS.escape(t.session)+'"]:not([data-agent])',s=f.querySelector(n);s&&et(s,e,t)}}function Yn(e,t){let n=Nt(e,t),s=be.get(n);if(!s)return;let l=te.get(n);l&&(clearTimeout(l),te.delete(n)),s.doneUntil=void 0,s.unread=!1;let r=t?'.session-item[data-agent="'+CSS.escape(t)+'"][data-session="'+CSS.escape(e)+'"]':'.session-item[data-session="'+CSS.escape(e)+'"]:not([data-agent])',c=f.querySelector(r);c&&et(c,n,s)}function $t(){if(we||Qe)return;let e=localStorage.getItem("tmux-web-token"),t=(location.protocol==="https:"?"wss:":"ws:")+"//"+location.host+"/ws/activity";e&&(t+="?token="+encodeURIComponent(e));try{let n=new WebSocket(t);we=n,n.onmessage=s=>{try{let l=JSON.parse(String(s.data));l&&l.type==="session.activity"&&typeof l.session=="string"&&Wn(l.session,l.agentId||void 0,l.state==="working"?"working":"idle")}catch{}},n.onclose=()=>{we===n&&(we=null,Qe=setTimeout(()=>{Qe=null,$t()},5e3))},n.onerror=()=>{try{n.close()}catch{}}}catch{we=null}}window.__openSession=fe,window.__refreshSidebar=O,O(),Ve(),tt(),$t(),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&tt()}),setInterval(()=>{document.visibilityState==="visible"&&O()},1e4);
47
+ <button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(N);function Pn(e){let t=e.getBoundingClientRect();N.style.top=t.bottom+4+"px",N.style.left=Math.max(8,Math.min(t.left,window.innerWidth-240))+"px"}function Ht(e,t,n){D=e,j=!!n?.tombstone,ze=n?.agentId;let s=document.getElementById("sp-name");s.value=e;let l=N.querySelector(".sp-field label");l.textContent=j?"\u91CD\u547D\u540D (\u4EC5\u8BB0\u5F55\uFF0C\u4E0D\u91CD\u5EFA)":"Rename session";let r=document.getElementById("sp-rebuild");r.style.display=j?"":"none";let c=document.getElementById("sp-delete");c.textContent=j?"\u5220\u9664\u5931\u6548\u8BB0\u5F55 (\u5893\u7891\u6D88\u5931)":"Delete session";let o=document.getElementById("sp-save");o.textContent=j?"\u91CD\u547D\u540D":"Save",ye.classList.add("open"),N.style.display="block",Pn(t),setTimeout(()=>s.focus(),50)}function X(){ye.classList.remove("open"),N.style.display="none"}ye.addEventListener("click",X),document.getElementById("sp-save").addEventListener("click",async()=>{let e=document.getElementById("sp-name").value.trim();if(!e||e===D){X();return}try{let t=j?{oldName:D,newName:e,agentId:ze}:{oldName:D,newName:e};if(!(await fetch(C(j?"/api/sessions/rename-tombstone":"/api/sessions/rename"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})).ok)return;X(),W(),!j&&g===D&&he(e)}catch{}}),document.getElementById("sp-rebuild").addEventListener("click",async()=>{if(confirm('\u91CD\u5EFA\u4F1A\u8BDD "'+D+'" (\u540C\u540D\u540C\u8DEF\u5F84\uFF0C\u5185\u5BB9\u4E3A\u7A7A)\uFF1F'))try{let e=await fetch(C("/api/sessions/rebuild"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D,agentId:ze})});if(!e.ok){let t=await e.json();alert(t.error||"\u91CD\u5EFA\u5931\u8D25");return}X(),W()}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(j){if(!confirm('\u5220\u9664\u5931\u6548\u8BB0\u5F55 "'+D+'"\uFF1F'))return;try{if(!(await fetch(C("/api/sessions/dismiss"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D,agentId:ze})})).ok)return;X(),W()}catch{}return}if(confirm('Delete session "'+D+'"?'))try{if(!(await fetch(C("/api/sessions/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D})})).ok)return;X(),g===D&&(v&&(v.destroy(),v=null),g=null,I.style.display="none",V.style.display="flex"),W()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",X);var Rn={esc:"\x1B",tab:" ","s-tab":"\x1B[Z",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",space:" ",enter:"\r","ctrl-r":"","ctrl-c":"",btw:"/btw ",yes:"yes\r"};document.getElementById("mobile-keys").addEventListener("click",e=>{let t=e.target.closest("button[data-key]");if(!t||!v)return;let n=Rn[t.dataset.key];n&&(v.sendInput(n),v.focus())});var $=document.getElementById("mk-input"),At=document.getElementById("mk-send");function Ft(){if(!$||!v)return;let e=$.value;e&&(v.sendInput(e+"\r"),$.value="",$.rows=1,v.focus())}if($&&($.addEventListener("input",()=>{$.rows=1;let e=$.value.split(`
48
+ `).length;$.rows=Math.min(e,4)}),$.addEventListener("keydown",e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),Ft())})),At&&At.addEventListener("click",Ft),window.visualViewport){let e=document.querySelector(".app-layout"),t=()=>{e&&(e.style.height=window.visualViewport.height+"px"),window.scrollTo(0,0),document.documentElement.scrollTop=0,document.body.scrollTop=0};window.visualViewport.addEventListener("resize",t),window.addEventListener("orientationchange",()=>setTimeout(t,100)),document.addEventListener("touchstart",()=>{(window.scrollY>0||document.documentElement.scrollTop>0)&&window.scrollTo(0,0)},{passive:!0})}var Ge=document.getElementById("process-panel"),we=document.getElementById("proc-list"),jn=document.getElementById("proc-close"),Qe=document.getElementById("proc-backdrop"),zn=document.getElementById("header-ram");function _n(){we.innerHTML='<div class="proc-empty">Loading\u2026</div>',fetch(C("/api/system/processes")).then(e=>e.json()).then(e=>{if(!Array.isArray(e)||!e.length){we.innerHTML='<div class="proc-empty">No processes</div>';return}let t="";for(let n of e){let s=n.rss,l=s<1048576?(s/1024).toFixed(0)+"K":(s/1048576).toFixed(1)+"M";t+='<div class="proc-row" data-pid="'+n.pid+'"><span class="proc-mem">'+n.mem+'%</span><span class="proc-rss">'+l+'</span><span class="proc-cmd" title="'+h(n.command)+'">'+h(n.command)+'</span><button class="proc-kill" title="Kill PID '+n.pid+'">&times;</button></div>'}we.innerHTML=t;for(let n of we.querySelectorAll(".proc-row")){let s=n.querySelector(".proc-kill");s&&s.addEventListener("click",l=>{let r=l.target.closest(".proc-row");!r||!confirm("Kill PID "+r.dataset.pid+"?")||fetch(C("/api/system/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({pid:parseInt(r.dataset.pid,10)})}).then(c=>c.json()).then(c=>{c.ok?r.style.opacity="0.3":alert("Failed: "+(c.error||"unknown"))}).catch(()=>alert("Network error"))})}}).catch(()=>{we.innerHTML='<div class="proc-empty">Failed to load</div>'})}function Wn(){Ge.classList.add("open"),Qe.classList.add("open"),_n()}function _e(){Ge.classList.remove("open"),Qe.classList.remove("open")}zn.addEventListener("click",e=>{e.stopPropagation(),Ge.classList.contains("open")?_e():Wn()}),jn.addEventListener("click",_e),Qe.addEventListener("click",_e);var On=2e3,be=null,et=null,te=new Map,Le=new Map;function Nt(e,t){return(t?"a:"+t+":":"l:")+e}function Un(e,t,n){let s=Nt(e,t),l=Le.get(s),r=e===g&&(t??null)===M,c=n==="idle"&&l?.state==="working";Le.set(s,{session:e,agentId:t,state:n,doneUntil:c?Date.now()+On:void 0,unread:c?!r:!1});let o=t?'.session-item[data-agent="'+CSS.escape(t)+'"][data-session="'+CSS.escape(e)+'"]':'.session-item[data-session="'+CSS.escape(e)+'"]:not([data-agent])',u=f.querySelector(o);u&&tt(u,s,Le.get(s))}function tt(e,t,n){let s=te.get(t);s&&(clearTimeout(s),te.delete(t)),e.classList.remove("working","just-done");let l=n.session===g&&(n.agentId??null)===M;n.state==="working"?e.classList.add("working"):l&&n.doneUntil&&Date.now()<n.doneUntil?(e.classList.add("just-done"),te.set(t,setTimeout(()=>{e.classList.remove("just-done"),te.delete(t)},Math.max(0,n.doneUntil-Date.now())))):!l&&n.unread&&e.classList.add("just-done")}function nt(){for(let[e,t]of Le){let n=t.agentId?'.session-item[data-agent="'+CSS.escape(t.agentId)+'"][data-session="'+CSS.escape(t.session)+'"]':'.session-item[data-session="'+CSS.escape(t.session)+'"]:not([data-agent])',s=f.querySelector(n);s&&tt(s,e,t)}}function Yn(e,t){let n=Nt(e,t),s=Le.get(n);if(!s)return;let l=te.get(n);l&&(clearTimeout(l),te.delete(n)),s.doneUntil=void 0,s.unread=!1;let r=t?'.session-item[data-agent="'+CSS.escape(t)+'"][data-session="'+CSS.escape(e)+'"]':'.session-item[data-session="'+CSS.escape(e)+'"]:not([data-agent])',c=f.querySelector(r);c&&tt(c,n,s)}function $t(){if(be||et)return;let e=localStorage.getItem("tmux-web-token"),t=(location.protocol==="https:"?"wss:":"ws:")+"//"+location.host+"/ws/activity";e&&(t+="?token="+encodeURIComponent(e));try{let n=new WebSocket(t);be=n,n.onmessage=s=>{try{let l=JSON.parse(String(s.data));l&&l.type==="session.activity"&&typeof l.session=="string"&&Un(l.session,l.agentId||void 0,l.state==="working"?"working":"idle")}catch{}},n.onclose=()=>{be===n&&(be=null,et=setTimeout(()=>{et=null,$t()},5e3))},n.onerror=()=>{try{n.close()}catch{}}}catch{be=null}}window.__openSession=he,window.__refreshSidebar=W,W(),Je(),nt(),$t(),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&nt()}),setInterval(()=>{document.visibilityState==="visible"&&W()},1e4);
@@ -1,33 +1,33 @@
1
- import{initTerminal as Oe}from"./terminal-core.js";const A=window.__TMUX_WEB_SHELL__;let p=null,f=null;const ve=typeof window.__TMUX_WEB_SCOPE__?.agentId=="string"?window.__TMUX_WEB_SCOPE__.agentId:null;let v=ve;window.__tmuxWebScopeAgent=ve;let ie="sessions",I="",G="",q="",ge="";function g(e){return v?"/a/"+encodeURIComponent(v)+e:e}const r=document.getElementById("sidebar-content"),T=document.getElementById("main-placeholder"),b=document.getElementById("terminal-container"),_=document.getElementById("file-editor"),We=document.getElementById("fe-path"),E=document.getElementById("fe-status"),D=document.getElementById("fe-content"),H=document.getElementById("fe-save"),Ue=document.getElementById("fe-delete"),ze=document.getElementById("fe-back"),ye=document.getElementById("fe-new-name"),Fe=document.getElementById("fe-new-btn"),oe=document.getElementById("settings-backdrop"),he=document.getElementById("settings-popover"),be=document.querySelector(".sidebar");function Ge(){return window.matchMedia("(max-width: 640px)").matches}function ae(){Ge()&&be.classList.add("collapsed")}function we(){be.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{we(),Le("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{we(),Le("files")});function Le(e){ie=e,document.querySelectorAll(".mode-btn").forEach(t=>t.classList.remove("active"));const n=document.getElementById(e==="sessions"?"mode-sessions":"mode-files");n&&n.classList.add("active"),e==="sessions"?(le="",B()):ot()}let le="";async function B(){if(ie!=="sessions")return;try{const t=await(await fetch("/api/sidebar/sessions")).json(),s=JSON.stringify({recent:t.recent,agents:t.agents,tombstones:t.tombstones});if(s===le)return;le=s,Xe(t)}catch{r.innerHTML+='<div class="file-tree-empty">Failed to load sessions</div>'}const e=document.getElementById("ns-btn");e&&e.addEventListener("click",()=>{const n=window.__openNewSessionModal;typeof n=="function"?n():document.getElementById("new-session-modal")?.classList.add("open")}),ue()}const Ee="tmux-web-sidebar-group-collapsed";function ke(){try{return new Set(JSON.parse(localStorage.getItem(Ee)||"[]"))}catch{return new Set}}function qe(e){try{localStorage.setItem(Ee,JSON.stringify([...e]))}catch{}}function Ve(e,n,t){if(!e)return"\u2026";const s=t&&(e===t||e.startsWith(t+"/"))?"~"+e.slice(t.length):e,i=s.split("/").filter(Boolean);if(i.length===0)return e;for(let o=1;o<=i.length;o++){const a=i.slice(-o).join("/");if(!n.some(l=>!l||l===e?!1:(t&&(l===t||l.startsWith(t+"/"))?"~"+l.slice(t.length):l).split("/").filter(Boolean).slice(-o).join("/")===a))return a}return s}function Se(e,n,t,s=!0){const i=new Map;for(const c of e){const l=c.path||"";i.has(l)||i.set(l,[]),i.get(l).push(c)}const o=[...i.keys()],a=ke();for(const[c,l]of i){const m=Ve(c,o,n),L=a.has(c),h=document.createElement("div");h.className="session-group-header"+(L?" collapsed":""),h.title=c||"No working directory",h.innerHTML=`<span class="sg-folder">&#128193;</span><span class="sg-label">${d(m)}</span>`,h.addEventListener("click",()=>{const M=ke(),me=h.nextElementSibling;M.has(c)?(M.delete(c),h.classList.remove("collapsed"),me?.classList.remove("collapsed")):(M.add(c),h.classList.add("collapsed"),me?.classList.add("collapsed")),qe(M)});const se=document.createElement("div");se.className="session-group-body"+(L?" collapsed":"");for(const M of l)se.appendChild(t?Je(M,t,s):Ke(M));r.appendChild(h),r.appendChild(se)}}function Je(e,n,t){const s=document.createElement("div");return s.className="session-item"+(e.name===f&&v===n?" active":"")+(t?"":" session-offline"),s.setAttribute("data-session",e.name),s.setAttribute("data-agent",n),s.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${e.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
2
- <span>${d(e.name)}</span>${t?"":'<span class="meta">offline</span>'}`,t&&s.addEventListener("click",i=>{i.target.closest(".session-edit-btn")||P(e.name,n)}),s}function Ke(e){const n=document.createElement("div");n.className="session-item"+(e.name===f&&!v?" active":""),n.setAttribute("data-session",e.name),n.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${e.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
1
+ import{initTerminal as Oe}from"./terminal-core.js";const A=window.__TMUX_WEB_SHELL__;let p=null,f=null;const _=typeof window.__TMUX_WEB_SCOPE__?.agentId=="string"?window.__TMUX_WEB_SCOPE__.agentId:null;let h=_;window.__tmuxWebScopeAgent=_;let oe="sessions",I="",q="",V="",ge="";function v(e){return h?"/a/"+encodeURIComponent(h)+e:e}const r=document.getElementById("sidebar-content"),T=document.getElementById("main-placeholder"),b=document.getElementById("terminal-container"),D=document.getElementById("file-editor"),We=document.getElementById("fe-path"),E=document.getElementById("fe-status"),P=document.getElementById("fe-content"),H=document.getElementById("fe-save"),Ue=document.getElementById("fe-delete"),ze=document.getElementById("fe-back"),ye=document.getElementById("fe-new-name"),Fe=document.getElementById("fe-new-btn"),ae=document.getElementById("settings-backdrop"),he=document.getElementById("settings-popover"),be=document.querySelector(".sidebar");function Ge(){return window.matchMedia("(max-width: 640px)").matches}function le(){Ge()&&be.classList.add("collapsed")}function we(){be.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{we(),Le("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{we(),Le("files")});function Le(e){oe=e,document.querySelectorAll(".mode-btn").forEach(t=>t.classList.remove("active"));const n=document.getElementById(e==="sessions"?"mode-sessions":"mode-files");n&&n.classList.add("active"),e==="sessions"?(ce="",B()):ot()}let ce="";async function B(){if(oe!=="sessions")return;try{const t=await(await fetch("/api/sidebar/sessions")).json(),s=JSON.stringify({recent:t.recent,agents:t.agents,tombstones:t.tombstones});if(s===ce)return;ce=s,Xe(t)}catch{r.innerHTML+='<div class="file-tree-empty">Failed to load sessions</div>'}const e=document.getElementById("ns-btn");e&&e.addEventListener("click",()=>{const n=window.__openNewSessionModal;typeof n=="function"?n():document.getElementById("new-session-modal")?.classList.add("open")}),me()}const Ee="tmux-web-sidebar-group-collapsed";function ke(){try{return new Set(JSON.parse(localStorage.getItem(Ee)||"[]"))}catch{return new Set}}function qe(e){try{localStorage.setItem(Ee,JSON.stringify([...e]))}catch{}}function Ve(e,n,t){if(!e)return"\u2026";const s=t&&(e===t||e.startsWith(t+"/"))?"~"+e.slice(t.length):e,i=s.split("/").filter(Boolean);if(i.length===0)return e;for(let o=1;o<=i.length;o++){const a=i.slice(-o).join("/");if(!n.some(l=>!l||l===e?!1:(t&&(l===t||l.startsWith(t+"/"))?"~"+l.slice(t.length):l).split("/").filter(Boolean).slice(-o).join("/")===a))return a}return s}function Se(e,n,t,s=!0){const i=new Map;for(const c of e){const l=c.path||"";i.has(l)||i.set(l,[]),i.get(l).push(c)}const o=[...i.keys()],a=ke();for(const[c,l]of i){const m=Ve(c,o,n),L=a.has(c),y=document.createElement("div");y.className="session-group-header"+(L?" collapsed":""),y.title=c||"No working directory",y.innerHTML=`<span class="sg-folder">&#128193;</span><span class="sg-label">${d(m)}</span>`,y.addEventListener("click",()=>{const M=ke(),ve=y.nextElementSibling;M.has(c)?(M.delete(c),y.classList.remove("collapsed"),ve?.classList.remove("collapsed")):(M.add(c),y.classList.add("collapsed"),ve?.classList.add("collapsed")),qe(M)});const ie=document.createElement("div");ie.className="session-group-body"+(L?" collapsed":"");for(const M of l)ie.appendChild(t?Je(M,t,s):Ke(M));r.appendChild(y),r.appendChild(ie)}}function Je(e,n,t){const s=document.createElement("div");return s.className="session-item"+(e.name===f&&h===n?" active":"")+(t?"":" session-offline"),s.setAttribute("data-session",e.name),s.setAttribute("data-agent",n),s.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${e.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
2
+ <span>${d(e.name)}</span>${t?"":'<span class="meta">offline</span>'}`,t&&s.addEventListener("click",i=>{i.target.closest(".session-edit-btn")||j(e.name,n)}),s}function Ke(e){const n=document.createElement("div");n.className="session-item"+(e.name===f&&!h?" active":""),n.setAttribute("data-session",e.name),n.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${e.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
3
3
  <span>${d(e.name)}</span>
4
4
  <button class="session-edit-btn" data-session="${d(e.name)}" title="Edit session"><svg viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg></button>
5
- `,n.addEventListener("click",s=>{s.target.closest(".session-edit-btn")||P(e.name)});const t=n.querySelector(".session-edit-btn");return t&&t.addEventListener("click",s=>{s.stopPropagation(),Ae(e.name,t)}),n}function Xe(e){r.innerHTML='<button class="new-session-sidebar-btn" id="ns-btn">+ New Session</button>';const n=e.recent||[],t=document.createElement("div");t.className="sidebar-section-label"+(v?" clickable":""),t.textContent=v?"\u2190 \u8FD4\u56DE\u672C\u673A":"\u672C\u673A",v&&(t.title="Back to hub",t.addEventListener("click",()=>{window.location.href="/"})),r.appendChild(t),Se(n,e.home);const s=e.agents||[];for(const o of s){if(!o.sessions||o.sessions.length===0)continue;const a=o.agentId===v,c=document.createElement("div");c.className="sidebar-section-label machine-label"+(o.online?"":" agent-offline-label")+(!a&&o.online?" clickable":""),c.textContent=o.agentName+(o.online?"":" (offline)"),!a&&o.online&&(c.title="\u6253\u5F00 "+o.agentName,c.addEventListener("click",()=>{window.location.href="/a/"+encodeURIComponent(o.agentId)+"/"})),r.appendChild(c),Se(o.sessions,e.home,o.agentId,o.online)}const i=e.tombstones||[];if(i.length>0){const o=document.createElement("div");o.className="sidebar-section-label tombstone-label",o.textContent="\u5931\u6548\u4F1A\u8BDD",r.appendChild(o);for(const a of i){const c=document.createElement("div");c.className="session-item session-tombstone",c.setAttribute("data-session",a.name),a.agentId&&c.setAttribute("data-agent",a.agentId);const l=a.agentId?a.agentOnline?" (agent)":" (agent \u79BB\u7EBF)":"";c.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"></svg>
5
+ `,n.addEventListener("click",s=>{s.target.closest(".session-edit-btn")||j(e.name)});const t=n.querySelector(".session-edit-btn");return t&&t.addEventListener("click",s=>{s.stopPropagation(),Ae(e.name,t)}),n}function Xe(e){r.innerHTML='<button class="new-session-sidebar-btn" id="ns-btn">+ New Session</button>';const n=e.recent||[],t=document.createElement("div");t.className="sidebar-section-label"+(_?" clickable":""),t.textContent=_?"\u2190 \u8FD4\u56DE\u672C\u673A":"\u672C\u673A",_&&(t.title="Back to hub",t.addEventListener("click",()=>{window.location.href="/"})),r.appendChild(t),Se(n,e.home);const s=e.agents||[];for(const o of s){if(!o.sessions||o.sessions.length===0)continue;const a=o.agentId===h,c=document.createElement("div");c.className="sidebar-section-label machine-label"+(o.online?"":" agent-offline-label")+(!a&&o.online?" clickable":""),c.textContent=o.agentName+(o.online?"":" (offline)"),!a&&o.online&&(c.title="\u6253\u5F00 "+o.agentName,c.addEventListener("click",()=>{window.location.href="/a/"+encodeURIComponent(o.agentId)+"/"})),r.appendChild(c),Se(o.sessions,e.home,o.agentId,o.online)}const i=e.tombstones||[];if(i.length>0){const o=document.createElement("div");o.className="sidebar-section-label tombstone-label",o.textContent="\u5931\u6548\u4F1A\u8BDD",r.appendChild(o);for(const a of i){const c=document.createElement("div");c.className="session-item session-tombstone",c.setAttribute("data-session",a.name),a.agentId&&c.setAttribute("data-agent",a.agentId);const l=a.agentId?a.agentOnline?" (agent)":" (agent \u79BB\u7EBF)":"";c.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"></svg>
6
6
  <span>${d(a.name)}</span><span class="meta">\u5931\u6548${l}</span>
7
- <button class="session-edit-btn" data-session="${d(a.name)}" title="\u6062\u590D\u4F1A\u8BDD"><svg viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg></button>`;const m=c.querySelector(".session-edit-btn");m&&m.addEventListener("click",L=>{L.stopPropagation(),Ae(a.name,m,{tombstone:!0,agentId:a.agentId})}),r.appendChild(c)}}}function d(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function P(e,n){if(!(f===e&&p&&v===(n||null))){_.style.display="none",T.style.display="none",b.style.display="",b.classList.add("terminal-pending"),ae(),p&&(ee(),p.destroy(),p=null),f=e,v=n||null,window.__tmuxWebScopeAgent=v,window.__tmuxWebCurrentSession=f,yt(e,n);for(const t of r.querySelectorAll(".session-item"))t.classList.toggle("active",t.getAttribute("data-session")===e&&(t.getAttribute("data-agent")||null)===v);try{p=await Oe(b,e,{terminal:A.terminal,scrollback:A.scrollback,theme:A.theme,wsBase:v?"/ws/a/"+encodeURIComponent(v):A.wsBase||"/ws"}),$e()}catch(t){console.error("[shell] terminal init failed:",t);const s=t&&typeof t=="object"&&"message"in t?t.message:String(t);b.textContent="Failed to open terminal for "+e+": "+s,b.classList.remove("terminal-pending")}}}let V=[],u=null,Ce=!1;function Ye(e){if(!u||!u.files.length)return null;const n=u.repoRoot;if(!n||!e.startsWith(n))return null;const t=e.slice(n.length+1);for(const s of u.files)if(s.path===t)return s.status;return null}async function Ze(e){Ce=!0;try{const n=await fetch(g("/api/git/status?path="+encodeURIComponent(e)));n.ok?u=await n.json():u=null}catch{u=null}finally{Ce=!1}}function Qe(){if(!u||!u.branch)return"";const{branch:e,linesAdded:n,linesRemoved:t}=u;let s=`<div class="sidebar-git"><div class="git-branch-badge">
7
+ <button class="session-edit-btn" data-session="${d(a.name)}" title="\u6062\u590D\u4F1A\u8BDD"><svg viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg></button>`;const m=c.querySelector(".session-edit-btn");m&&m.addEventListener("click",L=>{L.stopPropagation(),Ae(a.name,m,{tombstone:!0,agentId:a.agentId})}),r.appendChild(c)}}}function d(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function j(e,n){if(!(f===e&&p&&h===(n||null))){D.style.display="none",T.style.display="none",b.style.display="",b.classList.add("terminal-pending"),le(),p&&(te(),p.destroy(),p=null),f=e,h=n||null,window.__tmuxWebScopeAgent=h,window.__tmuxWebCurrentSession=f,yt(e,n);for(const t of r.querySelectorAll(".session-item"))t.classList.toggle("active",t.getAttribute("data-session")===e&&(t.getAttribute("data-agent")||null)===h);try{p=await Oe(b,e,{terminal:A.terminal,scrollback:A.scrollback,theme:A.theme,wsBase:h?"/ws/a/"+encodeURIComponent(h):A.wsBase||"/ws"}),$e()}catch(t){console.error("[shell] terminal init failed:",t);const s=t&&typeof t=="object"&&"message"in t?t.message:String(t);b.textContent="Failed to open terminal for "+e+": "+s,b.classList.remove("terminal-pending")}}}let J=[],u=null,Ce=!1;function Ye(e){if(!u||!u.files.length)return null;const n=u.repoRoot;if(!n||!e.startsWith(n))return null;const t=e.slice(n.length+1);for(const s of u.files)if(s.path===t)return s.status;return null}async function Ze(e){Ce=!0;try{const n=await fetch(v("/api/git/status?path="+encodeURIComponent(e)));n.ok?u=await n.json():u=null}catch{u=null}finally{Ce=!1}}function Qe(){if(!u||!u.branch)return"";const{branch:e,linesAdded:n,linesRemoved:t}=u;let s=`<div class="sidebar-git"><div class="git-branch-badge">
8
8
  <svg viewBox="0 0 16 16" fill="currentColor"><path d="M11.63 1.22a.75.75 0 00-1.06 0L5.99 5.8 4.12 3.93a.75.75 0 10-1.06 1.06L4.93 6.87A3.5 3.5 0 003 10.09v3.16a.75.75 0 001 0v-3.16a2.5 2.5 0 012.5-2.5h.27l-1.06 1.06a.75.75 0 001.06 1.06l2.37-2.38a.75.75 0 000-1.06L7.59 5.27l4.04-4.05a.75.75 0 000-1.06L11.63 1.22zM3.25 13.94a.75.75 0 01-.75-.75v-.69a.75.75 0 011.5 0v.69c0 .414-.336.75-.75.75z"/></svg>
9
- ${d(e)}</div>`;return(n>0||t>0)&&(s+=`<div class="git-diff-stats">+<span class="add">${n}</span> <span class="del">-${t}</span></div>`),s+"</div>"}r.addEventListener("click",e=>{e.target.closest(".sidebar-git")&&R&&u&&(e.stopPropagation(),Te())});const j=document.getElementById("header-git"),Ie=document.getElementById("git-diff-view"),Be=document.getElementById("gd-path"),J=document.getElementById("gd-status"),K=document.getElementById("gd-content"),et=document.getElementById("gd-back");let R=null;function O(e){if(!e||!e.branch){j.style.display="none",R=null;return}R=e.repoRoot;const{branch:n,linesAdded:t,linesRemoved:s}=e;let i=`<span class="branch">${d(n)}</span>`;(t>0||s>0)&&(i+=`<span class="sep">\xB7</span>+<span class="diff-add">${t}</span> <span class="diff-del">-${s}</span>`),j.innerHTML=i,j.style.display="block"}j.addEventListener("click",e=>{R&&u&&(e.stopPropagation(),Te())});const y=document.getElementById("git-popover"),X=document.getElementById("git-popover-backdrop");function ce(){const e=j.getBoundingClientRect();y.style.top=e.bottom+4+"px",y.style.left=Math.max(8,Math.min(e.left,window.innerWidth-400))+"px"}function xe(){const e=R,n=document.getElementById("git-popover-browse");n&&n.addEventListener("click",()=>{if(Z(),e){ie="files",document.querySelectorAll(".mode-btn").forEach(s=>s.classList.remove("active"));const t=document.getElementById("mode-files");t&&t.classList.add("active"),x(e)}})}let Me="";function Te(){if(!u)return;const e=u.files||[];if(!e.length)y.innerHTML=`<div class="git-popover-header">No changes \u2014 clean working tree</div>
9
+ ${d(e)}</div>`;return(n>0||t>0)&&(s+=`<div class="git-diff-stats">+<span class="add">${n}</span> <span class="del">-${t}</span></div>`),s+"</div>"}r.addEventListener("click",e=>{e.target.closest(".sidebar-git")&&R&&u&&(e.stopPropagation(),Te())});const O=document.getElementById("header-git"),Ie=document.getElementById("git-diff-view"),Be=document.getElementById("gd-path"),K=document.getElementById("gd-status"),X=document.getElementById("gd-content"),et=document.getElementById("gd-back");let R=null;function W(e){if(!e||!e.branch){O.style.display="none",R=null;return}R=e.repoRoot;const{branch:n,linesAdded:t,linesRemoved:s}=e;let i=`<span class="branch">${d(n)}</span>`;(t>0||s>0)&&(i+=`<span class="sep">\xB7</span>+<span class="diff-add">${t}</span> <span class="diff-del">-${s}</span>`),O.innerHTML=i,O.style.display="block"}O.addEventListener("click",e=>{R&&u&&(e.stopPropagation(),Te())});const g=document.getElementById("git-popover"),Y=document.getElementById("git-popover-backdrop");function re(){const e=O.getBoundingClientRect();g.style.top=e.bottom+4+"px",g.style.left=Math.max(8,Math.min(e.left,window.innerWidth-400))+"px"}function xe(){const e=R,n=document.getElementById("git-popover-browse");n&&n.addEventListener("click",()=>{if(Q(),e){oe="files",document.querySelectorAll(".mode-btn").forEach(s=>s.classList.remove("active"));const t=document.getElementById("mode-files");t&&t.classList.add("active"),x(e)}})}let Me="";function Te(){if(!u)return;const e=u.files||[];if(!e.length)g.innerHTML=`<div class="git-popover-header">No changes \u2014 clean working tree</div>
10
10
  <div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>`;else{let n=`<div class="git-popover-header">${e.length} file${e.length>1?"s":""} changed</div>`;for(let t=0;t<e.length;t++){const s=e[t],i=s.additions||0,o=s.deletions||0;let a="";switch(s.status){case"M":a='<span class="git-file-status M">M</span>';break;case"A":a='<span class="git-file-status A">A</span>';break;case"D":a='<span class="git-file-status D">D</span>';break;case"?":a='<span class="git-file-status ?">?</span>';break;case"R":a='<span class="git-file-status R">R</span>';break}n+=`<div class="git-popover-item" data-idx="${t}">
11
11
  ${a}<span class="file-path">${d(s.path)}</span>
12
12
  <span class="file-add">${i>0?"+"+i:""}</span>
13
13
  <span class="file-del">${o>0?"-"+o:""}</span>
14
- </div>`}n+='<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>',Me=n,y.innerHTML=n,y.querySelectorAll(".git-popover-item").forEach(t=>{const s=parseInt(t.dataset.idx||"0",10),i=e[s];!i||i.status==="D"||(t.classList.add("clickable"),t.style.cursor="pointer",t.addEventListener("click",()=>Ne(i.path)))})}ce(),y.classList.add("open"),X.classList.add("open"),xe()}function tt(){return window.innerWidth>=1024}function He(e,n){const s=(e+(n&&e?`
14
+ </div>`}n+='<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>',Me=n,g.innerHTML=n,g.querySelectorAll(".git-popover-item").forEach(t=>{const s=parseInt(t.dataset.idx||"0",10),i=e[s];!i||i.status==="D"||(t.classList.add("clickable"),t.style.cursor="pointer",t.addEventListener("click",()=>Ne(i.path)))})}re(),g.classList.add("open"),Y.classList.add("open"),xe()}function tt(){return window.innerWidth>=1024}function He(e,n){const s=(e+(n&&e?`
15
15
  `:"")+n).split(`
16
- `);let i="",o=0,a=0;for(const c of s){const l=c;if(l.startsWith("@@")){const m=l.match(/@@\s+-(\d+)[^+]*\+(\d+)/);m&&(o=parseInt(m[1],10)-1,a=parseInt(m[2],10)-1),i+=`<div class="diff-line hunk"><span class="ln-body">${d(l)}</span></div>`;continue}if(l.startsWith("diff --git")||l.startsWith("index ")||l.startsWith("--- ")||l.startsWith("+++ ")||l.startsWith("new file")||l.startsWith("deleted file")){l.startsWith("diff --git")&&(i+=`<div class="diff-line header"><span class="ln-body">${d(l)}</span></div>`);continue}if(l.startsWith("+"))a++,i+=`<div class="diff-line add"><span class="ln-no">${a}</span><span class="ln-body">${d(l)}</span></div>`;else if(l.startsWith("-"))o++,i+=`<div class="diff-line del"><span class="ln-no">${o}</span><span class="ln-body">${d(l)}</span></div>`;else if(l.startsWith("\\"))i+=`<div class="diff-line"><span class="ln-body">${d(l)}</span></div>`;else{if(!l&&!o&&!a)continue;o++,a++,i+=`<div class="diff-line"><span class="ln-no">${o}</span><span class="ln-no" style="margin-right:12px">${a}</span><span class="ln-body">${d(l)}</span></div>`}}return{html:i,lineCount:s.length}}let Y=null;async function Ne(e){const n=R;if(n)if(Z(),tt()){b.style.display="none",p&&(ee(),p.destroy(),p=null,Y=f,f=null),O(null),_.style.display="none",T.style.display="none",Ie.style.display="flex",Be.textContent=e,J.textContent="Loading\u2026",K.innerHTML="";try{const t=await fetch(g("/api/git/diff?path="+encodeURIComponent(n)+"&file="+encodeURIComponent(e)));if(!t.ok)throw new Error(await t.text());const s=await t.json();st(e,s.diff,s.stagedDiff)}catch(t){const s=t instanceof Error?t.message:String(t);J.textContent="Error",K.innerHTML=`<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">Error: ${d(s)}</div>`}}else{y.innerHTML=`<div class="git-diff-view"><div class="diff-header">
16
+ `);let i="",o=0,a=0;for(const c of s){const l=c;if(l.startsWith("@@")){const m=l.match(/@@\s+-(\d+)[^+]*\+(\d+)/);m&&(o=parseInt(m[1],10)-1,a=parseInt(m[2],10)-1),i+=`<div class="diff-line hunk"><span class="ln-body">${d(l)}</span></div>`;continue}if(l.startsWith("diff --git")||l.startsWith("index ")||l.startsWith("--- ")||l.startsWith("+++ ")||l.startsWith("new file")||l.startsWith("deleted file")){l.startsWith("diff --git")&&(i+=`<div class="diff-line header"><span class="ln-body">${d(l)}</span></div>`);continue}if(l.startsWith("+"))a++,i+=`<div class="diff-line add"><span class="ln-no">${a}</span><span class="ln-body">${d(l)}</span></div>`;else if(l.startsWith("-"))o++,i+=`<div class="diff-line del"><span class="ln-no">${o}</span><span class="ln-body">${d(l)}</span></div>`;else if(l.startsWith("\\"))i+=`<div class="diff-line"><span class="ln-body">${d(l)}</span></div>`;else{if(!l&&!o&&!a)continue;o++,a++,i+=`<div class="diff-line"><span class="ln-no">${o}</span><span class="ln-no" style="margin-right:12px">${a}</span><span class="ln-body">${d(l)}</span></div>`}}return{html:i,lineCount:s.length}}let Z=null;async function Ne(e){const n=R;if(n)if(Q(),tt()){b.style.display="none",p&&(te(),p.destroy(),p=null,Z=f,f=null),W(null),D.style.display="none",T.style.display="none",Ie.style.display="flex",Be.textContent=e,K.textContent="Loading\u2026",X.innerHTML="";try{const t=await fetch(v("/api/git/diff?path="+encodeURIComponent(n)+"&file="+encodeURIComponent(e)));if(!t.ok)throw new Error(await t.text());const s=await t.json();st(e,s.diff,s.stagedDiff)}catch(t){const s=t instanceof Error?t.message:String(t);K.textContent="Error",X.innerHTML=`<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">Error: ${d(s)}</div>`}}else{g.innerHTML=`<div class="git-diff-view"><div class="diff-header">
17
17
  <button class="diff-back">\u2190 Back</button>
18
18
  <span class="diff-filename">${d(e)}</span>
19
19
  <span class="diff-loading">Loading\u2026</span>
20
- </div></div>`,ce(),y.classList.add("open"),X.classList.add("open");try{const t=await fetch(g("/api/git/diff?path="+encodeURIComponent(n)+"&file="+encodeURIComponent(e)));if(!t.ok)throw new Error(await t.text());const s=await t.json();nt(e,s.diff,s.stagedDiff)}catch(t){const s=t instanceof Error?t.message:String(t);y.innerHTML=`<div class="git-diff-view"><div class="diff-header">
20
+ </div></div>`,re(),g.classList.add("open"),Y.classList.add("open");try{const t=await fetch(v("/api/git/diff?path="+encodeURIComponent(n)+"&file="+encodeURIComponent(e)));if(!t.ok)throw new Error(await t.text());const s=await t.json();nt(e,s.diff,s.stagedDiff)}catch(t){const s=t instanceof Error?t.message:String(t);g.innerHTML=`<div class="git-diff-view"><div class="diff-header">
21
21
  <button class="diff-back">\u2190 Back</button>
22
22
  <span class="diff-filename">${d(e)}</span>
23
- </div><div class="diff-empty">Error loading diff: ${d(s)}</div></div>`}}}function nt(e,n,t){if(!n&&!t){y.innerHTML=`<div class="git-diff-view"><div class="diff-header">
23
+ </div><div class="diff-empty">Error loading diff: ${d(s)}</div></div>`}}}function nt(e,n,t){if(!n&&!t){g.innerHTML=`<div class="git-diff-view"><div class="diff-header">
24
24
  <button class="diff-back">\u2190 Back</button>
25
25
  <span class="diff-filename">${d(e)}</span>
26
- </div><div class="diff-empty">No diff content available</div></div>`;return}const{html:s,lineCount:i}=He(n,t);y.innerHTML=`<div class="git-diff-view"><div class="diff-header">
26
+ </div><div class="diff-empty">No diff content available</div></div>`;return}const{html:s,lineCount:i}=He(n,t);g.innerHTML=`<div class="git-diff-view"><div class="diff-header">
27
27
  <button class="diff-back">\u2190 Back</button>
28
28
  <span class="diff-filename">${d(e)}</span>
29
29
  <span class="diff-filesize">${i} lines</span>
30
- </div><div class="diff-content">${s}</div></div>`,y.querySelector(".diff-back")?.addEventListener("click",()=>{y.innerHTML=Me,ce(),u&&y.querySelectorAll(".git-popover-item").forEach(o=>{const a=parseInt(o.dataset.idx||"0",10),c=u.files[a];!c||c.status==="D"||(o.style.cursor="pointer",o.addEventListener("click",()=>Ne(c.path)))}),xe()})}function st(e,n,t){if(!n&&!t){J.textContent="No diff",K.innerHTML='<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">No diff content available</div>';return}const{html:s,lineCount:i}=He(n,t);Be.textContent=e,J.textContent=i+" lines",K.innerHTML=s}function it(){Ie.style.display="none",Y?(b.style.display="",b.classList.add("terminal-pending"),P(Y),Y=null):f?(b.style.display="",b.classList.add("terminal-pending"),$e()):T.style.display="flex"}et.addEventListener("click",it);function Z(){y.classList.remove("open"),X.classList.remove("open")}X.addEventListener("click",Z),document.addEventListener("keydown",e=>{e.key==="Escape"&&(Z(),ne())});async function Re(e){try{const t=await(await fetch("/api/fs/session-path?session="+encodeURIComponent(e))).json();if(t.path){const s=await fetch("/api/git/status?path="+encodeURIComponent(t.path));if(s.ok){const i=await s.json();u=i,O(i);return}}}catch{}u=null,O(null)}let Q=null;function $e(){ee(),f&&(Re(f),Q=setInterval(()=>{f&&Re(f)},3e4))}function ee(){Q&&(clearInterval(Q),Q=null)}function ot(){if(V=A.fsRoots||[],V.length===0){if(f){at(f);return}r.innerHTML='<div class="file-tree-info">Open a session first, then switch to Files to browse its directory.</div>';return}r.innerHTML="";for(const e of V){const n=document.createElement("div");n.className="file-tree-item",n.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${d(e)}`,n.addEventListener("click",()=>x(e)),r.appendChild(n)}}async function at(e){r.innerHTML='<div class="file-tree-empty">Loading...</div>';try{const t=await(await fetch(g("/api/fs/session-path?session="+encodeURIComponent(e)))).json();t.path?x(t.path):r.innerHTML='<div class="file-tree-info">Could not determine session directory.</div>'}catch{r.innerHTML='<div class="file-tree-error">Failed to get session directory</div>'}}async function x(e){I=e,r.innerHTML='<div class="file-tree-empty">Loading...</div>';const n=Ze(e);try{const s=await(await fetch(g("/api/fs/list?path="+encodeURIComponent(e)))).json();await n,r.innerHTML="",O(u),r.innerHTML+=Qe();const i=lt(e);if(i&&!V.some(c=>e===c)){const c=document.createElement("div");c.className="file-tree-item",c.innerHTML="..",c.addEventListener("click",()=>x(i)),r.appendChild(c)}if(s.dirs)for(const a of s.dirs){const c=a.split("/").pop()||a.split("\\").pop(),l=document.createElement("div");l.className="file-tree-item",l.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${d(c)}`,l.addEventListener("click",()=>x(a)),r.appendChild(l)}else r.innerHTML="";const o=s.files||[];for(const a of o){const c=a.split("/").pop()||a.split("\\").pop(),l=Ye(a);let m="",L="";if(l)switch(l){case"M":m="git-mod",L='<span class="git-file-status M">M</span>';break;case"A":m="git-add",L='<span class="git-file-status A">A</span>';break;case"D":m="git-del",L='<span class="git-file-status D">D</span>';break;case"?":m="git-untracked",L='<span class="git-file-status ?">?</span>';break;case"R":m="git-mod",L='<span class="git-file-status R">R</span>';break}const h=document.createElement("div");h.className="file-tree-item file"+(m?" "+m:""),h.innerHTML=`<span class="file-icon">\u{1F4C4}</span> ${L}${d(c)}`,h.addEventListener("click",()=>ct(a)),r.appendChild(h)}}catch{r.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function lt(e){const n=e.lastIndexOf("/");return n<=0?null:e.substring(0,n)}async function ct(e){G=e,b.style.display="none",p&&(ee(),p.destroy(),p=null,f=null),O(null),ae(),T.style.display="none",_.style.display="flex",We.textContent=e,E.textContent="Loading...",H.style.display="none";try{const n=await fetch(g("/api/file?path="+encodeURIComponent(e)));if(!n.ok){const s=await n.json();E.textContent=s.error||"Failed to load",D.value="";return}const t=await n.json();D.value=t.content,q=t.content,ge=t.content,E.textContent=t.size+" bytes",H.style.display=""}catch{E.textContent="Failed to load",D.value=""}}D.addEventListener("input",()=>{q=D.value}),H.addEventListener("click",async()=>{H.textContent="Saving...",H.disabled=!0;try{const e=await fetch(g("/api/file"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:G,content:q})});if(!e.ok){const n=await e.json();E.textContent=n.error||"Save failed";return}ge=q,E.textContent="Saved"}catch{E.textContent="Save failed"}finally{H.disabled=!1,H.textContent="Save"}}),Ue.addEventListener("click",async()=>{if(confirm("Delete "+G+"?"))try{const e=await fetch(g("/api/file/delete"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:G})});if(!e.ok){const n=await e.json();E.textContent=n.error||"Delete failed";return}_.style.display="none",T.style.display="flex",I&&x(I)}catch{E.textContent="Delete failed"}}),ze.addEventListener("click",()=>{_.style.display="none",T.style.display="flex",I&&x(I)}),Fe.addEventListener("click",async()=>{const e=ye.value.trim();if(!e)return;const n=I+"/"+e;try{const t=await fetch(g("/api/file/touch"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:n})});if(!t.ok){const s=await t.json();E.textContent=s.error||"Create failed";return}ye.value="",I&&x(I)}catch{E.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{const e=he.classList.toggle("open");oe.classList.toggle("open",e)}),oe.addEventListener("click",()=>{he.classList.remove("open"),oe.classList.remove("open")});let w="",C=!1,te;const W=document.createElement("div");W.className="session-popover-backdrop",document.body.appendChild(W);const k=document.createElement("div");k.id="session-popover",k.className="session-popover",k.style.display="none",k.innerHTML=`<div class="sp-field">
30
+ </div><div class="diff-content">${s}</div></div>`,g.querySelector(".diff-back")?.addEventListener("click",()=>{g.innerHTML=Me,re(),u&&g.querySelectorAll(".git-popover-item").forEach(o=>{const a=parseInt(o.dataset.idx||"0",10),c=u.files[a];!c||c.status==="D"||(o.style.cursor="pointer",o.addEventListener("click",()=>Ne(c.path)))}),xe()})}function st(e,n,t){if(!n&&!t){K.textContent="No diff",X.innerHTML='<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">No diff content available</div>';return}const{html:s,lineCount:i}=He(n,t);Be.textContent=e,K.textContent=i+" lines",X.innerHTML=s}function it(){Ie.style.display="none",Z?(b.style.display="",b.classList.add("terminal-pending"),j(Z),Z=null):f?(b.style.display="",b.classList.add("terminal-pending"),$e()):T.style.display="flex"}et.addEventListener("click",it);function Q(){g.classList.remove("open"),Y.classList.remove("open")}Y.addEventListener("click",Q),document.addEventListener("keydown",e=>{e.key==="Escape"&&(Q(),se())});async function Re(e){try{const t=await(await fetch("/api/fs/session-path?session="+encodeURIComponent(e))).json();if(t.path){const s=await fetch("/api/git/status?path="+encodeURIComponent(t.path));if(s.ok){const i=await s.json();u=i,W(i);return}}}catch{}u=null,W(null)}let ee=null;function $e(){te(),f&&(Re(f),ee=setInterval(()=>{f&&Re(f)},3e4))}function te(){ee&&(clearInterval(ee),ee=null)}function ot(){if(J=A.fsRoots||[],J.length===0){if(f){at(f);return}r.innerHTML='<div class="file-tree-info">Open a session first, then switch to Files to browse its directory.</div>';return}r.innerHTML="";for(const e of J){const n=document.createElement("div");n.className="file-tree-item",n.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${d(e)}`,n.addEventListener("click",()=>x(e)),r.appendChild(n)}}async function at(e){r.innerHTML='<div class="file-tree-empty">Loading...</div>';try{const t=await(await fetch(v("/api/fs/session-path?session="+encodeURIComponent(e)))).json();t.path?x(t.path):r.innerHTML='<div class="file-tree-info">Could not determine session directory.</div>'}catch{r.innerHTML='<div class="file-tree-error">Failed to get session directory</div>'}}async function x(e){I=e,r.innerHTML='<div class="file-tree-empty">Loading...</div>';const n=Ze(e);try{const s=await(await fetch(v("/api/fs/list?path="+encodeURIComponent(e)))).json();await n,r.innerHTML="",W(u),r.innerHTML+=Qe();const i=lt(e);if(i&&!J.some(c=>e===c)){const c=document.createElement("div");c.className="file-tree-item",c.innerHTML="..",c.addEventListener("click",()=>x(i)),r.appendChild(c)}if(s.dirs)for(const a of s.dirs){const c=a.split("/").pop()||a.split("\\").pop(),l=document.createElement("div");l.className="file-tree-item",l.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${d(c)}`,l.addEventListener("click",()=>x(a)),r.appendChild(l)}else r.innerHTML="";const o=s.files||[];for(const a of o){const c=a.split("/").pop()||a.split("\\").pop(),l=Ye(a);let m="",L="";if(l)switch(l){case"M":m="git-mod",L='<span class="git-file-status M">M</span>';break;case"A":m="git-add",L='<span class="git-file-status A">A</span>';break;case"D":m="git-del",L='<span class="git-file-status D">D</span>';break;case"?":m="git-untracked",L='<span class="git-file-status ?">?</span>';break;case"R":m="git-mod",L='<span class="git-file-status R">R</span>';break}const y=document.createElement("div");y.className="file-tree-item file"+(m?" "+m:""),y.innerHTML=`<span class="file-icon">\u{1F4C4}</span> ${L}${d(c)}`,y.addEventListener("click",()=>ct(a)),r.appendChild(y)}}catch{r.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function lt(e){const n=e.lastIndexOf("/");return n<=0?null:e.substring(0,n)}async function ct(e){q=e,b.style.display="none",p&&(te(),p.destroy(),p=null,f=null),W(null),le(),T.style.display="none",D.style.display="flex",We.textContent=e,E.textContent="Loading...",H.style.display="none";try{const n=await fetch(v("/api/file?path="+encodeURIComponent(e)));if(!n.ok){const s=await n.json();E.textContent=s.error||"Failed to load",P.value="";return}const t=await n.json();P.value=t.content,V=t.content,ge=t.content,E.textContent=t.size+" bytes",H.style.display=""}catch{E.textContent="Failed to load",P.value=""}}P.addEventListener("input",()=>{V=P.value}),H.addEventListener("click",async()=>{H.textContent="Saving...",H.disabled=!0;try{const e=await fetch(v("/api/file"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:q,content:V})});if(!e.ok){const n=await e.json();E.textContent=n.error||"Save failed";return}ge=V,E.textContent="Saved"}catch{E.textContent="Save failed"}finally{H.disabled=!1,H.textContent="Save"}}),Ue.addEventListener("click",async()=>{if(confirm("Delete "+q+"?"))try{const e=await fetch(v("/api/file/delete"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:q})});if(!e.ok){const n=await e.json();E.textContent=n.error||"Delete failed";return}D.style.display="none",T.style.display="flex",I&&x(I)}catch{E.textContent="Delete failed"}}),ze.addEventListener("click",()=>{D.style.display="none",T.style.display="flex",I&&x(I)}),Fe.addEventListener("click",async()=>{const e=ye.value.trim();if(!e)return;const n=I+"/"+e;try{const t=await fetch(v("/api/file/touch"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:n})});if(!t.ok){const s=await t.json();E.textContent=s.error||"Create failed";return}ye.value="",I&&x(I)}catch{E.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{const e=he.classList.toggle("open");ae.classList.toggle("open",e)}),ae.addEventListener("click",()=>{he.classList.remove("open"),ae.classList.remove("open")});let w="",C=!1,ne;const U=document.createElement("div");U.className="session-popover-backdrop",document.body.appendChild(U);const k=document.createElement("div");k.id="session-popover",k.className="session-popover",k.style.display="none",k.innerHTML=`<div class="sp-field">
31
31
  <label>Rename session</label>
32
32
  <input type="text" id="sp-name" />
33
33
  </div>
@@ -37,5 +37,5 @@ import{initTerminal as Oe}from"./terminal-core.js";const A=window.__TMUX_WEB_SHE
37
37
  </div>
38
38
  <hr class="sp-divider" />
39
39
  <button class="btn primary" id="sp-rebuild" style="display:none">\u91CD\u5EFA\u540C\u540D\u540C\u8DEF\u5F84 session</button>
40
- <button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(k);function rt(e){const n=e.getBoundingClientRect();k.style.top=n.bottom+4+"px",k.style.left=Math.max(8,Math.min(n.left,window.innerWidth-240))+"px"}function Ae(e,n,t){w=e,C=!!t?.tombstone,te=t?.agentId;const s=document.getElementById("sp-name");s.value=e;const i=k.querySelector(".sp-field label");i.textContent=C?"\u91CD\u547D\u540D (\u4EC5\u8BB0\u5F55\uFF0C\u4E0D\u91CD\u5EFA)":"Rename session";const o=document.getElementById("sp-rebuild");o.style.display=C?"":"none";const a=document.getElementById("sp-delete");a.textContent=C?"\u5220\u9664\u5931\u6548\u8BB0\u5F55 (\u5893\u7891\u6D88\u5931)":"Delete session";const c=document.getElementById("sp-save");c.textContent=C?"\u91CD\u547D\u540D":"Save",W.classList.add("open"),k.style.display="block",rt(n),setTimeout(()=>s.focus(),50)}function N(){W.classList.remove("open"),k.style.display="none"}W.addEventListener("click",N),document.getElementById("sp-save").addEventListener("click",async()=>{const e=document.getElementById("sp-name").value.trim();if(!e||e===w){N();return}try{const n=C?{oldName:w,newName:e,agentId:te}:{oldName:w,newName:e};if(!(await fetch(g(C?"/api/sessions/rename-tombstone":"/api/sessions/rename"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})).ok)return;N(),B(),!C&&f===w&&P(e)}catch{}}),document.getElementById("sp-rebuild").addEventListener("click",async()=>{if(confirm('\u91CD\u5EFA\u4F1A\u8BDD "'+w+'" (\u540C\u540D\u540C\u8DEF\u5F84\uFF0C\u5185\u5BB9\u4E3A\u7A7A)\uFF1F'))try{const e=await fetch(g("/api/sessions/rebuild"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:w,agentId:te})});if(!e.ok){const n=await e.json();alert(n.error||"\u91CD\u5EFA\u5931\u8D25");return}N(),B()}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(C){if(!confirm('\u5220\u9664\u5931\u6548\u8BB0\u5F55 "'+w+'"\uFF1F'))return;try{if(!(await fetch(g("/api/sessions/dismiss"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:w,agentId:te})})).ok)return;N(),B()}catch{}return}if(confirm('Delete session "'+w+'"?'))try{if(!(await fetch(g("/api/sessions/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:w})})).ok)return;N(),f===w&&(p&&(p.destroy(),p=null),f=null,b.style.display="none",T.style.display="flex"),B()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",N);const dt={esc:"\x1B",tab:" ","s-tab":"\x1B[Z",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",space:" ",enter:"\r","ctrl-r":"","ctrl-c":"",btw:"/btw ",yes:"yes\r"};document.getElementById("mobile-keys").addEventListener("click",e=>{const n=e.target.closest("button[data-key]");if(!n||!p)return;const t=dt[n.dataset.key];t&&(p.sendInput(t),p.focus())});const S=document.getElementById("mk-input"),_e=document.getElementById("mk-send");function De(){if(!S||!p)return;const e=S.value;e&&(p.sendInput(e+"\r"),S.value="",S.rows=1,p.focus())}if(S&&(S.addEventListener("input",()=>{S.rows=1;const e=S.value.split(`
41
- `).length;S.rows=Math.min(e,4)}),S.addEventListener("keydown",e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),De())})),_e&&_e.addEventListener("click",De),window.visualViewport){const e=document.querySelector(".app-layout"),n=()=>{e&&(e.style.height=window.visualViewport.height+"px"),window.scrollTo(0,0),document.documentElement.scrollTop=0,document.body.scrollTop=0};window.visualViewport.addEventListener("resize",n),window.addEventListener("orientationchange",()=>setTimeout(n,100)),document.addEventListener("touchstart",()=>{(window.scrollY>0||document.documentElement.scrollTop>0)&&window.scrollTo(0,0)},{passive:!0})}const re=document.getElementById("process-panel"),U=document.getElementById("proc-list"),pt=document.getElementById("proc-close"),de=document.getElementById("proc-backdrop"),ft=document.getElementById("header-ram");function ut(){U.innerHTML='<div class="proc-empty">Loading\u2026</div>',fetch(g("/api/system/processes")).then(e=>e.json()).then(e=>{if(!Array.isArray(e)||!e.length){U.innerHTML='<div class="proc-empty">No processes</div>';return}let n="";for(const t of e){const s=t.rss,i=s<1048576?(s/1024).toFixed(0)+"K":(s/1048576).toFixed(1)+"M";n+='<div class="proc-row" data-pid="'+t.pid+'"><span class="proc-mem">'+t.mem+'%</span><span class="proc-rss">'+i+'</span><span class="proc-cmd" title="'+d(t.command)+'">'+d(t.command)+'</span><button class="proc-kill" title="Kill PID '+t.pid+'">&times;</button></div>'}U.innerHTML=n;for(const t of U.querySelectorAll(".proc-row")){const s=t.querySelector(".proc-kill");s&&s.addEventListener("click",i=>{const o=i.target.closest(".proc-row");!o||!confirm("Kill PID "+o.dataset.pid+"?")||fetch(g("/api/system/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({pid:parseInt(o.dataset.pid,10)})}).then(a=>a.json()).then(a=>{a.ok?o.style.opacity="0.3":alert("Failed: "+(a.error||"unknown"))}).catch(()=>alert("Network error"))})}}).catch(()=>{U.innerHTML='<div class="proc-empty">Failed to load</div>'})}function mt(){re.classList.add("open"),de.classList.add("open"),ut()}function ne(){re.classList.remove("open"),de.classList.remove("open")}ft.addEventListener("click",e=>{e.stopPropagation(),re.classList.contains("open")?ne():mt()}),pt.addEventListener("click",ne),de.addEventListener("click",ne);const vt=2e3;let z=null,pe=null;const $=new Map,F=new Map;function Pe(e,n){return(n?"a:"+n+":":"l:")+e}function gt(e,n,t){const s=Pe(e,n),i=F.get(s),o=e===f&&(n??null)===v,a=t==="idle"&&i?.state==="working";F.set(s,{session:e,agentId:n,state:t,doneUntil:a?Date.now()+vt:void 0,unread:a?!o:!1});const c=n?'.session-item[data-agent="'+CSS.escape(n)+'"][data-session="'+CSS.escape(e)+'"]':'.session-item[data-session="'+CSS.escape(e)+'"]:not([data-agent])',l=r.querySelector(c);l&&fe(l,s,F.get(s))}function fe(e,n,t){const s=$.get(n);s&&(clearTimeout(s),$.delete(n)),e.classList.remove("working","just-done");const i=t.session===f&&(t.agentId??null)===v;t.state==="working"?e.classList.add("working"):i&&t.doneUntil&&Date.now()<t.doneUntil?(e.classList.add("just-done"),$.set(n,setTimeout(()=>{e.classList.remove("just-done"),$.delete(n)},Math.max(0,t.doneUntil-Date.now())))):!i&&t.unread&&e.classList.add("just-done")}function ue(){for(const[e,n]of F){const t=n.agentId?'.session-item[data-agent="'+CSS.escape(n.agentId)+'"][data-session="'+CSS.escape(n.session)+'"]':'.session-item[data-session="'+CSS.escape(n.session)+'"]:not([data-agent])',s=r.querySelector(t);s&&fe(s,e,n)}}function yt(e,n){const t=Pe(e,n),s=F.get(t);if(!s)return;const i=$.get(t);i&&(clearTimeout(i),$.delete(t)),s.doneUntil=void 0,s.unread=!1;const o=n?'.session-item[data-agent="'+CSS.escape(n)+'"][data-session="'+CSS.escape(e)+'"]':'.session-item[data-session="'+CSS.escape(e)+'"]:not([data-agent])',a=r.querySelector(o);a&&fe(a,t,s)}function je(){if(z||pe)return;const e=localStorage.getItem("tmux-web-token");let t=(location.protocol==="https:"?"wss:":"ws:")+"//"+location.host+"/ws/activity";e&&(t+="?token="+encodeURIComponent(e));try{const s=new WebSocket(t);z=s,s.onmessage=i=>{try{const o=JSON.parse(String(i.data));o&&o.type==="session.activity"&&typeof o.session=="string"&&gt(o.session,o.agentId||void 0,o.state==="working"?"working":"idle")}catch{}},s.onclose=()=>{z===s&&(z=null,pe=setTimeout(()=>{pe=null,je()},5e3))},s.onerror=()=>{try{s.close()}catch{}}}catch{z=null}}window.__openSession=P,window.__refreshSidebar=B,B(),ae(),ue(),je(),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&ue()}),setInterval(()=>{document.visibilityState==="visible"&&B()},1e4);
40
+ <button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(k);function rt(e){const n=e.getBoundingClientRect();k.style.top=n.bottom+4+"px",k.style.left=Math.max(8,Math.min(n.left,window.innerWidth-240))+"px"}function Ae(e,n,t){w=e,C=!!t?.tombstone,ne=t?.agentId;const s=document.getElementById("sp-name");s.value=e;const i=k.querySelector(".sp-field label");i.textContent=C?"\u91CD\u547D\u540D (\u4EC5\u8BB0\u5F55\uFF0C\u4E0D\u91CD\u5EFA)":"Rename session";const o=document.getElementById("sp-rebuild");o.style.display=C?"":"none";const a=document.getElementById("sp-delete");a.textContent=C?"\u5220\u9664\u5931\u6548\u8BB0\u5F55 (\u5893\u7891\u6D88\u5931)":"Delete session";const c=document.getElementById("sp-save");c.textContent=C?"\u91CD\u547D\u540D":"Save",U.classList.add("open"),k.style.display="block",rt(n),setTimeout(()=>s.focus(),50)}function N(){U.classList.remove("open"),k.style.display="none"}U.addEventListener("click",N),document.getElementById("sp-save").addEventListener("click",async()=>{const e=document.getElementById("sp-name").value.trim();if(!e||e===w){N();return}try{const n=C?{oldName:w,newName:e,agentId:ne}:{oldName:w,newName:e};if(!(await fetch(v(C?"/api/sessions/rename-tombstone":"/api/sessions/rename"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})).ok)return;N(),B(),!C&&f===w&&j(e)}catch{}}),document.getElementById("sp-rebuild").addEventListener("click",async()=>{if(confirm('\u91CD\u5EFA\u4F1A\u8BDD "'+w+'" (\u540C\u540D\u540C\u8DEF\u5F84\uFF0C\u5185\u5BB9\u4E3A\u7A7A)\uFF1F'))try{const e=await fetch(v("/api/sessions/rebuild"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:w,agentId:ne})});if(!e.ok){const n=await e.json();alert(n.error||"\u91CD\u5EFA\u5931\u8D25");return}N(),B()}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(C){if(!confirm('\u5220\u9664\u5931\u6548\u8BB0\u5F55 "'+w+'"\uFF1F'))return;try{if(!(await fetch(v("/api/sessions/dismiss"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:w,agentId:ne})})).ok)return;N(),B()}catch{}return}if(confirm('Delete session "'+w+'"?'))try{if(!(await fetch(v("/api/sessions/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:w})})).ok)return;N(),f===w&&(p&&(p.destroy(),p=null),f=null,b.style.display="none",T.style.display="flex"),B()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",N);const dt={esc:"\x1B",tab:" ","s-tab":"\x1B[Z",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",space:" ",enter:"\r","ctrl-r":"","ctrl-c":"",btw:"/btw ",yes:"yes\r"};document.getElementById("mobile-keys").addEventListener("click",e=>{const n=e.target.closest("button[data-key]");if(!n||!p)return;const t=dt[n.dataset.key];t&&(p.sendInput(t),p.focus())});const S=document.getElementById("mk-input"),_e=document.getElementById("mk-send");function De(){if(!S||!p)return;const e=S.value;e&&(p.sendInput(e+"\r"),S.value="",S.rows=1,p.focus())}if(S&&(S.addEventListener("input",()=>{S.rows=1;const e=S.value.split(`
41
+ `).length;S.rows=Math.min(e,4)}),S.addEventListener("keydown",e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),De())})),_e&&_e.addEventListener("click",De),window.visualViewport){const e=document.querySelector(".app-layout"),n=()=>{e&&(e.style.height=window.visualViewport.height+"px"),window.scrollTo(0,0),document.documentElement.scrollTop=0,document.body.scrollTop=0};window.visualViewport.addEventListener("resize",n),window.addEventListener("orientationchange",()=>setTimeout(n,100)),document.addEventListener("touchstart",()=>{(window.scrollY>0||document.documentElement.scrollTop>0)&&window.scrollTo(0,0)},{passive:!0})}const de=document.getElementById("process-panel"),z=document.getElementById("proc-list"),pt=document.getElementById("proc-close"),pe=document.getElementById("proc-backdrop"),ft=document.getElementById("header-ram");function ut(){z.innerHTML='<div class="proc-empty">Loading\u2026</div>',fetch(v("/api/system/processes")).then(e=>e.json()).then(e=>{if(!Array.isArray(e)||!e.length){z.innerHTML='<div class="proc-empty">No processes</div>';return}let n="";for(const t of e){const s=t.rss,i=s<1048576?(s/1024).toFixed(0)+"K":(s/1048576).toFixed(1)+"M";n+='<div class="proc-row" data-pid="'+t.pid+'"><span class="proc-mem">'+t.mem+'%</span><span class="proc-rss">'+i+'</span><span class="proc-cmd" title="'+d(t.command)+'">'+d(t.command)+'</span><button class="proc-kill" title="Kill PID '+t.pid+'">&times;</button></div>'}z.innerHTML=n;for(const t of z.querySelectorAll(".proc-row")){const s=t.querySelector(".proc-kill");s&&s.addEventListener("click",i=>{const o=i.target.closest(".proc-row");!o||!confirm("Kill PID "+o.dataset.pid+"?")||fetch(v("/api/system/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({pid:parseInt(o.dataset.pid,10)})}).then(a=>a.json()).then(a=>{a.ok?o.style.opacity="0.3":alert("Failed: "+(a.error||"unknown"))}).catch(()=>alert("Network error"))})}}).catch(()=>{z.innerHTML='<div class="proc-empty">Failed to load</div>'})}function mt(){de.classList.add("open"),pe.classList.add("open"),ut()}function se(){de.classList.remove("open"),pe.classList.remove("open")}ft.addEventListener("click",e=>{e.stopPropagation(),de.classList.contains("open")?se():mt()}),pt.addEventListener("click",se),pe.addEventListener("click",se);const vt=2e3;let F=null,fe=null;const $=new Map,G=new Map;function Pe(e,n){return(n?"a:"+n+":":"l:")+e}function gt(e,n,t){const s=Pe(e,n),i=G.get(s),o=e===f&&(n??null)===h,a=t==="idle"&&i?.state==="working";G.set(s,{session:e,agentId:n,state:t,doneUntil:a?Date.now()+vt:void 0,unread:a?!o:!1});const c=n?'.session-item[data-agent="'+CSS.escape(n)+'"][data-session="'+CSS.escape(e)+'"]':'.session-item[data-session="'+CSS.escape(e)+'"]:not([data-agent])',l=r.querySelector(c);l&&ue(l,s,G.get(s))}function ue(e,n,t){const s=$.get(n);s&&(clearTimeout(s),$.delete(n)),e.classList.remove("working","just-done");const i=t.session===f&&(t.agentId??null)===h;t.state==="working"?e.classList.add("working"):i&&t.doneUntil&&Date.now()<t.doneUntil?(e.classList.add("just-done"),$.set(n,setTimeout(()=>{e.classList.remove("just-done"),$.delete(n)},Math.max(0,t.doneUntil-Date.now())))):!i&&t.unread&&e.classList.add("just-done")}function me(){for(const[e,n]of G){const t=n.agentId?'.session-item[data-agent="'+CSS.escape(n.agentId)+'"][data-session="'+CSS.escape(n.session)+'"]':'.session-item[data-session="'+CSS.escape(n.session)+'"]:not([data-agent])',s=r.querySelector(t);s&&ue(s,e,n)}}function yt(e,n){const t=Pe(e,n),s=G.get(t);if(!s)return;const i=$.get(t);i&&(clearTimeout(i),$.delete(t)),s.doneUntil=void 0,s.unread=!1;const o=n?'.session-item[data-agent="'+CSS.escape(n)+'"][data-session="'+CSS.escape(e)+'"]':'.session-item[data-session="'+CSS.escape(e)+'"]:not([data-agent])',a=r.querySelector(o);a&&ue(a,t,s)}function je(){if(F||fe)return;const e=localStorage.getItem("tmux-web-token");let t=(location.protocol==="https:"?"wss:":"ws:")+"//"+location.host+"/ws/activity";e&&(t+="?token="+encodeURIComponent(e));try{const s=new WebSocket(t);F=s,s.onmessage=i=>{try{const o=JSON.parse(String(i.data));o&&o.type==="session.activity"&&typeof o.session=="string"&&gt(o.session,o.agentId||void 0,o.state==="working"?"working":"idle")}catch{}},s.onclose=()=>{F===s&&(F=null,fe=setTimeout(()=>{fe=null,je()},5e3))},s.onerror=()=>{try{s.close()}catch{}}}catch{F=null}}window.__openSession=j,window.__refreshSidebar=B,B(),le(),me(),je(),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&me()}),setInterval(()=>{document.visibilityState==="visible"&&B()},1e4);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmux-weblink",
3
- "version": "2.2.8",
3
+ "version": "2.2.9",
4
4
  "description": "Access your tmux sessions from the browser. A continuation of tmux-web and persalink.",
5
5
  "type": "module",
6
6
  "bin": {