shellbell 0.16.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import{C as e,F as t,G as n,I as r,K as i,L as a,Nt as o,R as s,S as c,_ as l,c as u,ct as d,g as f,gt as p,h as m,ht as h,o as g,q as _,ut as v,v as y,w as b,x,zt as S}from"./service-lifecycle-ypi9zEPw.js";import{B as C,H as w,R as T,U as E,W as D,t as O}from"./doctor-BAkCLrvi.js";import{a as k,i as A,o as j,r as M,t as N}from"./service-entry-BeYEy-kj.js";import{spawn as P}from"node:child_process";import{closeSync as F,constants as I,openSync as L,realpathSync as R}from"node:fs";import{userInfo as z}from"node:os";import{dirname as B,join as V,resolve as H}from"node:path";import{fileURLToPath as U}from"node:url";import{createHash as W,randomUUID as G}from"node:crypto";import{performance as K}from"node:perf_hooks";function q(e,t,n,r){let i=!1,o=!1,c=0,u=!1,d=!1,p=!1,h,g,_,v,b=()=>v||(i=!0,clearTimeout(_),w(),e.off(`data`,E),e.off(`end`,D),e.destroy(),v=Promise.resolve(n.close()).finally(()=>{t.end()}),v.catch(()=>{}),v),S=e=>{if(i)return!1;let n=s(e),r=t.writableLength;if(!n||t.destroyed||!Number.isFinite(r)||r<0||r+n.byteLength>262144)return b(),!1;try{t.write(n)}catch{return b(),!1}return!0},C=(e,t)=>S({v:1,id:e,ok:!1,error:{code:t}}),w=n.onEvent(e=>{let t=y.safeParse(e);if(!t.success){b();return}if(p){h?b():h=t.data;return}if(t.data.flowId!==g){b();return}S(t.data),t.data.event===`pairing.closed`&&(g=void 0)}),T=new a({onError:b,onLine(e){if(i)return;let t;try{t=JSON.parse(e)}catch{b();return}let a=x.safeParse(t);if(!a.success){typeof t==`object`&&t&&`id`in t&&typeof t.id==`number`&&Number.isSafeInteger(t.id)&&t.id>c&&C(t.id,`v`in t&&t.v!==1?`unsupported-version`:`bad-request`),b();return}let v=a.data;if(v.id<=c){b();return}if(c=v.id,!o){if(v.cmd!==`hello`){C(v.id,`handshake-required`),b();return}o=!0,clearTimeout(_),S({v:1,id:v.id,ok:!0,data:f.hello.parse({version:1,agentVersion:r.agentVersion,capabilities:[`status`,`settings`,`lifecycle`,`pairing`,`devices`,`diagnostics`]})});return}if(v.cmd===`hello`){b();return}if(u){C(v.id,`busy`),d||b();return}u=!0,d=!1,p=v.cmd===`pairing.open`;let y=`args`in v;_=setTimeout(()=>{if(y){C(v.id,`delivery-unknown`),b();return}d=!0,C(v.id,`timeout`)},y?6e4:5e3),n.execute(v).then(e=>{if(i||d)return;let t=f[v.cmd].safeParse(e);if(!t.success){if(!y){C(v.id,`operation-failed`);return}C(v.id,`delivery-unknown`),b();return}if(v.cmd===`pairing.open`&&(g=t.data.flowId),!s({v:1,id:v.id,ok:!0,data:t.data})){C(v.id,`response-too-large`),b();return}if(S({v:1,id:v.id,ok:!0,data:t.data}),p=!1,h){if(h.flowId!==g){b();return}S(h),h.event===`pairing.closed`&&(g=void 0),h=void 0}},e=>{if(d)return;let t=e instanceof m&&l.safeParse(e.code).success?e.code:`operation-failed`;C(v.id,t),p=!1,h=void 0}).finally(()=>{clearTimeout(_),u=!1,d=!1})}}),E=e=>T.push(e),D=()=>{T.finish(),b()};return e.on(`data`,E),e.once(`end`,D),e.once(`error`,b),t.once(`error`,b),_=setTimeout(b,5e3),{close:b}}var J=class{options;owned;starting;closed=!1;readiness;clock;constructor(e){this.options=e,this.readiness=e.readiness??new g,this.clock=e.clock??{now:()=>K.now(),sleep:e=>new Promise(t=>setTimeout(t,e))}}async inspect(e){let t=this.owned;if(t&&!t.exited&&(t.selection.serviceInstance!==e.serviceInstance||t.selection.bundlePath!==e.bundlePath))throw new m(`conflict`);return{registration:`not-registered`,loaded:!!t&&!t.exited,pid:t&&!t.exited?t.child.pid??null:null,bundlePath:e.bundlePath}}start(e){return this.closed||this.starting||this.owned&&!this.owned.exited?Promise.reject(new m(`busy`)):!c.safeParse(e).success||e.mode!==`desktop`?Promise.reject(new m(`conflict`)):(this.starting=this.launch(structuredClone(e)).finally(()=>{this.starting=void 0}),this.starting)}async launch(e){this.owned&&await this.stopOwned(this.owned);let t=await(this.options.admitBundle??k)(e.bundlePath);if(t.agentVersion!==e.agentVersion||this.closed||(await this.readiness.observe(h(e.stateDir).sock)).kind!==`absent`||this.closed)throw new m(`conflict`);let n=P(t.nodePath,[t.servicePath,`desktop`],{cwd:this.options.homeDir,env:M(e,this.options.homeDir,process.env),stdio:[`ignore`,`pipe`,`pipe`,`pipe`]}),r={child:n,pipe:n.stdio[3],selection:e,exited:!1};this.owned=r,n.once(`exit`,()=>{r.exited=!0}),n.once(`error`,()=>{r.exited=!0}),n.stdout?.resume(),n.stderr?.resume(),r.pipe.on(`error`,()=>{});try{r.pipe.write(`${JSON.stringify({v:1,instance:e.serviceInstance})}\n`);let t=this.clock.now()+1e4;for(;this.clock.now()<t;){if(r.exited||this.closed||!n.pid)throw new m(`unavailable`);let i=await this.readiness.observe(h(e.stateDir).sock,{stateDir:e.stateDir,computerFp:e.computerFp,serviceInstance:e.serviceInstance,pid:n.pid},Math.min(500,t-this.clock.now()));if(i.kind===`verified`&&i.local?.process.agentVersion===e.agentVersion&&!r.exited&&!this.closed)return this.inspect(e);if(i.kind===`foreign`)throw new m(`conflict`);await this.clock.sleep(Math.min(25,Math.max(0,t-this.clock.now())))}throw new m(`unavailable`)}catch(e){throw await this.stopOwned(r),e}}async stop(e){let t=this.owned;if(!t){if(e.runtime)throw new m(`conflict`);return}let n=e.runtime,r=t.selection;if(!n||n.pid!==t.child.pid||n.stateDir!==r.stateDir||n.computerFp!==r.computerFp||n.serviceInstance!==r.serviceInstance||n.agentVersion!==r.agentVersion)throw new m(`conflict`);await this.stopOwned(t)}async close(){this.closed=!0,this.owned&&await this.stopOwned(this.owned),await this.starting?.catch(()=>{}),this.owned&&await this.stopOwned(this.owned)}stopOwned(e){return e.stopping||=this.finishStop(e).finally(()=>{e.stopping=void 0}),e.stopping}async finishStop(e){e.pipe.end();let t=this.options.stopTimeoutMs??1e4,n=this.clock.now()+t,r=n-t/2,i=!1;for(;!e.exited&&this.clock.now()<n;){if(!i&&this.clock.now()>=r){let t=e.selection,r=await this.readiness.observe(h(t.stateDir).sock,{pid:e.child.pid,stateDir:t.stateDir,computerFp:t.computerFp,serviceInstance:t.serviceInstance},Math.min(500,Math.max(1,n-this.clock.now())));if(r.kind===`foreign`)throw new m(`conflict`);r.kind===`verified`&&r.local?.process.agentVersion===t.agentVersion&&this.owned===e&&!e.exited&&(e.child.kill(`SIGTERM`),i=!0)}await this.clock.sleep(Math.min(25,Math.max(0,n-this.clock.now())))}if(!e.exited)throw new m(`unavailable`);if((await this.readiness.observe(h(e.selection.stateDir).sock)).kind!==`absent`)throw new m(`conflict`);e.pipe.destroy(),this.owned===e&&(this.owned=void 0)}};async function Y(e,t,n){await n.preflight();let r=n=>e.publish({v:1,mode:n===`prepared`?e.current?.mode??t.target:t.target,consented:!0,startupEnabled:e.current?.startupEnabled??!1,transition:{...t,phase:n}});e.current?.transition||r(`prepared`);try{await n.stopSource(),await n.verifyAbsent(),r(`source-stopped`),await n.startDestination(),r(`destination-started`),await n.complete(),e.publish({v:1,mode:t.target,consented:!0,startupEnabled:e.current.startupEnabled,transition:null})}catch(e){throw r(`recovery-required`),e}}var X=class{options;desktop;readiness;newId;client;listeners=new Set;observedStateDirs=new WeakMap;closed=!1;constructor(e){this.options=e,this.desktop=e.desktop??new J({uid:e.uid,homeDir:e.homeDir,readiness:e.readiness,admitBundle:e.inspectBundle}),this.readiness=e.readiness??new g,this.newId=e.newId??G}async status(){try{return await this.observe(this.options.store.inspect(),await this.options.platform.inspectLegacy())}catch(e){throw this.error(e)}}stateDirectory(e,t){return this.recordedStateDirectory(e,t)??this.options.defaultStateDir}recordedStateDirectory(e,t){return e?.selection?.stateDir??e?.transition?.destination?.stateDir??e?.transition?.source?.stateDir??t??e?.recovery?.stateDir??null}statusStateDirectory(e){return this.observedStateDirs.get(e)??e.selection?.stateDir??e.legacy.stateDir??this.options.defaultStateDir}async observe(t,n){let r=t?.selection??null,i=r?.bundlePath??t?.transition?.source?.bundlePath??this.options.bundlePath,[a,o,s]=await Promise.all([this.options.platform.inspect(`manual`,i),this.options.platform.inspect(`persistent`,i),this.options.platform.loginStatus(this.options.bundlePath).catch(()=>`unknown`)]),c=this.recordedStateDirectory(t,n.definition?.stateDir),l=c??this.options.defaultStateDir,d=N(l,this.options.uid),f=r?.mode===`desktop`?await this.desktop.inspect(r):{registration:`not-registered`,loaded:!1,pid:null,bundlePath:null},p=r?r.mode===`desktop`?f:b(r.mode)===`manual`?a:o:null,m=d?{stateDir:l,computerFp:d.fp,serviceInstance:r?.serviceInstance??n.definition?.serviceInstance??null,...p?.pid?{pid:p.pid}:{}}:void 0,g=await this.readiness.observe(h(l).sock,m);if(g.kind===`verified`&&(!d||r&&(!p?.loaded||!p.pid||d.fp!==r.computerFp))&&(g.kind=`foreign`),r){let e=r.mode===`desktop`?await this.desktop.inspect(r):await this.options.platform.inspect(b(r.mode),i);JSON.stringify(e)!==JSON.stringify(p)&&(g.kind=`unverified`,g.local=null)}let _=new u({stateDir:l,uid:this.options.uid}).inspect(),v=e.parse({desktopLogin:s,desktop:f,ownership:{revision:_?.revision??null,mode:_?.mode??(r||t?.transition?`legacy-native`:n.installed||n.loaded?`headless`:null),consented:_?.consented??!1,startupEnabled:_?.startupEnabled??null,transition:_?.transition??null},revision:t?.revision??null,selection:r,transition:t?.transition?{id:t.transition.id,action:t.transition.action,phase:t.transition.phase}:null,recoveryAvailable:!!t?.recovery,manualRecoveryAvailable:(t?.transition?.destination?.mode===`persistent`&&r?.serviceInstance===t.transition.destination.serviceInstance&&[`start`,`restart`].includes(t.transition.action)&&!t.transition.restoreLegacy||this.isManualRecovery(t)&&r?.serviceInstance===t?.transition?.source?.serviceInstance)&&!a.loaded&&!o.loaded&&g.kind===`absent`&&!n.installed&&!n.loaded,legacy:{installed:n.installed,loaded:n.loaded,stateDir:n.definition?.stateDir??null},manual:a,persistent:o,local:{kind:g.kind,status:g.local}});return c&&this.observedStateDirs.set(v,c),v}error(e){return e instanceof m?e:e instanceof d?new m(e.code===`busy`?`busy`:e.code===`invalid`?`invalid-config`:`unsafe-state`):e instanceof t?e.code===`server-error`?new m(e.serverCode===`runtime-mismatch`||e.serverCode===`configuration-mismatch`?`conflict`:e.serverCode===`pairing-busy`?`busy`:`operation-failed`):new m(e.code===`protocol-error`||e.code===`closed`?`unavailable`:e.code):new m(`operation-failed`)}exact(e,t){return e===null||t===null?e===t:[`pid`,`agentVersion`,`computerFp`,`stateDir`,`serviceInstance`].every(n=>e[n]===t[n])}expect(e,t,n=!1){if(e.revision!==t.revision||!this.exact(e.local.status?.process??null,t.runtime)||e.local.kind===`foreign`||e.local.kind===`unverified`&&!n)throw new m(`conflict`)}async control(e){let t=e.local.status?.process;if(e.local.kind!==`verified`||!t)throw new m(`unavailable`);if(this.client&&!this.exact(this.client.runtime,t)&&(this.client.close(),this.client=void 0),!this.client){let e=await(this.options.connect??r)(h(t.stateDir).sock,{onPairingRequest:e=>this.emit({...e,v:1}),onPairingClosed:e=>this.emit({...e,v:1}),onDisconnect:()=>{this.client=void 0}});if(this.closed)throw e.close(),new m(`unavailable`);if(!this.exact(e.runtime,t))throw e.close(),new m(`conflict`);this.client=e}return this.client}async settings(e){let t=this.statusStateDirectory(e),r=p(h(t)),i=n(r),a=null;if(e.local.kind===`verified`)try{a=await(await this.control(e)).configurationRevision()}catch{}return{saved:r,savedRevision:i,appliedRevision:a,applied:e.local.kind===`absent`?`not-running`:a===null?`unknown`:a===i?`matches`:`restart-required`}}async execute(e){try{if(this.closed)throw new m(`unavailable`);let t=x.safeParse(e);if(!t.success||t.data.cmd===`hello`)throw new m(`bad-request`);let r=t.data,a;if(r.cmd===`terminals.connect`){let e=await(await this.control(await this.status())).connectTerminal(r.args.name);a=e?{supported:!0,...e}:{supported:!1,started:!1,terminals:[]}}else if(r.cmd===`agents.setup`||r.cmd===`agents.skip`||r.cmd===`agents.remove`){let e=T(this.statusStateDirectory(await this.status()),this.options.homeDir);a={agents:r.cmd===`agents.setup`?E(e,r.args.kinds):r.cmd===`agents.skip`?D(e,r.args.kinds):w(e,r.args.kind)}}else if(`args`in r)a=`ownerRevision`in r.args?await this.ownership(r):await this.guardLegacy(r,e=>this.options.store.mutate(r.args.expect.revision,async t=>this.options.platform.withLegacyGuard(async a=>{let o=await a.inspect(),s=await this.observe(t.current,o);if(r.cmd.startsWith(`service.`)&&(s.ownership?.mode===`desktop`||s.ownership?.transition))throw new m(`conflict`);let c=(r.cmd===`service.start`&&r.args.migrateLegacy||r.cmd===`service.recover`&&r.args.action===`continue`&&t.current?.transition?.source===null&&t.current?.transition?.destination!==null&&!!t.current?.recovery)&&o.loaded&&o.definition?.serviceInstance===null&&s.local.kind===`unverified`;if(this.expect(s,r.args.expect,c),r.cmd.startsWith(`service.`))return this.lifecycle(r,t,a,o,s);if(r.cmd===`settings.set`){let t=this.statusStateDirectory(s);if(t!==e)throw new m(`conflict`);let a=h(t),o=v(a,e=>{if(n(e)!==r.args.configRevision)throw new m(`conflict`);let t=e;for(let n of r.args.changes){if(i(e,n.key)===n.value)continue;let r=_(t,n.key,n.value,!1);if(`error`in r)throw new m(`invalid-config`);t=r.next}return t});if(s.local.kind===`verified`&&r.args.changes.some(e=>e.key===`conversations`))try{await(await this.control(s)).applyConversationSetting(n(o))}catch{}return this.settings(s)}let l=await this.control(s);if(r.cmd===`devices.revoke`)return l.revoke(r.args.phoneFp);if(r.cmd===`pairing.open`)return l.openPairing();if(r.cmd===`pairing.close`)return await l.closePairing(r.args.flowId),{};if(r.cmd===`pairing.confirm`)return await l.confirm(r.args.flowId,r.args.challengeId,r.args.phoneFp,r.args.accept),{};throw new m(`bad-request`)}).catch(e=>{throw this.error(e)})));else{let e=await this.status();if(r.cmd===`status`)a=e;else if(r.cmd===`agents`)a={agents:C(T(this.statusStateDirectory(e),this.options.homeDir))};else if(r.cmd===`settings.get`)a=await this.settings(e);else if(r.cmd===`devices`)a=await(await this.control(e)).devices();else if(r.cmd===`terminals`){let t=await(await this.control(e)).terminals();a={supported:t!==null,terminals:t??[]}}else a={checks:await this.diagnose(e)}}let o=f[r.cmd].safeParse(a);if(!o.success)throw new m(`args`in r?`delivery-unknown`:`operation-failed`);return o.data}catch(e){throw this.error(e)}}async guardLegacy(e,t){let n=await this.status(),r=e.cmd===`settings.set`?this.statusStateDirectory(n):n.selection?.stateDir??n.legacy.stateDir??(e.cmd===`service.start`?e.args.stateDir:void 0)??this.options.defaultStateDir;e.cmd===`service.start`&&!n.selection&&!n.legacy.installed&&(N(r,this.options.uid),await this.requireAbsentDestination(r));let i=new u({stateDir:r,uid:this.options.uid});return i.mutate(i.inspect()?.revision??null,async n=>{if(e.cmd.startsWith(`service.`)&&(n.current?.mode===`desktop`||n.current?.transition))throw new m(`conflict`);return t(r)})}async ownership(e){let t=await this.status();this.expect(t,e.args.expect);let n=this.options.store.inspect();if((n?.revision??null)!==t.revision)throw new m(`conflict`);let r=this.stateDirectory(n,t.legacy.stateDir),i=new u({stateDir:r,uid:this.options.uid});if((e.cmd===`desktop.start`||e.cmd===`desktop.stop`)&&(t.ownership?.mode!==`desktop`||!t.ownership.consented))throw new m(`conflict`);return i.mutate(e.args.ownerRevision,async t=>this.options.store.mutate(e.args.expect.revision,async n=>this.options.platform.withLegacyGuard(async i=>{let a=await i.inspect(),o=await this.observe(n.current,a);if(this.expect(o,e.args.expect),e.cmd===`desktop.login.set`){if(t.current?.mode!==`desktop`||!t.current.consented)throw new m(`conflict`);if(t.current.transition||n.current?.transition)throw new m(`recovery-required`);return await this.options.platform.setLogin(this.options.bundlePath,e.args.enabled),t.publish({...t.current,startupEnabled:e.args.enabled}),this.observe(n.current,await i.inspect())}if(e.cmd===`desktop.stop`){if(o.selection?.mode!==`desktop`)throw new m(`conflict`);if(o.local.kind===`absent`&&!o.desktop?.loaded)return o;if(o.local.kind!==`verified`)throw new m(`conflict`);return await this.desktop.stop(e.args.expect),await this.readiness.waitStopped(h(r).sock),this.observe(n.current,await i.inspect())}if(e.cmd===`desktop.setup`){if(t.current||n.current?.selection||n.current?.transition||a.installed||a.loaded||o.manual.loaded||o.persistent.loaded||o.local.kind!==`absent`)throw new m(`conflict`)}else if(e.cmd===`desktop.start`){if(t.current?.transition||n.current?.transition)throw new m(`recovery-required`);if(t.current?.mode!==`desktop`||!t.current.consented||a.installed||a.loaded||o.manual.loaded||o.persistent.loaded)throw new m(`conflict`);if(o.local.kind===`verified`&&o.selection?.mode===`desktop`&&o.desktop?.loaded)return o;if(o.local.kind!==`absent`)throw new m(`conflict`)}else if(e.cmd===`ownership.recover`){if(!t.current?.transition||t.current.transition.id!==e.args.intentId)throw new m(`conflict`)}else if(t.current?.transition)throw new m(`recovery-required`);let s=e.cmd===`ownership.recover`,l=s?t.current.transition.target:e.cmd===`ownership.convert`?e.args.target:`desktop`;if(l===`headless`)return this.convertToHeadless(t,n,i,a,o,r,s);if(await this.admitBundle(this.options.bundlePath),[`foreign`,`unverified`].includes(o.local.kind))throw new m(`conflict`);let u=N(r,this.options.uid,e.cmd===`desktop.setup`);if(!u)throw new m(`unsafe-state`);let d=s&&n.current?.transition?.id===t.current?.transition?.id?n.current.transition:null,f=s&&!n.current?.transition&&n.current?.selection?.mode===`desktop`?n.current.selection:null,p=f?null:d?d.source:n.current?.selection??null,g=s?t.current.transition:{id:this.newId(),source:o.ownership?.mode??null,target:l,sourceManager:p?p.mode===`desktop`?`desktop-child`:p.mode===`manual`?`native-manual`:`native-persistent`:a.installed||a.loaded?`launchd`:null,sourceInstance:p?.serviceInstance??a.definition?.serviceInstance??null,stateDir:r,computerFp:u.fp,targetBundlePath:this.options.bundlePath,targetVersion:this.options.agentVersion,phase:`prepared`};if(g.stateDir!==r||g.computerFp!==u.fp||g.targetBundlePath!==this.options.bundlePath||g.targetVersion!==this.options.agentVersion)throw new m(`conflict`);let _=this.newId(),v=p?.environment??a.definition?.environment,y=f??d?.destination??{mode:`desktop`,stateDir:r,computerFp:u.fp,serviceInstance:_,bundlePath:this.options.bundlePath,bundleId:`sh.bilal.shellbell.host`,agentVersion:this.options.agentVersion,environment:{PATH:v?.PATH??`/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin`,...v?.HERDR_SOCKET_PATH?{HERDR_SOCKET_PATH:v.HERDR_SOCKET_PATH}:{},...v?.XDG_CONFIG_HOME?{XDG_CONFIG_HOME:v.XDG_CONFIG_HOME}:{},SHELLBELL_DIR:r,SHELLBELL_SERVICE_INSTANCE:_}};if(y.mode!==`desktop`||y.computerFp!==u.fp||y.stateDir!==r||y.bundlePath!==g.targetBundlePath||y.agentVersion!==g.targetVersion)throw new m(`conflict`);let b=async()=>{let e=await this.observe(n.current,await i.inspect());return e.selection?.serviceInstance===y.serviceInstance&&e.local.kind===`verified`&&!!e.desktop?.loaded&&!e.manual.loaded&&!e.persistent.loaded&&!e.legacy.installed&&!e.legacy.loaded};return await Y(t,g,{preflight:async()=>{if(!c.safeParse(y).success)throw new m(`unsafe-state`);await this.admitBundle(y.bundlePath)},stopSource:async()=>{if(g.source===`headless`&&t.current?.startupEnabled&&await this.options.platform.setLogin(this.options.bundlePath,!0),!d){let e=n.current?.recovery??null;if(a.installed){if(!a.raw||!a.definition||e&&s)throw new m(`recovery-required`);e={id:this.newId(),definitionPath:i.definitionPath,rawBase64:a.raw.toString(`base64`),sha256:W(`sha256`).update(a.raw).digest(`hex`),wasLoaded:a.loaded,stateDir:r,computerFp:u.fp}}this.publish(n,{recovery:e,transition:{id:g.id,action:`start`,phase:`prepared`,source:p,destination:y,recoveryId:e?.id??null}})}if(await b())return;if(p){if(p.stateDir!==r||p.computerFp!==u.fp)throw new m(`conflict`);if(p.mode===`desktop`){let e=await this.observe(n.current,await i.inspect());if(e.desktop?.loaded){if(e.local.kind!==`verified`)throw new m(`conflict`);await this.desktop.stop({revision:e.revision,runtime:e.local.status.process})}}else{let e=await this.options.platform.inspect(p.mode,p.bundlePath),t=p.mode===`persistent`&&!e.loaded;t?await this.options.platform.prepareManualRecovery(p):(e.loaded||e.registration!==`not-registered`)&&await this.options.platform.stop(p,e),await this.readiness.waitStopped(h(r).sock),t||await this.options.platform.remove(p)}}let e=await i.inspect();if(e.installed||e.loaded){let t=n.current?.recovery;if(!t||!e.raw||W(`sha256`).update(e.raw).digest(`hex`)!==t.sha256)throw new m(`conflict`);e.loaded&&await i.unload(),await this.readiness.waitStopped(h(r).sock);let a=await i.inspect();if(a.loaded||!a.raw?.equals(e.raw))throw new m(`conflict`);await i.restore(null)}},verifyAbsent:async()=>{if(await b())return;let e=await this.observe(n.current,await i.inspect());if(e.manual.loaded||e.persistent.loaded||e.legacy.installed||e.legacy.loaded||e.desktop?.loaded||e.local.kind!==`absent`)throw new m(`conflict`);this.phase(n,`source-stopped`,{selection:null})},startDestination:async()=>{await b()||(this.phase(n,`destination-start-requested`,{selection:y}),await this.desktop.start(y),await this.certify(y),this.phase(n,`destination-ready`))},complete:async()=>{this.publish(n,{selection:y,transition:null})}}),this.observe(n.current,await i.inspect())})))}async convertToHeadless(e,t,n,r,i,a,s){if(!s&&e.current?.mode===`headless`&&!t.current?.selection&&!t.current?.transition)return i;if([`foreign`,`unverified`].includes(i.local.kind))throw new m(`conflict`);await this.admitBundle(this.options.bundlePath);let c=await(this.options.inspectBundle??k)(this.options.bundlePath),l=N(a,this.options.uid);if(!l)throw new m(`unsafe-state`);let u=s&&t.current?.transition?.id===e.current?.transition?.id?t.current.transition:null,d=u?u.source:t.current?.selection??null,f=s?e.current.transition:{id:this.newId(),source:i.ownership?.mode??null,target:`headless`,sourceManager:d?.mode===`desktop`?`desktop-child`:d?.mode===`manual`?`native-manual`:d?.mode===`persistent`?`native-persistent`:null,sourceInstance:d?.serviceInstance??null,stateDir:a,computerFp:l.fp,targetBundlePath:this.options.bundlePath,targetVersion:this.options.agentVersion,phase:`prepared`};if(f.target!==`headless`||f.stateDir!==a||f.computerFp!==l.fp||f.targetBundlePath!==this.options.bundlePath||f.targetVersion!==this.options.agentVersion)throw new m(`conflict`);let p=d?.environment??(s&&r.definition?.serviceInstance===f.id?r.definition.environment:void 0),g={nodePath:c.nodePath,cliPath:V(this.options.bundlePath,`Contents/Resources/agent/dist/cli.js`),stateDir:a,serviceInstance:f.id,logPath:h(a).log,environment:{PATH:p?.PATH??`/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin`,SHELLBELL_DIR:a,SHELLBELL_SERVICE_INSTANCE:f.id,...p?.HERDR_SOCKET_PATH?{HERDR_SOCKET_PATH:p.HERDR_SOCKET_PATH}:{},...p?.XDG_CONFIG_HOME?{XDG_CONFIG_HOME:p.XDG_CONFIG_HOME}:{}}},_=e=>{let t=e.definition;return e.installed&&!!t&&t.serviceInstance===f.id&&t.stateDir===a&&t.nodePath===g.nodePath&&t.cliPath===g.cliPath&&t.logPath===g.logPath&&JSON.stringify(Object.entries(t.environment).sort())===JSON.stringify(Object.entries(g.environment).sort())},v={stateDir:a,computerFp:l.fp,serviceInstance:f.id},y=async()=>{let e=await n.inspect();if(!_(e)||!e.loaded||(await this.readiness.observe(h(a).sock,v)).kind!==`verified`)return!1;let t=await n.inspect();return _(t)&&t.loaded};return await Y(e,f,{preflight:async()=>{if((r.installed||r.loaded)&&(!s||!_(r))||r.loaded&&(i.manual.loaded||i.persistent.loaded||d?.mode===`desktop`&&(await this.desktop.inspect(d)).loaded)||d&&(d.stateDir!==a||d.computerFp!==l.fp)||i.manual.loaded&&d?.mode!==`manual`||i.persistent.loaded&&d?.mode!==`persistent`)throw new m(`conflict`)},stopSource:async()=>{this.publish(t,{transition:{id:f.id,action:`recover`,phase:`prepared`,source:d,destination:null,recoveryId:t.current?.recovery?.id??null}});let e=await this.options.platform.loginStatus(this.options.bundlePath);if(e===`unknown`)throw new m(`unavailable`);if((e===`enabled`||e===`requires-approval`)&&await this.options.platform.setLogin(this.options.bundlePath,!1),!await y()){if(d?.mode===`desktop`){let e=await this.desktop.inspect(d);if(e.loaded){let n=await this.readiness.observe(h(a).sock,{stateDir:a,computerFp:l.fp,serviceInstance:d.serviceInstance,...e.pid?{pid:e.pid}:{}});if(n.kind!==`verified`)throw new m(`conflict`);await this.desktop.stop({revision:t.current?.revision??null,runtime:n.local.process})}}else if(d){let e=await this.options.platform.inspect(d.mode,d.bundlePath),t=d.mode===`persistent`&&!e.loaded;t&&await this.options.platform.prepareManualRecovery(d),(e.loaded||e.registration!==`not-registered`)&&await this.options.platform.stop(d,e),await this.readiness.waitStopped(h(a).sock),t||await this.options.platform.remove(d)}}},verifyAbsent:async()=>{if(await y())return;let e=await this.observe(t.current,await n.inspect()),r=await n.inspect();if(e.manual.loaded||e.persistent.loaded||e.desktop?.loaded||r.loaded||r.installed&&!_(r)||e.local.kind!==`absent`)throw new m(`conflict`);this.phase(t,`source-stopped`,{selection:null})},startDestination:async()=>{if(await y())return;if(await this.admitBundle(this.options.bundlePath),N(a,this.options.uid)?.fp!==l.fp)throw new m(`unsafe-state`);o(g.logPath)||F(L(g.logPath,I.O_WRONLY|I.O_CREAT|I.O_EXCL|I.O_NOFOLLOW,384)),this.phase(t,`destination-start-requested`,{selection:null});let r=await n.inspect();if(!_(r)){if(r.installed||r.loaded)throw new m(`conflict`);await n.write(g)}await n.setStartupEnabled(e.current.startupEnabled);let i=await n.load();if(await this.readiness.waitReady(h(a).sock,{...v,pid:i}),!await y())throw new m(`conflict`);this.phase(t,`destination-ready`)},complete:async()=>{this.publish(t,{selection:null,transition:null})}}),this.observe(t.current,await n.inspect())}async diagnose(e){return this.options.diagnose?this.options.diagnose(this.statusStateDirectory(e)):[{name:`local-owner`,ok:e.local.kind===`verified`,severity:e.local.kind===`foreign`?`error`:e.local.kind===`verified`?`pass`:`warning`,detail:e.local.kind},{name:`legacy-service`,ok:!e.legacy.loaded,severity:e.legacy.loaded?`warning`:`pass`,detail:e.legacy.loaded?`Legacy service loaded`:`Legacy service stopped`},O(this.statusStateDirectory(e),this.options.homeDir)]}publish(e,t){return e.publish({v:1,selection:null,transition:null,recovery:null,...e.current,...t})}phase(e,t,n={}){let r=e.current?.transition;if(!r)throw new m(`recovery-required`);return this.publish(e,{...n,transition:{...r,phase:t}})}async admitBundle(e,t=this.options.agentVersion){let n=await(this.options.inspectBundle??k)(e);if(n.agentVersion!==t)throw new m(`upgrade-required`);return n}async lifecycle(e,t,n,r,i){if(e.cmd===`service.recover`)return this.recover(e,t,n,r,i);if(t.current?.transition)throw new m(`recovery-required`);let a=t.current?.selection??null;if(i.manual.loaded&&a?.mode!==`manual`||i.persistent.loaded&&a?.mode!==`persistent`||a&&r.loaded||e.cmd!==`service.start`&&!a||e.cmd===`service.start`&&a&&b(a.mode)===e.args.mode&&a.bundlePath===this.options.bundlePath&&i[b(a.mode)].loaded||r.installed&&(e.cmd!==`service.start`||!e.args.migrateLegacy))throw new m(`conflict`);let o=null;if(e.cmd===`service.start`||e.cmd===`service.restart`){await this.admitBundle(this.options.bundlePath),await this.options.platform.preflight(e.cmd===`service.start`?e.args.mode:b(a.mode),this.options.bundlePath);let t=a?.stateDir??r.definition?.stateDir??(e.cmd===`service.start`?e.args.stateDir:void 0)??this.options.defaultStateDir;if(e.cmd===`service.start`&&e.args.stateDir&&e.args.stateDir!==t)throw new m(`conflict`);!a&&!r.installed&&(N(t,this.options.uid),await this.requireAbsentDestination(t));let n=N(t,this.options.uid,!0),i=this.newId();o={mode:e.cmd===`service.start`?e.args.mode:a.mode,stateDir:t,computerFp:n.fp,serviceInstance:i,bundlePath:this.options.bundlePath,bundleId:`sh.bilal.shellbell.host`,agentVersion:this.options.agentVersion,environment:{PATH:`/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin`,SHELLBELL_DIR:t,SHELLBELL_SERVICE_INSTANCE:i}}}let s=t.current?.recovery??null;if(r.installed){if(!r.raw||!r.definition||s)throw new m(`recovery-required`);let e=N(r.definition.stateDir,this.options.uid);if(!e)throw new m(`unsafe-state`);s={id:this.newId(),definitionPath:n.definitionPath,rawBase64:r.raw.toString(`base64`),sha256:W(`sha256`).update(r.raw).digest(`hex`),wasLoaded:r.loaded,stateDir:r.definition.stateDir,computerFp:e.fp}}this.publish(t,{recovery:s,transition:{id:this.newId(),action:e.cmd.slice(8),phase:`prepared`,source:a,destination:o,recoveryId:s?.id??null}});try{return await this.advance(t,n,r,i)}catch(e){throw this.phase(t,`recovery-required`),e}}async stopSource(e,t,n,r){let i=e.current.transition,a=i.source;if(this.phase(e,`source-stop-requested`),a){try{await this.admitBundle(a.bundlePath,a.agentVersion)}catch{throw new m(`recovery-required`)}let e=r[b(a.mode)];(e.loaded||e.registration!==`not-registered`)&&await this.options.platform.stop(a,e),await this.readiness.waitStopped(h(a.stateDir).sock);let t=await this.options.platform.inspect(b(a.mode),a.bundlePath);if(t.loaded||b(a.mode)===`persistent`&&t.registration!==`not-registered`)throw new m(`operation-failed`)}else if(n.installed){n.loaded&&await t.unload(),await this.readiness.waitStopped(h(n.definition.stateDir).sock);let e=await t.inspect();if(e.loaded||!e.raw?.equals(n.raw))throw new m(`conflict`)}else if(r.local.kind!==`absent`)throw new m(`conflict`);if(this.phase(e,`source-stopped`,{selection:i.action===`stop`?a:null}),a&&i.destination&&(b(a.mode)!==b(i.destination.mode)||a.bundlePath!==i.destination.bundlePath)&&await this.options.platform.remove(a),n.installed){await t.restore(null);let e=await t.inspect();if(e.installed||e.loaded)throw new m(`operation-failed`)}}async advance(e,t,n,r){let i=e.current.transition;return await this.stopSource(e,t,n,r),i.destination?await this.startDestination(e,i.destination):i.action===`remove`&&i.source&&(await this.options.platform.remove(i.source),this.publish(e,{selection:null})),e.current.transition?.phase!==`awaiting-approval`&&this.publish(e,{transition:null}),this.observe(e.current,await t.inspect())}async startDestination(e,t){if(await this.admitBundle(t.bundlePath),N(t.stateDir,this.options.uid)?.fp!==t.computerFp)throw new m(`unsafe-state`);if(await this.requireAbsentDestination(t.stateDir),this.phase(e,`destination-start-requested`,{selection:t}),(await this.options.platform.start(t)).registration===`requires-approval`){this.phase(e,`awaiting-approval`);return}await this.certify(t),this.phase(e,`destination-ready`)}async requireAbsentDestination(e){if((await this.readiness.observe(h(e).sock)).kind!==`absent`)throw new m(`conflict`)}async certify(e){let t=e.mode===`desktop`?await this.desktop.inspect(e):await this.options.platform.inspect(b(e.mode),e.bundlePath);if(!t.loaded||!t.pid)throw new m(`operation-failed`);let n=await this.readiness.waitReady(h(e.stateDir).sock,{computerFp:e.computerFp,stateDir:e.stateDir,serviceInstance:e.serviceInstance,pid:t.pid}),r=e.mode===`desktop`?await this.desktop.inspect(e):await this.options.platform.inspect(b(e.mode),e.bundlePath);if(JSON.stringify(t)!==JSON.stringify(r)||n.process.agentVersion!==e.agentVersion)throw new m(`conflict`)}isManualRecovery(e){let t=e?.transition;return t?.action===`recover`&&!t.restoreLegacy&&t.source?.mode===`persistent`&&t.destination?.mode===`manual`&&t.source.stateDir===t.destination.stateDir&&t.source.computerFp===t.destination.computerFp}async recover(e,t,n,r,i){let a=t.current;if(!a||i.manual.loaded&&i.persistent.loaded||a.selection&&r.loaded||a.selection&&i[b(a.selection.mode)===`manual`?`persistent`:`manual`].loaded)throw new m(`conflict`);if(e.args.action===`discard-backup`){if(a.transition||!a.recovery||r.installed&&r.raw?.toString(`base64`)!==a.recovery.rawBase64)throw new m(`conflict`);return this.publish(t,{recovery:null}),this.observe(t.current,r)}let o=a.recovery,s=o?Buffer.from(o.rawBase64,`base64`):null;if(o&&(!s||W(`sha256`).update(s).digest(`hex`)!==o.sha256)||o&&(o.definitionPath!==n.definitionPath||N(o.stateDir,this.options.uid)?.fp!==o.computerFp))throw new m(`unsafe-state`);if(o&&r.installed&&!r.raw?.equals(s))throw new m(`conflict`);let c=this.isManualRecovery(a);if(e.args.action===`use-manual`||e.args.action===`continue`&&c){let e=c?a.transition?.source:a.transition?.destination;if(e?.mode!==`persistent`||a.transition?.restoreLegacy||!c&&![`start`,`restart`].includes(a.transition.action)||a.selection?.serviceInstance!==e.serviceInstance||i.manual.loaded||i.persistent.loaded||i.local.kind!==`absent`||r.installed||r.loaded)throw new m(`conflict`);if(await this.admitBundle(this.options.bundlePath),await this.options.platform.preflight(`manual`,this.options.bundlePath),N(e.stateDir,this.options.uid)?.fp!==e.computerFp)throw new m(`unsafe-state`);let o=this.newId(),s=c?a.transition.destination:{...e,mode:`manual`,bundlePath:this.options.bundlePath,agentVersion:this.options.agentVersion,serviceInstance:o,environment:{...e.environment,SHELLBELL_SERVICE_INSTANCE:o}};c||this.publish(t,{transition:{id:this.newId(),action:`recover`,phase:`prepared`,source:e,destination:s,recoveryId:a.recovery?.id??null}});try{await this.options.platform.prepareManualRecovery(e),await this.requireAbsentDestination(e.stateDir);let r=await this.observe(t.current,await n.inspect());if(r.manual.loaded||r.persistent.loaded||r.legacy.installed||r.legacy.loaded||r.local.kind!==`absent`)throw new m(`conflict`);return this.publish(t,{selection:null,transition:{id:this.newId(),action:`start`,phase:`source-stopped`,source:null,destination:s,recoveryId:a.recovery?.id??null}}),await this.startDestination(t,s),this.publish(t,{transition:null}),this.observe(t.current,await n.inspect())}catch(e){throw this.phase(t,`recovery-required`),e}}if(e.args.action===`continue`&&a.transition?.action===`recover`&&!a.transition.restoreLegacy)throw new m(`recovery-required`);try{if(e.args.action===`restore-legacy`||a.transition?.restoreLegacy){if(!o||!s)throw new m(`conflict`);if(e.args.action===`restore-legacy`){if(r.loaded)throw new m(`conflict`);this.publish(t,{transition:{id:this.newId(),action:`recover`,phase:`prepared`,source:a.selection,destination:null,recoveryId:o.id,restoreLegacy:{restartPrevious:e.args.restartPrevious}}})}return await this.restoreLegacy(t,n,r,i,s)}let c=a.transition;if(!c)throw new m(`conflict`);let l=c.destination;if(l&&a.selection?.serviceInstance===l.serviceInstance){let e=i[b(l.mode)];if(r.loaded||i[b(l.mode)===`manual`?`persistent`:`manual`].loaded)throw new m(`conflict`);if(e.registration===`requires-approval`)return this.phase(t,`awaiting-approval`),this.observe(t.current,r);if(e.loaded)await this.certify(l),this.phase(t,`destination-ready`);else{if(i.local.kind!==`absent`)throw new m(`conflict`);await this.startDestination(t,l)}return t.current.transition?.phase!==`awaiting-approval`&&this.publish(t,{transition:null}),this.observe(t.current,await n.inspect())}return await this.advance(t,n,r,i)}catch(e){throw t.current?.transition&&this.phase(t,`recovery-required`),e}}async restoreLegacy(e,t,n,r,i){let a=e.current,o=a.recovery,s=a.transition.restoreLegacy;if(n.loaded){if(!s.restartPrevious||a.selection||r.manual.loaded||r.persistent.loaded||r.local.kind!==`verified`||!n.raw?.equals(i))throw new m(`conflict`);let o=await t.inspect();if(!o.loaded||!o.raw?.equals(i))throw new m(`conflict`);return this.publish(e,{selection:null,transition:null}),this.observe(e.current,o)}if(a.selection)await this.stopSource(e,t,{installed:!1,loaded:!1,raw:null,definition:null},r);else if(r.manual.loaded||r.persistent.loaded||r.local.kind!==`absent`)throw new m(`conflict`);await this.readiness.waitStopped(h(o.stateDir).sock),this.phase(e,`source-stopped`,{selection:null}),n.installed||await t.restore(i);let c=await t.inspect();if(!c.raw?.equals(i)||c.loaded)throw new m(`operation-failed`);if(s.restartPrevious){this.phase(e,`destination-start-requested`);let n=await t.load();await this.readiness.waitReady(h(o.stateDir).sock,{computerFp:o.computerFp,stateDir:o.stateDir,serviceInstance:c.definition?.serviceInstance??null,pid:n});let r=await t.inspect();if(!r.loaded||!r.raw?.equals(i))throw new m(`conflict`)}return this.publish(e,{selection:null,transition:null}),this.observe(e.current,await t.inspect())}emit(e){for(let t of this.listeners)t(e)}onEvent(e){return this.listeners.add(e),()=>this.listeners.delete(e)}async close(){this.closed=!0,this.client?.close(),this.client=void 0,this.listeners.clear(),await this.desktop.close()}};async function Z(){if(process.argv.length===3&&[`--help`,`--version`].includes(process.argv[2])){process.stdout.write(process.argv[2]===`--version`?`${S}\n`:`Shellbell native controller
3
- `);return}if(process.argv.length!==2||process.execArgv.length||process.env.NODE_OPTIONS||process.env.NODE_PATH)throw Error();let e=z();if(process.platform!==`darwin`||e.uid<=0)throw Error();let t=H(B(U(import.meta.url)),`../../../..`);if((await k(t)).agentVersion!==S)throw Error();let n=V(e.homedir,`Library/Application Support/Shellbell`),r=new X({store:new A({root:n,uid:e.uid}),platform:j({root:n,uid:e.uid,homeDir:e.homedir}),bundlePath:t,uid:e.uid,homeDir:e.homedir,agentVersion:S,defaultStateDir:V(e.homedir,`.shellbell`)}),i=q(process.stdin,process.stdout,r,{agentVersion:S}),a=()=>{i.close().catch(()=>{process.exitCode=1})};process.once(`SIGTERM`,a),process.once(`SIGINT`,a)}process.argv[1]&&R(process.argv[1])===U(import.meta.url)&&Z().catch(()=>{process.stderr.write(`Shellbell controller unavailable
2
+ import{Bt as e,C as t,F as n,G as r,I as i,K as a,L as o,P as s,Pt as c,S as l,_ as u,_t as d,c as f,ct as p,dt as m,g as h,gt as g,h as _,o as v,q as y,v as b,w as x,x as S}from"./service-lifecycle-Dbs2mdix.js";import{B as C,H as w,R as T,U as E,W as D,t as O}from"./doctor-D4mZwQ1N.js";import{a as k,i as A,o as j,r as M,t as N}from"./service-entry-B036lDNH.js";import{spawn as P}from"node:child_process";import{closeSync as F,constants as I,openSync as L,realpathSync as R}from"node:fs";import{userInfo as z}from"node:os";import{dirname as B,join as V,resolve as H}from"node:path";import{fileURLToPath as U}from"node:url";import{createHash as W,randomUUID as G}from"node:crypto";import{performance as K}from"node:perf_hooks";function q(e,t,n,r){let a=!1,s=!1,c=0,l=!1,d=!1,f=!1,p,m,g,v,y=()=>v||(a=!0,clearTimeout(g),w(),e.off(`data`,E),e.off(`end`,D),e.destroy(),v=Promise.resolve(n.close()).finally(()=>{t.end()}),v.catch(()=>{}),v),x=e=>{if(a)return!1;let n=o(e),r=t.writableLength;if(!n||t.destroyed||!Number.isFinite(r)||r<0||r+n.byteLength>262144)return y(),!1;try{t.write(n)}catch{return y(),!1}return!0},C=(e,t)=>x({v:1,id:e,ok:!1,error:{code:t}}),w=n.onEvent(e=>{let t=b.safeParse(e);if(!t.success){y();return}if(f){p?y():p=t.data;return}if(t.data.flowId!==m){y();return}x(t.data),t.data.event===`pairing.closed`&&(m=void 0)}),T=new i({onError:y,onLine(e){if(a)return;let t;try{t=JSON.parse(e)}catch{y();return}let i=S.safeParse(t);if(!i.success){typeof t==`object`&&t&&`id`in t&&typeof t.id==`number`&&Number.isSafeInteger(t.id)&&t.id>c&&C(t.id,`v`in t&&t.v!==1?`unsupported-version`:`bad-request`),y();return}let v=i.data;if(v.id<=c){y();return}if(c=v.id,!s){if(v.cmd!==`hello`){C(v.id,`handshake-required`),y();return}s=!0,clearTimeout(g),x({v:1,id:v.id,ok:!0,data:h.hello.parse({version:1,agentVersion:r.agentVersion,capabilities:[`status`,`settings`,`lifecycle`,`pairing`,`devices`,`diagnostics`]})});return}if(v.cmd===`hello`){y();return}if(l){C(v.id,`busy`),d||y();return}l=!0,d=!1,f=v.cmd===`pairing.open`;let b=`args`in v;g=setTimeout(()=>{if(b){C(v.id,`delivery-unknown`),y();return}d=!0,C(v.id,`timeout`)},b?6e4:5e3),n.execute(v).then(e=>{if(a||d)return;let t=h[v.cmd].safeParse(e);if(!t.success){if(!b){C(v.id,`operation-failed`);return}C(v.id,`delivery-unknown`),y();return}if(v.cmd===`pairing.open`&&(m=t.data.flowId),!o({v:1,id:v.id,ok:!0,data:t.data})){C(v.id,`response-too-large`),y();return}if(x({v:1,id:v.id,ok:!0,data:t.data}),f=!1,p){if(p.flowId!==m){y();return}x(p),p.event===`pairing.closed`&&(m=void 0),p=void 0}},e=>{if(d)return;let t=e instanceof _&&u.safeParse(e.code).success?e.code:`operation-failed`;C(v.id,t),f=!1,p=void 0}).finally(()=>{clearTimeout(g),l=!1,d=!1})}}),E=e=>T.push(e),D=()=>{T.finish(),y()};return e.on(`data`,E),e.once(`end`,D),e.once(`error`,y),t.once(`error`,y),g=setTimeout(y,5e3),{close:y}}var J=class{options;owned;starting;closed=!1;readiness;clock;constructor(e){this.options=e,this.readiness=e.readiness??new v,this.clock=e.clock??{now:()=>K.now(),sleep:e=>new Promise(t=>setTimeout(t,e))}}async inspect(e){let t=this.owned;if(t&&!t.exited&&(t.selection.serviceInstance!==e.serviceInstance||t.selection.bundlePath!==e.bundlePath))throw new _(`conflict`);return{registration:`not-registered`,loaded:!!t&&!t.exited,pid:t&&!t.exited?t.child.pid??null:null,bundlePath:e.bundlePath}}start(e){return this.closed||this.starting||this.owned&&!this.owned.exited?Promise.reject(new _(`busy`)):!l.safeParse(e).success||e.mode!==`desktop`?Promise.reject(new _(`conflict`)):(this.starting=this.launch(structuredClone(e)).finally(()=>{this.starting=void 0}),this.starting)}async launch(e){this.owned&&await this.stopOwned(this.owned);let t=await(this.options.admitBundle??k)(e.bundlePath);if(t.agentVersion!==e.agentVersion||this.closed||(await this.readiness.observe(g(e.stateDir).sock)).kind!==`absent`||this.closed)throw new _(`conflict`);let n=P(t.nodePath,[t.servicePath,`desktop`],{cwd:this.options.homeDir,env:M(e,this.options.homeDir,process.env),stdio:[`ignore`,`pipe`,`pipe`,`pipe`]}),r={child:n,pipe:n.stdio[3],selection:e,exited:!1};this.owned=r,n.once(`exit`,()=>{r.exited=!0}),n.once(`error`,()=>{r.exited=!0}),n.stdout?.resume(),n.stderr?.resume(),r.pipe.on(`error`,()=>{});try{r.pipe.write(`${JSON.stringify({v:1,instance:e.serviceInstance})}\n`);let t=this.clock.now()+1e4;for(;this.clock.now()<t;){if(r.exited||this.closed||!n.pid)throw new _(`unavailable`);let i=await this.readiness.observe(g(e.stateDir).sock,{stateDir:e.stateDir,computerFp:e.computerFp,serviceInstance:e.serviceInstance,pid:n.pid},Math.min(500,t-this.clock.now()));if(i.kind===`verified`&&i.local?.process.agentVersion===e.agentVersion&&!r.exited&&!this.closed)return this.inspect(e);if(i.kind===`foreign`)throw new _(`conflict`);await this.clock.sleep(Math.min(25,Math.max(0,t-this.clock.now())))}throw new _(`unavailable`)}catch(e){throw await this.stopOwned(r),e}}async stop(e){let t=this.owned;if(!t){if(e.runtime)throw new _(`conflict`);return}let n=e.runtime,r=t.selection;if(!n||n.pid!==t.child.pid||n.stateDir!==r.stateDir||n.computerFp!==r.computerFp||n.serviceInstance!==r.serviceInstance||n.agentVersion!==r.agentVersion)throw new _(`conflict`);await this.stopOwned(t)}async close(){this.closed=!0,this.owned&&await this.stopOwned(this.owned),await this.starting?.catch(()=>{}),this.owned&&await this.stopOwned(this.owned)}stopOwned(e){return e.stopping||=this.finishStop(e).finally(()=>{e.stopping=void 0}),e.stopping}async finishStop(e){e.pipe.end();let t=this.options.stopTimeoutMs??1e4,n=this.clock.now()+t,r=n-t/2,i=!1;for(;!e.exited&&this.clock.now()<n;){if(!i&&this.clock.now()>=r){let t=e.selection,r=await this.readiness.observe(g(t.stateDir).sock,{pid:e.child.pid,stateDir:t.stateDir,computerFp:t.computerFp,serviceInstance:t.serviceInstance},Math.min(500,Math.max(1,n-this.clock.now())));if(r.kind===`foreign`)throw new _(`conflict`);r.kind===`verified`&&r.local?.process.agentVersion===t.agentVersion&&this.owned===e&&!e.exited&&(e.child.kill(`SIGTERM`),i=!0)}await this.clock.sleep(Math.min(25,Math.max(0,n-this.clock.now())))}if(!e.exited)throw new _(`unavailable`);if((await this.readiness.observe(g(e.selection.stateDir).sock)).kind!==`absent`)throw new _(`conflict`);e.pipe.destroy(),this.owned===e&&(this.owned=void 0)}};async function Y(e,t,n){await n.preflight();let r=n=>e.publish({v:1,mode:n===`prepared`?e.current?.mode??t.target:t.target,consented:!0,startupEnabled:e.current?.startupEnabled??!1,transition:{...t,phase:n}});e.current?.transition||r(`prepared`);try{await n.stopSource(),await n.verifyAbsent(),r(`source-stopped`),await n.startDestination(),r(`destination-started`),await n.complete(),e.publish({v:1,mode:t.target,consented:!0,startupEnabled:e.current.startupEnabled,transition:null})}catch(e){throw r(`recovery-required`),e}}var X=class{options;desktop;readiness;newId;client;listeners=new Set;observedStateDirs=new WeakMap;closed=!1;constructor(e){this.options=e,this.desktop=e.desktop??new J({uid:e.uid,homeDir:e.homeDir,readiness:e.readiness,admitBundle:e.inspectBundle}),this.readiness=e.readiness??new v,this.newId=e.newId??G}async status(){try{return await this.observe(this.options.store.inspect(),await this.options.platform.inspectLegacy())}catch(e){throw this.error(e)}}stateDirectory(e,t){return this.recordedStateDirectory(e,t)??this.options.defaultStateDir}recordedStateDirectory(e,t){return e?.selection?.stateDir??e?.transition?.destination?.stateDir??e?.transition?.source?.stateDir??t??e?.recovery?.stateDir??null}statusStateDirectory(e){return this.observedStateDirs.get(e)??e.selection?.stateDir??e.legacy.stateDir??this.options.defaultStateDir}async observe(e,n){let r=e?.selection??null,i=r?.bundlePath??e?.transition?.source?.bundlePath??this.options.bundlePath,[a,o,s]=await Promise.all([this.options.platform.inspect(`manual`,i),this.options.platform.inspect(`persistent`,i),this.options.platform.loginStatus(this.options.bundlePath).catch(()=>`unknown`)]),c=this.recordedStateDirectory(e,n.definition?.stateDir),l=c??this.options.defaultStateDir,u=N(l,this.options.uid),d=r?.mode===`desktop`?await this.desktop.inspect(r):{registration:`not-registered`,loaded:!1,pid:null,bundlePath:null},p=r?r.mode===`desktop`?d:x(r.mode)===`manual`?a:o:null,m=u?{stateDir:l,computerFp:u.fp,serviceInstance:r?.serviceInstance??n.definition?.serviceInstance??null,...p?.pid?{pid:p.pid}:{}}:void 0,h=await this.readiness.observe(g(l).sock,m);if(h.kind===`verified`&&(!u||r&&(!p?.loaded||!p.pid||u.fp!==r.computerFp))&&(h.kind=`foreign`),r){let e=r.mode===`desktop`?await this.desktop.inspect(r):await this.options.platform.inspect(x(r.mode),i);JSON.stringify(e)!==JSON.stringify(p)&&(h.kind=`unverified`,h.local=null)}let _=new f({stateDir:l,uid:this.options.uid}).inspect(),v=t.parse({desktopLogin:s,desktop:d,ownership:{revision:_?.revision??null,mode:_?.mode??(r||e?.transition?`legacy-native`:n.installed||n.loaded?`headless`:null),consented:_?.consented??!1,startupEnabled:_?.startupEnabled??null,transition:_?.transition??null},revision:e?.revision??null,selection:r,transition:e?.transition?{id:e.transition.id,action:e.transition.action,phase:e.transition.phase}:null,recoveryAvailable:!!e?.recovery,manualRecoveryAvailable:(e?.transition?.destination?.mode===`persistent`&&r?.serviceInstance===e.transition.destination.serviceInstance&&[`start`,`restart`].includes(e.transition.action)&&!e.transition.restoreLegacy||this.isManualRecovery(e)&&r?.serviceInstance===e?.transition?.source?.serviceInstance)&&!a.loaded&&!o.loaded&&h.kind===`absent`&&!n.installed&&!n.loaded,legacy:{installed:n.installed,loaded:n.loaded,stateDir:n.definition?.stateDir??null},manual:a,persistent:o,local:{kind:h.kind,status:h.local}});return c&&this.observedStateDirs.set(v,c),v}error(e){return e instanceof _?e:e instanceof p?new _(e.code===`busy`?`busy`:e.code===`invalid`?`invalid-config`:`unsafe-state`):e instanceof s?e.code===`server-error`?new _(e.serverCode===`runtime-mismatch`||e.serverCode===`configuration-mismatch`?`conflict`:e.serverCode===`pairing-busy`?`busy`:`operation-failed`):new _(e.code===`protocol-error`||e.code===`closed`?`unavailable`:e.code):new _(`operation-failed`)}exact(e,t){return e===null||t===null?e===t:[`pid`,`agentVersion`,`computerFp`,`stateDir`,`serviceInstance`].every(n=>e[n]===t[n])}expect(e,t,n=!1){if(e.revision!==t.revision||!this.exact(e.local.status?.process??null,t.runtime)||e.local.kind===`foreign`||e.local.kind===`unverified`&&!n)throw new _(`conflict`)}async control(e){let t=e.local.status?.process;if(e.local.kind!==`verified`||!t)throw new _(`unavailable`);if(this.client&&!this.exact(this.client.runtime,t)&&(this.client.close(),this.client=void 0),!this.client){let e=await(this.options.connect??n)(g(t.stateDir).sock,{onPairingRequest:e=>this.emit({...e,v:1}),onPairingClosed:e=>this.emit({...e,v:1}),onDisconnect:()=>{this.client=void 0}});if(this.closed)throw e.close(),new _(`unavailable`);if(!this.exact(e.runtime,t))throw e.close(),new _(`conflict`);this.client=e}return this.client}async settings(e){let t=this.statusStateDirectory(e),n=d(g(t)),i=r(n),a=null;if(e.local.kind===`verified`)try{a=await(await this.control(e)).configurationRevision()}catch{}return{saved:n,savedRevision:i,appliedRevision:a,applied:e.local.kind===`absent`?`not-running`:a===null?`unknown`:a===i?`matches`:`restart-required`}}async execute(e){try{if(this.closed)throw new _(`unavailable`);let t=S.safeParse(e);if(!t.success||t.data.cmd===`hello`)throw new _(`bad-request`);let n=t.data,i;if(n.cmd===`terminals.connect`){let e=await(await this.control(await this.status())).connectTerminal(n.args.name);i=e?{supported:!0,...e}:{supported:!1,started:!1,terminals:[]}}else if(n.cmd===`agents.setup`||n.cmd===`agents.skip`||n.cmd===`agents.remove`){let e=T(this.statusStateDirectory(await this.status()),this.options.homeDir);i={agents:n.cmd===`agents.setup`?E(e,n.args.kinds):n.cmd===`agents.skip`?D(e,n.args.kinds):w(e,n.args.kind)}}else if(`args`in n)i=`ownerRevision`in n.args?await this.ownership(n):await this.guardLegacy(n,e=>this.options.store.mutate(n.args.expect.revision,async t=>this.options.platform.withLegacyGuard(async i=>{let o=await i.inspect(),s=await this.observe(t.current,o);if(n.cmd.startsWith(`service.`)&&(s.ownership?.mode===`desktop`||s.ownership?.transition))throw new _(`conflict`);let c=(n.cmd===`service.start`&&n.args.migrateLegacy||n.cmd===`service.recover`&&n.args.action===`continue`&&t.current?.transition?.source===null&&t.current?.transition?.destination!==null&&!!t.current?.recovery)&&o.loaded&&o.definition?.serviceInstance===null&&s.local.kind===`unverified`;if(this.expect(s,n.args.expect,c),n.cmd.startsWith(`service.`))return this.lifecycle(n,t,i,o,s);if(n.cmd===`settings.set`){let t=this.statusStateDirectory(s);if(t!==e)throw new _(`conflict`);let i=g(t),o=m(i,e=>{if(r(e)!==n.args.configRevision)throw new _(`conflict`);let t=e;for(let r of n.args.changes){if(a(e,r.key)===r.value)continue;let n=y(t,r.key,r.value,!1);if(`error`in n)throw new _(`invalid-config`);t=n.next}return t});if(s.local.kind===`verified`&&n.args.changes.some(e=>e.key===`conversations`))try{await(await this.control(s)).applyConversationSetting(r(o))}catch{}return this.settings(s)}let l=await this.control(s);if(n.cmd===`devices.revoke`)return l.revoke(n.args.phoneFp);if(n.cmd===`pairing.open`)return l.openPairing();if(n.cmd===`pairing.close`)return await l.closePairing(n.args.flowId),{};if(n.cmd===`pairing.confirm`)return await l.confirm(n.args.flowId,n.args.challengeId,n.args.phoneFp,n.args.accept),{};throw new _(`bad-request`)}).catch(e=>{throw this.error(e)})));else{let e=await this.status();if(n.cmd===`status`)i=e;else if(n.cmd===`agents`)i={agents:C(T(this.statusStateDirectory(e),this.options.homeDir))};else if(n.cmd===`settings.get`)i=await this.settings(e);else if(n.cmd===`devices`)i=await(await this.control(e)).devices();else if(n.cmd===`terminals`){let t=await(await this.control(e)).terminals();i={supported:t!==null,terminals:t??[]}}else i={checks:await this.diagnose(e)}}let o=h[n.cmd].safeParse(i);if(!o.success)throw new _(`args`in n?`delivery-unknown`:`operation-failed`);return o.data}catch(e){throw this.error(e)}}async guardLegacy(e,t){let n=await this.status(),r=e.cmd===`settings.set`?this.statusStateDirectory(n):n.selection?.stateDir??n.legacy.stateDir??(e.cmd===`service.start`?e.args.stateDir:void 0)??this.options.defaultStateDir;e.cmd===`service.start`&&!n.selection&&!n.legacy.installed&&(N(r,this.options.uid),await this.requireAbsentDestination(r));let i=new f({stateDir:r,uid:this.options.uid});return i.mutate(i.inspect()?.revision??null,async n=>{if(e.cmd.startsWith(`service.`)&&(n.current?.mode===`desktop`||n.current?.transition))throw new _(`conflict`);return t(r)})}async ownership(e){let t=await this.status();this.expect(t,e.args.expect);let n=this.options.store.inspect();if((n?.revision??null)!==t.revision)throw new _(`conflict`);let r=this.stateDirectory(n,t.legacy.stateDir),i=new f({stateDir:r,uid:this.options.uid});if((e.cmd===`desktop.start`||e.cmd===`desktop.stop`)&&(t.ownership?.mode!==`desktop`||!t.ownership.consented))throw new _(`conflict`);return i.mutate(e.args.ownerRevision,async t=>this.options.store.mutate(e.args.expect.revision,async n=>this.options.platform.withLegacyGuard(async i=>{let a=await i.inspect(),o=await this.observe(n.current,a);if(this.expect(o,e.args.expect),e.cmd===`desktop.login.set`){if(t.current?.mode!==`desktop`||!t.current.consented)throw new _(`conflict`);if(t.current.transition||n.current?.transition)throw new _(`recovery-required`);return await this.options.platform.setLogin(this.options.bundlePath,e.args.enabled),t.publish({...t.current,startupEnabled:e.args.enabled}),this.observe(n.current,await i.inspect())}if(e.cmd===`desktop.stop`){if(o.selection?.mode!==`desktop`)throw new _(`conflict`);if(o.local.kind===`absent`&&!o.desktop?.loaded)return o;if(o.local.kind!==`verified`)throw new _(`conflict`);return await this.desktop.stop(e.args.expect),await this.readiness.waitStopped(g(r).sock),this.observe(n.current,await i.inspect())}if(e.cmd===`desktop.setup`){if(t.current||n.current?.selection||n.current?.transition||a.installed||a.loaded||o.manual.loaded||o.persistent.loaded||o.local.kind!==`absent`)throw new _(`conflict`)}else if(e.cmd===`desktop.start`){if(t.current?.transition||n.current?.transition)throw new _(`recovery-required`);if(t.current?.mode!==`desktop`||!t.current.consented||a.installed||a.loaded||o.manual.loaded||o.persistent.loaded)throw new _(`conflict`);if(o.local.kind===`verified`&&o.selection?.mode===`desktop`&&o.desktop?.loaded)return o;if(o.local.kind!==`absent`)throw new _(`conflict`)}else if(e.cmd===`ownership.recover`){if(!t.current?.transition||t.current.transition.id!==e.args.intentId)throw new _(`conflict`)}else if(t.current?.transition)throw new _(`recovery-required`);let s=e.cmd===`ownership.recover`,c=s?t.current.transition.target:e.cmd===`ownership.convert`?e.args.target:`desktop`;if(c===`headless`)return this.convertToHeadless(t,n,i,a,o,r,s);if(await this.admitBundle(this.options.bundlePath),[`foreign`,`unverified`].includes(o.local.kind))throw new _(`conflict`);let u=N(r,this.options.uid,e.cmd===`desktop.setup`);if(!u)throw new _(`unsafe-state`);let d=s&&n.current?.transition?.id===t.current?.transition?.id?n.current.transition:null,f=s&&!n.current?.transition&&n.current?.selection?.mode===`desktop`?n.current.selection:null,p=f?null:d?d.source:n.current?.selection??null,m=s?t.current.transition:{id:this.newId(),source:o.ownership?.mode??null,target:c,sourceManager:p?p.mode===`desktop`?`desktop-child`:p.mode===`manual`?`native-manual`:`native-persistent`:a.installed||a.loaded?`launchd`:null,sourceInstance:p?.serviceInstance??a.definition?.serviceInstance??null,stateDir:r,computerFp:u.fp,targetBundlePath:this.options.bundlePath,targetVersion:this.options.agentVersion,phase:`prepared`};if(m.stateDir!==r||m.computerFp!==u.fp||m.targetBundlePath!==this.options.bundlePath||m.targetVersion!==this.options.agentVersion)throw new _(`conflict`);let h=this.newId(),v=p?.environment??a.definition?.environment,y=f??d?.destination??{mode:`desktop`,stateDir:r,computerFp:u.fp,serviceInstance:h,bundlePath:this.options.bundlePath,bundleId:`sh.bilal.shellbell.host`,agentVersion:this.options.agentVersion,environment:{PATH:v?.PATH??`/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin`,...v?.HERDR_SOCKET_PATH?{HERDR_SOCKET_PATH:v.HERDR_SOCKET_PATH}:{},...v?.XDG_CONFIG_HOME?{XDG_CONFIG_HOME:v.XDG_CONFIG_HOME}:{},SHELLBELL_DIR:r,SHELLBELL_SERVICE_INSTANCE:h}};if(y.mode!==`desktop`||y.computerFp!==u.fp||y.stateDir!==r||y.bundlePath!==m.targetBundlePath||y.agentVersion!==m.targetVersion)throw new _(`conflict`);let b=async()=>{let e=await this.observe(n.current,await i.inspect());return e.selection?.serviceInstance===y.serviceInstance&&e.local.kind===`verified`&&!!e.desktop?.loaded&&!e.manual.loaded&&!e.persistent.loaded&&!e.legacy.installed&&!e.legacy.loaded};return await Y(t,m,{preflight:async()=>{if(!l.safeParse(y).success)throw new _(`unsafe-state`);await this.admitBundle(y.bundlePath)},stopSource:async()=>{if(m.source===`headless`&&t.current?.startupEnabled&&await this.options.platform.setLogin(this.options.bundlePath,!0),!d){let e=n.current?.recovery??null;if(a.installed){if(!a.raw||!a.definition||e&&s)throw new _(`recovery-required`);e={id:this.newId(),definitionPath:i.definitionPath,rawBase64:a.raw.toString(`base64`),sha256:W(`sha256`).update(a.raw).digest(`hex`),wasLoaded:a.loaded,stateDir:r,computerFp:u.fp}}this.publish(n,{recovery:e,transition:{id:m.id,action:`start`,phase:`prepared`,source:p,destination:y,recoveryId:e?.id??null}})}if(await b())return;if(p){if(p.stateDir!==r||p.computerFp!==u.fp)throw new _(`conflict`);if(p.mode===`desktop`){let e=await this.observe(n.current,await i.inspect());if(e.desktop?.loaded){if(e.local.kind!==`verified`)throw new _(`conflict`);await this.desktop.stop({revision:e.revision,runtime:e.local.status.process})}}else{let e=await this.options.platform.inspect(p.mode,p.bundlePath),t=p.mode===`persistent`&&!e.loaded;t?await this.options.platform.prepareManualRecovery(p):(e.loaded||e.registration!==`not-registered`)&&await this.options.platform.stop(p,e),await this.readiness.waitStopped(g(r).sock),t||await this.options.platform.remove(p)}}let e=await i.inspect();if(e.installed||e.loaded){let t=n.current?.recovery;if(!t||!e.raw||W(`sha256`).update(e.raw).digest(`hex`)!==t.sha256)throw new _(`conflict`);e.loaded&&await i.unload(),await this.readiness.waitStopped(g(r).sock);let a=await i.inspect();if(a.loaded||!a.raw?.equals(e.raw))throw new _(`conflict`);await i.restore(null)}},verifyAbsent:async()=>{if(await b())return;let e=await this.observe(n.current,await i.inspect());if(e.manual.loaded||e.persistent.loaded||e.legacy.installed||e.legacy.loaded||e.desktop?.loaded||e.local.kind!==`absent`)throw new _(`conflict`);this.phase(n,`source-stopped`,{selection:null})},startDestination:async()=>{await b()||(this.phase(n,`destination-start-requested`,{selection:y}),await this.desktop.start(y),await this.certify(y),this.phase(n,`destination-ready`))},complete:async()=>{this.publish(n,{selection:y,transition:null})}}),this.observe(n.current,await i.inspect())})))}async convertToHeadless(e,t,n,r,i,a,o){if(!o&&e.current?.mode===`headless`&&!t.current?.selection&&!t.current?.transition)return i;if([`foreign`,`unverified`].includes(i.local.kind))throw new _(`conflict`);await this.admitBundle(this.options.bundlePath);let s=await(this.options.inspectBundle??k)(this.options.bundlePath),l=N(a,this.options.uid);if(!l)throw new _(`unsafe-state`);let u=o&&t.current?.transition?.id===e.current?.transition?.id?t.current.transition:null,d=u?u.source:t.current?.selection??null,f=o?e.current.transition:{id:this.newId(),source:i.ownership?.mode??null,target:`headless`,sourceManager:d?.mode===`desktop`?`desktop-child`:d?.mode===`manual`?`native-manual`:d?.mode===`persistent`?`native-persistent`:null,sourceInstance:d?.serviceInstance??null,stateDir:a,computerFp:l.fp,targetBundlePath:this.options.bundlePath,targetVersion:this.options.agentVersion,phase:`prepared`};if(f.target!==`headless`||f.stateDir!==a||f.computerFp!==l.fp||f.targetBundlePath!==this.options.bundlePath||f.targetVersion!==this.options.agentVersion)throw new _(`conflict`);let p=d?.environment??(o&&r.definition?.serviceInstance===f.id?r.definition.environment:void 0),m={nodePath:s.nodePath,cliPath:V(this.options.bundlePath,`Contents/Resources/agent/dist/cli.js`),stateDir:a,serviceInstance:f.id,logPath:g(a).log,environment:{PATH:p?.PATH??`/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin`,SHELLBELL_DIR:a,SHELLBELL_SERVICE_INSTANCE:f.id,...p?.HERDR_SOCKET_PATH?{HERDR_SOCKET_PATH:p.HERDR_SOCKET_PATH}:{},...p?.XDG_CONFIG_HOME?{XDG_CONFIG_HOME:p.XDG_CONFIG_HOME}:{}}},h=e=>{let t=e.definition;return e.installed&&!!t&&t.serviceInstance===f.id&&t.stateDir===a&&t.nodePath===m.nodePath&&t.cliPath===m.cliPath&&t.logPath===m.logPath&&JSON.stringify(Object.entries(t.environment).sort())===JSON.stringify(Object.entries(m.environment).sort())},v={stateDir:a,computerFp:l.fp,serviceInstance:f.id},y=async()=>{let e=await n.inspect();if(!h(e)||!e.loaded||(await this.readiness.observe(g(a).sock,v)).kind!==`verified`)return!1;let t=await n.inspect();return h(t)&&t.loaded};return await Y(e,f,{preflight:async()=>{if((r.installed||r.loaded)&&(!o||!h(r))||r.loaded&&(i.manual.loaded||i.persistent.loaded||d?.mode===`desktop`&&(await this.desktop.inspect(d)).loaded)||d&&(d.stateDir!==a||d.computerFp!==l.fp)||i.manual.loaded&&d?.mode!==`manual`||i.persistent.loaded&&d?.mode!==`persistent`)throw new _(`conflict`)},stopSource:async()=>{this.publish(t,{transition:{id:f.id,action:`recover`,phase:`prepared`,source:d,destination:null,recoveryId:t.current?.recovery?.id??null}});let e=await this.options.platform.loginStatus(this.options.bundlePath);if(e===`unknown`)throw new _(`unavailable`);if((e===`enabled`||e===`requires-approval`)&&await this.options.platform.setLogin(this.options.bundlePath,!1),!await y()){if(d?.mode===`desktop`){let e=await this.desktop.inspect(d);if(e.loaded){let n=await this.readiness.observe(g(a).sock,{stateDir:a,computerFp:l.fp,serviceInstance:d.serviceInstance,...e.pid?{pid:e.pid}:{}});if(n.kind!==`verified`)throw new _(`conflict`);await this.desktop.stop({revision:t.current?.revision??null,runtime:n.local.process})}}else if(d){let e=await this.options.platform.inspect(d.mode,d.bundlePath),t=d.mode===`persistent`&&!e.loaded;t&&await this.options.platform.prepareManualRecovery(d),(e.loaded||e.registration!==`not-registered`)&&await this.options.platform.stop(d,e),await this.readiness.waitStopped(g(a).sock),t||await this.options.platform.remove(d)}}},verifyAbsent:async()=>{if(await y())return;let e=await this.observe(t.current,await n.inspect()),r=await n.inspect();if(e.manual.loaded||e.persistent.loaded||e.desktop?.loaded||r.loaded||r.installed&&!h(r)||e.local.kind!==`absent`)throw new _(`conflict`);this.phase(t,`source-stopped`,{selection:null})},startDestination:async()=>{if(await y())return;if(await this.admitBundle(this.options.bundlePath),N(a,this.options.uid)?.fp!==l.fp)throw new _(`unsafe-state`);c(m.logPath)||F(L(m.logPath,I.O_WRONLY|I.O_CREAT|I.O_EXCL|I.O_NOFOLLOW,384)),this.phase(t,`destination-start-requested`,{selection:null});let r=await n.inspect();if(!h(r)){if(r.installed||r.loaded)throw new _(`conflict`);await n.write(m)}await n.setStartupEnabled(e.current.startupEnabled);let i=await n.load();if(await this.readiness.waitReady(g(a).sock,{...v,pid:i}),!await y())throw new _(`conflict`);this.phase(t,`destination-ready`)},complete:async()=>{this.publish(t,{selection:null,transition:null})}}),this.observe(t.current,await n.inspect())}async diagnose(e){return this.options.diagnose?this.options.diagnose(this.statusStateDirectory(e)):[{name:`local-owner`,ok:e.local.kind===`verified`,severity:e.local.kind===`foreign`?`error`:e.local.kind===`verified`?`pass`:`warning`,detail:e.local.kind},{name:`legacy-service`,ok:!e.legacy.loaded,severity:e.legacy.loaded?`warning`:`pass`,detail:e.legacy.loaded?`Legacy service loaded`:`Legacy service stopped`},O(this.statusStateDirectory(e),this.options.homeDir)]}publish(e,t){return e.publish({v:1,selection:null,transition:null,recovery:null,...e.current,...t})}phase(e,t,n={}){let r=e.current?.transition;if(!r)throw new _(`recovery-required`);return this.publish(e,{...n,transition:{...r,phase:t}})}async admitBundle(e,t=this.options.agentVersion){let n=await(this.options.inspectBundle??k)(e);if(n.agentVersion!==t)throw new _(`upgrade-required`);return n}async lifecycle(e,t,n,r,i){if(e.cmd===`service.recover`)return this.recover(e,t,n,r,i);if(t.current?.transition)throw new _(`recovery-required`);let a=t.current?.selection??null;if(i.manual.loaded&&a?.mode!==`manual`||i.persistent.loaded&&a?.mode!==`persistent`||a&&r.loaded||e.cmd!==`service.start`&&!a||e.cmd===`service.start`&&a&&x(a.mode)===e.args.mode&&a.bundlePath===this.options.bundlePath&&i[x(a.mode)].loaded||r.installed&&(e.cmd!==`service.start`||!e.args.migrateLegacy))throw new _(`conflict`);let o=null;if(e.cmd===`service.start`||e.cmd===`service.restart`){await this.admitBundle(this.options.bundlePath),await this.options.platform.preflight(e.cmd===`service.start`?e.args.mode:x(a.mode),this.options.bundlePath);let t=a?.stateDir??r.definition?.stateDir??(e.cmd===`service.start`?e.args.stateDir:void 0)??this.options.defaultStateDir;if(e.cmd===`service.start`&&e.args.stateDir&&e.args.stateDir!==t)throw new _(`conflict`);!a&&!r.installed&&(N(t,this.options.uid),await this.requireAbsentDestination(t));let n=N(t,this.options.uid,!0),i=this.newId();o={mode:e.cmd===`service.start`?e.args.mode:a.mode,stateDir:t,computerFp:n.fp,serviceInstance:i,bundlePath:this.options.bundlePath,bundleId:`sh.bilal.shellbell.host`,agentVersion:this.options.agentVersion,environment:{PATH:`/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin`,SHELLBELL_DIR:t,SHELLBELL_SERVICE_INSTANCE:i}}}let s=t.current?.recovery??null;if(r.installed){if(!r.raw||!r.definition||s)throw new _(`recovery-required`);let e=N(r.definition.stateDir,this.options.uid);if(!e)throw new _(`unsafe-state`);s={id:this.newId(),definitionPath:n.definitionPath,rawBase64:r.raw.toString(`base64`),sha256:W(`sha256`).update(r.raw).digest(`hex`),wasLoaded:r.loaded,stateDir:r.definition.stateDir,computerFp:e.fp}}this.publish(t,{recovery:s,transition:{id:this.newId(),action:e.cmd.slice(8),phase:`prepared`,source:a,destination:o,recoveryId:s?.id??null}});try{return await this.advance(t,n,r,i)}catch(e){throw this.phase(t,`recovery-required`),e}}async stopSource(e,t,n,r){let i=e.current.transition,a=i.source;if(this.phase(e,`source-stop-requested`),a){try{await this.admitBundle(a.bundlePath,a.agentVersion)}catch{throw new _(`recovery-required`)}let e=r[x(a.mode)];(e.loaded||e.registration!==`not-registered`)&&await this.options.platform.stop(a,e),await this.readiness.waitStopped(g(a.stateDir).sock);let t=await this.options.platform.inspect(x(a.mode),a.bundlePath);if(t.loaded||x(a.mode)===`persistent`&&t.registration!==`not-registered`)throw new _(`operation-failed`)}else if(n.installed){n.loaded&&await t.unload(),await this.readiness.waitStopped(g(n.definition.stateDir).sock);let e=await t.inspect();if(e.loaded||!e.raw?.equals(n.raw))throw new _(`conflict`)}else if(r.local.kind!==`absent`)throw new _(`conflict`);if(this.phase(e,`source-stopped`,{selection:i.action===`stop`?a:null}),a&&i.destination&&(x(a.mode)!==x(i.destination.mode)||a.bundlePath!==i.destination.bundlePath)&&await this.options.platform.remove(a),n.installed){await t.restore(null);let e=await t.inspect();if(e.installed||e.loaded)throw new _(`operation-failed`)}}async advance(e,t,n,r){let i=e.current.transition;return await this.stopSource(e,t,n,r),i.destination?await this.startDestination(e,i.destination):i.action===`remove`&&i.source&&(await this.options.platform.remove(i.source),this.publish(e,{selection:null})),e.current.transition?.phase!==`awaiting-approval`&&this.publish(e,{transition:null}),this.observe(e.current,await t.inspect())}async startDestination(e,t){if(await this.admitBundle(t.bundlePath),N(t.stateDir,this.options.uid)?.fp!==t.computerFp)throw new _(`unsafe-state`);if(await this.requireAbsentDestination(t.stateDir),this.phase(e,`destination-start-requested`,{selection:t}),(await this.options.platform.start(t)).registration===`requires-approval`){this.phase(e,`awaiting-approval`);return}await this.certify(t),this.phase(e,`destination-ready`)}async requireAbsentDestination(e){if((await this.readiness.observe(g(e).sock)).kind!==`absent`)throw new _(`conflict`)}async certify(e){let t=e.mode===`desktop`?await this.desktop.inspect(e):await this.options.platform.inspect(x(e.mode),e.bundlePath);if(!t.loaded||!t.pid)throw new _(`operation-failed`);let n=await this.readiness.waitReady(g(e.stateDir).sock,{computerFp:e.computerFp,stateDir:e.stateDir,serviceInstance:e.serviceInstance,pid:t.pid}),r=e.mode===`desktop`?await this.desktop.inspect(e):await this.options.platform.inspect(x(e.mode),e.bundlePath);if(JSON.stringify(t)!==JSON.stringify(r)||n.process.agentVersion!==e.agentVersion)throw new _(`conflict`)}isManualRecovery(e){let t=e?.transition;return t?.action===`recover`&&!t.restoreLegacy&&t.source?.mode===`persistent`&&t.destination?.mode===`manual`&&t.source.stateDir===t.destination.stateDir&&t.source.computerFp===t.destination.computerFp}async recover(e,t,n,r,i){let a=t.current;if(!a||i.manual.loaded&&i.persistent.loaded||a.selection&&r.loaded||a.selection&&i[x(a.selection.mode)===`manual`?`persistent`:`manual`].loaded)throw new _(`conflict`);if(e.args.action===`discard-backup`){if(a.transition||!a.recovery||r.installed&&r.raw?.toString(`base64`)!==a.recovery.rawBase64)throw new _(`conflict`);return this.publish(t,{recovery:null}),this.observe(t.current,r)}let o=a.recovery,s=o?Buffer.from(o.rawBase64,`base64`):null;if(o&&(!s||W(`sha256`).update(s).digest(`hex`)!==o.sha256)||o&&(o.definitionPath!==n.definitionPath||N(o.stateDir,this.options.uid)?.fp!==o.computerFp))throw new _(`unsafe-state`);if(o&&r.installed&&!r.raw?.equals(s))throw new _(`conflict`);let c=this.isManualRecovery(a);if(e.args.action===`use-manual`||e.args.action===`continue`&&c){let e=c?a.transition?.source:a.transition?.destination;if(e?.mode!==`persistent`||a.transition?.restoreLegacy||!c&&![`start`,`restart`].includes(a.transition.action)||a.selection?.serviceInstance!==e.serviceInstance||i.manual.loaded||i.persistent.loaded||i.local.kind!==`absent`||r.installed||r.loaded)throw new _(`conflict`);if(await this.admitBundle(this.options.bundlePath),await this.options.platform.preflight(`manual`,this.options.bundlePath),N(e.stateDir,this.options.uid)?.fp!==e.computerFp)throw new _(`unsafe-state`);let o=this.newId(),s=c?a.transition.destination:{...e,mode:`manual`,bundlePath:this.options.bundlePath,agentVersion:this.options.agentVersion,serviceInstance:o,environment:{...e.environment,SHELLBELL_SERVICE_INSTANCE:o}};c||this.publish(t,{transition:{id:this.newId(),action:`recover`,phase:`prepared`,source:e,destination:s,recoveryId:a.recovery?.id??null}});try{await this.options.platform.prepareManualRecovery(e),await this.requireAbsentDestination(e.stateDir);let r=await this.observe(t.current,await n.inspect());if(r.manual.loaded||r.persistent.loaded||r.legacy.installed||r.legacy.loaded||r.local.kind!==`absent`)throw new _(`conflict`);return this.publish(t,{selection:null,transition:{id:this.newId(),action:`start`,phase:`source-stopped`,source:null,destination:s,recoveryId:a.recovery?.id??null}}),await this.startDestination(t,s),this.publish(t,{transition:null}),this.observe(t.current,await n.inspect())}catch(e){throw this.phase(t,`recovery-required`),e}}if(e.args.action===`continue`&&a.transition?.action===`recover`&&!a.transition.restoreLegacy)throw new _(`recovery-required`);try{if(e.args.action===`restore-legacy`||a.transition?.restoreLegacy){if(!o||!s)throw new _(`conflict`);if(e.args.action===`restore-legacy`){if(r.loaded)throw new _(`conflict`);this.publish(t,{transition:{id:this.newId(),action:`recover`,phase:`prepared`,source:a.selection,destination:null,recoveryId:o.id,restoreLegacy:{restartPrevious:e.args.restartPrevious}}})}return await this.restoreLegacy(t,n,r,i,s)}let c=a.transition;if(!c)throw new _(`conflict`);let l=c.destination;if(l&&a.selection?.serviceInstance===l.serviceInstance){let e=i[x(l.mode)];if(r.loaded||i[x(l.mode)===`manual`?`persistent`:`manual`].loaded)throw new _(`conflict`);if(e.registration===`requires-approval`)return this.phase(t,`awaiting-approval`),this.observe(t.current,r);if(e.loaded)await this.certify(l),this.phase(t,`destination-ready`);else{if(i.local.kind!==`absent`)throw new _(`conflict`);await this.startDestination(t,l)}return t.current.transition?.phase!==`awaiting-approval`&&this.publish(t,{transition:null}),this.observe(t.current,await n.inspect())}return await this.advance(t,n,r,i)}catch(e){throw t.current?.transition&&this.phase(t,`recovery-required`),e}}async restoreLegacy(e,t,n,r,i){let a=e.current,o=a.recovery,s=a.transition.restoreLegacy;if(n.loaded){if(!s.restartPrevious||a.selection||r.manual.loaded||r.persistent.loaded||r.local.kind!==`verified`||!n.raw?.equals(i))throw new _(`conflict`);let o=await t.inspect();if(!o.loaded||!o.raw?.equals(i))throw new _(`conflict`);return this.publish(e,{selection:null,transition:null}),this.observe(e.current,o)}if(a.selection)await this.stopSource(e,t,{installed:!1,loaded:!1,raw:null,definition:null},r);else if(r.manual.loaded||r.persistent.loaded||r.local.kind!==`absent`)throw new _(`conflict`);await this.readiness.waitStopped(g(o.stateDir).sock),this.phase(e,`source-stopped`,{selection:null}),n.installed||await t.restore(i);let c=await t.inspect();if(!c.raw?.equals(i)||c.loaded)throw new _(`operation-failed`);if(s.restartPrevious){this.phase(e,`destination-start-requested`);let n=await t.load();await this.readiness.waitReady(g(o.stateDir).sock,{computerFp:o.computerFp,stateDir:o.stateDir,serviceInstance:c.definition?.serviceInstance??null,pid:n});let r=await t.inspect();if(!r.loaded||!r.raw?.equals(i))throw new _(`conflict`)}return this.publish(e,{selection:null,transition:null}),this.observe(e.current,await t.inspect())}emit(e){for(let t of this.listeners)t(e)}onEvent(e){return this.listeners.add(e),()=>this.listeners.delete(e)}async close(){this.closed=!0,this.client?.close(),this.client=void 0,this.listeners.clear(),await this.desktop.close()}};async function Z(){if(process.argv.length===3&&[`--help`,`--version`].includes(process.argv[2])){process.stdout.write(process.argv[2]===`--version`?`${e}\n`:`Shellbell native controller
3
+ `);return}if(process.argv.length!==2||process.execArgv.length||process.env.NODE_OPTIONS||process.env.NODE_PATH)throw Error();let t=z();if(process.platform!==`darwin`||t.uid<=0)throw Error();let n=H(B(U(import.meta.url)),`../../../..`);if((await k(n)).agentVersion!==e)throw Error();let r=V(t.homedir,`Library/Application Support/Shellbell`),i=new X({store:new A({root:r,uid:t.uid}),platform:j({root:r,uid:t.uid,homeDir:t.homedir}),bundlePath:n,uid:t.uid,homeDir:t.homedir,agentVersion:e,defaultStateDir:V(t.homedir,`.shellbell`)}),a=q(process.stdin,process.stdout,i,{agentVersion:e}),o=()=>{a.close().catch(()=>{process.exitCode=1})};process.once(`SIGTERM`,o),process.once(`SIGINT`,o)}process.argv[1]&&R(process.argv[1])===U(import.meta.url)&&Z().catch(()=>{process.stderr.write(`Shellbell controller unavailable
4
4
  `),process.exitCode=1});export{};
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import{T as e,at as t,ht as n,ot as r,zt as i}from"./service-lifecycle-ypi9zEPw.js";import{a,n as o,r as s}from"./service-entry-BeYEy-kj.js";import{createReadStream as c,fstatSync as l,realpathSync as u}from"node:fs";import{userInfo as d}from"node:os";import{dirname as f,join as p,resolve as m}from"node:path";import{fileURLToPath as h}from"node:url";async function g(){if(process.argv.length===3&&[`--help`,`--version`].includes(process.argv[2])){process.stdout.write(process.argv[2]===`--version`?`${i}\n`:`Shellbell native service
3
- `);return}let u=e.parse(process.argv[2]);if(process.argv.length!==3||process.execArgv.length||process.env.NODE_OPTIONS||process.env.NODE_PATH)throw Error();let g=d();if(process.platform!==`darwin`||g.uid<=0)throw Error();let _,v=m(f(h(import.meta.url)),`../../../..`),y=await a(v);if(y.agentVersion!==i)throw Error();let b=p(g.homedir,`Library/Application Support/Shellbell`),x=await o(u,{...u===`desktop`?{ownerInput:(()=>{let e=l(3);if(!e.isFIFO()&&!e.isSocket())throw Error(`invalid owner channel`);return c(``,{fd:3,autoClose:!0})})(),onOwnerLost:e=>{_?.warn(e===null?`app connection closed; stopping`:`app connection failed; stopping`),process.exit(e===null?0:1)}}:{},bundlePath:v,root:b,uid:g.uid,async start(e){if(e.agentVersion!==y.agentVersion)throw Error();let i=s(e,g.homedir,process.env);for(let e of Object.keys(process.env))delete process.env[e];Object.assign(process.env,i);let{buildAgent:a,shutdown:o}=await import(new URL(`./cli.js`,import.meta.url).href),c=n(e.stateDir),l=t({file:c.log,stdout:!1}),u=r(l);_=u,u.info(`service starting`);let d=await a(u,void 0,!1,{paths:c,serviceInstance:e.serviceInstance,nativeService:!0});try{await d.control.start(),d.agent.start()}catch(e){throw d.stopBackendDetectors(),d.agent.stop(),await d.control.stop(),e}let f;return{stop(){return f??=o(d.agent,d.control,e=>{e&&process.exit(1)},d.stopBackendDetectors),f}}}}),S=()=>{_?.info(`asked to stop`),x.stop().then(()=>process.exit(0),()=>process.exit(1))};process.once(`SIGTERM`,S),process.once(`SIGINT`,S)}process.argv[1]&&u(process.argv[1])===h(import.meta.url)&&g().catch(()=>{process.stderr.write(`Shellbell service unavailable
2
+ import{Bt as e,T as t,at as n,gt as r,ot as i}from"./service-lifecycle-Dbs2mdix.js";import{a,n as o,r as s}from"./service-entry-B036lDNH.js";import{createReadStream as c,fstatSync as l,realpathSync as u}from"node:fs";import{userInfo as d}from"node:os";import{dirname as f,join as p,resolve as m}from"node:path";import{fileURLToPath as h}from"node:url";async function g(){if(process.argv.length===3&&[`--help`,`--version`].includes(process.argv[2])){process.stdout.write(process.argv[2]===`--version`?`${e}\n`:`Shellbell native service
3
+ `);return}let u=t.parse(process.argv[2]);if(process.argv.length!==3||process.execArgv.length||process.env.NODE_OPTIONS||process.env.NODE_PATH)throw Error();let g=d();if(process.platform!==`darwin`||g.uid<=0)throw Error();let _,v=m(f(h(import.meta.url)),`../../../..`),y=await a(v);if(y.agentVersion!==e)throw Error();let b=p(g.homedir,`Library/Application Support/Shellbell`),x=await o(u,{...u===`desktop`?{ownerInput:(()=>{let e=l(3);if(!e.isFIFO()&&!e.isSocket())throw Error(`invalid owner channel`);return c(``,{fd:3,autoClose:!0})})(),onOwnerLost:e=>{_?.warn(e===null?`app connection closed; stopping`:`app connection failed; stopping`),process.exit(e===null?0:1)}}:{},bundlePath:v,root:b,uid:g.uid,async start(e){if(e.agentVersion!==y.agentVersion)throw Error();let t=s(e,g.homedir,process.env);for(let e of Object.keys(process.env))delete process.env[e];Object.assign(process.env,t);let{buildAgent:a,shutdown:o}=await import(new URL(`./cli.js`,import.meta.url).href),c=r(e.stateDir),l=n({file:c.log,stdout:!1}),u=i(l);_=u,u.info(`service starting`);let d=await a(u,void 0,!1,{paths:c,serviceInstance:e.serviceInstance,nativeService:!0});try{await d.control.start(),d.agent.start()}catch(e){throw d.stopBackendDetectors(),d.agent.stop(),await d.agent.closePages(),await d.control.stop(),e}let f;return{stop(){return f??=o(d.agent,d.control,e=>{e&&process.exit(1)},d.stopBackendDetectors),f}}}}),S=()=>{_?.info(`asked to stop`),x.stop().then(()=>process.exit(0),()=>process.exit(1))};process.once(`SIGTERM`,S),process.once(`SIGINT`,S)}process.argv[1]&&u(process.argv[1])===h(import.meta.url)&&g().catch(()=>{process.stderr.write(`Shellbell service unavailable
4
4
  `),process.exitCode=1});export{};
@@ -0,0 +1,11 @@
1
+ import{A as e,D as t,E as n,Ft as r,It as i,Mt as a,O as o,Pt as s,R as c,S as l,_t as u,b as d,c as f,gt as p,h as m,i as h,k as g,m as _,p as v,w as y,y as b,yt as x}from"./service-lifecycle-Dbs2mdix.js";import{createRequire as S}from"node:module";import{closeSync as C,constants as w,fstatSync as ee,mkdirSync as T,openSync as E,readdirSync as te,realpathSync as D,unlinkSync as O}from"node:fs";import{basename as k,dirname as A,join as j}from"node:path";import{z as M}from"zod";const N=`sh.bilal.shellbell.host.manual`;function P(e){(!n.safeParse(e).success||e!==j(e))&&F();for(let t=e;;t=A(t)){let e=s(t);if(e&&(!e.isDirectory()||e.isSymbolicLink())&&F(),A(t)===t)break}}function F(){throw new m(`unsafe-state`)}function I(e){return(!n.safeParse(e).success||[...e].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)===127))&&F(),e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&apos;`)}function L(e){return(e!==j(e)||!e.endsWith(`/Shellbell.app/Contents/MacOS/Shellbell`))&&F(),Buffer.from(`<?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0"><dict>
4
+ <key>Label</key><string>${N}</string>
5
+ <key>ProgramArguments</key><array><string>${I(e)}</string><string>--service-run</string><string>manual</string></array>
6
+ <key>RunAtLoad</key><true/>
7
+ <key>KeepAlive</key><true/>
8
+ <key>ThrottleInterval</key><integer>10</integer>
9
+ </dict></plist>
10
+ `)}function R(e,t){return e===null||t===null?e===t:i(e.stat,t.stat)&&e.stat.mode===t.stat.mode&&e.stat.uid===t.stat.uid&&e.stat.size===t.stat.size&&e.stat.mtimeMs===t.stat.mtimeMs&&e.stat.ctimeMs===t.stat.ctimeMs&&e.raw.equals(t.raw)}function z(e,t){let n=j(e,`manual.plist`),o,c=i=>{try{if(P(e),!s(e))return null;r(e,t);let o=s(n);if(!o)return null;let c=a(n,65536,t);return c.equals(L(i))||F(),{stat:o,raw:c}}catch{return F()}},l=e=>{let t=c(e);return o!==void 0&&!R(o,t)&&F(),o=t,t};return{path:n,inspect(e){return l(e)!==null},write(a){let u=L(a),d=l(a);P(e),s(e)||T(e,{recursive:!0,mode:448});let f=r(e,t);x(n,u,()=>{P(e),(!i(f,r(e,t))||!R(d,c(a)))&&F()}),o=c(a),o?.raw.equals(u)||F()},remove(e){let t=l(e);t&&(R(t,c(e))||F(),O(n),o=null)}}}const B=`sh.bilal.shellbell.host.agent`,V=65536;function H(){throw new m(`unsafe-state`)}function U(e){(!n.safeParse(e).success||e!==j(e)||k(e)!==`Shellbell.app`)&&H();let t=j(e,`Contents`,`MacOS`,`Shellbell`);return n.safeParse(t).success||H(),t}async function W(e,t,n,r,i=!1,a=1e4){try{let i=await e(t,n,{input:r,timeoutMs:a,maxOutputBytes:V,captureOutput:!0});if(!Number.isInteger(i.exitCode)||i.exitCode<0||i.exitCode>255||!Buffer.isBuffer(i.stdout)||i.stdout.length>V)throw Error(`invalid command result`);return i}catch{throw new m(i?`delivery-unknown`:`unavailable`)}}function G(e,t){return i(e,t)&&e.mode===t.mode&&e.uid===t.uid&&e.size===t.size&&e.mtimeMs===t.mtimeMs&&e.ctimeMs===t.ctimeMs}async function K(e,t,n=c){let r=U(e),i=j(e,`Contents`,`Info.plist`),o=new Map,l=()=>{P(A(e));for(let n of[e,j(e,`Contents`),j(e,`Contents`,`MacOS`),i,r]){let e=s(n),a=n===i||n===r;(!e||e.isSymbolicLink()||(a?!e.isFile():!e.isDirectory())||e.uid!==t&&e.uid!==0||e.mode&3602||n===r&&!(e.mode&73))&&H();let c=o.get(n);c&&!G(c,e)&&H(),o.set(n,e)}};try{l();let e=await W(n,`/usr/bin/plutil`,[`-convert`,`json`,`-o`,`-`,`-`],a(i,V));e.exitCode!==0&&H();let t=JSON.parse(new TextDecoder(`utf-8`,{fatal:!0}).decode(e.stdout));return(t?.CFBundleIdentifier!==`sh.bilal.shellbell.host`||t?.CFBundleExecutable!==`Shellbell`)&&H(),l(),{executable:r,revalidate:l}}catch{return H()}}function q(e,t,n,r){let i;try{i=new TextDecoder(`utf-8`,{fatal:!0}).decode(e)}catch{return H()}let a=i.trim().split(/\r?\n/).map(e=>e.trim());(a.shift()!==`${t} = {`||a.pop()!==`}`)&&H();let o=1,s,c=null,l=!1,u,d=!1;for(let e of a)if(e){if(e===`}`){o<=1&&H(),d&&o===2&&(d=!1),o--;continue}if(o===1&&e.startsWith(`program = `)){s!==void 0&&H(),s=e.slice(10);continue}if(o===1&&e.startsWith(`pid = `)){(l||!/^pid = [1-9][0-9]*$/.test(e))&&H(),l=!0,c=Number(e.slice(6)),(!Number.isSafeInteger(c)||c>2147483647)&&H();continue}if(o===1&&/^(?:pid|program|arguments)(?:\s|=)/.test(e)&&e!==`arguments = {`&&H(),e.endsWith(`= {`)){o===1&&e===`arguments = {`?(u!==void 0&&H(),u=[],d=!0):d&&H(),o++;continue}d&&o===2?u.push(e):(e.includes(`{`)||e.includes(`}`))&&H()}return(o!==1||s!==n||!u||u.length!==3||u[0]!==(r===`persistent`?`Shellbell`:n)||u[1]!==`--service-run`||u[2]!==r)&&H(),c}function J(e){let{root:r,uid:i,homeDir:a}=e;(!Number.isSafeInteger(i)||i<=0||!n.safeParse(r).success||!n.safeParse(a).success||r!==j(r)||a!==j(a))&&H();let u=j(a,`Library`,`LaunchAgents`);(r===u||r.startsWith(`${u}/`))&&H();let d=e.run??c,f=z(r,i),p=()=>e.legacy??t({run:d,uid:i,homeDir:a}),g=`gui/${i}`,_=e=>`${g}/${e===`manual`?N:B}`,v=e=>{l.safeParse(e).success||H()};async function x(e,t,n,r=`service`){let a=await K(e,i,d);await n?.(),a.revalidate();let o=t!==`status`,s=await W(d,a.executable,[r===`login`?`--login-api`:`--service-api`,t],void 0,o);a.revalidate();let c;try{c=b.parse(JSON.parse(new TextDecoder(`utf-8`,{fatal:!0}).decode(s.stdout)))}catch{throw new m(o?`delivery-unknown`:`unavailable`)}if(!c.ok)throw new m(c.error.code===`denied`?`approval-required`:c.error.code===`invalid-bundle`?`unsafe-state`:`operation-failed`);if(s.exitCode!==0)throw new m(o?`delivery-unknown`:`unavailable`);return c.status}async function S(e,t,n=1e4){let r=await W(d,`/bin/launchctl`,[`print`,_(e)],void 0,!1,n);if(r.exitCode===113)return{loaded:!1,pid:null};if(r.exitCode!==0)throw new m(`unavailable`);return{loaded:!0,pid:q(r.stdout,_(e),U(t),e)}}let C={loginStatus:e=>x(e,`status`,void 0,`login`),async setLogin(e,t){let n=await K(e,i,d),r=await W(d,`/usr/bin/codesign`,[`--verify`,`--strict`,e]);if(n.revalidate(),r.exitCode!==0)throw new m(`startup-unavailable`);let a=await x(e,`status`,void 0,`login`);if(a===`not-found`&&!t||a===`unknown`)throw new m(`startup-unavailable`);if(t?a===`enabled`||a===`requires-approval`:a===`not-registered`)return a;try{await x(e,t?`register`:`unregister`,void 0,`login`)}catch(n){if(!(t&&n instanceof m&&n.code===`approval-required`&&await x(e,`status`,void 0,`login`)===`requires-approval`))throw n}let o=await x(e,`status`,void 0,`login`);if(t?o!==`enabled`&&o!==`requires-approval`:o!==`not-registered`)throw new m(`operation-failed`);return o},async preflight(e,t){await o(d,i,a);let n=await K(t,i,d);if(e===`persistent`){let e=await W(d,`/usr/bin/codesign`,[`--verify`,`--strict`,t]);if(n.revalidate(),e.exitCode!==0||await x(t,`status`)===`not-found`)throw new m(`startup-unavailable`)}},async prepareManualRecovery(e){if(await o(d,i,a),v(e),y(e.mode)!==`persistent`&&H(),(await C.inspect(`persistent`,e.bundlePath)).loaded)throw new m(`conflict`);if((await W(d,`/bin/launchctl`,[`disable`,_(`persistent`)],void 0,!0)).exitCode!==0)throw new m(`operation-failed`);let t=await W(d,`/bin/launchctl`,[`print-disabled`,g]),n=new TextDecoder(`utf-8`,{fatal:!0}).decode(t.stdout).trim().split(/\r?\n/).map(e=>e.trim());if(t.exitCode!==0||n.shift()!==`disabled services = {`||n.pop()!==`}`||n.filter(e=>e.includes(`"${B}"`)).join(`
11
+ `)!==`"${B}" => disabled`)throw new m(`operation-failed`);let r=await C.inspect(`persistent`,e.bundlePath);if(r.loaded)throw new m(`conflict`);r.registration!==`not-registered`&&r.registration!==`not-found`&&await C.stop(e,r)},inspectLegacy:()=>p().inspect(),async inspect(e,t){e!==`manual`&&e!==`persistent`&&H();let n=U(t),r;e===`manual`?r=f.inspect(n)?`enabled`:`not-registered`:(P(A(t)),r=s(t)?await x(t,`status`):`not-found`);let i=await S(e,t);return e===`manual`&&i.loaded&&r!==`enabled`&&H(),{registration:r,...i,bundlePath:t}},async start(e){if(v(e),await C.preflight(y(e.mode),e.bundlePath),(await C.inspect(y(e.mode),e.bundlePath)).loaded)throw new m(`conflict`);if(y(e.mode)===`persistent`){if((await W(d,`/bin/launchctl`,[`enable`,_(`persistent`)],void 0,!0)).exitCode!==0)throw new m(`operation-failed`);return{registration:await x(e.bundlePath,`register`,async()=>{if((await S(`persistent`,e.bundlePath)).loaded)throw new m(`conflict`)}),...await S(y(e.mode),e.bundlePath),bundlePath:e.bundlePath}}let t=await K(e.bundlePath,i,d);if(f.write(t.executable),(await S(`manual`,e.bundlePath)).loaded)throw new m(`conflict`);if(f.inspect(t.executable),t.revalidate(),(await W(d,`/bin/launchctl`,[`bootstrap`,g,f.path],void 0,!0)).exitCode!==0)throw new m(`operation-failed`);return C.inspect(`manual`,e.bundlePath)},async stop(e,t){v(e),t.bundlePath!==e.bundlePath&&H();let n=await C.inspect(y(e.mode),e.bundlePath);if(n.loaded!==t.loaded||n.pid!==t.pid||n.registration!==t.registration)throw new m(`conflict`);if(y(e.mode)===`persistent`){if(await x(e.bundlePath,`unregister`,async()=>{let t=await S(`persistent`,e.bundlePath);if(t.loaded!==n.loaded||t.pid!==n.pid)throw new m(`conflict`)})!==`not-registered`)throw new m(`operation-failed`)}else if(n.loaded&&(f.inspect(U(e.bundlePath)),(await W(d,`/bin/launchctl`,[`bootout`,_(`manual`)],void 0,!0)).exitCode!==0))throw new m(`operation-failed`);let r=performance.now()+1e4;for(;;){let t=r-performance.now();if(t<=0)throw new m(`operation-failed`);let i=await S(y(e.mode),e.bundlePath,t);if(!i.loaded)break;if(i.pid!==null&&i.pid!==n.pid)throw new m(`conflict`);let a=Math.min(100,r-performance.now());if(a<=0)throw new m(`operation-failed`);await new Promise(e=>setTimeout(e,a))}},async remove(e){v(e);let t=await C.inspect(y(e.mode),e.bundlePath);if(t.loaded||y(e.mode)===`persistent`&&t.registration!==`not-registered`)throw new m(`conflict`);y(e.mode)===`manual`&&f.remove(U(e.bundlePath))},withLegacyGuard(e){return h(p(),!0,e)}};return C}const Y=()=>{throw new m(`unsafe-state`)};async function X(e,t={}){try{(D(e)!==e||[...e].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)===127))&&Y();let n=t.run??c,r=await K(e,process.getuid(),n),i=j(e,`Contents`),o=j(i,`Resources`),l=j(i,`Helpers/node`),u=j(o,`agent/dist/native-controller.js`),d=j(o,`agent/dist/native-service.js`),f=[l,u,d,j(o,`runtime/LICENSE`),j(o,`agent/package.json`),j(o,`agent/dist/cli.js`)],p=()=>{for(let t of f){for(let n=A(t);n!==e;n=A(n)){let e=s(n);(!e?.isDirectory()||e.isSymbolicLink()||e.mode&3602||e.uid!==0&&e.uid!==process.getuid())&&Y()}let n=s(t);(!n?.isFile()||n.isSymbolicLink()||n.mode&3602||n.uid!==0&&n.uid!==process.getuid()||t===l&&!(n.mode&73))&&Y()}let t=0,n=new Set,r=e=>{++t>1e5&&Y();let i=s(e);if(!i)throw new m(`unsafe-state`);let a=D(e);if(a.startsWith(`${o}/`)||Y(),i.isSymbolicLink()){r(a);return}if(!n.has(a)){if(n.add(a),(i.uid!==0&&i.uid!==process.getuid()||i.mode&3602)&&Y(),i.isDirectory())for(let t of te(e))r(j(e,t));else i.isFile()||Y()}};for(let e of[`agent`,`runtime`])r(j(o,e))};p();let h=JSON.parse(a(j(o,`agent/package.json`),65536).toString(`utf8`));(h.name!==`shellbell`||typeof h.version!=`string`||!h.version||h.type!==`module`)&&Y();let g=S(j(o,`agent/package.json`));for(let e of Object.keys(h.dependencies??{}))D(g.resolve(e)).startsWith(`${o}/agent/`)||Y();let _=await n(`/usr/bin/plutil`,[`-convert`,`json`,`-o`,`-`,j(i,`Info.plist`)],{timeoutMs:1e4,maxOutputBytes:65536,captureOutput:!0});(_.exitCode!==0||JSON.parse(_.stdout.toString(`utf8`)).CFBundleShortVersionString!==h.version)&&Y();let v=await n(l,[`--version`],{timeoutMs:1e4,maxOutputBytes:65536,captureOutput:!0});(v.exitCode!==0||v.stdout.toString(`utf8`).trim()!==`v22.23.1`)&&Y();let y=await n(l,[`-p`,`process.platform + ':' + process.arch`],{timeoutMs:1e4,maxOutputBytes:65536,captureOutput:!0});(y.exitCode!==0||y.stdout.toString(`utf8`).trim()!==`${process.platform}:${process.arch}`)&&Y();for(let e of[j(o,`agent/dist/cli.js`),u,d]){let t=await n(l,[e,`--version`],{timeoutMs:1e4,maxOutputBytes:65536,captureOutput:!0});(t.exitCode!==0||t.stdout.toString(`utf8`).trim()!==h.version)&&Y()}return r.revalidate(),p(),{executable:r.executable,nodePath:l,controllerPath:u,servicePath:d,agentVersion:h.version}}catch(e){if(e instanceof m)throw e;return Y()}}const Z=M.strictObject({v:M.literal(1),instance:M.uuid()});function ne(e,t){let n,r,i=new Promise((e,t)=>{n=e,r=t}),a=!1,o=!1,s=Buffer.alloc(0),c=setTimeout(()=>u(),t.timeoutMs??5e3),l=()=>{clearTimeout(c),e.off(`data`,d),e.off(`end`,u),e.off(`close`,u),e.off(`error`,u)},u=()=>{o||(o=!0,l(),r(new m(`unavailable`)),Promise.resolve().then(()=>t.onLost()).catch(()=>{}))},d=e=>{if(o)return;let r=Buffer.isBuffer(e)?e:Buffer.from(e);if(a||s.length+r.length>1024){u();return}s=Buffer.concat([s,r]);let i=s.indexOf(10);if(!(i<0))try{let e=Z.parse(JSON.parse(new TextDecoder(`utf-8`,{fatal:!0}).decode(s.subarray(0,i))));if(i!==s.length-1||e.instance!==t.instance)throw Error();a=!0,s=Buffer.alloc(0),clearTimeout(c),n()}catch{u()}};return e.on(`data`,d),e.once(`end`,u),e.once(`close`,u),e.once(`error`,u),(e.destroyed||e.readableEnded)&&u(),{ready:i,close:u}}var Q=class extends v{constructor(e){super({...e,filename:`controller.json`,maxBytes:_,schema:d})}};function re(e,t,r){if(r.NODE_OPTIONS||r.NODE_PATH||!l.safeParse(e).success||!n.safeParse(t).success)throw new m(`unsafe-state`);return{...e.environment,HOME:t}}function $(t,i,o=!1){try{if(i<=0||!n.safeParse(t).success||[...t].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)===127))throw Error();for(let e=t;;e=A(e)){let t=s(e);if(t&&(!t.isDirectory()||t.isSymbolicLink()))throw Error();if(A(e)===e)break}if(!s(t)){if(!o)return null;T(t,{recursive:!0,mode:448})}if(r(t,i),D(t)!==t)throw Error();let c=p(t);for(let e of[c.identity,c.pairings,c.config,c.pid])s(e)&&a(e,65536,i);ie(c.log,i);let l=s(c.sock);if(l&&(!l.isSocket()||l.uid!==i||(l.mode&4095)!=384))throw Error();return u(c),o?g(c):e(c)}catch{throw new m(`unsafe-state`)}}function ie(e,t){let n=s(e);if(!n)return;let r=e=>{if(!e.isFile()||e.isSymbolicLink()||e.uid!==t||(e.mode&4095)!=384)throw Error()};r(n);let a=E(e,w.O_RDONLY|w.O_NOFOLLOW|w.O_NONBLOCK);try{let t=ee(a);r(t);let o=s(e);if(!o||(r(o),!i(n,t)||!i(t,o)))throw Error()}finally{C(a)}}async function ae(e,t){let n=new Q(t).inspect()?.selection;if(!n||n.mode!==e||n.bundlePath!==t.bundlePath)throw new m(`conflict`);let r=$(n.stateDir,t.uid);if(!r||r.fp!==n.computerFp)throw new m(`unsafe-state`);if(e!==`desktop`)return t.start(n);let i=new f({stateDir:n.stateDir,uid:t.uid}).inspect();if(!t.ownerInput||i?.mode!==`desktop`||!i.consented||i.transition&&(i.transition.target!==`desktop`||![`source-stopped`,`destination-started`].includes(i.transition.phase)))throw new m(`conflict`);let a=!1,o,s,c=()=>s??=(async()=>{o&&await(await o).stop()})(),l=ne(t.ownerInput,{instance:n.serviceInstance,onLost:async()=>{a=!0;try{await c(),t.onOwnerLost?.(null)}catch(e){t.onOwnerLost?.(e)}}});try{if(await l.ready,a)throw new m(`unavailable`);if(o=t.start(n),await o,a)throw await c(),new m(`unavailable`);return{stop:async()=>{await c(),l.close()}}}catch(e){throw l.close(),e}}export{X as a,Q as i,ae as n,J as o,re as r,$ as t};