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