shellbell 0.0.0-stage → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ import{$ as e,$t as t,A as n,An as r,At as i,B as a,Bn as o,Bt as s,Cn as c,Ct as l,Dn as u,Dt as d,E as f,En as p,Et as m,F as h,Fn as g,Ft as _,G as v,Gt as y,Hn as b,Ht as x,It as S,J as C,Jt as w,K as ee,Kt as te,Ln as ne,Lt as re,M as ie,Mn as ae,Mt as oe,N as se,Nn as ce,Nt as le,On as T,Ot as ue,Pn as de,Pt as fe,Q as E,Qt as pe,R as me,Rn as he,Rt as ge,Sn as _e,St as D,Tn as ve,Tt as O,U as ye,Ut as be,V as xe,Vn as Se,Vt as Ce,W as we,Wt as Te,X as k,Xt as Ee,Y as De,Yt as Oe,Z as ke,Zt as Ae,_n as je,_t as Me,a as Ne,an as Pe,at as Fe,bn as Ie,bt as Le,cn as Re,ct as ze,d as Be,dn as Ve,dt as He,en as Ue,et as We,fn as Ge,ft as Ke,gn as qe,gt as Je,hn as Ye,ht as Xe,in as Ze,it as Qe,j as $e,jn as A,jt as et,k as tt,kn as nt,kt as rt,l as it,ln as at,lt as ot,mn as st,mt as ct,n as lt,nn as ut,o as dt,on as ft,ot as pt,pn as mt,pt as ht,q as j,qt as gt,r as _t,rn as vt,rt as yt,s as bt,sn as xt,st as St,t as Ct,tn as wt,tt as M,u as Tt,un as Et,ut as Dt,vn as Ot,vt as kt,wn as At,wt as jt,xn as Mt,xt as Nt,yn as Pt,yt as Ft,z as It,zn as Lt,zt as Rt}from"./service-lifecycle-CcyJ7m6L.js";import{execFile as zt,spawn as Bt}from"node:child_process";import{accessSync as Vt,closeSync as Ht,constants as N,existsSync as Ut,fstatSync as Wt,fsyncSync as Gt,linkSync as Kt,lstatSync as qt,mkdirSync as Jt,openSync as Yt,opendirSync as Xt,readFileSync as Zt,readSync as Qt,readdirSync as $t,readlinkSync as en,realpathSync as tn,renameSync as nn,statSync as rn,statfsSync as an,symlinkSync as on,unlinkSync as sn,writeFileSync as cn}from"node:fs";import{homedir as P,hostname as ln}from"node:os";import{basename as un,delimiter as dn,dirname as F,isAbsolute as I,join as L,relative as fn,resolve as pn,sep as mn}from"node:path";import{createInterface as hn}from"node:readline";import{fileURLToPath as gn,pathToFileURL as _n}from"node:url";import{z as R}from"zod";import{Command as vn}from"commander";import yn from"qrcode-terminal";import{createHash as bn,randomUUID as xn,timingSafeEqual as Sn}from"node:crypto";import{EventEmitter as Cn}from"node:events";import{connect as wn,createConnection as Tn,isIP as En}from"node:net";import Dn from"ws";import{StringDecoder as On}from"node:string_decoder";import{isDeepStrictEqual as kn,promisify as An}from"node:util";import{create as z,fromBinary as jn,toBinary as Mn}from"@bufbuild/protobuf";import{fileDesc as Nn,messageDesc as B}from"@bufbuild/protobuf/codegenv2";import{importTerminalPlugin as Pn}from"#terminal-plugin-loader";import{performance as Fn}from"node:perf_hooks";const In=e=>/^turns?:/.test(e),Ln=e=>!/:53(\?|$)/.test(e);function Rn(e=[]){let t=[{urls:[`stun:stun.cloudflare.com:3478`]}],n=3;for(let r of e){if(!r.username||!r.credential)continue;let e=r.urls.filter(e=>In(e)&&Ln(e)).slice(0,n);if(e.length!==0&&(n-=e.length,t.push({urls:e,username:r.username,credential:r.credential}),n===0))break}return t}var zn=class{relay=[];expiresAt=0;advertised=!1;lastRefresh=-1/0;get supported(){return this.advertised}update(e,t,n){this.relay=e.map(e=>({...e,urls:[...e.urls]})),this.expiresAt=n+t,this.advertised=!0}servers(e){return Rn(e<this.expiresAt?this.relay:[])}needsRefresh(e){return this.advertised&&this.expiresAt-e<=288e5}takeRefresh(e){return!this.advertised||e-this.lastRefresh<6e5?!1:(this.lastRefresh=e,!0)}};const Bn=[[768,879],[1155,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1552,1562],[1611,1631],[1648,1648],[1750,1756],[1759,1764],[1767,1768],[1770,1773],[1809,1809],[1840,1866],[1958,1968],[2070,2093],[2304,2306],[2362,2362],[2364,2364],[2369,2376],[2381,2381],[2385,2391],[2402,2403],[3633,3633],[3636,3642],[3655,3662],[6832,6911],[7616,7679],[8203,8207],[8232,8238],[8288,8292],[8400,8432],[65024,65039],[65056,65071],[65279,65279],[127995,127999],[917760,917999]],Vn=[[4352,4447],[8986,8987],[9001,9002],[9193,9196],[9200,9200],[9203,9203],[9725,9726],[9748,9749],[9800,9811],[9855,9855],[9875,9875],[9889,9889],[9898,9899],[9917,9918],[9924,9925],[9934,9934],[9940,9940],[9962,9962],[9970,9971],[9973,9973],[9978,9978],[9981,9981],[9989,9989],[9994,9995],[10024,10024],[10060,10060],[10062,10062],[10067,10069],[10071,10071],[10133,10135],[10160,10160],[10175,10175],[11035,11036],[11088,11088],[11093,11093],[11904,12350],[12353,13311],[13312,19903],[19968,40959],[40960,42191],[43360,43391],[44032,55203],[63744,64255],[65040,65049],[65072,65135],[65280,65376],[65504,65510],[94176,94180],[94208,101119],[110592,111359],[126980,126980],[127183,127183],[127374,127374],[127377,127386],[127488,127569],[127744,127776],[127789,127797],[127799,127868],[127870,127891],[127904,127946],[127951,127955],[127968,127984],[127988,127988],[127992,128062],[128064,128064],[128066,128252],[128255,128317],[128331,128334],[128336,128359],[128378,128378],[128405,128406],[128420,128420],[128507,128591],[128640,128709],[128716,128716],[128720,128722],[128725,128727],[128747,128748],[128756,128764],[128992,129003],[129292,129338],[129340,129349],[129351,129535],[129648,129791],[131072,196605],[196608,262141]];function Hn(e,t){let n=0,r=t.length-1;for(;n<=r;){let i=n+r>>1,a=t[i];if(e<a[0])r=i-1;else if(e>a[1])n=i+1;else return!0}return!1}function Un(e){return e===0||e<32||e>=127&&e<160||Hn(e,Bn)?0:Hn(e,Vn)?2:1}function Wn(e){let t=0,n=!1,r=0;for(let i of e){let e=i.codePointAt(0);if(e===8205){n=!0;continue}let a=Un(e);if(a!==0||n){if(n){r=Math.max(r,a),n=!1;continue}t+=r,r=a}}return t+r}function Gn(e,t){let n={t:e},r=t.fg,i=t.bg;if(t.inv){let e=r??15;r=i??0,i=e}r!==void 0&&(n.fg=r),i!==void 0&&(n.bg=i),t.b&&(n.b=!0),t.i&&(n.i=!0),t.u&&(n.u=!0),t.s&&(n.s=!0),t.f&&(n.f=!0);let a=Wn(e);return a!==re(e)&&(n.n=a),n}function Kn(e){return Math.max(0,Math.min(255,e|0))}function qn(e,t){let n=e[t];if(n.length>1){let e=n[1],t=n.slice(2);if(e===5&&t.length>=1)return{color:Kn(t[0]),consumed:0};if(e===2){let e=t.length>=4?t.slice(1,4):t.slice(0,3);if(e.length===3)return{color:[Kn(e[0]),Kn(e[1]),Kn(e[2])],consumed:0}}return{consumed:0}}let r=e[t+1]?.[0];return r===5&&e[t+2]?{color:Kn(e[t+2]?.[0]??0),consumed:2}:r===2&&e[t+4]?{color:[Kn(e[t+2]?.[0]??0),Kn(e[t+3]?.[0]??0),Kn(e[t+4]?.[0]??0)],consumed:4}:{consumed:0}}function Jn(e,t){let n={...e},r=(t===``?[`0`]:t.split(`;`)).map(e=>e.split(`:`).map(e=>e===``?0:Number(e)));for(let e=0;e<r.length;e++){let t=r[e]?.[0]??0;if(t===0)for(let e of Object.keys(n))delete n[e];else if(t===1)n.b=!0;else if(t===2)n.f=!0;else if(t===3)n.i=!0;else if(t===4)n.u=!0;else if(t===7)n.inv=!0;else if(t===9)n.s=!0;else if(t===22)delete n.b,delete n.f;else if(t===23)delete n.i;else if(t===24)delete n.u;else if(t===27)delete n.inv;else if(t===29)delete n.s;else if(t>=30&&t<=37)n.fg=t-30;else if(t===39)delete n.fg;else if(t>=40&&t<=47)n.bg=t-40;else if(t===49)delete n.bg;else if(t>=90&&t<=97)n.fg=t-90+8;else if(t>=100&&t<=107)n.bg=t-100+8;else if(t===38||t===48){let{color:i,consumed:a}=qn(r,e);i!==void 0&&(t===38?n.fg=i:n.bg=i),e+=a}}return n}function Yn(e){let t=[],n={},r=``,i=0,a=()=>{r&&t.push(Gn(r,n)),r=``},o=0;for(;o<e.length;){let t=e[o];if(t===`\x1B`){let i=e[o+1];if(i===`[`){let i=o+2,s=``;for(;i<e.length&&i-(o+2)<32;){let t=e.charCodeAt(i);if(t>=64&&t<=126)break;s+=e[i],i++}if(i>=e.length||i-(o+2)>=32){r+=t,o++;continue}e[i]===`m`&&(a(),n=Jn(n,s)),o=i+1;continue}if(i===`]`){let t=o+2;for(;t<e.length&&e[t]!==`\x07`&&(e[t]!==`\x1B`||e[t+1]!==`\\`);)t++;o=e[t]===`\x07`?t+1:t+2;continue}o+=i===void 0?1:2,(i===`(`||i===`)`)&&(o+=1);continue}let s=e.charCodeAt(o);if(t===` `){let e=8-i%8;r+=` `.repeat(e),i+=e,o++;continue}if(s<32||s===127){o++;continue}let c=e.codePointAt(o);r+=String.fromCodePoint(c),i+=Un(c),o+=c>65535?2:1}return a(),{r:x(s(t))}}function Xn(e){return e.issue!==void 0&&[`needs-consent`,`automation-denied`,`iterm2-denied`,`timed-out`,`too-old`,`failed`,`limited`].includes(e.issue)}const Zn={iterm2:`iTerm2`,tmux:`tmux`,herdr:`Herdr`};function Qn(e,t){let n=Zn[e.name]??e.name;if(e.connected&&!e.issue)return{status:`Connected. Ready for your paired phone.`};if(t===`phone`)return Xn(e)?{status:`${n} needs one more step on your Mac.`,fix:`Open Shellbell → Settings → Terminals on that Mac, or run shellbell doctor there.`}:{status:`${n} isn't connected right now.`};let r=t===`mac-app`?`Click Connect iTerm2.`:`Run shellbell connect iterm2.`;switch(e.issue){case`not-installed`:return{status:`Shellbell couldn't find ${n}. Optional.`,...e.name===`tmux`?{fix:`Install tmux 3.2 or newer, for example: brew install tmux`}:{}};case`not-running`:return e.name===`iterm2`?{status:`iTerm2 isn't open. Open it to see its tabs on your phone.`}:{status:`${n} isn't running.`,fix:`In any terminal, run: ${e.name}`};case`no-session`:return{status:`No tmux session is running.`,fix:`In any terminal, run: tmux`};case`api-off`:return{status:`Turn on iTerm2's Python API to connect.`,fix:`In iTerm2, open Settings → General → Magic and turn on Enable Python API.`};case`needs-consent`:return{status:`Ready to connect.`,fix:`${r} macOS will ask to let Shellbell control iTerm2, and iTerm2 may ask to allow Shellbell. Allow both. Your paired phone can then read and type in your iTerm2 tabs.`};case`connecting`:return{status:`Finish connecting in the macOS or iTerm2 dialog.`};case`automation-denied`:return{status:`macOS is blocking Shellbell from iTerm2.`,fix:`Open System Settings → Privacy & Security → Automation, find Shellbell (or node, for the background service) and turn on iTerm2.`};case`iterm2-denied`:return{status:`iTerm2 is blocking Shellbell.`,fix:`In iTerm2, open Settings → General → Magic and check who may use the Python API. Then ${r.charAt(0).toLowerCase()}${r.slice(1)}`};case`timed-out`:return{status:`Connecting wasn't finished.`,fix:`Check for an open macOS or iTerm2 dialog, then try again. ${r}`};case`too-old`:return e.name===`iterm2`?{status:`Update iTerm2 to connect.`,fix:`Shellbell needs iTerm2 3.3 or newer.`}:e.name===`tmux`?{status:`Shellbell needs tmux 3.2 or newer.`,fix:`Update tmux, for example: brew upgrade tmux`}:{status:`Update ${n} to connect.`};case`limited`:return{status:`Viewing and typing work. Opening new sessions from your phone doesn't.`,...e.detail?{fix:e.detail}:{}};default:return{status:`Shellbell couldn't connect to ${n}.`,fix:e.name===`iterm2`?`Try again. ${r}`:`Shellbell keeps trying.`}}}var $n=class extends Cn{opts;s=new Map;now;constructor(e){super(),this.opts=e,this.now=e.now??(()=>Date.now())}stateOf(e){return this.s.get(e)?.promptState??`unknown`}forget(e){this.s.delete(e)}get(e){let t=this.s.get(e);return t||(t={blockedNotified:!1,promptState:`unknown`,commandStartedAt:null,command:``,lastChangeAt:0,activeSince:null,lastPromptRingAt:-1/0,agentState:null,workingSince:null},this.s.set(e,t)),t}onBackendEvent(e){let t=this.now();switch(e.type){case`screen-changed`:{let n=this.get(e.sessionId);n.lastChangeAt=t,n.activeSince??=t;return}case`command-start`:{let n=this.get(e.sessionId);n.promptState=`running`,n.commandStartedAt=t,n.command=e.command;return}case`command-end`:{let n=this.get(e.sessionId);n.promptState=`finished`;let r=n.commandStartedAt===null?void 0:t-n.commandStartedAt;n.commandStartedAt=null,this.emit(`event`,{type:`event`,sessionId:e.sessionId,kind:`prompt`,exitCode:e.exitCode,durationMs:r,command:n.command||void 0,at:t}),r!==void 0&&r>=this.opts.notifyMinCommandMs&&(n.lastPromptRingAt=t,n.activeSince=null,this.emit(`ring`,{reason:`command-finished`,sessionId:e.sessionId,kind:`prompt`,exitCode:e.exitCode,durationMs:r}));return}case`prompt`:{let n=this.get(e.sessionId),r=n.commandStartedAt===null?void 0:t-n.commandStartedAt;n.commandStartedAt=null,n.promptState=`editing`,r!==void 0&&r>=this.opts.notifyMinCommandMs&&(n.activeSince=null,n.lastPromptRingAt=t,this.emit(`ring`,{sessionId:e.sessionId,kind:`prompt`,reason:`prompt-returned`,durationMs:r}));return}case`agent-state`:{let n=this.get(e.sessionId),r=n.agentState;if(r===e.state)return;if(n.agentState=e.state,e.state===`working`){n.blockedNotified=!1,n.promptState=`running`,n.workingSince=t;return}if(e.state===`blocked`){n.promptState=`blocked`,n.workingSince=null,n.activeSince=null,n.lastPromptRingAt=t,this.emit(`event`,{type:`event`,sessionId:e.sessionId,kind:`blocked`,at:t}),r!==null&&!n.blockedNotified&&this.emit(`ring`,{sessionId:e.sessionId,kind:`blocked`,reason:`agent-blocked`}),n.blockedNotified=!0;return}if(e.state===`idle`||e.state===`done`){n.promptState=`finished`;let i=n.workingSince;if(n.workingSince=null,r!==`working`||i===null)return;let a=t-i;this.emit(`event`,{type:`event`,sessionId:e.sessionId,kind:`prompt`,durationMs:a,at:t}),a>=this.opts.notifyMinCommandMs&&(n.lastPromptRingAt=t,n.activeSince=null,this.emit(`ring`,{sessionId:e.sessionId,kind:`prompt`,reason:e.state===`done`?`agent-finished`:`quiet`,durationMs:a}));return}n.promptState=`unknown`,n.workingSince=null;return}case`session-removed`:this.s.delete(e.sessionId),this.emit(`event`,{type:`event`,sessionId:e.sessionId,kind:`exit`,at:t});return;default:return}}tick(){let e=this.now();for(let[t,n]of this.s){if(n.agentState!==null&&n.agentState!==`unknown`||n.activeSince===null||e-n.lastChangeAt<this.opts.idleQuietMs)continue;if(n.lastChangeAt-n.activeSince<this.opts.idleMinActiveMs){n.activeSince=null;continue}let r=n.lastChangeAt-n.activeSince;n.activeSince=null,this.emit(`event`,{type:`event`,sessionId:t,kind:`idle`,durationMs:r,at:e}),!(e-n.lastPromptRingAt<5e3+this.opts.idleQuietMs)&&n.promptState!==`editing`&&this.emit(`ring`,{sessionId:t,kind:`idle`,reason:`quiet`,durationMs:r})}}};function er(e){return e===`darwin`||e===`linux`||e===`win32`?e:`unknown`}const tr=new Set([`sh`,`bash`,`zsh`,`fish`,`dash`,`ksh`,`pwsh`,`powershell`,`cmd`]),nr=new Set([`ssh`,`mosh`,`docker`,`podman`,`kubectl`,`wsl`]);function rr(e){return un(e??``).replace(/^-/,``).replace(/\.exe$/i,``)}function ir(e,t,n){let r=rr(t),i=tr.has(r)?r:void 0,a=r===`claude`?`Claude`:r===`codex`?`Codex`:void 0,o=nr.has(r);return{...e,shell:i,agentName:a,locality:o?`guest`:n===`local-process`&&(i||a)?`local`:`unknown`,revision:JSON.stringify([e.sessionId,e.cwd,e.title,e.sessionLabel,r,n])}}function V(e,t){if(e===void 0)return;let n=e.replace(/[\r\n\t\u2028\u2029]+/gu,` `).replace(/[\p{Cc}\p{Cs}\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/gu,``).replace(/\s+/gu,` `).trim();if(/(?:^|[\s("'=:])(?:\/|~[\\/]|[a-z]:[\\/])|\\\\|[a-z][a-z0-9+.-]*:\/\/|[^\s@]+@[^\s:]+:/iu.test(n))return;let r=``,i=0;for(let e of n){let n=Buffer.byteLength(e,`utf8`);if(i+n>t)break;i+=n,r+=e}return r||void 0}function ar(e,t){return[...[`Desktop`,`Documents`,`Downloads`].map(e=>L(t,e)),L(t,`Library`,`Mobile Documents`),L(t,`Library`,`CloudStorage`),`/Volumes`].some(t=>{let n=fn(t,e);return n===``||!n.startsWith(`..${mn}`)&&n!==`..`&&!I(n)})}function or(e={}){let t=e.now??Date.now,n=e.platform??process.platform,r=e.home??P(),i=new Map,a=0,o=new Set;async function s(e){if(e.aborted||o.size>=32)throw Error(`git context unavailable`);if(a>=2?await new Promise((t,n)=>{let r=()=>{o.delete(i),n(Error(`git context unavailable`))},i=()=>{o.delete(i),e.removeEventListener(`abort`,r),a+=1,t()};o.add(i),e.addEventListener(`abort`,r,{once:!0})}):a+=1,e.aborted)throw--a,o.values().next().value?.(),Error(`git context unavailable`);return()=>{--a,o.values().next().value?.()}}let c={NODE_ENV:`production`,PATH:process.env.PATH,SystemRoot:process.env.SystemRoot,GIT_CONFIG_NOSYSTEM:`1`,GIT_CONFIG_GLOBAL:process.platform===`win32`?`NUL`:`/dev/null`,GIT_CONFIG_COUNT:`0`,GIT_TERMINAL_PROMPT:`0`,GIT_OPTIONAL_LOCKS:`0`,GIT_NO_REPLACE_OBJECTS:`1`},l=(e,t,n)=>new Promise((r,i)=>{zt(`git`,[`-c`,`core.fsmonitor=false`,`-C`,e,...t],{env:c,encoding:`utf8`,signal:n,timeout:250,killSignal:`SIGKILL`,maxBuffer:8192,windowsHide:!0},(e,t)=>e?i(e):r(t.trim()))});return async(e,a)=>{if(!I(e)||e.length>1024||a.aborted||n===`darwin`&&ar(e,r))return;let o=t();for(let[e,t]of i)(o<t.observedAt||o-t.observedAt>=5e3)&&i.delete(e);let c=i.get(e);if(c)return c;let u=new AbortController,d=()=>u.abort();a.addEventListener(`abort`,d,{once:!0});let f=setTimeout(d,250),p;try{p=await s(u.signal);let t=await l(e,[`rev-parse`,`--show-toplevel`],u.signal),n;try{n=await l(e,[`symbolic-ref`,`--quiet`,`--short`,`HEAD`],u.signal)}catch(e){!u.signal.aborted&&e.code===1&&(n=`detached HEAD`)}if(u.signal.aborted)return;let r=V(un(t),256);if(!r)return;let a={repository:r,branch:V(n,256),observedAt:o};return i.size>=500&&i.delete(i.keys().next().value),i.set(e,a),a}catch{return}finally{clearTimeout(f),a.removeEventListener(`abort`,d),p?.()}}}async function sr(e,t){let n=t.now(),r=new AbortController,i,a=new Promise(e=>{i=setTimeout(()=>{r.abort(),e(void 0)},250)}),o=async()=>{if(!await Promise.race([Promise.resolve().then(()=>t.stillCurrent(e)),a]))throw Error(`stale notification context`)};try{await o();let i;e.locality===`local`&&e.cwd&&I(e.cwd)&&(i=await Promise.race([Promise.resolve().then(()=>t.git(e.cwd,r.signal)).catch(()=>void 0),a]));let s=t.stillCurrent(e);if(typeof s==`boolean`?!s:!await Promise.race([s,a]))throw Error(`stale notification context`);let c={computerName:V(t.computerName,128)??`Computer`,sessionLabel:V(e.sessionLabel,128)??`Session`,observedAt:Math.min(n,i?.observedAt??n)};for(let[t,n]of[[`customName`,256],[`title`,256],[`shell`,64],[`agentName`,64]]){let r=V(e[t],n);r&&(c[t]=r)}let l=V(i?.repository,256),u=V(i?.branch,256);return l&&(c.repository=l),l&&u&&(c.branch=u),c}finally{clearTimeout(i),r.abort()}}function cr(e){return{type:`notify`,sessionId:e.sessionId,kind:e.kind,exitCode:e.exitCode,durationMs:e.durationMs}}function lr(e){let t={...e,context:{...e.context}};for(let e of[`branch`,`title`,`agentName`,`shell`,`customName`,`repository`]){if(Ve.safeParse(t).success)return t;delete t.context[e]}return Ve.safeParse(t).success?t:void 0}var ur=class{options;cache=new WeakMap;constructor(e){this.options=e}prepare(e){let t=this.cache.get(e);if(t)return t();let n=new Map(this.options.pairings().map(e=>[e.phoneFp,e.kPair])),r=(this.options.now??Date.now)(),i=!1,a=performance.now(),o,s=new Promise(t=>{o=setTimeout(()=>{i=!0,t(cr(e))},250)}),c=Promise.race([this.build(e,()=>i||performance.now()-a>=250,r),s]).catch(()=>cr(e)).finally(()=>clearTimeout(o)),l=()=>c.then(t=>{let i=(this.options.now??Date.now)();if(t.type!==`notify-context`)return t;if(!this.options.capable()||i<r||i-r>=at.freshnessMs)return cr(e);let a=this.options.pairings(),o=t.boxes.filter(e=>this.options.state.owns(e.phoneFp,e.generation)&&a.some(t=>t.phoneFp===e.phoneFp&&t.kPair===n.get(e.phoneFp)));return o.length?{...t,boxes:o}:cr(e)});return this.cache.set(e,l),l()}async build(e,t,n){let i=this.options,a=i.now??Date.now,o=cr(e);if(!i.capable()||!e.reason)return o;let s=r(p(16)),c=i.pairings().slice(0,10),l=await i.facts(e.sessionId);if(!l||t())return o;let u=async()=>{let t=await i.facts(e.sessionId);return t?.revision===l.revision&&t.sessionId===l.sessionId},d=await sr(l,{computerName:i.computerName(),now:a,stillCurrent:u,git:i.git});if(t()||!i.capable()||!await u()||t())return o;let f=a();if(f-n>=at.freshnessMs||f<n||f<d.observedAt)return o;let m=[],h={type:`notify-context`,sessionId:e.sessionId,eventId:s,kind:e.kind,exitCode:e.exitCode,durationMs:e.durationMs,boxes:m};for(let r of c){if(t())break;if(!i.pairings().some(e=>e.phoneFp===r.phoneFp&&e.kPair===r.kPair))continue;let a=i.state.reserve(r.phoneFp);if(!a)continue;let o=lr({computerFp:i.computerFp,phoneFp:r.phoneFp,generation:a.generation,sessionId:e.sessionId,eventId:s,sequence:a.sequence,issuedAt:f,expiresAt:n+at.freshnessMs,reason:e.reason,context:d,exitCode:e.exitCode,durationMs:e.durationMs});if(!o)continue;let c,l;try{c=T(r.kPair),l=te(c,o),m.push(gt(l,o)),Buffer.byteLength(JSON.stringify(h),`utf8`)>16384&&m.pop()}catch{}finally{c?.fill(0),l?.fill(0)}}return m.length?h:o}};const dr=R.string().regex(/^(0|[1-9][0-9]{0,19})$/).refine(e=>BigInt(e)<=18446744073709551615n),fr=R.strictObject({generation:Et,used:R.number().int().min(0).max(at.encryptions)}),pr=R.strictObject({version:R.literal(1),phones:R.array(R.strictObject({phoneFp:g,sequence:dr,current:fr,previous:R.strictObject({generation:Et,expiresAt:R.number().int().nonnegative().max(2**53-1)}).optional()})).max(10).refine(e=>new Set(e.map(e=>e.phoneFp)).size===e.length)});var mr=class{paths;now;data={version:1,phones:[]};healthy=!0;file;constructor(e,t=Date.now){this.paths=e,this.now=t,this.file=L(e.dir,`notifications.json`);try{Fe(e);let t=L(e.dir,`notifications.initialized`),n=O(t)!==void 0;if(n&&l(t,8,process.getuid?.()).toString(`utf8`)!==`v1
3
+ `)throw Error(`invalid marker`);try{this.data=pr.parse(JSON.parse(l(this.file,16384,process.getuid?.()).toString(`utf8`)))}catch(e){if(n||!(e instanceof D&&e.kind===`missing`))throw e;if(!this.commit(this.data))return}n||(He(t,`v1
4
+ `),this.syncDirectory())}catch{this.healthy=!1}}syncDirectory(){if(process.platform===`win32`)return;let e=Yt(this.paths.dir,`r`);try{Gt(e)}finally{Ht(e)}}commit(e){if(!this.healthy)return!1;try{return Fe(this.paths),He(this.file,JSON.stringify(e)),this.syncDirectory(),this.data=e,!0}catch{return this.healthy=!1,!1}}enroll(e,t){if(!this.healthy||!g.safeParse(e).success||!Et.safeParse(t).success)return!1;let n=this.data.phones.find(t=>t.phoneFp===e);if(n?.current.generation===t)return n.current.used<at.encryptions;if(n?.previous?.generation===t||!n&&this.data.phones.length>=10)return!1;let r=structuredClone(this.data);return r.phones=r.phones.filter(t=>t.phoneFp!==e),r.phones.push({phoneFp:e,sequence:n?.sequence??`0`,current:{generation:t,used:0},...n?{previous:{generation:n.current.generation,expiresAt:this.now()+at.previousGenerationMs}}:{}}),this.commit(r)}reserve(e){if(!this.healthy)return;let t=structuredClone(this.data),n=t.phones.find(t=>t.phoneFp===e);if(!(!n||n.current.used>=at.encryptions||BigInt(n.sequence)>=18446744073709551615n))return n.sequence=String(BigInt(n.sequence)+1n),n.current.used++,n.previous&&n.previous.expiresAt<=this.now()&&delete n.previous,this.commit(t)?{generation:n.current.generation,sequence:n.sequence}:void 0}owns(e,t){return this.healthy&&this.data.phones.some(n=>n.phoneFp===e&&n.current.generation===t)}retain(e){if(this.data.phones.every(t=>e.has(t.phoneFp)))return;let t=structuredClone(this.data);t.phones=t.phones.filter(t=>e.has(t.phoneFp)),this.commit(t)}forget(e){let t=structuredClone(this.data);t.phones=t.phones.filter(t=>t.phoneFp!==e),this.commit(t)}};const hr=6e4;var gr=class{send;log;now;prepare;last=new Map;constructor(e,t,n=()=>Date.now(),r){this.send=e,this.log=t,this.now=n,this.prepare=r}ring(e){let t=this.now(),n=this.last.get(e.sessionId);for(let[n,r]of this.last)n!==e.sessionId&&t-r>=hr&&this.last.delete(n);return n!==void 0&&t-n<hr?!1:(this.last.set(e.sessionId,t),this.prepare?this.prepare(e).then(e=>this.send(e)).catch(()=>{this.log.warn(`notification preparation failed`)}):this.send(cr(e)),this.log.info(`ring`,{session:e.sessionId.slice(0,12),kind:e.kind}),!0)}forget(e){this.last.delete(e)}get size(){return this.last.size}};function _r(e){return e.type===`input.line`||e.type===`input.text`||e.type===`input.key`||e.type===`input.mouse`||e.type===`input.terminal`||e.type===`input.paste`||e.type===`session.create`||e.type===`session.focus`}var vr=class{completed=new Map;pending=new Map;get idle(){return this.pending.size===0}run(e,t){let n=this.completed.get(e);if(n)return Promise.resolve({...n});let r=this.pending.get(e);if(r)return r;if(this.pending.size>=256)return Promise.resolve({type:`ack`,reqId:e,ok:!1,error:`busy`});let i,a=new Promise(e=>{i=e});this.pending.set(e,a);let o=t=>{let n={...t};if(this.completed.set(e,n),this.completed.size>256){let e=this.completed.keys().next().value;e!==void 0&&this.completed.delete(e)}this.pending.delete(e),i({...n})},s=()=>o({type:`ack`,reqId:e,ok:!1,error:`delivery-unknown`});try{t().then(t=>{t.type!==`ack`||t.reqId!==e?s():o(t)},s)}catch{s()}return a}};const yr=R.instanceof(Uint8Array).refine(e=>e.length===32,{message:`expected 32 bytes`}),br=R.instanceof(Uint8Array).refine(e=>e.length===64,{message:`expected 64 bytes`});function xr(e){return e.replace(/[\p{Cc}\p{Cs}\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]/gu,` `).replace(/\s+/gu,` `).trim()||`Phone`}const Sr=R.object({ed25519Pub:yr,x25519Pub:yr,name:R.string().min(1).max(64).transform(xr),platform:R.enum([`ios`,`android`]),bind:br});var Cr=class{opts;window=null;pending=null;now;log;constructor(e){this.opts=e,this.now=e.now??(()=>Date.now()),this.log=e.log.child({unit:`pairing`})}get isOpen(){return this.window!==null&&this.now()<this.window.expiresAt}openWindow(){this.window&&this.closeWindow();let e=p(16),t=p(16),n=this.now()+(this.opts.windowMs??3e5),i=be({v:1,r:this.opts.relayUrl,c:this.opts.fp,e:r(this.opts.identity.ed25519.pub),n:this.opts.computerName.slice(0,40),p:r(e),g:r(t),b:1});Te(i,{allowInsecure:!0}),this.window={code:e,gate:t,expiresAt:n,failures:0,requests:0};let a=this.opts.sendCtrl({type:`pairing-open`,gateHash:ve(t),expiresAt:n});return this.log.debug(a?`pairing-open sent`:`pairing-open not sent yet; will re-advertise once authenticated`),this.log.info(`pairing window opened`),{qrText:i,expiresAt:n}}readvertise(){if(!this.window||this.now()>=this.window.expiresAt)return;if(this.window.requests>=5){this.log.info(`pairing window not re-advertised: admission cap reached`),this.closeIfExhausted(this.window);return}let e=this.opts.sendCtrl({type:`pairing-open`,gateHash:ve(this.window.gate),expiresAt:this.window.expiresAt});this.log.debug(e?`pairing window re-advertised`:`pairing window re-advertise dropped`)}closeWindow(){if(!this.window)return;let e=this.window;e.code.fill(0),e.gate.fill(0),this.window=null,this.pending?.window===e&&(this.pending=null),this.opts.sendCtrl({type:`pairing-close`}),this.log.info(`pairing window closed`),this.opts.onClose?.()}closeIfExhausted(e){this.window!==e||e.requests<5||this.pending===null&&this.closeWindow()}tick(){this.window&&this.now()>=this.window.expiresAt&&this.closeWindow()}confirmWithTimeout(e,t){let n=this.opts.confirmTimeoutMs??6e4;return new Promise(r=>{let i=!1,a=setTimeout(()=>{i||(i=!0,this.log.warn(`confirmation timed out`,{phone:e.slice(0,8)}),r(!1))},n);typeof a.unref==`function`&&a.unref(),this.opts.confirm(e,t).then(e=>{i||(i=!0,clearTimeout(a),r(e))},()=>{i||(i=!0,clearTimeout(a),r(!1))})})}async handleRequest(e){let t=t=>{this.opts.sendCtrl({type:`pairing-reject`,phoneFp:e.phoneFp,reason:t}),this.log.warn(`pairing rejected`,{reason:t,phone:e.phoneFp.slice(0,8)})};if(!this.isOpen||!this.window)return t(`window-closed`);let n=this.window;if(n.requests>=5){t(`window-closed`),this.closeIfExhausted(n);return}if(n.requests+=1,this.opts.pairingCount()>=10||this.pending!==null){t(`too-many`),this.closeIfExhausted(n);return}let i=st(n.code,this.opts.fp),a;try{if(a=Sr.parse(Se(Pt(i,e.box,Ie(`request`,this.opts.fp,e.phoneFp)))),Ye(a.ed25519Pub)!==e.phoneFp)throw Error(`fp mismatch`);let t=Mt(`phone`,this.opts.fp,e.phoneFp,a.x25519Pub);if(!At(a.ed25519Pub,t,a.bind))throw Error(`unbound key`)}catch{n.failures+=1,t(`bad-code`),n.failures>=3?this.closeWindow():this.closeIfExhausted(n);return}let o={};this.pending={window:n,token:o};try{let s=await this.confirmWithTimeout(e.phoneFp,a.name);if(this.pending?.token!==o||!this.isOpen||this.window!==n)return;if(!s)return t(`declined`);let l;try{l=mt(this.opts.identity.x25519.priv,a.x25519Pub,n.code,this.opts.fp,e.phoneFp)}catch{n.failures+=1,t(`bad-code`),n.failures>=3&&this.closeWindow();return}this.opts.savePairing({phoneFp:e.phoneFp,name:a.name,platform:a.platform,ed25519Pub:r(a.ed25519Pub),x25519Pub:r(a.x25519Pub),kPair:r(l),pairedAt:new Date(this.now()).toISOString(),lastSeenAt:null}),this.opts.sendCtrl({type:`pairing-add`,phoneFp:e.phoneFp,ed25519Pub:a.ed25519Pub,name:a.name,pairId:ft(l)});let u=_e(i,b({x25519Pub:this.opts.identity.x25519.pub,computerName:this.opts.computerName,accent:this.opts.accent,bind:c(this.opts.identity.ed25519.priv,Mt(`computer`,this.opts.fp,e.phoneFp,this.opts.identity.x25519.pub))}),Ie(`response`,this.opts.fp,e.phoneFp));this.opts.sendCtrl({type:`pairing-response`,phoneFp:e.phoneFp,box:u}),this.log.info(`paired`,{phone:e.phoneFp.slice(0,8)}),this.closeWindow()}finally{this.pending?.token===o&&(this.pending=null,this.closeIfExhausted(n))}}};const wr=e=>!/^turns:/.test(e)&&!/[?&]transport=tcp(?:&|$)/.test(e);function Tr(e){return e.flatMap(e=>e.urls.filter(wr).map(t=>e.username&&e.credential?t.replace(/^(turns?):/,`$1:${encodeURIComponent(e.username)}:${encodeURIComponent(e.credential)}@`):t))}function Er(e){let t=e.trim().replace(/%.*$/,``).toLowerCase();if(En(t)!==6)return t;try{return new URL(`http://[${t}]/`).hostname.slice(1,-1)}catch{return t}}function Dr(e){let t=e.trim().replace(/^a=/,``).split(/\s+/),n=t.indexOf(`typ`);return!t[0]?.startsWith(`candidate:`)||t.length<8||n!==6?null:{address:Er(t[4]),type:t[7]}}function Or(e,t={}){let n=t.turn!==!1;return t=>kr(t,Tr(n?e():Rn()),n)}Or(()=>Rn());const kr=async(e,t,n=!0)=>{let{default:r}=await import(`node-datachannel`),i=new r.PeerConnection(`shellbell-v2`,{iceServers:t}),a=null,o=!1,s=new Set,c=new Set,l=()=>{let e=i.getSelectedCandidatePair();if(!e||e.local.type===`relay`||e.remote.type===`relay`)return!1;let t=Er(e.remote.address);return s.has(t)&&!c.has(t)},d=n,f=null,p=[],m=()=>{f&&clearInterval(f),f=null},h=()=>{if(m(),!o)try{e.closed()}catch{}},g=e=>{if(!o)try{e()}catch{h()}};return i.onLocalDescription((t,n)=>{g(()=>{(n===`offer`||n===`answer`)&&e.description(t,n)})}),i.onLocalCandidate((t,n)=>{g(()=>e.candidate(t.replace(/^a=candidate:/,`candidate:`),n,null))}),i.onStateChange(e=>{(e===`failed`||e===`closed`||e===`disconnected`)&&h()}),i.onDataChannel(t=>{g(()=>{if(a||t.getLabel()!==`shellbell-v2`){t.close(),h();return}a=t,t.onOpen(()=>{g(()=>{if(n){e.open();return}let t=Date.now()+3e3,r=()=>g(()=>{if(l()){if(d)return;d=!0,e.open();for(let t of p.splice(0))e.message(t)}else(d||Date.now()>=t)&&h()});f=setInterval(r,250),f.unref?.(),r()})}),t.onClosed(h),t.onError(h),t.onMessage(t=>{g(()=>{if(typeof t==`string`){h();return}let n=(t instanceof ArrayBuffer,new Uint8Array(t));if(n.length>61e3){h();return}if(!d){p.length>=16?h():p.push(n);return}e.message(n)})})})}),{async offer(){throw Error(`computer is WebRTC responder`)},async answer(e){i.setRemoteDescription(e,`offer`)},async acceptAnswer(){throw Error(`computer is WebRTC responder`)},async candidate(e,t){if(!n){let t=Dr(e);if(!t)return;if(t.type===`relay`){c.add(t.address);return}(t.type===`host`||t.type===`srflx`)&&s.add(t.address)}i.addRemoteCandidate(e,t??`0`)},async remoteCertificate(e){if(!a?.isOpen()||i.state()!==`connected`)throw Error(`DTLS not connected`);let t=i.remoteFingerprint();if(t.algorithm.toLowerCase()!==`sha-256`)throw Error(`DTLS fingerprint algorithm`);let n=nt(t.value.replaceAll(`:`,``));if(!u(e,n))throw Error(`DTLS fingerprint mismatch`);return n},send(e){if(o||!d||!a?.isOpen()||e.length>61e3||a.bufferedAmount()+e.length>262144)return!1;try{return a.sendMessageBinary(e)}catch{return!1}},close(){o||(o=!0,m(),a?.close(),a=null,i.close())}}};var Ar=class{helloTimeoutMs=15e3;phoneFp;connId;name;relayConnId;openedAt=Date.now();handshaken=!1;routed=!1;broken=!1;dormant=!1;viewed=null;generation=0;awaitingDirectReady=!1;endpoint;constructor(e){this.phoneFp=e.phoneFp,this.connId=e.connId,this.relayConnId=e.connId,this.name=e.name,this.endpoint=new S({role:`computer`,computerFp:e.computerFp,phoneFp:e.phoneFp,keys:{staticPrivate:e.identity.x25519.priv,remoteStatic:e.remoteStatic,pairKey:e.kPair},sendRelay:e.send,commitFloor:e.commitFloor,prepareReady:e.prepareReady,native:e.native??Or(e.iceServers??(()=>Rn()),{turn:e.turn}),allowDirect:!0,terminal:(t,n)=>{let r;try{r=wt(Se(t))}catch{return}this.awaitingDirectReady&&(this.awaitingDirectReady=!1,this.handshaken=!0,e.ready(this)),e.terminal(this,r,n)},routeChanged:t=>{this.awaitingDirectReady=t===`direct`,this.handshaken=!1,t&&(this.routed=!0),this.dormant=!1,this.viewed=null,this.generation+=1,e.log.info(`v2 terminal route changed`,{route:t,phone:e.phoneFp.slice(0,8)}),e.ready(this)},failure:(t,n)=>{e.log.warn(`v2 transport failed`,{stage:t,...n?{code:n.code,phase:n.phase}:{},phone:e.phoneFp.slice(0,8)})}})}get transportDiagnostics(){return this.endpoint.diagnostics}get activeRoute(){return this.endpoint.activeRoute}get handshakeGeneration(){return this.generation}helloOverdue(e=Date.now()){return!this.handshaken&&!this.routed&&!this.dormant&&e-this.openedAt>=this.helloTimeoutMs}handleEnvelope(e){return this.endpoint.receiveRelay(e)}send(e){return!this.broken&&this.endpoint.sendTerminal(b(e))}relayLost(){this.endpoint.relayLost()}close(){this.broken=!0,this.handshaken=!1,this.endpoint.close()}};const jr=new Set([`bad-sig`,`fp-mismatch`]),Mr=A.unacked*A.envelopeBytes;function Nr(e){if(e.t!==`ctrl`)return!1;let t=e.body;return typeof t==`object`&&!!t&&t.type===`auth`}function Pr(e){if(e.t!==`ctrl`)return e.t;let t=e.body;return typeof t==`object`&&t&&typeof t.type==`string`?t.type:`ctrl`}function Fr(e,t,n){let r=t*2**e,i=r*.2*(Math.random()*2-1);return Math.min(n,Math.max(0,r+i))}var Ir=class extends Cn{opts;ws=null;stopped=!0;attempt=0;reconnectTimer=null;pingTimer=null;pongTimer=null;authed=!1;relayWithholdsTurn=!1;ice=new zn;log;constructor(e){super(),this.opts=e,this.log=e.log.child({unit:`relay`})}get online(){return this.authed&&this.ws?.readyState===Dn.OPEN}start(){this.stopped&&(this.stopped=!1,this.attempt=0,this.connect())}stop(){this.stopped=!0,this.clearTimers();let e=this.ws,t=this.online;this.ws=null,this.authed=!1,e?.terminate(),t&&this.emit(`down`)}iceServers(){return this.refreshIceIfDue(),this.ice.servers(Date.now())}refreshIceIfDue(){let e=Date.now();this.authed&&this.ice.needsRefresh(e)&&this.ice.takeRefresh(e)&&this.sendCtrl({type:`ice-refresh`})}sendCtrl(e){return this.sendEnvelope({v:1,t:`ctrl`,from:this.opts.fp,seq:0,body:e})}sendEnvelope(e){return!this.authed&&!Nr(e)?(this.log.debug(`dropped send: not authenticated`,{type:Pr(e)}),!1):this.ws?.readyState===Dn.OPEN?(this.ws.send(e.v===2?Lt(e):he(e),{binary:!0}),!0):(this.log.debug(`dropped send: socket not open`,{type:Pr(e)}),!1)}sendBoundedEnvelope(e){let t=this.ws;if(!this.authed||t?.readyState!==Dn.OPEN)return!1;let n=e.v===2?Lt(e):he(e);if(n.byteLength>A.envelopeBytes)return!1;let r=t.bufferedAmount;return typeof r!=`number`||!Number.isFinite(r)||r<0||r>Mr-n.byteLength?!1:(t.send(n,{binary:!0}),!0)}connect(){if(this.stopped)return;let e=y(this.opts.relayUrl,this.opts.fp);this.log.info(`connecting`,{attempt:this.attempt});let t=new Dn(e,{handshakeTimeout:1e4}),n=t;this.ws=t,t.on(`open`,()=>{this.ws===n&&this.log.debug(`socket open`)}),t.on(`message`,(e,t)=>{if(this.ws!==n||!t)return;let r=new Uint8Array(e),i;try{i=ne(r)}catch(e){this.log.warn(`malformed frame from relay`,{code:e instanceof o?e.code:M(e)});return}if(i.t===`e2e`){this.authed&&this.emit(`e2e`,i,r.byteLength);return}let a;try{a=Pe(i.body)}catch(e){this.log.warn(`malformed ctrl from relay`,{code:e instanceof o?e.code:M(e)});return}this.onCtrl(a)}),t.on(`pong`,()=>{this.ws===n&&(this.pongTimer&&clearTimeout(this.pongTimer),this.pongTimer=null)}),t.on(`close`,e=>{this.ws===n&&this.onClose(e)}),t.on(`error`,e=>{this.ws===n&&this.log.warn(`socket error`,{name:M(e)})})}onCtrl(e){if(e.type===`challenge`){let t=c(this.opts.identity.ed25519.priv,Ge(e.connId,`agent`,this.opts.fp,e.nonce));this.sendCtrl({type:`auth`,role:`agent`,fp:this.opts.fp,ed25519Pub:this.opts.identity.ed25519.pub,sig:t,name:this.opts.name,appVersion:this.opts.appVersion,...this.opts.turn===!1&&{turn:!1}});return}if(e.type===`auth-ok`){this.authed=!0,this.ice=new zn,e.iceServers&&this.ice.update(e.iceServers,e.iceExpiresInMs??0,Date.now()),this.attempt=0,this.startPing(),this.log.info(`authenticated`,{minFrameMs:e.minFrameMs}),this.relayWithholdsTurn=e.turnOff===!0,this.opts.turn===!1&&!this.relayWithholdsTurn&&this.log.warn(`relay does not withhold TURN from phones; update the relay to 0.3.0`),this.emit(`auth-ok`,e);return}if(e.type===`ice-servers`){this.ice.update(e.iceServers,e.iceExpiresInMs,Date.now());return}if(e.type===`auth-fail`){this.log.error(`auth failed`,{reason:e.reason}),jr.has(e.reason)&&(this.stopped=!0),this.emit(`auth-fail`,e.reason);return}this.emit(`ctrl`,e)}onClose(e){let t=this.authed;if(this.authed=!1,this.clearTimers(),this.ws=null,e===4005){this.log.warn(`connection superseded by a newer agent`,{code:e}),this.stopped=!0,this.emit(`superseded`),this.emit(`down`);return}e===4413||e===4429?this.log.error(`relay closed connection`,{code:e}):this.log.info(`socket closed`,{code:e}),t&&this.emit(`down`),!this.stopped&&this.scheduleReconnect()}scheduleReconnect(){let e=this.opts.backoffMinMs??1e3,t=this.opts.backoffMaxMs??3e4,n=Fr(this.attempt,e,t);this.attempt=Math.min(this.attempt+1,10),this.reconnectTimer=setTimeout(()=>this.connect(),n)}startPing(){if(this.pingTimer)return;let e=this.opts.pingIntervalMs??45e3,t=this.opts.pongTimeoutMs??1e4,n=this.ws;this.pingTimer=setInterval(()=>{this.ws===n&&n?.readyState===Dn.OPEN&&(this.refreshIceIfDue(),this.pongTimer&&clearTimeout(this.pongTimer),n.ping(),this.pongTimer=setTimeout(()=>{this.log.warn(`pong timeout; terminating socket`),n.terminate()},t))},e)}clearTimers(){this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.pingTimer&&clearInterval(this.pingTimer),this.pongTimer&&clearTimeout(this.pongTimer),this.reconnectTimer=this.pingTimer=this.pongTimer=null}},Lr=class{options;sender;startedAt;open=!0;admitted=!1;sending=!1;refusalAt=null;pending=null;nativeHistory=null;timedOutHistory=null;latestHistoryRequestId;historyRevoked=!1;anchor;anchorBound=!1;lastAcknowledgedGeneration;snapshotAccepted=!1;snapshotRequested=!1;refreshRequested=!1;constructor(e){if(!ae.safeParse(e.subscriptionId).success||!de.safeParse(e.sessionId).success)throw Error(`Invalid screen stream identity`);let t=e.now();if(!Number.isFinite(t))throw Error(`Invalid screen stream clock`);this.options={...e,...e.history?{history:{...e.history}}:{}},this.startedAt=t,this.sender=new oe({subscriptionId:e.subscriptionId,sessionId:e.sessionId,now:()=>this.readClock(),newTransferId:()=>this.options.newTransferId(),send:e=>this.admitChunk(e)})}offer(e,t){if(!this.canOfferScreen()||e.sessionId!==this.options.sessionId||e.gen!==t.generation||e.scrollbackTotal!==t.reported)return!1;if(e.type===`screen.diff`){if(!this.snapshotAccepted||this.lastAcknowledgedGeneration===void 0||e.gen!==this.lastAcknowledgedGeneration+1)return this.requestFreshSnapshot(),!1}else if(this.lastAcknowledgedGeneration!==void 0&&(e.gen<this.lastAcknowledgedGeneration||e.gen===this.lastAcknowledgedGeneration&&!this.refreshRequested))return!1;let n;try{if(e.type===`screen.snapshot`){let{type:t,sessionId:r,...i}=e,a=fe(i);if(!a.ok)return this.close(a.code),!1;n=a.bytes}else{let{type:t,sessionId:r,...i}=e;n=le(i)}}catch{return e.type===`screen.diff`?this.requestFreshSnapshot():this.close(`invalid-transfer`),!1}if(!this.open)return!1;try{let t=this.sender.offer({kind:e.type===`screen.snapshot`?`snapshot`:`diff`,generation:e.gen},n);if(!this.reconcileSender())return!1;if(!t.accepted)return t.reason===`too-large`&&this.close(`screen-too-large`),!1}catch{return this.close(`invalid-transfer`),!1}return this.open?(this.pending={kind:e.type===`screen.snapshot`?`snapshot`:`diff`,generation:t.generation,reported:t.reported,...e.type===`screen.snapshot`&&t.capture!==void 0?{capture:t.capture}:{},finalSequence:null},e.type===`screen.snapshot`&&(this.snapshotAccepted=!0,this.snapshotRequested=!1,this.refreshRequested=!1),!0):!1}canOfferScreen(){if(this.tick(),!this.open||this.pending||this.sender.inFlight>=A.unacked)return!1;let e;try{e=this.sender.canOffer(`snapshot`)}catch{return this.close(`invalid-transfer`),!1}return!(!this.reconcileSender()||!e)}receive(e,t){if(!this.open||e.subscriptionId!==this.options.subscriptionId||(this.tick(),!this.open))return;if(!Number.isSafeInteger(t)||t<1||t>A.envelopeBytes||!ce.safeParse(e).success){this.close(`invalid-transfer`);return}if(e.type===`stream.cancel`){this.cancel();return}if(e.type===`stream.refresh`){this.refreshRequested=!0,this.requestFreshSnapshot();return}if(e.type===`stream.history.get`){this.requestHistory(e);return}if(e.type!==`stream.ack`){this.close(`invalid-transfer`);return}let n;try{n=this.sender.acknowledge(e.subscriptionId,e.through)}catch{this.close(`invalid-transfer`);return}if(!this.reconcileSender())return;if(n===`invalid`){this.close(`invalid-transfer`);return}if(n!==`advanced`)return;if(this.pending?.finalSequence!==null&&this.pending?.finalSequence!==void 0&&e.through>=this.pending.finalSequence){let e=this.pending;this.pending=null,this.lastAcknowledgedGeneration=e.generation,!this.anchorBound&&e.kind===`snapshot`&&(this.anchor=Object.freeze({generation:e.generation,reported:e.reported,...e.capture===void 0?{}:{capture:e.capture}}),this.anchorBound=!0)}let r=this.nativeHistory;r?.phase===`transfer`&&r.finalSequence!==null&&e.through>=r.finalSequence&&this.finishHistory(r)}requestHistory(e){let t=this.options.history;if(!t){this.close(`invalid-transfer`);return}if(e.requestId===this.nativeHistory?.requestId||e.requestId===this.latestHistoryRequestId)return;if(this.nativeHistory||this.timedOutHistory){this.sendHistoryError(e.requestId,`history-unavailable`);return}let n=this.anchor,r;try{r=this.sender.canOffer(`history`)}catch{this.close(`invalid-transfer`);return}if(!this.reconcileSender())return;if(this.historyRevoked||n&&!n.capture){this.latestHistoryRequestId=e.requestId,this.sendHistoryError(e.requestId,`history-reset`);return}if(!n?.capture||e.before>n.reported||this.sender.inFlight>=A.unacked||!r){this.latestHistoryRequestId=e.requestId,this.sendHistoryError(e.requestId,`history-unavailable`);return}let i;try{i=this.readClock()}catch{this.close(`invalid-transfer`);return}let a={requestId:e.requestId,before:e.before,count:e.count,anchor:n,controller:new AbortController,phase:`reading`,readDeadline:i+A.totalMs,readyDeadline:null,finalSequence:null};this.nativeHistory=a;let o;try{o=t.read(this.options.sessionId,{capture:n.capture,reported:n.reported,before:a.before,count:a.count,signal:a.controller.signal})}catch(e){this.failHistoryRead(a,e);return}Promise.resolve(o).then(e=>this.completeHistoryRead(a,e),e=>this.failHistoryRead(a,e)).catch(()=>{this.open&&this.nativeHistory===a&&this.close(`invalid-transfer`)})}completeHistoryRead(e,t){if(this.timedOutHistory===e){this.timedOutHistory=null;return}if(!this.open||this.nativeHistory!==e||e.phase!==`reading`)return;if(this.tick(),this.timedOutHistory===e){this.timedOutHistory=null;return}if(!this.open||this.nativeHistory!==e)return;if(typeof t!=`object`||!t){this.close(`invalid-transfer`);return}if(t.status===`reset`){this.historyRevoked=!0,this.finishHistory(e,`history-reset`);return}if(t.status===`unavailable`){if(![`unsupported`,`unanchored`,`busy`,`changed`,`fetch-window`].includes(t.reason)){this.close(`invalid-transfer`);return}this.finishHistory(e,`history-unavailable`,t.reason===`fetch-window`?`fetch-window`:void 0);return}if(t.status===`cancelled`){this.finishHistory(e,`history-unavailable`);return}if(t.status!==`page`&&t.status!==`boundary`){this.close(`invalid-transfer`);return}if(t.status===`page`&&(!Array.isArray(t.lines)||t.lines.length>e.count)){this.close(`invalid-transfer`);return}let n=_({...t,kind:`history`,generation:e.anchor.generation,requestId:e.requestId,before:e.before});if(!n.ok){n.code===`history-line-too-large`?this.finishHistory(e,`history-line-too-large`):this.close(`invalid-transfer`);return}try{let t=this.sender.offer({kind:`history`,generation:e.anchor.generation,requestId:e.requestId,before:e.before},n.bytes);if(!this.reconcileSender())return;if(!t.accepted){this.close(`invalid-transfer`);return}e.phase=`transfer`,e.readDeadline=null,e.readyDeadline=this.readClock()+A.progressMs}catch{this.close(`invalid-transfer`);return}if(this.open&&this.nativeHistory===e)try{Rr(this.options.history?.onReady(),()=>{this.open&&this.close(`invalid-transfer`)})}catch{this.open&&this.close(`invalid-transfer`)}}failHistoryRead(e,t){if(this.timedOutHistory===e){this.timedOutHistory=null;return}if(this.open&&this.nativeHistory===e&&e.phase===`reading`){if(this.tick(),this.timedOutHistory===e){this.timedOutHistory=null;return}this.open&&this.nativeHistory===e&&(t instanceof k?this.close(`session-gone`):this.finishHistory(e,`history-unavailable`))}}finishHistory(e,t,n){this.open&&this.nativeHistory===e&&(this.nativeHistory=null,this.latestHistoryRequestId=e.requestId,e.readDeadline=null,e.readyDeadline=null,t&&this.sendHistoryError(e.requestId,t,n))}sendHistoryError(e,t,n){if(!this.open)return;let r;try{r=this.options.sendControl({type:`stream.error`,subscriptionId:this.options.subscriptionId,requestId:e,code:t,...n?{historyReason:n}:{}})}catch{this.close(`invalid-transfer`);return}r!==!0&&r!==!1&&(Rr(r),this.close(`invalid-transfer`))}sendOne(){if(this.sending||(this.tick(),!this.open))return!1;this.sending=!0;try{return this.sender.pump(),this.reconcileSender(),this.chunkAdmitted}catch{throw this.close(`invalid-transfer`),Error(`Screen stream send failed`)}finally{this.chunkAdmitted=!1,this.sending=!1}}chunkAdmitted=!1;tick(){if(this.open)try{let e=this.readClock(),t=this.nativeHistory;if(t?.phase===`reading`&&t.readDeadline!==null&&e>=t.readDeadline&&(this.nativeHistory=null,this.timedOutHistory=t,this.latestHistoryRequestId=t.requestId,t.readDeadline=null,t.controller.abort(),this.sendHistoryError(t.requestId,`history-unavailable`)),!this.open)return;let n=this.nextDeadline();n!==null&&e>=n&&this.close(`stalled`)}catch{this.close(`invalid-transfer`)}}nextDeadline(){if(!this.open)return null;let e=[this.sender.nextDeadline()];this.admitted||e.push(this.startedAt+A.progressMs),this.refusalAt!==null&&e.push(this.refusalAt+A.progressMs),this.nativeHistory?.readDeadline!==null&&this.nativeHistory?.readDeadline!==void 0&&e.push(this.nativeHistory.readDeadline),this.nativeHistory?.readyDeadline!==null&&this.nativeHistory?.readyDeadline!==void 0&&e.push(this.nativeHistory.readyDeadline);let t=e.filter(e=>e!==null);return t.length===0?null:Math.min(...t)}historyAnchor(){return this.anchor}cancel(){this.close(`cancelled`)}terminate(e){if(e!==`session-gone`&&e!==`invalid-transfer`)throw TypeError(`Invalid screen stream termination reason`);this.close(e)}readClock(){let e=this.options.now();if(!Number.isFinite(e))throw Error(`Invalid screen stream clock`);return e}reconcileSender(){if(!this.open)return!1;try{let e=this.sender.tick();this.open&&e!==`open`&&this.close(e===`stalled`?`stalled`:`invalid-transfer`)}catch{this.close(`invalid-transfer`)}return this.open}admitChunk(e){if(!this.open||this.chunkAdmitted||(this.tick(),!this.open))return!1;let t;try{t=this.options.sendChunk(e)}catch{throw this.close(`invalid-transfer`),Error(`Screen stream send failed`)}if(t!==!0&&t!==!1)throw Rr(t),this.close(`invalid-transfer`),Error(`Screen stream send failed`);if(t)this.chunkAdmitted=!0,this.admitted=!0,this.refusalAt=null,e.meta.kind===`history`&&this.nativeHistory?.phase===`transfer`&&e.meta.requestId===this.nativeHistory.requestId?(this.nativeHistory.readyDeadline=null,e.index===e.count-1&&(this.nativeHistory.finalSequence=e.sequence)):e.meta.kind!==`history`&&this.pending&&e.meta.generation===this.pending.generation&&e.index===e.count-1&&(this.pending.finalSequence=e.sequence);else if(this.open&&this.refusalAt===null)try{this.refusalAt=this.readClock()}catch{this.close(`invalid-transfer`)}return t}requestFreshSnapshot(){if(this.open&&!this.snapshotRequested){this.snapshotRequested=!0;try{Rr(this.options.requestSnapshot(),()=>{this.open&&this.close(`invalid-transfer`)})}catch{this.close(`invalid-transfer`)}}}close(e){if(!this.open)return;this.open=!1;let t=this.nativeHistory;if(this.nativeHistory=null,this.timedOutHistory=null,this.sender.cancel(),this.pending=null,this.anchor=void 0,this.anchorBound=!1,this.refusalAt=null,this.snapshotRequested=!1,this.refreshRequested=!1,t?.controller.abort(),e!==`cancelled`)try{Rr(this.options.sendControl({type:`stream.error`,subscriptionId:this.options.subscriptionId,code:e}))}catch{}try{Rr(this.options.onClosed(e))}catch{}}};function Rr(e,t){e===null||typeof e!=`object`&&typeof e!=`function`||new Promise(t=>t(e)).catch(()=>t?.())}const zr=new TextEncoder;var Br=class{options;sender;open=!0;sending=!1;chunkAdmitted=!1;generation=0;state=null;backlog=[];backlogBytes=0;offset=0;behind=!1;reseedRequested=!1;historyLines=2e3;constructor(e){this.options=e,this.sender=new oe({subscriptionId:e.subscriptionId,sessionId:e.sessionId,now:()=>this.readClock(),newTransferId:()=>e.newTransferId(),send:e=>this.admitChunk(e)});let{source:t}=e;t.on(`seed`,e=>{if(!this.open)return;let n=zr.encode(e.data);if(n.length>A.screenBytes){this.historyLines>1?(this.historyLines=Math.max(1,Math.floor(this.historyLines/2)),t.reseed(this.historyLines)):this.close(`invalid-transfer`);return}this.generation=e.generation,this.state={cols:e.cols,rows:e.rows,bytes:n},this.backlog=[],this.backlogBytes=0,this.offset=0,this.behind=!1,this.reseedRequested=!1,this.ready()}),t.on(`bytes`,(e,t)=>{if(e.length!==0&&this.open&&!this.behind&&t===this.generation){if(this.backlogBytes+e.length>262144){this.behind=!0,this.backlog=[],this.backlogBytes=0,this.ready();return}this.backlog.push(new Uint8Array(e)),this.backlogBytes+=e.length,this.ready()}}),t.on(`end`,e=>this.close(Vr(e)))}start(){return this.options.source.start(this.historyLines)}receive(e,t){if(!this.open||e.subscriptionId!==this.options.subscriptionId||(this.tick(),!this.open))return;if(!Number.isSafeInteger(t)||t<1||t>A.envelopeBytes||!ce.safeParse(e).success){this.close(`invalid-transfer`);return}if(e.type===`stream.cancel`){this.cancel();return}if(e.type===`stream.refresh`){this.requestReseed();return}if(e.type===`stream.history.get`){this.sendControl({type:`stream.error`,subscriptionId:this.options.subscriptionId,requestId:e.requestId,code:`history-unavailable`});return}if(e.type!==`stream.ack`){this.close(`invalid-transfer`);return}let n;try{n=this.sender.acknowledge(e.subscriptionId,e.through)}catch{this.close(`invalid-transfer`);return}n===`invalid`?this.close(`invalid-transfer`):n===`advanced`&&this.ready()}sendOne(){if(this.sending||(this.tick(),!this.open))return!1;this.sending=!0;try{return this.sender.canOffer(`vt`)&&this.offerNext(),this.open?(this.sender.pump(),this.reconcileSender(),this.chunkAdmitted):!1}catch{return this.close(`invalid-transfer`),!1}finally{this.chunkAdmitted=!1,this.sending=!1}}tick(){if(this.open)try{this.reconcileSender()}catch{this.close(`invalid-transfer`)}}nextDeadline(){return this.open?this.sender.nextDeadline():null}cancel(){this.close(`cancelled`)}terminate(e){this.close(e)}offerNext(){if(this.state){let{cols:e,rows:t,bytes:n}=this.state;this.sender.offer({kind:`vt-state`,generation:this.generation,cols:e,rows:t},n).accepted&&(this.state=null);return}if(this.behind){this.requestReseed();return}if(this.backlogBytes===0)return;let e=new Uint8Array(this.backlogBytes),t=0;for(let n of this.backlog)e.set(n,t),t+=n.length;this.sender.offer({kind:`vt`,generation:this.generation,offset:this.offset},e).accepted&&(this.offset+=e.length,this.backlog=[],this.backlogBytes=0)}requestReseed(){this.reseedRequested||(this.reseedRequested=!0,this.options.source.reseed(this.historyLines))}ready(){try{this.options.onReady()}catch{}}readClock(){let e=this.options.now();if(!Number.isFinite(e))throw Error(`Invalid vt stream clock`);return e}reconcileSender(){let e=this.sender.tick();this.open&&e!==`open`&&this.close(e===`stalled`?`stalled`:`invalid-transfer`)}admitChunk(e){if(!this.open||this.chunkAdmitted)return!1;let t=this.options.sendChunk(e);return t&&(this.chunkAdmitted=!0),t}sendControl(e){try{this.options.sendControl(e)}catch{}}close(e){if(this.open){this.open=!1,this.sender.cancel(),this.state=null,this.backlog=[],this.backlogBytes=0,this.options.source.close(),e!==`cancelled`&&this.sendControl({type:`stream.error`,subscriptionId:this.options.subscriptionId,code:e});try{this.options.onClosed(e)}catch{}}}};function Vr(e){return e===`pane-gone`?`session-gone`:`unsupported`}const Hr=.6;var Ur=class{opts;offerPrepared(e,t){if(this.opts.delivery!==`scheduled`||this.stopped)return!1;let n=this.viewerSession.get(e);if(!n)return!1;let r=this.sessions.get(n),i=r?.viewers.get(e),a=r?.prepared;if(!r||!i||!a||i.offering)return!1;if(i.needsHistory&&!a.historyViewers.has(i))return r.dirty=!0,!1;if(i.lastSentGen===a.gen&&!i.forceSnapshot)return!1;let o=()=>!this.stopped&&this.sessions.get(n)===r&&r.prepared===a&&r.viewers.get(e)===i;i.offering=!0;try{let e=i.preparation===`bounded`,n=!e&&i.skipped>=3,r=i.lastSentGen===a.gen-1&&!i.forceSnapshot&&!a.forceSnapshotAll&&!n,s=t(r?a.diff:e?a.fullSnapshot():a.snapshotFor(n),r?a.diffContext:a.snapshotContext);if(s!==!0&&s!==!1)throw Wr(s),TypeError(`scheduled screen offer requires a synchronous boolean`);return s===!0?(o()&&(i.lastSentGen=a.gen,i.forceSnapshot=!1,i.skipped=0,r||(i.needsHistory=!1)),!0):(o()&&(i.forceSnapshot=!0),!1)}catch{throw o()&&(i.forceSnapshot=!0),TypeError(`scheduled screen offer failed`)}finally{i.offering=!1}}sessions=new Map;sessionOffset=0;scheduledCycle=0;lastReadinessCycle=0;viewerSession=new Map;budget;unsubscribe=null;timer=null;intervalMs;stopped=!0;watchedKey=``;now;log;constructor(e){this.opts=e,this.intervalMs=Math.max(125,e.intervalMs??125),this.now=e.now??(()=>Date.now()),this.log=e.log.child({unit:`tracker`}),this.budget={tokens:0,last:this.now()}}start(){this.timer||=(this.stopped=!1,this.unsubscribe??=this.opts.backend.on(e=>{e.type===`screen-changed`||e.type===`input-accepted`?this.markDirty(e.sessionId):e.type===`session-removed`&&this.sessionRemoved(e.sessionId)}),setInterval(()=>void this.tick(),this.intervalMs))}stop(){this.stopped=!0;for(let e of this.sessions.values())e.prepared=null,e.inflightViewers?.clear(),e.inflightViewers=null,e.viewers.size>0&&(e.dirty=!0);this.timer&&clearInterval(this.timer),this.timer=null,this.unsubscribe?.(),this.unsubscribe=null,this.watchedKey=`stopped`;try{this.opts.backend.setWatched?.([])}catch(e){this.log.warn(`setWatched failed`,{err:M(e)})}}setIntervalMs(e){let t=Math.max(125,e);t!==this.intervalMs&&(this.intervalMs=t,this.timer&&=(clearInterval(this.timer),setInterval(()=>void this.tick(),this.intervalMs)))}setViewed(e,t,n){if(t){let e=n?.preparation===void 0?`legacy`:n.preparation;if(e!==`legacy`&&e!==`bounded`)throw TypeError(`invalid screen preparation`);if(e===`bounded`&&this.opts.delivery!==`scheduled`)throw TypeError(`bounded screen preparation requires scheduled delivery`)}let r=this.viewerSession.get(e);if(r){let t=this.sessions.get(r),n=t?.viewers.get(e);n&&(t?.prepared?.historyViewers.delete(n),t?.inflightViewers?.delete(n)),t?.viewers.delete(e),t?.viewers.size===0&&(t.prepared=null,t.inflightViewers=null,this.retireUnused(r,t)),this.viewerSession.delete(e)}if(t){let r=this.state(t);r.viewers.set(e,{lastSentGen:-1,forceSnapshot:!0,skipped:0,needsHistory:n?.history===!0,offering:!1,preparation:n?.preparation??`legacy`}),r.dirty=!0,this.viewerSession.set(e,t)}this.pushWatched()}dropViewer(e){this.setViewed(e,null)}viewedBy(e){return[...this.sessions.get(e)?.viewers.keys()??[]]}markDirty(e){let t=this.sessions.get(e);t&&t.viewers.size>0&&(t.dirty=!0)}forceSnapshot(e,t){let n=this.sessions.get(t)?.viewers.get(e);n&&(n.forceSnapshot=!0,this.sessions.get(t).dirty=!0)}sessionRemoved(e){let t=this.sessions.get(e);if(t&&(t.prepared=null,t.inflightViewers?.clear(),t.inflightViewers=null),!t)return;let n=[...t.viewers.keys()];for(let e of n)this.viewerSession.delete(e);this.sessions.delete(e),this.pushWatched();try{Wr(this.opts.onSessionGone?.(e,n))}catch{}}pushWatched(){let e=[...this.sessions.entries()].filter(([,e])=>e.viewers.size>0).map(([e])=>e).sort(),t=e.join(` `);if(t!==this.watchedKey){this.watchedKey=t;try{this.opts.backend.setWatched?.(e)}catch(e){this.log.warn(`setWatched failed`,{err:M(e)})}}}retireUnused(e,t){t.viewers.size===0&&!t.inflight&&t.lastBackendScrollback===null&&this.sessions.get(e)===t&&this.sessions.delete(e)}state(e){let t=this.sessions.get(e);return t||(t={viewers:new Map,dirty:!1,inflight:!1,lastKeys:[],lastCols:0,lastRows:0,lastCursor:null,lastBackendScrollback:null,reported:0,gen:0,rrOffset:0,oversizeWarned:!1,prepared:null,inflightViewers:null},this.sessions.set(e,t)),t}async tick(){if(this.opts.delivery===`scheduled`){this.tickScheduled();return}let e=[...this.sessions.entries()];if(e.length===0)return;let t=this.sessionOffset%e.length,n=e.slice(t).concat(e.slice(0,t));for(let t of n){let[n,r]=t;if(this.stopped)return;if(r.viewers.size===0&&this.retireUnused(n,r),r.inflight||r.viewers.size===0)continue;if(r.dirty){r.inflight=!0,r.dirty=!1;let e=new Set([...r.viewers.values()].filter(e=>e.needsHistory)),t=e.size>0;r.inflightViewers=e;let i;try{i=t?await this.opts.backend.getScreen(n,{history:!0}):await this.opts.backend.getScreen(n)}catch(t){if(!this.stopped&&this.sessions.get(n)===r&&r.inflightViewers===e){if(t instanceof k)this.log.warn(`getScreen: session gone; dropping`,{session:n.slice(0,12)}),this.sessionRemoved(n);else{this.log.warn(`getScreen failed; will retry`,{session:n.slice(0,12),err:M(t)});for(let e of r.viewers.values())e.forceSnapshot=!0;r.dirty=!0}}r.inflightViewers=null,r.inflight=!1;continue}if(this.stopped||this.sessions.get(n)!==r||r.inflightViewers!==e){r.inflight=!1;continue}try{this.processScreen(n,r,i,e,t)}catch(e){this.log.error(`processScreen threw; will resync every viewer next tick`,{session:n.slice(0,12),err:M(e)});for(let e of r.viewers.values())e.forceSnapshot=!0;r.dirty=!0;continue}finally{r.inflightViewers=null,r.inflight=!1}}let i=!1;try{i=this.deliver(n,r)}catch(e){i=!0,this.log.error(`screen delivery threw; will retry prepared generation`,{session:n.slice(0,12),err:M(e)})}i&&(this.sessionOffset=(e.indexOf(t)+1)%e.length)}}tickScheduled(){let e=[...this.sessions.entries()];if(e.length===0)return;let t=this.sessionOffset%e.length,n=++this.scheduledCycle,r=(t+1)%e.length;for(let i of e.slice(t).concat(e.slice(0,t))){let[e,t]=i;if(this.stopped)return;t.viewers.size===0&&this.retireUnused(e,t),!(t.inflight||t.viewers.size===0)&&(t.dirty?this.captureScheduled(e,t,n,r):this.notifyScheduled(e,t,n,r))}}async captureScheduled(e,t,n,r){t.inflight=!0,t.dirty=!1;let i=new Set([...t.viewers.values()].filter(e=>e.needsHistory));t.inflightViewers=i;try{let n=i.size>0?await this.opts.backend.getScreen(e,{history:!0}):await this.opts.backend.getScreen(e);if(this.stopped||this.sessions.get(e)!==t||t.inflightViewers!==i)return;try{this.processScreen(e,t,n,i,i.size>0)}catch{this.log.error(`processScreen failed; will resync prepared screen`);for(let e of t.viewers.values())e.forceSnapshot=!0;t.dirty=!0;return}}catch(n){if(this.stopped||this.sessions.get(e)!==t||t.inflightViewers!==i)return;if(n instanceof k)this.sessionRemoved(e);else{this.log.warn(`getScreen failed; will retry`,{session:e.slice(0,12),err:M(n)});for(let e of t.viewers.values())e.forceSnapshot=!0;t.dirty=!0}return}finally{t.inflightViewers=null,t.inflight=!1}this.notifyScheduled(e,t,n,r)}notifyScheduled(e,t,n,r){if(this.opts.delivery!==`scheduled`||this.stopped)return;let i=t.prepared;if(!i||this.sessions.get(e)!==t)return;let a=[...t.viewers.entries()].filter(([,e])=>e.needsHistory&&!i.historyViewers.has(e)?(t.dirty=!0,!1):e.lastSentGen!==i.gen||e.forceSnapshot);if(a.length!==0){try{Wr(this.opts.onReady(e))}catch{this.log.error(`scheduled screen readiness failed`)}for(let[n,r]of a)!this.stopped&&this.sessions.get(e)===t&&t.prepared===i&&t.viewers.get(n)===r&&(r.lastSentGen!==i.gen||r.forceSnapshot)&&(r.skipped+=1);n>this.lastReadinessCycle&&(this.lastReadinessCycle=n,this.sessionOffset=r)}}processScreen(e,t,n,r,i){if(t.viewers.size===0)return;let a=this.opts.backend.capabilitiesOf?.(e)?.absoluteLines??this.opts.backend.capabilities.absoluteLines,o=n.lines.map(Rt),s=n.rows,c=0,l=!1,u=t.lastKeys.length===0||t.lastCols!==n.cols||t.lastRows!==n.rows;if(t.lastBackendScrollback===null)t.reported=n.scrollbackTotal;else{let e=n.scrollbackTotal-t.lastBackendScrollback;if(e<0)l=!0,u=!0,t.reported=n.scrollbackTotal;else if(e>=s)u=!0,t.reported+=e;else if(e>0)c=e,t.reported+=e;else if(!a&&!u&&Gr(o,t.lastKeys,0)>Hr*s){let e=Kr(o,t.lastKeys,s);e>0&&(c=e,t.reported+=e)}}t.lastBackendScrollback=n.scrollbackTotal,this.opts.backend.setReported?.(e,t.reported);let d=[];if(!u){for(let e=0;e<s;e++){let r=e+c<t.lastKeys.length?t.lastKeys[e+c]:void 0;(r===void 0||r!==o[e])&&d.push({i:e,line:n.lines[e]})}d.length>Hr*s&&(u=!0)}let f=!t.lastCursor||t.lastCursor.x!==n.cursor.x||t.lastCursor.y!==n.cursor.y,p=!u&&c===0&&d.length===0&&!f;p||(t.gen+=1);let m=p&&t.prepared?.gen===t.gen&&![...r].some(e=>e.needsHistory),h=this.opts.delivery===`scheduled`&&p&&t.prepared?.gen===t.gen?t.prepared:null;if(t.lastKeys=o,t.lastCols=n.cols,t.lastRows=n.rows,t.lastCursor=n.cursor,m)return;let g={sessionId:e,cursor:n.cursor,scrollbackTotal:t.reported,gen:t.gen},_=this.opts.maxEncodedBytes??262144,v,y,x,S=()=>(v??={type:`screen.snapshot`,...g,cols:n.cols,rows:n.rows,lines:n.lines,reset:l||void 0},v),C=()=>{if(!x&&(x={...S(),lines:n.lines.map(Ce),degraded:!0},!t.oversizeWarned)){let n=b(x).byteLength;n>_&&(this.log.warn(`screen.snapshot exceeds maxEncodedBytes even after stripStyles`,{session:e.slice(0,12),bytes:n,maxEncodedBytes:_}),t.oversizeWarned=!0)}return x},w=e=>e?C():(y??=b(S()).byteLength,y>_?C():S()),ee={type:`screen.diff`,...g,scroll:c,changed:d},te=Object.freeze({generation:t.gen,reported:t.reported,historyRequested:i}),ne=Object.freeze({...te,...n.historyCapture?{capture:n.historyCapture}:{}});t.prepared={gen:t.gen,diff:h?.diff??ee,forceSnapshotAll:h?.forceSnapshotAll??(u||p),snapshotFor:w,fullSnapshot:S,snapshotContext:ne,diffContext:h?.diffContext??te,historyViewers:r}}deliver(e,t){if(this.opts.delivery===`scheduled`)return!1;let n=t.prepared;if(!n||t.viewers.size===0)return!1;let r=()=>!this.stopped&&this.sessions.get(e)===t&&t.prepared===n,{gen:i,diff:a,forceSnapshotAll:o,snapshotFor:s}=n,c=!1,l=[...t.viewers.entries()],u=l.length,d=t.rrOffset%u,f=l.slice(d).concat(l.slice(0,d)).map((e,t)=>({entry:e,idx:t})).sort((e,t)=>t.entry[1].skipped-e.entry[1].skipped||e.idx-t.idx).map(e=>e.entry);t.rrOffset=(t.rrOffset+1)%u;for(let[e,l]of f){if(!r())break;if(t.viewers.get(e)!==l)continue;if(l.needsHistory&&!n.historyViewers.has(l)){t.dirty=!0;continue}if(l.lastSentGen===i&&!l.forceSnapshot)continue;if(!this.spend()){l.skipped+=1;continue}c=!0;let u=l.skipped>=3,d=l.lastSentGen===i-1&&!l.forceSnapshot&&!o&&!u;try{let i=d?a:s(u),o=this.opts.sink(e,i,d?n.diffContext:n.snapshotContext);if(!r())break;if(t.viewers.get(e)!==l)continue;if(o===!1){l.skipped+=1,l.forceSnapshot=!0;continue}}catch(n){if(!r())break;if(t.viewers.get(e)!==l)continue;l.skipped+=1,l.forceSnapshot=!0,this.log.error(`screen sink threw; will retry prepared generation`,{conn:e.slice(0,12),err:M(n)});continue}l.lastSentGen=i,l.forceSnapshot=!1,l.skipped=0,d||(l.needsHistory=!1)}return c}spend(){let e=this.opts.maxFramesPerSecond??40,t=this.now(),n=Math.max(0,t-this.budget.last);return this.budget.tokens=Math.min(e,this.budget.tokens+n*e/1e3),this.budget.last=t,this.budget.tokens<1?!1:(--this.budget.tokens,!0)}};function Wr(e){e===null||typeof e!=`object`&&typeof e!=`function`||new Promise(t=>t(e)).catch(()=>{})}function Gr(e,t,n){let r=0;for(let i=0;i<e.length;i++)t[i+n]!==e[i]&&r++;return r}function Kr(e,t,n){for(let r=1;r<=Math.min(n-1,16);r++){let i=n-r;if(i<=0)break;let a=0;for(let n=0;n<i;n++)e[n]===t[n+r]&&a++;if(a>=.8*i)return r}return 0}var qr=class{now;rate;onError;registrations=new Map;ownership={};pumping=!1;tokens=0;last;constructor(e){if(this.now=e.now,this.rate=e.maxFramesPerSecond??40,this.onError=e.onError,!Number.isSafeInteger(this.rate)||this.rate<=0)throw RangeError(`wire scheduler rate must be a positive safe integer`);this.last=this.readClock()}register(e,t){if(e.length===0)throw RangeError(`wire scheduler key must not be empty`);let n=Symbol(),r={identity:n,sendOne:t};return this.registrations.set(e,r),()=>this.remove(e,n)}pump(){if(this.pumping)return 0;this.pumping=!0;try{this.refill();let e=this.ownership,t=[...this.registrations],n=0;for(;t.length>0&&this.tokens>=1&&this.ownership===e;){let r=[];for(let[i,a]of t){if(this.tokens<1||this.ownership!==e)break;if(this.registrations.get(i)===a){this.registrations.delete(i),this.registrations.set(i,a),--this.tokens;try{let e=a.sendOne();if(e===!0)n++,r.push([i,a]);else if(e===!1)this.tokens+=1;else throw Jr(e),TypeError(`wire producer must return a synchronous boolean`)}catch(e){this.remove(i,a.identity);try{Jr(this.onError?.(e))}catch{}}}}t=r}return n}finally{this.pumping=!1}}nextBudgetAt(){return this.pumping||this.refill(),this.registrations.size===0||this.tokens>=1?null:this.last+(1-this.tokens)*1e3/this.rate}clear(){this.registrations.clear(),this.ownership={}}remove(e,t){this.registrations.get(e)?.identity===t&&this.registrations.delete(e)}readClock(){let e=this.now();if(!Number.isFinite(e))throw RangeError(`wire scheduler clock must be finite`);return e}refill(){let e=Math.max(this.last,this.readClock());this.tokens=Math.min(this.rate,this.tokens+(e-this.last)*this.rate/1e3),this.last=e}};function Jr(e){e===null||typeof e!=`object`&&typeof e!=`function`||new Promise(t=>t(e)).catch(()=>{})}var Yr=class{options;tracker;scheduler;entries=new Map;viewerOwners=new Map;attachTokens=new Map;started=!1;lifecycle=0;pumping=!1;timer=null;timerEpoch=0;nextViewer=0;constructor(e){if(!(e.backend instanceof ee))throw TypeError(`Service view backend must be a BackendRegistry`);if(!Number.isFinite(e.now()))throw RangeError(`Service view clock must be finite`);this.options={...e},this.scheduler=new qr({now:()=>this.options.now(),onError:()=>this.notifyError()}),this.tracker=new Ur({backend:this.options.backend,log:this.options.log,now:()=>this.options.now(),delivery:`scheduled`,onReady:()=>{this.pump()},onSessionGone:(e,t)=>this.sessionGone(e,t)})}start(){if(!this.started){if(!Number.isFinite(this.options.now()))throw RangeError(`Service view clock must be finite`);this.lifecycle++,this.started=!0,this.tracker.start()}}stop(){if(!this.started)return;this.lifecycle++,this.started=!1,this.clearTimer();let e=[...this.entries.values()];this.entries.clear();for(let t of e)t.unregister();this.tracker.stop();for(let t of e)this.dropView(t)}attach(e,t){if(!this.started)throw TypeError(`Service view coordinator is stopped`);if(typeof e!=`string`||e.length===0||e.length>256||!t)throw TypeError(`Invalid service view connection`);if(!this.entries.has(e)&&this.entries.size>=10)throw RangeError(`Too many service view connections`);let n=this.lifecycle,r={};this.attachTokens.set(e,r);try{let i=this.entries.get(e);i&&this.retire(i);let a={id:e,connection:{...t},view:null,closingView:null,unregister:()=>{},revision:0};if(this.started&&this.lifecycle===n&&this.attachTokens.get(e)===r&&!this.entries.has(e)){if(this.entries.size>=10)throw RangeError(`Too many service view connections`);this.entries.set(e,a),a.unregister=this.scheduler.register(e,()=>this.produce(a))}let o=this;return{get viewedSessionId(){return o.current(a)?a.view?.sessionId??null:null},receive:(e,t)=>this.receive(a,e,t),close:()=>this.retire(a)}}finally{this.attachTokens.get(e)===r&&this.attachTokens.delete(e)}}setIntervalMs(e){if(!Number.isFinite(e))throw TypeError(`Invalid service view interval`);this.tracker.setIntervalMs(e)}pump(){if(!this.started||this.pumping)return 0;this.pumping=!0;let e=0;try{if(!Number.isFinite(this.options.now()))throw RangeError(`Service view clock must be finite`);for(let e of[...this.entries.values()])this.current(e)&&e.view&&e.view.stream.tick();return this.started&&(e=this.scheduler.pump()),e}catch{return this.stop(),this.notifyError(),0}finally{this.pumping=!1,this.arm()}}current(e){return this.started&&this.entries.get(e.id)===e}receive(e,t,n){if(!this.current(e))return;let r=e.revision,i=e.view,a=null;try{if(Number.isSafeInteger(n)&&n>=1&&n<=A.envelopeBytes){let e=ce.safeParse(t);e.success&&(a=e.data)}}catch{}if(this.current(e)&&e.revision===r&&e.view===i){if(!a){i?.stream.terminate(`invalid-transfer`);return}if(a.type===`stream.subscribe`){let t=e.view;if(t&&t.subscriptionId===a.subscriptionId){t.sessionId!==a.sessionId&&t.stream.terminate(`invalid-transfer`);return}let n=++e.revision;if(this.dropView(e),!this.current(e)||e.revision!==n)return;let r={sessionId:a.sessionId,subscriptionId:a.subscriptionId,trackerKey:this.viewerKey(),stream:null};if(a.mode===`vt`&&this.openVtView(e,r,n))return;if(r.stream=new Lr({subscriptionId:r.subscriptionId,sessionId:r.sessionId,now:()=>this.options.now(),newTransferId:()=>this.options.newTransferId(),sendChunk:t=>this.current(e)&&e.view===r&&e.connection.sendChunk(t),sendControl:t=>this.current(e)&&(e.view===r||e.closingView===r)&&e.connection.sendControl(t),requestSnapshot:()=>{this.current(e)&&e.view===r&&this.tracker.forceSnapshot(r.trackerKey,r.sessionId)},onClosed:()=>{this.current(e)&&e.view===r&&this.dropView(e)},history:{read:(e,t)=>this.options.backend.getHistoryPage(e,t),onReady:()=>{this.current(e)&&e.view===r&&this.pump()}}}),!this.current(e)||e.revision!==n){r.stream.cancel();return}if(e.view=r,this.viewerOwners.set(r.trackerKey,{entry:e,view:r}),this.tracker.setViewed(r.trackerKey,r.sessionId,{history:!0,preparation:`bounded`}),!this.current(e)||e.revision!==n||e.view!==r)return;this.arm();return}if(i?.subscriptionId===a.subscriptionId){try{i.stream.receive(t,n)}catch{this.current(e)&&e.revision===r&&e.view===i&&i.stream.terminate(`invalid-transfer`)}this.pump()}}}openVtView(e,t,n){if(!this.options.backend.capabilitiesOf(t.sessionId)?.vtStream)return!1;let r;try{r=new Br({subscriptionId:t.subscriptionId,sessionId:t.sessionId,source:this.options.backend.openVtStream(t.sessionId),now:()=>this.options.now(),newTransferId:()=>this.options.newTransferId(),sendChunk:n=>this.current(e)&&e.view===t&&e.connection.sendChunk(n),sendControl:n=>this.current(e)&&(e.view===t||e.closingView===t)&&e.connection.sendControl(n),onReady:()=>{this.current(e)&&e.view===t&&this.pump()},onClosed:()=>{this.current(e)&&e.view===t&&this.dropView(e)}})}catch{return!1}return!this.current(e)||e.revision!==n?(r.cancel(),!0):(t.stream=r,e.view=t,this.viewerOwners.set(t.trackerKey,{entry:e,view:t}),r.start().catch(()=>r.terminate(`invalid-transfer`)),this.arm(),!0)}produce(e){if(!this.current(e))return!1;try{let t=e.view;return!t||(t.stream instanceof Lr&&t.stream.canOfferScreen()&&this.tracker.offerPrepared(t.trackerKey,(e,n)=>e.type!==`screen.snapshot`&&e.type!==`screen.diff`?!1:t.stream instanceof Lr&&t.stream.offer(e,n)),!this.current(e)||e.view!==t)?!1:t.stream.sendOne()}catch{throw this.retire(e),Error(`Service view producer failed`)}}viewerKey(){return`service-view-${++this.nextViewer}`}dropView(e){let t=e.view;t&&(e.view=null,this.viewerOwners.get(t.trackerKey)?.view===t&&this.viewerOwners.delete(t.trackerKey),this.tracker.dropViewer(t.trackerKey),t.stream.cancel())}retire(e){this.entries.get(e.id)===e&&(this.entries.delete(e.id),e.unregister(),this.dropView(e),this.arm())}sessionGone(e,t){let n=[];for(let r of t){let t=this.viewerOwners.get(r);t&&t.view.sessionId===e&&this.current(t.entry)&&t.entry.view===t.view&&(this.viewerOwners.delete(r),t.entry.view=null,n.push(t))}for(let{entry:e,view:t}of n)e.closingView=t,t.stream.terminate(`session-gone`),e.closingView===t&&(e.closingView=null);if(n.length>0)try{Xr(this.options.onSessionGone?.(e))}catch{}this.arm()}notifyError(){try{Xr(this.options.onError?.())}catch{}}clearTimer(){this.timerEpoch++,this.timer&&clearTimeout(this.timer),this.timer=null}arm(){if(this.clearTimer(),this.started)try{let e=[...this.entries.values()].flatMap(e=>e.view?[e.view]:[]);if(e.length===0)return;let t=this.options.now();if(!Number.isFinite(t))throw RangeError(`Service view clock must be finite`);let n=[this.scheduler.nextBudgetAt(),...e.map(e=>e.stream.nextDeadline())],r=25;for(let e of n)e!==null&&e>t&&(r=Math.min(r,e-t));let i=this.timerEpoch;this.timer=setTimeout(()=>{this.started&&i===this.timerEpoch&&(this.timer=null,this.pump())},Math.max(1,r))}catch{this.stop(),this.notifyError()}}};function Xr(e){e===null||typeof e!=`object`&&typeof e!=`function`||new Promise(t=>t(e)).catch(()=>{})}const Zr=`\\u2800-\\u28FF\\u25D0-\\u25D3\\u2722\\u2733\\u2736\\u273B\\u273D\\u00B7\\u2022*`,Qr=RegExp(`^[${Zr}][${Zr}\\uFE0F]*\\s+(?=\\S)`,`u`),$r=/^[⠀-⣿]/u,ei=/^v?\d+(?:\.\d+)+$/;function ti(e){return e.trim().replace(Qr,``)}function ni(e){let t=e?.trim()??``;return Qr.test(t)}function ri(e){let t=e?.trim().toLowerCase()??``;return/^claude(?:[- ]code)?$/.test(t)?`claude`:/^codex(?:[- ]cli)?$/.test(t)?`codex`:V(t,32)}function ii(e,t){let n=rr(e).toLowerCase();if(n===`claude`||n===`codex`)return n;if(n!==``&&n!==`node`&&!ei.test(n)||!ni(t))return;let r=t?.trim()??``;return $r.test(r)&&/ \| [^|]+$/.test(r)?`codex`:`claude`}function ai(e,t=P()){if(!e)return;let n=e=>e.replace(/[\\/]+$/,``);return t&&n(e)===n(t)?`~`:V(n(e).split(/[\\/]/).pop(),128)}const oi=new Set([...tr,`claude`,`codex`,`node`,`tmux`,`[tmux]`]);function si(e,t){let n=e.trim();if(n&&n!==t&&!n.endsWith(`[dead]`)&&!(oi.has(n.toLowerCase())||ei.test(n)))return V(n,128)}function ci(e){let t=rr(e).toLowerCase();return!t||nr.has(t)?!1:tr.has(t)||t===`claude`||t===`codex`||t===`node`||ei.test(t)}function li(e,t,n){if(!e)return;let r=ti(e.replace(/[\r\n\t]+/g,` `));if(n.command){let e=` (${n.command})`;r.endsWith(e)&&(r=r.slice(0,-e.length).trimEnd())}let i=/ \| ([^|]+)$/.exec(r);i&&(t===`codex`||i[1]?.trim()===n.project||i[1]?.trim()===n.folder)&&(r=r.slice(0,i.index).trimEnd());let a=V(r,256);if(!a)return;let o=a.toLowerCase();if(![t,`claude`,`claude code`,`codex`,...n.ignore??[]].some(e=>e.toLowerCase()===o))return a}function ui(e,t){return e.project===t.project&&e.agent?.kind===t.agent?.kind&&e.agent?.task===t.agent?.task}function di(e,t,n){let r={};return e&&(r.project=e),t&&(r.agent=n?{kind:t,task:n}:{kind:t}),r}function fi(e){let t=ai(e.cwd),n=V(e.project,128)??t,r=ii(e.processName,e.title);if(!r)return di(n,void 0);let i=rr(e.processName);return di(n,r,li(e.title,r,{project:n,folder:t,command:i||void 0,ignore:e.ignore}))}function pi(e,t){let n=ai(e.foreground_cwd??e.cwd??void 0),r=V(t,128)??n,i=ri(e.agent||e.display_agent||void 0);return i?di(r,i,li(e.label||e.terminal_title_stripped||e.terminal_title||void 0,i,{project:r,folder:n,ignore:e.display_agent?[e.display_agent]:[]})):di(r,void 0)}var mi=class{git;onChange;now;known=new Map;pending=new Set;constructor(e,t,n=Date.now){this.git=e,this.onChange=t,this.now=n}get size(){return this.known.size}lookup(e){if(!I(e)||e.length>1024)return;let t=this.known.get(e),n=this.now();return(!t||n<t.at||n-t.at>=3e4)&&this.refresh(e,t?.project),t?.project??void 0}refresh(e,t){if(this.pending.has(e)||this.pending.size>=16)return;this.pending.add(e);let n=new AbortController,r;try{r=this.git(e,n.signal)}catch{r=Promise.resolve(void 0)}r.catch(()=>void 0).then(n=>{let r=V(n?.repository,128)??null;for(this.known.delete(e);this.known.size>=256;){let e=this.known.keys().next().value;if(e===void 0)break;this.known.delete(e)}this.known.set(e,{project:r,at:this.now()}),r!==(t??null)&&this.onChange()}).finally(()=>{this.pending.delete(e),n.abort()})}};function hi(e,t=ut){let n=e=>b({type:`sessions`,list:e}).length<=t,r=[({agent:e,...t})=>e?{...t,agent:{kind:e.kind}}:t,({project:e,windowLabel:t,agent:n,...r})=>r,({project:e,windowLabel:t,agent:n,cwd:r,title:i,...a})=>({...a,title:Array.from(i).slice(0,gi).join(``)})];if(n(e))return{type:`sessions`,list:e};let i=e;for(let t of r)if(i=e.map(t),n(i))return{type:`sessions`,list:i};let a=0,o=i.length;for(;a<o;){let e=Math.ceil((a+o)/2);n(i.slice(0,e))?a=e:o=e-1}return{type:`sessions`,list:i.slice(0,a)}}const gi=64;function _i(e){return`no conn.hello within ${e/1e3}s; ignoring this link until one arrives`}var vi=class{o;relay;views;viewLeases=new Map;events;notifier;notificationState;notificationRelayCapable=!1;relayWithheldTurn=!1;pairing;links=new Map;connByFp=new Map;pairings;pairRequests=new Map;sessions=[];tick=null;sessionsDebounce=null;sessionsRefreshes=0;sessionsPublished=0;lastSeenSavedAt=new Map;log;localProcess;projects;stopped=!1;get configurationRevision(){return xe(this.o.config)}backendsKey=null;constructor(e){this.o=e,e={...e,config:Object.freeze(Je.parse(e.config))},this.o=e,this.log=e.log.child({unit:`agent`}),this.pairings=St(e.paths);let t=or();this.projects=new mi(t,()=>{this.stopped||this.scheduleSessions()}),e.registry.onSetupChanged(()=>{this.stopped||this.scheduleSessions()}),this.localProcess={pid:process.pid,agentVersion:e.appVersion,computerFp:e.fp,stateDir:tn(e.paths.dir),serviceInstance:e.serviceInstance??null};let n=e.relayUrlOverride??e.config.relayUrl;this.relay=e.relay??new Ir({relayUrl:n,fp:e.fp,identity:e.identity,name:e.config.computerName,appVersion:e.appVersion,log:e.log,...e.config.turn===!1&&{turn:!1}}),this.views=new Yr({backend:e.registry,log:e.log,now:()=>Date.now(),newTransferId:()=>r(p(16)),onSessionGone:()=>this.scheduleSessions()}),this.events=new $n({notifyMinCommandMs:e.config.notifyMinCommandMs,idleQuietMs:e.config.idleQuietMs,idleMinActiveMs:e.config.idleMinActiveMs}),this.notificationState=new mr(e.paths),this.notificationState.retain(new Set(this.pairings.map(e=>e.phoneFp)));let i=new ur({state:this.notificationState,computerFp:e.fp,computerName:()=>e.config.computerName,capable:()=>this.notificationRelayCapable,pairings:()=>this.pairings,facts:t=>e.registry.notificationFacts(t),git:t});this.notifier=new gr(e=>this.relay.sendCtrl(e),e.log,Date.now,e=>i.prepare(e)),this.pairing=new Cr({identity:e.identity,fp:e.fp,computerName:e.config.computerName,accent:e.config.accent,relayUrl:e.config.relayUrl,sendCtrl:e=>this.relay.sendCtrl(e),savePairing:e=>this.addPairing(e),confirm:e.confirm,pairingCount:()=>this.pairings.length,log:e.log,onClose:()=>this.o.onPairingClosed?.()}),this.relay.on(`auth-ok`,e=>{this.notificationRelayCapable=e.features?.includes(`notify-context-v1`)??!1,this.safe(`auth-ok`,()=>{this.views.setIntervalMs(Math.max(125,e.minFrameMs));let t=e.turnOff===!0;if(t&&!this.relayWithheldTurn)for(let e of[...this.links.values()])this.dropLinkFor(e.phoneFp);this.relayWithheldTurn=t,this.pairing.readvertise()})}),this.relay.on(`ctrl`,e=>this.safe(`ctrl`,()=>this.onCtrl(e))),this.relay.on(`e2e`,e=>this.safe(`e2e`,()=>this.onE2E(e))),this.relay.on(`down`,()=>{this.notificationRelayCapable=!1,this.safe(`down`,()=>{for(let e of[...this.links.values()])e.relayLost(),e.activeRoute!==`direct`&&this.dropLinkFor(e.phoneFp)})}),this.relay.on(`superseded`,()=>{this.safe(`superseded`,()=>{this.log.warn(`relay connection superseded by a newer agent instance; stopping`),this.stop(),this.o.onSuperseded?.()})}),e.registry.on(e=>this.safe(`backend-event`,()=>this.onBackendEvent(e))),this.events.on(`event`,e=>this.safe(`events-event`,()=>this.broadcast(e))),this.events.on(`ring`,e=>this.safe(`events-ring`,()=>{this.notifier.ring(e)}))}safe(e,t){try{let n=t();n&&typeof n.then==`function`&&n.catch(t=>this.logHandlerFailure(e,t))}catch(t){this.logHandlerFailure(e,t)}}logHandlerFailure(e,t){this.log.error(`handler failed`,{where:e,error:M(t)})}start(){this.stopped=!1,this.views.start(),this.relay.start(),this.tick=setInterval(()=>{this.safe(`tick`,()=>{this.events.tick(),this.pairing.tick(),this.sweepHandshakes()})},1e3),this.safe(`refresh-sessions`,()=>this.refreshSessions())}stop(){this.stopped=!0,this.tick&&clearInterval(this.tick),this.tick=null,this.sessionsDebounce&&clearTimeout(this.sessionsDebounce),this.sessionsDebounce=null,this.pairing.closeWindow();for(let e of this.links.values())this.closeLease(e),e.close();this.links.clear(),this.connByFp.clear(),this.views.stop(),this.pairRequests.clear(),this.relay.stop()}sweepHandshakes(){let e=Date.now();for(let t of this.links.values())t.helloOverdue(e)&&(t.dormant=!0,this.log.warn(_i(t.helloTimeoutMs),{phone:t.phoneFp.slice(0,8),conn:t.connId.slice(0,6)}))}get relayOnline(){return this.relay.online}get localStatus(){let e=this.o.registry.status();return{controlVersion:1,process:this.localProcess,backends:e,terminalReady:e.some(e=>e.connected)}}terminalSetup(){return this.o.registry.terminalSetup()}connectTerminal(e){let t=this.o.registry.connectTerminal(e);return t&&this.o.registry.notifySetupChanged(),t}get pairingList(){return this.pairings}get sessionList(){return this.sessions}get connectedPhones(){return[...this.links.values()].map(e=>({phoneFp:e.phoneFp,name:e.name,viewed:this.viewLeases.get(e)?.lease.viewedSessionId??null,transport:e.transportDiagnostics}))}linkForPhone(e){let t=this.connByFp.get(e);return t?this.links.get(t):void 0}openPairing(){return this.pairing.openWindow()}closePairing(){this.pairing.closeWindow()}get pairingOpen(){return this.pairing.tick(),this.pairing.isOpen}unpair(e){if(!e)return!1;let t=this.pairings.filter(t=>t.phoneFp.startsWith(e)||t.name===e);if(t.length>1)throw Error(`Ambiguous phone target; use a longer or complete fingerprint`);let n=t[0];return n?this.removePairing(n):!1}unpairExact(e){let t=this.pairings.find(t=>t.phoneFp===e);return t?this.removePairing(t):!1}raisePairProtocolFloor(e,t,n){let r=this.pairings.find(t=>t.phoneFp===e),i=St(this.o.paths).find(t=>t.phoneFp===e);if(!r||!i||t.length!==32)throw Error(`shellbell: pairing changed before protocol upgrade`);let a=T(i.kPair);if(a.length!==32||r.kPair!==i.kPair||r.ed25519Pub!==i.ed25519Pub||r.x25519Pub!==i.x25519Pub||!Sn(Buffer.from(a),Buffer.from(t)))throw Error(`shellbell: pairing changed before protocol upgrade`);let o=this.pairings.map(t=>t.phoneFp===e?{...t,minProtocolVersion:2}:t);this.pairings=Dt(this.o.paths,o),n!==this.linkForPhone(e)&&this.dropLinkFor(e)}removePairing(e){let t=this.pairings.filter(t=>t!==e);return this.pairings=Dt(this.o.paths,t),this.notificationState.forget(e.phoneFp),this.relay.sendCtrl({type:`unpair`,phoneFp:e.phoneFp}),this.pairRequests.delete(e.phoneFp),this.dropLinkFor(e.phoneFp),this.lastSeenSavedAt.delete(e.phoneFp),!0}dropLinkFor(e){let t=this.connByFp.get(e);if(t===void 0)return;let n=this.links.get(t);n&&(this.closeLease(n),n.close()),this.links.delete(t),this.connByFp.delete(e)}addPairing(e){let t=this.pairings.find(t=>t.phoneFp===e.phoneFp),n=Me(t,e),r=[...this.pairings.filter(t=>t.phoneFp!==e.phoneFp),n];this.pairings=Dt(this.o.paths,r),this.notificationState.forget(e.phoneFp),(t?.kPair!==e.kPair||t?.ed25519Pub!==e.ed25519Pub||t?.x25519Pub!==e.x25519Pub)&&(this.pairRequests.delete(e.phoneFp),this.dropLinkFor(e.phoneFp))}acceptsRelayUnpair(e,t){if(e.minProtocolVersion!==2)return!0;if(!t)return!1;try{return xt(t,{computerFp:this.o.fp,phoneFp:e.phoneFp,kPair:T(e.kPair),phoneEd25519Pub:T(e.ed25519Pub)})}catch{return!1}}forgetPairing(e,t){let n=this.pairings.find(t=>t.phoneFp===e);if(n&&!this.acceptsRelayUnpair(n,t))return this.log.warn(`ignored unsigned or invalid relay unpair for upgraded pairing`,{phone:e.slice(0,8)}),!1;let r=this.pairings.length,i=this.pairings.filter(t=>t.phoneFp!==e);return i.length!==r&&(this.pairings=Dt(this.o.paths,i)),this.notificationState.forget(e),this.pairRequests.delete(e),this.dropLinkFor(e),this.lastSeenSavedAt.delete(e),!0}async onCtrl(e){switch(e.type){case`unpaired`:if(e.phoneFps.length){let t=new Map(e.proofs?.map(e=>[e.phoneFp,e])),n=(e.proofs??[]).filter(t=>{if(!e.phoneFps.includes(t.phoneFp))return!1;let n=this.pairings.find(e=>e.phoneFp===t.phoneFp);return!n||this.acceptsRelayUnpair(n,t)}),r=e.phoneFps.filter(e=>this.pairings.some(n=>n.phoneFp===e&&this.acceptsRelayUnpair(n,t.get(e))));if(r.length){let e=this.pairings.filter(e=>!r.includes(e.phoneFp));this.pairings=Dt(this.o.paths,e);for(let e of r)this.notificationState.forget(e),this.pairRequests.delete(e),this.dropLinkFor(e);this.log.info(`applied verified or legacy unpair tombstones`,{count:r.length})}for(let e of n)this.relay.sendCtrl({type:`revocation-ack`,phoneFp:e.phoneFp,pairId:e.pairId})}this.relay.sendCtrl({type:`pairings-sync`,phones:this.pairings.slice(0,10).map(e=>({phoneFp:e.phoneFp,ed25519Pub:T(e.ed25519Pub),name:e.name,pairId:ft(T(e.kPair))}))});return;case`phones`:for(let t of e.connected)this.attach(t.phoneFp,t.connId,t.name);return;case`phone-connected`:this.attach(e.phoneFp,e.connId,e.name);return;case`phone-disconnected`:{let t=[...this.links.values()].find(t=>t.relayConnId===e.connId);if(!t||(t.relayLost(),t.activeRoute===`direct`))return;t.close(),this.closeLease(t),this.links.delete(t.connId),this.connByFp.get(t.phoneFp)===t.connId&&this.connByFp.delete(t.phoneFp);return}case`pairing-request`:await this.pairing.handleRequest(e);return;case`unpair`:this.forgetPairing(e.phoneFp,e.proof)&&e.proof&&this.relay.sendCtrl({type:`revocation-ack`,phoneFp:e.phoneFp,pairId:e.proof.pairId});return;case`error`:this.log.warn(`relay error`,{code:e.code===`too-many-pairings`?e.code:`unknown`});return;default:return}}attach(e,t,n){let r=this.pairings.find(t=>t.phoneFp===e);if(!r){this.log.warn(`relay announced an unknown phone; ignoring`,{phone:e.slice(0,8)});return}let i=this.linkForPhone(e);if(i&&!i.broken){i.relayConnId=t;return}this.dropLinkFor(e);let a=this.newV2Link(r,t,n);this.links.set(t,a),this.connByFp.set(e,t),r.lastSeenAt=new Date().toISOString();let o=Date.now();o-(this.lastSeenSavedAt.get(e)??0)>=6e4&&(this.lastSeenSavedAt.set(e,o),this.pairings=Dt(this.o.paths,this.pairings))}newV2Link(e,t,n){let r=T(e.kPair),i;return i=new Ar({phoneFp:e.phoneFp,connId:t,name:n,computerFp:this.o.fp,identity:this.o.identity,native:this.o.directFactory,iceServers:()=>this.relay.iceServers(),turn:this.o.config.turn!==!1,kPair:r,remoteStatic:T(e.x25519Pub),send:e=>this.relay.sendBoundedEnvelope(e),commitFloor:async()=>this.raisePairProtocolFloor(e.phoneFp,r,i),prepareReady:()=>this.pairRequests.get(e.phoneFp)?.idle!==!1,terminal:(e,t,n)=>this.safe(`v2-terminal`,()=>this.onInner(e,t,n)),ready:e=>this.onLinkReady(e),log:this.o.log}),i}onLinkReady(e){this.closeLease(e),this.ownsHandshake(e,e.handshakeGeneration)&&(this.installLease(e,e.handshakeGeneration),this.ownsHandshake(e,e.handshakeGeneration)&&(e.send(this.helloMessage()),this.ownsHandshake(e,e.handshakeGeneration)&&e.send(hi(this.sessions))))}helloMessage(e=this.o.registry.connected()){return{type:`hello`,features:[Re],agentVersion:this.o.appVersion,hostPlatform:er(process.platform),backends:e.filter(e=>v.includes(e.name)),launchableBackends:this.o.registry.launchable().filter(e=>v.includes(e)),backendCatalog:this.o.registry.catalog(),sessionLaunchTargets:this.o.registry.launchTargets(),sessionLaunchIssues:this.o.registry.launchIssues(),terminalSetup:this.o.registry.terminalSetup(),computerName:this.o.config.computerName,accent:this.o.config.accent}}onE2E(e){let t=this.connByFp.get(e.from);return(t===void 0?void 0:this.links.get(t))?.handleEnvelope(e)}closeLease(e){let t=this.viewLeases.get(e);t&&(this.viewLeases.delete(e),t.lease.close())}installLease(e,t){let n=null,r=()=>this.ownsHandshake(e,t)&&this.viewLeases.get(e)?.lease===n;if(n=this.views.attach(e.connId,{sendChunk:t=>r()&&e.send(t),sendControl:t=>r()&&e.send(t)}),!this.ownsHandshake(e,t)){n.close();return}this.viewLeases.set(e,{generation:t,lease:n})}ownsHandshake(e,t){return this.links.get(e.connId)===e&&e.handshaken&&!e.broken&&e.handshakeGeneration===t}async onInner(e,t,n){let r=e.handshakeGeneration;if(this.ownsHandshake(e,r)){if(t.type===`notification.enroll`){this.notificationState.enroll(e.phoneFp,t.generation)&&this.ownsHandshake(e,r)&&e.send({type:`notification.enrolled`,generation:t.generation});return}if(t.type===`stream.subscribe`||t.type===`stream.ack`||t.type===`stream.history.get`||t.type===`stream.cancel`||t.type===`stream.refresh`||t.type===`stream.chunk`||t.type===`stream.error`){let i=this.viewLeases.get(e);i?.generation===r&&i.lease.receive(t,n);return}if(!(`reqId`in t)){await this.execute(e,t,r);return}if(_r(t)){let n=this.pairRequests.get(e.phoneFp);n||(n=new vr,this.pairRequests.set(e.phoneFp,n));let i=await n.run(t.reqId,async()=>{let n=await this.execute(e,t,r);if(!n)throw Error(`paired request produced no outcome`);return n});this.ownsHandshake(e,r)&&e.send(i)}}}async execute(e,t,n){let r=this.o.registry,i=()=>this.ownsHandshake(e,n),a=(e,t={})=>({type:`ack`,reqId:e,ok:!0,...t}),o=(e,t)=>({type:`ack`,reqId:e,ok:!1,error:t});try{switch(t.type){case`input.line`:return this.log.info(`input`,{kind:`line`,len:t.text.length}),await r.sendText(t.sessionId,`${t.text}\r`,i),a(t.reqId);case`input.text`:return this.log.info(`input`,{kind:`text`,len:t.text.length}),await r.sendText(t.sessionId,t.text,i),a(t.reqId);case`input.key`:return await r.sendText(t.sessionId,Ze(t.key),i),a(t.reqId);case`input.terminal`:return await r.sendInput(t.sessionId,t.data,i),a(t.reqId);case`input.paste`:return await r.paste(t.sessionId,t.text,t.submit,i),a(t.reqId);case`input.mouse`:return await r.clickMouse(t.sessionId,t,i),a(t.reqId);case`session.create`:{let e=await r.createSession(t.in);return this.scheduleSessions(),a(t.reqId,{sessionId:e})}case`session.focus`:{let e=r.capabilitiesOf(t.sessionId);if(e===null)throw new k(t.sessionId);return e.focus?(await r.focus(t.sessionId),a(t.reqId)):o(t.reqId,`unsupported`)}default:return null}}catch(e){let n=e instanceof De?e.message:e instanceof k?`session-gone`:e instanceof E?`unsupported`:e instanceof C?`bad-window`:e instanceof ke?e.code:`failed`;return this.log.warn(`inner message failed`,{type:t.type,error:n,err:M(e)}),`reqId`in t?o(t.reqId,n):null}}broadcast(e){for(let t of this.links.values())t.send(e)}onBackendEvent(e){switch(this.events.onBackendEvent(e),e.type){case`screen-changed`:return;case`session-removed`:this.notifier.forget(e.sessionId),this.events.forget(e.sessionId),this.scheduleSessions();return;case`layout-changed`:case`session-added`:case`focus-changed`:case`title-changed`:case`command-start`:case`command-end`:case`prompt`:case`agent-state`:this.scheduleSessions();return;default:return}}scheduleSessions(){this.sessionsDebounce||=setTimeout(()=>{this.sessionsDebounce=null,this.refreshSessions()},100)}broadcastHelloIfBackendProfilesChanged(){let e=this.o.registry.connected(),t=JSON.stringify([this.o.registry.catalog().map(({capabilities:e,...t})=>({...t,capabilities:Object.entries(e).sort(([e],[t])=>e.localeCompare(t))})),this.o.registry.launchTargets(),this.o.registry.launchIssues(),this.o.registry.terminalSetup()]);if(t===this.backendsKey)return;let n=this.backendsKey===null;this.backendsKey=t,!n&&this.broadcast(this.helloMessage(e))}async refreshSessions(){let e=++this.sessionsRefreshes;try{let t=await this.o.registry.listSessions();if(e<this.sessionsPublished)return;this.sessionsPublished=e,this.sessions=t.map(e=>{let t=this.o.registry.projectFolder(e.id),n=t?this.projects.lookup(t):void 0,r=n?{...e,project:n}:e,i=this.events.stateOf(r.id);return i===`unknown`?r:{...r,state:i}}),this.broadcast(hi(this.sessions))}catch(e){this.log.warn(`listSessions failed`,{err:M(e)})}finally{this.broadcastHelloIfBackendProfilesChanged()}}};const yi=[0,7,2],bi=`Install Herdr: curl -fsSL https://herdr.dev/install.sh | sh, then start it with "herdr".`,xi=`Upgrade Herdr to 0.7.2 or newer: curl -fsSL https://herdr.dev/install.sh | sh, then restart it.`;var H=class extends Error{code;constructor(e,t){super(`herdr ${e}: ${t}`),this.code=e,this.name=`HerdrError`}};const Si=new Set([`not_found`,`pane_not_found`,`stale_pane_target`]),Ci=new Set([`invalid_request`,`unsupported`,`unknown_method`,`method_not_found`]);function wi(e,t){let n=/^\s*v?(\d+)\.(\d+)\.(\d+)/.exec(e);if(!n)return null;let r=[Number(n[1]),Number(n[2]),Number(n[3])];for(let e=0;e<3;e++){let n=r[e],i=t[e];if(n!==i)return n>i}return!0}function Ti(e=process.env,t=P()){let n=e.HERDR_SOCKET_PATH;if(n)return n;let r=e.XDG_CONFIG_HOME?L(e.XDG_CONFIG_HOME,`herdr`):L(t,`.config`,`herdr`),i=e.HERDR_SESSION;return i?L(r,`sessions`,i,`herdr.sock`):L(r,`herdr.sock`)}function Ei(e,t,n){let r=e.code??``;return r===`ENOENT`||r===`ECONNREFUSED`||r===`EACCES`||r===`EPERM`?new H(`unavailable`,`cannot reach the herdr socket at ${n} (${r})`):new H(`socket`,`${t}: ${e.message}`)}function Di(e,t,n,r=1048576){let i=new On(`utf8`),a=``;e.on(`data`,e=>{a+=i.write(e);let o=a.indexOf(`
5
+ `);for(;o>=0;){let e=a.slice(0,o);a=a.slice(o+1),e.trim()&&t(e),o=a.indexOf(`
6
+ `)}Buffer.byteLength(a,`utf8`)>r&&(a=``,n())})}var Oi=class{opts;log;nextId=1;constructor(e){this.opts=e,this.log=e.log.child({unit:`herdr`})}get socketPath(){return this.opts.socketPath??Ti()}request(e,t={}){let n=`sb${this.nextId++}`,r=this.opts.requestTimeoutMs??5e3,i=this.socketPath;return new Promise((a,o)=>{let s=!1,c=wn({path:i}),l=(e,t)=>{s||(s=!0,clearTimeout(u),c.destroy(),e?o(e):a(t))},u=setTimeout(()=>l(new H(`timeout`,`${e} did not answer within ${r} ms`)),r);c.on(`connect`,()=>{c.write(`${JSON.stringify({id:n,method:e,params:t})}\n`)}),Di(c,t=>{let r;try{r=JSON.parse(t)}catch{l(new H(`malformed`,`${e} answered with a non-JSON line`));return}if(r.id!==void 0&&r.id!==n&&this.log.debug(`herdr echoed a different id`,{method:e}),r.error){l(new H(r.error.code||`error`,r.error.message||e));return}if(r.result===void 0||r.result===null){l(new H(`malformed`,`${e} answered without a result`));return}l(null,r.result)},()=>l(new H(`overflow`,`${e} answered with an oversized line`)),8388608),c.on(`error`,t=>l(Ei(t,e,i))),c.on(`close`,()=>l(new H(`closed`,`herdr closed the connection before answering ${e}`)))})}subscribe(e,t){let n=`sb${this.nextId++}`,r=this.opts.requestTimeoutMs??5e3,i=this.socketPath;return new Promise((a,o)=>{let s=wn({path:i}),c=!1,l=!1,u=!1,d={close(){u=!0,s.destroy()}},f=e=>{c||(clearTimeout(m),s.destroy(),o(e))},p=e=>{l||(l=!0,t.onEnd(u?`closed`:e))},m=setTimeout(()=>f(new H(`timeout`,`events.subscribe was not acknowledged`)),r);s.on(`connect`,()=>{s.write(`${JSON.stringify({id:n,method:`events.subscribe`,params:{subscriptions:e}})}\n`)}),Di(s,e=>{let n;try{n=JSON.parse(e)}catch{this.log.warn(`undecodable herdr stream line`,{chars:e.length});return}if(!c){if(n.error){f(new H(n.error.code||`error`,n.error.message||`events.subscribe`));return}let e=n.result?.type;if(e!==`subscription_started`){f(new H(`malformed`,`events.subscribe answered ${e}`));return}c=!0,clearTimeout(m),a(d);return}if(typeof n.event==`string`){let e=n.data&&typeof n.data==`object`?n.data:{};t.onEvent({event:n.event,data:e})}},()=>{c?(s.destroy(),p(`overflow`)):f(new H(`overflow`,`events.subscribe line too long`))}),s.on(`error`,e=>{c?p(`error`):f(Ei(e,`events.subscribe`,i))}),s.on(`close`,()=>{if(!c){f(new H(`closed`,`herdr closed the connection before acknowledging the stream`));return}p(`eof`)})})}async ping(){let e;try{e=await this.request(`ping`,{})}catch(e){let t=e instanceof Error?e.message:String(e);throw new j(t,bi)}let t=typeof e.version==`string`?e.version:``,n=wi(t,yi);if(n===!1)throw new j(`herdr ${t} is older than 0.7.2 (session.snapshot and scroll metrics landed there)`,xi);return n===null&&this.log.warn(`herdr reported an unparseable version; relying on the feature probe`),this.log.debug(`herdr ping ok`,{version:/^\d{1,4}\.\d{1,4}\.\d{1,4}$/.test(t)?t:`unknown`,protocol:typeof e.protocol==`number`&&Number.isSafeInteger(e.protocol)&&e.protocol>=0?e.protocol:`unknown`}),e}};function ki(e){if(e===``)return[];let t=e.split(`
7
+ `);return t.length>1&&t[t.length-1]===``&&t.pop(),t.map(Yn)}function Ai(e,t){if(e.length>t)return e.slice(e.length-t);let n=e.slice();for(;n.length<t;)n.push(ge());return n}function ji(e){return e.r.reduce((e,t)=>e+(t.n??Wn(t.t)),0)}function Mi(e,t){let n=Math.max(0,t-1);for(let t=e.length-1;t>=0;t--){let r=e[t];if(r.r.some(e=>e.t.trim().length>0))return{x:Math.min(n,ji(r)),y:t}}return{x:0,y:0}}function Ni(e){let t=Math.max(1,e.rows),n=Math.max(1,e.cols),r=Ai(ki(e.text),t);return{cols:n,rows:t,cursor:Mi(r,n),lines:r,scrollbackTotal:Math.max(0,e.scrollMax)}}function Pi(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Fi(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>=0}function Ii(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>0}function Li(e,t,n){if(!Pi(e)||e.type!==`pane_info`||!Pi(e.pane))return null;let r=e.pane;if(typeof r.pane_id!=`string`||r.pane_id.length===0||r.pane_id!==t||typeof r.terminal_id!=`string`||r.terminal_id.length===0||r.terminal_id!==n||!Fi(r.revision)||!Pi(r.scroll))return null;let i=r.scroll;return!Fi(i.offset_from_bottom)||!Fi(i.max_offset_from_bottom)||!Ii(i.viewport_rows)||i.offset_from_bottom>i.max_offset_from_bottom||i.max_offset_from_bottom>2**53-1-i.viewport_rows?null:{paneId:r.pane_id,terminalId:r.terminal_id,revision:r.revision,history:i.max_offset_from_bottom,viewportRows:i.viewport_rows,offset:i.offset_from_bottom}}function Ri(e,t){if(!Ii(t.rows)||!Ii(t.cols)||t.minRows!==void 0&&(!Fi(t.minRows)||t.minRows>t.rows)||typeof t.paneId!=`string`||t.paneId.length===0||t.source!==`visible`&&t.source!==`recent`||!Pi(e)||e.type!==`pane_read`||!Pi(e.read))return null;let n=e.read;if(typeof n.pane_id!=`string`||n.pane_id.length===0||n.pane_id!==t.paneId||n.source!==t.source||n.format!==`ansi`||typeof n.text!=`string`||typeof n.truncated!=`boolean`)return null;let r=ki(n.text);return r.length<(t.minRows??t.rows)||r.length>t.rows||r.some(e=>ji(e)>t.cols)?null:r}function zi(e,t){let{visible:n,historyRows:r,viewportRows:i,requestedRows:a}=t;if(n.length===0||n.length>i)return null;let o=i-n.length,s=Ri(e,{paneId:t.paneId,source:`recent`,cols:t.cols,rows:a,minRows:Math.max(n.length,Math.min(a,r+i)-o)});if(!s||!kn(s.slice(-n.length),n))return null;let c=r+n.length-s.length;return c>=0?{from:c,lines:s}:null}const Bi=An(zt),Vi={iTerm:`iTerm2`},Hi=/\/([^/]+)\.app\/Contents\/MacOS\//;function Ui(e){let t=new Map;for(let n of e.split(`
8
+ `)){let e=/^\s*(\d+)\s+(\d+)\s+(.*)$/.exec(n);e&&t.set(Number(e[1]),{ppid:Number(e[2]),args:e[3]})}return t}async function Wi(){if(process.platform===`darwin`)try{let{stdout:e}=await Bi(`/bin/ps`,[`-axww`,`-o`,`pid=,ppid=,args=`],{timeout:2e3,maxBuffer:8388608});return Ui(e)}catch{return}}function Gi(e,t){let n=t.get(e)?.ppid;for(let e=0;n!==void 0&&n>1&&e<32;e++){let e=t.get(n);if(!e)return;let r=Hi.exec(e.args)?.[1];if(r)return Vi[r]??r;n=e.ppid}}function Ki(e){let[t,...n]=e.trim().split(/\s+/);if(t&&un(t)===`herdr`){if(n.length===0)return``;if(n[0]===`--session`&&n.length===2)return n[1];if(n.length===1&&n[0].startsWith(`--session=`))return n[0].slice(10);if(n[0]===`session`&&n[1]===`attach`&&n.length===3)return n[2]}}function qi(e,t,n=process.env){let r=new Set;for(let[i,a]of e){let o=Ki(a.args);if(o===void 0||Ti({XDG_CONFIG_HOME:n.XDG_CONFIG_HOME,...o?{HERDR_SESSION:o}:{}})!==t)continue;let s=Gi(i,e);s&&r.add(s)}return[...r].sort((e,t)=>e.localeCompare(t)).slice(0,4)}async function Ji(e){let t=await Wi();return t&&qi(t,e)}const Yi=Xi();function Xi(){let e={enter:`enter`,tab:`tab`,"shift-tab":`shift+tab`,esc:`esc`,backspace:`backspace`,up:`up`,down:`down`,left:`left`,right:`right`};for(let t of Object.keys(vt))/^ctrl-[a-z]$/.test(t)?e[t]=`ctrl+${t.slice(5)}`:/^f([1-9]|1[0-2])$/.test(t)&&(e[t]=t);return e}const Zi=Qi();function Qi(){let e=new Map([[`\r`,`enter`],[`
9
+ `,`enter`],[` `,`tab`]]);for(let[t,n]of Object.entries(vt)){let r=Yi[t];r&&!e.has(n)&&e.set(n,r)}return e}function $i(e){return Zi.get(e)}const ea=[`.local/bin`,`.cargo/bin`];function ta(e,t=process.env,n=e=>{try{return Vt(e,N.X_OK),rn(e).isFile()}catch{return!1}}){let r=t.HOME||P(),i=I(r)?ea.map(e=>L(r,e)):[];return[...t.PATH?.split(dn)??[],...i].map(t=>pn(t,e)).find(n)}const na=An(zt);function ra(e=process.env,t){return ta(`herdr`,e,t)}async function ia(e={}){let t=e.platform??process.platform,n;try{if(t===`darwin`)n=await oa(e);else if(t===`linux`)n=sa(e);else return}catch{return}let r=[...new Set(n)],i=e.executable??ca;return r.length===1&&I(r[0])&&i(r[0])?r[0]:void 0}function aa(e){return e.length===2&&un(e[0])===`herdr`&&e[1]===`server`}async function oa(e){let t=e.ps??(async e=>(await na(`/bin/ps`,e,{timeout:2e3,maxBuffer:8388608})).stdout),n=(await t([`-x`,`-ww`,`-o`,`pid=,args=`])).split(`
10
+ `).flatMap(e=>{let t=/^\s*(\d+)\s+(?:.*\/)?herdr server\s*$/.exec(e);return t?[t[1]]:[]});return n.length===0?[]:(await t([`-ww`,`-o`,`comm=`,`-p`,n.join(`,`)])).split(`
11
+ `).map(e=>e.trim()).filter(e=>un(e)===`herdr`)}function sa(e){let t=e.procRoot??`/proc`,n=e.uid??process.getuid?.(),r=[];for(let e of $t(t))if(/^\d+$/.test(e))try{if(n!==void 0&&rn(L(t,e)).uid!==n)continue;let i=Zt(L(t,e,`cmdline`),`latin1`).split(`\0`);if(i.at(-1)===``&&i.pop(),!aa(i))continue;let a=en(L(t,e,`exe`));a.endsWith(` (deleted)`)||r.push(a)}catch{}return r}function ca(e){try{return Vt(e,N.X_OK),rn(e).isFile()}catch{return!1}}const la=An(zt);var ua=class{opts;executable;issue;env;active=new Map;generation=0;constructor(e){this.opts=e,this.env={...e.env??process.env,HERDR_SOCKET_PATH:e.socketPath}}get available(){return this.executable!==void 0}get verifiedExecutable(){return this.executable===void 0?void 0:pn(this.executable)}get unavailableReason(){return this.executable===void 0?this.issue:void 0}async configure(e){this.close();let t=this.generation;if(!e||wi(e,[0,9,3])!==!0){this.issue=`Update Herdr to 0.9.3 or newer to open Herdr sessions from your phone${e?` (this computer runs ${e.replace(/^v/,``)})`:``}.`;return}let n=this.opts.executable===void 0&&this.defaultSocket()?await(this.opts.findRunningServer??ia)():void 0;if(t!==this.generation)return;let r=this.opts.executable?[this.opts.executable]:[...new Set([n,ra(this.env)])].filter(e=>e!==void 0);if(r.length===0){this.issue=`Herdr is running, but Shellbell can't find the herdr program. Install it in ~/.local/bin, /opt/homebrew/bin or /usr/local/bin.`;return}let i=e.replace(/^v/,``),a;for(let e of r){let n;try{let t=this.opts.readVersion?await this.opts.readVersion(e):(await la(e,[`--version`],{env:this.env,timeout:3e3,maxBuffer:4096})).stdout;n=/\b(?:herdr\s+)?v?(\d+\.\d+\.\d+(?:-[\w.-]+)?)/.exec(t)?.[1]}catch{if(t!==this.generation)return;a??=`Shellbell couldn't run the herdr program. Reinstall Herdr on this computer.`;continue}if(t!==this.generation)return;if(n===i){this.executable=e;return}a??=n?`The herdr program (${n}) and the running Herdr (${i}) are different versions. Quit Herdr and open it again.`:`Shellbell couldn't read the herdr program's version. Reinstall Herdr on this computer.`}this.issue=a}defaultSocket(){let{HERDR_SOCKET_PATH:e,HERDR_SESSION:t,...n}=this.env;return pn(this.opts.socketPath)===pn(Ti(n))}close(){this.generation++,this.executable=void 0,this.issue=void 0;for(let e of this.active.values())e();this.active.clear()}async click(e,t,n){let r=this.executable;if(!r||!n()||this.active.has(e)||this.active.size>=4)throw new E(`mouse control unavailable`);if(t.column>=t.cols||t.row>=t.rows)throw new E(`mouse coordinates`);let i=this.generation,a=[`terminal`,`session`,`control`,e,`--cols`,String(t.cols),`--rows`,String(t.rows)],o=this.opts.spawn?this.opts.spawn(r,a,this.env):Bt(r,a,{env:this.env,stdio:[`pipe`,`pipe`,`pipe`]});await new Promise((r,a)=>{let s=!1,c=!1,l=Buffer.alloc(0),u=t=>{s||(s=!0,clearTimeout(f),this.active.delete(e),o.kill(`SIGKILL`),t?a(t):r())},d=()=>u(c?Error(`mouse delivery unknown`):new E(`mouse control unavailable`)),f=setTimeout(d,this.opts.timeoutMs??3e3);this.active.set(e,d),o.on(`error`,d),o.stdin.on(`error`,d),o.stderr.resume(),o.stdout.on(`data`,e=>{if(s||c)return;if(l=Buffer.concat([l,e]),l.length>1048576)return d();let r=l.indexOf(10);if(r<0)return;let a;try{a=JSON.parse(l.subarray(0,r).toString(`utf8`))}catch{return d()}if(a.type!==`terminal.frame`||a.width!==t.cols||a.height!==t.rows||i!==this.generation||!n())return d();c=!0,l=Buffer.alloc(0);let u={type:`terminal.mouse`,button:t.button,column:t.column,row:t.row,modifiers:t.modifiers};o.stdin.end(`${[{...u,action:`down`},{...u,action:`up`},{type:`terminal.release`}].map(e=>JSON.stringify(e)).join(`
12
+ `)}\n`)}),o.on(`close`,e=>u(e===0&&c?void 0:c?Error(`mouse delivery unknown`):new E(`mouse control unavailable`)))})}},da=class{options;run;timer;busy=!1;watched=new Set;observations=new Map;watchedMs;backgroundMs;constructor(e){this.options=e,this.watchedMs=Math.max(125,e.watchedMs??125),this.backgroundMs=Math.max(this.watchedMs,e.backgroundMs??1e3)}start(){this.timer&&clearTimeout(this.timer),this.timer=void 0,this.run={};for(let e of this.observations.values())e.due=0;this.schedule()}stop(){this.run=void 0,this.timer&&clearTimeout(this.timer),this.timer=void 0,this.observations.clear()}setWatched(e){let t=new Set(e);for(let e of t)if(!this.watched.has(e)){let t=this.observations.get(e);t&&(t.due=0)}this.watched=t}schedule(){this.run&&!this.timer&&(this.timer=setTimeout(()=>{this.timer=void 0,this.pass().catch(()=>this.reportFailure())},this.watchedMs),this.timer.unref?.())}async pass(){let e=this.run;if(e){if(this.busy){this.schedule();return}this.busy=!0;try{let t=this.options.targets(),n=new Set(t.map(e=>e.id));for(let e of this.observations.keys())n.has(e)||this.observations.delete(e);let r=Date.now(),i=t.map(e=>{let t=this.observations.get(e.id);return(!t||t.identity!==e.identity)&&(t={identity:e.identity,digest:t?.digest,due:0},this.observations.set(e.id,t)),{target:e,observation:t}}).filter(({observation:e})=>e.due<=r).sort((e,t)=>e.observation.due-t.observation.due).slice(0,16),a=0;await Promise.all(Array.from({length:Math.min(4,i.length)},async()=>{for(;this.run===e&&a<i.length;){let t=i[a++];if(!t)return;let{target:n,observation:r}=t;try{let t=await n.read();if(this.run!==e||!n.current())continue;let i=bn(`sha256`).update(JSON.stringify([t.cols,t.rows,t.cursor,t.lines,t.scrollbackTotal])).digest(`hex`);r.digest!==void 0&&r.digest!==i&&this.options.changed(n.id),r.digest=i}catch{this.run===e&&n.current()&&this.reportFailure()}finally{r.due=Date.now()+(this.watched.has(n.id)?this.watchedMs:this.backgroundMs)}}}))}finally{this.busy=!1,this.schedule()}}}reportFailure(){try{this.options.failed()}catch{}}};function fa(e,t){return typeof t==`number`?`${e};5;${t}`:`${e};2;${t[0]};${t[1]};${t[2]}`}function pa(e){let t=[`0`];return e.b&&t.push(`1`),e.f&&t.push(`2`),e.i&&t.push(`3`),e.u&&t.push(`4`),e.s&&t.push(`9`),e.fg!==void 0&&t.push(fa(38,e.fg)),e.bg!==void 0&&t.push(fa(48,e.bg)),`\x1b[${t.join(`;`)}m`}function ma(e){let t=``;for(let n of e.r)t+=pa(n)+n.t.replace(/[\x00-\x1f\x7f]/g,``);return`${t}\x1b[0m`}const ha=1e3;var ga=class extends Error{},_a=class extends Cn{opts;log;generation=0;historyLines=ha;timer=null;busy=!1;seedWanted=!1;ended=!1;failures=0;seedFailures=0;shown;constructor(e){super(),this.opts=e,this.log=e.log.child({backend:`herdr`,stream:`vt`})}async start(e){e!==void 0&&(this.historyLines=e),await this.reseed()}async reseed(e){e!==void 0&&(this.historyLines=e),this.seedWanted=!0,await this.run()}close(){this.end(void 0)}async run(){if(!(this.ended||this.busy)){this.busy=!0,this.timer&&clearTimeout(this.timer),this.timer=null;try{this.seedWanted?await this.seed():await this.poll(),this.failures=0}catch(e){e instanceof k||e instanceof H&&Si.has(e.code)?this.end(`pane-gone`):!(e instanceof ga)&&++this.failures>=20&&(this.log.debug(`herdr vt stream failed`,{error:e instanceof Error?e.name:`unknown`}),this.end(`failed`))}finally{this.busy=!1,this.ended||(this.timer=setTimeout(()=>void this.run(),this.opts.pollMs??200),this.timer.unref?.())}}}current(){let e=this.opts.pane();if(!e)throw this.end(`pane-gone`),new ga;return e}async facts(e){let t=Li(await this.opts.request(`pane.get`,{pane_id:e.paneId}),e.paneId,e.terminalId);if(!t)throw new ga;return t}async frame(e,t){let n=await this.facts(e);if(n.offset!==0)throw new ga;let r=Ri(await this.opts.request(`pane.read`,{pane_id:e.paneId,source:`visible`,format:`ansi`}),{paneId:e.paneId,source:`visible`,rows:e.rows,cols:e.cols,minRows:0});if(!r)throw new ga;let i=t(n),a=[];if(i>0&&r.length>0){let t=Math.min(ha,i+r.length),n=Ri(await this.opts.request(`pane.read`,{pane_id:e.paneId,source:`recent`,format:`ansi`,lines:t}),{paneId:e.paneId,source:`recent`,rows:t,cols:e.cols,minRows:r.length});if(!n||!ba(n.slice(-r.length),r))throw new ga;a=n.slice(0,-r.length)}let o=await this.facts(e);if(!ya(n,o))throw new ga;return{facts:o,visible:r,above:a}}async seed(){let e=this.current(),t;try{t=await this.frame(e,t=>Math.min(e.agent&&va(e.agentStatus)?this.historyLines:t.history,this.historyLines))}catch(e){throw e instanceof ga&&++this.seedFailures>=50&&this.end(`unsettled`),e}this.seedFailures=0;let n=xa(t.visible,e.rows),r=Sa(t.visible,e.cols),i=[...t.above.map(ma),...n];this.seedWanted=!1,this.generation++,this.shown={cols:e.cols,rows:e.rows,history:t.facts.history,screen:n,cursor:r,idle:va(e.agentStatus)},this.emit(`seed`,{generation:this.generation,cols:e.cols,rows:e.rows,data:`\x1bc${i.join(`\r
13
+ `)}${r}`})}async poll(){let e=this.shown,t=this.current();if(!e||t.cols!==e.cols||t.rows!==e.rows){this.seedWanted=!0;return}let n=va(t.agentStatus);if(t.agent&&n&&!e.idle){this.seedWanted=!0;return}e.idle=n;let r=!1,i=await this.frame(t,n=>{let i=n.history-e.history;return r=i<0||i+t.rows>1e3,r?0:i});if(r||i.above.length!==i.facts.history-e.history){this.seedWanted=!0;return}let a=i.above,o=xa(i.visible,t.rows),s=Sa(i.visible,t.cols),c=``;if(a.length>0)c=`\x1b[H${[...a.map(ma),...o].map(e=>`\x1b[2K${e}`).join(`\r
14
+ `)}`;else for(let t=0;t<o.length;t++)o[t]!==e.screen[t]&&(c+=`\x1b[${t+1};1H\x1b[2K${o[t]}`);(c||s!==e.cursor)&&(c+=s),e.history=i.facts.history,e.screen=o,e.cursor=s,c&&this.emit(`bytes`,new TextEncoder().encode(c),this.generation)}end(e){this.ended||(this.ended=!0,this.timer&&clearTimeout(this.timer),this.timer=null,e&&this.emit(`end`,e))}};function va(e){return e===`idle`||e===`done`}function ya(e,t){return e.revision===t.revision&&e.history===t.history&&e.viewportRows===t.viewportRows&&e.offset===t.offset}function ba(e,t){return e.length===t.length&&e.every((e,n)=>ma(e)===ma(t[n]))}function xa(e,t){return Array.from({length:t},(t,n)=>ma(e[n]??{r:[]}))}function Sa(e,t){let{x:n,y:r}=Mi(e,t);return`\x1b[${r+1};${n+1}H`}const Ca=1e3,wa=1e3;function Ta(e){let t=[{type:`pane.created`},{type:`pane.closed`},{type:`pane.exited`},{type:`pane.updated`},{type:`pane.focused`},{type:`pane.moved`},{type:`pane.agent_detected`},{type:`tab.created`},{type:`tab.closed`},{type:`tab.focused`},{type:`tab.renamed`},{type:`tab.moved`},{type:`workspace.created`},{type:`workspace.updated`},{type:`workspace.closed`},{type:`workspace.focused`},{type:`workspace.renamed`},{type:`workspace.moved`},{type:`workspace.reordered`},{type:`layout.updated`}];for(let n of e)t.push({type:`pane.agent_status_changed`,pane_id:n}),t.push({type:`pane.scroll_changed`,pane_id:n});return t}const Ea=new Set([`working`,`blocked`,`idle`,`done`,`unknown`]);function Da(e){return typeof e==`string`&&Ea.has(e)?e:`unknown`}const Oa={working:`running`,blocked:`blocked`,idle:`finished`,done:`finished`,unknown:`unknown`};function ka(e){let t=e.foreground_cwd??e.cwd,n=t?t.split(`/`).filter(Boolean).pop():void 0;return e.display_agent||e.agent||e.title||e.terminal_title_stripped||n||`Pane`}function Aa(e){return M(e)}function ja(e){return typeof e==`string`?e:void 0}function Ma(e){return e&&typeof e==`object`?e:void 0}function Na(e,t){return e.length===t.size&&e.every(e=>t.has(e))}function Pa(e,t){return e.paneId===t.paneId&&e.terminalId===t.terminalId&&e.revision===t.revision&&e.history===t.history&&e.viewportRows===t.viewportRows&&e.offset===t.offset}var Fa=class{opts;name=`herdr`;get capabilities(){return{subscribe:!0,prompts:!1,createSession:!0,terminalInput:!0,terminalPaste:!0,focus:!0,history:!0,absoluteLines:!1,vtStream:!0,...this.mouse.available?{mouseClick:!0}:{}}}mouse;panes=new Map;historyEpochs=new Map;historyCaptures=new WeakMap;byPaneId=new Map;order=[];workspaces=new Set;focusedWorkspace=null;eventSeq=0;handlers=new Set;log;client;screenObserver;active=null;subscribedPaneIds=new Set;closed=!0;retryTimer=null;syncTimer=null;syncBusy=!1;wantSnapshot=!1;wantResubscribe=!1;shownIn=[];hostAppTimer=null;hostAppGeneration=0;constructor(e){this.opts=e,this.client=e.client,this.mouse=e.mouse??new ua({socketPath:this.client.socketPath}),this.log=e.log.child({backend:`herdr`}),this.screenObserver=new da({watchedMs:e.screenPollMs,backgroundMs:e.backgroundScreenPollMs,targets:()=>{let e=this.active;return this.closed||!e?.live?[]:[...this.panes].map(([t,n])=>({id:t,identity:n.paneId,current:()=>{let r=this.panes.get(t);return!this.closed&&this.active===e&&r?.paneId===n.paneId&&r.rows===n.rows&&r.cols===n.cols},read:()=>this.getScreen(t)}))},changed:e=>{this.historyEpochs.delete(e),this.emit({type:`screen-changed`,sessionId:e})},failed:()=>this.log.warn(`herdr screen observation failed`)})}get isConnected(){return!this.closed&&this.active!==null}async connect(){this.closed=!1;let e=await this.client.ping();await this.mouse.configure(e.version);let t=[];try{t=Ia((await this.client.request(`session.snapshot`,{}))?.snapshot).panes.map(e=>e.pane_id)}catch(e){throw this.unavailable(e)}try{await this.openStream(t)}catch(e){throw e instanceof j?e:this.unavailable(e)}this.hostAppTimer&&clearTimeout(this.hostAppTimer),this.hostAppGeneration++,this.refreshHostApps()}async refreshHostApps(){this.hostAppTimer=null;let e=this.hostAppGeneration,t=await(this.opts.hostApps??Ji)(this.client.socketPath).catch(()=>void 0)??[];this.closed||e!==this.hostAppGeneration||(t.join(`
15
+ `)!==this.shownIn.join(`
16
+ `)&&(this.shownIn=t,this.emit({type:`layout-changed`})),this.hostAppTimer=setTimeout(()=>void this.refreshHostApps(),this.opts.hostAppPollMs??1e4),this.hostAppTimer.unref?.())}unavailable(e){if(e instanceof j)return e;let t=e instanceof Error?e.message:String(e);return e instanceof H&&Ci.has(e.code)?new j(`herdr does not support session.snapshot (${t})`,xi):e instanceof H&&e.code===`malformed`?new j(`herdr answered session.snapshot with junk (${t})`,xi):new j(t,bi)}async close(){this.closed=!0,this.mouse.close(),this.screenObserver.stop(),this.retryTimer&&clearTimeout(this.retryTimer),this.retryTimer=null,this.syncTimer&&clearTimeout(this.syncTimer),this.syncTimer=null,this.hostAppTimer&&clearTimeout(this.hostAppTimer),this.hostAppTimer=null,this.hostAppGeneration++,this.shownIn=[];let e=this.active;this.active=null,e&&(e.cancelled=!0,e.stream?.close()),this.panes.clear(),this.historyEpochs.clear(),this.byPaneId.clear(),this.order=[],this.wantSnapshot=!1,this.wantResubscribe=!1,this.syncBusy=!1,this.subscribedPaneIds.clear(),this.handlers.clear()}on(e){return this.handlers.add(e),()=>this.handlers.delete(e)}async notificationFacts(e){let t=this.panes.get(e);if(t&&this.isConnected)return ir({sessionId:e,cwd:t.cwd,title:t.title,sessionLabel:`Herdr · Window ${t.windowNumber} · Tab ${t.tabIndex+1} · Pane ${t.paneIndex+1}`},void 0,`reported`)}async listSessions(){return this.order.map(e=>this.panes.get(e)).filter(e=>e!==void 0).map(e=>this.toInfo(e))}async getScreen(e,t){let n=this.pane(e),r=t?.history?this.captureEpoch(n):void 0;n.scrollStale&&await this.refreshScroll(n);let i=r&&this.ownsHistory(r)?await this.historyFacts(r):void 0,a=await this.call(e,`pane.read`,{pane_id:n.paneId,source:`visible`,format:`ansi`}),o=Ni({text:a?.read?.text??``,rows:n.rows,cols:n.cols,scrollMax:n.scrollMax});if(!r||!this.ownsHistory(r)||!i||!(`facts`in i))return o;let s=Ri(a,{paneId:r.paneId,source:`visible`,rows:r.rows,cols:r.cols,minRows:0});if(!s||i.facts.offset!==0)return o;let c=await this.historyFacts(r);if(!this.ownsHistory(r)||!(`facts`in c))return o;if(!Pa(i.facts,c.facts))return this.revokeHistory(r),o;r.certified=c.facts;let l=Object.freeze({});return this.historyCaptures.set(l,{epoch:r,facts:c.facts,visible:s}),o.historyCapture=l,o}async getHistoryPage(t,n){if(e(n),n.signal.aborted)return{status:`cancelled`};this.pane(t);let r=this.historyCaptures.get(n.capture);if(!r||r.epoch.sessionId!==t)return{status:`unavailable`,reason:`unanchored`};let{epoch:i,facts:a}=r,o=()=>n.signal.aborted?{status:`cancelled`}:this.ownsHistory(i)?void 0:{status:`reset`},s=o();if(s)return s;if(n.reported<a.history||n.reported>2**53-1-a.viewportRows)return{status:`unavailable`,reason:`unanchored`};let c=await this.historyFacts(i),l=o();if(l)return l;if(!(`facts`in c))return{status:`unavailable`,reason:c.reason};if(!Pa(a,c.facts))return this.revokeHistory(i),{status:`reset`};let u=n.reported-a.history,d;if(n.before<=u)d={status:`boundary`,reason:n.before===u?`end`:`truncated`,oldestAvailable:u};else{let e=Math.max(n.before-n.count,u),t=n.reported+r.visible.length-Ca;if(n.before<=t)return{status:`unavailable`,reason:`fetch-window`};let s=Math.min(Ca,a.viewportRows+(n.reported-e));if(!Number.isSafeInteger(s)||s<1||s>Ca)return{status:`unavailable`,reason:`fetch-window`};let c;try{c=await this.client.request(`pane.read`,{pane_id:i.paneId,source:`recent`,format:`ansi`,lines:s})}catch(e){return o()??{status:`unavailable`,reason:e instanceof H&&e.code===`agent_not_idle`?`busy`:`changed`}}let l=o();if(l)return l;let f=zi(c,{paneId:i.paneId,cols:i.cols,viewportRows:a.viewportRows,historyRows:a.history,requestedRows:s,visible:r.visible});if(!f)return{status:`unavailable`,reason:`changed`};let p=u+f.from,m=Math.max(e,p);if(m>=n.before)return{status:`unavailable`,reason:`fetch-window`};d={status:`page`,from:m,to:n.before,oldestAvailable:u,lines:f.lines.slice(m-p,n.before-p)}}let f=await this.historyFacts(i);return o()||(`facts`in f?Pa(a,f.facts)?(i.certified=f.facts,d):(this.revokeHistory(i),{status:`reset`}):{status:`unavailable`,reason:f.reason})}captureEpoch(e){if(this.closed||!this.active||this.active.cancelled||e.scrollOffset!==void 0&&e.scrollOffset!==0)return;let t=this.historyEpochs.get(e.terminalId);if(t&&this.ownsHistory(t))return t;let n={sessionId:e.terminalId,paneId:e.paneId,stream:this.active,revision:e.revision,cols:e.cols,rows:e.rows};return this.historyEpochs.set(e.terminalId,n),n}ownsHistory(e){let t=this.panes.get(e.sessionId);return!this.closed&&this.active===e.stream&&!e.stream.cancelled&&this.historyEpochs.get(e.sessionId)===e&&t?.paneId===e.paneId&&t.cols===e.cols&&t.rows===e.rows&&t.revision===e.revision}revokeHistory(e){this.historyEpochs.get(e.sessionId)===e&&this.historyEpochs.delete(e.sessionId)}async historyFacts(e){try{let t=await this.client.request(`pane.get`,{pane_id:e.paneId}),n=Li(t,t?.pane?.pane_id,t?.pane?.terminal_id);return n?(this.ownsHistory(e)&&(n.paneId!==e.paneId||n.terminalId!==e.sessionId||n.viewportRows!==e.rows||e.certified&&!Pa(e.certified,n))&&this.revokeHistory(e),{facts:n}):{reason:`changed`}}catch(e){return{reason:e instanceof H&&e.code===`agent_not_idle`?`busy`:`changed`}}}async getHistory(e,t,n){let r=this.pane(e),i=this.active,{scrollMax:a,rows:o,cols:s}=r,c=Math.max(0,a-t),l=Math.min(Ca,c+n+o),u=await this.call(e,`pane.read`,{pane_id:r.paneId,source:`recent`,format:`ansi`,lines:l}),d=()=>new j(`History temporarily unavailable`,`Retry history after output settles.`),f=Ri(await this.call(e,`pane.read`,{pane_id:r.paneId,source:`visible`,format:`ansi`}),{paneId:r.paneId,source:`visible`,rows:o,cols:s,minRows:0});if(!f)throw d();let p=zi(u,{paneId:r.paneId,cols:s,viewportRows:o,historyRows:a,requestedRows:l,visible:f});if(!p||t>0&&p.from>=t||this.closed||this.active!==i||i?.cancelled||this.panes.get(e)!==r||r.rows!==o||r.cols!==s||r.scrollMax!==a)throw d();let m=Math.max(0,a-c-p.from),h=Math.max(0,m-n),g=p.lines.slice(h,m);return{lines:g,oldestAvailable:p.from===0&&h===0?Math.max(0,t-g.length):0}}async sendText(e,t){let n=this.pane(e),r=$i(t);if(r){this.log.debug(`herdr key`),await this.call(e,`pane.send_keys`,{pane_id:n.paneId,keys:[r]});return}if(this.log.debug(`herdr text`,{len:t.length}),t.endsWith(`\r`)||t.endsWith(`
17
+ `)){let r=t.slice(0,-1);r&&await this.call(e,`pane.send_text`,{pane_id:n.paneId,text:r}),await this.call(e,`pane.send_keys`,{pane_id:n.paneId,keys:[`enter`]});return}await this.call(e,`pane.send_text`,{pane_id:n.paneId,text:t})}async clickMouse(e,t){let n=this.pane(e),r=this.active,i=()=>{let i=this.panes.get(e);return!this.closed&&this.active===r&&r?.live===!0&&i?.paneId===n.paneId&&i.cols===t.cols&&i.rows===t.rows&&(i.scrollOffset??0)===0};if(!this.mouse.available||!i())throw new E(`mouse input unavailable`);let a=Ia((await this.client.request(`session.snapshot`,{}))?.snapshot),o=a.panes.find(t=>t.terminal_id===e),s=a.layouts.flatMap(e=>e.panes).find(e=>e.pane_id===n.paneId)?.rect;if(!i()||o?.pane_id!==n.paneId||o.scroll?.offset_from_bottom!==0||s?.width!==t.cols||s.height!==t.rows)throw new E(`mouse grid changed`);await this.mouse.click(e,t,i)}async sendInput(e,t){let n=this.pane(e);await this.call(e,`pane.send_text`,{pane_id:n.paneId,text:t})}async paste(e,t,n){let r=this.pane(e);await this.call(e,`pane.send_input`,{pane_id:r.paneId,text:t,keys:n?[`Enter`]:[]})}async createSession(e){if(e.kind===`split`){let t=this.pane(e.sessionId),n=ja((await this.client.request(`pane.split`,{target_pane_id:t.paneId,direction:e.direction===`vertical`?`right`:`down`,focus:!1}))?.pane?.terminal_id);if(!n)throw Error(`herdr pane.split returned no terminal_id`);return this.scheduleSync(`snapshot`),n}if(e.windowId!==void 0&&!this.workspaces.has(e.windowId))throw new C(e.windowId);let t=e.windowId??this.focusedWorkspace??[...this.workspaces][0];if(!t)return this.createWorkspaceSession();let n=ja((await this.client.request(`tab.create`,{workspace_id:t,focus:!1}))?.root_pane?.terminal_id);if(!n)throw Error(`herdr tab.create returned no terminal_id`);return this.scheduleSync(`snapshot`),n}async createWorkspaceSession(){return(await this.createWorkspace()).terminalId}async createWorkspace(){let e=await this.client.request(`workspace.create`,{cwd:P(),focus:!1}),t=ja(e?.root_pane?.terminal_id);if(!t)throw Error(`herdr workspace.create returned no terminal_id`);this.scheduleSync(`snapshot`);let n=ja(e?.workspace?.workspace_id)??ja(e?.root_pane?.workspace_id);return n?{terminalId:t,workspaceId:n}:{terminalId:t}}async closeWorkspace(e){await this.client.request(`workspace.close`,{workspace_id:e}),this.scheduleSync(`snapshot`)}get terminalSocketPath(){return this.client.socketPath}get terminalAttachExecutable(){return this.isConnected?this.mouse.verifiedExecutable:void 0}get terminalAttachIssue(){return this.isConnected&&this.terminalAttachExecutable===void 0?this.mouse.unavailableReason:void 0}async focus(e){let t=this.pane(e);await this.call(e,`pane.focus`,{pane_id:t.paneId})}setWatched(e){this.screenObserver.setWatched(e)}emit(e){for(let t of this.handlers)try{t(e)}catch(e){this.log.warn(`event handler failed`,{error:Aa(e)})}}openVtStream(e){return this.pane(e),new _a({request:(t,n)=>this.call(e,t,n),pane:()=>{let t=this.closed?void 0:this.panes.get(e);return t&&{paneId:t.paneId,terminalId:t.terminalId,cols:t.cols,rows:t.rows,agentStatus:t.agentStatus,agent:t.naming.agent!==void 0}},log:this.opts.log})}pane(e){let t=this.panes.get(e);if(!t)throw new k(e);return t}async call(e,t,n){try{return await this.client.request(t,n)}catch(t){throw t instanceof H&&Si.has(t.code)?(this.scheduleSync(`snapshot`),new k(e)):t}}toInfo(e){return{id:e.terminalId,backend:`herdr`,title:e.title,cwd:e.cwd,...e.naming,...e.windowLabel?{windowLabel:e.windowLabel}:{},cols:Math.max(1,e.cols),rows:Math.max(1,e.rows),windowId:e.workspaceId,windowNumber:e.windowNumber,tabId:e.tabId,tabIndex:e.tabIndex,paneIndex:e.paneIndex,isFocusedOnMac:e.focused,state:Oa[e.agentStatus],...this.shownIn.length>0?{shownIn:[...this.shownIn]}:{}}}sortOrder(){this.order=[...this.panes.values()].sort((e,t)=>e.windowNumber-t.windowNumber||e.tabIndex-t.tabIndex||e.paneIndex-t.paneIndex||e.paneId.localeCompare(t.paneId)).map(e=>e.terminalId)}async openStream(e){let t=e??[...this.byPaneId.keys()],n={cancelled:!1,live:!1,buffer:[],stream:null,overflowed:!1},r=await this.client.subscribe(Ta(t),{onEvent:e=>{if(!n.cancelled){if(n.live){this.onEvent(e);return}if(n.buffer.length<wa){n.buffer.push(e);return}n.overflowed||(n.overflowed=!0,this.log.warn(`herdr bootstrap event buffer overflowed; dropping events`,{max:wa})),this.scheduleSync(`snapshot`)}},onEnd:e=>{!n.cancelled&&this.active===n&&this.onStreamEnd(e)}});if(n.stream=r,this.closed){n.cancelled=!0,r.close();return}let i=this.active;this.active=n,this.historyEpochs.clear(),this.subscribedPaneIds=new Set(t),i&&(i.cancelled=!0,i.stream?.close());try{await this.refreshSnapshot()}catch(e){throw n.cancelled=!0,r.close(),this.active===n&&(this.active=null),e}if(n.cancelled||this.closed||this.active!==n)return;n.live=!0;let a=n.buffer;n.buffer=[];for(let e of a)this.onEvent(e);this.screenObserver.start(),this.emit({type:`layout-changed`})}async refreshSnapshot(){let e=this.eventSeq,t=this.active;try{let n=await this.client.request(`session.snapshot`,{});if(this.closed||this.active!==t)return;this.applySnapshot(Ia(n?.snapshot),e)}catch(e){if(this.closed||this.active!==t)return;throw e}}scheduleSync(e){this.closed||(e===`resubscribe`?this.wantResubscribe=!0:this.wantSnapshot=!0,!this.syncTimer&&(this.syncTimer=setTimeout(()=>{this.syncTimer=null,this.runSync().catch(e=>{this.log.warn(`herdr sync crashed`,{error:Aa(e)})})},this.opts.syncDebounceMs??250),this.syncTimer.unref?.()))}async runSync(){if(!(this.syncBusy||this.closed)){this.syncBusy=!0;try{for(;(this.wantResubscribe||this.wantSnapshot)&&!this.closed&&this.active;){let e=this.wantResubscribe;this.wantResubscribe=!1,this.wantSnapshot=!1,e?await this.openStream():await this.refreshSnapshot()}}catch(e){this.log.warn(`herdr sync failed`,{error:Aa(e)}),this.onStreamEnd(`sync-failed`)}finally{this.syncBusy=!1}}}onStreamEnd(e){if(this.closed)return;this.screenObserver.stop();let t=this.active;this.active=null,this.historyEpochs.clear(),t&&(t.cancelled=!0,t.stream?.close()),this.log.info(`herdr stream ended`,{reason:e});let n=[...this.order];this.panes.clear(),this.byPaneId.clear(),this.order=[],this.subscribedPaneIds.clear();for(let e of n)this.emit({type:`session-removed`,sessionId:e});this.emit({type:`layout-changed`}),this.scheduleReconnect()}scheduleReconnect(){if(this.closed||this.retryTimer)return;let e=this.opts.reconnectMs??2e3;this.retryTimer=setTimeout(()=>{this.retryTimer=null,this.connect().catch(e=>{this.log.debug(`herdr reconnect failed`,{error:Aa(e)}),this.scheduleReconnect()})},e),this.retryTimer.unref?.()}applySnapshot(e,t=0){let n=new Map,r=new Map,i=new Set;for(let t of e.workspaces??[]){i.add(t.workspace_id),n.set(t.workspace_id,t.number??0);let e=V(typeof t.label==`string`?t.label:void 0,128);e&&r.set(t.workspace_id,e)}let a=new Map;for(let t of e.tabs??[])a.set(t.tab_id,t.number??0);let o=La(e.layouts??[]),s=this.panes,c=new Map,l=new Map,u=[],d=new Set,f=new Set;for(let p of e.panes){let m=p.terminal_id??p.pane_id,h=s.get(m),g=o.get(p.pane_id),_=Da(p.agent_status),v=h?.statusSeq??0,y=v>t,b=y?h?.agentStatus??_:_,x=p.scroll?.viewport_rows,S=ka(p),C=p.foreground_cwd??p.cwd,w=r.get(p.workspace_id),ee=pi(p,w);h&&(h.title!==S||h.cwd!==C||h.windowLabel!==w||!ui(h.naming,ee))&&d.add(m);let te=y?h?.revision??(typeof p.revision==`number`?p.revision:0):typeof p.revision==`number`?p.revision:h?.revision??0;!y&&h&&typeof p.revision==`number`&&typeof h.revision==`number`&&p.revision!==h.revision&&f.add(m),c.set(m,{terminalId:m,paneId:p.pane_id,workspaceId:p.workspace_id,tabId:p.tab_id,title:S,cwd:C,naming:ee,windowLabel:w,cols:g?.cols??h?.cols??80,rows:Math.max(1,g?.rows??x??h?.rows??24),rowsFromRect:g!==void 0,windowNumber:n.get(p.workspace_id)??0,tabIndex:a.get(p.tab_id)??0,paneIndex:g?.order??0,focused:p.focused===!0||p.pane_id===e.focused_pane_id,agentStatus:b,scrollMax:p.scroll?.max_offset_from_bottom??h?.scrollMax??0,scrollOffset:p.scroll?.offset_from_bottom??h?.scrollOffset,scrollStale:h?.scrollStale??!1,scrollFetchedAt:h?.scrollFetchedAt??0,statusSeq:v,revision:te}),l.set(p.pane_id,m),i.add(p.workspace_id),!y&&h?.agentStatus!==b&&u.push({id:m,state:b,agent:p.display_agent??p.agent})}let p=[...s.keys()].filter(e=>!c.has(e)),m=new Set([...c.keys()].filter(e=>!s.has(e))),h=new Map(u.map(e=>[e.id,e]));for(let[e,t]of this.historyEpochs){let n=s.get(e),r=c.get(e);(!r||r.paneId!==t.paneId||r.cols!==t.cols||r.rows!==t.rows||r.revision!==t.revision||r.scrollMax!==n?.scrollMax||r.scrollOffset!==n?.scrollOffset)&&this.revokeHistory(t)}this.panes=c,this.byPaneId=l,this.workspaces=i,this.focusedWorkspace=e.focused_workspace_id??null,this.sortOrder();for(let e of p)this.emit({type:`session-removed`,sessionId:e});for(let e of this.order)m.has(e)&&this.emit({type:`session-added`,sessionId:e});let g=Date.now();for(let e of this.order){let t=h.get(e);t&&this.emit({type:`agent-state`,sessionId:t.id,state:t.state,agent:t.agent,at:g})}for(let e of this.order)d.has(e)&&this.emit({type:`title-changed`,sessionId:e});for(let e of this.order)f.has(e)&&this.emit({type:`screen-changed`,sessionId:e});(p.length>0||m.size>0)&&this.emit({type:`layout-changed`}),Na([...l.keys()],this.subscribedPaneIds)||this.scheduleSync(`resubscribe`)}onEvent(e){try{this.handleEvent(e)}catch(e){this.log.warn(`herdr event handling failed`,{error:Aa(e)})}}handleEvent(e){let t=e.event.replaceAll(`.`,`_`),n=e.data;switch(t){case`pane_created`:case`pane_closed`:case`pane_exited`:case`pane_moved`:case`pane_agent_detected`:case`tab_created`:case`tab_closed`:case`tab_renamed`:case`tab_moved`:case`workspace_created`:case`workspace_updated`:case`workspace_closed`:case`workspace_renamed`:case`workspace_moved`:case`workspace_reordered`:this.historyEpochs.clear(),this.scheduleSync(`snapshot`);return;case`pane_updated`:{let e=n.pane,t=ja(e?.pane_id);if(!t)return;let r=this.paneByPaneId(t);if(!r){this.scheduleSync(`snapshot`);return}if(typeof e?.revision==`number`&&typeof r.revision==`number`&&e.revision<=r.revision)return;this.historyEpochs.delete(r.terminalId),(ka(e)!==r.title||(e?.foreground_cwd??e?.cwd)!==r.cwd||!ui(pi(e,r.windowLabel),r.naming))&&this.scheduleSync(`snapshot`);let i=Ma(e?.scroll);typeof i?.offset_from_bottom==`number`&&(r.scrollOffset=i.offset_from_bottom),i&&typeof i.max_offset_from_bottom==`number`&&(r.scrollMax=i.max_offset_from_bottom,!r.rowsFromRect&&typeof i.viewport_rows==`number`&&(r.rows=Math.max(1,i.viewport_rows)),r.scrollStale=!1),r.statusSeq=++this.eventSeq;let a=Da(e?.agent_status);r.agentStatus!==a&&(r.agentStatus=a,this.emit({type:`agent-state`,sessionId:r.terminalId,state:a,at:Date.now()})),typeof e?.revision==`number`&&e.revision!==r.revision&&(r.revision=e.revision,this.emit({type:`screen-changed`,sessionId:r.terminalId}));return}case`pane_agent_status_changed`:if(!this.paneByPaneId(ja(n.pane_id)))return;this.scheduleSync(`snapshot`);return;case`pane_scroll_changed`:{let e=this.paneByPaneId(ja(n.pane_id));if(!e)return;this.historyEpochs.delete(e.terminalId);let t=Ma(n.scroll);if(typeof t?.offset_from_bottom==`number`&&(e.scrollOffset=t.offset_from_bottom),t&&typeof t.max_offset_from_bottom==`number`){e.scrollMax=t.max_offset_from_bottom,!e.rowsFromRect&&typeof t.viewport_rows==`number`&&(e.rows=Math.max(1,t.viewport_rows)),e.scrollStale=!1;return}e.scrollStale=!0;return}case`layout_updated`:{this.historyEpochs.clear();let e=n.layout;if(e){for(let[t,n]of La([e])){let e=this.paneByPaneId(t);e&&(e.cols=n.cols,e.rows=Math.max(1,n.rows),e.rowsFromRect=!0,e.paneIndex=n.order)}this.sortOrder()}this.emit({type:`layout-changed`});return}case`pane_focused`:{let e=this.paneByPaneId(ja(n.pane_id));if(e)for(let t of this.panes.values())t.focused=t===e;else this.scheduleSync(`snapshot`);this.emit({type:`focus-changed`});return}case`tab_focused`:case`workspace_focused`:this.emit({type:`focus-changed`});return;default:this.log.debug(`unhandled herdr event`);return}}paneByPaneId(e){let t=e?this.byPaneId.get(e):void 0;return t?this.panes.get(t):void 0}async refreshScroll(e){let t=Date.now(),n=this.opts.scrollRefreshMs??1e3;if(!(t-e.scrollFetchedAt<n)){e.scrollFetchedAt=t;try{let t=(await this.client.request(`pane.get`,{pane_id:e.paneId}))?.pane?.scroll;this.panes.get(e.terminalId)===e&&t&&(t.max_offset_from_bottom!==e.scrollMax||t.viewport_rows!==e.rows||t.offset_from_bottom!==e.scrollOffset)&&this.historyEpochs.delete(e.terminalId),typeof t?.offset_from_bottom==`number`&&(e.scrollOffset=t.offset_from_bottom),t&&typeof t.max_offset_from_bottom==`number`&&(e.scrollMax=t.max_offset_from_bottom,!e.rowsFromRect&&typeof t.viewport_rows==`number`&&(e.rows=Math.max(1,t.viewport_rows))),e.scrollStale=!1}catch(e){this.log.debug(`herdr scroll refresh failed`,{error:Aa(e)})}}}};function Ia(e){let t=e;if(!t||typeof t!=`object`||!Array.isArray(t.panes))throw new H(`malformed`,`session.snapshot returned no panes array`);return t}function La(e){let t=new Map;for(let n of e)[...n.panes??[]].sort((e,t)=>(e.rect?.y??0)-(t.rect?.y??0)||(e.rect?.x??0)-(t.rect?.x??0)).forEach((e,n)=>{t.set(e.pane_id,{cols:Math.max(1,e.rect?.width??80),rows:Math.max(1,e.rect?.height??24),order:n})});return t}function Ra(e=process.env){return ra(e)!==void 0}async function za(e={}){let t=e.log??We({stdout:!1}),n=e.client??new Oi({log:t,socketPath:e.socketPath,requestTimeoutMs:3e3});if(!Ut(n.socketPath))return{name:`herdr`,ok:!0,detail:(e.herdrOnPath??Ra)()?`installed but not running (optional)`:`not installed (optional)`};let r;try{r=await n.ping()}catch(e){return e instanceof j?{name:`herdr`,ok:!1,detail:e.message,fix:e.hint}:{name:`herdr`,ok:!1,detail:String(e),fix:bi}}try{Ia((await n.request(`session.snapshot`,{}))?.snapshot)}catch(e){return{name:`herdr`,ok:!1,detail:e instanceof H&&Ci.has(e.code)?`herdr ${r.version??`?`} has no session.snapshot`:`session.snapshot failed: ${e instanceof Error?e.message:String(e)}`,fix:xi}}return{name:`herdr`,ok:!0,detail:`v${r.version??`?`} protocol ${r.protocol??`?`}`}}function Ba(e){let t=e.log.child({unit:`herdr-start`}),n=new Fa({client:e.client??new Oi({log:e.log,socketPath:e.socketPath}),log:e.log,...e.backendOptions}),r=null,i=!1,a=!1,o=!1;e.registry.add(n);let s=e.registry.registerSetupReporter(`herdr`,e=>{if(!e)return{issue:Ra()?`not-running`:`not-installed`};let t=n.terminalAttachIssue;return t?{issue:`limited`,detail:t}:{}}),c=()=>{i||r||(r=setTimeout(()=>{r=null,l()},e.retryMs??1e4),r.unref?.())},l=async()=>{if(!(i||n.isConnected)){try{await n.connect()}catch(n){t.debug(`herdr not available`,{error:M(n)}),e.onUnavailable&&!o&&n instanceof j&&(o=!0,e.onUnavailable()),c();return}try{if(i)return;if(t.info(`herdr connected`),e.onConnected&&!a){a=!0;let t=await n.listSessions().catch(()=>[]);e.onConnected(t.length)}}catch(e){t.debug(`herdr post-connect setup failed`,{error:M(e)})}}};return l(),{stop(){s(),i=!0,r&&clearTimeout(r),r=null,n.close(),e.registry.remove(`herdr`)}}}const Va=An(zt);var U=class extends Error{kind;constructor(e,t){super(e),this.kind=t,this.name=`ITerm2AuthError`}};const Ha=12e4;async function Ua(e,t=Ha){let n=Date.now()+t;if((await Wa(`if application "iTerm2" is running then
18
+ return "yes"
19
+ else
20
+ return "no"
21
+ end if`,n)).trim()!==`yes`)throw new U(`iTerm2 is not running`,`not-running`);let r=e.replace(/[\\"]/g,``),i;try{i=await Wa(`tell application "iTerm2" to request cookie and key for app named "${r}"`,n)}catch(e){if(e instanceof U)throw e;let t=String(e.stderr??e);throw/-274[01]/.test(t)?new U(`iTerm2 is too old (need 3.3+)`,`too-old`):/denied|not allowed|user/i.test(t)?new U(t.trim(),`denied`):new U(t.trim(),`unknown`)}let[a,o]=i.trim().split(` `);if(!a||!o)throw new U(`unexpected osascript output (${i.trim().split(` `).length} token(s), ${i.length} chars)`,`unknown`);return{cookie:a,key:o}}async function Wa(e,t){try{let{stdout:n}=await Va(`/usr/bin/osascript`,[`-e`,e],{timeout:Math.max(1,t-Date.now()),killSignal:`SIGKILL`});return n}catch(e){throw e.killed?new U(`osascript timed out waiting for iTerm2`,`unknown`):e}}const Ga=An(zt);var Ka=class{opts;granted;paused;explicit=!1;allowance=!1;current=`not-running`;listeners=new Set;constructor(e){this.opts=e;let t=this.readRecord();this.granted=t?.approved??!!e.assumeApproved,this.paused=e.interactive?void 0:t?.paused,this.paused&&(this.current=this.paused),(!t||t.paused!==this.paused)&&this.persist()}get issue(){return this.current}get connecting(){return this.explicit}onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}async connect(e){if(!this.explicit){this.explicit=!0,this.allowance=!0;try{await e()}finally{this.explicit=!1,this.allowance=!1,this.emit()}}}cookieProvider=async e=>{if(!await(this.opts.isRunning??Ja)())throw this.set(`not-running`),new U(`iTerm2 is not running`,`not-running`);if(!await(this.opts.apiListening??Ya)(this.opts.socketPath))throw this.set(`api-off`),Error(`iTerm2 Python API is off`);let t=this.allowance;if(!(t||!this.paused&&(this.granted||this.opts.interactive)))throw this.set(this.paused??`needs-consent`),new U(`waiting for Connect iTerm2`,`unknown`);this.allowance=!1,t&&this.set(`connecting`);try{let t=await(this.opts.requestCookie??Ua)(this.opts.appName??`Shellbell`,e);return this.granted=!0,this.paused=void 0,this.persist(),this.set(void 0),t}catch(e){let t=qa(e);throw(t===`iterm2-denied`||t===`timed-out`)&&(this.paused=t,this.persist()),this.set(t),e}};set(e){e!==this.current&&(this.current=e,this.emit())}emit(){for(let e of this.listeners)try{e()}catch{}}readRecord(){if(this.opts.recordPath)try{let e=JSON.parse(Zt(this.opts.recordPath,`utf8`));if(typeof e?.approved!=`boolean`)return;let t=e.paused===`iterm2-denied`||e.paused===`timed-out`?e.paused:void 0;return{approved:e.approved,paused:t}}catch{return}}persist(){if(this.opts.recordPath)try{He(this.opts.recordPath,`${JSON.stringify({v:1,approved:this.granted,...this.paused?{paused:this.paused}:{},at:new Date(this.opts.now?.()??Date.now()).toISOString()})}\n`)}catch{}}};function qa(e){return e instanceof U?e.kind===`too-old`?`too-old`:e.kind===`not-running`?`not-running`:/-1743\b|Not authori[sz]ed to send Apple events/i.test(e.message)?`automation-denied`:/timed out/i.test(e.message)?`timed-out`:e.kind===`denied`?`iterm2-denied`:`failed`:`failed`}async function Ja(){try{let e=process.getuid?.();return await Ga(`/usr/bin/pgrep`,[...e===void 0?[]:[`-U`,String(e)],`-x`,`iTerm2`],{timeout:2e3}),!0}catch{return!1}}async function Ya(e){try{if(!rn(e).isSocket())return!1}catch{return!1}return new Promise(t=>{let n=wn({path:e}),r=e=>{n.destroy(),t(e)};n.setTimeout(1e3,()=>r(!1)),n.once(`connect`,()=>r(!0)),n.once(`error`,()=>r(!1))})}const W=Nn(`CgxpdGVybTIucHJvdG8SBml0ZXJtMiLcBQoXQ2xpZW50T3JpZ2luYXRlZE1lc3NhZ2USCgoCaWQYASABKAMSNgoSZ2V0X2J1ZmZlcl9yZXF1ZXN0GGQgASgLMhguaXRlcm0yLkdldEJ1ZmZlclJlcXVlc3RIABI2ChJnZXRfcHJvbXB0X3JlcXVlc3QYZSABKAsyGC5pdGVybTIuR2V0UHJvbXB0UmVxdWVzdEgAEjsKFG5vdGlmaWNhdGlvbl9yZXF1ZXN0GGcgASgLMhsuaXRlcm0yLk5vdGlmaWNhdGlvblJlcXVlc3RIABI8ChVsaXN0X3Nlc3Npb25zX3JlcXVlc3QYaiABKAsyGy5pdGVybTIuTGlzdFNlc3Npb25zUmVxdWVzdEgAEjQKEXNlbmRfdGV4dF9yZXF1ZXN0GGsgASgLMhcuaXRlcm0yLlNlbmRUZXh0UmVxdWVzdEgAEjYKEmNyZWF0ZV90YWJfcmVxdWVzdBhsIAEoCzIYLml0ZXJtMi5DcmVhdGVUYWJSZXF1ZXN0SAASNgoSc3BsaXRfcGFuZV9yZXF1ZXN0GG0gASgLMhguaXRlcm0yLlNwbGl0UGFuZVJlcXVlc3RIABI6ChRnZXRfcHJvcGVydHlfcmVxdWVzdBhwIAEoCzIaLml0ZXJtMi5HZXRQcm9wZXJ0eVJlcXVlc3RIABIzChBhY3RpdmF0ZV9yZXF1ZXN0GHIgASgLMhcuaXRlcm0yLkFjdGl2YXRlUmVxdWVzdEgAEjMKEHZhcmlhYmxlX3JlcXVlc3QYcyABKAsyFy5pdGVybTIuVmFyaWFibGVSZXF1ZXN0SAASLQoNZm9jdXNfcmVxdWVzdBh1IAEoCzIULml0ZXJtMi5Gb2N1c1JlcXVlc3RIABJBChdpbnZva2VfZnVuY3Rpb25fcmVxdWVzdBiEASABKAsyHS5pdGVybTIuSW52b2tlRnVuY3Rpb25SZXF1ZXN0SABCDAoKc3VibWVzc2FnZSK0BgoXU2VydmVyT3JpZ2luYXRlZE1lc3NhZ2USCgoCaWQYASABKAMSDwoFZXJyb3IYAiABKAlIABI4ChNnZXRfYnVmZmVyX3Jlc3BvbnNlGGQgASgLMhkuaXRlcm0yLkdldEJ1ZmZlclJlc3BvbnNlSAASOAoTZ2V0X3Byb21wdF9yZXNwb25zZRhlIAEoCzIZLml0ZXJtMi5HZXRQcm9tcHRSZXNwb25zZUgAEj0KFW5vdGlmaWNhdGlvbl9yZXNwb25zZRhnIAEoCzIcLml0ZXJtMi5Ob3RpZmljYXRpb25SZXNwb25zZUgAEj4KFmxpc3Rfc2Vzc2lvbnNfcmVzcG9uc2UYaiABKAsyHC5pdGVybTIuTGlzdFNlc3Npb25zUmVzcG9uc2VIABI2ChJzZW5kX3RleHRfcmVzcG9uc2UYayABKAsyGC5pdGVybTIuU2VuZFRleHRSZXNwb25zZUgAEjgKE2NyZWF0ZV90YWJfcmVzcG9uc2UYbCABKAsyGS5pdGVybTIuQ3JlYXRlVGFiUmVzcG9uc2VIABI4ChNzcGxpdF9wYW5lX3Jlc3BvbnNlGG0gASgLMhkuaXRlcm0yLlNwbGl0UGFuZVJlc3BvbnNlSAASPAoVZ2V0X3Byb3BlcnR5X3Jlc3BvbnNlGHAgASgLMhsuaXRlcm0yLkdldFByb3BlcnR5UmVzcG9uc2VIABI1ChFhY3RpdmF0ZV9yZXNwb25zZRhyIAEoCzIYLml0ZXJtMi5BY3RpdmF0ZVJlc3BvbnNlSAASNQoRdmFyaWFibGVfcmVzcG9uc2UYcyABKAsyGC5pdGVybTIuVmFyaWFibGVSZXNwb25zZUgAEi8KDmZvY3VzX3Jlc3BvbnNlGHUgASgLMhUuaXRlcm0yLkZvY3VzUmVzcG9uc2VIABJDChhpbnZva2VfZnVuY3Rpb25fcmVzcG9uc2UYhAEgASgLMh4uaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVzcG9uc2VIABItCgxub3RpZmljYXRpb24Y6AcgASgLMhQuaXRlcm0yLk5vdGlmaWNhdGlvbkgAQgwKCnN1Ym1lc3NhZ2UiHQoFQ29vcmQSCQoBeBgBIAEoBRIJCgF5GAIgASgDIkYKCkNvb3JkUmFuZ2USHAoFc3RhcnQYASABKAsyDS5pdGVybTIuQ29vcmQSGgoDZW5kGAIgASgLMg0uaXRlcm0yLkNvb3JkIikKBVJhbmdlEhAKCGxvY2F0aW9uGAEgASgDEg4KBmxlbmd0aBgCIAEoAyJdChJXaW5kb3dlZENvb3JkUmFuZ2USJwoLY29vcmRfcmFuZ2UYASABKAsyEi5pdGVybTIuQ29vcmRSYW5nZRIeCgdjb2x1bW5zGAIgASgLMg0uaXRlcm0yLlJhbmdlIh0KBVBvaW50EgkKAXgYASABKAUSCQoBeRgCIAEoBSIlCgRTaXplEg0KBXdpZHRoGAEgASgFEg4KBmhlaWdodBgCIAEoBSJCCgVGcmFtZRIdCgZvcmlnaW4YASABKAsyDS5pdGVybTIuUG9pbnQSGgoEc2l6ZRgCIAEoCzIMLml0ZXJtMi5TaXplInsKCUxpbmVSYW5nZRIcChRzY3JlZW5fY29udGVudHNfb25seRgBIAEoCBIWCg50cmFpbGluZ19saW5lcxgCIAEoBRI4ChR3aW5kb3dlZF9jb29yZF9yYW5nZRgDIAEoCzIaLml0ZXJtMi5XaW5kb3dlZENvb3JkUmFuZ2UiYgoQR2V0QnVmZmVyUmVxdWVzdBIPCgdzZXNzaW9uGAEgASgJEiUKCmxpbmVfcmFuZ2UYAiABKAsyES5pdGVybTIuTGluZVJhbmdlEhYKDmluY2x1ZGVfc3R5bGVzGAMgASgIIjQKCFJHQkNvbG9yEgsKA3JlZBgBIAEoDRINCgVncmVlbhgCIAEoDRIMCgRibHVlGAMgASgNIowDCglDZWxsU3R5bGUSFAoKZmdTdGFuZGFyZBgBIAEoDUgAEi0KC2ZnQWx0ZXJuYXRlGAIgASgOMhYuaXRlcm0yLkFsdGVybmF0ZUNvbG9ySAASIQoFZmdSZ2IYAyABKAsyEC5pdGVybTIuUkdCQ29sb3JIABIUCgpiZ1N0YW5kYXJkGAUgASgNSAESLQoLYmdBbHRlcm5hdGUYBiABKA4yFi5pdGVybTIuQWx0ZXJuYXRlQ29sb3JIARIhCgViZ1JnYhgHIAEoCzIQLml0ZXJtMi5SR0JDb2xvckgBEgwKBGJvbGQYCSABKAgSDQoFZmFpbnQYCiABKAgSDgoGaXRhbGljGAsgASgIEg0KBWJsaW5rGAwgASgIEhEKCXVuZGVybGluZRgNIAEoCBIVCg1zdHJpa2V0aHJvdWdoGA4gASgIEhEKCWludmlzaWJsZRgPIAEoCBIPCgdpbnZlcnNlGBAgASgIEg8KB3JlcGVhdHMYFiABKA1CCQoHZmdDb2xvckIJCgdiZ0NvbG9yIkAKEUNvZGVQb2ludHNQZXJDZWxsEhoKD251bV9jb2RlX3BvaW50cxgBIAEoBToBMRIPCgdyZXBlYXRzGAIgASgFIo0CCgxMaW5lQ29udGVudHMSDAoEdGV4dBgBIAEoCRI3ChRjb2RlX3BvaW50c19wZXJfY2VsbBgCIAMoCzIZLml0ZXJtMi5Db2RlUG9pbnRzUGVyQ2VsbBJOCgxjb250aW51YXRpb24YAyABKA4yIS5pdGVybTIuTGluZUNvbnRlbnRzLkNvbnRpbnVhdGlvbjoVQ09OVElOVUFUSU9OX0hBUkRfRU9MEiAKBXN0eWxlGAQgAygLMhEuaXRlcm0yLkNlbGxTdHlsZSJECgxDb250aW51YXRpb24SGQoVQ09OVElOVUFUSU9OX0hBUkRfRU9MEAESGQoVQ09OVElOVUFUSU9OX1NPRlRfRU9MEAIiogIKEUdldEJ1ZmZlclJlc3BvbnNlEjQKBnN0YXR1cxgBIAEoDjIgLml0ZXJtMi5HZXRCdWZmZXJSZXNwb25zZS5TdGF0dXM6Ak9LEiYKCGNvbnRlbnRzGAMgAygLMhQuaXRlcm0yLkxpbmVDb250ZW50cxIdCgZjdXJzb3IYBCABKAsyDS5pdGVybTIuQ29vcmQSOAoUd2luZG93ZWRfY29vcmRfcmFuZ2UYBiABKAsyGi5pdGVybTIuV2luZG93ZWRDb29yZFJhbmdlIlYKBlN0YXR1cxIGCgJPSxAAEhUKEVNFU1NJT05fTk9UX0ZPVU5EEAESFgoSSU5WQUxJRF9MSU5FX1JBTkdFEAISFQoRUkVRVUVTVF9NQUxGT1JNRUQQAyIVChNMaXN0U2Vzc2lvbnNSZXF1ZXN0InkKDlNlc3Npb25TdW1tYXJ5EhkKEXVuaXF1ZV9pZGVudGlmaWVyGAEgASgJEhwKBWZyYW1lGAIgASgLMg0uaXRlcm0yLkZyYW1lEh8KCWdyaWRfc2l6ZRgDIAEoCzIMLml0ZXJtMi5TaXplEg0KBXRpdGxlGAQgASgJIsEBCg1TcGxpdFRyZWVOb2RlEhAKCHZlcnRpY2FsGAEgASgIEjIKBWxpbmtzGAIgAygLMiMuaXRlcm0yLlNwbGl0VHJlZU5vZGUuU3BsaXRUcmVlTGluaxpqCg1TcGxpdFRyZWVMaW5rEikKB3Nlc3Npb24YASABKAsyFi5pdGVybTIuU2Vzc2lvblN1bW1hcnlIABIlCgRub2RlGAIgASgLMhUuaXRlcm0yLlNwbGl0VHJlZU5vZGVIAEIHCgVjaGlsZCKbAgoUTGlzdFNlc3Npb25zUmVzcG9uc2USNAoHd2luZG93cxgBIAMoCzIjLml0ZXJtMi5MaXN0U2Vzc2lvbnNSZXNwb25zZS5XaW5kb3caeQoGV2luZG93Ei4KBHRhYnMYASADKAsyIC5pdGVybTIuTGlzdFNlc3Npb25zUmVzcG9uc2UuVGFiEhEKCXdpbmRvd19pZBgCIAEoCRIcCgVmcmFtZRgDIAEoCzINLml0ZXJtMi5GcmFtZRIOCgZudW1iZXIYBCABKAUaUgoDVGFiEiMKBHJvb3QYAyABKAsyFS5pdGVybTIuU3BsaXRUcmVlTm9kZRIOCgZ0YWJfaWQYAiABKAkSFgoOdG11eF93aW5kb3dfaWQYBCABKAkiTAoPU2VuZFRleHRSZXF1ZXN0Eg8KB3Nlc3Npb24YASABKAkSDAoEdGV4dBgCIAEoCRIaChJzdXBwcmVzc19icm9hZGNhc3QYAyABKAgibAoQU2VuZFRleHRSZXNwb25zZRIvCgZzdGF0dXMYASABKA4yHy5pdGVybTIuU2VuZFRleHRSZXNwb25zZS5TdGF0dXMiJwoGU3RhdHVzEgYKAk9LEAASFQoRU0VTU0lPTl9OT1RfRk9VTkQQASJbChJHZXRQcm9wZXJ0eVJlcXVlc3QSEwoJd2luZG93X2lkGAEgASgJSAASFAoKc2Vzc2lvbl9pZBgDIAEoCUgAEgwKBG5hbWUYAiABKAlCDAoKaWRlbnRpZmllciKaAQoTR2V0UHJvcGVydHlSZXNwb25zZRIyCgZzdGF0dXMYASABKA4yIi5pdGVybTIuR2V0UHJvcGVydHlSZXNwb25zZS5TdGF0dXMSEgoKanNvbl92YWx1ZRgCIAEoCSI7CgZTdGF0dXMSBgoCT0sQABIVChFVTlJFQ09HTklaRURfTkFNRRABEhIKDklOVkFMSURfVEFSR0VUEAIiQAoUUHJvbXB0TW9uaXRvclJlcXVlc3QSKAoFbW9kZXMYASADKA4yGS5pdGVybTIuUHJvbXB0TW9uaXRvck1vZGUiYAoWVmFyaWFibGVNb25pdG9yUmVxdWVzdBIMCgRuYW1lGAEgASgJEiQKBXNjb3BlGAIgASgOMhUuaXRlcm0yLlZhcmlhYmxlU2NvcGUSEgoKaWRlbnRpZmllchgDIAEoCSL/AQoTTm90aWZpY2F0aW9uUmVxdWVzdBIPCgdzZXNzaW9uGAEgASgJEhEKCXN1YnNjcmliZRgCIAEoCBIzChFub3RpZmljYXRpb25fdHlwZRgDIAEoDjIYLml0ZXJtMi5Ob3RpZmljYXRpb25UeXBlEkIKGHZhcmlhYmxlX21vbml0b3JfcmVxdWVzdBgGIAEoCzIeLml0ZXJtMi5WYXJpYWJsZU1vbml0b3JSZXF1ZXN0SAASPgoWcHJvbXB0X21vbml0b3JfcmVxdWVzdBgJIAEoCzIcLml0ZXJtMi5Qcm9tcHRNb25pdG9yUmVxdWVzdEgAQgsKCWFyZ3VtZW50cyL1AQoUTm90aWZpY2F0aW9uUmVzcG9uc2USMwoGc3RhdHVzGAEgASgOMiMuaXRlcm0yLk5vdGlmaWNhdGlvblJlc3BvbnNlLlN0YXR1cyKnAQoGU3RhdHVzEgYKAk9LEAASFQoRU0VTU0lPTl9OT1RfRk9VTkQQARIVChFSRVFVRVNUX01BTEZPUk1FRBACEhIKDk5PVF9TVUJTQ1JJQkVEEAMSFgoSQUxSRUFEWV9TVUJTQ1JJQkVEEAQSIwofRFVQTElDQVRFX1NFUlZFUl9PUklHSU5BVEVEX1JQQxAFEhYKEklOVkFMSURfSURFTlRJRklFUhAGIisKGFNjcmVlblVwZGF0ZU5vdGlmaWNhdGlvbhIPCgdzZXNzaW9uGAEgASgJIloKGFByb21wdE5vdGlmaWNhdGlvblByb21wdBITCgtwbGFjZWhvbGRlchgBIAEoCRIpCgZwcm9tcHQYAiABKAsyGS5pdGVybTIuR2V0UHJvbXB0UmVzcG9uc2UiMQoeUHJvbXB0Tm90aWZpY2F0aW9uQ29tbWFuZFN0YXJ0Eg8KB2NvbW1hbmQYASABKAkiLgocUHJvbXB0Tm90aWZpY2F0aW9uQ29tbWFuZEVuZBIOCgZzdGF0dXMYASABKAUi+gEKElByb21wdE5vdGlmaWNhdGlvbhIPCgdzZXNzaW9uGAEgASgJEjIKBnByb21wdBgCIAEoCzIgLml0ZXJtMi5Qcm9tcHROb3RpZmljYXRpb25Qcm9tcHRIABI/Cg1jb21tYW5kX3N0YXJ0GAMgASgLMiYuaXRlcm0yLlByb21wdE5vdGlmaWNhdGlvbkNvbW1hbmRTdGFydEgAEjsKC2NvbW1hbmRfZW5kGAQgASgLMiQuaXRlcm0yLlByb21wdE5vdGlmaWNhdGlvbkNvbW1hbmRFbmRIABIYChB1bmlxdWVfcHJvbXB0X2lkGAUgASgJQgcKBWV2ZW50IiwKFk5ld1Nlc3Npb25Ob3RpZmljYXRpb24SEgoKc2Vzc2lvbl9pZBgBIAEoCSIyChxUZXJtaW5hdGVTZXNzaW9uTm90aWZpY2F0aW9uEhIKCnNlc3Npb25faWQYASABKAkiWQoZTGF5b3V0Q2hhbmdlZE5vdGlmaWNhdGlvbhI8ChZsaXN0X3Nlc3Npb25zX3Jlc3BvbnNlGAEgASgLMhwuaXRlcm0yLkxpc3RTZXNzaW9uc1Jlc3BvbnNlIoQDChhGb2N1c0NoYW5nZWROb3RpZmljYXRpb24SHAoSYXBwbGljYXRpb25fYWN0aXZlGAEgASgISAASOQoGd2luZG93GAIgASgLMicuaXRlcm0yLkZvY3VzQ2hhbmdlZE5vdGlmaWNhdGlvbi5XaW5kb3dIABIWCgxzZWxlY3RlZF90YWIYAyABKAlIABIRCgdzZXNzaW9uGAQgASgJSAAa2gEKBldpbmRvdxJLCg13aW5kb3dfc3RhdHVzGAEgASgOMjQuaXRlcm0yLkZvY3VzQ2hhbmdlZE5vdGlmaWNhdGlvbi5XaW5kb3cuV2luZG93U3RhdHVzEhEKCXdpbmRvd19pZBgCIAEoCSJwCgxXaW5kb3dTdGF0dXMSHgoaVEVSTUlOQUxfV0lORE9XX0JFQ0FNRV9LRVkQABIeChpURVJNSU5BTF9XSU5ET1dfSVNfQ1VSUkVOVBABEiAKHFRFUk1JTkFMX1dJTkRPV19SRVNJR05FRF9LRVkQAkIHCgVldmVudCJ9ChtWYXJpYWJsZUNoYW5nZWROb3RpZmljYXRpb24SJAoFc2NvcGUYASABKA4yFS5pdGVybTIuVmFyaWFibGVTY29wZRISCgppZGVudGlmaWVyGAIgASgJEgwKBG5hbWUYAyABKAkSFgoOanNvbl9uZXdfdmFsdWUYBCABKAki9wMKDE5vdGlmaWNhdGlvbhJEChpzY3JlZW5fdXBkYXRlX25vdGlmaWNhdGlvbhgCIAEoCzIgLml0ZXJtMi5TY3JlZW5VcGRhdGVOb3RpZmljYXRpb24SNwoTcHJvbXB0X25vdGlmaWNhdGlvbhgDIAEoCzIaLml0ZXJtMi5Qcm9tcHROb3RpZmljYXRpb24SQAoYbmV3X3Nlc3Npb25fbm90aWZpY2F0aW9uGAYgASgLMh4uaXRlcm0yLk5ld1Nlc3Npb25Ob3RpZmljYXRpb24STAoedGVybWluYXRlX3Nlc3Npb25fbm90aWZpY2F0aW9uGAcgASgLMiQuaXRlcm0yLlRlcm1pbmF0ZVNlc3Npb25Ob3RpZmljYXRpb24SRgobbGF5b3V0X2NoYW5nZWRfbm90aWZpY2F0aW9uGAggASgLMiEuaXRlcm0yLkxheW91dENoYW5nZWROb3RpZmljYXRpb24SRAoaZm9jdXNfY2hhbmdlZF9ub3RpZmljYXRpb24YCSABKAsyIC5pdGVybTIuRm9jdXNDaGFuZ2VkTm90aWZpY2F0aW9uEkoKHXZhcmlhYmxlX2NoYW5nZWRfbm90aWZpY2F0aW9uGAwgASgLMiMuaXRlcm0yLlZhcmlhYmxlQ2hhbmdlZE5vdGlmaWNhdGlvbiI9ChBHZXRQcm9tcHRSZXF1ZXN0Eg8KB3Nlc3Npb24YASABKAkSGAoQdW5pcXVlX3Byb21wdF9pZBgCIAEoCSLkAgoRR2V0UHJvbXB0UmVzcG9uc2USNAoGc3RhdHVzGAEgASgOMiAuaXRlcm0yLkdldFByb21wdFJlc3BvbnNlLlN0YXR1czoCT0sSGQoRd29ya2luZ19kaXJlY3RvcnkYBSABKAkSDwoHY29tbWFuZBgGIAEoCRI1Cgxwcm9tcHRfc3RhdGUYByABKA4yHy5pdGVybTIuR2V0UHJvbXB0UmVzcG9uc2UuU3RhdGUSEwoLZXhpdF9zdGF0dXMYCSABKA0SGAoQdW5pcXVlX3Byb21wdF9pZBgKIAEoCSJWCgZTdGF0dXMSBgoCT0sQABIVChFTRVNTSU9OX05PVF9GT1VORBABEhUKEVJFUVVFU1RfTUFMRk9STUVEEAISFgoSUFJPTVBUX1VOQVZBSUxBQkxFEAMiLwoFU3RhdGUSCwoHRURJVElORxAAEgsKB1JVTk5JTkcQARIMCghGSU5JU0hFRBACIjIKD1Byb2ZpbGVQcm9wZXJ0eRILCgNrZXkYASABKAkSEgoKanNvbl92YWx1ZRgCIAEoCSKeAQoQQ3JlYXRlVGFiUmVxdWVzdBIUCgxwcm9maWxlX25hbWUYASABKAkSEQoJd2luZG93X2lkGAIgASgJEhEKCXRhYl9pbmRleBgDIAEoDRI6ChljdXN0b21fcHJvZmlsZV9wcm9wZXJ0aWVzGAUgAygLMhcuaXRlcm0yLlByb2ZpbGVQcm9wZXJ0eRISCgpzZWxlY3RfdGFiGAYgASgIIvABChFDcmVhdGVUYWJSZXNwb25zZRIwCgZzdGF0dXMYASABKA4yIC5pdGVybTIuQ3JlYXRlVGFiUmVzcG9uc2UuU3RhdHVzEhEKCXdpbmRvd19pZBgCIAEoCRIOCgZ0YWJfaWQYAyABKAUSEgoKc2Vzc2lvbl9pZBgEIAEoCSJyCgZTdGF0dXMSBgoCT0sQABIYChRJTlZBTElEX1BST0ZJTEVfTkFNRRABEhUKEUlOVkFMSURfV0lORE9XX0lEEAISFQoRSU5WQUxJRF9UQUJfSU5ERVgQAxIYChRNSVNTSU5HX1NVQlNUSVRVVElPThAEIqwBChBTcGxpdFBhbmVSZXF1ZXN0Eg8KB3Nlc3Npb24YASABKAkSQAoPc3BsaXRfZGlyZWN0aW9uGAIgASgOMicuaXRlcm0yLlNwbGl0UGFuZVJlcXVlc3QuU3BsaXREaXJlY3Rpb24SFQoGYmVmb3JlGAMgASgIOgVmYWxzZSIuCg5TcGxpdERpcmVjdGlvbhIMCghWRVJUSUNBTBAAEg4KCkhPUklaT05UQUwQASLVAQoRU3BsaXRQYW5lUmVzcG9uc2USMAoGc3RhdHVzGAEgASgOMiAuaXRlcm0yLlNwbGl0UGFuZVJlc3BvbnNlLlN0YXR1cxISCgpzZXNzaW9uX2lkGAIgAygJInoKBlN0YXR1cxIGCgJPSxAAEhUKEVNFU1NJT05fTk9UX0ZPVU5EEAESGAoUSU5WQUxJRF9QUk9GSUxFX05BTUUQAhIQCgxDQU5OT1RfU1BMSVQQAxIlCiFNQUxGT1JNRURfQ1VTVE9NX1BST0ZJTEVfUFJPUEVSVFkQBCKWAgoPQWN0aXZhdGVSZXF1ZXN0EhMKCXdpbmRvd19pZBgBIAEoCUgAEhAKBnRhYl9pZBgCIAEoCUgAEhQKCnNlc3Npb25faWQYAyABKAlIABIaChJvcmRlcl93aW5kb3dfZnJvbnQYBCABKAgSEgoKc2VsZWN0X3RhYhgFIAEoCBIWCg5zZWxlY3Rfc2Vzc2lvbhgGIAEoCBIxCgxhY3RpdmF0ZV9hcHAYByABKAsyGy5pdGVybTIuQWN0aXZhdGVSZXF1ZXN0LkFwcBo9CgNBcHASGQoRcmFpc2VfYWxsX3dpbmRvd3MYASABKAgSGwoTaWdub3Jpbmdfb3RoZXJfYXBwcxgCIAEoCEIMCgppZGVudGlmaWVyIn0KEEFjdGl2YXRlUmVzcG9uc2USLwoGc3RhdHVzGAEgASgOMh8uaXRlcm0yLkFjdGl2YXRlUmVzcG9uc2UuU3RhdHVzIjgKBlN0YXR1cxIGCgJPSxAAEhIKDkJBRF9JREVOVElGSUVSEAESEgoOSU5WQUxJRF9PUFRJT04QAiKLAQoPVmFyaWFibGVSZXF1ZXN0EhQKCnNlc3Npb25faWQYASABKAlIABIoCgNzZXQYAiADKAsyGy5pdGVybTIuVmFyaWFibGVSZXF1ZXN0LlNldBILCgNnZXQYAyADKAkaIgoDU2V0EgwKBG5hbWUYASABKAkSDQoFdmFsdWUYAiABKAlCBwoFc2NvcGUi5QEKEFZhcmlhYmxlUmVzcG9uc2USLwoGc3RhdHVzGAEgASgOMh8uaXRlcm0yLlZhcmlhYmxlUmVzcG9uc2UuU3RhdHVzEg4KBnZhbHVlcxgCIAMoCSKPAQoGU3RhdHVzEgYKAk9LEAASFQoRU0VTU0lPTl9OT1RfRk9VTkQQARIQCgxJTlZBTElEX05BTUUQAhIRCg1NSVNTSU5HX1NDT1BFEAMSEQoNVEFCX05PVF9GT1VORBAEEhgKFE1VTFRJX0dFVF9ESVNBTExPV0VEEAUSFAoQV0lORE9XX05PVF9GT1VORBAGIp8BChVJbnZva2VGdW5jdGlvblJlcXVlc3QSNgoGbWV0aG9kGAcgASgLMiQuaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVxdWVzdC5NZXRob2RIABISCgppbnZvY2F0aW9uGAUgASgJEhMKB3RpbWVvdXQYBiABKAE6Ai0xGhoKBk1ldGhvZBIQCghyZWNlaXZlchgBIAEoCUIJCgdjb250ZXh0ItkCChZJbnZva2VGdW5jdGlvblJlc3BvbnNlEjUKBWVycm9yGAEgASgLMiQuaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVzcG9uc2UuRXJyb3JIABI5CgdzdWNjZXNzGAIgASgLMiYuaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVzcG9uc2UuU3VjY2Vzc0gAGlQKBUVycm9yEjUKBnN0YXR1cxgBIAEoDjIlLml0ZXJtMi5JbnZva2VGdW5jdGlvblJlc3BvbnNlLlN0YXR1cxIUCgxlcnJvcl9yZWFzb24YAiABKAkaHgoHU3VjY2VzcxITCgtqc29uX3Jlc3VsdBgBIAEoCSJICgZTdGF0dXMSCwoHVElNRU9VVBABEgoKBkZBSUxFRBACEhUKEVJFUVVFU1RfTUFMRk9STUVEEAMSDgoKSU5WQUxJRF9JRBAEQg0KC2Rpc3Bvc2l0aW9uIg4KDEZvY3VzUmVxdWVzdCJICg1Gb2N1c1Jlc3BvbnNlEjcKDW5vdGlmaWNhdGlvbnMYASADKAsyIC5pdGVybTIuRm9jdXNDaGFuZ2VkTm90aWZpY2F0aW9uKkcKDkFsdGVybmF0ZUNvbG9yEgsKB0RFRkFVTFQQABIUChBSRVZFUlNFRF9ERUZBVUxUEAMSEgoOU1lTVEVNX01FU1NBR0UQBCrZAQoQTm90aWZpY2F0aW9uVHlwZRIbChdOT1RJRllfT05fU0NSRUVOX1VQREFURRACEhQKEE5PVElGWV9PTl9QUk9NUFQQAxIZChVOT1RJRllfT05fTkVXX1NFU1NJT04QBhIfChtOT1RJRllfT05fVEVSTUlOQVRFX1NFU1NJT04QBxIbChdOT1RJRllfT05fTEFZT1VUX0NIQU5HRRAIEhoKFk5PVElGWV9PTl9GT0NVU19DSEFOR0UQCRIdChlOT1RJRllfT05fVkFSSUFCTEVfQ0hBTkdFEAwqQwoRUHJvbXB0TW9uaXRvck1vZGUSCgoGUFJPTVBUEAESEQoNQ09NTUFORF9TVEFSVBACEg8KC0NPTU1BTkRfRU5EEAMqOgoNVmFyaWFibGVTY29wZRILCgdTRVNTSU9OEAESBwoDVEFCEAISCgoGV0lORE9XEAMSBwoDQVBQEAQ`),Xa=B(W,0),Za=B(W,1),Qa=B(W,2),$a=B(W,3),eo=B(W,5),to=B(W,9),no=B(W,10),ro=B(W,16),io=B(W,20);let ao=function(e){return e[e.OK=0]=`OK`,e[e.SESSION_NOT_FOUND=1]=`SESSION_NOT_FOUND`,e}({});const oo=B(W,22),so=B(W,24),co=B(W,25),lo=B(W,26),uo=B(W,42),fo=B(W,44),po=B(W,46),mo=B(W,46,0),ho=B(W,48),go=B(W,52);function _o(e){if(!e)return{};let t,n;if(e.fgColor.case===`fgStandard`?t=e.fgColor.value:e.fgColor.case===`fgRgb`&&(t=[e.fgColor.value.red??0,e.fgColor.value.green??0,e.fgColor.value.blue??0]),e.bgColor.case===`bgStandard`?n=e.bgColor.value:e.bgColor.case===`bgRgb`&&(n=[e.bgColor.value.red??0,e.bgColor.value.green??0,e.bgColor.value.blue??0]),e.inverse){let e=t??15;t=n??0,n=e}let r={};return t!==void 0&&(r.fg=t),n!==void 0&&(r.bg=n),e.bold&&(r.b=!0),e.italic&&(r.i=!0),e.underline&&(r.u=!0),e.strikethrough&&(r.s=!0),e.faint&&(r.f=!0),e.invisible&&(r.invisible=!0),r}function vo(e){return`${JSON.stringify(e.fg??null)}|${JSON.stringify(e.bg??null)}|${+!!e.b}${+!!e.i}${+!!e.u}${+!!e.s}${+!!e.f}${+!!e.invisible}`}function yo(e){let t=Array.from(e.text??``),n=[];for(let t of e.codePointsPerCell)for(let e=0;e<(t.repeats||1);e++)n.push(t.numCodePoints);if(n.length===0)for(let e=0;e<t.length;e++)n.push(1);let r=[];for(let t of e.style)for(let e=0;e<(t.repeats||1);e++)r.push(t);let i=[],a=null,o=0;for(let e=0;e<n.length;e++){let s=n[e],c;s===0?c=` `:(c=t.slice(o,o+s).join(``),o+=s);let l=_o(r[e]);l.invisible&&(c=` `.repeat(Math.max(1,re(c))));let u=vo(l);a&&a.key===u?(a.text+=c,a.cells+=1):(a&&i.push(bo(a)),a={style:l,key:u,text:c,cells:1})}a&&i.push(bo(a));let c=e.continuation===2,l=s(i),u={r:c?l:x(l)};return c&&(u.w=!0),u}function bo(e){let t={t:e.text};return e.style.fg!==void 0&&(t.fg=e.style.fg),e.style.bg!==void 0&&(t.bg=e.style.bg),e.style.b&&(t.b=!0),e.style.i&&(t.i=!0),e.style.u&&(t.u=!0),e.style.s&&(t.s=!0),e.style.f&&(t.f=!0),e.cells!==re(e.text)&&(t.n=e.cells),t}function xo(e,t,n){let r=Number(e.windowedCoordRange?.coordRange?.start?.y??0n),i=e.contents.map(yo);for(;i.length<t;)i.push(ge());i.length>t&&(i.length=t);let a=e.cursor?Number(e.cursor.y??0n)-r:-1;return{cols:n,rows:t,cursor:{x:e.cursor?.x??0,y:Math.max(-1,Math.min(t-1,a))},lines:i,scrollbackTotal:r}}function So(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>=0}function Co(e){return typeof e==`bigint`&&e>=0n&&e<=BigInt(2**53-1)}function wo(e){let t;try{t=JSON.parse(e)}catch{return null}if(typeof t!=`object`||!t||Array.isArray(t))return null;let{overflow:n,history:r,grid:i,first_visible:a}=t;if(!So(n)||!So(r)||!So(i)||!So(a)||i===0)return null;let o=n+r;return Number.isSafeInteger(o)?{overflow:n,history:r,grid:i,firstVisible:a,origin:o}:null}function To(e,t,n){if(!So(t)||!So(n)||n<t||e.status!==0)return!1;let r=e.windowedCoordRange?.coordRange,i=r?.start,a=r?.end;if(!i||!a||i.x!==0||a.x!==0||!Co(i.y)||!Co(a.y)||i.y!==BigInt(t)||a.y!==BigInt(n))return!1;let o=e.windowedCoordRange?.columns;return o&&(o.location!==0n||o.length!==0n)?!1:e.contents.length===n-t}function Eo(e,t){return e.overflow===t.overflow&&e.history===t.history&&e.grid===t.grid}function Do(e,t){return t!==void 0&&(e.overflow<t.overflow||e.origin<t.origin)}function Oo(e){if(!e)return null;let t=e.links.map(e=>e.child.case===`session`?e.child.value.gridSize?{cols:e.child.value.gridSize.width,rows:e.child.value.gridSize.height}:null:e.child.case===`node`?Oo(e.child.value):null).filter(e=>e!==null);if(t.length===0)return null;let n=t.length-1,r=e=>t.reduce((t,n)=>t+n[e],n),i=e=>Math.max(...t.map(t=>t[e]));return e.vertical?{cols:r(`cols`),rows:i(`rows`)}:{cols:i(`cols`),rows:r(`rows`)}}const ko="iTerm2 → Settings → General → Magic → ✓ Enable Python API, then run `shellbell` again.";function Ao(e){return M(e)}var jo=class{client;backoff;name=`iterm2`;capabilities={subscribe:!0,prompts:!0,createSession:!0,terminalInput:!0,focus:!0,history:!0,absoluteLines:!0};sessions=new Map;windowGrids=new Map;historyOwnership=new Map;historyCaptures=new WeakMap;order=[];focused=null;handlers=new Set;subscribed=new Set;log;attempt=0;retryTimer=null;closed=!1;connectionGeneration=0;layoutBusy=!1;layoutDirty=null;layoutRefresh=Promise.resolve();constructor(e,t,n={}){this.client=e,this.backoff=n,this.log=t.child({backend:`iterm2`}),this.client.on(`notification`,e=>this.onNotification(e)),this.client.on(`close`,()=>{this.invalidateConnection(),this.scheduleReconnect()})}get isConnected(){return!this.closed&&this.client.connected}invalidateConnection(){this.connectionGeneration++,this.layoutBusy=!1,this.layoutDirty=null;let e=[...this.sessions.keys()];this.sessions.clear(),this.historyOwnership.clear(),this.order=[],this.subscribed.clear(),this.focused=null;for(let t of e)this.emit({type:`session-removed`,sessionId:t});this.emit({type:`layout-changed`})}ownsConnection(e){return e===this.connectionGeneration&&this.isConnected}scheduleReconnect(){if(this.closed||this.retryTimer)return;let e=this.backoff.minMs??1e3,t=this.backoff.maxMs??3e4,n=Math.min(t,e*2**this.attempt);this.attempt=Math.min(this.attempt+1,10),this.log.info(`iTerm2 gone; retrying`,{delayMs:n,attempt:this.attempt}),this.retryTimer=setTimeout(()=>{this.retryTimer=null;let e=this.connectionGeneration;this.connect().catch(t=>{e!==this.connectionGeneration||this.closed||(this.log.warn(`iTerm2 reconnect failed`,{error:Ao(t)}),this.scheduleReconnect())})},n)}async connect(){this.closed=!1;let e=this.connectionGeneration;if(this.retryTimer&&clearTimeout(this.retryTimer),this.retryTimer=null,!this.client.connected)try{await this.client.connect()}catch(t){if(e!==this.connectionGeneration||this.closed)return;throw new j(String(t),ko)}if(!this.ownsConnection(e)){this.closed&&this.client.close();return}try{for(let t of[8,6,7,9])if(await this.client.request({case:`notificationRequest`,value:z(lo,{subscribe:!0,notificationType:t})}),!this.ownsConnection(e))return;let t=await this.client.request({case:`listSessionsRequest`,value:z(ro,{})});if(!this.ownsConnection(e)||(t.submessage.case===`listSessionsResponse`&&await this.applyLayout(t.submessage.value,e),!this.ownsConnection(e)))return;let n=await this.client.request({case:`focusRequest`,value:z(go,{})});if(!this.ownsConnection(e))return;if(n.submessage.case===`focusResponse`)for(let e of n.submessage.value.notifications)e.event.case===`session`&&(this.focused=e.event.value)}catch(t){if(!this.ownsConnection(e))return;throw new j(String(t),ko)}this.attempt=0}async close(){this.closed=!0,this.retryTimer&&clearTimeout(this.retryTimer),this.retryTimer=null,this.invalidateConnection(),this.client.close()}async notificationFacts(e){let t=this.sessions.get(e);if(t&&this.isConnected)return ir({sessionId:e,cwd:t.cwd,title:t.title,sessionLabel:`iTerm2 · Window ${t.windowNumber} · Tab ${t.tabIndex+1} · Pane ${t.paneIndex+1}`},t.job,`reported`)}async listSessions(){return this.order.map(e=>this.sessions.get(e)).filter(e=>e!==void 0).map(e=>this.toInfo(e))}tmuxWindowIds(){let e=new Set;for(let t of this.sessions.values())t.tmuxWindowId&&e.add(t.tmuxWindowId);return e}representedWindows(){return[...this.tmuxWindowIds()].map(e=>({backend:`tmux`,windowId:e}))}hostedProcess(e){return this.hostJob(e)}projectFolder(e){let t=this.sessions.get(e);return t?.cwd&&ci(t.job)?t.cwd:void 0}hostJob(e){let t=this.sessions.get(e);if(t&&!t.tmuxWindowId)return t.job}async getScreen(e,t){let n=this.sessions.get(e);if(!n)throw new k(e);let r=this.historyOwnership.get(e),i=t?.history&&r?{sessionId:e,connectionGeneration:this.connectionGeneration,coordinateRevision:r.coordinateRevision,cols:n.cols,rows:n.rows}:void 0,a=r?.activityRevision,o=r?.observed,s=i?await this.fetchHistoryFacts(e):null;i&&s&&this.ownsHistory(i)&&(s.grid!==i.rows||Do(s,o))&&this.revokeHistory(e);let c=await this.client.request({case:`getBufferRequest`,value:z(no,{session:e,lineRange:z(to,{screenContentsOnly:!0}),includeStyles:!0})});if(c.submessage.case!==`getBufferResponse`||c.submessage.value.status!==0)throw new k(e);let l=c.submessage.value,u;if(i&&s&&s.grid===i.rows&&this.ownsHistory(i)&&this.historyOwnership.get(e)?.activityRevision===a&&To(l,s.origin,s.origin+s.grid)){let t=await this.fetchHistoryFacts(e);t&&this.ownsHistory(i)&&(t.grid!==i.rows||Do(t,s))&&this.revokeHistory(e),t&&Eo(s,t)&&this.ownsHistory(i)&&this.historyOwnership.get(e)?.activityRevision===a&&(this.observeHistory(e,t),u=Object.freeze({}),this.historyCaptures.set(u,Object.freeze({...i,facts:Object.freeze(s)})))}let d=xo(l,n.rows,n.cols);return u&&(d.historyCapture=u),d}ownsHistory(e){let t=this.sessions.get(e.sessionId);return this.ownsConnection(e.connectionGeneration)&&this.historyOwnership.get(e.sessionId)?.coordinateRevision===e.coordinateRevision&&t?.cols===e.cols&&t.rows===e.rows}revokeHistory(e){let t=this.historyOwnership.get(e);t&&(t.coordinateRevision={},t.observed=void 0)}observeHistory(e,t){let n=this.historyOwnership.get(e);n&&(n.observed={overflow:Math.max(t.overflow,n.observed?.overflow??0),origin:Math.max(t.origin,n.observed?.origin??0)})}async fetchHistoryFacts(e){try{let t=await this.client.request({case:`getPropertyRequest`,value:z(oo,{identifier:{case:`sessionId`,value:e},name:`number_of_lines`})});return t.submessage.case===`getPropertyResponse`&&t.submessage.value.status===0?wo(t.submessage.value.jsonValue):null}catch{return null}}async getHistoryPage(t,n){if(e(n),n.signal.aborted)return{status:`cancelled`};if(!this.sessions.has(t))throw new k(t);let r=this.historyCaptures.get(n.capture);if(!r||r.sessionId!==t)return{status:`unavailable`,reason:`unanchored`};let i=()=>{if(n.signal.aborted)return{status:`cancelled`};if(!this.ownsHistory(r))return{status:`reset`}},a=i();if(a)return a;if(n.reported!==r.facts.origin)return{status:`unavailable`,reason:`unanchored`};let o=this.historyOwnership.get(t)?.activityRevision,s=this.historyOwnership.get(t)?.observed??r.facts,c={status:`unavailable`,reason:`changed`},l=(e,n=s)=>{if(!e)return c;if(e.grid!==r.rows||Do(e,n))return this.historyOwnership.get(t)?.coordinateRevision===r.coordinateRevision&&this.revokeHistory(t),{status:`reset`}},u=await this.fetchHistoryFacts(t),d=i()??l(u);if(d)return d;if(!u)return c;let f=u.overflow,p=Math.max(n.before-n.count,f),m;if(n.before>f)try{let e=await this.client.request({case:`getBufferRequest`,value:z(no,{session:t,lineRange:z(to,{windowedCoordRange:z(eo,{coordRange:z($a,{start:z(Qa,{x:0,y:BigInt(p)}),end:z(Qa,{x:0,y:BigInt(n.before)})})})}),includeStyles:!0})}),r=i();if(r)return r;if(e.submessage.case!==`getBufferResponse`||!To(e.submessage.value,p,n.before))return c;m=e.submessage.value.contents.map(yo)}catch{return i()??c}let h=await this.fetchHistoryFacts(t);return(i()??l(h,u))||(!h||!Eo(u,h)||this.historyOwnership.get(t)?.activityRevision!==o?c:(this.observeHistory(t,h),m?{status:`page`,from:p,to:n.before,oldestAvailable:f,lines:m}:{status:`boundary`,reason:n.before===f?`end`:`truncated`,oldestAvailable:f}))}async getHistory(e,t,n){if(!this.sessions.has(e))throw new k(e);let r=Math.max(0,t-n),i=await this.client.request({case:`getBufferRequest`,value:z(no,{session:e,lineRange:z(to,{windowedCoordRange:z(eo,{coordRange:z($a,{start:z(Qa,{x:0,y:BigInt(r)}),end:z(Qa,{x:0,y:BigInt(t)})})})}),includeStyles:!0})});if(i.submessage.case!==`getBufferResponse`||i.submessage.value.status!==0)throw new k(e);let a=i.submessage.value.contents.map(yo);return{lines:a,oldestAvailable:a.length<t-r?t-a.length:0}}async sendText(e,t){let n=await this.client.request({case:`sendTextRequest`,value:z(io,{session:e,text:t,suppressBroadcast:!0})});if(n.submessage.case!==`sendTextResponse`)throw new k(e);let r=n.submessage.value.status;if(r===1)throw new k(e);if(r!==0)throw Error(`sendText failed: ${ao[r]}`)}async sendInput(e,t){await this.sendText(e,t)}async createSession(e){if(e.kind===`tab`){let t=await this.client.request({case:`createTabRequest`,value:z(uo,{windowId:e.windowId,selectTab:!1})});if(t.submessage.case!==`createTabResponse`||!t.submessage.value.sessionId)throw Error(`create tab failed`);return t.submessage.value.sessionId}let t=await this.client.request({case:`splitPaneRequest`,value:z(fo,{session:e.sessionId,splitDirection:e.direction===`vertical`?0:1})}),n=t.submessage.case===`splitPaneResponse`?t.submessage.value.sessionId[0]:void 0;if(!n)throw Error(`split failed`);return n}hostedWindowGrid(){let e=this.focused?this.sessions.get(this.focused):void 0,t=e?this.windowGrids.get(e.windowId):void 0;if(t)return t;let n;for(let e of this.windowGrids.values())(!n||e.cols*e.rows>n.cols*n.rows)&&(n=e);return n}async createCommandSession(e){if(e.length===0||e.length>8192||e.includes(`\0`))throw Error(`Invalid terminal launch command`);let t=this.hostedWindowGrid(),n=await this.client.request({case:`createTabRequest`,value:z(uo,{selectTab:!1,customProfileProperties:[{key:`Custom Command`,jsonValue:JSON.stringify(`Yes`)},{key:`Command`,jsonValue:JSON.stringify(e)},...t?[{key:`Columns`,jsonValue:JSON.stringify(t.cols)},{key:`Rows`,jsonValue:JSON.stringify(t.rows)}]:[]]})});if(n.submessage.case!==`createTabResponse`||n.submessage.value.status!==0||!n.submessage.value.sessionId)throw Error(`iTerm2 could not create the terminal window`);return n.submessage.value.sessionId}async focus(e){await this.client.request({case:`activateRequest`,value:z(po,{identifier:{case:`sessionId`,value:e},orderWindowFront:!0,selectTab:!0,selectSession:!0,activateApp:z(mo,{raiseAllWindows:!1,ignoringOtherApps:!1})})})}on(e){return this.handlers.add(e),()=>this.handlers.delete(e)}emit(e){for(let t of this.handlers)try{t(e)}catch(e){this.log.warn(`event handler failed`,{error:Ao(e)})}}toInfo(e){return{id:e.id,backend:`iterm2`,title:e.title,cwd:e.cwd,...fi({cwd:e.cwd,processName:e.job,title:e.title}),cols:e.cols,rows:e.rows,windowId:e.windowId,windowNumber:e.windowNumber,tabId:e.tabId,tabIndex:e.tabIndex,paneIndex:e.paneIndex,isFocusedOnMac:this.focused===e.id,state:`unknown`}}applyLayout(e,t){return this.ownsConnection(t)?(this.layoutDirty=e,this.layoutBusy?this.layoutRefresh:(this.layoutBusy=!0,this.layoutRefresh=this.drainLayout(t),this.layoutRefresh)):Promise.resolve()}async drainLayout(e){try{for(;this.ownsConnection(e)&&this.layoutDirty;){let t=this.layoutDirty;this.layoutDirty=null,await this.runApplyLayout(t,e)}}finally{e===this.connectionGeneration&&(this.layoutBusy=!1)}}async runApplyLayout(e,t){let n=new Map,r=[],i=[...e.windows].sort((e,t)=>(e.number??0)-(t.number??0)),a=new Map;for(let e of i){for(let t of e.tabs){let n=Oo(t.root),r=a.get(e.windowId??``);n&&n.cols>0&&n.rows>0&&a.set(e.windowId??``,{cols:Math.max(n.cols,r?.cols??0),rows:Math.max(n.rows,r?.rows??0)})}e.tabs.forEach((t,i)=>{let a=0,o=s=>{if(s)for(let c of s.links)if(c.child.case===`session`){let o=c.child.value,s=o.uniqueIdentifier??``,l=this.sessions.get(s);n.set(s,{id:s,title:l?.title||o.title||`Session`,cwd:l?.cwd,job:l?.job,cols:o.gridSize?.width??80,rows:o.gridSize?.height??24,windowId:e.windowId??``,windowNumber:e.number??0,tabId:t.tabId??``,tabIndex:i,paneIndex:a++,tmuxWindowId:t.tmuxWindowId||void 0}),r.push(s)}else c.child.case===`node`&&o(c.child.value)};o(t.root)})}for(let e of this.sessions.keys())n.has(e)||(this.subscribed.delete(e),this.historyOwnership.delete(e));for(let[e,t]of n){let n=this.sessions.get(e);(!this.historyOwnership.has(e)||n?.cols!==t.cols||n.rows!==t.rows)&&this.historyOwnership.set(e,{coordinateRevision:{},activityRevision:{}})}this.sessions=n,this.windowGrids=a,this.order=r,await Promise.all(r.map(e=>this.ensureSession(e,t))),this.ownsConnection(t)&&this.emit({type:`layout-changed`})}async ensureSession(e,t){let n=this.sessions.get(e),r=()=>this.ownsConnection(t)&&this.sessions.get(e)===n;if(!n||!r()||this.subscribed.has(e))return;this.subscribed.add(e);let i=[z(lo,{session:e,subscribe:!0,notificationType:2}),z(lo,{session:e,subscribe:!0,notificationType:3,arguments:{case:`promptMonitorRequest`,value:z(so,{modes:[1,2,3]})}}),...[`session.name`,`session.path`,`jobName`].map(t=>z(lo,{session:e,subscribe:!0,notificationType:12,arguments:{case:`variableMonitorRequest`,value:z(co,{name:t,scope:1,identifier:e})}}))];for(let t of i){try{await this.client.request({case:`notificationRequest`,value:t})}catch(t){if(!r())return;this.log.warn(`subscribe failed`,{session:e.slice(0,8),error:Ao(t)})}if(!r())return}if(!r())return;let[a,o,s]=await Promise.all([this.variable(e,`session.name`),this.variable(e,`session.path`),this.variable(e,`jobName`)]);r()&&(a&&(n.title=a),o&&(n.cwd=o),s&&(n.job=s))}async variable(e,t){try{let n=await this.client.request({case:`variableRequest`,value:z(ho,{scope:{case:`sessionId`,value:e},get:[t]})});if(n.submessage.case!==`variableResponse`||n.submessage.value.status!==0)return;let r=n.submessage.value.values[0];if(!r||r===`null`)return;let i=JSON.parse(r);return typeof i==`string`?i:void 0}catch{return}}onNotification(e){let t=this.connectionGeneration;if(!this.ownsConnection(t))return;let n=Date.now();if(e.screenUpdateNotification?.session){let t=this.historyOwnership.get(e.screenUpdateNotification.session);t&&(t.activityRevision={}),this.emit({type:`screen-changed`,sessionId:e.screenUpdateNotification.session});return}if(e.promptNotification?.session){let t=e.promptNotification,r=t.session;t.event.case===`commandStart`?this.emit({type:`command-start`,sessionId:r,command:t.event.value.command??``,at:n}):t.event.case===`commandEnd`?this.emit({type:`command-end`,sessionId:r,exitCode:t.event.value.status??0,at:n}):t.event.case===`prompt`&&this.emit({type:`prompt`,sessionId:r,at:n});return}if(e.layoutChangedNotification?.listSessionsResponse){for(let e of this.historyOwnership.keys())this.revokeHistory(e);this.applyLayout(e.layoutChangedNotification.listSessionsResponse,t).catch(e=>{this.ownsConnection(t)&&this.log.warn(`layout refresh failed`,{error:Ao(e)})});return}if(e.newSessionNotification?.sessionId){this.client.request({case:`listSessionsRequest`,value:z(ro,{})}).then(e=>{if(this.ownsConnection(t)&&e.submessage.case===`listSessionsResponse`)return this.applyLayout(e.submessage.value,t)}).catch(e=>{this.ownsConnection(t)&&this.log.warn(`new-session layout refresh failed`,{error:Ao(e)})}),this.emit({type:`session-added`,sessionId:e.newSessionNotification.sessionId});return}if(e.terminateSessionNotification?.sessionId){let t=e.terminateSessionNotification.sessionId;this.sessions.delete(t),this.historyOwnership.delete(t),this.subscribed.delete(t),this.order=this.order.filter(e=>e!==t),this.emit({type:`session-removed`,sessionId:t}),this.emit({type:`layout-changed`});return}if(e.focusChangedNotification){e.focusChangedNotification.event.case===`session`&&(this.focused=e.focusChangedNotification.event.value),this.emit({type:`focus-changed`});return}if(e.variableChangedNotification?.identifier){let t=e.variableChangedNotification,n=this.sessions.get(t.identifier);if(!n)return;try{let e=JSON.parse(t.jsonNewValue??`null`);t.name===`session.name`&&typeof e==`string`&&(n.title=e),t.name===`session.path`&&typeof e==`string`&&(n.cwd=e),t.name===`jobName`&&typeof e==`string`&&(n.job=e)}catch{return}this.emit({type:`title-changed`,sessionId:n.id})}}};const Mo=L(P(),`Library`,`Application Support`,`iTerm2`,`private`,`socket`);var No=class extends Cn{opts;ws=null;connecting=null;nextId=1n;pending=new Map;log;constructor(e){super(),this.opts=e,this.log=e.log.child({unit:`iterm2`})}get connected(){return this.ws?.readyState===Dn.OPEN}connect(){if(this.connecting)return this.connecting;let e=this.open().finally(()=>{this.connecting===e&&(this.connecting=null)});return this.connecting=e,e}async open(){let e=this.opts.appName??`Shellbell`,t=this.opts.socketPath??Mo,n=this.opts.cookieTimeoutMs??12e4,{cookie:r,key:i}=await Po((this.opts.cookieProvider??(()=>Ua(e,n)))(),n,`iTerm2 did not answer the API cookie request`),a={origin:`ws://localhost/`,"x-iterm2-library-version":`shellbell 0.1.0`,"x-iterm2-disable-auth-ui":`true`,"x-iterm2-advisory-name":e,"x-iterm2-cookie":r,"x-iterm2-key":i},o=this.opts.connectTimeoutMs??1e4,s=this.opts.url?new Dn(this.opts.url,[`api.iterm2.com`],{headers:a,handshakeTimeout:o}):new Dn(`ws://localhost/`,[`api.iterm2.com`],{headers:a,handshakeTimeout:o,createConnection:()=>wn({path:t})});this.ws=s,await new Promise((e,t)=>{let n=()=>{s.off(`open`,i),s.off(`error`,a),s.off(`unexpected-response`,o),s.off(`close`,c)},r=e=>{n(),s.on(`error`,()=>{}),s.terminate(),this.ws===s&&(this.ws=null),t(e)},i=()=>{n(),e()},a=e=>r(e),o=(e,t)=>{t.destroy(),e.destroy(),r(Error(`iTerm2 API responded HTTP ${t.statusCode}`))},c=()=>r(Error(`iTerm2 connection closed before open`));s.once(`open`,i),s.once(`error`,a),s.once(`unexpected-response`,o),s.once(`close`,c)}),s.on(`message`,(e,t)=>{if(!t)return;let n;try{n=jn(Za,new Uint8Array(e))}catch(e){this.log.warn(`undecodable message from iTerm2`,{err:M(e)});return}if(n.submessage.case===`notification`){this.emit(`notification`,n.submessage.value);return}let r=this.pending.get(n.id);r&&(clearTimeout(r.timer),this.pending.delete(n.id),r.resolve(n))}),s.on(`close`,()=>{for(let[e,t]of this.pending)t.ws===s&&(clearTimeout(t.timer),t.reject(Error(`iTerm2 connection closed`)),this.pending.delete(e));this.ws===s&&(this.ws=null),this.emit(`close`)}),s.on(`error`,e=>this.log.warn(`iTerm2 socket error`,{err:M(e)})),this.log.info(`connected to iTerm2 API`)}close(){this.ws?.close(),this.ws=null}request(e){let t=this.ws;if(!t||t.readyState!==Dn.OPEN)return Promise.reject(Error(`iTerm2 not connected`));let n=this.nextId++,r=z(Xa,{id:n,submessage:e});return new Promise((i,a)=>{let o=setTimeout(()=>{this.pending.delete(n),a(Error(`iTerm2 request timeout (${e.case})`))},this.opts.requestTimeoutMs??5e3);this.pending.set(n,{resolve:i,reject:a,timer:o,ws:t}),t.send(Mn(Xa,r),{binary:!0})})}};function Po(e,t,n){let r,i=new Promise((e,i)=>{r=setTimeout(()=>i(Error(n)),t)});return Promise.race([e,i]).finally(()=>clearTimeout(r))}const Fo=R.object({apiVersion:R.literal(1),id:Oe,label:w,platforms:R.array(R.enum([`darwin`,`linux`])).min(1).max(2),hostCommands:R.array(R.string().regex(/^[a-zA-Z0-9._-]{1,64}$/)).max(16).optional()}),Io=R.string().min(1).max(128),Lo=R.discriminatedUnion(`type`,[R.object({type:R.literal(`focus-changed`)}),...[`screen-changed`,`session-added`,`session-removed`,`title-changed`].map(e=>R.object({type:R.literal(e),sessionId:Io})),R.object({type:R.literal(`layout-changed`)}),R.object({type:R.literal(`command-start`),sessionId:Io,command:R.string().max(512),at:R.number().finite()}),R.object({type:R.literal(`command-end`),sessionId:Io,exitCode:R.number().int(),at:R.number().finite()}),R.object({type:R.literal(`prompt`),sessionId:Io,at:R.number().finite()}),R.object({type:R.literal(`agent-state`),sessionId:Io,state:R.enum([`working`,`blocked`,`idle`,`done`,`unknown`]),agent:R.string().max(128).optional(),at:R.number().finite()})]),Ro=R.object({cols:R.number().int().min(1).max(A.cols),rows:R.number().int().min(1).max(A.rows),cursor:pe,lines:R.array(t).max(A.rows),scrollbackTotal:R.number().int().nonnegative().max(2**53-1),historyCapture:R.custom(e=>typeof e==`object`&&!!e&&!Array.isArray(e)).optional()}).refine(e=>e.lines.length===e.rows,`screen must contain every viewport row`),zo=R.number().int().nonnegative().max(2**53-1),Bo=R.discriminatedUnion(`status`,[R.object({status:R.literal(`page`),from:zo,to:zo,oldestAvailable:zo,lines:R.array(t).max(A.historyLines)}),R.object({status:R.literal(`boundary`),reason:R.enum([`end`,`truncated`]),oldestAvailable:zo}),R.object({status:R.literal(`unavailable`),reason:R.enum([`unsupported`,`unanchored`,`busy`,`changed`,`fetch-window`])}),R.object({status:R.literal(`reset`)}),R.object({status:R.literal(`cancelled`)})]);var Vo=class extends Error{};async function Ho(e,t){let n;try{return await Promise.race([e,new Promise((e,r)=>{n=setTimeout(()=>r(new Vo(`Terminal adapter deadline exceeded`)),t),n.unref()})])}finally{n&&clearTimeout(n)}}var Uo=class{raw;abort;timeoutMs;name;capabilities;connected=!1;closed=!1;generation=0;pending=0;handlers=new Set;unsubscribe;constructor(e,t,n,r=5e3){if(this.raw=e,this.abort=n,this.timeoutMs=r,this.name=Oe.parse(t),e.name!==t)throw Error(`Adapter identity does not match its manifest`);this.capabilities=Object.freeze(Ae.parse(e.capabilities));for(let t of[`connect`,`close`,`listSessions`,`getScreen`,`getHistory`,`sendText`,`createSession`,`focus`,`on`])if(typeof e[t]!=`function`)throw Error(`Adapter is missing a required method`);if(this.capabilities.terminalInput&&!e.sendInput||this.capabilities.terminalPaste&&!e.paste||this.capabilities.mouseClick&&!e.clickMouse)throw Error(`Adapter capability has no implementation`);if(this.unsubscribe=e.on(e=>{if(this.closed)return;let t=Lo.safeParse(e);if(!t.success||`sessionId`in t.data&&!this.validId(t.data.sessionId))return;let n=t.data;if(this.isConnected||n.type===`layout-changed`)for(let e of[...this.handlers])this.handlers.has(e)&&e(n)}),typeof this.unsubscribe!=`function`)throw Error(`Adapter subscription is invalid`)}get isConnected(){try{return!this.closed&&this.connected&&this.raw.isConnected!==!1}catch{return!1}}validId(e,t=!1){return(t||e.length>0)&&e.length+this.name.length+1<=128&&[...e].every(e=>e.charCodeAt(0)>=32&&e.charCodeAt(0)!==127)}async call(e){if(this.closed||this.pending>=4)throw new j(`Terminal adapter is busy`,`Try again after the adapter recovers.`);let t=this.generation;this.pending++;let n=Promise.resolve().then(()=>{if(this.closed||t!==this.generation)throw Error(`Terminal adapter generation retired`);return e()}).finally(()=>{this.pending--});try{let e=await Ho(n,this.timeoutMs);if(this.closed||t!==this.generation)throw Error(`Terminal adapter generation retired`);return e}catch(e){if(e instanceof Vo){this.connected=!1,this.generation++;for(let e of[...this.handlers])this.handlers.has(e)&&e({type:`layout-changed`})}throw e}}async connect(){if(!this.isConnected){if(this.closed||this.pending>0)throw new j(`Terminal adapter is unavailable`,`Wait for its pending operation or restart the service.`);await this.call(()=>this.raw.connect()),this.connected=!0;for(let e of[...this.handlers])this.handlers.has(e)&&e({type:`layout-changed`})}}canLaunch(){try{return!this.closed&&this.capabilities.createSession&&!!this.raw.launch&&(this.raw.canLaunch?.()??!0)}catch{return!1}}async launch(){if(!this.canLaunch())throw new E(`terminal startup`);await this.call(()=>this.raw.launch())}async close(){if(!this.closed){this.closed=!0,this.connected=!1,this.generation++,this.abort.abort(),this.handlers.clear();try{this.unsubscribe()}finally{await Ho(Promise.resolve().then(()=>this.raw.close()),this.timeoutMs)}}}async listSessions(){if(!this.isConnected)return[];let e=R.array(Ue).max(500).parse(await this.call(()=>this.raw.listSessions()));if(e.some(e=>e.backend!==this.name||!this.validId(e.id)||!this.validId(e.windowId,!0)||!this.validId(e.tabId,!0))||new Set(e.map(e=>e.id)).size!==e.length)throw Error(`Adapter returned invalid session identities`);return e}async getScreen(e,t){return Ro.parse(await this.call(()=>this.raw.getScreen(e,t)))}async getHistory(e,n,r){return R.object({lines:R.array(t).max(1e3),oldestAvailable:R.number().int().nonnegative()}).parse(await this.call(()=>this.raw.getHistory(e,n,r)))}async getHistoryPage(e,t){if(!this.raw.getHistoryPage)return{status:`unavailable`,reason:`unsupported`};let n=Bo.parse(await this.call(()=>this.raw.getHistoryPage(e,t)));if(n.status===`page`&&(n.to-n.from!==n.lines.length||n.from<n.oldestAvailable||n.to>t.before||n.lines.length>t.count))throw Error(`Adapter returned an invalid history range`);return n}async sendText(e,t){await this.call(()=>this.raw.sendText(e,t))}async sendInput(e,t){if(!this.raw.sendInput)throw new E(`terminal input`);await this.call(()=>this.raw.sendInput(e,t))}async paste(e,t,n){if(!this.raw.paste)throw new E(`terminal paste`);await this.call(()=>this.raw.paste(e,t,n))}async clickMouse(e,t){if(!this.raw.clickMouse)throw new E(`mouse input`);await this.call(()=>this.raw.clickMouse(e,t))}async createSession(e){let t=await this.call(()=>this.raw.createSession(e));if(!this.validId(t))throw Error(`Adapter returned an invalid session identity`);return t}async focus(e){await this.call(()=>this.raw.focus(e))}on(e){return this.handlers.add(e),()=>{this.handlers.delete(e)}}setWatched(e){this.raw.setWatched?.(e)}setReported(e,t){this.raw.setReported?.(e,t)}hostedProcess(e){let t=this.raw.hostedProcess?.(e);return t===void 0?void 0:R.string().max(128).refine(e=>[...e].every(e=>e.charCodeAt(0)>=32&&e.charCodeAt(0)!==127)).parse(t)}representedWindows(){return R.array(R.object({backend:Oe,windowId:R.string().min(1).max(128)})).max(500).parse(this.raw.representedWindows?.()??[])}nativeWindowIdOf(e){let t=this.raw.nativeWindowIdOf?.(e);return t===void 0?void 0:R.string().min(1).max(128).parse(t)}};function Wo(e){let t=!1,n=[],r=new Set(Ee.options),i=e.timeoutMs??5e3;return{ready:(async()=>{for(let a of e.paths){if(t)break;let o=new AbortController;n.push(()=>o.abort());let s,c,u=!1,d=async e=>{u||(u=!0,await Ho(Promise.resolve().then(()=>e.close()),i).catch(()=>{}))};try{if(e.admitPath)e.admitPath(a);else{if(qt(a).isSymbolicLink()||tn(a)!==a)throw Error(`Adapter path must be canonical`);l(a,262144,process.getuid())}let u=await Ho((e.importModule??Pn)(_n(a).href),i),f=Fo.parse(u.default);if(r.has(f.id))throw Error(`Adapter identity is already registered`);if(!f.platforms.includes(e.platform??process.platform)){o.abort();continue}let p=u.default;if(typeof p.create!=`function`)throw Error(`Adapter factory is missing`);let m=Promise.resolve().then(()=>p.create({log:e.log.child({adapter:f.id}),signal:o.signal}));if(m.then(async e=>{o.signal.aborted&&await d(e)},()=>{}),c=await Ho(m,i),t){o.abort(),await d(c);break}s=new Uo(c,f.id,o,i),r.add(f.id),e.registry.add(s,f.label,f.hostCommands??[]);let h=c.launch?e.registry.registerSessionLauncher(f.id,{available:()=>s?.canLaunch()??!1,start:async()=>(await _.launch(),await _.connect(),{backend:_})}):void 0,g,_=s,v=async()=>{if(!t){if(e.registry.member(f.id)!==_){await _.close().catch(()=>{});return}try{await _.connect()}catch(t){e.log.debug(`terminal adapter unavailable`,{adapter:f.id,error:M(t)})}t||(g=setTimeout(()=>{v()},e.retryMs??1e4),g.unref())}};n.push(()=>{h?.(),g&&clearTimeout(g),e.registry.member(f.id)===_&&e.registry.remove(f.id),_.close().catch(t=>e.log.warn(`terminal adapter cleanup failed`,{adapter:f.id,error:M(t)}))}),v()}catch(t){o.abort(),s?await s.close().catch(()=>{}):c&&await d(c),e.log.warn(`terminal plugin could not be loaded`,{error:M(t)})}}})(),stop(){t=!0;for(let e of n.splice(0))e()}}}const Go={iterm2:{bundle:`iTerm.app`,label:`iTerm2`}},Ko=An(zt);function qo(e,t={}){if((t.platform??process.platform)!==`darwin`)return null;let n=t.roots??[`/Applications`,L(P(),`Applications`)],r=t.exists??Ut,i=Go[e],a=()=>n.map(e=>L(e,i.bundle)).find(r);return{available:()=>a()!==void 0,start:async()=>{let e=a();if(!e)throw new j(`${i.label} is not installed`,`Install ${i.label} on your computer.`);try{await(t.execute??((e,t)=>Ko(e,t,{timeout:5e3,maxBuffer:4096})))(`/usr/bin/open`,[`-g`,`-a`,e])}catch{throw new j(`Could not launch ${i.label}`,`Open ${i.label} on your computer and check its local API.`)}}}}function Jo(e={}){let t=()=>ra(e.env,e.executable);return{available:()=>t()!==void 0,start:async()=>{let n=t();if(!n)throw new j(`Herdr is not installed`,`Install Herdr on your computer.`);await new Promise((t,r)=>{let i=(e.spawnImpl??Bt)(n,[`server`],{detached:!0,stdio:`ignore`,env:e.env??process.env});i.once(`error`,()=>r(new j(`Could not start Herdr`,`Check your Herdr installation.`))),i.once(`spawn`,()=>{i.unref(),t()})})}}}function Yo(e,t,n=2e4){return new Promise((r,i)=>{let a=setTimeout(()=>{s(),i(new j(`${t} did not become ready`,`Check the terminal application's local API on your computer.`))},n);a.unref();let o=()=>{e.connected().some(e=>e.name===t)&&(clearTimeout(a),s(),r())},s=e.on(o);o()})}const Xo=An(zt);function Zo(e){let t=[e.executable,...e.args],n=e=>[...e].every(e=>e.charCodeAt(0)>=32&&e.charCodeAt(0)!==127);if(!I(e.executable)||t.some(e=>!n(e))||t.reduce((e,t)=>e+t.length,0)>4096)throw Error(`Invalid terminal command`);let r=Object.entries(e.environment??{}).map(([e,t])=>{if(!/^[A-Z_][A-Z0-9_]*$/.test(e)||!n(t))throw Error(`Invalid terminal environment`);return`${e}=${t}`}),i=e=>`'${e.replace(/'/g,`'\\''`)}'`,a=[...r.length?[`/usr/bin/env`,...r]:[],...t].map(i).join(` `);if(a.length>8192)throw Error(`Terminal command is too large`);return a}async function Qo(e,t){try{await e()}catch{try{await t()}catch{throw new De(`The terminal window could not open on your computer, and the new session could not be closed. Check the session list.`)}throw new De(`The terminal window didn't open on your computer, so the new session was closed. If your computer is locked, unlock it and try again.`)}}function $o(e={}){if((e.platform??process.platform)!==`darwin`)return null;let t=()=>(e.roots??[`/Applications`,L(P(),`Applications`)]).map(e=>L(e,`Ghostty.app`)).find(e.exists??Ut);return{id:`ghostty`,label:`Ghostty`,available:()=>t()!==void 0,async launch(n){let r=t();if(!r)throw new j(`Ghostty is not installed`,`Install Ghostty on your computer.`);let i=Zo(n);try{await(e.execute??((e,t)=>Xo(e,t,{timeout:5e3,maxBuffer:4096})))(`/usr/bin/open`,[`-n`,`-a`,r,`--args`,`--initial-window=true`,`--window-save-state=never`,`--quit-after-last-window-closed=true`,`--initial-command=${i}`])}catch{throw new j(`Ghostty could not be launched`,`Check that Ghostty opens on your computer, then try again.`)}}}}async function es(e,t=fetch){let n;try{let t=new URL(e),r={"ws:":`http:`,"wss:":`https:`,"http:":`http:`,"https:":`https:`}[t.protocol];if(!r||!t.hostname)return!1;t.protocol=r,t.username=``,t.password=``,t.pathname=`/healthz`,t.search=``,t.hash=``,n=t.toString()}catch{return!1}let r=new AbortController,i=null,a=setTimeout(()=>{r.abort(),i?.cancel().catch(()=>{})},5e3);try{let e=await t(n,{redirect:`manual`,signal:r.signal});if(!e.body||(i=e.body.getReader(),e.status!==200))return!1;let a=[],o=0;for(;;){let{done:e,value:t}=await i.read();if(e)break;if(o+=t.byteLength,o>4096)return!1;a.push(t)}return!r.signal.aborted&&Buffer.concat(a,o).toString(`utf8`)===`ok`}catch{return!1}finally{if(clearTimeout(a),r.abort(),i){i.cancel().catch(()=>{});try{i.releaseLock()}catch{}}}}const ts=65536,ns=16384,rs=`# shellbell-systemd-v1 `,is=R.string().max(ns).refine(e=>{for(let t of e){let e=t.codePointAt(0);if(e<32||e>=127&&e<=159||e>=55296&&e<=57343)return!1}return!0}),as=is.refine(I),os=R.strictObject({v:R.literal(1),machineId:R.string().regex(/^[0-9a-f]{32}$/).refine(e=>e!==`0`.repeat(32)),nodePath:as.refine(e=>!/["'\\]/.test(e)),cliPath:as,stateDir:as,runtimeRoot:as,serviceInstance:R.uuid(),path:is.refine(e=>{let t=e.split(`:`);return t.every(I)&&new Set(t).size===t.length})});function G(){throw Error(`shellbell: invalid or foreign systemd unit`)}function ss(e){return`"${e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`).replaceAll(`%`,`%%`)}"`}function cs(e,t){return`Environment=${ss(`${e}=${t}`)}`}function ls(e){let t=os.safeParse(e);t.success||G();let n=t.data,r=2;for(let[e,t]of Object.entries(n))r+=e.length+3+(r===2?0:1),r+=typeof t==`number`?1:Buffer.byteLength(t)+2+[...t].filter(e=>e===`"`||e===`\\`).length;r>ns&&G();let i=JSON.stringify(n);Buffer.byteLength(i)>ns&&G();let a=Buffer.from([rs+Buffer.from(i).toString(`base64url`),`[Unit]`,`Description=Shellbell terminal host`,`ConditionHost=${n.machineId}`,`StartLimitIntervalSec=60s`,`StartLimitBurst=3`,``,`[Service]`,`Type=exec`,`ExecStart=${[`:${n.nodePath}`,n.cliPath,`start`,`--service`].map(ss).join(` `)}`,cs(`SHELLBELL_DIR`,n.stateDir),cs(`SHELLBELL_SERVICE_INSTANCE`,n.serviceInstance),cs(`XDG_RUNTIME_DIR`,n.runtimeRoot),cs(`PATH`,n.path),`Restart=on-failure`,`RestartSec=5s`,`TimeoutStopSec=15s`,`UMask=0077`,`StandardInput=null`,`StandardOutput=null`,`StandardError=journal`,`KillMode=control-group`,``,`[Install]`,`WantedBy=default.target`,``].join(`
22
+ `));return a.length>ts&&G(),a}function us(e){try{e.byteLength>ts&&G();let t=Buffer.from(e),n=t.subarray(0,t.indexOf(10)).toString(`utf8`);n.startsWith(rs)||G();let r=n.slice(23);(r.length>21846||!/^[A-Za-z0-9_-]+$/.test(r))&&G();let i=Buffer.from(r,`base64url`);(i.length>ns||i.toString(`base64url`)!==r)&&G();let a=os.parse(JSON.parse(i.toString(`utf8`)));return ls(a).equals(t)||G(),a}catch{return G()}}function ds(e,t){let n=O(e);n&&(!n.isDirectory()||n.isSymbolicLink()||n.uid!==t||n.mode&18)&&G()}function fs(e,t){as.safeParse(e).success||G();let n=O(e)?tn(e):jt(e);return ds(n,t),n}function ps(e){let{uid:t,hostScope:n}=e.identity;(!Number.isSafeInteger(t)||t<=0||!/^[0-9a-f]{32}$/.test(n))&&G();let r=fs(e.home,t),i=fs(e.env.XDG_CONFIG_HOME&&I(e.env.XDG_CONFIG_HOME)?e.env.XDG_CONFIG_HOME:L(r,`.config`),t),a=L(i,`systemd`,`user`);for(let e of[L(i,`systemd`),a])ds(e,t);let o=`shellbell-${n}.service`,s=L(a,o),c=O(s);return c&&(!c.isFile()||c.isSymbolicLink()||c.uid!==t||(c.mode&4095)!=384)&&G(),{uid:t,home:r,configRoot:i,unitName:o,unitDir:a,definitionPath:s,enablementPath:L(a,`default.target.wants`,o),managerRuntimeRoot:`/run/user/${t}`}}function K(){throw Error(`shellbell: unsafe, foreign or concurrently changed systemd files`)}function ms(e,t){return d(e,t)&&e.mode===t.mode&&e.uid===t.uid&&e.size===t.size&&e.mtimeMs===t.mtimeMs&&e.ctimeMs===t.ctimeMs}var hs=class{location;machineId;constructor(e,t){this.location=e,this.machineId=t}directory(e,t=!1){let n=O(e);return!n&&t&&(this.directory(F(e),!0),Jt(e,{mode:448}),n=O(e)),n&&(!n.isDirectory()||n.isSymbolicLink()||n.uid!==this.location.uid||n.mode&18)&&K(),n}parents(e=!1){let t=[this.location.home,this.location.configRoot,L(this.location.configRoot,`systemd`),this.location.unitDir,F(this.location.enablementPath)],n=[];for(let r of t){let t=this.directory(r,e&&r!==F(this.location.enablementPath));t&&n.push({path:r,stat:t})}return n}inspect(){let e=this.parents(),t=O(this.location.definitionPath),n=null;if(t){let e=l(this.location.definitionPath,65536,this.location.uid),r=us(e);(r.machineId!==this.machineId||!ms(t,O(this.location.definitionPath)))&&K(),n={stat:t,raw:e,definition:r}}let r=O(this.location.enablementPath),i=null;if(r){let e=r.isSymbolicLink()?en(this.location.enablementPath):null;ms(r,O(this.location.enablementPath))||K(),i={stat:r,target:e,owned:r.uid===this.location.uid&&e===this.location.definitionPath}}for(let t of e){let e=this.directory(t.path);(!e||!d(t.stat,e))&&K()}return{unit:n,link:i,parents:e}}assertUnchanged(e){let t=this.inspect();for(let t of e.parents??[]){let e=this.directory(t.path);(!e||!d(t.stat,e))&&K()}(!!t.unit!=!!e.unit||!!t.link!=!!e.link)&&K(),t.unit&&e.unit&&(!ms(t.unit.stat,e.unit.stat)||!t.unit.raw.equals(e.unit.raw))&&K(),t.link&&e.link&&(!ms(t.link.stat,e.link.stat)||t.link.target!==e.link.target)&&K()}matchesFragment(e){try{let t=O(e);return!!t&&t.isFile()&&!t.isSymbolicLink()&&t.uid===this.location.uid&&(t.mode&4095)==384&&L(tn(F(e)),un(e))===this.location.definitionPath}catch{return!1}}publish(e,t){(t.machineId!==this.machineId||e.link&&!e.link.owned)&&K();let n=ls(t);this.assertUnchanged(e),this.parents(!0);let r=`${this.location.definitionPath}.tmp-${xn()}`,i;try{let t=Yt(r,N.O_WRONLY|N.O_CREAT|N.O_EXCL|N.O_NOFOLLOW,384);try{i=O(r),cn(t,n),Gt(t)}finally{Ht(t)}this.assertUnchanged(e),e.unit?nn(r,this.location.definitionPath):Kt(r,this.location.definitionPath)}finally{let e=O(r);i&&e&&d(i,e)&&sn(r)}return this.inspect()}setEnabled(e,t){return this.assertUnchanged(e),e.link&&!e.link.owned&&K(),t===!!e.link?e:(t?(e.unit||K(),this.directory(F(this.location.enablementPath),!0),this.assertUnchanged(e),on(this.location.definitionPath,this.location.enablementPath)):(this.assertUnchanged(e),sn(this.location.enablementPath)),this.inspect())}remove(e){return this.assertUnchanged(e),e.link?.owned&&K(),e.unit&&sn(this.location.definitionPath),this.inspect()}restore(e,t){try{this.assertUnchanged(t);let n=t;e.unit&&!n.unit?.raw.equals(e.unit.raw)&&(n=this.publish(n,e.unit.definition)),!!n.link!=!!e.link&&(n=this.setEnabled(n,!!e.link)),e.unit||this.remove(n)}catch{try{this.parents(),e.unit&&cn(`${this.location.definitionPath}.recovery-${xn()}`,e.unit.raw,{flag:`wx`,mode:384})}catch{}throw Error(`shellbell: unresolved systemd file recovery; inspect owned artifacts before retrying`)}}};const gs=[`LoadState`,`ActiveState`,`SubState`,`MainPID`,`UnitFileState`,`FragmentPath`,`DropInPaths`,`NeedDaemonReload`,`ConditionResult`],_s=[`--user`,`--no-pager`,`--no-ask-password`],vs=new Set([16914836,61267,1481003842,2435016766]),q=()=>Error(`shellbell: systemd command failed`);function ys(e){for(let t of e){let e=t.codePointAt(0);if(e<32||e>=127&&e<=159||e>=55296&&e<=57343)return!1}return!0}const bs=()=>({available:!1,loadState:`unknown`,activeState:`unknown`,subState:`unknown`,mainPid:null,unitFileState:`unknown`,fragmentPath:``,dropInPaths:``,needDaemonReload:!0,conditionResult:!1,diagnostic:`systemd user manager unavailable or returned unsupported state`});function xs(e){for(let t of[`/usr/bin`,`/bin`]){let n=L(t,e);try{return Vt(n,N.X_OK),n}catch{}}throw q()}const Ss=(e,t,n)=>new Promise((r,i)=>{let a=Bt(e,[...t],{shell:!1,env:n.env,stdio:[`ignore`,`pipe`,`pipe`]}),o=0,s=[],c=!1,l=!1,u,d=setTimeout(p,n.timeoutMs);function f(e){c||(c=!0,clearTimeout(d),clearTimeout(u),a.stdout.destroy(),a.stderr.destroy(),l||e==null?i(q()):r({exitCode:e,stdout:Buffer.concat(s)}))}function p(){c||l||(l=!0,a.kill(`SIGTERM`),u=setTimeout(()=>{a.kill(`SIGKILL`),f()},250))}function m(e,t){if(!(c||l)){if(o+=e.length,o>n.maxOutputBytes){p();return}t&&s.push(Buffer.from(e))}}a.stdout.on(`data`,e=>m(e,!0)),a.stderr.on(`data`,e=>m(e,!1)),a.on(`error`,()=>f()),a.on(`close`,e=>f(e))});function Cs(e){if(e.length>65536)throw q();let t=new TextDecoder(`utf-8`,{fatal:!0}).decode(e),n=t.endsWith(`
23
+ `)?t.slice(0,-1).split(`
24
+ `):t.split(`
25
+ `),r=new Map;for(let e of n){let t=e.indexOf(`=`),n=e.slice(0,t),i=e.slice(t+1);if(t<0||!gs.includes(n)||r.has(n)||!ys(i))throw q();r.set(n,i)}if(r.size!==gs.length)throw q();let i=e=>r.get(e);for(let[e,t]of Object.entries({LoadState:[`stub`,`loaded`,`not-found`,`bad-setting`,`error`,`merged`,`masked`],ActiveState:[`active`,`reloading`,`inactive`,`failed`,`activating`,`deactivating`,`maintenance`],SubState:[`dead`,`condition`,`start-pre`,`start`,`start-post`,`running`,`exited`,`reload`,`stop`,`stop-watchdog`,`stop-sigterm`,`stop-sigkill`,`stop-post`,`final-sigterm`,`final-sigkill`,`failed`,`auto-restart`,`cleaning`],UnitFileState:[``,`enabled`,`enabled-runtime`,`linked`,`linked-runtime`,`alias`,`masked`,`masked-runtime`,`static`,`disabled`,`indirect`,`generated`,`transient`,`bad`]}))if(!t.includes(i(e)))throw q();if(!/^(0|[1-9][0-9]*)$/.test(i(`MainPID`)))throw q();let a=Number(i(`MainPID`));if(!Number.isSafeInteger(a))throw q();for(let e of[`NeedDaemonReload`,`ConditionResult`])if(![`yes`,`no`].includes(i(e)))throw q();let o=i(`FragmentPath`);if(o&&!I(o))throw q();return{available:!0,loadState:i(`LoadState`),activeState:i(`ActiveState`),subState:i(`SubState`),mainPid:a||null,unitFileState:i(`UnitFileState`),fragmentPath:o,dropInPaths:i(`DropInPaths`),needDaemonReload:i(`NeedDaemonReload`)===`yes`,conditionResult:i(`ConditionResult`)===`yes`}}function ws(e){return`unix:path=${[...Buffer.from(e)].map(e=>/[A-Za-z0-9_./-]/.test(String.fromCharCode(e))?String.fromCharCode(e):`%${e.toString(16).padStart(2,`0`)}`).join(``)}`}function Ts(e){let t={...e.location},n=e.run??Ss;async function r(r,i){try{let{uid:a}=t;if(!Number.isSafeInteger(a)||a<=0||a!==process.getuid?.()||a!==process.geteuid?.()||!/^shellbell-[0-9a-f]{32}\.service$/.test(t.unitName))throw q();for(let e of[t.home,t.configRoot,t.managerRuntimeRoot])if(!I(e)||!ys(e))throw q();m(t.managerRuntimeRoot,a);let o=e.runtimeFsType?.(t.managerRuntimeRoot)??an(t.managerRuntimeRoot).type;if(!vs.has(Number(o)))throw q();let s=await n(e.run?`/usr/bin/${r}`:xs(r),i,{timeoutMs:3e4,maxOutputBytes:65536,env:{HOME:t.home,XDG_CONFIG_HOME:t.configRoot,XDG_RUNTIME_DIR:t.managerRuntimeRoot,DBUS_SESSION_BUS_ADDRESS:ws(L(t.managerRuntimeRoot,`bus`)),PATH:`/usr/bin:/bin`,LANG:`C`,LC_ALL:`C`}});if(s.exitCode!==0||s.stdout.length>65536)throw q();return s.stdout}catch{throw q()}}return{async observe(){try{return Cs(await r(`systemctl`,[..._s,`show`,`--property=${gs.join(`,`)}`,t.unitName]))}catch{return bs()}},async execute(e){if(![`start`,`stop`,`daemon-reload`].includes(e))throw q();await r(`systemctl`,[..._s,e,...e===`daemon-reload`?[]:[t.unitName]])},async linger(){try{let e=(await r(`loginctl`,[`--no-pager`,`--no-ask-password`,`show-user`,String(t.uid),`--property=Linger`,`--value`])).toString(`utf8`);if(e===`yes
26
+ `||e===`yes`)return`yes`;if(e===`no
27
+ `||e===`no`)return`no`}catch{}return`unknown`}}}const J=e=>e.activeState===`inactive`||e.activeState===`failed`,Es=e=>[`enabled`,`enabled-runtime`].includes(e.unitFileState);function Y(e){throw Error(`shellbell: ${e}`)}var Ds=class{options;machine;location;files;manager;readiness;clock;constructor(e){this.options=e,this.machine=Nt(e.machine),this.location=ps({identity:this.machine,env:e.env,home:e.home??P()}),this.files=new hs(this.location,this.machine.machineId),this.manager=e.manager??Ts({location:this.location,runtimeFsType:e.runtimeFsType}),this.readiness=new dt(e),this.clock=e.clock??{now:()=>Fn.now(),sleep:e=>new Promise(t=>setTimeout(t,e))}}select(e,t,n=!1){let r=e.unit?.definition;r&&this.options.env.SHELLBELL_DIR!==void 0&&jt(this.options.env.SHELLBELL_DIR)!==r.stateDir&&Y(`SHELLBELL_DIR conflicts with installed service state; explicit migration is required`);let i;try{let e={...this.options.env,...r?{SHELLBELL_DIR:r.stateDir,...n?{}:{XDG_RUNTIME_DIR:r.runtimeRoot}}:{}};i=(this.options.selectPaths??(e=>Ft({...this.options.machine,env:e,home:this.options.home,runtimeFsType:this.options.runtimeFsType})))(e),(i.linuxHost.uid!==this.machine.uid||i.linuxHost.hostDigest!==this.machine.hostDigest||r&&i.dir!==r.stateDir)&&Y(`selected Linux paths do not match owned service`)}catch{return t&&Y(`Linux service runtime/state selection is unsafe or unavailable`),{degraded:!0}}try{let e=ct(i);return{paths:i,degraded:!1,expected:{computerFp:e.fp,stateDir:i.dir,...r?{serviceInstance:r.serviceInstance}:{}}}}catch{return t&&Y(`Linux host state is not ready; restore initialized credentials before granting service access`),{paths:i,degraded:!0}}}ownedManager(e,t,n=!1){return!t.available||t.dropInPaths!==``||t.needDaemonReload?!1:n&&!e.unit&&[``,`disabled`,`enabled`,`enabled-runtime`].includes(t.unitFileState)&&t.loadState===`not-found`&&t.fragmentPath===``&&J(t)&&t.mainPid===null?!0:![`disabled`,`enabled`,`enabled-runtime`,`linked`,`linked-runtime`].includes(t.unitFileState)||![`inactive`,`failed`,`active`,`activating`,`deactivating`].includes(t.activeState)?!1:!!e.unit&&t.loadState===`loaded`&&this.files.matchesFragment(t.fragmentPath)}assertManager(e,t,n=!1){this.files.assertUnchanged(e),this.ownedManager(e,t,n)||Y(`systemd manager ownership is unavailable, foreign or unresolved; inspect exact unit discovery and overrides`)}async local(e,t,n,r=500){if(!t.paths)return{kind:`unverified`,local:null,diagnostic:`Local certification degraded; runtime is unsafe or unavailable`};let i=await this.readiness.observe(t.paths.sock,t.expected?{...t.expected,...n.mainPid?{pid:n.mainPid}:{}}:void 0,r);return i.local&&e.unit&&(i.local.process.pid!==n.mainPid||!bt(i.local,{computerFp:t.expected?.computerFp??i.local.process.computerFp,stateDir:e.unit.definition.stateDir,serviceInstance:e.unit.definition.serviceInstance}))?{kind:`foreign`,local:i.local,diagnostic:`Local endpoint contradicts owned manager job`}:i}async result(e,t,n,r=!1){let i=await this.manager.observe(),a=this.ownedManager(e,i,!0),o=await this.local(e,t,i),s=await this.manager.observe(),c=!0;try{this.files.assertUnchanged(e)}catch{c=!1}let l=c&&a&&this.ownedManager(e,s,!0)&&i.mainPid===s.mainPid&&i.activeState===s.activeState,u=!!e.unit&&l&&!t.degraded&&i.activeState===`active`&&i.mainPid!==null&&i.conditionResult&&s.conditionResult&&o.kind===`verified`;r&&(!l||!J(s)||s.mainPid!==null||t.paths&&o.kind!==`absent`)&&Y(`service stop final confirmation is unresolved; current job or endpoint is not verified stopped`);let d=Es(s)&&!e.link?.owned||e.link&&!e.link.owned;return{manager:`systemd`,unitName:this.location.unitName,definitionPath:this.location.definitionPath,installed:!!e.unit,enabled:Es(s),startupEnabled:s.available?Es(s):null,autostartConfigured:!!e.link?.owned,activeState:s.activeState,managedPid:s.mainPid,ownership:!l||o.kind===`foreign`?`foreign`:t.degraded?`degraded`:e.unit?`verified`:`none`,ready:u,local:o.local,linger:await this.manager.linger(),...n||d||t.degraded||!l||o.diagnostic?{diagnostic:[n,d?`Remaining external enablement is outside Shellbell's owned link`:void 0,t.degraded?`Local identity/runtime certification degraded; credentials were not repaired`:void 0,l?void 0:`Manager ownership is unresolved`,o.diagnostic].filter(Boolean).join(`; `)}:{}}}async status(){let e=this.files.inspect();return this.result(e,this.select(e,!1))}async serialized(e,t,n){let r=this.files.inspect(),i=this.select(r,e,t),a=async()=>{let t;try{return i.paths&&(kt(i.paths),t=ue(L(i.paths.runtimeDir,`service`))),this.files.assertUnchanged(r),e&&ct(i.paths),await n(r,i,!!t)}finally{t?.()}},o=i.paths?.dir??r.unit?.definition.stateDir;return o?Be({stateDir:o,uid:this.machine.uid,create:t,startupPreference:e=>e.autostartConfigured},a):a()}async execute(e,t){this.files.assertUnchanged(t);try{await this.manager.execute(e)}catch{Y(`systemd ${e} failed or timed out; manager effect may be unresolved`)}}async install(){let e=(this.options.resolveRuntime??Ne)(),t=[`/usr/local/bin`,`/usr/bin`,`/bin`],n=(this.options.env.PATH??``).split(`:`).filter(e=>I(e)&&!t.includes(e));return this.serialized(!0,!0,async(r,i)=>{let a=r.unit?.definition,o={v:1,machineId:this.machine.machineId,nodePath:e.nodePath,cliPath:e.cliPath,stateDir:i.paths.dir,runtimeRoot:F(F(i.paths.runtimeDir)),serviceInstance:a?.serviceInstance??xn(),path:[...new Set([F(e.nodePath),...n,...t])].join(`:`)},s=ls(o),c=await this.manager.observe();if(this.assertManager(r,c,!r.unit),r.unit?.raw.equals(s))return this.result(r,i);(!J(c)||c.mainPid!==null)&&Y(`active service definition cannot be updated; stop, install, then start explicitly`),(await this.local(r,i,c)).kind!==`absent`&&Y(`local endpoint ownership is foreign or unverified; stop foreground owner before install`);let l=await this.manager.observe();this.assertManager(r,l,!r.unit),(!J(l)||l.mainPid!==null)&&Y(`active service job changed during install admission; stop before updating`),a&&(o.serviceInstance=xn());let u;try{return u=this.files.publish(r,o),await this.execute(`daemon-reload`,u),this.assertManager(u,await this.manager.observe()),await this.result(u,i)}catch{if(u){this.files.restore(r,u);try{await this.manager.execute(`daemon-reload`)}catch{Y(`systemd install failed; definition restored but manager reload remains unresolved`)}}Y(`systemd install failed; owned definition restored where possible, inspect manager discovery`)}})}enable(){return this.link(!0)}disable(){return this.link(!1)}link(e){return this.serialized(e,!1,async(t,n,r)=>{let i=await this.manager.observe();if(this.assertManager(t,i,!t.unit&&!e),!t.unit&&e&&Y(`service is not installed; run service install first`),t.link&&!t.link.owned)return e&&Y(`foreign autostart leaf prevents service enablement`),this.result(t,n,`Foreign autostart artifact remains; inspect it explicitly`);if(!r)return this.result(t,n,`Owned autostart cleanup remains; restore a safe local runtime before changing files`);if(!!t.link===e)return this.result(t,n);let a=this.files.setEnabled(t,e);try{await this.execute(`daemon-reload`,a),this.assertManager(a,await this.manager.observe(),!a.unit)}catch{e&&this.files.restore(t,a),Y(`systemd ${e?`enable`:`disable`} reload failed; inspect remaining manager state`)}return this.result(a,n)})}start(){return this.run(`start`)}restart(){return this.run(`restart`)}stop(){return this.run(`stop`)}uninstall(){return this.run(`uninstall`)}async stopped(e,t,n){let r=this.clock.now()+1e4;for(;this.clock.now()<r;){let i=await this.manager.observe();this.assertManager(e,i),i.mainPid!==null&&i.mainPid!==n&&Y(`service stop manager job changed; ownership unresolved`);let a=await this.local(e,t,{...i,mainPid:n},Math.min(500,r-this.clock.now()));a.kind===`foreign`&&Y(`service stop ownership changed; endpoint is foreign`);let o=await this.manager.observe();if(this.assertManager(e,o),(o.mainPid!==null&&o.mainPid!==n||J(i)&&!J(o))&&Y(`service stop manager job changed during local probe; ownership unresolved`),J(o)&&o.mainPid===null&&(!t.paths||a.kind===`absent`))return;await this.clock.sleep(Math.min(100,Math.max(0,r-this.clock.now())))}Y(`service stop timed out; stopped state remains unresolved`)}async stopOwned(e,t){let n=await this.manager.observe();this.assertManager(e,n);let r=await this.local(e,t,n);r.kind===`foreign`&&Y(`local endpoint ownership is foreign; refusing service stop`);let i=await this.manager.observe();this.assertManager(e,i),(i.mainPid!==n.mainPid||J(n)&&!J(i))&&Y(`service stop ownership changed during local probe`),(!J(i)||i.mainPid!==null||t.paths&&r.kind!==`absent`)&&(await this.execute(`stop`,e),await this.stopped(e,t,n.mainPid))}async ready(e,t,n={}){let r=this.clock.now()+1e4;for(;this.clock.now()<r;){let i=await this.manager.observe();this.assertManager(e,i),n.pid!==void 0&&i.mainPid!==n.pid&&Y(`service readiness manager job changed`),i.mainPid!==null&&(n.pid??=i.mainPid);let a=await this.local(e,t,i,Math.min(500,r-this.clock.now()));a.kind===`foreign`&&Y(`service readiness ownership is foreign`);let o=await this.manager.observe();if(this.assertManager(e,o),o.mainPid!==i.mainPid&&Y(`service readiness manager job changed`),o.activeState===`active`&&o.conditionResult&&o.mainPid!==null&&a.kind===`verified`)return a.local;await this.clock.sleep(Math.min(100,Math.max(0,r-this.clock.now())))}Y(`service readiness timed out`)}async cleanupStart(e,t,n){let r=await this.manager.observe();this.assertManager(e,r);let i=await this.local(e,t,r),a=await this.manager.observe();this.assertManager(e,a),(a.mainPid!==r.mainPid||J(r)&&!J(a))&&Y(`start ownership changed during local probe; cleanup unresolved`),!(J(a)&&a.mainPid===null&&i.kind===`absent`)&&((r.mainPid===null||n.pid!==void 0&&n.pid!==r.mainPid||![`verified`,`absent`].includes(i.kind))&&Y(`start ownership unresolved; no cleanup stop was attempted`),await this.execute(`stop`,e),await this.stopped(e,t,r.mainPid))}run(e){let t=e===`stop`||e===`uninstall`;return this.serialized(!t,!1,async(n,r,i)=>{let a=await this.manager.observe();if(this.assertManager(n,a,!n.unit&&t),!n.unit)return t||Y(`service is not installed; run service install first`),this.result(n,r);let o=await this.local(n,r,a);if(o.kind===`foreign`&&Y(`local endpoint ownership is foreign`),e!==`start`&&await this.stopOwned(n,r),t){let t=n;e===`uninstall`&&i&&((!t.link||t.link.owned)&&(t=this.files.setEnabled(t,!1)),t=this.files.remove(t),await this.execute(`daemon-reload`,t),this.assertManager(t,await this.manager.observe(),!0));let a=e===`uninstall`?i?`Service uninstalled; credentials remain unchanged`:`Service stopped; owned definition and autostart cleanup remain until runtime is safe`:`Service stopped; if enabled, it may start after a later user-manager restart`;return this.result(t,r,a,!0)}if(e===`start`&&a.activeState===`active`){await this.ready(n,r);let e=await this.result(n,r);return e.ready||Y(`service start readiness changed during final confirmation`),e}e===`start`&&(!J(a)||a.mainPid!==null||o.kind!==`absent`)&&Y(`service start ownership is unresolved; stop the foreground or pending owner first`);let s=await this.manager.observe();this.assertManager(n,s),(!J(s)||s.mainPid!==null)&&Y(`service start manager job changed before command; ownership unresolved`);let c={};try{await this.execute(`start`,n),await this.ready(n,r,c);let e=await this.result(n,r);return e.ready||Y(`service start readiness changed during final confirmation`),e}catch{try{await this.cleanupStart(n,r,c)}catch{Y(`service start failed; ownership or cleanup remains unresolved`)}Y(`service start failed; newly started owned job was stopped`)}})}};const Os=An(zt);function ks(e){let t=/(\d+)\.(\d+)/.exec(e);return t?Number(t[1])+Number(t[2])/100:null}function As(e){return+!!e.some(e=>e.severity===`error`)}function js(e,t){return{name:e,ok:!0,severity:`pass`,detail:t}}function X(e,t,n){return{name:e,ok:!0,severity:`warning`,detail:t,...n?{fix:n}:{}}}function Z(e,t,n){return{name:e,ok:!1,severity:`error`,detail:t,...n?{fix:n}:{}}}function Ms(e,t,n,r){return t?{...js(e,`connected to the local agent`),...n?{required:n}:{}}:n?{...Z(e,`required backend is not connected; ${r.detail}`,r.fix),required:!0}:r}function Ns(e,t){for(let n of t.PATH?.split(dn)??[])if(n)try{return Vt(L(n,e),N.X_OK),!0}catch{}return!1}async function Ps(e){return(await Os(`tmux`,[`-V`],{env:e,timeout:3e3,maxBuffer:65536})).stdout}async function Fs(e){return za({socketPath:Ti(e),herdrOnPath:()=>Ns(`herdr`,e)})}function Is(e,t){if(!e.installed||!e.definition)return{env:t,context:`current shell setup`};let n=e.definition.environment;return{env:{PATH:n.PATH,HERDR_SOCKET_PATH:n.HERDR_SOCKET_PATH,XDG_CONFIG_HOME:n.XDG_CONFIG_HOME},context:`installed service setup`}}function Ls(e,t){return e.loaded&&!e.installed?Z(`service manager`,`loaded service has no installed definition`):e.installed?e.definition?e.loaded?e.definition.serviceInstance?t?t.process.serviceInstance===e.definition.serviceInstance?js(`service manager`,`loaded job matches the local service instance`):Z(`service manager`,`loaded job does not match the local service instance`,`stop the foreground owner and restart the service`):X(`service manager`,`loaded job cannot be matched until local control responds`):X(`service manager`,`legacy service definition has no verifiable instance marker`,`reinstall the service to record a service instance`):X(`service manager`,`installed service is stopped`,"run `shellbell service start` if background operation is wanted"):Z(`service manager`,`installed service definition is unreadable`,`reinstall the service after checking its definition`):X(`service manager`,`no service definition installed; foreground agent can still run`,"run `shellbell service install` for autostart")}function Rs(e){let t=`installed=${e.installed}; enabled=${e.enabled}; active=${e.activeState}; authenticated ready=${e.ready}; linger=${e.linger}; ownership=${e.ownership}${e.diagnostic?`; ${e.diagnostic}`:``}`;return e.activeState===`unknown`?X(`service manager`,t,`restore access to the current user's systemd manager; foreground readiness is independent`):e.ownership===`foreign`?Z(`service manager`,t,`inspect the exact unit and any drop-ins; Shellbell refuses foreign definitions`):e.ready?js(`service manager`,t):X(`service manager`,t,`inspect shellbell service status; install, start, and enable are separate choices; foreground readiness is independent`)}function zs(e,t){let n=e=>t.includes(e)?{...Z(e,`required backend unavailable until service state is selected`),required:!0}:X(e,`unavailable until service state is selected`);return[X(`identity`,e),Z(`service manager`,e),X(`control`,`unavailable until service state is selected`),X(`relay`,`unavailable until service state is selected`),n(`iterm2`),n(`tmux`),n(`herdr`),X(`terminal readiness`,`unavailable until service state is selected`)]}async function Bs(e,t={}){let r=(e.platform??process.platform)===`linux`,i=X(`service manager`,`Linux systemd user-manager inspection unavailable; foreground readiness is independent`,`inspect shellbell service status and the current user's systemd manager`),a=e.requiredBackends.filter(e=>e!==`tmux`).map(e=>({...Z(e,e===`herdr`?`Shellbell's Herdr backend is not yet qualified for Linux delivery (Herdr itself supports Linux)`:`iTerm2 is not supported on Linux`),required:!0})),o=null,s;if(r){let n,r={...e.env,SHELLBELL_DIR:e.requestedStateDir??e.env.SHELLBELL_DIR},o=e=>(r=e,n=(t.selectLinuxPaths??(e=>Ft({env:e})))(e),n);try{i=Rs(await(t.inspectLinuxService??(()=>new Ds({env:r,selectPaths:o}).status()))(o))}catch{}let c;try{let e=n??o(r);s=e;let t=Ke(e);c=t.status===`ready`?js(`host state`,`Linux host state admitted`):Z(`host state`,t.reason??`Linux host state is absent`,`initialize absent state with shellbell host init --new, or inspect existing state before recovery`)}catch{c=Z(`host state`,`Linux state or runtime selection is unsafe or unavailable`,`use a nonroot matching real/effective user, a valid machine ID, and a private 0700 local runtime directory`)}if(c.severity===`error`)return[c,i,X(`control`,`unavailable until host state is admitted`),X(`relay`,`unavailable until host state is admitted`),...a,e.requiredBackends.includes(`tmux`)?{...Z(`tmux`,`required backend unavailable until host state is admitted`),required:!0}:X(`tmux`,`unavailable until host state is admitted`)]}else{try{o=await(t.inspectManager??(()=>f().inspect()))()}catch{return zs(`service manager inspection failed; state unavailable`,e.requiredBackends)}try{s=_t(o,e.requestedStateDir,e.defaultStateDir)}catch{return zs(`state selection unavailable; check SHELLBELL_DIR against installed service`,e.requiredBackends)}}let c,l=null;try{let e=n(s);e?(l=e.fp,c=js(`identity`,r?`valid admitted Linux identity`:`valid identity at ${s.identity}`)):c=Z(`identity`,`identity missing at ${s.identity}`,`start Shellbell once to create an identity`)}catch{c=Z(`identity`,r?`Linux identity invalid or unreadable`:`identity invalid or unreadable at ${s.identity}`,`restore the original identity file; do not replace paired keys`)}let u=null,d;if(!l)d=Z(`control`,`cannot verify local process without a valid identity`);else try{let e=await(t.controlStatus??(e=>se(e,`status`,void 0,{timeoutMs:500,maxResponseBytes:65536})))(s.sock),n=me.safeParse(e);n.success?bt(n.data,{computerFp:l,stateDir:s.dir})?(u=n.data,d=js(`control`,`local agent identity and state verified`)):d=Z(`control`,`local endpoint belongs to a different identity or state directory`):d=Z(`control`,`local endpoint returned malformed or unsupported status`)}catch{d=Z(`control`,`local endpoint is absent or did not return bounded status`,`start Shellbell, or inspect the configured service`)}let p=r?i:Ls(o,u),m=null,h=null;try{h=ot(s).relayUrl}catch{m=Z(`relay`,r?`Linux configuration invalid or unreadable`:`configuration invalid or unreadable at ${s.config}`,`repair the existing config without replacing identity files`)}if(!m){if(u?.relayOnline)m=js(`relay`,`local agent reports relay connected`);else{let e=`configured relay`,n=!1;try{let r=new URL(h);[`ws:`,`wss:`,`http:`,`https:`].includes(r.protocol)&&(e=`${r.protocol===`ws:`?`http:`:r.protocol===`wss:`?`https:`:r.protocol}//${r.host}/healthz`,n=await(t.relayHealth??es)(h))}catch{}m=Z(`relay`,`local agent is not relay-connected; ${e} ${n?`is reachable`:`is not confirmed reachable`} (HTTP health does not prove WebSocket authorization)`,`check the relay URL, network, and running agent`)}}let{env:g,context:_}=r?{env:e.env,context:`current shell setup`}:Is(o,e.env),v=new Set(e.requiredBackends),y=e=>u?.backends.find(t=>t.name===e)?.connected===!0,b=X(`iterm2`,`${_}: iTerm2 API socket unavailable`,`enable iTerm2 Python API, then start Shellbell to authorize access`);if(!r&&!y(`iterm2`))try{(t.itermSocketExists??(()=>Ut(Mo)))()&&(b=X(`iterm2`,`${_}: API socket exists but agent is disconnected`,`start Shellbell to authorize iTerm2 API access`))}catch{b=Z(`iterm2`,`iTerm2 API socket inspection failed`)}let x=Ms(`iterm2`,y(`iterm2`),v.has(`iterm2`),b),S=X(`tmux`,`${_}: tmux is unavailable`,`install tmux 3.2 or newer`);if(!y(`tmux`))try{let e=ks(await(t.tmuxVersion??Ps)(g));S=e===null||e<3.02?Z(`tmux`,`${_}: tmux version is unsupported or unrecognizable`,`install tmux 3.2 or newer`):X(`tmux`,`${_}: tmux 3.2+ is installed but not connected`,`start a tmux session and Shellbell`)}catch(e){S=e.code===`ENOENT`?X(`tmux`,`${_}: tmux executable not found`,`install tmux 3.2 or newer`):Z(`tmux`,`${_}: tmux version probe failed`,`check installed tmux and the saved PATH`)}let C=Ms(`tmux`,y(`tmux`),v.has(`tmux`),S),w=X(`herdr`,`${_}: Herdr is unavailable`,bi);if(!r&&!y(`herdr`))try{let e=await(t.checkHerdr??Fs)(g);w=e.ok?e.detail===`not installed (optional)`?X(`herdr`,`${_}: Herdr not found on PATH`,bi):e.detail===`installed but not running (optional)`?X(`herdr`,`${_}: Herdr is installed but not running`,`start Herdr and Shellbell`):X(`herdr`,`${_}: Herdr API available but agent is disconnected`,`start Shellbell with Herdr enabled`):Z(`herdr`,`${_}: Herdr API is broken or unsupported`,xi)}catch{w=Z(`herdr`,`${_}: Herdr API probe failed`,xi)}let ee=Ms(`herdr`,y(`herdr`),v.has(`herdr`),w),te=u?await(t.terminalSetup??Vs)(s.sock).catch(()=>null):null,ne=(e,t)=>{let n=te?.find(e=>e.name===t);if(!n?.issue)return e;let{status:r,fix:i}=Qn(n,`command-line`);return n.connected?{...X(t,r,i),...e.required?{required:!0}:{}}:Ms(t,!1,v.has(t),X(t,r,i))},re=(r?y(`tmux`):u?.terminalReady)?js(`terminal readiness`,`at least one backend connected to the verified local agent`):Z(`terminal readiness`,`no backend connected to a verified local agent`,`start Shellbell with a supported terminal backend`);return[...r?[js(`host state`,`Linux host state admitted`)]:[],c,p,d,m,...r?a:[ne(x,`iterm2`)],ne(C,`tmux`),...r?[]:[ne(ee,`herdr`)],re]}async function Vs(e){let t=await h(e);try{return await t.terminals()}finally{t.close()}}var Hs=class{parts=[];length=0;push(e){let t=[],n=0;for(let r=e.indexOf(10);r!==-1;r=e.indexOf(10,n)){this.parts.push(e.subarray(n,r)),this.length+=r-n,this.check();let i=this.parts.length===1?this.parts[0]:Buffer.concat(this.parts,this.length);i.length>0&&i[i.length-1]===13&&(i=i.subarray(0,-1)),t.push(i),this.parts=[],this.length=0,n=r+1}return n<e.length&&(this.parts.push(e.subarray(n)),this.length+=e.length-n,this.check()),t}check(){if(this.length>4194304)throw this.parts=[],this.length=0,Error(`tmux control line too long`)}};function Us(e){let t=new Uint8Array(e.length),n=0;for(let r=0;r<e.length;r++){let i=e[r];i===92&&e[r+1]===92?(t[n++]=92,r++):i===92&&r+3<e.length&&Ws(e[r+1])&&Ws(e[r+2])&&Ws(e[r+3])?(t[n++]=e[r+1]-48<<6|e[r+2]-48<<3|e[r+3]-48,r+=3):t[n++]=i}return t.subarray(0,n)}function Ws(e){return e!==void 0&&e>=48&&e<=55}const Gs=Buffer.from(`%output `),Ks=Buffer.from(`%extended-output `),qs=Buffer.from(` : `);function Js(e){let t;if(e.subarray(0,Gs.length).equals(Gs))t=e.subarray(Gs.length);else if(e.subarray(0,Ks.length).equals(Ks))t=e.subarray(Ks.length);else return;let n=t.indexOf(32),r=(n===-1?t:t.subarray(0,n)).toString(`latin1`);if(!/^%\d+$/.test(r))return;if(n===-1)return{pane:r,data:Buffer.alloc(0)};if(e[1]===Gs[1])return{pane:r,data:t.subarray(n+1)};let i=t.indexOf(qs,n);if(i!==-1)return{pane:r,data:t.subarray(i+qs.length)}}function Ys(e){return`'${e.replace(/'/g,`'\\''`)}'`}function Xs(e){return e.trim().split(/\s+/,1)[0]||`?`}const Zs=/^%(?:end|error) (\S+) (\S+) \S+$/;function Qs(e,t){let n=Zs.exec(e);return n!==null&&n[1]===t.time&&n[2]===t.num}var $s=class extends Cn{opts;child=null;queue=[];current=null;currentPending=null;started=!1;outputSeq=0;readyTimer=null;settleReady=null;alive=!1;log;constructor(e){super(),this.opts=e,this.log=e.log.child({backend:`tmux`,session:e.sessionId})}start(){let e=[...this.opts.socketName?[`-L`,this.opts.socketName]:[],`-u`,`-C`,`attach-session`,`-t`,this.opts.sessionId,`-f`,`ignore-size`],t=(this.opts.spawnImpl??Bt)(this.opts.executable??`tmux`,e,{stdio:[`pipe`,`pipe`,`pipe`]});this.child=t,this.alive=!0;let n=new Hs,r=null,i=new Promise(e=>{r=e,this.readyTimer=setTimeout(e,this.opts.readyTimeoutMs??2e3),this.readyTimer.unref?.()}),a=()=>{this.readyTimer&&clearTimeout(this.readyTimer),this.readyTimer=null,this.settleReady=null,r?.()};this.settleReady=a;let o=(e,t)=>{if(this.current&&!Qs(e,this.current)){this.current.lines.push(e);return}if(e.startsWith(`%begin`)){let[,t=``,n=``]=e.split(` `);this.current={lines:[],time:t,num:n},this.currentPending=this.started?this.queue.shift()??null:null;return}if(e.startsWith(`%end`)||e.startsWith(`%error`)){let t=this.current,n=this.currentPending;if(this.current=null,this.currentPending=null,!this.started){this.started=!0,a();return}n&&(clearTimeout(n.timer),e.startsWith(`%error`)?n.reject(Error(`tmux error: ${n.verb}`)):n.resolve((t?.lines??[]).map(e=>e),this.outputSeq));return}this.dispatchNotification(e,t)};return t.stdout?.on(`data`,e=>{if(!this.alive)return;let t;try{t=n.push(e)}catch{this.log.warn(`tmux control line too long`),this.stop();return}for(let e of t){if(!this.alive)return;o(e.toString(`utf8`),e)}}),t.stdout?.on(`end`,()=>this.onExit()),t.stdout?.on(`close`,()=>this.onExit()),t.on(`exit`,()=>this.onExit()),t.on(`error`,e=>{this.log.warn(`tmux control spawn failed`,{error:M(e)}),a(),this.onExit()}),t.stdin?.on(`error`,()=>void 0),t.stderr?.on(`data`,()=>{this.log.debug(`tmux stderr`)}),i}dispatchNotification(e,t){if(e.startsWith(`%output `)||e.startsWith(`%extended-output `)){let e=Js(t);if(!e)return!1;let n=++this.outputSeq;return this.emit(`output`,e.pane),this.listenerCount(`bytes`)>0&&this.emit(`bytes`,e.pane,Us(e.data),n),!0}let n=/^%(pause|continue) (%\d+)$/.exec(e);return n?(n[1]===`pause`?this.emit(`pause`,n[2]):this.emit(`output`,n[2]),!0):/^%(layout-change|window-add|window-close|window-renamed|unlinked-window-|session-changed|session-renamed|sessions-changed)/.test(e)?(this.emit(`layout`),!0):e.startsWith(`%exit`)?(this.onExit(),!0):!1}command(e){return this.send([e]).then(([e])=>e.lines)}async checkpoint(e){let t=this.outputSeq,n=await this.send(e);return{replies:n.map(e=>e.lines),sentSeq:t,outputSeq:n[0].outputSeq}}send(e){if(e.length===0||!this.alive||!this.child?.stdin)return Promise.reject(Error(`tmux control exited`));let t=[],n=e.map(e=>new Promise((n,r)=>{let i=setTimeout(()=>{r(Error(`tmux command timeout: ${Xs(e)}`)),this.stop()},this.opts.commandTimeoutMs??5e3);i.unref?.(),t.push({resolve:(e,t)=>n({lines:e,outputSeq:t}),reject:r,timer:i,verb:Xs(e)})}));this.queue.push(...t);try{this.child.stdin.write(`${e.join(` ; `)}\n`)}catch{for(let e of t)clearTimeout(e.timer),e.reject(Error(`tmux control exited`));this.queue=this.queue.filter(e=>!t.includes(e))}return Promise.all(n)}stop(){if(this.child){try{this.child.stdin?.write(`detach-client
28
+ `)}catch{}this.child.kill()}this.onExit()}onExit(){if(this.alive){this.alive=!1,this.settleReady?.();for(let e of[this.currentPending,...this.queue])e&&(clearTimeout(e.timer),e.reject(Error(`tmux control exited`)));this.queue=[],this.currentPending=null,this.emit(`exit`)}}};const ec={enter:`Enter`,tab:`Tab`,"shift-tab":`BTab`,esc:`Escape`,backspace:`BSpace`,delete:`DC`,up:`Up`,down:`Down`,right:`Right`,left:`Left`,home:`Home`,end:`End`,"page-up":`PPage`,"page-down":`NPage`,"ctrl-space":`C-Space`};function tc(e){let t=ec[e];if(t)return t;if(e.startsWith(`ctrl-`))return`C-${e.slice(5)}`;if(/^f([1-9]|1[0-2])$/.test(e))return e.toUpperCase();throw Error(`no tmux key for ${e}`)}const nc=rc();function rc(){let e=new Map([[`\r`,`Enter`],[`
29
+ `,`Enter`],[` `,`Tab`]]);for(let[t,n]of Object.entries(vt))e.has(n)||e.set(n,tc(t));return e}function ic(e){return e?nc.get(e):void 0}const ac=`#{session_id}\\t#{client_control_mode}\\t#{client_pid}`,oc=e=>Ys(e.replace(/\\t/g,` `)),sc=oc(`#{pane_id}\\t#{session_id}\\t#{session_name}\\t#{window_id}\\t#{window_index}\\t#{window_name}\\t#{pane_index}\\t#{pane_title}\\t#{pane_current_path}\\t#{pane_width}\\t#{pane_height}\\t#{pane_active}\\t#{window_active}\\t#{history_size}\\t#{cursor_x}\\t#{cursor_y}\\t#{pane_dead}\\t#{pane_current_command}`),cc=oc(ac),lc=oc(`#{cursor_x}\\t#{cursor_y}\\t#{history_size}\\t#{pane_width}\\t#{pane_height}\\t#{alternate_on}`),uc=oc(`#{cursor_x}\\t#{cursor_y}\\t#{history_size}\\t#{pane_width}\\t#{pane_height}\\t#{history_limit}\\t#{alternate_on}`),Q=e=>Number.parseInt(e??`0`,10)||0,dc=/^%\d+$/,fc=/^\$\d+$/,pc=/^@\d+$/;function mc(e){let t=e.split(` `);return t.length!==18||!dc.test(t[0]??``)||!fc.test(t[1]??``)||!pc.test(t[3]??``)?null:{paneId:t[0]??``,sessionId:t[1]??``,sessionName:t[2]??``,windowId:t[3]??``,windowIndex:Q(t[4]),windowName:t[5]??``,paneIndex:Q(t[6]),paneTitle:t[7]??``,cwd:t[8]??``,width:Q(t[9]),height:Q(t[10]),paneActive:t[11]===`1`,windowActive:t[12]===`1`,historySize:Q(t[13]),cursorX:Q(t[14]),cursorY:Q(t[15]),dead:t[16]===`1`,currentCommand:t[17]??``}}const hc=({sessionId:e,sessionName:t,windowIndex:n,windowActive:r,...i})=>JSON.stringify(i);function gc(e){let t=e.map(mc).filter(e=>e!==null),n=new Map;for(let e of t){let t=n.get(e.paneId);n.set(e.paneId,t===void 0||t===hc(e)?hc(e):null)}let r=new Map;for(let e of t)n.get(e.paneId)!==null&&r.set(e.paneId,e);return[...r.values()]}function _c(e){let t=e.split(` `),n=/^\d{1,10}$/.test(t[2]??``)?Number(t[2]):void 0;return{sessionId:t[0]??``,controlMode:t[1]===`1`,...n?{pid:n}:{}}}function vc(e){let t=e.split(` `);return{cursorX:Q(t[0]),cursorY:Q(t[1]),historySize:Q(t[2]),width:Q(t[3]),height:Q(t[4])}}function yc(e){let t=e.split(` `);if(!(t.length!==6||t[5]!==`0`&&t[5]!==`1`))return t[5]===`1`}function bc(e){let t=e.split(` `);if(t.length!==7||t[6]!==`0`&&t[6]!==`1`)return null;let n=t.slice(0,6).map(xc);if(n.some(e=>e===null))return null;let[r,i,a,o,s,c]=n;return o<1||s<1?null:{cursorX:r,cursorY:i,historySize:a,width:o,height:s,historyLimit:c,alternate:t[6]===`1`}}function xc(e){if(!/^(?:0|[1-9]\d*)$/.test(e))return null;let t=Number(e);return Number.isSafeInteger(t)?t:null}function Sc(e,t){return e.windowName&&e.windowName!==e.currentCommand?e.windowName:e.paneTitle&&e.paneTitle!==t?e.paneTitle:`${e.sessionName}:${e.windowIndex}.${e.paneIndex}`}var Cc=class{state=`ground`;write(e){let t=new Uint8Array(e.length+1),n=0;for(let r of e){if(this.state===`name-esc`&&r===92){this.state=`ground`;continue}if(this.state===`esc`||this.state===`name-esc`){if(r===107){this.state=`name`;continue}t[n++]=27,this.state=`ground`}r===27?this.state=this.state===`name`?`name-esc`:`esc`:this.state===`name`?(r===24||r===26)&&(t[n++]=r,this.state=`ground`):t[n++]=r}return t.subarray(0,n)}};const wc=[`history_size`,`pane_width`,`pane_height`,`cursor_x`,`cursor_y`,`scroll_region_upper`,`scroll_region_lower`,`origin_flag`,`wrap_flag`,`insert_flag`,`cursor_flag`,`keypad_cursor_flag`,`keypad_flag`,`alternate_on`,`alternate_saved_x`,`alternate_saved_y`,`pane_tabs`,`cursor_shape`,`cursor_blinking`];function Tc(e,t){if(!/^%\d+$/.test(e))throw Error(`invalid tmux pane id`);if(t!==void 0&&!(Number.isSafeInteger(t)&&t>=1))throw Error(`invalid history line count`);let n=t===void 0?`-`:`-${t}`;return[`display -p -t ${e} '${wc.map(e=>`#{${e}}`).join(` `)}'`,`capture-pane -p -e -J -S ${n} -E -1 -t ${e}`,`capture-pane -p -e -J -t ${e}`,`capture-pane -p -e -J -a -q -t ${e}`,`capture-pane -p -P -t ${e}`]}const Ec={block:2,underline:4,bar:6};function Dc(e){let t=``,n=``;return e.forEach((e,r)=>{r>0&&(n+=t?`\x1b[49m\r\n${t}`:`\r
30
+ `),n+=e;for(let[,n=``]of e.matchAll(/\x1b\[([\d;:]*)m/g))t=Oc(t,n)}),n}function Oc(e,t){let n=t.split(`;`);for(let t=0;t<n.length;t++){let r=n[t].split(`:`)[0],i=r===``?0:Number(r);i===0||i===49?e=``:i>=40&&i<=47||i>=100&&i<=107?e=`\x1b[${i}m`:i===48&&n[t].includes(`:`)?e=`\x1b[${n[t]}m`:i===48&&n[t+1]===`5`?(e=`\x1b[${n.slice(t,t+3).join(`;`)}m`,t+=2):i===48&&n[t+1]===`2`?(e=`\x1b[${n.slice(t,t+5).join(`;`)}m`,t+=4):(i===38||i===58)&&n[t+1]===`5`?t+=2:(i===38||i===58)&&n[t+1]===`2`&&(t+=4)}return e}function kc(e){let[t=[],n=[],r=[],i=[],a=[]]=e,o=(t[0]??``).split(` `);if(o.length!==wc.length)throw Error(`unexpected tmux pane state`);let s=Object.fromEntries(wc.map((e,t)=>[e,o[t]])),c=e=>{if(!/^\d{1,6}$/.test(s[e]))throw Error(`unexpected tmux ${e}`);return Number(s[e])},l=s.alternate_on===`1`,u=c(`pane_height`),d=`\x1Bc\x1B[3g`,f=s.pane_tabs.split(`,`).filter(Boolean);if(!f.every(e=>/^\d{1,6}$/.test(e)))throw Error(`unexpected tmux pane_tabs`);for(let e of f)d+=`\x1b[1;${Number(e)+1}H\x1bH`;d+=`\x1B[H`;let p=[...c(`history_size`)>0?n:[],...l?i:r];d+=Dc(p),l&&(d+=`\x1b[0m\x1b[${c(`alternate_saved_y`)+1};${c(`alternate_saved_x`)+1}H`,d+=`\x1b[?1049h${Dc(r.slice(0,u))}`),d+=`\x1B[0m`;let m=c(`scroll_region_upper`);d+=`\x1b[${m+1};${c(`scroll_region_lower`)+1}r`,s.wrap_flag===`0`&&(d+=`\x1B[?7l`),s.insert_flag===`1`&&(d+=`\x1B[4h`),s.keypad_cursor_flag===`1`&&(d+=`\x1B[?1h`),s.keypad_flag===`1`&&(d+=`\x1B=`),s.cursor_flag===`0`&&(d+=`\x1B[?25l`);let h=Ec[s.cursor_shape];h!==void 0&&(d+=`\x1b[${h-+(s.cursor_blinking===`1`)} q`);let g=s.origin_flag===`1`;g&&(d+=`\x1B[?6h`);let _=c(`cursor_y`)-(g?m:0);return d+=`\x1b[${_+1};${c(`cursor_x`)+1}H`,{cols:c(`pane_width`),rows:u,data:d+a.join(`
31
+ `)}}var Ac=class extends Cn{opts;control;log;generation=0;held=[];size;seeding=!1;reseedWanted=!1;resizeTimer=null;muting=null;ended=!1;historyLines;names=new Cc;constructor(e){if(super(),this.opts=e,!/^\$\d+$/.test(e.tmuxSessionId)||!/^%\d+$/.test(e.paneId))throw Error(`invalid tmux pane identity`);this.log=e.log.child({backend:`tmux`,stream:`vt`}),this.control=(e.controlFactory??(t=>new $s({sessionId:t,socketName:e.socketName,executable:e.executable,log:e.log})))(e.tmuxSessionId),this.control.on(`bytes`,(t,n,r)=>{this.held?this.held.push({pane:t,seq:r,data:n}):t===e.paneId?this.emitBytes(this.names.write(n)):this.mutePanes()}),this.control.on(`layout`,()=>{this.mutePanes().then(e=>{e&&this.scheduleResizeCheck()})}),this.control.on(`exit`,()=>this.end(`exited`))}async start(e){if(this.historyLines=e??this.opts.historyLines,await this.control.start(),!this.control.alive)return this.end(`exited`);await this.mutePanes()&&await this.reseed()}async reseed(e){if(!this.ended){if(e!==void 0&&(this.historyLines=e),this.seeding){this.reseedWanted=!0;return}this.seeding=!0;try{for(let e=0;e<5&&!this.ended;){this.reseedWanted=!1,this.held=[];let{replies:t,sentSeq:n,outputSeq:r}=await this.control.checkpoint(Tc(this.opts.paneId,this.historyLines)),i=this.held;if(i.some(e=>e.pane!==this.opts.paneId&&e.seq>n&&e.seq<=r)){e++,await this.mutePanes();continue}let a=kc(t);this.size={cols:a.cols,rows:a.rows},this.held=void 0,this.generation++,this.names=new Cc;let o=Buffer.from(this.names.write(Buffer.from(a.data))).toString();this.emit(`seed`,{...a,data:o,generation:this.generation});for(let e of i)e.pane===this.opts.paneId&&e.seq>r&&this.emitBytes(this.names.write(e.data));if(!this.reseedWanted)return}this.ended||this.end(`unsettled`)}catch(e){this.ended||(this.log.debug(`tmux vt seed failed`,{error:e instanceof Error?e.name:`unknown`}),this.end(this.control.alive?`failed`:`exited`))}finally{this.seeding=!1}}}close(){this.end(void 0)}emitBytes(e){e.length>0&&this.emit(`bytes`,e,this.generation)}mutePanes(){return this.muting??=this.listAndMute().finally(()=>{this.muting=null}),this.muting}async listAndMute(){if(this.ended)return!1;let e;try{e=await this.control.command(`list-panes -s -t ${this.opts.tmuxSessionId} -F '#{pane_id}'`)}catch{return this.ended||this.end(this.control.alive?`pane-gone`:`exited`),!1}if(!e.includes(this.opts.paneId))return this.end(`pane-gone`),!1;let t=e.filter(e=>/^%\d+$/.test(e)&&e!==this.opts.paneId);try{for(let e of t)await this.control.command(`refresh-client -A '${e}:off'`)}catch{}return!this.ended}scheduleResizeCheck(){this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{this.resizeTimer=null,this.checkSize()},this.opts.resizeDebounceMs??300),this.resizeTimer.unref?.()}async checkSize(){if(this.ended||!this.size)return;let e;try{[e]=await this.control.command(`display -p -t ${this.opts.paneId} '#{pane_width} #{pane_height}'`)}catch{return}e!==`${this.size.cols} ${this.size.rows}`&&await this.reseed()}end(e){this.ended||(this.ended=!0,this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=null,this.held=void 0,this.control.stop(),e&&this.emit(`end`,e))}};const jc=An(zt),Mc=`brew install tmux (3.2+), then start a tmux session`,Nc=5e3,Pc=10485760;function Fc(e,t){return fi({cwd:e.cwd||void 0,project:si(e.windowName,e.currentCommand),processName:e.currentCommand,title:e.paneTitle,ignore:[t]})}function Ic(e){return M(e)}function Lc(e){return`historySize`in e}function Rc(e,t){return new Promise((n,r)=>{let i=setTimeout(()=>r(Error(`tmux exec timeout: ${t}`)),Nc);i.unref?.(),e.then(e=>{clearTimeout(i),n(e)},e=>{clearTimeout(i),r(e instanceof Error?e:Error(String(e)))})})}var zc=class t{opts;name=`tmux`;processes;capabilities={subscribe:!0,prompts:!1,createSession:!0,terminalInput:!0,terminalPaste:!0,focus:!1,history:!0,absoluteLines:!1,vtStream:!0};setupIssue=`no-session`;controls=new Map;panes=new Map;paneRevisions=new Map;historyEvidence=new WeakMap;reported=new Map;alternate=new Map;sessionIndex=new Map;handlers=new Set;watcher=null;refreshTimer=null;refreshBusy=!1;refreshDirty=!1;syncBusy=!1;closed=!0;closes=0;log;exec;constructor(e){this.opts=e,this.log=e.log.child({backend:`tmux`});let t=e.execImpl??(async t=>(await jc(this.program(),[...e.socketName?[`-L`,e.socketName]:[],...t],{timeout:Nc,maxBuffer:Pc})).stdout);this.exec=e=>Rc(t(e),e[0]??`tmux`)}program(){let e=this.opts.executable;return(typeof e==`function`?e():e)??`tmux`}get isConnected(){return!this.closed&&[...this.controls.values()].some(e=>e.alive)}static async detect(e,{requireServer:t=!0,executable:n=`tmux`}={}){let r=e??(async e=>(await jc(n,e,{timeout:Nc,maxBuffer:Pc})).stdout),i=e=>Rc(r(e),e[0]??`tmux`),a;try{a=await i([`-V`])}catch{return{ok:!1,version:``,reason:`tmux not found`}}let o=/(\d+\.\d+)/.exec(a)?.[1]??``,s=ks(a);if(s===null||s<3.02)return{ok:!1,version:o,reason:`tmux 3.2+ required for Shellbell (found ${o||a.trim()})`};if(!t)return{ok:!0,version:o};try{await i([`list-sessions`,`-F`,`#{session_id}`])}catch{return{ok:!1,version:o,reason:`no tmux server running`}}return{ok:!0,version:o}}async connect(){let e=this.closes,n=await t.detect(this.exec);if(e===this.closes){if(this.setupIssue=n.ok?void 0:n.reason===`tmux not found`?`not-installed`:n.reason===`no tmux server running`?`no-session`:`too-old`,!n.ok)throw new j(n.reason??`tmux unavailable`,Mc);this.watcher&&clearInterval(this.watcher),this.closed=!1,await this.syncControls(),await this.refreshPanes(),!(this.closed||e!==this.closes)&&(this.watcher=setInterval(()=>{this.syncControls().then(()=>this.refreshPanes()).catch(e=>this.log.warn(`tmux watcher failed`,{error:Ic(e)}))},this.opts.watchIntervalMs??5e3),this.watcher.unref?.())}}async close(){this.closed=!0,this.closes++,this.watcher&&clearInterval(this.watcher),this.watcher=null,this.refreshTimer&&clearTimeout(this.refreshTimer),this.refreshTimer=null,this.refreshDirty=!1,this.syncBusy=!1,this.refreshBusy=!1;for(let e of this.controls.values())e.stop();this.controls.clear(),this.panes.clear(),this.invalidateAllHistory(),this.reported.clear(),this.alternate.clear(),this.sessionIndex.clear(),this.handlers.clear()}on(e){return this.handlers.add(e),()=>this.handlers.delete(e)}emit(e){for(let t of this.handlers)try{t(e)}catch(e){this.log.warn(`event handler failed`,{error:Ic(e)})}}channelForSession(e){if(e){let t=this.controls.get(e);if(t?.alive)return t}let t=[...this.controls.values()].find(e=>e.alive);if(!t)throw Error(`tmux command channel unavailable`);return t}channel(e){return this.channelForSession(e?this.panes.get(e)?.sessionId:void 0)}async syncControls(){if(!(this.syncBusy||this.closed)){this.syncBusy=!0;try{let e;try{e=(await this.exec([`list-sessions`,`-F`,`#{session_id}`])).split(`
32
+ `).filter(Boolean)}catch(e){this.log.debug(`tmux list-sessions failed; keeping the existing clients`,{error:Ic(e)});return}this.sessionIndex=new Map(e.map((e,t)=>[e,t]));for(let[t,n]of this.controls)(!e.includes(t)||!n.alive)&&(n.stop(),this.controls.delete(t),this.invalidateAllHistory());for(let t of e){if(this.closed||this.controls.has(t))continue;let e=(this.opts.controlFactory??(e=>new $s({sessionId:e,socketName:this.opts.socketName,executable:this.program(),log:this.opts.log})))(t);e.on(`output`,e=>{this.panes.has(e)?(this.invalidatePane(e),this.emit({type:`screen-changed`,sessionId:e})):this.scheduleRefresh()}),e.on(`layout`,()=>{this.invalidateAllHistory(),this.scheduleRefresh()}),e.on(`exit`,()=>{this.controls.delete(t),this.invalidateAllHistory(),this.scheduleRefresh()}),this.controls.set(t,e),this.invalidateAllHistory(),await e.start()}}finally{this.syncBusy=!1}}}scheduleRefresh(){if(!this.closed){if(this.refreshBusy){this.refreshDirty=!0;return}this.refreshTimer||(this.refreshTimer=setTimeout(()=>{this.refreshTimer=null,this.refreshPanes().catch(e=>this.log.warn(`tmux refresh failed`,{error:Ic(e)}))},this.opts.refreshDebounceMs??100),this.refreshTimer.unref?.())}}async refreshPanes(){if(!this.closed){if(this.refreshBusy){this.refreshDirty=!0;return}this.refreshBusy=!0;try{do this.refreshDirty=!1,await this.runRefresh();while(this.refreshDirty&&!this.closed)}finally{this.refreshBusy=!1}}}async runRefresh(){if(this.controls.size===0){let e=[...this.panes.keys()];this.panes.clear(),this.alternate.clear(),this.invalidateAllHistory();for(let t of e)this.emit({type:`session-removed`,sessionId:t});e.length>0&&this.emit({type:`layout-changed`});return}let e;try{e=gc(await this.channel().command(`list-panes -a -F ${sc}`))}catch(e){this.log.warn(`list-panes failed`,{error:Ic(e)});return}let t=this.panes,n=new Map(e.filter(e=>!e.dead).map(e=>[e.paneId,e])),r=[...t.keys()].filter(e=>!n.has(e)),i=[...n.keys()].filter(e=>!t.has(e)),a=this.opts.hostname??ln(),o=[...n.keys()].filter(e=>{let r=t.get(e);if(!r)return!1;let i=n.get(e);return Sc(r,a)!==Sc(i,a)||r.cwd!==i.cwd||!ui(Fc(r,a),Fc(i,a))});this.panes=n;for(let e of r)this.reported.delete(e),this.alternate.delete(e),this.invalidatePane(e),this.emit({type:`session-removed`,sessionId:e});for(let e of i)this.revisionFor(e),this.emit({type:`session-added`,sessionId:e});for(let e of o)this.emit({type:`title-changed`,sessionId:e});(r.length>0||i.length>0)&&this.emit({type:`layout-changed`})}pane(e){let t=this.panes.get(e);if(!t)throw new k(e);return t}revisionFor(e){let t=this.paneRevisions.get(e);return t||(t={},this.paneRevisions.set(e,t)),t}invalidatePane(e){this.paneRevisions.delete(e)}invalidateAllHistory(){this.paneRevisions.clear()}ownsEvidence(e){return this.panes.has(e.paneId)&&this.paneRevisions.get(e.paneId)===e.revision&&e.channel.alive&&this.channel(e.paneId)===e.channel}sameFacts(e,t){return e.cursorX===t.cursorX&&e.cursorY===t.cursorY&&e.historySize===t.historySize&&e.width===t.width&&e.height===t.height&&e.historyLimit===t.historyLimit&&e.alternate===t.alternate}async checkedFacts(e,t){if(t.aborted)return{status:`cancelled`};if(!this.ownsEvidence(e))return{status:`reset`};let n;try{n=(await e.channel.command(`display-message -p -t ${e.paneId} ${uc}`))[0]}catch{return t.aborted?{status:`cancelled`}:this.ownsEvidence(e)?{status:`unavailable`,reason:`changed`}:{status:`reset`}}if(t.aborted)return{status:`cancelled`};if(!this.ownsEvidence(e))return{status:`reset`};let r=bc(n??``);return r?this.sameFacts(r,e.facts)?r:(this.invalidatePane(e.paneId),{status:`reset`}):{status:`unavailable`,reason:`changed`}}readOutcome(e,t){if(t.aborted)return{status:`cancelled`};if(!this.ownsEvidence(e))return{status:`reset`}}async notificationFacts(e){let t=this.panes.get(e);if(t&&this.isConnected)return ir({sessionId:e,cwd:t.cwd,title:Sc(t,this.opts.hostname??ln()),sessionLabel:`tmux · ${t.sessionId} · Tab ${t.windowIndex+1} · Pane ${t.paneIndex+1}`},t.currentCommand,`local-process`)}async listSessions(){let e=new Set,t=new Map;try{let n=(await this.channel().command(`list-clients -F ${cc}`)).map(_c).filter(e=>!e.controlMode);e=new Set(n.map(e=>e.sessionId)),t=await this.hostApps(n)}catch(e){this.log.debug(`list-clients failed; no pane reported focused`,{error:Ic(e)})}let n=this.opts.hostname??ln(),r=e=>this.sessionIndex.get(e)??2**53-1;return[...this.panes.values()].sort((e,t)=>r(e.sessionId)-r(t.sessionId)||e.windowIndex-t.windowIndex||e.paneIndex-t.paneIndex).map(r=>({id:r.paneId,backend:`tmux`,title:Sc(r,n),cwd:r.cwd||void 0,...Fc(r,n),cols:Math.max(1,r.width),rows:Math.max(1,r.height),windowId:r.sessionId,windowNumber:this.sessionIndex.get(r.sessionId)??0,tabId:r.windowId,tabIndex:r.windowIndex,paneIndex:r.paneIndex,isFocusedOnMac:r.paneActive&&r.windowActive&&e.has(r.sessionId),state:`unknown`,...this.alternate.has(r.paneId)&&{alternateScreen:this.alternate.get(r.paneId)},...t.has(r.sessionId)&&{shownIn:t.get(r.sessionId)}}))}async hostApps(e){let t=new Map;if(!e.some(e=>e.pid))return t;let n=Date.now();(!this.processes||n-this.processes.at>1e4)&&(this.processes={at:n,table:await(this.opts.processTable??Wi)().catch(()=>void 0)});let r=this.processes.table;if(!r)return t;for(let{sessionId:n,pid:i}of e){let e=i?Gi(i,r):void 0;if(!e)continue;let a=t.get(n)??[];!a.includes(e)&&a.length<4&&a.push(e),t.set(n,a.sort((e,t)=>e.localeCompare(t)))}return t}openVtStream(e){return new Ac({tmuxSessionId:this.pane(e).sessionId,paneId:e,socketName:this.opts.socketName,executable:this.program(),log:this.opts.log})}projectFolder(e){let t=this.panes.get(e);if(t?.cwd&&!si(t.windowName,t.currentCommand))return ci(t.currentCommand)?t.cwd:void 0}tmuxWindowIdOf(e){return this.panes.get(e)?.windowId}nativeWindowIdOf(e){return this.tmuxWindowIdOf(e)}hostedProcess(e){return this.panes.get(e)?.currentCommand}observeAlternate(e,t){if(t===void 0||!this.panes.has(e))return;let n=this.alternate.get(e);n!==t&&(this.alternate.set(e,t),(n!==void 0||t)&&this.emit({type:`title-changed`,sessionId:e}))}setReported(e,t){this.reported.set(e,t)}async getScreen(e,t){this.pane(e);let n=this.channel(e),r=t?.history===!0,i=r?this.revisionFor(e):void 0,a=r?uc:lc,o=await n.command(`display-message -p -t ${e} ${a}`),s=await n.command(`capture-pane -p -e -N -t ${e}`),c=vc(o[0]??``);this.observeAlternate(e,r?bc(o[0]??``)?.alternate:yc(o[0]??``));let l=Math.max(1,c.height),u=s.map(Yn);for(;u.length<l;)u.push({r:[]});u.length>l&&(u.length=l);let d={cols:Math.max(1,c.width),rows:l,cursor:{x:c.cursorX,y:c.cursorY},lines:u,scrollbackTotal:c.historySize};if(!r)return d;let f=bc(o[0]??``);if(!f||f.alternate||!this.panes.has(e)||this.channel(e)!==n||!n.alive)return d;let p;try{p=bc((await n.command(`display-message -p -t ${e} ${uc}`))[0]??``)}catch{return d}if(!p||!this.sameFacts(f,p)||p.alternate||this.paneRevisions.get(e)!==i||this.channel(e)!==n||!n.alive)return d;let m=Object.freeze({});return this.historyEvidence.set(m,{paneId:e,revision:i,channel:n,facts:Object.freeze(f)}),{...d,historyCapture:m}}async getHistory(e,t,n){this.pane(e);let r=this.reported.get(e);if(r===void 0)return{lines:[],oldestAvailable:0};let i=this.channel(e),a=vc((await i.command(`display-message -p -t ${e} ${lc}`))[0]??``),o=Math.max(0,r-a.historySize),s=t-1-r,c=Math.max(t-n-r,-a.historySize);return s<c||s>-1?{lines:[],oldestAvailable:o}:{lines:(await i.command(`capture-pane -p -e -N -t ${e} -S ${c} -E ${s}`)).map(Yn),oldestAvailable:o}}async getHistoryPage(t,n){if(e(n),n.signal.aborted)return{status:`cancelled`};this.pane(t);let r=this.historyEvidence.get(n.capture);if(!r||r.paneId!==t)return{status:`unavailable`,reason:`unanchored`};let i=this.readOutcome(r,n.signal);if(i)return i;if(n.reported<r.facts.historySize)return{status:`unavailable`,reason:`unanchored`};let a=await this.checkedFacts(r,n.signal),o=this.readOutcome(r,n.signal);if(o)return o;if(!Lc(a))return a;let s=Math.max(0,n.reported-r.facts.historySize);if(n.before<s){let e=await this.checkedFacts(r,n.signal);return this.readOutcome(r,n.signal)||(Lc(e)?{status:`boundary`,reason:`truncated`,oldestAvailable:s}:e)}if(n.before===s){let e=await this.checkedFacts(r,n.signal);return this.readOutcome(r,n.signal)||(Lc(e)?{status:`boundary`,reason:`end`,oldestAvailable:s}:e)}let c=Math.max(n.before-n.count,s),l=c-n.reported,u=n.before-1-n.reported;if(l<-2147483648||u<-2147483648||l>-1||u>-1)return{status:`unavailable`,reason:`fetch-window`};if(n.signal.aborted)return{status:`cancelled`};if(!this.ownsEvidence(r))return{status:`reset`};let d;try{d=await r.channel.command(`capture-pane -p -e -N -t ${t} -S ${l} -E ${u}`)}catch{return n.signal.aborted?{status:`cancelled`}:this.ownsEvidence(r)?{status:`unavailable`,reason:`changed`}:{status:`reset`}}if(n.signal.aborted)return{status:`cancelled`};if(!this.ownsEvidence(r))return{status:`reset`};let f=await this.checkedFacts(r,n.signal);return this.readOutcome(r,n.signal)||(Lc(f)?d.length===n.before-c?{status:`page`,from:c,to:n.before,oldestAvailable:s,lines:d.map(Yn)}:{status:`unavailable`,reason:`changed`}:f)}async sendText(e,t){this.pane(e);let n=this.channel(e),r=ic(t);if(r){this.log.debug(`tmux key`),await n.command(`send-keys -t ${e} ${r}`);return}this.log.debug(`tmux text`,{len:t.length});let i=t.split(/\r\n|\r|\n/);for(let t=0;t<i.length;t++){let r=i[t];r&&await n.command(`send-keys -t ${e} -l -- ${Ys(r)}`),t<i.length-1&&await n.command(`send-keys -t ${e} Enter`)}}async sendInput(e,t){this.pane(e);let n=[...Buffer.from(t,`utf8`)].map(e=>e.toString(16).padStart(2,`0`)).join(` `);await this.channel(e).command(`send-keys -t ${e} -H -- ${n}`)}async paste(e,t,n){if(this.pane(e),t.includes(`\0`))throw new E(`paste containing NUL`);let r=`shellbell-${xn()}`,i=`"${[...Buffer.from(t,`utf8`)].map(e=>`\\${e.toString(8).padStart(3,`0`)}`).join(``)}"`,a=this.channel(e);try{await a.command(`set-buffer -b ${r} -- ${i}`),await a.command(`paste-buffer -p -d -b ${r} -t ${e}`),n&&await a.command(`send-keys -t ${e} Enter`)}finally{await a.command(`delete-buffer -b ${r}`).catch(()=>{})}}async createFirstSession(){let e=await t.detect(this.exec,{requireServer:!1});if(!e.ok)throw new j(e.reason??`tmux unavailable`,Mc);let n=(await this.exec([`new-session`,`-d`,`-P`,`-F`,`#{pane_id}`])).trim();if(!/^%\d+$/.test(n))throw Error(`tmux new-session returned an invalid pane id`);try{await this.connect()}catch(e){throw await this.exec([`kill-pane`,`-t`,n]).catch(()=>void 0),e}return n}async hostedSessionTarget(e){if(!/^%\d+$/.test(e))throw new k(e);let t=(await this.exec([`display-message`,`-p`,`-t`,e,`#{session_id}`])).trim();if(!/^\$\d+$/.test(t))throw new k(e);return{sessionId:t,socketName:this.opts.socketName}}async discardHostedSession(e){if(/^\$\d+$/.test(e))await this.exec([`kill-session`,`-t`,e]);else if(/^%\d+$/.test(e))await this.exec([`kill-pane`,`-t`,e]);else throw new k(e);this.scheduleRefresh()}async waitForVisibleClient(e,{timeoutMs:t=15e3,intervalMs:n=250}={}){if(!/^\$\d+$/.test(e))throw new k(e);let r=Date.now()+t;for(;;){if(await this.hasDesktopClient(e).catch(()=>!1))return!0;if(Date.now()>=r)return!1;await new Promise(e=>setTimeout(e,n))}}async shownOnComputer(e){let t;if(e.kind===`split`)t=this.pane(e.sessionId).sessionId;else if(e.windowId!==void 0){if(!this.sessionIndex.has(e.windowId))throw new k(e.windowId);t=e.windowId}else return!1;return this.hasDesktopClient(t)}async hasDesktopClient(e){let t=ac.replace(/\\t/g,` `),n=(await this.exec([`list-clients`,`-t`,e,`-F`,t])).split(`
33
+ `).filter(Boolean).map(_c).filter(e=>!e.controlMode);if(n.length===0)return!1;let r=await(this.opts.processTable??Wi)().catch(()=>void 0);return r?n.some(e=>e.pid!==void 0&&Gi(e.pid,r)!==void 0):(this.opts.platform??process.platform)!==`darwin`}async createSession(e){let t,n;if(e.kind===`split`)this.pane(e.sessionId),t=this.channel(e.sessionId),n=`split-window -P -F '#{pane_id}' -t ${e.sessionId} ${e.direction===`vertical`?`-h`:`-v`}`;else if(e.windowId){if(!this.sessionIndex.has(e.windowId))throw new k(e.windowId);t=this.channelForSession(e.windowId),n=`new-window -P -F '#{pane_id}' -t ${e.windowId}`}else t=this.channel(),n=`new-session -d -P -F '#{pane_id}'`;let r=(await t.command(n))[0]?.trim();if(!r)throw Error(`tmux ${n.split(` `)[0]} returned no pane id`);return this.scheduleRefresh(),r}async focus(e){throw new E(`focus`)}};function Bc(e){let t=e.log.child({unit:`tmux-start`}),n=e.terminalExecutable??(()=>ta(`tmux`)),r=()=>n()??`tmux`,i=new zc({log:e.log,executable:r,...e.backendOptions}),a,o=[],s=null,c=!1,l=!1,u=!1;e.registry.add(i);let d=e.registry.registerSetupReporter(`tmux`,e=>e?{}:{issue:i.setupIssue??`no-session`}),f=`none`,p=()=>{f!==`none`||c||(f=`checking`,zc.detect(e.backendOptions?.execImpl,{requireServer:!1,executable:r()}).then(t=>{if(c||!t.ok){f=`none`;return}f=`registered`,a=e.registry.registerSessionLauncher(`tmux`,{available:()=>!c,start:async()=>({backend:i,sessionId:await i.createFirstSession()})});for(let t of e.terminalWindows??[])o.push(e.registry.registerHostedLauncher({backend:`tmux`,host:t.id,label:t.label},{available:()=>!c&&t.available()&&n()!==void 0,create:async(r,a)=>{if(c||r!==i)throw new j(`tmux was replaced`,`Try again after the service reconnects.`);let o=n();if(!o)throw new j(`tmux is not installed`,`Install tmux 3.2 or newer.`);let s=a??await i.createFirstSession(),l=s;return await Qo(async()=>{let n=await i.hostedSessionTarget(s);if(l=n.sessionId,c)throw new j(`tmux stopped`,`Reconnect your computer.`);if(await t.launch({executable:o,args:[...n.socketName?[`-L`,n.socketName]:[],`attach-session`,`-t`,n.sessionId]}),!await i.waitForVisibleClient(n.sessionId,{timeoutMs:e.attachTimeoutMs}))throw new j(`terminal window did not attach`,`Unlock your computer and try again.`)},()=>i.discardHostedSession(l)),s}}))}).catch(e=>{f=`none`,t.debug(`tmux startup discovery failed`,{error:M(e)})}))};p();let m=()=>{c||s||(s=setTimeout(()=>{s=null,h()},e.retryMs??1e4),s.unref?.())},h=async()=>{if(!c){if(i.isConnected){p(),m();return}try{await i.connect()}catch(n){p(),t.debug(`tmux not available`,{error:M(n)}),e.onUnavailable&&!u&&n instanceof j&&(u=!0,e.onUnavailable()),m();return}try{if(c)return;if(p(),t.info(`tmux connected`),e.onConnected&&!l){l=!0;let t=await i.listSessions().catch(()=>[]);e.onConnected(t.length)}}catch(e){t.debug(`tmux post-connect setup failed`,{error:M(e)})}m()}};return h(),{stop(){d(),a?.();for(let e of o)e();c=!0,s&&clearTimeout(s),s=null,i.close(),e.registry.remove(`tmux`)}}}function Vc(e){return new Promise(t=>{let n=Tn(e),r=e=>{n.destroy(),t(e)};n.setTimeout(250,()=>r(`ambiguous`)),n.once(`connect`,()=>r(`active`)),n.once(`error`,e=>r([`ENOENT`,`ECONNREFUSED`].includes(e.code??``)?`absent`:`ambiguous`))})}async function Hc(e,t,n){let r=L(F(t.runtimeDir),bn(`sha256`).update(e).digest(`hex`).slice(0,32));for(let a of[e,r]){if(!O(a))continue;m(a,t.linuxHost.uid),a===r&&Le(t,a);let e=L(a,`agent.pid`);if(O(e)){let r=i(l(e,64,t.linuxHost.uid).toString(`utf8`).trim());if(!r||(n.processAlive??rt)(r))throw new D(`unsafe`)}let o=[`agent.sock.lock`,`init.sock.lock`,`service.lock`],s=Xt(a);try{for(let e=s.readSync();e;e=s.readSync())if(o.some(t=>e.name===t||e.name.startsWith(`${t}-candidate-`)))throw new D(`unsafe`)}finally{s.closeSync()}let c=L(a,`agent.sock`);if(Buffer.byteLength(c)>107)throw new D(`unsafe`);let u=O(c);if(u&&(!u.isSocket()||u.uid!==t.linuxHost.uid||(u.mode&4095)!=384)||await(n.probeSocket??Vc)(c)!==`absent`)throw new D(`unsafe`)}}function Uc(e,t){let n=t===void 0?O(e):m(e,t),r=Yt(e,N.O_RDONLY|N.O_DIRECTORY|N.O_NOFOLLOW);try{if(!n||!d(n,Wt(r)))throw new D(`unsafe`);Gt(r)}finally{Ht(r)}}function Wc(e,t){let n=O(e);if(n){if(!n.isDirectory()||n.isSymbolicLink())throw new D(`unsafe`);return}Wc(F(e),t);try{Jt(e,{mode:448})}catch(e){if(e.code!==`EEXIST`)throw e}m(e,t),Uc(F(e))}async function Gc(e,t,n,r={}){let i;try{if(jt(e.dir)!==e.dir)throw new D(`unsafe`);let a=Ke(e);if(a.status===`ready`)return{status:`already-initialized`,stateDir:e.dir};if(a.status!==`absent`)throw new D(`unsafe`);let o,s,c;if(t.kind===`adopt`){if(t.confirmSourceInactive!==!0||!I(t.source)||(s=jt(t.source),s===e.dir))throw new D(`unsafe`);o=ht(s,e.linuxHost.uid),await Hc(s,e,r)}else if(t.kind===`new`){if(c=Je.parse(n),Buffer.byteLength(`${JSON.stringify(c,null,2)}\n`)>65536)throw new D(`invalid`)}else throw new D(`invalid`);kt(e),i=ue(L(e.runtimeDir,`init.sock`));let l=Ke(e);if(l.status===`ready`)return{status:`already-initialized`,stateDir:e.dir};if(l.status!==`absent`)throw new D(`unsafe`);if(s){await Hc(s,e,r);let t=ht(s,e.linuxHost.uid);if(!o||!t.identity.equals(o.identity)||!t.config.equals(o.config)||!t.pairings.equals(o.pairings))throw new D(`unsafe`)}if(Wc(F(e.dir),e.linuxHost.uid),jt(e.dir)!==e.dir)throw new D(`unsafe`);Jt(e.dir,{mode:448});let u=m(e.dir,e.linuxHost.uid);Uc(F(e.dir));let f=()=>{if(!d(u,m(e.dir,e.linuxHost.uid)))throw new D(`unsafe`)},p=o??{identity:Buffer.from(`${JSON.stringify(Ot(je()),null,2)}\n`),config:Buffer.from(`${JSON.stringify(c,null,2)}\n`),pairings:Buffer.from(`{"v":1,"phones":[]}
34
+ `)};for(let t of[`identity`,`config`,`pairings`]){r.checkpoint?.(`before-${t}`),f();let n=L(e.dir,`${t}.json`);if(O(n))throw new D(`unsafe`);He(n,p[t],()=>{if(f(),O(n))throw new D(`unsafe`)}),r.checkpoint?.(`after-${t}`)}ht(e.dir,e.linuxHost.uid),Uc(e.dir,e.linuxHost.uid),r.checkpoint?.(`before-marker`),f();let h=L(e.dir,`host.json`);return He(h,`${JSON.stringify({v:1,hostDigest:e.linuxHost.hostDigest,installationId:xn()})}\n`,()=>{if(f(),O(h))throw new D(`unsafe`)}),r.checkpoint?.(`after-marker`),r.checkpoint?.(`before-directory-fsync`),Uc(e.dir,e.linuxHost.uid),r.checkpoint?.(`after-directory-fsync`),{status:`initialized`,stateDir:e.dir}}catch{throw Error(`shellbell: host initialization failed; inspect ${e.dir} before retrying. Preserve existing credentials; move partial state aside only after explicit recovery. Adoption requires the source to be inactive on every host.`)}finally{i?.()}}function Kc(e=process.platform,t){if(e!==`linux`)return ze();let n=Ft(t);return Xe(n),n}function qc(e,t={}){e.command(`host`).description(`manage explicit Linux host identity state`).command(`init`).description(`initialize Linux host state without starting an agent or enabling autostart`).option(`--new`,`create a new independent host identity`).option(`--adopt <absolute-source>`,`copy validated inactive legacy identity and pairings`).option(`--confirm-source-inactive`,`confirm no agent uses the source, including on other hosts`).action(async n=>{let r=!!e.opts().json,i;if((t.platform??process.platform)===`linux`?!!n.new==(n.adopt!==void 0)?i=`choose exactly one of --new or --adopt <absolute-source>`:n.adopt!==void 0&&(!I(n.adopt)||!n.confirmSourceInactive)?i=`adoption requires an absolute source and --confirm-source-inactive`:n.new&&n.confirmSourceInactive&&(i=`--confirm-source-inactive requires --adopt`):i=`host init is available only on Linux`,!i)try{let e=await Gc((t.selectPaths??Ft)(),n.new?{kind:`new`}:{kind:`adopt`,source:n.adopt,confirmSourceInactive:!0},{...yt(),computerName:(t.hostname??ln)().replace(/\.local$/,``)||`Linux`}),i={status:e.status,next:`shellbell start`};console.log(r?JSON.stringify(i):` host state ${e.status}; run shellbell start for foreground operation`);return}catch{i=`Linux host initialization failed; inspect host state and runtime permissions. Existing or partial state is preserved; do not delete paired keys to retry. Use shellbell doctor for admission diagnostics.`}process.exitCode=2,r?console.log(JSON.stringify({error:i})):console.error(` ${i}`)})}const Jc=et,$=new vn().name(`shellbell`).version(Jc).option(`--relay <url>`,`override relay url`).option(`--json`,`machine output`).option(`--verbose`,`debug logging`).option(`--insecure`,`allow a ws:// relay url (LAN dev only)`);function Yc(){let e=$.opts(),t=Kc();return{opts:e,p:t,cfg:pt(t),log:We({file:t.log,verbose:e.verbose,stdout:process.stdout.isTTY&&!e.json})}}const Xc=e=>`${e.slice(0,4)}-${e.slice(4,8)}`;function Zc(e,t){return Qc(`\n Pair "${xr(t)}"?\n Phone fingerprint ${qe(e)}\n Check that your phone shows the same fingerprint. [y/N] (60 s) `,6e4)}function Qc(e,t){return new Promise(n=>{let r=hn({input:process.stdin,output:process.stdout}),i=setTimeout(()=>{r.close(),console.log(`
35
+ (timed out — declined)`),n(!1)},t);r.question(e,e=>{clearTimeout(i),r.close(),n(/^y(es)?$/i.test(e.trim()))})})}function $c(e,t){console.log(`\n Computer ${e.computerName} (${Xc(t)})\n Relay ${e.relayUrl}\n\n Scan this with the Shellbell app:\n`)}function el(e,t){yn.generate(e,{small:!0},e=>{console.log(e.split(`
36
+ `).map(e=>` ${e}`).join(`
37
+ `)),console.log(`\n Pairing window closes in ${Math.round((t-Date.now())/6e4)} min\n`)})}function tl(e,t,n){let r=Yt(e,`r`);try{let e=Wt(r).size,i=Math.max(0,e-t),a=e-i,o=Buffer.alloc(a);a>0&&Qt(r,o,0,a,i);let s=o.toString(`utf8`).replace(/\n$/,``);return s.length===0?``:s.split(`
38
+ `).slice(-n).join(`
39
+ `)}finally{Ht(r)}}async function nl(e){try{return await se(e,`status`),!0}catch(e){let t=e.code;return t!==`ECONNREFUSED`&&t!==`ENOENT`}}function rl(e,t,n,r=!0){return async(i,a)=>e.server?.hasNativePairOwner?e.server.nativePairingConfirm(i,a):r?t?!0:e.server?.hasPairClients?e.server.pairingConfirm(i,a):n(i,a):!1}async function il(e,t,n=process.exit,r){r?.();let i=!1,a=e=>{i||(i=!0,n(e))},o=setTimeout(()=>a(1),5e3);typeof o.unref==`function`&&o.unref();try{e.stop(),await t.stop(),a(0)}finally{clearTimeout(o)}}function al(e,t){if(t===void 0)return{cfg:e};let n=we(t,!0);if(n)return{error:n};let r=new URL(t).protocol===`ws:`;return{cfg:{...e,relayUrl:t},warning:r?`insecure relay URL; for local testing only`:void 0}}async function ol(e,t,n=!1,r={}){let i=r.paths??Kc(),a=r.nativeService?void 0:()=>it({stateDir:i.dir,uid:i.linuxHost?.uid??process.getuid(),serviceInstance:r.serviceInstance});a?.(),i.linuxHost&&(Xe(i),kt(i));let o=pt(i);if(t!==void 0){let e=al(o,t);`error`in e&&(console.error(` --relay ${t}: ${e.error}`),process.exit(1)),e.warning&&console.error(` warning: ${e.warning}`),o=e.cfg}let{identity:s,fp:c}=tt(i),l=new ee(e),u=Wo({paths:o.terminalPlugins??[],registry:l,log:e}),d=i.linuxHost?null:new Ka({recordPath:L(i.dir,`iterm2-access.json`),assumeApproved:(()=>{try{return St(i).length>0}catch{return!1}})(),interactive:!r.nativeService&&!r.managedService&&process.stdin.isTTY===!0,socketPath:Mo}),f=i.linuxHost?null:r.itermBackend===void 0?new jo(new No({log:e,cookieProvider:()=>d.cookieProvider(Ha)}),e):r.itermBackend,p={ready:!1,queue:[]},m=e=>{r.nativeService||(p.ready?console.log(e):p.queue.push(e))},h=()=>{p.ready=!0;for(let e of p.queue)console.log(e);p.queue=[]},g=null,_=null,v=!1,y,b=async()=>{if(f&&!v)try{if(await f.connect(),v)return;l.add(f),y=void 0;let t=await f.listSessions().catch(()=>[]);if(v)return;m(` iTerm2 connected · ${t.length} session${t.length===1?``:`s`}`),e.info(`iTerm2 connected`)}catch(t){if(v)return;let n=d?.issue??`failed`;if(n!==y){y=n;let r=Qn({name:`iterm2`,connected:!1,issue:n},`command-line`);m(` iTerm2 ${r.status}${r.fix?`\n ${r.fix}`:``}`),e.info(`iTerm2 not connected`,{issue:n,err:M(t)})}g=setTimeout(()=>void x(),1e4)}},x=()=>v?Promise.resolve():_||(g&&clearTimeout(g),g=null,_=b().finally(()=>{_=null}),_);f?.isConnected===!1&&l.add(f),f&&x();let S=f&&d?(()=>{let e=d.onChange(()=>l.notifySetupChanged()),t=Object.assign(e=>e?{}:{issue:d.connecting?`connecting`:d.issue??`not-running`},{connect:()=>d.connect(async()=>{await _,l.connected().some(e=>e.name===`iterm2`)||await x()})}),n=l.registerSetupReporter(`iterm2`,t);return()=>{e(),n()}})():()=>{},C=!i.linuxHost&&r.itermBackend===void 0?qo(`iterm2`):null,w=!i.linuxHost&&r.tmuxBackendOptions===void 0?$o():null,te=async()=>{await C?.start(),await x();let e=d?.issue;if(e&&!l.connected().some(e=>e.name===`iterm2`)&&Xn({name:`iterm2`,connected:!1,issue:e})){let{status:t,fix:n}=Qn({name:`iterm2`,connected:!1,issue:e},`phone`);throw new De(`${t} ${n??``}`.trim())}await Yo(l,`iterm2`)},ne=r.terminalWindows??[...w?[w]:[],...f&&C?[{id:`iterm2`,label:`iTerm2`,available:C.available,async launch(e){if(l.connected().some(e=>e.name===`iterm2`)||await te(),l.member(`iterm2`)!==f)throw new j(`iTerm2 was replaced`,`Reconnect your computer.`);await f.createCommandSession(Zo(e))}}]:[]],re=Bc({registry:l,log:e,onConnected:e=>m(` tmux connected · ${e} pane${e===1?``:`s`}`),onUnavailable:()=>m(` tmux not running`),backendOptions:r.tmuxBackendOptions,terminalWindows:ne}),ie=i.linuxHost?null:(r.startHerdr??Ba)({registry:l,log:e,onConnected:e=>m(` herdr connected · ${e} pane${e===1?``:`s`}`),onUnavailable:()=>m(` herdr not running (optional)`)}),ae=()=>{S(),u.stop(),v=!0,g&&clearTimeout(g),g=null},oe=[];f&&C&&oe.push(l.registerSessionLauncher(`iterm2`,{available:C.available,start:async()=>(await te(),{backend:f})}));let se=!i.linuxHost&&r.startHerdr===void 0?Jo():null;if(se){oe.push(l.registerSessionLauncher(`herdr`,{available:se.available,start:async()=>{await se.start(),await Yo(l,`herdr`);let e=l.member(`herdr`);if(!e)throw new j(`Herdr unavailable`,`Check Herdr's local API.`);return{backend:e}}}));for(let e of ne)oe.push(l.registerHostedLauncher({backend:`herdr`,host:e.id,label:e.label},{available:()=>{let t=l.member(`herdr`);return e.available()&&(t instanceof Fa&&t.isConnected?t.terminalAttachExecutable!==void 0:ra()!==void 0)},unavailableReason:()=>{let t=l.member(`herdr`);return e.available()&&t instanceof Fa?t.terminalAttachIssue:void 0},create:async t=>{let n=t instanceof Fa?t.terminalAttachExecutable:void 0;if(!n||!(t instanceof Fa))throw new j(`Herdr terminal attach is unavailable`,`Use matching Herdr CLI/server versions, 0.9.3 or newer.`);let{terminalId:r,workspaceId:i}=await t.createWorkspace();return await Qo(async()=>{if(l.member(`herdr`)!==t||t.terminalAttachExecutable!==n)throw new j(`Herdr was disconnected before the terminal could open`,`Reconnect Herdr and try again.`);await e.launch({executable:n,args:[`terminal`,`attach`,r],environment:{HERDR_SOCKET_PATH:t.terminalSocketPath}})},async()=>{if(!i)throw Error(`Herdr workspace id unknown`);await t.closeWorkspace(i)}),r}}))}let ce=()=>{for(let e of oe)e();ae(),re.stop(),ie?.stop()},le={server:null},T;return T=new vi({paths:i,config:o,identity:s,fp:c,registry:l,log:e,appVersion:Jc,serviceInstance:r.serviceInstance??null,confirm:rl(le,n,(e,t)=>Zc(e,t),!r.nativeService),onPairingClosed:()=>le.server?.notifyClosed(),onSuperseded:()=>{r.nativeService||console.log(` another shellbell agent took over; exiting`),le.server?il(T,le.server,()=>process.exit(0),ce).catch(()=>process.exit(1)):process.exit(0)}}),le.server=new $e(i.sock,T,e,i.pid,a,!r.nativeService&&!r.managedService?e=>Tt({stateDir:i.dir,uid:i.linuxHost?.uid??process.getuid()},e):void 0,r.nativeService?`native`:`terminal`),{agent:T,control:le.server,p:i,cfg:o,fp:c,releaseOutput:h,stopFirstConnect:ae,stopBackendDetectors:ce,herdr:ie}}$.command(`start`,{isDefault:!0}).description(`run the agent in the foreground`).option(`--service`,`running under launchd or a systemd user service`).action(async e=>{let t;try{t=It(e.service===!0)}catch(e){console.error(` ${e.message}`),process.exit(1)}let{opts:n,p:r,log:i}=Yc(),{agent:a,control:o,cfg:s,fp:c,releaseOutput:l,stopBackendDetectors:u}=await ol(i,n.relay,!1,{serviceInstance:t,managedService:e.service===!0,paths:r});try{await o.start()}catch(e){console.error(` ${e.message}`),process.exit(1)}if(a.start(),console.log(`\n Shellbell agent v${Jc}\n Computer ${s.computerName} (${Xc(c)})`),console.log(` Relay ${s.relayUrl} ${a.relayOnline?`connected`:`connecting…`}`),a.relay.on(`auth-ok`,()=>console.log(` Relay ${s.relayUrl} connected`)),a.relay.on(`down`,()=>console.log(` Relay ${s.relayUrl} connecting…`)),console.log(` tmux detecting…`),r.linuxHost||console.log(` herdr detecting…`),l(),a.pairingList.length===0&&!e.service&&process.stdin.isTTY){console.log(`
40
+ No phones paired yet. Scan this with the Shellbell app:
41
+ `);let{qrText:e,expiresAt:t}=a.openPairing();el(e,t)}let d=!1,f=()=>{if(d){console.error(` forcing exit`),process.exit(130);return}d=!0,il(a,o,process.exit,u).catch(()=>process.exit(1))};process.on(`SIGINT`,f),process.on(`SIGTERM`,f)}),$.command(`pair`).description(`open a 5-minute pairing window and show the QR`).option(`--yes`,`auto-accept requests (unsafe on shared screens)`).action(async e=>{let{opts:t,p:n,cfg:r,log:i}=Yc(),{fp:a}=tt(n),o=async()=>{let{agent:r,control:a,cfg:o,fp:s,releaseOutput:c,stopBackendDetectors:l}=await ol(i,t.relay,e.yes,{paths:n});try{await a.start()}catch(e){console.error(` ${e.message}`),process.exit(1)}r.start();let{qrText:u,expiresAt:d}=r.openPairing();$c(o,s),el(u,d),c(),setTimeout(()=>void il(r,a,()=>process.exit(0),l).catch(()=>process.exit(1)),301e3)};if(!await nl(n.sock)){await o();return}let s=ie(n.sock,{onOpen:(e,t)=>{$c(r,a),el(e,t)},onRequest:(t,n)=>e.yes?Promise.resolve(!0):Zc(t,n),onClose:()=>{console.log(` pairing window closed`),process.exit(0)},onError:e=>{console.error(` ${e.message}`),process.exit(1)}});setTimeout(()=>{s.close(),process.exit(0)},301e3)}),$.command(`status`).description(`show agent status`).action(async()=>{let{opts:e,p:t}=Yc();try{let n=await se(t.sock,`status`);console.log(e.json?JSON.stringify(n):JSON.stringify(n,null,2))}catch{console.log(e.json?JSON.stringify({running:!1}):` agent not running`)}});function sl(e){let t=e?.code;console.error(t===`ENOENT`||t===`ECONNREFUSED`?` agent not running`:`shellbell: ${e instanceof Error?e.message:`control request failed`}`),process.exitCode=2}$.command(`devices`).description(`list paired phones`).action(async()=>{let{opts:e,p:t}=Yc();try{let n=await se(t.sock,`devices`);console.log(e.json?JSON.stringify(n):JSON.stringify(n,null,2))}catch(e){sl(e)}});async function cl(e,t,n={}){let r=n.log??console.log,i=await e.connectTerminal(t);if(!i)return r(` Update Shellbell on this computer to connect terminals from the command line.`),2;if(!i.started)return r(` ${t} has no connection step. Run shellbell doctor to see its status.`),2;r(` macOS may ask to let Shellbell control iTerm2, and iTerm2 may ask to allow Shellbell.`);let a=Date.now()+(n.timeoutMs??13e4),o=i.terminals;for(;o.find(e=>e.name===t)?.issue===`connecting`&&Date.now()<a;)await new Promise(e=>setTimeout(e,n.pollMs??500)),o=await e.terminals()??o;let s=o.find(e=>e.name===t);if(!s)return 2;let{status:c,fix:l}=Qn(s,`command-line`);return r(` ${c}`),l&&r(` ${l}`),s.connected&&!s.issue?0:2}$.command(`connect <terminal>`).description(`connect a terminal that needs your approval, such as iterm2`).action(async e=>{let{p:t}=Yc(),n;try{n=await h(t.sock),process.exitCode=await cl(n,e)}catch(e){sl(e)}finally{n?.close()}}),$.command(`unpair <target>`).description(`remove a paired phone (fp prefix or name)`).action(async e=>{let{p:t}=Yc();try{let n=await se(t.sock,`unpair`,{target:e});console.log(n.removed?` removed`:` no such phone`)}catch(e){sl(e)}});function ll(e,t,n={}){let r=e.command(`service`).description(`manage the per-user service`);for(let[i,a]of Object.entries({status:`inspect the installed service and local readiness without starting it`,install:`install or update the service (Linux: does not start or enable)`,start:`start the installed definition and verify local readiness`,stop:`stop now; retain the configured future autostart choice`,restart:`restart the installed definition and verify the new process`,uninstall:`remove future autostart; identity and pairings remain`,enable:`enable future per-user startup; do not start now`,disable:`disable owned future startup; do not stop now`}))r.command(i).description(a).action(async()=>{let r=e.opts().json,a=n.platform??process.platform,o=a===`linux`;if(!o&&a!==`darwin`){let e=`Service management supports macOS launchd and Linux systemd user managers only`;r?console.log(JSON.stringify({error:e})):console.error(` ${e}`),process.exitCode=2;return}try{if(o){let e=await(n.createLinuxLifecycle??(()=>new Ds({env:process.env})))()[i](),t=[`start`,`restart`,`status`].includes(i)?e.ready:i===`enable`?e.enabled&&e.autostartConfigured:i===`disable`?!e.enabled&&!e.autostartConfigured:i===`uninstall`?!e.installed&&!e.enabled&&!e.autostartConfigured:i!==`install`||e.installed;console.log(r?JSON.stringify(e):`${JSON.stringify(e,null,2)}\n Future autostart: ${e.enabled?`enabled`:`disabled`}; linger: ${e.linger}. Stop retains autostart; disable does not stop a running job.\n Linger is an operator policy; Shellbell never enables it automatically.`),process.exitCode=t?0:2;return}let e=await t()[i]();console.log(r?JSON.stringify(e):JSON.stringify(e,null,2)),i===`install`&&!r&&console.log(ul),process.exitCode=i===`status`&&!e.ready?2:0}catch(e){if(o){let t=e instanceof Error&&e.message.startsWith(`shellbell:`)?e.message:`Linux systemd service operation failed; inspect service status, host state, and the durable installed runtime before retrying`;r?console.log(JSON.stringify({error:t})):console.error(` ${t}`),process.exitCode=2;return}let t=e instanceof lt?e:new lt(e instanceof Error?e.message:`Service operation failed`),n={error:t.message,rollback:t.rollback,rollbackDiagnostic:t.rollbackDiagnostic,recoveryPath:t.recoveryPath};r?console.log(JSON.stringify(n)):console.error(` ${t.message}\n rollback: ${t.rollback}${t.rollbackDiagnostic?` — ${t.rollbackDiagnostic}`:``}${t.recoveryPath?`\n recovery definition: ${t.recoveryPath}`:``}`),process.exitCode=2}})}const ul=`
42
+ macOS may now ask a few questions. Each one is optional:
43
+ - "Background Items Added: node" is this service. node is the runtime Shellbell runs on.
44
+ - "node" or "osascript" wants to control "iTerm2" appears when you run
45
+ shellbell connect iterm2, so your phone can show iTerm2 tabs and type into them.
46
+ Shellbell controls no other app.
47
+ - "Find devices on your local network" lets your phone connect straight to this Mac on the
48
+ same Wi-Fi. Without it, your phone may not connect while it is on the same Wi-Fi.
49
+ Change any answer later in System Settings → Privacy & Security.`;ll($,()=>new Ct({manager:f(),requestedStateDir:process.env.SHELLBELL_DIR||void 0,defaultStateDir:L(P(),`.shellbell`),env:process.env})),$.command(`logs`).option(`-f, --follow`).description(`show the agent log`).action(e=>{let{p:t}=Yc();e.follow?Bt(`tail`,[`-f`,t.log],{stdio:`inherit`}):Ut(t.log)&&process.stdout.write(tl(t.log,65536,200))});function dl(e,t){process.exitCode=2,t?console.log(JSON.stringify({error:e})):console.error(` ${e}`)}$.command(`config`).description(`config set <${a.join(`|`)}> <value>`).argument(`<op>`).argument(`<key>`).argument(`<value>`).action((e,t,n)=>{let r=$.opts();if(e!==`set`){dl(`unknown config operation ${e} (expected set)`,r.json);return}let i=!!r.insecure||process.env.SHELLBELL_ALLOW_INSECURE_RELAY===`1`,a=ye(yt(),t,n,i);if(`error`in a){dl(a.error,r.json);return}try{let e=Kc();Qe(e,e=>{let r=ye(e,t,n,i);if(`error`in r)throw Error(r.error);return r.next})}catch(e){dl(e instanceof Error?e.message:String(e),r.json);return}r.json?console.log(JSON.stringify({saved:!0,restartRequired:!0})):console.log(` configuration saved; the running agent must be restarted`)});function fl(e,t,n=console.log,r=e=>{process.exitCode=e}){let i=As(e);if(t)n(JSON.stringify(e));else for(let t of e)n(` ${t.severity===`pass`?`✓`:t.severity===`warning`?`!`:`✗`} ${t.name.padEnd(18)} ${t.detail}${t.fix?`\n fix: ${t.fix}`:``}`);r(i)}function pl(e,t={}){e.command(`doctor`).description(`inspect local agent, relay and terminal backend health without changing state`).option(`--require-backend [name]`,`treat a disconnected backend as an error (repeatable)`,(e,t)=>[...t,typeof e==`string`?e:``],[]).action(async n=>{let r=!!e.opts().json,i=new Set(Array.isArray(n.requireBackend)?n.requireBackend:[``]);if([...i].some(e=>!v.some(t=>t===e))){let e={name:`doctor arguments`,ok:!1,severity:`error`,detail:`invalid required backend name`,fix:`use iterm2, tmux, or herdr`};console.log(r?JSON.stringify([e]):` ✗ ${e.name} ${e.detail}\n fix: ${e.fix}`),process.exitCode=2;return}let a=v.filter(e=>i.has(e)),o=t.env??process.env,s;try{s=await(t.runDoctor??Bs)({requestedStateDir:o.SHELLBELL_DIR,defaultStateDir:t.defaultStateDir??L(P(),`.shellbell`),requiredBackends:a,env:o})}catch{s=[{name:`doctor`,ok:!1,severity:`error`,detail:`diagnostic inspection failed`}]}fl(s,r)})}pl($),qc($);function ml(e,t,n=tn){if(!e)return!1;let r;try{r=n(e)}catch{r=e}let i=gn(t),a;try{a=n(i)}catch{a=i}return a===r}ml(process.argv[1],import.meta.url)&&$.parseAsync().catch(e=>{console.error(e),process.exit(1)});export{a as CONFIG_KEYS,ul as MACOS_SERVICE_PROMPTS,pl as addDoctorCommand,ll as addServiceCommands,ol as buildAgent,rl as chooseConfirm,cl as connectTerminalCommand,ml as isEntryPoint,fl as printDoctorResult,$ as program,ye as resolveConfigSet,al as resolveRelayOverride,il as shutdown,nl as socketAlive,tl as tailFile,we as validateRelayUrl};