tmux-weblink 2.2.16 → 2.2.18

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,30 +1,30 @@
1
- var yn=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function Ge(e){return e.replace(/\x1b\[\?1049[hl]/g,"")}function me(e){return e.replace(yn,"")}var Fe;function wn(){return Fe||(document.querySelector("link[data-tmux-web-xterm-css]")?Fe=Promise.resolve():(Fe=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)}),Fe))}var bn=class Ut{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"),wn()]),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 Ut(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=Ln(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 h=s.getLine(c+u);o.push(h?h.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),h=Math.max(t,s);this.terminal.select(u,r.viewportY+c,h-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),h=n<l?s:n>l?t:Math.max(t,s),k=r.viewportY,b=[];for(let M=c;M<=o;M++){let B=r.getLine(k+M);if(!B){b.push("");continue}let Q=M===c?u:0,F=M===o?h:this.terminal.cols-1,N="";for(let se=Q;se<=F;se++){let ie=B.getCell(se);ie&&(N+=ie.getChars())}b.push(N.replace(/\s+$/,""))}return b.join(`
3
- `)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}};function Ln(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 En(e,t,n){return e.innerHTML="",e.classList.add("terminal-pending"),(async()=>{let s=await bn.create(e,n.scrollback,n.theme),l,r=0,c,o=null,u=null,h=!1,k=/(?:^|\/)(?:vim|nvim|vi|less|more|htop|btop|top|hx|helix|lazygit)$/,b=null;async function M(){try{let i=await fetch("/api/session-program?session="+encodeURIComponent(t));if(i.ok){let a=await i.json();u=typeof a.program=="string"&&a.program?a.program:null,h=u!==null&&k.test(u)}}catch{}}function B(){b&&clearTimeout(b),b=setTimeout(()=>{M()},250)}function Q(i){return u!==null&&/(?:^|\/)(?:vim|nvim|vi)$/.test(u)?i?"":"":i?"\x1B[A":"\x1B[B"}let F=0,N=0,se=.2,ie=10,Yt=.95,Ot=.04;function ke(){F&&(cancelAnimationFrame(F),F=0),N=0}function Wt(i){if(ke(),Math.abs(i)<se)return;N=Math.max(-ie,Math.min(ie,i));let a=()=>{if(_){F=0;return}let d=e.querySelector(".xterm-rows > div"),p=d?d.getBoundingClientRect().height:16,w=p>0?Math.round(N*16/p):N>0?1:-1;w===0&&(w=N>0?1:-1);let I=s.viewportY()-w,V=s.baseY(),U=Math.max(0,Math.min(I,V));if(s.scrollToLine(U,!0),N*=Yt,U!==I){F=0;return}if(Math.abs(N)<Ot){F=0;return}F=requestAnimationFrame(a)};F=requestAnimationFrame(a)}let Ke=0,P="connecting",Se=0,ae=!1,Te=[],Z="",_=!1,oe=1e3,qt=location.protocol==="https:"?"wss:":"ws:",Kt=n.wsBase||"/ws",Vt=qt+"//"+location.host+Kt+"/"+encodeURIComponent(t),Jt="/api/session/"+encodeURIComponent(t)+"/upload",Xt=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function Gt(){return Te.join("")+Z}async function Qt(i,a=0){let d=i?s.viewportY():0,p=me(Gt());if(s.reset(),!p){i||s.scrollToBottom();return}await s.write(p),i?s.scrollToLine(a+d):s.scrollToBottom()}function q(i){l?.readyState===WebSocket.OPEN&&l.send(JSON.stringify(i))}function Zt(i){let a;try{a=JSON.parse(i)}catch{P==="live"&&(Z+=i,s.write(me(i)));return}if(a.type==="auth.required"){let d=localStorage.getItem("tmux-web-token");d?q({type:"auth.token",token:d}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(a.type==="attach_failed"&&typeof a.message=="string"){Me=!0,P="dead",s.reset(),s.write(`\r
1
+ var yn=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function Qe(e){return e.replace(/\x1b\[\?1049[hl]/g,"")}function me(e){return e.replace(yn,"")}var Fe;function wn(){return Fe||(document.querySelector("link[data-tmux-web-xterm-css]")?Fe=Promise.resolve():(Fe=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)}),Fe))}var bn=class Yt{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"),wn()]),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 Yt(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=Ln(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 h=s.getLine(c+u);o.push(h?h.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),h=Math.max(t,s);this.terminal.select(u,r.viewportY+c,h-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),h=n<l?s:n>l?t:Math.max(t,s),k=r.viewportY,b=[];for(let M=c;M<=o;M++){let B=r.getLine(k+M);if(!B){b.push("");continue}let Z=M===c?u:0,F=M===o?h:this.terminal.cols-1,N="";for(let se=Z;se<=F;se++){let ie=B.getCell(se);ie&&(N+=ie.getChars())}b.push(N.replace(/\s+$/,""))}return b.join(`
3
+ `)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}};function Ln(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 En(e,t,n){return e.innerHTML="",e.classList.add("terminal-pending"),(async()=>{let s=await bn.create(e,n.scrollback,n.theme),l,r=0,c,o=null,u=null,h=!1,k=/(?:^|\/)(?:vim|nvim|vi|less|more|htop|btop|top|hx|helix|lazygit)$/,b=null;async function M(){try{let i=(n.wsBase||"/ws").replace(/^\/ws/,"")||"",a=await fetch(i+"/api/session-program?session="+encodeURIComponent(t));if(a.ok){let d=await a.json();u=typeof d.program=="string"&&d.program?d.program:null,h=u!==null&&k.test(u)}}catch{}}function B(){b&&clearTimeout(b),b=setTimeout(()=>{M()},250)}function Z(i){return u!==null&&/(?:^|\/)(?:vim|nvim|vi)$/.test(u)?i?"":"":i?"\x1B[A":"\x1B[B"}let F=0,N=0,se=.2,ie=10,Ut=.95,Wt=.04;function ke(){F&&(cancelAnimationFrame(F),F=0),N=0}function Ot(i){if(ke(),Math.abs(i)<se)return;N=Math.max(-ie,Math.min(ie,i));let a=()=>{if(_){F=0;return}let d=e.querySelector(".xterm-rows > div"),p=d?d.getBoundingClientRect().height:16,w=p>0?Math.round(N*16/p):N>0?1:-1;w===0&&(w=N>0?1:-1);let I=s.viewportY()-w,V=s.baseY(),Y=Math.max(0,Math.min(I,V));if(s.scrollToLine(Y,!0),N*=Ut,Y!==I){F=0;return}if(Math.abs(N)<Wt){F=0;return}F=requestAnimationFrame(a)};F=requestAnimationFrame(a)}let Ke=0,P="connecting",Se=0,ae=!1,Te=[],G="",_=!1,oe=1e3,qt=location.protocol==="https:"?"wss:":"ws:",Kt=n.wsBase||"/ws",Vt=qt+"//"+location.host+Kt+"/"+encodeURIComponent(t),Xt="/api/session/"+encodeURIComponent(t)+"/upload",Jt=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function Qt(){return Te.join("")+G}async function Zt(i,a=0){let d=i?s.viewportY():0,p=me(Qt());if(s.reset(),!p){i||s.scrollToBottom();return}await s.write(p),i?s.scrollToLine(a+d):s.scrollToBottom()}function q(i){l?.readyState===WebSocket.OPEN&&l.send(JSON.stringify(i))}function Gt(i){let a;try{a=JSON.parse(i)}catch{P==="live"&&(G+=i,s.write(me(i)));return}if(a.type==="auth.required"){let d=localStorage.getItem("tmux-web-token");d?q({type:"auth.token",token:d}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(a.type==="attach_failed"&&typeof a.message=="string"){Me=!0,P="dead",s.reset(),s.write(`\r
4
4
  \x1B[31m`+me(a.message)+`\x1B[0m\r
5
- `).then(()=>{Be();try{l?.close()}catch{}});return}if(a.type==="auth.ok"){a.token&&localStorage.setItem("tmux-web-token",a.token),oe=1e3,K(),q({type:"resize",cols:s.cols,rows:s.rows}),S(),M();return}if(a.type==="auth.failed"){if(a.permanentLock||a.retryAfterMs&&a.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(a.message);return}return}if(a.type==="snapshot"&&typeof a.data=="string"){let d=Ge(me(a.data));Te=[d],Z="",Se=typeof a.lines=="number"?a.lines:n.terminal.initialLines,P="live",s.reset(),K(),q({type:"resize",cols:s.cols,rows:s.rows}),s.write(d).then(()=>s.scrollToBottom());return}if(a.type==="window_changed"&&typeof a.activeIndex=="number"){let d=new URL(location.href);d.searchParams.get("window")!==String(a.activeIndex)&&(d.searchParams.set("window",String(a.activeIndex)),history.replaceState(history.state,"",d)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:a.windows}));return}if(a.type==="history"&&typeof a.data=="string"){a.lines>0&&a.data?(Te.unshift(Ge(a.data)),Se+=a.lines,Qt(!0,a.lines).finally(()=>{ae=!1})):ae=!1;return}if(a.type==="data"&&typeof a.data=="string"){/\x1b\[\?1049[hl]/.test(a.data)&&B();let d=Ge(me(a.data));if(P==="connecting"){P="live",Z=d,s.write(d);return}P==="live"&&(Z+=d,s.write(d))}}let Me=!1;function rt(){if(Me)return;let i=Vt,a=localStorage.getItem("tmux-web-token");a&&(i+=(i.includes("?")?"&":"?")+"token="+encodeURIComponent(a)),i+=(i.includes("?")?"&":"?")+"cols="+s.cols+"&rows="+s.rows,l=new WebSocket(i),l.onopen=()=>{P="connecting",Se=0,ae=!1,Te=[],Z="",s.reset(),oe=1e3},l.onmessage=d=>{typeof d.data=="string"&&Zt(d.data)},l.onclose=()=>{_||(P="connecting",!Me&&setTimeout(()=>{oe=Math.min(oe*2,1e4),!_&&!Me&&rt()},oe))},l.onerror=()=>l?.close()}function le(i){q({type:"input",data:i})}function K(){return s.fit()}function Be(){e.classList.remove("terminal-pending")}function S(){r&&cancelAnimationFrame(r),c&&clearTimeout(c),K(),r=requestAnimationFrame(()=>{r=0,K()&&Be()}),c=setTimeout(()=>{K()&&Be()},120)}function en(){S(),setTimeout(S,50),setTimeout(S,150),setTimeout(S,300)}function ct(i){return typeof i=="string"&&i.startsWith("image/")}function dt(i){return i?.files?.length?i.files[0]??null:null}function tn(i){if(!i?.items)return null;for(let a=0;a<i.items.length;a++){let d=i.items[a];if(d?.kind==="file"&&ct(d.type))return d.getAsFile()}return null}async function nn(i){let a=new FormData,d=i instanceof File&&i.name?i.name:"upload";a.append("file",i,d);let p=localStorage.getItem("tmux-web-token"),w={};p&&(w.Authorization="Bearer "+p);let I=await fetch(Jt,{method:"POST",body:a,headers:w});if(!I.ok){let U="upload failed";try{let He=await I.json();He.error&&(U=He.error)}catch{}throw new Error(U)}let V=await I.json();if(!V.path)throw new Error("no path in response");return V.path}async function Ve(i){try{let a=await nn(i);le(a)}catch{}}s.onData(i=>le(i)),s.onResize(({cols:i,rows:a})=>q({type:"resize",cols:i,rows:a})),s.onScroll(()=>{P!=="live"||ae||!s.isNearScrollbackTop()||(ae=!0,q({type:"load_history",before:Se}))});let re=!1,ce=!1,L=null,E=null,de=document.createElement("div");de.className="terminal-copy-banner",de.innerHTML='<strong>Copy mode</strong><span class="hint">drag to copy \xB7 Esc exits</span>',de.hidden=!0,e.appendChild(de);let j=document.createElement("div");j.className="terminal-copy-banner terminal-copy-toast",j.textContent="Copied",j.hidden=!0,e.appendChild(j);function ut(i,a){let d=e.querySelector(".xterm-screen, canvas"),p=(d&&d.getBoundingClientRect().width>0?d:e).getBoundingClientRect(),w=p.height>0&&s.rows>0?p.height/s.rows:18,I=p.width>0&&s.cols>0?p.width/s.cols:9;return{row:Math.max(0,Math.min(s.rows-1,Math.floor((a-p.top)/w))),col:Math.max(0,Math.min(s.cols-1,Math.floor((i-p.left)/I)))}}async function Ie(i){if(!i)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(i);return}}catch{}let a=document.createElement("textarea");a.value=i,a.style.position="fixed",a.style.opacity="0",a.style.pointerEvents="none",document.body.appendChild(a),a.focus(),a.select();try{document.execCommand("copy")}catch{}a.remove()}let ue;function De(){j.hidden=!1,ue&&clearTimeout(ue),ue=setTimeout(()=>{j.hidden=!0},1e3)}function ee(i){re=i,de.hidden=!i,e.classList.toggle("terminal-copy-mode-active",i),i&&s.focus()}function pt(){ee(!re)}function sn(i){_||i.button!==0||ce||(re||i.shiftKey)&&(i.preventDefault(),i.stopPropagation(),ce=!0,L=ut(i.clientX,i.clientY),E=L,s.selectCells(L.col,L.row,E.col,E.row),document.addEventListener("mousemove",Je,!0),document.addEventListener("mouseup",Xe,!0))}function Je(i){_||!ce||!L||(i.preventDefault(),i.stopPropagation(),E=ut(i.clientX,i.clientY),s.selectCells(L.col,L.row,E.col,E.row))}function Xe(i){if(_||!ce||!L||!E)return;i.preventDefault(),i.stopPropagation(),document.removeEventListener("mousemove",Je,!0),document.removeEventListener("mouseup",Xe,!0),ce=!1;let a=s.getCellsText(L.col,L.row,E.col,E.row);L=null,E=null,s.clearSelection(),ee(!1),a&&(j.textContent="\u5DF2\u590D\u5236",Ie(a).then(De)),s.focus()}e.addEventListener("mousedown",sn,!0),document.addEventListener("keydown",an,!0);function an(i){if(!(_||!s.isFocused()||i.defaultPrevented||i.isComposing)){if(re){if(i.key==="Escape"){i.preventDefault(),i.stopPropagation(),L=null,E=null,s.clearSelection(),ee(!1);return}if(i.key==="Enter"||(i.ctrlKey||i.metaKey)&&i.code==="KeyC"){i.preventDefault(),i.stopPropagation(),Ie(s.getScreenText()).then(De),ee(!1);return}}if(i.altKey&&i.code==="KeyC"&&!i.ctrlKey&&!i.metaKey){if(i.preventDefault(),i.stopPropagation(),L&&E){let a=s.getCellsText(L.col,L.row,E.col,E.row);L=null,E=null,s.clearSelection(),ee(!1),a&&(j.textContent="Copied",Ie(a).then(De))}else{let a=s.getSelection();a?(s.clearSelection(),j.textContent="Copied",Ie(a).then(De)):pt()}return}if((i.ctrlKey||i.metaKey)&&i.code==="KeyV"){i.preventDefault(),i.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){let a=await navigator.clipboard.read();for(let d of a)for(let p of d.types)if(ct(p)){let w=await d.getType(p);await Ve(w);return}}}catch{}try{let a=await navigator.clipboard?.readText();a&&s.pasteText(mt(a))}catch{}})();return}}}let Ae=0;function mt(i){return i.split(`\r
5
+ `).then(()=>{Be();try{l?.close()}catch{}});return}if(a.type==="auth.ok"){a.token&&localStorage.setItem("tmux-web-token",a.token),oe=1e3,K(),q({type:"resize",cols:s.cols,rows:s.rows}),S(),M();return}if(a.type==="auth.failed"){if(a.permanentLock||a.retryAfterMs&&a.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(a.message);return}return}if(a.type==="snapshot"&&typeof a.data=="string"){let d=Qe(me(a.data));Te=[d],G="",Se=typeof a.lines=="number"?a.lines:n.terminal.initialLines,P="live",s.reset(),K(),q({type:"resize",cols:s.cols,rows:s.rows}),s.write(d).then(()=>s.scrollToBottom());return}if(a.type==="window_changed"&&typeof a.activeIndex=="number"){let d=new URL(location.href);d.searchParams.get("window")!==String(a.activeIndex)&&(d.searchParams.set("window",String(a.activeIndex)),history.replaceState(history.state,"",d)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:a.windows}));return}if(a.type==="history"&&typeof a.data=="string"){a.lines>0&&a.data?(Te.unshift(Qe(a.data)),Se+=a.lines,Zt(!0,a.lines).finally(()=>{ae=!1})):ae=!1;return}if(a.type==="data"&&typeof a.data=="string"){/\x1b\[\?1049[hl]/.test(a.data)&&B();let d=Qe(me(a.data));if(P==="connecting"){P="live",G=d,s.write(d);return}P==="live"&&(G+=d,s.write(d))}}let Me=!1;function rt(){if(Me)return;let i=Vt,a=localStorage.getItem("tmux-web-token");a&&(i+=(i.includes("?")?"&":"?")+"token="+encodeURIComponent(a)),i+=(i.includes("?")?"&":"?")+"cols="+s.cols+"&rows="+s.rows,l=new WebSocket(i),l.onopen=()=>{P="connecting",Se=0,ae=!1,Te=[],G="",s.reset(),oe=1e3},l.onmessage=d=>{typeof d.data=="string"&&Gt(d.data)},l.onclose=()=>{_||(P="connecting",!Me&&setTimeout(()=>{oe=Math.min(oe*2,1e4),!_&&!Me&&rt()},oe))},l.onerror=()=>l?.close()}function le(i){q({type:"input",data:i})}function K(){return s.fit()}function Be(){e.classList.remove("terminal-pending")}function S(){r&&cancelAnimationFrame(r),c&&clearTimeout(c),K(),r=requestAnimationFrame(()=>{r=0,K()&&Be()}),c=setTimeout(()=>{K()&&Be()},120)}function en(){S(),setTimeout(S,50),setTimeout(S,150),setTimeout(S,300)}function ct(i){return typeof i=="string"&&i.startsWith("image/")}function dt(i){return i?.files?.length?i.files[0]??null:null}function tn(i){if(!i?.items)return null;for(let a=0;a<i.items.length;a++){let d=i.items[a];if(d?.kind==="file"&&ct(d.type))return d.getAsFile()}return null}async function nn(i){let a=new FormData,d=i instanceof File&&i.name?i.name:"upload";a.append("file",i,d);let p=localStorage.getItem("tmux-web-token"),w={};p&&(w.Authorization="Bearer "+p);let I=await fetch(Xt,{method:"POST",body:a,headers:w});if(!I.ok){let Y="upload failed";try{let He=await I.json();He.error&&(Y=He.error)}catch{}throw new Error(Y)}let V=await I.json();if(!V.path)throw new Error("no path in response");return V.path}async function Ve(i){try{let a=await nn(i);le(a)}catch{}}s.onData(i=>le(i)),s.onResize(({cols:i,rows:a})=>q({type:"resize",cols:i,rows:a})),s.onScroll(()=>{P!=="live"||ae||!s.isNearScrollbackTop()||(ae=!0,q({type:"load_history",before:Se}))});let re=!1,ce=!1,L=null,E=null,de=document.createElement("div");de.className="terminal-copy-banner",de.innerHTML='<strong>Copy mode</strong><span class="hint">drag to copy \xB7 Esc exits</span>',de.hidden=!0,e.appendChild(de);let z=document.createElement("div");z.className="terminal-copy-banner terminal-copy-toast",z.textContent="Copied",z.hidden=!0,e.appendChild(z);function ut(i,a){let d=e.querySelector(".xterm-screen, canvas"),p=(d&&d.getBoundingClientRect().width>0?d:e).getBoundingClientRect(),w=p.height>0&&s.rows>0?p.height/s.rows:18,I=p.width>0&&s.cols>0?p.width/s.cols:9;return{row:Math.max(0,Math.min(s.rows-1,Math.floor((a-p.top)/w))),col:Math.max(0,Math.min(s.cols-1,Math.floor((i-p.left)/I)))}}async function Ie(i){if(!i)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(i);return}}catch{}let a=document.createElement("textarea");a.value=i,a.style.position="fixed",a.style.opacity="0",a.style.pointerEvents="none",document.body.appendChild(a),a.focus(),a.select();try{document.execCommand("copy")}catch{}a.remove()}let ue;function De(){z.hidden=!1,ue&&clearTimeout(ue),ue=setTimeout(()=>{z.hidden=!0},1e3)}function ee(i){re=i,de.hidden=!i,e.classList.toggle("terminal-copy-mode-active",i),i&&s.focus()}function pt(){ee(!re)}function sn(i){_||i.button!==0||ce||(re||i.shiftKey)&&(i.preventDefault(),i.stopPropagation(),ce=!0,L=ut(i.clientX,i.clientY),E=L,s.selectCells(L.col,L.row,E.col,E.row),document.addEventListener("mousemove",Xe,!0),document.addEventListener("mouseup",Je,!0))}function Xe(i){_||!ce||!L||(i.preventDefault(),i.stopPropagation(),E=ut(i.clientX,i.clientY),s.selectCells(L.col,L.row,E.col,E.row))}function Je(i){if(_||!ce||!L||!E)return;i.preventDefault(),i.stopPropagation(),document.removeEventListener("mousemove",Xe,!0),document.removeEventListener("mouseup",Je,!0),ce=!1;let a=s.getCellsText(L.col,L.row,E.col,E.row);L=null,E=null,s.clearSelection(),ee(!1),a&&(z.textContent="\u5DF2\u590D\u5236",Ie(a).then(De)),s.focus()}e.addEventListener("mousedown",sn,!0),document.addEventListener("keydown",an,!0);function an(i){if(!(_||!s.isFocused()||i.defaultPrevented||i.isComposing)){if(re){if(i.key==="Escape"){i.preventDefault(),i.stopPropagation(),L=null,E=null,s.clearSelection(),ee(!1);return}if(i.key==="Enter"||(i.ctrlKey||i.metaKey)&&i.code==="KeyC"){i.preventDefault(),i.stopPropagation(),Ie(s.getScreenText()).then(De),ee(!1);return}}if(i.altKey&&i.code==="KeyC"&&!i.ctrlKey&&!i.metaKey){if(i.preventDefault(),i.stopPropagation(),L&&E){let a=s.getCellsText(L.col,L.row,E.col,E.row);L=null,E=null,s.clearSelection(),ee(!1),a&&(z.textContent="Copied",Ie(a).then(De))}else{let a=s.getSelection();a?(s.clearSelection(),z.textContent="Copied",Ie(a).then(De)):pt()}return}if((i.ctrlKey||i.metaKey)&&i.code==="KeyV"){i.preventDefault(),i.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){let a=await navigator.clipboard.read();for(let d of a)for(let p of d.types)if(ct(p)){let w=await d.getType(p);await Ve(w);return}}}catch{}try{let a=await navigator.clipboard?.readText();a&&s.pasteText(mt(a))}catch{}})();return}}}let Ae=0;function mt(i){return i.split(`\r
6
6
  `).join(`
7
7
  `).split(`
8
- `).join("\r")}async function on(i){let a=tn(i.clipboardData);if(a){i.preventDefault(),i.stopPropagation();let w=Date.now();if(w-Ae<50)return;Ae=w,await Ve(a);return}let d=i.clipboardData?.getData("text/plain");if(!d)return;i.preventDefault(),i.stopPropagation();let p=Date.now();p-Ae<50||(Ae=p,s.pasteText(mt(d)))}let pe=0;function ln(i){i.preventDefault(),pe++,dt(i.dataTransfer)&&e.classList.add("terminal-drag-over")}function rn(i){i.preventDefault(),i.dataTransfer&&(i.dataTransfer.dropEffect="copy")}function cn(i){i.preventDefault(),pe--,pe<=0&&(pe=0,e.classList.remove("terminal-drag-over"))}async function dn(i){i.preventDefault(),pe=0,e.classList.remove("terminal-drag-over");let a=dt(i.dataTransfer);a&&await Ve(a)}function ft(i){!Xt||i.key!=="Escape"||re||i.defaultPrevented||i.repeat||i.metaKey||i.ctrlKey||i.altKey||s.isFocused()&&(i.preventDefault(),i.stopPropagation(),le("\x1B"))}e.addEventListener("paste",on),e.addEventListener("dragenter",ln),e.addEventListener("dragover",rn),e.addEventListener("dragleave",cn),e.addEventListener("drop",dn),document.addEventListener("keydown",ft,!0);function un(i){if(i.touches.length!==1){o=null;return}let a=i.touches[0];a&&(ke(),o={startX:a.clientX,startY:a.clientY,lastX:a.clientX,lastY:a.clientY,lastT:performance.now(),velocity:0,scrolling:!1,tuiAtStart:h,tuiAccum:0},i.stopPropagation())}function pn(i){if(!o||i.touches.length!==1)return;let a=i.touches[0];if(!a)return;let d=a.clientY-o.startY,p=a.clientX-o.startX;if(!o.scrolling){if(Math.abs(d)<8||Math.abs(d)<Math.abs(p))return;o.scrolling=!0,Ke=Date.now()+500}i.preventDefault(),i.stopPropagation();let w=performance.now(),I=a.clientY-o.lastY;if(h){o.tuiAccum+=I;let U=e.querySelector(".xterm-rows > div"),He=U?U.getBoundingClientRect().height:16,gt=Math.max(16,He);for(;Math.abs(o.tuiAccum)>=gt;)le(Q(o.tuiAccum>0)),o.tuiAccum-=Math.sign(o.tuiAccum)*gt;o.lastX=a.clientX,o.lastY=a.clientY,o.lastT=w;return}let V=w-o.lastT;V>0&&(o.velocity=I/V),vn(-I),o.lastX=a.clientX,o.lastY=a.clientY,o.lastT=w}function mn(i){if(!o)return;let a=o.scrolling,d=o.tuiAtStart,p=o.velocity;if(o=null,i.stopPropagation(),!a){s.focus();return}Ke=Date.now()+500,i.preventDefault(),!d&&p&&Wt(p)}function fn(i){o=null,ke(),i.stopPropagation()}function hn(i){i.pointerType==="touch"&&Date.now()<Ke&&(i.preventDefault(),i.stopPropagation())}function vn(i){let a=e.querySelector(".xterm-rows > div"),d=a?a.getBoundingClientRect().height:16,p=d>0?Math.round(i/d):i>0?1:-1;p===0&&(p=i>0?1:-1),s.scrollLines(p)}e.addEventListener("touchstart",un,{passive:!0,capture:!0}),e.addEventListener("touchmove",pn,{passive:!1,capture:!0}),e.addEventListener("touchend",mn,{passive:!1,capture:!0}),e.addEventListener("touchcancel",fn,{passive:!0,capture:!0}),e.addEventListener("pointerup",hn,!0);function ht(){S()}window.addEventListener("resize",ht),window.visualViewport?.addEventListener("resize",S),window.visualViewport?.addEventListener("scroll",S);let vt=new ResizeObserver(()=>S());vt.observe(e),document.fonts?.ready.then(()=>{S(),setTimeout(S,50),setTimeout(S,200)}),e.addEventListener("focusin",en,!0);async function gn(){if(document.fonts?.ready)try{await Promise.race([document.fonts.ready,new Promise(i=>setTimeout(i,1e3))])}catch{}}return requestAnimationFrame(()=>{K()&&Be(),(async()=>(await gn(),K()&&q({type:"resize",cols:s.cols,rows:s.rows}),rt(),S()))()}),{destroy(){if(_=!0,ke(),ee(!1),ue&&clearTimeout(ue),document.removeEventListener("mousemove",Je,!0),document.removeEventListener("mouseup",Xe,!0),l){try{l.close(1e3,"session switch")}catch{}l=void 0}e.innerHTML="",e.classList.remove("terminal-pending"),window.removeEventListener("resize",ht),vt.disconnect(),document.removeEventListener("keydown",ft,!0)},focus(){s.focus()},sendInput(i){le(i)},toggleCopyMode(){pt()}}})()}var fe=window.__TMUX_WEB_SHELL__,v=null,g=null,he=typeof window.__TMUX_WEB_SCOPE__?.agentId=="string"?window.__TMUX_WEB_SCOPE__.agentId:null,T=he;window.__tmuxWebScopeAgent=he;var Qe="sessions",Y="",Ne="",Re="",yt="";function x(e){return T?"/a/"+encodeURIComponent(T)+e:e}var m=document.getElementById("sidebar-content"),J=document.getElementById("main-placeholder"),D=document.getElementById("terminal-container"),ve=document.getElementById("file-editor"),xn=document.getElementById("fe-path"),H=document.getElementById("fe-status"),ge=document.getElementById("fe-content"),X=document.getElementById("fe-save"),Cn=document.getElementById("fe-delete"),kn=document.getElementById("fe-back"),wt=document.getElementById("fe-new-name"),Sn=document.getElementById("fe-new-btn"),Ze=document.getElementById("settings-backdrop"),bt=document.getElementById("settings-popover"),Lt=document.querySelector(".sidebar");function Tn(){return window.matchMedia("(max-width: 640px)").matches}function et(){Tn()&&Lt.classList.add("collapsed")}function Et(){Lt.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{Et(),xt("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{Et(),xt("files")});function xt(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"?(tt="",O()):_n()}var tt="";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===tt)return;tt=n,An(t)}catch{m.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")}),lt()}var Ct="tmux-web-sidebar-group-collapsed";function kt(){try{return new Set(JSON.parse(localStorage.getItem(Ct)||"[]"))}catch{return new Set}}function Mn(e){try{localStorage.setItem(Ct,JSON.stringify([...e]))}catch{}}function Bn(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 St(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=kt();for(let[o,u]of l){let h=Bn(o,r,t),k=c.has(o),b=document.createElement("div");b.className="session-group-header"+(k?" collapsed":""),b.title=o||"No working directory",b.innerHTML=`<span class="sg-folder">&#128193;</span><span class="sg-label">${f(h)}</span>`,b.addEventListener("click",()=>{let B=kt(),Q=b.nextElementSibling;B.has(o)?(B.delete(o),b.classList.remove("collapsed"),Q?.classList.remove("collapsed")):(B.add(o),b.classList.add("collapsed"),Q?.classList.add("collapsed")),Mn(B)});let M=document.createElement("div");M.className="session-group-body"+(k?" collapsed":"");for(let B of u)M.appendChild(n?In(B,n,s):Dn(B));m.appendChild(b),m.appendChild(M)}}function In(e,t,n){let s=document.createElement("div");return s.className="session-item"+(e.name===g&&T===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>
8
+ `).join("\r")}async function on(i){let a=tn(i.clipboardData);if(a){i.preventDefault(),i.stopPropagation();let w=Date.now();if(w-Ae<50)return;Ae=w,await Ve(a);return}let d=i.clipboardData?.getData("text/plain");if(!d)return;i.preventDefault(),i.stopPropagation();let p=Date.now();p-Ae<50||(Ae=p,s.pasteText(mt(d)))}let pe=0;function ln(i){i.preventDefault(),pe++,dt(i.dataTransfer)&&e.classList.add("terminal-drag-over")}function rn(i){i.preventDefault(),i.dataTransfer&&(i.dataTransfer.dropEffect="copy")}function cn(i){i.preventDefault(),pe--,pe<=0&&(pe=0,e.classList.remove("terminal-drag-over"))}async function dn(i){i.preventDefault(),pe=0,e.classList.remove("terminal-drag-over");let a=dt(i.dataTransfer);a&&await Ve(a)}function ft(i){!Jt||i.key!=="Escape"||re||i.defaultPrevented||i.repeat||i.metaKey||i.ctrlKey||i.altKey||s.isFocused()&&(i.preventDefault(),i.stopPropagation(),le("\x1B"))}e.addEventListener("paste",on),e.addEventListener("dragenter",ln),e.addEventListener("dragover",rn),e.addEventListener("dragleave",cn),e.addEventListener("drop",dn),document.addEventListener("keydown",ft,!0);function un(i){if(i.touches.length!==1){o=null;return}let a=i.touches[0];if(!a)return;ke();let d=a.clientX-e.getBoundingClientRect().left<e.clientWidth*.4?"tui":"history";o={startX:a.clientX,startY:a.clientY,lastX:a.clientX,lastY:a.clientY,lastT:performance.now(),velocity:0,scrolling:!1,zone:d,tuiAtStart:h,tuiAccum:0},i.stopPropagation()}function pn(i){if(!o||i.touches.length!==1)return;let a=i.touches[0];if(!a)return;let d=a.clientY-o.startY,p=a.clientX-o.startX;if(!o.scrolling){if(Math.abs(d)<8||Math.abs(d)<Math.abs(p))return;o.scrolling=!0,Ke=Date.now()+500}i.preventDefault(),i.stopPropagation();let w=performance.now(),I=a.clientY-o.lastY;if(o.zone==="tui"){if(!h){o.lastX=a.clientX,o.lastY=a.clientY,o.lastT=w;return}o.tuiAccum+=I;let Y=e.querySelector(".xterm-rows > div"),He=Y?Y.getBoundingClientRect().height:16,gt=Math.max(16,He);for(;Math.abs(o.tuiAccum)>=gt;)le(Z(o.tuiAccum>0)),o.tuiAccum-=Math.sign(o.tuiAccum)*gt;o.lastX=a.clientX,o.lastY=a.clientY,o.lastT=w;return}let V=w-o.lastT;V>0&&(o.velocity=I/V),vn(-I),o.lastX=a.clientX,o.lastY=a.clientY,o.lastT=w}function mn(i){if(!o)return;let a=o.scrolling,d=o.tuiAtStart,p=o.velocity;if(o=null,i.stopPropagation(),!a){s.focus();return}Ke=Date.now()+500,i.preventDefault(),!d&&p&&Ot(p)}function fn(i){o=null,ke(),i.stopPropagation()}function hn(i){i.pointerType==="touch"&&Date.now()<Ke&&(i.preventDefault(),i.stopPropagation())}function vn(i){let a=e.querySelector(".xterm-rows > div"),d=a?a.getBoundingClientRect().height:16,p=d>0?Math.round(i/d):i>0?1:-1;p===0&&(p=i>0?1:-1),s.scrollLines(p)}e.addEventListener("touchstart",un,{passive:!0,capture:!0}),e.addEventListener("touchmove",pn,{passive:!1,capture:!0}),e.addEventListener("touchend",mn,{passive:!1,capture:!0}),e.addEventListener("touchcancel",fn,{passive:!0,capture:!0}),e.addEventListener("pointerup",hn,!0);function ht(){S()}window.addEventListener("resize",ht),window.visualViewport?.addEventListener("resize",S),window.visualViewport?.addEventListener("scroll",S);let vt=new ResizeObserver(()=>S());vt.observe(e),document.fonts?.ready.then(()=>{S(),setTimeout(S,50),setTimeout(S,200)}),e.addEventListener("focusin",en,!0);async function gn(){if(document.fonts?.ready)try{await Promise.race([document.fonts.ready,new Promise(i=>setTimeout(i,1e3))])}catch{}}return requestAnimationFrame(()=>{K()&&Be(),(async()=>(await gn(),K()&&q({type:"resize",cols:s.cols,rows:s.rows}),rt(),S()))()}),{destroy(){if(_=!0,ke(),ee(!1),ue&&clearTimeout(ue),document.removeEventListener("mousemove",Xe,!0),document.removeEventListener("mouseup",Je,!0),l){try{l.close(1e3,"session switch")}catch{}l=void 0}e.innerHTML="",e.classList.remove("terminal-pending"),window.removeEventListener("resize",ht),vt.disconnect(),document.removeEventListener("keydown",ft,!0)},focus(){s.focus()},sendInput(i){le(i)},toggleCopyMode(){pt()}}})()}var fe=window.__TMUX_WEB_SHELL__,v=null,g=null,he=typeof window.__TMUX_WEB_SCOPE__?.agentId=="string"?window.__TMUX_WEB_SCOPE__.agentId:null,T=he;window.__tmuxWebScopeAgent=he;var Ze="sessions",U="",Ne="",Re="",yt="";function x(e){return T?"/a/"+encodeURIComponent(T)+e:e}var m=document.getElementById("sidebar-content"),X=document.getElementById("main-placeholder"),D=document.getElementById("terminal-container"),ve=document.getElementById("file-editor"),xn=document.getElementById("fe-path"),H=document.getElementById("fe-status"),ge=document.getElementById("fe-content"),J=document.getElementById("fe-save"),Cn=document.getElementById("fe-delete"),kn=document.getElementById("fe-back"),wt=document.getElementById("fe-new-name"),Sn=document.getElementById("fe-new-btn"),Ge=document.getElementById("settings-backdrop"),bt=document.getElementById("settings-popover"),Lt=document.querySelector(".sidebar");function Tn(){return window.matchMedia("(max-width: 640px)").matches}function et(){Tn()&&Lt.classList.add("collapsed")}function Et(){Lt.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{Et(),xt("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{Et(),xt("files")});function xt(e){Ze=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"?(tt="",W()):_n()}var tt="";async function W(){if(Ze!=="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===tt)return;tt=n,An(t)}catch{m.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")}),lt()}var Ct="tmux-web-sidebar-group-collapsed";function kt(){try{return new Set(JSON.parse(localStorage.getItem(Ct)||"[]"))}catch{return new Set}}function Mn(e){try{localStorage.setItem(Ct,JSON.stringify([...e]))}catch{}}function Bn(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 St(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=kt();for(let[o,u]of l){let h=Bn(o,r,t),k=c.has(o),b=document.createElement("div");b.className="session-group-header"+(k?" collapsed":""),b.title=o||"No working directory",b.innerHTML=`<span class="sg-folder">&#128193;</span><span class="sg-label">${f(h)}</span>`,b.addEventListener("click",()=>{let B=kt(),Z=b.nextElementSibling;B.has(o)?(B.delete(o),b.classList.remove("collapsed"),Z?.classList.remove("collapsed")):(B.add(o),b.classList.add("collapsed"),Z?.classList.add("collapsed")),Mn(B)});let M=document.createElement("div");M.className="session-group-body"+(k?" collapsed":"");for(let B of u)M.appendChild(n?In(B,n,s):Dn(B));m.appendChild(b),m.appendChild(M)}}function In(e,t,n){let s=document.createElement("div");return s.className="session-item"+(e.name===g&&T===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
9
  <span>${f(e.name)}</span>${n?"":'<span class="meta">offline</span>'}`,n&&s.addEventListener("click",l=>{l.target.closest(".session-edit-btn")||ye(e.name,t)}),s}function Dn(e){let t=document.createElement("div");t.className="session-item"+(e.name===g&&!T?" 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>${f(e.name)}</span>
11
11
  <button class="session-edit-btn" data-session="${f(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
12
  `,t.addEventListener("click",s=>{s.target.closest(".session-edit-btn")||ye(e.name)});let n=t.querySelector(".session-edit-btn");return n&&n.addEventListener("click",s=>{s.stopPropagation(),$t(e.name,n)}),t}function An(e){m.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"+(he?" clickable":""),n.textContent=he?"\u2190 \u8FD4\u56DE\u672C\u673A":"\u672C\u673A",he&&(n.title="Back to hub",n.addEventListener("click",()=>{window.location.href="/"})),m.appendChild(n),St(t,e.home);let s=e.agents||[];for(let r of s){if(!r.sessions||r.sessions.length===0)continue;let c=r.agentId===T,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)+"/"})),m.appendChild(o),St(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",m.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>${f(c.name)}</span><span class="meta">\u5931\u6548${u}</span>
14
- <button class="session-edit-btn" data-session="${f(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 h=o.querySelector(".session-edit-btn");h&&h.addEventListener("click",k=>{k.stopPropagation(),$t(c.name,h,{tombstone:!0,agentId:c.agentId})}),m.appendChild(o)}}}function f(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function ye(e,t){if(!(g===e&&v&&T===(t||null))){ve.style.display="none",J.style.display="none",D.style.display="",D.classList.add("terminal-pending"),et(),v&&(Oe(),v.destroy(),v=null),g=e,T=t||null,window.__tmuxWebScopeAgent=T,window.__tmuxWebCurrentSession=g,Zn(e,t);for(let n of m.querySelectorAll(".session-item"))n.classList.toggle("active",n.getAttribute("data-session")===e&&(n.getAttribute("data-agent")||null)===T);try{v=await En(D,e,{terminal:fe.terminal,scrollback:fe.scrollback,theme:fe.theme,wsBase:T?"/ws/a/"+encodeURIComponent(T):fe.wsBase||"/ws"}),Rt()}catch(n){console.error("[shell] terminal init failed:",n);let s=n&&typeof n=="object"&&"message"in n?n.message:String(n);D.textContent="Failed to open terminal for "+e+": "+s,D.classList.remove("terminal-pending")}}}var $e=[],y=null,Tt=!1;function Hn(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 Fn(e){Tt=!0;try{let t=await fetch(x("/api/git/status?path="+encodeURIComponent(e)));t.ok?y=await t.json():y=null}catch{y=null}finally{Tt=!1}}function Nn(){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="${f(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 h=o.querySelector(".session-edit-btn");h&&h.addEventListener("click",k=>{k.stopPropagation(),$t(c.name,h,{tombstone:!0,agentId:c.agentId})}),m.appendChild(o)}}}function f(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function ye(e,t){if(!(g===e&&v&&T===(t||null))){ve.style.display="none",X.style.display="none",D.style.display="",D.classList.add("terminal-pending"),et(),v&&(We(),v.destroy(),v=null),g=e,T=t||null,window.__tmuxWebScopeAgent=T,window.__tmuxWebCurrentSession=g,Gn(e,t);for(let n of m.querySelectorAll(".session-item"))n.classList.toggle("active",n.getAttribute("data-session")===e&&(n.getAttribute("data-agent")||null)===T);try{v=await En(D,e,{terminal:fe.terminal,scrollback:fe.scrollback,theme:fe.theme,wsBase:T?"/ws/a/"+encodeURIComponent(T):fe.wsBase||"/ws"}),Rt()}catch(n){console.error("[shell] terminal init failed:",n);let s=n&&typeof n=="object"&&"message"in n?n.message:String(n);D.textContent="Failed to open terminal for "+e+": "+s,D.classList.remove("terminal-pending")}}}var $e=[],y=null,Tt=!1;function Hn(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 Fn(e){Tt=!0;try{let t=await fetch(x("/api/git/status?path="+encodeURIComponent(e)));t.ok?y=await t.json():y=null}catch{y=null}finally{Tt=!1}}function Nn(){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
- ${f(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>"}m.addEventListener("click",e=>{e.target.closest(".sidebar-git")&&te&&y&&(e.stopPropagation(),At())});var we=document.getElementById("header-git"),Mt=document.getElementById("git-diff-view"),Bt=document.getElementById("gd-path"),Pe=document.getElementById("gd-status"),je=document.getElementById("gd-content"),Rn=document.getElementById("gd-back"),te=null;function be(e){if(!e||!e.branch){we.style.display="none",te=null;return}te=e.repoRoot;let{branch:t,linesAdded:n,linesRemoved:s}=e,l=`<span class="branch">${f(t)}</span>`;(n>0||s>0)&&(l+=`<span class="sep">\xB7</span>+<span class="diff-add">${n}</span> <span class="diff-del">-${s}</span>`),we.innerHTML=l,we.style.display="block"}we.addEventListener("click",e=>{te&&y&&(e.stopPropagation(),At())});var C=document.getElementById("git-popover"),ze=document.getElementById("git-popover-backdrop");function nt(){let e=we.getBoundingClientRect();C.style.top=e.bottom+4+"px",C.style.left=Math.max(8,Math.min(e.left,window.innerWidth-400))+"px"}function It(){let e=te,t=document.getElementById("git-popover-browse");t&&t.addEventListener("click",()=>{if(Ue(),e){Qe="files",document.querySelectorAll(".mode-btn").forEach(s=>s.classList.remove("active"));let n=document.getElementById("mode-files");n&&n.classList.add("active"),W(e)}})}var Dt="";function At(){if(!y)return;let e=y.files||[];if(!e.length)C.innerHTML=`<div class="git-popover-header">No changes \u2014 clean working tree</div>
16
+ ${f(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>"}m.addEventListener("click",e=>{e.target.closest(".sidebar-git")&&te&&y&&(e.stopPropagation(),At())});var we=document.getElementById("header-git"),Mt=document.getElementById("git-diff-view"),Bt=document.getElementById("gd-path"),Pe=document.getElementById("gd-status"),ze=document.getElementById("gd-content"),Rn=document.getElementById("gd-back"),te=null;function be(e){if(!e||!e.branch){we.style.display="none",te=null;return}te=e.repoRoot;let{branch:t,linesAdded:n,linesRemoved:s}=e,l=`<span class="branch">${f(t)}</span>`;(n>0||s>0)&&(l+=`<span class="sep">\xB7</span>+<span class="diff-add">${n}</span> <span class="diff-del">-${s}</span>`),we.innerHTML=l,we.style.display="block"}we.addEventListener("click",e=>{te&&y&&(e.stopPropagation(),At())});var C=document.getElementById("git-popover"),je=document.getElementById("git-popover-backdrop");function nt(){let e=we.getBoundingClientRect();C.style.top=e.bottom+4+"px",C.style.left=Math.max(8,Math.min(e.left,window.innerWidth-400))+"px"}function It(){let e=te,t=document.getElementById("git-popover-browse");t&&t.addEventListener("click",()=>{if(Ye(),e){Ze="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 Dt="";function At(){if(!y)return;let e=y.files||[];if(!e.length)C.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">${f(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>',Dt=t,C.innerHTML=t,C.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",()=>Ft(l.path)))})}nt(),C.classList.add("open"),ze.classList.add("open"),It()}function $n(){return window.innerWidth>=1024}function Ht(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>',Dt=t,C.innerHTML=t,C.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",()=>Ft(l.path)))})}nt(),C.classList.add("open"),je.classList.add("open"),It()}function $n(){return window.innerWidth>=1024}function Ht(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">${f(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">${f(o)}</span></div>`);continue}if(o.startsWith("+"))r++,s+=`<div class="diff-line add"><span class="ln-no">${r}</span><span class="ln-body">${f(o)}</span></div>`;else if(o.startsWith("-"))l++,s+=`<div class="diff-line del"><span class="ln-no">${l}</span><span class="ln-body">${f(o)}</span></div>`;else if(o.startsWith("\\"))s+=`<div class="diff-line"><span class="ln-body">${f(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">${f(o)}</span></div>`}}return{html:s,lineCount:n.length}}var _e=null;async function Ft(e){let t=te;if(t)if(Ue(),$n()){D.style.display="none",v&&(Oe(),v.destroy(),v=null,_e=g,g=null),be(null),ve.style.display="none",J.style.display="none",Mt.style.display="flex",Bt.textContent=e,Pe.textContent="Loading\u2026",je.innerHTML="";try{let n=await fetch(x("/api/git/diff?path="+encodeURIComponent(t)+"&file="+encodeURIComponent(e)));if(!n.ok)throw new Error(await n.text());let s=await n.json();jn(e,s.diff,s.stagedDiff)}catch(n){let s=n instanceof Error?n.message:String(n);Pe.textContent="Error",je.innerHTML=`<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">Error: ${f(s)}</div>`}}else{C.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">${f(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">${f(o)}</span></div>`);continue}if(o.startsWith("+"))r++,s+=`<div class="diff-line add"><span class="ln-no">${r}</span><span class="ln-body">${f(o)}</span></div>`;else if(o.startsWith("-"))l++,s+=`<div class="diff-line del"><span class="ln-no">${l}</span><span class="ln-body">${f(o)}</span></div>`;else if(o.startsWith("\\"))s+=`<div class="diff-line"><span class="ln-body">${f(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">${f(o)}</span></div>`}}return{html:s,lineCount:n.length}}var _e=null;async function Ft(e){let t=te;if(t)if(Ye(),$n()){D.style.display="none",v&&(We(),v.destroy(),v=null,_e=g,g=null),be(null),ve.style.display="none",X.style.display="none",Mt.style.display="flex",Bt.textContent=e,Pe.textContent="Loading\u2026",ze.innerHTML="";try{let n=await fetch(x("/api/git/diff?path="+encodeURIComponent(t)+"&file="+encodeURIComponent(e)));if(!n.ok)throw new Error(await n.text());let s=await n.json();zn(e,s.diff,s.stagedDiff)}catch(n){let s=n instanceof Error?n.message:String(n);Pe.textContent="Error",ze.innerHTML=`<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">Error: ${f(s)}</div>`}}else{C.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">${f(e)}</span>
26
26
  <span class="diff-loading">Loading\u2026</span>
27
- </div></div>`,nt(),C.classList.add("open"),ze.classList.add("open");try{let n=await fetch(x("/api/git/diff?path="+encodeURIComponent(t)+"&file="+encodeURIComponent(e)));if(!n.ok)throw new Error(await n.text());let s=await n.json();Pn(e,s.diff,s.stagedDiff)}catch(n){let s=n instanceof Error?n.message:String(n);C.innerHTML=`<div class="git-diff-view"><div class="diff-header">
27
+ </div></div>`,nt(),C.classList.add("open"),je.classList.add("open");try{let n=await fetch(x("/api/git/diff?path="+encodeURIComponent(t)+"&file="+encodeURIComponent(e)));if(!n.ok)throw new Error(await n.text());let s=await n.json();Pn(e,s.diff,s.stagedDiff)}catch(n){let s=n instanceof Error?n.message:String(n);C.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">${f(e)}</span>
30
30
  </div><div class="diff-empty">Error loading diff: ${f(s)}</div></div>`}}}function Pn(e,t,n){if(!t&&!n){C.innerHTML=`<div class="git-diff-view"><div class="diff-header">
@@ -34,7 +34,7 @@ var yn=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function
34
34
  <button class="diff-back">\u2190 Back</button>
35
35
  <span class="diff-filename">${f(e)}</span>
36
36
  <span class="diff-filesize">${l} lines</span>
37
- </div><div class="diff-content">${s}</div></div>`,C.querySelector(".diff-back")?.addEventListener("click",()=>{C.innerHTML=Dt,nt(),y&&C.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",()=>Ft(o.path)))}),It()})}function jn(e,t,n){if(!t&&!n){Pe.textContent="No diff",je.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}=Ht(t,n);Bt.textContent=e,Pe.textContent=l+" lines",je.innerHTML=s}function zn(){Mt.style.display="none",_e?(D.style.display="",D.classList.add("terminal-pending"),ye(_e),_e=null):g?(D.style.display="",D.classList.add("terminal-pending"),Rt()):J.style.display="flex"}Rn.addEventListener("click",zn);function Ue(){C.classList.remove("open"),ze.classList.remove("open")}ze.addEventListener("click",Ue),document.addEventListener("keydown",e=>{e.key==="Escape"&&(Ue(),qe())});async function Nt(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,be(s);return}}}catch{}y=null,be(null)}var Ye=null;function Rt(){Oe(),g&&(Nt(g),Ye=setInterval(()=>{g&&Nt(g)},3e4))}function Oe(){Ye&&(clearInterval(Ye),Ye=null)}function _n(){if($e=fe.fsRoots||[],$e.length===0){if(g){Un(g);return}m.innerHTML='<div class="file-tree-info">Open a session first, then switch to Files to browse its directory.</div>';return}m.innerHTML="";for(let e of $e){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> ${f(e)}`,t.addEventListener("click",()=>W(e)),m.appendChild(t)}}async function Un(e){m.innerHTML='<div class="file-tree-empty">Loading...</div>';try{let t=await(await fetch(x("/api/fs/session-path?session="+encodeURIComponent(e)))).json();t.path?W(t.path):m.innerHTML='<div class="file-tree-info">Could not determine session directory.</div>'}catch{m.innerHTML='<div class="file-tree-error">Failed to get session directory</div>'}}async function W(e){Y=e,m.innerHTML='<div class="file-tree-empty">Loading...</div>';let t=Fn(e);try{let n=await(await fetch(x("/api/fs/list?path="+encodeURIComponent(e)))).json();await t,m.innerHTML="",be(y),m.innerHTML+=Nn();let s=Yn(e);if(s&&!$e.some(r=>e===r)){let r=document.createElement("div");r.className="file-tree-item",r.innerHTML="..",r.addEventListener("click",()=>W(s)),m.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> ${f(c)}`,o.addEventListener("click",()=>W(r)),m.appendChild(o)}else m.innerHTML="";let l=n.files||[];for(let r of l){let c=r.split("/").pop()||r.split("\\").pop(),o=Hn(r),u="",h="";if(o)switch(o){case"M":u="git-mod",h='<span class="git-file-status M">M</span>';break;case"A":u="git-add",h='<span class="git-file-status A">A</span>';break;case"D":u="git-del",h='<span class="git-file-status D">D</span>';break;case"?":u="git-untracked",h='<span class="git-file-status ?">?</span>';break;case"R":u="git-mod",h='<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> ${h}${f(c)}`,k.addEventListener("click",()=>On(r)),m.appendChild(k)}}catch{m.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function Yn(e){let t=e.lastIndexOf("/");return t<=0?null:e.substring(0,t)}async function On(e){Ne=e,D.style.display="none",v&&(Oe(),v.destroy(),v=null,g=null),be(null),et(),J.style.display="none",ve.style.display="flex",xn.textContent=e,H.textContent="Loading...",X.style.display="none";try{let t=await fetch(x("/api/file?path="+encodeURIComponent(e)));if(!t.ok){let s=await t.json();H.textContent=s.error||"Failed to load",ge.value="";return}let n=await t.json();ge.value=n.content,Re=n.content,yt=n.content,H.textContent=n.size+" bytes",X.style.display=""}catch{H.textContent="Failed to load",ge.value=""}}ge.addEventListener("input",()=>{Re=ge.value}),X.addEventListener("click",async()=>{X.textContent="Saving...",X.disabled=!0;try{let e=await fetch(x("/api/file"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:Ne,content:Re})});if(!e.ok){let t=await e.json();H.textContent=t.error||"Save failed";return}yt=Re,H.textContent="Saved"}catch{H.textContent="Save failed"}finally{X.disabled=!1,X.textContent="Save"}}),Cn.addEventListener("click",async()=>{if(confirm("Delete "+Ne+"?"))try{let e=await fetch(x("/api/file/delete"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:Ne})});if(!e.ok){let t=await e.json();H.textContent=t.error||"Delete failed";return}ve.style.display="none",J.style.display="flex",Y&&W(Y)}catch{H.textContent="Delete failed"}}),kn.addEventListener("click",()=>{ve.style.display="none",J.style.display="flex",Y&&W(Y)}),Sn.addEventListener("click",async()=>{let e=wt.value.trim();if(!e)return;let t=Y+"/"+e;try{let n=await fetch(x("/api/file/touch"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!n.ok){let s=await n.json();H.textContent=s.error||"Create failed";return}wt.value="",Y&&W(Y)}catch{H.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{let e=bt.classList.toggle("open");Ze.classList.toggle("open",e)}),Ze.addEventListener("click",()=>{bt.classList.remove("open"),Ze.classList.remove("open")});var A="",z=!1,We,Le=document.createElement("div");Le.className="session-popover-backdrop",document.body.appendChild(Le);var R=document.createElement("div");R.id="session-popover",R.className="session-popover",R.style.display="none",R.innerHTML=`<div class="sp-field">
37
+ </div><div class="diff-content">${s}</div></div>`,C.querySelector(".diff-back")?.addEventListener("click",()=>{C.innerHTML=Dt,nt(),y&&C.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",()=>Ft(o.path)))}),It()})}function zn(e,t,n){if(!t&&!n){Pe.textContent="No diff",ze.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}=Ht(t,n);Bt.textContent=e,Pe.textContent=l+" lines",ze.innerHTML=s}function jn(){Mt.style.display="none",_e?(D.style.display="",D.classList.add("terminal-pending"),ye(_e),_e=null):g?(D.style.display="",D.classList.add("terminal-pending"),Rt()):X.style.display="flex"}Rn.addEventListener("click",jn);function Ye(){C.classList.remove("open"),je.classList.remove("open")}je.addEventListener("click",Ye),document.addEventListener("keydown",e=>{e.key==="Escape"&&(Ye(),qe())});async function Nt(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,be(s);return}}}catch{}y=null,be(null)}var Ue=null;function Rt(){We(),g&&(Nt(g),Ue=setInterval(()=>{g&&Nt(g)},3e4))}function We(){Ue&&(clearInterval(Ue),Ue=null)}function _n(){if($e=fe.fsRoots||[],$e.length===0){if(g){Yn(g);return}m.innerHTML='<div class="file-tree-info">Open a session first, then switch to Files to browse its directory.</div>';return}m.innerHTML="";for(let e of $e){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> ${f(e)}`,t.addEventListener("click",()=>O(e)),m.appendChild(t)}}async function Yn(e){m.innerHTML='<div class="file-tree-empty">Loading...</div>';try{let t=await(await fetch(x("/api/fs/session-path?session="+encodeURIComponent(e)))).json();t.path?O(t.path):m.innerHTML='<div class="file-tree-info">Could not determine session directory.</div>'}catch{m.innerHTML='<div class="file-tree-error">Failed to get session directory</div>'}}async function O(e){U=e,m.innerHTML='<div class="file-tree-empty">Loading...</div>';let t=Fn(e);try{let n=await(await fetch(x("/api/fs/list?path="+encodeURIComponent(e)))).json();await t,m.innerHTML="",be(y),m.innerHTML+=Nn();let s=Un(e);if(s&&!$e.some(r=>e===r)){let r=document.createElement("div");r.className="file-tree-item",r.innerHTML="..",r.addEventListener("click",()=>O(s)),m.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> ${f(c)}`,o.addEventListener("click",()=>O(r)),m.appendChild(o)}else m.innerHTML="";let l=n.files||[];for(let r of l){let c=r.split("/").pop()||r.split("\\").pop(),o=Hn(r),u="",h="";if(o)switch(o){case"M":u="git-mod",h='<span class="git-file-status M">M</span>';break;case"A":u="git-add",h='<span class="git-file-status A">A</span>';break;case"D":u="git-del",h='<span class="git-file-status D">D</span>';break;case"?":u="git-untracked",h='<span class="git-file-status ?">?</span>';break;case"R":u="git-mod",h='<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> ${h}${f(c)}`,k.addEventListener("click",()=>Wn(r)),m.appendChild(k)}}catch{m.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function Un(e){let t=e.lastIndexOf("/");return t<=0?null:e.substring(0,t)}async function Wn(e){Ne=e,D.style.display="none",v&&(We(),v.destroy(),v=null,g=null),be(null),et(),X.style.display="none",ve.style.display="flex",xn.textContent=e,H.textContent="Loading...",J.style.display="none";try{let t=await fetch(x("/api/file?path="+encodeURIComponent(e)));if(!t.ok){let s=await t.json();H.textContent=s.error||"Failed to load",ge.value="";return}let n=await t.json();ge.value=n.content,Re=n.content,yt=n.content,H.textContent=n.size+" bytes",J.style.display=""}catch{H.textContent="Failed to load",ge.value=""}}ge.addEventListener("input",()=>{Re=ge.value}),J.addEventListener("click",async()=>{J.textContent="Saving...",J.disabled=!0;try{let e=await fetch(x("/api/file"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:Ne,content:Re})});if(!e.ok){let t=await e.json();H.textContent=t.error||"Save failed";return}yt=Re,H.textContent="Saved"}catch{H.textContent="Save failed"}finally{J.disabled=!1,J.textContent="Save"}}),Cn.addEventListener("click",async()=>{if(confirm("Delete "+Ne+"?"))try{let e=await fetch(x("/api/file/delete"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:Ne})});if(!e.ok){let t=await e.json();H.textContent=t.error||"Delete failed";return}ve.style.display="none",X.style.display="flex",U&&O(U)}catch{H.textContent="Delete failed"}}),kn.addEventListener("click",()=>{ve.style.display="none",X.style.display="flex",U&&O(U)}),Sn.addEventListener("click",async()=>{let e=wt.value.trim();if(!e)return;let t=U+"/"+e;try{let n=await fetch(x("/api/file/touch"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!n.ok){let s=await n.json();H.textContent=s.error||"Create failed";return}wt.value="",U&&O(U)}catch{H.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{let e=bt.classList.toggle("open");Ge.classList.toggle("open",e)}),Ge.addEventListener("click",()=>{bt.classList.remove("open"),Ge.classList.remove("open")});var A="",j=!1,Oe,Le=document.createElement("div");Le.className="session-popover-backdrop",document.body.appendChild(Le);var R=document.createElement("div");R.id="session-popover",R.className="session-popover",R.style.display="none",R.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 yn=/\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(R);function Wn(e){let t=e.getBoundingClientRect();R.style.top=t.bottom+4+"px",R.style.left=Math.max(8,Math.min(t.left,window.innerWidth-240))+"px"}function $t(e,t,n){A=e,z=!!n?.tombstone,We=n?.agentId;let s=document.getElementById("sp-name");s.value=e;let l=R.querySelector(".sp-field label");l.textContent=z?"\u91CD\u547D\u540D (\u4EC5\u8BB0\u5F55\uFF0C\u4E0D\u91CD\u5EFA)":"Rename session";let r=document.getElementById("sp-rebuild");r.style.display=z?"":"none";let c=document.getElementById("sp-delete");c.textContent=z?"\u5220\u9664\u5931\u6548\u8BB0\u5F55 (\u5893\u7891\u6D88\u5931)":"Delete session";let o=document.getElementById("sp-save");o.textContent=z?"\u91CD\u547D\u540D":"Save",Le.classList.add("open"),R.style.display="block",Wn(t),setTimeout(()=>s.focus(),50)}function G(){Le.classList.remove("open"),R.style.display="none"}Le.addEventListener("click",G),document.getElementById("sp-save").addEventListener("click",async()=>{let e=document.getElementById("sp-name").value.trim();if(!e||e===A){G();return}try{let t=z?{oldName:A,newName:e,agentId:We}:{oldName:A,newName:e};if(!(await fetch(x(z?"/api/sessions/rename-tombstone":"/api/sessions/rename"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})).ok)return;G(),O(),!z&&g===A&&ye(e)}catch{}}),document.getElementById("sp-rebuild").addEventListener("click",async()=>{if(confirm('\u91CD\u5EFA\u4F1A\u8BDD "'+A+'" (\u540C\u540D\u540C\u8DEF\u5F84\uFF0C\u5185\u5BB9\u4E3A\u7A7A)\uFF1F'))try{let e=await fetch(x("/api/sessions/rebuild"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:A,agentId:We})});if(!e.ok){let t=await e.json();alert(t.error||"\u91CD\u5EFA\u5931\u8D25");return}G(),O()}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(z){if(!confirm('\u5220\u9664\u5931\u6548\u8BB0\u5F55 "'+A+'"\uFF1F'))return;try{if(!(await fetch(x("/api/sessions/dismiss"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:A,agentId:We})})).ok)return;G(),O()}catch{}return}if(confirm('Delete session "'+A+'"?'))try{if(!(await fetch(x("/api/sessions/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:A})})).ok)return;G(),g===A&&(v&&(v.destroy(),v=null),g=null,D.style.display="none",J.style.display="flex"),O()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",G);var qn={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=qn[t.dataset.key];n&&(v.sendInput(n),v.focus())});var $=document.getElementById("mk-input"),Pt=document.getElementById("mk-send");function jt(){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(),jt())})),Pt&&Pt.addEventListener("click",jt),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 st=document.getElementById("process-panel"),Ee=document.getElementById("proc-list"),Kn=document.getElementById("proc-close"),it=document.getElementById("proc-backdrop"),Vn=document.getElementById("header-ram");function Jn(){Ee.innerHTML='<div class="proc-empty">Loading\u2026</div>',fetch(x("/api/system/processes")).then(e=>e.json()).then(e=>{if(!Array.isArray(e)||!e.length){Ee.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="'+f(n.command)+'">'+f(n.command)+'</span><button class="proc-kill" title="Kill PID '+n.pid+'">&times;</button></div>'}Ee.innerHTML=t;for(let n of Ee.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(x("/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(()=>{Ee.innerHTML='<div class="proc-empty">Failed to load</div>'})}function Xn(){st.classList.add("open"),it.classList.add("open"),Jn()}function qe(){st.classList.remove("open"),it.classList.remove("open")}Vn.addEventListener("click",e=>{e.stopPropagation(),st.classList.contains("open")?qe():Xn()}),Kn.addEventListener("click",qe),it.addEventListener("click",qe);var Gn=2e3,xe=null,at=null,ne=new Map,Ce=new Map;function zt(e,t){return(t?"a:"+t+":":"l:")+e}function Qn(e,t,n){let s=zt(e,t),l=Ce.get(s),r=e===g&&(t??null)===T,c=n==="idle"&&l?.state==="working";Ce.set(s,{session:e,agentId:t,state:n,doneUntil:c?Date.now()+Gn: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=m.querySelector(o);u&&ot(u,s,Ce.get(s))}function ot(e,t,n){let s=ne.get(t);s&&(clearTimeout(s),ne.delete(t)),e.classList.remove("working","just-done");let l=n.session===g&&(n.agentId??null)===T;n.state==="working"?e.classList.add("working"):l&&n.doneUntil&&Date.now()<n.doneUntil?(e.classList.add("just-done"),ne.set(t,setTimeout(()=>{e.classList.remove("just-done"),ne.delete(t)},Math.max(0,n.doneUntil-Date.now())))):!l&&n.unread&&e.classList.add("just-done")}function lt(){for(let[e,t]of Ce){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=m.querySelector(n);s&&ot(s,e,t)}}function Zn(e,t){let n=zt(e,t),s=Ce.get(n);if(!s)return;let l=ne.get(n);l&&(clearTimeout(l),ne.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=m.querySelector(r);c&&ot(c,n,s)}function _t(){if(xe||at)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);xe=n,n.onmessage=s=>{try{let l=JSON.parse(String(s.data));l&&l.type==="session.activity"&&typeof l.session=="string"&&Qn(l.session,l.agentId||void 0,l.state==="working"?"working":"idle")}catch{}},n.onclose=()=>{xe===n&&(xe=null,at=setTimeout(()=>{at=null,_t()},5e3))},n.onerror=()=>{try{n.close()}catch{}}}catch{xe=null}}window.__openSession=ye,window.__refreshSidebar=O,O(),et(),lt(),_t(),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&lt()}),setInterval(()=>{document.visibilityState==="visible"&&O()},1e4);
47
+ <button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(R);function On(e){let t=e.getBoundingClientRect();R.style.top=t.bottom+4+"px",R.style.left=Math.max(8,Math.min(t.left,window.innerWidth-240))+"px"}function $t(e,t,n){A=e,j=!!n?.tombstone,Oe=n?.agentId;let s=document.getElementById("sp-name");s.value=e;let l=R.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",Le.classList.add("open"),R.style.display="block",On(t),setTimeout(()=>s.focus(),50)}function Q(){Le.classList.remove("open"),R.style.display="none"}Le.addEventListener("click",Q),document.getElementById("sp-save").addEventListener("click",async()=>{let e=document.getElementById("sp-name").value.trim();if(!e||e===A){Q();return}try{let t=j?{oldName:A,newName:e,agentId:Oe}:{oldName:A,newName:e};if(!(await fetch(x(j?"/api/sessions/rename-tombstone":"/api/sessions/rename"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})).ok)return;Q(),W(),!j&&g===A&&ye(e)}catch{}}),document.getElementById("sp-rebuild").addEventListener("click",async()=>{if(confirm('\u91CD\u5EFA\u4F1A\u8BDD "'+A+'" (\u540C\u540D\u540C\u8DEF\u5F84\uFF0C\u5185\u5BB9\u4E3A\u7A7A)\uFF1F'))try{let e=await fetch(x("/api/sessions/rebuild"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:A,agentId:Oe})});if(!e.ok){let t=await e.json();alert(t.error||"\u91CD\u5EFA\u5931\u8D25");return}Q(),W()}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(j){if(!confirm('\u5220\u9664\u5931\u6548\u8BB0\u5F55 "'+A+'"\uFF1F'))return;try{if(!(await fetch(x("/api/sessions/dismiss"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:A,agentId:Oe})})).ok)return;Q(),W()}catch{}return}if(confirm('Delete session "'+A+'"?'))try{if(!(await fetch(x("/api/sessions/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:A})})).ok)return;Q(),g===A&&(v&&(v.destroy(),v=null),g=null,D.style.display="none",X.style.display="flex"),W()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",Q);var qn={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=qn[t.dataset.key];n&&(v.sendInput(n),v.focus())});var $=document.getElementById("mk-input"),Pt=document.getElementById("mk-send");function zt(){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(),zt())})),Pt&&Pt.addEventListener("click",zt),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 st=document.getElementById("process-panel"),Ee=document.getElementById("proc-list"),Kn=document.getElementById("proc-close"),it=document.getElementById("proc-backdrop"),Vn=document.getElementById("header-ram");function Xn(){Ee.innerHTML='<div class="proc-empty">Loading\u2026</div>',fetch(x("/api/system/processes")).then(e=>e.json()).then(e=>{if(!Array.isArray(e)||!e.length){Ee.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="'+f(n.command)+'">'+f(n.command)+'</span><button class="proc-kill" title="Kill PID '+n.pid+'">&times;</button></div>'}Ee.innerHTML=t;for(let n of Ee.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(x("/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(()=>{Ee.innerHTML='<div class="proc-empty">Failed to load</div>'})}function Jn(){st.classList.add("open"),it.classList.add("open"),Xn()}function qe(){st.classList.remove("open"),it.classList.remove("open")}Vn.addEventListener("click",e=>{e.stopPropagation(),st.classList.contains("open")?qe():Jn()}),Kn.addEventListener("click",qe),it.addEventListener("click",qe);var Qn=2e3,xe=null,at=null,ne=new Map,Ce=new Map;function jt(e,t){return(t?"a:"+t+":":"l:")+e}function Zn(e,t,n){let s=jt(e,t),l=Ce.get(s),r=e===g&&(t??null)===T,c=n==="idle"&&l?.state==="working";Ce.set(s,{session:e,agentId:t,state:n,doneUntil:c?Date.now()+Qn: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=m.querySelector(o);u&&ot(u,s,Ce.get(s))}function ot(e,t,n){let s=ne.get(t);s&&(clearTimeout(s),ne.delete(t)),e.classList.remove("working","just-done");let l=n.session===g&&(n.agentId??null)===T;n.state==="working"?e.classList.add("working"):l&&n.doneUntil&&Date.now()<n.doneUntil?(e.classList.add("just-done"),ne.set(t,setTimeout(()=>{e.classList.remove("just-done"),ne.delete(t)},Math.max(0,n.doneUntil-Date.now())))):!l&&n.unread&&e.classList.add("just-done")}function lt(){for(let[e,t]of Ce){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=m.querySelector(n);s&&ot(s,e,t)}}function Gn(e,t){let n=jt(e,t),s=Ce.get(n);if(!s)return;let l=ne.get(n);l&&(clearTimeout(l),ne.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=m.querySelector(r);c&&ot(c,n,s)}function _t(){if(xe||at)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);xe=n,n.onmessage=s=>{try{let l=JSON.parse(String(s.data));l&&l.type==="session.activity"&&typeof l.session=="string"&&Zn(l.session,l.agentId||void 0,l.state==="working"?"working":"idle")}catch{}},n.onclose=()=>{xe===n&&(xe=null,at=setTimeout(()=>{at=null,_t()},5e3))},n.onerror=()=>{try{n.close()}catch{}}}catch{xe=null}}window.__openSession=ye,window.__refreshSidebar=W,W(),et(),lt(),_t(),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&lt()}),setInterval(()=>{document.visibilityState==="visible"&&W()},1e4);
@@ -1,8 +1,8 @@
1
- const Ht=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function st(a){return a.replace(/\x1b\[\?1049[hl]/g,"")}function U(a){return a.replace(Ht,"")}let N;function Vt(){return N||(document.querySelector("link[data-tmux-web-xterm-css]")?N=Promise.resolve():(N=new Promise(o=>{const r=document.createElement("link");r.rel="stylesheet",r.href="/assets/xterm.css",r.setAttribute("data-tmux-web-xterm-css",""),r.addEventListener("load",()=>o(),{once:!0}),r.addEventListener("error",()=>o(),{once:!0}),document.head.appendChild(r)}),N))}class at{terminal;fitAddon;container;constructor(o,r,n){this.container=o,this.terminal=r,this.fitAddon=n,this.terminal.loadAddon(this.fitAddon),this.terminal.open(o)}static async create(o,r,n){const[{Terminal:l},{FitAddon:f}]=await Promise.all([import("@xterm/xterm"),import("@xterm/addon-fit"),Vt()]),d=new l({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:r,convertEol:!1,smoothScrollDuration:120,theme:n});return new at(o,d,new f)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(o){return new Promise(r=>this.terminal.write(o,r))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(o,r=!1){this.terminal.scrollToLine(Math.max(0,o),r)}scrollLines(o){const r=this.terminal.buffer?.active;this.terminal.scrollLines(o)}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){const o=Wt(this.container);if(o.width<=0||o.height<=0)return!1;const n=this.terminal._core?._renderService?.dimensions?.css?.cell;if(!n?.width||!n?.height)return this.fitAddon.fit(),!0;const l=n.width,f=n.height,d=this.terminal.element?.querySelector(".xterm-viewport"),s=d?Math.max(0,d.offsetWidth-d.clientWidth):0,m=Math.max(2,Math.floor((o.width-s)/l)),g=Math.max(2,Math.floor(o.height/f));return(m!==this.terminal.cols||g!==this.terminal.rows)&&this.terminal.resize(m,g),!0}focus(){this.terminal.focus()}pasteText(o){this.terminal.paste(o)}input(o){this.terminal.input(o,!1)}onData(o){this.terminal.onData(o),this.terminal.onBinary(o)}onResize(o){this.terminal.onResize(o)}onScroll(o){this.terminal.onScroll(o)}attachCustomKeyEventHandler(o){this.terminal.attachCustomKeyEventHandler(o)}isFocused(){const o=document.activeElement;return o?o===this.container||o===this.terminal.textarea||this.container.contains(o)||!!o.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(o,r){const n=this.terminal.buffer.active,[l,f]=o<=r?[o,r]:[r,o],d=n.viewportY,s=[];for(let m=l;m<=f;m++){const g=n.getLine(d+m);s.push(g?g.translateToString(!0):"")}return s.join(`
1
+ const Ht=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function st(a){return a.replace(/\x1b\[\?1049[hl]/g,"")}function U(a){return a.replace(Ht,"")}let N;function Wt(){return N||(document.querySelector("link[data-tmux-web-xterm-css]")?N=Promise.resolve():(N=new Promise(o=>{const r=document.createElement("link");r.rel="stylesheet",r.href="/assets/xterm.css",r.setAttribute("data-tmux-web-xterm-css",""),r.addEventListener("load",()=>o(),{once:!0}),r.addEventListener("error",()=>o(),{once:!0}),document.head.appendChild(r)}),N))}class at{terminal;fitAddon;container;constructor(o,r,n){this.container=o,this.terminal=r,this.fitAddon=n,this.terminal.loadAddon(this.fitAddon),this.terminal.open(o)}static async create(o,r,n){const[{Terminal:l},{FitAddon:f}]=await Promise.all([import("@xterm/xterm"),import("@xterm/addon-fit"),Wt()]),d=new l({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:r,convertEol:!1,smoothScrollDuration:120,theme:n});return new at(o,d,new f)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(o){return new Promise(r=>this.terminal.write(o,r))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(o,r=!1){this.terminal.scrollToLine(Math.max(0,o),r)}scrollLines(o){const r=this.terminal.buffer?.active;this.terminal.scrollLines(o)}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){const o=Vt(this.container);if(o.width<=0||o.height<=0)return!1;const n=this.terminal._core?._renderService?.dimensions?.css?.cell;if(!n?.width||!n?.height)return this.fitAddon.fit(),!0;const l=n.width,f=n.height,d=this.terminal.element?.querySelector(".xterm-viewport"),s=d?Math.max(0,d.offsetWidth-d.clientWidth):0,m=Math.max(2,Math.floor((o.width-s)/l)),g=Math.max(2,Math.floor(o.height/f));return(m!==this.terminal.cols||g!==this.terminal.rows)&&this.terminal.resize(m,g),!0}focus(){this.terminal.focus()}pasteText(o){this.terminal.paste(o)}input(o){this.terminal.input(o,!1)}onData(o){this.terminal.onData(o),this.terminal.onBinary(o)}onResize(o){this.terminal.onResize(o)}onScroll(o){this.terminal.onScroll(o)}attachCustomKeyEventHandler(o){this.terminal.attachCustomKeyEventHandler(o)}isFocused(){const o=document.activeElement;return o?o===this.container||o===this.terminal.textarea||this.container.contains(o)||!!o.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(o,r){const n=this.terminal.buffer.active,[l,f]=o<=r?[o,r]:[r,o],d=n.viewportY,s=[];for(let m=l;m<=f;m++){const g=n.getLine(d+m);s.push(g?g.translateToString(!0):"")}return s.join(`
2
2
  `)}selectRows(o,r){const n=this.terminal.buffer.active,[l,f]=o<=r?[o,r]:[r,o];this.terminal.selectLines(n.viewportY+l,n.viewportY+f)}selectCells(o,r,n,l){const f=this.terminal.buffer.active,d=Math.min(r,l),s=Math.max(r,l);if(d===s){const m=Math.min(o,n),g=Math.max(o,n);this.terminal.select(m,f.viewportY+d,g-m+1)}else this.terminal.selectLines(f.viewportY+d,f.viewportY+s)}getCellsText(o,r,n,l){const f=this.terminal.buffer.active,d=Math.min(r,l),s=Math.max(r,l),m=r<l?o:r>l?n:Math.min(o,n),g=r<l?n:r>l?o:Math.max(o,n),tt=f.viewportY,L=[];for(let M=d;M<=s;M++){const j=f.getLine(tt+M);if(!j){L.push("");continue}const et=M===d?m:0,y=M===s?g:this.terminal.cols-1;let v="";for(let Y=et;Y<=y;Y++){const F=j.getCell(Y);F&&(v+=F.getChars())}L.push(v.replace(/\s+$/,""))}return L.join(`
3
- `)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}}function Wt(a){const o=a.getBoundingClientRect(),r=window.visualViewport;return r?{width:Math.min(o.width,r.width),height:Math.max(0,Math.min(o.height,r.height-Math.max(0,o.top)))}:o}function Jt(a,o,r){return a.innerHTML="",a.classList.add("terminal-pending"),(async()=>{const n=await at.create(a,r.scrollback,r.theme);let l,f=0,d,s=null,m=null,g=!1;const tt=/(?:^|\/)(?:vim|nvim|vi|less|more|htop|btop|top|hx|helix|lazygit)$/;let L=null;async function M(){try{const t=await fetch("/api/session-program?session="+encodeURIComponent(o));if(t.ok){const e=await t.json();m=typeof e.program=="string"&&e.program?e.program:null,g=m!==null&&tt.test(m)}}catch{}}function j(){L&&clearTimeout(L),L=setTimeout(()=>{M()},250)}function et(t){return m!==null&&/(?:^|\/)(?:vim|nvim|vi)$/.test(m)?t?"":"":t?"\x1B[A":"\x1B[B"}let y=0,v=0;const Y=.2,F=10,yt=.95,vt=.04;function H(){y&&(cancelAnimationFrame(y),y=0),v=0}function xt(t){if(H(),Math.abs(t)<Y)return;v=Math.max(-F,Math.min(F,t));const e=()=>{if(S){y=0;return}const i=a.querySelector(".xterm-rows > div"),c=i?i.getBoundingClientRect().height:16;let u=c>0?Math.round(v*16/c):v>0?1:-1;u===0&&(u=v>0?1:-1);const T=n.viewportY()-u,P=n.baseY(),A=Math.max(0,Math.min(T,P));if(n.scrollToLine(A,!0),v*=yt,A!==T){y=0;return}if(Math.abs(v)<vt){y=0;return}y=requestAnimationFrame(e)};y=requestAnimationFrame(e)}let nt=0,b="connecting",V=0,B=!1,W=[],I="",S=!1,K=1e3;const Tt=location.protocol==="https:"?"wss:":"ws:",bt=r.wsBase||"/ws",Et=Tt+"//"+location.host+bt+"/"+encodeURIComponent(o),Mt="/api/session/"+encodeURIComponent(o)+"/upload",St=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function Lt(){return W.join("")+I}async function Ct(t,e=0){const i=t?n.viewportY():0,c=U(Lt());if(n.reset(),!c){t||n.scrollToBottom();return}await n.write(c),t?n.scrollToLine(e+i):n.scrollToBottom()}function C(t){l?.readyState===WebSocket.OPEN&&l.send(JSON.stringify(t))}function Dt(t){let e;try{e=JSON.parse(t)}catch{b==="live"&&(I+=t,n.write(U(t)));return}if(e.type==="auth.required"){const i=localStorage.getItem("tmux-web-token");i?C({type:"auth.token",token:i}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(e.type==="attach_failed"&&typeof e.message=="string"){J=!0,b="dead",n.reset(),n.write(`\r
3
+ `)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}}function Vt(a){const o=a.getBoundingClientRect(),r=window.visualViewport;return r?{width:Math.min(o.width,r.width),height:Math.max(0,Math.min(o.height,r.height-Math.max(0,o.top)))}:o}function Jt(a,o,r){return a.innerHTML="",a.classList.add("terminal-pending"),(async()=>{const n=await at.create(a,r.scrollback,r.theme);let l,f=0,d,s=null,m=null,g=!1;const tt=/(?:^|\/)(?:vim|nvim|vi|less|more|htop|btop|top|hx|helix|lazygit)$/;let L=null;async function M(){try{const t=(r.wsBase||"/ws").replace(/^\/ws/,"")||"",e=await fetch(t+"/api/session-program?session="+encodeURIComponent(o));if(e.ok){const i=await e.json();m=typeof i.program=="string"&&i.program?i.program:null,g=m!==null&&tt.test(m)}}catch{}}function j(){L&&clearTimeout(L),L=setTimeout(()=>{M()},250)}function et(t){return m!==null&&/(?:^|\/)(?:vim|nvim|vi)$/.test(m)?t?"":"":t?"\x1B[A":"\x1B[B"}let y=0,v=0;const Y=.2,F=10,yt=.95,vt=.04;function H(){y&&(cancelAnimationFrame(y),y=0),v=0}function xt(t){if(H(),Math.abs(t)<Y)return;v=Math.max(-F,Math.min(F,t));const e=()=>{if(S){y=0;return}const i=a.querySelector(".xterm-rows > div"),c=i?i.getBoundingClientRect().height:16;let u=c>0?Math.round(v*16/c):v>0?1:-1;u===0&&(u=v>0?1:-1);const T=n.viewportY()-u,P=n.baseY(),A=Math.max(0,Math.min(T,P));if(n.scrollToLine(A,!0),v*=yt,A!==T){y=0;return}if(Math.abs(v)<vt){y=0;return}y=requestAnimationFrame(e)};y=requestAnimationFrame(e)}let nt=0,b="connecting",W=0,B=!1,V=[],I="",S=!1,K=1e3;const Tt=location.protocol==="https:"?"wss:":"ws:",bt=r.wsBase||"/ws",Et=Tt+"//"+location.host+bt+"/"+encodeURIComponent(o),Mt="/api/session/"+encodeURIComponent(o)+"/upload",St=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function Lt(){return V.join("")+I}async function Ct(t,e=0){const i=t?n.viewportY():0,c=U(Lt());if(n.reset(),!c){t||n.scrollToBottom();return}await n.write(c),t?n.scrollToLine(e+i):n.scrollToBottom()}function C(t){l?.readyState===WebSocket.OPEN&&l.send(JSON.stringify(t))}function Dt(t){let e;try{e=JSON.parse(t)}catch{b==="live"&&(I+=t,n.write(U(t)));return}if(e.type==="auth.required"){const i=localStorage.getItem("tmux-web-token");i?C({type:"auth.token",token:i}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(e.type==="attach_failed"&&typeof e.message=="string"){J=!0,b="dead",n.reset(),n.write(`\r
4
4
  \x1B[31m`+U(e.message)+`\x1B[0m\r
5
- `).then(()=>{$();try{l?.close()}catch{}});return}if(e.type==="auth.ok"){e.token&&localStorage.setItem("tmux-web-token",e.token),K=1e3,D(),C({type:"resize",cols:n.cols,rows:n.rows}),w(),M();return}if(e.type==="auth.failed"){if(e.permanentLock||e.retryAfterMs&&e.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(e.message);return}return}if(e.type==="snapshot"&&typeof e.data=="string"){const i=st(U(e.data));W=[i],I="",V=typeof e.lines=="number"?e.lines:r.terminal.initialLines,b="live",n.reset(),D(),C({type:"resize",cols:n.cols,rows:n.rows}),n.write(i).then(()=>n.scrollToBottom());return}if(e.type==="window_changed"&&typeof e.activeIndex=="number"){const i=new URL(location.href);i.searchParams.get("window")!==String(e.activeIndex)&&(i.searchParams.set("window",String(e.activeIndex)),history.replaceState(history.state,"",i)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:e.windows}));return}if(e.type==="history"&&typeof e.data=="string"){e.lines>0&&e.data?(W.unshift(st(e.data)),V+=e.lines,Ct(!0,e.lines).finally(()=>{B=!1})):B=!1;return}if(e.type==="data"&&typeof e.data=="string"){/\x1b\[\?1049[hl]/.test(e.data)&&j();const i=st(U(e.data));if(b==="connecting"){b="live",I=i,n.write(i);return}b==="live"&&(I+=i,n.write(i))}}let J=!1;function lt(){if(J)return;let t=Et;const e=localStorage.getItem("tmux-web-token");e&&(t+=(t.includes("?")?"&":"?")+"token="+encodeURIComponent(e)),t+=(t.includes("?")?"&":"?")+"cols="+n.cols+"&rows="+n.rows,l=new WebSocket(t),l.onopen=()=>{b="connecting",V=0,B=!1,W=[],I="",n.reset(),K=1e3},l.onmessage=i=>{typeof i.data=="string"&&Dt(i.data)},l.onclose=()=>{S||(b="connecting",!J&&setTimeout(()=>{K=Math.min(K*2,1e4),!S&&!J&&lt()},K))},l.onerror=()=>l?.close()}function R(t){C({type:"input",data:t})}function D(){return n.fit()}function $(){a.classList.remove("terminal-pending")}function w(){f&&cancelAnimationFrame(f),d&&clearTimeout(d),D(),f=requestAnimationFrame(()=>{f=0,D()&&$()}),d=setTimeout(()=>{D()&&$()},120)}function Pt(){w(),setTimeout(w,50),setTimeout(w,150),setTimeout(w,300)}function ct(t){return typeof t=="string"&&t.startsWith("image/")}function ut(t){return t?.files?.length?t.files[0]??null:null}function At(t){if(!t?.items)return null;for(let e=0;e<t.items.length;e++){const i=t.items[e];if(i?.kind==="file"&&ct(i.type))return i.getAsFile()}return null}async function It(t){const e=new FormData,i=t instanceof File&&t.name?t.name:"upload";e.append("file",t,i);const c=localStorage.getItem("tmux-web-token"),u={};c&&(u.Authorization="Bearer "+c);const x=await fetch(Mt,{method:"POST",body:e,headers:u});if(!x.ok){let P="upload failed";try{const A=await x.json();A.error&&(P=A.error)}catch{}throw new Error(P)}const T=await x.json();if(!T.path)throw new Error("no path in response");return T.path}async function ot(t){try{const e=await It(t);R(e)}catch{}}n.onData(t=>R(t)),n.onResize(({cols:t,rows:e})=>C({type:"resize",cols:t,rows:e})),n.onScroll(()=>{b!=="live"||B||!n.isNearScrollbackTop()||(B=!0,C({type:"load_history",before:V}))});let z=!1,O=!1,h=null,p=null;const X=document.createElement("div");X.className="terminal-copy-banner",X.innerHTML='<strong>Copy mode</strong><span class="hint">drag to copy \xB7 Esc exits</span>',X.hidden=!0,a.appendChild(X);const E=document.createElement("div");E.className="terminal-copy-banner terminal-copy-toast",E.textContent="Copied",E.hidden=!0,a.appendChild(E);function ft(t,e){const i=a.querySelector(".xterm-screen, canvas"),u=(i&&i.getBoundingClientRect().width>0?i:a).getBoundingClientRect(),x=u.height>0&&n.rows>0?u.height/n.rows:18,T=u.width>0&&n.cols>0?u.width/n.cols:9;return{row:Math.max(0,Math.min(n.rows-1,Math.floor((e-u.top)/x))),col:Math.max(0,Math.min(n.cols-1,Math.floor((t-u.left)/T)))}}async function G(t){if(!t)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(t);return}}catch{}const e=document.createElement("textarea");e.value=t,e.style.position="fixed",e.style.opacity="0",e.style.pointerEvents="none",document.body.appendChild(e),e.focus(),e.select();try{document.execCommand("copy")}catch{}e.remove()}let _;function Q(){E.hidden=!1,_&&clearTimeout(_),_=setTimeout(()=>{E.hidden=!0},1e3)}function k(t){z=t,X.hidden=!t,a.classList.toggle("terminal-copy-mode-active",t),t&&n.focus()}function dt(){k(!z)}function kt(t){S||t.button!==0||O||(z||t.shiftKey)&&(t.preventDefault(),t.stopPropagation(),O=!0,h=ft(t.clientX,t.clientY),p=h,n.selectCells(h.col,h.row,p.col,p.row),document.addEventListener("mousemove",it,!0),document.addEventListener("mouseup",rt,!0))}function it(t){S||!O||!h||(t.preventDefault(),t.stopPropagation(),p=ft(t.clientX,t.clientY),n.selectCells(h.col,h.row,p.col,p.row))}function rt(t){if(S||!O||!h||!p)return;t.preventDefault(),t.stopPropagation(),document.removeEventListener("mousemove",it,!0),document.removeEventListener("mouseup",rt,!0),O=!1;const e=n.getCellsText(h.col,h.row,p.col,p.row);h=null,p=null,n.clearSelection(),k(!1),e&&(E.textContent="\u5DF2\u590D\u5236",G(e).then(Q)),n.focus()}a.addEventListener("mousedown",kt,!0),document.addEventListener("keydown",Yt,!0);function Yt(t){if(!(S||!n.isFocused()||t.defaultPrevented||t.isComposing)){if(z){if(t.key==="Escape"){t.preventDefault(),t.stopPropagation(),h=null,p=null,n.clearSelection(),k(!1);return}if(t.key==="Enter"||(t.ctrlKey||t.metaKey)&&t.code==="KeyC"){t.preventDefault(),t.stopPropagation(),G(n.getScreenText()).then(Q),k(!1);return}}if(t.altKey&&t.code==="KeyC"&&!t.ctrlKey&&!t.metaKey){if(t.preventDefault(),t.stopPropagation(),h&&p){const e=n.getCellsText(h.col,h.row,p.col,p.row);h=null,p=null,n.clearSelection(),k(!1),e&&(E.textContent="Copied",G(e).then(Q))}else{const e=n.getSelection();e?(n.clearSelection(),E.textContent="Copied",G(e).then(Q)):dt()}return}if((t.ctrlKey||t.metaKey)&&t.code==="KeyV"){t.preventDefault(),t.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){const e=await navigator.clipboard.read();for(const i of e)for(const c of i.types)if(ct(c)){const u=await i.getType(c);await ot(u);return}}}catch{}try{const e=await navigator.clipboard?.readText();e&&n.pasteText(mt(e))}catch{}})();return}}}let Z=0;function mt(t){return t.split(`\r
5
+ `).then(()=>{$();try{l?.close()}catch{}});return}if(e.type==="auth.ok"){e.token&&localStorage.setItem("tmux-web-token",e.token),K=1e3,D(),C({type:"resize",cols:n.cols,rows:n.rows}),w(),M();return}if(e.type==="auth.failed"){if(e.permanentLock||e.retryAfterMs&&e.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(e.message);return}return}if(e.type==="snapshot"&&typeof e.data=="string"){const i=st(U(e.data));V=[i],I="",W=typeof e.lines=="number"?e.lines:r.terminal.initialLines,b="live",n.reset(),D(),C({type:"resize",cols:n.cols,rows:n.rows}),n.write(i).then(()=>n.scrollToBottom());return}if(e.type==="window_changed"&&typeof e.activeIndex=="number"){const i=new URL(location.href);i.searchParams.get("window")!==String(e.activeIndex)&&(i.searchParams.set("window",String(e.activeIndex)),history.replaceState(history.state,"",i)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:e.windows}));return}if(e.type==="history"&&typeof e.data=="string"){e.lines>0&&e.data?(V.unshift(st(e.data)),W+=e.lines,Ct(!0,e.lines).finally(()=>{B=!1})):B=!1;return}if(e.type==="data"&&typeof e.data=="string"){/\x1b\[\?1049[hl]/.test(e.data)&&j();const i=st(U(e.data));if(b==="connecting"){b="live",I=i,n.write(i);return}b==="live"&&(I+=i,n.write(i))}}let J=!1;function lt(){if(J)return;let t=Et;const e=localStorage.getItem("tmux-web-token");e&&(t+=(t.includes("?")?"&":"?")+"token="+encodeURIComponent(e)),t+=(t.includes("?")?"&":"?")+"cols="+n.cols+"&rows="+n.rows,l=new WebSocket(t),l.onopen=()=>{b="connecting",W=0,B=!1,V=[],I="",n.reset(),K=1e3},l.onmessage=i=>{typeof i.data=="string"&&Dt(i.data)},l.onclose=()=>{S||(b="connecting",!J&&setTimeout(()=>{K=Math.min(K*2,1e4),!S&&!J&&lt()},K))},l.onerror=()=>l?.close()}function z(t){C({type:"input",data:t})}function D(){return n.fit()}function $(){a.classList.remove("terminal-pending")}function w(){f&&cancelAnimationFrame(f),d&&clearTimeout(d),D(),f=requestAnimationFrame(()=>{f=0,D()&&$()}),d=setTimeout(()=>{D()&&$()},120)}function Pt(){w(),setTimeout(w,50),setTimeout(w,150),setTimeout(w,300)}function ct(t){return typeof t=="string"&&t.startsWith("image/")}function ut(t){return t?.files?.length?t.files[0]??null:null}function At(t){if(!t?.items)return null;for(let e=0;e<t.items.length;e++){const i=t.items[e];if(i?.kind==="file"&&ct(i.type))return i.getAsFile()}return null}async function It(t){const e=new FormData,i=t instanceof File&&t.name?t.name:"upload";e.append("file",t,i);const c=localStorage.getItem("tmux-web-token"),u={};c&&(u.Authorization="Bearer "+c);const x=await fetch(Mt,{method:"POST",body:e,headers:u});if(!x.ok){let P="upload failed";try{const A=await x.json();A.error&&(P=A.error)}catch{}throw new Error(P)}const T=await x.json();if(!T.path)throw new Error("no path in response");return T.path}async function ot(t){try{const e=await It(t);z(e)}catch{}}n.onData(t=>z(t)),n.onResize(({cols:t,rows:e})=>C({type:"resize",cols:t,rows:e})),n.onScroll(()=>{b!=="live"||B||!n.isNearScrollbackTop()||(B=!0,C({type:"load_history",before:W}))});let R=!1,X=!1,h=null,p=null;const O=document.createElement("div");O.className="terminal-copy-banner",O.innerHTML='<strong>Copy mode</strong><span class="hint">drag to copy \xB7 Esc exits</span>',O.hidden=!0,a.appendChild(O);const E=document.createElement("div");E.className="terminal-copy-banner terminal-copy-toast",E.textContent="Copied",E.hidden=!0,a.appendChild(E);function ft(t,e){const i=a.querySelector(".xterm-screen, canvas"),u=(i&&i.getBoundingClientRect().width>0?i:a).getBoundingClientRect(),x=u.height>0&&n.rows>0?u.height/n.rows:18,T=u.width>0&&n.cols>0?u.width/n.cols:9;return{row:Math.max(0,Math.min(n.rows-1,Math.floor((e-u.top)/x))),col:Math.max(0,Math.min(n.cols-1,Math.floor((t-u.left)/T)))}}async function G(t){if(!t)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(t);return}}catch{}const e=document.createElement("textarea");e.value=t,e.style.position="fixed",e.style.opacity="0",e.style.pointerEvents="none",document.body.appendChild(e),e.focus(),e.select();try{document.execCommand("copy")}catch{}e.remove()}let _;function Q(){E.hidden=!1,_&&clearTimeout(_),_=setTimeout(()=>{E.hidden=!0},1e3)}function k(t){R=t,O.hidden=!t,a.classList.toggle("terminal-copy-mode-active",t),t&&n.focus()}function dt(){k(!R)}function kt(t){S||t.button!==0||X||(R||t.shiftKey)&&(t.preventDefault(),t.stopPropagation(),X=!0,h=ft(t.clientX,t.clientY),p=h,n.selectCells(h.col,h.row,p.col,p.row),document.addEventListener("mousemove",it,!0),document.addEventListener("mouseup",rt,!0))}function it(t){S||!X||!h||(t.preventDefault(),t.stopPropagation(),p=ft(t.clientX,t.clientY),n.selectCells(h.col,h.row,p.col,p.row))}function rt(t){if(S||!X||!h||!p)return;t.preventDefault(),t.stopPropagation(),document.removeEventListener("mousemove",it,!0),document.removeEventListener("mouseup",rt,!0),X=!1;const e=n.getCellsText(h.col,h.row,p.col,p.row);h=null,p=null,n.clearSelection(),k(!1),e&&(E.textContent="\u5DF2\u590D\u5236",G(e).then(Q)),n.focus()}a.addEventListener("mousedown",kt,!0),document.addEventListener("keydown",Yt,!0);function Yt(t){if(!(S||!n.isFocused()||t.defaultPrevented||t.isComposing)){if(R){if(t.key==="Escape"){t.preventDefault(),t.stopPropagation(),h=null,p=null,n.clearSelection(),k(!1);return}if(t.key==="Enter"||(t.ctrlKey||t.metaKey)&&t.code==="KeyC"){t.preventDefault(),t.stopPropagation(),G(n.getScreenText()).then(Q),k(!1);return}}if(t.altKey&&t.code==="KeyC"&&!t.ctrlKey&&!t.metaKey){if(t.preventDefault(),t.stopPropagation(),h&&p){const e=n.getCellsText(h.col,h.row,p.col,p.row);h=null,p=null,n.clearSelection(),k(!1),e&&(E.textContent="Copied",G(e).then(Q))}else{const e=n.getSelection();e?(n.clearSelection(),E.textContent="Copied",G(e).then(Q)):dt()}return}if((t.ctrlKey||t.metaKey)&&t.code==="KeyV"){t.preventDefault(),t.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){const e=await navigator.clipboard.read();for(const i of e)for(const c of i.types)if(ct(c)){const u=await i.getType(c);await ot(u);return}}}catch{}try{const e=await navigator.clipboard?.readText();e&&n.pasteText(mt(e))}catch{}})();return}}}let Z=0;function mt(t){return t.split(`\r
6
6
  `).join(`
7
7
  `).split(`
8
- `).join("\r")}async function Ft(t){const e=At(t.clipboardData);if(e){t.preventDefault(),t.stopPropagation();const u=Date.now();if(u-Z<50)return;Z=u,await ot(e);return}const i=t.clipboardData?.getData("text/plain");if(!i)return;t.preventDefault(),t.stopPropagation();const c=Date.now();c-Z<50||(Z=c,n.pasteText(mt(i)))}let q=0;function Bt(t){t.preventDefault(),q++,ut(t.dataTransfer)&&a.classList.add("terminal-drag-over")}function Kt(t){t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy")}function Rt(t){t.preventDefault(),q--,q<=0&&(q=0,a.classList.remove("terminal-drag-over"))}async function zt(t){t.preventDefault(),q=0,a.classList.remove("terminal-drag-over");const e=ut(t.dataTransfer);e&&await ot(e)}function ht(t){!St||t.key!=="Escape"||z||t.defaultPrevented||t.repeat||t.metaKey||t.ctrlKey||t.altKey||n.isFocused()&&(t.preventDefault(),t.stopPropagation(),R("\x1B"))}a.addEventListener("paste",Ft),a.addEventListener("dragenter",Bt),a.addEventListener("dragover",Kt),a.addEventListener("dragleave",Rt),a.addEventListener("drop",zt),document.addEventListener("keydown",ht,!0);function Ot(t){if(t.touches.length!==1){s=null;return}const e=t.touches[0];e&&(H(),s={startX:e.clientX,startY:e.clientY,lastX:e.clientX,lastY:e.clientY,lastT:performance.now(),velocity:0,scrolling:!1,tuiAtStart:g,tuiAccum:0},t.stopPropagation())}function Xt(t){if(!s||t.touches.length!==1)return;const e=t.touches[0];if(!e)return;const i=e.clientY-s.startY,c=e.clientX-s.startX;if(!s.scrolling){if(Math.abs(i)<8||Math.abs(i)<Math.abs(c))return;s.scrolling=!0,nt=Date.now()+500}t.preventDefault(),t.stopPropagation();const u=performance.now(),x=e.clientY-s.lastY;if(g){s.tuiAccum+=x;const P=a.querySelector(".xterm-rows > div"),A=P?P.getBoundingClientRect().height:16,wt=Math.max(16,A);for(;Math.abs(s.tuiAccum)>=wt;)R(et(s.tuiAccum>0)),s.tuiAccum-=Math.sign(s.tuiAccum)*wt;s.lastX=e.clientX,s.lastY=e.clientY,s.lastT=u;return}const T=u-s.lastT;T>0&&(s.velocity=x/T),Nt(-x),s.lastX=e.clientX,s.lastY=e.clientY,s.lastT=u}function _t(t){if(!s)return;const e=s.scrolling,i=s.tuiAtStart,c=s.velocity;if(s=null,t.stopPropagation(),!e){n.focus();return}nt=Date.now()+500,t.preventDefault(),!i&&c&&xt(c)}function qt(t){s=null,H(),t.stopPropagation()}function Ut(t){t.pointerType==="touch"&&Date.now()<nt&&(t.preventDefault(),t.stopPropagation())}function Nt(t){const e=a.querySelector(".xterm-rows > div"),i=e?e.getBoundingClientRect().height:16;let c=i>0?Math.round(t/i):t>0?1:-1;c===0&&(c=t>0?1:-1),n.scrollLines(c)}a.addEventListener("touchstart",Ot,{passive:!0,capture:!0}),a.addEventListener("touchmove",Xt,{passive:!1,capture:!0}),a.addEventListener("touchend",_t,{passive:!1,capture:!0}),a.addEventListener("touchcancel",qt,{passive:!0,capture:!0}),a.addEventListener("pointerup",Ut,!0);function pt(){w()}window.addEventListener("resize",pt),window.visualViewport?.addEventListener("resize",w),window.visualViewport?.addEventListener("scroll",w);const gt=new ResizeObserver(()=>w());gt.observe(a),document.fonts?.ready.then(()=>{w(),setTimeout(w,50),setTimeout(w,200)}),a.addEventListener("focusin",Pt,!0);async function jt(){if(document.fonts?.ready)try{await Promise.race([document.fonts.ready,new Promise(t=>setTimeout(t,1e3))])}catch{}}return requestAnimationFrame(()=>{D()&&$(),(async()=>(await jt(),D()&&C({type:"resize",cols:n.cols,rows:n.rows}),lt(),w()))()}),{destroy(){if(S=!0,H(),k(!1),_&&clearTimeout(_),document.removeEventListener("mousemove",it,!0),document.removeEventListener("mouseup",rt,!0),l){try{l.close(1e3,"session switch")}catch{}l=void 0}a.innerHTML="",a.classList.remove("terminal-pending"),window.removeEventListener("resize",pt),gt.disconnect(),document.removeEventListener("keydown",ht,!0)},focus(){n.focus()},sendInput(t){R(t)},toggleCopyMode(){dt()}}})()}export{Jt as initTerminal,st as stripAltScreenSequences};
8
+ `).join("\r")}async function Ft(t){const e=At(t.clipboardData);if(e){t.preventDefault(),t.stopPropagation();const u=Date.now();if(u-Z<50)return;Z=u,await ot(e);return}const i=t.clipboardData?.getData("text/plain");if(!i)return;t.preventDefault(),t.stopPropagation();const c=Date.now();c-Z<50||(Z=c,n.pasteText(mt(i)))}let q=0;function Bt(t){t.preventDefault(),q++,ut(t.dataTransfer)&&a.classList.add("terminal-drag-over")}function Kt(t){t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy")}function zt(t){t.preventDefault(),q--,q<=0&&(q=0,a.classList.remove("terminal-drag-over"))}async function Rt(t){t.preventDefault(),q=0,a.classList.remove("terminal-drag-over");const e=ut(t.dataTransfer);e&&await ot(e)}function ht(t){!St||t.key!=="Escape"||R||t.defaultPrevented||t.repeat||t.metaKey||t.ctrlKey||t.altKey||n.isFocused()&&(t.preventDefault(),t.stopPropagation(),z("\x1B"))}a.addEventListener("paste",Ft),a.addEventListener("dragenter",Bt),a.addEventListener("dragover",Kt),a.addEventListener("dragleave",zt),a.addEventListener("drop",Rt),document.addEventListener("keydown",ht,!0);function Xt(t){if(t.touches.length!==1){s=null;return}const e=t.touches[0];if(!e)return;H();const i=e.clientX-a.getBoundingClientRect().left<a.clientWidth*.4?"tui":"history";s={startX:e.clientX,startY:e.clientY,lastX:e.clientX,lastY:e.clientY,lastT:performance.now(),velocity:0,scrolling:!1,zone:i,tuiAtStart:g,tuiAccum:0},t.stopPropagation()}function Ot(t){if(!s||t.touches.length!==1)return;const e=t.touches[0];if(!e)return;const i=e.clientY-s.startY,c=e.clientX-s.startX;if(!s.scrolling){if(Math.abs(i)<8||Math.abs(i)<Math.abs(c))return;s.scrolling=!0,nt=Date.now()+500}t.preventDefault(),t.stopPropagation();const u=performance.now(),x=e.clientY-s.lastY;if(s.zone==="tui"){if(!g){s.lastX=e.clientX,s.lastY=e.clientY,s.lastT=u;return}s.tuiAccum+=x;const P=a.querySelector(".xterm-rows > div"),A=P?P.getBoundingClientRect().height:16,wt=Math.max(16,A);for(;Math.abs(s.tuiAccum)>=wt;)z(et(s.tuiAccum>0)),s.tuiAccum-=Math.sign(s.tuiAccum)*wt;s.lastX=e.clientX,s.lastY=e.clientY,s.lastT=u;return}const T=u-s.lastT;T>0&&(s.velocity=x/T),Nt(-x),s.lastX=e.clientX,s.lastY=e.clientY,s.lastT=u}function _t(t){if(!s)return;const e=s.scrolling,i=s.tuiAtStart,c=s.velocity;if(s=null,t.stopPropagation(),!e){n.focus();return}nt=Date.now()+500,t.preventDefault(),!i&&c&&xt(c)}function qt(t){s=null,H(),t.stopPropagation()}function Ut(t){t.pointerType==="touch"&&Date.now()<nt&&(t.preventDefault(),t.stopPropagation())}function Nt(t){const e=a.querySelector(".xterm-rows > div"),i=e?e.getBoundingClientRect().height:16;let c=i>0?Math.round(t/i):t>0?1:-1;c===0&&(c=t>0?1:-1),n.scrollLines(c)}a.addEventListener("touchstart",Xt,{passive:!0,capture:!0}),a.addEventListener("touchmove",Ot,{passive:!1,capture:!0}),a.addEventListener("touchend",_t,{passive:!1,capture:!0}),a.addEventListener("touchcancel",qt,{passive:!0,capture:!0}),a.addEventListener("pointerup",Ut,!0);function pt(){w()}window.addEventListener("resize",pt),window.visualViewport?.addEventListener("resize",w),window.visualViewport?.addEventListener("scroll",w);const gt=new ResizeObserver(()=>w());gt.observe(a),document.fonts?.ready.then(()=>{w(),setTimeout(w,50),setTimeout(w,200)}),a.addEventListener("focusin",Pt,!0);async function jt(){if(document.fonts?.ready)try{await Promise.race([document.fonts.ready,new Promise(t=>setTimeout(t,1e3))])}catch{}}return requestAnimationFrame(()=>{D()&&$(),(async()=>(await jt(),D()&&C({type:"resize",cols:n.cols,rows:n.rows}),lt(),w()))()}),{destroy(){if(S=!0,H(),k(!1),_&&clearTimeout(_),document.removeEventListener("mousemove",it,!0),document.removeEventListener("mouseup",rt,!0),l){try{l.close(1e3,"session switch")}catch{}l=void 0}a.innerHTML="",a.classList.remove("terminal-pending"),window.removeEventListener("resize",pt),gt.disconnect(),document.removeEventListener("keydown",ht,!0)},focus(){n.focus()},sendInput(t){z(t)},toggleCopyMode(){dt()}}})()}export{Jt as initTerminal,st as stripAltScreenSequences};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmux-weblink",
3
- "version": "2.2.16",
3
+ "version": "2.2.18",
4
4
  "description": "Access your tmux sessions from the browser. A continuation of tmux-web and persalink.",
5
5
  "type": "module",
6
6
  "bin": {