shellbell 0.15.1 → 0.16.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 CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{$ as e,$n as t,$t as n,A as r,An as i,At as a,B as o,Bn as s,Bt as c,Ct as l,D as u,Dn as d,Dt as f,En as p,Et as m,Fn as h,Ft as g,G as _,Gn as v,Gt as y,H as b,Hn as x,Ht as ee,I as te,In as S,It as C,J as ne,Jn as re,Jt as ie,Kn as ae,Kt as oe,Ln as se,Lt as ce,M as le,Mn as ue,Mt as de,N as fe,Nn as pe,Nt as w,On as me,Ot as he,P as ge,Pn as _e,Pt as ve,Q as T,Qn as E,Qt as ye,Rn as be,Rt as xe,Sn as Se,Tn as Ce,Tt as we,U as Te,Un as D,Ut as Ee,V as De,Vn as Oe,Vt as ke,W as Ae,Wn as je,Wt as Me,X as Ne,Xn as Pe,Xt as Fe,Y as Ie,Yn as O,Yt as Le,Z as Re,Zn as ze,Zt as Be,_n as Ve,_t as He,a as Ue,an as We,ar as Ge,at as Ke,bn as qe,bt as Je,cn as Ye,cr as Xe,d as Ze,dn as Qe,dt as $e,en as et,er as tt,et as nt,fn as rt,ft as it,hn as at,ht as ot,in as st,ir as ct,it as lt,jn as ut,jt as dt,kn as ft,l as pt,ln as mt,lr as k,lt as ht,mn as gt,mt as _t,n as vt,nn as yt,nr as bt,nt as xt,or as St,pn as Ct,pt as wt,q as Tt,qn as A,qt as Et,rn as Dt,rt as Ot,sn as kt,sr as At,st as j,t as jt,tn as Mt,tr as Nt,tt as M,u as Pt,un as Ft,ut as It,vn as Lt,vt as Rt,wn as zt,wt as Bt,xn as Vt,xt as Ht,yn as Ut,yt as Wt,zn as Gt,zt as Kt}from"./service-lifecycle-CSQmtvfk.js";import{$ as qt,A as Jt,B as Yt,C as Xt,D as Zt,E as Qt,F as $t,G as en,H as tn,I as nn,J as rn,K as an,L as on,M as sn,N as cn,O as ln,P as un,Q as dn,R as fn,S as pn,T as mn,U as hn,V as gn,W as _n,X as vn,Y as yn,Z as bn,_ as xn,a as Sn,at as Cn,b as wn,c as Tn,ct as En,d as Dn,et as On,f as kn,g as An,h as jn,i as Mn,it as Nn,j as Pn,k as Fn,l as In,m as Ln,n as Rn,nt as zn,o as Bn,ot as Vn,p as Hn,q as Un,r as Wn,rt as Gn,s as Kn,st as qn,tt as Jn,u as Yn,v as Xn,w as Zn,x as Qn,y as $n,z as er}from"./doctor-CTHrssge.js";import{execFile as tr,spawn as nr}from"node:child_process";import{closeSync as rr,constants as ir,existsSync as ar,fstatSync as or,fsyncSync as sr,lstatSync as cr,mkdirSync as lr,openSync as ur,opendirSync as dr,readFileSync as fr,readSync as pr,realpathSync as mr,statSync as hr,watch as gr}from"node:fs";import{homedir as N,hostname as _r,tmpdir as vr,userInfo as yr}from"node:os";import{basename as br,dirname as P,isAbsolute as F,join as I,normalize as xr,relative as Sr,sep as Cr}from"node:path";import{createInterface as wr}from"node:readline";import{fileURLToPath as Tr,pathToFileURL as Er}from"node:url";import{z as L}from"zod";import{Command as Dr,Option as Or}from"commander";import kr from"qrcode-terminal";import{createHash as R,randomUUID as Ar,timingSafeEqual as jr}from"node:crypto";import{EventEmitter as Mr}from"node:events";import{connect as Nr,createConnection as Pr,isIP as Fr}from"node:net";import{lstat as z,mkdtemp as Ir,open as Lr,opendir as Rr,readFile as zr,readdir as Br,readlink as Vr,realpath as B,rm as Hr}from"node:fs/promises";import Ur from"ws";import{promisify as Wr}from"node:util";import{create as V}from"@bufbuild/protobuf";import{importTerminalPlugin as Gr}from"#terminal-plugin-loader";import{createInterface as Kr}from"node:readline/promises";function qr(e){return e?e.r.map(e=>e.t).join(``):``}const Jr=[[/\bIs this a project you (?:created or one you )?trust\?/i,`Is this a project you trust?`],[/\bTrust this folder\?/i,`Trust this folder?`],[/\bDo you trust the files in this folder\?/i,`Do you trust the files in this folder?`]],Yr=/^[❯›▶➤▸]\s*\S/u,Xr=/\b(?:enter to confirm|enter continue|press enter to (?:confirm|continue))\b/i;function Zr(e){if(!e.some(e=>Yr.test(e.text))||!e.some(e=>Xr.test(e.text)))return null;let t=e.map(e=>e.text).join(` `);for(let[e,n]of Jr)if(e.test(t))return n;return null}const Qr=/^(?:([❯›▶➤▸])\s*)?([1-9])[.)]\s+(\S.*)$/u,$r=/^\s*[│┃║▌▐]/u,ei=/[│┃║▌▐]\s*$/u;function ti(e){return ni.test(e)}const ni=/^[\s─━═┄┈╌╭╮╰╯┌┐└┘├┤┬┴┼-]*$/u,ri=/\s+\((?:esc|enter|tab|shift\+tab|ctrl\+[a-z]|[a-z])\)$/i,ii=/\s+\((esc|enter|[a-z])\)$/i,ai=/(?:\[(?:y\/n|n\/y|yes\/no|no\/yes)\]|\((?:y\/n|n\/y|yes\/no|no\/yes)\))\s*[:?]?\s*$/i;function oi(e){let t=e.replace($r,``).replace(ei,``).trimEnd(),n=t.trimStart();return{indent:t.length-n.length,text:ti(n)?``:n}}function si(e,t){let n=e.replace(/\s+/g,` `).trim(),r=Array.from(n);return r.length>t?`${r.slice(0,t-1).join(``).trimEnd()}…`:n}function ci(e){let t=[];for(let n=0;n<e.length;n++){if(Qr.exec(e[n].text)?.[2]!==`1`)continue;let r={first:n,options:[],markers:0},i=e[n].indent,a=n;for(;a<e.length;a++){let t=e[a],o=Qr.exec(t.text);if(o&&o[2]===String(r.options.length+1)){o[1]&&r.markers++,i=o[1]?t.indent+2:t.indent;let e=o[3].replace(ri,``),n=ii.exec(o[3])?.[1],a=n?.length===1?n:n?.toLowerCase();r.options.push({digit:o[2],label:si(e,48),...a&&(a!==`enter`||o[1])&&{shortcut:a}});continue}if(!(a>n&&t.text&&!o&&t.indent>i))break}t.push(r),n=a-1}return t}function li(e){if(!e||e.lines.length===0)return{question:null,options:null};let t=e.lines.map(e=>oi(qr(e))),n=t.length-1;for(;n>0&&!t[n].text;)n--;let r=e.cursor.y>=0&&e.cursor.y<t.length?e.cursor.y:-1,i=Math.max(0,(r>=0?r:n)-20),a=Math.min(t.length-1,r>=0?r+20:n),o=t.slice(i,a+1),s=ci(o).filter(e=>e.options.length>=2&&e.markers>0),c=s.length===1&&s[0].markers===1?s[0]:null,l=Zr(o);if(c)return{question:l??ui(o,c.first),options:c.options,...l?{trust:l}:{}};let u=r>=0?t[r]?.text:void 0,d=u&&ai.exec(u)?.[0];return{question:di(t,r>=0?r:n),options:null,...d?{yesNo:/yes|no/i.test(d)?`yes/no`:`y/n`}:{},...l?{trust:l}:{}}}function ui(e,t){let n=null;for(let r=t-1;r>=Math.max(0,t-8);r--){let t=e[r].text;if(t){if(Qr.test(t))break;if(/\?\s*$/.test(t))return si(t,120);n??=t}}return n===null?null:si(n,120)}function di(e,t){for(let n=t;n>=Math.max(0,t-3);n--){let t=e[n]?.text;if(t)return si(t,120)}return null}function fi(e){return e.options?`menu`:e.yesNo?`yes-no`:null}const pi=e=>/^turns?:/.test(e),mi=e=>!/:53(\?|$)/.test(e);function hi(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=>pi(e)&&mi(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 gi=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 hi(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)}},_i=class extends Mr{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`}setPromptState(e,t,n){e.promptState!==t&&e.promptState!==`unknown`&&(e.stateSince=n),e.promptState=t}activityOf(e){let t=this.s.get(e);return{...t?.lastChangeAt?{activeAt:t.lastChangeAt}:{},...t?.stateSince==null?{}:{stateSince:t.stateSince},reportsAgentState:t?.agentState!=null}}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,stateSince: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);this.setPromptState(n,`running`,t),n.commandStartedAt=t,n.command=e.command;return}case`command-end`:{let n=this.get(e.sessionId);this.setPromptState(n,`finished`,t);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,this.setPromptState(n,`editing`,t),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,this.setPromptState(n,`running`,t),n.workingSince=t;return}if(e.state===`blocked`){this.setPromptState(n,`blocked`,t),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`){this.setPromptState(n,`finished`,t);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.stateSince=null,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 vi(e){return e===`darwin`||e===`linux`||e===`win32`?e:`unknown`}function yi(e){return{type:`notify`,sessionId:e.sessionId,kind:e.kind,exitCode:e.exitCode,durationMs:e.durationMs}}function bi(e){let t={...e,context:{...e.context}};for(let e of[`branch`,`title`,`agentName`,`shell`,`customName`,`repository`]){if(p.safeParse(t).success)return t;delete t.context[e]}return p.safeParse(t).success?t:void 0}var xi=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(yi(e))},250)}),c=Promise.race([this.build(e,()=>i||performance.now()-a>=250,r),s]).catch(()=>yi(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>=zt.freshnessMs)return yi(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}:yi(e)});return this.cache.set(e,l),l()}async build(e,t,n){let r=this.options,i=r.now??Date.now,a=yi(e);if(!r.capable()||!e.reason)return a;let o=O(Oe(16)),s=r.pairings().slice(0,10),c=await r.facts(e.sessionId);if(!c||t())return a;let l=async()=>{let t=await r.facts(e.sessionId);return t?.revision===c.revision&&t.sessionId===c.sessionId},u=await Gn(c,{computerName:r.computerName(),now:i,stillCurrent:l,git:r.git});if(t()||!r.capable()||!await l()||t())return a;let d=i();if(d-n>=zt.freshnessMs||d<n||d<u.observedAt)return a;let f=[],p={type:`notify-context`,sessionId:e.sessionId,eventId:o,kind:e.kind,exitCode:e.exitCode,durationMs:e.durationMs,boxes:f};for(let i of s){if(t())break;if(!r.pairings().some(e=>e.phoneFp===i.phoneFp&&e.kPair===i.kPair))continue;let a=r.state.reserve(i.phoneFp);if(!a)continue;let s=bi({computerFp:r.computerFp,phoneFp:i.phoneFp,generation:a.generation,sessionId:e.sessionId,eventId:o,sequence:a.sequence,issuedAt:d,expiresAt:n+zt.freshnessMs,reason:e.reason,context:u,exitCode:e.exitCode,durationMs:e.durationMs,...c.instance&&r.state.instanceReader(i.phoneFp,a.generation)&&{instance:c.instance}});if(!s)continue;let l,m;try{l=A(i.kPair),m=yt(l,s),f.push(Dt(m,s)),Buffer.byteLength(JSON.stringify(p),`utf8`)>16384&&f.pop()}catch{}finally{l?.fill(0),m?.fill(0)}}return f.length?p:a}};const Si=L.string().regex(/^(0|[1-9][0-9]{0,19})$/).refine(e=>BigInt(e)<=18446744073709551615n),Ci=L.strictObject({generation:Ce,used:L.number().int().min(0).max(zt.encryptions)}),wi=L.strictObject({version:L.literal(1),phones:L.array(L.strictObject({phoneFp:bt,sequence:Si,current:Ci,previous:L.strictObject({generation:Ce,expiresAt:L.number().int().nonnegative().max(2**53-1)}).optional()})).max(10).refine(e=>new Set(e.map(e=>e.phoneFp)).size===e.length)});var Ti=class{paths;now;data={version:1,phones:[]};healthy=!0;readsInstance=new Map;file;constructor(e,t=Date.now){this.paths=e,this.now=t,this.file=I(e.dir,`notifications.json`);try{$e(e);let t=I(e.dir,`notifications.initialized`),n=w(t)!==void 0;if(n&&dt(t,8,process.getuid?.()).toString(`utf8`)!==`v1
2
+ import{$ as e,$n as t,$t as n,A as r,An as i,At as a,B as o,Bn as s,Bt as c,Ct as l,D as u,Dn as d,Dt as f,En as p,Et as m,Fn as h,Ft as g,G as _,Gn as v,Gt as y,H as b,Hn as x,Ht as ee,I as te,In as S,It as C,J as ne,Jn as re,Jt as ie,Kn as ae,Kt as oe,Ln as se,Lt as ce,M as le,Mn as ue,Mt as de,N as fe,Nn as pe,Nt as w,On as me,Ot as he,P as ge,Pn as _e,Pt as ve,Q as T,Qn as E,Qt as ye,Rn as be,Rt as xe,Sn as Se,Tn as Ce,Tt as we,U as Te,Un as D,Ut as Ee,V as De,Vn as Oe,Vt as ke,W as Ae,Wn as je,Wt as Me,X as Ne,Xn as Pe,Xt as Fe,Y as Ie,Yn as O,Yt as Le,Z as Re,Zn as ze,Zt as Be,_n as Ve,_t as He,a as Ue,an as We,ar as Ge,at as Ke,bn as qe,bt as Je,cn as Ye,cr as Xe,d as Ze,dn as Qe,dt as $e,en as et,er as tt,et as nt,fn as rt,ft as it,hn as at,ht as ot,in as st,ir as ct,it as lt,jn as ut,jt as dt,kn as ft,l as pt,ln as mt,lr as k,lt as ht,mn as gt,mt as _t,n as vt,nn as yt,nr as bt,nt as xt,or as St,pn as Ct,pt as wt,q as Tt,qn as A,qt as Et,rn as Dt,rt as Ot,sn as kt,sr as At,st as j,t as jt,tn as Mt,tr as Nt,tt as M,u as Pt,un as Ft,ut as It,vn as Lt,vt as Rt,wn as zt,wt as Bt,xn as Vt,xt as Ht,yn as Ut,yt as Wt,zn as Gt,zt as Kt}from"./service-lifecycle-CLWP08Es.js";import{$ as qt,A as Jt,B as Yt,C as Xt,D as Zt,E as Qt,F as $t,G as en,H as tn,I as nn,J as rn,K as an,L as on,M as sn,N as cn,O as ln,P as un,Q as dn,R as fn,S as pn,T as mn,U as hn,V as gn,W as _n,X as vn,Y as yn,Z as bn,_ as xn,a as Sn,at as Cn,b as wn,c as Tn,ct as En,d as Dn,et as On,f as kn,g as An,h as jn,i as Mn,it as Nn,j as Pn,k as Fn,l as In,m as Ln,n as Rn,nt as zn,o as Bn,ot as Vn,p as Hn,q as Un,r as Wn,rt as Gn,s as Kn,st as qn,tt as Jn,u as Yn,v as Xn,w as Zn,x as Qn,y as $n,z as er}from"./doctor-7CO6h_gI.js";import{execFile as tr,spawn as nr}from"node:child_process";import{closeSync as rr,constants as ir,existsSync as ar,fstatSync as or,fsyncSync as sr,lstatSync as cr,mkdirSync as lr,openSync as ur,opendirSync as dr,readFileSync as fr,readSync as pr,realpathSync as mr,statSync as hr,watch as gr}from"node:fs";import{homedir as N,hostname as _r,tmpdir as vr,userInfo as yr}from"node:os";import{basename as br,dirname as P,isAbsolute as F,join as I,normalize as xr,relative as Sr,sep as Cr}from"node:path";import{createInterface as wr}from"node:readline";import{fileURLToPath as Tr,pathToFileURL as Er}from"node:url";import{z as L}from"zod";import{Command as Dr,Option as Or}from"commander";import kr from"qrcode-terminal";import{createHash as R,randomUUID as Ar,timingSafeEqual as jr}from"node:crypto";import{EventEmitter as Mr}from"node:events";import{connect as Nr,createConnection as Pr,isIP as Fr}from"node:net";import{lstat as z,mkdtemp as Ir,open as Lr,opendir as Rr,readFile as zr,readdir as Br,readlink as Vr,realpath as B,rm as Hr}from"node:fs/promises";import Ur from"ws";import{promisify as Wr}from"node:util";import{create as V}from"@bufbuild/protobuf";import{importTerminalPlugin as Gr}from"#terminal-plugin-loader";import{createInterface as Kr}from"node:readline/promises";function qr(e){return e?e.r.map(e=>e.t).join(``):``}const Jr=[[/\bIs this a project you (?:created or one you )?trust\?/i,`Is this a project you trust?`],[/\bTrust this folder\?/i,`Trust this folder?`],[/\bDo you trust the files in this folder\?/i,`Do you trust the files in this folder?`]],Yr=/^[❯›▶➤▸]\s*\S/u,Xr=/\b(?:enter to confirm|enter continue|press enter to (?:confirm|continue))\b/i;function Zr(e){if(!e.some(e=>Yr.test(e.text))||!e.some(e=>Xr.test(e.text)))return null;let t=e.map(e=>e.text).join(` `);for(let[e,n]of Jr)if(e.test(t))return n;return null}const Qr=/^(?:([❯›▶➤▸])\s*)?([1-9])[.)]\s+(\S.*)$/u,$r=/^\s*[│┃║▌▐]/u,ei=/[│┃║▌▐]\s*$/u;function ti(e){return ni.test(e)}const ni=/^[\s─━═┄┈╌╭╮╰╯┌┐└┘├┤┬┴┼-]*$/u,ri=/\s+\((?:esc|enter|tab|shift\+tab|ctrl\+[a-z]|[a-z])\)$/i,ii=/\s+\((esc|enter|[a-z])\)$/i,ai=/(?:\[(?:y\/n|n\/y|yes\/no|no\/yes)\]|\((?:y\/n|n\/y|yes\/no|no\/yes)\))\s*[:?]?\s*$/i;function oi(e){let t=e.replace($r,``).replace(ei,``).trimEnd(),n=t.trimStart();return{indent:t.length-n.length,text:ti(n)?``:n}}function si(e,t){let n=e.replace(/\s+/g,` `).trim(),r=Array.from(n);return r.length>t?`${r.slice(0,t-1).join(``).trimEnd()}…`:n}function ci(e){let t=[];for(let n=0;n<e.length;n++){if(Qr.exec(e[n].text)?.[2]!==`1`)continue;let r={first:n,options:[],markers:0},i=e[n].indent,a=n;for(;a<e.length;a++){let t=e[a],o=Qr.exec(t.text);if(o&&o[2]===String(r.options.length+1)){o[1]&&r.markers++,i=o[1]?t.indent+2:t.indent;let e=o[3].replace(ri,``),n=ii.exec(o[3])?.[1],a=n?.length===1?n:n?.toLowerCase();r.options.push({digit:o[2],label:si(e,48),...a&&(a!==`enter`||o[1])&&{shortcut:a}});continue}if(!(a>n&&t.text&&!o&&t.indent>i))break}t.push(r),n=a-1}return t}function li(e){if(!e||e.lines.length===0)return{question:null,options:null};let t=e.lines.map(e=>oi(qr(e))),n=t.length-1;for(;n>0&&!t[n].text;)n--;let r=e.cursor.y>=0&&e.cursor.y<t.length?e.cursor.y:-1,i=Math.max(0,(r>=0?r:n)-20),a=Math.min(t.length-1,r>=0?r+20:n),o=t.slice(i,a+1),s=ci(o).filter(e=>e.options.length>=2&&e.markers>0),c=s.length===1&&s[0].markers===1?s[0]:null,l=Zr(o);if(c)return{question:l??ui(o,c.first),options:c.options,...l?{trust:l}:{}};let u=r>=0?t[r]?.text:void 0,d=u&&ai.exec(u)?.[0];return{question:di(t,r>=0?r:n),options:null,...d?{yesNo:/yes|no/i.test(d)?`yes/no`:`y/n`}:{},...l?{trust:l}:{}}}function ui(e,t){let n=null;for(let r=t-1;r>=Math.max(0,t-8);r--){let t=e[r].text;if(t){if(Qr.test(t))break;if(/\?\s*$/.test(t))return si(t,120);n??=t}}return n===null?null:si(n,120)}function di(e,t){for(let n=t;n>=Math.max(0,t-3);n--){let t=e[n]?.text;if(t)return si(t,120)}return null}function fi(e){return e.options?`menu`:e.yesNo?`yes-no`:null}const pi=e=>/^turns?:/.test(e),mi=e=>!/:53(\?|$)/.test(e);function hi(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=>pi(e)&&mi(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 gi=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 hi(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)}},_i=class extends Mr{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`}setPromptState(e,t,n){e.promptState!==t&&e.promptState!==`unknown`&&(e.stateSince=n),e.promptState=t}activityOf(e){let t=this.s.get(e);return{...t?.lastChangeAt?{activeAt:t.lastChangeAt}:{},...t?.stateSince==null?{}:{stateSince:t.stateSince},reportsAgentState:t?.agentState!=null}}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,stateSince: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);this.setPromptState(n,`running`,t),n.commandStartedAt=t,n.command=e.command;return}case`command-end`:{let n=this.get(e.sessionId);this.setPromptState(n,`finished`,t);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,this.setPromptState(n,`editing`,t),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,this.setPromptState(n,`running`,t),n.workingSince=t;return}if(e.state===`blocked`){this.setPromptState(n,`blocked`,t),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`){this.setPromptState(n,`finished`,t);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.stateSince=null,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 vi(e){return e===`darwin`||e===`linux`||e===`win32`?e:`unknown`}function yi(e){return{type:`notify`,sessionId:e.sessionId,kind:e.kind,exitCode:e.exitCode,durationMs:e.durationMs}}function bi(e){let t={...e,context:{...e.context}};for(let e of[`branch`,`title`,`agentName`,`shell`,`customName`,`repository`]){if(p.safeParse(t).success)return t;delete t.context[e]}return p.safeParse(t).success?t:void 0}var xi=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(yi(e))},250)}),c=Promise.race([this.build(e,()=>i||performance.now()-a>=250,r),s]).catch(()=>yi(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>=zt.freshnessMs)return yi(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}:yi(e)});return this.cache.set(e,l),l()}async build(e,t,n){let r=this.options,i=r.now??Date.now,a=yi(e);if(!r.capable()||!e.reason)return a;let o=O(Oe(16)),s=r.pairings().slice(0,10),c=await r.facts(e.sessionId);if(!c||t())return a;let l=async()=>{let t=await r.facts(e.sessionId);return t?.revision===c.revision&&t.sessionId===c.sessionId},u=await Gn(c,{computerName:r.computerName(),now:i,stillCurrent:l,git:r.git});if(t()||!r.capable()||!await l()||t())return a;let d=i();if(d-n>=zt.freshnessMs||d<n||d<u.observedAt)return a;let f=[],p={type:`notify-context`,sessionId:e.sessionId,eventId:o,kind:e.kind,exitCode:e.exitCode,durationMs:e.durationMs,boxes:f};for(let i of s){if(t())break;if(!r.pairings().some(e=>e.phoneFp===i.phoneFp&&e.kPair===i.kPair))continue;let a=r.state.reserve(i.phoneFp);if(!a)continue;let s=bi({computerFp:r.computerFp,phoneFp:i.phoneFp,generation:a.generation,sessionId:e.sessionId,eventId:o,sequence:a.sequence,issuedAt:d,expiresAt:n+zt.freshnessMs,reason:e.reason,context:u,exitCode:e.exitCode,durationMs:e.durationMs,...c.instance&&r.state.instanceReader(i.phoneFp,a.generation)&&{instance:c.instance}});if(!s)continue;let l,m;try{l=A(i.kPair),m=yt(l,s),f.push(Dt(m,s)),Buffer.byteLength(JSON.stringify(p),`utf8`)>16384&&f.pop()}catch{}finally{l?.fill(0),m?.fill(0)}}return f.length?p:a}};const Si=L.string().regex(/^(0|[1-9][0-9]{0,19})$/).refine(e=>BigInt(e)<=18446744073709551615n),Ci=L.strictObject({generation:Ce,used:L.number().int().min(0).max(zt.encryptions)}),wi=L.strictObject({version:L.literal(1),phones:L.array(L.strictObject({phoneFp:bt,sequence:Si,current:Ci,previous:L.strictObject({generation:Ce,expiresAt:L.number().int().nonnegative().max(2**53-1)}).optional()})).max(10).refine(e=>new Set(e.map(e=>e.phoneFp)).size===e.length)});var Ti=class{paths;now;data={version:1,phones:[]};healthy=!0;readsInstance=new Map;file;constructor(e,t=Date.now){this.paths=e,this.now=t,this.file=I(e.dir,`notifications.json`);try{$e(e);let t=I(e.dir,`notifications.initialized`),n=w(t)!==void 0;if(n&&dt(t,8,process.getuid?.()).toString(`utf8`)!==`v1
3
3
  `)throw Error(`invalid marker`);try{this.data=wi.parse(JSON.parse(dt(this.file,16384,process.getuid?.()).toString(`utf8`)))}catch(e){if(n||!(e instanceof a&&e.kind===`missing`))throw e;if(!this.commit(this.data))return}n||(Rt(t,`v1
4
4
  `),this.syncDirectory())}catch{this.healthy=!1}}syncDirectory(){if(process.platform===`win32`)return;let e=ur(this.paths.dir,`r`);try{sr(e)}finally{rr(e)}}commit(e){if(!this.healthy)return!1;try{return $e(this.paths),Rt(this.file,JSON.stringify(e)),this.syncDirectory(),this.data=e,!0}catch{return this.healthy=!1,!1}}enroll(e,t,n=[]){if(!this.healthy||!bt.safeParse(e).success||!Ce.safeParse(t).success)return!1;n.includes(`notify-instance-v1`)?this.readsInstance.set(e,t):this.readsInstance.delete(e);let r=this.data.phones.find(t=>t.phoneFp===e);if(r?.current.generation===t)return r.current.used<zt.encryptions;if(r?.previous?.generation===t||!r&&this.data.phones.length>=10)return!1;let i=structuredClone(this.data);return i.phones=i.phones.filter(t=>t.phoneFp!==e),i.phones.push({phoneFp:e,sequence:r?.sequence??`0`,current:{generation:t,used:0},...r?{previous:{generation:r.current.generation,expiresAt:this.now()+zt.previousGenerationMs}}:{}}),this.commit(i)}reserve(e){if(!this.healthy)return;let t=structuredClone(this.data),n=t.phones.find(t=>t.phoneFp===e);if(!(!n||n.current.used>=zt.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}instanceReader(e,t){return this.readsInstance.get(e)===t}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){this.readsInstance.delete(e);let t=structuredClone(this.data);t.phones=t.phones.filter(t=>t.phoneFp!==e),this.commit(t)}};const Ei=6e4;var Di=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>=Ei&&this.last.delete(n);return n!==void 0&&t-n<Ei?!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(yi(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 Oi(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 ki=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 Ai=L.instanceof(Uint8Array).refine(e=>e.length===32,{message:`expected 32 bytes`}),ji=L.instanceof(Uint8Array).refine(e=>e.length===64,{message:`expected 64 bytes`});function Mi(e){return e.replace(/[\p{Cc}\p{Cs}\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]/gu,` `).replace(/\s+/gu,` `).trim()||`Phone`}const Ni=L.object({ed25519Pub:Ai,x25519Pub:Ai,name:L.string().min(1).max(64).transform(Mi),platform:L.enum([`ios`,`android`]),bind:ji});var Pi=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(`replaced`);let e=Oe(16),t=Oe(16),r=this.now()+(this.opts.windowMs??3e5),i=n({v:1,r:this.opts.relayUrl,c:this.opts.fp,e:O(this.opts.identity.ed25519.pub),n:this.opts.computerName.slice(0,40),p:O(e),g:O(t),b:1,x:Math.ceil(r/1e3)});et(i,{allowInsecure:!0}),this.window={code:e,gate:t,expiresAt:r,failures:0,requests:0};let a=this.opts.sendCtrl({type:`pairing-open`,gateHash:s(t),expiresAt:r});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:r}}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:s(this.window.gate),expiresAt:this.window.expiresAt});this.log.debug(e?`pairing window re-advertised`:`pairing window re-advertise dropped`)}closeWindow(e=`closed`){if(!this.window)return;let t=this.window;t.code.fill(0),t.gate.fill(0),this.window=null,this.pending?.window===t&&(this.pending=null),this.opts.sendCtrl({type:`pairing-close`}),this.log.info(`pairing window closed`),this.opts.onClose?.(e)}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 r=ft(n.code,this.opts.fp),a;try{if(a=Ni.parse(Xe(_e(r,e.box,h(`request`,this.opts.fp,e.phoneFp)))),i(a.ed25519Pub)!==e.phoneFp)throw Error(`fp mismatch`);let t=S(`phone`,this.opts.fp,e.phoneFp,a.x25519Pub);if(!Gt(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 i=await this.confirmWithTimeout(e.phoneFp,a.name);if(this.pending?.token!==o||!this.isOpen||this.window!==n)return;if(!i)return t(`declined`);let s;try{s=me(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}if(this.opts.relayOnline?.()===!1){this.log.warn(`pairing approved while the relay was unreachable`,{phone:e.phoneFp.slice(0,8)});return}this.opts.savePairing({phoneFp:e.phoneFp,name:a.name,platform:a.platform,ed25519Pub:O(a.ed25519Pub),x25519Pub:O(a.x25519Pub),kPair:O(s),pairedAt:new Date(this.now()).toISOString(),lastSeenAt:null}),this.opts.sendCtrl({type:`pairing-add`,phoneFp:e.phoneFp,ed25519Pub:a.ed25519Pub,name:a.name,pairId:qe(s)});let c=se(r,k({x25519Pub:this.opts.identity.x25519.pub,computerName:this.opts.computerName,accent:this.opts.accent,bind:be(this.opts.identity.ed25519.priv,S(`computer`,this.opts.fp,e.phoneFp,this.opts.identity.x25519.pub))}),h(`response`,this.opts.fp,e.phoneFp));this.opts.sendCtrl({type:`pairing-response`,phoneFp:e.phoneFp,box:c}),this.log.info(`paired`,{phone:e.phoneFp.slice(0,8)}),this.closeWindow(`paired`)}finally{this.pending?.token===o&&(this.pending=null,this.closeIfExhausted(n))}}};const Fi=e=>!/^turns:/.test(e)&&!/[?&]transport=tcp(?:&|$)/.test(e);function Ii(e){return e.flatMap(e=>e.urls.filter(Fi).map(t=>e.username&&e.credential?t.replace(/^(turns?):/,`$1:${encodeURIComponent(e.username)}:${encodeURIComponent(e.credential)}@`):t))}function Li(e){let t=e.trim().replace(/%.*$/,``).toLowerCase();if(Fr(t)!==6)return t;try{return new URL(`http://[${t}]/`).hostname.slice(1,-1)}catch{return t}}function Ri(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:Li(t[4]),type:t[7]}}function zi(e,t={}){let n=t.turn!==!1;return t=>Bi(t,Ii(n?e():hi()),n)}zi(()=>hi());const Bi=async(e,t,n=!0)=>{let{default:r}=await import(`#webrtc-native`),i=new r.PeerConnection(`shellbell-v2`,{iceServers:t}),a=null,o=!1,s=new Set,c=new Map,l=new Set,u=()=>{let e=i.getSelectedCandidatePair();if(!e||e.local.type===`relay`||e.remote.type===`relay`)return!1;let t=Li(e.remote.address);return s.has(t)&&!l.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(u()){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){let r=Ri(e);if(r&&c.get(r.address)!==`host`&&c.set(r.address,r.type),!n){if(!r)return;if(r.type===`relay`){l.add(r.address);return}(r.type===`host`||r.type===`srflx`)&&s.add(r.address)}i.addRemoteCandidate(e,t??`0`)},async routeStats(){if(o||!d)return null;let e=i.getSelectedCandidatePair();if(!e)return null;let t=i.rtt();return{path:oe(e.local.type,c.get(Li(e.remote.address))??e.remote.type),...t>=0&&{rttMs:t}}},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=re(t.value.replaceAll(`:`,``));if(!ae(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 Vi=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;log;constructor(e){this.log=e.log,this.phoneFp=e.phoneFp,this.connId=e.connId,this.relayConnId=e.connId,this.name=e.name,this.endpoint=new y({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??zi(e.iceServers??(()=>hi()),{turn:e.turn}),allowDirect:!0,terminal:(t,n)=>{let r;try{r=at(Xe(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)}),t===`direct`&&this.logDirectRoute(),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(k(e))}relayLost(){this.endpoint.relayLost()}async logDirectRoute(){let e=await this.endpoint.routeStats();e&&!this.broken&&this.log.info(`v2 direct route`,{...e,setupMs:this.endpoint.diagnostics.directSetupMs,phone:this.phoneFp.slice(0,8)})}close(){this.broken=!0,this.handshaken=!1,this.endpoint.close()}};function Hi(e){return async t=>{let n=()=>!t.aborted&&e.enabled();try{if(!n())return null;let r=await e.reference(t);if(!n()||!r||typeof r.owner!=`string`||!r.owner||r.owner.length>1024)return null;let i=Object.freeze({...r}),a=await e.locator.locate(i,t);if(!n()||a.status!==`candidate`)return null;let o=Object.freeze({agent:a.candidate.agent,path:a.candidate.path,session:a.candidate.session});if(o.agent!==i.agent||(i.kind===`path`?o.path!==i.value:o.session!==i.value.toLowerCase()))return null;let s=await e.reference(t);return!n()||!On(i,s)||i.owner!==s?.owner?null:Object.freeze({...o,owner:i.owner,reference:i})}catch{return null}}}const Ui=new Set([`claude`,`codex`,`agy`,`gemini`]),H=e=>JSON.stringify([e.agent,e.kind,e.value]),Wi=(e,t)=>e.state===t.state&&e.id===t.id&&e.agent===t.agent&&e.reason===t.reason;var Gi=class{options;sessions=new Map;timer=null;probing=null;closed=!1;constructor(e){this.options={...e}}status(e){if(!this.closed&&this.options.enabled())return this.sessions.get(e)?.info}update(e){if(this.closed)return;let t=!1,n=new Set;for(let r of e){n.add(r.id);let e=this.sessions.get(r.id),i=r.agent?.kind;if(i){if(e?.present&&e.agent===i)continue;this.sessions.set(r.id,this.fresh(r.id,i,e)),t=!0}else if(e?.present){e.present=!1,e.generation=null,e.epoch++,e.due=1/0,this.cancel(r.id);let n=this.set(e,{state:`none`,agent:e.agent,reason:`agent-exited`});t||=n}}for(let e of[...this.sessions.keys()])n.has(e)||(this.sessions.delete(e),this.cancel(e));t&&this.notify(),this.schedule()}invalidate(e){let t=this.sessions.get(e);!this.closed&&t?.present&&this.lookable(e,t.agent)&&(t.epoch++,t.unsettled=0,t.due=this.now(),this.cancel(e),this.set(t,{state:`finding`,agent:t.agent})&&this.notify(),this.schedule())}recheck(e){let t=this.sessions.get(e);if(!this.closed&&t?.present&&this.lookable(e,t.agent)){if(t.info.state!==`found`){this.invalidate(e);return}t.epoch++,t.unsettled=0,t.due=this.now(),this.cancel(e),this.schedule()}}settled(){if(this.closed)return;let e=!1;for(let t of this.sessions.values())t.present&&t.unsettled>0&&t.due>this.now()&&(t.due=this.now(),e=!0);e&&this.schedule()}remove(e){this.sessions.delete(e)&&this.cancel(e)}wake(){if(!this.closed){if(!this.options.enabled()){this.cancel();for(let[e,t]of this.sessions)t.present?this.sessions.set(e,this.fresh(e,t.agent,t)):this.sessions.delete(e)}this.schedule()}}async check(e,t,n){let r=this.sessions.get(e),i=r?.generation,a={result:`conversation-changed`};if(this.closed||!this.options.enabled()||!r||!i||i.id!==t&&i.alias!==t)return a;let o=r.epoch,s=await this.options.reference(e,n).catch(()=>null),c=!this.closed&&this.options.enabled()&&this.sessions.get(e)===r&&r.epoch===o&&r.generation===i&&!n.aborted;return c&&s&&H(s)===i.key?{result:`ok`,...typeof s.waiting==`boolean`&&{waiting:s.waiting}}:!this.closed&&this.sessions.get(e)===r&&r.generation===i&&(!s||!c&&H(s)===i.key&&r.epoch!==o)?{result:`unchecked`}:(this.sessions.get(e)===r&&r.generation===i&&(s&&H(s)!==i.key&&this.options.replaced?.(e),this.invalidate(e)),a)}idFor(e,t){let n=this.sessions.get(e);if(this.closed||!this.options.enabled()||!n?.present)return;let r=H(t);return(n.generation?.key!==r||n.generation.kind!==`found`)&&(n.generation=this.found(n.generation,r),n.unsettled=0,n.due=this.now()+(this.options.refreshMs??1e4)),this.set(n,{state:`found`,id:n.generation.id,agent:t.agent})&&this.notify(),n.generation.id}knownId(e,t){let n=this.sessions.get(e)?.generation;return!this.closed&&this.options.enabled()&&n?.kind===`found`&&n.key===H(t)?n.id:void 0}holds(e,t){let n=this.sessions.get(e)?.generation;return!this.closed&&this.options.enabled()&&!!n&&(n.id===t||n.alias===t)}found(e,t){return{id:this.newId(),key:t,kind:`found`,...e?.kind===`not-started`&&e.key===t&&{alias:e.id}}}close(){this.closed=!0,this.cancel(),this.timer&&clearTimeout(this.timer),this.timer=null,this.sessions.clear()}fresh(e,t,n){n&&this.cancel(e);let r=this.lookable(e,t);return{agent:t,present:!0,info:r?{state:`finding`,agent:t}:{state:`none`,agent:t,reason:`not-supported`},generation:null,due:r?this.now():1/0,epoch:(n?.epoch??0)+1,unsettled:0}}lookable(e,t){return Ui.has(t)&&this.options.supported(e)}set(e,t){return!Wi(e.info,t)&&(e.info=t,!0)}notify(){this.options.enabled()&&this.options.changed()}now(){return this.options.now?.()??Date.now()}cancel(e){this.probing&&(e===void 0||this.probing.sessionId===e)&&(this.probing.controller.abort(),this.probing=null)}schedule(){if(this.closed||this.probing||(this.timer&&clearTimeout(this.timer),this.timer=null,!this.options.enabled()||!this.options.active()))return;let e=1/0;for(let t of this.sessions.values())e=Math.min(e,t.due);e!==1/0&&(this.timer=setTimeout(()=>{this.timer=null,this.pump()},Math.max(0,e-this.now())),this.timer.unref?.())}pump(){if(this.closed||this.probing||!this.options.enabled()||!this.options.active())return;let e=this.now(),t=null;for(let n of this.sessions){let[r,i]=n;if(i.due>e)continue;if(!t){t=n;continue}let a=this.options.viewed(r);(a===this.options.viewed(t[0])?i.due<t[1].due:a)&&(t=n)}if(!t){this.schedule();return}let[n,r]=t,i=new AbortController,a={sessionId:n,controller:i};this.probing=a,this.probe(n,r,i.signal).finally(()=>{this.probing===a&&(this.probing=null),this.schedule()})}async probe(e,t,n){let r=t.epoch,i=()=>!this.closed&&!n.aborted&&this.options.enabled()&&this.sessions.get(e)===t&&t.epoch===r,a=t.info.state===`found`?t.generation:null;if(a?.kind===`found`){let r=await this.within(n,t=>this.options.reference(e,t).catch(()=>null));if(!i())return;if(r&&H(r)===a.key){t.unsettled=0,t.due=this.now()+(this.options.refreshMs??1e4);return}}let o,s,c=Hi({enabled:i,reference:async t=>{let n=await this.options.reference(e,t);return o===void 0&&(o=n),n},locator:{locate:async(e,t)=>(s=await this.options.locator.locate(e,t),s)}}),l=await this.within(n,c);if(!i())return;let u=this.now(),d=u+(this.options.refreshMs??1e4),f=()=>{t.due=u+1e3},p=null;if(l&&o){let n=H(o);if(t.generation?.key!==n||t.generation.kind!==`found`){let r=t.generation;t.generation=this.found(r,n),r?.kind===`found`&&this.options.replaced?.(e)}t.unsettled=0,p={state:`found`,id:t.generation.id,agent:l.agent}}else if(s?.status===`busy`)f();else if(o===null)t.unsettled++===0?f():(t.generation=null,p={state:`none`,agent:t.agent,reason:`no-history`});else if(s?.status===`unavailable`){let n=s.reason;if(n===`unbound`&&o){let n=H(o);(t.generation?.key!==n||t.generation.kind!==`not-started`)&&(t.generation?.kind===`found`&&this.options.replaced?.(e),t.generation={id:this.newId(),key:n,kind:`not-started`}),p={state:`none`,agent:t.agent,reason:`not-started`,id:t.generation.id}}else n===`limit`||n===`ambiguous`||n===`unbound`?(t.generation=null,p={state:`none`,agent:t.agent,reason:n===`limit`?`lookup-limit`:n===`ambiguous`?`ambiguous`:`no-history`}):f()}else f();p&&(o&&(t.unsettled=0),t.due=d,this.set(t,p)&&this.notify())}async within(e,t){let n=new AbortController,r=setTimeout(()=>n.abort(),5e3),i=()=>n.abort();e.addEventListener(`abort`,i,{once:!0});try{return await t(n.signal)}finally{clearTimeout(r),e.removeEventListener(`abort`,i)}}newId(){let e=this.options.newId?.()??O(Oe(16));if(e.length<1||e.length>32)throw TypeError(`Invalid chat id`);return e}};const Ki=1e3,qi=5e3;var Ji=class{options;closed=!1;ended=!1;follower=null;operation=!1;epoch={};due=0;checkingShown=!1;generation=null;revision=0;appliedHistory=`complete`;applied=[];branch=null;projection=[];projectionClipped=!1;snapshot=null;snapshotCurrent=!1;discontinuity=0;pending=null;cursor=null;history=null;lastHistory=null;lastHistoryResult=null;clear=null;afterClear=null;controls=[];authorizedUntil=0;caughtUp=!1;reportedBusy=!1;queuedSent=null;retries=0;retrying=!1;replacingUntil=0;heldStatus=null;lastSourceAt;unlinkedHistory=!1;historicalBranch=new Map;constructor(e){if(!t.safeParse(e.subscriptionId).success)throw TypeError(`Invalid conversation subscription`);this.options={...e},this.lastSourceAt=e.now(),this.status(`checking`)}get sessionId(){return this.options.sessionId}get subscriptionId(){return this.options.subscriptionId}get needsWork(){return!this.closed&&!this.ended&&!this.operation&&!this.clear&&this.options.enabled()&&this.options.now()>=this.due}close(){this.closed||(this.closed=!0,this.discard(),this.clear=null,this.controls=[])}invalidate(e){this.closed||(this.ended||=e===`ended`,this.ended&&(e=`ended`),e===`changed`||e===`skipped`?this.generation&&(this.replacingUntil=this.options.now()+D.progressMs):(this.replacingUntil=0,this.heldStatus=null),this.discard(),this.controls=[],this.clear?.sent?this.clear.message.reason!==e&&(this.afterClear=e):this.clear={message:{type:`conversation.clear`,subscriptionId:this.subscriptionId,clearId:this.id(),reason:e},sent:!1,deadline:0},this.options.wake())}receive(e,t){if(!(this.closed||e.subscriptionId!==this.subscriptionId)){if(!Number.isSafeInteger(t)||t<1||t>D.envelopeBytes||!v.safeParse(e).success){this.invalidate(`unavailable`);return}if(e.type===`conversation.cancel`){this.close();return}if(e.type===`conversation.cleared`){if(this.clear?.sent&&e.clearId===this.clear.message.clearId){this.clear=null;let e=this.afterClear;if(this.afterClear=null,e){this.invalidate(e);return}this.due=this.options.now(),this.replacingUntil&&=this.options.now()+D.progressMs,!this.options.enabled()&&!this.ended&&this.status(`disabled`)}return}if(e.type===`conversation.refresh`){this.clear?(this.clear.deadline=0,this.options.wake()):this.ended||this.invalidate(this.options.enabled()?`changed`:`disabled`);return}if(this.options.enabled()&&!this.clear){if(e.type===`conversation.applied`){this.appliedBatch(e);return}if(e.type===`conversation.history.get`){if(e.generation!==this.generation||this.history?.requestId===e.requestId)return;if(this.history){this.endHistory(e,`busy`);return}if(e.requestId===this.lastHistory&&this.lastHistoryResult?.requestId===e.requestId){this.queueControl(this.lastHistoryResult);return}if(e.requestId===this.lastHistory||e.cursor!==this.cursor?.id){this.endHistory(e,`changed`);return}this.history={...e},this.due=this.options.now()}}}}async work(){if(!this.needsWork)return;this.operation=!0;let e=this.epoch,t=()=>!this.closed&&this.epoch===e&&this.options.enabled()&&!this.clear;try{if(!this.follower){this.follower=this.options.follow();let e=this.follower;e?.onChange?.(()=>{this.closed||this.follower!==e||(this.due=Math.min(this.due,this.options.now()),this.options.due?.())})}if(!this.follower){this.status(`checking`,`busy`),this.due=this.options.now()+1e3;return}let e=this.follower;if(this.pending?.sent&&this.options.now()<this.pending.deadline){this.due=this.pending.deadline;return}if(this.pending&&!this.pending.sent&&this.options.now()<=this.authorizedUntil){this.due=this.authorizedUntil+1,this.options.wake();return}if(this.snapshotCurrent&&this.snapshot&&this.history&&!this.pending&&this.cursor?.anchor&&e.older&&this.applied[0]?.local===this.cursor.local&&this.projection.findIndex(e=>e.local===this.cursor.local)<=0){let n=await e.older(this.cursor.anchor);if(!t()||this.follower!==e)return;if(this.due=this.options.now()+200,n.status===`stopped`)this.stopped(n.reason);else if(n.status===`refresh`)this.snapshotCurrent=!1;else if(n.status===`busy`)this.waitingForSource();else if(n.status===`reading`)this.waitingForSource(),this.due=this.options.now();else if(n.status===`unavailable`)this.finishHistory(`unavailable`);else if(n.status===`page`){let e=n.branch?.kind===`claude`?n.branch.nodes:[],t=[this.historicalBranch,new Map(this.branch?.kind===`claude`?this.branch.nodes.map(e=>[e.id,e.start]):[]),new Map(this.snapshot.branch?.kind===`claude`?this.snapshot.branch.nodes.map(e=>[e.id,e.start]):[])];if(e.some(e=>t.some(t=>t.has(e.id)&&t.get(e.id)!==e.start))){this.invalidate(`changed`);return}if(new Set([...this.historicalBranch.keys(),...e.map(e=>e.id)]).size>4096){this.finishHistory(`unavailable`);return}if(this.unlinkedHistory||=n.history===`unlinked`,this.lastSourceAt=this.options.now(),this.authorizedUntil=this.options.now()+200,this.caughtUp=!1,!n.entries.length)this.finishHistory(n.history===`complete`&&!this.unlinkedHistory?`complete`:`unavailable`);else{let t=new Map([...this.applied,...this.projection].map(e=>[e.local,e.id])),r=n.entries.map(({entry:e,anchor:n})=>{let r=t.get(e.id)??this.id(),i=Object.freeze({...e,id:r}),a=k(i),o=R(`sha256`).update(a).digest(`base64url`);return a.fill(0),{local:e.id,id:r,hash:o,entry:i,anchor:n}}),i=this.history,a=this.applied[0],o=this.page(r,`prepend`,a.id,i.requestId);o.length?this.queue(`prepend`,o,this.applied,a.id,i.requestId,void 0,[],{history:this.unlinkedHistory?`unlinked`:n.history,more:o.length<r.length||(n.more??n.history!==`complete`),ancestors:e}):this.finishHistory(`unavailable`)}this.options.wake()}return}if(this.snapshotCurrent&&this.snapshot&&(this.pending||this.history||this.hasUpdate())){let n=await e.confirm(this.snapshot.revision);if(!t()||this.follower!==e)return;if(n.status===`confirmed`){this.lastSourceAt=this.options.now(),this.caughtUp=n.caughtUp,this.authorizedUntil=this.options.now()+200,this.recovered(),this.prepare(),this.due=this.options.now(),this.options.wake();return}if(n.status===`stopped`){this.stopped(n.reason);return}if(n.status===`busy`){this.waitingForSource();return}this.pending?.sent?this.invalidate(`changed`):(this.pending=null,this.snapshotCurrent=!1,this.due=this.options.now()+200);return}if(this.snapshotCurrent&&this.snapshot&&!this.pending&&!this.history&&!this.reportedBusy&&e.idle){let n=await e.idle();if(!t()||this.follower!==e)return;if(n){this.lastSourceAt=this.options.now(),this.due=this.options.now()+Ki;return}}let n=await e.poll();if(!t()||this.follower!==e)return;this.accept(n)}catch{t()&&this.invalidate(`unavailable`)}finally{this.operation=!1}}offer(){if(this.closed)return!1;let e=this.options.now();if(this.clear){let t=this.clear;if(t.sent&&e<t.deadline)return!1;let n=this.send(t.message);return this.clear===t&&n&&(t.sent=!0,t.deadline=e+D.progressMs),n}let t=this.pending,n=()=>!!t&&this.options.enabled()&&e<=this.authorizedUntil&&!(t.sent&&e<t.deadline),r=this.controls.every(e=>e.type===`conversation.status`&&e.state===`ready`);if(this.controls.length&&!(r&&t&&!t.sent&&n())){let t=this.controls.find(e=>e.type===`conversation.history.end`)??this.controls[0];if(t.type===`conversation.status`&&t.state===`ready`&&(!this.options.enabled()||e>this.authorizedUntil))return!1;let n=this.send(t);return n&&(this.controls=this.controls.filter(e=>e!==t)),n}if(!t||!n())return!1;let i=this.send(t.batch);return this.pending===t&&i&&(t.sent=!0,t.deadline=e+D.progressMs,this.due=t.deadline),i}retry(){this.closed||this.ended||!this.retrying||(this.due=Math.min(this.due,this.options.now()),this.options.due?.())}tick(){this.closed||(this.replacingUntil&&this.options.now()>=this.replacingUntil&&this.endReplacing(),!this.options.enabled()&&(this.follower||this.generation||this.pending)&&this.invalidate(`disabled`),(this.clear&&this.options.now()>=this.clear.deadline||this.controls.length)&&this.options.wake())}accept(e){if(this.due=this.options.now()+200,e.status===`busy`){this.waitingForSource();return}if(e.status===`stopped`){this.stopped(e.reason);return}if(e.discontinuity!==this.discontinuity&&this.generation){this.invalidate(`skipped`);return}if(this.discontinuity=e.discontinuity,e.status===`catching-up`){this.snapshotCurrent=!1,this.generation?this.waitingForSource():(this.checkingShown||this.status(`checking`),this.checkingShown=!0),e.pending&&(this.due=this.options.now());return}this.lastSourceAt=this.options.now();let t=e.snapshot;if(t.state!==`ready`||!t.branch){this.generation?this.invalidate(`unavailable`):(this.status(`unavailable`,t.state===`unsupported`?`unsupported`:`unbound`),this.due=this.options.now()+qi);return}if(this.branch?.kind===`claude`){let e=this.branch.nodes.at(-1);if(t.branch.kind!==`claude`||!e||![...t.branch.nodes,...t.branch.parallel??[]].some(t=>t.id===e.id&&t.start===e.start)){let n=t.branch.kind===`claude`&&e&&t.history!==`complete`&&(t.branch.nodes[0]?.start??0)>e.start;this.invalidate(n?`skipped`:`changed`);return}let n=new Map(this.branch.nodes.map(e=>[e.id,e.start]));if(t.branch.nodes.some(e=>n.has(e.id)&&n.get(e.id)!==e.start||this.historicalBranch.has(e.id)&&this.historicalBranch.get(e.id)!==e.start)){this.invalidate(`changed`);return}}if(t.entries!==this.snapshot?.entries){let e=new Map([...this.applied,...this.projection].map(e=>[e.local,e.id])),n=[],r=0;this.projectionClipped=!1;for(let i=t.entries.length-1;i>=0;i--){let a=t.entries[i];if(a.id.startsWith(`history:`))continue;let o=e.get(a.id)??this.id(),s=Object.freeze({...a,id:o}),c=k(s);r+=c.byteLength;let l=R(`sha256`).update(c).digest(`base64url`);if(c.fill(0),r>D.queuedBytes-D.batchBytes||n.length>=D.retainedEntries){this.projectionClipped=!0;break}n.push({local:a.id,id:o,hash:l,entry:s})}n.reverse();let i=this.follower?.anchor;if(this.projectionClipped&&i){let e=n.findIndex(e=>i.call(this.follower,t.revision,e.local)!==null);e>0&&n.splice(0,e)}this.projection=n}this.snapshot=this.projectionClipped?{...t,history:`truncated`}:t,this.snapshotCurrent=!0,this.caughtUp=e.caughtUp,this.generation||=this.id(),this.retries=0,this.retrying=!1,this.recovered(),this.hasUpdate()||this.history?(this.authorizedUntil=this.options.now()+200,this.prepare(),this.due=this.options.now(),this.options.wake()):(this.authorizedUntil=0,this.due=this.options.now()+Ki)}recovered(){this.reportedBusy&&(this.reportedBusy=!1,this.queueControl(this.readyStatus()))}waitingForSource(){this.due=this.options.now()+200,this.options.now()-this.lastSourceAt>=D.progressMs&&(this.status(`checking`,`busy`),this.reportedBusy=this.generation!==null)}hasUpdate(){return!this.generation||this.revision===0||this.controls.some(e=>e.type===`conversation.status`&&e.state===`ready`)||this.queuedKey()!==this.queuedSent?!0:this.update()!==null}queuedKey(e=this.options.chat?.known()){return JSON.stringify([this.snapshot?.queued??[],e??null])}readyStatus(){let e=this.options.chat?.adopt();this.queuedSent=this.queuedKey(e);let t={type:`conversation.status`,subscriptionId:this.subscriptionId,state:`ready`,caughtUp:this.caughtUp},n=(this.snapshot?.queued??[]).map(e=>({...e}));return{...t,...n.length?{queued:n}:{},...e!==void 0&&{chat:e}}}update(){if(!this.applied.length)return this.projection.length?{at:0,rows:this.projection,after:0}:null;let e=new Map(this.applied.map((e,t)=>[e.local,t])),t=this.projection.findIndex(t=>e.has(t.local));if(t<0)return{at:-1,rows:[],after:0,reset:`skipped`};let n=e.get(this.projection[t].local);if(this.appliedHistory===`complete`){if(this.snapshot?.history===`complete`&&(t>0||n>0))return{at:0,rows:this.projection.slice(0,t),after:n};if(t>0)return{at:n,rows:this.projection.slice(0,t),after:n}}for(;t<this.projection.length&&n<this.applied.length&&this.projection[t].local===this.applied[n].local&&this.projection[t].hash===this.applied[n].hash;)t++,n++;if(t===this.projection.length)return n===this.applied.length?null:{at:n,rows:[],after:this.applied.length};let r=this.projection[t];if(this.applied[n]?.local===r.local)return{at:n,rows:[r],after:n+1};let i=e.get(r.local);if(i!==void 0)return i>n?{at:n,rows:[],after:i}:{at:-1,rows:[],after:0,reset:`changed`};let a=t;for(;a<this.projection.length&&!e.has(this.projection[a].local);)a++;return{at:n,rows:this.projection.slice(t,a),after:n}}prepare(){if(this.pending||!this.snapshot?.branch||!this.generation)return;if(this.controls.some(e=>e.type===`conversation.status`&&e.state===`ready`)&&this.queueControl(this.readyStatus()),this.history){let e=this.history,t=this.applied[0],n=this.projection.findIndex(e=>e.local===t?.local);if(!t||n<0||t.local!==this.cursor?.local){this.finishHistory(`changed`);return}if(n===0){this.finishHistory(this.snapshot.history===`complete`?`complete`:`unavailable`);return}let r=this.page(this.projection.slice(0,n),`prepend`,t.id,e.requestId);this.queue(`prepend`,r,this.applied,t.id,e.requestId);return}if(this.revision===0){this.queue(`reset`,this.page(this.projection,`reset`),[]);return}let e=this.update();if(!e){this.branch=this.snapshot.branch,this.queuedKey()!==this.queuedSent&&this.queueControl(this.readyStatus());return}if(e.at<0){this.invalidate(e.reset??`changed`);return}let t=this.applied[e.at-1]?.id??null,n=this.applied[e.after]?.id??null;this.queue(`patch`,this.page(e.rows,`patch`,t,void 0,n),this.applied.slice(0,e.at),t,void 0,n,this.applied.slice(e.after))}page(e,t,n,r,i){let a=[],o=t!==`patch`;for(let s=0;s<Math.min(e.length,D.entriesPerBatch);s++){let c=e[o?e.length-s-1:s],l=o?[c,...a]:[...a,c],u=this.message(t,l,n,r,`0`.repeat(22),i);if(k(u).byteLength>D.batchBytes)break;a.splice(0,a.length,...l)}return a}message(e,t,n,r,i=null,a){return{type:`conversation.batch`,subscriptionId:this.subscriptionId,generation:this.generation,batchId:`0`.repeat(22),baseRevision:this.revision,revision:this.revision+1,operation:e,...e!==`reset`&&{anchor:n??null},...r&&{requestId:r},...a!==void 0&&{after:a},entries:t.map(e=>e.entry),...e!==`patch`&&{olderCursor:i,history:i?`unloaded`:this.snapshot.history}}}queue(e,t,n,r,i,a,o=[],s){let c=t.map(({local:e,id:t,hash:n})=>({local:e,id:t,hash:n})),l=e===`prepend`?[...c,...n]:[...n,...c,...o];if(new Set(l.map(e=>e.local)).size!==l.length){e===`prepend`?this.finishHistory(`changed`):this.invalidate(`changed`);return}let u=this.projection.findIndex(e=>e.local===l[0]?.local),d=l[0],f=d?.local===`unlinked-side`?l[1]:d,p=f?t.find(e=>e.local===f.local)?.anchor??this.follower?.anchor?.(this.snapshot.revision,f.local)??null:null,m=s?s.more:u>0||this.snapshot.history!==`complete`,h=e===`patch`?void 0:d&&m&&(u>0||p)?{id:this.id(),local:d.local,anchor:p}:null,g={...this.message(e,t,r,i,h?.id,a),batchId:this.id(),...s&&{history:s.history===`unlinked`?`unlinked`:h||s.more?`unloaded`:s.history}};if(!je.safeParse(g).success){this.invalidate(`unavailable`);return}e===`reset`&&this.endReplacing(),this.pending={batch:g,proposed:l,branch:this.snapshot.branch,cursor:h,sent:!1,deadline:0,...s?.ancestors&&{ancestors:s.ancestors}},this.queueControl(this.readyStatus())}appliedBatch(e){let t=this.pending;if(!t?.sent||e.generation!==this.generation||e.batchId!==t.batch.batchId||e.revision!==t.batch.revision)return;let n=e.retainedCount===0?t.proposed.length:t.proposed.findIndex(t=>t.id===e.oldestId);if(n<0||t.proposed.length-n!==e.retainedCount||(t.proposed.at(-1)?.id??null)!==e.newestId){this.invalidate(`unavailable`);return}this.applied=t.proposed.slice(n);for(let e of t.ancestors??[])this.historicalBranch.set(e.id,e.start);this.branch=t.branch,this.revision=e.revision,t.batch.history!==void 0&&(this.appliedHistory=t.batch.history),n>0&&(this.appliedHistory=`unloaded`),t.cursor!==void 0&&(this.cursor=t.cursor),this.applied[0]?.local!==this.cursor?.local&&(this.cursor=null),t.batch.operation===`prepend`&&(this.lastHistory=t.batch.requestId,this.lastHistoryResult=null,this.history=null),this.pending=null,this.due=this.options.now()}finishHistory(e){this.follower?.cancelOlder?.(),e===`complete`?(this.appliedHistory=`complete`,this.cursor=null):e===`changed`&&(this.cursor=null);let t=this.history;this.history=null,this.lastHistory=t.requestId,this.endHistory(t,e),this.lastHistoryResult={type:`conversation.history.end`,subscriptionId:this.subscriptionId,generation:t.generation,requestId:t.requestId,reason:e}}endHistory(e,t){this.queueControl({type:`conversation.history.end`,subscriptionId:this.subscriptionId,generation:e.generation,requestId:e.requestId,reason:t})}stopped(e){this.generation?this.invalidate(e===`disabled`?`disabled`:e===`changed`?`changed`:`unavailable`):(this.discard(),this.status(e===`disabled`?`disabled`:`unavailable`,e===`unbound`?`unbound`:e===`unsupported`?`unsupported`:`source`),e===`unsupported`?this.due=1/0:(this.retrying=!0,this.due=this.options.now()+Math.min(qi,250*2**Math.min(this.retries++,5))))}status(e,t){let n={type:`conversation.status`,subscriptionId:this.subscriptionId,state:e,...t&&{reason:t}};if(e!==`disabled`&&this.replacingUntil>this.options.now()){this.heldStatus=n;return}this.queueControl(n)}endReplacing(){this.replacingUntil=0;let e=this.heldStatus;this.heldStatus=null,e&&!this.generation&&this.queueControl(e)}queueControl(e){if(e.type===`conversation.status`)this.controls=this.controls.filter(e=>e.type!==`conversation.status`);else if(e.type===`conversation.history.end`&&this.controls.some(t=>t.type===`conversation.history.end`&&t.generation===e.generation&&t.requestId===e.requestId))return;this.controls.length>=4&&(this.controls=this.controls.filter(e=>e.type!==`conversation.status`)),this.controls.length<4&&this.controls.push(e),this.options.wake()}discard(){this.checkingShown=!1,this.queuedSent=null,this.reportedBusy=!1,this.epoch={},this.follower?.close(),this.follower=null,this.generation=null,this.revision=0,this.appliedHistory=`complete`,this.applied=[],this.branch=null,this.projection=[],this.projectionClipped=!1,this.snapshot=null,this.snapshotCurrent=!1,this.pending=null,this.cursor=null,this.history=null,this.lastHistory=null,this.lastHistoryResult=null,this.authorizedUntil=0,this.discontinuity=0,this.unlinkedHistory=!1,this.historicalBranch.clear()}id(){let e=this.options.newId();if(!t.safeParse(e).success)throw TypeError(`Invalid conversation ID`);return e}send(e){try{let t=this.options.send(e);return t!==!0&&t!==!1?(Promise.resolve(t).catch(()=>{}),!1):t}catch{return!1}}};const Yi=65536;function Xi(e,t){return!!t&&e.agent===t.agent&&e.path===t.path&&e.session===t.session&&e.owner===t.owner&&(e.reference===t.reference||!!e.reference&&!!t.reference&&On(e.reference,t.reference)&&e.reference.owner===t.reference.owner)}function Zi(e,t){return e.dev===t.dev&&e.ino===t.ino}function Qi(e){return F(e)&&e.length<=4096&&!Array.from(e).some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)===127)}function $i(e,t){let n=Sr(e,t);return n!==``&&n!==`..`&&!n.startsWith(`..${Cr}`)&&!F(n)}function ea(e){return e.isFile()&&!e.isSymbolicLink()&&Number.isSafeInteger(e.size)&&e.size>=0&&(process.getuid===void 0||e.uid===process.getuid())}function ta(e){if(e.fd===-1)return Promise.resolve();let t=e;return new Promise(n=>{let r=!1,i=()=>{r&&e.fd===-1&&(t.removeListener(`close`,i),n())},a=()=>{r=!0,i()};t.once(`close`,i);try{e.close().then(a,a)}catch{a()}})}var na=class e{options;path;file;identity;controller=new AbortController;reason=null;reading=!1;opening=!0;closeFinished=!1;finishClosed;closed=new Promise(e=>{this.finishClosed=e});fences=[];observed;onAbort=()=>{this.stop(`cancelled`)};constructor(e,t,n,r,i){this.options=e,this.path=n,this.file=r,this.identity=Object.freeze({...t}),this.observed=i,e.signal?.addEventListener(`abort`,this.onAbort,{once:!0}),e.signal?.aborted&&this.stop(`cancelled`)}static async open(t){let n,r;try{if(t.signal?.aborted)return{status:`stopped`,reason:`cancelled`};if(!t.enabled())return{status:`stopped`,reason:`disabled`};let i=await ra(t,t.signal);if(!i)return{status:`stopped`,reason:t.signal?.aborted?`cancelled`:`unbound`};let a={...i};if(![`claude`,`codex`,`gemini`].includes(a.agent)||!Qi(a.path)||!a.path.endsWith(`.jsonl`)||!/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,255}$/.test(a.session)||!a.owner||a.owner.length>1024)return{status:`stopped`,reason:`unsafe`};let o=t.roots[a.agent];if(!o?.length||o.length>8)return{status:`stopped`,reason:`unsafe`};let s=await B(a.path),c=!1;for(let e of o)if(Qi(e))try{$i(await B(e),s)&&(c=!0)}catch{}if(!c)return{status:`stopped`,reason:`unsafe`};let l=await z(a.path);if(!ea(l))return{status:`stopped`,reason:`unsafe`};n=await Lr(s,ir.O_RDONLY|ir.O_NOFOLLOW|ir.O_NONBLOCK);let u=await n.stat();if(!ea(u)||!Zi(l,u))return{status:`stopped`,reason:`changed`};r=new e(t,a,s,n,u);let d=await r.validate();if(d)return{status:`stopped`,reason:d};if(!r.installFences(await r.captureFences(u.size)))return{status:`stopped`,reason:r.stopped};let f=await r.validate()??r.availability();return f?{status:`stopped`,reason:f}:(n=void 0,{status:`open`,file:r})}catch{return{status:`stopped`,reason:t.signal?.aborted?`cancelled`:`unreadable`}}finally{r?(n&&r.stop(`unreadable`),r.opening=!1,r.finishClosing(),n&&await r.closed):n&&await ta(n)}}get stopped(){return this.reason}get size(){return this.observed.size}async read(e,t=Yi){if(this.reason)return{status:`stopped`,reason:this.reason};if(this.reading)return{status:`busy`};if(!Number.isSafeInteger(e)||e<0||!Number.isSafeInteger(t)||t<1||t>65536)return this.stop(`unsafe`),{status:`stopped`,reason:`unsafe`};this.reading=!0;let n,r;try{let i=await this.file.stat();if(this.reason)return this.stoppedRead(this.reason);if(!ea(i)||!Zi(i,this.observed)||i.size<this.observed.size)return this.stoppedRead(`changed`);let a=i.size;if(e>a)return this.stoppedRead(`unsafe`);n=Buffer.alloc(Math.min(t,a-e));let{bytesRead:o}=await this.file.read(n,0,n.length,e);if(o!==n.length)return this.stoppedRead(`changed`);r=await this.captureFences(a);let s=await this.validate(r);if(s)return this.stoppedRead(s);if(this.observed.size<a)return this.stoppedRead(`changed`);if(!this.installFences(r))return this.stoppedRead(this.reason);r=void 0;let c=n;return n=void 0,{status:`data`,bytes:c,offset:e,size:a}}catch{return this.stoppedRead(this.reason??`unreadable`)}finally{n?.fill(0);for(let e of r??[])e.bytes.fill(0);this.reading=!1,this.finishClosing()}}async verify(){if(this.reason)return{status:`stopped`,reason:this.reason};if(this.reading)return{status:`busy`};this.reading=!0;try{let e=await this.validate()??this.availability();return e?(this.stop(e),{status:`stopped`,reason:this.reason}):{status:`verified`,size:this.observed.size}}catch{return this.stop(this.reason??`unreadable`),{status:`stopped`,reason:this.reason}}finally{this.reading=!1,this.finishClosing()}}async unchanged(){if(this.reason||this.reading)return!1;try{let e=await z(this.path),t=this.observed;return!this.reason&&e.dev===t.dev&&e.ino===t.ino&&e.size===t.size&&e.mtimeMs===t.mtimeMs&&e.ctimeMs===t.ctimeMs}catch{return!1}}get watchPath(){return this.path}close(){this.stop(`cancelled`)}stoppedRead(e){return this.stop(e),{status:`stopped`,reason:this.reason}}stop(e){if(!this.reason){this.reason=e,this.controller.abort(),this.options.signal?.removeEventListener(`abort`,this.onAbort);for(let e of this.fences)e.bytes.fill(0);this.fences=[],ta(this.file).then(()=>{this.closeFinished=!0,this.finishClosing()})}}finishClosing(){this.reason&&this.closeFinished&&!this.opening&&!this.reading&&this.finishClosed()}async validate(e=[]){if(this.reason)return this.reason;if(!this.options.enabled())return`disabled`;let t=await ra(this.options,this.controller.signal);if(this.reason)return this.reason;if(!this.options.enabled())return`disabled`;if(!t)return`unbound`;if(!Xi(this.identity,t)||await B(this.identity.path)!==this.path)return`changed`;let[n,r]=await Promise.all([z(this.path),this.file.stat()]);if(!ea(n)||!Zi(n,r)||!Zi(r,this.observed)||r.size<this.observed.size||r.size===this.observed.size&&r.mtimeMs!==this.observed.mtimeMs)return`changed`;for(let t of[...this.fences,...e]){let e=Buffer.alloc(t.bytes.length);try{if((await this.file.read(e,0,e.length,t.offset)).bytesRead!==e.length||!e.equals(t.bytes))return`changed`}finally{e.fill(0)}}return this.reason?this.reason:this.options.enabled()?(this.observed=r,null):`disabled`}availability(){let e=this.options.enabled();return this.reason??(e?null:`disabled`)}installFences(e){let t=this.availability();if(t){for(let t of e)t.bytes.fill(0);return this.stop(t),!1}for(let e of this.fences)e.bytes.fill(0);return this.fences=e,!0}async captureFences(e){let t=Math.min(4096,e),n=[];try{for(let r of t===e?[0]:[0,e-t]){let e=Buffer.alloc(t);if(n.push({offset:r,bytes:e}),(await this.file.read(e,0,e.length,r)).bytesRead!==e.length||this.reason)throw Error(`invalidated`)}return n}catch(e){for(let e of n)e.bytes.fill(0);throw e}}};async function ra(e,t){if(t?.aborted||!e.enabled())return null;let n=new AbortController,r=()=>n.abort();t?.addEventListener(`abort`,r,{once:!0});let i;try{let t=new Promise(e=>{n.signal.addEventListener(`abort`,()=>e(null),{once:!0}),i=setTimeout(r,2e3)}),a=await Promise.race([e.identity(n.signal),t]);return a?{...a}:null}catch{return null}finally{clearTimeout(i),t?.removeEventListener(`abort`,r),n.abort()}}const ia=16384,aa=ia,oa=aa*6,sa=/["\\\u0000-\u001f]/g,ca=/^(?:true|false|null|-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)$/;var la=class{outline;decoder=new TextDecoder(`utf-8`,{fatal:!0});stack=[];mode=`value`;root;rooted=!1;failed=null;budget=131072;shortBudget=65536;recordBudget=16384;keyString=!1;keep=null;raw=``;length=0;escape=0;literal=``;constructor(e){this.outline=e}push(e){if(this.failed)return;let t;try{t=this.decoder.decode(e,{stream:!0})}catch{this.failed=`invalid-utf8`;return}this.scan(t)}finish(){if(!this.failed){let e;try{e=this.decoder.decode()}catch{this.failed=`invalid-utf8`,e=``}this.scan(e),this.mode===`literal`&&this.endLiteral()}let e=this.root;return this.root=void 0,this.raw=``,this.failed?{kind:`skipped`,reason:this.failed}:!this.rooted&&this.mode===`value`?null:this.stack.length||this.mode!==`after`||typeof e!=`object`||!e||Array.isArray(e)?{kind:`skipped`,reason:`invalid-json`}:{kind:`record`,value:e}}fail(){this.failed=`invalid-json`}scan(e){let t=0;for(;t<e.length&&!this.failed;){if(this.mode===`string`){t=this.string(e,t);continue}let n=e.charCodeAt(t);if(this.mode===`literal`){if(/[0-9a-zA-Z+.-]/.test(e[t])){this.literal+=e[t],this.literal.length>512&&this.fail(),t++;continue}if(this.endLiteral(),this.failed)break}if(t++,n===32||n===9||n===10||n===13)continue;let r=this.stack.at(-1);if(this.mode===`first-item`&&n===93){this.close();continue}switch(this.mode){case`first-item`:case`value`:n===123?this.open(!1):n===91?this.open(!0):n===34?this.beginString(!1):/[-0-9tfn]/.test(e[t-1])?(this.keep=this.slot(),this.literal=e[t-1],this.mode=`literal`):this.fail();break;case`first-key`:n===125?this.close():n===34?this.beginString(!0):this.fail();break;case`key`:n===34?this.beginString(!0):this.fail();break;case`colon`:n===58?this.mode=`value`:this.fail();break;case`after`:r?n===44?this.mode=r.array?`value`:`key`:n===(r.array?93:125)?this.close():this.fail():this.fail()}}}slot(){let e=this.stack.at(-1);return e?e.array?e.shape?.items&&e.count<65?e.shape.items:null:e.child:this.outline}open(e){if(this.stack.length>=512){this.fail();return}let t=this.slot();this.stack.push({array:e,value:t?e?[]:{}:null,shape:t,child:null,key:null,count:0}),this.mode=e?`first-item`:`first-key`}close(){let e=this.stack.pop();this.place(e.value,e.value!==null)}place(e,t){let n=this.stack.at(-1);this.mode=`after`,n?n.array?(t&&n.value.push(e),n.count++):t&&n.key!==null&&(n.value[n.key]=e):(this.root=e,this.rooted=!0)}beginString(e){this.keyString=e,this.keep=e?null:this.slot(),this.raw=``,this.length=0,this.escape=0,this.mode=`string`}append(e){this.length+=e.length,(this.keyString||this.keep)&&(this.length<=(this.keyString?256:oa)?this.raw+=e:this.raw=``)}string(e,t){let n=t;for(;n<e.length;){if(this.escape===1){let t=e[n];if(t===`u`)this.escape=2;else if(`"\\/bfnrt`.includes(t))this.escape=0;else return this.fail(),n;this.append(t),n++;continue}if(this.escape>=2){if(!/[0-9a-fA-F]/.test(e[n]))return this.fail(),n;this.escape=this.escape===5?0:this.escape+1,this.append(e[n]),n++;continue}sa.lastIndex=n;let t=sa.exec(e),r=t?t.index:e.length;if(r>n&&this.append(e.slice(n,r)),n=r,!t)break;let i=e.charCodeAt(n);if(i===34)return this.endString(),n+1;if(i!==92)return this.fail(),n;this.append(`\\`),this.escape=1,n++}return n}endString(){let e=this.stack.at(-1),t=this.length>(this.keyString?256:oa)||!this.keyString&&!this.keep?null:JSON.parse(`"${this.raw}"`),n=t!==null&&(this.keyString||t.length<=aa)?t:null;if(this.raw=``,this.keyString){let t=e.shape?.keys;e.key=n,e.child=n!==null&&t&&Object.hasOwn(t,n)?t[n]:null,this.mode=`colon`;return}if(!this.keep){this.place(void 0,!1);return}let r=this.stack.length===1&&n!==null&&n.length<=1024&&n.length<=this.recordBudget,i=!r&&n!==null&&n.length<=256&&n.length<=this.shortBudget,a=r||i||n!==null&&n.length<=this.budget;r?this.recordBudget-=n.length:i?this.shortBudget-=n.length:a&&(this.budget-=n.length),this.place(a?n:`Too large to show here`,!0)}endLiteral(){if(!ca.test(this.literal)){this.fail();return}this.place(this.keep?JSON.parse(this.literal):void 0,this.keep!==null),this.literal=``}},ua=class{outline;buffer=null;length=0;skipped;outlining=null;closed=!1;next;start;decoder=new TextDecoder(`utf-8`,{fatal:!0});constructor(e=0,t=!1,n=null){if(this.outline=n,!Number.isSafeInteger(e)||e<0)throw RangeError(`Invalid transcript cursor`);this.next=e,this.start=e,this.skipped=t?`partial-prefix`:null}get offset(){return this.next}get boundary(){return this.skipped===`partial-prefix`?null:this.start}get bufferedBytes(){return this.length}push(e,t=this.next){if(this.closed)throw Error(`Transcript decoder is closed`);if(t!==this.next||e.byteLength>65536||!Number.isSafeInteger(this.next+e.byteLength))throw this.close(),RangeError(`Invalid transcript window`);let n=Buffer.from(e.buffer,e.byteOffset,e.byteLength),r=[],i=0,a=0;for(;i<n.length&&a<64;){let e=n.indexOf(10,i),t=e===-1?n.length:e,o=t-i;this.outlining?this.outlining.push(n.subarray(i,t)):this.skipped||(this.length+o>131072?(this.outline?(this.outlining=new la(this.outline),this.length&&this.outlining.push(this.buffer.subarray(0,this.length)),this.outlining.push(n.subarray(i,t))):this.skipped=`line-too-large`,this.clearBuffer()):o&&(this.buffer??=Buffer.alloc(131072),n.copy(this.buffer,this.length,i,t),this.length+=o));let s=o+(e===-1?0:1);if(i+=s,this.next+=s,e!==-1){let e=this.finishLine();e&&r.push(e),this.clearBuffer(),this.skipped=null,this.outlining=null,this.start=this.next,a++}}return{consumed:i,lines:r}}close(){this.clearBuffer(),this.buffer=null,this.skipped=null,this.outlining=null,this.closed=!0}finishLine(){let e={start:this.start,end:this.next};if(this.skipped)return{...e,kind:`skipped`,reason:this.skipped};if(this.outlining){let t=this.outlining.finish();return t?t.kind===`record`?{...e,kind:`record`,value:t.value,outlined:!0}:{...e,...t}:null}if(!this.length)return null;let t;try{t=this.decoder.decode(this.buffer.subarray(0,this.length))}catch{return{...e,kind:`skipped`,reason:`invalid-utf8`}}if(/^[ \t\r\n]*$/.test(t))return null;try{let n=JSON.parse(t);if(typeof n==`object`&&n&&!Array.isArray(n))return{...e,kind:`record`,value:n}}catch{}return{...e,kind:`skipped`,reason:`invalid-json`}}clearBuffer(){this.buffer?.fill(0,0,this.length),this.length=0}};const da=`Earlier content is not loaded`,fa=ia,pa=8192,ma=new Set([`progress`,`system`,`attachment`,`file-history-snapshot`,`queue-operation`,`summary`,`custom-title`,`tag`,`last-prompt`,`ai-title`,`agent-name`,`agent-setting`,`mode`,`permission-mode`,`atis-latch`,`cost-state`,`pr-link`,`continued-in`,`file-history-delta`,`api-request`,`api-request-blob`,`api-request-shape`]),ha=new Set([`token_count`,`agent_message`,`agent_reasoning`,`agent_reasoning_raw_content`,`thread_settings_applied`,`thread_goal_updated`,`context_compacted`,`patch_apply_end`,`mcp_tool_call_end`,`web_search_end`,`image_generation_end`,`item_completed`]),ga=new Set([`reasoning`,`additional_tools`,`configuration_update`,`compaction`,`context_compaction`]),_a={task_started:`Working`,turn_started:`Working`,task_complete:`Complete`,turn_complete:`Complete`,turn_aborted:`Stopped`,error:`Agent reported an error`},va=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,ya=/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,255}$/,ba=[`enqueue`,`dequeue`,`remove`,`popAll`];function xa(e){let t=ba.find(t=>t===e.operation);if(!t)return null;let n=e.content,r=``,i=!1;if(typeof n==`string`)r=n;else if(Array.isArray(n))for(let e of n.slice(0,64)){let t=U(e);t?.type===`text`&&typeof t.text==`string`?r+=t.text:t&&(i=!0)}else if(n!=null)return null;let a=Array.from(r.trim()).slice(0,D.queuedChars).join(``);return Object.freeze({operation:t,...n!=null&&{content:R(`sha256`).update(typeof n==`string`?n:JSON.stringify(n)).digest(`base64url`)},...a&&{text:a},...i&&{attachment:!0}})}function U(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:null}function W(e){return typeof e==`string`&&e.trim()===e&&ya.test(e)?e:null}function Sa(e){return typeof e==`string`&&e.length===36&&va.test(e)?e.toLowerCase():null}function G(e,t){if(!Number.isSafeInteger(t)||t<0||t>fa)throw RangeError(`Invalid transcript text budget`);let n=``,r=0,i=0;for(let a of e){let e=a.codePointAt(0);if(i>=t*4)break;if(e<32&&e!==9&&e!==10||e>=127&&e<=159){i+=a.length;continue}let o=e>=55296&&e<=57343?`�`:a,s=Buffer.byteLength(o);if(r+s>t)break;n+=o,r+=s,i+=a.length}return{text:n,truncated:i<e.length}}var Ca=class{offset;outlined;items=[];bytes=2;clipped=!1;scopeStart=0;constructor(e,t=!1){this.offset=e,this.outlined=t}scope(e){this.offset=e,this.scopeStart=this.items.length}get full(){return this.items.length>=31||this.bytes>=65024}add(e,t,n,r=!1,i=!1){if(this.full){this.clipped=!0;return}let a=G(t,fa),o=n===void 0?void 0:G(n,pa);this.outlined&&(t.includes(`Too large to show here`)||n?.includes(`Too large to show here`))&&(i=!0);let s={id:`${this.offset}:${this.items.length-this.scopeStart}`,kind:e,text:a.text,...o&&{detail:o.text},...r&&{collapsed:!0},...(i||a.truncated||o?.truncated)&&{truncated:!0}},c=Buffer.byteLength(JSON.stringify(s))+1;if(c+this.bytes>65024){this.clipped=!0;return}return this.items.push(Object.freeze(s)),this.bytes+=c,s}unknown(){return this.add(`unsupported`,`(Something this version can't show)`)}finish(){return this.clipped&&this.items.push(Object.freeze({id:`${this.offset}:${this.items.length-this.scopeStart}`,kind:`status`,text:`Additional content omitted to keep this entry small.`,truncated:!0})),Object.freeze(this.items)}};function wa(e,t){return Array.isArray(e)?(e.length>64&&(t.clipped=!0),e.slice(0,64)):null}function Ta(e){return typeof e==`string`&&G(e,128).text||`Tool`}function Ea(e,t){let n=G(e,pa),r=n.text.trim().split(`
5
5
  `,1)[0].trim(),i=G(r,120),a=!i.truncated&&r===n.text&&!n.truncated;return{text:t?`${t}: ${n.text}`:n.text,clipped:n.truncated,...r&&{summary:a?i.text:`${i.text}…`},...a&&{complete:!0}}}const Da=[`command`,`cmd`,`file_path`,`path`,`pattern`,`query`,`url`,`description`,`prompt`];function Oa(e){if(typeof e==`string`)return Ea(e);let t=U(e);if(t)for(let e of Da){let n=t[e];if(typeof n==`string`)return Ea(n,e)}return{text:`Structured arguments omitted.`,clipped:!1}}function ka(e){if(e===`Too large to show here`)return{text:`Arguments too large to show here.`,clipped:!0};if(typeof e==`string`)try{let t=JSON.parse(e);if(U(t))return Oa(t)}catch{}return{text:`Structured arguments omitted.`,clipped:!1}}function Aa(e,t,n){let r=Ta(t);return e.add(`tool-call`,n.summary?`${r} · ${n.summary}`:r,n.complete?void 0:n.text,!0,n.clipped)}function ja(e,t){if(!Number.isSafeInteger(t)||t<0||t>fa)throw RangeError(`Invalid transcript text budget`);let n=[],r=0,i=0,a=e.length;for(;a>0&&i<t*4;){let o=e.charCodeAt(a-1),s=a>1?e.charCodeAt(a-2):0,c=o>=56320&&o<=57343&&s>=55296&&s<=56319?2:1,l=e.slice(a-c,a),u=l.codePointAt(0);if(!(u<32&&u!==9&&u!==10||u>=127&&u<=159)){let e=u>=55296&&u<=57343?`�`:l,i=Buffer.byteLength(e);if(r+i>t)break;n.push(e),r+=i}a-=c,i+=c}return{text:n.reverse().join(``),truncated:a>0}}function Ma(e,t=pa,n=!1){let r=e=>n?ja(e,t):G(e,t);if(typeof e==`string`){let t=r(e);return{text:t.text,clipped:t.truncated}}if(!Array.isArray(e))return null;let i=[],a=e.length>64;for(let t of e.slice(0,64)){let e=U(t);if(!e){a=!0;continue}i.push((e.type===`text`||e.type===`input_text`||e.type===`output_text`)&&typeof e.text==`string`?e.text:`[Non-text content omitted]`)}let o=r(i.join(`
@@ -35,19 +35,19 @@ import{$ as e,$n as t,$t as n,A as r,An as i,At as a,B as o,Bn as s,Bt as c,Ct a
35
35
  same Wi-Fi. Without it, your phone may not connect while it is on the same Wi-Fi.
36
36
  Change any answer later in System Settings → Privacy & Security.`)}return a.running?(t||await e.afterInstall?.(),0):2}catch(e){return Nl(e,t,n),2}}function Nl(e,t,n){let r=kl(e),i=e instanceof vt?{rollback:e.rollback,rollbackDiagnostic:e.rollbackDiagnostic,recoveryPath:e.recoveryPath}:{};t?n.log(JSON.stringify({error:r,...i})):(n.error(` ${r}`),i.rollback===`failed`&&n.error(` Shellbell couldn't put the previous setup back${i.rollbackDiagnostic?` (${i.rollbackDiagnostic})`:``}.${i.recoveryPath?` A copy of it is saved at ${i.recoveryPath}.`:``}`))}async function Pl(e,t,n,r){try{if(e.appOwned?.())return 2;let i=e.background(),a=await i.status();if(!a.installed){if(t)n.log(JSON.stringify(a));else if(r!==`start`&&await e.otherCopyRunning?.())n.log(` Shellbell is running in a terminal window, not in the background. Press Ctrl-C in that window to stop it.`);else if(r===`uninstall`||r===`stop`)n.log(` Shellbell doesn't run in the background on this computer.`);else for(let e of Al(a,i.system))n.log(` ${e}`);return r===`uninstall`||r===`stop`?0:2}let o=await i[r](),s=r===`uninstall`?!o.installed&&!o.startsAtLogin:r===`stop`!==o.running;if(t)n.log(JSON.stringify(o));else if(r===`uninstall`)n.log(s?" Shellbell no longer runs in the background. Your phones stay paired; run `shellbell install` to turn it back on.":` Shellbell's background setup is removed, but something else still starts it when you log in. ${o.service.diagnostic??``}`.trimEnd());else for(let e of Al(o,i.system))n.log(` ${e}`);return s?0:2}catch(e){return Nl(e,t,n),2}}const Fl=(e,t,n=jl)=>Pl(e,t,n,`start`);function Il(e,t){let n=()=>!!e.opts().json;e.command(`install`).description(`run Shellbell in the background, starting again whenever you log in`).action(async()=>{process.exitCode=await Ml(t,n())}),e.command(`uninstall`).description(`stop running Shellbell in the background; your phones stay paired`).action(async()=>{process.exitCode=await Pl(t,n(),jl,`uninstall`)}),e.command(`stop`).description(`stop Shellbell until you next log in or run start`).action(async()=>{process.exitCode=await Pl(t,n(),jl,`stop`)}),e.command(`restart`).description(`restart the background Shellbell, for example after config set`).action(async()=>{process.exitCode=await Pl(t,n(),jl,`restart`)})}function X(e=process.platform,t){if(e!==`linux`)return ot();let n=f(t);return l(n),n}function Ll(e,t={}){e.command(`host`,{hidden:!0}).description(`recover or move 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&&(!F(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 Sl((t.selectPaths??f)(),n.new?{kind:`new`}:{kind:`adopt`,source:n.adopt,confirmSourceInactive:!0},{...ht(),computerName:(t.hostname??_r)().replace(/\.local$/,``)||`Linux`}),i={status:e.status,next:`shellbell install`};console.log(r?JSON.stringify(i):` host state ${e.status}; run shellbell install to run Shellbell in the background`);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}`)})}function Rl(e){let t;try{t=ur(e,`r`);let n=Buffer.alloc(65536),r=pr(t,n,0,n.length,0),i=JSON.parse(n.subarray(0,r).toString(`utf8`)).version;return typeof i==`string`&&/^\d+\.\d+\.\d+/.test(i)?i:null}catch{return null}finally{t!==void 0&&rr(t)}}function zl(e=process.argv[1]??``){return I(P(P(e)),`package.json`)}function Bl(e){let t=e.now??Date.now,n=Rl(e.packageJson)??e.running,r=null,i=null,a=!1,o=setInterval(()=>{if(a)return;let o=Rl(e.packageJson),s=I(P(e.packageJson),`dist`,`cli.js`);if(!o||o===n||!ar(s)){r=null,i=null;return}if(o!==r){r=o,i=null;return}i??=t();let c=t()-i;e.busy()&&c<(e.graceMs??6e5)||(a=!0,e.log.info(`installed version changed; restarting`,{from:e.running,to:o}),e.restart(o))},e.intervalMs??6e4);return o.unref?.(),()=>{a=!0,clearInterval(o)}}const Vl=`https://github.com/bilal-/shellbell`,Hl=`https://api.github.com/repos/bilal-/shellbell`,Ul=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,Wl=L.string().max(32).regex(Ul),Gl=L.string().regex(/^[a-f0-9]{64}$/),Kl=L.string().regex(/^[a-f0-9]{40}$/),ql=L.object({asset:L.string().max(160),sha256:Gl}).strict(),Jl=ql.extend({buildNumber:L.number().int().positive().max(2147483647),minimumOS:L.string().regex(/^\d{1,3}\.\d{1,3}(?:\.\d{1,3})?$/),signed:L.literal(!0),notarized:L.literal(!0)}).strict(),Yl=ql.extend({minimumGlibc:L.string().regex(/^[0-9]{1,6}\.[0-9]{1,6}$/)}).strict(),Xl=L.object({schemaVersion:L.literal(1),component:L.literal(`computer`),channel:L.literal(`stable`),version:Wl,tag:L.string().max(64),sourceCommit:Kl,platforms:L.object({macosArm64:Jl.optional(),macosHeadless:ql.optional(),linuxArm64:Yl.optional(),linuxX64:Yl.optional()}).strict()}).strict(),Zl=L.object({tag_name:L.string(),draft:L.boolean(),prerelease:L.boolean(),assets:L.array(L.object({name:L.string(),digest:L.string().nullable(),size:L.number().int().nonnegative(),browser_download_url:L.string()})).max(100)});function Ql(e,t){Wl.parse(e),Wl.parse(t);let n=e.split(`.`).map(BigInt),r=t.split(`.`).map(BigInt);for(let e=0;e<3;e++){if(n[e]<r[e])return-1;if(n[e]>r[e])return 1}return 0}function $l(e,t){if(!e.startsWith(`shellbell@`)||!Ul.test(e.slice(10)))throw Error(`Invalid computer release tag`);if(!/^[A-Za-z0-9._-]+$/.test(t))throw Error(`Invalid release asset name`);return`${Vl}/releases/download/${encodeURIComponent(e)}/${t}`}var eu=class{request;constructor(e=fetch){this.request=e}async bytes(e,t,n){let r=await this.response(e,n),i=[],a=0;if(!r.body)throw Error(`Empty release response`);let o=r.body.getReader();try{for(;;){let{done:e,value:n}=await o.read();if(e)break;if(a+=n.length,a>t)throw Error(`Release response exceeds its size limit`);i.push(n)}}finally{await o.cancel()}return Buffer.concat(i,a)}async response(e,t){let n=new URL(e);if(!(n.origin===`https://api.github.com`&&n.pathname.startsWith(`/repos/bilal-/shellbell/`))&&!(n.origin===`https://github.com`&&n.pathname.startsWith(`/bilal-/shellbell/releases/download/`)))throw Error(`Untrusted release URL`);for(let e=0;e<=3;e++){if(n.protocol!==`https:`||n.port!==``||n.username||n.password||![`api.github.com`,`github.com`,`release-assets.githubusercontent.com`,`objects.githubusercontent.com`].includes(n.hostname))throw Error(`Untrusted release redirect`);let r=await this.request(n.href,{redirect:`manual`,signal:t,headers:{Accept:`application/vnd.github+json`,"User-Agent":`Shellbell-update-check`}});if([301,302,303,307,308].includes(r.status)){let t=r.headers.get(`location`);if(await r.body?.cancel(),!t||e===3)throw Error(`Invalid release redirect`);n=new URL(t,n);continue}if(!r.ok)throw await r.body?.cancel(),Error(r.status===403||r.status===429?`GitHub is limiting update checks. Try again later.`:`Update lookup failed (HTTP ${r.status})`);return r}throw Error(`Too many release redirects`)}async json(e,t){return JSON.parse(Buffer.from(await this.bytes(e,2097152,t)).toString(`utf8`))}async check(e,t){Wl.parse(e);let n=AbortSignal.timeout(3e4),r;if(t){if(Wl.parse(t),r=Zl.parse(await this.json(`${Hl}/releases/tags/${encodeURIComponent(`shellbell@${t}`)}`,n)),r.tag_name!==`shellbell@${t}`)throw Error(`Release tag mismatch`)}else{let e=[],t=!1;for(let r=1;r<=5;r++){let i=L.array(Zl).max(100).parse(await this.json(`${Hl}/releases?per_page=100&page=${r}`,n));if(e.push(...i.filter(e=>!e.draft&&!e.prerelease&&e.tag_name.startsWith(`shellbell@`)&&Ul.test(e.tag_name.slice(10)))),i.length<100){t=!0;break}}if(!t)throw Error(`Release history is too large; specify the computer version to check`);if(e.sort((e,t)=>Ql(t.tag_name.slice(10),e.tag_name.slice(10))),!e[0])throw Error(`No stable computer release is available`);r=e[0]}if(r.draft||r.prerelease)throw Error(`Only published stable computer releases can be installed`);let i=this.asset(r,`computer-release.json`,1048576),a=await this.bytes(i.browser_download_url,i.size,n);this.verify(a,i);let o=Xl.parse(JSON.parse(Buffer.from(a).toString(`utf8`)));if(o.tag!==r.tag_name||o.tag!==`shellbell@${o.version}`)throw Error(`Computer release metadata does not match its tag`);if(L.object({object:L.object({type:L.literal(`commit`),sha:Kl})}).parse(await this.json(`${Hl}/git/ref/tags/${encodeURIComponent(o.tag)}`,n)).object.sha!==o.sourceCommit)throw Error(`Computer release source does not match its tag`);let s={macosArm64:`Shellbell-${o.version}-arm64.dmg`,macosHeadless:`shellbell-${o.version}.tgz`,linuxArm64:`shellbell-${o.version}-linux-arm64.tar.gz`,linuxX64:`shellbell-${o.version}-linux-x64.tar.gz`},c={};for(let e of Object.keys(s)){let t=o.platforms[e];if(!t)continue;if(t.asset!==s[e])throw Error(`Unexpected computer release asset`);let n=this.asset(r,s[e],268435456);if(n.digest!==`sha256:${t.sha256}`)throw Error(`Computer artifact digest mismatch`);c[e]=n}if(!Object.keys(c).length)throw Error(`Computer release has no installable artifacts`);return{check:{schemaVersion:1,currentVersion:e,available:Ql(o.version,e)>0,releaseUrl:`${Vl}/releases/tag/${encodeURIComponent(o.tag)}`,release:o},assets:c}}asset(e,t,n){let r=e.assets.filter(e=>e.name===t),i=r[0];if(r.length!==1||!i||!i.digest||!/^sha256:[a-f0-9]{64}$/.test(i.digest)||i.size<1||i.size>n||i.browser_download_url!==$l(e.tag_name,t))throw Error(`Missing or invalid release asset: ${t}`);return{...i,digest:i.digest}}verify(e,t){if(e.byteLength!==t.size||`sha256:${R(`sha256`).update(e).digest(`hex`)}`!==t.digest)throw Error(`Downloaded artifact does not match the published digest`)}};const tu=Wr(tr);function nu(e){let t=e.stderr.split(`
37
37
  `).filter(e=>e.startsWith(`Shellbell staging directory: `));return[e.stdout.trim(),...t].filter(Boolean).join(`
38
- `)}function ru(e,t){let n=/^\d{1,3}\.\d{1,3}(?:\.\d{1,3})?$/;if(!n.test(e.trim())||!n.test(t))throw Error(`Could not verify the release's macOS requirement`);let r=e.trim().split(`.`).map(Number),i=t.split(`.`).map(Number);if(([0,1,2].map(e=>(r[e]??0)-(i[e]??0)).find(e=>e!==0)??0)<0)throw Error(`This release requires macOS ${t} or later`)}function iu(e,t){let n=/^glibc ([0-9]{1,6})\.([0-9]{1,6})\s*$/.exec(e),r=/^([0-9]{1,6})\.([0-9]{1,6})$/.exec(t);if(!n||!r)throw Error(`Could not verify this release's glibc requirement; use the official manual installation guide`);let i=BigInt(n[1]),a=BigInt(n[2]),o=BigInt(r[1]),s=BigInt(r[2]);if(i<o||i===o&&a<s)throw Error(`This release requires glibc ${t} or later; the installed system has ${n[1]}.${n[2]}`)}async function au(e){let t=await B(e.cli);if(e.platform===`darwin`&&e.arch===`arm64`){let n=I(await B(e.home),`.local/share/shellbell/installs/darwin-arm64`,e.version);if(t===I(n,`Shellbell.app/Contents/Resources/agent/dist/cli.js`)&&await B(e.node)===I(n,`Shellbell.app/Contents/Helpers/node`)){let t=I(n,`installation.json`),r=await z(t);if(!r.isFile()||r.isSymbolicLink()||r.nlink!==1||r.uid!==process.getuid()||r.mode&3602||r.size>4096)throw Error(`Unsafe managed CLI installation receipt`);let i=JSON.parse(await zr(t,`utf8`));if(i.schema!==1||i.platform!==`darwin-arm64`||i.version!==e.version||!/^[a-f0-9]{64}$/.test(i.dmgSha256))throw Error(`Invalid managed CLI installation receipt`);return`mac-cli`}}if(e.platform===`darwin`&&t.includes(`/Shellbell.app/Contents/Resources/agent/dist/`))return`mac-app`;if(e.platform!==`linux`||![`arm64`,`x64`].includes(e.arch))return`other`;let n=I(await B(e.home),`.local/share/shellbell/installs`,`linux-${e.arch}`,e.version);return t!==I(n,`agent/dist/cli.js`)||await B(e.node)!==I(n,`runtime/bin/node`)?`other`:`linux-archive`}async function ou(e,t,n){let r=await e.response(t.browser_download_url,AbortSignal.timeout(18e4));if(!r.body)throw Error(`Empty update download`);let i=r.body.getReader(),a,o=0,s=R(`sha256`);try{for(a=await Lr(n,`wx`,384);;){let{done:e,value:n}=await i.read();if(e)break;if(o+=n.byteLength,o>t.size)throw Error(`Update download exceeds the published size`);s.update(n);let r=0;for(;r<n.byteLength;){let{bytesWritten:e}=await a.write(n,r,n.byteLength-r);if(!e)throw Error(`Could not write update download`);r+=e}}if(o!==t.size||`sha256:${s.digest(`hex`)}`!==t.digest)throw Error(`Update download does not match the published digest`)}finally{try{await i.cancel()}finally{await a?.close()}}}async function su(e){if(!process.stdin.isTTY)throw Error(`Use --yes to install an update without an interactive terminal, or --check to check only`);let t=Kr({input:process.stdin,output:process.stdout});try{return/^y(es)?$/i.test((await t.question(`Download and install Shellbell ${e}? Shellbell running in the background then restarts on it. [y/N] `)).trim())}finally{t.close()}}async function cu(e,t={}){let n=t.log??console.log,r=!1;try{r=(await(t.status??(async()=>Dl().status()))()).installed}catch{r=!1}if(!r)return n(`Run shellbell install to run it in the background. Shellbell running in a terminal window keeps the previous version until you start it again.`),!1;n(`Switching the background Shellbell to it. Your phone reconnects in a few seconds.`);let i=await(t.run??((e,t)=>new Promise(n=>{let r=nr(e,t,{stdio:[`ignore`,`inherit`,`inherit`]});r.once(`error`,()=>n(1)),r.once(`exit`,e=>n(e??1))})))(e,[`install`]);return i!==0&&n(`The background Shellbell couldn't switch. Run shellbell install to try again.`),i===0}function lu(e,t){e.command(`update [version]`).description(`check for a newer Shellbell, and install it when installed from shellbell.dev`).option(`--check`,`check only; do not download or install an app/archive`).option(`--yes`,`confirm installation without prompting`).action(async(n,r)=>{let i=!!e.opts().json;if(i&&!r.check)throw Error(`Use --check with --json; installation requires human-readable output`);let a=new eu,{check:o,assets:s}=await a.check(t,n);if(i){console.log(JSON.stringify(o));return}if(console.log(`Installed: ${t}. Latest stable computer release: ${o.release.version}.`),console.log(`Release notes: ${o.releaseUrl}`),!o.available){console.log(`No newer computer version is available.`);return}if(r.check)return;let c=await B(N()),l=await au({home:c,platform:process.platform,arch:process.arch,version:t,cli:process.argv[1],node:process.execPath});if(l===`mac-app`){console.log(`Open Shellbell → Settings → General → Check for Updates to download the official Mac installer.`);return}if(l!==`linux-archive`&&l!==`mac-cli`){console.log(`This installation is managed outside the CLI installer. Use its original installation method.`),process.platform===`darwin`&&console.log(`For a global npm installation, run: npm install -g shellbell@${o.release.version}. Shellbell running in the background switches to it by itself within a few minutes.`),console.log(`No files or services were changed.`),console.log(`Installation guide: https://github.com/bilal-/shellbell/blob/main/docs/install-agent.md`);return}let u=l===`mac-cli`?s.macosArm64:process.arch===`arm64`?s.linuxArm64:s.linuxX64;if(!u)throw Error(`This release has no archive for this computer's architecture`);let d=I(c,`.local/share/shellbell/installs`,`${process.platform}-${process.arch}`);if(l===`mac-cli`){let e=o.release.platforms.macosArm64;if(!e)throw Error(`Missing platform compatibility information`);ru((await tu(`/usr/bin/sw_vers`,[`-productVersion`],{env:{PATH:`/usr/bin:/bin`,LC_ALL:`C`},timeout:5e3,maxBuffer:1024})).stdout,e.minimumOS)}else{let e=process.arch===`arm64`?o.release.platforms.linuxArm64:o.release.platforms.linuxX64;if(!e)throw Error(`Missing platform compatibility information`);iu((await tu(`/usr/bin/getconf`,[`GNU_LIBC_VERSION`],{env:{PATH:`/usr/bin:/bin`,LC_ALL:`C`},timeout:5e3,maxBuffer:1024})).stdout,e.minimumGlibc)}if(await Vr(I(d,`current`))!==t)throw Error(`A different version is already selected; run ~/.local/bin/shellbell update instead`);let f=I(d,t,`install.sh`),p=await z(f);if(!p.isFile()||p.isSymbolicLink()||p.uid!==process.getuid()||p.mode&3602)throw Error(`The installed CLI's update bootstrap is unsafe; use the official manual installer`);if(!r.yes&&!await su(o.release.version)){console.log(`Update cancelled.`);return}let m=await Ir(I(vr(),`shellbell-update-`));try{let e=I(m,u.name);console.log(`Downloading Shellbell ${o.release.version}…`),await ou(a,u,e);let n=await tu(`/bin/sh`,[f,`--archive`,e,`--sha256`,u.digest.slice(7),`--update-from`,t,`--target-version`,o.release.version],{env:{HOME:c,PATH:`/usr/bin:/bin`,LANG:`C`},timeout:6e5,maxBuffer:65536});console.log(nu(n)),console.log(`Shellbell ${o.release.version} is installed.`),await cu(I(c,`.local/bin/shellbell`))}finally{await Hr(m,{recursive:!0,force:!0})}})}const Z=Kt,Q=new Dr().name(`shellbell`).version(Z).option(`--relay <url>`,`override relay url`).option(`--json`,`machine output`).option(`--verbose`,`debug logging`).option(`--insecure`,`allow a ws:// relay url (LAN dev only)`);lu(Q,Z);function $(e){let t=Q.opts(),n=e??X();return{opts:t,p:n,cfg:wt(n),log:Ke({file:n.log,verbose:t.verbose,stdout:process.stdout.isTTY&&!t.json})}}const uu=e=>`${e.slice(0,4)}-${e.slice(4,8)}`;function du(e,t){return fu(`\n Pair "${Mi(t)}"?\n Phone fingerprint ${ut(e)}\n Check that your phone shows the same fingerprint. [y/N] (60 s) `,6e4)}function fu(e,t,n=!1){return new Promise(r=>{let i=wr({input:process.stdin,output:process.stdout}),a=setTimeout(()=>{i.close(),console.log(`
39
- (timed out — declined)`),r(!1)},t);i.question(e,e=>{clearTimeout(a),i.close();let t=e.trim();r(t===``?n:/^y(es)?$/i.test(t))})})}function pu(e){if(!e.length){console.log(` No coding agents found on this computer.`);return}for(let t of e)console.log(` ${t.name.padEnd(12)} ${on(t)}`)}async function mu(e){let t=fn(e),n=er(Yt(t));if(!n.length)return;let r=n.map(e=>e.name).join(`, `);console.log(`\n Get the most out of ${r} on your phone (highly recommended)\n Scroll back through a whole session, not just what's on screen, in text sized for your
38
+ `)}function ru(e,t){let n=/^\d{1,3}\.\d{1,3}(?:\.\d{1,3})?$/;if(!n.test(e.trim())||!n.test(t))throw Error(`Could not verify the release's macOS requirement`);let r=e.trim().split(`.`).map(Number),i=t.split(`.`).map(Number);if(([0,1,2].map(e=>(r[e]??0)-(i[e]??0)).find(e=>e!==0)??0)<0)throw Error(`This release requires macOS ${t} or later`)}function iu(e,t){let n=/^glibc ([0-9]{1,6})\.([0-9]{1,6})\s*$/.exec(e),r=/^([0-9]{1,6})\.([0-9]{1,6})$/.exec(t);if(!n||!r)throw Error(`Could not verify this release's glibc requirement; use the official manual installation guide`);let i=BigInt(n[1]),a=BigInt(n[2]),o=BigInt(r[1]),s=BigInt(r[2]);if(i<o||i===o&&a<s)throw Error(`This release requires glibc ${t} or later; the installed system has ${n[1]}.${n[2]}`)}async function au(e){let t=await B(e.cli);if(e.platform===`darwin`&&e.arch===`arm64`){let n=I(await B(e.home),`.local/share/shellbell/installs/darwin-arm64`,e.version);if(t===I(n,`Shellbell.app/Contents/Resources/agent/dist/cli.js`)&&await B(e.node)===I(n,`Shellbell.app/Contents/Helpers/node`)){let t=I(n,`installation.json`),r=await z(t);if(!r.isFile()||r.isSymbolicLink()||r.nlink!==1||r.uid!==process.getuid()||r.mode&3602||r.size>4096)throw Error(`Unsafe managed CLI installation receipt`);let i=JSON.parse(await zr(t,`utf8`));if(i.schema!==1||i.platform!==`darwin-arm64`||i.version!==e.version||!/^[a-f0-9]{64}$/.test(i.dmgSha256))throw Error(`Invalid managed CLI installation receipt`);return`mac-cli`}}if(e.platform===`darwin`&&t.includes(`/Shellbell.app/Contents/Resources/agent/dist/`))return`mac-app`;if(e.platform!==`linux`||![`arm64`,`x64`].includes(e.arch))return`other`;let n=I(await B(e.home),`.local/share/shellbell/installs`,`linux-${e.arch}`,e.version);return t!==I(n,`agent/dist/cli.js`)||await B(e.node)!==I(n,`runtime/bin/node`)?`other`:`linux-archive`}async function ou(e,t,n,r=6e4){let i=new AbortController,a=new Promise((e,t)=>i.signal.addEventListener(`abort`,()=>t(Error(`Update download stalled`))));a.catch(()=>{});let o=setTimeout(()=>i.abort(),r),s=()=>{clearTimeout(o),o=setTimeout(()=>i.abort(),r)},c,l;try{let r=await Promise.race([e.response(t.browser_download_url,i.signal),a]);if(!r.body)throw Error(`Empty update download`);l=r.body.getReader();let o=0,u=R(`sha256`);for(c=await Lr(n,`wx`,384);;){let{done:e,value:n}=await Promise.race([l.read(),a]);if(s(),e)break;if(o+=n.byteLength,o>t.size)throw Error(`Update download exceeds the published size`);u.update(n);let r=0;for(;r<n.byteLength;){let{bytesWritten:e}=await c.write(n,r,n.byteLength-r);if(!e)throw Error(`Could not write update download`);r+=e}}if(o!==t.size||`sha256:${u.digest(`hex`)}`!==t.digest)throw Error(`Update download does not match the published digest`)}finally{clearTimeout(o);try{await l?.cancel().catch(()=>{})}finally{await c?.close()}}}async function su(e){if(!e.startsWith(`/`)||e.includes(`\0`))throw Error(`Download folder must be an absolute path`);let t=await z(e);if(!t.isDirectory()||t.isSymbolicLink()||t.uid!==process.getuid?.()||t.mode&63)throw Error(`Download folder must be a private folder of this user`);return e}async function cu(e,t,n,r){let i=t.release.platforms.macosArm64,a=n.macosArm64;if(!i||!a)throw Error(`This release has no Mac installer`);let o=I(await su(r),a.name);return await ou(e,a,o),{schemaVersion:1,version:t.release.version,buildNumber:i.buildNumber,sha256:a.digest.slice(7),path:o}}async function lu(e){if(!process.stdin.isTTY)throw Error(`Use --yes to install an update without an interactive terminal, or --check to check only`);let t=Kr({input:process.stdin,output:process.stdout});try{return/^y(es)?$/i.test((await t.question(`Download and install Shellbell ${e}? Shellbell running in the background then restarts on it. [y/N] `)).trim())}finally{t.close()}}async function uu(e,t={}){let n=t.log??console.log,r=!1;try{r=(await(t.status??(async()=>Dl().status()))()).installed}catch{r=!1}if(!r)return n(`Run shellbell install to run it in the background. Shellbell running in a terminal window keeps the previous version until you start it again.`),!1;n(`Switching the background Shellbell to it. Your phone reconnects in a few seconds.`);let i=await(t.run??((e,t)=>new Promise(n=>{let r=nr(e,t,{stdio:[`ignore`,`inherit`,`inherit`]});r.once(`error`,()=>n(1)),r.once(`exit`,e=>n(e??1))})))(e,[`install`]);return i!==0&&n(`The background Shellbell couldn't switch. Run shellbell install to try again.`),i===0}function du(e,t){e.command(`update [version]`).description(`check for a newer Shellbell, and install it when installed from shellbell.dev`).option(`--check`,`check only; do not download or install an app/archive`).option(`--yes`,`confirm installation without prompting`).addOption(new Or(`--download-mac <folder>`).hideHelp()).action(async(n,r)=>{let i=!!e.opts().json;if(r.downloadMac!==void 0){if(!i||r.check||r.yes||!n)throw Error(`Use --download-mac with a version and --json only`);let e=new eu,{check:a,assets:o}=await e.check(t,n);console.log(JSON.stringify(await cu(e,a,o,r.downloadMac)));return}if(i&&!r.check)throw Error(`Use --check with --json; installation requires human-readable output`);let a=new eu,{check:o,assets:s}=await a.check(t,n);if(i){console.log(JSON.stringify(o));return}if(console.log(`Installed: ${t}. Latest stable computer release: ${o.release.version}.`),console.log(`Release notes: ${o.releaseUrl}`),!o.available){console.log(`No newer computer version is available.`);return}if(r.check)return;let c=await B(N()),l=await au({home:c,platform:process.platform,arch:process.arch,version:t,cli:process.argv[1],node:process.execPath});if(l===`mac-app`){console.log(`Open Shellbell → Settings → General → Check for Updates to download the official Mac installer.`);return}if(l!==`linux-archive`&&l!==`mac-cli`){console.log(`This installation is managed outside the CLI installer. Use its original installation method.`),process.platform===`darwin`&&console.log(`For a global npm installation, run: npm install -g shellbell@${o.release.version}. Shellbell running in the background switches to it by itself within a few minutes.`),console.log(`No files or services were changed.`),console.log(`Installation guide: https://github.com/bilal-/shellbell/blob/main/docs/install-agent.md`);return}let u=l===`mac-cli`?s.macosArm64:process.arch===`arm64`?s.linuxArm64:s.linuxX64;if(!u)throw Error(`This release has no archive for this computer's architecture`);let d=I(c,`.local/share/shellbell/installs`,`${process.platform}-${process.arch}`);if(l===`mac-cli`){let e=o.release.platforms.macosArm64;if(!e)throw Error(`Missing platform compatibility information`);ru((await tu(`/usr/bin/sw_vers`,[`-productVersion`],{env:{PATH:`/usr/bin:/bin`,LC_ALL:`C`},timeout:5e3,maxBuffer:1024})).stdout,e.minimumOS)}else{let e=process.arch===`arm64`?o.release.platforms.linuxArm64:o.release.platforms.linuxX64;if(!e)throw Error(`Missing platform compatibility information`);iu((await tu(`/usr/bin/getconf`,[`GNU_LIBC_VERSION`],{env:{PATH:`/usr/bin:/bin`,LC_ALL:`C`},timeout:5e3,maxBuffer:1024})).stdout,e.minimumGlibc)}if(await Vr(I(d,`current`))!==t)throw Error(`A different version is already selected; run ~/.local/bin/shellbell update instead`);let f=I(d,t,`install.sh`),p=await z(f);if(!p.isFile()||p.isSymbolicLink()||p.uid!==process.getuid()||p.mode&3602)throw Error(`The installed CLI's update bootstrap is unsafe; use the official manual installer`);if(!r.yes&&!await lu(o.release.version)){console.log(`Update cancelled.`);return}let m=await Ir(I(vr(),`shellbell-update-`));try{let e=I(m,u.name);console.log(`Downloading Shellbell ${o.release.version}…`),await ou(a,u,e);let n=await tu(`/bin/sh`,[f,`--archive`,e,`--sha256`,u.digest.slice(7),`--update-from`,t,`--target-version`,o.release.version],{env:{HOME:c,PATH:`/usr/bin:/bin`,LANG:`C`},timeout:6e5,maxBuffer:65536});console.log(nu(n)),console.log(`Shellbell ${o.release.version} is installed.`),await uu(I(c,`.local/bin/shellbell`))}finally{await Hr(m,{recursive:!0,force:!0})}})}const Z=Kt,Q=new Dr().name(`shellbell`).version(Z).option(`--relay <url>`,`override relay url`).option(`--json`,`machine output`).option(`--verbose`,`debug logging`).option(`--insecure`,`allow a ws:// relay url (LAN dev only)`);du(Q,Z);function $(e){let t=Q.opts(),n=e??X();return{opts:t,p:n,cfg:wt(n),log:Ke({file:n.log,verbose:t.verbose,stdout:process.stdout.isTTY&&!t.json})}}const fu=e=>`${e.slice(0,4)}-${e.slice(4,8)}`;function pu(e,t){return mu(`\n Pair "${Mi(t)}"?\n Phone fingerprint ${ut(e)}\n Check that your phone shows the same fingerprint. [y/N] (60 s) `,6e4)}function mu(e,t,n=!1){return new Promise(r=>{let i=wr({input:process.stdin,output:process.stdout}),a=setTimeout(()=>{i.close(),console.log(`
39
+ (timed out — declined)`),r(!1)},t);i.question(e,e=>{clearTimeout(a),i.close();let t=e.trim();r(t===``?n:/^y(es)?$/i.test(t))})})}function hu(e){if(!e.length){console.log(` No coding agents found on this computer.`);return}for(let t of e)console.log(` ${t.name.padEnd(12)} ${on(t)}`)}async function gu(e){let t=fn(e),n=er(Yt(t));if(!n.length)return;let r=n.map(e=>e.name).join(`, `);console.log(`\n Get the most out of ${r} on your phone (highly recommended)\n Scroll back through a whole session, not just what's on screen, in text sized for your
40
40
  phone. Shellbell adds a small helper to each agent. It only notes which window each
41
41
  session runs in, and doesn't change how the agent works. Remove it with
42
- \`shellbell agents remove <name>\`.`),n.some(e=>e.kind===`codex`)&&console.log(` Codex asks you to trust the helper the next time it starts. Choose Trust.`);let i=n.map(e=>e.kind);if(await fu(` Set up now? [Y/n] `,12e4,!0))try{pu(hn(t,i).filter(e=>i.includes(e.kind)))}catch(e){console.error(` ${e instanceof Error?e.message:String(e)}`)}else _n(t,i),console.log(" Skipped. Set up later with `shellbell agents setup`.")}function hu(e,t){console.log(`\n Computer ${e.computerName} (${uu(t)})\n Relay ${e.relayUrl}\n\n Scan this with the Shellbell app:\n`)}function gu(e){return new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`})}function _u(e,t){console.log(` Valid until ${gu(t)}\n`),kr.generate(e,{small:!0},e=>{console.log(e.split(`
42
+ \`shellbell agents remove <name>\`.`),n.some(e=>e.kind===`codex`)&&console.log(` Codex asks you to trust the helper the next time it starts. Choose Trust.`);let i=n.map(e=>e.kind);if(await mu(` Set up now? [Y/n] `,12e4,!0))try{hu(hn(t,i).filter(e=>i.includes(e.kind)))}catch(e){console.error(` ${e instanceof Error?e.message:String(e)}`)}else _n(t,i),console.log(" Skipped. Set up later with `shellbell agents setup`.")}function _u(e,t){console.log(`\n Computer ${e.computerName} (${fu(t)})\n Relay ${e.relayUrl}\n\n Scan this with the Shellbell app:\n`)}function vu(e){return new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`})}function yu(e,t){console.log(` Valid until ${vu(t)}\n`),kr.generate(e,{small:!0},e=>{console.log(e.split(`
43
43
  `).map(e=>` ${e}`).join(`
44
- `)),console.log(``)})}function vu(e,t,n){let r=ur(e,`r`);try{let e=or(r).size,i=Math.max(0,e-t),a=e-i,o=Buffer.alloc(a);a>0&&pr(r,o,0,a,i);let s=o.toString(`utf8`).replace(/\n$/,``);return s.length===0?``:s.split(`
44
+ `)),console.log(``)})}function bu(e,t,n){let r=ur(e,`r`);try{let e=or(r).size,i=Math.max(0,e-t),a=e-i,o=Buffer.alloc(a);a>0&&pr(r,o,0,a,i);let s=o.toString(`utf8`).replace(/\n$/,``);return s.length===0?``:s.split(`
45
45
  `).slice(-n).join(`
46
- `)}finally{rr(r)}}async function yu(e){try{return await ge(e,`status`),!0}catch(e){let t=e.code;return t!==`ECONNREFUSED`&&t!==`ENOENT`}}function bu(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 xu(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 Su(e,t){if(t===void 0)return{cfg:e};let n=ne(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 Cu(e,t,n=!1,i={}){let a=i.paths??X(),o=i.nativeService?void 0:()=>Pt({stateDir:a.dir,uid:a.linuxHost?.uid??process.getuid(),serviceInstance:i.serviceInstance});o?.(),a.linuxHost&&(l(a),m(a)),an(a.dir),gn(fn(a.dir));let s=wt(a);if(t!==void 0){let e=Su(s,t);`error`in e&&(console.error(` --relay ${t}: ${e.error}`),process.exit(1)),e.warning&&console.error(` warning: ${e.warning}`),s=e.cfg}let{identity:c,fp:u}=r(a),d=new Ne(e),f=ac({paths:s.terminalPlugins??[],registry:d,log:e}),p=a.linuxHost?null:new Cs({recordPath:I(a.dir,`iterm2-access.json`),assumeApproved:(()=>{try{return _t(a).length>0}catch{return!1}})(),interactive:!i.nativeService&&!i.managedService&&process.stdin.isTTY===!0,socketPath:Kn}),h=a.linuxHost?null:i.itermBackend===void 0?new Ys(new Tn({log:e,cookieProvider:()=>p.cookieProvider(Zt)}),e):i.itermBackend,g={ready:!1,queue:[]},_=e=>{i.nativeService||(g.ready?console.log(e):g.queue.push(e))},v=()=>{g.ready=!0;for(let e of g.queue)console.log(e);g.queue=[]},y=null,b=null,x=!1,ee,te=async()=>{if(h&&!x)try{if(await h.connect(),x)return;d.add(h),ee=void 0;let t=await h.listSessions().catch(()=>[]);if(x)return;_(` iTerm2 connected · ${t.length} session${t.length===1?``:`s`}`),e.info(`iTerm2 connected`)}catch(t){if(x)return;let n=p?.issue??`failed`;if(n!==ee){ee=n;let r=Vn({name:`iterm2`,connected:!1,issue:n},`command-line`);_(` iTerm2 ${r.status}${r.fix?`\n ${r.fix}`:``}`),e.info(`iTerm2 not connected`,{issue:n,err:j(t)})}y=setTimeout(()=>void S(),1e4)}},S=()=>x?Promise.resolve():b||(y&&clearTimeout(y),y=null,b=te().finally(()=>{b=null}),b);h?.isConnected===!1&&d.add(h),h&&S();let C=!a.linuxHost&&i.itermBackend===void 0?cc(`iterm2`):null,ne=C?lc(`com.googlecode.iterm2`,C.available,{onChange:()=>d.notifySetupChanged()}):()=>void 0,re=h&&p?(()=>{let e=p.onChange(()=>d.notifySetupChanged()),t=Object.assign(e=>Ru(e,p,ne),{connect:()=>p.connect(async()=>{await b,d.connected().some(e=>e.name===`iterm2`)||await S()})}),n=d.registerSetupReporter(`iterm2`,t);return()=>{e(),n()}})():()=>{},ie=!a.linuxHost&&i.tmuxBackendOptions===void 0?hc():null,ae=async()=>{await C?.start(),await S();let e=p?.issue;if(e&&!d.connected().some(e=>e.name===`iterm2`)&&Cn({name:`iterm2`,connected:!1,issue:e})){let{status:t,fix:n}=Vn({name:`iterm2`,connected:!1,issue:e},`phone`);throw new nt(`${t} ${n??``}`.trim())}await dc(d,`iterm2`)},oe=i.terminalWindows??[...ie?[ie]:[],...h&&C?[gc({iterm:h,available:C.available,log:e,ready:async()=>{if(d.connected().some(e=>e.name===`iterm2`)||await ae(),d.member(`iterm2`)!==h)throw new T(`iTerm2 was replaced`,`Reconnect your computer.`)}})]:[]],se=_l({registry:d,log:e,onConnected:e=>_(` tmux connected · ${e} pane${e===1?``:`s`}`),onUnavailable:()=>_(` tmux not running`),backendOptions:i.tmuxBackendOptions,terminalWindows:oe}),ce=a.linuxHost?null:(i.startHerdr??Jt)({registry:d,log:e,onConnected:e=>_(` herdr connected · ${e} pane${e===1?``:`s`}`),onUnavailable:()=>_(` herdr not running (optional)`),...i.herdrBackendOptions?{backendOptions:i.herdrBackendOptions}:{}}),ue=()=>{re(),f.stop(),x=!0,y&&clearTimeout(y),y=null},de=[];h&&C&&de.push(d.registerSessionLauncher(`iterm2`,{available:C.available,start:async()=>(await ae(),{backend:h})}));let fe=!a.linuxHost&&i.startHerdr===void 0?uc():null;if(fe){de.push(d.registerSessionLauncher(`herdr`,{available:fe.available,start:async()=>{await fe.start(),await dc(d,`herdr`);let e=d.member(`herdr`);if(!e)throw new T(`Herdr unavailable`,`Check Herdr's local API.`);return{backend:e}}}));for(let e of oe)de.push(d.registerHostedLauncher({backend:`herdr`,host:e.id,label:e.label},{available:()=>{let t=d.member(`herdr`);return e.available()&&(t instanceof Pn&&t.isConnected?t.terminalAttachExecutable!==void 0:sn()!==void 0)},unavailableReason:()=>{let t=d.member(`herdr`);return e.available()&&t instanceof Pn?t.terminalAttachIssue:void 0},create:async(t,n,r,i)=>{let a=t instanceof Pn?t.terminalAttachExecutable:void 0;if(!a||!(t instanceof Pn))throw new T(`Herdr terminal attach is unavailable`,`Use matching Herdr CLI/server versions, 0.9.3 or newer.`);let{terminalId:o,workspaceId:s}=await t.createWorkspace(),c=`window`;return await mc(async()=>{if(d.member(`herdr`)!==t||t.terminalAttachExecutable!==a)throw new T(`Herdr was disconnected before the terminal could open`,`Reconnect Herdr and try again.`);if(c=await e.launch({executable:a,...r?{initialSize:r}:{},...i?.tab&&{tab:!0},args:[`terminal`,`attach`,o],environment:{HERDR_SOCKET_PATH:t.terminalSocketPath}}),!await t.waitForVisibleAttach(o))throw new T(`terminal window did not attach`,`Unlock your computer and try again.`)},async()=>{if(!s)throw Error(`Herdr workspace id unknown`);await t.closeWorkspace(s)}),{sessionId:o,opened:c}}}))}let pe=()=>{for(let e of de)e();ue(),se.stop(),ce?.stop()},w={server:null},me;return me=new xs({paths:a,config:s,identity:c,fp:u,registry:d,log:e,appVersion:Z,serviceInstance:i.serviceInstance??null,confirm:bu(w,n,(e,t)=>du(e,t),!i.nativeService),onPairingClosed:e=>{w.server?.notifyClosed(e),i.onPairingClosed?.(e)},onSuperseded:()=>{i.nativeService||console.log(` another shellbell agent took over; exiting`),w.server?xu(me,w.server,()=>process.exit(0),pe).catch(()=>process.exit(1)):process.exit(0)}}),w.server=new le(a.sock,me,e,a.pid,o,!i.nativeService&&!i.managedService?e=>Ze({stateDir:a.dir,uid:a.linuxHost?.uid??process.getuid()},e):void 0,i.nativeService?`native`:`terminal`),{agent:me,control:w.server,p:a,cfg:s,fp:u,releaseOutput:v,stopFirstConnect:ue,stopBackendDetectors:pe,herdr:ce}}async function wu(e){let t;try{t=o(e.service===!0)}catch(e){console.error(` ${e.message}`),process.exit(1)}let{opts:n,p:r,log:i}=$(e.paths),{agent:a,control:s,cfg:c,fp:l,releaseOutput:u,stopBackendDetectors:d}=await Cu(i,n.relay,!1,{serviceInstance:t,managedService:e.service===!0,paths:r});try{await s.start()}catch(e){console.error(` ${e.message}`),process.exit(1)}if(a.start(),console.log(`\n Shellbell ${Z}\n Computer ${c.computerName} (${uu(l)})`),console.log(` Relay ${c.relayUrl} ${a.relayOnline?`connected`:`connecting…`}`),a.relay.on(`auth-ok`,()=>console.log(` Relay ${c.relayUrl} connected`)),a.relay.on(`down`,()=>console.log(` Relay ${c.relayUrl} connecting…`)),console.log(` tmux detecting…`),r.linuxHost||console.log(` herdr detecting…`),u(),!e.service&&process.stdin.isTTY&&!n.json&&await mu(r.dir),a.pairingList.length===0&&!e.service&&process.stdin.isTTY){console.log(`
46
+ `)}finally{rr(r)}}async function xu(e){try{return await ge(e,`status`),!0}catch(e){let t=e.code;return t!==`ECONNREFUSED`&&t!==`ENOENT`}}function Su(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 Cu(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 wu(e,t){if(t===void 0)return{cfg:e};let n=ne(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 Tu(e,t,n=!1,i={}){let a=i.paths??X(),o=i.nativeService?void 0:()=>Pt({stateDir:a.dir,uid:a.linuxHost?.uid??process.getuid(),serviceInstance:i.serviceInstance});o?.(),a.linuxHost&&(l(a),m(a)),an(a.dir),gn(fn(a.dir));let s=wt(a);if(t!==void 0){let e=wu(s,t);`error`in e&&(console.error(` --relay ${t}: ${e.error}`),process.exit(1)),e.warning&&console.error(` warning: ${e.warning}`),s=e.cfg}let{identity:c,fp:u}=r(a),d=new Ne(e),f=ac({paths:s.terminalPlugins??[],registry:d,log:e}),p=a.linuxHost?null:new Cs({recordPath:I(a.dir,`iterm2-access.json`),assumeApproved:(()=>{try{return _t(a).length>0}catch{return!1}})(),interactive:!i.nativeService&&!i.managedService&&process.stdin.isTTY===!0,socketPath:Kn}),h=a.linuxHost?null:i.itermBackend===void 0?new Ys(new Tn({log:e,cookieProvider:()=>p.cookieProvider(Zt)}),e):i.itermBackend,g={ready:!1,queue:[]},_=e=>{i.nativeService||(g.ready?console.log(e):g.queue.push(e))},v=()=>{g.ready=!0;for(let e of g.queue)console.log(e);g.queue=[]},y=null,b=null,x=!1,ee,te=async()=>{if(h&&!x)try{if(await h.connect(),x)return;d.add(h),ee=void 0;let t=await h.listSessions().catch(()=>[]);if(x)return;_(` iTerm2 connected · ${t.length} session${t.length===1?``:`s`}`),e.info(`iTerm2 connected`)}catch(t){if(x)return;let n=p?.issue??`failed`;if(n!==ee){ee=n;let r=Vn({name:`iterm2`,connected:!1,issue:n},`command-line`);_(` iTerm2 ${r.status}${r.fix?`\n ${r.fix}`:``}`),e.info(`iTerm2 not connected`,{issue:n,err:j(t)})}y=setTimeout(()=>void S(),1e4)}},S=()=>x?Promise.resolve():b||(y&&clearTimeout(y),y=null,b=te().finally(()=>{b=null}),b);h?.isConnected===!1&&d.add(h),h&&S();let C=!a.linuxHost&&i.itermBackend===void 0?cc(`iterm2`):null,ne=C?lc(`com.googlecode.iterm2`,C.available,{onChange:()=>d.notifySetupChanged()}):()=>void 0,re=h&&p?(()=>{let e=p.onChange(()=>d.notifySetupChanged()),t=Object.assign(e=>Bu(e,p,ne),{connect:()=>p.connect(async()=>{await b,d.connected().some(e=>e.name===`iterm2`)||await S()})}),n=d.registerSetupReporter(`iterm2`,t);return()=>{e(),n()}})():()=>{},ie=!a.linuxHost&&i.tmuxBackendOptions===void 0?hc():null,ae=async()=>{await C?.start(),await S();let e=p?.issue;if(e&&!d.connected().some(e=>e.name===`iterm2`)&&Cn({name:`iterm2`,connected:!1,issue:e})){let{status:t,fix:n}=Vn({name:`iterm2`,connected:!1,issue:e},`phone`);throw new nt(`${t} ${n??``}`.trim())}await dc(d,`iterm2`)},oe=i.terminalWindows??[...ie?[ie]:[],...h&&C?[gc({iterm:h,available:C.available,log:e,ready:async()=>{if(d.connected().some(e=>e.name===`iterm2`)||await ae(),d.member(`iterm2`)!==h)throw new T(`iTerm2 was replaced`,`Reconnect your computer.`)}})]:[]],se=_l({registry:d,log:e,onConnected:e=>_(` tmux connected · ${e} pane${e===1?``:`s`}`),onUnavailable:()=>_(` tmux not running`),backendOptions:i.tmuxBackendOptions,terminalWindows:oe}),ce=a.linuxHost?null:(i.startHerdr??Jt)({registry:d,log:e,onConnected:e=>_(` herdr connected · ${e} pane${e===1?``:`s`}`),onUnavailable:()=>_(` herdr not running (optional)`),...i.herdrBackendOptions?{backendOptions:i.herdrBackendOptions}:{}}),ue=()=>{re(),f.stop(),x=!0,y&&clearTimeout(y),y=null},de=[];h&&C&&de.push(d.registerSessionLauncher(`iterm2`,{available:C.available,start:async()=>(await ae(),{backend:h})}));let fe=!a.linuxHost&&i.startHerdr===void 0?uc():null;if(fe){de.push(d.registerSessionLauncher(`herdr`,{available:fe.available,start:async()=>{await fe.start(),await dc(d,`herdr`);let e=d.member(`herdr`);if(!e)throw new T(`Herdr unavailable`,`Check Herdr's local API.`);return{backend:e}}}));for(let e of oe)de.push(d.registerHostedLauncher({backend:`herdr`,host:e.id,label:e.label},{available:()=>{let t=d.member(`herdr`);return e.available()&&(t instanceof Pn&&t.isConnected?t.terminalAttachExecutable!==void 0:sn()!==void 0)},unavailableReason:()=>{let t=d.member(`herdr`);return e.available()&&t instanceof Pn?t.terminalAttachIssue:void 0},create:async(t,n,r,i)=>{let a=t instanceof Pn?t.terminalAttachExecutable:void 0;if(!a||!(t instanceof Pn))throw new T(`Herdr terminal attach is unavailable`,`Use matching Herdr CLI/server versions, 0.9.3 or newer.`);let{terminalId:o,workspaceId:s}=await t.createWorkspace(),c=`window`;return await mc(async()=>{if(d.member(`herdr`)!==t||t.terminalAttachExecutable!==a)throw new T(`Herdr was disconnected before the terminal could open`,`Reconnect Herdr and try again.`);if(c=await e.launch({executable:a,...r?{initialSize:r}:{},...i?.tab&&{tab:!0},args:[`terminal`,`attach`,o],environment:{HERDR_SOCKET_PATH:t.terminalSocketPath}}),!await t.waitForVisibleAttach(o))throw new T(`terminal window did not attach`,`Unlock your computer and try again.`)},async()=>{if(!s)throw Error(`Herdr workspace id unknown`);await t.closeWorkspace(s)}),{sessionId:o,opened:c}}}))}let pe=()=>{for(let e of de)e();ue(),se.stop(),ce?.stop()},w={server:null},me;return me=new xs({paths:a,config:s,identity:c,fp:u,registry:d,log:e,appVersion:Z,serviceInstance:i.serviceInstance??null,confirm:Su(w,n,(e,t)=>pu(e,t),!i.nativeService),onPairingClosed:e=>{w.server?.notifyClosed(e),i.onPairingClosed?.(e)},onSuperseded:()=>{i.nativeService||console.log(` another shellbell agent took over; exiting`),w.server?Cu(me,w.server,()=>process.exit(0),pe).catch(()=>process.exit(1)):process.exit(0)}}),w.server=new le(a.sock,me,e,a.pid,o,!i.nativeService&&!i.managedService?e=>Ze({stateDir:a.dir,uid:a.linuxHost?.uid??process.getuid()},e):void 0,i.nativeService?`native`:`terminal`),{agent:me,control:w.server,p:a,cfg:s,fp:u,releaseOutput:v,stopFirstConnect:ue,stopBackendDetectors:pe,herdr:ce}}async function Eu(e){let t;try{t=o(e.service===!0)}catch(e){console.error(` ${e.message}`),process.exit(1)}let{opts:n,p:r,log:i}=$(e.paths),{agent:a,control:s,cfg:c,fp:l,releaseOutput:u,stopBackendDetectors:d}=await Tu(i,n.relay,!1,{serviceInstance:t,managedService:e.service===!0,paths:r});try{await s.start()}catch(e){console.error(` ${e.message}`),process.exit(1)}if(a.start(),console.log(`\n Shellbell ${Z}\n Computer ${c.computerName} (${fu(l)})`),console.log(` Relay ${c.relayUrl} ${a.relayOnline?`connected`:`connecting…`}`),a.relay.on(`auth-ok`,()=>console.log(` Relay ${c.relayUrl} connected`)),a.relay.on(`down`,()=>console.log(` Relay ${c.relayUrl} connecting…`)),console.log(` tmux detecting…`),r.linuxHost||console.log(` herdr detecting…`),u(),!e.service&&process.stdin.isTTY&&!n.json&&await gu(r.dir),a.pairingList.length===0&&!e.service&&process.stdin.isTTY){console.log(`
47
47
  No phones paired yet. Scan this with the Shellbell app:
48
- `);let{qrText:e,expiresAt:t}=a.openPairing();_u(e,t)}let f=!1,p=()=>{if(f){console.error(` forcing exit`),process.exit(130);return}f=!0,xu(a,s,process.exit,d).catch(()=>process.exit(1))};process.on(`SIGINT`,p),process.on(`SIGTERM`,p),e.service&&Bl({running:Z,packageJson:zl(),busy:()=>a.connectedPhones.some(e=>e.viewed!==null),log:i,restart:()=>{f||(f=!0,xu(a,s,()=>process.exit(75),d).catch(()=>process.exit(75)))}}),!e.service&&process.stdin.isTTY&&!n.json&&console.log(`\n ${Tu}`)}const Tu="Shellbell is running in this window, so your phone can reach this computer until you close it or press Ctrl-C. Run `shellbell install` to keep Shellbell running in the background instead.",Eu=`
48
+ `);let{qrText:e,expiresAt:t}=a.openPairing();yu(e,t)}let f=!1,p=()=>{if(f){console.error(` forcing exit`),process.exit(130);return}f=!0,Cu(a,s,process.exit,d).catch(()=>process.exit(1))};process.on(`SIGINT`,p),process.on(`SIGTERM`,p),e.service&&Bl({running:Z,packageJson:zl(),busy:()=>a.connectedPhones.some(e=>e.viewed!==null),log:i,restart:()=>{f||(f=!0,Cu(a,s,()=>process.exit(75),d).catch(()=>process.exit(75)))}}),!e.service&&process.stdin.isTTY&&!n.json&&console.log(`\n ${Du}`)}const Du="Shellbell is running in this window, so your phone can reach this computer until you close it or press Ctrl-C. Run `shellbell install` to keep Shellbell running in the background instead.",Ou=`
49
49
  Run Shellbell in the background? (highly recommended)
50
50
  Your phone can then reach this computer whenever it's on and you're logged in, without a
51
- terminal window open. [Y/n] `;function Du(){if(process.platform!==`darwin`)return!1;let e=pt({stateDir:X().dir,uid:process.getuid()});return e&&console.log(` ${e}`),e!==null}function Ou(){return process.platform===`linux`?f():ot()}async function ku(e){if(!e.linuxHost)return;let t=null;try{t=(await new Sn({env:process.env}).installedRuntime())?.stateDir??null}catch{}await El(e,{installedStateDir:t})}async function Au(e){try{return await yu((e??X()).sock)}catch{return!1}}async function ju(){try{return(await ge(X().sock,`status`)).process?.serviceInstance===null}catch{return!1}}async function Mu(){if(process.platform===`darwin`||process.platform===`linux`)try{return await Dl().status()}catch{return}}function Nu(){return{background:()=>Dl(),version:Z,offerAgents:async()=>{process.stdin.isTTY&&await mu(X().dir)},afterInstall:async()=>{if(!process.stdin.isTTY)return;let{p:e}=$();_t(e).length===0&&await Pu(!1)},otherCopyRunning:ju,appOwned:Du}}async function Pu(e){let{p:t,cfg:n}=$(),{fp:i}=r(t),a;try{a=await ge(t.sock,`status`)}catch{a=void 0}return new Promise(r=>{let o=``,s=fe(t.sock,{onOpen:(e,t)=>{hu(n,i),_u(e,t)},onRequest:async(t,n)=>{let r=e||await du(t,n);return r&&(o=Mi(n)),r},onClose:e=>{clearTimeout(c),e===`replaced`?console.log(` This code has been replaced by a newer one. Scan the new code instead.`):e===`paired`?a?.process?.serviceInstance===null?console.log(` Paired with ${o||`your phone`}. Shellbell is running in a terminal window, so your phone can reach this computer only while that window stays open. Run \`shellbell install\` to keep it running in the background.`):console.log(` Paired with ${o||`your phone`}. You're all set.`):console.log(` pairing window closed`),s.close(),r(e===`paired`?0:1)},onError:e=>{clearTimeout(c),console.error(` ${e.message}`),r(1)}}),c=setTimeout(()=>{s.close(),r(1)},301e3)})}async function Fu(e,t,n){let{p:r,log:i}=$(n),a=!1,o,s,c=e=>s?void xu(s.agent,s.control,()=>process.exit(e),s.stopBackendDetectors).catch(()=>process.exit(1)):process.exit(e);s=await Cu(i,t.relay,e,{paths:r,onPairingClosed:e=>{if(e!==`paired`){a||(console.log(` pairing window closed`),c(0));return}a=!0,clearTimeout(o);let t=s?.agent.pairingList.at(-1)?.name;console.log(` Paired with ${t?Mi(t):`your phone`}.\n\n ${Tu}`)}});let{agent:l,control:u,cfg:d,fp:f,releaseOutput:p}=s;try{await u.start()}catch(e){console.error(` ${e.message}`),process.exit(1)}l.start();let{qrText:m,expiresAt:h}=l.openPairing();hu(d,f),_u(m,h),p(),o=setTimeout(()=>c(0),301e3);let g=!1,_=()=>{g&&process.exit(130),g=!0,c(0)};process.on(`SIGINT`,_),process.on(`SIGTERM`,_)}Q.command(`start`,{isDefault:!0}).description(`start Shellbell, offering to run it in the background`).addOption(new Or(`--service`,`the background service's own entry`).hideHelp()).action(async e=>{if(e.service)return wu(e);let t=!!Q.opts().json;if(Du())return;let n=Nu(),r=await Mu();if(r?.installed){process.exitCode=await Fl(n,t);return}let i=Ou();if(await Au(i)){console.log(` Shellbell is already running in a terminal window.`);return}if(r?.available&&process.stdin.isTTY&&!t){if(console.log(`
52
- Shellbell isn't set up to run in the background on this computer yet.`),await fu(Eu,12e4,!0)){process.exitCode=await Ml(n,t);return}}else r&&!r.available&&!t&&console.log(` ${Ol}`);return await ku(i),wu({paths:i})}),Q.command(`run`).description(`run Shellbell in this window only, for containers and testing`).action(async()=>{if(Du())return;let e=Ou();return await ku(e),wu({paths:e})}),Q.command(`pair`).description(`pair a phone: shows a QR code to scan with the Shellbell app`).option(`--yes`,`auto-accept requests (unsafe on shared screens)`).action(async e=>{let t=Q.opts(),n=!!e.yes;if(Du())return;let r=Ou();if(await Au(r)){process.exitCode=await Pu(n);return}let i=await Mu(),a=Nu();if(i?.installed){await Fl(a,!!t.json)===0?process.exitCode=await Pu(n):process.exitCode=2;return}if(i?.available&&process.stdin.isTTY&&!t.json){if(console.log(`
53
- Shellbell isn't running in the background on this computer yet.`),await fu(Eu,12e4,!0)){let e=await Ml({...a,afterInstall:void 0},!1);process.exitCode=e===0?await Pu(n):e;return}}else process.stdin.isTTY||console.error(" Shellbell isn't running in the background, so this pairing lasts only while this command runs. Run `shellbell install` first.");await ku(r),await Fu(n,t,r)});const Iu={iterm2:`iTerm2`,tmux:`tmux`,herdr:`Herdr`};Q.command(`status`).description(`show whether Shellbell is running, and its phones and terminals`).action(async()=>{let e=!!Q.opts().json,t=null,n=null,r;try{if(process.platform===`darwin`||process.platform===`linux`){let e=Dl();n=e.system,t=await e.status()}}catch(e){r=kl(e)}let i=null;try{i=await ge(X().sock,`status`)}catch{i=null}if(process.exitCode=i?0:2,e){console.log(JSON.stringify({background:t,running:i,...r?{backgroundError:r}:{}}));return}if(Du())return;if(r&&console.log(` ${r}`),!i){for(let e of t&&n?Al(t,n):["Shellbell isn't running. Run `shellbell start`."])console.log(` ${e}`);return}if(t?.running&&n)for(let e of Al(t,n))console.log(` ${e}`);else console.log(` Shellbell ${i.process.agentVersion} is running in a terminal window, so it stops when that window closes. Run \`shellbell install\` to keep it running in the background.`);i.process.agentVersion!==Z&&console.log(i.process.serviceInstance?` Shellbell ${Z} is installed, but ${i.process.agentVersion} is still running. Run \`shellbell install\` to switch now.`:` Shellbell ${Z} is installed. Stop the copy in the terminal window and start it again to use it.`);let a=new Set(i.connected.map(e=>e.phoneFp)),o=i.phones.map(e=>`${Mi(e.name)}${a.has(e.phoneFp)?` (connected)`:``}`),s=i.backends.filter(e=>e.connected).map(e=>Iu[e.name]??e.name);console.log(` Phones ${o.join(`, `)||"none yet. Run `shellbell pair`."}`),console.log(` Terminals ${s.join(`, `)||"none ready. Run `shellbell doctor` to see why."}`),console.log(` Relay ${i.relayOnline?`connected`:`connecting…`}`)});function Lu(e){let t=e?.code;console.error(t===`ENOENT`||t===`ECONNREFUSED`?" Shellbell isn't running. Run `shellbell start`.":`shellbell: ${e instanceof Error?e.message:`control request failed`}`),process.exitCode=2}Q.command(`phones`).alias(`devices`).description(`list paired phones`).action(async()=>{let{opts:e,p:t}=$(),n=_t(t),r=new Set;try{let e=await ge(t.sock,`status`);r=new Set(e.connected.map(e=>e.phoneFp))}catch{}if(e.json){console.log(JSON.stringify(n.map(e=>({phoneFp:e.phoneFp,name:e.name,pairedAt:e.pairedAt,lastSeenAt:e.lastSeenAt,connected:r.has(e.phoneFp)}))));return}n.length||console.log(" No phones paired yet. Run `shellbell pair`.");for(let e of n)console.log(` ${Mi(e.name).padEnd(20)} ${r.has(e.phoneFp)?`connected`:e.lastSeenAt?`last seen ${new Date(e.lastSeenAt).toLocaleString()}`:`not seen yet`} ${uu(e.phoneFp)}`)});function Ru(e,t,n){if(e)return{};if(t.connecting)return{issue:`connecting`};let r=t.issue??`not-running`;return r===`not-running`&&n()===!1?{issue:`not-installed`}:{issue:r}}async function zu(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}=Vn(s,`command-line`);return r(` ${c}`),l&&r(` ${l}`),s.connected&&!s.issue?0:2}Q.command(`connect <terminal>`).description(`connect a terminal that needs your approval, such as iterm2`).action(async e=>{let{p:t}=$(),n;try{n=await te(t.sock),process.exitCode=await zu(n,e)}catch(e){Lu(e)}finally{n?.close()}}),Q.command(`agents [action] [name]`).description(`list coding agents, or set them up for full history: agents [setup [name] | remove <name>]`).action((e,t)=>{let{opts:n,p:r}=$(),i=fn(r.dir);if(!(e===void 0||e===`setup`||e===`remove`&&t!==void 0)){process.exitCode=2,console.error(` usage: shellbell agents [setup [name] | remove <name>]`);return}try{let r=Yt(i),a=t&&r.find(e=>[e.kind,e.name.toLowerCase()].includes(t.toLowerCase()))?.kind;if(t&&!a){process.exitCode=2,console.error(` Shellbell didn't find ${t} on this computer.`);return}let o=e===`setup`?hn(i,a?[a]:void 0):e===`remove`?tn(i,a):r;n.json?console.log(JSON.stringify({agents:o})):pu(o),e===void 0&&!n.json&&er(o).length&&console.log("\n Run `shellbell agents setup` for full history on your phone.")}catch(e){process.exitCode=2,console.error(` ${e instanceof Error?e.message:String(e)}`)}}),Q.command(`integration <action> <agent>`,{hidden:!0}).action((e,t)=>{if(t!==`codex`||![`install`,`uninstall`,`status`].includes(e)){process.exitCode=2,console.error(` usage: shellbell agents [setup [name] | remove <name>]`);return}let n=fn($().p.dir);try{pu((e===`install`?hn(n,[`codex`]):e===`uninstall`?tn(n,`codex`):Yt(n)).filter(e=>e.kind===`codex`))}catch(e){process.exitCode=2,console.error(` ${e instanceof Error?e.message:String(e)}`)}}),Q.command(`unpair <target>`).description(`remove a paired phone (fp prefix or name)`).action(async e=>{let{p:t}=$();try{let n=await ge(t.sock,`unpair`,{target:e});console.log(n.removed?` removed`:` no such phone`)}catch(e){Lu(e)}}),Il(Q,Nu()),Q.command(`logs`).option(`-f, --follow`).description(`show Shellbell's log`).action(e=>{let{p:t}=$();e.follow?nr(`tail`,[`-f`,t.log],{stdio:`inherit`}):ar(t.log)&&process.stdout.write(vu(t.log,65536,200))});function Bu(e,t){process.exitCode=2,t?console.log(JSON.stringify({error:e})):console.error(` ${e}`)}Q.command(`config`).description(`config set <${Ae.join(`|`)}> <value>`).argument(`<op>`).argument(`<key>`).argument(`<value>`).action(async(e,t,n)=>{let r=Q.opts();if(e!==`set`){Bu(`unknown config operation ${e} (expected set)`,r.json);return}let i=!!r.insecure||process.env.SHELLBELL_ALLOW_INSECURE_RELAY===`1`,a=Tt(ht(),t,n,i);if(`error`in a){Bu(a.error,r.json);return}let o=!1,s=!0;try{let e=X(),r=It(e,e=>{let r=Tt(e,t,n,i);if(`error`in r)throw Error(r.error);return r.next});if(t===`conversations`){let t;try{if(t=await te(e.sock),t.runtime.stateDir===mr(e.dir)){let e=await t.applyConversationSetting(_(r));o=e!==null,s=e!==_(r)}}catch{}finally{t?.close()}}}catch(e){Bu(e instanceof Error?e.message:String(e),r.json);return}r.json?console.log(JSON.stringify({saved:!0,restartRequired:s,...t===`conversations`?{conversationApplied:o}:{}})):console.log(t===`conversations`&&!o?` configuration saved; live conversation consent could not be confirmed. Restart the agent if it is running.`:s?o?` conversation consent applied; other saved settings still need an agent restart`:` configuration saved; the running agent must be restarted`:` conversation consent saved and applied to the running agent`)});function Vu(e,t,n=console.log,r=e=>{process.exitCode=e}){let i=Rn(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 Hu(e,t={}){e.command(`doctor`).description(`check Shellbell, the relay and terminals without changing anything`).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=>!Ie.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=Ie.filter(e=>i.has(e)),o=t.env??process.env,s;try{s=await(t.runDoctor??Mn)({requestedStateDir:o.SHELLBELL_DIR,defaultStateDir:t.defaultStateDir??I(N(),`.shellbell`),requiredBackends:a,env:o,version:Z})}catch{s=[{name:`doctor`,ok:!1,severity:`error`,detail:`diagnostic inspection failed`}]}Vu(s,r)})}Hu(Q),Ll(Q);function Uu(e,t,n=mr){if(!e)return!1;let r;try{r=n(e)}catch{r=e}let i=Tr(t),a;try{a=n(i)}catch{a=i}return a===r}Uu(process.argv[1],import.meta.url)&&Q.parseAsync().catch(e=>{e instanceof Error&&!Q.opts().verbose?console.error(` ${e.message.replace(/^shellbell: /,``)}`):console.error(e),process.exit(1)});export{Ae as CONFIG_KEYS,Tu as IN_THIS_WINDOW,Hu as addDoctorCommand,Cu as buildAgent,bu as chooseConfirm,zu as connectTerminalCommand,Ru as iTermSetupReport,Uu as isEntryPoint,gu as pairValidUntil,Vu as printDoctorResult,Q as program,Tt as resolveConfigSet,Su as resolveRelayOverride,xu as shutdown,yu as socketAlive,vu as tailFile,ne as validateRelayUrl};
51
+ terminal window open. [Y/n] `;function ku(){if(process.platform!==`darwin`)return!1;let e=pt({stateDir:X().dir,uid:process.getuid()});return e&&console.log(` ${e}`),e!==null}function Au(){return process.platform===`linux`?f():ot()}async function ju(e){if(!e.linuxHost)return;let t=null;try{t=(await new Sn({env:process.env}).installedRuntime())?.stateDir??null}catch{}await El(e,{installedStateDir:t})}async function Mu(e){try{return await xu((e??X()).sock)}catch{return!1}}async function Nu(){try{return(await ge(X().sock,`status`)).process?.serviceInstance===null}catch{return!1}}async function Pu(){if(process.platform===`darwin`||process.platform===`linux`)try{return await Dl().status()}catch{return}}function Fu(){return{background:()=>Dl(),version:Z,offerAgents:async()=>{process.stdin.isTTY&&await gu(X().dir)},afterInstall:async()=>{if(!process.stdin.isTTY)return;let{p:e}=$();_t(e).length===0&&await Iu(!1)},otherCopyRunning:Nu,appOwned:ku}}async function Iu(e){let{p:t,cfg:n}=$(),{fp:i}=r(t),a;try{a=await ge(t.sock,`status`)}catch{a=void 0}return new Promise(r=>{let o=``,s=fe(t.sock,{onOpen:(e,t)=>{_u(n,i),yu(e,t)},onRequest:async(t,n)=>{let r=e||await pu(t,n);return r&&(o=Mi(n)),r},onClose:e=>{clearTimeout(c),e===`replaced`?console.log(` This code has been replaced by a newer one. Scan the new code instead.`):e===`paired`?a?.process?.serviceInstance===null?console.log(` Paired with ${o||`your phone`}. Shellbell is running in a terminal window, so your phone can reach this computer only while that window stays open. Run \`shellbell install\` to keep it running in the background.`):console.log(` Paired with ${o||`your phone`}. You're all set.`):console.log(` pairing window closed`),s.close(),r(e===`paired`?0:1)},onError:e=>{clearTimeout(c),console.error(` ${e.message}`),r(1)}}),c=setTimeout(()=>{s.close(),r(1)},301e3)})}async function Lu(e,t,n){let{p:r,log:i}=$(n),a=!1,o,s,c=e=>s?void Cu(s.agent,s.control,()=>process.exit(e),s.stopBackendDetectors).catch(()=>process.exit(1)):process.exit(e);s=await Tu(i,t.relay,e,{paths:r,onPairingClosed:e=>{if(e!==`paired`){a||(console.log(` pairing window closed`),c(0));return}a=!0,clearTimeout(o);let t=s?.agent.pairingList.at(-1)?.name;console.log(` Paired with ${t?Mi(t):`your phone`}.\n\n ${Du}`)}});let{agent:l,control:u,cfg:d,fp:f,releaseOutput:p}=s;try{await u.start()}catch(e){console.error(` ${e.message}`),process.exit(1)}l.start();let{qrText:m,expiresAt:h}=l.openPairing();_u(d,f),yu(m,h),p(),o=setTimeout(()=>c(0),301e3);let g=!1,_=()=>{g&&process.exit(130),g=!0,c(0)};process.on(`SIGINT`,_),process.on(`SIGTERM`,_)}Q.command(`start`,{isDefault:!0}).description(`start Shellbell, offering to run it in the background`).addOption(new Or(`--service`,`the background service's own entry`).hideHelp()).action(async e=>{if(e.service)return Eu(e);let t=!!Q.opts().json;if(ku())return;let n=Fu(),r=await Pu();if(r?.installed){process.exitCode=await Fl(n,t);return}let i=Au();if(await Mu(i)){console.log(` Shellbell is already running in a terminal window.`);return}if(r?.available&&process.stdin.isTTY&&!t){if(console.log(`
52
+ Shellbell isn't set up to run in the background on this computer yet.`),await mu(Ou,12e4,!0)){process.exitCode=await Ml(n,t);return}}else r&&!r.available&&!t&&console.log(` ${Ol}`);return await ju(i),Eu({paths:i})}),Q.command(`run`).description(`run Shellbell in this window only, for containers and testing`).action(async()=>{if(ku())return;let e=Au();return await ju(e),Eu({paths:e})}),Q.command(`pair`).description(`pair a phone: shows a QR code to scan with the Shellbell app`).option(`--yes`,`auto-accept requests (unsafe on shared screens)`).action(async e=>{let t=Q.opts(),n=!!e.yes;if(ku())return;let r=Au();if(await Mu(r)){process.exitCode=await Iu(n);return}let i=await Pu(),a=Fu();if(i?.installed){await Fl(a,!!t.json)===0?process.exitCode=await Iu(n):process.exitCode=2;return}if(i?.available&&process.stdin.isTTY&&!t.json){if(console.log(`
53
+ Shellbell isn't running in the background on this computer yet.`),await mu(Ou,12e4,!0)){let e=await Ml({...a,afterInstall:void 0},!1);process.exitCode=e===0?await Iu(n):e;return}}else process.stdin.isTTY||console.error(" Shellbell isn't running in the background, so this pairing lasts only while this command runs. Run `shellbell install` first.");await ju(r),await Lu(n,t,r)});const Ru={iterm2:`iTerm2`,tmux:`tmux`,herdr:`Herdr`};Q.command(`status`).description(`show whether Shellbell is running, and its phones and terminals`).action(async()=>{let e=!!Q.opts().json,t=null,n=null,r;try{if(process.platform===`darwin`||process.platform===`linux`){let e=Dl();n=e.system,t=await e.status()}}catch(e){r=kl(e)}let i=null;try{i=await ge(X().sock,`status`)}catch{i=null}if(process.exitCode=i?0:2,e){console.log(JSON.stringify({background:t,running:i,...r?{backgroundError:r}:{}}));return}if(ku())return;if(r&&console.log(` ${r}`),!i){for(let e of t&&n?Al(t,n):["Shellbell isn't running. Run `shellbell start`."])console.log(` ${e}`);return}if(t?.running&&n)for(let e of Al(t,n))console.log(` ${e}`);else console.log(` Shellbell ${i.process.agentVersion} is running in a terminal window, so it stops when that window closes. Run \`shellbell install\` to keep it running in the background.`);i.process.agentVersion!==Z&&console.log(i.process.serviceInstance?` Shellbell ${Z} is installed, but ${i.process.agentVersion} is still running. Run \`shellbell install\` to switch now.`:` Shellbell ${Z} is installed. Stop the copy in the terminal window and start it again to use it.`);let a=new Set(i.connected.map(e=>e.phoneFp)),o=i.phones.map(e=>`${Mi(e.name)}${a.has(e.phoneFp)?` (connected)`:``}`),s=i.backends.filter(e=>e.connected).map(e=>Ru[e.name]??e.name);console.log(` Phones ${o.join(`, `)||"none yet. Run `shellbell pair`."}`),console.log(` Terminals ${s.join(`, `)||"none ready. Run `shellbell doctor` to see why."}`),console.log(` Relay ${i.relayOnline?`connected`:`connecting…`}`)});function zu(e){let t=e?.code;console.error(t===`ENOENT`||t===`ECONNREFUSED`?" Shellbell isn't running. Run `shellbell start`.":`shellbell: ${e instanceof Error?e.message:`control request failed`}`),process.exitCode=2}Q.command(`phones`).alias(`devices`).description(`list paired phones`).action(async()=>{let{opts:e,p:t}=$(),n=_t(t),r=new Set;try{let e=await ge(t.sock,`status`);r=new Set(e.connected.map(e=>e.phoneFp))}catch{}if(e.json){console.log(JSON.stringify(n.map(e=>({phoneFp:e.phoneFp,name:e.name,pairedAt:e.pairedAt,lastSeenAt:e.lastSeenAt,connected:r.has(e.phoneFp)}))));return}n.length||console.log(" No phones paired yet. Run `shellbell pair`.");for(let e of n)console.log(` ${Mi(e.name).padEnd(20)} ${r.has(e.phoneFp)?`connected`:e.lastSeenAt?`last seen ${new Date(e.lastSeenAt).toLocaleString()}`:`not seen yet`} ${fu(e.phoneFp)}`)});function Bu(e,t,n){if(e)return{};if(t.connecting)return{issue:`connecting`};let r=t.issue??`not-running`;return r===`not-running`&&n()===!1?{issue:`not-installed`}:{issue:r}}async function Vu(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}=Vn(s,`command-line`);return r(` ${c}`),l&&r(` ${l}`),s.connected&&!s.issue?0:2}Q.command(`connect <terminal>`).description(`connect a terminal that needs your approval, such as iterm2`).action(async e=>{let{p:t}=$(),n;try{n=await te(t.sock),process.exitCode=await Vu(n,e)}catch(e){zu(e)}finally{n?.close()}}),Q.command(`agents [action] [name]`).description(`list coding agents, or set them up for full history: agents [setup [name] | remove <name>]`).action((e,t)=>{let{opts:n,p:r}=$(),i=fn(r.dir);if(!(e===void 0||e===`setup`||e===`remove`&&t!==void 0)){process.exitCode=2,console.error(` usage: shellbell agents [setup [name] | remove <name>]`);return}try{let r=Yt(i),a=t&&r.find(e=>[e.kind,e.name.toLowerCase()].includes(t.toLowerCase()))?.kind;if(t&&!a){process.exitCode=2,console.error(` Shellbell didn't find ${t} on this computer.`);return}let o=e===`setup`?hn(i,a?[a]:void 0):e===`remove`?tn(i,a):r;n.json?console.log(JSON.stringify({agents:o})):hu(o),e===void 0&&!n.json&&er(o).length&&console.log("\n Run `shellbell agents setup` for full history on your phone.")}catch(e){process.exitCode=2,console.error(` ${e instanceof Error?e.message:String(e)}`)}}),Q.command(`integration <action> <agent>`,{hidden:!0}).action((e,t)=>{if(t!==`codex`||![`install`,`uninstall`,`status`].includes(e)){process.exitCode=2,console.error(` usage: shellbell agents [setup [name] | remove <name>]`);return}let n=fn($().p.dir);try{hu((e===`install`?hn(n,[`codex`]):e===`uninstall`?tn(n,`codex`):Yt(n)).filter(e=>e.kind===`codex`))}catch(e){process.exitCode=2,console.error(` ${e instanceof Error?e.message:String(e)}`)}}),Q.command(`unpair <target>`).description(`remove a paired phone (fp prefix or name)`).action(async e=>{let{p:t}=$();try{let n=await ge(t.sock,`unpair`,{target:e});console.log(n.removed?` removed`:` no such phone`)}catch(e){zu(e)}}),Il(Q,Fu()),Q.command(`logs`).option(`-f, --follow`).description(`show Shellbell's log`).action(e=>{let{p:t}=$();e.follow?nr(`tail`,[`-f`,t.log],{stdio:`inherit`}):ar(t.log)&&process.stdout.write(bu(t.log,65536,200))});function Hu(e,t){process.exitCode=2,t?console.log(JSON.stringify({error:e})):console.error(` ${e}`)}Q.command(`config`).description(`config set <${Ae.join(`|`)}> <value>`).argument(`<op>`).argument(`<key>`).argument(`<value>`).action(async(e,t,n)=>{let r=Q.opts();if(e!==`set`){Hu(`unknown config operation ${e} (expected set)`,r.json);return}let i=!!r.insecure||process.env.SHELLBELL_ALLOW_INSECURE_RELAY===`1`,a=Tt(ht(),t,n,i);if(`error`in a){Hu(a.error,r.json);return}let o=!1,s=!0;try{let e=X(),r=It(e,e=>{let r=Tt(e,t,n,i);if(`error`in r)throw Error(r.error);return r.next});if(t===`conversations`){let t;try{if(t=await te(e.sock),t.runtime.stateDir===mr(e.dir)){let e=await t.applyConversationSetting(_(r));o=e!==null,s=e!==_(r)}}catch{}finally{t?.close()}}}catch(e){Hu(e instanceof Error?e.message:String(e),r.json);return}r.json?console.log(JSON.stringify({saved:!0,restartRequired:s,...t===`conversations`?{conversationApplied:o}:{}})):console.log(t===`conversations`&&!o?` configuration saved; live conversation consent could not be confirmed. Restart the agent if it is running.`:s?o?` conversation consent applied; other saved settings still need an agent restart`:` configuration saved; the running agent must be restarted`:` conversation consent saved and applied to the running agent`)});function Uu(e,t,n=console.log,r=e=>{process.exitCode=e}){let i=Rn(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 Wu(e,t={}){e.command(`doctor`).description(`check Shellbell, the relay and terminals without changing anything`).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=>!Ie.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=Ie.filter(e=>i.has(e)),o=t.env??process.env,s;try{s=await(t.runDoctor??Mn)({requestedStateDir:o.SHELLBELL_DIR,defaultStateDir:t.defaultStateDir??I(N(),`.shellbell`),requiredBackends:a,env:o,version:Z})}catch{s=[{name:`doctor`,ok:!1,severity:`error`,detail:`diagnostic inspection failed`}]}Uu(s,r)})}Wu(Q),Ll(Q);function Gu(e,t,n=mr){if(!e)return!1;let r;try{r=n(e)}catch{r=e}let i=Tr(t),a;try{a=n(i)}catch{a=i}return a===r}Gu(process.argv[1],import.meta.url)&&Q.parseAsync().catch(e=>{e instanceof Error&&!Q.opts().verbose?console.error(` ${e.message.replace(/^shellbell: /,``)}`):console.error(e),process.exit(1)});export{Ae as CONFIG_KEYS,Du as IN_THIS_WINDOW,Wu as addDoctorCommand,Tu as buildAgent,Su as chooseConfirm,Vu as connectTerminalCommand,Bu as iTermSetupReport,Gu as isEntryPoint,vu as pairValidUntil,Uu as printDoctorResult,Q as program,Tt as resolveConfigSet,wu as resolveRelayOverride,Cu as shutdown,xu as socketAlive,bu as tailFile,ne as validateRelayUrl};
@@ -1,4 +1,4 @@
1
- import{$ as e,D as t,Dt as n,Et as r,Ft as i,I as a,It as o,Jt as s,Mt as c,Nt as l,P as u,Pt as d,Q as f,Qn as p,Qt as m,St as h,Xt as g,_n as _,a as v,at as y,c as b,f as ee,gn as te,gt as x,ht as ne,it as re,j as ie,jt as S,kt as ae,lr as C,o as w,qt as oe,r as se,rt as T,s as ce,st as le,tt as ue,yt as de,z as fe}from"./service-lifecycle-CSQmtvfk.js";import{execFile as pe,execFileSync as me,spawn as he}from"node:child_process";import{accessSync as ge,chmodSync as _e,closeSync as ve,constants as E,existsSync as D,fsyncSync as ye,linkSync as be,mkdirSync as xe,openSync as Se,readFileSync as O,readSync as Ce,readdirSync as we,readlinkSync as Te,realpathSync as Ee,renameSync as De,rmSync as Oe,statSync as k,statfsSync as ke,symlinkSync as Ae,unlinkSync as je,writeFileSync as Me}from"node:fs";import{homedir as A}from"node:os";import{basename as j,delimiter as Ne,dirname as M,isAbsolute as N,join as P,normalize as Pe,relative as Fe,resolve as Ie,sep as Le}from"node:path";import{z as Re}from"zod";import{createHash as ze,randomUUID as F}from"node:crypto";import{EventEmitter as Be}from"node:events";import{connect as Ve}from"node:net";import He from"ws";import{isDeepStrictEqual as Ue,promisify as We}from"node:util";import{StringDecoder as Ge}from"node:string_decoder";import{create as Ke,fromBinary as qe,toBinary as Je}from"@bufbuild/protobuf";import{fileDesc as Ye,messageDesc as I}from"@bufbuild/protobuf/codegenv2";import{performance as Xe}from"node:perf_hooks";const Ze=[[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]],Qe=[[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 $e(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 et(e){return e===0||e<32||e>=127&&e<160||$e(e,Ze)?0:$e(e,Qe)?2:1}function tt(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=et(e);if(a!==0||n){if(n){r=Math.max(r,a),n=!1;continue}t+=r,r=a}}return t+r}function nt(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=tt(e);return a!==oe(e)&&(n.n=a),n}function L(e){return Math.max(0,Math.min(255,e|0))}function rt(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:L(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:[L(e[0]),L(e[1]),L(e[2])],consumed:0}}return{consumed:0}}let r=e[t+1]?.[0];return r===5&&e[t+2]?{color:L(e[t+2]?.[0]??0),consumed:2}:r===2&&e[t+4]?{color:[L(e[t+2]?.[0]??0),L(e[t+3]?.[0]??0),L(e[t+4]?.[0]??0)],consumed:4}:{consumed:0}}function it(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}=rt(r,e);i!==void 0&&(t===38?n.fg=i:n.bg=i),e+=a}}return n}function at(e){return st(e,{}).line}function ot(e){let t={};return e.map(e=>{let n=st(e,t);return t=n.style,n.line})}function st(e,t){let n=[],r=t,i=``,a=0,o=()=>{i&&n.push(nt(i,r)),i=``},s=0;for(;s<e.length;){let t=e[s];if(t===`\x1B`){let n=e[s+1];if(n===`[`){let n=s+2,a=``;for(;n<e.length&&n-(s+2)<32;){let t=e.charCodeAt(n);if(t>=64&&t<=126)break;a+=e[n],n++}if(n>=e.length||n-(s+2)>=32){i+=t,s++;continue}e[n]===`m`&&(o(),r=it(r,a)),s=n+1;continue}if(n===`]`){let t=s+2;for(;t<e.length&&e[t]!==`\x07`&&(e[t]!==`\x1B`||e[t+1]!==`\\`);)t++;s=e[t]===`\x07`?t+1:t+2;continue}s+=n===void 0?1:2,(n===`(`||n===`)`)&&(s+=1);continue}let n=e.charCodeAt(s);if(t===` `){let e=8-a%8;i+=` `.repeat(e),a+=e,s++;continue}if(n<32||n===127){s++;continue}let c=e.codePointAt(s);i+=String.fromCodePoint(c),a+=et(c),s+=c>65535?2:1}return o(),{line:{r:m(g(n))},style:r}}function ct(e){return e.issue!==void 0&&[`needs-consent`,`automation-denied`,`iterm2-denied`,`timed-out`,`too-old`,`failed`,`limited`].includes(e.issue)}const lt={iterm2:`iTerm2`,tmux:`tmux`,herdr:`Herdr`};function ut(e,t,n={}){let r=lt[e.name]??e.name;if(e.connected&&!e.issue)return{status:`Connected. Ready for your paired phone.`};if(t===`phone`)return ct(e)?{status:`${r} needs one more step on your Mac.`,fix:`Open Shellbell → Settings → Terminals on that Mac, or run shellbell doctor there.`}:{status:`${r} isn't connected right now.`};let i=t===`mac-app`?`Click Connect iTerm2.`:`Run shellbell connect iterm2.`;switch(e.issue){case`not-installed`:return{status:n.noneUsable?`Shellbell couldn't find ${r}.`:`Shellbell couldn't find ${r}. 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:`${r} 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:`${i} 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 ${i.charAt(0).toLowerCase()}${i.slice(1)}`};case`timed-out`:return{status:`Connecting wasn't finished.`,fix:`Check for an open macOS or iTerm2 dialog, then try again. ${i}`};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 ${r} 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 ${r}.`,fix:e.name===`iterm2`?`Try again. ${i}`:`Shellbell keeps trying.`}}}const dt=[`iterm2`,`tmux`,`herdr`];function ft(e){return!e.some(e=>e.connected)&&dt.every(t=>{let n=e.find(e=>e.name===t);return n!==void 0&&!n.connected&&n.issue===`not-installed`})}function pt(e){let t=`Apple's Terminal only lets other apps see plain text and type whole lines, which isn't enough to use a terminal from your phone, so Shellbell can't use it by itself.`;if(e===`phone`)return{status:`Your Mac needs iTerm2, tmux or Herdr.`,fix:`${t} Install one on your Mac. iTerm2 is the easiest.`};let n=`iTerm2 is the easiest: your phone sees every tab and can open new ones. With tmux or Herdr, sessions you run inside them show on your phone, in Terminal too.`;return{status:`Shellbell needs iTerm2, tmux or Herdr on this Mac.`,fix:e===`command-line`?`${t} ${n} For example: brew install --cask iterm2, or brew install tmux`:`${t} ${n}`}}const mt=`\x1B[?1049l\x1B[!p\x1B[20l\x1B[?12l\x1B[?9l\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?1015l\x1B]104\x07\x1B]110\x07\x1B]111\x07\x1B]112\x07\x1B[0m\x1B[2J\x1B[H`,ht=new Set([`sh`,`bash`,`zsh`,`fish`,`dash`,`ksh`,`pwsh`,`powershell`,`cmd`]),gt=new Set([`ssh`,`mosh`,`docker`,`podman`,`kubectl`,`wsl`]);function _t(e){return j(e??``).replace(/^-/,``).replace(/\.exe$/i,``)}function vt(e,t,n){let r=_t(t),i=ht.has(r)?r:void 0,a=r===`claude`?`Claude`:r===`codex`?`Codex`:void 0,o=gt.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 R(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 yt(e,t){return[...[`Desktop`,`Documents`,`Downloads`].map(e=>P(t,e)),P(t,`Library`,`Mobile Documents`),P(t,`Library`,`CloudStorage`),`/Volumes`].some(t=>{let n=Fe(t,e);return n===``||!n.startsWith(`..${Le}`)&&n!==`..`&&!N(n)})}function bt(e={}){let t=e.now??Date.now,n=e.platform??process.platform,r=e.home??A(),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)=>{pe(`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(!N(e)||e.length>1024||a.aborted||n===`darwin`&&yt(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=R(j(t),256);if(!r)return;let a={repository:r,branch:R(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 xt(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&&N(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:R(t.computerName,128)??`Computer`,sessionLabel:R(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=R(e[t],n);r&&(c[t]=r)}let l=R(i?.repository,256),u=R(i?.branch,256);if(l&&(c.repository=l),l&&u&&(c.branch=u),!l&&e.locality===`local`&&e.cwd&&N(e.cwd)){let t=R(e.cwd===A()?`~`:j(e.cwd),256);t&&(c.title=t)}return c}finally{clearTimeout(i),r.abort()}}function St(e,t){return e===t||!!e&&!!t&&e.agent===t.agent&&e.kind===t.kind&&e.value===t.value}const Ct={claude:[`claude`,`claude-code`,`claude code`],codex:[`codex`,`codex-cli`,`codex cli`],agy:[`agy`,`antigravity`,`antigravity-cli`],gemini:[`gemini`,`gemini-cli`],cursor:[`cursor`,`cursor-agent`],copilot:[`copilot`,`github-copilot`,`ghcs`],opencode:[`opencode`,`opencode2`,`open-code`],pi:[`pi`],omp:[`omp`],devin:[`devin`,`devin-cli`,`devin cli`],cline:[`cline`,`.cline`],mastracode:[`mastracode`,`mastra-code`,`mastra code`],kimi:[`kimi`,`kimi-code`,`kimi code`],kiro:[`kiro`,`kiro-cli`],droid:[`droid`],amp:[`amp`,`amp-local`],grok:[`grok`,`grok-build`],hermes:[`hermes`,`hermes-agent`],kilo:[`kilo`,`kilo-code`,`kilo code`],qodercli:[`qodercli`,`qoderclicn`,`qoder`,`qodercn`],qwen:[`qwen`,`qwen-code`,`qwen code`],letta:[`letta`,`letta-code`,`letta code`],maki:[`maki`],muse:[`muse`,`muse-code`,`muse-cli`]},wt=new Map(Object.entries(Ct).flatMap(([e,t])=>t.map(t=>[t,e])));function Tt(e){let t=(e??``).trim().toLowerCase().split(/[\\/]/).pop().replace(/\.(cmd|exe)$/,``);if(t)return/^muse-bin-\d/.test(t)?`muse`:wt.get(t)}const Et=`\\u2800-\\u28FF\\u25D0-\\u25D3\\u2722\\u2733\\u2736\\u273B\\u273D\\u00B7\\u2022*`,Dt=RegExp(`^[${Et}][${Et}\\uFE0F]*\\s+(?=\\S)`,`u`),Ot=/^[⠀-⣿]/u,kt=/^v?\d+(?:\.\d+)+$/;function At(e){return e.trim().replace(Dt,``)}function jt(e){let t=e?.trim()??``;return Dt.test(t)}function Mt(e){let t=e?.trim().toLowerCase()??``;return Tt(t)??R(t,32)}const Nt=/^\s*(?:Gemini CLI \(.*\)|[\u25C7\u270B\u23F2\u2726] {2}\S.*\(.*\))\s*$/u;function Pt(e,t){let n=_t(e).toLowerCase(),r=Tt(n);if(r)return r;if(n!==``&&n!==`node`&&!kt.test(n))return;if(Nt.test(t??``))return`gemini`;if(!jt(t))return;let i=t?.trim()??``;return Ot.test(i)&&/ \| [^|]+$/.test(i)?`codex`:`claude`}function Ft(e,t=A()){if(!e)return;let n=e=>e.replace(/[\\/]+$/,``);return t&&n(e)===n(t)?`~`:R(n(e).split(/[\\/]/).pop(),128)}const It=new Set([...ht,...Ct.claude,...Ct.codex,...Ct.agy,`node`,`tmux`,`[tmux]`]);function Lt(e,t){let n=e.trim();if(n&&n!==t&&!n.endsWith(`[dead]`)&&!(It.has(n.toLowerCase())||kt.test(n)))return R(n,128)}function Rt(e){let t=_t(e).toLowerCase();return!t||gt.has(t)?!1:ht.has(t)||Tt(t)!==void 0||t===`node`||kt.test(t)}function zt(e,t,n){if(!e)return;let r=At(e.replace(/[\r\n\t]+/g,` `));if(t===`gemini`&&Nt.test(r))return;if(t===`pi`&&/^\s*π\s+-\s+/u.test(r)){r=r.replace(/^\s*π\s+-\s+/u,``);for(let e of[n.folder,n.project])e&&(r===e||r.endsWith(` - ${e}`))&&(r=r.slice(0,r.length-e.length).replace(/\s+-\s*$/,``))}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=R(r,256);if(!a)return;let o=a.toLowerCase();if(!(o===t.toLowerCase()||Tt(o))&&!(n.ignore??[]).some(e=>e.toLowerCase()===o))return a}function Bt(e,t){return e.project===t.project&&e.agent?.kind===t.agent?.kind&&e.agent?.task===t.agent?.task}function Vt(e,t,n){let r={};return e&&(r.project=e),t&&(r.agent=n?{kind:t,task:n}:{kind:t}),r}function Ht(e){let t=Ft(e.cwd),n=R(e.project,128)??t,r=Pt(e.processName,e.title);if(!r)return Vt(n,void 0);let i=_t(e.processName);return Vt(n,r,zt(e.title,r,{project:n,folder:t,command:i||void 0,ignore:e.ignore}))}function Ut(e,t){let n=Ft(e.foreground_cwd??e.cwd??void 0),r=R(t,128)??n,i=Mt(e.agent||e.display_agent||void 0);return i?Vt(r,i,zt(e.label||e.terminal_title_stripped||e.terminal_title||void 0,i,{project:r,folder:n,ignore:e.display_agent?[e.display_agent]:[]})):Vt(r,void 0)}var Wt=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(!N(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=R(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 Gt(e,t=te){let n=e=>C({type:`sessions`,list:e,complete:!1}).length<=t,r=({agent:e,stateSince:t,activeAt:n,...r})=>e?{...r,agent:{kind:e.kind,...e.reportsState&&{reportsState:!0}}}:r,i=[r,e=>{let{project:t,windowLabel:n,...i}=r(e);return i},e=>{let{project:t,windowLabel:n,cwd:i,title:a,...o}=r(e);return{...o,title:Array.from(a).slice(0,Kt).join(``)}}];if(n(e))return{type:`sessions`,list:e,complete:!0};let a=e;for(let t of i)if(a=e.map(t),n(a))return{type:`sessions`,list:a,complete:!0};let o=0,s=a.length;for(;o<s;){let e=Math.ceil((o+s)/2);n(a.slice(0,e))?o=e:s=e-1}return{type:`sessions`,list:a.slice(0,o),complete:!1}}const Kt=64,qt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Jt=/^\d{1,12}-\d{1,10}\.rec$/;function Yt(e=ne().dir,t=process.platform){return t===`linux`?`${e}-agents`:e}function Xt(e,t){return P(e,`${t}-sessions`)}function Zt(e,t=ne().dir){return Xt(Yt(t),e)}const Qt=e=>new Map(e.map(e=>[e.slice(0,e.indexOf(`=`)),e.slice(e.indexOf(`=`)+1)]));function $t(e){return!e.startsWith(`/`)||e.length>4096||/[\u0000-\u001f\u007f]/.test(e)||e.split(`/`).some(e=>e===`.`||e===`..`)||e.includes(`//`)?``:e}function en(e,t){let n=t.startsWith(`shellbell-codex-hook 1
1
+ import{$ as e,D as t,Dt as n,Et as r,Ft as i,I as a,It as o,Jt as s,Mt as c,Nt as l,P as u,Pt as d,Q as f,Qn as p,Qt as m,St as h,Xt as g,_n as _,a as v,at as y,c as b,f as ee,gn as te,gt as x,ht as ne,it as re,j as ie,jt as S,kt as ae,lr as C,o as w,qt as oe,r as se,rt as T,s as ce,st as le,tt as ue,yt as de,z as fe}from"./service-lifecycle-CLWP08Es.js";import{execFile as pe,execFileSync as me,spawn as he}from"node:child_process";import{accessSync as ge,chmodSync as _e,closeSync as ve,constants as E,existsSync as D,fsyncSync as ye,linkSync as be,mkdirSync as xe,openSync as Se,readFileSync as O,readSync as Ce,readdirSync as we,readlinkSync as Te,realpathSync as Ee,renameSync as De,rmSync as Oe,statSync as k,statfsSync as ke,symlinkSync as Ae,unlinkSync as je,writeFileSync as Me}from"node:fs";import{homedir as A}from"node:os";import{basename as j,delimiter as Ne,dirname as M,isAbsolute as N,join as P,normalize as Pe,relative as Fe,resolve as Ie,sep as Le}from"node:path";import{z as Re}from"zod";import{createHash as ze,randomUUID as F}from"node:crypto";import{EventEmitter as Be}from"node:events";import{connect as Ve}from"node:net";import He from"ws";import{isDeepStrictEqual as Ue,promisify as We}from"node:util";import{StringDecoder as Ge}from"node:string_decoder";import{create as Ke,fromBinary as qe,toBinary as Je}from"@bufbuild/protobuf";import{fileDesc as Ye,messageDesc as I}from"@bufbuild/protobuf/codegenv2";import{performance as Xe}from"node:perf_hooks";const Ze=[[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]],Qe=[[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 $e(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 et(e){return e===0||e<32||e>=127&&e<160||$e(e,Ze)?0:$e(e,Qe)?2:1}function tt(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=et(e);if(a!==0||n){if(n){r=Math.max(r,a),n=!1;continue}t+=r,r=a}}return t+r}function nt(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=tt(e);return a!==oe(e)&&(n.n=a),n}function L(e){return Math.max(0,Math.min(255,e|0))}function rt(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:L(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:[L(e[0]),L(e[1]),L(e[2])],consumed:0}}return{consumed:0}}let r=e[t+1]?.[0];return r===5&&e[t+2]?{color:L(e[t+2]?.[0]??0),consumed:2}:r===2&&e[t+4]?{color:[L(e[t+2]?.[0]??0),L(e[t+3]?.[0]??0),L(e[t+4]?.[0]??0)],consumed:4}:{consumed:0}}function it(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}=rt(r,e);i!==void 0&&(t===38?n.fg=i:n.bg=i),e+=a}}return n}function at(e){return st(e,{}).line}function ot(e){let t={};return e.map(e=>{let n=st(e,t);return t=n.style,n.line})}function st(e,t){let n=[],r=t,i=``,a=0,o=()=>{i&&n.push(nt(i,r)),i=``},s=0;for(;s<e.length;){let t=e[s];if(t===`\x1B`){let n=e[s+1];if(n===`[`){let n=s+2,a=``;for(;n<e.length&&n-(s+2)<32;){let t=e.charCodeAt(n);if(t>=64&&t<=126)break;a+=e[n],n++}if(n>=e.length||n-(s+2)>=32){i+=t,s++;continue}e[n]===`m`&&(o(),r=it(r,a)),s=n+1;continue}if(n===`]`){let t=s+2;for(;t<e.length&&e[t]!==`\x07`&&(e[t]!==`\x1B`||e[t+1]!==`\\`);)t++;s=e[t]===`\x07`?t+1:t+2;continue}s+=n===void 0?1:2,(n===`(`||n===`)`)&&(s+=1);continue}let n=e.charCodeAt(s);if(t===` `){let e=8-a%8;i+=` `.repeat(e),a+=e,s++;continue}if(n<32||n===127){s++;continue}let c=e.codePointAt(s);i+=String.fromCodePoint(c),a+=et(c),s+=c>65535?2:1}return o(),{line:{r:m(g(n))},style:r}}function ct(e){return e.issue!==void 0&&[`needs-consent`,`automation-denied`,`iterm2-denied`,`timed-out`,`too-old`,`failed`,`limited`].includes(e.issue)}const lt={iterm2:`iTerm2`,tmux:`tmux`,herdr:`Herdr`};function ut(e,t,n={}){let r=lt[e.name]??e.name;if(e.connected&&!e.issue)return{status:`Connected. Ready for your paired phone.`};if(t===`phone`)return ct(e)?{status:`${r} needs one more step on your Mac.`,fix:`Open Shellbell → Settings → Terminals on that Mac, or run shellbell doctor there.`}:{status:`${r} isn't connected right now.`};let i=t===`mac-app`?`Click Connect iTerm2.`:`Run shellbell connect iterm2.`;switch(e.issue){case`not-installed`:return{status:n.noneUsable?`Shellbell couldn't find ${r}.`:`Shellbell couldn't find ${r}. 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:`${r} 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:`${i} 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 ${i.charAt(0).toLowerCase()}${i.slice(1)}`};case`timed-out`:return{status:`Connecting wasn't finished.`,fix:`Check for an open macOS or iTerm2 dialog, then try again. ${i}`};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 ${r} 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 ${r}.`,fix:e.name===`iterm2`?`Try again. ${i}`:`Shellbell keeps trying.`}}}const dt=[`iterm2`,`tmux`,`herdr`];function ft(e){return!e.some(e=>e.connected)&&dt.every(t=>{let n=e.find(e=>e.name===t);return n!==void 0&&!n.connected&&n.issue===`not-installed`})}function pt(e){let t=`Apple's Terminal only lets other apps see plain text and type whole lines, which isn't enough to use a terminal from your phone, so Shellbell can't use it by itself.`;if(e===`phone`)return{status:`Your Mac needs iTerm2, tmux or Herdr.`,fix:`${t} Install one on your Mac. iTerm2 is the easiest.`};let n=`iTerm2 is the easiest: your phone sees every tab and can open new ones. With tmux or Herdr, sessions you run inside them show on your phone, in Terminal too.`;return{status:`Shellbell needs iTerm2, tmux or Herdr on this Mac.`,fix:e===`command-line`?`${t} ${n} For example: brew install --cask iterm2, or brew install tmux`:`${t} ${n}`}}const mt=`\x1B[?1049l\x1B[!p\x1B[20l\x1B[?12l\x1B[?9l\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?1015l\x1B]104\x07\x1B]110\x07\x1B]111\x07\x1B]112\x07\x1B[0m\x1B[2J\x1B[H`,ht=new Set([`sh`,`bash`,`zsh`,`fish`,`dash`,`ksh`,`pwsh`,`powershell`,`cmd`]),gt=new Set([`ssh`,`mosh`,`docker`,`podman`,`kubectl`,`wsl`]);function _t(e){return j(e??``).replace(/^-/,``).replace(/\.exe$/i,``)}function vt(e,t,n){let r=_t(t),i=ht.has(r)?r:void 0,a=r===`claude`?`Claude`:r===`codex`?`Codex`:void 0,o=gt.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 R(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 yt(e,t){return[...[`Desktop`,`Documents`,`Downloads`].map(e=>P(t,e)),P(t,`Library`,`Mobile Documents`),P(t,`Library`,`CloudStorage`),`/Volumes`].some(t=>{let n=Fe(t,e);return n===``||!n.startsWith(`..${Le}`)&&n!==`..`&&!N(n)})}function bt(e={}){let t=e.now??Date.now,n=e.platform??process.platform,r=e.home??A(),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)=>{pe(`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(!N(e)||e.length>1024||a.aborted||n===`darwin`&&yt(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=R(j(t),256);if(!r)return;let a={repository:r,branch:R(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 xt(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&&N(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:R(t.computerName,128)??`Computer`,sessionLabel:R(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=R(e[t],n);r&&(c[t]=r)}let l=R(i?.repository,256),u=R(i?.branch,256);if(l&&(c.repository=l),l&&u&&(c.branch=u),!l&&e.locality===`local`&&e.cwd&&N(e.cwd)){let t=R(e.cwd===A()?`~`:j(e.cwd),256);t&&(c.title=t)}return c}finally{clearTimeout(i),r.abort()}}function St(e,t){return e===t||!!e&&!!t&&e.agent===t.agent&&e.kind===t.kind&&e.value===t.value}const Ct={claude:[`claude`,`claude-code`,`claude code`],codex:[`codex`,`codex-cli`,`codex cli`],agy:[`agy`,`antigravity`,`antigravity-cli`],gemini:[`gemini`,`gemini-cli`],cursor:[`cursor`,`cursor-agent`],copilot:[`copilot`,`github-copilot`,`ghcs`],opencode:[`opencode`,`opencode2`,`open-code`],pi:[`pi`],omp:[`omp`],devin:[`devin`,`devin-cli`,`devin cli`],cline:[`cline`,`.cline`],mastracode:[`mastracode`,`mastra-code`,`mastra code`],kimi:[`kimi`,`kimi-code`,`kimi code`],kiro:[`kiro`,`kiro-cli`],droid:[`droid`],amp:[`amp`,`amp-local`],grok:[`grok`,`grok-build`],hermes:[`hermes`,`hermes-agent`],kilo:[`kilo`,`kilo-code`,`kilo code`],qodercli:[`qodercli`,`qoderclicn`,`qoder`,`qodercn`],qwen:[`qwen`,`qwen-code`,`qwen code`],letta:[`letta`,`letta-code`,`letta code`],maki:[`maki`],muse:[`muse`,`muse-code`,`muse-cli`]},wt=new Map(Object.entries(Ct).flatMap(([e,t])=>t.map(t=>[t,e])));function Tt(e){let t=(e??``).trim().toLowerCase().split(/[\\/]/).pop().replace(/\.(cmd|exe)$/,``);if(t)return/^muse-bin-\d/.test(t)?`muse`:wt.get(t)}const Et=`\\u2800-\\u28FF\\u25D0-\\u25D3\\u2722\\u2733\\u2736\\u273B\\u273D\\u00B7\\u2022*`,Dt=RegExp(`^[${Et}][${Et}\\uFE0F]*\\s+(?=\\S)`,`u`),Ot=/^[⠀-⣿]/u,kt=/^v?\d+(?:\.\d+)+$/;function At(e){return e.trim().replace(Dt,``)}function jt(e){let t=e?.trim()??``;return Dt.test(t)}function Mt(e){let t=e?.trim().toLowerCase()??``;return Tt(t)??R(t,32)}const Nt=/^\s*(?:Gemini CLI \(.*\)|[\u25C7\u270B\u23F2\u2726] {2}\S.*\(.*\))\s*$/u;function Pt(e,t){let n=_t(e).toLowerCase(),r=Tt(n);if(r)return r;if(n!==``&&n!==`node`&&!kt.test(n))return;if(Nt.test(t??``))return`gemini`;if(!jt(t))return;let i=t?.trim()??``;return Ot.test(i)&&/ \| [^|]+$/.test(i)?`codex`:`claude`}function Ft(e,t=A()){if(!e)return;let n=e=>e.replace(/[\\/]+$/,``);return t&&n(e)===n(t)?`~`:R(n(e).split(/[\\/]/).pop(),128)}const It=new Set([...ht,...Ct.claude,...Ct.codex,...Ct.agy,`node`,`tmux`,`[tmux]`]);function Lt(e,t){let n=e.trim();if(n&&n!==t&&!n.endsWith(`[dead]`)&&!(It.has(n.toLowerCase())||kt.test(n)))return R(n,128)}function Rt(e){let t=_t(e).toLowerCase();return!t||gt.has(t)?!1:ht.has(t)||Tt(t)!==void 0||t===`node`||kt.test(t)}function zt(e,t,n){if(!e)return;let r=At(e.replace(/[\r\n\t]+/g,` `));if(t===`gemini`&&Nt.test(r))return;if(t===`pi`&&/^\s*π\s+-\s+/u.test(r)){r=r.replace(/^\s*π\s+-\s+/u,``);for(let e of[n.folder,n.project])e&&(r===e||r.endsWith(` - ${e}`))&&(r=r.slice(0,r.length-e.length).replace(/\s+-\s*$/,``))}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=R(r,256);if(!a)return;let o=a.toLowerCase();if(!(o===t.toLowerCase()||Tt(o))&&!(n.ignore??[]).some(e=>e.toLowerCase()===o))return a}function Bt(e,t){return e.project===t.project&&e.agent?.kind===t.agent?.kind&&e.agent?.task===t.agent?.task}function Vt(e,t,n){let r={};return e&&(r.project=e),t&&(r.agent=n?{kind:t,task:n}:{kind:t}),r}function Ht(e){let t=Ft(e.cwd),n=R(e.project,128)??t,r=Pt(e.processName,e.title);if(!r)return Vt(n,void 0);let i=_t(e.processName);return Vt(n,r,zt(e.title,r,{project:n,folder:t,command:i||void 0,ignore:e.ignore}))}function Ut(e,t){let n=Ft(e.foreground_cwd??e.cwd??void 0),r=R(t,128)??n,i=Mt(e.agent||e.display_agent||void 0);return i?Vt(r,i,zt(e.label||e.terminal_title_stripped||e.terminal_title||void 0,i,{project:r,folder:n,ignore:e.display_agent?[e.display_agent]:[]})):Vt(r,void 0)}var Wt=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(!N(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=R(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 Gt(e,t=te){let n=e=>C({type:`sessions`,list:e,complete:!1}).length<=t,r=({agent:e,stateSince:t,activeAt:n,...r})=>e?{...r,agent:{kind:e.kind,...e.reportsState&&{reportsState:!0}}}:r,i=[r,e=>{let{project:t,windowLabel:n,...i}=r(e);return i},e=>{let{project:t,windowLabel:n,cwd:i,title:a,...o}=r(e);return{...o,title:Array.from(a).slice(0,Kt).join(``)}}];if(n(e))return{type:`sessions`,list:e,complete:!0};let a=e;for(let t of i)if(a=e.map(t),n(a))return{type:`sessions`,list:a,complete:!0};let o=0,s=a.length;for(;o<s;){let e=Math.ceil((o+s)/2);n(a.slice(0,e))?o=e:s=e-1}return{type:`sessions`,list:a.slice(0,o),complete:!1}}const Kt=64,qt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Jt=/^\d{1,12}-\d{1,10}\.rec$/;function Yt(e=ne().dir,t=process.platform){return t===`linux`?`${e}-agents`:e}function Xt(e,t){return P(e,`${t}-sessions`)}function Zt(e,t=ne().dir){return Xt(Yt(t),e)}const Qt=e=>new Map(e.map(e=>[e.slice(0,e.indexOf(`=`)),e.slice(e.indexOf(`=`)+1)]));function $t(e){return!e.startsWith(`/`)||e.length>4096||/[\u0000-\u001f\u007f]/.test(e)||e.split(`/`).some(e=>e===`.`||e===`..`)||e.includes(`//`)?``:e}function en(e,t){let n=t.startsWith(`shellbell-codex-hook 1
2
2
  `),r=n?t.indexOf(`
3
3
 
4
4
  `):t.length;if(r<0)return null;let[i,...a]=t.slice(0,r).replace(/\n+$/,``).split(`