shellbell 0.13.1 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shellbell",
3
- "version": "0.13.1",
3
+ "version": "0.15.0",
4
4
  "description": "Shellbell agent — mirrors your Mac's terminal sessions to your phone",
5
5
  "type": "module",
6
6
  "imports": {
@@ -42,7 +42,7 @@
42
42
  "tsx": "4.23.13",
43
43
  "typescript": "5.9.3",
44
44
  "vitest": "5.0.0",
45
- "@shellbell/protocol": "0.4.0"
45
+ "@shellbell/protocol": "0.5.0"
46
46
  },
47
47
  "scripts": {
48
48
  "proto:gen": "buf generate",
@@ -1,86 +0,0 @@
1
- import{$ as e,A as t,At as n,Dt as r,E as i,Et as a,F as o,Gt as s,Ht as c,J as l,N as u,Ot as d,R as f,St as p,Ut as m,Y as h,Z as g,_t as _,a as ee,c as te,d as v,dn as ne,dt as y,et as b,fn as re,ft as ie,ht as ae,ir as x,jt as oe,kt as S,o as C,qn as se,qt as ce,r as le,rt as w,s as ue,tt as de,wt as fe,xt as pe}from"./service-lifecycle-CCOIXXFm.js";import{execFile as me,execFileSync as he,spawn as ge}from"node:child_process";import{accessSync as _e,chmodSync as ve,closeSync as ye,constants as T,existsSync as E,fsyncSync as be,linkSync as xe,mkdirSync as Se,openSync as Ce,readFileSync as D,readSync as we,readdirSync as Te,readlinkSync as Ee,realpathSync as De,renameSync as Oe,rmSync as ke,statSync as O,statfsSync as Ae,symlinkSync as je,unlinkSync as Me,writeFileSync as Ne}from"node:fs";import{homedir as k}from"node:os";import{basename as A,delimiter as Pe,dirname as j,isAbsolute as M,join as N,normalize as Fe,relative as Ie,resolve as Le,sep as Re}from"node:path";import{z as ze}from"zod";import{createHash as Be,randomUUID as P}from"node:crypto";import{EventEmitter as Ve}from"node:events";import{connect as He}from"node:net";import Ue from"ws";import{isDeepStrictEqual as We,promisify as Ge}from"node:util";import{StringDecoder as Ke}from"node:string_decoder";import{create as qe,fromBinary as Je,toBinary as Ye}from"@bufbuild/protobuf";import{fileDesc as Xe,messageDesc as F}from"@bufbuild/protobuf/codegenv2";import{performance as Ze}from"node:perf_hooks";const Qe=[[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]],$e=[[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 et(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 tt(e){return e===0||e<32||e>=127&&e<160||et(e,Qe)?0:et(e,$e)?2:1}function nt(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=tt(e);if(a!==0||n){if(n){r=Math.max(r,a),n=!1;continue}t+=r,r=a}}return t+r}function rt(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=nt(e);return a!==c(e)&&(n.n=a),n}function I(e){return Math.max(0,Math.min(255,e|0))}function it(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:I(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:[I(e[0]),I(e[1]),I(e[2])],consumed:0}}return{consumed:0}}let r=e[t+1]?.[0];return r===5&&e[t+2]?{color:I(e[t+2]?.[0]??0),consumed:2}:r===2&&e[t+4]?{color:[I(e[t+2]?.[0]??0),I(e[t+3]?.[0]??0),I(e[t+4]?.[0]??0)],consumed:4}:{consumed:0}}function at(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}=it(r,e);i!==void 0&&(t===38?n.fg=i:n.bg=i),e+=a}}return n}function ot(e){return ct(e,{}).line}function st(e){let t={};return e.map(e=>{let n=ct(e,t);return t=n.style,n.line})}function ct(e,t){let n=[],r=t,i=``,a=0,o=()=>{i&&n.push(rt(i,r)),i=``},c=0;for(;c<e.length;){let t=e[c];if(t===`\x1B`){let n=e[c+1];if(n===`[`){let n=c+2,a=``;for(;n<e.length&&n-(c+2)<32;){let t=e.charCodeAt(n);if(t>=64&&t<=126)break;a+=e[n],n++}if(n>=e.length||n-(c+2)>=32){i+=t,c++;continue}e[n]===`m`&&(o(),r=at(r,a)),c=n+1;continue}if(n===`]`){let t=c+2;for(;t<e.length&&e[t]!==`\x07`&&(e[t]!==`\x1B`||e[t+1]!==`\\`);)t++;c=e[t]===`\x07`?t+1:t+2;continue}c+=n===void 0?1:2,(n===`(`||n===`)`)&&(c+=1);continue}let n=e.charCodeAt(c);if(t===` `){let e=8-a%8;i+=` `.repeat(e),a+=e,c++;continue}if(n<32||n===127){c++;continue}let s=e.codePointAt(c);i+=String.fromCodePoint(s),a+=tt(s),c+=s>65535?2:1}return o(),{line:{r:ce(s(n))},style:r}}function lt(e){return e.issue!==void 0&&[`needs-consent`,`automation-denied`,`iterm2-denied`,`timed-out`,`too-old`,`failed`,`limited`].includes(e.issue)}const ut={iterm2:`iTerm2`,tmux:`tmux`,herdr:`Herdr`};function dt(e,t,n={}){let r=ut[e.name]??e.name;if(e.connected&&!e.issue)return{status:`Connected. Ready for your paired phone.`};if(t===`phone`)return lt(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 ft=[`iterm2`,`tmux`,`herdr`];function pt(e){return!e.some(e=>e.connected)&&ft.every(t=>{let n=e.find(e=>e.name===t);return n!==void 0&&!n.connected&&n.issue===`not-installed`})}function mt(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 ht=`\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`,gt=new Set([`sh`,`bash`,`zsh`,`fish`,`dash`,`ksh`,`pwsh`,`powershell`,`cmd`]),_t=new Set([`ssh`,`mosh`,`docker`,`podman`,`kubectl`,`wsl`]);function vt(e){return A(e??``).replace(/^-/,``).replace(/\.exe$/i,``)}function yt(e,t,n){let r=vt(t),i=gt.has(r)?r:void 0,a=r===`claude`?`Claude`:r===`codex`?`Codex`:void 0,o=_t.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 L(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 bt(e,t){return[...[`Desktop`,`Documents`,`Downloads`].map(e=>N(t,e)),N(t,`Library`,`Mobile Documents`),N(t,`Library`,`CloudStorage`),`/Volumes`].some(t=>{let n=Ie(t,e);return n===``||!n.startsWith(`..${Re}`)&&n!==`..`&&!M(n)})}function xt(e={}){let t=e.now??Date.now,n=e.platform??process.platform,r=e.home??k(),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)=>{me(`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(!M(e)||e.length>1024||a.aborted||n===`darwin`&&bt(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=L(A(t),256);if(!r)return;let a={repository:r,branch:L(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 St(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&&M(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:L(t.computerName,128)??`Computer`,sessionLabel:L(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=L(e[t],n);r&&(c[t]=r)}let l=L(i?.repository,256),u=L(i?.branch,256);if(l&&(c.repository=l),l&&u&&(c.branch=u),!l&&e.locality===`local`&&e.cwd&&M(e.cwd)){let t=L(e.cwd===k()?`~`:A(e.cwd),256);t&&(c.title=t)}return c}finally{clearTimeout(i),r.abort()}}function Ct(e,t){return e===t||!!e&&!!t&&e.agent===t.agent&&e.kind===t.kind&&e.value===t.value}const wt={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`]},Tt=new Map(Object.entries(wt).flatMap(([e,t])=>t.map(t=>[t,e])));function Et(e){let t=(e??``).trim().toLowerCase().split(/[\\/]/).pop().replace(/\.(cmd|exe)$/,``);if(t)return/^muse-bin-\d/.test(t)?`muse`:Tt.get(t)}const Dt=`\\u2800-\\u28FF\\u25D0-\\u25D3\\u2722\\u2733\\u2736\\u273B\\u273D\\u00B7\\u2022*`,Ot=RegExp(`^[${Dt}][${Dt}\\uFE0F]*\\s+(?=\\S)`,`u`),kt=/^[⠀-⣿]/u,At=/^v?\d+(?:\.\d+)+$/;function jt(e){return e.trim().replace(Ot,``)}function Mt(e){let t=e?.trim()??``;return Ot.test(t)}function Nt(e){let t=e?.trim().toLowerCase()??``;return Et(t)??L(t,32)}const Pt=/^\s*(?:Gemini CLI \(.*\)|[\u25C7\u270B\u23F2\u2726] {2}\S.*\(.*\))\s*$/u;function Ft(e,t){let n=vt(e).toLowerCase(),r=Et(n);if(r)return r;if(n!==``&&n!==`node`&&!At.test(n))return;if(Pt.test(t??``))return`gemini`;if(!Mt(t))return;let i=t?.trim()??``;return kt.test(i)&&/ \| [^|]+$/.test(i)?`codex`:`claude`}function It(e,t=k()){if(!e)return;let n=e=>e.replace(/[\\/]+$/,``);return t&&n(e)===n(t)?`~`:L(n(e).split(/[\\/]/).pop(),128)}const Lt=new Set([...gt,...wt.claude,...wt.codex,...wt.agy,`node`,`tmux`,`[tmux]`]);function Rt(e,t){let n=e.trim();if(n&&n!==t&&!n.endsWith(`[dead]`)&&!(Lt.has(n.toLowerCase())||At.test(n)))return L(n,128)}function zt(e){let t=vt(e).toLowerCase();return!t||_t.has(t)?!1:gt.has(t)||Et(t)!==void 0||t===`node`||At.test(t)}function Bt(e,t,n){if(!e)return;let r=jt(e.replace(/[\r\n\t]+/g,` `));if(t===`gemini`&&Pt.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=L(r,256);if(!a)return;let o=a.toLowerCase();if(!(o===t.toLowerCase()||Et(o))&&!(n.ignore??[]).some(e=>e.toLowerCase()===o))return a}function Vt(e,t){return e.project===t.project&&e.agent?.kind===t.agent?.kind&&e.agent?.task===t.agent?.task}function Ht(e,t,n){let r={};return e&&(r.project=e),t&&(r.agent=n?{kind:t,task:n}:{kind:t}),r}function Ut(e){let t=It(e.cwd),n=L(e.project,128)??t,r=Ft(e.processName,e.title);if(!r)return Ht(n,void 0);let i=vt(e.processName);return Ht(n,r,Bt(e.title,r,{project:n,folder:t,command:i||void 0,ignore:e.ignore}))}function Wt(e,t){let n=It(e.foreground_cwd??e.cwd??void 0),r=L(t,128)??n,i=Nt(e.agent||e.display_agent||void 0);return i?Ht(r,i,Bt(e.label||e.terminal_title_stripped||e.terminal_title||void 0,i,{project:r,folder:n,ignore:e.display_agent?[e.display_agent]:[]})):Ht(r,void 0)}var Gt=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(!M(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=L(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 Kt(e,t=ne){let n=e=>x({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,({project:e,windowLabel:t,agent:n,...r})=>r,({project:e,windowLabel:t,agent:n,cwd:r,title:i,...a})=>({...a,title:Array.from(i).slice(0,qt).join(``)})];if(n(e))return{type:`sessions`,list:e,complete:!0};let i=e;for(let[t,a]of r.entries())if(i=e.map(a),n(i))return{type:`sessions`,list:i,complete:t===0};let a=0,o=i.length;for(;a<o;){let e=Math.ceil((a+o)/2);n(i.slice(0,e))?a=e:o=e-1}return{type:`sessions`,list:i.slice(0,a),complete:!1}}const qt=64,Jt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Yt=/^\d{1,12}-\d{1,10}\.rec$/;function Xt(e=y().dir,t=process.platform){return t===`linux`?`${e}-agents`:e}function R(e,t){return N(e,`${t}-sessions`)}function Zt(e,t=y().dir){return R(Xt(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
- `),r=n?t.indexOf(`
3
-
4
- `):t.length;if(r<0)return null;let[i,...a]=t.slice(0,r).replace(/\n+$/,``).split(`
5
- `);if(i!==`shellbell-codex-hook 1`&&i!==`shellbell-agent-hook 2`)return null;let o=Qt(a),s=o.get(`session`);if(n)try{s=JSON.parse(t.slice(r+2))?.session_id}catch{return null}let c=n?`codex`:o.get(`agent`);if(c!==`codex`&&c!==`gemini`)return null;let l=Number(o.get(`time`));if(typeof s!=`string`||!Jt.test(s)||!Number.isSafeInteger(l)||!/^\d{1,9}$/.test(o.get(`pid`)??``)||!o.get(`start`)||!o.get(`tty`))return null;let u=o.get(`tmux`)??``;return Object.freeze({name:e,agent:c,transcript:$t(o.get(`transcript`)??``),time:l*1e3,session:s.toLowerCase(),tmuxSocket:u.split(`,`)[0],tmuxPane:o.get(`tmux_pane`)??``,iterm:(o.get(`iterm`)??``).split(`:`).pop().toLowerCase(),herdr:o.get(`herdr_pane`)??``,process:{pid:Number(o.get(`pid`)),start:o.get(`start`),tty:o.get(`tty`)}})}function tn(e,t){return t.tty!==void 0&&e.process.tty!==t.tty?!1:t.tmux?!!e.tmuxPane&&e.tmuxPane===t.tmux.pane&&e.tmuxSocket===t.tmux.socket:t.iterm?!!e.iterm&&e.iterm===t.iterm.toLowerCase():t.herdr?!!e.herdr&&e.herdr===t.herdr:!1}function nn(e){try{return he(`ps`,[`-o`,`lstart=`,`-p`,String(e)],{encoding:`utf8`,timeout:1e3,env:{PATH:`/usr/bin:/bin`,TZ:`UTC`,LC_ALL:`C`}}).trim().replace(/\s+/g,` `)||null}catch{return null}}function rn(e){try{return process.kill(e,0),!0}catch(e){return e.code===`EPERM`}}var an=class{dir;now;startOf;exists;stamp=``;loadedAt=-1/0;records=[];verified=new Map;dead=new Set;retryAt=new Map;constructor(e,t=()=>Date.now(),n=nn,r=rn){this.dir=e,this.now=t,this.startOf=n,this.exists=r}running(e){let{pid:t,start:n}=e.process,r=`${t}:${n}`;if(this.dead.has(r))return!1;if(!this.exists(t))return this.markDead(r),!1;let i=this.verified.get(r);if(i!==void 0&&this.now()-i<6e4)return!0;let a=this.retryAt.get(r);if(a!==void 0&&this.now()<a)return!1;let o=this.startOf(t);return o===null?(this.retryAt.size>256&&this.retryAt.clear(),this.retryAt.set(r,this.now()+1e4),!1):(this.retryAt.delete(r),o===n?(this.verified.size>256&&this.verified.clear(),this.verified.set(r,this.now()),!0):(this.markDead(r),!1))}markDead(e){this.verified.delete(e),this.dead.size>256&&this.dead.clear(),this.dead.add(e)}load(){if(this.now()-this.loadedAt<1e3)return this.records;this.loadedAt=this.now();let e;try{let t=O(this.dir);if(!t.isDirectory()||process.getuid&&t.uid!==process.getuid())return[];e=Te(this.dir).filter(e=>Yt.test(e))}catch{return this.records=[],this.records}e.sort((e,t)=>Number(t.split(`-`)[0])-Number(e.split(`-`)[0])||(e<t?1:-1));let t=e.join(`/`);if(t===this.stamp)return this.records;let n=[],r=new Set;for(let[t,i]of e.entries()){let e=N(this.dir,i);try{let a=O(e);if(!a.isFile()||a.size>81920||process.getuid&&a.uid!==process.getuid())continue;let o=en(i,D(e,`utf8`)),s=t>=256||this.now()-a.mtimeMs>2592e6,c=o&&`${o.process.pid}:${o.process.start}`;if(c!==null&&r.has(c)||s&&(!o||!this.exists(o.process.pid))){Me(e);continue}c&&r.add(c),o&&n.push(o)}catch{}}return this.stamp=t,this.records=n,n}find(e,t){let n;try{n=this.load()}catch{return null}let r=n.find(n=>tn(n,e)&&(!t||n.process.pid===t.pid&&n.process.start===t.start));return r&&(t||this.running(r))?r:null}};const on=new Map;let sn;function cn(e){e!==sn&&(sn=e,on.clear())}function ln(e){let t=on.get(e)??new an(Zt(e,sn));return on.set(e,t),t}const un={codex:`case "$(ps -o comm= -p "$pid" 2>/dev/null)" in
6
- codex | */codex) agent=$pid; break ;;
7
- esac`,gemini:`case "$(ps -o args= -p "$pid" 2>/dev/null)" in
8
- gemini | "gemini "* | */gemini | */gemini\\ * | */gemini.js | */gemini.js\\ *) agent=$pid; break ;;
9
- esac`};function dn(e,t){return`#!/bin/sh
10
- # Installed by Shellbell. Records which terminal pane runs which ${e} session, so your phone
11
- # can show its full history. Remove it with: shellbell agents remove ${e}
12
- umask 077
13
- dir=${`'${t.replaceAll(`'`,`'\\''`)}'`}
14
- clean() { printf '%s' "$1" | tr -cd 'A-Za-z0-9_.:/%,@=+-' | cut -c1-512; }
15
- # Only these two values are read from the input; the input itself is never saved.
16
- input=$(head -c 65536 | tr '\\n' ' ')
17
- session=$(printf '%s' "$input" | sed -n 's/.*"session_id"[[:space:]]*:[[:space:]]*"\\([0-9A-Fa-f-]\\{36\\}\\)".*/\\1/p')
18
- transcript=$(printf '%s' "$input" | sed -n 's/.*"transcript_path"[[:space:]]*:[[:space:]]*"\\([^"\\\\]*\\)".*/\\1/p')
19
- input=
20
- [ -n "$session" ] || exit 0
21
- case "$transcript" in /*) ;; *) transcript= ;; esac
22
- printf '%s' "$transcript" | LC_ALL=C grep -q '[^A-Za-z0-9 _./@+,%=-]' && transcript=
23
- now=$(date +%s)
24
- tmp="$dir/.$now-$$.tmp"
25
- # The agent process that ran this hook and the terminal it runs in. A record counts only while
26
- # that process runs, and only for an agent with its own terminal: a shared background agent has
27
- # none, and the pane markers it inherited may name another pane, so it records nothing.
28
- pid=$PPID
29
- agent=
30
- i=0
31
- while [ "$i" -lt 8 ] && [ "$pid" -gt 1 ] 2>/dev/null; do
32
- ${un[e]}
33
- pid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ')
34
- i=$((i + 1))
35
- done
36
- [ -n "$agent" ] || exit 0
37
- tty=$(ps -o tty= -p "$agent" 2>/dev/null | tr -d ' ')
38
- case "$tty" in '' | '?' | '??') exit 0 ;; esac
39
- mkdir -p "$dir" 2>/dev/null || exit 0
40
- {
41
- echo 'shellbell-agent-hook 2'
42
- echo "agent=${e}"
43
- echo "time=$now"
44
- echo "pid=$agent"
45
- echo "start=$(TZ=UTC LC_ALL=C ps -o lstart= -p "$agent" 2>/dev/null | tr -s ' ' | sed 's/^ //;s/ $//')"
46
- echo "tty=$(clean "$tty")"
47
- echo "tmux=$(clean "\${TMUX:-}")"
48
- echo "tmux_pane=$(clean "\${TMUX_PANE:-}")"
49
- echo "iterm=$(clean "\${ITERM_SESSION_ID:-}")"
50
- echo "herdr_pane=$(clean "\${HERDR_PANE_ID:-}")"
51
- echo "session=$session"
52
- echo "transcript=$transcript"
53
- } >"$tmp" 2>/dev/null && mv -f "$tmp" "$dir/$now-$$.rec" 2>/dev/null
54
- rm -f "$tmp" 2>/dev/null
55
- exit 0
56
- `}function fn(e,t=k(),n=Xt(e)){return{codexHome:process.env.CODEX_HOME||N(t,`.codex`),stateDir:e,helperDir:n}}const pn=e=>N(e.helperDir,`codex-session-hook.sh`),mn=e=>N(e.codexHome,`hooks.json`),z=e=>N(e.codexHome,`config.toml`),hn=e=>`sh '${pn(e).replaceAll(`'`,`'\\''`)}'`;function gn(e){if(!E(mn(e)))return{};let t=JSON.parse(D(mn(e),`utf8`));if(typeof t!=`object`||!t||Array.isArray(t))throw Error(`${mn(e)} isn't a JSON object; Shellbell left it unchanged.`);return t}function B(e,t,n=384){Se(j(e),{recursive:!0});let r=E(e)?De(e):e,i=E(r)?O(r).mode&511:n,a=`${r}.shellbell-${process.pid}.tmp`;try{Ne(a,t,{mode:i}),Oe(a,r)}finally{ke(a,{force:!0})}}const _n=e=>t=>t.hooks?.some(t=>t.command===hn(e))===!0;function vn(e){let t=/^\[\s*(["']?)([^\]"']+)\1\s*\]\s*(?:#.*)?$/.exec(e.trim());return t?t[2].trim():null}function yn(e){if(!E(z(e)))return`unset`;let t=``;for(let n of D(z(e),`utf8`).split(`
57
- `)){let e=n.trim(),r=vn(e);if(r!==null){if(r.startsWith(`features.`))return`unknown`;t=r;continue}let i=/^["']?hooks["']?\s*=\s*(true|false)\b/.exec(e)?.[1];if(t===`features`&&i)return i===`true`?`on`:`off`;let a=/^["']?features["']?\s*\.\s*["']?hooks["']?\s*=\s*(true|false)\b/.exec(e)?.[1];if(t===``&&a)return a===`true`?`on`:`off`;if(/^\[/.test(e)?/features/.test(e)&&r===null:t===``&&/^["']?features["']?\s*=/.test(e))return`unknown`}return`unset`}function bn(e){return{installed:(gn(e).hooks?.SessionStart??[]).some(_n(e))&&E(pn(e)),hooksFeature:yn(e)}}function xn(e){let t=yn(e);if(t===`off`)throw Error(`Codex hooks are turned off in ${z(e)} (hooks = false). Turn them on, then run this again.`);if(t===`unknown`)throw Error(`${z(e)} sets features in a form Shellbell won't edit. Add hooks = true to Codex's features, then run this again.`);let n=gn(e);B(pn(e),dn(`codex`,R(e.helperDir,`codex`)),448),ve(pn(e),448);let r=n.hooks?.SessionStart??[];if(!r.some(_n(e))){let t={...n,hooks:{...n.hooks,SessionStart:[...r,{hooks:[{type:`command`,command:hn(e),timeout:10}]}]}};B(mn(e),`${JSON.stringify(t,null,2)}\n`)}if(t===`unset`){let t=E(z(e))?D(z(e),`utf8`):``,n=t.split(`
58
- `),r=n.findIndex(e=>vn(e)===`features`);r>=0?n.splice(r+1,0,`hooks = true`):n.push(...t&&!t.endsWith(`
59
- `)?[``]:[],`[features]`,`hooks = true`,``),B(z(e),n.join(`
60
- `))}return bn(e)}function Sn(e){let t=gn(e),n=t.hooks?.SessionStart;if(n?.some(_n(e))){let r=n.filter(t=>!_n(e)(t)),i={...t.hooks};r.length?i.SessionStart=r:delete i.SessionStart,B(mn(e),`${JSON.stringify({...t,hooks:i},null,2)}\n`)}return ke(pn(e),{force:!0}),ke(R(e.helperDir,`codex`),{recursive:!0,force:!0}),bn(e)}const Cn=[`SessionStart`,`BeforeAgent`];function wn(e,t=k(),n=Xt(e)){return{settings:N(process.env.GEMINI_CLI_HOME||t,`.gemini`,`settings.json`),stateDir:e,helperDir:n}}const Tn=e=>N(e.helperDir,`gemini-session-hook.sh`),En=e=>`sh '${Tn(e).replaceAll(`'`,`'\\''`)}'`;function Dn(e){if(!E(e.settings))return{};let t;try{t=JSON.parse(D(e.settings,`utf8`))}catch{return null}if(typeof t!=`object`||!t||Array.isArray(t))return null;let n=t,r=n.hooks;if(r!==void 0&&(typeof r!=`object`||!r||Array.isArray(r)))return null;for(let e of Cn){let t=n.hooks?.[e];if(t!==void 0&&!Array.isArray(t))return null}return n}const On=e=>t=>t?.hooks?.some(t=>t?.name===`shellbell-session`&&t.command===En(e))===!0;function kn(e){let t=Dn(e);if(!t)return{installed:!1,hooks:`unknown`};let n=Cn.every(n=>(t.hooks?.[n]??[]).some(On(e)))&&E(Tn(e)),r=t.hooksConfig?.disabled;return{installed:n,hooks:t.hooksConfig?.enabled===!1||Array.isArray(r)&&r.includes(`shellbell-session`)?`off`:`on`}}function An(e){let t=E(e.settings)?D(e.settings,`utf8`):null,n=Dn(e);if(!n)throw Error(`${e.settings} has comments or settings Shellbell won't rewrite. Remove the comments, then run shellbell agents setup gemini.`);if(kn(e).hooks===`off`)throw Error(`Gemini hooks are turned off in ${e.settings}; Shellbell leaves them off.`);B(Tn(e),dn(`gemini`,R(e.helperDir,`gemini`)),448),ve(Tn(e),448);let r={...n.hooks};for(let t of Cn){let n=r[t]??[];n.some(On(e))||(r[t]=[...n,{hooks:[{type:`command`,name:`shellbell-session`,command:En(e),timeout:5e3}]}])}if((E(e.settings)?D(e.settings,`utf8`):null)!==t)throw Error(`${e.settings} changed while Shellbell was editing it. Try again.`);return B(e.settings,`${JSON.stringify({...n,hooks:r},null,2)}\n`),kn(e)}function jn(e){let t=Dn(e);if(t?.hooks&&Cn.some(n=>t.hooks?.[n]?.some(On(e)))){let n={...t.hooks};for(let t of Cn){let r=(n[t]??[]).filter(t=>!On(e)(t));r.length?n[t]=r:delete n[t]}let{hooks:r,...i}=t,a=Object.keys(n).length?{...i,hooks:n}:i;B(e.settings,`${JSON.stringify(a,null,2)}\n`)}return ke(Tn(e),{force:!0}),ke(R(e.helperDir,`gemini`),{recursive:!0,force:!0}),kn(e)}function Mn(e,t=k(),n=process.platform){let r=Xt(e,n);return{stateDir:e,helperDir:r,home:t,codex:fn(e,t,r),gemini:wn(e,t,r),claudeDir:process.env.CLAUDE_CONFIG_DIR||N(t,`.claude`)}}const Nn=[[`cursor`,`Cursor`,`.cursor/cli-config.json`],[`copilot`,`Copilot`,`.copilot`],[`opencode`,`OpenCode`,`.config/opencode`],[`pi`,`Pi`,`.pi/agent`],[`omp`,`Oh My Pi`,`.omp/agent`],[`devin`,`Devin`,`.config/devin`],[`droid`,`Droid`,`.factory`],[`kimi`,`Kimi`,`.kimi-code`],[`kilo`,`Kilo Code`,`.config/kilo`],[`hermes`,`Hermes`,`.hermes`],[`qodercli`,`Qoder`,`.qoder`],[`qwen`,`Qwen`,`.qwen`],[`mastracode`,`Mastra Code`,`.mastracode`],[`grok`,`Grok`,`.grok`],[`letta`,`Letta`,`.letta`]],Pn=e=>N(e.helperDir,`agent-setup.json`);function Fn(e){try{let t=JSON.parse(D(Pn(e),`utf8`))?.skipped;return new Set(Array.isArray(t)?t.filter(e=>typeof e==`string`):[])}catch{return new Set}}function In(e){Se(e.helperDir,{recursive:!0,mode:448});try{S(e.helperDir,process.getuid?.()??-1)}catch{throw Error(`${e.helperDir} isn't a private folder of yours, so Shellbell won't put agent helpers there.`)}}function Ln(e,t){if(!t.size){ke(Pn(e),{force:!0});return}In(e);let n=`${Pn(e)}.${process.pid}.tmp`;Ne(n,`${JSON.stringify({v:1,skipped:[...t].sort()})}\n`,{mode:384}),Oe(n,Pn(e))}function Rn(e,t){let n={kind:`codex`,name:`Codex`,skipped:t};try{let t=bn(e.codex);return t.installed?t.hooksFeature===`off`?{...n,state:`hooks-off`,helper:!0}:{...n,state:`ready`,helper:!0}:t.hooksFeature===`off`?{...n,state:`hooks-off`,helper:!1}:t.hooksFeature===`unknown`?{...n,state:`blocked`,helper:!1,detail:`Add hooks = true to the [features] section of ${N(e.codex.codexHome,`config.toml`)}.`}:{...n,state:`needs-setup`,helper:!1}}catch(e){return{...n,state:`blocked`,helper:!1,detail:e instanceof Error?e.message:String(e)}}}function zn(e,t){let n={kind:`gemini`,name:`Gemini`,skipped:t},r=kn(e.gemini);return r.hooks===`unknown`?{...n,state:`blocked`,helper:!1,detail:`${e.gemini.settings} has comments or settings Shellbell won't rewrite. Remove the comments, then run shellbell agents setup gemini.`}:r.hooks===`off`?{...n,state:`hooks-off`,helper:r.installed}:{...n,state:r.installed?`ready`:`needs-setup`,helper:r.installed}}function Bn(e){let t=Fn(e),n=[],r={helper:!1,skipped:!1};E(e.claudeDir)&&n.push({kind:`claude`,name:`Claude Code`,state:`ready`,...r}),E(e.codex.codexHome)&&n.push(Rn(e,t.has(`codex`))),E(N(e.home,`.gemini`,`antigravity-cli`))&&n.push({kind:`agy`,name:`Antigravity`,state:`ready`,...r}),E(N(e.gemini.settings,`..`,`tmp`))&&n.push(zn(e,t.has(`gemini`)));for(let[t,i,a]of Nn)E(N(e.home,a))&&n.push({kind:t,name:i,state:`coming-soon`,...r});return n}function Vn(e){return e.filter(e=>e.state===`needs-setup`&&!e.skipped)}function Hn(e,t){let n=e=>!t||t.includes(e);In(e);let r=Fn(e);for(let t of Bn(e))n(t.kind)&&(r.delete(t.kind),t.state===`needs-setup`&&(t.kind===`codex`&&xn(e.codex),t.kind===`gemini`&&An(e.gemini)));return Ln(e,r),Bn(e)}function Un(e,t){let n=Fn(e);for(let e of t)n.add(e);return Ln(e,n),Bn(e)}function Wn(e,t){return In(e),t===`codex`&&Sn(e.codex),t===`gemini`&&jn(e.gemini),Un(e,[t])}function Gn(e){try{S(e.helperDir,process.getuid?.()??-1)}catch{return}for(let t of[`codex`,`gemini`]){let n=N(e.helperDir,`${t}-session-hook.sh`);try{let r=dn(t,R(e.helperDir,t));if(E(n)&&D(n,`utf8`)!==r){let e=`${n}.${process.pid}.tmp`;Ne(e,r,{mode:448}),Oe(e,n)}}catch{}}}function Kn(e){switch(e.state){case`ready`:return e.kind===`codex`?`Ready. Codex sessions started from now on show their full history. If Codex asks, trust Shellbell's helper.`:e.kind===`gemini`?`Ready. Gemini sessions started from now on show their full history.`:`Ready.`;case`needs-setup`:return`Needs a small helper for full history on your phone.`;case`hooks-off`:return e.kind===`gemini`?`Gemini hooks are turned off (in Gemini's settings.json or its /hooks list), so its sessions open as a terminal.`:`Codex hooks are turned off (hooks = false in Codex's config.toml), so its sessions open as a terminal.`;case`blocked`:return e.detail??`Shellbell couldn't change this agent's settings.`;case`coming-soon`:return`Full history coming soon. Opens as a terminal for now.`}}const qn=Ge(me),Jn={iTerm:`iTerm2`},Yn=/\/([^/]+)\.app\/Contents\/MacOS\//;function Xn(e){let t=new Map;for(let n of e.split(`
61
- `)){let e=/^\s*(\d+)\s+(\d+)\s+(.*)$/.exec(n);e&&t.set(Number(e[1]),{ppid:Number(e[2]),args:e[3]})}return t}async function Zn(){if(process.platform===`darwin`)try{let{stdout:e}=await qn(`/bin/ps`,[`-axww`,`-o`,`pid=,ppid=,args=`],{timeout:2e3,maxBuffer:8388608});return Xn(e)}catch{return}}function Qn(e,t){let n=t.get(e)?.ppid;for(let e=0;n!==void 0&&n>1&&e<32;e++){let e=t.get(n);if(!e)return;let r=Yn.exec(e.args)?.[1];if(r)return Jn[r]??r;n=e.ppid}}const $n=[0,7,2],er=`Install Herdr: curl -fsSL https://herdr.dev/install.sh | sh, then start it with "herdr".`,tr=`Upgrade Herdr to 0.7.2 or newer: curl -fsSL https://herdr.dev/install.sh | sh, then restart it.`;var V=class extends Error{code;constructor(e,t){super(`herdr ${e}: ${t}`),this.code=e,this.name=`HerdrError`}};const nr=new Set([`not_found`,`pane_not_found`,`stale_pane_target`]),rr=new Set([`invalid_request`,`unsupported`,`unknown_method`,`method_not_found`]);function ir(e,t){let n=/^\s*v?(\d+)\.(\d+)\.(\d+)/.exec(e);if(!n)return null;let r=[Number(n[1]),Number(n[2]),Number(n[3])];for(let e=0;e<3;e++){let n=r[e],i=t[e];if(n!==i)return n>i}return!0}function ar(e=process.env,t=k()){let n=e.HERDR_SOCKET_PATH;if(n)return n;let r=e.XDG_CONFIG_HOME?N(e.XDG_CONFIG_HOME,`herdr`):N(t,`.config`,`herdr`),i=e.HERDR_SESSION;return i?N(r,`sessions`,i,`herdr.sock`):N(r,`herdr.sock`)}function or(e,t,n){let r=e.code??``;return r===`ENOENT`||r===`ECONNREFUSED`||r===`EACCES`||r===`EPERM`?new V(`unavailable`,`cannot reach the herdr socket at ${n} (${r})`):new V(`socket`,`${t}: ${e.message}`)}function sr(e,t,n,r=1048576){let i=new Ke(`utf8`),a=``;e.on(`data`,e=>{a+=i.write(e);let o=a.indexOf(`
62
- `);for(;o>=0;){let e=a.slice(0,o);a=a.slice(o+1),e.trim()&&t(e),o=a.indexOf(`
63
- `)}Buffer.byteLength(a,`utf8`)>r&&(a=``,n())})}var cr=class{opts;log;nextId=1;constructor(e){this.opts=e,this.log=e.log.child({unit:`herdr`})}get socketPath(){return this.opts.socketPath??ar()}request(e,t={},n={}){let r=n.signal;if(r?.aborted)return Promise.reject(new V(`cancelled`,`request cancelled`));let i=`sb${this.nextId++}`,a=this.opts.requestTimeoutMs??5e3,o=this.socketPath;return new Promise((n,s)=>{let c=!1,l=He({path:o}),u=(e,t)=>{c||(c=!0,clearTimeout(d),r?.removeEventListener(`abort`,f),l.destroy(),e?s(e):n(t))},d=setTimeout(()=>u(new V(`timeout`,`${e} did not answer within ${a} ms`)),a),f=()=>u(new V(`cancelled`,`request cancelled`));r?.addEventListener(`abort`,f,{once:!0}),l.on(`connect`,()=>{c||l.write(`${JSON.stringify({id:i,method:e,params:t})}\n`)}),sr(l,t=>{let n;try{n=JSON.parse(t)}catch{u(new V(`malformed`,`${e} answered with a non-JSON line`));return}if(n.id!==void 0&&n.id!==i&&this.log.debug(`herdr echoed a different id`,{method:e}),n.error){u(new V(n.error.code||`error`,n.error.message||e));return}if(n.result===void 0||n.result===null){u(new V(`malformed`,`${e} answered without a result`));return}u(null,n.result)},()=>u(new V(`overflow`,`${e} answered with an oversized line`)),8388608),l.on(`error`,t=>u(or(t,e,o))),l.on(`close`,()=>u(new V(`closed`,`herdr closed the connection before answering ${e}`))),r?.aborted&&f()})}subscribe(e,t){let n=`sb${this.nextId++}`,r=this.opts.requestTimeoutMs??5e3,i=this.socketPath;return new Promise((a,o)=>{let s=He({path:i}),c=!1,l=!1,u=!1,d={close(){u=!0,s.destroy()}},f=e=>{c||(clearTimeout(m),s.destroy(),o(e))},p=e=>{l||(l=!0,t.onEnd(u?`closed`:e))},m=setTimeout(()=>f(new V(`timeout`,`events.subscribe was not acknowledged`)),r);s.on(`connect`,()=>{s.write(`${JSON.stringify({id:n,method:`events.subscribe`,params:{subscriptions:e}})}\n`)}),sr(s,e=>{let n;try{n=JSON.parse(e)}catch{this.log.warn(`undecodable herdr stream line`,{chars:e.length});return}if(!c){if(n.error){f(new V(n.error.code||`error`,n.error.message||`events.subscribe`));return}let e=n.result?.type;if(e!==`subscription_started`){f(new V(`malformed`,`events.subscribe answered ${e}`));return}c=!0,clearTimeout(m),a(d);return}if(typeof n.event==`string`){let e=n.data&&typeof n.data==`object`?n.data:{};t.onEvent({event:n.event,data:e})}},()=>{c?(s.destroy(),p(`overflow`)):f(new V(`overflow`,`events.subscribe line too long`))}),s.on(`error`,e=>{c?p(`error`):f(or(e,`events.subscribe`,i))}),s.on(`close`,()=>{if(!c){f(new V(`closed`,`herdr closed the connection before acknowledging the stream`));return}p(`eof`)})})}async ping(){let e;try{e=await this.request(`ping`,{})}catch(e){let t=e instanceof Error?e.message:String(e);throw new l(t,er)}let t=typeof e.version==`string`?e.version:``,n=ir(t,$n);if(n===!1)throw new l(`herdr ${t} is older than 0.7.2 (session.snapshot and scroll metrics landed there)`,tr);return n===null&&this.log.warn(`herdr reported an unparseable version; relying on the feature probe`),this.log.debug(`herdr ping ok`,{version:/^\d{1,4}\.\d{1,4}\.\d{1,4}$/.test(t)?t:`unknown`,protocol:typeof e.protocol==`number`&&Number.isSafeInteger(e.protocol)&&e.protocol>=0?e.protocol:`unknown`}),e}};const lr=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,ur=/^[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏] /,dr=/^\[ [!.] \] Action Required \| /;function fr(e){let t=e.trim();if(t.startsWith(`● `))t=t.slice(2);else if(t===`●`)return null;t=t.replace(ur,``).replace(dr,``);let n=t.lastIndexOf(` | `);if(n<=0)return null;let r=t.slice(0,n),i=t.slice(n+3);return i&&!i.includes(` | `)?{name:r,project:i}:null}const pr=new Intl.Segmenter(void 0,{granularity:`grapheme`});function mr(e,t){let n=[...pr.segment(e)].map(e=>e.segment);return n.length<=t?e:`${n.slice(0,t-3).join(``)}...`}function hr(e,t){let n=new Set([mr(A(e),24)]);for(let r=e;r!==j(r);r=j(r))t(N(r,`.git`))&&n.add(mr(A(r),24));return n}function gr(e){let t=Ce(e,`r`);try{let e=[],n=0;for(;n<1048576;){let r=Buffer.alloc(65536),i=we(t,r,0,r.length,n);if(i===0)break;let a=r.subarray(0,i).indexOf(10);if(e.push(r.subarray(0,a<0?i:a)),n+=i,a>=0)return Buffer.concat(e).toString(`utf8`)}return null}finally{ye(t)}}function _r(e){let t=new Date(e),n=e=>String(e).padStart(2,`0`);return N(String(t.getFullYear()),n(t.getMonth()+1),n(t.getDate()))}var vr=class{home;stamp=``;names=new Map;folders=new Map;now;exists;constructor(e,t={}){this.home=e,this.now=t.now??Date.now,this.exists=t.exists??E}find(e,t){let n=e?fr(e):null;if(!n)return null;try{let e=this.load();if(!e)return null;let r=null;for(let[i,a]of e){if(mr(a,48)!==n.name)continue;let e=this.folder(i);if(!e)return null;if((t===void 0||e===t)&&hr(e,this.exists).has(n.project)){if(r)return null;r=i}}return r}catch{return null}}load(){let e=N(this.home,`session_index.jsonl`),t,n;try{let r=O(e);if(!r.isFile()||process.getuid&&r.uid!==process.getuid()||r.size>4194304)return null;if(t=r.size,n=`${r.mtimeMs}:${t}`,n===this.stamp)return this.names}catch{return this.stamp=``,null}let r=Ce(e,`r`),i;try{let e=Buffer.alloc(t);i=e.subarray(0,we(r,e,0,t,0)).toString(`utf8`)}finally{ye(r)}let a=i.split(`
64
- `),o=new Map;for(let e of a)if(e.trim())try{let t=JSON.parse(e);if(typeof t.id!=`string`||!lr.test(t.id))continue;let n=t.id.toLowerCase();o.delete(n),typeof t.thread_name==`string`&&t.thread_name.trim()&&o.set(n,t.thread_name)}catch{}return this.names=o,this.stamp=n,o}folder(e){let t=this.folders.get(e);if(t&&(t.cwd!==null||this.now()-t.at<1e4))return t.cwd;let n=this.readFolder(e);return this.folders.size>=1024&&this.folders.clear(),this.folders.set(e,{cwd:n,at:this.now()}),n}readFolder(e){if(e[14]!==`7`)return null;let t=Number.parseInt(e.slice(0,8)+e.slice(9,13),16),n=N(this.home,`sessions`);for(let r of[0,-1,1]){let i=N(n,_r(t+r*24*60*60*1e3)),a;try{a=Te(i)}catch{continue}let o=a.find(t=>t.startsWith(`rollout-`)&&t.endsWith(`-${e}.jsonl`));if(!o)continue;let s=gr(N(i,o));if(!s)return null;let c=JSON.parse(s),l=c.payload?.cwd;return c.type!==`session_meta`||c.payload?.id!==e?null:typeof l==`string`&&M(l)?l:null}return null}};let yr;function br(){return yr??=new vr(process.env.CODEX_HOME||N(k(),`.codex`)),yr}function xr(e){if(typeof e!=`object`||!e||Array.isArray(e))return null;let t=e,n=t.agent===`agy`?`herdr:antigravity_cli`:`herdr:${t.agent}`;return t.agent!==`claude`&&t.agent!==`codex`&&t.agent!==`agy`||t.source!==n||typeof t.value!=`string`||t.agent===`agy`&&t.kind!==`id`?null:t.kind===`id`&&/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,255}$/.test(t.value)?Object.freeze({agent:t.agent,kind:`id`,value:t.value}):t.kind===`path`&&t.value.length<=4096&&M(t.value)&&Fe(t.value)===t.value&&t.value.endsWith(`.jsonl`)&&!Array.from(t.value).some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)>=127&&e.charCodeAt(0)<=159||e.length===1&&e.charCodeAt(0)>=55296&&e.charCodeAt(0)<=57343)?Object.freeze({agent:t.agent,kind:`path`,value:t.value}):null}function Sr(e,t,n){let r=xr(e?.agent_session),i=e?.agent;if(r||i!==`codex`&&i!==`gemini`||typeof e?.pane_id!=`string`)return r;let a=(t??ln(i)).find({herdr:e.pane_id});if(a)return Object.freeze({agent:i,kind:`id`,value:a.session});if(i!==`codex`||typeof e.terminal_title!=`string`)return null;let o=e.foreground_cwd??e.cwd,s=(n??br()).find(e.terminal_title,typeof o==`string`?o:void 0);return s?Object.freeze({agent:i,kind:`id`,value:s}):null}function Cr(e){if(e===``)return[];let t=e.split(`
65
- `);return t.length>1&&t[t.length-1]===``&&t.pop(),t.map(ot)}function wr(e,t){if(e.length>t)return e.slice(e.length-t);let n=e.slice();for(;n.length<t;)n.push(m());return n}function Tr(e){return e.r.reduce((e,t)=>e+(t.n??nt(t.t)),0)}function Er(e,t){let n=Math.max(0,t-1);for(let t=e.length-1;t>=0;t--){let r=e[t];if(r.r.some(e=>e.t.trim().length>0))return{x:Math.min(n,Tr(r)),y:t}}return{x:0,y:0}}function Dr(e){let t=Math.max(1,e.rows),n=Math.max(1,e.cols),r=wr(Cr(e.text),t);return{cols:n,rows:t,cursor:Er(r,n),lines:r,scrollbackTotal:Math.max(0,e.scrollMax)}}function Or(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function kr(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>=0}function Ar(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>0}function jr(e,t,n){if(!Or(e)||e.type!==`pane_info`||!Or(e.pane))return null;let r=e.pane;if(typeof r.pane_id!=`string`||r.pane_id.length===0||r.pane_id!==t||typeof r.terminal_id!=`string`||r.terminal_id.length===0||r.terminal_id!==n||!kr(r.revision)||!Or(r.scroll))return null;let i=r.scroll;return!kr(i.offset_from_bottom)||!kr(i.max_offset_from_bottom)||!Ar(i.viewport_rows)||i.offset_from_bottom>i.max_offset_from_bottom||i.max_offset_from_bottom>2**53-1-i.viewport_rows?null:{paneId:r.pane_id,terminalId:r.terminal_id,revision:r.revision,history:i.max_offset_from_bottom,viewportRows:i.viewport_rows,offset:i.offset_from_bottom}}function Mr(e,t){if(!Ar(t.rows)||!Ar(t.cols)||t.minRows!==void 0&&(!kr(t.minRows)||t.minRows>t.rows)||typeof t.paneId!=`string`||t.paneId.length===0||t.source!==`visible`&&t.source!==`recent`||!Or(e)||e.type!==`pane_read`||!Or(e.read))return null;let n=e.read;if(typeof n.pane_id!=`string`||n.pane_id.length===0||n.pane_id!==t.paneId||n.source!==t.source||n.format!==`ansi`||typeof n.text!=`string`||typeof n.truncated!=`boolean`)return null;let r=Cr(n.text);return r.length<(t.minRows??t.rows)||r.length>t.rows||r.some(e=>Tr(e)>t.cols)?null:r}function Nr(e,t){let{visible:n,historyRows:r,viewportRows:i,requestedRows:a}=t;if(n.length===0||n.length>i)return null;let o=i-n.length,s=Mr(e,{paneId:t.paneId,source:`recent`,cols:t.cols,rows:a,minRows:Math.max(n.length,Math.min(a,r+i)-o)});if(!s||!We(s.slice(-n.length),n))return null;let c=r+n.length-s.length;return c>=0?{from:c,lines:s}:null}function Pr(e){let[t,...n]=e.trim().split(/\s+/);if(t&&A(t)===`herdr`){if(n.length===0)return``;if(n[0]===`--session`&&n.length===2)return n[1];if(n.length===1&&n[0].startsWith(`--session=`))return n[0].slice(10);if(n[0]===`session`&&n[1]===`attach`&&n.length===3)return n[2]}}function Fr(e,t,n=process.env){let r=new Set;for(let[i,a]of e){let o=Pr(a.args);if(o===void 0||ar({XDG_CONFIG_HOME:n.XDG_CONFIG_HOME,...o?{HERDR_SESSION:o}:{}})!==t)continue;let s=Qn(i,e);s&&r.add(s)}return[...r].sort((e,t)=>e.localeCompare(t)).slice(0,4)}function Ir(e,t){for(let[n,r]of e){let i=r.args.trim().split(/\s+/);if(i.length===4&&A(i[0])===`herdr`&&i[1]===`terminal`&&i[2]===`attach`&&i[3]===t&&Qn(n,e)!==void 0)return!0}return!1}async function Lr(e){let t=await Zn();return t&&Fr(t,e)}const Rr=zr();function zr(){let e={enter:`enter`,tab:`tab`,"shift-tab":`shift+tab`,esc:`esc`,backspace:`backspace`,up:`up`,down:`down`,left:`left`,right:`right`};for(let t of Object.keys(re))/^ctrl-[a-z]$/.test(t)?e[t]=`ctrl+${t.slice(5)}`:/^f([1-9]|1[0-2])$/.test(t)&&(e[t]=t);return e}const Br=Vr();function Vr(){let e=new Map([[`\r`,`enter`],[`
66
- `,`enter`],[` `,`tab`]]);for(let[t,n]of Object.entries(re)){let r=Rr[t];r&&!e.has(n)&&e.set(n,r)}return e}function Hr(e){return Br.get(e)}const Ur=[`.local/bin`,`.cargo/bin`];function Wr(e,t=process.env,n=e=>{try{return _e(e,T.X_OK),O(e).isFile()}catch{return!1}}){let r=t.HOME||k(),i=M(r)?Ur.map(e=>N(r,e)):[];return[...t.PATH?.split(Pe)??[],...i].map(t=>Le(t,e)).find(n)}const Gr=Ge(me);function Kr(e=process.env,t){return Wr(`herdr`,e,t)}async function qr(e={}){let t=e.platform??process.platform,n;try{if(t===`darwin`)n=await Yr(e);else if(t===`linux`)n=Xr(e);else return}catch{return}let r=[...new Set(n)],i=e.executable??Zr;return r.length===1&&M(r[0])&&i(r[0])?r[0]:void 0}function Jr(e){return e.length===2&&A(e[0])===`herdr`&&e[1]===`server`}async function Yr(e){let t=e.ps??(async e=>(await Gr(`/bin/ps`,e,{timeout:2e3,maxBuffer:8388608})).stdout),n=(await t([`-x`,`-ww`,`-o`,`pid=,args=`])).split(`
67
- `).flatMap(e=>{let t=/^\s*(\d+)\s+(?:.*\/)?herdr server\s*$/.exec(e);return t?[t[1]]:[]});return n.length===0?[]:(await t([`-ww`,`-o`,`comm=`,`-p`,n.join(`,`)])).split(`
68
- `).map(e=>e.trim()).filter(e=>A(e)===`herdr`)}function Xr(e){let t=e.procRoot??`/proc`,n=e.uid??process.getuid?.(),r=[];for(let e of Te(t))if(/^\d+$/.test(e))try{if(n!==void 0&&O(N(t,e)).uid!==n)continue;let i=D(N(t,e,`cmdline`),`latin1`).split(`\0`);if(i.at(-1)===``&&i.pop(),!Jr(i))continue;let a=Ee(N(t,e,`exe`));a.endsWith(` (deleted)`)||r.push(a)}catch{}return r}function Zr(e){try{return _e(e,T.X_OK),O(e).isFile()}catch{return!1}}const Qr=Ge(me);var $r=class{opts;executable;issue;env;active=new Map;generation=0;constructor(e){this.opts=e,this.env={...e.env??process.env,HERDR_SOCKET_PATH:e.socketPath}}get available(){return this.executable!==void 0}get verifiedExecutable(){return this.executable===void 0?void 0:Le(this.executable)}get unavailableReason(){return this.executable===void 0?this.issue:void 0}async configure(e){this.close();let t=this.generation;if(!e||ir(e,[0,9,3])!==!0){this.issue=`Update Herdr to 0.9.3 or newer to open Herdr sessions from your phone${e?` (this computer runs ${e.replace(/^v/,``)})`:``}.`;return}let n=this.opts.executable===void 0&&this.defaultSocket()?await(this.opts.findRunningServer??qr)():void 0;if(t!==this.generation)return;let r=this.opts.executable?[this.opts.executable]:[...new Set([n,Kr(this.env)])].filter(e=>e!==void 0);if(r.length===0){this.issue=`Herdr is running, but Shellbell can't find the herdr program. Install it in ~/.local/bin, /opt/homebrew/bin or /usr/local/bin.`;return}let i=e.replace(/^v/,``),a;for(let e of r){let n;try{let t=this.opts.readVersion?await this.opts.readVersion(e):(await Qr(e,[`--version`],{env:this.env,timeout:3e3,maxBuffer:4096})).stdout;n=/\b(?:herdr\s+)?v?(\d+\.\d+\.\d+(?:-[\w.-]+)?)/.exec(t)?.[1]}catch{if(t!==this.generation)return;a??=`Shellbell couldn't run the herdr program. Reinstall Herdr on this computer.`;continue}if(t!==this.generation)return;if(n===i){this.executable=e;return}a??=n?`The herdr program (${n}) and the running Herdr (${i}) are different versions. Quit Herdr and open it again.`:`Shellbell couldn't read the herdr program's version. Reinstall Herdr on this computer.`}this.issue=a}defaultSocket(){let{HERDR_SOCKET_PATH:e,HERDR_SESSION:t,...n}=this.env;return Le(this.opts.socketPath)===Le(ar(n))}close(){this.generation++,this.executable=void 0,this.issue=void 0;for(let e of this.active.values())e();this.active.clear()}async click(t,n,r){let i=this.executable;if(!i||!r()||this.active.has(t)||this.active.size>=4)throw new e(`mouse control unavailable`);if(n.column>=n.cols||n.row>=n.rows)throw new e(`mouse coordinates`);let a=this.generation,o=[`terminal`,`session`,`control`,t,`--cols`,String(n.cols),`--rows`,String(n.rows)],s=this.opts.spawn?this.opts.spawn(i,o,this.env):ge(i,o,{env:this.env,stdio:[`pipe`,`pipe`,`pipe`]});await new Promise((i,o)=>{let c=!1,l=!1,u=Buffer.alloc(0),d=e=>{c||(c=!0,clearTimeout(p),this.active.delete(t),s.kill(`SIGKILL`),e?o(e):i())},f=()=>d(l?Error(`mouse delivery unknown`):new e(`mouse control unavailable`)),p=setTimeout(f,this.opts.timeoutMs??3e3);this.active.set(t,f),s.on(`error`,f),s.stdin.on(`error`,f),s.stderr.resume(),s.stdout.on(`data`,e=>{if(c||l)return;if(u=Buffer.concat([u,e]),u.length>1048576)return f();let t=u.indexOf(10);if(t<0)return;let i;try{i=JSON.parse(u.subarray(0,t).toString(`utf8`))}catch{return f()}if(i.type!==`terminal.frame`||i.width!==n.cols||i.height!==n.rows||a!==this.generation||!r())return f();l=!0,u=Buffer.alloc(0);let o={type:`terminal.mouse`,button:n.button,column:n.column,row:n.row,modifiers:n.modifiers};s.stdin.end(`${[{...o,action:`down`},{...o,action:`up`},{type:`terminal.release`}].map(e=>JSON.stringify(e)).join(`
69
- `)}\n`)}),s.on(`close`,t=>d(t===0&&l?void 0:l?Error(`mouse delivery unknown`):new e(`mouse control unavailable`)))})}},ei=class{options;run;timer;busy=!1;watched=new Set;observations=new Map;watchedMs;backgroundMs;constructor(e){this.options=e,this.watchedMs=Math.max(125,e.watchedMs??125),this.backgroundMs=Math.max(this.watchedMs,e.backgroundMs??1e3)}start(){this.timer&&clearTimeout(this.timer),this.timer=void 0,this.run={};for(let e of this.observations.values())e.due=0;this.schedule()}stop(){this.run=void 0,this.timer&&clearTimeout(this.timer),this.timer=void 0,this.observations.clear()}setWatched(e){let t=new Set(e);for(let e of t)if(!this.watched.has(e)){let t=this.observations.get(e);t&&(t.due=0)}this.watched=t}schedule(){this.run&&!this.timer&&(this.timer=setTimeout(()=>{this.timer=void 0,this.pass().catch(()=>this.reportFailure())},this.watchedMs),this.timer.unref?.())}async pass(){let e=this.run;if(e){if(this.busy){this.schedule();return}this.busy=!0;try{let t=this.options.targets(),n=new Set(t.map(e=>e.id));for(let e of this.observations.keys())n.has(e)||this.observations.delete(e);let r=Date.now(),i=t.map(e=>{let t=this.observations.get(e.id);return(!t||t.identity!==e.identity)&&(t={identity:e.identity,digest:t?.digest,due:0},this.observations.set(e.id,t)),{target:e,observation:t}}).filter(({observation:e})=>e.due<=r).sort((e,t)=>e.observation.due-t.observation.due).slice(0,16),a=0;await Promise.all(Array.from({length:Math.min(4,i.length)},async()=>{for(;this.run===e&&a<i.length;){let t=i[a++];if(!t)return;let{target:n,observation:r}=t;try{let t=await n.read();if(this.run!==e||!n.current())continue;let i=Be(`sha256`).update(JSON.stringify([t.cols,t.rows,t.cursor,t.lines,t.scrollbackTotal])).digest(`hex`);r.digest!==void 0&&r.digest!==i&&this.options.changed(n.id),r.digest=i}catch{this.run===e&&n.current()&&this.reportFailure()}finally{r.due=Date.now()+(this.watched.has(n.id)?this.watchedMs:this.backgroundMs)}}}))}finally{this.busy=!1,this.schedule()}}}reportFailure(){try{this.options.failed()}catch{}}};function ti(e,t){return typeof t==`number`?`${e};5;${t}`:`${e};2;${t[0]};${t[1]};${t[2]}`}function ni(e){let t=[`0`];return e.b&&t.push(`1`),e.f&&t.push(`2`),e.i&&t.push(`3`),e.u&&t.push(`4`),e.s&&t.push(`9`),e.fg!==void 0&&t.push(ti(38,e.fg)),e.bg!==void 0&&t.push(ti(48,e.bg)),`\x1b[${t.join(`;`)}m`}function ri(e){let t=``;for(let n of e.r)t+=ni(n)+n.t.replace(/[\x00-\x1f\x7f]/g,``);return`${t}\x1b[0m`}function ii(e){if(typeof e!=`object`||!e||!(`pane`in e))return;let t=e.pane;if(typeof t!=`object`||!t||!(`agent_status`in t))return;let n=t.agent_status;if(typeof n!=`string`||![`idle`,`working`,`blocked`,`done`,`unknown`].includes(n))return;let r=`agent`in t?t.agent:null,i=`display_agent`in t?t.display_agent:null;if(!(r!=null&&typeof r!=`string`||i!=null&&typeof i!=`string`))return{agent:r||null,displayAgent:i||null,status:n}}var ai=class{options;enabled=!1;closed=!1;busy=!1;evidence=null;constructor(e){this.options=e}enable(){this.enabled=!0}invalidate(){this.evidence=null}close(){this.closed=!0,this.invalidate()}observe(e,t){let n=this.evidence;n&&(!oi(e,n.pane)||!si(t,n.facts))&&this.invalidate()}capture(e,t,n){this.invalidate();let{facts:r,above:i,visible:a}=t;if(!this.enabled||this.closed||!oi(this.options.pane(),e)||e.agent&&(e.agentStatus===`idle`||e.agentStatus===`done`)||!r.source||(r.source.agent!==null||r.source.displayAgent!==null)&&(r.source.status===`idle`||r.source.status===`done`)||r.paneId!==e.paneId||r.terminalId!==e.terminalId||r.offset!==0||r.viewportRows!==e.rows||i.length>r.history||i.length+a.length>1e3||r.history>0&&a.length===0||Buffer.byteLength(n)>se.screenBytes)return;let o=Object.freeze({});return this.evidence={capture:o,pane:{...e},facts:{...r,source:{...r.source}},visible:a},{capture:o,from:r.history-i.length,to:r.history,lines:i,replay:n}}async read(e){if(b(e),e.signal.aborted)return{status:`cancelled`};let t=this.evidence;if(!t||e.capture!==t.capture||e.reported!==t.facts.history)return{status:`unavailable`,reason:`unanchored`};if(!this.owns(t))return{status:`reset`};if(this.busy)return{status:`unavailable`,reason:`busy`};this.busy=!0;let n=()=>e.signal.aborted?{status:`cancelled`}:this.owns(t)?void 0:{status:`reset`};try{if(!await this.confirm(t))return n()??{status:`reset`};let r=n();if(r)return r;let i;if(e.before===0)i={status:`boundary`,reason:`end`,oldestAvailable:0};else{let r=Math.max(0,e.before-e.count),a=Math.max(0,e.reported+t.visible.length-1e3);if(e.before<=a)return{status:`unavailable`,reason:`fetch-window`};let o=Math.min(1e3,t.facts.viewportRows+e.reported-r),s=await this.options.request(`pane.read`,{pane_id:t.pane.paneId,source:`recent`,format:`ansi`,lines:o}),c=n();if(c)return c;let l=Nr(s,{paneId:t.pane.paneId,cols:t.pane.cols,viewportRows:t.facts.viewportRows,historyRows:t.facts.history,requestedRows:o,visible:t.visible});if(!l)return{status:`unavailable`,reason:`changed`};let u=Math.max(r,l.from);if(u>=e.before)return{status:`unavailable`,reason:`fetch-window`};i={status:`page`,from:u,to:e.before,oldestAvailable:0,lines:l.lines.slice(u-l.from,e.before-l.from)}}return await this.confirm(t)?n()??i:n()??{status:`reset`}}catch{return this.evidence===t&&this.invalidate(),n()??{status:`reset`}}finally{this.busy=!1}}owns(e){return!this.closed&&this.evidence===e&&oi(this.options.pane(),e.pane)}async confirm(e){let t=await this.options.request(`pane.get`,{pane_id:e.pane.paneId}),n=jr(t,e.pane.paneId,e.pane.terminalId),r=n?{...n,source:ii(t)}:null;return!r||!si(r,e.facts)?(this.evidence===e&&this.invalidate(),!1):!0}};function oi(e,t){return!!e&&e.paneId===t.paneId&&e.terminalId===t.terminalId&&e.cols===t.cols&&e.rows===t.rows&&e.agent===t.agent&&e.agentStatus===t.agentStatus}function si(e,t){return e.paneId===t.paneId&&e.terminalId===t.terminalId&&e.revision===t.revision&&e.history===t.history&&e.offset===t.offset&&e.viewportRows===t.viewportRows&&e.source?.agent===t.source?.agent&&e.source?.displayAgent===t.source?.displayAgent&&e.source?.status===t.source?.status}const ci=1e3;var H=class extends Error{},li=class extends Ve{opts;log;history;generation=0;historyLines=ci;timer=null;busy=!1;seedWanted=!1;ended=!1;failures=0;readFailureSince=null;waitSupported=!0;wakeSeq=0;seedReason=`refresh`;lastSeedReason=`refresh`;probing=null;continuation={cursor:`guessed`,alternate:`unknown`,probe:()=>(this.probing??=this.probe().finally(()=>{this.probing=null}),this.probing)};shown;constructor(e){super(),this.opts=e,this.log=e.log.child({backend:`herdr`,stream:`vt`}),this.history=new ai(e)}async start(e){e!==void 0&&(this.historyLines=e),await this.reseed()}async reseed(e){this.history.invalidate(),e!==void 0&&e<this.historyLines&&(this.seedReason=this.lastSeedReason),e!==void 0&&(this.historyLines=e),this.seedWanted=!0,await this.run()}close(){this.end(void 0)}async run(){if(!(this.ended||this.busy)){++this.wakeSeq,this.busy=!0,this.timer&&clearTimeout(this.timer),this.timer=null;try{this.seedWanted?await this.seed():await this.poll(),this.failures=0,this.readFailureSince=null}catch(e){if(this.readFailureSince??=Date.now(),e instanceof g||e instanceof V&&nr.has(e.code))this.end(`pane-gone`);else if(Date.now()-this.readFailureSince>=2e3){let t=await this.probeBottomSnapshot();this.ended||this.end(t?e instanceof H?`unsettled`:`failed`:`herdr-unreadable`)}else if(!(e instanceof H)&&++this.failures>=20){this.log.debug(`herdr vt stream failed`,{error:e instanceof Error?e.name:`unknown`});let t=await this.probeBottomSnapshot();this.ended||this.end(t?`failed`:`herdr-unreadable`)}}finally{if(this.busy=!1,!this.ended){if(this.opts.pollMs===void 0&&this.waitSupported&&this.shown&&!this.seedWanted&&this.readFailureSince===null){let e=this.opts.pane();e?this.waitForOutput(this.wakeSeq,e.paneId,this.shown.revision):this.end(`pane-gone`)}else this.schedulePoll(this.opts.pollMs??200)}}}}schedulePoll(e){this.ended||(this.timer=setTimeout(()=>void this.run(),e),this.timer.unref?.())}async waitForOutput(e,t,n){let r=Date.now(),i;try{await Promise.race([this.opts.request(`events.wait`,{match_event:{event:`pane_output_changed`,pane_id:t,min_revision:n+1},timeout_ms:1800}),new Promise(e=>{i=setTimeout(e,2e3),i.unref?.()})])}catch(e){this.waitSupported=!1,e instanceof V&&rr.has(e.code)||this.log.debug(`herdr output wait failed`,{error:e instanceof Error?e.name:`unknown`})}finally{i&&clearTimeout(i)}this.ended||e!==this.wakeSeq||this.schedulePoll(Math.max(0,200-(Date.now()-r)))}current(){let e=this.opts.pane();if(!e)throw this.end(`pane-gone`),new H;return e}async facts(e){let t=await this.opts.request(`pane.get`,{pane_id:e.paneId}),n=jr(t,e.paneId,e.terminalId);if(!n)throw new H;return{...n,source:ii(t)}}async probeBottomSnapshot(){let e=async()=>{try{let e=this.current(),t=await this.opts.request(`pane.read`,{pane_id:e.paneId,source:`detection`,format:`text`});if(t?.type!==`pane_read`||t.read?.pane_id!==e.paneId||t.read.source!==`detection`||t.read.format!==`text`||t.read.truncated||typeof t.read.text!=`string`)return!1;let n=this.current();return n.paneId===e.paneId&&n.terminalId===e.terminalId}catch{return!1}},t;try{return await Promise.race([e(),new Promise(e=>{t=setTimeout(()=>e(!1),1e3)})])}finally{t&&clearTimeout(t)}}async frame(e,t){let n=await this.facts(e);if(n.offset!==0)throw new H;let r=Mr(await this.opts.request(`pane.read`,{pane_id:e.paneId,source:`visible`,format:`ansi`}),{paneId:e.paneId,source:`visible`,rows:n.viewportRows,cols:e.cols,minRows:0});if(!r)throw new H;let i=t(n),a=[];if(i>0&&r.length>0){let t=Math.min(ci,i+r.length),n=Mr(await this.opts.request(`pane.read`,{pane_id:e.paneId,source:`recent`,format:`ansi`,lines:t}),{paneId:e.paneId,source:`recent`,rows:t,cols:e.cols,minRows:r.length});if(!n||!fi(n.slice(-r.length),r))throw new H;a=n.slice(0,-r.length)}let o=await this.facts(e);if(!di(n,o))throw new H;return this.history.observe(e,o),{facts:o,visible:r,above:a}}async seed(){let e=this.current(),t=await this.frame(e,t=>Math.min(e.agent&&ui(e.agentStatus)?this.historyLines:t.history,this.historyLines)),n=pi(t.visible,t.facts.viewportRows),r=mi(t.visible,e.cols),i=[...t.above.map(ri),...n],a=e.agent&&ui(e.agentStatus)&&!this.shown?.idle?`herdr-idle`:this.seedReason;this.lastSeedReason=a,this.seedReason=`refresh`,this.seedWanted=!1,this.generation++,this.shown={cols:e.cols,rows:t.facts.viewportRows,history:t.facts.history,screen:n,cursor:r,idle:ui(e.agentStatus),revision:t.facts.revision};let o=this.history.capture(e,t,`${ht}${i.join(`\r
70
- `)}${r}`);this.emit(`seed`,{generation:this.generation,cols:e.cols,rows:t.facts.viewportRows,data:`\x1bc${i.join(`\r
71
- `)}${r}`,...o?{nativeHistory:o}:{},continuation:{data:`${ht}${n.join(`\r
72
- `)}${r}`,reason:a}})}async poll(){let e=this.shown,t=this.current();if(!e||t.cols!==e.cols){this.seedReason=`resize`,this.seedWanted=!0;return}let n=ui(t.agentStatus);if(t.agent&&n&&!e.idle){this.seedWanted=!0,this.seedReason=`herdr-idle`;return}e.idle=n;let r=!1,i=await this.frame(t,t=>{let n=t.history-e.history;return r=n<0||n+t.viewportRows>1e3,r?0:n});if(r||i.facts.viewportRows!==e.rows||i.above.length!==i.facts.history-e.history){this.seedReason=i.facts.viewportRows===e.rows?`source-gap`:`resize`,this.seedWanted=!0;return}let a=i.above,o=pi(i.visible,i.facts.viewportRows),s=mi(i.visible,t.cols),c=``;if(a.length>0)c=`\x1b[H${[...a.map(ri),...o].map(e=>`\x1b[2K${e}`).join(`\r
73
- `)}`;else for(let t=0;t<o.length;t++)o[t]!==e.screen[t]&&(c+=`\x1b[${t+1};1H\x1b[2K${o[t]}`);(c||s!==e.cursor)&&(c+=s),e.history=i.facts.history,e.revision=i.facts.revision,e.screen=o,e.cursor=s,c&&this.emit(`bytes`,new TextEncoder().encode(c),this.generation)}end(e){this.ended||(this.ended=!0,this.history.close(),++this.wakeSeq,this.timer&&clearTimeout(this.timer),this.timer=null,e&&this.emit(`end`,e))}async probe(){let e=this.generation,t=await this.frame(this.current(),()=>0);return{generation:e,quiescent:!this.ended&&!this.seedWanted&&e===this.generation&&t.facts.revision===this.shown?.revision&&t.facts.viewportRows===this.shown.rows}}};function ui(e){return e===`idle`||e===`done`}function di(e,t){return e.revision===t.revision&&e.history===t.history&&e.viewportRows===t.viewportRows&&e.offset===t.offset&&e.source?.agent===t.source?.agent&&e.source?.displayAgent===t.source?.displayAgent&&e.source?.status===t.source?.status}function fi(e,t){return e.length===t.length&&e.every((e,n)=>ri(e)===ri(t[n]))}function pi(e,t){return Array.from({length:t},(t,n)=>ri(e[n]??{r:[]}))}function mi(e,t){let{x:n,y:r}=Er(e,t);return`\x1b[${r+1};${n+1}H`}const hi=1e3,gi=1e3;function _i(e){let t=[{type:`pane.created`},{type:`pane.closed`},{type:`pane.exited`},{type:`pane.updated`},{type:`pane.focused`},{type:`pane.moved`},{type:`pane.agent_detected`},{type:`tab.created`},{type:`tab.closed`},{type:`tab.focused`},{type:`tab.renamed`},{type:`tab.moved`},{type:`workspace.created`},{type:`workspace.updated`},{type:`workspace.closed`},{type:`workspace.focused`},{type:`workspace.renamed`},{type:`workspace.moved`},{type:`workspace.reordered`},{type:`layout.updated`}];for(let n of e)t.push({type:`pane.agent_status_changed`,pane_id:n}),t.push({type:`pane.scroll_changed`,pane_id:n});return t}const vi=new Set([`working`,`blocked`,`idle`,`done`,`unknown`]);function yi(e){return typeof e==`string`&&vi.has(e)?e:`unknown`}const bi={working:`running`,blocked:`blocked`,idle:`finished`,done:`finished`,unknown:`unknown`};function xi(e){let t=e.foreground_cwd??e.cwd,n=t?t.split(`/`).filter(Boolean).pop():void 0;return e.display_agent||e.agent||e.title||e.terminal_title_stripped||n||`Pane`}function Si(e){return w(e)}function U(e){return typeof e==`string`?e:void 0}function Ci(e){return e&&typeof e==`object`?e:void 0}function wi(e,t){return e.length===t.size&&e.every(e=>t.has(e))}function Ti(e,t){return e.paneId===t.paneId&&e.terminalId===t.terminalId&&e.revision===t.revision&&e.history===t.history&&e.viewportRows===t.viewportRows&&e.offset===t.offset}var Ei=class{opts;name=`herdr`;get capabilities(){return{subscribe:!0,prompts:!1,createSession:!0,terminalInput:!0,terminalPaste:!0,focus:!0,history:!0,absoluteLines:!1,vtStream:!0,...this.mouse.available?{mouseClick:!0}:{}}}mouse;panes=new Map;historyEpochs=new Map;historyCaptures=new WeakMap;byPaneId=new Map;order=[];workspaces=new Set;focusedWorkspace=null;eventSeq=0;conversationEpoch=P();conversationSupported=!1;conversationPending=!0;conversationHintRevision=0;handlers=new Set;log;client;screenObserver;active=null;subscribedPaneIds=new Set;closed=!0;retryTimer=null;syncTimer=null;syncBusy=!1;wantSnapshot=!1;wantResubscribe=!1;shownIn=[];hostAppTimer=null;hostAppGeneration=0;constructor(e){this.opts=e,this.client=e.client,this.mouse=e.mouse??new $r({socketPath:this.client.socketPath}),this.log=e.log.child({backend:`herdr`}),this.screenObserver=new ei({watchedMs:e.screenPollMs,backgroundMs:e.backgroundScreenPollMs,targets:()=>{let e=this.active;return this.closed||!e?.live?[]:[...this.panes].map(([t,n])=>({id:t,identity:n.paneId,current:()=>{let r=this.panes.get(t);return!this.closed&&this.active===e&&r?.paneId===n.paneId&&r.rows===n.rows&&r.cols===n.cols},read:()=>this.getScreen(t)}))},changed:e=>{this.historyEpochs.delete(e),this.emit({type:`screen-changed`,sessionId:e})},failed:()=>this.log.warn(`herdr screen observation failed`)})}get isConnected(){return!this.closed&&this.active!==null}async connect(){this.closed=!1,this.conversationSupported=!1;let e=await this.client.ping();this.conversationSupported=typeof e.version==`string`&&/^v?\d+\.\d+\.\d+$/.test(e.version.trim())&&ir(e.version,[0,9,5])===!0,await this.mouse.configure(e.version);let t=[];try{t=Di((await this.client.request(`session.snapshot`,{}))?.snapshot).panes.map(e=>e.pane_id)}catch(e){throw this.unavailable(e)}try{await this.openStream(t)}catch(e){throw e instanceof l?e:this.unavailable(e)}this.hostAppTimer&&clearTimeout(this.hostAppTimer),this.hostAppGeneration++,this.refreshHostApps()}async waitForVisibleAttach(e,{timeoutMs:t=15e3,intervalMs:n=250}={}){let r=Date.now()+t;for(;;){let t=await(this.opts.processTable??Zn)().catch(()=>void 0);if(!t&&(this.opts.platform??process.platform)!==`darwin`||t&&Ir(t,e))return!0;if(this.closed||Date.now()>=r)return!1;await new Promise(e=>setTimeout(e,n))}}async refreshHostApps(){this.hostAppTimer=null;let e=this.hostAppGeneration,t=await(this.opts.hostApps??Lr)(this.client.socketPath).catch(()=>void 0)??[];this.closed||e!==this.hostAppGeneration||(t.join(`
74
- `)!==this.shownIn.join(`
75
- `)&&(this.shownIn=t,this.emit({type:`layout-changed`})),this.hostAppTimer=setTimeout(()=>void this.refreshHostApps(),this.opts.hostAppPollMs??1e4),this.hostAppTimer.unref?.())}unavailable(e){if(e instanceof l)return e;let t=e instanceof Error?e.message:String(e);return e instanceof V&&rr.has(e.code)?new l(`herdr does not support session.snapshot (${t})`,tr):e instanceof V&&e.code===`malformed`?new l(`herdr answered session.snapshot with junk (${t})`,tr):new l(t,er)}async close(){this.closed=!0,this.mouse.close(),this.screenObserver.stop(),this.retryTimer&&clearTimeout(this.retryTimer),this.retryTimer=null,this.syncTimer&&clearTimeout(this.syncTimer),this.syncTimer=null,this.hostAppTimer&&clearTimeout(this.hostAppTimer),this.hostAppTimer=null,this.hostAppGeneration++,this.shownIn=[];let e=this.active;this.active=null,e&&(e.cancelled=!0,e.stream?.close()),this.panes.clear(),this.historyEpochs.clear(),this.byPaneId.clear(),this.order=[],this.wantSnapshot=!1,this.wantResubscribe=!1,this.syncBusy=!1,this.subscribedPaneIds.clear(),this.handlers.clear()}on(e){return this.handlers.add(e),()=>this.handlers.delete(e)}async conversationReference(e,t){let n=this.panes.get(e),r=this.active;if(t.aborted||!n||!this.isConnected||!r?.live||this.conversationPending||!this.conversationSupported)return null;let i=n.conversationOwner,a=n.conversationRevision,o=this.conversationEpoch;try{let s=await this.client.request(`pane.get`,{pane_id:n.paneId},{signal:t}),c=this.panes.get(e);if(t.aborted||this.closed||this.active!==r||this.conversationPending||this.conversationEpoch!==o||!c||c.paneId!==n.paneId||c.conversationOwner!==i||s?.pane?.pane_id!==n.paneId||s.pane.terminal_id!==e||!Number.isSafeInteger(s.pane.revision)||s.pane.revision<a)return null;let l=Sr(s.pane);return this.setConversationReference(c,l,s.pane.revision),c.conversationSeq=++this.eventSeq,t.aborted||this.closed||this.active!==r||this.conversationPending||this.conversationEpoch!==o||this.panes.get(e)!==c||!Ct(l,c.conversation)?null:l?Object.freeze({...l,owner:`${o}:${c.conversationOwner}`}):null}catch(e){return e instanceof V&&nr.has(e.code)&&(this.invalidateConversations(),this.scheduleSync(`snapshot`)),null}}setConversationReference(e,t,n){n<e.conversationRevision||(n>e.conversationRevision&&(e.conversationRevision=n,e.conversationSeq=++this.eventSeq),!Ct(e.conversation,t)&&(e.conversation=t,e.conversationOwner=P(),e.conversationSeq=++this.eventSeq,this.emit({type:`conversation-changed`,sessionId:e.terminalId})))}invalidateConversations(){if(this.conversationHintRevision++,!this.conversationPending){this.conversationPending=!0,this.conversationEpoch=P();for(let e of this.panes.values())this.emit({type:`conversation-changed`,sessionId:e.terminalId})}}async notificationFacts(e){let t=this.panes.get(e);if(!t||!this.isConnected)return;let n=t.naming.agent?.kind;return yt({sessionId:e,cwd:t.cwd,title:t.title,sessionLabel:`Herdr`},n,n?`local-process`:`reported`)}async listSessions(){return this.order.map(e=>this.panes.get(e)).filter(e=>e!==void 0).map(e=>this.toInfo(e))}async getScreen(e,t){let n=this.pane(e),r=t?.history?this.captureEpoch(n):void 0;n.scrollStale&&await this.refreshScroll(n);let i=r&&this.ownsHistory(r)?await this.historyFacts(r):void 0,a=!n.scrollStale&&n.scrollOffset===0&&(!i||!(`facts`in i)||i.facts.offset===0)?`visible`:`detection`,o=t=>this.call(e,`pane.read`,{pane_id:n.paneId,source:t,format:t===`visible`?`ansi`:`text`}),s=await o(a);if(a===`visible`&&(n.scrollStale||n.scrollOffset!==0)&&(a=`detection`,s=await o(a)),a===`detection`&&(s?.type!==`pane_read`||s.read?.pane_id!==n.paneId||s.read.source!==`detection`||s.read.format!==`text`||s.read.truncated||typeof s.read.text!=`string`))throw Error(`Herdr live bottom screen unavailable`);let c=Dr({text:s?.read?.text??``,rows:n.rows,cols:n.cols,scrollMax:n.scrollMax});if(a===`detection`||!r||!this.ownsHistory(r)||!i||!(`facts`in i))return c;let l=Mr(s,{paneId:r.paneId,source:`visible`,rows:r.rows,cols:r.cols,minRows:0});if(!l||i.facts.offset!==0)return c;let u=await this.historyFacts(r);if(!this.ownsHistory(r)||!(`facts`in u))return c;if(!Ti(i.facts,u.facts))return this.revokeHistory(r),c;r.certified=u.facts;let d=Object.freeze({});this.historyCaptures.set(d,{epoch:r,facts:u.facts,visible:l}),c.scrollbackTotal=u.facts.history;let f=this.pane(e);return f.scrollMax=u.facts.history,f.scrollOffset=u.facts.offset,f.scrollEventSeq=++this.eventSeq,c.historyCapture=d,c}async getHistoryPage(e,t){if(b(t),t.signal.aborted)return{status:`cancelled`};this.pane(e);let n=this.historyCaptures.get(t.capture);if(!n||n.epoch.sessionId!==e)return{status:`unavailable`,reason:`unanchored`};let{epoch:r,facts:i}=n,a=()=>t.signal.aborted?{status:`cancelled`}:this.ownsHistory(r)?void 0:{status:`reset`},o=a();if(o)return o;if(t.reported<i.history||t.reported>2**53-1-i.viewportRows)return{status:`unavailable`,reason:`unanchored`};let s=await this.historyFacts(r),c=a();if(c)return c;if(!(`facts`in s))return{status:`unavailable`,reason:s.reason};if(!Ti(i,s.facts))return this.revokeHistory(r),{status:`reset`};let l=t.reported-i.history,u;if(t.before<=l)u={status:`boundary`,reason:t.before===l?`end`:`truncated`,oldestAvailable:l};else{let e=Math.max(t.before-t.count,l),o=t.reported+n.visible.length-hi;if(t.before<=o)return{status:`unavailable`,reason:`fetch-window`};let s=Math.min(hi,i.viewportRows+(t.reported-e));if(!Number.isSafeInteger(s)||s<1||s>hi)return{status:`unavailable`,reason:`fetch-window`};let c;try{c=await this.client.request(`pane.read`,{pane_id:r.paneId,source:`recent`,format:`ansi`,lines:s})}catch(e){return a()??{status:`unavailable`,reason:e instanceof V&&e.code===`agent_not_idle`?`busy`:`changed`}}let d=a();if(d)return d;let f=Nr(c,{paneId:r.paneId,cols:r.cols,viewportRows:i.viewportRows,historyRows:i.history,requestedRows:s,visible:n.visible});if(!f)return{status:`unavailable`,reason:`changed`};let p=l+f.from,m=Math.max(e,p);if(m>=t.before)return{status:`unavailable`,reason:`fetch-window`};u={status:`page`,from:m,to:t.before,oldestAvailable:l,lines:f.lines.slice(m-p,t.before-p)}}let d=await this.historyFacts(r);return a()||(`facts`in d?Ti(i,d.facts)?(r.certified=d.facts,u):(this.revokeHistory(r),{status:`reset`}):{status:`unavailable`,reason:d.reason})}captureEpoch(e){if(this.closed||!this.active||this.active.cancelled||e.scrollOffset!==void 0&&e.scrollOffset!==0)return;let t=this.historyEpochs.get(e.terminalId);if(t&&this.ownsHistory(t))return t;let n={sessionId:e.terminalId,paneId:e.paneId,stream:this.active,revision:e.revision,cols:e.cols,rows:e.rows};return this.historyEpochs.set(e.terminalId,n),n}ownsHistory(e){let t=this.panes.get(e.sessionId);return!this.closed&&this.active===e.stream&&!e.stream.cancelled&&this.historyEpochs.get(e.sessionId)===e&&t?.paneId===e.paneId&&t.cols===e.cols&&t.rows===e.rows&&t.revision===e.revision}revokeHistory(e){this.historyEpochs.get(e.sessionId)===e&&this.historyEpochs.delete(e.sessionId)}async historyFacts(e){try{let t=await this.client.request(`pane.get`,{pane_id:e.paneId}),n=jr(t,t?.pane?.pane_id,t?.pane?.terminal_id);return n?(this.ownsHistory(e)&&(n.paneId!==e.paneId||n.terminalId!==e.sessionId||n.viewportRows!==e.rows||e.certified&&!Ti(e.certified,n))&&this.revokeHistory(e),{facts:n}):{reason:`changed`}}catch(e){return{reason:e instanceof V&&e.code===`agent_not_idle`?`busy`:`changed`}}}async getHistory(e,t,n){let r=this.pane(e),i=this.active,{scrollMax:a,rows:o,cols:s}=r,c=Math.max(0,a-t),u=Math.min(hi,c+n+o),d=await this.call(e,`pane.read`,{pane_id:r.paneId,source:`recent`,format:`ansi`,lines:u}),f=()=>new l(`History temporarily unavailable`,`Retry history after output settles.`),p=Mr(await this.call(e,`pane.read`,{pane_id:r.paneId,source:`visible`,format:`ansi`}),{paneId:r.paneId,source:`visible`,rows:o,cols:s,minRows:0});if(!p)throw f();let m=Nr(d,{paneId:r.paneId,cols:s,viewportRows:o,historyRows:a,requestedRows:u,visible:p});if(!m||t>0&&m.from>=t||this.closed||this.active!==i||i?.cancelled||this.panes.get(e)!==r||r.rows!==o||r.cols!==s||r.scrollMax!==a)throw f();let h=Math.max(0,a-c-m.from),g=Math.max(0,h-n),_=m.lines.slice(g,h);return{lines:_,oldestAvailable:m.from===0&&g===0?Math.max(0,t-_.length):0}}async sendText(e,t){let n=this.pane(e),r=Hr(t);if(r){this.log.debug(`herdr key`),await this.call(e,`pane.send_keys`,{pane_id:n.paneId,keys:[r]});return}if(this.log.debug(`herdr text`,{len:t.length}),t.endsWith(`\r`)||t.endsWith(`
76
- `)){let r=t.slice(0,-1);r&&await this.call(e,`pane.send_text`,{pane_id:n.paneId,text:r}),await this.call(e,`pane.send_keys`,{pane_id:n.paneId,keys:[`enter`]});return}await this.call(e,`pane.send_text`,{pane_id:n.paneId,text:t})}async clickMouse(t,n){let r=this.pane(t),i=this.active,a=()=>{let e=this.panes.get(t);return!this.closed&&this.active===i&&i?.live===!0&&e?.paneId===r.paneId&&e.cols===n.cols&&e.rows===n.rows&&(e.scrollOffset??0)===0};if(!this.mouse.available||!a())throw new e(`mouse input unavailable`);let o=Di((await this.client.request(`session.snapshot`,{}))?.snapshot),s=o.panes.find(e=>e.terminal_id===t),c=o.layouts.flatMap(e=>e.panes).find(e=>e.pane_id===r.paneId)?.rect;if(!a()||s?.pane_id!==r.paneId||s.scroll?.offset_from_bottom!==0||c?.width!==n.cols||c.height!==n.rows)throw new e(`mouse grid changed`);await this.mouse.click(t,n,a)}async sendInput(e,t){let n=this.pane(e);await this.call(e,`pane.send_text`,{pane_id:n.paneId,text:t})}async paste(e,t,n){let r=this.pane(e);await this.call(e,`pane.send_input`,{pane_id:r.paneId,text:t,keys:n?[`Enter`]:[]})}async createSession(e){if(e.kind===`split`){let t=this.pane(e.sessionId),n=U((await this.client.request(`pane.split`,{target_pane_id:t.paneId,direction:e.direction===`vertical`?`right`:`down`,focus:!1}))?.pane?.terminal_id);if(!n)throw Error(`herdr pane.split returned no terminal_id`);return this.scheduleSync(`snapshot`),n}if(e.windowId!==void 0&&!this.workspaces.has(e.windowId))throw new h(e.windowId);let t=e.windowId??this.focusedWorkspace??[...this.workspaces][0];if(!t)return this.createWorkspaceSession();let n=U((await this.client.request(`tab.create`,{workspace_id:t,focus:!1}))?.root_pane?.terminal_id);if(!n)throw Error(`herdr tab.create returned no terminal_id`);return this.scheduleSync(`snapshot`),n}async createWorkspaceSession(){return(await this.createWorkspace()).terminalId}async createWorkspace(){let e=await this.client.request(`workspace.create`,{cwd:k(),focus:!1}),t=U(e?.root_pane?.terminal_id);if(!t)throw Error(`herdr workspace.create returned no terminal_id`);this.scheduleSync(`snapshot`);let n=U(e?.workspace?.workspace_id)??U(e?.root_pane?.workspace_id);return n?{terminalId:t,workspaceId:n}:{terminalId:t}}async closeWorkspace(e){await this.client.request(`workspace.close`,{workspace_id:e}),this.scheduleSync(`snapshot`)}get terminalSocketPath(){return this.client.socketPath}get terminalAttachExecutable(){return this.isConnected?this.mouse.verifiedExecutable:void 0}get terminalAttachIssue(){return this.isConnected&&this.terminalAttachExecutable===void 0?this.mouse.unavailableReason:void 0}async focus(e){let t=this.pane(e);await this.call(e,`pane.focus`,{pane_id:t.paneId})}setWatched(e){this.screenObserver.setWatched(e)}emit(e){for(let t of this.handlers)try{t(e)}catch(e){this.log.warn(`event handler failed`,{error:Si(e)})}}openVtStream(e){return this.pane(e),new li({request:(t,n)=>this.call(e,t,n),pane:()=>{let t=this.closed?void 0:this.panes.get(e);return t&&{paneId:t.paneId,terminalId:t.terminalId,cols:t.cols,rows:t.rows,agentStatus:t.agentStatus,agent:t.naming.agent!==void 0}},log:this.opts.log})}pane(e){let t=this.panes.get(e);if(!t)throw new g(e);return t}async call(e,t,n){try{return await this.client.request(t,n)}catch(t){throw t instanceof V&&nr.has(t.code)?(this.scheduleSync(`snapshot`),new g(e)):t}}toInfo(e){return{id:e.terminalId,backend:`herdr`,title:e.title,cwd:e.cwd,...e.naming,...e.windowLabel?{windowLabel:e.windowLabel}:{},cols:Math.max(1,e.cols),rows:Math.max(1,e.rows),windowId:e.workspaceId,windowNumber:e.windowNumber,tabId:e.tabId,tabIndex:e.tabIndex,paneIndex:e.paneIndex,isFocusedOnMac:e.focused,state:bi[e.agentStatus],...this.shownIn.length>0?{shownIn:[...this.shownIn]}:{}}}sortOrder(){this.order=[...this.panes.values()].sort((e,t)=>e.windowNumber-t.windowNumber||e.tabIndex-t.tabIndex||e.paneIndex-t.paneIndex||e.paneId.localeCompare(t.paneId)).map(e=>e.terminalId)}async openStream(e){let t=e??[...this.byPaneId.keys()],n={cancelled:!1,live:!1,buffer:[],stream:null,overflowed:!1},r=await this.client.subscribe(_i(t),{onEvent:e=>{if(!n.cancelled){if(n.live){this.onEvent(e);return}if(n.buffer.length<gi){n.buffer.push(e);return}n.overflowed||(n.overflowed=!0,this.log.warn(`herdr bootstrap event buffer overflowed; dropping events`,{max:gi})),this.active===n&&this.invalidateConversations(),this.scheduleSync(`snapshot`)}},onEnd:e=>{!n.cancelled&&this.active===n&&this.onStreamEnd(e)}});if(n.stream=r,this.closed){n.cancelled=!0,r.close();return}let i=this.active;this.active=n,this.conversationEpoch=P(),this.conversationPending=!0,this.conversationHintRevision++;for(let e of this.panes.values())this.emit({type:`conversation-changed`,sessionId:e.terminalId});this.historyEpochs.clear(),this.subscribedPaneIds=new Set(t),i&&(i.cancelled=!0,i.stream?.close());try{await this.refreshSnapshot()}catch(e){throw n.cancelled=!0,r.close(),this.active===n&&(this.active=null),e}if(n.cancelled||this.closed||this.active!==n)return;n.live=!0;let a=n.buffer;n.buffer=[];for(let e of a)this.onEvent(e);this.screenObserver.start(),this.emit({type:`layout-changed`})}async refreshSnapshot(){let e=this.eventSeq,t=this.active,n=this.conversationHintRevision;try{let r=await this.client.request(`session.snapshot`,{});if(this.closed||this.active!==t)return;this.applySnapshot(Di(r?.snapshot),e),this.conversationHintRevision===n&&(this.conversationPending=!1)}catch(e){if(this.closed||this.active!==t)return;throw e}}scheduleSync(e){this.closed||(e===`resubscribe`?this.wantResubscribe=!0:this.wantSnapshot=!0,!this.syncTimer&&(this.syncTimer=setTimeout(()=>{this.syncTimer=null,this.runSync().catch(e=>{this.log.warn(`herdr sync crashed`,{error:Si(e)})})},this.opts.syncDebounceMs??250),this.syncTimer.unref?.()))}async runSync(){if(!(this.syncBusy||this.closed)){this.syncBusy=!0;try{for(;(this.wantResubscribe||this.wantSnapshot)&&!this.closed&&this.active;){let e=this.wantResubscribe;this.wantResubscribe=!1,this.wantSnapshot=!1,e?await this.openStream():await this.refreshSnapshot()}}catch(e){this.log.warn(`herdr sync failed`,{error:Si(e)}),this.onStreamEnd(`sync-failed`)}finally{this.syncBusy=!1}}}onStreamEnd(e){if(this.closed)return;this.screenObserver.stop();let t=this.active;this.active=null,this.historyEpochs.clear(),t&&(t.cancelled=!0,t.stream?.close()),this.log.info(`herdr stream ended`,{reason:e});let n=[...this.order];this.panes.clear(),this.byPaneId.clear(),this.order=[],this.subscribedPaneIds.clear();for(let e of n)this.emit({type:`session-removed`,sessionId:e});this.emit({type:`layout-changed`}),this.scheduleReconnect()}scheduleReconnect(){if(this.closed||this.retryTimer)return;let e=this.opts.reconnectMs??2e3;this.retryTimer=setTimeout(()=>{this.retryTimer=null,this.connect().catch(e=>{this.log.debug(`herdr reconnect failed`,{error:Si(e)}),this.scheduleReconnect()})},e),this.retryTimer.unref?.()}applySnapshot(e,t=0){let n=new Map,r=new Map,i=new Set;for(let t of e.workspaces??[]){i.add(t.workspace_id),n.set(t.workspace_id,t.number??0);let e=L(typeof t.label==`string`?t.label:void 0,128);e&&r.set(t.workspace_id,e)}let a=new Map;for(let t of e.tabs??[])a.set(t.tab_id,t.number??0);let o=Oi(e.layouts??[]),s=this.panes,c=new Map,l=new Map,u=[],d=new Set,f=new Set,p=new Set;for(let m of e.panes){let h=m.terminal_id??m.pane_id,g=s.get(h),_=!this.conversationPending&&g?.paneId===m.pane_id?g:void 0,ee=_&&(_.conversationSeq>t||m.revision<_.conversationRevision)?_.conversation:Sr(m),te=_&&Ct(_.conversation,ee),v=te?_.conversationOwner:P(),ne=te?_.conversationSeq:++this.eventSeq,y=Math.max(_?.conversationRevision??0,Number.isSafeInteger(m.revision)?m.revision:0);g&&!te&&f.add(h);let b=o.get(m.pane_id),re=yi(m.agent_status),ie=g?.statusSeq??0,ae=ie>t,x=g?.paneId===m.pane_id&&g.scrollEventSeq>t,oe=g?.paneId===m.pane_id&&g.layoutEventSeq>t,S=ae?g?.agentStatus??re:re,C=m.scroll?.viewport_rows,se=xi(m),ce=m.foreground_cwd??m.cwd,le=r.get(m.workspace_id),w=Wt(m,le);g&&(g.title!==se||g.cwd!==ce||g.windowLabel!==le||!Vt(g.naming,w))&&d.add(h);let ue=ae?g?.revision??(typeof m.revision==`number`?m.revision:0):typeof m.revision==`number`?m.revision:g?.revision??0;!ae&&g&&typeof m.revision==`number`&&typeof g.revision==`number`&&m.revision!==g.revision&&p.add(h),c.set(h,{conversation:ee,conversationOwner:v,conversationSeq:ne,conversationRevision:y,terminalId:h,paneId:m.pane_id,workspaceId:m.workspace_id,tabId:m.tab_id,title:se,cwd:ce,naming:w,windowLabel:le,cols:oe?g.cols:b?.cols??g?.cols??80,rows:x?g.rows:Math.max(1,C??b?.rows??g?.rows??24),windowNumber:n.get(m.workspace_id)??0,tabIndex:a.get(m.tab_id)??0,paneIndex:oe?g.paneIndex:b?.order??0,focused:m.focused===!0||m.pane_id===e.focused_pane_id,agentStatus:S,scrollMax:x?g.scrollMax:m.scroll?.max_offset_from_bottom??g?.scrollMax??0,scrollOffset:x?g.scrollOffset:m.scroll?.offset_from_bottom??g?.scrollOffset,scrollStale:x?g.scrollStale:(g?.scrollStale??!1)||b!==void 0&&(C===void 0||C!==b.rows),scrollFetchedAt:x?g.scrollFetchedAt:b!==void 0&&(C===void 0||C!==b.rows)?0:g?.scrollFetchedAt??0,scrollEventSeq:g?.scrollEventSeq??0,layoutEventSeq:g?.layoutEventSeq??0,statusSeq:ie,revision:ue}),l.set(m.pane_id,h),i.add(m.workspace_id),!ae&&g?.agentStatus!==S&&u.push({id:h,state:S,agent:m.display_agent??m.agent})}let m=[...s.keys()].filter(e=>!c.has(e)),h=new Set([...c.keys()].filter(e=>!s.has(e))),g=new Map(u.map(e=>[e.id,e]));for(let[e,t]of this.historyEpochs){let n=s.get(e),r=c.get(e);(!r||r.paneId!==t.paneId||r.cols!==t.cols||r.rows!==t.rows||r.revision!==t.revision||r.scrollMax!==n?.scrollMax||r.scrollOffset!==n?.scrollOffset)&&this.revokeHistory(t)}this.panes=c,this.byPaneId=l,this.workspaces=i,this.focusedWorkspace=e.focused_workspace_id??null,this.sortOrder();for(let e of m)this.emit({type:`session-removed`,sessionId:e});for(let e of this.order)h.has(e)&&this.emit({type:`session-added`,sessionId:e});for(let e of this.order)f.has(e)&&this.emit({type:`conversation-changed`,sessionId:e});let _=Date.now();for(let e of this.order){let t=g.get(e);t&&this.emit({type:`agent-state`,sessionId:t.id,state:t.state,agent:t.agent,at:_})}for(let e of this.order)d.has(e)&&this.emit({type:`title-changed`,sessionId:e});for(let e of this.order)p.has(e)&&this.emit({type:`screen-changed`,sessionId:e});(m.length>0||h.size>0)&&this.emit({type:`layout-changed`}),wi([...l.keys()],this.subscribedPaneIds)||this.scheduleSync(`resubscribe`)}onEvent(e){try{this.handleEvent(e)}catch(e){this.log.warn(`herdr event handling failed`,{error:Si(e)})}}handleEvent(e){let t=e.event.replaceAll(`.`,`_`),n=e.data;switch([`pane_created`,`pane_closed`,`pane_exited`,`pane_moved`,`pane_agent_detected`,`tab_created`,`tab_closed`,`tab_moved`,`workspace_created`,`workspace_closed`].includes(t)&&this.invalidateConversations(),t){case`pane_created`:case`pane_closed`:case`pane_exited`:case`pane_moved`:case`pane_agent_detected`:case`tab_created`:case`tab_closed`:case`tab_renamed`:case`tab_moved`:case`workspace_created`:case`workspace_updated`:case`workspace_closed`:case`workspace_renamed`:case`workspace_moved`:case`workspace_reordered`:this.historyEpochs.clear(),this.scheduleSync(`snapshot`);return;case`pane_updated`:{let e=n.pane,t=U(e?.pane_id);if(!t)return;let r=this.paneByPaneId(t);if(!r){this.scheduleSync(`snapshot`);return}if(typeof e?.revision==`number`&&typeof r.revision==`number`&&e.revision<=r.revision)return;this.historyEpochs.delete(r.terminalId),Number.isSafeInteger(e?.revision)&&e.revision>r.conversationRevision&&this.setConversationReference(r,Sr(e),e.revision),(xi(e)!==r.title||(e?.foreground_cwd??e?.cwd)!==r.cwd||!Vt(Wt(e,r.windowLabel),r.naming))&&this.scheduleSync(`snapshot`);let i=Ci(e?.scroll);typeof i?.offset_from_bottom==`number`&&(r.scrollOffset=i.offset_from_bottom),i&&typeof i.max_offset_from_bottom==`number`&&(r.scrollMax=i.max_offset_from_bottom,typeof i.viewport_rows==`number`&&(r.rows=Math.max(1,i.viewport_rows)),r.scrollStale=!1),r.statusSeq=++this.eventSeq,i&&(r.scrollEventSeq=r.statusSeq);let a=yi(e?.agent_status);r.agentStatus!==a&&(r.agentStatus=a,this.emit({type:`agent-state`,sessionId:r.terminalId,state:a,at:Date.now()})),typeof e?.revision==`number`&&e.revision!==r.revision&&(r.revision=e.revision,this.emit({type:`screen-changed`,sessionId:r.terminalId}));return}case`pane_agent_status_changed`:if(!this.paneByPaneId(U(n.pane_id)))return;this.scheduleSync(`snapshot`);return;case`pane_scroll_changed`:{let e=this.paneByPaneId(U(n.pane_id));if(!e)return;e.scrollEventSeq=++this.eventSeq,this.historyEpochs.delete(e.terminalId);let t=Ci(n.scroll);if(typeof t?.offset_from_bottom==`number`&&(e.scrollOffset=t.offset_from_bottom),t&&typeof t.max_offset_from_bottom==`number`){e.scrollMax=t.max_offset_from_bottom,typeof t.viewport_rows==`number`&&(e.rows=Math.max(1,t.viewport_rows)),e.scrollStale=!1,this.emit({type:`screen-changed`,sessionId:e.terminalId});return}e.scrollStale=!0,this.emit({type:`screen-changed`,sessionId:e.terminalId});return}case`layout_updated`:{this.historyEpochs.clear();let e=n.layout;if(e){for(let[t,n]of Oi([e])){let e=this.paneByPaneId(t);e&&(e.cols=n.cols,e.rows=Math.max(1,n.rows),e.scrollStale=!0,e.scrollFetchedAt=0,e.scrollEventSeq=++this.eventSeq,e.layoutEventSeq=e.scrollEventSeq,e.paneIndex=n.order)}this.sortOrder()}this.emit({type:`layout-changed`});return}case`pane_focused`:{let e=this.paneByPaneId(U(n.pane_id));if(e)for(let t of this.panes.values())t.focused=t===e;else this.scheduleSync(`snapshot`);this.emit({type:`focus-changed`});return}case`tab_focused`:case`workspace_focused`:this.emit({type:`focus-changed`});return;default:this.log.debug(`unhandled herdr event`);return}}paneByPaneId(e){let t=e?this.byPaneId.get(e):void 0;return t?this.panes.get(t):void 0}async refreshScroll(e){let t=Date.now(),n=this.opts.scrollRefreshMs??1e3;if(t-e.scrollFetchedAt<n)return;e.scrollFetchedAt=t;let r=e.scrollEventSeq;try{let t=await this.client.request(`pane.get`,{pane_id:e.paneId});if(this.panes.get(e.terminalId)!==e)return;if(e.scrollEventSeq!==r){e.scrollStale&&(e.scrollFetchedAt=0,this.emit({type:`screen-changed`,sessionId:e.terminalId}));return}let n=t?.pane?.scroll;this.panes.get(e.terminalId)===e&&n&&(n.max_offset_from_bottom!==e.scrollMax||n.viewport_rows!==e.rows||n.offset_from_bottom!==e.scrollOffset)&&this.historyEpochs.delete(e.terminalId),typeof n?.offset_from_bottom==`number`&&(e.scrollOffset=n.offset_from_bottom),n&&typeof n.max_offset_from_bottom==`number`&&(e.scrollMax=n.max_offset_from_bottom,typeof n.viewport_rows==`number`&&(e.rows=Math.max(1,n.viewport_rows))),e.scrollStale=!1}catch(e){this.log.debug(`herdr scroll refresh failed`,{error:Si(e)})}}};function Di(e){let t=e;if(!t||typeof t!=`object`||!Array.isArray(t.panes))throw new V(`malformed`,`session.snapshot returned no panes array`);return t}function Oi(e){let t=new Map;for(let n of e)[...n.panes??[]].sort((e,t)=>(e.rect?.y??0)-(t.rect?.y??0)||(e.rect?.x??0)-(t.rect?.x??0)).forEach((e,n)=>{t.set(e.pane_id,{cols:Math.max(1,e.rect?.width??80),rows:Math.max(1,e.rect?.height??24),order:n})});return t}function ki(e=process.env){return Kr(e)!==void 0}async function Ai(e={}){let t=e.log??de({stdout:!1}),n=e.client??new cr({log:t,socketPath:e.socketPath,requestTimeoutMs:3e3});if(!E(n.socketPath))return{name:`herdr`,ok:!0,detail:(e.herdrOnPath??ki)()?`installed but not running (optional)`:`not installed (optional)`};let r;try{r=await n.ping()}catch(e){return e instanceof l?{name:`herdr`,ok:!1,detail:e.message,fix:e.hint}:{name:`herdr`,ok:!1,detail:String(e),fix:er}}try{Di((await n.request(`session.snapshot`,{}))?.snapshot)}catch(e){return{name:`herdr`,ok:!1,detail:e instanceof V&&rr.has(e.code)?`herdr ${r.version??`?`} has no session.snapshot`:`session.snapshot failed: ${e instanceof Error?e.message:String(e)}`,fix:tr}}return{name:`herdr`,ok:!0,detail:`v${r.version??`?`} protocol ${r.protocol??`?`}`}}function ji(e){let t=e.log.child({unit:`herdr-start`}),n=new Ei({client:e.client??new cr({log:e.log,socketPath:e.socketPath}),log:e.log,...e.backendOptions}),r=null,i=!1,a=!1,o=!1;e.registry.add(n);let s=e.registry.registerSetupReporter(`herdr`,e=>{if(!e)return{issue:ki()?`not-running`:`not-installed`};let t=n.terminalAttachIssue;return t?{issue:`limited`,detail:t}:{}}),c=()=>{i||r||(r=setTimeout(()=>{r=null,u()},e.retryMs??1e4),r.unref?.())},u=async()=>{if(!(i||n.isConnected)){try{await n.connect()}catch(n){t.debug(`herdr not available`,{error:w(n)}),e.onUnavailable&&!o&&n instanceof l&&(o=!0,e.onUnavailable()),c();return}try{if(i)return;if(t.info(`herdr connected`),e.onConnected&&!a){a=!0;let t=await n.listSessions().catch(()=>[]);e.onConnected(t.length)}}catch(e){t.debug(`herdr post-connect setup failed`,{error:w(e)})}}};return u(),{stop(){s(),i=!0,r&&clearTimeout(r),r=null,n.close(),e.registry.remove(`herdr`)}}}const Mi=Ge(me);var W=class extends Error{kind;constructor(e,t){super(e),this.kind=t,this.name=`ITerm2AuthError`}};const Ni=12e4;async function Pi(e,t=Ni){let n=Date.now()+t;if((await Fi(`if application "iTerm2" is running then
77
- return "yes"
78
- else
79
- return "no"
80
- end if`,n)).trim()!==`yes`)throw new W(`iTerm2 is not running`,`not-running`);let r=e.replace(/[\\"]/g,``),i;try{i=await Fi(`tell application "iTerm2" to request cookie and key for app named "${r}"`,n)}catch(e){if(e instanceof W)throw e;let t=String(e.stderr??e);throw/-274[01]/.test(t)?new W(`iTerm2 is too old (need 3.3+)`,`too-old`):/denied|not allowed|user/i.test(t)?new W(t.trim(),`denied`):new W(t.trim(),`unknown`)}let[a,o]=i.trim().split(` `);if(!a||!o)throw new W(`unexpected osascript output (${i.trim().split(` `).length} token(s), ${i.length} chars)`,`unknown`);return{cookie:a,key:o}}async function Fi(e,t){try{let{stdout:n}=await Mi(`/usr/bin/osascript`,[`-e`,e],{timeout:Math.max(1,t-Date.now()),killSignal:`SIGKILL`});return n}catch(e){throw e.killed?new W(`osascript timed out waiting for iTerm2`,`unknown`):e}}const G=Xe(`CgxpdGVybTIucHJvdG8SBml0ZXJtMiLcBQoXQ2xpZW50T3JpZ2luYXRlZE1lc3NhZ2USCgoCaWQYASABKAMSNgoSZ2V0X2J1ZmZlcl9yZXF1ZXN0GGQgASgLMhguaXRlcm0yLkdldEJ1ZmZlclJlcXVlc3RIABI2ChJnZXRfcHJvbXB0X3JlcXVlc3QYZSABKAsyGC5pdGVybTIuR2V0UHJvbXB0UmVxdWVzdEgAEjsKFG5vdGlmaWNhdGlvbl9yZXF1ZXN0GGcgASgLMhsuaXRlcm0yLk5vdGlmaWNhdGlvblJlcXVlc3RIABI8ChVsaXN0X3Nlc3Npb25zX3JlcXVlc3QYaiABKAsyGy5pdGVybTIuTGlzdFNlc3Npb25zUmVxdWVzdEgAEjQKEXNlbmRfdGV4dF9yZXF1ZXN0GGsgASgLMhcuaXRlcm0yLlNlbmRUZXh0UmVxdWVzdEgAEjYKEmNyZWF0ZV90YWJfcmVxdWVzdBhsIAEoCzIYLml0ZXJtMi5DcmVhdGVUYWJSZXF1ZXN0SAASNgoSc3BsaXRfcGFuZV9yZXF1ZXN0GG0gASgLMhguaXRlcm0yLlNwbGl0UGFuZVJlcXVlc3RIABI6ChRnZXRfcHJvcGVydHlfcmVxdWVzdBhwIAEoCzIaLml0ZXJtMi5HZXRQcm9wZXJ0eVJlcXVlc3RIABIzChBhY3RpdmF0ZV9yZXF1ZXN0GHIgASgLMhcuaXRlcm0yLkFjdGl2YXRlUmVxdWVzdEgAEjMKEHZhcmlhYmxlX3JlcXVlc3QYcyABKAsyFy5pdGVybTIuVmFyaWFibGVSZXF1ZXN0SAASLQoNZm9jdXNfcmVxdWVzdBh1IAEoCzIULml0ZXJtMi5Gb2N1c1JlcXVlc3RIABJBChdpbnZva2VfZnVuY3Rpb25fcmVxdWVzdBiEASABKAsyHS5pdGVybTIuSW52b2tlRnVuY3Rpb25SZXF1ZXN0SABCDAoKc3VibWVzc2FnZSK0BgoXU2VydmVyT3JpZ2luYXRlZE1lc3NhZ2USCgoCaWQYASABKAMSDwoFZXJyb3IYAiABKAlIABI4ChNnZXRfYnVmZmVyX3Jlc3BvbnNlGGQgASgLMhkuaXRlcm0yLkdldEJ1ZmZlclJlc3BvbnNlSAASOAoTZ2V0X3Byb21wdF9yZXNwb25zZRhlIAEoCzIZLml0ZXJtMi5HZXRQcm9tcHRSZXNwb25zZUgAEj0KFW5vdGlmaWNhdGlvbl9yZXNwb25zZRhnIAEoCzIcLml0ZXJtMi5Ob3RpZmljYXRpb25SZXNwb25zZUgAEj4KFmxpc3Rfc2Vzc2lvbnNfcmVzcG9uc2UYaiABKAsyHC5pdGVybTIuTGlzdFNlc3Npb25zUmVzcG9uc2VIABI2ChJzZW5kX3RleHRfcmVzcG9uc2UYayABKAsyGC5pdGVybTIuU2VuZFRleHRSZXNwb25zZUgAEjgKE2NyZWF0ZV90YWJfcmVzcG9uc2UYbCABKAsyGS5pdGVybTIuQ3JlYXRlVGFiUmVzcG9uc2VIABI4ChNzcGxpdF9wYW5lX3Jlc3BvbnNlGG0gASgLMhkuaXRlcm0yLlNwbGl0UGFuZVJlc3BvbnNlSAASPAoVZ2V0X3Byb3BlcnR5X3Jlc3BvbnNlGHAgASgLMhsuaXRlcm0yLkdldFByb3BlcnR5UmVzcG9uc2VIABI1ChFhY3RpdmF0ZV9yZXNwb25zZRhyIAEoCzIYLml0ZXJtMi5BY3RpdmF0ZVJlc3BvbnNlSAASNQoRdmFyaWFibGVfcmVzcG9uc2UYcyABKAsyGC5pdGVybTIuVmFyaWFibGVSZXNwb25zZUgAEi8KDmZvY3VzX3Jlc3BvbnNlGHUgASgLMhUuaXRlcm0yLkZvY3VzUmVzcG9uc2VIABJDChhpbnZva2VfZnVuY3Rpb25fcmVzcG9uc2UYhAEgASgLMh4uaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVzcG9uc2VIABItCgxub3RpZmljYXRpb24Y6AcgASgLMhQuaXRlcm0yLk5vdGlmaWNhdGlvbkgAQgwKCnN1Ym1lc3NhZ2UiHQoFQ29vcmQSCQoBeBgBIAEoBRIJCgF5GAIgASgDIkYKCkNvb3JkUmFuZ2USHAoFc3RhcnQYASABKAsyDS5pdGVybTIuQ29vcmQSGgoDZW5kGAIgASgLMg0uaXRlcm0yLkNvb3JkIikKBVJhbmdlEhAKCGxvY2F0aW9uGAEgASgDEg4KBmxlbmd0aBgCIAEoAyJdChJXaW5kb3dlZENvb3JkUmFuZ2USJwoLY29vcmRfcmFuZ2UYASABKAsyEi5pdGVybTIuQ29vcmRSYW5nZRIeCgdjb2x1bW5zGAIgASgLMg0uaXRlcm0yLlJhbmdlIh0KBVBvaW50EgkKAXgYASABKAUSCQoBeRgCIAEoBSIlCgRTaXplEg0KBXdpZHRoGAEgASgFEg4KBmhlaWdodBgCIAEoBSJCCgVGcmFtZRIdCgZvcmlnaW4YASABKAsyDS5pdGVybTIuUG9pbnQSGgoEc2l6ZRgCIAEoCzIMLml0ZXJtMi5TaXplInsKCUxpbmVSYW5nZRIcChRzY3JlZW5fY29udGVudHNfb25seRgBIAEoCBIWCg50cmFpbGluZ19saW5lcxgCIAEoBRI4ChR3aW5kb3dlZF9jb29yZF9yYW5nZRgDIAEoCzIaLml0ZXJtMi5XaW5kb3dlZENvb3JkUmFuZ2UiYgoQR2V0QnVmZmVyUmVxdWVzdBIPCgdzZXNzaW9uGAEgASgJEiUKCmxpbmVfcmFuZ2UYAiABKAsyES5pdGVybTIuTGluZVJhbmdlEhYKDmluY2x1ZGVfc3R5bGVzGAMgASgIIjQKCFJHQkNvbG9yEgsKA3JlZBgBIAEoDRINCgVncmVlbhgCIAEoDRIMCgRibHVlGAMgASgNIowDCglDZWxsU3R5bGUSFAoKZmdTdGFuZGFyZBgBIAEoDUgAEi0KC2ZnQWx0ZXJuYXRlGAIgASgOMhYuaXRlcm0yLkFsdGVybmF0ZUNvbG9ySAASIQoFZmdSZ2IYAyABKAsyEC5pdGVybTIuUkdCQ29sb3JIABIUCgpiZ1N0YW5kYXJkGAUgASgNSAESLQoLYmdBbHRlcm5hdGUYBiABKA4yFi5pdGVybTIuQWx0ZXJuYXRlQ29sb3JIARIhCgViZ1JnYhgHIAEoCzIQLml0ZXJtMi5SR0JDb2xvckgBEgwKBGJvbGQYCSABKAgSDQoFZmFpbnQYCiABKAgSDgoGaXRhbGljGAsgASgIEg0KBWJsaW5rGAwgASgIEhEKCXVuZGVybGluZRgNIAEoCBIVCg1zdHJpa2V0aHJvdWdoGA4gASgIEhEKCWludmlzaWJsZRgPIAEoCBIPCgdpbnZlcnNlGBAgASgIEg8KB3JlcGVhdHMYFiABKA1CCQoHZmdDb2xvckIJCgdiZ0NvbG9yIkAKEUNvZGVQb2ludHNQZXJDZWxsEhoKD251bV9jb2RlX3BvaW50cxgBIAEoBToBMRIPCgdyZXBlYXRzGAIgASgFIo0CCgxMaW5lQ29udGVudHMSDAoEdGV4dBgBIAEoCRI3ChRjb2RlX3BvaW50c19wZXJfY2VsbBgCIAMoCzIZLml0ZXJtMi5Db2RlUG9pbnRzUGVyQ2VsbBJOCgxjb250aW51YXRpb24YAyABKA4yIS5pdGVybTIuTGluZUNvbnRlbnRzLkNvbnRpbnVhdGlvbjoVQ09OVElOVUFUSU9OX0hBUkRfRU9MEiAKBXN0eWxlGAQgAygLMhEuaXRlcm0yLkNlbGxTdHlsZSJECgxDb250aW51YXRpb24SGQoVQ09OVElOVUFUSU9OX0hBUkRfRU9MEAESGQoVQ09OVElOVUFUSU9OX1NPRlRfRU9MEAIiogIKEUdldEJ1ZmZlclJlc3BvbnNlEjQKBnN0YXR1cxgBIAEoDjIgLml0ZXJtMi5HZXRCdWZmZXJSZXNwb25zZS5TdGF0dXM6Ak9LEiYKCGNvbnRlbnRzGAMgAygLMhQuaXRlcm0yLkxpbmVDb250ZW50cxIdCgZjdXJzb3IYBCABKAsyDS5pdGVybTIuQ29vcmQSOAoUd2luZG93ZWRfY29vcmRfcmFuZ2UYBiABKAsyGi5pdGVybTIuV2luZG93ZWRDb29yZFJhbmdlIlYKBlN0YXR1cxIGCgJPSxAAEhUKEVNFU1NJT05fTk9UX0ZPVU5EEAESFgoSSU5WQUxJRF9MSU5FX1JBTkdFEAISFQoRUkVRVUVTVF9NQUxGT1JNRUQQAyIVChNMaXN0U2Vzc2lvbnNSZXF1ZXN0InkKDlNlc3Npb25TdW1tYXJ5EhkKEXVuaXF1ZV9pZGVudGlmaWVyGAEgASgJEhwKBWZyYW1lGAIgASgLMg0uaXRlcm0yLkZyYW1lEh8KCWdyaWRfc2l6ZRgDIAEoCzIMLml0ZXJtMi5TaXplEg0KBXRpdGxlGAQgASgJIsEBCg1TcGxpdFRyZWVOb2RlEhAKCHZlcnRpY2FsGAEgASgIEjIKBWxpbmtzGAIgAygLMiMuaXRlcm0yLlNwbGl0VHJlZU5vZGUuU3BsaXRUcmVlTGluaxpqCg1TcGxpdFRyZWVMaW5rEikKB3Nlc3Npb24YASABKAsyFi5pdGVybTIuU2Vzc2lvblN1bW1hcnlIABIlCgRub2RlGAIgASgLMhUuaXRlcm0yLlNwbGl0VHJlZU5vZGVIAEIHCgVjaGlsZCKbAgoUTGlzdFNlc3Npb25zUmVzcG9uc2USNAoHd2luZG93cxgBIAMoCzIjLml0ZXJtMi5MaXN0U2Vzc2lvbnNSZXNwb25zZS5XaW5kb3caeQoGV2luZG93Ei4KBHRhYnMYASADKAsyIC5pdGVybTIuTGlzdFNlc3Npb25zUmVzcG9uc2UuVGFiEhEKCXdpbmRvd19pZBgCIAEoCRIcCgVmcmFtZRgDIAEoCzINLml0ZXJtMi5GcmFtZRIOCgZudW1iZXIYBCABKAUaUgoDVGFiEiMKBHJvb3QYAyABKAsyFS5pdGVybTIuU3BsaXRUcmVlTm9kZRIOCgZ0YWJfaWQYAiABKAkSFgoOdG11eF93aW5kb3dfaWQYBCABKAkiTAoPU2VuZFRleHRSZXF1ZXN0Eg8KB3Nlc3Npb24YASABKAkSDAoEdGV4dBgCIAEoCRIaChJzdXBwcmVzc19icm9hZGNhc3QYAyABKAgibAoQU2VuZFRleHRSZXNwb25zZRIvCgZzdGF0dXMYASABKA4yHy5pdGVybTIuU2VuZFRleHRSZXNwb25zZS5TdGF0dXMiJwoGU3RhdHVzEgYKAk9LEAASFQoRU0VTU0lPTl9OT1RfRk9VTkQQASJbChJHZXRQcm9wZXJ0eVJlcXVlc3QSEwoJd2luZG93X2lkGAEgASgJSAASFAoKc2Vzc2lvbl9pZBgDIAEoCUgAEgwKBG5hbWUYAiABKAlCDAoKaWRlbnRpZmllciKaAQoTR2V0UHJvcGVydHlSZXNwb25zZRIyCgZzdGF0dXMYASABKA4yIi5pdGVybTIuR2V0UHJvcGVydHlSZXNwb25zZS5TdGF0dXMSEgoKanNvbl92YWx1ZRgCIAEoCSI7CgZTdGF0dXMSBgoCT0sQABIVChFVTlJFQ09HTklaRURfTkFNRRABEhIKDklOVkFMSURfVEFSR0VUEAIiQAoUUHJvbXB0TW9uaXRvclJlcXVlc3QSKAoFbW9kZXMYASADKA4yGS5pdGVybTIuUHJvbXB0TW9uaXRvck1vZGUiYAoWVmFyaWFibGVNb25pdG9yUmVxdWVzdBIMCgRuYW1lGAEgASgJEiQKBXNjb3BlGAIgASgOMhUuaXRlcm0yLlZhcmlhYmxlU2NvcGUSEgoKaWRlbnRpZmllchgDIAEoCSL/AQoTTm90aWZpY2F0aW9uUmVxdWVzdBIPCgdzZXNzaW9uGAEgASgJEhEKCXN1YnNjcmliZRgCIAEoCBIzChFub3RpZmljYXRpb25fdHlwZRgDIAEoDjIYLml0ZXJtMi5Ob3RpZmljYXRpb25UeXBlEkIKGHZhcmlhYmxlX21vbml0b3JfcmVxdWVzdBgGIAEoCzIeLml0ZXJtMi5WYXJpYWJsZU1vbml0b3JSZXF1ZXN0SAASPgoWcHJvbXB0X21vbml0b3JfcmVxdWVzdBgJIAEoCzIcLml0ZXJtMi5Qcm9tcHRNb25pdG9yUmVxdWVzdEgAQgsKCWFyZ3VtZW50cyL1AQoUTm90aWZpY2F0aW9uUmVzcG9uc2USMwoGc3RhdHVzGAEgASgOMiMuaXRlcm0yLk5vdGlmaWNhdGlvblJlc3BvbnNlLlN0YXR1cyKnAQoGU3RhdHVzEgYKAk9LEAASFQoRU0VTU0lPTl9OT1RfRk9VTkQQARIVChFSRVFVRVNUX01BTEZPUk1FRBACEhIKDk5PVF9TVUJTQ1JJQkVEEAMSFgoSQUxSRUFEWV9TVUJTQ1JJQkVEEAQSIwofRFVQTElDQVRFX1NFUlZFUl9PUklHSU5BVEVEX1JQQxAFEhYKEklOVkFMSURfSURFTlRJRklFUhAGIisKGFNjcmVlblVwZGF0ZU5vdGlmaWNhdGlvbhIPCgdzZXNzaW9uGAEgASgJIloKGFByb21wdE5vdGlmaWNhdGlvblByb21wdBITCgtwbGFjZWhvbGRlchgBIAEoCRIpCgZwcm9tcHQYAiABKAsyGS5pdGVybTIuR2V0UHJvbXB0UmVzcG9uc2UiMQoeUHJvbXB0Tm90aWZpY2F0aW9uQ29tbWFuZFN0YXJ0Eg8KB2NvbW1hbmQYASABKAkiLgocUHJvbXB0Tm90aWZpY2F0aW9uQ29tbWFuZEVuZBIOCgZzdGF0dXMYASABKAUi+gEKElByb21wdE5vdGlmaWNhdGlvbhIPCgdzZXNzaW9uGAEgASgJEjIKBnByb21wdBgCIAEoCzIgLml0ZXJtMi5Qcm9tcHROb3RpZmljYXRpb25Qcm9tcHRIABI/Cg1jb21tYW5kX3N0YXJ0GAMgASgLMiYuaXRlcm0yLlByb21wdE5vdGlmaWNhdGlvbkNvbW1hbmRTdGFydEgAEjsKC2NvbW1hbmRfZW5kGAQgASgLMiQuaXRlcm0yLlByb21wdE5vdGlmaWNhdGlvbkNvbW1hbmRFbmRIABIYChB1bmlxdWVfcHJvbXB0X2lkGAUgASgJQgcKBWV2ZW50IiwKFk5ld1Nlc3Npb25Ob3RpZmljYXRpb24SEgoKc2Vzc2lvbl9pZBgBIAEoCSIyChxUZXJtaW5hdGVTZXNzaW9uTm90aWZpY2F0aW9uEhIKCnNlc3Npb25faWQYASABKAkiWQoZTGF5b3V0Q2hhbmdlZE5vdGlmaWNhdGlvbhI8ChZsaXN0X3Nlc3Npb25zX3Jlc3BvbnNlGAEgASgLMhwuaXRlcm0yLkxpc3RTZXNzaW9uc1Jlc3BvbnNlIoQDChhGb2N1c0NoYW5nZWROb3RpZmljYXRpb24SHAoSYXBwbGljYXRpb25fYWN0aXZlGAEgASgISAASOQoGd2luZG93GAIgASgLMicuaXRlcm0yLkZvY3VzQ2hhbmdlZE5vdGlmaWNhdGlvbi5XaW5kb3dIABIWCgxzZWxlY3RlZF90YWIYAyABKAlIABIRCgdzZXNzaW9uGAQgASgJSAAa2gEKBldpbmRvdxJLCg13aW5kb3dfc3RhdHVzGAEgASgOMjQuaXRlcm0yLkZvY3VzQ2hhbmdlZE5vdGlmaWNhdGlvbi5XaW5kb3cuV2luZG93U3RhdHVzEhEKCXdpbmRvd19pZBgCIAEoCSJwCgxXaW5kb3dTdGF0dXMSHgoaVEVSTUlOQUxfV0lORE9XX0JFQ0FNRV9LRVkQABIeChpURVJNSU5BTF9XSU5ET1dfSVNfQ1VSUkVOVBABEiAKHFRFUk1JTkFMX1dJTkRPV19SRVNJR05FRF9LRVkQAkIHCgVldmVudCJ9ChtWYXJpYWJsZUNoYW5nZWROb3RpZmljYXRpb24SJAoFc2NvcGUYASABKA4yFS5pdGVybTIuVmFyaWFibGVTY29wZRISCgppZGVudGlmaWVyGAIgASgJEgwKBG5hbWUYAyABKAkSFgoOanNvbl9uZXdfdmFsdWUYBCABKAki9wMKDE5vdGlmaWNhdGlvbhJEChpzY3JlZW5fdXBkYXRlX25vdGlmaWNhdGlvbhgCIAEoCzIgLml0ZXJtMi5TY3JlZW5VcGRhdGVOb3RpZmljYXRpb24SNwoTcHJvbXB0X25vdGlmaWNhdGlvbhgDIAEoCzIaLml0ZXJtMi5Qcm9tcHROb3RpZmljYXRpb24SQAoYbmV3X3Nlc3Npb25fbm90aWZpY2F0aW9uGAYgASgLMh4uaXRlcm0yLk5ld1Nlc3Npb25Ob3RpZmljYXRpb24STAoedGVybWluYXRlX3Nlc3Npb25fbm90aWZpY2F0aW9uGAcgASgLMiQuaXRlcm0yLlRlcm1pbmF0ZVNlc3Npb25Ob3RpZmljYXRpb24SRgobbGF5b3V0X2NoYW5nZWRfbm90aWZpY2F0aW9uGAggASgLMiEuaXRlcm0yLkxheW91dENoYW5nZWROb3RpZmljYXRpb24SRAoaZm9jdXNfY2hhbmdlZF9ub3RpZmljYXRpb24YCSABKAsyIC5pdGVybTIuRm9jdXNDaGFuZ2VkTm90aWZpY2F0aW9uEkoKHXZhcmlhYmxlX2NoYW5nZWRfbm90aWZpY2F0aW9uGAwgASgLMiMuaXRlcm0yLlZhcmlhYmxlQ2hhbmdlZE5vdGlmaWNhdGlvbiI9ChBHZXRQcm9tcHRSZXF1ZXN0Eg8KB3Nlc3Npb24YASABKAkSGAoQdW5pcXVlX3Byb21wdF9pZBgCIAEoCSLkAgoRR2V0UHJvbXB0UmVzcG9uc2USNAoGc3RhdHVzGAEgASgOMiAuaXRlcm0yLkdldFByb21wdFJlc3BvbnNlLlN0YXR1czoCT0sSGQoRd29ya2luZ19kaXJlY3RvcnkYBSABKAkSDwoHY29tbWFuZBgGIAEoCRI1Cgxwcm9tcHRfc3RhdGUYByABKA4yHy5pdGVybTIuR2V0UHJvbXB0UmVzcG9uc2UuU3RhdGUSEwoLZXhpdF9zdGF0dXMYCSABKA0SGAoQdW5pcXVlX3Byb21wdF9pZBgKIAEoCSJWCgZTdGF0dXMSBgoCT0sQABIVChFTRVNTSU9OX05PVF9GT1VORBABEhUKEVJFUVVFU1RfTUFMRk9STUVEEAISFgoSUFJPTVBUX1VOQVZBSUxBQkxFEAMiLwoFU3RhdGUSCwoHRURJVElORxAAEgsKB1JVTk5JTkcQARIMCghGSU5JU0hFRBACIjIKD1Byb2ZpbGVQcm9wZXJ0eRILCgNrZXkYASABKAkSEgoKanNvbl92YWx1ZRgCIAEoCSKeAQoQQ3JlYXRlVGFiUmVxdWVzdBIUCgxwcm9maWxlX25hbWUYASABKAkSEQoJd2luZG93X2lkGAIgASgJEhEKCXRhYl9pbmRleBgDIAEoDRI6ChljdXN0b21fcHJvZmlsZV9wcm9wZXJ0aWVzGAUgAygLMhcuaXRlcm0yLlByb2ZpbGVQcm9wZXJ0eRISCgpzZWxlY3RfdGFiGAYgASgIIvABChFDcmVhdGVUYWJSZXNwb25zZRIwCgZzdGF0dXMYASABKA4yIC5pdGVybTIuQ3JlYXRlVGFiUmVzcG9uc2UuU3RhdHVzEhEKCXdpbmRvd19pZBgCIAEoCRIOCgZ0YWJfaWQYAyABKAUSEgoKc2Vzc2lvbl9pZBgEIAEoCSJyCgZTdGF0dXMSBgoCT0sQABIYChRJTlZBTElEX1BST0ZJTEVfTkFNRRABEhUKEUlOVkFMSURfV0lORE9XX0lEEAISFQoRSU5WQUxJRF9UQUJfSU5ERVgQAxIYChRNSVNTSU5HX1NVQlNUSVRVVElPThAEIqwBChBTcGxpdFBhbmVSZXF1ZXN0Eg8KB3Nlc3Npb24YASABKAkSQAoPc3BsaXRfZGlyZWN0aW9uGAIgASgOMicuaXRlcm0yLlNwbGl0UGFuZVJlcXVlc3QuU3BsaXREaXJlY3Rpb24SFQoGYmVmb3JlGAMgASgIOgVmYWxzZSIuCg5TcGxpdERpcmVjdGlvbhIMCghWRVJUSUNBTBAAEg4KCkhPUklaT05UQUwQASLVAQoRU3BsaXRQYW5lUmVzcG9uc2USMAoGc3RhdHVzGAEgASgOMiAuaXRlcm0yLlNwbGl0UGFuZVJlc3BvbnNlLlN0YXR1cxISCgpzZXNzaW9uX2lkGAIgAygJInoKBlN0YXR1cxIGCgJPSxAAEhUKEVNFU1NJT05fTk9UX0ZPVU5EEAESGAoUSU5WQUxJRF9QUk9GSUxFX05BTUUQAhIQCgxDQU5OT1RfU1BMSVQQAxIlCiFNQUxGT1JNRURfQ1VTVE9NX1BST0ZJTEVfUFJPUEVSVFkQBCKWAgoPQWN0aXZhdGVSZXF1ZXN0EhMKCXdpbmRvd19pZBgBIAEoCUgAEhAKBnRhYl9pZBgCIAEoCUgAEhQKCnNlc3Npb25faWQYAyABKAlIABIaChJvcmRlcl93aW5kb3dfZnJvbnQYBCABKAgSEgoKc2VsZWN0X3RhYhgFIAEoCBIWCg5zZWxlY3Rfc2Vzc2lvbhgGIAEoCBIxCgxhY3RpdmF0ZV9hcHAYByABKAsyGy5pdGVybTIuQWN0aXZhdGVSZXF1ZXN0LkFwcBo9CgNBcHASGQoRcmFpc2VfYWxsX3dpbmRvd3MYASABKAgSGwoTaWdub3Jpbmdfb3RoZXJfYXBwcxgCIAEoCEIMCgppZGVudGlmaWVyIn0KEEFjdGl2YXRlUmVzcG9uc2USLwoGc3RhdHVzGAEgASgOMh8uaXRlcm0yLkFjdGl2YXRlUmVzcG9uc2UuU3RhdHVzIjgKBlN0YXR1cxIGCgJPSxAAEhIKDkJBRF9JREVOVElGSUVSEAESEgoOSU5WQUxJRF9PUFRJT04QAiKLAQoPVmFyaWFibGVSZXF1ZXN0EhQKCnNlc3Npb25faWQYASABKAlIABIoCgNzZXQYAiADKAsyGy5pdGVybTIuVmFyaWFibGVSZXF1ZXN0LlNldBILCgNnZXQYAyADKAkaIgoDU2V0EgwKBG5hbWUYASABKAkSDQoFdmFsdWUYAiABKAlCBwoFc2NvcGUi5QEKEFZhcmlhYmxlUmVzcG9uc2USLwoGc3RhdHVzGAEgASgOMh8uaXRlcm0yLlZhcmlhYmxlUmVzcG9uc2UuU3RhdHVzEg4KBnZhbHVlcxgCIAMoCSKPAQoGU3RhdHVzEgYKAk9LEAASFQoRU0VTU0lPTl9OT1RfRk9VTkQQARIQCgxJTlZBTElEX05BTUUQAhIRCg1NSVNTSU5HX1NDT1BFEAMSEQoNVEFCX05PVF9GT1VORBAEEhgKFE1VTFRJX0dFVF9ESVNBTExPV0VEEAUSFAoQV0lORE9XX05PVF9GT1VORBAGIp8BChVJbnZva2VGdW5jdGlvblJlcXVlc3QSNgoGbWV0aG9kGAcgASgLMiQuaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVxdWVzdC5NZXRob2RIABISCgppbnZvY2F0aW9uGAUgASgJEhMKB3RpbWVvdXQYBiABKAE6Ai0xGhoKBk1ldGhvZBIQCghyZWNlaXZlchgBIAEoCUIJCgdjb250ZXh0ItkCChZJbnZva2VGdW5jdGlvblJlc3BvbnNlEjUKBWVycm9yGAEgASgLMiQuaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVzcG9uc2UuRXJyb3JIABI5CgdzdWNjZXNzGAIgASgLMiYuaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVzcG9uc2UuU3VjY2Vzc0gAGlQKBUVycm9yEjUKBnN0YXR1cxgBIAEoDjIlLml0ZXJtMi5JbnZva2VGdW5jdGlvblJlc3BvbnNlLlN0YXR1cxIUCgxlcnJvcl9yZWFzb24YAiABKAkaHgoHU3VjY2VzcxITCgtqc29uX3Jlc3VsdBgBIAEoCSJICgZTdGF0dXMSCwoHVElNRU9VVBABEgoKBkZBSUxFRBACEhUKEVJFUVVFU1RfTUFMRk9STUVEEAMSDgoKSU5WQUxJRF9JRBAEQg0KC2Rpc3Bvc2l0aW9uIg4KDEZvY3VzUmVxdWVzdCJICg1Gb2N1c1Jlc3BvbnNlEjcKDW5vdGlmaWNhdGlvbnMYASADKAsyIC5pdGVybTIuRm9jdXNDaGFuZ2VkTm90aWZpY2F0aW9uKkcKDkFsdGVybmF0ZUNvbG9yEgsKB0RFRkFVTFQQABIUChBSRVZFUlNFRF9ERUZBVUxUEAMSEgoOU1lTVEVNX01FU1NBR0UQBCrZAQoQTm90aWZpY2F0aW9uVHlwZRIbChdOT1RJRllfT05fU0NSRUVOX1VQREFURRACEhQKEE5PVElGWV9PTl9QUk9NUFQQAxIZChVOT1RJRllfT05fTkVXX1NFU1NJT04QBhIfChtOT1RJRllfT05fVEVSTUlOQVRFX1NFU1NJT04QBxIbChdOT1RJRllfT05fTEFZT1VUX0NIQU5HRRAIEhoKFk5PVElGWV9PTl9GT0NVU19DSEFOR0UQCRIdChlOT1RJRllfT05fVkFSSUFCTEVfQ0hBTkdFEAwqQwoRUHJvbXB0TW9uaXRvck1vZGUSCgoGUFJPTVBUEAESEQoNQ09NTUFORF9TVEFSVBACEg8KC0NPTU1BTkRfRU5EEAMqOgoNVmFyaWFibGVTY29wZRILCgdTRVNTSU9OEAESBwoDVEFCEAISCgoGV0lORE9XEAMSBwoDQVBQEAQ`),Ii=F(G,0),Li=F(G,1),Ri=F(G,2),zi=F(G,3),Bi=F(G,5),Vi=F(G,9),Hi=F(G,10),Ui=F(G,16),Wi=F(G,20);let Gi=function(e){return e[e.OK=0]=`OK`,e[e.SESSION_NOT_FOUND=1]=`SESSION_NOT_FOUND`,e}({});const Ki=F(G,22),qi=F(G,24),Ji=F(G,25),Yi=F(G,26),Xi=F(G,42),Zi=F(G,44),Qi=F(G,46),$i=F(G,46,0),ea=F(G,48),ta=F(G,52),na=N(k(),`Library`,`Application Support`,`iTerm2`,`private`,`socket`);var ra=class extends Ve{opts;ws=null;connecting=null;nextId=1n;pending=new Map;log;constructor(e){super(),this.opts=e,this.log=e.log.child({unit:`iterm2`})}get connected(){return this.ws?.readyState===Ue.OPEN}connect(){if(this.connecting)return this.connecting;let e=this.open().finally(()=>{this.connecting===e&&(this.connecting=null)});return this.connecting=e,e}async open(){let e=this.opts.appName??`Shellbell`,t=this.opts.socketPath??na,n=this.opts.cookieTimeoutMs??12e4,{cookie:r,key:i}=await ia((this.opts.cookieProvider??(()=>Pi(e,n)))(),n,`iTerm2 did not answer the API cookie request`),a={origin:`ws://localhost/`,"x-iterm2-library-version":`shellbell 0.1.0`,"x-iterm2-disable-auth-ui":`true`,"x-iterm2-advisory-name":e,"x-iterm2-cookie":r,"x-iterm2-key":i},o=this.opts.connectTimeoutMs??1e4,s=this.opts.url?new Ue(this.opts.url,[`api.iterm2.com`],{headers:a,handshakeTimeout:o}):new Ue(`ws://localhost/`,[`api.iterm2.com`],{headers:a,handshakeTimeout:o,createConnection:()=>He({path:t})});this.ws=s,await new Promise((e,t)=>{let n=()=>{s.off(`open`,i),s.off(`error`,a),s.off(`unexpected-response`,o),s.off(`close`,c)},r=e=>{n(),s.on(`error`,()=>{}),s.terminate(),this.ws===s&&(this.ws=null),t(e)},i=()=>{n(),e()},a=e=>r(e),o=(e,t)=>{t.destroy(),e.destroy(),r(Error(`iTerm2 API responded HTTP ${t.statusCode}`))},c=()=>r(Error(`iTerm2 connection closed before open`));s.once(`open`,i),s.once(`error`,a),s.once(`unexpected-response`,o),s.once(`close`,c)}),s.on(`message`,(e,t)=>{if(!t)return;let n;try{n=Je(Li,new Uint8Array(e))}catch(e){this.log.warn(`undecodable message from iTerm2`,{err:w(e)});return}if(n.submessage.case===`notification`){this.emit(`notification`,n.submessage.value);return}let r=this.pending.get(n.id);r&&(clearTimeout(r.timer),this.pending.delete(n.id),r.resolve(n))}),s.on(`close`,()=>{for(let[e,t]of this.pending)t.ws===s&&(clearTimeout(t.timer),t.reject(Error(`iTerm2 connection closed`)),this.pending.delete(e));this.ws===s&&(this.ws=null),this.emit(`close`)}),s.on(`error`,e=>this.log.warn(`iTerm2 socket error`,{err:w(e)})),this.log.info(`connected to iTerm2 API`)}close(){this.ws?.close(),this.ws=null}request(e){let t=this.ws;if(!t||t.readyState!==Ue.OPEN)return Promise.reject(Error(`iTerm2 not connected`));let n=this.nextId++,r=qe(Ii,{id:n,submessage:e});return new Promise((i,a)=>{let o=setTimeout(()=>{this.pending.delete(n),a(Error(`iTerm2 request timeout (${e.case})`))},this.opts.requestTimeoutMs??5e3);this.pending.set(n,{resolve:i,reject:a,timer:o,ws:t}),t.send(Ye(Ii,r),{binary:!0})})}};function ia(e,t,n){let r,i=new Promise((e,i)=>{r=setTimeout(()=>i(Error(n)),t)});return Promise.race([e,i]).finally(()=>clearTimeout(r))}async function aa(e,t=fetch){let n;try{let t=new URL(e),r={"ws:":`http:`,"wss:":`https:`,"http:":`http:`,"https:":`https:`}[t.protocol];if(!r||!t.hostname)return!1;t.protocol=r,t.username=``,t.password=``,t.pathname=`/healthz`,t.search=``,t.hash=``,n=t.toString()}catch{return!1}let r=new AbortController,i=null,a=setTimeout(()=>{r.abort(),i?.cancel().catch(()=>{})},5e3);try{let e=await t(n,{redirect:`manual`,signal:r.signal});if(!e.body||(i=e.body.getReader(),e.status!==200))return!1;let a=[],o=0;for(;;){let{done:e,value:t}=await i.read();if(e)break;if(o+=t.byteLength,o>4096)return!1;a.push(t)}return!r.signal.aborted&&Buffer.concat(a,o).toString(`utf8`)===`ok`}catch{return!1}finally{if(clearTimeout(a),r.abort(),i){i.cancel().catch(()=>{});try{i.releaseLock()}catch{}}}}const oa=65536,sa=16384,ca=`# shellbell-systemd-v1 `,la=ze.string().max(sa).refine(e=>{for(let t of e){let e=t.codePointAt(0);if(e<32||e>=127&&e<=159||e>=55296&&e<=57343)return!1}return!0}),ua=la.refine(M),da=ze.strictObject({v:ze.literal(1),machineId:ze.string().regex(/^[0-9a-f]{32}$/).refine(e=>e!==`0`.repeat(32)),nodePath:ua.refine(e=>!/["'\\]/.test(e)),cliPath:ua,stateDir:ua,runtimeRoot:ua,serviceInstance:ze.uuid(),path:la.refine(e=>{let t=e.split(`:`);return t.every(M)&&new Set(t).size===t.length})});function K(){throw Error(`shellbell: invalid or foreign systemd unit`)}function fa(e){return`"${e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`).replaceAll(`%`,`%%`)}"`}function pa(e,t){return`Environment=${fa(`${e}=${t}`)}`}function ma(e){let t=da.safeParse(e);t.success||K();let n=t.data,r=2;for(let[e,t]of Object.entries(n))r+=e.length+3+(r===2?0:1),r+=typeof t==`number`?1:Buffer.byteLength(t)+2+[...t].filter(e=>e===`"`||e===`\\`).length;r>sa&&K();let i=JSON.stringify(n);Buffer.byteLength(i)>sa&&K();let a=Buffer.from([ca+Buffer.from(i).toString(`base64url`),`[Unit]`,`Description=Shellbell terminal host`,`ConditionHost=${n.machineId}`,`StartLimitIntervalSec=60s`,`StartLimitBurst=3`,``,`[Service]`,`Type=exec`,`ExecStart=${[`:${n.nodePath}`,n.cliPath,`start`,`--service`].map(fa).join(` `)}`,pa(`SHELLBELL_DIR`,n.stateDir),pa(`SHELLBELL_SERVICE_INSTANCE`,n.serviceInstance),pa(`XDG_RUNTIME_DIR`,n.runtimeRoot),pa(`PATH`,n.path),`Restart=on-failure`,`RestartSec=5s`,`TimeoutStopSec=15s`,`UMask=0077`,`StandardInput=null`,`StandardOutput=null`,`StandardError=journal`,`KillMode=control-group`,``,`[Install]`,`WantedBy=default.target`,``].join(`
81
- `));return a.length>oa&&K(),a}function ha(e){try{e.byteLength>oa&&K();let t=Buffer.from(e),n=t.subarray(0,t.indexOf(10)).toString(`utf8`);n.startsWith(ca)||K();let r=n.slice(23);(r.length>21846||!/^[A-Za-z0-9_-]+$/.test(r))&&K();let i=Buffer.from(r,`base64url`);(i.length>sa||i.toString(`base64url`)!==r)&&K();let a=da.parse(JSON.parse(i.toString(`utf8`)));return ma(a).equals(t)||K(),a}catch{return K()}}function ga(e,t){let n=d(e);n&&(!n.isDirectory()||n.isSymbolicLink()||n.uid!==t||n.mode&18)&&K()}function _a(e,t){ua.safeParse(e).success||K();let n=d(e)?De(e):r(e);return ga(n,t),n}function va(e){let{uid:t,hostScope:n}=e.identity;(!Number.isSafeInteger(t)||t<=0||!/^[0-9a-f]{32}$/.test(n))&&K();let r=_a(e.home,t),i=_a(e.env.XDG_CONFIG_HOME&&M(e.env.XDG_CONFIG_HOME)?e.env.XDG_CONFIG_HOME:N(r,`.config`),t),a=N(i,`systemd`,`user`);for(let e of[N(i,`systemd`),a])ga(e,t);let o=`shellbell-${n}.service`,s=N(a,o),c=d(s);return c&&(!c.isFile()||c.isSymbolicLink()||c.uid!==t||(c.mode&4095)!=384)&&K(),{uid:t,home:r,configRoot:i,unitName:o,unitDir:a,definitionPath:s,enablementPath:N(a,`default.target.wants`,o),managerRuntimeRoot:`/run/user/${t}`}}function q(){throw Error(`shellbell: unsafe, foreign or concurrently changed systemd files`)}function ya(e,t){return n(e,t)&&e.mode===t.mode&&e.uid===t.uid&&e.size===t.size&&e.mtimeMs===t.mtimeMs&&e.ctimeMs===t.ctimeMs}var ba=class{location;machineId;constructor(e,t){this.location=e,this.machineId=t}directory(e,t=!1){let n=d(e);return!n&&t&&(this.directory(j(e),!0),Se(e,{mode:448}),n=d(e)),n&&(!n.isDirectory()||n.isSymbolicLink()||n.uid!==this.location.uid||n.mode&18)&&q(),n}parents(e=!1){let t=[this.location.home,this.location.configRoot,N(this.location.configRoot,`systemd`),this.location.unitDir,j(this.location.enablementPath)],n=[];for(let r of t){let t=this.directory(r,e&&r!==j(this.location.enablementPath));t&&n.push({path:r,stat:t})}return n}inspect(){let e=this.parents(),t=d(this.location.definitionPath),r=null;if(t){let e=a(this.location.definitionPath,65536,this.location.uid),n=ha(e);(n.machineId!==this.machineId||!ya(t,d(this.location.definitionPath)))&&q(),r={stat:t,raw:e,definition:n}}let i=d(this.location.enablementPath),o=null;if(i){let e=i.isSymbolicLink()?Ee(this.location.enablementPath):null;ya(i,d(this.location.enablementPath))||q(),o={stat:i,target:e,owned:i.uid===this.location.uid&&e===this.location.definitionPath}}for(let t of e){let e=this.directory(t.path);(!e||!n(t.stat,e))&&q()}return{unit:r,link:o,parents:e}}assertUnchanged(e){let t=this.inspect();for(let t of e.parents??[]){let e=this.directory(t.path);(!e||!n(t.stat,e))&&q()}(!!t.unit!=!!e.unit||!!t.link!=!!e.link)&&q(),t.unit&&e.unit&&(!ya(t.unit.stat,e.unit.stat)||!t.unit.raw.equals(e.unit.raw))&&q(),t.link&&e.link&&(!ya(t.link.stat,e.link.stat)||t.link.target!==e.link.target)&&q()}matchesFragment(e){try{let t=d(e);return!!t&&t.isFile()&&!t.isSymbolicLink()&&t.uid===this.location.uid&&(t.mode&4095)==384&&N(De(j(e)),A(e))===this.location.definitionPath}catch{return!1}}publish(e,t){(t.machineId!==this.machineId||e.link&&!e.link.owned)&&q();let r=ma(t);this.assertUnchanged(e),this.parents(!0);let i=`${this.location.definitionPath}.tmp-${P()}`,a;try{let t=Ce(i,T.O_WRONLY|T.O_CREAT|T.O_EXCL|T.O_NOFOLLOW,384);try{a=d(i),Ne(t,r),be(t)}finally{ye(t)}this.assertUnchanged(e),e.unit?Oe(i,this.location.definitionPath):xe(i,this.location.definitionPath)}finally{let e=d(i);a&&e&&n(a,e)&&Me(i)}return this.inspect()}setEnabled(e,t){return this.assertUnchanged(e),e.link&&!e.link.owned&&q(),t===!!e.link?e:(t?(e.unit||q(),this.directory(j(this.location.enablementPath),!0),this.assertUnchanged(e),je(this.location.definitionPath,this.location.enablementPath)):(this.assertUnchanged(e),Me(this.location.enablementPath)),this.inspect())}remove(e){return this.assertUnchanged(e),e.link?.owned&&q(),e.unit&&Me(this.location.definitionPath),this.inspect()}restore(e,t){try{this.assertUnchanged(t);let n=t;e.unit&&!n.unit?.raw.equals(e.unit.raw)&&(n=this.publish(n,e.unit.definition)),!!n.link!=!!e.link&&(n=this.setEnabled(n,!!e.link)),e.unit||this.remove(n)}catch{try{this.parents(),e.unit&&Ne(`${this.location.definitionPath}.recovery-${P()}`,e.unit.raw,{flag:`wx`,mode:384})}catch{}throw Error(`shellbell: unresolved systemd file recovery; inspect owned artifacts before retrying`)}}};const xa=[`LoadState`,`ActiveState`,`SubState`,`MainPID`,`UnitFileState`,`FragmentPath`,`DropInPaths`,`NeedDaemonReload`,`ConditionResult`],Sa=[`--user`,`--no-pager`,`--no-ask-password`],Ca=new Set([16914836,61267,1481003842,2435016766]),J=()=>Error(`shellbell: systemd command failed`);function wa(e){for(let t of e){let e=t.codePointAt(0);if(e<32||e>=127&&e<=159||e>=55296&&e<=57343)return!1}return!0}const Ta=()=>({available:!1,loadState:`unknown`,activeState:`unknown`,subState:`unknown`,mainPid:null,unitFileState:`unknown`,fragmentPath:``,dropInPaths:``,needDaemonReload:!0,conditionResult:!1,diagnostic:`systemd user manager unavailable or returned unsupported state`});function Ea(e){for(let t of[`/usr/bin`,`/bin`]){let n=N(t,e);try{return _e(n,T.X_OK),n}catch{}}throw J()}const Da=(e,t,n)=>new Promise((r,i)=>{let a=ge(e,[...t],{shell:!1,env:n.env,stdio:[`ignore`,`pipe`,`pipe`]}),o=0,s=[],c=!1,l=!1,u,d=setTimeout(p,n.timeoutMs);function f(e){c||(c=!0,clearTimeout(d),clearTimeout(u),a.stdout.destroy(),a.stderr.destroy(),l||e==null?i(J()):r({exitCode:e,stdout:Buffer.concat(s)}))}function p(){c||l||(l=!0,a.kill(`SIGTERM`),u=setTimeout(()=>{a.kill(`SIGKILL`),f()},250))}function m(e,t){if(!(c||l)){if(o+=e.length,o>n.maxOutputBytes){p();return}t&&s.push(Buffer.from(e))}}a.stdout.on(`data`,e=>m(e,!0)),a.stderr.on(`data`,e=>m(e,!1)),a.on(`error`,()=>f()),a.on(`close`,e=>f(e))});function Oa(e){if(e.length>65536)throw J();let t=new TextDecoder(`utf-8`,{fatal:!0}).decode(e),n=t.endsWith(`
82
- `)?t.slice(0,-1).split(`
83
- `):t.split(`
84
- `),r=new Map;for(let e of n){let t=e.indexOf(`=`),n=e.slice(0,t),i=e.slice(t+1);if(t<0||!xa.includes(n)||r.has(n)||!wa(i))throw J();r.set(n,i)}if(r.size!==xa.length)throw J();let i=e=>r.get(e);for(let[e,t]of Object.entries({LoadState:[`stub`,`loaded`,`not-found`,`bad-setting`,`error`,`merged`,`masked`],ActiveState:[`active`,`reloading`,`inactive`,`failed`,`activating`,`deactivating`,`maintenance`],SubState:[`dead`,`condition`,`start-pre`,`start`,`start-post`,`running`,`exited`,`reload`,`stop`,`stop-watchdog`,`stop-sigterm`,`stop-sigkill`,`stop-post`,`final-sigterm`,`final-sigkill`,`failed`,`auto-restart`,`cleaning`],UnitFileState:[``,`enabled`,`enabled-runtime`,`linked`,`linked-runtime`,`alias`,`masked`,`masked-runtime`,`static`,`disabled`,`indirect`,`generated`,`transient`,`bad`]}))if(!t.includes(i(e)))throw J();if(!/^(0|[1-9][0-9]*)$/.test(i(`MainPID`)))throw J();let a=Number(i(`MainPID`));if(!Number.isSafeInteger(a))throw J();for(let e of[`NeedDaemonReload`,`ConditionResult`])if(![`yes`,`no`].includes(i(e)))throw J();let o=i(`FragmentPath`);if(o&&!M(o))throw J();return{available:!0,loadState:i(`LoadState`),activeState:i(`ActiveState`),subState:i(`SubState`),mainPid:a||null,unitFileState:i(`UnitFileState`),fragmentPath:o,dropInPaths:i(`DropInPaths`),needDaemonReload:i(`NeedDaemonReload`)===`yes`,conditionResult:i(`ConditionResult`)===`yes`}}function ka(e){return`unix:path=${[...Buffer.from(e)].map(e=>/[A-Za-z0-9_./-]/.test(String.fromCharCode(e))?String.fromCharCode(e):`%${e.toString(16).padStart(2,`0`)}`).join(``)}`}function Aa(e){let t={...e.location},n=e.run??Da;async function r(r,i){try{let{uid:a}=t;if(!Number.isSafeInteger(a)||a<=0||a!==process.getuid?.()||a!==process.geteuid?.()||!/^shellbell-[0-9a-f]{32}\.service$/.test(t.unitName))throw J();for(let e of[t.home,t.configRoot,t.managerRuntimeRoot])if(!M(e)||!wa(e))throw J();S(t.managerRuntimeRoot,a);let o=e.runtimeFsType?.(t.managerRuntimeRoot)??Ae(t.managerRuntimeRoot).type;if(!Ca.has(Number(o)))throw J();let s=await n(e.run?`/usr/bin/${r}`:Ea(r),i,{timeoutMs:3e4,maxOutputBytes:65536,env:{HOME:t.home,XDG_CONFIG_HOME:t.configRoot,XDG_RUNTIME_DIR:t.managerRuntimeRoot,DBUS_SESSION_BUS_ADDRESS:ka(N(t.managerRuntimeRoot,`bus`)),PATH:`/usr/bin:/bin`,LANG:`C`,LC_ALL:`C`}});if(s.exitCode!==0||s.stdout.length>65536)throw J();return s.stdout}catch{throw J()}}return{async observe(){try{return Oa(await r(`systemctl`,[...Sa,`show`,`--property=${xa.join(`,`)}`,t.unitName]))}catch{return Ta()}},async execute(e){if(![`start`,`stop`,`daemon-reload`].includes(e))throw J();await r(`systemctl`,[...Sa,e,...e===`daemon-reload`?[]:[t.unitName]])},async linger(){try{let e=(await r(`loginctl`,[`--no-pager`,`--no-ask-password`,`show-user`,String(t.uid),`--property=Linger`,`--value`])).toString(`utf8`);if(e===`yes
85
- `||e===`yes`)return`yes`;if(e===`no
86
- `||e===`no`)return`no`}catch{}return`unknown`}}}const Y=e=>e.activeState===`inactive`||e.activeState===`failed`,ja=e=>[`enabled`,`enabled-runtime`].includes(e.unitFileState);function X(e){throw Error(`shellbell: ${e}`)}var Ma=class{options;machine;location;files;manager;readiness;clock;constructor(e){this.options=e,this.machine=fe(e.machine),this.location=va({identity:this.machine,env:e.env,home:e.home??k()}),this.files=new ba(this.location,this.machine.machineId),this.manager=e.manager??Aa({location:this.location,runtimeFsType:e.runtimeFsType}),this.readiness=new C(e),this.clock=e.clock??{now:()=>Ze.now(),sleep:e=>new Promise(t=>setTimeout(t,e))}}select(e,t,n=!1){let i=e.unit?.definition;i&&this.options.env.SHELLBELL_DIR!==void 0&&r(this.options.env.SHELLBELL_DIR)!==i.stateDir&&X(`SHELLBELL_DIR conflicts with installed service state; explicit migration is required`);let a;try{let e={...this.options.env,...i?{SHELLBELL_DIR:i.stateDir,...n?{}:{XDG_RUNTIME_DIR:i.runtimeRoot}}:{}};a=(this.options.selectPaths??(e=>p({...this.options.machine,env:e,home:this.options.home,runtimeFsType:this.options.runtimeFsType})))(e),(a.linuxHost.uid!==this.machine.uid||a.linuxHost.hostDigest!==this.machine.hostDigest||i&&a.dir!==i.stateDir)&&X(`selected Linux paths do not match owned service`)}catch{return t&&X(`Linux service runtime/state selection is unsafe or unavailable`),{degraded:!0}}try{let e=_(a);return{paths:a,degraded:!1,expected:{computerFp:e.fp,stateDir:a.dir,...i?{serviceInstance:i.serviceInstance}:{}}}}catch{return t&&X(`Linux host state is not ready; restore initialized credentials before granting service access`),{paths:a,degraded:!0}}}ownedManager(e,t,n=!1){return!t.available||t.dropInPaths!==``||t.needDaemonReload?!1:n&&!e.unit&&[``,`disabled`,`enabled`,`enabled-runtime`].includes(t.unitFileState)&&t.loadState===`not-found`&&t.fragmentPath===``&&Y(t)&&t.mainPid===null?!0:![`disabled`,`enabled`,`enabled-runtime`,`linked`,`linked-runtime`].includes(t.unitFileState)||![`inactive`,`failed`,`active`,`activating`,`deactivating`].includes(t.activeState)?!1:!!e.unit&&t.loadState===`loaded`&&this.files.matchesFragment(t.fragmentPath)}assertManager(e,t,n=!1){this.files.assertUnchanged(e),this.ownedManager(e,t,n)||X(`systemd manager ownership is unavailable, foreign or unresolved; inspect exact unit discovery and overrides`)}async local(e,t,n,r=500){if(!t.paths)return{kind:`unverified`,local:null,diagnostic:`Local certification degraded; runtime is unsafe or unavailable`};let i=await this.readiness.observe(t.paths.sock,t.expected?{...t.expected,...n.mainPid?{pid:n.mainPid}:{}}:void 0,r);return i.local&&e.unit&&(i.local.process.pid!==n.mainPid||!ue(i.local,{computerFp:t.expected?.computerFp??i.local.process.computerFp,stateDir:e.unit.definition.stateDir,serviceInstance:e.unit.definition.serviceInstance}))?{kind:`foreign`,local:i.local,diagnostic:`Local endpoint contradicts owned manager job`}:i}async result(e,t,n,r=!1){let i=await this.manager.observe(),a=this.ownedManager(e,i,!0),o=await this.local(e,t,i),s=await this.manager.observe(),c=!0;try{this.files.assertUnchanged(e)}catch{c=!1}let l=c&&a&&this.ownedManager(e,s,!0)&&i.mainPid===s.mainPid&&i.activeState===s.activeState,u=!!e.unit&&l&&!t.degraded&&i.activeState===`active`&&i.mainPid!==null&&i.conditionResult&&s.conditionResult&&o.kind===`verified`;r&&(!l||!Y(s)||s.mainPid!==null||t.paths&&o.kind!==`absent`)&&X(`service stop final confirmation is unresolved; current job or endpoint is not verified stopped`);let d=ja(s)&&!e.link?.owned||e.link&&!e.link.owned;return{manager:`systemd`,unitName:this.location.unitName,definitionPath:this.location.definitionPath,installed:!!e.unit,enabled:ja(s),startupEnabled:s.available?ja(s):null,autostartConfigured:!!e.link?.owned,activeState:s.activeState,managedPid:s.mainPid,ownership:!l||o.kind===`foreign`?`foreign`:t.degraded?`degraded`:e.unit?`verified`:`none`,ready:u,local:o.local,linger:await this.manager.linger(),...n||d||t.degraded||!l||o.diagnostic?{diagnostic:[n,d?`Remaining external enablement is outside Shellbell's owned link`:void 0,t.degraded?`Local identity/runtime certification degraded; credentials were not repaired`:void 0,l?void 0:`Manager ownership is unresolved`,o.diagnostic].filter(Boolean).join(`; `)}:{}}}async status(){let e=this.files.inspect();return this.result(e,this.select(e,!1))}async serialized(e,t,n){let r=this.files.inspect(),i=this.select(r,e,t),a=async()=>{let t;try{return i.paths&&(pe(i.paths),t=oe(N(i.paths.runtimeDir,`service`))),this.files.assertUnchanged(r),e&&_(i.paths),await n(r,i,!!t)}finally{t?.()}},o=i.paths?.dir??r.unit?.definition.stateDir;return o?v({stateDir:o,uid:this.machine.uid,create:t,startupPreference:e=>e.autostartConfigured},a):a()}async execute(e,t){this.files.assertUnchanged(t);try{await this.manager.execute(e)}catch{X(`systemd ${e} failed or timed out; manager effect may be unresolved`)}}async install(){let e=(this.options.resolveRuntime??ee)(),t=[`/usr/local/bin`,`/usr/bin`,`/bin`],n=(this.options.env.PATH??``).split(`:`).filter(e=>M(e)&&!t.includes(e));return this.serialized(!0,!0,async(r,i)=>{let a=r.unit?.definition,o={v:1,machineId:this.machine.machineId,nodePath:e.nodePath,cliPath:e.cliPath,stateDir:i.paths.dir,runtimeRoot:j(j(i.paths.runtimeDir)),serviceInstance:a?.serviceInstance??P(),path:[...new Set([j(e.nodePath),...n,...t])].join(`:`)},s=ma(o),c=await this.manager.observe();if(this.assertManager(r,c,!r.unit),r.unit?.raw.equals(s))return this.result(r,i);(!Y(c)||c.mainPid!==null)&&X(`active service definition cannot be updated; stop, install, then start explicitly`),(await this.local(r,i,c)).kind!==`absent`&&X(`local endpoint ownership is foreign or unverified; stop foreground owner before install`);let l=await this.manager.observe();this.assertManager(r,l,!r.unit),(!Y(l)||l.mainPid!==null)&&X(`active service job changed during install admission; stop before updating`),a&&(o.serviceInstance=P());let u;try{return u=this.files.publish(r,o),await this.execute(`daemon-reload`,u),this.assertManager(u,await this.manager.observe()),await this.result(u,i)}catch{if(u){this.files.restore(r,u);try{await this.manager.execute(`daemon-reload`)}catch{X(`systemd install failed; definition restored but manager reload remains unresolved`)}}X(`systemd install failed; owned definition restored where possible, inspect manager discovery`)}})}enable(){return this.link(!0)}disable(){return this.link(!1)}link(e){return this.serialized(e,!1,async(t,n,r)=>{let i=await this.manager.observe();if(this.assertManager(t,i,!t.unit&&!e),!t.unit&&e&&X(`service is not installed; run service install first`),t.link&&!t.link.owned)return e&&X(`foreign autostart leaf prevents service enablement`),this.result(t,n,`Foreign autostart artifact remains; inspect it explicitly`);if(!r)return this.result(t,n,`Owned autostart cleanup remains; restore a safe local runtime before changing files`);if(!!t.link===e)return this.result(t,n);let a=this.files.setEnabled(t,e);try{await this.execute(`daemon-reload`,a),this.assertManager(a,await this.manager.observe(),!a.unit)}catch{e&&this.files.restore(t,a),X(`systemd ${e?`enable`:`disable`} reload failed; inspect remaining manager state`)}return this.result(a,n)})}start(){return this.run(`start`)}restart(){return this.run(`restart`)}stop(){return this.run(`stop`)}uninstall(){return this.run(`uninstall`)}async stopped(e,t,n){let r=this.clock.now()+1e4;for(;this.clock.now()<r;){let i=await this.manager.observe();this.assertManager(e,i),i.mainPid!==null&&i.mainPid!==n&&X(`service stop manager job changed; ownership unresolved`);let a=await this.local(e,t,{...i,mainPid:n},Math.min(500,r-this.clock.now()));a.kind===`foreign`&&X(`service stop ownership changed; endpoint is foreign`);let o=await this.manager.observe();if(this.assertManager(e,o),(o.mainPid!==null&&o.mainPid!==n||Y(i)&&!Y(o))&&X(`service stop manager job changed during local probe; ownership unresolved`),Y(o)&&o.mainPid===null&&(!t.paths||a.kind===`absent`))return;await this.clock.sleep(Math.min(100,Math.max(0,r-this.clock.now())))}X(`service stop timed out; stopped state remains unresolved`)}async stopOwned(e,t){let n=await this.manager.observe();this.assertManager(e,n);let r=await this.local(e,t,n);r.kind===`foreign`&&X(`local endpoint ownership is foreign; refusing service stop`);let i=await this.manager.observe();this.assertManager(e,i),(i.mainPid!==n.mainPid||Y(n)&&!Y(i))&&X(`service stop ownership changed during local probe`),(!Y(i)||i.mainPid!==null||t.paths&&r.kind!==`absent`)&&(await this.execute(`stop`,e),await this.stopped(e,t,n.mainPid))}async ready(e,t,n={}){let r=this.clock.now()+1e4;for(;this.clock.now()<r;){let i=await this.manager.observe();this.assertManager(e,i),n.pid!==void 0&&i.mainPid!==n.pid&&X(`service readiness manager job changed`),i.mainPid!==null&&(n.pid??=i.mainPid);let a=await this.local(e,t,i,Math.min(500,r-this.clock.now()));a.kind===`foreign`&&X(`service readiness ownership is foreign`);let o=await this.manager.observe();if(this.assertManager(e,o),o.mainPid!==i.mainPid&&X(`service readiness manager job changed`),o.activeState===`active`&&o.conditionResult&&o.mainPid!==null&&a.kind===`verified`)return a.local;await this.clock.sleep(Math.min(100,Math.max(0,r-this.clock.now())))}X(`service readiness timed out`)}async cleanupStart(e,t,n){let r=await this.manager.observe();this.assertManager(e,r);let i=await this.local(e,t,r),a=await this.manager.observe();this.assertManager(e,a),(a.mainPid!==r.mainPid||Y(r)&&!Y(a))&&X(`start ownership changed during local probe; cleanup unresolved`),!(Y(a)&&a.mainPid===null&&i.kind===`absent`)&&((r.mainPid===null||n.pid!==void 0&&n.pid!==r.mainPid||![`verified`,`absent`].includes(i.kind))&&X(`start ownership unresolved; no cleanup stop was attempted`),await this.execute(`stop`,e),await this.stopped(e,t,r.mainPid))}run(e){let t=e===`stop`||e===`uninstall`;return this.serialized(!t,!1,async(n,r,i)=>{let a=await this.manager.observe();if(this.assertManager(n,a,!n.unit&&t),!n.unit)return t||X(`service is not installed; run service install first`),this.result(n,r);let o=await this.local(n,r,a);if(o.kind===`foreign`&&X(`local endpoint ownership is foreign`),e!==`start`&&await this.stopOwned(n,r),t){let t=n;e===`uninstall`&&i&&((!t.link||t.link.owned)&&(t=this.files.setEnabled(t,!1)),t=this.files.remove(t),await this.execute(`daemon-reload`,t),this.assertManager(t,await this.manager.observe(),!0));let a=e===`uninstall`?i?`Service uninstalled; credentials remain unchanged`:`Service stopped; owned definition and autostart cleanup remain until runtime is safe`:`Service stopped; if enabled, it may start after a later user-manager restart`;return this.result(t,r,a,!0)}if(e===`start`&&a.activeState===`active`){await this.ready(n,r);let e=await this.result(n,r);return e.ready||X(`service start readiness changed during final confirmation`),e}e===`start`&&(!Y(a)||a.mainPid!==null||o.kind!==`absent`)&&X(`service start ownership is unresolved; stop the foreground or pending owner first`);let s=await this.manager.observe();this.assertManager(n,s),(!Y(s)||s.mainPid!==null)&&X(`service start manager job changed before command; ownership unresolved`);let c={};try{await this.execute(`start`,n),await this.ready(n,r,c);let e=await this.result(n,r);return e.ready||X(`service start readiness changed during final confirmation`),e}catch{try{await this.cleanupStart(n,r,c)}catch{X(`service start failed; ownership or cleanup remains unresolved`)}X(`service start failed; newly started owned job was stopped`)}})}};const Na=Ge(me);function Pa(e){let t=/(\d+)\.(\d+)/.exec(e);return t?Number(t[1])+Number(t[2])/100:null}function Fa(e){return+!!e.some(e=>e.severity===`error`)}function Z(e,t){return{name:e,ok:!0,severity:`pass`,detail:t}}function Q(e,t,n){return{name:e,ok:!0,severity:`warning`,detail:t,...n?{fix:n}:{}}}function $(e,t,n){return{name:e,ok:!1,severity:`error`,detail:t,...n?{fix:n}:{}}}function Ia(e,t,n,r){return t?{...Z(e,`connected to the local agent`),...n?{required:n}:{}}:n?{...$(e,`required backend is not connected; ${r.detail}`,r.fix),required:!0}:r}function La(e,t){for(let n of t.PATH?.split(Pe)??[])if(n)try{return _e(N(n,e),T.X_OK),!0}catch{}return!1}async function Ra(e){return(await Na(`tmux`,[`-V`],{env:e,timeout:3e3,maxBuffer:65536})).stdout}async function za(e){return Ai({socketPath:ar(e),herdrOnPath:()=>La(`herdr`,e)})}function Ba(e,t){if(!e.installed||!e.definition)return{env:t,context:`current shell setup`};let n=e.definition.environment;return{env:{PATH:n.PATH,HERDR_SOCKET_PATH:n.HERDR_SOCKET_PATH,XDG_CONFIG_HOME:n.XDG_CONFIG_HOME},context:`installed service setup`}}function Va(e){try{let t=process.getuid?.();return t!==void 0&&new te({stateDir:r(e),uid:t}).inspect()?.mode===`desktop`}catch{return!1}}function Ha(e,t,n){return e.loaded&&!e.installed?$(`service manager`,`loaded service has no installed definition`):!e.installed&&Va(n)?Z(`service manager`,`the Shellbell app runs this service`):e.installed?e.definition?e.loaded?e.definition.serviceInstance?t?t.process.serviceInstance===e.definition.serviceInstance?Z(`service manager`,`loaded job matches the local service instance`):$(`service manager`,`loaded job does not match the local service instance`,`stop the foreground owner and restart the service`):Q(`service manager`,`loaded job cannot be matched until local control responds`):Q(`service manager`,`legacy service definition has no verifiable instance marker`,`reinstall the service to record a service instance`):Q(`service manager`,`installed service is stopped`,"run `shellbell service start` if background operation is wanted"):$(`service manager`,`installed service definition is unreadable`,`reinstall the service after checking its definition`):Q(`service manager`,`no service definition installed; foreground agent can still run`,"run `shellbell service install` for autostart")}function Ua(e){let t=`installed=${e.installed}; enabled=${e.enabled}; active=${e.activeState}; authenticated ready=${e.ready}; linger=${e.linger}; ownership=${e.ownership}${e.diagnostic?`; ${e.diagnostic}`:``}`;return e.activeState===`unknown`?Q(`service manager`,t,`restore access to the current user's systemd manager; foreground readiness is independent`):e.ownership===`foreign`?$(`service manager`,t,`inspect the exact unit and any drop-ins; Shellbell refuses foreign definitions`):e.ready?Z(`service manager`,t):Q(`service manager`,t,`inspect shellbell service status; install, start, and enable are separate choices; foreground readiness is independent`)}function Wa(e,t){let n=e=>t.includes(e)?{...$(e,`required backend unavailable until service state is selected`),required:!0}:Q(e,`unavailable until service state is selected`);return[Q(`identity`,e),$(`service manager`,e),Q(`control`,`unavailable until service state is selected`),Q(`relay`,`unavailable until service state is selected`),n(`iterm2`),n(`tmux`),n(`herdr`),Q(`terminal readiness`,`unavailable until service state is selected`)]}async function Ga(e,n={}){let r=(e.platform??process.platform)===`linux`,a=Q(`service manager`,`Linux systemd user-manager inspection unavailable; foreground readiness is independent`,`inspect shellbell service status and the current user's systemd manager`),o=e.requiredBackends.filter(e=>e!==`tmux`).map(e=>({...$(e,e===`herdr`?`Shellbell's Herdr backend is not yet qualified for Linux delivery (Herdr itself supports Linux)`:`iTerm2 is not supported on Linux`),required:!0})),s=null,c;if(r){let t,r={...e.env,SHELLBELL_DIR:e.requestedStateDir??e.env.SHELLBELL_DIR},i=e=>(r=e,t=(n.selectLinuxPaths??(e=>p({env:e})))(e),t);try{a=Ua(await(n.inspectLinuxService??(()=>new Ma({env:r,selectPaths:i}).status()))(i))}catch{}let s;try{let e=t??i(r);c=e;let n=ae(e);s=n.status===`ready`?Z(`host state`,`Linux host state admitted`):$(`host state`,n.reason??`Linux host state is absent`,`initialize absent state with shellbell host init --new, or inspect existing state before recovery`)}catch{s=$(`host state`,`Linux state or runtime selection is unsafe or unavailable`,`use a nonroot matching real/effective user, a valid machine ID, and a private 0700 local runtime directory`)}if(s.severity===`error`)return[s,a,Q(`control`,`unavailable until host state is admitted`),Q(`relay`,`unavailable until host state is admitted`),...o,e.requiredBackends.includes(`tmux`)?{...$(`tmux`,`required backend unavailable until host state is admitted`),required:!0}:Q(`tmux`,`unavailable until host state is admitted`)]}else{try{s=await(n.inspectManager??(()=>i().inspect()))()}catch{return Wa(`service manager inspection failed; state unavailable`,e.requiredBackends)}try{c=le(s,e.requestedStateDir,e.defaultStateDir)}catch{return Wa(`state selection unavailable; check SHELLBELL_DIR against installed service`,e.requiredBackends)}}let l,d=null;try{let e=t(c);e?(d=e.fp,l=Z(`identity`,r?`valid admitted Linux identity`:`valid identity at ${c.identity}`)):l=$(`identity`,`identity missing at ${c.identity}`,`start Shellbell once to create an identity`)}catch{l=$(`identity`,r?`Linux identity invalid or unreadable`:`identity invalid or unreadable at ${c.identity}`,`restore the original identity file; do not replace paired keys`)}let m=null,h;if(!d)h=$(`control`,`cannot verify local process without a valid identity`);else try{let e=await(n.controlStatus??(e=>u(e,`status`,void 0,{timeoutMs:500,maxResponseBytes:65536})))(c.sock),t=f.safeParse(e);t.success?ue(t.data,{computerFp:d,stateDir:c.dir})?(m=t.data,h=Z(`control`,`local agent identity and state verified`)):h=$(`control`,`local endpoint belongs to a different identity or state directory`):h=$(`control`,`local endpoint returned malformed or unsupported status`)}catch{h=$(`control`,`local endpoint is absent or did not return bounded status`,`start Shellbell, or inspect the configured service`)}let g=r?a:Ha(s,m,c.dir),_=null,ee=null;try{ee=ie(c).relayUrl}catch{_=$(`relay`,r?`Linux configuration invalid or unreadable`:`configuration invalid or unreadable at ${c.config}`,`repair the existing config without replacing identity files`)}if(!_){if(m?.relayOnline)_=Z(`relay`,`local agent reports relay connected`);else{let e=`configured relay`,t=!1;try{let r=new URL(ee);[`ws:`,`wss:`,`http:`,`https:`].includes(r.protocol)&&(e=`${r.protocol===`ws:`?`http:`:r.protocol===`wss:`?`https:`:r.protocol}//${r.host}/healthz`,t=await(n.relayHealth??aa)(ee))}catch{}_=$(`relay`,`local agent is not relay-connected; ${e} ${t?`is reachable`:`is not confirmed reachable`} (HTTP health does not prove WebSocket authorization)`,`check the relay URL, network, and running agent`)}}let{env:te,context:v}=r?{env:e.env,context:`current shell setup`}:Ba(s,e.env),ne=new Set(e.requiredBackends),y=e=>m?.backends.find(t=>t.name===e)?.connected===!0,b=Q(`iterm2`,`${v}: iTerm2 API socket unavailable`,`enable iTerm2 Python API, then start Shellbell to authorize access`);if(!r&&!y(`iterm2`))try{(n.itermSocketExists??(()=>E(na)))()&&(b=Q(`iterm2`,`${v}: API socket exists but agent is disconnected`,`start Shellbell to authorize iTerm2 API access`))}catch{b=$(`iterm2`,`iTerm2 API socket inspection failed`)}let re=Ia(`iterm2`,y(`iterm2`),ne.has(`iterm2`),b),x=Q(`tmux`,`${v}: tmux is unavailable`,`install tmux 3.2 or newer`);if(!y(`tmux`))try{let e=Pa(await(n.tmuxVersion??Ra)(te));x=e===null||e<3.02?$(`tmux`,`${v}: tmux version is unsupported or unrecognizable`,`install tmux 3.2 or newer`):Q(`tmux`,`${v}: tmux 3.2+ is installed but not connected`,`start a tmux session and Shellbell`)}catch(e){x=e.code===`ENOENT`?Q(`tmux`,`${v}: tmux executable not found`,`install tmux 3.2 or newer`):$(`tmux`,`${v}: tmux version probe failed`,`check installed tmux and the saved PATH`)}let oe=Ia(`tmux`,y(`tmux`),ne.has(`tmux`),x),S=Q(`herdr`,`${v}: Herdr is unavailable`,er);if(!r&&!y(`herdr`))try{let e=await(n.checkHerdr??za)(te);S=e.ok?e.detail===`not installed (optional)`?Q(`herdr`,`${v}: Herdr not found on PATH`,er):e.detail===`installed but not running (optional)`?Q(`herdr`,`${v}: Herdr is installed but not running`,`start Herdr and Shellbell`):Q(`herdr`,`${v}: Herdr API available but agent is disconnected`,`start Shellbell with Herdr enabled`):$(`herdr`,`${v}: Herdr API is broken or unsupported`,tr)}catch{S=$(`herdr`,`${v}: Herdr API probe failed`,tr)}let C=Ia(`herdr`,y(`herdr`),ne.has(`herdr`),S),se=m?await(n.terminalSetup??qa)(c.sock).catch(()=>null):null,ce=!r&&!!se&&pt(se),w=(e,t)=>{let n=se?.find(e=>e.name===t);if(!n?.issue)return e;let{status:r,fix:i}=dt(n,`command-line`,{noneUsable:ce});return n.connected?{...Q(t,r,i),...e.required?{required:!0}:{}}:Ia(t,!1,ne.has(t),Q(t,r,i))},de=(r?y(`tmux`):m?.terminalReady)?Z(`terminal readiness`,`at least one backend connected to the verified local agent`):ce?$(`terminal readiness`,mt(`command-line`).status,mt(`command-line`).fix):$(`terminal readiness`,`no backend connected to a verified local agent`,`start Shellbell with a supported terminal backend`);return[...r?[Z(`host state`,`Linux host state admitted`)]:[],l,g,h,_,...r?o:[w(re,`iterm2`)],w(oe,`tmux`),...r?[]:[w(C,`herdr`)],de,Ka(c.dir,e.env.HOME)]}function Ka(e,t){try{let n=Bn(Mn(e,t||void 0)),r=n.filter(e=>e.state===`needs-setup`);if(r.length)return Q(`coding agents`,`${r.map(e=>e.name).join(`, `)} can't show full history on your phone yet`,`run shellbell agents setup`);let i=n.filter(e=>e.state===`ready`);return Z(`coding agents`,i.length?`full history ready for ${i.map(e=>e.name).join(`, `)}`:`no agents need setup`)}catch{return Q(`coding agents`,`couldn't check coding agents`,`run shellbell agents`)}}async function qa(e){let t=await o(e);try{return await t.terminals()}finally{t.close()}}export{Ct as $,Ei as A,Gn as B,Ji as C,W as D,Ni as E,Zn as F,cn as G,Hn as H,Kn as I,zt as J,Gt as K,Mn as L,Wr as M,br as N,Pi as O,Qn as P,Et as Q,Vn as R,Zi as S,Bi as T,Un as U,Wn as V,ln as W,Ut as X,Rt as Y,Vt as Z,Ui as _,Ma as a,dt as at,Wi as b,Qi as c,Ri as d,xt as et,Xi as f,Vi as g,Ki as h,Ga as i,lt as it,Kr as j,ji as k,$i as l,Hi as m,Fa as n,St as nt,na as o,ot,ta as p,Kt as q,Pa as r,ht as rt,ra as s,st,Ka as t,yt as tt,zi as u,Yi as v,ea as w,Gi as x,qi as y,Bn as z};
@@ -1,11 +0,0 @@
1
- import{A as e,At as t,C as n,D as r,E as i,Et as a,O as o,Ot as s,T as c,c as l,dt as u,f as d,ft as f,i as p,k as m,kt as h,m as g,mt as _,p as v,v as y,x as b,y as x}from"./service-lifecycle-CCOIXXFm.js";import{createRequire as S}from"node:module";import{closeSync as C,constants as w,fstatSync as T,mkdirSync as E,openSync as ee,readdirSync as D,realpathSync as O,unlinkSync as k}from"node:fs";import{basename as te,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){(!c.safeParse(e).success||e!==j(e))&&F();for(let t=e;;t=A(t)){let e=s(t);if(e&&(!e.isDirectory()||e.isSymbolicLink())&&F(),A(t)===t)break}}function F(){throw new g(`unsafe-state`)}function I(e){return(!c.safeParse(e).success||[...e].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)===127))&&F(),e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&apos;`)}function L(e){return(e!==j(e)||!e.endsWith(`/Shellbell.app/Contents/MacOS/Shellbell`))&&F(),Buffer.from(`<?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0"><dict>
4
- <key>Label</key><string>${N}</string>
5
- <key>ProgramArguments</key><array><string>${I(e)}</string><string>--service-run</string><string>manual</string></array>
6
- <key>RunAtLoad</key><true/>
7
- <key>KeepAlive</key><true/>
8
- <key>ThrottleInterval</key><integer>10</integer>
9
- </dict></plist>
10
- `)}function R(e,n){return e===null||n===null?e===n:t(e.stat,n.stat)&&e.stat.mode===n.stat.mode&&e.stat.uid===n.stat.uid&&e.stat.size===n.stat.size&&e.stat.mtimeMs===n.stat.mtimeMs&&e.stat.ctimeMs===n.stat.ctimeMs&&e.raw.equals(n.raw)}function z(e,n){let r=j(e,`manual.plist`),i,o=t=>{try{if(P(e),!s(e))return null;h(e,n);let i=s(r);if(!i)return null;let o=a(r,65536,n);return o.equals(L(t))||F(),{stat:i,raw:o}}catch{return F()}},c=e=>{let t=o(e);return i!==void 0&&!R(i,t)&&F(),i=t,t};return{path:r,inspect(e){return c(e)!==null},write(a){let l=L(a),u=c(a);P(e),s(e)||E(e,{recursive:!0,mode:448});let d=h(e,n);_(r,l,()=>{P(e),(!t(d,h(e,n))||!R(u,o(a)))&&F()}),i=o(a),i?.raw.equals(l)||F()},remove(e){let t=c(e);t&&(R(t,o(e))||F(),k(r),i=null)}}}const B=`sh.bilal.shellbell.host.agent`,V=65536;function H(){throw new g(`unsafe-state`)}function U(e){(!c.safeParse(e).success||e!==j(e)||te(e)!==`Shellbell.app`)&&H();let t=j(e,`Contents`,`MacOS`,`Shellbell`);return c.safeParse(t).success||H(),t}async function W(e,t,n,r,i=!1,a=1e4){try{let i=await e(t,n,{input:r,timeoutMs:a,maxOutputBytes:V,captureOutput:!0});if(!Number.isInteger(i.exitCode)||i.exitCode<0||i.exitCode>255||!Buffer.isBuffer(i.stdout)||i.stdout.length>V)throw Error(`invalid command result`);return i}catch{throw new g(i?`delivery-unknown`:`unavailable`)}}function G(e,n){return t(e,n)&&e.mode===n.mode&&e.uid===n.uid&&e.size===n.size&&e.mtimeMs===n.mtimeMs&&e.ctimeMs===n.ctimeMs}async function K(e,t,n=r){let i=U(e),o=j(e,`Contents`,`Info.plist`),c=new Map,l=()=>{P(A(e));for(let n of[e,j(e,`Contents`),j(e,`Contents`,`MacOS`),o,i]){let e=s(n),r=n===o||n===i;(!e||e.isSymbolicLink()||(r?!e.isFile():!e.isDirectory())||e.uid!==t&&e.uid!==0||e.mode&3602||n===i&&!(e.mode&73))&&H();let a=c.get(n);a&&!G(a,e)&&H(),c.set(n,e)}};try{l();let e=await W(n,`/usr/bin/plutil`,[`-convert`,`json`,`-o`,`-`,`-`],a(o,V));e.exitCode!==0&&H();let t=JSON.parse(new TextDecoder(`utf-8`,{fatal:!0}).decode(e.stdout));return(t?.CFBundleIdentifier!==`sh.bilal.shellbell.host`||t?.CFBundleExecutable!==`Shellbell`)&&H(),l(),{executable:i,revalidate:l}}catch{return H()}}function q(e,t,n,r){let i;try{i=new TextDecoder(`utf-8`,{fatal:!0}).decode(e)}catch{return H()}let a=i.trim().split(/\r?\n/).map(e=>e.trim());(a.shift()!==`${t} = {`||a.pop()!==`}`)&&H();let o=1,s,c=null,l=!1,u,d=!1;for(let e of a)if(e){if(e===`}`){o<=1&&H(),d&&o===2&&(d=!1),o--;continue}if(o===1&&e.startsWith(`program = `)){s!==void 0&&H(),s=e.slice(10);continue}if(o===1&&e.startsWith(`pid = `)){(l||!/^pid = [1-9][0-9]*$/.test(e))&&H(),l=!0,c=Number(e.slice(6)),(!Number.isSafeInteger(c)||c>2147483647)&&H();continue}if(o===1&&/^(?:pid|program|arguments)(?:\s|=)/.test(e)&&e!==`arguments = {`&&H(),e.endsWith(`= {`)){o===1&&e===`arguments = {`?(u!==void 0&&H(),u=[],d=!0):d&&H(),o++;continue}d&&o===2?u.push(e):(e.includes(`{`)||e.includes(`}`))&&H()}return(o!==1||s!==n||!u||u.length!==3||u[0]!==(r===`persistent`?`Shellbell`:n)||u[1]!==`--service-run`||u[2]!==r)&&H(),c}function J(e){let{root:t,uid:a,homeDir:l}=e;(!Number.isSafeInteger(a)||a<=0||!c.safeParse(t).success||!c.safeParse(l).success||t!==j(t)||l!==j(l))&&H();let u=j(l,`Library`,`LaunchAgents`);(t===u||t.startsWith(`${u}/`))&&H();let d=e.run??r,f=z(t,a),m=()=>e.legacy??i({run:d,uid:a,homeDir:l}),h=`gui/${a}`,_=e=>`${h}/${e===`manual`?N:B}`,v=e=>{b.safeParse(e).success||H()};async function x(e,t,n,r=`service`){let i=await K(e,a,d);await n?.(),i.revalidate();let o=t!==`status`,s=await W(d,i.executable,[r===`login`?`--login-api`:`--service-api`,t],void 0,o);i.revalidate();let c;try{c=y.parse(JSON.parse(new TextDecoder(`utf-8`,{fatal:!0}).decode(s.stdout)))}catch{throw new g(o?`delivery-unknown`:`unavailable`)}if(!c.ok)throw new g(c.error.code===`denied`?`approval-required`:c.error.code===`invalid-bundle`?`unsafe-state`:`operation-failed`);if(s.exitCode!==0)throw new g(o?`delivery-unknown`:`unavailable`);return c.status}async function S(e,t,n=1e4){let r=await W(d,`/bin/launchctl`,[`print`,_(e)],void 0,!1,n);if(r.exitCode===113)return{loaded:!1,pid:null};if(r.exitCode!==0)throw new g(`unavailable`);return{loaded:!0,pid:q(r.stdout,_(e),U(t),e)}}let C={loginStatus:e=>x(e,`status`,void 0,`login`),async setLogin(e,t){let n=await K(e,a,d),r=await W(d,`/usr/bin/codesign`,[`--verify`,`--strict`,e]);if(n.revalidate(),r.exitCode!==0)throw new g(`startup-unavailable`);let i=await x(e,`status`,void 0,`login`);if(i===`not-found`&&!t||i===`unknown`)throw new g(`startup-unavailable`);if(t?i===`enabled`||i===`requires-approval`:i===`not-registered`)return i;try{await x(e,t?`register`:`unregister`,void 0,`login`)}catch(n){if(!(t&&n instanceof g&&n.code===`approval-required`&&await x(e,`status`,void 0,`login`)===`requires-approval`))throw n}let o=await x(e,`status`,void 0,`login`);if(t?o!==`enabled`&&o!==`requires-approval`:o!==`not-registered`)throw new g(`operation-failed`);return o},async preflight(e,t){await o(d,a,l);let n=await K(t,a,d);if(e===`persistent`){let e=await W(d,`/usr/bin/codesign`,[`--verify`,`--strict`,t]);if(n.revalidate(),e.exitCode!==0||await x(t,`status`)===`not-found`)throw new g(`startup-unavailable`)}},async prepareManualRecovery(e){if(await o(d,a,l),v(e),n(e.mode)!==`persistent`&&H(),(await C.inspect(`persistent`,e.bundlePath)).loaded)throw new g(`conflict`);if((await W(d,`/bin/launchctl`,[`disable`,_(`persistent`)],void 0,!0)).exitCode!==0)throw new g(`operation-failed`);let t=await W(d,`/bin/launchctl`,[`print-disabled`,h]),r=new TextDecoder(`utf-8`,{fatal:!0}).decode(t.stdout).trim().split(/\r?\n/).map(e=>e.trim());if(t.exitCode!==0||r.shift()!==`disabled services = {`||r.pop()!==`}`||r.filter(e=>e.includes(`"${B}"`)).join(`
11
- `)!==`"${B}" => disabled`)throw new g(`operation-failed`);let i=await C.inspect(`persistent`,e.bundlePath);if(i.loaded)throw new g(`conflict`);i.registration!==`not-registered`&&i.registration!==`not-found`&&await C.stop(e,i)},inspectLegacy:()=>m().inspect(),async inspect(e,t){e!==`manual`&&e!==`persistent`&&H();let n=U(t),r;e===`manual`?r=f.inspect(n)?`enabled`:`not-registered`:(P(A(t)),r=s(t)?await x(t,`status`):`not-found`);let i=await S(e,t);return e===`manual`&&i.loaded&&r!==`enabled`&&H(),{registration:r,...i,bundlePath:t}},async start(e){if(v(e),await C.preflight(n(e.mode),e.bundlePath),(await C.inspect(n(e.mode),e.bundlePath)).loaded)throw new g(`conflict`);if(n(e.mode)===`persistent`){if((await W(d,`/bin/launchctl`,[`enable`,_(`persistent`)],void 0,!0)).exitCode!==0)throw new g(`operation-failed`);return{registration:await x(e.bundlePath,`register`,async()=>{if((await S(`persistent`,e.bundlePath)).loaded)throw new g(`conflict`)}),...await S(n(e.mode),e.bundlePath),bundlePath:e.bundlePath}}let t=await K(e.bundlePath,a,d);if(f.write(t.executable),(await S(`manual`,e.bundlePath)).loaded)throw new g(`conflict`);if(f.inspect(t.executable),t.revalidate(),(await W(d,`/bin/launchctl`,[`bootstrap`,h,f.path],void 0,!0)).exitCode!==0)throw new g(`operation-failed`);return C.inspect(`manual`,e.bundlePath)},async stop(e,t){v(e),t.bundlePath!==e.bundlePath&&H();let r=await C.inspect(n(e.mode),e.bundlePath);if(r.loaded!==t.loaded||r.pid!==t.pid||r.registration!==t.registration)throw new g(`conflict`);if(n(e.mode)===`persistent`){if(await x(e.bundlePath,`unregister`,async()=>{let t=await S(`persistent`,e.bundlePath);if(t.loaded!==r.loaded||t.pid!==r.pid)throw new g(`conflict`)})!==`not-registered`)throw new g(`operation-failed`)}else if(r.loaded&&(f.inspect(U(e.bundlePath)),(await W(d,`/bin/launchctl`,[`bootout`,_(`manual`)],void 0,!0)).exitCode!==0))throw new g(`operation-failed`);let i=performance.now()+1e4;for(;;){let t=i-performance.now();if(t<=0)throw new g(`operation-failed`);let a=await S(n(e.mode),e.bundlePath,t);if(!a.loaded)break;if(a.pid!==null&&a.pid!==r.pid)throw new g(`conflict`);let o=Math.min(100,i-performance.now());if(o<=0)throw new g(`operation-failed`);await new Promise(e=>setTimeout(e,o))}},async remove(e){v(e);let t=await C.inspect(n(e.mode),e.bundlePath);if(t.loaded||n(e.mode)===`persistent`&&t.registration!==`not-registered`)throw new g(`conflict`);n(e.mode)===`manual`&&f.remove(U(e.bundlePath))},withLegacyGuard(e){return p(m(),!0,e)}};return C}const Y=()=>{throw new g(`unsafe-state`)};async function X(e,t={}){try{(O(e)!==e||[...e].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)===127))&&Y();let n=t.run??r,i=await K(e,process.getuid(),n),o=j(e,`Contents`),c=j(o,`Resources`),l=j(o,`Helpers/node`),u=j(c,`agent/dist/native-controller.js`),d=j(c,`agent/dist/native-service.js`),f=[l,u,d,j(c,`runtime/LICENSE`),j(c,`agent/package.json`),j(c,`agent/dist/cli.js`)],p=()=>{for(let t of f){for(let n=A(t);n!==e;n=A(n)){let e=s(n);(!e?.isDirectory()||e.isSymbolicLink()||e.mode&3602||e.uid!==0&&e.uid!==process.getuid())&&Y()}let n=s(t);(!n?.isFile()||n.isSymbolicLink()||n.mode&3602||n.uid!==0&&n.uid!==process.getuid()||t===l&&!(n.mode&73))&&Y()}let t=0,n=new Set,r=e=>{++t>1e5&&Y();let i=s(e);if(!i)throw new g(`unsafe-state`);let a=O(e);if(a.startsWith(`${c}/`)||Y(),i.isSymbolicLink()){r(a);return}if(!n.has(a)){if(n.add(a),(i.uid!==0&&i.uid!==process.getuid()||i.mode&3602)&&Y(),i.isDirectory())for(let t of D(e))r(j(e,t));else i.isFile()||Y()}};for(let e of[`agent`,`runtime`])r(j(c,e))};p();let m=JSON.parse(a(j(c,`agent/package.json`),65536).toString(`utf8`));(m.name!==`shellbell`||typeof m.version!=`string`||!m.version||m.type!==`module`)&&Y();let h=S(j(c,`agent/package.json`));for(let e of Object.keys(m.dependencies??{}))O(h.resolve(e)).startsWith(`${c}/agent/`)||Y();let _=await n(`/usr/bin/plutil`,[`-convert`,`json`,`-o`,`-`,j(o,`Info.plist`)],{timeoutMs:1e4,maxOutputBytes:65536,captureOutput:!0});(_.exitCode!==0||JSON.parse(_.stdout.toString(`utf8`)).CFBundleShortVersionString!==m.version)&&Y();let v=await n(l,[`--version`],{timeoutMs:1e4,maxOutputBytes:65536,captureOutput:!0});(v.exitCode!==0||v.stdout.toString(`utf8`).trim()!==`v22.23.1`)&&Y();let y=await n(l,[`-p`,`process.platform + ':' + process.arch`],{timeoutMs:1e4,maxOutputBytes:65536,captureOutput:!0});(y.exitCode!==0||y.stdout.toString(`utf8`).trim()!==`${process.platform}:${process.arch}`)&&Y();for(let e of[j(c,`agent/dist/cli.js`),u,d]){let t=await n(l,[e,`--version`],{timeoutMs:1e4,maxOutputBytes:65536,captureOutput:!0});(t.exitCode!==0||t.stdout.toString(`utf8`).trim()!==m.version)&&Y()}return i.revalidate(),p(),{executable:i.executable,nodePath:l,controllerPath:u,servicePath:d,agentVersion:m.version}}catch(e){if(e instanceof g)throw e;return Y()}}const Z=M.strictObject({v:M.literal(1),instance:M.uuid()});function ne(e,t){let n,r,i=new Promise((e,t)=>{n=e,r=t}),a=!1,o=!1,s=Buffer.alloc(0),c=setTimeout(()=>u(),t.timeoutMs??5e3),l=()=>{clearTimeout(c),e.off(`data`,d),e.off(`end`,u),e.off(`close`,u),e.off(`error`,u)},u=()=>{o||(o=!0,l(),r(new g(`unavailable`)),Promise.resolve().then(()=>t.onLost()).catch(()=>{}))},d=e=>{if(o)return;let r=Buffer.isBuffer(e)?e:Buffer.from(e);if(a||s.length+r.length>1024){u();return}s=Buffer.concat([s,r]);let i=s.indexOf(10);if(!(i<0))try{let e=Z.parse(JSON.parse(new TextDecoder(`utf-8`,{fatal:!0}).decode(s.subarray(0,i))));if(i!==s.length-1||e.instance!==t.instance)throw Error();a=!0,s=Buffer.alloc(0),clearTimeout(c),n()}catch{u()}};return e.on(`data`,d),e.once(`end`,u),e.once(`close`,u),e.once(`error`,u),(e.destroyed||e.readableEnded)&&u(),{ready:i,close:u}}var Q=class extends d{constructor(e){super({...e,filename:`controller.json`,maxBytes:v,schema:x})}};function re(e,t,n){if(n.NODE_OPTIONS||n.NODE_PATH||!b.safeParse(e).success||!c.safeParse(t).success)throw new g(`unsafe-state`);return{...e.environment,HOME:t}}function $(t,n,r=!1){try{if(n<=0||!c.safeParse(t).success||[...t].some(e=>e.charCodeAt(0)<32||e.charCodeAt(0)===127))throw Error();for(let e=t;;e=A(e)){let t=s(e);if(t&&(!t.isDirectory()||t.isSymbolicLink()))throw Error();if(A(e)===e)break}if(!s(t)){if(!r)return null;E(t,{recursive:!0,mode:448})}if(h(t,n),O(t)!==t)throw Error();let i=u(t);for(let e of[i.identity,i.pairings,i.config,i.pid])s(e)&&a(e,65536,n);ie(i.log,n);let o=s(i.sock);if(o&&(!o.isSocket()||o.uid!==n||(o.mode&4095)!=384))throw Error();return f(i),r?m(i):e(i)}catch{throw new g(`unsafe-state`)}}function ie(e,n){let r=s(e);if(!r)return;let i=e=>{if(!e.isFile()||e.isSymbolicLink()||e.uid!==n||(e.mode&4095)!=384)throw Error()};i(r);let a=ee(e,w.O_RDONLY|w.O_NOFOLLOW|w.O_NONBLOCK);try{let n=T(a);i(n);let o=s(e);if(!o||(i(o),!t(r,n)||!t(n,o)))throw Error()}finally{C(a)}}async function ae(e,t){let n=new Q(t).inspect()?.selection;if(!n||n.mode!==e||n.bundlePath!==t.bundlePath)throw new g(`conflict`);let r=$(n.stateDir,t.uid);if(!r||r.fp!==n.computerFp)throw new g(`unsafe-state`);if(e!==`desktop`)return t.start(n);let i=new l({stateDir:n.stateDir,uid:t.uid}).inspect();if(!t.ownerInput||i?.mode!==`desktop`||!i.consented||i.transition&&(i.transition.target!==`desktop`||![`source-stopped`,`destination-started`].includes(i.transition.phase)))throw new g(`conflict`);let a=!1,o,s,c=()=>s??=(async()=>{o&&await(await o).stop()})(),u=ne(t.ownerInput,{instance:n.serviceInstance,onLost:async()=>{a=!0;try{await c(),t.onOwnerLost?.(null)}catch(e){t.onOwnerLost?.(e)}}});try{if(await u.ready,a)throw new g(`unavailable`);if(o=t.start(n),await o,a)throw await c(),new g(`unavailable`);return{stop:async()=>{await c(),u.close()}}}catch(e){throw u.close(),e}}export{X as a,Q as i,ae as n,J as o,re as r,$ as t};