shellbell 0.15.0 → 0.15.1

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.
@@ -13,10 +13,10 @@ const ps=BigInt(0),ms=BigInt(1),hs=BigInt(2),gs=BigInt(4),_s=BigInt(8);function
13
13
  const xs=BigInt(0),Ss=BigInt(1),Cs=BigInt(2);function ws(e,t){return e+t-(t>>Ss<<Ss)}function Ts(e){let t=BigInt(6)*e;return(n,r,i)=>{let a=r+i,o=((t+i-r)*n+r)%e;return{x_2:o,x_3:a-o}}}function Es(e){return mo(e,{P:`bigint`,type:`string`,adjustScalarBytes:`function`,powPminus2:`function`},{randomBytes:`function`,scalarMultBase:`function`}),Object.freeze({...e})}function Ds(e){let t=Es(e),{P:n,type:r,adjustScalarBytes:i,powPminus2:a,randomBytes:o}=t,s=t.scalarMultBase,c=r===`x25519`;if(!c&&r!==`x448`)throw Error(`invalid type`);let l=o===void 0?Ya:o,u=c?255:448,d=Ts(n),f=c?32:56,p=BigInt(c?9:5),m=BigInt(c?121665:39081),h=c?Cs**BigInt(254):Cs**BigInt(447),g=h+(c?BigInt(8)*(Cs**BigInt(251)-Ss):BigInt(4)*(Cs**BigInt(445)-Ss))+Ss,_=e=>J(e,n),v=y(p);function y(e){return oo(_(e),f)}function b(e){let t=so(Va(e,f,`uCoordinate`));return c&&(t[31]&=127),_(io(t))}function ee(e){return io(i(so(Va(e,f,`scalar`))))}let x=new Set(c?[xs,Ss,n-Ss,BigInt(`325606250916557431795983626356110631294008115727848805560023387167927233504`),BigInt(`39382357235489614581723060781553021112529911719440698176882885853963445705823`)]:[xs,Ss,n-Ss]);function S(e,t){let n=b(t);if(x.has(n))throw Error(`invalid private or public key received`);let r=E(n,ee(e));if(r===xs)throw Error(`invalid private or public key received`);return y(r)}function C(e){if(s===void 0)return S(e,v);let t=ee(e);uo(`scalar`,t,h,g);let n=_(s(t));if(n===xs)throw Error(`invalid private or public key received`);return y(n)}let w=C,T=S;function E(e,t){uo(`u`,e,xs,n),uo(`scalar`,t,h,g);let r=t,i=e,o=Ss,s=xs,c=e,l=Ss,f=r^r>>Ss;for(let e=BigInt(u-1);e>=xs;e--){let t=ws(n,f>>e);({x_2:o,x_3:c}=d(t,o,c)),{x_2:s,x_3:l}=d(t,s,l);let r=o+s,a=_(r*r),u=o-s,p=_(u*u),h=a-p,g=c+l,v=c-l,y=_(v*r),b=_(g*u),ee=y+b,x=y-b;c=_(ee*ee),l=_(i*_(x*x)),o=_(a*p),s=_(h*(a+_(m*h)))}let p=ws(n,r);({x_2:o,x_3:c}=d(p,o,c)),{x_2:s,x_3:l}=d(p,s,l);let v=a(s);return _(o*v)}let D={secretKey:f,publicKey:f,seed:f},O=e=>(e=e===void 0?l(f):e,Va(e,D.seed,`seed`),e),k={randomSecretKey:O};return Object.freeze(D),Object.freeze(k),Object.freeze({keygen:fs(O,w),getSharedSecret:T,getPublicKey:w,scalarMult:S,scalarMultBase:C,utils:k,GuBytes:v.slice(),lengths:D})}
14
14
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
15
15
  const Os=BigInt(0),ks=BigInt(1),As=BigInt(2),js=BigInt(3),Ms=BigInt(5),Ns=BigInt(8),Ps=BigInt(`0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed`),Fs={p:Ps,n:BigInt(`0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed`),h:Ns,a:BigInt(`0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec`),d:BigInt(`0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3`),Gx:BigInt(`0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a`),Gy:BigInt(`0x6666666666666666666666666666666666666666666666666666666666666658`)};function Is(e){let t=BigInt(10),n=BigInt(20),r=BigInt(40),i=BigInt(80),a=Ps,o=e*e%a*e%a,s=Do(Do(o,As,a)*o%a,ks,a)*e%a,c=Do(s,Ms,a)*s%a,l=Do(c,t,a)*c%a,u=Do(l,n,a)*l%a,d=Do(u,r,a)*u%a;return{pow_p_5_8:Do(Do(Do(Do(d,i,a)*d%a,i,a)*d%a,t,a)*c%a,As,a)*e%a,b2:o}}function Ls(e){return e[0]&=248,e[31]&=127,e[31]|=64,e}const Rs=BigInt(`19681161376707505956807079304988542015446066515923890162744021073123829784752`);function zs(e,t){let n=Ps,r=J(t*t*t,n),i=Is(e*J(r*r*t,n)).pow_p_5_8,a=J(e*r*i,n),o=J(t*a*a,n),s=a,c=J(a*Rs,n),l=o===e,u=o===J(-e,n),d=o===J(-e*Rs,n);return l&&(a=s),(u||d)&&(a=c),Io(a,n)&&(a=J(-a,n)),{isValid:l||u,value:a}}const Bs=ys(Fs,{uvRatio:zs}),Vs=Bs.Fp;function Hs(e){let{y:t}=e;return Vs.toBytes(Vs.div(ks+t,ks-t))}function Us(e){let t=Bs.Fp.BYTES;return ra(e,t),Ls(za(e.subarray(0,t))).subarray(0,t)}function Ws(e){return bs(Bs,za,Object.assign({adjustScalarBytes:Ls,toMontgomery:Hs,toMontgomerySecret:Us,zip215:!0},e))}const Gs=Ws({}),Ks=(()=>{let e=Ps,t=t=>{let{pow_p_5_8:n,b2:r}=Is(t);return J(Do(n,js,e)*r,e)};return Ds({P:e,type:`x25519`,powPminus2:t,adjustScalarBytes:Ls,scalarMultBase:n=>{let r=J(n,Bs.Fn.ORDER);if(r===Os)return Os;let i=Bs.BASE.multiply(r);return J((i.Z+i.Y)*t(J(i.Z-i.Y,e)),e)}})})();var qs=class{oHash;iHash;blockLen;outputLen;canXOF=!1;finished=!1;destroyed=!1;constructor(e,t){if(ia(e),ra(t,void 0,`key`),this.iHash=e.create(),typeof this.iHash.update!=`function`)throw Error(`expected Hash instance`);this.blockLen=this.iHash.blockLen,this.outputLen=this.iHash.outputLen;let n=this.blockLen,r=new Uint8Array(n);r.set(t.length>n?e.create().update(t).digest():t);for(let e=0;e<r.length;e++)r[e]^=54;this.iHash.update(r),this.oHash=e.create();for(let e=0;e<r.length;e++)r[e]^=106;this.oHash.update(r),la(r)}update(e){return sa(this),this.iHash.update(e),this}digestInto(e){sa(this),ca(e,this),this.finished=!0;let t=e.subarray(0,this.outputLen);this.iHash.digestInto(t),this.oHash.update(t),this.oHash.digestInto(t),this.destroy()}digest(){let e=new Uint8Array(this.oHash.outputLen);return this.digestInto(e),e}_cloneInto(e){e||=Object.create(Object.getPrototypeOf(this),{});let{oHash:t,iHash:n,finished:r,destroyed:i,blockLen:a,outputLen:o,canXOF:s}=this;return e=e,e.finished=r,e.destroyed=i,e.blockLen=a,e.outputLen=o,e.canXOF=s,e.oHash=t._cloneInto(e.oHash),e.iHash=n._cloneInto(e.iHash),e}clone(){return this._cloneInto()}destroy(){this.destroyed=!0,this.oHash.destroy(),this.iHash.destroy()}};const Js=(()=>{let e=((e,t,n)=>new qs(e,t).update(n).digest());return e.create=(e,t)=>new qs(e,t),e})(),Ys=Uint8Array.of(0),Xs=Uint8Array.of();function Zs(e,t,n,r=32,i){ia(e),na(r,`length`),ra(t,void 0,`prk`);let a=e.outputLen;if(t.length<a)throw Error(`"prk" must be at least HashLen octets`);if(r>255*a)throw Error(`Length must be <= 255*HashLen`);let o=Math.ceil(r/a);if(n===void 0?n=Xs:ra(n,void 0,`info`),!o)return i&&la(t),new Uint8Array;let s=i&&o===1?t:new Uint8Array(o*a),{iHash:c,oHash:l}=Js.create(e,t),u=i?t:new Uint8Array(a),d=o>1?i?.iHash||e.create():void 0;for(let e=0;e<o-1;e++){Ys[0]=e+1;let t=c._cloneInto(d);e&&t.update(u),t.update(n).update(Ys).digestInto(u),l._cloneInto(d).update(u).digestInto(u),s.set(u,a*e)}if(Ys[0]=o,o>1&&c.update(u),c.update(n).update(Ys).digestInto(u),l.update(u).digestInto(u),s.set(u,a*(o-1)),c.destroy(),l.destroy(),d?.destroy(),u!==s&&la(u),la(Ys),r===s.length)return s;let f=s.slice(0,r);return la(s),f}const Qs=(e,t,n,r,i)=>{ia(e),n===void 0&&(n=new Uint8Array(e.outputLen));let a=Js.create(e,n).update(t);return Zs(e,a.digest(),r,i,a)};function $s(){return ec(ba(32),ba(32),new Date().toISOString())}function ec(e,t,n){let r=Gs.keygen(e),i=Ks.keygen(t);return{ed25519:{pub:r.publicKey,priv:r.secretKey},x25519:{pub:i.publicKey,priv:i.secretKey},createdAt:n}}const tc=F.object({v:F.literal(1),ed25519:F.object({pub:F.string(),priv:F.string()}),x25519:F.object({pub:F.string(),priv:F.string()}),createdAt:F.string()});function nc(e){return{v:1,ed25519:{pub:br(e.ed25519.pub),priv:br(e.ed25519.priv)},x25519:{pub:br(e.x25519.pub),priv:br(e.x25519.priv)},createdAt:e.createdAt}}function rc(e){let t=tc.safeParse(e);if(!t.success)throw new V(`malformed`,`identity: ${F.prettifyError(t.error)}`);let n=t.data,r,i,a,o;try{r=xr(n.ed25519.pub),i=xr(n.ed25519.priv),a=xr(n.x25519.pub),o=xr(n.x25519.priv)}catch{throw new V(`malformed`,`identity: bad base64url`)}if(r.length!==32||i.length!==32||a.length!==32||o.length!==32)throw new V(`malformed`,`identity: key length`);return{ed25519:{pub:r,priv:i},x25519:{pub:a,priv:o},createdAt:n.createdAt}}function ic(e){return Sr(Ra(e)).slice(0,26)}function ac(e){return typeof e==`string`?yr(e):e}function oc(e,t){return Gs.sign(ac(t),e)}function sc(e,t,n){try{return Gs.verify(n,ac(t),e)}catch{return!1}}function cc(e,t,n,r){return`shellbell-auth-v1|${e}|${t}|${n}|${br(r)}`}function lc(e,t,n,r){return{n:t,c:Ni(e,t,yr(r)).encrypt(n)}}function uc(e,t,n){return lc(e,ba(24),t,n)}function dc(e,t,n){try{return Ni(e,t.n,yr(n)).decrypt(t.c)}catch{throw new V(`crypto`,`aead open failed`)}}function fc(e,t){return Qs(Ra,e,yr(`shellbell-pairing-v1`),yr(t),32)}function pc(e,t,n,r,i){let a=Ks.getSharedSecret(e,t);if(a.every(e=>e===0))throw new V(`crypto`,`low-order point`);return Qs(Ra,Tr(a,n),yr(`shellbell-pair-v1`),yr(`${r}|${i}`),32)}function mc(e,t,n,r,i){let a=Tr(t,n);return{kConn:Qs(Ra,e,a,yr(`shellbell-conn-v1|${r}|${i}`),32),connTag:br(Ra(a)).slice(0,22)}}function hc(e,t,n){if(e.length!==32||!/^[a-z2-7]{26}$/.test(t)||!/^[a-z2-7]{26}$/.test(n))throw new V(`malformed`,`invalid Noise PSK derivation input`);return Qs(Ra,e,yr(`shellbell-noise-v2-psk`),yr(`${t}|${n}`),32)}function gc(e,t,n,r){return`1|${e}|${t}|${n}|${r}`}function _c(e,t){return`1|${e}|${t}|hello|0`}function vc(e,t,n){return`pairing-${e}|${t}|${n}`}function yc(e,t,n,r){return`shellbell-pair-bind-v1|${e}|${t}|${n}|${br(r)}`}function bc(e){return e.match(/.{1,4}/g)?.join(` `)??e}const xc=`notify-context-v1`,Sc=`notify-instance-v1`,Cc=`shellbell-notification-v1`,wc={plaintextBytes:1536,ciphertextBytes:1552,providerBytes:3500,freshnessMs:12e4,clockSkewMs:6e4,previousGenerationMs:3e5,sessions:500,encryptions:2**20};function Tc(e,t=e){return F.string().min(Math.ceil(e*4/3)).max(Math.ceil(t*4/3)).refine(n=>{try{let r=xr(n);return r.length>=e&&r.length<=t&&br(r)===n}catch{return!1}},`invalid canonical base64url`)}const Ec=Tc(16),Dc=F.array(F.string().min(1).max(32)).max(8),Oc=F.number().int().nonnegative().max(2**53-1),kc=F.string().regex(/^[1-9][0-9]{0,19}$/).refine(e=>/^[1-9][0-9]{0,19}$/.test(e)&&BigInt(e)<=18446744073709551615n,`sequence overflow`),Ac=/[\p{Cc}\p{Cs}\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/u;function jc(e){return F.string().min(1).max(e).refine(t=>t.trim().length>0&&!Ac.test(t)&&yr(t).length<=e,`invalid notification label`)}const Mc=F.strictObject({computerName:jc(128),sessionLabel:jc(128),observedAt:Oc,customName:jc(256).optional(),repository:jc(256).optional(),branch:jc(256).optional(),title:jc(256).optional(),shell:jc(64).optional(),agentName:jc(64).optional()}),Nc=F.strictObject({computerFp:U,phoneFp:U,generation:Ec,sessionId:F.string().min(1).max(128),eventId:Tc(16)}),Pc=F.enum([`command-finished`,`prompt-returned`,`agent-finished`,`agent-blocked`,`quiet`]),Fc=Nc.extend({context:Mc,reason:Pc,exitCode:F.number().int().optional(),durationMs:Oc.optional(),instance:F.string().regex(/^[A-Za-z0-9._:-]{1,64}$/).optional(),issuedAt:Oc,expiresAt:Oc,sequence:kc}).refine(e=>e.expiresAt>e.issuedAt&&e.expiresAt-e.issuedAt<=wc.freshnessMs&&e.context.observedAt<=e.issuedAt,`invalid notification times`).refine(e=>yr(JSON.stringify(e)).length<=wc.plaintextBytes,`notification plaintext exceeds byte limit`),Ic=Nc.extend({nonce:Tc(12),ciphertext:Tc(17,wc.ciphertextBytes)});function Lc(e){return Nc.parse({computerFp:e.computerFp,phoneFp:e.phoneFp,generation:e.generation,sessionId:e.sessionId,eventId:e.eventId})}const Rc=yr(`shellbell-pair-revocation-id-v2\0`),zc=F.strictObject({v:F.literal(2),computerFp:U,phoneFp:U,pairId:H(32),signature:H(64)});function Bc(e){if(!(e instanceof Uint8Array)||e.length!==32)throw Error(`K_pair must be 32 bytes`);return Ra(Tr(Rc,e))}function Vc(e,t,n){return Gn([`shellbell-pair-revocation-v2`,e,t,n])}function Hc(e,t){if(e.length!==32||t.length!==32)return!1;let n=0;for(let r=0;r<32;r++)n|=(e[r]??0)^(t[r]??0);return n===0}function Uc(e,t){if(!Wc(e,t))return!1;try{return Hc(e.pairId,Bc(t.kPair))}catch{return!1}}function Wc(e,t){let n=zc.safeParse(e);if(!n.success)return!1;let r=n.data;if(r.computerFp!==t.computerFp||r.phoneFp!==t.phoneFp||t.phoneEd25519Pub.length!==32||ic(t.phoneEd25519Pub)!==t.phoneFp)return!1;try{return sc(t.phoneEd25519Pub,Vc(r.computerFp,r.phoneFp,r.pairId),r.signature)}catch{return!1}}const Gc=F.enum([`agent`,`phone`,`pairing`]),Kc=F.enum([`prompt`,`idle`,`exit`,`blocked`]),qc=F.enum([`bad-sig`,`not-paired`,`fp-mismatch`,`no-agent`,`no-window`,`timeout`]),Jc=F.enum([`bad-code`,`declined`,`window-closed`,`no-agent`,`too-many`]),Yc=F.string().min(1).max(64),Xc=F.string().max(256).regex(/^(stun|turns?):[\x21-\x7e]+$/,`ICE server URL must be STUN or TURN`),Zc=F.object({urls:F.array(Xc).min(1).max(8),username:F.string().min(1).max(256).optional(),credential:F.string().min(1).max(256).optional()}).strict(),Qc=F.array(Zc).max(4),$c=F.number().int().min(0).max(6048e5),el=F.string().min(1).max(64),tl=Qn;function nl(e){let t=e.environment??void 0;return e.provider===`fcm`?e.platform===`android`&&t===void 0:e.provider===`apns`&&e.platform===`ios`&&(t===`development`||t===`production`)}const rl=F.strictObject({type:F.literal(`push-token`),token:F.string().min(1).max(4096),platform:F.enum([`ios`,`android`]),provider:F.enum([`fcm`,`apns`]).optional(),environment:F.enum([`development`,`production`]).optional(),enabled:F.boolean(),features:Dc.optional()}).superRefine((e,t)=>{if(e.provider===void 0){e.token.length>256&&t.addIssue({code:`custom`,path:[`token`],message:`legacy token exceeds 256 characters`}),e.environment!==void 0&&t.addIssue({code:`custom`,path:[`environment`],message:`environment requires APNs`});return}[...e.token].some(e=>e.charCodeAt(0)>127)&&t.addIssue({code:`custom`,path:[`token`],message:`native token must be ASCII`}),!nl(e)&&(e.provider===`fcm`?(e.platform!==`android`&&t.addIssue({code:`custom`,path:[`platform`],message:`FCM requires Android`}),e.environment!==void 0&&t.addIssue({code:`custom`,path:[`environment`],message:`FCM has no environment`})):(e.platform!==`ios`&&t.addIssue({code:`custom`,path:[`platform`],message:`APNs requires iOS`}),e.environment===void 0&&t.addIssue({code:`custom`,path:[`environment`],message:`APNs requires an environment`})))}).refine(e=>e.provider===void 0?e.token.length<=256&&e.environment===void 0:![...e.token].some(e=>e.charCodeAt(0)>127)&&nl(e),{message:`invalid push-token provider, platform, environment, or token`}),il=F.object({phoneFp:U,ed25519Pub:H(32),name:Yc,pairId:H(32).optional()}),al=F.discriminatedUnion(`type`,[F.strictObject({type:F.literal(`notify-context`),sessionId:Nc.shape.sessionId,eventId:Nc.shape.eventId,kind:F.enum([`prompt`,`idle`,`blocked`]),exitCode:F.number().int().optional(),durationMs:F.number().int().nonnegative().optional(),boxes:F.array(Ic).max(10)}).refine(e=>new Set(e.boxes.map(e=>e.phoneFp)).size===e.boxes.length&&e.boxes.every(t=>t.sessionId===e.sessionId&&t.eventId===e.eventId&&t.computerFp===e.boxes[0]?.computerFp),`inconsistent notification recipients`),F.object({type:F.literal(`challenge`),nonce:H(32),connId:el}),F.object({type:F.literal(`auth`),role:Gc,fp:U,ed25519Pub:H(32),sig:H(64),name:Yc,appVersion:F.string().max(32),gate:H(16).optional(),turn:F.literal(!1).optional()}),F.object({type:F.literal(`auth-ok`),role:Gc,agentOnline:F.boolean(),computerName:F.string().max(64).nullable(),serverTime:F.number(),minFrameMs:F.number().int().min(50).max(2e3),features:Dc.optional(),iceServers:Qc.optional(),iceExpiresInMs:$c.optional(),turnOff:F.literal(!0).optional()}),F.object({type:F.literal(`auth-fail`),reason:qc}),F.object({type:F.literal(`presence`),agentOnline:F.boolean(),computerName:F.string().max(64).nullable()}),F.object({type:F.literal(`unpaired`),phoneFps:F.array(U).max(10),proofs:F.array(zc).max(10).optional()}),F.object({type:F.literal(`phones`),connected:F.array(F.object({phoneFp:U,connId:el,name:Yc})).max(10)}),F.object({type:F.literal(`pairings-sync`),phones:F.array(il).max(10)}),F.object({type:F.literal(`revocation-ack`),phoneFp:U,pairId:H(32)}),F.object({type:F.literal(`pairing-open`),gateHash:H(32),expiresAt:F.number()}),F.object({type:F.literal(`pairing-close`)}),F.object({type:F.literal(`pairing-request`),phoneFp:U,box:tl}),F.object({type:F.literal(`pairing-response`),phoneFp:U,box:tl}),F.object({type:F.literal(`pairing-reject`),phoneFp:U,reason:Jc}),F.object({type:F.literal(`pairing-add`),phoneFp:U,ed25519Pub:H(32),name:Yc,pairId:H(32).optional()}),F.object({type:F.literal(`unpair`),phoneFp:U,proof:zc.optional()}),F.object({type:F.literal(`revocation-submit`),phoneEd25519Pub:H(32),proof:zc}),F.object({type:F.literal(`revocation-receipt`),phoneFp:U,pairId:H(32),status:F.enum([`stored`,`absent`,`stale`,`unavailable`])}),rl,F.object({type:F.literal(`lease`),ttlMs:F.number().int().min(0).max(12e4)}),F.object({type:F.literal(`ice-refresh`)}),F.object({type:F.literal(`ice-servers`),iceServers:Qc,iceExpiresInMs:$c}),F.object({type:F.literal(`notify`),sessionId:F.string().min(1).max(128),kind:F.enum([`prompt`,`idle`,`blocked`]),exitCode:F.number().int().optional(),durationMs:F.number().int().nonnegative().optional()}),F.object({type:F.literal(`phone-connected`),phoneFp:U,connId:el,name:Yc}),F.object({type:F.literal(`phone-disconnected`),phoneFp:U,connId:el}),F.object({type:F.literal(`error`),code:F.string().max(64),message:F.string().max(512)})]);function ol(e){let t=al.safeParse(e);if(!t.success)throw new V(`malformed`,`ctrl: ${F.prettifyError(t.error)}`);return t.data}const sl={enter:`\r`,tab:` `,"shift-tab":`\x1B[Z`,esc:`\x1B`,backspace:``,delete:`\x1B[3~`,up:`\x1B[A`,down:`\x1B[B`,right:`\x1B[C`,left:`\x1B[D`,home:`\x1B[H`,end:`\x1B[F`,"page-up":`\x1B[5~`,"page-down":`\x1B[6~`,"ctrl-space":`\0`,...Object.fromEntries(`abcdefghijklmnopqrstuvwxyz`.split(``).map((e,t)=>[`ctrl-${e}`,String.fromCharCode(t+1)])),f1:`\x1BOP`,f2:`\x1BOQ`,f3:`\x1BOR`,f4:`\x1BOS`,f5:`\x1B[15~`,f6:`\x1B[17~`,f7:`\x1B[18~`,f8:`\x1B[19~`,f9:`\x1B[20~`,f10:`\x1B[21~`,f11:`\x1B[23~`,f12:`\x1B[24~`},cl=F.enum(Object.keys(sl));function ll(e){return sl[e]}const ul=new Uint8Array,dl=yr(`Noise_KKpsk2_25519_ChaChaPoly_SHA256`),fl=(1n<<64n)-2n,pl=65535,ml=Symbol(`Noise transport factory`);function hl(){return globalThis.process?.env?.NODE_ENV===`test`}function gl(e){if(e<0n||e>fl)throw Error(`invalid Noise sequence or reserved nonce`)}function _l(e){gl(e);let t=new Uint8Array(8);return new DataView(t.buffer).setBigUint64(0,e,!0),t}function vl(e){if(e.length!==8)throw Error(`invalid Noise sequence length`);let t=new DataView(e.buffer,e.byteOffset,8).getBigUint64(0,!0);return gl(t),t}function yl(e){let t=new Uint8Array(12);return t.set(_l(e),4),t}function bl(e,t,n){let r=Js(Ra,e,t),i=Js(Ra,r,Uint8Array.of(1)),a=Js(Ra,r,Tr(i,Uint8Array.of(2))),o=n===2?[i,a]:[i,a,Js(Ra,r,Tr(a,Uint8Array.of(3)))];return r.fill(0),o}function xl(e,t){let n=Ks.getSharedSecret(e,t);if(n.every(e=>e===0))throw Error(`invalid Noise public key`);return n}var Sl=class{chainingKey=Ra(dl);hash=this.chainingKey.slice();key=null;nonce=0n;get handshakeHash(){return this.hash.slice()}mixHash(e){this.hash=Ra(Tr(this.hash,e))}setKey(e){this.key?.fill(0),this.key=e,this.nonce=0n}mixKey(e){let[t,n]=bl(this.chainingKey,e,2);this.chainingKey.fill(0),this.chainingKey=t,this.setKey(n)}mixKeyAndHash(e){let[t,n,r]=bl(this.chainingKey,e,3);this.chainingKey.fill(0),this.chainingKey=t,this.mixHash(n),n.fill(0),this.setKey(r)}encryptAndHash(e){if(!this.key)throw Error(`Noise handshake key missing`);let t=Mi(this.key,yl(this.nonce),this.hash).encrypt(e);return this.nonce+=1n,this.mixHash(t),t}decryptAndHash(e){if(!this.key)throw Error(`Noise handshake key missing`);let t=Mi(this.key,yl(this.nonce),this.hash).decrypt(e);return this.nonce+=1n,this.mixHash(e),t}split(){let[e,t]=bl(this.chainingKey,ul,2);return this.close(),[e,t]}close(){this.chainingKey.fill(0),this.hash.fill(0),this.key?.fill(0),this.key=null}},Cl=class{sendKey;receiveKey;lastSent=-1n;lastReceived=-1n;closed=!1;constructor(e,t,n,r){if(r!==ml)throw Error(`Noise transport factory required`);this.sendKey=new Uint8Array(e===`initiator`?t:n),this.receiveKey=new Uint8Array(e===`initiator`?n:t),t.fill(0),n.fill(0)}seal(e,t,n=ul){if(this.closed)throw Error(`Noise transport closed`);if(t.length>65519)throw Error(`Noise message too large`);if(gl(e),e<=this.lastSent)throw Error(`Noise send sequence reuse`);let r=Mi(this.sendKey,yl(e),n).encrypt(t);return this.lastSent=e,r}open(e,t,n=ul){if(this.closed)throw Error(`Noise transport closed`);if(t.length<16||t.length>pl)throw Error(`Noise message length invalid`);if(gl(e),e<=this.lastReceived)throw Error(`Noise receive sequence replay`);let r=Mi(this.receiveKey,yl(e),n).decrypt(t);return this.lastReceived=e,r}close(){this.closed||(this.closed=!0,this.sendKey.fill(0),this.receiveKey.fill(0))}},wl=class{role;staticPrivate;remoteStatic;psk;ephemeralPrivate;remoteEphemeral=null;symmetric=new Sl;finalHash=null;phase=`first`;constructor(e){if(e.role!==`initiator`&&e.role!==`responder`)throw Error(`invalid Noise role`);if(e.ephemeralPrivate&&!hl())throw Error(`fixed Noise ephemeral key is test-only`);for(let t of[e.staticPrivate,e.remoteStatic,e.psk])if(t.length!==32)throw Error(`Noise key must be 32 bytes`);if(e.prologue.length>1024)throw Error(`Noise prologue too large`);if(e.ephemeralPrivate&&e.ephemeralPrivate.length!==32)throw Error(`Noise ephemeral key must be 32 bytes`);this.role=e.role,this.staticPrivate=new Uint8Array(e.staticPrivate),this.remoteStatic=new Uint8Array(e.remoteStatic),this.psk=new Uint8Array(e.psk),this.ephemeralPrivate=e.ephemeralPrivate?new Uint8Array(e.ephemeralPrivate):Ks.utils.randomSecretKey(),this.symmetric.mixHash(e.prologue);let t=Ks.getPublicKey(this.staticPrivate);this.symmetric.mixHash(this.role===`initiator`?t:this.remoteStatic),this.symmetric.mixHash(this.role===`responder`?t:this.remoteStatic)}get handshakeHash(){if(this.finalHash)return this.finalHash.slice();if(this.phase!==`complete`)throw Error(`Noise handshake not complete`);return this.symmetric.handshakeHash}write(e=ul){if(e.length>0&&!hl())throw Error(`Noise handshake payloads are test-only`);if(this.role===`initiator`&&this.phase!==`first`||this.role===`responder`&&this.phase!==`second`)throw Error(`Noise handshake message order`);if(e.length>65487)throw Error(`Noise handshake payload too large`);try{let t=Ks.getPublicKey(this.ephemeralPrivate);if(this.symmetric.mixHash(t),this.symmetric.mixKey(t),this.role===`initiator`)this.symmetric.mixKey(xl(this.ephemeralPrivate,this.remoteStatic)),this.symmetric.mixKey(xl(this.staticPrivate,this.remoteStatic));else{if(!this.remoteEphemeral)throw Error(`Noise peer ephemeral key missing`);this.symmetric.mixKey(xl(this.ephemeralPrivate,this.remoteEphemeral)),this.symmetric.mixKey(xl(this.ephemeralPrivate,this.remoteStatic)),this.symmetric.mixKeyAndHash(this.psk)}let n=Tr(t,this.symmetric.encryptAndHash(e));return this.phase=this.role===`initiator`?`second`:`complete`,n}catch(e){throw this.close(),e}}read(e){if(this.role===`responder`&&this.phase!==`first`||this.role===`initiator`&&this.phase!==`second`)throw Error(`Noise handshake message order`);if(e.length<48||e.length>pl)throw this.close(),Error(`Noise handshake message length`);if(e.length!==48&&!hl())throw this.close(),Error(`Noise handshake payloads are test-only`);try{let t=new Uint8Array(e.subarray(0,32));this.remoteEphemeral=t,this.symmetric.mixHash(t),this.symmetric.mixKey(t),this.role===`responder`?(this.symmetric.mixKey(xl(this.staticPrivate,t)),this.symmetric.mixKey(xl(this.staticPrivate,this.remoteStatic))):(this.symmetric.mixKey(xl(this.ephemeralPrivate,t)),this.symmetric.mixKey(xl(this.staticPrivate,t)),this.symmetric.mixKeyAndHash(this.psk));let n=this.symmetric.decryptAndHash(e.subarray(32));return this.phase=this.role===`responder`?`second`:`complete`,n}catch(e){throw this.close(),e}}split(){if(this.phase!==`complete`)throw Error(`Noise handshake not complete`);this.finalHash=this.symmetric.handshakeHash;let[e,t]=this.symmetric.split();return this.close(),new Cl(this.role,e,t,ml)}close(){this.phase!==`failed`&&(this.phase=`failed`,this.staticPrivate.fill(0),this.remoteStatic.fill(0),this.psk.fill(0),this.ephemeralPrivate.fill(0),this.remoteEphemeral?.fill(0),this.symmetric.close())}};const Tl=`shellbell-v2-key-confirm`,El=Symbol(`v2 handshake factory`),Dl=Symbol(`v2 session factory`),Ol=H(16).refine(e=>e.some(e=>e!==0),{message:`v2 ID must not be zero`}),kl=H(8).refine(e=>{try{return vl(e)>0n}catch{return!1}},{message:`invalid v2 route generation`}),Al={computerFp:U,phoneFp:U,sessionId:Ol,attemptId:Ol,generation:kl},jl=F.discriminatedUnion(`route`,[F.object({...Al,route:F.literal(`relay`)}).strict(),F.object({...Al,route:F.literal(`direct`),phoneDtls:H(32),computerDtls:H(32)}).strict()]),Ml=F.custom(e=>e instanceof Uint8Array&&e.length>=16&&e.length<=60016,{message:`invalid v2 ciphertext length`}),Nl=F.object({v:F.literal(2),type:F.enum([`confirm`,`data`]),sessionId:Ol,generation:kl,seq:H(8),ciphertext:Ml}).strict();function Pl(e){let t=jl.parse(e),n={...t,sessionId:new Uint8Array(t.sessionId),attemptId:new Uint8Array(t.attemptId),generation:new Uint8Array(t.generation),...t.route===`direct`&&{phoneDtls:new Uint8Array(t.phoneDtls),computerDtls:new Uint8Array(t.computerDtls)}};return jl.parse(n)}function Fl(e){let t=jl.parse(e);return Gn([`shellbell-session-v2`,2,`phone`,`computer`,t.computerFp,t.phoneFp,t.sessionId,t.attemptId,t.generation,t.route,t.route===`direct`?t.phoneDtls:null,t.route===`direct`?t.computerDtls:null])}function Il(e,t,n){return Gn([`shellbell-v2-frame`,e.sessionId,e.attemptId,e.generation,e.route,t,n.type,n.seq])}function Ll(e){return e===`phone`?`computer`:`phone`}function Rl(e){let t=Gn(Nl.parse(e));if(t.length>61e3)throw new V(`malformed`,`v2 frame too large`);return t}function zl(e){if(e.length>61e3)throw new V(`malformed`,`v2 frame too large`);return Nl.parse(Kn(e))}var Bl=class{context;role;noise;finished=!1;constructor(e,t,n,r){if(this.context=e,this.role=t,this.noise=n,r!==El)throw Error(`v2 handshake factory required`)}write(){if(this.finished)throw Error(`v2 handshake finished`);return this.noise.write()}read(e){if(this.finished)throw Error(`v2 handshake finished`);if(e.length!==48)throw Error(`v2 empty-payload handshake must be 48 bytes`);if(this.noise.read(e).length!==0)throw Error(`v2 handshake payload forbidden`)}finish(){if(this.finished)throw Error(`v2 handshake already finished`);let e=this.noise.handshakeHash,t=this.noise.split();return this.finished=!0,new Hl(this.context,this.role,t,e,Dl)}close(){this.finished=!0,this.noise.close()}};function Vl(e,t,n){if(t!==`phone`&&t!==`computer`)throw Error(`invalid v2 role`);let r=Pl(e),i=hc(n.pairKey,r.computerFp,r.phoneFp);try{return new Bl(r,t,new wl({role:t===`phone`?`initiator`:`responder`,staticPrivate:n.staticPrivate,remoteStatic:n.remoteStatic,psk:i,prologue:Fl(r)}),El)}finally{i.fill(0)}}var Hl=class{context;role;transport;handshakeHash;sentConfirmation=!1;receivedConfirmation=!1;dtlsVerified=!1;nextSequence=0n;lastReceived=-1n;closed=!1;constructor(e,t,n,r,i){if(this.context=e,this.role=t,this.transport=n,this.handshakeHash=r,i!==Dl)throw Error(`v2 session factory required`)}get ready(){return!this.closed&&this.sentConfirmation&&this.receivedConfirmation&&(this.context.route===`relay`||this.dtlsVerified)}get description(){return Pl(this.context)}get senderRole(){return this.role}verifyRemoteDtls(e){if(this.closed)throw Error(`v2 session closed`);if(this.context.route!==`direct`)throw Error(`relay route has no DTLS certificate`);let t=this.role===`phone`?this.context.computerDtls:this.context.phoneDtls;if(e.length!==32||!Er(e,t))throw this.close(),Error(`remote DTLS certificate mismatch`);this.dtlsVerified=!0}frame(e,t){if(this.closed)throw Error(`v2 session closed`);if(t.length>6e4)throw Error(`v2 data too large`);let n=_l(this.nextSequence),r={v:2,type:e,sessionId:this.context.sessionId.slice(),generation:this.context.generation.slice(),seq:n,ciphertext:new Uint8Array};return r.ciphertext=this.transport.seal(this.nextSequence,t,Il(this.context,this.role,r)),this.nextSequence+=1n,r}openFrame(e,t){if(this.closed)throw Error(`v2 session closed`);let n=Nl.parse(e);if(n.type!==t)throw Error(`wrong v2 frame type`);if(!Er(n.sessionId,this.context.sessionId)||!Er(n.generation,this.context.generation))throw Error(`wrong v2 session or route generation`);let r=vl(n.seq),i=this.transport.open(r,n.ciphertext,Il(this.context,Ll(this.role),n));if(r!==this.lastReceived+1n)throw i.fill(0),this.close(),Error(`v2 sequence gap requires resync`);return this.lastReceived=r,i}confirmation(){if(this.sentConfirmation)throw Error(`v2 confirmation already sent`);let e=this.frame(`confirm`,Gn([Tl,this.handshakeHash,this.role]));return this.sentConfirmation=!0,e}acceptConfirmation(e){try{if(this.receivedConfirmation)throw Error(`v2 confirmation already received`);if(vl(e.seq)!==0n)throw Error(`v2 confirmation sequence must be 0`);let t=Kn(this.openFrame(e,`confirm`));if(!Array.isArray(t)||t.length!==3||t[0]!==Tl||!(t[1]instanceof Uint8Array)||!Er(t[1],this.handshakeHash)||t[2]!==Ll(this.role))throw Error(`invalid v2 key confirmation`);this.receivedConfirmation=!0}catch(e){throw this.close(),e}}seal(e){if(this.closed)throw Error(`v2 session closed`);if(!this.ready)throw Error(`v2 key confirmation incomplete`);return this.frame(`data`,e)}open(e){if(this.closed)throw Error(`v2 session closed`);if(!this.ready)throw Error(`v2 key confirmation incomplete`);if(vl(e.seq)<1n)throw Error(`v2 data sequence must be positive`);return this.openFrame(e,`data`)}close(){this.closed||(this.closed=!0,this.transport.close(),this.handshakeHash.fill(0))}};const Ul=`shellbell-v2-route-payload`,Wl=59e3,Gl={terminalBytes:Wl,signalBytes:3e4,controlBytes:512,payloadBytes:6e4,attemptMs:15e3,directAttempts:32,wireSessions:128},Kl={transitionId:Ol,target:F.object({route:F.enum([`relay`,`direct`]),sessionId:Ol,attemptId:Ol,generation:kl}).strict()},ql=F.discriminatedUnion(`type`,[F.object({type:F.literal(`route.prepare`),...Kl}).strict(),F.object({type:F.literal(`route.prepared`),...Kl}).strict(),F.object({type:F.literal(`route.commit`),...Kl}).strict(),F.object({type:F.literal(`route.committed`),...Kl}).strict(),F.object({type:F.literal(`route.abort`),...Kl,reason:F.enum([`cancelled`,`timeout`,`not-ready`,`candidate-failed`])}).strict()]);function Jl(e,t){return e instanceof Uint8Array&&e.length>0&&e.length<=t}function Yl(e){let t;if(e.kind===`control`){if(t=ql.parse(e.control),Gn(t).length>Gl.controlBytes)throw new V(`malformed`)}else{if(!Jl(e.bytes,e.kind===`terminal`?Gl.terminalBytes:Gl.signalBytes))throw new V(`malformed`);t=e.bytes}let n=Gn([Ul,e.kind,t]);if(n.length>Gl.payloadBytes)throw new V(`malformed`);return n}function Xl(e){let t=hr(e,Gl.payloadBytes,{allowBytes:!0});if(!Array.isArray(t)||t.length!==3||t[0]!==Ul)throw new V(`malformed`);if(t[1]===`control`){if(Gn(t[2]).length>Gl.controlBytes)throw new V(`malformed`);let e=ql.parse(t[2]);return{kind:`control`,control:{...e,transitionId:e.transitionId.slice(),target:{route:e.target.route,sessionId:e.target.sessionId.slice(),attemptId:e.target.attemptId.slice(),generation:e.target.generation.slice()}}}}if(t[1]!==`terminal`&&t[1]!==`signal`||!Jl(t[2],t[1]===`terminal`?Gl.terminalBytes:Gl.signalBytes))throw new V(`malformed`);return{kind:t[1],bytes:t[2].slice()}}const Zl=F.enum([`iterm2`,`tmux`,`herdr`]),Ql=F.string().regex(/^[a-z][a-z0-9-]{0,31}$/),$l={iterm2:`iTerm2`,tmux:`tmux`,herdr:`Herdr`},eu=F.enum([`darwin`,`linux`,`win32`,`unknown`]),tu=F.number().int().min(0).max(255),nu=F.union([tu,F.tuple([tu,tu,tu])]),ru=F.object({t:F.string().max(4096),fg:nu.optional(),bg:nu.optional(),b:F.boolean().optional(),i:F.boolean().optional(),u:F.boolean().optional(),s:F.boolean().optional(),f:F.boolean().optional(),n:F.number().int().min(0).max(4096).optional()}),iu=F.object({r:F.array(ru).max(2048),w:F.boolean().optional()}),au=F.object({x:F.number().int(),y:F.number().int()}),ou=F.object({subscribe:F.boolean(),prompts:F.boolean(),createSession:F.boolean(),focus:F.boolean(),history:F.boolean(),absoluteLines:F.boolean(),mouseClick:F.boolean().optional(),terminalInput:F.boolean().optional(),terminalPaste:F.boolean().optional(),vtStream:F.boolean().optional()}),su=F.string().min(1).max(64).refine(e=>[...e].every(e=>e.charCodeAt(0)>=32&&e.charCodeAt(0)!==127)),cu=F.object({name:Ql,label:su,capabilities:ou,connected:F.boolean(),launchable:F.boolean()}),lu=F.array(cu).max(32).refine(e=>new Set(e.map(e=>e.name)).size===e.length,`adapter IDs must be unique`),uu=F.object({backend:Ql,host:Ql,label:su}),du=F.array(uu).max(64).refine(e=>new Set(e.map(e=>`${e.backend}:${e.host}`)).size===e.length,`launch targets must be unique`),fu=F.object({backend:Ql,reason:F.string().min(1).max(240).refine(e=>[...e].every(e=>e.charCodeAt(0)>=32&&e.charCodeAt(0)!==127))}),pu=F.array(fu).max(16).refine(e=>new Set(e.map(e=>e.backend)).size===e.length,`one launch issue per backend`),mu=F.enum([`not-installed`,`not-running`,`no-session`,`api-off`,`needs-consent`,`connecting`,`automation-denied`,`iterm2-denied`,`timed-out`,`too-old`,`limited`,`failed`]),hu=F.strictObject({name:Ql,connected:F.boolean(),issue:mu.optional(),detail:fu.shape.reason.optional()}),gu=F.array(hu).max(16).refine(e=>new Set(e.map(e=>e.name)).size===e.length),_u=[`iterm2`,`ghostty`];function vu(e,t){let n=e=>{let t=_u.indexOf(e);return t===-1?_u.length:t};return n(e)-n(t)||e.localeCompare(t)}function yu(e,t=[]){return t.filter(t=>t.backend===e).sort((e,t)=>vu(e.host,t.host))[0]}const bu=F.object({column:F.number().int().min(0).max(W.cols-1),row:F.number().int().min(0).max(W.rows-1),cols:F.number().int().min(1).max(W.cols),rows:F.number().int().min(1).max(W.rows),button:F.enum([`left`,`right`,`middle`]),modifiers:F.number().int().min(0).max(7)}),xu=F.enum([`unknown`,`editing`,`running`,`finished`,`blocked`]),Su=F.string().min(1).max(64),Cu=F.enum([`no-history`,`not-started`,`agent-exited`,`not-supported`,`lookup-limit`,`ambiguous`]),wu=F.string().min(1).max(32),Tu=F.object({state:F.enum([`finding`,`found`,`none`]),id:wu.optional(),agent:F.string().min(1).max(32).optional(),reason:Cu.optional()}).refine(e=>(e.state===`found`||e.state===`none`&&e.reason===`not-started`)==(e.id!==void 0),`A chat has an id exactly when it is found or not yet started`).refine(e=>e.reason===void 0||e.state===`none`,`Only a chat that is none has a reason`),Eu=F.object({chat:wu}),Du=F.enum([`conversation-changed`,`waiting-for-you`,`unchecked`]),Ou=F.object({id:nr,backend:Ql,title:F.string().max(256),cwd:F.string().max(1024).optional(),cols:F.number().int().positive(),rows:F.number().int().positive(),windowId:F.string().max(128),windowNumber:F.number().int(),tabId:F.string().max(128),tabIndex:F.number().int(),paneIndex:F.number().int(),isFocusedOnMac:F.boolean(),state:xu,project:F.string().min(1).max(128).optional(),windowLabel:F.string().min(1).max(128).optional(),agent:F.object({kind:F.string().min(1).max(32),task:F.string().min(1).max(256).optional(),reportsState:F.literal(!0).optional()}).optional(),stateSince:F.number().int().nonnegative().optional(),activeAt:F.number().int().nonnegative().optional(),alternateScreen:F.boolean().optional(),shownIn:F.array(su).min(1).max(4).optional(),instance:F.string().min(1).max(64).optional(),chat:Tu.optional()}),ku=Object.freeze({minCols:40,maxCols:240,minRows:24,maxRows:100}),Au=F.object({cols:F.number().int().min(ku.minCols).max(ku.maxCols),rows:F.number().int().min(ku.minRows).max(ku.maxRows)}),ju=F.union([F.object({kind:F.literal(`tab`),backend:Ql,windowId:F.string().max(128).optional(),host:Ql.optional(),initialSize:Au.optional(),near:F.literal(`focused`).optional(),explicit:F.boolean().optional()}).refine(e=>e.initialSize===void 0||e.windowId===void 0,`initial size applies only to a new independent window`).refine(e=>e.near===void 0||e.windowId===void 0,`a tab goes either in a named window or next to the focused session`),F.object({kind:F.literal(`split`),sessionId:nr,direction:F.enum([`vertical`,`horizontal`])})]),Mu=F.enum([`tab`,`window`,`split`]),Nu={sessionId:nr,cursor:au,scrollbackTotal:F.number().int().nonnegative(),gen:F.number().int().nonnegative()},Pu=`alive-v1`,Fu=5e3,Iu=F.object({type:F.literal(`hello`),agentVersion:F.string().max(32),features:Dc.optional(),conversationEnabled:F.boolean().optional(),hostPlatform:eu.optional(),launchableBackends:F.array(Ql).max(4).optional(),backendCatalog:lu.optional(),sessionLaunchTargets:du.optional(),sessionLaunchIssues:pu.optional(),terminalSetup:gu.optional(),backends:F.array(F.object({name:Ql,capabilities:ou})).max(4),computerName:F.string().max(64),accent:F.string().max(32)}),Lu=F.object({type:F.literal(`sessions`),list:F.array(Ou).max(500),complete:F.boolean().optional()}),Ru=F.object({type:F.literal(`event`),sessionId:nr,kind:Kc,exitCode:F.number().int().optional(),durationMs:F.number().int().nonnegative().optional(),command:F.string().max(512).optional(),at:F.number()}),zu=F.discriminatedUnion(`type`,[F.object({type:F.literal(`notification.enroll`),generation:Ec,features:Dc.optional()}),F.object({type:F.literal(`notification.enrolled`),generation:Ec}),F.object({type:F.literal(`conn.hello`),n:H(16),features:F.array(F.string().min(1).max(32)).max(8).optional()}),F.object({type:F.literal(`session.v2.bootstrap`),bytes:H().refine(e=>e.length>0&&e.length<=1024)}),Iu,F.object({type:F.literal(`alive`)}),Lu,F.object({type:F.literal(`screen.snapshot`),...Nu,cols:F.number().int().positive(),rows:F.number().int().positive(),lines:F.array(iu).max(1e3),reset:F.boolean().optional(),degraded:F.boolean().optional()}),F.object({type:F.literal(`screen.diff`),...Nu,scroll:F.number().int().nonnegative().max(1e3),changed:F.array(F.object({i:F.number().int().nonnegative(),line:iu})).max(1e3)}),F.object({type:F.literal(`history`),sessionId:nr,before:F.number().int().nonnegative(),lines:F.array(iu).max(200),oldestAvailable:F.number().int().nonnegative()}),Ru,F.object({type:F.literal(`ack`),reqId:Su,ok:F.boolean(),error:F.string().max(256).optional(),sessionId:nr.optional(),opened:Mu.optional(),openedIn:su.optional()}),F.object({type:F.literal(`subscribe`),sessionId:nr.nullable()}),F.object({type:F.literal(`input.line`),reqId:Su,sessionId:nr,text:F.string().max(8192),expect:Eu.optional()}),F.object({type:F.literal(`input.text`),reqId:Su,sessionId:nr,text:F.string().max(65536)}),F.object({type:F.literal(`input.key`),reqId:Su,sessionId:nr,key:cl}),F.object({type:F.literal(`input.terminal`),reqId:Su,sessionId:nr,data:F.string().min(1).max(Wl),expect:Eu.optional()}),F.object({type:F.literal(`input.paste`),reqId:Su,sessionId:nr,text:F.string().min(1).max(Wl),submit:F.boolean(),expect:Eu.optional()}),bu.extend({type:F.literal(`input.mouse`),reqId:Su,sessionId:nr}).refine(e=>e.column<e.cols&&e.row<e.rows,`Mouse coordinates must be inside the source grid`),F.object({type:F.literal(`history.get`),reqId:Su,sessionId:nr,before:F.number().int().nonnegative(),count:F.number().int().min(1).max(200)}),F.object({type:F.literal(`session.create`),reqId:Su,in:ju}),F.object({type:F.literal(`session.focus`),reqId:Su,sessionId:nr}),F.object({type:F.literal(`snapshot.get`),reqId:Su,sessionId:nr}),...ur.options,...Rr.options]);function Bu(e){let t=zu.safeParse(e);if(!t.success)throw new V(`malformed`,`inner: ${F.prettifyError(t.error)}`);return t.data}const Vu=e=>F.union([e,F.string().min(1).max(32)]),Hu=Vu(Ql),Uu=Vu(xu),Wu=Vu(Kc),Gu=Ou.extend({backend:Hu,state:Uu});F.discriminatedUnion(`type`,[Iu.extend({launchableBackends:F.array(Hu).max(4).optional(),backends:F.array(F.object({name:Hu,capabilities:ou})).max(4)}),Lu.extend({list:F.array(Gu).max(500)}),Ru.extend({kind:Wu})]),F.object({type:F.literal(`notify`),sessionId:nr,kind:Wu,exitCode:F.number().int().optional(),durationMs:F.number().int().nonnegative().optional()});const Ku=/[\x00-\x1f\x7f-\x9f]/;function qu(e,t){if(!Number.isSafeInteger(e)||e<1||e>W.cols||t.length>2e3)return null;let n=Ra.create();n.update(yr(`shellbell-native-history-v1\n${e}\n${t.length}\n`));let r=0;for(let e of t){if(typeof e!=`string`||e.length>W.screenBytes||Ku.test(e))return null;let t=yr(`${JSON.stringify(e.replace(/ +$/,``))}\n`);if(r+=t.byteLength,r>W.screenBytes)return null;n.update(t)}return Cr(n.digest())}const Ju=new Uint8Array(16),Yu=Yr(Ju),Xu=(e,t,n,r)=>{let i=r&1;return{s3:n<<31|r>>>1,s2:t<<31|n>>>1,s1:e<<31|t>>>1,s0:e>>>1^225<<24&-(i&1)}},Zu=e=>(e>>>0&255)<<24|(e>>>8&255)<<16|(e>>>16&255)<<8|e>>>24&255|0,Qu=e=>e>65536?8:e>1024?4:2;var $u=class{blockLen=16;outputLen=16;s0=0;s1=0;s2=0;s3=0;finished=!1;destroyed=!1;t;W;windowSize;constructor(e,t){Ur(e,16,`key`),e=fi(e);let n=Zr(e),r=n.getUint32(0,!1),i=n.getUint32(4,!1),a=n.getUint32(8,!1),o=n.getUint32(12,!1),s=[];for(let e=0;e<128;e++)s.push({s0:Zu(r),s1:Zu(i),s2:Zu(a),s3:Zu(o)}),{s0:r,s1:i,s2:a,s3:o}=Xu(r,i,a,o);let c=Qu(t||1024);if(![1,2,4,8].includes(c))throw Error(`ghash: invalid window size, expected 2, 4 or 8`);this.W=c;let l=128/c,u=this.windowSize=2**c,d=[];for(let e=0;e<l;e++)for(let t=0;t<u;t++){let n=0,r=0,i=0,a=0;for(let o=0;o<c;o++){if(!(t>>>c-o-1&1))continue;let{s0:l,s1:u,s2:d,s3:f}=s[c*e+o];n^=l,r^=u,i^=d,a^=f}d.push({s0:n,s1:r,s2:i,s3:a})}this.t=d}_updateBlock(e,t,n,r){e^=this.s0,t^=this.s1,n^=this.s2,r^=this.s3;let{W:i,t:a,windowSize:o}=this,s=0,c=0,l=0,u=0,d=(1<<i)-1,f=0;for(let p of[e,t,n,r])for(let e=0;e<4;e++){let t=p>>>8*e&255;for(let e=8/i-1;e>=0;e--){let n=t>>>i*e&d,{s0:r,s1:p,s2:m,s3:h}=a[f*o+n];s^=r,c^=p,l^=m,u^=h,f+=1}}this.s0=s,this.s1=c,this.s2=l,this.s3=u}update(e){Gr(this),Ur(e),e=fi(e);let t=Yr(e),n=Math.floor(e.length/16),r=e.length%16;for(let e=0;e<n;e++)this._updateBlock(ei(t[e*4+0]),ei(t[e*4+1]),ei(t[e*4+2]),ei(t[e*4+3]));return r&&(Ju.set(e.subarray(n*16)),this._updateBlock(ei(Yu[0]),ei(Yu[1]),ei(Yu[2]),ei(Yu[3])),Xr(Yu)),this}destroy(){this.destroyed=!0;let{t:e}=this;for(let t of e)t.s0=0,t.s1=0,t.s2=0,t.s3=0}digestInto(e){Gr(this),qr(e,this),this.finished=!0;let{s0:t,s1:n,s2:r,s3:i}=this,a=Yr(e);a[0]=t,a[1]=n,a[2]=r,a[3]=i,Qr||ni(a.subarray(0,4))}digest(){let e=new Uint8Array(16);return this.digestInto(e),this.destroy(),e}};const ed=si(16,(e,t)=>new $u(e,t),e=>[e.length]),td=new Uint8Array(16);function nd(e){if(![16,24,32].includes(e.length))throw Error(`"aes key" expected Uint8Array of length 16/24/32, got length=`+e.length)}function rd(e){return e<<1^283&-(e>>7)}function id(e,t){let n=0;for(;t>0;t>>=1)n^=e&-(t&1),e=rd(e);return n}const ad=(()=>{let e=new Uint8Array(256);for(let t=0,n=1;t<256;t++,n^=rd(n))e[t]=n;let t=new Uint8Array(256);t[0]=99;for(let n=0;n<255;n++){let r=e[255-n];r|=r<<8,t[e[n]]=(r^r>>4^r>>5^r>>6^r>>7^99)&255}return Xr(e),t})(),od=e=>e<<24|e>>>8,sd=e=>e<<8|e>>>24;function cd(e,t){if(e.length!==256)throw Error(`wrong sbox length`);let n=new Uint32Array(256).map((n,r)=>t(e[r])),r=n.map(sd),i=r.map(sd),a=i.map(sd),o=new Uint32Array(65536),s=new Uint32Array(65536),c=new Uint16Array(65536);for(let t=0;t<256;t++)for(let l=0;l<256;l++){let u=t*256+l;o[u]=n[t]^r[l],s[u]=i[t]^a[l],c[u]=e[t]<<8|e[l]}return{sbox:e,sbox2:c,T0:n,T1:r,T2:i,T3:a,T01:o,T23:s}}const ld=cd(ad,e=>id(e,3)<<24|e<<16|e<<8|id(e,2)),ud=(()=>{let e=new Uint8Array(16);for(let t=0,n=1;t<16;t++,n=rd(n))e[t]=n;return e})();function dd(e){Ur(e);let t=e.length;nd(e);let{sbox2:n}=ld,r=[];(!Qr||!di(e))&&r.push(e=fi(e));let i=ni(Yr(e)),a=i.length,o=e=>pd(n,e,e,e,e),s=new Uint32Array(t+28);s.set(i);for(let e=a;e<s.length;e++){let t=s[e-1];e%a===0?t=o(od(t))^ud[e/a-1]:a>6&&e%a===4&&(t=o(t)),s[e]=s[e-a]^t}return Xr(...r),s}function fd(e,t,n,r,i,a){return e[n<<8&65280|r>>>8&255]^t[i>>>8&65280|a>>>24&255]}function pd(e,t,n,r,i){return e[t&255|n&65280]|e[r>>>16&255|i>>>16&65280]<<16}function md(e,t,n,r,i){let{sbox2:a,T01:o,T23:s}=ld,c=0;t^=e[c++],n^=e[c++],r^=e[c++],i^=e[c++];let l=e.length/4-2;for(let a=0;a<l;a++){let a=e[c++]^fd(o,s,t,n,r,i),l=e[c++]^fd(o,s,n,r,i,t),u=e[c++]^fd(o,s,r,i,t,n),d=e[c++]^fd(o,s,i,t,n,r);t=a,n=l,r=u,i=d}return{s0:e[c++]^pd(a,t,n,r,i),s1:e[c++]^pd(a,n,r,i,t),s2:e[c++]^pd(a,r,i,t,n),s3:e[c++]^pd(a,i,t,n,r)}}function hd(e,t,n,r,i){Ur(n,16,`nonce`),Ur(r),i=li(r.length,i);let a=n,o=Yr(a),s=Zr(a),c=Yr(r),l=Yr(i),u=t?0:12,d=r.length,f=s.getUint32(u,t);for(let n=0;n+4<=c.length;n+=4){let{s0:r,s1:i,s2:a,s3:d}=md(e,ei(o[0]),ei(o[1]),ei(o[2]),ei(o[3]));l[n+0]=c[n+0]^ei(r),l[n+1]=c[n+1]^ei(i),l[n+2]=c[n+2]^ei(a),l[n+3]=c[n+3]^ei(d),f=f+1>>>0,s.setUint32(u,f,t)}let p=16*Math.floor(c.length/4);if(p<d){let{s0:t,s1:n,s2:a,s3:s}=md(e,ei(o[0]),ei(o[1]),ei(o[2]),ei(o[3])),c=new Uint32Array([t,n,a,s]);ni(c);let l=Jr(c);for(let e=p,t=0;e<d;e++,t++)i[e]=r[e]^l[t];Xr(c)}return i}function gd(e,t,n,r,i){let a=i?i.length:0,o=e.create(n,r.length+a);i&&o.update(i);let s=ui(8*r.length,8*a,t);o.update(r),o.update(s);let c=o.digest();return Xr(s),c}const _d=ci({blockSize:16,nonceLength:12,tagLength:16,withAAD:!0,varSizeNonce:!0},function(e,t,n){if(t.length<8)throw Error(`aes/gcm: invalid nonce length`);function r(e,t,r){let i=gd(ed,!1,e,r,n);for(let e=0;e<t.length;e++)i[e]^=t[e];return i}function i(){let n=dd(e),r=td.slice(),i=td.slice();if(hd(n,!1,i,i,r),t.length===12)i.set(t);else{let e=td.slice();Zr(e).setBigUint64(8,BigInt(t.length*8),!1);let n=ed.create(r).update(t).update(e);n.digestInto(i),n.destroy()}return{xk:n,authKey:r,counter:i,tagMask:hd(n,!1,i,td)}}return{encrypt(e){let{xk:t,authKey:n,counter:a,tagMask:o}=i(),s=new Uint8Array(e.length+16),c=[t,n,a,o];di(e)||c.push(e=fi(e)),hd(t,!1,a,e,s.subarray(0,e.length));let l=r(n,o,s.subarray(0,s.length-16));return c.push(l),s.set(l,e.length),Xr(...c),s},decrypt(e){let{xk:t,authKey:n,counter:a,tagMask:o}=i(),s=[t,n,o,a];di(e)||s.push(e=fi(e));let c=e.subarray(0,-16),l=e.subarray(-16),u=r(n,o,c);if(s.push(u),!oi(u,l))throw Xr(...s),Error(`aes-gcm: invalid tag`);let d=hd(t,!1,a,c);return Xr(...s),d}}});function vd(e){if(!(e instanceof Uint8Array)||e.length!==32)throw new V(`crypto`,`invalid notification key`)}const yd=Nc.pick({computerFp:!0,phoneFp:!0,generation:!0});function bd(e,t){vd(e);let n=yd.parse({computerFp:t.computerFp,phoneFp:t.phoneFp,generation:t.generation});return Qs(Ra,e,yr(Cc),yr(JSON.stringify([n.computerFp,n.phoneFp,n.generation])),32)}function xd(e){let t=Lc(e);return yr(JSON.stringify([Cc,t.computerFp,t.phoneFp,t.generation,t.sessionId,t.eventId]))}function Sd(e,t){try{vd(e);let n=Fc.parse(t),r=Lc(n),i=ba(12),a=yr(JSON.stringify(n));try{let t=_d(e,i,xd(r)).encrypt(a);return{...r,nonce:br(i),ciphertext:br(t)}}finally{a.fill(0)}}catch{throw new V(`crypto`,`notification seal failed`)}}const Cd=F.string().regex(/^[A-Za-z0-9_-]{22}$/),wd=F.object({v:F.literal(1),r:F.url().max(256),c:U,e:F.string().regex(/^[A-Za-z0-9_-]{43}$/),n:F.string().min(1).max(40),p:Cd,g:Cd,b:F.literal(1).optional(),x:F.number().int().positive().max(2**32).optional()});function Td(e){return JSON.stringify(e)}function Ed(e,t={}){let n;try{n=JSON.parse(e)}catch{throw new V(`malformed`,`qr: not json`)}let r=wd.safeParse(n);if(!r.success)throw new V(`malformed`,`qr: ${F.prettifyError(r.error)}`);let i=r.data,a=new URL(i.r);if(a.username||a.password)throw new V(`malformed`,`qr: relay url must not contain credentials`);if(a.protocol!==`wss:`&&!(t.allowInsecure&&a.protocol===`ws:`))throw new V(`malformed`,`qr: relay must be wss://`);if(i.r.endsWith(`/`)||/[?#]/.test(i.r)||a.pathname!==`/`||a.search||a.hash)throw new V(`malformed`,`qr: relay url must be scheme://host[:port] with no path`);if(ic(xr(i.e))!==i.c)throw new V(`malformed`,`qr: fingerprint mismatch`);return i}function Dd(e,t){return`${e}/ws/${t}`}function Od(){return{r:[]}}function kd(e){let t=0;for(let n of e)t++;return t}function Ad(e){return e===void 0?``:typeof e==`number`?String(e):`${e[0]},${e[1]},${e[2]}`}function jd(e,t){return Ad(e.fg)===Ad(t.fg)&&Ad(e.bg)===Ad(t.bg)&&!!e.b==!!t.b&&!!e.i==!!t.i&&!!e.u==!!t.u&&!!e.s==!!t.s&&!!e.f==!!t.f}function Md(e){return e.n??kd(e.t)}function Nd(e){let t=[];for(let n of e){let e=t[t.length-1];if(e&&jd(e,n)){let t=Md(e)+Md(n);e.t+=n.t,t===kd(e.t)?delete e.n:e.n=t}else{let e={...n};e.n!==void 0&&e.n===kd(e.t)&&delete e.n,t.push(e)}}return t}function Pd(e){let t=e.slice();for(;t.length>0;){let e=t[t.length-1];if(e.bg!==void 0)break;let n=e.t.replace(/ +$/,``);if(n===``){t.pop();continue}if(n!==e.t){let r=kd(e.t)-kd(n),i=(e.n??kd(e.t))-r,a={...e,t:n};i===kd(n)?delete a.n:a.n=i,t[t.length-1]=a}break}return t}function Fd(e){let t={r:[]};for(let n of e.r){let e=Md(n);if(n.t===``&&e===0)continue;let r=t.r[t.r.length-1];if(r&&r.t.length+n.t.length<=4096&&Md(r)+e<=4096){let t=Md(r)+e;r.t+=n.t,t===kd(r.t)?delete r.n:r.n=t}else{let r={t:n.t};e!==kd(n.t)&&(r.n=e),t.r.push(r)}}return e.w!==void 0&&(t.w=e.w),t}function Id(e){return`${+!!e.b}${+!!e.i}${+!!e.u}${+!!e.s}${+!!e.f}`}function Ld(e){let t=e.r.map(e=>`${e.t}|${Ad(e.fg)}|${Ad(e.bg)}|${Id(e)}|${e.n??``}`).join(``);return e.w===!0?`${t}\x00w`:t}const Rd={sdpChars:24e3,candidateChars:1024,candidatesPerSide:32,encodedBytes:3e4,bootstrapConfirmBytes:512},zd=kl.refine(e=>e[0]===1&&e.subarray(1).every(e=>e===0),{message:`initial relay generation must be one`}),Bd=kl.refine(e=>e[0]!==1||e.subarray(1).some(e=>e!==0),{message:`direct generation must exceed one`}),Vd=F.string().min(1).max(Rd.sdpChars).regex(/^[\x20-\x7e\r\n]+$/,`SDP must contain printable ASCII and line endings only`),Hd=F.string().min(1).max(Rd.candidateChars).startsWith(`candidate:`).regex(/^[\x20-\x7e]+$/,`ICE candidate must contain printable ASCII only`),Ud={sessionId:Ol,offerId:Ol,generation:Bd};function Wd(e,t){if(/\r(?!\n)/.test(e))return!1;let n=e.split(/\r?\n/).filter(e=>e.length>0);if(n.some(e=>!/^[a-z]=/.test(e)))return!1;let r=n.filter(e=>e.startsWith(`m=`));if(r.length!==1||!/^m=application [0-9]+ (?:UDP|TCP)\/DTLS\/SCTP webrtc-datachannel$/i.test(r[0]??``)||n.some(e=>/^a=(?:candidate|remote-candidates|end-of-candidates)(?::|$)/i.test(e))||!n.some(e=>/^a=ice-ufrag:/i.test(e))||!n.some(e=>/^a=ice-pwd:/i.test(e)))return!1;let i=n.filter(e=>/^a=fingerprint:/i.test(e));if(i.length===0)return!1;for(let e of i){let n=/^a=fingerprint:sha-256 ((?:[0-9a-f]{2}:){31}[0-9a-f]{2})$/i.exec(e);if(!n?.[1]||!Er(wr(n[1].replaceAll(`:`,``)),t))return!1}return!0}const Gd=F.discriminatedUnion(`type`,[F.object({type:F.literal(`session.v2.begin`),sessionId:Ol,generation:zd}).strict(),F.object({type:F.literal(`session.v2.accept`),sessionId:Ol,attemptId:Ol,generation:zd}).strict(),F.object({type:F.literal(`session.v2.noise1`),sessionId:Ol,attemptId:Ol,message:H(48)}).strict(),F.object({type:F.literal(`session.v2.noise2`),sessionId:Ol,attemptId:Ol,message:H(48)}).strict(),F.object({type:F.literal(`session.v2.confirm`),sessionId:Ol,attemptId:Ol,frame:F.custom(e=>e instanceof Uint8Array&&e.length>0&&e.length<=Rd.bootstrapConfirmBytes,{message:`invalid v2 confirmation frame length`})}).strict()]);function Kd(e,t){return t!==void 0&&Ol.safeParse(t).success&&Er(e,t)}function qd(e,t){return!t||e.type!==t.expectedType?!1:e.type===`session.v2.begin`?t.sender===`phone`&&t.sessionId===void 0&&t.attemptId===void 0:Kd(e.sessionId,t.sessionId)?e.type===`session.v2.accept`?t.sender===`computer`&&t.attemptId===void 0:Kd(e.attemptId,t.attemptId)?e.type===`session.v2.noise1`?t.sender===`phone`:e.type===`session.v2.noise2`?t.sender===`computer`:t.sender===`phone`||t.sender===`computer`:!1:!1}const Jd=1024;function Yd(e){let t=Gd.safeParse(e);if(!t.success)throw new V(`malformed`,`invalid v2 bootstrap`);let n=Gn(t.data);if(n.length>Jd)throw new V(`malformed`,`v2 bootstrap too large`);return n}function Xd(e,t){if(e.length>Jd)throw new V(`malformed`,`v2 bootstrap too large`);let n=Gd.safeParse(Kn(e));if(!n.success||!qd(n.data,t))throw new V(`malformed`,`invalid or stale v2 bootstrap`);return n.data}const Zd=F.discriminatedUnion(`type`,[F.object({type:F.literal(`direct.offer`),...Ud,sdp:Vd,phoneDtls:H(32)}).strict(),F.object({type:F.literal(`direct.answer`),...Ud,attemptId:Ol,sdp:Vd,computerDtls:H(32)}).strict(),F.object({type:F.literal(`direct.candidate`),...Ud,index:F.number().int().min(0).max(Rd.candidatesPerSide-1),candidate:Hd,mid:F.string().min(1).max(64).regex(/^[\x21-\x7e]+$/).nullable(),mlineIndex:F.number().int().min(0).max(0).nullable()}).strict(),F.object({type:F.literal(`direct.end`),...Ud,count:F.number().int().min(0).max(Rd.candidatesPerSide)}).strict(),F.object({type:F.literal(`direct.abort`),...Ud,reason:F.enum([`timeout`,`ice-failed`,`dtls-failed`,`resource-limit`,`cancelled`])}).strict()]).superRefine((e,t)=>{e.type===`direct.candidate`&&e.mid===null&&e.mlineIndex===null&&t.addIssue({code:`custom`,message:`candidate needs a media section`}),e.type===`direct.offer`&&!Wd(e.sdp,e.phoneDtls)&&t.addIssue({code:`custom`,message:`invalid data-channel offer SDP`}),e.type===`direct.answer`&&!Wd(e.sdp,e.computerDtls)&&t.addIssue({code:`custom`,message:`invalid data-channel answer SDP`})});function Qd(e,t){if(!t||t.sender!==`phone`&&t.sender!==`computer`||!Ol.safeParse(t.sessionId).success||!kl.safeParse(t.committedGeneration).success||!Er(e.sessionId,t.sessionId))return!1;if(e.type===`direct.offer`)return t.sender===`phone`&&t.pending===void 0&&vl(e.generation)>vl(t.committedGeneration);let n=t.pending;return n!==void 0&&Ol.safeParse(n.offerId).success&&kl.safeParse(n.generation).success&&vl(n.generation)>vl(t.committedGeneration)&&Er(e.offerId,n.offerId)&&Er(e.generation,n.generation)&&(e.type!==`direct.answer`||t.sender===`computer`)}function $d(e){let t=Zd.safeParse(e);if(!t.success)throw new V(`malformed`,`invalid direct signal`);let n=Gn(t.data);if(n.length>Rd.encodedBytes)throw new V(`malformed`,`direct signal too large`);return n}function ef(e,t){if(e.length>Rd.encodedBytes)throw new V(`malformed`,`direct signal too large`);let n=Zd.safeParse(Kn(e));if(!n.success||!Qd(n.data,t))throw new V(`malformed`,`invalid or stale direct signal`);return n.data}var tf=class{context;role;actualRemoteCertificate;handshake;session=null;phase;constructor(e,t,n,r){if(this.context=e,this.role=t,this.actualRemoteCertificate=r,e.route!==`direct`)throw Error(`direct context required`);this.handshake=Vl(e,t,n),this.phase=t===`phone`?`new`:`noise1`}get ready(){return this.phase===`ready`&&this.session?.ready===!0}begin(){if(this.phase!==`new`||!this.handshake)throw Error(`direct handshake order`);return this.phase=`noise2`,Yd({type:`session.v2.noise1`,sessionId:this.context.sessionId,attemptId:this.context.attemptId,message:this.handshake.write()})}receive(e){try{if((this.phase===`noise1`||this.phase===`noise2`)&&this.handshake){let t=this.phase===`noise1`?`session.v2.noise1`:`session.v2.noise2`,n=Xd(e,{sender:this.role===`phone`?`computer`:`phone`,expectedType:t,sessionId:this.context.sessionId,attemptId:this.context.attemptId});if(n.type!==t)throw Error(`direct handshake order`);this.handshake.read(n.message);let r=null;return this.role===`computer`&&(r=Yd({type:`session.v2.noise2`,sessionId:this.context.sessionId,attemptId:this.context.attemptId,message:this.handshake.write()})),this.session=this.handshake.finish(),this.handshake=null,this.session.verifyRemoteDtls(this.actualRemoteCertificate),this.phase=`confirm`,r??Yd({type:`session.v2.confirm`,sessionId:this.context.sessionId,attemptId:this.context.attemptId,frame:Rl(this.session.confirmation())})}if(this.phase!==`confirm`||!this.session)throw Error(`direct handshake order`);let t=Xd(e,{sender:this.role===`phone`?`computer`:`phone`,expectedType:`session.v2.confirm`,sessionId:this.context.sessionId,attemptId:this.context.attemptId});if(t.type!==`session.v2.confirm`)throw Error(`direct confirmation required`);this.session.acceptConfirmation(zl(t.frame));let n=this.role===`computer`?Yd({type:`session.v2.confirm`,sessionId:this.context.sessionId,attemptId:this.context.attemptId,frame:Rl(this.session.confirmation())}):null;if(!this.session.ready)throw Error(`direct confirmation incomplete`);return this.phase=`ready`,n}catch(e){throw this.close(),e}}takeReadySession(){if(!this.ready||!this.session)throw Error(`direct handshake incomplete`);let e=this.session;return this.session=null,this.phase=`closed`,e}close(){this.handshake?.close(),this.handshake=null,this.session?.close(),this.session=null,this.phase=`closed`}};function nf(e,t){return e===`relay`||t===`relay`?`turn`:e===`host`&&t===`host`?`local`:`internet`}const rf=e=>/ typ relay(?: |$)/.test(e.candidate);function af(e){let t=/^a=fingerprint:sha-256 ((?:[0-9a-f]{2}:){31}[0-9a-f]{2})\r?$/im.exec(e);if(!t?.[1])throw Error(`missing SHA-256 SDP fingerprint`);return wr(t[1].replaceAll(`:`,``))}function of(e){return`${e.split(/\r?\n/).filter(e=>e.length&&!/^a=(?:candidate|remote-candidates|end-of-candidates)(?::|$)/i.test(e)).join(`\r
16
- `)}\r\n`}var sf=class{options;offerId;generation;attemptId;peer=null;phoneDtls;computerDtls=null;localSdp=null;remoteSdp=!1;opened=!1;verifying=!1;sentDescription=!1;sentCandidates=0;receivedCandidates=0;pendingData=[];pendingLocal=[];pendingRemote=[];handshake=null;secureSession=null;closed=!1;timer;constructor(e){this.options=e,this.offerId=e.offer?.offerId.slice()??ba(16),this.attemptId=e.offer?ba(16):null,this.generation=e.generation.slice(),this.phoneDtls=e.offer?.phoneDtls.slice()??null,this.timer=setTimeout(()=>this.fail(`timeout`),15e3)}get session(){return this.secureSession}get phase(){return this.secureSession?`cutover`:this.handshake?`noise`:this.verifying?`certificate`:this.opened?`open`:this.remoteSdp?`connecting`:this.localSdp?`offer`:`native`}get active(){return!this.closed&&this.options.current()}cancelDeadline(){clearTimeout(this.timer)}close(){this.closed||(this.closed=!0,this.cancelDeadline(),this.pendingData=[],this.pendingLocal=[],this.pendingRemote=[],this.handshake?.close(),this.secureSession?.close(),this.peer?.close())}routeStats(){return this.peer?.routeStats?.()??Promise.resolve(null)}send(e){let t=this.active&&(this.peer?.send(e)??!1);return t&&this.options.sent(e.length),t}fail(e=`closed`){this.active&&this.options.failed(e)}async start(){let e={description:(e,t)=>{this.active&&this.description(e,t)},candidate:(e,t,n)=>{if(this.active)try{this.localCandidate({candidate:e,mid:t,mlineIndex:n})}catch{this.fail(`local-candidate`)}},open:()=>{this.active&&(this.opened=!0,this.openDirect().catch(()=>this.fail(`certificate`)))},message:e=>{this.active&&(this.options.received(e.length),this.directMessage(e))},closed:()=>this.fail(`native-closed`)},t;try{t=await this.options.native(e)}catch{this.fail(`native-create`);return}if(!this.active){t.close();return}this.peer=t;try{if(this.options.offer){if(await t.answer(this.options.offer.sdp),!this.active)return;this.remoteSdp=!0}else await t.offer();if(!this.active)return;await this.flushRemote(),await this.openDirect()}catch{this.fail(`native-description`)}}description(e,t){try{let n=af(e);if(this.localSdp=of(e),this.options.role===`phone`&&t===`offer`)this.phoneDtls=n;else if(this.options.role===`computer`&&t===`answer`)this.computerDtls=n;else throw Error(`description role mismatch`);let r=this.signalContext(),i=t===`offer`?{type:`direct.offer`,...r,phoneDtls:n,sdp:this.localSdp}:{type:`direct.answer`,...r,attemptId:this.attemptId,computerDtls:n,sdp:this.localSdp};if(!this.options.sendSignal(i))throw Error(`signaling queue refused`);this.sentDescription=!0;for(let e of this.pendingLocal.splice(0))this.localCandidate(e);this.openDirect().catch(()=>this.fail(`certificate`))}catch{this.fail(`local-description`)}}admits(e){return this.sentCandidates+this.pendingLocal.length<(rf(e)?Rd.candidatesPerSide:Rd.candidatesPerSide-6)}localCandidate(e){if(this.active&&!this.options.committed()&&this.admits(e)){if(!this.sentDescription){this.pendingLocal.push(e);return}this.options.sendSignal({type:`direct.candidate`,...this.signalContext(),index:this.sentCandidates++,...e})||this.fail()}}async signal(e){if(this.active&&this.peer){if(e.type===`direct.answer`){if(this.remoteSdp||(this.computerDtls=e.computerDtls.slice(),this.attemptId=e.attemptId.slice(),await this.peer.acceptAnswer(e.sdp),!this.active))return;this.remoteSdp=!0,await this.flushRemote(),await this.openDirect()}else if(e.type===`direct.candidate`){if(e.index!==this.receivedCandidates++)throw Error(`candidate order`);this.remoteSdp?await this.peer.candidate(e.candidate,e.mid,e.mlineIndex):this.pendingRemote.push(e)}else e.type===`direct.abort`&&this.fail()}}async flushRemote(){if(this.remoteSdp&&this.peer)for(let e of this.pendingRemote.splice(0)){if(!this.active)return;await this.peer.candidate(e.candidate,e.mid,e.mlineIndex)}}signalContext(){return{sessionId:this.options.relay.sessionId,offerId:this.offerId,generation:this.generation}}async openDirect(){if(!this.active||!this.opened||!this.peer||!this.phoneDtls||!this.computerDtls||!this.attemptId||this.verifying||this.handshake||this.secureSession)return;this.verifying=!0;let e=await this.peer.remoteCertificate(this.options.role===`phone`?this.computerDtls:this.phoneDtls);if(this.active){if(this.handshake=new tf({route:`direct`,computerFp:this.options.computerFp,phoneFp:this.options.phoneFp,sessionId:this.options.relay.sessionId,generation:this.generation,attemptId:this.attemptId,phoneDtls:this.phoneDtls,computerDtls:this.computerDtls},this.options.role,this.options.keys,e),this.options.role===`phone`&&!this.send(this.handshake.begin())){this.fail();return}for(let e of this.pendingData.splice(0))this.directMessage(e)}}directMessage(e){if(this.active)try{if(!this.peer||e.length>61e3)throw Error(`direct frame bounds`);if(this.secureSession){this.options.frame(this.secureSession,e);return}if(!this.handshake){if(!this.verifying||this.pendingData.length>=4||e.length>1024)throw Error(`direct handshake missing`);this.pendingData.push(e.slice());return}let t=this.handshake.receive(e);if(t&&!this.send(t))throw Error(`direct queue refused`);this.handshake.ready&&(this.secureSession=this.handshake.takeReadySession(),this.handshake=null,this.options.ready(this.secureSession))}catch{this.fail(`direct-frame`)}}};const cf=Uint8Array.of(1,0,0,0,0,0,0,0);var lf=class{options;stage;startedAt=null;sessionId=null;attemptId=null;handshake=null;session=null;timer=null;keys;timeoutMs;constructor(e){if(this.options=e,U.parse(e.computerFp),U.parse(e.phoneFp),e.role!==`phone`&&e.role!==`computer`)throw Error(`invalid v2 role`);if(e.keys.staticPrivate.length!==32||e.keys.remoteStatic.length!==32||e.keys.pairKey.length!==32)throw Error(`invalid v2 pairing keys`);if(this.timeoutMs=e.timeoutMs??15e3,!Number.isSafeInteger(this.timeoutMs)||this.timeoutMs<1||this.timeoutMs>3e4)throw Error(`invalid v2 bootstrap timeout`);this.keys={staticPrivate:e.keys.staticPrivate.slice(),remoteStatic:e.keys.remoteStatic.slice(),pairKey:e.keys.pairKey.slice()},this.stage=e.role===`phone`?`phone:new`:`computer:begin`}get ready(){return this.stage===`ready`&&this.session?.ready===!0}begin(){if(this.stage!==`phone:new`)throw Error(`v2 begin not allowed`);try{return this.startedAt=this.clock(),this.armTimer(),this.sessionId=this.freshId(),this.stage=`phone:accept`,Yd({type:`session.v2.begin`,sessionId:this.sessionId,generation:cf})}catch(e){throw this.close(),e}}receive(e){try{if(this.stage===`closed`||this.stage===`detached`||this.stage===`ready`)throw Error(`v2 bootstrap no longer accepts messages`);switch(this.stage!==`computer:begin`&&this.assertNotExpired(),this.stage){case`computer:begin`:{let t=Xd(e,{sender:`phone`,expectedType:`session.v2.begin`});if(t.type!==`session.v2.begin`)throw Error(`invalid v2 begin`);if(this.startedAt=this.clock(),this.armTimer(),this.sessionId=t.sessionId.slice(),this.attemptId=this.freshId(),Er(this.sessionId,this.attemptId))throw Error(`repeated v2 attempt ID`);return this.handshake=this.newHandshake(),this.stage=`computer:noise1`,Yd({type:`session.v2.accept`,sessionId:this.sessionId,attemptId:this.attemptId,generation:cf})}case`phone:accept`:{let t=Xd(e,{sender:`computer`,expectedType:`session.v2.accept`,sessionId:this.requireSessionId()});if(t.type!==`session.v2.accept`)throw Error(`invalid v2 accept`);if(this.attemptId=t.attemptId.slice(),Er(this.requireSessionId(),this.attemptId))throw Error(`repeated v2 attempt ID`);this.handshake=this.newHandshake();let n=this.handshake.write();return this.stage=`phone:noise2`,Yd({type:`session.v2.noise1`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId(),message:n})}case`computer:noise1`:{let t=Xd(e,{sender:`phone`,expectedType:`session.v2.noise1`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId()});if(t.type!==`session.v2.noise1`||!this.handshake)throw Error(`invalid v2 noise1`);this.handshake.read(t.message);let n=this.handshake.write();return this.session=this.handshake.finish(),this.handshake=null,this.stage=`computer:confirm`,Yd({type:`session.v2.noise2`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId(),message:n})}case`phone:noise2`:{let t=Xd(e,{sender:`computer`,expectedType:`session.v2.noise2`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId()});if(t.type!==`session.v2.noise2`||!this.handshake)throw Error(`invalid v2 noise2`);this.handshake.read(t.message),this.session=this.handshake.finish(),this.handshake=null;let n=Rl(this.session.confirmation());return this.stage=`phone:confirm`,Yd({type:`session.v2.confirm`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId(),frame:n})}case`computer:confirm`:{let t=this.decodeConfirmation(e,`phone`);if(!this.session)throw Error(`v2 session missing`);this.session.acceptConfirmation(zl(t.frame));let n=Rl(this.session.confirmation());if(!this.session.ready)throw Error(`v2 computer confirmation incomplete`);return this.markReady(),Yd({type:`session.v2.confirm`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId(),frame:n})}case`phone:confirm`:{let t=this.decodeConfirmation(e,`computer`);if(!this.session)throw Error(`v2 session missing`);if(this.session.acceptConfirmation(zl(t.frame)),!this.session.ready)throw Error(`v2 phone confirmation incomplete`);return this.markReady(),null}default:throw Error(`invalid v2 bootstrap stage`)}}catch(e){throw this.close(),e}}takeReadySession(){if(!this.ready||!this.session)throw Error(`v2 session not confirmed`);let e=this.session;return this.session=null,this.stage=`detached`,e}close(){this.stage!==`closed`&&(this.stage=`closed`,this.clearTimer(),this.handshake?.close(),this.handshake=null,this.session?.close(),this.session=null,this.keys.staticPrivate.fill(0),this.keys.remoteStatic.fill(0),this.keys.pairKey.fill(0))}decodeConfirmation(e,t){let n=Xd(e,{sender:t,expectedType:`session.v2.confirm`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId()});if(n.type!==`session.v2.confirm`)throw Error(`invalid v2 confirmation`);return n}newHandshake(){let e={route:`relay`,computerFp:this.options.computerFp,phoneFp:this.options.phoneFp,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId(),generation:cf};try{return Vl(e,this.options.role,this.keys)}finally{this.keys.staticPrivate.fill(0),this.keys.remoteStatic.fill(0),this.keys.pairKey.fill(0)}}freshId(){return Ol.parse(this.options.newId()).slice()}requireSessionId(){if(!this.sessionId)throw Error(`v2 session ID missing`);return this.sessionId}requireAttemptId(){if(!this.attemptId)throw Error(`v2 attempt ID missing`);return this.attemptId}clock(){let e=this.options.now();if(!Number.isFinite(e)||e<0)throw Error(`invalid v2 clock`);return e}armTimer(){this.clearTimer(),this.timer=setTimeout(()=>this.close(),this.timeoutMs)}clearTimer(){this.timer!==null&&clearTimeout(this.timer),this.timer=null}markReady(){this.stage=`ready`,this.clearTimer()}assertNotExpired(){if(this.startedAt===null)throw Error(`v2 bootstrap not started`);let e=this.clock()-this.startedAt;if(e<0||e>this.timeoutMs)throw Error(`v2 bootstrap expired`)}},uf=class{options;stage;pairKey;bootstrap;timeoutMs;startedAt=null;timer=null;phoneNonce=null;connKey=null;connTag=``;seqIn=0;seqOut=0;constructor(e){if(this.options=e,U.parse(e.computerFp),U.parse(e.phoneFp),e.role!==`phone`&&e.role!==`computer`)throw Error(`invalid v2 role`);if(e.keys.pairKey.length!==32)throw Error(`invalid pair key`);if(this.timeoutMs=e.timeoutMs??15e3,!Number.isSafeInteger(this.timeoutMs)||this.timeoutMs<1)throw Error(`invalid v2 carrier timeout`);this.pairKey=e.keys.pairKey.slice(),this.bootstrap=new lf(e),this.stage=e.role===`phone`?`phone:new`:`computer:hello`}get ready(){return this.stage===`ready`&&this.bootstrap.ready}get closed(){return this.stage===`closed`}start(){if(this.stage!==`phone:new`)throw Error(`v2 carrier cannot start`);try{return this.startDeadline(),this.phoneNonce=ba(16),this.stage=`phone:hello`,this.hello(this.phoneNonce)}catch(e){throw this.close(),e}}receive(e){if(this.stage===`closed`||this.stage===`ready`||this.stage===`phone:new`)throw Error(`v2 carrier not receiving`);try{this.stage!==`computer:hello`&&this.checkDeadline();let t=this.options.role===`phone`?this.options.computerFp:this.options.phoneFp,n=this.options.role===`phone`?this.options.phoneFp:this.options.computerFp;if(e.v!==1||e.t!==`e2e`||e.from!==t||e.to!==n)throw Error(`v2 carrier peer mismatch`);let r=Qn.parse(e.body);if(r.c.length<16||r.c.length>2048)throw Error(`v2 carrier ciphertext exceeds bound`);if(this.stage===`phone:hello`||this.stage===`computer:hello`){if(e.seq!==0)throw Error(`v2 carrier expected hello`);let i=Bu(Kn(dc(this.pairKey,r,_c(t,n))));if(i.type!==`conn.hello`||!i.features?.includes(`session-v2`))throw Error(`v2 carrier requires v2 hello intent`);if(this.stage===`computer:hello`){this.startDeadline(),this.phoneNonce=i.n.slice();let e=ba(16);if(Er(this.phoneNonce,e))throw Error(`reused hello nonce`);return this.deriveConnection(this.phoneNonce,e),this.stage=`bootstrap`,this.hello(e)}if(!this.phoneNonce||Er(this.phoneNonce,i.n))throw Error(`invalid hello nonce`);return this.deriveConnection(this.phoneNonce,i.n),this.stage=`bootstrap`,this.frame(this.bootstrap.begin())}if(!this.connKey||e.seq!==this.seqIn+1)throw Error(`v2 carrier frame sequence mismatch`);let i=Bu(Kn(dc(this.connKey,r,gc(t,n,this.connTag,e.seq))));if(i.type!==`session.v2.bootstrap`)throw Error(`v2 carrier rejects legacy terminal message`);this.seqIn=e.seq;let a=this.bootstrap.receive(i.bytes);return this.bootstrap.ready&&(this.stage=`ready`,this.clearDeadline()),a?this.frame(a):null}catch(e){throw this.close(),e}}takeReadySession(){if(!this.ready)throw Error(`v2 carrier not confirmed`);let e=this.bootstrap.takeReadySession();return this.close(),e}close(){this.stage!==`closed`&&(this.stage=`closed`,this.clearDeadline(),this.pairKey.fill(0),this.phoneNonce?.fill(0),this.phoneNonce=null,this.connKey?.fill(0),this.connKey=null,this.connTag=``,this.bootstrap.close())}hello(e){let t=this.options.role===`phone`?this.options.phoneFp:this.options.computerFp,n=this.options.role===`phone`?this.options.computerFp:this.options.phoneFp;return{v:1,t:`e2e`,from:t,to:n,seq:0,body:uc(this.pairKey,Gn({type:`conn.hello`,n:e,features:[`session-v2`]}),_c(t,n))}}frame(e){if(!this.connKey||this.seqOut>=2**53-1)throw Error(`v2 carrier unavailable`);let t=this.options.role===`phone`?this.options.phoneFp:this.options.computerFp,n=this.options.role===`phone`?this.options.computerFp:this.options.phoneFp,r=++this.seqOut;return{v:1,t:`e2e`,from:t,to:n,seq:r,body:uc(this.connKey,Gn({type:`session.v2.bootstrap`,bytes:e}),gc(t,n,this.connTag,r))}}deriveConnection(e,t){let n=mc(this.pairKey,e,t,this.options.computerFp,this.options.phoneFp);this.connKey=n.kConn,this.connTag=n.connTag}startDeadline(){if(this.startedAt=this.options.now(),!Number.isFinite(this.startedAt))throw Error(`invalid v2 carrier clock`);this.timer=setTimeout(()=>this.close(),this.timeoutMs)}checkDeadline(){let e=this.options.now();if(this.startedAt===null||!Number.isFinite(e)||e<this.startedAt||e-this.startedAt>=this.timeoutMs)throw Error(`v2 carrier handshake expired`)}clearDeadline(){this.timer&&clearTimeout(this.timer),this.timer=null}};function df(e){return{route:e.route,sessionId:e.sessionId.slice(),attemptId:e.attemptId.slice(),generation:e.generation.slice()}}function ff(e,t){return e.route===t.route&&Er(e.sessionId,t.sessionId)&&Er(e.attemptId,t.attemptId)&&Er(e.generation,t.generation)}var pf=class{options;relay=null;active=null;staged=null;transition=null;wireIds=new Set;attemptIds=new Set;transitionIds=new Set;highGeneration=1n;directAttempts=0;lastNow=-1;deadline=null;timer=null;revoked=!1;recovering=!1;snapshot=!1;revision=0;constructor(e){if(this.options=e,U.parse(e.computerFp),U.parse(e.phoneFp),e.role!==`phone`&&e.role!==`computer`)throw Error(`invalid route role`);this.installRelay(e.relay)}get status(){return this.revoked?`closed`:this.recovering?`recovering`:this.transition?`cutover`:this.active?.reference.route??`uncommitted`}get activeRoute(){return this.active?df(this.active.reference):null}get routeRevision(){return this.revision}get needsSnapshot(){return this.snapshot}get preparationPending(){return this.transition?.phase===`computer:preparing`}get paused(){return this.revoked||this.recovering||this.transition!==null||this.active===null}get directActive(){return this.active?.reference.route===`direct`}snapshotApplied(){this.paused||(this.snapshot=!1)}stageDirect(e){if(this.sweep(),this.revoked||this.recovering||!this.active||!this.relay||this.staged||this.transition)throw Error(`route candidate unavailable`);let t=null;try{if(t=this.validate(e,`direct`),!Er(t.reference.sessionId,this.relay.reference.sessionId))throw Error(`direct wire session mismatch`);let n=vl(t.reference.generation);if(n<=this.highGeneration)throw Error(`direct generation reused`);let r=Cr(t.reference.attemptId);if(this.attemptIds.has(r))throw Error(`direct attempt reused`);if(this.directAttempts>=Gl.directAttempts)throw Error(`direct attempt capacity`);this.highGeneration=n,this.directAttempts+=1,this.attemptIds.add(r),this.staged=t,this.arm()}catch(t){throw e.session!==this.active?.session&&e.session!==this.relay?.session&&e.session.close(),t}}begin(){if(this.sweep(),this.options.role!==`phone`||this.revoked||this.recovering||!this.staged||!this.relay||this.transition)throw Error(`route prepare unavailable`);if(!this.options.prepareReady())return!1;let e=Ol.parse(this.options.newId()).slice();if(this.transitionIds.has(Cr(e)))throw Error(`route transition reused`);return this.transitionIds.add(Cr(e)),this.transition={id:e,target:this.staged,phase:`phone:prepared`},this.sendControl(`route.prepare`)}approve(){return this.sweep(),!this.preparationPending||!this.transition||!this.options.prepareReady()||!this.transition.target.session.ready?!1:(this.transition.phase=`computer:commit`,this.sendControl(`route.prepared`))}receive(e,t){if(this.sweep(),this.revoked||this.recovering||!this.registered(e))return null;try{let n=e.open(t),r;try{r=Xl(n)}finally{n.fill(0)}if(r.kind===`control`){if(e!==this.relay?.session)throw Error(`route control requires relay session`);return this.control(r.control),null}if(r.kind===`signal`){if(e!==this.relay?.session)throw Error(`direct signaling requires relay session`);return r}return this.paused||e!==this.active?.session||!this.directActive?(r.bytes.fill(0),null):r}catch{return this.routeLost(e),null}}sendTerminal(e){return this.sweep(),this.paused||!this.active||!this.directActive?!1:this.sendPayload(this.active,{kind:`terminal`,bytes:e})}sendSignal(e){return this.sweep(),this.revoked||this.recovering||!this.relay?!1:this.sendPayload(this.relay,{kind:`signal`,bytes:e})}abort(e=`cancelled`){if(!this.staged&&!this.transition)return;if(this.transition?.phase===`phone:committed`||!this.active){this.failAll();return}let t=this.transition;t&&this.relay&&this.sendPayload(this.relay,{kind:`control`,control:{type:`route.abort`,transitionId:t.id,target:df(t.target.reference),reason:e}}),this.discardCandidate(),t&&(this.snapshot=!0)}relayLost(){this.active?.reference.route===`direct`&&!this.transition&&!this.staged?(this.relay?.session.close(),this.relay=null):this.failAll()}routeLost(e){e===this.active?.session?this.failAll():e===this.relay?.session?this.relayLost():e===this.staged?.session&&this.abort(`candidate-failed`)}recover(e){if(this.revoked)throw e.session.close(),Error(`route owner revoked`);let t=this.validate(e,`relay`);if(this.wireIds.has(Cr(t.reference.sessionId)))throw t.session.close(),Error(`wire session reused`);this.failAll(),this.installRelay(t)}sweep(){if(this.revoked)return;let e=this.clock();this.deadline!==null&&e>=this.deadline&&this.abort(`timeout`)}close(){this.failAll(),this.revoked=!0,this.recovering=!1}validate(e,t){if(!(e.session instanceof Hl)||!e.session.ready||e.session.senderRole!==this.options.role)throw Error(`route session not ready`);let n=e.session.description;if(n.computerFp!==this.options.computerFp||n.phoneFp!==this.options.phoneFp||n.route!==t)throw Error(`route pairing mismatch`);if(t===`relay`&&vl(n.generation)!==1n)throw Error(`relay generation must be one`);return{session:e.session,send:e.send.bind(e),reference:df(n)}}installRelay(e){let t=this.validate(e,`relay`),n=Cr(t.reference.sessionId);if(this.wireIds.has(n)||this.wireIds.size>=Gl.wireSessions)throw t.session.close(),Error(`wire session reused or capacity reached`);this.wireIds.add(n),this.attemptIds.clear(),this.transitionIds.clear(),this.attemptIds.add(Cr(t.reference.attemptId)),this.highGeneration=1n,this.directAttempts=0,this.relay=t,this.staged=t,this.recovering=!1,this.arm()}control(e){if(e.type===`route.prepare`){if(this.options.role!==`computer`||this.transition||!this.staged||!ff(e.target,this.staged.reference)||this.transitionIds.has(Cr(e.transitionId)))throw Error(`invalid route prepare`);this.transitionIds.add(Cr(e.transitionId)),this.transition={id:e.transitionId.slice(),target:this.staged,phase:`computer:preparing`};return}let t=this.transition;if(!t||!ff(e.target,t.target.reference)||!Er(e.transitionId,t.id))throw Error(`route transition mismatch`);if(e.type===`route.abort`){this.abortWithoutSending();return}if(e.type===`route.prepared`&&t.phase===`phone:prepared`){if(!this.options.prepareReady()||!t.target.session.ready)throw Error(`route prepare gate changed`);t.phase=`phone:committed`,this.sendControl(`route.commit`);return}if(e.type===`route.commit`&&t.phase===`computer:commit`){if(!this.options.prepareReady()||!t.target.session.ready)throw Error(`route commit gate changed`);let e={type:`route.committed`,transitionId:t.id,target:df(t.target.reference)};this.activate(),(!this.relay||!this.sendPayload(this.relay,{kind:`control`,control:e}))&&this.failAll();return}if(e.type===`route.committed`&&t.phase===`phone:committed`){this.activate();return}throw Error(`route control order mismatch`)}sendControl(e){return!this.relay||!this.transition?!1:this.sendPayload(this.relay,{kind:`control`,control:{type:e,transitionId:this.transition.id,target:df(this.transition.target.reference)}})}sendPayload(e,t){let n=Yl(t);try{if(e.send(e.session.seal(n))===!0)return!0}catch{}finally{n.fill(0)}return t.kind===`control`?this.failAll():this.routeLost(e.session),!1}activate(){if(!this.staged)throw Error(`route target missing`);let e=this.active;this.active=this.staged,this.staged=null,this.transition=null,e&&e!==this.relay&&e!==this.active&&e.session.close(),this.clearTimer(),this.snapshot=!0,this.revision+=1}abortWithoutSending(){if(this.transition?.phase===`phone:committed`||!this.active){this.failAll();return}this.discardCandidate(),this.snapshot=!0}discardCandidate(){this.staged&&this.staged!==this.active&&this.staged!==this.relay&&this.staged.session.close(),this.staged=null,this.transition=null,this.clearTimer()}failAll(){for(let e of new Set([this.active,this.staged,this.relay]))e?.session.close();this.active=null,this.staged=null,this.relay=null,this.transition=null,this.clearTimer(),this.recovering=!0,this.snapshot=!0,this.revision+=1}registered(e){return e===this.relay?.session||e===this.active?.session||e===this.staged?.session}clock(){let e=this.options.now();if(!Number.isFinite(e)||e<0||e<this.lastNow)throw this.failAll(),Error(`invalid route clock`);return this.lastNow=e,e}arm(){this.clearTimer(),this.deadline=this.clock()+Gl.attemptMs,this.timer=setTimeout(()=>this.abort(`timeout`),Gl.attemptMs)}clearTimer(){this.timer&&clearTimeout(this.timer),this.timer=null,this.deadline=null}};function mf(e,t,n,r){if(e.seq!==0||e.from!==r||e.to!==n)return!1;try{let i=Bu(Kn(dc(t,Qn.parse(e.body),_c(r,n))));return i.type===`conn.hello`&&i.features?.includes(`session-v2`)===!0}catch{return!1}}var hf=class{options;carrier=null;owner=null;relaySession=null;direct=null;directStartedAt=null;directSetupMs=null;generation=1n;lastFailure=null;retryAt=null;retryFailures=0;nativeAttempts=0;retriesExhausted=!1;traffic={relaySent:0,relayReceived:0,directSent:0,directReceived:0};bootstrapRevision=0;reportedRevision=-1;reportedRoute=null;reportedState=``;recoveryNotified=!1;closed=!1;incoming=Promise.resolve();queued=0;clock;interval;constructor(e){this.options=e,this.clock=e.now??(()=>performance.now()),this.interval=setInterval(()=>this.poll(),100)}get activeRoute(){return this.owner?.activeRoute?.route??null}get ready(){return this.activeRoute!==null&&this.owner?.paused===!1}get routeRevision(){return this.owner?.routeRevision??0}get diagnostics(){let e=this.direct,t=this.activeRoute===`direct`?`direct`:e?.phase??`none`;return{route:this.activeRoute,ready:this.ready,phase:t,lastFailure:this.lastFailure,directSetupMs:this.directSetupMs,...this.traffic}}routeStats(){return this.activeRoute!==`direct`||!this.direct?Promise.resolve(null):this.direct.routeStats().catch(()=>null)}get state(){let{route:e,ready:t,phase:n,lastFailure:r}=this.diagnostics;return{route:e,ready:t,phase:n,lastFailure:r,retryPending:this.retryAt!==null}}sendRelay(e){let t=this.options.sendRelay(e);return t&&e.v===2&&(this.traffic.relaySent+=e.body.length),t}begin(){this.closed||this.options.role!==`phone`||(this.carrier?.close(),this.carrier=this.newCarrier(),this.bootstrapRevision+=1,this.sendRelay(this.carrier.start())||this.bootstrapFailed())}receiveRelay(e){if(this.closed)return Promise.resolve();if(++this.queued>32)return--this.queued,this.bootstrapFailed(),Promise.resolve();let t=this.incoming.then(()=>this.relay(e));return this.incoming=t.catch(()=>this.bootstrapFailed()).finally(()=>{--this.queued}),this.incoming}sendTerminal(e){return this.owner?.sendTerminal(e)??!1}relayLost(){this.owner?.relayLost(),this.carrier?.close(),this.carrier=null,this.changed()}close(){this.closed||(this.closed=!0,clearInterval(this.interval),this.carrier?.close(),this.carrier=null,this.owner?.close(),this.owner=null,this.closeDirect())}interruptDirect(){this.directFailed(`interrupted`)}newCarrier(){return new uf({role:this.options.role,computerFp:this.options.computerFp,phoneFp:this.options.phoneFp,keys:this.options.keys,now:this.clock,newId:()=>ba(16)})}async relay(e){if(this.closed||e.from!==(this.options.role===`phone`?this.options.computerFp:this.options.phoneFp)||e.to!==(this.options.role===`phone`?this.options.phoneFp:this.options.computerFp))return;if(e.v===2){if(this.traffic.relayReceived+=e.body.length,!this.owner||!this.relaySession)return;let t=this.owner.receive(this.relaySession,zl(e.body));if(t?.kind===`terminal`)this.options.terminal(t.bytes,e.body.length);else if(t?.kind===`signal`){let e=this.direct;try{await this.signal(t.bytes)}catch{this.direct===e&&!e?.session?.ready&&this.directFailed(`remote-signal`,e??void 0)}}this.poll();return}if(e.t!==`e2e`)return;if(this.options.role===`computer`&&e.seq===0){if(!mf(e,this.options.keys.pairKey,this.options.computerFp,this.options.phoneFp))return;this.carrier?.close(),this.carrier=this.newCarrier(),this.bootstrapRevision+=1}let t=this.carrier;if(!t)return;let n=this.bootstrapRevision,r=t.receive(e);if(r&&!this.sendRelay(r))throw Error(`bootstrap queue refused`);if(!t.ready)return;let i=t.takeReadySession();this.carrier=null;try{await this.options.commitFloor()}catch(e){throw i.close(),e}if(this.closed||n!==this.bootstrapRevision){i.close();return}this.closeDirect(),this.relaySession=i,this.generation=1n,this.nativeAttempts=0,this.retriesExhausted=!1,this.retryAt=null;let a={session:i,send:e=>this.sendRelay({v:2,t:`e2e`,from:this.options.role===`phone`?this.options.phoneFp:this.options.computerFp,to:this.options.role===`phone`?this.options.computerFp:this.options.phoneFp,body:Rl(e)})};this.owner?this.owner.recover(a):this.owner=new pf({role:this.options.role,computerFp:this.options.computerFp,phoneFp:this.options.phoneFp,relay:a,now:this.clock,newId:()=>ba(16),prepareReady:this.options.prepareReady}),this.options.role===`phone`&&this.owner.begin(),this.recoveryNotified=!1,this.poll()}poll(){if(this.closed||(this.carrier?.closed&&this.bootstrapFailed(),!this.owner))return;try{this.owner.sweep(),this.owner.preparationPending&&this.owner.approve(),this.options.role===`phone`&&(this.owner.status===`uncommitted`||this.owner.status===`relay`&&this.direct?.session&&this.direct.session.ready)&&this.owner.begin(),this.changed(),this.retryDirect(),this.owner.status===`recovering`&&!this.carrier&&!this.recoveryNotified&&(this.recoveryNotified=!0,this.closeDirect(),this.options.failure(`recovery`))}catch{this.options.failure(`recovery`)}let e=this.state,t=JSON.stringify(e);t!==this.reportedState&&(this.reportedState=t,this.options.stateChanged?.(e))}changed(){let e=this.activeRoute,t=this.routeRevision;(this.reportedRevision!==t||this.reportedRoute!==e)&&(this.reportedRevision=t,this.reportedRoute=e,this.options.routeChanged(e,t),e===`direct`&&this.direct&&(this.directStartedAt!==null&&(this.directSetupMs=Math.round(this.clock()-this.directStartedAt)),this.directStartedAt=null,this.direct.cancelDeadline(),this.retryFailures=0,this.retryAt=null,this.lastFailure=null))}retryDirect(){if(this.options.role===`phone`&&this.options.allowDirect&&this.options.native&&!this.retriesExhausted&&!this.direct&&!this.carrier&&this.ready&&this.activeRoute===`relay`&&this.options.prepareReady()&&!(this.retryAt!==null&&this.clock()<this.retryAt)){if(this.nativeAttempts>=Gl.directAttempts){this.retriesExhausted=!0,this.bootstrapFailed();return}this.nativeAttempts+=1,this.retryAt=null,this.startDirect()}}bootstrapFailed(){this.carrier?.close(),this.carrier=null,this.options.failure(`bootstrap`)}async startDirect(e){if(this.closed||this.direct||!this.ready||!this.relaySession||!this.options.native)return;this.generation=e?new DataView(e.generation.buffer,e.generation.byteOffset,8).getBigUint64(0,!0):this.generation+1n;let t=new sf({role:this.options.role,keys:this.options.keys,computerFp:this.options.computerFp,phoneFp:this.options.phoneFp,relay:this.relaySession.description,generation:e?.generation??_l(this.generation),offer:e,native:this.options.native,current:()=>!this.closed&&this.direct===t,committed:()=>this.activeRoute===`direct`,sendSignal:e=>this.sendSignal(e),sent:e=>{this.traffic.directSent+=e},received:e=>{this.traffic.directReceived+=e},ready:e=>{this.owner?.stageDirect({session:e,send:e=>t.send(Rl(e))}),this.options.role===`phone`&&this.owner?.begin()},frame:(e,t)=>{let n=this.owner?.receive(e,zl(t));n?.kind===`terminal`&&this.options.terminal(n.bytes,t.length),this.poll()},failed:e=>this.directFailed(e,t)});this.direct=t,this.directStartedAt=this.clock(),await t.start()}async signal(e){if(!this.relaySession||!this.owner)return;let t=this.direct;if(this.activeRoute===`direct`&&t?.session?.ready)return;let n=ef(e,{sender:this.options.role===`phone`?`computer`:`phone`,sessionId:this.relaySession.description.sessionId,committedGeneration:this.relaySession.description.generation,...t&&{pending:{offerId:t.offerId,generation:t.generation}}});if(n.type===`direct.offer`){if(!this.options.native||this.options.role!==`computer`)return;await this.startDirect(n);return}await t?.signal(n)}sendSignal(e){return this.owner?.sendSignal($d(e))??!1}directFailed(e=`closed`,t){if(t&&this.direct!==t)return;let n=this.direct;if(!n)return;let r=this.diagnostics.phase,i=Math.min(6e4,5e3*2**this.retryFailures);if(this.retryFailures=Math.min(this.retryFailures+1,4),this.retryAt=this.clock()+Math.min(6e4,i*(.8+.4*ba(1)[0]/255)),this.lastFailure=e,!n.session?.ready)try{this.sendSignal({type:`direct.abort`,...n.signalContext(),reason:e===`timeout`?`timeout`:e===`certificate`?`dtls-failed`:`ice-failed`})}catch{}let a=n?.session;a&&this.owner?.routeLost(a),this.closeDirect(),this.options.failure(`direct`,{code:e,phase:r}),this.poll()}closeDirect(){let e=this.direct;this.direct=null,e&&e.close()}};function gf(e,t){return rr.every(n=>e?.includes(n)&&t.includes(n))?[...rr,...e?.includes(`native-history-v1`)&&t.includes(`native-history-v1`)?[ir]:[]]:[]}function _f(e){if(e.length>4096)return!1;for(let t=0;t<e.length;t++){let n=e.charCodeAt(t);if(n>=55296&&n<=56319){let n=e.charCodeAt(++t);if(!(n>=56320&&n<=57343))return!1}else if(n>=56320&&n<=57343)return!1}return!0}const vf=ru.extend({t:ru.shape.t.refine(_f)}).strict(),yf=iu.extend({r:F.array(vf)}).strict(),bf=yf.extend({r:F.array(vf).max(2048)}),xf=F.number().int().min(0).max(2**53-1),Sf={kind:F.literal(`history`),generation:xf,requestId:G,before:xf},Cf=F.custom(e=>Array.isArray(e)&&e.length>0&&e.length<=W.historyLines),wf=F.strictObject({...Sf,status:F.literal(`page`),from:xf,to:xf,oldestAvailable:xf,lines:Cf});function Tf(e){return e.to===e.before&&e.lines.length<=2**53-1-e.from&&e.from+e.lines.length===e.to&&e.oldestAvailable<=e.from}const Ef=wf.refine(Tf),Df=wf.extend({nextBefore:xf}).refine(e=>Tf(e)&&e.nextBefore===e.from),Of=F.strictObject({...Sf,status:F.literal(`boundary`),reason:F.enum([`end`,`truncated`]),oldestAvailable:xf}).refine(e=>e.reason===`end`?e.before===e.oldestAvailable:e.before<e.oldestAvailable),kf=F.discriminatedUnion(`status`,[Ef,Of]),Af=F.discriminatedUnion(`status`,[Df,Of]),jf=F.strictObject({r:F.unknown(),w:F.boolean().optional()}),Mf={ok:!1,code:`invalid-transfer`},Nf={ok:!1,code:`history-line-too-large`};function Pf(e){let t=jf.safeParse(e);if(!t.success||!Array.isArray(t.data.r))return Mf;if(t.data.r.length>2048)return Nf;let n={r:[],...t.data.w===void 0?{}:{w:t.data.w}},r=0,i=0;for(let e of t.data.r){let t=vf.safeParse(e);if(!t.success)return Mf;if(r+=t.data.n??kd(t.data.t),r>W.historyCells||(i+=Gn(t.data).length,i>W.historyBytes))return Nf;n.r.push(t.data)}let a=Gn(n).length;return a>W.historyBytes?Nf:{ok:!0,line:n,bytes:a}}F.unknown().transform((e,t)=>{let n=()=>(t.addIssue({code:`custom`,message:`invalid history record`}),F.NEVER);try{let t=Af.safeParse(e);if(!t.success)return n();let r;if(t.data.status===`boundary`)r=t.data;else{let e=[],i=0;for(let r of t.data.lines){let t=Pf(r);if(!t.ok||(i+=t.bytes,i>W.historyBytes))return n();e.push(t.line)}r={...t.data,lines:e}}return Gn(r).length>W.historyBytes?n():r}catch{return n()}});function Ff(e){try{let t=kf.safeParse(e);if(!t.success)return Mf;if(t.data.status===`boundary`){let e=t.data;return{ok:!0,record:e,bytes:Gn(e)}}let n=t.data,r=[],i=0,a;for(let e=n.lines.length-1;e>=0;e--){let t=Pf(n.lines[e]);if(!t.ok){if(t.code===`invalid-transfer`)return Mf;break}if(i+=t.bytes,i>W.historyBytes)break;r.unshift(t.line);let o=n.from+e,s={...n,from:o,nextBefore:o,lines:r.slice()},c=Gn(s);c.length<=W.historyBytes&&(a={ok:!0,record:s,bytes:c})}return a??{...Nf,before:n.before}}catch{return Mf}}const If=F.number().int().min(0).max(2**53-1),Lf=If.min(1),Rf=au.extend({x:If,y:F.number().int().min(-1).max(2**53-1)}).strict(),zf=F.strictObject({cols:Lf,rows:Lf,cursor:Rf,lines:F.array(yf),scrollbackTotal:If,gen:If,reset:F.boolean().optional(),degraded:F.boolean().optional()});function Bf(e){return e.lines.length===e.rows&&e.cursor.x<=e.cols&&e.cursor.y<e.rows&&Vf(e.lines,e.cols)}function Vf(e,t){return e.every(e=>{let n=0;for(let r of e.r)if(n+=r.n??kd(r.t),n>t)return!1;return!0})}function Hf(e){let t=0,n=0;for(let r of e){t+=r.r.length;for(let e of r.r)n+=kd(e.t)}return{runs:t,points:n}}function Uf(e){let{runs:t,points:n}=Hf(e);return t<=W.runs&&n<=W.codePoints}const Wf=zf.extend({kind:F.literal(`snapshot`),cols:Lf.max(W.cols),rows:Lf.max(W.rows),lines:F.array(bf).max(W.rows)}).refine(e=>Bf(e)&&Uf(e.lines)),Gf=F.strictObject({scroll:If.max(W.rows),changed:F.array(F.strictObject({i:If.max(W.rows-1),line:bf})).max(W.rows),cursor:Rf.extend({x:If.max(W.cols),y:Rf.shape.y.max(W.rows-1)}),scrollbackTotal:If,gen:Lf}),Kf=Gf.extend({kind:F.literal(`diff`)}).refine(e=>{let t=new Set(e.changed.map(e=>e.i)),n=e.changed.map(e=>e.line);return t.size===e.changed.length&&Vf(n,W.cols)&&Uf(n)}),qf=F.discriminatedUnion(`kind`,[Wf,Kf]);function Jf(e){let t=qf.safeParse(e);if(!t.success)throw new V(`malformed`);let n;try{n=Gn(t.data)}catch{throw new V(`malformed`)}if(n.length>W.screenBytes)throw new V(`malformed`);return{record:t.data,bytes:n}}function Yf(e){let{kind:t,...n}=e;return n}function Xf(e){let t=zf.safeParse(e);if(!t.success||!Bf(t.data))return{ok:!1,code:`invalid-transfer`};let n=t.data;if(n.cols>W.cols||n.rows>W.rows||Hf(n.lines).points>W.codePoints)return{ok:!1,code:`screen-too-large`};for(let e=0;e<2;e++){let t=e===0?n:{...n,lines:n.lines.map(Fd),degraded:!0};try{let{record:e,bytes:n}=Jf({kind:`snapshot`,...t});if(e.kind===`snapshot`)return{ok:!0,snapshot:Yf(e),bytes:n}}catch{}}return{ok:!1,code:`screen-too-large`}}function Zf(e){let t=Gf.safeParse(e);if(!t.success)throw new V(`malformed`);return Jf({kind:`diff`,...t.data}).bytes}var Qf=class{options;lanes=[null,null];outstanding=[];state=`open`;nextLane=0;lastSequence=0;acknowledgedThrough=0;constructor(e){if(!lr.shape.subscriptionId.safeParse(e.subscriptionId).success||!lr.shape.sessionId.safeParse(e.sessionId).success)throw Error(`Invalid stream sender identity`);this.options={...e}}canOffer(e){return this.tick()===`open`&&this.lanes[+(e===`history`)]===null}offer(e,t){if(this.tick()!==`open`)return{accepted:!1,reason:`closed`};let n=cr.safeParse(e);if(!n.success||!(t instanceof Uint8Array)||t.length===0)throw Error(`Invalid stream transfer`);let r=+(n.data.kind===`history`),i=r===1?W.historyBytes:W.screenBytes;if(t.length>i)return{accepted:!1,reason:`too-large`};if(this.lanes[r])return{accepted:!1,reason:`busy`};let a;try{a=this.options.newTransferId()}catch(e){throw this.cancel(),e}if(!lr.shape.transferId.safeParse(a).success)throw Error(`Invalid stream transfer identity`);return this.state===`open`?(this.lanes[r]={id:a,meta:n.data,bytes:new Uint8Array(t),count:Math.ceil(t.length/W.chunkBytes),nextIndex:0,acknowledged:0,startedAt:null,progressAt:null},{accepted:!0,transferId:a}):{accepted:!1,reason:`closed`}}pump(){if(this.tick()!==`open`)return 0;let e=0;for(;e<W.unacked&&this.inFlight<W.unacked&&this.tick()===`open`;){let t=this.nextLane,n=this.lanes[t];if((!n||n.nextIndex===n.count)&&(t=1-t,n=this.lanes[t]),!n||n.nextIndex===n.count)break;if(this.lastSequence===2**53-1){this.cancel();break}let r=this.lastSequence+1,i=n.nextIndex,a={type:`stream.chunk`,subscriptionId:this.options.subscriptionId,sessionId:this.options.sessionId,transferId:n.id,sequence:r,index:i,count:n.count,totalBytes:n.bytes.length,data:n.bytes.slice(i*W.chunkBytes,(i+1)*W.chunkBytes),meta:{...n.meta}},o;try{o=this.options.send(a)}catch(e){throw this.cancel(),e}if(o&&e++,this.state!==`open`||!o)break;this.lastSequence=r,n.nextIndex++,n.startedAt===null&&(n.startedAt=this.options.now(),n.progressAt=n.startedAt),this.outstanding.push({sequence:r,transfer:n}),this.nextLane=1-t}return e}acknowledge(e,t){if(e!==this.options.subscriptionId||this.tick()!==`open`)return`ignored`;if(!Number.isSafeInteger(t)||t<1||t>this.lastSequence)return`invalid`;if(t<=this.acknowledgedThrough)return`duplicate`;let n=this.options.now();for(let e of this.outstanding){if(e.sequence>t)break;e.transfer.acknowledged++,e.transfer.progressAt=n,e.transfer.acknowledged===e.transfer.count&&(this.lanes[+(e.transfer.meta.kind===`history`)]=null)}return this.outstanding=this.outstanding.filter(e=>e.sequence>t),this.acknowledgedThrough=t,`advanced`}tick(){let e=this.nextDeadline();return e!==null&&this.options.now()>=e&&this.stop(`stalled`),this.state}nextDeadline(){let e=1/0;for(let t of this.lanes)t&&t.startedAt!==null&&t.progressAt!==null&&(e=Math.min(e,t.startedAt+W.totalMs,t.progressAt+W.progressMs));return Number.isFinite(e)?e:null}cancel(){this.stop(`closed`)}stop(e){this.state=e,this.lanes[0]=null,this.lanes[1]=null,this.outstanding=[]}get inFlight(){return this.outstanding.length}get retainedBytes(){return(this.lanes[0]?.bytes.length??0)+(this.lanes[1]?.bytes.length??0)}},$f=`0.15.0`;const ep=/^owner-([1-9][0-9]*)-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;function tp(e){if(!/^[1-9][0-9]*$/.test(e))return null;let t=Number(e);return Number.isInteger(t)&&t<=2147483647?t:null}function np(e){try{return process.kill(e,0),!0}catch(e){let t=e.code;if(t===`ESRCH`)return!1;if(t===`EPERM`)return!0;throw e}}function rp(e,n){try{t.unlinkSync(N(e,n))}catch(e){if(e.code!==`ENOENT`)throw e}try{t.rmdirSync(e)}catch(e){if(![`ENOENT`,`ENOTEMPTY`,`EEXIST`].includes(e.code??``))throw e}}function ip(e){let n=`${A(e)}.lock-candidate-`;for(let r of t.readdirSync(j(e))){if(!r.startsWith(n))continue;let i=`owner-${r.slice(n.length)}`,a=ep.exec(i),o=a&&tp(a[1]);if(!o)continue;let s=N(j(e),r);try{if(np(o)||!t.lstatSync(s).isDirectory())continue;let e=t.readdirSync(s);e.length===0?t.rmdirSync(s):e.length===1&&e[0]===i&&t.lstatSync(N(s,i)).isFile()&&rp(s,i)}catch{}}}function ap(e){let n=`${e}.lock`,r=`${process.pid}-${ce()}`,i=`${e}.lock-candidate-${r}`,a=`owner-${r}`;t.mkdirSync(i,{mode:448});let o=!1;try{t.writeFileSync(N(i,a),``,{mode:384,flag:`wx`});for(let r=0;r<3;r++){try{t.renameSync(i,n),o=!0;try{ip(e)}catch{}return()=>rp(n,a)}catch(e){if(![`EEXIST`,`ENOTEMPTY`].includes(e.code??``))throw e}try{if(!t.lstatSync(n).isDirectory())throw Error(`Invalid control guard ${n}; inspect it before retrying`);let e=t.readdirSync(n);if(e.length===0)continue;let r=e[0],i=ep.exec(r),a=i&&tp(i[1]);if(e.length!==1||!a||!t.lstatSync(N(n,r)).isFile())throw Error(`Invalid control guard ${n}; inspect its owner marker before retrying`);if(np(a))throw Error(`Control endpoint busy (guard owner pid ${a})`);rp(n,r)}catch(e){if(e.code!==`ENOENT`)throw e}}throw Error(`Control endpoint busy; could not acquire ${n} after three attempts`)}finally{o||rp(i,a)}}var Y=class extends Error{kind;constructor(e){super(`shellbell: ${e} Linux host state; inspect ownership, permissions and host initialization`),this.kind=e}};function X(e){try{return p(e)}catch(e){if(e.code===`ENOENT`)return;throw new Y(`unsafe`)}}function op(e,t){return e.dev===t.dev&&e.ino===t.ino}function Z(e,t){let n=X(e);if(!n)throw new Y(`missing`);if(!n.isDirectory()||n.isSymbolicLink()||n.uid!==t||(n.mode&4095)!=448)throw new Y(`unsafe`);return n}function sp(e){let t=P(e),n=X(t);if(n){if(n.isSymbolicLink()||!n.isDirectory())throw new Y(`unsafe`);return y(t)}return N(cp(j(t)),A(t))}function cp(e){if(X(e))try{return y(e)}catch{throw new Y(`unsafe`)}return N(cp(j(e)),A(e))}function lp(e,t,n,r=!0){let i;try{let a=X(e);if(!a)throw new Y(`missing`);let s=e=>{if(!e.isFile()||e.isSymbolicLink()||n!==void 0&&(e.uid!==n||(e.mode&4095)!=384))throw new Y(`unsafe`);if(e.size>t)throw new Y(`invalid`)};s(a),i=h(e,o.O_RDONLY|o.O_NOFOLLOW|o.O_NONBLOCK);let c=l(i);if(s(c),!op(a,c))throw new Y(`unsafe`);let u=Buffer.alloc(t+ +!!r),d=0;for(;d<u.length;){let e=_(i,u,d,u.length-d,null);if(e===0)break;d+=e}let f=l(i),p=X(e);if(s(f),!p||!op(c,p)||!op(c,f)||c.size!==f.size||c.mtimeMs!==f.mtimeMs||c.ctimeMs!==f.ctimeMs)throw new Y(`unsafe`);if(s(p),d>t||d!==f.size)throw new Y(`invalid`);return u.subarray(0,d)}catch(e){throw e instanceof Y?e:new Y(`unsafe`)}finally{i!==void 0&&a(i)}}function up(e={}){let t=e.uid??process.getuid?.(),n=e.euid??process.geteuid?.();if(!Number.isInteger(t)||t===void 0||t<=0||t!==n)throw Error(`shellbell: Linux hosting requires matching non-root real and effective users`);let r;try{let t=lp(e.machineIdPath??`/etc/machine-id`,256,void 0,!1).toString(`utf8`);if(!/^[0-9a-fA-F]{32}\n?$/.test(t)||/^0{32}\n?$/.test(t))throw Error();r=Buffer.from(t.trim().toLowerCase(),`hex`)}catch{throw Error(`shellbell: Linux machine identity is unavailable or invalid; provision /etc/machine-id before host initialization`)}let i=oe(`sha256`,`shellbell.local-host-scope.v1`).update(r).digest(`hex`),a=i.slice(0,32);return{uid:t,machineId:r.toString(`hex`),hostDigest:i,hostScope:a}}const dp=new WeakMap,fp=new Set([16914836,61267,1481003842,2435016766]);function pp(e,t){let n=dp.get(e),r=n?.root??j(j(e.runtimeDir)),i=n?.fsType??(e=>C(e).type);try{if(Z(r,e.linuxHost.uid),!fp.has(Number(i(r))))throw new Y(`unsafe`);for(let n of[N(r,`shellbell`),e.runtimeDir]){if(!X(n)){if(!t)continue;try{m(n,{mode:448})}catch(e){if(e.code!==`EEXIST`)throw e}}if(Z(n,e.linuxHost.uid),!fp.has(Number(i(n))))throw new Y(`unsafe`)}X(e.runtimeDir)&&mp(e.runtimeDir,e.linuxHost.uid,0,i)}catch{throw Error(`shellbell: Shellbell can't use your login session's runtime folder (XDG_RUNTIME_DIR). Log in to this computer as yourself, directly or over SSH, rather than through sudo or su, and try again. The folder must be private to you (0700) and on local storage.`)}}function mp(e,t,n,r){if(n>2)throw new Y(`unsafe`);let i=v(e);if(i.length>256)throw new Y(`unsafe`);for(let a of i){let i=N(e,a),o=X(i);if(!o||o.uid!==t||o.isSymbolicLink())throw new Y(`unsafe`);if(o.isDirectory()){if(Z(i,t),!fp.has(Number(r(i))))throw new Y(`unsafe`);mp(i,t,n+1,r)}else if(!o.isFile()&&!o.isSocket()||(o.mode&4095)!=384)throw new Y(`unsafe`)}}function hp(e,t){if(j(t)!==j(e.runtimeDir))throw new Y(`unsafe`);Z(t,e.linuxHost.uid);let n=dp.get(e)?.fsType??(e=>C(e).type);if(!fp.has(Number(n(t))))throw new Y(`unsafe`);mp(t,e.linuxHost.uid,0,n)}function gp(e={}){let{uid:t,hostDigest:n,hostScope:r}=up(e),i=e.env??process.env,a=e.home??D(),o=i.SHELLBELL_DIR;if(o!==void 0&&!M(o))throw Error(`shellbell: SHELLBELL_DIR must be absolute`);let s=i.XDG_STATE_HOME&&M(i.XDG_STATE_HOME)?i.XDG_STATE_HOME:N(a,`.local`,`state`),c=sp(o??N(s,`shellbell`,`hosts`,r));X(c)&&Z(c,t);let l=i.XDG_RUNTIME_DIR??`/run/user/${t}`;if(!M(l))throw Error(`shellbell: XDG_RUNTIME_DIR must be absolute`);let u=N(P(l),`shellbell`,ae(`sha256`).update(c).digest(`hex`).slice(0,32)),d={dir:c,serviceOwner:N(c,`service-owner.json`),identity:N(c,`identity.json`),config:N(c,`config.json`),pairings:N(c,`pairings.json`),log:N(c,`agent.log`),runtimeDir:u,sock:N(u,`agent.sock`),pid:N(u,`agent.pid`),linuxHost:{uid:t,hostDigest:n,hostScope:r}};if(Buffer.byteLength(d.sock)>107)throw Error(`shellbell: Linux socket path exceeds 107 bytes; choose a shorter XDG_RUNTIME_DIR`);return dp.set(d,{root:P(l),fsType:e.runtimeFsType??(e=>C(e).type)}),pp(d,!1),d}function _p(e){pp(e,!0)}const vp=F.object({v:F.literal(1),relayUrl:F.string().url(),computerName:F.string().min(1).max(64),accent:F.string().min(1).max(32),notifyMinCommandMs:F.number().int().nonnegative().default(1e4),idleQuietMs:F.number().int().positive().default(4e3),idleMinActiveMs:F.number().int().nonnegative().default(1500),turn:F.boolean().optional(),showAgentConversations:F.boolean().optional(),terminalPlugins:F.array(F.string().min(1).max(4096).refine(e=>e.startsWith(`/`)&&e.endsWith(`.mjs`)&&[...e].every(e=>e.charCodeAt(0)>=32&&e.charCodeAt(0)!==127))).max(29).optional()}),yp=F.object({phoneFp:F.string().regex(/^[a-z2-7]{26}$/),name:F.string().min(1).max(64),platform:F.enum([`ios`,`android`]),ed25519Pub:F.string(),x25519Pub:F.string(),kPair:F.string(),minProtocolVersion:F.literal(2).optional(),pairedAt:F.string(),lastSeenAt:F.string().nullable()}),bp=F.object({v:F.literal(1),phones:F.array(yp)});function xp(e,t){if(!e||e.phoneFp!==t.phoneFp||e.kPair!==t.kPair)return t;if(e.ed25519Pub!==t.ed25519Pub||e.x25519Pub!==t.x25519Pub)throw Error(`shellbell: pairing identity changed without a new pairing key`);return e.minProtocolVersion===2?{...t,minProtocolVersion:2}:t}const Sp=F.object({v:F.literal(1),hostDigest:F.string().regex(/^[0-9a-f]{64}$/),installationId:F.string().uuid()}).strict();function Cp(e){try{let t=rc(JSON.parse(e.toString(`utf8`))),n=ec(t.ed25519.priv,t.x25519.priv,t.createdAt);if(!Buffer.from(n.ed25519.pub).equals(Buffer.from(t.ed25519.pub))||!Buffer.from(n.x25519.pub).equals(Buffer.from(t.x25519.pub)))throw Error();return{identity:t,fp:ic(t.ed25519.pub)}}catch{throw new Y(`invalid`)}}function wp(e){try{return vp.parse(JSON.parse(e.toString(`utf8`)))}catch{throw new Y(`invalid`)}}function Tp(e){try{let{phones:t}=bp.parse(JSON.parse(e.toString(`utf8`)));for(let e of t){let t=xr(e.ed25519Pub);if(t.length!==32||xr(e.x25519Pub).length!==32||xr(e.kPair).length!==32||ic(t)!==e.phoneFp)throw Error()}return t}catch{throw new Y(`invalid`)}}function Ep(e,t){let n=Z(e,t),r=lp(N(e,`identity.json`),65536,t),i=lp(N(e,`config.json`),65536,t),a=lp(N(e,`pairings.json`),1048576,t);if(Cp(r),wp(i),Tp(a),!op(n,Z(e,t)))throw new Y(`unsafe`);return{identity:r,config:i,pairings:a}}function Dp(e){try{if(!X(e.dir))return{status:`absent`};let t=Z(e.dir,e.linuxHost.uid);for(let t of v(e.dir)){let n=/^owner-[1-9][0-9]*-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,r=`owner-${t.slice(34)}`,i=t.startsWith(`service-owner.json.lock-candidate-`)&&n.test(r);if(t===`service-owner.json.lock`||i){let a=N(e.dir,t),o;try{o=Z(a,e.linuxHost.uid);let t=v(a),s=t[0];if(!(i&&t.length===0)){if(t.length!==1||!s||!n.test(s)||i&&s!==r)throw new Y(`unsafe`);lp(N(a,s),0,e.linuxHost.uid)}if(!op(o,Z(a,e.linuxHost.uid)))throw new Y(`unsafe`)}catch(t){let n=X(a);if(!n)continue;try{if(i&&o&&op(o,n)&&v(a).length===0&&op(n,Z(a,e.linuxHost.uid)))continue}catch(e){if(e instanceof Y&&e.kind===`missing`||e.code===`ENOENT`)continue;throw e}throw t}continue}let a=X(N(e.dir,t));if(a&&(!a.isFile()||a.isSymbolicLink()||a.uid!==e.linuxHost.uid||(a.mode&4095)!=384))throw new Y(`unsafe`)}let n=N(e.dir,`host.json`);if(!X(n))return{status:`unmarked`,reason:`Host marker missing; explicit host initialization or recovery required`};let r,i=lp(n,4096,e.linuxHost.uid);try{r=Sp.parse(JSON.parse(i.toString(`utf8`)))}catch{throw new Y(`invalid`)}if(r.hostDigest!==e.linuxHost.hostDigest)return{status:`wrong-host`,reason:`State belongs to a different host; choose this host's state directory`};let a=Ep(e.dir,e.linuxHost.uid);if(!i.equals(lp(n,4096,e.linuxHost.uid))||!op(t,Z(e.dir,e.linuxHost.uid)))throw new Y(`unsafe`);return{status:`ready`,bytes:a}}catch(e){return{status:e instanceof Y&&e.kind===`unsafe`?`unsafe`:`invalid`,reason:`Host state failed validation; inspect files and recover explicitly`}}}function Op(e){let t=Dp(e);return t.status===`ready`?{status:`ready`}:t}function kp(e,t){return t===`unmarked`||t===`wrong-host`?`Shellbell found a state folder at ${e} that this computer didn't create. It may have been copied from another computer, and two computers must never share one identity, so Shellbell won't use it. Move the folder aside to start fresh, or see the Linux guide to move Shellbell from another computer.`:`Shellbell's state folder at ${e} failed its safety checks. It must belong to you, must not be writable by anyone else, and should hold only Shellbell's files. Run \`shellbell doctor\` for details.`}function Ap(e,t=Op(e).status){return Error(t===`absent`?"shellbell: Shellbell isn't set up on this computer yet. Run `shellbell install`.":`shellbell: ${kp(e.dir,t)}`)}function jp(e){let t=Dp(e);if(!(`bytes`in t))throw Ap(e,t.status);return t.bytes}function Mp(e){let{status:t}=Op(e);if(t!==`ready`)throw Ap(e,t)}function Np(e){return Cp(jp(e).identity)}function Pp(e){return wp(jp(e).config)}function Fp(e){return Tp(jp(e).pairings)}const Ip=[`emerald`,`blue`,`amber`,`violet`,`rose`,`cyan`,`lime`,`orange`];function Lp(e=process.env.SHELLBELL_DIR??N(D(),`.shellbell`)){return{dir:e,serviceOwner:N(e,`service-owner.json`),identity:N(e,`identity.json`),pairings:N(e,`pairings.json`),config:N(e,`config.json`),log:N(e,`agent.log`),sock:N(e,`agent.sock`),pid:N(e,`agent.pid`)}}function Rp(e){if(e.linuxHost){Mp(e);return}m(e.dir,{recursive:!0,mode:448}),i(e.dir,448)}function zp(e,t,n){Up(e,t,t=>{n?.(),b(t,e)})}const Bp=new Set([`EPERM`,`ENOTSUP`,`EOPNOTSUPP`,`EXDEV`]);function Vp(e,t){try{return Up(e,t,n=>{try{f(n,e)}catch(n){if(!Bp.has(n.code??``))throw n;Hp(e,t)}ee(n)}),!0}catch(e){if(e.code===`EEXIST`)return!1;throw e}}function Hp(e,t){let n=h(e,`wx`,384),r=l(n),i=!1;try{c(n,384);let e=typeof t==`string`?Buffer.from(t):t,r=0;for(;r<e.byteLength;){let t=E(n,e,r,e.byteLength-r);if(t<=0)throw Error(`secret file write made no progress`);r+=t}u(n),i=!0}finally{if(a(n),!i)try{let t=p(e);t.dev===r.dev&&t.ino===r.ino&&ee(e)}catch{}}}function Up(e,t,n){let r=`${e}.tmp-${process.pid}`,o=null;try{let s;try{s=h(r,`wx`,384)}catch(t){if(t.code!==`EEXIST`)throw t;r=`${e}.tmp-${process.pid}-${ce()}`,s=h(r,`wx`,384)}try{let e=l(s);o={dev:e.dev,ino:e.ino};let n=typeof t==`string`?Buffer.from(t):t,r=0;for(;r<n.byteLength;){let e=E(s,n,r,n.byteLength-r);if(e<=0)throw Error(`atomic file write made no progress`);r+=e}u(s)}finally{a(s)}i(r,384),n(r)}catch(e){try{if(o){let e=p(r);e.dev===o.dev&&e.ino===o.ino&&ee(r)}}catch{}throw e}}function Wp(e){let t;try{t=g(e,`utf8`)}catch(t){throw Error(`shellbell: cannot read ${e}: ${t.message}`)}try{return JSON.parse(t)}catch{throw Error(`shellbell: ${e} is not valid JSON`)}}function Gp(){return{v:1,relayUrl:`wss://relay.shellbell.dev`,computerName:O().replace(/\.local$/,``)||`Mac`,accent:Ip[0],notifyMinCommandMs:1e4,idleQuietMs:3e4,idleMinActiveMs:1500}}function Kp(e){return Zp(e,()=>{if(em(e),e.linuxHost)return Pp(e);if(!X(e.dir))return Gp();let t=Z(e.dir,process.getuid());if(!X(e.config))return Gp();let n=lp(e.config,Yp,process.getuid());if(!op(t,Z(e.dir,process.getuid())))throw new Y(`unsafe`);let r;try{r=JSON.parse(n.toString(`utf8`))}catch{throw new Xp(`invalid`,e.config,`not valid JSON`)}return Qp(e,r)})}function qp(e){return e.linuxHost?Kp(e):nm(e,()=>{let t=Kp(e);return X(e.config)||rm(e,t),t})}function Jp(e,t){return nm(e,()=>t(Kp(e)))}const Yp=65536;var Xp=class extends Error{code;constructor(e,t,n=e){super(`shellbell: config ${n} at ${t}`),this.code=e,this.name=`ConfigEditError`}};function Zp(e,t){try{return t()}catch(t){throw t instanceof Xp?t:new Xp(t instanceof Y?t.kind===`invalid`?`invalid`:`unsafe`:`io`,e.config)}}function Qp(e,t){let n=vp.safeParse(t);if(!n.success)throw new Xp(`invalid`,e.config);return n.data}function $p(e){if(e.linuxHost){Mp(e);return}Z(e.dir,process.getuid())}function em(e){if([e.dir,e.config].some(e=>Buffer.byteLength(e)>4096||e.includes(`\0`))||j(P(e.config))!==P(e.dir))throw new Xp(`unsafe`,e.config)}function tm(e,t){let n=`${A(e)}.lock`;for(let r of v(j(e))){if(r!==n&&!r.startsWith(`${n}-candidate-`))continue;let i=N(j(e),r);if(X(i)){Z(i,t);for(let e of v(i)){let n=X(N(i,e));if(n&&(!n.isFile()||n.isSymbolicLink()||n.uid!==t||(n.mode&4095)!=384))throw new Y(`unsafe`)}}}}function nm(e,t){let n=Zp(e,()=>{if(em(e),!e.linuxHost&&!X(e.dir))try{m(e.dir,{recursive:!0,mode:448})}catch(e){if(e.code!==`EEXIST`)throw e}$p(e);let t=e.config;e.linuxHost&&(_p(e),t=N(e.runtimeDir,`config-${ae(`sha256`).update(e.config).digest(`hex`)}`)),tm(t,e.linuxHost?.uid??process.getuid());try{return ap(t)}catch(t){throw t instanceof Error&&t.message.startsWith(`Control endpoint busy`)?new Xp(`busy`,e.config):t instanceof Error&&t.message.startsWith(`Invalid control guard`)?new Xp(`unsafe`,e.config):t}}),r;try{r=t()}catch(e){try{n()}catch{}throw e}return Zp(e,n),r}function rm(e,t){Zp(e,()=>{let n=`${JSON.stringify(Qp(e,t),null,2)}\n`;if(Buffer.byteLength(n)>Yp)throw new Xp(`invalid`,e.config);zp(e.config,n,()=>{$p(e),Kp(e)})})}function im(e,t){return nm(e,()=>{let n=Qp(e,t(Kp(e)));return rm(e,n),n})}function am(e){if(e.linuxHost)return Fp(e);if(Rp(e),!s(e.pairings))return[];let t=bp.safeParse(Wp(e.pairings));if(!t.success)throw Error(`shellbell: invalid pairings at ${e.pairings}: ${F.prettifyError(t.error)}`);return t.data.phones}function om(e,t){Rp(e);let n=new Map(am(e).map(e=>[e.phoneFp,e])),r=t.map(e=>xp(n.get(e.phoneFp),e)),i=bp.parse({v:1,phones:r}),a=`${JSON.stringify(i,null,2)}\n`;if(e.linuxHost){if(Buffer.byteLength(a)>1048576)throw Error(`shellbell: Linux pairings exceed their state size limit`);Tp(Buffer.from(a))}return zp(e.pairings,a,e.linuxHost?()=>Mp(e):void 0),i.phones}const sm=new Set([`Error`,`TypeError`,`RangeError`,`ReferenceError`,`SyntaxError`,`URIError`,`EvalError`,`AggregateError`,`AbortError`,`TimeoutError`,`ProtocolError`,`BackendUnavailable`,`SessionGone`,`Unsupported`,`BadWindow`,`HerdrError`,`ITerm2AuthError`,`ConfigEditError`,`NativeControllerError`,`ControlV2ClientError`]);function cm(e){try{if(!(e instanceof Error))return`unknown`;let t=e.name;return typeof t==`string`&&sm.has(t)?t:`Error`}catch{return`unknown`}}function lm(e){return typeof e==`string`&&(sm.has(e)||e===`unknown`)}function um(e){let t=e=>lm(e?.err)?{err:e.err}:void 0,n={debug:()=>{},info:(n,r)=>e.info(n,t(r)),warn:(n,r)=>e.warn(n,t(r)),error:(n,r)=>e.error(n,t(r)),child:()=>n};return n}const dm=1048576;function fm(e){return e.isFile()&&e.uid===process.getuid?.()&&e.nlink===1}function pm(e,t){return e.dev===t.dev&&e.ino===t.ino}function mm(e,t){let n;try{let i;try{i=p(e)}catch(e){if(e.code!==`ENOENT`)return}if(i&&!fm(i))return;n=h(e,o.O_WRONLY|o.O_APPEND|o.O_NOFOLLOW|o.O_NONBLOCK|(i?0:o.O_CREAT|o.O_EXCL),384);let a=l(n),s=p(e);if(!fm(a)||!fm(s)||!pm(a,s)||i&&!pm(i,a))return;c(n,384),r(n,t)}catch{}finally{if(n!==void 0)try{a(n)}catch{}}}function hm(e){let t;try{let n=p(e);if(!fm(n)||n.size<dm)return;t=h(e,o.O_RDWR|o.O_NOFOLLOW|o.O_NONBLOCK);let r=l(t);if(!fm(r)||!pm(n,r)||r.size<dm)return;c(t,384);let i=Math.max(0,r.size-dm),a=Buffer.alloc(r.size-i);for(let e=0;e<a.length;){let n=_(t,a,e,a.length-e,i+e);if(n===0)return;e+=n}for(let t=4;t>=1;t--)s(`${e}.${t}`)&&b(`${e}.${t}`,`${e}.${t+1}`);zp(`${e}.1`,a);let u=p(e);fm(u)&&pm(u,r)&&fm(l(t))&&d(t,0)}catch{}finally{if(t!==void 0)try{a(t)}catch{}}}function gm(e,t={}){let n=e.stdout??process.stdout.isTTY===!0,r=(r,i,a)=>{if(r===`debug`&&!e.verbose)return;let o={t:new Date().toISOString(),level:r,msg:i,...t,...a};if(e.file){hm(e.file);try{mm(e.file,`${JSON.stringify(o)}\n`)}catch{}}if(n){let e=Object.keys({...t,...a}).length?` ${JSON.stringify({...t,...a})}`:``,n=`${o.t.slice(11,19)} ${r.padEnd(5)} ${i}${e}`;(r===`error`||r===`warn`?process.stderr:process.stdout).write(`${n}\n`)}};return{debug:(e,t)=>r(`debug`,e,t),info:(e,t)=>r(`info`,e,t),warn:(e,t)=>r(`warn`,e,t),error:(e,t)=>r(`error`,e,t),child:n=>gm(e,{...t,...n})}}function _m(e){if(!vm(e.reported)||!vm(e.before)||e.before>e.reported||!Number.isSafeInteger(e.count)||e.count<1||e.count>W.historyLines||e.capture===null||typeof e.capture!=`object`)throw RangeError(`invalid history read request`)}function vm(e){return Number.isSafeInteger(e)&&e>=0}var ym=class extends Error{hint;constructor(e,t){super(e),this.hint=t,this.name=`BackendUnavailable`}},bm=class extends Error{constructor(e){super(`session gone: ${e}`),this.name=`SessionGone`}},xm=class extends Error{code;constructor(e){super(`Terminal input ${e}`),this.code=e,this.name=`TerminalInputError`}},Sm=class extends Error{constructor(e){super(`unsupported: ${e}`),this.name=`Unsupported`}},Cm=class extends Error{constructor(e=`No terminal app on this computer can show a new session.`){super(e),this.name=`NotShownOnComputer`}},wm=class extends Error{constructor(e){super(`bad-window: ${e}`),this.name=`BadWindow`}};async function Tm(e,t){let n;try{return await Promise.race([Promise.resolve().then(e),new Promise((e,r)=>{n=setTimeout(()=>r(Error(`Terminal adapter deadline exceeded`)),t),n.unref()})])}finally{n&&clearTimeout(n)}}function Em(e,t){return`${e}:${t}`}const Dm=Zl.options,Om=new Set([`iterm2`]);function km(e){let t=e.indexOf(`:`);if(t<=0)return null;let n=Ql.safeParse(e.slice(0,t));return n.success?{name:n.data,native:e.slice(t+1)}:null}var Am=class{log;listTimeoutMs;conversationPermits=new Map;conversationSupported(e){let t=km(e),n=t?this.members.get(t.name):void 0;return!!n&&n.isConnected!==!1&&!!n.conversationReference}async conversationReference(e,t){let n=km(e);if(!n||t.aborted)return null;let r=this.members.get(n.name);if(!r||r.isConnected===!1||!r.conversationReference)return null;let i=this.conversationPermits.get(e);if(i?i.count>=12:this.conversationPermits.size>=20)return null;let a,o=new Promise(e=>{a=e}),s=i??{tail:Promise.resolve(),count:0},c=s.tail;s.tail=c.then(()=>o),s.count++,this.conversationPermits.set(e,s);let l=()=>{};try{if(i){let e=()=>{},n=new Promise(n=>{e=n,t.addEventListener(`abort`,e,{once:!0})});if(await Promise.race([c,n]),t.removeEventListener(`abort`,e),t.aborted)return null}let r=this.members.get(n.name);if(!r||r.isConnected===!1||!r.conversationReference)return null;let a=this.historyMembership.get(n.name),o=!0;l=this.on(t=>{(r.isConnected===!1||(t.type===`session-removed`||t.type===`conversation-changed`)&&t.sessionId===e)&&(o=!1)});let s=await r.conversationReference(n.native,t);return s&&o&&!t.aborted&&this.historyMembership.get(n.name)===a&&this.members.get(n.name)===r&&this.members.get(n.name)?.isConnected!==!1?s:null}catch{return null}finally{l(),a(),--s.count===0&&this.conversationPermits.get(e)===s&&this.conversationPermits.delete(e)}}notificationRevision=0;async notificationFacts(e){let t=km(e);if(!t)return;let n=this.members.get(t.name);if(!n||n.isConnected===!1)return;let r=this.notificationRevision,i=await n.notificationFacts?.(t.native);if(i&&i.sessionId===t.native&&this.members.get(t.name)===n&&r===this.notificationRevision&&this.connected().some(e=>e.name===t.name))return{...i,sessionId:e,revision:JSON.stringify([r,i.revision])}}members=new Map;labels=new Map;hostCommands=new Map;hostedLaunchers=new Map;hostedPending=0;sessionLaunchers=new Map;setupReporters=new Map;setupListeners=new Set;sessionStartups=new Map;startupWaiters=new Map;unsubs=new Map;historyMembership=new Map;historyPermits=new Map;inputCount=0;inputBytes=0;inputQueues=new Map;handlers=new Set;constructor(e,t=8e3){this.log=e,this.listTimeoutMs=t}orderedNames(){let e=new Set([...this.members.keys(),...this.sessionLaunchers.keys()]);for(let t of Dm)e.delete(t);return[...Dm,...[...e].sort()]}defaultLabel(e){let t=Zl.safeParse(e);return t.success?$l[t.data]:e}catalog(){return this.orderedNames().map(e=>{let t=this.memberConnected(e);return{name:e,label:this.labels.get(e)??this.defaultLabel(e),capabilities:this.members.get(e)?.capabilities??{subscribe:!1,prompts:!1,createSession:!1,focus:!1,history:!1,absoluteLines:!1},connected:t,launchable:!t&&(this.sessionLaunchers.get(e)?.available()??!1)}})}registerHostedLauncher(e,t){let n=uu.parse(e),r=`${n.backend}:${n.host}`;if(!this.hostedLaunchers.has(r)&&this.hostedLaunchers.size>=64)throw new ym(`Too many terminal launch targets`,`Disable a launch target first.`);let i={target:n,launcher:t};return this.hostedLaunchers.set(r,i),this.emit({type:`layout-changed`}),()=>{this.hostedLaunchers.get(r)===i&&(this.hostedLaunchers.delete(r),this.emit({type:`layout-changed`}))}}launchTargets(){return[...this.hostedLaunchers.values()].filter(({target:e,launcher:t})=>t.available()&&(this.memberConnected(e.backend)||this.sessionLaunchers.get(e.backend)?.available())).map(({target:e})=>({...e})).sort((e,t)=>`${e.backend}:${e.host}`.localeCompare(`${t.backend}:${t.host}`))}launchIssues(){let e=new Set(this.launchTargets().map(e=>e.backend)),t=new Map;for(let{target:n,launcher:r}of this.hostedLaunchers.values()){if(e.has(n.backend)||t.has(n.backend))continue;let i=r.unavailableReason?.();i&&t.set(n.backend,i)}return pu.parse([...t].map(([e,t])=>({backend:e,reason:t})))}preferredHost(e){return yu(e,this.launchTargets())?.host}async requireShownOnComputer(e,t){if(!Om.has(e.name)&&!(e.shownOnComputer&&await Tm(()=>e.shownOnComputer(t),5e3)))throw new Cm(`This session is not open in a terminal window on your computer, so it cannot be split or extended from the phone.`)}async createHostedSession(e,t=!1){let n=`${e.backend}:${e.host}`,r=this.hostedLaunchers.get(n);if(e.windowId!==void 0||!r?.launcher.available())throw new ym(`Terminal launch target is unavailable`,`Check the selected terminal app on your computer.`);if(this.hostedPending>=8)throw new ym(`Terminal startup is busy`,`Wait for the current startup to finish.`);this.hostedPending++;let i=(async()=>{if(this.hostedLaunchers.get(n)!==r)throw new bm(n);let i=this.members.get(e.backend),a;if(!i||i.isConnected===!1){let t=await this.startSession(e.backend,e.initialSize);i=t.backend,a=t.sessionId}if(this.hostedLaunchers.get(n)!==r||this.members.get(e.backend)!==i)throw new bm(n);let o=e.initialSize?await r.launcher.create(i,a,e.initialSize):t?await r.launcher.create(i,a,void 0,{tab:!0}):await r.launcher.create(i,a);if(this.hostedLaunchers.get(n)!==r||this.members.get(e.backend)!==i||i.isConnected===!1)throw new bm(n);return{sessionId:Em(e.backend,o.sessionId),opened:o.opened,openedIn:r.target.label}})().finally(()=>{this.hostedPending--});return Tm(()=>i,3e4)}get capabilities(){let e=[...this.members.values()].filter(e=>e.isConnected!==!1).map(e=>e.capabilities),t=t=>e.some(e=>e[t]);return{subscribe:t(`subscribe`),prompts:t(`prompts`),createSession:t(`createSession`)||[...this.sessionLaunchers.values()].some(e=>e.available()),focus:t(`focus`),history:t(`history`),absoluteLines:e.length>0&&e.every(e=>e.absoluteLines)}}add(e,t,n){let r=cu.parse({name:e.name,label:t??this.defaultLabel(e.name),capabilities:e.capabilities,connected:!1,launchable:!1});if(!this.orderedNames().includes(e.name)&&this.orderedNames().length>=32)throw new ym(`Too many terminal adapters`,`Disable an adapter before adding another.`);let i={},a=e.on(t=>{this.members.get(e.name)===e&&this.historyMembership.get(e.name)===i&&this.emit(Mm(e.name,t))});if(typeof a!=`function`)throw Error(`Terminal adapter subscription is invalid`);let o=this.unsubs.get(e.name);this.labels.set(e.name,r.label),this.hostCommands.set(e.name,n??(e.name===`tmux`||e.name===`herdr`?[e.name]:[])),this.members.set(e.name,e),this.historyMembership.set(e.name,i),this.unsubs.set(e.name,a);try{o?.()}catch(t){this.log.warn(`backend subscription cleanup failed`,{backend:e.name,err:cm(t)})}this.emit({type:`layout-changed`})}remove(e){let t=this.unsubs.get(e);this.unsubs.delete(e),this.members.delete(e),this.labels.delete(e),this.hostCommands.delete(e),this.historyMembership.delete(e);try{t?.()}catch(t){this.log.warn(`backend subscription cleanup failed`,{backend:e,err:cm(t)})}this.emit({type:`layout-changed`})}connected(){let e=[];for(let t of this.orderedNames()){let n=this.members.get(t);n&&n.isConnected!==!1&&e.push({name:n.name,capabilities:n.capabilities})}return e}registerSessionLauncher(e,t){if(Ql.parse(e),!this.orderedNames().includes(e)&&this.orderedNames().length>=32)throw new ym(`Too many terminal adapters`,`Disable an adapter before adding another.`);return this.sessionLaunchers.set(e,t),this.sessionStartups.delete(e),this.emit({type:`layout-changed`}),()=>{this.sessionLaunchers.get(e)===t&&(this.sessionLaunchers.delete(e),this.sessionStartups.delete(e),this.emit({type:`layout-changed`}))}}launchable(){return this.orderedNames().filter(e=>!this.memberConnected(e)&&this.sessionLaunchers.get(e)?.available())}async startSession(e,t){let n=this.sessionLaunchers.get(e);if(!n?.available())throw new bm(`backend ${e}`);let r=this.startupWaiters.get(e)??0;if(r>=8)throw new ym(`Terminal startup is busy`,`Try again after the current startup finishes.`);this.startupWaiters.set(e,r+1);try{let r=this.sessionStartups.get(e);if(!r){let i=Promise.resolve().then(()=>{if(this.sessionLaunchers.get(e)!==n)throw new bm(`backend ${e}`);return t?n.start(t):n.start()}).then(e=>({...e})).finally(()=>{this.sessionStartups.get(e)===i&&this.sessionStartups.delete(e)});r=i,this.sessionStartups.set(e,i)}let i=await r;if(this.sessionLaunchers.get(e)!==n||this.members.get(e)!==i.backend||i.backend.isConnected===!1)throw new bm(`backend ${e}`);let a=i.sessionId;return i.sessionId=void 0,{backend:i.backend,sessionId:a}}finally{let t=(this.startupWaiters.get(e)??1)-1;t===0?this.startupWaiters.delete(e):this.startupWaiters.set(e,t)}}member(e){return this.members.get(e)}registerSetupReporter(e,t){return this.setupReporters.set(e,t),()=>{this.setupReporters.get(e)===t&&this.setupReporters.delete(e)}}onSetupChanged(e){return this.setupListeners.add(e),()=>this.setupListeners.delete(e)}notifySetupChanged(){for(let e of this.setupListeners)try{e()}catch{}}terminalSetup(){return this.orderedNames().flatMap(e=>{let t=this.setupReporters.get(e),n=this.memberConnected(e);if(!t&&!this.members.has(e))return[];let r={};try{r=t?.(n)??{}}catch{r=n?{}:{issue:`failed`}}return[{name:e,connected:n,...r.issue?{issue:r.issue}:{},...r.issue&&r.detail?{detail:r.detail}:{}}]}).slice(0,16)}connectTerminal(e){let t=this.setupReporters.get(e)?.connect;if(!t)return!1;try{t().catch(e=>this.log.debug(`terminal connect failed`,{error:cm(e)}))}catch(e){this.log.debug(`terminal connect failed`,{error:cm(e)})}return!0}status(){return this.orderedNames().map(e=>({name:e,connected:this.memberConnected(e)}))}nameOf(e){return km(e)?.name??null}capabilitiesOf(e){let t=this.nameOf(e);return t?this.members.get(t)?.capabilities??null:null}async connect(){}async close(){let e=[...this.members.values()],t=[...this.unsubs.values()];this.sessionLaunchers.clear(),this.hostedLaunchers.clear(),this.sessionStartups.clear(),this.historyMembership.clear(),this.unsubs.clear(),this.members.clear(),this.labels.clear(),this.hostCommands.clear();for(let e of t)try{e()}catch(e){this.log.warn(`backend subscription cleanup failed`,{err:cm(e)})}await Promise.all(e.map(async e=>{try{await Tm(()=>e.close(),this.listTimeoutMs)}catch(t){this.log.warn(`backend close failed`,{backend:e.name,err:cm(t)})}}))}async listSessions(){let e=this.orderedNames().map(e=>({name:e,backend:this.members.get(e),membership:this.historyMembership.get(e)})),t=(await Promise.all(e.map(async e=>({...e,sessions:await this.safeListSessions(e.backend,e.name)})))).filter(({name:e,backend:t,membership:n})=>t&&this.members.get(e)===t&&this.historyMembership.get(e)===n),n=new Set;for(let{name:e,backend:r}of t)try{for(let e of r?.representedWindows?.()??[])n.add(JSON.stringify([e.backend,e.windowId]))}catch(t){this.log.warn(`terminal window relationships unavailable`,{backend:e,err:cm(t)})}let r=[];for(let{name:e,backend:i,sessions:a}of t)for(let o of a){try{let r=i?.nativeWindowIdOf?.(o.id);if(r&&n.has(JSON.stringify([e,r])))continue;let a=i?.hostedProcess?.(o.id);if(a&&t.some(t=>t.name!==e&&this.memberConnected(t.name)&&this.hostCommands.get(t.name)?.includes(a)))continue}catch(t){this.log.warn(`terminal host relationship unavailable`,{backend:e,err:cm(t)})}r.push(jm(e,o))}return r}projectFolder(e){let t=km(e),n=t?this.members.get(t.name):void 0;if(t&&n?.projectFolder)try{return n.projectFolder(t.native)}catch(e){this.log.warn(`session project folder unavailable`,{backend:t.name,err:cm(e)});return}}memberConnected(e){let t=this.members.get(e);return!!t&&t.isConnected!==!1}async safeListSessions(e,t){if(!e)return[];let n=this.historyMembership.get(t);try{let r=await Tm(()=>e.listSessions(),this.listTimeoutMs);return this.members.get(t)!==e||this.historyMembership.get(t)!==n?[]:r}catch(e){return this.log.warn(`listSessions failed for backend; returning the other backends' sessions`,{backend:t,err:cm(e)}),[]}}target(e){let t=km(e),n=t?this.members.get(t.name):void 0;if(!t||!n)throw new bm(e);return{backend:n,native:t.native}}async getScreen(e,t){let{backend:n,native:r}=this.target(e);return t===void 0?n.getScreen(r):n.getScreen(r,t)}async getHistory(e,t,n){let{backend:r,native:i}=this.target(e);return r.getHistory(i,t,n)}async getHistoryPage(e,t){let{backend:n,native:r}=this.target(e);if(_m(t),t.signal.aborted)return{status:`cancelled`};let i=n.getHistoryPage;if(!i)return{status:`unavailable`,reason:`unsupported`};if(this.historyPermits.has(e)||this.historyPermits.size>=10)return{status:`unavailable`,reason:`busy`};let a={};this.historyPermits.set(e,a);let o=this.historyMembership.get(n.name);try{let e=await i.call(n,r,t);return t.signal.aborted?{status:`cancelled`}:this.historyMembership.get(n.name)===o?e:{status:`reset`}}catch(e){if(t.signal.aborted)return{status:`cancelled`};if(this.historyMembership.get(n.name)!==o)return{status:`reset`};throw e}finally{this.historyPermits.get(e)===a&&this.historyPermits.delete(e)}}async sendText(e,t,n,r){let{backend:i,native:a}=this.target(e);return this.enqueueInput(e,i,t,()=>i.sendText(a,t),n,r)}async clickMouse(e,t,n){let{backend:r,native:i}=this.target(e);if(!r.capabilities.mouseClick||!r.clickMouse)throw new Sm(`mouse input`);return this.enqueueInput(e,r,``,()=>r.clickMouse(i,t),n)}async sendInput(e,t,n,r){let{backend:i,native:a}=this.target(e);if(!i.capabilities.terminalInput||!i.sendInput)throw new Sm(`terminal input`);return this.enqueueInput(e,i,t,()=>i.sendInput(a,t),n,r)}openVtStream(e){let{backend:t,native:n}=this.target(e);if(!t.capabilities.vtStream||!t.openVtStream)throw new Sm(`vt stream`);return t.openVtStream(n)}async paste(e,t,n,r,i){let{backend:a,native:o}=this.target(e);if(!a.capabilities.terminalPaste||!a.paste)throw new Sm(`terminal paste`);return this.enqueueInput(e,a,t,()=>a.paste(o,t,n),r,i)}enqueueInput(e,t,n,r,i,a){let o=Buffer.byteLength(n);if(this.inputCount>=256||this.inputBytes+o>1048576)return Promise.reject(new xm(`busy`));let s=this.inputQueues.get(e);if(s||(s={backend:t,membership:this.historyMembership.get(t.name),tail:Promise.resolve(),pending:0,valid:!0},this.inputQueues.set(e,s)),!s.valid||s.backend!==t)return Promise.reject(new xm(`cancelled`));let c=s;c.pending++,this.inputCount++,this.inputBytes+=o;let l=()=>this.members.get(t.name)===t&&t.isConnected!==!1&&this.historyMembership.get(t.name)===c.membership,u=()=>{if(!c.valid||i?.()===!1)throw new xm(`cancelled`);if(!l())throw new bm(e)},d=c.tail.then(async()=>{u(),a&&(await a(),u()),await r(),c.valid&&l()&&this.emit({type:`input-accepted`,sessionId:e})});return c.tail=d.catch(e=>{(!(e instanceof xm)||!Du.safeParse(e.code).success)&&(c.valid=!1)}),d.finally(()=>{this.inputCount--,this.inputBytes-=o,--c.pending===0&&this.inputQueues.get(e)===c&&this.inputQueues.delete(e)})}async createSession(e){let t=e=>({sessionId:e,opened:`tab`});if(e.kind===`split`){let{backend:t,native:n}=this.target(e.sessionId),r={kind:`split`,sessionId:n,direction:e.direction};return await this.requireShownOnComputer(t,r),{sessionId:Em(t.name,await t.createSession(r)),opened:`split`}}if(e.explicit===!0||e.initialSize!==void 0){let{near:t,explicit:n,...r}=e;return this.createWindow(r)}if(e.windowId!==void 0){let n=km(e.windowId);if(!n||n.name!==e.backend)throw new wm(e.windowId);let r=this.members.get(e.backend);if(!r||r.isConnected===!1)throw new bm(e.windowId);if(Om.has(e.backend))return t(Em(r.name,await r.createSession({kind:`tab`,backend:e.backend,windowId:n.native})));let i=await this.createTab(r,n.native,e.host);if(i===void 0)throw new Cm(`That window isn't open on your computer any more, so the tab couldn't open there. Open a new window instead.`);return i}if(e.near===`focused`){let n=this.members.get(e.backend);if(n&&n.isConnected!==!1&&n.focusedWindow){let r=await Tm(()=>n.focusedWindow(),5e3).catch(()=>void 0);if(r!==void 0){if(Om.has(e.backend))try{return t(Em(n.name,await n.createSession({kind:`tab`,backend:e.backend,windowId:r})))}catch(t){let i=await n.listSessions().catch(()=>null);if(!i||i.some(e=>e.windowId===r))throw t;this.log.warn(`focused window closed before its tab`,{backend:e.backend,err:cm(t)})}else{let t=await this.createTab(n,r,e.host);if(t!==void 0)return t}}}}let{near:n,explicit:r,...i}=e;return this.createWindow(i,n===`focused`)}async createTab(e,t,n){let r={kind:`tab`,backend:e.name,windowId:t},i=()=>e.shownOnComputer?Tm(()=>e.shownOnComputer(r),5e3):Promise.resolve(!1);if(!await i())return;let a=await e.createSession(r);if(await i().catch(()=>!1))return{sessionId:Em(e.name,a),opened:`tab`};try{if(!e.discardSession)throw Error(`no discard`);await e.discardSession(a)}catch(t){throw this.log.warn(`unshown tab not closed`,{backend:e.name,err:cm(t)}),new Cm(`The new tab didn't stay where your computer shows it, and it could not be closed. Check the session list.`)}return this.createWindow({kind:`tab`,backend:e.name,...n!==void 0&&{host:n}})}async createWindow(e,t=!1){if(e.host!==void 0)return this.createHostedSession(e,t);if(!Om.has(e.backend)){let n=this.preferredHost(e.backend);if(n===void 0)throw new Cm;return this.createHostedSession({kind:`tab`,backend:e.backend,host:n,...e.initialSize?{initialSize:e.initialSize}:{}},t)}let n=this.members.get(e.backend);if(!n||n.isConnected===!1){let t=await this.startSession(e.backend,e.initialSize);if(t.sessionId)return{sessionId:Em(e.backend,t.sessionId),opened:`window`};n=t.backend}let r=await n.createSession({kind:`tab`,backend:e.backend,windowId:void 0,...e.initialSize?{initialSize:e.initialSize}:{}});return{sessionId:Em(n.name,r),opened:`window`}}async focus(e){let{backend:t,native:n}=this.target(e);return t.focus(n)}setWatched(e){let t=new Map;for(let e of this.members.keys())t.set(e,[]);for(let n of e){let e=km(n);e&&t.get(e.name)?.push(e.native)}for(let[e,n]of t)try{this.members.get(e)?.setWatched?.(n)}catch(t){this.log.warn(`setWatched failed for backend`,{backend:e,err:cm(t)})}}setReported(e,t){let n=km(e);if(n)try{this.members.get(n.name)?.setReported?.(n.native,t)}catch(e){this.log.warn(`setReported failed for backend`,{backend:n.name,err:cm(e)})}}on(e){return this.handlers.add(e),()=>this.handlers.delete(e)}emit(e){if(e.type===`session-removed`){let t=this.inputQueues.get(e.sessionId);t&&(t.valid=!1)}for(let e of this.inputQueues.values())(e.backend.isConnected===!1||this.members.get(e.backend.name)!==e.backend)&&(e.valid=!1);[`layout-changed`,`session-added`,`session-removed`,`title-changed`].includes(e.type)&&this.notificationRevision++;for(let t of[...this.handlers])if(this.handlers.has(t))try{t(e)}catch(e){this.log.error(`backend event handler threw`,{err:cm(e)})}}};function jm(e,t){return{...t,id:Em(e,t.id),windowId:Em(e,t.windowId),tabId:Em(e,t.tabId),backend:e}}function Mm(e,t){return`sessionId`in t?{...t,sessionId:Em(e,t.sessionId)}:t}function Nm(e,t){let n;try{n=new URL(e)}catch{return`must be a valid URL, e.g. wss://relay.example.com`}return e.endsWith(`/`)||/[?#]/.test(e)||n.pathname!==`/`||n.username||n.password?`relay url must be scheme://host[:port] with no path, query or credentials`:e.length>256?`relay url is too long for a pairing code (at most 256 characters)`:n.protocol===`wss:`?null:n.protocol===`ws:`?t?null:`ws:// is insecure; pass --insecure or set SHELLBELL_ALLOW_INSECURE_RELAY=1 for LAN dev`:`relay url must use wss:// (ws:// only with --insecure, for LAN dev)`}function Pm(e,t,n,r){let i;if(t===`relay`){let t=Nm(n,r);if(t)return{error:t};i={...e,relayUrl:n}}else if(t===`name`)i={...e,computerName:n};else if(t===`accent`){if(!Ip.includes(n))return{error:`unknown accent ${n} (must be one of ${Ip.join(`, `)})`};i={...e,accent:n}}else if(t===`turn`){if(n!==`on`&&n!==`off`)return{error:`turn must be on or off`};let{turn:t,...r}=e;i=n===`off`?{...r,turn:!1}:r}else if(t===`conversations`){if(n!==`on`&&n!==`off`)return{error:`conversations must be on or off`};let{showAgentConversations:t,...r}=e;i=n===`off`?{...r,showAgentConversations:!1}:r}else if(Lm(t)){if(!/^\d+$/.test(n))return{error:`${t} must be a complete decimal integer`};let r=Number(n);if(!Number.isSafeInteger(r))return{error:`${t} must be a safe decimal integer`};i={...e,[t]:r}}else return{error:`unknown key ${t} (expected ${Rm()})`};let a=vp.safeParse(i);return a.success?{next:a.data}:{error:a.error.issues.map(e=>e.message).join(`; `)}}const Fm=[`notifyMinCommandMs`,`idleQuietMs`,`idleMinActiveMs`],Im=[`relay`,`name`,`accent`,...Fm,`turn`,`conversations`];function Lm(e){return Fm.includes(e)}function Rm(){return`${Im.slice(0,-1).join(`, `)}, or ${Im.at(-1)}`}function zm(e,t){switch(t){case`relay`:return e.relayUrl;case`name`:return e.computerName;case`accent`:return e.accent;case`turn`:return e.turn===!1?`off`:`on`;case`conversations`:return e.showAgentConversations===!1?`off`:`on`;default:return String(e[t])}}function Bm(e){let t=vp.parse(e);return ae(`sha256`).update(JSON.stringify({v:t.v,relayUrl:t.relayUrl,computerName:t.computerName,accent:t.accent,notifyMinCommandMs:t.notifyMinCommandMs,idleQuietMs:t.idleQuietMs,idleMinActiveMs:t.idleMinActiveMs,...t.terminalPlugins?.length?{terminalPlugins:t.terminalPlugins}:{},...t.turn===!1?{turn:!1}:{},...t.showAgentConversations===!1?{showAgentConversations:!1}:{}})).digest(`hex`)}const Vm={claude:{name:`Claude Code`,from:`2.1.286`,through:`2.1.310`},codex:{name:`Codex`,from:`0.164.0`,through:`0.166.0`},gemini:{name:`Gemini CLI`,from:`0.62.0`,through:`0.62.0`}},Hm=/^\d{1,6}(?:\.\d{1,6}){0,3}$/;function Um(e){return typeof e==`string`&&Hm.test(e)?e:null}function Wm(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<Math.max(n.length,r.length);e++){let t=(n[e]??0)-(r[e]??0);if(t)return Math.sign(t)}return 0}function Gm(e,t){if(!Object.hasOwn(Vm,e))return`tested`;let n=Vm[e];return Wm(t,n.through)>0?`newer`:Wm(t,n.from)<0?`older`:`tested`}const Km=new Map;function qm(){return[...Km.values()].map(e=>({...e}))}function Jm(e,t,n){if(Gm(e,t)!==`newer`)return;let r=`${e}@${t}`;if(Km.has(r)||Km.size>=16)return;let i=Vm[e].name;Km.set(r,{agent:e,name:i,version:t}),n(`agent-version-newer-than-tested`,{agent:e,version:t,tested:Vm[e].through})}const Ym=F.object({name:Ql,connected:F.boolean()}),Xm=F.array(Ym).max(32),Zm=F.object({pid:F.number().int().positive().max(2**53-1),agentVersion:F.string().min(1),computerFp:U,stateDir:F.string().min(1).refine(M,`state directory must be absolute`),serviceInstance:F.uuid().nullable()}),Qm=F.object({agent:F.string().min(1).max(32),name:F.string().min(1).max(64),version:F.string().regex(Hm)}),$m={controlVersion:F.literal(1),process:Zm,backends:Xm,terminalReady:F.boolean(),newerAgents:F.array(Qm).max(16).optional()};function eh(e,t){(e.backends.length<Dm.length||Dm.some((t,n)=>e.backends[n]?.name!==t)||new Set(e.backends.map(e=>e.name)).size!==e.backends.length||e.backends.slice(Dm.length).some((e,t,n)=>t>0&&e.name<n[t-1].name))&&t.addIssue({code:`custom`,path:[`backends`],message:`backend status must contain each known backend in protocol order`}),e.terminalReady!==e.backends.some(e=>e.connected)&&t.addIssue({code:`custom`,path:[`terminalReady`],message:`terminal readiness must match backend connectivity`})}const th=F.string().min(1).max(64),nh=F.object({route:F.enum([`relay`,`direct`]).nullable(),ready:F.boolean(),phase:F.string().max(32),lastFailure:F.string().max(32).nullable(),relaySent:F.number().int().nonnegative(),relayReceived:F.number().int().nonnegative(),directSent:F.number().int().nonnegative(),directReceived:F.number().int().nonnegative()}),rh=F.object({...$m,relayOnline:F.boolean(),sessions:F.number().int().nonnegative().max(2**53-1),phones:F.array(F.object({phoneFp:U,name:th,lastSeenAt:F.string().nullable()})).max(10),connected:F.array(F.object({phoneFp:U,name:th,viewed:F.string().nullable(),transport:nh.optional()})).max(10)}).superRefine(eh);function ih(e,t=process.env){if(!e)return null;let n=t.SHELLBELL_SERVICE_INSTANCE;if(n===void 0)return null;if(!F.uuid().safeParse(n).success)throw Error(`SHELLBELL_SERVICE_INSTANCE must be a valid UUID`);return n}function ah(e){try{return t.lstatSync(e)}catch(e){if(e.code===`ENOENT`)return;throw e}}function oh(e,t){return e?.dev===t.dev&&e.ino===t.ino}function sh(e){let t=process.platform===`darwin`?103:process.platform===`linux`?107:null;if(t===null)throw Error(`Unsupported control socket platform: ${process.platform}`);if(Buffer.byteLength(e)>t)throw Error(`Control socket path is too long (maximum ${t} bytes): ${e}`)}async function ch(e){return new Promise((t,n)=>{let r=le(e),i=setTimeout(()=>a(Error(`Control socket probe timed out: ${e}`)),1e3),a=(e,a=!1)=>{clearTimeout(i),r.destroy(),e?n(e):t(a)};r.once(`connect`,()=>a(void 0,!0)),r.once(`error`,e=>{e.code===`ENOENT`||e.code===`ECONNREFUSED`?a():a(e)})})}var lh=class{sockPath;onConnection;log;pidPath;admit;server;clients=new Set;ownedSocket;ownedPid;lifecycle=Promise.resolve();constructor(e,t,n,r,i){this.sockPath=e,this.onConnection=t,this.log=n,this.pidPath=r,this.admit=i}serialize(e){let t=this.lifecycle.then(e);return this.lifecycle=t.catch(()=>{}),t}start(){return this.serialize(async()=>{if(this.server)return;if(this.ownedSocket||this.ownedPid)throw Error(`Control endpoint cleanup pending; stop it before restarting`);sh(this.sockPath),sh(N(j(this.sockPath),`.s12345678`));let e=ap(this.sockPath);try{this.admit?.(),this.checkPid();let e=ah(this.sockPath);if(e){if(!e.isSocket())throw Error(`Control socket path is not a socket: ${this.sockPath}`);if(await ch(this.sockPath))throw Error(`Control endpoint already running: ${this.sockPath}`);if(!oh(ah(this.sockPath),e))throw Error(`Control socket changed during startup; retry`);t.unlinkSync(this.sockPath);for(let n of t.readdirSync(j(this.sockPath))){if(!/^\.s[A-Za-z0-9_-]{8}$/.test(n))continue;let r=N(j(this.sockPath),n);oh(ah(r),e)&&t.unlinkSync(r)}}let n=await this.bind();t.chmodSync(n,384);let r=t.lstatSync(n);if(t.linkSync(n,this.sockPath),this.ownedSocket=r,this.pidPath){this.checkPid();let e=String(process.pid);zp(this.pidPath,e),this.ownedPid={identity:t.lstatSync(this.pidPath),contents:e}}this.admit?.()}catch(e){try{this.removeOwned()}finally{await this.closeListener()}throw e}finally{e()}})}checkPid(){if(!this.pidPath)return;let e=ah(this.pidPath);if(!e)return;if(!e.isFile())throw Error(`PID path must be a regular file: ${this.pidPath}`);let n=tp(t.readFileSync(this.pidPath,`utf8`).trim());if(n===null)throw Error(`Invalid PID file; inspect ${this.pidPath} before retrying`);if(np(n))throw Error(`shellbell is already running (pid ${n})`)}async bind(){for(let e=0;e<8;e++){let e=N(j(this.sockPath),`.s${se(6).toString(`base64url`)}`),t=ue(e=>{this.clients.add(e),e.once(`close`,()=>this.clients.delete(e)),e.on(`error`,()=>{}),this.onConnection(e)});this.server=t;try{return await new Promise((n,r)=>{t.once(`error`,r);let i=process.umask(127);try{t.listen(e,()=>{t.removeListener(`error`,r),n()})}finally{process.umask(i)}}),e}catch(e){if(await this.closeListener(),e.code!==`EADDRINUSE`)throw e}}throw Error(`Control endpoint private socket names are in use after eight attempts`)}removeOwned(){if(this.ownedSocket&&=(oh(ah(this.sockPath),this.ownedSocket)&&t.unlinkSync(this.sockPath),void 0),this.pidPath&&this.ownedPid){let e=ah(this.pidPath);e?.isFile()&&oh(e,this.ownedPid.identity)&&t.readFileSync(this.pidPath,`utf8`)===this.ownedPid.contents&&t.unlinkSync(this.pidPath),this.ownedPid=void 0}}async closeListener(){for(let e of this.clients)e.destroy();this.clients.clear();let e=this.server;this.server=void 0,e&&await new Promise((t,n)=>e.close(e=>{e&&e.code!==`ERR_SERVER_NOT_RUNNING`?n(e):t()}))}stop(){return this.serialize(async()=>{let e;try{(this.ownedSocket||this.ownedPid)&&(e=ap(this.sockPath),this.removeOwned())}catch(e){throw this.log.warn(`Control endpoint cleanup failed; shared paths retained for retry`,{error:cm(e)}),e}finally{try{await this.closeListener()}finally{e?.()}}})}};const uh={lineBytes:65536,queuedBytes:262144,connections:16,initialRequestMs:5e3,requestMs:5e3,challengeMs:6e4};function dh(e){let t;try{t=JSON.stringify(e)}catch{return null}if(t===void 0)return null;let n=new TextEncoder().encode(`${t}\n`);return n.byteLength-1<=uh.lineBytes?n:null}function fh(e,t){let n=e.writableLength;if(e.destroyed||!Number.isFinite(n)||n<0||n+t.byteLength>uh.queuedBytes)return e.destroy(),!1;try{return e.write(t),!0}catch{return e.destroy(),!1}}var ph=class{onLine;onError;maxBytes;chunks=[];bytes=0;terminal=!1;constructor(e){this.onLine=e.onLine,this.onError=e.onError;let t=e.maxBytes??uh.lineBytes;this.maxBytes=Number.isFinite(t)?Math.max(0,Math.min(t,uh.lineBytes)):uh.lineBytes}push(e){if(this.terminal||e.byteLength===0)return;let t=0;for(;t<e.byteLength&&!this.terminal;){let n=e.indexOf(10,t),r=n===-1?e.byteLength:n,i=r-t;if(this.bytes+i>this.maxBytes){this.fail(`line-too-large`);return}if(i>0&&(this.chunks.push(Uint8Array.from(e.subarray(t,r))),this.bytes+=i),n===-1)return;let a=this.decodeLine();if(a===null)return;this.reset(),this.onLine(a),t=n+1}}finish(){this.terminal||(this.bytes>0?this.fail(`incomplete-line`):(this.terminal=!0,this.reset()))}decodeLine(){let e=new Uint8Array(this.bytes),t=0;for(let n of this.chunks)e.set(n,t),t+=n.byteLength;try{return new TextDecoder(`utf-8`,{fatal:!0,ignoreBOM:!0}).decode(e)}catch{return this.fail(`invalid-utf8`),null}}fail(e){this.terminal||(this.terminal=!0,this.reset(),this.onError(e))}reset(){this.chunks=[],this.bytes=0}};const mh=F.number().int().positive().max(2**53-1),hh=F.string().regex(/^[A-Za-z0-9_-]{22}$/),gh=F.string().min(1).max(64),_h=F.object({pid:mh,agentVersion:F.string().min(1),computerFp:U,stateDir:F.string().min(1).refine(M,`state directory must be absolute`),serviceInstance:F.uuid().nullable()}).strict(),vh=F.object({name:Ql,connected:F.boolean()}).strict(),yh=F.object({phoneFp:U,name:gh,lastSeenAt:F.string().nullable()}).strict(),bh=F.object({phoneFp:U,name:gh,viewed:F.string().nullable(),transport:nh.strict().optional()}).strict(),xh=F.object({controlVersion:F.literal(1),process:_h,backends:F.array(vh),terminalReady:F.boolean(),relayOnline:F.boolean(),sessions:F.number().int().nonnegative().max(2**53-1),phones:F.array(yh).max(10),connected:F.array(bh).max(10)}).strict().superRefine((e,t)=>{rh.safeParse(e).success||t.addIssue({code:`custom`,message:`status must satisfy LocalStatus semantics`})}),Sh=F.object({}).strict(),Ch=F.object({version:F.literal(2),runtime:_h,capabilities:F.tuple([F.literal(`status`),F.literal(`devices`),F.literal(`pairing`),F.literal(`revoke`)])}).strict(),wh=F.array(yh).max(10),Th=F.object({removed:F.boolean()}).strict(),Eh=F.object({flowId:hh,qrText:F.string().min(1).refine(e=>new TextEncoder().encode(e).byteLength<=uh.lineBytes),expiresAt:mh}).strict(),Dh={hello:Ch,status:xh,"status.config":F.object({revision:F.string().regex(/^[0-9a-f]{64}$/)}).strict(),"settings.conversations.apply":F.object({revision:F.string().regex(/^[0-9a-f]{64}$/)}).strict(),devices:wh,"devices.revoke":Th,"pairing.open":Eh,"pairing.close":Sh,"pairing.confirm":Sh,terminals:F.object({terminals:gu}).strict(),"terminals.connect":F.object({started:F.boolean(),terminals:gu}).strict()},Oh={v:F.literal(2),id:mh},kh={...Oh,expect:_h},Ah=F.discriminatedUnion(`cmd`,[F.object({...kh,cmd:F.literal(`settings.conversations.apply`),args:F.object({revision:F.string().regex(/^[0-9a-f]{64}$/)}).strict()}).strict(),F.object({...Oh,cmd:F.literal(`hello`)}).strict(),F.object({...Oh,cmd:F.literal(`status`)}).strict(),F.object({...Oh,cmd:F.literal(`status.config`)}).strict(),F.object({...Oh,cmd:F.literal(`devices`)}).strict(),F.object({...Oh,cmd:F.literal(`terminals`)}).strict(),F.object({...kh,cmd:F.literal(`terminals.connect`),args:F.object({name:Ql}).strict()}).strict(),F.object({...kh,cmd:F.literal(`devices.revoke`),args:F.object({phoneFp:U}).strict()}).strict(),F.object({...kh,cmd:F.literal(`pairing.open`)}).strict(),F.object({...kh,cmd:F.literal(`pairing.close`),args:F.object({flowId:hh}).strict()}).strict(),F.object({...kh,cmd:F.literal(`pairing.confirm`),args:F.object({flowId:hh,challengeId:hh,phoneFp:U,accept:F.boolean()}).strict()}).strict()]),jh=F.enum([`bad-request`,`unsupported-version`,`handshake-required`,`runtime-mismatch`,`configuration-mismatch`,`pairing-busy`,`stale-flow`,`stale-challenge`,`response-too-large`,`operation-failed`]),Mh=F.object({v:F.literal(2),id:mh,ok:F.literal(!0),data:F.unknown()}).strict().refine(e=>Object.hasOwn(e,`data`)),Nh=F.object({v:F.literal(2),id:mh,ok:F.literal(!1),error:F.object({code:jh}).strict()}).strict(),Ph=F.union([Mh,Nh]),Fh=F.object({v:F.literal(2),event:F.literal(`pairing.request`),flowId:hh,challengeId:hh,phoneFp:U,name:gh}).strict(),Ih=F.object({v:F.literal(2),event:F.literal(`pairing.closed`),flowId:hh}).strict(),Lh=F.discriminatedUnion(`event`,[Fh,Ih]),Rh=[`status`,`devices`,`pairing`,`revoke`];function zh(e,t){return e.pid===t.pid&&e.agentVersion===t.agentVersion&&e.computerFp===t.computerFp&&e.stateDir===t.stateDir&&e.serviceInstance===t.serviceInstance}function Bh(e){if(!e||typeof e!=`object`)return;let t=e.id;return typeof t==`number`&&Number.isSafeInteger(t)&&t>0?t:void 0}var Vh=class{agent;log;peers=new Set;owner;stopped=!1;newId;constructor(e,t,n){this.agent=e,this.log=t,this.newId=n?.newId??(()=>se(16).toString(`base64url`))}get hasPairOwner(){return this.owner!==void 0}accept(e){let t=new Hh(this,e,this.agent);return this.stopped?t.close():this.peers.add(t),t}confirm(e,t){let n=this.owner;if(!n||n.resolve||this.stopped)return Promise.resolve(!1);let r=this.newId();return new Promise(i=>{if(this.owner!==n)return i(!1);n.resolve=i,n.challengeId=r,n.phoneFp=e,n.name=t,n.opening||this.emitRequest(n,t)})}activate(e,t){let n=this.owner;n&&n.peer===e&&n.flowId===t&&(n.opening=!1,n.resolve&&n.phoneFp&&n.challengeId&&this.emitRequest(n,n.name??``))}emitRequest(e,t){if(!e.resolve||!e.challengeId||!e.phoneFp)return;let n=e.resolve,r=Math.max(0,(e.expiresAt??Date.now())-Date.now());e.timer=setTimeout(()=>{this.owner===e&&e.resolve===n&&(e.resolve=void 0,e.challengeId=void 0,e.phoneFp=void 0,n(!1))},Math.min(uh.challengeMs,r)),e.timer.unref(),e.peer.event({v:2,event:`pairing.request`,flowId:e.flowId,challengeId:e.challengeId,phoneFp:e.phoneFp,name:t})||this.clearOwner(e,!1,!0)}notifyClosed(){let e=this.owner;e&&(this.clearOwner(e,!1,!1),e.peer.event({v:2,event:`pairing.closed`,flowId:e.flowId}))}stop(){this.stopped=!0;let e=this.owner;e&&this.clearOwner(e,!0,!1);for(let e of this.peers)e.close();this.peers.clear()}removed(e){this.peers.delete(e);let t=this.owner;t?.peer===e&&this.clearOwner(t,!0,!1)}open(e){if(this.owner||this.agent.pairingOpen)return`pairing-busy`;try{let t=this.newId(),n={peer:e,flowId:t,opening:!0};this.owner=n;let r=this.agent.openPairing();return this.owner!==n||!this.agent.pairingOpen?(this.clearOwner(n,!0,!1),`operation-failed`):(n.expiresAt=r.expiresAt,{flowId:t,...r})}catch{let t=this.owner;return t?.peer===e&&this.clearOwner(t,!0,!1),`operation-failed`}}close(e,t){let n=this.owner;if(!n||n.peer!==e||n.flowId!==t)return`stale-flow`;this.clearOwner(n,!0,!1)}answer(e,t){let n=this.owner;if(!n||n.peer!==e||n.flowId!==t.args.flowId)return`stale-flow`;if(n.expiresAt===void 0||Date.now()>=n.expiresAt)return this.clearOwner(n,!0,!0),`stale-flow`;if(!n.resolve||n.challengeId!==t.args.challengeId||n.phoneFp!==t.args.phoneFp)return`stale-challenge`;let r=n.resolve;n.timer&&clearTimeout(n.timer),n.timer=void 0,n.resolve=void 0,n.challengeId=void 0,n.phoneFp=void 0,n.name=void 0,r(t.args.accept)}clearOwner(e,t,n){if(this.owner!==e)return;this.owner=void 0;let r=e.resolve;if(e.timer&&clearTimeout(e.timer),e.timer=void 0,e.resolve=void 0,e.challengeId=void 0,e.phoneFp=void 0,e.name=void 0,r?.(!1),t)try{this.agent.closePairing()}catch{this.log.warn(`native pairing close failed`)}n&&e.peer.event({v:2,event:`pairing.closed`,flowId:e.flowId})}},Hh=class{hub;socket;agent;helloRuntime;lastId=0;closed=!1;constructor(e,t,n){this.hub=e,this.socket=t,this.agent=n}get handshaken(){return this.helloRuntime!==void 0}close(){this.closed||(this.closed=!0,this.hub.removed(this),this.socket.destroy())}handle(e){if(this.closed||this.socket.destroyed)return;let t=Bh(e);if(this.handshaken&&t!==void 0){if(t<=this.lastId){this.close();return}this.lastId=t}if(e&&typeof e==`object`&&e.v!==2){t!==void 0&&this.failure(t,`unsupported-version`),this.close();return}let n=Ah.safeParse(e);if(!n.success){t===void 0?this.close():this.failure(t,`bad-request`);return}let r=n.data;if(!this.handshaken){if(r.id!==1||r.cmd!==`hello`){this.close();return}this.lastId=1,this.helloRuntime={...this.runtime()},this.success(r,{version:2,runtime:this.helloRuntime,capabilities:Rh});return}if(r.cmd===`hello`){this.close();return}let i=this.helloRuntime,a=this.runtime();if(`expect`in r&&(!i||!zh(r.expect,i)||!zh(r.expect,a))){this.failure(r.id,`runtime-mismatch`);return}switch(r.cmd){case`status`:this.success(r,this.status());return;case`status.config`:this.success(r,{revision:this.agent.configurationRevision});return;case`settings.conversations.apply`:try{let e=this.agent.applyConversationSetting(r.args.revision);e===null?this.failure(r.id,`configuration-mismatch`):this.success(r,{revision:e})}catch{this.failure(r.id,`operation-failed`)}return;case`devices`:this.success(r,this.devices());return;case`devices.revoke`:try{this.success(r,{removed:this.agent.unpairExact(r.args.phoneFp)})}catch{this.failure(r.id,`operation-failed`)}return;case`terminals`:this.success(r,{terminals:this.agent.terminalSetup()});return;case`terminals.connect`:{let e=this.agent.connectTerminal(r.args.name);this.success(r,{started:e,terminals:this.agent.terminalSetup()});return}case`pairing.open`:{let e=this.hub.open(this);typeof e==`string`?this.failure(r.id,e):this.success(r,e)?this.hub.activate(this,e.flowId):this.hub.close(this,e.flowId);return}case`pairing.close`:{let e=this.hub.close(this,r.args.flowId);e?this.failure(r.id,e):this.success(r,{})&&this.event({v:2,event:`pairing.closed`,flowId:r.args.flowId});return}case`pairing.confirm`:{let e=this.hub.answer(this,r);e?this.failure(r.id,e):this.success(r,{});return}}}event(e){return Lh.safeParse(e).success?this.write(e):!1}runtime(){return this.agent.localStatus.process}status(){let e=this.agent;return{...e.localStatus,relayOnline:e.relayOnline,sessions:e.sessionList.length,phones:this.devices(),connected:e.connectedPhones}}devices(){return this.agent.pairingList.map(e=>({phoneFp:e.phoneFp,name:e.name,lastSeenAt:e.lastSeenAt}))}success(e,t){if(!Dh[e.cmd].safeParse(t).success)return this.failure(e.id,`operation-failed`),!1;let n={v:2,id:e.id,ok:!0,data:t};if(!Ph.safeParse(n).success)return this.failure(e.id,`operation-failed`),!1;let r=dh(n);return r?this.writeFrame(r):(this.failure(e.id,`response-too-large`),!1)}failure(e,t){let n={v:2,id:e,ok:!1,error:{code:t}};return Ph.safeParse(n).success?this.write(n):!1}write(e){let t=dh(e);return t?this.writeFrame(t):!1}writeFrame(e){return fh(this.socket,e)?!0:(this.close(),!1)}};const Uh={unavailable:`Local control unavailable`,"upgrade-required":`Local control upgrade required`,"protocol-error":`Local control protocol error`,timeout:`Local control timed out`,"delivery-unknown":`Local control mutation outcome unknown`,busy:`Local control request already pending`,closed:`Local control closed`,"server-error":`Local control server rejected request`},Wh=new Set([`hello`,`status`,`status.config`,`devices`,`terminals`]);var Q=class extends Error{code;serverCode;constructor(e,t){super(Uh[e]),this.code=e,this.serverCode=t,this.name=`ControlV2ClientError`}};function Gh(e,t={}){return new Promise((n,r)=>{let i;try{i=(t.connector??le)(e)}catch{r(new Q(`unavailable`));return}let a=!1,o=!1,s=!1,c=0,l,u,d,f=setTimeout(()=>p(new Q(`timeout`)),uh.requestMs);function p(e){if(a)return;a=!0,clearTimeout(f);let n=l;l=void 0,d=void 0,n&&(clearTimeout(n.timer),n.reject(n.mutation&&n.attempted?new Q(`delivery-unknown`):e)),o||r(e),i.destroy(),t.onDisconnect?.(e)}function m(e,t){if(a)return Promise.reject(new Q(`closed`));if(l)return Promise.reject(new Q(`busy`));if(c===2**53-1)return p(new Q(`protocol-error`)),Promise.reject(new Q(`protocol-error`));let n=!Wh.has(e),r=Ah.safeParse({v:2,id:c+1,cmd:e,...n?{expect:u}:{},...t===void 0?{}:{args:t}});if(!r.success)return Promise.reject(new Q(`protocol-error`));let o=dh(r.data);if(o===null)return Promise.reject(new Q(`protocol-error`));let s=i.writableLength;return i.destroyed||!Number.isFinite(s)||s<0||s+o.byteLength>uh.queuedBytes?(p(new Q(`unavailable`)),Promise.reject(new Q(`unavailable`))):(c++,new Promise((t,r)=>{let a={id:c,command:e,mutation:n,attempted:!1,resolve:e=>t(e),reject:r,timer:setTimeout(()=>p(new Q(`timeout`)),uh.requestMs)};l=a,a.attempted=!0,fh(i,o)||p(new Q(`unavailable`))}))}let h=new ph({onError:()=>p(new Q(`protocol-error`)),onLine:e=>{if(a)return;let n;try{n=JSON.parse(e)}catch{p(new Q(`protocol-error`));return}if(typeof n==`object`&&n&&`event`in n){let e=Lh.safeParse(n);if(!e.success){p(new Q(`protocol-error`));return}let r=e.data;if(r.event===`pairing.closed`&&r.flowId!==d)return;if(r.flowId!==d){p(new Q(`protocol-error`));return}r.event===`pairing.closed`?(d=void 0,t.onPairingClosed?.(r)):t.onPairingRequest?.(r);return}let r=l;if(r?.command===`hello`&&typeof n==`object`&&n&&!(`v`in n)&&`ok`in n&&typeof n.ok==`boolean`){p(new Q(`upgrade-required`));return}let i=Ph.safeParse(n);if(!i.success||!r||i.data.id!==r.id){p(new Q(`protocol-error`));return}if(!i.data.ok){clearTimeout(r.timer),l=void 0;let e=new Q(`server-error`,i.data.error.code);r.reject(e),r.command===`hello`&&p(e);return}let o=Dh[r.command].safeParse(i.data.data);if(!o.success){p(new Q(`protocol-error`));return}r.command===`pairing.open`&&(d=o.data.flowId),clearTimeout(r.timer),l=void 0,r.resolve(o.data)}});i.on(`data`,e=>h.push(e)),i.on(`error`,()=>p(new Q(`unavailable`)));let g=()=>{h.finish(),p(new Q(`unavailable`))};i.once(`end`,g),i.once(`close`,g);let _=()=>{a||s||(s=!0,clearTimeout(f),m(`hello`).then(e=>{a||(u={...e.runtime},o=!0,n({runtime:{...e.runtime},status:()=>m(`status`),applyConversationSetting:async e=>{try{return(await m(`settings.conversations.apply`,{revision:e})).revision}catch(e){if(e instanceof Q&&e.code===`server-error`&&e.serverCode===`bad-request`)return null;throw e}},configurationRevision:async()=>{try{return(await m(`status.config`)).revision}catch(e){if(e instanceof Q&&e.code===`server-error`&&e.serverCode===`bad-request`)return null;throw e}},devices:()=>m(`devices`),terminals:async()=>{try{return(await m(`terminals`)).terminals}catch(e){if(Kh(e))return null;throw e}},connectTerminal:async e=>{try{return await m(`terminals.connect`,{name:e})}catch(e){if(Kh(e))return null;throw e}},revoke:e=>m(`devices.revoke`,{phoneFp:e}),openPairing:()=>m(`pairing.open`),closePairing:async e=>{await m(`pairing.close`,{flowId:e})},confirm:async(e,t,n,r)=>{await m(`pairing.confirm`,{flowId:e,challengeId:t,phoneFp:n,accept:r})},close:()=>p(new Q(`closed`))}))},e=>p(e)))};i.once(`connect`,_),i.connecting||_()})}function Kh(e){return e instanceof Q&&e.code===`server-error`&&e.serverCode===`bad-request`}var qh=class{agent;log;admission;pairingMode;endpoint;pending=new Map;pairClients=new Set;controlSockets=new Set;v2;pairingConfirm=(e,t)=>new Promise(n=>{if(this.pending.has(e)){this.log.warn(`pairing confirm requested twice for the same phone; declining the newer one`,{phone:e.slice(0,8)}),n(!1);return}let r=setTimeout(()=>{this.pending.delete(e),n(!1)},6e4);this.pending.set(e,t=>{clearTimeout(r),this.pending.delete(e),n(t)});for(let n of this.pairClients)this.writeLegacy(n,{event:`request`,phoneFp:e,name:t})||this.pairClients.delete(n)});constructor(e,t,n,r,i,a,o=`terminal`){this.agent=t,this.log=n,this.admission=a,this.pairingMode=o,this.endpoint=new lh(e,e=>this.handle(e),n,r,i),this.v2=new Vh(t,n)}get hasPairClients(){return this.pairClients.size>0}get hasNativePairOwner(){return this.v2.hasPairOwner}nativePairingConfirm=(e,t)=>this.v2.confirm(e,t);notifyClosed(e=`closed`){for(let e of this.pending.values())e(!1);this.pending.clear();for(let t of this.pairClients)this.writeLegacy(t,{event:`closed`,reason:e})||this.pairClients.delete(t);this.pairClients.clear(),this.v2.notifyClosed()}async start(){this.admission?await this.admission(()=>this.endpoint.start()):await this.endpoint.start()}async stop(){for(let e of this.pending.values())e(!1);for(let e of this.controlSockets)e.destroy();this.controlSockets.clear();for(let e of this.pairClients)e.destroy();this.pairClients.clear(),this.v2.stop(),await this.endpoint.stop()}handle(e){if(this.controlSockets.size>=uh.connections){e.destroy();return}this.controlSockets.add(e);let t=!0,n,r,i=setTimeout(()=>e.destroy(),uh.initialRequestMs),a=new ph({onLine:a=>{if(e.destroyed)return;let o;try{o=JSON.parse(a)}catch{if(n===`v2`){e.destroy();return}this.writeLegacy(e,{ok:!1,error:`bad json`});return}if(n===`v2`){r?.handle(o),t&&r?.handshaken&&(t=!1,clearTimeout(i));return}if(n===void 0&&o&&typeof o==`object`&&Object.hasOwn(o,`v`)){n=`v2`,r=this.v2.accept(e),r.handle(o),r.handshaken&&(t=!1,clearTimeout(i));return}if(n===`legacy`&&o&&typeof o==`object`&&Object.hasOwn(o,`v`)){e.destroy();return}n=`legacy`;let s=o;if(!s||typeof s!=`object`||typeof s.cmd!=`string`){this.writeLegacy(e,{ok:!1,error:`bad request`});return}t&&(t=!1,clearTimeout(i));try{let t=this.dispatch(s,e);this.writeLegacy(e,{ok:!0,data:t})}catch(t){this.writeLegacy(e,{ok:!1,error:t.message})}},onError:()=>e.destroy()});e.on(`data`,e=>a.push(new Uint8Array(e))),e.once(`end`,()=>a.finish()),e.once(`close`,()=>{clearTimeout(i),this.controlSockets.delete(e),this.pairClients.delete(e),r?.close()}),e.on(`error`,()=>this.log.debug(`control socket error`))}writeLegacy(e,t){let n=dh(t);if(n&&fh(e,n))return!0;let r=dh({ok:!1,error:`response too large`});return r!==null&&fh(e,r)}dispatch(e,t){let n=this.agent;if(this.pairingMode===`native`&&[`pair-open`,`pair-close`,`confirm`].includes(e.cmd))throw Error(`pairing is managed by the Shellbell app`);if(this.v2.hasPairOwner&&[`pair-open`,`pair-close`,`confirm`].includes(e.cmd))throw Error(`native pairing active`);switch(e.cmd){case`status`:return{...n.localStatus,relayOnline:n.relayOnline,sessions:n.sessionList.length,phones:n.pairingList.map(e=>({phoneFp:e.phoneFp,name:e.name,lastSeenAt:e.lastSeenAt})),connected:n.connectedPhones};case`devices`:return n.pairingList.map(e=>({phoneFp:e.phoneFp,name:e.name,lastSeenAt:e.lastSeenAt}));case`unpair`:return{removed:n.unpair(String(e.args?.target??``))};case`pair-open`:{let e=n.openPairing();return this.pairClients.add(t),e}case`pair-close`:return n.closePairing(),{};case`confirm`:{let t=String(e.args?.phoneFp??``),n=this.pending.get(t);if(!n)throw Error(`no pending request`);return n(!!e.args?.accept),{}}default:throw Error(`unknown command: ${e.cmd}`)}}};function Jh(e,t,n,r){return new Promise((i,a)=>{let o=dh({cmd:t,args:n});if(!o){a(Error(`control socket request too large`));return}let s=!1,c=le(e),l=r?.timeoutMs??5e3,u=e=>{s||(s=!0,clearTimeout(d),c.destroy(),e())},d=setTimeout(()=>u(()=>a(Error(`control socket timed out`))),l),f=new ph({maxBytes:r?.maxResponseBytes,onError:e=>u(()=>a(Error(e===`line-too-large`?`control socket response too large`:`control socket sent a malformed response`))),onLine:e=>{f.finish(),u(()=>{let t;try{if(t=JSON.parse(e),typeof t!=`object`||!t||typeof t.ok!=`boolean`)throw Error()}catch{a(Error(`control socket sent a malformed response`));return}t.ok?i(t.data):a(Error(t.error??`control error`))})}});c.on(`error`,e=>u(()=>a(e))),c.once(`connect`,()=>{fh(c,o)||u(()=>a(Error(`control socket write failed`)))}),c.once(`close`,()=>u(()=>a(Error(`control socket closed without a response`)))),c.once(`end`,()=>u(()=>a(Error(`control socket closed without a response`)))),c.on(`data`,e=>{s||f.push(new Uint8Array(e))}),c.once(`end`,()=>f.finish())})}function Yh(e,t){let n=le(e),r=!1,i,a=()=>{r||(r=!0,i?.finish(),n.end())};n.on(`error`,t.onError);let o=dh({cmd:`pair-open`});return n.once(`connect`,()=>{(o===null||!fh(n,o))&&t.onError(Error(`control socket write failed`))}),i=new ph({onError:()=>{n.destroy(),t.onError(Error(`control socket sent a malformed message`))},onLine:e=>{if(r)return;let i;try{i=JSON.parse(e)}catch{t.onError(Error(`control socket sent a malformed message`));return}i.event===`request`&&i.phoneFp?t.onRequest(i.phoneFp,i.name??``).then(e=>{if(r)return;let t=dh({cmd:`confirm`,args:{phoneFp:i.phoneFp,accept:e}});if(t===null||!fh(n,t))throw Error(`control socket write failed`)}).catch(e=>t.onError(e)):i.event===`closed`?t.onClose(i.reason===`replaced`||i.reason===`paired`?i.reason:`closed`):i.ok&&i.data?.qrText?t.onOpen(i.data.qrText,i.data.expiresAt):i.ok===!1&&t.onError(Error(i.error??`control error`))}}),n.on(`data`,e=>i.push(new Uint8Array(e))),n.once(`end`,()=>{r=!0,i?.finish()}),n.once(`close`,()=>{r=!0,i?.finish()}),{close:a}}function Xh(e){if(e.linuxHost)return Np(e);let t;try{t=g(e.identity,`utf8`)}catch(t){if(t.code===`ENOENT`)return null;throw Error(`shellbell: cannot read identity at ${e.identity}`)}try{let e=rc(JSON.parse(t));return{identity:e,fp:ic(e.ed25519.pub)}}catch{throw Error(`shellbell: invalid identity at ${e.identity}`)}}function Zh(e){if(e.linuxHost)return Np(e);Rp(e);let t;return s(e.identity)?t=Qh(e):(t=$s(),Vp(e.identity,`${JSON.stringify(nc(t),null,2)}\n`)||(t=Qh(e))),{identity:t,fp:ic(t.ed25519.pub)}}function Qh(e){try{return rc(Wp(e.identity))}catch(t){throw Error(`shellbell: invalid identity at ${e.identity}: ${t.message}`)}}const $h=[`dev.bilalahmad.shellbell`,`dev.bilalahmad.shellbell.host.agent`,`dev.bilalahmad.shellbell.host.manual`];async function eg(e,t,n){if(!Number.isSafeInteger(t)||t<0)throw Error(`Invalid service UID`);let r=()=>Error(`Legacy Shellbell installation requires migration before starting the new service; preserve identity and remove old registrations explicitly.`);if(n)for(let e of $h){try{p(N(n,`Library`,`LaunchAgents`,`${e}.plist`))}catch(e){if(e.code===`ENOENT`)continue;throw e}throw r()}for(let n of[...$h.map(e=>`gui/${t}/${e}`),`system/dev.bilalahmad.shellbell.power`]){let t=await e(`/bin/launchctl`,[`print`,n],{timeoutMs:5e3,maxOutputBytes:65536,captureOutput:!1});if(t.exitCode===0)throw r();if(t.exitCode!==113)throw Error(`Could not verify legacy Shellbell registration absence`)}}const tg=(t,n,r)=>new Promise((i,a)=>{let o=e(t,n,{shell:!1,stdio:[`pipe`,`pipe`,`pipe`]}),s=0,c=0,l=[],u=!1,d=e=>{u||(u=!0,clearTimeout(f),o.kill(),a(e))},f=setTimeout(()=>d(Error(`${t} timed out`)),r.timeoutMs);o.stdout.on(`data`,e=>{if(s+=e.length,s>r.maxOutputBytes)return d(Error(`${t} output limit exceeded`));r.captureOutput&&l.push(e)}),o.stderr.on(`data`,e=>{c+=e.length,c>r.maxOutputBytes&&d(Error(`${t} output limit exceeded`))}),o.on(`error`,d),o.on(`close`,(e,n)=>{if(!u){if(u=!0,clearTimeout(f),n||e===null)return a(Error(`${t} terminated by signal`));i({exitCode:e,stdout:r.captureOutput?Buffer.concat(l):Buffer.alloc(0)})}}),o.stdin.on(`error`,d),o.stdin.end(r.input)}),ng=[`/opt/homebrew/bin`,`/usr/local/bin`,`/usr/bin`,`/bin`],rg=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function ig(e){for(let t of e){let e=t.codePointAt(0);if(!(e===9||e===10||e===13||e>=32&&e<=55295||e>=57344&&e<=65533||e>=65536&&e<=1114111))throw Error(`invalid XML character in service definition`)}}function ag(e,t){if(!e||!M(e))throw Error(`${t} must be an absolute path`);return ig(e),e}function og(e){if(ag(e.stateDir,`stateDir`),ag(e.nodePath,`nodePath`),!rg.test(e.serviceInstance))throw Error(`serviceInstance must be a UUID`);let t=[j(e.nodePath),...e.env.PATH?.split(`:`)??[],...ng].filter(e=>e.length>0&&M(e)),n={SHELLBELL_DIR:e.stateDir,SHELLBELL_SERVICE_INSTANCE:e.serviceInstance,PATH:[...new Set(t)].join(`:`)};for(let t of[`HERDR_SOCKET_PATH`,`XDG_CONFIG_HOME`]){let r=e.env[t];r&&(n[t]=ag(r,t))}for(let e of Object.values(n))ig(e);return n}const sg=`sh.bilal.shellbell`;N(D(),`Library`,`LaunchAgents`,`${sg}.plist`);const cg=1048576,lg=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,ug=new Set([`SHELLBELL_DIR`,`SHELLBELL_SERVICE_INSTANCE`,`PATH`,`HERDR_SOCKET_PATH`,`XDG_CONFIG_HOME`]),dg=new Set([`Label`,`ProgramArguments`,`EnvironmentVariables`,`RunAtLoad`,`KeepAlive`,`StandardOutPath`,`StandardErrorPath`]);function fg(e){return ig(e),e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&apos;`)}function pg(e){let t=fg,n=e.environment??{PATH:`/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin`},r=Object.entries(n).map(([e,n])=>`<key>${t(e)}</key><string>${t(n)}</string>`).join(``);return`<?xml version="1.0" encoding="UTF-8"?>
16
+ `)}\r\n`}var sf=class{options;offerId;generation;attemptId;peer=null;phoneDtls;computerDtls=null;localSdp=null;remoteSdp=!1;opened=!1;verifying=!1;sentDescription=!1;sentCandidates=0;receivedCandidates=0;pendingData=[];pendingLocal=[];pendingRemote=[];handshake=null;secureSession=null;closed=!1;timer;constructor(e){this.options=e,this.offerId=e.offer?.offerId.slice()??ba(16),this.attemptId=e.offer?ba(16):null,this.generation=e.generation.slice(),this.phoneDtls=e.offer?.phoneDtls.slice()??null,this.timer=setTimeout(()=>this.fail(`timeout`),15e3)}get session(){return this.secureSession}get phase(){return this.secureSession?`cutover`:this.handshake?`noise`:this.verifying?`certificate`:this.opened?`open`:this.remoteSdp?`connecting`:this.localSdp?`offer`:`native`}get active(){return!this.closed&&this.options.current()}cancelDeadline(){clearTimeout(this.timer)}close(){this.closed||(this.closed=!0,this.cancelDeadline(),this.pendingData=[],this.pendingLocal=[],this.pendingRemote=[],this.handshake?.close(),this.secureSession?.close(),this.peer?.close())}routeStats(){return this.peer?.routeStats?.()??Promise.resolve(null)}send(e){let t=this.active&&(this.peer?.send(e)??!1);return t&&this.options.sent(e.length),t}fail(e=`closed`){this.active&&this.options.failed(e)}async start(){let e={description:(e,t)=>{this.active&&this.description(e,t)},candidate:(e,t,n)=>{if(this.active)try{this.localCandidate({candidate:e,mid:t,mlineIndex:n})}catch{this.fail(`local-candidate`)}},open:()=>{this.active&&(this.opened=!0,this.openDirect().catch(()=>this.fail(`certificate`)))},message:e=>{this.active&&(this.options.received(e.length),this.directMessage(e))},closed:()=>this.fail(`native-closed`)},t;try{t=await this.options.native(e)}catch{this.fail(`native-create`);return}if(!this.active){t.close();return}this.peer=t;try{if(this.options.offer){if(await t.answer(this.options.offer.sdp),!this.active)return;this.remoteSdp=!0}else await t.offer();if(!this.active)return;await this.flushRemote(),await this.openDirect()}catch{this.fail(`native-description`)}}description(e,t){try{let n=af(e);if(this.localSdp=of(e),this.options.role===`phone`&&t===`offer`)this.phoneDtls=n;else if(this.options.role===`computer`&&t===`answer`)this.computerDtls=n;else throw Error(`description role mismatch`);let r=this.signalContext(),i=t===`offer`?{type:`direct.offer`,...r,phoneDtls:n,sdp:this.localSdp}:{type:`direct.answer`,...r,attemptId:this.attemptId,computerDtls:n,sdp:this.localSdp};if(!this.options.sendSignal(i))throw Error(`signaling queue refused`);this.sentDescription=!0;for(let e of this.pendingLocal.splice(0))this.localCandidate(e);this.openDirect().catch(()=>this.fail(`certificate`))}catch{this.fail(`local-description`)}}admits(e){return this.sentCandidates+this.pendingLocal.length<(rf(e)?Rd.candidatesPerSide:Rd.candidatesPerSide-6)}localCandidate(e){if(this.active&&!this.options.committed()&&this.admits(e)){if(!this.sentDescription){this.pendingLocal.push(e);return}this.options.sendSignal({type:`direct.candidate`,...this.signalContext(),index:this.sentCandidates++,...e})||this.fail()}}async signal(e){if(this.active&&this.peer){if(e.type===`direct.answer`){if(this.remoteSdp||(this.computerDtls=e.computerDtls.slice(),this.attemptId=e.attemptId.slice(),await this.peer.acceptAnswer(e.sdp),!this.active))return;this.remoteSdp=!0,await this.flushRemote(),await this.openDirect()}else if(e.type===`direct.candidate`){if(e.index!==this.receivedCandidates++)throw Error(`candidate order`);this.remoteSdp?await this.peer.candidate(e.candidate,e.mid,e.mlineIndex):this.pendingRemote.push(e)}else e.type===`direct.abort`&&this.fail()}}async flushRemote(){if(this.remoteSdp&&this.peer)for(let e of this.pendingRemote.splice(0)){if(!this.active)return;await this.peer.candidate(e.candidate,e.mid,e.mlineIndex)}}signalContext(){return{sessionId:this.options.relay.sessionId,offerId:this.offerId,generation:this.generation}}async openDirect(){if(!this.active||!this.opened||!this.peer||!this.phoneDtls||!this.computerDtls||!this.attemptId||this.verifying||this.handshake||this.secureSession)return;this.verifying=!0;let e=await this.peer.remoteCertificate(this.options.role===`phone`?this.computerDtls:this.phoneDtls);if(this.active){if(this.handshake=new tf({route:`direct`,computerFp:this.options.computerFp,phoneFp:this.options.phoneFp,sessionId:this.options.relay.sessionId,generation:this.generation,attemptId:this.attemptId,phoneDtls:this.phoneDtls,computerDtls:this.computerDtls},this.options.role,this.options.keys,e),this.options.role===`phone`&&!this.send(this.handshake.begin())){this.fail();return}for(let e of this.pendingData.splice(0))this.directMessage(e)}}directMessage(e){if(this.active)try{if(!this.peer||e.length>61e3)throw Error(`direct frame bounds`);if(this.secureSession){this.options.frame(this.secureSession,e);return}if(!this.handshake){if(!this.verifying||this.pendingData.length>=4||e.length>1024)throw Error(`direct handshake missing`);this.pendingData.push(e.slice());return}let t=this.handshake.receive(e);if(t&&!this.send(t))throw Error(`direct queue refused`);this.handshake.ready&&(this.secureSession=this.handshake.takeReadySession(),this.handshake=null,this.options.ready(this.secureSession))}catch{this.fail(`direct-frame`)}}};const cf=Uint8Array.of(1,0,0,0,0,0,0,0);var lf=class{options;stage;startedAt=null;sessionId=null;attemptId=null;handshake=null;session=null;timer=null;keys;timeoutMs;constructor(e){if(this.options=e,U.parse(e.computerFp),U.parse(e.phoneFp),e.role!==`phone`&&e.role!==`computer`)throw Error(`invalid v2 role`);if(e.keys.staticPrivate.length!==32||e.keys.remoteStatic.length!==32||e.keys.pairKey.length!==32)throw Error(`invalid v2 pairing keys`);if(this.timeoutMs=e.timeoutMs??15e3,!Number.isSafeInteger(this.timeoutMs)||this.timeoutMs<1||this.timeoutMs>3e4)throw Error(`invalid v2 bootstrap timeout`);this.keys={staticPrivate:e.keys.staticPrivate.slice(),remoteStatic:e.keys.remoteStatic.slice(),pairKey:e.keys.pairKey.slice()},this.stage=e.role===`phone`?`phone:new`:`computer:begin`}get ready(){return this.stage===`ready`&&this.session?.ready===!0}begin(){if(this.stage!==`phone:new`)throw Error(`v2 begin not allowed`);try{return this.startedAt=this.clock(),this.armTimer(),this.sessionId=this.freshId(),this.stage=`phone:accept`,Yd({type:`session.v2.begin`,sessionId:this.sessionId,generation:cf})}catch(e){throw this.close(),e}}receive(e){try{if(this.stage===`closed`||this.stage===`detached`||this.stage===`ready`)throw Error(`v2 bootstrap no longer accepts messages`);switch(this.stage!==`computer:begin`&&this.assertNotExpired(),this.stage){case`computer:begin`:{let t=Xd(e,{sender:`phone`,expectedType:`session.v2.begin`});if(t.type!==`session.v2.begin`)throw Error(`invalid v2 begin`);if(this.startedAt=this.clock(),this.armTimer(),this.sessionId=t.sessionId.slice(),this.attemptId=this.freshId(),Er(this.sessionId,this.attemptId))throw Error(`repeated v2 attempt ID`);return this.handshake=this.newHandshake(),this.stage=`computer:noise1`,Yd({type:`session.v2.accept`,sessionId:this.sessionId,attemptId:this.attemptId,generation:cf})}case`phone:accept`:{let t=Xd(e,{sender:`computer`,expectedType:`session.v2.accept`,sessionId:this.requireSessionId()});if(t.type!==`session.v2.accept`)throw Error(`invalid v2 accept`);if(this.attemptId=t.attemptId.slice(),Er(this.requireSessionId(),this.attemptId))throw Error(`repeated v2 attempt ID`);this.handshake=this.newHandshake();let n=this.handshake.write();return this.stage=`phone:noise2`,Yd({type:`session.v2.noise1`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId(),message:n})}case`computer:noise1`:{let t=Xd(e,{sender:`phone`,expectedType:`session.v2.noise1`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId()});if(t.type!==`session.v2.noise1`||!this.handshake)throw Error(`invalid v2 noise1`);this.handshake.read(t.message);let n=this.handshake.write();return this.session=this.handshake.finish(),this.handshake=null,this.stage=`computer:confirm`,Yd({type:`session.v2.noise2`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId(),message:n})}case`phone:noise2`:{let t=Xd(e,{sender:`computer`,expectedType:`session.v2.noise2`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId()});if(t.type!==`session.v2.noise2`||!this.handshake)throw Error(`invalid v2 noise2`);this.handshake.read(t.message),this.session=this.handshake.finish(),this.handshake=null;let n=Rl(this.session.confirmation());return this.stage=`phone:confirm`,Yd({type:`session.v2.confirm`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId(),frame:n})}case`computer:confirm`:{let t=this.decodeConfirmation(e,`phone`);if(!this.session)throw Error(`v2 session missing`);this.session.acceptConfirmation(zl(t.frame));let n=Rl(this.session.confirmation());if(!this.session.ready)throw Error(`v2 computer confirmation incomplete`);return this.markReady(),Yd({type:`session.v2.confirm`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId(),frame:n})}case`phone:confirm`:{let t=this.decodeConfirmation(e,`computer`);if(!this.session)throw Error(`v2 session missing`);if(this.session.acceptConfirmation(zl(t.frame)),!this.session.ready)throw Error(`v2 phone confirmation incomplete`);return this.markReady(),null}default:throw Error(`invalid v2 bootstrap stage`)}}catch(e){throw this.close(),e}}takeReadySession(){if(!this.ready||!this.session)throw Error(`v2 session not confirmed`);let e=this.session;return this.session=null,this.stage=`detached`,e}close(){this.stage!==`closed`&&(this.stage=`closed`,this.clearTimer(),this.handshake?.close(),this.handshake=null,this.session?.close(),this.session=null,this.keys.staticPrivate.fill(0),this.keys.remoteStatic.fill(0),this.keys.pairKey.fill(0))}decodeConfirmation(e,t){let n=Xd(e,{sender:t,expectedType:`session.v2.confirm`,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId()});if(n.type!==`session.v2.confirm`)throw Error(`invalid v2 confirmation`);return n}newHandshake(){let e={route:`relay`,computerFp:this.options.computerFp,phoneFp:this.options.phoneFp,sessionId:this.requireSessionId(),attemptId:this.requireAttemptId(),generation:cf};try{return Vl(e,this.options.role,this.keys)}finally{this.keys.staticPrivate.fill(0),this.keys.remoteStatic.fill(0),this.keys.pairKey.fill(0)}}freshId(){return Ol.parse(this.options.newId()).slice()}requireSessionId(){if(!this.sessionId)throw Error(`v2 session ID missing`);return this.sessionId}requireAttemptId(){if(!this.attemptId)throw Error(`v2 attempt ID missing`);return this.attemptId}clock(){let e=this.options.now();if(!Number.isFinite(e)||e<0)throw Error(`invalid v2 clock`);return e}armTimer(){this.clearTimer(),this.timer=setTimeout(()=>this.close(),this.timeoutMs)}clearTimer(){this.timer!==null&&clearTimeout(this.timer),this.timer=null}markReady(){this.stage=`ready`,this.clearTimer()}assertNotExpired(){if(this.startedAt===null)throw Error(`v2 bootstrap not started`);let e=this.clock()-this.startedAt;if(e<0||e>this.timeoutMs)throw Error(`v2 bootstrap expired`)}},uf=class{options;stage;pairKey;bootstrap;timeoutMs;startedAt=null;timer=null;phoneNonce=null;connKey=null;connTag=``;seqIn=0;seqOut=0;constructor(e){if(this.options=e,U.parse(e.computerFp),U.parse(e.phoneFp),e.role!==`phone`&&e.role!==`computer`)throw Error(`invalid v2 role`);if(e.keys.pairKey.length!==32)throw Error(`invalid pair key`);if(this.timeoutMs=e.timeoutMs??15e3,!Number.isSafeInteger(this.timeoutMs)||this.timeoutMs<1)throw Error(`invalid v2 carrier timeout`);this.pairKey=e.keys.pairKey.slice(),this.bootstrap=new lf(e),this.stage=e.role===`phone`?`phone:new`:`computer:hello`}get ready(){return this.stage===`ready`&&this.bootstrap.ready}get closed(){return this.stage===`closed`}start(){if(this.stage!==`phone:new`)throw Error(`v2 carrier cannot start`);try{return this.startDeadline(),this.phoneNonce=ba(16),this.stage=`phone:hello`,this.hello(this.phoneNonce)}catch(e){throw this.close(),e}}receive(e){if(this.stage===`closed`||this.stage===`ready`||this.stage===`phone:new`)throw Error(`v2 carrier not receiving`);try{this.stage!==`computer:hello`&&this.checkDeadline();let t=this.options.role===`phone`?this.options.computerFp:this.options.phoneFp,n=this.options.role===`phone`?this.options.phoneFp:this.options.computerFp;if(e.v!==1||e.t!==`e2e`||e.from!==t||e.to!==n)throw Error(`v2 carrier peer mismatch`);let r=Qn.parse(e.body);if(r.c.length<16||r.c.length>2048)throw Error(`v2 carrier ciphertext exceeds bound`);if(this.stage===`phone:hello`||this.stage===`computer:hello`){if(e.seq!==0)throw Error(`v2 carrier expected hello`);let i=Bu(Kn(dc(this.pairKey,r,_c(t,n))));if(i.type!==`conn.hello`||!i.features?.includes(`session-v2`))throw Error(`v2 carrier requires v2 hello intent`);if(this.stage===`computer:hello`){this.startDeadline(),this.phoneNonce=i.n.slice();let e=ba(16);if(Er(this.phoneNonce,e))throw Error(`reused hello nonce`);return this.deriveConnection(this.phoneNonce,e),this.stage=`bootstrap`,this.hello(e)}if(!this.phoneNonce||Er(this.phoneNonce,i.n))throw Error(`invalid hello nonce`);return this.deriveConnection(this.phoneNonce,i.n),this.stage=`bootstrap`,this.frame(this.bootstrap.begin())}if(!this.connKey||e.seq!==this.seqIn+1)throw Error(`v2 carrier frame sequence mismatch`);let i=Bu(Kn(dc(this.connKey,r,gc(t,n,this.connTag,e.seq))));if(i.type!==`session.v2.bootstrap`)throw Error(`v2 carrier rejects legacy terminal message`);this.seqIn=e.seq;let a=this.bootstrap.receive(i.bytes);return this.bootstrap.ready&&(this.stage=`ready`,this.clearDeadline()),a?this.frame(a):null}catch(e){throw this.close(),e}}takeReadySession(){if(!this.ready)throw Error(`v2 carrier not confirmed`);let e=this.bootstrap.takeReadySession();return this.close(),e}close(){this.stage!==`closed`&&(this.stage=`closed`,this.clearDeadline(),this.pairKey.fill(0),this.phoneNonce?.fill(0),this.phoneNonce=null,this.connKey?.fill(0),this.connKey=null,this.connTag=``,this.bootstrap.close())}hello(e){let t=this.options.role===`phone`?this.options.phoneFp:this.options.computerFp,n=this.options.role===`phone`?this.options.computerFp:this.options.phoneFp;return{v:1,t:`e2e`,from:t,to:n,seq:0,body:uc(this.pairKey,Gn({type:`conn.hello`,n:e,features:[`session-v2`]}),_c(t,n))}}frame(e){if(!this.connKey||this.seqOut>=2**53-1)throw Error(`v2 carrier unavailable`);let t=this.options.role===`phone`?this.options.phoneFp:this.options.computerFp,n=this.options.role===`phone`?this.options.computerFp:this.options.phoneFp,r=++this.seqOut;return{v:1,t:`e2e`,from:t,to:n,seq:r,body:uc(this.connKey,Gn({type:`session.v2.bootstrap`,bytes:e}),gc(t,n,this.connTag,r))}}deriveConnection(e,t){let n=mc(this.pairKey,e,t,this.options.computerFp,this.options.phoneFp);this.connKey=n.kConn,this.connTag=n.connTag}startDeadline(){if(this.startedAt=this.options.now(),!Number.isFinite(this.startedAt))throw Error(`invalid v2 carrier clock`);this.timer=setTimeout(()=>this.close(),this.timeoutMs)}checkDeadline(){let e=this.options.now();if(this.startedAt===null||!Number.isFinite(e)||e<this.startedAt||e-this.startedAt>=this.timeoutMs)throw Error(`v2 carrier handshake expired`)}clearDeadline(){this.timer&&clearTimeout(this.timer),this.timer=null}};function df(e){return{route:e.route,sessionId:e.sessionId.slice(),attemptId:e.attemptId.slice(),generation:e.generation.slice()}}function ff(e,t){return e.route===t.route&&Er(e.sessionId,t.sessionId)&&Er(e.attemptId,t.attemptId)&&Er(e.generation,t.generation)}var pf=class{options;relay=null;active=null;staged=null;transition=null;wireIds=new Set;attemptIds=new Set;transitionIds=new Set;highGeneration=1n;directAttempts=0;lastNow=-1;deadline=null;timer=null;revoked=!1;recovering=!1;snapshot=!1;revision=0;constructor(e){if(this.options=e,U.parse(e.computerFp),U.parse(e.phoneFp),e.role!==`phone`&&e.role!==`computer`)throw Error(`invalid route role`);this.installRelay(e.relay)}get status(){return this.revoked?`closed`:this.recovering?`recovering`:this.transition?`cutover`:this.active?.reference.route??`uncommitted`}get activeRoute(){return this.active?df(this.active.reference):null}get routeRevision(){return this.revision}get needsSnapshot(){return this.snapshot}get preparationPending(){return this.transition?.phase===`computer:preparing`}get paused(){return this.revoked||this.recovering||this.transition!==null||this.active===null}get directActive(){return this.active?.reference.route===`direct`}snapshotApplied(){this.paused||(this.snapshot=!1)}stageDirect(e){if(this.sweep(),this.revoked||this.recovering||!this.active||!this.relay||this.staged||this.transition)throw Error(`route candidate unavailable`);let t=null;try{if(t=this.validate(e,`direct`),!Er(t.reference.sessionId,this.relay.reference.sessionId))throw Error(`direct wire session mismatch`);let n=vl(t.reference.generation);if(n<=this.highGeneration)throw Error(`direct generation reused`);let r=Cr(t.reference.attemptId);if(this.attemptIds.has(r))throw Error(`direct attempt reused`);if(this.directAttempts>=Gl.directAttempts)throw Error(`direct attempt capacity`);this.highGeneration=n,this.directAttempts+=1,this.attemptIds.add(r),this.staged=t,this.arm()}catch(t){throw e.session!==this.active?.session&&e.session!==this.relay?.session&&e.session.close(),t}}begin(){if(this.sweep(),this.options.role!==`phone`||this.revoked||this.recovering||!this.staged||!this.relay||this.transition)throw Error(`route prepare unavailable`);if(!this.options.prepareReady())return!1;let e=Ol.parse(this.options.newId()).slice();if(this.transitionIds.has(Cr(e)))throw Error(`route transition reused`);return this.transitionIds.add(Cr(e)),this.transition={id:e,target:this.staged,phase:`phone:prepared`},this.sendControl(`route.prepare`)}approve(){return this.sweep(),!this.preparationPending||!this.transition||!this.options.prepareReady()||!this.transition.target.session.ready?!1:(this.transition.phase=`computer:commit`,this.sendControl(`route.prepared`))}receive(e,t){if(this.sweep(),this.revoked||this.recovering||!this.registered(e))return null;try{let n=e.open(t),r;try{r=Xl(n)}finally{n.fill(0)}if(r.kind===`control`){if(e!==this.relay?.session)throw Error(`route control requires relay session`);return this.control(r.control),null}if(r.kind===`signal`){if(e!==this.relay?.session)throw Error(`direct signaling requires relay session`);return r}return this.paused||e!==this.active?.session||!this.directActive?(r.bytes.fill(0),null):r}catch{return this.routeLost(e),null}}sendTerminal(e){return this.sweep(),this.paused||!this.active||!this.directActive?!1:this.sendPayload(this.active,{kind:`terminal`,bytes:e})}sendSignal(e){return this.sweep(),this.revoked||this.recovering||!this.relay?!1:this.sendPayload(this.relay,{kind:`signal`,bytes:e})}abort(e=`cancelled`){if(!this.staged&&!this.transition)return;if(this.transition?.phase===`phone:committed`||!this.active){this.failAll();return}let t=this.transition;t&&this.relay&&this.sendPayload(this.relay,{kind:`control`,control:{type:`route.abort`,transitionId:t.id,target:df(t.target.reference),reason:e}}),this.discardCandidate(),t&&(this.snapshot=!0)}relayLost(){this.active?.reference.route===`direct`&&!this.transition&&!this.staged?(this.relay?.session.close(),this.relay=null):this.failAll()}routeLost(e){e===this.active?.session?this.failAll():e===this.relay?.session?this.relayLost():e===this.staged?.session&&this.abort(`candidate-failed`)}recover(e){if(this.revoked)throw e.session.close(),Error(`route owner revoked`);let t=this.validate(e,`relay`);if(this.wireIds.has(Cr(t.reference.sessionId)))throw t.session.close(),Error(`wire session reused`);this.failAll(),this.installRelay(t)}sweep(){if(this.revoked)return;let e=this.clock();this.deadline!==null&&e>=this.deadline&&this.abort(`timeout`)}close(){this.failAll(),this.revoked=!0,this.recovering=!1}validate(e,t){if(!(e.session instanceof Hl)||!e.session.ready||e.session.senderRole!==this.options.role)throw Error(`route session not ready`);let n=e.session.description;if(n.computerFp!==this.options.computerFp||n.phoneFp!==this.options.phoneFp||n.route!==t)throw Error(`route pairing mismatch`);if(t===`relay`&&vl(n.generation)!==1n)throw Error(`relay generation must be one`);return{session:e.session,send:e.send.bind(e),reference:df(n)}}installRelay(e){let t=this.validate(e,`relay`),n=Cr(t.reference.sessionId);if(this.wireIds.has(n)||this.wireIds.size>=Gl.wireSessions)throw t.session.close(),Error(`wire session reused or capacity reached`);this.wireIds.add(n),this.attemptIds.clear(),this.transitionIds.clear(),this.attemptIds.add(Cr(t.reference.attemptId)),this.highGeneration=1n,this.directAttempts=0,this.relay=t,this.staged=t,this.recovering=!1,this.arm()}control(e){if(e.type===`route.prepare`){if(this.options.role!==`computer`||this.transition||!this.staged||!ff(e.target,this.staged.reference)||this.transitionIds.has(Cr(e.transitionId)))throw Error(`invalid route prepare`);this.transitionIds.add(Cr(e.transitionId)),this.transition={id:e.transitionId.slice(),target:this.staged,phase:`computer:preparing`};return}let t=this.transition;if(!t||!ff(e.target,t.target.reference)||!Er(e.transitionId,t.id))throw Error(`route transition mismatch`);if(e.type===`route.abort`){this.abortWithoutSending();return}if(e.type===`route.prepared`&&t.phase===`phone:prepared`){if(!this.options.prepareReady()||!t.target.session.ready)throw Error(`route prepare gate changed`);t.phase=`phone:committed`,this.sendControl(`route.commit`);return}if(e.type===`route.commit`&&t.phase===`computer:commit`){if(!this.options.prepareReady()||!t.target.session.ready)throw Error(`route commit gate changed`);let e={type:`route.committed`,transitionId:t.id,target:df(t.target.reference)};this.activate(),(!this.relay||!this.sendPayload(this.relay,{kind:`control`,control:e}))&&this.failAll();return}if(e.type===`route.committed`&&t.phase===`phone:committed`){this.activate();return}throw Error(`route control order mismatch`)}sendControl(e){return!this.relay||!this.transition?!1:this.sendPayload(this.relay,{kind:`control`,control:{type:e,transitionId:this.transition.id,target:df(this.transition.target.reference)}})}sendPayload(e,t){let n=Yl(t);try{if(e.send(e.session.seal(n))===!0)return!0}catch{}finally{n.fill(0)}return t.kind===`control`?this.failAll():this.routeLost(e.session),!1}activate(){if(!this.staged)throw Error(`route target missing`);let e=this.active;this.active=this.staged,this.staged=null,this.transition=null,e&&e!==this.relay&&e!==this.active&&e.session.close(),this.clearTimer(),this.snapshot=!0,this.revision+=1}abortWithoutSending(){if(this.transition?.phase===`phone:committed`||!this.active){this.failAll();return}this.discardCandidate(),this.snapshot=!0}discardCandidate(){this.staged&&this.staged!==this.active&&this.staged!==this.relay&&this.staged.session.close(),this.staged=null,this.transition=null,this.clearTimer()}failAll(){for(let e of new Set([this.active,this.staged,this.relay]))e?.session.close();this.active=null,this.staged=null,this.relay=null,this.transition=null,this.clearTimer(),this.recovering=!0,this.snapshot=!0,this.revision+=1}registered(e){return e===this.relay?.session||e===this.active?.session||e===this.staged?.session}clock(){let e=this.options.now();if(!Number.isFinite(e)||e<0||e<this.lastNow)throw this.failAll(),Error(`invalid route clock`);return this.lastNow=e,e}arm(){this.clearTimer(),this.deadline=this.clock()+Gl.attemptMs,this.timer=setTimeout(()=>this.abort(`timeout`),Gl.attemptMs)}clearTimer(){this.timer&&clearTimeout(this.timer),this.timer=null,this.deadline=null}};function mf(e,t,n,r){if(e.seq!==0||e.from!==r||e.to!==n)return!1;try{let i=Bu(Kn(dc(t,Qn.parse(e.body),_c(r,n))));return i.type===`conn.hello`&&i.features?.includes(`session-v2`)===!0}catch{return!1}}var hf=class{options;carrier=null;owner=null;relaySession=null;direct=null;directStartedAt=null;directSetupMs=null;generation=1n;lastFailure=null;retryAt=null;retryFailures=0;nativeAttempts=0;retriesExhausted=!1;traffic={relaySent:0,relayReceived:0,directSent:0,directReceived:0};bootstrapRevision=0;reportedRevision=-1;reportedRoute=null;reportedState=``;recoveryNotified=!1;closed=!1;incoming=Promise.resolve();queued=0;clock;interval;constructor(e){this.options=e,this.clock=e.now??(()=>performance.now()),this.interval=setInterval(()=>this.poll(),100)}get activeRoute(){return this.owner?.activeRoute?.route??null}get ready(){return this.activeRoute!==null&&this.owner?.paused===!1}get routeRevision(){return this.owner?.routeRevision??0}get diagnostics(){let e=this.direct,t=this.activeRoute===`direct`?`direct`:e?.phase??`none`;return{route:this.activeRoute,ready:this.ready,phase:t,lastFailure:this.lastFailure,directSetupMs:this.directSetupMs,...this.traffic}}routeStats(){return this.activeRoute!==`direct`||!this.direct?Promise.resolve(null):this.direct.routeStats().catch(()=>null)}get state(){let{route:e,ready:t,phase:n,lastFailure:r}=this.diagnostics;return{route:e,ready:t,phase:n,lastFailure:r,retryPending:this.retryAt!==null}}sendRelay(e){let t=this.options.sendRelay(e);return t&&e.v===2&&(this.traffic.relaySent+=e.body.length),t}begin(){this.closed||this.options.role!==`phone`||(this.carrier?.close(),this.carrier=this.newCarrier(),this.bootstrapRevision+=1,this.sendRelay(this.carrier.start())||this.bootstrapFailed())}receiveRelay(e){if(this.closed)return Promise.resolve();if(++this.queued>32)return--this.queued,this.bootstrapFailed(),Promise.resolve();let t=this.incoming.then(()=>this.relay(e));return this.incoming=t.catch(()=>this.bootstrapFailed()).finally(()=>{--this.queued}),this.incoming}sendTerminal(e){return this.owner?.sendTerminal(e)??!1}relayLost(){this.owner?.relayLost(),this.carrier?.close(),this.carrier=null,this.changed()}close(){this.closed||(this.closed=!0,clearInterval(this.interval),this.carrier?.close(),this.carrier=null,this.owner?.close(),this.owner=null,this.closeDirect())}interruptDirect(){this.directFailed(`interrupted`)}newCarrier(){return new uf({role:this.options.role,computerFp:this.options.computerFp,phoneFp:this.options.phoneFp,keys:this.options.keys,now:this.clock,newId:()=>ba(16)})}async relay(e){if(this.closed||e.from!==(this.options.role===`phone`?this.options.computerFp:this.options.phoneFp)||e.to!==(this.options.role===`phone`?this.options.phoneFp:this.options.computerFp))return;if(e.v===2){if(this.traffic.relayReceived+=e.body.length,!this.owner||!this.relaySession)return;let t=this.owner.receive(this.relaySession,zl(e.body));if(t?.kind===`terminal`)this.options.terminal(t.bytes,e.body.length);else if(t?.kind===`signal`){let e=this.direct;try{await this.signal(t.bytes)}catch{this.direct===e&&!e?.session?.ready&&this.directFailed(`remote-signal`,e??void 0)}}this.poll();return}if(e.t!==`e2e`)return;if(this.options.role===`computer`&&e.seq===0){if(!mf(e,this.options.keys.pairKey,this.options.computerFp,this.options.phoneFp))return;this.carrier?.close(),this.carrier=this.newCarrier(),this.bootstrapRevision+=1}let t=this.carrier;if(!t)return;let n=this.bootstrapRevision,r=t.receive(e);if(r&&!this.sendRelay(r))throw Error(`bootstrap queue refused`);if(!t.ready)return;let i=t.takeReadySession();this.carrier=null;try{await this.options.commitFloor()}catch(e){throw i.close(),e}if(this.closed||n!==this.bootstrapRevision){i.close();return}this.closeDirect(),this.relaySession=i,this.generation=1n,this.nativeAttempts=0,this.retriesExhausted=!1,this.retryAt=null;let a={session:i,send:e=>this.sendRelay({v:2,t:`e2e`,from:this.options.role===`phone`?this.options.phoneFp:this.options.computerFp,to:this.options.role===`phone`?this.options.computerFp:this.options.phoneFp,body:Rl(e)})};this.owner?this.owner.recover(a):this.owner=new pf({role:this.options.role,computerFp:this.options.computerFp,phoneFp:this.options.phoneFp,relay:a,now:this.clock,newId:()=>ba(16),prepareReady:this.options.prepareReady}),this.options.role===`phone`&&this.owner.begin(),this.recoveryNotified=!1,this.poll()}poll(){if(this.closed||(this.carrier?.closed&&this.bootstrapFailed(),!this.owner))return;try{this.owner.sweep(),this.owner.preparationPending&&this.owner.approve(),this.options.role===`phone`&&(this.owner.status===`uncommitted`||this.owner.status===`relay`&&this.direct?.session&&this.direct.session.ready)&&this.owner.begin(),this.changed(),this.retryDirect(),this.owner.status===`recovering`&&!this.carrier&&!this.recoveryNotified&&(this.recoveryNotified=!0,this.closeDirect(),this.options.failure(`recovery`))}catch{this.options.failure(`recovery`)}let e=this.state,t=JSON.stringify(e);t!==this.reportedState&&(this.reportedState=t,this.options.stateChanged?.(e))}changed(){let e=this.activeRoute,t=this.routeRevision;(this.reportedRevision!==t||this.reportedRoute!==e)&&(this.reportedRevision=t,this.reportedRoute=e,this.options.routeChanged(e,t),e===`direct`&&this.direct&&(this.directStartedAt!==null&&(this.directSetupMs=Math.round(this.clock()-this.directStartedAt)),this.directStartedAt=null,this.direct.cancelDeadline(),this.retryFailures=0,this.retryAt=null,this.lastFailure=null))}retryDirect(){if(this.options.role===`phone`&&this.options.allowDirect&&this.options.native&&!this.retriesExhausted&&!this.direct&&!this.carrier&&this.ready&&this.activeRoute===`relay`&&this.options.prepareReady()&&!(this.retryAt!==null&&this.clock()<this.retryAt)){if(this.nativeAttempts>=Gl.directAttempts){this.retriesExhausted=!0,this.bootstrapFailed();return}this.nativeAttempts+=1,this.retryAt=null,this.startDirect()}}bootstrapFailed(){this.carrier?.close(),this.carrier=null,this.options.failure(`bootstrap`)}async startDirect(e){if(this.closed||this.direct||!this.ready||!this.relaySession||!this.options.native)return;this.generation=e?new DataView(e.generation.buffer,e.generation.byteOffset,8).getBigUint64(0,!0):this.generation+1n;let t=new sf({role:this.options.role,keys:this.options.keys,computerFp:this.options.computerFp,phoneFp:this.options.phoneFp,relay:this.relaySession.description,generation:e?.generation??_l(this.generation),offer:e,native:this.options.native,current:()=>!this.closed&&this.direct===t,committed:()=>this.activeRoute===`direct`,sendSignal:e=>this.sendSignal(e),sent:e=>{this.traffic.directSent+=e},received:e=>{this.traffic.directReceived+=e},ready:e=>{this.owner?.stageDirect({session:e,send:e=>t.send(Rl(e))}),this.options.role===`phone`&&this.owner?.begin()},frame:(e,t)=>{let n=this.owner?.receive(e,zl(t));n?.kind===`terminal`&&this.options.terminal(n.bytes,t.length),this.poll()},failed:e=>this.directFailed(e,t)});this.direct=t,this.directStartedAt=this.clock(),await t.start()}async signal(e){if(!this.relaySession||!this.owner)return;let t=this.direct;if(this.activeRoute===`direct`&&t?.session?.ready)return;let n=ef(e,{sender:this.options.role===`phone`?`computer`:`phone`,sessionId:this.relaySession.description.sessionId,committedGeneration:this.relaySession.description.generation,...t&&{pending:{offerId:t.offerId,generation:t.generation}}});if(n.type===`direct.offer`){if(!this.options.native||this.options.role!==`computer`)return;await this.startDirect(n);return}await t?.signal(n)}sendSignal(e){return this.owner?.sendSignal($d(e))??!1}directFailed(e=`closed`,t){if(t&&this.direct!==t)return;let n=this.direct;if(!n)return;let r=this.diagnostics.phase,i=Math.min(6e4,5e3*2**this.retryFailures);if(this.retryFailures=Math.min(this.retryFailures+1,4),this.retryAt=this.clock()+Math.min(6e4,i*(.8+.4*ba(1)[0]/255)),this.lastFailure=e,!n.session?.ready)try{this.sendSignal({type:`direct.abort`,...n.signalContext(),reason:e===`timeout`?`timeout`:e===`certificate`?`dtls-failed`:`ice-failed`})}catch{}let a=n?.session;a&&this.owner?.routeLost(a),this.closeDirect(),this.options.failure(`direct`,{code:e,phase:r}),this.poll()}closeDirect(){let e=this.direct;this.direct=null,e&&e.close()}};function gf(e,t){return rr.every(n=>e?.includes(n)&&t.includes(n))?[...rr,...e?.includes(`native-history-v1`)&&t.includes(`native-history-v1`)?[ir]:[]]:[]}function _f(e){if(e.length>4096)return!1;for(let t=0;t<e.length;t++){let n=e.charCodeAt(t);if(n>=55296&&n<=56319){let n=e.charCodeAt(++t);if(!(n>=56320&&n<=57343))return!1}else if(n>=56320&&n<=57343)return!1}return!0}const vf=ru.extend({t:ru.shape.t.refine(_f)}).strict(),yf=iu.extend({r:F.array(vf)}).strict(),bf=yf.extend({r:F.array(vf).max(2048)}),xf=F.number().int().min(0).max(2**53-1),Sf={kind:F.literal(`history`),generation:xf,requestId:G,before:xf},Cf=F.custom(e=>Array.isArray(e)&&e.length>0&&e.length<=W.historyLines),wf=F.strictObject({...Sf,status:F.literal(`page`),from:xf,to:xf,oldestAvailable:xf,lines:Cf});function Tf(e){return e.to===e.before&&e.lines.length<=2**53-1-e.from&&e.from+e.lines.length===e.to&&e.oldestAvailable<=e.from}const Ef=wf.refine(Tf),Df=wf.extend({nextBefore:xf}).refine(e=>Tf(e)&&e.nextBefore===e.from),Of=F.strictObject({...Sf,status:F.literal(`boundary`),reason:F.enum([`end`,`truncated`]),oldestAvailable:xf}).refine(e=>e.reason===`end`?e.before===e.oldestAvailable:e.before<e.oldestAvailable),kf=F.discriminatedUnion(`status`,[Ef,Of]),Af=F.discriminatedUnion(`status`,[Df,Of]),jf=F.strictObject({r:F.unknown(),w:F.boolean().optional()}),Mf={ok:!1,code:`invalid-transfer`},Nf={ok:!1,code:`history-line-too-large`};function Pf(e){let t=jf.safeParse(e);if(!t.success||!Array.isArray(t.data.r))return Mf;if(t.data.r.length>2048)return Nf;let n={r:[],...t.data.w===void 0?{}:{w:t.data.w}},r=0,i=0;for(let e of t.data.r){let t=vf.safeParse(e);if(!t.success)return Mf;if(r+=t.data.n??kd(t.data.t),r>W.historyCells||(i+=Gn(t.data).length,i>W.historyBytes))return Nf;n.r.push(t.data)}let a=Gn(n).length;return a>W.historyBytes?Nf:{ok:!0,line:n,bytes:a}}F.unknown().transform((e,t)=>{let n=()=>(t.addIssue({code:`custom`,message:`invalid history record`}),F.NEVER);try{let t=Af.safeParse(e);if(!t.success)return n();let r;if(t.data.status===`boundary`)r=t.data;else{let e=[],i=0;for(let r of t.data.lines){let t=Pf(r);if(!t.ok||(i+=t.bytes,i>W.historyBytes))return n();e.push(t.line)}r={...t.data,lines:e}}return Gn(r).length>W.historyBytes?n():r}catch{return n()}});function Ff(e){try{let t=kf.safeParse(e);if(!t.success)return Mf;if(t.data.status===`boundary`){let e=t.data;return{ok:!0,record:e,bytes:Gn(e)}}let n=t.data,r=[],i=0,a;for(let e=n.lines.length-1;e>=0;e--){let t=Pf(n.lines[e]);if(!t.ok){if(t.code===`invalid-transfer`)return Mf;break}if(i+=t.bytes,i>W.historyBytes)break;r.unshift(t.line);let o=n.from+e,s={...n,from:o,nextBefore:o,lines:r.slice()},c=Gn(s);c.length<=W.historyBytes&&(a={ok:!0,record:s,bytes:c})}return a??{...Nf,before:n.before}}catch{return Mf}}const If=F.number().int().min(0).max(2**53-1),Lf=If.min(1),Rf=au.extend({x:If,y:F.number().int().min(-1).max(2**53-1)}).strict(),zf=F.strictObject({cols:Lf,rows:Lf,cursor:Rf,lines:F.array(yf),scrollbackTotal:If,gen:If,reset:F.boolean().optional(),degraded:F.boolean().optional()});function Bf(e){return e.lines.length===e.rows&&e.cursor.x<=e.cols&&e.cursor.y<e.rows&&Vf(e.lines,e.cols)}function Vf(e,t){return e.every(e=>{let n=0;for(let r of e.r)if(n+=r.n??kd(r.t),n>t)return!1;return!0})}function Hf(e){let t=0,n=0;for(let r of e){t+=r.r.length;for(let e of r.r)n+=kd(e.t)}return{runs:t,points:n}}function Uf(e){let{runs:t,points:n}=Hf(e);return t<=W.runs&&n<=W.codePoints}const Wf=zf.extend({kind:F.literal(`snapshot`),cols:Lf.max(W.cols),rows:Lf.max(W.rows),lines:F.array(bf).max(W.rows)}).refine(e=>Bf(e)&&Uf(e.lines)),Gf=F.strictObject({scroll:If.max(W.rows),changed:F.array(F.strictObject({i:If.max(W.rows-1),line:bf})).max(W.rows),cursor:Rf.extend({x:If.max(W.cols),y:Rf.shape.y.max(W.rows-1)}),scrollbackTotal:If,gen:Lf}),Kf=Gf.extend({kind:F.literal(`diff`)}).refine(e=>{let t=new Set(e.changed.map(e=>e.i)),n=e.changed.map(e=>e.line);return t.size===e.changed.length&&Vf(n,W.cols)&&Uf(n)}),qf=F.discriminatedUnion(`kind`,[Wf,Kf]);function Jf(e){let t=qf.safeParse(e);if(!t.success)throw new V(`malformed`);let n;try{n=Gn(t.data)}catch{throw new V(`malformed`)}if(n.length>W.screenBytes)throw new V(`malformed`);return{record:t.data,bytes:n}}function Yf(e){let{kind:t,...n}=e;return n}function Xf(e){let t=zf.safeParse(e);if(!t.success||!Bf(t.data))return{ok:!1,code:`invalid-transfer`};let n=t.data;if(n.cols>W.cols||n.rows>W.rows||Hf(n.lines).points>W.codePoints)return{ok:!1,code:`screen-too-large`};for(let e=0;e<2;e++){let t=e===0?n:{...n,lines:n.lines.map(Fd),degraded:!0};try{let{record:e,bytes:n}=Jf({kind:`snapshot`,...t});if(e.kind===`snapshot`)return{ok:!0,snapshot:Yf(e),bytes:n}}catch{}}return{ok:!1,code:`screen-too-large`}}function Zf(e){let t=Gf.safeParse(e);if(!t.success)throw new V(`malformed`);return Jf({kind:`diff`,...t.data}).bytes}var Qf=class{options;lanes=[null,null];outstanding=[];state=`open`;nextLane=0;lastSequence=0;acknowledgedThrough=0;constructor(e){if(!lr.shape.subscriptionId.safeParse(e.subscriptionId).success||!lr.shape.sessionId.safeParse(e.sessionId).success)throw Error(`Invalid stream sender identity`);this.options={...e}}canOffer(e){return this.tick()===`open`&&this.lanes[+(e===`history`)]===null}offer(e,t){if(this.tick()!==`open`)return{accepted:!1,reason:`closed`};let n=cr.safeParse(e);if(!n.success||!(t instanceof Uint8Array)||t.length===0)throw Error(`Invalid stream transfer`);let r=+(n.data.kind===`history`),i=r===1?W.historyBytes:W.screenBytes;if(t.length>i)return{accepted:!1,reason:`too-large`};if(this.lanes[r])return{accepted:!1,reason:`busy`};let a;try{a=this.options.newTransferId()}catch(e){throw this.cancel(),e}if(!lr.shape.transferId.safeParse(a).success)throw Error(`Invalid stream transfer identity`);return this.state===`open`?(this.lanes[r]={id:a,meta:n.data,bytes:new Uint8Array(t),count:Math.ceil(t.length/W.chunkBytes),nextIndex:0,acknowledged:0,startedAt:null,progressAt:null},{accepted:!0,transferId:a}):{accepted:!1,reason:`closed`}}pump(){if(this.tick()!==`open`)return 0;let e=0;for(;e<W.unacked&&this.inFlight<W.unacked&&this.tick()===`open`;){let t=this.nextLane,n=this.lanes[t];if((!n||n.nextIndex===n.count)&&(t=1-t,n=this.lanes[t]),!n||n.nextIndex===n.count)break;if(this.lastSequence===2**53-1){this.cancel();break}let r=this.lastSequence+1,i=n.nextIndex,a={type:`stream.chunk`,subscriptionId:this.options.subscriptionId,sessionId:this.options.sessionId,transferId:n.id,sequence:r,index:i,count:n.count,totalBytes:n.bytes.length,data:n.bytes.slice(i*W.chunkBytes,(i+1)*W.chunkBytes),meta:{...n.meta}},o;try{o=this.options.send(a)}catch(e){throw this.cancel(),e}if(o&&e++,this.state!==`open`||!o)break;this.lastSequence=r,n.nextIndex++,n.startedAt===null&&(n.startedAt=this.options.now(),n.progressAt=n.startedAt),this.outstanding.push({sequence:r,transfer:n}),this.nextLane=1-t}return e}acknowledge(e,t){if(e!==this.options.subscriptionId||this.tick()!==`open`)return`ignored`;if(!Number.isSafeInteger(t)||t<1||t>this.lastSequence)return`invalid`;if(t<=this.acknowledgedThrough)return`duplicate`;let n=this.options.now();for(let e of this.outstanding){if(e.sequence>t)break;e.transfer.acknowledged++,e.transfer.progressAt=n,e.transfer.acknowledged===e.transfer.count&&(this.lanes[+(e.transfer.meta.kind===`history`)]=null)}return this.outstanding=this.outstanding.filter(e=>e.sequence>t),this.acknowledgedThrough=t,`advanced`}tick(){let e=this.nextDeadline();return e!==null&&this.options.now()>=e&&this.stop(`stalled`),this.state}nextDeadline(){let e=1/0;for(let t of this.lanes)t&&t.startedAt!==null&&t.progressAt!==null&&(e=Math.min(e,t.startedAt+W.totalMs,t.progressAt+W.progressMs));return Number.isFinite(e)?e:null}cancel(){this.stop(`closed`)}stop(e){this.state=e,this.lanes[0]=null,this.lanes[1]=null,this.outstanding=[]}get inFlight(){return this.outstanding.length}get retainedBytes(){return(this.lanes[0]?.bytes.length??0)+(this.lanes[1]?.bytes.length??0)}},$f=`0.15.1`;const ep=/^owner-([1-9][0-9]*)-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;function tp(e){if(!/^[1-9][0-9]*$/.test(e))return null;let t=Number(e);return Number.isInteger(t)&&t<=2147483647?t:null}function np(e){try{return process.kill(e,0),!0}catch(e){let t=e.code;if(t===`ESRCH`)return!1;if(t===`EPERM`)return!0;throw e}}function rp(e,n){try{t.unlinkSync(N(e,n))}catch(e){if(e.code!==`ENOENT`)throw e}try{t.rmdirSync(e)}catch(e){if(![`ENOENT`,`ENOTEMPTY`,`EEXIST`].includes(e.code??``))throw e}}function ip(e){let n=`${A(e)}.lock-candidate-`;for(let r of t.readdirSync(j(e))){if(!r.startsWith(n))continue;let i=`owner-${r.slice(n.length)}`,a=ep.exec(i),o=a&&tp(a[1]);if(!o)continue;let s=N(j(e),r);try{if(np(o)||!t.lstatSync(s).isDirectory())continue;let e=t.readdirSync(s);e.length===0?t.rmdirSync(s):e.length===1&&e[0]===i&&t.lstatSync(N(s,i)).isFile()&&rp(s,i)}catch{}}}function ap(e){let n=`${e}.lock`,r=`${process.pid}-${ce()}`,i=`${e}.lock-candidate-${r}`,a=`owner-${r}`;t.mkdirSync(i,{mode:448});let o=!1;try{t.writeFileSync(N(i,a),``,{mode:384,flag:`wx`});for(let r=0;r<3;r++){try{t.renameSync(i,n),o=!0;try{ip(e)}catch{}return()=>rp(n,a)}catch(e){if(![`EEXIST`,`ENOTEMPTY`].includes(e.code??``))throw e}try{if(!t.lstatSync(n).isDirectory())throw Error(`Invalid control guard ${n}; inspect it before retrying`);let e=t.readdirSync(n);if(e.length===0)continue;let r=e[0],i=ep.exec(r),a=i&&tp(i[1]);if(e.length!==1||!a||!t.lstatSync(N(n,r)).isFile())throw Error(`Invalid control guard ${n}; inspect its owner marker before retrying`);if(np(a))throw Error(`Control endpoint busy (guard owner pid ${a})`);rp(n,r)}catch(e){if(e.code!==`ENOENT`)throw e}}throw Error(`Control endpoint busy; could not acquire ${n} after three attempts`)}finally{o||rp(i,a)}}var Y=class extends Error{kind;constructor(e){super(`shellbell: ${e} Linux host state; inspect ownership, permissions and host initialization`),this.kind=e}};function X(e){try{return p(e)}catch(e){if(e.code===`ENOENT`)return;throw new Y(`unsafe`)}}function op(e,t){return e.dev===t.dev&&e.ino===t.ino}function Z(e,t){let n=X(e);if(!n)throw new Y(`missing`);if(!n.isDirectory()||n.isSymbolicLink()||n.uid!==t||(n.mode&4095)!=448)throw new Y(`unsafe`);return n}function sp(e){let t=P(e),n=X(t);if(n){if(n.isSymbolicLink()||!n.isDirectory())throw new Y(`unsafe`);return y(t)}return N(cp(j(t)),A(t))}function cp(e){if(X(e))try{return y(e)}catch{throw new Y(`unsafe`)}return N(cp(j(e)),A(e))}function lp(e,t,n,r=!0){let i;try{let a=X(e);if(!a)throw new Y(`missing`);let s=e=>{if(!e.isFile()||e.isSymbolicLink()||n!==void 0&&(e.uid!==n||(e.mode&4095)!=384))throw new Y(`unsafe`);if(e.size>t)throw new Y(`invalid`)};s(a),i=h(e,o.O_RDONLY|o.O_NOFOLLOW|o.O_NONBLOCK);let c=l(i);if(s(c),!op(a,c))throw new Y(`unsafe`);let u=Buffer.alloc(t+ +!!r),d=0;for(;d<u.length;){let e=_(i,u,d,u.length-d,null);if(e===0)break;d+=e}let f=l(i),p=X(e);if(s(f),!p||!op(c,p)||!op(c,f)||c.size!==f.size||c.mtimeMs!==f.mtimeMs||c.ctimeMs!==f.ctimeMs)throw new Y(`unsafe`);if(s(p),d>t||d!==f.size)throw new Y(`invalid`);return u.subarray(0,d)}catch(e){throw e instanceof Y?e:new Y(`unsafe`)}finally{i!==void 0&&a(i)}}function up(e={}){let t=e.uid??process.getuid?.(),n=e.euid??process.geteuid?.();if(!Number.isInteger(t)||t===void 0||t<=0||t!==n)throw Error(`shellbell: Linux hosting requires matching non-root real and effective users`);let r;try{let t=lp(e.machineIdPath??`/etc/machine-id`,256,void 0,!1).toString(`utf8`);if(!/^[0-9a-fA-F]{32}\n?$/.test(t)||/^0{32}\n?$/.test(t))throw Error();r=Buffer.from(t.trim().toLowerCase(),`hex`)}catch{throw Error(`shellbell: Linux machine identity is unavailable or invalid; provision /etc/machine-id before host initialization`)}let i=oe(`sha256`,`shellbell.local-host-scope.v1`).update(r).digest(`hex`),a=i.slice(0,32);return{uid:t,machineId:r.toString(`hex`),hostDigest:i,hostScope:a}}const dp=new WeakMap,fp=new Set([16914836,61267,1481003842,2435016766]);function pp(e,t){let n=dp.get(e),r=n?.root??j(j(e.runtimeDir)),i=n?.fsType??(e=>C(e).type);try{if(Z(r,e.linuxHost.uid),!fp.has(Number(i(r))))throw new Y(`unsafe`);for(let n of[N(r,`shellbell`),e.runtimeDir]){if(!X(n)){if(!t)continue;try{m(n,{mode:448})}catch(e){if(e.code!==`EEXIST`)throw e}}if(Z(n,e.linuxHost.uid),!fp.has(Number(i(n))))throw new Y(`unsafe`)}X(e.runtimeDir)&&mp(e.runtimeDir,e.linuxHost.uid,0,i)}catch{throw Error(`shellbell: Shellbell can't use your login session's runtime folder (XDG_RUNTIME_DIR). Log in to this computer as yourself, directly or over SSH, rather than through sudo or su, and try again. The folder must be private to you (0700) and on local storage.`)}}function mp(e,t,n,r){if(n>2)throw new Y(`unsafe`);let i=v(e);if(i.length>256)throw new Y(`unsafe`);for(let a of i){let i=N(e,a),o=X(i);if(!o||o.uid!==t||o.isSymbolicLink())throw new Y(`unsafe`);if(o.isDirectory()){if(Z(i,t),!fp.has(Number(r(i))))throw new Y(`unsafe`);mp(i,t,n+1,r)}else if(!o.isFile()&&!o.isSocket()||(o.mode&4095)!=384)throw new Y(`unsafe`)}}function hp(e,t){if(j(t)!==j(e.runtimeDir))throw new Y(`unsafe`);Z(t,e.linuxHost.uid);let n=dp.get(e)?.fsType??(e=>C(e).type);if(!fp.has(Number(n(t))))throw new Y(`unsafe`);mp(t,e.linuxHost.uid,0,n)}function gp(e={}){let{uid:t,hostDigest:n,hostScope:r}=up(e),i=e.env??process.env,a=e.home??D(),o=i.SHELLBELL_DIR;if(o!==void 0&&!M(o))throw Error(`shellbell: SHELLBELL_DIR must be absolute`);let s=i.XDG_STATE_HOME&&M(i.XDG_STATE_HOME)?i.XDG_STATE_HOME:N(a,`.local`,`state`),c=sp(o??N(s,`shellbell`,`hosts`,r));X(c)&&Z(c,t);let l=i.XDG_RUNTIME_DIR??`/run/user/${t}`;if(!M(l))throw Error(`shellbell: XDG_RUNTIME_DIR must be absolute`);let u=N(P(l),`shellbell`,ae(`sha256`).update(c).digest(`hex`).slice(0,32)),d={dir:c,serviceOwner:N(c,`service-owner.json`),identity:N(c,`identity.json`),config:N(c,`config.json`),pairings:N(c,`pairings.json`),log:N(c,`agent.log`),runtimeDir:u,sock:N(u,`agent.sock`),pid:N(u,`agent.pid`),linuxHost:{uid:t,hostDigest:n,hostScope:r}};if(Buffer.byteLength(d.sock)>107)throw Error(`shellbell: Linux socket path exceeds 107 bytes; choose a shorter XDG_RUNTIME_DIR`);return dp.set(d,{root:P(l),fsType:e.runtimeFsType??(e=>C(e).type)}),pp(d,!1),d}function _p(e){pp(e,!0)}const vp=F.object({v:F.literal(1),relayUrl:F.string().url(),computerName:F.string().min(1).max(64),accent:F.string().min(1).max(32),notifyMinCommandMs:F.number().int().nonnegative().default(1e4),idleQuietMs:F.number().int().positive().default(4e3),idleMinActiveMs:F.number().int().nonnegative().default(1500),turn:F.boolean().optional(),showAgentConversations:F.boolean().optional(),terminalPlugins:F.array(F.string().min(1).max(4096).refine(e=>e.startsWith(`/`)&&e.endsWith(`.mjs`)&&[...e].every(e=>e.charCodeAt(0)>=32&&e.charCodeAt(0)!==127))).max(29).optional()}),yp=F.object({phoneFp:F.string().regex(/^[a-z2-7]{26}$/),name:F.string().min(1).max(64),platform:F.enum([`ios`,`android`]),ed25519Pub:F.string(),x25519Pub:F.string(),kPair:F.string(),minProtocolVersion:F.literal(2).optional(),pairedAt:F.string(),lastSeenAt:F.string().nullable()}),bp=F.object({v:F.literal(1),phones:F.array(yp)});function xp(e,t){if(!e||e.phoneFp!==t.phoneFp||e.kPair!==t.kPair)return t;if(e.ed25519Pub!==t.ed25519Pub||e.x25519Pub!==t.x25519Pub)throw Error(`shellbell: pairing identity changed without a new pairing key`);return e.minProtocolVersion===2?{...t,minProtocolVersion:2}:t}const Sp=F.object({v:F.literal(1),hostDigest:F.string().regex(/^[0-9a-f]{64}$/),installationId:F.string().uuid()}).strict();function Cp(e){try{let t=rc(JSON.parse(e.toString(`utf8`))),n=ec(t.ed25519.priv,t.x25519.priv,t.createdAt);if(!Buffer.from(n.ed25519.pub).equals(Buffer.from(t.ed25519.pub))||!Buffer.from(n.x25519.pub).equals(Buffer.from(t.x25519.pub)))throw Error();return{identity:t,fp:ic(t.ed25519.pub)}}catch{throw new Y(`invalid`)}}function wp(e){try{return vp.parse(JSON.parse(e.toString(`utf8`)))}catch{throw new Y(`invalid`)}}function Tp(e){try{let{phones:t}=bp.parse(JSON.parse(e.toString(`utf8`)));for(let e of t){let t=xr(e.ed25519Pub);if(t.length!==32||xr(e.x25519Pub).length!==32||xr(e.kPair).length!==32||ic(t)!==e.phoneFp)throw Error()}return t}catch{throw new Y(`invalid`)}}function Ep(e,t){let n=Z(e,t),r=lp(N(e,`identity.json`),65536,t),i=lp(N(e,`config.json`),65536,t),a=lp(N(e,`pairings.json`),1048576,t);if(Cp(r),wp(i),Tp(a),!op(n,Z(e,t)))throw new Y(`unsafe`);return{identity:r,config:i,pairings:a}}function Dp(e){try{if(!X(e.dir))return{status:`absent`};let t=Z(e.dir,e.linuxHost.uid);for(let t of v(e.dir)){let n=/^owner-[1-9][0-9]*-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,r=`owner-${t.slice(34)}`,i=t.startsWith(`service-owner.json.lock-candidate-`)&&n.test(r);if(t===`service-owner.json.lock`||i){let a=N(e.dir,t),o;try{o=Z(a,e.linuxHost.uid);let t=v(a),s=t[0];if(!(i&&t.length===0)){if(t.length!==1||!s||!n.test(s)||i&&s!==r)throw new Y(`unsafe`);lp(N(a,s),0,e.linuxHost.uid)}if(!op(o,Z(a,e.linuxHost.uid)))throw new Y(`unsafe`)}catch(t){let n=X(a);if(!n)continue;try{if(i&&o&&op(o,n)&&v(a).length===0&&op(n,Z(a,e.linuxHost.uid)))continue}catch(e){if(e instanceof Y&&e.kind===`missing`||e.code===`ENOENT`)continue;throw e}throw t}continue}let a=X(N(e.dir,t));if(a&&(!a.isFile()||a.isSymbolicLink()||a.uid!==e.linuxHost.uid||(a.mode&4095)!=384))throw new Y(`unsafe`)}let n=N(e.dir,`host.json`);if(!X(n))return{status:`unmarked`,reason:`Host marker missing; explicit host initialization or recovery required`};let r,i=lp(n,4096,e.linuxHost.uid);try{r=Sp.parse(JSON.parse(i.toString(`utf8`)))}catch{throw new Y(`invalid`)}if(r.hostDigest!==e.linuxHost.hostDigest)return{status:`wrong-host`,reason:`State belongs to a different host; choose this host's state directory`};let a=Ep(e.dir,e.linuxHost.uid);if(!i.equals(lp(n,4096,e.linuxHost.uid))||!op(t,Z(e.dir,e.linuxHost.uid)))throw new Y(`unsafe`);return{status:`ready`,bytes:a}}catch(e){return{status:e instanceof Y&&e.kind===`unsafe`?`unsafe`:`invalid`,reason:`Host state failed validation; inspect files and recover explicitly`}}}function Op(e){let t=Dp(e);return t.status===`ready`?{status:`ready`}:t}function kp(e,t){return t===`unmarked`||t===`wrong-host`?`Shellbell found a state folder at ${e} that this computer didn't create. It may have been copied from another computer, and two computers must never share one identity, so Shellbell won't use it. Move the folder aside to start fresh, or see the Linux guide to move Shellbell from another computer.`:`Shellbell's state folder at ${e} failed its safety checks. It must belong to you, must not be writable by anyone else, and should hold only Shellbell's files. Run \`shellbell doctor\` for details.`}function Ap(e,t=Op(e).status){return Error(t===`absent`?"shellbell: Shellbell isn't set up on this computer yet. Run `shellbell install`.":`shellbell: ${kp(e.dir,t)}`)}function jp(e){let t=Dp(e);if(!(`bytes`in t))throw Ap(e,t.status);return t.bytes}function Mp(e){let{status:t}=Op(e);if(t!==`ready`)throw Ap(e,t)}function Np(e){return Cp(jp(e).identity)}function Pp(e){return wp(jp(e).config)}function Fp(e){return Tp(jp(e).pairings)}const Ip=[`emerald`,`blue`,`amber`,`violet`,`rose`,`cyan`,`lime`,`orange`];function Lp(e=process.env.SHELLBELL_DIR??N(D(),`.shellbell`)){return{dir:e,serviceOwner:N(e,`service-owner.json`),identity:N(e,`identity.json`),pairings:N(e,`pairings.json`),config:N(e,`config.json`),log:N(e,`agent.log`),sock:N(e,`agent.sock`),pid:N(e,`agent.pid`)}}function Rp(e){if(e.linuxHost){Mp(e);return}m(e.dir,{recursive:!0,mode:448}),i(e.dir,448)}function zp(e,t,n){Up(e,t,t=>{n?.(),b(t,e)})}const Bp=new Set([`EPERM`,`ENOTSUP`,`EOPNOTSUPP`,`EXDEV`]);function Vp(e,t){try{return Up(e,t,n=>{try{f(n,e)}catch(n){if(!Bp.has(n.code??``))throw n;Hp(e,t)}ee(n)}),!0}catch(e){if(e.code===`EEXIST`)return!1;throw e}}function Hp(e,t){let n=h(e,`wx`,384),r=l(n),i=!1;try{c(n,384);let e=typeof t==`string`?Buffer.from(t):t,r=0;for(;r<e.byteLength;){let t=E(n,e,r,e.byteLength-r);if(t<=0)throw Error(`secret file write made no progress`);r+=t}u(n),i=!0}finally{if(a(n),!i)try{let t=p(e);t.dev===r.dev&&t.ino===r.ino&&ee(e)}catch{}}}function Up(e,t,n){let r=`${e}.tmp-${process.pid}`,o=null;try{let s;try{s=h(r,`wx`,384)}catch(t){if(t.code!==`EEXIST`)throw t;r=`${e}.tmp-${process.pid}-${ce()}`,s=h(r,`wx`,384)}try{let e=l(s);o={dev:e.dev,ino:e.ino};let n=typeof t==`string`?Buffer.from(t):t,r=0;for(;r<n.byteLength;){let e=E(s,n,r,n.byteLength-r);if(e<=0)throw Error(`atomic file write made no progress`);r+=e}u(s)}finally{a(s)}i(r,384),n(r)}catch(e){try{if(o){let e=p(r);e.dev===o.dev&&e.ino===o.ino&&ee(r)}}catch{}throw e}}function Wp(e){let t;try{t=g(e,`utf8`)}catch(t){throw Error(`shellbell: cannot read ${e}: ${t.message}`)}try{return JSON.parse(t)}catch{throw Error(`shellbell: ${e} is not valid JSON`)}}function Gp(){return{v:1,relayUrl:`wss://relay.shellbell.dev`,computerName:O().replace(/\.local$/,``)||`Mac`,accent:Ip[0],notifyMinCommandMs:1e4,idleQuietMs:3e4,idleMinActiveMs:1500}}function Kp(e){return Zp(e,()=>{if(em(e),e.linuxHost)return Pp(e);if(!X(e.dir))return Gp();let t=Z(e.dir,process.getuid());if(!X(e.config))return Gp();let n=lp(e.config,Yp,process.getuid());if(!op(t,Z(e.dir,process.getuid())))throw new Y(`unsafe`);let r;try{r=JSON.parse(n.toString(`utf8`))}catch{throw new Xp(`invalid`,e.config,`not valid JSON`)}return Qp(e,r)})}function qp(e){return e.linuxHost?Kp(e):nm(e,()=>{let t=Kp(e);return X(e.config)||rm(e,t),t})}function Jp(e,t){return nm(e,()=>t(Kp(e)))}const Yp=65536;var Xp=class extends Error{code;constructor(e,t,n=e){super(`shellbell: config ${n} at ${t}`),this.code=e,this.name=`ConfigEditError`}};function Zp(e,t){try{return t()}catch(t){throw t instanceof Xp?t:new Xp(t instanceof Y?t.kind===`invalid`?`invalid`:`unsafe`:`io`,e.config)}}function Qp(e,t){let n=vp.safeParse(t);if(!n.success)throw new Xp(`invalid`,e.config);return n.data}function $p(e){if(e.linuxHost){Mp(e);return}Z(e.dir,process.getuid())}function em(e){if([e.dir,e.config].some(e=>Buffer.byteLength(e)>4096||e.includes(`\0`))||j(P(e.config))!==P(e.dir))throw new Xp(`unsafe`,e.config)}function tm(e,t){let n=`${A(e)}.lock`;for(let r of v(j(e))){if(r!==n&&!r.startsWith(`${n}-candidate-`))continue;let i=N(j(e),r);if(X(i)){Z(i,t);for(let e of v(i)){let n=X(N(i,e));if(n&&(!n.isFile()||n.isSymbolicLink()||n.uid!==t||(n.mode&4095)!=384))throw new Y(`unsafe`)}}}}function nm(e,t){let n=Zp(e,()=>{if(em(e),!e.linuxHost&&!X(e.dir))try{m(e.dir,{recursive:!0,mode:448})}catch(e){if(e.code!==`EEXIST`)throw e}$p(e);let t=e.config;e.linuxHost&&(_p(e),t=N(e.runtimeDir,`config-${ae(`sha256`).update(e.config).digest(`hex`)}`)),tm(t,e.linuxHost?.uid??process.getuid());try{return ap(t)}catch(t){throw t instanceof Error&&t.message.startsWith(`Control endpoint busy`)?new Xp(`busy`,e.config):t instanceof Error&&t.message.startsWith(`Invalid control guard`)?new Xp(`unsafe`,e.config):t}}),r;try{r=t()}catch(e){try{n()}catch{}throw e}return Zp(e,n),r}function rm(e,t){Zp(e,()=>{let n=`${JSON.stringify(Qp(e,t),null,2)}\n`;if(Buffer.byteLength(n)>Yp)throw new Xp(`invalid`,e.config);zp(e.config,n,()=>{$p(e),Kp(e)})})}function im(e,t){return nm(e,()=>{let n=Qp(e,t(Kp(e)));return rm(e,n),n})}function am(e){if(e.linuxHost)return Fp(e);if(Rp(e),!s(e.pairings))return[];let t=bp.safeParse(Wp(e.pairings));if(!t.success)throw Error(`shellbell: invalid pairings at ${e.pairings}: ${F.prettifyError(t.error)}`);return t.data.phones}function om(e,t){Rp(e);let n=new Map(am(e).map(e=>[e.phoneFp,e])),r=t.map(e=>xp(n.get(e.phoneFp),e)),i=bp.parse({v:1,phones:r}),a=`${JSON.stringify(i,null,2)}\n`;if(e.linuxHost){if(Buffer.byteLength(a)>1048576)throw Error(`shellbell: Linux pairings exceed their state size limit`);Tp(Buffer.from(a))}return zp(e.pairings,a,e.linuxHost?()=>Mp(e):void 0),i.phones}const sm=new Set([`Error`,`TypeError`,`RangeError`,`ReferenceError`,`SyntaxError`,`URIError`,`EvalError`,`AggregateError`,`AbortError`,`TimeoutError`,`ProtocolError`,`BackendUnavailable`,`SessionGone`,`Unsupported`,`BadWindow`,`HerdrError`,`ITerm2AuthError`,`ConfigEditError`,`NativeControllerError`,`ControlV2ClientError`]);function cm(e){try{if(!(e instanceof Error))return`unknown`;let t=e.name;return typeof t==`string`&&sm.has(t)?t:`Error`}catch{return`unknown`}}function lm(e){return typeof e==`string`&&(sm.has(e)||e===`unknown`)}function um(e){let t=e=>lm(e?.err)?{err:e.err}:void 0,n={debug:()=>{},info:(n,r)=>e.info(n,t(r)),warn:(n,r)=>e.warn(n,t(r)),error:(n,r)=>e.error(n,t(r)),child:()=>n};return n}const dm=1048576;function fm(e){return e.isFile()&&e.uid===process.getuid?.()&&e.nlink===1}function pm(e,t){return e.dev===t.dev&&e.ino===t.ino}function mm(e,t){let n;try{let i;try{i=p(e)}catch(e){if(e.code!==`ENOENT`)return}if(i&&!fm(i))return;n=h(e,o.O_WRONLY|o.O_APPEND|o.O_NOFOLLOW|o.O_NONBLOCK|(i?0:o.O_CREAT|o.O_EXCL),384);let a=l(n),s=p(e);if(!fm(a)||!fm(s)||!pm(a,s)||i&&!pm(i,a))return;c(n,384),r(n,t)}catch{}finally{if(n!==void 0)try{a(n)}catch{}}}function hm(e){let t;try{let n=p(e);if(!fm(n)||n.size<dm)return;t=h(e,o.O_RDWR|o.O_NOFOLLOW|o.O_NONBLOCK);let r=l(t);if(!fm(r)||!pm(n,r)||r.size<dm)return;c(t,384);let i=Math.max(0,r.size-dm),a=Buffer.alloc(r.size-i);for(let e=0;e<a.length;){let n=_(t,a,e,a.length-e,i+e);if(n===0)return;e+=n}for(let t=4;t>=1;t--)s(`${e}.${t}`)&&b(`${e}.${t}`,`${e}.${t+1}`);zp(`${e}.1`,a);let u=p(e);fm(u)&&pm(u,r)&&fm(l(t))&&d(t,0)}catch{}finally{if(t!==void 0)try{a(t)}catch{}}}function gm(e,t={}){let n=e.stdout??process.stdout.isTTY===!0,r=(r,i,a)=>{if(r===`debug`&&!e.verbose)return;let o={t:new Date().toISOString(),level:r,msg:i,...t,...a};if(e.file){hm(e.file);try{mm(e.file,`${JSON.stringify(o)}\n`)}catch{}}if(n){let e=Object.keys({...t,...a}).length?` ${JSON.stringify({...t,...a})}`:``,n=`${o.t.slice(11,19)} ${r.padEnd(5)} ${i}${e}`;(r===`error`||r===`warn`?process.stderr:process.stdout).write(`${n}\n`)}};return{debug:(e,t)=>r(`debug`,e,t),info:(e,t)=>r(`info`,e,t),warn:(e,t)=>r(`warn`,e,t),error:(e,t)=>r(`error`,e,t),child:n=>gm(e,{...t,...n})}}function _m(e){if(!vm(e.reported)||!vm(e.before)||e.before>e.reported||!Number.isSafeInteger(e.count)||e.count<1||e.count>W.historyLines||e.capture===null||typeof e.capture!=`object`)throw RangeError(`invalid history read request`)}function vm(e){return Number.isSafeInteger(e)&&e>=0}var ym=class extends Error{hint;constructor(e,t){super(e),this.hint=t,this.name=`BackendUnavailable`}},bm=class extends Error{constructor(e){super(`session gone: ${e}`),this.name=`SessionGone`}},xm=class extends Error{code;constructor(e){super(`Terminal input ${e}`),this.code=e,this.name=`TerminalInputError`}},Sm=class extends Error{constructor(e){super(`unsupported: ${e}`),this.name=`Unsupported`}},Cm=class extends Error{constructor(e=`No terminal app on this computer can show a new session.`){super(e),this.name=`NotShownOnComputer`}},wm=class extends Error{constructor(e){super(`bad-window: ${e}`),this.name=`BadWindow`}};async function Tm(e,t){let n;try{return await Promise.race([Promise.resolve().then(e),new Promise((e,r)=>{n=setTimeout(()=>r(Error(`Terminal adapter deadline exceeded`)),t),n.unref()})])}finally{n&&clearTimeout(n)}}function Em(e,t){return`${e}:${t}`}const Dm=Zl.options,Om=new Set([`iterm2`]);function km(e){let t=e.indexOf(`:`);if(t<=0)return null;let n=Ql.safeParse(e.slice(0,t));return n.success?{name:n.data,native:e.slice(t+1)}:null}var Am=class{log;listTimeoutMs;conversationPermits=new Map;conversationSupported(e){let t=km(e),n=t?this.members.get(t.name):void 0;return!!n&&n.isConnected!==!1&&!!n.conversationReference}async conversationReference(e,t){let n=km(e);if(!n||t.aborted)return null;let r=this.members.get(n.name);if(!r||r.isConnected===!1||!r.conversationReference)return null;let i=this.conversationPermits.get(e);if(i?i.count>=12:this.conversationPermits.size>=20)return null;let a,o=new Promise(e=>{a=e}),s=i??{tail:Promise.resolve(),count:0},c=s.tail;s.tail=c.then(()=>o),s.count++,this.conversationPermits.set(e,s);let l=()=>{};try{if(i){let e=()=>{},n=new Promise(n=>{e=n,t.addEventListener(`abort`,e,{once:!0})});if(await Promise.race([c,n]),t.removeEventListener(`abort`,e),t.aborted)return null}let r=this.members.get(n.name);if(!r||r.isConnected===!1||!r.conversationReference)return null;let a=this.historyMembership.get(n.name),o=!0;l=this.on(t=>{(r.isConnected===!1||(t.type===`session-removed`||t.type===`conversation-changed`)&&t.sessionId===e)&&(o=!1)});let s=await r.conversationReference(n.native,t);return s&&o&&!t.aborted&&this.historyMembership.get(n.name)===a&&this.members.get(n.name)===r&&this.members.get(n.name)?.isConnected!==!1?s:null}catch{return null}finally{l(),a(),--s.count===0&&this.conversationPermits.get(e)===s&&this.conversationPermits.delete(e)}}notificationRevision=0;async notificationFacts(e){let t=km(e);if(!t)return;let n=this.members.get(t.name);if(!n||n.isConnected===!1)return;let r=this.notificationRevision,i=await n.notificationFacts?.(t.native);if(i&&i.sessionId===t.native&&this.members.get(t.name)===n&&r===this.notificationRevision&&this.connected().some(e=>e.name===t.name))return{...i,sessionId:e,revision:JSON.stringify([r,i.revision])}}members=new Map;labels=new Map;hostCommands=new Map;hostedLaunchers=new Map;hostedPending=0;sessionLaunchers=new Map;setupReporters=new Map;setupListeners=new Set;sessionStartups=new Map;startupWaiters=new Map;unsubs=new Map;historyMembership=new Map;historyPermits=new Map;inputCount=0;inputBytes=0;inputQueues=new Map;handlers=new Set;constructor(e,t=8e3){this.log=e,this.listTimeoutMs=t}orderedNames(){let e=new Set([...this.members.keys(),...this.sessionLaunchers.keys()]);for(let t of Dm)e.delete(t);return[...Dm,...[...e].sort()]}defaultLabel(e){let t=Zl.safeParse(e);return t.success?$l[t.data]:e}catalog(){return this.orderedNames().map(e=>{let t=this.memberConnected(e);return{name:e,label:this.labels.get(e)??this.defaultLabel(e),capabilities:this.members.get(e)?.capabilities??{subscribe:!1,prompts:!1,createSession:!1,focus:!1,history:!1,absoluteLines:!1},connected:t,launchable:!t&&(this.sessionLaunchers.get(e)?.available()??!1)}})}registerHostedLauncher(e,t){let n=uu.parse(e),r=`${n.backend}:${n.host}`;if(!this.hostedLaunchers.has(r)&&this.hostedLaunchers.size>=64)throw new ym(`Too many terminal launch targets`,`Disable a launch target first.`);let i={target:n,launcher:t};return this.hostedLaunchers.set(r,i),this.emit({type:`layout-changed`}),()=>{this.hostedLaunchers.get(r)===i&&(this.hostedLaunchers.delete(r),this.emit({type:`layout-changed`}))}}launchTargets(){return[...this.hostedLaunchers.values()].filter(({target:e,launcher:t})=>t.available()&&(this.memberConnected(e.backend)||this.sessionLaunchers.get(e.backend)?.available())).map(({target:e})=>({...e})).sort((e,t)=>`${e.backend}:${e.host}`.localeCompare(`${t.backend}:${t.host}`))}launchIssues(){let e=new Set(this.launchTargets().map(e=>e.backend)),t=new Map;for(let{target:n,launcher:r}of this.hostedLaunchers.values()){if(e.has(n.backend)||t.has(n.backend))continue;let i=r.unavailableReason?.();i&&t.set(n.backend,i)}return pu.parse([...t].map(([e,t])=>({backend:e,reason:t})))}preferredHost(e){return yu(e,this.launchTargets())?.host}async requireShownOnComputer(e,t){if(!Om.has(e.name)&&!(e.shownOnComputer&&await Tm(()=>e.shownOnComputer(t),5e3)))throw new Cm(`This session is not open in a terminal window on your computer, so it cannot be split or extended from the phone.`)}async createHostedSession(e,t=!1){let n=`${e.backend}:${e.host}`,r=this.hostedLaunchers.get(n);if(e.windowId!==void 0||!r?.launcher.available())throw new ym(`Terminal launch target is unavailable`,`Check the selected terminal app on your computer.`);if(this.hostedPending>=8)throw new ym(`Terminal startup is busy`,`Wait for the current startup to finish.`);this.hostedPending++;let i=(async()=>{if(this.hostedLaunchers.get(n)!==r)throw new bm(n);let i=this.members.get(e.backend),a;if(!i||i.isConnected===!1){let t=await this.startSession(e.backend,e.initialSize);i=t.backend,a=t.sessionId}if(this.hostedLaunchers.get(n)!==r||this.members.get(e.backend)!==i)throw new bm(n);let o=e.initialSize?await r.launcher.create(i,a,e.initialSize):t?await r.launcher.create(i,a,void 0,{tab:!0}):await r.launcher.create(i,a);if(this.hostedLaunchers.get(n)!==r||this.members.get(e.backend)!==i||i.isConnected===!1)throw new bm(n);return{sessionId:Em(e.backend,o.sessionId),opened:o.opened,openedIn:r.target.label}})().finally(()=>{this.hostedPending--});return Tm(()=>i,3e4)}get capabilities(){let e=[...this.members.values()].filter(e=>e.isConnected!==!1).map(e=>e.capabilities),t=t=>e.some(e=>e[t]);return{subscribe:t(`subscribe`),prompts:t(`prompts`),createSession:t(`createSession`)||[...this.sessionLaunchers.values()].some(e=>e.available()),focus:t(`focus`),history:t(`history`),absoluteLines:e.length>0&&e.every(e=>e.absoluteLines)}}add(e,t,n){let r=cu.parse({name:e.name,label:t??this.defaultLabel(e.name),capabilities:e.capabilities,connected:!1,launchable:!1});if(!this.orderedNames().includes(e.name)&&this.orderedNames().length>=32)throw new ym(`Too many terminal adapters`,`Disable an adapter before adding another.`);let i={},a=e.on(t=>{this.members.get(e.name)===e&&this.historyMembership.get(e.name)===i&&this.emit(Mm(e.name,t))});if(typeof a!=`function`)throw Error(`Terminal adapter subscription is invalid`);let o=this.unsubs.get(e.name);this.labels.set(e.name,r.label),this.hostCommands.set(e.name,n??(e.name===`tmux`||e.name===`herdr`?[e.name]:[])),this.members.set(e.name,e),this.historyMembership.set(e.name,i),this.unsubs.set(e.name,a);try{o?.()}catch(t){this.log.warn(`backend subscription cleanup failed`,{backend:e.name,err:cm(t)})}this.emit({type:`layout-changed`})}remove(e){let t=this.unsubs.get(e);this.unsubs.delete(e),this.members.delete(e),this.labels.delete(e),this.hostCommands.delete(e),this.historyMembership.delete(e);try{t?.()}catch(t){this.log.warn(`backend subscription cleanup failed`,{backend:e,err:cm(t)})}this.emit({type:`layout-changed`})}connected(){let e=[];for(let t of this.orderedNames()){let n=this.members.get(t);n&&n.isConnected!==!1&&e.push({name:n.name,capabilities:n.capabilities})}return e}registerSessionLauncher(e,t){if(Ql.parse(e),!this.orderedNames().includes(e)&&this.orderedNames().length>=32)throw new ym(`Too many terminal adapters`,`Disable an adapter before adding another.`);return this.sessionLaunchers.set(e,t),this.sessionStartups.delete(e),this.emit({type:`layout-changed`}),()=>{this.sessionLaunchers.get(e)===t&&(this.sessionLaunchers.delete(e),this.sessionStartups.delete(e),this.emit({type:`layout-changed`}))}}launchable(){return this.orderedNames().filter(e=>!this.memberConnected(e)&&this.sessionLaunchers.get(e)?.available())}async startSession(e,t){let n=this.sessionLaunchers.get(e);if(!n?.available())throw new bm(`backend ${e}`);let r=this.startupWaiters.get(e)??0;if(r>=8)throw new ym(`Terminal startup is busy`,`Try again after the current startup finishes.`);this.startupWaiters.set(e,r+1);try{let r=this.sessionStartups.get(e);if(!r){let i=Promise.resolve().then(()=>{if(this.sessionLaunchers.get(e)!==n)throw new bm(`backend ${e}`);return t?n.start(t):n.start()}).then(e=>({...e})).finally(()=>{this.sessionStartups.get(e)===i&&this.sessionStartups.delete(e)});r=i,this.sessionStartups.set(e,i)}let i=await r;if(this.sessionLaunchers.get(e)!==n||this.members.get(e)!==i.backend||i.backend.isConnected===!1)throw new bm(`backend ${e}`);let a=i.sessionId;return i.sessionId=void 0,{backend:i.backend,sessionId:a}}finally{let t=(this.startupWaiters.get(e)??1)-1;t===0?this.startupWaiters.delete(e):this.startupWaiters.set(e,t)}}member(e){return this.members.get(e)}registerSetupReporter(e,t){return this.setupReporters.set(e,t),()=>{this.setupReporters.get(e)===t&&this.setupReporters.delete(e)}}onSetupChanged(e){return this.setupListeners.add(e),()=>this.setupListeners.delete(e)}notifySetupChanged(){for(let e of this.setupListeners)try{e()}catch{}}terminalSetup(){return this.orderedNames().flatMap(e=>{let t=this.setupReporters.get(e),n=this.memberConnected(e);if(!t&&!this.members.has(e))return[];let r={};try{r=t?.(n)??{}}catch{r=n?{}:{issue:`failed`}}return[{name:e,connected:n,...r.issue?{issue:r.issue}:{},...r.issue&&r.detail?{detail:r.detail}:{}}]}).slice(0,16)}connectTerminal(e){let t=this.setupReporters.get(e)?.connect;if(!t)return!1;try{t().catch(e=>this.log.debug(`terminal connect failed`,{error:cm(e)}))}catch(e){this.log.debug(`terminal connect failed`,{error:cm(e)})}return!0}status(){return this.orderedNames().map(e=>({name:e,connected:this.memberConnected(e)}))}nameOf(e){return km(e)?.name??null}capabilitiesOf(e){let t=this.nameOf(e);return t?this.members.get(t)?.capabilities??null:null}async connect(){}async close(){let e=[...this.members.values()],t=[...this.unsubs.values()];this.sessionLaunchers.clear(),this.hostedLaunchers.clear(),this.sessionStartups.clear(),this.historyMembership.clear(),this.unsubs.clear(),this.members.clear(),this.labels.clear(),this.hostCommands.clear();for(let e of t)try{e()}catch(e){this.log.warn(`backend subscription cleanup failed`,{err:cm(e)})}await Promise.all(e.map(async e=>{try{await Tm(()=>e.close(),this.listTimeoutMs)}catch(t){this.log.warn(`backend close failed`,{backend:e.name,err:cm(t)})}}))}async listSessions(){let e=this.orderedNames().map(e=>({name:e,backend:this.members.get(e),membership:this.historyMembership.get(e)})),t=(await Promise.all(e.map(async e=>({...e,sessions:await this.safeListSessions(e.backend,e.name)})))).filter(({name:e,backend:t,membership:n})=>t&&this.members.get(e)===t&&this.historyMembership.get(e)===n),n=new Set;for(let{name:e,backend:r}of t)try{for(let e of r?.representedWindows?.()??[])n.add(JSON.stringify([e.backend,e.windowId]))}catch(t){this.log.warn(`terminal window relationships unavailable`,{backend:e,err:cm(t)})}let r=[];for(let{name:e,backend:i,sessions:a}of t)for(let o of a){try{let r=i?.nativeWindowIdOf?.(o.id);if(r&&n.has(JSON.stringify([e,r])))continue;let a=i?.hostedProcess?.(o.id);if(a&&t.some(t=>t.name!==e&&this.memberConnected(t.name)&&this.hostCommands.get(t.name)?.includes(a)))continue}catch(t){this.log.warn(`terminal host relationship unavailable`,{backend:e,err:cm(t)})}r.push(jm(e,o))}return r}projectFolder(e){let t=km(e),n=t?this.members.get(t.name):void 0;if(t&&n?.projectFolder)try{return n.projectFolder(t.native)}catch(e){this.log.warn(`session project folder unavailable`,{backend:t.name,err:cm(e)});return}}memberConnected(e){let t=this.members.get(e);return!!t&&t.isConnected!==!1}async safeListSessions(e,t){if(!e)return[];let n=this.historyMembership.get(t);try{let r=await Tm(()=>e.listSessions(),this.listTimeoutMs);return this.members.get(t)!==e||this.historyMembership.get(t)!==n?[]:r}catch(e){return this.log.warn(`listSessions failed for backend; returning the other backends' sessions`,{backend:t,err:cm(e)}),[]}}target(e){let t=km(e),n=t?this.members.get(t.name):void 0;if(!t||!n)throw new bm(e);return{backend:n,native:t.native}}async getScreen(e,t){let{backend:n,native:r}=this.target(e);return t===void 0?n.getScreen(r):n.getScreen(r,t)}async getHistory(e,t,n){let{backend:r,native:i}=this.target(e);return r.getHistory(i,t,n)}async getHistoryPage(e,t){let{backend:n,native:r}=this.target(e);if(_m(t),t.signal.aborted)return{status:`cancelled`};let i=n.getHistoryPage;if(!i)return{status:`unavailable`,reason:`unsupported`};if(this.historyPermits.has(e)||this.historyPermits.size>=10)return{status:`unavailable`,reason:`busy`};let a={};this.historyPermits.set(e,a);let o=this.historyMembership.get(n.name);try{let e=await i.call(n,r,t);return t.signal.aborted?{status:`cancelled`}:this.historyMembership.get(n.name)===o?e:{status:`reset`}}catch(e){if(t.signal.aborted)return{status:`cancelled`};if(this.historyMembership.get(n.name)!==o)return{status:`reset`};throw e}finally{this.historyPermits.get(e)===a&&this.historyPermits.delete(e)}}async sendText(e,t,n,r){let{backend:i,native:a}=this.target(e);return this.enqueueInput(e,i,t,()=>i.sendText(a,t),n,r)}async clickMouse(e,t,n){let{backend:r,native:i}=this.target(e);if(!r.capabilities.mouseClick||!r.clickMouse)throw new Sm(`mouse input`);return this.enqueueInput(e,r,``,()=>r.clickMouse(i,t),n)}async sendInput(e,t,n,r){let{backend:i,native:a}=this.target(e);if(!i.capabilities.terminalInput||!i.sendInput)throw new Sm(`terminal input`);return this.enqueueInput(e,i,t,()=>i.sendInput(a,t),n,r)}openVtStream(e){let{backend:t,native:n}=this.target(e);if(!t.capabilities.vtStream||!t.openVtStream)throw new Sm(`vt stream`);return t.openVtStream(n)}async paste(e,t,n,r,i){let{backend:a,native:o}=this.target(e);if(!a.capabilities.terminalPaste||!a.paste)throw new Sm(`terminal paste`);return this.enqueueInput(e,a,t,()=>a.paste(o,t,n),r,i)}enqueueInput(e,t,n,r,i,a){let o=Buffer.byteLength(n);if(this.inputCount>=256||this.inputBytes+o>1048576)return Promise.reject(new xm(`busy`));let s=this.inputQueues.get(e);if(s||(s={backend:t,membership:this.historyMembership.get(t.name),tail:Promise.resolve(),pending:0,valid:!0},this.inputQueues.set(e,s)),!s.valid||s.backend!==t)return Promise.reject(new xm(`cancelled`));let c=s;c.pending++,this.inputCount++,this.inputBytes+=o;let l=()=>this.members.get(t.name)===t&&t.isConnected!==!1&&this.historyMembership.get(t.name)===c.membership,u=()=>{if(!c.valid||i?.()===!1)throw new xm(`cancelled`);if(!l())throw new bm(e)},d=c.tail.then(async()=>{u(),a&&(await a(),u()),await r(),c.valid&&l()&&this.emit({type:`input-accepted`,sessionId:e})});return c.tail=d.catch(e=>{(!(e instanceof xm)||!Du.safeParse(e.code).success)&&(c.valid=!1)}),d.finally(()=>{this.inputCount--,this.inputBytes-=o,--c.pending===0&&this.inputQueues.get(e)===c&&this.inputQueues.delete(e)})}async createSession(e){let t=e=>({sessionId:e,opened:`tab`});if(e.kind===`split`){let{backend:t,native:n}=this.target(e.sessionId),r={kind:`split`,sessionId:n,direction:e.direction};return await this.requireShownOnComputer(t,r),{sessionId:Em(t.name,await t.createSession(r)),opened:`split`}}if(e.explicit===!0||e.initialSize!==void 0){let{near:t,explicit:n,...r}=e;return this.createWindow(r)}if(e.windowId!==void 0){let n=km(e.windowId);if(!n||n.name!==e.backend)throw new wm(e.windowId);let r=this.members.get(e.backend);if(!r||r.isConnected===!1)throw new bm(e.windowId);if(Om.has(e.backend))return t(Em(r.name,await r.createSession({kind:`tab`,backend:e.backend,windowId:n.native})));let i=await this.createTab(r,n.native,e.host);if(i===void 0)throw new Cm(`That window isn't open on your computer any more, so the tab couldn't open there. Open a new window instead.`);return i}if(e.near===`focused`){let n=this.members.get(e.backend);if(n&&n.isConnected!==!1&&n.focusedWindow){let r=await Tm(()=>n.focusedWindow(),5e3).catch(()=>void 0);if(r!==void 0){if(Om.has(e.backend))try{return t(Em(n.name,await n.createSession({kind:`tab`,backend:e.backend,windowId:r})))}catch(t){let i=await n.listSessions().catch(()=>null);if(!i||i.some(e=>e.windowId===r))throw t;this.log.warn(`focused window closed before its tab`,{backend:e.backend,err:cm(t)})}else{let t=await this.createTab(n,r,e.host);if(t!==void 0)return t}}}}let{near:n,explicit:r,...i}=e;return this.createWindow(i,n===`focused`)}async createTab(e,t,n){let r={kind:`tab`,backend:e.name,windowId:t},i=()=>e.shownOnComputer?Tm(()=>e.shownOnComputer(r),5e3):Promise.resolve(!1);if(!await i())return;let a=await e.createSession(r);if(await i().catch(()=>!1))return{sessionId:Em(e.name,a),opened:`tab`};try{if(!e.discardSession)throw Error(`no discard`);await e.discardSession(a)}catch(t){throw this.log.warn(`unshown tab not closed`,{backend:e.name,err:cm(t)}),new Cm(`The new tab didn't stay where your computer shows it, and it could not be closed. Check the session list.`)}return this.createWindow({kind:`tab`,backend:e.name,...n!==void 0&&{host:n}})}async createWindow(e,t=!1){if(e.host!==void 0)return this.createHostedSession(e,t);if(!Om.has(e.backend)){let n=this.preferredHost(e.backend);if(n===void 0)throw new Cm;return this.createHostedSession({kind:`tab`,backend:e.backend,host:n,...e.initialSize?{initialSize:e.initialSize}:{}},t)}let n=this.members.get(e.backend);if(!n||n.isConnected===!1){let t=await this.startSession(e.backend,e.initialSize);if(t.sessionId)return{sessionId:Em(e.backend,t.sessionId),opened:`window`};n=t.backend}let r=await n.createSession({kind:`tab`,backend:e.backend,windowId:void 0,...e.initialSize?{initialSize:e.initialSize}:{}});return{sessionId:Em(n.name,r),opened:`window`}}async focus(e){let{backend:t,native:n}=this.target(e);return t.focus(n)}setWatched(e){let t=new Map;for(let e of this.members.keys())t.set(e,[]);for(let n of e){let e=km(n);e&&t.get(e.name)?.push(e.native)}for(let[e,n]of t)try{this.members.get(e)?.setWatched?.(n)}catch(t){this.log.warn(`setWatched failed for backend`,{backend:e,err:cm(t)})}}setReported(e,t){let n=km(e);if(n)try{this.members.get(n.name)?.setReported?.(n.native,t)}catch(e){this.log.warn(`setReported failed for backend`,{backend:n.name,err:cm(e)})}}on(e){return this.handlers.add(e),()=>this.handlers.delete(e)}emit(e){if(e.type===`session-removed`){let t=this.inputQueues.get(e.sessionId);t&&(t.valid=!1)}for(let e of this.inputQueues.values())(e.backend.isConnected===!1||this.members.get(e.backend.name)!==e.backend)&&(e.valid=!1);[`layout-changed`,`session-added`,`session-removed`,`title-changed`].includes(e.type)&&this.notificationRevision++;for(let t of[...this.handlers])if(this.handlers.has(t))try{t(e)}catch(e){this.log.error(`backend event handler threw`,{err:cm(e)})}}};function jm(e,t){return{...t,id:Em(e,t.id),windowId:Em(e,t.windowId),tabId:Em(e,t.tabId),backend:e}}function Mm(e,t){return`sessionId`in t?{...t,sessionId:Em(e,t.sessionId)}:t}function Nm(e,t){let n;try{n=new URL(e)}catch{return`must be a valid URL, e.g. wss://relay.example.com`}return e.endsWith(`/`)||/[?#]/.test(e)||n.pathname!==`/`||n.username||n.password?`relay url must be scheme://host[:port] with no path, query or credentials`:e.length>256?`relay url is too long for a pairing code (at most 256 characters)`:n.protocol===`wss:`?null:n.protocol===`ws:`?t?null:`ws:// is insecure; pass --insecure or set SHELLBELL_ALLOW_INSECURE_RELAY=1 for LAN dev`:`relay url must use wss:// (ws:// only with --insecure, for LAN dev)`}function Pm(e,t,n,r){let i;if(t===`relay`){let t=Nm(n,r);if(t)return{error:t};i={...e,relayUrl:n}}else if(t===`name`)i={...e,computerName:n};else if(t===`accent`){if(!Ip.includes(n))return{error:`unknown accent ${n} (must be one of ${Ip.join(`, `)})`};i={...e,accent:n}}else if(t===`turn`){if(n!==`on`&&n!==`off`)return{error:`turn must be on or off`};let{turn:t,...r}=e;i=n===`off`?{...r,turn:!1}:r}else if(t===`conversations`){if(n!==`on`&&n!==`off`)return{error:`conversations must be on or off`};let{showAgentConversations:t,...r}=e;i=n===`off`?{...r,showAgentConversations:!1}:r}else if(Lm(t)){if(!/^\d+$/.test(n))return{error:`${t} must be a complete decimal integer`};let r=Number(n);if(!Number.isSafeInteger(r))return{error:`${t} must be a safe decimal integer`};i={...e,[t]:r}}else return{error:`unknown key ${t} (expected ${Rm()})`};let a=vp.safeParse(i);return a.success?{next:a.data}:{error:a.error.issues.map(e=>e.message).join(`; `)}}const Fm=[`notifyMinCommandMs`,`idleQuietMs`,`idleMinActiveMs`],Im=[`relay`,`name`,`accent`,...Fm,`turn`,`conversations`];function Lm(e){return Fm.includes(e)}function Rm(){return`${Im.slice(0,-1).join(`, `)}, or ${Im.at(-1)}`}function zm(e,t){switch(t){case`relay`:return e.relayUrl;case`name`:return e.computerName;case`accent`:return e.accent;case`turn`:return e.turn===!1?`off`:`on`;case`conversations`:return e.showAgentConversations===!1?`off`:`on`;default:return String(e[t])}}function Bm(e){let t=vp.parse(e);return ae(`sha256`).update(JSON.stringify({v:t.v,relayUrl:t.relayUrl,computerName:t.computerName,accent:t.accent,notifyMinCommandMs:t.notifyMinCommandMs,idleQuietMs:t.idleQuietMs,idleMinActiveMs:t.idleMinActiveMs,...t.terminalPlugins?.length?{terminalPlugins:t.terminalPlugins}:{},...t.turn===!1?{turn:!1}:{},...t.showAgentConversations===!1?{showAgentConversations:!1}:{}})).digest(`hex`)}const Vm={claude:{name:`Claude Code`,from:`2.1.286`,through:`2.1.310`},codex:{name:`Codex`,from:`0.164.0`,through:`0.166.0`},gemini:{name:`Gemini CLI`,from:`0.62.0`,through:`0.62.0`}},Hm=/^\d{1,6}(?:\.\d{1,6}){0,3}$/;function Um(e){return typeof e==`string`&&Hm.test(e)?e:null}function Wm(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<Math.max(n.length,r.length);e++){let t=(n[e]??0)-(r[e]??0);if(t)return Math.sign(t)}return 0}function Gm(e,t){if(!Object.hasOwn(Vm,e))return`tested`;let n=Vm[e];return Wm(t,n.through)>0?`newer`:Wm(t,n.from)<0?`older`:`tested`}const Km=new Map;function qm(){return[...Km.values()].map(e=>({...e}))}function Jm(e,t,n){if(Gm(e,t)!==`newer`)return;let r=`${e}@${t}`;if(Km.has(r)||Km.size>=16)return;let i=Vm[e].name;Km.set(r,{agent:e,name:i,version:t}),n(`agent-version-newer-than-tested`,{agent:e,version:t,tested:Vm[e].through})}const Ym=F.object({name:Ql,connected:F.boolean()}),Xm=F.array(Ym).max(32),Zm=F.object({pid:F.number().int().positive().max(2**53-1),agentVersion:F.string().min(1),computerFp:U,stateDir:F.string().min(1).refine(M,`state directory must be absolute`),serviceInstance:F.uuid().nullable()}),Qm=F.strictObject({agent:F.string().min(1).max(32),name:F.string().min(1).max(64),version:F.string().regex(Hm)}),$m=F.array(Qm).max(16),eh={controlVersion:F.literal(1),process:Zm,backends:Xm,terminalReady:F.boolean(),newerAgents:$m.optional()};function th(e,t){(e.backends.length<Dm.length||Dm.some((t,n)=>e.backends[n]?.name!==t)||new Set(e.backends.map(e=>e.name)).size!==e.backends.length||e.backends.slice(Dm.length).some((e,t,n)=>t>0&&e.name<n[t-1].name))&&t.addIssue({code:`custom`,path:[`backends`],message:`backend status must contain each known backend in protocol order`}),e.terminalReady!==e.backends.some(e=>e.connected)&&t.addIssue({code:`custom`,path:[`terminalReady`],message:`terminal readiness must match backend connectivity`})}const nh=F.string().min(1).max(64),rh=F.object({route:F.enum([`relay`,`direct`]).nullable(),ready:F.boolean(),phase:F.string().max(32),lastFailure:F.string().max(32).nullable(),relaySent:F.number().int().nonnegative(),relayReceived:F.number().int().nonnegative(),directSent:F.number().int().nonnegative(),directReceived:F.number().int().nonnegative()}),ih=F.object({...eh,relayOnline:F.boolean(),sessions:F.number().int().nonnegative().max(2**53-1),phones:F.array(F.object({phoneFp:U,name:nh,lastSeenAt:F.string().nullable()})).max(10),connected:F.array(F.object({phoneFp:U,name:nh,viewed:F.string().nullable(),transport:rh.optional()})).max(10)}).superRefine(th);function ah(e,t=process.env){if(!e)return null;let n=t.SHELLBELL_SERVICE_INSTANCE;if(n===void 0)return null;if(!F.uuid().safeParse(n).success)throw Error(`SHELLBELL_SERVICE_INSTANCE must be a valid UUID`);return n}function oh(e){try{return t.lstatSync(e)}catch(e){if(e.code===`ENOENT`)return;throw e}}function sh(e,t){return e?.dev===t.dev&&e.ino===t.ino}function ch(e){let t=process.platform===`darwin`?103:process.platform===`linux`?107:null;if(t===null)throw Error(`Unsupported control socket platform: ${process.platform}`);if(Buffer.byteLength(e)>t)throw Error(`Control socket path is too long (maximum ${t} bytes): ${e}`)}async function lh(e){return new Promise((t,n)=>{let r=le(e),i=setTimeout(()=>a(Error(`Control socket probe timed out: ${e}`)),1e3),a=(e,a=!1)=>{clearTimeout(i),r.destroy(),e?n(e):t(a)};r.once(`connect`,()=>a(void 0,!0)),r.once(`error`,e=>{e.code===`ENOENT`||e.code===`ECONNREFUSED`?a():a(e)})})}var uh=class{sockPath;onConnection;log;pidPath;admit;server;clients=new Set;ownedSocket;ownedPid;lifecycle=Promise.resolve();constructor(e,t,n,r,i){this.sockPath=e,this.onConnection=t,this.log=n,this.pidPath=r,this.admit=i}serialize(e){let t=this.lifecycle.then(e);return this.lifecycle=t.catch(()=>{}),t}start(){return this.serialize(async()=>{if(this.server)return;if(this.ownedSocket||this.ownedPid)throw Error(`Control endpoint cleanup pending; stop it before restarting`);ch(this.sockPath),ch(N(j(this.sockPath),`.s12345678`));let e=ap(this.sockPath);try{this.admit?.(),this.checkPid();let e=oh(this.sockPath);if(e){if(!e.isSocket())throw Error(`Control socket path is not a socket: ${this.sockPath}`);if(await lh(this.sockPath))throw Error(`Control endpoint already running: ${this.sockPath}`);if(!sh(oh(this.sockPath),e))throw Error(`Control socket changed during startup; retry`);t.unlinkSync(this.sockPath);for(let n of t.readdirSync(j(this.sockPath))){if(!/^\.s[A-Za-z0-9_-]{8}$/.test(n))continue;let r=N(j(this.sockPath),n);sh(oh(r),e)&&t.unlinkSync(r)}}let n=await this.bind();t.chmodSync(n,384);let r=t.lstatSync(n);if(t.linkSync(n,this.sockPath),this.ownedSocket=r,this.pidPath){this.checkPid();let e=String(process.pid);zp(this.pidPath,e),this.ownedPid={identity:t.lstatSync(this.pidPath),contents:e}}this.admit?.()}catch(e){try{this.removeOwned()}finally{await this.closeListener()}throw e}finally{e()}})}checkPid(){if(!this.pidPath)return;let e=oh(this.pidPath);if(!e)return;if(!e.isFile())throw Error(`PID path must be a regular file: ${this.pidPath}`);let n=tp(t.readFileSync(this.pidPath,`utf8`).trim());if(n===null)throw Error(`Invalid PID file; inspect ${this.pidPath} before retrying`);if(np(n))throw Error(`shellbell is already running (pid ${n})`)}async bind(){for(let e=0;e<8;e++){let e=N(j(this.sockPath),`.s${se(6).toString(`base64url`)}`),t=ue(e=>{this.clients.add(e),e.once(`close`,()=>this.clients.delete(e)),e.on(`error`,()=>{}),this.onConnection(e)});this.server=t;try{return await new Promise((n,r)=>{t.once(`error`,r);let i=process.umask(127);try{t.listen(e,()=>{t.removeListener(`error`,r),n()})}finally{process.umask(i)}}),e}catch(e){if(await this.closeListener(),e.code!==`EADDRINUSE`)throw e}}throw Error(`Control endpoint private socket names are in use after eight attempts`)}removeOwned(){if(this.ownedSocket&&=(sh(oh(this.sockPath),this.ownedSocket)&&t.unlinkSync(this.sockPath),void 0),this.pidPath&&this.ownedPid){let e=oh(this.pidPath);e?.isFile()&&sh(e,this.ownedPid.identity)&&t.readFileSync(this.pidPath,`utf8`)===this.ownedPid.contents&&t.unlinkSync(this.pidPath),this.ownedPid=void 0}}async closeListener(){for(let e of this.clients)e.destroy();this.clients.clear();let e=this.server;this.server=void 0,e&&await new Promise((t,n)=>e.close(e=>{e&&e.code!==`ERR_SERVER_NOT_RUNNING`?n(e):t()}))}stop(){return this.serialize(async()=>{let e;try{(this.ownedSocket||this.ownedPid)&&(e=ap(this.sockPath),this.removeOwned())}catch(e){throw this.log.warn(`Control endpoint cleanup failed; shared paths retained for retry`,{error:cm(e)}),e}finally{try{await this.closeListener()}finally{e?.()}}})}};const dh={lineBytes:65536,queuedBytes:262144,connections:16,initialRequestMs:5e3,requestMs:5e3,challengeMs:6e4};function fh(e){let t;try{t=JSON.stringify(e)}catch{return null}if(t===void 0)return null;let n=new TextEncoder().encode(`${t}\n`);return n.byteLength-1<=dh.lineBytes?n:null}function ph(e,t){let n=e.writableLength;if(e.destroyed||!Number.isFinite(n)||n<0||n+t.byteLength>dh.queuedBytes)return e.destroy(),!1;try{return e.write(t),!0}catch{return e.destroy(),!1}}var mh=class{onLine;onError;maxBytes;chunks=[];bytes=0;terminal=!1;constructor(e){this.onLine=e.onLine,this.onError=e.onError;let t=e.maxBytes??dh.lineBytes;this.maxBytes=Number.isFinite(t)?Math.max(0,Math.min(t,dh.lineBytes)):dh.lineBytes}push(e){if(this.terminal||e.byteLength===0)return;let t=0;for(;t<e.byteLength&&!this.terminal;){let n=e.indexOf(10,t),r=n===-1?e.byteLength:n,i=r-t;if(this.bytes+i>this.maxBytes){this.fail(`line-too-large`);return}if(i>0&&(this.chunks.push(Uint8Array.from(e.subarray(t,r))),this.bytes+=i),n===-1)return;let a=this.decodeLine();if(a===null)return;this.reset(),this.onLine(a),t=n+1}}finish(){this.terminal||(this.bytes>0?this.fail(`incomplete-line`):(this.terminal=!0,this.reset()))}decodeLine(){let e=new Uint8Array(this.bytes),t=0;for(let n of this.chunks)e.set(n,t),t+=n.byteLength;try{return new TextDecoder(`utf-8`,{fatal:!0,ignoreBOM:!0}).decode(e)}catch{return this.fail(`invalid-utf8`),null}}fail(e){this.terminal||(this.terminal=!0,this.reset(),this.onError(e))}reset(){this.chunks=[],this.bytes=0}};const hh=F.number().int().positive().max(2**53-1),gh=F.string().regex(/^[A-Za-z0-9_-]{22}$/),_h=F.string().min(1).max(64),vh=F.object({pid:hh,agentVersion:F.string().min(1),computerFp:U,stateDir:F.string().min(1).refine(M,`state directory must be absolute`),serviceInstance:F.uuid().nullable()}).strict(),yh=F.object({name:Ql,connected:F.boolean()}).strict(),bh=F.object({phoneFp:U,name:_h,lastSeenAt:F.string().nullable()}).strict(),xh=F.object({phoneFp:U,name:_h,viewed:F.string().nullable(),transport:rh.strict().optional()}).strict(),Sh=F.object({controlVersion:F.literal(1),process:vh,backends:F.array(yh),terminalReady:F.boolean(),relayOnline:F.boolean(),sessions:F.number().int().nonnegative().max(2**53-1),phones:F.array(bh).max(10),connected:F.array(xh).max(10),newerAgents:$m.optional()}).strict().superRefine((e,t)=>{ih.safeParse(e).success||t.addIssue({code:`custom`,message:`status must satisfy LocalStatus semantics`})}),Ch=F.object({}).strict(),wh=F.object({version:F.literal(2),runtime:vh,capabilities:F.tuple([F.literal(`status`),F.literal(`devices`),F.literal(`pairing`),F.literal(`revoke`)])}).strict(),Th=F.array(bh).max(10),Eh=F.object({removed:F.boolean()}).strict(),Dh=F.object({flowId:gh,qrText:F.string().min(1).refine(e=>new TextEncoder().encode(e).byteLength<=dh.lineBytes),expiresAt:hh}).strict(),Oh={hello:wh,status:Sh,"status.config":F.object({revision:F.string().regex(/^[0-9a-f]{64}$/)}).strict(),"settings.conversations.apply":F.object({revision:F.string().regex(/^[0-9a-f]{64}$/)}).strict(),devices:Th,"devices.revoke":Eh,"pairing.open":Dh,"pairing.close":Ch,"pairing.confirm":Ch,terminals:F.object({terminals:gu}).strict(),"terminals.connect":F.object({started:F.boolean(),terminals:gu}).strict()},kh={v:F.literal(2),id:hh},Ah={...kh,expect:vh},jh=F.discriminatedUnion(`cmd`,[F.object({...Ah,cmd:F.literal(`settings.conversations.apply`),args:F.object({revision:F.string().regex(/^[0-9a-f]{64}$/)}).strict()}).strict(),F.object({...kh,cmd:F.literal(`hello`)}).strict(),F.object({...kh,cmd:F.literal(`status`)}).strict(),F.object({...kh,cmd:F.literal(`status.config`)}).strict(),F.object({...kh,cmd:F.literal(`devices`)}).strict(),F.object({...kh,cmd:F.literal(`terminals`)}).strict(),F.object({...Ah,cmd:F.literal(`terminals.connect`),args:F.object({name:Ql}).strict()}).strict(),F.object({...Ah,cmd:F.literal(`devices.revoke`),args:F.object({phoneFp:U}).strict()}).strict(),F.object({...Ah,cmd:F.literal(`pairing.open`)}).strict(),F.object({...Ah,cmd:F.literal(`pairing.close`),args:F.object({flowId:gh}).strict()}).strict(),F.object({...Ah,cmd:F.literal(`pairing.confirm`),args:F.object({flowId:gh,challengeId:gh,phoneFp:U,accept:F.boolean()}).strict()}).strict()]),Mh=F.enum([`bad-request`,`unsupported-version`,`handshake-required`,`runtime-mismatch`,`configuration-mismatch`,`pairing-busy`,`stale-flow`,`stale-challenge`,`response-too-large`,`operation-failed`]),Nh=F.object({v:F.literal(2),id:hh,ok:F.literal(!0),data:F.unknown()}).strict().refine(e=>Object.hasOwn(e,`data`)),Ph=F.object({v:F.literal(2),id:hh,ok:F.literal(!1),error:F.object({code:Mh}).strict()}).strict(),Fh=F.union([Nh,Ph]),Ih=F.object({v:F.literal(2),event:F.literal(`pairing.request`),flowId:gh,challengeId:gh,phoneFp:U,name:_h}).strict(),Lh=F.object({v:F.literal(2),event:F.literal(`pairing.closed`),flowId:gh}).strict(),Rh=F.discriminatedUnion(`event`,[Ih,Lh]),zh=[`status`,`devices`,`pairing`,`revoke`];function Bh(e,t){return e.pid===t.pid&&e.agentVersion===t.agentVersion&&e.computerFp===t.computerFp&&e.stateDir===t.stateDir&&e.serviceInstance===t.serviceInstance}function Vh(e){if(!e||typeof e!=`object`)return;let t=e.id;return typeof t==`number`&&Number.isSafeInteger(t)&&t>0?t:void 0}var Hh=class{agent;log;peers=new Set;owner;stopped=!1;newId;constructor(e,t,n){this.agent=e,this.log=t,this.newId=n?.newId??(()=>se(16).toString(`base64url`))}get hasPairOwner(){return this.owner!==void 0}accept(e){let t=new Uh(this,e,this.agent);return this.stopped?t.close():this.peers.add(t),t}confirm(e,t){let n=this.owner;if(!n||n.resolve||this.stopped)return Promise.resolve(!1);let r=this.newId();return new Promise(i=>{if(this.owner!==n)return i(!1);n.resolve=i,n.challengeId=r,n.phoneFp=e,n.name=t,n.opening||this.emitRequest(n,t)})}activate(e,t){let n=this.owner;n&&n.peer===e&&n.flowId===t&&(n.opening=!1,n.resolve&&n.phoneFp&&n.challengeId&&this.emitRequest(n,n.name??``))}emitRequest(e,t){if(!e.resolve||!e.challengeId||!e.phoneFp)return;let n=e.resolve,r=Math.max(0,(e.expiresAt??Date.now())-Date.now());e.timer=setTimeout(()=>{this.owner===e&&e.resolve===n&&(e.resolve=void 0,e.challengeId=void 0,e.phoneFp=void 0,n(!1))},Math.min(dh.challengeMs,r)),e.timer.unref(),e.peer.event({v:2,event:`pairing.request`,flowId:e.flowId,challengeId:e.challengeId,phoneFp:e.phoneFp,name:t})||this.clearOwner(e,!1,!0)}notifyClosed(){let e=this.owner;e&&(this.clearOwner(e,!1,!1),e.peer.event({v:2,event:`pairing.closed`,flowId:e.flowId}))}stop(){this.stopped=!0;let e=this.owner;e&&this.clearOwner(e,!0,!1);for(let e of this.peers)e.close();this.peers.clear()}removed(e){this.peers.delete(e);let t=this.owner;t?.peer===e&&this.clearOwner(t,!0,!1)}open(e){if(this.owner||this.agent.pairingOpen)return`pairing-busy`;try{let t=this.newId(),n={peer:e,flowId:t,opening:!0};this.owner=n;let r=this.agent.openPairing();return this.owner!==n||!this.agent.pairingOpen?(this.clearOwner(n,!0,!1),`operation-failed`):(n.expiresAt=r.expiresAt,{flowId:t,...r})}catch{let t=this.owner;return t?.peer===e&&this.clearOwner(t,!0,!1),`operation-failed`}}close(e,t){let n=this.owner;if(!n||n.peer!==e||n.flowId!==t)return`stale-flow`;this.clearOwner(n,!0,!1)}answer(e,t){let n=this.owner;if(!n||n.peer!==e||n.flowId!==t.args.flowId)return`stale-flow`;if(n.expiresAt===void 0||Date.now()>=n.expiresAt)return this.clearOwner(n,!0,!0),`stale-flow`;if(!n.resolve||n.challengeId!==t.args.challengeId||n.phoneFp!==t.args.phoneFp)return`stale-challenge`;let r=n.resolve;n.timer&&clearTimeout(n.timer),n.timer=void 0,n.resolve=void 0,n.challengeId=void 0,n.phoneFp=void 0,n.name=void 0,r(t.args.accept)}clearOwner(e,t,n){if(this.owner!==e)return;this.owner=void 0;let r=e.resolve;if(e.timer&&clearTimeout(e.timer),e.timer=void 0,e.resolve=void 0,e.challengeId=void 0,e.phoneFp=void 0,e.name=void 0,r?.(!1),t)try{this.agent.closePairing()}catch{this.log.warn(`native pairing close failed`)}n&&e.peer.event({v:2,event:`pairing.closed`,flowId:e.flowId})}},Uh=class{hub;socket;agent;helloRuntime;lastId=0;closed=!1;constructor(e,t,n){this.hub=e,this.socket=t,this.agent=n}get handshaken(){return this.helloRuntime!==void 0}close(){this.closed||(this.closed=!0,this.hub.removed(this),this.socket.destroy())}handle(e){if(this.closed||this.socket.destroyed)return;let t=Vh(e);if(this.handshaken&&t!==void 0){if(t<=this.lastId){this.close();return}this.lastId=t}if(e&&typeof e==`object`&&e.v!==2){t!==void 0&&this.failure(t,`unsupported-version`),this.close();return}let n=jh.safeParse(e);if(!n.success){t===void 0?this.close():this.failure(t,`bad-request`);return}let r=n.data;if(!this.handshaken){if(r.id!==1||r.cmd!==`hello`){this.close();return}this.lastId=1,this.helloRuntime={...this.runtime()},this.success(r,{version:2,runtime:this.helloRuntime,capabilities:zh});return}if(r.cmd===`hello`){this.close();return}let i=this.helloRuntime,a=this.runtime();if(`expect`in r&&(!i||!Bh(r.expect,i)||!Bh(r.expect,a))){this.failure(r.id,`runtime-mismatch`);return}switch(r.cmd){case`status`:this.success(r,this.status());return;case`status.config`:this.success(r,{revision:this.agent.configurationRevision});return;case`settings.conversations.apply`:try{let e=this.agent.applyConversationSetting(r.args.revision);e===null?this.failure(r.id,`configuration-mismatch`):this.success(r,{revision:e})}catch{this.failure(r.id,`operation-failed`)}return;case`devices`:this.success(r,this.devices());return;case`devices.revoke`:try{this.success(r,{removed:this.agent.unpairExact(r.args.phoneFp)})}catch{this.failure(r.id,`operation-failed`)}return;case`terminals`:this.success(r,{terminals:this.agent.terminalSetup()});return;case`terminals.connect`:{let e=this.agent.connectTerminal(r.args.name);this.success(r,{started:e,terminals:this.agent.terminalSetup()});return}case`pairing.open`:{let e=this.hub.open(this);typeof e==`string`?this.failure(r.id,e):this.success(r,e)?this.hub.activate(this,e.flowId):this.hub.close(this,e.flowId);return}case`pairing.close`:{let e=this.hub.close(this,r.args.flowId);e?this.failure(r.id,e):this.success(r,{})&&this.event({v:2,event:`pairing.closed`,flowId:r.args.flowId});return}case`pairing.confirm`:{let e=this.hub.answer(this,r);e?this.failure(r.id,e):this.success(r,{});return}}}event(e){return Rh.safeParse(e).success?this.write(e):!1}runtime(){return this.agent.localStatus.process}status(){let e=this.agent;return{...e.localStatus,relayOnline:e.relayOnline,sessions:e.sessionList.length,phones:this.devices(),connected:e.connectedPhones}}devices(){return this.agent.pairingList.map(e=>({phoneFp:e.phoneFp,name:e.name,lastSeenAt:e.lastSeenAt}))}success(e,t){if(!Oh[e.cmd].safeParse(t).success)return this.failure(e.id,`operation-failed`),!1;let n={v:2,id:e.id,ok:!0,data:t};if(!Fh.safeParse(n).success)return this.failure(e.id,`operation-failed`),!1;let r=fh(n);return r?this.writeFrame(r):(this.failure(e.id,`response-too-large`),!1)}failure(e,t){let n={v:2,id:e,ok:!1,error:{code:t}};return Fh.safeParse(n).success?this.write(n):!1}write(e){let t=fh(e);return t?this.writeFrame(t):!1}writeFrame(e){return ph(this.socket,e)?!0:(this.close(),!1)}};const Wh={unavailable:`Local control unavailable`,"upgrade-required":`Local control upgrade required`,"protocol-error":`Local control protocol error`,timeout:`Local control timed out`,"delivery-unknown":`Local control mutation outcome unknown`,busy:`Local control request already pending`,closed:`Local control closed`,"server-error":`Local control server rejected request`},Gh=new Set([`hello`,`status`,`status.config`,`devices`,`terminals`]);var Q=class extends Error{code;serverCode;constructor(e,t){super(Wh[e]),this.code=e,this.serverCode=t,this.name=`ControlV2ClientError`}};function Kh(e,t={}){return new Promise((n,r)=>{let i;try{i=(t.connector??le)(e)}catch{r(new Q(`unavailable`));return}let a=!1,o=!1,s=!1,c=0,l,u,d,f=setTimeout(()=>p(new Q(`timeout`)),dh.requestMs);function p(e){if(a)return;a=!0,clearTimeout(f);let n=l;l=void 0,d=void 0,n&&(clearTimeout(n.timer),n.reject(n.mutation&&n.attempted?new Q(`delivery-unknown`):e)),o||r(e),i.destroy(),t.onDisconnect?.(e)}function m(e,t){if(a)return Promise.reject(new Q(`closed`));if(l)return Promise.reject(new Q(`busy`));if(c===2**53-1)return p(new Q(`protocol-error`)),Promise.reject(new Q(`protocol-error`));let n=!Gh.has(e),r=jh.safeParse({v:2,id:c+1,cmd:e,...n?{expect:u}:{},...t===void 0?{}:{args:t}});if(!r.success)return Promise.reject(new Q(`protocol-error`));let o=fh(r.data);if(o===null)return Promise.reject(new Q(`protocol-error`));let s=i.writableLength;return i.destroyed||!Number.isFinite(s)||s<0||s+o.byteLength>dh.queuedBytes?(p(new Q(`unavailable`)),Promise.reject(new Q(`unavailable`))):(c++,new Promise((t,r)=>{let a={id:c,command:e,mutation:n,attempted:!1,resolve:e=>t(e),reject:r,timer:setTimeout(()=>p(new Q(`timeout`)),dh.requestMs)};l=a,a.attempted=!0,ph(i,o)||p(new Q(`unavailable`))}))}let h=new mh({onError:()=>p(new Q(`protocol-error`)),onLine:e=>{if(a)return;let n;try{n=JSON.parse(e)}catch{p(new Q(`protocol-error`));return}if(typeof n==`object`&&n&&`event`in n){let e=Rh.safeParse(n);if(!e.success){p(new Q(`protocol-error`));return}let r=e.data;if(r.event===`pairing.closed`&&r.flowId!==d)return;if(r.flowId!==d){p(new Q(`protocol-error`));return}r.event===`pairing.closed`?(d=void 0,t.onPairingClosed?.(r)):t.onPairingRequest?.(r);return}let r=l;if(r?.command===`hello`&&typeof n==`object`&&n&&!(`v`in n)&&`ok`in n&&typeof n.ok==`boolean`){p(new Q(`upgrade-required`));return}let i=Fh.safeParse(n);if(!i.success||!r||i.data.id!==r.id){p(new Q(`protocol-error`));return}if(!i.data.ok){clearTimeout(r.timer),l=void 0;let e=new Q(`server-error`,i.data.error.code);r.reject(e),r.command===`hello`&&p(e);return}let o=Oh[r.command].safeParse(i.data.data);if(!o.success){p(new Q(`protocol-error`));return}r.command===`pairing.open`&&(d=o.data.flowId),clearTimeout(r.timer),l=void 0,r.resolve(o.data)}});i.on(`data`,e=>h.push(e)),i.on(`error`,()=>p(new Q(`unavailable`)));let g=()=>{h.finish(),p(new Q(`unavailable`))};i.once(`end`,g),i.once(`close`,g);let _=()=>{a||s||(s=!0,clearTimeout(f),m(`hello`).then(e=>{a||(u={...e.runtime},o=!0,n({runtime:{...e.runtime},status:()=>m(`status`),applyConversationSetting:async e=>{try{return(await m(`settings.conversations.apply`,{revision:e})).revision}catch(e){if(e instanceof Q&&e.code===`server-error`&&e.serverCode===`bad-request`)return null;throw e}},configurationRevision:async()=>{try{return(await m(`status.config`)).revision}catch(e){if(e instanceof Q&&e.code===`server-error`&&e.serverCode===`bad-request`)return null;throw e}},devices:()=>m(`devices`),terminals:async()=>{try{return(await m(`terminals`)).terminals}catch(e){if(qh(e))return null;throw e}},connectTerminal:async e=>{try{return await m(`terminals.connect`,{name:e})}catch(e){if(qh(e))return null;throw e}},revoke:e=>m(`devices.revoke`,{phoneFp:e}),openPairing:()=>m(`pairing.open`),closePairing:async e=>{await m(`pairing.close`,{flowId:e})},confirm:async(e,t,n,r)=>{await m(`pairing.confirm`,{flowId:e,challengeId:t,phoneFp:n,accept:r})},close:()=>p(new Q(`closed`))}))},e=>p(e)))};i.once(`connect`,_),i.connecting||_()})}function qh(e){return e instanceof Q&&e.code===`server-error`&&e.serverCode===`bad-request`}var Jh=class{agent;log;admission;pairingMode;endpoint;pending=new Map;pairClients=new Set;controlSockets=new Set;v2;pairingConfirm=(e,t)=>new Promise(n=>{if(this.pending.has(e)){this.log.warn(`pairing confirm requested twice for the same phone; declining the newer one`,{phone:e.slice(0,8)}),n(!1);return}let r=setTimeout(()=>{this.pending.delete(e),n(!1)},6e4);this.pending.set(e,t=>{clearTimeout(r),this.pending.delete(e),n(t)});for(let n of this.pairClients)this.writeLegacy(n,{event:`request`,phoneFp:e,name:t})||this.pairClients.delete(n)});constructor(e,t,n,r,i,a,o=`terminal`){this.agent=t,this.log=n,this.admission=a,this.pairingMode=o,this.endpoint=new uh(e,e=>this.handle(e),n,r,i),this.v2=new Hh(t,n)}get hasPairClients(){return this.pairClients.size>0}get hasNativePairOwner(){return this.v2.hasPairOwner}nativePairingConfirm=(e,t)=>this.v2.confirm(e,t);notifyClosed(e=`closed`){for(let e of this.pending.values())e(!1);this.pending.clear();for(let t of this.pairClients)this.writeLegacy(t,{event:`closed`,reason:e})||this.pairClients.delete(t);this.pairClients.clear(),this.v2.notifyClosed()}async start(){this.admission?await this.admission(()=>this.endpoint.start()):await this.endpoint.start()}async stop(){for(let e of this.pending.values())e(!1);for(let e of this.controlSockets)e.destroy();this.controlSockets.clear();for(let e of this.pairClients)e.destroy();this.pairClients.clear(),this.v2.stop(),await this.endpoint.stop()}handle(e){if(this.controlSockets.size>=dh.connections){e.destroy();return}this.controlSockets.add(e);let t=!0,n,r,i=setTimeout(()=>e.destroy(),dh.initialRequestMs),a=new mh({onLine:a=>{if(e.destroyed)return;let o;try{o=JSON.parse(a)}catch{if(n===`v2`){e.destroy();return}this.writeLegacy(e,{ok:!1,error:`bad json`});return}if(n===`v2`){r?.handle(o),t&&r?.handshaken&&(t=!1,clearTimeout(i));return}if(n===void 0&&o&&typeof o==`object`&&Object.hasOwn(o,`v`)){n=`v2`,r=this.v2.accept(e),r.handle(o),r.handshaken&&(t=!1,clearTimeout(i));return}if(n===`legacy`&&o&&typeof o==`object`&&Object.hasOwn(o,`v`)){e.destroy();return}n=`legacy`;let s=o;if(!s||typeof s!=`object`||typeof s.cmd!=`string`){this.writeLegacy(e,{ok:!1,error:`bad request`});return}t&&(t=!1,clearTimeout(i));try{let t=this.dispatch(s,e);this.writeLegacy(e,{ok:!0,data:t})}catch(t){this.writeLegacy(e,{ok:!1,error:t.message})}},onError:()=>e.destroy()});e.on(`data`,e=>a.push(new Uint8Array(e))),e.once(`end`,()=>a.finish()),e.once(`close`,()=>{clearTimeout(i),this.controlSockets.delete(e),this.pairClients.delete(e),r?.close()}),e.on(`error`,()=>this.log.debug(`control socket error`))}writeLegacy(e,t){let n=fh(t);if(n&&ph(e,n))return!0;let r=fh({ok:!1,error:`response too large`});return r!==null&&ph(e,r)}dispatch(e,t){let n=this.agent;if(this.pairingMode===`native`&&[`pair-open`,`pair-close`,`confirm`].includes(e.cmd))throw Error(`pairing is managed by the Shellbell app`);if(this.v2.hasPairOwner&&[`pair-open`,`pair-close`,`confirm`].includes(e.cmd))throw Error(`native pairing active`);switch(e.cmd){case`status`:return{...n.localStatus,relayOnline:n.relayOnline,sessions:n.sessionList.length,phones:n.pairingList.map(e=>({phoneFp:e.phoneFp,name:e.name,lastSeenAt:e.lastSeenAt})),connected:n.connectedPhones};case`devices`:return n.pairingList.map(e=>({phoneFp:e.phoneFp,name:e.name,lastSeenAt:e.lastSeenAt}));case`unpair`:return{removed:n.unpair(String(e.args?.target??``))};case`pair-open`:{let e=n.openPairing();return this.pairClients.add(t),e}case`pair-close`:return n.closePairing(),{};case`confirm`:{let t=String(e.args?.phoneFp??``),n=this.pending.get(t);if(!n)throw Error(`no pending request`);return n(!!e.args?.accept),{}}default:throw Error(`unknown command: ${e.cmd}`)}}};function Yh(e,t,n,r){return new Promise((i,a)=>{let o=fh({cmd:t,args:n});if(!o){a(Error(`control socket request too large`));return}let s=!1,c=le(e),l=r?.timeoutMs??5e3,u=e=>{s||(s=!0,clearTimeout(d),c.destroy(),e())},d=setTimeout(()=>u(()=>a(Error(`control socket timed out`))),l),f=new mh({maxBytes:r?.maxResponseBytes,onError:e=>u(()=>a(Error(e===`line-too-large`?`control socket response too large`:`control socket sent a malformed response`))),onLine:e=>{f.finish(),u(()=>{let t;try{if(t=JSON.parse(e),typeof t!=`object`||!t||typeof t.ok!=`boolean`)throw Error()}catch{a(Error(`control socket sent a malformed response`));return}t.ok?i(t.data):a(Error(t.error??`control error`))})}});c.on(`error`,e=>u(()=>a(e))),c.once(`connect`,()=>{ph(c,o)||u(()=>a(Error(`control socket write failed`)))}),c.once(`close`,()=>u(()=>a(Error(`control socket closed without a response`)))),c.once(`end`,()=>u(()=>a(Error(`control socket closed without a response`)))),c.on(`data`,e=>{s||f.push(new Uint8Array(e))}),c.once(`end`,()=>f.finish())})}function Xh(e,t){let n=le(e),r=!1,i,a=()=>{r||(r=!0,i?.finish(),n.end())};n.on(`error`,t.onError);let o=fh({cmd:`pair-open`});return n.once(`connect`,()=>{(o===null||!ph(n,o))&&t.onError(Error(`control socket write failed`))}),i=new mh({onError:()=>{n.destroy(),t.onError(Error(`control socket sent a malformed message`))},onLine:e=>{if(r)return;let i;try{i=JSON.parse(e)}catch{t.onError(Error(`control socket sent a malformed message`));return}i.event===`request`&&i.phoneFp?t.onRequest(i.phoneFp,i.name??``).then(e=>{if(r)return;let t=fh({cmd:`confirm`,args:{phoneFp:i.phoneFp,accept:e}});if(t===null||!ph(n,t))throw Error(`control socket write failed`)}).catch(e=>t.onError(e)):i.event===`closed`?t.onClose(i.reason===`replaced`||i.reason===`paired`?i.reason:`closed`):i.ok&&i.data?.qrText?t.onOpen(i.data.qrText,i.data.expiresAt):i.ok===!1&&t.onError(Error(i.error??`control error`))}}),n.on(`data`,e=>i.push(new Uint8Array(e))),n.once(`end`,()=>{r=!0,i?.finish()}),n.once(`close`,()=>{r=!0,i?.finish()}),{close:a}}function Zh(e){if(e.linuxHost)return Np(e);let t;try{t=g(e.identity,`utf8`)}catch(t){if(t.code===`ENOENT`)return null;throw Error(`shellbell: cannot read identity at ${e.identity}`)}try{let e=rc(JSON.parse(t));return{identity:e,fp:ic(e.ed25519.pub)}}catch{throw Error(`shellbell: invalid identity at ${e.identity}`)}}function Qh(e){if(e.linuxHost)return Np(e);Rp(e);let t;return s(e.identity)?t=$h(e):(t=$s(),Vp(e.identity,`${JSON.stringify(nc(t),null,2)}\n`)||(t=$h(e))),{identity:t,fp:ic(t.ed25519.pub)}}function $h(e){try{return rc(Wp(e.identity))}catch(t){throw Error(`shellbell: invalid identity at ${e.identity}: ${t.message}`)}}const eg=[`dev.bilalahmad.shellbell`,`dev.bilalahmad.shellbell.host.agent`,`dev.bilalahmad.shellbell.host.manual`];async function tg(e,t,n){if(!Number.isSafeInteger(t)||t<0)throw Error(`Invalid service UID`);let r=()=>Error(`Legacy Shellbell installation requires migration before starting the new service; preserve identity and remove old registrations explicitly.`);if(n)for(let e of eg){try{p(N(n,`Library`,`LaunchAgents`,`${e}.plist`))}catch(e){if(e.code===`ENOENT`)continue;throw e}throw r()}for(let n of[...eg.map(e=>`gui/${t}/${e}`),`system/dev.bilalahmad.shellbell.power`]){let t=await e(`/bin/launchctl`,[`print`,n],{timeoutMs:5e3,maxOutputBytes:65536,captureOutput:!1});if(t.exitCode===0)throw r();if(t.exitCode!==113)throw Error(`Could not verify legacy Shellbell registration absence`)}}const ng=(t,n,r)=>new Promise((i,a)=>{let o=e(t,n,{shell:!1,stdio:[`pipe`,`pipe`,`pipe`]}),s=0,c=0,l=[],u=!1,d=e=>{u||(u=!0,clearTimeout(f),o.kill(),a(e))},f=setTimeout(()=>d(Error(`${t} timed out`)),r.timeoutMs);o.stdout.on(`data`,e=>{if(s+=e.length,s>r.maxOutputBytes)return d(Error(`${t} output limit exceeded`));r.captureOutput&&l.push(e)}),o.stderr.on(`data`,e=>{c+=e.length,c>r.maxOutputBytes&&d(Error(`${t} output limit exceeded`))}),o.on(`error`,d),o.on(`close`,(e,n)=>{if(!u){if(u=!0,clearTimeout(f),n||e===null)return a(Error(`${t} terminated by signal`));i({exitCode:e,stdout:r.captureOutput?Buffer.concat(l):Buffer.alloc(0)})}}),o.stdin.on(`error`,d),o.stdin.end(r.input)}),rg=[`/opt/homebrew/bin`,`/usr/local/bin`,`/usr/bin`,`/bin`],ig=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function ag(e){for(let t of e){let e=t.codePointAt(0);if(!(e===9||e===10||e===13||e>=32&&e<=55295||e>=57344&&e<=65533||e>=65536&&e<=1114111))throw Error(`invalid XML character in service definition`)}}function og(e,t){if(!e||!M(e))throw Error(`${t} must be an absolute path`);return ag(e),e}function sg(e){if(og(e.stateDir,`stateDir`),og(e.nodePath,`nodePath`),!ig.test(e.serviceInstance))throw Error(`serviceInstance must be a UUID`);let t=[j(e.nodePath),...e.env.PATH?.split(`:`)??[],...rg].filter(e=>e.length>0&&M(e)),n={SHELLBELL_DIR:e.stateDir,SHELLBELL_SERVICE_INSTANCE:e.serviceInstance,PATH:[...new Set(t)].join(`:`)};for(let t of[`HERDR_SOCKET_PATH`,`XDG_CONFIG_HOME`]){let r=e.env[t];r&&(n[t]=og(r,t))}for(let e of Object.values(n))ag(e);return n}const cg=`sh.bilal.shellbell`;N(D(),`Library`,`LaunchAgents`,`${cg}.plist`);const lg=1048576,ug=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,dg=new Set([`SHELLBELL_DIR`,`SHELLBELL_SERVICE_INSTANCE`,`PATH`,`HERDR_SOCKET_PATH`,`XDG_CONFIG_HOME`]),fg=new Set([`Label`,`ProgramArguments`,`EnvironmentVariables`,`RunAtLoad`,`KeepAlive`,`StandardOutPath`,`StandardErrorPath`]);function pg(e){return ag(e),e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&apos;`)}function mg(e){let t=pg,n=e.environment??{PATH:`/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin`},r=Object.entries(n).map(([e,n])=>`<key>${t(e)}</key><string>${t(n)}</string>`).join(``);return`<?xml version="1.0" encoding="UTF-8"?>
17
17
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
18
18
  <plist version="1.0"><dict>
19
- <key>Label</key><string>${sg}</string>
19
+ <key>Label</key><string>${cg}</string>
20
20
  <key>ProgramArguments</key><array>
21
21
  <string>${t(e.nodePath)}</string><string>${t(e.cliPath)}</string><string>start</string><string>--service</string>
22
22
  </array>
@@ -26,4 +26,4 @@ const Os=BigInt(0),ks=BigInt(1),As=BigInt(2),js=BigInt(3),Ms=BigInt(5),Ns=BigInt
26
26
  <key>StandardOutPath</key><string>${t(e.logPath)}</string>
27
27
  <key>StandardErrorPath</key><string>${t(e.logPath)}</string>
28
28
  </dict></plist>
29
- `}function mg(e,t){if(typeof e!=`string`||!e||!M(e))throw Error(`invalid service definition: ${t} must be an absolute path`);return fg(e),e}function hg(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`invalid service definition`);let n=e;for(let e of Object.keys(n))if(!dg.has(e))throw Error(`unrecognized service definition key: ${e}`);if(n.Label!==`sh.bilal.shellbell`||!Array.isArray(n.ProgramArguments)||n.ProgramArguments.length!==4||n.ProgramArguments[2]!==`start`||n.ProgramArguments[3]!==`--service`||n.RunAtLoad!==!0||n.KeepAlive!==!0||n.StandardOutPath!==n.StandardErrorPath)throw Error(`unrecognized Shellbell service definition`);let r=n.EnvironmentVariables;if(!r||typeof r!=`object`||Array.isArray(r))throw Error(`invalid service environment`);let i=r;for(let[e,t]of Object.entries(i)){if(!ug.has(e))throw Error(`unrecognized service environment: ${e}`);if(typeof t!=`string`)throw Error(`invalid service environment: ${e}`);fg(e),fg(t),(e===`HERDR_SOCKET_PATH`||e===`XDG_CONFIG_HOME`)&&mg(t,e)}if(typeof i.PATH!=`string`||!i.PATH||i.PATH.split(`:`).some(e=>!e||!M(e)))throw Error(`invalid service PATH`);let a=i.SHELLBELL_DIR===void 0?N(t,`.shellbell`):mg(i.SHELLBELL_DIR,`SHELLBELL_DIR`),o=i.SHELLBELL_SERVICE_INSTANCE;if(o!==void 0&&(typeof o!=`string`||!lg.test(o)))throw Error(`invalid service instance`);return{nodePath:mg(n.ProgramArguments[0],`nodePath`),cliPath:mg(n.ProgramArguments[1],`cliPath`),stateDir:a,serviceInstance:o??null,environment:i,logPath:mg(n.StandardOutPath,`logPath`)}}function gg(e){if(mg(e.nodePath,`nodePath`),mg(e.cliPath,`cliPath`),mg(e.stateDir,`stateDir`),mg(e.logPath,`logPath`),!e.serviceInstance||!lg.test(e.serviceInstance))throw Error(`serviceInstance must be a UUID`);let t=e.environment;if(t.SHELLBELL_DIR!==e.stateDir||t.SHELLBELL_SERVICE_INSTANCE!==e.serviceInstance)throw Error(`service definition and environment disagree`);if(!t.PATH||t.PATH.split(`:`).some(e=>!e||!M(e)))throw Error(`invalid service PATH`);for(let[e,n]of Object.entries(t)){if(!ug.has(e))throw Error(`unsupported service environment: ${e}`);if(typeof n!=`string`)throw Error(`invalid service environment: ${e}`);fg(e),fg(n),(e===`HERDR_SOCKET_PATH`||e===`XDG_CONFIG_HOME`)&&mg(n,e)}}function _g(e={}){let t=e.run??tg,n=e.uid??te().uid;if(!Number.isSafeInteger(n)||n<0)throw Error(`invalid service UID`);let r=e.homeDir??D(),i=e.definitionPath??N(r,`Library`,`LaunchAgents`,`sh.bilal.shellbell.plist`),a=`gui/${n}`,o=`${a}/${sg}`,s;function c(e,t){return e===null||t===null?e===t:e.stat.dev===t.stat.dev&&e.stat.ino===t.stat.ino&&e.stat.uid===t.stat.uid&&e.stat.mode===t.stat.mode&&e.stat.size===t.stat.size&&e.stat.mtimeMs===t.stat.mtimeMs&&e.stat.ctimeMs===t.stat.ctimeMs&&e.raw.equals(t.raw)}function l(){let e;try{e=p(i)}catch(e){if(e.code===`ENOENT`)return null;throw e}return!e.isFile()||e.isSymbolicLink()||e.uid!==n||e.mode&18||e.size>cg?{stat:e,raw:Buffer.alloc(0)}:{stat:e,raw:g(i)}}function u(e){if(!c(e,l()))throw Error(`service definition changed or was replaced during operation`)}function d(e){let t=l();if(!t?.raw.equals(e))throw Error(`service definition changed after publication`);s=t}async function f(e,n,r=!1,i){let a=await t(e,n,{input:i,timeoutMs:5e3,maxOutputBytes:e===`/usr/bin/plutil`?cg:65536,captureOutput:r});if(!Number.isInteger(a.exitCode))throw Error(`${e} returned invalid exit status`);return a}async function h(e){let t=await f(`/usr/bin/plutil`,[`-convert`,`json`,`-o`,`-`,`-`],!0,e);if(t.exitCode!==0)throw Error(`plutil could not parse service definition`);let n;try{n=JSON.parse(t.stdout.toString(`utf8`))}catch{throw Error(`plutil returned invalid service definition JSON`)}return hg(n,r)}async function _(){let e;try{e=p(i)}catch(e){if(e.code===`ENOENT`)return null;throw e}if(!e.isFile()||e.isSymbolicLink()||e.uid!==n||e.mode&18||e.size>cg)throw Error(`unsafe service definition metadata`);let t=g(i);if(t.length>cg)throw Error(`service definition too large`);let r=await h(t),a={stat:e,raw:t};return u(a),{...a,definition:r}}async function v(){let e=await f(`/bin/launchctl`,[`print`,o]);if(e.exitCode===0)return!0;if(e.exitCode===113)return!1;throw Error(`launchctl print failed (${e.exitCode})`)}async function y(){try{let e=await f(`/bin/launchctl`,[`print-disabled`,a],!0),t=new TextDecoder(`utf-8`,{fatal:!0}).decode(e.stdout).trim().split(/\r?\n/).map(e=>e.trim());if(e.exitCode!==0||t.shift()!==`disabled services = {`||t.pop()!==`}`)return null;let n=t.filter(e=>e.includes(`"${sg}"`));return n.length===0?!0:n.length===1?n[0]===`"sh.bilal.shellbell" => disabled`||n[0]===`"sh.bilal.shellbell" => true`?!1:n[0]===`"sh.bilal.shellbell" => enabled`||n[0]===`"sh.bilal.shellbell" => false`||null:null}catch{return null}}let b={kind:`launchd`,definitionPath:i,async inspect(){let e=await _(),t=await v();if(u(e),!e&&t)throw Error(`loaded Shellbell job has no valid installed definition`);if(s!==void 0&&!c(s,e))throw Error(`service definition changed or was replaced after inspection`);return s===void 0&&(s=e),{installed:!!e,startupEnabled:e?await y():!1,loaded:t,raw:e?.raw??null,definition:e?.definition??null}},async setStartupEnabled(e){let t=await b.inspect();if(!t.installed)throw Error(`service is not installed`);if(t.startupEnabled!==e){if((await f(`/bin/launchctl`,[e?`enable`:`disable`,o])).exitCode!==0)throw Error(`launchctl startup preference change failed`);if((await b.inspect()).startupEnabled!==e)throw Error(`launchctl startup preference could not be verified`)}},async write(e){await eg(t,n,r),gg(e);let a=await _();if(s!==void 0&&!c(s,a))throw Error(`service definition changed or was replaced after inspection`);if(!a&&await v())throw Error(`loaded Shellbell job has no installed definition`);let o=pg({...e});m(j(i),{recursive:!0,mode:448}),zp(i,o,()=>u(a)),d(Buffer.from(o))},async restore(e){if(e!==null&&e.length>cg)throw Error(`service definition too large`);let a=await _();if(s!==void 0&&!c(s,a))throw Error(`service definition changed or was replaced after inspection`);if(e===null){if(!a)return;if(s===void 0)throw Error(`refusing to remove unexpected service definition replacement`);u(a),w(i),s=null;return}if(s===void 0)throw Error(`service definition changed unexpectedly`);if(await h(e),a)zp(i,e,()=>u(a));else if(await eg(t,n,r),m(j(i),{recursive:!0,mode:448}),!Vp(i,e))throw Error(`service definition changed or was replaced after inspection`);d(e)},async load(){await eg(t,n,r);let e=await b.inspect();if(!e.installed)throw Error(`service definition is not installed`);if(e.startupEnabled===null)throw Error(`service startup preference is unresolved`);let s=e.startupEnabled===!1;try{if(s&&await b.setStartupEnabled(!0),!e.loaded){let e=await f(`/bin/launchctl`,[`bootstrap`,a,i]);if(e.exitCode!==0)throw Error(`launchctl bootstrap failed (${e.exitCode})`)}let t=await f(`/bin/launchctl`,[`kickstart`,`-p`,o],!0);if(t.exitCode!==0)throw Error(`launchctl kickstart failed (${t.exitCode})`);let n=t.stdout.toString(`utf8`).trim();if(!/^[1-9][0-9]*$/.test(n))throw Error(`invalid launchctl PID output`);let r=Number(n);if(!Number.isSafeInteger(r)||r>2147483647)throw Error(`invalid launchctl PID output`);return r}finally{s&&await b.setStartupEnabled(!1)}},async unload(){if(!(await b.inspect()).loaded)return;let e=await f(`/bin/launchctl`,[`bootout`,o]);if(e.exitCode!==0)throw Error(`launchctl bootout failed (${e.exitCode})`);if(await v())throw Error(`launchctl bootout did not unload service`)}};return b}function vg(e){s(e)?i(e,384):T(e,``,{mode:384})}const yg=F.string().refine(e=>Buffer.byteLength(e,`utf8`)<=4096&&M(e)&&![...e].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)===127)),bg=F.enum([`desktop`,`headless`]),xg=F.enum([`prepared`,`source-stopped`,`destination-started`,`recovery-required`]),Sg=F.enum([`manual`,`persistent`,`desktop`]),Cg=F.strictObject({id:F.uuid(),source:F.enum([`desktop`,`headless`,`legacy-native`]).nullable(),target:bg,sourceManager:F.enum([`desktop-child`,`native-manual`,`native-persistent`,`launchd`,`systemd`]).nullable(),sourceInstance:F.uuid().nullable(),stateDir:yg,computerFp:U,targetBundlePath:yg.nullable(),targetVersion:F.string().min(1).max(256),phase:xg}),wg=F.strictObject({v:F.literal(1),revision:F.uuid(),mode:bg,consented:F.boolean(),startupEnabled:F.boolean(),transition:Cg.nullable()}),Tg=2097152,Eg=F.number().int().positive().max(2**53-1),Dg=F.uuid(),Og=F.string().regex(/^[0-9a-f]{64}$/),kg=F.string().refine(e=>Buffer.byteLength(e,`utf8`)<=4096),Ag=F.enum([`manual`,`persistent`]);function jg(e){if(e===`desktop`)throw new t_(`conflict`);return e}const Mg=F.enum([`prepared`,`source-stop-requested`,`source-stopped`,`destination-start-requested`,`awaiting-approval`,`destination-ready`,`recovery-required`]),Ng=F.strictObject({PATH:kg.refine(e=>e.split(`:`).every(e=>yg.safeParse(e).success)),SHELLBELL_DIR:yg,SHELLBELL_SERVICE_INSTANCE:F.uuid(),HERDR_SOCKET_PATH:yg.optional(),XDG_CONFIG_HOME:yg.optional()}),Pg=F.strictObject({mode:Sg,stateDir:yg,computerFp:U,serviceInstance:F.uuid(),bundlePath:yg,bundleId:F.literal(`sh.bilal.shellbell.host`),agentVersion:F.string().min(1),environment:Ng}).refine(e=>e.environment.SHELLBELL_DIR===e.stateDir&&e.environment.SHELLBELL_SERVICE_INSTANCE===e.serviceInstance),Fg=F.strictObject({id:F.uuid(),definitionPath:yg,rawBase64:F.string().max(1398104).refine(e=>/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(e)&&Buffer.from(e,`base64`).byteLength<=1048576&&Buffer.from(e,`base64`).toString(`base64`)===e),sha256:Og,wasLoaded:F.boolean(),stateDir:yg,computerFp:U}),Ig=F.strictObject({id:F.uuid(),action:F.enum([`start`,`stop`,`restart`,`remove`,`recover`]),phase:Mg}),Lg=Ig.extend({source:Pg.nullable(),destination:Pg.nullable(),recoveryId:F.uuid().nullable(),restoreLegacy:F.strictObject({restartPrevious:F.boolean()}).optional()}).refine(e=>e.restoreLegacy===void 0||e.action===`recover`),Rg=F.strictObject({v:F.literal(1),revision:Dg,selection:Pg.nullable(),transition:Lg.nullable(),recovery:Fg.nullable()}).refine(e=>e.transition?.recoveryId==null||e.transition.recoveryId===e.recovery?.id),zg=F.strictObject({registration:F.enum([`not-registered`,`enabled`,`requires-approval`,`not-found`,`unknown`]),loaded:F.boolean(),pid:Eg.nullable(),bundlePath:yg.nullable()}),Bg=F.discriminatedUnion(`ok`,[F.strictObject({v:F.literal(1),ok:F.literal(!0),status:F.enum([`not-registered`,`enabled`,`requires-approval`,`not-found`])}),F.strictObject({v:F.literal(1),ok:F.literal(!1),error:F.strictObject({code:F.enum([`unavailable`,`denied`,`invalid-bundle`,`operation-failed`])})})]),Vg=F.strictObject({revision:Dg.nullable(),runtime:_h.extend({stateDir:yg}).nullable()}),Hg=F.strictObject({revision:Dg.nullable(),mode:F.enum([`desktop`,`headless`,`legacy-native`]).nullable(),consented:F.boolean(),startupEnabled:F.boolean().nullable(),transition:Cg.nullable()}),Ug=F.strictObject({desktopLogin:zg.shape.registration.optional(),desktop:zg.optional(),ownership:Hg.optional(),revision:Dg.nullable(),selection:Pg.nullable(),transition:Ig.nullable(),recoveryAvailable:F.boolean(),manualRecoveryAvailable:F.boolean().optional(),legacy:F.strictObject({installed:F.boolean(),loaded:F.boolean(),stateDir:yg.nullable()}),manual:zg,persistent:zg,local:F.strictObject({kind:F.enum([`verified`,`foreign`,`absent`,`unverified`]),status:Dh.status.safeExtend({process:_h.extend({stateDir:yg})}).nullable()})}),Wg=F.strictObject({saved:vp.strict(),savedRevision:Og,appliedRevision:Og.nullable(),applied:F.enum([`not-running`,`unknown`,`matches`,`restart-required`])}),Gg=F.string().regex(/^[a-z][a-z0-9-]{0,31}$/),Kg=F.strictObject({agents:F.array(F.strictObject({kind:Gg,name:F.string().min(1).max(64),state:F.enum([`ready`,`needs-setup`,`hooks-off`,`blocked`,`coming-soon`]),helper:F.boolean(),skipped:F.boolean(),detail:F.string().min(1).max(512).optional()})).max(32)}),qg=F.strictObject({kinds:F.array(Gg).min(1).max(32)}),Jg={hello:F.strictObject({version:F.literal(1),agentVersion:F.string().min(1),capabilities:F.tuple([F.literal(`status`),F.literal(`settings`),F.literal(`lifecycle`),F.literal(`pairing`),F.literal(`devices`),F.literal(`diagnostics`)])}),status:Ug,"desktop.setup":Ug,"desktop.login.set":Ug,"desktop.start":Ug,"desktop.stop":Ug,"ownership.convert":Ug,"ownership.recover":Ug,"settings.get":Wg,"settings.set":Wg,"service.start":Ug,"service.stop":Ug,"service.restart":Ug,"service.remove":Ug,"service.recover":Ug,diagnostics:F.strictObject({checks:F.array(F.strictObject({name:F.string().min(1).max(64),ok:F.boolean(),severity:F.enum([`pass`,`warning`,`error`]),detail:F.string().max(1024),fix:F.string().max(2048).optional(),required:F.boolean().optional()})).max(32)}),devices:Dh.devices,terminals:F.strictObject({supported:F.boolean(),terminals:gu}),"terminals.connect":F.strictObject({supported:F.boolean(),started:F.boolean(),terminals:gu}),agents:Kg,"agents.setup":Kg,"agents.skip":Kg,"agents.remove":Kg,"devices.revoke":Dh[`devices.revoke`],"pairing.open":Eh,"pairing.close":Dh[`pairing.close`],"pairing.confirm":Dh[`pairing.confirm`]},$={v:F.literal(1),id:Eg},Yg=F.strictObject({expect:Vg}),Xg=Yg.extend({ownerRevision:Dg.nullable()}),Zg=Lh.options[0],Qg=Zg.shape.flowId,$g=F.discriminatedUnion(`cmd`,[F.strictObject({...$,cmd:F.literal(`desktop.login.set`),args:Xg.extend({enabled:F.boolean()})}),F.strictObject({...$,cmd:F.literal(`desktop.setup`),args:Xg.extend({consent:F.literal(!0)})}),F.strictObject({...$,cmd:F.literal(`desktop.start`),args:Xg}),F.strictObject({...$,cmd:F.literal(`desktop.stop`),args:Xg}),F.strictObject({...$,cmd:F.literal(`ownership.convert`),args:Xg.extend({target:bg,consent:F.literal(!0)})}),F.strictObject({...$,cmd:F.literal(`ownership.recover`),args:Xg.extend({intentId:F.uuid()})}),F.strictObject({...$,cmd:F.literal(`hello`)}),F.strictObject({...$,cmd:F.literal(`status`)}),F.strictObject({...$,cmd:F.literal(`settings.get`)}),F.strictObject({...$,cmd:F.literal(`diagnostics`)}),F.strictObject({...$,cmd:F.literal(`devices`)}),F.strictObject({...$,cmd:F.literal(`terminals`)}),F.strictObject({...$,cmd:F.literal(`agents`)}),F.strictObject({...$,cmd:F.literal(`agents.setup`),args:qg}),F.strictObject({...$,cmd:F.literal(`agents.skip`),args:qg}),F.strictObject({...$,cmd:F.literal(`agents.remove`),args:F.strictObject({kind:Gg})}),F.strictObject({...$,cmd:F.literal(`terminals.connect`),args:F.strictObject({name:Ql})}),F.strictObject({...$,cmd:F.literal(`settings.set`),args:Yg.extend({configRevision:Og,changes:F.array(F.strictObject({key:F.enum(Im),value:kg})).min(1).max(Im.length).refine(e=>new Set(e.map(e=>e.key)).size===e.length)})}),F.strictObject({...$,cmd:F.literal(`service.start`),args:Yg.extend({mode:Ag,consent:F.literal(!0),migrateLegacy:F.boolean(),stateDir:yg.optional()})}),F.strictObject({...$,cmd:F.literal(`service.stop`),args:Yg}),F.strictObject({...$,cmd:F.literal(`service.restart`),args:Yg}),F.strictObject({...$,cmd:F.literal(`service.remove`),args:Yg}),F.strictObject({...$,cmd:F.literal(`service.recover`),args:Yg.extend({action:F.enum([`continue`,`restore-legacy`,`discard-backup`,`use-manual`]),restartPrevious:F.boolean(),consent:F.literal(!0)}).refine(e=>!e.restartPrevious||e.action===`restore-legacy`)}),F.strictObject({...$,cmd:F.literal(`devices.revoke`),args:Yg.extend({phoneFp:U})}),F.strictObject({...$,cmd:F.literal(`pairing.open`),args:Yg}),F.strictObject({...$,cmd:F.literal(`pairing.close`),args:Yg.extend({flowId:Qg})}),F.strictObject({...$,cmd:F.literal(`pairing.confirm`),args:Yg.extend({flowId:Qg,challengeId:Zg.shape.challengeId,phoneFp:U,accept:F.boolean()})})]),e_=F.enum([`bad-request`,`unsupported-version`,`handshake-required`,`busy`,`unavailable`,`conflict`,`unsafe-state`,`invalid-config`,`upgrade-required`,`startup-unavailable`,`delivery-unknown`,`approval-required`,`recovery-required`,`operation-failed`,`response-too-large`,`timeout`]);var t_=class extends Error{code;constructor(e){super(e),this.code=e,this.name=`NativeControllerError`}};F.discriminatedUnion(`ok`,[F.strictObject({...$,ok:F.literal(!0),data:F.union(Object.values(Jg))}),F.strictObject({...$,ok:F.literal(!1),error:F.strictObject({code:e_})})]);const n_=F.discriminatedUnion(`event`,[Zg.extend({v:F.literal(1)}),Lh.options[1].extend({v:F.literal(1)})]);function r_(){throw new t_(`unsafe-state`)}function i_(e,t){return op(e,t)&&e.size===t.size&&e.mtimeMs===t.mtimeMs&&e.ctimeMs===t.ctimeMs&&e.mode===t.mode&&e.uid===t.uid}function a_(e){return e instanceof t_?e:new t_(e instanceof Y?`unsafe-state`:`operation-failed`)}var o_=class{options;root;path;uid;newId;constructor(e){this.options=e,(!yg.safeParse(e.root).success||!Number.isSafeInteger(e.uid)||e.uid<0)&&r_(),this.root=e.root.replace(/\/+$/,``)||`/`,this.path=N(this.root,e.filename),this.uid=e.uid,this.newId=e.newId??ce}inspect(){try{return this.checkAncestors(),X(this.root)?this.readSnapshot(Z(this.root,this.uid)).record:null}catch{return r_()}}async mutate(e,t){let n,r,i=!0;try{this.checkAncestors(),X(this.root)||m(this.root,{recursive:!0,mode:448});let a=Z(this.root,this.uid);r=h(this.root,o.O_RDONLY|o.O_NOFOLLOW|o.O_NONBLOCK),op(a,l(r))||r_(),n=this.acquireGuard(a);let s=this.readSnapshot(a);if((s.record?.revision??null)!==e)throw new t_(`conflict`);return await t({get current(){return structuredClone(s.record)},publish:e=>{if(!i)throw new t_(`operation-failed`);try{let t=this.options.schema.safeParse({...e,revision:this.newId()});(!t.success||t.data.revision===s.record?.revision)&&r_();let i=Buffer.from(JSON.stringify(t.data));return i.length>this.options.maxBytes&&r_(),this.publish(i,a,s,()=>n.assert()),u(r),s=this.readSnapshot(a),structuredClone(t.data)}catch(e){throw a_(e)}}})}catch(e){throw a_(e)}finally{i=!1;try{n?.release()}finally{r!==void 0&&a(r)}}}checkAncestors(){let e=this.root;for(;;){let t=X(e);t&&(!t.isDirectory()||t.isSymbolicLink())&&r_();let n=j(e);if(n===e)return;e=n}}checkRoot(e){this.checkAncestors(),op(e,Z(this.root,this.uid))||r_()}readSnapshot(e){this.checkRoot(e);let t=X(this.path);if(!t)return this.checkRoot(e),{record:null,stat:void 0,bytes:null};let n=lp(this.path,this.options.maxBytes,this.uid),r=X(this.path);(!r||!i_(t,r))&&r_(),this.checkRoot(e);let i;try{i=JSON.parse(new TextDecoder(`utf-8`,{fatal:!0}).decode(n))}catch{return r_()}let a=this.options.schema.safeParse(i);return a.success?{record:a.data,stat:r,bytes:n}:r_()}checkSnapshot(e,t){let n=this.readSnapshot(e);(t.stat?!n.stat||!i_(t.stat,n.stat)||!t.bytes?.equals(n.bytes):n.stat!==void 0)&&r_()}publish(e,t,n,r){r(),this.checkSnapshot(t,n);let i=`${this.path}.tmp-${ce()}`,s,c;try{s=h(i,o.O_WRONLY|o.O_CREAT|o.O_EXCL|o.O_NOFOLLOW,384),c=l(s);let a=0;for(;a<e.length;){let t=E(s,e,a,e.length-a);if(t<=0)throw new t_(`operation-failed`);a+=t}u(s);let d=l(s);this.checkSnapshot(t,n);let f=X(i);(!f||!op(c,d)||!i_(d,f)||!f.isFile()||f.uid!==this.uid||(f.mode&4095)!=384||d.size!==e.length)&&r_(),r(),b(i,this.path)}finally{s!==void 0&&a(s);try{this.checkRoot(t);let e=X(i);c&&e&&op(c,e)&&w(i)}catch{}}}acquireGuard(e){let t=`${this.path}.lock`,n=`owner-${process.pid}-${ce()}`,r=`${this.path}.lock-candidate-${n.slice(6)}`,i,o,s=!1,c=(r,i,a=n,s=o,c=!1)=>{try{if(this.checkRoot(e),!op(i,Z(r,this.uid)))return!1;let n=X(N(r,a));if(n&&(!s||!i_(s,n)))return!1;if(r===t){if(!n||!s)return!1;let e=`${this.path}.lock-candidate-${a.slice(6)}`;if(X(e)||(b(r,e),r=e,!op(i,Z(r,this.uid)))||(n=X(N(r,a)),!n||!i_(s,n)))return!1;if(c)return!0}return n&&w(N(r,a)),x(r),!0}catch{return!1}};try{this.checkRoot(e),m(r,{mode:448}),i=Z(r,this.uid);let u=h(N(r,n),`wx`,384);try{o=l(u)}finally{a(u)}for(let a=0;a<3;a++){if(this.checkRoot(e),X(t)){let e=Z(t,this.uid),n=v(t),r=n[0],i=r&&/^owner-([1-9][0-9]*)-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/.exec(r),a=i&&tp(i[1]);(n.length!==1||!r||!a)&&r_();let o=X(N(t,r));if(lp(N(t,r),0,this.uid),np(a))throw new t_(`busy`);op(e,Z(t,this.uid))||r_();let s=X(N(t,r));(!o||!s||!i_(o,s))&&r_(),c(t,e,r,o,!0)||r_()}try{b(r,t),s=!0;let a=Z(t,this.uid);return op(i,a)||r_(),{assert:()=>{this.checkRoot(e),op(a,Z(t,this.uid))||r_();let r=X(N(t,n));(!r||!o||!i_(o,r))&&r_()},release:()=>c(t,a)}}catch(e){if(![`EEXIST`,`ENOTEMPTY`,`ENOENT`].includes(e.code??``))throw e}}throw new t_(`busy`)}finally{!s&&i&&c(r,i)}}},s_=class extends o_{constructor(e){super({root:e.stateDir,uid:e.uid,filename:`service-owner.json`,maxBytes:16384,schema:wg})}};function c_(e){if(e?.mode===`desktop`)throw Error(`Service is desktop-owned; use Shellbell or explicitly convert it to headless mode`);if(e?.transition)throw Error(`An ownership conversion needs explicit recovery before headless service changes`)}function l_(e){let t;try{t=new s_({...e,stateDir:sp(e.stateDir)}).inspect()}catch{return null}return t?.mode===`desktop`?`The Shellbell app runs Shellbell on this Mac. Use the app to pair phones and change settings.`:t?.transition?`The Shellbell app is switching how Shellbell runs on this Mac. Open the app to finish, then try again.`:null}function u_(e){let t=p_(new s_({...e,stateDir:sp(e.stateDir)})),n=t?.transition;t?.mode===`headless`&&n?.target===`headless`&&e.serviceInstance===n.id&&[`source-stopped`,`destination-started`].includes(n.phase)||c_(t)}async function d_(e,t){let n=new s_({...e,stateDir:sp(e.stateDir)}),r=p_(n);return c_(r),f_(n,r?.revision??null,async e=>(c_(e.current),t()))}async function f_(e,t,n){let r=!1,i;return e.mutate(t,async e=>{try{return await n(e)}catch(e){throw r=!0,i=e,e}}).catch(e=>{throw r?i:m_(e)})}function p_(e){try{return e.inspect()}catch(e){throw m_(e)}}function m_(e){if(!(e instanceof t_))return e;let t={busy:`shellbell: Another Shellbell change is in progress, such as the Mac app starting or stopping its service. Try again in a moment.`,conflict:"shellbell: Shellbell's service ownership changed while this ran. Check `shellbell status`, then try again.","operation-failed":`shellbell: Shellbell couldn't read or save its service ownership record in its state folder. Check that the folder is yours and has free space, then try again.`,"unsafe-state":`shellbell: Shellbell's state folder has unsafe permissions or ownership; it must belong to you and not be writable by others.`};return t[e.code]?Error(t[e.code]):e}async function h_(e,t){let n=new s_(e),r=p_(n);return c_(r),!e.create&&!r&&!s(e.stateDir)?t():f_(n,r?.revision??null,async n=>{c_(n.current);let r=await t(),i=e.startupPreference?e.startupPreference(r):r.startupEnabled;if(i!==null&&(r.installed||n.current)&&(!n.current||n.current.startupEnabled!==i))try{n.publish({v:1,mode:`headless`,consented:!0,startupEnabled:i,transition:null})}catch(e){throw m_(e)}return r})}function g_(e){try{return y(e)}catch(t){if(t.code===`ENOENT`)return P(e);throw Error(`Cannot resolve state directory ${e}`)}}function __(e,t){try{return e.process.computerFp===t.computerFp&&g_(e.process.stateDir)===g_(t.stateDir)&&(t.serviceInstance===void 0||e.process.serviceInstance===t.serviceInstance)&&(t.pid===void 0||e.process.pid===t.pid)}catch{return!1}}var v_=class{clock;probe;constructor(e={}){this.clock=e.clock??{now:()=>de.now(),sleep:e=>new Promise(t=>setTimeout(t,e))},this.probe=e.probe??((e,t)=>Jh(e,`status`,void 0,{timeoutMs:t,maxResponseBytes:65536}))}async observe(e,t,n=500){let r;try{r=await this.probe(e,n)}catch(e){let t=e.code;return t===`ENOENT`||t===`ECONNREFUSED`?{kind:`absent`,local:null,diagnostic:`Local endpoint is absent`}:{kind:`unverified`,local:null,diagnostic:`Local endpoint did not return a bounded status response`}}let i=rh.safeParse(r);return i.success?t&&!__(i.data,t)?{kind:`foreign`,local:i.data,diagnostic:`Local endpoint belongs to a different process, identity, state directory, or service instance`}:{kind:`verified`,local:i.data}:{kind:`unverified`,local:null,diagnostic:`Local endpoint uses an unsupported or malformed status protocol`}}async waitReady(e,t){return(await this.wait(e,t,!1)).local}async waitStopped(e){await this.wait(e,void 0,!0)}async wait(e,t,n){let r=this.clock.now()+1e4,i=`Local endpoint is absent`;for(;this.clock.now()<r;){let a=await this.observe(e,t,Math.min(500,r-this.clock.now()));if(n?a.kind===`absent`:a.kind===`verified`)return a;if(i=a.diagnostic??`Local endpoint is still responding`,!n&&a.kind===`foreign`)throw Error(`Service readiness conflict: ${i}; stop the foreground owner before retrying`);let o=r-this.clock.now();o>0&&await this.clock.sleep(Math.min(100,o))}throw Error(`${n?`Service stop`:`Service readiness`} timed out: ${i}`)}};const y_=new Set([`.npm`,`_npx`,`dlx`]),b_=[[`npm`,`config`,`cache`].join(`_`),`NPM_CONFIG_CACHE`];function x_(e,t){throw Error(`Shellbell service runtime at ${e} ${t}; install a built Shellbell package in a durable directory, then run shellbell install again`)}function S_(e){try{return y(e)}catch{return ne(e)}}function C_(){let e=[k(),`/tmp`,`/private/tmp`,`/var/tmp`,`/private/var/tmp`];for(let t of b_){let n=process.env[t];n&&M(n)&&e.push(n)}return[...new Set(e.flatMap(e=>[ne(e),S_(e)]))]}function w_(e,t){let n=re(t,e);return n===``||n!==`..`&&!n.startsWith(`..${ie}`)&&!M(n)}function T_(e){let t=ne(e);(t.split(ie).some(e=>y_.has(e))||C_().some(e=>w_(t,e)))&&x_(e,`is in a temporary or package-manager cache location`)}function E_(e,t){M(e)||x_(e,`${t} path must be absolute`),T_(e);let n;try{n=y(e)}catch{x_(e,`${t} does not exist`)}return T_(n),(()=>{try{return S(n)}catch{return x_(n,`${t} does not exist`)}})().isFile()||x_(n,`${t} must be a regular file`),n}function D_(e,t,r){try{n(e,t)}catch{x_(e,r)}}function O_(e){let t=`${e}${ie}package.json`,n=(()=>{try{return S(t)}catch{return x_(t,`package.json is missing`)}})();n.isFile()||x_(t,`package.json must be a regular file`),n.size>1048576&&x_(t,`package.json exceeds 1 MiB`);let r;try{r=g(t,`utf8`)}catch{x_(t,`package.json is not readable`)}let i;try{i=JSON.parse(r)}catch{x_(t,`package.json is not valid JSON`)}return(typeof i!=`object`||!i||Array.isArray(i))&&x_(t,`package.json is not a valid manifest`),i}function k_(e){let t=e.bin,n=typeof t==`string`?t:typeof t==`object`&&t&&!Array.isArray(t)?t.shellbell:void 0;return n===`dist/cli.js`||n===`./dist/cli.js`}function A_(e=process.execPath,t=process.argv[1]??``){let n=Number.parseInt(process.versions.node.split(`.`)[0]??``,10);(!Number.isInteger(n)||n<22)&&x_(process.execPath,`requires the currently running Node.js major version to be at least 22`);let r=E_(e,`Node executable`);D_(r,o.X_OK,`Node executable is not executable`);let i=E_(t,`CLI entrypoint`);D_(i,o.R_OK,`CLI entrypoint is not readable`),(A(i)!==`cli.js`||A(j(i))!==`dist`)&&x_(i,`is not an installed built CLI entrypoint`);let a=j(j(i)),c=`${a}${ie}src${ie}cli.ts`;s(c)&&x_(a,`is a source checkout rather than an installed built package`);let l=O_(a);return l.name!==`shellbell`&&x_(`${a}${ie}package.json`,`has the wrong package name`),k_(l)||x_(`${a}${ie}package.json`,`does not declare the Shellbell bin entrypoint`),{nodePath:r,cliPath:i,packageRoot:a}}var j_=class extends Error{rollback=`not-needed`;rollbackDiagnostic;recoveryPath};function M_(e,t,n){let r=e.definition?.stateDir,i=g_(r??(t||n));if(r&&t&&g_(t)!==i)throw new j_(`SHELLBELL_DIR conflicts with the installed service state directory; state migration is not an implicit install operation`);return Lp(i)}function N_(e){return e instanceof j_?e:new j_(e instanceof Error?e.message.slice(0,600):`Service operation failed`)}async function P_(e,t,n){let r=j(e.definitionPath),i;try{return t&&m(r,{recursive:!0,mode:448}),s(r)&&(i=ap(e.definitionPath)),await n(e)}finally{i?.()}}var F_=class{options;manager;readiness;constructor(e){this.options=e,this.manager=e.manager,this.readiness=new v_(e)}selected(e){return M_(e,this.options.requestedStateDir,this.options.defaultStateDir)}definitionFor(e,t,n){let r=og({stateDir:t.dir,serviceInstance:n,nodePath:e.nodePath,env:this.options.env}),i={nodePath:e.nodePath,cliPath:e.cliPath,stateDir:t.dir,serviceInstance:n,environment:r,logPath:t.log};for(let e of Object.values(i))typeof e==`string`&&ig(e);for(let[e,t]of Object.entries(r))ig(e),ig(t);return i}expected(e,t){let n=Xh(t);return n?{computerFp:n.fp,stateDir:t.dir,serviceInstance:e.definition?.serviceInstance??null}:void 0}result(e,t,n,r=null,i){let a=e.installed&&e.definition?.serviceInstance===null,o=e.installed&&e.loaded&&!!n&&t.kind===`verified`&&(!a||r!==null),s=i??(n?a&&r===null?`Legacy service cannot be verified by read-only status; run service install to upgrade`:void 0:`Local identity is missing; no keys were created`),c=e.definition&&!e.definition.environment.SHELLBELL_DIR?`Legacy definition assumes the historical ~/.shellbell state directory`:void 0;return{manager:this.manager.kind,definitionPath:this.manager.definitionPath,installed:e.installed,loaded:e.loaded,startupEnabled:e.startupEnabled??null,autostartConfigured:e.installed&&e.startupEnabled===!0,managedPid:r,ownership:t.kind===`foreign`?`foreign`:a&&!o?`legacy`:o?`verified`:`none`,local:t.local,ready:o,...t.diagnostic||s||c?{diagnostic:[t.diagnostic,s,c].filter(Boolean).join(`; `)}:{}}}async installedRuntime(){let{definition:e}=await this.manager.inspect();return e?{nodePath:e.nodePath,cliPath:e.cliPath,stateDir:e.stateDir}:null}async status(){let e=await this.manager.inspect(),t=this.selected(e),n=this.expected(e,t);return this.result(e,await this.readiness.observe(t.sock,n),n)}async serialized(e,t){try{let n=await this.manager.inspect();return await h_({stateDir:sp(this.selected(n).dir),uid:process.getuid(),create:e},()=>P_(this.manager,e,t))}catch(e){throw N_(e)}}assertAvailable(e,t,n){if(t.kind!==`absent`&&!(e.loaded&&e.definition?.serviceInstance===null&&t.kind===`unverified`)&&!(e.loaded&&n&&t.kind===`verified`))throw new j_(`Local endpoint ownership is unverified or foreign; stop the foreground owner before retrying service changes`)}async rollback(e,t,n,r,i){let a=N_(i);if(!r.unloadAttempted&&!r.written&&!r.loaded)throw a;try{if(r.loaded&&await this.manager.unload(),(r.unloadAttempted||r.loaded)&&await this.readiness.waitStopped(t.sock),r.written&&await this.manager.restore(e.raw),e.loaded){let r=await this.manager.load();e.definition?.serviceInstance&&n&&await this.readiness.waitReady(t.sock,{...n,pid:r})}a.rollback=`restored`}catch(t){if(a.rollback=`failed`,a.rollbackDiagnostic=N_(t).message,e.raw){let t=`${this.manager.definitionPath}.recovery-${ce()}`;try{T(t,e.raw,{mode:384,flag:`wx`}),a.recoveryPath=t}catch{a.rollbackDiagnostic+=`; could not save a private recovery definition`}}}throw a}async install(){try{let e=A_(),t=ce();return this.definitionFor(e,Lp(g_(this.options.requestedStateDir||this.options.defaultStateDir)),t),await this.serialized(!0,async()=>{let n=await this.manager.inspect(),r=this.selected(n),i=this.definitionFor(e,r,t),a=this.expected(n,r);if(n.installed&&!a)throw new j_(`Installed service identity is missing at ${r.identity}; restore it before upgrading`);this.assertAvailable(n,await this.readiness.observe(r.sock,a),a);let o=Xh(r)??Zh(r);vg(r.log);let s={computerFp:o.fp,stateDir:r.dir,serviceInstance:t},c={unloadAttempted:!1,written:!1,loaded:!1};try{n.loaded&&(c.unloadAttempted=!0,await this.manager.unload(),await this.readiness.waitStopped(r.sock)),c.written=!0,await this.manager.write(i),c.loaded=!0;let e=await this.manager.load(),t=await this.readiness.waitReady(r.sock,{...s,pid:e}),a=await this.manager.inspect();if(!a.loaded)throw Error(`Service unloaded before readiness could be confirmed`);return this.result(a,{kind:`verified`,local:t},s,e)}catch(e){return this.rollback(n,r,a,c,e)}})}catch(e){throw N_(e)}}start(){return this.runInstalled(`start`)}restart(){return this.runInstalled(`restart`)}stop(){return this.runInstalled(`stop`)}enable(){return this.setStartup(!0)}disable(){return this.setStartup(!1)}async setStartup(e){return this.serialized(!1,async()=>{let t=await this.manager.inspect(),n=this.selected(t);if(!t.installed)throw new j_(`Service is not installed; run service install first`);await this.manager.setStartupEnabled(e);let r=await this.manager.inspect();if(r.startupEnabled!==e||r.loaded!==t.loaded)throw new j_(`Startup preference or current execution could not be verified`);let i=this.expected(r,n);return this.result(r,await this.readiness.observe(n.sock,i),i)})}uninstall(){return this.runInstalled(`uninstall`)}runInstalled(e){return this.serialized(!1,async()=>{let t=await this.manager.inspect(),n=this.selected(t),r=e===`stop`||e===`uninstall`,i,a;try{i=this.expected(t,n)}catch(e){if(!r)throw e;a=N_(e).message}let o=await this.readiness.observe(n.sock,i);if(!t.installed){if(!r)throw new j_(`Service is not installed; run service install first`);return this.result(t,o,i,null,a)}if(!r&&!i)throw new j_(`Local identity is missing at ${n.identity}; restore it before starting`);r&&t.loaded&&o.kind===`unverified`||this.assertAvailable(t,o,i);let s={unloadAttempted:!1,written:!1,loaded:!1};try{if(e!==`start`&&t.loaded&&(s.unloadAttempted=!0,await this.manager.unload(),await this.readiness.waitStopped(n.sock)),r){e===`uninstall`&&await this.manager.restore(null);let t=await this.manager.inspect();if(t.loaded)throw Error(`Service remains loaded after stop`);return this.result(t,{kind:`absent`,local:null,diagnostic:e===`stop`?`Service stopped; definition remains and it may start at next login`:`Service uninstalled; identity and pairings remain`},i,null,a)}s.loaded=!t.loaded||e===`restart`;let c=await this.manager.load();if(e===`restart`&&o.local?.process.pid===c)throw Error(`Service restart did not produce a new manager-certified process`);let l=await this.readiness.waitReady(n.sock,{...i,pid:c}),u=await this.manager.inspect();if(!u.loaded)throw Error(`Service unloaded before readiness could be confirmed`);return this.result(u,{kind:`verified`,local:l},i,c)}catch(e){if(r)throw N_(e);return this.rollback(t,n,i,s,e)}})}};export{wm as $,G as $n,Td as $t,Zh as A,ic as An,Y as At,ih as B,Ra as Bn,Qf as Bt,Ug as C,Sc as Cn,Mp as Ct,_g as D,cc as Dn,gp as Dt,yg as E,Fc as En,_p as Et,Q as F,vc as Fn,op as Ft,Bm as G,Rr as Gn,hf as Gt,Jm as H,Dr as Hn,Xf as Ht,Gh as I,yc as In,ap as It,Nm as J,wr as Jn,Od as Jt,zm as K,Er as Kn,nf as Kt,ph as L,uc as Ln,np as Lt,qh as M,$s as Mn,sp as Mt,Yh as N,nc as Nn,X as Nt,tg as O,pc as On,hp as Ot,Jh as P,dc as Pn,Z as Pt,ym as Q,W as Qn,Pd as Qt,dh as R,oc as Rn,tp as Rt,Pg as S,xc as Sn,Np as St,Sg as T,Ec as Tn,xp as Tt,Um as U,Or as Un,Ff as Ut,qm as V,ba as Vn,Zf as Vt,Im as W,Lr as Wn,gf as Wt,Am as X,rr as Xn,Nd as Xt,Dm as Y,br as Yn,Ld as Yt,km as Z,ir as Zn,Fd as Zt,e_ as _,sl as _n,om as _t,A_ as a,Pu as an,$n as ar,gm as at,Rg as b,Bc as bn,kp as bt,s_ as c,Ql as cn,Kn as cr,Xp as ct,d_ as d,au as dn,Rp as dt,Ed as en,ur as er,Cm as et,h_ as f,Au as fn,Jp as ft,Jg as g,Wl as gn,Kp as gt,t_ as h,Bu as hn,Lp as ht,P_ as i,qu as in,tr as ir,_m as it,Xh as j,bc as jn,lp as jt,eg as k,fc as kn,up as kt,l_ as l,Zl as ln,Gn as lr,Gp as lt,Tg as m,Ou as mn,am as mt,j_ as n,bd as nn,U as nr,xm as nt,v_ as o,Fu as on,er as or,um as ot,o_ as p,iu as pn,qp as pt,Pm as q,xr as qn,kd as qt,M_ as r,Sd as rn,Yn as rr,Sm as rt,__ as s,su as sn,V as sr,cm as st,F_ as t,Dd as tn,nr as tr,bm as tt,u_ as u,ou as un,im as ut,n_ as v,ll as vn,zp as vt,jg as w,wc as wn,vp as wt,$g as x,Uc as xn,Ep as xt,Bg as y,ol as yn,Op as yt,rh as z,sc as zn,$f as zt};
29
+ `}function hg(e,t){if(typeof e!=`string`||!e||!M(e))throw Error(`invalid service definition: ${t} must be an absolute path`);return pg(e),e}function gg(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`invalid service definition`);let n=e;for(let e of Object.keys(n))if(!fg.has(e))throw Error(`unrecognized service definition key: ${e}`);if(n.Label!==`sh.bilal.shellbell`||!Array.isArray(n.ProgramArguments)||n.ProgramArguments.length!==4||n.ProgramArguments[2]!==`start`||n.ProgramArguments[3]!==`--service`||n.RunAtLoad!==!0||n.KeepAlive!==!0||n.StandardOutPath!==n.StandardErrorPath)throw Error(`unrecognized Shellbell service definition`);let r=n.EnvironmentVariables;if(!r||typeof r!=`object`||Array.isArray(r))throw Error(`invalid service environment`);let i=r;for(let[e,t]of Object.entries(i)){if(!dg.has(e))throw Error(`unrecognized service environment: ${e}`);if(typeof t!=`string`)throw Error(`invalid service environment: ${e}`);pg(e),pg(t),(e===`HERDR_SOCKET_PATH`||e===`XDG_CONFIG_HOME`)&&hg(t,e)}if(typeof i.PATH!=`string`||!i.PATH||i.PATH.split(`:`).some(e=>!e||!M(e)))throw Error(`invalid service PATH`);let a=i.SHELLBELL_DIR===void 0?N(t,`.shellbell`):hg(i.SHELLBELL_DIR,`SHELLBELL_DIR`),o=i.SHELLBELL_SERVICE_INSTANCE;if(o!==void 0&&(typeof o!=`string`||!ug.test(o)))throw Error(`invalid service instance`);return{nodePath:hg(n.ProgramArguments[0],`nodePath`),cliPath:hg(n.ProgramArguments[1],`cliPath`),stateDir:a,serviceInstance:o??null,environment:i,logPath:hg(n.StandardOutPath,`logPath`)}}function _g(e){if(hg(e.nodePath,`nodePath`),hg(e.cliPath,`cliPath`),hg(e.stateDir,`stateDir`),hg(e.logPath,`logPath`),!e.serviceInstance||!ug.test(e.serviceInstance))throw Error(`serviceInstance must be a UUID`);let t=e.environment;if(t.SHELLBELL_DIR!==e.stateDir||t.SHELLBELL_SERVICE_INSTANCE!==e.serviceInstance)throw Error(`service definition and environment disagree`);if(!t.PATH||t.PATH.split(`:`).some(e=>!e||!M(e)))throw Error(`invalid service PATH`);for(let[e,n]of Object.entries(t)){if(!dg.has(e))throw Error(`unsupported service environment: ${e}`);if(typeof n!=`string`)throw Error(`invalid service environment: ${e}`);pg(e),pg(n),(e===`HERDR_SOCKET_PATH`||e===`XDG_CONFIG_HOME`)&&hg(n,e)}}function vg(e={}){let t=e.run??ng,n=e.uid??te().uid;if(!Number.isSafeInteger(n)||n<0)throw Error(`invalid service UID`);let r=e.homeDir??D(),i=e.definitionPath??N(r,`Library`,`LaunchAgents`,`sh.bilal.shellbell.plist`),a=`gui/${n}`,o=`${a}/${cg}`,s;function c(e,t){return e===null||t===null?e===t:e.stat.dev===t.stat.dev&&e.stat.ino===t.stat.ino&&e.stat.uid===t.stat.uid&&e.stat.mode===t.stat.mode&&e.stat.size===t.stat.size&&e.stat.mtimeMs===t.stat.mtimeMs&&e.stat.ctimeMs===t.stat.ctimeMs&&e.raw.equals(t.raw)}function l(){let e;try{e=p(i)}catch(e){if(e.code===`ENOENT`)return null;throw e}return!e.isFile()||e.isSymbolicLink()||e.uid!==n||e.mode&18||e.size>lg?{stat:e,raw:Buffer.alloc(0)}:{stat:e,raw:g(i)}}function u(e){if(!c(e,l()))throw Error(`service definition changed or was replaced during operation`)}function d(e){let t=l();if(!t?.raw.equals(e))throw Error(`service definition changed after publication`);s=t}async function f(e,n,r=!1,i){let a=await t(e,n,{input:i,timeoutMs:5e3,maxOutputBytes:e===`/usr/bin/plutil`?lg:65536,captureOutput:r});if(!Number.isInteger(a.exitCode))throw Error(`${e} returned invalid exit status`);return a}async function h(e){let t=await f(`/usr/bin/plutil`,[`-convert`,`json`,`-o`,`-`,`-`],!0,e);if(t.exitCode!==0)throw Error(`plutil could not parse service definition`);let n;try{n=JSON.parse(t.stdout.toString(`utf8`))}catch{throw Error(`plutil returned invalid service definition JSON`)}return gg(n,r)}async function _(){let e;try{e=p(i)}catch(e){if(e.code===`ENOENT`)return null;throw e}if(!e.isFile()||e.isSymbolicLink()||e.uid!==n||e.mode&18||e.size>lg)throw Error(`unsafe service definition metadata`);let t=g(i);if(t.length>lg)throw Error(`service definition too large`);let r=await h(t),a={stat:e,raw:t};return u(a),{...a,definition:r}}async function v(){let e=await f(`/bin/launchctl`,[`print`,o]);if(e.exitCode===0)return!0;if(e.exitCode===113)return!1;throw Error(`launchctl print failed (${e.exitCode})`)}async function y(){try{let e=await f(`/bin/launchctl`,[`print-disabled`,a],!0),t=new TextDecoder(`utf-8`,{fatal:!0}).decode(e.stdout).trim().split(/\r?\n/).map(e=>e.trim());if(e.exitCode!==0||t.shift()!==`disabled services = {`||t.pop()!==`}`)return null;let n=t.filter(e=>e.includes(`"${cg}"`));return n.length===0?!0:n.length===1?n[0]===`"sh.bilal.shellbell" => disabled`||n[0]===`"sh.bilal.shellbell" => true`?!1:n[0]===`"sh.bilal.shellbell" => enabled`||n[0]===`"sh.bilal.shellbell" => false`||null:null}catch{return null}}let b={kind:`launchd`,definitionPath:i,async inspect(){let e=await _(),t=await v();if(u(e),!e&&t)throw Error(`loaded Shellbell job has no valid installed definition`);if(s!==void 0&&!c(s,e))throw Error(`service definition changed or was replaced after inspection`);return s===void 0&&(s=e),{installed:!!e,startupEnabled:e?await y():!1,loaded:t,raw:e?.raw??null,definition:e?.definition??null}},async setStartupEnabled(e){let t=await b.inspect();if(!t.installed)throw Error(`service is not installed`);if(t.startupEnabled!==e){if((await f(`/bin/launchctl`,[e?`enable`:`disable`,o])).exitCode!==0)throw Error(`launchctl startup preference change failed`);if((await b.inspect()).startupEnabled!==e)throw Error(`launchctl startup preference could not be verified`)}},async write(e){await tg(t,n,r),_g(e);let a=await _();if(s!==void 0&&!c(s,a))throw Error(`service definition changed or was replaced after inspection`);if(!a&&await v())throw Error(`loaded Shellbell job has no installed definition`);let o=mg({...e});m(j(i),{recursive:!0,mode:448}),zp(i,o,()=>u(a)),d(Buffer.from(o))},async restore(e){if(e!==null&&e.length>lg)throw Error(`service definition too large`);let a=await _();if(s!==void 0&&!c(s,a))throw Error(`service definition changed or was replaced after inspection`);if(e===null){if(!a)return;if(s===void 0)throw Error(`refusing to remove unexpected service definition replacement`);u(a),w(i),s=null;return}if(s===void 0)throw Error(`service definition changed unexpectedly`);if(await h(e),a)zp(i,e,()=>u(a));else if(await tg(t,n,r),m(j(i),{recursive:!0,mode:448}),!Vp(i,e))throw Error(`service definition changed or was replaced after inspection`);d(e)},async load(){await tg(t,n,r);let e=await b.inspect();if(!e.installed)throw Error(`service definition is not installed`);if(e.startupEnabled===null)throw Error(`service startup preference is unresolved`);let s=e.startupEnabled===!1;try{if(s&&await b.setStartupEnabled(!0),!e.loaded){let e=await f(`/bin/launchctl`,[`bootstrap`,a,i]);if(e.exitCode!==0)throw Error(`launchctl bootstrap failed (${e.exitCode})`)}let t=await f(`/bin/launchctl`,[`kickstart`,`-p`,o],!0);if(t.exitCode!==0)throw Error(`launchctl kickstart failed (${t.exitCode})`);let n=t.stdout.toString(`utf8`).trim();if(!/^[1-9][0-9]*$/.test(n))throw Error(`invalid launchctl PID output`);let r=Number(n);if(!Number.isSafeInteger(r)||r>2147483647)throw Error(`invalid launchctl PID output`);return r}finally{s&&await b.setStartupEnabled(!1)}},async unload(){if(!(await b.inspect()).loaded)return;let e=await f(`/bin/launchctl`,[`bootout`,o]);if(e.exitCode!==0)throw Error(`launchctl bootout failed (${e.exitCode})`);if(await v())throw Error(`launchctl bootout did not unload service`)}};return b}function yg(e){s(e)?i(e,384):T(e,``,{mode:384})}const bg=F.string().refine(e=>Buffer.byteLength(e,`utf8`)<=4096&&M(e)&&![...e].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)===127)),xg=F.enum([`desktop`,`headless`]),Sg=F.enum([`prepared`,`source-stopped`,`destination-started`,`recovery-required`]),Cg=F.enum([`manual`,`persistent`,`desktop`]),wg=F.strictObject({id:F.uuid(),source:F.enum([`desktop`,`headless`,`legacy-native`]).nullable(),target:xg,sourceManager:F.enum([`desktop-child`,`native-manual`,`native-persistent`,`launchd`,`systemd`]).nullable(),sourceInstance:F.uuid().nullable(),stateDir:bg,computerFp:U,targetBundlePath:bg.nullable(),targetVersion:F.string().min(1).max(256),phase:Sg}),Tg=F.strictObject({v:F.literal(1),revision:F.uuid(),mode:xg,consented:F.boolean(),startupEnabled:F.boolean(),transition:wg.nullable()}),Eg=2097152,Dg=F.number().int().positive().max(2**53-1),Og=F.uuid(),kg=F.string().regex(/^[0-9a-f]{64}$/),Ag=F.string().refine(e=>Buffer.byteLength(e,`utf8`)<=4096),jg=F.enum([`manual`,`persistent`]);function Mg(e){if(e===`desktop`)throw new n_(`conflict`);return e}const Ng=F.enum([`prepared`,`source-stop-requested`,`source-stopped`,`destination-start-requested`,`awaiting-approval`,`destination-ready`,`recovery-required`]),Pg=F.strictObject({PATH:Ag.refine(e=>e.split(`:`).every(e=>bg.safeParse(e).success)),SHELLBELL_DIR:bg,SHELLBELL_SERVICE_INSTANCE:F.uuid(),HERDR_SOCKET_PATH:bg.optional(),XDG_CONFIG_HOME:bg.optional()}),Fg=F.strictObject({mode:Cg,stateDir:bg,computerFp:U,serviceInstance:F.uuid(),bundlePath:bg,bundleId:F.literal(`sh.bilal.shellbell.host`),agentVersion:F.string().min(1),environment:Pg}).refine(e=>e.environment.SHELLBELL_DIR===e.stateDir&&e.environment.SHELLBELL_SERVICE_INSTANCE===e.serviceInstance),Ig=F.strictObject({id:F.uuid(),definitionPath:bg,rawBase64:F.string().max(1398104).refine(e=>/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(e)&&Buffer.from(e,`base64`).byteLength<=1048576&&Buffer.from(e,`base64`).toString(`base64`)===e),sha256:kg,wasLoaded:F.boolean(),stateDir:bg,computerFp:U}),Lg=F.strictObject({id:F.uuid(),action:F.enum([`start`,`stop`,`restart`,`remove`,`recover`]),phase:Ng}),Rg=Lg.extend({source:Fg.nullable(),destination:Fg.nullable(),recoveryId:F.uuid().nullable(),restoreLegacy:F.strictObject({restartPrevious:F.boolean()}).optional()}).refine(e=>e.restoreLegacy===void 0||e.action===`recover`),zg=F.strictObject({v:F.literal(1),revision:Og,selection:Fg.nullable(),transition:Rg.nullable(),recovery:Ig.nullable()}).refine(e=>e.transition?.recoveryId==null||e.transition.recoveryId===e.recovery?.id),Bg=F.strictObject({registration:F.enum([`not-registered`,`enabled`,`requires-approval`,`not-found`,`unknown`]),loaded:F.boolean(),pid:Dg.nullable(),bundlePath:bg.nullable()}),Vg=F.discriminatedUnion(`ok`,[F.strictObject({v:F.literal(1),ok:F.literal(!0),status:F.enum([`not-registered`,`enabled`,`requires-approval`,`not-found`])}),F.strictObject({v:F.literal(1),ok:F.literal(!1),error:F.strictObject({code:F.enum([`unavailable`,`denied`,`invalid-bundle`,`operation-failed`])})})]),Hg=F.strictObject({revision:Og.nullable(),runtime:vh.extend({stateDir:bg}).nullable()}),Ug=F.strictObject({revision:Og.nullable(),mode:F.enum([`desktop`,`headless`,`legacy-native`]).nullable(),consented:F.boolean(),startupEnabled:F.boolean().nullable(),transition:wg.nullable()}),Wg=F.strictObject({desktopLogin:Bg.shape.registration.optional(),desktop:Bg.optional(),ownership:Ug.optional(),revision:Og.nullable(),selection:Fg.nullable(),transition:Lg.nullable(),recoveryAvailable:F.boolean(),manualRecoveryAvailable:F.boolean().optional(),legacy:F.strictObject({installed:F.boolean(),loaded:F.boolean(),stateDir:bg.nullable()}),manual:Bg,persistent:Bg,local:F.strictObject({kind:F.enum([`verified`,`foreign`,`absent`,`unverified`]),status:Oh.status.safeExtend({process:vh.extend({stateDir:bg})}).nullable()})}),Gg=F.strictObject({saved:vp.strict(),savedRevision:kg,appliedRevision:kg.nullable(),applied:F.enum([`not-running`,`unknown`,`matches`,`restart-required`])}),Kg=F.string().regex(/^[a-z][a-z0-9-]{0,31}$/),qg=F.strictObject({agents:F.array(F.strictObject({kind:Kg,name:F.string().min(1).max(64),state:F.enum([`ready`,`needs-setup`,`hooks-off`,`blocked`,`coming-soon`]),helper:F.boolean(),skipped:F.boolean(),detail:F.string().min(1).max(512).optional()})).max(32)}),Jg=F.strictObject({kinds:F.array(Kg).min(1).max(32)}),Yg={hello:F.strictObject({version:F.literal(1),agentVersion:F.string().min(1),capabilities:F.tuple([F.literal(`status`),F.literal(`settings`),F.literal(`lifecycle`),F.literal(`pairing`),F.literal(`devices`),F.literal(`diagnostics`)])}),status:Wg,"desktop.setup":Wg,"desktop.login.set":Wg,"desktop.start":Wg,"desktop.stop":Wg,"ownership.convert":Wg,"ownership.recover":Wg,"settings.get":Gg,"settings.set":Gg,"service.start":Wg,"service.stop":Wg,"service.restart":Wg,"service.remove":Wg,"service.recover":Wg,diagnostics:F.strictObject({checks:F.array(F.strictObject({name:F.string().min(1).max(64),ok:F.boolean(),severity:F.enum([`pass`,`warning`,`error`]),detail:F.string().max(1024),fix:F.string().max(2048).optional(),required:F.boolean().optional()})).max(32)}),devices:Oh.devices,terminals:F.strictObject({supported:F.boolean(),terminals:gu}),"terminals.connect":F.strictObject({supported:F.boolean(),started:F.boolean(),terminals:gu}),agents:qg,"agents.setup":qg,"agents.skip":qg,"agents.remove":qg,"devices.revoke":Oh[`devices.revoke`],"pairing.open":Dh,"pairing.close":Oh[`pairing.close`],"pairing.confirm":Oh[`pairing.confirm`]},$={v:F.literal(1),id:Dg},Xg=F.strictObject({expect:Hg}),Zg=Xg.extend({ownerRevision:Og.nullable()}),Qg=Rh.options[0],$g=Qg.shape.flowId,e_=F.discriminatedUnion(`cmd`,[F.strictObject({...$,cmd:F.literal(`desktop.login.set`),args:Zg.extend({enabled:F.boolean()})}),F.strictObject({...$,cmd:F.literal(`desktop.setup`),args:Zg.extend({consent:F.literal(!0)})}),F.strictObject({...$,cmd:F.literal(`desktop.start`),args:Zg}),F.strictObject({...$,cmd:F.literal(`desktop.stop`),args:Zg}),F.strictObject({...$,cmd:F.literal(`ownership.convert`),args:Zg.extend({target:xg,consent:F.literal(!0)})}),F.strictObject({...$,cmd:F.literal(`ownership.recover`),args:Zg.extend({intentId:F.uuid()})}),F.strictObject({...$,cmd:F.literal(`hello`)}),F.strictObject({...$,cmd:F.literal(`status`)}),F.strictObject({...$,cmd:F.literal(`settings.get`)}),F.strictObject({...$,cmd:F.literal(`diagnostics`)}),F.strictObject({...$,cmd:F.literal(`devices`)}),F.strictObject({...$,cmd:F.literal(`terminals`)}),F.strictObject({...$,cmd:F.literal(`agents`)}),F.strictObject({...$,cmd:F.literal(`agents.setup`),args:Jg}),F.strictObject({...$,cmd:F.literal(`agents.skip`),args:Jg}),F.strictObject({...$,cmd:F.literal(`agents.remove`),args:F.strictObject({kind:Kg})}),F.strictObject({...$,cmd:F.literal(`terminals.connect`),args:F.strictObject({name:Ql})}),F.strictObject({...$,cmd:F.literal(`settings.set`),args:Xg.extend({configRevision:kg,changes:F.array(F.strictObject({key:F.enum(Im),value:Ag})).min(1).max(Im.length).refine(e=>new Set(e.map(e=>e.key)).size===e.length)})}),F.strictObject({...$,cmd:F.literal(`service.start`),args:Xg.extend({mode:jg,consent:F.literal(!0),migrateLegacy:F.boolean(),stateDir:bg.optional()})}),F.strictObject({...$,cmd:F.literal(`service.stop`),args:Xg}),F.strictObject({...$,cmd:F.literal(`service.restart`),args:Xg}),F.strictObject({...$,cmd:F.literal(`service.remove`),args:Xg}),F.strictObject({...$,cmd:F.literal(`service.recover`),args:Xg.extend({action:F.enum([`continue`,`restore-legacy`,`discard-backup`,`use-manual`]),restartPrevious:F.boolean(),consent:F.literal(!0)}).refine(e=>!e.restartPrevious||e.action===`restore-legacy`)}),F.strictObject({...$,cmd:F.literal(`devices.revoke`),args:Xg.extend({phoneFp:U})}),F.strictObject({...$,cmd:F.literal(`pairing.open`),args:Xg}),F.strictObject({...$,cmd:F.literal(`pairing.close`),args:Xg.extend({flowId:$g})}),F.strictObject({...$,cmd:F.literal(`pairing.confirm`),args:Xg.extend({flowId:$g,challengeId:Qg.shape.challengeId,phoneFp:U,accept:F.boolean()})})]),t_=F.enum([`bad-request`,`unsupported-version`,`handshake-required`,`busy`,`unavailable`,`conflict`,`unsafe-state`,`invalid-config`,`upgrade-required`,`startup-unavailable`,`delivery-unknown`,`approval-required`,`recovery-required`,`operation-failed`,`response-too-large`,`timeout`]);var n_=class extends Error{code;constructor(e){super(e),this.code=e,this.name=`NativeControllerError`}};F.discriminatedUnion(`ok`,[F.strictObject({...$,ok:F.literal(!0),data:F.union(Object.values(Yg))}),F.strictObject({...$,ok:F.literal(!1),error:F.strictObject({code:t_})})]);const r_=F.discriminatedUnion(`event`,[Qg.extend({v:F.literal(1)}),Rh.options[1].extend({v:F.literal(1)})]);function i_(){throw new n_(`unsafe-state`)}function a_(e,t){return op(e,t)&&e.size===t.size&&e.mtimeMs===t.mtimeMs&&e.ctimeMs===t.ctimeMs&&e.mode===t.mode&&e.uid===t.uid}function o_(e){return e instanceof n_?e:new n_(e instanceof Y?`unsafe-state`:`operation-failed`)}var s_=class{options;root;path;uid;newId;constructor(e){this.options=e,(!bg.safeParse(e.root).success||!Number.isSafeInteger(e.uid)||e.uid<0)&&i_(),this.root=e.root.replace(/\/+$/,``)||`/`,this.path=N(this.root,e.filename),this.uid=e.uid,this.newId=e.newId??ce}inspect(){try{return this.checkAncestors(),X(this.root)?this.readSnapshot(Z(this.root,this.uid)).record:null}catch{return i_()}}async mutate(e,t){let n,r,i=!0;try{this.checkAncestors(),X(this.root)||m(this.root,{recursive:!0,mode:448});let a=Z(this.root,this.uid);r=h(this.root,o.O_RDONLY|o.O_NOFOLLOW|o.O_NONBLOCK),op(a,l(r))||i_(),n=this.acquireGuard(a);let s=this.readSnapshot(a);if((s.record?.revision??null)!==e)throw new n_(`conflict`);return await t({get current(){return structuredClone(s.record)},publish:e=>{if(!i)throw new n_(`operation-failed`);try{let t=this.options.schema.safeParse({...e,revision:this.newId()});(!t.success||t.data.revision===s.record?.revision)&&i_();let i=Buffer.from(JSON.stringify(t.data));return i.length>this.options.maxBytes&&i_(),this.publish(i,a,s,()=>n.assert()),u(r),s=this.readSnapshot(a),structuredClone(t.data)}catch(e){throw o_(e)}}})}catch(e){throw o_(e)}finally{i=!1;try{n?.release()}finally{r!==void 0&&a(r)}}}checkAncestors(){let e=this.root;for(;;){let t=X(e);t&&(!t.isDirectory()||t.isSymbolicLink())&&i_();let n=j(e);if(n===e)return;e=n}}checkRoot(e){this.checkAncestors(),op(e,Z(this.root,this.uid))||i_()}readSnapshot(e){this.checkRoot(e);let t=X(this.path);if(!t)return this.checkRoot(e),{record:null,stat:void 0,bytes:null};let n=lp(this.path,this.options.maxBytes,this.uid),r=X(this.path);(!r||!a_(t,r))&&i_(),this.checkRoot(e);let i;try{i=JSON.parse(new TextDecoder(`utf-8`,{fatal:!0}).decode(n))}catch{return i_()}let a=this.options.schema.safeParse(i);return a.success?{record:a.data,stat:r,bytes:n}:i_()}checkSnapshot(e,t){let n=this.readSnapshot(e);(t.stat?!n.stat||!a_(t.stat,n.stat)||!t.bytes?.equals(n.bytes):n.stat!==void 0)&&i_()}publish(e,t,n,r){r(),this.checkSnapshot(t,n);let i=`${this.path}.tmp-${ce()}`,s,c;try{s=h(i,o.O_WRONLY|o.O_CREAT|o.O_EXCL|o.O_NOFOLLOW,384),c=l(s);let a=0;for(;a<e.length;){let t=E(s,e,a,e.length-a);if(t<=0)throw new n_(`operation-failed`);a+=t}u(s);let d=l(s);this.checkSnapshot(t,n);let f=X(i);(!f||!op(c,d)||!a_(d,f)||!f.isFile()||f.uid!==this.uid||(f.mode&4095)!=384||d.size!==e.length)&&i_(),r(),b(i,this.path)}finally{s!==void 0&&a(s);try{this.checkRoot(t);let e=X(i);c&&e&&op(c,e)&&w(i)}catch{}}}acquireGuard(e){let t=`${this.path}.lock`,n=`owner-${process.pid}-${ce()}`,r=`${this.path}.lock-candidate-${n.slice(6)}`,i,o,s=!1,c=(r,i,a=n,s=o,c=!1)=>{try{if(this.checkRoot(e),!op(i,Z(r,this.uid)))return!1;let n=X(N(r,a));if(n&&(!s||!a_(s,n)))return!1;if(r===t){if(!n||!s)return!1;let e=`${this.path}.lock-candidate-${a.slice(6)}`;if(X(e)||(b(r,e),r=e,!op(i,Z(r,this.uid)))||(n=X(N(r,a)),!n||!a_(s,n)))return!1;if(c)return!0}return n&&w(N(r,a)),x(r),!0}catch{return!1}};try{this.checkRoot(e),m(r,{mode:448}),i=Z(r,this.uid);let u=h(N(r,n),`wx`,384);try{o=l(u)}finally{a(u)}for(let a=0;a<3;a++){if(this.checkRoot(e),X(t)){let e=Z(t,this.uid),n=v(t),r=n[0],i=r&&/^owner-([1-9][0-9]*)-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/.exec(r),a=i&&tp(i[1]);(n.length!==1||!r||!a)&&i_();let o=X(N(t,r));if(lp(N(t,r),0,this.uid),np(a))throw new n_(`busy`);op(e,Z(t,this.uid))||i_();let s=X(N(t,r));(!o||!s||!a_(o,s))&&i_(),c(t,e,r,o,!0)||i_()}try{b(r,t),s=!0;let a=Z(t,this.uid);return op(i,a)||i_(),{assert:()=>{this.checkRoot(e),op(a,Z(t,this.uid))||i_();let r=X(N(t,n));(!r||!o||!a_(o,r))&&i_()},release:()=>c(t,a)}}catch(e){if(![`EEXIST`,`ENOTEMPTY`,`ENOENT`].includes(e.code??``))throw e}}throw new n_(`busy`)}finally{!s&&i&&c(r,i)}}},c_=class extends s_{constructor(e){super({root:e.stateDir,uid:e.uid,filename:`service-owner.json`,maxBytes:16384,schema:Tg})}};function l_(e){if(e?.mode===`desktop`)throw Error(`Service is desktop-owned; use Shellbell or explicitly convert it to headless mode`);if(e?.transition)throw Error(`An ownership conversion needs explicit recovery before headless service changes`)}function u_(e){let t;try{t=new c_({...e,stateDir:sp(e.stateDir)}).inspect()}catch{return null}return t?.mode===`desktop`?`The Shellbell app runs Shellbell on this Mac. Use the app to pair phones and change settings.`:t?.transition?`The Shellbell app is switching how Shellbell runs on this Mac. Open the app to finish, then try again.`:null}function d_(e){let t=m_(new c_({...e,stateDir:sp(e.stateDir)})),n=t?.transition;t?.mode===`headless`&&n?.target===`headless`&&e.serviceInstance===n.id&&[`source-stopped`,`destination-started`].includes(n.phase)||l_(t)}async function f_(e,t){let n=new c_({...e,stateDir:sp(e.stateDir)}),r=m_(n);return l_(r),p_(n,r?.revision??null,async e=>(l_(e.current),t()))}async function p_(e,t,n){let r=!1,i;return e.mutate(t,async e=>{try{return await n(e)}catch(e){throw r=!0,i=e,e}}).catch(e=>{throw r?i:h_(e)})}function m_(e){try{return e.inspect()}catch(e){throw h_(e)}}function h_(e){if(!(e instanceof n_))return e;let t={busy:`shellbell: Another Shellbell change is in progress, such as the Mac app starting or stopping its service. Try again in a moment.`,conflict:"shellbell: Shellbell's service ownership changed while this ran. Check `shellbell status`, then try again.","operation-failed":`shellbell: Shellbell couldn't read or save its service ownership record in its state folder. Check that the folder is yours and has free space, then try again.`,"unsafe-state":`shellbell: Shellbell's state folder has unsafe permissions or ownership; it must belong to you and not be writable by others.`};return t[e.code]?Error(t[e.code]):e}async function g_(e,t){let n=new c_(e),r=m_(n);return l_(r),!e.create&&!r&&!s(e.stateDir)?t():p_(n,r?.revision??null,async n=>{l_(n.current);let r=await t(),i=e.startupPreference?e.startupPreference(r):r.startupEnabled;if(i!==null&&(r.installed||n.current)&&(!n.current||n.current.startupEnabled!==i))try{n.publish({v:1,mode:`headless`,consented:!0,startupEnabled:i,transition:null})}catch(e){throw h_(e)}return r})}function __(e){try{return y(e)}catch(t){if(t.code===`ENOENT`)return P(e);throw Error(`Cannot resolve state directory ${e}`)}}function v_(e,t){try{return e.process.computerFp===t.computerFp&&__(e.process.stateDir)===__(t.stateDir)&&(t.serviceInstance===void 0||e.process.serviceInstance===t.serviceInstance)&&(t.pid===void 0||e.process.pid===t.pid)}catch{return!1}}var y_=class{clock;probe;constructor(e={}){this.clock=e.clock??{now:()=>de.now(),sleep:e=>new Promise(t=>setTimeout(t,e))},this.probe=e.probe??((e,t)=>Yh(e,`status`,void 0,{timeoutMs:t,maxResponseBytes:65536}))}async observe(e,t,n=500){let r;try{r=await this.probe(e,n)}catch(e){let t=e.code;return t===`ENOENT`||t===`ECONNREFUSED`?{kind:`absent`,local:null,diagnostic:`Local endpoint is absent`}:{kind:`unverified`,local:null,diagnostic:`Local endpoint did not return a bounded status response`}}let i=ih.safeParse(r);return i.success?t&&!v_(i.data,t)?{kind:`foreign`,local:i.data,diagnostic:`Local endpoint belongs to a different process, identity, state directory, or service instance`}:{kind:`verified`,local:i.data}:{kind:`unverified`,local:null,diagnostic:`Local endpoint uses an unsupported or malformed status protocol`}}async waitReady(e,t){return(await this.wait(e,t,!1)).local}async waitStopped(e){await this.wait(e,void 0,!0)}async wait(e,t,n){let r=this.clock.now()+1e4,i=`Local endpoint is absent`;for(;this.clock.now()<r;){let a=await this.observe(e,t,Math.min(500,r-this.clock.now()));if(n?a.kind===`absent`:a.kind===`verified`)return a;if(i=a.diagnostic??`Local endpoint is still responding`,!n&&a.kind===`foreign`)throw Error(`Service readiness conflict: ${i}; stop the foreground owner before retrying`);let o=r-this.clock.now();o>0&&await this.clock.sleep(Math.min(100,o))}throw Error(`${n?`Service stop`:`Service readiness`} timed out: ${i}`)}};const b_=new Set([`.npm`,`_npx`,`dlx`]),x_=[[`npm`,`config`,`cache`].join(`_`),`NPM_CONFIG_CACHE`];function S_(e,t){throw Error(`Shellbell service runtime at ${e} ${t}; install a built Shellbell package in a durable directory, then run shellbell install again`)}function C_(e){try{return y(e)}catch{return ne(e)}}function w_(){let e=[k(),`/tmp`,`/private/tmp`,`/var/tmp`,`/private/var/tmp`];for(let t of x_){let n=process.env[t];n&&M(n)&&e.push(n)}return[...new Set(e.flatMap(e=>[ne(e),C_(e)]))]}function T_(e,t){let n=re(t,e);return n===``||n!==`..`&&!n.startsWith(`..${ie}`)&&!M(n)}function E_(e){let t=ne(e);(t.split(ie).some(e=>b_.has(e))||w_().some(e=>T_(t,e)))&&S_(e,`is in a temporary or package-manager cache location`)}function D_(e,t){M(e)||S_(e,`${t} path must be absolute`),E_(e);let n;try{n=y(e)}catch{S_(e,`${t} does not exist`)}return E_(n),(()=>{try{return S(n)}catch{return S_(n,`${t} does not exist`)}})().isFile()||S_(n,`${t} must be a regular file`),n}function O_(e,t,r){try{n(e,t)}catch{S_(e,r)}}function k_(e){let t=`${e}${ie}package.json`,n=(()=>{try{return S(t)}catch{return S_(t,`package.json is missing`)}})();n.isFile()||S_(t,`package.json must be a regular file`),n.size>1048576&&S_(t,`package.json exceeds 1 MiB`);let r;try{r=g(t,`utf8`)}catch{S_(t,`package.json is not readable`)}let i;try{i=JSON.parse(r)}catch{S_(t,`package.json is not valid JSON`)}return(typeof i!=`object`||!i||Array.isArray(i))&&S_(t,`package.json is not a valid manifest`),i}function A_(e){let t=e.bin,n=typeof t==`string`?t:typeof t==`object`&&t&&!Array.isArray(t)?t.shellbell:void 0;return n===`dist/cli.js`||n===`./dist/cli.js`}function j_(e=process.execPath,t=process.argv[1]??``){let n=Number.parseInt(process.versions.node.split(`.`)[0]??``,10);(!Number.isInteger(n)||n<22)&&S_(process.execPath,`requires the currently running Node.js major version to be at least 22`);let r=D_(e,`Node executable`);O_(r,o.X_OK,`Node executable is not executable`);let i=D_(t,`CLI entrypoint`);O_(i,o.R_OK,`CLI entrypoint is not readable`),(A(i)!==`cli.js`||A(j(i))!==`dist`)&&S_(i,`is not an installed built CLI entrypoint`);let a=j(j(i)),c=`${a}${ie}src${ie}cli.ts`;s(c)&&S_(a,`is a source checkout rather than an installed built package`);let l=k_(a);return l.name!==`shellbell`&&S_(`${a}${ie}package.json`,`has the wrong package name`),A_(l)||S_(`${a}${ie}package.json`,`does not declare the Shellbell bin entrypoint`),{nodePath:r,cliPath:i,packageRoot:a}}var M_=class extends Error{rollback=`not-needed`;rollbackDiagnostic;recoveryPath};function N_(e,t,n){let r=e.definition?.stateDir,i=__(r??(t||n));if(r&&t&&__(t)!==i)throw new M_(`SHELLBELL_DIR conflicts with the installed service state directory; state migration is not an implicit install operation`);return Lp(i)}function P_(e){return e instanceof M_?e:new M_(e instanceof Error?e.message.slice(0,600):`Service operation failed`)}async function F_(e,t,n){let r=j(e.definitionPath),i;try{return t&&m(r,{recursive:!0,mode:448}),s(r)&&(i=ap(e.definitionPath)),await n(e)}finally{i?.()}}var I_=class{options;manager;readiness;constructor(e){this.options=e,this.manager=e.manager,this.readiness=new y_(e)}selected(e){return N_(e,this.options.requestedStateDir,this.options.defaultStateDir)}definitionFor(e,t,n){let r=sg({stateDir:t.dir,serviceInstance:n,nodePath:e.nodePath,env:this.options.env}),i={nodePath:e.nodePath,cliPath:e.cliPath,stateDir:t.dir,serviceInstance:n,environment:r,logPath:t.log};for(let e of Object.values(i))typeof e==`string`&&ag(e);for(let[e,t]of Object.entries(r))ag(e),ag(t);return i}expected(e,t){let n=Zh(t);return n?{computerFp:n.fp,stateDir:t.dir,serviceInstance:e.definition?.serviceInstance??null}:void 0}result(e,t,n,r=null,i){let a=e.installed&&e.definition?.serviceInstance===null,o=e.installed&&e.loaded&&!!n&&t.kind===`verified`&&(!a||r!==null),s=i??(n?a&&r===null?`Legacy service cannot be verified by read-only status; run service install to upgrade`:void 0:`Local identity is missing; no keys were created`),c=e.definition&&!e.definition.environment.SHELLBELL_DIR?`Legacy definition assumes the historical ~/.shellbell state directory`:void 0;return{manager:this.manager.kind,definitionPath:this.manager.definitionPath,installed:e.installed,loaded:e.loaded,startupEnabled:e.startupEnabled??null,autostartConfigured:e.installed&&e.startupEnabled===!0,managedPid:r,ownership:t.kind===`foreign`?`foreign`:a&&!o?`legacy`:o?`verified`:`none`,local:t.local,ready:o,...t.diagnostic||s||c?{diagnostic:[t.diagnostic,s,c].filter(Boolean).join(`; `)}:{}}}async installedRuntime(){let{definition:e}=await this.manager.inspect();return e?{nodePath:e.nodePath,cliPath:e.cliPath,stateDir:e.stateDir}:null}async status(){let e=await this.manager.inspect(),t=this.selected(e),n=this.expected(e,t);return this.result(e,await this.readiness.observe(t.sock,n),n)}async serialized(e,t){try{let n=await this.manager.inspect();return await g_({stateDir:sp(this.selected(n).dir),uid:process.getuid(),create:e},()=>F_(this.manager,e,t))}catch(e){throw P_(e)}}assertAvailable(e,t,n){if(t.kind!==`absent`&&!(e.loaded&&e.definition?.serviceInstance===null&&t.kind===`unverified`)&&!(e.loaded&&n&&t.kind===`verified`))throw new M_(`Local endpoint ownership is unverified or foreign; stop the foreground owner before retrying service changes`)}async rollback(e,t,n,r,i){let a=P_(i);if(!r.unloadAttempted&&!r.written&&!r.loaded)throw a;try{if(r.loaded&&await this.manager.unload(),(r.unloadAttempted||r.loaded)&&await this.readiness.waitStopped(t.sock),r.written&&await this.manager.restore(e.raw),e.loaded){let r=await this.manager.load();e.definition?.serviceInstance&&n&&await this.readiness.waitReady(t.sock,{...n,pid:r})}a.rollback=`restored`}catch(t){if(a.rollback=`failed`,a.rollbackDiagnostic=P_(t).message,e.raw){let t=`${this.manager.definitionPath}.recovery-${ce()}`;try{T(t,e.raw,{mode:384,flag:`wx`}),a.recoveryPath=t}catch{a.rollbackDiagnostic+=`; could not save a private recovery definition`}}}throw a}async install(){try{let e=j_(),t=ce();return this.definitionFor(e,Lp(__(this.options.requestedStateDir||this.options.defaultStateDir)),t),await this.serialized(!0,async()=>{let n=await this.manager.inspect(),r=this.selected(n),i=this.definitionFor(e,r,t),a=this.expected(n,r);if(n.installed&&!a)throw new M_(`Installed service identity is missing at ${r.identity}; restore it before upgrading`);this.assertAvailable(n,await this.readiness.observe(r.sock,a),a);let o=Zh(r)??Qh(r);yg(r.log);let s={computerFp:o.fp,stateDir:r.dir,serviceInstance:t},c={unloadAttempted:!1,written:!1,loaded:!1};try{n.loaded&&(c.unloadAttempted=!0,await this.manager.unload(),await this.readiness.waitStopped(r.sock)),c.written=!0,await this.manager.write(i),c.loaded=!0;let e=await this.manager.load(),t=await this.readiness.waitReady(r.sock,{...s,pid:e}),a=await this.manager.inspect();if(!a.loaded)throw Error(`Service unloaded before readiness could be confirmed`);return this.result(a,{kind:`verified`,local:t},s,e)}catch(e){return this.rollback(n,r,a,c,e)}})}catch(e){throw P_(e)}}start(){return this.runInstalled(`start`)}restart(){return this.runInstalled(`restart`)}stop(){return this.runInstalled(`stop`)}enable(){return this.setStartup(!0)}disable(){return this.setStartup(!1)}async setStartup(e){return this.serialized(!1,async()=>{let t=await this.manager.inspect(),n=this.selected(t);if(!t.installed)throw new M_(`Service is not installed; run service install first`);await this.manager.setStartupEnabled(e);let r=await this.manager.inspect();if(r.startupEnabled!==e||r.loaded!==t.loaded)throw new M_(`Startup preference or current execution could not be verified`);let i=this.expected(r,n);return this.result(r,await this.readiness.observe(n.sock,i),i)})}uninstall(){return this.runInstalled(`uninstall`)}runInstalled(e){return this.serialized(!1,async()=>{let t=await this.manager.inspect(),n=this.selected(t),r=e===`stop`||e===`uninstall`,i,a;try{i=this.expected(t,n)}catch(e){if(!r)throw e;a=P_(e).message}let o=await this.readiness.observe(n.sock,i);if(!t.installed){if(!r)throw new M_(`Service is not installed; run service install first`);return this.result(t,o,i,null,a)}if(!r&&!i)throw new M_(`Local identity is missing at ${n.identity}; restore it before starting`);r&&t.loaded&&o.kind===`unverified`||this.assertAvailable(t,o,i);let s={unloadAttempted:!1,written:!1,loaded:!1};try{if(e!==`start`&&t.loaded&&(s.unloadAttempted=!0,await this.manager.unload(),await this.readiness.waitStopped(n.sock)),r){e===`uninstall`&&await this.manager.restore(null);let t=await this.manager.inspect();if(t.loaded)throw Error(`Service remains loaded after stop`);return this.result(t,{kind:`absent`,local:null,diagnostic:e===`stop`?`Service stopped; definition remains and it may start at next login`:`Service uninstalled; identity and pairings remain`},i,null,a)}s.loaded=!t.loaded||e===`restart`;let c=await this.manager.load();if(e===`restart`&&o.local?.process.pid===c)throw Error(`Service restart did not produce a new manager-certified process`);let l=await this.readiness.waitReady(n.sock,{...i,pid:c}),u=await this.manager.inspect();if(!u.loaded)throw Error(`Service unloaded before readiness could be confirmed`);return this.result(u,{kind:`verified`,local:l},i,c)}catch(e){if(r)throw P_(e);return this.rollback(t,n,i,s,e)}})}};export{wm as $,G as $n,Td as $t,Qh as A,ic as An,Y as At,ah as B,Ra as Bn,Qf as Bt,Wg as C,Sc as Cn,Mp as Ct,vg as D,cc as Dn,gp as Dt,bg as E,Fc as En,_p as Et,Q as F,vc as Fn,op as Ft,Bm as G,Rr as Gn,hf as Gt,Jm as H,Dr as Hn,Xf as Ht,Kh as I,yc as In,ap as It,Nm as J,wr as Jn,Od as Jt,zm as K,Er as Kn,nf as Kt,mh as L,uc as Ln,np as Lt,Jh as M,$s as Mn,sp as Mt,Xh as N,nc as Nn,X as Nt,ng as O,pc as On,hp as Ot,Yh as P,dc as Pn,Z as Pt,ym as Q,W as Qn,Pd as Qt,fh as R,oc as Rn,tp as Rt,Fg as S,xc as Sn,Np as St,Cg as T,Ec as Tn,xp as Tt,Um as U,Or as Un,Ff as Ut,qm as V,ba as Vn,Zf as Vt,Im as W,Lr as Wn,gf as Wt,Am as X,rr as Xn,Nd as Xt,Dm as Y,br as Yn,Ld as Yt,km as Z,ir as Zn,Fd as Zt,t_ as _,sl as _n,om as _t,j_ as a,Pu as an,$n as ar,gm as at,zg as b,Bc as bn,kp as bt,c_ as c,Ql as cn,Kn as cr,Xp as ct,f_ as d,au as dn,Rp as dt,Ed as en,ur as er,Cm as et,g_ as f,Au as fn,Jp as ft,Yg as g,Wl as gn,Kp as gt,n_ as h,Bu as hn,Lp as ht,F_ as i,qu as in,tr as ir,_m as it,Zh as j,bc as jn,lp as jt,tg as k,fc as kn,up as kt,u_ as l,Zl as ln,Gn as lr,Gp as lt,Eg as m,Ou as mn,am as mt,M_ as n,bd as nn,U as nr,xm as nt,y_ as o,Fu as on,er as or,um as ot,s_ as p,iu as pn,qp as pt,Pm as q,xr as qn,kd as qt,N_ as r,Sd as rn,Yn as rr,Sm as rt,v_ as s,su as sn,V as sr,cm as st,I_ as t,Dd as tn,nr as tr,bm as tt,d_ as u,ou as un,im as ut,r_ as v,ll as vn,zp as vt,Mg as w,wc as wn,vp as wt,e_ as x,Uc as xn,Ep as xt,Vg as y,ol as yn,Op as yt,ih as z,sc as zn,$f as zt};