shellbell 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,87 @@
1
+ import{$ as e,$t as t,A as n,At as r,Ct as i,D as a,Dt as o,En as s,F as c,Ft as l,It as u,Lt as d,Mt as f,N as p,Nt as m,Ot as h,Pt as g,Q as _,R as ee,Sn as v,Tn as te,Xt as y,Zt as ne,_t as b,a as re,at as ie,bt as ae,c as oe,f as se,gt as ce,it as x,lt as le,o as ue,r as de,rt as S,s as fe,sr as pe,st as me,tn as he,tt as ge,vr as _e,xn as C,yt as ve,z as ye}from"./service-lifecycle-Dbs2mdix.js";import{execFile as be,execFileSync as xe,spawn as Se}from"node:child_process";import{accessSync as Ce,chmodSync as we,closeSync as Te,constants as w,existsSync as T,fstatSync as Ee,fsyncSync as De,linkSync as Oe,lstatSync as E,mkdirSync as ke,openSync as Ae,readFileSync as D,readSync as je,readdirSync as Me,readlinkSync as Ne,realpathSync as O,renameSync as Pe,rmSync as Fe,statSync as k,statfsSync as Ie,symlinkSync as Le,unlinkSync as Re,watch as ze,writeFileSync as Be}from"node:fs";import{homedir as A,userInfo as Ve}from"node:os";import{basename as j,delimiter as He,dirname as M,isAbsolute as N,join as P,normalize as Ue,relative as We,resolve as Ge,sep as Ke}from"node:path";import{z as F}from"zod";import{createHash as qe,randomUUID as I}from"node:crypto";import{EventEmitter as Je}from"node:events";import{connect as Ye}from"node:net";import{StringDecoder as Xe}from"node:string_decoder";import{isDeepStrictEqual as Ze,promisify as Qe}from"node:util";import{crc32 as $e}from"node:zlib";import et from"ws";import{create as tt,fromBinary as nt,toBinary as rt}from"@bufbuild/protobuf";import{fileDesc as it,messageDesc as L}from"@bufbuild/protobuf/codegenv2";import{performance as at}from"node:perf_hooks";const ot=[[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]],st=[[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 ct(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 lt(e){return e===0||e<32||e>=127&&e<160||ct(e,ot)?0:ct(e,st)?2:1}function ut(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=lt(e);if(a!==0||n){if(n){r=Math.max(r,a),n=!1;continue}t+=r,r=a}}return t+r}function dt(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=ut(e);return a!==y(e)&&(n.n=a),n}function R(e){return Math.max(0,Math.min(255,e|0))}function ft(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:R(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:[R(e[0]),R(e[1]),R(e[2])],consumed:0}}return{consumed:0}}let r=e[t+1]?.[0];return r===5&&e[t+2]?{color:R(e[t+2]?.[0]??0),consumed:2}:r===2&&e[t+4]?{color:[R(e[t+2]?.[0]??0),R(e[t+3]?.[0]??0),R(e[t+4]?.[0]??0)],consumed:4}:{consumed:0}}function pt(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}=ft(r,e);i!==void 0&&(t===38?n.fg=i:n.bg=i),e+=a}}return n}function mt(e){return gt(e,{}).line}function ht(e){let t={};return e.map(e=>{let n=gt(e,t);return t=n.style,n.line})}function gt(e,n){let r=[],i=n,a=``,o=0,s=()=>{a&&r.push(dt(a,i)),a=``},c=0;for(;c<e.length;){let t=e[c];if(t===`\x1B`){let n=e[c+1];if(n===`[`){let n=c+2,r=``;for(;n<e.length&&n-(c+2)<32;){let t=e.charCodeAt(n);if(t>=64&&t<=126)break;r+=e[n],n++}if(n>=e.length||n-(c+2)>=32){a+=t,c++;continue}e[n]===`m`&&(s(),i=pt(i,r)),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-o%8;a+=` `.repeat(e),o+=e,c++;continue}if(n<32||n===127){c++;continue}let r=e.codePointAt(c);a+=String.fromCodePoint(r),o+=lt(r),c+=r>65535?2:1}return s(),{line:{r:he(t(r))},style:i}}function _t(e){return e.issue!==void 0&&[`needs-consent`,`automation-denied`,`iterm2-denied`,`timed-out`,`too-old`,`failed`,`limited`].includes(e.issue)}const vt={iterm2:`iTerm2`,tmux:`tmux`,herdr:`Herdr`};function yt(e,t,n={}){let r=vt[e.name]??e.name;if(e.connected&&!e.issue)return{status:`Connected. Ready for your paired phone.`};if(t===`phone`)return _t(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 bt=[`iterm2`,`tmux`,`herdr`];function xt(e){return!e.some(e=>e.connected)&&bt.every(t=>{let n=e.find(e=>e.name===t);return n!==void 0&&!n.connected&&n.issue===`not-installed`})}function St(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 Ct=`\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`,wt=/^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;function Tt(e){let t=e.toLowerCase();return t===`127.0.0.1`?{kind:`ipv4`}:t===`[::1]`?{kind:`ipv6`}:t===`localhost`||t===`0.0.0.0`||t===`[::]`?{kind:`name`,name:`localhost`}:t.endsWith(`.localhost`)?t.slice(0,-10).split(`.`).every(e=>wt.test(e))?{kind:`name`,name:t}:null:t.length===0||/[\s<>"{}|\\^`]/.test(t)?null:`public`}function Et(e){return e.kind===`ipv4`?`127.0.0.1`:e.kind===`ipv6`?`[::1]`:e.name}function Dt(e){let t=/^([a-zA-Z][a-zA-Z0-9+.-]*):\/\/([^/?#]*)(.*)$/s.exec(e.trim());if(!t)return null;let[,n,r,i]=t,a=r.lastIndexOf(`@`),o=a===-1?r:r.slice(a+1),s=/^(\[[^\]]*\])(?::(\d*))?$/.exec(o),c=/^([^:[\]]*)(?::(\d*))?$/.exec(o),l=s??c;return l?{scheme:n.toLowerCase(),userinfo:a!==-1,host:l[1]??``,port:l[2]===void 0||l[2]===``?null:l[2],rest:i}:null}function Ot(e,t){let n=t===null?80:Number(t);if(!Number.isInteger(n)||n<1||n>65535)return null;let r=t===null?Et(e):`${Et(e)}:${n}`;return{origin:`http://${r}`,authority:r,host:e,port:n}}function kt(e){let t=Dt(e);if(t?.scheme!==`http`||t.userinfo||t.rest!==``)return null;let n=Tt(t.host);return n===null||n===`public`?null:Ot(n,t.port)}function At(e){let t=Dt(e);if(!t||t.scheme!==`http`&&t.scheme!==`https`)return{kind:`refused`};let n=Tt(t.host);if(n===null)return{kind:`refused`};if(n===`public`)return{kind:`public`};if(t.userinfo)return{kind:`refused`};if(t.scheme===`https`)return{kind:`secure-local`};let r=Ot(n,t.port);if(!r)return{kind:`refused`};let i=t.rest.split(`#`)[0]??``;return{kind:`local`,origin:r,path:i.startsWith(`/`)?i:`/${i}`}}function jt(e){return e.kind===`ipv4`?[{address:`127.0.0.1`,family:4}]:e.kind===`ipv6`?[{address:`::1`,family:6}]:[{address:`127.0.0.1`,family:4},{address:`::1`,family:6}]}function Mt(e,t,n){if(e.port!==n.port)return!1;let r=e.host,i=n.host;return r.kind===`name`&&r.name!==`localhost`?i.kind===`name`&&i.name===r.name:i.kind===`name`?i.name===`localhost`:i.kind===(t===4?`ipv4`:`ipv6`)}const Nt=new Set([`sh`,`bash`,`zsh`,`fish`,`dash`,`ksh`,`pwsh`,`powershell`,`cmd`]),Pt=new Set([`ssh`,`mosh`,`docker`,`podman`,`kubectl`,`wsl`]);function Ft(e){return j(e??``).replace(/^-/,``).replace(/\.exe$/i,``)}function It(e,t,n){let r=Ft(t),i=Nt.has(r)?r:void 0,a=r===`claude`?`Claude`:r===`codex`?`Codex`:void 0,o=Pt.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 z(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 Lt(e,t){return[...[`Desktop`,`Documents`,`Downloads`].map(e=>P(t,e)),P(t,`Library`,`Mobile Documents`),P(t,`Library`,`CloudStorage`),`/Volumes`].some(t=>{let n=We(t,e);return n===``||!n.startsWith(`..${Ke}`)&&n!==`..`&&!N(n)})}function Rt(e={}){let t=e.now??Date.now,n=e.platform??process.platform,r=e.home??A(),i=new Map,a=0,o=new Set;async function s(e){if(e.aborted||o.size>=32)throw Error(`git context unavailable`);if(a>=2?await new Promise((t,n)=>{let r=()=>{o.delete(i),n(Error(`git context unavailable`))},i=()=>{o.delete(i),e.removeEventListener(`abort`,r),a+=1,t()};o.add(i),e.addEventListener(`abort`,r,{once:!0})}):a+=1,e.aborted)throw--a,o.values().next().value?.(),Error(`git context unavailable`);return()=>{--a,o.values().next().value?.()}}let c={NODE_ENV:`production`,PATH:process.env.PATH,SystemRoot:process.env.SystemRoot,GIT_CONFIG_NOSYSTEM:`1`,GIT_CONFIG_GLOBAL:process.platform===`win32`?`NUL`:`/dev/null`,GIT_CONFIG_COUNT:`0`,GIT_TERMINAL_PROMPT:`0`,GIT_OPTIONAL_LOCKS:`0`,GIT_NO_REPLACE_OBJECTS:`1`},l=(e,t,n)=>new Promise((r,i)=>{be(`git`,[`-c`,`core.fsmonitor=false`,`-C`,e,...t],{env:c,encoding:`utf8`,signal:n,timeout:250,killSignal:`SIGKILL`,maxBuffer:8192,windowsHide:!0},(e,t)=>e?i(e):r(t.trim()))});return async(e,a)=>{if(!N(e)||e.length>1024||a.aborted||n===`darwin`&&Lt(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=z(j(t),256);if(!r)return;let a={repository:r,branch:z(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 zt(e,t){let n=t.now(),r=new AbortController,i,a=new Promise(e=>{i=setTimeout(()=>{r.abort(),e(void 0)},250)}),o=async()=>{if(!await Promise.race([Promise.resolve().then(()=>t.stillCurrent(e)),a]))throw Error(`stale notification context`)};try{await o();let i;e.locality===`local`&&e.cwd&&N(e.cwd)&&(i=await Promise.race([Promise.resolve().then(()=>t.git(e.cwd,r.signal)).catch(()=>void 0),a]));let s=t.stillCurrent(e);if(typeof s==`boolean`?!s:!await Promise.race([s,a]))throw Error(`stale notification context`);let c={computerName:z(t.computerName,128)??`Computer`,sessionLabel:z(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=z(e[t],n);r&&(c[t]=r)}let l=z(i?.repository,256),u=z(i?.branch,256);if(l&&(c.repository=l),l&&u&&(c.branch=u),!l&&e.locality===`local`&&e.cwd&&N(e.cwd)){let t=z(e.cwd===A()?`~`:j(e.cwd),256);t&&(c.title=t)}return c}finally{clearTimeout(i),r.abort()}}const Bt=e=>F.string().min(1).max(e).refine(e=>!/\p{Cc}/u.test(e)),Vt=Bt(4096).refine(N),Ht=F.object({shellbell:F.literal(1),name:Bt(40),description:Bt(120).optional(),start:F.array(Bt(4096)).min(1).max(64).optional(),cwd:Vt.optional(),startHelp:Bt(120).optional(),url:Bt(8192).optional(),icon:F.unknown().optional()}).refine(e=>e.start!==void 0!=(e.url!==void 0),`Choose start or url`).refine(e=>!e.cwd||e.start!==void 0,`cwd requires start`).refine(e=>!e.start||N(e.start[0]),`The program must have an absolute path`);function Ut(e){try{let t=new URL(e),n=At(e);return n.kind!==`local`||t.username||t.password?null:{origin:n.origin,path:t.pathname+t.search,url:n.origin.origin+t.pathname+t.search}}catch{return null}}function Wt(e){let t=E(e,{bigint:!0});return`${O(e)}:${t.dev}:${t.ino}:${t.ctimeNs}:${t.mtimeNs}:${t.mode}:${t.uid}:${t.gid}:${t.size}`}var Gt=class extends Map{stamps=new Map;observe(e){this.stamps.set(e,Wt(e))}},B=class extends Error{reason;fix;constructor(e,t){super(e),this.reason=e,this.fix=t}};const Kt=new Set([`write`,`append`,`delete`,`delete_child`,`add_file`,`add_subdirectory`,`writeattr`,`writeextattr`,`writesecurity`,`chown`]);function qt(e,t,n){for(let r of e.split(`
2
+ `)){if(!/^\s*\d+:/.test(r)||!/\ballow\b/.test(r))continue;let e=/^\s*\d+:\s+(user|group):(.+?)\s+(?:inherited\s+)?allow\s+(.+)$/.exec(r);if(!e||e[3].split(/[,\s]+/).some(e=>Kt.has(e))&&(e[1]!==`user`||![String(t),n].includes(e[2])))return!0}return!1}function Jt(e){let t=Buffer.from(e.buffer,e.byteOffset,e.byteLength);if(t.length<57||t.length>C.iconBytes||!t.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10])))return!1;let n=8,r=!1,i=!0;for(;n+12<=t.length;){let e=t.readUInt32BE(n),a=n+12+e;if(a>t.length)return!1;let o=t.toString(`ascii`,n+4,n+8);if(!/^[A-Za-z]{4}$/.test(o)||$e(t.subarray(n+4,a-4))!==t.readUInt32BE(a-4))return!1;if(i){if(o!==`IHDR`||e!==13)return!1;let r=t.readUInt32BE(n+8),a=t.readUInt32BE(n+12);if(!r||r!==a||r>C.iconDimension||t[n+18]!==0||t[n+19]!==0||t[n+20]>1)return!1;i=!1}else if(o===`IHDR`)return!1;if(o===`IDAT`&&(r=!0),o===`IEND`)return e===0&&r&&a===t.length;n=a}return!1}var Yt=class extends Error{},Xt=class{options;directory;uid;username;platform;acl;records=new Map;rows=[];problems=[];watcher;watched;poll;debounce;refreshing;validation=new Map;trustedACLs=new Map;closed=!1;constructor(e){this.options=e,this.directory=P(e.home,`.config/shellbell/apps`),this.uid=e.uid??process.getuid(),this.username=e.username??Ve().username,this.platform=e.platform??process.platform,this.acl=e.acl??(async e=>{let t=await ee(`/bin/ls`,[`-ldne`,e],{timeoutMs:3e3,maxOutputBytes:65536,captureOutput:!0});if(t.exitCode!==0)throw new B(`File permissions could not be checked.`);return t.stdout.toString(`utf8`)})}get entries(){return this.rows}get issues(){return this.problems}get(e){return this.records.get(e)}async trustedFile(e,t){if(!N(e)||t<1||t>C.iconBytes)throw new B(`Invalid plugin file path or size.`);return this.read(e,t,new Gt)}async registrationFile(e){v.parse(e);try{let t=await this.prepare(new Gt);return await this.trustedFile(P(t,`${e}.json`),16384)}catch(e){if(e instanceof Yt||e.code===`ENOENT`)return;throw e}}async putFile(e,t,n){if(this.closed||this.options.create===!1)throw new B(`This inspector is read-only or closed.`);let r=/^[a-z0-9-]{1,32}\.json$/.test(e),i=/^plugin-[a-z0-9-]{1,32}-[a-f0-9]{64}\.png$/.test(e);if(!r&&!i||t.byteLength>(r?16384:C.iconBytes))throw new B(`Invalid plugin file name or size.`);let a=await this.prepare(new Gt),o=P(a,e);if(this.closed)throw new B(`Plugin action cancelled.`);if(!n){if(r&&Me(a).filter(e=>e.endsWith(`.json`)).length>=C.pages)throw new B(`The page limit is reached. Remove a page before installing another plugin.`);if(!le(o,t))throw new B(`The plugin file changed. Try again.`);return}if(!(await this.trustedFile(o,r?16384:C.iconBytes)).equals(n))throw new B(`The plugin file changed. Try again.`);let s=E(o);ve(o,t,()=>{if(this.closed)throw new B(`Plugin action cancelled.`);let e=E(o);if(s.dev!==e.dev||s.ino!==e.ino||s.ctimeMs!==e.ctimeMs)throw new B(`The plugin file changed. Try again.`)})}async removeRegistration(e,t){if(this.closed||this.options.create===!1)throw new B(`This inspector is read-only or closed.`);v.parse(e);let n=await this.prepare(new Gt),r=P(n,`${e}.json`);if(!(await this.trustedFile(r,16384)).equals(t))throw new B(`The plugin file changed. Try again.`);if(this.closed)throw new B(`Plugin action cancelled.`);Re(r)}async start(){await this.refresh(),!this.closed&&!this.poll&&(this.poll=setInterval(()=>void this.refresh(),5e3),this.poll.unref())}close(){this.closed=!0,this.watcher?.close(),this.poll&&clearInterval(this.poll),this.debounce&&clearTimeout(this.debounce)}async refresh(){if(!this.closed)return this.refreshing||=this.scan().finally(()=>{this.refreshing=void 0}),this.refreshing}async refreshIfChanged(){if(this.refreshing)return this.refreshing;let e=this.validation.size===0;try{for(let[t,n]of this.validation)if(Wt(t)!==n){e=!0;break}}catch{e=!0}e&&await this.refresh()}label(e){let t=O(this.options.home);return e===t?`~`:e.startsWith(t+`/`)?`~`+e.slice(t.length):e}async foreignACL(e){if(this.platform!==`darwin`)return!1;let t=Wt(e);if(this.trustedACLs.get(e)===t)return!1;let n=qt(await this.acl(e),this.uid,this.username);if(Wt(e)!==t)throw new B(`Permissions changed while they were checked.`);return n||(this.trustedACLs.size>=512&&this.trustedACLs.clear(),this.trustedACLs.set(e,t)),n}async trust(e,t=new Gt){t.observe(e);let n=O(e),r=O(this.options.home),i=n;for(;;){let e=i,n=t.get(e);if(n||(n=(async()=>{t.observe(e);let n=E(e),i=We(r,e)===``||!We(r,e).startsWith(`..`)&&!N(We(r,e)),a=this.label(e);if(!n.isDirectory()||n.isSymbolicLink()||n.uid!==this.uid&&(i||n.uid!==0))throw new B(`An application folder has an unexpected owner.`);if(n.mode&18){let t=n.mode&2?`go-w`:`g-w`,r;try{r=O(P(this.options.home,`.config`))}catch{}let i=e===r?`~/.config`:`'`+e.replaceAll(`'`,`'\\''`)+`'`;throw new B(`${a} can be changed by other users.`.slice(0,120),`chmod ${t} ${i}`.slice(0,120))}if(await this.foreignACL(e))throw new B(`${a} grants write access to another user.`.slice(0,120),`Remove its write, append or delete allow ACL entries.`)})(),t.set(e,n)),await n,i===r||i===M(i))break;i=M(i)}}async prepare(e){let t=P(this.options.home,`.config`);if(this.options.create===!1){for(let n of[t,P(t,`shellbell`),this.directory]){try{E(n)}catch(e){throw e.code===`ENOENT`?new Yt:e}await this.trust(n,e)}return O(this.directory)}try{E(t)}catch(e){if(e.code!==`ENOENT`)throw e;ke(t,{mode:448})}await this.trust(t,e);for(let n of[P(t,`shellbell`),this.directory]){try{E(n)}catch(e){if(e.code!==`ENOENT`)throw e;ke(n,{mode:448})}let t=O(n),r=E(t);if(!r.isDirectory()||r.uid!==this.uid)throw new B(`The applications folder must belong to you.`);(r.mode&4095)!=448&&we(t,448),await this.trust(n,e)}return O(this.directory)}async read(e,t,n){await this.trust(M(e),n);let r=e=>{if(!e.isFile()||e.isSymbolicLink()||e.uid!==this.uid||e.mode&18)throw new B(`The file must belong to you and not be writable by other users.`);if(e.size>t)throw new B(`The file is too large.`)},i=E(e);if(r(i),await this.foreignACL(e))throw new B(`The file grants write access to another user.`);let a=Ae(e,w.O_RDONLY|w.O_NOFOLLOW|w.O_NONBLOCK);try{let o=Ee(a);if(r(o),o.dev!==i.dev||o.ino!==i.ino)throw new B(`The file changed while it was read.`);let s=Buffer.alloc(t+1),c=0;for(;c<s.length;){let e=je(a,s,c,s.length-c,null);if(!e)break;c+=e}let l=Ee(a);r(l);let u=E(e);if(r(u),c>t||l.dev!==u.dev||l.ino!==u.ino||l.size!==c||l.mtimeMs!==o.mtimeMs)throw new B(`The file changed while it was read.`);return n.observe(e),s.subarray(0,c)}finally{Te(a)}}async scan(){let e=new Map,t=[],n=[],r=new Gt;try{let i=await this.prepare(r);if(this.closed)return;if(this.watched!==i){this.watcher?.close(),this.watched=i;try{this.watcher=ze(i,()=>{this.trustedACLs.clear(),this.validation.clear(),this.debounce&&clearTimeout(this.debounce),this.debounce=setTimeout(()=>void this.refresh(),60),this.debounce.unref()}),this.watcher.on(`error`,()=>{this.watcher?.close(),this.watcher=void 0,this.watched=void 0})}catch{this.watched=void 0}}let a=Me(i).filter(e=>e.endsWith(`.json`)).sort();a.length>C.pages&&n.push(`Only the first ${C.pages} registration files are listed.`);for(let o of a.slice(0,C.pages)){let a=o.slice(0,-5),s=v.safeParse(a),c=s.success?s.data:`invalid-${qe(`sha256`).update(o).digest(`hex`).slice(0,24)}`,l={id:c,name:a.replace(/\p{Cc}/gu,`?`).slice(0,40)||`Invalid registration`};try{if(!s.success)throw new B(`Use a file name of 1–32 lowercase letters, digits or hyphens.`);let t=await this.read(P(i,o),16384,r),a=Ht.safeParse(JSON.parse(t.toString(`utf8`)));if(!a.success)throw new B(`The registration needs version 1, a name and either start or url.`);let u=a.data;l={id:c,name:u.name,...u.description&&{description:u.description}};let d;if(u.url){if(d=Ut(u.url)??void 0,!d)throw new B(`Only HTTP addresses on this computer's loopback are supported.`);l.address=d.origin.authority}if(u.start){try{Ce(u.start[0],w.F_OK)}catch(e){if(e.code===`ENOENT`){n.push(`${u.name}: the registered program is no longer installed.`);continue}throw e}try{Ce(u.start[0],w.X_OK)}catch{throw new B(`The registered program cannot be executed.`)}}u.cwd&&await this.trust(u.cwd,r);let f={id:c,name:u.name,...u.description&&{description:u.description},...u.start&&{start:u.start},...u.startHelp&&{startHelp:u.startHelp},...u.cwd&&{cwd:O(u.cwd)},...d&&{url:d},revision:qe(`sha256`).update(JSON.stringify({...u,icon:void 0})).digest(`hex`)};if(u.icon!==void 0)try{if(!Vt.safeParse(u.icon).success)throw new B(`The icon needs an absolute PNG path.`);let e=await this.read(u.icon,C.iconBytes,r);if(!Jt(e))throw new B(`Use a square PNG, at most 64 KB and 1024 pixels wide.`);f.icon={hash:qe(`sha256`).update(e).digest(`hex`),bytes:e},l.icon=f.icon.hash}catch(e){l.iconIssue=this.issue(e,`The page icon could not be read.`)}e.set(c,f)}catch(e){l.skipped=this.issue(e,`The registration could not be read.`)}t.push(l)}}catch(e){if(!(e instanceof Yt)){let r=this.issue(e,`The applications folder could not be read.`);t.push({id:`shellbell-pages`,name:`Pages`,skipped:r}),n.push(r.reason)}}if(this.closed)return;t.sort((e,t)=>e.name.localeCompare(t.name)||e.id.localeCompare(t.id));let i=JSON.stringify(t)!==JSON.stringify(this.rows)||JSON.stringify(n)!==JSON.stringify(this.problems)||[...e].some(([e,t])=>this.records.get(e)?.revision!==t.revision)||e.size!==this.records.size;this.validation=r.stamps,this.records=e,this.rows=t,this.problems=n,i&&this.options.changed?.()}issue(e,t){return e instanceof B?{reason:e.reason,...e.fix&&{fix:e.fix}}:{reason:t}}};function Zt(e,t){return e===t||!!e&&!!t&&e.agent===t.agent&&e.kind===t.kind&&e.value===t.value}const Qt={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`]},$t=new Map(Object.entries(Qt).flatMap(([e,t])=>t.map(t=>[t,e])));function en(e){let t=(e??``).trim().toLowerCase().split(/[\\/]/).pop().replace(/\.(cmd|exe)$/,``);if(t)return/^muse-bin-\d/.test(t)?`muse`:$t.get(t)}const tn=`\\u2800-\\u28FF\\u25D0-\\u25D3\\u2722\\u2733\\u2736\\u273B\\u273D\\u00B7\\u2022*`,nn=RegExp(`^[${tn}][${tn}\\uFE0F]*\\s+(?=\\S)`,`u`),rn=/^[⠀-⣿]/u,an=/^v?\d+(?:\.\d+)+$/;function on(e){return e.trim().replace(nn,``)}function sn(e){let t=e?.trim()??``;return nn.test(t)}function cn(e){let t=e?.trim().toLowerCase()??``;return en(t)??z(t,32)}const ln=/^\s*(?:Gemini CLI \(.*\)|[\u25C7\u270B\u23F2\u2726] {2}\S.*\(.*\))\s*$/u;function un(e,t){let n=Ft(e).toLowerCase(),r=en(n);if(r)return r;if(n!==``&&n!==`node`&&!an.test(n))return;if(ln.test(t??``))return`gemini`;if(!sn(t))return;let i=t?.trim()??``;return rn.test(i)&&/ \| [^|]+$/.test(i)?`codex`:`claude`}function dn(e,t=A()){if(!e)return;let n=e=>e.replace(/[\\/]+$/,``);return t&&n(e)===n(t)?`~`:z(n(e).split(/[\\/]/).pop(),128)}const fn=new Set([...Nt,...Qt.claude,...Qt.codex,...Qt.agy,`node`,`tmux`,`[tmux]`]);function pn(e,t){let n=e.trim();if(n&&n!==t&&!n.endsWith(`[dead]`)&&!(fn.has(n.toLowerCase())||an.test(n)))return z(n,128)}function mn(e){let t=Ft(e).toLowerCase();return!t||Pt.has(t)?!1:Nt.has(t)||en(t)!==void 0||t===`node`||an.test(t)}function hn(e,t,n){if(!e)return;let r=on(e.replace(/[\r\n\t]+/g,` `));if(t===`gemini`&&ln.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=z(r,256);if(!a)return;let o=a.toLowerCase();if(!(o===t.toLowerCase()||en(o))&&!(n.ignore??[]).some(e=>e.toLowerCase()===o))return a}function gn(e,t){return e.project===t.project&&e.agent?.kind===t.agent?.kind&&e.agent?.task===t.agent?.task}function _n(e,t,n){let r={};return e&&(r.project=e),t&&(r.agent=n?{kind:t,task:n}:{kind:t}),r}function vn(e){let t=dn(e.cwd),n=z(e.project,128)??t,r=un(e.processName,e.title);if(!r)return _n(n,void 0);let i=Ft(e.processName);return _n(n,r,hn(e.title,r,{project:n,folder:t,command:i||void 0,ignore:e.ignore}))}function yn(e,t){let n=dn(e.foreground_cwd??e.cwd??void 0),r=z(t,128)??n,i=cn(e.agent||e.display_agent||void 0);return i?_n(r,i,hn(e.label||e.terminal_title_stripped||e.terminal_title||void 0,i,{project:r,folder:n,ignore:e.display_agent?[e.display_agent]:[]})):_n(r,void 0)}var bn=class{git;onChange;now;known=new Map;pending=new Set;constructor(e,t,n=Date.now){this.git=e,this.onChange=t,this.now=n}get size(){return this.known.size}lookup(e){if(!N(e)||e.length>1024)return;let t=this.known.get(e),n=this.now();return(!t||n<t.at||n-t.at>=3e4)&&this.refresh(e,t?.project),t?.project??void 0}refresh(e,t){if(this.pending.has(e)||this.pending.size>=16)return;this.pending.add(e);let n=new AbortController,r;try{r=this.git(e,n.signal)}catch{r=Promise.resolve(void 0)}r.catch(()=>void 0).then(n=>{let r=z(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 xn(e,t=te){let n=e=>_e({type:`sessions`,list:e,complete:!1}).length<=t,r=({agent:e,stateSince:t,activeAt:n,...r})=>e?{...r,agent:{kind:e.kind,...e.reportsState&&{reportsState:!0}}}:r,i=[r,e=>{let{project:t,windowLabel:n,...i}=r(e);return i},e=>{let{project:t,windowLabel:n,cwd:i,title:a,...o}=r(e);return{...o,title:Array.from(a).slice(0,Sn).join(``)}}];if(n(e))return{type:`sessions`,list:e,complete:!0};let a=e;for(let t of i)if(a=e.map(t),n(a))return{type:`sessions`,list:a,complete:!0};let o=0,s=a.length;for(;o<s;){let e=Math.ceil((o+s)/2);n(a.slice(0,e))?o=e:s=e-1}return{type:`sessions`,list:a.slice(0,o),complete:!1}}const Sn=64,Cn=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,wn=/^\d{1,12}-\d{1,10}\.rec$/;function Tn(e=ce().dir,t=process.platform){return t===`linux`?`${e}-agents`:e}function En(e,t){return P(e,`${t}-sessions`)}function Dn(e,t=ce().dir){return En(Tn(t),e)}const On=e=>new Map(e.map(e=>[e.slice(0,e.indexOf(`=`)),e.slice(e.indexOf(`=`)+1)]));function kn(e){return!e.startsWith(`/`)||e.length>4096||/[\u0000-\u001f\u007f]/.test(e)||e.split(`/`).some(e=>e===`.`||e===`..`)||e.includes(`//`)?``:e}function An(e,t){let n=t.startsWith(`shellbell-codex-hook 1
3
+ `),r=n?t.indexOf(`
4
+
5
+ `):t.length;if(r<0)return null;let[i,...a]=t.slice(0,r).replace(/\n+$/,``).split(`
6
+ `);if(i!==`shellbell-codex-hook 1`&&i!==`shellbell-agent-hook 2`)return null;let o=On(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`||!Cn.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:kn(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 jn(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 Mn(e){try{return xe(`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 Nn(e){try{return process.kill(e,0),!0}catch(e){return e.code===`EPERM`}}var Pn=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=Mn,r=Nn){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=k(this.dir);if(!t.isDirectory()||process.getuid&&t.uid!==process.getuid())return[];e=Me(this.dir).filter(e=>wn.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=P(this.dir,i);try{let a=k(e);if(!a.isFile()||a.size>81920||process.getuid&&a.uid!==process.getuid())continue;let o=An(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))){Re(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=>jn(n,e)&&(!t||n.process.pid===t.pid&&n.process.start===t.start));return r&&(t||this.running(r))?r:null}};const Fn=new Map;let In;function Ln(e){e!==In&&(In=e,Fn.clear())}function Rn(e){let t=Fn.get(e)??new Pn(Dn(e,In));return Fn.set(e,t),t}const zn={codex:`case "$(ps -o comm= -p "$pid" 2>/dev/null)" in
7
+ codex | */codex) agent=$pid; break ;;
8
+ esac`,gemini:`case "$(ps -o args= -p "$pid" 2>/dev/null)" in
9
+ gemini | "gemini "* | */gemini | */gemini\\ * | */gemini.js | */gemini.js\\ *) agent=$pid; break ;;
10
+ esac`};function Bn(e,t){return`#!/bin/sh
11
+ # Installed by Shellbell. Records which terminal pane runs which ${e} session, so your phone
12
+ # can show its full history. Remove it with: shellbell agents remove ${e}
13
+ umask 077
14
+ dir=${`'${t.replaceAll(`'`,`'\\''`)}'`}
15
+ clean() { printf '%s' "$1" | tr -cd 'A-Za-z0-9_.:/%,@=+-' | cut -c1-512; }
16
+ # Only these two values are read from the input; the input itself is never saved.
17
+ input=$(head -c 65536 | tr '\\n' ' ')
18
+ session=$(printf '%s' "$input" | sed -n 's/.*"session_id"[[:space:]]*:[[:space:]]*"\\([0-9A-Fa-f-]\\{36\\}\\)".*/\\1/p')
19
+ transcript=$(printf '%s' "$input" | sed -n 's/.*"transcript_path"[[:space:]]*:[[:space:]]*"\\([^"\\\\]*\\)".*/\\1/p')
20
+ input=
21
+ [ -n "$session" ] || exit 0
22
+ case "$transcript" in /*) ;; *) transcript= ;; esac
23
+ printf '%s' "$transcript" | LC_ALL=C grep -q '[^A-Za-z0-9 _./@+,%=-]' && transcript=
24
+ now=$(date +%s)
25
+ tmp="$dir/.$now-$$.tmp"
26
+ # The agent process that ran this hook and the terminal it runs in. A record counts only while
27
+ # that process runs, and only for an agent with its own terminal: a shared background agent has
28
+ # none, and the pane markers it inherited may name another pane, so it records nothing.
29
+ pid=$PPID
30
+ agent=
31
+ i=0
32
+ while [ "$i" -lt 8 ] && [ "$pid" -gt 1 ] 2>/dev/null; do
33
+ ${zn[e]}
34
+ pid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ')
35
+ i=$((i + 1))
36
+ done
37
+ [ -n "$agent" ] || exit 0
38
+ tty=$(ps -o tty= -p "$agent" 2>/dev/null | tr -d ' ')
39
+ case "$tty" in '' | '?' | '??') exit 0 ;; esac
40
+ mkdir -p "$dir" 2>/dev/null || exit 0
41
+ {
42
+ echo 'shellbell-agent-hook 2'
43
+ echo "agent=${e}"
44
+ echo "time=$now"
45
+ echo "pid=$agent"
46
+ echo "start=$(TZ=UTC LC_ALL=C ps -o lstart= -p "$agent" 2>/dev/null | tr -s ' ' | sed 's/^ //;s/ $//')"
47
+ echo "tty=$(clean "$tty")"
48
+ echo "tmux=$(clean "\${TMUX:-}")"
49
+ echo "tmux_pane=$(clean "\${TMUX_PANE:-}")"
50
+ echo "iterm=$(clean "\${ITERM_SESSION_ID:-}")"
51
+ echo "herdr_pane=$(clean "\${HERDR_PANE_ID:-}")"
52
+ echo "session=$session"
53
+ echo "transcript=$transcript"
54
+ } >"$tmp" 2>/dev/null && mv -f "$tmp" "$dir/$now-$$.rec" 2>/dev/null
55
+ rm -f "$tmp" 2>/dev/null
56
+ exit 0
57
+ `}function Vn(e,t=A(),n=Tn(e)){return{codexHome:process.env.CODEX_HOME||P(t,`.codex`),stateDir:e,helperDir:n}}const Hn=e=>P(e.helperDir,`codex-session-hook.sh`),Un=e=>P(e.codexHome,`hooks.json`),Wn=e=>P(e.codexHome,`config.toml`),Gn=e=>`sh '${Hn(e).replaceAll(`'`,`'\\''`)}'`;function Kn(e){if(!T(Un(e)))return{};let t=JSON.parse(D(Un(e),`utf8`));if(typeof t!=`object`||!t||Array.isArray(t))throw Error(`${Un(e)} isn't a JSON object; Shellbell left it unchanged.`);return t}function qn(e,t,n=384){ke(M(e),{recursive:!0});let r=T(e)?O(e):e,i=T(r)?k(r).mode&511:n,a=`${r}.shellbell-${process.pid}.tmp`;try{Be(a,t,{mode:i}),Pe(a,r)}finally{Fe(a,{force:!0})}}const Jn=e=>t=>t.hooks?.some(t=>t.command===Gn(e))===!0;function Yn(e){let t=/^\[\s*(["']?)([^\]"']+)\1\s*\]\s*(?:#.*)?$/.exec(e.trim());return t?t[2].trim():null}function Xn(e){if(!T(Wn(e)))return`unset`;let t=``;for(let n of D(Wn(e),`utf8`).split(`
58
+ `)){let e=n.trim(),r=Yn(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 Zn(e){return{installed:(Kn(e).hooks?.SessionStart??[]).some(Jn(e))&&T(Hn(e)),hooksFeature:Xn(e)}}function Qn(e){let t=Xn(e);if(t===`off`)throw Error(`Codex hooks are turned off in ${Wn(e)} (hooks = false). Turn them on, then run this again.`);if(t===`unknown`)throw Error(`${Wn(e)} sets features in a form Shellbell won't edit. Add hooks = true to Codex's features, then run this again.`);let n=Kn(e);qn(Hn(e),Bn(`codex`,En(e.helperDir,`codex`)),448),we(Hn(e),448);let r=n.hooks?.SessionStart??[];if(!r.some(Jn(e))){let t={...n,hooks:{...n.hooks,SessionStart:[...r,{hooks:[{type:`command`,command:Gn(e),timeout:10}]}]}};qn(Un(e),`${JSON.stringify(t,null,2)}\n`)}if(t===`unset`){let t=T(Wn(e))?D(Wn(e),`utf8`):``,n=t.split(`
59
+ `),r=n.findIndex(e=>Yn(e)===`features`);r>=0?n.splice(r+1,0,`hooks = true`):n.push(...t&&!t.endsWith(`
60
+ `)?[``]:[],`[features]`,`hooks = true`,``),qn(Wn(e),n.join(`
61
+ `))}return Zn(e)}function $n(e){let t=Kn(e),n=t.hooks?.SessionStart;if(n?.some(Jn(e))){let r=n.filter(t=>!Jn(e)(t)),i={...t.hooks};r.length?i.SessionStart=r:delete i.SessionStart,qn(Un(e),`${JSON.stringify({...t,hooks:i},null,2)}\n`)}return Fe(Hn(e),{force:!0}),Fe(En(e.helperDir,`codex`),{recursive:!0,force:!0}),Zn(e)}const er=[`SessionStart`,`BeforeAgent`];function tr(e,t=A(),n=Tn(e)){return{settings:P(process.env.GEMINI_CLI_HOME||t,`.gemini`,`settings.json`),stateDir:e,helperDir:n}}const nr=e=>P(e.helperDir,`gemini-session-hook.sh`),rr=e=>`sh '${nr(e).replaceAll(`'`,`'\\''`)}'`;function ir(e){if(!T(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 er){let t=n.hooks?.[e];if(t!==void 0&&!Array.isArray(t))return null}return n}const ar=e=>t=>t?.hooks?.some(t=>t?.name===`shellbell-session`&&t.command===rr(e))===!0;function or(e){let t=ir(e);if(!t)return{installed:!1,hooks:`unknown`};let n=er.every(n=>(t.hooks?.[n]??[]).some(ar(e)))&&T(nr(e)),r=t.hooksConfig?.disabled;return{installed:n,hooks:t.hooksConfig?.enabled===!1||Array.isArray(r)&&r.includes(`shellbell-session`)?`off`:`on`}}function sr(e){let t=T(e.settings)?D(e.settings,`utf8`):null,n=ir(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(or(e).hooks===`off`)throw Error(`Gemini hooks are turned off in ${e.settings}; Shellbell leaves them off.`);qn(nr(e),Bn(`gemini`,En(e.helperDir,`gemini`)),448),we(nr(e),448);let r={...n.hooks};for(let t of er){let n=r[t]??[];n.some(ar(e))||(r[t]=[...n,{hooks:[{type:`command`,name:`shellbell-session`,command:rr(e),timeout:5e3}]}])}if((T(e.settings)?D(e.settings,`utf8`):null)!==t)throw Error(`${e.settings} changed while Shellbell was editing it. Try again.`);return qn(e.settings,`${JSON.stringify({...n,hooks:r},null,2)}\n`),or(e)}function cr(e){let t=ir(e);if(t?.hooks&&er.some(n=>t.hooks?.[n]?.some(ar(e)))){let n={...t.hooks};for(let t of er){let r=(n[t]??[]).filter(t=>!ar(e)(t));r.length?n[t]=r:delete n[t]}let{hooks:r,...i}=t,a=Object.keys(n).length?{...i,hooks:n}:i;qn(e.settings,`${JSON.stringify(a,null,2)}\n`)}return Fe(nr(e),{force:!0}),Fe(En(e.helperDir,`gemini`),{recursive:!0,force:!0}),or(e)}function lr(e,t=A(),n=process.platform){let r=Tn(e,n);return{stateDir:e,helperDir:r,home:t,codex:Vn(e,t,r),gemini:tr(e,t,r),claudeDir:process.env.CLAUDE_CONFIG_DIR||P(t,`.claude`)}}const ur=[[`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`]],dr=e=>P(e.helperDir,`agent-setup.json`);function fr(e){try{let t=JSON.parse(D(dr(e),`utf8`))?.skipped;return new Set(Array.isArray(t)?t.filter(e=>typeof e==`string`):[])}catch{return new Set}}function pr(e){ke(e.helperDir,{recursive:!0,mode:448});try{l(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 mr(e,t){if(!t.size){Fe(dr(e),{force:!0});return}pr(e);let n=`${dr(e)}.${process.pid}.tmp`;Be(n,`${JSON.stringify({v:1,skipped:[...t].sort()})}\n`,{mode:384}),Pe(n,dr(e))}function hr(e,t){let n={kind:`codex`,name:`Codex`,skipped:t};try{let t=Zn(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 ${P(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 gr(e,t){let n={kind:`gemini`,name:`Gemini`,skipped:t},r=or(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 _r(e){let t=fr(e),n=[],r={helper:!1,skipped:!1};T(e.claudeDir)&&n.push({kind:`claude`,name:`Claude Code`,state:`ready`,...r}),T(e.codex.codexHome)&&n.push(hr(e,t.has(`codex`))),T(P(e.home,`.gemini`,`antigravity-cli`))&&n.push({kind:`agy`,name:`Antigravity`,state:`ready`,...r}),T(P(e.gemini.settings,`..`,`tmp`))&&n.push(gr(e,t.has(`gemini`)));for(let[t,i,a]of ur)T(P(e.home,a))&&n.push({kind:t,name:i,state:`coming-soon`,...r});return n}function vr(e){return e.filter(e=>e.state===`needs-setup`&&!e.skipped)}function yr(e,t){let n=e=>!t||t.includes(e);pr(e);let r=fr(e);for(let t of _r(e))n(t.kind)&&(r.delete(t.kind),t.state===`needs-setup`&&(t.kind===`codex`&&Qn(e.codex),t.kind===`gemini`&&sr(e.gemini)));return mr(e,r),_r(e)}function br(e,t){let n=fr(e);for(let e of t)n.add(e);return mr(e,n),_r(e)}function xr(e,t){return pr(e),t===`codex`&&$n(e.codex),t===`gemini`&&cr(e.gemini),br(e,[t])}function Sr(e){try{l(e.helperDir,process.getuid?.()??-1)}catch{return}for(let t of[`codex`,`gemini`]){let n=P(e.helperDir,`${t}-session-hook.sh`);try{let r=Bn(t,En(e.helperDir,t));if(T(n)&&D(n,`utf8`)!==r){let e=`${n}.${process.pid}.tmp`;Be(e,r,{mode:448}),Pe(e,n)}}catch{}}}function Cr(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 wr=Qe(be),Tr={iTerm:`iTerm2`},Er=/\/([^/]+)\.app\/Contents\/MacOS\//;function Dr(e){let t=new Map;for(let n of e.split(`
62
+ `)){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 Or(){if(process.platform===`darwin`)try{let{stdout:e}=await wr(`/bin/ps`,[`-axww`,`-o`,`pid=,ppid=,args=`],{timeout:2e3,maxBuffer:8388608});return Dr(e)}catch{return}}function kr(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=Er.exec(e.args)?.[1];if(r)return Tr[r]??r;n=e.ppid}}const Ar=[0,7,2],jr=`Install Herdr: curl -fsSL https://herdr.dev/install.sh | sh, then start it with "herdr".`,Mr=`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`]),Pr=new Set([`invalid_request`,`unsupported`,`unknown_method`,`method_not_found`]);function Fr(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 Ir(e=process.env,t=A()){let n=e.HERDR_SOCKET_PATH;if(n)return n;let r=e.XDG_CONFIG_HOME?P(e.XDG_CONFIG_HOME,`herdr`):P(t,`.config`,`herdr`),i=e.HERDR_SESSION;return i?P(r,`sessions`,i,`herdr.sock`):P(r,`herdr.sock`)}function Lr(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 Rr(e,t,n,r=1048576){let i=new Xe(`utf8`),a=``;e.on(`data`,e=>{a+=i.write(e);let o=a.indexOf(`
63
+ `);for(;o>=0;){let e=a.slice(0,o);a=a.slice(o+1),e.trim()&&t(e),o=a.indexOf(`
64
+ `)}Buffer.byteLength(a,`utf8`)>r&&(a=``,n())})}var zr=class{opts;log;nextId=1;constructor(e){this.opts=e,this.log=e.log.child({unit:`herdr`})}get socketPath(){return this.opts.socketPath??Ir()}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=Ye({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`)}),Rr(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(Lr(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=Ye({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`)}),Rr(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(Lr(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 _(t,jr)}let t=typeof e.version==`string`?e.version:``,n=Fr(t,Ar);if(n===!1)throw new _(`herdr ${t} is older than 0.7.2 (session.snapshot and scroll metrics landed there)`,Mr);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 Br=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Vr=/^[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏] /,Hr=/^\[ [!.] \] Action Required \| /;function Ur(e){let t=e.trim();if(t.startsWith(`● `))t=t.slice(2);else if(t===`●`)return null;t=t.replace(Vr,``).replace(Hr,``);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 Wr=new Intl.Segmenter(void 0,{granularity:`grapheme`});function Gr(e,t){let n=[...Wr.segment(e)].map(e=>e.segment);return n.length<=t?e:`${n.slice(0,t-3).join(``)}...`}function Kr(e,t){let n=new Set([Gr(j(e),24)]);for(let r=e;r!==M(r);r=M(r))t(P(r,`.git`))&&n.add(Gr(j(r),24));return n}function qr(e){let t=Ae(e,`r`);try{let e=[],n=0;for(;n<1048576;){let r=Buffer.alloc(65536),i=je(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{Te(t)}}function Jr(e){let t=new Date(e),n=e=>String(e).padStart(2,`0`);return P(String(t.getFullYear()),n(t.getMonth()+1),n(t.getDate()))}var Yr=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??T}find(e,t){let n=e?Ur(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(Gr(a,48)!==n.name)continue;let e=this.folder(i);if(!e)return null;if((t===void 0||e===t)&&Kr(e,this.exists).has(n.project)){if(r)return null;r=i}}return r}catch{return null}}load(){let e=P(this.home,`session_index.jsonl`),t,n;try{let r=k(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=Ae(e,`r`),i;try{let e=Buffer.alloc(t);i=e.subarray(0,je(r,e,0,t,0)).toString(`utf8`)}finally{Te(r)}let a=i.split(`
65
+ `),o=new Map;for(let e of a)if(e.trim())try{let t=JSON.parse(e);if(typeof t.id!=`string`||!Br.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=P(this.home,`sessions`);for(let r of[0,-1,1]){let i=P(n,Jr(t+r*24*60*60*1e3)),a;try{a=Me(i)}catch{continue}let o=a.find(t=>t.startsWith(`rollout-`)&&t.endsWith(`-${e}.jsonl`));if(!o)continue;let s=qr(P(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`&&N(l)?l:null}return null}};let Xr;function Zr(){return Xr??=new Yr(process.env.CODEX_HOME||P(A(),`.codex`)),Xr}function Qr(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&&N(t.value)&&Ue(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 $r(e,t,n){let r=Qr(e?.agent_session),i=e?.agent;if(r||i!==`codex`&&i!==`gemini`||typeof e?.pane_id!=`string`)return r;let a=(t??Rn(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??Zr()).find(e.terminal_title,typeof o==`string`?o:void 0);return s?Object.freeze({agent:i,kind:`id`,value:s}):null}function ei(e){if(e===``)return[];let t=e.split(`
66
+ `);return t.length>1&&t[t.length-1]===``&&t.pop(),t.map(mt)}function ti(e,t){if(e.length>t)return e.slice(e.length-t);let n=e.slice();for(;n.length<t;)n.push(ne());return n}function ni(e){return e.r.reduce((e,t)=>e+(t.n??ut(t.t)),0)}function ri(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,ni(r)),y:t}}return{x:0,y:0}}function ii(e){let t=Math.max(1,e.rows),n=Math.max(1,e.cols),r=ti(ei(e.text),t);return{cols:n,rows:t,cursor:ri(r,n),lines:r,scrollbackTotal:Math.max(0,e.scrollMax)}}function ai(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function oi(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>=0}function si(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>0}function ci(e,t,n){if(!ai(e)||e.type!==`pane_info`||!ai(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||!oi(r.revision)||!ai(r.scroll))return null;let i=r.scroll;return!oi(i.offset_from_bottom)||!oi(i.max_offset_from_bottom)||!si(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 li(e,t){if(!si(t.rows)||!si(t.cols)||t.minRows!==void 0&&(!oi(t.minRows)||t.minRows>t.rows)||typeof t.paneId!=`string`||t.paneId.length===0||t.source!==`visible`&&t.source!==`recent`||!ai(e)||e.type!==`pane_read`||!ai(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=ei(n.text);return r.length<(t.minRows??t.rows)||r.length>t.rows||r.some(e=>ni(e)>t.cols)?null:r}function ui(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=li(e,{paneId:t.paneId,source:`recent`,cols:t.cols,rows:a,minRows:Math.max(n.length,Math.min(a,r+i)-o)});if(!s||!Ze(s.slice(-n.length),n))return null;let c=r+n.length-s.length;return c>=0?{from:c,lines:s}:null}function di(e){let[t,...n]=e.trim().split(/\s+/);if(t&&j(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 fi(e,t,n=process.env){let r=new Set;for(let[i,a]of e){let o=di(a.args);if(o===void 0||Ir({XDG_CONFIG_HOME:n.XDG_CONFIG_HOME,...o?{HERDR_SESSION:o}:{}})!==t)continue;let s=kr(i,e);s&&r.add(s)}return[...r].sort((e,t)=>e.localeCompare(t)).slice(0,4)}function pi(e,t){for(let[n,r]of e){let i=r.args.trim().split(/\s+/);if(i.length===4&&j(i[0])===`herdr`&&i[1]===`terminal`&&i[2]===`attach`&&i[3]===t&&kr(n,e)!==void 0)return!0}return!1}async function mi(e){let t=await Or();return t&&fi(t,e)}const hi=gi();function gi(){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(s))/^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 _i=vi();function vi(){let e=new Map([[`\r`,`enter`],[`
67
+ `,`enter`],[` `,`tab`]]);for(let[t,n]of Object.entries(s)){let r=hi[t];r&&!e.has(n)&&e.set(n,r)}return e}function yi(e){return _i.get(e)}const bi=[`.local/bin`,`.cargo/bin`];function xi(e,t=process.env,n=e=>{try{return Ce(e,w.X_OK),k(e).isFile()}catch{return!1}}){let r=t.HOME||A(),i=N(r)?bi.map(e=>P(r,e)):[];return[...t.PATH?.split(He)??[],...i].map(t=>Ge(t,e)).find(n)}const Si=Qe(be);function Ci(e=process.env,t){return xi(`herdr`,e,t)}async function wi(e={}){let t=e.platform??process.platform,n;try{if(t===`darwin`)n=await Ei(e);else if(t===`linux`)n=Di(e);else return}catch{return}let r=[...new Set(n)],i=e.executable??Oi;return r.length===1&&N(r[0])&&i(r[0])?r[0]:void 0}function Ti(e){return e.length===2&&j(e[0])===`herdr`&&e[1]===`server`}async function Ei(e){let t=e.ps??(async e=>(await Si(`/bin/ps`,e,{timeout:2e3,maxBuffer:8388608})).stdout),n=(await t([`-x`,`-ww`,`-o`,`pid=,args=`])).split(`
68
+ `).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(`
69
+ `).map(e=>e.trim()).filter(e=>j(e)===`herdr`)}function Di(e){let t=e.procRoot??`/proc`,n=e.uid??process.getuid?.(),r=[];for(let e of Me(t))if(/^\d+$/.test(e))try{if(n!==void 0&&k(P(t,e)).uid!==n)continue;let i=D(P(t,e,`cmdline`),`latin1`).split(`\0`);if(i.at(-1)===``&&i.pop(),!Ti(i))continue;let a=Ne(P(t,e,`exe`));a.endsWith(` (deleted)`)||r.push(a)}catch{}return r}function Oi(e){try{return Ce(e,w.X_OK),k(e).isFile()}catch{return!1}}const ki=Qe(be);var Ai=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:Ge(this.executable)}get unavailableReason(){return this.executable===void 0?this.issue:void 0}async configure(e){this.close();let t=this.generation;if(!e||Fr(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??wi)():void 0;if(t!==this.generation)return;let r=this.opts.executable?[this.opts.executable]:[...new Set([n,Ci(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 ki(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 Ge(this.opts.socketPath)===Ge(Ir(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(e,t,n){let r=this.executable;if(!r||!n()||this.active.has(e)||this.active.size>=4)throw new S(`mouse control unavailable`);if(t.column>=t.cols||t.row>=t.rows)throw new S(`mouse coordinates`);let i=this.generation,a=[`terminal`,`session`,`control`,e,`--cols`,String(t.cols),`--rows`,String(t.rows)],o=this.opts.spawn?this.opts.spawn(r,a,this.env):Se(r,a,{env:this.env,stdio:[`pipe`,`pipe`,`pipe`]});await new Promise((r,a)=>{let s=!1,c=!1,l=Buffer.alloc(0),u=t=>{s||(s=!0,clearTimeout(f),this.active.delete(e),o.kill(`SIGKILL`),t?a(t):r())},d=()=>u(c?Error(`mouse delivery unknown`):new S(`mouse control unavailable`)),f=setTimeout(d,this.opts.timeoutMs??3e3);this.active.set(e,d),o.on(`error`,d),o.stdin.on(`error`,d),o.stderr.resume(),o.stdout.on(`data`,e=>{if(s||c)return;if(l=Buffer.concat([l,e]),l.length>1048576)return d();let r=l.indexOf(10);if(r<0)return;let a;try{a=JSON.parse(l.subarray(0,r).toString(`utf8`))}catch{return d()}if(a.type!==`terminal.frame`||a.width!==t.cols||a.height!==t.rows||i!==this.generation||!n())return d();c=!0,l=Buffer.alloc(0);let u={type:`terminal.mouse`,button:t.button,column:t.column,row:t.row,modifiers:t.modifiers};o.stdin.end(`${[{...u,action:`down`},{...u,action:`up`},{type:`terminal.release`}].map(e=>JSON.stringify(e)).join(`
70
+ `)}\n`)}),o.on(`close`,e=>u(e===0&&c?void 0:c?Error(`mouse delivery unknown`):new S(`mouse control unavailable`)))})}},ji=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=qe(`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 Mi(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(Mi(38,e.fg)),e.bg!==void 0&&t.push(Mi(48,e.bg)),`\x1b[${t.join(`;`)}m`}function Pi(e){let t=``;for(let n of e.r)t+=Ni(n)+n.t.replace(/[\x00-\x1f\x7f]/g,``);return`${t}\x1b[0m`}function Fi(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 Ii=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&&(!Li(e,n.pane)||!Ri(t,n.facts))&&this.invalidate()}capture(e,t,n){this.invalidate();let{facts:r,above:i,visible:a}=t;if(!this.enabled||this.closed||!Li(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)>pe.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(x(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=ui(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&&Li(this.options.pane(),e.pane)}async confirm(e){let t=await this.options.request(`pane.get`,{pane_id:e.pane.paneId}),n=ci(t,e.pane.paneId,e.pane.terminalId),r=n?{...n,source:Fi(t)}:null;return!r||!Ri(r,e.facts)?(this.evidence===e&&this.invalidate(),!1):!0}};function Li(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 Ri(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 zi=1e3;var H=class extends Error{},Bi=class extends Je{opts;log;history;generation=0;historyLines=zi;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 Ii(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 ge||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&&Pr.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=ci(t,e.paneId,e.terminalId);if(!n)throw new H;return{...n,source:Fi(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=li(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(zi,i+r.length),n=li(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||!Ui(n.slice(-r.length),r))throw new H;a=n.slice(0,-r.length)}let o=await this.facts(e);if(!Hi(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&&Vi(e.agentStatus)?this.historyLines:t.history,this.historyLines)),n=Wi(t.visible,t.facts.viewportRows),r=Gi(t.visible,e.cols),i=[...t.above.map(Pi),...n],a=e.agent&&Vi(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:Vi(e.agentStatus),revision:t.facts.revision};let o=this.history.capture(e,t,`${Ct}${i.join(`\r
71
+ `)}${r}`);this.emit(`seed`,{generation:this.generation,cols:e.cols,rows:t.facts.viewportRows,data:`\x1bc${i.join(`\r
72
+ `)}${r}`,...o?{nativeHistory:o}:{},continuation:{data:`${Ct}${n.join(`\r
73
+ `)}${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=Vi(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=Wi(i.visible,i.facts.viewportRows),s=Gi(i.visible,t.cols),c=``;if(a.length>0)c=`\x1b[H${[...a.map(Pi),...o].map(e=>`\x1b[2K${e}`).join(`\r
74
+ `)}`;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 Vi(e){return e===`idle`||e===`done`}function Hi(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 Ui(e,t){return e.length===t.length&&e.every((e,n)=>Pi(e)===Pi(t[n]))}function Wi(e,t){return Array.from({length:t},(t,n)=>Pi(e[n]??{r:[]}))}function Gi(e,t){let{x:n,y:r}=ri(e,t);return`\x1b[${r+1};${n+1}H`}const Ki=1e3,qi=1e3;function Ji(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 Yi=new Set([`working`,`blocked`,`idle`,`done`,`unknown`]);function Xi(e){return typeof e==`string`&&Yi.has(e)?e:`unknown`}const Zi={working:`running`,blocked:`blocked`,idle:`finished`,done:`finished`,unknown:`unknown`};function Qi(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 $i(e){return me(e)}function U(e){return typeof e==`string`?e:void 0}function ea(e){return e&&typeof e==`object`?e:void 0}function ta(e,t){return e.length===t.size&&e.every(e=>t.has(e))}function na(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 ra=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=I();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=[];createdTabs=new Map;hostAppTimer=null;hostAppGeneration=0;constructor(e){this.opts=e,this.client=e.client,this.mouse=e.mouse??new Ai({socketPath:this.client.socketPath}),this.log=e.log.child({backend:`herdr`}),this.screenObserver=new ji({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())&&Fr(e.version,[0,9,5])===!0,await this.mouse.configure(e.version);let t=[];try{t=ia((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 _?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??Or)().catch(()=>void 0);if(!t&&(this.opts.platform??process.platform)!==`darwin`||t&&pi(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??mi)(this.client.socketPath).catch(()=>void 0)??[];this.closed||e!==this.hostAppGeneration||(t.join(`
75
+ `)!==this.shownIn.join(`
76
+ `)&&(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 _)return e;let t=e instanceof Error?e.message:String(e);return e instanceof V&&Pr.has(e.code)?new _(`herdr does not support session.snapshot (${t})`,Mr):e instanceof V&&e.code===`malformed`?new _(`herdr answered session.snapshot with junk (${t})`,Mr):new _(t,jr)}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=$r(s.pane);if(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||!Zt(l,c.conversation))return null;let u=Xi(s.pane.agent_status);return l?Object.freeze({...l,owner:`${o}:${c.conversationOwner}`,...u!==`unknown`&&{waiting:u===`blocked`}}):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),!Zt(e.conversation,t)&&(e.conversation=t,e.conversationOwner=I(),e.conversationSeq=++this.eventSeq,this.emit({type:`conversation-changed`,sessionId:e.terminalId})))}invalidateConversations(){if(this.conversationHintRevision++,!this.conversationPending){this.conversationPending=!0,this.conversationEpoch=I();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 It({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=ii({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=li(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(!na(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(x(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(!na(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-Ki;if(t.before<=o)return{status:`unavailable`,reason:`fetch-window`};let s=Math.min(Ki,i.viewportRows+(t.reported-e));if(!Number.isSafeInteger(s)||s<1||s>Ki)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=ui(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?na(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=ci(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&&!na(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),l=Math.min(Ki,c+n+o),u=await this.call(e,`pane.read`,{pane_id:r.paneId,source:`recent`,format:`ansi`,lines:l}),d=()=>new _(`History temporarily unavailable`,`Retry history after output settles.`),f=li(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(!f)throw d();let p=ui(u,{paneId:r.paneId,cols:s,viewportRows:o,historyRows:a,requestedRows:l,visible:f});if(!p||t>0&&p.from>=t||this.closed||this.active!==i||i?.cancelled||this.panes.get(e)!==r||r.rows!==o||r.cols!==s||r.scrollMax!==a)throw d();let m=Math.max(0,a-c-p.from),h=Math.max(0,m-n),g=p.lines.slice(h,m);return{lines:g,oldestAvailable:p.from===0&&h===0?Math.max(0,t-g.length):0}}async sendText(e,t){let n=this.pane(e),r=yi(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(`
77
+ `)){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(e,t){let n=this.pane(e),r=this.active,i=()=>{let i=this.panes.get(e);return!this.closed&&this.active===r&&r?.live===!0&&i?.paneId===n.paneId&&i.cols===t.cols&&i.rows===t.rows&&(i.scrollOffset??0)===0};if(!this.mouse.available||!i())throw new S(`mouse input unavailable`);let a=ia((await this.client.request(`session.snapshot`,{}))?.snapshot),o=a.panes.find(t=>t.terminal_id===e),s=a.layouts.flatMap(e=>e.panes).find(e=>e.pane_id===n.paneId)?.rect;if(!i()||o?.pane_id!==n.paneId||o.scroll?.offset_from_bottom!==0||s?.width!==t.cols||s.height!==t.rows)throw new S(`mouse grid changed`);await this.mouse.click(e,t,i)}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(t){if(t.kind===`split`){let e=this.pane(t.sessionId),n=U((await this.client.request(`pane.split`,{target_pane_id:e.paneId,direction:t.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(t.windowId!==void 0&&!this.workspaces.has(t.windowId))throw new e(t.windowId);let n=t.windowId??this.focusedWorkspace??[...this.workspaces][0];if(!n)return this.createWorkspaceSession();let r=await this.client.request(`tab.create`,{workspace_id:n,focus:!1}),i=U(r?.root_pane?.terminal_id);if(!i)throw Error(`herdr tab.create returned no terminal_id`);let a=U(r?.tab?.tab_id);return a&&(this.createdTabs.set(i,a),this.createdTabs.size>16&&this.createdTabs.delete(this.createdTabs.keys().next().value)),this.scheduleSync(`snapshot`),i}async shownOnComputer(e){if(e.kind===`split`)this.pane(e.sessionId);else if(e.windowId!==void 0&&!this.workspaces.has(e.windowId))throw new ge(e.windowId);let t=await(this.opts.hostApps??mi)(this.client.socketPath).catch(()=>void 0);return!this.closed&&this.isConnected&&(t?.length??0)>0}async focusedWindow(){let e=this.focusedWorkspace??[...this.workspaces][0];if(e)return await this.shownOnComputer({kind:`tab`,backend:`herdr`,windowId:e})?e:void 0}async discardSession(e){let t=this.createdTabs.get(e);if(!t)throw new ge(e);this.createdTabs.delete(e),await this.client.request(`tab.close`,{tab_id:t}),this.scheduleSync(`snapshot`)}async createWorkspaceSession(){return(await this.createWorkspace()).terminalId}async createWorkspace(){let e=await this.client.request(`workspace.create`,{cwd:A(),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:$i(e)})}}openVtStream(e){return this.pane(e),new Bi({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 ge(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 ge(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:Zi[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(Ji(t),{onEvent:e=>{if(!n.cancelled){if(n.live){this.onEvent(e);return}if(n.buffer.length<qi){n.buffer.push(e);return}n.overflowed||(n.overflowed=!0,this.log.warn(`herdr bootstrap event buffer overflowed; dropping events`,{max:qi})),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=I(),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`}),!this.conversationPending&&this.active===n&&this.emit({type:`conversation-settled`})}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(ia(r?.snapshot),e),this.conversationHintRevision===n&&this.conversationPending&&!this.wantResubscribe&&(this.conversationPending=!1,t?.live&&this.emit({type:`conversation-settled`}))}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:$i(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:$i(e)}),this.onStreamEnd(`sync-failed`)}finally{this.syncBusy=!1}}}onStreamEnd(e){if(this.closed)return;this.screenObserver.stop(),this.syncTimer&&clearTimeout(this.syncTimer),this.syncTimer=null,this.wantSnapshot=!1,this.wantResubscribe=!1;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:$i(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=z(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=aa(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:$r(m),v=_&&Zt(_.conversation,ee),te=v?_.conversationOwner:I(),y=v?_.conversationSeq:++this.eventSeq,ne=Math.max(_?.conversationRevision??0,Number.isSafeInteger(m.revision)?m.revision:0);g&&!v&&f.add(h);let b=o.get(m.pane_id),re=Xi(m.agent_status),ie=g?.statusSeq??0,ae=ie>t,oe=g?.paneId===m.pane_id&&g.scrollEventSeq>t,se=g?.paneId===m.pane_id&&g.layoutEventSeq>t,ce=ae?g?.agentStatus??re:re,x=m.scroll?.viewport_rows,le=Qi(m),ue=m.foreground_cwd??m.cwd,de=r.get(m.workspace_id),S=yn(m,de);g&&(g.title!==le||g.cwd!==ue||g.windowLabel!==de||!gn(g.naming,S))&&d.add(h);let fe=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:te,conversationSeq:y,conversationRevision:ne,terminalId:h,paneId:m.pane_id,workspaceId:m.workspace_id,tabId:m.tab_id,title:le,cwd:ue,naming:S,windowLabel:de,cols:se?g.cols:b?.cols??g?.cols??80,rows:oe?g.rows:Math.max(1,x??b?.rows??g?.rows??24),windowNumber:n.get(m.workspace_id)??0,tabIndex:a.get(m.tab_id)??0,paneIndex:se?g.paneIndex:b?.order??0,focused:m.focused===!0||m.pane_id===e.focused_pane_id,agentStatus:ce,scrollMax:oe?g.scrollMax:m.scroll?.max_offset_from_bottom??g?.scrollMax??0,scrollOffset:oe?g.scrollOffset:m.scroll?.offset_from_bottom??g?.scrollOffset,scrollStale:oe?g.scrollStale:(g?.scrollStale??!1)||b!==void 0&&(x===void 0||x!==b.rows),scrollFetchedAt:oe?g.scrollFetchedAt:b!==void 0&&(x===void 0||x!==b.rows)?0:g?.scrollFetchedAt??0,scrollEventSeq:g?.scrollEventSeq??0,layoutEventSeq:g?.layoutEventSeq??0,statusSeq:ie,revision:fe}),l.set(m.pane_id,h),i.add(m.workspace_id),!ae&&g?.agentStatus!==ce&&u.push({id:h,state:ce,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`}),ta([...l.keys()],this.subscribedPaneIds)||this.scheduleSync(`resubscribe`)}onEvent(e){try{this.handleEvent(e)}catch(e){this.log.warn(`herdr event handling failed`,{error:$i(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,$r(e),e.revision),(Qi(e)!==r.title||(e?.foreground_cwd??e?.cwd)!==r.cwd||!gn(yn(e,r.windowLabel),r.naming))&&this.scheduleSync(`snapshot`);let i=ea(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=Xi(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=ea(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 aa([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:$i(e)})}}};function ia(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 aa(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 oa(e=process.env){return Ci(e)!==void 0}async function sa(e={}){let t=e.log??ie({stdout:!1}),n=e.client??new zr({log:t,socketPath:e.socketPath,requestTimeoutMs:3e3});if(!T(n.socketPath))return{name:`herdr`,ok:!0,detail:(e.herdrOnPath??oa)()?`installed but not running (optional)`:`not installed (optional)`};let r;try{r=await n.ping()}catch(e){return e instanceof _?{name:`herdr`,ok:!1,detail:e.message,fix:e.hint}:{name:`herdr`,ok:!1,detail:String(e),fix:jr}}try{ia((await n.request(`session.snapshot`,{}))?.snapshot)}catch(e){return{name:`herdr`,ok:!1,detail:e instanceof V&&Pr.has(e.code)?`herdr ${r.version??`?`} has no session.snapshot`:`session.snapshot failed: ${e instanceof Error?e.message:String(e)}`,fix:Mr}}return{name:`herdr`,ok:!0,detail:`v${r.version??`?`} protocol ${r.protocol??`?`}`}}function ca(e){let t=e.log.child({unit:`herdr-start`}),n=new ra({client:e.client??new zr({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:oa()?`not-running`:`not-installed`};let t=n.terminalAttachIssue;return t?{issue:`limited`,detail:t}:{}}),c=()=>{i||r||(r=setTimeout(()=>{r=null,l()},e.retryMs??1e4),r.unref?.())},l=async()=>{if(!(i||n.isConnected)){try{await n.connect()}catch(n){t.debug(`herdr not available`,{error:me(n)}),e.onUnavailable&&!o&&n instanceof _&&(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:me(e)})}}};return l(),{stop(){s(),i=!0,r&&clearTimeout(r),r=null,n.close(),e.registry.remove(`herdr`)}}}const la=Qe(be);var W=class extends Error{kind;constructor(e,t){super(e),this.kind=t,this.name=`ITerm2AuthError`}};const ua=12e4;async function da(e,t=ua){let n=Date.now()+t;if((await fa(`if application "iTerm2" is running then
78
+ return "yes"
79
+ else
80
+ return "no"
81
+ end if`,n)).trim()!==`yes`)throw new W(`iTerm2 is not running`,`not-running`);let r=e.replace(/[\\"]/g,``),i;try{i=await fa(`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 fa(e,t){try{let{stdout:n}=await la(`/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=it(`CgxpdGVybTIucHJvdG8SBml0ZXJtMiLcBQoXQ2xpZW50T3JpZ2luYXRlZE1lc3NhZ2USCgoCaWQYASABKAMSNgoSZ2V0X2J1ZmZlcl9yZXF1ZXN0GGQgASgLMhguaXRlcm0yLkdldEJ1ZmZlclJlcXVlc3RIABI2ChJnZXRfcHJvbXB0X3JlcXVlc3QYZSABKAsyGC5pdGVybTIuR2V0UHJvbXB0UmVxdWVzdEgAEjsKFG5vdGlmaWNhdGlvbl9yZXF1ZXN0GGcgASgLMhsuaXRlcm0yLk5vdGlmaWNhdGlvblJlcXVlc3RIABI8ChVsaXN0X3Nlc3Npb25zX3JlcXVlc3QYaiABKAsyGy5pdGVybTIuTGlzdFNlc3Npb25zUmVxdWVzdEgAEjQKEXNlbmRfdGV4dF9yZXF1ZXN0GGsgASgLMhcuaXRlcm0yLlNlbmRUZXh0UmVxdWVzdEgAEjYKEmNyZWF0ZV90YWJfcmVxdWVzdBhsIAEoCzIYLml0ZXJtMi5DcmVhdGVUYWJSZXF1ZXN0SAASNgoSc3BsaXRfcGFuZV9yZXF1ZXN0GG0gASgLMhguaXRlcm0yLlNwbGl0UGFuZVJlcXVlc3RIABI6ChRnZXRfcHJvcGVydHlfcmVxdWVzdBhwIAEoCzIaLml0ZXJtMi5HZXRQcm9wZXJ0eVJlcXVlc3RIABIzChBhY3RpdmF0ZV9yZXF1ZXN0GHIgASgLMhcuaXRlcm0yLkFjdGl2YXRlUmVxdWVzdEgAEjMKEHZhcmlhYmxlX3JlcXVlc3QYcyABKAsyFy5pdGVybTIuVmFyaWFibGVSZXF1ZXN0SAASLQoNZm9jdXNfcmVxdWVzdBh1IAEoCzIULml0ZXJtMi5Gb2N1c1JlcXVlc3RIABJBChdpbnZva2VfZnVuY3Rpb25fcmVxdWVzdBiEASABKAsyHS5pdGVybTIuSW52b2tlRnVuY3Rpb25SZXF1ZXN0SABCDAoKc3VibWVzc2FnZSK0BgoXU2VydmVyT3JpZ2luYXRlZE1lc3NhZ2USCgoCaWQYASABKAMSDwoFZXJyb3IYAiABKAlIABI4ChNnZXRfYnVmZmVyX3Jlc3BvbnNlGGQgASgLMhkuaXRlcm0yLkdldEJ1ZmZlclJlc3BvbnNlSAASOAoTZ2V0X3Byb21wdF9yZXNwb25zZRhlIAEoCzIZLml0ZXJtMi5HZXRQcm9tcHRSZXNwb25zZUgAEj0KFW5vdGlmaWNhdGlvbl9yZXNwb25zZRhnIAEoCzIcLml0ZXJtMi5Ob3RpZmljYXRpb25SZXNwb25zZUgAEj4KFmxpc3Rfc2Vzc2lvbnNfcmVzcG9uc2UYaiABKAsyHC5pdGVybTIuTGlzdFNlc3Npb25zUmVzcG9uc2VIABI2ChJzZW5kX3RleHRfcmVzcG9uc2UYayABKAsyGC5pdGVybTIuU2VuZFRleHRSZXNwb25zZUgAEjgKE2NyZWF0ZV90YWJfcmVzcG9uc2UYbCABKAsyGS5pdGVybTIuQ3JlYXRlVGFiUmVzcG9uc2VIABI4ChNzcGxpdF9wYW5lX3Jlc3BvbnNlGG0gASgLMhkuaXRlcm0yLlNwbGl0UGFuZVJlc3BvbnNlSAASPAoVZ2V0X3Byb3BlcnR5X3Jlc3BvbnNlGHAgASgLMhsuaXRlcm0yLkdldFByb3BlcnR5UmVzcG9uc2VIABI1ChFhY3RpdmF0ZV9yZXNwb25zZRhyIAEoCzIYLml0ZXJtMi5BY3RpdmF0ZVJlc3BvbnNlSAASNQoRdmFyaWFibGVfcmVzcG9uc2UYcyABKAsyGC5pdGVybTIuVmFyaWFibGVSZXNwb25zZUgAEi8KDmZvY3VzX3Jlc3BvbnNlGHUgASgLMhUuaXRlcm0yLkZvY3VzUmVzcG9uc2VIABJDChhpbnZva2VfZnVuY3Rpb25fcmVzcG9uc2UYhAEgASgLMh4uaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVzcG9uc2VIABItCgxub3RpZmljYXRpb24Y6AcgASgLMhQuaXRlcm0yLk5vdGlmaWNhdGlvbkgAQgwKCnN1Ym1lc3NhZ2UiHQoFQ29vcmQSCQoBeBgBIAEoBRIJCgF5GAIgASgDIkYKCkNvb3JkUmFuZ2USHAoFc3RhcnQYASABKAsyDS5pdGVybTIuQ29vcmQSGgoDZW5kGAIgASgLMg0uaXRlcm0yLkNvb3JkIikKBVJhbmdlEhAKCGxvY2F0aW9uGAEgASgDEg4KBmxlbmd0aBgCIAEoAyJdChJXaW5kb3dlZENvb3JkUmFuZ2USJwoLY29vcmRfcmFuZ2UYASABKAsyEi5pdGVybTIuQ29vcmRSYW5nZRIeCgdjb2x1bW5zGAIgASgLMg0uaXRlcm0yLlJhbmdlIh0KBVBvaW50EgkKAXgYASABKAUSCQoBeRgCIAEoBSIlCgRTaXplEg0KBXdpZHRoGAEgASgFEg4KBmhlaWdodBgCIAEoBSJCCgVGcmFtZRIdCgZvcmlnaW4YASABKAsyDS5pdGVybTIuUG9pbnQSGgoEc2l6ZRgCIAEoCzIMLml0ZXJtMi5TaXplInsKCUxpbmVSYW5nZRIcChRzY3JlZW5fY29udGVudHNfb25seRgBIAEoCBIWCg50cmFpbGluZ19saW5lcxgCIAEoBRI4ChR3aW5kb3dlZF9jb29yZF9yYW5nZRgDIAEoCzIaLml0ZXJtMi5XaW5kb3dlZENvb3JkUmFuZ2UiYgoQR2V0QnVmZmVyUmVxdWVzdBIPCgdzZXNzaW9uGAEgASgJEiUKCmxpbmVfcmFuZ2UYAiABKAsyES5pdGVybTIuTGluZVJhbmdlEhYKDmluY2x1ZGVfc3R5bGVzGAMgASgIIjQKCFJHQkNvbG9yEgsKA3JlZBgBIAEoDRINCgVncmVlbhgCIAEoDRIMCgRibHVlGAMgASgNIowDCglDZWxsU3R5bGUSFAoKZmdTdGFuZGFyZBgBIAEoDUgAEi0KC2ZnQWx0ZXJuYXRlGAIgASgOMhYuaXRlcm0yLkFsdGVybmF0ZUNvbG9ySAASIQoFZmdSZ2IYAyABKAsyEC5pdGVybTIuUkdCQ29sb3JIABIUCgpiZ1N0YW5kYXJkGAUgASgNSAESLQoLYmdBbHRlcm5hdGUYBiABKA4yFi5pdGVybTIuQWx0ZXJuYXRlQ29sb3JIARIhCgViZ1JnYhgHIAEoCzIQLml0ZXJtMi5SR0JDb2xvckgBEgwKBGJvbGQYCSABKAgSDQoFZmFpbnQYCiABKAgSDgoGaXRhbGljGAsgASgIEg0KBWJsaW5rGAwgASgIEhEKCXVuZGVybGluZRgNIAEoCBIVCg1zdHJpa2V0aHJvdWdoGA4gASgIEhEKCWludmlzaWJsZRgPIAEoCBIPCgdpbnZlcnNlGBAgASgIEg8KB3JlcGVhdHMYFiABKA1CCQoHZmdDb2xvckIJCgdiZ0NvbG9yIkAKEUNvZGVQb2ludHNQZXJDZWxsEhoKD251bV9jb2RlX3BvaW50cxgBIAEoBToBMRIPCgdyZXBlYXRzGAIgASgFIo0CCgxMaW5lQ29udGVudHMSDAoEdGV4dBgBIAEoCRI3ChRjb2RlX3BvaW50c19wZXJfY2VsbBgCIAMoCzIZLml0ZXJtMi5Db2RlUG9pbnRzUGVyQ2VsbBJOCgxjb250aW51YXRpb24YAyABKA4yIS5pdGVybTIuTGluZUNvbnRlbnRzLkNvbnRpbnVhdGlvbjoVQ09OVElOVUFUSU9OX0hBUkRfRU9MEiAKBXN0eWxlGAQgAygLMhEuaXRlcm0yLkNlbGxTdHlsZSJECgxDb250aW51YXRpb24SGQoVQ09OVElOVUFUSU9OX0hBUkRfRU9MEAESGQoVQ09OVElOVUFUSU9OX1NPRlRfRU9MEAIiogIKEUdldEJ1ZmZlclJlc3BvbnNlEjQKBnN0YXR1cxgBIAEoDjIgLml0ZXJtMi5HZXRCdWZmZXJSZXNwb25zZS5TdGF0dXM6Ak9LEiYKCGNvbnRlbnRzGAMgAygLMhQuaXRlcm0yLkxpbmVDb250ZW50cxIdCgZjdXJzb3IYBCABKAsyDS5pdGVybTIuQ29vcmQSOAoUd2luZG93ZWRfY29vcmRfcmFuZ2UYBiABKAsyGi5pdGVybTIuV2luZG93ZWRDb29yZFJhbmdlIlYKBlN0YXR1cxIGCgJPSxAAEhUKEVNFU1NJT05fTk9UX0ZPVU5EEAESFgoSSU5WQUxJRF9MSU5FX1JBTkdFEAISFQoRUkVRVUVTVF9NQUxGT1JNRUQQAyIVChNMaXN0U2Vzc2lvbnNSZXF1ZXN0InkKDlNlc3Npb25TdW1tYXJ5EhkKEXVuaXF1ZV9pZGVudGlmaWVyGAEgASgJEhwKBWZyYW1lGAIgASgLMg0uaXRlcm0yLkZyYW1lEh8KCWdyaWRfc2l6ZRgDIAEoCzIMLml0ZXJtMi5TaXplEg0KBXRpdGxlGAQgASgJIsEBCg1TcGxpdFRyZWVOb2RlEhAKCHZlcnRpY2FsGAEgASgIEjIKBWxpbmtzGAIgAygLMiMuaXRlcm0yLlNwbGl0VHJlZU5vZGUuU3BsaXRUcmVlTGluaxpqCg1TcGxpdFRyZWVMaW5rEikKB3Nlc3Npb24YASABKAsyFi5pdGVybTIuU2Vzc2lvblN1bW1hcnlIABIlCgRub2RlGAIgASgLMhUuaXRlcm0yLlNwbGl0VHJlZU5vZGVIAEIHCgVjaGlsZCKbAgoUTGlzdFNlc3Npb25zUmVzcG9uc2USNAoHd2luZG93cxgBIAMoCzIjLml0ZXJtMi5MaXN0U2Vzc2lvbnNSZXNwb25zZS5XaW5kb3caeQoGV2luZG93Ei4KBHRhYnMYASADKAsyIC5pdGVybTIuTGlzdFNlc3Npb25zUmVzcG9uc2UuVGFiEhEKCXdpbmRvd19pZBgCIAEoCRIcCgVmcmFtZRgDIAEoCzINLml0ZXJtMi5GcmFtZRIOCgZudW1iZXIYBCABKAUaUgoDVGFiEiMKBHJvb3QYAyABKAsyFS5pdGVybTIuU3BsaXRUcmVlTm9kZRIOCgZ0YWJfaWQYAiABKAkSFgoOdG11eF93aW5kb3dfaWQYBCABKAkiTAoPU2VuZFRleHRSZXF1ZXN0Eg8KB3Nlc3Npb24YASABKAkSDAoEdGV4dBgCIAEoCRIaChJzdXBwcmVzc19icm9hZGNhc3QYAyABKAgibAoQU2VuZFRleHRSZXNwb25zZRIvCgZzdGF0dXMYASABKA4yHy5pdGVybTIuU2VuZFRleHRSZXNwb25zZS5TdGF0dXMiJwoGU3RhdHVzEgYKAk9LEAASFQoRU0VTU0lPTl9OT1RfRk9VTkQQASJbChJHZXRQcm9wZXJ0eVJlcXVlc3QSEwoJd2luZG93X2lkGAEgASgJSAASFAoKc2Vzc2lvbl9pZBgDIAEoCUgAEgwKBG5hbWUYAiABKAlCDAoKaWRlbnRpZmllciKaAQoTR2V0UHJvcGVydHlSZXNwb25zZRIyCgZzdGF0dXMYASABKA4yIi5pdGVybTIuR2V0UHJvcGVydHlSZXNwb25zZS5TdGF0dXMSEgoKanNvbl92YWx1ZRgCIAEoCSI7CgZTdGF0dXMSBgoCT0sQABIVChFVTlJFQ09HTklaRURfTkFNRRABEhIKDklOVkFMSURfVEFSR0VUEAIiQAoUUHJvbXB0TW9uaXRvclJlcXVlc3QSKAoFbW9kZXMYASADKA4yGS5pdGVybTIuUHJvbXB0TW9uaXRvck1vZGUiYAoWVmFyaWFibGVNb25pdG9yUmVxdWVzdBIMCgRuYW1lGAEgASgJEiQKBXNjb3BlGAIgASgOMhUuaXRlcm0yLlZhcmlhYmxlU2NvcGUSEgoKaWRlbnRpZmllchgDIAEoCSL/AQoTTm90aWZpY2F0aW9uUmVxdWVzdBIPCgdzZXNzaW9uGAEgASgJEhEKCXN1YnNjcmliZRgCIAEoCBIzChFub3RpZmljYXRpb25fdHlwZRgDIAEoDjIYLml0ZXJtMi5Ob3RpZmljYXRpb25UeXBlEkIKGHZhcmlhYmxlX21vbml0b3JfcmVxdWVzdBgGIAEoCzIeLml0ZXJtMi5WYXJpYWJsZU1vbml0b3JSZXF1ZXN0SAASPgoWcHJvbXB0X21vbml0b3JfcmVxdWVzdBgJIAEoCzIcLml0ZXJtMi5Qcm9tcHRNb25pdG9yUmVxdWVzdEgAQgsKCWFyZ3VtZW50cyL1AQoUTm90aWZpY2F0aW9uUmVzcG9uc2USMwoGc3RhdHVzGAEgASgOMiMuaXRlcm0yLk5vdGlmaWNhdGlvblJlc3BvbnNlLlN0YXR1cyKnAQoGU3RhdHVzEgYKAk9LEAASFQoRU0VTU0lPTl9OT1RfRk9VTkQQARIVChFSRVFVRVNUX01BTEZPUk1FRBACEhIKDk5PVF9TVUJTQ1JJQkVEEAMSFgoSQUxSRUFEWV9TVUJTQ1JJQkVEEAQSIwofRFVQTElDQVRFX1NFUlZFUl9PUklHSU5BVEVEX1JQQxAFEhYKEklOVkFMSURfSURFTlRJRklFUhAGIisKGFNjcmVlblVwZGF0ZU5vdGlmaWNhdGlvbhIPCgdzZXNzaW9uGAEgASgJIloKGFByb21wdE5vdGlmaWNhdGlvblByb21wdBITCgtwbGFjZWhvbGRlchgBIAEoCRIpCgZwcm9tcHQYAiABKAsyGS5pdGVybTIuR2V0UHJvbXB0UmVzcG9uc2UiMQoeUHJvbXB0Tm90aWZpY2F0aW9uQ29tbWFuZFN0YXJ0Eg8KB2NvbW1hbmQYASABKAkiLgocUHJvbXB0Tm90aWZpY2F0aW9uQ29tbWFuZEVuZBIOCgZzdGF0dXMYASABKAUi+gEKElByb21wdE5vdGlmaWNhdGlvbhIPCgdzZXNzaW9uGAEgASgJEjIKBnByb21wdBgCIAEoCzIgLml0ZXJtMi5Qcm9tcHROb3RpZmljYXRpb25Qcm9tcHRIABI/Cg1jb21tYW5kX3N0YXJ0GAMgASgLMiYuaXRlcm0yLlByb21wdE5vdGlmaWNhdGlvbkNvbW1hbmRTdGFydEgAEjsKC2NvbW1hbmRfZW5kGAQgASgLMiQuaXRlcm0yLlByb21wdE5vdGlmaWNhdGlvbkNvbW1hbmRFbmRIABIYChB1bmlxdWVfcHJvbXB0X2lkGAUgASgJQgcKBWV2ZW50IiwKFk5ld1Nlc3Npb25Ob3RpZmljYXRpb24SEgoKc2Vzc2lvbl9pZBgBIAEoCSIyChxUZXJtaW5hdGVTZXNzaW9uTm90aWZpY2F0aW9uEhIKCnNlc3Npb25faWQYASABKAkiWQoZTGF5b3V0Q2hhbmdlZE5vdGlmaWNhdGlvbhI8ChZsaXN0X3Nlc3Npb25zX3Jlc3BvbnNlGAEgASgLMhwuaXRlcm0yLkxpc3RTZXNzaW9uc1Jlc3BvbnNlIoQDChhGb2N1c0NoYW5nZWROb3RpZmljYXRpb24SHAoSYXBwbGljYXRpb25fYWN0aXZlGAEgASgISAASOQoGd2luZG93GAIgASgLMicuaXRlcm0yLkZvY3VzQ2hhbmdlZE5vdGlmaWNhdGlvbi5XaW5kb3dIABIWCgxzZWxlY3RlZF90YWIYAyABKAlIABIRCgdzZXNzaW9uGAQgASgJSAAa2gEKBldpbmRvdxJLCg13aW5kb3dfc3RhdHVzGAEgASgOMjQuaXRlcm0yLkZvY3VzQ2hhbmdlZE5vdGlmaWNhdGlvbi5XaW5kb3cuV2luZG93U3RhdHVzEhEKCXdpbmRvd19pZBgCIAEoCSJwCgxXaW5kb3dTdGF0dXMSHgoaVEVSTUlOQUxfV0lORE9XX0JFQ0FNRV9LRVkQABIeChpURVJNSU5BTF9XSU5ET1dfSVNfQ1VSUkVOVBABEiAKHFRFUk1JTkFMX1dJTkRPV19SRVNJR05FRF9LRVkQAkIHCgVldmVudCJ9ChtWYXJpYWJsZUNoYW5nZWROb3RpZmljYXRpb24SJAoFc2NvcGUYASABKA4yFS5pdGVybTIuVmFyaWFibGVTY29wZRISCgppZGVudGlmaWVyGAIgASgJEgwKBG5hbWUYAyABKAkSFgoOanNvbl9uZXdfdmFsdWUYBCABKAki9wMKDE5vdGlmaWNhdGlvbhJEChpzY3JlZW5fdXBkYXRlX25vdGlmaWNhdGlvbhgCIAEoCzIgLml0ZXJtMi5TY3JlZW5VcGRhdGVOb3RpZmljYXRpb24SNwoTcHJvbXB0X25vdGlmaWNhdGlvbhgDIAEoCzIaLml0ZXJtMi5Qcm9tcHROb3RpZmljYXRpb24SQAoYbmV3X3Nlc3Npb25fbm90aWZpY2F0aW9uGAYgASgLMh4uaXRlcm0yLk5ld1Nlc3Npb25Ob3RpZmljYXRpb24STAoedGVybWluYXRlX3Nlc3Npb25fbm90aWZpY2F0aW9uGAcgASgLMiQuaXRlcm0yLlRlcm1pbmF0ZVNlc3Npb25Ob3RpZmljYXRpb24SRgobbGF5b3V0X2NoYW5nZWRfbm90aWZpY2F0aW9uGAggASgLMiEuaXRlcm0yLkxheW91dENoYW5nZWROb3RpZmljYXRpb24SRAoaZm9jdXNfY2hhbmdlZF9ub3RpZmljYXRpb24YCSABKAsyIC5pdGVybTIuRm9jdXNDaGFuZ2VkTm90aWZpY2F0aW9uEkoKHXZhcmlhYmxlX2NoYW5nZWRfbm90aWZpY2F0aW9uGAwgASgLMiMuaXRlcm0yLlZhcmlhYmxlQ2hhbmdlZE5vdGlmaWNhdGlvbiI9ChBHZXRQcm9tcHRSZXF1ZXN0Eg8KB3Nlc3Npb24YASABKAkSGAoQdW5pcXVlX3Byb21wdF9pZBgCIAEoCSLkAgoRR2V0UHJvbXB0UmVzcG9uc2USNAoGc3RhdHVzGAEgASgOMiAuaXRlcm0yLkdldFByb21wdFJlc3BvbnNlLlN0YXR1czoCT0sSGQoRd29ya2luZ19kaXJlY3RvcnkYBSABKAkSDwoHY29tbWFuZBgGIAEoCRI1Cgxwcm9tcHRfc3RhdGUYByABKA4yHy5pdGVybTIuR2V0UHJvbXB0UmVzcG9uc2UuU3RhdGUSEwoLZXhpdF9zdGF0dXMYCSABKA0SGAoQdW5pcXVlX3Byb21wdF9pZBgKIAEoCSJWCgZTdGF0dXMSBgoCT0sQABIVChFTRVNTSU9OX05PVF9GT1VORBABEhUKEVJFUVVFU1RfTUFMRk9STUVEEAISFgoSUFJPTVBUX1VOQVZBSUxBQkxFEAMiLwoFU3RhdGUSCwoHRURJVElORxAAEgsKB1JVTk5JTkcQARIMCghGSU5JU0hFRBACIjIKD1Byb2ZpbGVQcm9wZXJ0eRILCgNrZXkYASABKAkSEgoKanNvbl92YWx1ZRgCIAEoCSKeAQoQQ3JlYXRlVGFiUmVxdWVzdBIUCgxwcm9maWxlX25hbWUYASABKAkSEQoJd2luZG93X2lkGAIgASgJEhEKCXRhYl9pbmRleBgDIAEoDRI6ChljdXN0b21fcHJvZmlsZV9wcm9wZXJ0aWVzGAUgAygLMhcuaXRlcm0yLlByb2ZpbGVQcm9wZXJ0eRISCgpzZWxlY3RfdGFiGAYgASgIIvABChFDcmVhdGVUYWJSZXNwb25zZRIwCgZzdGF0dXMYASABKA4yIC5pdGVybTIuQ3JlYXRlVGFiUmVzcG9uc2UuU3RhdHVzEhEKCXdpbmRvd19pZBgCIAEoCRIOCgZ0YWJfaWQYAyABKAUSEgoKc2Vzc2lvbl9pZBgEIAEoCSJyCgZTdGF0dXMSBgoCT0sQABIYChRJTlZBTElEX1BST0ZJTEVfTkFNRRABEhUKEUlOVkFMSURfV0lORE9XX0lEEAISFQoRSU5WQUxJRF9UQUJfSU5ERVgQAxIYChRNSVNTSU5HX1NVQlNUSVRVVElPThAEIqwBChBTcGxpdFBhbmVSZXF1ZXN0Eg8KB3Nlc3Npb24YASABKAkSQAoPc3BsaXRfZGlyZWN0aW9uGAIgASgOMicuaXRlcm0yLlNwbGl0UGFuZVJlcXVlc3QuU3BsaXREaXJlY3Rpb24SFQoGYmVmb3JlGAMgASgIOgVmYWxzZSIuCg5TcGxpdERpcmVjdGlvbhIMCghWRVJUSUNBTBAAEg4KCkhPUklaT05UQUwQASLVAQoRU3BsaXRQYW5lUmVzcG9uc2USMAoGc3RhdHVzGAEgASgOMiAuaXRlcm0yLlNwbGl0UGFuZVJlc3BvbnNlLlN0YXR1cxISCgpzZXNzaW9uX2lkGAIgAygJInoKBlN0YXR1cxIGCgJPSxAAEhUKEVNFU1NJT05fTk9UX0ZPVU5EEAESGAoUSU5WQUxJRF9QUk9GSUxFX05BTUUQAhIQCgxDQU5OT1RfU1BMSVQQAxIlCiFNQUxGT1JNRURfQ1VTVE9NX1BST0ZJTEVfUFJPUEVSVFkQBCKWAgoPQWN0aXZhdGVSZXF1ZXN0EhMKCXdpbmRvd19pZBgBIAEoCUgAEhAKBnRhYl9pZBgCIAEoCUgAEhQKCnNlc3Npb25faWQYAyABKAlIABIaChJvcmRlcl93aW5kb3dfZnJvbnQYBCABKAgSEgoKc2VsZWN0X3RhYhgFIAEoCBIWCg5zZWxlY3Rfc2Vzc2lvbhgGIAEoCBIxCgxhY3RpdmF0ZV9hcHAYByABKAsyGy5pdGVybTIuQWN0aXZhdGVSZXF1ZXN0LkFwcBo9CgNBcHASGQoRcmFpc2VfYWxsX3dpbmRvd3MYASABKAgSGwoTaWdub3Jpbmdfb3RoZXJfYXBwcxgCIAEoCEIMCgppZGVudGlmaWVyIn0KEEFjdGl2YXRlUmVzcG9uc2USLwoGc3RhdHVzGAEgASgOMh8uaXRlcm0yLkFjdGl2YXRlUmVzcG9uc2UuU3RhdHVzIjgKBlN0YXR1cxIGCgJPSxAAEhIKDkJBRF9JREVOVElGSUVSEAESEgoOSU5WQUxJRF9PUFRJT04QAiKLAQoPVmFyaWFibGVSZXF1ZXN0EhQKCnNlc3Npb25faWQYASABKAlIABIoCgNzZXQYAiADKAsyGy5pdGVybTIuVmFyaWFibGVSZXF1ZXN0LlNldBILCgNnZXQYAyADKAkaIgoDU2V0EgwKBG5hbWUYASABKAkSDQoFdmFsdWUYAiABKAlCBwoFc2NvcGUi5QEKEFZhcmlhYmxlUmVzcG9uc2USLwoGc3RhdHVzGAEgASgOMh8uaXRlcm0yLlZhcmlhYmxlUmVzcG9uc2UuU3RhdHVzEg4KBnZhbHVlcxgCIAMoCSKPAQoGU3RhdHVzEgYKAk9LEAASFQoRU0VTU0lPTl9OT1RfRk9VTkQQARIQCgxJTlZBTElEX05BTUUQAhIRCg1NSVNTSU5HX1NDT1BFEAMSEQoNVEFCX05PVF9GT1VORBAEEhgKFE1VTFRJX0dFVF9ESVNBTExPV0VEEAUSFAoQV0lORE9XX05PVF9GT1VORBAGIp8BChVJbnZva2VGdW5jdGlvblJlcXVlc3QSNgoGbWV0aG9kGAcgASgLMiQuaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVxdWVzdC5NZXRob2RIABISCgppbnZvY2F0aW9uGAUgASgJEhMKB3RpbWVvdXQYBiABKAE6Ai0xGhoKBk1ldGhvZBIQCghyZWNlaXZlchgBIAEoCUIJCgdjb250ZXh0ItkCChZJbnZva2VGdW5jdGlvblJlc3BvbnNlEjUKBWVycm9yGAEgASgLMiQuaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVzcG9uc2UuRXJyb3JIABI5CgdzdWNjZXNzGAIgASgLMiYuaXRlcm0yLkludm9rZUZ1bmN0aW9uUmVzcG9uc2UuU3VjY2Vzc0gAGlQKBUVycm9yEjUKBnN0YXR1cxgBIAEoDjIlLml0ZXJtMi5JbnZva2VGdW5jdGlvblJlc3BvbnNlLlN0YXR1cxIUCgxlcnJvcl9yZWFzb24YAiABKAkaHgoHU3VjY2VzcxITCgtqc29uX3Jlc3VsdBgBIAEoCSJICgZTdGF0dXMSCwoHVElNRU9VVBABEgoKBkZBSUxFRBACEhUKEVJFUVVFU1RfTUFMRk9STUVEEAMSDgoKSU5WQUxJRF9JRBAEQg0KC2Rpc3Bvc2l0aW9uIg4KDEZvY3VzUmVxdWVzdCJICg1Gb2N1c1Jlc3BvbnNlEjcKDW5vdGlmaWNhdGlvbnMYASADKAsyIC5pdGVybTIuRm9jdXNDaGFuZ2VkTm90aWZpY2F0aW9uKkcKDkFsdGVybmF0ZUNvbG9yEgsKB0RFRkFVTFQQABIUChBSRVZFUlNFRF9ERUZBVUxUEAMSEgoOU1lTVEVNX01FU1NBR0UQBCrZAQoQTm90aWZpY2F0aW9uVHlwZRIbChdOT1RJRllfT05fU0NSRUVOX1VQREFURRACEhQKEE5PVElGWV9PTl9QUk9NUFQQAxIZChVOT1RJRllfT05fTkVXX1NFU1NJT04QBhIfChtOT1RJRllfT05fVEVSTUlOQVRFX1NFU1NJT04QBxIbChdOT1RJRllfT05fTEFZT1VUX0NIQU5HRRAIEhoKFk5PVElGWV9PTl9GT0NVU19DSEFOR0UQCRIdChlOT1RJRllfT05fVkFSSUFCTEVfQ0hBTkdFEAwqQwoRUHJvbXB0TW9uaXRvck1vZGUSCgoGUFJPTVBUEAESEQoNQ09NTUFORF9TVEFSVBACEg8KC0NPTU1BTkRfRU5EEAMqOgoNVmFyaWFibGVTY29wZRILCgdTRVNTSU9OEAESBwoDVEFCEAISCgoGV0lORE9XEAMSBwoDQVBQEAQ`),pa=L(G,0),ma=L(G,1),ha=L(G,2),ga=L(G,3),_a=L(G,5),va=L(G,9),ya=L(G,10),ba=L(G,16),xa=L(G,20);let Sa=function(e){return e[e.OK=0]=`OK`,e[e.SESSION_NOT_FOUND=1]=`SESSION_NOT_FOUND`,e}({});const Ca=L(G,22),wa=L(G,24),Ta=L(G,25),Ea=L(G,26),Da=L(G,42),Oa=L(G,44),ka=L(G,46),Aa=L(G,46,0),ja=L(G,48),Ma=L(G,52),Na=P(A(),`Library`,`Application Support`,`iTerm2`,`private`,`socket`);var Pa=class extends Je{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===et.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 Fa((this.opts.cookieProvider??(()=>da(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 et(this.opts.url,[`api.iterm2.com`],{headers:a,handshakeTimeout:o}):new et(`ws://localhost/`,[`api.iterm2.com`],{headers:a,handshakeTimeout:o,createConnection:()=>Ye({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=nt(ma,new Uint8Array(e))}catch(e){this.log.warn(`undecodable message from iTerm2`,{err:me(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:me(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!==et.OPEN)return Promise.reject(Error(`iTerm2 not connected`));let n=this.nextId++,r=tt(pa,{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(rt(pa,r),{binary:!0})})}};function Fa(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 Ia(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 La=65536,Ra=16384,za=`# shellbell-systemd-v1 `,Ba=F.string().max(Ra).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}),Va=Ba.refine(N),Ha=F.strictObject({v:F.literal(1),machineId:F.string().regex(/^[0-9a-f]{32}$/).refine(e=>e!==`0`.repeat(32)),nodePath:Va.refine(e=>!/["'\\]/.test(e)),cliPath:Va,stateDir:Va,runtimeRoot:Va,serviceInstance:F.uuid(),path:Ba.refine(e=>{let t=e.split(`:`);return t.every(N)&&new Set(t).size===t.length})});function K(){throw Error(`shellbell: invalid or foreign systemd unit`)}function Ua(e){return`"${e.replaceAll(`\\`,`\\\\`).replaceAll(`"`,`\\"`).replaceAll(`%`,`%%`)}"`}function Wa(e,t){return`Environment=${Ua(`${e}=${t}`)}`}function Ga(e){let t=Ha.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>Ra&&K();let i=JSON.stringify(n);Buffer.byteLength(i)>Ra&&K();let a=Buffer.from([za+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(Ua).join(` `)}`,Wa(`SHELLBELL_DIR`,n.stateDir),Wa(`SHELLBELL_SERVICE_INSTANCE`,n.serviceInstance),Wa(`XDG_RUNTIME_DIR`,n.runtimeRoot),Wa(`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(`
82
+ `));return a.length>La&&K(),a}function Ka(e){try{e.byteLength>La&&K();let t=Buffer.from(e),n=t.subarray(0,t.indexOf(10)).toString(`utf8`);n.startsWith(za)||K();let r=n.slice(23);(r.length>21846||!/^[A-Za-z0-9_-]+$/.test(r))&&K();let i=Buffer.from(r,`base64url`);(i.length>Ra||i.toString(`base64url`)!==r)&&K();let a=Ha.parse(JSON.parse(i.toString(`utf8`)));return Ga(a).equals(t)||K(),a}catch{return K()}}function qa(e,t){let n=g(e);n&&(!n.isDirectory()||n.isSymbolicLink()||n.uid!==t||n.mode&18)&&K()}function Ja(e,t){Va.safeParse(e).success||K();let n=g(e)?O(e):m(e);return qa(n,t),n}function Ya(e){let{uid:t,hostScope:n}=e.identity;(!Number.isSafeInteger(t)||t<=0||!/^[0-9a-f]{32}$/.test(n))&&K();let r=Ja(e.home,t),i=Ja(e.env.XDG_CONFIG_HOME&&N(e.env.XDG_CONFIG_HOME)?e.env.XDG_CONFIG_HOME:P(r,`.config`),t),a=P(i,`systemd`,`user`);for(let e of[P(i,`systemd`),a])qa(e,t);let o=`shellbell-${n}.service`,s=P(a,o),c=g(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:P(a,`default.target.wants`,o),managerRuntimeRoot:`/run/user/${t}`}}function q(){throw Error(`shellbell: unsafe, foreign or concurrently changed systemd files`)}function Xa(e,t){return u(e,t)&&e.mode===t.mode&&e.uid===t.uid&&e.size===t.size&&e.mtimeMs===t.mtimeMs&&e.ctimeMs===t.ctimeMs}var Za=class{location;machineId;constructor(e,t){this.location=e,this.machineId=t}directory(e,t=!1){let n=g(e);return!n&&t&&(this.directory(M(e),!0),ke(e,{mode:448}),n=g(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,P(this.location.configRoot,`systemd`),this.location.unitDir,M(this.location.enablementPath)],n=[];for(let r of t){let t=this.directory(r,e&&r!==M(this.location.enablementPath));t&&n.push({path:r,stat:t})}return n}inspect(){let e=this.parents(),t=g(this.location.definitionPath),n=null;if(t){let e=f(this.location.definitionPath,65536,this.location.uid),r=Ka(e);(r.machineId!==this.machineId||!Xa(t,g(this.location.definitionPath)))&&q(),n={stat:t,raw:e,definition:r}}let r=g(this.location.enablementPath),i=null;if(r){let e=r.isSymbolicLink()?Ne(this.location.enablementPath):null;Xa(r,g(this.location.enablementPath))||q(),i={stat:r,target:e,owned:r.uid===this.location.uid&&e===this.location.definitionPath}}for(let t of e){let e=this.directory(t.path);(!e||!u(t.stat,e))&&q()}return{unit:n,link:i,parents:e}}assertUnchanged(e){let t=this.inspect();for(let t of e.parents??[]){let e=this.directory(t.path);(!e||!u(t.stat,e))&&q()}(!!t.unit!=!!e.unit||!!t.link!=!!e.link)&&q(),t.unit&&e.unit&&(!Xa(t.unit.stat,e.unit.stat)||!t.unit.raw.equals(e.unit.raw))&&q(),t.link&&e.link&&(!Xa(t.link.stat,e.link.stat)||t.link.target!==e.link.target)&&q()}matchesFragment(e){try{let t=g(e);return!!t&&t.isFile()&&!t.isSymbolicLink()&&t.uid===this.location.uid&&(t.mode&4095)==384&&P(O(M(e)),j(e))===this.location.definitionPath}catch{return!1}}publish(e,t){(t.machineId!==this.machineId||e.link&&!e.link.owned)&&q();let n=Ga(t);this.assertUnchanged(e),this.parents(!0);let r=`${this.location.definitionPath}.tmp-${I()}`,i;try{let t=Ae(r,w.O_WRONLY|w.O_CREAT|w.O_EXCL|w.O_NOFOLLOW,384);try{i=g(r),Be(t,n),De(t)}finally{Te(t)}this.assertUnchanged(e),e.unit?Pe(r,this.location.definitionPath):Oe(r,this.location.definitionPath)}finally{let e=g(r);i&&e&&u(i,e)&&Re(r)}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(M(this.location.enablementPath),!0),this.assertUnchanged(e),Le(this.location.definitionPath,this.location.enablementPath)):(this.assertUnchanged(e),Re(this.location.enablementPath)),this.inspect())}remove(e){return this.assertUnchanged(e),e.link?.owned&&q(),e.unit&&Re(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&&Be(`${this.location.definitionPath}.recovery-${I()}`,e.unit.raw,{flag:`wx`,mode:384})}catch{}throw Error(`shellbell: unresolved systemd file recovery; inspect owned artifacts before retrying`)}}};const Qa=[`LoadState`,`ActiveState`,`SubState`,`MainPID`,`UnitFileState`,`FragmentPath`,`DropInPaths`,`NeedDaemonReload`,`ConditionResult`],$a=[`--user`,`--no-pager`,`--no-ask-password`],eo=new Set([16914836,61267,1481003842,2435016766]),J=()=>Error(`shellbell: systemd command failed`);function to(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 no=()=>({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 ro(e){for(let t of[`/usr/bin`,`/bin`]){let n=P(t,e);try{return Ce(n,w.X_OK),n}catch{}}throw J()}const io=(e,t,n)=>new Promise((r,i)=>{let a=Se(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 ao(e){if(e.length>65536)throw J();let t=new TextDecoder(`utf-8`,{fatal:!0}).decode(e),n=t.endsWith(`
83
+ `)?t.slice(0,-1).split(`
84
+ `):t.split(`
85
+ `),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||!Qa.includes(n)||r.has(n)||!to(i))throw J();r.set(n,i)}if(r.size!==Qa.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&&!N(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 oo(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 so(e){let t={...e.location},n=e.run??io;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(!N(e)||!to(e))throw J();l(t.managerRuntimeRoot,a);let o=e.runtimeFsType?.(t.managerRuntimeRoot)??Ie(t.managerRuntimeRoot).type;if(!eo.has(Number(o)))throw J();let s=await n(e.run?`/usr/bin/${r}`:ro(r),i,{timeoutMs:3e4,maxOutputBytes:65536,env:{HOME:t.home,XDG_CONFIG_HOME:t.configRoot,XDG_RUNTIME_DIR:t.managerRuntimeRoot,DBUS_SESSION_BUS_ADDRESS:oo(P(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 ao(await r(`systemctl`,[...$a,`show`,`--property=${Qa.join(`,`)}`,t.unitName]))}catch{return no()}},async execute(e){if(![`start`,`stop`,`daemon-reload`].includes(e))throw J();await r(`systemctl`,[...$a,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
86
+ `||e===`yes`)return`yes`;if(e===`no
87
+ `||e===`no`)return`no`}catch{}return`unknown`}}}const Y=e=>e.activeState===`inactive`||e.activeState===`failed`,co=e=>[`enabled`,`enabled-runtime`].includes(e.unitFileState);function X(e){throw Error(`shellbell: ${e}`)}var lo=class extends Error{},uo=class{options;machine;location;files;manager;readiness;clock;constructor(e){this.options=e,this.machine=r(e.machine),this.location=Ya({identity:this.machine,env:e.env,home:e.home??A()}),this.files=new Za(this.location,this.machine.machineId),this.manager=e.manager??so({location:this.location,runtimeFsType:e.runtimeFsType}),this.readiness=new ue(e),this.clock=e.clock??{now:()=>at.now(),sleep:e=>new Promise(t=>setTimeout(t,e))}}select(e,t,n=!1){let r=e.unit?.definition;r&&this.options.env.SHELLBELL_DIR!==void 0&&m(this.options.env.SHELLBELL_DIR)!==r.stateDir&&X(`SHELLBELL_DIR conflicts with installed service state; explicit migration is required`);let a;try{let e={...this.options.env,...r?{SHELLBELL_DIR:r.stateDir,...n?{}:{XDG_RUNTIME_DIR:r.runtimeRoot}}:{}};a=(this.options.selectPaths??(e=>h({...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||r&&a.dir!==r.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=i(a);return{paths:a,degraded:!1,expected:{computerFp:e.fp,stateDir:a.dir,...r?{serviceInstance:r.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){if(this.files.assertUnchanged(e),!t.available)throw new lo(`shellbell: systemd manager ownership is unavailable, foreign or unresolved; inspect exact unit discovery and overrides`);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||!fe(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=co(s)&&!e.link?.owned||e.link&&!e.link.owned;return{manager:`systemd`,unitName:this.location.unitName,definitionPath:this.location.definitionPath,installed:!!e.unit,enabled:co(s),startupEnabled:s.available?co(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 installedRuntime(){let e=this.files.inspect().unit?.definition;return e?{nodePath:e.nodePath,cliPath:e.cliPath,stateDir:e.stateDir}:null}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(),a=this.select(r,e,t),s=async()=>{let t;try{return a.paths&&(o(a.paths),t=d(P(a.paths.runtimeDir,`service`))),this.files.assertUnchanged(r),e&&i(a.paths),await n(r,a,!!t)}finally{t?.()}},c=a.paths?.dir??r.unit?.definition.stateDir;return c?se({stateDir:c,uid:this.machine.uid,create:t,startupPreference:e=>e.autostartConfigured},s):s()}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??re)(),t=[`/usr/local/bin`,`/usr/bin`,`/bin`],n=(this.options.env.PATH??``).split(`:`).filter(e=>N(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:M(M(i.paths.runtimeDir)),serviceInstance:a?.serviceInstance??I(),path:[...new Set([M(e.nodePath),...n,...t])].join(`:`)},s=Ga(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=I());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 fo=Qe(be);function po(e){let t=/(\d+)\.(\d+)/.exec(e);return t?Number(t[1])+Number(t[2])/100:null}function mo(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 ho(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 go(e,t){for(let n of t.PATH?.split(He)??[])if(n)try{return Ce(P(n,e),w.X_OK),!0}catch{}return!1}async function _o(e){return(await fo(`tmux`,[`-V`],{env:e,timeout:3e3,maxBuffer:65536})).stdout}async function vo(e){return sa({socketPath:Ir(e),herdrOnPath:()=>go(`herdr`,e)})}function yo(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 bo(e){try{let t=process.getuid?.();return t!==void 0&&new oe({stateDir:m(e),uid:t}).inspect()?.mode===`desktop`}catch{return!1}}function xo(e,t,n){return e.loaded&&!e.installed?$(`service manager`,`loaded service has no installed definition`):!e.installed&&bo(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 start`"):$(`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 install` to run Shellbell in the background")}function So(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,"run `shellbell install` to run Shellbell in the background; foreground readiness is independent")}function Co(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 wo(e,t=process.platform){if(!e)return[];let n=new Xt({home:e,platform:t,create:!1});try{await n.refresh();let e=[],t=new Set;for(let r of n.entries){let n=r.skipped??r.iconIssue;n&&(e.push(Q(`page ${r.name}`,n.reason,n.fix)),t.add(n.reason))}for(let r of n.issues)t.has(r)||e.push(Q(`pages`,r));return e.unshift(Z(`pages`,`${n.entries.filter(e=>!e.skipped).length} registered pages available`)),e}finally{n.close()}}async function To(e,t={}){return[...await Eo(e,t),...await wo(e.env.HOME,e.platform??process.platform)]}async function Eo(e,t={}){let r=(e.platform??process.platform)===`linux`,i=Q(`service manager`,`Linux systemd user-manager inspection unavailable; foreground readiness is independent`,"run `shellbell status` and inspect 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 n,r={...e.env,SHELLBELL_DIR:e.requestedStateDir??e.env.SHELLBELL_DIR},a=e=>(r=e,n=(t.selectLinuxPaths??(e=>h({env:e})))(e),n);try{i=So(await(t.inspectLinuxService??(()=>new uo({env:r,selectPaths:a}).status()))(a))}catch{}let s;try{let e=n??a(r);c=e;let t=ae(e);s=t.status===`ready`?Z(`host state`,`Linux host state admitted`):$(`host state`,t.reason??`Linux host state is absent`,"absent state: run `shellbell install`; otherwise 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,i,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(t.inspectManager??(()=>a().inspect()))()}catch{return Co(`service manager inspection failed; state unavailable`,e.requiredBackends)}try{c=de(s,e.requestedStateDir,e.defaultStateDir)}catch{return Co(`state selection unavailable; check SHELLBELL_DIR against installed service`,e.requiredBackends)}}let l,u=null;try{let e=n(c);e?(u=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 d=null,f;if(!u)f=$(`control`,`cannot verify local process without a valid identity`);else try{let n=await(t.controlStatus??(e=>p(e,`status`,void 0,{timeoutMs:500,maxResponseBytes:65536})))(c.sock),r=ye.safeParse(n);if(!r.success)f=$(`control`,`local endpoint returned malformed or unsupported status`);else if(!fe(r.data,{computerFp:u,stateDir:c.dir}))f=$(`control`,`local endpoint belongs to a different identity or state directory`);else{d=r.data;let t=d.process.agentVersion;f=e.version&&t!==e.version?Q(`control`,`Shellbell ${t} is running, but ${e.version} is installed`,d.process.serviceInstance?`run \`shellbell install\` to switch to ${e.version}`:`stop Shellbell in its terminal window and start it again`):Z(`control`,`Shellbell ${t} answers; identity and state verified`)}}catch{f=$(`control`,`local endpoint is absent or did not return bounded status`,`start Shellbell, or inspect the configured service`)}let m=r?i:xo(s,d,c.dir),g=null,_=null;try{_=b(c).relayUrl}catch{g=$(`relay`,r?`Linux configuration invalid or unreadable`:`configuration invalid or unreadable at ${c.config}`,`repair the existing config without replacing identity files`)}if(!g){if(d?.relayOnline)g=Z(`relay`,`local agent reports relay connected`);else{let e=`configured relay`,n=!1;try{let r=new URL(_);[`ws:`,`wss:`,`http:`,`https:`].includes(r.protocol)&&(e=`${r.protocol===`ws:`?`http:`:r.protocol===`wss:`?`https:`:r.protocol}//${r.host}/healthz`,n=await(t.relayHealth??Ia)(_))}catch{}g=$(`relay`,`local agent is not relay-connected; ${e} ${n?`is reachable`:`is not confirmed reachable`} (HTTP health does not prove WebSocket authorization)`,`check the relay URL, network, and running agent`)}}let{env:ee,context:v}=r?{env:e.env,context:`current shell setup`}:yo(s,e.env),te=new Set(e.requiredBackends),y=e=>d?.backends.find(t=>t.name===e)?.connected===!0,ne=Q(`iterm2`,`${v}: iTerm2 API socket unavailable`,`enable iTerm2 Python API, then start Shellbell to authorize access`);if(!r&&!y(`iterm2`))try{(t.itermSocketExists??(()=>T(Na)))()&&(ne=Q(`iterm2`,`${v}: API socket exists but agent is disconnected`,`start Shellbell to authorize iTerm2 API access`))}catch{ne=$(`iterm2`,`iTerm2 API socket inspection failed`)}let re=ho(`iterm2`,y(`iterm2`),te.has(`iterm2`),ne),ie=Q(`tmux`,`${v}: tmux is unavailable`,`install tmux 3.2 or newer`);if(!y(`tmux`))try{let e=po(await(t.tmuxVersion??_o)(ee));ie=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){ie=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=ho(`tmux`,y(`tmux`),te.has(`tmux`),ie),se=Q(`herdr`,`${v}: Herdr is unavailable`,jr);if(!r&&!y(`herdr`))try{let e=await(t.checkHerdr??vo)(ee);se=e.ok?e.detail===`not installed (optional)`?Q(`herdr`,`${v}: Herdr not found on PATH`,jr):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`,Mr)}catch{se=$(`herdr`,`${v}: Herdr API probe failed`,Mr)}let ce=ho(`herdr`,y(`herdr`),te.has(`herdr`),se),x=d?await(t.terminalSetup??ko)(c.sock).catch(()=>null):null,le=!r&&!!x&&xt(x),ue=(e,t)=>{let n=x?.find(e=>e.name===t);if(!n?.issue)return e;let{status:r,fix:i}=yt(n,`command-line`,{noneUsable:le});return n.connected?{...Q(t,r,i),...e.required?{required:!0}:{}}:ho(t,!1,te.has(t),Q(t,r,i))},S=(r?y(`tmux`):d?.terminalReady)?Z(`terminal readiness`,`at least one backend connected to the verified local agent`):le?$(`terminal readiness`,St(`command-line`).status,St(`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,m,f,g,...r?o:[ue(re,`iterm2`)],ue(oe,`tmux`),...r?[]:[ue(ce,`herdr`)],S,Oo(c.dir,e.env.HOME),...Do(d)]}function Do(e){return(e?.newerAgents??[]).map(e=>Z(`agent version`,`${e.name} ${e.version} is newer than Shellbell was tested with. Chat still works; tell us if something looks wrong.`))}function Oo(e,t){try{let n=_r(lr(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 ko(e){let t=await c(e);try{return await t.terminals()}finally{t.close()}}export{en as $,ca as A,_r as B,Oa as C,ua as D,_a as E,kr as F,Rn as G,xr as H,Or as I,xn as J,Ln as K,Cr as L,Ci as M,xi as N,W as O,Zr as P,gn as Q,lr as R,Sa as S,ja as T,yr as U,Sr as V,br as W,pn as X,mn as Y,vn as Z,va as _,uo as a,Rt as at,wa as b,Pa as c,At as ct,ga as d,Mt as dt,Zt as et,ha as f,Ct as ft,Ca as g,ht as gt,ya as h,mt as ht,To as i,Jt as it,ra as j,da as k,ka as l,jt as lt,Ma as m,yt as mt,mo as n,Xt as nt,lo as o,It as ot,Da as p,_t as pt,bn as q,po as r,Ut as rt,Na as s,zt as st,Oo as t,B as tt,Aa as u,kt as ut,ba as v,Ta as w,xa as x,Ea as y,vr as z};