tmux-weblink 2.0.9 → 2.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,40 +1,40 @@
1
- var Ft="https://esm.sh/ghostty-web@0.4.0",Vt=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function ie(n){return n.replace(Vt,"")}var ge;function _t(){return ge||(document.querySelector("link[data-tmux-web-xterm-css]")?ge=Promise.resolve():(ge=new Promise(n=>{let e=document.createElement("link");e.rel="stylesheet",e.href="/assets/xterm.css",e.setAttribute("data-tmux-web-xterm-css",""),e.addEventListener("load",()=>n(),{once:!0}),e.addEventListener("error",()=>n(),{once:!0}),document.head.appendChild(e)}),ge))}var Je=class wt{terminal;fitAddon;container;constructor(e,t,i){this.container=e,this.terminal=t,this.fitAddon=i,this.terminal.loadAddon(this.fitAddon),this.terminal.open(e)}static async create(e,t,i){let[{Terminal:a},{FitAddon:l}]=await Promise.all([import("./xterm-BXEES47M.js"),import("./addon-fit-D5N335P2.js"),_t()]),c=new a({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:t,convertEol:!1,theme:i});return new wt(e,c,new l)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(e){return new Promise(t=>this.terminal.write(e,t))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(e){this.terminal.scrollToLine(Math.max(0,e))}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){let e=Ze(this.container);return e.width<=0||e.height<=0?!1:(this.fitAddon.fit(),!0)}focus(){this.terminal.focus()}pasteText(e){this.terminal.paste(e)}input(e){this.terminal.input(e,!1)}onData(e){this.terminal.onData(e),this.terminal.onBinary(e)}onResize(e){this.terminal.onResize(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){let e=document.activeElement;return e?e===this.container||e===this.terminal.textarea||this.container.contains(e)||!!e.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(e,t){let i=this.terminal.buffer.active,[a,l]=e<=t?[e,t]:[t,e],c=i.viewportY,r=[];for(let d=a;d<=l;d++){let p=i.getLine(c+d);r.push(p?p.translateToString(!0):"")}return r.join(`
2
- `)}selectRows(e,t){let i=this.terminal.buffer.active,[a,l]=e<=t?[e,t]:[t,e];this.terminal.selectLines(i.viewportY+a,i.viewportY+l)}selectCells(e,t,i,a){let l=this.terminal.buffer.active,c=Math.min(t,a),r=Math.max(t,a);if(c===r){let d=Math.min(e,i),p=Math.max(e,i);this.terminal.select(d,l.viewportY+c,p-d+1)}else this.terminal.selectLines(l.viewportY+c,l.viewportY+r)}getCellsText(e,t,i,a){let l=this.terminal.buffer.active,c=Math.min(t,a),r=Math.max(t,a),d=t<a?e:t>a?i:Math.min(e,i),p=t<a?i:t>a?e:Math.max(e,i),b=l.viewportY,M=[];for(let w=c;w<=r;w++){let L=l.getLine(b+w);if(!L){M.push("");continue}let H=w===c?d:0,A=w===r?p:this.terminal.cols-1,z="";for(let Y=H;Y<=A;Y++){let N=L.getCell(Y);N&&(z+=N.getChars())}M.push(z.replace(/\s+$/,""))}return M.join(`
1
+ var Ft="https://esm.sh/ghostty-web@0.4.0",Vt=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function ie(n){return n.replace(Vt,"")}var ye;function _t(){return ye||(document.querySelector("link[data-tmux-web-xterm-css]")?ye=Promise.resolve():(ye=new Promise(n=>{let e=document.createElement("link");e.rel="stylesheet",e.href="/assets/xterm.css",e.setAttribute("data-tmux-web-xterm-css",""),e.addEventListener("load",()=>n(),{once:!0}),e.addEventListener("error",()=>n(),{once:!0}),document.head.appendChild(e)}),ye))}var Je=class wt{terminal;fitAddon;container;constructor(e,t,i){this.container=e,this.terminal=t,this.fitAddon=i,this.terminal.loadAddon(this.fitAddon),this.terminal.open(e)}static async create(e,t,i){let[{Terminal:a},{FitAddon:l}]=await Promise.all([import("./xterm-BXEES47M.js"),import("./addon-fit-D5N335P2.js"),_t()]),c=new a({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:t,convertEol:!1,theme:i});return new wt(e,c,new l)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(e){return new Promise(t=>this.terminal.write(e,t))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(e){this.terminal.scrollToLine(Math.max(0,e))}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){let e=Ze(this.container);return e.width<=0||e.height<=0?!1:(this.fitAddon.fit(),!0)}focus(){this.terminal.focus()}pasteText(e){this.terminal.paste(e)}input(e){this.terminal.input(e,!1)}onData(e){this.terminal.onData(e),this.terminal.onBinary(e)}onResize(e){this.terminal.onResize(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){let e=document.activeElement;return e?e===this.container||e===this.terminal.textarea||this.container.contains(e)||!!e.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(e,t){let i=this.terminal.buffer.active,[a,l]=e<=t?[e,t]:[t,e],c=i.viewportY,r=[];for(let d=a;d<=l;d++){let p=i.getLine(c+d);r.push(p?p.translateToString(!0):"")}return r.join(`
2
+ `)}selectRows(e,t){let i=this.terminal.buffer.active,[a,l]=e<=t?[e,t]:[t,e];this.terminal.selectLines(i.viewportY+a,i.viewportY+l)}selectCells(e,t,i,a){let l=this.terminal.buffer.active,c=Math.min(t,a),r=Math.max(t,a);if(c===r){let d=Math.min(e,i),p=Math.max(e,i);this.terminal.select(d,l.viewportY+c,p-d+1)}else this.terminal.selectLines(l.viewportY+c,l.viewportY+r)}getCellsText(e,t,i,a){let l=this.terminal.buffer.active,c=Math.min(t,a),r=Math.max(t,a),d=t<a?e:t>a?i:Math.min(e,i),p=t<a?i:t>a?e:Math.max(e,i),L=l.viewportY,S=[];for(let w=c;w<=r;w++){let E=l.getLine(L+w);if(!E){S.push("");continue}let H=w===c?d:0,A=w===r?p:this.terminal.cols-1,z="";for(let Y=H;Y<=A;Y++){let N=E.getCell(Y);N&&(z+=N.getChars())}S.push(z.replace(/\s+$/,""))}return S.join(`
3
3
  `)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}},Ut=class bt{terminal;container;colsValue=80;rowsValue=24;charW=0;charH=0;resizeCallbacks=[];constructor(e,t){this.container=e,this.terminal=t,this.terminal.open(e)}static async create(e,t,i){let a=await import(Ft);await a.init();let l=new a.Terminal({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:t,convertEol:!1,theme:i});return new bt(e,l)}get cols(){return this.colsValue}get rows(){return this.rowsValue}write(e){return new Promise(t=>this.terminal.write(e,t))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom?.()}scrollToLine(e){this.terminal.scrollToLine?.(Math.max(0,e))}isNearScrollbackTop(){let e=this.terminal.buffer?.active;return e?e.viewportY>=e.baseY:!1}viewportY(){return this.terminal.buffer?.active?.viewportY??0}baseY(){return this.terminal.buffer?.active?.baseY??0}fit(){let e=Ze(this.container);if(e.width<=0||e.height<=0)return!1;this.updateCellMetrics(!this.charW||!this.charH);let t=Math.floor(e.width/this.charW),i=Math.floor(e.height/this.charH);if(t<10||i<5)return!1;if(t!==this.colsValue||i!==this.rowsValue){this.colsValue=t,this.rowsValue=i,this.terminal.resize(t,i);for(let a of this.resizeCallbacks)a({cols:t,rows:i})}return!0}focus(){(this.terminal.textarea||this.container.querySelector("textarea")||this.container)?.focus?.()}pasteText(e){let t=this.terminal.getMode?.(2004)??!1;this.input(t?"\x1B[200~"+e+"\x1B[201~":e)}input(e){this.terminal.input?.(e,!1)}onData(e){this.terminal.onData(t=>e(t))}onResize(e){this.resizeCallbacks.push(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){let e=document.activeElement;return!!e&&(e===this.container||e===this.terminal.textarea||this.container.contains(e))}getScreenText(){return this.getRowsText(0,this.rowsValue-1)}getRowsText(e,t){try{let i=this.terminal.buffer?.active;if(!i||typeof i.getLine!="function")return"";let[a,l]=e<=t?[e,t]:[t,e],c=typeof i.viewportY=="number"?i.viewportY:0,r=[];for(let d=a;d<=l;d++){let p=i.getLine(c+d);r.push(typeof p?.translateToString=="function"?p.translateToString(!0):"")}return r.join(`
4
- `)}catch{return""}}selectRows(e,t){try{if(typeof this.terminal?.selectLines!="function")return;let i=this.terminal.buffer?.active,a=typeof i?.viewportY=="number"?i.viewportY:0,[l,c]=e<=t?[e,t]:[t,e];this.terminal.selectLines(a+l,a+c)}catch{}}selectCells(e,t,i,a){try{let l=this.terminal.buffer?.active,c=typeof l?.viewportY=="number"?l.viewportY:0,r=Math.min(t,a),d=Math.max(t,a);if(r===d){if(typeof this.terminal?.select!="function"){this.selectRows(r,d);return}let p=Math.min(e,i),b=Math.max(e,i);this.terminal.select(p,c+r,b-p+1)}else this.selectRows(r,d)}catch{this.selectRows(t,a)}}getCellsText(e,t,i,a){try{let l=this.terminal.buffer?.active;if(!l||typeof l.getLine!="function")return this.getRowsText(t,a);let c=typeof l.viewportY=="number"?l.viewportY:0,r=Math.min(t,a),d=Math.max(t,a),p=t<a?e:t>a?i:Math.min(e,i),b=t<a?i:t>a?e:Math.max(e,i),M=[];for(let w=r;w<=d;w++){let L=l.getLine(c+w);if(!L){M.push("");continue}let H=w===r?p:0,A=w===d?b:this.colsValue-1,z="";if(typeof L.getCell=="function")for(let Y=H;Y<=A;Y++){let N=L.getCell(Y);N&&(z+=typeof N.getChars=="function"?N.getChars():"")}else z=typeof L.translateToString=="function"?L.translateToString(!1):"";M.push(z.replace(/\s+$/,""))}return M.join(`
5
- `)}catch{return this.getRowsText(t,a)}}getSelection(){try{if(typeof this.terminal?.getSelection=="function")return this.terminal.getSelection()}catch{}return""}clearSelection(){try{typeof this.terminal?.clearSelection=="function"&&this.terminal.clearSelection()}catch{}}hasSelectionSupport(){return typeof this.terminal?.selectLines=="function"}updateCellMetrics(e=!1){let t=this.container.querySelector("canvas");if(t instanceof HTMLElement&&t.offsetWidth>0&&t.offsetHeight>0&&this.colsValue>0&&this.rowsValue>0){let i=t.offsetWidth/this.colsValue,a=t.offsetHeight/this.rowsValue;(e||!this.charW||!this.charH)&&(this.charW=i,this.charH=a)}(!this.charW||!this.charH)&&(this.charW=9,this.charH=18)}};function Ze(n){let e=n.getBoundingClientRect(),t=window.visualViewport;return t?{width:Math.min(e.width,t.width),height:Math.max(0,Math.min(e.height,t.height-Math.max(0,e.top)))}:e}function Kt(n,e,t){return n.innerHTML="",n.classList.add("terminal-pending"),(async()=>{let i;if(t.renderer==="ghostty")try{i=await Ut.create(n,t.scrollback,t.theme)}catch{console.error("[tmux-web] ghostty-web failed; falling back to xterm.js"),i=await Je.create(n,t.scrollback,t.theme)}else i=await Je.create(n,t.scrollback,t.theme);let a,l=0,c,r=null,d=0,p="connecting",b=0,M=!1,w=[],L="",H=!1,A=1e3,z=location.protocol==="https:"?"wss:":"ws:",Y=t.wsBase||"/ws",N=z+"//"+location.host+Y+"/"+encodeURIComponent(e),Lt="/api/session/"+encodeURIComponent(e)+"/upload",Et=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function xt(){return w.join("")+L}async function kt(s,o=0){let u=s?i.viewportY():0,v=s?i.baseY():0,B=ie(xt());if(i.reset(),!B){s||i.scrollToBottom();return}await i.write(B),s?i.scrollToLine(v+u+o):i.scrollToBottom()}function X(s){a?.readyState===WebSocket.OPEN&&a.send(JSON.stringify(s))}function Ct(s){let o;try{o=JSON.parse(s)}catch{p==="live"&&(L+=s,i.write(ie(s)));return}if(o.type==="auth.required"){let u=localStorage.getItem("tmux-web-token");u?X({type:"auth.token",token:u}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(o.type==="attach_failed"&&typeof o.message=="string"){pe=!0,p="dead",i.reset(),i.write(`\r
4
+ `)}catch{return""}}selectRows(e,t){try{if(typeof this.terminal?.selectLines!="function")return;let i=this.terminal.buffer?.active,a=typeof i?.viewportY=="number"?i.viewportY:0,[l,c]=e<=t?[e,t]:[t,e];this.terminal.selectLines(a+l,a+c)}catch{}}selectCells(e,t,i,a){try{let l=this.terminal.buffer?.active,c=typeof l?.viewportY=="number"?l.viewportY:0,r=Math.min(t,a),d=Math.max(t,a);if(r===d){if(typeof this.terminal?.select!="function"){this.selectRows(r,d);return}let p=Math.min(e,i),L=Math.max(e,i);this.terminal.select(p,c+r,L-p+1)}else this.selectRows(r,d)}catch{this.selectRows(t,a)}}getCellsText(e,t,i,a){try{let l=this.terminal.buffer?.active;if(!l||typeof l.getLine!="function")return this.getRowsText(t,a);let c=typeof l.viewportY=="number"?l.viewportY:0,r=Math.min(t,a),d=Math.max(t,a),p=t<a?e:t>a?i:Math.min(e,i),L=t<a?i:t>a?e:Math.max(e,i),S=[];for(let w=r;w<=d;w++){let E=l.getLine(c+w);if(!E){S.push("");continue}let H=w===r?p:0,A=w===d?L:this.colsValue-1,z="";if(typeof E.getCell=="function")for(let Y=H;Y<=A;Y++){let N=E.getCell(Y);N&&(z+=typeof N.getChars=="function"?N.getChars():"")}else z=typeof E.translateToString=="function"?E.translateToString(!1):"";S.push(z.replace(/\s+$/,""))}return S.join(`
5
+ `)}catch{return this.getRowsText(t,a)}}getSelection(){try{if(typeof this.terminal?.getSelection=="function")return this.terminal.getSelection()}catch{}return""}clearSelection(){try{typeof this.terminal?.clearSelection=="function"&&this.terminal.clearSelection()}catch{}}hasSelectionSupport(){return typeof this.terminal?.selectLines=="function"}updateCellMetrics(e=!1){let t=this.container.querySelector("canvas");if(t instanceof HTMLElement&&t.offsetWidth>0&&t.offsetHeight>0&&this.colsValue>0&&this.rowsValue>0){let i=t.offsetWidth/this.colsValue,a=t.offsetHeight/this.rowsValue;(e||!this.charW||!this.charH)&&(this.charW=i,this.charH=a)}(!this.charW||!this.charH)&&(this.charW=9,this.charH=18)}};function Ze(n){let e=n.getBoundingClientRect(),t=window.visualViewport;return t?{width:Math.min(e.width,t.width),height:Math.max(0,Math.min(e.height,t.height-Math.max(0,e.top)))}:e}function Kt(n,e,t){return n.innerHTML="",n.classList.add("terminal-pending"),(async()=>{let i;if(t.renderer==="ghostty")try{i=await Ut.create(n,t.scrollback,t.theme)}catch{console.error("[tmux-web] ghostty-web failed; falling back to xterm.js"),i=await Je.create(n,t.scrollback,t.theme)}else i=await Je.create(n,t.scrollback,t.theme);let a,l=0,c,r=null,d=0,p="connecting",L=0,S=!1,w=[],E="",H=!1,A=1e3,z=location.protocol==="https:"?"wss:":"ws:",Y=t.wsBase||"/ws",N=z+"//"+location.host+Y+"/"+encodeURIComponent(e),Lt="/api/session/"+encodeURIComponent(e)+"/upload",Et=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function xt(){return w.join("")+E}async function kt(s,o=0){let u=s?i.viewportY():0,v=s?i.baseY():0,B=ie(xt());if(i.reset(),!B){s||i.scrollToBottom();return}await i.write(B),s?i.scrollToLine(v+u+o):i.scrollToBottom()}function X(s){a?.readyState===WebSocket.OPEN&&a.send(JSON.stringify(s))}function Tt(s){let o;try{o=JSON.parse(s)}catch{p==="live"&&(E+=s,i.write(ie(s)));return}if(o.type==="auth.required"){let u=localStorage.getItem("tmux-web-token");u?X({type:"auth.token",token:u}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(o.type==="attach_failed"&&typeof o.message=="string"){pe=!0,p="dead",i.reset(),i.write(`\r
6
6
  \x1B[31m`+ie(o.message)+`\x1B[0m\r
7
- `).then(()=>{me();try{a?.close()}catch{}});return}if(o.type==="auth.ok"){o.token&&localStorage.setItem("tmux-web-token",o.token),A=1e3,J(),X({type:"resize",cols:i.cols,rows:i.rows}),k();return}if(o.type==="auth.failed"){if(o.permanentLock||o.retryAfterMs&&o.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(o.message);return}return}if(o.type==="snapshot"&&typeof o.data=="string"){let u=ie(o.data);w=[u],L="",b=typeof o.lines=="number"?o.lines:t.terminal.initialLines,p="live",i.reset(),i.write(u).then(()=>i.scrollToBottom());return}if(o.type==="window_changed"&&typeof o.activeIndex=="number"){let u=new URL(location.href);u.searchParams.get("window")!==String(o.activeIndex)&&(u.searchParams.set("window",String(o.activeIndex)),history.replaceState(history.state,"",u)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:o.windows}));return}if(o.type==="history"&&typeof o.data=="string"){M=!1,o.lines>0&&o.data&&(w.unshift(o.data),b+=o.lines,kt(!0,o.lines));return}if(o.type==="data"&&typeof o.data=="string"){let u=ie(o.data);if(p==="connecting"){p="live",L=u,i.write(u);return}p==="live"&&(L+=u,i.write(u))}}let pe=!1;function ze(){if(pe)return;let s=N,o=localStorage.getItem("tmux-web-token");o&&(s+=(s.includes("?")?"&":"?")+"token="+encodeURIComponent(o)),a=new WebSocket(s),a.onopen=()=>{p="connecting",b=0,M=!1,w=[],L="",i.reset(),A=1e3},a.onmessage=u=>{typeof u.data=="string"&&Ct(u.data)},a.onclose=()=>{H||(p="connecting",!pe&&setTimeout(()=>{A=Math.min(A*2,1e4),!H&&!pe&&ze()},A))},a.onerror=()=>a?.close()}function fe(s){X({type:"input",data:s})}function J(){return i.fit()}function me(){n.classList.remove("terminal-pending")}function k(){l&&cancelAnimationFrame(l),c&&clearTimeout(c),J(),l=requestAnimationFrame(()=>{l=0,J()&&me()}),c=setTimeout(()=>{J()&&me()},120)}function Tt(){k(),setTimeout(k,50),setTimeout(k,150),setTimeout(k,300)}function Ne(s){return typeof s=="string"&&s.startsWith("image/")}function We(s){return s?.files?.length?s.files[0]??null:null}function Mt(s){if(!s?.items)return null;for(let o=0;o<s.items.length;o++){let u=s.items[o];if(u?.kind==="file"&&Ne(u.type))return u.getAsFile()}return null}async function St(s){let o=new FormData,u=s instanceof File&&s.name?s.name:"upload";o.append("file",s,u);let v=localStorage.getItem("tmux-web-token"),B={};v&&(B.Authorization="Bearer "+v);let ne=await fetch(Lt,{method:"POST",body:o,headers:B});if(!ne.ok){let qe="upload failed";try{let Xe=await ne.json();Xe.error&&(qe=Xe.error)}catch{}throw new Error(qe)}let Oe=await ne.json();if(!Oe.path)throw new Error("no path in response");return Oe.path}async function Be(s){try{let o=await St(s);fe(o)}catch{}}i.onData(s=>fe(s)),i.onResize(({cols:s,rows:o})=>X({type:"resize",cols:s,rows:o})),i.onScroll(()=>{p!=="live"||M||!i.isNearScrollbackTop()||(M=!0,X({type:"load_history",before:b}))});let Z=!1,G=!1,C=null,S=null,Q=document.createElement("div");Q.className="terminal-copy-banner",Q.innerHTML='<strong>Copy mode</strong><span class="hint">drag to select \xB7 Alt+C copies \xB7 Esc exits</span>',Q.hidden=!0,n.appendChild(Q);let $=document.createElement("div");$.className="terminal-copy-banner terminal-copy-toast",$.textContent="Copied",$.hidden=!0,n.appendChild($);function je(s,o){let u=n.querySelector(".xterm-screen, canvas"),v=(u&&u.getBoundingClientRect().width>0?u:n).getBoundingClientRect(),B=v.height>0&&i.rows>0?v.height/i.rows:18,ne=v.width>0&&i.cols>0?v.width/i.cols:9;return{row:Math.max(0,Math.min(i.rows-1,Math.floor((o-v.top)/B))),col:Math.max(0,Math.min(i.cols-1,Math.floor((s-v.left)/ne)))}}async function Ie(s){if(!s)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(s);return}}catch{}let o=document.createElement("textarea");o.value=s,o.style.position="fixed",o.style.opacity="0",o.style.pointerEvents="none",document.body.appendChild(o),o.focus(),o.select();try{document.execCommand("copy")}catch{}o.remove()}let ee;function he(){$.hidden=!1,ee&&clearTimeout(ee),ee=setTimeout(()=>{$.hidden=!0},1e3)}function U(s){Z=s,Q.hidden=!s,n.classList.toggle("terminal-copy-mode-active",s),s&&i.focus()}function Fe(){U(!Z)}function Bt(s){H||s.button!==0||G||(Z||s.shiftKey)&&(s.preventDefault(),s.stopPropagation(),G=!0,C=je(s.clientX,s.clientY),S=C,i.selectCells(C.col,C.row,S.col,S.row),document.addEventListener("mousemove",He,!0),document.addEventListener("mouseup",De,!0))}function He(s){H||!G||!C||(s.preventDefault(),s.stopPropagation(),S=je(s.clientX,s.clientY),i.selectCells(C.col,C.row,S.col,S.row))}function De(s){H||!G||!C||!S||(s.preventDefault(),s.stopPropagation(),document.removeEventListener("mousemove",He,!0),document.removeEventListener("mouseup",De,!0),G=!1,U(!1),$.textContent="\u5DF2\u9009\u4E2D \xB7 Alt+C \u590D\u5236",he(),i.focus())}n.addEventListener("mousedown",Bt,!0),document.addEventListener("keydown",It,!0);function It(s){if(!(H||!i.isFocused()||s.defaultPrevented||s.isComposing)){if(Z){if(s.key==="Escape"){s.preventDefault(),s.stopPropagation(),C=null,S=null,i.clearSelection(),U(!1);return}if(s.key==="Enter"||(s.ctrlKey||s.metaKey)&&s.code==="KeyC"){s.preventDefault(),s.stopPropagation(),Ie(i.getScreenText()).then(he),U(!1);return}}if(s.altKey&&s.code==="KeyC"&&!s.ctrlKey&&!s.metaKey){if(s.preventDefault(),s.stopPropagation(),C&&S){let o=i.getCellsText(C.col,C.row,S.col,S.row);C=null,S=null,i.clearSelection(),U(!1),o&&($.textContent="Copied",Ie(o).then(he))}else{let o=i.getSelection();o?(i.clearSelection(),$.textContent="Copied",Ie(o).then(he)):Fe()}return}if((s.ctrlKey||s.metaKey)&&s.code==="KeyV"){s.preventDefault(),s.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){let o=await navigator.clipboard.read();for(let u of o)for(let v of u.types)if(Ne(v)){let B=await u.getType(v);await Be(B);return}}}catch{}try{let o=await navigator.clipboard?.readText();o&&i.pasteText(Ve(o))}catch{}})();return}}}let ve=0;function Ve(s){return s.split(`\r
7
+ `).then(()=>{me();try{a?.close()}catch{}});return}if(o.type==="auth.ok"){o.token&&localStorage.setItem("tmux-web-token",o.token),A=1e3,J(),X({type:"resize",cols:i.cols,rows:i.rows}),C();return}if(o.type==="auth.failed"){if(o.permanentLock||o.retryAfterMs&&o.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(o.message);return}return}if(o.type==="snapshot"&&typeof o.data=="string"){let u=ie(o.data);w=[u],E="",L=typeof o.lines=="number"?o.lines:t.terminal.initialLines,p="live",i.reset(),i.write(u).then(()=>i.scrollToBottom());return}if(o.type==="window_changed"&&typeof o.activeIndex=="number"){let u=new URL(location.href);u.searchParams.get("window")!==String(o.activeIndex)&&(u.searchParams.set("window",String(o.activeIndex)),history.replaceState(history.state,"",u)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:o.windows}));return}if(o.type==="history"&&typeof o.data=="string"){S=!1,o.lines>0&&o.data&&(w.unshift(o.data),L+=o.lines,kt(!0,o.lines));return}if(o.type==="data"&&typeof o.data=="string"){let u=ie(o.data);if(p==="connecting"){p="live",E=u,i.write(u);return}p==="live"&&(E+=u,i.write(u))}}let pe=!1;function ze(){if(pe)return;let s=N,o=localStorage.getItem("tmux-web-token");o&&(s+=(s.includes("?")?"&":"?")+"token="+encodeURIComponent(o)),a=new WebSocket(s),a.onopen=()=>{p="connecting",L=0,S=!1,w=[],E="",i.reset(),A=1e3},a.onmessage=u=>{typeof u.data=="string"&&Tt(u.data)},a.onclose=()=>{H||(p="connecting",!pe&&setTimeout(()=>{A=Math.min(A*2,1e4),!H&&!pe&&ze()},A))},a.onerror=()=>a?.close()}function fe(s){X({type:"input",data:s})}function J(){return i.fit()}function me(){n.classList.remove("terminal-pending")}function C(){l&&cancelAnimationFrame(l),c&&clearTimeout(c),J(),l=requestAnimationFrame(()=>{l=0,J()&&me()}),c=setTimeout(()=>{J()&&me()},120)}function Ct(){C(),setTimeout(C,50),setTimeout(C,150),setTimeout(C,300)}function Ne(s){return typeof s=="string"&&s.startsWith("image/")}function We(s){return s?.files?.length?s.files[0]??null:null}function Mt(s){if(!s?.items)return null;for(let o=0;o<s.items.length;o++){let u=s.items[o];if(u?.kind==="file"&&Ne(u.type))return u.getAsFile()}return null}async function St(s){let o=new FormData,u=s instanceof File&&s.name?s.name:"upload";o.append("file",s,u);let v=localStorage.getItem("tmux-web-token"),B={};v&&(B.Authorization="Bearer "+v);let ne=await fetch(Lt,{method:"POST",body:o,headers:B});if(!ne.ok){let qe="upload failed";try{let Xe=await ne.json();Xe.error&&(qe=Xe.error)}catch{}throw new Error(qe)}let Oe=await ne.json();if(!Oe.path)throw new Error("no path in response");return Oe.path}async function Ie(s){try{let o=await St(s);fe(o)}catch{}}i.onData(s=>fe(s)),i.onResize(({cols:s,rows:o})=>X({type:"resize",cols:s,rows:o})),i.onScroll(()=>{p!=="live"||S||!i.isNearScrollbackTop()||(S=!0,X({type:"load_history",before:L}))});let Z=!1,G=!1,b=null,x=null,Q=document.createElement("div");Q.className="terminal-copy-banner",Q.innerHTML='<strong>Copy mode</strong><span class="hint">drag to copy \xB7 Esc exits</span>',Q.hidden=!0,n.appendChild(Q);let $=document.createElement("div");$.className="terminal-copy-banner terminal-copy-toast",$.textContent="Copied",$.hidden=!0,n.appendChild($);function je(s,o){let u=n.querySelector(".xterm-screen, canvas"),v=(u&&u.getBoundingClientRect().width>0?u:n).getBoundingClientRect(),B=v.height>0&&i.rows>0?v.height/i.rows:18,ne=v.width>0&&i.cols>0?v.width/i.cols:9;return{row:Math.max(0,Math.min(i.rows-1,Math.floor((o-v.top)/B))),col:Math.max(0,Math.min(i.cols-1,Math.floor((s-v.left)/ne)))}}async function he(s){if(!s)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(s);return}}catch{}let o=document.createElement("textarea");o.value=s,o.style.position="fixed",o.style.opacity="0",o.style.pointerEvents="none",document.body.appendChild(o),o.focus(),o.select();try{document.execCommand("copy")}catch{}o.remove()}let ee;function ve(){$.hidden=!1,ee&&clearTimeout(ee),ee=setTimeout(()=>{$.hidden=!0},1e3)}function U(s){Z=s,Q.hidden=!s,n.classList.toggle("terminal-copy-mode-active",s),s&&i.focus()}function Fe(){U(!Z)}function Bt(s){H||s.button!==0||G||(Z||s.shiftKey)&&(s.preventDefault(),s.stopPropagation(),G=!0,b=je(s.clientX,s.clientY),x=b,i.selectCells(b.col,b.row,x.col,x.row),document.addEventListener("mousemove",He,!0),document.addEventListener("mouseup",De,!0))}function He(s){H||!G||!b||(s.preventDefault(),s.stopPropagation(),x=je(s.clientX,s.clientY),i.selectCells(b.col,b.row,x.col,x.row))}function De(s){if(H||!G||!b||!x)return;s.preventDefault(),s.stopPropagation(),document.removeEventListener("mousemove",He,!0),document.removeEventListener("mouseup",De,!0),G=!1;let o=i.getCellsText(b.col,b.row,x.col,x.row);b=null,x=null,i.clearSelection(),U(!1),o&&($.textContent="\u5DF2\u590D\u5236",he(o).then(ve)),i.focus()}n.addEventListener("mousedown",Bt,!0),document.addEventListener("keydown",It,!0);function It(s){if(!(H||!i.isFocused()||s.defaultPrevented||s.isComposing)){if(Z){if(s.key==="Escape"){s.preventDefault(),s.stopPropagation(),b=null,x=null,i.clearSelection(),U(!1);return}if(s.key==="Enter"||(s.ctrlKey||s.metaKey)&&s.code==="KeyC"){s.preventDefault(),s.stopPropagation(),he(i.getScreenText()).then(ve),U(!1);return}}if(s.altKey&&s.code==="KeyC"&&!s.ctrlKey&&!s.metaKey){if(s.preventDefault(),s.stopPropagation(),b&&x){let o=i.getCellsText(b.col,b.row,x.col,x.row);b=null,x=null,i.clearSelection(),U(!1),o&&($.textContent="Copied",he(o).then(ve))}else{let o=i.getSelection();o?(i.clearSelection(),$.textContent="Copied",he(o).then(ve)):Fe()}return}if((s.ctrlKey||s.metaKey)&&s.code==="KeyV"){s.preventDefault(),s.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){let o=await navigator.clipboard.read();for(let u of o)for(let v of u.types)if(Ne(v)){let B=await u.getType(v);await Ie(B);return}}}catch{}try{let o=await navigator.clipboard?.readText();o&&i.pasteText(Ve(o))}catch{}})();return}}}let ge=0;function Ve(s){return s.split(`\r
8
8
  `).join(`
9
9
  `).split(`
10
- `).join("\r")}async function Ht(s){let o=Mt(s.clipboardData);if(o){s.preventDefault(),s.stopPropagation();let B=Date.now();if(B-ve<50)return;ve=B,await Be(o);return}let u=s.clipboardData?.getData("text/plain");if(!u)return;s.preventDefault(),s.stopPropagation();let v=Date.now();v-ve<50||(ve=v,i.pasteText(Ve(u)))}let te=0;function Dt(s){s.preventDefault(),te++,We(s.dataTransfer)&&n.classList.add("terminal-drag-over")}function Rt(s){s.preventDefault(),s.dataTransfer&&(s.dataTransfer.dropEffect="copy")}function At(s){s.preventDefault(),te--,te<=0&&(te=0,n.classList.remove("terminal-drag-over"))}async function Yt(s){s.preventDefault(),te=0,n.classList.remove("terminal-drag-over");let o=We(s.dataTransfer);o&&await Be(o)}function _e(s){!Et||s.key!=="Escape"||Z||s.defaultPrevented||s.repeat||s.metaKey||s.ctrlKey||s.altKey||i.isFocused()&&(s.preventDefault(),s.stopPropagation(),fe("\x1B"))}n.addEventListener("paste",Ht),n.addEventListener("dragenter",Dt),n.addEventListener("dragover",Rt),n.addEventListener("dragleave",At),n.addEventListener("drop",Yt),document.addEventListener("keydown",_e,!0);function $t(s){if(s.touches.length!==1){r=null;return}let o=s.touches[0];o&&(r={startX:o.clientX,startY:o.clientY,lastX:o.clientX,lastY:o.clientY,scrolling:!1},s.stopPropagation())}function Pt(s){if(!r||s.touches.length!==1)return;let o=s.touches[0];if(!o)return;let u=o.clientY-r.startY,v=o.clientX-r.startX;if(!r.scrolling){if(Math.abs(u)<8||Math.abs(u)<Math.abs(v))return;r.scrolling=!0,d=Date.now()+500}s.preventDefault(),s.stopPropagation(),jt(-(o.clientY-r.lastY),o.clientX,o.clientY),r.lastX=o.clientX,r.lastY=o.clientY}function zt(s){if(!r)return;let o=r.scrolling;r=null,s.stopPropagation(),o?(d=Date.now()+500,s.preventDefault()):i.focus()}function Nt(s){r=null,s.stopPropagation()}function Wt(s){s.pointerType==="touch"&&Date.now()<d&&(s.preventDefault(),s.stopPropagation())}function jt(s,o,u){(n.querySelector(".xterm-screen")??n).dispatchEvent(new WheelEvent("wheel",{deltaY:s,deltaMode:WheelEvent.DOM_DELTA_PIXEL,clientX:o,clientY:u,bubbles:!0,cancelable:!0}))}n.addEventListener("touchstart",$t,{passive:!0,capture:!0}),n.addEventListener("touchmove",Pt,{passive:!1,capture:!0}),n.addEventListener("touchend",zt,{passive:!1,capture:!0}),n.addEventListener("touchcancel",Nt,{passive:!0,capture:!0}),n.addEventListener("pointerup",Wt,!0);function Ue(){k()}window.addEventListener("resize",Ue),window.visualViewport?.addEventListener("resize",k),window.visualViewport?.addEventListener("scroll",k);let Ke=new ResizeObserver(()=>k());return Ke.observe(n),document.fonts?.ready.then(()=>{k(),setTimeout(k,50),setTimeout(k,200)}),n.addEventListener("focusin",Tt,!0),requestAnimationFrame(()=>{J()&&me(),ze(),k()}),{destroy(){if(H=!0,U(!1),ee&&clearTimeout(ee),document.removeEventListener("mousemove",He,!0),document.removeEventListener("mouseup",De,!0),a){try{a.close(1e3,"session switch")}catch{}a=void 0}n.innerHTML="",n.classList.remove("terminal-pending"),window.removeEventListener("resize",Ue),Ke.disconnect(),document.removeEventListener("keydown",_e,!0)},focus(){i.focus()},sendInput(s){fe(s)},toggleCopyMode(){Fe()}}})()}var K=window.__TMUX_WEB_SHELL__,h=null,y=null,Ge=typeof window.__TMUX_WEB_SCOPE__?.agentId=="string"?window.__TMUX_WEB_SCOPE__.agentId:null,x=Ge;window.__tmuxWebScopeAgent=Ge;var Qe="sessions",W="",ye="",we="",et="";function T(n){return x?"/a/"+encodeURIComponent(x)+n:n}var m=document.getElementById("sidebar-content"),F=document.getElementById("main-placeholder"),I=document.getElementById("terminal-container"),se=document.getElementById("file-editor"),Ot=document.getElementById("fe-path"),D=document.getElementById("fe-status"),ae=document.getElementById("fe-content"),V=document.getElementById("fe-save"),qt=document.getElementById("fe-delete"),Xt=document.getElementById("fe-back"),tt=document.getElementById("fe-new-name"),Jt=document.getElementById("fe-new-btn"),Re=document.getElementById("settings-backdrop"),nt=document.getElementById("settings-popover"),it=document.querySelector(".sidebar");function Zt(){return window.matchMedia("(max-width: 640px)").matches}function Ae(){Zt()&&it.classList.add("collapsed")}function st(){it.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{st(),at("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{st(),at("files")});function at(n){Qe=n,document.querySelectorAll(".mode-btn").forEach(t=>t.classList.remove("active"));let e=document.getElementById(n==="sessions"?"mode-sessions":"mode-files");e&&e.classList.add("active"),n==="sessions"?O():rn()}var ot="";async function O(){try{let e=await(await fetch("/api/sidebar/sessions")).json(),t=JSON.stringify({recent:e.recent,agents:e.agents});if(t===ot)return;ot=t,Gt(e)}catch{m.innerHTML+='<div class="file-tree-empty">Failed to load sessions</div>'}let n=document.getElementById("ns-btn");n&&n.addEventListener("click",()=>document.getElementById("new-session-modal")?.classList.add("open"))}function Gt(n){m.innerHTML='<button class="new-session-sidebar-btn" id="ns-btn">+ New Session</button>';let e=n.recent||[],t=document.createElement("div");t.className="sidebar-section-label"+(x?" clickable":""),t.textContent=x?"\u2190 \u8FD4\u56DE\u672C\u673A":"\u672C\u673A",x&&(t.title="Back to hub",t.addEventListener("click",()=>{window.location.href="/"})),m.appendChild(t);for(let a of e){let l=document.createElement("div");l.className="session-item"+(a.name===y&&!x?" active":""),l.setAttribute("data-session",a.name),l.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${a.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
+ `).join("\r")}async function Ht(s){let o=Mt(s.clipboardData);if(o){s.preventDefault(),s.stopPropagation();let B=Date.now();if(B-ge<50)return;ge=B,await Ie(o);return}let u=s.clipboardData?.getData("text/plain");if(!u)return;s.preventDefault(),s.stopPropagation();let v=Date.now();v-ge<50||(ge=v,i.pasteText(Ve(u)))}let te=0;function Dt(s){s.preventDefault(),te++,We(s.dataTransfer)&&n.classList.add("terminal-drag-over")}function Rt(s){s.preventDefault(),s.dataTransfer&&(s.dataTransfer.dropEffect="copy")}function At(s){s.preventDefault(),te--,te<=0&&(te=0,n.classList.remove("terminal-drag-over"))}async function Yt(s){s.preventDefault(),te=0,n.classList.remove("terminal-drag-over");let o=We(s.dataTransfer);o&&await Ie(o)}function _e(s){!Et||s.key!=="Escape"||Z||s.defaultPrevented||s.repeat||s.metaKey||s.ctrlKey||s.altKey||i.isFocused()&&(s.preventDefault(),s.stopPropagation(),fe("\x1B"))}n.addEventListener("paste",Ht),n.addEventListener("dragenter",Dt),n.addEventListener("dragover",Rt),n.addEventListener("dragleave",At),n.addEventListener("drop",Yt),document.addEventListener("keydown",_e,!0);function $t(s){if(s.touches.length!==1){r=null;return}let o=s.touches[0];o&&(r={startX:o.clientX,startY:o.clientY,lastX:o.clientX,lastY:o.clientY,scrolling:!1},s.stopPropagation())}function Pt(s){if(!r||s.touches.length!==1)return;let o=s.touches[0];if(!o)return;let u=o.clientY-r.startY,v=o.clientX-r.startX;if(!r.scrolling){if(Math.abs(u)<8||Math.abs(u)<Math.abs(v))return;r.scrolling=!0,d=Date.now()+500}s.preventDefault(),s.stopPropagation(),jt(-(o.clientY-r.lastY),o.clientX,o.clientY),r.lastX=o.clientX,r.lastY=o.clientY}function zt(s){if(!r)return;let o=r.scrolling;r=null,s.stopPropagation(),o?(d=Date.now()+500,s.preventDefault()):i.focus()}function Nt(s){r=null,s.stopPropagation()}function Wt(s){s.pointerType==="touch"&&Date.now()<d&&(s.preventDefault(),s.stopPropagation())}function jt(s,o,u){(n.querySelector(".xterm-screen")??n).dispatchEvent(new WheelEvent("wheel",{deltaY:s,deltaMode:WheelEvent.DOM_DELTA_PIXEL,clientX:o,clientY:u,bubbles:!0,cancelable:!0}))}n.addEventListener("touchstart",$t,{passive:!0,capture:!0}),n.addEventListener("touchmove",Pt,{passive:!1,capture:!0}),n.addEventListener("touchend",zt,{passive:!1,capture:!0}),n.addEventListener("touchcancel",Nt,{passive:!0,capture:!0}),n.addEventListener("pointerup",Wt,!0);function Ue(){C()}window.addEventListener("resize",Ue),window.visualViewport?.addEventListener("resize",C),window.visualViewport?.addEventListener("scroll",C);let Ke=new ResizeObserver(()=>C());return Ke.observe(n),document.fonts?.ready.then(()=>{C(),setTimeout(C,50),setTimeout(C,200)}),n.addEventListener("focusin",Ct,!0),requestAnimationFrame(()=>{J()&&me(),ze(),C()}),{destroy(){if(H=!0,U(!1),ee&&clearTimeout(ee),document.removeEventListener("mousemove",He,!0),document.removeEventListener("mouseup",De,!0),a){try{a.close(1e3,"session switch")}catch{}a=void 0}n.innerHTML="",n.classList.remove("terminal-pending"),window.removeEventListener("resize",Ue),Ke.disconnect(),document.removeEventListener("keydown",_e,!0)},focus(){i.focus()},sendInput(s){fe(s)},toggleCopyMode(){Fe()}}})()}var K=window.__TMUX_WEB_SHELL__,h=null,y=null,Ge=typeof window.__TMUX_WEB_SCOPE__?.agentId=="string"?window.__TMUX_WEB_SCOPE__.agentId:null,T=Ge;window.__tmuxWebScopeAgent=Ge;var Qe="sessions",W="",we="",be="",et="";function M(n){return T?"/a/"+encodeURIComponent(T)+n:n}var m=document.getElementById("sidebar-content"),F=document.getElementById("main-placeholder"),I=document.getElementById("terminal-container"),se=document.getElementById("file-editor"),Ot=document.getElementById("fe-path"),D=document.getElementById("fe-status"),ae=document.getElementById("fe-content"),V=document.getElementById("fe-save"),qt=document.getElementById("fe-delete"),Xt=document.getElementById("fe-back"),tt=document.getElementById("fe-new-name"),Jt=document.getElementById("fe-new-btn"),Re=document.getElementById("settings-backdrop"),nt=document.getElementById("settings-popover"),it=document.querySelector(".sidebar");function Zt(){return window.matchMedia("(max-width: 640px)").matches}function Ae(){Zt()&&it.classList.add("collapsed")}function st(){it.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{st(),at("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{st(),at("files")});function at(n){Qe=n,document.querySelectorAll(".mode-btn").forEach(t=>t.classList.remove("active"));let e=document.getElementById(n==="sessions"?"mode-sessions":"mode-files");e&&e.classList.add("active"),n==="sessions"?O():rn()}var ot="";async function O(){try{let e=await(await fetch("/api/sidebar/sessions")).json(),t=JSON.stringify({recent:e.recent,agents:e.agents});if(t===ot)return;ot=t,Gt(e)}catch{m.innerHTML+='<div class="file-tree-empty">Failed to load sessions</div>'}let n=document.getElementById("ns-btn");n&&n.addEventListener("click",()=>document.getElementById("new-session-modal")?.classList.add("open"))}function Gt(n){m.innerHTML='<button class="new-session-sidebar-btn" id="ns-btn">+ New Session</button>';let e=n.recent||[],t=document.createElement("div");t.className="sidebar-section-label"+(T?" clickable":""),t.textContent=T?"\u2190 \u8FD4\u56DE\u672C\u673A":"\u672C\u673A",T&&(t.title="Back to hub",t.addEventListener("click",()=>{window.location.href="/"})),m.appendChild(t);for(let a of e){let l=document.createElement("div");l.className="session-item"+(a.name===y&&!T?" active":""),l.setAttribute("data-session",a.name),l.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${a.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>
11
11
  <span>${f(a.name)}</span>
12
12
  <button class="session-edit-btn" data-session="${f(a.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>
13
- `,l.addEventListener("click",r=>{r.target.closest(".session-edit-btn")||oe(a.name)}),m.appendChild(l);let c=l.querySelector(".session-edit-btn");c&&c.addEventListener("click",r=>{r.stopPropagation(),fn(a.name,c)})}let i=n.agents||[];for(let a of i){if(!a.sessions||a.sessions.length===0)continue;let l=a.agentId===x,c=document.createElement("div");c.className="sidebar-section-label machine-label"+(a.online?"":" agent-offline-label")+(!l&&a.online?" clickable":""),c.textContent=a.agentName+(a.online?"":" (offline)"),!l&&a.online&&(c.title="\u6253\u5F00 "+a.agentName,c.addEventListener("click",()=>{window.location.href="/a/"+encodeURIComponent(a.agentId)+"/"})),m.appendChild(c);for(let r of a.sessions){let d=document.createElement("div");d.className="session-item"+(r.name===y&&x===a.agentId?" active":"")+(a.online?"":" session-offline"),d.setAttribute("data-session",r.name),d.setAttribute("data-agent",a.agentId),d.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${r.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>
14
- <span>${f(r.name)}</span><span class="meta">${a.online?"":"offline"}</span>`,a.online&&d.addEventListener("click",p=>{p.target.closest(".session-edit-btn")||oe(r.name,a.agentId)}),m.appendChild(d)}}}function f(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function oe(n,e){if(!(y===n&&h&&x===(e||null))){se.style.display="none",F.style.display="none",I.style.display="",I.classList.add("terminal-pending"),Ae(),h&&(Me(),h.destroy(),h=null),y=n,x=e||null,window.__tmuxWebScopeAgent=x;for(let t of m.querySelectorAll(".session-item"))t.classList.toggle("active",t.getAttribute("data-session")===n&&(t.getAttribute("data-agent")||null)===x);try{h=await Kt(I,n,{terminal:K.terminal,scrollback:K.scrollback,theme:K.theme,renderer:K.renderer,wsBase:x?"/ws/a/"+encodeURIComponent(x):K.wsBase||"/ws"}),vt()}catch(t){console.error("[shell] terminal init failed:",t);let i=t&&typeof t=="object"&&"message"in t?t.message:String(t);I.textContent="Failed to open terminal for "+n+": "+i,I.classList.remove("terminal-pending")}}}var be=[],g=null,lt=!1;function Qt(n){if(!g||!g.files.length)return null;let e=g.repoRoot;if(!e||!n.startsWith(e))return null;let t=n.slice(e.length+1);for(let i of g.files)if(i.path===t)return i.status;return null}async function en(n){lt=!0;try{let e=await fetch(T("/api/git/status?path="+encodeURIComponent(n)));e.ok?g=await e.json():g=null}catch{g=null}finally{lt=!1}}function tn(){if(!g||!g.branch)return"";let{branch:n,linesAdded:e,linesRemoved:t}=g,i=`<div class="sidebar-git"><div class="git-branch-badge">
13
+ `,l.addEventListener("click",r=>{r.target.closest(".session-edit-btn")||oe(a.name)}),m.appendChild(l);let c=l.querySelector(".session-edit-btn");c&&c.addEventListener("click",r=>{r.stopPropagation(),fn(a.name,c)})}let i=n.agents||[];for(let a of i){if(!a.sessions||a.sessions.length===0)continue;let l=a.agentId===T,c=document.createElement("div");c.className="sidebar-section-label machine-label"+(a.online?"":" agent-offline-label")+(!l&&a.online?" clickable":""),c.textContent=a.agentName+(a.online?"":" (offline)"),!l&&a.online&&(c.title="\u6253\u5F00 "+a.agentName,c.addEventListener("click",()=>{window.location.href="/a/"+encodeURIComponent(a.agentId)+"/"})),m.appendChild(c);for(let r of a.sessions){let d=document.createElement("div");d.className="session-item"+(r.name===y&&T===a.agentId?" active":"")+(a.online?"":" session-offline"),d.setAttribute("data-session",r.name),d.setAttribute("data-agent",a.agentId),d.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${r.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>
14
+ <span>${f(r.name)}</span><span class="meta">${a.online?"":"offline"}</span>`,a.online&&d.addEventListener("click",p=>{p.target.closest(".session-edit-btn")||oe(r.name,a.agentId)}),m.appendChild(d)}}}function f(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function oe(n,e){if(!(y===n&&h&&T===(e||null))){se.style.display="none",F.style.display="none",I.style.display="",I.classList.add("terminal-pending"),Ae(),h&&(Se(),h.destroy(),h=null),y=n,T=e||null,window.__tmuxWebScopeAgent=T;for(let t of m.querySelectorAll(".session-item"))t.classList.toggle("active",t.getAttribute("data-session")===n&&(t.getAttribute("data-agent")||null)===T);try{h=await Kt(I,n,{terminal:K.terminal,scrollback:K.scrollback,theme:K.theme,renderer:K.renderer,wsBase:T?"/ws/a/"+encodeURIComponent(T):K.wsBase||"/ws"}),vt()}catch(t){console.error("[shell] terminal init failed:",t);let i=t&&typeof t=="object"&&"message"in t?t.message:String(t);I.textContent="Failed to open terminal for "+n+": "+i,I.classList.remove("terminal-pending")}}}var Le=[],g=null,lt=!1;function Qt(n){if(!g||!g.files.length)return null;let e=g.repoRoot;if(!e||!n.startsWith(e))return null;let t=n.slice(e.length+1);for(let i of g.files)if(i.path===t)return i.status;return null}async function en(n){lt=!0;try{let e=await fetch(M("/api/git/status?path="+encodeURIComponent(n)));e.ok?g=await e.json():g=null}catch{g=null}finally{lt=!1}}function tn(){if(!g||!g.branch)return"";let{branch:n,linesAdded:e,linesRemoved:t}=g,i=`<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(n)}</div>`;return(e>0||t>0)&&(i+=`<div class="git-diff-stats">+<span class="add">${e}</span> <span class="del">-${t}</span></div>`),i+"</div>"}m.addEventListener("click",n=>{n.target.closest(".sidebar-git")&&q&&g&&(n.stopPropagation(),pt())});var le=document.getElementById("header-git"),rt=document.getElementById("git-diff-view"),ct=document.getElementById("gd-path"),Le=document.getElementById("gd-status"),Ee=document.getElementById("gd-content"),nn=document.getElementById("gd-back"),q=null;function re(n){if(!n||!n.branch){le.style.display="none",q=null;return}q=n.repoRoot;let{branch:e,linesAdded:t,linesRemoved:i}=n,a=`<span class="branch">${f(e)}</span>`;(t>0||i>0)&&(a+=`<span class="sep">\xB7</span>+<span class="diff-add">${t}</span> <span class="diff-del">-${i}</span>`),le.innerHTML=a,le.style.display="block"}le.addEventListener("click",n=>{q&&g&&(n.stopPropagation(),pt())});var E=document.getElementById("git-popover"),xe=document.getElementById("git-popover-backdrop");function Ye(){let n=le.getBoundingClientRect();E.style.top=n.bottom+4+"px",E.style.left=Math.max(8,Math.min(n.left,window.innerWidth-400))+"px"}function dt(){let n=q,e=document.getElementById("git-popover-browse");e&&e.addEventListener("click",()=>{if(Ce(),n){Qe="files",document.querySelectorAll(".mode-btn").forEach(i=>i.classList.remove("active"));let t=document.getElementById("mode-files");t&&t.classList.add("active"),j(n)}})}var ut="";function pt(){if(!g)return;let n=g.files||[];if(!n.length)E.innerHTML=`<div class="git-popover-header">No changes \u2014 clean working tree</div>
16
+ ${f(n)}</div>`;return(e>0||t>0)&&(i+=`<div class="git-diff-stats">+<span class="add">${e}</span> <span class="del">-${t}</span></div>`),i+"</div>"}m.addEventListener("click",n=>{n.target.closest(".sidebar-git")&&q&&g&&(n.stopPropagation(),pt())});var le=document.getElementById("header-git"),rt=document.getElementById("git-diff-view"),ct=document.getElementById("gd-path"),Ee=document.getElementById("gd-status"),xe=document.getElementById("gd-content"),nn=document.getElementById("gd-back"),q=null;function re(n){if(!n||!n.branch){le.style.display="none",q=null;return}q=n.repoRoot;let{branch:e,linesAdded:t,linesRemoved:i}=n,a=`<span class="branch">${f(e)}</span>`;(t>0||i>0)&&(a+=`<span class="sep">\xB7</span>+<span class="diff-add">${t}</span> <span class="diff-del">-${i}</span>`),le.innerHTML=a,le.style.display="block"}le.addEventListener("click",n=>{q&&g&&(n.stopPropagation(),pt())});var k=document.getElementById("git-popover"),ke=document.getElementById("git-popover-backdrop");function Ye(){let n=le.getBoundingClientRect();k.style.top=n.bottom+4+"px",k.style.left=Math.max(8,Math.min(n.left,window.innerWidth-400))+"px"}function dt(){let n=q,e=document.getElementById("git-popover-browse");e&&e.addEventListener("click",()=>{if(Ce(),n){Qe="files",document.querySelectorAll(".mode-btn").forEach(i=>i.classList.remove("active"));let t=document.getElementById("mode-files");t&&t.classList.add("active"),j(n)}})}var ut="";function pt(){if(!g)return;let n=g.files||[];if(!n.length)k.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 e=`<div class="git-popover-header">${n.length} file${n.length>1?"s":""} changed</div>`;for(let t=0;t<n.length;t++){let i=n[t],a=i.additions||0,l=i.deletions||0,c="";switch(i.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}e+=`<div class="git-popover-item" data-idx="${t}">
18
18
  ${c}<span class="file-path">${f(i.path)}</span>
19
19
  <span class="file-add">${a>0?"+"+a:""}</span>
20
20
  <span class="file-del">${l>0?"-"+l:""}</span>
21
- </div>`}e+='<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>',ut=e,E.innerHTML=e,E.querySelectorAll(".git-popover-item").forEach(t=>{let i=parseInt(t.dataset.idx||"0",10),a=n[i];!a||a.status==="D"||(t.classList.add("clickable"),t.style.cursor="pointer",t.addEventListener("click",()=>mt(a.path)))})}Ye(),E.classList.add("open"),xe.classList.add("open"),dt()}function sn(){return window.innerWidth>=1024}function ft(n,e){let t=(n+(e&&n?`
21
+ </div>`}e+='<div class="git-popover-footer"><button id="git-popover-browse">Browse repository \u2192</button></div>',ut=e,k.innerHTML=e,k.querySelectorAll(".git-popover-item").forEach(t=>{let i=parseInt(t.dataset.idx||"0",10),a=n[i];!a||a.status==="D"||(t.classList.add("clickable"),t.style.cursor="pointer",t.addEventListener("click",()=>mt(a.path)))})}Ye(),k.classList.add("open"),ke.classList.add("open"),dt()}function sn(){return window.innerWidth>=1024}function ft(n,e){let t=(n+(e&&n?`
22
22
  `:"")+e).split(`
23
- `),i="",a=0,l=0;for(let c of t){let r=c;if(r.startsWith("@@")){let d=r.match(/@@\s+-(\d+)[^+]*\+(\d+)/);d&&(a=parseInt(d[1],10)-1,l=parseInt(d[2],10)-1),i+=`<div class="diff-line hunk"><span class="ln-body">${f(r)}</span></div>`;continue}if(r.startsWith("diff --git")||r.startsWith("index ")||r.startsWith("--- ")||r.startsWith("+++ ")||r.startsWith("new file")||r.startsWith("deleted file")){r.startsWith("diff --git")&&(i+=`<div class="diff-line header"><span class="ln-body">${f(r)}</span></div>`);continue}if(r.startsWith("+"))l++,i+=`<div class="diff-line add"><span class="ln-no">${l}</span><span class="ln-body">${f(r)}</span></div>`;else if(r.startsWith("-"))a++,i+=`<div class="diff-line del"><span class="ln-no">${a}</span><span class="ln-body">${f(r)}</span></div>`;else if(r.startsWith("\\"))i+=`<div class="diff-line"><span class="ln-body">${f(r)}</span></div>`;else{if(!r&&!a&&!l)continue;a++,l++,i+=`<div class="diff-line"><span class="ln-no">${a}</span><span class="ln-no" style="margin-right:12px">${l}</span><span class="ln-body">${f(r)}</span></div>`}}return{html:i,lineCount:t.length}}var ke=null;async function mt(n){let e=q;if(e)if(Ce(),sn()){I.style.display="none",h&&(Me(),h.destroy(),h=null,ke=y,y=null),re(null),se.style.display="none",F.style.display="none",rt.style.display="flex",ct.textContent=n,Le.textContent="Loading\u2026",Ee.innerHTML="";try{let t=await fetch(T("/api/git/diff?path="+encodeURIComponent(e)+"&file="+encodeURIComponent(n)));if(!t.ok)throw new Error(await t.text());let i=await t.json();on(n,i.diff,i.stagedDiff)}catch(t){let i=t instanceof Error?t.message:String(t);Le.textContent="Error",Ee.innerHTML=`<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">Error: ${f(i)}</div>`}}else{E.innerHTML=`<div class="git-diff-view"><div class="diff-header">
23
+ `),i="",a=0,l=0;for(let c of t){let r=c;if(r.startsWith("@@")){let d=r.match(/@@\s+-(\d+)[^+]*\+(\d+)/);d&&(a=parseInt(d[1],10)-1,l=parseInt(d[2],10)-1),i+=`<div class="diff-line hunk"><span class="ln-body">${f(r)}</span></div>`;continue}if(r.startsWith("diff --git")||r.startsWith("index ")||r.startsWith("--- ")||r.startsWith("+++ ")||r.startsWith("new file")||r.startsWith("deleted file")){r.startsWith("diff --git")&&(i+=`<div class="diff-line header"><span class="ln-body">${f(r)}</span></div>`);continue}if(r.startsWith("+"))l++,i+=`<div class="diff-line add"><span class="ln-no">${l}</span><span class="ln-body">${f(r)}</span></div>`;else if(r.startsWith("-"))a++,i+=`<div class="diff-line del"><span class="ln-no">${a}</span><span class="ln-body">${f(r)}</span></div>`;else if(r.startsWith("\\"))i+=`<div class="diff-line"><span class="ln-body">${f(r)}</span></div>`;else{if(!r&&!a&&!l)continue;a++,l++,i+=`<div class="diff-line"><span class="ln-no">${a}</span><span class="ln-no" style="margin-right:12px">${l}</span><span class="ln-body">${f(r)}</span></div>`}}return{html:i,lineCount:t.length}}var Te=null;async function mt(n){let e=q;if(e)if(Ce(),sn()){I.style.display="none",h&&(Se(),h.destroy(),h=null,Te=y,y=null),re(null),se.style.display="none",F.style.display="none",rt.style.display="flex",ct.textContent=n,Ee.textContent="Loading\u2026",xe.innerHTML="";try{let t=await fetch(M("/api/git/diff?path="+encodeURIComponent(e)+"&file="+encodeURIComponent(n)));if(!t.ok)throw new Error(await t.text());let i=await t.json();on(n,i.diff,i.stagedDiff)}catch(t){let i=t instanceof Error?t.message:String(t);Ee.textContent="Error",xe.innerHTML=`<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">Error: ${f(i)}</div>`}}else{k.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(n)}</span>
26
26
  <span class="diff-loading">Loading\u2026</span>
27
- </div></div>`,Ye(),E.classList.add("open"),xe.classList.add("open");try{let t=await fetch(T("/api/git/diff?path="+encodeURIComponent(e)+"&file="+encodeURIComponent(n)));if(!t.ok)throw new Error(await t.text());let i=await t.json();an(n,i.diff,i.stagedDiff)}catch(t){let i=t instanceof Error?t.message:String(t);E.innerHTML=`<div class="git-diff-view"><div class="diff-header">
27
+ </div></div>`,Ye(),k.classList.add("open"),ke.classList.add("open");try{let t=await fetch(M("/api/git/diff?path="+encodeURIComponent(e)+"&file="+encodeURIComponent(n)));if(!t.ok)throw new Error(await t.text());let i=await t.json();an(n,i.diff,i.stagedDiff)}catch(t){let i=t instanceof Error?t.message:String(t);k.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(n)}</span>
30
- </div><div class="diff-empty">Error loading diff: ${f(i)}</div></div>`}}}function an(n,e,t){if(!e&&!t){E.innerHTML=`<div class="git-diff-view"><div class="diff-header">
30
+ </div><div class="diff-empty">Error loading diff: ${f(i)}</div></div>`}}}function an(n,e,t){if(!e&&!t){k.innerHTML=`<div class="git-diff-view"><div class="diff-header">
31
31
  <button class="diff-back">\u2190 Back</button>
32
32
  <span class="diff-filename">${f(n)}</span>
33
- </div><div class="diff-empty">No diff content available</div></div>`;return}let{html:i,lineCount:a}=ft(e,t);E.innerHTML=`<div class="git-diff-view"><div class="diff-header">
33
+ </div><div class="diff-empty">No diff content available</div></div>`;return}let{html:i,lineCount:a}=ft(e,t);k.innerHTML=`<div class="git-diff-view"><div class="diff-header">
34
34
  <button class="diff-back">\u2190 Back</button>
35
35
  <span class="diff-filename">${f(n)}</span>
36
36
  <span class="diff-filesize">${a} lines</span>
37
- </div><div class="diff-content">${i}</div></div>`,E.querySelector(".diff-back")?.addEventListener("click",()=>{E.innerHTML=ut,Ye(),g&&E.querySelectorAll(".git-popover-item").forEach(l=>{let c=parseInt(l.dataset.idx||"0",10),r=g.files[c];!r||r.status==="D"||(l.style.cursor="pointer",l.addEventListener("click",()=>mt(r.path)))}),dt()})}function on(n,e,t){if(!e&&!t){Le.textContent="No diff",Ee.innerHTML='<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">No diff content available</div>';return}let{html:i,lineCount:a}=ft(e,t);ct.textContent=n,Le.textContent=a+" lines",Ee.innerHTML=i}function ln(){rt.style.display="none",ke?(I.style.display="",I.classList.add("terminal-pending"),oe(ke),ke=null):y?(I.style.display="",I.classList.add("terminal-pending"),vt()):F.style.display="flex"}nn.addEventListener("click",ln);function Ce(){E.classList.remove("open"),xe.classList.remove("open")}xe.addEventListener("click",Ce),document.addEventListener("keydown",n=>{n.key==="Escape"&&(Ce(),Se())});async function ht(n){try{let e=await(await fetch("/api/fs/session-path?session="+encodeURIComponent(n))).json();if(e.path){let t=await fetch("/api/git/status?path="+encodeURIComponent(e.path));if(t.ok){let i=await t.json();g=i,re(i);return}}}catch{}g=null,re(null)}var Te=null;function vt(){Me(),y&&(ht(y),Te=setInterval(()=>{y&&ht(y)},3e4))}function Me(){Te&&(clearInterval(Te),Te=null)}function rn(){if(be=K.fsRoots||[],be.length===0){if(y){cn(y);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 n of be){let e=document.createElement("div");e.className="file-tree-item",e.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(n)}`,e.addEventListener("click",()=>j(n)),m.appendChild(e)}}async function cn(n){m.innerHTML='<div class="file-tree-empty">Loading...</div>';try{let e=await(await fetch(T("/api/fs/session-path?session="+encodeURIComponent(n)))).json();e.path?j(e.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 j(n){W=n,m.innerHTML='<div class="file-tree-empty">Loading...</div>';let e=en(n);try{let t=await(await fetch(T("/api/fs/list?path="+encodeURIComponent(n)))).json();await e,m.innerHTML="",re(g),m.innerHTML+=tn();let i=dn(n);if(i&&!be.some(l=>n===l)){let l=document.createElement("div");l.className="file-tree-item",l.innerHTML="..",l.addEventListener("click",()=>j(i)),m.appendChild(l)}if(t.dirs)for(let l of t.dirs){let c=l.split("/").pop()||l.split("\\").pop(),r=document.createElement("div");r.className="file-tree-item",r.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)}`,r.addEventListener("click",()=>j(l)),m.appendChild(r)}else m.innerHTML="";let a=t.files||[];for(let l of a){let c=l.split("/").pop()||l.split("\\").pop(),r=Qt(l),d="",p="";if(r)switch(r){case"M":d="git-mod",p='<span class="git-file-status M">M</span>';break;case"A":d="git-add",p='<span class="git-file-status A">A</span>';break;case"D":d="git-del",p='<span class="git-file-status D">D</span>';break;case"?":d="git-untracked",p='<span class="git-file-status ?">?</span>';break;case"R":d="git-mod",p='<span class="git-file-status R">R</span>';break}let b=document.createElement("div");b.className="file-tree-item file"+(d?" "+d:""),b.innerHTML=`<span class="file-icon">\u{1F4C4}</span> ${p}${f(c)}`,b.addEventListener("click",()=>un(l)),m.appendChild(b)}}catch{m.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function dn(n){let e=n.lastIndexOf("/");return e<=0?null:n.substring(0,e)}async function un(n){ye=n,I.style.display="none",h&&(Me(),h.destroy(),h=null,y=null),re(null),Ae(),F.style.display="none",se.style.display="flex",Ot.textContent=n,D.textContent="Loading...",V.style.display="none";try{let e=await fetch(T("/api/file?path="+encodeURIComponent(n)));if(!e.ok){let i=await e.json();D.textContent=i.error||"Failed to load",ae.value="";return}let t=await e.json();ae.value=t.content,we=t.content,et=t.content,D.textContent=t.size+" bytes",V.style.display=""}catch{D.textContent="Failed to load",ae.value=""}}ae.addEventListener("input",()=>{we=ae.value}),V.addEventListener("click",async()=>{V.textContent="Saving...",V.disabled=!0;try{let n=await fetch(T("/api/file"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:ye,content:we})});if(!n.ok){let e=await n.json();D.textContent=e.error||"Save failed";return}et=we,D.textContent="Saved"}catch{D.textContent="Save failed"}finally{V.disabled=!1,V.textContent="Save"}}),qt.addEventListener("click",async()=>{if(confirm("Delete "+ye+"?"))try{let n=await fetch(T("/api/file/delete"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:ye})});if(!n.ok){let e=await n.json();D.textContent=e.error||"Delete failed";return}se.style.display="none",F.style.display="flex",W&&j(W)}catch{D.textContent="Delete failed"}}),Xt.addEventListener("click",()=>{se.style.display="none",F.style.display="flex",W&&j(W)}),Jt.addEventListener("click",async()=>{let n=tt.value.trim();if(!n)return;let e=W+"/"+n;try{let t=await fetch(T("/api/file/touch"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})});if(!t.ok){let i=await t.json();D.textContent=i.error||"Create failed";return}tt.value="",W&&j(W)}catch{D.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{let n=nt.classList.toggle("open");Re.classList.toggle("open",n)}),Re.addEventListener("click",()=>{nt.classList.remove("open"),Re.classList.remove("open")});var _="",ce=document.createElement("div");ce.className="session-popover-backdrop",document.body.appendChild(ce);var P=document.createElement("div");P.id="session-popover",P.className="session-popover",P.style.display="none",P.innerHTML=`<div class="sp-field">
37
+ </div><div class="diff-content">${i}</div></div>`,k.querySelector(".diff-back")?.addEventListener("click",()=>{k.innerHTML=ut,Ye(),g&&k.querySelectorAll(".git-popover-item").forEach(l=>{let c=parseInt(l.dataset.idx||"0",10),r=g.files[c];!r||r.status==="D"||(l.style.cursor="pointer",l.addEventListener("click",()=>mt(r.path)))}),dt()})}function on(n,e,t){if(!e&&!t){Ee.textContent="No diff",xe.innerHTML='<div class="diff-empty" style="padding:24px;text-align:center;color:var(--panel-muted)">No diff content available</div>';return}let{html:i,lineCount:a}=ft(e,t);ct.textContent=n,Ee.textContent=a+" lines",xe.innerHTML=i}function ln(){rt.style.display="none",Te?(I.style.display="",I.classList.add("terminal-pending"),oe(Te),Te=null):y?(I.style.display="",I.classList.add("terminal-pending"),vt()):F.style.display="flex"}nn.addEventListener("click",ln);function Ce(){k.classList.remove("open"),ke.classList.remove("open")}ke.addEventListener("click",Ce),document.addEventListener("keydown",n=>{n.key==="Escape"&&(Ce(),Be())});async function ht(n){try{let e=await(await fetch("/api/fs/session-path?session="+encodeURIComponent(n))).json();if(e.path){let t=await fetch("/api/git/status?path="+encodeURIComponent(e.path));if(t.ok){let i=await t.json();g=i,re(i);return}}}catch{}g=null,re(null)}var Me=null;function vt(){Se(),y&&(ht(y),Me=setInterval(()=>{y&&ht(y)},3e4))}function Se(){Me&&(clearInterval(Me),Me=null)}function rn(){if(Le=K.fsRoots||[],Le.length===0){if(y){cn(y);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 n of Le){let e=document.createElement("div");e.className="file-tree-item",e.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(n)}`,e.addEventListener("click",()=>j(n)),m.appendChild(e)}}async function cn(n){m.innerHTML='<div class="file-tree-empty">Loading...</div>';try{let e=await(await fetch(M("/api/fs/session-path?session="+encodeURIComponent(n)))).json();e.path?j(e.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 j(n){W=n,m.innerHTML='<div class="file-tree-empty">Loading...</div>';let e=en(n);try{let t=await(await fetch(M("/api/fs/list?path="+encodeURIComponent(n)))).json();await e,m.innerHTML="",re(g),m.innerHTML+=tn();let i=dn(n);if(i&&!Le.some(l=>n===l)){let l=document.createElement("div");l.className="file-tree-item",l.innerHTML="..",l.addEventListener("click",()=>j(i)),m.appendChild(l)}if(t.dirs)for(let l of t.dirs){let c=l.split("/").pop()||l.split("\\").pop(),r=document.createElement("div");r.className="file-tree-item",r.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)}`,r.addEventListener("click",()=>j(l)),m.appendChild(r)}else m.innerHTML="";let a=t.files||[];for(let l of a){let c=l.split("/").pop()||l.split("\\").pop(),r=Qt(l),d="",p="";if(r)switch(r){case"M":d="git-mod",p='<span class="git-file-status M">M</span>';break;case"A":d="git-add",p='<span class="git-file-status A">A</span>';break;case"D":d="git-del",p='<span class="git-file-status D">D</span>';break;case"?":d="git-untracked",p='<span class="git-file-status ?">?</span>';break;case"R":d="git-mod",p='<span class="git-file-status R">R</span>';break}let L=document.createElement("div");L.className="file-tree-item file"+(d?" "+d:""),L.innerHTML=`<span class="file-icon">\u{1F4C4}</span> ${p}${f(c)}`,L.addEventListener("click",()=>un(l)),m.appendChild(L)}}catch{m.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function dn(n){let e=n.lastIndexOf("/");return e<=0?null:n.substring(0,e)}async function un(n){we=n,I.style.display="none",h&&(Se(),h.destroy(),h=null,y=null),re(null),Ae(),F.style.display="none",se.style.display="flex",Ot.textContent=n,D.textContent="Loading...",V.style.display="none";try{let e=await fetch(M("/api/file?path="+encodeURIComponent(n)));if(!e.ok){let i=await e.json();D.textContent=i.error||"Failed to load",ae.value="";return}let t=await e.json();ae.value=t.content,be=t.content,et=t.content,D.textContent=t.size+" bytes",V.style.display=""}catch{D.textContent="Failed to load",ae.value=""}}ae.addEventListener("input",()=>{be=ae.value}),V.addEventListener("click",async()=>{V.textContent="Saving...",V.disabled=!0;try{let n=await fetch(M("/api/file"),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:we,content:be})});if(!n.ok){let e=await n.json();D.textContent=e.error||"Save failed";return}et=be,D.textContent="Saved"}catch{D.textContent="Save failed"}finally{V.disabled=!1,V.textContent="Save"}}),qt.addEventListener("click",async()=>{if(confirm("Delete "+we+"?"))try{let n=await fetch(M("/api/file/delete"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:we})});if(!n.ok){let e=await n.json();D.textContent=e.error||"Delete failed";return}se.style.display="none",F.style.display="flex",W&&j(W)}catch{D.textContent="Delete failed"}}),Xt.addEventListener("click",()=>{se.style.display="none",F.style.display="flex",W&&j(W)}),Jt.addEventListener("click",async()=>{let n=tt.value.trim();if(!n)return;let e=W+"/"+n;try{let t=await fetch(M("/api/file/touch"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e})});if(!t.ok){let i=await t.json();D.textContent=i.error||"Create failed";return}tt.value="",W&&j(W)}catch{D.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{let n=nt.classList.toggle("open");Re.classList.toggle("open",n)}),Re.addEventListener("click",()=>{nt.classList.remove("open"),Re.classList.remove("open")});var _="",ce=document.createElement("div");ce.className="session-popover-backdrop",document.body.appendChild(ce);var P=document.createElement("div");P.id="session-popover",P.className="session-popover",P.style.display="none",P.innerHTML=`<div class="sp-field">
38
38
  <label>Rename session</label>
39
39
  <input type="text" id="sp-name" />
40
40
  </div>
@@ -43,5 +43,5 @@ var Ft="https://esm.sh/ghostty-web@0.4.0",Vt=/\x1b\](?:10|11|110|111|104)(?:;[^\
43
43
  <button class="btn" id="sp-cancel">Cancel</button>
44
44
  </div>
45
45
  <hr class="sp-divider" />
46
- <button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(P);function pn(n){let e=n.getBoundingClientRect();P.style.top=e.bottom+4+"px",P.style.left=Math.max(8,Math.min(e.left,window.innerWidth-240))+"px"}function fn(n,e){_=n;let t=document.getElementById("sp-name");t.value=n,ce.classList.add("open"),P.style.display="block",pn(e),setTimeout(()=>t.focus(),50)}function de(){ce.classList.remove("open"),P.style.display="none"}ce.addEventListener("click",de),document.getElementById("sp-save").addEventListener("click",async()=>{let n=document.getElementById("sp-name").value.trim();if(!n||n===_){de();return}try{if(!(await fetch(T("/api/sessions/rename"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({oldName:_,newName:n})})).ok)return;de(),O(),y===_&&oe(n)}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(confirm('Delete session "'+_+'"?'))try{if(!(await fetch(T("/api/sessions/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:_})})).ok)return;de(),y===_&&(h&&(h.destroy(),h=null),y=null,I.style.display="none",F.style.display="flex"),O()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",de);var mn={esc:"\x1B",tab:" ","s-tab":"\x1B[Z",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",space:" ",enter:"\r",exit:"exit\r",yes:"yes\r"};document.getElementById("mobile-keys").addEventListener("click",n=>{let e=n.target.closest("button[data-key]");if(!e||!h)return;let t=mn[e.dataset.key];t&&(h.sendInput(t),h.focus())});var R=document.getElementById("mk-input"),gt=document.getElementById("mk-send");function yt(){if(!R||!h)return;let n=R.value;n&&(h.sendInput(n+"\r"),R.value="",R.rows=1,h.focus())}if(R&&(R.addEventListener("input",()=>{R.rows=1;let n=R.value.split(`
47
- `).length;R.rows=Math.min(n,4)}),R.addEventListener("keydown",n=>{n.key==="Enter"&&!n.shiftKey&&(n.preventDefault(),yt())})),gt&&gt.addEventListener("click",yt),window.visualViewport){let n=document.querySelector(".app-layout"),e=()=>{n&&(n.style.height=window.visualViewport.height+"px"),window.scrollTo(0,0),document.documentElement.scrollTop=0,document.body.scrollTop=0};window.visualViewport.addEventListener("resize",e),window.addEventListener("orientationchange",()=>setTimeout(e,100)),document.addEventListener("touchstart",()=>{(window.scrollY>0||document.documentElement.scrollTop>0)&&window.scrollTo(0,0)},{passive:!0})}var $e=document.getElementById("process-panel"),ue=document.getElementById("proc-list"),hn=document.getElementById("proc-close"),Pe=document.getElementById("proc-backdrop"),vn=document.getElementById("header-ram");function gn(){ue.innerHTML='<div class="proc-empty">Loading\u2026</div>',fetch(T("/api/system/processes")).then(n=>n.json()).then(n=>{if(!Array.isArray(n)||!n.length){ue.innerHTML='<div class="proc-empty">No processes</div>';return}let e="";for(let t of n){let i=t.rss,a=i<1048576?(i/1024).toFixed(0)+"K":(i/1048576).toFixed(1)+"M";e+='<div class="proc-row" data-pid="'+t.pid+'"><span class="proc-mem">'+t.mem+'%</span><span class="proc-rss">'+a+'</span><span class="proc-cmd" title="'+f(t.command)+'">'+f(t.command)+'</span><button class="proc-kill" title="Kill PID '+t.pid+'">&times;</button></div>'}ue.innerHTML=e;for(let t of ue.querySelectorAll(".proc-row")){let i=t.querySelector(".proc-kill");i&&i.addEventListener("click",a=>{let l=a.target.closest(".proc-row");!l||!confirm("Kill PID "+l.dataset.pid+"?")||fetch(T("/api/system/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({pid:parseInt(l.dataset.pid,10)})}).then(c=>c.json()).then(c=>{c.ok?l.style.opacity="0.3":alert("Failed: "+(c.error||"unknown"))}).catch(()=>alert("Network error"))})}}).catch(()=>{ue.innerHTML='<div class="proc-empty">Failed to load</div>'})}function yn(){$e.classList.add("open"),Pe.classList.add("open"),gn()}function Se(){$e.classList.remove("open"),Pe.classList.remove("open")}vn.addEventListener("click",n=>{n.stopPropagation(),$e.classList.contains("open")?Se():yn()}),hn.addEventListener("click",Se),Pe.addEventListener("click",Se),window.__openSession=oe,window.__refreshSidebar=O,O(),Ae(),setInterval(()=>{document.visibilityState==="visible"&&O()},1e4);
46
+ <button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(P);function pn(n){let e=n.getBoundingClientRect();P.style.top=e.bottom+4+"px",P.style.left=Math.max(8,Math.min(e.left,window.innerWidth-240))+"px"}function fn(n,e){_=n;let t=document.getElementById("sp-name");t.value=n,ce.classList.add("open"),P.style.display="block",pn(e),setTimeout(()=>t.focus(),50)}function de(){ce.classList.remove("open"),P.style.display="none"}ce.addEventListener("click",de),document.getElementById("sp-save").addEventListener("click",async()=>{let n=document.getElementById("sp-name").value.trim();if(!n||n===_){de();return}try{if(!(await fetch(M("/api/sessions/rename"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({oldName:_,newName:n})})).ok)return;de(),O(),y===_&&oe(n)}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(confirm('Delete session "'+_+'"?'))try{if(!(await fetch(M("/api/sessions/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:_})})).ok)return;de(),y===_&&(h&&(h.destroy(),h=null),y=null,I.style.display="none",F.style.display="flex"),O()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",de);var mn={esc:"\x1B",tab:" ","s-tab":"\x1B[Z",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",space:" ",enter:"\r",exit:"exit\r",yes:"yes\r"};document.getElementById("mobile-keys").addEventListener("click",n=>{let e=n.target.closest("button[data-key]");if(!e||!h)return;let t=mn[e.dataset.key];t&&(h.sendInput(t),h.focus())});var R=document.getElementById("mk-input"),gt=document.getElementById("mk-send");function yt(){if(!R||!h)return;let n=R.value;n&&(h.sendInput(n+"\r"),R.value="",R.rows=1,h.focus())}if(R&&(R.addEventListener("input",()=>{R.rows=1;let n=R.value.split(`
47
+ `).length;R.rows=Math.min(n,4)}),R.addEventListener("keydown",n=>{n.key==="Enter"&&!n.shiftKey&&(n.preventDefault(),yt())})),gt&&gt.addEventListener("click",yt),window.visualViewport){let n=document.querySelector(".app-layout"),e=()=>{n&&(n.style.height=window.visualViewport.height+"px"),window.scrollTo(0,0),document.documentElement.scrollTop=0,document.body.scrollTop=0};window.visualViewport.addEventListener("resize",e),window.addEventListener("orientationchange",()=>setTimeout(e,100)),document.addEventListener("touchstart",()=>{(window.scrollY>0||document.documentElement.scrollTop>0)&&window.scrollTo(0,0)},{passive:!0})}var $e=document.getElementById("process-panel"),ue=document.getElementById("proc-list"),hn=document.getElementById("proc-close"),Pe=document.getElementById("proc-backdrop"),vn=document.getElementById("header-ram");function gn(){ue.innerHTML='<div class="proc-empty">Loading\u2026</div>',fetch(M("/api/system/processes")).then(n=>n.json()).then(n=>{if(!Array.isArray(n)||!n.length){ue.innerHTML='<div class="proc-empty">No processes</div>';return}let e="";for(let t of n){let i=t.rss,a=i<1048576?(i/1024).toFixed(0)+"K":(i/1048576).toFixed(1)+"M";e+='<div class="proc-row" data-pid="'+t.pid+'"><span class="proc-mem">'+t.mem+'%</span><span class="proc-rss">'+a+'</span><span class="proc-cmd" title="'+f(t.command)+'">'+f(t.command)+'</span><button class="proc-kill" title="Kill PID '+t.pid+'">&times;</button></div>'}ue.innerHTML=e;for(let t of ue.querySelectorAll(".proc-row")){let i=t.querySelector(".proc-kill");i&&i.addEventListener("click",a=>{let l=a.target.closest(".proc-row");!l||!confirm("Kill PID "+l.dataset.pid+"?")||fetch(M("/api/system/kill"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({pid:parseInt(l.dataset.pid,10)})}).then(c=>c.json()).then(c=>{c.ok?l.style.opacity="0.3":alert("Failed: "+(c.error||"unknown"))}).catch(()=>alert("Network error"))})}}).catch(()=>{ue.innerHTML='<div class="proc-empty">Failed to load</div>'})}function yn(){$e.classList.add("open"),Pe.classList.add("open"),gn()}function Be(){$e.classList.remove("open"),Pe.classList.remove("open")}vn.addEventListener("click",n=>{n.stopPropagation(),$e.classList.contains("open")?Be():yn()}),hn.addEventListener("click",Be),Pe.addEventListener("click",Be),window.__openSession=oe,window.__refreshSidebar=O,O(),Ae(),setInterval(()=>{document.visibilityState==="visible"&&O()},1e4);
@@ -1,10 +1,10 @@
1
- const kt="https://esm.sh/ghostty-web@0.4.0",Pt=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function K(a){return a.replace(Pt,"")}let A;function Ft(){return A||(document.querySelector("link[data-tmux-web-xterm-css]")?A=Promise.resolve():(A=new Promise(e=>{const r=document.createElement("link");r.rel="stylesheet",r.href="/assets/xterm.css",r.setAttribute("data-tmux-web-xterm-css",""),r.addEventListener("load",()=>e(),{once:!0}),r.addEventListener("error",()=>e(),{once:!0}),document.head.appendChild(r)}),A))}class q{terminal;fitAddon;container;constructor(e,r,i){this.container=e,this.terminal=r,this.fitAddon=i,this.terminal.loadAddon(this.fitAddon),this.terminal.open(e)}static async create(e,r,i){const[{Terminal:o},{FitAddon:c}]=await Promise.all([import("@xterm/xterm"),import("@xterm/addon-fit"),Ft()]),h=new o({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:r,convertEol:!1,theme:i});return new q(e,h,new c)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(e){return new Promise(r=>this.terminal.write(e,r))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(e){this.terminal.scrollToLine(Math.max(0,e))}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){const e=lt(this.container);return e.width<=0||e.height<=0?!1:(this.fitAddon.fit(),!0)}focus(){this.terminal.focus()}pasteText(e){this.terminal.paste(e)}input(e){this.terminal.input(e,!1)}onData(e){this.terminal.onData(e),this.terminal.onBinary(e)}onResize(e){this.terminal.onResize(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){const e=document.activeElement;return e?e===this.container||e===this.terminal.textarea||this.container.contains(e)||!!e.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(e,r){const i=this.terminal.buffer.active,[o,c]=e<=r?[e,r]:[r,e],h=i.viewportY,l=[];for(let f=o;f<=c;f++){const u=i.getLine(h+f);l.push(u?u.translateToString(!0):"")}return l.join(`
2
- `)}selectRows(e,r){const i=this.terminal.buffer.active,[o,c]=e<=r?[e,r]:[r,e];this.terminal.selectLines(i.viewportY+o,i.viewportY+c)}selectCells(e,r,i,o){const c=this.terminal.buffer.active,h=Math.min(r,o),l=Math.max(r,o);if(h===l){const f=Math.min(e,i),u=Math.max(e,i);this.terminal.select(f,c.viewportY+h,u-f+1)}else this.terminal.selectLines(c.viewportY+h,c.viewportY+l)}getCellsText(e,r,i,o){const c=this.terminal.buffer.active,h=Math.min(r,o),l=Math.max(r,o),f=r<o?e:r>o?i:Math.min(e,i),u=r<o?i:r>o?e:Math.max(e,i),x=c.viewportY,v=[];for(let p=h;p<=l;p++){const d=c.getLine(x+p);if(!d){v.push("");continue}const T=p===h?f:0,S=p===l?u:this.terminal.cols-1;let M="";for(let L=T;L<=S;L++){const C=d.getCell(L);C&&(M+=C.getChars())}v.push(M.replace(/\s+$/,""))}return v.join(`
1
+ const kt="https://esm.sh/ghostty-web@0.4.0",Pt=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function K(a){return a.replace(Pt,"")}let V;function Ft(){return V||(document.querySelector("link[data-tmux-web-xterm-css]")?V=Promise.resolve():(V=new Promise(e=>{const r=document.createElement("link");r.rel="stylesheet",r.href="/assets/xterm.css",r.setAttribute("data-tmux-web-xterm-css",""),r.addEventListener("load",()=>e(),{once:!0}),r.addEventListener("error",()=>e(),{once:!0}),document.head.appendChild(r)}),V))}class N{terminal;fitAddon;container;constructor(e,r,i){this.container=e,this.terminal=r,this.fitAddon=i,this.terminal.loadAddon(this.fitAddon),this.terminal.open(e)}static async create(e,r,i){const[{Terminal:o},{FitAddon:c}]=await Promise.all([import("@xterm/xterm"),import("@xterm/addon-fit"),Ft()]),h=new o({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:r,convertEol:!1,theme:i});return new N(e,h,new c)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(e){return new Promise(r=>this.terminal.write(e,r))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(e){this.terminal.scrollToLine(Math.max(0,e))}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){const e=lt(this.container);return e.width<=0||e.height<=0?!1:(this.fitAddon.fit(),!0)}focus(){this.terminal.focus()}pasteText(e){this.terminal.paste(e)}input(e){this.terminal.input(e,!1)}onData(e){this.terminal.onData(e),this.terminal.onBinary(e)}onResize(e){this.terminal.onResize(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){const e=document.activeElement;return e?e===this.container||e===this.terminal.textarea||this.container.contains(e)||!!e.closest?.(".xterm"):!1}getScreenText(){return this.getRowsText(0,this.terminal.rows-1)}getRowsText(e,r){const i=this.terminal.buffer.active,[o,c]=e<=r?[e,r]:[r,e],h=i.viewportY,l=[];for(let f=o;f<=c;f++){const u=i.getLine(h+f);l.push(u?u.translateToString(!0):"")}return l.join(`
2
+ `)}selectRows(e,r){const i=this.terminal.buffer.active,[o,c]=e<=r?[e,r]:[r,e];this.terminal.selectLines(i.viewportY+o,i.viewportY+c)}selectCells(e,r,i,o){const c=this.terminal.buffer.active,h=Math.min(r,o),l=Math.max(r,o);if(h===l){const f=Math.min(e,i),u=Math.max(e,i);this.terminal.select(f,c.viewportY+h,u-f+1)}else this.terminal.selectLines(c.viewportY+h,c.viewportY+l)}getCellsText(e,r,i,o){const c=this.terminal.buffer.active,h=Math.min(r,o),l=Math.max(r,o),f=r<o?e:r>o?i:Math.min(e,i),u=r<o?i:r>o?e:Math.max(e,i),T=c.viewportY,b=[];for(let p=h;p<=l;p++){const g=c.getLine(T+p);if(!g){b.push("");continue}const x=p===h?f:0,S=p===l?u:this.terminal.cols-1;let M="";for(let L=x;L<=S;L++){const C=g.getCell(L);C&&(M+=C.getChars())}b.push(M.replace(/\s+$/,""))}return b.join(`
3
3
  `)}getSelection(){return this.terminal.getSelection()}clearSelection(){this.terminal.clearSelection()}hasSelectionSupport(){return!0}}class ${terminal;container;colsValue=80;rowsValue=24;charW=0;charH=0;resizeCallbacks=[];constructor(e,r){this.container=e,this.terminal=r,this.terminal.open(e)}static async create(e,r,i){const o=await import(kt);await o.init();const c=new o.Terminal({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:r,convertEol:!1,theme:i});return new $(e,c)}get cols(){return this.colsValue}get rows(){return this.rowsValue}write(e){return new Promise(r=>this.terminal.write(e,r))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom?.()}scrollToLine(e){this.terminal.scrollToLine?.(Math.max(0,e))}isNearScrollbackTop(){const e=this.terminal.buffer?.active;return e?e.viewportY>=e.baseY:!1}viewportY(){return this.terminal.buffer?.active?.viewportY??0}baseY(){return this.terminal.buffer?.active?.baseY??0}fit(){const e=lt(this.container);if(e.width<=0||e.height<=0)return!1;this.updateCellMetrics(!this.charW||!this.charH);const r=Math.floor(e.width/this.charW),i=Math.floor(e.height/this.charH);if(r<10||i<5)return!1;if(r!==this.colsValue||i!==this.rowsValue){this.colsValue=r,this.rowsValue=i,this.terminal.resize(r,i);for(const o of this.resizeCallbacks)o({cols:r,rows:i})}return!0}focus(){(this.terminal.textarea||this.container.querySelector("textarea")||this.container)?.focus?.()}pasteText(e){const r=this.terminal.getMode?.(2004)??!1;this.input(r?"\x1B[200~"+e+"\x1B[201~":e)}input(e){this.terminal.input?.(e,!1)}onData(e){this.terminal.onData(r=>e(r))}onResize(e){this.resizeCallbacks.push(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){const e=document.activeElement;return!!e&&(e===this.container||e===this.terminal.textarea||this.container.contains(e))}getScreenText(){return this.getRowsText(0,this.rowsValue-1)}getRowsText(e,r){try{const i=this.terminal.buffer?.active;if(!i||typeof i.getLine!="function")return"";const[o,c]=e<=r?[e,r]:[r,e],h=typeof i.viewportY=="number"?i.viewportY:0,l=[];for(let f=o;f<=c;f++){const u=i.getLine(h+f);l.push(typeof u?.translateToString=="function"?u.translateToString(!0):"")}return l.join(`
4
- `)}catch{return""}}selectRows(e,r){try{if(typeof this.terminal?.selectLines!="function")return;const i=this.terminal.buffer?.active,o=typeof i?.viewportY=="number"?i.viewportY:0,[c,h]=e<=r?[e,r]:[r,e];this.terminal.selectLines(o+c,o+h)}catch{}}selectCells(e,r,i,o){try{const c=this.terminal.buffer?.active,h=typeof c?.viewportY=="number"?c.viewportY:0,l=Math.min(r,o),f=Math.max(r,o);if(l===f){if(typeof this.terminal?.select!="function"){this.selectRows(l,f);return}const u=Math.min(e,i),x=Math.max(e,i);this.terminal.select(u,h+l,x-u+1)}else this.selectRows(l,f)}catch{this.selectRows(r,o)}}getCellsText(e,r,i,o){try{const c=this.terminal.buffer?.active;if(!c||typeof c.getLine!="function")return this.getRowsText(r,o);const h=typeof c.viewportY=="number"?c.viewportY:0,l=Math.min(r,o),f=Math.max(r,o),u=r<o?e:r>o?i:Math.min(e,i),x=r<o?i:r>o?e:Math.max(e,i),v=[];for(let p=l;p<=f;p++){const d=c.getLine(h+p);if(!d){v.push("");continue}const T=p===l?u:0,S=p===f?x:this.colsValue-1;let M="";if(typeof d.getCell=="function")for(let L=T;L<=S;L++){const C=d.getCell(L);C&&(M+=typeof C.getChars=="function"?C.getChars():"")}else M=typeof d.translateToString=="function"?d.translateToString(!1):"";v.push(M.replace(/\s+$/,""))}return v.join(`
5
- `)}catch{return this.getRowsText(r,o)}}getSelection(){try{if(typeof this.terminal?.getSelection=="function")return this.terminal.getSelection()}catch{}return""}clearSelection(){try{typeof this.terminal?.clearSelection=="function"&&this.terminal.clearSelection()}catch{}}hasSelectionSupport(){return typeof this.terminal?.selectLines=="function"}updateCellMetrics(e=!1){const r=this.container.querySelector("canvas");if(r instanceof HTMLElement&&r.offsetWidth>0&&r.offsetHeight>0&&this.colsValue>0&&this.rowsValue>0){const i=r.offsetWidth/this.colsValue,o=r.offsetHeight/this.rowsValue;(e||!this.charW||!this.charH)&&(this.charW=i,this.charH=o)}(!this.charW||!this.charH)&&(this.charW=9,this.charH=18)}}function lt(a){const e=a.getBoundingClientRect(),r=window.visualViewport;return r?{width:Math.min(e.width,r.width),height:Math.max(0,Math.min(e.height,r.height-Math.max(0,e.top)))}:e}function Bt(a,e,r){return a.innerHTML="",a.classList.add("terminal-pending"),(async()=>{let i;if(r.renderer==="ghostty")try{i=await $.create(a,r.scrollback,r.theme)}catch{console.error("[tmux-web] ghostty-web failed; falling back to xterm.js"),i=await q.create(a,r.scrollback,r.theme)}else i=await q.create(a,r.scrollback,r.theme);let o,c=0,h,l=null,f=0,u="connecting",x=0,v=!1,p=[],d="",T=!1,S=1e3;const M=location.protocol==="https:"?"wss:":"ws:",L=r.wsBase||"/ws",C=M+"//"+location.host+L+"/"+encodeURIComponent(e),ct="/api/session/"+encodeURIComponent(e)+"/upload",ut=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function ft(){return p.join("")+d}async function ht(t,n=0){const s=t?i.viewportY():0,g=t?i.baseY():0,m=K(ft());if(i.reset(),!m){t||i.scrollToBottom();return}await i.write(m),t?i.scrollToLine(g+s+n):i.scrollToBottom()}function Y(t){o?.readyState===WebSocket.OPEN&&o.send(JSON.stringify(t))}function mt(t){let n;try{n=JSON.parse(t)}catch{u==="live"&&(d+=t,i.write(K(t)));return}if(n.type==="auth.required"){const s=localStorage.getItem("tmux-web-token");s?Y({type:"auth.token",token:s}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(n.type==="attach_failed"&&typeof n.message=="string"){V=!0,u="dead",i.reset(),i.write(`\r
4
+ `)}catch{return""}}selectRows(e,r){try{if(typeof this.terminal?.selectLines!="function")return;const i=this.terminal.buffer?.active,o=typeof i?.viewportY=="number"?i.viewportY:0,[c,h]=e<=r?[e,r]:[r,e];this.terminal.selectLines(o+c,o+h)}catch{}}selectCells(e,r,i,o){try{const c=this.terminal.buffer?.active,h=typeof c?.viewportY=="number"?c.viewportY:0,l=Math.min(r,o),f=Math.max(r,o);if(l===f){if(typeof this.terminal?.select!="function"){this.selectRows(l,f);return}const u=Math.min(e,i),T=Math.max(e,i);this.terminal.select(u,h+l,T-u+1)}else this.selectRows(l,f)}catch{this.selectRows(r,o)}}getCellsText(e,r,i,o){try{const c=this.terminal.buffer?.active;if(!c||typeof c.getLine!="function")return this.getRowsText(r,o);const h=typeof c.viewportY=="number"?c.viewportY:0,l=Math.min(r,o),f=Math.max(r,o),u=r<o?e:r>o?i:Math.min(e,i),T=r<o?i:r>o?e:Math.max(e,i),b=[];for(let p=l;p<=f;p++){const g=c.getLine(h+p);if(!g){b.push("");continue}const x=p===l?u:0,S=p===f?T:this.colsValue-1;let M="";if(typeof g.getCell=="function")for(let L=x;L<=S;L++){const C=g.getCell(L);C&&(M+=typeof C.getChars=="function"?C.getChars():"")}else M=typeof g.translateToString=="function"?g.translateToString(!1):"";b.push(M.replace(/\s+$/,""))}return b.join(`
5
+ `)}catch{return this.getRowsText(r,o)}}getSelection(){try{if(typeof this.terminal?.getSelection=="function")return this.terminal.getSelection()}catch{}return""}clearSelection(){try{typeof this.terminal?.clearSelection=="function"&&this.terminal.clearSelection()}catch{}}hasSelectionSupport(){return typeof this.terminal?.selectLines=="function"}updateCellMetrics(e=!1){const r=this.container.querySelector("canvas");if(r instanceof HTMLElement&&r.offsetWidth>0&&r.offsetHeight>0&&this.colsValue>0&&this.rowsValue>0){const i=r.offsetWidth/this.colsValue,o=r.offsetHeight/this.rowsValue;(e||!this.charW||!this.charH)&&(this.charW=i,this.charH=o)}(!this.charW||!this.charH)&&(this.charW=9,this.charH=18)}}function lt(a){const e=a.getBoundingClientRect(),r=window.visualViewport;return r?{width:Math.min(e.width,r.width),height:Math.max(0,Math.min(e.height,r.height-Math.max(0,e.top)))}:e}function Bt(a,e,r){return a.innerHTML="",a.classList.add("terminal-pending"),(async()=>{let i;if(r.renderer==="ghostty")try{i=await $.create(a,r.scrollback,r.theme)}catch{console.error("[tmux-web] ghostty-web failed; falling back to xterm.js"),i=await N.create(a,r.scrollback,r.theme)}else i=await N.create(a,r.scrollback,r.theme);let o,c=0,h,l=null,f=0,u="connecting",T=0,b=!1,p=[],g="",x=!1,S=1e3;const M=location.protocol==="https:"?"wss:":"ws:",L=r.wsBase||"/ws",C=M+"//"+location.host+L+"/"+encodeURIComponent(e),ct="/api/session/"+encodeURIComponent(e)+"/upload",ut=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function ft(){return p.join("")+g}async function ht(t,n=0){const s=t?i.viewportY():0,w=t?i.baseY():0,m=K(ft());if(i.reset(),!m){t||i.scrollToBottom();return}await i.write(m),t?i.scrollToLine(w+s+n):i.scrollToBottom()}function Y(t){o?.readyState===WebSocket.OPEN&&o.send(JSON.stringify(t))}function mt(t){let n;try{n=JSON.parse(t)}catch{u==="live"&&(g+=t,i.write(K(t)));return}if(n.type==="auth.required"){const s=localStorage.getItem("tmux-web-token");s?Y({type:"auth.token",token:s}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(n.type==="attach_failed"&&typeof n.message=="string"){A=!0,u="dead",i.reset(),i.write(`\r
6
6
  \x1B[31m`+K(n.message)+`\x1B[0m\r
7
- `).then(()=>{O();try{o?.close()}catch{}});return}if(n.type==="auth.ok"){n.token&&localStorage.setItem("tmux-web-token",n.token),S=1e3,k(),Y({type:"resize",cols:i.cols,rows:i.rows}),y();return}if(n.type==="auth.failed"){if(n.permanentLock||n.retryAfterMs&&n.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(n.message);return}return}if(n.type==="snapshot"&&typeof n.data=="string"){const s=K(n.data);p=[s],d="",x=typeof n.lines=="number"?n.lines:r.terminal.initialLines,u="live",i.reset(),i.write(s).then(()=>i.scrollToBottom());return}if(n.type==="window_changed"&&typeof n.activeIndex=="number"){const s=new URL(location.href);s.searchParams.get("window")!==String(n.activeIndex)&&(s.searchParams.set("window",String(n.activeIndex)),history.replaceState(history.state,"",s)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:n.windows}));return}if(n.type==="history"&&typeof n.data=="string"){v=!1,n.lines>0&&n.data&&(p.unshift(n.data),x+=n.lines,ht(!0,n.lines));return}if(n.type==="data"&&typeof n.data=="string"){const s=K(n.data);if(u==="connecting"){u="live",d=s,i.write(s);return}u==="live"&&(d+=s,i.write(s))}}let V=!1;function Q(){if(V)return;let t=C;const n=localStorage.getItem("tmux-web-token");n&&(t+=(t.includes("?")?"&":"?")+"token="+encodeURIComponent(n)),o=new WebSocket(t),o.onopen=()=>{u="connecting",x=0,v=!1,p=[],d="",i.reset(),S=1e3},o.onmessage=s=>{typeof s.data=="string"&&mt(s.data)},o.onclose=()=>{T||(u="connecting",!V&&setTimeout(()=>{S=Math.min(S*2,1e4),!T&&!V&&Q()},S))},o.onerror=()=>o?.close()}function W(t){Y({type:"input",data:t})}function k(){return i.fit()}function O(){a.classList.remove("terminal-pending")}function y(){c&&cancelAnimationFrame(c),h&&clearTimeout(h),k(),c=requestAnimationFrame(()=>{c=0,k()&&O()}),h=setTimeout(()=>{k()&&O()},120)}function pt(){y(),setTimeout(y,50),setTimeout(y,150),setTimeout(y,300)}function Z(t){return typeof t=="string"&&t.startsWith("image/")}function R(t){return t?.files?.length?t.files[0]??null:null}function dt(t){if(!t?.items)return null;for(let n=0;n<t.items.length;n++){const s=t.items[n];if(s?.kind==="file"&&Z(s.type))return s.getAsFile()}return null}async function gt(t){const n=new FormData,s=t instanceof File&&t.name?t.name:"upload";n.append("file",t,s);const g=localStorage.getItem("tmux-web-token"),m={};g&&(m.Authorization="Bearer "+g);const I=await fetch(ct,{method:"POST",body:n,headers:m});if(!I.ok){let st="upload failed";try{const at=await I.json();at.error&&(st=at.error)}catch{}throw new Error(st)}const U=await I.json();if(!U.path)throw new Error("no path in response");return U.path}async function N(t){try{const n=await gt(t);W(n)}catch{}}i.onData(t=>W(t)),i.onResize(({cols:t,rows:n})=>Y({type:"resize",cols:t,rows:n})),i.onScroll(()=>{u!=="live"||v||!i.isNearScrollbackTop()||(v=!0,Y({type:"load_history",before:x}))});let P=!1,F=!1,w=null,b=null;const B=document.createElement("div");B.className="terminal-copy-banner",B.innerHTML='<strong>Copy mode</strong><span class="hint">drag to select \xB7 Alt+C copies \xB7 Esc exits</span>',B.hidden=!0,a.appendChild(B);const E=document.createElement("div");E.className="terminal-copy-banner terminal-copy-toast",E.textContent="Copied",E.hidden=!0,a.appendChild(E);function tt(t,n){const s=a.querySelector(".xterm-screen, canvas"),m=(s&&s.getBoundingClientRect().width>0?s:a).getBoundingClientRect(),I=m.height>0&&i.rows>0?m.height/i.rows:18,U=m.width>0&&i.cols>0?m.width/i.cols:9;return{row:Math.max(0,Math.min(i.rows-1,Math.floor((n-m.top)/I))),col:Math.max(0,Math.min(i.cols-1,Math.floor((t-m.left)/U)))}}async function _(t){if(!t)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(t);return}}catch{}const n=document.createElement("textarea");n.value=t,n.style.position="fixed",n.style.opacity="0",n.style.pointerEvents="none",document.body.appendChild(n),n.focus(),n.select();try{document.execCommand("copy")}catch{}n.remove()}let z;function X(){E.hidden=!1,z&&clearTimeout(z),z=setTimeout(()=>{E.hidden=!0},1e3)}function D(t){P=t,B.hidden=!t,a.classList.toggle("terminal-copy-mode-active",t),t&&i.focus()}function et(){D(!P)}function yt(t){T||t.button!==0||F||(P||t.shiftKey)&&(t.preventDefault(),t.stopPropagation(),F=!0,w=tt(t.clientX,t.clientY),b=w,i.selectCells(w.col,w.row,b.col,b.row),document.addEventListener("mousemove",J,!0),document.addEventListener("mouseup",G,!0))}function J(t){T||!F||!w||(t.preventDefault(),t.stopPropagation(),b=tt(t.clientX,t.clientY),i.selectCells(w.col,w.row,b.col,b.row))}function G(t){T||!F||!w||!b||(t.preventDefault(),t.stopPropagation(),document.removeEventListener("mousemove",J,!0),document.removeEventListener("mouseup",G,!0),F=!1,D(!1),E.textContent="\u5DF2\u9009\u4E2D \xB7 Alt+C \u590D\u5236",X(),i.focus())}a.addEventListener("mousedown",yt,!0),document.addEventListener("keydown",wt,!0);function wt(t){if(!(T||!i.isFocused()||t.defaultPrevented||t.isComposing)){if(P){if(t.key==="Escape"){t.preventDefault(),t.stopPropagation(),w=null,b=null,i.clearSelection(),D(!1);return}if(t.key==="Enter"||(t.ctrlKey||t.metaKey)&&t.code==="KeyC"){t.preventDefault(),t.stopPropagation(),_(i.getScreenText()).then(X),D(!1);return}}if(t.altKey&&t.code==="KeyC"&&!t.ctrlKey&&!t.metaKey){if(t.preventDefault(),t.stopPropagation(),w&&b){const n=i.getCellsText(w.col,w.row,b.col,b.row);w=null,b=null,i.clearSelection(),D(!1),n&&(E.textContent="Copied",_(n).then(X))}else{const n=i.getSelection();n?(i.clearSelection(),E.textContent="Copied",_(n).then(X)):et()}return}if((t.ctrlKey||t.metaKey)&&t.code==="KeyV"){t.preventDefault(),t.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){const n=await navigator.clipboard.read();for(const s of n)for(const g of s.types)if(Z(g)){const m=await s.getType(g);await N(m);return}}}catch{}try{const n=await navigator.clipboard?.readText();n&&i.pasteText(nt(n))}catch{}})();return}}}let j=0;function nt(t){return t.split(`\r
7
+ `).then(()=>{O();try{o?.close()}catch{}});return}if(n.type==="auth.ok"){n.token&&localStorage.setItem("tmux-web-token",n.token),S=1e3,k(),Y({type:"resize",cols:i.cols,rows:i.rows}),v();return}if(n.type==="auth.failed"){if(n.permanentLock||n.retryAfterMs&&n.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(n.message);return}return}if(n.type==="snapshot"&&typeof n.data=="string"){const s=K(n.data);p=[s],g="",T=typeof n.lines=="number"?n.lines:r.terminal.initialLines,u="live",i.reset(),i.write(s).then(()=>i.scrollToBottom());return}if(n.type==="window_changed"&&typeof n.activeIndex=="number"){const s=new URL(location.href);s.searchParams.get("window")!==String(n.activeIndex)&&(s.searchParams.set("window",String(n.activeIndex)),history.replaceState(history.state,"",s)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:n.windows}));return}if(n.type==="history"&&typeof n.data=="string"){b=!1,n.lines>0&&n.data&&(p.unshift(n.data),T+=n.lines,ht(!0,n.lines));return}if(n.type==="data"&&typeof n.data=="string"){const s=K(n.data);if(u==="connecting"){u="live",g=s,i.write(s);return}u==="live"&&(g+=s,i.write(s))}}let A=!1;function Q(){if(A)return;let t=C;const n=localStorage.getItem("tmux-web-token");n&&(t+=(t.includes("?")?"&":"?")+"token="+encodeURIComponent(n)),o=new WebSocket(t),o.onopen=()=>{u="connecting",T=0,b=!1,p=[],g="",i.reset(),S=1e3},o.onmessage=s=>{typeof s.data=="string"&&mt(s.data)},o.onclose=()=>{x||(u="connecting",!A&&setTimeout(()=>{S=Math.min(S*2,1e4),!x&&!A&&Q()},S))},o.onerror=()=>o?.close()}function W(t){Y({type:"input",data:t})}function k(){return i.fit()}function O(){a.classList.remove("terminal-pending")}function v(){c&&cancelAnimationFrame(c),h&&clearTimeout(h),k(),c=requestAnimationFrame(()=>{c=0,k()&&O()}),h=setTimeout(()=>{k()&&O()},120)}function pt(){v(),setTimeout(v,50),setTimeout(v,150),setTimeout(v,300)}function Z(t){return typeof t=="string"&&t.startsWith("image/")}function R(t){return t?.files?.length?t.files[0]??null:null}function dt(t){if(!t?.items)return null;for(let n=0;n<t.items.length;n++){const s=t.items[n];if(s?.kind==="file"&&Z(s.type))return s.getAsFile()}return null}async function gt(t){const n=new FormData,s=t instanceof File&&t.name?t.name:"upload";n.append("file",t,s);const w=localStorage.getItem("tmux-web-token"),m={};w&&(m.Authorization="Bearer "+w);const I=await fetch(ct,{method:"POST",body:n,headers:m});if(!I.ok){let st="upload failed";try{const at=await I.json();at.error&&(st=at.error)}catch{}throw new Error(st)}const q=await I.json();if(!q.path)throw new Error("no path in response");return q.path}async function _(t){try{const n=await gt(t);W(n)}catch{}}i.onData(t=>W(t)),i.onResize(({cols:t,rows:n})=>Y({type:"resize",cols:t,rows:n})),i.onScroll(()=>{u!=="live"||b||!i.isNearScrollbackTop()||(b=!0,Y({type:"load_history",before:T}))});let P=!1,F=!1,d=null,y=null;const B=document.createElement("div");B.className="terminal-copy-banner",B.innerHTML='<strong>Copy mode</strong><span class="hint">drag to copy \xB7 Esc exits</span>',B.hidden=!0,a.appendChild(B);const E=document.createElement("div");E.className="terminal-copy-banner terminal-copy-toast",E.textContent="Copied",E.hidden=!0,a.appendChild(E);function tt(t,n){const s=a.querySelector(".xterm-screen, canvas"),m=(s&&s.getBoundingClientRect().width>0?s:a).getBoundingClientRect(),I=m.height>0&&i.rows>0?m.height/i.rows:18,q=m.width>0&&i.cols>0?m.width/i.cols:9;return{row:Math.max(0,Math.min(i.rows-1,Math.floor((n-m.top)/I))),col:Math.max(0,Math.min(i.cols-1,Math.floor((t-m.left)/q)))}}async function X(t){if(!t)return;try{if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(t);return}}catch{}const n=document.createElement("textarea");n.value=t,n.style.position="fixed",n.style.opacity="0",n.style.pointerEvents="none",document.body.appendChild(n),n.focus(),n.select();try{document.execCommand("copy")}catch{}n.remove()}let z;function j(){E.hidden=!1,z&&clearTimeout(z),z=setTimeout(()=>{E.hidden=!0},1e3)}function D(t){P=t,B.hidden=!t,a.classList.toggle("terminal-copy-mode-active",t),t&&i.focus()}function et(){D(!P)}function yt(t){x||t.button!==0||F||(P||t.shiftKey)&&(t.preventDefault(),t.stopPropagation(),F=!0,d=tt(t.clientX,t.clientY),y=d,i.selectCells(d.col,d.row,y.col,y.row),document.addEventListener("mousemove",J,!0),document.addEventListener("mouseup",G,!0))}function J(t){x||!F||!d||(t.preventDefault(),t.stopPropagation(),y=tt(t.clientX,t.clientY),i.selectCells(d.col,d.row,y.col,y.row))}function G(t){if(x||!F||!d||!y)return;t.preventDefault(),t.stopPropagation(),document.removeEventListener("mousemove",J,!0),document.removeEventListener("mouseup",G,!0),F=!1;const n=i.getCellsText(d.col,d.row,y.col,y.row);d=null,y=null,i.clearSelection(),D(!1),n&&(E.textContent="\u5DF2\u590D\u5236",X(n).then(j)),i.focus()}a.addEventListener("mousedown",yt,!0),document.addEventListener("keydown",wt,!0);function wt(t){if(!(x||!i.isFocused()||t.defaultPrevented||t.isComposing)){if(P){if(t.key==="Escape"){t.preventDefault(),t.stopPropagation(),d=null,y=null,i.clearSelection(),D(!1);return}if(t.key==="Enter"||(t.ctrlKey||t.metaKey)&&t.code==="KeyC"){t.preventDefault(),t.stopPropagation(),X(i.getScreenText()).then(j),D(!1);return}}if(t.altKey&&t.code==="KeyC"&&!t.ctrlKey&&!t.metaKey){if(t.preventDefault(),t.stopPropagation(),d&&y){const n=i.getCellsText(d.col,d.row,y.col,y.row);d=null,y=null,i.clearSelection(),D(!1),n&&(E.textContent="Copied",X(n).then(j))}else{const n=i.getSelection();n?(i.clearSelection(),E.textContent="Copied",X(n).then(j)):et()}return}if((t.ctrlKey||t.metaKey)&&t.code==="KeyV"){t.preventDefault(),t.stopPropagation(),(async()=>{try{if(navigator.clipboard?.read){const n=await navigator.clipboard.read();for(const s of n)for(const w of s.types)if(Z(w)){const m=await s.getType(w);await _(m);return}}}catch{}try{const n=await navigator.clipboard?.readText();n&&i.pasteText(nt(n))}catch{}})();return}}}let U=0;function nt(t){return t.split(`\r
8
8
  `).join(`
9
9
  `).split(`
10
- `).join("\r")}async function vt(t){const n=dt(t.clipboardData);if(n){t.preventDefault(),t.stopPropagation();const m=Date.now();if(m-j<50)return;j=m,await N(n);return}const s=t.clipboardData?.getData("text/plain");if(!s)return;t.preventDefault(),t.stopPropagation();const g=Date.now();g-j<50||(j=g,i.pasteText(nt(s)))}let H=0;function bt(t){t.preventDefault(),H++,R(t.dataTransfer)&&a.classList.add("terminal-drag-over")}function Tt(t){t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy")}function xt(t){t.preventDefault(),H--,H<=0&&(H=0,a.classList.remove("terminal-drag-over"))}async function St(t){t.preventDefault(),H=0,a.classList.remove("terminal-drag-over");const n=R(t.dataTransfer);n&&await N(n)}function it(t){!ut||t.key!=="Escape"||P||t.defaultPrevented||t.repeat||t.metaKey||t.ctrlKey||t.altKey||i.isFocused()&&(t.preventDefault(),t.stopPropagation(),W("\x1B"))}a.addEventListener("paste",vt),a.addEventListener("dragenter",bt),a.addEventListener("dragover",Tt),a.addEventListener("dragleave",xt),a.addEventListener("drop",St),document.addEventListener("keydown",it,!0);function Lt(t){if(t.touches.length!==1){l=null;return}const n=t.touches[0];n&&(l={startX:n.clientX,startY:n.clientY,lastX:n.clientX,lastY:n.clientY,scrolling:!1},t.stopPropagation())}function Et(t){if(!l||t.touches.length!==1)return;const n=t.touches[0];if(!n)return;const s=n.clientY-l.startY,g=n.clientX-l.startX;if(!l.scrolling){if(Math.abs(s)<8||Math.abs(s)<Math.abs(g))return;l.scrolling=!0,f=Date.now()+500}t.preventDefault(),t.stopPropagation(),Yt(-(n.clientY-l.lastY),n.clientX,n.clientY),l.lastX=n.clientX,l.lastY=n.clientY}function Mt(t){if(!l)return;const n=l.scrolling;l=null,t.stopPropagation(),n?(f=Date.now()+500,t.preventDefault()):i.focus()}function Ct(t){l=null,t.stopPropagation()}function Dt(t){t.pointerType==="touch"&&Date.now()<f&&(t.preventDefault(),t.stopPropagation())}function Yt(t,n,s){(a.querySelector(".xterm-screen")??a).dispatchEvent(new WheelEvent("wheel",{deltaY:t,deltaMode:WheelEvent.DOM_DELTA_PIXEL,clientX:n,clientY:s,bubbles:!0,cancelable:!0}))}a.addEventListener("touchstart",Lt,{passive:!0,capture:!0}),a.addEventListener("touchmove",Et,{passive:!1,capture:!0}),a.addEventListener("touchend",Mt,{passive:!1,capture:!0}),a.addEventListener("touchcancel",Ct,{passive:!0,capture:!0}),a.addEventListener("pointerup",Dt,!0);function rt(){y()}window.addEventListener("resize",rt),window.visualViewport?.addEventListener("resize",y),window.visualViewport?.addEventListener("scroll",y);const ot=new ResizeObserver(()=>y());return ot.observe(a),document.fonts?.ready.then(()=>{y(),setTimeout(y,50),setTimeout(y,200)}),a.addEventListener("focusin",pt,!0),requestAnimationFrame(()=>{k()&&O(),Q(),y()}),{destroy(){if(T=!0,D(!1),z&&clearTimeout(z),document.removeEventListener("mousemove",J,!0),document.removeEventListener("mouseup",G,!0),o){try{o.close(1e3,"session switch")}catch{}o=void 0}a.innerHTML="",a.classList.remove("terminal-pending"),window.removeEventListener("resize",rt),ot.disconnect(),document.removeEventListener("keydown",it,!0)},focus(){i.focus()},sendInput(t){W(t)},toggleCopyMode(){et()}}})()}export{Bt as initTerminal};
10
+ `).join("\r")}async function vt(t){const n=dt(t.clipboardData);if(n){t.preventDefault(),t.stopPropagation();const m=Date.now();if(m-U<50)return;U=m,await _(n);return}const s=t.clipboardData?.getData("text/plain");if(!s)return;t.preventDefault(),t.stopPropagation();const w=Date.now();w-U<50||(U=w,i.pasteText(nt(s)))}let H=0;function bt(t){t.preventDefault(),H++,R(t.dataTransfer)&&a.classList.add("terminal-drag-over")}function xt(t){t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy")}function Tt(t){t.preventDefault(),H--,H<=0&&(H=0,a.classList.remove("terminal-drag-over"))}async function St(t){t.preventDefault(),H=0,a.classList.remove("terminal-drag-over");const n=R(t.dataTransfer);n&&await _(n)}function it(t){!ut||t.key!=="Escape"||P||t.defaultPrevented||t.repeat||t.metaKey||t.ctrlKey||t.altKey||i.isFocused()&&(t.preventDefault(),t.stopPropagation(),W("\x1B"))}a.addEventListener("paste",vt),a.addEventListener("dragenter",bt),a.addEventListener("dragover",xt),a.addEventListener("dragleave",Tt),a.addEventListener("drop",St),document.addEventListener("keydown",it,!0);function Lt(t){if(t.touches.length!==1){l=null;return}const n=t.touches[0];n&&(l={startX:n.clientX,startY:n.clientY,lastX:n.clientX,lastY:n.clientY,scrolling:!1},t.stopPropagation())}function Et(t){if(!l||t.touches.length!==1)return;const n=t.touches[0];if(!n)return;const s=n.clientY-l.startY,w=n.clientX-l.startX;if(!l.scrolling){if(Math.abs(s)<8||Math.abs(s)<Math.abs(w))return;l.scrolling=!0,f=Date.now()+500}t.preventDefault(),t.stopPropagation(),Yt(-(n.clientY-l.lastY),n.clientX,n.clientY),l.lastX=n.clientX,l.lastY=n.clientY}function Mt(t){if(!l)return;const n=l.scrolling;l=null,t.stopPropagation(),n?(f=Date.now()+500,t.preventDefault()):i.focus()}function Ct(t){l=null,t.stopPropagation()}function Dt(t){t.pointerType==="touch"&&Date.now()<f&&(t.preventDefault(),t.stopPropagation())}function Yt(t,n,s){(a.querySelector(".xterm-screen")??a).dispatchEvent(new WheelEvent("wheel",{deltaY:t,deltaMode:WheelEvent.DOM_DELTA_PIXEL,clientX:n,clientY:s,bubbles:!0,cancelable:!0}))}a.addEventListener("touchstart",Lt,{passive:!0,capture:!0}),a.addEventListener("touchmove",Et,{passive:!1,capture:!0}),a.addEventListener("touchend",Mt,{passive:!1,capture:!0}),a.addEventListener("touchcancel",Ct,{passive:!0,capture:!0}),a.addEventListener("pointerup",Dt,!0);function rt(){v()}window.addEventListener("resize",rt),window.visualViewport?.addEventListener("resize",v),window.visualViewport?.addEventListener("scroll",v);const ot=new ResizeObserver(()=>v());return ot.observe(a),document.fonts?.ready.then(()=>{v(),setTimeout(v,50),setTimeout(v,200)}),a.addEventListener("focusin",pt,!0),requestAnimationFrame(()=>{k()&&O(),Q(),v()}),{destroy(){if(x=!0,D(!1),z&&clearTimeout(z),document.removeEventListener("mousemove",J,!0),document.removeEventListener("mouseup",G,!0),o){try{o.close(1e3,"session switch")}catch{}o=void 0}a.innerHTML="",a.classList.remove("terminal-pending"),window.removeEventListener("resize",rt),ot.disconnect(),document.removeEventListener("keydown",it,!0)},focus(){i.focus()},sendInput(t){W(t)},toggleCopyMode(){et()}}})()}export{Bt as initTerminal};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmux-weblink",
3
- "version": "2.0.9",
3
+ "version": "2.0.10",
4
4
  "description": "Access your tmux sessions from the browser. A continuation of tmux-web and persalink.",
5
5
  "type": "module",
6
6
  "bin": {