shellbell 0.16.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import{$ as e,D as t,Dt as n,Et as r,Ft as i,I as a,It as o,Jt as s,Mt as c,Nt as l,P as u,Pt as d,Q as f,Qn as p,Qt as m,St as h,Xt as g,_n as _,a as v,at as y,c as b,f as ee,gn as te,gt as x,ht as ne,it as re,j as ie,jt as S,kt as ae,lr as C,o as w,qt as oe,r as se,rt as T,s as ce,st as le,tt as ue,yt as de,z as fe}from"./service-lifecycle-CLWP08Es.js";import{execFile as pe,execFileSync as me,spawn as he}from"node:child_process";import{accessSync as ge,chmodSync as _e,closeSync as ve,constants as E,existsSync as D,fsyncSync as ye,linkSync as be,mkdirSync as xe,openSync as Se,readFileSync as O,readSync as Ce,readdirSync as we,readlinkSync as Te,realpathSync as Ee,renameSync as De,rmSync as Oe,statSync as k,statfsSync as ke,symlinkSync as Ae,unlinkSync as je,writeFileSync as Me}from"node:fs";import{homedir as A}from"node:os";import{basename as j,delimiter as Ne,dirname as M,isAbsolute as N,join as P,normalize as Pe,relative as Fe,resolve as Ie,sep as Le}from"node:path";import{z as Re}from"zod";import{createHash as ze,randomUUID as F}from"node:crypto";import{EventEmitter as Be}from"node:events";import{connect as Ve}from"node:net";import He from"ws";import{isDeepStrictEqual as Ue,promisify as We}from"node:util";import{StringDecoder as Ge}from"node:string_decoder";import{create as Ke,fromBinary as qe,toBinary as Je}from"@bufbuild/protobuf";import{fileDesc as Ye,messageDesc as I}from"@bufbuild/protobuf/codegenv2";import{performance as Xe}from"node:perf_hooks";const Ze=[[768,879],[1155,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1552,1562],[1611,1631],[1648,1648],[1750,1756],[1759,1764],[1767,1768],[1770,1773],[1809,1809],[1840,1866],[1958,1968],[2070,2093],[2304,2306],[2362,2362],[2364,2364],[2369,2376],[2381,2381],[2385,2391],[2402,2403],[3633,3633],[3636,3642],[3655,3662],[6832,6911],[7616,7679],[8203,8207],[8232,8238],[8288,8292],[8400,8432],[65024,65039],[65056,65071],[65279,65279],[127995,127999],[917760,917999]],Qe=[[4352,4447],[8986,8987],[9001,9002],[9193,9196],[9200,9200],[9203,9203],[9725,9726],[9748,9749],[9800,9811],[9855,9855],[9875,9875],[9889,9889],[9898,9899],[9917,9918],[9924,9925],[9934,9934],[9940,9940],[9962,9962],[9970,9971],[9973,9973],[9978,9978],[9981,9981],[9989,9989],[9994,9995],[10024,10024],[10060,10060],[10062,10062],[10067,10069],[10071,10071],[10133,10135],[10160,10160],[10175,10175],[11035,11036],[11088,11088],[11093,11093],[11904,12350],[12353,13311],[13312,19903],[19968,40959],[40960,42191],[43360,43391],[44032,55203],[63744,64255],[65040,65049],[65072,65135],[65280,65376],[65504,65510],[94176,94180],[94208,101119],[110592,111359],[126980,126980],[127183,127183],[127374,127374],[127377,127386],[127488,127569],[127744,127776],[127789,127797],[127799,127868],[127870,127891],[127904,127946],[127951,127955],[127968,127984],[127988,127988],[127992,128062],[128064,128064],[128066,128252],[128255,128317],[128331,128334],[128336,128359],[128378,128378],[128405,128406],[128420,128420],[128507,128591],[128640,128709],[128716,128716],[128720,128722],[128725,128727],[128747,128748],[128756,128764],[128992,129003],[129292,129338],[129340,129349],[129351,129535],[129648,129791],[131072,196605],[196608,262141]];function $e(e,t){let n=0,r=t.length-1;for(;n<=r;){let i=n+r>>1,a=t[i];if(e<a[0])r=i-1;else if(e>a[1])n=i+1;else return!0}return!1}function et(e){return e===0||e<32||e>=127&&e<160||$e(e,Ze)?0:$e(e,Qe)?2:1}function tt(e){let t=0,n=!1,r=0;for(let i of e){let e=i.codePointAt(0);if(e===8205){n=!0;continue}let a=et(e);if(a!==0||n){if(n){r=Math.max(r,a),n=!1;continue}t+=r,r=a}}return t+r}function nt(e,t){let n={t:e},r=t.fg,i=t.bg;if(t.inv){let e=r??15;r=i??0,i=e}r!==void 0&&(n.fg=r),i!==void 0&&(n.bg=i),t.b&&(n.b=!0),t.i&&(n.i=!0),t.u&&(n.u=!0),t.s&&(n.s=!0),t.f&&(n.f=!0);let a=tt(e);return a!==oe(e)&&(n.n=a),n}function L(e){return Math.max(0,Math.min(255,e|0))}function rt(e,t){let n=e[t];if(n.length>1){let e=n[1],t=n.slice(2);if(e===5&&t.length>=1)return{color:L(t[0]),consumed:0};if(e===2){let e=t.length>=4?t.slice(1,4):t.slice(0,3);if(e.length===3)return{color:[L(e[0]),L(e[1]),L(e[2])],consumed:0}}return{consumed:0}}let r=e[t+1]?.[0];return r===5&&e[t+2]?{color:L(e[t+2]?.[0]??0),consumed:2}:r===2&&e[t+4]?{color:[L(e[t+2]?.[0]??0),L(e[t+3]?.[0]??0),L(e[t+4]?.[0]??0)],consumed:4}:{consumed:0}}function it(e,t){let n={...e},r=(t===``?[`0`]:t.split(`;`)).map(e=>e.split(`:`).map(e=>e===``?0:Number(e)));for(let e=0;e<r.length;e++){let t=r[e]?.[0]??0;if(t===0)for(let e of Object.keys(n))delete n[e];else if(t===1)n.b=!0;else if(t===2)n.f=!0;else if(t===3)n.i=!0;else if(t===4)n.u=!0;else if(t===7)n.inv=!0;else if(t===9)n.s=!0;else if(t===22)delete n.b,delete n.f;else if(t===23)delete n.i;else if(t===24)delete n.u;else if(t===27)delete n.inv;else if(t===29)delete n.s;else if(t>=30&&t<=37)n.fg=t-30;else if(t===39)delete n.fg;else if(t>=40&&t<=47)n.bg=t-40;else if(t===49)delete n.bg;else if(t>=90&&t<=97)n.fg=t-90+8;else if(t>=100&&t<=107)n.bg=t-100+8;else if(t===38||t===48){let{color:i,consumed:a}=rt(r,e);i!==void 0&&(t===38?n.fg=i:n.bg=i),e+=a}}return n}function at(e){return st(e,{}).line}function ot(e){let t={};return e.map(e=>{let n=st(e,t);return t=n.style,n.line})}function st(e,t){let n=[],r=t,i=``,a=0,o=()=>{i&&n.push(nt(i,r)),i=``},s=0;for(;s<e.length;){let t=e[s];if(t===`\x1B`){let n=e[s+1];if(n===`[`){let n=s+2,a=``;for(;n<e.length&&n-(s+2)<32;){let t=e.charCodeAt(n);if(t>=64&&t<=126)break;a+=e[n],n++}if(n>=e.length||n-(s+2)>=32){i+=t,s++;continue}e[n]===`m`&&(o(),r=it(r,a)),s=n+1;continue}if(n===`]`){let t=s+2;for(;t<e.length&&e[t]!==`\x07`&&(e[t]!==`\x1B`||e[t+1]!==`\\`);)t++;s=e[t]===`\x07`?t+1:t+2;continue}s+=n===void 0?1:2,(n===`(`||n===`)`)&&(s+=1);continue}let n=e.charCodeAt(s);if(t===` `){let e=8-a%8;i+=` `.repeat(e),a+=e,s++;continue}if(n<32||n===127){s++;continue}let c=e.codePointAt(s);i+=String.fromCodePoint(c),a+=et(c),s+=c>65535?2:1}return o(),{line:{r:m(g(n))},style:r}}function ct(e){return e.issue!==void 0&&[`needs-consent`,`automation-denied`,`iterm2-denied`,`timed-out`,`too-old`,`failed`,`limited`].includes(e.issue)}const lt={iterm2:`iTerm2`,tmux:`tmux`,herdr:`Herdr`};function ut(e,t,n={}){let r=lt[e.name]??e.name;if(e.connected&&!e.issue)return{status:`Connected. Ready for your paired phone.`};if(t===`phone`)return ct(e)?{status:`${r} needs one more step on your Mac.`,fix:`Open Shellbell → Settings → Terminals on that Mac, or run shellbell doctor there.`}:{status:`${r} isn't connected right now.`};let i=t===`mac-app`?`Click Connect iTerm2.`:`Run shellbell connect iterm2.`;switch(e.issue){case`not-installed`:return{status:n.noneUsable?`Shellbell couldn't find ${r}.`:`Shellbell couldn't find ${r}. Optional.`,...e.name===`tmux`?{fix:`Install tmux 3.2 or newer, for example: brew install tmux`}:{}};case`not-running`:return e.name===`iterm2`?{status:`iTerm2 isn't open. Open it to see its tabs on your phone.`}:{status:`${r} isn't running.`,fix:`In any terminal, run: ${e.name}`};case`no-session`:return{status:`No tmux session is running.`,fix:`In any terminal, run: tmux`};case`api-off`:return{status:`Turn on iTerm2's Python API to connect.`,fix:`In iTerm2, open Settings → General → Magic and turn on Enable Python API.`};case`needs-consent`:return{status:`Ready to connect.`,fix:`${i} macOS will ask to let Shellbell control iTerm2, and iTerm2 may ask to allow Shellbell. Allow both. Your paired phone can then read and type in your iTerm2 tabs.`};case`connecting`:return{status:`Finish connecting in the macOS or iTerm2 dialog.`};case`automation-denied`:return{status:`macOS is blocking Shellbell from iTerm2.`,fix:`Open System Settings → Privacy & Security → Automation, find Shellbell (or node, for the background service) and turn on iTerm2.`};case`iterm2-denied`:return{status:`iTerm2 is blocking Shellbell.`,fix:`In iTerm2, open Settings → General → Magic and check who may use the Python API. Then ${i.charAt(0).toLowerCase()}${i.slice(1)}`};case`timed-out`:return{status:`Connecting wasn't finished.`,fix:`Check for an open macOS or iTerm2 dialog, then try again. ${i}`};case`too-old`:return e.name===`iterm2`?{status:`Update iTerm2 to connect.`,fix:`Shellbell needs iTerm2 3.3 or newer.`}:e.name===`tmux`?{status:`Shellbell needs tmux 3.2 or newer.`,fix:`Update tmux, for example: brew upgrade tmux`}:{status:`Update ${r} to connect.`};case`limited`:return{status:`Viewing and typing work. Opening new sessions from your phone doesn't.`,...e.detail?{fix:e.detail}:{}};default:return{status:`Shellbell couldn't connect to ${r}.`,fix:e.name===`iterm2`?`Try again. ${i}`:`Shellbell keeps trying.`}}}const dt=[`iterm2`,`tmux`,`herdr`];function ft(e){return!e.some(e=>e.connected)&&dt.every(t=>{let n=e.find(e=>e.name===t);return n!==void 0&&!n.connected&&n.issue===`not-installed`})}function pt(e){let t=`Apple's Terminal only lets other apps see plain text and type whole lines, which isn't enough to use a terminal from your phone, so Shellbell can't use it by itself.`;if(e===`phone`)return{status:`Your Mac needs iTerm2, tmux or Herdr.`,fix:`${t} Install one on your Mac. iTerm2 is the easiest.`};let n=`iTerm2 is the easiest: your phone sees every tab and can open new ones. With tmux or Herdr, sessions you run inside them show on your phone, in Terminal too.`;return{status:`Shellbell needs iTerm2, tmux or Herdr on this Mac.`,fix:e===`command-line`?`${t} ${n} For example: brew install --cask iterm2, or brew install tmux`:`${t} ${n}`}}const mt=`\x1B[?1049l\x1B[!p\x1B[20l\x1B[?12l\x1B[?9l\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?1015l\x1B]104\x07\x1B]110\x07\x1B]111\x07\x1B]112\x07\x1B[0m\x1B[2J\x1B[H`,ht=new Set([`sh`,`bash`,`zsh`,`fish`,`dash`,`ksh`,`pwsh`,`powershell`,`cmd`]),gt=new Set([`ssh`,`mosh`,`docker`,`podman`,`kubectl`,`wsl`]);function _t(e){return j(e??``).replace(/^-/,``).replace(/\.exe$/i,``)}function vt(e,t,n){let r=_t(t),i=ht.has(r)?r:void 0,a=r===`claude`?`Claude`:r===`codex`?`Codex`:void 0,o=gt.has(r);return{...e,shell:i,agentName:a,locality:o?`guest`:n===`local-process`&&(i||a)?`local`:`unknown`,revision:JSON.stringify([e.sessionId,e.cwd,e.title,e.sessionLabel,r,n])}}function R(e,t){if(e===void 0)return;let n=e.replace(/[\r\n\t\u2028\u2029]+/gu,` `).replace(/[\p{Cc}\p{Cs}\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/gu,``).replace(/\s+/gu,` `).trim();if(/(?:^|[\s("'=:])(?:\/|~[\\/]|[a-z]:[\\/])|\\\\|[a-z][a-z0-9+.-]*:\/\/|[^\s@]+@[^\s:]+:/iu.test(n))return;let r=``,i=0;for(let e of n){let n=Buffer.byteLength(e,`utf8`);if(i+n>t)break;i+=n,r+=e}return r||void 0}function yt(e,t){return[...[`Desktop`,`Documents`,`Downloads`].map(e=>P(t,e)),P(t,`Library`,`Mobile Documents`),P(t,`Library`,`CloudStorage`),`/Volumes`].some(t=>{let n=Fe(t,e);return n===``||!n.startsWith(`..${Le}`)&&n!==`..`&&!N(n)})}function bt(e={}){let t=e.now??Date.now,n=e.platform??process.platform,r=e.home??A(),i=new Map,a=0,o=new Set;async function s(e){if(e.aborted||o.size>=32)throw Error(`git context unavailable`);if(a>=2?await new Promise((t,n)=>{let r=()=>{o.delete(i),n(Error(`git context unavailable`))},i=()=>{o.delete(i),e.removeEventListener(`abort`,r),a+=1,t()};o.add(i),e.addEventListener(`abort`,r,{once:!0})}):a+=1,e.aborted)throw--a,o.values().next().value?.(),Error(`git context unavailable`);return()=>{--a,o.values().next().value?.()}}let c={NODE_ENV:`production`,PATH:process.env.PATH,SystemRoot:process.env.SystemRoot,GIT_CONFIG_NOSYSTEM:`1`,GIT_CONFIG_GLOBAL:process.platform===`win32`?`NUL`:`/dev/null`,GIT_CONFIG_COUNT:`0`,GIT_TERMINAL_PROMPT:`0`,GIT_OPTIONAL_LOCKS:`0`,GIT_NO_REPLACE_OBJECTS:`1`},l=(e,t,n)=>new Promise((r,i)=>{pe(`git`,[`-c`,`core.fsmonitor=false`,`-C`,e,...t],{env:c,encoding:`utf8`,signal:n,timeout:250,killSignal:`SIGKILL`,maxBuffer:8192,windowsHide:!0},(e,t)=>e?i(e):r(t.trim()))});return async(e,a)=>{if(!N(e)||e.length>1024||a.aborted||n===`darwin`&&yt(e,r))return;let o=t();for(let[e,t]of i)(o<t.observedAt||o-t.observedAt>=5e3)&&i.delete(e);let c=i.get(e);if(c)return c;let u=new AbortController,d=()=>u.abort();a.addEventListener(`abort`,d,{once:!0});let f=setTimeout(d,250),p;try{p=await s(u.signal);let t=await l(e,[`rev-parse`,`--show-toplevel`],u.signal),n;try{n=await l(e,[`symbolic-ref`,`--quiet`,`--short`,`HEAD`],u.signal)}catch(e){!u.signal.aborted&&e.code===1&&(n=`detached HEAD`)}if(u.signal.aborted)return;let r=R(j(t),256);if(!r)return;let a={repository:r,branch:R(n,256),observedAt:o};return i.size>=500&&i.delete(i.keys().next().value),i.set(e,a),a}catch{return}finally{clearTimeout(f),a.removeEventListener(`abort`,d),p?.()}}}async function xt(e,t){let n=t.now(),r=new AbortController,i,a=new Promise(e=>{i=setTimeout(()=>{r.abort(),e(void 0)},250)}),o=async()=>{if(!await Promise.race([Promise.resolve().then(()=>t.stillCurrent(e)),a]))throw Error(`stale notification context`)};try{await o();let i;e.locality===`local`&&e.cwd&&N(e.cwd)&&(i=await Promise.race([Promise.resolve().then(()=>t.git(e.cwd,r.signal)).catch(()=>void 0),a]));let s=t.stillCurrent(e);if(typeof s==`boolean`?!s:!await Promise.race([s,a]))throw Error(`stale notification context`);let c={computerName:R(t.computerName,128)??`Computer`,sessionLabel:R(e.sessionLabel,128)??`Session`,observedAt:Math.min(n,i?.observedAt??n)};for(let[t,n]of[[`customName`,256],[`title`,256],[`shell`,64],[`agentName`,64]]){let r=R(e[t],n);r&&(c[t]=r)}let l=R(i?.repository,256),u=R(i?.branch,256);if(l&&(c.repository=l),l&&u&&(c.branch=u),!l&&e.locality===`local`&&e.cwd&&N(e.cwd)){let t=R(e.cwd===A()?`~`:j(e.cwd),256);t&&(c.title=t)}return c}finally{clearTimeout(i),r.abort()}}function St(e,t){return e===t||!!e&&!!t&&e.agent===t.agent&&e.kind===t.kind&&e.value===t.value}const Ct={claude:[`claude`,`claude-code`,`claude code`],codex:[`codex`,`codex-cli`,`codex cli`],agy:[`agy`,`antigravity`,`antigravity-cli`],gemini:[`gemini`,`gemini-cli`],cursor:[`cursor`,`cursor-agent`],copilot:[`copilot`,`github-copilot`,`ghcs`],opencode:[`opencode`,`opencode2`,`open-code`],pi:[`pi`],omp:[`omp`],devin:[`devin`,`devin-cli`,`devin cli`],cline:[`cline`,`.cline`],mastracode:[`mastracode`,`mastra-code`,`mastra code`],kimi:[`kimi`,`kimi-code`,`kimi code`],kiro:[`kiro`,`kiro-cli`],droid:[`droid`],amp:[`amp`,`amp-local`],grok:[`grok`,`grok-build`],hermes:[`hermes`,`hermes-agent`],kilo:[`kilo`,`kilo-code`,`kilo code`],qodercli:[`qodercli`,`qoderclicn`,`qoder`,`qodercn`],qwen:[`qwen`,`qwen-code`,`qwen code`],letta:[`letta`,`letta-code`,`letta code`],maki:[`maki`],muse:[`muse`,`muse-code`,`muse-cli`]},wt=new Map(Object.entries(Ct).flatMap(([e,t])=>t.map(t=>[t,e])));function Tt(e){let t=(e??``).trim().toLowerCase().split(/[\\/]/).pop().replace(/\.(cmd|exe)$/,``);if(t)return/^muse-bin-\d/.test(t)?`muse`:wt.get(t)}const Et=`\\u2800-\\u28FF\\u25D0-\\u25D3\\u2722\\u2733\\u2736\\u273B\\u273D\\u00B7\\u2022*`,Dt=RegExp(`^[${Et}][${Et}\\uFE0F]*\\s+(?=\\S)`,`u`),Ot=/^[⠀-⣿]/u,kt=/^v?\d+(?:\.\d+)+$/;function At(e){return e.trim().replace(Dt,``)}function jt(e){let t=e?.trim()??``;return Dt.test(t)}function Mt(e){let t=e?.trim().toLowerCase()??``;return Tt(t)??R(t,32)}const Nt=/^\s*(?:Gemini CLI \(.*\)|[\u25C7\u270B\u23F2\u2726] {2}\S.*\(.*\))\s*$/u;function Pt(e,t){let n=_t(e).toLowerCase(),r=Tt(n);if(r)return r;if(n!==``&&n!==`node`&&!kt.test(n))return;if(Nt.test(t??``))return`gemini`;if(!jt(t))return;let i=t?.trim()??``;return Ot.test(i)&&/ \| [^|]+$/.test(i)?`codex`:`claude`}function Ft(e,t=A()){if(!e)return;let n=e=>e.replace(/[\\/]+$/,``);return t&&n(e)===n(t)?`~`:R(n(e).split(/[\\/]/).pop(),128)}const It=new Set([...ht,...Ct.claude,...Ct.codex,...Ct.agy,`node`,`tmux`,`[tmux]`]);function Lt(e,t){let n=e.trim();if(n&&n!==t&&!n.endsWith(`[dead]`)&&!(It.has(n.toLowerCase())||kt.test(n)))return R(n,128)}function Rt(e){let t=_t(e).toLowerCase();return!t||gt.has(t)?!1:ht.has(t)||Tt(t)!==void 0||t===`node`||kt.test(t)}function zt(e,t,n){if(!e)return;let r=At(e.replace(/[\r\n\t]+/g,` `));if(t===`gemini`&&Nt.test(r))return;if(t===`pi`&&/^\s*π\s+-\s+/u.test(r)){r=r.replace(/^\s*π\s+-\s+/u,``);for(let e of[n.folder,n.project])e&&(r===e||r.endsWith(` - ${e}`))&&(r=r.slice(0,r.length-e.length).replace(/\s+-\s*$/,``))}if(n.command){let e=` (${n.command})`;r.endsWith(e)&&(r=r.slice(0,-e.length).trimEnd())}let i=/ \| ([^|]+)$/.exec(r);i&&(t===`codex`||i[1]?.trim()===n.project||i[1]?.trim()===n.folder)&&(r=r.slice(0,i.index).trimEnd());let a=R(r,256);if(!a)return;let o=a.toLowerCase();if(!(o===t.toLowerCase()||Tt(o))&&!(n.ignore??[]).some(e=>e.toLowerCase()===o))return a}function Bt(e,t){return e.project===t.project&&e.agent?.kind===t.agent?.kind&&e.agent?.task===t.agent?.task}function Vt(e,t,n){let r={};return e&&(r.project=e),t&&(r.agent=n?{kind:t,task:n}:{kind:t}),r}function Ht(e){let t=Ft(e.cwd),n=R(e.project,128)??t,r=Pt(e.processName,e.title);if(!r)return Vt(n,void 0);let i=_t(e.processName);return Vt(n,r,zt(e.title,r,{project:n,folder:t,command:i||void 0,ignore:e.ignore}))}function Ut(e,t){let n=Ft(e.foreground_cwd??e.cwd??void 0),r=R(t,128)??n,i=Mt(e.agent||e.display_agent||void 0);return i?Vt(r,i,zt(e.label||e.terminal_title_stripped||e.terminal_title||void 0,i,{project:r,folder:n,ignore:e.display_agent?[e.display_agent]:[]})):Vt(r,void 0)}var Wt=class{git;onChange;now;known=new Map;pending=new Set;constructor(e,t,n=Date.now){this.git=e,this.onChange=t,this.now=n}get size(){return this.known.size}lookup(e){if(!N(e)||e.length>1024)return;let t=this.known.get(e),n=this.now();return(!t||n<t.at||n-t.at>=3e4)&&this.refresh(e,t?.project),t?.project??void 0}refresh(e,t){if(this.pending.has(e)||this.pending.size>=16)return;this.pending.add(e);let n=new AbortController,r;try{r=this.git(e,n.signal)}catch{r=Promise.resolve(void 0)}r.catch(()=>void 0).then(n=>{let r=R(n?.repository,128)??null;for(this.known.delete(e);this.known.size>=256;){let e=this.known.keys().next().value;if(e===void 0)break;this.known.delete(e)}this.known.set(e,{project:r,at:this.now()}),r!==(t??null)&&this.onChange()}).finally(()=>{this.pending.delete(e),n.abort()})}};function Gt(e,t=te){let n=e=>C({type:`sessions`,list:e,complete:!1}).length<=t,r=({agent:e,stateSince:t,activeAt:n,...r})=>e?{...r,agent:{kind:e.kind,...e.reportsState&&{reportsState:!0}}}:r,i=[r,e=>{let{project:t,windowLabel:n,...i}=r(e);return i},e=>{let{project:t,windowLabel:n,cwd:i,title:a,...o}=r(e);return{...o,title:Array.from(a).slice(0,Kt).join(``)}}];if(n(e))return{type:`sessions`,list:e,complete:!0};let a=e;for(let t of i)if(a=e.map(t),n(a))return{type:`sessions`,list:a,complete:!0};let o=0,s=a.length;for(;o<s;){let e=Math.ceil((o+s)/2);n(a.slice(0,e))?o=e:s=e-1}return{type:`sessions`,list:a.slice(0,o),complete:!1}}const Kt=64,qt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Jt=/^\d{1,12}-\d{1,10}\.rec$/;function Yt(e=ne().dir,t=process.platform){return t===`linux`?`${e}-agents`:e}function Xt(e,t){return P(e,`${t}-sessions`)}function Zt(e,t=ne().dir){return Xt(Yt(t),e)}const Qt=e=>new Map(e.map(e=>[e.slice(0,e.indexOf(`=`)),e.slice(e.indexOf(`=`)+1)]));function $t(e){return!e.startsWith(`/`)||e.length>4096||/[\u0000-\u001f\u007f]/.test(e)||e.split(`/`).some(e=>e===`.`||e===`..`)||e.includes(`//`)?``:e}function en(e,t){let n=t.startsWith(`shellbell-codex-hook 1
1
+ import{$ as e,D as t,Dt as n,Et as r,Ft as i,I as a,It as o,Jt as s,Mt as c,Nt as l,P as u,Pt as d,Q as f,Qn as p,Qt as m,St as h,Xt as g,_n as _,a as v,at as y,c as b,f as ee,gn as te,gt as x,ht as ne,it as re,j as ie,jt as S,kt as ae,lr as C,o as w,qt as oe,r as se,rt as T,s as ce,st as le,tt as ue,yt as de,z as fe}from"./service-lifecycle-ypi9zEPw.js";import{execFile as pe,execFileSync as me,spawn as he}from"node:child_process";import{accessSync as ge,chmodSync as _e,closeSync as ve,constants as E,existsSync as D,fsyncSync as ye,linkSync as be,mkdirSync as xe,openSync as Se,readFileSync as O,readSync as Ce,readdirSync as we,readlinkSync as Te,realpathSync as Ee,renameSync as De,rmSync as Oe,statSync as k,statfsSync as ke,symlinkSync as Ae,unlinkSync as je,writeFileSync as Me}from"node:fs";import{homedir as A}from"node:os";import{basename as j,delimiter as Ne,dirname as M,isAbsolute as N,join as P,normalize as Pe,relative as Fe,resolve as Ie,sep as Le}from"node:path";import{z as Re}from"zod";import{createHash as ze,randomUUID as F}from"node:crypto";import{EventEmitter as Be}from"node:events";import{connect as Ve}from"node:net";import He from"ws";import{isDeepStrictEqual as Ue,promisify as We}from"node:util";import{StringDecoder as Ge}from"node:string_decoder";import{create as Ke,fromBinary as qe,toBinary as Je}from"@bufbuild/protobuf";import{fileDesc as Ye,messageDesc as I}from"@bufbuild/protobuf/codegenv2";import{performance as Xe}from"node:perf_hooks";const Ze=[[768,879],[1155,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1552,1562],[1611,1631],[1648,1648],[1750,1756],[1759,1764],[1767,1768],[1770,1773],[1809,1809],[1840,1866],[1958,1968],[2070,2093],[2304,2306],[2362,2362],[2364,2364],[2369,2376],[2381,2381],[2385,2391],[2402,2403],[3633,3633],[3636,3642],[3655,3662],[6832,6911],[7616,7679],[8203,8207],[8232,8238],[8288,8292],[8400,8432],[65024,65039],[65056,65071],[65279,65279],[127995,127999],[917760,917999]],Qe=[[4352,4447],[8986,8987],[9001,9002],[9193,9196],[9200,9200],[9203,9203],[9725,9726],[9748,9749],[9800,9811],[9855,9855],[9875,9875],[9889,9889],[9898,9899],[9917,9918],[9924,9925],[9934,9934],[9940,9940],[9962,9962],[9970,9971],[9973,9973],[9978,9978],[9981,9981],[9989,9989],[9994,9995],[10024,10024],[10060,10060],[10062,10062],[10067,10069],[10071,10071],[10133,10135],[10160,10160],[10175,10175],[11035,11036],[11088,11088],[11093,11093],[11904,12350],[12353,13311],[13312,19903],[19968,40959],[40960,42191],[43360,43391],[44032,55203],[63744,64255],[65040,65049],[65072,65135],[65280,65376],[65504,65510],[94176,94180],[94208,101119],[110592,111359],[126980,126980],[127183,127183],[127374,127374],[127377,127386],[127488,127569],[127744,127776],[127789,127797],[127799,127868],[127870,127891],[127904,127946],[127951,127955],[127968,127984],[127988,127988],[127992,128062],[128064,128064],[128066,128252],[128255,128317],[128331,128334],[128336,128359],[128378,128378],[128405,128406],[128420,128420],[128507,128591],[128640,128709],[128716,128716],[128720,128722],[128725,128727],[128747,128748],[128756,128764],[128992,129003],[129292,129338],[129340,129349],[129351,129535],[129648,129791],[131072,196605],[196608,262141]];function $e(e,t){let n=0,r=t.length-1;for(;n<=r;){let i=n+r>>1,a=t[i];if(e<a[0])r=i-1;else if(e>a[1])n=i+1;else return!0}return!1}function et(e){return e===0||e<32||e>=127&&e<160||$e(e,Ze)?0:$e(e,Qe)?2:1}function tt(e){let t=0,n=!1,r=0;for(let i of e){let e=i.codePointAt(0);if(e===8205){n=!0;continue}let a=et(e);if(a!==0||n){if(n){r=Math.max(r,a),n=!1;continue}t+=r,r=a}}return t+r}function nt(e,t){let n={t:e},r=t.fg,i=t.bg;if(t.inv){let e=r??15;r=i??0,i=e}r!==void 0&&(n.fg=r),i!==void 0&&(n.bg=i),t.b&&(n.b=!0),t.i&&(n.i=!0),t.u&&(n.u=!0),t.s&&(n.s=!0),t.f&&(n.f=!0);let a=tt(e);return a!==oe(e)&&(n.n=a),n}function L(e){return Math.max(0,Math.min(255,e|0))}function rt(e,t){let n=e[t];if(n.length>1){let e=n[1],t=n.slice(2);if(e===5&&t.length>=1)return{color:L(t[0]),consumed:0};if(e===2){let e=t.length>=4?t.slice(1,4):t.slice(0,3);if(e.length===3)return{color:[L(e[0]),L(e[1]),L(e[2])],consumed:0}}return{consumed:0}}let r=e[t+1]?.[0];return r===5&&e[t+2]?{color:L(e[t+2]?.[0]??0),consumed:2}:r===2&&e[t+4]?{color:[L(e[t+2]?.[0]??0),L(e[t+3]?.[0]??0),L(e[t+4]?.[0]??0)],consumed:4}:{consumed:0}}function it(e,t){let n={...e},r=(t===``?[`0`]:t.split(`;`)).map(e=>e.split(`:`).map(e=>e===``?0:Number(e)));for(let e=0;e<r.length;e++){let t=r[e]?.[0]??0;if(t===0)for(let e of Object.keys(n))delete n[e];else if(t===1)n.b=!0;else if(t===2)n.f=!0;else if(t===3)n.i=!0;else if(t===4)n.u=!0;else if(t===7)n.inv=!0;else if(t===9)n.s=!0;else if(t===22)delete n.b,delete n.f;else if(t===23)delete n.i;else if(t===24)delete n.u;else if(t===27)delete n.inv;else if(t===29)delete n.s;else if(t>=30&&t<=37)n.fg=t-30;else if(t===39)delete n.fg;else if(t>=40&&t<=47)n.bg=t-40;else if(t===49)delete n.bg;else if(t>=90&&t<=97)n.fg=t-90+8;else if(t>=100&&t<=107)n.bg=t-100+8;else if(t===38||t===48){let{color:i,consumed:a}=rt(r,e);i!==void 0&&(t===38?n.fg=i:n.bg=i),e+=a}}return n}function at(e){return st(e,{}).line}function ot(e){let t={};return e.map(e=>{let n=st(e,t);return t=n.style,n.line})}function st(e,t){let n=[],r=t,i=``,a=0,o=()=>{i&&n.push(nt(i,r)),i=``},s=0;for(;s<e.length;){let t=e[s];if(t===`\x1B`){let n=e[s+1];if(n===`[`){let n=s+2,a=``;for(;n<e.length&&n-(s+2)<32;){let t=e.charCodeAt(n);if(t>=64&&t<=126)break;a+=e[n],n++}if(n>=e.length||n-(s+2)>=32){i+=t,s++;continue}e[n]===`m`&&(o(),r=it(r,a)),s=n+1;continue}if(n===`]`){let t=s+2;for(;t<e.length&&e[t]!==`\x07`&&(e[t]!==`\x1B`||e[t+1]!==`\\`);)t++;s=e[t]===`\x07`?t+1:t+2;continue}s+=n===void 0?1:2,(n===`(`||n===`)`)&&(s+=1);continue}let n=e.charCodeAt(s);if(t===` `){let e=8-a%8;i+=` `.repeat(e),a+=e,s++;continue}if(n<32||n===127){s++;continue}let c=e.codePointAt(s);i+=String.fromCodePoint(c),a+=et(c),s+=c>65535?2:1}return o(),{line:{r:m(g(n))},style:r}}function ct(e){return e.issue!==void 0&&[`needs-consent`,`automation-denied`,`iterm2-denied`,`timed-out`,`too-old`,`failed`,`limited`].includes(e.issue)}const lt={iterm2:`iTerm2`,tmux:`tmux`,herdr:`Herdr`};function ut(e,t,n={}){let r=lt[e.name]??e.name;if(e.connected&&!e.issue)return{status:`Connected. Ready for your paired phone.`};if(t===`phone`)return ct(e)?{status:`${r} needs one more step on your Mac.`,fix:`Open Shellbell → Settings → Terminals on that Mac, or run shellbell doctor there.`}:{status:`${r} isn't connected right now.`};let i=t===`mac-app`?`Click Connect iTerm2.`:`Run shellbell connect iterm2.`;switch(e.issue){case`not-installed`:return{status:n.noneUsable?`Shellbell couldn't find ${r}.`:`Shellbell couldn't find ${r}. Optional.`,...e.name===`tmux`?{fix:`Install tmux 3.2 or newer, for example: brew install tmux`}:{}};case`not-running`:return e.name===`iterm2`?{status:`iTerm2 isn't open. Open it to see its tabs on your phone.`}:{status:`${r} isn't running.`,fix:`In any terminal, run: ${e.name}`};case`no-session`:return{status:`No tmux session is running.`,fix:`In any terminal, run: tmux`};case`api-off`:return{status:`Turn on iTerm2's Python API to connect.`,fix:`In iTerm2, open Settings → General → Magic and turn on Enable Python API.`};case`needs-consent`:return{status:`Ready to connect.`,fix:`${i} macOS will ask to let Shellbell control iTerm2, and iTerm2 may ask to allow Shellbell. Allow both. Your paired phone can then read and type in your iTerm2 tabs.`};case`connecting`:return{status:`Finish connecting in the macOS or iTerm2 dialog.`};case`automation-denied`:return{status:`macOS is blocking Shellbell from iTerm2.`,fix:`Open System Settings → Privacy & Security → Automation, find Shellbell (or node, for the background service) and turn on iTerm2.`};case`iterm2-denied`:return{status:`iTerm2 is blocking Shellbell.`,fix:`In iTerm2, open Settings → General → Magic and check who may use the Python API. Then ${i.charAt(0).toLowerCase()}${i.slice(1)}`};case`timed-out`:return{status:`Connecting wasn't finished.`,fix:`Check for an open macOS or iTerm2 dialog, then try again. ${i}`};case`too-old`:return e.name===`iterm2`?{status:`Update iTerm2 to connect.`,fix:`Shellbell needs iTerm2 3.3 or newer.`}:e.name===`tmux`?{status:`Shellbell needs tmux 3.2 or newer.`,fix:`Update tmux, for example: brew upgrade tmux`}:{status:`Update ${r} to connect.`};case`limited`:return{status:`Viewing and typing work. Opening new sessions from your phone doesn't.`,...e.detail?{fix:e.detail}:{}};default:return{status:`Shellbell couldn't connect to ${r}.`,fix:e.name===`iterm2`?`Try again. ${i}`:`Shellbell keeps trying.`}}}const dt=[`iterm2`,`tmux`,`herdr`];function ft(e){return!e.some(e=>e.connected)&&dt.every(t=>{let n=e.find(e=>e.name===t);return n!==void 0&&!n.connected&&n.issue===`not-installed`})}function pt(e){let t=`Apple's Terminal only lets other apps see plain text and type whole lines, which isn't enough to use a terminal from your phone, so Shellbell can't use it by itself.`;if(e===`phone`)return{status:`Your Mac needs iTerm2, tmux or Herdr.`,fix:`${t} Install one on your Mac. iTerm2 is the easiest.`};let n=`iTerm2 is the easiest: your phone sees every tab and can open new ones. With tmux or Herdr, sessions you run inside them show on your phone, in Terminal too.`;return{status:`Shellbell needs iTerm2, tmux or Herdr on this Mac.`,fix:e===`command-line`?`${t} ${n} For example: brew install --cask iterm2, or brew install tmux`:`${t} ${n}`}}const mt=`\x1B[?1049l\x1B[!p\x1B[20l\x1B[?12l\x1B[?9l\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?1015l\x1B]104\x07\x1B]110\x07\x1B]111\x07\x1B]112\x07\x1B[0m\x1B[2J\x1B[H`,ht=new Set([`sh`,`bash`,`zsh`,`fish`,`dash`,`ksh`,`pwsh`,`powershell`,`cmd`]),gt=new Set([`ssh`,`mosh`,`docker`,`podman`,`kubectl`,`wsl`]);function _t(e){return j(e??``).replace(/^-/,``).replace(/\.exe$/i,``)}function vt(e,t,n){let r=_t(t),i=ht.has(r)?r:void 0,a=r===`claude`?`Claude`:r===`codex`?`Codex`:void 0,o=gt.has(r);return{...e,shell:i,agentName:a,locality:o?`guest`:n===`local-process`&&(i||a)?`local`:`unknown`,revision:JSON.stringify([e.sessionId,e.cwd,e.title,e.sessionLabel,r,n])}}function R(e,t){if(e===void 0)return;let n=e.replace(/[\r\n\t\u2028\u2029]+/gu,` `).replace(/[\p{Cc}\p{Cs}\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/gu,``).replace(/\s+/gu,` `).trim();if(/(?:^|[\s("'=:])(?:\/|~[\\/]|[a-z]:[\\/])|\\\\|[a-z][a-z0-9+.-]*:\/\/|[^\s@]+@[^\s:]+:/iu.test(n))return;let r=``,i=0;for(let e of n){let n=Buffer.byteLength(e,`utf8`);if(i+n>t)break;i+=n,r+=e}return r||void 0}function yt(e,t){return[...[`Desktop`,`Documents`,`Downloads`].map(e=>P(t,e)),P(t,`Library`,`Mobile Documents`),P(t,`Library`,`CloudStorage`),`/Volumes`].some(t=>{let n=Fe(t,e);return n===``||!n.startsWith(`..${Le}`)&&n!==`..`&&!N(n)})}function bt(e={}){let t=e.now??Date.now,n=e.platform??process.platform,r=e.home??A(),i=new Map,a=0,o=new Set;async function s(e){if(e.aborted||o.size>=32)throw Error(`git context unavailable`);if(a>=2?await new Promise((t,n)=>{let r=()=>{o.delete(i),n(Error(`git context unavailable`))},i=()=>{o.delete(i),e.removeEventListener(`abort`,r),a+=1,t()};o.add(i),e.addEventListener(`abort`,r,{once:!0})}):a+=1,e.aborted)throw--a,o.values().next().value?.(),Error(`git context unavailable`);return()=>{--a,o.values().next().value?.()}}let c={NODE_ENV:`production`,PATH:process.env.PATH,SystemRoot:process.env.SystemRoot,GIT_CONFIG_NOSYSTEM:`1`,GIT_CONFIG_GLOBAL:process.platform===`win32`?`NUL`:`/dev/null`,GIT_CONFIG_COUNT:`0`,GIT_TERMINAL_PROMPT:`0`,GIT_OPTIONAL_LOCKS:`0`,GIT_NO_REPLACE_OBJECTS:`1`},l=(e,t,n)=>new Promise((r,i)=>{pe(`git`,[`-c`,`core.fsmonitor=false`,`-C`,e,...t],{env:c,encoding:`utf8`,signal:n,timeout:250,killSignal:`SIGKILL`,maxBuffer:8192,windowsHide:!0},(e,t)=>e?i(e):r(t.trim()))});return async(e,a)=>{if(!N(e)||e.length>1024||a.aborted||n===`darwin`&&yt(e,r))return;let o=t();for(let[e,t]of i)(o<t.observedAt||o-t.observedAt>=5e3)&&i.delete(e);let c=i.get(e);if(c)return c;let u=new AbortController,d=()=>u.abort();a.addEventListener(`abort`,d,{once:!0});let f=setTimeout(d,250),p;try{p=await s(u.signal);let t=await l(e,[`rev-parse`,`--show-toplevel`],u.signal),n;try{n=await l(e,[`symbolic-ref`,`--quiet`,`--short`,`HEAD`],u.signal)}catch(e){!u.signal.aborted&&e.code===1&&(n=`detached HEAD`)}if(u.signal.aborted)return;let r=R(j(t),256);if(!r)return;let a={repository:r,branch:R(n,256),observedAt:o};return i.size>=500&&i.delete(i.keys().next().value),i.set(e,a),a}catch{return}finally{clearTimeout(f),a.removeEventListener(`abort`,d),p?.()}}}async function xt(e,t){let n=t.now(),r=new AbortController,i,a=new Promise(e=>{i=setTimeout(()=>{r.abort(),e(void 0)},250)}),o=async()=>{if(!await Promise.race([Promise.resolve().then(()=>t.stillCurrent(e)),a]))throw Error(`stale notification context`)};try{await o();let i;e.locality===`local`&&e.cwd&&N(e.cwd)&&(i=await Promise.race([Promise.resolve().then(()=>t.git(e.cwd,r.signal)).catch(()=>void 0),a]));let s=t.stillCurrent(e);if(typeof s==`boolean`?!s:!await Promise.race([s,a]))throw Error(`stale notification context`);let c={computerName:R(t.computerName,128)??`Computer`,sessionLabel:R(e.sessionLabel,128)??`Session`,observedAt:Math.min(n,i?.observedAt??n)};for(let[t,n]of[[`customName`,256],[`title`,256],[`shell`,64],[`agentName`,64]]){let r=R(e[t],n);r&&(c[t]=r)}let l=R(i?.repository,256),u=R(i?.branch,256);if(l&&(c.repository=l),l&&u&&(c.branch=u),!l&&e.locality===`local`&&e.cwd&&N(e.cwd)){let t=R(e.cwd===A()?`~`:j(e.cwd),256);t&&(c.title=t)}return c}finally{clearTimeout(i),r.abort()}}function St(e,t){return e===t||!!e&&!!t&&e.agent===t.agent&&e.kind===t.kind&&e.value===t.value}const Ct={claude:[`claude`,`claude-code`,`claude code`],codex:[`codex`,`codex-cli`,`codex cli`],agy:[`agy`,`antigravity`,`antigravity-cli`],gemini:[`gemini`,`gemini-cli`],cursor:[`cursor`,`cursor-agent`],copilot:[`copilot`,`github-copilot`,`ghcs`],opencode:[`opencode`,`opencode2`,`open-code`],pi:[`pi`],omp:[`omp`],devin:[`devin`,`devin-cli`,`devin cli`],cline:[`cline`,`.cline`],mastracode:[`mastracode`,`mastra-code`,`mastra code`],kimi:[`kimi`,`kimi-code`,`kimi code`],kiro:[`kiro`,`kiro-cli`],droid:[`droid`],amp:[`amp`,`amp-local`],grok:[`grok`,`grok-build`],hermes:[`hermes`,`hermes-agent`],kilo:[`kilo`,`kilo-code`,`kilo code`],qodercli:[`qodercli`,`qoderclicn`,`qoder`,`qodercn`],qwen:[`qwen`,`qwen-code`,`qwen code`],letta:[`letta`,`letta-code`,`letta code`],maki:[`maki`],muse:[`muse`,`muse-code`,`muse-cli`]},wt=new Map(Object.entries(Ct).flatMap(([e,t])=>t.map(t=>[t,e])));function Tt(e){let t=(e??``).trim().toLowerCase().split(/[\\/]/).pop().replace(/\.(cmd|exe)$/,``);if(t)return/^muse-bin-\d/.test(t)?`muse`:wt.get(t)}const Et=`\\u2800-\\u28FF\\u25D0-\\u25D3\\u2722\\u2733\\u2736\\u273B\\u273D\\u00B7\\u2022*`,Dt=RegExp(`^[${Et}][${Et}\\uFE0F]*\\s+(?=\\S)`,`u`),Ot=/^[⠀-⣿]/u,kt=/^v?\d+(?:\.\d+)+$/;function At(e){return e.trim().replace(Dt,``)}function jt(e){let t=e?.trim()??``;return Dt.test(t)}function Mt(e){let t=e?.trim().toLowerCase()??``;return Tt(t)??R(t,32)}const Nt=/^\s*(?:Gemini CLI \(.*\)|[\u25C7\u270B\u23F2\u2726] {2}\S.*\(.*\))\s*$/u;function Pt(e,t){let n=_t(e).toLowerCase(),r=Tt(n);if(r)return r;if(n!==``&&n!==`node`&&!kt.test(n))return;if(Nt.test(t??``))return`gemini`;if(!jt(t))return;let i=t?.trim()??``;return Ot.test(i)&&/ \| [^|]+$/.test(i)?`codex`:`claude`}function Ft(e,t=A()){if(!e)return;let n=e=>e.replace(/[\\/]+$/,``);return t&&n(e)===n(t)?`~`:R(n(e).split(/[\\/]/).pop(),128)}const It=new Set([...ht,...Ct.claude,...Ct.codex,...Ct.agy,`node`,`tmux`,`[tmux]`]);function Lt(e,t){let n=e.trim();if(n&&n!==t&&!n.endsWith(`[dead]`)&&!(It.has(n.toLowerCase())||kt.test(n)))return R(n,128)}function Rt(e){let t=_t(e).toLowerCase();return!t||gt.has(t)?!1:ht.has(t)||Tt(t)!==void 0||t===`node`||kt.test(t)}function zt(e,t,n){if(!e)return;let r=At(e.replace(/[\r\n\t]+/g,` `));if(t===`gemini`&&Nt.test(r))return;if(t===`pi`&&/^\s*π\s+-\s+/u.test(r)){r=r.replace(/^\s*π\s+-\s+/u,``);for(let e of[n.folder,n.project])e&&(r===e||r.endsWith(` - ${e}`))&&(r=r.slice(0,r.length-e.length).replace(/\s+-\s*$/,``))}if(n.command){let e=` (${n.command})`;r.endsWith(e)&&(r=r.slice(0,-e.length).trimEnd())}let i=/ \| ([^|]+)$/.exec(r);i&&(t===`codex`||i[1]?.trim()===n.project||i[1]?.trim()===n.folder)&&(r=r.slice(0,i.index).trimEnd());let a=R(r,256);if(!a)return;let o=a.toLowerCase();if(!(o===t.toLowerCase()||Tt(o))&&!(n.ignore??[]).some(e=>e.toLowerCase()===o))return a}function Bt(e,t){return e.project===t.project&&e.agent?.kind===t.agent?.kind&&e.agent?.task===t.agent?.task}function Vt(e,t,n){let r={};return e&&(r.project=e),t&&(r.agent=n?{kind:t,task:n}:{kind:t}),r}function Ht(e){let t=Ft(e.cwd),n=R(e.project,128)??t,r=Pt(e.processName,e.title);if(!r)return Vt(n,void 0);let i=_t(e.processName);return Vt(n,r,zt(e.title,r,{project:n,folder:t,command:i||void 0,ignore:e.ignore}))}function Ut(e,t){let n=Ft(e.foreground_cwd??e.cwd??void 0),r=R(t,128)??n,i=Mt(e.agent||e.display_agent||void 0);return i?Vt(r,i,zt(e.label||e.terminal_title_stripped||e.terminal_title||void 0,i,{project:r,folder:n,ignore:e.display_agent?[e.display_agent]:[]})):Vt(r,void 0)}var Wt=class{git;onChange;now;known=new Map;pending=new Set;constructor(e,t,n=Date.now){this.git=e,this.onChange=t,this.now=n}get size(){return this.known.size}lookup(e){if(!N(e)||e.length>1024)return;let t=this.known.get(e),n=this.now();return(!t||n<t.at||n-t.at>=3e4)&&this.refresh(e,t?.project),t?.project??void 0}refresh(e,t){if(this.pending.has(e)||this.pending.size>=16)return;this.pending.add(e);let n=new AbortController,r;try{r=this.git(e,n.signal)}catch{r=Promise.resolve(void 0)}r.catch(()=>void 0).then(n=>{let r=R(n?.repository,128)??null;for(this.known.delete(e);this.known.size>=256;){let e=this.known.keys().next().value;if(e===void 0)break;this.known.delete(e)}this.known.set(e,{project:r,at:this.now()}),r!==(t??null)&&this.onChange()}).finally(()=>{this.pending.delete(e),n.abort()})}};function Gt(e,t=te){let n=e=>C({type:`sessions`,list:e,complete:!1}).length<=t,r=({agent:e,stateSince:t,activeAt:n,...r})=>e?{...r,agent:{kind:e.kind,...e.reportsState&&{reportsState:!0}}}:r,i=[r,e=>{let{project:t,windowLabel:n,...i}=r(e);return i},e=>{let{project:t,windowLabel:n,cwd:i,title:a,...o}=r(e);return{...o,title:Array.from(a).slice(0,Kt).join(``)}}];if(n(e))return{type:`sessions`,list:e,complete:!0};let a=e;for(let t of i)if(a=e.map(t),n(a))return{type:`sessions`,list:a,complete:!0};let o=0,s=a.length;for(;o<s;){let e=Math.ceil((o+s)/2);n(a.slice(0,e))?o=e:s=e-1}return{type:`sessions`,list:a.slice(0,o),complete:!1}}const Kt=64,qt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Jt=/^\d{1,12}-\d{1,10}\.rec$/;function Yt(e=ne().dir,t=process.platform){return t===`linux`?`${e}-agents`:e}function Xt(e,t){return P(e,`${t}-sessions`)}function Zt(e,t=ne().dir){return Xt(Yt(t),e)}const Qt=e=>new Map(e.map(e=>[e.slice(0,e.indexOf(`=`)),e.slice(e.indexOf(`=`)+1)]));function $t(e){return!e.startsWith(`/`)||e.length>4096||/[\u0000-\u001f\u007f]/.test(e)||e.split(`/`).some(e=>e===`.`||e===`..`)||e.includes(`//`)?``:e}function en(e,t){let n=t.startsWith(`shellbell-codex-hook 1
2
2
  `),r=n?t.indexOf(`
3
3
 
4
4
  `):t.length;if(r<0)return null;let[i,...a]=t.slice(0,r).replace(/\n+$/,``).split(`
@@ -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-CLWP08Es.js";import{B as C,H as w,R as T,U as E,W as D,t as O}from"./doctor-7CO6h_gI.js";import{a as k,i as A,o as j,r as M,t as N}from"./service-entry-CjiJBFHG.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
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
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
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-CLWP08Es.js";import{a,n as o,r as s}from"./service-entry-CjiJBFHG.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
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
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
4
4
  `),process.exitCode=1});export{};
@@ -1,4 +1,4 @@
1
- import{A as e,D as t,E as n,Ft as r,Nt as i,O as a,Pt as o,S as s,b as c,c as l,gt as u,h as d,ht as f,i as p,j as m,jt as h,k as g,m as _,p as v,vt as y,w as b,y as x}from"./service-lifecycle-CLWP08Es.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=i(t);if(e&&(!e.isDirectory()||e.isSymbolicLink())&&F(),A(t)===t)break}}function F(){throw new d(`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"?>
1
+ import{A as e,D as t,E as n,Ft as r,Nt as i,O as a,Pt as o,S as s,b as c,c as l,gt as u,h as d,ht as f,i as p,j as m,jt as h,k as g,m as _,p as v,vt as y,w as b,y as x}from"./service-lifecycle-ypi9zEPw.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=i(t);if(e&&(!e.isDirectory()||e.isSymbolicLink())&&F(),A(t)===t)break}}function F(){throw new d(`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
2
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
3
  <plist version="1.0"><dict>
4
4
  <key>Label</key><string>${N}</string>