@hydra-acp/cli 0.1.213 → 0.1.214

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/daemon.js CHANGED
@@ -1,63 +1,63 @@
1
1
  #!/usr/bin/env node
2
- var Il=Object.defineProperty;var Zn=(s,e)=>()=>(s&&(e=s(s=0)),e);var Al=(s,e)=>{for(var t in e)Il(s,t,{get:e[t],enumerable:!0})};import*as U from"path";import*as Sr from"os";function $(s){let e=Sr.homedir();if(!e)return s;let t=o=>process.platform==="win32"?o.replace(/\\/g,"/").toLowerCase():o,n=t(e),r=t(s);return r===n?"~":r.startsWith(n+"/")?"~"+s.slice(e.length):s}function Cl(){if(process.env.VITEST)return"vitest";if(process.versions.bun||typeof globalThis.Bun<"u")return"bun";if(process.env.JEST_WORKER_ID!==void 0)return"jest";if(process.env.NODE_TEST_CONTEXT!==void 0)return"node:test"}function Rl(s,e){Ri||U.isAbsolute(s)||(Ri=!0,process.stderr.write(`hydra-acp: ${xi} is relative (${JSON.stringify(s)}); resolved against the current directory to ${e}. Processes started from elsewhere will use a different home and will not see each other's daemon. Set an absolute path.
3
- `))}function z(){let s=process.env[xi];if(s&&s.length>0){let t=U.resolve(s);return Rl(s,t),t}let e=Cl();if(e)throw new Error(`HYDRA_ACP_HOME is unset under a test runner (${e}); refusing to fall back to ~/.hydra-acp. The harness must set HYDRA_ACP_HOME \u2014 vitest.setup.ts does this, but \`bun test\` bypasses the vitest config and does not. Run the suite with \`npx vitest run\`, not \`bun test\`.`);return U.join(Sr.homedir(),".hydra-acp")}var xi,Ri,T,Y=Zn(()=>{"use strict";xi="HYDRA_ACP_HOME";Ri=!1;T={home:z,config:()=>U.join(z(),"config.json"),authToken:()=>U.join(z(),"auth-token"),remotes:()=>U.join(z(),"remotes.json"),peers:()=>U.join(z(),"peers.json"),tlsDir:()=>U.join(z(),"tls"),pidFile:()=>U.join(z(),"daemon.pid"),logFile:()=>U.join(z(),"daemon.log"),daemonBootLog:()=>U.join(z(),"daemon-boot.log"),currentLogFile:()=>U.join(z(),"current.log"),registryCache:()=>U.join(z(),"registry.json"),themesDir:()=>U.join(z(),"themes"),ttySessionDir:()=>U.join(z(),"tty"),ttySessionFile:s=>U.join(z(),"tty",s),agentsDir:()=>U.join(z(),"agents"),agentLogFile:s=>U.join(z(),"agents","logs",`${s}.log`),agentInstallDir:(s,e,t)=>U.join(z(),"agents",e,s,t),agentNpmInstallDir:(s,e,t)=>U.join(z(),"agents",e,s,t,`node${process.versions.modules}`),sessionsDir:()=>U.join(z(),"sessions"),sessionDir:s=>U.join(z(),"sessions",s),sessionFile:s=>U.join(z(),"sessions",s,"meta.json"),historyFile:s=>U.join(z(),"sessions",s,"history.jsonl"),historyArchiveFile:(s,e)=>U.join(z(),"sessions",s,`history.jsonl.${e}`),toolsDir:s=>U.join(z(),"sessions",s,"tools"),toolBlobFile:(s,e)=>U.join(z(),"sessions",s,"tools",e),queueFile:s=>U.join(z(),"sessions",s,"queue.ndjson"),tombstonesDir:()=>U.join(z(),"sessions",".tombstones"),tombstoneAgentDir:s=>U.join(z(),"sessions",".tombstones",encodeURIComponent(s)),tombstoneFile:(s,e)=>U.join(z(),"sessions",".tombstones",encodeURIComponent(s),encodeURIComponent(e)),extensionsDir:()=>U.join(z(),"extensions"),extensionLogDir:s=>U.join(z(),"extensions",s),extensionLogFile:s=>U.join(z(),"extensions",s,"current.log"),extensionPidFile:s=>U.join(z(),"extensions",s,"extension.pid"),transformersDir:()=>U.join(z(),"transformers"),transformerLogDir:s=>U.join(z(),"transformers",s),transformerLogFile:s=>U.join(z(),"transformers",s,"current.log"),transformerPidFile:s=>U.join(z(),"transformers",s,"transformer.pid"),transformerState:(s,e)=>U.join(z(),"sessions",s,"transformer-state",e),tuiHistoryFile:s=>U.join(z(),"sessions",s,"prompt-history"),globalTuiHistoryFile:()=>U.join(z(),"prompt-history"),tuiLogFile:()=>U.join(z(),"tui.log"),shimWireLogFile:()=>U.join(z(),"shim-wire.log")}});import*as ge from"fs/promises";import*as Ti from"fs";import*as Me from"path";import{randomBytes as El}from"crypto";async function me(s,e,t={}){let r=(t.pretty??!0?JSON.stringify(e,null,2):JSON.stringify(e))+`
4
- `;await _l(s,r,t)}async function Ml(s,e,t={}){let n=t.rename??ge.rename,r=t.platform??process.platform,o=t.sleep??(i=>new Promise(a=>setTimeout(a,i)));for(let i=0;;i++)try{await n(s,e);return}catch(a){let d=a.code??"";if(!(r==="win32"&&Tl.has(d)&&i<Pl-1))throw a;await o(10*(i+1))}}async function _l(s,e,t={}){let n=await $l(s),r=Me.dirname(n);await ge.mkdir(r,{recursive:!0});let o=`${n}.tmp-${process.pid}-${Ol()}`;try{let i={encoding:"utf8"};t.mode!==void 0&&(i.mode=t.mode),await ge.writeFile(o,e,i),await Ml(o,n)}catch(i){throw await ge.unlink(o).catch(()=>{}),i}if(t.mode!==void 0)try{Ti.chmodSync(n,t.mode)}catch{}}async function $l(s){let e;try{e=await ge.lstat(s)}catch(r){if(r.code==="ENOENT")return s;throw r}if(!e.isSymbolicLink())return s;let t=await ge.readlink(s),n=Me.isAbsolute(t)?t:Me.resolve(Me.dirname(s),t);try{let r=await ge.realpath(Me.dirname(n));return Me.join(r,Me.basename(n))}catch(r){if(r.code==="ENOENT")return n;throw r}}async function de(s){let e;try{e=await ge.readFile(s,"utf8")}catch(t){if(t.code==="ENOENT")return;throw t}if(e.trim().length!==0)try{return JSON.parse(e)}catch{return}}function Ol(){return El(4).toString("hex")}var Tl,Pl,je=Zn(()=>{"use strict";Tl=new Set(["EPERM","EACCES","EBUSY"]),Pl=10});function fr(s,e){return`${s}:${e}`}var Hu=Zn(()=>{"use strict";Y();je()});var zu={};Al(zu,{_resetForTests:()=>ow,clearPin:()=>ui,fetchPeerFingerprint:()=>sw,formatFingerprint:()=>Lu,getPin:()=>tw,installGlobalTlsTrust:()=>pi,loadPinsFromPeerStore:()=>li,loadPinsFromStore:()=>nw,setPin:()=>Gn,sha256Hex:()=>fi,wsTlsOptions:()=>gi});import{createHash as Ky}from"crypto";import*as ju from"tls";import{Agent as Qy,Dispatcher as Yy,buildConnector as Xy,getGlobalDispatcher as Zy,setGlobalDispatcher as ew}from"undici";function Gn(s,e,t){Tt.set(fr(s,e),Uu(t))}function ui(s,e){Tt.delete(fr(s,e))}function tw(s,e){return Tt.get(fr(s,e))}function nw(s){Tt.clear();for(let e of s.list())e.entry.pinnedFingerprint&&Gn(e.host,e.port,e.entry.pinnedFingerprint)}function li(s){for(let e of s.list())e.pinnedFingerprint&&Gn(e.host,e.port,e.pinnedFingerprint)}async function sw(s,e,t={}){let n=t.timeoutMs??1e4;return new Promise((r,o)=>{let i=ju.connect({host:s,port:e,servername:s,rejectUnauthorized:!1,autoSelectFamily:!0}),a=!1,d=(u,l)=>{if(!a){a=!0,clearTimeout(c);try{i.destroy()}catch{}u?o(u):l&&r(l)}},c=setTimeout(()=>{d(new Error(`TLS connect to ${s}:${e} timed out`))},n);i.once("secureConnect",()=>{let u=i.getPeerCertificate(!1);if(!u||!u.raw){d(new Error(`${s}:${e} did not present a TLS certificate`));return}d(null,fi(u.raw))}),i.once("error",u=>d(u))})}function fi(s){return Ky("sha256").update(s).digest("hex")}function Lu(s){let e=Uu(s),t=e.match(/.{2}/g);return t?t.join(":"):e}function Uu(s){return s.replace(/:/g,"").toLowerCase()}function pi(){if(ci)return;ci=!0;let s=Zy(),e=new Qy({connect:Xy({rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(n,r)=>Wu(n,r)})}),t=new Yy;t.dispatch=(n,r)=>{let o=rw(n.origin);return(o&&Bu(o)?e:s).dispatch(n,r)},t.close=(()=>Promise.all([e.close(),s.close()]).then(()=>{})),t.destroy=(n=>Promise.all([e.destroy(n??null),s.destroy(n??null)]).then(()=>{})),ew(t)}function rw(s){if(!s)return null;try{return new URL(String(s)).hostname}catch{return null}}function Bu(s){for(let e of Tt.keys())if(qu(e)?.host===s)return!0;return!1}function Wu(s,e){if(!e||!e.raw)return new Error(`TLS peer ${s} did not present a certificate`);let t=fi(e.raw);for(let[n,r]of Tt.entries()){let o=qu(n);if(o&&o.host===s&&r===t)return}return new Error(`TLS pin mismatch for ${s} (cert sha256 ${Lu(t)})`)}function qu(s){let e=s.lastIndexOf(":");if(e<0)return null;let t=s.slice(0,e),n=Number(s.slice(e+1));return Number.isInteger(n)?{host:t,port:n}:null}function gi(s){return Bu(s)?{rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(e,t)=>Wu(e,t)}:{autoSelectFamily:!0}}function ow(){Tt.clear(),ci=!1}var Tt,ci,Kn=Zn(()=>{"use strict";Hu();Tt=new Map,ci=!1});Y();import*as ot from"fs/promises";import{homedir as Mr}from"os";import{z as A}from"zod";Y();import*as Mt from"fs/promises";function Ir(){let s=new Uint8Array(32);crypto.getRandomValues(s);let e="";for(let t of s)e+=t.toString(16).padStart(2,"0");return`hydra_token_${e}`}async function xl(){try{let e=(await Mt.readFile(T.authToken(),"utf8")).trim();return e.length>0?e:void 0}catch(s){if(s.code==="ENOENT")return;throw s}}async function Ar(s){await Mt.mkdir(T.home(),{recursive:!0}),await Mt.writeFile(T.authToken(),s+`
5
- `,{encoding:"utf8",mode:384})}async function Ei(){let s=await xl();if(s)return s;let e=Ir();return await Ar(e),process.stderr.write(`hydra-acp: initialized ${T.authToken()} with a fresh service token.
6
- `),e}je();import*as Mi from"fs/promises";import*as fn from"os";import*as Le from"path";var ne="read by the daemon, which loads config.json at startup",Pi={daemon:{reload:"restart",overlay:"partial",overlayNote:"only changes which daemon this client dials; a daemon started from here still binds config.json's host/port. Use `home` for a separate daemon",nested:!0},agents:{reload:"live",overlay:"inert",overlayNote:ne},agentOverrides:{reload:"live",overlay:"inert",overlayNote:ne},registry:{reload:"live",overlay:"inert",overlayNote:ne},npmRegistry:{reload:"live",overlay:"inert",overlayNote:ne},defaultAgent:{reload:"live",overlay:"effective"},defaultCwd:{reload:"live",overlay:"effective"},sessionDefaults:{reload:"live",overlay:"partial",overlayNote:"applies to WS session/new and child_session/spawn; POST /v1/sessions has no model/mode/effort field to apply any of it to"},synopsisAgent:{reload:"warn",overlay:"inert",overlayNote:ne},synopsisModel:{reload:"warn",overlay:"inert",overlayNote:ne},compaction:{reload:"warn",overlay:"inert",overlayNote:ne},defaultTransformers:{reload:"warn",overlay:"inert",overlayNote:ne},disableWorkspaceSnapshots:{reload:"warn",overlay:"inert",overlayNote:ne},compressToolContent:{reload:"warn",overlay:"inert",overlayNote:ne},extensions:{reload:"warn",overlay:"inert",overlayNote:ne},transformers:{reload:"warn",overlay:"inert",overlayNote:ne},tui:{reload:"client",overlay:"effective"},sessionListColdLimit:{reload:"client",overlay:"effective"}},Fl={host:{reload:"restart",overlay:"inert"},port:{reload:"restart",overlay:"inert"},publicHost:{reload:"restart",overlay:"inert"},tls:{reload:"restart",overlay:"inert"},scrubEnv:{reload:"live",overlay:"inert",overlayNote:ne},logLevel:{reload:"warn",overlay:"inert",overlayNote:ne},sessionIdleTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:ne},nonInteractiveOrphanTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:ne},sessionHistoryMaxEntries:{reload:"warn",overlay:"inert",overlayNote:ne},sessionHistoryArchiveMaxBytes:{reload:"warn",overlay:"inert",overlayNote:ne},sessionHistoryArchiveTiers:{reload:"warn",overlay:"inert",overlayNote:ne},agentStderrTailBytes:{reload:"warn",overlay:"inert",overlayNote:ne},agentSyncIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:ne},sessionGcIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:ne},sessionGcMaxAgeDays:{reload:"warn",overlay:"inert",overlayNote:ne}};function Cr(s){return Pi[s]??{reload:"restart",overlay:"inert"}}function Rr(s){return Fl[s]??{reload:"restart",overlay:"inert"}}function xr(){let s=[];for(let[e,t]of Object.entries(Pi))t.overlay!=="effective"&&s.push({key:e,effect:t.overlay,note:t.overlayNote??ne});return s}var Nl=".hydra-acp.json",Er="home",Dl=64,vk=xr().map(s=>s.key);function Hl(s){return s==="~"?fn.homedir():s.startsWith("~/")?Le.join(fn.homedir(),s.slice(2)):s.startsWith("$HOME/")?Le.join(fn.homedir(),s.slice(6)):s}function Tr(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function Pr(s,e){let t={...s};for(let[n,r]of Object.entries(e)){let o=t[n];t[n]=Tr(o)&&Tr(r)?Pr(o,r):r}return t}async function jl(s,e=fn.homedir()){let t=[],n=[],r=Le.resolve(e),o=Le.resolve(s);for(let i=0;i<Dl;i+=1){let a=Le.join(o,Nl),d;try{d=await Mi.readFile(a,"utf8")}catch{d=void 0}if(d!==void 0)try{let u=JSON.parse(d);Tr(u)?t.push({file:a,data:u}):n.push({file:a,key:"",message:"expected a JSON object; ignoring this file"})}catch(u){n.push({file:a,key:"",message:`is not valid JSON (${u.message}); ignoring this file`})}if(o===r)break;let c=Le.dirname(o);if(c===o)break;o=c}return t.reverse(),{layers:t,notices:n}}function Ll(s){let e=new Map(xr().map(n=>[n.key,n])),t=[];for(let n of s)for(let r of Object.keys(n.data)){let o=e.get(r);if(!o)continue;let i=o.effect==="partial"?`\`${r}\` ${o.note}`:`\`${r}\` is ${o.note}, so it has no effect in a directory config`;t.push({file:n.file,key:r,message:i})}return t}async function Ul(s=process.cwd()){let{layers:e,notices:t}=await jl(s);t.push(...Ll(e));let n={};for(let i of e)n=Pr(n,i.data);let r,o=n[Er];return typeof o=="string"&&o.length>0?r=Le.resolve(Hl(o)):o!==void 0&&t.push({file:e[e.length-1].file,key:Er,message:"`home` must be a non-empty string; ignoring it"}),delete n[Er],{layers:e,notices:t,merged:n,...r!==void 0?{homeRequest:r}:{}}}function Bl(s,e){let t=s[e];return typeof t=="string"&&t.length>0?t:void 0}function Wl(s,e){let t=s[e];if(t===null||typeof t!="object"||Array.isArray(t))return;let n={};for(let[r,o]of Object.entries(t)){if(o===null||typeof o!="object"||Array.isArray(o))continue;let i={};for(let[a,d]of Object.entries(o))typeof d=="string"&&(i[a]=d);Object.keys(i).length>0&&(n[r]=i)}return Object.keys(n).length>0?n:void 0}async function pn(s){let e={};try{e=(await Ul(s)).merged}catch{return{}}let t=Bl(e,"defaultAgent"),n=Wl(e,"sessionDefaults");return{...t!==void 0?{agentId:t}:{},...n!==void 0?{configDefaults:n}:{}}}var Oi="https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",ql=A.object({cert:A.string(),key:A.string()}),_t=55514,zl=A.object({host:A.string().default("127.0.0.1"),port:A.number().int().positive().default(_t),logLevel:A.enum(["debug","info","warn","error"]).default("info"),tls:ql.optional(),sessionIdleTimeoutSeconds:A.number().int().nonnegative().default(3600),nonInteractiveOrphanTimeoutSeconds:A.number().int().nonnegative().default(180),sessionHistoryMaxEntries:A.number().int().positive().default(1e4),sessionHistoryArchiveMaxBytes:A.number().int().nonnegative().default(1e7),sessionHistoryArchiveTiers:A.number().int().positive().default(10),agentStderrTailBytes:A.number().int().positive().default(4096),publicHost:A.string().optional(),agentSyncIntervalMinutes:A.number().nonnegative().default(60),scrubEnv:A.array(A.string()).default([]),sessionGcIntervalMinutes:A.number().nonnegative().default(60),sessionGcMaxAgeDays:A.number().positive().default(2)}),Jl=A.object({url:A.string().url().default(Oi),ttlHours:A.number().positive().default(24),pinned:A.boolean().default(!1)}),Vl=A.object({extends:A.string().optional(),name:A.string().optional(),description:A.string().optional(),command:A.string().optional(),args:A.array(A.string()).optional(),env:A.record(A.string()).optional()}),Gl=A.object({packageSpec:A.string().optional(),extraArgs:A.array(A.string()).optional(),env:A.record(A.string()).optional()}),Kl=A.enum(["enter","alt-enter","shift-enter","ctrl-enter","alt-b","alt-f","alt-n","alt-tab","shift-tab","tab","up","down","left","right","home","end","backspace","alt-backspace","delete","ctrl-a","ctrl-b","ctrl-c","ctrl-d","ctrl-e","ctrl-f","ctrl-g","ctrl-k","ctrl-l","ctrl-n","ctrl-o","ctrl-p","ctrl-q","ctrl-r","ctrl-s","ctrl-u","ctrl-v","ctrl-t","ctrl-w","ctrl-x","ctrl-x-ctrl-e","ctrl-y","ctrl-underscore","alt-underscore","escape"]),Ql=A.union([A.string(),A.object({field:A.string().optional(),text:A.string().optional(),script:A.string().optional(),refreshMs:A.number().int().positive().optional(),maxWidth:A.number().int().positive().optional(),minWidth:A.number().int().nonnegative().optional(),truncate:A.boolean().optional(),priority:A.number().optional(),prefix:A.string().optional(),suffix:A.string().optional(),separator:A.string().optional(),style:A.string().optional(),onClick:A.string().optional(),onDoubleClick:A.string().optional()}).strict()]),Yl=A.object({id:A.string().min(1),script:A.string().min(1),refreshMs:A.number().int().positive().optional(),title:A.string().optional(),cap:A.number().int().positive().optional()}).strict(),Xl=A.union([A.string(),Yl]),_i=A.array(Ql);function _r(s,e){return A.object({left:_i.default(s),right:_i.default(e)}).default({})}var Zl=["status",{field:"elapsed",separator:" "},"sessionId","queued","scroll"],ef=["usage"],tf=[],nf=["helpHint"],sf=["cwd","title"],rf=["agentModel"],of=A.object({composer:A.object({top:_r(Zl,ef),bottom:_r(tf,nf),hintTurns:A.number().int().nonnegative().nullable().default(3)}).default({}),sessionbar:_r(sf,rf),scriptRefreshMs:A.number().int().positive().default(5e3),readIdleSeconds:A.number().int().nonnegative().default(180),repaintThrottleMs:A.number().int().nonnegative().default(1e3),maxScrollbackLines:A.number().int().positive().default(1e4),mouse:A.boolean().default(!0),inAppSelection:A.boolean().optional(),selectionClipboard:A.enum(["primary","clipboard","both"]).default("both"),openFileCommand:A.union([A.string(),A.array(A.string())]).optional(),openFileInTerminal:A.boolean().optional(),logMaxBytes:A.number().int().positive().default(5*1024*1024),keyTrace:A.boolean().optional(),cwdColumnMaxWidth:A.number().int().positive().default(32),progressIndicator:A.boolean().default(!0),terminalHost:A.union([A.boolean(),A.enum(["auto","paseo","herdr","tmux"])]).default(!0),launcherModeWhenHosted:A.boolean().default(!1),skipPermissions:A.boolean().default(!1),defaultEnterAction:A.enum(["enqueue","amend"]).default("amend"),showThoughts:A.boolean().default(!0),ambiguousWidth:A.enum(["auto","narrow","wide"]).default("auto"),toolContent:A.enum(["inline","references"]).default("references"),diffContextLines:A.number().int().min(0).default(3),promptHistoryMaxEntries:A.number().int().positive().default(2e3),maxToolItems:A.number().int().nonnegative().default(5),maxPlanItems:A.number().int().nonnegative().default(5),sidebar:A.object({enabled:A.boolean().default(!0),width:A.number().int().positive().optional(),border:A.enum(["none","rule","frame"]).default("frame"),gadgets:A.array(Xl).default(["activity","sessions","tasks","context","queue","todo","files","git","resources","info","tools"])}).default({}),showFileUpdates:A.enum(["none","edit","diff"]).default("edit"),sessionColumns:A.array(A.enum(["session","upstream","host","state","agent","model","age","cwd","title","cost"])).nonempty().optional(),defaultHost:A.string().min(1).default("remote:all"),hotkeys:A.record(Kl,A.object({command:A.union([A.string(),A.array(A.string())])})).default({}),theme:A.union([A.string(),A.record(A.string(),A.unknown())]).optional(),themeBackground:A.string().optional()}),$i=A.string().min(1).regex(/^[A-Za-z0-9._-]+$/,"extension name must be filename-safe"),af=A.object({command:A.array(A.string()).default([]),args:A.array(A.string()).default([]),env:A.record(A.string()).default({}),enabled:A.boolean().default(!0)}),df=A.object({command:A.array(A.string()).default([]),args:A.array(A.string()).default([]),env:A.record(A.string()).default({}),enabled:A.boolean().default(!0)}),cf=A.object({daemon:zl.default({}),registry:Jl.default({url:Oi,ttlHours:24,pinned:!1}),agents:A.record(A.string(),Vl).default({}),agentOverrides:A.record(A.string(),Gl).default({}),defaultAgent:A.string().default("opencode"),sessionDefaults:A.record(A.string(),A.record(A.string(),A.string())).default({}),synopsisAgent:A.string().optional(),synopsisModel:A.string().optional(),compaction:A.object({agent:A.string().optional(),model:A.string().optional(),tailK:A.number().int().nonnegative().default(20),maxIterations:A.number().int().positive().default(3),contextFraction:A.number().min(0).max(1).default(.5),hardCeilingFraction:A.number().min(0).max(1).default(.85),absoluteFallback:A.number().int().positive().default(2e5),idleBeforePromptMs:A.number().int().nonnegative().default(3e5),modelContextWindows:A.record(A.string(),A.number().int().positive()).default({})}).default({}),defaultCwd:A.string().default("~"),disableWorkspaceSnapshots:A.boolean().optional(),compressToolContent:A.boolean().default(!0),sessionListColdLimit:A.number().int().nonnegative().default(20),extensions:A.record($i,af).default({}),transformers:A.record($i,df).default({}),defaultTransformers:A.array(A.string()).default([]),npmRegistry:A.string().url().optional(),tui:of.default({})});function Fi(s){return Object.entries(s.extensions).map(([e,t])=>({name:e,...t}))}function Ni(s){return Object.entries(s.transformers).map(([e,t])=>({name:e,...t}))}async function $r(){return await uf(),await de(T.config())??{}}async function uf(){let s;try{s=await ot.lstat(T.config())}catch(e){if(e.code==="ENOENT")return;throw e}if(s.isSymbolicLink())try{await ot.stat(T.config())}catch(e){if(e.code!=="ENOENT")throw e;let t=await ot.readlink(T.config()).catch(()=>"<unknown>");throw new Error(`config.json at ${T.config()} is a broken symlink (-> ${t}); its target is missing. Refusing to treat this as "no config" and overwrite it. Restore the target (e.g. decrypt/check out your dotfiles) or remove the dangling link.`)}}async function lf(){let s=await $r(),e=s.daemon,t=e&&typeof e.authToken=="string"?e.authToken:void 0;if(!t)return;let n=!1;try{await ot.access(T.authToken()),n=!0}catch(r){if(r.code!=="ENOENT")throw r}if(n)throw new Error(`Auth token present in both ${T.authToken()} and ${T.config()} (daemon.authToken). Remove daemon.authToken from config.json to resolve.`);await Ar(t),delete e.authToken,Object.keys(e).length===0&&delete s.daemon,await me(T.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated auth token from ${T.config()} to ${T.authToken()}.
7
- `)}async function ff(){let s=await $r(),e=s.defaultModels&&typeof s.defaultModels=="object"&&!Array.isArray(s.defaultModels)?s.defaultModels:void 0;if(!e)return;let t=s.sessionDefaults&&typeof s.sessionDefaults=="object"&&!Array.isArray(s.sessionDefaults)?s.sessionDefaults:{};for(let[n,r]of Object.entries(e)){if(typeof r!="string")continue;let o=t[n]&&typeof t[n]=="object"&&!Array.isArray(t[n])?t[n]:{};o.model===void 0&&(o.model=r),t[n]=o}s.sessionDefaults=t,delete s.defaultModels,await me(T.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated defaultModels to sessionDefaults in ${T.config()}.
8
- `)}async function gn(){return await lf(),await ff(),cf.parse(await $r())}function ce(s){return s==="~"||s==="$HOME"?Mr():s.startsWith("~/")?Mr()+s.slice(1):s.startsWith("$HOME/")?Mr()+s.slice(5):s}Y();import*as et from"fs/promises";import*as Di from"path";var pf=64*1024;async function Hi(s){let e=T.daemonBootLog(),t=`[${new Date().toISOString()}] pid=${process.pid} ${s}
9
- `;if(await et.mkdir(Di.dirname(e),{recursive:!0}),await et.stat(e).then(r=>r.size).catch(()=>0)>pf){await et.writeFile(e,t,{encoding:"utf8",mode:384});return}await et.appendFile(e,t,{encoding:"utf8",mode:384})}import*as hl from"fs";import*as Xe from"fs/promises";import*as yl from"net";import*as cn from"path";import*as wl from"tls";import sk from"fastify";import rk from"@fastify/websocket";var ji="acp.v1";function Li(s,e){return s.has(ji)?ji:!1}import gl from"pino";import ok from"pino-roll";var gf={herdr:["HERDR_PANE_ID","HERDR_TAB_ID","HERDR_WORKSPACE_ID","HERDR_STARTUP_CWD"],tmux:["TMUX_PANE"],zellij:["ZELLIJ_PANE_ID","ZELLIJ_SESSION_NAME"],wezterm:["WEZTERM_PANE"],kitty:["KITTY_WINDOW_ID"],screen:["STY"],iterm2:["ITERM_SESSION_ID"],paseo:["PASEO_TERMINAL_ID","PASEO_ACTIVITY_TOKEN"],hydra:["HYDRA_TAB_LABEL"]},Ui="HYDRA_ACP_SESSION",mf=[Ui],hf=[...Object.values(gf).flat(),...mf];function es(s,e){return s?{...e??{},[Ui]:s}:e}var Bi=[];function Or(s){Bi=s?[...s]:[]}function yf(s,e){return e.endsWith("*")?s.startsWith(e.slice(0,-1)):s===e}function wf(){return[...hf,...Bi]}function ts(s=process.env){let e=wf(),t={};for(let[n,r]of Object.entries(s))r!==void 0&&(e.some(o=>yf(n,o))||(t[n]=r));return t}Y();import*as he from"fs/promises";import{createHash as kf}from"crypto";import{gzip as vf,gunzip as bf}from"zlib";import{promisify as Wi}from"util";var qi=Wi(vf),Sf=Wi(bf),zi=/^[A-Za-z0-9_-]+$/,If=/^[a-f0-9]{64}$/,Fr=!0;function Ji(s){Fr=s}function ns(s,e){return zi.test(s)?e===void 0||If.test(e):!1}function ss(s,e){return`${T.toolBlobFile(s,e)}.gz`}async function Nr(s,e){if(!ns(s))return null;let t=kf("sha256").update(e,"utf8").digest("hex"),n=ss(s,t),r=T.toolBlobFile(s,t);for(let a of[n,r])try{return await he.access(a),t}catch{}await he.mkdir(T.toolsDir(s),{recursive:!0});let o=Fr?n:r,i=Fr?await qi(Buffer.from(e,"utf8")):Buffer.from(e,"utf8");return await he.writeFile(o,i,{mode:384,flag:"wx"}).catch(async a=>{if(a.code!=="EEXIST")throw a}),t}async function mn(s,e){if(!ns(s,e))return null;try{let t=await he.readFile(ss(s,e));return(await Sf(t)).toString("utf8")}catch{}try{return await he.readFile(T.toolBlobFile(s,e),"utf8")}catch{return null}}async function Vi(s,e){if(!ns(s,e))return null;try{return await he.readFile(ss(s,e))}catch{}try{let t=await he.readFile(T.toolBlobFile(s,e));return await qi(t)}catch{return null}}async function Gi(s,e,t){if(!ns(s,e))return;let n=ss(s,e);try{await he.access(n);return}catch{}await he.mkdir(T.toolsDir(s),{recursive:!0}),await he.writeFile(n,t,{mode:384,flag:"wx"}).catch(r=>{if(r.code!=="EEXIST")throw r})}async function Ki(s){zi.test(s)&&await he.rm(T.toolsDir(s),{recursive:!0,force:!0}).catch(()=>{})}Y();import*as ca from"fs/promises";import*as os from"path";import{z as j}from"zod";je();Y();import*as Yi from"fs";import*as ke from"fs/promises";import*as it from"path";import{spawn as Xi}from"child_process";import{Readable as Af}from"stream";function Ue(){let s=process.platform==="darwin"?"darwin":process.platform==="linux"?"linux":process.platform==="win32"?"windows":void 0,e=process.arch==="arm64"?"aarch64":process.arch==="x64"?"x86_64":void 0;if(!(!s||!e))return`${s}-${e}`}function jr(s,e=Ue()){if(e)return s[e]}var $t=s=>{process.stderr.write(s+`
10
- `)};function Lr(s){$t=s??(e=>process.stderr.write(e+`
11
- `))}async function Zi(s){if(!s.target.archive)throw new Error(`Agent ${s.agentId} has no archive URL for ${Ue()??"this platform"}`);if(!s.target.cmd)throw new Error(`Agent ${s.agentId} has no cmd in its binary target`);let e=Ue();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=T.agentInstallDir(s.agentId,e,s.version),n=it.resolve(t,s.target.cmd);if(await Hr(n))return n;if(await Cf({agentId:s.agentId,version:s.version,archiveUrl:s.target.archive,installDir:t,onProgress:s.onProgress}),!await Hr(n))throw new Error(`Agent ${s.agentId}: extracted archive did not contain ${s.target.cmd} (looked in ${t})`);return process.platform!=="win32"&&await ke.chmod(n,493).catch(()=>{}),n}async function Cf(s){await ke.mkdir(it.dirname(s.installDir),{recursive:!0});let e=await ke.mkdtemp(`${s.installDir}.partial-`);try{$t(`hydra-acp: downloading ${s.agentId} from ${s.archiveUrl}`);let t=await Rf({url:s.archiveUrl,dir:e,agentId:s.agentId,version:s.version,onProgress:s.onProgress});$t(`hydra-acp: extracting ${s.agentId}`),Ot(s.onProgress,{phase:"extract",agentId:s.agentId,version:s.version}),await Ef(t,e),await ke.unlink(t).catch(()=>{});try{await ke.rename(e,s.installDir)}catch(n){let r=n;if((r.code==="EEXIST"||r.code==="ENOTEMPTY")&&await Hr(s.installDir)){await ke.rm(e,{recursive:!0,force:!0}).catch(()=>{}),Ot(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw n}$t(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),Ot(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await ke.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function Ot(s,e){if(s)try{s(e)}catch{}}async function Rf(s){let e=xf(s.url),t=it.join(s.dir,e),n=await fetch(s.url,{redirect:"follow"});if(!n.ok||!n.body)throw new Error(`Failed to download ${s.url}: HTTP ${n.status} ${n.statusText}`);let r=Number(n.headers.get("content-length")??"0"),o=Yi.createWriteStream(t),i=Af.fromWeb(n.body);Ot(s.onProgress,{phase:"download_start",agentId:s.agentId,version:s.version,totalBytes:r});let a=0,d=Date.now(),c=0,u=2e3,l=150;return i.on("data",p=>{a+=p.length;let f=Date.now();f-c>=l&&(c=f,Ot(s.onProgress,{phase:"download_progress",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r})),f-d>=u&&(d=f,$t(Qi(s.agentId,a,r)))}),await new Promise((p,f)=>{i.on("error",f),o.on("error",f),o.on("finish",()=>p()),i.pipe(o)}),$t(Qi(s.agentId,a,r,!0)),Ot(s.onProgress,{phase:"download_done",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r}),t}function Qi(s,e,t,n=!1){let r=(e/1e6).toFixed(1);if(t>0){let i=(t/1e6).toFixed(1),a=Math.min(100,Math.floor(e/t*100));return`hydra-acp: ${n?"downloaded":"downloading"} ${s} ${r}/${i} MB (${a}%)`}return`hydra-acp: ${n?"downloaded":"downloading"} ${s} ${r} MB`}function xf(s){let e=new URL(s);return it.posix.basename(e.pathname)||"archive"}async function Ef(s,e){let t=s.toLowerCase();if(t.endsWith(".tar.gz")||t.endsWith(".tgz")||t.endsWith(".tar")){await Dr("tar",["-xf",s,"-C",e]);return}if(t.endsWith(".zip")){if(await Tf("unzip")){await Dr("unzip",["-q",s,"-d",e]);return}await Dr("tar",["-xf",s,"-C",e]);return}throw new Error(`Unsupported archive format: ${s}`)}function Dr(s,e){return new Promise((t,n)=>{let r=Xi(s,e,{stdio:["ignore","ignore","inherit"]});r.on("error",n),r.on("exit",(o,i)=>{if(o===0){t();return}n(new Error(`${s} ${e.join(" ")} exited with ${o!==null?`code ${o}`:`signal ${i}`}`))})})}async function Tf(s){return new Promise(e=>{let t=process.platform==="win32"?"where":"which",n=Xi(t,[s],{stdio:"ignore"});n.on("error",()=>e(!1)),n.on("exit",r=>e(r===0))})}async function Hr(s){try{return await ke.access(s),!0}catch{return!1}}Y();import*as ve from"fs/promises";import*as Fe from"path";import{delimiter as Hf}from"path";import{spawn as jf}from"child_process";import{statSync as Pf}from"fs";import{delimiter as Mf,join as _f}from"path";var $f=".COM;.EXE;.BAT;.CMD";function ea(s){try{return Pf(s).isFile()}catch{return!1}}function Of(s){let e=(s.PATHEXT??$f).split(";").map(n=>n.trim()).filter(n=>n.length>0),t=[];for(let n of e)for(let r of[n,n.toLowerCase(),n.toUpperCase()])t.includes(r)||t.push(r);return t}function Ff(s,e){let t=s.toLowerCase();return e.some(n=>t.endsWith(n.toLowerCase()))}function Nf(s,e={}){if((e.platform??process.platform)!=="win32")return s;let n=e.env??process.env,r=Of(n);if(Ff(s,r))return s;if(/[\\/]/.test(s)){for(let i of r){let a=s+i;if(ea(a))return a}return s}let o=n.PATH??n.Path??"";for(let i of o.split(Mf).filter(a=>a.length>0))for(let a of r){let d=_f(i,s+a);if(ea(d))return d}return s}var Df=/["%\r\n]/;function ta(s){if(Df.test(s))throw new Error(`cannot pass ${JSON.stringify(s)} through cmd.exe: it contains a quote, a percent sign, or a newline, none of which can be escaped unambiguously`);return/[\s&|<>^()]/.test(s)?`"${s}"`:s}function Ft(s,e,t={}){let n=t.platform??process.platform,r=Nf(s,t);return n!=="win32"||!/\.(cmd|bat)$/i.test(r)?{command:r,args:[...e],shell:!1}:{command:ta(r),args:e.map(ta),shell:!0}}var Br=s=>{process.stderr.write(s+`
12
- `)};function Wr(s){Br=s??(e=>process.stderr.write(e+`
13
- `))}async function sa(s){let e=Ue();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=T.agentNpmInstallDir(s.agentId,e,s.version),n=qf(s.packageSpec),r=zf(n),o={installDir:t,packageName:n,hint:s.bin,basename:r},i=Fe.join(t,"node_modules",".bin",s.bin);if(await vt(i))return i;if(await vt(t)){let l=await na(o);if(l)return l.binPath}await Lf({agentId:s.agentId,version:s.version,packageSpec:s.packageSpec,installDir:t,registry:s.registry,onProgress:s.onProgress});let a=await na(o);if(a)return a.binPath;let d=await oa(t,n),c=typeof d=="object"&&d!==null?Object.keys(d):typeof d=="string"?[r]:[],u=c.length>0?` (package declares bins: ${c.join(", ")})`:"";throw new Error(`Agent ${s.agentId}: npm install of ${s.packageSpec} did not produce bin ${s.bin} (looked in ${t}/node_modules/.bin/)${u}`)}async function Lf(s){await ve.mkdir(Fe.dirname(s.installDir),{recursive:!0});let e=await ve.mkdtemp(`${s.installDir}.partial-`);try{Br(`hydra-acp: installing ${s.packageSpec} for ${s.agentId} into ${e}`),Ur(s.onProgress,{phase:"install_start",agentId:s.agentId,version:s.version,packageSpec:s.packageSpec}),await ve.writeFile(Fe.join(e,"package.json"),`{"private":true}
14
- `),await Wf({packageSpec:s.packageSpec,cwd:e,registry:s.registry});try{await ve.rename(e,s.installDir)}catch(t){let n=t;if((n.code==="EEXIST"||n.code==="ENOTEMPTY")&&await vt(s.installDir)){await ve.rm(e,{recursive:!0,force:!0}).catch(()=>{}),Ur(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw t}Br(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),Ur(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await ve.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function Ur(s,e){if(s)try{s(e)}catch{}}var Uf=5,Bf=25;function Wf(s){return ra(s,0)}async function ra(s,e){try{await new Promise((t,n)=>{let r=s.registry?["--registry",s.registry]:[],o=Ft("npm",["install","--no-audit","--no-fund","--silent",...r,s.packageSpec]),i;try{i=jf(o.command,o.args,{cwd:s.cwd,stdio:["ignore","pipe","pipe"],shell:o.shell,windowsHide:!0})}catch(d){n(d);return}let a="";i.stdout?.on("data",d=>{}),i.stderr?.setEncoding("utf8"),i.stderr?.on("data",d=>{a=(a+d).slice(-4096)}),i.on("error",d=>{if(d.code==="ENOENT"){let u=(process.env.PATH??process.env.Path??"").split(Hf).filter(l=>l.length>0);n(new Error(`npm not found on PATH: tried to run ${JSON.stringify(o.command)}${o.shell?" through a shell":""} against ${u.length} PATH entries. Install Node.js / npm, or use a binary-distributed agent.`));return}n(d)}),i.on("exit",(d,c)=>{if(d===0){t();return}let u=d!==null?`exit code ${d}`:`signal ${c??"unknown"}`,l=a.trim();n(new Error(l?`npm install ${s.packageSpec} failed (${u})
15
- stderr: ${l}`:`npm install ${s.packageSpec} failed (${u})`))})})}catch(t){if(t.code==="ETXTBSY"&&e<Uf)return await new Promise(r=>setTimeout(r,Bf*(e+1))),ra(s,e+1);throw t}}function qf(s){if(s.startsWith("@")){let t=s.indexOf("/");if(t===-1)return s;let r=s.slice(t+1).indexOf("@");return r===-1?s:s.slice(0,t+1+r)}let e=s.indexOf("@");return e<=0?s:s.slice(0,e)}function zf(s){let e=s.lastIndexOf("/");return e===-1?s:s.slice(e+1)}async function oa(s,e){let t=Fe.join(s,"node_modules",e,"package.json");try{let n=await ve.readFile(t,"utf8"),r=JSON.parse(n);return typeof r.bin=="string"||typeof r.bin=="object"&&r.bin!==null&&!Array.isArray(r.bin)?r.bin:void 0}catch{return}}async function na(s){let e=Fe.join(s.installDir,"node_modules",".bin"),t=Fe.join(e,s.hint);if(await vt(t))return{binName:s.hint,binPath:t};let n=await oa(s.installDir,s.packageName);if(typeof n=="object"&&n!==null){let r=Object.keys(n);if(r.length===1){let o=r[0],i=Fe.join(e,o);if(await vt(i))return{binName:o,binPath:i}}else if(r.length>1){for(let o of[s.hint,s.basename])if(r.includes(o)){let i=Fe.join(e,o);if(await vt(i))return{binName:o,binPath:i}}}}if(s.basename!==s.hint){let r=Fe.join(e,s.basename);if(await vt(r))return{binName:s.basename,binPath:r}}}async function vt(s){try{return await ve.access(s),!0}catch{return!1}}var Jf=j.object({package:j.string(),bin:j.string().optional(),args:j.array(j.string()).optional(),env:j.record(j.string()).optional()}),Nt=j.object({archive:j.string().url().optional(),cmd:j.string().optional(),args:j.array(j.string()).optional(),env:j.record(j.string()).optional()}),Vf=j.object({"darwin-aarch64":Nt.optional(),"darwin-x86_64":Nt.optional(),"linux-aarch64":Nt.optional(),"linux-x86_64":Nt.optional(),"windows-x86_64":Nt.optional(),"windows-aarch64":Nt.optional()}),Gf=j.object({package:j.string(),args:j.array(j.string()).optional(),env:j.record(j.string()).optional()}),Kf=j.object({command:j.string(),args:j.array(j.string()).optional(),env:j.record(j.string()).optional()}),Qf=j.object({command:j.string().optional(),url:j.string().optional(),description:j.string().optional()}),Yf=j.object({npx:Jf.optional(),binary:Vf.optional(),uvx:Gf.optional(),exec:Kf.optional()}),Xf=j.object({id:j.string(),name:j.string(),version:j.string().optional(),description:j.string().optional(),authors:j.array(j.string()).optional(),license:j.string().optional(),icon:j.string().optional(),repository:j.string().optional(),website:j.string().optional(),distribution:Yf,onboarding:Qf.optional(),requiredEnv:j.array(j.string().min(1)).optional()}),ia=8;function ua(s){return s.installId??s.id}function zr(s){let e=s.extendsChain;return e&&e.length>0?e[e.length-1]:s.id}function Jr(s,e){if(s)for(let t of e.extendsChain??[e.id]){let n=s[t];if(n!==void 0)return{value:n,from:t}}}function la(s,e){if(!s)return;let t,n;for(let r of[...e.extendsChain??[e.id]].reverse()){let o=s[r];o!==void 0&&(t={...t,...o},n=r)}return t!==void 0&&n!==void 0?{value:t,from:n}:void 0}var aa=j.object({version:j.string(),agents:j.array(Xf),extensions:j.array(j.unknown()).optional()}),rs=class{constructor(e,t={}){this.config=e;this.options=t}config;options;cache;async load(){if(this.cache&&(this.isPinned()||this.isFresh(this.cache.fetchedAt)))return this.cache.data;let e=await this.readDiskCache();if(e&&(this.isPinned()||this.isFresh(e.fetchedAt)))return this.cache=e,e.data;try{let t=await this.fetchFromNetwork();return this.cache=t,await this.writeDiskCache(t),t.data}catch(t){if(e){let n=this.options.onStaleFallback;if(n)try{n(t,Date.now()-e.fetchedAt)}catch{}return this.cache=e,e.data}throw t}}async refresh(){let e=await this.fetchFromNetwork();return this.cache=e,await this.writeDiskCache(e),e.data}lastFetchedAt(){return this.cache?.fetchedAt}setConfig(e){this.config=e}async getAgent(e){return this.resolveAgent(e,[])}async resolveAgent(e,t){let n=this.findLocalDef(e);if(n){if(n.def.extends===void 0)return{...qr(n.id,n.def),extendsChain:[n.id]};if(t.includes(n.id))throw new Error(`agent ${n.id}: extends cycle (${[...t,n.id].join(" -> ")})`);if(t.length+1>=ia)throw new Error(`agent ${n.id}: extends chain deeper than ${ia} (${[...t,n.id].join(" -> ")})`);let c=await this.resolveAgent(n.def.extends,[...t,n.id]);if(!c)throw new Error(`agent ${n.id}: extends ${JSON.stringify(n.def.extends)}, which is not a known agent`);return this.applyOverride(ep(n.id,n.def,c))}let r=await this.load(),o=r.agents.find(c=>c.id===e);if(o)return this.applyOverride(o);let i=r.agents.find(c=>Vr(c)===e);if(i)return this.applyOverride(i);let a=e.toLowerCase(),d=r.agents.find(c=>c.id.toLowerCase()===`${a}-acp`);if(d)return this.applyOverride(d);if(a.length>0){let c=r.agents.filter(u=>u.id.toLowerCase().startsWith(a));if(c.length===1)return this.applyOverride(c[0])}}findLocalDef(e){let t=this.config.agents??{},n=t[e];if(n)return{id:e,def:n};let r=e.toLowerCase();for(let[o,i]of Object.entries(t))if(o.toLowerCase()===`${r}-acp`)return{id:o,def:i}}localAgents(){return Object.entries(this.config.agents??{}).filter(([,e])=>e.extends===void 0).map(([e,t])=>qr(e,t))}async resolvedLocalAgents(){let e=[];for(let t of Object.keys(this.config.agents??{}))try{let n=await this.resolveAgent(t,[]);n&&e.push(n)}catch(n){this.options.onResolveError?.(t,n)}return e}applyOverride(e){let t=e.extendsChain?e:{...e,extendsChain:[e.id]},n=this.config.agentOverrides?.[t.id];if(!n)return t;let r=t.distribution,o=t.version,i=t.installId;return n.packageSpec&&r.npx&&(o=tp(n.packageSpec),i=t.id,r={...r,npx:{...r.npx,package:n.packageSpec}}),n.extraArgs?.length&&(r=Zf(r,n.extraArgs)),n.env&&Object.keys(n.env).length>0&&(r=pa(r,{env:n.env})),r===t.distribution?t:{...t,version:o,installId:i,distribution:r}}isPinned(){return this.config.registry?.pinned===!0}isFresh(e){let t=Date.now()-e,n=this.config.registry.ttlHours*60*60*1e3;return t<n}async fetchFromNetwork(){let e=await fetch(this.config.registry.url);if(!e.ok)throw new Error(`Registry fetch failed: HTTP ${e.status}`);let t=await e.json(),n=aa.parse(t),r={fetchedAt:Date.now(),raw:t,data:n},o=this.options.onFetched;return o&&Promise.resolve().then(()=>o(n)).catch(()=>{}),r}async readDiskCache(){let e=await de(T.registryCache());if(!(!e||typeof e.fetchedAt!="number"||e.data===void 0))try{let t=aa.parse(e.data);return{fetchedAt:e.fetchedAt,raw:e.data,data:t}}catch{return}}async writeDiskCache(e){await me(T.registryCache(),{fetchedAt:e.fetchedAt,data:e.raw})}};function fa(s){return s&&Object.fromEntries(Object.entries(s).map(([e,t])=>[e,ce(t)]))}function qr(s,e){return{id:s,name:e.name??s,description:e.description,version:"local",distribution:{exec:{command:ce(e.command??s),args:e.args?.map(ce),env:fa(e.env)}}}}function pa(s,e){let t=e.args?.map(ce),n=fa(e.env),r=o=>({...o,...t?{args:t}:{},...n?{env:{...o.env,...n}}:{}});return{...s.npx?{npx:r(s.npx)}:{},...s.uvx?{uvx:r(s.uvx)}:{},...s.exec?{exec:r(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([o,i])=>[o,i&&r(i)]))}:{}}}function Zf(s,e){let t=n=>({...n,args:[...n.args??[],...e]});return{...s.npx?{npx:t(s.npx)}:{},...s.uvx?{uvx:t(s.uvx)}:{},...s.exec?{exec:t(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([n,r])=>[n,r&&t(r)]))}:{}}}function ep(s,e,t){let n=e.command!==void 0;return{...t,id:s,name:e.name??t.name,description:e.description??t.description,version:n?"local":t.version,distribution:n?qr(s,e).distribution:pa(t.distribution,e),installId:n?s:t.installId??t.id,extendsChain:[s,...t.extendsChain??[t.id]]}}function tp(s){let e=s.lastIndexOf("@"),n=(e>0?s.slice(e+1):"").replace(/[^a-zA-Z0-9._-]/g,"_");return n.length>0?`pin-${n}`:"pinned"}function Vr(s){let e=s.distribution.npx?.package;if(!e)return;let t=e.lastIndexOf("/"),n=t===-1?e:e.slice(t+1),r=n.lastIndexOf("@");return r<=0?n:n.slice(0,r)}async function Dt(s){let e=typeof s.resolvedLocalAgents=="function"?await s.resolvedLocalAgents():typeof s.localAgents=="function"?s.localAgents():[],t;try{t=await s.load()}catch(i){if(e.length===0)throw i;t={version:"local-only",agents:[]}}let n=new Set(e.map(i=>i.id)),r=[...e,...t.agents.filter(i=>!n.has(i.id))],o=await Promise.all(r.map(async i=>({id:i.id,name:i.name,version:i.version,description:i.description,distributions:Object.keys(i.distribution),installed:await Gr(i),...i.extendsChain?{extendsChain:i.extendsChain}:{},source:n.has(i.id)?"local":"registry",...i.onboarding?{onboarding:i.onboarding}:{}})));return{version:t.version,fetchedAt:s.lastFetchedAt(),agents:o}}async function Gr(s){let e=Ue();if(!e)return"no";let t=s.version??"current",n=ua(s);if(s.distribution.exec)return"yes";if(s.distribution.binary){let r=jr(s.distribution.binary,e);if(r?.cmd){let o=os.resolve(T.agentInstallDir(n,e,t),r.cmd);if(await da(o))return"yes"}}if(s.distribution.npx){let r=s.distribution.npx,o=r.bin??Vr(s)??r.package,i=T.agentNpmInstallDir(n,e,t),a=os.join(i,"node_modules",".bin",o);if(await da(a))return"yes"}return!s.distribution.npx&&!s.distribution.binary&&s.distribution.uvx?"lazy":"no"}async function da(s){try{return await ca.access(s),!0}catch{return!1}}async function _e(s,e=[],t={}){let n=s.version??"current",r=ua(s);if(s.distribution.npx){let o=s.distribution.npx,i=e.length>0?e:o.args??[];if(process.env.HYDRA_ACP_SKIP_NPM_PREFETCH)return{command:"npx",args:["-y",o.package,...i],env:o.env??{},version:n,installId:r};let a=o.bin??Vr(s)??o.package,d=t.onInstallProgress;return{command:await sa({agentId:r,version:n,packageSpec:o.package,bin:a,registry:t.npmRegistry,onProgress:d?u=>d({source:"npm",...u}):void 0}),args:i,env:o.env??{},version:n,installId:r}}if(s.distribution.binary){let o=jr(s.distribution.binary);if(!o)throw new Error(`Agent ${s.id} has no binary distribution for ${Ue()??"this platform"}.`);let i=t.onInstallProgress,a=await Zi({agentId:r,version:n,target:o,onProgress:i?c=>i({source:"binary",...c}):void 0}),d=e.length>0?e:o.args??[];return{command:a,args:d,env:o.env??{},version:n,installId:r}}if(s.distribution.uvx){let o=s.distribution.uvx,i=e.length>0?e:o.args??[];return{command:"uvx",args:[o.package,...i],env:o.env??{},version:n,installId:r}}if(s.distribution.exec){let o=s.distribution.exec,i=e.length>0?e:o.args??[];return{command:o.command,args:i,env:o.env??{},version:n,installId:r}}throw new Error(`Agent ${s.id} has no usable distribution method.`)}import{spawn as ip,spawnSync as ap}from"child_process";import*as ds from"fs";import*as Pa from"path";var x={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603,AuthRequired:-32e3,SessionNotFound:-32001,NotAuthorisedToAttach:-32002,MultiClientNotSupported:-32003,AgentNotInstalled:-32005,BundleAlreadyImported:-32010,PermissionDenied:-32011,AlreadyAttached:-32012,StreamNotEnabled:-32013,SessionClosing:-32014};import{z as X}from"zod";var ga=X.object({protocolVersion:X.number().optional(),clientCapabilities:X.record(X.unknown()).optional(),clientInfo:X.object({name:X.string(),version:X.string().optional()}).optional()}),np=X.enum(["full","pending_only","none","after_message"]),ma=X.object({cwd:X.string(),mcpServers:X.array(X.unknown()).optional(),_meta:X.record(X.unknown()).optional()}),ha=X.object({upstreamSessionId:X.string(),agentId:X.string(),cwd:X.string(),title:X.string().optional(),agentArgs:X.array(X.string()).optional()}),ya=X.object({sessionId:X.string(),historyPolicy:np.default("full"),afterMessageId:X.string().optional(),afterSeq:X.number().optional(),clientId:X.string().optional(),clientInfo:X.object({name:X.string(),version:X.string().optional()}).optional(),_meta:X.record(X.unknown()).optional()});import{z as hn}from"zod";var Ht=hn.object({selection:hn.object({text:hn.string().min(1),responsePartId:hn.string().optional()}).optional(),contextThroughSeq:hn.number().optional()});import{z as D}from"zod";var wa=D.object({sessionId:D.string()}),ka=D.object({cwd:D.string().optional(),cursor:D.string().optional()}),Kr=D.object({used:D.number().optional(),size:D.number().optional(),costAmount:D.number().optional(),costCurrency:D.string().optional()}),pv=D.object({sessionId:D.string(),upstreamSessionId:D.string().optional(),cwd:D.string(),workspace:D.object({path:D.string(),sourceCwd:D.string(),label:D.string(),provider:D.string(),snapshot:D.string().optional(),vcs:D.record(D.string(),D.string()).optional()}).optional(),workspaceError:D.string().optional(),title:D.string().optional(),agentId:D.string().optional(),currentModel:D.string().optional(),currentUsage:Kr.optional(),importedFromMachine:D.string().optional(),importedFromUpstreamSessionId:D.string().optional(),parentSessionId:D.string().optional(),forkedFromSessionId:D.string().optional(),forkedFromMessageId:D.string().optional(),side:Ht.optional(),originatingClient:D.object({name:D.string(),version:D.string().optional()}).optional(),interactive:D.boolean().optional(),priority:D.number().int().nonnegative().optional(),lastTurnEndedAt:D.number().optional(),readAt:D.number().optional(),unread:D.boolean().optional(),createdAt:D.string().optional(),updatedAt:D.string(),attachedClients:D.number().int().nonnegative(),status:D.enum(["warm","cold"]).default("warm"),busy:D.boolean().default(!1),awaitingInput:D.boolean().default(!1),turnStartedAt:D.number().optional(),armedTasks:D.number().int().nonnegative().optional(),armedSince:D.number().int().positive().optional(),compactionState:D.any().optional(),agentPid:D.number().int().positive().optional(),forkSynthesisState:D.enum(["running","failed"]).optional(),_meta:D.record(D.unknown()).optional()}),sp=D.object({sessionId:D.string(),cwd:D.string(),title:D.string().optional(),updatedAt:D.string().optional(),_meta:D.record(D.unknown()).optional()}),gv=D.object({sessions:D.array(sp),nextCursor:D.string().optional()});function is(s,e){let t={attachedClients:s.attachedClients,status:s.status,busy:s.busy,awaitingInput:s.awaitingInput};return s.cwd!==void 0&&(t.cwd=s.cwd),s.workspace!==void 0&&(t.workspaceInfo=s.workspace),s.workspaceError!==void 0&&(t.workspaceError=s.workspaceError),s.title!==void 0&&(t.title=s.title),s.agentId!==void 0&&(t.agentId=s.agentId),s.upstreamSessionId!==void 0&&(t.upstreamSessionId=s.upstreamSessionId),s.createdAt!==void 0&&(t.createdAt=s.createdAt),s.currentModel!==void 0&&(t.currentModel=s.currentModel),s.currentUsage!==void 0&&(t.currentUsage=s.currentUsage),s.importedFromMachine!==void 0&&(t.importedFromMachine=s.importedFromMachine),s.importedFromUpstreamSessionId!==void 0&&(t.importedFromUpstreamSessionId=s.importedFromUpstreamSessionId),s.parentSessionId!==void 0&&(t.parentSessionId=s.parentSessionId),s.forkedFromSessionId!==void 0&&(t.forkedFromSessionId=s.forkedFromSessionId),s.forkedFromMessageId!==void 0&&(t.forkedFromMessageId=s.forkedFromMessageId),s.side!==void 0&&(t.side=s.side),s.originatingClient!==void 0&&(t.originatingClient=s.originatingClient),s.interactive!==void 0&&(t.interactive=s.interactive),s.priority!==void 0&&s.priority>0&&(t.priority=s.priority),s.lastTurnEndedAt!==void 0&&(t.lastTurnEndedAt=s.lastTurnEndedAt),s.readAt!==void 0&&(t.readAt=s.readAt),s.unread&&(t.unread=!0),s.armedTasks!==void 0&&(t.armedTasks=s.armedTasks),s.armedSince!==void 0&&(t.armedSince=s.armedSince),s.compactionState!==void 0&&(t.compactionState=s.compactionState),s.forkSynthesisState!==void 0&&(t.forkSynthesisState=s.forkSynthesisState),e&&(e.clientId!==void 0&&(t.clientId=e.clientId),e.currentMode!==void 0&&(t.currentMode=e.currentMode),e.agentArgs!==void 0&&e.agentArgs.length>0&&(t.agentArgs=e.agentArgs),e.availableCommands!==void 0&&e.availableCommands.length>0&&(t.availableCommands=e.availableCommands),e.availableModes!==void 0&&e.availableModes.length>0&&(t.availableModes=e.availableModes),e.availableModels!==void 0&&e.availableModels.length>0&&(t.availableModels=e.availableModels),e.turnStartedAt!==void 0&&(t.turnStartedAt=e.turnStartedAt),e.agentCapabilities!==void 0&&(t.agentCapabilities=e.agentCapabilities),e.queue!==void 0&&e.queue.length>0&&(t.queue=e.queue),e.resurrected===!0&&(t.resurrected=!0),e.armedTaskList!==void 0&&(t.armedTaskList=e.armedTaskList)),t}function va(s){let e={sessionId:s.sessionId,cwd:s.cwd,updatedAt:s.updatedAt,_meta:yn(s._meta,is(s))};return s.title!==void 0&&(e.title=s.title),e}var le="hydra-acp";function rp(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e={};for(let[t,n]of Object.entries(s)){if(typeof t!="string"||t.length===0||typeof n!="string")return;e[t]=n}return e}function at(s){if(!s)return{};let e=s[le];if(!e||typeof e!="object"||Array.isArray(e))return{};let t=e,n={};if(typeof t.upstreamSessionId=="string"&&(n.upstreamSessionId=t.upstreamSessionId),typeof t.agentId=="string"&&(n.agentId=t.agentId),typeof t.cwd=="string"&&(n.cwd=t.cwd),t.workspace!==null&&typeof t.workspace=="object"&&!Array.isArray(t.workspace)){let o=t.workspace,i={};typeof o.label=="string"&&(i.label=o.label),typeof o.from=="string"&&(i.from=o.from),o.required===!0&&(i.required=!0),o.adopt===!0&&(i.adopt=!0),typeof o.provider=="string"&&(i.provider=o.provider),n.workspace=i}if(t.workspaceInfo!==null&&typeof t.workspaceInfo=="object"&&!Array.isArray(t.workspaceInfo)){let o=t.workspaceInfo;if(typeof o.path=="string"&&typeof o.sourceCwd=="string"&&typeof o.label=="string"&&typeof o.provider=="string"){let i={path:o.path,sourceCwd:o.sourceCwd,label:o.label,provider:o.provider};if(typeof o.snapshot=="string"&&(i.snapshot=o.snapshot),o.vcs!==null&&typeof o.vcs=="object"&&!Array.isArray(o.vcs)){let a={};for(let[d,c]of Object.entries(o.vcs))typeof c=="string"&&(a[d]=c);i.vcs=a}n.workspaceInfo=i}}if(typeof t.workspaceError=="string"&&(n.workspaceError=t.workspaceError),typeof t.clientId=="string"&&(n.clientId=t.clientId),typeof t.readonly=="boolean"&&(n.readonly=t.readonly),(t.replayMode==="instant"||t.replayMode==="drip")&&(n.replayMode=t.replayMode),typeof t.dripSpeed=="number"&&t.dripSpeed>0&&(n.dripSpeed=t.dripSpeed),typeof t.historyLimit=="number"&&Number.isFinite(t.historyLimit)&&t.historyLimit>=0&&(n.historyLimit=t.historyLimit),(t.toolContent==="inline"||t.toolContent==="references")&&(n.toolContent=t.toolContent),t.detachStatus==="detached"&&(n.detachStatus=t.detachStatus),typeof t.title=="string"&&(n.title=t.title),Array.isArray(t.agentArgs)&&t.agentArgs.every(o=>typeof o=="string")&&(n.agentArgs=t.agentArgs),Array.isArray(t.transformers)&&t.transformers.every(o=>typeof o=="string")&&(n.transformers=t.transformers),t.resume){let o=ha.safeParse(t.resume);o.success&&(n.resume=o.data)}if(typeof t.model=="string"&&(n.model=t.model),typeof t.currentModel=="string"&&(n.currentModel=t.currentModel),typeof t.currentMode=="string"&&(n.currentMode=t.currentMode),t.currentUsage){let o=Kr.safeParse(t.currentUsage);o.success&&(n.currentUsage=o.data)}if(typeof t.turnStartedAt=="number"&&t.turnStartedAt>0&&(n.turnStartedAt=t.turnStartedAt),typeof t.armedTasks=="number"&&t.armedTasks>=0&&(n.armedTasks=t.armedTasks),typeof t.armedSince=="number"&&t.armedSince>0&&(n.armedSince=t.armedSince),Array.isArray(t.armedTaskList)){let o=[];for(let i of t.armedTaskList){if(!i||typeof i!="object"||Array.isArray(i))continue;let a=i;typeof a.label!="string"||typeof a.since!="number"||o.push({label:a.label,since:a.since,...typeof a.taskId=="string"?{taskId:a.taskId}:{},...typeof a.taskType=="string"?{taskType:a.taskType}:{},...typeof a.toolCallId=="string"?{toolCallId:a.toolCallId}:{},...a.endUnobservable===!0?{endUnobservable:!0}:{}})}n.armedTaskList=o}if(Array.isArray(t.availableCommands)){let o=[];for(let i of t.availableCommands){if(!i||typeof i!="object"||Array.isArray(i))continue;let a=i;if(typeof a.name!="string")continue;let d={name:a.name};typeof a.description=="string"&&(d.description=a.description),o.push(d)}o.length>0&&(n.availableCommands=o)}if(t.prompt&&typeof t.prompt=="object"&&!Array.isArray(t.prompt)){let o=t.prompt,i={};typeof o.queueing=="boolean"&&(i.queueing=o.queueing),typeof o.cancelling=="boolean"&&(i.cancelling=o.cancelling),typeof o.updating=="boolean"&&(i.updating=o.updating),typeof o.amending=="boolean"&&(i.amending=o.amending),typeof o.pipelining=="boolean"&&(i.pipelining=o.pipelining),n.prompt=i}if(t.agents&&typeof t.agents=="object"&&!Array.isArray(t.agents)){let o=t.agents,i={};typeof o.list=="boolean"&&(i.list=o.list),typeof o.installProgress=="boolean"&&(i.installProgress=o.installProgress),n.agents=i}if(typeof t.mcpStdin=="boolean"&&(n.mcpStdin=t.mcpStdin),typeof t.interactive=="boolean"&&(n.interactive=t.interactive),typeof t.ancillary=="boolean"&&(n.ancillary=t.ancillary),t.salvaged&&typeof t.salvaged=="object"&&!Array.isArray(t.salvaged)){let o=t.salvaged;typeof o.reason=="string"&&typeof o.supersededMessageId=="string"&&(n.salvaged={reason:o.reason,supersededMessageId:o.supersededMessageId})}if(Array.isArray(t.queue)){let o=[];for(let i of t.queue){if(!i||typeof i!="object"||Array.isArray(i))continue;let a=i,d=a.originator;if(typeof a.messageId!="string"||!d||typeof d.clientId!="string"||!Array.isArray(a.prompt)||typeof a.position!="number"||typeof a.enqueuedAt!="number")continue;let c={clientId:d.clientId};typeof d.name=="string"&&(c.name=d.name),typeof d.version=="string"&&(c.version=d.version),o.push({messageId:a.messageId,originator:c,prompt:a.prompt,position:a.position,enqueuedAt:a.enqueuedAt})}o.length>0&&(n.queue=o)}if(Array.isArray(t.availableModes)){let o=[];for(let i of t.availableModes){if(!i||typeof i!="object"||Array.isArray(i))continue;let a=i;if(typeof a.id!="string")continue;let d={id:a.id};typeof a.name=="string"&&(d.name=a.name),typeof a.description=="string"&&(d.description=a.description),o.push(d)}o.length>0&&(n.availableModes=o)}if(Array.isArray(t.availableModels)){let o=[];for(let i of t.availableModels){if(!i||typeof i!="object"||Array.isArray(i))continue;let a=i;if(typeof a.modelId!="string")continue;let d={modelId:a.modelId};typeof a.name=="string"&&(d.name=a.name),typeof a.description=="string"&&(d.description=a.description),o.push(d)}o.length>0&&(n.availableModels=o)}(t.status==="warm"||t.status==="cold")&&(n.status=t.status),typeof t.busy=="boolean"&&(n.busy=t.busy),typeof t.awaitingInput=="boolean"&&(n.awaitingInput=t.awaitingInput),typeof t.attachedClients=="number"&&(n.attachedClients=t.attachedClients),typeof t.resurrected=="boolean"&&(n.resurrected=t.resurrected),typeof t.importedFromMachine=="string"&&(n.importedFromMachine=t.importedFromMachine),typeof t.importedFromUpstreamSessionId=="string"&&(n.importedFromUpstreamSessionId=t.importedFromUpstreamSessionId),typeof t.parentSessionId=="string"&&(n.parentSessionId=t.parentSessionId),typeof t.forkedFromSessionId=="string"&&(n.forkedFromSessionId=t.forkedFromSessionId),typeof t.forkedFromMessageId=="string"&&(n.forkedFromMessageId=t.forkedFromMessageId);let r=Ht.safeParse(t.side);if(r.success&&(n.side=r.data),t.originatingClient&&typeof t.originatingClient=="object"&&!Array.isArray(t.originatingClient)&&typeof t.originatingClient.name=="string"){let o=t.originatingClient;n.originatingClient={name:o.name,...typeof o.version=="string"?{version:o.version}:{}}}if(t.agentCapabilities!==void 0&&(n.agentCapabilities=t.agentCapabilities),t.env!==void 0){let o=rp(t.env);o!==void 0&&(n.env=o)}return n}function Be(s,e){if(typeof e!="number"||!Number.isFinite(e)||!s||typeof s!="object"||Array.isArray(s))return s;let t=s,n=t._meta&&typeof t._meta=="object"&&!Array.isArray(t._meta)?t._meta:{},r=n[le],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.recordedAt=="number"?s:{...t,_meta:{...n,[le]:{...o,recordedAt:e}}}}function We(s,e){if(typeof e!="number"||!Number.isFinite(e)||!s||typeof s!="object"||Array.isArray(s))return s;let t=s,n=t._meta&&typeof t._meta=="object"&&!Array.isArray(t._meta)?t._meta:{},r=n[le],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.seq=="number"?s:{...t,_meta:{...n,[le]:{...o,seq:e}}}}function yn(s,e){return{...s??{},[le]:e}}import{z as _}from"zod";var ba=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.record(_.unknown()).optional()}),as=_.object({sessionId:_.string()}),Sa=_.object({clientId:_.string(),name:_.string().optional(),version:_.string().optional()}),bv=_.object({sessionId:_.string(),messageId:_.string(),originator:Sa,prompt:_.array(_.unknown()),position:_.number().int().nonnegative(),queueDepth:_.number().int().positive(),enqueuedAt:_.number()}),Sv=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),Iv=_.object({sessionId:_.string(),messageId:_.string(),reason:_.enum(["started","cancelled","abandoned"])}),Ia=_.object({sessionId:_.string(),messageId:_.string()}),Av=_.object({cancelled:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),Aa=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),Cv=_.object({updated:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),Ca=_.object({sessionId:_.string(),targetMessageId:_.string(),prompt:_.array(_.unknown()),replaceQueue:_.boolean().optional(),onTargetCompleted:_.enum(["reject","send_anyway"]).optional()}),Rv=_.object({amended:_.boolean(),reason:_.enum(["ok","target_completed","target_cancelled","target_not_found"]),messageId:_.string().optional()}),Ra=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.object({steering:_.object({idleBehavior:_.literal("promptRequired").optional()}).optional()}).optional()}),xv=_.object({outcome:_.enum(["injected","startedNewTurn","promptRequired","failed"]),reason:_.literal("noRunningTurn").optional(),detached:_.boolean().optional()}),Ev=_.object({sessionId:_.string(),cancelledMessageId:_.string(),newMessageId:_.string(),prompt:_.array(_.unknown()),originator:Sa,amendedAt:_.number()});import{z as dt}from"zod";var Mv=dt.object({agentId:dt.string(),version:dt.string(),source:dt.enum(["binary","npm"]),phase:dt.enum(["download_start","download_progress","download_done","extract","install_start","installed"]),receivedBytes:dt.number().optional(),totalBytes:dt.number().optional(),packageSpec:dt.string().optional()}),xa="hydra-acp/agents/install_progress",jt={auth:{terminal:!0},_meta:{"terminal-auth":!0}};function Ea(s,e){let t="",n=[],r=[],o=!1,i=a=>{if(!o){o=!0;for(let d of r)d(a)}};return s.setEncoding("utf8"),s.on("data",a=>{t+=a;let d=t.indexOf(`
16
- `);for(;d!==-1;){let c=t.slice(0,d).trim();if(t=t.slice(d+1),c.length>0)try{let u=JSON.parse(c);for(let l of n)l(u)}catch(u){for(let l of n)l({jsonrpc:"2.0",id:null,error:{code:x.ParseError,message:`Failed to parse ndjson line: ${u.message}`}})}d=t.indexOf(`
2
+ var Cl=Object.defineProperty;var ts=(s,e)=>()=>(s&&(e=s(s=0)),e);var Rl=(s,e)=>{for(var t in e)Cl(s,t,{get:e[t],enumerable:!0})};import*as U from"path";import*as Ar from"os";function $(s){let e=Ar.homedir();if(!e)return s;let t=o=>process.platform==="win32"?o.replace(/\\/g,"/").toLowerCase():o,n=t(e),r=t(s);return r===n?"~":r.startsWith(n+"/")?"~"+s.slice(e.length):s}function xl(){if(process.env.VITEST)return"vitest";if(process.versions.bun||typeof globalThis.Bun<"u")return"bun";if(process.env.JEST_WORKER_ID!==void 0)return"jest";if(process.env.NODE_TEST_CONTEXT!==void 0)return"node:test"}function Tl(s,e){Ti||U.isAbsolute(s)||(Ti=!0,process.stderr.write(`hydra-acp: ${Ei} is relative (${JSON.stringify(s)}); resolved against the current directory to ${e}. Processes started from elsewhere will use a different home and will not see each other's daemon. Set an absolute path.
3
+ `))}function z(){let s=process.env[Ei];if(s&&s.length>0){let t=U.resolve(s);return Tl(s,t),t}let e=xl();if(e)throw new Error(`HYDRA_ACP_HOME is unset under a test runner (${e}); refusing to fall back to ~/.hydra-acp. The harness must set HYDRA_ACP_HOME \u2014 vitest.setup.ts does this, but \`bun test\` bypasses the vitest config and does not. Run the suite with \`npx vitest run\`, not \`bun test\`.`);return U.join(Ar.homedir(),".hydra-acp")}var Ei,Ti,E,Y=ts(()=>{"use strict";Ei="HYDRA_ACP_HOME";Ti=!1;E={home:z,config:()=>U.join(z(),"config.json"),authToken:()=>U.join(z(),"auth-token"),remotes:()=>U.join(z(),"remotes.json"),peers:()=>U.join(z(),"peers.json"),tlsDir:()=>U.join(z(),"tls"),pidFile:()=>U.join(z(),"daemon.pid"),logFile:()=>U.join(z(),"daemon.log"),daemonBootLog:()=>U.join(z(),"daemon-boot.log"),currentLogFile:()=>U.join(z(),"current.log"),registryCache:()=>U.join(z(),"registry.json"),themesDir:()=>U.join(z(),"themes"),ttySessionDir:()=>U.join(z(),"tty"),ttySessionFile:s=>U.join(z(),"tty",s),agentsDir:()=>U.join(z(),"agents"),agentLogFile:s=>U.join(z(),"agents","logs",`${s}.log`),agentInstallDir:(s,e,t)=>U.join(z(),"agents",e,s,t),agentNpmInstallDir:(s,e,t)=>U.join(z(),"agents",e,s,t,`node${process.versions.modules}`),sessionsDir:()=>U.join(z(),"sessions"),sessionDir:s=>U.join(z(),"sessions",s),sessionFile:s=>U.join(z(),"sessions",s,"meta.json"),historyFile:s=>U.join(z(),"sessions",s,"history.jsonl"),historyArchiveFile:(s,e)=>U.join(z(),"sessions",s,`history.jsonl.${e}`),toolsDir:s=>U.join(z(),"sessions",s,"tools"),toolBlobFile:(s,e)=>U.join(z(),"sessions",s,"tools",e),queueFile:s=>U.join(z(),"sessions",s,"queue.ndjson"),tombstonesDir:()=>U.join(z(),"sessions",".tombstones"),tombstoneAgentDir:s=>U.join(z(),"sessions",".tombstones",encodeURIComponent(s)),tombstoneFile:(s,e)=>U.join(z(),"sessions",".tombstones",encodeURIComponent(s),encodeURIComponent(e)),extensionsDir:()=>U.join(z(),"extensions"),extensionLogDir:s=>U.join(z(),"extensions",s),extensionLogFile:s=>U.join(z(),"extensions",s,"current.log"),extensionPidFile:s=>U.join(z(),"extensions",s,"extension.pid"),transformersDir:()=>U.join(z(),"transformers"),transformerLogDir:s=>U.join(z(),"transformers",s),transformerLogFile:s=>U.join(z(),"transformers",s,"current.log"),transformerPidFile:s=>U.join(z(),"transformers",s,"transformer.pid"),transformerState:(s,e)=>U.join(z(),"sessions",s,"transformer-state",e),tuiHistoryFile:s=>U.join(z(),"sessions",s,"prompt-history"),globalTuiHistoryFile:()=>U.join(z(),"prompt-history"),tuiLogFile:()=>U.join(z(),"tui.log"),shimWireLogFile:()=>U.join(z(),"shim-wire.log")}});import*as ge from"fs/promises";import*as Mi from"fs";import*as Me from"path";import{randomBytes as Pl}from"crypto";async function me(s,e,t={}){let r=(t.pretty??!0?JSON.stringify(e,null,2):JSON.stringify(e))+`
4
+ `;await Ol(s,r,t)}async function $l(s,e,t={}){let n=t.rename??ge.rename,r=t.platform??process.platform,o=t.sleep??(i=>new Promise(a=>setTimeout(a,i)));for(let i=0;;i++)try{await n(s,e);return}catch(a){let d=a.code??"";if(!(r==="win32"&&Ml.has(d)&&i<_l-1))throw a;await o(10*(i+1))}}async function Ol(s,e,t={}){let n=await Fl(s),r=Me.dirname(n);await ge.mkdir(r,{recursive:!0});let o=`${n}.tmp-${process.pid}-${Nl()}`;try{let i={encoding:"utf8"};t.mode!==void 0&&(i.mode=t.mode),await ge.writeFile(o,e,i),await $l(o,n)}catch(i){throw await ge.unlink(o).catch(()=>{}),i}if(t.mode!==void 0)try{Mi.chmodSync(n,t.mode)}catch{}}async function Fl(s){let e;try{e=await ge.lstat(s)}catch(r){if(r.code==="ENOENT")return s;throw r}if(!e.isSymbolicLink())return s;let t=await ge.readlink(s),n=Me.isAbsolute(t)?t:Me.resolve(Me.dirname(s),t);try{let r=await ge.realpath(Me.dirname(n));return Me.join(r,Me.basename(n))}catch(r){if(r.code==="ENOENT")return n;throw r}}async function de(s){let e;try{e=await ge.readFile(s,"utf8")}catch(t){if(t.code==="ENOENT")return;throw t}if(e.trim().length!==0)try{return JSON.parse(e)}catch{return}}function Nl(){return Pl(4).toString("hex")}var Ml,_l,je=ts(()=>{"use strict";Ml=new Set(["EPERM","EACCES","EBUSY"]),_l=10});function gr(s,e){return`${s}:${e}`}var Lu=ts(()=>{"use strict";Y();je()});var Vu={};Rl(Vu,{_resetForTests:()=>aw,clearPin:()=>fi,fetchPeerFingerprint:()=>ow,formatFingerprint:()=>Bu,getPin:()=>sw,installGlobalTlsTrust:()=>mi,loadPinsFromPeerStore:()=>pi,loadPinsFromStore:()=>rw,setPin:()=>Qn,sha256Hex:()=>gi,wsTlsOptions:()=>hi});import{createHash as Yy}from"crypto";import*as Uu from"tls";import{Agent as Xy,Dispatcher as Zy,buildConnector as ew,getGlobalDispatcher as tw,setGlobalDispatcher as nw}from"undici";function Qn(s,e,t){Pt.set(gr(s,e),Wu(t))}function fi(s,e){Pt.delete(gr(s,e))}function sw(s,e){return Pt.get(gr(s,e))}function rw(s){Pt.clear();for(let e of s.list())e.entry.pinnedFingerprint&&Qn(e.host,e.port,e.entry.pinnedFingerprint)}function pi(s){for(let e of s.list())e.pinnedFingerprint&&Qn(e.host,e.port,e.pinnedFingerprint)}async function ow(s,e,t={}){let n=t.timeoutMs??1e4;return new Promise((r,o)=>{let i=Uu.connect({host:s,port:e,servername:s,rejectUnauthorized:!1,autoSelectFamily:!0}),a=!1,d=(u,l)=>{if(!a){a=!0,clearTimeout(c);try{i.destroy()}catch{}u?o(u):l&&r(l)}},c=setTimeout(()=>{d(new Error(`TLS connect to ${s}:${e} timed out`))},n);i.once("secureConnect",()=>{let u=i.getPeerCertificate(!1);if(!u||!u.raw){d(new Error(`${s}:${e} did not present a TLS certificate`));return}d(null,gi(u.raw))}),i.once("error",u=>d(u))})}function gi(s){return Yy("sha256").update(s).digest("hex")}function Bu(s){let e=Wu(s),t=e.match(/.{2}/g);return t?t.join(":"):e}function Wu(s){return s.replace(/:/g,"").toLowerCase()}function mi(){if(li)return;li=!0;let s=tw(),e=new Xy({connect:ew({rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(n,r)=>zu(n,r)})}),t=new Zy;t.dispatch=(n,r)=>{let o=iw(n.origin);return(o&&qu(o)?e:s).dispatch(n,r)},t.close=(()=>Promise.all([e.close(),s.close()]).then(()=>{})),t.destroy=(n=>Promise.all([e.destroy(n??null),s.destroy(n??null)]).then(()=>{})),nw(t)}function iw(s){if(!s)return null;try{return new URL(String(s)).hostname}catch{return null}}function qu(s){for(let e of Pt.keys())if(Ju(e)?.host===s)return!0;return!1}function zu(s,e){if(!e||!e.raw)return new Error(`TLS peer ${s} did not present a certificate`);let t=gi(e.raw);for(let[n,r]of Pt.entries()){let o=Ju(n);if(o&&o.host===s&&r===t)return}return new Error(`TLS pin mismatch for ${s} (cert sha256 ${Bu(t)})`)}function Ju(s){let e=s.lastIndexOf(":");if(e<0)return null;let t=s.slice(0,e),n=Number(s.slice(e+1));return Number.isInteger(n)?{host:t,port:n}:null}function hi(s){return qu(s)?{rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(e,t)=>zu(e,t)}:{autoSelectFamily:!0}}function aw(){Pt.clear(),li=!1}var Pt,li,Yn=ts(()=>{"use strict";Lu();Pt=new Map,li=!1});Y();import*as it from"fs/promises";import{homedir as $r}from"os";import{z as C}from"zod";Y();import*as _t from"fs/promises";function Cr(){let s=new Uint8Array(32);crypto.getRandomValues(s);let e="";for(let t of s)e+=t.toString(16).padStart(2,"0");return`hydra_token_${e}`}async function El(){try{let e=(await _t.readFile(E.authToken(),"utf8")).trim();return e.length>0?e:void 0}catch(s){if(s.code==="ENOENT")return;throw s}}async function Rr(s){await _t.mkdir(E.home(),{recursive:!0}),await _t.writeFile(E.authToken(),s+`
5
+ `,{encoding:"utf8",mode:384})}async function Pi(){let s=await El();if(s)return s;let e=Cr();return await Rr(e),process.stderr.write(`hydra-acp: initialized ${E.authToken()} with a fresh service token.
6
+ `),e}je();import*as $i from"fs/promises";import*as gn from"os";import*as Le from"path";var ne="read by the daemon, which loads config.json at startup",_i={daemon:{reload:"restart",overlay:"partial",overlayNote:"only changes which daemon this client dials; a daemon started from here still binds config.json's host/port. Use `home` for a separate daemon",nested:!0},agents:{reload:"live",overlay:"inert",overlayNote:ne},agentOverrides:{reload:"live",overlay:"inert",overlayNote:ne},registry:{reload:"live",overlay:"inert",overlayNote:ne},npmRegistry:{reload:"live",overlay:"inert",overlayNote:ne},defaultAgent:{reload:"live",overlay:"effective"},defaultCwd:{reload:"live",overlay:"effective"},sessionDefaults:{reload:"live",overlay:"partial",overlayNote:"applies to WS session/new and child_session/spawn; POST /v1/sessions has no model/mode/effort field to apply any of it to"},synopsisAgent:{reload:"warn",overlay:"inert",overlayNote:ne},synopsisModel:{reload:"warn",overlay:"inert",overlayNote:ne},compaction:{reload:"warn",overlay:"inert",overlayNote:ne},defaultTransformers:{reload:"warn",overlay:"inert",overlayNote:ne},disableWorkspaceSnapshots:{reload:"warn",overlay:"inert",overlayNote:ne},compressToolContent:{reload:"warn",overlay:"inert",overlayNote:ne},extensions:{reload:"warn",overlay:"inert",overlayNote:ne},transformers:{reload:"warn",overlay:"inert",overlayNote:ne},tui:{reload:"client",overlay:"effective"},sessionListColdLimit:{reload:"client",overlay:"effective"}},Dl={host:{reload:"restart",overlay:"inert"},port:{reload:"restart",overlay:"inert"},publicHost:{reload:"restart",overlay:"inert"},tls:{reload:"restart",overlay:"inert"},scrubEnv:{reload:"live",overlay:"inert",overlayNote:ne},logLevel:{reload:"warn",overlay:"inert",overlayNote:ne},sessionIdleTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:ne},backgroundTaskTracking:{reload:"warn",overlay:"inert",overlayNote:ne},nonInteractiveOrphanTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:ne},sessionHistoryMaxEntries:{reload:"warn",overlay:"inert",overlayNote:ne},sessionHistoryArchiveMaxBytes:{reload:"warn",overlay:"inert",overlayNote:ne},sessionHistoryArchiveTiers:{reload:"warn",overlay:"inert",overlayNote:ne},agentStderrTailBytes:{reload:"warn",overlay:"inert",overlayNote:ne},agentSyncIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:ne},sessionGcIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:ne},sessionGcMaxAgeDays:{reload:"warn",overlay:"inert",overlayNote:ne}};function xr(s){return _i[s]??{reload:"restart",overlay:"inert"}}function Tr(s){return Dl[s]??{reload:"restart",overlay:"inert"}}function Er(){let s=[];for(let[e,t]of Object.entries(_i))t.overlay!=="effective"&&s.push({key:e,effect:t.overlay,note:t.overlayNote??ne});return s}var Hl=".hydra-acp.json",Pr="home",jl=64,Sk=Er().map(s=>s.key);function Ll(s){return s==="~"?gn.homedir():s.startsWith("~/")?Le.join(gn.homedir(),s.slice(2)):s.startsWith("$HOME/")?Le.join(gn.homedir(),s.slice(6)):s}function Mr(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function _r(s,e){let t={...s};for(let[n,r]of Object.entries(e)){let o=t[n];t[n]=Mr(o)&&Mr(r)?_r(o,r):r}return t}async function Ul(s,e=gn.homedir()){let t=[],n=[],r=Le.resolve(e),o=Le.resolve(s);for(let i=0;i<jl;i+=1){let a=Le.join(o,Hl),d;try{d=await $i.readFile(a,"utf8")}catch{d=void 0}if(d!==void 0)try{let u=JSON.parse(d);Mr(u)?t.push({file:a,data:u}):n.push({file:a,key:"",message:"expected a JSON object; ignoring this file"})}catch(u){n.push({file:a,key:"",message:`is not valid JSON (${u.message}); ignoring this file`})}if(o===r)break;let c=Le.dirname(o);if(c===o)break;o=c}return t.reverse(),{layers:t,notices:n}}function Bl(s){let e=new Map(Er().map(n=>[n.key,n])),t=[];for(let n of s)for(let r of Object.keys(n.data)){let o=e.get(r);if(!o)continue;let i=o.effect==="partial"?`\`${r}\` ${o.note}`:`\`${r}\` is ${o.note}, so it has no effect in a directory config`;t.push({file:n.file,key:r,message:i})}return t}async function Wl(s=process.cwd()){let{layers:e,notices:t}=await Ul(s);t.push(...Bl(e));let n={};for(let i of e)n=_r(n,i.data);let r,o=n[Pr];return typeof o=="string"&&o.length>0?r=Le.resolve(Ll(o)):o!==void 0&&t.push({file:e[e.length-1].file,key:Pr,message:"`home` must be a non-empty string; ignoring it"}),delete n[Pr],{layers:e,notices:t,merged:n,...r!==void 0?{homeRequest:r}:{}}}function ql(s,e){let t=s[e];return typeof t=="string"&&t.length>0?t:void 0}function zl(s,e){let t=s[e];if(t===null||typeof t!="object"||Array.isArray(t))return;let n={};for(let[r,o]of Object.entries(t)){if(o===null||typeof o!="object"||Array.isArray(o))continue;let i={};for(let[a,d]of Object.entries(o))typeof d=="string"&&(i[a]=d);Object.keys(i).length>0&&(n[r]=i)}return Object.keys(n).length>0?n:void 0}async function mn(s){let e={};try{e=(await Wl(s)).merged}catch{return{}}let t=ql(e,"defaultAgent"),n=zl(e,"sessionDefaults");return{...t!==void 0?{agentId:t}:{},...n!==void 0?{configDefaults:n}:{}}}var Ni="https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",Jl=C.object({cert:C.string(),key:C.string()}),$t=55514,Vl=C.object({host:C.string().default("127.0.0.1"),port:C.number().int().positive().default($t),logLevel:C.enum(["debug","info","warn","error"]).default("info"),tls:Jl.optional(),sessionIdleTimeoutSeconds:C.number().int().nonnegative().default(3600),backgroundTaskTracking:C.boolean().optional(),nonInteractiveOrphanTimeoutSeconds:C.number().int().nonnegative().default(180),sessionHistoryMaxEntries:C.number().int().positive().default(1e4),sessionHistoryArchiveMaxBytes:C.number().int().nonnegative().default(1e7),sessionHistoryArchiveTiers:C.number().int().positive().default(10),agentStderrTailBytes:C.number().int().positive().default(4096),publicHost:C.string().optional(),agentSyncIntervalMinutes:C.number().nonnegative().default(60),scrubEnv:C.array(C.string()).default([]),sessionGcIntervalMinutes:C.number().nonnegative().default(60),sessionGcMaxAgeDays:C.number().positive().default(2)}),Gl=C.object({url:C.string().url().default(Ni),ttlHours:C.number().positive().default(24),pinned:C.boolean().default(!1)}),Kl=C.object({extends:C.string().optional(),name:C.string().optional(),description:C.string().optional(),command:C.string().optional(),args:C.array(C.string()).optional(),env:C.record(C.string()).optional()}),Ql=C.object({packageSpec:C.string().optional(),extraArgs:C.array(C.string()).optional(),env:C.record(C.string()).optional()}),Yl=C.enum(["enter","alt-enter","shift-enter","ctrl-enter","alt-b","alt-f","alt-n","alt-tab","shift-tab","tab","up","down","left","right","home","end","backspace","alt-backspace","delete","ctrl-a","ctrl-b","ctrl-c","ctrl-d","ctrl-e","ctrl-f","ctrl-g","ctrl-k","ctrl-l","ctrl-n","ctrl-o","ctrl-p","ctrl-q","ctrl-r","ctrl-s","ctrl-u","ctrl-v","ctrl-t","ctrl-w","ctrl-x","ctrl-x-ctrl-e","ctrl-y","ctrl-underscore","alt-underscore","escape"]),Xl=C.union([C.string(),C.object({field:C.string().optional(),text:C.string().optional(),script:C.string().optional(),refreshMs:C.number().int().positive().optional(),maxWidth:C.number().int().positive().optional(),minWidth:C.number().int().nonnegative().optional(),truncate:C.boolean().optional(),priority:C.number().optional(),prefix:C.string().optional(),suffix:C.string().optional(),separator:C.string().optional(),style:C.string().optional(),onClick:C.string().optional(),onDoubleClick:C.string().optional()}).strict()]),Zl=C.object({id:C.string().min(1),script:C.string().min(1),refreshMs:C.number().int().positive().optional(),title:C.string().optional(),cap:C.number().int().positive().optional()}).strict(),ef=C.union([C.string(),Zl]),Oi=C.array(Xl);function Or(s,e){return C.object({left:Oi.default(s),right:Oi.default(e)}).default({})}var tf=["status",{field:"elapsed",separator:" "},"sessionId","queued","scroll"],nf=["usage"],sf=[],rf=["helpHint"],of=["cwd","title"],af=["agentModel"],df=C.object({composer:C.object({top:Or(tf,nf),bottom:Or(sf,rf),hintTurns:C.number().int().nonnegative().nullable().default(3)}).default({}),sessionbar:Or(of,af),scriptRefreshMs:C.number().int().positive().default(5e3),readIdleSeconds:C.number().int().nonnegative().default(180),repaintThrottleMs:C.number().int().nonnegative().default(1e3),maxScrollbackLines:C.number().int().positive().default(1e4),mouse:C.boolean().default(!0),inAppSelection:C.boolean().optional(),selectionClipboard:C.enum(["primary","clipboard","both"]).default("both"),openFileCommand:C.union([C.string(),C.array(C.string())]).optional(),openFileInTerminal:C.boolean().optional(),logMaxBytes:C.number().int().positive().default(5*1024*1024),keyTrace:C.boolean().optional(),cwdColumnMaxWidth:C.number().int().positive().default(32),progressIndicator:C.boolean().default(!0),terminalHost:C.union([C.boolean(),C.enum(["auto","paseo","herdr","tmux"])]).default(!0),launcherModeWhenHosted:C.boolean().default(!1),skipPermissions:C.boolean().default(!1),defaultEnterAction:C.enum(["enqueue","amend"]).default("amend"),showThoughts:C.boolean().default(!0),ambiguousWidth:C.enum(["auto","narrow","wide"]).default("auto"),toolContent:C.enum(["inline","references"]).default("references"),diffContextLines:C.number().int().min(0).default(3),promptHistoryMaxEntries:C.number().int().positive().default(2e3),maxToolItems:C.number().int().nonnegative().default(5),maxPlanItems:C.number().int().nonnegative().default(5),sidebar:C.object({enabled:C.boolean().default(!0),width:C.number().int().positive().optional(),border:C.enum(["none","rule","frame"]).default("frame"),gadgets:C.array(ef).default(["activity","sessions","tasks","context","queue","todo","files","git","resources","info","tools"])}).default({}),showFileUpdates:C.enum(["none","edit","diff"]).default("edit"),sessionColumns:C.array(C.enum(["session","upstream","host","state","agent","model","age","cwd","title","cost"])).nonempty().optional(),defaultHost:C.string().min(1).default("remote:all"),hotkeys:C.record(Yl,C.object({command:C.union([C.string(),C.array(C.string())])})).default({}),theme:C.union([C.string(),C.record(C.string(),C.unknown())]).optional(),themeBackground:C.string().optional()}),Fi=C.string().min(1).regex(/^[A-Za-z0-9._-]+$/,"extension name must be filename-safe"),cf=C.object({command:C.array(C.string()).default([]),args:C.array(C.string()).default([]),env:C.record(C.string()).default({}),enabled:C.boolean().default(!0)}),uf=C.object({command:C.array(C.string()).default([]),args:C.array(C.string()).default([]),env:C.record(C.string()).default({}),enabled:C.boolean().default(!0)}),lf=C.object({daemon:Vl.default({}),registry:Gl.default({url:Ni,ttlHours:24,pinned:!1}),agents:C.record(C.string(),Kl).default({}),agentOverrides:C.record(C.string(),Ql).default({}),defaultAgent:C.string().default("opencode"),sessionDefaults:C.record(C.string(),C.record(C.string(),C.string())).default({}),synopsisAgent:C.string().optional(),synopsisModel:C.string().optional(),compaction:C.object({agent:C.string().optional(),model:C.string().optional(),tailK:C.number().int().nonnegative().default(20),maxIterations:C.number().int().positive().default(3),contextFraction:C.number().min(0).max(1).default(.5),hardCeilingFraction:C.number().min(0).max(1).default(.85),absoluteFallback:C.number().int().positive().default(2e5),idleBeforePromptMs:C.number().int().nonnegative().default(3e5),modelContextWindows:C.record(C.string(),C.number().int().positive()).default({})}).default({}),defaultCwd:C.string().default("~"),disableWorkspaceSnapshots:C.boolean().optional(),compressToolContent:C.boolean().default(!0),sessionListColdLimit:C.number().int().nonnegative().default(20),extensions:C.record(Fi,cf).default({}),transformers:C.record(Fi,uf).default({}),defaultTransformers:C.array(C.string()).default([]),npmRegistry:C.string().url().optional(),tui:df.default({})});function Di(s){return Object.entries(s.extensions).map(([e,t])=>({name:e,...t}))}function Hi(s){return Object.entries(s.transformers).map(([e,t])=>({name:e,...t}))}async function Fr(){return await ff(),await de(E.config())??{}}async function ff(){let s;try{s=await it.lstat(E.config())}catch(e){if(e.code==="ENOENT")return;throw e}if(s.isSymbolicLink())try{await it.stat(E.config())}catch(e){if(e.code!=="ENOENT")throw e;let t=await it.readlink(E.config()).catch(()=>"<unknown>");throw new Error(`config.json at ${E.config()} is a broken symlink (-> ${t}); its target is missing. Refusing to treat this as "no config" and overwrite it. Restore the target (e.g. decrypt/check out your dotfiles) or remove the dangling link.`)}}async function pf(){let s=await Fr(),e=s.daemon,t=e&&typeof e.authToken=="string"?e.authToken:void 0;if(!t)return;let n=!1;try{await it.access(E.authToken()),n=!0}catch(r){if(r.code!=="ENOENT")throw r}if(n)throw new Error(`Auth token present in both ${E.authToken()} and ${E.config()} (daemon.authToken). Remove daemon.authToken from config.json to resolve.`);await Rr(t),delete e.authToken,Object.keys(e).length===0&&delete s.daemon,await me(E.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated auth token from ${E.config()} to ${E.authToken()}.
7
+ `)}async function gf(){let s=await Fr(),e=s.defaultModels&&typeof s.defaultModels=="object"&&!Array.isArray(s.defaultModels)?s.defaultModels:void 0;if(!e)return;let t=s.sessionDefaults&&typeof s.sessionDefaults=="object"&&!Array.isArray(s.sessionDefaults)?s.sessionDefaults:{};for(let[n,r]of Object.entries(e)){if(typeof r!="string")continue;let o=t[n]&&typeof t[n]=="object"&&!Array.isArray(t[n])?t[n]:{};o.model===void 0&&(o.model=r),t[n]=o}s.sessionDefaults=t,delete s.defaultModels,await me(E.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated defaultModels to sessionDefaults in ${E.config()}.
8
+ `)}async function hn(){return await pf(),await gf(),lf.parse(await Fr())}function ce(s){return s==="~"||s==="$HOME"?$r():s.startsWith("~/")?$r()+s.slice(1):s.startsWith("$HOME/")?$r()+s.slice(5):s}Y();import*as tt from"fs/promises";import*as ji from"path";var mf=64*1024;async function Li(s){let e=E.daemonBootLog(),t=`[${new Date().toISOString()}] pid=${process.pid} ${s}
9
+ `;if(await tt.mkdir(ji.dirname(e),{recursive:!0}),await tt.stat(e).then(r=>r.size).catch(()=>0)>mf){await tt.writeFile(e,t,{encoding:"utf8",mode:384});return}await tt.appendFile(e,t,{encoding:"utf8",mode:384})}import*as wl from"fs";import*as Ze from"fs/promises";import*as kl from"net";import*as ln from"path";import*as vl from"tls";import ok from"fastify";import ik from"@fastify/websocket";var Ui="acp.v1";function Bi(s,e){return s.has(Ui)?Ui:!1}import hl from"pino";import ak from"pino-roll";var hf={herdr:["HERDR_PANE_ID","HERDR_TAB_ID","HERDR_WORKSPACE_ID","HERDR_STARTUP_CWD"],tmux:["TMUX_PANE"],zellij:["ZELLIJ_PANE_ID","ZELLIJ_SESSION_NAME"],wezterm:["WEZTERM_PANE"],kitty:["KITTY_WINDOW_ID"],screen:["STY"],iterm2:["ITERM_SESSION_ID"],paseo:["PASEO_TERMINAL_ID","PASEO_ACTIVITY_TOKEN"],hydra:["HYDRA_TAB_LABEL"]},Wi="HYDRA_ACP_SESSION",yf=[Wi],wf=[...Object.values(hf).flat(),...yf];function ns(s,e){return s?{...e??{},[Wi]:s}:e}var qi=[];function Nr(s){qi=s?[...s]:[]}function kf(s,e){return e.endsWith("*")?s.startsWith(e.slice(0,-1)):s===e}function vf(){return[...wf,...qi]}function ss(s=process.env){let e=vf(),t={};for(let[n,r]of Object.entries(s))r!==void 0&&(e.some(o=>kf(n,o))||(t[n]=r));return t}Y();import*as he from"fs/promises";import{createHash as bf}from"crypto";import{gzip as Sf,gunzip as If}from"zlib";import{promisify as zi}from"util";var Ji=zi(Sf),Af=zi(If),Vi=/^[A-Za-z0-9_-]+$/,Cf=/^[a-f0-9]{64}$/,Dr=!0;function Gi(s){Dr=s}function rs(s,e){return Vi.test(s)?e===void 0||Cf.test(e):!1}function os(s,e){return`${E.toolBlobFile(s,e)}.gz`}async function Hr(s,e){if(!rs(s))return null;let t=bf("sha256").update(e,"utf8").digest("hex"),n=os(s,t),r=E.toolBlobFile(s,t);for(let a of[n,r])try{return await he.access(a),t}catch{}await he.mkdir(E.toolsDir(s),{recursive:!0});let o=Dr?n:r,i=Dr?await Ji(Buffer.from(e,"utf8")):Buffer.from(e,"utf8");return await he.writeFile(o,i,{mode:384,flag:"wx"}).catch(async a=>{if(a.code!=="EEXIST")throw a}),t}async function yn(s,e){if(!rs(s,e))return null;try{let t=await he.readFile(os(s,e));return(await Af(t)).toString("utf8")}catch{}try{return await he.readFile(E.toolBlobFile(s,e),"utf8")}catch{return null}}async function Ki(s,e){if(!rs(s,e))return null;try{return await he.readFile(os(s,e))}catch{}try{let t=await he.readFile(E.toolBlobFile(s,e));return await Ji(t)}catch{return null}}async function Qi(s,e,t){if(!rs(s,e))return;let n=os(s,e);try{await he.access(n);return}catch{}await he.mkdir(E.toolsDir(s),{recursive:!0}),await he.writeFile(n,t,{mode:384,flag:"wx"}).catch(r=>{if(r.code!=="EEXIST")throw r})}async function Yi(s){Vi.test(s)&&await he.rm(E.toolsDir(s),{recursive:!0,force:!0}).catch(()=>{})}Y();import*as la from"fs/promises";import*as as from"path";import{z as j}from"zod";je();Y();import*as Zi from"fs";import*as ke from"fs/promises";import*as at from"path";import{spawn as ea}from"child_process";import{Readable as Rf}from"stream";function Ue(){let s=process.platform==="darwin"?"darwin":process.platform==="linux"?"linux":process.platform==="win32"?"windows":void 0,e=process.arch==="arm64"?"aarch64":process.arch==="x64"?"x86_64":void 0;if(!(!s||!e))return`${s}-${e}`}function Ur(s,e=Ue()){if(e)return s[e]}var Ot=s=>{process.stderr.write(s+`
10
+ `)};function Br(s){Ot=s??(e=>process.stderr.write(e+`
11
+ `))}async function ta(s){if(!s.target.archive)throw new Error(`Agent ${s.agentId} has no archive URL for ${Ue()??"this platform"}`);if(!s.target.cmd)throw new Error(`Agent ${s.agentId} has no cmd in its binary target`);let e=Ue();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=E.agentInstallDir(s.agentId,e,s.version),n=at.resolve(t,s.target.cmd);if(await Lr(n))return n;if(await xf({agentId:s.agentId,version:s.version,archiveUrl:s.target.archive,installDir:t,onProgress:s.onProgress}),!await Lr(n))throw new Error(`Agent ${s.agentId}: extracted archive did not contain ${s.target.cmd} (looked in ${t})`);return process.platform!=="win32"&&await ke.chmod(n,493).catch(()=>{}),n}async function xf(s){await ke.mkdir(at.dirname(s.installDir),{recursive:!0});let e=await ke.mkdtemp(`${s.installDir}.partial-`);try{Ot(`hydra-acp: downloading ${s.agentId} from ${s.archiveUrl}`);let t=await Tf({url:s.archiveUrl,dir:e,agentId:s.agentId,version:s.version,onProgress:s.onProgress});Ot(`hydra-acp: extracting ${s.agentId}`),Ft(s.onProgress,{phase:"extract",agentId:s.agentId,version:s.version}),await Pf(t,e),await ke.unlink(t).catch(()=>{});try{await ke.rename(e,s.installDir)}catch(n){let r=n;if((r.code==="EEXIST"||r.code==="ENOTEMPTY")&&await Lr(s.installDir)){await ke.rm(e,{recursive:!0,force:!0}).catch(()=>{}),Ft(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw n}Ot(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),Ft(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await ke.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function Ft(s,e){if(s)try{s(e)}catch{}}async function Tf(s){let e=Ef(s.url),t=at.join(s.dir,e),n=await fetch(s.url,{redirect:"follow"});if(!n.ok||!n.body)throw new Error(`Failed to download ${s.url}: HTTP ${n.status} ${n.statusText}`);let r=Number(n.headers.get("content-length")??"0"),o=Zi.createWriteStream(t),i=Rf.fromWeb(n.body);Ft(s.onProgress,{phase:"download_start",agentId:s.agentId,version:s.version,totalBytes:r});let a=0,d=Date.now(),c=0,u=2e3,l=150;return i.on("data",p=>{a+=p.length;let f=Date.now();f-c>=l&&(c=f,Ft(s.onProgress,{phase:"download_progress",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r})),f-d>=u&&(d=f,Ot(Xi(s.agentId,a,r)))}),await new Promise((p,f)=>{i.on("error",f),o.on("error",f),o.on("finish",()=>p()),i.pipe(o)}),Ot(Xi(s.agentId,a,r,!0)),Ft(s.onProgress,{phase:"download_done",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r}),t}function Xi(s,e,t,n=!1){let r=(e/1e6).toFixed(1);if(t>0){let i=(t/1e6).toFixed(1),a=Math.min(100,Math.floor(e/t*100));return`hydra-acp: ${n?"downloaded":"downloading"} ${s} ${r}/${i} MB (${a}%)`}return`hydra-acp: ${n?"downloaded":"downloading"} ${s} ${r} MB`}function Ef(s){let e=new URL(s);return at.posix.basename(e.pathname)||"archive"}async function Pf(s,e){let t=s.toLowerCase();if(t.endsWith(".tar.gz")||t.endsWith(".tgz")||t.endsWith(".tar")){await jr("tar",["-xf",s,"-C",e]);return}if(t.endsWith(".zip")){if(await Mf("unzip")){await jr("unzip",["-q",s,"-d",e]);return}await jr("tar",["-xf",s,"-C",e]);return}throw new Error(`Unsupported archive format: ${s}`)}function jr(s,e){return new Promise((t,n)=>{let r=ea(s,e,{stdio:["ignore","ignore","inherit"]});r.on("error",n),r.on("exit",(o,i)=>{if(o===0){t();return}n(new Error(`${s} ${e.join(" ")} exited with ${o!==null?`code ${o}`:`signal ${i}`}`))})})}async function Mf(s){return new Promise(e=>{let t=process.platform==="win32"?"where":"which",n=ea(t,[s],{stdio:"ignore"});n.on("error",()=>e(!1)),n.on("exit",r=>e(r===0))})}async function Lr(s){try{return await ke.access(s),!0}catch{return!1}}Y();import*as ve from"fs/promises";import*as Fe from"path";import{delimiter as Lf}from"path";import{spawn as Uf}from"child_process";import{statSync as _f}from"fs";import{delimiter as $f,join as Of}from"path";var Ff=".COM;.EXE;.BAT;.CMD";function na(s){try{return _f(s).isFile()}catch{return!1}}function Nf(s){let e=(s.PATHEXT??Ff).split(";").map(n=>n.trim()).filter(n=>n.length>0),t=[];for(let n of e)for(let r of[n,n.toLowerCase(),n.toUpperCase()])t.includes(r)||t.push(r);return t}function Df(s,e){let t=s.toLowerCase();return e.some(n=>t.endsWith(n.toLowerCase()))}function Hf(s,e={}){if((e.platform??process.platform)!=="win32")return s;let n=e.env??process.env,r=Nf(n);if(Df(s,r))return s;if(/[\\/]/.test(s)){for(let i of r){let a=s+i;if(na(a))return a}return s}let o=n.PATH??n.Path??"";for(let i of o.split($f).filter(a=>a.length>0))for(let a of r){let d=Of(i,s+a);if(na(d))return d}return s}var jf=/["%\r\n]/;function sa(s){if(jf.test(s))throw new Error(`cannot pass ${JSON.stringify(s)} through cmd.exe: it contains a quote, a percent sign, or a newline, none of which can be escaped unambiguously`);return/[\s&|<>^()]/.test(s)?`"${s}"`:s}function Nt(s,e,t={}){let n=t.platform??process.platform,r=Hf(s,t);return n!=="win32"||!/\.(cmd|bat)$/i.test(r)?{command:r,args:[...e],shell:!1}:{command:sa(r),args:e.map(sa),shell:!0}}var qr=s=>{process.stderr.write(s+`
12
+ `)};function zr(s){qr=s??(e=>process.stderr.write(e+`
13
+ `))}async function oa(s){let e=Ue();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=E.agentNpmInstallDir(s.agentId,e,s.version),n=Jf(s.packageSpec),r=Vf(n),o={installDir:t,packageName:n,hint:s.bin,basename:r},i=Fe.join(t,"node_modules",".bin",s.bin);if(await bt(i))return i;if(await bt(t)){let l=await ra(o);if(l)return l.binPath}await Bf({agentId:s.agentId,version:s.version,packageSpec:s.packageSpec,installDir:t,registry:s.registry,onProgress:s.onProgress});let a=await ra(o);if(a)return a.binPath;let d=await aa(t,n),c=typeof d=="object"&&d!==null?Object.keys(d):typeof d=="string"?[r]:[],u=c.length>0?` (package declares bins: ${c.join(", ")})`:"";throw new Error(`Agent ${s.agentId}: npm install of ${s.packageSpec} did not produce bin ${s.bin} (looked in ${t}/node_modules/.bin/)${u}`)}async function Bf(s){await ve.mkdir(Fe.dirname(s.installDir),{recursive:!0});let e=await ve.mkdtemp(`${s.installDir}.partial-`);try{qr(`hydra-acp: installing ${s.packageSpec} for ${s.agentId} into ${e}`),Wr(s.onProgress,{phase:"install_start",agentId:s.agentId,version:s.version,packageSpec:s.packageSpec}),await ve.writeFile(Fe.join(e,"package.json"),`{"private":true}
14
+ `),await zf({packageSpec:s.packageSpec,cwd:e,registry:s.registry});try{await ve.rename(e,s.installDir)}catch(t){let n=t;if((n.code==="EEXIST"||n.code==="ENOTEMPTY")&&await bt(s.installDir)){await ve.rm(e,{recursive:!0,force:!0}).catch(()=>{}),Wr(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw t}qr(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),Wr(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await ve.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function Wr(s,e){if(s)try{s(e)}catch{}}var Wf=5,qf=25;function zf(s){return ia(s,0)}async function ia(s,e){try{await new Promise((t,n)=>{let r=s.registry?["--registry",s.registry]:[],o=Nt("npm",["install","--no-audit","--no-fund","--silent",...r,s.packageSpec]),i;try{i=Uf(o.command,o.args,{cwd:s.cwd,stdio:["ignore","pipe","pipe"],shell:o.shell,windowsHide:!0})}catch(d){n(d);return}let a="";i.stdout?.on("data",d=>{}),i.stderr?.setEncoding("utf8"),i.stderr?.on("data",d=>{a=(a+d).slice(-4096)}),i.on("error",d=>{if(d.code==="ENOENT"){let u=(process.env.PATH??process.env.Path??"").split(Lf).filter(l=>l.length>0);n(new Error(`npm not found on PATH: tried to run ${JSON.stringify(o.command)}${o.shell?" through a shell":""} against ${u.length} PATH entries. Install Node.js / npm, or use a binary-distributed agent.`));return}n(d)}),i.on("exit",(d,c)=>{if(d===0){t();return}let u=d!==null?`exit code ${d}`:`signal ${c??"unknown"}`,l=a.trim();n(new Error(l?`npm install ${s.packageSpec} failed (${u})
15
+ stderr: ${l}`:`npm install ${s.packageSpec} failed (${u})`))})})}catch(t){if(t.code==="ETXTBSY"&&e<Wf)return await new Promise(r=>setTimeout(r,qf*(e+1))),ia(s,e+1);throw t}}function Jf(s){if(s.startsWith("@")){let t=s.indexOf("/");if(t===-1)return s;let r=s.slice(t+1).indexOf("@");return r===-1?s:s.slice(0,t+1+r)}let e=s.indexOf("@");return e<=0?s:s.slice(0,e)}function Vf(s){let e=s.lastIndexOf("/");return e===-1?s:s.slice(e+1)}async function aa(s,e){let t=Fe.join(s,"node_modules",e,"package.json");try{let n=await ve.readFile(t,"utf8"),r=JSON.parse(n);return typeof r.bin=="string"||typeof r.bin=="object"&&r.bin!==null&&!Array.isArray(r.bin)?r.bin:void 0}catch{return}}async function ra(s){let e=Fe.join(s.installDir,"node_modules",".bin"),t=Fe.join(e,s.hint);if(await bt(t))return{binName:s.hint,binPath:t};let n=await aa(s.installDir,s.packageName);if(typeof n=="object"&&n!==null){let r=Object.keys(n);if(r.length===1){let o=r[0],i=Fe.join(e,o);if(await bt(i))return{binName:o,binPath:i}}else if(r.length>1){for(let o of[s.hint,s.basename])if(r.includes(o)){let i=Fe.join(e,o);if(await bt(i))return{binName:o,binPath:i}}}}if(s.basename!==s.hint){let r=Fe.join(e,s.basename);if(await bt(r))return{binName:s.basename,binPath:r}}}async function bt(s){try{return await ve.access(s),!0}catch{return!1}}var Gf=j.object({package:j.string(),bin:j.string().optional(),args:j.array(j.string()).optional(),env:j.record(j.string()).optional()}),Dt=j.object({archive:j.string().url().optional(),cmd:j.string().optional(),args:j.array(j.string()).optional(),env:j.record(j.string()).optional()}),Kf=j.object({"darwin-aarch64":Dt.optional(),"darwin-x86_64":Dt.optional(),"linux-aarch64":Dt.optional(),"linux-x86_64":Dt.optional(),"windows-x86_64":Dt.optional(),"windows-aarch64":Dt.optional()}),Qf=j.object({package:j.string(),args:j.array(j.string()).optional(),env:j.record(j.string()).optional()}),Yf=j.object({command:j.string(),args:j.array(j.string()).optional(),env:j.record(j.string()).optional()}),Xf=j.object({command:j.string().optional(),url:j.string().optional(),description:j.string().optional()}),Zf=j.object({npx:Gf.optional(),binary:Kf.optional(),uvx:Qf.optional(),exec:Yf.optional()}),ep=j.object({id:j.string(),name:j.string(),version:j.string().optional(),description:j.string().optional(),authors:j.array(j.string()).optional(),license:j.string().optional(),icon:j.string().optional(),repository:j.string().optional(),website:j.string().optional(),distribution:Zf,onboarding:Xf.optional(),requiredEnv:j.array(j.string().min(1)).optional()}),da=8;function fa(s){return s.installId??s.id}function Vr(s){let e=s.extendsChain;return e&&e.length>0?e[e.length-1]:s.id}function Gr(s,e){if(s)for(let t of e.extendsChain??[e.id]){let n=s[t];if(n!==void 0)return{value:n,from:t}}}function pa(s,e){if(!s)return;let t,n;for(let r of[...e.extendsChain??[e.id]].reverse()){let o=s[r];o!==void 0&&(t={...t,...o},n=r)}return t!==void 0&&n!==void 0?{value:t,from:n}:void 0}var ca=j.object({version:j.string(),agents:j.array(ep),extensions:j.array(j.unknown()).optional()}),is=class{constructor(e,t={}){this.config=e;this.options=t}config;options;cache;async load(){if(this.cache&&(this.isPinned()||this.isFresh(this.cache.fetchedAt)))return this.cache.data;let e=await this.readDiskCache();if(e&&(this.isPinned()||this.isFresh(e.fetchedAt)))return this.cache=e,e.data;try{let t=await this.fetchFromNetwork();return this.cache=t,await this.writeDiskCache(t),t.data}catch(t){if(e){let n=this.options.onStaleFallback;if(n)try{n(t,Date.now()-e.fetchedAt)}catch{}return this.cache=e,e.data}throw t}}async refresh(){let e=await this.fetchFromNetwork();return this.cache=e,await this.writeDiskCache(e),e.data}lastFetchedAt(){return this.cache?.fetchedAt}setConfig(e){this.config=e}async getAgent(e){return this.resolveAgent(e,[])}async resolveAgent(e,t){let n=this.findLocalDef(e);if(n){if(n.def.extends===void 0)return{...Jr(n.id,n.def),extendsChain:[n.id]};if(t.includes(n.id))throw new Error(`agent ${n.id}: extends cycle (${[...t,n.id].join(" -> ")})`);if(t.length+1>=da)throw new Error(`agent ${n.id}: extends chain deeper than ${da} (${[...t,n.id].join(" -> ")})`);let c=await this.resolveAgent(n.def.extends,[...t,n.id]);if(!c)throw new Error(`agent ${n.id}: extends ${JSON.stringify(n.def.extends)}, which is not a known agent`);return this.applyOverride(np(n.id,n.def,c))}let r=await this.load(),o=r.agents.find(c=>c.id===e);if(o)return this.applyOverride(o);let i=r.agents.find(c=>Kr(c)===e);if(i)return this.applyOverride(i);let a=e.toLowerCase(),d=r.agents.find(c=>c.id.toLowerCase()===`${a}-acp`);if(d)return this.applyOverride(d);if(a.length>0){let c=r.agents.filter(u=>u.id.toLowerCase().startsWith(a));if(c.length===1)return this.applyOverride(c[0])}}findLocalDef(e){let t=this.config.agents??{},n=t[e];if(n)return{id:e,def:n};let r=e.toLowerCase();for(let[o,i]of Object.entries(t))if(o.toLowerCase()===`${r}-acp`)return{id:o,def:i}}localAgents(){return Object.entries(this.config.agents??{}).filter(([,e])=>e.extends===void 0).map(([e,t])=>Jr(e,t))}async resolvedLocalAgents(){let e=[];for(let t of Object.keys(this.config.agents??{}))try{let n=await this.resolveAgent(t,[]);n&&e.push(n)}catch(n){this.options.onResolveError?.(t,n)}return e}applyOverride(e){let t=e.extendsChain?e:{...e,extendsChain:[e.id]},n=this.config.agentOverrides?.[t.id];if(!n)return t;let r=t.distribution,o=t.version,i=t.installId;return n.packageSpec&&r.npx&&(o=sp(n.packageSpec),i=t.id,r={...r,npx:{...r.npx,package:n.packageSpec}}),n.extraArgs?.length&&(r=tp(r,n.extraArgs)),n.env&&Object.keys(n.env).length>0&&(r=ma(r,{env:n.env})),r===t.distribution?t:{...t,version:o,installId:i,distribution:r}}isPinned(){return this.config.registry?.pinned===!0}isFresh(e){let t=Date.now()-e,n=this.config.registry.ttlHours*60*60*1e3;return t<n}async fetchFromNetwork(){let e=await fetch(this.config.registry.url);if(!e.ok)throw new Error(`Registry fetch failed: HTTP ${e.status}`);let t=await e.json(),n=ca.parse(t),r={fetchedAt:Date.now(),raw:t,data:n},o=this.options.onFetched;return o&&Promise.resolve().then(()=>o(n)).catch(()=>{}),r}async readDiskCache(){let e=await de(E.registryCache());if(!(!e||typeof e.fetchedAt!="number"||e.data===void 0))try{let t=ca.parse(e.data);return{fetchedAt:e.fetchedAt,raw:e.data,data:t}}catch{return}}async writeDiskCache(e){await me(E.registryCache(),{fetchedAt:e.fetchedAt,data:e.raw})}};function ga(s){return s&&Object.fromEntries(Object.entries(s).map(([e,t])=>[e,ce(t)]))}function Jr(s,e){return{id:s,name:e.name??s,description:e.description,version:"local",distribution:{exec:{command:ce(e.command??s),args:e.args?.map(ce),env:ga(e.env)}}}}function ma(s,e){let t=e.args?.map(ce),n=ga(e.env),r=o=>({...o,...t?{args:t}:{},...n?{env:{...o.env,...n}}:{}});return{...s.npx?{npx:r(s.npx)}:{},...s.uvx?{uvx:r(s.uvx)}:{},...s.exec?{exec:r(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([o,i])=>[o,i&&r(i)]))}:{}}}function tp(s,e){let t=n=>({...n,args:[...n.args??[],...e]});return{...s.npx?{npx:t(s.npx)}:{},...s.uvx?{uvx:t(s.uvx)}:{},...s.exec?{exec:t(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([n,r])=>[n,r&&t(r)]))}:{}}}function np(s,e,t){let n=e.command!==void 0;return{...t,id:s,name:e.name??t.name,description:e.description??t.description,version:n?"local":t.version,distribution:n?Jr(s,e).distribution:ma(t.distribution,e),installId:n?s:t.installId??t.id,extendsChain:[s,...t.extendsChain??[t.id]]}}function sp(s){let e=s.lastIndexOf("@"),n=(e>0?s.slice(e+1):"").replace(/[^a-zA-Z0-9._-]/g,"_");return n.length>0?`pin-${n}`:"pinned"}function Kr(s){let e=s.distribution.npx?.package;if(!e)return;let t=e.lastIndexOf("/"),n=t===-1?e:e.slice(t+1),r=n.lastIndexOf("@");return r<=0?n:n.slice(0,r)}async function Ht(s){let e=typeof s.resolvedLocalAgents=="function"?await s.resolvedLocalAgents():typeof s.localAgents=="function"?s.localAgents():[],t;try{t=await s.load()}catch(i){if(e.length===0)throw i;t={version:"local-only",agents:[]}}let n=new Set(e.map(i=>i.id)),r=[...e,...t.agents.filter(i=>!n.has(i.id))],o=await Promise.all(r.map(async i=>({id:i.id,name:i.name,version:i.version,description:i.description,distributions:Object.keys(i.distribution),installed:await Qr(i),...i.extendsChain?{extendsChain:i.extendsChain}:{},source:n.has(i.id)?"local":"registry",...i.onboarding?{onboarding:i.onboarding}:{}})));return{version:t.version,fetchedAt:s.lastFetchedAt(),agents:o}}async function Qr(s){let e=Ue();if(!e)return"no";let t=s.version??"current",n=fa(s);if(s.distribution.exec)return"yes";if(s.distribution.binary){let r=Ur(s.distribution.binary,e);if(r?.cmd){let o=as.resolve(E.agentInstallDir(n,e,t),r.cmd);if(await ua(o))return"yes"}}if(s.distribution.npx){let r=s.distribution.npx,o=r.bin??Kr(s)??r.package,i=E.agentNpmInstallDir(n,e,t),a=as.join(i,"node_modules",".bin",o);if(await ua(a))return"yes"}return!s.distribution.npx&&!s.distribution.binary&&s.distribution.uvx?"lazy":"no"}async function ua(s){try{return await la.access(s),!0}catch{return!1}}async function _e(s,e=[],t={}){let n=s.version??"current",r=fa(s);if(s.distribution.npx){let o=s.distribution.npx,i=e.length>0?e:o.args??[];if(process.env.HYDRA_ACP_SKIP_NPM_PREFETCH)return{command:"npx",args:["-y",o.package,...i],env:o.env??{},version:n,installId:r};let a=o.bin??Kr(s)??o.package,d=t.onInstallProgress;return{command:await oa({agentId:r,version:n,packageSpec:o.package,bin:a,registry:t.npmRegistry,onProgress:d?u=>d({source:"npm",...u}):void 0}),args:i,env:o.env??{},version:n,installId:r}}if(s.distribution.binary){let o=Ur(s.distribution.binary);if(!o)throw new Error(`Agent ${s.id} has no binary distribution for ${Ue()??"this platform"}.`);let i=t.onInstallProgress,a=await ta({agentId:r,version:n,target:o,onProgress:i?c=>i({source:"binary",...c}):void 0}),d=e.length>0?e:o.args??[];return{command:a,args:d,env:o.env??{},version:n,installId:r}}if(s.distribution.uvx){let o=s.distribution.uvx,i=e.length>0?e:o.args??[];return{command:"uvx",args:[o.package,...i],env:o.env??{},version:n,installId:r}}if(s.distribution.exec){let o=s.distribution.exec,i=e.length>0?e:o.args??[];return{command:o.command,args:i,env:o.env??{},version:n,installId:r}}throw new Error(`Agent ${s.id} has no usable distribution method.`)}import{spawn as dp,spawnSync as cp}from"child_process";import*as us from"fs";import*as _a from"path";var R={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603,AuthRequired:-32e3,SessionNotFound:-32001,NotAuthorisedToAttach:-32002,MultiClientNotSupported:-32003,AgentNotInstalled:-32005,BundleAlreadyImported:-32010,PermissionDenied:-32011,AlreadyAttached:-32012,StreamNotEnabled:-32013,SessionClosing:-32014};import{z as X}from"zod";var ha=X.object({protocolVersion:X.number().optional(),clientCapabilities:X.record(X.unknown()).optional(),clientInfo:X.object({name:X.string(),version:X.string().optional()}).optional()}),rp=X.enum(["full","pending_only","none","after_message"]),ya=X.object({cwd:X.string(),mcpServers:X.array(X.unknown()).optional(),_meta:X.record(X.unknown()).optional()}),wa=X.object({upstreamSessionId:X.string(),agentId:X.string(),cwd:X.string(),title:X.string().optional(),agentArgs:X.array(X.string()).optional()}),ka=X.object({sessionId:X.string(),historyPolicy:rp.default("full"),afterMessageId:X.string().optional(),afterSeq:X.number().optional(),clientId:X.string().optional(),clientInfo:X.object({name:X.string(),version:X.string().optional()}).optional(),_meta:X.record(X.unknown()).optional()});import{z as wn}from"zod";var jt=wn.object({selection:wn.object({text:wn.string().min(1),responsePartId:wn.string().optional()}).optional(),contextThroughSeq:wn.number().optional()});import{z as D}from"zod";var va=D.object({sessionId:D.string()}),ba=D.object({cwd:D.string().optional(),cursor:D.string().optional()}),Yr=D.object({used:D.number().optional(),size:D.number().optional(),costAmount:D.number().optional(),costCurrency:D.string().optional()}),mv=D.object({sessionId:D.string(),upstreamSessionId:D.string().optional(),cwd:D.string(),workspace:D.object({path:D.string(),sourceCwd:D.string(),label:D.string(),provider:D.string(),snapshot:D.string().optional(),vcs:D.record(D.string(),D.string()).optional()}).optional(),workspaceError:D.string().optional(),title:D.string().optional(),agentId:D.string().optional(),currentModel:D.string().optional(),currentUsage:Yr.optional(),importedFromMachine:D.string().optional(),importedFromUpstreamSessionId:D.string().optional(),parentSessionId:D.string().optional(),forkedFromSessionId:D.string().optional(),forkedFromMessageId:D.string().optional(),side:jt.optional(),originatingClient:D.object({name:D.string(),version:D.string().optional()}).optional(),interactive:D.boolean().optional(),priority:D.number().int().nonnegative().optional(),lastTurnEndedAt:D.number().optional(),readAt:D.number().optional(),unread:D.boolean().optional(),createdAt:D.string().optional(),updatedAt:D.string(),attachedClients:D.number().int().nonnegative(),status:D.enum(["warm","cold"]).default("warm"),busy:D.boolean().default(!1),awaitingInput:D.boolean().default(!1),turnStartedAt:D.number().optional(),armedTasks:D.number().int().nonnegative().optional(),armedSince:D.number().int().positive().optional(),compactionState:D.any().optional(),agentPid:D.number().int().positive().optional(),forkSynthesisState:D.enum(["running","failed"]).optional(),_meta:D.record(D.unknown()).optional()}),op=D.object({sessionId:D.string(),cwd:D.string(),title:D.string().optional(),updatedAt:D.string().optional(),_meta:D.record(D.unknown()).optional()}),hv=D.object({sessions:D.array(op),nextCursor:D.string().optional()});function ds(s,e){let t={attachedClients:s.attachedClients,status:s.status,busy:s.busy,awaitingInput:s.awaitingInput};return s.cwd!==void 0&&(t.cwd=s.cwd),s.workspace!==void 0&&(t.workspaceInfo=s.workspace),s.workspaceError!==void 0&&(t.workspaceError=s.workspaceError),s.title!==void 0&&(t.title=s.title),s.agentId!==void 0&&(t.agentId=s.agentId),s.upstreamSessionId!==void 0&&(t.upstreamSessionId=s.upstreamSessionId),s.createdAt!==void 0&&(t.createdAt=s.createdAt),s.currentModel!==void 0&&(t.currentModel=s.currentModel),s.currentUsage!==void 0&&(t.currentUsage=s.currentUsage),s.importedFromMachine!==void 0&&(t.importedFromMachine=s.importedFromMachine),s.importedFromUpstreamSessionId!==void 0&&(t.importedFromUpstreamSessionId=s.importedFromUpstreamSessionId),s.parentSessionId!==void 0&&(t.parentSessionId=s.parentSessionId),s.forkedFromSessionId!==void 0&&(t.forkedFromSessionId=s.forkedFromSessionId),s.forkedFromMessageId!==void 0&&(t.forkedFromMessageId=s.forkedFromMessageId),s.side!==void 0&&(t.side=s.side),s.originatingClient!==void 0&&(t.originatingClient=s.originatingClient),s.interactive!==void 0&&(t.interactive=s.interactive),s.priority!==void 0&&s.priority>0&&(t.priority=s.priority),s.lastTurnEndedAt!==void 0&&(t.lastTurnEndedAt=s.lastTurnEndedAt),s.readAt!==void 0&&(t.readAt=s.readAt),s.unread&&(t.unread=!0),s.armedTasks!==void 0&&(t.armedTasks=s.armedTasks),s.armedSince!==void 0&&(t.armedSince=s.armedSince),s.compactionState!==void 0&&(t.compactionState=s.compactionState),s.forkSynthesisState!==void 0&&(t.forkSynthesisState=s.forkSynthesisState),e&&(e.clientId!==void 0&&(t.clientId=e.clientId),e.currentMode!==void 0&&(t.currentMode=e.currentMode),e.agentArgs!==void 0&&e.agentArgs.length>0&&(t.agentArgs=e.agentArgs),e.availableCommands!==void 0&&e.availableCommands.length>0&&(t.availableCommands=e.availableCommands),e.availableModes!==void 0&&e.availableModes.length>0&&(t.availableModes=e.availableModes),e.availableModels!==void 0&&e.availableModels.length>0&&(t.availableModels=e.availableModels),e.turnStartedAt!==void 0&&(t.turnStartedAt=e.turnStartedAt),e.agentCapabilities!==void 0&&(t.agentCapabilities=e.agentCapabilities),e.queue!==void 0&&e.queue.length>0&&(t.queue=e.queue),e.resurrected===!0&&(t.resurrected=!0),e.armedTaskList!==void 0&&(t.armedTaskList=e.armedTaskList)),t}function Sa(s){let e={sessionId:s.sessionId,cwd:s.cwd,updatedAt:s.updatedAt,_meta:kn(s._meta,ds(s))};return s.title!==void 0&&(e.title=s.title),e}var le="hydra-acp";function ip(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e={};for(let[t,n]of Object.entries(s)){if(typeof t!="string"||t.length===0||typeof n!="string")return;e[t]=n}return e}function dt(s){if(!s)return{};let e=s[le];if(!e||typeof e!="object"||Array.isArray(e))return{};let t=e,n={};if(typeof t.upstreamSessionId=="string"&&(n.upstreamSessionId=t.upstreamSessionId),typeof t.agentId=="string"&&(n.agentId=t.agentId),typeof t.cwd=="string"&&(n.cwd=t.cwd),t.workspace!==null&&typeof t.workspace=="object"&&!Array.isArray(t.workspace)){let o=t.workspace,i={};typeof o.label=="string"&&(i.label=o.label),typeof o.from=="string"&&(i.from=o.from),o.required===!0&&(i.required=!0),o.adopt===!0&&(i.adopt=!0),typeof o.provider=="string"&&(i.provider=o.provider),n.workspace=i}if(t.workspaceInfo!==null&&typeof t.workspaceInfo=="object"&&!Array.isArray(t.workspaceInfo)){let o=t.workspaceInfo;if(typeof o.path=="string"&&typeof o.sourceCwd=="string"&&typeof o.label=="string"&&typeof o.provider=="string"){let i={path:o.path,sourceCwd:o.sourceCwd,label:o.label,provider:o.provider};if(typeof o.snapshot=="string"&&(i.snapshot=o.snapshot),o.vcs!==null&&typeof o.vcs=="object"&&!Array.isArray(o.vcs)){let a={};for(let[d,c]of Object.entries(o.vcs))typeof c=="string"&&(a[d]=c);i.vcs=a}n.workspaceInfo=i}}if(typeof t.workspaceError=="string"&&(n.workspaceError=t.workspaceError),typeof t.clientId=="string"&&(n.clientId=t.clientId),typeof t.readonly=="boolean"&&(n.readonly=t.readonly),(t.replayMode==="instant"||t.replayMode==="drip")&&(n.replayMode=t.replayMode),typeof t.dripSpeed=="number"&&t.dripSpeed>0&&(n.dripSpeed=t.dripSpeed),typeof t.historyLimit=="number"&&Number.isFinite(t.historyLimit)&&t.historyLimit>=0&&(n.historyLimit=t.historyLimit),(t.toolContent==="inline"||t.toolContent==="references")&&(n.toolContent=t.toolContent),t.detachStatus==="detached"&&(n.detachStatus=t.detachStatus),typeof t.title=="string"&&(n.title=t.title),Array.isArray(t.agentArgs)&&t.agentArgs.every(o=>typeof o=="string")&&(n.agentArgs=t.agentArgs),Array.isArray(t.transformers)&&t.transformers.every(o=>typeof o=="string")&&(n.transformers=t.transformers),t.resume){let o=wa.safeParse(t.resume);o.success&&(n.resume=o.data)}if(typeof t.model=="string"&&(n.model=t.model),typeof t.currentModel=="string"&&(n.currentModel=t.currentModel),typeof t.currentMode=="string"&&(n.currentMode=t.currentMode),t.currentUsage){let o=Yr.safeParse(t.currentUsage);o.success&&(n.currentUsage=o.data)}if(typeof t.turnStartedAt=="number"&&t.turnStartedAt>0&&(n.turnStartedAt=t.turnStartedAt),typeof t.armedTasks=="number"&&t.armedTasks>=0&&(n.armedTasks=t.armedTasks),typeof t.armedSince=="number"&&t.armedSince>0&&(n.armedSince=t.armedSince),Array.isArray(t.armedTaskList)){let o=[];for(let i of t.armedTaskList){if(!i||typeof i!="object"||Array.isArray(i))continue;let a=i;typeof a.label!="string"||typeof a.since!="number"||o.push({label:a.label,since:a.since,...typeof a.taskId=="string"?{taskId:a.taskId}:{},...typeof a.taskType=="string"?{taskType:a.taskType}:{},...typeof a.toolCallId=="string"?{toolCallId:a.toolCallId}:{},...a.endUnobservable===!0?{endUnobservable:!0}:{}})}n.armedTaskList=o}if(Array.isArray(t.availableCommands)){let o=[];for(let i of t.availableCommands){if(!i||typeof i!="object"||Array.isArray(i))continue;let a=i;if(typeof a.name!="string")continue;let d={name:a.name};typeof a.description=="string"&&(d.description=a.description),o.push(d)}o.length>0&&(n.availableCommands=o)}if(t.prompt&&typeof t.prompt=="object"&&!Array.isArray(t.prompt)){let o=t.prompt,i={};typeof o.queueing=="boolean"&&(i.queueing=o.queueing),typeof o.cancelling=="boolean"&&(i.cancelling=o.cancelling),typeof o.updating=="boolean"&&(i.updating=o.updating),typeof o.amending=="boolean"&&(i.amending=o.amending),typeof o.pipelining=="boolean"&&(i.pipelining=o.pipelining),n.prompt=i}if(t.agents&&typeof t.agents=="object"&&!Array.isArray(t.agents)){let o=t.agents,i={};typeof o.list=="boolean"&&(i.list=o.list),typeof o.installProgress=="boolean"&&(i.installProgress=o.installProgress),n.agents=i}if(typeof t.mcpStdin=="boolean"&&(n.mcpStdin=t.mcpStdin),typeof t.interactive=="boolean"&&(n.interactive=t.interactive),typeof t.ancillary=="boolean"&&(n.ancillary=t.ancillary),t.salvaged&&typeof t.salvaged=="object"&&!Array.isArray(t.salvaged)){let o=t.salvaged;typeof o.reason=="string"&&typeof o.supersededMessageId=="string"&&(n.salvaged={reason:o.reason,supersededMessageId:o.supersededMessageId})}if(Array.isArray(t.queue)){let o=[];for(let i of t.queue){if(!i||typeof i!="object"||Array.isArray(i))continue;let a=i,d=a.originator;if(typeof a.messageId!="string"||!d||typeof d.clientId!="string"||!Array.isArray(a.prompt)||typeof a.position!="number"||typeof a.enqueuedAt!="number")continue;let c={clientId:d.clientId};typeof d.name=="string"&&(c.name=d.name),typeof d.version=="string"&&(c.version=d.version),o.push({messageId:a.messageId,originator:c,prompt:a.prompt,position:a.position,enqueuedAt:a.enqueuedAt})}o.length>0&&(n.queue=o)}if(Array.isArray(t.availableModes)){let o=[];for(let i of t.availableModes){if(!i||typeof i!="object"||Array.isArray(i))continue;let a=i;if(typeof a.id!="string")continue;let d={id:a.id};typeof a.name=="string"&&(d.name=a.name),typeof a.description=="string"&&(d.description=a.description),o.push(d)}o.length>0&&(n.availableModes=o)}if(Array.isArray(t.availableModels)){let o=[];for(let i of t.availableModels){if(!i||typeof i!="object"||Array.isArray(i))continue;let a=i;if(typeof a.modelId!="string")continue;let d={modelId:a.modelId};typeof a.name=="string"&&(d.name=a.name),typeof a.description=="string"&&(d.description=a.description),o.push(d)}o.length>0&&(n.availableModels=o)}(t.status==="warm"||t.status==="cold")&&(n.status=t.status),typeof t.busy=="boolean"&&(n.busy=t.busy),typeof t.awaitingInput=="boolean"&&(n.awaitingInput=t.awaitingInput),typeof t.attachedClients=="number"&&(n.attachedClients=t.attachedClients),typeof t.resurrected=="boolean"&&(n.resurrected=t.resurrected),typeof t.importedFromMachine=="string"&&(n.importedFromMachine=t.importedFromMachine),typeof t.importedFromUpstreamSessionId=="string"&&(n.importedFromUpstreamSessionId=t.importedFromUpstreamSessionId),typeof t.parentSessionId=="string"&&(n.parentSessionId=t.parentSessionId),typeof t.forkedFromSessionId=="string"&&(n.forkedFromSessionId=t.forkedFromSessionId),typeof t.forkedFromMessageId=="string"&&(n.forkedFromMessageId=t.forkedFromMessageId);let r=jt.safeParse(t.side);if(r.success&&(n.side=r.data),t.originatingClient&&typeof t.originatingClient=="object"&&!Array.isArray(t.originatingClient)&&typeof t.originatingClient.name=="string"){let o=t.originatingClient;n.originatingClient={name:o.name,...typeof o.version=="string"?{version:o.version}:{}}}if(t.agentCapabilities!==void 0&&(n.agentCapabilities=t.agentCapabilities),t.env!==void 0){let o=ip(t.env);o!==void 0&&(n.env=o)}return n}function Be(s,e){if(typeof e!="number"||!Number.isFinite(e)||!s||typeof s!="object"||Array.isArray(s))return s;let t=s,n=t._meta&&typeof t._meta=="object"&&!Array.isArray(t._meta)?t._meta:{},r=n[le],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.recordedAt=="number"?s:{...t,_meta:{...n,[le]:{...o,recordedAt:e}}}}function We(s,e){if(typeof e!="number"||!Number.isFinite(e)||!s||typeof s!="object"||Array.isArray(s))return s;let t=s,n=t._meta&&typeof t._meta=="object"&&!Array.isArray(t._meta)?t._meta:{},r=n[le],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.seq=="number"?s:{...t,_meta:{...n,[le]:{...o,seq:e}}}}function kn(s,e){return{...s??{},[le]:e}}import{z as _}from"zod";var Ia=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.record(_.unknown()).optional()}),cs=_.object({sessionId:_.string()}),Aa=_.object({clientId:_.string(),name:_.string().optional(),version:_.string().optional()}),Iv=_.object({sessionId:_.string(),messageId:_.string(),originator:Aa,prompt:_.array(_.unknown()),position:_.number().int().nonnegative(),queueDepth:_.number().int().positive(),enqueuedAt:_.number()}),Av=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),Cv=_.object({sessionId:_.string(),messageId:_.string(),reason:_.enum(["started","cancelled","abandoned"])}),Ca=_.object({sessionId:_.string(),messageId:_.string()}),Rv=_.object({cancelled:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),Ra=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),xv=_.object({updated:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),xa=_.object({sessionId:_.string(),targetMessageId:_.string(),prompt:_.array(_.unknown()),replaceQueue:_.boolean().optional(),onTargetCompleted:_.enum(["reject","send_anyway"]).optional()}),Tv=_.object({amended:_.boolean(),reason:_.enum(["ok","target_completed","target_cancelled","target_not_found"]),messageId:_.string().optional()}),Ta=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.object({steering:_.object({idleBehavior:_.literal("promptRequired").optional()}).optional()}).optional()}),Ev=_.object({outcome:_.enum(["injected","startedNewTurn","promptRequired","failed"]),reason:_.literal("noRunningTurn").optional(),detached:_.boolean().optional()}),Pv=_.object({sessionId:_.string(),cancelledMessageId:_.string(),newMessageId:_.string(),prompt:_.array(_.unknown()),originator:Aa,amendedAt:_.number()});import{z as ct}from"zod";var $v=ct.object({agentId:ct.string(),version:ct.string(),source:ct.enum(["binary","npm"]),phase:ct.enum(["download_start","download_progress","download_done","extract","install_start","installed"]),receivedBytes:ct.number().optional(),totalBytes:ct.number().optional(),packageSpec:ct.string().optional()}),Ea="hydra-acp/agents/install_progress",Lt={auth:{terminal:!0},_meta:{"terminal-auth":!0}};function Pa(s,e){let t="",n=[],r=[],o=!1,i=a=>{if(!o){o=!0;for(let d of r)d(a)}};return s.setEncoding("utf8"),s.on("data",a=>{t+=a;let d=t.indexOf(`
16
+ `);for(;d!==-1;){let c=t.slice(0,d).trim();if(t=t.slice(d+1),c.length>0)try{let u=JSON.parse(c);for(let l of n)l(u)}catch(u){for(let l of n)l({jsonrpc:"2.0",id:null,error:{code:R.ParseError,message:`Failed to parse ndjson line: ${u.message}`}})}d=t.indexOf(`
17
17
  `)}}),s.on("end",()=>i()),s.on("error",a=>i(a)),e.on("error",a=>i(a)),{async send(a){if(o)throw new Error("stream is closed");let d=JSON.stringify(a)+`
18
- `;await new Promise((c,u)=>{e.write(d,l=>{if(l){u(l);return}c()})})},onMessage(a){n.push(a)},onClose(a){r.push(a)},async close(){e.end(),i()}}}import{nanoid as op}from"nanoid";var Qr=class extends Error{code="ERR_CONNECTION_CLOSED";constructor(e="connection is closed"){super(e),this.name="ConnectionClosedError"}},qe=class s{constructor(e){this.stream=e;this.stream.onMessage(t=>this.handleIncoming(t)),this.stream.onClose(t=>this.handleClose(t))}stream;requestHandlers=new Map;defaultRequestHandler;notificationHandlers=new Map;paramsRewriter;anyNotificationHandlers=[];bufferedNotifications=new Map;static MAX_BUFFERED_PER_METHOD=64;static MAX_BUFFERED_METHODS=256;pending=new Map;closed=!1;closeHandlers=[];orphanErrorHandlers=[];onRequest(e,t){this.requestHandlers.set(e,t)}setDefaultHandler(e){this.defaultRequestHandler=e}setParamsRewriter(e){this.paramsRewriter=e}onNotification(e,t){this.notificationHandlers.set(e,t);let n=this.bufferedNotifications.get(e);if(n){this.bufferedNotifications.delete(e);for(let r of n)try{t(r.params,r.method)}catch{}}}drainBuffered(e){let n=this.bufferedNotifications.get(e)?.length??0;return this.bufferedNotifications.delete(e),n}dropBufferedWhere(e,t){let n=this.bufferedNotifications.get(e);if(!n)return 0;let r=n.filter(o=>!t(o.params));return r.length>0?this.bufferedNotifications.set(e,r):this.bufferedNotifications.delete(e),n.length-r.length}onAnyNotification(e){this.anyNotificationHandlers.push(e)}onClose(e){this.closeHandlers.push(e)}isClosed(){return this.closed}onOrphanError(e){this.orphanErrorHandlers.push(e)}async request(e,t){return this.requestWithId(e,t).response}requestWithId(e,t){if(this.closed)throw new Qr;let n=op(),r={jsonrpc:"2.0",id:n,method:e,params:t},o=new Promise((i,a)=>{this.pending.set(n,{resolve:d=>i(d),reject:a}),this.stream.send(r).catch(d=>{this.pending.delete(n),a(d)})});return{id:n,response:o}}notify(e,t){if(this.closed)return Promise.resolve();let n={jsonrpc:"2.0",method:e,params:t};return this.stream.send(n)}async close(){this.closed||await this.stream.close()}fail(e){this.handleClose(e)}handleIncoming(e){"method"in e?(this.paramsRewriter&&(e={...e,params:this.paramsRewriter(e.params,e.method)}),"id"in e&&e.id!==void 0?this.handleRequest(e).catch(()=>{}):this.handleNotification(e)):"id"in e?this.handleResponse(e):"error"in e&&this.handleResponse(e)}async handleRequest(e){let t=this.requestHandlers.get(e.method)??this.defaultRequestHandler;if(!t){await this.sendError(e.id,{code:x.MethodNotFound,message:`Method not found: ${e.method}`}).catch(()=>{});return}try{let n=await t(e.params,e.method),r={jsonrpc:"2.0",id:e.id,result:n};await this.stream.send(r).catch(()=>{})}catch(n){let r=n;await this.sendError(e.id,{code:r.code??x.InternalError,message:r.message,data:r.data}).catch(()=>{})}}handleNotification(e){for(let r of this.anyNotificationHandlers)try{r(e.params,e.method)}catch{}let t=this.notificationHandlers.get(e.method);if(t){t(e.params,e.method);return}let n=this.bufferedNotifications.get(e.method);if(!n){if(this.bufferedNotifications.size>=s.MAX_BUFFERED_METHODS){let r=this.bufferedNotifications.keys().next().value;r!==void 0&&this.bufferedNotifications.delete(r)}n=[],this.bufferedNotifications.set(e.method,n)}n.push(e),n.length>s.MAX_BUFFERED_PER_METHOD&&n.shift()}handleResponse(e){let t=e.id===null?void 0:this.pending.get(e.id);if(!t){if(e.error)for(let n of this.orphanErrorHandlers)try{n({code:e.error.code,message:e.error.message,data:e.error.data})}catch{}return}if(this.pending.delete(e.id),e.error){let n=new Error(e.error.message);n.code=e.error.code,n.data=e.error.data,t.reject(n)}else t.resolve(e.result)}async sendError(e,t){let n={jsonrpc:"2.0",id:e,error:t};await this.stream.send(n)}handleClose(e){if(!this.closed){this.closed=!0;for(let t of this.pending.values())t.reject(e??new Error("connection closed"));this.pending.clear();for(let t of this.closeHandlers)t(e)}}};Y();var dp=4096,ct=class s{agentId;version;installId;cwd;connection;authMethods;steeringSupported;child;get pid(){return this.child.pid}exited=!1;killed=!1;stderrTail="";stderrTailBytes;killEscalationMs;logger;fileLog;exitHandlers=[];constructor(e,t){if(this.agentId=e.agentId,this.version=e.plan.version,this.installId=e.plan.installId??e.agentId,this.cwd=e.cwd,this.child=t,this.stderrTailBytes=e.stderrTailBytes??dp,this.killEscalationMs=e.killEscalationMs??cp,this.logger=e.logger,this.fileLog=up(e.agentId),this.writeLog(`--- spawn pid=${t.pid} version=${e.plan.version} cwd=${e.cwd} cmd=${e.plan.command} args=${JSON.stringify(e.plan.args)} time=${new Date().toISOString()} ---
19
- `),!t.stdout||!t.stdin)throw new Error("agent subprocess missing stdio");let n=Ea(t.stdout,t.stdin);this.connection=new qe(n),t.stderr?.setEncoding("utf8"),t.stderr?.on("data",r=>{if(this.stderrTail=(this.stderrTail+r).slice(-this.stderrTailBytes),this.writeLog(r),this.logger)for(let o of r.split(/\r?\n/))o.length>0&&this.logger.info(`[${e.agentId}] ${o}`);else process.stderr.write(`[${e.agentId}] ${r}`)}),t.on("error",r=>{let o=this.formatFailure(r.message);this.writeLog(`--- spawn error: ${r.message} time=${new Date().toISOString()} ---
18
+ `;await new Promise((c,u)=>{e.write(d,l=>{if(l){u(l);return}c()})})},onMessage(a){n.push(a)},onClose(a){r.push(a)},async close(){e.end(),i()}}}import{nanoid as ap}from"nanoid";var Xr=class extends Error{code="ERR_CONNECTION_CLOSED";constructor(e="connection is closed"){super(e),this.name="ConnectionClosedError"}},qe=class s{constructor(e){this.stream=e;this.stream.onMessage(t=>this.handleIncoming(t)),this.stream.onClose(t=>this.handleClose(t))}stream;requestHandlers=new Map;defaultRequestHandler;notificationHandlers=new Map;paramsRewriter;anyNotificationHandlers=[];bufferedNotifications=new Map;static MAX_BUFFERED_PER_METHOD=64;static MAX_BUFFERED_METHODS=256;pending=new Map;closed=!1;closeHandlers=[];orphanErrorHandlers=[];onRequest(e,t){this.requestHandlers.set(e,t)}setDefaultHandler(e){this.defaultRequestHandler=e}setParamsRewriter(e){this.paramsRewriter=e}onNotification(e,t){this.notificationHandlers.set(e,t);let n=this.bufferedNotifications.get(e);if(n){this.bufferedNotifications.delete(e);for(let r of n)try{t(r.params,r.method)}catch{}}}drainBuffered(e){let n=this.bufferedNotifications.get(e)?.length??0;return this.bufferedNotifications.delete(e),n}dropBufferedWhere(e,t){let n=this.bufferedNotifications.get(e);if(!n)return 0;let r=n.filter(o=>!t(o.params));return r.length>0?this.bufferedNotifications.set(e,r):this.bufferedNotifications.delete(e),n.length-r.length}onAnyNotification(e){this.anyNotificationHandlers.push(e)}onClose(e){this.closeHandlers.push(e)}isClosed(){return this.closed}onOrphanError(e){this.orphanErrorHandlers.push(e)}async request(e,t){return this.requestWithId(e,t).response}requestWithId(e,t){if(this.closed)throw new Xr;let n=ap(),r={jsonrpc:"2.0",id:n,method:e,params:t},o=new Promise((i,a)=>{this.pending.set(n,{resolve:d=>i(d),reject:a}),this.stream.send(r).catch(d=>{this.pending.delete(n),a(d)})});return{id:n,response:o}}notify(e,t){if(this.closed)return Promise.resolve();let n={jsonrpc:"2.0",method:e,params:t};return this.stream.send(n)}async close(){this.closed||await this.stream.close()}fail(e){this.handleClose(e)}handleIncoming(e){"method"in e?(this.paramsRewriter&&(e={...e,params:this.paramsRewriter(e.params,e.method)}),"id"in e&&e.id!==void 0?this.handleRequest(e).catch(()=>{}):this.handleNotification(e)):"id"in e?this.handleResponse(e):"error"in e&&this.handleResponse(e)}async handleRequest(e){let t=this.requestHandlers.get(e.method)??this.defaultRequestHandler;if(!t){await this.sendError(e.id,{code:R.MethodNotFound,message:`Method not found: ${e.method}`}).catch(()=>{});return}try{let n=await t(e.params,e.method),r={jsonrpc:"2.0",id:e.id,result:n};await this.stream.send(r).catch(()=>{})}catch(n){let r=n;await this.sendError(e.id,{code:r.code??R.InternalError,message:r.message,data:r.data}).catch(()=>{})}}handleNotification(e){for(let r of this.anyNotificationHandlers)try{r(e.params,e.method)}catch{}let t=this.notificationHandlers.get(e.method);if(t){t(e.params,e.method);return}let n=this.bufferedNotifications.get(e.method);if(!n){if(this.bufferedNotifications.size>=s.MAX_BUFFERED_METHODS){let r=this.bufferedNotifications.keys().next().value;r!==void 0&&this.bufferedNotifications.delete(r)}n=[],this.bufferedNotifications.set(e.method,n)}n.push(e),n.length>s.MAX_BUFFERED_PER_METHOD&&n.shift()}handleResponse(e){let t=e.id===null?void 0:this.pending.get(e.id);if(!t){if(e.error)for(let n of this.orphanErrorHandlers)try{n({code:e.error.code,message:e.error.message,data:e.error.data})}catch{}return}if(this.pending.delete(e.id),e.error){let n=new Error(e.error.message);n.code=e.error.code,n.data=e.error.data,t.reject(n)}else t.resolve(e.result)}async sendError(e,t){let n={jsonrpc:"2.0",id:e,error:t};await this.stream.send(n)}handleClose(e){if(!this.closed){this.closed=!0;for(let t of this.pending.values())t.reject(e??new Error("connection closed"));this.pending.clear();for(let t of this.closeHandlers)t(e)}}};Y();var up=4096,ut=class s{agentId;version;installId;cwd;connection;authMethods;steeringSupported;child;get pid(){return this.child.pid}exited=!1;killed=!1;stderrTail="";stderrTailBytes;killEscalationMs;logger;fileLog;exitHandlers=[];constructor(e,t){if(this.agentId=e.agentId,this.version=e.plan.version,this.installId=e.plan.installId??e.agentId,this.cwd=e.cwd,this.child=t,this.stderrTailBytes=e.stderrTailBytes??up,this.killEscalationMs=e.killEscalationMs??lp,this.logger=e.logger,this.fileLog=fp(e.agentId),this.writeLog(`--- spawn pid=${t.pid} version=${e.plan.version} cwd=${e.cwd} cmd=${e.plan.command} args=${JSON.stringify(e.plan.args)} time=${new Date().toISOString()} ---
19
+ `),!t.stdout||!t.stdin)throw new Error("agent subprocess missing stdio");let n=Pa(t.stdout,t.stdin);this.connection=new qe(n),t.stderr?.setEncoding("utf8"),t.stderr?.on("data",r=>{if(this.stderrTail=(this.stderrTail+r).slice(-this.stderrTailBytes),this.writeLog(r),this.logger)for(let o of r.split(/\r?\n/))o.length>0&&this.logger.info(`[${e.agentId}] ${o}`);else process.stderr.write(`[${e.agentId}] ${r}`)}),t.on("error",r=>{let o=this.formatFailure(r.message);this.writeLog(`--- spawn error: ${r.message} time=${new Date().toISOString()} ---
20
20
  `),t.pid===void 0&&(this.fileLog?.end(),this.fileLog=void 0),this.connection.fail(new Error(o))}),t.on("exit",(r,o)=>{if(this.exited=!0,this.writeLog(`--- exit code=${r} signal=${o} ${this.killed?"(after kill) ":""}time=${new Date().toISOString()} ---
21
21
  `),this.fileLog?.end(),this.fileLog=void 0,this.killed)this.logger?.info(`agent ${e.agentId} pid=${t.pid} exited after kill code=${r} signal=${o}`);else{let i=`agent ${e.agentId} exited before responding (code=${r} signal=${o})`;this.connection.fail(new Error(this.formatFailure(i))),this.logger?.warn(`agent ${e.agentId} pid=${t.pid} exited unexpectedly code=${r} signal=${o}`)}for(let i of this.exitHandlers)i(r,o)})}writeLog(e){if(this.fileLog)try{this.fileLog.write(e)}catch{}}formatFailure(e){let t=this.stderrTail.trim();return t?`${e}
22
- stderr: ${t}`:e}stderrTailText(){return this.stderrTail.trim()}static spawn(e){let t={...ts(),...e.plan.env,...e.extraEnv??{}},n=Ft(e.plan.command,e.plan.args),r=ip(n.command,n.args,{cwd:e.cwd,env:t,stdio:["pipe","pipe","pipe"],shell:n.shell,windowsHide:!0,detached:!0});return r.unref(),new s(e,r)}onExit(e){this.exitHandlers.push(e)}isAlive(){return!this.exited}async kill(e="SIGTERM"){this.exited||(this.killed=!0,this.writeLog(`--- kill requested signal=${e} time=${new Date().toISOString()} ---
22
+ stderr: ${t}`:e}stderrTailText(){return this.stderrTail.trim()}static spawn(e){let t={...ss(),...e.plan.env,...e.extraEnv??{}},n=Nt(e.plan.command,e.plan.args),r=dp(n.command,n.args,{cwd:e.cwd,env:t,stdio:["pipe","pipe","pipe"],shell:n.shell,windowsHide:!0,detached:!0});return r.unref(),new s(e,r)}onExit(e){this.exitHandlers.push(e)}isAlive(){return!this.exited}async kill(e="SIGTERM"){this.exited||(this.killed=!0,this.writeLog(`--- kill requested signal=${e} time=${new Date().toISOString()} ---
23
23
  `),this.logger?.info(`agent ${this.agentId} pid=${this.child.pid} kill requested signal=${e}`),await this.connection.close().catch(()=>{}),this.signalProcessGroup(e),await this.waitForExit(this.killEscalationMs),!this.exited&&(this.writeLog(`--- kill escalating signal=SIGKILL time=${new Date().toISOString()} ---
24
- `),this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} did not exit after ${e}; sending SIGKILL`),this.signalProcessGroup("SIGKILL"),await this.waitForExit(Ta),this.exited||this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} still has not exited ${Ta}ms after SIGKILL; giving up on the reap`)))}signalProcessGroup(e){let t=this.child.pid;if(t!==void 0){if(process.platform==="win32"){try{ap("taskkill",["/pid",String(t),"/T","/F"],{stdio:"ignore",windowsHide:!0})}catch{try{this.child.kill()}catch{}}return}try{process.kill(-t,e)}catch{try{this.child.kill(e)}catch{}}}}waitForExit(e){return this.exited?Promise.resolve():new Promise(t=>{let n=setTimeout(()=>{this.child.off("exit",r),t()},e),r=()=>{clearTimeout(n),t()};this.child.once("exit",r)})}},cp=2e3,Ta=5e3;function up(s){try{let e=T.agentLogFile(s);ds.mkdirSync(Pa.dirname(e),{recursive:!0});let t=ds.createWriteStream(e,{flags:"a"});return t.on("error",()=>{}),t}catch{return}}function cs(s){if(s.length===0)return s;let e=new Map,t=new Map,n=new Map;for(let a=0;a<s.length;a++){let d=s[a];if(d===void 0)continue;let c=Yr(d);if(c?.sessionUpdate!=="tool_call_update")continue;let u=typeof c.toolCallId=="string"?c.toolCallId:void 0;if(u!==void 0){e.set(u,a);for(let l of mp){if(!Ma(c[l]))continue;let p=n.get(u);p===void 0?n.set(u,new Map([[l,c[l]]])):p.set(l,c[l])}Array.isArray(c.content)&&c.content.length>0&&t.set(u,c.content)}}let r=[],o=null,i=null;for(let a=0;a<s.length;a++){let d=s[a];if(d===void 0)continue;let c=Yr(d);if(!c||typeof c.sessionUpdate!="string"){r.push(d),o=null;continue}let u=c.sessionUpdate;if(u==="agent_message_chunk"||u==="agent_thought_chunk"||u==="user_message_chunk"){o&&o.kind===u?(pp(r,o.outIndex,lp(c.content)),fp(r,o.outIndex,d.seq)):(r.push(d),o={outIndex:r.length-1,kind:u});continue}if(o=null,u==="tool_call_update"){let l=typeof c.toolCallId=="string"?c.toolCallId:void 0;if(l!==void 0&&e.get(l)!==a)continue;let p=l!==void 0&&t.has(l)?gp(d,t.get(l)??[]):d,f=l===void 0?void 0:n.get(l);if(f!==void 0)for(let[h,k]of f)Ma(Yr(p)?.[h])||(p=hp(p,h,k));r.push(p);continue}if(u==="plan"){i!==null?r[i]=d:(r.push(d),i=r.length-1);continue}(u==="prompt_received"||u==="turn_complete")&&(i=null),r.push(d)}return r}function Yr(s){if(s.method!=="session/update")return;let t=s.params?.update;if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function lp(s){if(!s||typeof s!="object")return"";let e=s;return typeof e.text=="string"?e.text:""}function fp(s,e,t){let n=s[e];n===void 0||typeof t!="number"||n.seq!==void 0&&n.seq>=t||(s[e]={...n,seq:t})}function pp(s,e,t){if(t.length===0)return;let n=s[e];if(n===void 0)return;let r=n.params??{},o=r.update??{},i=o.content??{},a=typeof i.text=="string"?i.text:"";s[e]={...n,params:{...r,update:{...o,content:{...i,text:a+t}}}}}function gp(s,e){let t=s.params??{},n=t.update??{};return{...s,params:{...t,update:{...n,content:e}}}}var mp=["rawInput","locations"];function Ma(s){return s==null||typeof s!="object"?!1:Array.isArray(s)?s.length>0:Object.keys(s).length>0}function hp(s,e,t){let n=s.params??{},r=n.update??{};return{...s,params:{...n,update:{...r,[e]:t}}}}function Lt(s,e){let t=e?.contextThroughSeq;return t===void 0?[...s]:s.filter(n=>n.seq===void 0||n.seq>t)}function _a(s){let e;for(let t of s)t.seq!==void 0&&(e===void 0||t.seq>e)&&(e=t.seq);return e===void 0?{}:{contextThroughSeq:e}}import*as xt from"fs/promises";import*as Mc from"os";import*as $a from"os";function bt(){return $a.hostname()}import*as jn from"path";import{customAlphabet as Ih}from"nanoid";var ze="session/set_model",Zr="session/set_config_option",Na="model";function Xr(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.availableModels)}function Da(s){return Array.isArray(s)&&s.some(e=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.id===Na)}function Ut(s){if(!s)return;if(Xr(s)||Xr(s.models))return ze;let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){for(let[t,n]of Object.entries(e))if(t!=="hydra-acp"&&Xr(n))return ze}if(Da(s.configOptions))return Zr}function Ha(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.sessionUpdate;if(e==="_hydra_current_model_update")return ze;if(e==="config_option_update"&&Da(s.configOptions))return Zr}function Oa(s){return typeof s=="object"&&s!==null&&s.code===x.MethodNotFound}function Fa(s,e,t,n){let r={...n??{}};return delete r.sessionId,delete r.modelId,delete r.configId,delete r.value,s===ze?{...r,sessionId:e,modelId:t}:{...r,sessionId:e,configId:Na,value:t}}function yp(s){return s===ze?Zr:ze}async function ut(s){let{request:e,sessionId:t,modelId:n,extraParams:r,logger:o}=s,i=s.verb??ze;try{let a=await e(i,Fa(i,t,n,r));return{verb:i,result:a}}catch(a){if(!Oa(a))throw a;let d=yp(i);o?.info(`agent does not implement ${i} (MethodNotFound); retrying model change via ${d} modelId=${JSON.stringify(n)}`);try{let c=await e(d,Fa(d,t,n,r));return{verb:d,result:c}}catch(c){throw Oa(c)?a:c}}}async function lt(s){let{agent:e,upstreamSessionId:t,persistedMode:n,agentReportedMode:r,advertisedModes:o,logger:i}=s;if(!n)return r;if(n===r)return n;if(o&&o.length>0&&!o.some(a=>a.id===n)){let a=o.map(d=>d.id).join(", ");return i?.warn(`resurrect: persisted currentMode=${JSON.stringify(n)} not in agent's availableModes ([${a}]); skipping session/set_mode, session will use ${JSON.stringify(r)}`),r}try{return i?.info(`resurrect: pushing persisted modeId=${JSON.stringify(n)} to agent (agentReported=${JSON.stringify(r)})`),await e.connection.request("session/set_mode",{sessionId:t,modeId:n}),i?.info(`resurrect: session/set_mode accepted, effectiveMode=${JSON.stringify(n)}`),n}catch(a){return i?.warn(`resurrect: session/set_mode rejected by agent for modeId=${JSON.stringify(n)} (${a.message}); session will use ${JSON.stringify(r)}`),r}}async function ft(s){let{agent:e,upstreamSessionId:t,persistedModel:n,agentReportedModel:r,modelVerb:o,logger:i}=s;if(!n)return{modelId:r};if(n===r)return{modelId:n};try{i?.info(`resurrect: pushing persisted modelId=${JSON.stringify(n)} to agent (agentReported=${JSON.stringify(r)})`);let{verb:a,result:d}=await ut({request:(c,u)=>e.connection.request(c,u),sessionId:t,modelId:n,...o?{verb:o}:{},logger:i});return i?.info(`resurrect: ${a} accepted, effectiveModel=${JSON.stringify(n)}`),{modelId:n,result:d}}catch(a){return i?.warn(`resurrect: session/set_model rejected by agent for modelId=${JSON.stringify(n)} (${a.message}); session will use ${JSON.stringify(r)}`),{modelId:r}}}var Bt=class{started=performance.now();last=this.started;phases=[];mark(e){let t=performance.now();this.phases.push([e,t-this.last]),this.last=t}absorb(e,t){for(let[n,r]of t.phases)this.phases.push([`${e}.${n}`,r]);this.last=performance.now()}totalMs(){return performance.now()-this.started}summary(){let e=this.phases.map(([t,n])=>`${t}=${Math.round(n)}ms`);return`total=${Math.round(this.totalMs())}ms ${e.join(" ")}`}};var ja="edit",us=class{kinds=new Map;note(e,t){t!==void 0&&t.length>0&&!this.kinds.has(e)&&this.kinds.set(e,t)}get(e){return this.kinds.get(e)}effective(e,t){return t!==void 0&&t.length>0?t:this.kinds.get(e)}clear(){this.kinds.clear()}get size(){return this.kinds.size}};function La(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(t===null||typeof t!="object")continue;let n=t.path;typeof n=="string"&&n.length>0&&e.push(n)}return e}function eo(s){let e=[],t=[],n=!1;for(let r of s.split(`
24
+ `),this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} did not exit after ${e}; sending SIGKILL`),this.signalProcessGroup("SIGKILL"),await this.waitForExit(Ma),this.exited||this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} still has not exited ${Ma}ms after SIGKILL; giving up on the reap`)))}signalProcessGroup(e){let t=this.child.pid;if(t!==void 0){if(process.platform==="win32"){try{cp("taskkill",["/pid",String(t),"/T","/F"],{stdio:"ignore",windowsHide:!0})}catch{try{this.child.kill()}catch{}}return}try{process.kill(-t,e)}catch{try{this.child.kill(e)}catch{}}}}waitForExit(e){return this.exited?Promise.resolve():new Promise(t=>{let n=setTimeout(()=>{this.child.off("exit",r),t()},e),r=()=>{clearTimeout(n),t()};this.child.once("exit",r)})}},lp=2e3,Ma=5e3;function fp(s){try{let e=E.agentLogFile(s);us.mkdirSync(_a.dirname(e),{recursive:!0});let t=us.createWriteStream(e,{flags:"a"});return t.on("error",()=>{}),t}catch{return}}function ls(s){if(s.length===0)return s;let e=new Map,t=new Map,n=new Map;for(let a=0;a<s.length;a++){let d=s[a];if(d===void 0)continue;let c=Zr(d);if(c?.sessionUpdate!=="tool_call_update")continue;let u=typeof c.toolCallId=="string"?c.toolCallId:void 0;if(u!==void 0){e.set(u,a);for(let l of yp){if(!$a(c[l]))continue;let p=n.get(u);p===void 0?n.set(u,new Map([[l,c[l]]])):p.set(l,c[l])}Array.isArray(c.content)&&c.content.length>0&&t.set(u,c.content)}}let r=[],o=null,i=null;for(let a=0;a<s.length;a++){let d=s[a];if(d===void 0)continue;let c=Zr(d);if(!c||typeof c.sessionUpdate!="string"){r.push(d),o=null;continue}let u=c.sessionUpdate;if(u==="agent_message_chunk"||u==="agent_thought_chunk"||u==="user_message_chunk"){o&&o.kind===u?(mp(r,o.outIndex,pp(c.content)),gp(r,o.outIndex,d.seq)):(r.push(d),o={outIndex:r.length-1,kind:u});continue}if(o=null,u==="tool_call_update"){let l=typeof c.toolCallId=="string"?c.toolCallId:void 0;if(l!==void 0&&e.get(l)!==a)continue;let p=l!==void 0&&t.has(l)?hp(d,t.get(l)??[]):d,f=l===void 0?void 0:n.get(l);if(f!==void 0)for(let[h,k]of f)$a(Zr(p)?.[h])||(p=wp(p,h,k));r.push(p);continue}if(u==="plan"){i!==null?r[i]=d:(r.push(d),i=r.length-1);continue}(u==="prompt_received"||u==="turn_complete")&&(i=null),r.push(d)}return r}function Zr(s){if(s.method!=="session/update")return;let t=s.params?.update;if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function pp(s){if(!s||typeof s!="object")return"";let e=s;return typeof e.text=="string"?e.text:""}function gp(s,e,t){let n=s[e];n===void 0||typeof t!="number"||n.seq!==void 0&&n.seq>=t||(s[e]={...n,seq:t})}function mp(s,e,t){if(t.length===0)return;let n=s[e];if(n===void 0)return;let r=n.params??{},o=r.update??{},i=o.content??{},a=typeof i.text=="string"?i.text:"";s[e]={...n,params:{...r,update:{...o,content:{...i,text:a+t}}}}}function hp(s,e){let t=s.params??{},n=t.update??{};return{...s,params:{...t,update:{...n,content:e}}}}var yp=["rawInput","locations"];function $a(s){return s==null||typeof s!="object"?!1:Array.isArray(s)?s.length>0:Object.keys(s).length>0}function wp(s,e,t){let n=s.params??{},r=n.update??{};return{...s,params:{...n,update:{...r,[e]:t}}}}function Ut(s,e){let t=e?.contextThroughSeq;return t===void 0?[...s]:s.filter(n=>n.seq===void 0||n.seq>t)}function Oa(s){let e;for(let t of s)t.seq!==void 0&&(e===void 0||t.seq>e)&&(e=t.seq);return e===void 0?{}:{contextThroughSeq:e}}import*as Tt from"fs/promises";import*as $c from"os";import*as Fa from"os";function St(){return Fa.hostname()}import*as Un from"path";import{customAlphabet as Ch}from"nanoid";var ze="session/set_model",to="session/set_config_option",Ha="model";function eo(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.availableModels)}function ja(s){return Array.isArray(s)&&s.some(e=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.id===Ha)}function Bt(s){if(!s)return;if(eo(s)||eo(s.models))return ze;let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){for(let[t,n]of Object.entries(e))if(t!=="hydra-acp"&&eo(n))return ze}if(ja(s.configOptions))return to}function La(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.sessionUpdate;if(e==="_hydra_current_model_update")return ze;if(e==="config_option_update"&&ja(s.configOptions))return to}function Na(s){return typeof s=="object"&&s!==null&&s.code===R.MethodNotFound}function Da(s,e,t,n){let r={...n??{}};return delete r.sessionId,delete r.modelId,delete r.configId,delete r.value,s===ze?{...r,sessionId:e,modelId:t}:{...r,sessionId:e,configId:Ha,value:t}}function kp(s){return s===ze?to:ze}async function lt(s){let{request:e,sessionId:t,modelId:n,extraParams:r,logger:o}=s,i=s.verb??ze;try{let a=await e(i,Da(i,t,n,r));return{verb:i,result:a}}catch(a){if(!Na(a))throw a;let d=kp(i);o?.info(`agent does not implement ${i} (MethodNotFound); retrying model change via ${d} modelId=${JSON.stringify(n)}`);try{let c=await e(d,Da(d,t,n,r));return{verb:d,result:c}}catch(c){throw Na(c)?a:c}}}async function ft(s){let{agent:e,upstreamSessionId:t,persistedMode:n,agentReportedMode:r,advertisedModes:o,logger:i}=s;if(!n)return r;if(n===r)return n;if(o&&o.length>0&&!o.some(a=>a.id===n)){let a=o.map(d=>d.id).join(", ");return i?.warn(`resurrect: persisted currentMode=${JSON.stringify(n)} not in agent's availableModes ([${a}]); skipping session/set_mode, session will use ${JSON.stringify(r)}`),r}try{return i?.info(`resurrect: pushing persisted modeId=${JSON.stringify(n)} to agent (agentReported=${JSON.stringify(r)})`),await e.connection.request("session/set_mode",{sessionId:t,modeId:n}),i?.info(`resurrect: session/set_mode accepted, effectiveMode=${JSON.stringify(n)}`),n}catch(a){return i?.warn(`resurrect: session/set_mode rejected by agent for modeId=${JSON.stringify(n)} (${a.message}); session will use ${JSON.stringify(r)}`),r}}async function pt(s){let{agent:e,upstreamSessionId:t,persistedModel:n,agentReportedModel:r,modelVerb:o,logger:i}=s;if(!n)return{modelId:r};if(n===r)return{modelId:n};try{i?.info(`resurrect: pushing persisted modelId=${JSON.stringify(n)} to agent (agentReported=${JSON.stringify(r)})`);let{verb:a,result:d}=await lt({request:(c,u)=>e.connection.request(c,u),sessionId:t,modelId:n,...o?{verb:o}:{},logger:i});return i?.info(`resurrect: ${a} accepted, effectiveModel=${JSON.stringify(n)}`),{modelId:n,result:d}}catch(a){return i?.warn(`resurrect: session/set_model rejected by agent for modelId=${JSON.stringify(n)} (${a.message}); session will use ${JSON.stringify(r)}`),{modelId:r}}}var Wt=class{started=performance.now();last=this.started;phases=[];mark(e){let t=performance.now();this.phases.push([e,t-this.last]),this.last=t}absorb(e,t){for(let[n,r]of t.phases)this.phases.push([`${e}.${n}`,r]);this.last=performance.now()}totalMs(){return performance.now()-this.started}summary(){let e=this.phases.map(([t,n])=>`${t}=${Math.round(n)}ms`);return`total=${Math.round(this.totalMs())}ms ${e.join(" ")}`}};var Ua="edit",fs=class{kinds=new Map;note(e,t){t!==void 0&&t.length>0&&!this.kinds.has(e)&&this.kinds.set(e,t)}get(e){return this.kinds.get(e)}effective(e,t){return t!==void 0&&t.length>0?t:this.kinds.get(e)}clear(){this.kinds.clear()}get size(){return this.kinds.size}};function Ba(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(t===null||typeof t!="object")continue;let n=t.path;typeof n=="string"&&n.length>0&&e.push(n)}return e}function no(s){let e=[],t=[],n=!1;for(let r of s.split(`
25
25
  `)){if(r.startsWith("@@")){n=!0;continue}if(!n||r.startsWith("\\"))continue;let o=r.slice(1);r.startsWith("-")?e.push(o):r.startsWith("+")?t.push(o):r.startsWith(" ")&&(e.push(o),t.push(o))}return{oldText:e.length>0?e.join(`
26
26
  `)+`
27
27
  `:"",newText:t.length>0?t.join(`
28
28
  `)+`
29
- `:""}}function Ua(s){if(s===null||typeof s!="object")return[];let e=s.rawOutput;if(e===null||typeof e!="object")return[];let t=e.metadata;if(t===null||typeof t!="object")return[];let n=t.files;if(!Array.isArray(n))return[];let r=[];for(let o of n){if(o===null||typeof o!="object")continue;let i=o,a=typeof i.filePath=="string"&&i.filePath.length>0?i.filePath:i.file;if(typeof a!="string"||a.length===0)continue;let d=i.patch,c=d!==null&&typeof d=="object"?d:void 0;r.push({path:a,...typeof i.additions=="number"?{added:i.additions}:{},...typeof i.deletions=="number"?{removed:i.deletions}:{},...typeof d=="string"?{patch:d}:{},...typeof c?.__hydraBlob=="string"?{patchRef:{hash:c.__hydraBlob,bytes:typeof c.bytes=="number"?c.bytes:0}}:{}})}return r}function St(s){if(typeof s=="string")return{text:s};if(s&&typeof s=="object"&&!Array.isArray(s)){let e=s;if(typeof e.__hydraBlob=="string")return{ref:{hash:e.__hydraBlob,bytes:typeof e.bytes=="number"?e.bytes:0}}}}function ls(s){let e=s.rawInput;return e&&typeof e=="object"&&!Array.isArray(e)?e:void 0}function to(s){return typeof s.file_path=="string"?s.file_path:typeof s.path=="string"?s.path:void 0}function fs(s){let e=s.content;if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n;if(r.type!=="diff")continue;let o=St(r.oldText),i=St(r.newText);o===void 0&&i===void 0||t.push({...typeof r.path=="string"?{path:r.path}:{},...o?{old:o}:{},...i?{new:i}:{}})}return t}function ps(s){let e=ls(s);if(!e)return;let t=to(e);if(e.old_string!==void 0||e.new_string!==void 0){let n=St(e.old_string),r=St(e.new_string);return{...t!==void 0?{path:t}:{},...n?{old:n}:{},...r?{new:r}:{}}}if(e.content!==void 0){let n=St(e.content);return{...t!==void 0?{path:t}:{},old:{text:""},...n?{new:n}:{}}}}function wp(s){let e=ls(s),t=e?to(e):void 0;if(!e||t===void 0||!Array.isArray(e.edits))return[];let n=[];for(let r of e.edits){if(!r||typeof r!="object")continue;let o=r,i=St(o.old_string),a=St(o.new_string);i===void 0||a===void 0||n.push({path:t,old:i,new:a})}return n}function Ba(s){return Ua(s).map(e=>({path:e.path,...e.patch!==void 0?{patch:{text:e.patch}}:{},...e.patchRef!==void 0?{patch:{ref:e.patchRef}}:{}}))}function gs(s){let e=wp(s);if(e.length>0)return e.map(r=>({...r,scope:"snippet"}));let t=fs(s).filter(r=>r.path!==void 0);if(t.length>0){let r=kp(s);return r===void 0?t:t.map(o=>({...o,scope:r}))}let n=ps(s);return n?.path!==void 0?[{...n,scope:n.old?.text===""?"file":"snippet"}]:Ba(s).map(r=>({...r,scope:"snippet"}))}function kp(s){let e=ls(s);return e&&(e.old_string!==void 0||e.new_string!==void 0)?"snippet":e&&e.content!==void 0||vp(s)?"file":void 0}function vp(s){let e=s.rawOutput;return Array.isArray(e?.metadata?.files)}function Wa(s){let e=new Set,t=ls(s),n=[...fs(s).map(r=>r.path),ps(s)?.path,t&&Array.isArray(t.edits)?to(t):void 0,...Ba(s).map(r=>r.path)];for(let r of n)typeof r=="string"&&r.length>0&&e.add(r);return[...e]}function qa(s){return s.patch!==void 0?s.patch.text!==void 0?eo(s.patch.text):{oldText:"",newText:""}:{oldText:s.old?.text??"",newText:s.new?.text??""}}Y();import{posix as bp}from"path";import Sp from"strip-ansi";function wn(s){if(!s||typeof s!="object")return;let e=s;return typeof e.workerTaskId=="string"?e.workerTaskId:void 0}function no(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object")return;let t=e.claudeCode;if(!t||typeof t!="object")return;let n=t.parentToolUseId;return typeof n=="string"?n:void 0}var Ip=/[\x00-\x08\x0b-\x1f\x7f]/g;function be(s){return Sp(s).replace(Ip,"")}function ie(s){return be(s).replace(/[\n\t]+/g," ").replace(/ +/g," ").trim()}function Ga(s,e={}){if(!s||typeof s!="object")return null;let t=s,n=t.sessionUpdate??t.kind;if(typeof n!="string")return null;switch(n){case"agent_message_chunk":return Pp(t);case"agent_thought_chunk":case"agent_thought":return Mp(t);case"user_message_chunk":return _p(t);case"prompt_received":return $p(t);case"tool_call":return Op(t,e);case"tool_call_update":return jp(t,e);case"plan":return Wp(t);case"current_mode_update":return qp(t);case"_hydra_current_model_update":return zp(t);case"turn_complete":return Jp(t);case"_hydra_turn_started":return Va(t,"turn-started");case"_hydra_turn_ended":return Va(t,"turn-ended");case"usage_update":return Tp(t);case"available_commands_update":return xp(t);case"_hydra_available_modes_update":return Ep(t);case"session_info_update":return Cp(t);case"config_option_update":return Ap(t);default:return{kind:"unknown",sessionUpdate:n,raw:s}}}function Ap(s){let e=s.configOptions;if(!Array.isArray(e))return null;let t=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n;if(typeof r.id!="string"||typeof r.currentValue!="string"||!Array.isArray(r.options))continue;let o=[];for(let i of r.options){if(!i||typeof i!="object")continue;let a=i;typeof a.value=="string"&&o.push({value:a.value,name:typeof a.name=="string"?a.name:a.value,...typeof a.description=="string"?{description:a.description}:{}})}t.push({id:r.id,name:typeof r.name=="string"?r.name:r.id,type:"select",currentValue:r.currentValue,options:o,...typeof r.category=="string"?{category:r.category}:{}})}return{kind:"config-options",options:t}}function Cp(s){let e=se(s,"title"),t=e!==void 0?ie(e):void 0,n=s._meta,r,o;if(n&&typeof n=="object"&&!Array.isArray(n)){let a=n["hydra-acp"];if(a&&typeof a=="object"&&!Array.isArray(a)){let d=a.agentId;if(typeof d=="string"&&(r=d),"pendingAgentSwap"in a){let c=a.pendingAgentSwap;typeof c=="string"?o=c:c===null&&(o=null)}}}if(t===void 0&&r===void 0&&o===void 0)return null;let i={kind:"session-info"};return t!==void 0&&(i.title=t),r!==void 0&&(i.agentId=r),o!==void 0&&(i.pendingAgentSwap=o),i}function Rp(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object")continue;let n=t;if(typeof n.name!="string"||n.name.length===0)continue;let r=n.name.startsWith("/")?n.name:`/${n.name}`,o={name:ie(r)};typeof n.description=="string"&&(o.description=ie(n.description)),e.push(o)}return e}function xp(s){let e=s.availableCommands??s.commands;return Array.isArray(e)?{kind:"available-commands",commands:Rp(e)}:null}function Ep(s){let e=s.availableModes;if(!Array.isArray(e))return null;let t=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n;if(typeof r.id!="string"||r.id.length===0)continue;let o={id:ie(r.id)};typeof r.name=="string"&&(o.name=ie(r.name)),typeof r.description=="string"&&(o.description=ie(r.description)),t.push(o)}return{kind:"available-modes",modes:t}}function Tp(s){let e={kind:"usage-update"};if(typeof s.used=="number"&&(e.used=s.used),typeof s.size=="number"&&(e.size=s.size),s.cost&&typeof s.cost=="object"){let t=s.cost;typeof t.amount=="number"&&(e.costAmount=t.amount),typeof t.currency=="string"&&(e.costCurrency=t.currency)}return e}function Pp(s){let e=kn(s.content);return e===null?null:{kind:"agent-text",text:e,workerTaskId:wn(s)}}function Mp(s){let e=typeof s.text=="string"?be(s.text):kn(s.content);return e===null?null:{kind:"agent-thought",text:e,workerTaskId:wn(s)}}function _p(s){let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){let n=e["hydra-acp"];if(n&&typeof n=="object"&&!Array.isArray(n)&&n.compatFor==="prompt_received")return null}let t=kn(s.content);return t===null?null:{kind:"user-text",text:t}}function $p(s){let e=Vp(s.prompt);return e===null?null:{kind:"user-text",text:e}}function Ka(s){return s?s.toLowerCase().replace(/[_\s-]/g,"")==="exitplanmode":!1}function Qa(s){let e=fs(s)[0];if(e)return za(e);let t=ps(s);return t?.old?.text!==void 0&&t.new?.text!==void 0?za(t):null}function za(s){return{...s.path!==void 0?{path:s.path}:{},oldText:s.old?.text??"",newText:s.new?.text??"",...s.old?.ref?{oldRef:s.old.ref}:{},...s.new?.ref?{newRef:s.new.ref}:{}}}function Ya(s){let e=s.rawInput;if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e.plan;return typeof t!="string"||t.length===0?null:be(t)}function Op(s,e={}){let t=se(s,"toolCallId")??se(s,"id");if(!t)return null;let n=se(s,"title")??se(s,"name")??se(s,"label")??"tool call",r=se(s,"name")??se(s,"title");if(Ka(r)){let k=Ya(s);if(k!==null){let m=se(s,"status"),g={kind:"exit-plan-mode",toolCallId:t,plan:k};return m!==void 0&&(g.status=m),g}}let o=ed(ie(n),s,e),i=se(s,"status"),a=se(s,"kind"),d={kind:"tool-call",toolCallId:t,title:o};i!==void 0&&(d.status=i),a!==void 0&&(d.rawKind=a);let c=Qa(s);c!==null&&(d.editDiff=c);let u=Za(s);u!==void 0&&(d.detail=u);let l=so(s);l!==void 0&&(d.detailFull=l);let p=Xa(s);p!==void 0&&(d.locations=p);let f=wn(s);f!==void 0&&(d.workerTaskId=f);let h=no(s);return h!==void 0&&(d.parentToolUseId=h),d}function Xa(s){let e=s.locations;if(!Array.isArray(e))return;let t=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n;if(typeof r.path!="string"||r.path.length===0)continue;let o={path:r.path};typeof r.line=="number"&&Number.isFinite(r.line)&&r.line>=1&&(o.line=Math.floor(r.line)),t.push(o)}return t.length>0?t:void 0}var Ja=64;function Za(s){let e=so(s);if(e===void 0)return;let t=ie(e),n=s.rawInput;return n&&typeof n.command=="string"?Dp(t,Ja):Hp(t,Ja)}function so(s){let e=s.rawInput;if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(typeof t.command=="string"&&t.command.trim().length>0)return be(t.command).trim().replace(/^cd\s+\S+\s+&&\s+/,"");let n=typeof t.file_path=="string"?t.file_path:typeof t.filePath=="string"?t.filePath:typeof t.path=="string"?t.path:void 0;if(n!==void 0&&n.length>0)return $(ie(n))}if(Array.isArray(s.locations)){for(let t of s.locations)if(t&&typeof t=="object"){let n=t.path;if(typeof n=="string"&&n.length>0)return $(ie(n))}}}var Fp=["home/","Users/","root/","tmp/","var/","opt/","etc/","usr/","mnt/","private/"];function Np(s){for(let e of Fp)if(s.startsWith(e))return!0;return!1}function ed(s,e,t={}){if(s.length===0)return s;if(s.startsWith("/"))return $(s);if(s.startsWith("~")||!s.includes("/")||/\s/.test(s))return s;let n=e.rawInput;if(n&&typeof n=="object"&&!Array.isArray(n)){let r=n,o=[r.file_path,r.filePath,r.path];for(let i of o)if(!(typeof i!="string"||i.length===0)&&(i===`/${s}`||i.endsWith(`/${s}`)||i===s))return $(i)}return Np(s)?$(`/${s}`):t.cwd&&t.cwd.length>0?$(bp.resolve(t.cwd,s)):s}function Dp(s,e){return s.length>e?`${s.slice(0,e-1)}\u2026`:s}function Hp(s,e){if(s.length<=e)return s;let t=s.slice(-(e-1)),n=t.indexOf("/");return n>=0&&n<e/2?`\u2026${t.slice(n)}`:`\u2026${t}`}function jp(s,e={}){let t=se(s,"toolCallId")??se(s,"id");if(!t)return null;let n=se(s,"title"),r=n!==void 0?ed(ie(n),s,e):void 0,o=se(s,"status"),i=Qa(s),a=Za(s),d=Lp(s);if(!(r!==void 0||i!==null||a!==void 0||d!==void 0||o==="completed"||o==="failed"||o==="rejected"||o==="cancelled"))return null;let u=se(s,"name")??n;if(Ka(u)){let m={kind:"exit-plan-mode",toolCallId:t},g=Ya(s);return g!==null&&(m.plan=g),o!==void 0&&(m.status=o),m}let l={kind:"tool-call-update",toolCallId:t};r!==void 0&&(l.title=r),a!==void 0&&(l.detail=a);let p=so(s);p!==void 0&&(l.detailFull=p);let f=Xa(s);if(f!==void 0&&(l.locations=f),d!==void 0&&(l.resultSummary=d),o!==void 0&&(l.status=o),i!==null&&(l.editDiff=i),o==="failed"){let m=Up(s);m!==null&&(l.errorText=m),Bp(s,m)&&(l.upstreamInterrupted=!0)}let h=wn(s);h!==void 0&&(l.workerTaskId=h);let k=no(s);return k!==void 0&&(l.parentToolUseId=k),l}function Lp(s){if(!s||typeof s!="object")return;let e=s.rawOutput;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,n=u=>{let l=t[u];return typeof l=="number"&&Number.isFinite(l)?l:void 0},r=(u,l,p=`${l}s`)=>`${u} ${u===1?l:p}`,o=[],i=n("totalMatches");i!==void 0&&o.push(r(i,"match","matches"));let a=n("totalFiles");a!==void 0&&o.push(r(a,"file"));let d=n("referenceCount");d!==void 0&&o.push(r(d,"reference")),o.length>0&&t.truncated===!0&&o.push("truncated");let c=n("exitCode");return c!==void 0&&c!==0&&o.push(`exit ${c}`),o.length>0?o.join(", "):void 0}function Up(s){let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let o=kn(n.content);if(o!==null&&o.length>0)return o}let t=s.rawOutput;if(t&&typeof t=="object"){let n=t.error;if(typeof n=="string"&&n.length>0)return be(n)}return null}function Bp(s,e){let t=s.rawOutput;if(t&&typeof t=="object"){let n=t.metadata;if(n&&typeof n=="object"&&n.interrupted===!0)return!0}return!!(e!==null&&e.toLowerCase().includes("tool execution aborted"))}function Wp(s){let e=s.entries;if(!Array.isArray(e)||e.length===0)return null;let t=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n,o=typeof r.content=="string"?ie(r.content):void 0;if(!o)continue;let i={content:o};typeof r.status=="string"&&(i.status=r.status),typeof r.priority=="string"&&(i.priority=r.priority),t.push(i)}return{kind:"plan",entries:t}}function qp(s){let e=se(s,"currentModeId")??se(s,"currentMode")??se(s,"mode");return e?{kind:"mode-changed",mode:ie(e)}:null}function zp(s){let e=se(s,"currentModel")??se(s,"model");if(!e)return null;let t=s.availableModels,n=Array.isArray(t)?t.map(r=>typeof r=="object"&&r!==null?r.modelId:typeof r=="string"?r:void 0).filter(r=>typeof r=="string"&&r.length>0):void 0;return{kind:"model-changed",model:ie(e),...n&&n.length>0?{availableModels:n}:{}}}function Jp(s){let e=se(s,"stopReason"),t=s._meta,n=t?.["hydra-acp"]?.amended!==void 0&&t["hydra-acp"].amended!==null,r={kind:"turn-complete"};e!==void 0&&(r.stopReason=e);let o=se(s,"errorMessage");return o!==void 0&&(r.errorMessage=o),n&&(r.amended=!0),r}function Va(s,e){let n=s._meta?.["hydra-acp"],r=n?.unsolicited===!0;if(e==="turn-started"){let i=n?.cause?.label,a={kind:e,unsolicited:r};return typeof i=="string"&&i.length>0&&(a.cause=i),a}let o={kind:e,unsolicited:r};return typeof n?.reason=="string"&&(o.reason=n.reason),o}function kn(s){if(typeof s=="string")return be(s);if(!s||typeof s!="object")return null;let e=s;return e.type==="text"&&typeof e.text=="string"||typeof e.text=="string"?be(e.text):null}function Vp(s){if(!Array.isArray(s))return null;let e=[];for(let t of s){let n=kn(t);n!==null&&e.push(n)}return e.length===0?null:e.join("")}function se(s,e){let t=s[e];return typeof t=="string"?t:void 0}function Gp(s,e){let t=be(s).split(`
29
+ `:""}}function Wa(s){if(s===null||typeof s!="object")return[];let e=s.rawOutput;if(e===null||typeof e!="object")return[];let t=e.metadata;if(t===null||typeof t!="object")return[];let n=t.files;if(!Array.isArray(n))return[];let r=[];for(let o of n){if(o===null||typeof o!="object")continue;let i=o,a=typeof i.filePath=="string"&&i.filePath.length>0?i.filePath:i.file;if(typeof a!="string"||a.length===0)continue;let d=i.patch,c=d!==null&&typeof d=="object"?d:void 0;r.push({path:a,...typeof i.additions=="number"?{added:i.additions}:{},...typeof i.deletions=="number"?{removed:i.deletions}:{},...typeof d=="string"?{patch:d}:{},...typeof c?.__hydraBlob=="string"?{patchRef:{hash:c.__hydraBlob,bytes:typeof c.bytes=="number"?c.bytes:0}}:{}})}return r}function It(s){if(typeof s=="string")return{text:s};if(s&&typeof s=="object"&&!Array.isArray(s)){let e=s;if(typeof e.__hydraBlob=="string")return{ref:{hash:e.__hydraBlob,bytes:typeof e.bytes=="number"?e.bytes:0}}}}function ps(s){let e=s.rawInput;return e&&typeof e=="object"&&!Array.isArray(e)?e:void 0}function so(s){return typeof s.file_path=="string"?s.file_path:typeof s.path=="string"?s.path:void 0}function gs(s){let e=s.content;if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n;if(r.type!=="diff")continue;let o=It(r.oldText),i=It(r.newText);o===void 0&&i===void 0||t.push({...typeof r.path=="string"?{path:r.path}:{},...o?{old:o}:{},...i?{new:i}:{}})}return t}function ms(s){let e=ps(s);if(!e)return;let t=so(e);if(e.old_string!==void 0||e.new_string!==void 0){let n=It(e.old_string),r=It(e.new_string);return{...t!==void 0?{path:t}:{},...n?{old:n}:{},...r?{new:r}:{}}}if(e.content!==void 0){let n=It(e.content);return{...t!==void 0?{path:t}:{},old:{text:""},...n?{new:n}:{}}}}function vp(s){let e=ps(s),t=e?so(e):void 0;if(!e||t===void 0||!Array.isArray(e.edits))return[];let n=[];for(let r of e.edits){if(!r||typeof r!="object")continue;let o=r,i=It(o.old_string),a=It(o.new_string);i===void 0||a===void 0||n.push({path:t,old:i,new:a})}return n}function qa(s){return Wa(s).map(e=>({path:e.path,...e.patch!==void 0?{patch:{text:e.patch}}:{},...e.patchRef!==void 0?{patch:{ref:e.patchRef}}:{}}))}function hs(s){let e=vp(s);if(e.length>0)return e.map(r=>({...r,scope:"snippet"}));let t=gs(s).filter(r=>r.path!==void 0);if(t.length>0){let r=bp(s);return r===void 0?t:t.map(o=>({...o,scope:r}))}let n=ms(s);return n?.path!==void 0?[{...n,scope:n.old?.text===""?"file":"snippet"}]:qa(s).map(r=>({...r,scope:"snippet"}))}function bp(s){let e=ps(s);return e&&(e.old_string!==void 0||e.new_string!==void 0)?"snippet":e&&e.content!==void 0||Sp(s)?"file":void 0}function Sp(s){let e=s.rawOutput;return Array.isArray(e?.metadata?.files)}function za(s){let e=new Set,t=ps(s),n=[...gs(s).map(r=>r.path),ms(s)?.path,t&&Array.isArray(t.edits)?so(t):void 0,...qa(s).map(r=>r.path)];for(let r of n)typeof r=="string"&&r.length>0&&e.add(r);return[...e]}function Ja(s){return s.patch!==void 0?s.patch.text!==void 0?no(s.patch.text):{oldText:"",newText:""}:{oldText:s.old?.text??"",newText:s.new?.text??""}}Y();import{posix as Ip}from"path";import Ap from"strip-ansi";function vn(s){if(!s||typeof s!="object")return;let e=s;return typeof e.workerTaskId=="string"?e.workerTaskId:void 0}function ro(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object")return;let t=e.claudeCode;if(!t||typeof t!="object")return;let n=t.parentToolUseId;return typeof n=="string"?n:void 0}var Cp=/[\x00-\x08\x0b-\x1f\x7f]/g;function be(s){return Ap(s).replace(Cp,"")}function ie(s){return be(s).replace(/[\n\t]+/g," ").replace(/ +/g," ").trim()}function Qa(s,e={}){if(!s||typeof s!="object")return null;let t=s,n=t.sessionUpdate??t.kind;if(typeof n!="string")return null;switch(n){case"agent_message_chunk":return _p(t);case"agent_thought_chunk":case"agent_thought":return $p(t);case"user_message_chunk":return Op(t);case"prompt_received":return Fp(t);case"tool_call":return Np(t,e);case"tool_call_update":return Up(t,e);case"plan":return zp(t);case"current_mode_update":return Jp(t);case"_hydra_current_model_update":return Vp(t);case"turn_complete":return Gp(t);case"_hydra_turn_started":return Ka(t,"turn-started");case"_hydra_turn_ended":return Ka(t,"turn-ended");case"usage_update":return Mp(t);case"available_commands_update":return Ep(t);case"_hydra_available_modes_update":return Pp(t);case"session_info_update":return xp(t);case"config_option_update":return Rp(t);default:return{kind:"unknown",sessionUpdate:n,raw:s}}}function Rp(s){let e=s.configOptions;if(!Array.isArray(e))return null;let t=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n;if(typeof r.id!="string"||typeof r.currentValue!="string"||!Array.isArray(r.options))continue;let o=[];for(let i of r.options){if(!i||typeof i!="object")continue;let a=i;typeof a.value=="string"&&o.push({value:a.value,name:typeof a.name=="string"?a.name:a.value,...typeof a.description=="string"?{description:a.description}:{}})}t.push({id:r.id,name:typeof r.name=="string"?r.name:r.id,type:"select",currentValue:r.currentValue,options:o,...typeof r.category=="string"?{category:r.category}:{}})}return{kind:"config-options",options:t}}function xp(s){let e=se(s,"title"),t=e!==void 0?ie(e):void 0,n=s._meta,r,o;if(n&&typeof n=="object"&&!Array.isArray(n)){let a=n["hydra-acp"];if(a&&typeof a=="object"&&!Array.isArray(a)){let d=a.agentId;if(typeof d=="string"&&(r=d),"pendingAgentSwap"in a){let c=a.pendingAgentSwap;typeof c=="string"?o=c:c===null&&(o=null)}}}if(t===void 0&&r===void 0&&o===void 0)return null;let i={kind:"session-info"};return t!==void 0&&(i.title=t),r!==void 0&&(i.agentId=r),o!==void 0&&(i.pendingAgentSwap=o),i}function Tp(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object")continue;let n=t;if(typeof n.name!="string"||n.name.length===0)continue;let r=n.name.startsWith("/")?n.name:`/${n.name}`,o={name:ie(r)};typeof n.description=="string"&&(o.description=ie(n.description)),e.push(o)}return e}function Ep(s){let e=s.availableCommands??s.commands;return Array.isArray(e)?{kind:"available-commands",commands:Tp(e)}:null}function Pp(s){let e=s.availableModes;if(!Array.isArray(e))return null;let t=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n;if(typeof r.id!="string"||r.id.length===0)continue;let o={id:ie(r.id)};typeof r.name=="string"&&(o.name=ie(r.name)),typeof r.description=="string"&&(o.description=ie(r.description)),t.push(o)}return{kind:"available-modes",modes:t}}function Mp(s){let e={kind:"usage-update"};if(typeof s.used=="number"&&(e.used=s.used),typeof s.size=="number"&&(e.size=s.size),s.cost&&typeof s.cost=="object"){let t=s.cost;typeof t.amount=="number"&&(e.costAmount=t.amount),typeof t.currency=="string"&&(e.costCurrency=t.currency)}return e}function _p(s){let e=bn(s.content);return e===null?null:{kind:"agent-text",text:e,workerTaskId:vn(s)}}function $p(s){let e=typeof s.text=="string"?be(s.text):bn(s.content);return e===null?null:{kind:"agent-thought",text:e,workerTaskId:vn(s)}}function Op(s){let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){let n=e["hydra-acp"];if(n&&typeof n=="object"&&!Array.isArray(n)&&n.compatFor==="prompt_received")return null}let t=bn(s.content);return t===null?null:{kind:"user-text",text:t}}function Fp(s){let e=Kp(s.prompt);return e===null?null:{kind:"user-text",text:e}}function Ya(s){return s?s.toLowerCase().replace(/[_\s-]/g,"")==="exitplanmode":!1}function Xa(s){let e=gs(s)[0];if(e)return Va(e);let t=ms(s);return t?.old?.text!==void 0&&t.new?.text!==void 0?Va(t):null}function Va(s){return{...s.path!==void 0?{path:s.path}:{},oldText:s.old?.text??"",newText:s.new?.text??"",...s.old?.ref?{oldRef:s.old.ref}:{},...s.new?.ref?{newRef:s.new.ref}:{}}}function Za(s){let e=s.rawInput;if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e.plan;return typeof t!="string"||t.length===0?null:be(t)}function Np(s,e={}){let t=se(s,"toolCallId")??se(s,"id");if(!t)return null;let n=se(s,"title")??se(s,"name")??se(s,"label")??"tool call",r=se(s,"name")??se(s,"title");if(Ya(r)){let k=Za(s);if(k!==null){let m=se(s,"status"),g={kind:"exit-plan-mode",toolCallId:t,plan:k};return m!==void 0&&(g.status=m),g}}let o=nd(ie(n),s,e),i=se(s,"status"),a=se(s,"kind"),d={kind:"tool-call",toolCallId:t,title:o};i!==void 0&&(d.status=i),a!==void 0&&(d.rawKind=a);let c=Xa(s);c!==null&&(d.editDiff=c);let u=td(s);u!==void 0&&(d.detail=u);let l=oo(s);l!==void 0&&(d.detailFull=l);let p=ed(s);p!==void 0&&(d.locations=p);let f=vn(s);f!==void 0&&(d.workerTaskId=f);let h=ro(s);return h!==void 0&&(d.parentToolUseId=h),d}function ed(s){let e=s.locations;if(!Array.isArray(e))return;let t=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n;if(typeof r.path!="string"||r.path.length===0)continue;let o={path:r.path};typeof r.line=="number"&&Number.isFinite(r.line)&&r.line>=1&&(o.line=Math.floor(r.line)),t.push(o)}return t.length>0?t:void 0}var Ga=64;function td(s){let e=oo(s);if(e===void 0)return;let t=ie(e),n=s.rawInput;return n&&typeof n.command=="string"?jp(t,Ga):Lp(t,Ga)}function oo(s){let e=s.rawInput;if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(typeof t.command=="string"&&t.command.trim().length>0)return be(t.command).trim().replace(/^cd\s+\S+\s+&&\s+/,"");let n=typeof t.file_path=="string"?t.file_path:typeof t.filePath=="string"?t.filePath:typeof t.path=="string"?t.path:void 0;if(n!==void 0&&n.length>0)return $(ie(n))}if(Array.isArray(s.locations)){for(let t of s.locations)if(t&&typeof t=="object"){let n=t.path;if(typeof n=="string"&&n.length>0)return $(ie(n))}}}var Dp=["home/","Users/","root/","tmp/","var/","opt/","etc/","usr/","mnt/","private/"];function Hp(s){for(let e of Dp)if(s.startsWith(e))return!0;return!1}function nd(s,e,t={}){if(s.length===0)return s;if(s.startsWith("/"))return $(s);if(s.startsWith("~")||!s.includes("/")||/\s/.test(s))return s;let n=e.rawInput;if(n&&typeof n=="object"&&!Array.isArray(n)){let r=n,o=[r.file_path,r.filePath,r.path];for(let i of o)if(!(typeof i!="string"||i.length===0)&&(i===`/${s}`||i.endsWith(`/${s}`)||i===s))return $(i)}return Hp(s)?$(`/${s}`):t.cwd&&t.cwd.length>0?$(Ip.resolve(t.cwd,s)):s}function jp(s,e){return s.length>e?`${s.slice(0,e-1)}\u2026`:s}function Lp(s,e){if(s.length<=e)return s;let t=s.slice(-(e-1)),n=t.indexOf("/");return n>=0&&n<e/2?`\u2026${t.slice(n)}`:`\u2026${t}`}function Up(s,e={}){let t=se(s,"toolCallId")??se(s,"id");if(!t)return null;let n=se(s,"title"),r=n!==void 0?nd(ie(n),s,e):void 0,o=se(s,"status"),i=Xa(s),a=td(s),d=Bp(s);if(!(r!==void 0||i!==null||a!==void 0||d!==void 0||o==="completed"||o==="failed"||o==="rejected"||o==="cancelled"))return null;let u=se(s,"name")??n;if(Ya(u)){let m={kind:"exit-plan-mode",toolCallId:t},g=Za(s);return g!==null&&(m.plan=g),o!==void 0&&(m.status=o),m}let l={kind:"tool-call-update",toolCallId:t};r!==void 0&&(l.title=r),a!==void 0&&(l.detail=a);let p=oo(s);p!==void 0&&(l.detailFull=p);let f=ed(s);if(f!==void 0&&(l.locations=f),d!==void 0&&(l.resultSummary=d),o!==void 0&&(l.status=o),i!==null&&(l.editDiff=i),o==="failed"){let m=Wp(s);m!==null&&(l.errorText=m),qp(s,m)&&(l.upstreamInterrupted=!0)}let h=vn(s);h!==void 0&&(l.workerTaskId=h);let k=ro(s);return k!==void 0&&(l.parentToolUseId=k),l}function Bp(s){if(!s||typeof s!="object")return;let e=s.rawOutput;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,n=u=>{let l=t[u];return typeof l=="number"&&Number.isFinite(l)?l:void 0},r=(u,l,p=`${l}s`)=>`${u} ${u===1?l:p}`,o=[],i=n("totalMatches");i!==void 0&&o.push(r(i,"match","matches"));let a=n("totalFiles");a!==void 0&&o.push(r(a,"file"));let d=n("referenceCount");d!==void 0&&o.push(r(d,"reference")),o.length>0&&t.truncated===!0&&o.push("truncated");let c=n("exitCode");return c!==void 0&&c!==0&&o.push(`exit ${c}`),o.length>0?o.join(", "):void 0}function Wp(s){let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let o=bn(n.content);if(o!==null&&o.length>0)return o}let t=s.rawOutput;if(t&&typeof t=="object"){let n=t.error;if(typeof n=="string"&&n.length>0)return be(n)}return null}function qp(s,e){let t=s.rawOutput;if(t&&typeof t=="object"){let n=t.metadata;if(n&&typeof n=="object"&&n.interrupted===!0)return!0}return!!(e!==null&&e.toLowerCase().includes("tool execution aborted"))}function zp(s){let e=s.entries;if(!Array.isArray(e)||e.length===0)return null;let t=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n,o=typeof r.content=="string"?ie(r.content):void 0;if(!o)continue;let i={content:o};typeof r.status=="string"&&(i.status=r.status),typeof r.priority=="string"&&(i.priority=r.priority),t.push(i)}return{kind:"plan",entries:t}}function Jp(s){let e=se(s,"currentModeId")??se(s,"currentMode")??se(s,"mode");return e?{kind:"mode-changed",mode:ie(e)}:null}function Vp(s){let e=se(s,"currentModel")??se(s,"model");if(!e)return null;let t=s.availableModels,n=Array.isArray(t)?t.map(r=>typeof r=="object"&&r!==null?r.modelId:typeof r=="string"?r:void 0).filter(r=>typeof r=="string"&&r.length>0):void 0;return{kind:"model-changed",model:ie(e),...n&&n.length>0?{availableModels:n}:{}}}function Gp(s){let e=se(s,"stopReason"),t=s._meta,n=t?.["hydra-acp"]?.amended!==void 0&&t["hydra-acp"].amended!==null,r={kind:"turn-complete"};e!==void 0&&(r.stopReason=e);let o=se(s,"errorMessage");return o!==void 0&&(r.errorMessage=o),n&&(r.amended=!0),r}function Ka(s,e){let n=s._meta?.["hydra-acp"],r=n?.unsolicited===!0;if(e==="turn-started"){let i=n?.cause?.label,a={kind:e,unsolicited:r};return typeof i=="string"&&i.length>0&&(a.cause=i),a}let o={kind:e,unsolicited:r};return typeof n?.reason=="string"&&(o.reason=n.reason),o}function bn(s){if(typeof s=="string")return be(s);if(!s||typeof s!="object")return null;let e=s;return e.type==="text"&&typeof e.text=="string"||typeof e.text=="string"?be(e.text):null}function Kp(s){if(!Array.isArray(s))return null;let e=[];for(let t of s){let n=bn(t);n!==null&&e.push(n)}return e.length===0?null:e.join("")}function se(s,e){let t=s[e];return typeof t=="string"?t:void 0}function Qp(s,e){let t=be(s).split(`
30
30
  `),n=be(e).split(`
31
- `);return t.length>0&&t[t.length-1]===""&&t.pop(),n.length>0&&n[n.length-1]===""&&n.pop(),{oldLines:t,newLines:n}}function td(s,e){let{oldLines:t,newLines:n}=Gp(s,e),r=0,o=0;for(let i of Kp(t,n))i.op==="+"?r++:i.op==="-"&&o++;return{added:r,removed:o}}function Kp(s,e){let t=0,n=Math.min(s.length,e.length);for(;t<n&&s[t]===e[t];)t++;let r=s.length,o=e.length;for(;r>t&&o>t&&s[r-1]===e[o-1];)r--,o--;let i=[];for(let a=0;a<t;a++)i.push({op:"=",text:s[a]});i.push(...Qp(s.slice(t,r),e.slice(t,o)));for(let a=r;a<s.length;a++)i.push({op:"=",text:s[a]});return i}function Qp(s,e){let t=s.length,n=e.length;if(t===0||n===0){let d=[];for(let c of s)d.push({op:"-",text:c});for(let c of e)d.push({op:"+",text:c});return d}let r=Array.from({length:t+1},()=>new Array(n+1).fill(0));for(let d=t-1;d>=0;d--)for(let c=n-1;c>=0;c--)s[d]===e[c]?r[d][c]=r[d+1][c+1]+1:r[d][c]=Math.max(r[d+1][c],r[d][c+1]);let o=[],i=0,a=0;for(;i<t&&a<n;)s[i]===e[a]?(o.push({op:"=",text:s[i]}),i++,a++):r[i+1][a]>=r[i][a+1]?(o.push({op:"-",text:s[i]}),i++):(o.push({op:"+",text:e[a]}),a++);for(;i<t;)o.push({op:"-",text:s[i]}),i++;for(;a<n;)o.push({op:"+",text:e[a]}),a++;return o}var nd="hydra-acp";function Yp(s){let e=0,t=0,n=!1;for(let r of s.split(`
32
- `)){if(r.startsWith("@@")){n=!0;continue}n&&(r.startsWith("+")?e++:r.startsWith("-")&&t++)}return{added:e,removed:t}}function Xp(s){let e=[];for(let t of gs(s))if(t.path!==void 0){if(t.patch!==void 0){t.patch.text!==void 0&&e.push({path:t.path,...Yp(t.patch.text)});continue}t.old!==void 0&&t.old.text===void 0||t.new!==void 0&&t.new.text===void 0||e.push({path:t.path,...td(t.old?.text??"",t.new?.text??"")})}return e}function sd(s){let e=s.update;if(!e||e.sessionUpdate!=="tool_call"&&e.sessionUpdate!=="tool_call_update")return s;let t=Xp(e);if(t.length===0)return s;let n=e._meta??{},r=n[nd]??{};return{...s,update:{...e,_meta:{...n,[nd]:{...r,editStats:t}}}}}var rd=["hydra-acp-","hydra-"];function ro(s){for(let e of rd)if(s.startsWith(e)&&s.length>e.length)return s.slice(e.length)}function od(s){return rd.map(e=>`${e}${s}`)}import{customAlphabet as $d}from"nanoid";function Je(s){return`${s.name}:${s.localId}`}function pt(s){let e=s.indexOf(":");if(e===-1)return;let t=s.slice(0,e),n=s.slice(e+1);if(!(t.length===0||n.length===0))return{name:t,localId:n}}import{createHmac as Zp}from"crypto";function eg(s,e){return Zp("sha256",s).update(e).digest("hex")}function oo(s,e){let t=JSON.stringify(e),n=eg(s.secret,t);fetch(s.callbackUrl,{method:"POST",headers:{"Content-Type":"application/json","X-Hydra-Turn-Notify-Signature":n},body:t}).catch(()=>{})}function vn(s,e){return s!==void 0&&e!==void 0&&s>e}function Wt(s){return{...s.lastTurnEndedAt!==void 0?{lastTurnEndedAt:s.lastTurnEndedAt}:{},...s.readAt!==void 0?{readAt:s.readAt}:{},unread:vn(s.lastTurnEndedAt,s.readAt)}}function ms(s,e,t=Date.now()){let n;if(e){if(s.readAt!==void 0&&!vn(s.lastTurnEndedAt,s.readAt))return;n=Math.max(t,s.lastTurnEndedAt??0)}else s.lastTurnEndedAt!==void 0&&!vn(s.lastTurnEndedAt,s.readAt)&&(n=s.lastTurnEndedAt-1);return n===s.readAt?void 0:n}import*as ad from"fs/promises";var tg=64*1024*1024,ng=1*1024*1024,qt=64*1024,sg=6e4,rg=100,og=1e3,ig=64*1024,ag=256*1024,id=20;function dg(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var hs=class{storage;maxCapacityBytes;currentCapacityBytes;writeCursor=0;closed=!1;waiters=[];filePath;fileCapBytes;fileBytesWritten=0;fileCapReached=!1;onFileCapReached;logWriteError;fileWriteChain=Promise.resolve();constructor(e={}){if(this.maxCapacityBytes=e.capacityBytes??tg,this.maxCapacityBytes<=0)throw new Error("capacityBytes must be > 0");this.currentCapacityBytes=Math.min(ng,this.maxCapacityBytes),this.storage=Buffer.alloc(this.currentCapacityBytes),this.filePath=e.filePath,this.fileCapBytes=e.fileCapBytes??Number.POSITIVE_INFINITY,this.onFileCapReached=e.onFileCapReached,this.logWriteError=e.logWriteError}get capacity(){return this.maxCapacityBytes}get allocatedBytes(){return this.currentCapacityBytes}get writeCursorPos(){return this.writeCursor}get oldestAvailable(){return Math.max(0,this.writeCursor-this.currentCapacityBytes)}get isClosed(){return this.closed}append(e){this.closed||e.length===0||(this.writeRing(e),this.writeCursor+=e.length,this.filePath!==void 0&&this.scheduleFileWrite(e),this.wakeWaiters("data"))}close(){this.closed||(this.closed=!0,this.wakeWaiters("eof"))}read(e,t){let n=Math.max(0,Math.min(t,qt));if(n===0){let l={bytes:Buffer.alloc(0),nextCursor:e};return this.closed&&e>=this.writeCursor&&(l.eof=!0),l}let r=e,o=0,i=this.oldestAvailable;r<i&&(o=i-r,r=i);let a=this.writeCursor-r;if(a<=0){let l={bytes:Buffer.alloc(0),nextCursor:r};return o>0&&(l.gap=o),this.closed&&(l.eof=!0),l}let d=Math.min(a,n),u={bytes:this.sliceFromRing(r,d),nextCursor:r+d};return o>0&&(u.gap=o),this.closed&&r+d>=this.writeCursor&&(u.eof=!0),u}tail(e){let t=Math.max(0,Math.min(e,qt)),n=this.oldestAvailable,r=this.writeCursor-t,o=Math.max(n,r),i=r<n;return{bytes:this.sliceFromRing(o,this.writeCursor-o),startCursor:o,endCursor:this.writeCursor,truncated:i}}head(e){let t=Math.max(0,Math.min(e,qt)),n=this.oldestAvailable,r=n>0,o=n,i=Math.min(this.writeCursor,o+t);return{bytes:this.sliceFromRing(o,i-o),startCursor:o,endCursor:i,truncated:r}}waitForData(e,t){if(e<this.writeCursor)return Promise.resolve("data");if(this.closed)return Promise.resolve("eof");let n=Math.max(0,Math.min(t,sg));return n===0?Promise.resolve("timeout"):new Promise(r=>{let o={resolve:i=>{o.timer!==void 0&&(clearTimeout(o.timer),o.timer=void 0),r(i)},timer:setTimeout(()=>{let i=this.waiters.indexOf(o);i>=0&&this.waiters.splice(i,1),o.timer=void 0,r("timeout")},n)};this.waiters.push(o)})}grep(e){let t=this.oldestAvailable,n=e.cursor,r=n??t,o=0;n!==void 0&&n<t&&(o=t-n,r=t),r>this.writeCursor&&(r=this.writeCursor);let i=this.sliceFromRing(r,this.writeCursor-r),a=e.regex??!0,d=e.caseInsensitive===!0?"i":"",c=a?new RegExp(e.pattern,d):new RegExp(dg(e.pattern),d),u=e.invert??!1,l=Math.max(1,Math.min(e.maxMatches??rg,og)),p=Math.max(1,Math.min(e.maxBytes??ig,ag)),f=Math.max(0,Math.min(e.contextBefore??0,id)),h=Math.max(0,Math.min(e.contextAfter??0,id)),k=[],m=[],g=[],y=0,w=!1,v=0,S=0,b=(R,E)=>{for(let q of g)q.remaining>0&&(q.match.after===void 0&&(q.match.after=[]),q.match.after.push({cursor:R,line:E}),q.remaining--,y+=E.length);for(;g.length>0&&g[0].remaining===0;)g.shift();if(c.test(E)!==u&&k.length<l){let q={cursor:R,line:E};if(f>0&&m.length>0){q.before=m.slice();for(let V of q.before)y+=V.line.length}y+=E.length,k.push(q),h>0&&g.push({match:q,remaining:h})}if(f>0)for(m.push({cursor:R,line:E});m.length>f;)m.shift();let N=k.length>=l&&g.length===0,B=y>=p;return N||B};for(let R=0;R<i.length;R++){if(i[R]!==10)continue;let E=i.subarray(v,R).toString("utf8"),M=r+v;if(v=R+1,S=v,b(M,E)){w=!0;break}}if(!w&&v<i.length&&this.closed){let R=i.subarray(v).toString("utf8"),E=r+v;b(E,R)&&(w=!0),S=i.length}let I=Math.min(r+S,this.writeCursor),C={matches:k,truncated:w,nextCursor:I,scannedBytes:S};return o>0&&(C.gap=o),this.closed&&I>=this.writeCursor&&(C.eof=!0),C}wakeWaiters(e){if(this.waiters.length===0)return;let t=this.waiters;this.waiters=[];for(let n of t)n.resolve(e)}growIfNeeded(e){if(this.currentCapacityBytes>=this.maxCapacityBytes)return;let t=this.writeCursor+e;if(t<=this.currentCapacityBytes)return;let n=this.currentCapacityBytes;for(;n<t&&n<this.maxCapacityBytes;)n=Math.min(this.maxCapacityBytes,n*2);if(n===this.currentCapacityBytes)return;let r=Buffer.alloc(n);this.storage.copy(r,0,0,this.writeCursor),this.storage=r,this.currentCapacityBytes=n}writeRing(e){let t=e.length;if(this.growIfNeeded(t),t>=this.currentCapacityBytes){let o=t-this.currentCapacityBytes;e.copy(this.storage,0,o,t);return}let n=this.writeCursor%this.currentCapacityBytes,r=this.currentCapacityBytes-n;t<=r?e.copy(this.storage,n,0,t):(e.copy(this.storage,n,0,r),e.copy(this.storage,0,r,t))}sliceFromRing(e,t){if(t<=0)return Buffer.alloc(0);let n=Buffer.alloc(t),r=e%this.currentCapacityBytes,o=Math.min(t,this.currentCapacityBytes-r);return this.storage.copy(n,0,r,r+o),o<t&&this.storage.copy(n,o,0,t-o),n}scheduleFileWrite(e){let t=this.filePath;if(t===void 0||this.fileCapReached)return;let n=this.fileCapBytes-this.fileBytesWritten;if(n<=0){this.fileCapReached=!0,this.onFileCapReached?.();return}let r=e.length<=n?e:e.subarray(0,n);this.fileBytesWritten+=r.length;let o=this.fileBytesWritten>=this.fileCapBytes;this.fileWriteChain=this.fileWriteChain.then(()=>ad.appendFile(t,r)).catch(i=>{this.logWriteError?.(i)}),o&&!this.fileCapReached&&(this.fileCapReached=!0,this.onFileCapReached?.())}async drainFileWrites(){await this.fileWriteChain.catch(()=>{})}};var zt=[{verb:"title",name:"hydra title",description:"Regenerate the session title + synopsis via the agent (or set title manually with an arg)"},{verb:"agent",name:"hydra agent",argsHint:"<agent | status>",description:"Schedule a swap to a different agent (synthesizes a brief in the target's idiom, rotates on idle); `status` reports any pending swap"},{verb:"workspace",name:"hydra workspace",argsHint:"<start [name] [--clean] | sync | merge | apply | stop | detach | clean [--deep] | discard | status>",description:"Move this session into an isolated workspace so its edits cannot collide with other work, then land or discard them. `start` copies your uncommitted changes in and leaves the real tree untouched; `start --clean` leaves them behind so the workspace begins at the last commit. `stop` merges and returns; `discard` throws the work away and returns; `detach` returns without merging, leaving the workspace and its branch intact; `merge` lands the work without leaving; `apply` also stays, but delivers the work as ONE staged, uncommitted changeset instead of as the agent's commits, so you review and commit it yourself, with no fast-forward needed, which is what makes it work once the source has moved on; `clean` throws away everything done in the workspace and stays there, putting it back exactly as `start --clean` would have made it (add `--deep` to rebuild dependencies and carried config files too, rather than keeping them); `sync` pulls the source's committed history INTO the workspace, so you can test against what you will land onto, and because landing is fast-forward-only, syncing is also how you recover once the source has moved on. `start <name>` naming a workspace another live session is already in JOINS it instead of making a second one, so two sessions can share a checkout deliberately: edits interleave, `stop` behaves as `detach` while anyone else is still there, and the work lands when the last of them leaves."},{verb:"kill",name:"hydra kill",description:"Close this session (kills the agent; record is kept so it can be resumed later)"},{verb:"restart",name:"hydra restart",description:"Restart the agent with a fresh session/new while preserving conversation history (useful when the proxy has changed available models)"},{verb:"compact",name:"hydra compact",description:"Compact this session's history. Use '/hydra compact status' to inspect current compaction state without triggering."},{verb:"uncompact",name:"hydra uncompact",description:"Roll back the most recent compaction swap (only available immediately after a swap, before any new turns)"},{verb:"clear",name:"hydra clear",description:"Drop every turn of this conversation, this command included, and restart the agent with no context"},{verb:"fork",name:"hydra fork",argsHint:"[--verbatim] [prompt]",description:"Fork this conversation into a new session (default: synthesis mode with a synopsis brief; pass --verbatim to slice at the last completed turn instead). A prompt is sent to the fork as its first turn once it's ready."},{verb:"config",name:"hydra config",argsHint:"[<id> [<value>]]",description:"List or set an agent-advertised configOption (model, mode, effort, etc.). With no args, lists all options; with <id>, shows its choices; with <id> <value>, applies it."}],Eb=new Map(zt.map(s=>[s.verb,s]));function dd(s){let e=s.lastIndexOf("/");return(e===-1?s:s.slice(e+1)).toLowerCase()}function Jt(s,e){return Vt(s,e.map(t=>t.modelId))}function Vt(s,e){if(e.length===0)return{kind:"none",requested:s};if(e.includes(s))return{kind:"exact",modelId:s};let t=dd(s),n=e.filter(o=>dd(o)===t);if(n.length===1)return{kind:"resolved",modelId:n[0],requested:s};if(n.length>1)return{kind:"ambiguous",requested:s,candidates:n};let r=s.toLowerCase();if(r.length>0){let o=e.filter(i=>i.toLowerCase().includes(r));if(o.length===1)return{kind:"resolved",modelId:o[0],requested:s};if(o.length>1)return{kind:"ambiguous",requested:s,candidates:o}}return{kind:"unknown",requested:s}}var cg="Compact conversation",ug="contextCompaction",lg=`
31
+ `);return t.length>0&&t[t.length-1]===""&&t.pop(),n.length>0&&n[n.length-1]===""&&n.pop(),{oldLines:t,newLines:n}}function sd(s,e){let{oldLines:t,newLines:n}=Qp(s,e),r=0,o=0;for(let i of Yp(t,n))i.op==="+"?r++:i.op==="-"&&o++;return{added:r,removed:o}}function Yp(s,e){let t=0,n=Math.min(s.length,e.length);for(;t<n&&s[t]===e[t];)t++;let r=s.length,o=e.length;for(;r>t&&o>t&&s[r-1]===e[o-1];)r--,o--;let i=[];for(let a=0;a<t;a++)i.push({op:"=",text:s[a]});i.push(...Xp(s.slice(t,r),e.slice(t,o)));for(let a=r;a<s.length;a++)i.push({op:"=",text:s[a]});return i}function Xp(s,e){let t=s.length,n=e.length;if(t===0||n===0){let d=[];for(let c of s)d.push({op:"-",text:c});for(let c of e)d.push({op:"+",text:c});return d}let r=Array.from({length:t+1},()=>new Array(n+1).fill(0));for(let d=t-1;d>=0;d--)for(let c=n-1;c>=0;c--)s[d]===e[c]?r[d][c]=r[d+1][c+1]+1:r[d][c]=Math.max(r[d+1][c],r[d][c+1]);let o=[],i=0,a=0;for(;i<t&&a<n;)s[i]===e[a]?(o.push({op:"=",text:s[i]}),i++,a++):r[i+1][a]>=r[i][a+1]?(o.push({op:"-",text:s[i]}),i++):(o.push({op:"+",text:e[a]}),a++);for(;i<t;)o.push({op:"-",text:s[i]}),i++;for(;a<n;)o.push({op:"+",text:e[a]}),a++;return o}var rd="hydra-acp";function Zp(s){let e=0,t=0,n=!1;for(let r of s.split(`
32
+ `)){if(r.startsWith("@@")){n=!0;continue}n&&(r.startsWith("+")?e++:r.startsWith("-")&&t++)}return{added:e,removed:t}}function eg(s){let e=[];for(let t of hs(s))if(t.path!==void 0){if(t.patch!==void 0){t.patch.text!==void 0&&e.push({path:t.path,...Zp(t.patch.text)});continue}t.old!==void 0&&t.old.text===void 0||t.new!==void 0&&t.new.text===void 0||e.push({path:t.path,...sd(t.old?.text??"",t.new?.text??"")})}return e}function od(s){let e=s.update;if(!e||e.sessionUpdate!=="tool_call"&&e.sessionUpdate!=="tool_call_update")return s;let t=eg(e);if(t.length===0)return s;let n=e._meta??{},r=n[rd]??{};return{...s,update:{...e,_meta:{...n,[rd]:{...r,editStats:t}}}}}var id=["hydra-acp-","hydra-"];function io(s){for(let e of id)if(s.startsWith(e)&&s.length>e.length)return s.slice(e.length)}function ad(s){return id.map(e=>`${e}${s}`)}import{customAlphabet as Fd}from"nanoid";function Je(s){return`${s.name}:${s.localId}`}function gt(s){let e=s.indexOf(":");if(e===-1)return;let t=s.slice(0,e),n=s.slice(e+1);if(!(t.length===0||n.length===0))return{name:t,localId:n}}import{createHmac as tg}from"crypto";function ng(s,e){return tg("sha256",s).update(e).digest("hex")}function ao(s,e){let t=JSON.stringify(e),n=ng(s.secret,t);fetch(s.callbackUrl,{method:"POST",headers:{"Content-Type":"application/json","X-Hydra-Turn-Notify-Signature":n},body:t}).catch(()=>{})}function Sn(s,e){return s!==void 0&&e!==void 0&&s>e}function qt(s){return{...s.lastTurnEndedAt!==void 0?{lastTurnEndedAt:s.lastTurnEndedAt}:{},...s.readAt!==void 0?{readAt:s.readAt}:{},unread:Sn(s.lastTurnEndedAt,s.readAt)}}function ys(s,e,t=Date.now()){let n;if(e){if(s.readAt!==void 0&&!Sn(s.lastTurnEndedAt,s.readAt))return;n=Math.max(t,s.lastTurnEndedAt??0)}else s.lastTurnEndedAt!==void 0&&!Sn(s.lastTurnEndedAt,s.readAt)&&(n=s.lastTurnEndedAt-1);return n===s.readAt?void 0:n}import*as cd from"fs/promises";var sg=64*1024*1024,rg=1*1024*1024,zt=64*1024,og=6e4,ig=100,ag=1e3,dg=64*1024,cg=256*1024,dd=20;function ug(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var ws=class{storage;maxCapacityBytes;currentCapacityBytes;writeCursor=0;closed=!1;waiters=[];filePath;fileCapBytes;fileBytesWritten=0;fileCapReached=!1;onFileCapReached;logWriteError;fileWriteChain=Promise.resolve();constructor(e={}){if(this.maxCapacityBytes=e.capacityBytes??sg,this.maxCapacityBytes<=0)throw new Error("capacityBytes must be > 0");this.currentCapacityBytes=Math.min(rg,this.maxCapacityBytes),this.storage=Buffer.alloc(this.currentCapacityBytes),this.filePath=e.filePath,this.fileCapBytes=e.fileCapBytes??Number.POSITIVE_INFINITY,this.onFileCapReached=e.onFileCapReached,this.logWriteError=e.logWriteError}get capacity(){return this.maxCapacityBytes}get allocatedBytes(){return this.currentCapacityBytes}get writeCursorPos(){return this.writeCursor}get oldestAvailable(){return Math.max(0,this.writeCursor-this.currentCapacityBytes)}get isClosed(){return this.closed}append(e){this.closed||e.length===0||(this.writeRing(e),this.writeCursor+=e.length,this.filePath!==void 0&&this.scheduleFileWrite(e),this.wakeWaiters("data"))}close(){this.closed||(this.closed=!0,this.wakeWaiters("eof"))}read(e,t){let n=Math.max(0,Math.min(t,zt));if(n===0){let l={bytes:Buffer.alloc(0),nextCursor:e};return this.closed&&e>=this.writeCursor&&(l.eof=!0),l}let r=e,o=0,i=this.oldestAvailable;r<i&&(o=i-r,r=i);let a=this.writeCursor-r;if(a<=0){let l={bytes:Buffer.alloc(0),nextCursor:r};return o>0&&(l.gap=o),this.closed&&(l.eof=!0),l}let d=Math.min(a,n),u={bytes:this.sliceFromRing(r,d),nextCursor:r+d};return o>0&&(u.gap=o),this.closed&&r+d>=this.writeCursor&&(u.eof=!0),u}tail(e){let t=Math.max(0,Math.min(e,zt)),n=this.oldestAvailable,r=this.writeCursor-t,o=Math.max(n,r),i=r<n;return{bytes:this.sliceFromRing(o,this.writeCursor-o),startCursor:o,endCursor:this.writeCursor,truncated:i}}head(e){let t=Math.max(0,Math.min(e,zt)),n=this.oldestAvailable,r=n>0,o=n,i=Math.min(this.writeCursor,o+t);return{bytes:this.sliceFromRing(o,i-o),startCursor:o,endCursor:i,truncated:r}}waitForData(e,t){if(e<this.writeCursor)return Promise.resolve("data");if(this.closed)return Promise.resolve("eof");let n=Math.max(0,Math.min(t,og));return n===0?Promise.resolve("timeout"):new Promise(r=>{let o={resolve:i=>{o.timer!==void 0&&(clearTimeout(o.timer),o.timer=void 0),r(i)},timer:setTimeout(()=>{let i=this.waiters.indexOf(o);i>=0&&this.waiters.splice(i,1),o.timer=void 0,r("timeout")},n)};this.waiters.push(o)})}grep(e){let t=this.oldestAvailable,n=e.cursor,r=n??t,o=0;n!==void 0&&n<t&&(o=t-n,r=t),r>this.writeCursor&&(r=this.writeCursor);let i=this.sliceFromRing(r,this.writeCursor-r),a=e.regex??!0,d=e.caseInsensitive===!0?"i":"",c=a?new RegExp(e.pattern,d):new RegExp(ug(e.pattern),d),u=e.invert??!1,l=Math.max(1,Math.min(e.maxMatches??ig,ag)),p=Math.max(1,Math.min(e.maxBytes??dg,cg)),f=Math.max(0,Math.min(e.contextBefore??0,dd)),h=Math.max(0,Math.min(e.contextAfter??0,dd)),k=[],m=[],g=[],y=0,w=!1,v=0,S=0,b=(x,T)=>{for(let q of g)q.remaining>0&&(q.match.after===void 0&&(q.match.after=[]),q.match.after.push({cursor:x,line:T}),q.remaining--,y+=T.length);for(;g.length>0&&g[0].remaining===0;)g.shift();if(c.test(T)!==u&&k.length<l){let q={cursor:x,line:T};if(f>0&&m.length>0){q.before=m.slice();for(let V of q.before)y+=V.line.length}y+=T.length,k.push(q),h>0&&g.push({match:q,remaining:h})}if(f>0)for(m.push({cursor:x,line:T});m.length>f;)m.shift();let N=k.length>=l&&g.length===0,B=y>=p;return N||B};for(let x=0;x<i.length;x++){if(i[x]!==10)continue;let T=i.subarray(v,x).toString("utf8"),M=r+v;if(v=x+1,S=v,b(M,T)){w=!0;break}}if(!w&&v<i.length&&this.closed){let x=i.subarray(v).toString("utf8"),T=r+v;b(T,x)&&(w=!0),S=i.length}let I=Math.min(r+S,this.writeCursor),A={matches:k,truncated:w,nextCursor:I,scannedBytes:S};return o>0&&(A.gap=o),this.closed&&I>=this.writeCursor&&(A.eof=!0),A}wakeWaiters(e){if(this.waiters.length===0)return;let t=this.waiters;this.waiters=[];for(let n of t)n.resolve(e)}growIfNeeded(e){if(this.currentCapacityBytes>=this.maxCapacityBytes)return;let t=this.writeCursor+e;if(t<=this.currentCapacityBytes)return;let n=this.currentCapacityBytes;for(;n<t&&n<this.maxCapacityBytes;)n=Math.min(this.maxCapacityBytes,n*2);if(n===this.currentCapacityBytes)return;let r=Buffer.alloc(n);this.storage.copy(r,0,0,this.writeCursor),this.storage=r,this.currentCapacityBytes=n}writeRing(e){let t=e.length;if(this.growIfNeeded(t),t>=this.currentCapacityBytes){let o=t-this.currentCapacityBytes;e.copy(this.storage,0,o,t);return}let n=this.writeCursor%this.currentCapacityBytes,r=this.currentCapacityBytes-n;t<=r?e.copy(this.storage,n,0,t):(e.copy(this.storage,n,0,r),e.copy(this.storage,0,r,t))}sliceFromRing(e,t){if(t<=0)return Buffer.alloc(0);let n=Buffer.alloc(t),r=e%this.currentCapacityBytes,o=Math.min(t,this.currentCapacityBytes-r);return this.storage.copy(n,0,r,r+o),o<t&&this.storage.copy(n,o,0,t-o),n}scheduleFileWrite(e){let t=this.filePath;if(t===void 0||this.fileCapReached)return;let n=this.fileCapBytes-this.fileBytesWritten;if(n<=0){this.fileCapReached=!0,this.onFileCapReached?.();return}let r=e.length<=n?e:e.subarray(0,n);this.fileBytesWritten+=r.length;let o=this.fileBytesWritten>=this.fileCapBytes;this.fileWriteChain=this.fileWriteChain.then(()=>cd.appendFile(t,r)).catch(i=>{this.logWriteError?.(i)}),o&&!this.fileCapReached&&(this.fileCapReached=!0,this.onFileCapReached?.())}async drainFileWrites(){await this.fileWriteChain.catch(()=>{})}};var Jt=[{verb:"title",name:"hydra title",description:"Regenerate the session title + synopsis via the agent (or set title manually with an arg)"},{verb:"agent",name:"hydra agent",argsHint:"<agent | status>",description:"Schedule a swap to a different agent (synthesizes a brief in the target's idiom, rotates on idle); `status` reports any pending swap"},{verb:"workspace",name:"hydra workspace",argsHint:"<start [name] [--clean] | sync | merge | apply | stop | detach | clean [--deep] | discard | status>",description:"Move this session into an isolated workspace so its edits cannot collide with other work, then land or discard them. `start` copies your uncommitted changes in and leaves the real tree untouched; `start --clean` leaves them behind so the workspace begins at the last commit. `stop` merges and returns; `discard` throws the work away and returns; `detach` returns without merging, leaving the workspace and its branch intact; `merge` lands the work without leaving; `apply` also stays, but delivers the work as ONE staged, uncommitted changeset instead of as the agent's commits, so you review and commit it yourself, with no fast-forward needed, which is what makes it work once the source has moved on; `clean` throws away everything done in the workspace and stays there, putting it back exactly as `start --clean` would have made it (add `--deep` to rebuild dependencies and carried config files too, rather than keeping them); `sync` pulls the source's committed history INTO the workspace, so you can test against what you will land onto, and because landing is fast-forward-only, syncing is also how you recover once the source has moved on. `start <name>` naming a workspace another live session is already in JOINS it instead of making a second one, so two sessions can share a checkout deliberately: edits interleave, `stop` behaves as `detach` while anyone else is still there, and the work lands when the last of them leaves."},{verb:"kill",name:"hydra kill",description:"Close this session (kills the agent; record is kept so it can be resumed later)"},{verb:"restart",name:"hydra restart",description:"Restart the agent with a fresh session/new while preserving conversation history (useful when the proxy has changed available models)"},{verb:"compact",name:"hydra compact",description:"Compact this session's history. Use '/hydra compact status' to inspect current compaction state without triggering."},{verb:"uncompact",name:"hydra uncompact",description:"Roll back the most recent compaction swap (only available immediately after a swap, before any new turns)"},{verb:"clear",name:"hydra clear",description:"Drop every turn of this conversation, this command included, and restart the agent with no context"},{verb:"fork",name:"hydra fork",argsHint:"[--verbatim] [prompt]",description:"Fork this conversation into a new session (default: synthesis mode with a synopsis brief; pass --verbatim to slice at the last completed turn instead). A prompt is sent to the fork as its first turn once it's ready."},{verb:"config",name:"hydra config",argsHint:"[<id> [<value>]]",description:"List or set an agent-advertised configOption (model, mode, effort, etc.). With no args, lists all options; with <id>, shows its choices; with <id> <value>, applies it."}],Pb=new Map(Jt.map(s=>[s.verb,s]));function ud(s){let e=s.lastIndexOf("/");return(e===-1?s:s.slice(e+1)).toLowerCase()}function Vt(s,e){return Gt(s,e.map(t=>t.modelId))}function Gt(s,e){if(e.length===0)return{kind:"none",requested:s};if(e.includes(s))return{kind:"exact",modelId:s};let t=ud(s),n=e.filter(o=>ud(o)===t);if(n.length===1)return{kind:"resolved",modelId:n[0],requested:s};if(n.length>1)return{kind:"ambiguous",requested:s,candidates:n};let r=s.toLowerCase();if(r.length>0){let o=e.filter(i=>i.toLowerCase().includes(r));if(o.length===1)return{kind:"resolved",modelId:o[0],requested:s};if(o.length>1)return{kind:"ambiguous",requested:s,candidates:o}}return{kind:"unknown",requested:s}}var lg="Compact conversation",fg="contextCompaction",pg=`
33
33
 
34
- Compacting completed.`;function fg(s){if(!s||s.status!=="completed"||s.sessionUpdate!=="tool_call"&&s.sessionUpdate!=="tool_call_update")return!1;let e=s._meta,t=e!==null&&typeof e=="object"&&ug in e;return s.title===cg||t}function pg(s){if(!s||s.sessionUpdate!=="agent_message_chunk")return!1;let e=s.content;return!e||typeof e!="object"||Array.isArray(e)?!1:e.text===lg}function ud(s){return fg(s)||pg(s)}var cd=[`## Objective
34
+ Compacting completed.`;function gg(s){if(!s||s.status!=="completed"||s.sessionUpdate!=="tool_call"&&s.sessionUpdate!=="tool_call_update")return!1;let e=s._meta,t=e!==null&&typeof e=="object"&&fg in e;return s.title===lg||t}function mg(s){if(!s||s.sessionUpdate!=="agent_message_chunk")return!1;let e=s.content;return!e||typeof e!="object"||Array.isArray(e)?!1:e.text===pg}function fd(s){return gg(s)||mg(s)}var ld=[`## Objective
35
35
  `,`## Important Details
36
- `],gg=8e3,mg=2e4,hg=.5;function ld(s,e){return s!==void 0&&s>=mg&&e>0&&e<s*hg}var ys=class{messageId;buffer="";settled=!1;feed(e){if(!e||e.sessionUpdate!=="agent_message_chunk")return!1;let t=e.content;if(!t||typeof t!="object"||Array.isArray(t))return!1;let n=t.text;if(typeof n!="string")return!1;let r=typeof e.messageId=="string"?e.messageId:void 0;if((r===void 0||r!==this.messageId)&&(this.messageId=r,this.buffer="",this.settled=r===void 0),this.settled)return!1;this.buffer+=n;let o=cd[0],i=this.buffer.slice(0,o.length);return!o.startsWith(i)||this.buffer.length>gg?(this.settled=!0,this.buffer="",!1):cd.every(a=>this.buffer.includes(a))?(this.settled=!0,this.buffer="",!0):!1}};var fd=`[older history truncated]
37
- `,pd=["file_path","filePath","path","command","pattern","query"];function Gt(s,e={}){let t=e.maxChars??4e5,n=io(s),r=[],o="",i=e.toolOutput?.maxTotal??0,a=()=>{o.length!==0&&(r.push(`Assistant: ${o}`),o="")};for(let d of s){if(d.method!=="session/update")continue;let u=d.params?.update;if(!u||typeof u.sessionUpdate!="string")continue;let l=u.sessionUpdate;if(l==="prompt_received"){a();let p=lo(u.prompt).trim();p.length>0&&r.push(`User: ${p}`)}else if(l==="agent_message_chunk"){let p=fo(u.content);p.length>0&&(o+=p)}else if(l==="tool_call"){if(a(),r.push(uo(u,n)),e.toolOutput!==void 0){let p=co(u),f=p!==void 0?n.get(p)?.output:void 0;if(f!==void 0&&i>0){let h=Math.min(e.toolOutput.maxPerCall,i),k=f.length<=h?f:`${f.slice(0,h)}\u2026[${f.length-h} more chars]`;r.push(`Output: ${k}`),i-=Math.min(k.length,h)}}}else if(l==="turn_complete"){a();let p=u.errorMessage;typeof p=="string"&&p.length>0&&r.push(`Error: turn failed: ${p}`)}}return a(),Ig(r.join(`
38
- `),t)}function io(s){let e=new Map;for(let t of s){if(t.method!=="session/update")continue;let r=t.params?.update;if(!r)continue;let o=r.sessionUpdate;if(o!=="tool_call"&&o!=="tool_call_update")continue;let i=co(r);if(i===void 0)continue;let a=e.get(i);if(a===void 0&&(a={name:"(unnamed)",rawInput:{}},e.set(i,a)),a.name==="(unnamed)"){let c=wg(r,o);c!==void 0&&(a.name=c)}if(a.kind===void 0&&typeof r.kind=="string"&&r.kind.length>0&&(a.kind=r.kind),a.output===void 0){let c=ws(r);c!==void 0&&(a.output=c)}let d=r.rawInput;d&&typeof d=="object"&&!Array.isArray(d)&&Object.assign(a.rawInput,d)}for(let t of e.values())t.name=ao(t);return e}function ao(s){return yg(s)?s.kind??"(unnamed)":s.name}function yg(s){for(let e of pd){let t=s.rawInput[e];if(!(typeof t!="string"||t.length===0)&&(t===s.name||s.name.length>=12&&t.startsWith(s.name)))return!0}return!1}function wg(s,e){let t=bn(s);if(t!==void 0)return t;if(typeof s.name=="string"&&s.name.length>0)return s.name;if(e==="tool_call"&&typeof s.title=="string"&&s.title.length>0)return s.title}function co(s){let e=s.toolCallId;if(typeof e=="string"&&e.length>0)return e}function ws(s){let e=kg(s);if(e!==void 0)return e;let t=s.rawOutput;if(typeof t=="string")return t.length>0?t:void 0;if(t&&typeof t=="object"&&!Array.isArray(t)){let n=t.output;if(typeof n=="string")return n.length>0?n:void 0}}function kg(s){let e=s._meta;if(!e||typeof e!="object")return;let t=e.claudeCode;if(!t||typeof t!="object")return;let n=t.toolResponse;if(typeof n=="string")return n.length>0?n:void 0;if(!n||typeof n!="object")return;let{stdout:r,stderr:o}=n,i=[];if(typeof r=="string"&&r.length>0&&i.push(r),typeof o=="string"&&o.length>0&&i.push(`[stderr] ${o}`),i.length!==0)return i.join(`
39
- `)}function bn(s){let e=s._meta;if(!e||typeof e!="object")return;let t=e.claudeCode;if(!t||typeof t!="object")return;let n=t.toolName;if(typeof n=="string"&&n.length>0)return n}function uo(s,e){let t=co(s),n=t!==void 0?e?.get(t):void 0,r=n?.name??vg(s),o=bg(n?.rawInput??s.rawInput);return o.length===0?`Tool: ${r}`:`Tool: ${r}(${o.join(", ")})`}function vg(s){let e=bn(s);return e!==void 0?e:typeof s.name=="string"&&s.name.length>0?s.name:typeof s.title=="string"&&s.title.length>0?s.title:"(unnamed)"}function bg(s){if(!s||typeof s!="object"||Array.isArray(s))return[];let e=s,t=[];for(let n of pd){let r=e[n];typeof r=="string"&&r.length>0&&t.push(`${n}=${Sg(r,600)}`)}return t}function lo(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>{if(e&&typeof e=="object"){let t=e.text;if(typeof t=="string")return t}return""}).join(""):""}function fo(s){if(!s||typeof s!="object")return"";let e=s.text;return typeof e=="string"?e:""}function Sg(s,e){return s.length<=e?s:s.slice(0,e-1)+"\u2026"}function Ig(s,e){if(s.length<=e)return s;let t=s.split(`
40
- `);for(;t.length>0;){let n=fd+t.join(`
41
- `);if(n.length<=e)return n;t.shift()}return fd}var gd="(untitled)";function po(s){let e=[],t=s.synopsis;if(t!==void 0){e.push("--- begin prior session compaction ---"),e.push(`[Title] ${s.title??gd}`),t.goal!==void 0&&t.goal.trim().length>0&&e.push(`[Goal] ${t.goal}`),t.outcome!==void 0&&t.outcome.trim().length>0&&e.push(`[Outcome] ${t.outcome}`);let d=Sn("Open threads",t.open_threads);d.length>0&&e.push(d);let c=Sn("Decisions",t.decisions);c.length>0&&e.push(c);let u=Sn("File edit intentions",t.file_edit_intentions);u.length>0&&e.push(u);let l=Sn("Unresolved errors",t.unresolved_errors);l.length>0&&e.push(l);let p=Sn("Tool state",t.tool_state);p.length>0&&e.push(p);let f=md(t.files_touched);f.length>0&&e.push(`[Files previously touched] ${f}`);let h=md(t.tools_used);h.length>0&&e.push(`[Tools previously used] ${h}`),e.push("--- end prior session compaction ---")}else e.push(`[Title] ${s.title??gd}`);s.note!==void 0&&s.note.trim().length>0&&e.push(`[Situation] ${s.note.trim()}`);let{closedText:n,openText:r,keptCount:o}=Ag(s.tail,s.tailK,s.watermark??0,s.tailFloor??0);e.push("--- begin recent turns (verbatim, last "+o+") ---"),n.length>0&&e.push(n),e.push("--- end recent turns ---"),r.length>0&&(e.push("--- begin current in-flight turn (no completion yet) ---"),e.push(r),e.push("--- end current in-flight turn ---"));let i=s.recallArmed??!0;e.push("");let a=s.framing??(t!==void 0?"compaction":"fork");return a==="swap"?e.push(i?"(This session's agent process was replaced; nothing was summarized away. The turns above are the most recent; earlier history is available on demand via the hydra-recall tools. Do NOT call any tools yet. Do NOT read any files or run any commands. Reply with the single word 'OK' and wait for the next user message.)":"(This session's agent process was replaced; nothing was summarized away. The turns above are the most recent. Do NOT call any tools yet. Do NOT read any files or run any commands. Reply with the single word 'OK' and wait for the next user message.)"):a==="compaction"&&i?e.push("(Hydra has compacted earlier conversation. Do NOT call any tools yet. Do NOT read any files, run any commands, or invoke hydra-recall. Reply with the single word 'OK' and wait for the next user message \u2014 at that point you can use the hydra-recall tools to look up specifics on demand if needed.)"):a==="compaction"?e.push("(Hydra has compacted earlier conversation; the turns above are what survives. Do NOT call any tools yet. Do NOT read any files or run any commands. Reply with the single word 'OK' and wait for the next user message.)"):i?e.push("(This is a side conversation forked from another session. The turns above are the most recent; earlier history is available on demand via the hydra-recall tools. Do NOT call any tools yet. Do NOT read any files or run any commands. Reply with the single word 'OK' and wait for the next user message.)"):e.push("(This is a side conversation forked from another session. The turns above are the most recent. Do NOT call any tools yet. Do NOT read any files or run any commands. Reply with the single word 'OK' and wait for the next user message.)"),e.join(`
42
- `)}function Sn(s,e){if(!e||!Array.isArray(e))return"";let t=e.filter(r=>typeof r=="string"&&r.trim().length>0);if(t.length===0)return"";let n=t.map(r=>"- "+r.trim());return`[${s}] ${n.join(`
43
- `)}`}function md(s){if(!s||!Array.isArray(s))return"";let e=s.filter(t=>typeof t=="string"&&t.trim().length>0);return e.length===0?"":e.map(t=>t.trim()).join(", ")}function Ag(s,e,t,n){if(s.length===0)return{closedText:"",openText:"",keptCount:0};let{closed:r,open:o}=Cg(s),i=0,a=[];if(e>0&&r.length>0){let u=r.filter(f=>f.startEntryIndex>=t).length,l=Math.max(u,n),p=Math.min(l,e,r.length);i=p,a=p>0?r.slice(-p):[]}let d=a.length>0?hd(a):"",c=o?hd([o]):"";return{closedText:d,openText:c,keptCount:i}}function hd(s){let e=[];for(let t of s){t.user.length>0&&e.push("User: "+t.user),t.agent.length>0&&e.push("Assistant: "+t.agent);for(let n of t.tools)e.push(n)}return e.join(`
44
- `)}function Cg(s){let e=[],t=null,n=io(s);for(let o=0;o<s.length;o++){let i=s[o];if(i.method!=="session/update")continue;let d=i.params?.update;if(!d||typeof d.sessionUpdate!="string")continue;let c=d.sessionUpdate;if(c==="prompt_received")t!==null&&t.user.length>0&&e.push(t),t={user:lo(d.prompt).trim(),agent:"",tools:[],startEntryIndex:o};else if(c==="agent_message_chunk"&&t!==null){let u=fo(d.content);u.length>0&&(t.agent+=u)}else c==="tool_call"&&t!==null?t.tools.push(uo(d,n)):c==="turn_complete"&&t!==null&&(e.push(t),t=null)}let r=t!==null&&t.user.length>0?t:null;return{closed:e,open:r}}function wd(s,e){let t=s??[],n=(e??0)>0,r=[],o=new Set,i=t[0];i&&o.add(i.upstreamSessionId);for(let d=1;d<t.length;d++){let c=t[d],u=t[d-1],l={upstreamSessionId:c.upstreamSessionId,agentId:c.agentId,...c.startedAt!==void 0?{at:c.startedAt}:{},...c.endedAt!==void 0?{endedAt:c.endedAt}:{},...c.cost!==void 0?{cost:c.cost}:{},...c.usedAtStart!==void 0?{usedAfter:c.usedAtStart}:{},...u.usedAtEnd!==void 0?{usedBefore:u.usedAtEnd}:{},...c.reason!==void 0?{reason:c.reason}:{},...c.runId!==void 0?{runId:c.runId}:{}};c.reason===void 0&&(c.agentId!==u.agentId?l.inferredReason="agent-swap":o.has(c.upstreamSessionId)?l.inferredReason="rollback":n||(l.notCompaction=!0)),o.add(c.upstreamSessionId),r.push(l)}let a=r.filter(d=>d.reason==="compaction");return{rotations:r,compactions:a,runs:Rg(a),unknownCount:r.filter(d=>d.reason===void 0&&d.inferredReason===void 0&&!d.notCompaction).length}}function Rg(s){let e=[],t;for(let n of s){let r=e[e.length-1];if(r!==void 0&&n.runId!==void 0&&n.runId===t){r.swaps++,r.upstreamSessionId=n.upstreamSessionId,r.current=n.endedAt===void 0,n.cost!==void 0&&(r.cost=(r.cost??0)+n.cost),n.usedAfter!==void 0&&(r.usedAfter=n.usedAfter);continue}e.push({...n.at!==void 0?{at:n.at}:{},upstreamSessionId:n.upstreamSessionId,swaps:1,...n.cost!==void 0?{cost:n.cost}:{},...n.usedBefore!==void 0?{usedBefore:n.usedBefore}:{},...n.usedAfter!==void 0?{usedAfter:n.usedAfter}:{},current:n.endedAt===void 0}),t=n.runId}return e}function xg(s){if(!s)return"unknown time";let e=Date.parse(s);return Number.isNaN(e)?"unknown time":`${new Date(e).toISOString().slice(0,16)}Z`}function yd(s){if(s<1e3)return String(s);let e=s/1e3;return e<100?`${e.toFixed(1)}k`:`${Math.round(e)}k`}function Eg(s){return s.usedBefore===void 0||s.usedAfter===void 0?"":` ${yd(s.usedBefore)} \u2192 ${yd(s.usedAfter)}`}function kd(s){let{runs:e,unknownCount:t}=s,n=[];if(e.length>0){n.push(e.length===1?"Compacted 1 time:":`Compacted ${e.length} times:`);for(let r of e){let o=Eg(r),i=r.cost!==void 0?` $${r.cost.toFixed(2)}`:"",a=r.current?" (current)":"",d=r.swaps>1?` (${r.swaps} swaps)`:"";n.push(` ${xg(r.at)} ${r.upstreamSessionId}${o}${i}${d}${a}`)}}if(t>0){let r=t===1?"rotation":"rotations";n.push(e.length>0?`${t} earlier ${r}, cause not recorded; the count above is a lower bound.`:`No compactions on record. ${t} ${r} predate reason tracking, and any of them may have been a compaction.`)}return n}import*as gt from"path";function Tg(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function go(s,e,t){if(e.length===0||e===t)return{text:s,rewritten:[]};let n=e.endsWith("/")?e.slice(0,-1):e,r=t.endsWith("/")?t.slice(0,-1):t,o=[],i=new RegExp(`${Tg(n)}/(?![/\\s])`,"g");return{text:s.replace(i,(d,c)=>{let u=s.slice(c+d.length),l=u.search(/[\s"'`,;:)\]}]|$/);return o.push(`${n}/${u.slice(0,l<0?void 0:l)}`),`${r}/`}),rewritten:o}}function mo(s,e){if(e.length===0)return!1;let t=e.endsWith("/")?e.slice(0,-1):e;return s.includes(t)}function vd(s){let e=[];return e.push("[workspace] You have LEFT the isolated workspace."),e.push(`- Your working directory is now ${s.sourceCwd}`),e.push(s.removed?`- The workspace at ${s.formerWorkspacePath} has been removed. Paths under it from earlier in this conversation no longer exist.`:`- The workspace at ${s.formerWorkspacePath} still exists but is NO LONGER YOURS. Editing anything under it is wasted: that work will not reach ${s.sourceCwd}.`),e.push("- Earlier turns refer to files by their workspace paths. Treat those as referring to the same files under your current working directory, and prefer repo-relative paths from here on."),e.join(`
45
- `)}function bd(s){let e=[];e.push(s.reassert===!0?"[workspace] Reminder: you are NOT working in the directory that path names.":"[workspace] Before anything else, note where you are working:"),e.push(`- Your working directory is ${s.workspacePath}`),e.push(`- It is an isolated copy of ${s.sourceCwd}`),e.push(`- Any absolute path under ${s.sourceCwd} refers to the matching file under your working directory. Do not read or write ${s.sourceCwd} directly.`),e.push("- Prefer repo-relative paths (`src/foo.ts`). They are identical in both trees, so they cannot be misread.");for(let t of s.notes)e.push(`- ${t}`);return e.join(`
46
- `)}function Sd(s,e,t){return s.length===0||!gt.isAbsolute(s)||ks(s,t)?!1:ks(s,e)}function ks(s,e){let t=gt.relative(gt.resolve(e),gt.resolve(s));return!(t.length===0||t.startsWith("..")||gt.isAbsolute(t))}Y();import*as Ve from"fs/promises";async function In(s,e){let t=T.queueFile(s);if(e.length===0){await Ve.unlink(t).catch(()=>{});return}await Ve.mkdir(T.sessionDir(s),{recursive:!0});let n=e.map(r=>JSON.stringify(r)).join(`
36
+ `],hg=8e3,yg=2e4,wg=.5;function pd(s,e){return s!==void 0&&s>=yg&&e>0&&e<s*wg}var ks=class{messageId;buffer="";settled=!1;feed(e){if(!e||e.sessionUpdate!=="agent_message_chunk")return!1;let t=e.content;if(!t||typeof t!="object"||Array.isArray(t))return!1;let n=t.text;if(typeof n!="string")return!1;let r=typeof e.messageId=="string"?e.messageId:void 0;if((r===void 0||r!==this.messageId)&&(this.messageId=r,this.buffer="",this.settled=r===void 0),this.settled)return!1;this.buffer+=n;let o=ld[0],i=this.buffer.slice(0,o.length);return!o.startsWith(i)||this.buffer.length>hg?(this.settled=!0,this.buffer="",!1):ld.every(a=>this.buffer.includes(a))?(this.settled=!0,this.buffer="",!0):!1}};var gd=`[older history truncated]
37
+ `,md=["file_path","filePath","path","command","pattern","query"];function Kt(s,e={}){let t=e.maxChars??4e5,n=co(s),r=[],o="",i=e.toolOutput?.maxTotal??0,a=()=>{o.length!==0&&(r.push(`Assistant: ${o}`),o="")};for(let d of s){if(d.method!=="session/update")continue;let u=d.params?.update;if(!u||typeof u.sessionUpdate!="string")continue;let l=u.sessionUpdate;if(l==="prompt_received"){a();let p=po(u.prompt).trim();p.length>0&&r.push(`User: ${p}`)}else if(l==="agent_message_chunk"){let p=go(u.content);p.length>0&&(o+=p)}else if(l==="tool_call"){if(a(),r.push(fo(u,n)),e.toolOutput!==void 0){let p=lo(u),f=p!==void 0?n.get(p)?.output:void 0;if(f!==void 0&&i>0){let h=Math.min(e.toolOutput.maxPerCall,i),k=f.length<=h?f:`${f.slice(0,h)}\u2026[${f.length-h} more chars]`;r.push(`Output: ${k}`),i-=Math.min(k.length,h)}}}else if(l==="turn_complete"){a();let p=u.errorMessage;typeof p=="string"&&p.length>0&&r.push(`Error: turn failed: ${p}`)}}return a(),Cg(r.join(`
38
+ `),t)}function co(s){let e=new Map;for(let t of s){if(t.method!=="session/update")continue;let r=t.params?.update;if(!r)continue;let o=r.sessionUpdate;if(o!=="tool_call"&&o!=="tool_call_update")continue;let i=lo(r);if(i===void 0)continue;let a=e.get(i);if(a===void 0&&(a={name:"(unnamed)",rawInput:{}},e.set(i,a)),a.name==="(unnamed)"){let c=vg(r,o);c!==void 0&&(a.name=c)}if(a.kind===void 0&&typeof r.kind=="string"&&r.kind.length>0&&(a.kind=r.kind),a.output===void 0){let c=vs(r);c!==void 0&&(a.output=c)}let d=r.rawInput;d&&typeof d=="object"&&!Array.isArray(d)&&Object.assign(a.rawInput,d)}for(let t of e.values())t.name=uo(t);return e}function uo(s){return kg(s)?s.kind??"(unnamed)":s.name}function kg(s){for(let e of md){let t=s.rawInput[e];if(!(typeof t!="string"||t.length===0)&&(t===s.name||s.name.length>=12&&t.startsWith(s.name)))return!0}return!1}function vg(s,e){let t=In(s);if(t!==void 0)return t;if(typeof s.name=="string"&&s.name.length>0)return s.name;if(e==="tool_call"&&typeof s.title=="string"&&s.title.length>0)return s.title}function lo(s){let e=s.toolCallId;if(typeof e=="string"&&e.length>0)return e}function vs(s){let e=bg(s);if(e!==void 0)return e;let t=s.rawOutput;if(typeof t=="string")return t.length>0?t:void 0;if(t&&typeof t=="object"&&!Array.isArray(t)){let n=t.output;if(typeof n=="string")return n.length>0?n:void 0}}function bg(s){let e=s._meta;if(!e||typeof e!="object")return;let t=e.claudeCode;if(!t||typeof t!="object")return;let n=t.toolResponse;if(typeof n=="string")return n.length>0?n:void 0;if(!n||typeof n!="object")return;let{stdout:r,stderr:o}=n,i=[];if(typeof r=="string"&&r.length>0&&i.push(r),typeof o=="string"&&o.length>0&&i.push(`[stderr] ${o}`),i.length!==0)return i.join(`
39
+ `)}function In(s){let e=s._meta;if(!e||typeof e!="object")return;let t=e.claudeCode;if(!t||typeof t!="object")return;let n=t.toolName;if(typeof n=="string"&&n.length>0)return n}function fo(s,e){let t=lo(s),n=t!==void 0?e?.get(t):void 0,r=n?.name??Sg(s),o=Ig(n?.rawInput??s.rawInput);return o.length===0?`Tool: ${r}`:`Tool: ${r}(${o.join(", ")})`}function Sg(s){let e=In(s);return e!==void 0?e:typeof s.name=="string"&&s.name.length>0?s.name:typeof s.title=="string"&&s.title.length>0?s.title:"(unnamed)"}function Ig(s){if(!s||typeof s!="object"||Array.isArray(s))return[];let e=s,t=[];for(let n of md){let r=e[n];typeof r=="string"&&r.length>0&&t.push(`${n}=${Ag(r,600)}`)}return t}function po(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>{if(e&&typeof e=="object"){let t=e.text;if(typeof t=="string")return t}return""}).join(""):""}function go(s){if(!s||typeof s!="object")return"";let e=s.text;return typeof e=="string"?e:""}function Ag(s,e){return s.length<=e?s:s.slice(0,e-1)+"\u2026"}function Cg(s,e){if(s.length<=e)return s;let t=s.split(`
40
+ `);for(;t.length>0;){let n=gd+t.join(`
41
+ `);if(n.length<=e)return n;t.shift()}return gd}var hd="(untitled)";function mo(s){let e=[],t=s.synopsis;if(t!==void 0){e.push("--- begin prior session compaction ---"),e.push(`[Title] ${s.title??hd}`),t.goal!==void 0&&t.goal.trim().length>0&&e.push(`[Goal] ${t.goal}`),t.outcome!==void 0&&t.outcome.trim().length>0&&e.push(`[Outcome] ${t.outcome}`);let d=An("Open threads",t.open_threads);d.length>0&&e.push(d);let c=An("Decisions",t.decisions);c.length>0&&e.push(c);let u=An("File edit intentions",t.file_edit_intentions);u.length>0&&e.push(u);let l=An("Unresolved errors",t.unresolved_errors);l.length>0&&e.push(l);let p=An("Tool state",t.tool_state);p.length>0&&e.push(p);let f=yd(t.files_touched);f.length>0&&e.push(`[Files previously touched] ${f}`);let h=yd(t.tools_used);h.length>0&&e.push(`[Tools previously used] ${h}`),e.push("--- end prior session compaction ---")}else e.push(`[Title] ${s.title??hd}`);s.note!==void 0&&s.note.trim().length>0&&e.push(`[Situation] ${s.note.trim()}`);let{closedText:n,openText:r,keptCount:o}=Rg(s.tail,s.tailK,s.watermark??0,s.tailFloor??0);e.push("--- begin recent turns (verbatim, last "+o+") ---"),n.length>0&&e.push(n),e.push("--- end recent turns ---"),r.length>0&&(e.push("--- begin current in-flight turn (no completion yet) ---"),e.push(r),e.push("--- end current in-flight turn ---"));let i=s.recallArmed??!0;e.push("");let a=s.framing??(t!==void 0?"compaction":"fork");return a==="swap"?e.push(i?"(This session's agent process was replaced; nothing was summarized away. The turns above are the most recent; earlier history is available on demand via the hydra-recall tools. Do NOT call any tools yet. Do NOT read any files or run any commands. Reply with the single word 'OK' and wait for the next user message.)":"(This session's agent process was replaced; nothing was summarized away. The turns above are the most recent. Do NOT call any tools yet. Do NOT read any files or run any commands. Reply with the single word 'OK' and wait for the next user message.)"):a==="compaction"&&i?e.push("(Hydra has compacted earlier conversation. Do NOT call any tools yet. Do NOT read any files, run any commands, or invoke hydra-recall. Reply with the single word 'OK' and wait for the next user message \u2014 at that point you can use the hydra-recall tools to look up specifics on demand if needed.)"):a==="compaction"?e.push("(Hydra has compacted earlier conversation; the turns above are what survives. Do NOT call any tools yet. Do NOT read any files or run any commands. Reply with the single word 'OK' and wait for the next user message.)"):i?e.push("(This is a side conversation forked from another session. The turns above are the most recent; earlier history is available on demand via the hydra-recall tools. Do NOT call any tools yet. Do NOT read any files or run any commands. Reply with the single word 'OK' and wait for the next user message.)"):e.push("(This is a side conversation forked from another session. The turns above are the most recent. Do NOT call any tools yet. Do NOT read any files or run any commands. Reply with the single word 'OK' and wait for the next user message.)"),e.join(`
42
+ `)}function An(s,e){if(!e||!Array.isArray(e))return"";let t=e.filter(r=>typeof r=="string"&&r.trim().length>0);if(t.length===0)return"";let n=t.map(r=>"- "+r.trim());return`[${s}] ${n.join(`
43
+ `)}`}function yd(s){if(!s||!Array.isArray(s))return"";let e=s.filter(t=>typeof t=="string"&&t.trim().length>0);return e.length===0?"":e.map(t=>t.trim()).join(", ")}function Rg(s,e,t,n){if(s.length===0)return{closedText:"",openText:"",keptCount:0};let{closed:r,open:o}=xg(s),i=0,a=[];if(e>0&&r.length>0){let u=r.filter(f=>f.startEntryIndex>=t).length,l=Math.max(u,n),p=Math.min(l,e,r.length);i=p,a=p>0?r.slice(-p):[]}let d=a.length>0?wd(a):"",c=o?wd([o]):"";return{closedText:d,openText:c,keptCount:i}}function wd(s){let e=[];for(let t of s){t.user.length>0&&e.push("User: "+t.user),t.agent.length>0&&e.push("Assistant: "+t.agent);for(let n of t.tools)e.push(n)}return e.join(`
44
+ `)}function xg(s){let e=[],t=null,n=co(s);for(let o=0;o<s.length;o++){let i=s[o];if(i.method!=="session/update")continue;let d=i.params?.update;if(!d||typeof d.sessionUpdate!="string")continue;let c=d.sessionUpdate;if(c==="prompt_received")t!==null&&t.user.length>0&&e.push(t),t={user:po(d.prompt).trim(),agent:"",tools:[],startEntryIndex:o};else if(c==="agent_message_chunk"&&t!==null){let u=go(d.content);u.length>0&&(t.agent+=u)}else c==="tool_call"&&t!==null?t.tools.push(fo(d,n)):c==="turn_complete"&&t!==null&&(e.push(t),t=null)}let r=t!==null&&t.user.length>0?t:null;return{closed:e,open:r}}function vd(s,e){let t=s??[],n=(e??0)>0,r=[],o=new Set,i=t[0];i&&o.add(i.upstreamSessionId);for(let d=1;d<t.length;d++){let c=t[d],u=t[d-1],l={upstreamSessionId:c.upstreamSessionId,agentId:c.agentId,...c.startedAt!==void 0?{at:c.startedAt}:{},...c.endedAt!==void 0?{endedAt:c.endedAt}:{},...c.cost!==void 0?{cost:c.cost}:{},...c.usedAtStart!==void 0?{usedAfter:c.usedAtStart}:{},...u.usedAtEnd!==void 0?{usedBefore:u.usedAtEnd}:{},...c.reason!==void 0?{reason:c.reason}:{},...c.runId!==void 0?{runId:c.runId}:{}};c.reason===void 0&&(c.agentId!==u.agentId?l.inferredReason="agent-swap":o.has(c.upstreamSessionId)?l.inferredReason="rollback":n||(l.notCompaction=!0)),o.add(c.upstreamSessionId),r.push(l)}let a=r.filter(d=>d.reason==="compaction");return{rotations:r,compactions:a,runs:Tg(a),unknownCount:r.filter(d=>d.reason===void 0&&d.inferredReason===void 0&&!d.notCompaction).length}}function Tg(s){let e=[],t;for(let n of s){let r=e[e.length-1];if(r!==void 0&&n.runId!==void 0&&n.runId===t){r.swaps++,r.upstreamSessionId=n.upstreamSessionId,r.current=n.endedAt===void 0,n.cost!==void 0&&(r.cost=(r.cost??0)+n.cost),n.usedAfter!==void 0&&(r.usedAfter=n.usedAfter);continue}e.push({...n.at!==void 0?{at:n.at}:{},upstreamSessionId:n.upstreamSessionId,swaps:1,...n.cost!==void 0?{cost:n.cost}:{},...n.usedBefore!==void 0?{usedBefore:n.usedBefore}:{},...n.usedAfter!==void 0?{usedAfter:n.usedAfter}:{},current:n.endedAt===void 0}),t=n.runId}return e}function Eg(s){if(!s)return"unknown time";let e=Date.parse(s);return Number.isNaN(e)?"unknown time":`${new Date(e).toISOString().slice(0,16)}Z`}function kd(s){if(s<1e3)return String(s);let e=s/1e3;return e<100?`${e.toFixed(1)}k`:`${Math.round(e)}k`}function Pg(s){return s.usedBefore===void 0||s.usedAfter===void 0?"":` ${kd(s.usedBefore)} \u2192 ${kd(s.usedAfter)}`}function bd(s){let{runs:e,unknownCount:t}=s,n=[];if(e.length>0){n.push(e.length===1?"Compacted 1 time:":`Compacted ${e.length} times:`);for(let r of e){let o=Pg(r),i=r.cost!==void 0?` $${r.cost.toFixed(2)}`:"",a=r.current?" (current)":"",d=r.swaps>1?` (${r.swaps} swaps)`:"";n.push(` ${Eg(r.at)} ${r.upstreamSessionId}${o}${i}${d}${a}`)}}if(t>0){let r=t===1?"rotation":"rotations";n.push(e.length>0?`${t} earlier ${r}, cause not recorded; the count above is a lower bound.`:`No compactions on record. ${t} ${r} predate reason tracking, and any of them may have been a compaction.`)}return n}import*as mt from"path";function Mg(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function ho(s,e,t){if(e.length===0||e===t)return{text:s,rewritten:[]};let n=e.endsWith("/")?e.slice(0,-1):e,r=t.endsWith("/")?t.slice(0,-1):t,o=[],i=new RegExp(`${Mg(n)}/(?![/\\s])`,"g");return{text:s.replace(i,(d,c)=>{let u=s.slice(c+d.length),l=u.search(/[\s"'`,;:)\]}]|$/);return o.push(`${n}/${u.slice(0,l<0?void 0:l)}`),`${r}/`}),rewritten:o}}function yo(s,e){if(e.length===0)return!1;let t=e.endsWith("/")?e.slice(0,-1):e;return s.includes(t)}function Sd(s){let e=[];return e.push("[workspace] You have LEFT the isolated workspace."),e.push(`- Your working directory is now ${s.sourceCwd}`),e.push(s.removed?`- The workspace at ${s.formerWorkspacePath} has been removed. Paths under it from earlier in this conversation no longer exist.`:`- The workspace at ${s.formerWorkspacePath} still exists but is NO LONGER YOURS. Editing anything under it is wasted: that work will not reach ${s.sourceCwd}.`),e.push("- Earlier turns refer to files by their workspace paths. Treat those as referring to the same files under your current working directory, and prefer repo-relative paths from here on."),e.join(`
45
+ `)}function Id(s){let e=[];e.push(s.reassert===!0?"[workspace] Reminder: you are NOT working in the directory that path names.":"[workspace] Before anything else, note where you are working:"),e.push(`- Your working directory is ${s.workspacePath}`),e.push(`- It is an isolated copy of ${s.sourceCwd}`),e.push(`- Any absolute path under ${s.sourceCwd} refers to the matching file under your working directory. Do not read or write ${s.sourceCwd} directly.`),e.push("- Prefer repo-relative paths (`src/foo.ts`). They are identical in both trees, so they cannot be misread.");for(let t of s.notes)e.push(`- ${t}`);return e.join(`
46
+ `)}function Ad(s,e,t){return s.length===0||!mt.isAbsolute(s)||bs(s,t)?!1:bs(s,e)}function bs(s,e){let t=mt.relative(mt.resolve(e),mt.resolve(s));return!(t.length===0||t.startsWith("..")||mt.isAbsolute(t))}Y();import*as Ve from"fs/promises";async function Cn(s,e){let t=E.queueFile(s);if(e.length===0){await Ve.unlink(t).catch(()=>{});return}await Ve.mkdir(E.sessionDir(s),{recursive:!0});let n=e.map(r=>JSON.stringify(r)).join(`
47
47
  `)+`
48
- `;await Ve.writeFile(t,n,"utf8")}async function Id(s){let e=T.queueFile(s),t;try{t=await Ve.readFile(e,"utf8")}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t.split(`
49
- `))if(r.trim())try{let o=JSON.parse(r);o&&typeof o.messageId=="string"&&Array.isArray(o.prompt)&&typeof o.enqueuedAt=="number"&&n.push(o)}catch{}return n}async function Ad(s){let e=T.queueFile(s);await Ve.unlink(e).catch(()=>{})}import*as Nd from"fs/promises";var Od="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Fd=$d(Od,16),ho=$d(Od,16),Pg=2e3,Mg=20,_g=20,$g=5,Og=32,ye="hydra_session_";function Ge(){return`m_${Fd()}`}function tt(s){let e=pt(s)?.localId??s;return e.startsWith(ye)?e.slice(ye.length):e}var Cd=["start","merge","apply","sync","stop","detach","discard","clean","status"],Fg=1e3,vs=300*1e3,Ng=64,Dg=new Set(["task-notification","peer","coordinator","observer","observer-activity"]);function Hg(s){let e=s?.update;if(!e||typeof e!="object"||e.sessionUpdate!=="usage_update")return!1;let t=e._meta;if(!t||typeof t!="object")return!1;let n=t["_claude/origin"];if(!n||typeof n!="object")return!1;let r=n.kind;return typeof r=="string"&&Dg.has(r)}function Rd(s){let e=s?.update;return!!e&&typeof e=="object"&&e.sessionUpdate==="usage_update"}function jg(s){let e=s?.update;return!!e&&typeof e=="object"&&e.sessionUpdate==="tool_call_update"}function Lg(s,e){return e===void 0?!1:s.some(t=>{if(!t||typeof t!="object")return!1;let n=t.id;return typeof n=="string"&&n.trim()!==""&&n.trim()!==e})}var yo=120;function Ug(s){let e=s.split(`
50
- `).map(t=>t.trim()).filter(t=>t!=="");return e.length===0?"":e[e.length-1]}var Bg=128,Wg=new Set(["local_bash"]),qg=1e3,zg=1e4,Kt=class s{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=ze;modelVerbConfirmed=!1;agentArgs;parentSessionId;forkedFromSessionId;forkedFromMessageId;side;forkSynthesisState;originatingClient;_interactive;get interactive(){return this._interactive}_priority;get priority(){return this._priority}_lastTurnEndedAt;get lastTurnEndedAt(){return this._lastTurnEndedAt}_readAt;get readAt(){return this._readAt}title;_summarizedThroughEntry;get summarizedThroughEntry(){return this._summarizedThroughEntry}set summarizedThroughEntry(e){this._summarizedThroughEntry=e}currentModel;currentMode;compactionState;_currentUsage;updatedAt;createdAt;clients=new Map;historyStore;promptQueue=[];currentEntry;promptInFlight=!1;agentTurnInFlight=!1;swapInFlight=!1;opencodeSummary=new ys;modeChangeInFlight=!1;modelChangeInFlight=!1;queueWriteChain=Promise.resolve();closed=!1;closing=!1;closeInFlight;deleteRecordIntent=!1;closeHandlers=[];titleHandlers=[];scheduleSynopsisHook;scheduleWorkspaceSnapshotHook;scheduleCompactionHook;resolveAgentIdHook;getCompactionStateHook;getUpstreamGenerationsHook;getPendingAgentSwapHook;_liveCompactionPhase;broadcastHandlers=[];lastCancelAt=0;static CANCEL_ERROR_WINDOW_MS=2e3;lastUnsolicitedCancelAt=0;cancelReopenStreak=0;static UNSOLICITED_REOPEN_WINDOW_MS=1e4;static UNSOLICITED_REOPEN_LIMIT=3;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}_titleSeedPending=!0;_upstreamRespawned=!1;promptStartedAt;turnRanTool=!1;unsolicitedTurn;pendingSteerDetach;supersededAutonomousTurn;autonomousSalvage;lastBackgroundTask;toolLabels=new Map;armedTasks=new Map;upstreamBaselineMs;upstreamBaselineGen=0;upstreamPollTimer;lastArmedBroadcast;liveBackgroundTasks=new Map;sawBackgroundTaskLevel=!1;sawTurnComplete=!1;appendCount=0;historyMaxEntries;compactEvery;permissionCallbacks=new Map;attentionFlags=new Map;get hasPermissionFlag(){for(let e of this.attentionFlags.values())if(e.source==="daemon"&&e.reason.startsWith("permission:"))return!0;return!1}attentionFlagsChangeHandlers=[];internalPromptCapture;idleTimeoutMs;idleTimer;orphanTimeoutMs;orphanTimer;idleEventTimeoutMs;idleHandlers=[];lastRecordedAt;lastSeq=0;spawnReplacementAgent;mintMcpServersForSwap;loadExistingAgentSession;clearRollbackBreadcrumbHook;onCompactionSwapHook;persistWatermarkHook;uncompactHook;rewindHook;forkHook;mcpServersConfig;forwardedEnv;workspace;workspaceError;workspaceNotes=[];workspaceHook;workspacePreambleSent=!1;formerWorkspace;departureNoteSent=!1;listSessions;logger;transformChain;extensionCommands;extensionCommandsUnsub;pendingClaims=new Map;toolCompletionSeen=new Map;toolCallKind=new us;filesEditedSeen=new Set;openToolCalls=new Map;agentChangeHandlers=[];retiringGenerationCost;retiringGenerationUsed;rotationLifetimeCost;agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];configOptionsHandlers=[];availableAgentsFn;modelHandlers=[];modeHandlers=[];interactiveHandlers=[];priorityHandlers=[];readStateHandlers=[];usageHandlers=[];cumulativeCost=0;costLedgerProbe;get persistableUsage(){if(!(!this._currentUsage&&!this.cumulativeCost))return{...this._currentUsage??{},...this.cumulativeCost?{cumulativeCost:this.cumulativeCost}:{cumulativeCost:void 0}}}get currentUsage(){if(!this._currentUsage&&!this.cumulativeCost)return;let e=this._currentUsage??{},t=this.cumulativeCost+(e.costAmount??0);return{...e,costAmount:t||void 0,cumulativeCost:void 0}}amendInProgress;inFlightExtensionDispatches=new Map;recentlyTerminal=new Map;pendingTurnNotifiers=new Map;streamBuffer;streamFilePath;constructor(e){if(this.sessionId=e.sessionId??`${ye}${Fd()}`,this.cwd=e.cwd,this.workspace=e.workspace,this.workspaceError=e.workspaceError,this.workspaceHook=e.workspaceHook,this.agentId=e.agentId,this.agent=e.agent,this.upstreamSessionId=e.upstreamSessionId,this.agentMeta=e.agentMeta,this.agentCapabilities=e.agentCapabilities,this.agentArgs=e.agentArgs,this.parentSessionId=e.parentSessionId,this.forkedFromSessionId=e.forkedFromSessionId,this.forkedFromMessageId=e.forkedFromMessageId,this.side=e.side,this.forkSynthesisState=e.forkSynthesisState,this.originatingClient=e.originatingClient,this.title=e.title,this.scheduleSynopsisHook=e.scheduleSynopsis,this.scheduleWorkspaceSnapshotHook=e.scheduleWorkspaceSnapshot,this.scheduleCompactionHook=e.scheduleCompaction,this.resolveAgentIdHook=e.resolveAgentId,this.getCompactionStateHook=e.getCompactionState,this.getUpstreamGenerationsHook=e.getUpstreamGenerations,this.getPendingAgentSwapHook=e.getPendingAgentSwap,this.currentModel=e.currentModel,this.currentMode=e.currentMode,this._currentUsage=e.currentUsage,this.cumulativeCost=e.currentUsage?.cumulativeCost??0,e.reloadsUpstreamLedger&&this.armCostLedgerProbe(),e.agentCommands&&e.agentCommands.length>0&&(this.agentAdvertisedCommands=[...e.agentCommands]),e.agentModes&&e.agentModes.length>0&&(this.agentAdvertisedModes=[...e.agentModes]),e.agentModels&&e.agentModels.length>0&&(this.agentAdvertisedModels=[...e.agentModels]),e.agentConfigOptions&&e.agentConfigOptions.length>0&&(this.agentAdvertisedConfigOptions=[...e.agentConfigOptions]),this.idleTimeoutMs=e.idleTimeoutMs??0,this.orphanTimeoutMs=e.orphanTimeoutMs??0,this.idleEventTimeoutMs=e.idleEventTimeoutMs??3e4,this.idleEventTimeoutMs>0&&this.onIdle(t=>t.notifyChain("session.idle",{}),{debounceMs:this.idleEventTimeoutMs}),this.spawnReplacementAgent=e.spawnReplacementAgent,this.mintMcpServersForSwap=e.mintMcpServersForSwap,this.loadExistingAgentSession=e.loadExistingAgentSession,this.clearRollbackBreadcrumbHook=e.clearRollbackBreadcrumbHook,this.onCompactionSwapHook=e.onCompactionSwapHook,this.persistWatermarkHook=e.persistWatermarkHook,this.uncompactHook=e.uncompactHook,this.forkHook=e.forkHook,this.mcpServersConfig=e.mcpServers,this.forwardedEnv=e.forwardedEnv,this.availableAgentsFn=e.availableAgents,this.listSessions=e.listSessions,this.logger=e.logger,this.transformChain=e.transformChain??[],this.extensionCommands=e.extensionCommands,this.extensionCommands&&(this.extensionCommandsUnsub=this.extensionCommands.onChange(()=>{this.closed||this.broadcastMergedCommands()})),e.firstPromptSeeded&&(this._firstPromptSeeded=!0,this._titleSeedPending=!1),e.upstreamRespawned&&(this._upstreamRespawned=!0),this._interactive=e.interactive,this._priority=e.priority,this._lastTurnEndedAt=e.lastTurnEndedAt,this._readAt=e.readAt,this._summarizedThroughEntry=e.summarizedThroughEntry,this.compactionState=e.compactionState,e.compactionState){let t=e.compactionState;(t.status==="requested"||t.status==="running"||t.status==="swap_pending"||t.status==="swap_deferred")&&(t.status==="swap_deferred"?this._liveCompactionPhase={phase:"deferred",attempts:t.attempts}:this._liveCompactionPhase={phase:t.status==="requested"?"started":"iteration",iter:t.iter})}if(e.attentionFlags&&e.attentionFlags.length>0)for(let t of e.attentionFlags)this.attentionFlags.set(`${t.source}::${t.reason}`,t);this.historyStore=e.historyStore,this.historyMaxEntries=e.historyMaxEntries??Fg,this.compactEvery=Math.max(1,Math.floor(this.historyMaxEntries*.2)),this.updatedAt=Date.now(),this.createdAt=e.createdAt??this.updatedAt,this.lastRecordedAt=this.updatedAt,this.resetModelVerb(e.modelVerb),this.wireAgent(this.agent),this.scheduleIdleCheck(),this.notifyChain("session.opened",{})}broadcastMergedCommands(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"available_commands_update",availableCommands:this.mergedAvailableCommands()}})}broadcastAvailableModes(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_available_modes_update",availableModes:this.agentAdvertisedModes}})}broadcastAvailableModels(){let e={sessionUpdate:"_hydra_current_model_update",availableModels:[...this.agentAdvertisedModels]};this.currentModel!==void 0&&this.currentModel.length>0&&(e.currentModel=this.currentModel),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:e})}wireAgent(e,t){this.resetBackgroundTaskLevel(),t?.respawn&&(this._upstreamRespawned=!0),e.connection.onNotification("session/update",n=>{if(this.internalPromptCapture){om(this.internalPromptCapture,n);return}this.maybeEmitToolEdges(n),this.runResponseChain(n)}),e.connection.onNotification("_claude/sdkMessage",n=>{this.applyBackgroundTaskLevel(n)}),e.connection.onRequest("session/request_permission",async n=>{let r=await this.runAgentRequestChain("session/request_permission",n),o=Pd(r.shortCircuit?n:r.envelope);if(r.shortCircuit)return this.notifyChain("permission.replied",{toolCallId:o??null,outcome:r.payload,sourceWasTransformer:!0}),r.payload;let i=await this.handlePermissionRequest(r.envelope);return this.notifyChain("permission.replied",{toolCallId:o??null,outcome:i,sourceWasTransformer:!1}),i}),typeof e.connection.onOrphanError=="function"&&e.connection.onOrphanError(n=>{this.handleOrphanError(n)}),e.onExit(()=>{this.agent===e&&this.markClosed({deleteRecord:!1})})}handleOrphanError(e){let t=Date.now()-this.lastCancelAt;if(this.lastCancelAt===0||t>s.CANCEL_ERROR_WINDOW_MS){this.logger?.warn(`agent ${this.agentId} sent uncorrelated error frame code=${e.code} message=${e.message}`);return}this.lastCancelAt=0,this.logger?.warn(`agent ${this.agentId} rejected session/cancel code=${e.code} message=${e.message}`),this.broadcastQueueNotification("hydra-acp/cancel_failed",{sessionId:this.sessionId,code:e.code,message:e.message})}async runResponseChain(e,t=new Set,n=0,r="session/update"){let o=e,i=r==="session/update"?this.injectCumulativeCost(e):e,a=`response:${r}`;for(let l=n;l<this.transformChain.length;l++){let p=this.transformChain[l];if(t.has(p.name)||!p.intercepts.has(a))continue;let f=`t_${ho()}`,h;try{h=await p.connection.request("hydra-acp/transformer/message",{token:f,phase:"response",method:r,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(m){this.logger?.warn(`transformer ${p.name} error on ${a}: ${m.message}`);continue}let k=h?.action??"continue";if(k==="stop")return;if(k==="processing"){let m=l,g=i,y=new Set(t),w=r;await new Promise(v=>{let S=setTimeout(()=>{this.pendingClaims.delete(f)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:f,transformerName:p.name}),this.runResponseChain(g,new Set([...y,p.name]),m+1,w).then(()=>v()).catch(()=>v()))},vs);typeof S.unref=="function"&&S.unref(),this.pendingClaims.set(f,{resolve:()=>v(),timer:S,transformerName:p.name,method:w,envelope:g,chainIdx:m,originatedBy:y,side:"response"})});return}h?.payload&&typeof h.payload=="object"&&(i=h.payload),t.add(p.name)}if(r!=="session/update")return;this.noteAgentActivity(i);let d=i.update;(ud(d)||this.agentId==="opencode"&&this.opencodeSummary.feed(d))&&this.armRecallFromSelfCompaction();let c=im(i);if(c!==null){this.setAgentAdvertisedCommands(c);return}let u=rm(i);if(u!==null){this.setAgentAdvertisedModes(u);return}if(this.noteModelVerbHint(Ha(i.update),"session/update"),this.maybeApplyAgentModel(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentMode(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentConfigOption(i)){this.recordAndBroadcast("session/update",this.mergeAgentOptionIntoEnvelope(i));return}if(this.maybeApplyAgentUsage(o)){this.recordAndBroadcast("session/update",i);return}this.maybeApplyAgentSessionInfo(i),this.recordAndBroadcast("session/update",sd(i))}armRecallFromSelfCompaction(){this.armRecallInPlace().catch(e=>{this.logger?.warn(`armRecallInPlace failed: ${e.message}`)})}async armRecallInPlace(){if(!this.historyStore)return;let e=await this.historyStore.getRecallTotalCount(this.sessionId).catch(()=>0);if(!(e<=(this._summarizedThroughEntry??0))){if(this._summarizedThroughEntry=e,this.persistWatermarkHook)try{this.persistWatermarkHook(e)}catch(t){this.logger?.warn(`armRecallInPlace: persistWatermarkHook failed: ${t.message}`)}this.broadcastQueueNotification("hydra-acp/context_self_compacted",{sessionId:this.sessionId})}}onAgentChange(e){this.agentChangeHandlers.push(e)}get attachedCount(){return this.clients.size}connectedClients(e){let t=[];for(let n of this.clients.values()){if(e&&n.clientId===e)continue;let r={clientId:n.clientId};n.clientInfo?.name&&(r.name=n.clientInfo.name),n.clientInfo?.version&&(r.version=n.clientInfo.version),t.push(r)}return t}get turnStartedAt(){return this.promptStartedAt}get inUnsolicitedTurn(){return this.unsolicitedTurn!==void 0}get agentPid(){return this.agent.pid}get awaitingInput(){return this.attentionFlags.size>0}async isQuiescedForSwap(){return await this.quiesceBlocker()===void 0}async quiesceBlocker(){if(this.agentTurnInFlight)return"the agent is still working; wait for the current turn to finish, then try again";if(this.unsolicitedTurn!==void 0)return"the agent is part-way through a turn it started by itself; wait for it to finish or interrupt it (^C), then try again";if(this.internalPromptCapture!==void 0)return"hydra is driving the agent right now (compaction seed or transcript injection); this clears by itself, so try again in a moment";if(this.modelChangeInFlight)return"a model change is still settling; try again in a moment";if(this.modeChangeInFlight)return"a mode change is still settling; try again in a moment";let e=this.pendingOneShotBackgroundTasks();if(e.length>0)return`${e.length} background task(s) still running (${e.join(", ")}); a swap would kill the agent process and abandon them. Wait for them to finish, or cancel them, then try again`;let t=await this.openToolCallIdsInHistory();if(t.length>0)return`${t.length} tool call(s) from an earlier turn never reported a result, so the session still reads as busy. ^C closes an abandoned chain; failing that it clears as new history accumulates`}isQuiescedSync(){return!(this.promptInFlight||this.unsolicitedTurn!==void 0||this.modeChangeInFlight||this.modelChangeInFlight)}async swapIntoWorkspace(e){await this.swapUpstream({...e.synopsis!==void 0?{artifact:e.synopsis}:{},note:e.note,framing:"swap",...e.title!==void 0?{title:e.title}:{},tailK:8,tailFloor:4,summarizedThroughEntry:e.historyLength,newCwd:e.cwd,reason:e.workspace!==void 0?"workspace-enter":"workspace-leave"}),this.workspace=e.workspace,e.left!==void 0?(this.formerWorkspace={path:e.left.path,sourceCwd:e.cwd,removed:e.left.removed},this.departureNoteSent=!1):this.formerWorkspace=void 0}async swapUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for swap: ${t}`);if(this.swapInFlight)throw new Error("a swap is already in progress for this session");this.swapInFlight=!0;try{await this.doSwapUpstream(e)}finally{this.swapInFlight=!1}}async doSwapUpstream(e){this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let t=this.agentId,n=e.newAgentId??this.agentId,r=n!==this.agentId,o=e.reason!==void 0&&e.reason!=="compaction"?e.reason:r?"agent-swap":"compaction",i=e.newCwd??this.cwd,a=this.agentArgs,d=this.forwardedEnv,c=this.currentModel,u=this.currentMode,l=this.spawnReplacementAgent;if(!l)throw new Error("agent spawning not configured for this session");let p=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],f=await l({agentId:n,cwd:i,agentArgs:a,...d?{forwardedEnv:d}:{},mcpServers:p});if(this.accumulateAndResetCost(),this.cwd=i,this.wireAgent(f.agent,{respawn:!0}),!r){let M=await ft({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedModel:c,agentReportedModel:f.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(M.result,"model"),await lt({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedMode:u,agentReportedMode:f.initialMode,logger:this.logger})}f.agent.connection.drainBuffered("session/update");let h=[];if(this.historyStore)try{h=await this.historyStore.load(this.sessionId)}catch(M){this.logger?.warn(`swapUpstream: historyStore.load failed: ${M.message}`)}let k=po({...e.artifact!==void 0?{synopsis:e.artifact}:{},...e.note!==void 0?{note:e.note}:{},...e.framing!==void 0?{framing:e.framing}:{},title:e.title,tail:h,tailK:e.tailK,tailFloor:e.tailFloor,...e.summarizedThroughEntry!==void 0?{watermark:e.summarizedThroughEntry}:{},recallArmed:(e.summarizedThroughEntry??this._summarizedThroughEntry??0)>0});if(this.internalPromptCapture)throw new Error("swapUpstream: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};let m,g;try{await f.agent.connection.request("session/prompt",{sessionId:f.upstreamSessionId,prompt:[{type:"text",text:k}]});let M=this.internalPromptCapture;m=M.lastUsed,g=M.lastSize,this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${k.length} toolCalls=${M.toolCalls} thinkingChars=${M.thinkingChars} messageChars=${M.messageChars} used=${M.lastUsed??"?"} size=${M.lastSize??"?"} reply=${JSON.stringify(M.chunks.join("").slice(0,200))}`)}finally{this.internalPromptCapture=void 0}m!==void 0&&(this.maybeApplyAgentUsage({update:{sessionUpdate:"usage_update",used:m,...g!==void 0?{size:g}:{}}}),this.broadcastCurrentUsage());let y=this.upstreamSessionId,w=this._summarizedThroughEntry;e.summarizedThroughEntry!==void 0&&(this._summarizedThroughEntry=e.summarizedThroughEntry);let v=this.agent;if(this.agent=f.agent,this.upstreamSessionId=f.upstreamSessionId,this.agentMeta=f.agentMeta,this.agentCapabilities=f.agentCapabilities,this.resetModelVerb(f.modelVerb),this.sawTurnComplete=!1,r&&(this.agentId=n,this.agentAdvertisedCommands=[],this.currentModel=f.initialModel,this.currentMode=f.initialMode,this.setAgentAdvertisedModels(f.initialModels??[]),this.setAgentAdvertisedModes(f.initialModes??[]),this.agentAdvertisedConfigOptions=f.initialConfigOptions??[]),this.broadcastMergedCommands(),this.broadcastConfigOptions(),this.notifyAgentChange("swapUpstream",o,e.runId,m),e.summarizedThroughEntry!==void 0&&this.persistWatermarkHook)try{this.persistWatermarkHook(e.summarizedThroughEntry)}catch(M){this.logger?.warn(`swapUpstream: persistWatermarkHook failed: ${M.message}`)}if(!r&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:y,...w!==void 0?{previousSummarizedThroughEntry:w}:{},...e.runId!==void 0?{runId:e.runId}:{}})}catch(M){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${M.message}`)}let S=await this.retireAgent(v,r?"agent switch":e.reason==="workspace-enter"||e.reason==="workspace-leave"?"workspace move":"compaction swap");this.notifyChain("agent.swap",{phase:"post",previousUpstreamSessionId:y,upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}),r||this.broadcastCompactionPhase({phase:"swapped",...this.title!==void 0?{title:this.title}:{},summarizedThroughEntry:e.summarizedThroughEntry??this._summarizedThroughEntry??0}),r&&this.broadcastAgentSwitch(t,n);let b=S.length>0?`
48
+ `;await Ve.writeFile(t,n,"utf8")}async function Cd(s){let e=E.queueFile(s),t;try{t=await Ve.readFile(e,"utf8")}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t.split(`
49
+ `))if(r.trim())try{let o=JSON.parse(r);o&&typeof o.messageId=="string"&&Array.isArray(o.prompt)&&typeof o.enqueuedAt=="number"&&n.push(o)}catch{}return n}async function Rd(s){let e=E.queueFile(s);await Ve.unlink(e).catch(()=>{})}import*as Hd from"fs/promises";var Nd="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Dd=Fd(Nd,16),wo=Fd(Nd,16),_g=2e3,$g=20,Og=20,Fg=5,Ng=32,ye="hydra_session_";function Ge(){return`m_${Dd()}`}function nt(s){let e=gt(s)?.localId??s;return e.startsWith(ye)?e.slice(ye.length):e}var xd=["start","merge","apply","sync","stop","detach","discard","clean","status"],Dg=1e3,Ss=300*1e3,Hg=64,jg=new Set(["task-notification","peer","coordinator","observer","observer-activity"]);function Lg(s){let e=s?.update;if(!e||typeof e!="object"||e.sessionUpdate!=="usage_update")return!1;let t=e._meta;if(!t||typeof t!="object")return!1;let n=t["_claude/origin"];if(!n||typeof n!="object")return!1;let r=n.kind;return typeof r=="string"&&jg.has(r)}function Td(s){let e=s?.update;return!!e&&typeof e=="object"&&e.sessionUpdate==="usage_update"}function Ug(s){let e=s?.update;return!!e&&typeof e=="object"&&e.sessionUpdate==="tool_call_update"}function Bg(s,e){return e===void 0?!1:s.some(t=>{if(!t||typeof t!="object")return!1;let n=t.id;return typeof n=="string"&&n.trim()!==""&&n.trim()!==e})}var ko=120;function Wg(s){let e=s.split(`
50
+ `).map(t=>t.trim()).filter(t=>t!=="");return e.length===0?"":e[e.length-1]}var qg=128,zg=new Set(["local_bash"]),Jg=1e3,Vg=1e4,Qt=class s{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=ze;modelVerbConfirmed=!1;agentArgs;parentSessionId;forkedFromSessionId;forkedFromMessageId;side;forkSynthesisState;originatingClient;_interactive;get interactive(){return this._interactive}_priority;get priority(){return this._priority}_lastTurnEndedAt;get lastTurnEndedAt(){return this._lastTurnEndedAt}_readAt;get readAt(){return this._readAt}title;_summarizedThroughEntry;get summarizedThroughEntry(){return this._summarizedThroughEntry}set summarizedThroughEntry(e){this._summarizedThroughEntry=e}currentModel;currentMode;compactionState;_currentUsage;updatedAt;createdAt;clients=new Map;historyStore;promptQueue=[];currentEntry;promptInFlight=!1;agentTurnInFlight=!1;swapInFlight=!1;opencodeSummary=new ks;modeChangeInFlight=!1;modelChangeInFlight=!1;queueWriteChain=Promise.resolve();closed=!1;closing=!1;closeInFlight;deleteRecordIntent=!1;closeHandlers=[];titleHandlers=[];scheduleSynopsisHook;scheduleWorkspaceSnapshotHook;scheduleCompactionHook;resolveAgentIdHook;getCompactionStateHook;getUpstreamGenerationsHook;getPendingAgentSwapHook;_liveCompactionPhase;broadcastHandlers=[];lastCancelAt=0;static CANCEL_ERROR_WINDOW_MS=2e3;lastUnsolicitedCancelAt=0;cancelReopenStreak=0;static UNSOLICITED_REOPEN_WINDOW_MS=1e4;static UNSOLICITED_REOPEN_LIMIT=3;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}_titleSeedPending=!0;_upstreamRespawned=!1;promptStartedAt;turnRanTool=!1;unsolicitedTurn;pendingSteerDetach;supersededAutonomousTurn;autonomousSalvage;lastBackgroundTask;toolLabels=new Map;armedTasks=new Map;upstreamBaselineMs;upstreamBaselineGen=0;upstreamPollTimer;lastArmedBroadcast;liveBackgroundTasks=new Map;sawBackgroundTaskLevel=!1;sawTurnComplete=!1;appendCount=0;historyMaxEntries;compactEvery;permissionCallbacks=new Map;attentionFlags=new Map;get hasPermissionFlag(){for(let e of this.attentionFlags.values())if(e.source==="daemon"&&e.reason.startsWith("permission:"))return!0;return!1}attentionFlagsChangeHandlers=[];internalPromptCapture;idleTimeoutMs;backgroundTaskTracking;idleTimer;orphanTimeoutMs;orphanTimer;idleEventTimeoutMs;idleHandlers=[];lastRecordedAt;lastSeq=0;spawnReplacementAgent;mintMcpServersForSwap;loadExistingAgentSession;clearRollbackBreadcrumbHook;onCompactionSwapHook;persistWatermarkHook;uncompactHook;rewindHook;forkHook;mcpServersConfig;forwardedEnv;workspace;workspaceError;workspaceNotes=[];workspaceHook;workspacePreambleSent=!1;formerWorkspace;departureNoteSent=!1;listSessions;logger;transformChain;extensionCommands;extensionCommandsUnsub;pendingClaims=new Map;toolCompletionSeen=new Map;toolCallKind=new fs;filesEditedSeen=new Set;openToolCalls=new Map;agentChangeHandlers=[];retiringGenerationCost;retiringGenerationUsed;rotationLifetimeCost;agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];configOptionsHandlers=[];availableAgentsFn;modelHandlers=[];modeHandlers=[];interactiveHandlers=[];priorityHandlers=[];readStateHandlers=[];usageHandlers=[];cumulativeCost=0;costLedgerProbe;get persistableUsage(){if(!(!this._currentUsage&&!this.cumulativeCost))return{...this._currentUsage??{},...this.cumulativeCost?{cumulativeCost:this.cumulativeCost}:{cumulativeCost:void 0}}}get currentUsage(){if(!this._currentUsage&&!this.cumulativeCost)return;let e=this._currentUsage??{},t=this.cumulativeCost+(e.costAmount??0);return{...e,costAmount:t||void 0,cumulativeCost:void 0}}amendInProgress;inFlightExtensionDispatches=new Map;recentlyTerminal=new Map;pendingTurnNotifiers=new Map;streamBuffer;streamFilePath;constructor(e){if(this.sessionId=e.sessionId??`${ye}${Dd()}`,this.cwd=e.cwd,this.workspace=e.workspace,this.workspaceError=e.workspaceError,this.workspaceHook=e.workspaceHook,this.agentId=e.agentId,this.agent=e.agent,this.upstreamSessionId=e.upstreamSessionId,this.agentMeta=e.agentMeta,this.agentCapabilities=e.agentCapabilities,this.agentArgs=e.agentArgs,this.parentSessionId=e.parentSessionId,this.forkedFromSessionId=e.forkedFromSessionId,this.forkedFromMessageId=e.forkedFromMessageId,this.side=e.side,this.forkSynthesisState=e.forkSynthesisState,this.originatingClient=e.originatingClient,this.title=e.title,this.scheduleSynopsisHook=e.scheduleSynopsis,this.scheduleWorkspaceSnapshotHook=e.scheduleWorkspaceSnapshot,this.scheduleCompactionHook=e.scheduleCompaction,this.resolveAgentIdHook=e.resolveAgentId,this.getCompactionStateHook=e.getCompactionState,this.getUpstreamGenerationsHook=e.getUpstreamGenerations,this.getPendingAgentSwapHook=e.getPendingAgentSwap,this.currentModel=e.currentModel,this.currentMode=e.currentMode,this._currentUsage=e.currentUsage,this.cumulativeCost=e.currentUsage?.cumulativeCost??0,e.reloadsUpstreamLedger&&this.armCostLedgerProbe(),e.agentCommands&&e.agentCommands.length>0&&(this.agentAdvertisedCommands=[...e.agentCommands]),e.agentModes&&e.agentModes.length>0&&(this.agentAdvertisedModes=[...e.agentModes]),e.agentModels&&e.agentModels.length>0&&(this.agentAdvertisedModels=[...e.agentModels]),e.agentConfigOptions&&e.agentConfigOptions.length>0&&(this.agentAdvertisedConfigOptions=[...e.agentConfigOptions]),this.idleTimeoutMs=e.idleTimeoutMs??0,this.backgroundTaskTracking=e.backgroundTaskTracking,this.orphanTimeoutMs=e.orphanTimeoutMs??0,this.idleEventTimeoutMs=e.idleEventTimeoutMs??3e4,this.idleEventTimeoutMs>0&&this.onIdle(t=>t.notifyChain("session.idle",{}),{debounceMs:this.idleEventTimeoutMs}),this.spawnReplacementAgent=e.spawnReplacementAgent,this.mintMcpServersForSwap=e.mintMcpServersForSwap,this.loadExistingAgentSession=e.loadExistingAgentSession,this.clearRollbackBreadcrumbHook=e.clearRollbackBreadcrumbHook,this.onCompactionSwapHook=e.onCompactionSwapHook,this.persistWatermarkHook=e.persistWatermarkHook,this.uncompactHook=e.uncompactHook,this.forkHook=e.forkHook,this.mcpServersConfig=e.mcpServers,this.forwardedEnv=e.forwardedEnv,this.availableAgentsFn=e.availableAgents,this.listSessions=e.listSessions,this.logger=e.logger,this.transformChain=e.transformChain??[],this.extensionCommands=e.extensionCommands,this.extensionCommands&&(this.extensionCommandsUnsub=this.extensionCommands.onChange(()=>{this.closed||this.broadcastMergedCommands()})),e.firstPromptSeeded&&(this._firstPromptSeeded=!0,this._titleSeedPending=!1),e.upstreamRespawned&&(this._upstreamRespawned=!0),this._interactive=e.interactive,this._priority=e.priority,this._lastTurnEndedAt=e.lastTurnEndedAt,this._readAt=e.readAt,this._summarizedThroughEntry=e.summarizedThroughEntry,this.compactionState=e.compactionState,e.compactionState){let t=e.compactionState;(t.status==="requested"||t.status==="running"||t.status==="swap_pending"||t.status==="swap_deferred")&&(t.status==="swap_deferred"?this._liveCompactionPhase={phase:"deferred",attempts:t.attempts}:this._liveCompactionPhase={phase:t.status==="requested"?"started":"iteration",iter:t.iter})}if(e.attentionFlags&&e.attentionFlags.length>0)for(let t of e.attentionFlags)this.attentionFlags.set(`${t.source}::${t.reason}`,t);this.historyStore=e.historyStore,this.historyMaxEntries=e.historyMaxEntries??Dg,this.compactEvery=Math.max(1,Math.floor(this.historyMaxEntries*.2)),this.updatedAt=Date.now(),this.createdAt=e.createdAt??this.updatedAt,this.lastRecordedAt=this.updatedAt,this.resetModelVerb(e.modelVerb),this.wireAgent(this.agent),this.scheduleIdleCheck(),this.notifyChain("session.opened",{})}broadcastMergedCommands(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"available_commands_update",availableCommands:this.mergedAvailableCommands()}})}broadcastAvailableModes(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_available_modes_update",availableModes:this.agentAdvertisedModes}})}broadcastAvailableModels(){let e={sessionUpdate:"_hydra_current_model_update",availableModels:[...this.agentAdvertisedModels]};this.currentModel!==void 0&&this.currentModel.length>0&&(e.currentModel=this.currentModel),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:e})}wireAgent(e,t){this.resetBackgroundTaskLevel(),t?.respawn&&(this._upstreamRespawned=!0),e.connection.onNotification("session/update",n=>{if(this.internalPromptCapture){am(this.internalPromptCapture,n);return}this.maybeEmitToolEdges(n),this.runResponseChain(n)}),e.connection.onNotification("_claude/sdkMessage",n=>{this.applyBackgroundTaskLevel(n)}),e.connection.onRequest("session/request_permission",async n=>{let r=await this.runAgentRequestChain("session/request_permission",n),o=_d(r.shortCircuit?n:r.envelope);if(r.shortCircuit)return this.notifyChain("permission.replied",{toolCallId:o??null,outcome:r.payload,sourceWasTransformer:!0}),r.payload;let i=await this.handlePermissionRequest(r.envelope);return this.notifyChain("permission.replied",{toolCallId:o??null,outcome:i,sourceWasTransformer:!1}),i}),typeof e.connection.onOrphanError=="function"&&e.connection.onOrphanError(n=>{this.handleOrphanError(n)}),e.onExit(()=>{this.agent===e&&this.markClosed({deleteRecord:!1})})}handleOrphanError(e){let t=Date.now()-this.lastCancelAt;if(this.lastCancelAt===0||t>s.CANCEL_ERROR_WINDOW_MS){this.logger?.warn(`agent ${this.agentId} sent uncorrelated error frame code=${e.code} message=${e.message}`);return}this.lastCancelAt=0,this.logger?.warn(`agent ${this.agentId} rejected session/cancel code=${e.code} message=${e.message}`),this.broadcastQueueNotification("hydra-acp/cancel_failed",{sessionId:this.sessionId,code:e.code,message:e.message})}async runResponseChain(e,t=new Set,n=0,r="session/update"){let o=e,i=r==="session/update"?this.injectCumulativeCost(e):e,a=`response:${r}`;for(let l=n;l<this.transformChain.length;l++){let p=this.transformChain[l];if(t.has(p.name)||!p.intercepts.has(a))continue;let f=`t_${wo()}`,h;try{h=await p.connection.request("hydra-acp/transformer/message",{token:f,phase:"response",method:r,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(m){this.logger?.warn(`transformer ${p.name} error on ${a}: ${m.message}`);continue}let k=h?.action??"continue";if(k==="stop")return;if(k==="processing"){let m=l,g=i,y=new Set(t),w=r;await new Promise(v=>{let S=setTimeout(()=>{this.pendingClaims.delete(f)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:f,transformerName:p.name}),this.runResponseChain(g,new Set([...y,p.name]),m+1,w).then(()=>v()).catch(()=>v()))},Ss);typeof S.unref=="function"&&S.unref(),this.pendingClaims.set(f,{resolve:()=>v(),timer:S,transformerName:p.name,method:w,envelope:g,chainIdx:m,originatedBy:y,side:"response"})});return}h?.payload&&typeof h.payload=="object"&&(i=h.payload),t.add(p.name)}if(r!=="session/update")return;this.noteAgentActivity(i);let d=i.update;(fd(d)||this.agentId==="opencode"&&this.opencodeSummary.feed(d))&&this.armRecallFromSelfCompaction();let c=dm(i);if(c!==null){this.setAgentAdvertisedCommands(c);return}let u=im(i);if(u!==null){this.setAgentAdvertisedModes(u);return}if(this.noteModelVerbHint(La(i.update),"session/update"),this.maybeApplyAgentModel(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentMode(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentConfigOption(i)){this.recordAndBroadcast("session/update",this.mergeAgentOptionIntoEnvelope(i));return}if(this.maybeApplyAgentUsage(o)){this.recordAndBroadcast("session/update",i);return}this.maybeApplyAgentSessionInfo(i),this.recordAndBroadcast("session/update",od(i))}armRecallFromSelfCompaction(){this.armRecallInPlace().catch(e=>{this.logger?.warn(`armRecallInPlace failed: ${e.message}`)})}async armRecallInPlace(){if(!this.historyStore)return;let e=await this.historyStore.getRecallTotalCount(this.sessionId).catch(()=>0);if(!(e<=(this._summarizedThroughEntry??0))){if(this._summarizedThroughEntry=e,this.persistWatermarkHook)try{this.persistWatermarkHook(e)}catch(t){this.logger?.warn(`armRecallInPlace: persistWatermarkHook failed: ${t.message}`)}this.broadcastQueueNotification("hydra-acp/context_self_compacted",{sessionId:this.sessionId})}}onAgentChange(e){this.agentChangeHandlers.push(e)}get attachedCount(){return this.clients.size}connectedClients(e){let t=[];for(let n of this.clients.values()){if(e&&n.clientId===e)continue;let r={clientId:n.clientId};n.clientInfo?.name&&(r.name=n.clientInfo.name),n.clientInfo?.version&&(r.version=n.clientInfo.version),t.push(r)}return t}get turnStartedAt(){return this.promptStartedAt}get inUnsolicitedTurn(){return this.unsolicitedTurn!==void 0}get agentPid(){return this.agent.pid}get awaitingInput(){return this.attentionFlags.size>0}async isQuiescedForSwap(){return await this.quiesceBlocker()===void 0}async quiesceBlocker(){if(this.agentTurnInFlight)return"the agent is still working; wait for the current turn to finish, then try again";if(this.unsolicitedTurn!==void 0)return"the agent is part-way through a turn it started by itself; wait for it to finish or interrupt it (^C), then try again";if(this.internalPromptCapture!==void 0)return"hydra is driving the agent right now (compaction seed or transcript injection); this clears by itself, so try again in a moment";if(this.modelChangeInFlight)return"a model change is still settling; try again in a moment";if(this.modeChangeInFlight)return"a mode change is still settling; try again in a moment";let e=this.pendingOneShotBackgroundTasks();if(e.length>0)return`${e.length} background task(s) still running (${e.join(", ")}); a swap would kill the agent process and abandon them. Wait for them to finish, or cancel them, then try again`;let t=await this.openToolCallIdsInHistory();if(t.length>0)return`${t.length} tool call(s) from an earlier turn never reported a result, so the session still reads as busy. ^C closes an abandoned chain; failing that it clears as new history accumulates`}isQuiescedSync(){return!(this.promptInFlight||this.unsolicitedTurn!==void 0||this.modeChangeInFlight||this.modelChangeInFlight)}async swapIntoWorkspace(e){await this.swapUpstream({...e.synopsis!==void 0?{artifact:e.synopsis}:{},note:e.note,framing:"swap",...e.title!==void 0?{title:e.title}:{},tailK:8,tailFloor:4,summarizedThroughEntry:e.historyLength,newCwd:e.cwd,reason:e.workspace!==void 0?"workspace-enter":"workspace-leave"}),this.workspace=e.workspace,e.left!==void 0?(this.formerWorkspace={path:e.left.path,sourceCwd:e.cwd,removed:e.left.removed},this.departureNoteSent=!1):this.formerWorkspace=void 0}async swapUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for swap: ${t}`);if(this.swapInFlight)throw new Error("a swap is already in progress for this session");this.swapInFlight=!0;try{await this.doSwapUpstream(e)}finally{this.swapInFlight=!1}}async doSwapUpstream(e){this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let t=this.agentId,n=e.newAgentId??this.agentId,r=n!==this.agentId,o=e.reason!==void 0&&e.reason!=="compaction"?e.reason:r?"agent-swap":"compaction",i=e.newCwd??this.cwd,a=this.agentArgs,d=this.forwardedEnv,c=this.currentModel,u=this.currentMode,l=this.spawnReplacementAgent;if(!l)throw new Error("agent spawning not configured for this session");let p=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],f=await l({agentId:n,cwd:i,agentArgs:a,...d?{forwardedEnv:d}:{},mcpServers:p});if(this.accumulateAndResetCost(),this.cwd=i,this.wireAgent(f.agent,{respawn:!0}),!r){let M=await pt({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedModel:c,agentReportedModel:f.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(M.result,"model"),await ft({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedMode:u,agentReportedMode:f.initialMode,logger:this.logger})}f.agent.connection.drainBuffered("session/update");let h=[];if(this.historyStore)try{h=await this.historyStore.load(this.sessionId)}catch(M){this.logger?.warn(`swapUpstream: historyStore.load failed: ${M.message}`)}let k=mo({...e.artifact!==void 0?{synopsis:e.artifact}:{},...e.note!==void 0?{note:e.note}:{},...e.framing!==void 0?{framing:e.framing}:{},title:e.title,tail:h,tailK:e.tailK,tailFloor:e.tailFloor,...e.summarizedThroughEntry!==void 0?{watermark:e.summarizedThroughEntry}:{},recallArmed:(e.summarizedThroughEntry??this._summarizedThroughEntry??0)>0});if(this.internalPromptCapture)throw new Error("swapUpstream: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};let m,g;try{await f.agent.connection.request("session/prompt",{sessionId:f.upstreamSessionId,prompt:[{type:"text",text:k}]});let M=this.internalPromptCapture;m=M.lastUsed,g=M.lastSize,this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${k.length} toolCalls=${M.toolCalls} thinkingChars=${M.thinkingChars} messageChars=${M.messageChars} used=${M.lastUsed??"?"} size=${M.lastSize??"?"} reply=${JSON.stringify(M.chunks.join("").slice(0,200))}`)}finally{this.internalPromptCapture=void 0}m!==void 0&&(this.maybeApplyAgentUsage({update:{sessionUpdate:"usage_update",used:m,...g!==void 0?{size:g}:{}}}),this.broadcastCurrentUsage());let y=this.upstreamSessionId,w=this._summarizedThroughEntry;e.summarizedThroughEntry!==void 0&&(this._summarizedThroughEntry=e.summarizedThroughEntry);let v=this.agent;if(this.agent=f.agent,this.upstreamSessionId=f.upstreamSessionId,this.agentMeta=f.agentMeta,this.agentCapabilities=f.agentCapabilities,this.resetModelVerb(f.modelVerb),this.sawTurnComplete=!1,r&&(this.agentId=n,this.agentAdvertisedCommands=[],this.currentModel=f.initialModel,this.currentMode=f.initialMode,this.setAgentAdvertisedModels(f.initialModels??[]),this.setAgentAdvertisedModes(f.initialModes??[]),this.agentAdvertisedConfigOptions=f.initialConfigOptions??[]),this.broadcastMergedCommands(),this.broadcastConfigOptions(),this.notifyAgentChange("swapUpstream",o,e.runId,m),e.summarizedThroughEntry!==void 0&&this.persistWatermarkHook)try{this.persistWatermarkHook(e.summarizedThroughEntry)}catch(M){this.logger?.warn(`swapUpstream: persistWatermarkHook failed: ${M.message}`)}if(!r&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:y,...w!==void 0?{previousSummarizedThroughEntry:w}:{},...e.runId!==void 0?{runId:e.runId}:{}})}catch(M){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${M.message}`)}let S=await this.retireAgent(v,r?"agent switch":e.reason==="workspace-enter"||e.reason==="workspace-leave"?"workspace move":"compaction swap");this.notifyChain("agent.swap",{phase:"post",previousUpstreamSessionId:y,upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}),r||this.broadcastCompactionPhase({phase:"swapped",...this.title!==void 0?{title:this.title}:{},summarizedThroughEntry:e.summarizedThroughEntry??this._summarizedThroughEntry??0}),r&&this.broadcastAgentSwitch(t,n);let b=S.length>0?`
51
51
  Stopped ${S.length} background task(s) with the previous agent: ${S.join(", ")}. Re-arm anything still needed.
52
- `:"",R=(e.reason==="workspace-enter"||e.reason==="workspace-leave"?"":r?`
52
+ `:"",x=(e.reason==="workspace-enter"||e.reason==="workspace-leave"?"":r?`
53
53
  Switched to ${n}.
54
54
  `:`
55
55
  Compaction completed.
56
- `)+b,E=R===""?void 0:R;if(E!==void 0){let M=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:E},_meta:{"hydra-acp":{synthetic:!0}}}});for(let N of this.clients.values())N.connection.notify("session/update",M).catch(()=>{})}this.updatedAt=Date.now()}async rollbackToUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for rollback: ${t}`);let n=this.loadExistingAgentSession;if(!n)throw new Error("loadExistingAgentSession not configured for this session");let r=this.agentId,o=this.cwd,i=this.agentArgs,a=this.forwardedEnv,d=this.currentModel,c=this.currentMode,u=await n(e.previousUpstreamSessionId,{agentId:r,cwd:o,agentArgs:i,...a?{forwardedEnv:a}:{},mcpServers:this.mcpServersConfig??[]});this.accumulateAndResetCost(),this.wireAgent(u.agent,{respawn:!0});let l=await ft({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedModel:d,agentReportedModel:u.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(l.result,"model"),await lt({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedMode:c,agentReportedMode:u.initialMode,logger:this.logger}),u.agent.connection.drainBuffered("session/update");let p=this.agent;this.agent=u.agent,this.upstreamSessionId=u.upstreamSessionId,this.agentMeta=u.agentMeta,this.agentCapabilities=u.agentCapabilities,this.resetModelVerb(u.modelVerb),this.broadcastMergedCommands(),this.broadcastConfigOptions(),await this.retireAgent(p,"rollback"),this._summarizedThroughEntry=e.previousSummarizedThroughEntry,this.broadcastCompactionPhase({phase:"rolled_back",summarizedThroughEntry:e.previousSummarizedThroughEntry??0}),this.notifyAgentChange("rollbackToUpstream","rollback"),this.updatedAt=Date.now()}async reloadUpstreamAfterAgentLoss(){let e=this.loadExistingAgentSession;if(!e)throw new Error("loadExistingAgentSession not configured for this session");let t=this.currentModel,n=this.currentMode,r=await e(this.upstreamSessionId,{agentId:this.agentId,cwd:this.cwd,agentArgs:this.agentArgs,...this.forwardedEnv?{forwardedEnv:this.forwardedEnv}:{},mcpServers:this.mcpServersConfig??[]});this.accumulateAndResetCost(),this.wireAgent(r.agent,{respawn:!0});let o=await ft({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:t,agentReportedModel:r.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(o.result,"model"),await lt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedMode:n,agentReportedMode:r.initialMode,logger:this.logger}),r.agent.connection.drainBuffered("session/update");let i=this.agent;this.agent=r.agent,this.upstreamSessionId=r.upstreamSessionId,this.agentMeta=r.agentMeta,this.agentCapabilities=r.agentCapabilities,this.resetModelVerb(r.modelVerb),this.broadcastMergedCommands(),this.broadcastConfigOptions(),await this.retireAgent(i,"upstream-lost"),this.notifyAgentChange("reloadUpstreamAfterAgentLoss"),this.updatedAt=Date.now()}async openToolCallIdsInHistory(e=Mg){if(!this.historyStore)return[];let t=await this.historyStore.load(this.sessionId),n=t.length>e?t.slice(-e):t,r=new Set,o=new Set;for(let i of n){let d=i.params?.update;if(!d||typeof d.sessionUpdate!="string")continue;let c=d.sessionUpdate,u=typeof d.toolCallId=="string"?d.toolCallId:void 0;if(!u)continue;let l=d.status;c==="tool_call"&&r.add(u),(c==="tool_call"||c==="tool_call_update")&&(l==="completed"||l==="failed")&&o.add(u)}return[...r].filter(i=>!o.has(i))}async getHistorySnapshot(e="inline",t){return this.historyStore?this.historyStore.load(this.sessionId,{tools:e,...t!==void 0?{maxEntries:t}:{}}).catch(()=>[]):[]}async*iterRecallNewestFirst(){this.historyStore&&(yield*this.historyStore.iterRecallNewestFirst(this.sessionId))}async getRecallTotalCount(){return this.historyStore?this.historyStore.getRecallTotalCount(this.sessionId).catch(()=>0):0}async sliceRecallHistory(e,t){return this.historyStore?(await this.historyStore.rangeSlice(this.sessionId,e,t).catch(()=>[])).map(r=>r.entry):[]}onBroadcast(e){return this.broadcastHandlers.push(e),()=>{let t=this.broadcastHandlers.indexOf(e);t>=0&&this.broadcastHandlers.splice(t,1)}}broadcastClientUpdate(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:e});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}broadcastCompactionPhase(e){let t=e.phase;t==="swapped"||t==="failed"||t==="rolled_back"?this._liveCompactionPhase=void 0:this._liveCompactionPhase=e;let n=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_compaction",...e}});for(let r of this.broadcastHandlers)try{r({method:"session/update",params:n,recordedAt:Date.now()})}catch{}for(let r of this.clients.values())r.connection.notify("session/update",n).catch(()=>{});this.notifyChain("compaction",{...e})}broadcastWorkspacePhase(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_workspace",...e}});for(let n of this.broadcastHandlers)try{n({method:"session/update",params:t,recordedAt:Date.now()})}catch{}for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{});this.notifyChain("workspace",{...e})}broadcastSyntheticText(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:e},_meta:{"hydra-acp":{synthetic:!0}}}});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}attach(e,t,n={}){if(this.closed)throw fe(new Error("session is closed"),x.SessionNotFound);if(this.clients.has(e.clientId))throw fe(new Error(`client ${e.clientId} is already attached`),x.AlreadyAttached);return this.clients.set(e.clientId,e),this.cancelOrphanTimer(),this.updatedAt=Date.now(),t==="none"?Promise.resolve({entries:[],appliedPolicy:t}):t==="pending_only"?Promise.resolve({entries:this.buildStateSnapshotReplay(),appliedPolicy:t}):this.loadReplay(t,n)}async loadReplay(e,t){let n=t.toolContent??"inline",r=n==="inline"&&!t.raw&&this.historyStore!==void 0,o=async u=>{if(t.raw)return u;let l=cs(u);return r&&this.historyStore?this.historyStore.hydrate(this.sessionId,l):l},i=t.historyLimit===0?1/0:t.historyLimit??this.historyMaxEntries,a=Lt(await this.getHistorySnapshot(r?"references":n,i===1/0?1/0:i*2),this.side),d=dm(a.filter(u=>!An(u.method,u.params)),i),c=this.buildStateSnapshotReplay();if(e==="after_message"){let u=t.afterSeq!==void 0?cm(d,t.afterSeq):t.afterMessageId?um(d,t.afterMessageId):-1;return u<0?{entries:[...c,...await o(d)],appliedPolicy:"full"}:{entries:[...c,...await o(d.slice(u+1))],appliedPolicy:"after_message"}}return{entries:[...c,...await o(d)],appliedPolicy:"full"}}buildStateSnapshotReplay(){let e=[],t=this.sessionId,n=Date.now();if(this.title!==void 0&&this.title.length>0&&e.push({method:"session/update",params:{sessionId:t,update:{sessionUpdate:"session_info_update",title:this.title}},recordedAt:n}),this.currentModel!==void 0&&this.currentModel.length>0||this.agentAdvertisedModels.length>0){let o={sessionUpdate:"_hydra_current_model_update"};this.currentModel!==void 0&&this.currentModel.length>0&&(o.currentModel=this.currentModel),this.agentAdvertisedModels.length>0&&(o.availableModels=[...this.agentAdvertisedModels]),e.push({method:"session/update",params:{sessionId:t,update:o},recordedAt:n})}this.currentMode!==void 0&&this.currentMode.length>0&&e.push({method:"session/update",params:{sessionId:t,update:{sessionUpdate:"current_mode_update",currentModeId:this.currentMode}},recordedAt:n});let r=this.mergedAvailableCommands();if(r.length>0&&e.push({method:"session/update",params:{sessionId:t,update:{sessionUpdate:"available_commands_update",availableCommands:r}},recordedAt:n}),this.agentAdvertisedModes.length>0&&e.push({method:"session/update",params:{sessionId:t,update:{sessionUpdate:"_hydra_available_modes_update",availableModes:[...this.agentAdvertisedModes]}},recordedAt:n}),this.currentUsage!==void 0){let o=this.currentUsage,i={sessionUpdate:"usage_update"};if(typeof o.used=="number"&&(i.used=o.used),typeof o.size=="number"&&(i.size=o.size),typeof o.costAmount=="number"||typeof o.costCurrency=="string"){let a={};typeof o.costAmount=="number"&&(a.amount=o.costAmount),typeof o.costCurrency=="string"&&(a.currency=o.costCurrency),i.cost=a}Object.keys(i).length>1&&e.push({method:"session/update",params:{sessionId:t,update:i},recordedAt:n})}return this._liveCompactionPhase!==void 0&&e.push({method:"session/update",params:{sessionId:t,update:{sessionUpdate:"_hydra_compaction",...this._liveCompactionPhase}},recordedAt:n}),e}replayPendingPermissions(e){for(let t of this.attentionFlags.values()){if(t.source!=="daemon"||!t.reason.startsWith("permission:"))continue;let n=t.reason.slice(11),r=this.permissionCallbacks.get(n);r&&r(e)}}detach(e){let t=this.clients.get(e);t&&(this.clients.delete(e),this.updatedAt=Date.now(),this.scheduleOrphanCheck(),this.broadcastClientDisconnected(t))}broadcastClientDisconnected(e){let t={clientId:e.clientId};e.clientInfo?.name&&(t.name=e.clientInfo.name),e.clientInfo?.version&&(t.version=e.clientInfo.version);let n={sessionUpdate:"client_disconnected",client:t,timestamp:new Date().toISOString()};for(let r of this.clients.values())r.connection.notify("session/update",{sessionId:this.sessionId,update:n}).catch(()=>{})}reportIsolationBreach(e,t){let n=this.workspace;if(n===void 0){let r=this.formerWorkspace;r!==void 0&&ks(e,r.path)&&(this.logger?.warn?.(`STALE WORKSPACE WRITE on session ${this.sessionId}: the agent wrote ${e}, which is inside the workspace this session already left. That work will not reach ${r.sourceCwd}.`),this.notifyChain("workspace.staleWrite",{path:e,formerWorkspacePath:r.path,sourceCwd:r.sourceCwd,toolCallId:t}));return}Sd(e,n.sourceCwd,n.path)&&(this.logger?.warn?.(`ISOLATION BREACH on session ${this.sessionId}: the agent wrote ${e}, which is in the source tree ${n.sourceCwd}, not its workspace ${n.path}. The user's checkout has been modified.`),this.notifyChain("workspace.breach",{path:e,sourceCwd:n.sourceCwd,workspacePath:n.path,toolCallId:t}))}applyDepartedPromptRewrite(e){let t=this.formerWorkspace;if(t===void 0)return e;let n=!1,r=Md(e,o=>mo(o,t.path)?(n=!0,go(o,t.path,t.sourceCwd).text):o);if(!this.departureNoteSent||n){let o=vd({sourceCwd:t.sourceCwd,formerWorkspacePath:t.path,removed:t.removed});r=wo(r,`${o}
56
+ `)+b,T=x===""?void 0:x;if(T!==void 0){let M=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:T},_meta:{"hydra-acp":{synthetic:!0}}}});for(let N of this.clients.values())N.connection.notify("session/update",M).catch(()=>{})}this.updatedAt=Date.now()}async rollbackToUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for rollback: ${t}`);let n=this.loadExistingAgentSession;if(!n)throw new Error("loadExistingAgentSession not configured for this session");let r=this.agentId,o=this.cwd,i=this.agentArgs,a=this.forwardedEnv,d=this.currentModel,c=this.currentMode,u=await n(e.previousUpstreamSessionId,{agentId:r,cwd:o,agentArgs:i,...a?{forwardedEnv:a}:{},mcpServers:this.mcpServersConfig??[]});this.accumulateAndResetCost(),this.wireAgent(u.agent,{respawn:!0});let l=await pt({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedModel:d,agentReportedModel:u.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(l.result,"model"),await ft({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedMode:c,agentReportedMode:u.initialMode,logger:this.logger}),u.agent.connection.drainBuffered("session/update");let p=this.agent;this.agent=u.agent,this.upstreamSessionId=u.upstreamSessionId,this.agentMeta=u.agentMeta,this.agentCapabilities=u.agentCapabilities,this.resetModelVerb(u.modelVerb),this.broadcastMergedCommands(),this.broadcastConfigOptions(),await this.retireAgent(p,"rollback"),this._summarizedThroughEntry=e.previousSummarizedThroughEntry,this.broadcastCompactionPhase({phase:"rolled_back",summarizedThroughEntry:e.previousSummarizedThroughEntry??0}),this.notifyAgentChange("rollbackToUpstream","rollback"),this.updatedAt=Date.now()}async reloadUpstreamAfterAgentLoss(){let e=this.loadExistingAgentSession;if(!e)throw new Error("loadExistingAgentSession not configured for this session");let t=this.currentModel,n=this.currentMode,r=await e(this.upstreamSessionId,{agentId:this.agentId,cwd:this.cwd,agentArgs:this.agentArgs,...this.forwardedEnv?{forwardedEnv:this.forwardedEnv}:{},mcpServers:this.mcpServersConfig??[]});this.accumulateAndResetCost(),this.wireAgent(r.agent,{respawn:!0});let o=await pt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:t,agentReportedModel:r.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(o.result,"model"),await ft({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedMode:n,agentReportedMode:r.initialMode,logger:this.logger}),r.agent.connection.drainBuffered("session/update");let i=this.agent;this.agent=r.agent,this.upstreamSessionId=r.upstreamSessionId,this.agentMeta=r.agentMeta,this.agentCapabilities=r.agentCapabilities,this.resetModelVerb(r.modelVerb),this.broadcastMergedCommands(),this.broadcastConfigOptions(),await this.retireAgent(i,"upstream-lost"),this.notifyAgentChange("reloadUpstreamAfterAgentLoss"),this.updatedAt=Date.now()}async openToolCallIdsInHistory(e=$g){if(!this.historyStore)return[];let t=await this.historyStore.load(this.sessionId),n=t.length>e?t.slice(-e):t,r=new Set,o=new Set;for(let i of n){let d=i.params?.update;if(!d||typeof d.sessionUpdate!="string")continue;let c=d.sessionUpdate,u=typeof d.toolCallId=="string"?d.toolCallId:void 0;if(!u)continue;let l=d.status;c==="tool_call"&&r.add(u),(c==="tool_call"||c==="tool_call_update")&&(l==="completed"||l==="failed")&&o.add(u)}return[...r].filter(i=>!o.has(i))}async getHistorySnapshot(e="inline",t){return this.historyStore?this.historyStore.load(this.sessionId,{tools:e,...t!==void 0?{maxEntries:t}:{}}).catch(()=>[]):[]}async*iterRecallNewestFirst(){this.historyStore&&(yield*this.historyStore.iterRecallNewestFirst(this.sessionId))}async getRecallTotalCount(){return this.historyStore?this.historyStore.getRecallTotalCount(this.sessionId).catch(()=>0):0}async sliceRecallHistory(e,t){return this.historyStore?(await this.historyStore.rangeSlice(this.sessionId,e,t).catch(()=>[])).map(r=>r.entry):[]}onBroadcast(e){return this.broadcastHandlers.push(e),()=>{let t=this.broadcastHandlers.indexOf(e);t>=0&&this.broadcastHandlers.splice(t,1)}}broadcastClientUpdate(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:e});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}broadcastCompactionPhase(e){let t=e.phase;t==="swapped"||t==="failed"||t==="rolled_back"?this._liveCompactionPhase=void 0:this._liveCompactionPhase=e;let n=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_compaction",...e}});for(let r of this.broadcastHandlers)try{r({method:"session/update",params:n,recordedAt:Date.now()})}catch{}for(let r of this.clients.values())r.connection.notify("session/update",n).catch(()=>{});this.notifyChain("compaction",{...e})}broadcastWorkspacePhase(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_workspace",...e}});for(let n of this.broadcastHandlers)try{n({method:"session/update",params:t,recordedAt:Date.now()})}catch{}for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{});this.notifyChain("workspace",{...e})}broadcastSyntheticText(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:e},_meta:{"hydra-acp":{synthetic:!0}}}});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}attach(e,t,n={}){if(this.closed)throw fe(new Error("session is closed"),R.SessionNotFound);if(this.clients.has(e.clientId))throw fe(new Error(`client ${e.clientId} is already attached`),R.AlreadyAttached);return this.clients.set(e.clientId,e),this.cancelOrphanTimer(),this.updatedAt=Date.now(),t==="none"?Promise.resolve({entries:[],appliedPolicy:t}):t==="pending_only"?Promise.resolve({entries:this.buildStateSnapshotReplay(),appliedPolicy:t}):this.loadReplay(t,n)}async loadReplay(e,t){let n=t.toolContent??"inline",r=n==="inline"&&!t.raw&&this.historyStore!==void 0,o=async u=>{if(t.raw)return u;let l=ls(u);return r&&this.historyStore?this.historyStore.hydrate(this.sessionId,l):l},i=t.historyLimit===0?1/0:t.historyLimit??this.historyMaxEntries,a=Ut(await this.getHistorySnapshot(r?"references":n,i===1/0?1/0:i*2),this.side),d=um(a.filter(u=>!Rn(u.method,u.params)),i),c=this.buildStateSnapshotReplay();if(e==="after_message"){let u=t.afterSeq!==void 0?lm(d,t.afterSeq):t.afterMessageId?fm(d,t.afterMessageId):-1;return u<0?{entries:[...c,...await o(d)],appliedPolicy:"full"}:{entries:[...c,...await o(d.slice(u+1))],appliedPolicy:"after_message"}}return{entries:[...c,...await o(d)],appliedPolicy:"full"}}buildStateSnapshotReplay(){let e=[],t=this.sessionId,n=Date.now();if(this.title!==void 0&&this.title.length>0&&e.push({method:"session/update",params:{sessionId:t,update:{sessionUpdate:"session_info_update",title:this.title}},recordedAt:n}),this.currentModel!==void 0&&this.currentModel.length>0||this.agentAdvertisedModels.length>0){let o={sessionUpdate:"_hydra_current_model_update"};this.currentModel!==void 0&&this.currentModel.length>0&&(o.currentModel=this.currentModel),this.agentAdvertisedModels.length>0&&(o.availableModels=[...this.agentAdvertisedModels]),e.push({method:"session/update",params:{sessionId:t,update:o},recordedAt:n})}this.currentMode!==void 0&&this.currentMode.length>0&&e.push({method:"session/update",params:{sessionId:t,update:{sessionUpdate:"current_mode_update",currentModeId:this.currentMode}},recordedAt:n});let r=this.mergedAvailableCommands();if(r.length>0&&e.push({method:"session/update",params:{sessionId:t,update:{sessionUpdate:"available_commands_update",availableCommands:r}},recordedAt:n}),this.agentAdvertisedModes.length>0&&e.push({method:"session/update",params:{sessionId:t,update:{sessionUpdate:"_hydra_available_modes_update",availableModes:[...this.agentAdvertisedModes]}},recordedAt:n}),this.currentUsage!==void 0){let o=this.currentUsage,i={sessionUpdate:"usage_update"};if(typeof o.used=="number"&&(i.used=o.used),typeof o.size=="number"&&(i.size=o.size),typeof o.costAmount=="number"||typeof o.costCurrency=="string"){let a={};typeof o.costAmount=="number"&&(a.amount=o.costAmount),typeof o.costCurrency=="string"&&(a.currency=o.costCurrency),i.cost=a}Object.keys(i).length>1&&e.push({method:"session/update",params:{sessionId:t,update:i},recordedAt:n})}return this._liveCompactionPhase!==void 0&&e.push({method:"session/update",params:{sessionId:t,update:{sessionUpdate:"_hydra_compaction",...this._liveCompactionPhase}},recordedAt:n}),e}replayPendingPermissions(e){for(let t of this.attentionFlags.values()){if(t.source!=="daemon"||!t.reason.startsWith("permission:"))continue;let n=t.reason.slice(11),r=this.permissionCallbacks.get(n);r&&r(e)}}detach(e){let t=this.clients.get(e);t&&(this.clients.delete(e),this.updatedAt=Date.now(),this.scheduleOrphanCheck(),this.broadcastClientDisconnected(t))}broadcastClientDisconnected(e){let t={clientId:e.clientId};e.clientInfo?.name&&(t.name=e.clientInfo.name),e.clientInfo?.version&&(t.version=e.clientInfo.version);let n={sessionUpdate:"client_disconnected",client:t,timestamp:new Date().toISOString()};for(let r of this.clients.values())r.connection.notify("session/update",{sessionId:this.sessionId,update:n}).catch(()=>{})}reportIsolationBreach(e,t){let n=this.workspace;if(n===void 0){let r=this.formerWorkspace;r!==void 0&&bs(e,r.path)&&(this.logger?.warn?.(`STALE WORKSPACE WRITE on session ${this.sessionId}: the agent wrote ${e}, which is inside the workspace this session already left. That work will not reach ${r.sourceCwd}.`),this.notifyChain("workspace.staleWrite",{path:e,formerWorkspacePath:r.path,sourceCwd:r.sourceCwd,toolCallId:t}));return}Ad(e,n.sourceCwd,n.path)&&(this.logger?.warn?.(`ISOLATION BREACH on session ${this.sessionId}: the agent wrote ${e}, which is in the source tree ${n.sourceCwd}, not its workspace ${n.path}. The user's checkout has been modified.`),this.notifyChain("workspace.breach",{path:e,sourceCwd:n.sourceCwd,workspacePath:n.path,toolCallId:t}))}applyDepartedPromptRewrite(e){let t=this.formerWorkspace;if(t===void 0)return e;let n=!1,r=$d(e,o=>yo(o,t.path)?(n=!0,ho(o,t.path,t.sourceCwd).text):o);if(!this.departureNoteSent||n){let o=Sd({sourceCwd:t.sourceCwd,formerWorkspacePath:t.path,removed:t.removed});r=vo(r,`${o}
57
57
 
58
- `),this.departureNoteSent=!0}return r}applyWorkspacePromptRewrite(e){let t=this.workspace;if(t===void 0)return this.applyDepartedPromptRewrite(e);let n=!1,r=Md(e,i=>mo(i,t.sourceCwd)?(n=!0,go(i,t.sourceCwd,t.path).text):i);if(!this.workspacePreambleSent||n){let i=bd({workspacePath:t.path,sourceCwd:t.sourceCwd,notes:this.workspaceNotes,...this.workspacePreambleSent?{reassert:!0}:{}});r=wo(r,`${i}
58
+ `),this.departureNoteSent=!0}return r}applyWorkspacePromptRewrite(e){let t=this.workspace;if(t===void 0)return this.applyDepartedPromptRewrite(e);let n=!1,r=$d(e,i=>yo(i,t.sourceCwd)?(n=!0,ho(i,t.sourceCwd,t.path).text):i);if(!this.workspacePreambleSent||n){let i=Id({workspacePath:t.path,sourceCwd:t.sourceCwd,notes:this.workspaceNotes,...this.workspacePreambleSent?{reassert:!0}:{}});r=vo(r,`${i}
59
59
 
60
- `),this.workspacePreambleSent=!0}return r}async prompt(e,t,n,r){let o=this.clients.get(e);if(!o)throw fe(new Error("client not attached"),x.SessionNotFound);if(this.closing)throw fe(new Error("session is closing; new prompts cannot be accepted"),x.SessionClosing);let i=Ge();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(at((t??{})._meta).ancillary===!0)&&this._interactive!==!0){this._interactive=!0,this.cancelOrphanTimer();for(let d of this.interactiveHandlers)try{d(!0)}catch{}}return this.enqueueUserPrompt(o,t,i,n,r)}broadcastPromptReceived(e){this.closeUnsolicitedTurn("superseded",`prompt:${e.messageId}`);let t={clientId:e.originator.clientId};e.originator.name&&(t.name=e.originator.name),e.originator.version&&(t.version=e.originator.version),e.originator.fromSession&&(t.fromSession=e.originator.fromSession),e.originator.fromSessionTitle&&(t.fromSessionTitle=e.originator.fromSessionTitle),e.originator.fromLabel&&(t.fromLabel=e.originator.fromLabel),e.originator.depth!==void 0&&(t.depth=e.originator.depth),this.promptStartedAt=Date.now(),this.turnRanTool=!1,this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"prompt_received",messageId:e.messageId,prompt:e.prompt,sentBy:t}},e.clientId);let n=It(e.prompt);n.length>0&&this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"user_message_chunk",content:{type:"text",text:n},_meta:{"hydra-acp":{compatFor:"prompt_received"}}}},e.clientId)}recordCurrentUsageSnapshot(){if(this.historyStore===void 0)return;let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let r={};typeof e.costAmount=="number"&&(r.amount=e.costAmount),typeof e.costCurrency=="string"&&(r.currency=e.costCurrency),t.cost=r}if(Object.keys(t).length<=1)return;t._meta={"hydra-acp":{upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}};let n={sessionId:this.sessionId,update:t};this.historyStore.append(this.sessionId,{method:"session/update",params:n,recordedAt:Date.now()}).catch(()=>{})}originatorNeedsTurnComplete(e){return e.wasAmend===!0||e.wasSteer===!0}broadcastTurnComplete(e,t,n,r,o){let i=t&&typeof t=="object"&&"stopReason"in t&&typeof t.stopReason=="string"?t.stopReason:void 0,a={sessionUpdate:"turn_complete",messageId:Ge()};i!==void 0&&(a.stopReason=i),o!==void 0&&(a.errorMessage=o);let d=at(t?._meta).salvaged;d!==void 0&&(a._meta={[le]:{salvaged:d}}),this.supersededAutonomousTurn=void 0;let c=this.amendInProgress;if(c&&n!==void 0&&c.cancelledMessageId===n&&(a._meta={[le]:{...d!==void 0?{salvaged:d}:{},amended:{cancelledMessageId:c.cancelledMessageId,newMessageId:c.newMessageId}}}),this.promptStartedAt=void 0,this.noteTurnEnded(),this.sawTurnComplete=!0,this.scheduleWorkspaceSnapshotHook?.(),n!==void 0&&i!==void 0){this.recordTerminal(n,i);let u=this.pendingTurnNotifiers.get(n);u&&(this.pendingTurnNotifiers.delete(n),oo(u,{sessionId:this.sessionId,messageId:u.originalMessageId,stopReason:i,deliveredAt:Date.now(),...n!==u.originalMessageId?{amendedTo:n}:{}}))}i==="cancelled"||i==="error"||i==="refusal"?this.closeOpenToolCalls(i):this.armOpenToolCalls(),this.recordCurrentUsageSnapshot(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:a},r?void 0:e),c&&n!==void 0&&c.cancelledMessageId===n&&this.broadcastPromptAmended(c)}noteAgentActivity(e){if(!(this.closing||this.closed)){if(Hg(e)||this.steerCausedTurnTerminal(e)){if(this.unsolicitedTurn!==void 0){this.closeUnsolicitedTurn("completed");return}this.salvageSupersededTerminal();return}this.pendingSteerDetach!==void 0&&this.currentEntry?.messageId===this.pendingSteerDetach.messageId&&Rd(e)&&(this.pendingSteerDetach=void 0),!An("session/update",e)&&(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||jg(e)||this.openUnsolicitedTurn()))}}steerCausedTurnTerminal(e){return this.unsolicitedTurn?.steerCaused!==!0?!1:Rd(e)}noteBackgroundTaskArming(e){let t=e?.update;if(!t||typeof t!="object")return;let n=typeof t.toolCallId=="string"?t.toolCallId:void 0;if(n===void 0)return;let r=t.rawInput,o=em(t._meta);this.rememberToolLabel(n,t,r,o),this.noteBackgroundTaskStopped(t,r,o);let i=Zg(t.rawOutput),a=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:i??Xg(t.rawOutput),d=i!==void 0||r?.background===!0;if(!(a!==void 0||d||r!==void 0&&r.run_in_background===!0))return;let u=this.toolLabels.get(n)?.label??"background task";this.lastBackgroundTask={toolCallId:n,label:u};let l=Date.now(),p=this.armedTasks.get(n),f=a??p?.taskId,h=Yg(t.title,o,r)||p?.repeating===!0;this.armedTasks.set(n,{label:u,...f!==void 0?{taskId:f}:{},repeating:h,armedAt:p?.armedAt??l,...d||p?.endUnobservable===!0?{endUnobservable:!0}:{}}),this.onArmedTasksChanged()}applyBackgroundTaskLevel(e){let t=e?.message;if(!t||t.subtype!=="background_tasks_changed")return;let n=t.tasks;if(!Array.isArray(n))return;let r=Date.now(),o=new Map;for(let a of n){let d=a,c=typeof d?.task_id=="string"?d.task_id:void 0;c!==void 0&&o.set(c,{taskType:typeof d?.task_type=="string"?d.task_type:"unknown",description:typeof d?.description=="string"?d.description:"",firstSeen:this.liveBackgroundTasks.get(c)?.firstSeen??r})}let i=[...this.liveBackgroundTasks.keys()].filter(a=>!o.has(a));this.liveBackgroundTasks=o,this.sawBackgroundTaskLevel=!0,this.logger?.info(`session ${this.sessionId} background level: ${o.size} live`+(i.length>0?` (ended: ${i.join(", ")})`:"")),this.onArmedTasksChanged()}get armedBackgroundTasks(){return this.sawBackgroundTaskLevel?[...this.liveBackgroundTasks.entries()].map(([e,t])=>({taskId:e,label:t.description||t.taskType,taskType:t.taskType,since:t.firstSeen})):[...this.armedTasks.entries()].map(([e,t])=>({toolCallId:e,label:t.label,...t.taskId!==void 0?{taskId:t.taskId}:{},since:t.armedAt,...t.endUnobservable===!0?{endUnobservable:!0}:{}}))}pendingOneShotBackgroundTasks(){return this.sawBackgroundTaskLevel?[...this.liveBackgroundTasks.values()].filter(e=>Wg.has(e.taskType)).map(e=>e.description||e.taskType):[...this.armedTasks.values()].filter(e=>!e.repeating&&e.endUnobservable!==!0).map(e=>e.label)}get armedSince(){let e;if(this.sawBackgroundTaskLevel){for(let t of this.liveBackgroundTasks.values())(e===void 0||t.firstSeen<e)&&(e=t.firstSeen);return e}for(let t of this.armedTasks.values())(e===void 0||t.armedAt<e)&&(e=t.armedAt);return e}onArmedTasksChanged(){let e=this.armedBackgroundTasks,t=e.length,n=this.armedSince,r=e.map(o=>o.taskId??o.toolCallId??o.label).sort().join("\0");r===this.lastArmedBroadcast?.key&&n===this.lastArmedBroadcast?.since||this.closed||(this.lastArmedBroadcast={key:r,since:n},this.broadcastQueueNotification("hydra-acp/session/armed_tasks_updated",{sessionId:this.sessionId,count:t,...n!==void 0?{since:n}:{},tasks:e}),this.dispatchIdle())}async retireAgent(e,t){return await e.kill().catch(()=>{}),this.resetBackgroundTaskLevel(),this.discardArmedTasks(t)}resetBackgroundTaskLevel(){this.liveBackgroundTasks.clear(),this.sawBackgroundTaskLevel=!1}discardArmedTasks(e){if(this.armedTasks.size===0)return[];let t=[...this.armedTasks.values()].map(n=>n.label);for(let[n,r]of this.armedTasks)r.openToolCall===!0&&this.openToolCalls.delete(n);return this.armedTasks.clear(),this.upstreamBaselineMs=void 0,this.logger?.info(`session ${this.sessionId} discarded ${t.length} armed task(s) on ${e}: ${t.join(", ")}`),this.onArmedTasksChanged(),t}noteBackgroundTaskStopped(e,t,n){if(!(n?.toolName==="TaskStop"||e.title==="TaskStop"))return;let o=t?.task_id;if(typeof o!="string"||o.length===0)return;let i=!1;for(let[a,d]of this.armedTasks)d.taskId===o&&(this.armedTasks.delete(a),i=!0);i&&this.onArmedTasksChanged()}rememberToolLabel(e,t,n,r){let o=n!==void 0&&typeof n.description=="string"&&n.description?n.description:void 0;if(o!==void 0)this.toolLabels.set(e,{label:o.slice(0,yo),fromDescription:!0});else if(this.toolLabels.get(e)?.fromDescription!==!0){let i=typeof t.title=="string"&&t.title?t.title:typeof r?.toolName=="string"&&r.toolName?r.toolName:void 0;i!==void 0&&this.toolLabels.set(e,{label:i.slice(0,yo),fromDescription:!1})}for(;this.toolLabels.size>Bg;){let i=this.toolLabels.keys().next().value;if(i===void 0)break;this.toolLabels.delete(i)}}openUnsolicitedTurn(){let e=Date.now();if(this.lastUnsolicitedCancelAt!==0&&e-this.lastUnsolicitedCancelAt<=s.UNSOLICITED_REOPEN_WINDOW_MS?this.cancelReopenStreak+=1:this.cancelReopenStreak=0,this.lastUnsolicitedCancelAt=0,this.cancelReopenStreak>=s.UNSOLICITED_REOPEN_LIMIT){this.escalateUnresponsiveCancel();return}let t=this.lastBackgroundTask,n=!1;for(let[i,a]of this.armedTasks)a.repeating||a.openToolCall===!0||(this.armedTasks.delete(i),n=!0);n&&this.onArmedTasksChanged();let r={messageId:Ge(),startedAt:e,cause:t,steerCaused:this.pendingSteerDetach!==void 0};this.pendingSteerDetach=void 0,this.unsolicitedTurn=r,this.promptStartedAt=e,this.logger?.info(`session ${this.sessionId} agent resumed with no prompt in flight`+(t?` (after ${t.label})`:""));let o={unsolicited:!0};t&&(o.cause=t),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"_hydra_turn_started",messageId:r.messageId,_meta:{"hydra-acp":o}}})}async holdForUnsolicitedTurn(e){if(this.unsolicitedTurn===void 0){this.logger?.info(`session ${this.sessionId} queue hold skipped for ${e.messageId} (no unsolicited turn open)`);return}let t=Date.now(),n=this.unsolicitedTurn.cause;this.logger?.info(`session ${this.sessionId} holding ${e.messageId} behind unsolicited turn ${this.unsolicitedTurn.messageId}`+(n?` cause=${JSON.stringify(n.label)}`:"")),this.broadcastQueueNotification("hydra-acp/prompt_queue/held",{sessionId:this.sessionId,messageId:e.messageId,reason:"agent_resumed",...n?{cause:n}:{}});let r="turn_ended";for(;;){if(this.closing||this.closed){r="closing";break}if(e.cancelled){r="cancelled";break}if(this.unsolicitedTurn===void 0){r="turn_ended";break}await new Promise(i=>{let a=setTimeout(i,qg);typeof a.unref=="function"&&a.unref()})}let o=Date.now()-t;this.logger?.info(`session ${this.sessionId} released ${e.messageId} reason=${r} heldMs=${o}`),this.broadcastQueueNotification("hydra-acp/prompt_queue/released",{sessionId:this.sessionId,messageId:e.messageId,reason:r,heldMs:o})}closeUnsolicitedTurn(e,t){let n=this.unsolicitedTurn;if(n===void 0)return;let r=Date.now()-n.startedAt;this.unsolicitedTurn=void 0,this.promptStartedAt=void 0,this.noteTurnEnded(),e==="cancelled"?this.lastUnsolicitedCancelAt=Date.now():(this.lastUnsolicitedCancelAt=0,this.cancelReopenStreak=0),this.logger?.info(`session ${this.sessionId} unsolicited turn ${n.messageId} closed reason=${e} durationMs=${r}`+(t?` by=${t}`:"")+(n.cause?` cause=${JSON.stringify(n.cause.label)}`:"")),e==="superseded"&&(this.supersededAutonomousTurn={turnMessageId:n.messageId,cause:n.cause,supersededAt:Date.now()}),this.recordCurrentUsageSnapshot(),!this.closed&&(e==="cancelled"?this.closeOpenToolCalls("cancelled"):e==="completed"&&this.armOpenToolCalls(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"_hydra_turn_ended",messageId:Ge(),startedMessageId:n.messageId,durationMs:r,_meta:{"hydra-acp":{unsolicited:!0,reason:e}}}}))}salvageSupersededTerminal(){let e=this.supersededAutonomousTurn;if(e===void 0)return;this.supersededAutonomousTurn=void 0;let t=this.autonomousSalvage;t!==void 0&&(this.autonomousSalvage=void 0,this.logger?.warn(`session ${this.sessionId} salvaged session/prompt from autonomous terminal (superseded turn ${e.turnMessageId}, ${Date.now()-e.supersededAt}ms earlier)`+(e.cause?` cause=${JSON.stringify(e.cause.label)}`:"")),t({stopReason:"end_turn",_meta:{[le]:{salvaged:{reason:"autonomous_terminal",supersededMessageId:e.turnMessageId}}}}))}async awaitPromptResponse(e){if(this.supersededAutonomousTurn===void 0)return e;try{return await new Promise((t,n)=>{this.autonomousSalvage=t,e.then(t,n)})}finally{this.autonomousSalvage=void 0}}recordTerminal(e,t){for(this.recentlyTerminal.set(e,{stopReason:t,terminatedAt:Date.now()});this.recentlyTerminal.size>Ng;){let n=this.recentlyTerminal.keys().next().value;if(n===void 0)break;this.recentlyTerminal.delete(n)}}registerTurnNotify(e,t,n){let r=this.recentlyTerminal.get(e);if(r)return{alreadyTerminal:!0,stopReason:r.stopReason};for(this.pendingTurnNotifiers.set(e,{callbackUrl:t,secret:n,registeredAt:Date.now(),originalMessageId:e});this.pendingTurnNotifiers.size>Og;){let o=this.pendingTurnNotifiers.keys().next().value;if(o===void 0)break;this.pendingTurnNotifiers.delete(o)}return{alreadyTerminal:!1}}broadcastPromptAmended(e){let t=this.findUserEntry(e.newMessageId);if(!t)return;let n={sessionId:this.sessionId,cancelledMessageId:e.cancelledMessageId,newMessageId:e.newMessageId,prompt:t.prompt,originator:t.originator,amendedAt:Date.now()};this.broadcastQueueNotification("hydra-acp/prompt/amended",n)}findUserEntry(e){if(this.currentEntry?.messageId===e&&this.currentEntry.kind==="user")return this.currentEntry;let t=this.promptQueue.find(n=>n.messageId===e&&n.kind==="user");return t?.kind==="user"?t:void 0}visibleQueueDepth(){let e=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled?1:0;for(let t of this.promptQueue)t.kind==="user"&&!t.cancelled&&(e+=1);return e}broadcastQueueAdded(e,t){let n=this.visibleQueueDepth(),r=t?.position??Math.max(0,n-1),o={sessionId:this.sessionId,messageId:e.messageId,originator:e.originator,prompt:e.prompt,position:r,queueDepth:n,enqueuedAt:e.enqueuedAt};t?.amending!==void 0&&(o._meta={"hydra-acp":{amending:t.amending}}),this.broadcastQueueNotification("hydra-acp/prompt_queue/added",o)}broadcastQueueUpdated(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/updated",{sessionId:this.sessionId,messageId:e,prompt:t})}broadcastQueueRemoved(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/removed",{sessionId:this.sessionId,messageId:e,reason:t})}broadcastQueueNotification(e,t){for(let n of this.clients.values())n.connection.notify(e,t).catch(()=>{})}queueSnapshot(){let e=[],t=0;this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled&&e.push({messageId:this.currentEntry.messageId,originator:this.currentEntry.originator,prompt:this.currentEntry.prompt,position:t++,enqueuedAt:this.currentEntry.enqueuedAt});for(let n of this.promptQueue)n.kind!=="user"||n.cancelled||e.push({messageId:n.messageId,originator:n.originator,prompt:n.prompt,position:t++,enqueuedAt:n.enqueuedAt});return e}async flushPersistWrites(){await this.queueWriteChain.catch(()=>{})}replayPersistedQueue(e){for(let t of e){let n={clientId:`hydra-resurrected_${t.messageId}`};t.originator.clientInfo.name!==void 0&&(n.name=t.originator.clientInfo.name),t.originator.clientInfo.version!==void 0&&(n.version=t.originator.clientInfo.version);let r={kind:"user",messageId:t.messageId,originator:n,clientId:n.clientId,prompt:t.prompt,enqueuedAt:t.enqueuedAt,cancelled:!1,resolve:()=>{},reject:()=>{}};this.promptQueue.push(r),this.broadcastQueueAdded(r)}this.drainQueue()}cancelQueuedPrompt(e){if(this.currentEntry?.messageId===e)return{cancelled:!1,reason:"already_running"};let t=this.promptQueue.findIndex(r=>r.messageId===e);if(t<0)return{cancelled:!1,reason:"not_found"};let n=this.promptQueue[t];return n.cancelled=!0,this.promptQueue.splice(t,1),n.kind==="user"&&(this.broadcastQueueRemoved(e,"cancelled"),this.persistRewrite()),this.amendInProgress?.newMessageId===e&&(this.amendInProgress=void 0),n.resolve({stopReason:"cancelled"}),{cancelled:!0,reason:"ok"}}updateQueuedPrompt(e,t){if(this.currentEntry?.messageId===e)return{updated:!1,reason:"already_running"};let n=this.promptQueue.find(r=>r.messageId===e);return!n||n.kind!=="user"?{updated:!1,reason:"not_found"}:(n.prompt=t,this.broadcastQueueUpdated(e,t),this.persistRewrite(),{updated:!0,reason:"ok"})}amendPrompt(e,t){let n=this.clients.get(e);if(!n)throw fe(new Error("client not attached"),x.SessionNotFound);let{targetMessageId:r,prompt:o,replaceQueue:i,onTargetCompleted:a}=t;if(this.currentEntry?.messageId===r&&this.currentEntry.kind==="user"&&!this.currentEntry.cancelled&&this.amendInProgress===void 0)return this.amendOnHead(n,o,r,i);let d=this.promptQueue.find(u=>u.messageId===r&&u.kind==="user");if(d&&d.kind==="user"&&!d.cancelled)return d.prompt=o,this.broadcastQueueUpdated(r,o),this.persistRewrite(),{amended:!0,reason:"ok",messageId:r};let c=this.recentlyTerminal.get(r);return c?c.stopReason==="cancelled"?{amended:!1,reason:"target_cancelled"}:a==="send_anyway"?{amended:!1,reason:"target_completed",messageId:this.enqueueAmendmentAsFollowUp(n,o)}:{amended:!1,reason:"target_completed"}:{amended:!1,reason:"target_not_found"}}amendOnHead(e,t,n,r){let o=Ge(),i={clientId:e.clientId};if(e.clientInfo?.name&&(i.name=e.clientInfo.name),e.clientInfo?.version&&(i.version=e.clientInfo.version),r){let c=[];for(let u of this.promptQueue){if(u.kind==="user"&&!u.cancelled){u.cancelled=!0,this.broadcastQueueRemoved(u.messageId,"cancelled"),u.resolve({stopReason:"cancelled"});continue}c.push(u)}this.promptQueue=c}let a={kind:"user",messageId:o,originator:i,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,wasAmend:!0,resolve:()=>{},reject:()=>{}};this.promptQueue.unshift(a),this.persistRewrite(),this.broadcastQueueAdded(a,{amending:n,position:1}),this.amendInProgress={cancelledMessageId:n,newMessageId:o};let d=this.pendingTurnNotifiers.get(n);return d&&(this.pendingTurnNotifiers.delete(n),this.pendingTurnNotifiers.set(o,d)),this.cancelExtensionDispatch(n,"amended"),this.agent.connection.notify("session/cancel",{sessionId:this.upstreamSessionId}).catch(()=>{}),{amended:!0,reason:"ok",messageId:o}}async steer(e,t){let n=this.clients.get(e);if(!n)throw fe(new Error("client not attached"),x.SessionNotFound);let r=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled;if(r&&this.agent.steeringSupported){this.pendingSteerDetach={messageId:this.currentEntry.messageId};let o;try{o=await this.forwardRequest("_session/steering",t)}catch(d){throw this.pendingSteerDetach=void 0,d}let i=o?.outcome,a=i==="injected"||i==="startedNewTurn"||i==="promptRequired"||i==="failed"?o:{outcome:"failed"};return a.outcome!=="startedNewTurn"&&(this.pendingSteerDetach=void 0),a.outcome==="injected"&&this.recordSteerAsUserMessageChunk(t.prompt,e),a.outcome==="startedNewTurn"?{...a,detached:!0}:a}return r?(this.amendOnHead(n,t.prompt,this.currentEntry.messageId,!1),{outcome:"startedNewTurn"}):t._meta?.steering?.idleBehavior==="promptRequired"?{outcome:"promptRequired",reason:"noRunningTurn"}:(this.prompt(e,{sessionId:t.sessionId,prompt:t.prompt},void 0,{steerOriginated:!0}).catch(o=>{this.logger?.warn(`steer-originated prompt failed to enqueue: ${o.message}`)}),{outcome:"startedNewTurn"})}recordSteerAsUserMessageChunk(e,t){let n=It(e);n.length!==0&&this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"user_message_chunk",content:{type:"text",text:n},_meta:{"hydra-acp":{steered:!0}}}},t)}enqueueAmendmentAsFollowUp(e,t){let n=Ge(),r={clientId:e.clientId};e.clientInfo?.name&&(r.name=e.clientInfo.name),e.clientInfo?.version&&(r.version=e.clientInfo.version);let o={kind:"user",messageId:n,originator:r,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,resolve:()=>{},reject:()=>{}};return this.promptQueue.push(o),this.persistRewrite(),this.broadcastQueueAdded(o),this.drainQueue(),n}async cancel(e){if(!this.clients.get(e))throw fe(new Error("client not attached"),x.SessionNotFound);this.logger?.info(`session ${this.sessionId} session/cancel from ${e} promptInFlight=${this.promptInFlight} agentTurnInFlight=${this.agentTurnInFlight} unsolicitedTurn=${this.unsolicitedTurn!==void 0} queued=${this.promptQueue.length}`),this.lastCancelAt=Date.now(),this.currentEntry?.kind==="user"&&this.currentEntry.messageId!==void 0&&this.cancelExtensionDispatch(this.currentEntry.messageId,"cancelled"),this.closeUnsolicitedTurn("cancelled"),this.agentTurnInFlight||this.closeOpenToolCalls("cancelled"),await this.forwardRequest("session/cancel",{sessionId:this.sessionId},new Set,0,"notification")}addTransformer(e){let t=this.transformChain.findIndex(n=>n.name===e.name);t>=0?this.transformChain[t]=e:this.transformChain.push(e),e.intercepts.has("lifecycle:session.opened")&&e.connection.notify("hydra-acp/transformer/session_event",{event:"session.opened",sessionId:this.sessionId}).catch(()=>{})}async forwardRequest(e,t,n=new Set,r=0,o="request"){let i=this.rewriteForAgent(t);for(let a=r;a<this.transformChain.length;a++){let d=this.transformChain[a];if(n.has(d.name))continue;let c=`request:${e}`;if(!d.intercepts.has(c))continue;let u=`t_${ho()}`,l;try{l=await d.connection.request("hydra-acp/transformer/message",{token:u,phase:"request",method:e,direction:"client\u2192agent",sessionId:this.sessionId,envelope:i})}catch(f){this.logger?.warn(`transformer ${d.name} error on ${c}: ${f.message}`);continue}let p=l?.action??"continue";if(p==="stop")return o==="notification"?void 0:l?.payload??ko(e);if(p==="continue"){l?.payload&&typeof l.payload=="object"&&(i=l.payload),n.add(d.name);continue}if(p==="processing"){let f=a,h=i,k=new Set(n);return new Promise(m=>{let g=setTimeout(()=>{this.pendingClaims.delete(u)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:u,transformerName:d.name}),this.forwardRequest(e,h,new Set([...k,d.name]),f+1,o).then(m).catch(()=>m(o==="notification"?void 0:ko(e))))},vs);typeof g.unref=="function"&&g.unref(),this.pendingClaims.set(u,{resolve:m,timer:g,transformerName:d.name,method:e,envelope:h,chainIdx:f,originatedBy:k,side:"request",tailKind:o})})}n.add(d.name)}if(o==="notification"){await this.agent.connection.notify(e,i);return}return this.agent.connection.request(e,i)}async forwardModelChange(e,t){let n=await ut({request:(r,o)=>this.forwardRequest(r,o),sessionId:this.sessionId,modelId:e,verb:this.modelVerb,extraParams:t,logger:this.logger});return this.modelVerb=n.verb,this.modelVerbConfirmed=!0,n.result}noteModelVerbHint(e,t){e===void 0||this.modelVerbConfirmed||e===this.modelVerb||(this.logger?.info(`model verb for agent ${this.agentId} inferred as ${e} from ${t} (was ${this.modelVerb})`),this.modelVerb=e)}resetModelVerb(e){this.modelVerb=e??ze,this.modelVerbConfirmed=!1}async runAgentRequestChain(e,t,n=new Set,r=0){let o=t,i=`request:${e}`;for(let a=r;a<this.transformChain.length;a++){let d=this.transformChain[a];if(n.has(d.name)||!d.intercepts.has(i))continue;let c=`t_${ho()}`,u;try{u=await d.connection.request("hydra-acp/transformer/message",{token:c,phase:"request",method:e,direction:"agent\u2192client",sessionId:this.sessionId,envelope:o})}catch(p){this.logger?.warn(`transformer ${d.name} error on ${i}: ${p.message}`);continue}let l=u?.action??"continue";if(l==="stop")return{shortCircuit:!0,payload:u?.payload??mm(e)};if(l==="continue"){u?.payload&&typeof u.payload=="object"&&(o=u.payload),n.add(d.name);continue}if(l==="processing"){let p=a,f=o,h=new Set(n),k=e;return new Promise(m=>{let g=setTimeout(()=>{this.pendingClaims.delete(c)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:c,transformerName:d.name}),this.runAgentRequestChain(k,f,new Set([...h,d.name]),p+1).then(m).catch(()=>m({shortCircuit:!1,envelope:f})))},vs);typeof g.unref=="function"&&g.unref(),this.pendingClaims.set(c,{resolve:y=>m({shortCircuit:!0,payload:y}),timer:g,transformerName:d.name,method:k,envelope:f,chainIdx:p,originatedBy:h,side:"agent-request"})})}n.add(d.name)}return{shortCircuit:!1,envelope:o}}dischargeClaim(e,t){let n=this.pendingClaims.get(e);return n?(clearTimeout(n.timer),this.pendingClaims.delete(e),n.resolve(t),!0):!1}keepAliveClaim(e,t){let n=this.pendingClaims.get(e);if(!n)return!1;clearTimeout(n.timer);let r=typeof t=="number"&&t>0?Math.min(t*1.5,1800*1e3):vs,o=setTimeout(()=>{if(this.pendingClaims.delete(e))if(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:e,transformerName:n.transformerName}),n.side==="response")this.runResponseChain(n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1).then(()=>n.resolve(void 0)).catch(()=>n.resolve(void 0));else if(n.side==="agent-request")this.runAgentRequestChain(n.method,n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1).then(n.resolve).catch(()=>n.resolve({shortCircuit:!1,envelope:n.envelope}));else{let i=n.tailKind??"request";this.forwardRequest(n.method,n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1,i).then(n.resolve).catch(()=>n.resolve(i==="notification"?void 0:ko(n.method)))}},r);return typeof o.unref=="function"&&o.unref(),n.timer=o,!0}async emitToChain(e,t,n){let r=this.transformChain.findIndex(a=>a.name===e),o=r>=0?r+1:0,i=new Set([e]);if(t==="session/update"){await this.runResponseChain(n,i,o);return}return this.forwardRequest(t,n,i,o)}async emitToQueue(e,t){let n=this.transformChain.findIndex(c=>c.name===e),r=n>=0?n+1:0,o=(t??{}).prompt??[],i=Ge(),a=`transformer:${e}`,d={clientId:a,name:e};return new Promise((c,u)=>{let l={kind:"user",messageId:i,originator:d,clientId:a,prompt:o,enqueuedAt:Date.now(),cancelled:!1,emitterName:e,chainStartIdx:r,resolve:c,reject:u},p=this.insertEntryAt(l,"tail");this.persistRewrite(),this.broadcastQueueAdded(l,{position:p}),this.drainQueue()})}rewriteForAgent(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(t.sessionId===this.sessionId)return{...t,sessionId:this.upstreamSessionId}}return e}async close(e={}){if(e.deleteRecord&&(this.deleteRecordIntent=!0),!this.closed)return this.closeInFlight?this.closeInFlight:(this.closing=!0,this.closeInFlight=this.doClose(e),this.closeInFlight)}async doClose(e){let t=this.turnStartedAt!==void 0;this.logger?.info(`session ${this.sessionId} closing deleteRecord=${e.deleteRecord??!1} by=${e.by??"unknown"} midTurn=${t} unsolicitedTurn=${this.unsolicitedTurn!==void 0} queued=${this.promptQueue.length} awaitingPermission=${this.hasPermissionFlag}`),t&&this.logger?.warn(`session ${this.sessionId} closed mid-turn by=${e.by??"unknown"}; the in-flight turn will not settle and the agent is being killed`),this.cancelIdleTimer(),this.cancelOrphanTimer(),clearTimeout(this.upstreamPollTimer);for(let n of this.pendingClaims.values())clearTimeout(n.timer);this.pendingClaims.clear(),await this.requestAgentSessionClose(),await this.agent.kill().catch(()=>{}),this.markClosed({deleteRecord:e.deleteRecord??!1})}async requestAgentSessionClose(){if(this.agentCapabilities?.sessionCapabilities?.close===void 0)return;let e,t=new Promise(r=>{e=setTimeout(r,Pg)}),n=this.agent.connection.request("session/close",{sessionId:this.upstreamSessionId}).then(()=>{},()=>{});await Promise.race([n,t]),clearTimeout(e)}onClose(e){return this.closeHandlers.push(e),()=>{let t=this.closeHandlers.indexOf(e);t>=0&&this.closeHandlers.splice(t,1)}}onTitleChange(e){this.titleHandlers.push(e)}retitle(e){return this.runTitleCommand(e)}retitleFromAgent(){return this.runTitleCommand("")}setTitle(e){let t=e.trim();if(!(!t||t===this.title)){this._titleSeedPending=!1,this.title=t,this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",title:t,updatedAt:new Date().toISOString()}});for(let n of this.titleHandlers)try{n(t)}catch{}}}maybeSeedTitleFromPrompt(e){if(!this._titleSeedPending||at((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let r=It((e??{}).prompt),o=bo(r,200);!o||o.startsWith("/")||(this._titleSeedPending=!1,this.setTitle(o))}maybeApplyAgentModel(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="_hydra_current_model_update")return!1;let r=Cn(n.availableModels);r.length>0&&this.setAgentAdvertisedModels(r);let o=typeof n.currentModel=="string"?n.currentModel:typeof n.model=="string"?n.model:void 0;if(o===void 0)return!0;let i=o.trim();if(!i||i===this.currentModel)return!0;this.logger?.info(`live current_model_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(i)}`),this.currentModel=i;for(let a of this.modelHandlers)try{a(i)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentConfigOption(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="config_option_update")return!1;let r=n.configOptions;if(!Array.isArray(r))return!0;for(let i of r)this.applyOneConfigOptionEntry(i);let o=new Set(r.filter(i=>!!i&&typeof i=="object").map(i=>typeof i.id=="string"?i.id.trim():void 0).filter(i=>!!i&&i!=="model"&&i!=="mode"&&i!=="agent"));return this.agentAdvertisedConfigOptions=this.agentAdvertisedConfigOptions.filter(i=>o.has(i.id)),this.fireConfigOptionsHandlers(),!0}applyAgentConfigOptionResponse(e,t){let n=e?.configOptions;if(!Array.isArray(n))return!1;let r=JSON.stringify(this.agentAdvertisedConfigOptions);for(let o of n){let i=o?.id;i==="model"||i==="mode"||i==="agent"||this.applyOneConfigOptionEntry(o)}if(Lg(n,t)){let o=new Set(n.filter(i=>!!i&&typeof i=="object").map(i=>typeof i.id=="string"?i.id.trim():void 0).filter(i=>!!i));this.agentAdvertisedConfigOptions=this.agentAdvertisedConfigOptions.filter(i=>o.has(i.id))}return JSON.stringify(this.agentAdvertisedConfigOptions)!==r}applyOneConfigOptionEntry(e){if(!e||typeof e!="object")return;let t=e;if(t.id==="model"){let k=Cn(t.options);k.length>0&&this.setAgentAdvertisedModels(k);let m=t.currentValue;if(typeof m=="string"){let g=m.trim();g&&g!==this.currentModel&&(this.logger?.info(`live config_option_update(model): sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(g)}`),this.applyModelChange(g))}return}if(t.id==="mode"){let k=bs(t.options);k.length>0&&this.setAgentAdvertisedModes(k);let m=t.currentValue;if(typeof m=="string"){let g=m.trim();g&&g!==this.currentMode&&(this.logger?.info(`live config_option_update(mode): sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(g)}`),this.applyModeChange(g))}return}if(typeof t.id!="string"||!t.id.trim())return;let n=t.id.trim(),r=vo(t.options);if(r.length===0)return;let o=t.name,i=typeof o=="string"&&o.trim()?o.trim():n,a=t.category,d=typeof a=="string"&&a.trim()?a.trim():"other",c=t.description,u=typeof c=="string"&&c.trim()?c.trim():void 0,l=t.currentValue,p=typeof l=="string"&&l.trim()?l.trim():r[0].value,f={id:n,name:i,category:d,type:"select",currentValue:p,options:r,...u?{description:u}:{}},h=this.agentAdvertisedConfigOptions.findIndex(k=>k.id===n);h>=0?this.agentAdvertisedConfigOptions[h]=f:this.agentAdvertisedConfigOptions.push(f)}maybeApplyAgentMode(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="current_mode_update")return!1;let r=typeof n.currentModeId=="string"?n.currentModeId:typeof n.currentMode=="string"?n.currentMode:typeof n.mode=="string"?n.mode:void 0;if(r===void 0)return!0;let o=r.trim();if(!o||o===this.currentMode)return!0;this.logger?.info(`current_mode_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(o)}`),this.currentMode=o;for(let i of this.modeHandlers)try{i(o)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentUsage(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="usage_update")return!1;let r={...this._currentUsage??{}},o=!1;if(typeof n.used=="number"&&!this.swapInFlight&&ld(r.used,n.used)&&this.armRecallFromSelfCompaction(),typeof n.used=="number"&&r.used!==n.used&&(r.used=n.used,o=!0),typeof n.size=="number"&&r.size!==n.size&&(r.size=n.size,o=!0),n.cost&&typeof n.cost=="object"){let a=n.cost;typeof a.amount=="number"&&(this.reconcileCostLedger(a.amount)&&(o=!0),r.costAmount!==a.amount&&(r.costAmount=a.amount,o=!0)),typeof a.currency=="string"&&r.costCurrency!==a.currency&&(r.costCurrency=a.currency,o=!0)}if(!o)return!0;this._currentUsage=r;let i=this.persistableUsage??r;for(let a of this.usageHandlers)try{a(i)}catch{}return!0}armCostLedgerProbe(){let e=this._currentUsage?.costAmount;typeof e=="number"&&e>0&&(this.costLedgerProbe=e)}reconcileCostLedger(e){let t=this.costLedgerProbe;return t===void 0||(this.costLedgerProbe=void 0,e>=t-1e-6)?!1:(this.cumulativeCost+=t,!0)}notifyAgentChange(e,t,n,r){let o=this.retiringGenerationCost;this.retiringGenerationCost=void 0;let i=this.retiringGenerationUsed;this.retiringGenerationUsed=void 0;let a=this.rotationLifetimeCost;this.rotationLifetimeCost=void 0;for(let d of this.agentChangeHandlers)try{d({agentId:this.agentId,upstreamSessionId:this.upstreamSessionId,...o!==void 0?{retiredCost:o}:{},...a!==void 0?{lifetimeCost:a}:{},...i!==void 0?{retiredUsed:i}:{},...r!==void 0?{startedUsed:r}:{},...t!==void 0?{reason:t}:{},...n!==void 0?{runId:n}:{}})}catch(c){this.logger?.warn(`${e}: agentChange handler failed: ${c.message}`)}}accumulateAndResetCost(){let e=this._currentUsage?.costAmount;e&&(this.cumulativeCost+=e,this.retiringGenerationCost=e);let t=this._currentUsage?.used;typeof t=="number"&&t>0&&(this.retiringGenerationUsed=t),this.rotationLifetimeCost=this.cumulativeCost;let n={used:0,cumulativeCost:this.cumulativeCost,...typeof this._currentUsage?.size=="number"?{size:this._currentUsage.size}:{},...this._currentUsage?.costCurrency?{costCurrency:this._currentUsage.costCurrency}:{}};this._currentUsage=n;for(let r of this.usageHandlers)try{r(n)}catch{}this.broadcastCurrentUsage()}broadcastCurrentUsage(){let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let n={};typeof e.costAmount=="number"&&(n.amount=e.costAmount),typeof e.costCurrency=="string"&&(n.currency=e.costCurrency),t.cost=n}this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:t})}injectCumulativeCost(e){if(!this.cumulativeCost||!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let n=t.update;if(n.sessionUpdate!=="usage_update"||!n.cost||typeof n.cost!="object")return e;let r=n.cost;return typeof r.amount!="number"?e:{...t,update:{...n,cost:{...r,amount:this.cumulativeCost+r.amount}}}}get totalUsage(){return this.currentUsage}setAgentAdvertisedCommands(e){if(tm(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(nm(this.agentAdvertisedModes,e)){this.broadcastAvailableModes();return}this.agentAdvertisedModes=e;for(let t of this.agentModesHandlers)try{t(e)}catch{}this.broadcastAvailableModes()}setAgentAdvertisedModels(e){if(this.logger?.info(`setAgentAdvertisedModels: sessionId=${this.sessionId} currentModel=${JSON.stringify(this.currentModel)} newList=[${e.map(t=>t.modelId).join(",")}]`),sm(this.agentAdvertisedModels,e)){this.broadcastAvailableModels();return}this.agentAdvertisedModels=e;for(let t of this.agentModelsHandlers)try{t(e)}catch{}this.broadcastAvailableModels()}onAgentCommandsChange(e){this.agentCommandsHandlers.push(e)}onAgentModesChange(e){this.agentModesHandlers.push(e)}onAgentModelsChange(e){this.agentModelsHandlers.push(e)}onConfigOptionsChange(e){this.configOptionsHandlers.push(e)}extraConfigOptionValues(){return Object.fromEntries(this.agentAdvertisedConfigOptions.map(e=>[e.id,e.currentValue]))}onModelChange(e){this.modelHandlers.push(e)}onModeChange(e){this.modeHandlers.push(e)}onInteractiveChange(e){this.interactiveHandlers.push(e)}onPriorityChange(e){this.priorityHandlers.push(e)}onReadStateChange(e){this.readStateHandlers.push(e)}get unread(){return vn(this._lastTurnEndedAt,this._readAt)}setRead(e,t=Date.now()){let n=ms({lastTurnEndedAt:this._lastTurnEndedAt,readAt:this._readAt},e,t);n!==void 0&&(this._readAt=n,this.fireReadState())}noteTurnEnded(e=Date.now()){this._readAt===void 0&&(this._readAt=Math.min(this._lastTurnEndedAt??this.createdAt,e-1)),this._lastTurnEndedAt=e,this.fireReadState(),this.captureUpstreamBaseline()}hasEndUnobservableTask(){for(let e of this.armedTasks.values())if(e.endUnobservable===!0)return!0;return!1}captureUpstreamBaseline(){let e=++this.upstreamBaselineGen;if(!this.hasEndUnobservableTask()){this.upstreamBaselineMs=void 0;return}this.fetchUpstreamUpdatedAt().then(t=>{t===void 0||e!==this.upstreamBaselineGen||this.promptInFlight||this.unsolicitedTurn!==void 0||(this.upstreamBaselineMs=t,this.scheduleUpstreamPoll(e))}).catch(()=>{})}scheduleUpstreamPoll(e){clearTimeout(this.upstreamPollTimer),this.upstreamPollTimer=setTimeout(()=>{this.upstreamPollTimer=void 0,this.pollUpstream(e)},zg),this.upstreamPollTimer.unref()}async pollUpstream(e){if(!this.upstreamPollLive(e))return;let t=await this.fetchUpstreamUpdatedAt().catch(()=>{});this.upstreamPollLive(e)&&(t!==void 0&&this.applyUpstreamUpdatedAt(t),this.upstreamPollLive(e)&&this.scheduleUpstreamPoll(e))}upstreamPollLive(e){return e===this.upstreamBaselineGen&&this.upstreamBaselineMs!==void 0&&!this.closing&&!this.closed&&this.hasEndUnobservableTask()}async fetchUpstreamUpdatedAt(){let t=(await this.agent.connection.request("session/list",{cwd:this.cwd}))?.sessions?.find(r=>r.sessionId===this.upstreamSessionId),n=typeof t?.updatedAt=="string"?Date.parse(t.updatedAt):NaN;return Number.isNaN(n)?void 0:n}noteUpstreamUpdatedAt(e){let t=e===void 0?NaN:Date.parse(e);Number.isNaN(t)||this.applyUpstreamUpdatedAt(t)}applyUpstreamUpdatedAt(e){if(this.upstreamBaselineMs===void 0||e<=this.upstreamBaselineMs||this.promptInFlight||this.unsolicitedTurn!==void 0)return;let t=0;for(let[n,r]of this.armedTasks)r.endUnobservable===!0&&(this.armedTasks.delete(n),t+=1);this.upstreamBaselineMs=void 0,t>0&&(this.logger?.info(`session ${this.sessionId} cleared ${t} armed task(s): agent updated the session after its turn ended`),this.onArmedTasksChanged())}fireReadState(){let e={lastTurnEndedAt:this._lastTurnEndedAt,readAt:this._readAt};for(let t of this.readStateHandlers)try{t(e)}catch{}}setPriority(e){let t=e===void 0||e<=0?void 0:Math.floor(e);if(t!==this._priority){this._priority=t,this.updatedAt=Date.now();for(let n of this.priorityHandlers)try{n(t)}catch{}}}applyModelChange(e){let t=e.trim();if(t){this.modelChangeInFlight=!0;try{if(t!==this.currentModel){this.logger?.info(`applyModelChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(t)}`),this.currentModel=t;for(let r of this.modelHandlers)try{r(t)}catch{}}let n={sessionUpdate:"_hydra_current_model_update",currentModel:t};this.agentAdvertisedModels.length>0&&(n.availableModels=[...this.agentAdvertisedModels]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modelChangeInFlight=!1}}}applyModeChange(e){let t=e.trim();if(t){this.modeChangeInFlight=!0;try{if(t!==this.currentMode){this.logger?.info(`applyModeChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(t)}`),this.currentMode=t;for(let r of this.modeHandlers)try{r(t)}catch{}}let n={sessionUpdate:"current_mode_update",currentModeId:t};this.agentAdvertisedModes.length>0&&(n.availableModes=[...this.agentAdvertisedModes]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modeChangeInFlight=!1}}}buildConfigOptions(){let e=[];if(this.agentAdvertisedModels.length>0){let r=this.agentAdvertisedModels.map(i=>({value:i.modelId,name:i.name??i.modelId,...i.description!==void 0?{description:i.description}:{}}));this.currentModel&&!r.some(i=>i.value===this.currentModel)&&r.unshift({value:this.currentModel,name:this.currentModel});let o=this.currentModel||r[0].value;e.push({id:"model",name:"Model",category:"model",type:"select",currentValue:o,options:r})}if(this.agentAdvertisedModes.length>0){let r=this.agentAdvertisedModes.map(i=>({value:i.id,name:i.name??i.id,...i.description!==void 0?{description:i.description}:{}}));this.currentMode&&!r.some(i=>i.value===this.currentMode)&&r.unshift({value:this.currentMode,name:this.currentMode});let o=this.currentMode||r[0].value;e.push({id:"mode",name:"Session Mode",category:"mode",type:"select",currentValue:o,options:r})}let n=(this.availableAgentsFn?.()??[]).map(r=>({value:r.id,name:r.name??r.id,...r.description!==void 0?{description:r.description}:{}}));return n.some(r=>r.value===this.agentId)||n.unshift({value:this.agentId,name:this.agentId}),e.push({id:"agent",name:"Agent",category:"_hydra_agent",type:"select",currentValue:this.agentId,options:n}),e.push(...this.agentAdvertisedConfigOptions),e}broadcastConfigOptions(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"config_option_update",configOptions:this.buildConfigOptions()}}),this.fireConfigOptionsHandlers()}fireConfigOptionsHandlers(){for(let e of this.configOptionsHandlers)try{e(this.agentAdvertisedConfigOptions)}catch{}}mergeAgentOptionIntoEnvelope(e){if(!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let n=t.update,r=Array.isArray(n.configOptions)?[...n.configOptions]:[];if(r.some(a=>a&&typeof a=="object"&&a.id==="agent"))return e;let i=this.buildConfigOptions().find(a=>a.id==="agent");return i?{...t,update:{...n,configOptions:[...r,i]}}:e}onUsageChange(e){this.usageHandlers.push(e)}mergedAvailableCommands(){let e=this.daemonTopLevelCommands(),t=this.aliasableBareVerbs();for(let n of zt){if(t.get(n.verb)!=="__hydra__")continue;let r=n.argsHint?`${n.verb} ${n.argsHint}`:n.verb;e.push({name:r,description:`Alias for '/hydra ${n.verb}': ${n.description}`})}if(this.extensionCommands)for(let{name:n,command:r}of this.extensionCommands.list()){let o=r.verb?`hydra ${n} ${r.verb}`:`hydra ${n}`,a={name:r.argsHint?`${o} ${r.argsHint}`:o};r.description&&(a.description=r.description),e.push(a);let d=ro(n),c=d??n;if(d!==void 0){let u=r.verb?`hydra ${c} ${r.verb}`:`hydra ${c}`,p={name:r.argsHint?`${u} ${r.argsHint}`:u};r.description&&(p.description=r.description),e.push(p)}if(c.length>0&&t.get(c)===n){let u=r.verb?`${c} ${r.verb}`:c,p={name:r.argsHint?`${u} ${r.argsHint}`:u};r.description&&(p.description=r.description),e.push(p)}}return e.push(...this.agentAdvertisedCommands),e}daemonTopLevelCommands(){return[{name:"hydra",description:"Hydra session command (kill, restart, title, agent <agent>)"},{name:"model",description:"Switch model; omit arg to list available models"},{name:"mode",description:"Switch mode; omit arg to list available modes"},{name:"sessions",description:"List all sessions"},{name:"help",description:"Show available commands"}]}aliasableBareVerbs(){let e=new Set,t=i=>i.split(/\s+/)[0]??"";for(let i of this.daemonTopLevelCommands()){let a=t(i.name);a&&e.add(a)}for(let i of this.agentAdvertisedCommands){let a=t(i.name),d=a.startsWith("/")?a.slice(1):a;d&&e.add(d)}let n=new Map;for(let i of zt)e.has(i.verb)||n.set(i.verb,"__hydra__");if(!this.extensionCommands)return n;let r=new Map,o=new Set;for(let{name:i}of this.extensionCommands.list()){if(o.has(i))continue;o.add(i);let a=ro(i)??i;if(!a||e.has(a)||n.has(a))continue;let d=r.get(a);d===void 0?r.set(a,i):d!==i&&r.set(a,"__conflict__")}for(let[i,a]of r)a!=="__conflict__"&&n.set(i,a);return n}agentOnlyAdvertisedCommands(){return[...this.agentAdvertisedCommands]}agentKnowsSlashCommand(e){let t=r=>r.startsWith("/")?r.slice(1):r,n=t(e);if(!n)return!1;for(let r of this.agentAdvertisedCommands)if(t(r.name.split(/\s+/)[0]??"")===n)return!0;return!1}availableModes(){return[...this.agentAdvertisedModes]}availableModels(){return[...this.agentAdvertisedModels]}maybeApplyAgentSessionInfo(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="session_info_update"||typeof n.title!="string"||this._upstreamRespawned)return;let r=n.title.trim();if(!(!r||r===this.title)){this.title=r,this._firstPromptSeeded=!0,this._titleSeedPending=!1;for(let o of this.titleHandlers)try{o(r)}catch{}}}async handleSlashCommand(e,t){let r=e.slice(6).trim().match(/^(\S+)(?:\s+([\s\S]*))?$/),o=r?.[1]??"",i=(r?.[2]??"").trim();if(o==="")return{stopReason:"end_turn"};let a=t!==void 0;if(zt.some(l=>l.verb===o))switch(o){case"title":return a?this.runTitleCommandInline(i):this.runTitleCommand(i);case"agent":return this.runAgentCommandInline(i);case"config":return this.handleConfigCommand(`/config ${i}`);case"kill":return this.runKillCommand();case"workspace":return this.runWorkspaceCommand(i);case"restart":return a?this.runRestartCommandInline():this.runRestartCommand();case"clear":return this.runClearCommand();case"compact":return a?this.runCompactCommandInline(i):this.runCompactCommand(i);case"uncompact":return a?this.runUncompactCommandInline():this.runUncompactCommand();case"fork":return a?this.runForkCommandInline(i,t):this.runForkCommand(i);default:{let l=new Error(`no dispatcher for /hydra verb ${o}`);throw l.code=x.InternalError,l}}if(this.extensionCommands?.has(o))return a?this.runExtensionCommandInline(o,i,t):this.runExtensionCommand(o,i);let d=od(o).find(l=>this.extensionCommands?.has(l));if(d!==void 0)return a?this.runExtensionCommandInline(d,i,t):this.runExtensionCommand(d,i);let c=zt.map(l=>l.verb);if(this.extensionCommands){let l=new Set;for(let{name:p}of this.extensionCommands.list())l.has(p)||(c.push(p),l.add(p))}let u=new Error(`unknown /hydra verb: ${o} (known: ${c.join(", ")})`);throw u.code=x.InvalidParams,u}runExtensionCommand(e,t){return this.enqueuePrompt(`extension:${e}`,()=>this.runExtensionCommandInline(e,t,void 0))}async runExtensionCommandInline(e,t,n){let r=this.extensionCommands?.get(e);if(!r)return this.emitExtensionReply(`extension "${e}" is no longer connected`);let o=t.match(/^(\S+)(?:\s+([\s\S]*))?$/),i=o?.[1]??"",a=(o?.[2]??"").trim();if(!r.commands.some(h=>h.verb===i)){let h=r.commands.map(k=>k.verb).join(", ");return this.emitExtensionReply(`/hydra ${e}${i?` ${i}`:""}: unknown verb (known: ${h||"(none)"})`)}let d={sessionId:this.sessionId,verb:i,args:a};n!==void 0&&(d.messageId=n);let c=()=>{},u=new Promise(h=>{c=h});n!==void 0&&this.inFlightExtensionDispatches.set(n,{extensionName:e,connection:r.connection,cancel:h=>c({stopReason:"cancelled",reason:h})});let l,p=!1;try{let h=r.connection.request("hydra-acp/commands/invoke",d),k=await Promise.race([h,u]);if(k&&typeof k=="object"&&k.stopReason==="cancelled"&&"reason"in k)return p=!0,this.logger?.info(`extension ${e} ${i} cancelled (cancelExtensionDispatch); abandoning in-flight commands/invoke`),{stopReason:"cancelled"};l=k}catch(h){return this.emitExtensionReply(`${e} ${i}: ${h.message}`)}finally{n!==void 0&&!p&&this.inFlightExtensionDispatches.delete(n)}let f=l&&typeof l=="object"&&typeof l.text=="string"?l.text:"";return f.length>0?this.emitExtensionReply(f):{stopReason:"end_turn"}}cancelExtensionDispatch(e,t){let n=this.inFlightExtensionDispatches.get(e);if(!n)return!1;this.inFlightExtensionDispatches.delete(e);try{n.connection.notify("hydra-acp/commands/cancel",{sessionId:this.sessionId,messageId:e,reason:t})}catch(r){this.logger?.warn(`notify commands/cancel to ${n.extensionName} failed: ${r.message}`)}return n.cancel(t),!0}emitExtensionReply(e){return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
60
+ `),this.workspacePreambleSent=!0}return r}async prompt(e,t,n,r){let o=this.clients.get(e);if(!o)throw fe(new Error("client not attached"),R.SessionNotFound);if(this.closing)throw fe(new Error("session is closing; new prompts cannot be accepted"),R.SessionClosing);let i=Ge();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(dt((t??{})._meta).ancillary===!0)&&this._interactive!==!0){this._interactive=!0,this.cancelOrphanTimer();for(let d of this.interactiveHandlers)try{d(!0)}catch{}}return this.enqueueUserPrompt(o,t,i,n,r)}broadcastPromptReceived(e){this.closeUnsolicitedTurn("superseded",`prompt:${e.messageId}`);let t={clientId:e.originator.clientId};e.originator.name&&(t.name=e.originator.name),e.originator.version&&(t.version=e.originator.version),e.originator.fromSession&&(t.fromSession=e.originator.fromSession),e.originator.fromSessionTitle&&(t.fromSessionTitle=e.originator.fromSessionTitle),e.originator.fromLabel&&(t.fromLabel=e.originator.fromLabel),e.originator.depth!==void 0&&(t.depth=e.originator.depth),this.promptStartedAt=Date.now(),this.turnRanTool=!1,this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"prompt_received",messageId:e.messageId,prompt:e.prompt,sentBy:t}},e.clientId);let n=At(e.prompt);n.length>0&&this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"user_message_chunk",content:{type:"text",text:n},_meta:{"hydra-acp":{compatFor:"prompt_received"}}}},e.clientId)}recordCurrentUsageSnapshot(){if(this.historyStore===void 0)return;let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let r={};typeof e.costAmount=="number"&&(r.amount=e.costAmount),typeof e.costCurrency=="string"&&(r.currency=e.costCurrency),t.cost=r}if(Object.keys(t).length<=1)return;t._meta={"hydra-acp":{upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}};let n={sessionId:this.sessionId,update:t};this.historyStore.append(this.sessionId,{method:"session/update",params:n,recordedAt:Date.now()}).catch(()=>{})}originatorNeedsTurnComplete(e){return e.wasAmend===!0||e.wasSteer===!0}broadcastTurnComplete(e,t,n,r,o){let i=t&&typeof t=="object"&&"stopReason"in t&&typeof t.stopReason=="string"?t.stopReason:void 0,a={sessionUpdate:"turn_complete",messageId:Ge()};i!==void 0&&(a.stopReason=i),o!==void 0&&(a.errorMessage=o);let d=dt(t?._meta).salvaged;d!==void 0&&(a._meta={[le]:{salvaged:d}}),this.supersededAutonomousTurn=void 0;let c=this.amendInProgress;if(c&&n!==void 0&&c.cancelledMessageId===n&&(a._meta={[le]:{...d!==void 0?{salvaged:d}:{},amended:{cancelledMessageId:c.cancelledMessageId,newMessageId:c.newMessageId}}}),this.promptStartedAt=void 0,this.noteTurnEnded(),this.sawTurnComplete=!0,this.scheduleWorkspaceSnapshotHook?.(),n!==void 0&&i!==void 0){this.recordTerminal(n,i);let u=this.pendingTurnNotifiers.get(n);u&&(this.pendingTurnNotifiers.delete(n),ao(u,{sessionId:this.sessionId,messageId:u.originalMessageId,stopReason:i,deliveredAt:Date.now(),...n!==u.originalMessageId?{amendedTo:n}:{}}))}i==="cancelled"||i==="error"||i==="refusal"?this.closeOpenToolCalls(i):this.armOpenToolCalls(),this.recordCurrentUsageSnapshot(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:a},r?void 0:e),c&&n!==void 0&&c.cancelledMessageId===n&&this.broadcastPromptAmended(c)}noteAgentActivity(e){if(!(this.closing||this.closed)){if(Lg(e)||this.steerCausedTurnTerminal(e)){if(this.unsolicitedTurn!==void 0){this.closeUnsolicitedTurn("completed");return}this.salvageSupersededTerminal();return}this.pendingSteerDetach!==void 0&&this.currentEntry?.messageId===this.pendingSteerDetach.messageId&&Td(e)&&(this.pendingSteerDetach=void 0),!Rn("session/update",e)&&(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||Ug(e)||this.openUnsolicitedTurn()))}}steerCausedTurnTerminal(e){return this.unsolicitedTurn?.steerCaused!==!0?!1:Td(e)}noteBackgroundTaskArming(e){let t=e?.update;if(!t||typeof t!="object")return;let n=typeof t.toolCallId=="string"?t.toolCallId:void 0;if(n===void 0)return;let r=t.rawInput,o=nm(t._meta);if(this.rememberToolLabel(n,t,r,o),this.noteBackgroundTaskStopped(t,r,o),this.backgroundTaskTracking===!1)return;let i=this.backgroundTaskTracking===!0,a=i?tm(t.rawOutput):void 0,d=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:a??em(t.rawOutput),c=a!==void 0||i&&r?.background===!0;if(!(d!==void 0||c||r!==void 0&&r.run_in_background===!0))return;let l=this.toolLabels.get(n)?.label??"background task";this.lastBackgroundTask={toolCallId:n,label:l};let p=Date.now(),f=this.armedTasks.get(n),h=d??f?.taskId,k=Zg(t.title,o,r)||f?.repeating===!0;this.armedTasks.set(n,{label:l,...h!==void 0?{taskId:h}:{},repeating:k,armedAt:f?.armedAt??p,...c||f?.endUnobservable===!0?{endUnobservable:!0}:{}}),this.onArmedTasksChanged()}applyBackgroundTaskLevel(e){if(this.backgroundTaskTracking===!1)return;let t=e?.message;if(!t||t.subtype!=="background_tasks_changed")return;let n=t.tasks;if(!Array.isArray(n))return;let r=Date.now(),o=new Map;for(let a of n){let d=a,c=typeof d?.task_id=="string"?d.task_id:void 0;c!==void 0&&o.set(c,{taskType:typeof d?.task_type=="string"?d.task_type:"unknown",description:typeof d?.description=="string"?d.description:"",firstSeen:this.liveBackgroundTasks.get(c)?.firstSeen??r})}let i=[...this.liveBackgroundTasks.keys()].filter(a=>!o.has(a));this.liveBackgroundTasks=o,this.sawBackgroundTaskLevel=!0,this.logger?.info(`session ${this.sessionId} background level: ${o.size} live`+(i.length>0?` (ended: ${i.join(", ")})`:"")),this.onArmedTasksChanged()}get armedBackgroundTasks(){return this.sawBackgroundTaskLevel?[...this.liveBackgroundTasks.entries()].map(([e,t])=>({taskId:e,label:t.description||t.taskType,taskType:t.taskType,since:t.firstSeen})):[...this.armedTasks.entries()].map(([e,t])=>({toolCallId:e,label:t.label,...t.taskId!==void 0?{taskId:t.taskId}:{},since:t.armedAt,...t.endUnobservable===!0?{endUnobservable:!0}:{}}))}pendingOneShotBackgroundTasks(){return this.sawBackgroundTaskLevel?[...this.liveBackgroundTasks.values()].filter(e=>zg.has(e.taskType)).map(e=>e.description||e.taskType):[...this.armedTasks.values()].filter(e=>!e.repeating&&e.endUnobservable!==!0).map(e=>e.label)}get armedSince(){let e;if(this.sawBackgroundTaskLevel){for(let t of this.liveBackgroundTasks.values())(e===void 0||t.firstSeen<e)&&(e=t.firstSeen);return e}for(let t of this.armedTasks.values())(e===void 0||t.armedAt<e)&&(e=t.armedAt);return e}onArmedTasksChanged(){let e=this.armedBackgroundTasks,t=e.length,n=this.armedSince,r=e.map(o=>o.taskId??o.toolCallId??o.label).sort().join("\0");r===this.lastArmedBroadcast?.key&&n===this.lastArmedBroadcast?.since||this.closed||(this.lastArmedBroadcast={key:r,since:n},this.broadcastQueueNotification("hydra-acp/session/armed_tasks_updated",{sessionId:this.sessionId,count:t,...n!==void 0?{since:n}:{},tasks:e}),this.dispatchIdle())}async retireAgent(e,t){return await e.kill().catch(()=>{}),this.resetBackgroundTaskLevel(),this.discardArmedTasks(t)}resetBackgroundTaskLevel(){this.liveBackgroundTasks.clear(),this.sawBackgroundTaskLevel=!1}discardArmedTasks(e){if(this.armedTasks.size===0)return[];let t=[...this.armedTasks.values()].map(n=>n.label);for(let[n,r]of this.armedTasks)r.openToolCall===!0&&this.openToolCalls.delete(n);return this.armedTasks.clear(),this.upstreamBaselineMs=void 0,this.logger?.info(`session ${this.sessionId} discarded ${t.length} armed task(s) on ${e}: ${t.join(", ")}`),this.onArmedTasksChanged(),t}noteBackgroundTaskStopped(e,t,n){if(!(n?.toolName==="TaskStop"||e.title==="TaskStop"))return;let o=t?.task_id;if(typeof o!="string"||o.length===0)return;let i=!1;for(let[a,d]of this.armedTasks)d.taskId===o&&(this.armedTasks.delete(a),i=!0);i&&this.onArmedTasksChanged()}rememberToolLabel(e,t,n,r){let o=n!==void 0&&typeof n.description=="string"&&n.description?n.description:void 0;if(o!==void 0)this.toolLabels.set(e,{label:o.slice(0,ko),fromDescription:!0});else if(this.toolLabels.get(e)?.fromDescription!==!0){let i=typeof t.title=="string"&&t.title?t.title:typeof r?.toolName=="string"&&r.toolName?r.toolName:void 0;i!==void 0&&this.toolLabels.set(e,{label:i.slice(0,ko),fromDescription:!1})}for(;this.toolLabels.size>qg;){let i=this.toolLabels.keys().next().value;if(i===void 0)break;this.toolLabels.delete(i)}}openUnsolicitedTurn(){let e=Date.now();if(this.lastUnsolicitedCancelAt!==0&&e-this.lastUnsolicitedCancelAt<=s.UNSOLICITED_REOPEN_WINDOW_MS?this.cancelReopenStreak+=1:this.cancelReopenStreak=0,this.lastUnsolicitedCancelAt=0,this.cancelReopenStreak>=s.UNSOLICITED_REOPEN_LIMIT){this.escalateUnresponsiveCancel();return}let t=this.lastBackgroundTask,n=!1;for(let[i,a]of this.armedTasks)a.repeating||a.openToolCall===!0||(this.armedTasks.delete(i),n=!0);n&&this.onArmedTasksChanged();let r={messageId:Ge(),startedAt:e,cause:t,steerCaused:this.pendingSteerDetach!==void 0};this.pendingSteerDetach=void 0,this.unsolicitedTurn=r,this.promptStartedAt=e,this.logger?.info(`session ${this.sessionId} agent resumed with no prompt in flight`+(t?` (after ${t.label})`:""));let o={unsolicited:!0};t&&(o.cause=t),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"_hydra_turn_started",messageId:r.messageId,_meta:{"hydra-acp":o}}})}async holdForUnsolicitedTurn(e){if(this.unsolicitedTurn===void 0){this.logger?.info(`session ${this.sessionId} queue hold skipped for ${e.messageId} (no unsolicited turn open)`);return}let t=Date.now(),n=this.unsolicitedTurn.cause;this.logger?.info(`session ${this.sessionId} holding ${e.messageId} behind unsolicited turn ${this.unsolicitedTurn.messageId}`+(n?` cause=${JSON.stringify(n.label)}`:"")),this.broadcastQueueNotification("hydra-acp/prompt_queue/held",{sessionId:this.sessionId,messageId:e.messageId,reason:"agent_resumed",...n?{cause:n}:{}});let r="turn_ended";for(;;){if(this.closing||this.closed){r="closing";break}if(e.cancelled){r="cancelled";break}if(this.unsolicitedTurn===void 0){r="turn_ended";break}await new Promise(i=>{let a=setTimeout(i,Jg);typeof a.unref=="function"&&a.unref()})}let o=Date.now()-t;this.logger?.info(`session ${this.sessionId} released ${e.messageId} reason=${r} heldMs=${o}`),this.broadcastQueueNotification("hydra-acp/prompt_queue/released",{sessionId:this.sessionId,messageId:e.messageId,reason:r,heldMs:o})}closeUnsolicitedTurn(e,t){let n=this.unsolicitedTurn;if(n===void 0)return;let r=Date.now()-n.startedAt;this.unsolicitedTurn=void 0,this.promptStartedAt=void 0,this.noteTurnEnded(),e==="cancelled"?this.lastUnsolicitedCancelAt=Date.now():(this.lastUnsolicitedCancelAt=0,this.cancelReopenStreak=0),this.logger?.info(`session ${this.sessionId} unsolicited turn ${n.messageId} closed reason=${e} durationMs=${r}`+(t?` by=${t}`:"")+(n.cause?` cause=${JSON.stringify(n.cause.label)}`:"")),e==="superseded"&&(this.supersededAutonomousTurn={turnMessageId:n.messageId,cause:n.cause,supersededAt:Date.now()}),this.recordCurrentUsageSnapshot(),!this.closed&&(e==="cancelled"?this.closeOpenToolCalls("cancelled"):e==="completed"&&this.armOpenToolCalls(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"_hydra_turn_ended",messageId:Ge(),startedMessageId:n.messageId,durationMs:r,_meta:{"hydra-acp":{unsolicited:!0,reason:e}}}}))}salvageSupersededTerminal(){let e=this.supersededAutonomousTurn;if(e===void 0)return;this.supersededAutonomousTurn=void 0;let t=this.autonomousSalvage;t!==void 0&&(this.autonomousSalvage=void 0,this.logger?.warn(`session ${this.sessionId} salvaged session/prompt from autonomous terminal (superseded turn ${e.turnMessageId}, ${Date.now()-e.supersededAt}ms earlier)`+(e.cause?` cause=${JSON.stringify(e.cause.label)}`:"")),t({stopReason:"end_turn",_meta:{[le]:{salvaged:{reason:"autonomous_terminal",supersededMessageId:e.turnMessageId}}}}))}async awaitPromptResponse(e){if(this.supersededAutonomousTurn===void 0)return e;try{return await new Promise((t,n)=>{this.autonomousSalvage=t,e.then(t,n)})}finally{this.autonomousSalvage=void 0}}recordTerminal(e,t){for(this.recentlyTerminal.set(e,{stopReason:t,terminatedAt:Date.now()});this.recentlyTerminal.size>Hg;){let n=this.recentlyTerminal.keys().next().value;if(n===void 0)break;this.recentlyTerminal.delete(n)}}registerTurnNotify(e,t,n){let r=this.recentlyTerminal.get(e);if(r)return{alreadyTerminal:!0,stopReason:r.stopReason};for(this.pendingTurnNotifiers.set(e,{callbackUrl:t,secret:n,registeredAt:Date.now(),originalMessageId:e});this.pendingTurnNotifiers.size>Ng;){let o=this.pendingTurnNotifiers.keys().next().value;if(o===void 0)break;this.pendingTurnNotifiers.delete(o)}return{alreadyTerminal:!1}}broadcastPromptAmended(e){let t=this.findUserEntry(e.newMessageId);if(!t)return;let n={sessionId:this.sessionId,cancelledMessageId:e.cancelledMessageId,newMessageId:e.newMessageId,prompt:t.prompt,originator:t.originator,amendedAt:Date.now()};this.broadcastQueueNotification("hydra-acp/prompt/amended",n)}findUserEntry(e){if(this.currentEntry?.messageId===e&&this.currentEntry.kind==="user")return this.currentEntry;let t=this.promptQueue.find(n=>n.messageId===e&&n.kind==="user");return t?.kind==="user"?t:void 0}visibleQueueDepth(){let e=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled?1:0;for(let t of this.promptQueue)t.kind==="user"&&!t.cancelled&&(e+=1);return e}broadcastQueueAdded(e,t){let n=this.visibleQueueDepth(),r=t?.position??Math.max(0,n-1),o={sessionId:this.sessionId,messageId:e.messageId,originator:e.originator,prompt:e.prompt,position:r,queueDepth:n,enqueuedAt:e.enqueuedAt};t?.amending!==void 0&&(o._meta={"hydra-acp":{amending:t.amending}}),this.broadcastQueueNotification("hydra-acp/prompt_queue/added",o)}broadcastQueueUpdated(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/updated",{sessionId:this.sessionId,messageId:e,prompt:t})}broadcastQueueRemoved(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/removed",{sessionId:this.sessionId,messageId:e,reason:t})}broadcastQueueNotification(e,t){for(let n of this.clients.values())n.connection.notify(e,t).catch(()=>{})}queueSnapshot(){let e=[],t=0;this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled&&e.push({messageId:this.currentEntry.messageId,originator:this.currentEntry.originator,prompt:this.currentEntry.prompt,position:t++,enqueuedAt:this.currentEntry.enqueuedAt});for(let n of this.promptQueue)n.kind!=="user"||n.cancelled||e.push({messageId:n.messageId,originator:n.originator,prompt:n.prompt,position:t++,enqueuedAt:n.enqueuedAt});return e}async flushPersistWrites(){await this.queueWriteChain.catch(()=>{})}replayPersistedQueue(e){for(let t of e){let n={clientId:`hydra-resurrected_${t.messageId}`};t.originator.clientInfo.name!==void 0&&(n.name=t.originator.clientInfo.name),t.originator.clientInfo.version!==void 0&&(n.version=t.originator.clientInfo.version);let r={kind:"user",messageId:t.messageId,originator:n,clientId:n.clientId,prompt:t.prompt,enqueuedAt:t.enqueuedAt,cancelled:!1,resolve:()=>{},reject:()=>{}};this.promptQueue.push(r),this.broadcastQueueAdded(r)}this.drainQueue()}cancelQueuedPrompt(e){if(this.currentEntry?.messageId===e)return{cancelled:!1,reason:"already_running"};let t=this.promptQueue.findIndex(r=>r.messageId===e);if(t<0)return{cancelled:!1,reason:"not_found"};let n=this.promptQueue[t];return n.cancelled=!0,this.promptQueue.splice(t,1),n.kind==="user"&&(this.broadcastQueueRemoved(e,"cancelled"),this.persistRewrite()),this.amendInProgress?.newMessageId===e&&(this.amendInProgress=void 0),n.resolve({stopReason:"cancelled"}),{cancelled:!0,reason:"ok"}}updateQueuedPrompt(e,t){if(this.currentEntry?.messageId===e)return{updated:!1,reason:"already_running"};let n=this.promptQueue.find(r=>r.messageId===e);return!n||n.kind!=="user"?{updated:!1,reason:"not_found"}:(n.prompt=t,this.broadcastQueueUpdated(e,t),this.persistRewrite(),{updated:!0,reason:"ok"})}amendPrompt(e,t){let n=this.clients.get(e);if(!n)throw fe(new Error("client not attached"),R.SessionNotFound);let{targetMessageId:r,prompt:o,replaceQueue:i,onTargetCompleted:a}=t;if(this.currentEntry?.messageId===r&&this.currentEntry.kind==="user"&&!this.currentEntry.cancelled&&this.amendInProgress===void 0)return this.amendOnHead(n,o,r,i);let d=this.promptQueue.find(u=>u.messageId===r&&u.kind==="user");if(d&&d.kind==="user"&&!d.cancelled)return d.prompt=o,this.broadcastQueueUpdated(r,o),this.persistRewrite(),{amended:!0,reason:"ok",messageId:r};let c=this.recentlyTerminal.get(r);return c?c.stopReason==="cancelled"?{amended:!1,reason:"target_cancelled"}:a==="send_anyway"?{amended:!1,reason:"target_completed",messageId:this.enqueueAmendmentAsFollowUp(n,o)}:{amended:!1,reason:"target_completed"}:{amended:!1,reason:"target_not_found"}}amendOnHead(e,t,n,r){let o=Ge(),i={clientId:e.clientId};if(e.clientInfo?.name&&(i.name=e.clientInfo.name),e.clientInfo?.version&&(i.version=e.clientInfo.version),r){let c=[];for(let u of this.promptQueue){if(u.kind==="user"&&!u.cancelled){u.cancelled=!0,this.broadcastQueueRemoved(u.messageId,"cancelled"),u.resolve({stopReason:"cancelled"});continue}c.push(u)}this.promptQueue=c}let a={kind:"user",messageId:o,originator:i,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,wasAmend:!0,resolve:()=>{},reject:()=>{}};this.promptQueue.unshift(a),this.persistRewrite(),this.broadcastQueueAdded(a,{amending:n,position:1}),this.amendInProgress={cancelledMessageId:n,newMessageId:o};let d=this.pendingTurnNotifiers.get(n);return d&&(this.pendingTurnNotifiers.delete(n),this.pendingTurnNotifiers.set(o,d)),this.cancelExtensionDispatch(n,"amended"),this.agent.connection.notify("session/cancel",{sessionId:this.upstreamSessionId}).catch(()=>{}),{amended:!0,reason:"ok",messageId:o}}async steer(e,t){let n=this.clients.get(e);if(!n)throw fe(new Error("client not attached"),R.SessionNotFound);let r=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled;if(r&&this.agent.steeringSupported){this.pendingSteerDetach={messageId:this.currentEntry.messageId};let o;try{o=await this.forwardRequest("_session/steering",t)}catch(d){throw this.pendingSteerDetach=void 0,d}let i=o?.outcome,a=i==="injected"||i==="startedNewTurn"||i==="promptRequired"||i==="failed"?o:{outcome:"failed"};return a.outcome!=="startedNewTurn"&&(this.pendingSteerDetach=void 0),a.outcome==="injected"&&this.recordSteerAsUserMessageChunk(t.prompt,e),a.outcome==="startedNewTurn"?{...a,detached:!0}:a}return r?(this.amendOnHead(n,t.prompt,this.currentEntry.messageId,!1),{outcome:"startedNewTurn"}):t._meta?.steering?.idleBehavior==="promptRequired"?{outcome:"promptRequired",reason:"noRunningTurn"}:(this.prompt(e,{sessionId:t.sessionId,prompt:t.prompt},void 0,{steerOriginated:!0}).catch(o=>{this.logger?.warn(`steer-originated prompt failed to enqueue: ${o.message}`)}),{outcome:"startedNewTurn"})}recordSteerAsUserMessageChunk(e,t){let n=At(e);n.length!==0&&this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"user_message_chunk",content:{type:"text",text:n},_meta:{"hydra-acp":{steered:!0}}}},t)}enqueueAmendmentAsFollowUp(e,t){let n=Ge(),r={clientId:e.clientId};e.clientInfo?.name&&(r.name=e.clientInfo.name),e.clientInfo?.version&&(r.version=e.clientInfo.version);let o={kind:"user",messageId:n,originator:r,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,resolve:()=>{},reject:()=>{}};return this.promptQueue.push(o),this.persistRewrite(),this.broadcastQueueAdded(o),this.drainQueue(),n}async cancel(e){if(!this.clients.get(e))throw fe(new Error("client not attached"),R.SessionNotFound);this.logger?.info(`session ${this.sessionId} session/cancel from ${e} promptInFlight=${this.promptInFlight} agentTurnInFlight=${this.agentTurnInFlight} unsolicitedTurn=${this.unsolicitedTurn!==void 0} queued=${this.promptQueue.length}`),this.lastCancelAt=Date.now(),this.currentEntry?.kind==="user"&&this.currentEntry.messageId!==void 0&&this.cancelExtensionDispatch(this.currentEntry.messageId,"cancelled"),this.closeUnsolicitedTurn("cancelled"),this.agentTurnInFlight||this.closeOpenToolCalls("cancelled"),await this.forwardRequest("session/cancel",{sessionId:this.sessionId},new Set,0,"notification")}addTransformer(e){let t=this.transformChain.findIndex(n=>n.name===e.name);t>=0?this.transformChain[t]=e:this.transformChain.push(e),e.intercepts.has("lifecycle:session.opened")&&e.connection.notify("hydra-acp/transformer/session_event",{event:"session.opened",sessionId:this.sessionId}).catch(()=>{})}async forwardRequest(e,t,n=new Set,r=0,o="request"){let i=this.rewriteForAgent(t);for(let a=r;a<this.transformChain.length;a++){let d=this.transformChain[a];if(n.has(d.name))continue;let c=`request:${e}`;if(!d.intercepts.has(c))continue;let u=`t_${wo()}`,l;try{l=await d.connection.request("hydra-acp/transformer/message",{token:u,phase:"request",method:e,direction:"client\u2192agent",sessionId:this.sessionId,envelope:i})}catch(f){this.logger?.warn(`transformer ${d.name} error on ${c}: ${f.message}`);continue}let p=l?.action??"continue";if(p==="stop")return o==="notification"?void 0:l?.payload??bo(e);if(p==="continue"){l?.payload&&typeof l.payload=="object"&&(i=l.payload),n.add(d.name);continue}if(p==="processing"){let f=a,h=i,k=new Set(n);return new Promise(m=>{let g=setTimeout(()=>{this.pendingClaims.delete(u)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:u,transformerName:d.name}),this.forwardRequest(e,h,new Set([...k,d.name]),f+1,o).then(m).catch(()=>m(o==="notification"?void 0:bo(e))))},Ss);typeof g.unref=="function"&&g.unref(),this.pendingClaims.set(u,{resolve:m,timer:g,transformerName:d.name,method:e,envelope:h,chainIdx:f,originatedBy:k,side:"request",tailKind:o})})}n.add(d.name)}if(o==="notification"){await this.agent.connection.notify(e,i);return}return this.agent.connection.request(e,i)}async forwardModelChange(e,t){let n=await lt({request:(r,o)=>this.forwardRequest(r,o),sessionId:this.sessionId,modelId:e,verb:this.modelVerb,extraParams:t,logger:this.logger});return this.modelVerb=n.verb,this.modelVerbConfirmed=!0,n.result}noteModelVerbHint(e,t){e===void 0||this.modelVerbConfirmed||e===this.modelVerb||(this.logger?.info(`model verb for agent ${this.agentId} inferred as ${e} from ${t} (was ${this.modelVerb})`),this.modelVerb=e)}resetModelVerb(e){this.modelVerb=e??ze,this.modelVerbConfirmed=!1}async runAgentRequestChain(e,t,n=new Set,r=0){let o=t,i=`request:${e}`;for(let a=r;a<this.transformChain.length;a++){let d=this.transformChain[a];if(n.has(d.name)||!d.intercepts.has(i))continue;let c=`t_${wo()}`,u;try{u=await d.connection.request("hydra-acp/transformer/message",{token:c,phase:"request",method:e,direction:"agent\u2192client",sessionId:this.sessionId,envelope:o})}catch(p){this.logger?.warn(`transformer ${d.name} error on ${i}: ${p.message}`);continue}let l=u?.action??"continue";if(l==="stop")return{shortCircuit:!0,payload:u?.payload??ym(e)};if(l==="continue"){u?.payload&&typeof u.payload=="object"&&(o=u.payload),n.add(d.name);continue}if(l==="processing"){let p=a,f=o,h=new Set(n),k=e;return new Promise(m=>{let g=setTimeout(()=>{this.pendingClaims.delete(c)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:c,transformerName:d.name}),this.runAgentRequestChain(k,f,new Set([...h,d.name]),p+1).then(m).catch(()=>m({shortCircuit:!1,envelope:f})))},Ss);typeof g.unref=="function"&&g.unref(),this.pendingClaims.set(c,{resolve:y=>m({shortCircuit:!0,payload:y}),timer:g,transformerName:d.name,method:k,envelope:f,chainIdx:p,originatedBy:h,side:"agent-request"})})}n.add(d.name)}return{shortCircuit:!1,envelope:o}}dischargeClaim(e,t){let n=this.pendingClaims.get(e);return n?(clearTimeout(n.timer),this.pendingClaims.delete(e),n.resolve(t),!0):!1}keepAliveClaim(e,t){let n=this.pendingClaims.get(e);if(!n)return!1;clearTimeout(n.timer);let r=typeof t=="number"&&t>0?Math.min(t*1.5,1800*1e3):Ss,o=setTimeout(()=>{if(this.pendingClaims.delete(e))if(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:e,transformerName:n.transformerName}),n.side==="response")this.runResponseChain(n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1).then(()=>n.resolve(void 0)).catch(()=>n.resolve(void 0));else if(n.side==="agent-request")this.runAgentRequestChain(n.method,n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1).then(n.resolve).catch(()=>n.resolve({shortCircuit:!1,envelope:n.envelope}));else{let i=n.tailKind??"request";this.forwardRequest(n.method,n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1,i).then(n.resolve).catch(()=>n.resolve(i==="notification"?void 0:bo(n.method)))}},r);return typeof o.unref=="function"&&o.unref(),n.timer=o,!0}async emitToChain(e,t,n){let r=this.transformChain.findIndex(a=>a.name===e),o=r>=0?r+1:0,i=new Set([e]);if(t==="session/update"){await this.runResponseChain(n,i,o);return}return this.forwardRequest(t,n,i,o)}async emitToQueue(e,t){let n=this.transformChain.findIndex(c=>c.name===e),r=n>=0?n+1:0,o=(t??{}).prompt??[],i=Ge(),a=`transformer:${e}`,d={clientId:a,name:e};return new Promise((c,u)=>{let l={kind:"user",messageId:i,originator:d,clientId:a,prompt:o,enqueuedAt:Date.now(),cancelled:!1,emitterName:e,chainStartIdx:r,resolve:c,reject:u},p=this.insertEntryAt(l,"tail");this.persistRewrite(),this.broadcastQueueAdded(l,{position:p}),this.drainQueue()})}rewriteForAgent(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(t.sessionId===this.sessionId)return{...t,sessionId:this.upstreamSessionId}}return e}async close(e={}){if(e.deleteRecord&&(this.deleteRecordIntent=!0),!this.closed)return this.closeInFlight?this.closeInFlight:(this.closing=!0,this.closeInFlight=this.doClose(e),this.closeInFlight)}async doClose(e){let t=this.turnStartedAt!==void 0;this.logger?.info(`session ${this.sessionId} closing deleteRecord=${e.deleteRecord??!1} by=${e.by??"unknown"} midTurn=${t} unsolicitedTurn=${this.unsolicitedTurn!==void 0} queued=${this.promptQueue.length} awaitingPermission=${this.hasPermissionFlag}`),t&&this.logger?.warn(`session ${this.sessionId} closed mid-turn by=${e.by??"unknown"}; the in-flight turn will not settle and the agent is being killed`),this.cancelIdleTimer(),this.cancelOrphanTimer(),clearTimeout(this.upstreamPollTimer);for(let n of this.pendingClaims.values())clearTimeout(n.timer);this.pendingClaims.clear(),await this.requestAgentSessionClose(),await this.agent.kill().catch(()=>{}),this.markClosed({deleteRecord:e.deleteRecord??!1})}async requestAgentSessionClose(){if(this.agentCapabilities?.sessionCapabilities?.close===void 0)return;let e,t=new Promise(r=>{e=setTimeout(r,_g)}),n=this.agent.connection.request("session/close",{sessionId:this.upstreamSessionId}).then(()=>{},()=>{});await Promise.race([n,t]),clearTimeout(e)}onClose(e){return this.closeHandlers.push(e),()=>{let t=this.closeHandlers.indexOf(e);t>=0&&this.closeHandlers.splice(t,1)}}onTitleChange(e){this.titleHandlers.push(e)}retitle(e){return this.runTitleCommand(e)}retitleFromAgent(){return this.runTitleCommand("")}setTitle(e){let t=e.trim();if(!(!t||t===this.title)){this._titleSeedPending=!1,this.title=t,this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",title:t,updatedAt:new Date().toISOString()}});for(let n of this.titleHandlers)try{n(t)}catch{}}}maybeSeedTitleFromPrompt(e){if(!this._titleSeedPending||dt((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let r=At((e??{}).prompt),o=Io(r,200);!o||o.startsWith("/")||(this._titleSeedPending=!1,this.setTitle(o))}maybeApplyAgentModel(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="_hydra_current_model_update")return!1;let r=xn(n.availableModels);r.length>0&&this.setAgentAdvertisedModels(r);let o=typeof n.currentModel=="string"?n.currentModel:typeof n.model=="string"?n.model:void 0;if(o===void 0)return!0;let i=o.trim();if(!i||i===this.currentModel)return!0;this.logger?.info(`live current_model_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(i)}`),this.currentModel=i;for(let a of this.modelHandlers)try{a(i)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentConfigOption(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="config_option_update")return!1;let r=n.configOptions;if(!Array.isArray(r))return!0;for(let i of r)this.applyOneConfigOptionEntry(i);let o=new Set(r.filter(i=>!!i&&typeof i=="object").map(i=>typeof i.id=="string"?i.id.trim():void 0).filter(i=>!!i&&i!=="model"&&i!=="mode"&&i!=="agent"));return this.agentAdvertisedConfigOptions=this.agentAdvertisedConfigOptions.filter(i=>o.has(i.id)),this.fireConfigOptionsHandlers(),!0}applyAgentConfigOptionResponse(e,t){let n=e?.configOptions;if(!Array.isArray(n))return!1;let r=JSON.stringify(this.agentAdvertisedConfigOptions);for(let o of n){let i=o?.id;i==="model"||i==="mode"||i==="agent"||this.applyOneConfigOptionEntry(o)}if(Bg(n,t)){let o=new Set(n.filter(i=>!!i&&typeof i=="object").map(i=>typeof i.id=="string"?i.id.trim():void 0).filter(i=>!!i));this.agentAdvertisedConfigOptions=this.agentAdvertisedConfigOptions.filter(i=>o.has(i.id))}return JSON.stringify(this.agentAdvertisedConfigOptions)!==r}applyOneConfigOptionEntry(e){if(!e||typeof e!="object")return;let t=e;if(t.id==="model"){let k=xn(t.options);k.length>0&&this.setAgentAdvertisedModels(k);let m=t.currentValue;if(typeof m=="string"){let g=m.trim();g&&g!==this.currentModel&&(this.logger?.info(`live config_option_update(model): sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(g)}`),this.applyModelChange(g))}return}if(t.id==="mode"){let k=Is(t.options);k.length>0&&this.setAgentAdvertisedModes(k);let m=t.currentValue;if(typeof m=="string"){let g=m.trim();g&&g!==this.currentMode&&(this.logger?.info(`live config_option_update(mode): sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(g)}`),this.applyModeChange(g))}return}if(typeof t.id!="string"||!t.id.trim())return;let n=t.id.trim(),r=So(t.options);if(r.length===0)return;let o=t.name,i=typeof o=="string"&&o.trim()?o.trim():n,a=t.category,d=typeof a=="string"&&a.trim()?a.trim():"other",c=t.description,u=typeof c=="string"&&c.trim()?c.trim():void 0,l=t.currentValue,p=typeof l=="string"&&l.trim()?l.trim():r[0].value,f={id:n,name:i,category:d,type:"select",currentValue:p,options:r,...u?{description:u}:{}},h=this.agentAdvertisedConfigOptions.findIndex(k=>k.id===n);h>=0?this.agentAdvertisedConfigOptions[h]=f:this.agentAdvertisedConfigOptions.push(f)}maybeApplyAgentMode(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="current_mode_update")return!1;let r=typeof n.currentModeId=="string"?n.currentModeId:typeof n.currentMode=="string"?n.currentMode:typeof n.mode=="string"?n.mode:void 0;if(r===void 0)return!0;let o=r.trim();if(!o||o===this.currentMode)return!0;this.logger?.info(`current_mode_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(o)}`),this.currentMode=o;for(let i of this.modeHandlers)try{i(o)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentUsage(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="usage_update")return!1;let r={...this._currentUsage??{}},o=!1;if(typeof n.used=="number"&&!this.swapInFlight&&pd(r.used,n.used)&&this.armRecallFromSelfCompaction(),typeof n.used=="number"&&r.used!==n.used&&(r.used=n.used,o=!0),typeof n.size=="number"&&r.size!==n.size&&(r.size=n.size,o=!0),n.cost&&typeof n.cost=="object"){let a=n.cost;typeof a.amount=="number"&&(this.reconcileCostLedger(a.amount)&&(o=!0),r.costAmount!==a.amount&&(r.costAmount=a.amount,o=!0)),typeof a.currency=="string"&&r.costCurrency!==a.currency&&(r.costCurrency=a.currency,o=!0)}if(!o)return!0;this._currentUsage=r;let i=this.persistableUsage??r;for(let a of this.usageHandlers)try{a(i)}catch{}return!0}armCostLedgerProbe(){let e=this._currentUsage?.costAmount;typeof e=="number"&&e>0&&(this.costLedgerProbe=e)}reconcileCostLedger(e){let t=this.costLedgerProbe;return t===void 0||(this.costLedgerProbe=void 0,e>=t-1e-6)?!1:(this.cumulativeCost+=t,!0)}notifyAgentChange(e,t,n,r){let o=this.retiringGenerationCost;this.retiringGenerationCost=void 0;let i=this.retiringGenerationUsed;this.retiringGenerationUsed=void 0;let a=this.rotationLifetimeCost;this.rotationLifetimeCost=void 0;for(let d of this.agentChangeHandlers)try{d({agentId:this.agentId,upstreamSessionId:this.upstreamSessionId,...o!==void 0?{retiredCost:o}:{},...a!==void 0?{lifetimeCost:a}:{},...i!==void 0?{retiredUsed:i}:{},...r!==void 0?{startedUsed:r}:{},...t!==void 0?{reason:t}:{},...n!==void 0?{runId:n}:{}})}catch(c){this.logger?.warn(`${e}: agentChange handler failed: ${c.message}`)}}accumulateAndResetCost(){let e=this._currentUsage?.costAmount;e&&(this.cumulativeCost+=e,this.retiringGenerationCost=e);let t=this._currentUsage?.used;typeof t=="number"&&t>0&&(this.retiringGenerationUsed=t),this.rotationLifetimeCost=this.cumulativeCost;let n={used:0,cumulativeCost:this.cumulativeCost,...typeof this._currentUsage?.size=="number"?{size:this._currentUsage.size}:{},...this._currentUsage?.costCurrency?{costCurrency:this._currentUsage.costCurrency}:{}};this._currentUsage=n;for(let r of this.usageHandlers)try{r(n)}catch{}this.broadcastCurrentUsage()}broadcastCurrentUsage(){let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let n={};typeof e.costAmount=="number"&&(n.amount=e.costAmount),typeof e.costCurrency=="string"&&(n.currency=e.costCurrency),t.cost=n}this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:t})}injectCumulativeCost(e){if(!this.cumulativeCost||!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let n=t.update;if(n.sessionUpdate!=="usage_update"||!n.cost||typeof n.cost!="object")return e;let r=n.cost;return typeof r.amount!="number"?e:{...t,update:{...n,cost:{...r,amount:this.cumulativeCost+r.amount}}}}get totalUsage(){return this.currentUsage}setAgentAdvertisedCommands(e){if(sm(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(rm(this.agentAdvertisedModes,e)){this.broadcastAvailableModes();return}this.agentAdvertisedModes=e;for(let t of this.agentModesHandlers)try{t(e)}catch{}this.broadcastAvailableModes()}setAgentAdvertisedModels(e){if(this.logger?.info(`setAgentAdvertisedModels: sessionId=${this.sessionId} currentModel=${JSON.stringify(this.currentModel)} newList=[${e.map(t=>t.modelId).join(",")}]`),om(this.agentAdvertisedModels,e)){this.broadcastAvailableModels();return}this.agentAdvertisedModels=e;for(let t of this.agentModelsHandlers)try{t(e)}catch{}this.broadcastAvailableModels()}onAgentCommandsChange(e){this.agentCommandsHandlers.push(e)}onAgentModesChange(e){this.agentModesHandlers.push(e)}onAgentModelsChange(e){this.agentModelsHandlers.push(e)}onConfigOptionsChange(e){this.configOptionsHandlers.push(e)}extraConfigOptionValues(){return Object.fromEntries(this.agentAdvertisedConfigOptions.map(e=>[e.id,e.currentValue]))}onModelChange(e){this.modelHandlers.push(e)}onModeChange(e){this.modeHandlers.push(e)}onInteractiveChange(e){this.interactiveHandlers.push(e)}onPriorityChange(e){this.priorityHandlers.push(e)}onReadStateChange(e){this.readStateHandlers.push(e)}get unread(){return Sn(this._lastTurnEndedAt,this._readAt)}setRead(e,t=Date.now()){let n=ys({lastTurnEndedAt:this._lastTurnEndedAt,readAt:this._readAt},e,t);n!==void 0&&(this._readAt=n,this.fireReadState())}noteTurnEnded(e=Date.now()){this._readAt===void 0&&(this._readAt=Math.min(this._lastTurnEndedAt??this.createdAt,e-1)),this._lastTurnEndedAt=e,this.fireReadState(),this.captureUpstreamBaseline()}hasEndUnobservableTask(){for(let e of this.armedTasks.values())if(e.endUnobservable===!0)return!0;return!1}captureUpstreamBaseline(){let e=++this.upstreamBaselineGen;if(!this.hasEndUnobservableTask()){this.upstreamBaselineMs=void 0;return}this.fetchUpstreamUpdatedAt().then(t=>{t===void 0||e!==this.upstreamBaselineGen||this.promptInFlight||this.unsolicitedTurn!==void 0||(this.upstreamBaselineMs=t,this.scheduleUpstreamPoll(e))}).catch(()=>{})}scheduleUpstreamPoll(e){clearTimeout(this.upstreamPollTimer),this.upstreamPollTimer=setTimeout(()=>{this.upstreamPollTimer=void 0,this.pollUpstream(e)},Vg),this.upstreamPollTimer.unref()}async pollUpstream(e){if(!this.upstreamPollLive(e))return;let t=await this.fetchUpstreamUpdatedAt().catch(()=>{});this.upstreamPollLive(e)&&(t!==void 0&&this.applyUpstreamUpdatedAt(t),this.upstreamPollLive(e)&&this.scheduleUpstreamPoll(e))}upstreamPollLive(e){return e===this.upstreamBaselineGen&&this.upstreamBaselineMs!==void 0&&!this.closing&&!this.closed&&this.hasEndUnobservableTask()}async fetchUpstreamUpdatedAt(){let t=(await this.agent.connection.request("session/list",{cwd:this.cwd}))?.sessions?.find(r=>r.sessionId===this.upstreamSessionId),n=typeof t?.updatedAt=="string"?Date.parse(t.updatedAt):NaN;return Number.isNaN(n)?void 0:n}noteUpstreamUpdatedAt(e){let t=e===void 0?NaN:Date.parse(e);Number.isNaN(t)||this.applyUpstreamUpdatedAt(t)}applyUpstreamUpdatedAt(e){if(this.upstreamBaselineMs===void 0||e<=this.upstreamBaselineMs||this.promptInFlight||this.unsolicitedTurn!==void 0)return;let t=0;for(let[n,r]of this.armedTasks)r.endUnobservable===!0&&(this.armedTasks.delete(n),t+=1);this.upstreamBaselineMs=void 0,t>0&&(this.logger?.info(`session ${this.sessionId} cleared ${t} armed task(s): agent updated the session after its turn ended`),this.onArmedTasksChanged())}fireReadState(){let e={lastTurnEndedAt:this._lastTurnEndedAt,readAt:this._readAt};for(let t of this.readStateHandlers)try{t(e)}catch{}}setPriority(e){let t=e===void 0||e<=0?void 0:Math.floor(e);if(t!==this._priority){this._priority=t,this.updatedAt=Date.now();for(let n of this.priorityHandlers)try{n(t)}catch{}}}applyModelChange(e){let t=e.trim();if(t){this.modelChangeInFlight=!0;try{if(t!==this.currentModel){this.logger?.info(`applyModelChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(t)}`),this.currentModel=t;for(let r of this.modelHandlers)try{r(t)}catch{}}let n={sessionUpdate:"_hydra_current_model_update",currentModel:t};this.agentAdvertisedModels.length>0&&(n.availableModels=[...this.agentAdvertisedModels]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modelChangeInFlight=!1}}}applyModeChange(e){let t=e.trim();if(t){this.modeChangeInFlight=!0;try{if(t!==this.currentMode){this.logger?.info(`applyModeChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(t)}`),this.currentMode=t;for(let r of this.modeHandlers)try{r(t)}catch{}}let n={sessionUpdate:"current_mode_update",currentModeId:t};this.agentAdvertisedModes.length>0&&(n.availableModes=[...this.agentAdvertisedModes]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modeChangeInFlight=!1}}}buildConfigOptions(){let e=[];if(this.agentAdvertisedModels.length>0){let r=this.agentAdvertisedModels.map(i=>({value:i.modelId,name:i.name??i.modelId,...i.description!==void 0?{description:i.description}:{}}));this.currentModel&&!r.some(i=>i.value===this.currentModel)&&r.unshift({value:this.currentModel,name:this.currentModel});let o=this.currentModel||r[0].value;e.push({id:"model",name:"Model",category:"model",type:"select",currentValue:o,options:r})}if(this.agentAdvertisedModes.length>0){let r=this.agentAdvertisedModes.map(i=>({value:i.id,name:i.name??i.id,...i.description!==void 0?{description:i.description}:{}}));this.currentMode&&!r.some(i=>i.value===this.currentMode)&&r.unshift({value:this.currentMode,name:this.currentMode});let o=this.currentMode||r[0].value;e.push({id:"mode",name:"Session Mode",category:"mode",type:"select",currentValue:o,options:r})}let n=(this.availableAgentsFn?.()??[]).map(r=>({value:r.id,name:r.name??r.id,...r.description!==void 0?{description:r.description}:{}}));return n.some(r=>r.value===this.agentId)||n.unshift({value:this.agentId,name:this.agentId}),e.push({id:"agent",name:"Agent",category:"_hydra_agent",type:"select",currentValue:this.agentId,options:n}),e.push(...this.agentAdvertisedConfigOptions),e}broadcastConfigOptions(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"config_option_update",configOptions:this.buildConfigOptions()}}),this.fireConfigOptionsHandlers()}fireConfigOptionsHandlers(){for(let e of this.configOptionsHandlers)try{e(this.agentAdvertisedConfigOptions)}catch{}}mergeAgentOptionIntoEnvelope(e){if(!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let n=t.update,r=Array.isArray(n.configOptions)?[...n.configOptions]:[];if(r.some(a=>a&&typeof a=="object"&&a.id==="agent"))return e;let i=this.buildConfigOptions().find(a=>a.id==="agent");return i?{...t,update:{...n,configOptions:[...r,i]}}:e}onUsageChange(e){this.usageHandlers.push(e)}mergedAvailableCommands(){let e=this.daemonTopLevelCommands(),t=this.aliasableBareVerbs();for(let n of Jt){if(t.get(n.verb)!=="__hydra__")continue;let r=n.argsHint?`${n.verb} ${n.argsHint}`:n.verb;e.push({name:r,description:`Alias for '/hydra ${n.verb}': ${n.description}`})}if(this.extensionCommands)for(let{name:n,command:r}of this.extensionCommands.list()){let o=r.verb?`hydra ${n} ${r.verb}`:`hydra ${n}`,a={name:r.argsHint?`${o} ${r.argsHint}`:o};r.description&&(a.description=r.description),e.push(a);let d=io(n),c=d??n;if(d!==void 0){let u=r.verb?`hydra ${c} ${r.verb}`:`hydra ${c}`,p={name:r.argsHint?`${u} ${r.argsHint}`:u};r.description&&(p.description=r.description),e.push(p)}if(c.length>0&&t.get(c)===n){let u=r.verb?`${c} ${r.verb}`:c,p={name:r.argsHint?`${u} ${r.argsHint}`:u};r.description&&(p.description=r.description),e.push(p)}}return e.push(...this.agentAdvertisedCommands),e}daemonTopLevelCommands(){return[{name:"hydra",description:"Hydra session command (kill, restart, title, agent <agent>)"},{name:"model",description:"Switch model; omit arg to list available models"},{name:"mode",description:"Switch mode; omit arg to list available modes"},{name:"sessions",description:"List all sessions"},{name:"help",description:"Show available commands"}]}aliasableBareVerbs(){let e=new Set,t=i=>i.split(/\s+/)[0]??"";for(let i of this.daemonTopLevelCommands()){let a=t(i.name);a&&e.add(a)}for(let i of this.agentAdvertisedCommands){let a=t(i.name),d=a.startsWith("/")?a.slice(1):a;d&&e.add(d)}let n=new Map;for(let i of Jt)e.has(i.verb)||n.set(i.verb,"__hydra__");if(!this.extensionCommands)return n;let r=new Map,o=new Set;for(let{name:i}of this.extensionCommands.list()){if(o.has(i))continue;o.add(i);let a=io(i)??i;if(!a||e.has(a)||n.has(a))continue;let d=r.get(a);d===void 0?r.set(a,i):d!==i&&r.set(a,"__conflict__")}for(let[i,a]of r)a!=="__conflict__"&&n.set(i,a);return n}agentOnlyAdvertisedCommands(){return[...this.agentAdvertisedCommands]}agentKnowsSlashCommand(e){let t=r=>r.startsWith("/")?r.slice(1):r,n=t(e);if(!n)return!1;for(let r of this.agentAdvertisedCommands)if(t(r.name.split(/\s+/)[0]??"")===n)return!0;return!1}availableModes(){return[...this.agentAdvertisedModes]}availableModels(){return[...this.agentAdvertisedModels]}maybeApplyAgentSessionInfo(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="session_info_update"||typeof n.title!="string"||this._upstreamRespawned)return;let r=n.title.trim();if(!(!r||r===this.title)){this.title=r,this._firstPromptSeeded=!0,this._titleSeedPending=!1;for(let o of this.titleHandlers)try{o(r)}catch{}}}async handleSlashCommand(e,t){let r=e.slice(6).trim().match(/^(\S+)(?:\s+([\s\S]*))?$/),o=r?.[1]??"",i=(r?.[2]??"").trim();if(o==="")return{stopReason:"end_turn"};let a=t!==void 0;if(Jt.some(l=>l.verb===o))switch(o){case"title":return a?this.runTitleCommandInline(i):this.runTitleCommand(i);case"agent":return this.runAgentCommandInline(i);case"config":return this.handleConfigCommand(`/config ${i}`);case"kill":return this.runKillCommand();case"workspace":return this.runWorkspaceCommand(i);case"restart":return a?this.runRestartCommandInline():this.runRestartCommand();case"clear":return this.runClearCommand();case"compact":return a?this.runCompactCommandInline(i):this.runCompactCommand(i);case"uncompact":return a?this.runUncompactCommandInline():this.runUncompactCommand();case"fork":return a?this.runForkCommandInline(i,t):this.runForkCommand(i);default:{let l=new Error(`no dispatcher for /hydra verb ${o}`);throw l.code=R.InternalError,l}}if(this.extensionCommands?.has(o))return a?this.runExtensionCommandInline(o,i,t):this.runExtensionCommand(o,i);let d=ad(o).find(l=>this.extensionCommands?.has(l));if(d!==void 0)return a?this.runExtensionCommandInline(d,i,t):this.runExtensionCommand(d,i);let c=Jt.map(l=>l.verb);if(this.extensionCommands){let l=new Set;for(let{name:p}of this.extensionCommands.list())l.has(p)||(c.push(p),l.add(p))}let u=new Error(`unknown /hydra verb: ${o} (known: ${c.join(", ")})`);throw u.code=R.InvalidParams,u}runExtensionCommand(e,t){return this.enqueuePrompt(`extension:${e}`,()=>this.runExtensionCommandInline(e,t,void 0))}async runExtensionCommandInline(e,t,n){let r=this.extensionCommands?.get(e);if(!r)return this.emitExtensionReply(`extension "${e}" is no longer connected`);let o=t.match(/^(\S+)(?:\s+([\s\S]*))?$/),i=o?.[1]??"",a=(o?.[2]??"").trim();if(!r.commands.some(h=>h.verb===i)){let h=r.commands.map(k=>k.verb).join(", ");return this.emitExtensionReply(`/hydra ${e}${i?` ${i}`:""}: unknown verb (known: ${h||"(none)"})`)}let d={sessionId:this.sessionId,verb:i,args:a};n!==void 0&&(d.messageId=n);let c=()=>{},u=new Promise(h=>{c=h});n!==void 0&&this.inFlightExtensionDispatches.set(n,{extensionName:e,connection:r.connection,cancel:h=>c({stopReason:"cancelled",reason:h})});let l,p=!1;try{let h=r.connection.request("hydra-acp/commands/invoke",d),k=await Promise.race([h,u]);if(k&&typeof k=="object"&&k.stopReason==="cancelled"&&"reason"in k)return p=!0,this.logger?.info(`extension ${e} ${i} cancelled (cancelExtensionDispatch); abandoning in-flight commands/invoke`),{stopReason:"cancelled"};l=k}catch(h){return this.emitExtensionReply(`${e} ${i}: ${h.message}`)}finally{n!==void 0&&!p&&this.inFlightExtensionDispatches.delete(n)}let f=l&&typeof l=="object"&&typeof l.text=="string"?l.text:"";return f.length>0?this.emitExtensionReply(f):{stopReason:"end_turn"}}cancelExtensionDispatch(e,t){let n=this.inFlightExtensionDispatches.get(e);if(!n)return!1;this.inFlightExtensionDispatches.delete(e);try{n.connection.notify("hydra-acp/commands/cancel",{sessionId:this.sessionId,messageId:e,reason:t})}catch(r){this.logger?.warn(`notify commands/cancel to ${n.extensionName} failed: ${r.message}`)}return n.cancel(t),!0}emitExtensionReply(e){return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
61
61
  ${e}
62
62
  `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}async handleSessionsCommand(){let e;if(!this.listSessions)e="_(session listing not available)_";else{let t=await this.listSessions();if(t.length===0)e="_(no sessions)_";else{let n=t.map(r=>{let o=r.sessionId.replace(/^hydra_session_/,"").slice(0,12),i=r.currentModel?` \xB7 ${r.currentModel}`:"",a=r.sessionId===this.sessionId?" \u25C0":"",d=r.title?` ${r.title}`:"";return`\`${o}\` ${r.cwd}${i}${a}${d}`});e=`Sessions (${t.length}):
63
63
  ${n.join(`
@@ -70,7 +70,7 @@ ${n}
70
70
  `},_meta:{"hydra-acp":{synthetic:!0}}}}),Promise.resolve({stopReason:"end_turn"})}async handleModelCommand(e){let t=e.slice(6).trim();if(t===""){let i=this.agentAdvertisedModels,a=this.currentModel,d;if(i.length===0)d=a?`Current model: ${a}`:"_(no models advertised yet)_";else{let c=a?i.some(l=>l.modelId===a):!0,u=i.map(l=>{let p=l.modelId===a?"\u25B6 ":" ",f=l.name&&l.name!==l.modelId?` ${l.name}`:"";return`${p}${l.modelId}${f}`});!c&&a&&u.unshift(`\u25B6 ${a}`),d=u.join(`
71
71
  `)}return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
72
72
  ${d}
73
- `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}let n=Jt(t,this.agentAdvertisedModels),r=t;if(n.kind==="resolved")r=n.modelId;else if(n.kind==="ambiguous"||n.kind==="unknown"){let i=this.agentAdvertisedModels.map(p=>p.modelId),a=t.toLowerCase(),d=n.kind==="ambiguous"?n.candidates:i.filter(p=>p.toLowerCase().includes(a)),c=d.length>0?d:i,u=n.kind==="ambiguous"?`"${t}" matches multiple models: ${n.candidates.join(", ")}`:d.length>0?`"${t}" is not an available model. Did you mean`:`"${t}" is not an available model`,l=n.kind==="ambiguous"||d.length===0?"Available models":"Matching models";return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
73
+ `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}let n=Vt(t,this.agentAdvertisedModels),r=t;if(n.kind==="resolved")r=n.modelId;else if(n.kind==="ambiguous"||n.kind==="unknown"){let i=this.agentAdvertisedModels.map(p=>p.modelId),a=t.toLowerCase(),d=n.kind==="ambiguous"?n.candidates:i.filter(p=>p.toLowerCase().includes(a)),c=d.length>0?d:i,u=n.kind==="ambiguous"?`"${t}" matches multiple models: ${n.candidates.join(", ")}`:d.length>0?`"${t}" is not an available model. Did you mean`:`"${t}" is not an available model`,l=n.kind==="ambiguous"||d.length===0?"Available models":"Matching models";return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
74
74
  ${u}.
75
75
  ${l}:
76
76
  ${c.join(`
@@ -78,9 +78,9 @@ ${l}:
78
78
  `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}let o=await this.forwardModelChange(r);return this.applyAgentConfigOptionResponse(o,"model"),this.applyModelChange(r),{stopReason:"end_turn"}}async handleModeCommand(e){let t=e.slice(5).trim();if(t===""){let r=this.agentAdvertisedModes,o=this.currentMode,i;if(r.length===0)i=o?`Current mode: ${o}`:"_(no modes advertised yet)_";else{let a=o?r.some(c=>c.id===o):!0,d=r.map(c=>{let u=c.id===o?"\u25B6 ":" ",l=c.name&&c.name!==c.id?` ${c.name}`:"";return`${u}${c.id}${l}`});!a&&o&&d.unshift(`\u25B6 ${o}`),i=d.join(`
79
79
  `)}return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
80
80
  ${i}
81
- `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}let n=this.agentAdvertisedModes;if(n.length>0&&!n.some(r=>r.id===t)){let r=n.map(o=>o.id).join(", ");throw fe(new Error(`unknown mode: ${t} (known: ${r})`),x.InvalidParams)}return await this.forwardRequest("session/set_mode",{sessionId:this.sessionId,modeId:t}),this.applyModeChange(t),{stopReason:"end_turn"}}async handleConfigCommand(e){let t=e.slice(7).trim().match(/^(\S+)(?:\s+([\s\S]*))?$/),n=t?.[1],r=t?.[2]??"";if(!n){let l=this.buildConfigOptions();if(l.length===0)return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
81
+ `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}let n=this.agentAdvertisedModes;if(n.length>0&&!n.some(r=>r.id===t)){let r=n.map(o=>o.id).join(", ");throw fe(new Error(`unknown mode: ${t} (known: ${r})`),R.InvalidParams)}return await this.forwardRequest("session/set_mode",{sessionId:this.sessionId,modeId:t}),this.applyModeChange(t),{stopReason:"end_turn"}}async handleConfigCommand(e){let t=e.slice(7).trim().match(/^(\S+)(?:\s+([\s\S]*))?$/),n=t?.[1],r=t?.[2]??"";if(!n){let l=this.buildConfigOptions();if(l.length===0)return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
82
82
  _(no config options advertised yet)_
83
- `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let p=l.map(f=>_d(f));return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
83
+ `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let p=l.map(f=>Od(f));return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
84
84
  ${p.join(`
85
85
 
86
86
  `)}
@@ -90,18 +90,18 @@ ${p.join(`
90
90
  Available options:
91
91
  ${l}
92
92
  `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}if(!r)return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
93
- ${_d(i)}
94
- `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let a=i.options.map(l=>l.value),d=Vt(r,a),c=r;if(d.kind==="resolved")c=d.modelId;else if(d.kind==="ambiguous"||d.kind==="unknown"){let l=r.toLowerCase(),p=d.kind==="ambiguous"?d.candidates:a.filter(m=>m.toLowerCase().includes(l)),f=p.length>0?p:a,h=d.kind==="ambiguous"?`"${r}" matches multiple values for "${n}": ${d.candidates.join(", ")}`:p.length>0?`"${r}" is not a valid value for "${n}". Did you mean`:`"${r}" is not a valid value for "${n}"`,k=d.kind==="ambiguous"||p.length===0?"Valid values":"Matching values";return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
93
+ ${Od(i)}
94
+ `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let a=i.options.map(l=>l.value),d=Gt(r,a),c=r;if(d.kind==="resolved")c=d.modelId;else if(d.kind==="ambiguous"||d.kind==="unknown"){let l=r.toLowerCase(),p=d.kind==="ambiguous"?d.candidates:a.filter(m=>m.toLowerCase().includes(l)),f=p.length>0?p:a,h=d.kind==="ambiguous"?`"${r}" matches multiple values for "${n}": ${d.candidates.join(", ")}`:p.length>0?`"${r}" is not a valid value for "${n}". Did you mean`:`"${r}" is not a valid value for "${n}"`,k=d.kind==="ambiguous"||p.length===0?"Valid values":"Matching values";return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
95
95
  ${h}.
96
96
  ${k}:
97
97
  ${f.join(`
98
98
  `)}
99
- `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}if(n==="model"){if(c!==this.currentModel){let l=await this.forwardModelChange(c);this.applyAgentConfigOptionResponse(l,"model")}return this.applyModelChange(c),{stopReason:"end_turn"}}if(n==="mode")return c!==this.currentMode&&await this.forwardRequest("session/set_mode",{sessionId:this.sessionId,modeId:c}),this.applyModeChange(c),{stopReason:"end_turn"};if(n==="agent")return c!==this.agentId&&await this.runAgentCommandInline(c),{stopReason:"end_turn"};let u=await this.forwardRequest("session/set_config_option",{sessionId:this.sessionId,configId:n,value:c});return this.applyAgentConfigOptionResponse(u,n)&&this.broadcastConfigOptions(),{stopReason:"end_turn"}}runTitleCommand(e){return this.enqueuePrompt("title",()=>this.runTitleCommandInline(e))}async runTitleCommandInline(e){return e?(this.setTitle(e),{stopReason:"end_turn"}):(this.scheduleSynopsisHook?.(),{stopReason:"end_turn"})}async runInternalPrompt(e){if(this.internalPromptCapture)throw new Error("internal prompt already in flight");let t={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};this.internalPromptCapture=t;try{return await this.agent.connection.request("session/prompt",{sessionId:this.upstreamSessionId,prompt:[{type:"text",text:e}]}),t.chunks.join("")}finally{this.internalPromptCapture=void 0}}setAgent(e){return this.runAgentCommandInline(e)}async runAgentCommandInline(e){if(e==="status")return this.runAgentStatusCommandInline();let t=e;if(!t)throw fe(new Error("/hydra agent requires an agent id"),x.InvalidParams);let r=(this.resolveAgentIdHook?await this.resolveAgentIdHook(t):void 0)??t;if(r===this.agentId)throw fe(new Error(`already on agent ${r}`),x.InvalidParams);if(!this.scheduleCompactionHook)return this.emitExtensionReply("agent switching not configured for this session"),{stopReason:"end_turn"};this.scheduleCompactionHook({targetAgentId:r});let o=this.agentTurnInFlight||this.unsolicitedTurn!==void 0;return this.emitExtensionReply(o?`Agent switch to ${r} scheduled. A turn is still in flight \u2014 the rotation lands on the next idle edge; cancel the turn to make that happen now.`:`Agent switch to ${r} scheduled. The session will rotate to ${r} once synthesis completes.`),{stopReason:"end_turn"}}async runAgentStatusCommandInline(){let e=await this.getPendingAgentSwapHook?.();return e?(this.emitExtensionReply(`Agent switch to ${e} pending \u2014 will rotate on the next idle edge.`),{stopReason:"end_turn"}):(this.emitExtensionReply("No agent switch pending."),{stopReason:"end_turn"})}async runKillCommand(){return await this.close({deleteRecord:!1,by:"/hydra kill"}),{stopReason:"end_turn"}}runRestartCommand(){return this.enqueuePrompt("restart",()=>this.runRestartCommandInline())}async runRestartCommandInline(){if(!this.spawnReplacementAgent)throw fe(new Error("agent restart not configured for this session"),x.InternalError);return await this.respawnAgent(),{stopReason:"end_turn"}}runCompactCommand(e){return this.enqueuePrompt("compact",()=>this.runCompactCommandInline(e))}async runCompactCommandInline(e){return e==="status"?this.runCompactStatusCommandInline():this.scheduleCompactionHook?(this.scheduleCompactionHook(),this.emitExtensionReply("Compaction scheduled. The session will rotate to a fresh upstream once summarization completes."),{stopReason:"end_turn"}):(this.emitExtensionReply("compaction scheduling not configured for this session"),{stopReason:"end_turn"})}async runCompactStatusCommandInline(){let e=await this.getCompactionStateHook?.(),t=this._summarizedThroughEntry,n=await this.getUpstreamGenerationsHook?.()??[],r=wd(n,t),o=kd(r);if(e==null&&t==null&&o.length===0)return this.emitExtensionReply("This session has never been compacted."),{stopReason:"end_turn"};let i=[];return e==null?i.push(`No compaction in progress. Last summarized through entry: ${t??0}`):(i.push(`Compaction state: ${e.status}${e.iter!=null?` (iteration ${e.iter})`:""}`,`Summarized through entry: ${t??0}`,`Pending attempts: ${e.attempts??0}`),e.lastError!==void 0&&i.push(`Last error: ${e.lastError}`)),i.push(`Current upstream: ${this.upstreamSessionId}`),o.length>0&&i.push("",...o),this.emitExtensionReply(i.join(`
100
- `)),{stopReason:"end_turn"}}runUncompactCommand(){return this.enqueuePrompt("uncompact",()=>this.runUncompactCommandInline())}async runWorkspaceCommand(e){if(!this.workspaceHook)return this.emitExtensionReply("Workspaces are not available on this session (no workspace hook configured)."),{stopReason:"end_turn"};let[t="status",...n]=e.split(/\s+/).filter(d=>d.length>0);if(!Cd.includes(t))return this.emitExtensionReply(`Unknown workspace verb "${t}". Use one of: ${Cd.join(", ")}.`),{stopReason:"end_turn"};let r=n.filter(d=>d.startsWith("--")),o=r.filter(d=>d!=="--clean"&&d!=="--deep");if(o.length>0)return this.emitExtensionReply(`Unknown workspace flag(s) ${o.join(", ")}. Supported: --clean (start), --deep (clean).`),{stopReason:"end_turn"};let i={clean:r.includes("--clean"),deep:r.includes("--deep")};if(i.clean&&t!=="start")return this.emitExtensionReply(`--clean applies to \`start\`, not to \`${t}\`.`),{stopReason:"end_turn"};if(i.deep&&t!=="clean")return this.emitExtensionReply(`--deep applies to \`clean\`, not to \`${t}\`.`),{stopReason:"end_turn"};let a=n.filter(d=>!d.startsWith("--")).join(" ").trim();try{let d=await this.workspaceHook(t,a.length>0?a:void 0,i);this.emitExtensionReply(d)}catch(d){this.emitExtensionReply(`Workspace ${t} failed: ${d instanceof Error?d.message:String(d)}`)}return{stopReason:"end_turn"}}async runUncompactCommandInline(){if(!this.uncompactHook)return this.emitExtensionReply("Rollback not available: uncompact hook not configured for this session."),{stopReason:"end_turn"};try{await this.uncompactHook(),this.emitExtensionReply("Rolled back to pre-compaction upstream. The session is now using the previous agent context.")}catch(e){this.emitExtensionReply(`Rollback failed: ${e instanceof Error?e.message:String(e)}`)}return{stopReason:"end_turn"}}runForkCommand(e){return this.enqueuePrompt("fork",()=>this.runForkCommandInline(e,void 0))}async findMessageIdBefore(e){if(!this.historyStore)return;let t=await this.historyStore.load(this.sessionId),n;for(let r of t){if(r.method!=="session/update")continue;let i=r.params?.update?.messageId;if(typeof i=="string"){if(i===e)return n;n=i}}}async runForkCommandInline(e,t){if(!this.forkHook)return this.emitExtensionReply("Fork not configured for this session."),{stopReason:"end_turn"};let n=(e??"").trim(),r=n.match(/^--verbatim(?:\s+([\s\S]*))?$/),o=r?"verbatim":void 0,i=(r?r[1]??"":n).trim();try{let a={};if(o&&(a.mode=o),i!==""&&(a.prompt=i),t&&this.historyStore){let u=await this.findMessageIdBefore(t).catch(()=>{});u&&(a.forkAt=u)}let c=(await this.forkHook(Object.keys(a).length>0?a:void 0)).sessionId.replace(/^hydra_session_/,"");this.emitExtensionReply(i!==""?`Forked to [\`${c}\`](hydra://sessions/${c}) and sent the prompt.`:`Forked to [\`${c}\`](hydra://sessions/${c}).`)}catch(a){this.emitExtensionReply(`Fork failed: ${a instanceof Error?a.message:String(a)}`)}return{stopReason:"end_turn"}}escalateUnresponsiveCancel(){this.cancelReopenStreak=0,this.logger?.warn(`session ${this.sessionId} agent ${this.agentId} reopened an unsolicited turn right after cancel ${s.UNSOLICITED_REOPEN_LIMIT} times in a row; forcing a restart`),this.broadcastQueueNotification("hydra-acp/cancel_failed",{sessionId:this.sessionId,reason:"unresponsive",message:`${this.agentId} kept resuming after repeated cancels; restarting the agent`}),this.forceCancel().catch(e=>{this.logger?.warn(`session ${this.sessionId} forceCancel after unresponsive-cancel escalation failed: ${e instanceof Error?e.message:String(e)}`)})}async forceCancel(){if(this.closed||this.closing)throw fe(new Error("session is closing"),x.SessionClosing);return this.lastCancelAt=0,this.forceCancelling=!0,await this.close({deleteRecord:!1,by:"force-cancel"}),{stopReason:"cancelled"}}async rewind(e,t,n={}){let r=()=>this.promptInFlight&&!n.afterCurrentTurn||this.promptQueue.length>0?"the session is busy; wait for the current turn and queued prompts to finish, then try again":this.swapInFlight?"the session's agent is being replaced; try again in a moment":void 0,o=r()??await this.quiesceBlocker()??r();if(o!==void 0)throw fe(new Error(o),x.InvalidRequest);if(!this.spawnReplacementAgent)throw fe(new Error("agent restart not configured for this session"),x.InternalError);await this.enqueuePrompt("rewind",async()=>{this.swapInFlight=!0;try{if(!await t())return;await this.respawnAgent({rewind:!0})}finally{this.swapInFlight=!1}this.broadcastClientUpdate({sessionUpdate:"_hydra_history_truncated",keepThrough:e})})}runClearCommand(){if(!this.rewindHook)throw fe(new Error("clear not configured for this session"),x.InternalError);return this.rewindHook(null).catch(e=>{this.broadcastSyntheticText(`/hydra clear failed: ${e.message}`)}),Promise.resolve({stopReason:"end_turn"})}async respawnAgent(e={}){let t=this.spawnReplacementAgent,n=this.agentId,r=await this.buildSwitchTranscript(n,e.rewind?{intro:"You are continuing a conversation whose later turns were withdrawn by the user. Below is the transcript of what remains.",followup:"Each line is prefixed with its speaker. Treat this as context for the next user message; do not re-respond to earlier turns."}:void 0),o=this.currentModel,i=this.currentMode,a=await t({agentId:n,cwd:this.cwd,agentArgs:this.agentArgs,...this.forwardedEnv?{forwardedEnv:this.forwardedEnv}:{}});if(this.accumulateAndResetCost(),this.wireAgent(a.agent,{respawn:!0}),e.rewind){let c=await ft({agent:a.agent,upstreamSessionId:a.upstreamSessionId,persistedModel:o,agentReportedModel:a.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(c.result,"model"),await lt({agent:a.agent,upstreamSessionId:a.upstreamSessionId,persistedMode:i,agentReportedMode:a.initialMode,logger:this.logger}),a.agent.connection.drainBuffered("session/update")}let d=this.agent;this.agent=a.agent,this.upstreamSessionId=a.upstreamSessionId,this.agentMeta=a.agentMeta,this.agentCapabilities=a.agentCapabilities,this.resetModelVerb(a.modelVerb),this.agentAdvertisedCommands=[],this.broadcastMergedCommands(),e.rewind||(this.currentModel=a.initialModel,this.currentMode=a.initialMode),this.setAgentAdvertisedModels(a.initialModels??[]),this.setAgentAdvertisedModes(a.initialModes??[]),this.agentAdvertisedConfigOptions=a.initialConfigOptions??[],await this.retireAgent(d,"agent restart"),r&&await this.runInternalPrompt(r).catch(()=>{}),e.rewind||this.broadcastAgentSwitch(n,n),this.notifyAgentChange("respawnAgent","restart")}async buildSwitchTranscript(e,t){let n=[],r=await this.getHistorySnapshot();for(let c of r){if(c.method!=="session/update")continue;let l=(c.params??{}).update;if(!l||l._meta?.["hydra-acp"]?.synthetic)continue;let f=l.sessionUpdate;if(f==="prompt_received"){let h=It(l.prompt);h&&n.push({speaker:"user",text:h})}else if(f==="agent_message_chunk"){let k=l.content?.text;k&&n.push({speaker:`agent: ${e}`,text:k})}else if(f==="tool_call"||f==="tool_call_update"){let h=l.status,k=l.title;(h==="completed"||h==="failed")&&n.push({speaker:"tool",text:`${k??"?"} ${h}`})}}if(n.length===0)return"";let o=[],i;for(let c of n)i&&i.speaker===c.speaker?i.text+=c.text:(i&&o.push(`<${i.speaker}>: ${i.text.trim()}`),i={speaker:c.speaker,text:c.text});i&&o.push(`<${i.speaker}>: ${i.text.trim()}`);let a=t?.intro??`You are taking over this conversation from ${e}. Below is the transcript so far.`,d=t?.followup??`Each line is prefixed with its speaker. Continue from where ${e} left off, responding to the user's most recent message.`;return[a,d,"","--- begin transcript ---",...o,"--- end transcript ---"].join(`
101
- `)}async seedFromImport(){await this.enqueuePrompt("seed:import",async()=>{let e=await this.buildSwitchTranscript(this.agentId,{intro:"You are continuing a conversation that was imported from another hydra. Below is the transcript so far.",followup:"Each line is prefixed with its speaker. Treat this as context for the next user message; do not re-respond to earlier turns."});e&&await this.runInternalPrompt(e).catch(()=>{})})}async seedFromFork(e){await this.enqueuePrompt("seed:fork",async()=>{let t=this.title??"(untitled)",n=[];if(this.historyStore)try{n=await this.historyStore.load(this.sessionId)}catch(o){this.logger?.warn(`seedFromFork: historyStore.load failed: ${o.message}`)}let r=po({synopsis:e,title:t,tail:n,tailK:_g,tailFloor:$g,watermark:this._summarizedThroughEntry,recallArmed:(this._summarizedThroughEntry??0)>0});if(this.internalPromptCapture)throw new Error("seedFromFork: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};try{await this.agent.connection.request("session/prompt",{sessionId:this.upstreamSessionId,prompt:[{type:"text",text:r}]});let o=this.internalPromptCapture;this.logger?.info(`seedFromFork: seed processed sessionId=${this.sessionId} seedChars=${r.length} toolCalls=${o.toolCalls} thinkingChars=${o.thinkingChars} messageChars=${o.messageChars}`)}finally{this.internalPromptCapture=void 0}})}broadcastAgentSwitch(e,t){this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",_meta:{"hydra-acp":{synthetic:!0,agentId:t,pendingAgentSwap:null}}}}),this.broadcastConfigOptions()}broadcastPendingAgentSwap(e){this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",_meta:{"hydra-acp":{synthetic:!0,pendingAgentSwap:e}}}})}hasStreamBuffer(){return this.streamBuffer!==void 0}get streamPath(){return this.streamFilePath}openStream(e){if(this.streamBuffer!==void 0)throw new Error(`stream buffer already open for session ${this.sessionId}`);let n=(e.mode??"memory")==="file"&&e.filePathFor!==void 0?e.filePathFor(this.sessionId):void 0,r={};e.capacityBytes!==void 0&&(r.capacityBytes=e.capacityBytes),n!==void 0&&(r.filePath=n),e.fileCapBytes!==void 0&&(r.fileCapBytes=e.fileCapBytes),r.onFileCapReached=()=>{this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_stream_truncated",...n!==void 0?{filePath:n}:{},fileCapBytes:e.fileCapBytes}})};let o=new hs(r);this.streamBuffer=o,this.streamFilePath=n;let i={capacityBytes:o.capacity};return n!==void 0&&(i.filePath=n),e.fileCapBytes!==void 0&&(i.fileCapBytes=e.fileCapBytes),i}streamWrite(e,t){let n=this.requireStreamBuffer();if(e.length>0){let r=Buffer.from(e,"base64");n.append(r)}return t===!0&&n.close(),{writeCursor:n.writeCursorPos}}async streamRead(e,t,n){let r=this.requireStreamBuffer(),o=Math.max(0,Math.min(t??qt,qt)),i=r.read(e,o);if(i.bytes.length===0&&i.eof!==!0&&n!==void 0&&n>0){let d=await r.waitForData(i.nextCursor,n);(d==="data"||d==="eof")&&(i=r.read(i.nextCursor,o))}let a={bytes:i.bytes.toString("base64"),nextCursor:i.nextCursor};return i.gap!==void 0&&(a.gap=i.gap),i.eof===!0&&(a.eof=!0),a}streamTail(e){let n=this.requireStreamBuffer().tail(e);return{bytes:n.bytes.toString("base64"),startCursor:n.startCursor,endCursor:n.endCursor,truncated:n.truncated}}streamHead(e){let n=this.requireStreamBuffer().head(e);return{bytes:n.bytes.toString("base64"),startCursor:n.startCursor,endCursor:n.endCursor,truncated:n.truncated}}async streamWaitFor(e,t){return this.requireStreamBuffer().waitForData(e,t)}streamGrep(e){return this.requireStreamBuffer().grep(e)}streamInfo(){let e=this.requireStreamBuffer();return{writeCursor:e.writeCursorPos,oldestAvailable:e.oldestAvailable,capacity:e.capacity,closed:e.isClosed}}requireStreamBuffer(){if(this.streamBuffer===void 0){let e=new Error(`session ${this.sessionId} has no stream buffer; POST /v1/sessions/:id/stdin/open first`);throw e.code=x.StreamNotEnabled,e}return this.streamBuffer}markClosed(e){if(this.closed)return;this.closeUnsolicitedTurn("closed"),e={deleteRecord:e.deleteRecord||this.deleteRecordIntent},this.closing=!0,this.closed=!0,this.cancelIdleTimer(),this.cancelOrphanTimer(),this.extensionCommandsUnsub&&(this.extensionCommandsUnsub(),this.extensionCommandsUnsub=void 0);for(let o of[...this.inFlightExtensionDispatches.keys()])this.cancelExtensionDispatch(o,"abandoned");this.currentEntry?.kind==="user"&&!this.recentlyTerminal.has(this.currentEntry.messageId)&&this.broadcastTurnComplete(this.currentEntry.clientId,{stopReason:"interrupted"},this.currentEntry.messageId,this.originatorNeedsTurnComplete(this.currentEntry)),this.currentEntry=void 0;let n=this.promptQueue;this.promptQueue=[];for(let o of n){o.cancelled=!0,o.kind==="user"&&this.broadcastQueueRemoved(o.messageId,"abandoned");let i=this.pendingTurnNotifiers.get(o.messageId);i&&(this.pendingTurnNotifiers.delete(o.messageId),oo(i,{sessionId:this.sessionId,messageId:i.originalMessageId,stopReason:"cancelled",deliveredAt:Date.now(),...o.messageId!==i.originalMessageId?{amendedTo:o.messageId}:{}}));try{o.resolve({stopReason:"cancelled"})}catch{}}this.notifyChain("session.closed",{}),this.toolCompletionSeen.clear(),this.toolCallKind.clear(),this.filesEditedSeen.clear(),this.openToolCalls.clear();let r=this.sessionId;this.queueWriteChain=this.queueWriteChain.catch(()=>{}).then(()=>Ad(r).catch(()=>{}));for(let o of this.clients.values())o.connection.notify("hydra-acp/session/closed",{sessionId:this.sessionId}).catch(()=>{});if(this.clients.clear(),this.streamBuffer!==void 0){let o=this.streamBuffer,i=this.streamFilePath;this.streamBuffer=void 0,this.streamFilePath=void 0,o.close(),i!==void 0&&o.drainFileWrites().then(()=>Nd.unlink(i).catch(()=>{}))}for(let o of this.closeHandlers)o(e)}get lastActivityAt(){return this.lastRecordedAt}setAttentionFlag(e,t,n){this._setAttentionFlag(e,t,n,!0)}_setAttentionFlag(e,t,n,r){let o=`${e}::${t}`,i=this.attentionFlags.get(o);if(i){if(JSON.stringify(i.payload)===JSON.stringify(n))return;this.attentionFlags.set(o,{...i,payload:n,raisedAt:i.raisedAt})}else this.attentionFlags.set(o,{source:e,reason:t,raisedAt:Date.now(),payload:n});r&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}clearAttentionFlag(e,t){this._clearAttentionFlag(e,t,!0)}_clearAttentionFlag(e,t,n){let r=`${e}::${t}`;this.attentionFlags.delete(r)&&n&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}listAttentionFlags(){return Array.from(this.attentionFlags.values()).sort((e,t)=>e.raisedAt-t.raisedAt)}listAttentionFlagsBySource(e){return this.listAttentionFlags().filter(t=>t.source===e)}onAttentionFlagsChange(e){this.attentionFlagsChangeHandlers.push(e)}fireAttentionFlagsChange(){let e=this.listAttentionFlags();for(let t of this.attentionFlagsChangeHandlers)try{t(e)}catch{}}broadcastAttentionUpdated(){for(let e of this.clients.values())e.connection.notify("hydra-acp/session/attention_updated",{sessionId:this.sessionId,flags:this.listAttentionFlags()}).catch(()=>{})}scheduleIdleCheck(){if(this.closed||this.idleTimeoutMs<=0)return;let e=this.lastActivityAt+this.idleTimeoutMs;this.armIdleTimer(Math.max(0,e-Date.now()))}armIdleTimer(e){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{this.idleTimer=void 0,this.checkIdle()},e),typeof this.idleTimer.unref=="function"&&this.idleTimer.unref()}checkIdle(){if(this.closed||this.idleTimeoutMs<=0)return;if(this.hasWorkInFlight){this.armIdleTimer(this.idleTimeoutMs);return}let e=Date.now()-this.lastActivityAt;if(e<this.idleTimeoutMs){this.armIdleTimer(this.idleTimeoutMs-e);return}let t=this.firstPromptSeeded?{deleteRecord:!1}:{deleteRecord:!0},n=Math.round(e/1e3);this.logger?.info(`session ${this.sessionId} idle timeout fired after ${n}s (window=${Math.round(this.idleTimeoutMs/1e3)}s) \u2014 closing`),this.close(t).catch(()=>{})}cancelIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=void 0),this.disposeIdleHandlers()}scheduleOrphanCheck(){this.closed||this.orphanTimeoutMs<=0||this.clients.size>0||this._interactive===!0||this.armOrphanTimer(this.orphanTimeoutMs)}armOrphanTimer(e){this.orphanTimer&&clearTimeout(this.orphanTimer),this.orphanTimer=setTimeout(()=>{this.orphanTimer=void 0,this.checkOrphan()},e),typeof this.orphanTimer.unref=="function"&&this.orphanTimer.unref()}checkOrphan(){if(!this.closed&&!(this.clients.size>0||this._interactive===!0)){if(this.hasWorkInFlight){this.armOrphanTimer(this.orphanTimeoutMs);return}this.logger?.info(`session ${this.sessionId} orphan timeout fired after ${Math.round(this.orphanTimeoutMs/1e3)}s with no attached client and no prompt ever received \u2014 closing`),this.close({deleteRecord:!1,by:"reap-orphaned"}).catch(()=>{})}}cancelOrphanTimer(){this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=void 0)}get currentPromptDepth(){if(this.currentEntry?.kind==="user")return this.currentEntry.originator.depth??0}get hasWorkInFlight(){return this.turnStartedAt!==void 0||this.hasPermissionFlag||this.promptQueue.length>0||this.armedBackgroundTasks.length>0}onIdle(e,t){let n={fn:e,once:!!t?.once,debounceMs:t?.debounceMs??0};return this.idleHandlers.push(n),()=>{let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1),n.timer&&(clearTimeout(n.timer),n.timer=void 0)}}onceIdle(e){return this.onIdle(e,{once:!0})}dispatchIdle(){if(this.closed)return;if(!this.isQuiescedSync()){for(let n of this.idleHandlers)n.timer&&(clearTimeout(n.timer),n.timer=void 0);return}let t=[...this.idleHandlers];for(let n of t){if(n.debounceMs===0){if(n.once){let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1)}try{n.fn(this)}catch{}continue}n.timer&&(clearTimeout(n.timer),n.timer=void 0),n.timer=setTimeout(()=>{if(n.timer=void 0,!this.closed&&this.isQuiescedSync()){if(n.once){let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1)}try{n.fn(this)}catch{}}},n.debounceMs),typeof n.timer.unref=="function"&&n.timer.unref()}}disposeIdleHandlers(){for(let e of this.idleHandlers)e.timer&&(clearTimeout(e.timer),e.timer=void 0);this.idleHandlers.length=0}noteRecordedToolCall(e,t){if(e!=="session/update")return;let n=t?.update;if(n===void 0)return;let r=typeof n.toolCallId=="string"?n.toolCallId:"";if(r.length===0)return;let o=typeof n.title=="string"&&n.title!==""?n.title:void 0;if(n.sessionUpdate==="tool_call"){this.turnRanTool=!0,n.status!=="completed"&&n.status!=="failed"&&this.openToolCalls.set(r,{startedAt:Date.now(),...o!==void 0?{title:o}:{}});return}if(n.sessionUpdate!=="tool_call_update")return;if(n.status==="completed"||n.status==="failed"){this.openToolCalls.delete(r),this.disarmOpenToolCall(r);return}let i=this.openToolCalls.get(r);i!==void 0&&o!==void 0&&(i.title=o)}armOpenToolCalls(){let e=!1;for(let[t,n]of this.openToolCalls){if(this.armedTasks.has(t))continue;let r=this.toolLabels.get(t),o=r?.fromDescription===!0?r.label:Ug(n.title??r?.label??"").slice(0,yo);this.armedTasks.set(t,{label:o===""?"running tool":o,repeating:!1,armedAt:n.startedAt,openToolCall:!0}),e=!0}e&&this.onArmedTasksChanged()}disarmOpenToolCall(e){this.armedTasks.get(e)?.openToolCall===!0&&(this.armedTasks.delete(e),this.onArmedTasksChanged())}closeOpenToolCalls(e){if(this.openToolCalls.size===0||this.closed)return;let t=[...this.openToolCalls.keys()];this.openToolCalls.clear();for(let n of t)this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"tool_call_update",toolCallId:n,status:"failed",_meta:{[le]:{synthetic:!0,closedBy:e}}}});this.logger?.info(`session ${this.sessionId} closed ${t.length} open tool call(s) on ${e}`)}maybeEmitToolEdges(e){if(!e||typeof e!="object")return;let t=e.update;if(!t||typeof t!="object")return;let n=t,r=typeof n.sessionUpdate=="string"?n.sessionUpdate:"";if(r!=="tool_call"&&r!=="tool_call_update")return;let o=typeof n.toolCallId=="string"&&n.toolCallId.length>0?n.toolCallId:void 0;if(!o)return;let i=typeof n.kind=="string"?n.kind:void 0;this.toolCallKind.note(o,i);let a=this.toolCallKind.effective(o,i);if(a===ja&&Array.isArray(n.locations))for(let u of n.locations){if(!u||typeof u!="object")continue;let l=u.path;if(typeof l!="string"||l.length===0||this.filesEditedSeen.has(l))continue;this.filesEditedSeen.add(l);let p=u.line,f={path:l,toolCallId:o};typeof p=="number"&&(f.line=p),this.notifyChain("file.edited",f),this.reportIsolationBreach(l,o)}if(r!=="tool_call_update")return;let d=typeof n.status=="string"?n.status:void 0;if(d!=="completed"&&d!=="failed"||this.toolCompletionSeen.has(o))return;this.toolCompletionSeen.set(o,d);let c={toolCallId:o,status:d};a&&(c.kind=a),n.content!==void 0&&(c.content=n.content),Array.isArray(n.locations)&&(c.locations=n.locations),this.notifyChain("tool.completed",c)}notifyChain(e,t){let n=`lifecycle:${e}`;for(let r of this.transformChain)r.intercepts.has(n)&&r.connection.notify("hydra-acp/transformer/session_event",{event:e,sessionId:this.sessionId,payload:t}).catch(()=>{})}rewriteForClient(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(typeof t.sessionId=="string"&&t.sessionId!==this.sessionId)return{...t,sessionId:this.sessionId}}return e}recordAndBroadcast(e,t,n){let r=this.rewriteForClient(t),o=!An(e,r),i=o?am(e,r):r,a=Date.now(),d=o?this.lastSeq=Math.max(this.lastSeq+1,a):void 0,c=o?We(Be(i,a),d):i;if(o){this.noteRecordedToolCall(e,i);let u={method:e,params:i,recordedAt:a,seq:d};if(this.lastRecordedAt=u.recordedAt,this.appendCount+=1,this.historyStore){let l=this.historyStore;l.append(this.sessionId,u).catch(()=>{}),this.appendCount>=this.compactEvery&&(this.appendCount=0,l.compact(this.sessionId,this.historyMaxEntries).catch(()=>{}))}for(let l of this.broadcastHandlers)try{l(u)}catch{}this.scheduleIdleCheck(),this.dispatchIdle()}this.updatedAt=Date.now();for(let u of this.clients.values())n&&u.clientId===n||u.connection.notify(e,c).catch(()=>{})}async requestPermissionFromClients(e){return this.handlePermissionRequest(e)}async handlePermissionRequest(e){let t=[...this.clients.values()];if(t.length===0)throw fe(new Error("no clients attached to handle permission request"),x.PermissionDenied);let n=this.rewriteForClient(e),r=Pd(n),o=Ge(),{toolCall:i,options:a}=n??{};return new Promise((d,c)=>{let u=!1,l=[],p=0,f,h=this.sessionId,k=y=>{u||(u=!0,this.clearAttentionFlag("daemon",`permission:${o}`),this.permissionCallbacks.delete(o),y())},m=y=>y?.code===x.MethodNotFound;function g(y){if(u)return;let w=y.connection.request("session/request_permission",n);l.push({client:y}),p++,w.then(v=>{p--,k(()=>{let S=lm({toolCallId:r,result:v,resolver:y});for(let b of l)b.client.clientId!==y.clientId&&b.client.connection.notify("session/update",{sessionId:h,update:S}).catch(()=>{});d(v)})}).catch(v=>{if(p--,m(v)||(f=v),p===0&&!u){let S=f??fe(new Error("no client handled permission request"),x.PermissionDenied);k(()=>c(S))}})}this.setAttentionFlag("daemon",`permission:${o}`,{kind:"permission",toolCall:i??null,options:a??null}),this.permissionCallbacks.set(o,g);for(let y of t)g(y)})}async enqueuePrompt(e,t){return new Promise((n,r)=>{let o={kind:"internal",messageId:Ge(),label:e,enqueuedAt:Date.now(),cancelled:!1,task:t,resolve:n,reject:r};this.promptQueue.push(o),this.drainQueue()})}async enqueueUserPrompt(e,t,n,r,o){let i=(t??{}).prompt??[],a={clientId:e.clientId};e.clientInfo?.name&&(a.name=e.clientInfo.name),e.clientInfo?.version&&(a.version=e.clientInfo.version),r?.fromSession&&(a.fromSession=r.fromSession),r?.fromSessionTitle&&(a.fromSessionTitle=r.fromSessionTitle),r?.fromLabel&&(a.fromLabel=r.fromLabel),r?.depth!==void 0&&(a.depth=r.depth);let d=this.parseQueuePosition(t);return new Promise((c,u)=>{let l={kind:"user",messageId:n,originator:a,clientId:e.clientId,prompt:i,enqueuedAt:Date.now(),cancelled:!1,resolve:c,reject:u};o?.steerOriginated===!0&&(l.wasSteer=!0);let p=this.insertEntryAt(l,d);this.persistRewrite(),this.broadcastQueueAdded(l,{position:p}),this.drainQueue()})}promptCarriesSentBy(e){if(!e||typeof e!="object")return!1;let t=e._meta;if(!t||typeof t!="object"||Array.isArray(t))return!1;let n=t[le];if(!n||typeof n!="object"||Array.isArray(n))return!1;let r=n.sentBy;return!!r&&typeof r=="object"}parseQueuePosition(e){if(!e||typeof e!="object")return"tail";let t=e._meta;if(!t||typeof t!="object"||Array.isArray(t))return"tail";let n=t["hydra-acp"];if(!n||typeof n!="object"||Array.isArray(n))return"tail";let r=n.queuePosition;if(r==="head"||r==="tail")return r;if(r&&typeof r=="object"&&!Array.isArray(r)){let o=r.afterMessageId;if(typeof o=="string"&&o.length>0)return{afterMessageId:o}}return"tail"}insertEntryAt(e,t){let n=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled?1:0;if(t==="head")return this.promptQueue.unshift(e),n;if(typeof t=="object"){let r=t.afterMessageId,o=this.promptQueue.findIndex(i=>i.messageId===r);if(o>=0)return this.promptQueue.splice(o+1,0,e),n+o+1}return this.promptQueue.push(e),n+this.promptQueue.length-1}persistRewrite(){let e=[];for(let n of this.promptQueue)n.kind!=="user"||n.cancelled||e.push(this.persistedFromEntry(n));let t=this.sessionId;this.queueWriteChain=this.queueWriteChain.catch(()=>{}).then(()=>In(t,e).catch(()=>{}))}persistedFromEntry(e){return{messageId:e.messageId,originator:{clientInfo:{...e.originator.name!==void 0?{name:e.originator.name}:{},...e.originator.version!==void 0?{version:e.originator.version}:{}}},prompt:e.prompt,enqueuedAt:e.enqueuedAt}}async drainQueue(){if(!this.promptInFlight){this.promptInFlight=!0,await new Promise(e=>setImmediate(e));try{for(;this.promptQueue.length>0&&!this.closing;){let e=this.promptQueue[0];if(e?.kind==="user"&&(await this.holdForUnsolicitedTurn(e),this.closing))break;let t=this.promptQueue.shift();if(!t)break;if(!t.cancelled){this.currentEntry=t,t.kind==="user"&&this.persistRewrite(),t.kind==="user"&&this.broadcastQueueRemoved(t.messageId,"started");try{let n=await this.runQueueEntry(t);t.resolve(n),await new Promise(r=>setImmediate(r))}catch(n){t.reject(n)}finally{this.currentEntry=void 0}}}}finally{this.promptInFlight=!1,this.supersededAutonomousTurn=void 0,this.dispatchIdle()}}}async runQueueEntry(e){if(e.kind==="internal")return this.closeUnsolicitedTurn("superseded",`internal:${e.label}`),e.task();this.broadcastPromptReceived(e);let t=It(e.prompt).replace(/\s+$/,""),n=!t.includes(`
102
- `)&&t.startsWith("/")?t.split(/\s+/)[0]??"":"",r=n.startsWith("/")?n.slice(1):"",o=r.length>0&&this.aliasableBareVerbs().has(r);if(n==="/model"||n==="/mode"||n==="/sessions"||n==="/help"||n==="/hydra"||o){let d;try{if(n==="/sessions")d=await this.handleSessionsCommand();else if(n==="/help")d=await this.handleHelpCommand();else if(n==="/mode")d=await this.handleModeCommand(t);else if(n==="/model")d=await this.handleModelCommand(t);else if(o){let c=t.slice(n.length).trim(),u=c?`/hydra ${r} ${c}`:`/hydra ${r}`;d=await this.handleSlashCommand(u,e.messageId)}else d=await this.handleSlashCommand(t,e.messageId)}catch(c){throw this.closed||this.broadcastTurnComplete(e.clientId,{stopReason:"error"},e.messageId,this.originatorNeedsTurnComplete(e),Ed(c)),this.clearAmendIfMatches(e.messageId),c}return this.closed||this.broadcastTurnComplete(e.clientId,d,e.messageId,this.originatorNeedsTurnComplete(e)),this.clearAmendIfMatches(e.messageId),d}if(this.clearRollbackBreadcrumbHook)try{this.clearRollbackBreadcrumbHook()}catch{}let i=e.prompt;n&&this.agentAdvertisedCommands.length>0&&!this.agentKnowsSlashCommand(n)&&(i=wo(e.prompt,gm));let a;this.agentTurnInFlight=!0;try{i=this.applyWorkspacePromptRewrite(i),a=await this.dispatchPrompt(e,i)}catch(d){if(this.forceCancelling)return this.clearAmendIfMatches(e.messageId),{stopReason:"cancelled"};throw this.closed||this.broadcastTurnComplete(e.clientId,{stopReason:"error"},e.messageId,this.originatorNeedsTurnComplete(e),Ed(d)),this.clearAmendIfMatches(e.messageId),d}finally{this.agentTurnInFlight=!1}return this.closed||this.broadcastTurnComplete(e.clientId,a,e.messageId,this.originatorNeedsTurnComplete(e)),this.clearAmendIfMatches(e.messageId),a}async dispatchPrompt(e,t){let n=()=>this.awaitPromptResponse(this.forwardRequest("session/prompt",{sessionId:this.sessionId,prompt:t},e.emitterName?new Set([e.emitterName]):new Set,e.chainStartIdx??0));try{return await n()}catch(r){if(this.loadExistingAgentSession&&Vg(r))return this.logger?.warn(`agent ${this.agentId} no longer knows upstream session ${this.upstreamSessionId} for ${this.sessionId}; reloading it onto a fresh process and retrying the prompt once`),await this.reloadUpstreamAfterAgentLoss(),await n();if(!Kg(r)||this.turnRanTool||(this.logger?.warn(`agent ${this.agentId} hit a transient auth failure for ${this.sessionId}; retrying the prompt once in ${Td}ms`),await new Promise(o=>setTimeout(o,Td)),e.cancelled))throw r;return await n()}}clearAmendIfMatches(e){this.amendInProgress?.cancelledMessageId===e&&(this.amendInProgress=void 0)}},xd=2e3;function Ed(s){let e=s?.message;if(!(typeof e!="string"||e.trim().length===0))return e.length>xd?`${e.slice(0,xd)}...`:e}var Jg=["session not found","the claude agent session has ended"];function Dd(s){let e=s;if(e?.code!==x.InternalError)return;let t=e.data?.details;return`${typeof e.message=="string"?e.message:""} ${typeof t=="string"?t:""}`.toLowerCase()}function Vg(s){let e=Dd(s);return e!==void 0&&Jg.some(t=>e.includes(t))}var Gg=["failed to refresh oauth token"],Td=6e4;function Kg(s){let e=Dd(s);return e!==void 0&&Gg.some(t=>e.includes(t))}function fe(s,e){return s.code=e,s}var Qg=new Set(["session_info_update","_hydra_current_model_update","current_mode_update","available_commands_update","_hydra_available_modes_update","usage_update","config_option_update","_hydra_compaction"]);function Yg(s,e,t){return t?.run_in_background===!0||t?.background===!0?!1:e?.toolName==="Monitor"||s==="Monitor"||typeof e?.toolResponse?.taskId=="string"}function Xg(s){return typeof s!="string"?void 0:/Command running in background with ID: ([A-Za-z0-9_-]+)/.exec(s)?.[1]}function Zg(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.metadata;if(!e||typeof e!="object")return;let{status:t,shellID:n}=e;return t==="running"&&typeof n=="string"&&n!==""?n:void 0}function em(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.claudeCode;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,n={};return t.toolName!==void 0&&(n.toolName=t.toolName),t.toolResponse&&typeof t.toolResponse=="object"&&(n.toolResponse=t.toolResponse),n}function An(s,e){if(s!=="session/update")return!1;let n=(e??{}).update?.sessionUpdate;return typeof n=="string"&&Qg.has(n)}function tm(s,e){if(s.length!==e.length)return!1;for(let t=0;t<s.length;t++)if(s[t]?.name!==e[t]?.name||s[t]?.description!==e[t]?.description)return!1;return!0}function nm(s,e){if(s.length!==e.length)return!1;for(let t=0;t<s.length;t++)if(s[t]?.id!==e[t]?.id||s[t]?.name!==e[t]?.name||s[t]?.description!==e[t]?.description)return!1;return!0}function sm(s,e){if(s.length!==e.length)return!1;for(let t=0;t<s.length;t++)if(s[t]?.modelId!==e[t]?.modelId||s[t]?.name!==e[t]?.name||s[t]?.description!==e[t]?.description)return!1;return!0}function Cn(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object"||Array.isArray(t))continue;let n=t,r=typeof n.modelId=="string"&&n.modelId.trim()||typeof n.value=="string"&&n.value.trim()||typeof n.id=="string"&&n.id.trim()||void 0;if(!r)continue;let o={modelId:r};typeof n.name=="string"&&n.name.length>0&&(o.name=n.name),typeof n.description=="string"&&n.description.length>0&&(o.description=n.description),e.push(o)}return e}function bs(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object"||Array.isArray(t))continue;let n=t,r=typeof n.value=="string"&&n.value.trim()||typeof n.id=="string"&&n.id.trim()||void 0;if(!r)continue;let o={id:r};typeof n.name=="string"&&n.name.length>0&&(o.name=n.name),typeof n.description=="string"&&n.description.length>0&&(o.description=n.description),e.push(o)}return e}function vo(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object"||Array.isArray(t))continue;let n=t,r=typeof n.value=="string"&&n.value.trim()||typeof n.id=="string"&&n.id.trim()||void 0;if(!r)continue;let o=typeof n.name=="string"&&n.name.trim()?n.name.trim():r,i={value:r,name:o};typeof n.description=="string"&&n.description.length>0&&(i.description=n.description),e.push(i)}return e}function rm(s){let t=(s??{}).update??{};if(t.sessionUpdate!=="_hydra_available_modes_update")return null;let n=t.availableModes;if(!Array.isArray(n))return[];let r=[];for(let o of n){if(!o||typeof o!="object")continue;let i=o;if(typeof i.id!="string"||i.id.length===0)continue;let a={id:i.id};typeof i.name=="string"&&(a.name=i.name),typeof i.description=="string"&&(a.description=i.description),r.push(a)}return r}function om(s,e){let n=(e??{}).update??{},r=n.sessionUpdate;if(r==="agent_message_chunk"){let o=n.content??{};typeof o.text=="string"&&(s.chunks.push(o.text),s.messageChars+=o.text.length);return}if(r==="agent_thought_chunk"){let o=n.content??{};typeof o.text=="string"&&(s.thinkingChars+=o.text.length);return}if(r==="tool_call"){s.toolCalls++;return}if(r==="usage_update"){typeof n.used=="number"&&(s.lastUsed=n.used),typeof n.size=="number"&&(s.lastSize=n.size);return}}function im(s){let t=(s??{}).update??{};if(t.sessionUpdate!=="available_commands_update")return null;let n=t.availableCommands??t.commands;if(!Array.isArray(n))return[];let r=[];for(let o of n){if(!o||typeof o!="object")continue;let i=o;if(typeof i.name!="string"||i.name.length===0)continue;let a={name:i.name};typeof i.description=="string"&&(a.description=i.description),r.push(a)}return r}function am(s,e){if(s!=="session/update"||!e||typeof e!="object")return e;let t=e;return!t.update||typeof t.update!="object"||Array.isArray(t.update)||typeof t.update.messageId=="string"?e:{...e,update:{...t.update,messageId:Ge()}}}function dm(s,e){if(s.length<=e)return s;let t=s.length-e;for(let n=t;n>=0;n--)if(s[n]?.params?.update?.sessionUpdate==="prompt_received")return s.slice(n);return s.slice(t)}function cm(s,e){for(let t=s.length-1;t>=0;t--)if(s[t]?.seq===e)return t;return-1}function um(s,e){for(let t=s.length-1;t>=0;t--){let n=s[t];if(!n||n.method!=="session/update")continue;if(n.params?.update?.messageId===e)return t}return-1}function Pd(s){if(!s||typeof s!="object")return;let e=s.toolCall;if(!e||typeof e!="object")return;let t=e.toolCallId;return typeof t=="string"?t:void 0}function lm(s){let e=fm(s.result),t={sessionUpdate:"permission_resolved"};return s.toolCallId!==void 0&&(t.toolCallId=s.toolCallId),e&&(t.outcome=e,e.kind==="selected"&&typeof e.optionId=="string"&&(t.chosenOptionId=e.optionId)),t.resolvedBy=pm(s.resolver),t}function fm(s){if(!s||typeof s!="object")return;let e=s.outcome;if(!e||typeof e!="object")return;let t=e.kind;if(typeof t!="string")return;let n={kind:t},r=e.optionId;typeof r=="string"&&(n.optionId=r);let o=e.reason;return typeof o=="string"&&(n.reason=o),n}function pm(s){let e={clientId:s.clientId};return s.clientInfo?.name&&(e.name=s.clientInfo.name),s.clientInfo?.version&&(e.version=s.clientInfo.version),e}function It(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?e.text:"").join(""):""}var gm="\u200B";function Md(s,e){return s.map(t=>{if(t&&typeof t=="object"&&typeof t.text=="string"){let n=t;return{...n,text:e(n.text)}}return t})}function wo(s,e){let t=s.findIndex(o=>o&&typeof o=="object"&&typeof o.text=="string");if(t<0)return s;let n=s[t],r=[...s];return r[t]={...n,text:`${e}${n.text}`},r}function ko(s){return s==="session/prompt"?{stopReason:"stopped"}:{}}function mm(s){return s==="session/request_permission"?{outcome:{outcome:"cancelled"}}:{}}function _d(s){let e=s.name&&s.name!==s.id?`${s.id} (${s.name}) \u2014 \u25B6 ${s.currentValue}`:`${s.id} \u2014 \u25B6 ${s.currentValue}`;if(s.options.length===0)return e;let t=Math.max(...s.options.map(r=>r.value.length)),n=s.options.map(r=>{let o=r.value===s.currentValue?"\u25B6":"\xB7",i=r.name&&r.name!==r.value,a=i?r.value.padEnd(t):r.value;return i?` ${o} ${a} ${r.name}`:` ${o} ${a}`});return`${e}
99
+ `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}if(n==="model"){if(c!==this.currentModel){let l=await this.forwardModelChange(c);this.applyAgentConfigOptionResponse(l,"model")}return this.applyModelChange(c),{stopReason:"end_turn"}}if(n==="mode")return c!==this.currentMode&&await this.forwardRequest("session/set_mode",{sessionId:this.sessionId,modeId:c}),this.applyModeChange(c),{stopReason:"end_turn"};if(n==="agent")return c!==this.agentId&&await this.runAgentCommandInline(c),{stopReason:"end_turn"};let u=await this.forwardRequest("session/set_config_option",{sessionId:this.sessionId,configId:n,value:c});return this.applyAgentConfigOptionResponse(u,n)&&this.broadcastConfigOptions(),{stopReason:"end_turn"}}runTitleCommand(e){return this.enqueuePrompt("title",()=>this.runTitleCommandInline(e))}async runTitleCommandInline(e){return e?(this.setTitle(e),{stopReason:"end_turn"}):(this.scheduleSynopsisHook?.(),{stopReason:"end_turn"})}async runInternalPrompt(e){if(this.internalPromptCapture)throw new Error("internal prompt already in flight");let t={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};this.internalPromptCapture=t;try{return await this.agent.connection.request("session/prompt",{sessionId:this.upstreamSessionId,prompt:[{type:"text",text:e}]}),t.chunks.join("")}finally{this.internalPromptCapture=void 0}}setAgent(e){return this.runAgentCommandInline(e)}async runAgentCommandInline(e){if(e==="status")return this.runAgentStatusCommandInline();let t=e;if(!t)throw fe(new Error("/hydra agent requires an agent id"),R.InvalidParams);let r=(this.resolveAgentIdHook?await this.resolveAgentIdHook(t):void 0)??t;if(r===this.agentId)throw fe(new Error(`already on agent ${r}`),R.InvalidParams);if(!this.scheduleCompactionHook)return this.emitExtensionReply("agent switching not configured for this session"),{stopReason:"end_turn"};this.scheduleCompactionHook({targetAgentId:r});let o=this.agentTurnInFlight||this.unsolicitedTurn!==void 0;return this.emitExtensionReply(o?`Agent switch to ${r} scheduled. A turn is still in flight \u2014 the rotation lands on the next idle edge; cancel the turn to make that happen now.`:`Agent switch to ${r} scheduled. The session will rotate to ${r} once synthesis completes.`),{stopReason:"end_turn"}}async runAgentStatusCommandInline(){let e=await this.getPendingAgentSwapHook?.();return e?(this.emitExtensionReply(`Agent switch to ${e} pending \u2014 will rotate on the next idle edge.`),{stopReason:"end_turn"}):(this.emitExtensionReply("No agent switch pending."),{stopReason:"end_turn"})}async runKillCommand(){return await this.close({deleteRecord:!1,by:"/hydra kill"}),{stopReason:"end_turn"}}runRestartCommand(){return this.enqueuePrompt("restart",()=>this.runRestartCommandInline())}async runRestartCommandInline(){if(!this.spawnReplacementAgent)throw fe(new Error("agent restart not configured for this session"),R.InternalError);return await this.respawnAgent(),{stopReason:"end_turn"}}runCompactCommand(e){return this.enqueuePrompt("compact",()=>this.runCompactCommandInline(e))}async runCompactCommandInline(e){return e==="status"?this.runCompactStatusCommandInline():this.scheduleCompactionHook?(this.scheduleCompactionHook(),this.emitExtensionReply("Compaction scheduled. The session will rotate to a fresh upstream once summarization completes."),{stopReason:"end_turn"}):(this.emitExtensionReply("compaction scheduling not configured for this session"),{stopReason:"end_turn"})}async runCompactStatusCommandInline(){let e=await this.getCompactionStateHook?.(),t=this._summarizedThroughEntry,n=await this.getUpstreamGenerationsHook?.()??[],r=vd(n,t),o=bd(r);if(e==null&&t==null&&o.length===0)return this.emitExtensionReply("This session has never been compacted."),{stopReason:"end_turn"};let i=[];return e==null?i.push(`No compaction in progress. Last summarized through entry: ${t??0}`):(i.push(`Compaction state: ${e.status}${e.iter!=null?` (iteration ${e.iter})`:""}`,`Summarized through entry: ${t??0}`,`Pending attempts: ${e.attempts??0}`),e.lastError!==void 0&&i.push(`Last error: ${e.lastError}`)),i.push(`Current upstream: ${this.upstreamSessionId}`),o.length>0&&i.push("",...o),this.emitExtensionReply(i.join(`
100
+ `)),{stopReason:"end_turn"}}runUncompactCommand(){return this.enqueuePrompt("uncompact",()=>this.runUncompactCommandInline())}async runWorkspaceCommand(e){if(!this.workspaceHook)return this.emitExtensionReply("Workspaces are not available on this session (no workspace hook configured)."),{stopReason:"end_turn"};let[t="status",...n]=e.split(/\s+/).filter(d=>d.length>0);if(!xd.includes(t))return this.emitExtensionReply(`Unknown workspace verb "${t}". Use one of: ${xd.join(", ")}.`),{stopReason:"end_turn"};let r=n.filter(d=>d.startsWith("--")),o=r.filter(d=>d!=="--clean"&&d!=="--deep");if(o.length>0)return this.emitExtensionReply(`Unknown workspace flag(s) ${o.join(", ")}. Supported: --clean (start), --deep (clean).`),{stopReason:"end_turn"};let i={clean:r.includes("--clean"),deep:r.includes("--deep")};if(i.clean&&t!=="start")return this.emitExtensionReply(`--clean applies to \`start\`, not to \`${t}\`.`),{stopReason:"end_turn"};if(i.deep&&t!=="clean")return this.emitExtensionReply(`--deep applies to \`clean\`, not to \`${t}\`.`),{stopReason:"end_turn"};let a=n.filter(d=>!d.startsWith("--")).join(" ").trim();try{let d=await this.workspaceHook(t,a.length>0?a:void 0,i);this.emitExtensionReply(d)}catch(d){this.emitExtensionReply(`Workspace ${t} failed: ${d instanceof Error?d.message:String(d)}`)}return{stopReason:"end_turn"}}async runUncompactCommandInline(){if(!this.uncompactHook)return this.emitExtensionReply("Rollback not available: uncompact hook not configured for this session."),{stopReason:"end_turn"};try{await this.uncompactHook(),this.emitExtensionReply("Rolled back to pre-compaction upstream. The session is now using the previous agent context.")}catch(e){this.emitExtensionReply(`Rollback failed: ${e instanceof Error?e.message:String(e)}`)}return{stopReason:"end_turn"}}runForkCommand(e){return this.enqueuePrompt("fork",()=>this.runForkCommandInline(e,void 0))}async findMessageIdBefore(e){if(!this.historyStore)return;let t=await this.historyStore.load(this.sessionId),n;for(let r of t){if(r.method!=="session/update")continue;let i=r.params?.update?.messageId;if(typeof i=="string"){if(i===e)return n;n=i}}}async runForkCommandInline(e,t){if(!this.forkHook)return this.emitExtensionReply("Fork not configured for this session."),{stopReason:"end_turn"};let n=(e??"").trim(),r=n.match(/^--verbatim(?:\s+([\s\S]*))?$/),o=r?"verbatim":void 0,i=(r?r[1]??"":n).trim();try{let a={};if(o&&(a.mode=o),i!==""&&(a.prompt=i),t&&this.historyStore){let u=await this.findMessageIdBefore(t).catch(()=>{});u&&(a.forkAt=u)}let c=(await this.forkHook(Object.keys(a).length>0?a:void 0)).sessionId.replace(/^hydra_session_/,"");this.emitExtensionReply(i!==""?`Forked to [\`${c}\`](hydra://sessions/${c}) and sent the prompt.`:`Forked to [\`${c}\`](hydra://sessions/${c}).`)}catch(a){this.emitExtensionReply(`Fork failed: ${a instanceof Error?a.message:String(a)}`)}return{stopReason:"end_turn"}}escalateUnresponsiveCancel(){this.cancelReopenStreak=0,this.logger?.warn(`session ${this.sessionId} agent ${this.agentId} reopened an unsolicited turn right after cancel ${s.UNSOLICITED_REOPEN_LIMIT} times in a row; forcing a restart`),this.broadcastQueueNotification("hydra-acp/cancel_failed",{sessionId:this.sessionId,reason:"unresponsive",message:`${this.agentId} kept resuming after repeated cancels; restarting the agent`}),this.forceCancel().catch(e=>{this.logger?.warn(`session ${this.sessionId} forceCancel after unresponsive-cancel escalation failed: ${e instanceof Error?e.message:String(e)}`)})}async forceCancel(){if(this.closed||this.closing)throw fe(new Error("session is closing"),R.SessionClosing);return this.lastCancelAt=0,this.forceCancelling=!0,await this.close({deleteRecord:!1,by:"force-cancel"}),{stopReason:"cancelled"}}async rewind(e,t,n={}){let r=()=>this.promptInFlight&&!n.afterCurrentTurn||this.promptQueue.length>0?"the session is busy; wait for the current turn and queued prompts to finish, then try again":this.swapInFlight?"the session's agent is being replaced; try again in a moment":void 0,o=r()??await this.quiesceBlocker()??r();if(o!==void 0)throw fe(new Error(o),R.InvalidRequest);if(!this.spawnReplacementAgent)throw fe(new Error("agent restart not configured for this session"),R.InternalError);await this.enqueuePrompt("rewind",async()=>{this.swapInFlight=!0;try{if(!await t())return;await this.respawnAgent({rewind:!0})}finally{this.swapInFlight=!1}this.broadcastClientUpdate({sessionUpdate:"_hydra_history_truncated",keepThrough:e})})}runClearCommand(){if(!this.rewindHook)throw fe(new Error("clear not configured for this session"),R.InternalError);return this.rewindHook(null).catch(e=>{this.broadcastSyntheticText(`/hydra clear failed: ${e.message}`)}),Promise.resolve({stopReason:"end_turn"})}async respawnAgent(e={}){let t=this.spawnReplacementAgent,n=this.agentId,r=await this.buildSwitchTranscript(n,e.rewind?{intro:"You are continuing a conversation whose later turns were withdrawn by the user. Below is the transcript of what remains.",followup:"Each line is prefixed with its speaker. Treat this as context for the next user message; do not re-respond to earlier turns."}:void 0),o=this.currentModel,i=this.currentMode,a=await t({agentId:n,cwd:this.cwd,agentArgs:this.agentArgs,...this.forwardedEnv?{forwardedEnv:this.forwardedEnv}:{}});if(this.accumulateAndResetCost(),this.wireAgent(a.agent,{respawn:!0}),e.rewind){let c=await pt({agent:a.agent,upstreamSessionId:a.upstreamSessionId,persistedModel:o,agentReportedModel:a.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(c.result,"model"),await ft({agent:a.agent,upstreamSessionId:a.upstreamSessionId,persistedMode:i,agentReportedMode:a.initialMode,logger:this.logger}),a.agent.connection.drainBuffered("session/update")}let d=this.agent;this.agent=a.agent,this.upstreamSessionId=a.upstreamSessionId,this.agentMeta=a.agentMeta,this.agentCapabilities=a.agentCapabilities,this.resetModelVerb(a.modelVerb),this.agentAdvertisedCommands=[],this.broadcastMergedCommands(),e.rewind||(this.currentModel=a.initialModel,this.currentMode=a.initialMode),this.setAgentAdvertisedModels(a.initialModels??[]),this.setAgentAdvertisedModes(a.initialModes??[]),this.agentAdvertisedConfigOptions=a.initialConfigOptions??[],await this.retireAgent(d,"agent restart"),r&&await this.runInternalPrompt(r).catch(()=>{}),e.rewind||this.broadcastAgentSwitch(n,n),this.notifyAgentChange("respawnAgent","restart")}async buildSwitchTranscript(e,t){let n=[],r=await this.getHistorySnapshot();for(let c of r){if(c.method!=="session/update")continue;let l=(c.params??{}).update;if(!l||l._meta?.["hydra-acp"]?.synthetic)continue;let f=l.sessionUpdate;if(f==="prompt_received"){let h=At(l.prompt);h&&n.push({speaker:"user",text:h})}else if(f==="agent_message_chunk"){let k=l.content?.text;k&&n.push({speaker:`agent: ${e}`,text:k})}else if(f==="tool_call"||f==="tool_call_update"){let h=l.status,k=l.title;(h==="completed"||h==="failed")&&n.push({speaker:"tool",text:`${k??"?"} ${h}`})}}if(n.length===0)return"";let o=[],i;for(let c of n)i&&i.speaker===c.speaker?i.text+=c.text:(i&&o.push(`<${i.speaker}>: ${i.text.trim()}`),i={speaker:c.speaker,text:c.text});i&&o.push(`<${i.speaker}>: ${i.text.trim()}`);let a=t?.intro??`You are taking over this conversation from ${e}. Below is the transcript so far.`,d=t?.followup??`Each line is prefixed with its speaker. Continue from where ${e} left off, responding to the user's most recent message.`;return[a,d,"","--- begin transcript ---",...o,"--- end transcript ---"].join(`
101
+ `)}async seedFromImport(){await this.enqueuePrompt("seed:import",async()=>{let e=await this.buildSwitchTranscript(this.agentId,{intro:"You are continuing a conversation that was imported from another hydra. Below is the transcript so far.",followup:"Each line is prefixed with its speaker. Treat this as context for the next user message; do not re-respond to earlier turns."});e&&await this.runInternalPrompt(e).catch(()=>{})})}async seedFromFork(e){await this.enqueuePrompt("seed:fork",async()=>{let t=this.title??"(untitled)",n=[];if(this.historyStore)try{n=await this.historyStore.load(this.sessionId)}catch(o){this.logger?.warn(`seedFromFork: historyStore.load failed: ${o.message}`)}let r=mo({synopsis:e,title:t,tail:n,tailK:Og,tailFloor:Fg,watermark:this._summarizedThroughEntry,recallArmed:(this._summarizedThroughEntry??0)>0});if(this.internalPromptCapture)throw new Error("seedFromFork: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};try{await this.agent.connection.request("session/prompt",{sessionId:this.upstreamSessionId,prompt:[{type:"text",text:r}]});let o=this.internalPromptCapture;this.logger?.info(`seedFromFork: seed processed sessionId=${this.sessionId} seedChars=${r.length} toolCalls=${o.toolCalls} thinkingChars=${o.thinkingChars} messageChars=${o.messageChars}`)}finally{this.internalPromptCapture=void 0}})}broadcastAgentSwitch(e,t){this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",_meta:{"hydra-acp":{synthetic:!0,agentId:t,pendingAgentSwap:null}}}}),this.broadcastConfigOptions()}broadcastPendingAgentSwap(e){this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",_meta:{"hydra-acp":{synthetic:!0,pendingAgentSwap:e}}}})}hasStreamBuffer(){return this.streamBuffer!==void 0}get streamPath(){return this.streamFilePath}openStream(e){if(this.streamBuffer!==void 0)throw new Error(`stream buffer already open for session ${this.sessionId}`);let n=(e.mode??"memory")==="file"&&e.filePathFor!==void 0?e.filePathFor(this.sessionId):void 0,r={};e.capacityBytes!==void 0&&(r.capacityBytes=e.capacityBytes),n!==void 0&&(r.filePath=n),e.fileCapBytes!==void 0&&(r.fileCapBytes=e.fileCapBytes),r.onFileCapReached=()=>{this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_stream_truncated",...n!==void 0?{filePath:n}:{},fileCapBytes:e.fileCapBytes}})};let o=new ws(r);this.streamBuffer=o,this.streamFilePath=n;let i={capacityBytes:o.capacity};return n!==void 0&&(i.filePath=n),e.fileCapBytes!==void 0&&(i.fileCapBytes=e.fileCapBytes),i}streamWrite(e,t){let n=this.requireStreamBuffer();if(e.length>0){let r=Buffer.from(e,"base64");n.append(r)}return t===!0&&n.close(),{writeCursor:n.writeCursorPos}}async streamRead(e,t,n){let r=this.requireStreamBuffer(),o=Math.max(0,Math.min(t??zt,zt)),i=r.read(e,o);if(i.bytes.length===0&&i.eof!==!0&&n!==void 0&&n>0){let d=await r.waitForData(i.nextCursor,n);(d==="data"||d==="eof")&&(i=r.read(i.nextCursor,o))}let a={bytes:i.bytes.toString("base64"),nextCursor:i.nextCursor};return i.gap!==void 0&&(a.gap=i.gap),i.eof===!0&&(a.eof=!0),a}streamTail(e){let n=this.requireStreamBuffer().tail(e);return{bytes:n.bytes.toString("base64"),startCursor:n.startCursor,endCursor:n.endCursor,truncated:n.truncated}}streamHead(e){let n=this.requireStreamBuffer().head(e);return{bytes:n.bytes.toString("base64"),startCursor:n.startCursor,endCursor:n.endCursor,truncated:n.truncated}}async streamWaitFor(e,t){return this.requireStreamBuffer().waitForData(e,t)}streamGrep(e){return this.requireStreamBuffer().grep(e)}streamInfo(){let e=this.requireStreamBuffer();return{writeCursor:e.writeCursorPos,oldestAvailable:e.oldestAvailable,capacity:e.capacity,closed:e.isClosed}}requireStreamBuffer(){if(this.streamBuffer===void 0){let e=new Error(`session ${this.sessionId} has no stream buffer; POST /v1/sessions/:id/stdin/open first`);throw e.code=R.StreamNotEnabled,e}return this.streamBuffer}markClosed(e){if(this.closed)return;this.closeUnsolicitedTurn("closed"),e={deleteRecord:e.deleteRecord||this.deleteRecordIntent},this.closing=!0,this.closed=!0,this.cancelIdleTimer(),this.cancelOrphanTimer(),this.extensionCommandsUnsub&&(this.extensionCommandsUnsub(),this.extensionCommandsUnsub=void 0);for(let o of[...this.inFlightExtensionDispatches.keys()])this.cancelExtensionDispatch(o,"abandoned");this.currentEntry?.kind==="user"&&!this.recentlyTerminal.has(this.currentEntry.messageId)&&this.broadcastTurnComplete(this.currentEntry.clientId,{stopReason:"interrupted"},this.currentEntry.messageId,this.originatorNeedsTurnComplete(this.currentEntry)),this.currentEntry=void 0;let n=this.promptQueue;this.promptQueue=[];for(let o of n){o.cancelled=!0,o.kind==="user"&&this.broadcastQueueRemoved(o.messageId,"abandoned");let i=this.pendingTurnNotifiers.get(o.messageId);i&&(this.pendingTurnNotifiers.delete(o.messageId),ao(i,{sessionId:this.sessionId,messageId:i.originalMessageId,stopReason:"cancelled",deliveredAt:Date.now(),...o.messageId!==i.originalMessageId?{amendedTo:o.messageId}:{}}));try{o.resolve({stopReason:"cancelled"})}catch{}}this.notifyChain("session.closed",{}),this.toolCompletionSeen.clear(),this.toolCallKind.clear(),this.filesEditedSeen.clear(),this.openToolCalls.clear();let r=this.sessionId;this.queueWriteChain=this.queueWriteChain.catch(()=>{}).then(()=>Rd(r).catch(()=>{}));for(let o of this.clients.values())o.connection.notify("hydra-acp/session/closed",{sessionId:this.sessionId}).catch(()=>{});if(this.clients.clear(),this.streamBuffer!==void 0){let o=this.streamBuffer,i=this.streamFilePath;this.streamBuffer=void 0,this.streamFilePath=void 0,o.close(),i!==void 0&&o.drainFileWrites().then(()=>Hd.unlink(i).catch(()=>{}))}for(let o of this.closeHandlers)o(e)}get lastActivityAt(){return this.lastRecordedAt}setAttentionFlag(e,t,n){this._setAttentionFlag(e,t,n,!0)}_setAttentionFlag(e,t,n,r){let o=`${e}::${t}`,i=this.attentionFlags.get(o);if(i){if(JSON.stringify(i.payload)===JSON.stringify(n))return;this.attentionFlags.set(o,{...i,payload:n,raisedAt:i.raisedAt})}else this.attentionFlags.set(o,{source:e,reason:t,raisedAt:Date.now(),payload:n});r&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}clearAttentionFlag(e,t){this._clearAttentionFlag(e,t,!0)}_clearAttentionFlag(e,t,n){let r=`${e}::${t}`;this.attentionFlags.delete(r)&&n&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}listAttentionFlags(){return Array.from(this.attentionFlags.values()).sort((e,t)=>e.raisedAt-t.raisedAt)}listAttentionFlagsBySource(e){return this.listAttentionFlags().filter(t=>t.source===e)}onAttentionFlagsChange(e){this.attentionFlagsChangeHandlers.push(e)}fireAttentionFlagsChange(){let e=this.listAttentionFlags();for(let t of this.attentionFlagsChangeHandlers)try{t(e)}catch{}}broadcastAttentionUpdated(){for(let e of this.clients.values())e.connection.notify("hydra-acp/session/attention_updated",{sessionId:this.sessionId,flags:this.listAttentionFlags()}).catch(()=>{})}scheduleIdleCheck(){if(this.closed||this.idleTimeoutMs<=0)return;let e=this.lastActivityAt+this.idleTimeoutMs;this.armIdleTimer(Math.max(0,e-Date.now()))}armIdleTimer(e){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{this.idleTimer=void 0,this.checkIdle()},e),typeof this.idleTimer.unref=="function"&&this.idleTimer.unref()}checkIdle(){if(this.closed||this.idleTimeoutMs<=0)return;if(this.hasWorkInFlight){this.armIdleTimer(this.idleTimeoutMs);return}let e=Date.now()-this.lastActivityAt;if(e<this.idleTimeoutMs){this.armIdleTimer(this.idleTimeoutMs-e);return}let t=this.firstPromptSeeded?{deleteRecord:!1}:{deleteRecord:!0},n=Math.round(e/1e3);this.logger?.info(`session ${this.sessionId} idle timeout fired after ${n}s (window=${Math.round(this.idleTimeoutMs/1e3)}s) \u2014 closing`),this.close(t).catch(()=>{})}cancelIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=void 0),this.disposeIdleHandlers()}scheduleOrphanCheck(){this.closed||this.orphanTimeoutMs<=0||this.clients.size>0||this._interactive===!0||this.armOrphanTimer(this.orphanTimeoutMs)}armOrphanTimer(e){this.orphanTimer&&clearTimeout(this.orphanTimer),this.orphanTimer=setTimeout(()=>{this.orphanTimer=void 0,this.checkOrphan()},e),typeof this.orphanTimer.unref=="function"&&this.orphanTimer.unref()}checkOrphan(){if(!this.closed&&!(this.clients.size>0||this._interactive===!0)){if(this.hasWorkInFlight){this.armOrphanTimer(this.orphanTimeoutMs);return}this.logger?.info(`session ${this.sessionId} orphan timeout fired after ${Math.round(this.orphanTimeoutMs/1e3)}s with no attached client and no prompt ever received \u2014 closing`),this.close({deleteRecord:!1,by:"reap-orphaned"}).catch(()=>{})}}cancelOrphanTimer(){this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=void 0)}get currentPromptDepth(){if(this.currentEntry?.kind==="user")return this.currentEntry.originator.depth??0}get hasWorkInFlight(){return this.turnStartedAt!==void 0||this.hasPermissionFlag||this.promptQueue.length>0||this.armedBackgroundTasks.length>0}onIdle(e,t){let n={fn:e,once:!!t?.once,debounceMs:t?.debounceMs??0};return this.idleHandlers.push(n),()=>{let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1),n.timer&&(clearTimeout(n.timer),n.timer=void 0)}}onceIdle(e){return this.onIdle(e,{once:!0})}dispatchIdle(){if(this.closed)return;if(!this.isQuiescedSync()){for(let n of this.idleHandlers)n.timer&&(clearTimeout(n.timer),n.timer=void 0);return}let t=[...this.idleHandlers];for(let n of t){if(n.debounceMs===0){if(n.once){let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1)}try{n.fn(this)}catch{}continue}n.timer&&(clearTimeout(n.timer),n.timer=void 0),n.timer=setTimeout(()=>{if(n.timer=void 0,!this.closed&&this.isQuiescedSync()){if(n.once){let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1)}try{n.fn(this)}catch{}}},n.debounceMs),typeof n.timer.unref=="function"&&n.timer.unref()}}disposeIdleHandlers(){for(let e of this.idleHandlers)e.timer&&(clearTimeout(e.timer),e.timer=void 0);this.idleHandlers.length=0}noteRecordedToolCall(e,t){if(e!=="session/update")return;let n=t?.update;if(n===void 0)return;let r=typeof n.toolCallId=="string"?n.toolCallId:"";if(r.length===0)return;let o=typeof n.title=="string"&&n.title!==""?n.title:void 0;if(n.sessionUpdate==="tool_call"){this.turnRanTool=!0,n.status!=="completed"&&n.status!=="failed"&&this.openToolCalls.set(r,{startedAt:Date.now(),...o!==void 0?{title:o}:{}});return}if(n.sessionUpdate!=="tool_call_update")return;if(n.status==="completed"||n.status==="failed"){this.openToolCalls.delete(r),this.disarmOpenToolCall(r);return}let i=this.openToolCalls.get(r);i!==void 0&&o!==void 0&&(i.title=o)}armOpenToolCalls(){let e=!1;for(let[t,n]of this.openToolCalls){if(this.armedTasks.has(t))continue;let r=this.toolLabels.get(t),o=r?.fromDescription===!0?r.label:Wg(n.title??r?.label??"").slice(0,ko);this.armedTasks.set(t,{label:o===""?"running tool":o,repeating:!1,armedAt:n.startedAt,openToolCall:!0}),e=!0}e&&this.onArmedTasksChanged()}disarmOpenToolCall(e){this.armedTasks.get(e)?.openToolCall===!0&&(this.armedTasks.delete(e),this.onArmedTasksChanged())}closeOpenToolCalls(e){if(this.openToolCalls.size===0||this.closed)return;let t=[...this.openToolCalls.keys()];this.openToolCalls.clear();for(let n of t)this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"tool_call_update",toolCallId:n,status:"failed",_meta:{[le]:{synthetic:!0,closedBy:e}}}});this.logger?.info(`session ${this.sessionId} closed ${t.length} open tool call(s) on ${e}`)}maybeEmitToolEdges(e){if(!e||typeof e!="object")return;let t=e.update;if(!t||typeof t!="object")return;let n=t,r=typeof n.sessionUpdate=="string"?n.sessionUpdate:"";if(r!=="tool_call"&&r!=="tool_call_update")return;let o=typeof n.toolCallId=="string"&&n.toolCallId.length>0?n.toolCallId:void 0;if(!o)return;let i=typeof n.kind=="string"?n.kind:void 0;this.toolCallKind.note(o,i);let a=this.toolCallKind.effective(o,i);if(a===Ua&&Array.isArray(n.locations))for(let u of n.locations){if(!u||typeof u!="object")continue;let l=u.path;if(typeof l!="string"||l.length===0||this.filesEditedSeen.has(l))continue;this.filesEditedSeen.add(l);let p=u.line,f={path:l,toolCallId:o};typeof p=="number"&&(f.line=p),this.notifyChain("file.edited",f),this.reportIsolationBreach(l,o)}if(r!=="tool_call_update")return;let d=typeof n.status=="string"?n.status:void 0;if(d!=="completed"&&d!=="failed"||this.toolCompletionSeen.has(o))return;this.toolCompletionSeen.set(o,d);let c={toolCallId:o,status:d};a&&(c.kind=a),n.content!==void 0&&(c.content=n.content),Array.isArray(n.locations)&&(c.locations=n.locations),this.notifyChain("tool.completed",c)}notifyChain(e,t){let n=`lifecycle:${e}`;for(let r of this.transformChain)r.intercepts.has(n)&&r.connection.notify("hydra-acp/transformer/session_event",{event:e,sessionId:this.sessionId,payload:t}).catch(()=>{})}rewriteForClient(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(typeof t.sessionId=="string"&&t.sessionId!==this.sessionId)return{...t,sessionId:this.sessionId}}return e}recordAndBroadcast(e,t,n){let r=this.rewriteForClient(t),o=!Rn(e,r),i=o?cm(e,r):r,a=Date.now(),d=o?this.lastSeq=Math.max(this.lastSeq+1,a):void 0,c=o?We(Be(i,a),d):i;if(o){this.noteRecordedToolCall(e,i);let u={method:e,params:i,recordedAt:a,seq:d};if(this.lastRecordedAt=u.recordedAt,this.appendCount+=1,this.historyStore){let l=this.historyStore;l.append(this.sessionId,u).catch(()=>{}),this.appendCount>=this.compactEvery&&(this.appendCount=0,l.compact(this.sessionId,this.historyMaxEntries).catch(()=>{}))}for(let l of this.broadcastHandlers)try{l(u)}catch{}this.scheduleIdleCheck(),this.dispatchIdle()}this.updatedAt=Date.now();for(let u of this.clients.values())n&&u.clientId===n||u.connection.notify(e,c).catch(()=>{})}async requestPermissionFromClients(e){return this.handlePermissionRequest(e)}async handlePermissionRequest(e){let t=[...this.clients.values()];if(t.length===0)throw fe(new Error("no clients attached to handle permission request"),R.PermissionDenied);let n=this.rewriteForClient(e),r=_d(n),o=Ge(),{toolCall:i,options:a}=n??{};return new Promise((d,c)=>{let u=!1,l=[],p=0,f,h=this.sessionId,k=y=>{u||(u=!0,this.clearAttentionFlag("daemon",`permission:${o}`),this.permissionCallbacks.delete(o),y())},m=y=>y?.code===R.MethodNotFound;function g(y){if(u)return;let w=y.connection.request("session/request_permission",n);l.push({client:y}),p++,w.then(v=>{p--,k(()=>{let S=pm({toolCallId:r,result:v,resolver:y});for(let b of l)b.client.clientId!==y.clientId&&b.client.connection.notify("session/update",{sessionId:h,update:S}).catch(()=>{});d(v)})}).catch(v=>{if(p--,m(v)||(f=v),p===0&&!u){let S=f??fe(new Error("no client handled permission request"),R.PermissionDenied);k(()=>c(S))}})}this.setAttentionFlag("daemon",`permission:${o}`,{kind:"permission",toolCall:i??null,options:a??null}),this.permissionCallbacks.set(o,g);for(let y of t)g(y)})}async enqueuePrompt(e,t){return new Promise((n,r)=>{let o={kind:"internal",messageId:Ge(),label:e,enqueuedAt:Date.now(),cancelled:!1,task:t,resolve:n,reject:r};this.promptQueue.push(o),this.drainQueue()})}async enqueueUserPrompt(e,t,n,r,o){let i=(t??{}).prompt??[],a={clientId:e.clientId};e.clientInfo?.name&&(a.name=e.clientInfo.name),e.clientInfo?.version&&(a.version=e.clientInfo.version),r?.fromSession&&(a.fromSession=r.fromSession),r?.fromSessionTitle&&(a.fromSessionTitle=r.fromSessionTitle),r?.fromLabel&&(a.fromLabel=r.fromLabel),r?.depth!==void 0&&(a.depth=r.depth);let d=this.parseQueuePosition(t);return new Promise((c,u)=>{let l={kind:"user",messageId:n,originator:a,clientId:e.clientId,prompt:i,enqueuedAt:Date.now(),cancelled:!1,resolve:c,reject:u};o?.steerOriginated===!0&&(l.wasSteer=!0);let p=this.insertEntryAt(l,d);this.persistRewrite(),this.broadcastQueueAdded(l,{position:p}),this.drainQueue()})}promptCarriesSentBy(e){if(!e||typeof e!="object")return!1;let t=e._meta;if(!t||typeof t!="object"||Array.isArray(t))return!1;let n=t[le];if(!n||typeof n!="object"||Array.isArray(n))return!1;let r=n.sentBy;return!!r&&typeof r=="object"}parseQueuePosition(e){if(!e||typeof e!="object")return"tail";let t=e._meta;if(!t||typeof t!="object"||Array.isArray(t))return"tail";let n=t["hydra-acp"];if(!n||typeof n!="object"||Array.isArray(n))return"tail";let r=n.queuePosition;if(r==="head"||r==="tail")return r;if(r&&typeof r=="object"&&!Array.isArray(r)){let o=r.afterMessageId;if(typeof o=="string"&&o.length>0)return{afterMessageId:o}}return"tail"}insertEntryAt(e,t){let n=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled?1:0;if(t==="head")return this.promptQueue.unshift(e),n;if(typeof t=="object"){let r=t.afterMessageId,o=this.promptQueue.findIndex(i=>i.messageId===r);if(o>=0)return this.promptQueue.splice(o+1,0,e),n+o+1}return this.promptQueue.push(e),n+this.promptQueue.length-1}persistRewrite(){let e=[];for(let n of this.promptQueue)n.kind!=="user"||n.cancelled||e.push(this.persistedFromEntry(n));let t=this.sessionId;this.queueWriteChain=this.queueWriteChain.catch(()=>{}).then(()=>Cn(t,e).catch(()=>{}))}persistedFromEntry(e){return{messageId:e.messageId,originator:{clientInfo:{...e.originator.name!==void 0?{name:e.originator.name}:{},...e.originator.version!==void 0?{version:e.originator.version}:{}}},prompt:e.prompt,enqueuedAt:e.enqueuedAt}}async drainQueue(){if(!this.promptInFlight){this.promptInFlight=!0,await new Promise(e=>setImmediate(e));try{for(;this.promptQueue.length>0&&!this.closing;){let e=this.promptQueue[0];if(e?.kind==="user"&&(await this.holdForUnsolicitedTurn(e),this.closing))break;let t=this.promptQueue.shift();if(!t)break;if(!t.cancelled){this.currentEntry=t,t.kind==="user"&&this.persistRewrite(),t.kind==="user"&&this.broadcastQueueRemoved(t.messageId,"started");try{let n=await this.runQueueEntry(t);t.resolve(n),await new Promise(r=>setImmediate(r))}catch(n){t.reject(n)}finally{this.currentEntry=void 0}}}}finally{this.promptInFlight=!1,this.supersededAutonomousTurn=void 0,this.dispatchIdle()}}}async runQueueEntry(e){if(e.kind==="internal")return this.closeUnsolicitedTurn("superseded",`internal:${e.label}`),e.task();this.broadcastPromptReceived(e);let t=At(e.prompt).replace(/\s+$/,""),n=!t.includes(`
102
+ `)&&t.startsWith("/")?t.split(/\s+/)[0]??"":"",r=n.startsWith("/")?n.slice(1):"",o=r.length>0&&this.aliasableBareVerbs().has(r);if(n==="/model"||n==="/mode"||n==="/sessions"||n==="/help"||n==="/hydra"||o){let d;try{if(n==="/sessions")d=await this.handleSessionsCommand();else if(n==="/help")d=await this.handleHelpCommand();else if(n==="/mode")d=await this.handleModeCommand(t);else if(n==="/model")d=await this.handleModelCommand(t);else if(o){let c=t.slice(n.length).trim(),u=c?`/hydra ${r} ${c}`:`/hydra ${r}`;d=await this.handleSlashCommand(u,e.messageId)}else d=await this.handleSlashCommand(t,e.messageId)}catch(c){throw this.closed||this.broadcastTurnComplete(e.clientId,{stopReason:"error"},e.messageId,this.originatorNeedsTurnComplete(e),Pd(c)),this.clearAmendIfMatches(e.messageId),c}return this.closed||this.broadcastTurnComplete(e.clientId,d,e.messageId,this.originatorNeedsTurnComplete(e)),this.clearAmendIfMatches(e.messageId),d}if(this.clearRollbackBreadcrumbHook)try{this.clearRollbackBreadcrumbHook()}catch{}let i=e.prompt;n&&this.agentAdvertisedCommands.length>0&&!this.agentKnowsSlashCommand(n)&&(i=vo(e.prompt,hm));let a;this.agentTurnInFlight=!0;try{i=this.applyWorkspacePromptRewrite(i),a=await this.dispatchPrompt(e,i)}catch(d){if(this.forceCancelling)return this.clearAmendIfMatches(e.messageId),{stopReason:"cancelled"};throw this.closed||this.broadcastTurnComplete(e.clientId,{stopReason:"error"},e.messageId,this.originatorNeedsTurnComplete(e),Pd(d)),this.clearAmendIfMatches(e.messageId),d}finally{this.agentTurnInFlight=!1}return this.closed||this.broadcastTurnComplete(e.clientId,a,e.messageId,this.originatorNeedsTurnComplete(e)),this.clearAmendIfMatches(e.messageId),a}async dispatchPrompt(e,t){let n=()=>this.awaitPromptResponse(this.forwardRequest("session/prompt",{sessionId:this.sessionId,prompt:t},e.emitterName?new Set([e.emitterName]):new Set,e.chainStartIdx??0));try{return await n()}catch(r){if(this.loadExistingAgentSession&&Kg(r))return this.logger?.warn(`agent ${this.agentId} no longer knows upstream session ${this.upstreamSessionId} for ${this.sessionId}; reloading it onto a fresh process and retrying the prompt once`),await this.reloadUpstreamAfterAgentLoss(),await n();if(!Yg(r)||this.turnRanTool||(this.logger?.warn(`agent ${this.agentId} hit a transient auth failure for ${this.sessionId}; retrying the prompt once in ${Md}ms`),await new Promise(o=>setTimeout(o,Md)),e.cancelled))throw r;return await n()}}clearAmendIfMatches(e){this.amendInProgress?.cancelledMessageId===e&&(this.amendInProgress=void 0)}},Ed=2e3;function Pd(s){let e=s?.message;if(!(typeof e!="string"||e.trim().length===0))return e.length>Ed?`${e.slice(0,Ed)}...`:e}var Gg=["session not found","the claude agent session has ended"];function jd(s){let e=s;if(e?.code!==R.InternalError)return;let t=e.data?.details;return`${typeof e.message=="string"?e.message:""} ${typeof t=="string"?t:""}`.toLowerCase()}function Kg(s){let e=jd(s);return e!==void 0&&Gg.some(t=>e.includes(t))}var Qg=["failed to refresh oauth token"],Md=6e4;function Yg(s){let e=jd(s);return e!==void 0&&Qg.some(t=>e.includes(t))}function fe(s,e){return s.code=e,s}var Xg=new Set(["session_info_update","_hydra_current_model_update","current_mode_update","available_commands_update","_hydra_available_modes_update","usage_update","config_option_update","_hydra_compaction"]);function Zg(s,e,t){return t?.run_in_background===!0||t?.background===!0?!1:e?.toolName==="Monitor"||s==="Monitor"||typeof e?.toolResponse?.taskId=="string"}function em(s){return typeof s!="string"?void 0:/Command running in background with ID: ([A-Za-z0-9_-]+)/.exec(s)?.[1]}function tm(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.metadata;if(!e||typeof e!="object")return;let{status:t,shellID:n}=e;return t==="running"&&typeof n=="string"&&n!==""?n:void 0}function nm(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.claudeCode;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,n={};return t.toolName!==void 0&&(n.toolName=t.toolName),t.toolResponse&&typeof t.toolResponse=="object"&&(n.toolResponse=t.toolResponse),n}function Rn(s,e){if(s!=="session/update")return!1;let n=(e??{}).update?.sessionUpdate;return typeof n=="string"&&Xg.has(n)}function sm(s,e){if(s.length!==e.length)return!1;for(let t=0;t<s.length;t++)if(s[t]?.name!==e[t]?.name||s[t]?.description!==e[t]?.description)return!1;return!0}function rm(s,e){if(s.length!==e.length)return!1;for(let t=0;t<s.length;t++)if(s[t]?.id!==e[t]?.id||s[t]?.name!==e[t]?.name||s[t]?.description!==e[t]?.description)return!1;return!0}function om(s,e){if(s.length!==e.length)return!1;for(let t=0;t<s.length;t++)if(s[t]?.modelId!==e[t]?.modelId||s[t]?.name!==e[t]?.name||s[t]?.description!==e[t]?.description)return!1;return!0}function xn(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object"||Array.isArray(t))continue;let n=t,r=typeof n.modelId=="string"&&n.modelId.trim()||typeof n.value=="string"&&n.value.trim()||typeof n.id=="string"&&n.id.trim()||void 0;if(!r)continue;let o={modelId:r};typeof n.name=="string"&&n.name.length>0&&(o.name=n.name),typeof n.description=="string"&&n.description.length>0&&(o.description=n.description),e.push(o)}return e}function Is(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object"||Array.isArray(t))continue;let n=t,r=typeof n.value=="string"&&n.value.trim()||typeof n.id=="string"&&n.id.trim()||void 0;if(!r)continue;let o={id:r};typeof n.name=="string"&&n.name.length>0&&(o.name=n.name),typeof n.description=="string"&&n.description.length>0&&(o.description=n.description),e.push(o)}return e}function So(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object"||Array.isArray(t))continue;let n=t,r=typeof n.value=="string"&&n.value.trim()||typeof n.id=="string"&&n.id.trim()||void 0;if(!r)continue;let o=typeof n.name=="string"&&n.name.trim()?n.name.trim():r,i={value:r,name:o};typeof n.description=="string"&&n.description.length>0&&(i.description=n.description),e.push(i)}return e}function im(s){let t=(s??{}).update??{};if(t.sessionUpdate!=="_hydra_available_modes_update")return null;let n=t.availableModes;if(!Array.isArray(n))return[];let r=[];for(let o of n){if(!o||typeof o!="object")continue;let i=o;if(typeof i.id!="string"||i.id.length===0)continue;let a={id:i.id};typeof i.name=="string"&&(a.name=i.name),typeof i.description=="string"&&(a.description=i.description),r.push(a)}return r}function am(s,e){let n=(e??{}).update??{},r=n.sessionUpdate;if(r==="agent_message_chunk"){let o=n.content??{};typeof o.text=="string"&&(s.chunks.push(o.text),s.messageChars+=o.text.length);return}if(r==="agent_thought_chunk"){let o=n.content??{};typeof o.text=="string"&&(s.thinkingChars+=o.text.length);return}if(r==="tool_call"){s.toolCalls++;return}if(r==="usage_update"){typeof n.used=="number"&&(s.lastUsed=n.used),typeof n.size=="number"&&(s.lastSize=n.size);return}}function dm(s){let t=(s??{}).update??{};if(t.sessionUpdate!=="available_commands_update")return null;let n=t.availableCommands??t.commands;if(!Array.isArray(n))return[];let r=[];for(let o of n){if(!o||typeof o!="object")continue;let i=o;if(typeof i.name!="string"||i.name.length===0)continue;let a={name:i.name};typeof i.description=="string"&&(a.description=i.description),r.push(a)}return r}function cm(s,e){if(s!=="session/update"||!e||typeof e!="object")return e;let t=e;return!t.update||typeof t.update!="object"||Array.isArray(t.update)||typeof t.update.messageId=="string"?e:{...e,update:{...t.update,messageId:Ge()}}}function um(s,e){if(s.length<=e)return s;let t=s.length-e;for(let n=t;n>=0;n--)if(s[n]?.params?.update?.sessionUpdate==="prompt_received")return s.slice(n);return s.slice(t)}function lm(s,e){for(let t=s.length-1;t>=0;t--)if(s[t]?.seq===e)return t;return-1}function fm(s,e){for(let t=s.length-1;t>=0;t--){let n=s[t];if(!n||n.method!=="session/update")continue;if(n.params?.update?.messageId===e)return t}return-1}function _d(s){if(!s||typeof s!="object")return;let e=s.toolCall;if(!e||typeof e!="object")return;let t=e.toolCallId;return typeof t=="string"?t:void 0}function pm(s){let e=gm(s.result),t={sessionUpdate:"permission_resolved"};return s.toolCallId!==void 0&&(t.toolCallId=s.toolCallId),e&&(t.outcome=e,e.kind==="selected"&&typeof e.optionId=="string"&&(t.chosenOptionId=e.optionId)),t.resolvedBy=mm(s.resolver),t}function gm(s){if(!s||typeof s!="object")return;let e=s.outcome;if(!e||typeof e!="object")return;let t=e.kind;if(typeof t!="string")return;let n={kind:t},r=e.optionId;typeof r=="string"&&(n.optionId=r);let o=e.reason;return typeof o=="string"&&(n.reason=o),n}function mm(s){let e={clientId:s.clientId};return s.clientInfo?.name&&(e.name=s.clientInfo.name),s.clientInfo?.version&&(e.version=s.clientInfo.version),e}function At(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?e.text:"").join(""):""}var hm="\u200B";function $d(s,e){return s.map(t=>{if(t&&typeof t=="object"&&typeof t.text=="string"){let n=t;return{...n,text:e(n.text)}}return t})}function vo(s,e){let t=s.findIndex(o=>o&&typeof o=="object"&&typeof o.text=="string");if(t<0)return s;let n=s[t],r=[...s];return r[t]={...n,text:`${e}${n.text}`},r}function bo(s){return s==="session/prompt"?{stopReason:"stopped"}:{}}function ym(s){return s==="session/request_permission"?{outcome:{outcome:"cancelled"}}:{}}function Od(s){let e=s.name&&s.name!==s.id?`${s.id} (${s.name}) \u2014 \u25B6 ${s.currentValue}`:`${s.id} \u2014 \u25B6 ${s.currentValue}`;if(s.options.length===0)return e;let t=Math.max(...s.options.map(r=>r.value.length)),n=s.options.map(r=>{let o=r.value===s.currentValue?"\u25B6":"\xB7",i=r.name&&r.name!==r.value,a=i?r.value.padEnd(t):r.value;return i?` ${o} ${a} ${r.name}`:` ${o} ${a}`});return`${e}
103
103
  ${n.join(`
104
- `)}`}function bo(s,e){for(let t of s.split(/\r?\n/)){let n=t.trim();if(n)return n.length>e?`${n.slice(0,e)}\u2026`:n}}Y();je();import*as $e from"fs/promises";import*as fS from"path";import{customAlphabet as wm}from"nanoid";import{z as P}from"zod";import{z as Qt}from"zod";var hm=Qt.object({source:Qt.string(),reason:Qt.string(),raisedAt:Qt.number(),payload:Qt.unknown()}),Hd=Qt.array(hm);import{z as Z}from"zod";var jd=Z.object({status:Z.enum(["requested","running","swap_pending","swap_deferred","failed"]),requestedAt:Z.number(),runId:Z.string().optional(),iter:Z.number().int().nonnegative().optional(),attempts:Z.number().int().nonnegative().optional(),lastError:Z.string().optional(),worker:Z.object({upstreamSessionId:Z.string(),pid:Z.number().int().nonnegative()}).optional()}),Rn=Z.object({goal:Z.string().optional(),outcome:Z.string().optional(),files_touched:Z.array(Z.string()).optional(),tools_used:Z.array(Z.string()).optional(),rejected_approaches:Z.array(Z.string()).optional(),open_threads:Z.array(Z.string()).optional(),decisions:Z.array(Z.string()).optional(),file_edit_intentions:Z.array(Z.string()).optional(),unresolved_errors:Z.array(Z.string()).optional(),tool_state:Z.array(Z.string()).optional()}),Ld=200,So=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
104
+ `)}`}function Io(s,e){for(let t of s.split(/\r?\n/)){let n=t.trim();if(n)return n.length>e?`${n.slice(0,e)}\u2026`:n}}Y();je();import*as $e from"fs/promises";import*as gS from"path";import{customAlphabet as vm}from"nanoid";import{z as P}from"zod";import{z as Yt}from"zod";var wm=Yt.object({source:Yt.string(),reason:Yt.string(),raisedAt:Yt.number(),payload:Yt.unknown()}),Ld=Yt.array(wm);import{z as Z}from"zod";var Ud=Z.object({status:Z.enum(["requested","running","swap_pending","swap_deferred","failed"]),requestedAt:Z.number(),runId:Z.string().optional(),iter:Z.number().int().nonnegative().optional(),attempts:Z.number().int().nonnegative().optional(),lastError:Z.string().optional(),worker:Z.object({upstreamSessionId:Z.string(),pid:Z.number().int().nonnegative()}).optional()}),Tn=Z.object({goal:Z.string().optional(),outcome:Z.string().optional(),files_touched:Z.array(Z.string()).optional(),tools_used:Z.array(Z.string()).optional(),rejected_approaches:Z.array(Z.string()).optional(),open_threads:Z.array(Z.string()).optional(),decisions:Z.array(Z.string()).optional(),file_edit_intentions:Z.array(Z.string()).optional(),unresolved_errors:Z.array(Z.string()).optional(),tool_state:Z.array(Z.string()).optional()}),Bd=200,Ao=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
105
105
  {
106
106
  "title": "short summary, max 80 chars",
107
107
  "synopsis": {
@@ -111,7 +111,7 @@ ${n.join(`
111
111
  "open_threads": ["work started but not finished"]
112
112
  }
113
113
  }
114
- Use empty arrays/strings where a field doesn't apply.`;function Ud(s){let e=s.trim();if(e.length===0)return;let t=Yt(e);if(t===void 0){let o=e.indexOf("{"),i=e.lastIndexOf("}");o>=0&&i>o&&(t=Yt(e.slice(o,i+1)))}if(t===void 0){let o=Wd(e);o!==void 0&&(t=Yt(o))}if(t===void 0||t===null||typeof t!="object")return;let n=t,r={};if(typeof n.title=="string"){let o=n.title.trim();o.length>0&&(r.title=o.slice(0,Ld))}if(n.synopsis!==void 0&&n.synopsis!==null){let o=Rn.safeParse(n.synopsis);o.success&&ym(o.data)&&(r.synopsis=o.data)}if(!(r.title===void 0&&r.synopsis===void 0))return r}var Io=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
114
+ Use empty arrays/strings where a field doesn't apply.`;function Wd(s){let e=s.trim();if(e.length===0)return;let t=Xt(e);if(t===void 0){let o=e.indexOf("{"),i=e.lastIndexOf("}");o>=0&&i>o&&(t=Xt(e.slice(o,i+1)))}if(t===void 0){let o=zd(e);o!==void 0&&(t=Xt(o))}if(t===void 0||t===null||typeof t!="object")return;let n=t,r={};if(typeof n.title=="string"){let o=n.title.trim();o.length>0&&(r.title=o.slice(0,Bd))}if(n.synopsis!==void 0&&n.synopsis!==null){let o=Tn.safeParse(n.synopsis);o.success&&km(o.data)&&(r.synopsis=o.data)}if(!(r.title===void 0&&r.synopsis===void 0))return r}var Co=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
115
115
  {
116
116
  "title": "short summary, max 80 chars",
117
117
  "goal": "the user's original ask",
@@ -123,97 +123,97 @@ Use empty arrays/strings where a field doesn't apply.`;function Ud(s){let e=s.tr
123
123
  "unresolved_errors": ["errors left open at session end"],
124
124
  "tool_state": ["runtime state relevant for recall"]
125
125
  }
126
- Use empty arrays/strings where a field doesn't apply.`;function Bd(s){let e=s.trim();if(e.length===0)return;let t=Yt(e);if(t===void 0){let c=e.indexOf("{"),u=e.lastIndexOf("}");c>=0&&u>c&&(t=Yt(e.slice(c,u+1)))}if(t===void 0){let c=Wd(e);c!==void 0&&(t=Yt(c))}if(t===void 0||t===null||typeof t!="object")return;let n=t,r={};if(typeof n.title=="string"){let c=n.title.trim();c.length>0&&(r.title=c.slice(0,Ld))}let o={},i=!1,a=["goal","outcome"];for(let c of a)if(typeof n[c]=="string"){let u=n[c].trim();u.length>0&&(o[c]=u,i=!0)}let d=["files_touched","tools_used","rejected_approaches","open_threads","decisions","file_edit_intentions","unresolved_errors","tool_state"];for(let c of d)if(Array.isArray(n[c])){let u=n[c],l=Z.array(Z.string()).safeParse(u);l.success&&u.length>0&&(o[c]=l.data,i=!0)}if(i&&(r.synopsis=o),!(r.title===void 0&&r.synopsis===void 0))return r}function Yt(s){try{return JSON.parse(s)}catch{return}}function Wd(s){let e=s.indexOf("{");if(e<0)return;let t=0,n=!1,r=!1;for(let o=e;o<s.length;o++){let i=s[o];if(n){r?r=!1:i==="\\"?r=!0:i==='"'&&(n=!1);continue}if(i==='"'){n=!0;continue}if(i==="{")t++;else if(i==="}"&&(t--,t===0))return s.slice(e,o+1)}}function ym(s){return s.goal!==void 0&&s.goal.trim().length>0||s.outcome!==void 0&&s.outcome.trim().length>0||s.files_touched!==void 0&&s.files_touched.length>0||s.tools_used!==void 0&&s.tools_used.length>0||s.rejected_approaches!==void 0&&s.rejected_approaches.length>0||s.open_threads!==void 0&&s.open_threads.length>0||s.decisions!==void 0&&s.decisions.length>0||s.file_edit_intentions!==void 0&&s.file_edit_intentions.length>0||s.unresolved_errors!==void 0&&s.unresolved_errors.length>0||s.tool_state!==void 0&&s.tool_state.length>0}var km="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",vm=wm(km,16),bm="hydra_lineage_";function En(){return`${bm}${vm()}`}var Ao=P.object({name:P.string(),description:P.string().optional()}),Co=P.object({id:P.string(),name:P.string().optional(),description:P.string().optional()}),Sm=P.object({modelId:P.string(),name:P.string().optional(),description:P.string().optional()}),Ro=P.object({used:P.number().optional(),size:P.number().optional(),costAmount:P.number().optional(),costCurrency:P.string().optional(),cumulativeCost:P.number().optional()}),xo=P.object({name:P.string(),version:P.string().optional()}),Im=P.object({path:P.string(),sourceCwd:P.string(),label:P.string(),requestedLabel:P.string().optional(),provider:P.string(),snapshot:P.string().optional(),line:P.string().optional(),vcs:P.record(P.string(),P.string()).optional(),clean:P.boolean().optional()}),Am=P.object({previousUpstreamSessionId:P.string(),previousSummarizedThroughEntry:P.number().int().nonnegative().optional(),runId:P.string().optional()}),Cm=P.enum(["compaction","agent-swap","workspace-enter","workspace-leave","rollback","restart"]),Rm=P.object({upstreamSessionId:P.string(),agentId:P.string(),reason:Cm.optional(),runId:P.string().optional(),startedAt:P.string().optional(),endedAt:P.string().optional(),cost:P.number().nonnegative().optional(),lifetimeCostAtStart:P.number().nonnegative().optional(),usedAtStart:P.number().nonnegative().optional(),usedAtEnd:P.number().nonnegative().optional(),inferred:P.boolean().optional()}),xm=P.object({version:P.literal(1),sessionId:P.string(),lineageId:P.string().optional(),upstreamSessionId:P.string(),importedFromSessionId:P.string().optional(),importedFromUpstreamSessionId:P.string().optional(),importedFromMachine:P.string().optional(),agentId:P.string(),cwd:P.string(),title:P.string().optional(),synopsis:Rn.optional(),compactionState:jd.optional(),rollbackBreadcrumb:Am.optional(),upstreamGenerations:P.array(Rm).optional(),summarizedThroughEntry:P.number().int().nonnegative().optional(),agentArgs:P.array(P.string()).optional(),currentModel:P.string().optional(),currentMode:P.string().optional(),currentUsage:Ro.optional(),agentCommands:P.array(Ao).optional(),agentModes:P.array(Co).optional(),agentModels:P.array(Sm).optional(),configOptionValues:P.record(P.string(),P.string()).optional(),pendingHistorySync:P.boolean().optional(),pendingAgentSwap:P.string().optional(),parentSessionId:P.string().optional(),forkedFromSessionId:P.string().optional(),forkedFromMessageId:P.string().optional(),side:Ht.optional(),forkSynthesisState:P.enum(["running","failed"]).optional(),originatingClient:xo.optional(),interactive:P.boolean().optional(),priority:P.number().int().nonnegative().optional(),lastTurnEndedAt:P.number().int().nonnegative().optional(),readAt:P.number().int().nonnegative().optional(),forwardedEnv:P.record(P.string(),P.string()).optional(),workspace:Im.optional(),attentionFlags:Hd.default([]).optional(),extensionState:P.record(P.string(),P.record(P.string(),P.unknown())).default({}).optional(),createdAt:P.string(),updatedAt:P.string()}),xn=/^[A-Za-z0-9_-]+$/;function Em(s){if(!xn.test(s))throw new Error(`unsafe session id: ${s}`)}var Ss=class{index;indexSeed;async write(e){Em(e.sessionId);let t={version:1,...e};await me(T.sessionFile(e.sessionId),t,{mode:384}),await this.reindex(e.sessionId)}async touch(e){if(!xn.test(e))return;let t=new Date;try{await $e.utimes(T.sessionFile(e),t,t)}catch(n){if(n.code!=="ENOENT")throw n;return}await this.reindex(e)}async markDeleted(e,t){await this.ensureIndex();let n=this.index.get(e);n&&!n.deleted||n&&n.mtimeMs>=t||this.index.set(e,{mtimeMs:t,deleted:!0})}async cursor(){await this.ensureIndex();let e=0;for(let t of this.index.values())t.mtimeMs>e&&(e=t.mtimeMs);return e}async listChangedSince(e){let t=await this.cursor(),n=[],r=[];for(let[a,d]of this.index)d.mtimeMs<e||(d.deleted?r.push(a):n.push(a));let o=await Promise.all(n.map(a=>this.read(a).catch(()=>{}))),i=[];for(let a of o)a&&i.push(a);return{records:i,removed:r,cursor:t}}async ensureIndex(){this.index||(this.indexSeed||(this.indexSeed=this.seedIndex()),await this.indexSeed)}async seedIndex(){let e=new Map,t=[];try{t=await $e.readdir(T.sessionsDir())}catch(n){if(n.code!=="ENOENT")throw n}await Promise.all(t.map(async n=>{if(xn.test(n))try{let r=await $e.stat(T.sessionFile(n));e.set(n,{mtimeMs:r.mtimeMs,deleted:!1})}catch{}})),this.index=e}async reindex(e){if(this.indexSeed){await this.indexSeed;try{let t=await $e.stat(T.sessionFile(e));this.index.set(e,{mtimeMs:t.mtimeMs,deleted:!1})}catch{}}}async read(e){if(!xn.test(e))return;let t=await de(T.sessionFile(e));if(t!==void 0)try{return xm.parse(t)}catch{return}}async delete(e){if(xn.test(e)){this.indexSeed&&(await this.indexSeed,this.index.set(e,{mtimeMs:Date.now(),deleted:!0}));try{await $e.unlink(T.sessionFile(e))}catch(t){if(t.code!=="ENOENT")throw t}try{await $e.rmdir(T.sessionDir(e))}catch(t){let n=t;if(n.code!=="ENOENT"&&n.code!=="ENOTEMPTY")throw t}}}async findByLineageId(e){if(e.length===0)return;let t=await this.list().catch(()=>[]);for(let n of t)if(n.lineageId===e)return n}async list(){let e;try{e=await $e.readdir(T.sessionsDir())}catch(r){if(r.code==="ENOENT")return[];throw r}let t=await Promise.all(e.map(r=>this.read(r).catch(()=>{}))),n=[];for(let r of t)r&&n.push(r);return n}};function Eo(s){let e=new Date().toISOString(),t=s.createdAt??e,n=(s.currentUsage?.cumulativeCost??0)+(s.currentUsage?.costAmount??0),r=s.upstreamGenerations??(s.upstreamSessionId?[{upstreamSessionId:s.upstreamSessionId,agentId:s.agentId,startedAt:t,...n===0?{lifetimeCostAtStart:0}:{}}]:[]);return{sessionId:s.sessionId,lineageId:s.lineageId,upstreamSessionId:s.upstreamSessionId,importedFromSessionId:s.importedFromSessionId,importedFromUpstreamSessionId:s.importedFromUpstreamSessionId,importedFromMachine:s.importedFromMachine,agentId:s.agentId,cwd:s.cwd,title:s.title,synopsis:s.synopsis,summarizedThroughEntry:s.summarizedThroughEntry,compactionState:s.compactionState,rollbackBreadcrumb:s.rollbackBreadcrumb,upstreamGenerations:r,agentArgs:s.agentArgs,currentModel:s.currentModel,currentMode:s.currentMode,currentUsage:s.currentUsage,agentCommands:s.agentCommands,agentModes:s.agentModes,agentModels:s.agentModels,configOptionValues:s.configOptionValues,pendingHistorySync:s.pendingHistorySync,pendingAgentSwap:s.pendingAgentSwap,parentSessionId:s.parentSessionId,forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,side:s.side,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:s.interactive,priority:s.priority,lastTurnEndedAt:s.lastTurnEndedAt,readAt:s.readAt,forwardedEnv:s.forwardedEnv,workspace:s.workspace,attentionFlags:s.attentionFlags??[],extensionState:s.extensionState??{},createdAt:t,updatedAt:s.updatedAt??e}}je();Y();import*as ae from"fs/promises";import*as Se from"path";Y();import*as Is from"path";import{createHash as Tm}from"crypto";var Ne=class extends Error{constructor(e,t){super(`provider "${e}" does not support ${t}; check capabilities().supports before calling`),this.name="WorkspaceUnsupportedError"}};function Xt(s){let e=Tm("sha256").update(Is.resolve(s)).digest("hex").slice(0,12);return Is.join(z(),"workspaces",e)}async function As(s,e,t=100){if(await e(s))return s;for(let n=2;n<=t;n+=1){let r=`${s}-${n}`;if(await e(r))return r}}function At(s,e=10){if(s.length<=e)return[...s];let t=s.slice(0,e),n=s.length-e;return[...t,`... and ${n} more`]}function To(s){return s.changedPaths.length>0||s.recorded!==void 0&&s.recorded!==s.actual}function Pm(s){let e=[];for(let t of s){if(t.changedPaths.length===0){e.push(`${t.relPath} (nested tree advanced to ${t.actual.slice(0,8)})`);continue}for(let n of t.changedPaths)e.push(`${t.relPath}/${n}`)}return e}function Po(s,e){let t=new Set(e.map(r=>r.relPath));return[...s.filter(r=>!t.has(r.replace(/\/$/,""))),...Pm(e.filter(To))]}function Cs(s){let e=s.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return e.length>0?e.slice(0,64):"workspace"}var Mo="copy",zd=new Set([".git"]);function Tn(s){return`${s}.manifest.json`}async function qd(s){let e=new Map,t=[s];for(;t.length>0;){let n=t.pop();if(n===void 0)break;let r;try{r=await ae.readdir(n,{withFileTypes:!0})}catch{continue}for(let o of r){let i=Se.join(n,o.name);if(!(n===s&&zd.has(o.name))){if(o.isDirectory()){t.push(i);continue}if(o.isFile())try{let a=await ae.stat(i);e.set(Se.relative(s,i),{size:a.size,mtimeMs:a.mtimeMs})}catch{continue}}}}return e}var Rs=class{kind=Mo;capabilities(){return{cheapWorkspaces:!1,sharedHistory:!1,nonMutatingCapture:!0,conflictReporting:!1,locking:!1,requiresServer:!1,supports:{record:!1,integrate:!1,captureWorkingState:!1,changedPaths:!1,environmentNotes:!0,rematerialize:!1,nestedTrees:!1}}}async materializeNested(){return{ok:!0,count:0}}async retainSnapshot(){}async dropSnapshotRef(){}async rematerialize(e){return{ok:!1,reason:`copy provider retains nothing outside ${e.path}; it cannot be rebuilt`}}async createWorkspace(e){if(e.from!==void 0)return{ok:!1,reason:"copy provider cannot create from a snapshot; it records none"};let t=Se.resolve(e.sourceCwd),n=e.contentFrom!==void 0?Se.resolve(e.contentFrom):t;try{n=await ae.realpath(n)}catch{}try{if(!(await ae.stat(n)).isDirectory())return{ok:!1,reason:`${n} is not a directory`}}catch{return{ok:!1,reason:`${n} does not exist`}}let r=Xt(t);try{await ae.mkdir(r,{recursive:!0})}catch(u){return{ok:!1,reason:`could not create workspace root: ${String(u)}`}}let o=await As(Cs(e.label),async u=>ae.access(Se.join(r,u)).then(()=>!1).catch(()=>!0));if(o===void 0)return{ok:!1,reason:`no free name available for "${e.label}"`};let i=Se.join(r,o),a;try{a=await ae.readdir(n)}catch(u){return{ok:!1,reason:`copy failed: ${String(u)}`}}try{await ae.mkdir(i,{recursive:!0});for(let u of a)zd.has(u)||await ae.cp(Se.join(n,u),Se.join(i,u),{recursive:!0,errorOnExist:!1,force:!0})}catch(u){return await ae.rm(i,{recursive:!0,force:!0}).catch(()=>{}),{ok:!1,reason:`copy failed: ${String(u)}`}}let d=await qd(i),c={sourceCwd:t,label:o,createdAt:new Date().toISOString(),entries:Object.fromEntries(d)};return await me(Tn(i),c,{pretty:!1}),{ok:!0,workspace:{path:i,sourceCwd:t,label:o,provider:this.kind}}}async removeWorkspace(e,t){if(!t.force){let n=await this.status(e);if(!n.clean)throw new Error(`workspace ${e.path} has ${n.changedPaths.length} changed path(s); pass force to remove`)}await ae.rm(e.path,{recursive:!0,force:!0}),await ae.rm(Tn(e.path),{force:!0})}async listWorkspaces(e){let t=Xt(Se.resolve(e)),n;try{n=await ae.readdir(t)}catch{return[]}let r=[];for(let o of n){if(o.endsWith(".manifest.json"))continue;let i=Se.join(t,o),a=await de(Tn(i));a!==void 0&&r.push({path:i,sourceCwd:a.sourceCwd,label:a.label,provider:this.kind})}return r}async status(e){let t=await de(Tn(e.path)),n=await qd(e.path);if(t===void 0)return{clean:!1,changedPaths:[...n.keys()].sort(),hasRecordedWork:!1};let r=[];for(let[o,i]of n){let a=t.entries[o];(a===void 0||a.size!==i.size||a.mtimeMs!==i.mtimeMs)&&r.push(o)}for(let o of Object.keys(t.entries))n.has(o)||r.push(o);return r.sort(),{clean:r.length===0,changedPaths:r,hasRecordedWork:!1}}async statusReport(e){let{changedPaths:t}=await this.status(e),n=t.length===0?["no changes since this copy was made"]:[`${t.length} changed file(s) since this copy was made:`,...At(t.map(r=>` ${r}`))];return n.push(`Not tracking ${$(e.sourceCwd)}: a copied directory has no shared history, so there is nothing to be in or out of sync with.`),n}async environmentNotes(e){return[`This directory is an isolated copy of ${e.sourceCwd}. It is not under version control: there is no history, no branches, and version-control commands will not behave as they would in the original.`,"Changes here are not automatically returned to the original directory."]}async captureWorkingState(){throw new Ne(this.kind,"captureWorkingState")}async record(){throw new Ne(this.kind,"record")}async attributeOrphan(e){let t=await de(Tn(e));if(t?.sourceCwd!==void 0)return{path:e,sourceCwd:t.sourceCwd,label:t.label??Se.basename(e),provider:this.kind}}async discardLine(){return{ok:!0,dropped:0}}ownsLine(){return!1}async pruneStale(){}async changedPaths(){throw new Ne(this.kind,"changedPaths")}async integrate(){return{ok:!1,conflicts:[],declined:!0,reason:`the "${this.kind}" provider keeps no history, so there is nothing to integrate from`}}async currentState(){}async contentId(){}async currentLineName(){}async resolveRoot(e){return e}async resolveRetained(){}async contains(){return!1}async divergence(){}async changedPathsBetween(){return[]}async captureDelta(){throw new Ne(this.kind,"captureDelta")}async applyDelta(){return{ok:!1,reason:`the "${this.kind}" provider cannot reproduce a captured change`}}async resetTo(){return{ok:!1,reason:`the "${this.kind}" provider records no state to return to`}}async integrationInProgress(){return!1}async abortIntegration(){}async conflictedPaths(){return[]}async listNested(){return[]}async captureNested(){return[]}async reproduceNested(){return{applied:[],failed:[]}}async integrateNested(){return{applied:[],failed:[]}}async lock(){throw new Ne(this.kind,"lock")}async unlock(){throw new Ne(this.kind,"unlock")}};Y();import{execFile as Qd}from"child_process";import{randomBytes as Om}from"crypto";import*as De from"fs/promises";import*as Yd from"os";import*as ee from"path";function Mm(s){let e=s.indexOf(" ");return e===-1?{key:s,value:""}:{key:s.slice(0,e),value:s.slice(e+1)}}function Jd(s){let e=[],t,n=()=>{t!==void 0&&(e.push(t),t=void 0)};for(let r of s.split(`
127
- `)){let o=r.replace(/\r$/,"");if(o.length===0){n();continue}let{key:i,value:a}=Mm(o);if(i==="worktree"){n(),t={path:a,bare:!1,detached:!1};continue}if(t!==void 0)switch(i){case"HEAD":t.head=a;break;case"branch":t.branch=a;break;case"bare":t.bare=!0;break;case"detached":t.detached=!0;break;case"locked":t.lockedReason=a;break;case"prunable":t.prunableReason=a;break;default:break}}return n(),e}function Vd(s){if(s===void 0)return;let e="refs/heads/";return s.startsWith(e)?s.slice(e.length):s}var Ts="git",Gd="hydra-acp:",_o="hydra",J=5e3,pe=12e4,xs=9e5;function Kd(s){return De.access(s).then(()=>!0).catch(()=>!1)}function Pn(s){return s.length===0?s:ee.normalize(s)}function Fm(s){return De.realpath(s).catch(()=>s)}function H(s,e,t,n){return new Promise(r=>{Qd("git",s,{cwd:e,timeout:t,maxBuffer:8*1024*1024,...n?{env:{...process.env,...n}}:{}},(o,i,a)=>{r({ok:!o,stdout:i??"",stderr:a??""})})})}function $o(s,e,t,n=pe){return new Promise(r=>{let o=Qd("git",s,{cwd:e,timeout:n,maxBuffer:67108864},(i,a,d)=>{r({ok:!i,stdout:a??"",stderr:d??""})});o.stdin?.on("error",()=>{}),o.stdin?.end(t)})}function Oo(s){let e=[];for(let t of s.split(`
128
- `)){let n=t.replace(/\r$/,"");if(n.length<4)continue;let r=n.slice(3),o=r.indexOf(" -> ");e.push({code:n.slice(0,2),path:o===-1?r:r.slice(o+4)})}return e}var Es=class{kind=Ts;refRoot(e){return e.vcs?.repoRoot??e.sourceCwd}ownsLine(e){return e.startsWith(`${_o}/`)}capabilities(){return{cheapWorkspaces:!0,sharedHistory:!0,nonMutatingCapture:!0,conflictReporting:!0,locking:!0,requiresServer:!1,supports:{record:!0,integrate:!0,captureWorkingState:!0,changedPaths:!1,environmentNotes:!0,rematerialize:!0,nestedTrees:!0}}}async materializeNested(e,t){if(!await Kd(ee.join(e.path,".gitmodules")))return{ok:!0,count:0};let r=await H(["submodule","update","--init","--recursive",...t?.discardLocal===!0?["--force"]:[]],e.path,xs);if(!r.ok)return{ok:!1,count:0,reason:r.stderr.trim()||"git submodule update --init failed"};if(t?.discardLocal===!0){let a=await H(["submodule","foreach","--recursive","git","reset","--hard"],e.path,xs);if(!a.ok)return{ok:!1,count:0,reason:a.stderr.trim()||"could not reset submodules"};let d=t.purgeIgnored===!0?"-ffdx":"-fd",c=await H(["submodule","foreach","--recursive","git","clean",d],e.path,xs);if(!c.ok)return{ok:!1,count:0,reason:c.stderr.trim()||"could not clean submodules"}}let o=await H(["submodule","status","--recursive"],e.path,J);return{ok:!0,count:o.ok?o.stdout.split(`
129
- `).filter(a=>a.trim().length>0).length:0}}async rematerialize(e){let t=e.vcs?.branch;if(t===void 0)return{ok:!1,reason:"workspace has no recorded branch to restore from"};let n=this.refRoot(e);if(!await Kd(n))return{ok:!1,reason:`source repository ${n} no longer exists`};let r=await H(["rev-parse","--verify","--quiet",`refs/heads/${t}`],n,J);if(!r.ok||r.stdout.trim().length===0)return{ok:!1,reason:`branch ${t} no longer exists in ${n}`};await H(["worktree","unlock",e.path],n,J),await H(["worktree","prune"],n,J);let o=await H(["worktree","add",e.path,t],n,pe);return o.ok?{ok:!0,workspace:{...e,line:t,vcs:{...e.vcs??{},kind:"git",branch:t,repoRoot:n}}}:{ok:!1,reason:`could not restore worktree: ${o.stderr.trim()||"unknown error"}`}}async createWorkspace(e){let t=ee.resolve(e.sourceCwd),n=await H(["rev-parse","--show-toplevel"],t,J);if(!n.ok)return{ok:!1,reason:`${t} is not a git repository (or git is unavailable)`};let r=Pn(n.stdout.trim());if(r.length===0)return{ok:!1,reason:`could not resolve the repository root for ${t}`};let o=await H(["rev-parse","HEAD"],r,J);if(!o.ok)return{ok:!1,reason:`${r} has no commits yet, so there is nothing to branch from`};let i=e.from??o.stdout.trim(),a=Cs(e.label),d=Xt(t);try{await De.mkdir(d,{recursive:!0})}catch(f){return{ok:!1,reason:`could not create workspace root: ${String(f)}`}}let c=await As(a,async f=>await De.access(ee.join(d,f)).then(()=>!0).catch(()=>!1)?!1:!(await H(["rev-parse","--verify","--quiet",`refs/heads/${_o}/${f}`],r,J)).ok);if(c===void 0)return{ok:!1,reason:`no free name available for "${a}"`};let u=ee.join(d,c),l=`${_o}/${c}`,p=await H(["worktree","add","--no-track","-b",l,u,i],r,pe);return p.ok?{ok:!0,workspace:{path:u,sourceCwd:t,label:c,provider:this.kind,snapshot:i,line:l,vcs:{kind:"git",branch:l,base:i,repoRoot:r}}}:{ok:!1,reason:`git worktree add failed: ${p.stderr.trim()||"unknown error"}`}}async removeWorkspace(e,t){if(!t.force){let o=await this.status(e);if(!o.clean)throw new Error(`workspace ${e.path} has ${o.changedPaths.length} changed path(s)${o.hasRecordedWork?" and unintegrated recorded work":""}; pass force to remove`)}let n=this.refRoot(e);await this.unlock(e).catch(()=>{});let r=await H(["worktree","remove","--force",e.path],n,pe);t.discardLine===!0&&e.vcs?.branch!==void 0&&await H(["branch","-D",e.vcs.branch],n,J),r.ok||(await De.rm(e.path,{recursive:!0,force:!0}),await H(["worktree","prune"],n,J))}async listWorkspaces(e){let t=ee.resolve(e),n=await H(["rev-parse","--show-toplevel"],t,J);if(!n.ok)return[];let r=Pn(n.stdout.trim()),o=await H(["worktree","list","--porcelain"],r,J);if(!o.ok)return[];let i=Xt(t),a=await Fm(i),d=[];for(let c of Jd(o.stdout)){let u=Pn(c.path),l=ee.dirname(u);if(l!==i&&l!==a)continue;let p=ee.join(i,ee.basename(u)),f={kind:"git",repoRoot:r},h=Vd(c.branch);h!==void 0&&(f.branch=h),c.head!==void 0&&(f.head=c.head),c.lockedReason!==void 0&&(f.locked=c.lockedReason);let k=c.lockedReason?.startsWith(Gd)===!0;d.push({path:p,sourceCwd:t,label:ee.basename(p),...k?{heldByUs:!0}:{},provider:this.kind,...h!==void 0?{line:h}:{},vcs:f})}return d}async status(e){let t=await H(["status","--porcelain","--untracked-files=all"],e.path,J);if(!t.ok)return{clean:!1,changedPaths:[],hasRecordedWork:!1};let n=Oo(t.stdout),r=n.map(a=>a.path),o=n.some(({code:a})=>a!=="??"&&a[0]!==" "&&a[0]!=="?"),i=!1;if(e.snapshot!==void 0){let a=await H(["rev-list","--count",`${e.snapshot}..HEAD`],e.path,J);a.ok&&(i=Number.parseInt(a.stdout.trim(),10)>0)}return{clean:r.length===0&&!i,changedPaths:r,hasRecordedWork:i,hasStagedWork:o}}async lock(e,t){let n=this.refRoot(e);await H(["worktree","lock","--reason",`${Gd}${t}`,e.path],n,J)}async unlock(e){let t=this.refRoot(e);await H(["worktree","unlock",e.path],t,J)}async environmentNotes(e){let t=[],n=e.vcs?.branch;return t.push(`This directory is a git worktree of ${e.sourceCwd}${n!==void 0?`, on branch ${n}`:""}. Do not read or write ${e.sourceCwd} directly; paths under it refer to the corresponding file here. Prefer repo-relative paths, which are identical in both.`),t.push("`.git` here is a file, not a directory. That is normal for a worktree and does not need repairing."),await De.access(ee.join(e.path,".gitmodules")).then(()=>!0).catch(()=>!1)&&t.push("Submodules here are initialized and checked out at the commits this tree records, which means each sits on a detached HEAD. That is normal and does not need repairing. Never re-add a submodule's contents as ordinary tracked files in the superproject: that silently corrupts the integration back to the source branch."),t}async statusReport(e){let t=[],n=await H(["status","--porcelain","--untracked-files=all"],e.path,J);if(n.ok){let r=Oo(n.stdout);if(r.length===0)t.push("no uncommitted changes");else{let o=0,i=0,a=0;for(let{code:c}of r){if(c==="??"){a+=1;continue}c[0]!==" "&&c[0]!=="?"&&(o+=1),c[1]!==" "&&c[1]!=="?"&&(i+=1)}let d=[];o>0&&d.push(`${o} staged`),i>0&&d.push(`${i} unstaged`),a>0&&d.push(`${a} untracked`),t.push(`${d.join(", ")}:`),t.push(...At(r.map(c=>` ${c.code} ${c.path}`)))}}return t.push(...await this.syncLines(e)),t}async syncLines(e){if(e.vcs?.branch===void 0)return[];let[t,n]=await Promise.all([H(["rev-parse","HEAD"],e.sourceCwd,J),H(["rev-parse","HEAD"],e.path,J)]),r=t.stdout.trim(),o=n.stdout.trim();if(!t.ok||!n.ok||r.length===0||o.length===0)return[];let i=$(e.sourceCwd);if(r===o)return[`in sync with ${i}`];let a=await H(["rev-list","--left-right","--count",`${r}...${o}`],e.path,J),d=a.stdout.trim().split(/\s+/).map(p=>Number.parseInt(p,10)),c=d[0],u=d[1];if(!a.ok||c===void 0||u===void 0||!Number.isFinite(c)||!Number.isFinite(u))return[];let l=[];return c>0&&l.push(`${c} commit(s) behind ${i}. \`/hydra workspace sync\` brings them in; landing is fast-forward-only, so this also unblocks \`stop\`.`),u>0&&l.push(`${u} commit(s) recorded here and not landed yet.`),l}async captureWorkingState(e,t){let n=ee.join(Yd.tmpdir(),`hydra-index-${process.pid}-${Om(6).toString("hex")}`),r={GIT_INDEX_FILE:n};try{let o=await H(["rev-parse","--verify","HEAD"],e,J),i=o.ok&&o.stdout.trim().length>0;if(i){let l=await H(["read-tree","HEAD"],e,pe,r);if(!l.ok)throw new Error(`could not seed the snapshot index: ${l.stderr.trim()}`)}let a=await H(["add","-A"],e,pe,r);if(!a.ok)throw new Error(`could not stage working state: ${a.stderr.trim()}`);let d=await H(["write-tree"],e,pe,r);if(!d.ok||d.stdout.trim().length===0)throw new Error(`could not write tree: ${d.stderr.trim()}`);let c=["commit-tree",d.stdout.trim(),"-m",t];i&&c.push("-p",o.stdout.trim());let u=await H(c,e,pe,r);if(!u.ok||u.stdout.trim().length===0)throw new Error(`could not create snapshot commit: ${u.stderr.trim()}`);return u.stdout.trim()}finally{await De.rm(n,{force:!0}).catch(()=>{})}}async retainSnapshot(e,t,n){let r=this.refRoot(e);await H(["update-ref","--create-reflog",t,n],r,J)}async dropSnapshotRef(e,t){let n=this.refRoot(e);await H(["update-ref","-d",t],n,J)}async currentState(e){let t=await H(["rev-parse","HEAD"],e,J),n=t.stdout.trim();return t.ok&&n.length>0?n:void 0}async contentId(e,t){let n=await H(["rev-parse",`${t}^{tree}`],e,J),r=n.stdout.trim();return n.ok&&r.length>0?r:void 0}async currentLineName(e){let t=await H(["rev-parse","--abbrev-ref","HEAD"],e,J),n=t.stdout.trim();return t.ok&&n.length>0?n:void 0}async resolveRoot(e){let t=await H(["rev-parse","--show-toplevel"],e,J),n=Pn(t.stdout.trim());return t.ok&&n.length>0?n:void 0}async resolveRetained(e,t){let n=await H(["rev-parse","--verify","--quiet",`${t}^{commit}`],this.refRoot(e),J),r=n.stdout.trim();return n.ok&&r.length>0?r:void 0}async contains(e,t){return(await H(["merge-base","--is-ancestor",t.state,t.within],e,J)).ok}async divergence(e,t,n){let r=await H(["rev-list","--left-right","--count",`${t}...${n}`],e,J);if(!r.ok)return;let o=r.stdout.trim().split(/\s+/).map(d=>Number.parseInt(d,10)),i=o[0],a=o[1];if(!(i===void 0||a===void 0||!Number.isFinite(i)||!Number.isFinite(a)))return{ahead:i,behind:a}}async changedPathsBetween(e,t,n){let r=await H(["diff","--name-only",t,n],e,J);return r.ok?r.stdout.split(`
130
- `).map(o=>o.replace(/\r$/,"").trim()).filter(o=>o.length>0):[]}async captureDelta(e,t,n){let r=await H(["diff","--binary","--ignore-submodules=all",t,n],e,pe);if(r.ok)return r.stdout}async applyDelta(e,t,n){if(t.trim().length===0)return{ok:!0,alreadyPresent:!0};let r=n?.stage===!0?["--index"]:[],o=await $o(["apply",...r],e,t);if(o.ok)return{ok:!0};if(n?.tolerant!==!0)return{ok:!1,reason:o.stderr.trim()||"the change did not apply"};if((await $o(["apply","--reverse","--check"],e,t)).ok)return{ok:!0,alreadyPresent:!0};let a=await $o(["apply","--3way"],e,t);return a.ok?{ok:!0}:{ok:!1,reason:a.stderr.trim()||"the change overlaps what is already there"}}async resetTo(e,t,n){let r=await H(["reset","--hard",t],e,pe);if(!r.ok)return{ok:!1,reason:r.stderr.trim()||"could not return to that state"};let o=await H(["clean",n?.purgeIgnored===!0?"-ffdx":"-fd"],e,pe);if(!o.ok)return{ok:!1,reason:o.stderr.trim()||"returned to that state but could not remove extra files"};let i=await this.materializeNested({path:e,sourceCwd:e,label:"",provider:this.kind},{discardLocal:!0,...n?.purgeIgnored===!0?{purgeIgnored:!0}:{}});return i.ok?{ok:!0}:{ok:!1,reason:i.reason??"could not reset nested trees"}}async integrationInProgress(e){return(await H(["rev-parse","-q","--verify","MERGE_HEAD"],e,J)).ok}async abortIntegration(e){await H(["merge","--abort"],e,pe)}async conflictedPaths(e){let t=await H(["diff","--name-only","--diff-filter=U"],e,J);return t.ok?t.stdout.split(`
131
- `).map(n=>n.replace(/\r$/,"").trim()).filter(n=>n.length>0):[]}async record(e,t){let n=await H(["add","-A"],e.path,pe);if(!n.ok)throw new Error(`could not stage ${e.path}: ${n.stderr.trim()||"unknown error"}`);let r=await this.status(e),o=await this.currentState(e.path);if(r.changedPaths.length===0){if(o===void 0)throw new Error(`could not read the state of ${e.path}`);return o}let i=await H(["commit","-m",t],e.path,pe);if(!i.ok)throw new Error(`could not record ${e.path}: ${i.stderr.trim()||i.stdout.trim()||"unknown error"}`);let a=await this.currentState(e.path);if(a===void 0)throw new Error(`recorded ${e.path} but could not read the resulting state`);return a}async attributeOrphan(e){let t=await H(["rev-parse","--path-format=absolute","--git-common-dir"],e,J),n=Pn(t.stdout.trim());if(!t.ok||n.length===0)return;let r=ee.dirname(n),o=await this.currentLineName(e);return{path:e,sourceCwd:r,label:ee.basename(e),provider:this.kind,...o!==void 0?{line:o}:{},vcs:{repoRoot:r,...o!==void 0?{branch:o}:{}}}}async discardLine(e,t){let n=this.refRoot(e),o=(await this.divergence(n,"HEAD",t))?.behind??0,i=await H(["branch","-D",t],n,J);return i.ok?{ok:!0,dropped:o}:{ok:!1,dropped:o,reason:i.stderr.trim()||"could not discard the line"}}async pruneStale(e){await H(["worktree","prune"],this.refRoot(e),J)}async changedPaths(){throw new Ne(this.kind,"changedPaths")}async integrate(e){let{into:t,from:n}=e,r=await this.currentState(t);if(r===void 0)return{ok:!1,conflicts:[],declined:!0,reason:`cannot read the state of ${t}`};if(await this.contains(t,{state:n,within:r}))return{ok:!0,snapshot:r,alreadyUpToDate:!0};if(e.fastForwardOnly===!0&&!await this.contains(t,{state:r,within:n}))return{ok:!1,conflicts:[],declined:!0,reason:`${t} cannot simply advance to that state; it has moved on independently`};let o=e.fastForwardOnly===!0?["merge","--ff-only",n]:["merge","--no-edit","-m",e.message??"hydra: integrate",n],i=await H(o,t,pe);if(i.ok){let c=await this.currentState(t);return c===void 0?{ok:!1,conflicts:[],reason:"integrated but could not read the resulting state"}:{ok:!0,snapshot:c}}let a=await this.conflictedPaths(t),d=await this.integrationInProgress(t);return a.length===0&&!d?{ok:!1,conflicts:[],declined:!0,reason:i.stderr.trim()||"the integration was refused"}:(e.onConflict==="abort"&&await this.abortIntegration(t),{ok:!1,conflicts:a})}async listNested(e){let t=await H(["submodule","status","--recursive"],e,pe);if(!t.ok)return[];let n=[];for(let r of t.stdout.split(`
132
- `)){let o=r.replace(/\r$/,"");if(o.trim().length===0||(o[0]??" ")==="-")continue;let a=o.slice(1),d=a.indexOf(" ");if(d<=0)continue;let c=a.slice(d+1).replace(/\s+\(.*\)\s*$/,"").trim();if(c.length===0||!Nm(e,c))continue;let u=ee.join(e,c),[l,p,f]=await Promise.all([this.currentState(u),H(["rev-parse",`HEAD:${c}`],e,J),H(["status","--porcelain","--untracked-files=all"],u,J)]);if(l===void 0)continue;let h=p.ok?p.stdout.trim():"";n.push({relPath:c,actual:l,...h.length>0?{recorded:h}:{},changedPaths:f.ok?Oo(f.stdout).map(k=>k.path):[]})}return n}async captureNested(e,t){let n=[];for(let r of t){if(!To(r))continue;if(r.changedPaths.length===0){n.push(r);continue}let o=ee.join(e,r.relPath),i=await this.captureWorkingState(o,"hydra: nested work carried into workspace").catch(()=>{});if(i===void 0){n.push(r);continue}let a=await this.captureDelta(o,r.actual,i);n.push(a===void 0?r:{...r,delta:a})}return n}async reproduceNested(e,t,n){let r=[],o=[];for(let i of n){let a=ee.join(e,i.relPath),d=ee.join(t,i.relPath),c=await this.alignNested(a,d,i.actual);if(c!==void 0){o.push({path:i.relPath,reason:c});continue}if(i.delta!==void 0){let u=await this.applyDelta(a,i.delta);if(!u.ok){o.push({path:i.relPath,reason:u.reason??"changes did not apply"});continue}}r.push(i.relPath)}return{applied:r,failed:o}}async integrateNested(e,t,n){let r=[],o=[],i=new Map(n.map(c=>[c.relPath,c])),a=await this.listNested(e),d=new Set([...a.map(c=>c.relPath),...i.keys()]);for(let c of[...d].sort()){let u=a.find(m=>m.relPath===c),l=i.get(c);if(u===void 0){o.push({path:c,reason:"not populated in the receiving tree"});continue}let p=u.recorded!==void 0&&u.recorded!==u.actual,f=l?.delta!==void 0;if(!p&&!f)continue;if(u.changedPaths.length>0){o.push({path:c,reason:`it has ${u.changedPaths.length} uncommitted change(s) of its own, and nothing can tell those apart from what was integrated`});continue}let h=ee.join(e,c),k=ee.join(t,c);if(p&&u.recorded!==void 0){let m=await this.alignNested(h,k,u.recorded);if(m!==void 0){o.push({path:c,reason:m});continue}}if(l?.delta!==void 0){let m=await this.applyDelta(h,l.delta);if(!m.ok){o.push({path:c,reason:m.reason??"the uncommitted changes there did not apply"});continue}}r.push(c)}return{applied:r,failed:o}}async alignNested(e,t,n){let r=await this.currentState(e);if(r===void 0)return"not populated here";if(r===n)return;if(!(await H(["cat-file","-e",`${n}^{commit}`],e,J)).ok&&!(await H(["fetch","--no-tags",t,n],e,xs)).ok)return`could not transfer ${n.slice(0,8)} from the other copy`;if(!(await H(["checkout","--detach",n],e,pe)).ok)return`could not move to ${n.slice(0,8)}`}};function Nm(s,e){if(ee.isAbsolute(e))return!1;let t=ee.resolve(s),n=ee.resolve(t,e);return n!==t&&n.startsWith(t+ee.sep)}var Dm=Ts,Hm=new Map([[Ts,new Es],[Mo,new Rs]]);function re(s){return Hm.get(s??Dm)}var Ps="refs/hydra";function Zt(s){let e=`${Ps}/workspaces/${s}`;return{autosave:`${e}/autosave`,start:`${e}/start`,baseline:`${e}/baseline`}}function Fo(s){return`${Ps}/landing/${s}`}function Xd(s){return`${Ps}/sync/${s}`}function Zd(s,e){return`${Ps}/retired/${s}-${e.slice(0,12)}`}function ec(s){let e=Zt(s);return[e.autosave,e.start,e.baseline]}async function No(s){let{source:e,ws:t,startSnapshotRef:n,baselineRef:r,retainRef:o,provider:i}=s;if(i===void 0)throw new Error("no provider available to inspect the source tree");let a=await i.status({...t,path:e}).catch(()=>{}),d="";for(let l of[r,n]){if(l===void 0)continue;let p=await i.resolveRetained(t,l).catch(()=>{});if(p!==void 0){d=p;break}}let c=a===void 0||a.changedPaths.length>0;if(d.length===0){if(c)throw new Error(`${e} has uncommitted changes but this workspace has no start anchor, so its copy of your work cannot be told apart from edits you made since. Refusing rather than reporting a conflict that is not yours. Commit or stash the source, then retry.`);d=await i.currentState(e).catch(()=>{})??""}if(!c)return{clean:!0,base:d};if(i.capabilities().supports.captureWorkingState!==!0)throw new Error(`${e} has uncommitted changes and this provider cannot snapshot them, so they cannot be preserved across the landing. Commit or stash them first.`);let u=await i.captureWorkingState(e,"hydra: source state before landing").catch(()=>{});if(u===void 0)throw new Error(`could not snapshot the uncommitted changes in ${e}, so refusing to touch them`);return await i.retainSnapshot({...t,path:e},o,u),{clean:!1,snapshot:u,base:d,retainedRef:o}}async function Ct(s){let{source:e,capture:t,provider:n}=s;if(t.clean||t.snapshot===void 0||n===void 0)return!0;let r=await n.captureDelta(e,t.base,t.snapshot).catch(()=>{});return r===void 0?!1:(await n.applyDelta(e,r,{tolerant:!0})).ok}async function Mn(s){s.capture.retainedRef===void 0||s.provider===void 0||await s.provider.dropSnapshotRef({...s.ws,path:s.source},s.capture.retainedRef).catch(()=>{})}je();import{exec as jm}from"child_process";import*as Ke from"fs/promises";import*as Ee from"path";var Lm=".hydra/worktree.json",Um=".worktreeinclude",Bm=120;async function Ms(s){let e=await de(Ee.join(s,Lm))??{},t=new Set(Array.isArray(e.carry)?e.carry:[]),n=await Ke.readFile(Ee.join(s,Um),"utf8").catch(()=>{});if(n!==void 0)for(let o of n.split(`
133
- `)){let i=o.trim();i.length===0||i.startsWith("#")||i.startsWith("!")||i.includes("*")||i.includes("?")||t.add(i)}let r={};return t.size>0&&(r.carry=[...t]),typeof e.postCreate=="string"&&(r.postCreate=e.postCreate),typeof e.preRemove=="string"&&(r.preRemove=e.preRemove),typeof e.hookTimeoutSeconds=="number"&&(r.hookTimeoutSeconds=e.hookTimeoutSeconds),r}async function Do(s,e,t){let n=[],r=[],o=Ee.resolve(s),i=Ee.resolve(e);for(let a of t){let d=Ee.resolve(o,a),c=Ee.resolve(i,a);if(!d.startsWith(o+Ee.sep)||!c.startsWith(i+Ee.sep)){r.push(a);continue}if(await Ke.access(c).then(()=>!0).catch(()=>!1)){r.push(a);continue}let l=await Ke.stat(d).catch(()=>{});if(l===void 0){r.push(a);continue}try{await Ke.mkdir(Ee.dirname(c),{recursive:!0}),await Ke.cp(d,c,{recursive:l.isDirectory(),dereference:!0}),n.push(a)}catch{r.push(a)}}return{copied:n,skipped:r}}async function _s(s,e){let t=JSON.stringify({path:e.workspacePath,sourceCwd:e.sourceCwd,label:e.label,...e.sessionId!==void 0?{sessionId:e.sessionId}:{}}),n=(e.timeoutSeconds??Bm)*1e3;return new Promise(r=>{let o=jm(s,{cwd:e.workspacePath,timeout:n,maxBuffer:8388608,windowsHide:!0,env:{...process.env,HYDRA_WORKSPACE_PATH:e.workspacePath,HYDRA_SOURCE_CWD:e.sourceCwd,HYDRA_WORKSPACE_LABEL:e.label,...e.sessionId!==void 0?{HYDRA_SESSION_ID:e.sessionId}:{}}},(i,a,d)=>{if(i){let c=(d||i.message||"").trim().slice(0,500);r({ok:!1,reason:c.length>0?c:"hook failed"});return}r({ok:!0})});o.stdin?.on("error",()=>{}),o.stdin?.end(t)})}Y();je();import*as nt from"fs/promises";import{z as He}from"zod";var Wm=He.object({version:He.literal(1),agentId:He.string(),upstreamSessionId:He.string(),sessionId:He.string().optional(),deletedAt:He.string(),upstreamUpdatedAt:He.string().optional(),cwd:He.string().optional(),title:He.string().optional(),reason:He.enum(["user","expired"]).optional(),interactive:He.boolean().optional()}),$s=class{async add(e){let t={version:1,...e};await me(T.tombstoneFile(e.agentId,e.upstreamSessionId),t,{mode:384})}async has(e,t){try{return await nt.access(T.tombstoneFile(e,t)),!0}catch{return!1}}async read(e,t){let n=T.tombstoneFile(e,t),r=await de(n);if(r===void 0)return await this.has(e,t)?{version:1,agentId:e,upstreamSessionId:t,deletedAt:new Date(0).toISOString()}:void 0;try{return Wm.parse(r)}catch{return{version:1,agentId:e,upstreamSessionId:t,deletedAt:new Date(0).toISOString()}}}async remove(e,t){try{await nt.unlink(T.tombstoneFile(e,t))}catch(n){if(n.code!=="ENOENT")throw n}try{await nt.rmdir(T.tombstoneAgentDir(e))}catch(n){let r=n;if(r.code!=="ENOENT"&&r.code!=="ENOTEMPTY")throw n}}async list(e){if(e!==void 0)return this.listForAgent(e);let t;try{t=await nt.readdir(T.tombstonesDir())}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t){let o;try{o=decodeURIComponent(r)}catch{continue}n.push(...await this.listForAgent(o))}return n}async listForAgent(e){let t;try{t=await nt.readdir(T.tombstoneAgentDir(e))}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t){let o;try{o=decodeURIComponent(r)}catch{continue}let i=await this.read(e,o);i&&n.push(i)}return n}};function tc(s,e){return s.reason==="user"||e===void 0?!1:s.upstreamUpdatedAt===void 0?!0:e>s.upstreamUpdatedAt}import*as mc from"fs/promises";import{customAlphabet as Zm}from"nanoid";import{fileURLToPath as qm}from"url";import*as _n from"path";import*as Os from"fs";function zm(){try{let s=_n.dirname(qm(import.meta.url));for(let e=0;e<8;e+=1){let t=_n.join(s,"package.json");if(Os.existsSync(t)){let r=JSON.parse(Os.readFileSync(t,"utf8"));if(typeof r.version=="string"&&r.version.length>0&&(typeof r.name!="string"||r.name.includes("hydra-acp")))return r.version}let n=_n.dirname(s);if(n===s)break;s=n}}catch{}return"0.0.0"}var ue=zm(),Fs="hydra-acp-cat";var Jm=12e4;async function sc(s,e,t){let n=s.timeoutMs??Jm,r,o,i=!1;try{let a=(async()=>{r=ct.spawn({agentId:s.agentId,cwd:s.cwd,plan:s.plan,logger:s.logger});let d=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:{},clientInfo:{name:"hydra-synopsis",version:ue}}),c=await r.connection.request("session/new",{cwd:s.cwd,mcpServers:[]}),u=c.sessionId;if(typeof u!="string"){s.logger?.warn(`synopsis: agent ${s.agentId} returned non-string sessionId from session/new`),s.onFailure?.(`agent ${s.agentId} did not return a sessionId from session/new`);return}if(s.onWorkerSpawned?.(u,r.pid),s.modelId){let h=Gm(c);if(h.size===0||h.has(s.modelId)){let k=r.connection;try{await ut({request:(m,g)=>k.request(m,g),sessionId:u,modelId:s.modelId,verb:Ut(c),logger:s.logger})}catch(m){s.logger?.warn(`synopsis: agent ${s.agentId} rejected model change to ${JSON.stringify(s.modelId)}: ${m.message}; continuing on default`)}}else s.logger?.warn(`synopsis: model ${JSON.stringify(s.modelId)} not advertised by agent ${s.agentId} (have [${[...h].join(", ")}]); continuing on default`)}let l=[];r.connection.onNotification("session/update",h=>{let k=Vm(h);k.length>0&&l.push(k)}),await r.connection.request("session/prompt",{sessionId:u,prompt:[{type:"text",text:e}]});let p=l.join(""),f=t(p);if(!f){let h=JSON.stringify(p.slice(0,200));s.logger?.warn(`synopsis: agent ${s.agentId} reply did not parse (replyLen=${p.length} preview=${h})`);let k=p.slice(0,120).replace(/\s+/g," ").trim();s.onFailure?.(`agent ${s.agentId} returned unparseable JSON (${p.length} chars): ${k}${p.length>120?"\u2026":""}`)}return f})();return await new Promise((d,c)=>{o=setTimeout(()=>{i=!0,s.logger?.warn(`synopsis: agent ${s.agentId} timed out after ${n}ms`),s.onFailure?.(`agent ${s.agentId} timed out after ${n}ms`),d(void 0)},n),o.unref?.(),a.then(u=>{o&&clearTimeout(o),i||d(u)},u=>{o&&clearTimeout(o),i||c(u)})})}catch(a){let d=a.message;s.logger?.warn(`synopsis: agent ${s.agentId} failed: ${d}`),s.onFailure?.(`agent ${s.agentId} failed: ${d}`);return}finally{o&&clearTimeout(o),r&&await r.kill().catch(()=>{})}}async function Ns(s){let e=Gt(s.history,{maxChars:s.maxTranscriptChars}),t=s.sessionId!==void 0?`[hydra-acp title-regen worker for session ${s.sessionId}]`:"[hydra-acp title-regen worker]",n=e.length>0?`${t}
126
+ Use empty arrays/strings where a field doesn't apply.`;function qd(s){let e=s.trim();if(e.length===0)return;let t=Xt(e);if(t===void 0){let c=e.indexOf("{"),u=e.lastIndexOf("}");c>=0&&u>c&&(t=Xt(e.slice(c,u+1)))}if(t===void 0){let c=zd(e);c!==void 0&&(t=Xt(c))}if(t===void 0||t===null||typeof t!="object")return;let n=t,r={};if(typeof n.title=="string"){let c=n.title.trim();c.length>0&&(r.title=c.slice(0,Bd))}let o={},i=!1,a=["goal","outcome"];for(let c of a)if(typeof n[c]=="string"){let u=n[c].trim();u.length>0&&(o[c]=u,i=!0)}let d=["files_touched","tools_used","rejected_approaches","open_threads","decisions","file_edit_intentions","unresolved_errors","tool_state"];for(let c of d)if(Array.isArray(n[c])){let u=n[c],l=Z.array(Z.string()).safeParse(u);l.success&&u.length>0&&(o[c]=l.data,i=!0)}if(i&&(r.synopsis=o),!(r.title===void 0&&r.synopsis===void 0))return r}function Xt(s){try{return JSON.parse(s)}catch{return}}function zd(s){let e=s.indexOf("{");if(e<0)return;let t=0,n=!1,r=!1;for(let o=e;o<s.length;o++){let i=s[o];if(n){r?r=!1:i==="\\"?r=!0:i==='"'&&(n=!1);continue}if(i==='"'){n=!0;continue}if(i==="{")t++;else if(i==="}"&&(t--,t===0))return s.slice(e,o+1)}}function km(s){return s.goal!==void 0&&s.goal.trim().length>0||s.outcome!==void 0&&s.outcome.trim().length>0||s.files_touched!==void 0&&s.files_touched.length>0||s.tools_used!==void 0&&s.tools_used.length>0||s.rejected_approaches!==void 0&&s.rejected_approaches.length>0||s.open_threads!==void 0&&s.open_threads.length>0||s.decisions!==void 0&&s.decisions.length>0||s.file_edit_intentions!==void 0&&s.file_edit_intentions.length>0||s.unresolved_errors!==void 0&&s.unresolved_errors.length>0||s.tool_state!==void 0&&s.tool_state.length>0}var bm="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Sm=vm(bm,16),Im="hydra_lineage_";function Pn(){return`${Im}${Sm()}`}var Ro=P.object({name:P.string(),description:P.string().optional()}),xo=P.object({id:P.string(),name:P.string().optional(),description:P.string().optional()}),Am=P.object({modelId:P.string(),name:P.string().optional(),description:P.string().optional()}),To=P.object({used:P.number().optional(),size:P.number().optional(),costAmount:P.number().optional(),costCurrency:P.string().optional(),cumulativeCost:P.number().optional()}),Eo=P.object({name:P.string(),version:P.string().optional()}),Cm=P.object({path:P.string(),sourceCwd:P.string(),label:P.string(),requestedLabel:P.string().optional(),provider:P.string(),snapshot:P.string().optional(),line:P.string().optional(),vcs:P.record(P.string(),P.string()).optional(),clean:P.boolean().optional()}),Rm=P.object({previousUpstreamSessionId:P.string(),previousSummarizedThroughEntry:P.number().int().nonnegative().optional(),runId:P.string().optional()}),xm=P.enum(["compaction","agent-swap","workspace-enter","workspace-leave","rollback","restart"]),Tm=P.object({upstreamSessionId:P.string(),agentId:P.string(),reason:xm.optional(),runId:P.string().optional(),startedAt:P.string().optional(),endedAt:P.string().optional(),cost:P.number().nonnegative().optional(),lifetimeCostAtStart:P.number().nonnegative().optional(),usedAtStart:P.number().nonnegative().optional(),usedAtEnd:P.number().nonnegative().optional(),inferred:P.boolean().optional()}),Em=P.object({version:P.literal(1),sessionId:P.string(),lineageId:P.string().optional(),upstreamSessionId:P.string(),importedFromSessionId:P.string().optional(),importedFromUpstreamSessionId:P.string().optional(),importedFromMachine:P.string().optional(),agentId:P.string(),cwd:P.string(),title:P.string().optional(),synopsis:Tn.optional(),compactionState:Ud.optional(),rollbackBreadcrumb:Rm.optional(),upstreamGenerations:P.array(Tm).optional(),summarizedThroughEntry:P.number().int().nonnegative().optional(),agentArgs:P.array(P.string()).optional(),currentModel:P.string().optional(),currentMode:P.string().optional(),currentUsage:To.optional(),agentCommands:P.array(Ro).optional(),agentModes:P.array(xo).optional(),agentModels:P.array(Am).optional(),configOptionValues:P.record(P.string(),P.string()).optional(),pendingHistorySync:P.boolean().optional(),pendingAgentSwap:P.string().optional(),parentSessionId:P.string().optional(),forkedFromSessionId:P.string().optional(),forkedFromMessageId:P.string().optional(),side:jt.optional(),forkSynthesisState:P.enum(["running","failed"]).optional(),originatingClient:Eo.optional(),interactive:P.boolean().optional(),priority:P.number().int().nonnegative().optional(),lastTurnEndedAt:P.number().int().nonnegative().optional(),readAt:P.number().int().nonnegative().optional(),forwardedEnv:P.record(P.string(),P.string()).optional(),workspace:Cm.optional(),attentionFlags:Ld.default([]).optional(),extensionState:P.record(P.string(),P.record(P.string(),P.unknown())).default({}).optional(),createdAt:P.string(),updatedAt:P.string()}),En=/^[A-Za-z0-9_-]+$/;function Pm(s){if(!En.test(s))throw new Error(`unsafe session id: ${s}`)}var As=class{index;indexSeed;async write(e){Pm(e.sessionId);let t={version:1,...e};await me(E.sessionFile(e.sessionId),t,{mode:384}),await this.reindex(e.sessionId)}async touch(e){if(!En.test(e))return;let t=new Date;try{await $e.utimes(E.sessionFile(e),t,t)}catch(n){if(n.code!=="ENOENT")throw n;return}await this.reindex(e)}async markDeleted(e,t){await this.ensureIndex();let n=this.index.get(e);n&&!n.deleted||n&&n.mtimeMs>=t||this.index.set(e,{mtimeMs:t,deleted:!0})}async cursor(){await this.ensureIndex();let e=0;for(let t of this.index.values())t.mtimeMs>e&&(e=t.mtimeMs);return e}async listChangedSince(e){let t=await this.cursor(),n=[],r=[];for(let[a,d]of this.index)d.mtimeMs<e||(d.deleted?r.push(a):n.push(a));let o=await Promise.all(n.map(a=>this.read(a).catch(()=>{}))),i=[];for(let a of o)a&&i.push(a);return{records:i,removed:r,cursor:t}}async ensureIndex(){this.index||(this.indexSeed||(this.indexSeed=this.seedIndex()),await this.indexSeed)}async seedIndex(){let e=new Map,t=[];try{t=await $e.readdir(E.sessionsDir())}catch(n){if(n.code!=="ENOENT")throw n}await Promise.all(t.map(async n=>{if(En.test(n))try{let r=await $e.stat(E.sessionFile(n));e.set(n,{mtimeMs:r.mtimeMs,deleted:!1})}catch{}})),this.index=e}async reindex(e){if(this.indexSeed){await this.indexSeed;try{let t=await $e.stat(E.sessionFile(e));this.index.set(e,{mtimeMs:t.mtimeMs,deleted:!1})}catch{}}}async read(e){if(!En.test(e))return;let t=await de(E.sessionFile(e));if(t!==void 0)try{return Em.parse(t)}catch{return}}async delete(e){if(En.test(e)){this.indexSeed&&(await this.indexSeed,this.index.set(e,{mtimeMs:Date.now(),deleted:!0}));try{await $e.unlink(E.sessionFile(e))}catch(t){if(t.code!=="ENOENT")throw t}try{await $e.rmdir(E.sessionDir(e))}catch(t){let n=t;if(n.code!=="ENOENT"&&n.code!=="ENOTEMPTY")throw t}}}async findByLineageId(e){if(e.length===0)return;let t=await this.list().catch(()=>[]);for(let n of t)if(n.lineageId===e)return n}async list(){let e;try{e=await $e.readdir(E.sessionsDir())}catch(r){if(r.code==="ENOENT")return[];throw r}let t=await Promise.all(e.map(r=>this.read(r).catch(()=>{}))),n=[];for(let r of t)r&&n.push(r);return n}};function Po(s){let e=new Date().toISOString(),t=s.createdAt??e,n=(s.currentUsage?.cumulativeCost??0)+(s.currentUsage?.costAmount??0),r=s.upstreamGenerations??(s.upstreamSessionId?[{upstreamSessionId:s.upstreamSessionId,agentId:s.agentId,startedAt:t,...n===0?{lifetimeCostAtStart:0}:{}}]:[]);return{sessionId:s.sessionId,lineageId:s.lineageId,upstreamSessionId:s.upstreamSessionId,importedFromSessionId:s.importedFromSessionId,importedFromUpstreamSessionId:s.importedFromUpstreamSessionId,importedFromMachine:s.importedFromMachine,agentId:s.agentId,cwd:s.cwd,title:s.title,synopsis:s.synopsis,summarizedThroughEntry:s.summarizedThroughEntry,compactionState:s.compactionState,rollbackBreadcrumb:s.rollbackBreadcrumb,upstreamGenerations:r,agentArgs:s.agentArgs,currentModel:s.currentModel,currentMode:s.currentMode,currentUsage:s.currentUsage,agentCommands:s.agentCommands,agentModes:s.agentModes,agentModels:s.agentModels,configOptionValues:s.configOptionValues,pendingHistorySync:s.pendingHistorySync,pendingAgentSwap:s.pendingAgentSwap,parentSessionId:s.parentSessionId,forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,side:s.side,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:s.interactive,priority:s.priority,lastTurnEndedAt:s.lastTurnEndedAt,readAt:s.readAt,forwardedEnv:s.forwardedEnv,workspace:s.workspace,attentionFlags:s.attentionFlags??[],extensionState:s.extensionState??{},createdAt:t,updatedAt:s.updatedAt??e}}je();Y();import*as ae from"fs/promises";import*as Se from"path";Y();import*as Cs from"path";import{createHash as Mm}from"crypto";var Ne=class extends Error{constructor(e,t){super(`provider "${e}" does not support ${t}; check capabilities().supports before calling`),this.name="WorkspaceUnsupportedError"}};function Zt(s){let e=Mm("sha256").update(Cs.resolve(s)).digest("hex").slice(0,12);return Cs.join(z(),"workspaces",e)}async function Rs(s,e,t=100){if(await e(s))return s;for(let n=2;n<=t;n+=1){let r=`${s}-${n}`;if(await e(r))return r}}function Ct(s,e=10){if(s.length<=e)return[...s];let t=s.slice(0,e),n=s.length-e;return[...t,`... and ${n} more`]}function Mo(s){return s.changedPaths.length>0||s.recorded!==void 0&&s.recorded!==s.actual}function _m(s){let e=[];for(let t of s){if(t.changedPaths.length===0){e.push(`${t.relPath} (nested tree advanced to ${t.actual.slice(0,8)})`);continue}for(let n of t.changedPaths)e.push(`${t.relPath}/${n}`)}return e}function _o(s,e){let t=new Set(e.map(r=>r.relPath));return[...s.filter(r=>!t.has(r.replace(/\/$/,""))),..._m(e.filter(Mo))]}function xs(s){let e=s.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return e.length>0?e.slice(0,64):"workspace"}var $o="copy",Vd=new Set([".git"]);function Mn(s){return`${s}.manifest.json`}async function Jd(s){let e=new Map,t=[s];for(;t.length>0;){let n=t.pop();if(n===void 0)break;let r;try{r=await ae.readdir(n,{withFileTypes:!0})}catch{continue}for(let o of r){let i=Se.join(n,o.name);if(!(n===s&&Vd.has(o.name))){if(o.isDirectory()){t.push(i);continue}if(o.isFile())try{let a=await ae.stat(i);e.set(Se.relative(s,i),{size:a.size,mtimeMs:a.mtimeMs})}catch{continue}}}}return e}var Ts=class{kind=$o;capabilities(){return{cheapWorkspaces:!1,sharedHistory:!1,nonMutatingCapture:!0,conflictReporting:!1,locking:!1,requiresServer:!1,supports:{record:!1,integrate:!1,captureWorkingState:!1,changedPaths:!1,environmentNotes:!0,rematerialize:!1,nestedTrees:!1}}}async materializeNested(){return{ok:!0,count:0}}async retainSnapshot(){}async dropSnapshotRef(){}async rematerialize(e){return{ok:!1,reason:`copy provider retains nothing outside ${e.path}; it cannot be rebuilt`}}async createWorkspace(e){if(e.from!==void 0)return{ok:!1,reason:"copy provider cannot create from a snapshot; it records none"};let t=Se.resolve(e.sourceCwd),n=e.contentFrom!==void 0?Se.resolve(e.contentFrom):t;try{n=await ae.realpath(n)}catch{}try{if(!(await ae.stat(n)).isDirectory())return{ok:!1,reason:`${n} is not a directory`}}catch{return{ok:!1,reason:`${n} does not exist`}}let r=Zt(t);try{await ae.mkdir(r,{recursive:!0})}catch(u){return{ok:!1,reason:`could not create workspace root: ${String(u)}`}}let o=await Rs(xs(e.label),async u=>ae.access(Se.join(r,u)).then(()=>!1).catch(()=>!0));if(o===void 0)return{ok:!1,reason:`no free name available for "${e.label}"`};let i=Se.join(r,o),a;try{a=await ae.readdir(n)}catch(u){return{ok:!1,reason:`copy failed: ${String(u)}`}}try{await ae.mkdir(i,{recursive:!0});for(let u of a)Vd.has(u)||await ae.cp(Se.join(n,u),Se.join(i,u),{recursive:!0,errorOnExist:!1,force:!0})}catch(u){return await ae.rm(i,{recursive:!0,force:!0}).catch(()=>{}),{ok:!1,reason:`copy failed: ${String(u)}`}}let d=await Jd(i),c={sourceCwd:t,label:o,createdAt:new Date().toISOString(),entries:Object.fromEntries(d)};return await me(Mn(i),c,{pretty:!1}),{ok:!0,workspace:{path:i,sourceCwd:t,label:o,provider:this.kind}}}async removeWorkspace(e,t){if(!t.force){let n=await this.status(e);if(!n.clean)throw new Error(`workspace ${e.path} has ${n.changedPaths.length} changed path(s); pass force to remove`)}await ae.rm(e.path,{recursive:!0,force:!0}),await ae.rm(Mn(e.path),{force:!0})}async listWorkspaces(e){let t=Zt(Se.resolve(e)),n;try{n=await ae.readdir(t)}catch{return[]}let r=[];for(let o of n){if(o.endsWith(".manifest.json"))continue;let i=Se.join(t,o),a=await de(Mn(i));a!==void 0&&r.push({path:i,sourceCwd:a.sourceCwd,label:a.label,provider:this.kind})}return r}async status(e){let t=await de(Mn(e.path)),n=await Jd(e.path);if(t===void 0)return{clean:!1,changedPaths:[...n.keys()].sort(),hasRecordedWork:!1};let r=[];for(let[o,i]of n){let a=t.entries[o];(a===void 0||a.size!==i.size||a.mtimeMs!==i.mtimeMs)&&r.push(o)}for(let o of Object.keys(t.entries))n.has(o)||r.push(o);return r.sort(),{clean:r.length===0,changedPaths:r,hasRecordedWork:!1}}async statusReport(e){let{changedPaths:t}=await this.status(e),n=t.length===0?["no changes since this copy was made"]:[`${t.length} changed file(s) since this copy was made:`,...Ct(t.map(r=>` ${r}`))];return n.push(`Not tracking ${$(e.sourceCwd)}: a copied directory has no shared history, so there is nothing to be in or out of sync with.`),n}async environmentNotes(e){return[`This directory is an isolated copy of ${e.sourceCwd}. It is not under version control: there is no history, no branches, and version-control commands will not behave as they would in the original.`,"Changes here are not automatically returned to the original directory."]}async captureWorkingState(){throw new Ne(this.kind,"captureWorkingState")}async record(){throw new Ne(this.kind,"record")}async attributeOrphan(e){let t=await de(Mn(e));if(t?.sourceCwd!==void 0)return{path:e,sourceCwd:t.sourceCwd,label:t.label??Se.basename(e),provider:this.kind}}async discardLine(){return{ok:!0,dropped:0}}ownsLine(){return!1}async pruneStale(){}async changedPaths(){throw new Ne(this.kind,"changedPaths")}async integrate(){return{ok:!1,conflicts:[],declined:!0,reason:`the "${this.kind}" provider keeps no history, so there is nothing to integrate from`}}async currentState(){}async contentId(){}async currentLineName(){}async resolveRoot(e){return e}async resolveRetained(){}async contains(){return!1}async divergence(){}async changedPathsBetween(){return[]}async captureDelta(){throw new Ne(this.kind,"captureDelta")}async applyDelta(){return{ok:!1,reason:`the "${this.kind}" provider cannot reproduce a captured change`}}async resetTo(){return{ok:!1,reason:`the "${this.kind}" provider records no state to return to`}}async integrationInProgress(){return!1}async abortIntegration(){}async conflictedPaths(){return[]}async listNested(){return[]}async captureNested(){return[]}async reproduceNested(){return{applied:[],failed:[]}}async integrateNested(){return{applied:[],failed:[]}}async lock(){throw new Ne(this.kind,"lock")}async unlock(){throw new Ne(this.kind,"unlock")}};Y();import{execFile as Xd}from"child_process";import{randomBytes as Nm}from"crypto";import*as De from"fs/promises";import*as Zd from"os";import*as ee from"path";function $m(s){let e=s.indexOf(" ");return e===-1?{key:s,value:""}:{key:s.slice(0,e),value:s.slice(e+1)}}function Gd(s){let e=[],t,n=()=>{t!==void 0&&(e.push(t),t=void 0)};for(let r of s.split(`
127
+ `)){let o=r.replace(/\r$/,"");if(o.length===0){n();continue}let{key:i,value:a}=$m(o);if(i==="worktree"){n(),t={path:a,bare:!1,detached:!1};continue}if(t!==void 0)switch(i){case"HEAD":t.head=a;break;case"branch":t.branch=a;break;case"bare":t.bare=!0;break;case"detached":t.detached=!0;break;case"locked":t.lockedReason=a;break;case"prunable":t.prunableReason=a;break;default:break}}return n(),e}function Kd(s){if(s===void 0)return;let e="refs/heads/";return s.startsWith(e)?s.slice(e.length):s}var Ms="git",Qd="hydra-acp:",Oo="hydra",J=5e3,pe=12e4,Es=9e5;function Yd(s){return De.access(s).then(()=>!0).catch(()=>!1)}function _n(s){return s.length===0?s:ee.normalize(s)}function Dm(s){return De.realpath(s).catch(()=>s)}function H(s,e,t,n){return new Promise(r=>{Xd("git",s,{cwd:e,timeout:t,maxBuffer:8*1024*1024,...n?{env:{...process.env,...n}}:{}},(o,i,a)=>{r({ok:!o,stdout:i??"",stderr:a??""})})})}function Fo(s,e,t,n=pe){return new Promise(r=>{let o=Xd("git",s,{cwd:e,timeout:n,maxBuffer:67108864},(i,a,d)=>{r({ok:!i,stdout:a??"",stderr:d??""})});o.stdin?.on("error",()=>{}),o.stdin?.end(t)})}function No(s){let e=[];for(let t of s.split(`
128
+ `)){let n=t.replace(/\r$/,"");if(n.length<4)continue;let r=n.slice(3),o=r.indexOf(" -> ");e.push({code:n.slice(0,2),path:o===-1?r:r.slice(o+4)})}return e}var Ps=class{kind=Ms;refRoot(e){return e.vcs?.repoRoot??e.sourceCwd}ownsLine(e){return e.startsWith(`${Oo}/`)}capabilities(){return{cheapWorkspaces:!0,sharedHistory:!0,nonMutatingCapture:!0,conflictReporting:!0,locking:!0,requiresServer:!1,supports:{record:!0,integrate:!0,captureWorkingState:!0,changedPaths:!1,environmentNotes:!0,rematerialize:!0,nestedTrees:!0}}}async materializeNested(e,t){if(!await Yd(ee.join(e.path,".gitmodules")))return{ok:!0,count:0};let r=await H(["submodule","update","--init","--recursive",...t?.discardLocal===!0?["--force"]:[]],e.path,Es);if(!r.ok)return{ok:!1,count:0,reason:r.stderr.trim()||"git submodule update --init failed"};if(t?.discardLocal===!0){let a=await H(["submodule","foreach","--recursive","git","reset","--hard"],e.path,Es);if(!a.ok)return{ok:!1,count:0,reason:a.stderr.trim()||"could not reset submodules"};let d=t.purgeIgnored===!0?"-ffdx":"-fd",c=await H(["submodule","foreach","--recursive","git","clean",d],e.path,Es);if(!c.ok)return{ok:!1,count:0,reason:c.stderr.trim()||"could not clean submodules"}}let o=await H(["submodule","status","--recursive"],e.path,J);return{ok:!0,count:o.ok?o.stdout.split(`
129
+ `).filter(a=>a.trim().length>0).length:0}}async rematerialize(e){let t=e.vcs?.branch;if(t===void 0)return{ok:!1,reason:"workspace has no recorded branch to restore from"};let n=this.refRoot(e);if(!await Yd(n))return{ok:!1,reason:`source repository ${n} no longer exists`};let r=await H(["rev-parse","--verify","--quiet",`refs/heads/${t}`],n,J);if(!r.ok||r.stdout.trim().length===0)return{ok:!1,reason:`branch ${t} no longer exists in ${n}`};await H(["worktree","unlock",e.path],n,J),await H(["worktree","prune"],n,J);let o=await H(["worktree","add",e.path,t],n,pe);return o.ok?{ok:!0,workspace:{...e,line:t,vcs:{...e.vcs??{},kind:"git",branch:t,repoRoot:n}}}:{ok:!1,reason:`could not restore worktree: ${o.stderr.trim()||"unknown error"}`}}async createWorkspace(e){let t=ee.resolve(e.sourceCwd),n=await H(["rev-parse","--show-toplevel"],t,J);if(!n.ok)return{ok:!1,reason:`${t} is not a git repository (or git is unavailable)`};let r=_n(n.stdout.trim());if(r.length===0)return{ok:!1,reason:`could not resolve the repository root for ${t}`};let o=await H(["rev-parse","HEAD"],r,J);if(!o.ok)return{ok:!1,reason:`${r} has no commits yet, so there is nothing to branch from`};let i=e.from??o.stdout.trim(),a=xs(e.label),d=Zt(t);try{await De.mkdir(d,{recursive:!0})}catch(f){return{ok:!1,reason:`could not create workspace root: ${String(f)}`}}let c=await Rs(a,async f=>await De.access(ee.join(d,f)).then(()=>!0).catch(()=>!1)?!1:!(await H(["rev-parse","--verify","--quiet",`refs/heads/${Oo}/${f}`],r,J)).ok);if(c===void 0)return{ok:!1,reason:`no free name available for "${a}"`};let u=ee.join(d,c),l=`${Oo}/${c}`,p=await H(["worktree","add","--no-track","-b",l,u,i],r,pe);return p.ok?{ok:!0,workspace:{path:u,sourceCwd:t,label:c,provider:this.kind,snapshot:i,line:l,vcs:{kind:"git",branch:l,base:i,repoRoot:r}}}:{ok:!1,reason:`git worktree add failed: ${p.stderr.trim()||"unknown error"}`}}async removeWorkspace(e,t){if(!t.force){let o=await this.status(e);if(!o.clean)throw new Error(`workspace ${e.path} has ${o.changedPaths.length} changed path(s)${o.hasRecordedWork?" and unintegrated recorded work":""}; pass force to remove`)}let n=this.refRoot(e);await this.unlock(e).catch(()=>{});let r=await H(["worktree","remove","--force",e.path],n,pe);t.discardLine===!0&&e.vcs?.branch!==void 0&&await H(["branch","-D",e.vcs.branch],n,J),r.ok||(await De.rm(e.path,{recursive:!0,force:!0}),await H(["worktree","prune"],n,J))}async listWorkspaces(e){let t=ee.resolve(e),n=await H(["rev-parse","--show-toplevel"],t,J);if(!n.ok)return[];let r=_n(n.stdout.trim()),o=await H(["worktree","list","--porcelain"],r,J);if(!o.ok)return[];let i=Zt(t),a=await Dm(i),d=[];for(let c of Gd(o.stdout)){let u=_n(c.path),l=ee.dirname(u);if(l!==i&&l!==a)continue;let p=ee.join(i,ee.basename(u)),f={kind:"git",repoRoot:r},h=Kd(c.branch);h!==void 0&&(f.branch=h),c.head!==void 0&&(f.head=c.head),c.lockedReason!==void 0&&(f.locked=c.lockedReason);let k=c.lockedReason?.startsWith(Qd)===!0;d.push({path:p,sourceCwd:t,label:ee.basename(p),...k?{heldByUs:!0}:{},provider:this.kind,...h!==void 0?{line:h}:{},vcs:f})}return d}async status(e){let t=await H(["status","--porcelain","--untracked-files=all"],e.path,J);if(!t.ok)return{clean:!1,changedPaths:[],hasRecordedWork:!1};let n=No(t.stdout),r=n.map(a=>a.path),o=n.some(({code:a})=>a!=="??"&&a[0]!==" "&&a[0]!=="?"),i=!1;if(e.snapshot!==void 0){let a=await H(["rev-list","--count",`${e.snapshot}..HEAD`],e.path,J);a.ok&&(i=Number.parseInt(a.stdout.trim(),10)>0)}return{clean:r.length===0&&!i,changedPaths:r,hasRecordedWork:i,hasStagedWork:o}}async lock(e,t){let n=this.refRoot(e);await H(["worktree","lock","--reason",`${Qd}${t}`,e.path],n,J)}async unlock(e){let t=this.refRoot(e);await H(["worktree","unlock",e.path],t,J)}async environmentNotes(e){let t=[],n=e.vcs?.branch;return t.push(`This directory is a git worktree of ${e.sourceCwd}${n!==void 0?`, on branch ${n}`:""}. Do not read or write ${e.sourceCwd} directly; paths under it refer to the corresponding file here. Prefer repo-relative paths, which are identical in both.`),t.push("`.git` here is a file, not a directory. That is normal for a worktree and does not need repairing."),await De.access(ee.join(e.path,".gitmodules")).then(()=>!0).catch(()=>!1)&&t.push("Submodules here are initialized and checked out at the commits this tree records, which means each sits on a detached HEAD. That is normal and does not need repairing. Never re-add a submodule's contents as ordinary tracked files in the superproject: that silently corrupts the integration back to the source branch."),t}async statusReport(e){let t=[],n=await H(["status","--porcelain","--untracked-files=all"],e.path,J);if(n.ok){let r=No(n.stdout);if(r.length===0)t.push("no uncommitted changes");else{let o=0,i=0,a=0;for(let{code:c}of r){if(c==="??"){a+=1;continue}c[0]!==" "&&c[0]!=="?"&&(o+=1),c[1]!==" "&&c[1]!=="?"&&(i+=1)}let d=[];o>0&&d.push(`${o} staged`),i>0&&d.push(`${i} unstaged`),a>0&&d.push(`${a} untracked`),t.push(`${d.join(", ")}:`),t.push(...Ct(r.map(c=>` ${c.code} ${c.path}`)))}}return t.push(...await this.syncLines(e)),t}async syncLines(e){if(e.vcs?.branch===void 0)return[];let[t,n]=await Promise.all([H(["rev-parse","HEAD"],e.sourceCwd,J),H(["rev-parse","HEAD"],e.path,J)]),r=t.stdout.trim(),o=n.stdout.trim();if(!t.ok||!n.ok||r.length===0||o.length===0)return[];let i=$(e.sourceCwd);if(r===o)return[`in sync with ${i}`];let a=await H(["rev-list","--left-right","--count",`${r}...${o}`],e.path,J),d=a.stdout.trim().split(/\s+/).map(p=>Number.parseInt(p,10)),c=d[0],u=d[1];if(!a.ok||c===void 0||u===void 0||!Number.isFinite(c)||!Number.isFinite(u))return[];let l=[];return c>0&&l.push(`${c} commit(s) behind ${i}. \`/hydra workspace sync\` brings them in; landing is fast-forward-only, so this also unblocks \`stop\`.`),u>0&&l.push(`${u} commit(s) recorded here and not landed yet.`),l}async captureWorkingState(e,t){let n=ee.join(Zd.tmpdir(),`hydra-index-${process.pid}-${Nm(6).toString("hex")}`),r={GIT_INDEX_FILE:n};try{let o=await H(["rev-parse","--verify","HEAD"],e,J),i=o.ok&&o.stdout.trim().length>0;if(i){let l=await H(["read-tree","HEAD"],e,pe,r);if(!l.ok)throw new Error(`could not seed the snapshot index: ${l.stderr.trim()}`)}let a=await H(["add","-A"],e,pe,r);if(!a.ok)throw new Error(`could not stage working state: ${a.stderr.trim()}`);let d=await H(["write-tree"],e,pe,r);if(!d.ok||d.stdout.trim().length===0)throw new Error(`could not write tree: ${d.stderr.trim()}`);let c=["commit-tree",d.stdout.trim(),"-m",t];i&&c.push("-p",o.stdout.trim());let u=await H(c,e,pe,r);if(!u.ok||u.stdout.trim().length===0)throw new Error(`could not create snapshot commit: ${u.stderr.trim()}`);return u.stdout.trim()}finally{await De.rm(n,{force:!0}).catch(()=>{})}}async retainSnapshot(e,t,n){let r=this.refRoot(e);await H(["update-ref","--create-reflog",t,n],r,J)}async dropSnapshotRef(e,t){let n=this.refRoot(e);await H(["update-ref","-d",t],n,J)}async currentState(e){let t=await H(["rev-parse","HEAD"],e,J),n=t.stdout.trim();return t.ok&&n.length>0?n:void 0}async contentId(e,t){let n=await H(["rev-parse",`${t}^{tree}`],e,J),r=n.stdout.trim();return n.ok&&r.length>0?r:void 0}async currentLineName(e){let t=await H(["rev-parse","--abbrev-ref","HEAD"],e,J),n=t.stdout.trim();return t.ok&&n.length>0?n:void 0}async resolveRoot(e){let t=await H(["rev-parse","--show-toplevel"],e,J),n=_n(t.stdout.trim());return t.ok&&n.length>0?n:void 0}async resolveRetained(e,t){let n=await H(["rev-parse","--verify","--quiet",`${t}^{commit}`],this.refRoot(e),J),r=n.stdout.trim();return n.ok&&r.length>0?r:void 0}async contains(e,t){return(await H(["merge-base","--is-ancestor",t.state,t.within],e,J)).ok}async divergence(e,t,n){let r=await H(["rev-list","--left-right","--count",`${t}...${n}`],e,J);if(!r.ok)return;let o=r.stdout.trim().split(/\s+/).map(d=>Number.parseInt(d,10)),i=o[0],a=o[1];if(!(i===void 0||a===void 0||!Number.isFinite(i)||!Number.isFinite(a)))return{ahead:i,behind:a}}async changedPathsBetween(e,t,n){let r=await H(["diff","--name-only",t,n],e,J);return r.ok?r.stdout.split(`
130
+ `).map(o=>o.replace(/\r$/,"").trim()).filter(o=>o.length>0):[]}async captureDelta(e,t,n){let r=await H(["diff","--binary","--ignore-submodules=all",t,n],e,pe);if(r.ok)return r.stdout}async applyDelta(e,t,n){if(t.trim().length===0)return{ok:!0,alreadyPresent:!0};let r=n?.stage===!0?["--index"]:[],o=await Fo(["apply",...r],e,t);if(o.ok)return{ok:!0};if(n?.tolerant!==!0)return{ok:!1,reason:o.stderr.trim()||"the change did not apply"};if((await Fo(["apply","--reverse","--check"],e,t)).ok)return{ok:!0,alreadyPresent:!0};let a=await Fo(["apply","--3way"],e,t);return a.ok?{ok:!0}:{ok:!1,reason:a.stderr.trim()||"the change overlaps what is already there"}}async resetTo(e,t,n){let r=await H(["reset","--hard",t],e,pe);if(!r.ok)return{ok:!1,reason:r.stderr.trim()||"could not return to that state"};let o=await H(["clean",n?.purgeIgnored===!0?"-ffdx":"-fd"],e,pe);if(!o.ok)return{ok:!1,reason:o.stderr.trim()||"returned to that state but could not remove extra files"};let i=await this.materializeNested({path:e,sourceCwd:e,label:"",provider:this.kind},{discardLocal:!0,...n?.purgeIgnored===!0?{purgeIgnored:!0}:{}});return i.ok?{ok:!0}:{ok:!1,reason:i.reason??"could not reset nested trees"}}async integrationInProgress(e){return(await H(["rev-parse","-q","--verify","MERGE_HEAD"],e,J)).ok}async abortIntegration(e){await H(["merge","--abort"],e,pe)}async conflictedPaths(e){let t=await H(["diff","--name-only","--diff-filter=U"],e,J);return t.ok?t.stdout.split(`
131
+ `).map(n=>n.replace(/\r$/,"").trim()).filter(n=>n.length>0):[]}async record(e,t){let n=await H(["add","-A"],e.path,pe);if(!n.ok)throw new Error(`could not stage ${e.path}: ${n.stderr.trim()||"unknown error"}`);let r=await this.status(e),o=await this.currentState(e.path);if(r.changedPaths.length===0){if(o===void 0)throw new Error(`could not read the state of ${e.path}`);return o}let i=await H(["commit","-m",t],e.path,pe);if(!i.ok)throw new Error(`could not record ${e.path}: ${i.stderr.trim()||i.stdout.trim()||"unknown error"}`);let a=await this.currentState(e.path);if(a===void 0)throw new Error(`recorded ${e.path} but could not read the resulting state`);return a}async attributeOrphan(e){let t=await H(["rev-parse","--path-format=absolute","--git-common-dir"],e,J),n=_n(t.stdout.trim());if(!t.ok||n.length===0)return;let r=ee.dirname(n),o=await this.currentLineName(e);return{path:e,sourceCwd:r,label:ee.basename(e),provider:this.kind,...o!==void 0?{line:o}:{},vcs:{repoRoot:r,...o!==void 0?{branch:o}:{}}}}async discardLine(e,t){let n=this.refRoot(e),o=(await this.divergence(n,"HEAD",t))?.behind??0,i=await H(["branch","-D",t],n,J);return i.ok?{ok:!0,dropped:o}:{ok:!1,dropped:o,reason:i.stderr.trim()||"could not discard the line"}}async pruneStale(e){await H(["worktree","prune"],this.refRoot(e),J)}async changedPaths(){throw new Ne(this.kind,"changedPaths")}async integrate(e){let{into:t,from:n}=e,r=await this.currentState(t);if(r===void 0)return{ok:!1,conflicts:[],declined:!0,reason:`cannot read the state of ${t}`};if(await this.contains(t,{state:n,within:r}))return{ok:!0,snapshot:r,alreadyUpToDate:!0};if(e.fastForwardOnly===!0&&!await this.contains(t,{state:r,within:n}))return{ok:!1,conflicts:[],declined:!0,reason:`${t} cannot simply advance to that state; it has moved on independently`};let o=e.fastForwardOnly===!0?["merge","--ff-only",n]:["merge","--no-edit","-m",e.message??"hydra: integrate",n],i=await H(o,t,pe);if(i.ok){let c=await this.currentState(t);return c===void 0?{ok:!1,conflicts:[],reason:"integrated but could not read the resulting state"}:{ok:!0,snapshot:c}}let a=await this.conflictedPaths(t),d=await this.integrationInProgress(t);return a.length===0&&!d?{ok:!1,conflicts:[],declined:!0,reason:i.stderr.trim()||"the integration was refused"}:(e.onConflict==="abort"&&await this.abortIntegration(t),{ok:!1,conflicts:a})}async listNested(e){let t=await H(["submodule","status","--recursive"],e,pe);if(!t.ok)return[];let n=[];for(let r of t.stdout.split(`
132
+ `)){let o=r.replace(/\r$/,"");if(o.trim().length===0||(o[0]??" ")==="-")continue;let a=o.slice(1),d=a.indexOf(" ");if(d<=0)continue;let c=a.slice(d+1).replace(/\s+\(.*\)\s*$/,"").trim();if(c.length===0||!Hm(e,c))continue;let u=ee.join(e,c),[l,p,f]=await Promise.all([this.currentState(u),H(["rev-parse",`HEAD:${c}`],e,J),H(["status","--porcelain","--untracked-files=all"],u,J)]);if(l===void 0)continue;let h=p.ok?p.stdout.trim():"";n.push({relPath:c,actual:l,...h.length>0?{recorded:h}:{},changedPaths:f.ok?No(f.stdout).map(k=>k.path):[]})}return n}async captureNested(e,t){let n=[];for(let r of t){if(!Mo(r))continue;if(r.changedPaths.length===0){n.push(r);continue}let o=ee.join(e,r.relPath),i=await this.captureWorkingState(o,"hydra: nested work carried into workspace").catch(()=>{});if(i===void 0){n.push(r);continue}let a=await this.captureDelta(o,r.actual,i);n.push(a===void 0?r:{...r,delta:a})}return n}async reproduceNested(e,t,n){let r=[],o=[];for(let i of n){let a=ee.join(e,i.relPath),d=ee.join(t,i.relPath),c=await this.alignNested(a,d,i.actual);if(c!==void 0){o.push({path:i.relPath,reason:c});continue}if(i.delta!==void 0){let u=await this.applyDelta(a,i.delta);if(!u.ok){o.push({path:i.relPath,reason:u.reason??"changes did not apply"});continue}}r.push(i.relPath)}return{applied:r,failed:o}}async integrateNested(e,t,n){let r=[],o=[],i=new Map(n.map(c=>[c.relPath,c])),a=await this.listNested(e),d=new Set([...a.map(c=>c.relPath),...i.keys()]);for(let c of[...d].sort()){let u=a.find(m=>m.relPath===c),l=i.get(c);if(u===void 0){o.push({path:c,reason:"not populated in the receiving tree"});continue}let p=u.recorded!==void 0&&u.recorded!==u.actual,f=l?.delta!==void 0;if(!p&&!f)continue;if(u.changedPaths.length>0){o.push({path:c,reason:`it has ${u.changedPaths.length} uncommitted change(s) of its own, and nothing can tell those apart from what was integrated`});continue}let h=ee.join(e,c),k=ee.join(t,c);if(p&&u.recorded!==void 0){let m=await this.alignNested(h,k,u.recorded);if(m!==void 0){o.push({path:c,reason:m});continue}}if(l?.delta!==void 0){let m=await this.applyDelta(h,l.delta);if(!m.ok){o.push({path:c,reason:m.reason??"the uncommitted changes there did not apply"});continue}}r.push(c)}return{applied:r,failed:o}}async alignNested(e,t,n){let r=await this.currentState(e);if(r===void 0)return"not populated here";if(r===n)return;if(!(await H(["cat-file","-e",`${n}^{commit}`],e,J)).ok&&!(await H(["fetch","--no-tags",t,n],e,Es)).ok)return`could not transfer ${n.slice(0,8)} from the other copy`;if(!(await H(["checkout","--detach",n],e,pe)).ok)return`could not move to ${n.slice(0,8)}`}};function Hm(s,e){if(ee.isAbsolute(e))return!1;let t=ee.resolve(s),n=ee.resolve(t,e);return n!==t&&n.startsWith(t+ee.sep)}var jm=Ms,Lm=new Map([[Ms,new Ps],[$o,new Ts]]);function re(s){return Lm.get(s??jm)}var _s="refs/hydra";function en(s){let e=`${_s}/workspaces/${s}`;return{autosave:`${e}/autosave`,start:`${e}/start`,baseline:`${e}/baseline`}}function Do(s){return`${_s}/landing/${s}`}function ec(s){return`${_s}/sync/${s}`}function tc(s,e){return`${_s}/retired/${s}-${e.slice(0,12)}`}function nc(s){let e=en(s);return[e.autosave,e.start,e.baseline]}async function Ho(s){let{source:e,ws:t,startSnapshotRef:n,baselineRef:r,retainRef:o,provider:i}=s;if(i===void 0)throw new Error("no provider available to inspect the source tree");let a=await i.status({...t,path:e}).catch(()=>{}),d="";for(let l of[r,n]){if(l===void 0)continue;let p=await i.resolveRetained(t,l).catch(()=>{});if(p!==void 0){d=p;break}}let c=a===void 0||a.changedPaths.length>0;if(d.length===0){if(c)throw new Error(`${e} has uncommitted changes but this workspace has no start anchor, so its copy of your work cannot be told apart from edits you made since. Refusing rather than reporting a conflict that is not yours. Commit or stash the source, then retry.`);d=await i.currentState(e).catch(()=>{})??""}if(!c)return{clean:!0,base:d};if(i.capabilities().supports.captureWorkingState!==!0)throw new Error(`${e} has uncommitted changes and this provider cannot snapshot them, so they cannot be preserved across the landing. Commit or stash them first.`);let u=await i.captureWorkingState(e,"hydra: source state before landing").catch(()=>{});if(u===void 0)throw new Error(`could not snapshot the uncommitted changes in ${e}, so refusing to touch them`);return await i.retainSnapshot({...t,path:e},o,u),{clean:!1,snapshot:u,base:d,retainedRef:o}}async function Rt(s){let{source:e,capture:t,provider:n}=s;if(t.clean||t.snapshot===void 0||n===void 0)return!0;let r=await n.captureDelta(e,t.base,t.snapshot).catch(()=>{});return r===void 0?!1:(await n.applyDelta(e,r,{tolerant:!0})).ok}async function $n(s){s.capture.retainedRef===void 0||s.provider===void 0||await s.provider.dropSnapshotRef({...s.ws,path:s.source},s.capture.retainedRef).catch(()=>{})}je();import{exec as Um}from"child_process";import*as Ke from"fs/promises";import*as Te from"path";var Bm=".hydra/worktree.json",Wm=".worktreeinclude",qm=120;async function $s(s){let e=await de(Te.join(s,Bm))??{},t=new Set(Array.isArray(e.carry)?e.carry:[]),n=await Ke.readFile(Te.join(s,Wm),"utf8").catch(()=>{});if(n!==void 0)for(let o of n.split(`
133
+ `)){let i=o.trim();i.length===0||i.startsWith("#")||i.startsWith("!")||i.includes("*")||i.includes("?")||t.add(i)}let r={};return t.size>0&&(r.carry=[...t]),typeof e.postCreate=="string"&&(r.postCreate=e.postCreate),typeof e.preRemove=="string"&&(r.preRemove=e.preRemove),typeof e.hookTimeoutSeconds=="number"&&(r.hookTimeoutSeconds=e.hookTimeoutSeconds),r}async function jo(s,e,t){let n=[],r=[],o=Te.resolve(s),i=Te.resolve(e);for(let a of t){let d=Te.resolve(o,a),c=Te.resolve(i,a);if(!d.startsWith(o+Te.sep)||!c.startsWith(i+Te.sep)){r.push(a);continue}if(await Ke.access(c).then(()=>!0).catch(()=>!1)){r.push(a);continue}let l=await Ke.stat(d).catch(()=>{});if(l===void 0){r.push(a);continue}try{await Ke.mkdir(Te.dirname(c),{recursive:!0}),await Ke.cp(d,c,{recursive:l.isDirectory(),dereference:!0}),n.push(a)}catch{r.push(a)}}return{copied:n,skipped:r}}async function Os(s,e){let t=JSON.stringify({path:e.workspacePath,sourceCwd:e.sourceCwd,label:e.label,...e.sessionId!==void 0?{sessionId:e.sessionId}:{}}),n=(e.timeoutSeconds??qm)*1e3;return new Promise(r=>{let o=Um(s,{cwd:e.workspacePath,timeout:n,maxBuffer:8388608,windowsHide:!0,env:{...process.env,HYDRA_WORKSPACE_PATH:e.workspacePath,HYDRA_SOURCE_CWD:e.sourceCwd,HYDRA_WORKSPACE_LABEL:e.label,...e.sessionId!==void 0?{HYDRA_SESSION_ID:e.sessionId}:{}}},(i,a,d)=>{if(i){let c=(d||i.message||"").trim().slice(0,500);r({ok:!1,reason:c.length>0?c:"hook failed"});return}r({ok:!0})});o.stdin?.on("error",()=>{}),o.stdin?.end(t)})}Y();je();import*as st from"fs/promises";import{z as He}from"zod";var zm=He.object({version:He.literal(1),agentId:He.string(),upstreamSessionId:He.string(),sessionId:He.string().optional(),deletedAt:He.string(),upstreamUpdatedAt:He.string().optional(),cwd:He.string().optional(),title:He.string().optional(),reason:He.enum(["user","expired"]).optional(),interactive:He.boolean().optional()}),Fs=class{async add(e){let t={version:1,...e};await me(E.tombstoneFile(e.agentId,e.upstreamSessionId),t,{mode:384})}async has(e,t){try{return await st.access(E.tombstoneFile(e,t)),!0}catch{return!1}}async read(e,t){let n=E.tombstoneFile(e,t),r=await de(n);if(r===void 0)return await this.has(e,t)?{version:1,agentId:e,upstreamSessionId:t,deletedAt:new Date(0).toISOString()}:void 0;try{return zm.parse(r)}catch{return{version:1,agentId:e,upstreamSessionId:t,deletedAt:new Date(0).toISOString()}}}async remove(e,t){try{await st.unlink(E.tombstoneFile(e,t))}catch(n){if(n.code!=="ENOENT")throw n}try{await st.rmdir(E.tombstoneAgentDir(e))}catch(n){let r=n;if(r.code!=="ENOENT"&&r.code!=="ENOTEMPTY")throw n}}async list(e){if(e!==void 0)return this.listForAgent(e);let t;try{t=await st.readdir(E.tombstonesDir())}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t){let o;try{o=decodeURIComponent(r)}catch{continue}n.push(...await this.listForAgent(o))}return n}async listForAgent(e){let t;try{t=await st.readdir(E.tombstoneAgentDir(e))}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t){let o;try{o=decodeURIComponent(r)}catch{continue}let i=await this.read(e,o);i&&n.push(i)}return n}};function sc(s,e){return s.reason==="user"||e===void 0?!1:s.upstreamUpdatedAt===void 0?!0:e>s.upstreamUpdatedAt}import*as yc from"fs/promises";import{customAlphabet as th}from"nanoid";import{fileURLToPath as Jm}from"url";import*as On from"path";import*as Ns from"fs";function Vm(){try{let s=On.dirname(Jm(import.meta.url));for(let e=0;e<8;e+=1){let t=On.join(s,"package.json");if(Ns.existsSync(t)){let r=JSON.parse(Ns.readFileSync(t,"utf8"));if(typeof r.version=="string"&&r.version.length>0&&(typeof r.name!="string"||r.name.includes("hydra-acp")))return r.version}let n=On.dirname(s);if(n===s)break;s=n}}catch{}return"0.0.0"}var ue=Vm(),Ds="hydra-acp-cat";var Gm=12e4;async function oc(s,e,t){let n=s.timeoutMs??Gm,r,o,i=!1;try{let a=(async()=>{r=ut.spawn({agentId:s.agentId,cwd:s.cwd,plan:s.plan,logger:s.logger});let d=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:{},clientInfo:{name:"hydra-synopsis",version:ue}}),c=await r.connection.request("session/new",{cwd:s.cwd,mcpServers:[]}),u=c.sessionId;if(typeof u!="string"){s.logger?.warn(`synopsis: agent ${s.agentId} returned non-string sessionId from session/new`),s.onFailure?.(`agent ${s.agentId} did not return a sessionId from session/new`);return}if(s.onWorkerSpawned?.(u,r.pid),s.modelId){let h=Qm(c);if(h.size===0||h.has(s.modelId)){let k=r.connection;try{await lt({request:(m,g)=>k.request(m,g),sessionId:u,modelId:s.modelId,verb:Bt(c),logger:s.logger})}catch(m){s.logger?.warn(`synopsis: agent ${s.agentId} rejected model change to ${JSON.stringify(s.modelId)}: ${m.message}; continuing on default`)}}else s.logger?.warn(`synopsis: model ${JSON.stringify(s.modelId)} not advertised by agent ${s.agentId} (have [${[...h].join(", ")}]); continuing on default`)}let l=[];r.connection.onNotification("session/update",h=>{let k=Km(h);k.length>0&&l.push(k)}),await r.connection.request("session/prompt",{sessionId:u,prompt:[{type:"text",text:e}]});let p=l.join(""),f=t(p);if(!f){let h=JSON.stringify(p.slice(0,200));s.logger?.warn(`synopsis: agent ${s.agentId} reply did not parse (replyLen=${p.length} preview=${h})`);let k=p.slice(0,120).replace(/\s+/g," ").trim();s.onFailure?.(`agent ${s.agentId} returned unparseable JSON (${p.length} chars): ${k}${p.length>120?"\u2026":""}`)}return f})();return await new Promise((d,c)=>{o=setTimeout(()=>{i=!0,s.logger?.warn(`synopsis: agent ${s.agentId} timed out after ${n}ms`),s.onFailure?.(`agent ${s.agentId} timed out after ${n}ms`),d(void 0)},n),o.unref?.(),a.then(u=>{o&&clearTimeout(o),i||d(u)},u=>{o&&clearTimeout(o),i||c(u)})})}catch(a){let d=a.message;s.logger?.warn(`synopsis: agent ${s.agentId} failed: ${d}`),s.onFailure?.(`agent ${s.agentId} failed: ${d}`);return}finally{o&&clearTimeout(o),r&&await r.kill().catch(()=>{})}}async function Hs(s){let e=Kt(s.history,{maxChars:s.maxTranscriptChars}),t=s.sessionId!==void 0?`[hydra-acp title-regen worker for session ${s.sessionId}]`:"[hydra-acp title-regen worker]",n=e.length>0?`${t}
134
134
 
135
135
  ${e}
136
136
 
137
- ${So}`:`${t}
137
+ ${Ao}`:`${t}
138
138
 
139
- ${So}`;return sc(s,n,Ud)}async function rc(s){let e=Gt(s.history,{maxChars:s.maxTranscriptChars}),t=s.sessionId!==void 0?`[hydra-acp compaction worker for session ${s.sessionId}]`:"[hydra-acp compaction worker]",n=e.length>0?`${t}
139
+ ${Ao}`;return oc(s,n,Wd)}async function ic(s){let e=Kt(s.history,{maxChars:s.maxTranscriptChars}),t=s.sessionId!==void 0?`[hydra-acp compaction worker for session ${s.sessionId}]`:"[hydra-acp compaction worker]",n=e.length>0?`${t}
140
140
 
141
141
  ${e}
142
142
 
143
- ${Io}`:`${t}
143
+ ${Co}`:`${t}
144
144
 
145
- ${Io}`;return sc(s,n,Bd)}function Vm(s){if(!s||typeof s!="object")return"";let e=s.update;if(!e||typeof e!="object")return"";let t=e;if(t.sessionUpdate!=="agent_message_chunk")return"";let n=t.content;return n&&typeof n.text=="string"?n.text:""}function Gm(s){let e=new Set;nc(e,s.availableModels);let t=s.models;return t&&typeof t=="object"&&!Array.isArray(t)&&nc(e,t.availableModels),e}function nc(s,e){if(Array.isArray(e)){for(let t of e)if(t&&typeof t=="object"){let n=t.modelId??t.value??t.id;typeof n=="string"&&n.length>0&&s.add(n)}}}var Km="guardian_assessment:",Qm="Guardian Review";function oc(s,e){return s!==void 0&&s.startsWith(Km)||e===Qm}function Ym(s){let e=new Map;for(let t of lc(s).values())e.set(t.toolName,(e.get(t.toolName)??0)+1);return[...e.entries()].map(([t,n])=>({name:t,count:n})).sort((t,n)=>n.count-t.count||t.name.localeCompare(n.name))}function dc(s){return Ym(s).map(e=>e.name)}function Xm(s){let e=new Map;for(let t of lc(s).values())for(let n of t.paths){let r=e.get(n);r===void 0&&(r=new Map,e.set(n,r)),r.set(t.toolName,(r.get(t.toolName)??0)+1)}return[...e.entries()].map(([t,n])=>{let r=[...n.entries()].map(([i,a])=>({name:i,count:a})).sort((i,a)=>a.count-i.count||i.name.localeCompare(a.name)),o=r.reduce((i,a)=>i+a.count,0);return{path:t,count:o,byTool:r}}).sort((t,n)=>n.count-t.count||t.path.localeCompare(n.path))}function cc(s){return Xm(s).map(e=>e.path)}function uc(s){let e=0;for(let t of s)t.params?.update?.sessionUpdate==="prompt_received"&&(e+=1);return e}function lc(s){let e=new Map,t=0;for(let n of s){let o=n.params?.update;if(!o)continue;let i=o.sessionUpdate;if(i!=="tool_call"&&i!=="tool_call_update")continue;if(i==="tool_call"){let d=typeof o.toolCallId=="string"&&o.toolCallId.length>0?o.toolCallId:void 0,c=typeof o.title=="string"?o.title:void 0;if(oc(d,c))continue;let u=d??`__synth_${t++}`,l=e.get(u);l===void 0?(l={toolName:ic(o),paths:new Set},e.set(u,l)):l.toolName=ic(o);for(let p of ac(o.rawInput,o.locations))l.paths.add(p);continue}if(typeof o.toolCallId!="string"||o.toolCallId.length===0)continue;let a=e.get(o.toolCallId);if(a!==void 0)for(let d of ac(o.rawInput,o.locations))a.paths.add(d)}return e}function ic(s){return typeof s.name=="string"&&s.name.length>0?s.name:typeof s.title=="string"&&s.title.length>0?s.title:"(unnamed)"}function ac(s,e){let t=new Set;if(s&&typeof s=="object"&&!Array.isArray(s)){let n=s;typeof n.file_path=="string"?t.add(n.file_path):typeof n.path=="string"&&t.add(n.path);let r=n.edits;if(Array.isArray(r)){for(let o of r)if(o&&typeof o=="object"){let i=o.file_path;typeof i=="string"&&t.add(i)}}}for(let n of La(e))t.add(n);return t}Y();var eh=Zm("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",12),th=2,Ds=class{constructor(e){this.opts=e;this.maxConcurrent=e.maxConcurrent??th}opts;queued={};inflight=new Map;stopped=!1;maxConcurrent;schedule(e){this.stopped||this.inflight.has(e)||e in this.queued||(this.queued[e]={kind:"title"},this.drain())}scheduleCompaction(e,t){if(this.stopped)return;let n=t?.targetAgentId;if(this.inflight.has(e))return;let r=this.queued[e];if(r&&r.kind==="title"){this.queued[e]={kind:"compaction",...n?{targetAgentId:n}:{}};return}this.queued[e]={kind:"compaction",...n?{targetAgentId:n}:{}},this.drain()}size(){return{queued:Object.keys(this.queued).length,inflight:this.inflight.size}}async flush(e){let t=Date.now()+e;for(;Object.keys(this.queued).length>0||this.inflight.size>0;){let n=t-Date.now();if(n<=0)return;let r=[...this.inflight.values()];if(r.length===0){await new Promise(o=>{setTimeout(o,25).unref?.()});continue}await Promise.race([Promise.race(r),new Promise(o=>{setTimeout(o,n).unref?.()})])}}async shutdown(){this.stopped=!0,this.queued={},await Promise.allSettled([...this.inflight.values()])}drain(){if(!this.stopped)for(;this.inflight.size<this.maxConcurrent&&Object.keys(this.queued).length>0;){let t=Object.keys(this.queued)[0];if(!t)return;let n=this.queued[t];delete this.queued[t];let r=this.runOne(t,n).finally(()=>{this.inflight.delete(t),this.drain()});this.inflight.set(t,r)}}async runOne(e,t){let n=t.kind,r=t.targetAgentId;try{let o=await this.opts.store.read(e);if(!o){this.opts.logger?.info(`synopsis: session ${e} record missing; skipping`);return}let i=await this.opts.histories.load(e,{maxEntries:1/0}),a=o.summarizedThroughEntry;if(a!==void 0&&i.length===a){this.opts.logger?.info(`synopsis: skip ${e} (history unchanged at ${i.length})`);return}a!==void 0&&i.length<a&&this.opts.logger?.warn(`synopsis: watermark ahead of history (last=${a} history=${i.length}) for ${e} \u2014 re-baselining`);let d=n==="compaction"?r??this.opts.compactionAgent??o.agentId:this.opts.synopsisAgent??o.agentId,c=await this.opts.registry.getAgent(d);if(!c){this.opts.logger?.warn(`synopsis: agent ${d} not in registry for session ${e}; skipping`);return}let u=await _e(c,[],{npmRegistry:this.opts.npmRegistry}),l=this.opts.compactionAgent===void 0&&r===void 0,p=n==="compaction"?this.opts.compactionModel??(l?o.currentModel:void 0):this.opts.synopsisModel,f=T.sessionDir(e);if(await mc.mkdir(f,{recursive:!0}).catch(()=>{}),this.opts.logger?.info(`synopsis: start sessionId=${e} agentId=${d} historyLen=${i.length} model=${JSON.stringify(p??"(default)")} cwd=${f}`),n==="compaction"){let h=this.opts.compactionMaxIterations??3,k=0,m=a??0,g,y=0,w,v=Date.now(),S=eh(),b={targetAgentId:r},I=R=>this.opts.onCompactionStateChange?.(e,{runId:S,...R},b)??Promise.resolve(),C=R=>{this.opts.broadcastHydraCompaction?.(e,R,b)};await I({status:"requested",requestedAt:v}),C({sessionUpdate:"_hydra_compaction",phase:"started",requestedAt:v});try{do{k++,this.opts.logger?.info(`synopsis: compaction iteration ${k} sessionId=${e} historyLen=${i.length} watermark=${m}`);let R=await this.opts.histories.load(e,{maxEntries:1/0});if(R.length===m)break;let E=await rc({agentId:d,cwd:f,plan:u,history:R,modelId:p,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs,onWorkerSpawned:(N,B)=>{I({status:"running",requestedAt:v,iter:k,worker:{upstreamSessionId:N,pid:B??0}})},onFailure:N=>{w=N}});if(E){let N=fc(E.synopsis,R);N&&pc(N)&&(await this.opts.persistSynopsis(e,N,R.length),g=N,y=R.length,w=void 0,await I({status:"running",requestedAt:v,iter:k}),C({sessionUpdate:"_hydra_compaction",phase:"iteration",iter:k,historyLen:R.length}),await this.opts.onSynthesisArtifact?.(e,N,y,r,S),this.opts.logger?.info(`synopsis: persisted compaction sessionId=${e} iteration=${k} fields=${gc(N)}`))}else this.opts.logger?.warn(`synopsis: sessionId=${e} compaction iteration ${k} returned no result`);if(m=R.length,(await this.opts.histories.load(e,{maxEntries:1/0})).length===m)break}while(k<h);if(g)this.opts.logger?.info(`synopsis: compaction converged sessionId=${e} runId=${S} watermark=${y} iterations=${k}`+(k>=h?` (hit maxIterations=${h})`:"")),C({sessionUpdate:"_hydra_compaction",phase:"converged",iter:k,summarizedThroughEntry:y});else{k>0&&this.opts.logger?.warn(`synopsis: compaction hit maxIterations=${h} without producing artifact sessionId=${e}: ${w??"no reason captured"}`);let R=w??(k===0?"no new history to compact since last summary":`compaction did not produce an artifact after ${k} iteration(s)`);await I({status:"failed",requestedAt:v,iter:k,lastError:R}),C({sessionUpdate:"_hydra_compaction",phase:"failed",error:R}),r&&await this.opts.onSynthesisUnavailable?.(e,r,R)}}catch(R){let E=R instanceof Error?R.message:String(R);if(this.opts.logger?.warn(`synopsis: compaction threw for sessionId=${e}: ${E}`),await I({status:"failed",requestedAt:v,iter:k,lastError:E}),this.opts.broadcastHydraCompaction?.(e,{sessionUpdate:"_hydra_compaction",phase:"failed",error:E},{targetAgentId:r}),r)try{await this.opts.onSynthesisUnavailable?.(e,r,E)}catch{}}}else{let h=await Ns({agentId:d,cwd:f,plan:u,history:i,modelId:p,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs});if(!h){this.opts.logger?.warn(`synopsis: sessionId=${e} no parseable result; not persisting`);return}let k=fc(h.synopsis,i);k&&pc(k)?(await this.opts.persistSynopsis(e,k,i.length),h.title&&await this.opts.persistTitle(e,h.title),this.opts.logger?.info(`synopsis: persisted sessionId=${e} title=${JSON.stringify(!!h.title)} fields=${gc(k)}`)):h.title&&(await this.opts.persistTitle(e,h.title),this.opts.logger?.info(`synopsis: persisted title only sessionId=${e}`))}}catch(o){this.opts.logger?.warn(`synopsis: sessionId=${e} failed: ${o.message}`)}}};function fc(s,e){let t=cc(e),n=dc(e);return s?{...s,files_touched:t.length>0?t:s.files_touched,tools_used:n.length>0?n:s.tools_used}:t.length===0&&n.length===0?void 0:{files_touched:t.length>0?t:void 0,tools_used:n.length>0?n:void 0}}function pc(s){return!!(s.goal&&s.goal.trim().length>0||s.outcome&&s.outcome.trim().length>0||s.files_touched&&s.files_touched.length>0||s.tools_used&&s.tools_used.length>0||s.rejected_approaches&&s.rejected_approaches.length>0||s.open_threads&&s.open_threads.length>0)}function gc(s){let e=[];return s.goal&&e.push("goal"),s.outcome&&e.push("outcome"),s.files_touched&&s.files_touched.length>0&&e.push(`files=${s.files_touched.length}`),s.tools_used&&s.tools_used.length>0&&e.push(`tools=${s.tools_used.length}`),s.rejected_approaches&&s.rejected_approaches.length>0&&e.push(`rejected=${s.rejected_approaches.length}`),s.open_threads&&s.open_threads.length>0&&e.push(`open=${s.open_threads.length}`),`[${e.join(",")}]`}Y();import*as G from"fs/promises";import{createReadStream as dh}from"fs";import{createGunzip as ch,gzip as uh,gunzip as lh}from"zlib";import{createInterface as fh}from"readline";import{promisify as bc}from"util";function hc(s){return s==="summary"?"summary":"inline"}var Ho=256,nh=["totalMatches","totalFiles","referenceCount","truncated","exitCode"],sh=["content","stdout","stderr"];function yc(s,e){return e!=="summary"?s:s.map(rh)}function rh(s){if(s.method!=="session/update")return s;let e=s.params;if(!e||typeof e!="object"||Array.isArray(e))return s;let t=e,n=t.update;if(!n||typeof n!="object"||Array.isArray(n))return s;let r=n;if(r.sessionUpdate!=="tool_call"&&r.sessionUpdate!=="tool_call_update")return s;let o={...r};Array.isArray(r.content)&&(o.content=r.content.map(wc));let i=r.rawOutput;if(i&&typeof i=="object"&&!Array.isArray(i)){let a=i,d={};a.error!==void 0&&(d.error=Hs(a.error)),a.metadata!==void 0&&(d.metadata=a.metadata);for(let c of nh)a[c]!==void 0&&(d[c]=a[c]);for(let c of sh)typeof a[c]=="string"&&(d[c]=Hs(a[c]));o.rawOutput=d}return{...s,params:{...t,update:o}}}function oh(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&s.type==="diff"}function wc(s){if(oh(s)){let n=s,r={type:"diff",oldText:"",newText:""};return typeof n.path=="string"&&(r.path=n.path),r}if(!s||typeof s!="object"||Array.isArray(s))return s;let e=s,t={...e};return typeof e.text=="string"&&(t.text=Hs(e.text)),typeof e.content=="string"?t.content=Hs(e.content):e.content&&typeof e.content=="object"&&(t.content=wc(e.content)),t}function Hs(s){if(typeof s=="string"&&s.length>Ho){let e=s.length-Ho;return`${s.slice(0,Ho)}\u2026[+${e} chars omitted from summary export]`}return s}var ih=2048;function kc(s){let e=new Set,t=n=>{if(vc(n)){e.add(n.__hydraBlob);return}if(Array.isArray(n)){for(let r of n)t(r);return}if(n&&typeof n=="object")for(let r of Object.values(n))t(r)};for(let n of s)t(n.params);return e}function vc(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&typeof s.__hydraBlob=="string"}function ah(s){if(s.method!=="session/update")return!1;let e=s.params;if(!e||typeof e!="object"||Array.isArray(e))return!1;let t=e.update;if(!t||typeof t!="object"||Array.isArray(t))return!1;let n=t.sessionUpdate;return n==="tool_call"||n==="tool_call_update"}async function Uo(s,e){if(!ah(s))return s;let t=s.params,n=t.update,r=await jo(n,e);return{...s,params:{...t,update:r}}}async function jo(s,e){if(typeof s=="string"){if(s.length<=ih)return s;let t=await e(s);return t===null?s:{__hydraBlob:t,bytes:s.length}}if(Array.isArray(s)){let t=[];for(let n of s)t.push(await jo(n,e));return t}if(s&&typeof s=="object"){let t={};for(let[n,r]of Object.entries(s))t[n]=await jo(r,e);return t}return s}async function Bo(s,e){let t=s.params;if(!t||typeof t!="object"||Array.isArray(t))return s;let n=await Lo(t,e);return n===t?s:{...s,params:n}}async function Lo(s,e){if(vc(s))return await e(s.__hydraBlob)??"";if(Array.isArray(s)){let t=!1,n=[];for(let r of s){let o=await Lo(r,e);o!==r&&(t=!0),n.push(o)}return t?n:s}if(s&&typeof s=="object"){let t=!1,n={};for(let[r,o]of Object.entries(s)){let i=await Lo(o,e);i!==o&&(t=!0),n[r]=i}return t?n:s}return s}function $n(s,e){let t=-1;for(let n=s.length-1;n>=0;n--)if(s[n]?.messageId===e){t=n;break}if(t<0)return-1;for(let n=t;n<s.length;n++){let r=s[n]?.sessionUpdate;if(r==="turn_complete"||r==="_hydra_turn_ended")return n;if(n>t&&(r==="prompt_received"||r==="_hydra_turn_started"))return n-1}return s.length-1}function Wo(s){return s.map(e=>e.method==="session/update"?e.params?.update:void 0)}var ph=bc(uh),gh=bc(lh),mh=/^history\.jsonl\.(\d+)(\.gz)?$/,Oe=/^[A-Za-z0-9_-]+$/;function hh(s){try{let e=JSON.parse(s);return e.method==="session/update"?e.params?.update:void 0}catch{return}}var yh=1e3,wh=1e7,kh=10,js=class{writeQueues=new Map;maxEntries;archiveMaxBytes;archiveTiers;nextArchiveIndex=new Map;archiveLineCounts=new Map;constructor(e={}){this.maxEntries=e.maxEntries??yh,this.archiveMaxBytes=e.archiveMaxBytes??wh,this.archiveTiers=e.archiveTiers??kh}async append(e,t){if(Oe.test(e))return this.enqueue(e,async()=>{await G.mkdir(T.sessionDir(e),{recursive:!0});let n=await Uo(t,o=>Nr(e,o)),r=JSON.stringify(n)+`
146
- `;await G.appendFile(T.historyFile(e),r,{encoding:"utf8",mode:384})})}async rewrite(e,t){if(Oe.test(e))return this.enqueue(e,async()=>{await G.mkdir(T.sessionDir(e),{recursive:!0});let n=[];for(let o of t)n.push(await Uo(o,i=>Nr(e,i)));let r=n.length===0?"":n.map(o=>JSON.stringify(o)).join(`
145
+ ${Co}`;return oc(s,n,qd)}function Km(s){if(!s||typeof s!="object")return"";let e=s.update;if(!e||typeof e!="object")return"";let t=e;if(t.sessionUpdate!=="agent_message_chunk")return"";let n=t.content;return n&&typeof n.text=="string"?n.text:""}function Qm(s){let e=new Set;rc(e,s.availableModels);let t=s.models;return t&&typeof t=="object"&&!Array.isArray(t)&&rc(e,t.availableModels),e}function rc(s,e){if(Array.isArray(e)){for(let t of e)if(t&&typeof t=="object"){let n=t.modelId??t.value??t.id;typeof n=="string"&&n.length>0&&s.add(n)}}}var Ym="guardian_assessment:",Xm="Guardian Review";function ac(s,e){return s!==void 0&&s.startsWith(Ym)||e===Xm}function Zm(s){let e=new Map;for(let t of pc(s).values())e.set(t.toolName,(e.get(t.toolName)??0)+1);return[...e.entries()].map(([t,n])=>({name:t,count:n})).sort((t,n)=>n.count-t.count||t.name.localeCompare(n.name))}function uc(s){return Zm(s).map(e=>e.name)}function eh(s){let e=new Map;for(let t of pc(s).values())for(let n of t.paths){let r=e.get(n);r===void 0&&(r=new Map,e.set(n,r)),r.set(t.toolName,(r.get(t.toolName)??0)+1)}return[...e.entries()].map(([t,n])=>{let r=[...n.entries()].map(([i,a])=>({name:i,count:a})).sort((i,a)=>a.count-i.count||i.name.localeCompare(a.name)),o=r.reduce((i,a)=>i+a.count,0);return{path:t,count:o,byTool:r}}).sort((t,n)=>n.count-t.count||t.path.localeCompare(n.path))}function lc(s){return eh(s).map(e=>e.path)}function fc(s){let e=0;for(let t of s)t.params?.update?.sessionUpdate==="prompt_received"&&(e+=1);return e}function pc(s){let e=new Map,t=0;for(let n of s){let o=n.params?.update;if(!o)continue;let i=o.sessionUpdate;if(i!=="tool_call"&&i!=="tool_call_update")continue;if(i==="tool_call"){let d=typeof o.toolCallId=="string"&&o.toolCallId.length>0?o.toolCallId:void 0,c=typeof o.title=="string"?o.title:void 0;if(ac(d,c))continue;let u=d??`__synth_${t++}`,l=e.get(u);l===void 0?(l={toolName:dc(o),paths:new Set},e.set(u,l)):l.toolName=dc(o);for(let p of cc(o.rawInput,o.locations))l.paths.add(p);continue}if(typeof o.toolCallId!="string"||o.toolCallId.length===0)continue;let a=e.get(o.toolCallId);if(a!==void 0)for(let d of cc(o.rawInput,o.locations))a.paths.add(d)}return e}function dc(s){return typeof s.name=="string"&&s.name.length>0?s.name:typeof s.title=="string"&&s.title.length>0?s.title:"(unnamed)"}function cc(s,e){let t=new Set;if(s&&typeof s=="object"&&!Array.isArray(s)){let n=s;typeof n.file_path=="string"?t.add(n.file_path):typeof n.path=="string"&&t.add(n.path);let r=n.edits;if(Array.isArray(r)){for(let o of r)if(o&&typeof o=="object"){let i=o.file_path;typeof i=="string"&&t.add(i)}}}for(let n of Ba(e))t.add(n);return t}Y();var nh=th("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",12),sh=2,js=class{constructor(e){this.opts=e;this.maxConcurrent=e.maxConcurrent??sh}opts;queued={};inflight=new Map;stopped=!1;maxConcurrent;schedule(e){this.stopped||this.inflight.has(e)||e in this.queued||(this.queued[e]={kind:"title"},this.drain())}scheduleCompaction(e,t){if(this.stopped)return;let n=t?.targetAgentId;if(this.inflight.has(e))return;let r=this.queued[e];if(r&&r.kind==="title"){this.queued[e]={kind:"compaction",...n?{targetAgentId:n}:{}};return}this.queued[e]={kind:"compaction",...n?{targetAgentId:n}:{}},this.drain()}size(){return{queued:Object.keys(this.queued).length,inflight:this.inflight.size}}async flush(e){let t=Date.now()+e;for(;Object.keys(this.queued).length>0||this.inflight.size>0;){let n=t-Date.now();if(n<=0)return;let r=[...this.inflight.values()];if(r.length===0){await new Promise(o=>{setTimeout(o,25).unref?.()});continue}await Promise.race([Promise.race(r),new Promise(o=>{setTimeout(o,n).unref?.()})])}}async shutdown(){this.stopped=!0,this.queued={},await Promise.allSettled([...this.inflight.values()])}drain(){if(!this.stopped)for(;this.inflight.size<this.maxConcurrent&&Object.keys(this.queued).length>0;){let t=Object.keys(this.queued)[0];if(!t)return;let n=this.queued[t];delete this.queued[t];let r=this.runOne(t,n).finally(()=>{this.inflight.delete(t),this.drain()});this.inflight.set(t,r)}}async runOne(e,t){let n=t.kind,r=t.targetAgentId;try{let o=await this.opts.store.read(e);if(!o){this.opts.logger?.info(`synopsis: session ${e} record missing; skipping`);return}let i=await this.opts.histories.load(e,{maxEntries:1/0}),a=o.summarizedThroughEntry;if(a!==void 0&&i.length===a){this.opts.logger?.info(`synopsis: skip ${e} (history unchanged at ${i.length})`);return}a!==void 0&&i.length<a&&this.opts.logger?.warn(`synopsis: watermark ahead of history (last=${a} history=${i.length}) for ${e} \u2014 re-baselining`);let d=n==="compaction"?r??this.opts.compactionAgent??o.agentId:this.opts.synopsisAgent??o.agentId,c=await this.opts.registry.getAgent(d);if(!c){this.opts.logger?.warn(`synopsis: agent ${d} not in registry for session ${e}; skipping`);return}let u=await _e(c,[],{npmRegistry:this.opts.npmRegistry}),l=this.opts.compactionAgent===void 0&&r===void 0,p=n==="compaction"?this.opts.compactionModel??(l?o.currentModel:void 0):this.opts.synopsisModel,f=E.sessionDir(e);if(await yc.mkdir(f,{recursive:!0}).catch(()=>{}),this.opts.logger?.info(`synopsis: start sessionId=${e} agentId=${d} historyLen=${i.length} model=${JSON.stringify(p??"(default)")} cwd=${f}`),n==="compaction"){let h=this.opts.compactionMaxIterations??3,k=0,m=a??0,g,y=0,w,v=Date.now(),S=nh(),b={targetAgentId:r},I=x=>this.opts.onCompactionStateChange?.(e,{runId:S,...x},b)??Promise.resolve(),A=x=>{this.opts.broadcastHydraCompaction?.(e,x,b)};await I({status:"requested",requestedAt:v}),A({sessionUpdate:"_hydra_compaction",phase:"started",requestedAt:v});try{do{k++,this.opts.logger?.info(`synopsis: compaction iteration ${k} sessionId=${e} historyLen=${i.length} watermark=${m}`);let x=await this.opts.histories.load(e,{maxEntries:1/0});if(x.length===m)break;let T=await ic({agentId:d,cwd:f,plan:u,history:x,modelId:p,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs,onWorkerSpawned:(N,B)=>{I({status:"running",requestedAt:v,iter:k,worker:{upstreamSessionId:N,pid:B??0}})},onFailure:N=>{w=N}});if(T){let N=gc(T.synopsis,x);N&&mc(N)&&(await this.opts.persistSynopsis(e,N,x.length),g=N,y=x.length,w=void 0,await I({status:"running",requestedAt:v,iter:k}),A({sessionUpdate:"_hydra_compaction",phase:"iteration",iter:k,historyLen:x.length}),await this.opts.onSynthesisArtifact?.(e,N,y,r,S),this.opts.logger?.info(`synopsis: persisted compaction sessionId=${e} iteration=${k} fields=${hc(N)}`))}else this.opts.logger?.warn(`synopsis: sessionId=${e} compaction iteration ${k} returned no result`);if(m=x.length,(await this.opts.histories.load(e,{maxEntries:1/0})).length===m)break}while(k<h);if(g)this.opts.logger?.info(`synopsis: compaction converged sessionId=${e} runId=${S} watermark=${y} iterations=${k}`+(k>=h?` (hit maxIterations=${h})`:"")),A({sessionUpdate:"_hydra_compaction",phase:"converged",iter:k,summarizedThroughEntry:y});else{k>0&&this.opts.logger?.warn(`synopsis: compaction hit maxIterations=${h} without producing artifact sessionId=${e}: ${w??"no reason captured"}`);let x=w??(k===0?"no new history to compact since last summary":`compaction did not produce an artifact after ${k} iteration(s)`);await I({status:"failed",requestedAt:v,iter:k,lastError:x}),A({sessionUpdate:"_hydra_compaction",phase:"failed",error:x}),r&&await this.opts.onSynthesisUnavailable?.(e,r,x)}}catch(x){let T=x instanceof Error?x.message:String(x);if(this.opts.logger?.warn(`synopsis: compaction threw for sessionId=${e}: ${T}`),await I({status:"failed",requestedAt:v,iter:k,lastError:T}),this.opts.broadcastHydraCompaction?.(e,{sessionUpdate:"_hydra_compaction",phase:"failed",error:T},{targetAgentId:r}),r)try{await this.opts.onSynthesisUnavailable?.(e,r,T)}catch{}}}else{let h=await Hs({agentId:d,cwd:f,plan:u,history:i,modelId:p,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs});if(!h){this.opts.logger?.warn(`synopsis: sessionId=${e} no parseable result; not persisting`);return}let k=gc(h.synopsis,i);k&&mc(k)?(await this.opts.persistSynopsis(e,k,i.length),h.title&&await this.opts.persistTitle(e,h.title),this.opts.logger?.info(`synopsis: persisted sessionId=${e} title=${JSON.stringify(!!h.title)} fields=${hc(k)}`)):h.title&&(await this.opts.persistTitle(e,h.title),this.opts.logger?.info(`synopsis: persisted title only sessionId=${e}`))}}catch(o){this.opts.logger?.warn(`synopsis: sessionId=${e} failed: ${o.message}`)}}};function gc(s,e){let t=lc(e),n=uc(e);return s?{...s,files_touched:t.length>0?t:s.files_touched,tools_used:n.length>0?n:s.tools_used}:t.length===0&&n.length===0?void 0:{files_touched:t.length>0?t:void 0,tools_used:n.length>0?n:void 0}}function mc(s){return!!(s.goal&&s.goal.trim().length>0||s.outcome&&s.outcome.trim().length>0||s.files_touched&&s.files_touched.length>0||s.tools_used&&s.tools_used.length>0||s.rejected_approaches&&s.rejected_approaches.length>0||s.open_threads&&s.open_threads.length>0)}function hc(s){let e=[];return s.goal&&e.push("goal"),s.outcome&&e.push("outcome"),s.files_touched&&s.files_touched.length>0&&e.push(`files=${s.files_touched.length}`),s.tools_used&&s.tools_used.length>0&&e.push(`tools=${s.tools_used.length}`),s.rejected_approaches&&s.rejected_approaches.length>0&&e.push(`rejected=${s.rejected_approaches.length}`),s.open_threads&&s.open_threads.length>0&&e.push(`open=${s.open_threads.length}`),`[${e.join(",")}]`}Y();import*as G from"fs/promises";import{createReadStream as uh}from"fs";import{createGunzip as lh,gzip as fh,gunzip as ph}from"zlib";import{createInterface as gh}from"readline";import{promisify as Ic}from"util";function wc(s){return s==="summary"?"summary":"inline"}var Lo=256,rh=["totalMatches","totalFiles","referenceCount","truncated","exitCode"],oh=["content","stdout","stderr"];function kc(s,e){return e!=="summary"?s:s.map(ih)}function ih(s){if(s.method!=="session/update")return s;let e=s.params;if(!e||typeof e!="object"||Array.isArray(e))return s;let t=e,n=t.update;if(!n||typeof n!="object"||Array.isArray(n))return s;let r=n;if(r.sessionUpdate!=="tool_call"&&r.sessionUpdate!=="tool_call_update")return s;let o={...r};Array.isArray(r.content)&&(o.content=r.content.map(vc));let i=r.rawOutput;if(i&&typeof i=="object"&&!Array.isArray(i)){let a=i,d={};a.error!==void 0&&(d.error=Ls(a.error)),a.metadata!==void 0&&(d.metadata=a.metadata);for(let c of rh)a[c]!==void 0&&(d[c]=a[c]);for(let c of oh)typeof a[c]=="string"&&(d[c]=Ls(a[c]));o.rawOutput=d}return{...s,params:{...t,update:o}}}function ah(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&s.type==="diff"}function vc(s){if(ah(s)){let n=s,r={type:"diff",oldText:"",newText:""};return typeof n.path=="string"&&(r.path=n.path),r}if(!s||typeof s!="object"||Array.isArray(s))return s;let e=s,t={...e};return typeof e.text=="string"&&(t.text=Ls(e.text)),typeof e.content=="string"?t.content=Ls(e.content):e.content&&typeof e.content=="object"&&(t.content=vc(e.content)),t}function Ls(s){if(typeof s=="string"&&s.length>Lo){let e=s.length-Lo;return`${s.slice(0,Lo)}\u2026[+${e} chars omitted from summary export]`}return s}var dh=2048;function bc(s){let e=new Set,t=n=>{if(Sc(n)){e.add(n.__hydraBlob);return}if(Array.isArray(n)){for(let r of n)t(r);return}if(n&&typeof n=="object")for(let r of Object.values(n))t(r)};for(let n of s)t(n.params);return e}function Sc(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&typeof s.__hydraBlob=="string"}function ch(s){if(s.method!=="session/update")return!1;let e=s.params;if(!e||typeof e!="object"||Array.isArray(e))return!1;let t=e.update;if(!t||typeof t!="object"||Array.isArray(t))return!1;let n=t.sessionUpdate;return n==="tool_call"||n==="tool_call_update"}async function Wo(s,e){if(!ch(s))return s;let t=s.params,n=t.update,r=await Uo(n,e);return{...s,params:{...t,update:r}}}async function Uo(s,e){if(typeof s=="string"){if(s.length<=dh)return s;let t=await e(s);return t===null?s:{__hydraBlob:t,bytes:s.length}}if(Array.isArray(s)){let t=[];for(let n of s)t.push(await Uo(n,e));return t}if(s&&typeof s=="object"){let t={};for(let[n,r]of Object.entries(s))t[n]=await Uo(r,e);return t}return s}async function qo(s,e){let t=s.params;if(!t||typeof t!="object"||Array.isArray(t))return s;let n=await Bo(t,e);return n===t?s:{...s,params:n}}async function Bo(s,e){if(Sc(s))return await e(s.__hydraBlob)??"";if(Array.isArray(s)){let t=!1,n=[];for(let r of s){let o=await Bo(r,e);o!==r&&(t=!0),n.push(o)}return t?n:s}if(s&&typeof s=="object"){let t=!1,n={};for(let[r,o]of Object.entries(s)){let i=await Bo(o,e);i!==o&&(t=!0),n[r]=i}return t?n:s}return s}function Fn(s,e){let t=-1;for(let n=s.length-1;n>=0;n--)if(s[n]?.messageId===e){t=n;break}if(t<0)return-1;for(let n=t;n<s.length;n++){let r=s[n]?.sessionUpdate;if(r==="turn_complete"||r==="_hydra_turn_ended")return n;if(n>t&&(r==="prompt_received"||r==="_hydra_turn_started"))return n-1}return s.length-1}function zo(s){return s.map(e=>e.method==="session/update"?e.params?.update:void 0)}var mh=Ic(fh),hh=Ic(ph),yh=/^history\.jsonl\.(\d+)(\.gz)?$/,Oe=/^[A-Za-z0-9_-]+$/;function wh(s){try{let e=JSON.parse(s);return e.method==="session/update"?e.params?.update:void 0}catch{return}}var kh=1e3,vh=1e7,bh=10,Us=class{writeQueues=new Map;maxEntries;archiveMaxBytes;archiveTiers;nextArchiveIndex=new Map;archiveLineCounts=new Map;constructor(e={}){this.maxEntries=e.maxEntries??kh,this.archiveMaxBytes=e.archiveMaxBytes??vh,this.archiveTiers=e.archiveTiers??bh}async append(e,t){if(Oe.test(e))return this.enqueue(e,async()=>{await G.mkdir(E.sessionDir(e),{recursive:!0});let n=await Wo(t,o=>Hr(e,o)),r=JSON.stringify(n)+`
146
+ `;await G.appendFile(E.historyFile(e),r,{encoding:"utf8",mode:384})})}async rewrite(e,t){if(Oe.test(e))return this.enqueue(e,async()=>{await G.mkdir(E.sessionDir(e),{recursive:!0});let n=[];for(let o of t)n.push(await Wo(o,i=>Hr(e,i)));let r=n.length===0?"":n.map(o=>JSON.stringify(o)).join(`
147
147
  `)+`
148
- `;await G.writeFile(T.historyFile(e),r,{encoding:"utf8",mode:384})})}async truncateAfterTurn(e,t){if(!Oe.test(e))return;let n;return await this.enqueue(e,async()=>{let r="";try{r=await G.readFile(T.historyFile(e),"utf8")}catch(d){if(d.code!=="ENOENT")throw d}let o=r.split(`
149
- `).filter(d=>d.length>0),i=0;if(t!==null){let d=$n(o.map(hh),t);if(d<0)return;i=d+1}let a=o.slice(0,i);if(await G.writeFile(T.historyFile(e),a.length===0?"":a.join(`
148
+ `;await G.writeFile(E.historyFile(e),r,{encoding:"utf8",mode:384})})}async truncateAfterTurn(e,t){if(!Oe.test(e))return;let n;return await this.enqueue(e,async()=>{let r="";try{r=await G.readFile(E.historyFile(e),"utf8")}catch(d){if(d.code!=="ENOENT")throw d}let o=r.split(`
149
+ `).filter(d=>d.length>0),i=0;if(t!==null){let d=Fn(o.map(wh),t);if(d<0)return;i=d+1}let a=o.slice(0,i);if(await G.writeFile(E.historyFile(e),a.length===0?"":a.join(`
150
150
  `)+`
151
- `,{encoding:"utf8",mode:384}),t===null){for(let d of await this.listArchiveIndices(e))await this.unlinkArchive(e,d);this.nextArchiveIndex.delete(e)}this.archiveLineCounts.delete(e),n={kept:a.length,removed:o.length-a.length}}),n}async compact(e,t){if(Oe.test(e))return this.enqueue(e,async()=>{let n;try{n=await G.readFile(T.historyFile(e),"utf8")}catch(a){if(a.code==="ENOENT")return;throw a}let r=n.split(`
152
- `).filter(a=>a.length>0);if(r.length<=t)return;let o=r.slice(0,r.length-t),i=r.slice(-t);this.archiveMaxBytes>0&&o.length>0&&await this.spillToArchive(e,o),await G.writeFile(T.historyFile(e),i.join(`
151
+ `,{encoding:"utf8",mode:384}),t===null){for(let d of await this.listArchiveIndices(e))await this.unlinkArchive(e,d);this.nextArchiveIndex.delete(e)}this.archiveLineCounts.delete(e),n={kept:a.length,removed:o.length-a.length}}),n}async compact(e,t){if(Oe.test(e))return this.enqueue(e,async()=>{let n;try{n=await G.readFile(E.historyFile(e),"utf8")}catch(a){if(a.code==="ENOENT")return;throw a}let r=n.split(`
152
+ `).filter(a=>a.length>0);if(r.length<=t)return;let o=r.slice(0,r.length-t),i=r.slice(-t);this.archiveMaxBytes>0&&o.length>0&&await this.spillToArchive(e,o),await G.writeFile(E.historyFile(e),i.join(`
153
153
  `)+`
154
154
  `,{encoding:"utf8",mode:384})})}async spillToArchive(e,t){let n=t.join(`
155
155
  `)+`
156
- `,r=await this.resolveNextArchiveIndex(e);await this.enforceArchiveTierCap(e,r);let o=T.historyArchiveFile(e,r);await G.mkdir(T.sessionDir(e),{recursive:!0}),await G.appendFile(o,n,{encoding:"utf8",mode:384});let i=0;try{i=(await G.stat(o)).size}catch{i=0}i>=this.archiveMaxBytes?(await this.sealArchive(e,r),this.nextArchiveIndex.set(e,r+1)):this.nextArchiveIndex.set(e,r),this.archiveLineCounts.delete(e)}async sealArchive(e,t){let n=T.historyArchiveFile(e,t),r;try{r=await G.readFile(n)}catch(i){if(i.code==="ENOENT")return;throw i}let o=await ph(r);await G.writeFile(n+".gz",o,{mode:384});try{await G.unlink(n)}catch(i){if(i.code!=="ENOENT")throw i}}async resolveNextArchiveIndex(e){let t=this.nextArchiveIndex.get(e);if(t!==void 0)return t;let n=await this.listArchiveIndices(e),r=n.length===0?0:n[n.length-1],o=r===0?1:r;if(r>0){let i=T.historyArchiveFile(e,r),a=i+".gz",d=!1;try{await G.access(a),d=!0}catch{d=!1}if(d)o=r+1;else try{(await G.stat(i)).size>=this.archiveMaxBytes&&(o=r+1)}catch{o=r}}return this.nextArchiveIndex.set(e,o),o}async enforceArchiveTierCap(e,t){if(this.archiveTiers<=0)return;let n=await this.listArchiveIndices(e),o=(n.includes(t)?n.length:n.length+1)-this.archiveTiers,i=0;for(;o>0&&i<n.length;){let a=n[i];a!==t&&(await this.unlinkArchive(e,a),o-=1),i+=1}}async unlinkArchive(e,t){let n=T.historyArchiveFile(e,t);for(let r of[n,n+".gz"])try{await G.unlink(r)}catch(o){if(o.code!=="ENOENT")throw o}this.archiveLineCounts.delete(e)}async listArchiveIndices(e){let t;try{t=await G.readdir(T.sessionDir(e))}catch(r){if(r.code==="ENOENT")return[];throw r}let n=new Set;for(let r of t){let o=mh.exec(r);if(!o)continue;let i=Number.parseInt(o[1],10);Number.isFinite(i)&&i>0&&n.add(i)}return[...n].sort((r,o)=>r-o)}async listArchives(e){if(!Oe.test(e))return[];let t=await this.listArchiveIndices(e),n=[];for(let r of t){let o=T.historyArchiveFile(e,r),i=o+".gz",a=o;try{await G.access(i),a=i}catch{a=o}n.push({index:r,path:a})}return n}async loadArchives(e){if(!Oe.test(e))return[];let t=this.writeQueues.get(e);t&&await t;let n=await this.listArchives(e),r=[];for(let{path:o}of n){let i;try{if(o.endsWith(".gz")){let a=await G.readFile(o);i=(await gh(a)).toString("utf8")}else i=await G.readFile(o,"utf8")}catch(a){if(a.code==="ENOENT")continue;throw a}for(let a of i.split(`
157
- `)){if(a.length===0)continue;let d;try{d=JSON.parse(a)}catch{continue}if(!d||typeof d!="object"||Array.isArray(d))continue;let c=d;typeof c.method=="string"&&typeof c.recordedAt=="number"&&r.push({method:c.method,params:c.params,recordedAt:c.recordedAt,...typeof c.seq=="number"?{seq:c.seq}:{}})}}return r}async*streamFile(e){let t;try{t=dh(e)}catch(i){if(i.code==="ENOENT")return;throw i}if(await new Promise(i=>{let a=!1,d=c=>{a||(a=!0,i(c))};t.once("error",c=>{c.code==="ENOENT"?d(!0):(t.destroy(),d(!1))}),t.once("readable",()=>d(!1)),t.once("end",()=>d(!1))}))return;let r=e.endsWith(".gz")?t.pipe(ch()):t,o=fh({input:r,crlfDelay:1/0});try{for await(let i of o){if(i.length===0)continue;let a;try{a=JSON.parse(i)}catch{continue}if(!a||typeof a!="object"||Array.isArray(a))continue;let d=a;typeof d.method=="string"&&typeof d.recordedAt=="number"&&(yield{method:d.method,params:d.params,recordedAt:d.recordedAt,...typeof d.seq=="number"?{seq:d.seq}:{}})}}finally{o.close(),t.destroy()}}async getArchiveLineCounts(e){if(!Oe.test(e))return[];let t=this.archiveLineCounts.get(e),n=await this.listArchives(e);if(t&&t.length===n.length&&t.every((o,i)=>o.index===n[i].index&&o.path===n[i].path))return t;let r=[];for(let{index:o,path:i}of n){let a=t?.find(c=>c.index===o&&c.path===i);if(a){r.push(a);continue}let d=0;for await(let c of this.streamFile(i))d+=1;r.push({index:o,path:i,lineCount:d})}return this.archiveLineCounts.set(e,r),r}async hydrate(e,t){let n=new Map,r=[];for(let o of t)r.push(await this.hydrateEntry(e,o,n));return r}async hydrateEntry(e,t,n){return Bo(t,async r=>{let o=n.get(r);if(o!==void 0)return o;let i=await mn(e,r);return n.set(r,i),i})}async*iterRecallNewestFirst(e,t={}){if(!Oe.test(e))return;let n=this.writeQueues.get(e);n&&await n;let r=await this.getArchiveLineCounts(e),o=0;for(let l of r)o+=l.lineCount;let i=new Map,a=[];for await(let l of this.streamFile(T.historyFile(e)))a.push(l);let d=t.hydrate!==!1;for(let l=a.length-1;l>=0;l--){let p=d?await this.hydrateEntry(e,a[l],i):a[l];yield{entryId:o+l,entry:p}}let c=new Array(r.length),u=0;for(let l=0;l<r.length;l++)c[l]=u,u+=r[l].lineCount;for(let l=r.length-1;l>=0;l--){let p=r[l],f=[];for await(let k of this.streamFile(p.path))f.push(k);let h=c[l];for(let k=f.length-1;k>=0;k--){let m=d?await this.hydrateEntry(e,f[k],i):f[k];yield{entryId:h+k,entry:m}}}}async pageBefore(e,t){let n=[],r=0,o=!1,i=!1;for await(let{entry:a}of this.iterRecallNewestFirst(e,{hydrate:t.hydrate})){if(!o){if(a.seq===void 0||a.seq>=t.beforeSeq)continue;o=!0}if(t.skip?.(a))continue;if(r>=t.turns){i=!0;break}let d=a.params?.update;n.push(a),d?.sessionUpdate==="prompt_received"&&(r+=1)}return n.reverse(),{entries:n,hasMore:i}}async rangeSlice(e,t,n){if(!Oe.test(e))return[];if(n<t)return[];let r=this.writeQueues.get(e);r&&await r;let o=await this.getArchiveLineCounts(e),i=0;for(let u of o)i+=u.lineCount;let a=[],d=new Map,c=0;for(let u of o){let l=c,p=c+u.lineCount;if(c=p,p<=t)continue;if(l>n)break;let f=0;for await(let h of this.streamFile(u.path)){let k=l+f;if(f+=1,k<t)continue;if(k>n)break;let m=await this.hydrateEntry(e,h,d);a.push({entryId:k,entry:m})}}if(n>=i){let u=Math.max(t-i,0),l=n-i,p=0;for await(let f of this.streamFile(T.historyFile(e))){if(p>l)break;if(p>=u){let h=await this.hydrateEntry(e,f,d);a.push({entryId:i+p,entry:h})}p+=1}}return a}async getRecallTotalCount(e){if(!Oe.test(e))return 0;let t=await this.getArchiveLineCounts(e),n=0;for(let o of t)n+=o.lineCount;let r=0;for await(let o of this.streamFile(T.historyFile(e)))r+=1;return n+r}async load(e,t={}){if(!Oe.test(e))return[];let n=(t.tools??"inline")==="inline",r=this.writeQueues.get(e);r&&await r;let o;try{o=await G.readFile(T.historyFile(e),"utf8")}catch(p){if(p.code==="ENOENT")return[];throw p}let i=[];for(let p of o.split(`
158
- `)){if(p.length===0)continue;let f;try{f=JSON.parse(p)}catch{continue}if(!f||typeof f!="object"||Array.isArray(f))continue;let h=f;typeof h.method=="string"&&typeof h.recordedAt=="number"&&i.push({method:h.method,params:h.params,recordedAt:h.recordedAt,...typeof h.seq=="number"?{seq:h.seq}:{}})}let a=t.maxEntries??this.maxEntries,d=i.length>a?i.slice(-a):i;if(!n)return d;let c=new Map,u=async p=>{let f=c.get(p);if(f!==void 0)return f;let h=await mn(e,p);return c.set(p,h),h},l=[];for(let p of d)l.push(await Bo(p,u));return l}async flushAll(){let e=[...this.writeQueues.values()];e.length!==0&&await Promise.allSettled(e)}async delete(e){if(Oe.test(e))return this.enqueue(e,async()=>{try{await G.unlink(T.historyFile(e))}catch(n){if(n.code!=="ENOENT")throw n}let t=await this.listArchiveIndices(e);for(let n of t)await this.unlinkArchive(e,n);this.nextArchiveIndex.delete(e),this.archiveLineCounts.delete(e),await Ki(e);try{await G.rmdir(T.sessionDir(e))}catch(n){let r=n;if(r.code!=="ENOENT"&&r.code!=="ENOTEMPTY")throw n}})}enqueue(e,t){let r=(this.writeQueues.get(e)??Promise.resolve()).then(t,t),o=r.catch(()=>{});return this.writeQueues.set(e,o),o.finally(()=>{this.writeQueues.get(e)===o&&this.writeQueues.delete(e)}),r}};Y();import{promises as Sc}from"fs";import*as Ic from"path";async function Ac(s,e){await Sc.mkdir(Ic.dirname(s),{recursive:!0});let t=e.map(n=>JSON.stringify(n));await Sc.writeFile(s,t.length>0?t.join(`
156
+ `,r=await this.resolveNextArchiveIndex(e);await this.enforceArchiveTierCap(e,r);let o=E.historyArchiveFile(e,r);await G.mkdir(E.sessionDir(e),{recursive:!0}),await G.appendFile(o,n,{encoding:"utf8",mode:384});let i=0;try{i=(await G.stat(o)).size}catch{i=0}i>=this.archiveMaxBytes?(await this.sealArchive(e,r),this.nextArchiveIndex.set(e,r+1)):this.nextArchiveIndex.set(e,r),this.archiveLineCounts.delete(e)}async sealArchive(e,t){let n=E.historyArchiveFile(e,t),r;try{r=await G.readFile(n)}catch(i){if(i.code==="ENOENT")return;throw i}let o=await mh(r);await G.writeFile(n+".gz",o,{mode:384});try{await G.unlink(n)}catch(i){if(i.code!=="ENOENT")throw i}}async resolveNextArchiveIndex(e){let t=this.nextArchiveIndex.get(e);if(t!==void 0)return t;let n=await this.listArchiveIndices(e),r=n.length===0?0:n[n.length-1],o=r===0?1:r;if(r>0){let i=E.historyArchiveFile(e,r),a=i+".gz",d=!1;try{await G.access(a),d=!0}catch{d=!1}if(d)o=r+1;else try{(await G.stat(i)).size>=this.archiveMaxBytes&&(o=r+1)}catch{o=r}}return this.nextArchiveIndex.set(e,o),o}async enforceArchiveTierCap(e,t){if(this.archiveTiers<=0)return;let n=await this.listArchiveIndices(e),o=(n.includes(t)?n.length:n.length+1)-this.archiveTiers,i=0;for(;o>0&&i<n.length;){let a=n[i];a!==t&&(await this.unlinkArchive(e,a),o-=1),i+=1}}async unlinkArchive(e,t){let n=E.historyArchiveFile(e,t);for(let r of[n,n+".gz"])try{await G.unlink(r)}catch(o){if(o.code!=="ENOENT")throw o}this.archiveLineCounts.delete(e)}async listArchiveIndices(e){let t;try{t=await G.readdir(E.sessionDir(e))}catch(r){if(r.code==="ENOENT")return[];throw r}let n=new Set;for(let r of t){let o=yh.exec(r);if(!o)continue;let i=Number.parseInt(o[1],10);Number.isFinite(i)&&i>0&&n.add(i)}return[...n].sort((r,o)=>r-o)}async listArchives(e){if(!Oe.test(e))return[];let t=await this.listArchiveIndices(e),n=[];for(let r of t){let o=E.historyArchiveFile(e,r),i=o+".gz",a=o;try{await G.access(i),a=i}catch{a=o}n.push({index:r,path:a})}return n}async loadArchives(e){if(!Oe.test(e))return[];let t=this.writeQueues.get(e);t&&await t;let n=await this.listArchives(e),r=[];for(let{path:o}of n){let i;try{if(o.endsWith(".gz")){let a=await G.readFile(o);i=(await hh(a)).toString("utf8")}else i=await G.readFile(o,"utf8")}catch(a){if(a.code==="ENOENT")continue;throw a}for(let a of i.split(`
157
+ `)){if(a.length===0)continue;let d;try{d=JSON.parse(a)}catch{continue}if(!d||typeof d!="object"||Array.isArray(d))continue;let c=d;typeof c.method=="string"&&typeof c.recordedAt=="number"&&r.push({method:c.method,params:c.params,recordedAt:c.recordedAt,...typeof c.seq=="number"?{seq:c.seq}:{}})}}return r}async*streamFile(e){let t;try{t=uh(e)}catch(i){if(i.code==="ENOENT")return;throw i}if(await new Promise(i=>{let a=!1,d=c=>{a||(a=!0,i(c))};t.once("error",c=>{c.code==="ENOENT"?d(!0):(t.destroy(),d(!1))}),t.once("readable",()=>d(!1)),t.once("end",()=>d(!1))}))return;let r=e.endsWith(".gz")?t.pipe(lh()):t,o=gh({input:r,crlfDelay:1/0});try{for await(let i of o){if(i.length===0)continue;let a;try{a=JSON.parse(i)}catch{continue}if(!a||typeof a!="object"||Array.isArray(a))continue;let d=a;typeof d.method=="string"&&typeof d.recordedAt=="number"&&(yield{method:d.method,params:d.params,recordedAt:d.recordedAt,...typeof d.seq=="number"?{seq:d.seq}:{}})}}finally{o.close(),t.destroy()}}async getArchiveLineCounts(e){if(!Oe.test(e))return[];let t=this.archiveLineCounts.get(e),n=await this.listArchives(e);if(t&&t.length===n.length&&t.every((o,i)=>o.index===n[i].index&&o.path===n[i].path))return t;let r=[];for(let{index:o,path:i}of n){let a=t?.find(c=>c.index===o&&c.path===i);if(a){r.push(a);continue}let d=0;for await(let c of this.streamFile(i))d+=1;r.push({index:o,path:i,lineCount:d})}return this.archiveLineCounts.set(e,r),r}async hydrate(e,t){let n=new Map,r=[];for(let o of t)r.push(await this.hydrateEntry(e,o,n));return r}async hydrateEntry(e,t,n){return qo(t,async r=>{let o=n.get(r);if(o!==void 0)return o;let i=await yn(e,r);return n.set(r,i),i})}async*iterRecallNewestFirst(e,t={}){if(!Oe.test(e))return;let n=this.writeQueues.get(e);n&&await n;let r=await this.getArchiveLineCounts(e),o=0;for(let l of r)o+=l.lineCount;let i=new Map,a=[];for await(let l of this.streamFile(E.historyFile(e)))a.push(l);let d=t.hydrate!==!1;for(let l=a.length-1;l>=0;l--){let p=d?await this.hydrateEntry(e,a[l],i):a[l];yield{entryId:o+l,entry:p}}let c=new Array(r.length),u=0;for(let l=0;l<r.length;l++)c[l]=u,u+=r[l].lineCount;for(let l=r.length-1;l>=0;l--){let p=r[l],f=[];for await(let k of this.streamFile(p.path))f.push(k);let h=c[l];for(let k=f.length-1;k>=0;k--){let m=d?await this.hydrateEntry(e,f[k],i):f[k];yield{entryId:h+k,entry:m}}}}async pageBefore(e,t){let n=[],r=0,o=!1,i=!1;for await(let{entry:a}of this.iterRecallNewestFirst(e,{hydrate:t.hydrate})){if(!o){if(a.seq===void 0||a.seq>=t.beforeSeq)continue;o=!0}if(t.skip?.(a))continue;if(r>=t.turns){i=!0;break}let d=a.params?.update;n.push(a),d?.sessionUpdate==="prompt_received"&&(r+=1)}return n.reverse(),{entries:n,hasMore:i}}async rangeSlice(e,t,n){if(!Oe.test(e))return[];if(n<t)return[];let r=this.writeQueues.get(e);r&&await r;let o=await this.getArchiveLineCounts(e),i=0;for(let u of o)i+=u.lineCount;let a=[],d=new Map,c=0;for(let u of o){let l=c,p=c+u.lineCount;if(c=p,p<=t)continue;if(l>n)break;let f=0;for await(let h of this.streamFile(u.path)){let k=l+f;if(f+=1,k<t)continue;if(k>n)break;let m=await this.hydrateEntry(e,h,d);a.push({entryId:k,entry:m})}}if(n>=i){let u=Math.max(t-i,0),l=n-i,p=0;for await(let f of this.streamFile(E.historyFile(e))){if(p>l)break;if(p>=u){let h=await this.hydrateEntry(e,f,d);a.push({entryId:i+p,entry:h})}p+=1}}return a}async getRecallTotalCount(e){if(!Oe.test(e))return 0;let t=await this.getArchiveLineCounts(e),n=0;for(let o of t)n+=o.lineCount;let r=0;for await(let o of this.streamFile(E.historyFile(e)))r+=1;return n+r}async load(e,t={}){if(!Oe.test(e))return[];let n=(t.tools??"inline")==="inline",r=this.writeQueues.get(e);r&&await r;let o;try{o=await G.readFile(E.historyFile(e),"utf8")}catch(p){if(p.code==="ENOENT")return[];throw p}let i=[];for(let p of o.split(`
158
+ `)){if(p.length===0)continue;let f;try{f=JSON.parse(p)}catch{continue}if(!f||typeof f!="object"||Array.isArray(f))continue;let h=f;typeof h.method=="string"&&typeof h.recordedAt=="number"&&i.push({method:h.method,params:h.params,recordedAt:h.recordedAt,...typeof h.seq=="number"?{seq:h.seq}:{}})}let a=t.maxEntries??this.maxEntries,d=i.length>a?i.slice(-a):i;if(!n)return d;let c=new Map,u=async p=>{let f=c.get(p);if(f!==void 0)return f;let h=await yn(e,p);return c.set(p,h),h},l=[];for(let p of d)l.push(await qo(p,u));return l}async flushAll(){let e=[...this.writeQueues.values()];e.length!==0&&await Promise.allSettled(e)}async delete(e){if(Oe.test(e))return this.enqueue(e,async()=>{try{await G.unlink(E.historyFile(e))}catch(n){if(n.code!=="ENOENT")throw n}let t=await this.listArchiveIndices(e);for(let n of t)await this.unlinkArchive(e,n);this.nextArchiveIndex.delete(e),this.archiveLineCounts.delete(e),await Yi(e);try{await G.rmdir(E.sessionDir(e))}catch(n){let r=n;if(r.code!=="ENOENT"&&r.code!=="ENOTEMPTY")throw n}})}enqueue(e,t){let r=(this.writeQueues.get(e)??Promise.resolve()).then(t,t),o=r.catch(()=>{});return this.writeQueues.set(e,o),o.finally(()=>{this.writeQueues.get(e)===o&&this.writeQueues.delete(e)}),r}};Y();import{promises as Ac}from"fs";import*as Cc from"path";async function Rc(s,e){await Ac.mkdir(Cc.dirname(s),{recursive:!0});let t=e.map(n=>JSON.stringify(n));await Ac.writeFile(s,t.length>0?t.join(`
159
159
  `)+`
160
- `:"")}import{z as K}from"zod";var vh=K.object({method:K.string(),params:K.unknown(),recordedAt:K.number()}),bh=K.object({sessionId:K.string(),lineageId:K.string(),upstreamSessionId:K.string().optional(),agentId:K.string(),cwd:K.string(),title:K.string().optional(),synopsis:Rn.optional(),summarizedThroughEntry:K.number().int().nonnegative().optional(),currentModel:K.string().optional(),currentMode:K.string().optional(),currentUsage:Ro.optional(),agentCommands:K.array(Ao).optional(),agentModes:K.array(Co).optional(),interactive:K.boolean().optional(),originatingClient:xo.optional(),priority:K.number().int().nonnegative().optional(),createdAt:K.string(),updatedAt:K.string()}),Sh=K.object({version:K.literal(1),exportedAt:K.string(),exportedFrom:K.object({hydraVersion:K.string(),machine:K.string(),hydraHost:K.string().optional()}),session:bh,history:K.array(vh),promptHistory:K.array(K.string()).optional(),toolBlobs:K.record(K.string()).optional()});function On(s){let e={version:1,exportedAt:new Date().toISOString(),exportedFrom:{hydraVersion:s.hydraVersion,machine:s.machine,...s.hydraHost!==void 0&&s.hydraHost.length>0?{hydraHost:s.hydraHost}:{}},session:{sessionId:s.record.sessionId,lineageId:s.record.lineageId,...s.record.upstreamSessionId?{upstreamSessionId:s.record.upstreamSessionId}:{},agentId:s.record.agentId,cwd:s.record.cwd,...s.record.title!==void 0?{title:s.record.title}:{},...s.record.synopsis!==void 0?{synopsis:s.record.synopsis}:{},...s.record.summarizedThroughEntry!==void 0?{summarizedThroughEntry:s.record.summarizedThroughEntry}:{},...s.record.currentModel!==void 0?{currentModel:s.record.currentModel}:{},...s.record.currentMode!==void 0?{currentMode:s.record.currentMode}:{},...s.record.currentUsage!==void 0?{currentUsage:s.record.currentUsage}:{},...s.record.agentCommands!==void 0?{agentCommands:s.record.agentCommands}:{},...s.record.agentModes!==void 0?{agentModes:s.record.agentModes}:{},...s.record.interactive!==void 0?{interactive:s.record.interactive}:{},...s.record.originatingClient!==void 0?{originatingClient:s.record.originatingClient}:{},...s.record.priority!==void 0&&s.record.priority>0?{priority:s.record.priority}:{},createdAt:s.record.createdAt,updatedAt:s.record.updatedAt},history:s.history};return s.promptHistory!==void 0&&(e.promptHistory=s.promptHistory),s.toolBlobs!==void 0&&Object.keys(s.toolBlobs).length>0&&(e.toolBlobs=s.toolBlobs),e}function Cc(s){return Sh.parse(s)}function qo(s){if(s&&!(s.costAmount===void 0&&s.cumulativeCost===void 0))return(s.cumulativeCost??0)+(s.costAmount??0)}function Fn(s){if(!s)return;let e={};s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size);let t=qo(s);return t&&(e.costAmount=t),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),e}var Rc=900*1e3,Ah=12,Ch="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Rt=Ih(Ch,16);function Rh(){let s,e,t=!1;return{send(n){if(t)return Promise.resolve();if("method"in n&&"id"in n){let r={jsonrpc:"2.0",id:n.id,error:{code:x.MethodNotFound,message:`no handler for ${n.method} (headless fork-prompt client)`}};queueMicrotask(()=>s?.(r))}return Promise.resolve()},onMessage(n){s=n},onClose(n){e=n},close(){return t||(t=!0,e?.()),Promise.resolve()}}}var Ls=class s{constructor(e,t,n,r={}){this.registry=e;this.spawner=t??(a=>ct.spawn(a)),this.store=n??new Ss,this.tombstones=r.tombstones??new $s,this.sessionHistoryMaxEntries=r.sessionHistoryMaxEntries??1e3,this.histories=new js({maxEntries:this.sessionHistoryMaxEntries,archiveMaxBytes:r.sessionHistoryArchiveMaxBytes,archiveTiers:r.sessionHistoryArchiveTiers}),this.workspaceSnapshotsDisabled=r.disableWorkspaceSnapshots===!0,this.idleTimeoutMs=r.idleTimeoutMs??0,this.orphanTimeoutMs=r.orphanTimeoutMs??0,this.idleEventTimeoutMs=r.idleEventTimeoutMs??3e4,this.sessionDefaults=r.sessionDefaults??{},this.synopsisAgent=r.synopsisAgent,this.synopsisModel=r.synopsisModel,this.compactionAgent=r.compactionAgent,this.compactionModel=r.compactionModel,this.defaultTransformers=r.defaultTransformers??[],this.logger=r.logger,this.npmRegistry=r.npmRegistry,this.extensionCommands=r.extensionCommands,this.defaultCwd=r.defaultCwd??"~";let o=r.compaction??{},i=o.tailK??20;this.compactionTailK=i,this.synopsisCoordinator=new Ds({registry:this.registry,store:this.store,histories:this.histories,synopsisAgent:this.synopsisAgent,synopsisModel:this.synopsisModel,compactionAgent:this.compactionAgent,compactionModel:this.compactionModel,compactionMaxIterations:o.maxIterations,persistTitle:async(a,d)=>{let c=this.get(a);if(c){await c.retitle(d);return}await this.persistTitle(a,d)},persistSynopsis:(a,d,c)=>this.persistSynopsis(a,d,c),logger:this.logger,npmRegistry:this.npmRegistry,onCompactionStateChange:async(a,d,c)=>{if(c.targetAgentId)return;let u=this.get(a);u&&(u.compactionState=d),await this.mutateRecord(a,{compactionState:d})},broadcastHydraCompaction:(a,d,c)=>{this.emitSwapPhase(a,c.targetAgentId,d)},onSynthesisArtifact:async(a,d,c,u,l)=>{await this.dispatchSynthesisSwap(a,d,c,u,l)},onSynthesisUnavailable:async(a,d,c)=>{let u=await this.store.read(a).catch(()=>{});if(u?.synopsis&&u.summarizedThroughEntry!==void 0){this.logger?.info(`agent switch: synthesis produced no new artifact for sessionId=${a} (${c}); swapping to ${d} on the persisted synopsis`),await this.dispatchSynthesisSwap(a,u.synopsis,u.summarizedThroughEntry,d);return}let l=(await this.histories.load(a).catch(()=>[])).length;this.logger?.warn(`agent switch: synthesis unavailable for sessionId=${a} (${c}); swapping to ${d} on verbatim tail`),await this.dispatchSynthesisSwap(a,void 0,l,d)}}),this.refreshAgentCatalog()}registry;sessions=new Map;resurrectionInflight=new Map;snapshotInFlight=new Set;snapshotPending=new Set;workspaceSnapshotsDisabled=!1;driftNoticed=new Map;pendingAuthAgents=new Map;spawner;store;tombstones;histories;idleTimeoutMs;orphanTimeoutMs;sessionDefaults;synopsisAgent;synopsisModel;compactionAgent;compactionModel;defaultTransformers;idleEventTimeoutMs;sessionHistoryMaxEntries;metaWriteQueues=new Map;workspaceQueues=new Map;listCache=new Map;static LIST_CACHE_TTL_MS=500;logger;npmRegistry;extensionCommands;defaultCwd;synopsisCoordinator;pendingDeletions=new Map;pendingSwapDisposers=new Map;rollbackLocks=new Set;compactionTailK=20;agentCatalog=[];async dispatchSynthesisSwap(e,t,n,r,o){let i=this.get(e);if(t===void 0&&r===void 0)return;if(!i){if(this.logger?.info(`compaction: persisted artifact for cold session sessionId=${e}`),t===void 0)return;await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:n});return}let a=this.compactionTailK;try{if(await i.isQuiescedForSwap()){this.pendingSwapDisposers.get(e)?.(),this.pendingSwapDisposers.delete(e),await this.performSynthesisSwap(i,t,a,n,r,o);return}this.pendingSwapDisposers.get(e)?.(),this.logger?.info(`compaction: session not quiesced, parking onceIdle swap sessionId=${e}`),this.emitSwapPhase(e,r,{phase:"deferred"});let c=i.onceIdle(()=>{this.pendingSwapDisposers.delete(e),this.onIdleAttemptSwap(e)});this.pendingSwapDisposers.set(e,c)}catch(d){this.logger?.warn(`compaction: dispatch failed for sessionId=${e}: ${d instanceof Error?d.message:String(d)}, leaving session as-is`)}}async onIdleAttemptSwap(e){let t=this.get(e);if(!t)return;let n=this.compactionTailK;try{if(!await t.isQuiescedForSwap()){let d=await this.store.read(e).catch(()=>{});d?.synopsis&&d.summarizedThroughEntry!==void 0?this.dispatchSynthesisSwap(e,d.synopsis,d.summarizedThroughEntry,d.pendingAgentSwap):d?.pendingAgentSwap&&this.dispatchSynthesisSwap(e,void 0,(await this.histories.load(e).catch(()=>[])).length,d.pendingAgentSwap);return}let o=await this.store.read(e).catch(()=>{});if(!o?.synopsis||o.summarizedThroughEntry===void 0){if(o?.pendingAgentSwap){let d=(await this.histories.load(e).catch(()=>[])).length;this.logger?.info(`compaction: no artifact for sessionId=${e}, swapping to ${o.pendingAgentSwap} on verbatim tail`),await this.performSynthesisSwap(t,void 0,n,d,o.pendingAgentSwap);return}this.logger?.warn(`compaction: persisted artifact missing for sessionId=${e}, abandoning swap`),t.compactionState=void 0,await this.mutateRecord(e,{},["compactionState"]);return}let i=o.pendingAgentSwap,a=await this.histories.load(e).catch(()=>[]);if(a.length>o.summarizedThroughEntry){this.logger?.info(`compaction: history grew during deferral (have=${a.length} artifact=${o.summarizedThroughEntry}), rescheduling synopsis sessionId=${e}`),i?this.synopsisCoordinator.scheduleCompaction(e,{targetAgentId:i}):this.synopsisCoordinator.scheduleCompaction(e);return}await this.performSynthesisSwap(t,o.synopsis,n,o.summarizedThroughEntry,i,o.compactionState?.runId)}catch(r){this.logger?.warn(`compaction: onIdleAttemptSwap failed for sessionId=${e}: ${r instanceof Error?r.message:String(r)}`)}}async recordSynopsisFor(e){let t=await this.store.read(e).catch(()=>{});return t?.synopsis?{synopsis:t.synopsis}:{}}async performSynthesisSwap(e,t,n,r,o,i){try{let a=o?Math.min(t===void 0?Ah:5,n):0;await e.swapUpstream({...t!==void 0?{artifact:t}:{},tailK:n,tailFloor:a,summarizedThroughEntry:r,...o?{newAgentId:o}:{},...i!==void 0?{runId:i}:{}}),o?await this.mutateRecord(e.sessionId,{},["pendingAgentSwap"]):(e.compactionState=void 0,await this.mutateRecord(e.sessionId,{},["compactionState"]))}catch(a){this.logger?.warn(`compaction: swap failed for sessionId=${e.sessionId}: ${a instanceof Error?a.message:String(a)}, leaving session as-is`)}finally{this.invalidateListCache()}}async refreshAgentCatalog(){try{let{agents:e}=await Dt(this.registry);this.agentCatalog=e.map(t=>({id:t.id,name:t.name,...t.description!==void 0?{description:t.description}:{}}))}catch{}}async adoptWorkspace(e,t,n){let r=t.label;if(r===void 0)throw new Error("workspace.adopt requires workspace.label");let o=this.liveSessionsWithLabel(n.cwd,r)[0]?.workspace,i=o!==void 0?this.asWorkspace(o):(await e.listWorkspaces(n.cwd).catch(()=>[])).find(a=>a.label===r);if(i===void 0)throw new Error(`cannot adopt workspace "${r}": no workspace by that name derived from ${$(n.cwd)}`);return await this.enqueueKeyed(this.workspaceQueues,i.path,async()=>(e.capabilities().locking&&await e.lock(i,`session ${n.title??"live"}`).catch(()=>{}),{cwd:i.path,workspace:{path:i.path,sourceCwd:i.sourceCwd,label:i.label,provider:i.provider,...i.snapshot!==void 0?{snapshot:i.snapshot}:{},...i.line!==void 0?{line:i.line}:{},...i.vcs!==void 0?{vcs:{...i.vcs}}:{},...o?.clean!==void 0?{clean:o.clean}:{}}}))}async resolveWorkspace(e){let t=e.workspace;if(t===void 0)return{cwd:e.cwd};let n=re(t.provider);if(n===void 0){let u=`unknown workspace provider "${t.provider}"`;if(t.required===!0)throw new Error(`isolation required but unavailable: ${u}`);return this.logger?.warn?.(`session workspace: ${u}; running in ${e.cwd}`),{cwd:e.cwd,isolationError:u}}if(t.adopt===!0)return await this.adoptWorkspace(n,t,e);let r=t.label??`s-${Rt().slice(0,8)}`,o=await n.createWorkspace({sourceCwd:e.cwd,label:r,...t.from!==void 0?{from:t.from}:{}}).catch(u=>({ok:!1,reason:String(u)}));if(!o.ok){if(t.required===!0)throw new Error(`isolation required but unavailable: ${o.reason}`);return this.logger?.warn?.(`session workspace: ${o.reason}; falling back to ${e.cwd} (unisolated)`),{cwd:e.cwd,isolationError:o.reason}}let i=o.workspace;n.capabilities().locking&&await n.lock(i,`session ${e.title??"live"}`).catch(()=>{});let a=await Ms(i.sourceCwd).catch(()=>({})),d,c=await this.materializeNestedTrees(i);if(c!==void 0&&this.logger?.info?.(`session workspace: ${c} in ${i.path}`),a.carry!==void 0&&a.carry.length>0){let u=await Do(i.sourceCwd,i.path,a.carry).catch(()=>{});u!==void 0&&u.copied.length>0&&this.logger?.info?.(`session workspace: carried ${u.copied.length} file(s) into ${i.path}`)}if(a.postCreate!==void 0){let u=await _s(a.postCreate,{workspacePath:i.path,sourceCwd:i.sourceCwd,label:i.label,...a.hookTimeoutSeconds!==void 0?{timeoutSeconds:a.hookTimeoutSeconds}:{}});u.ok||(d=`postCreate failed: ${u.reason??"unknown"}`,this.logger?.warn?.(`session workspace: ${d} (${i.path})`))}return i.snapshot!==void 0&&await n.retainSnapshot(i,this.startRefFor(i.label),i.snapshot).catch(()=>{}),{cwd:i.path,workspace:{path:i.path,sourceCwd:i.sourceCwd,label:i.label,provider:i.provider,...i.snapshot!==void 0?{snapshot:i.snapshot}:{},...i.line!==void 0?{line:i.line}:{},...i.vcs!==void 0?{vcs:{...i.vcs}}:{},clean:!0},...d!==void 0?{isolationError:d}:{}}}logInfo(e){this.logger?.info(e)}async create(e){let t=e.timer??new Bt,n=await this.registry.getAgent(e.agentId);n&&n.id!==e.agentId&&(e={...e,agentId:n.id}),t.mark("create.canonicalize");let r=`${ye}${Rt()}`,o=await this.resolveWorkspace(e),i=o.cwd;t.mark("create.workspace");let a=await this.bootstrapAgent({timer:t,agentId:e.agentId,cwd:i,agentArgs:e.agentArgs,mcpServers:e.mcpServers,model:e.model,configDefaults:e.configDefaults,onInstallProgress:e.onInstallProgress,forwardedEnv:e.forwardedEnv,selfSessionId:r});if(e.transformChain&&e.transformChain.length>0){let c={...a.agentCapabilities??{}};for(let u of e.transformChain)if(u.intercepts.has("agent:initialize"))try{let l=await u.connection.request("hydra-acp/transformer/message",{token:`t_${Rt()}`,phase:"response",method:"initialize",direction:"agent\u2192daemon",sessionId:"(pre-session)",envelope:c});l.action==="stop"&&l.payload&&(c=l.payload)}catch{}a.agentCapabilities=c}t.mark("create.transformers");let d=new Kt({sessionId:r,cwd:i,...o.workspace!==void 0?{workspace:o.workspace}:{},...o.isolationError!==void 0?{workspaceError:o.isolationError}:{},agentId:e.agentId,agent:a.agent,upstreamSessionId:a.upstreamSessionId,agentMeta:a.agentMeta,agentCapabilities:a.agentCapabilities,...a.modelVerb?{modelVerb:a.modelVerb}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,orphanTimeoutMs:this.orphanTimeoutMs,idleEventTimeoutMs:this.idleEventTimeoutMs,logger:this.logger,spawnReplacementAgent:c=>this.bootstrapAgent({...c,mcpServers:c.mcpServers??[],selfSessionId:r}),loadExistingAgentSession:(c,u)=>this.bootstrapAgentLoad(c,{...u,mcpServers:u.mcpServers??[],selfSessionId:r}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:a.initialModel,currentMode:a.initialMode,agentModes:a.initialModes,agentModels:a.initialModels,agentConfigOptions:a.initialConfigOptions,transformChain:e.transformChain,parentSessionId:e.parentSessionId,originatingClient:e.originatingClient,interactive:e.interactive,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(d.sessionId),scheduleWorkspaceSnapshot:()=>this.scheduleWorkspaceSnapshot(d),scheduleCompaction:c=>this.scheduleCompaction(d.sessionId,c),resolveAgentId:async c=>(await this.registry.getAgent(c))?.id,getCompactionState:()=>this.getCompactionState(d.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(d.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(d.sessionId),uncompactHook:()=>this.performUncompact(d.sessionId),forkHook:c=>this.forkSession(d.sessionId,c??{}),workspaceHook:(c,u,l)=>this.runWorkspaceAction(d.sessionId,c,u,l),onCompactionSwapHook:c=>{this.persistRollbackBreadcrumb(d.sessionId,c).catch(()=>{})},persistWatermarkHook:c=>{this.mutateRecord(d.sessionId,{summarizedThroughEntry:c}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(d.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});if(t.mark("create.session-ctor"),o.workspace!==void 0){let c=re(o.workspace.provider);c!==void 0&&c.capabilities().supports.environmentNotes&&(d.workspaceNotes=await c.environmentNotes({path:o.workspace.path,sourceCwd:o.workspace.sourceCwd,label:o.workspace.label,provider:o.workspace.provider,...o.workspace.snapshot!==void 0?{snapshot:o.workspace.snapshot}:{},...o.workspace.vcs!==void 0?{vcs:o.workspace.vcs}:{}}).catch(()=>[]))}return await this.attachManagerHooks(d),t.mark("create.persist"),d}async resurrect(e){let t=this.sessions.get(e.hydraSessionId);if(t){if(t.upstreamSessionId!==e.upstreamSessionId){let o=new Error(`session ${e.hydraSessionId} already exists with a different upstream id`);throw o.code=x.AlreadyAttached,o}return t}let n=this.resurrectionInflight.get(e.hydraSessionId);if(n)return n;let r=this.doResurrect(e);this.resurrectionInflight.set(e.hydraSessionId,r);try{return await r}finally{this.resurrectionInflight.delete(e.hydraSessionId)}}async doResurrect(e){let t=this.sessions.get(e.hydraSessionId);if(t)return t;let n=await this.registry.getAgent(e.agentId);if(!n){let w=new Error(`agent ${e.agentId} not found in registry; cannot resurrect`);throw w.code=x.AgentNotInstalled,w}if(e.upstreamSessionId==="")return this.doResurrectFromImport(e);if(!await this.dirExists(e.cwd))return this.doResurrectFromImport(e);let r=await _e(n,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),o=es(e.hydraSessionId,e.forwardedEnv),i=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:r,...o?{extraEnv:o}:{}}),a;try{let w=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:jt,clientInfo:{name:"hydra",version:ue}});a=w.agentCapabilities,i.authMethods=Dn(w.authMethods),i.steeringSupported=Nn(w)}catch(w){throw await i.kill().catch(()=>{}),ht(w,i)}let d;try{let w=Jo(n,{model:e.currentModel});d=await i.connection.request("session/load",{sessionId:e.upstreamSessionId,cwd:e.cwd,mcpServers:e.mcpServers??[],...w&&{_meta:w}})}catch(w){if(w&&typeof w=="object"&&w.code===x.AuthRequired)throw await i.kill().catch(()=>{}),ht(w,i);return process.stderr.write(`session/load failed for upstream ${e.upstreamSessionId} on ${e.agentId} (${w.message}); recovering via import-reseed
161
- `),await i.kill().catch(()=>{}),this.doResurrectFromImport(e)}if(e.pendingHistorySync===!0)this.clearPendingHistorySync(e.hydraSessionId).catch(()=>{});else{let w=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain1 dropped ${w} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let c=Qo(d??{}),u=e.agentModes??mt(Ko(d??{}));this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedMode=${JSON.stringify(e.currentMode)} agentReportedMode=${JSON.stringify(c)} advertisedModes=${JSON.stringify(u?.map(w=>w.id))}`);let l=await lt({agent:i,upstreamSessionId:e.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:c,advertisedModes:u,logger:this.logger});this.logger?.info(`resurrect: effectiveMode=${JSON.stringify(l)} for sessionId=${e.hydraSessionId}`);let p=Vo(d??{}),f=mt(Go(d??{}))??e.agentModels;if(this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedModel=${JSON.stringify(e.currentModel)} agentReportedModel=${JSON.stringify(p)} advertisedModels=${JSON.stringify(f?.map(w=>w.modelId))}`),e.pendingHistorySync!==!0){let w=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain2 (post-mode-restore) dropped ${w} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let h=Ut(d),k=await ft({agent:i,upstreamSessionId:e.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:p,...h?{modelVerb:h}:{},logger:this.logger}),m=k.modelId,g=mt(tn(en(k.result)?k.result:d??{}));if(g=mt(await this.restoreConfigOptionValues(i,e.upstreamSessionId,e.configOptionValues,g??[])),e.pendingHistorySync!==!0){let w=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain3 (post-model-restore) dropped ${w} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let y=new Kt({sessionId:e.hydraSessionId,cwd:e.cwd,...e.workspace!==void 0?{workspace:e.workspace}:{},agentId:e.agentId,agent:i,upstreamSessionId:e.upstreamSessionId,agentMeta:d?._meta,agentCapabilities:a,...h?{modelVerb:h}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,orphanTimeoutMs:this.orphanTimeoutMs,logger:this.logger,spawnReplacementAgent:w=>this.bootstrapAgent({...w,mcpServers:w.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),loadExistingAgentSession:(w,v)=>this.bootstrapAgentLoad(w,{...v,mcpServers:v.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:m,currentMode:l,currentUsage:e.currentUsage,reloadsUpstreamLedger:!0,agentCommands:e.agentCommands,agentModes:u,agentModels:f,agentConfigOptions:g,summarizedThroughEntry:e.summarizedThroughEntry,compactionState:e.compactionState,firstPromptSeeded:!!e.title,upstreamRespawned:!0,createdAt:e.createdAt?new Date(e.createdAt).getTime():void 0,originatingClient:e.originatingClient,interactive:e.interactive,priority:e.priority,lastTurnEndedAt:e.lastTurnEndedAt,readAt:e.readAt,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,side:e.side,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,attentionFlags:e.attentionFlags,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(y.sessionId),scheduleWorkspaceSnapshot:()=>this.scheduleWorkspaceSnapshot(y),scheduleCompaction:w=>this.scheduleCompaction(y.sessionId,w),resolveAgentId:async w=>(await this.registry.getAgent(w))?.id,getCompactionState:()=>this.getCompactionState(y.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(y.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(y.sessionId),uncompactHook:()=>this.performUncompact(y.sessionId),forkHook:w=>this.forkSession(y.sessionId,w??{}),workspaceHook:(w,v,S)=>this.runWorkspaceAction(y.sessionId,w,v,S),onCompactionSwapHook:w=>{this.persistRollbackBreadcrumb(y.sessionId,w).catch(()=>{})},persistWatermarkHook:w=>{this.mutateRecord(y.sessionId,{summarizedThroughEntry:w}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(y.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(y),y}async doResurrectFromImport(e){let t=await this.resolveResurrectTarget(e.cwd,e.workspace),n=t.cwd,r=await this.bootstrapAgent({agentId:e.agentId,cwd:n,agentArgs:e.agentArgs,mcpServers:e.mcpServers??[],onInstallProgress:e.onInstallProgress,forwardedEnv:e.forwardedEnv,model:e.currentModel}),o=e.agentModes??r.initialModes,i=await lt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:r.initialMode,advertisedModes:o,logger:this.logger}),a=e.agentModels??r.initialModels,d=await ft({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:r.initialModel,...r.modelVerb?{modelVerb:r.modelVerb}:{},logger:this.logger}),c=d.modelId,u=en(d.result)?mt(tn(d.result)):void 0;u=mt(await this.restoreConfigOptionValues(r.agent,r.upstreamSessionId,e.configOptionValues,u??r.initialConfigOptions??[])),r.agent.connection.drainBuffered("session/update");let l=new Kt({sessionId:e.hydraSessionId,cwd:n,...t.workspace!==void 0?{workspace:t.workspace}:{},agentId:e.agentId,agent:r.agent,upstreamSessionId:r.upstreamSessionId,agentMeta:r.agentMeta,agentCapabilities:r.agentCapabilities,...r.modelVerb?{modelVerb:r.modelVerb}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,orphanTimeoutMs:this.orphanTimeoutMs,logger:this.logger,spawnReplacementAgent:p=>this.bootstrapAgent({...p,mcpServers:p.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),loadExistingAgentSession:(p,f)=>this.bootstrapAgentLoad(p,{...f,mcpServers:f.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:c,currentMode:i,currentUsage:e.currentUsage,agentCommands:e.agentCommands,agentModes:o,agentModels:a,agentConfigOptions:u??r.initialConfigOptions,summarizedThroughEntry:e.summarizedThroughEntry,firstPromptSeeded:!!e.title,upstreamRespawned:!0,createdAt:e.createdAt?new Date(e.createdAt).getTime():void 0,originatingClient:e.originatingClient,interactive:e.interactive,priority:e.priority,lastTurnEndedAt:e.lastTurnEndedAt,readAt:e.readAt,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,side:e.side,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,attentionFlags:e.attentionFlags,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(l.sessionId),scheduleWorkspaceSnapshot:()=>this.scheduleWorkspaceSnapshot(l),scheduleCompaction:p=>this.scheduleCompaction(l.sessionId,p),resolveAgentId:async p=>(await this.registry.getAgent(p))?.id,getCompactionState:()=>this.getCompactionState(l.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(l.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(l.sessionId),uncompactHook:()=>this.performUncompact(l.sessionId),forkHook:p=>this.forkSession(l.sessionId,p??{}),workspaceHook:(p,f,h)=>this.runWorkspaceAction(l.sessionId,p,f,h),onCompactionSwapHook:p=>{this.persistRollbackBreadcrumb(l.sessionId,p).catch(()=>{})},persistWatermarkHook:p=>{this.mutateRecord(l.sessionId,{summarizedThroughEntry:p}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(l.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(l),e.forkedFromSessionId&&e.forkSynthesisState==="running"?this.logger?.info(`fork ${l.sessionId}: synthesis in flight \u2014 skipping seed, recall available`):e.forkedFromSessionId&&(e.synopsis||(e.summarizedThroughEntry??0)>0)?l.seedFromFork(e.synopsis).catch(()=>{}):l.seedFromImport().catch(()=>{}),l}async dirExists(e){try{return(await xt.stat(e)).isDirectory()}catch{return!1}}async reapIfOrphanedNonInteractive(e){let t=this.sessions.get(e);if(!(!t||t.attachedCount>0)&&t.interactive!==!0){if(t.hasWorkInFlight){this.logger?.info(`deferring reap of ${e}: work still in flight after detach`),t.onceIdle(n=>{this.reapIfOrphanedNonInteractive(n.sessionId).catch(()=>{})});return}this.logger?.info(`reaping orphaned non-interactive session ${e} (agent killed, cold record kept)`),await t.close({deleteRecord:!1,by:"reap-orphaned"}).catch(()=>{})}}async resolveResurrectTarget(e,t){if(await this.dirExists(e))return t!==void 0?{cwd:e,workspace:t}:{cwd:e};if(t!==void 0){let n=await this.recoverWorkspace(t);if(n!==void 0)return{cwd:n.path,workspace:n}}return{cwd:ce(this.defaultCwd)}}async releaseWorkspace(e,t){let n=re(e.provider);if(n===void 0){this.logger?.warn?.(`session workspace: no provider "${e.provider}" to release ${e.path}; leaving it in place`);return}return this.enqueueKeyed(this.workspaceQueues,e.path,async()=>{let r=this.liveSessionsIn(e.path,t);if(r.length>0){this.logger?.info?.(`session workspace: keeping ${e.path} \u2014 ${r.length} live session(s) still in it`);return}await this.tearDownWorkspace(n,e,t)})}async syncWorkspaceFromSource(e,t,n){let r=this.liveSessionsIn(t.path,e.sessionId);if(r.length>0)throw new Error(`${$(t.path)} is shared with ${r.map(f=>tt(f.sessionId)).join(", ")}, and a sync would move files under them. Sync it from a session that has it to itself.`);let o=await e.quiesceBlocker();if(o!==void 0)throw new Error(o);let i=re(t.provider);if(t.line===void 0||i?.capabilities().sharedHistory!==!0)throw new Error(`workspace ${t.label} uses the "${t.provider}" provider, which has no history to merge from \u2014 a sync needs a common base, and a copied directory has none. Land its work with \`/hydra workspace merge\` instead, or start a git-backed workspace if you need to track the source.`);let[a,d]=await Promise.all([i.currentState(t.sourceCwd),i.currentState(t.path)]);if(a===void 0||d===void 0)throw new Error("could not read the state of the source or the workspace");if(await i.contains(t.path,{state:a,within:d}))return{ok:!0,message:`Already up to date with ${$(t.sourceCwd)} (${a.slice(0,8)}).`};let c=await i.divergence(t.path,d,a),u=String(c?.behind??0),l=await i.integrate({into:t.path,from:a,message:`hydra: sync ${t.label} with the source`});if(!l.ok){let f=l.conflicts,h=await i.integrationInProgress(t.path);if(f.length===0&&!h){let m=await this.syncOverDirtyTree(t,{provider:i,before:d,sourceHead:a,incoming:u});if(m!==void 0)return m}let k=f.length>0?`
160
+ `:"")}import{z as K}from"zod";var Sh=K.object({method:K.string(),params:K.unknown(),recordedAt:K.number()}),Ih=K.object({sessionId:K.string(),lineageId:K.string(),upstreamSessionId:K.string().optional(),agentId:K.string(),cwd:K.string(),title:K.string().optional(),synopsis:Tn.optional(),summarizedThroughEntry:K.number().int().nonnegative().optional(),currentModel:K.string().optional(),currentMode:K.string().optional(),currentUsage:To.optional(),agentCommands:K.array(Ro).optional(),agentModes:K.array(xo).optional(),interactive:K.boolean().optional(),originatingClient:Eo.optional(),priority:K.number().int().nonnegative().optional(),createdAt:K.string(),updatedAt:K.string()}),Ah=K.object({version:K.literal(1),exportedAt:K.string(),exportedFrom:K.object({hydraVersion:K.string(),machine:K.string(),hydraHost:K.string().optional()}),session:Ih,history:K.array(Sh),promptHistory:K.array(K.string()).optional(),toolBlobs:K.record(K.string()).optional()});function Nn(s){let e={version:1,exportedAt:new Date().toISOString(),exportedFrom:{hydraVersion:s.hydraVersion,machine:s.machine,...s.hydraHost!==void 0&&s.hydraHost.length>0?{hydraHost:s.hydraHost}:{}},session:{sessionId:s.record.sessionId,lineageId:s.record.lineageId,...s.record.upstreamSessionId?{upstreamSessionId:s.record.upstreamSessionId}:{},agentId:s.record.agentId,cwd:s.record.cwd,...s.record.title!==void 0?{title:s.record.title}:{},...s.record.synopsis!==void 0?{synopsis:s.record.synopsis}:{},...s.record.summarizedThroughEntry!==void 0?{summarizedThroughEntry:s.record.summarizedThroughEntry}:{},...s.record.currentModel!==void 0?{currentModel:s.record.currentModel}:{},...s.record.currentMode!==void 0?{currentMode:s.record.currentMode}:{},...s.record.currentUsage!==void 0?{currentUsage:s.record.currentUsage}:{},...s.record.agentCommands!==void 0?{agentCommands:s.record.agentCommands}:{},...s.record.agentModes!==void 0?{agentModes:s.record.agentModes}:{},...s.record.interactive!==void 0?{interactive:s.record.interactive}:{},...s.record.originatingClient!==void 0?{originatingClient:s.record.originatingClient}:{},...s.record.priority!==void 0&&s.record.priority>0?{priority:s.record.priority}:{},createdAt:s.record.createdAt,updatedAt:s.record.updatedAt},history:s.history};return s.promptHistory!==void 0&&(e.promptHistory=s.promptHistory),s.toolBlobs!==void 0&&Object.keys(s.toolBlobs).length>0&&(e.toolBlobs=s.toolBlobs),e}function xc(s){return Ah.parse(s)}function Jo(s){if(s&&!(s.costAmount===void 0&&s.cumulativeCost===void 0))return(s.cumulativeCost??0)+(s.costAmount??0)}function Dn(s){if(!s)return;let e={};s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size);let t=Jo(s);return t&&(e.costAmount=t),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),e}var Tc=900*1e3,Rh=12,xh="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",xt=Ch(xh,16);function Th(){let s,e,t=!1;return{send(n){if(t)return Promise.resolve();if("method"in n&&"id"in n){let r={jsonrpc:"2.0",id:n.id,error:{code:R.MethodNotFound,message:`no handler for ${n.method} (headless fork-prompt client)`}};queueMicrotask(()=>s?.(r))}return Promise.resolve()},onMessage(n){s=n},onClose(n){e=n},close(){return t||(t=!0,e?.()),Promise.resolve()}}}var Bs=class s{constructor(e,t,n,r={}){this.registry=e;this.spawner=t??(a=>ut.spawn(a)),this.store=n??new As,this.tombstones=r.tombstones??new Fs,this.sessionHistoryMaxEntries=r.sessionHistoryMaxEntries??1e3,this.histories=new Us({maxEntries:this.sessionHistoryMaxEntries,archiveMaxBytes:r.sessionHistoryArchiveMaxBytes,archiveTiers:r.sessionHistoryArchiveTiers}),this.workspaceSnapshotsDisabled=r.disableWorkspaceSnapshots===!0,this.idleTimeoutMs=r.idleTimeoutMs??0,this.backgroundTaskTracking=r.backgroundTaskTracking,this.orphanTimeoutMs=r.orphanTimeoutMs??0,this.idleEventTimeoutMs=r.idleEventTimeoutMs??3e4,this.sessionDefaults=r.sessionDefaults??{},this.synopsisAgent=r.synopsisAgent,this.synopsisModel=r.synopsisModel,this.compactionAgent=r.compactionAgent,this.compactionModel=r.compactionModel,this.defaultTransformers=r.defaultTransformers??[],this.logger=r.logger,this.npmRegistry=r.npmRegistry,this.extensionCommands=r.extensionCommands,this.defaultCwd=r.defaultCwd??"~";let o=r.compaction??{},i=o.tailK??20;this.compactionTailK=i,this.synopsisCoordinator=new js({registry:this.registry,store:this.store,histories:this.histories,synopsisAgent:this.synopsisAgent,synopsisModel:this.synopsisModel,compactionAgent:this.compactionAgent,compactionModel:this.compactionModel,compactionMaxIterations:o.maxIterations,persistTitle:async(a,d)=>{let c=this.get(a);if(c){await c.retitle(d);return}await this.persistTitle(a,d)},persistSynopsis:(a,d,c)=>this.persistSynopsis(a,d,c),logger:this.logger,npmRegistry:this.npmRegistry,onCompactionStateChange:async(a,d,c)=>{if(c.targetAgentId)return;let u=this.get(a);u&&(u.compactionState=d),await this.mutateRecord(a,{compactionState:d})},broadcastHydraCompaction:(a,d,c)=>{this.emitSwapPhase(a,c.targetAgentId,d)},onSynthesisArtifact:async(a,d,c,u,l)=>{await this.dispatchSynthesisSwap(a,d,c,u,l)},onSynthesisUnavailable:async(a,d,c)=>{let u=await this.store.read(a).catch(()=>{});if(u?.synopsis&&u.summarizedThroughEntry!==void 0){this.logger?.info(`agent switch: synthesis produced no new artifact for sessionId=${a} (${c}); swapping to ${d} on the persisted synopsis`),await this.dispatchSynthesisSwap(a,u.synopsis,u.summarizedThroughEntry,d);return}let l=(await this.histories.load(a).catch(()=>[])).length;this.logger?.warn(`agent switch: synthesis unavailable for sessionId=${a} (${c}); swapping to ${d} on verbatim tail`),await this.dispatchSynthesisSwap(a,void 0,l,d)}}),this.refreshAgentCatalog()}registry;sessions=new Map;resurrectionInflight=new Map;snapshotInFlight=new Set;snapshotPending=new Set;workspaceSnapshotsDisabled=!1;driftNoticed=new Map;pendingAuthAgents=new Map;spawner;store;tombstones;histories;idleTimeoutMs;backgroundTaskTracking;orphanTimeoutMs;sessionDefaults;synopsisAgent;synopsisModel;compactionAgent;compactionModel;defaultTransformers;idleEventTimeoutMs;sessionHistoryMaxEntries;metaWriteQueues=new Map;workspaceQueues=new Map;listCache=new Map;static LIST_CACHE_TTL_MS=500;logger;npmRegistry;extensionCommands;defaultCwd;synopsisCoordinator;pendingDeletions=new Map;pendingSwapDisposers=new Map;rollbackLocks=new Set;compactionTailK=20;agentCatalog=[];async dispatchSynthesisSwap(e,t,n,r,o){let i=this.get(e);if(t===void 0&&r===void 0)return;if(!i){if(this.logger?.info(`compaction: persisted artifact for cold session sessionId=${e}`),t===void 0)return;await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:n});return}let a=this.compactionTailK;try{if(await i.isQuiescedForSwap()){this.pendingSwapDisposers.get(e)?.(),this.pendingSwapDisposers.delete(e),await this.performSynthesisSwap(i,t,a,n,r,o);return}this.pendingSwapDisposers.get(e)?.(),this.logger?.info(`compaction: session not quiesced, parking onceIdle swap sessionId=${e}`),this.emitSwapPhase(e,r,{phase:"deferred"});let c=i.onceIdle(()=>{this.pendingSwapDisposers.delete(e),this.onIdleAttemptSwap(e)});this.pendingSwapDisposers.set(e,c)}catch(d){this.logger?.warn(`compaction: dispatch failed for sessionId=${e}: ${d instanceof Error?d.message:String(d)}, leaving session as-is`)}}async onIdleAttemptSwap(e){let t=this.get(e);if(!t)return;let n=this.compactionTailK;try{if(!await t.isQuiescedForSwap()){let d=await this.store.read(e).catch(()=>{});d?.synopsis&&d.summarizedThroughEntry!==void 0?this.dispatchSynthesisSwap(e,d.synopsis,d.summarizedThroughEntry,d.pendingAgentSwap):d?.pendingAgentSwap&&this.dispatchSynthesisSwap(e,void 0,(await this.histories.load(e).catch(()=>[])).length,d.pendingAgentSwap);return}let o=await this.store.read(e).catch(()=>{});if(!o?.synopsis||o.summarizedThroughEntry===void 0){if(o?.pendingAgentSwap){let d=(await this.histories.load(e).catch(()=>[])).length;this.logger?.info(`compaction: no artifact for sessionId=${e}, swapping to ${o.pendingAgentSwap} on verbatim tail`),await this.performSynthesisSwap(t,void 0,n,d,o.pendingAgentSwap);return}this.logger?.warn(`compaction: persisted artifact missing for sessionId=${e}, abandoning swap`),t.compactionState=void 0,await this.mutateRecord(e,{},["compactionState"]);return}let i=o.pendingAgentSwap,a=await this.histories.load(e).catch(()=>[]);if(a.length>o.summarizedThroughEntry){this.logger?.info(`compaction: history grew during deferral (have=${a.length} artifact=${o.summarizedThroughEntry}), rescheduling synopsis sessionId=${e}`),i?this.synopsisCoordinator.scheduleCompaction(e,{targetAgentId:i}):this.synopsisCoordinator.scheduleCompaction(e);return}await this.performSynthesisSwap(t,o.synopsis,n,o.summarizedThroughEntry,i,o.compactionState?.runId)}catch(r){this.logger?.warn(`compaction: onIdleAttemptSwap failed for sessionId=${e}: ${r instanceof Error?r.message:String(r)}`)}}async recordSynopsisFor(e){let t=await this.store.read(e).catch(()=>{});return t?.synopsis?{synopsis:t.synopsis}:{}}async performSynthesisSwap(e,t,n,r,o,i){try{let a=o?Math.min(t===void 0?Rh:5,n):0;await e.swapUpstream({...t!==void 0?{artifact:t}:{},tailK:n,tailFloor:a,summarizedThroughEntry:r,...o?{newAgentId:o}:{},...i!==void 0?{runId:i}:{}}),o?await this.mutateRecord(e.sessionId,{},["pendingAgentSwap"]):(e.compactionState=void 0,await this.mutateRecord(e.sessionId,{},["compactionState"]))}catch(a){this.logger?.warn(`compaction: swap failed for sessionId=${e.sessionId}: ${a instanceof Error?a.message:String(a)}, leaving session as-is`)}finally{this.invalidateListCache()}}async refreshAgentCatalog(){try{let{agents:e}=await Ht(this.registry);this.agentCatalog=e.map(t=>({id:t.id,name:t.name,...t.description!==void 0?{description:t.description}:{}}))}catch{}}async adoptWorkspace(e,t,n){let r=t.label;if(r===void 0)throw new Error("workspace.adopt requires workspace.label");let o=this.liveSessionsWithLabel(n.cwd,r)[0]?.workspace,i=o!==void 0?this.asWorkspace(o):(await e.listWorkspaces(n.cwd).catch(()=>[])).find(a=>a.label===r);if(i===void 0)throw new Error(`cannot adopt workspace "${r}": no workspace by that name derived from ${$(n.cwd)}`);return await this.enqueueKeyed(this.workspaceQueues,i.path,async()=>(e.capabilities().locking&&await e.lock(i,`session ${n.title??"live"}`).catch(()=>{}),{cwd:i.path,workspace:{path:i.path,sourceCwd:i.sourceCwd,label:i.label,provider:i.provider,...i.snapshot!==void 0?{snapshot:i.snapshot}:{},...i.line!==void 0?{line:i.line}:{},...i.vcs!==void 0?{vcs:{...i.vcs}}:{},...o?.clean!==void 0?{clean:o.clean}:{}}}))}async resolveWorkspace(e){let t=e.workspace;if(t===void 0)return{cwd:e.cwd};let n=re(t.provider);if(n===void 0){let u=`unknown workspace provider "${t.provider}"`;if(t.required===!0)throw new Error(`isolation required but unavailable: ${u}`);return this.logger?.warn?.(`session workspace: ${u}; running in ${e.cwd}`),{cwd:e.cwd,isolationError:u}}if(t.adopt===!0)return await this.adoptWorkspace(n,t,e);let r=t.label??`s-${xt().slice(0,8)}`,o=await n.createWorkspace({sourceCwd:e.cwd,label:r,...t.from!==void 0?{from:t.from}:{}}).catch(u=>({ok:!1,reason:String(u)}));if(!o.ok){if(t.required===!0)throw new Error(`isolation required but unavailable: ${o.reason}`);return this.logger?.warn?.(`session workspace: ${o.reason}; falling back to ${e.cwd} (unisolated)`),{cwd:e.cwd,isolationError:o.reason}}let i=o.workspace;n.capabilities().locking&&await n.lock(i,`session ${e.title??"live"}`).catch(()=>{});let a=await $s(i.sourceCwd).catch(()=>({})),d,c=await this.materializeNestedTrees(i);if(c!==void 0&&this.logger?.info?.(`session workspace: ${c} in ${i.path}`),a.carry!==void 0&&a.carry.length>0){let u=await jo(i.sourceCwd,i.path,a.carry).catch(()=>{});u!==void 0&&u.copied.length>0&&this.logger?.info?.(`session workspace: carried ${u.copied.length} file(s) into ${i.path}`)}if(a.postCreate!==void 0){let u=await Os(a.postCreate,{workspacePath:i.path,sourceCwd:i.sourceCwd,label:i.label,...a.hookTimeoutSeconds!==void 0?{timeoutSeconds:a.hookTimeoutSeconds}:{}});u.ok||(d=`postCreate failed: ${u.reason??"unknown"}`,this.logger?.warn?.(`session workspace: ${d} (${i.path})`))}return i.snapshot!==void 0&&await n.retainSnapshot(i,this.startRefFor(i.label),i.snapshot).catch(()=>{}),{cwd:i.path,workspace:{path:i.path,sourceCwd:i.sourceCwd,label:i.label,provider:i.provider,...i.snapshot!==void 0?{snapshot:i.snapshot}:{},...i.line!==void 0?{line:i.line}:{},...i.vcs!==void 0?{vcs:{...i.vcs}}:{},clean:!0},...d!==void 0?{isolationError:d}:{}}}logInfo(e){this.logger?.info(e)}async create(e){let t=e.timer??new Wt,n=await this.registry.getAgent(e.agentId);n&&n.id!==e.agentId&&(e={...e,agentId:n.id}),t.mark("create.canonicalize");let r=`${ye}${xt()}`,o=await this.resolveWorkspace(e),i=o.cwd;t.mark("create.workspace");let a=await this.bootstrapAgent({timer:t,agentId:e.agentId,cwd:i,agentArgs:e.agentArgs,mcpServers:e.mcpServers,model:e.model,configDefaults:e.configDefaults,onInstallProgress:e.onInstallProgress,forwardedEnv:e.forwardedEnv,selfSessionId:r});if(e.transformChain&&e.transformChain.length>0){let c={...a.agentCapabilities??{}};for(let u of e.transformChain)if(u.intercepts.has("agent:initialize"))try{let l=await u.connection.request("hydra-acp/transformer/message",{token:`t_${xt()}`,phase:"response",method:"initialize",direction:"agent\u2192daemon",sessionId:"(pre-session)",envelope:c});l.action==="stop"&&l.payload&&(c=l.payload)}catch{}a.agentCapabilities=c}t.mark("create.transformers");let d=new Qt({sessionId:r,cwd:i,...o.workspace!==void 0?{workspace:o.workspace}:{},...o.isolationError!==void 0?{workspaceError:o.isolationError}:{},agentId:e.agentId,agent:a.agent,upstreamSessionId:a.upstreamSessionId,agentMeta:a.agentMeta,agentCapabilities:a.agentCapabilities,...a.modelVerb?{modelVerb:a.modelVerb}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,...this.backgroundTaskTracking!==void 0?{backgroundTaskTracking:this.backgroundTaskTracking}:{},orphanTimeoutMs:this.orphanTimeoutMs,idleEventTimeoutMs:this.idleEventTimeoutMs,logger:this.logger,spawnReplacementAgent:c=>this.bootstrapAgent({...c,mcpServers:c.mcpServers??[],selfSessionId:r}),loadExistingAgentSession:(c,u)=>this.bootstrapAgentLoad(c,{...u,mcpServers:u.mcpServers??[],selfSessionId:r}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:a.initialModel,currentMode:a.initialMode,agentModes:a.initialModes,agentModels:a.initialModels,agentConfigOptions:a.initialConfigOptions,transformChain:e.transformChain,parentSessionId:e.parentSessionId,originatingClient:e.originatingClient,interactive:e.interactive,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(d.sessionId),scheduleWorkspaceSnapshot:()=>this.scheduleWorkspaceSnapshot(d),scheduleCompaction:c=>this.scheduleCompaction(d.sessionId,c),resolveAgentId:async c=>(await this.registry.getAgent(c))?.id,getCompactionState:()=>this.getCompactionState(d.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(d.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(d.sessionId),uncompactHook:()=>this.performUncompact(d.sessionId),forkHook:c=>this.forkSession(d.sessionId,c??{}),workspaceHook:(c,u,l)=>this.runWorkspaceAction(d.sessionId,c,u,l),onCompactionSwapHook:c=>{this.persistRollbackBreadcrumb(d.sessionId,c).catch(()=>{})},persistWatermarkHook:c=>{this.mutateRecord(d.sessionId,{summarizedThroughEntry:c}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(d.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});if(t.mark("create.session-ctor"),o.workspace!==void 0){let c=re(o.workspace.provider);c!==void 0&&c.capabilities().supports.environmentNotes&&(d.workspaceNotes=await c.environmentNotes({path:o.workspace.path,sourceCwd:o.workspace.sourceCwd,label:o.workspace.label,provider:o.workspace.provider,...o.workspace.snapshot!==void 0?{snapshot:o.workspace.snapshot}:{},...o.workspace.vcs!==void 0?{vcs:o.workspace.vcs}:{}}).catch(()=>[]))}return await this.attachManagerHooks(d),t.mark("create.persist"),d}async resurrect(e){let t=this.sessions.get(e.hydraSessionId);if(t){if(t.upstreamSessionId!==e.upstreamSessionId){let o=new Error(`session ${e.hydraSessionId} already exists with a different upstream id`);throw o.code=R.AlreadyAttached,o}return t}let n=this.resurrectionInflight.get(e.hydraSessionId);if(n)return n;let r=this.doResurrect(e);this.resurrectionInflight.set(e.hydraSessionId,r);try{return await r}finally{this.resurrectionInflight.delete(e.hydraSessionId)}}async doResurrect(e){let t=this.sessions.get(e.hydraSessionId);if(t)return t;let n=await this.registry.getAgent(e.agentId);if(!n){let w=new Error(`agent ${e.agentId} not found in registry; cannot resurrect`);throw w.code=R.AgentNotInstalled,w}if(e.upstreamSessionId==="")return this.doResurrectFromImport(e);if(!await this.dirExists(e.cwd))return this.doResurrectFromImport(e);let r=await _e(n,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),o=ns(e.hydraSessionId,e.forwardedEnv),i=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:r,...o?{extraEnv:o}:{}}),a;try{let w=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:Lt,clientInfo:{name:"hydra",version:ue}});a=w.agentCapabilities,i.authMethods=jn(w.authMethods),i.steeringSupported=Hn(w)}catch(w){throw await i.kill().catch(()=>{}),yt(w,i)}let d;try{let w=Go(n,{model:e.currentModel});d=await i.connection.request("session/load",{sessionId:e.upstreamSessionId,cwd:e.cwd,mcpServers:e.mcpServers??[],...w&&{_meta:w}})}catch(w){if(w&&typeof w=="object"&&w.code===R.AuthRequired)throw await i.kill().catch(()=>{}),yt(w,i);return process.stderr.write(`session/load failed for upstream ${e.upstreamSessionId} on ${e.agentId} (${w.message}); recovering via import-reseed
161
+ `),await i.kill().catch(()=>{}),this.doResurrectFromImport(e)}if(e.pendingHistorySync===!0)this.clearPendingHistorySync(e.hydraSessionId).catch(()=>{});else{let w=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain1 dropped ${w} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let c=Xo(d??{}),u=e.agentModes??ht(Yo(d??{}));this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedMode=${JSON.stringify(e.currentMode)} agentReportedMode=${JSON.stringify(c)} advertisedModes=${JSON.stringify(u?.map(w=>w.id))}`);let l=await ft({agent:i,upstreamSessionId:e.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:c,advertisedModes:u,logger:this.logger});this.logger?.info(`resurrect: effectiveMode=${JSON.stringify(l)} for sessionId=${e.hydraSessionId}`);let p=Ko(d??{}),f=ht(Qo(d??{}))??e.agentModels;if(this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedModel=${JSON.stringify(e.currentModel)} agentReportedModel=${JSON.stringify(p)} advertisedModels=${JSON.stringify(f?.map(w=>w.modelId))}`),e.pendingHistorySync!==!0){let w=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain2 (post-mode-restore) dropped ${w} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let h=Bt(d),k=await pt({agent:i,upstreamSessionId:e.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:p,...h?{modelVerb:h}:{},logger:this.logger}),m=k.modelId,g=ht(nn(tn(k.result)?k.result:d??{}));if(g=ht(await this.restoreConfigOptionValues(i,e.upstreamSessionId,e.configOptionValues,g??[])),e.pendingHistorySync!==!0){let w=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain3 (post-model-restore) dropped ${w} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let y=new Qt({sessionId:e.hydraSessionId,cwd:e.cwd,...e.workspace!==void 0?{workspace:e.workspace}:{},agentId:e.agentId,agent:i,upstreamSessionId:e.upstreamSessionId,agentMeta:d?._meta,agentCapabilities:a,...h?{modelVerb:h}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,...this.backgroundTaskTracking!==void 0?{backgroundTaskTracking:this.backgroundTaskTracking}:{},orphanTimeoutMs:this.orphanTimeoutMs,logger:this.logger,spawnReplacementAgent:w=>this.bootstrapAgent({...w,mcpServers:w.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),loadExistingAgentSession:(w,v)=>this.bootstrapAgentLoad(w,{...v,mcpServers:v.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:m,currentMode:l,currentUsage:e.currentUsage,reloadsUpstreamLedger:!0,agentCommands:e.agentCommands,agentModes:u,agentModels:f,agentConfigOptions:g,summarizedThroughEntry:e.summarizedThroughEntry,compactionState:e.compactionState,firstPromptSeeded:!!e.title,upstreamRespawned:!0,createdAt:e.createdAt?new Date(e.createdAt).getTime():void 0,originatingClient:e.originatingClient,interactive:e.interactive,priority:e.priority,lastTurnEndedAt:e.lastTurnEndedAt,readAt:e.readAt,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,side:e.side,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,attentionFlags:e.attentionFlags,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(y.sessionId),scheduleWorkspaceSnapshot:()=>this.scheduleWorkspaceSnapshot(y),scheduleCompaction:w=>this.scheduleCompaction(y.sessionId,w),resolveAgentId:async w=>(await this.registry.getAgent(w))?.id,getCompactionState:()=>this.getCompactionState(y.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(y.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(y.sessionId),uncompactHook:()=>this.performUncompact(y.sessionId),forkHook:w=>this.forkSession(y.sessionId,w??{}),workspaceHook:(w,v,S)=>this.runWorkspaceAction(y.sessionId,w,v,S),onCompactionSwapHook:w=>{this.persistRollbackBreadcrumb(y.sessionId,w).catch(()=>{})},persistWatermarkHook:w=>{this.mutateRecord(y.sessionId,{summarizedThroughEntry:w}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(y.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(y),y}async doResurrectFromImport(e){let t=await this.resolveResurrectTarget(e.cwd,e.workspace),n=t.cwd,r=await this.bootstrapAgent({agentId:e.agentId,cwd:n,agentArgs:e.agentArgs,mcpServers:e.mcpServers??[],onInstallProgress:e.onInstallProgress,forwardedEnv:e.forwardedEnv,model:e.currentModel}),o=e.agentModes??r.initialModes,i=await ft({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:r.initialMode,advertisedModes:o,logger:this.logger}),a=e.agentModels??r.initialModels,d=await pt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:r.initialModel,...r.modelVerb?{modelVerb:r.modelVerb}:{},logger:this.logger}),c=d.modelId,u=tn(d.result)?ht(nn(d.result)):void 0;u=ht(await this.restoreConfigOptionValues(r.agent,r.upstreamSessionId,e.configOptionValues,u??r.initialConfigOptions??[])),r.agent.connection.drainBuffered("session/update");let l=new Qt({sessionId:e.hydraSessionId,cwd:n,...t.workspace!==void 0?{workspace:t.workspace}:{},agentId:e.agentId,agent:r.agent,upstreamSessionId:r.upstreamSessionId,agentMeta:r.agentMeta,agentCapabilities:r.agentCapabilities,...r.modelVerb?{modelVerb:r.modelVerb}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,...this.backgroundTaskTracking!==void 0?{backgroundTaskTracking:this.backgroundTaskTracking}:{},orphanTimeoutMs:this.orphanTimeoutMs,logger:this.logger,spawnReplacementAgent:p=>this.bootstrapAgent({...p,mcpServers:p.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),loadExistingAgentSession:(p,f)=>this.bootstrapAgentLoad(p,{...f,mcpServers:f.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:c,currentMode:i,currentUsage:e.currentUsage,agentCommands:e.agentCommands,agentModes:o,agentModels:a,agentConfigOptions:u??r.initialConfigOptions,summarizedThroughEntry:e.summarizedThroughEntry,firstPromptSeeded:!!e.title,upstreamRespawned:!0,createdAt:e.createdAt?new Date(e.createdAt).getTime():void 0,originatingClient:e.originatingClient,interactive:e.interactive,priority:e.priority,lastTurnEndedAt:e.lastTurnEndedAt,readAt:e.readAt,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,side:e.side,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,attentionFlags:e.attentionFlags,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(l.sessionId),scheduleWorkspaceSnapshot:()=>this.scheduleWorkspaceSnapshot(l),scheduleCompaction:p=>this.scheduleCompaction(l.sessionId,p),resolveAgentId:async p=>(await this.registry.getAgent(p))?.id,getCompactionState:()=>this.getCompactionState(l.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(l.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(l.sessionId),uncompactHook:()=>this.performUncompact(l.sessionId),forkHook:p=>this.forkSession(l.sessionId,p??{}),workspaceHook:(p,f,h)=>this.runWorkspaceAction(l.sessionId,p,f,h),onCompactionSwapHook:p=>{this.persistRollbackBreadcrumb(l.sessionId,p).catch(()=>{})},persistWatermarkHook:p=>{this.mutateRecord(l.sessionId,{summarizedThroughEntry:p}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(l.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(l),e.forkedFromSessionId&&e.forkSynthesisState==="running"?this.logger?.info(`fork ${l.sessionId}: synthesis in flight \u2014 skipping seed, recall available`):e.forkedFromSessionId&&(e.synopsis||(e.summarizedThroughEntry??0)>0)?l.seedFromFork(e.synopsis).catch(()=>{}):l.seedFromImport().catch(()=>{}),l}async dirExists(e){try{return(await Tt.stat(e)).isDirectory()}catch{return!1}}async reapIfOrphanedNonInteractive(e){let t=this.sessions.get(e);if(!(!t||t.attachedCount>0)&&t.interactive!==!0){if(t.hasWorkInFlight){this.logger?.info(`deferring reap of ${e}: work still in flight after detach`),t.onceIdle(n=>{this.reapIfOrphanedNonInteractive(n.sessionId).catch(()=>{})});return}this.logger?.info(`reaping orphaned non-interactive session ${e} (agent killed, cold record kept)`),await t.close({deleteRecord:!1,by:"reap-orphaned"}).catch(()=>{})}}async resolveResurrectTarget(e,t){if(await this.dirExists(e))return t!==void 0?{cwd:e,workspace:t}:{cwd:e};if(t!==void 0){let n=await this.recoverWorkspace(t);if(n!==void 0)return{cwd:n.path,workspace:n}}return{cwd:ce(this.defaultCwd)}}async releaseWorkspace(e,t){let n=re(e.provider);if(n===void 0){this.logger?.warn?.(`session workspace: no provider "${e.provider}" to release ${e.path}; leaving it in place`);return}return this.enqueueKeyed(this.workspaceQueues,e.path,async()=>{let r=this.liveSessionsIn(e.path,t);if(r.length>0){this.logger?.info?.(`session workspace: keeping ${e.path} \u2014 ${r.length} live session(s) still in it`);return}await this.tearDownWorkspace(n,e,t)})}async syncWorkspaceFromSource(e,t,n){let r=this.liveSessionsIn(t.path,e.sessionId);if(r.length>0)throw new Error(`${$(t.path)} is shared with ${r.map(f=>nt(f.sessionId)).join(", ")}, and a sync would move files under them. Sync it from a session that has it to itself.`);let o=await e.quiesceBlocker();if(o!==void 0)throw new Error(o);let i=re(t.provider);if(t.line===void 0||i?.capabilities().sharedHistory!==!0)throw new Error(`workspace ${t.label} uses the "${t.provider}" provider, which has no history to merge from \u2014 a sync needs a common base, and a copied directory has none. Land its work with \`/hydra workspace merge\` instead, or start a git-backed workspace if you need to track the source.`);let[a,d]=await Promise.all([i.currentState(t.sourceCwd),i.currentState(t.path)]);if(a===void 0||d===void 0)throw new Error("could not read the state of the source or the workspace");if(await i.contains(t.path,{state:a,within:d}))return{ok:!0,message:`Already up to date with ${$(t.sourceCwd)} (${a.slice(0,8)}).`};let c=await i.divergence(t.path,d,a),u=String(c?.behind??0),l=await i.integrate({into:t.path,from:a,message:`hydra: sync ${t.label} with the source`});if(!l.ok){let f=l.conflicts,h=await i.integrationInProgress(t.path);if(f.length===0&&!h){let m=await this.syncOverDirtyTree(t,{provider:i,before:d,sourceHead:a,incoming:u});if(m!==void 0)return m}let k=f.length>0?`
162
162
  ${f.map(m=>` ${m}`).join(`
163
163
  `)}`:` (${l.reason??"the integration failed"})`;return f.length===0?{ok:!1,message:`the source could not be merged into ${$(t.path)}; nothing changed.${k}
164
164
  `+(h?"A merge is already in progress there. Finish it \u2014 resolve, commit \u2014 then `/hydra workspace sync` again.":"Clear that in the workspace, then `/hydra workspace sync` again.")}:n.onConflict==="abort"?(await i.abortIntegration(t.path).catch(()=>{}),{ok:!1,message:`${f.length} file(s) conflict between the source and this workspace:${k}`}):{ok:!1,message:`Synced with conflicts. ${f.length} file(s) need resolving in ${$(t.path)}:${k}
165
- The merge is left in progress deliberately: fix the markers, commit, then \`/hydra workspace stop\`. To back it out instead: git -C ${t.path} merge --abort`}}let p=(await i.changedPathsBetween(t.path,d,l.snapshot)).length;return{ok:!0,message:`Synced ${$(t.path)} with ${$(t.sourceCwd)}: ${u} commit(s), ${p} file(s) changed. Your uncommitted work is untouched.`}}async syncOverDirtyTree(e,t){let{provider:n,before:r,sourceHead:o,incoming:i}=t;if(n?.capabilities().supports.captureWorkingState!==!0)return;let a=this.asWorkspace(e),d=await n.status(a).catch(()=>{});if(d===void 0||d.changedPaths.length===0)return;let c=await n.captureWorkingState(e.path,`hydra: work set aside to sync ${e.label}`).catch(()=>{});if(c===void 0)return;let u=Xd(e.label);if(await n.retainSnapshot(a,u,c).then(()=>n.resolveRetained(a,u)).catch(()=>{})===void 0)return;let p={clean:!1,snapshot:c,base:r},f=`git -C ${e.path} cherry-pick --no-commit ${u} # the snapshot's parent is ${r.slice(0,8)}, so this replays exactly your work`;if(!(await n.resetTo(e.path,r)).ok){let v=await Ct({source:e.path,capture:p,provider:n});return{ok:!1,message:`Could not clear ${$(e.path)} to merge into it, so nothing was synced. ${v?"Your uncommitted work is back in place.":`Your uncommitted work is at ${u}: ${f}`}`}}if(!(await n.integrate({into:e.path,from:o,message:`hydra: sync ${e.label} with the source`})).ok){await n.abortIntegration(e.path).catch(()=>{});let v=await Ct({source:e.path,capture:p,provider:n});return v&&await n.dropSnapshotRef(a,u).catch(()=>{}),{ok:!1,message:`The source's commits and this workspace's commits genuinely conflict, and that has to be resolved with a merge left in progress \u2014 which cannot happen while there is uncommitted work here, since the work has to be set aside for the merge to run at all.
165
+ The merge is left in progress deliberately: fix the markers, commit, then \`/hydra workspace stop\`. To back it out instead: git -C ${t.path} merge --abort`}}let p=(await i.changedPathsBetween(t.path,d,l.snapshot)).length;return{ok:!0,message:`Synced ${$(t.path)} with ${$(t.sourceCwd)}: ${u} commit(s), ${p} file(s) changed. Your uncommitted work is untouched.`}}async syncOverDirtyTree(e,t){let{provider:n,before:r,sourceHead:o,incoming:i}=t;if(n?.capabilities().supports.captureWorkingState!==!0)return;let a=this.asWorkspace(e),d=await n.status(a).catch(()=>{});if(d===void 0||d.changedPaths.length===0)return;let c=await n.captureWorkingState(e.path,`hydra: work set aside to sync ${e.label}`).catch(()=>{});if(c===void 0)return;let u=ec(e.label);if(await n.retainSnapshot(a,u,c).then(()=>n.resolveRetained(a,u)).catch(()=>{})===void 0)return;let p={clean:!1,snapshot:c,base:r},f=`git -C ${e.path} cherry-pick --no-commit ${u} # the snapshot's parent is ${r.slice(0,8)}, so this replays exactly your work`;if(!(await n.resetTo(e.path,r)).ok){let v=await Rt({source:e.path,capture:p,provider:n});return{ok:!1,message:`Could not clear ${$(e.path)} to merge into it, so nothing was synced. ${v?"Your uncommitted work is back in place.":`Your uncommitted work is at ${u}: ${f}`}`}}if(!(await n.integrate({into:e.path,from:o,message:`hydra: sync ${e.label} with the source`})).ok){await n.abortIntegration(e.path).catch(()=>{});let v=await Rt({source:e.path,capture:p,provider:n});return v&&await n.dropSnapshotRef(a,u).catch(()=>{}),{ok:!1,message:`The source's commits and this workspace's commits genuinely conflict, and that has to be resolved with a merge left in progress \u2014 which cannot happen while there is uncommitted work here, since the work has to be set aside for the merge to run at all.
166
166
  `+(v?`Your uncommitted work is back in place (unstaged) and nothing else changed. Commit it in ${$(e.path)}, then \`/hydra workspace sync\` again to resolve the conflict there.`:`Your uncommitted work could not be put back and is preserved at ${u}. Recover it with:
167
- ${f}`)}}let m=await Ct({source:e.path,capture:p,provider:n}),g=await n.currentState(e.path),y=g===void 0?0:(await n.changedPathsBetween(e.path,r,g)).length,w=`Synced ${$(e.path)} with ${$(e.sourceCwd)}: ${i} commit(s), ${y} file(s) changed.`;return m?(await n.dropSnapshotRef(a,u).catch(()=>{}),{ok:!0,message:`${w} Your uncommitted work was set aside for the merge and restored on top.`}):{ok:!1,message:`${w}
167
+ ${f}`)}}let m=await Rt({source:e.path,capture:p,provider:n}),g=await n.currentState(e.path),y=g===void 0?0:(await n.changedPathsBetween(e.path,r,g)).length,w=`Synced ${$(e.path)} with ${$(e.sourceCwd)}: ${i} commit(s), ${y} file(s) changed.`;return m?(await n.dropSnapshotRef(a,u).catch(()=>{}),{ok:!0,message:`${w} Your uncommitted work was set aside for the merge and restored on top.`}):{ok:!1,message:`${w}
168
168
  Your uncommitted work touches the same lines as the commits that just arrived, so replaying it left conflict markers where they collide. The whole set is preserved at ${u} if you would rather start over:
169
- ${f}`}}async fastForwardBlocked(e){let n=this.asWorkspace(e).line;if(n===void 0)return"the workspace has no line of work to land from";let r=re(e.provider);if(r===void 0)return;let o=await r.currentState(e.sourceCwd);if(o===void 0||await r.contains(e.sourceCwd,{state:o,within:n}))return;let i=await r.currentLineName(e.sourceCwd);return`${$(e.sourceCwd)} has moved on since this workspace was created (it is on ${i??"an unknown branch"}). \`/hydra workspace sync\` brings those commits in here and makes the landing possible again, or land it by hand with: git -C ${e.sourceCwd} merge ${n}`}async tearDownWorkspace(e,t,n){let r={path:t.path,sourceCwd:t.sourceCwd,label:t.label,provider:t.provider,...t.snapshot!==void 0?{snapshot:t.snapshot}:{},...t.vcs!==void 0?{vcs:t.vcs}:{}},o=await Ms(t.sourceCwd).catch(()=>({}));if(o.preRemove!==void 0){let a=await _s(o.preRemove,{workspacePath:t.path,sourceCwd:t.sourceCwd,label:t.label,...n!==void 0?{sessionId:n}:{},...o.hookTimeoutSeconds!==void 0?{timeoutSeconds:o.hookTimeoutSeconds}:{}});a.ok||this.logger?.warn?.(`session workspace: preRemove failed for ${t.path}: ${a.reason??"unknown"}`)}let i=await e.status(r).catch(()=>({clean:!1,changedPaths:["<unknown>"],hasRecordedWork:!1}));if(i.changedPaths.length>0){await e.dropSnapshotRef(r,Zt(t.label).autosave).catch(()=>{}),this.logger?.warn?.(`session workspace: keeping ${t.path} \u2014 it has ${i.changedPaths.length} uncommitted change(s) that removal would destroy. Remove it by hand once you have salvaged or discarded them.`);return}for(let a of ec(t.label))await e.dropSnapshotRef(r,a).catch(()=>{});await e.removeWorkspace(r,{force:!0}).catch(a=>this.logger?.warn?.(`session workspace: could not remove ${t.path}: ${String(a)}`))}snapshotRefFor(e){return Zt(e).autosave}startRefFor(e){return Zt(e).start}baselineRefFor(e){return Zt(e).baseline}scheduleWorkspaceSnapshot(e){if(e.workspace===void 0){this.driftNoticed.delete(e.sessionId);return}if(this.snapshotInFlight.has(e.sessionId)){this.snapshotPending.add(e.sessionId);return}this.snapshotInFlight.add(e.sessionId),this.runWorkspaceSnapshot(e).catch(()=>{}).finally(()=>{this.snapshotInFlight.delete(e.sessionId),this.snapshotPending.delete(e.sessionId)&&this.scheduleWorkspaceSnapshot(e)})}async runWorkspaceSnapshot(e){let t=e.workspace;if(t===void 0)return;let n=re(t.provider);if(n===void 0||!n.capabilities().supports.captureWorkingState)return;let r={path:t.path,sourceCwd:t.sourceCwd,label:t.label,provider:t.provider,...t.snapshot!==void 0?{snapshot:t.snapshot}:{},...t.vcs!==void 0?{vcs:t.vcs}:{}};if(await this.noticeSourceDrift(e,t).catch(()=>{}),this.workspaceSnapshotsDisabled)return;let o=await n.status(r).catch(()=>{});if(o!==void 0&&o.changedPaths.length===0)return;let i=await n.captureWorkingState(t.path,`hydra: autosave ${e.sessionId}`);await n.retainSnapshot(r,this.snapshotRefFor(t.label),i)}async noticeSourceDrift(e,t){if(this.asWorkspace(t).line===void 0)return;let r=re(t.provider);if(r===void 0||!r.capabilities().sharedHistory)return;let o=await r.currentState(t.sourceCwd);if(o===void 0||this.driftNoticed.get(e.sessionId)===o)return;let i=await r.currentState(t.path);if(i===void 0)return;if(await r.contains(t.path,{state:o,within:i})){this.driftNoticed.delete(e.sessionId);return}let d=(await r.divergence(t.path,i,o))?.behind??0;d<=0||(this.driftNoticed.set(e.sessionId,o),e.broadcastWorkspacePhase({phase:"drift",label:t.label,sourceCwd:t.sourceCwd,behind:d}),e.broadcastSyntheticText(`
169
+ ${f}`}}async fastForwardBlocked(e){let n=this.asWorkspace(e).line;if(n===void 0)return"the workspace has no line of work to land from";let r=re(e.provider);if(r===void 0)return;let o=await r.currentState(e.sourceCwd);if(o===void 0||await r.contains(e.sourceCwd,{state:o,within:n}))return;let i=await r.currentLineName(e.sourceCwd);return`${$(e.sourceCwd)} has moved on since this workspace was created (it is on ${i??"an unknown branch"}). \`/hydra workspace sync\` brings those commits in here and makes the landing possible again, or land it by hand with: git -C ${e.sourceCwd} merge ${n}`}async tearDownWorkspace(e,t,n){let r={path:t.path,sourceCwd:t.sourceCwd,label:t.label,provider:t.provider,...t.snapshot!==void 0?{snapshot:t.snapshot}:{},...t.vcs!==void 0?{vcs:t.vcs}:{}},o=await $s(t.sourceCwd).catch(()=>({}));if(o.preRemove!==void 0){let a=await Os(o.preRemove,{workspacePath:t.path,sourceCwd:t.sourceCwd,label:t.label,...n!==void 0?{sessionId:n}:{},...o.hookTimeoutSeconds!==void 0?{timeoutSeconds:o.hookTimeoutSeconds}:{}});a.ok||this.logger?.warn?.(`session workspace: preRemove failed for ${t.path}: ${a.reason??"unknown"}`)}let i=await e.status(r).catch(()=>({clean:!1,changedPaths:["<unknown>"],hasRecordedWork:!1}));if(i.changedPaths.length>0){await e.dropSnapshotRef(r,en(t.label).autosave).catch(()=>{}),this.logger?.warn?.(`session workspace: keeping ${t.path} \u2014 it has ${i.changedPaths.length} uncommitted change(s) that removal would destroy. Remove it by hand once you have salvaged or discarded them.`);return}for(let a of nc(t.label))await e.dropSnapshotRef(r,a).catch(()=>{});await e.removeWorkspace(r,{force:!0}).catch(a=>this.logger?.warn?.(`session workspace: could not remove ${t.path}: ${String(a)}`))}snapshotRefFor(e){return en(e).autosave}startRefFor(e){return en(e).start}baselineRefFor(e){return en(e).baseline}scheduleWorkspaceSnapshot(e){if(e.workspace===void 0){this.driftNoticed.delete(e.sessionId);return}if(this.snapshotInFlight.has(e.sessionId)){this.snapshotPending.add(e.sessionId);return}this.snapshotInFlight.add(e.sessionId),this.runWorkspaceSnapshot(e).catch(()=>{}).finally(()=>{this.snapshotInFlight.delete(e.sessionId),this.snapshotPending.delete(e.sessionId)&&this.scheduleWorkspaceSnapshot(e)})}async runWorkspaceSnapshot(e){let t=e.workspace;if(t===void 0)return;let n=re(t.provider);if(n===void 0||!n.capabilities().supports.captureWorkingState)return;let r={path:t.path,sourceCwd:t.sourceCwd,label:t.label,provider:t.provider,...t.snapshot!==void 0?{snapshot:t.snapshot}:{},...t.vcs!==void 0?{vcs:t.vcs}:{}};if(await this.noticeSourceDrift(e,t).catch(()=>{}),this.workspaceSnapshotsDisabled)return;let o=await n.status(r).catch(()=>{});if(o!==void 0&&o.changedPaths.length===0)return;let i=await n.captureWorkingState(t.path,`hydra: autosave ${e.sessionId}`);await n.retainSnapshot(r,this.snapshotRefFor(t.label),i)}async noticeSourceDrift(e,t){if(this.asWorkspace(t).line===void 0)return;let r=re(t.provider);if(r===void 0||!r.capabilities().sharedHistory)return;let o=await r.currentState(t.sourceCwd);if(o===void 0||this.driftNoticed.get(e.sessionId)===o)return;let i=await r.currentState(t.path);if(i===void 0)return;if(await r.contains(t.path,{state:o,within:i})){this.driftNoticed.delete(e.sessionId);return}let d=(await r.divergence(t.path,i,o))?.behind??0;d<=0||(this.driftNoticed.set(e.sessionId,o),e.broadcastWorkspacePhase({phase:"drift",label:t.label,sourceCwd:t.sourceCwd,behind:d}),e.broadcastSyntheticText(`
170
170
  ${$(t.sourceCwd)} has moved on: ${d} commit(s) are there and not in this workspace. Landing is fast-forward-only, so \`/hydra workspace sync\` now is what keeps \`stop\` from refusing later.
171
171
  `))}async runWorkspaceAction(e,t,n,r){let o=this.get(e);if(o===void 0)throw new Error("session is not live");if(t==="status"){let a=o.workspace;if(a===void 0)return`Not isolated. Working directly in ${$(o.cwd)}.
172
- Use \`/hydra workspace start\` to move into an isolated workspace.`;let d=this.liveSessionsIn(a.path,o.sessionId).map(f=>tt(f.sessionId)),c=a.line,u=[`Isolated in ${$(a.path)}`,` source: ${$(a.sourceCwd)}`,` provider: ${a.provider}${c!==void 0?` (${c})`:""}`];d.length>0&&u.push(` shared with: ${d.join(", ")}`);let p=await re(a.provider)?.statusReport({path:a.path,sourceCwd:a.sourceCwd,label:a.label,provider:a.provider,...a.snapshot!==void 0?{snapshot:a.snapshot}:{},...a.vcs!==void 0?{vcs:a.vcs}:{}}).catch(()=>{});for(let f of p??[])u.push(` ${f}`);return u.push(d.length>0?`\`stop\` behaves as \`detach\` while ${d.length===1?"that session is":"those sessions are"} still here; the work lands when the last one leaves.`:"Use `/hydra workspace stop` to merge and return, `discard` to throw the work away, `detach` to return and leave it here, or `clean` to wipe it and keep working here."),u.join(`
172
+ Use \`/hydra workspace start\` to move into an isolated workspace.`;let d=this.liveSessionsIn(a.path,o.sessionId).map(f=>nt(f.sessionId)),c=a.line,u=[`Isolated in ${$(a.path)}`,` source: ${$(a.sourceCwd)}`,` provider: ${a.provider}${c!==void 0?` (${c})`:""}`];d.length>0&&u.push(` shared with: ${d.join(", ")}`);let p=await re(a.provider)?.statusReport({path:a.path,sourceCwd:a.sourceCwd,label:a.label,provider:a.provider,...a.snapshot!==void 0?{snapshot:a.snapshot}:{},...a.vcs!==void 0?{vcs:a.vcs}:{}}).catch(()=>{});for(let f of p??[])u.push(` ${f}`);return u.push(d.length>0?`\`stop\` behaves as \`detach\` while ${d.length===1?"that session is":"those sessions are"} still here; the work lands when the last one leaves.`:"Use `/hydra workspace stop` to merge and return, `discard` to throw the work away, `detach` to return and leave it here, or `clean` to wipe it and keep working here."),u.join(`
173
173
  `)}if(t==="start")return this.startWorkspace(o,n,{clean:r?.clean===!0});let i=o.workspace;if(i===void 0)throw new Error("this session is not in a workspace. Use `/hydra workspace start` first.");if(t==="sync")return(await this.syncWorkspaceFromSource(o,i,{onConflict:"keep"})).message;if(t==="clean")return await this.cleanWorkspace(o,i,{deep:r?.deep===!0});if(t==="merge"){o.broadcastWorkspacePhase({phase:"landing"});let a;try{a=await this.mergeWorkspaceIntoSource(i,o.sessionId)}catch(d){let c=d instanceof Error?d.message:String(d);throw o.broadcastWorkspacePhase({phase:"failed",error:c}),d}return o.broadcastWorkspacePhase({phase:"entered",cwd:o.cwd,sourceCwd:i.sourceCwd,label:i.label}),[`${a.merged}; still working in ${$(i.path)}.`,...a.warnings].join(`
174
174
  `)}if(t==="apply"){o.broadcastWorkspacePhase({phase:"applying"});let a;try{a=await this.applyWorkspaceToSource(i,o.sessionId)}catch(d){let c=d instanceof Error?d.message:String(d);throw o.broadcastWorkspacePhase({phase:"failed",error:c}),d}return o.broadcastWorkspacePhase({phase:"entered",cwd:o.cwd,sourceCwd:i.sourceCwd,label:i.label}),[a.applied,...a.warnings].join(`
175
- `)}if(t==="stop"){let a=this.liveSessionsIn(i.path,o.sessionId);if(a.length>0){o.broadcastWorkspacePhase({phase:"returning"}),await this.leaveWorkspace(o,i,{exit:"detached"});let c=a.map(p=>tt(p.sessionId)).join(", "),u=[`Left ${$(i.path)} and returned to ${$(i.sourceCwd)}.`,`Nothing landed yet: ${c} still working there. It lands when the last session leaves.`],l=await this.fastForwardBlocked(i);return l!==void 0&&u.push(`WARNING: that merge will not fast-forward as things stand \u2014 ${l}`),u.join(`
175
+ `)}if(t==="stop"){let a=this.liveSessionsIn(i.path,o.sessionId);if(a.length>0){o.broadcastWorkspacePhase({phase:"returning"}),await this.leaveWorkspace(o,i,{exit:"detached"});let c=a.map(p=>nt(p.sessionId)).join(", "),u=[`Left ${$(i.path)} and returned to ${$(i.sourceCwd)}.`,`Nothing landed yet: ${c} still working there. It lands when the last session leaves.`],l=await this.fastForwardBlocked(i);return l!==void 0&&u.push(`WARNING: that merge will not fast-forward as things stand \u2014 ${l}`),u.join(`
176
176
  `)}o.broadcastWorkspacePhase({phase:"landing"});let d;try{d=await this.mergeWorkspaceIntoSource(i,o.sessionId)}catch(c){let u=c instanceof Error?c.message:String(c);throw o.broadcastWorkspacePhase({phase:"failed",error:u}),c}o.broadcastWorkspacePhase({phase:"returning"});try{await this.leaveWorkspace(o,i,{exit:"landed"})}catch(c){let u=c instanceof Error?c.message:String(c);throw new Error(`${d.merged}, but the session could not leave the workspace: ${u}`)}return[`${d.merged} and returned there; workspace removed.`,...d.warnings].join(`
177
- `)}if(t==="discard"){let a=this.liveSessionsIn(i.path,o.sessionId);if(a.length>0)throw new Error(`${$(i.path)} is shared with ${a.map(u=>tt(u.sessionId)).join(", ")}, so its work is not yours alone to discard. Use \`/hydra workspace detach\` to leave it to them.`);o.broadcastWorkspacePhase({phase:"returning"}),await this.leaveWorkspace(o,i,{exit:"discarded"});let d=await this.retireAutosave(i),c=[`Discarded ${$(i.path)} and its branch ${i.line??"(none)"}; returned to ${$(i.sourceCwd)}.`];return d!==void 0&&c.push(`The last autosave is kept at ${d} if you want it back: git -C ${i.sourceCwd} checkout ${d}`),c.join(`
177
+ `)}if(t==="discard"){let a=this.liveSessionsIn(i.path,o.sessionId);if(a.length>0)throw new Error(`${$(i.path)} is shared with ${a.map(u=>nt(u.sessionId)).join(", ")}, so its work is not yours alone to discard. Use \`/hydra workspace detach\` to leave it to them.`);o.broadcastWorkspacePhase({phase:"returning"}),await this.leaveWorkspace(o,i,{exit:"discarded"});let d=await this.retireAutosave(i),c=[`Discarded ${$(i.path)} and its branch ${i.line??"(none)"}; returned to ${$(i.sourceCwd)}.`];return d!==void 0&&c.push(`The last autosave is kept at ${d} if you want it back: git -C ${i.sourceCwd} checkout ${d}`),c.join(`
178
178
  `)}return o.broadcastWorkspacePhase({phase:"returning"}),await this.leaveWorkspace(o,i,{exit:"detached"}),[`Returned to ${$(i.sourceCwd)} WITHOUT merging.`,`The workspace is still at ${$(i.path)} and its branch ${i.line??"(none)"} is intact, so nothing is lost. Land it later with \`hydra workspace merge\`, or drop it with \`/hydra workspace discard\`.`].join(`
179
- `)}asWorkspace(e){return{path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:e.provider,...e.snapshot!==void 0?{snapshot:e.snapshot}:{},...e.line!==void 0?{line:e.line}:{},...e.vcs!==void 0?{vcs:e.vcs}:{}}}async retireAutosave(e){let t=re(e.provider);if(t===void 0)return;let n=this.asWorkspace(e),r=this.snapshotRefFor(e.label),o=await t.resolveRetained(n,r).catch(()=>{});if(o===void 0)return;let i=Zd(e.label,o);return await t.retainSnapshot(n,i,o).then(()=>!0).catch(()=>!1)?(await t.dropSnapshotRef(n,r).catch(()=>{}),i):r}async cleanWorkspace(e,t,n){return await this.enqueueKeyed(this.workspaceQueues,t.path,async()=>{let r=this.liveSessionsIn(t.path,e.sessionId);if(r.length>0)throw new Error(`${$(t.path)} is shared with ${r.map(w=>tt(w.sessionId)).join(", ")}, and a clean would destroy their work too. Clean it from a session that has it to itself.`);let o=await e.quiesceBlocker();if(o!==void 0)throw new Error(o);let i=re(t.provider);if(i===void 0)throw new Error(`no provider "${t.provider}" available to clean this workspace`);if(t.snapshot===void 0||i.capabilities().sharedHistory!==!0)throw new Error(`workspace ${t.label} uses the "${t.provider}" provider, which records no base state to return to, so there is nothing to clean back to. Use \`/hydra workspace discard\` to throw it away instead.`);let a=this.asWorkspace(t),d=t.snapshot,u=(await i.status(a).catch(()=>{}))?.changedPaths.length??0,p=(await i.divergence(t.path,d,"HEAD").catch(()=>{}))?.behind??0,f=await i.currentState(t.path)??"",h=await this.retireAutosave(t);e.broadcastWorkspacePhase({phase:"cleaning",label:t.label});let k=await i.resetTo(t.path,d,{purgeIgnored:n.deep});if(!k.ok)throw new Error(`could not return ${$(t.path)} to its base: ${k.reason??"unknown error"}. Nothing was changed.`);let m=n.deep?await this.applyWorkspaceSetup(t,e.sessionId):void 0;await i.retainSnapshot(a,this.startRefFor(t.label),t.snapshot).catch(()=>{});let g={...t,clean:!0};e.workspace=g,await this.mutateRecord(e.sessionId,{workspace:g}),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:t.sourceCwd,label:t.label,...a.line!==void 0?{branch:a.line}:{}});let y=[`Cleaned ${$(t.path)} back to the state it was created in.`];if(u>0||p>0){let w=[];u>0&&w.push(`${u} uncommitted change(s)`),p>0&&w.push(`${p} commit(s)`),y.push(` discarded ${w.join(" and ")}`)}else y.push(" nothing to discard; it was already at its base");return m!==void 0&&y.push(` ${m}`),h!==void 0&&y.push(` last autosave kept at ${h}: git -C ${t.sourceCwd} checkout ${h}`),p>0&&f.length>0&&y.push(` discarded commits are still at ${f.slice(0,12)} (and in the reflog for ${t.line??"this branch"})`),y.push(`Your uncommitted work in ${$(t.sourceCwd)} was never touched by this.`),y.join(`
180
- `)})}async mergeWorkspaceIntoSource(e,t){let n=e.sourceCwd,r=e.line;if(r===void 0)throw new Error(`workspace ${e.label} has no line of work to land from`);if(!await this.dirExists(n))throw new Error(`source tree ${$(n)} no longer exists`);let i=re(e.provider),a=this.asWorkspace(e),d=await No({source:n,ws:a,startSnapshotRef:this.startRefFor(e.label),baselineRef:this.baselineRefFor(e.label),retainRef:Fo(t),provider:i});if(i===void 0)throw new Error(`no provider "${e.provider}" available to land this workspace`);let c=await i.currentState(n);if(c===void 0)throw new Error(`could not read the state of ${$(n)}`);let u=await i.contains(n,{state:c,within:r}),l=[];if(!u){let b=this.get(t),I="";if(b!==void 0)try{let C=await this.syncWorkspaceFromSource(b,e,{onConflict:"abort"});C.ok?(l.push(`
181
- synced with the source first: ${C.message}`),u=await i.contains(n,{state:c,within:r})):I=`
182
- A sync was attempted first and could not complete: ${C.message}`}catch(C){I=`
183
- A sync was attempted first but was refused: ${C instanceof Error?C.message:String(C)}`}if(!u){let C=await i.currentLineName(n)??"the source";throw new Error(`cannot fast-forward ${C} in ${$(n)} to ${r}. The source has moved on since this workspace was created. The source is untouched.${I}
184
- `+(I.length>0?`Or land it by hand with: git -C ${n} merge ${r}`:`Resolve it in the workspace with \`/hydra workspace sync\` (which leaves the conflict there to fix), or land it by hand with: git -C ${n} merge ${r}`))}}let p=i!==void 0&&i.capabilities().supports.nestedTrees?await i.captureNested(e.path,await i.listNested(e.path)).catch(()=>[]):[],f,h=await i.status(a).catch(()=>{});if(h!==void 0&&h.changedPaths.length>0&&(f=await i.captureWorkingState(e.path,`hydra: uncommitted work in ${e.label}`).catch(()=>{}),f===void 0))throw new Error(`could not capture the uncommitted work in ${$(e.path)}; nothing was changed`);if(!d.clean&&!(await i.resetTo(n,c)).ok)throw new Error(`could not clear ${$(n)} for the merge; your work is preserved at ${d.retainedRef}. Nothing was merged.`);let k=await i.integrate({into:n,from:r,fastForwardOnly:!0});if(!k.ok)throw new Error(`merge failed: ${k.reason??"unknown error"}`);let m=!0;if(f!==void 0){let b=await i.captureDelta(n,k.snapshot,f);b!==void 0&&(m=(await i.applyDelta(n,b)).ok)}let g=await Ct({source:n,capture:d,provider:i});g&&await Mn({source:n,ws:a,capture:d,provider:i});let y={applied:[],failed:[]},w=i!==void 0&&i.capabilities().supports.nestedTrees?await i.integrateNested(n,e.path,p).catch(()=>y):y,v=await i.captureWorkingState(n,`hydra: source state after landing ${e.label}`).catch(()=>{});v!==void 0&&await i.retainSnapshot({...a,path:n},this.baselineRefFor(e.label),v).catch(()=>{});let S=[];m||S.push(` WARNING: the workspace's uncommitted changes could not be replayed; they remain reachable from ${r}.`),g||S.push(e.clean===!0?` WARNING: this workspace started clean, so your uncommitted work was never copied in. The whole of it is being replayed now and it overlaps what the agent changed. All of it is preserved at ${d.retainedRef}; recover with: git -C ${n} diff ${d.base} ${d.retainedRef}`:` WARNING: your own edits to ${$(n)} overlap the workspace's changes and could not be replayed on top. They are preserved at ${d.retainedRef}; recover with: git -C ${n} diff ${d.base} ${d.retainedRef}`);for(let b of w.failed)S.push(` WARNING: nested tree ${b.path} was NOT reconciled: ${b.reason}. ${$(n)} now records a different state for it, so it will report it as modified until you resolve that.`);return{merged:`Merged ${r} into ${$(n)}${l.join("")}`,warnings:S}}async applyWorkspaceToSource(e,t){let n=e.sourceCwd;if(!await this.dirExists(n))throw new Error(`source tree ${$(n)} no longer exists`);let r=re(e.provider);if(r===void 0)throw new Error(`no provider "${e.provider}" available to apply this workspace`);if(!r.capabilities().supports.captureWorkingState)throw new Error(`provider "${e.provider}" cannot snapshot a working tree, so there is no change set to apply. Use \`/hydra workspace stop\` to land this workspace instead.`);let o=this.asWorkspace(e);if((await r.status({...o,path:n}).catch(()=>{}))?.hasStagedWork===!0)throw new Error(`${$(n)} already has changes staged for its next commit, and \`apply\` delivers into that same index: the two sets would be indistinguishable, and unstaging one would unstage both. Commit or unstage them first, or use \`/hydra workspace merge\`, which lands the work as commits and does not touch the index.`);let a=await r.currentState(n);if(a===void 0)throw new Error(`could not read the state of ${$(n)}`);let d=e.line,c=d!==void 0&&await r.contains(n,{state:a,within:d}).catch(()=>!1),u=c?a:e.snapshot??"";if(u.length===0)throw new Error(`workspace ${e.label} has no recorded base to measure its changes against, so there is no way to tell its work apart from what the source already had`);let l=await No({source:n,ws:o,startSnapshotRef:this.startRefFor(e.label),baselineRef:this.baselineRefFor(e.label),retainRef:Fo(t),provider:r}),p=r.capabilities().supports.nestedTrees?(await r.listNested(e.path).catch(()=>[])).filter(w=>w.changedPaths.length>0||w.recorded!==void 0&&w.recorded!==w.actual):[],f=await r.captureWorkingState(e.path,`hydra: apply from ${e.label}`).catch(()=>{});if(f===void 0)throw new Error(`could not snapshot the work in ${$(e.path)}; nothing was changed`);let h=await r.captureDelta(n,u,f);if(h===void 0)throw new Error(`could not work out what ${e.label} changed; ${$(n)} was not touched`);if(h.trim().length===0)return await Mn({source:n,ws:o,capture:l,provider:r}),{applied:`Nothing to apply: ${e.label} holds no changes ${$(n)} does not already have.`,warnings:[]};if(!l.clean&&!(await r.resetTo(n,a)).ok)throw new Error(`could not clear ${$(n)} to apply onto; your work is preserved at ${l.retainedRef}. Nothing was applied.`);let k=await r.applyDelta(n,h,{stage:!0,tolerant:!c});if(!k.ok){await r.resetTo(n,a).catch(()=>{});let w=await Ct({source:n,capture:l,provider:r});throw w&&await Mn({source:n,ws:o,capture:l,provider:r}),new Error(`could not apply ${e.label} into ${$(n)}: ${k.reason??"the change set did not apply"}.`+(c?"":" The source has moved on since this workspace was created; `/hydra workspace sync` brings those commits in here, which is what lets the change set apply against them.")+(w?` ${$(n)} is as you left it.`:` Your uncommitted work there is preserved at ${l.retainedRef}.`))}let m=await Ct({source:n,capture:l,provider:r});m&&await Mn({source:n,ws:o,capture:l,provider:r});let g=await r.captureWorkingState(n,`hydra: source state after applying ${e.label}`).catch(()=>{});g!==void 0&&await r.retainSnapshot({...o,path:n},this.baselineRefFor(e.label),g).catch(()=>{});let y=[];k.alreadyPresent===!0&&y.push(` Nothing was staged: ${$(n)} already had every one of those changes.`),m||y.push(` WARNING: your own edits to ${$(n)} overlap the workspace's changes and could not be replayed on top. They are preserved at ${l.retainedRef}; recover with: git -C ${n} diff ${l.base} ${l.retainedRef}`);for(let w of p)y.push(` WARNING: nested tree ${w.relPath} was NOT included: a change set can only move the pointer to it, not what is inside. Land it with \`/hydra workspace stop\`, or copy that work across by hand.`);return{applied:`Applied ${e.label} into ${$(n)} as staged changes; still working in ${$(e.path)}.
185
- Nothing was committed: review it with \`git -C ${n} diff --cached\` and commit it however you like. The workspace and its history are untouched.`,warnings:y}}async leaveWorkspace(e,t,n){let r=n.exit!=="detached",o=re(t.provider),i={path:t.path,sourceCwd:t.sourceCwd,label:t.label,provider:t.provider,...t.snapshot!==void 0?{snapshot:t.snapshot}:{},...t.vcs!==void 0?{vcs:t.vcs}:{}},a=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:t.sourceCwd,workspace:void 0,historyLength:a.length,note:`Returned to the source tree at ${t.sourceCwd}`+(n.exit==="landed"?" after merging the workspace.":n.exit==="discarded"?" after discarding the workspace and its work.":" without merging."),...await this.recordSynopsisFor(e.sessionId),left:{path:t.path,removed:r}}),await this.mutateRecord(e.sessionId,{cwd:e.cwd},["workspace"]),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"left",cwd:e.cwd,sourceCwd:t.sourceCwd,integrated:n.exit==="landed"}),o!==void 0&&await this.enqueueKeyed(this.workspaceQueues,t.path,async()=>{let d=this.liveSessionsIn(t.path,e.sessionId);if(d.length>0){this.logger?.info?.(`session workspace: ${e.sessionId} left ${t.path}; ${d.length} live session(s) remain, so it stays`);return}await this.reclaimAfterLastLeaver(o,i,t,e.sessionId,n)})}async reclaimAfterLastLeaver(e,t,n,r,o){await e.unlock(t).catch(()=>{});for(let i of[this.startRefFor(n.label),this.baselineRefFor(n.label)])await e.dropSnapshotRef(t,i).catch(()=>{});o.exit!=="detached"&&(o.exit==="landed"&&await e.dropSnapshotRef(t,this.snapshotRefFor(n.label)).catch(()=>{}),await e.removeWorkspace(t,{force:!0,discardLine:!0}).catch(()=>{}))}async joinDivergence(e,t,n){let[r,o]=await Promise.all([e.captureWorkingState(t,"hydra: source state at join").catch(()=>{}),e.captureWorkingState(n.path,"hydra: workspace state at join").catch(()=>{})]);if(r===void 0||o===void 0)return`could not compare ${$(t)} with ${$(n.path)}, so refusing to join a workspace that may not match your tree`;let i=await Promise.all([r,o].map(a=>e.contentId(t,a).catch(()=>{})));if(!(i[0]!==void 0&&i[0]===i[1]))return`${$(t)} and ${$(n.path)} have diverged, and joining does not carry work across \u2014 whichever side you are not in would be left behind. Land or stash one of them first: \`git -C ${t} stash\` if the difference is yours, or \`/hydra workspace merge\` from the session already in there if it is theirs.`}liveSessionsWithLabel(e,t){let n=[];for(let r of this.sessions.values()){let o=r.workspace;o===void 0||o.sourceCwd!==e||(o.label===t||o.requestedLabel===t)&&n.push(r)}return n}async joinWorkspace(e,t,n,r){let o=re(n.provider);if(o===void 0)throw new Error(`no provider "${n.provider}" to join that workspace with`);if(o.capabilities().supports.captureWorkingState){let i=await this.joinDivergence(o,r,n);if(i!==void 0)throw new Error(i)}return await this.enqueueKeyed(this.workspaceQueues,n.path,async()=>{if(this.sessions.get(t.sessionId)?.workspace?.path!==n.path)throw new Error(`${$(n.path)} was released while joining it; run the command again`);e.broadcastWorkspacePhase({phase:"swapping"});let i=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:n.path,workspace:{path:n.path,sourceCwd:n.sourceCwd,label:n.label,...n.requestedLabel!==void 0?{requestedLabel:n.requestedLabel}:{},provider:n.provider,...n.snapshot!==void 0?{snapshot:n.snapshot}:{},...n.line!==void 0?{line:n.line}:{},...n.vcs!==void 0?{vcs:{...n.vcs}}:{}},historyLength:i.length,note:`Continuing in an isolated workspace at ${n.path}, derived from ${r}, shared with another session.`,...await this.recordSynopsisFor(e.sessionId)}),await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),this.invalidateListCache();let a=n.line;e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:n.sourceCwd,label:n.label,...a!==void 0?{branch:a}:{}});let d=this.liveSessionsIn(n.path,e.sessionId).map(u=>tt(u.sessionId)),c=[`Joined workspace ${$(n.path)}`,` source: ${$(n.sourceCwd)}`];return a!==void 0&&c.push(` branch: ${a}`),c.push(` shared with: ${d.join(", ")}`),c.push(" your edits will interleave with that session's"),c.push("Use `/hydra workspace stop` to leave; the work lands when the last session leaves."),c.join(`
186
- `)})}async startWorkspace(e,t,n){if(e.workspace!==void 0)throw new Error(`already isolated in ${$(e.workspace.path)}. Use \`/hydra workspace stop\` to merge and return first, or \`detach\` to leave it behind.`);let r=e.cwd,o=re();if(o===void 0)throw new Error("no workspace provider available");let i=await e.quiesceBlocker();if(i!==void 0)throw new Error(i);let a=o.capabilities();if(t!==void 0){let b=this.liveSessionsWithLabel(r,t)[0];if(b!==void 0&&b.workspace!==void 0)return await this.joinWorkspace(e,b,b.workspace,r)}let d,c=[],u=!1,l=!1,p=[],f=[],h=n?.clean===!0;if(a.supports.captureWorkingState){let b=await o.status({path:r,sourceCwd:r,label:"source",provider:o.kind}).catch(()=>{});l=b!==void 0;let I=a.supports.nestedTrees&&b!==void 0&&b.changedPaths.length>0?await o.listNested(r).catch(()=>[]):[];if(b!==void 0&&b.changedPaths.length>0&&h)p=Po(b.changedPaths,I);else if(b!==void 0&&b.changedPaths.length>0&&(c=Po(b.changedPaths,I),f=await o.captureNested(r,I).catch(()=>[]),u=b.hasStagedWork===!0,d=await o.captureWorkingState(r,"hydra: work carried into workspace").catch(()=>{}),d===void 0))throw new Error("could not snapshot your uncommitted work, so refusing to move it. Commit or stash first.")}e.broadcastWorkspacePhase({phase:"provisioning"});let k=await o.createWorkspace({sourceCwd:r,label:t??`s-${e.sessionId.slice(-8)}`});if(!k.ok)throw e.broadcastWorkspacePhase({phase:"failed",error:k.reason}),new Error(k.reason);let m=k.workspace,g=this.startRefFor(m.label),y,w=!1,v=[];try{a.locking&&await o.lock(m,`session ${e.sessionId}`).catch(()=>{});let b=d??m.snapshot;if(b===void 0)throw new Error(`provider "${m.provider}" gave the workspace no base to anchor landing against`);await o.retainSnapshot(m,g,b),e.broadcastWorkspacePhase({phase:"setup"}),w=d!==void 0?await this.copyCarriedWork(m,d,r):!0;let I=await this.materializeNestedTrees(m);if(f.length>0){let R=await o.reproduceNested(m.path,r,f).catch(E=>({applied:[],failed:f.map(M=>({path:M.relPath,reason:E instanceof Error?E.message:String(E)}))}));R.failed.length>0&&(w=!1,v=R.failed)}y=await this.applyWorkspaceSetup(m,e.sessionId),I!==void 0&&(y=y===void 0?I:`${I}; ${y}`),e.broadcastWorkspacePhase({phase:"swapping"});let C=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:m.path,workspace:{path:m.path,sourceCwd:m.sourceCwd,label:m.label,...t!==void 0&&t!==m.label?{requestedLabel:t}:{},provider:m.provider,...m.snapshot!==void 0?{snapshot:m.snapshot}:{},...m.line!==void 0?{line:m.line}:{},...m.vcs!==void 0?{vcs:{...m.vcs}}:{},...d===void 0?{clean:!0}:{}},historyLength:C.length,note:`Continuing in an isolated workspace at ${m.path}, derived from ${r}.`,...await this.recordSynopsisFor(e.sessionId)})}catch(b){let I=await this.unwindStartWorkspace({provider:o,ws:m,startRef:g,carried:d}),C=b instanceof Error?b.message:String(b);throw e.broadcastWorkspacePhase({phase:"failed",error:C}),new Error(I===void 0?C:`${C}
187
- ${I}`)}await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:m.sourceCwd,label:m.label,...m.line!==void 0?{branch:m.line}:{}});let S=[`Moved into workspace ${$(m.path)}`,` source: ${$(r)}`];if(m.line!==void 0&&S.push(` branch: ${m.line}`),t!==void 0&&t!==m.label&&S.push(` note: "${t}" was already taken by a surviving branch, so this is "${m.label}"`),d!==void 0){S.push(w?` carried ${c.length} uncommitted file(s) in; the source tree is untouched:`:` WARNING: could not copy ${c.length} uncommitted file(s); the workspace starts from HEAD. They are untouched in the source tree:`);for(let b of At(c))S.push(` ${b}`);w&&u&&S.push(" staging did not come along; everything above is unstaged here");for(let b of v)S.push(` nested tree ${b.path}: ${b.reason}`)}else if(p.length>0){S.push(` started clean: ${p.length} uncommitted file(s) stayed in the source and did NOT come along:`);for(let b of At(p))S.push(` ${b}`)}else l&&S.push(" source tree was clean; nothing carried in");return y!==void 0&&S.push(` ${y}`),S.push("Use `/hydra workspace stop` to merge back and return."),S.join(`
188
- `)}async copyCarriedWork(e,t,n){let r=await this.patchFromSnapshot(n,t,e.provider);if(r===void 0)return!1;if(r.length===0)return!0;let o=re(e.provider);return o===void 0?!1:(await o.applyDelta(e.path,r)).ok}async patchFromSnapshot(e,t,n){let r=re(n);if(r===void 0)return;let o=await r.currentState(e);if(o!==void 0)return await r.captureDelta(e,o,t).catch(()=>{})}async unwindStartWorkspace(e){let{provider:t,ws:n,startRef:r,carried:o}=e;await t.unlock(n).catch(()=>{}),o!==void 0&&await t.dropSnapshotRef(n,r).catch(()=>{}),await t.removeWorkspace(n,{force:!0}).catch(()=>{})}async materializeNestedTrees(e,t){let n=re(e.provider);if(n?.capabilities().supports.nestedTrees!==!0)return;let r=await n.materializeNested({path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:n.kind},t).catch(o=>({ok:!1,count:0,reason:o instanceof Error?o.message:String(o)}));return r.ok?r.count>0?`populated ${r.count} nested tree(s)`:void 0:`nested trees FAILED: ${r.reason??"unknown"}`}async applyWorkspaceSetup(e,t){let n=await Ms(e.sourceCwd).catch(()=>({})),r=[];if(n.carry!==void 0&&n.carry.length>0){let o=await Do(e.sourceCwd,e.path,n.carry).catch(()=>{});o!==void 0&&o.copied.length>0&&r.push(`carried ${o.copied.length} config file(s)`)}if(n.postCreate!==void 0){let o=await _s(n.postCreate,{workspacePath:e.path,sourceCwd:e.sourceCwd,label:e.label,sessionId:t,...n.hookTimeoutSeconds!==void 0?{timeoutSeconds:n.hookTimeoutSeconds}:{}});r.push(o.ok?"ran postCreate":`postCreate FAILED: ${o.reason??"unknown"}`)}return r.length>0?r.join("; "):void 0}async deriveForkWorkspace(e,t){let n=re(e.provider);if(n===void 0)return;let r=n.capabilities(),o=r.sharedHistory?await n.currentState(e.path)??"":"",i=await n.createWorkspace({sourceCwd:e.sourceCwd,label:t,...o.length>0?{from:o}:{contentFrom:e.path}}).catch(d=>({ok:!1,reason:String(d)}));if(!i.ok){this.logger?.warn?.(`fork workspace: could not derive from ${e.path}: ${i.reason}`);return}let a=i.workspace;if(o.length>0&&r.supports.captureWorkingState){let d=await n.captureWorkingState(e.path,`hydra: fork carry from ${e.label}`).catch(()=>{});d!==void 0&&d!==o&&await this.copyUncommittedInto(e.path,a.path,o,d,a.provider).catch(()=>{})}return{path:a.path,sourceCwd:a.sourceCwd,label:a.label,provider:a.provider,...a.snapshot!==void 0?{snapshot:a.snapshot}:{},...a.line!==void 0?{line:a.line}:{},...a.vcs!==void 0?{vcs:{...a.vcs}}:{}}}async copyUncommittedInto(e,t,n,r,o){let i=re(o);if(i===void 0)return!1;let a=await i.captureDelta(e,n,r).catch(()=>{});return a===void 0||a.trim().length===0?!1:(await i.applyDelta(t,a,{stage:!0})).ok}async recoverWorkspace(e){let t=re(e.provider);if(t===void 0)return;let n={path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:e.provider,...e.snapshot!==void 0?{snapshot:e.snapshot}:{},...e.vcs!==void 0?{vcs:e.vcs}:{}};if(t.capabilities().supports.rematerialize){let o=await t.rematerialize(n).catch(i=>({ok:!1,reason:String(i)}));if(o.ok)return this.logger?.info?.(`session workspace: restored ${o.workspace.path} from retained state`),{...e,path:o.workspace.path};this.logger?.warn?.(`session workspace: could not restore: ${o.reason}`)}if(!await this.dirExists(e.sourceCwd))return;let r=await t.createWorkspace({sourceCwd:e.sourceCwd,label:`${e.label}-r`}).catch(o=>({ok:!1,reason:String(o)}));if(r.ok)return this.logger?.warn?.(`session workspace: ${e.path} is gone and could not be restored; resurrecting in a fresh workspace ${r.workspace.path} from ${e.sourceCwd}. Uncommitted work from the old workspace is not recoverable.`),{path:r.workspace.path,sourceCwd:r.workspace.sourceCwd,label:r.workspace.label,provider:r.workspace.provider,...r.workspace.snapshot!==void 0?{snapshot:r.workspace.snapshot}:{},...r.workspace.vcs!==void 0?{vcs:{...r.workspace.vcs}}:{}}}async syncFromAgent(e){let t=await this.registry.getAgent(e);if(!t){let m=new Error(`agent ${e} not found in registry`);throw m.code=x.AgentNotInstalled,m}let n=await _e(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:Mc.homedir(),plan:n}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:jt,clientInfo:{name:"hydra",version:ue}})}catch(m){throw await r.kill().catch(()=>{}),ht(m,r)}if(r.authMethods=Dn(o.authMethods),r.steeringSupported=Nn(o),(o.agentCapabilities??{}).sessionCapabilities?.list===void 0)throw await r.kill().catch(()=>{}),new Error(`agent ${e} does not advertise sessionCapabilities.list; cannot sync`);let a;try{a=await this.collectAgentSessions(r)}catch(m){throw await r.kill().catch(()=>{}),m}await r.kill().catch(()=>{});let d=new Map,c=zr(t);d.set(e,c);let u=new Set,l=new Map;for(let m of this.sessions.values()){let g=await this.agentStoreKey(m.agentId,d);u.add(`${g}::${m.upstreamSessionId}`),g===c&&l.set(m.upstreamSessionId,m)}let p=await this.store.list().catch(()=>[]);for(let m of p){u.add(`${await this.agentStoreKey(m.agentId,d)}::${m.upstreamSessionId}`);for(let g of m.upstreamGenerations??[])u.add(`${await this.agentStoreKey(g.agentId,d)}::${g.upstreamSessionId}`)}let f=T.sessionsDir(),h=[],k=0;for(let m of a){l.get(m.sessionId)?.noteUpstreamUpdatedAt(m.updatedAt);let g=`${c}::${m.sessionId}`;if(u.has(g)){k+=1;continue}if(xh(m.cwd,f)){k+=1;continue}let y=c,w=await this.tombstones.read(y,m.sessionId).catch(()=>{});if(!w&&c!==e&&(y=e,w=await this.tombstones.read(y,m.sessionId).catch(()=>{})),w){if(!tc(w,m.updatedAt)){k+=1;continue}await this.tombstones.remove(y,m.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${m.sessionId} (upstream updatedAt advanced past ${w.upstreamUpdatedAt??"<unset>"})`)}u.add(g);let v=`${ye}${Rt()}`,S=new Date().toISOString(),b=m.updatedAt??S,I={sessionId:v,lineageId:En(),upstreamSessionId:m.sessionId,agentId:e,cwd:m.cwd,pendingHistorySync:!0,interactive:!Eh(m.title),createdAt:b,updatedAt:b};m.title!==void 0&&(I.title=m.title);let C=Eo(I);await this.store.write(C),h.push({version:1,...C})}return{synced:h,skipped:k}}async listTombstones(e={}){let t=e.grep?.toLowerCase();return(await this.tombstones.list(e.agentId)).filter(r=>e.since===void 0||r.deletedAt>=e.since).filter(r=>t===void 0||[r.title,r.cwd,r.sessionId,r.upstreamSessionId].some(o=>o?.toLowerCase().includes(t))).sort((r,o)=>r.deletedAt<o.deletedAt?1:-1)}async undeleteSessions(e){let t=await this.tombstones.list(),n=[],r=[],o=[];for(let a of e){let d=t.filter(u=>u.upstreamSessionId===a),c=d.length>0?d:t.filter(u=>u.sessionId===a||u.sessionId===`${ye}${a}`);if(c.length===0){r.push({id:a,reason:"no tombstone found"});continue}if(c.length>1){r.push({id:a,reason:"ambiguous: several tombstones match; pass an upstream id",candidates:c.map(u=>u.upstreamSessionId)});continue}o.push({id:a,tombstone:c[0]})}let i=new Map;for(let a of o){let d=i.get(a.tombstone.agentId)??[];d.push(a),i.set(a.tombstone.agentId,d)}for(let[a,d]of i){let c=l=>{let{version:p,...f}=l;return this.tombstones.add(f).catch(()=>{})};for(let l of d)await this.tombstones.remove(a,l.tombstone.upstreamSessionId);let u;try{u=(await this.syncFromAgent(a)).synced}catch(l){for(let p of d)await c(p.tombstone),r.push({id:p.id,reason:`agent sync failed: ${l.message}`});continue}for(let l of d){let p=u.find(f=>f.upstreamSessionId===l.tombstone.upstreamSessionId);if(!p){await c(l.tombstone),r.push({id:l.id,reason:`agent ${a} no longer lists this session`});continue}n.push({id:l.id,sessionId:p.sessionId,upstreamSessionId:l.tombstone.upstreamSessionId})}}return{restored:n,failed:r}}async collectAgentSessions(e){let t=[],n,r=new Set;for(let o=0;o<100;o+=1){let i={};n!==void 0&&(i.cursor=n);let a=await e.connection.request("session/list",i),d=Array.isArray(a.sessions)?a.sessions:[];for(let c of d){if(typeof c.sessionId!="string"||typeof c.cwd!="string")continue;let u={sessionId:c.sessionId,cwd:c.cwd};typeof c.title=="string"&&(u.title=c.title),typeof c.updatedAt=="string"&&(u.updatedAt=c.updatedAt),t.push(u)}if(typeof a.nextCursor!="string"||a.nextCursor.length===0||r.has(a.nextCursor))break;r.add(a.nextCursor),n=a.nextCursor}return t}async applySeedModel(e,t,n,r,o){try{let{verb:i,result:a}=await ut({request:(d,c)=>e.connection.request(d,c),sessionId:t,modelId:n,...o?{verb:o}:{},logger:this.logger});return this.logger?.info(`${r}: ${i} accepted`),{accepted:!0,result:a}}catch(i){return this.logger?.warn(`${r} rejected by agent (${i.message}); session will use the agent's own default`),{accepted:!1}}}async applySeedMode(e,t,n,r){try{let o=await e.connection.request("session/set_mode",{sessionId:t,modeId:n});return this.logger?.info(`${r}: session/set_mode accepted`),{accepted:!0,result:o}}catch(o){return this.logger?.warn(`${r} rejected by agent (${o.message}); session will use the agent's own default mode`),{accepted:!1}}}async restoreConfigOptionValues(e,t,n,r){if(!n||Object.keys(n).length===0)return this.logger?.info(`resurrect: no persisted configOptionValues; agent reports ${JSON.stringify(Object.fromEntries(r.map(i=>[i.id,i.currentValue])))}`),r;let o=r;for(let[i,a]of Object.entries(n)){let d=`resurrect: persisted configOptionValues.${i}=${JSON.stringify(a)}`,c=o.find(p=>p.id===i);if(!c){this.logger?.warn(`${d}: agent does not currently advertise configId=${i}; skipping session/set_config_option`);continue}if(a===c.currentValue){this.logger?.info(`${d}: agent already reports ${JSON.stringify(c.currentValue)}; nothing to restore`);continue}this.logger?.info(`${d}: agent reports ${JSON.stringify(c.currentValue)}; restoring`);let u=Vt(a,c.options.map(p=>p.value));if(u.kind!=="exact"&&u.kind!=="resolved"){this.logger?.warn(`${d} ${u.kind}; skipping session/set_config_option`);continue}let l=u.kind==="resolved"?u.modelId:a;try{let p=await e.connection.request("session/set_config_option",{sessionId:t,configId:i,value:l});this.logger?.info(`${d}: session/set_config_option accepted`),o=en(p)?tn(p):o.map(f=>f.id===i?{...f,currentValue:l}:f)}catch(p){this.logger?.warn(`${d}: session/set_config_option rejected by agent (${p.message})`)}}return o}async bootstrapAgent(e){let t=e.timer,n=await this.registry.getAgent(e.agentId);if(!n){let a=new Error(`agent ${e.agentId} not found in registry`);throw a.code=x.AgentNotInstalled,a}t?.mark("boot.resolve-agent");let r=await _e(n,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress});t?.mark("boot.plan-spawn");let o=es(e.selfSessionId,e.forwardedEnv),i=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:r,...o?{extraEnv:o}:{}});t?.mark("boot.spawn");try{let a=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:jt,clientInfo:{name:"hydra",version:ue}}),d=a.agentCapabilities;i.authMethods=Dn(a.authMethods),i.steeringSupported=Nn(a),t?.mark("boot.initialize");let c=Jo(n),u=await i.connection.request("session/new",{cwd:e.cwd,mcpServers:e.mcpServers??[],...c&&{_meta:c}});t?.mark("boot.session-new");let l=u.sessionId;if(typeof l!="string")throw new Error(`agent ${e.agentId} returned a non-string sessionId from session/new`);let p=Vo(u),f=Go(u),h=Ut(u),k=la(this.sessionDefaults,n),m=k?.value,g=e.configDefaults,y=k?.from??e.agentId,w=e.model??g?.model??m?.model,v;if(w&&w!==p){let E=Jt(w,f),M=e.model!==void 0?`model=${JSON.stringify(w)}`:g?.model!==void 0?`configDefaults.model=${JSON.stringify(w)}`:`sessionDefaults[${y}].model=${JSON.stringify(w)}`;if(E.kind==="exact"||E.kind==="none"){let N=await this.applySeedModel(i,l,w,M,h);N.accepted&&(p=w,v=N.result)}else if(E.kind==="resolved")if(E.modelId===p)p=E.modelId;else{let N=await this.applySeedModel(i,l,E.modelId,`${M} resolved to ${JSON.stringify(E.modelId)}`,h);N.accepted&&(p=E.modelId,v=N.result)}else if(E.kind==="ambiguous")this.logger?.warn(`${M} is ambiguous (trailing-segment matches [${E.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(p)}`);else{let N=f.map(B=>B.modelId).join(", ");this.logger?.warn(`${M} not in agent's availableModels ([${N}]); skipping session/set_model, session will use ${JSON.stringify(p)}`)}}t?.mark("boot.seed-model");let S=Ko(u),b=Qo(u),I=g?.mode??m?.mode;if(I&&I!==b){let E=g?.mode!==void 0?`configDefaults.mode=${JSON.stringify(I)}`:`sessionDefaults[${y}].mode=${JSON.stringify(I)}`;if(S.length>0&&!S.some(M=>M.id===I)){let M=S.map(N=>N.id).join(", ");this.logger?.warn(`${E} not in agent's availableModes ([${M}]); skipping session/set_mode, session will use ${JSON.stringify(b)}`)}else{let M=await this.applySeedMode(i,l,I,E);M.accepted&&(b=I,en(M.result)&&(v=M.result))}}t?.mark("boot.seed-mode");let C={...m??{},...g??{}};delete C.model,delete C.mode;let R=tn(en(v)?v:u);if(Object.keys(C).length>0)for(let[E,M]of Object.entries(C)){let N=`sessionDefaults[${y}].${E}=${JSON.stringify(M)}`,B=R.find(L=>L.id===E);if(!B){this.logger?.warn(`${N}: agent does not currently advertise configId=${E}; skipping session/set_config_option`);continue}let q=Vt(M,B.options.map(L=>L.value));if(q.kind!=="exact"&&q.kind!=="resolved"){this.logger?.warn(`${N} ${q.kind}; skipping session/set_config_option`);continue}let V=q.kind==="resolved"?q.modelId:M;if(V!==B.currentValue)try{let L=await i.connection.request("session/set_config_option",{sessionId:l,configId:E,value:V});this.logger?.info(`${N}: session/set_config_option accepted`),en(L)?(R=tn(L),v=L):R=R.map(W=>W.id===E?{...W,currentValue:V}:W)}catch(L){this.logger?.warn(`${N}: session/set_config_option rejected by agent (${L.message})`)}}return t?.mark("boot.seed-config"),i.connection.dropBufferedWhere("session/update",E=>E?.update?.sessionUpdate==="config_option_update"),{agent:i,upstreamSessionId:l,agentMeta:u._meta,agentCapabilities:d,initialModel:p,initialModels:f.length>0?f:void 0,initialModes:S.length>0?S:void 0,initialMode:b,initialConfigOptions:R.length>0?R:void 0,modelVerb:h}}catch(a){throw await i.kill().catch(()=>{}),ht(Tc(a,i,e.agentId,{command:r.command,args:r.args,cwd:e.cwd}),i)}}async bootstrapAgentLoad(e,t){let n=await this.registry.getAgent(t.agentId);if(!n){let a=new Error(`agent ${t.agentId} not found in registry`);throw a.code=x.AgentNotInstalled,a}let r=await _e(n,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=es(t.selfSessionId,t.forwardedEnv),i=this.spawner({agentId:t.agentId,cwd:t.cwd,plan:r,...o?{extraEnv:o}:{}});try{let a=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:jt,clientInfo:{name:"hydra",version:ue}}),d=a.agentCapabilities;i.authMethods=Dn(a.authMethods),i.steeringSupported=Nn(a);let c=Jo(n),u=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),l=Vo(u),p=mt(Go(u)),f=Ko(u),h=Qo(u),k=mt(tn(u));return{agent:i,upstreamSessionId:e,agentMeta:u._meta,agentCapabilities:d,initialModel:l,initialModels:p,initialModes:f.length>0?f:void 0,initialMode:h,initialConfigOptions:k,modelVerb:Ut(u)}}catch(a){throw await i.kill().catch(()=>{}),ht(Tc(a,i,t.agentId,{command:r.command,args:r.args,cwd:t.cwd}),i)}}async rewindSession(e,t,n={}){let r=await this.store.read(e);if(!r){let a=new Error(`session not found: ${e}`);throw a.code=x.SessionNotFound,a}if(this.rollbackLocks.has(e)||r.compactionState!=null){let a=new Error("the session is being compacted or rolled back; try again when that finishes");throw a.code=x.InvalidRequest,a}let o=0,i=async()=>{let a=await this.histories.truncateAfterTurn(e,t);if(!a){let u=new Error(`keepThrough messageId not found in the session's recent history: ${t}`);throw u.code=x.InvalidParams,u}if(o=a.removed,o===0)return!1;let d=r.summarizedThroughEntry,c=d!==void 0&&a.kept<d;if(c){let u=this.get(e);u&&(u.summarizedThroughEntry=void 0)}return await this.mutateRecord(e,{},c?["rollbackBreadcrumb","synopsis","summarizedThroughEntry"]:["rollbackBreadcrumb"]),!0};this.rollbackLocks.add(e);try{let a=this.get(e);a?await a.rewind(t,i,n):await i()&&await this.mutateRecord(e,{upstreamSessionId:""})}finally{this.rollbackLocks.delete(e)}return{sessionId:e,removed:o}}async performUncompact(e){if(this.rollbackLocks.has(e))throw new Error("a rollback is already in progress for this session");let t=this.get(e);if(!t)throw new Error("session is not live \u2014 cannot roll back a cold session");let n=await this.store.read(e);if(!n)throw new Error("session record not found");let r=n.rollbackBreadcrumb;if(!r)throw new Error("no rollback breadcrumb found \u2014 either the session has not been compacted, the rollback window has closed (a new turn was dispatched), or a previous rollback already consumed the breadcrumb");let o=n.compactionState;if(o!=null)throw new Error(`compaction is in progress (status: ${o.status}) \u2014 wait for it to complete before rolling back`);if(!await t.isQuiescedForSwap())throw new Error("session is not quiesced for rollback \u2014 wait for in-flight work to complete");this.rollbackLocks.add(e);try{await t.rollbackToUpstream({previousUpstreamSessionId:r.previousUpstreamSessionId,previousSummarizedThroughEntry:r.previousSummarizedThroughEntry}),await this.mutateRecord(e,{summarizedThroughEntry:r.previousSummarizedThroughEntry},["synopsis","rollbackBreadcrumb"])}finally{this.rollbackLocks.delete(e)}}async bootstrapAgentForAuth(e,t){let n=this.pendingAuthAgents.get(e);if(n&&n.isAlive())return n;let r=await this.registry.getAgent(e);if(!r){let d=new Error(`agent ${e} not found in registry`);throw d.code=x.AgentNotInstalled,d}let o=await _e(r,[],{npmRegistry:this.npmRegistry}),i=t??ce(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let d=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:jt,clientInfo:{name:"hydra",version:ue}});a.authMethods=Dn(d.authMethods),a.steeringSupported=Nn(d)}catch(d){throw await a.kill().catch(()=>{}),ht(d,a)}return this.pendingAuthAgents.set(e,a),a.onExit(()=>{this.pendingAuthAgents.get(e)===a&&this.pendingAuthAgents.delete(e)}),a}async planSpawnForAgent(e){let t=await this.registry.getAgent(e);if(!t){let n=new Error(`agent ${e} not found in registry`);throw n.code=x.AgentNotInstalled,n}return _e(t,[],{npmRegistry:this.npmRegistry})}consumePendingAuthAgent(e){let t=this.pendingAuthAgents.get(e);if(t&&(this.pendingAuthAgents.delete(e),!!t.isAlive()))return t}getAgentForSession(e){return this.sessions.get(e)?.agent}async attachManagerHooks(e){e.onClose(({deleteRecord:t})=>{if(this.sessions.delete(e.sessionId),this.driftNoticed.delete(e.sessionId),this.invalidateListCache(),t||this.store.touch(e.sessionId).catch(()=>{}),t&&e.workspace!==void 0&&this.releaseWorkspace(e.workspace,e.sessionId).catch(()=>{}),t){if(e.upstreamSessionId){let r=nn({interactive:e.interactive,...e.originatingClient?{originatingClient:e.originatingClient}:{}},!0),o=this.tombstoneAllGenerations(e.sessionId,{agentId:e.agentId,upstreamSessionId:e.upstreamSessionId,upstreamUpdatedAt:new Date(e.updatedAt).toISOString(),cwd:e.cwd,...e.title!==void 0?{title:e.title}:{},...r!==void 0?{interactive:r}:{}},"user").catch(()=>{}).then(()=>this.store.delete(e.sessionId).catch(()=>{})).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===o&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,o);return}let n=this.store.delete(e.sessionId).catch(()=>{}).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===n&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,n);return}}),e.rewindHook=t=>this.rewindSession(e.sessionId,t,{afterCurrentTurn:!0}),e.onTitleChange(t=>{this.persistTitle(e.sessionId,t).catch(()=>{})}),e.onPriorityChange(t=>{this.persistPriority(e.sessionId,t).catch(()=>{})}),e.onAgentChange(({agentId:t,upstreamSessionId:n,...r})=>{this.persistAgentChange(e.sessionId,t,n,r).catch(()=>{})}),e.onModelChange(t=>{this.persistSnapshot(e.sessionId,{currentModel:t}).catch(()=>{})}),e.onModeChange(t=>{this.persistSnapshot(e.sessionId,{currentMode:t}).catch(()=>{})}),e.onInteractiveChange(t=>{this.persistSnapshot(e.sessionId,{interactive:t}).catch(()=>{})}),e.onUsageChange(t=>{this.persistSnapshot(e.sessionId,{currentUsage:_c(t)}).catch(()=>{})}),e.onAgentCommandsChange(t=>{this.persistSnapshot(e.sessionId,{agentCommands:t.map(n=>({name:n.name,...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModesChange(t=>{this.persistSnapshot(e.sessionId,{agentModes:t.map(n=>({id:n.id,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModelsChange(t=>{this.persistSnapshot(e.sessionId,{agentModels:t.map(n=>({modelId:n.modelId,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onConfigOptionsChange(t=>{this.persistSnapshot(e.sessionId,{configOptionValues:Object.fromEntries(t.map(n=>[n.id,n.currentValue]))}).catch(()=>{})}),e.onAttentionFlagsChange(t=>{this.mutateRecord(e.sessionId,{attentionFlags:t}).catch(()=>{})}),e.onReadStateChange(t=>{this.invalidateListCache(),this.persistReadState(e.sessionId,t).then(()=>this.invalidateListCache()).catch(()=>{})}),this.sessions.set(e.sessionId,e),this.invalidateListCache(),await this.enqueueMetaWrite(e.sessionId,async()=>{let t=await this.store.read(e.sessionId),n=Th(e,t);await this.store.write(n)}).catch(t=>{this.logger?.warn(`failed to persist session record for ${e.sessionId}: ${t instanceof Error?t.message:String(t)}`)})}async getHistory(e){if(this.sessions.has(e))return this.histories.load(e).catch(()=>[]);if(await this.store.read(e))return this.histories.load(e).catch(()=>[])}async pageHistory(e,t){let n=await this.store.read(e);if(!this.sessions.has(e)&&!n)return;let r=this.sessions.get(e)?.side??n?.side,o=await this.histories.pageBefore(e,{...t,skip:a=>An(a.method,a.params),hydrate:!1}),i=Lt(o.entries,r);return{entries:await this.histories.hydrate(e,cs(i)),hasMore:o.hasMore&&i.length===o.entries.length}}async loadHistory(e,t={}){return this.histories.load(e,t)}async loadToolBlob(e,t){return mn(e,t)}async loadFromDisk(e){let t=await this.store.read(e);if(!t)return;let n=t.title;return n||(n=await this.deriveTitleFromHistory(e)),{hydraSessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,agentId:t.agentId,cwd:t.cwd,title:n,synopsis:t.synopsis,summarizedThroughEntry:t.summarizedThroughEntry,agentArgs:t.agentArgs,currentModel:t.currentModel,currentMode:t.currentMode,currentUsage:Ph(t.currentUsage),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,configOptionValues:t.configOptionValues,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,lastTurnEndedAt:t.lastTurnEndedAt,readAt:t.readAt,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,side:t.side,forkSynthesisState:t.forkSynthesisState,forwardedEnv:t.forwardedEnv,workspace:t.workspace,compactionState:t.compactionState,attentionFlags:t.attentionFlags?.filter(r=>!(r.source==="daemon"&&r.reason.startsWith("permission:")))}}async setForwardedEnv(e,t){if(t===void 0)return;let n=this.sessions.get(e);n&&(n.forwardedEnv=t),await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r)return;let o={...r,forwardedEnv:t};await this.store.write(o)})}async clearPendingHistorySync(e){await this.enqueueMetaWrite(e,async()=>{let t=await this.store.read(e);if(!t||t.pendingHistorySync!==!0)return;let n={...t};delete n.pendingHistorySync,await this.store.write(n)})}async deriveTitleFromHistory(e){let t=await this.histories.load(e).catch(()=>[]);for(let n of t){let r=n.params;if(r?.update?.sessionUpdate!=="prompt_received")continue;let o=r.update.sentBy;if(typeof o?.fromSession=="string"||typeof o?.clientId=="string"&&o.clientId.startsWith("transformer:"))continue;let i=It(r.update.prompt),a=bo(i,200);if(a&&!a.startsWith("/"))return a}}get(e){return this.sessions.get(e)}liveSessions(){return this.sessions.values()}setLiveConfig(e){e.sessionDefaults&&(this.sessionDefaults=e.sessionDefaults)}activeAgentVersions(){let e=new Map;for(let t of this.sessions.values()){let n=t.agent.installId,r=t.agent.version,o=e.get(n);o||(o=new Set,e.set(n,o)),o.add(r)}return e}async resolveCanonicalId(e){if(this.sessions.has(e)||await this.store.read(e))return e;if(e.startsWith(ye))return;let t=ye+e;if(this.sessions.has(t)||await this.store.read(t))return t}require(e){let t=this.sessions.get(e);if(!t){let n=new Error(`session ${e} not found`);throw n.code=x.SessionNotFound,n}return t}liveListEntry(e){return{sessionId:e.sessionId,upstreamSessionId:e.upstreamSessionId,cwd:e.cwd,workspace:e.workspace,workspaceError:e.workspaceError,title:e.title,agentId:e.agentId,currentModel:e.currentModel,currentUsage:e.currentUsage,parentSessionId:e.parentSessionId,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,side:e.side,forkSynthesisState:e.forkSynthesisState,originatingClient:e.originatingClient,interactive:e.interactive,createdAt:new Date(e.createdAt).toISOString(),updatedAt:new Date(e.updatedAt).toISOString(),attachedClients:e.attachedCount,status:"warm",busy:e.turnStartedAt!==void 0,turnStartedAt:e.turnStartedAt,armedTasks:e.armedBackgroundTasks.length,...e.armedSince!==void 0?{armedSince:e.armedSince}:{},awaitingInput:e.awaitingInput,agentPid:e.agentPid,...Wt(e)}}async getOne(e){let t=this.sessions.get(e);if(t){let a=await Hn(t.sessionId),d=nn({interactive:t.interactive,...t.originatingClient?{originatingClient:t.originatingClient}:{}},a.hasContent),c=a.mtime??new Date(t.updatedAt).toISOString();return{sessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,cwd:t.cwd,title:t.title,agentId:t.agentId,currentModel:t.currentModel,currentUsage:t.currentUsage,parentSessionId:t.parentSessionId,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,side:t.side,forkSynthesisState:t.forkSynthesisState,originatingClient:t.originatingClient,interactive:d,priority:t.priority,createdAt:new Date(t.createdAt).toISOString(),updatedAt:c,attachedClients:t.attachedCount,status:"warm",agentPid:t.agentPid,busy:t.turnStartedAt!==void 0,turnStartedAt:t.turnStartedAt,armedTasks:t.armedBackgroundTasks.length,...t.armedSince!==void 0?{armedSince:t.armedSince}:{},awaitingInput:t.awaitingInput,...Wt(t)}}let n=await this.store.read(e).catch(()=>{});if(!n)return;let r=await Hn(n.sessionId),o=nn(n,r.hasContent),i=r.mtime??n.updatedAt;return{sessionId:n.sessionId,upstreamSessionId:n.upstreamSessionId,cwd:n.cwd,title:n.title,agentId:n.agentId,currentModel:n.currentModel,currentUsage:Fn(n.currentUsage),importedFromMachine:n.importedFromMachine,importedFromUpstreamSessionId:n.importedFromUpstreamSessionId,parentSessionId:n.parentSessionId,forkedFromSessionId:n.forkedFromSessionId,forkedFromMessageId:n.forkedFromMessageId,side:n.side,forkSynthesisState:n.forkSynthesisState,originatingClient:n.originatingClient,interactive:o,priority:n.priority,createdAt:n.createdAt,updatedAt:i,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,...Wt(n)}}async list(e={}){return(await this.listing(e)).entries}async listing(e={}){let t=`${e.cwd??""}|${e.includeNonInteractive?"1":"0"}|${e.status??""}`,n=Date.now(),r=this.listCache.get(t);if(r&&r.expiresAt>n)return r.promise;let o=this.listUncached(e);return this.listCache.set(t,{expiresAt:n+s.LIST_CACHE_TTL_MS,promise:o}),o.catch(()=>{let i=this.listCache.get(t);i&&i.promise===o&&this.listCache.delete(t)}),o}invalidateListCache(){this.listCache.clear()}async listUncached(e={}){let t=await this.store.cursor(),{entries:n,liveIds:r}=await this.warmRows(e);if(e.status==="warm")return{entries:n,cursor:t};let o=await this.store.list().catch(i=>{throw this.logger?.warn(`session list: store.list() failed: ${i?.message??String(i)}`),i});return n.push(...await this.coldRows(o,r,e)),n.sort((i,a)=>i.updatedAt<a.updatedAt?1:-1),{entries:n,cursor:t}}async listSince(e,t){let{entries:n,liveIds:r}=await this.warmRows(e);if(e.status==="warm")return{entries:n,removed:[],cursor:await this.store.cursor()};let o=await this.store.listChangedSince(t);return n.push(...await this.coldRows(o.records,r,e)),n.sort((i,a)=>i.updatedAt<a.updatedAt?1:-1),{entries:n,removed:o.removed,cursor:o.cursor}}async seedSessionIndex(){await this.store.ensureIndex();let e=await this.tombstones.list().catch(()=>[]);for(let t of e){if(t.sessionId===void 0)continue;let n=Date.parse(t.deletedAt);Number.isNaN(n)||await this.store.markDeleted(t.sessionId,n)}}static includeRow(e,t){return e.includeNonInteractive?!0:t===!0}async warmRows(e){let t=[],n=new Set,r=[...this.sessions.values()].filter(i=>xc(e.cwd,i));if(e.status==="cold"){for(let i of r)n.add(i.sessionId);return{entries:t,liveIds:n}}let o=await Promise.all(r.map(i=>Hn(i.sessionId)));for(let i=0;i<o.length;i+=1){let a=r[i],d=o[i];n.add(a.sessionId);let c=nn({interactive:a.interactive,...a.originatingClient?{originatingClient:a.originatingClient}:{}},d.hasContent);if(!s.includeRow(e,c))continue;let u=d.mtime??new Date(a.updatedAt).toISOString();t.push({sessionId:a.sessionId,upstreamSessionId:a.upstreamSessionId,cwd:a.cwd,workspace:a.workspace,workspaceError:a.workspaceError,title:a.title,agentId:a.agentId,currentModel:a.currentModel,currentUsage:a.currentUsage,parentSessionId:a.parentSessionId,forkedFromSessionId:a.forkedFromSessionId,forkedFromMessageId:a.forkedFromMessageId,side:a.side,originatingClient:a.originatingClient,interactive:c,priority:a.priority,createdAt:new Date(a.createdAt).toISOString(),updatedAt:u,attachedClients:a.attachedCount,status:"warm",agentPid:a.agentPid,busy:a.turnStartedAt!==void 0,turnStartedAt:a.turnStartedAt,armedTasks:a.armedBackgroundTasks.length,...a.armedSince!==void 0?{armedSince:a.armedSince}:{},awaitingInput:a.awaitingInput,compactionState:a.compactionState,forkSynthesisState:a.forkSynthesisState,...Wt(a)})}return{entries:t,liveIds:n}}async coldRows(e,t,n){let r=[],o=e.filter(a=>!t.has(a.sessionId)&&xc(n.cwd,a)),i=await Promise.all(o.map(a=>Hn(a.sessionId)));for(let a=0;a<o.length;a+=1){let d=o[a],c=i[a],u=nn(d,c.hasContent);if(!s.includeRow(n,u))continue;let l=c.mtime??d.updatedAt;r.push({sessionId:d.sessionId,upstreamSessionId:d.upstreamSessionId,cwd:d.cwd,workspace:d.workspace,title:d.title,agentId:d.agentId,currentModel:d.currentModel,currentUsage:Fn(d.currentUsage),importedFromMachine:d.importedFromMachine,importedFromUpstreamSessionId:d.importedFromUpstreamSessionId,parentSessionId:d.parentSessionId,forkedFromSessionId:d.forkedFromSessionId,forkedFromMessageId:d.forkedFromMessageId,side:d.side,originatingClient:d.originatingClient,interactive:u,priority:d.priority,createdAt:d.createdAt,updatedAt:l,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,compactionState:d.compactionState,forkSynthesisState:d.forkSynthesisState,...Wt(d)})}return r}async exportBundle(e,t={}){let n=await this.store.read(e);if(!n)return;let r;if(n.lineageId)r=n;else{let c=En(),u={...n,lineageId:c};await this.enqueueMetaWrite(e,async()=>{let l=await this.store.read(e);l&&(l.lineageId||await this.store.write({...l,lineageId:c}))}).catch(()=>{}),r=u}let o=t.tools??"inline",i=t.includeArchivedHistory?await this.loadArchivedHistory(e,o):await this.histories.load(e,o==="references"?{tools:"references"}:{}).catch(()=>[]),a=await Pc(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let d={};for(let c of kc(i)){let u=await Vi(e,c);u&&(d[c]=u.toString("base64"))}return{record:r,history:i,promptHistory:a,toolBlobs:d}}async loadArchivedHistory(e,t){let n=await this.histories.loadArchives(e),r=await this.histories.load(e,{tools:"references",maxEntries:1/0}),o=[...n,...r];return t==="references"?o:this.histories.hydrate(e,o)}async importBundle(e,t={}){let n=await this.store.findByLineageId(e.session.lineageId);if(n){if(!t.replace){let i=new Error(`bundle already imported as ${n.sessionId}`);throw i.code=x.BundleAlreadyImported,i.existingSessionId=n.sessionId,i}let o=this.sessions.get(n.sessionId);return o&&await o.close({deleteRecord:!1,by:"bundle-import-overwrite"}).catch(()=>{}),await this.writeImportedRecord({sessionId:n.sessionId,bundle:e,preservedCreatedAt:n.createdAt,cwd:t.cwd}),{sessionId:n.sessionId,importedFromSessionId:e.session.sessionId,replaced:!0}}let r=`${ye}${Rt()}`;return await this.writeImportedRecord({sessionId:r,bundle:e,cwd:t.cwd}),{sessionId:r,importedFromSessionId:e.session.sessionId,replaced:!1}}async forkSession(e,t={}){let n=await this.store.read(e);if(!n){let b=new Error(`source session not found: ${e}`);throw b.code=x.SessionNotFound,b}let r=t.agentId??n.agentId,o=r!==n.agentId;if(o&&!await this.registry.getAgent(r)){let I=new Error(`agent ${r} not found in registry`);throw I.code=x.AgentNotInstalled,I}let i=await this.histories.load(e).catch(()=>[]),a=i,d,c=t.mode??(t.side?"verbatim":"synthesis"),u,l,p,f=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let b=$n(Wo(i),t.forkAt);if(b<0){let I=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw I.code=x.InvalidParams,I}d=t.forkAt,a=i.slice(0,b+1)}else{let b=Oh(i);b?(d=b.messageId,a=i.slice(0,b.index+1)):(d="",a=i.slice(0,0))}else{if(t.forkAt!==void 0&&t.forkAt!==""){let I=$n(Wo(i),t.forkAt);if(I<0){let C=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw C.code=x.InvalidParams,C}d=t.forkAt,a=i.slice(0,I+1)}else d="",a=i;let b=await this.registry.getAgent(r);if(!b){let I=new Error(`agent ${r} not found in registry`);throw I.code=x.AgentNotInstalled,I}p=b,l=n.currentModel,u="running"}let h=await Pc(e),k=c==="synthesis",m={...n,lineageId:En(),agentId:r,interactive:!1,...u!==void 0?{forkSynthesisState:u}:{},summarizedThroughEntry:a.length,...t.title!==void 0?{title:t.title}:{},currentUsage:void 0,...o?{currentModel:void 0,currentMode:void 0,agentCommands:void 0,agentModes:void 0,agentModels:void 0}:{},...t.model!==void 0?{currentModel:t.model}:{}},g=On({record:m,history:a,promptHistory:h.length>0?h:void 0,hydraVersion:ue,machine:bt()}),y=`${ye}${Rt()}`,w=t.cwd,v;if(t.cwd===void 0&&n.workspace!==void 0){let b=await this.deriveForkWorkspace(n.workspace,`${n.workspace.label}-fork-${y.slice(-6)}`);b!==void 0?(v=b,w=b.path):(w=n.workspace.sourceCwd,this.logger?.warn?.(`fork ${y}: could not derive an isolated workspace from ${n.workspace.path}; running unisolated in ${w}`))}await this.writeImportedRecord({sessionId:y,bundle:g,cwd:w,...v!==void 0?{workspace:v}:{},forkedFromSessionId:e,forkedFromMessageId:d,...t.side!==void 0?{side:{...t.side.selection!==void 0?{selection:t.side.selection}:{},..._a(a)}}:{},...u!==void 0?{forkSynthesisState:u}:{}});let S=k?(async()=>{try{let b=await _e(p,[],{npmRegistry:this.npmRegistry}),I=await Ns({agentId:r,cwd:t.cwd??T.sessionDir(e),plan:b,history:a,modelId:l,sessionId:e,logger:this.logger,timeoutMs:f});I&&I.synopsis?await this.mutateRecord(y,{synopsis:I.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(y,{},["forkSynthesisState"]))}catch(b){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${b.message}`);try{await this.mutateRecord(y,{},["forkSynthesisState"])}catch(I){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${I.message}`)}}})():Promise.resolve();if(t.prompt!==void 0&&t.prompt.trim()!==""){let b=t.prompt;S.catch(()=>{}).then(()=>this.deliverHeadlessPrompt(y,b)).catch(I=>{this.logger?.warn(`forkSession(${e}): headless prompt delivery to ${y} failed: ${I.message}`)})}return{sessionId:y,forkedFromSessionId:e,forkedAt:d}}async deliverHeadlessPrompt(e,t){let n=await this.loadFromDisk(e);if(!n){this.logger?.warn(`deliverHeadlessPrompt: ${e} vanished before its prompt could be sent`);return}let r=this.sessions.get(e)??await this.resurrect(n),o=Rh(),i={clientId:`fork-prompt-${Rt().slice(0,8)}`,connection:new qe(o),clientInfo:{name:"hydra-acp-fork",version:ue}};await r.attach(i,"none");try{await r.prompt(i.clientId,{sessionId:e,prompt:[{type:"text",text:t}]})}finally{r.detach(i.clientId),o.close()}}async writeImportedRecord(e){if(await this.histories.rewrite(e.sessionId,e.bundle.history),e.bundle.toolBlobs)for(let[o,i]of Object.entries(e.bundle.toolBlobs))await Gi(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await xt.utimes(T.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await Ac(T.tuiHistoryFile(e.sessionId),e.bundle.promptHistory).catch(()=>{});let n=new Date().toISOString(),r=e.forkedFromSessionId!==void 0;await this.enqueueMetaWrite(e.sessionId,async()=>{await this.store.write({sessionId:e.sessionId,lineageId:e.bundle.session.lineageId,upstreamSessionId:"",...r?{forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,...e.side!==void 0?{side:e.side}:{}}:{importedFromSessionId:e.bundle.session.sessionId,importedFromUpstreamSessionId:e.bundle.session.upstreamSessionId,importedFromMachine:e.bundle.exportedFrom.machine},agentId:e.bundle.session.agentId,cwd:e.cwd??e.bundle.session.cwd,workspace:e.workspace,title:e.bundle.session.title,synopsis:e.bundle.session.synopsis,summarizedThroughEntry:e.bundle.session.summarizedThroughEntry,...e.forkSynthesisState!==void 0?{forkSynthesisState:e.forkSynthesisState}:{},currentModel:e.bundle.session.currentModel,currentMode:e.bundle.session.currentMode,currentUsage:e.bundle.session.currentUsage,agentCommands:e.bundle.session.agentCommands,agentModes:e.bundle.session.agentModes,interactive:e.bundle.session.interactive,originatingClient:e.bundle.session.originatingClient,priority:e.bundle.session.priority,attentionFlags:[],createdAt:e.preservedCreatedAt??n,updatedAt:e.bundle.session.updatedAt})})}async agentStoreKey(e,t){let n=t.get(e);if(n!==void 0)return n;let r=e;try{let o=await this.registry.getAgent(e);o&&(r=zr(o))}catch{}return t.set(e,r),r}async tombstoneAllGenerations(e,t,n){let r=await this.store.read(e).catch(()=>{}),o=new Map;for(let d of r?.upstreamGenerations??[])d.upstreamSessionId&&o.set(`${d.agentId}::${d.upstreamSessionId}`,{agentId:d.agentId,upstreamSessionId:d.upstreamSessionId});o.set(`${t.agentId}::${t.upstreamSessionId}`,{agentId:t.agentId,upstreamSessionId:t.upstreamSessionId});let i=new Date().toISOString(),a=new Map;for(let d of o.values())await this.tombstones.add({agentId:await this.agentStoreKey(d.agentId,a),upstreamSessionId:d.upstreamSessionId,sessionId:e,deletedAt:i,upstreamUpdatedAt:t.upstreamUpdatedAt,cwd:t.cwd,...t.title!==void 0?{title:t.title}:{},reason:n,...t.interactive!==void 0?{interactive:t.interactive}:{}}).catch(()=>{})}async deleteRecord(e,t="user"){let n=await this.store.read(e);if(!n)return!1;if(n.upstreamSessionId){let r=await Hn(e),o=nn(n,r.hasContent);await this.tombstoneAllGenerations(e,{agentId:n.agentId,upstreamSessionId:n.upstreamSessionId,upstreamUpdatedAt:n.updatedAt,cwd:n.cwd,...n.title!==void 0?{title:n.title}:{},...o!==void 0?{interactive:o}:{}},t)}return n.workspace!==void 0&&await this.releaseWorkspace(n.workspace,e).catch(()=>{}),await this.store.delete(e).catch(()=>{}),await this.histories.delete(e).catch(()=>{}),this.invalidateListCache(),!0}async waitForDeletion(e){let t=this.pendingDeletions.get(e);t&&await t}async isTombstoned(e,t){let n=await this.agentStoreKey(e,new Map);return(await this.tombstones.read(n,t).catch(()=>{})??(n!==e?await this.tombstones.read(e,t).catch(()=>{}):void 0))?.reason==="user"}async hasRecord(e){return await this.store.read(e).catch(()=>{})!==void 0}async isRetiredGeneration(e,t){let n=await this.store.read(e).catch(()=>{});return!n||n.upstreamSessionId===t?!1:(n.upstreamGenerations??[]).some(r=>r.upstreamSessionId===t)}async clearWorkspaceBinding(e){if(this.get(e)!==void 0)return"live";let t=await this.store.read(e).catch(()=>{});if(!t)return"missing";let n=t.workspace?.sourceCwd;return await this.mutateRecord(e,n!==void 0?{cwd:n}:{},["workspace"]),"cleared"}async setCwd(e,t){if(this.get(e)!==void 0)return"live";let n=await this.store.read(e).catch(()=>{});return n?n.workspace!==void 0?"bound":await this.dirExists(t)?(await this.mutateRecord(e,{cwd:t}),this.invalidateListCache(),"set"):"not-a-directory":"missing"}async setPriority(e,t){let n=this.get(e);if(n)return n.setPriority(t),!0;if(!await this.hasRecord(e))return!1;let r=t===void 0||t<=0?void 0:Math.floor(t);return await this.persistPriority(e,r),!0}async persistPriority(e,t){t===void 0?await this.mutateRecord(e,{},["priority"]):await this.mutateRecord(e,{priority:t}),this.invalidateListCache()}async setTitle(e,t){let n=this.get(e);return n?(await n.retitle(t),!0):await this.hasRecord(e)?(await this.persistTitle(e,t),!0):!1}async persistTitle(e,t){await this.mutateRecord(e,{title:t})}async persistSynopsis(e,t,n){await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:n})}async persistAgentChange(e,t,n,r={}){await this.mutateRecord(e,{agentId:t,upstreamSessionId:n},void 0,o=>({upstreamGenerations:$c(o,t,n,void 0,r)}))}async persistSnapshot(e,t){let n={};t.currentModel!==void 0&&(n.currentModel=t.currentModel),t.currentMode!==void 0&&(n.currentMode=t.currentMode),t.currentUsage!==void 0&&(n.currentUsage=t.currentUsage),t.agentCommands!==void 0&&(n.agentCommands=t.agentCommands),t.agentModes!==void 0&&(n.agentModes=t.agentModes),t.agentModels!==void 0&&(n.agentModels=t.agentModels),t.configOptionValues!==void 0&&(n.configOptionValues=t.configOptionValues),t.interactive!==void 0&&(n.interactive=t.interactive),t.cwd!==void 0&&(n.cwd=t.cwd),await this.mutateRecord(e,n)}async setRead(e,t){let n=this.sessions.get(e);if(n)return n.setRead(t),!0;let r=!1;return await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;r=!0;let i=ms(o,t);i!==void 0&&await this.store.write({...o,readAt:i})}),this.invalidateListCache(),r}async persistReadState(e,t){await this.enqueueMetaWrite(e,async()=>{let n=await this.store.read(e);n&&await this.store.write({...n,lastTurnEndedAt:t.lastTurnEndedAt,readAt:t.readAt})})}async mutateRecord(e,t,n=[],r){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o,...t,...r?r(o):{},updatedAt:new Date().toISOString()};for(let a of n)delete i[a];await this.store.write(i)})}static EXTENSION_STATE_CAP_BYTES=64*1024;async getExtensionState(e,t){return(await this.store.read(e))?.extensionState?.[t]??{}}async getExtensionStateKey(e,t,n){return(await this.getExtensionState(e,t))[n]}async setExtensionStateKey(e,t,n,r){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o.extensionState??{}},a={...i[t]??{},[n]:r},d=Buffer.byteLength(JSON.stringify(a),"utf8");if(d>s.EXTENSION_STATE_CAP_BYTES)throw new Error(`extension_state: bucket for ${t} would be ${d} bytes; cap is ${s.EXTENSION_STATE_CAP_BYTES}`);i[t]=a;let c={...o,extensionState:i,updatedAt:new Date().toISOString()};await this.store.write(c)})}async deleteExtensionStateKey(e,t,n){await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r?.extensionState?.[t])return;let o={...r.extensionState},i={...o[t]};if(!(n in i))return;delete i[n],Object.keys(i).length===0?delete o[t]:o[t]=i;let a={...r,extensionState:o,updatedAt:new Date().toISOString()};await this.store.write(a)})}enqueueMetaWrite(e,t){return this.enqueueKeyed(this.metaWriteQueues,e,t)}enqueueKeyed(e,t,n){let o=(e.get(t)??Promise.resolve()).catch(()=>{}).then(n),i=o.catch(()=>{});return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)}),o}liveSessionsIn(e,t){let n=[];for(let r of this.sessions.values())r.sessionId!==t&&r.workspace?.path===e&&n.push(r);return n}async closeAll(){let e=[...this.sessions.values()];await Promise.allSettled(e.map(t=>t.close({deleteRecord:!1,by:"daemon-shutdown"}))),this.sessions.clear()}async flushSynopsis(e){await this.synopsisCoordinator.flush(e)}async shutdownSynopsis(){await this.synopsisCoordinator.shutdown()}scheduleSynopsis(e){this.synopsisCoordinator.schedule(e)}scheduleCompaction(e,t){if(t?.targetAgentId){this.mutateRecord(e,{pendingAgentSwap:t.targetAgentId}).catch(r=>{this.logger?.warn(`scheduleCompaction: failed to stamp pendingAgentSwap for ${e}: ${r instanceof Error?r.message:String(r)}`)});let n=t.targetAgentId;(async()=>{try{let r=await this.store.read(e),o=await this.histories.load(e,{maxEntries:1/0});if(uc(o)===0){this.logger?.info(`compaction: zero-turn fast-path swap sessionId=${e} target=${n}`),await this.dispatchSynthesisSwap(e,void 0,o.length,n);return}if(!r?.synopsis||r.summarizedThroughEntry===void 0){this.synopsisCoordinator.scheduleCompaction(e,t);return}if(o.length!==r.summarizedThroughEntry){this.synopsisCoordinator.scheduleCompaction(e,t);return}this.logger?.info(`compaction: fast-path swap sessionId=${e} target=${n} (reusing artifact @${r.summarizedThroughEntry})`),await this.dispatchSynthesisSwap(e,r.synopsis,r.summarizedThroughEntry,n)}catch(r){this.logger?.warn(`scheduleCompaction: fast-path check failed for ${e}: ${r instanceof Error?r.message:String(r)} \u2014 falling back to synthesis`),this.synopsisCoordinator.scheduleCompaction(e,t)}})();return}this.synopsisCoordinator.scheduleCompaction(e,t)}getCompactionInFlight(){let e=this.synopsisCoordinator.size();return e.inflight>0||e.queued>0}async getPendingAgentSwap(e){return(await this.store.read(e).catch(()=>{}))?.pendingAgentSwap}async getCompactionState(e){return(await this.store.read(e).catch(()=>{}))?.compactionState}async persistRollbackBreadcrumb(e,t){await this.mutateRecord(e,{},void 0,n=>{let r=n.rollbackBreadcrumb;return r!==void 0&&t.runId!==void 0&&r.runId===t.runId?(this.logger?.info(`compaction: keeping rollback breadcrumb pinned at ${r.previousUpstreamSessionId} for runId=${t.runId} sessionId=${e} (later swap of the same run)`),{}):{rollbackBreadcrumb:t}})}async getUpstreamGenerations(e){return(await this.store.read(e).catch(()=>{}))?.upstreamGenerations??[]}async getRollbackBreadcrumb(e){return(await this.store.read(e).catch(()=>{}))?.rollbackBreadcrumb}emitSwapPhase(e,t,n){let r=this.get(e);if(r){if(t){if(n.phase==="failed"){r.broadcastPendingAgentSwap(null);return}if(n.phase==="converged")return;r.broadcastPendingAgentSwap(t);return}r.broadcastCompactionPhase(n)}}async getSummarizedThroughEntry(e){let t=this.sessions.get(e);return t?t.summarizedThroughEntry:(await this.store.read(e).catch(()=>{}))?.summarizedThroughEntry}async flushMetaWrites(){let e=[...this.metaWriteQueues.values()];e.length!==0&&await Promise.allSettled(e)}async flushHistoryWrites(){await this.histories.flushAll()}async reconcilePermissionFlags(){let e=await this.store.list().catch(()=>[]),t=0;for(let n of e){let r=n.attentionFlags??[],o=r.filter(i=>!(i.source==="daemon"&&i.reason.startsWith("permission:")));if(o.length!==r.length){let i=r.length-o.length;t+=i,await this.mutateRecord(n.sessionId,{attentionFlags:o}).catch(()=>{})}}t>0&&this.logger?.info(`cleared ${t} stale permission attention flags on startup`)}async resumePendingCompactions(){let e=new Set(["requested","running","swap_pending","swap_deferred"]),t=await this.store.list().catch(()=>[]);for(let n of t){let r=n.compactionState;if(r!=null){if(!e.has(r.status)){this.logger?.info(`compaction: not resuming sessionId=${n.sessionId} status=${r.status} (terminal \u2014 user must re-trigger explicitly)`);continue}this.logger?.info(`compaction: resuming sessionId=${n.sessionId} status=${r.status} from prior daemon`);try{this.scheduleCompaction(n.sessionId)}catch(o){this.logger?.warn(`compaction: resume failed for sessionId=${n.sessionId}: ${o instanceof Error?o.message:String(o)}`)}}}}async resumePendingAgentSwaps(){let e=await this.store.list().catch(()=>[]);for(let t of e){let n=t.pendingAgentSwap;if(n)try{let r=await this.histories.load(t.sessionId).catch(()=>[]);t.synopsis!==void 0&&t.summarizedThroughEntry!==void 0&&t.summarizedThroughEntry>=r.length&&t.synopsis?(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${n} with persisted synopsis (history=${r.length})`),await this.dispatchSynthesisSwap(t.sessionId,t.synopsis,t.summarizedThroughEntry??r.length,n)):(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${n} via fresh synthesis (history=${r.length} watermark=${t.summarizedThroughEntry??"(none)"})`),this.scheduleCompaction(t.sessionId,{targetAgentId:n}))}catch(r){this.logger?.warn(`agent-swap: resume failed for sessionId=${t.sessionId}: ${r instanceof Error?r.message:String(r)}`)}}}async resurrectPendingQueues(){let e=await this.store.list().catch(()=>[]);for(let t of e){let n=await Id(t.sessionId).catch(()=>[]);if(n.length===0)continue;let r=Date.now(),o=n.filter(d=>r-d.enqueuedAt<Rc),i=n.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${Rc/1e3}s)`),await In(t.sessionId,o).catch(()=>{})),o.length===0)continue;let a=await this.loadFromDisk(t.sessionId).catch(()=>{});if(!a){this.logger?.warn(`queue replay: no meta for ${t.sessionId}; discarding ${o.length} entr${o.length===1?"y":"ies"}`),await In(t.sessionId,[]).catch(()=>{});continue}try{let d=await this.resurrect(a);this.logger?.info(`queue replay: resurrected ${t.sessionId} and replaying ${o.length} prompt(s)`),d.replayPersistedQueue(o)}catch(d){this.logger?.warn(`queue replay: failed to resurrect ${t.sessionId}: ${d.message}`)}}}};function xh(s,e){if(typeof s!="string"||s.length===0)return!1;let t=jn.resolve(s),n=jn.resolve(e);return t===n||t.startsWith(n+jn.sep)}function Eh(s){return s!==void 0&&/^\{\s*"session_id"\s*:\s*"[^"]*"\s*,\s*"(?:transcript_path|cwd|permission_mode|hook_event_name)"\s*:/.test(s)}function xc(s,e){if(s===void 0||s.length===0)return!0;let t=zo(s);if(zo(e.cwd)===t)return!0;let n=e.workspace?.sourceCwd;return n!==void 0&&zo(n)===t}function zo(s){return s.length>1&&s.endsWith("/")?s.replace(/\/+$/,""):s}function Th(s,e){let n=(s.mergedAvailableCommands().length>0?s.agentOnlyAdvertisedCommands().map(p=>p.description!==void 0?{name:p.name,description:p.description}:{name:p.name}):void 0)??e?.agentCommands,r=s.availableModes(),i=(r.length>0?r.map(p=>{let f={id:p.id};return p.name!==void 0&&(f.name=p.name),p.description!==void 0&&(f.description=p.description),f}):void 0)??e?.agentModes,a=s.availableModels(),c=(a.length>0?a.map(p=>{let f={modelId:p.modelId};return p.name!==void 0&&(f.name=p.name),p.description!==void 0&&(f.description=p.description),f}):void 0)??e?.agentModels,u=s.extraConfigOptionValues(),l=Object.keys(u).length>0?u:e?.configOptionValues;return Eo({sessionId:s.sessionId,lineageId:e?.lineageId??En(),upstreamSessionId:s.upstreamSessionId,importedFromSessionId:e?.importedFromSessionId,importedFromUpstreamSessionId:e?.importedFromUpstreamSessionId,importedFromMachine:e?.importedFromMachine,agentId:s.agentId,cwd:s.cwd,title:s.title,synopsis:e?.synopsis,summarizedThroughEntry:e?.summarizedThroughEntry,agentArgs:s.agentArgs,currentModel:s.currentModel??e?.currentModel,currentMode:s.currentMode??e?.currentMode,currentUsage:_c(s.persistableUsage)??e?.currentUsage,agentCommands:n,agentModes:i,agentModels:c,configOptionValues:l,parentSessionId:s.parentSessionId??e?.parentSessionId,forkedFromSessionId:s.forkedFromSessionId??e?.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId??e?.forkedFromMessageId,side:s.side??e?.side,originatingClient:s.originatingClient??e?.originatingClient,interactive:s.interactive??e?.interactive,priority:s.priority??e?.priority,lastTurnEndedAt:s.lastTurnEndedAt??e?.lastTurnEndedAt,readAt:s.readAt??e?.readAt,forwardedEnv:s.forwardedEnv??e?.forwardedEnv,workspace:s.workspace,attentionFlags:s.listAttentionFlags(),extensionState:e?.extensionState,upstreamGenerations:e?$c(e,s.agentId,s.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(s.createdAt).toISOString()})}function _c(s){if(!s)return;let e={};return s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size),s.costAmount!==void 0&&(e.costAmount=s.costAmount),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),s.cumulativeCost!==void 0&&(e.cumulativeCost=s.cumulativeCost),Object.keys(e).length>0?e:void 0}function Ph(s){return s?{...s}:void 0}function Mh(s){return(s.extendsChain??[s.id]).some(t=>t==="claude-acp"||t.startsWith("claude-acp-"))}var _h=[{type:"system",subtype:"background_tasks_changed"}];function Jo(s,e={}){if(!Mh(s))return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t,emitRawSDKMessages:_h}}}function Us(s,e){let t=e.fromObject(s);if(t!==void 0)return t;let n=s[e.nestedKey];if(n&&typeof n=="object"&&!Array.isArray(n)){let i=e.fromObject(n);if(i!==void 0)return i}let r=s._meta;if(r&&typeof r=="object"&&!Array.isArray(r)){for(let[i,a]of Object.entries(r))if(i!=="hydra-acp"&&a&&typeof a=="object"&&!Array.isArray(a)){let d=e.fromObject(a);if(d!==void 0)return d}}let o=$h(s,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function Vo(s){return Us(s,{nestedKey:"models",configId:"model",fromObject:e=>Ie(e.currentModelId)??Ie(e.currentModel)??Ie(e.modelId)??Ie(e.model),fromConfig:e=>Ie(e.currentValue)})}function ht(s,e){if(!s||typeof s!="object")return s;let t=s;if(t.code!==x.AuthRequired)return s;let n=c=>!!c&&typeof c=="object"&&!Array.isArray(c),r=n(t.data)?t.data:{},o=n(r._meta)?r._meta:{},i=n(o["hydra-acp"])?o["hydra-acp"]:{},a=typeof t.message=="string"?t.message:"authentication required",d=new Error(a);return d.code=x.AuthRequired,d.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function Ec(s){return/^[A-Za-z0-9_\-./=:@]+$/.test(s)?s:`'${s.replace(/'/g,"'\\''")}'`}function Tc(s,e,t,n){if(s&&typeof s=="object"&&s.code===x.AuthRequired)return s;let r=s instanceof Error?s.message:String(s),o=r.includes("stderr:"),i=o?"":e.stderrTailText(),a=n?`to reproduce: (cd ${Ec(n.cwd)} && ${[n.command,...n.args].map(Ec).join(" ")})`:"";if(!i&&!a)return s;let d=[o?r:`agent ${t} failed to start: ${r}`];i&&d.push(`stderr: ${i}`),a&&d.push(a);let c=new Error(d.join(`
189
- `));if(s&&typeof s=="object"){let u=s;typeof u.code=="number"&&(c.code=u.code),u.data!==void 0&&(c.data=u.data)}return c}function Nn(s){return s._meta?.steering?.supported===!0}function Dn(s){if(!Array.isArray(s))return;let e=[];for(let t of s){if(!t||typeof t!="object")continue;let n=t;if(typeof n.id!="string")continue;let r=typeof n.description=="string"?n.description:"",o=n.type==="agent"||n.type==="terminal"?n.type:void 0,i=typeof n.name=="string"?n.name:void 0,a=n._meta,d=a!==null&&typeof a=="object"&&!Array.isArray(a)?a:void 0;e.push({id:n.id,description:r,...o&&{type:o},...i!==void 0&&{name:i},...d&&{_meta:d}})}return e.length>0?e:void 0}function Ie(s){if(typeof s!="string")return;let e=s.trim();return e.length>0?e:void 0}function $h(s,e){let t=s.configOptions;if(Array.isArray(t))for(let n of t){if(!n||typeof n!="object"||Array.isArray(n))continue;let r=n;if(r.id===e)return r}}function en(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.configOptions)}function tn(s){let e=s.configOptions;if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!n||typeof n!="object"||Array.isArray(n))continue;let r=n,o=Ie(r.id);if(!o||o==="model"||o==="mode"||o==="agent")continue;let i=vo(r.options);if(i.length===0)continue;let a=Ie(r.description);t.push({id:o,name:Ie(r.name)??o,...a?{description:a}:{},category:Ie(r.category)??"other",type:"select",currentValue:Ie(r.currentValue)??i[0].value,options:i})}return t}function mt(s){return s.length>0?s:void 0}function Go(s){return Us(s,{nestedKey:"models",configId:"model",fromObject:e=>{let t=Cn(e.availableModels);return t.length>0?t:void 0},fromConfig:e=>{let t=Cn(e.options);return t.length>0?t:void 0}})??[]}function Ko(s){return Us(s,{nestedKey:"modes",configId:"mode",fromObject:e=>{let t=bs(e.availableModes);return t.length>0?t:void 0},fromConfig:e=>{let t=bs(e.options);return t.length>0?t:void 0}})??[]}function Qo(s){return Us(s,{nestedKey:"modes",configId:"mode",fromObject:e=>Ie(e.currentModeId)??Ie(e.currentMode)??Ie(e.modeId)??Ie(e.mode),fromConfig:e=>Ie(e.currentValue)})}function Oh(s){for(let e=s.length-1;e>=0;e--){let t=s[e];if(!t||t.method!=="session/update")continue;let n=t.params?.update;if(n?.sessionUpdate==="turn_complete"&&!(typeof n.messageId!="string"||n.messageId.length===0))return{index:e,messageId:n.messageId}}}async function Pc(s){try{let e=await xt.readFile(T.tuiHistoryFile(s),"utf8"),t=[];for(let n of e.split(`
190
- `))if(n.length!==0)try{let r=JSON.parse(n);typeof r=="string"&&t.push(r)}catch{}return t}catch{return[]}}function $c(s,e,t,n=new Date().toISOString(),r={}){let{retiredCost:o,retiredUsed:i,startedUsed:a,lifetimeCost:d,reason:c,runId:u}=r,l=h=>d!==void 0&&h.lifetimeCostAtStart!==void 0?Math.max(0,d-h.lifetimeCostAtStart):o,p=s.upstreamGenerations&&s.upstreamGenerations.length>0?[...s.upstreamGenerations]:s.upstreamSessionId?[{upstreamSessionId:s.upstreamSessionId,agentId:s.agentId}]:[],f=p[p.length-1];if(f&&f.upstreamSessionId===t){if(p.length>=2){let h=p[p.length-2];if(h){let k=l(h);p[p.length-2]={...h,...k!==void 0&&h.cost===void 0?{cost:k}:{},...i!==void 0&&h.usedAtEnd===void 0?{usedAtEnd:i}:{}}}}return(c!==void 0&&f.reason===void 0||a!==void 0&&f.usedAtStart===void 0||d!==void 0&&f.lifetimeCostAtStart===void 0)&&(p[p.length-1]={...f,...c!==void 0&&f.reason===void 0?{reason:c,...u!==void 0?{runId:u}:{}}:{},...a!==void 0&&f.usedAtStart===void 0?{usedAtStart:a}:{},...d!==void 0&&f.lifetimeCostAtStart===void 0?{lifetimeCostAtStart:d}:{}}),p}return f&&f.endedAt===void 0&&(p[p.length-1]={...f,endedAt:n,...(()=>{let h=l(f);return h!==void 0?{cost:h}:{}})(),...i!==void 0?{usedAtEnd:i}:{}}),p.push({upstreamSessionId:t,agentId:e,startedAt:n,...c!==void 0?{reason:c}:{},...u!==void 0?{runId:u}:{},...a!==void 0?{usedAtStart:a}:{},...d!==void 0?{lifetimeCostAtStart:d}:{}}),p}async function Hn(s){try{let e=await xt.stat(T.historyFile(s));return{mtime:new Date(e.mtimeMs).toISOString(),hasContent:e.size>0}}catch{return{hasContent:!1}}}function nn(s,e){return s.interactive!==void 0?s.interactive:s.originatingClient?.name===Fs?!1:e?!0:void 0}import{spawn as Fh}from"child_process";import*as qs from"fs";import*as rt from"fs/promises";import*as zs from"path";import Nh from"pino-roll";var Bs=class{windowMs;maxFailures;now;recentExits=[];tripped_;constructor(e={}){this.windowMs=e.windowMs??3e5,this.maxFailures=e.maxFailuresInWindow??10,this.now=e.now??Date.now}recordExit(e,t,n){if(e===78){let i=`exited with code 78 (unrecoverable); fix and run \`${n}s start ${t}\``;return this.tripped_=i,{tripped:i}}let r=this.now();this.recentExits.push(r);let o=r-this.windowMs;for(;this.recentExits.length>0&&this.recentExits[0]<o;)this.recentExits.shift();if(this.recentExits.length>this.maxFailures){let i=Math.round(this.windowMs/6e4),a=`${this.recentExits.length} exits in ${i}m (crash loop); fix and run \`${n}s start ${t}\``;return this.tripped_=a,{tripped:a}}return"restart"}reset(){this.recentExits=[],this.tripped_=void 0}get tripped(){return this.tripped_}};import*as Oc from"fs/promises";import*as Yo from"path";var Ws=process.platform!=="win32";var Dh=1e3,Hh=6e4,Xo=3e3,sn=class{entries=new Map;stopping=!1;context;tokenRegistry;breakerOptions;restartBaseMs;restartCapMs;adapter;constructor(e,t,n,r={}){this.adapter=t,this.context=n,this.tokenRegistry=r.tokenRegistry,this.breakerOptions=r.breakerOptions,this.restartBaseMs=r.restartBaseMs??Dh,this.restartCapMs=r.restartCapMs??Hh;for(let o of e)this.entries.set(o.name,this.makeEntry(o))}setContext(e){this.context=e}reportVersion(e,t){let n=this.entries.get(e);n&&(n.version=t)}async start(){if(!this.context)throw new Error(`${this.managerName()}: setContext must be called before start`);await rt.mkdir(this.adapter.paths.dir(),{recursive:!0}),await this.reapOrphans();let e=[];for(let t of this.entries.values())t.config.enabled&&e.push(this.spawn(t,0));await Promise.all(e)}async stop(){this.stopping=!0;let e=[];for(let t of this.entries.values()){t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let n=t.child;if(n){try{n.kill("SIGTERM")}catch{}e.push(new Promise(r=>{if(n.exitCode!==null||n.signalCode!==null){r();return}let o=setTimeout(()=>{try{n.kill("SIGKILL")}catch{}r()},Xo);n.on("exit",()=>{clearTimeout(o),r()})}))}}await Promise.allSettled(e);for(let t of this.entries.values()){try{t.logStream?.end()}catch{}t.child=void 0,t.logStream=void 0,t.pid=void 0}}list(){return[...this.entries.values()].map(e=>this.infoFor(e))}get(e){let t=this.entries.get(e);return t?this.infoFor(t):void 0}has(e){return this.entries.has(e)}async startByName(e){let t=this.entries.get(e);if(!t)throw Ln(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");if(t.child)throw Ln(new Error(`${this.adapter.kind} ${e} already running`),"CONFLICT");return t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0),t.manuallyStopped=!1,t.restartCount=0,t.breaker.reset(),t.failureReason=void 0,await this.spawn(t,0),this.infoFor(t)}async stopByName(e){let t=this.entries.get(e);if(!t)throw Ln(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");t.manuallyStopped=!0,t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let n=t.child;return n?(await this.terminate(t,n),this.infoFor(t)):this.infoFor(t)}async restartByName(e){return await this.stopByName(e),this.startByName(e)}register(e){if(this.entries.has(e.name))throw Ln(new Error(`${this.adapter.kind} ${e.name} already exists`),"CONFLICT");if(!this.context)throw new Error(`${this.managerName()}: setContext must be called before register`);let t=this.makeEntry(e);return this.entries.set(e.name,t),e.enabled&&this.spawn(t,0).catch(n=>{t.failureReason=`spawn: ${n.message}`}),this.infoFor(t)}async unregister(e){let t=this.entries.get(e);if(!t)throw Ln(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");t.manuallyStopped=!0,t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let n=t.child;n&&await this.terminate(t,n);try{t.logStream?.end()}catch{}this.entries.delete(e)}async terminate(e,t){if(t.exitCode!==null||t.signalCode!==null)return;let n=new Promise(o=>{e.exitWaiters.push(o)});try{t.kill("SIGTERM")}catch{}let r=setTimeout(()=>{try{t.kill("SIGKILL")}catch{}},Xo);typeof r.unref=="function"&&r.unref();try{await n}finally{clearTimeout(r)}}infoFor(e){let t;return e.failureReason!==void 0?t="failed":e.child?t="running":e.restartTimer?t="restarting":e.config.enabled?t="stopped":t="disabled",{name:e.config.name,status:t,pid:e.pid,enabled:e.config.enabled,restartCount:e.restartCount,startedAt:e.startedAt,lastExitCode:e.lastExitCode,logPath:this.adapter.paths.logFile(e.config.name),version:e.version,failureReason:e.failureReason}}makeEntry(e){return{config:e,child:void 0,logStream:void 0,restartTimer:void 0,pid:void 0,startedAt:void 0,restartCount:0,lastExitCode:void 0,manuallyStopped:!1,exitWaiters:[],version:void 0,processToken:void 0,breaker:new Bs(this.breakerOptions),failureReason:void 0}}async reapOrphans(){let e;try{e=await rt.readdir(this.adapter.paths.dir(),{withFileTypes:!0})}catch(t){if(t.code==="ENOENT")return;throw t}for(let t of e){if(!t.isDirectory())continue;let n=this.adapter.paths.pidFile(t.name),r;try{let o=await rt.readFile(n,"utf8"),i=Number.parseInt(o.trim(),10);Number.isInteger(i)&&i>0&&(r=i)}catch{}if(typeof r=="number"&&Zo(r)){try{process.kill(r,"SIGTERM")}catch{}let o=Date.now()+Xo;for(;Date.now()<o&&Zo(r);)await new Promise(i=>setTimeout(i,50));if(Zo(r))try{process.kill(r,"SIGKILL")}catch{}}await rt.unlink(n).catch(()=>{})}}async spawn(e,t){if(this.stopping||e.manuallyStopped)return;let n=this.context;if(!n)throw new Error(`${this.managerName()}.spawn called before setContext`);let r=e.config,o=r.command.length>0?r.command:[r.name],i=zs.dirname(this.adapter.paths.logFile(r.name)),a;try{await rt.mkdir(i,{recursive:!0}),a=await Nh({file:zs.join(i,`${r.name}.log`),size:"5m",mkdir:!0,symlink:Ws,limit:{count:5}}),a.on("error",m=>{e.failureReason=`log stream: ${m.message}`})}catch(m){if(this.stopping||e.manuallyStopped)return;e.failureReason=`log setup: ${m.message}`,this.scheduleRestart(e,t+1);return}if(this.stopping||e.manuallyStopped){try{a.end()}catch{}return}a.write(`[hydra-acp] ${new Date().toISOString()} starting ${this.adapter.kind} ${r.name} (attempt ${t+1})
191
- `);let d=this.tokenRegistry?.mint(r.name,this.adapter.tokenRole)??n.serviceToken;e.processToken=d,e.version=void 0;let c={...ts(),HYDRA_ACP_DAEMON_URL:n.daemonUrl,HYDRA_ACP_DAEMON_HOST:n.daemonHost,HYDRA_ACP_DAEMON_PORT:String(n.daemonPort),HYDRA_ACP_TOKEN:d,HYDRA_ACP_WS_URL:n.daemonWsUrl,HYDRA_ACP_HOME:n.hydraHome,[this.adapter.nameEnvVar]:r.name,...r.env},[u,...l]=o;if(u===void 0){a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} has empty command
192
- `),a.end();return}let p=ce(u),f=[...l,...r.args].map(ce),h;try{let m=Ft(p,f);h=Fh(m.command,m.args,{env:c,stdio:["ignore","pipe","pipe"],detached:!1,shell:m.shell,windowsHide:!0})}catch(m){a.write(`[hydra-acp] failed to spawn ${r.name}: ${m.message}
193
- `),a.end(),this.scheduleRestart(e,t);return}let k=m=>{try{a.write(typeof m=="string"?m:m.toString())}catch{}};if(h.stdout?.on("data",k),h.stderr?.on("data",k),typeof h.pid=="number")try{qs.writeFileSync(this.adapter.paths.pidFile(r.name),`${h.pid}
179
+ `)}asWorkspace(e){return{path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:e.provider,...e.snapshot!==void 0?{snapshot:e.snapshot}:{},...e.line!==void 0?{line:e.line}:{},...e.vcs!==void 0?{vcs:e.vcs}:{}}}async retireAutosave(e){let t=re(e.provider);if(t===void 0)return;let n=this.asWorkspace(e),r=this.snapshotRefFor(e.label),o=await t.resolveRetained(n,r).catch(()=>{});if(o===void 0)return;let i=tc(e.label,o);return await t.retainSnapshot(n,i,o).then(()=>!0).catch(()=>!1)?(await t.dropSnapshotRef(n,r).catch(()=>{}),i):r}async cleanWorkspace(e,t,n){return await this.enqueueKeyed(this.workspaceQueues,t.path,async()=>{let r=this.liveSessionsIn(t.path,e.sessionId);if(r.length>0)throw new Error(`${$(t.path)} is shared with ${r.map(w=>nt(w.sessionId)).join(", ")}, and a clean would destroy their work too. Clean it from a session that has it to itself.`);let o=await e.quiesceBlocker();if(o!==void 0)throw new Error(o);let i=re(t.provider);if(i===void 0)throw new Error(`no provider "${t.provider}" available to clean this workspace`);if(t.snapshot===void 0||i.capabilities().sharedHistory!==!0)throw new Error(`workspace ${t.label} uses the "${t.provider}" provider, which records no base state to return to, so there is nothing to clean back to. Use \`/hydra workspace discard\` to throw it away instead.`);let a=this.asWorkspace(t),d=t.snapshot,u=(await i.status(a).catch(()=>{}))?.changedPaths.length??0,p=(await i.divergence(t.path,d,"HEAD").catch(()=>{}))?.behind??0,f=await i.currentState(t.path)??"",h=await this.retireAutosave(t);e.broadcastWorkspacePhase({phase:"cleaning",label:t.label});let k=await i.resetTo(t.path,d,{purgeIgnored:n.deep});if(!k.ok)throw new Error(`could not return ${$(t.path)} to its base: ${k.reason??"unknown error"}. Nothing was changed.`);let m=n.deep?await this.applyWorkspaceSetup(t,e.sessionId):void 0;await i.retainSnapshot(a,this.startRefFor(t.label),t.snapshot).catch(()=>{});let g={...t,clean:!0};e.workspace=g,await this.mutateRecord(e.sessionId,{workspace:g}),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:t.sourceCwd,label:t.label,...a.line!==void 0?{branch:a.line}:{}});let y=[`Cleaned ${$(t.path)} back to the state it was created in.`];if(u>0||p>0){let w=[];u>0&&w.push(`${u} uncommitted change(s)`),p>0&&w.push(`${p} commit(s)`),y.push(` discarded ${w.join(" and ")}`)}else y.push(" nothing to discard; it was already at its base");return m!==void 0&&y.push(` ${m}`),h!==void 0&&y.push(` last autosave kept at ${h}: git -C ${t.sourceCwd} checkout ${h}`),p>0&&f.length>0&&y.push(` discarded commits are still at ${f.slice(0,12)} (and in the reflog for ${t.line??"this branch"})`),y.push(`Your uncommitted work in ${$(t.sourceCwd)} was never touched by this.`),y.join(`
180
+ `)})}async mergeWorkspaceIntoSource(e,t){let n=e.sourceCwd,r=e.line;if(r===void 0)throw new Error(`workspace ${e.label} has no line of work to land from`);if(!await this.dirExists(n))throw new Error(`source tree ${$(n)} no longer exists`);let i=re(e.provider),a=this.asWorkspace(e),d=await Ho({source:n,ws:a,startSnapshotRef:this.startRefFor(e.label),baselineRef:this.baselineRefFor(e.label),retainRef:Do(t),provider:i});if(i===void 0)throw new Error(`no provider "${e.provider}" available to land this workspace`);let c=await i.currentState(n);if(c===void 0)throw new Error(`could not read the state of ${$(n)}`);let u=await i.contains(n,{state:c,within:r}),l=[];if(!u){let b=this.get(t),I="";if(b!==void 0)try{let A=await this.syncWorkspaceFromSource(b,e,{onConflict:"abort"});A.ok?(l.push(`
181
+ synced with the source first: ${A.message}`),u=await i.contains(n,{state:c,within:r})):I=`
182
+ A sync was attempted first and could not complete: ${A.message}`}catch(A){I=`
183
+ A sync was attempted first but was refused: ${A instanceof Error?A.message:String(A)}`}if(!u){let A=await i.currentLineName(n)??"the source";throw new Error(`cannot fast-forward ${A} in ${$(n)} to ${r}. The source has moved on since this workspace was created. The source is untouched.${I}
184
+ `+(I.length>0?`Or land it by hand with: git -C ${n} merge ${r}`:`Resolve it in the workspace with \`/hydra workspace sync\` (which leaves the conflict there to fix), or land it by hand with: git -C ${n} merge ${r}`))}}let p=i!==void 0&&i.capabilities().supports.nestedTrees?await i.captureNested(e.path,await i.listNested(e.path)).catch(()=>[]):[],f,h=await i.status(a).catch(()=>{});if(h!==void 0&&h.changedPaths.length>0&&(f=await i.captureWorkingState(e.path,`hydra: uncommitted work in ${e.label}`).catch(()=>{}),f===void 0))throw new Error(`could not capture the uncommitted work in ${$(e.path)}; nothing was changed`);if(!d.clean&&!(await i.resetTo(n,c)).ok)throw new Error(`could not clear ${$(n)} for the merge; your work is preserved at ${d.retainedRef}. Nothing was merged.`);let k=await i.integrate({into:n,from:r,fastForwardOnly:!0});if(!k.ok)throw new Error(`merge failed: ${k.reason??"unknown error"}`);let m=!0;if(f!==void 0){let b=await i.captureDelta(n,k.snapshot,f);b!==void 0&&(m=(await i.applyDelta(n,b)).ok)}let g=await Rt({source:n,capture:d,provider:i});g&&await $n({source:n,ws:a,capture:d,provider:i});let y={applied:[],failed:[]},w=i!==void 0&&i.capabilities().supports.nestedTrees?await i.integrateNested(n,e.path,p).catch(()=>y):y,v=await i.captureWorkingState(n,`hydra: source state after landing ${e.label}`).catch(()=>{});v!==void 0&&await i.retainSnapshot({...a,path:n},this.baselineRefFor(e.label),v).catch(()=>{});let S=[];m||S.push(` WARNING: the workspace's uncommitted changes could not be replayed; they remain reachable from ${r}.`),g||S.push(e.clean===!0?` WARNING: this workspace started clean, so your uncommitted work was never copied in. The whole of it is being replayed now and it overlaps what the agent changed. All of it is preserved at ${d.retainedRef}; recover with: git -C ${n} diff ${d.base} ${d.retainedRef}`:` WARNING: your own edits to ${$(n)} overlap the workspace's changes and could not be replayed on top. They are preserved at ${d.retainedRef}; recover with: git -C ${n} diff ${d.base} ${d.retainedRef}`);for(let b of w.failed)S.push(` WARNING: nested tree ${b.path} was NOT reconciled: ${b.reason}. ${$(n)} now records a different state for it, so it will report it as modified until you resolve that.`);return{merged:`Merged ${r} into ${$(n)}${l.join("")}`,warnings:S}}async applyWorkspaceToSource(e,t){let n=e.sourceCwd;if(!await this.dirExists(n))throw new Error(`source tree ${$(n)} no longer exists`);let r=re(e.provider);if(r===void 0)throw new Error(`no provider "${e.provider}" available to apply this workspace`);if(!r.capabilities().supports.captureWorkingState)throw new Error(`provider "${e.provider}" cannot snapshot a working tree, so there is no change set to apply. Use \`/hydra workspace stop\` to land this workspace instead.`);let o=this.asWorkspace(e);if((await r.status({...o,path:n}).catch(()=>{}))?.hasStagedWork===!0)throw new Error(`${$(n)} already has changes staged for its next commit, and \`apply\` delivers into that same index: the two sets would be indistinguishable, and unstaging one would unstage both. Commit or unstage them first, or use \`/hydra workspace merge\`, which lands the work as commits and does not touch the index.`);let a=await r.currentState(n);if(a===void 0)throw new Error(`could not read the state of ${$(n)}`);let d=e.line,c=d!==void 0&&await r.contains(n,{state:a,within:d}).catch(()=>!1),u=c?a:e.snapshot??"";if(u.length===0)throw new Error(`workspace ${e.label} has no recorded base to measure its changes against, so there is no way to tell its work apart from what the source already had`);let l=await Ho({source:n,ws:o,startSnapshotRef:this.startRefFor(e.label),baselineRef:this.baselineRefFor(e.label),retainRef:Do(t),provider:r}),p=r.capabilities().supports.nestedTrees?(await r.listNested(e.path).catch(()=>[])).filter(w=>w.changedPaths.length>0||w.recorded!==void 0&&w.recorded!==w.actual):[],f=await r.captureWorkingState(e.path,`hydra: apply from ${e.label}`).catch(()=>{});if(f===void 0)throw new Error(`could not snapshot the work in ${$(e.path)}; nothing was changed`);let h=await r.captureDelta(n,u,f);if(h===void 0)throw new Error(`could not work out what ${e.label} changed; ${$(n)} was not touched`);if(h.trim().length===0)return await $n({source:n,ws:o,capture:l,provider:r}),{applied:`Nothing to apply: ${e.label} holds no changes ${$(n)} does not already have.`,warnings:[]};if(!l.clean&&!(await r.resetTo(n,a)).ok)throw new Error(`could not clear ${$(n)} to apply onto; your work is preserved at ${l.retainedRef}. Nothing was applied.`);let k=await r.applyDelta(n,h,{stage:!0,tolerant:!c});if(!k.ok){await r.resetTo(n,a).catch(()=>{});let w=await Rt({source:n,capture:l,provider:r});throw w&&await $n({source:n,ws:o,capture:l,provider:r}),new Error(`could not apply ${e.label} into ${$(n)}: ${k.reason??"the change set did not apply"}.`+(c?"":" The source has moved on since this workspace was created; `/hydra workspace sync` brings those commits in here, which is what lets the change set apply against them.")+(w?` ${$(n)} is as you left it.`:` Your uncommitted work there is preserved at ${l.retainedRef}.`))}let m=await Rt({source:n,capture:l,provider:r});m&&await $n({source:n,ws:o,capture:l,provider:r});let g=await r.captureWorkingState(n,`hydra: source state after applying ${e.label}`).catch(()=>{});g!==void 0&&await r.retainSnapshot({...o,path:n},this.baselineRefFor(e.label),g).catch(()=>{});let y=[];k.alreadyPresent===!0&&y.push(` Nothing was staged: ${$(n)} already had every one of those changes.`),m||y.push(` WARNING: your own edits to ${$(n)} overlap the workspace's changes and could not be replayed on top. They are preserved at ${l.retainedRef}; recover with: git -C ${n} diff ${l.base} ${l.retainedRef}`);for(let w of p)y.push(` WARNING: nested tree ${w.relPath} was NOT included: a change set can only move the pointer to it, not what is inside. Land it with \`/hydra workspace stop\`, or copy that work across by hand.`);return{applied:`Applied ${e.label} into ${$(n)} as staged changes; still working in ${$(e.path)}.
185
+ Nothing was committed: review it with \`git -C ${n} diff --cached\` and commit it however you like. The workspace and its history are untouched.`,warnings:y}}async leaveWorkspace(e,t,n){let r=n.exit!=="detached",o=re(t.provider),i={path:t.path,sourceCwd:t.sourceCwd,label:t.label,provider:t.provider,...t.snapshot!==void 0?{snapshot:t.snapshot}:{},...t.vcs!==void 0?{vcs:t.vcs}:{}},a=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:t.sourceCwd,workspace:void 0,historyLength:a.length,note:`Returned to the source tree at ${t.sourceCwd}`+(n.exit==="landed"?" after merging the workspace.":n.exit==="discarded"?" after discarding the workspace and its work.":" without merging."),...await this.recordSynopsisFor(e.sessionId),left:{path:t.path,removed:r}}),await this.mutateRecord(e.sessionId,{cwd:e.cwd},["workspace"]),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"left",cwd:e.cwd,sourceCwd:t.sourceCwd,integrated:n.exit==="landed"}),o!==void 0&&await this.enqueueKeyed(this.workspaceQueues,t.path,async()=>{let d=this.liveSessionsIn(t.path,e.sessionId);if(d.length>0){this.logger?.info?.(`session workspace: ${e.sessionId} left ${t.path}; ${d.length} live session(s) remain, so it stays`);return}await this.reclaimAfterLastLeaver(o,i,t,e.sessionId,n)})}async reclaimAfterLastLeaver(e,t,n,r,o){await e.unlock(t).catch(()=>{});for(let i of[this.startRefFor(n.label),this.baselineRefFor(n.label)])await e.dropSnapshotRef(t,i).catch(()=>{});o.exit!=="detached"&&(o.exit==="landed"&&await e.dropSnapshotRef(t,this.snapshotRefFor(n.label)).catch(()=>{}),await e.removeWorkspace(t,{force:!0,discardLine:!0}).catch(()=>{}))}async joinDivergence(e,t,n){let[r,o]=await Promise.all([e.captureWorkingState(t,"hydra: source state at join").catch(()=>{}),e.captureWorkingState(n.path,"hydra: workspace state at join").catch(()=>{})]);if(r===void 0||o===void 0)return`could not compare ${$(t)} with ${$(n.path)}, so refusing to join a workspace that may not match your tree`;let i=await Promise.all([r,o].map(a=>e.contentId(t,a).catch(()=>{})));if(!(i[0]!==void 0&&i[0]===i[1]))return`${$(t)} and ${$(n.path)} have diverged, and joining does not carry work across \u2014 whichever side you are not in would be left behind. Land or stash one of them first: \`git -C ${t} stash\` if the difference is yours, or \`/hydra workspace merge\` from the session already in there if it is theirs.`}liveSessionsWithLabel(e,t){let n=[];for(let r of this.sessions.values()){let o=r.workspace;o===void 0||o.sourceCwd!==e||(o.label===t||o.requestedLabel===t)&&n.push(r)}return n}async joinWorkspace(e,t,n,r){let o=re(n.provider);if(o===void 0)throw new Error(`no provider "${n.provider}" to join that workspace with`);if(o.capabilities().supports.captureWorkingState){let i=await this.joinDivergence(o,r,n);if(i!==void 0)throw new Error(i)}return await this.enqueueKeyed(this.workspaceQueues,n.path,async()=>{if(this.sessions.get(t.sessionId)?.workspace?.path!==n.path)throw new Error(`${$(n.path)} was released while joining it; run the command again`);e.broadcastWorkspacePhase({phase:"swapping"});let i=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:n.path,workspace:{path:n.path,sourceCwd:n.sourceCwd,label:n.label,...n.requestedLabel!==void 0?{requestedLabel:n.requestedLabel}:{},provider:n.provider,...n.snapshot!==void 0?{snapshot:n.snapshot}:{},...n.line!==void 0?{line:n.line}:{},...n.vcs!==void 0?{vcs:{...n.vcs}}:{}},historyLength:i.length,note:`Continuing in an isolated workspace at ${n.path}, derived from ${r}, shared with another session.`,...await this.recordSynopsisFor(e.sessionId)}),await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),this.invalidateListCache();let a=n.line;e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:n.sourceCwd,label:n.label,...a!==void 0?{branch:a}:{}});let d=this.liveSessionsIn(n.path,e.sessionId).map(u=>nt(u.sessionId)),c=[`Joined workspace ${$(n.path)}`,` source: ${$(n.sourceCwd)}`];return a!==void 0&&c.push(` branch: ${a}`),c.push(` shared with: ${d.join(", ")}`),c.push(" your edits will interleave with that session's"),c.push("Use `/hydra workspace stop` to leave; the work lands when the last session leaves."),c.join(`
186
+ `)})}async startWorkspace(e,t,n){if(e.workspace!==void 0)throw new Error(`already isolated in ${$(e.workspace.path)}. Use \`/hydra workspace stop\` to merge and return first, or \`detach\` to leave it behind.`);let r=e.cwd,o=re();if(o===void 0)throw new Error("no workspace provider available");let i=await e.quiesceBlocker();if(i!==void 0)throw new Error(i);let a=o.capabilities();if(t!==void 0){let b=this.liveSessionsWithLabel(r,t)[0];if(b!==void 0&&b.workspace!==void 0)return await this.joinWorkspace(e,b,b.workspace,r)}let d,c=[],u=!1,l=!1,p=[],f=[],h=n?.clean===!0;if(a.supports.captureWorkingState){let b=await o.status({path:r,sourceCwd:r,label:"source",provider:o.kind}).catch(()=>{});l=b!==void 0;let I=a.supports.nestedTrees&&b!==void 0&&b.changedPaths.length>0?await o.listNested(r).catch(()=>[]):[];if(b!==void 0&&b.changedPaths.length>0&&h)p=_o(b.changedPaths,I);else if(b!==void 0&&b.changedPaths.length>0&&(c=_o(b.changedPaths,I),f=await o.captureNested(r,I).catch(()=>[]),u=b.hasStagedWork===!0,d=await o.captureWorkingState(r,"hydra: work carried into workspace").catch(()=>{}),d===void 0))throw new Error("could not snapshot your uncommitted work, so refusing to move it. Commit or stash first.")}e.broadcastWorkspacePhase({phase:"provisioning"});let k=await o.createWorkspace({sourceCwd:r,label:t??`s-${e.sessionId.slice(-8)}`});if(!k.ok)throw e.broadcastWorkspacePhase({phase:"failed",error:k.reason}),new Error(k.reason);let m=k.workspace,g=this.startRefFor(m.label),y,w=!1,v=[];try{a.locking&&await o.lock(m,`session ${e.sessionId}`).catch(()=>{});let b=d??m.snapshot;if(b===void 0)throw new Error(`provider "${m.provider}" gave the workspace no base to anchor landing against`);await o.retainSnapshot(m,g,b),e.broadcastWorkspacePhase({phase:"setup"}),w=d!==void 0?await this.copyCarriedWork(m,d,r):!0;let I=await this.materializeNestedTrees(m);if(f.length>0){let x=await o.reproduceNested(m.path,r,f).catch(T=>({applied:[],failed:f.map(M=>({path:M.relPath,reason:T instanceof Error?T.message:String(T)}))}));x.failed.length>0&&(w=!1,v=x.failed)}y=await this.applyWorkspaceSetup(m,e.sessionId),I!==void 0&&(y=y===void 0?I:`${I}; ${y}`),e.broadcastWorkspacePhase({phase:"swapping"});let A=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:m.path,workspace:{path:m.path,sourceCwd:m.sourceCwd,label:m.label,...t!==void 0&&t!==m.label?{requestedLabel:t}:{},provider:m.provider,...m.snapshot!==void 0?{snapshot:m.snapshot}:{},...m.line!==void 0?{line:m.line}:{},...m.vcs!==void 0?{vcs:{...m.vcs}}:{},...d===void 0?{clean:!0}:{}},historyLength:A.length,note:`Continuing in an isolated workspace at ${m.path}, derived from ${r}.`,...await this.recordSynopsisFor(e.sessionId)})}catch(b){let I=await this.unwindStartWorkspace({provider:o,ws:m,startRef:g,carried:d}),A=b instanceof Error?b.message:String(b);throw e.broadcastWorkspacePhase({phase:"failed",error:A}),new Error(I===void 0?A:`${A}
187
+ ${I}`)}await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:m.sourceCwd,label:m.label,...m.line!==void 0?{branch:m.line}:{}});let S=[`Moved into workspace ${$(m.path)}`,` source: ${$(r)}`];if(m.line!==void 0&&S.push(` branch: ${m.line}`),t!==void 0&&t!==m.label&&S.push(` note: "${t}" was already taken by a surviving branch, so this is "${m.label}"`),d!==void 0){S.push(w?` carried ${c.length} uncommitted file(s) in; the source tree is untouched:`:` WARNING: could not copy ${c.length} uncommitted file(s); the workspace starts from HEAD. They are untouched in the source tree:`);for(let b of Ct(c))S.push(` ${b}`);w&&u&&S.push(" staging did not come along; everything above is unstaged here");for(let b of v)S.push(` nested tree ${b.path}: ${b.reason}`)}else if(p.length>0){S.push(` started clean: ${p.length} uncommitted file(s) stayed in the source and did NOT come along:`);for(let b of Ct(p))S.push(` ${b}`)}else l&&S.push(" source tree was clean; nothing carried in");return y!==void 0&&S.push(` ${y}`),S.push("Use `/hydra workspace stop` to merge back and return."),S.join(`
188
+ `)}async copyCarriedWork(e,t,n){let r=await this.patchFromSnapshot(n,t,e.provider);if(r===void 0)return!1;if(r.length===0)return!0;let o=re(e.provider);return o===void 0?!1:(await o.applyDelta(e.path,r)).ok}async patchFromSnapshot(e,t,n){let r=re(n);if(r===void 0)return;let o=await r.currentState(e);if(o!==void 0)return await r.captureDelta(e,o,t).catch(()=>{})}async unwindStartWorkspace(e){let{provider:t,ws:n,startRef:r,carried:o}=e;await t.unlock(n).catch(()=>{}),o!==void 0&&await t.dropSnapshotRef(n,r).catch(()=>{}),await t.removeWorkspace(n,{force:!0}).catch(()=>{})}async materializeNestedTrees(e,t){let n=re(e.provider);if(n?.capabilities().supports.nestedTrees!==!0)return;let r=await n.materializeNested({path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:n.kind},t).catch(o=>({ok:!1,count:0,reason:o instanceof Error?o.message:String(o)}));return r.ok?r.count>0?`populated ${r.count} nested tree(s)`:void 0:`nested trees FAILED: ${r.reason??"unknown"}`}async applyWorkspaceSetup(e,t){let n=await $s(e.sourceCwd).catch(()=>({})),r=[];if(n.carry!==void 0&&n.carry.length>0){let o=await jo(e.sourceCwd,e.path,n.carry).catch(()=>{});o!==void 0&&o.copied.length>0&&r.push(`carried ${o.copied.length} config file(s)`)}if(n.postCreate!==void 0){let o=await Os(n.postCreate,{workspacePath:e.path,sourceCwd:e.sourceCwd,label:e.label,sessionId:t,...n.hookTimeoutSeconds!==void 0?{timeoutSeconds:n.hookTimeoutSeconds}:{}});r.push(o.ok?"ran postCreate":`postCreate FAILED: ${o.reason??"unknown"}`)}return r.length>0?r.join("; "):void 0}async deriveForkWorkspace(e,t){let n=re(e.provider);if(n===void 0)return;let r=n.capabilities(),o=r.sharedHistory?await n.currentState(e.path)??"":"",i=await n.createWorkspace({sourceCwd:e.sourceCwd,label:t,...o.length>0?{from:o}:{contentFrom:e.path}}).catch(d=>({ok:!1,reason:String(d)}));if(!i.ok){this.logger?.warn?.(`fork workspace: could not derive from ${e.path}: ${i.reason}`);return}let a=i.workspace;if(o.length>0&&r.supports.captureWorkingState){let d=await n.captureWorkingState(e.path,`hydra: fork carry from ${e.label}`).catch(()=>{});d!==void 0&&d!==o&&await this.copyUncommittedInto(e.path,a.path,o,d,a.provider).catch(()=>{})}return{path:a.path,sourceCwd:a.sourceCwd,label:a.label,provider:a.provider,...a.snapshot!==void 0?{snapshot:a.snapshot}:{},...a.line!==void 0?{line:a.line}:{},...a.vcs!==void 0?{vcs:{...a.vcs}}:{}}}async copyUncommittedInto(e,t,n,r,o){let i=re(o);if(i===void 0)return!1;let a=await i.captureDelta(e,n,r).catch(()=>{});return a===void 0||a.trim().length===0?!1:(await i.applyDelta(t,a,{stage:!0})).ok}async recoverWorkspace(e){let t=re(e.provider);if(t===void 0)return;let n={path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:e.provider,...e.snapshot!==void 0?{snapshot:e.snapshot}:{},...e.vcs!==void 0?{vcs:e.vcs}:{}};if(t.capabilities().supports.rematerialize){let o=await t.rematerialize(n).catch(i=>({ok:!1,reason:String(i)}));if(o.ok)return this.logger?.info?.(`session workspace: restored ${o.workspace.path} from retained state`),{...e,path:o.workspace.path};this.logger?.warn?.(`session workspace: could not restore: ${o.reason}`)}if(!await this.dirExists(e.sourceCwd))return;let r=await t.createWorkspace({sourceCwd:e.sourceCwd,label:`${e.label}-r`}).catch(o=>({ok:!1,reason:String(o)}));if(r.ok)return this.logger?.warn?.(`session workspace: ${e.path} is gone and could not be restored; resurrecting in a fresh workspace ${r.workspace.path} from ${e.sourceCwd}. Uncommitted work from the old workspace is not recoverable.`),{path:r.workspace.path,sourceCwd:r.workspace.sourceCwd,label:r.workspace.label,provider:r.workspace.provider,...r.workspace.snapshot!==void 0?{snapshot:r.workspace.snapshot}:{},...r.workspace.vcs!==void 0?{vcs:{...r.workspace.vcs}}:{}}}async syncFromAgent(e){let t=await this.registry.getAgent(e);if(!t){let m=new Error(`agent ${e} not found in registry`);throw m.code=R.AgentNotInstalled,m}let n=await _e(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:$c.homedir(),plan:n}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:Lt,clientInfo:{name:"hydra",version:ue}})}catch(m){throw await r.kill().catch(()=>{}),yt(m,r)}if(r.authMethods=jn(o.authMethods),r.steeringSupported=Hn(o),(o.agentCapabilities??{}).sessionCapabilities?.list===void 0)throw await r.kill().catch(()=>{}),new Error(`agent ${e} does not advertise sessionCapabilities.list; cannot sync`);let a;try{a=await this.collectAgentSessions(r)}catch(m){throw await r.kill().catch(()=>{}),m}await r.kill().catch(()=>{});let d=new Map,c=Vr(t);d.set(e,c);let u=new Set,l=new Map;for(let m of this.sessions.values()){let g=await this.agentStoreKey(m.agentId,d);u.add(`${g}::${m.upstreamSessionId}`),g===c&&l.set(m.upstreamSessionId,m)}let p=await this.store.list().catch(()=>[]);for(let m of p){u.add(`${await this.agentStoreKey(m.agentId,d)}::${m.upstreamSessionId}`);for(let g of m.upstreamGenerations??[])u.add(`${await this.agentStoreKey(g.agentId,d)}::${g.upstreamSessionId}`)}let f=E.sessionsDir(),h=[],k=0;for(let m of a){l.get(m.sessionId)?.noteUpstreamUpdatedAt(m.updatedAt);let g=`${c}::${m.sessionId}`;if(u.has(g)){k+=1;continue}if(Eh(m.cwd,f)){k+=1;continue}let y=c,w=await this.tombstones.read(y,m.sessionId).catch(()=>{});if(!w&&c!==e&&(y=e,w=await this.tombstones.read(y,m.sessionId).catch(()=>{})),w){if(!sc(w,m.updatedAt)){k+=1;continue}await this.tombstones.remove(y,m.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${m.sessionId} (upstream updatedAt advanced past ${w.upstreamUpdatedAt??"<unset>"})`)}u.add(g);let v=`${ye}${xt()}`,S=new Date().toISOString(),b=m.updatedAt??S,I={sessionId:v,lineageId:Pn(),upstreamSessionId:m.sessionId,agentId:e,cwd:m.cwd,pendingHistorySync:!0,interactive:!Ph(m.title),createdAt:b,updatedAt:b};m.title!==void 0&&(I.title=m.title);let A=Po(I);await this.store.write(A),h.push({version:1,...A})}return{synced:h,skipped:k}}async listTombstones(e={}){let t=e.grep?.toLowerCase();return(await this.tombstones.list(e.agentId)).filter(r=>e.since===void 0||r.deletedAt>=e.since).filter(r=>t===void 0||[r.title,r.cwd,r.sessionId,r.upstreamSessionId].some(o=>o?.toLowerCase().includes(t))).sort((r,o)=>r.deletedAt<o.deletedAt?1:-1)}async undeleteSessions(e){let t=await this.tombstones.list(),n=[],r=[],o=[];for(let a of e){let d=t.filter(u=>u.upstreamSessionId===a),c=d.length>0?d:t.filter(u=>u.sessionId===a||u.sessionId===`${ye}${a}`);if(c.length===0){r.push({id:a,reason:"no tombstone found"});continue}if(c.length>1){r.push({id:a,reason:"ambiguous: several tombstones match; pass an upstream id",candidates:c.map(u=>u.upstreamSessionId)});continue}o.push({id:a,tombstone:c[0]})}let i=new Map;for(let a of o){let d=i.get(a.tombstone.agentId)??[];d.push(a),i.set(a.tombstone.agentId,d)}for(let[a,d]of i){let c=l=>{let{version:p,...f}=l;return this.tombstones.add(f).catch(()=>{})};for(let l of d)await this.tombstones.remove(a,l.tombstone.upstreamSessionId);let u;try{u=(await this.syncFromAgent(a)).synced}catch(l){for(let p of d)await c(p.tombstone),r.push({id:p.id,reason:`agent sync failed: ${l.message}`});continue}for(let l of d){let p=u.find(f=>f.upstreamSessionId===l.tombstone.upstreamSessionId);if(!p){await c(l.tombstone),r.push({id:l.id,reason:`agent ${a} no longer lists this session`});continue}n.push({id:l.id,sessionId:p.sessionId,upstreamSessionId:l.tombstone.upstreamSessionId})}}return{restored:n,failed:r}}async collectAgentSessions(e){let t=[],n,r=new Set;for(let o=0;o<100;o+=1){let i={};n!==void 0&&(i.cursor=n);let a=await e.connection.request("session/list",i),d=Array.isArray(a.sessions)?a.sessions:[];for(let c of d){if(typeof c.sessionId!="string"||typeof c.cwd!="string")continue;let u={sessionId:c.sessionId,cwd:c.cwd};typeof c.title=="string"&&(u.title=c.title),typeof c.updatedAt=="string"&&(u.updatedAt=c.updatedAt),t.push(u)}if(typeof a.nextCursor!="string"||a.nextCursor.length===0||r.has(a.nextCursor))break;r.add(a.nextCursor),n=a.nextCursor}return t}async applySeedModel(e,t,n,r,o){try{let{verb:i,result:a}=await lt({request:(d,c)=>e.connection.request(d,c),sessionId:t,modelId:n,...o?{verb:o}:{},logger:this.logger});return this.logger?.info(`${r}: ${i} accepted`),{accepted:!0,result:a}}catch(i){return this.logger?.warn(`${r} rejected by agent (${i.message}); session will use the agent's own default`),{accepted:!1}}}async applySeedMode(e,t,n,r){try{let o=await e.connection.request("session/set_mode",{sessionId:t,modeId:n});return this.logger?.info(`${r}: session/set_mode accepted`),{accepted:!0,result:o}}catch(o){return this.logger?.warn(`${r} rejected by agent (${o.message}); session will use the agent's own default mode`),{accepted:!1}}}async restoreConfigOptionValues(e,t,n,r){if(!n||Object.keys(n).length===0)return this.logger?.info(`resurrect: no persisted configOptionValues; agent reports ${JSON.stringify(Object.fromEntries(r.map(i=>[i.id,i.currentValue])))}`),r;let o=r;for(let[i,a]of Object.entries(n)){let d=`resurrect: persisted configOptionValues.${i}=${JSON.stringify(a)}`,c=o.find(p=>p.id===i);if(!c){this.logger?.warn(`${d}: agent does not currently advertise configId=${i}; skipping session/set_config_option`);continue}if(a===c.currentValue){this.logger?.info(`${d}: agent already reports ${JSON.stringify(c.currentValue)}; nothing to restore`);continue}this.logger?.info(`${d}: agent reports ${JSON.stringify(c.currentValue)}; restoring`);let u=Gt(a,c.options.map(p=>p.value));if(u.kind!=="exact"&&u.kind!=="resolved"){this.logger?.warn(`${d} ${u.kind}; skipping session/set_config_option`);continue}let l=u.kind==="resolved"?u.modelId:a;try{let p=await e.connection.request("session/set_config_option",{sessionId:t,configId:i,value:l});this.logger?.info(`${d}: session/set_config_option accepted`),o=tn(p)?nn(p):o.map(f=>f.id===i?{...f,currentValue:l}:f)}catch(p){this.logger?.warn(`${d}: session/set_config_option rejected by agent (${p.message})`)}}return o}async bootstrapAgent(e){let t=e.timer,n=await this.registry.getAgent(e.agentId);if(!n){let a=new Error(`agent ${e.agentId} not found in registry`);throw a.code=R.AgentNotInstalled,a}t?.mark("boot.resolve-agent");let r=await _e(n,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress});t?.mark("boot.plan-spawn");let o=ns(e.selfSessionId,e.forwardedEnv),i=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:r,...o?{extraEnv:o}:{}});t?.mark("boot.spawn");try{let a=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:Lt,clientInfo:{name:"hydra",version:ue}}),d=a.agentCapabilities;i.authMethods=jn(a.authMethods),i.steeringSupported=Hn(a),t?.mark("boot.initialize");let c=Go(n),u=await i.connection.request("session/new",{cwd:e.cwd,mcpServers:e.mcpServers??[],...c&&{_meta:c}});t?.mark("boot.session-new");let l=u.sessionId;if(typeof l!="string")throw new Error(`agent ${e.agentId} returned a non-string sessionId from session/new`);let p=Ko(u),f=Qo(u),h=Bt(u),k=pa(this.sessionDefaults,n),m=k?.value,g=e.configDefaults,y=k?.from??e.agentId,w=e.model??g?.model??m?.model,v;if(w&&w!==p){let T=Vt(w,f),M=e.model!==void 0?`model=${JSON.stringify(w)}`:g?.model!==void 0?`configDefaults.model=${JSON.stringify(w)}`:`sessionDefaults[${y}].model=${JSON.stringify(w)}`;if(T.kind==="exact"||T.kind==="none"){let N=await this.applySeedModel(i,l,w,M,h);N.accepted&&(p=w,v=N.result)}else if(T.kind==="resolved")if(T.modelId===p)p=T.modelId;else{let N=await this.applySeedModel(i,l,T.modelId,`${M} resolved to ${JSON.stringify(T.modelId)}`,h);N.accepted&&(p=T.modelId,v=N.result)}else if(T.kind==="ambiguous")this.logger?.warn(`${M} is ambiguous (trailing-segment matches [${T.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(p)}`);else{let N=f.map(B=>B.modelId).join(", ");this.logger?.warn(`${M} not in agent's availableModels ([${N}]); skipping session/set_model, session will use ${JSON.stringify(p)}`)}}t?.mark("boot.seed-model");let S=Yo(u),b=Xo(u),I=g?.mode??m?.mode;if(I&&I!==b){let T=g?.mode!==void 0?`configDefaults.mode=${JSON.stringify(I)}`:`sessionDefaults[${y}].mode=${JSON.stringify(I)}`;if(S.length>0&&!S.some(M=>M.id===I)){let M=S.map(N=>N.id).join(", ");this.logger?.warn(`${T} not in agent's availableModes ([${M}]); skipping session/set_mode, session will use ${JSON.stringify(b)}`)}else{let M=await this.applySeedMode(i,l,I,T);M.accepted&&(b=I,tn(M.result)&&(v=M.result))}}t?.mark("boot.seed-mode");let A={...m??{},...g??{}};delete A.model,delete A.mode;let x=nn(tn(v)?v:u);if(Object.keys(A).length>0)for(let[T,M]of Object.entries(A)){let N=`sessionDefaults[${y}].${T}=${JSON.stringify(M)}`,B=x.find(L=>L.id===T);if(!B){this.logger?.warn(`${N}: agent does not currently advertise configId=${T}; skipping session/set_config_option`);continue}let q=Gt(M,B.options.map(L=>L.value));if(q.kind!=="exact"&&q.kind!=="resolved"){this.logger?.warn(`${N} ${q.kind}; skipping session/set_config_option`);continue}let V=q.kind==="resolved"?q.modelId:M;if(V!==B.currentValue)try{let L=await i.connection.request("session/set_config_option",{sessionId:l,configId:T,value:V});this.logger?.info(`${N}: session/set_config_option accepted`),tn(L)?(x=nn(L),v=L):x=x.map(W=>W.id===T?{...W,currentValue:V}:W)}catch(L){this.logger?.warn(`${N}: session/set_config_option rejected by agent (${L.message})`)}}return t?.mark("boot.seed-config"),i.connection.dropBufferedWhere("session/update",T=>T?.update?.sessionUpdate==="config_option_update"),{agent:i,upstreamSessionId:l,agentMeta:u._meta,agentCapabilities:d,initialModel:p,initialModels:f.length>0?f:void 0,initialModes:S.length>0?S:void 0,initialMode:b,initialConfigOptions:x.length>0?x:void 0,modelVerb:h}}catch(a){throw await i.kill().catch(()=>{}),yt(Mc(a,i,e.agentId,{command:r.command,args:r.args,cwd:e.cwd}),i)}}async bootstrapAgentLoad(e,t){let n=await this.registry.getAgent(t.agentId);if(!n){let a=new Error(`agent ${t.agentId} not found in registry`);throw a.code=R.AgentNotInstalled,a}let r=await _e(n,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=ns(t.selfSessionId,t.forwardedEnv),i=this.spawner({agentId:t.agentId,cwd:t.cwd,plan:r,...o?{extraEnv:o}:{}});try{let a=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:Lt,clientInfo:{name:"hydra",version:ue}}),d=a.agentCapabilities;i.authMethods=jn(a.authMethods),i.steeringSupported=Hn(a);let c=Go(n),u=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),l=Ko(u),p=ht(Qo(u)),f=Yo(u),h=Xo(u),k=ht(nn(u));return{agent:i,upstreamSessionId:e,agentMeta:u._meta,agentCapabilities:d,initialModel:l,initialModels:p,initialModes:f.length>0?f:void 0,initialMode:h,initialConfigOptions:k,modelVerb:Bt(u)}}catch(a){throw await i.kill().catch(()=>{}),yt(Mc(a,i,t.agentId,{command:r.command,args:r.args,cwd:t.cwd}),i)}}async rewindSession(e,t,n={}){let r=await this.store.read(e);if(!r){let a=new Error(`session not found: ${e}`);throw a.code=R.SessionNotFound,a}if(this.rollbackLocks.has(e)||r.compactionState!=null){let a=new Error("the session is being compacted or rolled back; try again when that finishes");throw a.code=R.InvalidRequest,a}let o=0,i=async()=>{let a=await this.histories.truncateAfterTurn(e,t);if(!a){let u=new Error(`keepThrough messageId not found in the session's recent history: ${t}`);throw u.code=R.InvalidParams,u}if(o=a.removed,o===0)return!1;let d=r.summarizedThroughEntry,c=d!==void 0&&a.kept<d;if(c){let u=this.get(e);u&&(u.summarizedThroughEntry=void 0)}return await this.mutateRecord(e,{},c?["rollbackBreadcrumb","synopsis","summarizedThroughEntry"]:["rollbackBreadcrumb"]),!0};this.rollbackLocks.add(e);try{let a=this.get(e);a?await a.rewind(t,i,n):await i()&&await this.mutateRecord(e,{upstreamSessionId:""})}finally{this.rollbackLocks.delete(e)}return{sessionId:e,removed:o}}async performUncompact(e){if(this.rollbackLocks.has(e))throw new Error("a rollback is already in progress for this session");let t=this.get(e);if(!t)throw new Error("session is not live \u2014 cannot roll back a cold session");let n=await this.store.read(e);if(!n)throw new Error("session record not found");let r=n.rollbackBreadcrumb;if(!r)throw new Error("no rollback breadcrumb found \u2014 either the session has not been compacted, the rollback window has closed (a new turn was dispatched), or a previous rollback already consumed the breadcrumb");let o=n.compactionState;if(o!=null)throw new Error(`compaction is in progress (status: ${o.status}) \u2014 wait for it to complete before rolling back`);if(!await t.isQuiescedForSwap())throw new Error("session is not quiesced for rollback \u2014 wait for in-flight work to complete");this.rollbackLocks.add(e);try{await t.rollbackToUpstream({previousUpstreamSessionId:r.previousUpstreamSessionId,previousSummarizedThroughEntry:r.previousSummarizedThroughEntry}),await this.mutateRecord(e,{summarizedThroughEntry:r.previousSummarizedThroughEntry},["synopsis","rollbackBreadcrumb"])}finally{this.rollbackLocks.delete(e)}}async bootstrapAgentForAuth(e,t){let n=this.pendingAuthAgents.get(e);if(n&&n.isAlive())return n;let r=await this.registry.getAgent(e);if(!r){let d=new Error(`agent ${e} not found in registry`);throw d.code=R.AgentNotInstalled,d}let o=await _e(r,[],{npmRegistry:this.npmRegistry}),i=t??ce(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let d=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:Lt,clientInfo:{name:"hydra",version:ue}});a.authMethods=jn(d.authMethods),a.steeringSupported=Hn(d)}catch(d){throw await a.kill().catch(()=>{}),yt(d,a)}return this.pendingAuthAgents.set(e,a),a.onExit(()=>{this.pendingAuthAgents.get(e)===a&&this.pendingAuthAgents.delete(e)}),a}async planSpawnForAgent(e){let t=await this.registry.getAgent(e);if(!t){let n=new Error(`agent ${e} not found in registry`);throw n.code=R.AgentNotInstalled,n}return _e(t,[],{npmRegistry:this.npmRegistry})}consumePendingAuthAgent(e){let t=this.pendingAuthAgents.get(e);if(t&&(this.pendingAuthAgents.delete(e),!!t.isAlive()))return t}getAgentForSession(e){return this.sessions.get(e)?.agent}async attachManagerHooks(e){e.onClose(({deleteRecord:t})=>{if(this.sessions.delete(e.sessionId),this.driftNoticed.delete(e.sessionId),this.invalidateListCache(),t||this.store.touch(e.sessionId).catch(()=>{}),t&&e.workspace!==void 0&&this.releaseWorkspace(e.workspace,e.sessionId).catch(()=>{}),t){if(e.upstreamSessionId){let r=sn({interactive:e.interactive,...e.originatingClient?{originatingClient:e.originatingClient}:{}},!0),o=this.tombstoneAllGenerations(e.sessionId,{agentId:e.agentId,upstreamSessionId:e.upstreamSessionId,upstreamUpdatedAt:new Date(e.updatedAt).toISOString(),cwd:e.cwd,...e.title!==void 0?{title:e.title}:{},...r!==void 0?{interactive:r}:{}},"user").catch(()=>{}).then(()=>this.store.delete(e.sessionId).catch(()=>{})).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===o&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,o);return}let n=this.store.delete(e.sessionId).catch(()=>{}).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===n&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,n);return}}),e.rewindHook=t=>this.rewindSession(e.sessionId,t,{afterCurrentTurn:!0}),e.onTitleChange(t=>{this.persistTitle(e.sessionId,t).catch(()=>{})}),e.onPriorityChange(t=>{this.persistPriority(e.sessionId,t).catch(()=>{})}),e.onAgentChange(({agentId:t,upstreamSessionId:n,...r})=>{this.persistAgentChange(e.sessionId,t,n,r).catch(()=>{})}),e.onModelChange(t=>{this.persistSnapshot(e.sessionId,{currentModel:t}).catch(()=>{})}),e.onModeChange(t=>{this.persistSnapshot(e.sessionId,{currentMode:t}).catch(()=>{})}),e.onInteractiveChange(t=>{this.persistSnapshot(e.sessionId,{interactive:t}).catch(()=>{})}),e.onUsageChange(t=>{this.persistSnapshot(e.sessionId,{currentUsage:Oc(t)}).catch(()=>{})}),e.onAgentCommandsChange(t=>{this.persistSnapshot(e.sessionId,{agentCommands:t.map(n=>({name:n.name,...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModesChange(t=>{this.persistSnapshot(e.sessionId,{agentModes:t.map(n=>({id:n.id,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModelsChange(t=>{this.persistSnapshot(e.sessionId,{agentModels:t.map(n=>({modelId:n.modelId,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onConfigOptionsChange(t=>{this.persistSnapshot(e.sessionId,{configOptionValues:Object.fromEntries(t.map(n=>[n.id,n.currentValue]))}).catch(()=>{})}),e.onAttentionFlagsChange(t=>{this.mutateRecord(e.sessionId,{attentionFlags:t}).catch(()=>{})}),e.onReadStateChange(t=>{this.invalidateListCache(),this.persistReadState(e.sessionId,t).then(()=>this.invalidateListCache()).catch(()=>{})}),this.sessions.set(e.sessionId,e),this.invalidateListCache(),await this.enqueueMetaWrite(e.sessionId,async()=>{let t=await this.store.read(e.sessionId),n=Mh(e,t);await this.store.write(n)}).catch(t=>{this.logger?.warn(`failed to persist session record for ${e.sessionId}: ${t instanceof Error?t.message:String(t)}`)})}async getHistory(e){if(this.sessions.has(e))return this.histories.load(e).catch(()=>[]);if(await this.store.read(e))return this.histories.load(e).catch(()=>[])}async pageHistory(e,t){let n=await this.store.read(e);if(!this.sessions.has(e)&&!n)return;let r=this.sessions.get(e)?.side??n?.side,o=await this.histories.pageBefore(e,{...t,skip:a=>Rn(a.method,a.params),hydrate:!1}),i=Ut(o.entries,r);return{entries:await this.histories.hydrate(e,ls(i)),hasMore:o.hasMore&&i.length===o.entries.length}}async loadHistory(e,t={}){return this.histories.load(e,t)}async loadToolBlob(e,t){return yn(e,t)}async loadFromDisk(e){let t=await this.store.read(e);if(!t)return;let n=t.title;return n||(n=await this.deriveTitleFromHistory(e)),{hydraSessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,agentId:t.agentId,cwd:t.cwd,title:n,synopsis:t.synopsis,summarizedThroughEntry:t.summarizedThroughEntry,agentArgs:t.agentArgs,currentModel:t.currentModel,currentMode:t.currentMode,currentUsage:_h(t.currentUsage),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,configOptionValues:t.configOptionValues,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,lastTurnEndedAt:t.lastTurnEndedAt,readAt:t.readAt,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,side:t.side,forkSynthesisState:t.forkSynthesisState,forwardedEnv:t.forwardedEnv,workspace:t.workspace,compactionState:t.compactionState,attentionFlags:t.attentionFlags?.filter(r=>!(r.source==="daemon"&&r.reason.startsWith("permission:")))}}async setForwardedEnv(e,t){if(t===void 0)return;let n=this.sessions.get(e);n&&(n.forwardedEnv=t),await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r)return;let o={...r,forwardedEnv:t};await this.store.write(o)})}async clearPendingHistorySync(e){await this.enqueueMetaWrite(e,async()=>{let t=await this.store.read(e);if(!t||t.pendingHistorySync!==!0)return;let n={...t};delete n.pendingHistorySync,await this.store.write(n)})}async deriveTitleFromHistory(e){let t=await this.histories.load(e).catch(()=>[]);for(let n of t){let r=n.params;if(r?.update?.sessionUpdate!=="prompt_received")continue;let o=r.update.sentBy;if(typeof o?.fromSession=="string"||typeof o?.clientId=="string"&&o.clientId.startsWith("transformer:"))continue;let i=At(r.update.prompt),a=Io(i,200);if(a&&!a.startsWith("/"))return a}}get(e){return this.sessions.get(e)}liveSessions(){return this.sessions.values()}setLiveConfig(e){e.sessionDefaults&&(this.sessionDefaults=e.sessionDefaults)}activeAgentVersions(){let e=new Map;for(let t of this.sessions.values()){let n=t.agent.installId,r=t.agent.version,o=e.get(n);o||(o=new Set,e.set(n,o)),o.add(r)}return e}async resolveCanonicalId(e){if(this.sessions.has(e)||await this.store.read(e))return e;if(e.startsWith(ye))return;let t=ye+e;if(this.sessions.has(t)||await this.store.read(t))return t}require(e){let t=this.sessions.get(e);if(!t){let n=new Error(`session ${e} not found`);throw n.code=R.SessionNotFound,n}return t}liveListEntry(e){return{sessionId:e.sessionId,upstreamSessionId:e.upstreamSessionId,cwd:e.cwd,workspace:e.workspace,workspaceError:e.workspaceError,title:e.title,agentId:e.agentId,currentModel:e.currentModel,currentUsage:e.currentUsage,parentSessionId:e.parentSessionId,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,side:e.side,forkSynthesisState:e.forkSynthesisState,originatingClient:e.originatingClient,interactive:e.interactive,createdAt:new Date(e.createdAt).toISOString(),updatedAt:new Date(e.updatedAt).toISOString(),attachedClients:e.attachedCount,status:"warm",busy:e.turnStartedAt!==void 0,turnStartedAt:e.turnStartedAt,armedTasks:e.armedBackgroundTasks.length,...e.armedSince!==void 0?{armedSince:e.armedSince}:{},awaitingInput:e.awaitingInput,agentPid:e.agentPid,...qt(e)}}async getOne(e){let t=this.sessions.get(e);if(t){let a=await Ln(t.sessionId),d=sn({interactive:t.interactive,...t.originatingClient?{originatingClient:t.originatingClient}:{}},a.hasContent),c=a.mtime??new Date(t.updatedAt).toISOString();return{sessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,cwd:t.cwd,title:t.title,agentId:t.agentId,currentModel:t.currentModel,currentUsage:t.currentUsage,parentSessionId:t.parentSessionId,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,side:t.side,forkSynthesisState:t.forkSynthesisState,originatingClient:t.originatingClient,interactive:d,priority:t.priority,createdAt:new Date(t.createdAt).toISOString(),updatedAt:c,attachedClients:t.attachedCount,status:"warm",agentPid:t.agentPid,busy:t.turnStartedAt!==void 0,turnStartedAt:t.turnStartedAt,armedTasks:t.armedBackgroundTasks.length,...t.armedSince!==void 0?{armedSince:t.armedSince}:{},awaitingInput:t.awaitingInput,...qt(t)}}let n=await this.store.read(e).catch(()=>{});if(!n)return;let r=await Ln(n.sessionId),o=sn(n,r.hasContent),i=r.mtime??n.updatedAt;return{sessionId:n.sessionId,upstreamSessionId:n.upstreamSessionId,cwd:n.cwd,title:n.title,agentId:n.agentId,currentModel:n.currentModel,currentUsage:Dn(n.currentUsage),importedFromMachine:n.importedFromMachine,importedFromUpstreamSessionId:n.importedFromUpstreamSessionId,parentSessionId:n.parentSessionId,forkedFromSessionId:n.forkedFromSessionId,forkedFromMessageId:n.forkedFromMessageId,side:n.side,forkSynthesisState:n.forkSynthesisState,originatingClient:n.originatingClient,interactive:o,priority:n.priority,createdAt:n.createdAt,updatedAt:i,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,...qt(n)}}async list(e={}){return(await this.listing(e)).entries}async listing(e={}){let t=`${e.cwd??""}|${e.includeNonInteractive?"1":"0"}|${e.status??""}`,n=Date.now(),r=this.listCache.get(t);if(r&&r.expiresAt>n)return r.promise;let o=this.listUncached(e);return this.listCache.set(t,{expiresAt:n+s.LIST_CACHE_TTL_MS,promise:o}),o.catch(()=>{let i=this.listCache.get(t);i&&i.promise===o&&this.listCache.delete(t)}),o}invalidateListCache(){this.listCache.clear()}async listUncached(e={}){let t=await this.store.cursor(),{entries:n,liveIds:r}=await this.warmRows(e);if(e.status==="warm")return{entries:n,cursor:t};let o=await this.store.list().catch(i=>{throw this.logger?.warn(`session list: store.list() failed: ${i?.message??String(i)}`),i});return n.push(...await this.coldRows(o,r,e)),n.sort((i,a)=>i.updatedAt<a.updatedAt?1:-1),{entries:n,cursor:t}}async listSince(e,t){let{entries:n,liveIds:r}=await this.warmRows(e);if(e.status==="warm")return{entries:n,removed:[],cursor:await this.store.cursor()};let o=await this.store.listChangedSince(t);return n.push(...await this.coldRows(o.records,r,e)),n.sort((i,a)=>i.updatedAt<a.updatedAt?1:-1),{entries:n,removed:o.removed,cursor:o.cursor}}async seedSessionIndex(){await this.store.ensureIndex();let e=await this.tombstones.list().catch(()=>[]);for(let t of e){if(t.sessionId===void 0)continue;let n=Date.parse(t.deletedAt);Number.isNaN(n)||await this.store.markDeleted(t.sessionId,n)}}static includeRow(e,t){return e.includeNonInteractive?!0:t===!0}async warmRows(e){let t=[],n=new Set,r=[...this.sessions.values()].filter(i=>Ec(e.cwd,i));if(e.status==="cold"){for(let i of r)n.add(i.sessionId);return{entries:t,liveIds:n}}let o=await Promise.all(r.map(i=>Ln(i.sessionId)));for(let i=0;i<o.length;i+=1){let a=r[i],d=o[i];n.add(a.sessionId);let c=sn({interactive:a.interactive,...a.originatingClient?{originatingClient:a.originatingClient}:{}},d.hasContent);if(!s.includeRow(e,c))continue;let u=d.mtime??new Date(a.updatedAt).toISOString();t.push({sessionId:a.sessionId,upstreamSessionId:a.upstreamSessionId,cwd:a.cwd,workspace:a.workspace,workspaceError:a.workspaceError,title:a.title,agentId:a.agentId,currentModel:a.currentModel,currentUsage:a.currentUsage,parentSessionId:a.parentSessionId,forkedFromSessionId:a.forkedFromSessionId,forkedFromMessageId:a.forkedFromMessageId,side:a.side,originatingClient:a.originatingClient,interactive:c,priority:a.priority,createdAt:new Date(a.createdAt).toISOString(),updatedAt:u,attachedClients:a.attachedCount,status:"warm",agentPid:a.agentPid,busy:a.turnStartedAt!==void 0,turnStartedAt:a.turnStartedAt,armedTasks:a.armedBackgroundTasks.length,...a.armedSince!==void 0?{armedSince:a.armedSince}:{},awaitingInput:a.awaitingInput,compactionState:a.compactionState,forkSynthesisState:a.forkSynthesisState,...qt(a)})}return{entries:t,liveIds:n}}async coldRows(e,t,n){let r=[],o=e.filter(a=>!t.has(a.sessionId)&&Ec(n.cwd,a)),i=await Promise.all(o.map(a=>Ln(a.sessionId)));for(let a=0;a<o.length;a+=1){let d=o[a],c=i[a],u=sn(d,c.hasContent);if(!s.includeRow(n,u))continue;let l=c.mtime??d.updatedAt;r.push({sessionId:d.sessionId,upstreamSessionId:d.upstreamSessionId,cwd:d.cwd,workspace:d.workspace,title:d.title,agentId:d.agentId,currentModel:d.currentModel,currentUsage:Dn(d.currentUsage),importedFromMachine:d.importedFromMachine,importedFromUpstreamSessionId:d.importedFromUpstreamSessionId,parentSessionId:d.parentSessionId,forkedFromSessionId:d.forkedFromSessionId,forkedFromMessageId:d.forkedFromMessageId,side:d.side,originatingClient:d.originatingClient,interactive:u,priority:d.priority,createdAt:d.createdAt,updatedAt:l,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,compactionState:d.compactionState,forkSynthesisState:d.forkSynthesisState,...qt(d)})}return r}async exportBundle(e,t={}){let n=await this.store.read(e);if(!n)return;let r;if(n.lineageId)r=n;else{let c=Pn(),u={...n,lineageId:c};await this.enqueueMetaWrite(e,async()=>{let l=await this.store.read(e);l&&(l.lineageId||await this.store.write({...l,lineageId:c}))}).catch(()=>{}),r=u}let o=t.tools??"inline",i=t.includeArchivedHistory?await this.loadArchivedHistory(e,o):await this.histories.load(e,o==="references"?{tools:"references"}:{}).catch(()=>[]),a=await _c(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let d={};for(let c of bc(i)){let u=await Ki(e,c);u&&(d[c]=u.toString("base64"))}return{record:r,history:i,promptHistory:a,toolBlobs:d}}async loadArchivedHistory(e,t){let n=await this.histories.loadArchives(e),r=await this.histories.load(e,{tools:"references",maxEntries:1/0}),o=[...n,...r];return t==="references"?o:this.histories.hydrate(e,o)}async importBundle(e,t={}){let n=await this.store.findByLineageId(e.session.lineageId);if(n){if(!t.replace){let i=new Error(`bundle already imported as ${n.sessionId}`);throw i.code=R.BundleAlreadyImported,i.existingSessionId=n.sessionId,i}let o=this.sessions.get(n.sessionId);return o&&await o.close({deleteRecord:!1,by:"bundle-import-overwrite"}).catch(()=>{}),await this.writeImportedRecord({sessionId:n.sessionId,bundle:e,preservedCreatedAt:n.createdAt,cwd:t.cwd}),{sessionId:n.sessionId,importedFromSessionId:e.session.sessionId,replaced:!0}}let r=`${ye}${xt()}`;return await this.writeImportedRecord({sessionId:r,bundle:e,cwd:t.cwd}),{sessionId:r,importedFromSessionId:e.session.sessionId,replaced:!1}}async forkSession(e,t={}){let n=await this.store.read(e);if(!n){let b=new Error(`source session not found: ${e}`);throw b.code=R.SessionNotFound,b}let r=t.agentId??n.agentId,o=r!==n.agentId;if(o&&!await this.registry.getAgent(r)){let I=new Error(`agent ${r} not found in registry`);throw I.code=R.AgentNotInstalled,I}let i=await this.histories.load(e).catch(()=>[]),a=i,d,c=t.mode??(t.side?"verbatim":"synthesis"),u,l,p,f=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let b=Fn(zo(i),t.forkAt);if(b<0){let I=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw I.code=R.InvalidParams,I}d=t.forkAt,a=i.slice(0,b+1)}else{let b=Nh(i);b?(d=b.messageId,a=i.slice(0,b.index+1)):(d="",a=i.slice(0,0))}else{if(t.forkAt!==void 0&&t.forkAt!==""){let I=Fn(zo(i),t.forkAt);if(I<0){let A=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw A.code=R.InvalidParams,A}d=t.forkAt,a=i.slice(0,I+1)}else d="",a=i;let b=await this.registry.getAgent(r);if(!b){let I=new Error(`agent ${r} not found in registry`);throw I.code=R.AgentNotInstalled,I}p=b,l=n.currentModel,u="running"}let h=await _c(e),k=c==="synthesis",m={...n,lineageId:Pn(),agentId:r,interactive:!1,...u!==void 0?{forkSynthesisState:u}:{},summarizedThroughEntry:a.length,...t.title!==void 0?{title:t.title}:{},currentUsage:void 0,...o?{currentModel:void 0,currentMode:void 0,agentCommands:void 0,agentModes:void 0,agentModels:void 0}:{},...t.model!==void 0?{currentModel:t.model}:{}},g=Nn({record:m,history:a,promptHistory:h.length>0?h:void 0,hydraVersion:ue,machine:St()}),y=`${ye}${xt()}`,w=t.cwd,v;if(t.cwd===void 0&&n.workspace!==void 0){let b=await this.deriveForkWorkspace(n.workspace,`${n.workspace.label}-fork-${y.slice(-6)}`);b!==void 0?(v=b,w=b.path):(w=n.workspace.sourceCwd,this.logger?.warn?.(`fork ${y}: could not derive an isolated workspace from ${n.workspace.path}; running unisolated in ${w}`))}await this.writeImportedRecord({sessionId:y,bundle:g,cwd:w,...v!==void 0?{workspace:v}:{},forkedFromSessionId:e,forkedFromMessageId:d,...t.side!==void 0?{side:{...t.side.selection!==void 0?{selection:t.side.selection}:{},...Oa(a)}}:{},...u!==void 0?{forkSynthesisState:u}:{}});let S=k?(async()=>{try{let b=await _e(p,[],{npmRegistry:this.npmRegistry}),I=await Hs({agentId:r,cwd:t.cwd??E.sessionDir(e),plan:b,history:a,modelId:l,sessionId:e,logger:this.logger,timeoutMs:f});I&&I.synopsis?await this.mutateRecord(y,{synopsis:I.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(y,{},["forkSynthesisState"]))}catch(b){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${b.message}`);try{await this.mutateRecord(y,{},["forkSynthesisState"])}catch(I){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${I.message}`)}}})():Promise.resolve();if(t.prompt!==void 0&&t.prompt.trim()!==""){let b=t.prompt;S.catch(()=>{}).then(()=>this.deliverHeadlessPrompt(y,b)).catch(I=>{this.logger?.warn(`forkSession(${e}): headless prompt delivery to ${y} failed: ${I.message}`)})}return{sessionId:y,forkedFromSessionId:e,forkedAt:d}}async deliverHeadlessPrompt(e,t){let n=await this.loadFromDisk(e);if(!n){this.logger?.warn(`deliverHeadlessPrompt: ${e} vanished before its prompt could be sent`);return}let r=this.sessions.get(e)??await this.resurrect(n),o=Th(),i={clientId:`fork-prompt-${xt().slice(0,8)}`,connection:new qe(o),clientInfo:{name:"hydra-acp-fork",version:ue}};await r.attach(i,"none");try{await r.prompt(i.clientId,{sessionId:e,prompt:[{type:"text",text:t}]})}finally{r.detach(i.clientId),o.close()}}async writeImportedRecord(e){if(await this.histories.rewrite(e.sessionId,e.bundle.history),e.bundle.toolBlobs)for(let[o,i]of Object.entries(e.bundle.toolBlobs))await Qi(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await Tt.utimes(E.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await Rc(E.tuiHistoryFile(e.sessionId),e.bundle.promptHistory).catch(()=>{});let n=new Date().toISOString(),r=e.forkedFromSessionId!==void 0;await this.enqueueMetaWrite(e.sessionId,async()=>{await this.store.write({sessionId:e.sessionId,lineageId:e.bundle.session.lineageId,upstreamSessionId:"",...r?{forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,...e.side!==void 0?{side:e.side}:{}}:{importedFromSessionId:e.bundle.session.sessionId,importedFromUpstreamSessionId:e.bundle.session.upstreamSessionId,importedFromMachine:e.bundle.exportedFrom.machine},agentId:e.bundle.session.agentId,cwd:e.cwd??e.bundle.session.cwd,workspace:e.workspace,title:e.bundle.session.title,synopsis:e.bundle.session.synopsis,summarizedThroughEntry:e.bundle.session.summarizedThroughEntry,...e.forkSynthesisState!==void 0?{forkSynthesisState:e.forkSynthesisState}:{},currentModel:e.bundle.session.currentModel,currentMode:e.bundle.session.currentMode,currentUsage:e.bundle.session.currentUsage,agentCommands:e.bundle.session.agentCommands,agentModes:e.bundle.session.agentModes,interactive:e.bundle.session.interactive,originatingClient:e.bundle.session.originatingClient,priority:e.bundle.session.priority,attentionFlags:[],createdAt:e.preservedCreatedAt??n,updatedAt:e.bundle.session.updatedAt})})}async agentStoreKey(e,t){let n=t.get(e);if(n!==void 0)return n;let r=e;try{let o=await this.registry.getAgent(e);o&&(r=Vr(o))}catch{}return t.set(e,r),r}async tombstoneAllGenerations(e,t,n){let r=await this.store.read(e).catch(()=>{}),o=new Map;for(let d of r?.upstreamGenerations??[])d.upstreamSessionId&&o.set(`${d.agentId}::${d.upstreamSessionId}`,{agentId:d.agentId,upstreamSessionId:d.upstreamSessionId});o.set(`${t.agentId}::${t.upstreamSessionId}`,{agentId:t.agentId,upstreamSessionId:t.upstreamSessionId});let i=new Date().toISOString(),a=new Map;for(let d of o.values())await this.tombstones.add({agentId:await this.agentStoreKey(d.agentId,a),upstreamSessionId:d.upstreamSessionId,sessionId:e,deletedAt:i,upstreamUpdatedAt:t.upstreamUpdatedAt,cwd:t.cwd,...t.title!==void 0?{title:t.title}:{},reason:n,...t.interactive!==void 0?{interactive:t.interactive}:{}}).catch(()=>{})}async deleteRecord(e,t="user"){let n=await this.store.read(e);if(!n)return!1;if(n.upstreamSessionId){let r=await Ln(e),o=sn(n,r.hasContent);await this.tombstoneAllGenerations(e,{agentId:n.agentId,upstreamSessionId:n.upstreamSessionId,upstreamUpdatedAt:n.updatedAt,cwd:n.cwd,...n.title!==void 0?{title:n.title}:{},...o!==void 0?{interactive:o}:{}},t)}return n.workspace!==void 0&&await this.releaseWorkspace(n.workspace,e).catch(()=>{}),await this.store.delete(e).catch(()=>{}),await this.histories.delete(e).catch(()=>{}),this.invalidateListCache(),!0}async waitForDeletion(e){let t=this.pendingDeletions.get(e);t&&await t}async isTombstoned(e,t){let n=await this.agentStoreKey(e,new Map);return(await this.tombstones.read(n,t).catch(()=>{})??(n!==e?await this.tombstones.read(e,t).catch(()=>{}):void 0))?.reason==="user"}async hasRecord(e){return await this.store.read(e).catch(()=>{})!==void 0}async isRetiredGeneration(e,t){let n=await this.store.read(e).catch(()=>{});return!n||n.upstreamSessionId===t?!1:(n.upstreamGenerations??[]).some(r=>r.upstreamSessionId===t)}async clearWorkspaceBinding(e){if(this.get(e)!==void 0)return"live";let t=await this.store.read(e).catch(()=>{});if(!t)return"missing";let n=t.workspace?.sourceCwd;return await this.mutateRecord(e,n!==void 0?{cwd:n}:{},["workspace"]),"cleared"}async setCwd(e,t){if(this.get(e)!==void 0)return"live";let n=await this.store.read(e).catch(()=>{});return n?n.workspace!==void 0?"bound":await this.dirExists(t)?(await this.mutateRecord(e,{cwd:t}),this.invalidateListCache(),"set"):"not-a-directory":"missing"}async setPriority(e,t){let n=this.get(e);if(n)return n.setPriority(t),!0;if(!await this.hasRecord(e))return!1;let r=t===void 0||t<=0?void 0:Math.floor(t);return await this.persistPriority(e,r),!0}async persistPriority(e,t){t===void 0?await this.mutateRecord(e,{},["priority"]):await this.mutateRecord(e,{priority:t}),this.invalidateListCache()}async setTitle(e,t){let n=this.get(e);return n?(await n.retitle(t),!0):await this.hasRecord(e)?(await this.persistTitle(e,t),!0):!1}async persistTitle(e,t){await this.mutateRecord(e,{title:t})}async persistSynopsis(e,t,n){await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:n})}async persistAgentChange(e,t,n,r={}){await this.mutateRecord(e,{agentId:t,upstreamSessionId:n},void 0,o=>({upstreamGenerations:Fc(o,t,n,void 0,r)}))}async persistSnapshot(e,t){let n={};t.currentModel!==void 0&&(n.currentModel=t.currentModel),t.currentMode!==void 0&&(n.currentMode=t.currentMode),t.currentUsage!==void 0&&(n.currentUsage=t.currentUsage),t.agentCommands!==void 0&&(n.agentCommands=t.agentCommands),t.agentModes!==void 0&&(n.agentModes=t.agentModes),t.agentModels!==void 0&&(n.agentModels=t.agentModels),t.configOptionValues!==void 0&&(n.configOptionValues=t.configOptionValues),t.interactive!==void 0&&(n.interactive=t.interactive),t.cwd!==void 0&&(n.cwd=t.cwd),await this.mutateRecord(e,n)}async setRead(e,t){let n=this.sessions.get(e);if(n)return n.setRead(t),!0;let r=!1;return await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;r=!0;let i=ys(o,t);i!==void 0&&await this.store.write({...o,readAt:i})}),this.invalidateListCache(),r}async persistReadState(e,t){await this.enqueueMetaWrite(e,async()=>{let n=await this.store.read(e);n&&await this.store.write({...n,lastTurnEndedAt:t.lastTurnEndedAt,readAt:t.readAt})})}async mutateRecord(e,t,n=[],r){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o,...t,...r?r(o):{},updatedAt:new Date().toISOString()};for(let a of n)delete i[a];await this.store.write(i)})}static EXTENSION_STATE_CAP_BYTES=64*1024;async getExtensionState(e,t){return(await this.store.read(e))?.extensionState?.[t]??{}}async getExtensionStateKey(e,t,n){return(await this.getExtensionState(e,t))[n]}async setExtensionStateKey(e,t,n,r){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o.extensionState??{}},a={...i[t]??{},[n]:r},d=Buffer.byteLength(JSON.stringify(a),"utf8");if(d>s.EXTENSION_STATE_CAP_BYTES)throw new Error(`extension_state: bucket for ${t} would be ${d} bytes; cap is ${s.EXTENSION_STATE_CAP_BYTES}`);i[t]=a;let c={...o,extensionState:i,updatedAt:new Date().toISOString()};await this.store.write(c)})}async deleteExtensionStateKey(e,t,n){await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r?.extensionState?.[t])return;let o={...r.extensionState},i={...o[t]};if(!(n in i))return;delete i[n],Object.keys(i).length===0?delete o[t]:o[t]=i;let a={...r,extensionState:o,updatedAt:new Date().toISOString()};await this.store.write(a)})}enqueueMetaWrite(e,t){return this.enqueueKeyed(this.metaWriteQueues,e,t)}enqueueKeyed(e,t,n){let o=(e.get(t)??Promise.resolve()).catch(()=>{}).then(n),i=o.catch(()=>{});return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)}),o}liveSessionsIn(e,t){let n=[];for(let r of this.sessions.values())r.sessionId!==t&&r.workspace?.path===e&&n.push(r);return n}async closeAll(){let e=[...this.sessions.values()];await Promise.allSettled(e.map(t=>t.close({deleteRecord:!1,by:"daemon-shutdown"}))),this.sessions.clear()}async flushSynopsis(e){await this.synopsisCoordinator.flush(e)}async shutdownSynopsis(){await this.synopsisCoordinator.shutdown()}scheduleSynopsis(e){this.synopsisCoordinator.schedule(e)}scheduleCompaction(e,t){if(t?.targetAgentId){this.mutateRecord(e,{pendingAgentSwap:t.targetAgentId}).catch(r=>{this.logger?.warn(`scheduleCompaction: failed to stamp pendingAgentSwap for ${e}: ${r instanceof Error?r.message:String(r)}`)});let n=t.targetAgentId;(async()=>{try{let r=await this.store.read(e),o=await this.histories.load(e,{maxEntries:1/0});if(fc(o)===0){this.logger?.info(`compaction: zero-turn fast-path swap sessionId=${e} target=${n}`),await this.dispatchSynthesisSwap(e,void 0,o.length,n);return}if(!r?.synopsis||r.summarizedThroughEntry===void 0){this.synopsisCoordinator.scheduleCompaction(e,t);return}if(o.length!==r.summarizedThroughEntry){this.synopsisCoordinator.scheduleCompaction(e,t);return}this.logger?.info(`compaction: fast-path swap sessionId=${e} target=${n} (reusing artifact @${r.summarizedThroughEntry})`),await this.dispatchSynthesisSwap(e,r.synopsis,r.summarizedThroughEntry,n)}catch(r){this.logger?.warn(`scheduleCompaction: fast-path check failed for ${e}: ${r instanceof Error?r.message:String(r)} \u2014 falling back to synthesis`),this.synopsisCoordinator.scheduleCompaction(e,t)}})();return}this.synopsisCoordinator.scheduleCompaction(e,t)}getCompactionInFlight(){let e=this.synopsisCoordinator.size();return e.inflight>0||e.queued>0}async getPendingAgentSwap(e){return(await this.store.read(e).catch(()=>{}))?.pendingAgentSwap}async getCompactionState(e){return(await this.store.read(e).catch(()=>{}))?.compactionState}async persistRollbackBreadcrumb(e,t){await this.mutateRecord(e,{},void 0,n=>{let r=n.rollbackBreadcrumb;return r!==void 0&&t.runId!==void 0&&r.runId===t.runId?(this.logger?.info(`compaction: keeping rollback breadcrumb pinned at ${r.previousUpstreamSessionId} for runId=${t.runId} sessionId=${e} (later swap of the same run)`),{}):{rollbackBreadcrumb:t}})}async getUpstreamGenerations(e){return(await this.store.read(e).catch(()=>{}))?.upstreamGenerations??[]}async getRollbackBreadcrumb(e){return(await this.store.read(e).catch(()=>{}))?.rollbackBreadcrumb}emitSwapPhase(e,t,n){let r=this.get(e);if(r){if(t){if(n.phase==="failed"){r.broadcastPendingAgentSwap(null);return}if(n.phase==="converged")return;r.broadcastPendingAgentSwap(t);return}r.broadcastCompactionPhase(n)}}async getSummarizedThroughEntry(e){let t=this.sessions.get(e);return t?t.summarizedThroughEntry:(await this.store.read(e).catch(()=>{}))?.summarizedThroughEntry}async flushMetaWrites(){let e=[...this.metaWriteQueues.values()];e.length!==0&&await Promise.allSettled(e)}async flushHistoryWrites(){await this.histories.flushAll()}async reconcilePermissionFlags(){let e=await this.store.list().catch(()=>[]),t=0;for(let n of e){let r=n.attentionFlags??[],o=r.filter(i=>!(i.source==="daemon"&&i.reason.startsWith("permission:")));if(o.length!==r.length){let i=r.length-o.length;t+=i,await this.mutateRecord(n.sessionId,{attentionFlags:o}).catch(()=>{})}}t>0&&this.logger?.info(`cleared ${t} stale permission attention flags on startup`)}async resumePendingCompactions(){let e=new Set(["requested","running","swap_pending","swap_deferred"]),t=await this.store.list().catch(()=>[]);for(let n of t){let r=n.compactionState;if(r!=null){if(!e.has(r.status)){this.logger?.info(`compaction: not resuming sessionId=${n.sessionId} status=${r.status} (terminal \u2014 user must re-trigger explicitly)`);continue}this.logger?.info(`compaction: resuming sessionId=${n.sessionId} status=${r.status} from prior daemon`);try{this.scheduleCompaction(n.sessionId)}catch(o){this.logger?.warn(`compaction: resume failed for sessionId=${n.sessionId}: ${o instanceof Error?o.message:String(o)}`)}}}}async resumePendingAgentSwaps(){let e=await this.store.list().catch(()=>[]);for(let t of e){let n=t.pendingAgentSwap;if(n)try{let r=await this.histories.load(t.sessionId).catch(()=>[]);t.synopsis!==void 0&&t.summarizedThroughEntry!==void 0&&t.summarizedThroughEntry>=r.length&&t.synopsis?(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${n} with persisted synopsis (history=${r.length})`),await this.dispatchSynthesisSwap(t.sessionId,t.synopsis,t.summarizedThroughEntry??r.length,n)):(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${n} via fresh synthesis (history=${r.length} watermark=${t.summarizedThroughEntry??"(none)"})`),this.scheduleCompaction(t.sessionId,{targetAgentId:n}))}catch(r){this.logger?.warn(`agent-swap: resume failed for sessionId=${t.sessionId}: ${r instanceof Error?r.message:String(r)}`)}}}async resurrectPendingQueues(){let e=await this.store.list().catch(()=>[]);for(let t of e){let n=await Cd(t.sessionId).catch(()=>[]);if(n.length===0)continue;let r=Date.now(),o=n.filter(d=>r-d.enqueuedAt<Tc),i=n.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${Tc/1e3}s)`),await Cn(t.sessionId,o).catch(()=>{})),o.length===0)continue;let a=await this.loadFromDisk(t.sessionId).catch(()=>{});if(!a){this.logger?.warn(`queue replay: no meta for ${t.sessionId}; discarding ${o.length} entr${o.length===1?"y":"ies"}`),await Cn(t.sessionId,[]).catch(()=>{});continue}try{let d=await this.resurrect(a);this.logger?.info(`queue replay: resurrected ${t.sessionId} and replaying ${o.length} prompt(s)`),d.replayPersistedQueue(o)}catch(d){this.logger?.warn(`queue replay: failed to resurrect ${t.sessionId}: ${d.message}`)}}}};function Eh(s,e){if(typeof s!="string"||s.length===0)return!1;let t=Un.resolve(s),n=Un.resolve(e);return t===n||t.startsWith(n+Un.sep)}function Ph(s){return s!==void 0&&/^\{\s*"session_id"\s*:\s*"[^"]*"\s*,\s*"(?:transcript_path|cwd|permission_mode|hook_event_name)"\s*:/.test(s)}function Ec(s,e){if(s===void 0||s.length===0)return!0;let t=Vo(s);if(Vo(e.cwd)===t)return!0;let n=e.workspace?.sourceCwd;return n!==void 0&&Vo(n)===t}function Vo(s){return s.length>1&&s.endsWith("/")?s.replace(/\/+$/,""):s}function Mh(s,e){let n=(s.mergedAvailableCommands().length>0?s.agentOnlyAdvertisedCommands().map(p=>p.description!==void 0?{name:p.name,description:p.description}:{name:p.name}):void 0)??e?.agentCommands,r=s.availableModes(),i=(r.length>0?r.map(p=>{let f={id:p.id};return p.name!==void 0&&(f.name=p.name),p.description!==void 0&&(f.description=p.description),f}):void 0)??e?.agentModes,a=s.availableModels(),c=(a.length>0?a.map(p=>{let f={modelId:p.modelId};return p.name!==void 0&&(f.name=p.name),p.description!==void 0&&(f.description=p.description),f}):void 0)??e?.agentModels,u=s.extraConfigOptionValues(),l=Object.keys(u).length>0?u:e?.configOptionValues;return Po({sessionId:s.sessionId,lineageId:e?.lineageId??Pn(),upstreamSessionId:s.upstreamSessionId,importedFromSessionId:e?.importedFromSessionId,importedFromUpstreamSessionId:e?.importedFromUpstreamSessionId,importedFromMachine:e?.importedFromMachine,agentId:s.agentId,cwd:s.cwd,title:s.title,synopsis:e?.synopsis,summarizedThroughEntry:e?.summarizedThroughEntry,agentArgs:s.agentArgs,currentModel:s.currentModel??e?.currentModel,currentMode:s.currentMode??e?.currentMode,currentUsage:Oc(s.persistableUsage)??e?.currentUsage,agentCommands:n,agentModes:i,agentModels:c,configOptionValues:l,parentSessionId:s.parentSessionId??e?.parentSessionId,forkedFromSessionId:s.forkedFromSessionId??e?.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId??e?.forkedFromMessageId,side:s.side??e?.side,originatingClient:s.originatingClient??e?.originatingClient,interactive:s.interactive??e?.interactive,priority:s.priority??e?.priority,lastTurnEndedAt:s.lastTurnEndedAt??e?.lastTurnEndedAt,readAt:s.readAt??e?.readAt,forwardedEnv:s.forwardedEnv??e?.forwardedEnv,workspace:s.workspace,attentionFlags:s.listAttentionFlags(),extensionState:e?.extensionState,upstreamGenerations:e?Fc(e,s.agentId,s.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(s.createdAt).toISOString()})}function Oc(s){if(!s)return;let e={};return s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size),s.costAmount!==void 0&&(e.costAmount=s.costAmount),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),s.cumulativeCost!==void 0&&(e.cumulativeCost=s.cumulativeCost),Object.keys(e).length>0?e:void 0}function _h(s){return s?{...s}:void 0}function $h(s){return(s.extendsChain??[s.id]).some(t=>t==="claude-acp"||t.startsWith("claude-acp-"))}var Oh=[{type:"system",subtype:"background_tasks_changed"}];function Go(s,e={}){if(!$h(s))return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t,emitRawSDKMessages:Oh}}}function Ws(s,e){let t=e.fromObject(s);if(t!==void 0)return t;let n=s[e.nestedKey];if(n&&typeof n=="object"&&!Array.isArray(n)){let i=e.fromObject(n);if(i!==void 0)return i}let r=s._meta;if(r&&typeof r=="object"&&!Array.isArray(r)){for(let[i,a]of Object.entries(r))if(i!=="hydra-acp"&&a&&typeof a=="object"&&!Array.isArray(a)){let d=e.fromObject(a);if(d!==void 0)return d}}let o=Fh(s,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function Ko(s){return Ws(s,{nestedKey:"models",configId:"model",fromObject:e=>Ie(e.currentModelId)??Ie(e.currentModel)??Ie(e.modelId)??Ie(e.model),fromConfig:e=>Ie(e.currentValue)})}function yt(s,e){if(!s||typeof s!="object")return s;let t=s;if(t.code!==R.AuthRequired)return s;let n=c=>!!c&&typeof c=="object"&&!Array.isArray(c),r=n(t.data)?t.data:{},o=n(r._meta)?r._meta:{},i=n(o["hydra-acp"])?o["hydra-acp"]:{},a=typeof t.message=="string"?t.message:"authentication required",d=new Error(a);return d.code=R.AuthRequired,d.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function Pc(s){return/^[A-Za-z0-9_\-./=:@]+$/.test(s)?s:`'${s.replace(/'/g,"'\\''")}'`}function Mc(s,e,t,n){if(s&&typeof s=="object"&&s.code===R.AuthRequired)return s;let r=s instanceof Error?s.message:String(s),o=r.includes("stderr:"),i=o?"":e.stderrTailText(),a=n?`to reproduce: (cd ${Pc(n.cwd)} && ${[n.command,...n.args].map(Pc).join(" ")})`:"";if(!i&&!a)return s;let d=[o?r:`agent ${t} failed to start: ${r}`];i&&d.push(`stderr: ${i}`),a&&d.push(a);let c=new Error(d.join(`
189
+ `));if(s&&typeof s=="object"){let u=s;typeof u.code=="number"&&(c.code=u.code),u.data!==void 0&&(c.data=u.data)}return c}function Hn(s){return s._meta?.steering?.supported===!0}function jn(s){if(!Array.isArray(s))return;let e=[];for(let t of s){if(!t||typeof t!="object")continue;let n=t;if(typeof n.id!="string")continue;let r=typeof n.description=="string"?n.description:"",o=n.type==="agent"||n.type==="terminal"?n.type:void 0,i=typeof n.name=="string"?n.name:void 0,a=n._meta,d=a!==null&&typeof a=="object"&&!Array.isArray(a)?a:void 0;e.push({id:n.id,description:r,...o&&{type:o},...i!==void 0&&{name:i},...d&&{_meta:d}})}return e.length>0?e:void 0}function Ie(s){if(typeof s!="string")return;let e=s.trim();return e.length>0?e:void 0}function Fh(s,e){let t=s.configOptions;if(Array.isArray(t))for(let n of t){if(!n||typeof n!="object"||Array.isArray(n))continue;let r=n;if(r.id===e)return r}}function tn(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.configOptions)}function nn(s){let e=s.configOptions;if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!n||typeof n!="object"||Array.isArray(n))continue;let r=n,o=Ie(r.id);if(!o||o==="model"||o==="mode"||o==="agent")continue;let i=So(r.options);if(i.length===0)continue;let a=Ie(r.description);t.push({id:o,name:Ie(r.name)??o,...a?{description:a}:{},category:Ie(r.category)??"other",type:"select",currentValue:Ie(r.currentValue)??i[0].value,options:i})}return t}function ht(s){return s.length>0?s:void 0}function Qo(s){return Ws(s,{nestedKey:"models",configId:"model",fromObject:e=>{let t=xn(e.availableModels);return t.length>0?t:void 0},fromConfig:e=>{let t=xn(e.options);return t.length>0?t:void 0}})??[]}function Yo(s){return Ws(s,{nestedKey:"modes",configId:"mode",fromObject:e=>{let t=Is(e.availableModes);return t.length>0?t:void 0},fromConfig:e=>{let t=Is(e.options);return t.length>0?t:void 0}})??[]}function Xo(s){return Ws(s,{nestedKey:"modes",configId:"mode",fromObject:e=>Ie(e.currentModeId)??Ie(e.currentMode)??Ie(e.modeId)??Ie(e.mode),fromConfig:e=>Ie(e.currentValue)})}function Nh(s){for(let e=s.length-1;e>=0;e--){let t=s[e];if(!t||t.method!=="session/update")continue;let n=t.params?.update;if(n?.sessionUpdate==="turn_complete"&&!(typeof n.messageId!="string"||n.messageId.length===0))return{index:e,messageId:n.messageId}}}async function _c(s){try{let e=await Tt.readFile(E.tuiHistoryFile(s),"utf8"),t=[];for(let n of e.split(`
190
+ `))if(n.length!==0)try{let r=JSON.parse(n);typeof r=="string"&&t.push(r)}catch{}return t}catch{return[]}}function Fc(s,e,t,n=new Date().toISOString(),r={}){let{retiredCost:o,retiredUsed:i,startedUsed:a,lifetimeCost:d,reason:c,runId:u}=r,l=h=>d!==void 0&&h.lifetimeCostAtStart!==void 0?Math.max(0,d-h.lifetimeCostAtStart):o,p=s.upstreamGenerations&&s.upstreamGenerations.length>0?[...s.upstreamGenerations]:s.upstreamSessionId?[{upstreamSessionId:s.upstreamSessionId,agentId:s.agentId}]:[],f=p[p.length-1];if(f&&f.upstreamSessionId===t){if(p.length>=2){let h=p[p.length-2];if(h){let k=l(h);p[p.length-2]={...h,...k!==void 0&&h.cost===void 0?{cost:k}:{},...i!==void 0&&h.usedAtEnd===void 0?{usedAtEnd:i}:{}}}}return(c!==void 0&&f.reason===void 0||a!==void 0&&f.usedAtStart===void 0||d!==void 0&&f.lifetimeCostAtStart===void 0)&&(p[p.length-1]={...f,...c!==void 0&&f.reason===void 0?{reason:c,...u!==void 0?{runId:u}:{}}:{},...a!==void 0&&f.usedAtStart===void 0?{usedAtStart:a}:{},...d!==void 0&&f.lifetimeCostAtStart===void 0?{lifetimeCostAtStart:d}:{}}),p}return f&&f.endedAt===void 0&&(p[p.length-1]={...f,endedAt:n,...(()=>{let h=l(f);return h!==void 0?{cost:h}:{}})(),...i!==void 0?{usedAtEnd:i}:{}}),p.push({upstreamSessionId:t,agentId:e,startedAt:n,...c!==void 0?{reason:c}:{},...u!==void 0?{runId:u}:{},...a!==void 0?{usedAtStart:a}:{},...d!==void 0?{lifetimeCostAtStart:d}:{}}),p}async function Ln(s){try{let e=await Tt.stat(E.historyFile(s));return{mtime:new Date(e.mtimeMs).toISOString(),hasContent:e.size>0}}catch{return{hasContent:!1}}}function sn(s,e){return s.interactive!==void 0?s.interactive:s.originatingClient?.name===Ds?!1:e?!0:void 0}import{spawn as Dh}from"child_process";import*as Js from"fs";import*as ot from"fs/promises";import*as Vs from"path";import Hh from"pino-roll";var qs=class{windowMs;maxFailures;now;recentExits=[];tripped_;constructor(e={}){this.windowMs=e.windowMs??3e5,this.maxFailures=e.maxFailuresInWindow??10,this.now=e.now??Date.now}recordExit(e,t,n){if(e===78){let i=`exited with code 78 (unrecoverable); fix and run \`${n}s start ${t}\``;return this.tripped_=i,{tripped:i}}let r=this.now();this.recentExits.push(r);let o=r-this.windowMs;for(;this.recentExits.length>0&&this.recentExits[0]<o;)this.recentExits.shift();if(this.recentExits.length>this.maxFailures){let i=Math.round(this.windowMs/6e4),a=`${this.recentExits.length} exits in ${i}m (crash loop); fix and run \`${n}s start ${t}\``;return this.tripped_=a,{tripped:a}}return"restart"}reset(){this.recentExits=[],this.tripped_=void 0}get tripped(){return this.tripped_}};import*as Nc from"fs/promises";import*as Zo from"path";var zs=process.platform!=="win32";var jh=1e3,Lh=6e4,ei=3e3,rn=class{entries=new Map;stopping=!1;context;tokenRegistry;breakerOptions;restartBaseMs;restartCapMs;adapter;constructor(e,t,n,r={}){this.adapter=t,this.context=n,this.tokenRegistry=r.tokenRegistry,this.breakerOptions=r.breakerOptions,this.restartBaseMs=r.restartBaseMs??jh,this.restartCapMs=r.restartCapMs??Lh;for(let o of e)this.entries.set(o.name,this.makeEntry(o))}setContext(e){this.context=e}reportVersion(e,t){let n=this.entries.get(e);n&&(n.version=t)}async start(){if(!this.context)throw new Error(`${this.managerName()}: setContext must be called before start`);await ot.mkdir(this.adapter.paths.dir(),{recursive:!0}),await this.reapOrphans();let e=[];for(let t of this.entries.values())t.config.enabled&&e.push(this.spawn(t,0));await Promise.all(e)}async stop(){this.stopping=!0;let e=[];for(let t of this.entries.values()){t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let n=t.child;if(n){try{n.kill("SIGTERM")}catch{}e.push(new Promise(r=>{if(n.exitCode!==null||n.signalCode!==null){r();return}let o=setTimeout(()=>{try{n.kill("SIGKILL")}catch{}r()},ei);n.on("exit",()=>{clearTimeout(o),r()})}))}}await Promise.allSettled(e);for(let t of this.entries.values()){try{t.logStream?.end()}catch{}t.child=void 0,t.logStream=void 0,t.pid=void 0}}list(){return[...this.entries.values()].map(e=>this.infoFor(e))}get(e){let t=this.entries.get(e);return t?this.infoFor(t):void 0}has(e){return this.entries.has(e)}async startByName(e){let t=this.entries.get(e);if(!t)throw Bn(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");if(t.child)throw Bn(new Error(`${this.adapter.kind} ${e} already running`),"CONFLICT");return t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0),t.manuallyStopped=!1,t.restartCount=0,t.breaker.reset(),t.failureReason=void 0,await this.spawn(t,0),this.infoFor(t)}async stopByName(e){let t=this.entries.get(e);if(!t)throw Bn(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");t.manuallyStopped=!0,t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let n=t.child;return n?(await this.terminate(t,n),this.infoFor(t)):this.infoFor(t)}async restartByName(e){return await this.stopByName(e),this.startByName(e)}register(e){if(this.entries.has(e.name))throw Bn(new Error(`${this.adapter.kind} ${e.name} already exists`),"CONFLICT");if(!this.context)throw new Error(`${this.managerName()}: setContext must be called before register`);let t=this.makeEntry(e);return this.entries.set(e.name,t),e.enabled&&this.spawn(t,0).catch(n=>{t.failureReason=`spawn: ${n.message}`}),this.infoFor(t)}async unregister(e){let t=this.entries.get(e);if(!t)throw Bn(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");t.manuallyStopped=!0,t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let n=t.child;n&&await this.terminate(t,n);try{t.logStream?.end()}catch{}this.entries.delete(e)}async terminate(e,t){if(t.exitCode!==null||t.signalCode!==null)return;let n=new Promise(o=>{e.exitWaiters.push(o)});try{t.kill("SIGTERM")}catch{}let r=setTimeout(()=>{try{t.kill("SIGKILL")}catch{}},ei);typeof r.unref=="function"&&r.unref();try{await n}finally{clearTimeout(r)}}infoFor(e){let t;return e.failureReason!==void 0?t="failed":e.child?t="running":e.restartTimer?t="restarting":e.config.enabled?t="stopped":t="disabled",{name:e.config.name,status:t,pid:e.pid,enabled:e.config.enabled,restartCount:e.restartCount,startedAt:e.startedAt,lastExitCode:e.lastExitCode,logPath:this.adapter.paths.logFile(e.config.name),version:e.version,failureReason:e.failureReason}}makeEntry(e){return{config:e,child:void 0,logStream:void 0,restartTimer:void 0,pid:void 0,startedAt:void 0,restartCount:0,lastExitCode:void 0,manuallyStopped:!1,exitWaiters:[],version:void 0,processToken:void 0,breaker:new qs(this.breakerOptions),failureReason:void 0}}async reapOrphans(){let e;try{e=await ot.readdir(this.adapter.paths.dir(),{withFileTypes:!0})}catch(t){if(t.code==="ENOENT")return;throw t}for(let t of e){if(!t.isDirectory())continue;let n=this.adapter.paths.pidFile(t.name),r;try{let o=await ot.readFile(n,"utf8"),i=Number.parseInt(o.trim(),10);Number.isInteger(i)&&i>0&&(r=i)}catch{}if(typeof r=="number"&&ti(r)){try{process.kill(r,"SIGTERM")}catch{}let o=Date.now()+ei;for(;Date.now()<o&&ti(r);)await new Promise(i=>setTimeout(i,50));if(ti(r))try{process.kill(r,"SIGKILL")}catch{}}await ot.unlink(n).catch(()=>{})}}async spawn(e,t){if(this.stopping||e.manuallyStopped)return;let n=this.context;if(!n)throw new Error(`${this.managerName()}.spawn called before setContext`);let r=e.config,o=r.command.length>0?r.command:[r.name],i=Vs.dirname(this.adapter.paths.logFile(r.name)),a;try{await ot.mkdir(i,{recursive:!0}),a=await Hh({file:Vs.join(i,`${r.name}.log`),size:"5m",mkdir:!0,symlink:zs,limit:{count:5}}),a.on("error",m=>{e.failureReason=`log stream: ${m.message}`})}catch(m){if(this.stopping||e.manuallyStopped)return;e.failureReason=`log setup: ${m.message}`,this.scheduleRestart(e,t+1);return}if(this.stopping||e.manuallyStopped){try{a.end()}catch{}return}a.write(`[hydra-acp] ${new Date().toISOString()} starting ${this.adapter.kind} ${r.name} (attempt ${t+1})
191
+ `);let d=this.tokenRegistry?.mint(r.name,this.adapter.tokenRole)??n.serviceToken;e.processToken=d,e.version=void 0;let c={...ss(),HYDRA_ACP_DAEMON_URL:n.daemonUrl,HYDRA_ACP_DAEMON_HOST:n.daemonHost,HYDRA_ACP_DAEMON_PORT:String(n.daemonPort),HYDRA_ACP_TOKEN:d,HYDRA_ACP_WS_URL:n.daemonWsUrl,HYDRA_ACP_HOME:n.hydraHome,[this.adapter.nameEnvVar]:r.name,...r.env},[u,...l]=o;if(u===void 0){a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} has empty command
192
+ `),a.end();return}let p=ce(u),f=[...l,...r.args].map(ce),h;try{let m=Nt(p,f);h=Dh(m.command,m.args,{env:c,stdio:["ignore","pipe","pipe"],detached:!1,shell:m.shell,windowsHide:!0})}catch(m){a.write(`[hydra-acp] failed to spawn ${r.name}: ${m.message}
193
+ `),a.end(),this.scheduleRestart(e,t);return}let k=m=>{try{a.write(typeof m=="string"?m:m.toString())}catch{}};if(h.stdout?.on("data",k),h.stderr?.on("data",k),typeof h.pid=="number")try{Js.writeFileSync(this.adapter.paths.pidFile(r.name),`${h.pid}
194
194
  `,{encoding:"utf8",mode:384})}catch(m){a.write(`[hydra-acp] failed to write pid file for ${r.name}: ${m.message}
195
195
  `)}e.child=h,e.logStream=a,e.pid=typeof h.pid=="number"?h.pid:void 0,e.startedAt=Date.now(),e.lastExitCode=void 0,h.on("error",m=>{a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} error: ${m.message}
196
- `)}),h.on("exit",(m,g)=>{try{qs.unlinkSync(this.adapter.paths.pidFile(r.name))}catch{}a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} exited code=${m??"null"} signal=${g??"null"}
196
+ `)}),h.on("exit",(m,g)=>{try{Js.unlinkSync(this.adapter.paths.pidFile(r.name))}catch{}a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} exited code=${m??"null"} signal=${g??"null"}
197
197
  `),e.child=void 0,e.pid=void 0,e.lastExitCode=typeof m=="number"?m:void 0,e.processToken&&(this.tokenRegistry?.revoke(r.name),e.processToken=void 0);let y=e.exitWaiters.splice(0);for(let v of y)v();if(this.stopping||e.manuallyStopped){try{a.end()}catch{}e.logStream=void 0;return}e.restartCount+=1;let w=e.breaker.recordExit(m,r.name,this.adapter.kind);if(typeof w=="object"){e.failureReason=w.tripped,a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} circuit breaker tripped: ${w.tripped}
198
- `);try{a.end()}catch{}e.logStream=void 0;return}this.scheduleRestart(e,t+1)})}scheduleRestart(e,t){if(this.stopping||e.manuallyStopped)return;let n=Math.min(this.restartBaseMs*2**Math.min(t,10),this.restartCapMs);e.restartTimer=setTimeout(()=>{e.restartTimer=void 0,this.spawn(e,t).catch(r=>{e.failureReason=`spawn: ${r.message}`})},n),typeof e.restartTimer.unref=="function"&&e.restartTimer.unref()}managerName(){return this.adapter.kind==="extension"?"ExtensionManager":"TransformerManager"}};function Zo(s){try{return process.kill(s,0),!0}catch{return!1}}function Ln(s,e){return s.code=e,s}Y();var jh={kind:"extension",nameEnvVar:"HYDRA_ACP_EXTENSION_NAME",tokenRole:"extension",paths:{dir:T.extensionsDir,logFile:T.extensionLogFile,pidFile:T.extensionPidFile}},Js=class extends sn{constructor(e,t,n={}){super(e,jh,t,n)}};Y();var Lh={kind:"transformer",nameEnvVar:"HYDRA_ACP_TRANSFORMER_NAME",tokenRole:"transformer",paths:{dir:T.transformersDir,logFile:T.transformerLogFile,pidFile:T.transformerPidFile}},Vs=class extends sn{connected=new Map;constructor(e,t,n={}){super(e,Lh,t,n)}registerConnection(e,t,n){this.connected.set(e,{name:e,connection:t,intercepts:new Set(n)})}deregisterConnection(e){this.connected.delete(e)}resolveChain(e){let t=[];for(let n of e){let r=this.connected.get(n);r&&t.push(r)}return t}interestedIn(e){let t=[];for(let n of this.connected.values())n.intercepts.has(e)&&t.push(n);return t}};var Gs=class{entries=new Map;changeHandlers=[];register(e,t,n){this.entries.set(e,{connection:t,commands:[...n]}),this.fireChanged()}clear(e){this.entries.delete(e)&&this.fireChanged()}get(e){return this.entries.get(e)}has(e){return this.entries.has(e)}list(){let e=[];for(let[t,n]of this.entries)for(let r of n.commands)e.push({name:t,command:r});return e}onChange(e){return this.changeHandlers.push(e),()=>{let t=this.changeHandlers.indexOf(e);t>=0&&this.changeHandlers.splice(t,1)}}fireChanged(){for(let e of this.changeHandlers)try{e()}catch{}}};Y();Y();import*as Un from"fs/promises";async function Fc(s){let e=T.pidFile(),t=`${e}.${process.pid}.tmp`;await Un.writeFile(t,JSON.stringify(s)+`
199
- `,{encoding:"utf8",mode:384}),await Un.rename(t,e)}Y();import*as Wn from"fs/promises";import*as Ks from"path";var Bn=s=>{process.stderr.write(s+`
200
- `)};function ei(s){Bn=s??(e=>process.stderr.write(e+`
201
- `))}async function Nc(s,e){let t=Ue();if(!t)return;let n=await s.load(),r=new Map;for(let d of n.agents)r.set(d.id,d.version??"current");let o=e.activeAgentVersions(),i=Ks.join(T.agentsDir(),t),a;try{a=await Wn.readdir(i,{withFileTypes:!0})}catch(d){let c=d;if(c.code==="ENOENT")return;Bn(`hydra-acp: prune: failed to read ${i}: ${c.message}`);return}for(let d of a){if(!d.isDirectory())continue;let c=d.name,u=r.get(c);if(u===void 0)continue;let l=o.get(c)??new Set,p=Ks.join(i,c),f;try{f=await Wn.readdir(p,{withFileTypes:!0})}catch(h){Bn(`hydra-acp: prune: failed to read ${p}: ${h.message}`);continue}for(let h of f){if(!h.isDirectory())continue;let k=h.name;if(k===u||l.has(k)||k.includes(".partial-"))continue;let m=Ks.join(p,k);try{await Wn.rm(m,{recursive:!0,force:!0}),Bn(`hydra-acp: pruned stale ${c} ${k} (${m})`)}catch(g){Bn(`hydra-acp: prune: failed to remove ${m}: ${g.message}`)}}}}function Dc(s){let e,t=!1,n=0,r=(a,d)=>{s.logger&&s.logger[a](`agent-sync: ${d}`)},o=async()=>{let a=[];try{let u=await s.registry.load();for(let l of u.agents)await Gr(l)==="yes"&&a.push(l.id)}catch(u){return r("warn",`registry load failed: ${u.message}`),s.intervalMs}if(a.length===0)return s.intervalMs;let d=n%a.length;n=(n+1)%a.length;let c=a[d];try{let{synced:u,skipped:l}=await s.manager.syncFromAgent(c);r("info",`${c}: synced ${u.length}, skipped ${l}`)}catch(u){r("warn",`${c}: ${u.message}`)}return Math.max(1,Math.floor(s.intervalMs/a.length))},i=a=>{t||(e=setTimeout(()=>{o().then(d=>{i(d)}).catch(d=>{r("warn",`tick crashed: ${d.message}`),i(s.intervalMs)})},a),e.unref())};return i(s.intervalMs),()=>{t=!0,e&&(clearTimeout(e),e=void 0)}}async function ti(s){let e=s.maxDeletions??200,t=(f,h)=>{s.logger&&s.logger[f](`session-gc: ${h}`)},n=Date.now(),r=s.maxAgeMs>0?n-s.maxAgeMs:Number.POSITIVE_INFINITY,o=await s.manager.list({includeNonInteractive:!0}).catch(f=>(t("warn",`manager.list failed: ${f.message}`),[])),i=[];for(let f of o){if(f.status!=="cold")continue;if((s.selection??"explicit")==="explicit"){if(f.interactive!==!1)continue}else if(f.interactive===!0)continue;let k=Date.parse(f.updatedAt);Number.isFinite(k)&&(s.maxAgeMs>0&&k>r||i.push({sessionId:f.sessionId,lastUsedMs:k}))}if(i.length===0)return s.verbose&&t("info","no candidates"),{considered:0,deleted:0,failed:0,deferred:0};i.sort((f,h)=>f.lastUsedMs-h.lastUsedMs);let a=i.slice(0,e),d=a[0]?.lastUsedMs,c=0,u=0;for(let{sessionId:f}of a)try{await s.manager.deleteRecord(f,"expired")&&(c+=1)}catch(h){u+=1,t("warn",`delete ${f} failed: ${h.message}`)}let l=i.length-a.length;if(s.verbose||c>0||u>0){let f=(s.selection??"explicit")==="unpromoted"?"unpromoted":"non-interactive";t("info",`swept ${c} ${f} session(s) older than ${Uh(s.maxAgeMs)}`+(u>0?`; ${u} failed`:"")+(l>0?`; ${l} deferred to next sweep`:""))}let p={considered:i.length,deleted:c,failed:u,deferred:l};return d!==void 0&&(p.oldestLastUsedMs=d),p}function Hc(s){let e,t=!1,n=!1,r=o=>{t||(e=setTimeout(()=>{(async()=>{if(!n){n=!0;try{await ti({manager:s.manager,maxAgeMs:s.maxAgeMs,selection:"unpromoted",...s.maxDeletionsPerSweep!==void 0?{maxDeletions:s.maxDeletionsPerSweep}:{},...s.logger?{logger:s.logger}:{}})}finally{n=!1}}})().catch(a=>{s.logger?.warn(`session-gc: sweep crashed: ${a.message}`)}).finally(()=>{r(s.intervalMs)})},o),e.unref())};return r(s.intervalMs),()=>{t=!0,e&&(clearTimeout(e),e=void 0)}}function Uh(s){if(s<=0)return"any age";let e=s/(1440*60*1e3);if(e>=1)return`${e.toFixed(e>=10?0:1)}d`;let t=s/(3600*1e3);return`${t.toFixed(t>=10?0:1)}h`}import{createHash as Bh}from"crypto";function qn(s){if(Array.isArray(s))return s.map(qn);if(s!==null&&typeof s=="object"){let e={};for(let t of Object.keys(s).sort())e[t]=qn(s[t]);return e}return s}function jc(s){let e={};for(let[n,r]of Object.entries(s)){let o=Cr(n);if(o.nested){let i={};for(let[a,d]of Object.entries(r??{}))Rr(a).reload==="restart"&&(i[a]=d);Object.keys(i).length>0&&(e[n]=i);continue}o.reload==="restart"&&(e[n]=r)}let t=JSON.stringify(qn(e));return Bh("sha256").update(t).digest("hex").slice(0,16)}function Lc(s,e){let t=[],n=(r,o)=>JSON.stringify(qn(r))!==JSON.stringify(qn(o));for(let r of Object.keys(e)){let o=Cr(r),i=e[r],a=s[r];if(o.nested){for(let d of Object.keys(i??{})){if(Rr(d).reload!=="warn")continue;let c=i[d],u=(a??{})[d];n(u,c)&&t.push(`${r}.${d}`)}continue}o.reload==="warn"&&n(a,i)&&t.push(r)}return t}import*as Bc from"fs/promises";Y();var Wh=3e3;async function Uc(){try{return(await Bc.stat(T.config())).mtimeMs}catch{return}}function Wc(s){let e=s.intervalMs??Wh,t=!1,n,r,o=Uc().then(d=>{r=d}),i=async()=>{await o;let d=await Uc();if(d===r)return;r=d;let c;try{c=await gn()}catch(l){s.logger?.warn(`config-reload: config.json changed but did not parse (${l.message}); keeping the loaded config`);return}try{s.apply(c)}catch(l){s.logger?.warn(`config-reload: applying live config failed: ${l.message}`)}let u=Lc(s.bootConfig,c);s.onDrift?.(u),s.logger?.info(u.length>0?`config-reload: applied live config; restart-only keys differing from boot: ${u.join(", ")}`:"config-reload: applied live config")},a=()=>{t||(n=setTimeout(()=>{i().finally(a)},e),n.unref?.())};return a(),()=>{t=!0,n&&clearTimeout(n)}}Y();je();import*as Jc from"path";import{createHash as qh,randomBytes as zh,timingSafeEqual as Jh}from"crypto";var Vc="hydra_session_",Vh=3600*24*30,qc=12,Gh=32,Kh=50;function Qh(){return Jc.join(T.home(),"session-tokens.json")}function zc(s){return qh("sha256").update(s).digest("hex")}function Gc(s){return zh(s).toString("hex")}function Yh(){return Gc(qc).slice(0,qc*2)}function Xh(){return`${Vc}${Gc(Gh)}`}var Qs=class s{records=new Map;writeTimer=null;writeInflight=null;filePath;constructor(e,t){this.filePath=t;for(let n of e)this.records.set(n.hash,n)}static async load(){let e=[],t=Qh(),n=await de(t);n&&Array.isArray(n.records)&&(e=n.records.filter(Zh));let r=new s(e,t);return r.sweepExpired(new Date)>0&&await r.flush(),r}async issue(e={}){let t=Xh(),n=zc(t),r=Yh(),o=new Date,i=e.ttlSec&&e.ttlSec>0?e.ttlSec:Vh,a=new Date(o.getTime()+i*1e3),d={id:r,hash:n,label:e.label,createdAt:o.toISOString(),expiresAt:a.toISOString(),lastUsedAt:o.toISOString()};return this.records.set(n,d),this.scheduleWrite(),{id:r,token:t,expiresAt:d.expiresAt}}async verify(e){if(typeof e!="string"||!e.startsWith(Vc))return;let t=zc(e),n=this.records.get(t);if(!n)return;let r=Buffer.from(n.hash,"hex"),o=Buffer.from(t,"hex");if(r.length!==o.length||!Jh(r,o))return;let i=new Date;if(new Date(n.expiresAt).getTime()<=i.getTime()){this.records.delete(t),this.scheduleWrite();return}return n.lastUsedAt=i.toISOString(),this.scheduleWrite(),n.id}async revoke(e){for(let[t,n]of this.records)if(n.id===e)return this.records.delete(t),this.scheduleWrite(),!0;return!1}async revokeAll(){let e=this.records.size;return this.records.clear(),this.scheduleWrite(),e}list(){return Array.from(this.records.values()).map(({id:e,label:t,createdAt:n,expiresAt:r,lastUsedAt:o})=>({id:e,label:t,createdAt:n,expiresAt:r,lastUsedAt:o})).sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}sweepExpired(e=new Date){let t=0;for(let[n,r]of this.records)new Date(r.expiresAt).getTime()<=e.getTime()&&(this.records.delete(n),t+=1);return t>0&&this.scheduleWrite(),t}async flush(){this.writeTimer&&(clearTimeout(this.writeTimer),this.writeTimer=null),await this.persist()}scheduleWrite(){this.writeTimer||(this.writeTimer=setTimeout(()=>{this.writeTimer=null,this.persist().catch(()=>{})},Kh))}persist(){let e=(this.writeInflight??Promise.resolve()).catch(()=>{}).then(()=>me(this.filePath,{records:Array.from(this.records.values())},{mode:384}));return this.writeInflight=e,e.catch(()=>{}).finally(()=>{this.writeInflight===e&&(this.writeInflight=null)}),e}};function Zh(s){if(!s||typeof s!="object")return!1;let e=s;return typeof e.id=="string"&&typeof e.hash=="string"&&typeof e.createdAt=="string"&&typeof e.expiresAt=="string"&&typeof e.lastUsedAt=="string"&&(e.label===void 0||typeof e.label=="string")}var Kc="Bearer ",Ys=class{constructor(e){this.token=e}token;async validate(e){return ty(e,this.token)?"service":void 0}rotate(e){this.token=e}},Xs=class{constructor(e){this.store=e}store;async validate(e){return this.store.verify(e)}},Zs=class{constructor(e){this.validators=e}validators;async validate(e){for(let t of this.validators){let n=await t.validate(e);if(n!==void 0)return n}}};function Qc(s){return async function(t,n){let r=t.headers.authorization;if(!r||!r.startsWith(Kc)){n.code(401).send({error:"Missing bearer token"});return}let o=r.slice(Kc.length).trim(),i=await s.validator.validate(o);if(!i){n.code(403).send({error:"Invalid token"});return}t.authIdentity=i}}function Yc(s){let e=s.headers["sec-websocket-protocol"],t=Array.isArray(e)?e.join(","):e;if(t)for(let n of t.split(",")){let r=n.trim(),o="hydra-acp-token.";if(r.startsWith(o))return r.slice(o.length)}if(s.url)try{let r=new URL(s.url,"http://localhost").searchParams.get("token");if(r)return r}catch{return}}var er=class{tokens=new Map;mint(e,t){let n=Ir();return this.tokens.set(n,{name:e,kind:t}),n}revoke(e){for(let[t,n]of this.tokens)n.name===e&&this.tokens.delete(t)}resolve(e){return this.tokens.get(e)}async validate(e){let t=this.tokens.get(e);if(t)return`${t.kind}:${t.name}`}},ey=new Set(["GET /v1/sessions","GET /v1/sessions/:id","GET /v1/config","GET /v1/system"]);function Xc(s,e){return e?ey.has(`${s} ${e}`):!1}function ty(s,e){if(s.length!==e.length)return!1;let t=0;for(let n=0;n<s.length;n+=1)t|=s.charCodeAt(n)^e.charCodeAt(n);return t===0}var tr=class{entries=new Map;maxFails;windowMs;constructor(e=10,t=900*1e3){this.maxFails=e,this.windowMs=t}isBlocked(e){let t=this.entries.get(e);return t?Date.now()-t.windowStart>this.windowMs?(this.entries.delete(e),!1):t.fails>=this.maxFails:!1}recordFailure(e){let t=Date.now(),n=this.entries.get(e);if(!n||t-n.windowStart>this.windowMs){this.entries.set(e,{fails:1,windowStart:t});return}n.fails+=1}recordSuccess(e){this.entries.delete(e)}sweepExpired(){let e=Date.now();for(let[t,n]of this.entries)e-n.windowStart>this.windowMs&&this.entries.delete(t)}};import*as ii from"fs";import*as ku from"os";import*as ar from"path";import*as ai from"readline";Y();function ni(s){return Math.floor(s/4)}function Zc(s){let e=0,t=new Map;for(let n of s){let r=n.params;if(!r||typeof r!="object")continue;let o=r.update;if(!o||typeof o!="object")continue;let i=o;switch(i.sessionUpdate){case"user_message_chunk":case"agent_message_chunk":case"agent_thought_chunk":e+=Et(i.content);break;case"tool_call":case"tool_call_update":{let a=typeof i.toolCallId=="string"?i.toolCallId:"",d=ny(i),c=t.get(a)??0;d>c&&t.set(a,d);break}default:break}}for(let n of t.values())e+=n;return e}function ny(s){let e=0;return typeof s.title=="string"&&(e+=s.title.length),e+=nr(s.rawInput),e+=Et(s.content),e+=nr(s.rawOutput),e}function nr(s){if(s==null)return 0;if(typeof s=="string")return s.length;if(typeof s=="number"||typeof s=="boolean")return String(s).length;if(Array.isArray(s)){let e=0;for(let t of s)e+=nr(t);return e}if(typeof s=="object"){let e=s.bytes;if(typeof s.__hydraBlob=="string"&&typeof e=="number")return e;let t=0;for(let n of Object.values(s))t+=nr(n);return t}return 0}function Et(s){if(s==null)return 0;if(typeof s=="string")return s.length;if(Array.isArray(s)){let t=0;for(let n of s)t+=Et(n);return t}if(typeof s!="object")return 0;let e=s;return typeof e.__hydraBlob=="string"&&typeof e.bytes=="number"?e.bytes:e.text!==void 0?Et(e.text):e.type==="diff"?Et(e.oldText)+Et(e.newText):e.content!==void 0?Et(e.content):0}function eu(s){if(s.compactionInFlight||s.totalEntries===0)return!1;let e,t;if(typeof s.agentReportedUsed=="number"&&typeof s.agentReportedSize=="number"&&s.agentReportedSize>0)e=s.agentReportedUsed/s.agentReportedSize,t=!0;else{let r=ni(s.unsummarizedChars),o=s.currentModel!==void 0?s.config.modelContextWindows[s.currentModel]??s.config.absoluteFallback:s.config.absoluteFallback;e=r/o,t=!1}if(t&&e>=s.config.hardCeilingFraction)return!0;let n=s.nowMs-s.lastActivityMs;return e>=s.config.contextFraction&&n>=s.config.idleBeforePromptMs}function tu(s){let e=new Map,t=new Map,n=new Map;for(let o of s){let a=o.params?.update;if(!a||typeof a!="object")continue;let d=a.sessionUpdate;if(d!=="tool_call"&&d!=="tool_call_update")continue;let c=typeof a.toolCallId=="string"&&a.toolCallId.length>0?a.toolCallId:void 0,u=ry(a);if(u.length===0)continue;let l=u;if(c!==void 0){let p=e.get(c)??[],f=[];for(let h of u){let k=p.find(m=>m.path===h.path&&m.oldText===h.oldText&&m.newText===h.newText);if(k===void 0)f.push(h);else if(k.scope===void 0&&h.scope!==void 0){k.scope=h.scope;let m=t.get(k);m&&(m.scope=h.scope)}}if(f.length===0)continue;e.set(c,[...p,...f]),l=f}for(let p of l)t.set(p,sy(n,p))}let r=[];for(let[o,i]of n)r.push({path:o,hunks:i.hunks,created:i.created});return r}function nu(s){let e=[];for(let t of s){let n=-1;for(let o=e.length-1;o>=0;o--)if(e[o].newText===t.oldText){n=o;break}if(n===-1){e.push(t);continue}let r=e[n];e.splice(n,1,{oldText:r.oldText,newText:t.newText,...r.scope!==void 0&&r.scope===t.scope?{scope:r.scope}:{}})}return e}function sy(s,e){let t={oldText:e.oldText,newText:e.newText,...e.scope!==void 0?{scope:e.scope}:{}},n=s.get(e.path);return n===void 0?(s.set(e.path,{hunks:[t],created:e.oldText.length===0}),t):(n.hunks.push(t),t)}function ry(s){let e=[];for(let t of gs(s))t.path!==void 0&&e.push({path:t.path,...qa(t),...t.scope!==void 0?{scope:t.scope}:{}});return e}function ru(s,e={}){let t=iy(s),{events:n,window:r}=oy(t,e),o=ay(n),i=[];dy(i,s),r&&(r.from>1||r.to<r.total)&&(i.push(`_Showing turns ${r.from}-${r.to} of ${r.total}._`),i.push("")),cy(i,n,o,{includeTools:e.includeTools??!1,includeThoughts:e.includeThoughts??!1});let a=i.join(`
198
+ `);try{a.end()}catch{}e.logStream=void 0;return}this.scheduleRestart(e,t+1)})}scheduleRestart(e,t){if(this.stopping||e.manuallyStopped)return;let n=Math.min(this.restartBaseMs*2**Math.min(t,10),this.restartCapMs);e.restartTimer=setTimeout(()=>{e.restartTimer=void 0,this.spawn(e,t).catch(r=>{e.failureReason=`spawn: ${r.message}`})},n),typeof e.restartTimer.unref=="function"&&e.restartTimer.unref()}managerName(){return this.adapter.kind==="extension"?"ExtensionManager":"TransformerManager"}};function ti(s){try{return process.kill(s,0),!0}catch{return!1}}function Bn(s,e){return s.code=e,s}Y();var Uh={kind:"extension",nameEnvVar:"HYDRA_ACP_EXTENSION_NAME",tokenRole:"extension",paths:{dir:E.extensionsDir,logFile:E.extensionLogFile,pidFile:E.extensionPidFile}},Gs=class extends rn{constructor(e,t,n={}){super(e,Uh,t,n)}};Y();var Bh={kind:"transformer",nameEnvVar:"HYDRA_ACP_TRANSFORMER_NAME",tokenRole:"transformer",paths:{dir:E.transformersDir,logFile:E.transformerLogFile,pidFile:E.transformerPidFile}},Ks=class extends rn{connected=new Map;constructor(e,t,n={}){super(e,Bh,t,n)}registerConnection(e,t,n){this.connected.set(e,{name:e,connection:t,intercepts:new Set(n)})}deregisterConnection(e){this.connected.delete(e)}resolveChain(e){let t=[];for(let n of e){let r=this.connected.get(n);r&&t.push(r)}return t}interestedIn(e){let t=[];for(let n of this.connected.values())n.intercepts.has(e)&&t.push(n);return t}};var Qs=class{entries=new Map;changeHandlers=[];register(e,t,n){this.entries.set(e,{connection:t,commands:[...n]}),this.fireChanged()}clear(e){this.entries.delete(e)&&this.fireChanged()}get(e){return this.entries.get(e)}has(e){return this.entries.has(e)}list(){let e=[];for(let[t,n]of this.entries)for(let r of n.commands)e.push({name:t,command:r});return e}onChange(e){return this.changeHandlers.push(e),()=>{let t=this.changeHandlers.indexOf(e);t>=0&&this.changeHandlers.splice(t,1)}}fireChanged(){for(let e of this.changeHandlers)try{e()}catch{}}};Y();Y();import*as Wn from"fs/promises";async function Dc(s){let e=E.pidFile(),t=`${e}.${process.pid}.tmp`;await Wn.writeFile(t,JSON.stringify(s)+`
199
+ `,{encoding:"utf8",mode:384}),await Wn.rename(t,e)}Y();import*as zn from"fs/promises";import*as Ys from"path";var qn=s=>{process.stderr.write(s+`
200
+ `)};function ni(s){qn=s??(e=>process.stderr.write(e+`
201
+ `))}async function Hc(s,e){let t=Ue();if(!t)return;let n=await s.load(),r=new Map;for(let d of n.agents)r.set(d.id,d.version??"current");let o=e.activeAgentVersions(),i=Ys.join(E.agentsDir(),t),a;try{a=await zn.readdir(i,{withFileTypes:!0})}catch(d){let c=d;if(c.code==="ENOENT")return;qn(`hydra-acp: prune: failed to read ${i}: ${c.message}`);return}for(let d of a){if(!d.isDirectory())continue;let c=d.name,u=r.get(c);if(u===void 0)continue;let l=o.get(c)??new Set,p=Ys.join(i,c),f;try{f=await zn.readdir(p,{withFileTypes:!0})}catch(h){qn(`hydra-acp: prune: failed to read ${p}: ${h.message}`);continue}for(let h of f){if(!h.isDirectory())continue;let k=h.name;if(k===u||l.has(k)||k.includes(".partial-"))continue;let m=Ys.join(p,k);try{await zn.rm(m,{recursive:!0,force:!0}),qn(`hydra-acp: pruned stale ${c} ${k} (${m})`)}catch(g){qn(`hydra-acp: prune: failed to remove ${m}: ${g.message}`)}}}}function jc(s){let e,t=!1,n=0,r=(a,d)=>{s.logger&&s.logger[a](`agent-sync: ${d}`)},o=async()=>{let a=[];try{let u=await s.registry.load();for(let l of u.agents)await Qr(l)==="yes"&&a.push(l.id)}catch(u){return r("warn",`registry load failed: ${u.message}`),s.intervalMs}if(a.length===0)return s.intervalMs;let d=n%a.length;n=(n+1)%a.length;let c=a[d];try{let{synced:u,skipped:l}=await s.manager.syncFromAgent(c);r("info",`${c}: synced ${u.length}, skipped ${l}`)}catch(u){r("warn",`${c}: ${u.message}`)}return Math.max(1,Math.floor(s.intervalMs/a.length))},i=a=>{t||(e=setTimeout(()=>{o().then(d=>{i(d)}).catch(d=>{r("warn",`tick crashed: ${d.message}`),i(s.intervalMs)})},a),e.unref())};return i(s.intervalMs),()=>{t=!0,e&&(clearTimeout(e),e=void 0)}}async function si(s){let e=s.maxDeletions??200,t=(f,h)=>{s.logger&&s.logger[f](`session-gc: ${h}`)},n=Date.now(),r=s.maxAgeMs>0?n-s.maxAgeMs:Number.POSITIVE_INFINITY,o=await s.manager.list({includeNonInteractive:!0}).catch(f=>(t("warn",`manager.list failed: ${f.message}`),[])),i=[];for(let f of o){if(f.status!=="cold")continue;if((s.selection??"explicit")==="explicit"){if(f.interactive!==!1)continue}else if(f.interactive===!0)continue;let k=Date.parse(f.updatedAt);Number.isFinite(k)&&(s.maxAgeMs>0&&k>r||i.push({sessionId:f.sessionId,lastUsedMs:k}))}if(i.length===0)return s.verbose&&t("info","no candidates"),{considered:0,deleted:0,failed:0,deferred:0};i.sort((f,h)=>f.lastUsedMs-h.lastUsedMs);let a=i.slice(0,e),d=a[0]?.lastUsedMs,c=0,u=0;for(let{sessionId:f}of a)try{await s.manager.deleteRecord(f,"expired")&&(c+=1)}catch(h){u+=1,t("warn",`delete ${f} failed: ${h.message}`)}let l=i.length-a.length;if(s.verbose||c>0||u>0){let f=(s.selection??"explicit")==="unpromoted"?"unpromoted":"non-interactive";t("info",`swept ${c} ${f} session(s) older than ${Wh(s.maxAgeMs)}`+(u>0?`; ${u} failed`:"")+(l>0?`; ${l} deferred to next sweep`:""))}let p={considered:i.length,deleted:c,failed:u,deferred:l};return d!==void 0&&(p.oldestLastUsedMs=d),p}function Lc(s){let e,t=!1,n=!1,r=o=>{t||(e=setTimeout(()=>{(async()=>{if(!n){n=!0;try{await si({manager:s.manager,maxAgeMs:s.maxAgeMs,selection:"unpromoted",...s.maxDeletionsPerSweep!==void 0?{maxDeletions:s.maxDeletionsPerSweep}:{},...s.logger?{logger:s.logger}:{}})}finally{n=!1}}})().catch(a=>{s.logger?.warn(`session-gc: sweep crashed: ${a.message}`)}).finally(()=>{r(s.intervalMs)})},o),e.unref())};return r(s.intervalMs),()=>{t=!0,e&&(clearTimeout(e),e=void 0)}}function Wh(s){if(s<=0)return"any age";let e=s/(1440*60*1e3);if(e>=1)return`${e.toFixed(e>=10?0:1)}d`;let t=s/(3600*1e3);return`${t.toFixed(t>=10?0:1)}h`}import{createHash as qh}from"crypto";function Jn(s){if(Array.isArray(s))return s.map(Jn);if(s!==null&&typeof s=="object"){let e={};for(let t of Object.keys(s).sort())e[t]=Jn(s[t]);return e}return s}function Uc(s){let e={};for(let[n,r]of Object.entries(s)){let o=xr(n);if(o.nested){let i={};for(let[a,d]of Object.entries(r??{}))Tr(a).reload==="restart"&&(i[a]=d);Object.keys(i).length>0&&(e[n]=i);continue}o.reload==="restart"&&(e[n]=r)}let t=JSON.stringify(Jn(e));return qh("sha256").update(t).digest("hex").slice(0,16)}function Bc(s,e){let t=[],n=(r,o)=>JSON.stringify(Jn(r))!==JSON.stringify(Jn(o));for(let r of Object.keys(e)){let o=xr(r),i=e[r],a=s[r];if(o.nested){for(let d of Object.keys(i??{})){if(Tr(d).reload!=="warn")continue;let c=i[d],u=(a??{})[d];n(u,c)&&t.push(`${r}.${d}`)}continue}o.reload==="warn"&&n(a,i)&&t.push(r)}return t}import*as qc from"fs/promises";Y();var zh=3e3;async function Wc(){try{return(await qc.stat(E.config())).mtimeMs}catch{return}}function zc(s){let e=s.intervalMs??zh,t=!1,n,r,o=Wc().then(d=>{r=d}),i=async()=>{await o;let d=await Wc();if(d===r)return;r=d;let c;try{c=await hn()}catch(l){s.logger?.warn(`config-reload: config.json changed but did not parse (${l.message}); keeping the loaded config`);return}try{s.apply(c)}catch(l){s.logger?.warn(`config-reload: applying live config failed: ${l.message}`)}let u=Bc(s.bootConfig,c);s.onDrift?.(u),s.logger?.info(u.length>0?`config-reload: applied live config; restart-only keys differing from boot: ${u.join(", ")}`:"config-reload: applied live config")},a=()=>{t||(n=setTimeout(()=>{i().finally(a)},e),n.unref?.())};return a(),()=>{t=!0,n&&clearTimeout(n)}}Y();je();import*as Gc from"path";import{createHash as Jh,randomBytes as Vh,timingSafeEqual as Gh}from"crypto";var Kc="hydra_session_",Kh=3600*24*30,Jc=12,Qh=32,Yh=50;function Xh(){return Gc.join(E.home(),"session-tokens.json")}function Vc(s){return Jh("sha256").update(s).digest("hex")}function Qc(s){return Vh(s).toString("hex")}function Zh(){return Qc(Jc).slice(0,Jc*2)}function ey(){return`${Kc}${Qc(Qh)}`}var Xs=class s{records=new Map;writeTimer=null;writeInflight=null;filePath;constructor(e,t){this.filePath=t;for(let n of e)this.records.set(n.hash,n)}static async load(){let e=[],t=Xh(),n=await de(t);n&&Array.isArray(n.records)&&(e=n.records.filter(ty));let r=new s(e,t);return r.sweepExpired(new Date)>0&&await r.flush(),r}async issue(e={}){let t=ey(),n=Vc(t),r=Zh(),o=new Date,i=e.ttlSec&&e.ttlSec>0?e.ttlSec:Kh,a=new Date(o.getTime()+i*1e3),d={id:r,hash:n,label:e.label,createdAt:o.toISOString(),expiresAt:a.toISOString(),lastUsedAt:o.toISOString()};return this.records.set(n,d),this.scheduleWrite(),{id:r,token:t,expiresAt:d.expiresAt}}async verify(e){if(typeof e!="string"||!e.startsWith(Kc))return;let t=Vc(e),n=this.records.get(t);if(!n)return;let r=Buffer.from(n.hash,"hex"),o=Buffer.from(t,"hex");if(r.length!==o.length||!Gh(r,o))return;let i=new Date;if(new Date(n.expiresAt).getTime()<=i.getTime()){this.records.delete(t),this.scheduleWrite();return}return n.lastUsedAt=i.toISOString(),this.scheduleWrite(),n.id}async revoke(e){for(let[t,n]of this.records)if(n.id===e)return this.records.delete(t),this.scheduleWrite(),!0;return!1}async revokeAll(){let e=this.records.size;return this.records.clear(),this.scheduleWrite(),e}list(){return Array.from(this.records.values()).map(({id:e,label:t,createdAt:n,expiresAt:r,lastUsedAt:o})=>({id:e,label:t,createdAt:n,expiresAt:r,lastUsedAt:o})).sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}sweepExpired(e=new Date){let t=0;for(let[n,r]of this.records)new Date(r.expiresAt).getTime()<=e.getTime()&&(this.records.delete(n),t+=1);return t>0&&this.scheduleWrite(),t}async flush(){this.writeTimer&&(clearTimeout(this.writeTimer),this.writeTimer=null),await this.persist()}scheduleWrite(){this.writeTimer||(this.writeTimer=setTimeout(()=>{this.writeTimer=null,this.persist().catch(()=>{})},Yh))}persist(){let e=(this.writeInflight??Promise.resolve()).catch(()=>{}).then(()=>me(this.filePath,{records:Array.from(this.records.values())},{mode:384}));return this.writeInflight=e,e.catch(()=>{}).finally(()=>{this.writeInflight===e&&(this.writeInflight=null)}),e}};function ty(s){if(!s||typeof s!="object")return!1;let e=s;return typeof e.id=="string"&&typeof e.hash=="string"&&typeof e.createdAt=="string"&&typeof e.expiresAt=="string"&&typeof e.lastUsedAt=="string"&&(e.label===void 0||typeof e.label=="string")}var Yc="Bearer ",Zs=class{constructor(e){this.token=e}token;async validate(e){return sy(e,this.token)?"service":void 0}rotate(e){this.token=e}},er=class{constructor(e){this.store=e}store;async validate(e){return this.store.verify(e)}},tr=class{constructor(e){this.validators=e}validators;async validate(e){for(let t of this.validators){let n=await t.validate(e);if(n!==void 0)return n}}};function Xc(s){return async function(t,n){let r=t.headers.authorization;if(!r||!r.startsWith(Yc)){n.code(401).send({error:"Missing bearer token"});return}let o=r.slice(Yc.length).trim(),i=await s.validator.validate(o);if(!i){n.code(403).send({error:"Invalid token"});return}t.authIdentity=i}}function Zc(s){let e=s.headers["sec-websocket-protocol"],t=Array.isArray(e)?e.join(","):e;if(t)for(let n of t.split(",")){let r=n.trim(),o="hydra-acp-token.";if(r.startsWith(o))return r.slice(o.length)}if(s.url)try{let r=new URL(s.url,"http://localhost").searchParams.get("token");if(r)return r}catch{return}}var nr=class{tokens=new Map;mint(e,t){let n=Cr();return this.tokens.set(n,{name:e,kind:t}),n}revoke(e){for(let[t,n]of this.tokens)n.name===e&&this.tokens.delete(t)}resolve(e){return this.tokens.get(e)}async validate(e){let t=this.tokens.get(e);if(t)return`${t.kind}:${t.name}`}},ny=new Set(["GET /v1/sessions","GET /v1/sessions/:id","GET /v1/config","GET /v1/system"]);function eu(s,e){return e?ny.has(`${s} ${e}`):!1}function sy(s,e){if(s.length!==e.length)return!1;let t=0;for(let n=0;n<s.length;n+=1)t|=s.charCodeAt(n)^e.charCodeAt(n);return t===0}var sr=class{entries=new Map;maxFails;windowMs;constructor(e=10,t=900*1e3){this.maxFails=e,this.windowMs=t}isBlocked(e){let t=this.entries.get(e);return t?Date.now()-t.windowStart>this.windowMs?(this.entries.delete(e),!1):t.fails>=this.maxFails:!1}recordFailure(e){let t=Date.now(),n=this.entries.get(e);if(!n||t-n.windowStart>this.windowMs){this.entries.set(e,{fails:1,windowStart:t});return}n.fails+=1}recordSuccess(e){this.entries.delete(e)}sweepExpired(){let e=Date.now();for(let[t,n]of this.entries)e-n.windowStart>this.windowMs&&this.entries.delete(t)}};import*as di from"fs";import*as bu from"os";import*as cr from"path";import*as ci from"readline";Y();function ri(s){return Math.floor(s/4)}function tu(s){let e=0,t=new Map;for(let n of s){let r=n.params;if(!r||typeof r!="object")continue;let o=r.update;if(!o||typeof o!="object")continue;let i=o;switch(i.sessionUpdate){case"user_message_chunk":case"agent_message_chunk":case"agent_thought_chunk":e+=Et(i.content);break;case"tool_call":case"tool_call_update":{let a=typeof i.toolCallId=="string"?i.toolCallId:"",d=ry(i),c=t.get(a)??0;d>c&&t.set(a,d);break}default:break}}for(let n of t.values())e+=n;return e}function ry(s){let e=0;return typeof s.title=="string"&&(e+=s.title.length),e+=rr(s.rawInput),e+=Et(s.content),e+=rr(s.rawOutput),e}function rr(s){if(s==null)return 0;if(typeof s=="string")return s.length;if(typeof s=="number"||typeof s=="boolean")return String(s).length;if(Array.isArray(s)){let e=0;for(let t of s)e+=rr(t);return e}if(typeof s=="object"){let e=s.bytes;if(typeof s.__hydraBlob=="string"&&typeof e=="number")return e;let t=0;for(let n of Object.values(s))t+=rr(n);return t}return 0}function Et(s){if(s==null)return 0;if(typeof s=="string")return s.length;if(Array.isArray(s)){let t=0;for(let n of s)t+=Et(n);return t}if(typeof s!="object")return 0;let e=s;return typeof e.__hydraBlob=="string"&&typeof e.bytes=="number"?e.bytes:e.text!==void 0?Et(e.text):e.type==="diff"?Et(e.oldText)+Et(e.newText):e.content!==void 0?Et(e.content):0}function nu(s){if(s.compactionInFlight||s.totalEntries===0)return!1;let e,t;if(typeof s.agentReportedUsed=="number"&&typeof s.agentReportedSize=="number"&&s.agentReportedSize>0)e=s.agentReportedUsed/s.agentReportedSize,t=!0;else{let r=ri(s.unsummarizedChars),o=s.currentModel!==void 0?s.config.modelContextWindows[s.currentModel]??s.config.absoluteFallback:s.config.absoluteFallback;e=r/o,t=!1}if(t&&e>=s.config.hardCeilingFraction)return!0;let n=s.nowMs-s.lastActivityMs;return e>=s.config.contextFraction&&n>=s.config.idleBeforePromptMs}function su(s){let e=new Map,t=new Map,n=new Map;for(let o of s){let a=o.params?.update;if(!a||typeof a!="object")continue;let d=a.sessionUpdate;if(d!=="tool_call"&&d!=="tool_call_update")continue;let c=typeof a.toolCallId=="string"&&a.toolCallId.length>0?a.toolCallId:void 0,u=iy(a);if(u.length===0)continue;let l=u;if(c!==void 0){let p=e.get(c)??[],f=[];for(let h of u){let k=p.find(m=>m.path===h.path&&m.oldText===h.oldText&&m.newText===h.newText);if(k===void 0)f.push(h);else if(k.scope===void 0&&h.scope!==void 0){k.scope=h.scope;let m=t.get(k);m&&(m.scope=h.scope)}}if(f.length===0)continue;e.set(c,[...p,...f]),l=f}for(let p of l)t.set(p,oy(n,p))}let r=[];for(let[o,i]of n)r.push({path:o,hunks:i.hunks,created:i.created});return r}function ru(s){let e=[];for(let t of s){let n=-1;for(let o=e.length-1;o>=0;o--)if(e[o].newText===t.oldText){n=o;break}if(n===-1){e.push(t);continue}let r=e[n];e.splice(n,1,{oldText:r.oldText,newText:t.newText,...r.scope!==void 0&&r.scope===t.scope?{scope:r.scope}:{}})}return e}function oy(s,e){let t={oldText:e.oldText,newText:e.newText,...e.scope!==void 0?{scope:e.scope}:{}},n=s.get(e.path);return n===void 0?(s.set(e.path,{hunks:[t],created:e.oldText.length===0}),t):(n.hunks.push(t),t)}function iy(s){let e=[];for(let t of hs(s))t.path!==void 0&&e.push({path:t.path,...Ja(t),...t.scope!==void 0?{scope:t.scope}:{}});return e}function iu(s,e={}){let t=dy(s),{events:n,window:r}=ay(t,e),o=cy(n),i=[];uy(i,s),r&&(r.from>1||r.to<r.total)&&(i.push(`_Showing turns ${r.from}-${r.to} of ${r.total}._`),i.push("")),ly(i,n,o,{includeTools:e.includeTools??!1,includeThoughts:e.includeThoughts??!1});let a=i.join(`
202
202
  `);return a.endsWith(`
203
203
  `)||(a+=`
204
- `),a}function si(s,e){let t=s<0?e+s+1:s;return t<1?1:t>e?e:t}function oy(s,e){if(!(e.from!==void 0||e.to!==void 0||e.last!==void 0)&&e.sinceMs===void 0)return{events:s};let n=[],r=0;for(let{event:f}of s)f.kind==="user-text"&&(r+=1),n.push(r===0?1:r);let o=Math.max(r,1),i=1,a=o;if(e.last!==void 0&&e.last>0?i=si(o-e.last+1,o):(e.from!==void 0&&(i=si(e.from,o)),e.to!==void 0&&(a=si(e.to,o))),i>a)return{events:[],window:{from:i,to:a,total:o}};let d=e.sinceMs,c=new Set;d!==void 0&&s.forEach((f,h)=>{f.recordedAt>=d&&c.add(n[h])});let u=[],l,p;return s.forEach((f,h)=>{let k=n[h];k<i||k>a||d!==void 0&&!c.has(k)||(u.push(f),l??=k,p=k)}),{events:u,window:{from:l??i,to:p??a,total:o}}}function iy(s){let e=[];for(let t of s.history){if(t.method!=="session/update")continue;let n=t.params;if(!n||typeof n!="object")continue;let r=Ga(n.update,{cwd:s.session.cwd});r!==null&&e.push({event:r,recordedAt:t.recordedAt})}return e}function ay(s){let e=new Map;for(let{event:t}of s){if(t.kind==="tool-call"){let n=e.get(t.toolCallId);e.set(t.toolCallId,{title:t.title,status:t.status??n?.status??"pending"});continue}if(t.kind==="tool-call-update"){let n=e.get(t.toolCallId)??{title:"tool call",status:"pending"};e.set(t.toolCallId,{title:t.title??n.title,status:t.status??n.status})}}return e}function dy(s,e){let t=e.session,n=tt(t.sessionId),r=t.title?.trim()||`Hydra session ${n}`;s.push(`# ${zn(r)}`),s.push("");let o=[];o.push(`- **Session:** \`${n}\` (lineage \`${t.lineageId}\`)`);let i=[t.agentId];t.currentModel&&i.push(`model: ${t.currentModel}`),t.currentMode&&i.push(`mode: ${t.currentMode}`),o.push(`- **Agent:** ${i.filter(Boolean).join(" \xB7 ")}`),o.push(`- **Cwd:** ${t.cwd}`),o.push(`- **Exported:** ${e.exportedAt} from ${e.exportedFrom.machine} (hydra ${e.exportedFrom.hydraVersion})`);let a=t.currentUsage;if(a&&(a.used!==void 0||a.costAmount!==void 0||a.cumulativeCost!==void 0)){let d=[];if(a.used!==void 0){let u=a.size!==void 0?`${ri(a.size)}`:void 0;d.push(u?`${ri(a.used)} / ${u} tokens`:`${ri(a.used)} tokens`)}let c=qo(a);if(c!==void 0){let u=a.costCurrency??"USD";d.push(`$${c.toFixed(2)} ${u}`)}o.push(`- **Usage:** ${d.join(" \xB7 ")}`)}s.push(o.join(`
205
- `)),s.push("")}function cy(s,e,t,n){let{includeTools:r,includeThoughts:o}=n;if(!e.some(k=>uy(k.event,o))){s.push("_No conversation history recorded._"),s.push("");return}let i=0,a="",d="",c=[],u=new Set,l=!1,p=()=>{if(c.length!==0){for(let k of c)s.push(k);s.push(""),c=[]}},f=()=>{p(),d.length>0&&(su(s,d.trimEnd(),"*"),s.push(""),d=""),a.length!==0&&(s.push(a.trimEnd()),s.push(""),a="")},h=()=>{l||(l=!0)};for(let{event:k}of e)switch(k.kind){case"user-text":{f(),s.push("---"),s.push(""),i+=1,su(s,k.text,"**"),s.push(""),l=!0;break}case"agent-text":h(),a+=k.text;break;case"agent-thought":{if(!o)break;h(),a.length>0&&(s.push(a.trimEnd()),s.push(""),a=""),d+=k.text;break}case"tool-call":{if(!r||(h(),(a.length>0||d.length>0)&&f(),u.has(k.toolCallId)))break;u.add(k.toolCallId);let m=t.get(k.toolCallId)??{title:k.title,status:k.status??"pending"};c.push(`- ${fy(m.status)} ${ly(m)}`);break}case"tool-call-update":break;case"plan":{h(),f(),s.push("**Plan:**"),s.push("");for(let m of k.entries){let g=m.status==="completed"?"[x]":"[ ]";s.push(`- ${g} ${zn(m.content)}`)}s.push("");break}case"mode-changed":h(),f(),s.push(`_mode: ${zn(k.mode)}_`),s.push("");break;case"model-changed":h(),f(),s.push(`_model: ${zn(k.model)}_`),s.push("");break;case"turn-complete":f();break;case"usage-update":case"available-commands":case"session-info":case"unknown":break}f()}function uy(s,e){switch(s.kind){case"agent-thought":return e;case"usage-update":case"available-commands":case"session-info":case"unknown":case"turn-complete":return!1;default:return!0}}function ly(s){let e=s.status,t=e==="completed"||e===void 0?"":` _(${e})_`;return`${zn(s.title)}${t}`}function fy(s){switch(s){case"completed":return"\u2713";case"failed":return"\u2717";case"cancelled":case"rejected":return"\u2298";case"in_progress":return"\u21BB";default:return"\xB7"}}var ou=String.raw`<\/?[a-zA-Z][a-zA-Z0-9-]*(?:\s[^<>]*)?\/?>`,py=new RegExp(ou);function su(s,e,t){if(py.test(e)){gy(s,e);return}let n=e.split(/\n\s*\n/);for(let r=0;r<n.length;r++){let o=n[r];if(o.trim().length===0)continue;let i=o.split(`
206
- `);for(let a=0;a<i.length;a++){let d=i[a];s.push(a===0&&a===i.length-1?`${t}${d}${t}`:a===0?`${t}${d}`:a===i.length-1?`${d}${t}`:d)}r<n.length-1&&s.push("")}}function gy(s,e){let t=e.replace(/\s+$/,"");if(t.length===0)return;let n=0;for(let o of t.match(/`+/g)??[])n=Math.max(n,o.length);let r="`".repeat(Math.max(3,n+1));s.push(r);for(let o of t.split(`
207
- `))s.push(o);s.push(r)}function zn(s){return s.replace(new RegExp(ou,"g"),e=>e.replace(/</g,"&lt;").replace(/>/g,"&gt;"))}function ri(s){return s.toLocaleString("en-US")}function Ae(s){return s==="127.0.0.1"||s==="::1"||s==="localhost"||s==="[::1]"}function my(s){let e=s.trim();if(e.length===0)return{operator:"OR",terms:[]};let t=/\w+:"[^"]*"|"[^"]*"|\S+/g,n=[],r;for(;(r=t.exec(e))!==null;)n.push(r[0]);let o="OR",i=!1,a=!1,d=[];for(let u of n){let l=u.toUpperCase();l==="AND"?i=!0:l==="OR"?a=!0:d.push(u)}i?o="AND":a&&(o="OR");let c=d.map(u=>hy(u)).filter(u=>u.term.length>0);return{operator:o,terms:c}}function hy(s){let e=/^(\w+):"([^"]*)"$/.exec(s);if(e)return{scope:iu(e[1]),term:e[2]};let t=/^"([^"]*)"$/.exec(s);if(t)return{scope:"all",term:t[1]};let n=/^(prompt|response|tool|edit|edited):([\s\S]*)$/i.exec(s);return n?{scope:iu(n[1]),term:n[2].trim()}:{scope:"all",term:s.trim()}}function iu(s){switch(s.toLowerCase()){case"prompt":return"user";case"response":return"agent";case"tool":return"tool";case"edit":case"edited":return"edit";default:return"all"}}function yy(s,e){return e==="edit"?s==="edit":s==="edit"?!1:s==="all"?!0:s==="user"?e==="user":s==="agent"?e==="agent"||e==="thought":e==="tool"||e==="tool-input"}var wy=5,ky=200,rr=72,vy=24,by=512;function lu(s){return Number.isFinite(s)?Math.max(vy,Math.min(by,Math.floor(s))):rr}async function fu(s,e,t={}){let n=my(e);if(n.terms.length===0)return{query:e,truncated:!1,results:[]};let r=t.maxSnippetsPerSession??wy,o=t.maxSessions??ky,i=lu(t.snippetWidth??rr),a=t.sessionIds?new Set(t.sessionIds):null,d=await s.list(),c=a?d.filter(p=>a.has(p.sessionId)):d,u=[],l=!1;for(let p of c){if(u.length>=o){l=!0;break}let f=await s.loadHistory(p.sessionId,{tools:"references"}).catch(()=>[]),h=Iy(f,n,r,i,Sy(p));if(h.snippets.length===0)continue;let k={sessionId:p.sessionId,cwd:p.cwd,status:p.status,updatedAt:p.updatedAt,totalMatches:h.totalMatches,snippets:h.snippets};p.title!==void 0&&(k.title=p.title),u.push(k)}return{query:e,truncated:l,results:u}}function Sy(s){let e=s.workspace?.sourceCwd;if(e===void 0||e.length===0||s.cwd.length===0)return;let t=s.cwd.endsWith("/")?s.cwd:s.cwd+"/";return n=>n.startsWith(t)?e.replace(/\/+$/,"")+"/"+n.slice(t.length):n}function Iy(s,e,t,n=rr,r){if(e.terms.length===0)return{totalMatches:0,snippets:[]};let o=0,i=[],a=Math.max(1,Math.floor(t/e.terms.length)),d=[];for(let{scope:c,term:u}of e.terms){let l=Ay(s,u,c,t,n,r);if(e.operator==="AND"&&l.totalMatches===0)return{totalMatches:0,snippets:[]};o+=l.totalMatches,i.push(...l.snippets.slice(0,a)),d.push(...l.snippets.slice(a))}for(let c of d){if(i.length>=t)break;i.push(c)}return{totalMatches:o,snippets:i.slice(0,t)}}function Ay(s,e,t,n,r,o){let i=e.toLowerCase(),a=0,d=[],c=new Set;for(let u of s){let l=Cy(u).filter(p=>yy(t,p.kind));for(let p of l){let f=p.text.toLowerCase();if(p.kind==="edit"){let m=o?.(p.text);if(!(au(p.text,e)||(m!==void 0&&m!==p.text?au(m,e):!1))||c.has(p.text))continue;if(c.add(p.text),a+=1,d.length<n){let y={kind:"edit",text:p.text,recordedAt:u.recordedAt};p.toolName!==void 0&&(y.toolName=p.toolName),d.push(y)}continue}let h=f.indexOf(i);if(h===-1)continue;let k=0;for(;h!==-1;)k++,h=f.indexOf(i,h+i.length);if(a+=k,d.length<n){let m=f.indexOf(i),g={kind:p.kind,text:My(p.text,m,i.length,r),recordedAt:u.recordedAt};p.toolName!==void 0&&(g.toolName=p.toolName),d.push(g)}}}return{totalMatches:a,snippets:d}}function Cy(s){if(s.method!=="session/update")return[];let e=s.params;if(!e||typeof e!="object"||Array.isArray(e))return[];let t=e.update;if(!t||typeof t!="object"||Array.isArray(t))return[];let n=t,r=typeof n.sessionUpdate=="string"?n.sessionUpdate:n.kind;if(typeof r!="string")return[];switch(r){case"agent_message_chunk":{let o=sr(n.content);return o?[{kind:"agent",text:o}]:[]}case"agent_thought":case"agent_thought_chunk":{let o=typeof n.text=="string"?be(n.text):sr(n.content);return o?[{kind:"thought",text:o}]:[]}case"user_message_chunk":{if(Ty(n))return[];let o=sr(n.content);return o?[{kind:"user",text:o}]:[]}case"prompt_received":{let o=Py(n.prompt);return o?[{kind:"user",text:o}]:[]}case"tool_call":case"tool_call_update":return Ry(n);default:return[]}}function Ry(s){let e=cu(s,"name"),t=cu(s,"title"),n=[];if(t!==void 0){let a=ie(t);if(a.length>0){let d={kind:"tool",text:a};e!==void 0&&(d.toolName=e),n.push(d)}}if(e!==void 0&&e!==t){let a=ie(e);a.length>0&&n.push({kind:"tool",toolName:e,text:a})}let r=s.rawInput;if(r&&typeof r=="object"){let a=uu(r);if(a.length>0){let d={kind:"tool-input",text:ie(a)};e!==void 0&&(d.toolName=e),n.push(d)}}for(let a of Wa(s)){let d={kind:"edit",text:a};e!==void 0&&(d.toolName=e),n.push(d)}let o=s.locations;if(Array.isArray(o)&&o.length>0){let a=uu(o);if(a.length>0){let d={kind:"tool-input",text:ie(a)};e!==void 0&&(d.toolName=e),n.push(d)}}let i=xy(s);if(i!==null){let a={kind:"tool",text:i};e!==void 0&&(a.toolName=e),n.push(a)}return n}function au(s,e){let t=du(s.toLowerCase()),n=du(e.toLowerCase());if(n.length===0)return!1;if(n.startsWith("/"))return t===n||t.startsWith(n+"/");let r="/"+n,o=t.indexOf(r);for(;o!==-1;){let i=o+r.length;if(i===t.length||t[i]==="/")return!0;o=t.indexOf(r,o+1)}return t===n||t.startsWith(n+"/")}function du(s){return s.length>1&&s.endsWith("/")?s.slice(0,-1):s}function xy(s){if(!Ey(s.status))return null;let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let o=n.content;if(!o||typeof o!="object")continue;let i=o;if(i.type==="text"&&typeof i.text=="string"){let a=ie(i.text);if(a.length>0)return a}}let t=s.rawOutput;if(t&&typeof t=="object"){let n=t.error;if(typeof n=="string"){let r=ie(n);if(r.length>0)return r}}return null}function Ey(s){return s==="failed"||s==="rejected"||s==="cancelled"}function Ty(s){let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return!1;let t=e["hydra-acp"];return!t||typeof t!="object"||Array.isArray(t)?!1:t.compatFor==="prompt_received"}function sr(s){if(typeof s=="string")return be(s);if(!s||typeof s!="object"||Array.isArray(s))return"";let e=s;return typeof e.text=="string"?be(e.text):""}function Py(s){if(!Array.isArray(s))return"";let e=[];for(let t of s){let n=sr(t);n.length>0&&e.push(n)}return e.join("")}function cu(s,e){let t=s[e];return typeof t=="string"?t:void 0}function uu(s){try{return JSON.stringify(s)}catch{return""}}function My(s,e,t,n=rr){let r=s.replace(/\s+/g," ").trim();if(r.length===0)return"";let o=r.toLowerCase(),i=s.slice(e,e+t).toLowerCase().replace(/\s+/g," ").trim(),a=i.length>0?o.indexOf(i):0;a===-1&&(a=0);let d=lu(n),c=Math.max(0,d-i.length),u=Math.floor(c/2),l=Math.min(u,a),p=Math.min(c-l,r.length-(a+i.length)),f=Math.max(0,a-(c-p)),h=Math.min(r.length,a+i.length+p),k=f>0?"\u2026":"",m=h<r.length?"\u2026":"";return`${k}${r.slice(f,h)}${m}`}import{randomBytes as gu}from"crypto";function pu(s){let e=gu(32).toString("hex");return s.tokenRegistry.reserve(e).complete(s.session),s.session.onClose(()=>{s.tokenRegistry.unbind(e)}),{name:s.name,type:"http",url:`${s.getOrigin()}/mcp/${s.name}`,headers:[{name:"Authorization",value:`Bearer ${e}`}]}}function oi(s){if(s.deps.mcpTokenRegistry===void 0||s.deps.getDaemonOrigin===void 0)return;let e=s.deps.mcpTokenRegistry,t=s.deps.getDaemonOrigin;return async n=>{let r=[...s.baselineMcpServers??[]];s.stdinEnabled&&r.push(pu({name:"hydra-acp-stdin",session:n,tokenRegistry:e,getOrigin:t})),r.push(pu({name:"hydra-acp-recall",session:n,tokenRegistry:e,getOrigin:t}));let o=rn(s.deps);return o!==void 0&&(o.bindToSession(n),r=[...r,...o.descriptors]),r}}function rn(s){if(s.extensionMcp===void 0||s.mcpTokenRegistry===void 0||s.getDaemonOrigin===void 0)return;let e=s.extensionMcp.list();if(e.length===0)return;let t=gu(32).toString("hex"),n=s.mcpTokenRegistry.reserve(t),r=s.getDaemonOrigin(),o=e.map(a=>({name:a,type:"http",url:`${r}/mcp/${a}`,headers:[{name:"Authorization",value:`Bearer ${t}`}]})),i=s.mcpTokenRegistry;return{descriptors:o,bindToSession:a=>{n.complete(a),a.onClose(()=>{i.unbind(t)})},abandon:a=>n.abandon(a)}}var _y=new Set(["/v1/sessions/:id/history","/v1/sessions/:id/events"]);function mu(s,e){let t=e.fetchImpl??fetch;s.addHook("preHandler",async(n,r)=>{let o=n.routeOptions.url;if(!o||!o.startsWith("/v1/sessions/:id"))return;let i=n.params,a=i.id;if(typeof a!="string")return;let d=pt(a);if(!d){if(!e.localMiss||await e.localMiss.resolvesLocally(a))return;let g=e.localMiss.cache.findByLocalId(a);if(g.length===0)return;if(g.length>1){r.code(404).send({error:`Session "${a}" exists on more than one remote (${g.map(y=>y.name).join(", ")}). Address it as "<remote>:${a}".`});return}d=g[0]}let c=e.store.get(d.name);if(!c){r.code(404).send({error:`No remote named "${d.name}". Run \`hydra remote add\` first.`});return}let u=n.query;if(_y.has(o)&&Oy(u?.follow)){let g=c.port===_t?"":`:${c.port}`;r.code(501).send({error:`Streaming a federated session isn't supported yet. Attach directly with hydra://${c.host}${g}/${d.localId} instead.`});return}let l=Fy(o,i,d.localId,n.url),f=`${Ae(c.host)?"http":"https"}://${c.host}:${c.port}${l}`,h;try{h=await t(f,{method:n.method,headers:{Authorization:`Bearer ${c.token}`,...n.body!==void 0?{"Content-Type":"application/json"}:{}},...n.body!==void 0&&n.method!=="GET"?{body:JSON.stringify(n.body)}:{}})}catch(g){r.code(502).send({error:`Could not reach remote "${d.name}" (${c.host}:${c.port}): ${g.message}`});return}if(n.method==="DELETE"&&o==="/v1/sessions/:id"&&(h.ok||h.status===404)&&e.localMiss?.cache.evict(d.name,d.localId),h.status===204){r.code(204).send();return}let k=await h.text(),m=h.headers.get("content-type");m&&r.header("content-type",m),r.code(h.status).send(k)})}var $y=5e3,or=class{constructor(e,t={}){this.store=e;this.opts=t}store;opts;perPeer=new Map;timer;start(){this.timer||(this.refreshNow(),this.timer=setInterval(()=>{this.refreshNow()},this.opts.intervalMs??$y),this.timer.unref?.())}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}async refreshNow(){let e=this.opts.fetchImpl??fetch,t=new Set(this.store.list().map(n=>n.name));for(let n of[...this.perPeer.keys()])t.has(n)||this.perPeer.delete(n);await Promise.allSettled(this.store.list().map(async n=>{let r=this.store.get(n.name);if(!r)return;let o=this.perPeer.get(n.name),i=Ae(r.host)?"http":"https",a=new URLSearchParams({includeNonInteractive:"1"}),d=o?.cursor!==void 0;d&&a.set("since",String(o.cursor));let c=`${i}://${r.host}:${r.port}/v1/sessions?${a.toString()}`,u;try{u=await e(c,{headers:{Authorization:`Bearer ${r.token}`}})}catch{return}if(!u.ok)return;let l=await u.json(),p=o?.sessions??new Map;if(d){for(let[f,h]of[...p])h.status!=="cold"&&p.delete(f);for(let f of l.removed??[])p.delete(Je({name:n.name,localId:f}))}else p.clear();for(let f of l.sessions??[]){let h=Je({name:n.name,localId:String(f.sessionId)});p.set(h,{...f,sessionId:h,remote:n.name})}this.perPeer.set(n.name,{cursor:l.cursor,sessions:p})}))}list(e){let t=[];for(let n of this.perPeer.values())t.push(...n.sessions.values());return t.filter(n=>!(e.status&&n.status!==e.status||!e.includeNonInteractive&&n.interactive!==!0))}evict(e,t){this.perPeer.get(e)?.sessions.delete(Je({name:e,localId:t}))}findByLocalId(e){let t=e.startsWith(ye)?[e]:[e,ye+e],n=[];for(let[r,o]of this.perPeer)for(let i of t)if(o.sessions.has(Je({name:r,localId:i}))){n.push({name:r,localId:i});break}return n}};async function hu(s,e,t,n=fetch){let r=s.get(e);if(!r)return{status:404,body:{error:`No remote named "${e}". Run \`hydra remote add\` first.`}};let i=`${Ae(r.host)?"http":"https"}://${r.host}:${r.port}/v1/sessions`,a;try{a=await n(i,{method:"POST",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:JSON.stringify(t)})}catch(l){return{status:502,body:{error:`Could not reach remote "${e}" (${r.host}:${r.port}): ${l.message}`}}}let d=await a.text(),c=null;try{c=d.length>0?JSON.parse(d):null}catch{c=null}if(!a.ok)return{status:a.status,body:c};let u=c;return u&&typeof u.sessionId=="string"?{status:a.status,body:{...u,sessionId:Je({name:e,localId:u.sessionId})}}:{status:a.status,body:c}}async function yu(s,e,t=fetch){let n;if(e.sessionIds===void 0)n=s.list().map(a=>({name:a.name}));else{let a=new Map;for(let d of e.sessionIds){let c=pt(d);if(!c)continue;let u=a.get(c.name)??[];u.push(c.localId),a.set(c.name,u)}n=[...a.entries()].map(([d,c])=>({name:d,sessionIds:c}))}if(n.length===0)return{query:e.q,truncated:!1,results:[]};let r=await Promise.all(n.map(async a=>{let d=s.get(a.name);if(!d)return null;let u=`${Ae(d.host)?"http":"https"}://${d.host}:${d.port}/v1/sessions/search`,l;try{l=await t(u,{method:"POST",headers:{Authorization:`Bearer ${d.token}`,"Content-Type":"application/json"},body:JSON.stringify({q:e.q,...a.sessionIds?{sessionIds:a.sessionIds}:{},...e.snippetWidth!==void 0?{snippetWidth:e.snippetWidth}:{}})})}catch{return null}if(!l.ok)return null;let p;try{p=await l.json()}catch{return null}let f=p;if(!f||!Array.isArray(f.results))return null;let h=f.results.map(k=>({...k,sessionId:Je({name:a.name,localId:k.sessionId})}));return{query:e.q,truncated:f.truncated===!0,results:h}})),o=[],i=!1;for(let a of r)a!==null&&(o.push(...a.results),i=i||a.truncated);return{query:e.q,truncated:i,results:o}}function Oy(s){return s==="1"||s==="true"||s===!0}function Fy(s,e,t,n){let r=s.replace(/:([A-Za-z_]+)/g,(i,a)=>encodeURIComponent(a==="id"?t:e[a]??"")),o=n.indexOf("?");return o===-1?r:r+n.slice(o)}var ir=new Set(["usage_update","tool_call","tool_call_update","prompt_received","turn_complete","permission_resolved"]);function wu(s){if(s.publicHost&&s.publicHost.length>0)return s.publicHost;if(s.host&&!Ae(s.host))return s.port!==void 0?`${s.host}:${s.port}`:s.host}function vu(s,e,t,n={},r,o){s.get("/v1/sessions",async(p,f)=>{let h=p.query,k=h?.includeNonInteractive==="1"||h?.includeNonInteractive==="true",m;if(h?.since!==void 0&&(m=Number(h.since),!Number.isFinite(m)||m<0))return f.code(400).send({error:`since must be a non-negative number, got ${JSON.stringify(h.since)}`});let g=h?.status==="warm"||h?.status==="cold"?h.status:void 0,y={cwd:h?.cwd,includeNonInteractive:k,...g?{status:g}:{}},w=o&&!y.cwd?o.list({includeNonInteractive:k,...g?{status:g}:{}}):[];if(m!==void 0){let S=await e.listSince(y,m);return{sessions:[...S.entries,...w],removed:S.removed,cursor:S.cursor}}let v=await e.listing(y);return{sessions:[...v.entries,...w],removed:[],cursor:v.cursor}}),s.get("/v1/sessions/:id",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=await e.getOne(k);return m||(f.code(404).send({error:"session not found"}),f)}),s.post("/v1/sessions/search",async(p,f)=>{let h=p.body??{},k=typeof h.q=="string"?h.q:"";if(k.trim().length===0)return f.code(400).send({error:"q is required"}),f;let m=Array.isArray(h.sessionIds)?h.sessionIds.filter(v=>typeof v=="string"&&v.length>0):void 0,g={sessionIds:m};typeof h.snippetWidth=="number"&&(g.snippetWidth=h.snippetWidth);let y=await fu(e,k,g);if(!r)return y;let w=await yu(r,{q:k,...m?{sessionIds:m}:{},...g.snippetWidth!==void 0?{snippetWidth:g.snippetWidth}:{}});return{query:k,truncated:y.truncated||w.truncated,results:[...y.results,...w.results]}}),s.post("/v1/sessions",async(p,f)=>{let h=p.body??{};if(h.remote){if(!r)return f.code(404).send({error:`No remote named "${h.remote}". Run \`hydra remote add\` first.`});let v=await hu(r,h.remote,{cwd:h.cwd,agentId:h.agentId,mcpServers:h.mcpServers,workspace:h.workspace});return f.code(v.status).send(v.body)}let k=ce(h.cwd??t.cwd),m=await pn(k),g=h.agentId??m.agentId??t.agentId,y=rn(n),w=y!==void 0?[...h.mcpServers??[],...y.descriptors]:h.mcpServers;try{let v=await e.create({cwd:k,agentId:g,mcpServers:w,...h.workspace!==void 0?{workspace:h.workspace}:{}});y!==void 0&&y.bindToSession(v),f.code(201).send({sessionId:v.sessionId,agentId:v.agentId,cwd:v.cwd,...v.workspace!==void 0?{workspace:v.workspace}:{},...v.workspaceError!==void 0?{workspaceError:v.workspaceError}:{}})}catch(v){y!==void 0&&y.abandon(v instanceof Error?v:void 0),f.code(500).send({error:v.message})}}),s.post("/v1/sessions/collect",async(p,f)=>{let h=p.body??{},k=typeof h.maxAgeDays=="number"&&h.maxAgeDays>0?h.maxAgeDays*24*60*60*1e3:0,m=typeof h.limit=="number"&&h.limit>0?h.limit:1e3,g=h.selection==="explicit"||h.selection==="unpromoted"?h.selection:"unpromoted";try{let y=await ti({manager:e,maxAgeMs:k,maxDeletions:m,selection:g,verbose:!1});f.code(200).send(y)}catch(y){f.code(500).send({error:y.message})}}),s.get("/v1/sessions/tombstones",async(p,f)=>{let h=p.query;if(h.since!==void 0&&Number.isNaN(Date.parse(h.since))){f.code(400).send({error:"since must be an ISO timestamp"});return}let k=await e.listTombstones({...h.agent?{agentId:h.agent}:{},...h.since?{since:h.since}:{},...h.grep?{grep:h.grep}:{}});f.code(200).send({tombstones:k})}),s.post("/v1/sessions/undelete",async(p,f)=>{let h=p.body??{};if(!Array.isArray(h.ids)||h.ids.length===0||!h.ids.every(k=>typeof k=="string"&&k.length>0)){f.code(400).send({error:"ids must be a non-empty array of strings"});return}try{f.code(200).send(await e.undeleteSessions(h.ids))}catch(k){f.code(500).send({error:k.message})}}),s.post("/v1/sessions/:id/kill",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k);if(m){m.close({deleteRecord:!1,by:"REST POST /kill"}).catch(()=>{}),f.code(202).send();return}if(!await e.hasRecord(k)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.post("/v1/sessions/:id/stdin/open",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k);if(!m)return f.code(404).send({error:"session not found"}),f;let g=p.body??{},y={};(g.mode==="memory"||g.mode==="file")&&(y.mode=g.mode),typeof g.capacityBytes=="number"&&(y.capacityBytes=g.capacityBytes),typeof g.fileCapBytes=="number"&&(y.fileCapBytes=g.fileCapBytes),(y.mode??"memory")==="file"&&(y.filePathFor=w=>ar.join(ku.tmpdir(),`hydra-acp-stdin-${w}.log`));try{return m.openStream(y)}catch(w){return f.code(409).send({error:w.message}),f}}),s.post("/v1/sessions/:id/stdin",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k);if(!m)return f.code(404).send({error:"session not found"}),f;let g=p.body??{},y=typeof g.chunk=="string"?g.chunk:"",w=g.eof===!0;try{return m.streamWrite(y,w)}catch(v){return f.code(409).send({error:v.message}),f}}),s.patch("/v1/sessions/:id",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=p.body??{};if(m.cwd!==void 0){if(typeof m.cwd!="string"||!ar.isAbsolute(m.cwd)){f.code(400).send({error:"cwd must be an absolute path"});return}let y=await e.setCwd(k,m.cwd);if(y==="missing"){f.code(404).send({error:"session not found"});return}if(y==="not-a-directory"){f.code(400).send({error:`${m.cwd} is not a directory`});return}if(y==="live"){f.code(409).send({error:"session is live; its agent was spawned in its cwd and cannot change directory. Moving a live session is a swap \u2014 use `workspace start` in it."});return}if(y==="bound"){f.code(409).send({error:"session is isolated, so its cwd IS its workspace. Clear the binding first (PATCH { workspace: null }) or leave the workspace from inside the session."});return}f.code(204).send();return}if("workspace"in m){if(m.workspace!==null){f.code(400).send({error:"workspace may only be set to null (clear the binding)"});return}let y=await e.clearWorkspaceBinding(k);if(y==="missing"){f.code(404).send({error:"session not found"});return}if(y==="live"){f.code(409).send({error:"session is live; its cwd is the workspace. Use `workspace stop` or `workspace detach` in the session so the agent moves with the binding."});return}f.code(204).send();return}if(m.priority!==void 0){let y=m.priority,w;if(y===null||y===0)w=void 0;else if(typeof y=="number"&&Number.isInteger(y)&&y>0)w=y;else{f.code(400).send({error:"priority must be a non-negative integer (or null to clear)"});return}if(!await e.setPriority(k,w)){f.code(404).send({error:"session not found"});return}f.code(204).send();return}if(m.read!==void 0){if(typeof m.read!="boolean"){f.code(400).send({error:"read must be a boolean"});return}if(!await e.setRead(k,m.read)){f.code(404).send({error:"session not found"});return}f.code(204).send();return}if(m.regen===!0){if(!(e.get(k)!==void 0||await e.hasRecord(k))){f.code(404).send({error:"session not found"});return}e.scheduleSynopsis(k),f.code(202).send();return}if(typeof m.title!="string"||m.title.trim().length===0){f.code(400).send({error:"title must be a non-empty string"});return}if(!await e.setTitle(k,m.title)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.delete("/v1/sessions/:id",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k);if(m){await m.close({deleteRecord:!0,by:"REST DELETE /v1/sessions"}),await e.waitForDeletion(k),await e.hasRecord(k)&&await e.deleteRecord(k),f.code(204).send();return}if(!await e.deleteRecord(k)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.get("/v1/sessions/:id/export",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=p.query?.tools,g=m==="references"?"references":hc(m),y=await e.exportBundle(k,g==="references"?{tools:"references"}:{});if(!y){f.code(404).send({error:"session not found"});return}let w=On({record:y.record,history:g==="summary"?yc(y.history,"summary"):y.history,promptHistory:y.promptHistory.length>0?y.promptHistory:void 0,...y.toolBlobs!==void 0?{toolBlobs:y.toolBlobs}:{},hydraVersion:ue,machine:bt(),hydraHost:wu(t)}),v=new Date().toISOString().replace(/[:.]/g,"-");f.header("Content-Disposition",`attachment; filename="${k}-${v}.hydra"`),f.code(200).send(w)}),s.get("/v1/sessions/:id/diff",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=await e.exportBundle(k,{includeArchivedHistory:!0});if(!m){f.code(404).send({error:"session not found"});return}let g=p.query??{},y=g.fold==="true"||g.fold==="1",w=typeof g.paths=="string"&&g.paths.length>0?new Set(g.paths.split(",").map(S=>S.trim()).filter(S=>S.length>0)):void 0,v=tu(m.history);w&&(v=v.filter(S=>w.has(S.path))),y&&(v=v.map(S=>({...S,hunks:nu(S.hunks)}))),f.code(200).send(v)}),s.get("/v1/sessions/:id/tools/:hash",async(p,f)=>{let h=p.params,k=await e.resolveCanonicalId(h.id)??h.id,m=await e.loadToolBlob(k,h.hash);if(m===null){f.code(404).send({error:"tool blob not found"});return}f.header("Content-Type","text/plain; charset=utf-8"),f.code(200).send(m)}),s.get("/v1/sessions/:id/transcript",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=await e.exportBundle(k);if(!m){f.code(404).send({error:"session not found"});return}let g=On({record:m.record,history:m.history,promptHistory:m.promptHistory.length>0?m.promptHistory:void 0,hydraVersion:ue,machine:bt(),hydraHost:wu(t)}),y=p.query,w=b=>b==="1"||b==="true"||b==="yes",v=b=>{let I=y?.[b];if(I===void 0||I==="")return;let C=Number(I);return Number.isFinite(C)?C:"bad"},S={};for(let b of["from","to","last","since"]){let I=v(b);if(I==="bad"){f.code(400).send({error:`${b} must be a number`});return}I!==void 0&&(S[b==="since"?"sinceMs":b]=I)}f.header("Content-Type","text/markdown; charset=utf-8"),f.code(200).send(ru(g,{includeTools:w(y?.tools),includeThoughts:w(y?.thoughts),...S}))});let i=p=>async(f,h)=>{let k=f.params.id,m=await e.resolveCanonicalId(k)??k,g=f.body??{},y={};if(g.forkAt!==void 0){if(typeof g.forkAt!="string"||g.forkAt.length===0){h.code(400).send({error:"forkAt must be a non-empty string"});return}y.forkAt=g.forkAt}if(g.cwd!==void 0){if(typeof g.cwd!="string"||g.cwd.length===0){h.code(400).send({error:"cwd must be a non-empty string"});return}y.cwd=ce(g.cwd)}if(g.agentId!==void 0){if(typeof g.agentId!="string"||g.agentId.length===0){h.code(400).send({error:"agentId must be a non-empty string"});return}y.agentId=g.agentId}if(g.title!==void 0){if(typeof g.title!="string"){h.code(400).send({error:"title must be a string"});return}y.title=g.title}if(p){let w=g.selection;if(w!==void 0){if(typeof w.text!="string"||w.text.length===0){h.code(400).send({error:"selection.text must be a non-empty string"});return}y.side={selection:{text:w.text,...typeof w.responsePartId=="string"?{responsePartId:w.responsePartId}:{}}}}else y.side={}}if(g.mode!==void 0&&!p){if(g.mode!=="verbatim"&&g.mode!=="synthesis"){h.code(400).send({error:'mode must be "verbatim" or "synthesis"'});return}y.mode=g.mode}if(g.model!==void 0){if(typeof g.model!="string"||g.model.length===0){h.code(400).send({error:"model must be a non-empty string"});return}y.model=g.model}try{let w=await e.forkSession(m,y);h.code(201).send(w)}catch(w){let v=w;if(v.code===x.SessionNotFound){h.code(404).send({error:v.message});return}if(v.code===x.InvalidParams||v.code===x.AgentNotInstalled){h.code(400).send({error:v.message});return}h.code(500).send({error:v.message})}};s.post("/v1/sessions/:id/fork",i(!1)),s.post("/v1/sessions/:id/side",i(!0)),s.post("/v1/sessions/:id/rewind",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=(p.body??{}).keepThrough;if(m!==null&&(typeof m!="string"||m.length===0)){f.code(400).send({error:"keepThrough must be a non-empty messageId, or null to drop every turn"});return}try{f.code(200).send(await e.rewindSession(k,m))}catch(g){let y=g;if(y.code===x.SessionNotFound){f.code(404).send({error:y.message});return}if(y.code===x.InvalidParams){f.code(400).send({error:y.message});return}if(y.code===x.InvalidRequest){f.code(409).send({error:y.message});return}f.code(500).send({error:y.message})}}),s.post("/v1/sessions/import",async(p,f)=>{let h=p.body??{};if(h.bundle===void 0){f.code(400).send({error:"missing bundle"});return}let k;if(h.cwd!==void 0){if(typeof h.cwd!="string"||h.cwd.length===0){f.code(400).send({error:"cwd must be a non-empty string"});return}k=h.cwd}let m;try{m=Cc(h.bundle)}catch(g){f.code(400).send({error:"invalid bundle",details:g.message});return}try{let g=await e.importBundle(m,{replace:h.replace===!0,...k!==void 0?{cwd:k}:{}});f.code(201).send(g)}catch(g){let y=g;if(y.code===x.BundleAlreadyImported){f.code(409).send({error:"bundle already imported",existingSessionId:y.existingSessionId});return}f.code(500).send({error:y.message})}}),s.get("/v1/sessions/:id/compact/status",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k),g;if(m?g=m.summarizedThroughEntry:g=await e.getSummarizedThroughEntry(k),g===void 0&&!await e.hasRecord(k))return f.code(404).send({error:"session not found"}),f;let y=await e.getCompactionState(k),w=await e.getRollbackBreadcrumb(k),v=await e.getPendingAgentSwap(k),S=!1,b,I=m?.currentUsage,C=typeof I?.used=="number"&&typeof I?.size=="number"&&I.size>0?{used:I.used,size:I.size}:void 0,R=await e.loadHistory(k,{tools:"references",maxEntries:1/0}).catch(()=>[]);if(R.length>0&&t.compaction){let E=g??0,M=R.length,N=E<=R.length?E:0,B=R.slice(N),q=Zc(B);b=ni(q);let V=m?.currentModel,L=R.at(-1).recordedAt;S=eu({summarizedThroughEntry:E,totalEntries:M,unsummarizedChars:q,compactionInFlight:e.getCompactionInFlight(),currentModel:V,lastActivityMs:L,nowMs:Date.now(),config:t.compaction,...typeof I?.used=="number"?{agentReportedUsed:I.used}:{},...typeof I?.size=="number"?{agentReportedSize:I.size}:{}})}return{summarizedThroughEntry:g??void 0,inFlight:e.getCompactionInFlight(),shouldCompact:S,...b!=null?{approxTokens:b}:{},...C!=null?{currentUsage:C}:{},...y!=null?{compactionState:y}:{},...w!=null?{rollbackBreadcrumb:w}:{},...v!=null?{pendingAgentSwap:v}:{}}}),s.post("/v1/sessions/:id/compact",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h;if(e.get(k)){e.scheduleCompaction(k),f.code(202).send({scheduled:!0});return}if(!await e.hasRecord(k)){f.code(404).send({error:"session not found"});return}e.scheduleCompaction(k),f.code(202).send({scheduled:!0})}),s.post("/v1/sessions/:id/compact/rollback",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h;if(!await e.hasRecord(k)){f.code(404).send({error:"session not found"});return}try{await e.performUncompact(k),f.code(202).send({rolledBack:!0})}catch(m){let g=m instanceof Error?m.message:String(m);f.code(409).send({error:g})}}),s.post("/v1/sessions/:id/workspace/clean",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=p.body??{};if(m.deep!==void 0&&typeof m.deep!="boolean"){f.code(400).send({error:"deep must be a boolean"});return}if(!await e.hasRecord(k)){f.code(404).send({error:"session not found"});return}if(e.get(k)===void 0){f.code(409).send({error:"session is not live. Cleaning rewrites the workspace under a running agent, so it is only available inside a live session (`/hydra workspace clean`). For a cold workspace use `hydra workspace remove` instead."});return}try{let g=await e.runWorkspaceAction(k,"clean",void 0,{deep:m.deep===!0});f.code(202).send({report:g})}catch(g){f.code(409).send({error:g instanceof Error?g.message:String(g)})}}),s.get("/v1/sessions/:id/history/page",async(p,f)=>{let h=p.params.id,k=p.query,m=Number(k?.beforeSeq);if(k?.beforeSeq===void 0||k.beforeSeq===""||!Number.isFinite(m)){f.code(400).send({error:"beforeSeq must be a number"});return}let g=k.turns===void 0||k.turns===""?10:Number(k.turns);if(!Number.isInteger(g)||g<1){f.code(400).send({error:"turns must be a positive integer"});return}let y=await e.resolveCanonicalId(h)??h,w=await e.pageHistory(y,{beforeSeq:m,turns:Math.min(g,100)});if(!w){f.code(404).send({error:"session not found"});return}f.code(200).send({entries:w.entries,hasMore:w.hasMore})}),s.get("/v1/sessions/:id/history",async(p,f)=>{let h=p.params.id,k=p.query,m=k?.follow==="1"||k?.follow==="true",g=await e.resolveCanonicalId(h)??h,y=e.get(g),w,v,S=!1,b=1e4,I=[];if(y){m&&(v=y.onBroadcast(R=>{f.raw.writableEnded||(S?f.raw.write(JSON.stringify(R)+`
208
- `):(I.push(R),I.length>b&&I.shift()))})),p.raw.on("close",()=>{v?.(),f.raw.writableEnded||f.raw.end()});try{w=await y.getHistorySnapshot()}catch(R){throw v?.(),R}}else{let R=await e.getHistory(g);if(R===void 0)return f.code(404).send({error:"session not found"}),f;w=R}f.raw.setHeader("Content-Type","application/x-ndjson"),f.raw.setHeader("Cache-Control","no-cache"),f.raw.statusCode=200;let C=new Set;for(let R of w??[]){f.raw.write(JSON.stringify(R)+`
209
- `);let E=R;typeof E.recordedAt=="number"&&C.add(String(E.recordedAt))}for(;I.length>0;){let R=I.splice(0,I.length);for(let E of R){let M=E,N=typeof M.recordedAt=="number"?String(M.recordedAt):"";N&&C.has(N)||f.raw.write(JSON.stringify(E)+`
210
- `)}}return S=!0,v||f.raw.end(),f});function a(p,f,h){let k=typeof p=="string"?p.trim():"";if(k.length===0)return null;let m;try{m=JSON.parse(k)}catch{return console.debug("events endpoint: skipping malformed JSONL line"),null}if(!m||typeof m!="object"||Array.isArray(m))return console.debug("events endpoint: skipping non-object JSONL line"),null;let g=m;if(typeof g.recordedAt!="number"||h!==void 0&&g.recordedAt<h||typeof g.params!="object"||g.params===null||Array.isArray(g.params))return null;let y=g.params;if(typeof y.update!="object"||y.update===null||Array.isArray(y.update))return null;let v=y.update.sessionUpdate;return typeof v!="string"||!f.has(v)?null:{recordedAt:g.recordedAt,entry:m}}function d(p,f,h){let m=f.params.update,g={sessionId:p,ts:new Date(f.recordedAt).toISOString(),kind:h,update:m};return m.messageId!==void 0&&m.messageId!==null&&(g.messageId=m.messageId),g}async function*c(p,f,h,k){for await(let m of f){let g=a(m,h,k);if(g){let y=g.entry.params.update.sessionUpdate;yield{ts:g.recordedAt,row:d(p,g.entry,y)}}}}async function u(p,f,h,k){let m=ai.createInterface({input:ii.createReadStream(f),crlfDelay:1/0}),g=c(p,m,h,k),y=await g.next(),w=y.done?null:y.value;return{sessionId:p,rl:m,gen:g,current:w,exhausted:w===null}}async function l(p){let f=await p.gen.next();f.done?(p.exhausted=!0,p.current=null):p.current=f.value}s.get("/v1/sessions/events",async(p,f)=>{let h=p.query,k=h.kinds;if(!k||k.trim().length===0)return f.code(400).send({error:"kinds parameter is required"}),f;let m=k.split(",").map(b=>b.trim());if(m.length===0)return f.code(400).send({error:"kinds parameter is required"}),f;for(let b of m)if(!ir.has(b))return f.code(400).send({error:`kind "${b}" is not queryable; allowed kinds: ${[...ir].join(", ")}`}),f;let g=new Set(m),y;if(h.since!==void 0&&h.since.trim().length>0){let b=new Date(h.since);if(isNaN(b.getTime()))return f.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),f;y=b.getTime()}let w=await e.list({includeNonInteractive:!0}),v=y!==void 0?w.filter(b=>new Date(b.updatedAt).getTime()>=y):w;f.raw.setHeader("content-type","application/x-ndjson"),f.raw.statusCode=200;let S=[];for(let b of v)try{let I=T.historyFile(b.sessionId),C=await u(b.sessionId,I,g,y);C.exhausted||S.push(C)}catch(I){if(I.code==="ENOENT")continue;throw I}p.raw.on("close",()=>{for(let b of S)try{b.rl.close()}catch{}f.raw.writableEnded||f.raw.end()});try{for(;S.length>0;){let b=-1,I=1/0;for(let R=0;R<S.length;R++){let E=S[R];E.current!==null&&E.current.ts<I&&(I=E.current.ts,b=R)}if(b===-1)break;let C=S[b];if(f.raw.write(JSON.stringify(C.current.row)+`
211
- `),await l(C),C.exhausted){try{C.rl.close()}catch{}S.splice(b,1)}}}catch(b){for(let I of S)try{I.rl.close()}catch{}throw b}return f.raw.end(),f}),s.get("/v1/sessions/:id/events",async(p,f)=>{let h=p.params.id,k=p.query,m=await e.resolveCanonicalId(h)??h;if(!e.get(m)&&!await e.hasRecord(m))return f.code(404).send({error:"session not found"}),f;let y=k.kinds;if(!y||y.trim().length===0)return f.code(400).send({error:"kinds parameter is required"}),f;let w=y.split(",").map(R=>R.trim());if(w.length===0)return f.code(400).send({error:"kinds parameter is required"}),f;for(let R of w)if(!ir.has(R))return f.code(400).send({error:`kind "${R}" is not queryable; allowed kinds: ${[...ir].join(", ")}`}),f;let v=new Set(w),S;if(k.since!==void 0&&k.since.trim().length>0){let R=new Date(k.since);if(isNaN(R.getTime()))return f.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),f;S=R.getTime()}let b=T.historyFile(m),I=ii.createReadStream(b),C=ai.createInterface({input:I,crlfDelay:1/0});f.raw.setHeader("content-type","application/x-ndjson"),f.raw.statusCode=200;try{for await(let R of C){let E=typeof R=="string"?R.trim():"";if(E.length===0)continue;let M;try{M=JSON.parse(E)}catch{console.debug("events endpoint: skipping malformed JSONL line in %s",b);continue}if(!M||typeof M!="object"||Array.isArray(M)){console.debug("events endpoint: skipping non-object JSONL line in %s",b);continue}let N=M;if(typeof N.recordedAt!="number"||typeof N.params!="object"||N.params===null||Array.isArray(N.params))continue;let B=N.params;if(typeof B.update!="object"||B.update===null||Array.isArray(B.update))continue;let q=B.update,V=q.sessionUpdate;if(typeof V!="string"||!v.has(V)||S!==void 0&&N.recordedAt<S)continue;let L={ts:new Date(N.recordedAt).toISOString(),kind:V,update:q};q.messageId!==void 0&&q.messageId!==null&&(L.messageId=q.messageId),f.raw.write(JSON.stringify(L)+`
212
- `)}}catch(R){if(R.code==="ENOENT")return f.raw.end(),f;throw R}return f.raw.end(),f}),s.post("/v1/sessions/:id/prompt/:messageId/notify",async(p,f)=>{let h=p.params,k=h.id,m=await e.resolveCanonicalId(k)??k,g=h.messageId,y=p.body,w=typeof y?.callbackUrl=="string"?y.callbackUrl:"",v=typeof y?.secret=="string"?y.secret:"";if(!g||!w||!v){f.code(400).send({error:"messageId, callbackUrl, and secret are all required"});return}let S;try{S=new URL(w)}catch{f.code(400).send({error:"callbackUrl must be a valid absolute URL"});return}if(S.protocol!=="https:"&&S.protocol!=="http:"){f.code(400).send({error:"callbackUrl must be http or https"});return}let b=e.get(m);if(!b){f.code(404).send({error:"session not found or not warm"});return}let I=b.registerTurnNotify(g,w,v);if(I.alreadyTerminal){f.code(200).send({status:"already_terminal",stopReason:I.stopReason});return}f.code(202).send({status:"registered"})}),s.get("/v1/sessions/:id/attention",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k);return!m&&!await e.hasRecord(k)?(f.code(404).send({error:"session not found"}),f):m?{flags:m.listAttentionFlags()}:{flags:(await e.store.read(k))?.attentionFlags??[]}}),s.get("/v1/sessions/attention",async(p,f)=>{let h=p.query;if(!h.source||h.source.trim().length===0)return f.code(400).send({error:"source query parameter is required"}),f;let k=await e.list({includeNonInteractive:!0}),m=[];for(let g of k){let y=e.get(g.sessionId),w;y?w=y.listAttentionFlags():w=(await e.store.read(g.sessionId))?.attentionFlags??[];for(let v of w)v.source===h.source&&m.push({...v,sessionId:g.sessionId})}return{flags:m}}),s.post("/v1/sessions/:id/attention/clear",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,g=p.body??{},y=typeof g.source=="string"?g.source:"",w=typeof g.reason=="string"?g.reason:"";if((y.length>0||w.length>0)&&!(y.length>0&&w.length>0)){f.code(400).send({error:"both source and reason are required to clear a specific flag, or omit both to clear all"});return}y.length===0&&w.length;let v=e.get(k);if(v){if(y.length>0&&w.length>0)v.clearAttentionFlag(y,w);else{let R=Array.from(v.listAttentionFlags()).map(E=>`${E.source}::${E.reason}`);for(let E of R)v.clearAttentionFlag(E.split("::")[0],E.split("::").slice(1).join("::"))}f.code(204).send();return}if(!await e.hasRecord(k)){f.code(404).send({error:"session not found"});return}let S=e.store,b=await S.read(k);if(!b){f.code(404).send({error:"session not found"});return}let I=b.attentionFlags??[],C;if(y.length>0&&w.length>0){let R=`${y}::${w}`;C=I.filter(E=>`${E.source}::${E.reason}`!==R)}else C=[];if(C.length===I.length&&C.every((R,E)=>R.source===I[E].source&&R.reason===I[E].reason)){f.code(204).send();return}await S.write({...b,attentionFlags:C}),f.code(204).send()})}function bu(s,e,t,n={}){s.get("/v1/agents",async()=>Dt(e)),s.get("/v1/registry",async()=>e.load()),s.post("/v1/registry/refresh",async()=>{let r=await e.refresh();return{version:r.version,agentCount:r.agents.length}}),s.post("/v1/agents/:id/install",async(r,o)=>{let i=r.params.id,a=await e.getAgent(i);if(!a){o.code(404).send({error:`agent ${i} not found in registry`});return}if(a.distribution.uvx&&!a.distribution.npx&&!a.distribution.binary){o.send({agentId:a.id,version:a.version??"current",distribution:"uvx",installed:!1,message:"uvx agents resolve on first run; nothing to pre-install."});return}try{let d=await _e(a,[],{npmRegistry:n.npmRegistry}),c=a.distribution.npx?"npx":a.distribution.binary?"binary":"unknown";o.send({agentId:a.id,version:d.version,distribution:c,installed:!0,command:d.command})}catch(d){o.code(500).send({error:d.message})}}),s.post("/v1/agents/:id/sync",async(r,o)=>{let i=r.params.id;try{let{synced:a,skipped:d}=await t.syncFromAgent(i);return{synced:a.map(c=>({sessionId:c.sessionId,upstreamSessionId:c.upstreamSessionId,agentId:c.agentId,cwd:c.cwd,title:c.title,updatedAt:c.updatedAt})),skipped:d}}catch(a){let d=a;if(d.code===x.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}Y();function Su(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:T.home(),driftedKeys:n()}))}import*as Ru from"os";Y();je();var Jn=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,dr=class s{data;constructor(e){this.data=e}static async load(){let e=await de(T.peers());return new s(Ny(e))}get(e){return this.data.entries[e]}async set(e){this.data.entries[e.name]=e,await Iu(this.data)}async delete(e){return e in this.data.entries?(delete this.data.entries[e],await Iu(this.data),!0):!1}list(){return Object.values(this.data.entries).map(({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})=>({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})).sort((e,t)=>e.addedAt.localeCompare(t.addedAt))}};function Ny(s){if(!s||typeof s!="object")return{version:1,entries:{}};let e=s,t=e.entries&&typeof e.entries=="object"?e.entries:{},n={};for(let[r,o]of Object.entries(t)){if(!o||typeof o!="object")continue;let i=o;if(typeof i.name!="string"||typeof i.host!="string"||typeof i.port!="number"||typeof i.token!="string"||typeof i.expiresAt!="string"||typeof i.addedAt!="string")continue;let a={name:i.name,host:i.host,port:i.port,token:i.token,expiresAt:i.expiresAt,addedAt:i.addedAt};typeof i.label=="string"&&(a.label=i.label),typeof i.pinnedFingerprint=="string"&&(a.pinnedFingerprint=i.pinnedFingerprint),typeof i.pinnedAt=="string"&&(a.pinnedAt=i.pinnedAt),n[r]=a}return{version:1,entries:n}}async function Iu(s){await me(T.peers(),s,{mode:384})}var Dy=3600*24*365,Qe=class extends Error{status;constructor(e,t){super(e),this.name="PeerLoginError",this.status=t}};function cr(s,e){return`${Ae(s)?"http":"https"}://${s}:${e}`}async function Au(s){let e=s.fetchImpl??fetch,t=`${s.host}:${s.port}`,n=cr(s.host,s.port),r;try{r=await e(`${n}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:s.password,label:s.label,ttlSec:s.ttlSec??Dy})})}catch(i){throw new Qe(`Could not reach ${t}: ${i.message}`,502)}if(r.status===401)throw new Qe(`Wrong password for ${t}.`,401);if(r.status===403)throw new Qe(`No password is configured on ${t}. Run \`hydra-acp auth password\` on that daemon first.`,502);if(r.status===429)throw new Qe(`Too many failed login attempts on ${t}; try again later.`,429);if(!r.ok)throw new Qe(`Login to ${t} failed: HTTP ${r.status}`,502);let o=await r.json();if(!o.session_token||!o.expires_at)throw new Qe(`Login to ${t} returned a malformed response.`,502);return{token:o.session_token,expiresAt:o.expires_at}}async function di(s){let e=s.fetchImpl??fetch,t=cr(s.host,s.port);try{await e(`${t}/v1/auth/logout`,{method:"POST",headers:{Authorization:`Bearer ${s.token}`,"Content-Type":"application/json"},body:JSON.stringify({})})}catch{}}function xu(s){return{machine:bt(),hydraVersion:ue,startedAt:s,os:{platform:process.platform,release:Ru.release(),arch:process.arch},node:process.version}}async function ur(s){let e=s.fetchImpl??fetch,t;try{t=await e(`${cr(s.host,s.port)}/v1/system`,{headers:{Authorization:`Bearer ${s.token}`},signal:s.signal})}catch(n){return{kind:"error",message:n.message}}if(t.status===401||t.status===403)return{kind:"unauthorized"};if(t.status===404)return{kind:"unsupported"};if(!t.ok)return{kind:"error",message:`HTTP ${t.status}`};try{let n=await t.json();return typeof n?.machine=="string"?{kind:"ok",system:n}:{kind:"ok"}}catch{return{kind:"ok"}}}function Cu(s){return s!==void 0&&s.length<=64&&Jn.test(s)}function Eu(s,e){if(Cu(s))return s;if(/^[\d.]+$/.test(e)||e.includes(":"))return;let t=e.split(".")[0];return Cu(t)?t:void 0}function Tu(s,e){s.get("/v1/system",async()=>xu(e))}var Hy=/^[A-Za-z0-9._-]+$/;function lr(s,e,t){let n=e==="extension"?"extensions":"transformers",r=`/v1/${n}`;s.get(r,async()=>({[n]:t.list()})),s.get(`${r}/:name`,async(o,i)=>{let a=o.params.name,d=t.get(a);if(!d){i.code(404).send({error:`unknown ${e}: ${a}`});return}return d}),s.post(r,async(o,i)=>{let a=o.body??{},d=jy(a);if("error"in d){i.code(400).send({error:d.error});return}try{let c=t.register(d.config);i.code(201).send(c)}catch(c){Vn(i,c)}}),s.delete(`${r}/:name`,async(o,i)=>{let a=o.params.name;try{await t.unregister(a),i.code(204).send()}catch(d){Vn(i,d)}}),s.post(`${r}/:name/start`,async(o,i)=>{let a=o.params.name;try{let d=await t.startByName(a);i.code(200).send(d)}catch(d){Vn(i,d)}}),s.post(`${r}/:name/stop`,async(o,i)=>{let a=o.params.name;try{let d=await t.stopByName(a);i.code(200).send(d)}catch(d){Vn(i,d)}}),s.post(`${r}/:name/restart`,async(o,i)=>{let a=o.params.name;try{let d=await t.restartByName(a);i.code(200).send(d)}catch(d){Vn(i,d)}})}function Vn(s,e){let t=e.code,n=e.message??"unknown error";if(t==="NOT_FOUND"){s.code(404).send({error:n});return}if(t==="CONFLICT"){s.code(409).send({error:n});return}s.code(500).send({error:n})}function jy(s){let e=s.name;if(typeof e!="string"||!Hy.test(e))return{error:"name must match [A-Za-z0-9._-]+"};let t=s.command;if(t!==void 0&&(!Array.isArray(t)||t.some(i=>typeof i!="string")))return{error:"command must be string[]"};let n=s.args;if(n!==void 0&&(!Array.isArray(n)||n.some(i=>typeof i!="string")))return{error:"args must be string[]"};let r=s.env;if(r!==void 0&&(typeof r!="object"||r===null||Array.isArray(r)))return{error:"env must be an object of string\u2192string"};if(r&&Object.values(r).some(i=>typeof i!="string"))return{error:"env values must be strings"};let o=s.enabled;return o!==void 0&&typeof o!="boolean"?{error:"enabled must be a boolean"}:{config:{name:e,command:t??[],args:n??[],env:r??{},enabled:o===void 0?!0:o}}}function Pu(s,e){lr(s,"extension",e)}function Mu(s,e){lr(s,"transformer",e)}function _u(s,e){s.get("/v1/config",async()=>e())}import{z as yt}from"zod";Y();import*as on from"fs/promises";import*as $u from"path";import{randomBytes as aR,scrypt as Ly,timingSafeEqual as Uy}from"crypto";import{promisify as By}from"util";var Wy=By(Ly);function Ou(){return $u.join(T.home(),"password-hash")}var qy=128*1024*1024;async function Fu(){try{return(await on.readFile(Ou(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function Nu(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await on.readFile(Ou(),"utf8")).trim()}catch(c){if(c.code==="ENOENT")return!1;throw c}let t=e.split("$");if(t.length!==6||t[0]!=="scrypt")return!1;let n=parseInt(t[1],10),r=parseInt(t[2],10),o=parseInt(t[3],10);if(!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(o))return!1;let i=Buffer.from(t[4],"hex"),a=Buffer.from(t[5],"hex");if(i.length===0||a.length===0)return!1;let d=await Wy(s,i,a.length,{N:n,r,p:o,maxmem:qy});return d.length!==a.length?!1:Uy(d,a)}var zy=yt.object({password:yt.string().min(1),label:yt.string().min(1).max(256).optional(),ttlSec:yt.number().int().positive().optional()}),Jy=yt.object({id:yt.string().optional()}).optional(),Vy=yt.object({token:yt.string().min(32)});function Du(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=Gy(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=zy.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await Fu())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await Nu(o.password))return e.rateLimiter.recordFailure(r),n.code(401).send({error:"Invalid password"});e.rateLimiter.recordSuccess(r);let a=await e.store.issue({label:o.label,ttlSec:o.ttlSec});return n.code(200).send({session_token:a.token,id:a.id,expires_at:a.expiresAt})}),s.post("/v1/auth/logout",async(t,n)=>{let r;try{r=Jy.parse(t.body??void 0)}catch{return n.code(400).send({error:"Invalid request body"})}let o=r?.id??t.authIdentity;if(!o||o==="service")return n.code(200).send({revoked:!1});let i=await e.store.revoke(o);return n.code(200).send({revoked:i})}),s.get("/v1/auth/verify",async(t,n)=>n.code(200).send({ok:!0})),s.get("/v1/auth/sessions",async(t,n)=>n.code(200).send({sessions:e.store.list()})),s.delete("/v1/auth/sessions",async(t,n)=>{let r=await e.store.revokeAll();return n.code(200).send({revoked:r})}),s.delete("/v1/auth/sessions/:id",async(t,n)=>{let r=t.params.id;return await e.store.revoke(r)?n.code(204).send():n.code(404).send({error:"Not found"})}),s.post("/v1/auth/rotate-token",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=Vy.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}return e.staticTokenValidator.rotate(r.token),n.code(200).send({rotated:!0})})}function Gy(s){return s.ip||"unknown"}import{z as wt}from"zod";Kn();var iw=wt.object({name:wt.string().min(1).max(64).regex(Jn).optional(),host:wt.string().min(1),port:wt.number().int().positive().optional(),password:wt.string().min(1),label:wt.string().min(1).max(256).optional(),ttlSec:wt.number().int().positive().optional(),pinnedFingerprint:wt.string().min(1).optional()});function Ju(s,e){s.post("/v1/remotes",async(t,n)=>{let r;try{r=iw.parse(t.body)}catch{return n.code(400).send({error:`Invalid request body (name must match ${Jn} and the rest is a normal login request)`})}let o=r.port??_t;r.pinnedFingerprint&&Gn(r.host,o,r.pinnedFingerprint);let i;try{i=await Au({host:r.host,port:o,password:r.password,label:r.label,ttlSec:r.ttlSec})}catch(p){if(p instanceof Qe)return n.code(p.status).send({error:p.message});throw p}let a=await ur({host:r.host,port:o,token:i.token}),d=a.kind==="ok"?a.system:void 0,c=r.name;if(c===void 0){c=Eu(d?.machine,r.host);let p=c!==void 0?e.store.get(c):void 0,f=p!==void 0&&(p.host!==r.host||p.port!==o);if(c===void 0||f){await di({host:r.host,port:o,token:i.token});let h=c===void 0?`Couldn't derive a remote name for ${r.host}`:`A remote named ${c} already points at ${p.host}:${p.port}`;return n.code(c===void 0?400:409).send({error:`${h}. Pass a name: hydra-acp remote add <name> ${r.host}`})}}let u=new Date().toISOString(),l={name:c,host:r.host,port:o,token:i.token,expiresAt:i.expiresAt,addedAt:u,...r.label!==void 0?{label:r.label}:{},...r.pinnedFingerprint!==void 0?{pinnedFingerprint:r.pinnedFingerprint,pinnedAt:u}:{}};return await e.store.set(l),e.health?.markOk(l.name,d),n.code(201).send({name:l.name,host:l.host,port:l.port,expiresAt:l.expiresAt,label:l.label,addedAt:l.addedAt,pinnedFingerprint:l.pinnedFingerprint,status:e.health?.get(l.name)?.status??"unknown"})}),s.get("/v1/remotes",async(t,n)=>{let r=e.store.list().map(o=>{let i=e.health?.get(o.name);return{...o,status:i?.status??"unknown",...i?.checkedAt?{lastCheckedAt:i.checkedAt}:{},...i?.system?{system:i.system}:{}}});return n.code(200).send({remotes:r})}),s.get("/v1/remotes/:name/agents",async(t,n)=>{let r=e.store.get(t.params.name);if(!r)return n.code(404).send({error:"Not found"});let i=`${Ae(r.host)?"http":"https"}://${r.host}:${r.port}`,a={Authorization:`Bearer ${r.token}`};try{let[d,c]=await Promise.all([fetch(`${i}/v1/agents`,{headers:a}),fetch(`${i}/v1/config`,{headers:a}).catch(()=>null)]);if(!d.ok)return n.code(d.status).header("content-type","application/json").send(await d.text());let u=await d.json(),l={};if(c?.ok){let p=await c.json();l={defaultAgent:p.defaultAgent,sessionDefaults:p.sessionDefaults}}return n.code(200).send({...u,...l})}catch(d){return n.code(502).send({error:`Could not reach remote "${r.name}": ${d.message}`})}}),s.delete("/v1/remotes/:name",async(t,n)=>{let r=t.params.name,o=e.store.get(r);return o?(await di({host:o.host,port:o.port,token:o.token}),await e.store.delete(r),e.health?.forget(r),e.store.list().some(a=>a.host===o.host&&a.port===o.port)||ui(o.host,o.port),n.code(204).send()):n.code(404).send({error:"Not found"})})}function pr(s){let e=[],t=[],n=!1,r=o=>{if(!n){n=!0;for(let i of t)i(o)}};return s.on("message",(o,i)=>{if(i)return;let a=o.toString("utf8");try{let d=JSON.parse(a);for(let c of e)c(d)}catch(d){for(let c of e)c({jsonrpc:"2.0",id:null,error:{code:x.ParseError,message:`Failed to parse WS frame: ${d.message}`}})}}),s.on("close",()=>r()),s.on("error",o=>r(o)),{async send(o){if(n)throw new Error("ws is closed");let i=JSON.stringify(o);await new Promise((a,d)=>{s.send(i,c=>{if(c){d(c);return}a()})})},onMessage(o){e.push(o)},onClose(o){t.push(o)},async close(){n||(await new Promise(o=>{let i=!1,a=()=>{i||(i=!0,clearTimeout(d),o())},d=setTimeout(a,5e3);s.once("close",a);try{s.close()}catch{a()}}),r())}}}Kn();import{WebSocket as aw}from"ws";var dw=1e4,mi=class extends Error{url;elapsedMs;constructor(e,t){super(`hydra-acp: websocket connect to ${e} timed out after ${t}ms`),this.name="WsConnectTimeoutError",this.url=e,this.elapsedMs=t}};async function Vu(s,e,t=dw){let n={};try{let r=new URL(s);if(r.protocol==="wss:"){let o=gi(r.hostname);o.rejectUnauthorized!==void 0&&(n.rejectUnauthorized=o.rejectUnauthorized),o.autoSelectFamily!==void 0&&(n.autoSelectFamily=o.autoSelectFamily),o.checkServerIdentity!==void 0&&(n.checkServerIdentity=o.checkServerIdentity)}}catch{}return new Promise((r,o)=>{let i=new aw(s,e,n),a=Date.now(),d=setTimeout(()=>{i.off("open",c),i.off("error",u),i.on("error",()=>{});try{i.terminate()}catch{}o(new mi(s,Date.now()-a))},t),c=()=>{clearTimeout(d),i.off("error",u),r(i)},u=l=>{clearTimeout(d),i.off("open",c),o(l)};i.once("open",c),i.once("error",u)})}var cw=new Set(["session/attach","session/detach","session/prompt","session/cancel","session/close","session/delete","hydra-acp/session/delete","session/set_model","session/set_mode","session/set_config_option","_session/steering","hydra-acp/prompt/cancel","hydra-acp/prompt/update","hydra-acp/prompt/amend","hydra-acp/session/tool_content","hydra-acp/session/force_cancel"]);function uw(s){return cw.has(s)}function Ku(s,e,t,n){let r=[],o=a=>{for(let d of r)d(a)},i=(a,d)=>{e.handleLocalMessage(a,d,{connection:t.connection,clientId:n}).then(c=>c?s.send(c):void 0).catch(()=>{})};return s.onMessage(a=>{if("method"in a&&uw(a.method)){let d=a.params,c=typeof d?.sessionId=="string"?d.sessionId:void 0;if(c){if(pt(c)){i(a,c);return}if(a.method==="session/attach"){let u="id"in a;e.resolveLocalMiss(c).then(l=>{if(l.ok){i(a,l.foreignId);return}if(l.ambiguous&&u){s.send(Qn(a.id,x.SessionNotFound,`Session "${c}" exists on more than one remote (${l.ambiguous.join(", ")}). Address it as "<remote>:${c}".`));return}o(a)});return}}}o(a)}),{send:a=>s.send(a),onMessage:a=>r.push(a),onClose:a=>s.onClose(a),close:()=>s.close()}}var gr=class{constructor(e,t=fw,n){this.store=e;this.dial=t;this.localMiss=n}store;dial;localMiss;attachments=new Map;async resolveLocalMiss(e){if(!this.localMiss)return{ok:!1};if(await this.localMiss.resolvesLocally(e))return{ok:!1};let t=this.localMiss.cache.findByLocalId(e);return t.length===0?{ok:!1}:t.length>1?{ok:!1,ambiguous:t.map(n=>n.name)}:{ok:!0,foreignId:Je(t[0])}}async handleLocalMessage(e,t,n){let r="id"in e,o=r?e.id:void 0,i=pt(t);if(!i)return r?Qn(o,x.SessionNotFound,`not a federated session id: ${t}`):void 0;let a=Gu(n.clientId,t),d={...e.params,sessionId:i.localId};if(e.method==="session/attach"){let u=this.store.get(i.name);if(!u)return r?Qn(o,x.SessionNotFound,`No remote named "${i.name}". Run \`hydra remote add\` first.`):void 0;let l=this.attachments.get(a);l&&(this.attachments.delete(a),l.peerConnection.close().catch(()=>{}));let p;try{p=await this.dial(u)}catch(m){return r?Qn(o,x.InternalError,`Could not reach remote "${i.name}": ${m.message}`):void 0}let f={peerConnection:p,localId:i.localId,target:n};this.wireAttachment(i.name,f);let h;try{h=await p.request("session/attach",d)}catch(m){return p.close().catch(()=>{}),r?hi(o,m):void 0}this.attachments.set(a,f);let k=h&&typeof h.sessionId=="string"?{...h,sessionId:t}:h;return r?{jsonrpc:"2.0",id:o,result:k}:void 0}let c=this.attachments.get(a);if(!c)return r?Qn(o,x.SessionNotFound,`"${t}" is not attached through this daemon.`):void 0;if(e.method==="session/detach"){let u,l;try{u=await c.peerConnection.request("session/detach",d)}catch(p){l=p}return this.attachments.delete(a),c.peerConnection.close().catch(()=>{}),l?r?hi(o,l):void 0:r?{jsonrpc:"2.0",id:o,result:u??{}}:void 0}if(r)try{let u=await c.peerConnection.request(e.method,d);return{jsonrpc:"2.0",id:o,result:u}}catch(u){return hi(o,u)}await c.peerConnection.notify(e.method,d).catch(()=>{})}detachClient(e){for(let[t,n]of[...this.attachments.entries()])n.target.clientId===e&&(this.attachments.delete(t),n.peerConnection.request("session/detach",{sessionId:n.localId}).catch(()=>{}),n.peerConnection.close().catch(()=>{}))}wireAttachment(e,t){let{peerConnection:n,localId:r,target:o}=t,i=Je({name:e,localId:r}),a=()=>{this.attachments.delete(Gu(o.clientId,i))};n.onAnyNotification((d,c)=>{let u=d;!u||u.sessionId!==r||(c==="hydra-acp/session/closed"&&a(),o.connection.notify(c,{...u,sessionId:i}).catch(()=>{}))}),n.onRequest("hydra-acp/session/request_permission",async d=>{let c=d;if(!c||c.sessionId!==r)throw{code:x.MethodNotFound,message:"unexpected sessionId"};return o.connection.request("hydra-acp/session/request_permission",{...c,sessionId:i})}),n.onClose(()=>{a(),o.connection.notify("hydra-acp/session/closed",{sessionId:i}).catch(()=>{})})}};function Gu(s,e){return`${s} ${e}`}function Qn(s,e,t){return{jsonrpc:"2.0",id:s,error:{code:e,message:t}}}function hi(s,e){let t=e,n=typeof t?.code=="number"?t.code:x.InternalError,r=typeof t?.message=="string"?t.message:String(e??"forward failed");return{jsonrpc:"2.0",id:s,error:{code:n,message:r,...t?.data!==void 0?{data:t.data}:{}}}}var lw=1e4;async function fw(s){let t=`${Ae(s.host)?"ws":"wss"}://${s.host}:${s.port}/acp`,n=await Vu(t,["acp.v1",`hydra-acp-token.${s.token}`],lw);return new qe(pr(n))}var pw=3e4,gw=5e3,mr=class{constructor(e,t={}){this.store=e;this.opts=t}store;opts;snapshots=new Map;timer;start(){this.timer||(this.checkAll(),this.timer=setInterval(()=>{this.checkAll()},this.opts.intervalMs??pw),this.timer.unref?.())}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}get(e){return this.snapshots.get(e)}markOk(e,t){this.snapshots.set(e,{status:"ok",checkedAt:new Date().toISOString(),...t?{system:t}:{}})}forget(e){this.snapshots.delete(e)}async checkAll(){let e=this.opts.fetchImpl??fetch;await Promise.allSettled(this.store.list().map(async t=>{let n=this.store.get(t.name);if(!n)return;let r=new AbortController,o=setTimeout(()=>r.abort(),gw);try{let i=await ur({host:n.host,port:n.port,token:n.token,fetchImpl:e,signal:r.signal});if(i.kind==="ok"){this.snapshots.set(t.name,{status:"ok",checkedAt:new Date().toISOString(),...i.system?{system:i.system}:{}});return}if(i.kind==="unauthorized"){this.snapshots.set(t.name,{status:"unauthorized",checkedAt:new Date().toISOString()});return}if(i.kind==="error")throw new Error(i.message);let d=`${Ae(n.host)?"http":"https"}://${n.host}:${n.port}/v1/auth/verify`,c=await e(d,{headers:{Authorization:`Bearer ${n.token}`},signal:r.signal});this.snapshots.set(t.name,{status:c.ok?"ok":"unauthorized",checkedAt:new Date().toISOString()})}catch(i){this.snapshots.set(t.name,{status:"unreachable",checkedAt:new Date().toISOString(),error:i.message})}finally{clearTimeout(o)}}))}};Kn();import{z as Qu}from"zod";var mw=Qu.object({sessionLabel:Qu.string().min(1).max(256)});function Yu(s,e){s.post("/v1/process-tokens",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=mw.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}let o=e.processRegistry.mint(r.sessionLabel,"script");return n.code(201).send({token:o})}),s.delete("/v1/process-tokens/:sessionLabel",async(t,n)=>t.authIdentity!=="service"?n.code(403).send({error:"Requires the service token"}):(e.processRegistry.revoke(t.params.sessionLabel),n.code(204).send()))}import{nanoid as yi}from"nanoid";import{randomBytes as nl}from"crypto";import*as sl from"os";import*as rl from"path";var hw=200;function yw(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e[le];if(!t||typeof t!="object"||Array.isArray(t))return;let n=t.sentBy;if(!n||typeof n!="object"||Array.isArray(n))return;let r=n,o={};if(typeof r.sessionId=="string"&&r.sessionId.length>0&&(o.sessionId=r.sessionId),typeof r.label=="string"&&r.label.length>0&&(o.label=r.label.slice(0,hw)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function Xu(s,e,t){let n=yw(s);if(!n)return;let r={};if(n.label!==void 0&&(r.fromLabel=n.label),n.awaiting===!0&&(r.awaiting=!0),n.sessionId!==void 0){let o=await e.resolveCanonicalId(n.sessionId)??n.sessionId,i=await e.getOne(o);if(i){r.fromSession=o,i.title&&(r.fromSessionTitle=i.title);let a=e.get(o)?.currentPromptDepth;r.depth=(a??0)+1}else t?.(n.sessionId)}if(!(r.fromSession===void 0&&r.fromLabel===void 0))return r}var Yn=new Map;function Zu(s,e){let t=Yn.get(s);t||(t=new Set,Yn.set(s,t)),t.add(e);let n=!1;return()=>{if(n)return;n=!0;let r=Yn.get(s);r&&(r.delete(e),r.size===0&&Yn.delete(s))}}function el(s,e){if(s===e)return!0;let t=new Set,n=[e];for(;n.length>0;){let r=n.pop();if(t.has(r))continue;t.add(r);let o=Yn.get(r);if(o){if(o.has(s))return!0;for(let i of o)n.push(i)}}return!1}function O(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function Sw(s){if(!s||typeof s!="object")return 512;let n=s.params?.update;if(!n)return 512;let r=512,o=n.content;if(typeof o=="string")r+=o.length;else if(o&&typeof o=="object"){let a=o;typeof a.text=="string"&&(r+=a.text.length),typeof a.data=="string"&&(r+=a.data.length)}let i=n.toolCall;if(i&&(typeof i.rawInput=="string"?r+=i.rawInput.length:i.rawInput&&typeof i.rawInput=="object"&&(r+=256),typeof i.rawOutput=="string"?r+=i.rawOutput.length:i.rawOutput&&typeof i.rawOutput=="object"&&(r+=256),Array.isArray(i.content)))for(let a of i.content){if(!a||typeof a!="object")continue;let d=a;if(typeof d.text=="string"&&(r+=d.text.length),d.content&&typeof d.content=="object"){let c=d.content;typeof c.text=="string"&&(r+=c.text.length)}}return r}function Te(s,e,t){let n=s.get(e);if(!n)throw O(x.SessionNotFound,t??`session ${e} not found`);return n}async function Pt(s,e){let t=rn(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=nl(32).toString("hex"),r=s.mcpTokenRegistry.reserve(n),o={name:"hydra-acp-recall",type:"http",url:`${s.getDaemonOrigin()}/mcp/hydra-acp-recall`,headers:[{name:"Authorization",value:`Bearer ${n}`}]});let a=[...t?.descriptors??[],...o!==void 0?[o]:[]],d=oi({baselineMcpServers:void 0,stdinEnabled:!1,deps:s}),c;try{c=await s.manager.resurrect({...e,mcpServers:a,...d?{mintMcpServersForSwap:d}:{}})}catch(u){throw t!==void 0&&t.abandon(u instanceof Error?u:void 0),r!==void 0&&r.abandon(u instanceof Error?u:void 0),u}if(t!==void 0&&t.bindToSession(c),n!==void 0&&r!==void 0&&s.mcpTokenRegistry!==void 0){let u=n,l=s.mcpTokenRegistry;r.complete(c),c.onClose(()=>{l.unbind(u)})}return _w(c,s),il(c.sessionId,s),c}function ol(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=Yc({headers:n.headers,url:n.url});if(!r||!await e.validator.validate(r)){t.close(4401,"Unauthorized");return}let o=e.processRegistry?.resolve(r),i=`hydra_client_${yi(12)}`,a=pr(t),d={},c=e.foreignSessions?Ku(a,e.foreignSessions,d,i):a,u=new qe(c);d.connection=u;let l={clientId:i,processIdentity:o,attached:new Map};u.setParamsRewriter(m=>{if(m===null||typeof m!="object")return m;let g=m.sessionId;if(typeof g!="string"||l.attached.has(g))return m;let y=ye+g;return l.attached.has(y)?{...m,sessionId:y}:m}),u.onClose(()=>{for(let m of l.attached.values())e.manager.get(m.sessionId)?.detach(m.clientId);l.attached.clear(),e.foreignSessions?.detachClient(i)});let p=(m,g)=>{if(l.attached.get(m)?.readonly)throw O(x.PermissionDenied,`${g} not permitted on a read-only attachment`)};if(u.onRequest("initialize",async m=>{let g=ga.parse(m??{});g.clientInfo?.name&&(l.clientInfo={name:g.clientInfo.name,...g.clientInfo.version!==void 0?{version:g.clientInfo.version}:{}});let y=g.clientInfo?.version;return y&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,y):e.onTransformerVersion?.(o.name,y)),Mw()}),o&&e.extensionCommands){let m=e.extensionCommands;u.onRequest("hydra-acp/commands/register",async g=>{let y=g??{},w=Array.isArray(y.commands)?y.commands.map(v=>{if(!v||typeof v!="object")return;let S=v;if(typeof S.verb!="string")return;let b={verb:S.verb};return typeof S.argsHint=="string"&&(b.argsHint=S.argsHint),typeof S.description=="string"&&(b.description=S.description),b}).filter(v=>v!==void 0):[];return m.register(o.name,u,w),{ok:!0,registered:w.length}}),u.onClose(()=>{m.clear(o.name)})}if(o&&e.extensionMcp){let m=e.extensionMcp;u.onRequest("hydra-acp/mcp_tools/register",async y=>{let w=y??{},v=typeof w.instructions=="string"?w.instructions:void 0,S=Array.isArray(w.tools)?w.tools.map(b=>{if(!b||typeof b!="object")return;let I=b;if(typeof I.name!="string"||I.name.length===0||typeof I.description!="string"||I.inputSchema===null||typeof I.inputSchema!="object")return;let C={name:I.name,description:I.description,inputSchema:I.inputSchema};return I.outputSchema!==null&&typeof I.outputSchema=="object"&&(C.outputSchema=I.outputSchema),C}).filter(b=>b!==void 0):[];if(S.length===0)throw new Error("register_mcp_tools requires at least one tool");return m.register(o.name,u,v,S),{ok:!0,registered:S.length}});let g=y=>{let w=y??{};if(typeof w.sessionId!="string"||w.sessionId.length===0)throw O(x.InvalidParams,"sessionId is required");return w.sessionId};if(u.onRequest("hydra-acp/session/extension_state/get",async y=>{let w=g(y),v=y??{};if(typeof v.key!="string"||v.key.length===0)throw O(x.InvalidParams,"key is required");if(!e.manager)throw O(x.InternalError,"manager not wired");return{value:await e.manager.getExtensionStateKey(w,o.name,v.key)??null}}),u.onRequest("hydra-acp/session/extension_state/list",async y=>{let w=g(y);if(!e.manager)throw O(x.InternalError,"manager not wired");return{state:await e.manager.getExtensionState(w,o.name)}}),u.onRequest("hydra-acp/session/extension_state/set",async y=>{let w=g(y),v=y??{};if(typeof v.key!="string"||v.key.length===0)throw O(x.InvalidParams,"key is required");if(v.value===void 0)throw O(x.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw O(x.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(w,o.name,v.key,v.value)}catch(S){throw O(x.InvalidParams,S.message)}return{ok:!0}}),u.onRequest("hydra-acp/session/extension_state/delete",async y=>{let w=g(y),v=y??{};if(typeof v.key!="string"||v.key.length===0)throw O(x.InvalidParams,"key is required");if(!e.manager)throw O(x.InternalError,"manager not wired");return await e.manager.deleteExtensionStateKey(w,o.name,v.key),{ok:!0}}),e.extensionMcpControls){let y=e.extensionMcpControls;u.onRequest("hydra-acp/mcp_tools/refresh_session",async w=>{let v=w??{};if(typeof v.sessionId!="string"||v.sessionId.length===0)throw O(x.InvalidParams,"refresh_session requires sessionId");return await y.notifyToolListChanged(v.sessionId,o.name),{ok:!0}})}u.onClose(()=>{m.clear(o.name)})}o?.kind==="transformer"&&(u.onRequest("hydra-acp/transformer/initialize",async m=>{let g=m??{},y=Array.isArray(g.intercepts)?g.intercepts.filter(w=>typeof w=="string"):[];if(e.transformers&&(e.transformers.registerConnection(o.name,u,y),e.manager?.defaultTransformers.includes(o.name))){let w=e.transformers.resolveChain([o.name])[0];if(w)for(let v of e.manager.liveSessions())v.addTransformer(w)}return{ack:!0}}),u.onClose(()=>{e.transformers?.deregisterConnection(o.name)}),u.onRequest("hydra-acp/message/emit",async m=>{let g=m??{},y=typeof g.sessionId=="string"?g.sessionId:void 0,w=typeof g.method=="string"?g.method:void 0,v=g.envelope,S=g.route;if(!y)throw O(-32602,"emit_message requires sessionId");if(!w&&S!=="client_broadcast")throw O(-32602,"emit_message requires method");let b=Te(e.manager,y),I=typeof g.respondsTo=="string"?g.respondsTo:void 0;if(I)return b.dischargeClaim(I,v),{ok:!0};if(S==="chain")return{ok:!0,response:await b.emitToChain(o.name,w,v)};if(S==="queue"){if(w!=="session/prompt")throw O(-32602,'route "queue" only supports method "session/prompt"');return{ok:!0,response:await b.emitToQueue(o.name,v)}}if(S==="daemon")return{ok:!0,response:await b.emitToChain(o.name,w,v)};if(S==="client_broadcast"){if(!v||typeof v!="object")throw O(-32602,"client_broadcast requires an envelope object");return b.broadcastClientUpdate(v),{ok:!0}}throw O(-32602,`unsupported route: ${JSON.stringify(S)}`)}),u.onRequest("hydra-acp/session/request_permission",async m=>{let g=m??{},y=typeof g.sessionId=="string"?g.sessionId:void 0;if(!y)throw O(-32602,"hydra-acp/session/request_permission requires sessionId");return Te(e.manager,y).requestPermissionFromClients(g)}),u.onRequest("hydra-acp/transformer/attach",async m=>xw(m,o.name,e)),u.onRequest("hydra-acp/child_session/spawn",async m=>{let g=m??{},y=typeof g.agentId=="string"?g.agentId:void 0,w=typeof g.cwd=="string"?g.cwd:void 0,v=typeof g.parentSessionId=="string"?g.parentSessionId:void 0,S=at(g._meta??void 0),b=S.title,I=S.model,C=S.workspace;if(!w&&v){let L=e.manager.get(v);L&&(w=L.cwd)}if(!w)throw O(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let R=await pn(w),E=y??R.agentId??e.defaultAgent,M=await e.registry?.getAgent(E),N=Jr(R.configDefaults,M??{id:E})?.value,B=I??N?.model,q=typeof g.interactive=="boolean"?g.interactive:!1,V=await e.manager.create({agentId:E,cwd:w,parentSessionId:v,interactive:q,transformChain:[],title:b,model:B,configDefaults:N,...C!==void 0?{workspace:C}:{}});return{childSessionId:V.sessionId,...V.workspace!==void 0||V.workspaceError!==void 0?{_meta:{[le]:{...V.workspace!==void 0?{workspaceInfo:V.workspace}:{},...V.workspaceError!==void 0?{workspaceError:V.workspaceError}:{}}}}:{}}}));let f=async(m,g)=>{let y=m??{};if(typeof y.sessionId!="string")throw O(x.InvalidParams,"fork_session requires sessionId");let w=typeof y.forkAt=="string"?y.forkAt:void 0,v=typeof y.cwd=="string"?y.cwd:void 0,S=typeof y.agentId=="string"?y.agentId:void 0,b=g?void 0:typeof y.mode=="string"&&(y.mode==="verbatim"||y.mode==="synthesis")?y.mode:void 0,I=typeof y.model=="string"&&y.model.length>0?y.model:void 0,C;if(g){let B=y.selection;if(B!==void 0&&(typeof B.text!="string"||B.text.length===0))throw O(x.InvalidParams,"selection.text must be a non-empty string");C={...B!==void 0?{selection:{text:B.text,...typeof B.responsePartId=="string"?{responsePartId:B.responsePartId}:{}}}:{}}}let R=await e.manager.forkSession(y.sessionId,{...C!==void 0?{side:C}:{},...w!==void 0?{forkAt:w}:{},...v!==void 0?{cwd:v}:{},...S!==void 0?{agentId:S}:{},...b!==void 0?{mode:b}:{},...I!==void 0?{model:I}:{}}),E=e.manager.get(R.sessionId);if(!E){let B=await e.manager.loadFromDisk(R.sessionId);if(!B)throw O(x.InternalError,`fork ${R.sessionId} vanished before it could be attached`);E=await Pt(e,{...B,onInstallProgress:hr(u)})}an(l,E,E.sessionId);let M=kt(u,E,l),{entries:N}=await E.attach(M,"full");l.attached.set(E.sessionId,{sessionId:E.sessionId,clientId:M.clientId,readonly:!1});for(let B of N){if(u.isClosed())break;await u.notify(B.method,We(Be(B.params,B.recordedAt),B.seq)).catch(()=>{})}return{...R,sessionId:E.sessionId}};u.onRequest("hydra-acp/session/fork",m=>f(m,!1)),u.onRequest("hydra-acp/session/side",m=>f(m,!0)),u.onRequest("hydra-acp/session/rewind",async m=>{let g=m??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"hydra-acp/session/rewind requires sessionId");let y=g.keepThrough;if(y!==null&&(typeof y!="string"||y.length===0))throw O(x.InvalidParams,"keepThrough must be a non-empty messageId, or null to drop every turn");let w=await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId;try{return await e.manager.rewindSession(w,y)}catch(v){let S=v;throw O(S.code??x.InternalError,S.message)}}),u.onRequest("session/fork",async m=>{let g=m??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"session/fork requires sessionId");let y=typeof g.cwd=="string"?g.cwd:void 0,w=await e.manager.forkSession(g.sessionId,{...y!==void 0?{cwd:y}:{},mode:"verbatim"}),v=e.manager.get(w.sessionId);if(!v){let I=await e.manager.loadFromDisk(w.sessionId);if(!I)throw O(x.InternalError,`fork ${w.sessionId} vanished before it could be attached`);v=await Pt(e,{...I,onInstallProgress:hr(u)})}an(l,v,v.sessionId);let S=kt(u,v,l),{entries:b}=await v.attach(S,"full");l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:S.clientId,readonly:!1});for(let I of b){if(u.isClosed())break;await u.notify(I.method,We(Be(I.params,I.recordedAt),I.seq)).catch(()=>{})}return{sessionId:v.sessionId}});let h=async(m,g)=>{let y=m??{};if(typeof y.sessionId!="string")throw O(x.InvalidParams,`${g} requires sessionId`);let w=await e.manager.resolveCanonicalId(y.sessionId)??y.sessionId,v=e.manager.get(w);if(v)return await v.close({deleteRecord:!0,by:`session/delete ${l.clientId}`}),await e.manager.waitForDeletion(w),await e.manager.hasRecord(w)&&await e.manager.deleteRecord(w),{id:w,existed:!0};let S=await e.manager.deleteRecord(w);return{id:w,existed:S}};u.onRequest("session/delete",async m=>(await h(m,"session/delete"),{})),u.onRequest("session/close",async m=>{let g=m??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"session/close requires sessionId");p(g.sessionId,"session/close");let y=await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId,w=e.manager.get(y);if(w)return await w.close({deleteRecord:!1,by:`session/close ${l.clientId}`+(l.processIdentity?` (${l.processIdentity.name})`:"")}),{};if(await e.manager.hasRecord(y))return{};throw O(x.SessionNotFound,`session ${y} not found`)}),u.onRequest("hydra-acp/session/delete",async m=>{let{id:g,existed:y}=await h(m,"hydra-acp/session/delete");if(!y)throw O(x.SessionNotFound,`session ${g} not found`);return{deleted:!0,sessionId:g}}),o?.kind==="transformer"&&(u.onRequest("hydra-acp/child_session/await",async m=>{let g=m??{},y=typeof g.childSessionId=="string"?g.childSessionId:void 0,w=g.until==="idle"?"idle":"turn_complete",v=typeof g.timeoutMs=="number"?Math.min(g.timeoutMs,18e5):3e5;if(!y)throw O(-32602,"await_child requires childSessionId");let S=Te(e.manager,y,`child session ${y} not found`);return new Promise(b=>{let R=[],E=[],M=0,N=!1,B,q,V=!1,L=()=>{V||(V=!0,clearTimeout(W),B?.(),q?.(),b(N?{entries:R,truncated:!0}:{entries:R}))};B=S.onBroadcast(Q=>{let oe=Sw(Q);for(R.push(Q),E.push(oe),M+=oe;R.length>0&&(R.length>1e3||M>1048576);)R.shift(),M-=E.shift()??0,N=!0;w==="turn_complete"&&Q.params?.update?.sessionUpdate==="turn_complete"&&L()});let W=setTimeout(L,v);typeof W.unref=="function"&&W.unref(),q=S.onClose(()=>L())})}),u.onRequest("hydra-acp/child_session/close",async m=>{let g=m??{},y=typeof g.childSessionId=="string"?g.childSessionId:void 0;if(!y)throw O(-32602,"close_child_session requires childSessionId");let w=e.manager.get(y);return w&&await w.close({deleteRecord:!1,by:`child_session/close ${l.clientId}`}),{ok:!0}}),u.onRequest("hydra-acp/attention/set",async m=>Ew(m,o.name,e)),u.onRequest("hydra-acp/attention/clear",async m=>Tw(m,o.name,e)),u.onRequest("hydra-acp/connection/keep_alive",async m=>{let g=m??{},y=typeof g.token=="string"?g.token:void 0,w=typeof g.sessionId=="string"?g.sessionId:void 0,v=typeof g.estimatedRemainingMs=="number"?g.estimatedRemainingMs:void 0;return y&&w&&e.manager.get(w)?.keepAliveClaim(y,v),{ok:!0}})),u.onRequest("hydra-acp/session/tool_content",async m=>{let g=m??{};if(typeof g.sessionId!="string"||typeof g.hash!="string")throw O(x.InvalidParams,"hydra-acp/session/tool_content requires sessionId and hash");let y=await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId,w=await e.manager.loadToolBlob(y,g.hash);if(w===null)throw O(x.SessionNotFound,"tool content not found");return{content:w}}),u.onRequest("authenticate",async m=>Iw(m,e)),u.onRequest("logout",async m=>Aw(m,e)),u.onRequest("session/new",async m=>{let g=new Bt,y=ma.parse(m),w=at(m?._meta),v=Array.isArray(w.transformers)&&w.transformers.every(te=>typeof te=="string")?w.transformers:e.manager.defaultTransformers??[],S=e.transformers?.resolveChain(v)??[],b=await pn(y.cwd),I=w.agentId??b.agentId??e.defaultAgent,C=await e.registry?.getAgent(I),R=Jr(b.configDefaults,C??{id:I})?.value,E,M,N=y.mcpServers;if(w.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){E=nl(32).toString("hex"),M=e.mcpTokenRegistry.reserve(E);let Pe={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${E}`}]};N=[...y.mcpServers??[],Pe]}let B,q,V=rn(e);V!==void 0&&(N=[...N??[],...V.descriptors]);let L=oi({baselineMcpServers:y.mcpServers,stdinEnabled:w.mcpStdin===!0,deps:e});g.mark("ws.prepare");let W;try{W=await e.manager.create({timer:g,cwd:y.cwd,agentId:I,mcpServers:N,title:w.title,agentArgs:w.agentArgs,model:w.model??R?.model,configDefaults:R,onInstallProgress:hr(u),transformChain:S,originatingClient:l.clientInfo,...w.interactive!==void 0?{interactive:w.interactive}:{},...w.env!==void 0?{forwardedEnv:w.env}:{},...w.workspace!==void 0?{workspace:w.workspace}:{},...L?{mintMcpServersForSwap:L}:{}})}catch(te){throw M!==void 0&&M.abandon(te instanceof Error?te:void 0),q!==void 0&&q.abandon(te instanceof Error?te:void 0),V!==void 0&&V.abandon(te instanceof Error?te:void 0),te}if(E!==void 0&&M!==void 0&&e.mcpTokenRegistry!==void 0){let te=E,Pe=e.mcpTokenRegistry;M.complete(W),W.onClose(()=>{Pe.unbind(te)})}if(B!==void 0&&q!==void 0&&e.mcpTokenRegistry!==void 0){let te=B,Pe=e.mcpTokenRegistry;q.complete(W),W.onClose(()=>{Pe.unbind(te)})}V!==void 0&&V.bindToSession(W),g.mark("ws.bind-mcp"),il(W.sessionId,e);let Q,oe;try{an(l,W,W.sessionId),Q=kt(u,W,l),{entries:oe}=await W.attach(Q,"full")}catch(te){throw await W.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),te}l.attached.set(W.sessionId,{sessionId:W.sessionId,clientId:Q.clientId,readonly:!1}),g.mark("ws.attach"),e.manager.logInfo(`session/new timing agent=${I} session=${W.sessionId} ${g.summary()}`),setImmediate(()=>{(async()=>{for(let te of oe){if(u.isClosed())break;await u.notify(te.method,We(Be(te.params,te.recordedAt),te.seq)).catch(()=>{})}})()});let xe=yr(W),Ze=wr(W);return{sessionId:W.sessionId,...xe?{modes:xe}:{},...Ze?{models:Ze}:{},configOptions:W.buildConfigOptions(),_meta:kr(e.manager,W,{clientId:Q.clientId})}}),u.onRequest("session/attach",async m=>{let g=ya.parse(m),y=g.clientInfo?.version;y&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,y):e.onTransformerVersion?.(o.name,y));let w=at(g._meta),v=w.resume,S=w.readonly===!0,b=w.env;s.log.info(`session/attach sessionId=${g.sessionId} hasResumeHints=${!!v} readonly=${S}`);let I=v?g.sessionId:await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId,C=e.manager.get(I);if(!C&&S){let L=await e.manager.loadFromDisk(I);if(!L)throw O(x.SessionNotFound,`session ${g.sessionId} not found`);let W=Lt(await e.manager.loadHistory(I,{...w.historyLimit!==void 0?{maxEntries:w.historyLimit}:{}}),L.side),Q=g.clientId??`cli_${yi(8)}`;l.attached.set(L.hydraSessionId,{sessionId:L.hydraSessionId,clientId:Q,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${L.hydraSessionId} clientId=${Q} attachedCount=${l.attached.size} replayed=${W.length}`);for(let oe of W)await u.notify(oe.method,We(Be(oe.params,oe.recordedAt),oe.seq)).catch(()=>{});return{sessionId:L.hydraSessionId,clientId:Q,connectedClients:[Q],historyPolicy:"full",replayed:W.length,_meta:Pw(L)}}let R=!C;if(!C){let L=await e.manager.loadFromDisk(I),W=await Cw(I,v,L?.upstreamSessionId,e.manager);W.kind==="ignore"&&s.log.warn(W.logMessage);let Q=L;if(v&&W.kind==="honor"&&(Q={...L,hydraSessionId:g.sessionId,upstreamSessionId:v.upstreamSessionId,agentId:v.agentId,cwd:L?.workspace?.path??v.cwd,...v.title!==void 0?{title:v.title}:{},...v.agentArgs!==void 0?{agentArgs:v.agentArgs}:{}}),!Q)throw O(x.SessionNotFound,`session ${g.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(Q.agentId,Q.upstreamSessionId))throw O(x.SessionNotFound,`session ${g.sessionId} was deleted`);let oe=Q.originatingClient?Q:{...Q,originatingClient:l.clientInfo},xe=b!==void 0?{...oe,forwardedEnv:b}:oe;C=await Pt(e,{...xe,onInstallProgress:hr(u)})}an(l,C,C.sessionId);let E=kt(u,C,l,g.clientInfo,g.clientId),M=w.replayMode==="drip",{entries:N,appliedPolicy:B}=await C.attach(E,g.historyPolicy,{afterMessageId:g.afterMessageId,afterSeq:g.afterSeq,raw:M,...w.historyLimit!==void 0?{historyLimit:w.historyLimit}:{},...w.toolContent!==void 0?{toolContent:w.toolContent}:{}});if(l.attached.set(C.sessionId,{sessionId:C.sessionId,clientId:E.clientId,readonly:S}),b!==void 0&&await e.manager.setForwardedEnv(C.sessionId,b).catch(()=>{}),s.log.info(`session/attach OK sessionId=${C.sessionId} clientId=${E.clientId} attachedCount=${l.attached.size} requestedPolicy=${g.historyPolicy} appliedPolicy=${B} replayed=${N.length} readonly=${S}${M?" replayMode=drip":""}`),M){let L=w.dripSpeed&&w.dripSpeed>0?w.dripSpeed:1,W=750;(async()=>{let Q=null;for(let oe of N){let xe=typeof oe.recordedAt=="number"?oe.recordedAt:null;if(Q!==null&&xe!==null){let Ze=Math.min(W,Math.max(0,(xe-Q)/L));Ze>0&&await new Promise(te=>setTimeout(te,Ze))}xe!==null&&(Q=xe);try{await u.notify(oe.method,We(Be(oe.params,xe??void 0),oe.seq))}catch{return}}})()}else for(let L=0;L<N.length&&!u.isClosed();L++){let W=N[L],Q=u.notify(W.method,We(Be(W.params,W.recordedAt),W.seq)).catch(()=>{});(L+1)%200===0&&await Q}C.replayPendingPermissions(E);let q=yr(C),V=wr(C);return{sessionId:C.sessionId,clientId:E.clientId,connectedClients:C.connectedClients(E.clientId),historyPolicy:B,replayed:N.length,...q?{modes:q}:{},...V?{models:V}:{},configOptions:C.buildConfigOptions(),_meta:kr(e.manager,C,{resurrected:R})}}),u.onRequest("session/detach",async m=>{let g=wa.parse(m),y=l.attached.get(g.sessionId);if(!y)throw O(x.SessionNotFound,"client not attached to that session");let w=e.manager.get(g.sessionId);return w?.detach(y.clientId),l.attached.delete(g.sessionId),w&&e.manager.reapIfOrphanedNonInteractive(g.sessionId),{sessionId:g.sessionId,_meta:{[le]:{detachStatus:"detached"}}}}),u.onRequest("session/list",async m=>{let g=ka.parse(m??{});return{sessions:(await e.manager.list({cwd:g.cwd})).filter(S=>S.originatingClient?.name!==Fs).map(va)}}),u.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw O(x.InternalError,"agent registry unavailable");return Dt(e.registry)}),u.onRequest("hydra-acp/agents/auth_methods",async m=>{let g=m??{};if(typeof g.agentId!="string"||g.agentId.length===0)throw O(x.InvalidParams,"hydra-acp/agents/auth_methods requires a non-empty agentId string");return{authMethods:(await e.manager.bootstrapAgentForAuth(g.agentId)).authMethods??[]}}),u.onRequest("session/prompt",async m=>{let g=ba.parse(m);p(g.sessionId,"session/prompt");let y=await Xu(g,e.manager,b=>{s.log.warn(`session/prompt: dropping unknown sentBy.sessionId=${b} sessionId=${g.sessionId}`)});if(y?.fromSession!==void 0){if((y.depth??0)>3)throw s.log.warn(`session/prompt: refusing depth ${y.depth} chain from ${y.fromSession} to ${g.sessionId}`),O(x.InvalidRequest,`message chain too deep (${y.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(y.awaiting===!0&&el(y.fromSession,g.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${y.fromSession} -> ${g.sessionId}`),O(x.InvalidRequest,`would deadlock: ${g.sessionId} is already blocked waiting on ${y.fromSession}. Send with --no-wait, or let the other turn finish first.`)}let w=l.attached.get(g.sessionId);if(!w)throw s.log.warn(`session/prompt rejected: not attached sessionId=${g.sessionId} attachedKeys=[${[...l.attached.keys()].join(",")}]`),O(x.SessionNotFound,"not attached to session");let v=e.manager.get(g.sessionId);if(!v){let b=await e.manager.loadFromDisk(g.sessionId);if(!b)throw O(x.SessionNotFound,`session ${g.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${g.sessionId}`),v=await Pt(e,b);let I=kt(u,v,l,void 0,w.clientId);await v.attach(I,"none")}let S=y?.awaiting===!0&&y.fromSession!==void 0?Zu(y.fromSession,g.sessionId):void 0;try{return await v.prompt(w.clientId,g,y)}finally{S?.()}});let k=m=>{let g;try{g=as.parse(m)}catch(v){s.log.warn(`session/cancel: invalid params: ${v.message}`);return}let y=l.attached.get(g.sessionId);if(!y)return;if(y.readonly){s.log.warn(`session/cancel dropped (readonly attachment) sessionId=${g.sessionId}`);return}let w=e.manager.get(g.sessionId);w&&w.cancel(y.clientId).catch(v=>{s.log.warn(`session/cancel for ${g.sessionId}: ${v.message}`)})};u.onNotification("session/cancel",k),u.onRequest("session/cancel",async m=>{let g=as.parse(m);return p(g.sessionId,"session/cancel"),k(m),null}),u.onRequest("hydra-acp/prompt/cancel",async m=>{let g=Ia.parse(m);return p(g.sessionId,"hydra-acp/prompt/cancel"),Te(e.manager,g.sessionId).cancelQueuedPrompt(g.messageId)}),u.onRequest("hydra-acp/session/force_cancel",async m=>{let g=as.parse(m);return p(g.sessionId,"hydra-acp/session/force_cancel"),Te(e.manager,g.sessionId).forceCancel()}),u.onRequest("hydra-acp/prompt/update",async m=>{let g=Aa.parse(m);return p(g.sessionId,"hydra-acp/prompt/update"),Te(e.manager,g.sessionId).updateQueuedPrompt(g.messageId,g.prompt)}),u.onRequest("hydra-acp/prompt/amend",async m=>{let g=Ca.parse(m);p(g.sessionId,"hydra-acp/prompt/amend");let y=l.attached.get(g.sessionId);if(!y)throw O(x.SessionNotFound,"not attached to session");return Te(e.manager,g.sessionId).amendPrompt(y.clientId,g)}),u.onRequest("_session/steering",async m=>{let g=Ra.parse(m);p(g.sessionId,"_session/steering");let y=l.attached.get(g.sessionId);if(!y)throw O(x.SessionNotFound,"not attached to session");let w=e.manager.get(g.sessionId);if(!w){let v=await e.manager.loadFromDisk(g.sessionId);if(!v)throw O(x.SessionNotFound,`session ${g.sessionId} not found`);w=await Pt(e,v);let S=kt(u,w,l,void 0,y.clientId);await w.attach(S,"none")}return w.steer(y.clientId,g)}),u.onRequest("session/resume",async m=>{let g=m??{},y=typeof g.sessionId=="string"?g.sessionId:void 0;if(!y)throw O(x.InvalidParams,"session/resume requires sessionId");let w=await e.manager.resolveCanonicalId(y)??y,v=e.manager.get(w);if(!v){let C=await e.manager.loadFromDisk(w);if(!C)throw O(x.SessionNotFound,`session ${y} not found in memory or on disk`);v=await Pt(e,C)}an(l,v,v.sessionId);let S=kt(u,v,l);await v.attach(S,"pending_only"),l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:S.clientId,readonly:!1}),v.replayPendingPermissions(S);let b=yr(v),I=wr(v);return{sessionId:v.sessionId,...b?{modes:b}:{},...I?{models:I}:{},configOptions:v.buildConfigOptions(),_meta:kr(e.manager,v,{clientId:S.clientId})}}),u.onRequest("session/load",async m=>{let g=m??{},y=typeof g.sessionId=="string"?g.sessionId:void 0;if(!y)throw O(x.InvalidParams,"session/load requires sessionId");let w=await e.manager.resolveCanonicalId(y)??y,v=e.manager.get(w);if(!v){let R=await e.manager.loadFromDisk(w);if(!R)throw O(x.SessionNotFound,`session ${y} not found in memory or on disk`);v=await Pt(e,R)}an(l,v,v.sessionId);let S=kt(u,v,l),{entries:b}=await v.attach(S,"full");l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:S.clientId,readonly:!1});for(let R of b){if(u.isClosed())break;await u.notify(R.method,We(Be(R.params,R.recordedAt),R.seq)).catch(()=>{})}v.replayPendingPermissions(S);let I=yr(v),C=wr(v);return{sessionId:v.sessionId,...I?{modes:I}:{},...C?{models:C}:{},configOptions:v.buildConfigOptions(),_meta:kr(e.manager,v,{clientId:S.clientId})}}),u.onRequest("session/set_model",async m=>{let g=m?.sessionId;typeof g=="string"&&p(g,"session/set_model");let y=Rw(m,e.manager);if(y.kind==="error")throw s.log.warn(y.logMessage),O(y.code,y.message);if(y.kind==="no_op")return s.log.warn(y.logMessage),await u.notify("session/update",{sessionId:y.sessionId,update:{sessionUpdate:"_hydra_current_model_update",currentModel:y.currentModel}}).catch(()=>{}),null;s.log.info(y.logMessage);let{modelId:w}=y,v=await y.session.forwardModelChange(w,m);return y.session.applyAgentConfigOptionResponse(v,"model"),y.session.applyModelChange(w),v}),u.onRequest("session/set_mode",async m=>{let g=m,y=g?.sessionId;if(typeof y=="string"&&p(y,"session/set_mode"),!g||typeof g.sessionId!="string")throw O(x.InvalidParams,"session/set_mode requires string sessionId");if(typeof g.modeId!="string")throw O(x.InvalidParams,"session/set_mode requires string modeId");let w=Te(e.manager,g.sessionId),v=await w.forwardRequest("session/set_mode",m);return w.applyModeChange(g.modeId),v}),u.onRequest("session/set_config_option",async m=>{let g=m,y=b=>O(x.InvalidParams,b),w=g?.sessionId;if(typeof w=="string"&&p(w,"session/set_config_option"),!g||typeof g.sessionId!="string")throw y("session/set_config_option requires string sessionId");if(typeof g.configId!="string")throw y("session/set_config_option requires string configId");if(typeof g.value!="string")throw y("session/set_config_option requires string value");let v=Te(e.manager,g.sessionId),S=v.buildConfigOptions().find(b=>b.id===g.configId);if(!S)throw y(`unknown configId ${JSON.stringify(g.configId)} for this session`);if(!S.options.some(b=>b.value===g.value))throw y(`value ${JSON.stringify(g.value)} is not valid for configId ${JSON.stringify(g.configId)}`);switch(g.configId){case"model":{if(g.value!==v.currentModel){let b=await v.forwardModelChange(g.value);v.applyAgentConfigOptionResponse(b,"model")}v.applyModelChange(g.value);break}case"mode":{g.value!==v.currentMode&&await v.forwardRequest("session/set_mode",{sessionId:g.sessionId,modeId:g.value}),v.applyModeChange(g.value);break}case"agent":{g.value!==v.agentId&&await v.setAgent(g.value);break}default:{let b=await v.forwardRequest("session/set_config_option",{sessionId:g.sessionId,configId:g.configId,value:g.value});v.applyAgentConfigOptionResponse(b,g.configId)&&v.broadcastConfigOptions()}}return{configOptions:v.buildConfigOptions()}}),u.setDefaultHandler(async(m,g)=>{let y=new Set(["hydra-acp/attention/set","hydra-acp/attention/clear"]),w=g.startsWith("session/"),v=g.startsWith("hydra-acp/");if(!w&&!v||m===null||typeof m!="object"||y.has(g))throw O(x.MethodNotFound,`Method not found: ${g}`);let S=m.sessionId;if(typeof S!="string")throw O(x.MethodNotFound,`Method not found: ${g}`);return p(S,g),Te(e.manager,S).forwardRequest(g,m)})})}async function Iw(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw O(x.InvalidParams,"authenticate requires a non-empty methodId string");let n=t.methodId,r=t._meta?.["hydra-acp"],o=typeof r?.sessionId=="string"?r.sessionId:void 0,i=typeof r?.agentId=="string"?r.agentId:void 0,a=o!==void 0?e.manager.getAgentForSession(o):void 0;if(!a||!a.isAlive()){let f=i??e.defaultAgent;a=await e.manager.bootstrapAgentForAuth(f)}let d=a.authMethods??[],c=d.find(f=>f.id===n);if(!c){let f=d.map(h=>h.id);throw O(x.InvalidParams,`authenticate: methodId ${JSON.stringify(n)} is not advertised by agent ${a.agentId}; valid: [${f.map(h=>JSON.stringify(h)).join(", ")}]`)}let u=c._meta?.type,l=(()=>{let f=c._meta?.["terminal-auth"];if(f&&typeof f=="object"&&!Array.isArray(f))return f})();if((c.type??(u==="agent"||u==="terminal"?u:l!==void 0?"terminal":"agent"))==="terminal"){let f=(w,v)=>{if(!Array.isArray(w))throw O(x.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${v} must be a string[]; got ${w===null?"null":typeof w}`);for(let S of w)if(typeof S!="string")throw O(x.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${v} must be string[]; got non-string entry ${JSON.stringify(S)}`);return w},h=await e.manager.planSpawnForAgent(a.agentId),k,m;if(l?.args!==void 0){let w=typeof l.command=="string"?l.command:void 0;k=w!==void 0&&rl.isAbsolute(w)?w:h.command,m=f(l.args,'_meta["terminal-auth"].args')}else{let w=c.args!==void 0?{raw:c.args,label:"args"}:c._meta?.args!==void 0?{raw:c._meta.args,label:"_meta.args"}:void 0,v=w!==void 0?f(w.raw,w.label):[];k=h.command,m=[...h.args,...v]}let g={};for(let[w,v]of Object.entries(process.env))typeof v=="string"&&(g[w]=v);Object.assign(g,h.env);let y=sl.homedir();return console.error(`[authenticate] terminal-auth requested agentId=${a.agentId} methodId=${n}`),{kind:"terminal",command:k,args:m,env:g,cwd:y}}try{return await a.connection.request("authenticate",{methodId:n})}catch(f){throw ht(f,a)}}async function Aw(s,e){let n=(s??{})._meta?.["hydra-acp"],r=typeof n?.sessionId=="string"?n.sessionId:void 0,o=typeof n?.agentId=="string"?n.agentId:void 0,i=r!==void 0?e.manager.getAgentForSession(r):void 0;if(!i||!i.isAlive()){let a=o??e.defaultAgent;i=await e.manager.bootstrapAgentForAuth(a)}return await i.connection.request("logout",{})}function hr(s){return e=>{let t={agentId:e.agentId,version:e.version,source:e.source,phase:e.phase};"receivedBytes"in e&&(t.receivedBytes=e.receivedBytes),"totalBytes"in e&&(t.totalBytes=e.totalBytes),"packageSpec"in e&&(t.packageSpec=e.packageSpec),s.notify(xa,t).catch(()=>{})}}function yr(s){let e=s.availableModes();if(e.length===0)return;let t=e.map(r=>{let o={id:r.id,name:r.name??r.id};return r.description!==void 0&&(o.description=r.description),o});return{currentModeId:s.currentMode??e[0].id,availableModes:t}}function wr(s){let e=s.availableModels();if(e.length===0)return;let t=e.map(r=>{let o={modelId:r.modelId};return r.name!==void 0&&(o.name=r.name),r.description!==void 0&&(o.description=r.description),o});return{currentModelId:s.currentModel??e[0].modelId,availableModels:t}}async function Cw(s,e,t,n){return e?await n.isRetiredGeneration(s,e.upstreamSessionId)?{kind:"ignore",logMessage:`session/attach ignoring stale resume hint sessionId=${s} hintUpstream=${e.upstreamSessionId} recordUpstream=${t} (retired generation)`}:{kind:"honor"}:{kind:"none"}}function Rw(s,e){if(!s||typeof s!="object")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires params",logMessage:"session/set_model rejected: params not an object"};let t=s;if(typeof t.sessionId!="string")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires string sessionId",logMessage:"session/set_model rejected: missing/non-string sessionId"};if(typeof t.modelId!="string")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires string modelId",logMessage:`session/set_model rejected: missing/non-string modelId sessionId=${t.sessionId}`};let n=e.get(t.sessionId);if(!n)return{kind:"error",code:x.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=Jt(t.modelId,r);if(o.kind==="none")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model passthrough (no availableModels) sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="exact")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model accepted sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="resolved")return{kind:"ok",session:n,modelId:o.modelId,logMessage:`session/set_model resolved sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} \u2192 ${JSON.stringify(o.modelId)}`};let i=r.map(d=>d.modelId).join(", "),a=o.kind==="ambiguous"?`ambiguous (trailing-segment matches [${o.candidates.join(", ")}])`:"not in availableModels";return n.currentModel!==void 0&&n.currentModel.length>0?{kind:"no_op",session:n,sessionId:t.sessionId,currentModel:n.currentModel,logMessage:`session/set_model no_op (resyncing client) sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} ${a} actual=${JSON.stringify(n.currentModel)} agentId=${n.agentId} known=[${i}]`}:{kind:"error",code:x.InvalidParams,message:`model "${t.modelId}" is ${a==="not in availableModels"?"not in this session's availableModels":a} (agent ${n.agentId}); known models: ${i}`,logMessage:`session/set_model rejected sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)} ${a} agentId=${n.agentId} known=[${i}] (no current model to fall back to)`}}async function xw(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw O(x.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw O(x.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw O(x.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return Te(t.manager,r).addTransformer(o),{ok:!0}}async function Ew(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(x.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw O(x.InvalidParams,"hydra-acp/attention/set requires string reason");return Te(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function Tw(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(x.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw O(x.InvalidParams,"hydra-acp/attention/clear requires string reason");return Te(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function Pw(s){let e={sessionId:s.hydraSessionId,upstreamSessionId:s.upstreamSessionId,cwd:s.cwd,workspace:s.workspace,title:s.title,agentId:s.agentId,currentModel:s.currentModel,currentUsage:Fn(s.currentUsage),forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:s.interactive,updatedAt:s.createdAt??new Date().toISOString(),attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1},t={currentMode:s.currentMode,agentArgs:s.agentArgs,availableCommands:s.agentCommands,availableModes:s.agentModes,availableModels:s.agentModels,armedTaskList:[]};return{[le]:is(e,t)}}function kr(s,e,t={}){let n=s.liveListEntry(e),r={clientId:t.clientId,currentMode:e.currentMode,agentArgs:e.agentArgs,availableCommands:e.mergedAvailableCommands(),availableModes:e.availableModes(),availableModels:e.availableModels(),turnStartedAt:e.turnStartedAt,agentCapabilities:e.agentCapabilities,queue:e.queueSnapshot(),armedTaskList:e.armedBackgroundTasks,...t.resurrected===!0?{resurrected:!0}:{}};return yn(e.agentMeta,is(n,r))}function Mw(){return{protocolVersion:1,agentInfo:{name:"hydra",version:ue},agentCapabilities:{promptCapabilities:{image:!0,audio:!0,embeddedContext:!0},mcpCapabilities:{http:!0,sse:!0},loadSession:!0,auth:{logout:{}},sessionCapabilities:{attach:{},list:{},resume:{},delete:{},close:{},fork:{}}},authMethods:[{id:"proxy",name:"Hydra proxy",type:"agent",description:"Hydra proxies authentication to the downstream agent selected per session"}],_meta:{...yn(void 0,{prompt:{queueing:!0,cancelling:!0,updating:!0,amending:!0,pipelining:!1},agents:{list:!0,installProgress:!0},session:{fork:{forkAt:!0,agentSwap:!0,synthesis:!0,model:!0},side:{selection:!0},rewind:{}}}),steering:{supported:!0}}}}function _w(s,e){if(!(!e.transformers||!e.manager))for(let t of e.manager.defaultTransformers){let n=e.transformers.resolveChain([t])[0];n&&s.addTransformer(n)}}function il(s,e){if(!e.transformers)return;let t=e.transformers.interestedIn("lifecycle:session.starting");for(let n of t)n.connection.notify("hydra-acp/transformer/session_event",{event:"session.starting",sessionId:s}).catch(()=>{})}function kt(s,e,t,n,r){return{clientId:r??`cli_${yi(8)}`,connection:s,clientInfo:n}}function an(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var vr=class{byToken=new Map;reserve(e){if(this.byToken.has(e))throw new Error("mcp token already bound");let t,n,r=new Promise((i,a)=>{t=i,n=a});r.catch(()=>{});let o={session:void 0,sessionReady:r,disposers:[]};return this.byToken.set(e,o),{complete:i=>{o.session=i,t(i)},abandon:i=>{this.byToken.delete(e),n(i??new Error("mcp token reservation abandoned"))}}}bind(e,t){let{complete:n}=this.reserve(e);n(t)}lookup(e){return this.byToken.get(e)}addDisposer(e,t){let n=this.byToken.get(e);n!==void 0&&n.disposers.push(t)}async unbind(e){let t=this.byToken.get(e);if(t!==void 0){this.byToken.delete(e);for(let n of t.disposers)try{await n()}catch{}}}size(){return this.byToken.size}};import{randomUUID as $w}from"crypto";import{McpServer as Ow}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Fw}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as we}from"zod";function wi(s){if(s.method!=="session/update")return null;let t=s.params?.update;return!t||typeof t.sessionUpdate!="string"?null:{kind:t.sessionUpdate,update:t}}function Re(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var al="Bearer ";function dn(s){let e=s.headers.authorization;if(typeof e!="string"||!e.startsWith(al))return;let t=e.slice(al.length).trim();return t.length>0?t:void 0}function Nw(s){let e=new Ow({name:"hydra-acp-stdin",version:"1.0.0"},{instructions:"Piped input from `hydra cat --stream` is exposed here as a byte stream. Use `tail` for the latest N bytes (good for finding the end of a log), `head` for the first N bytes (good for headers/preamble), `read` for windowed reads against an absolute byte cursor, `wait_for_more` to block until new bytes arrive past a cursor, and `info` for the current cursors/capacity/closed status. Byte payloads come back base64-encoded."});return e.registerTool("tail",{description:"Return the most recent `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means older bytes existed but have been evicted from the ring.",inputSchema:{bytes:we.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return Re(n)}),e.registerTool("head",{description:"Return the first `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means the head has already been evicted from the ring and the returned bytes start at the oldest still-resident cursor.",inputSchema:{bytes:we.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return Re(n)}),e.registerTool("read",{description:"Read up to `max_bytes` bytes starting at absolute byte `cursor`. Returns `{bytes, nextCursor, gap?, eof?}` \u2014 `gap` is the number of bytes silently skipped because the ring had evicted them; `eof:true` means the producer closed and there is nothing left to read.",inputSchema:{cursor:we.number().int().min(0).describe("Absolute byte offset to start reading from. Use 0 to read from the very beginning (may produce a gap if old bytes have been evicted)."),max_bytes:we.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:we.number().int().min(0).optional().describe("If no bytes are available, block up to this many ms for more (capped server-side at 60_000).")}},async({cursor:t,max_bytes:n,wait_ms:r})=>{let o=await s.streamRead(t,n,r);return Re(o)}),e.registerTool("wait_for_more",{description:"Block until bytes are available past `cursor`, the stream closes, or `timeout_ms` elapses. Returns one of {data, eof, timeout} plus the current `writeCursor`. Use this when you've consumed everything up to a cursor and want to wait for more without busy-polling.",inputSchema:{cursor:we.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:we.number().int().min(0).describe("Maximum ms to block (server caps at 60_000).")}},async({cursor:t,timeout_ms:n})=>{let r=await s.streamWaitFor(t,n),o=s.streamInfo();return Re({outcome:r,writeCursor:o.writeCursor,closed:o.closed})}),e.registerTool("grep",{description:"Scan piped stdin line-by-line and return lines matching `pattern`. Prefer this over `read` when the question is 'find lines that mention X' \u2014 it filters server-side so you don't pull and decode 64 KiB base64 windows. Returns `{matches: [{cursor, line, before?, after?}], truncated, nextCursor, gap?, scannedBytes, eof?}`. Lines come back as decoded UTF-8 strings (not base64). When `truncated:true`, re-call with `cursor: nextCursor` to resume.",inputSchema:{pattern:we.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:we.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:we.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:we.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:we.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:we.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:we.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:we.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:we.number().int().min(0).optional().describe("Optional absolute byte offset to start scanning from. Omit to scan from the oldest still-resident byte. Pass the `nextCursor` from a previous truncated call to resume.")}},async t=>{let n={pattern:t.pattern};t.regex!==void 0&&(n.regex=t.regex),t.case_insensitive!==void 0&&(n.caseInsensitive=t.case_insensitive),t.invert!==void 0&&(n.invert=t.invert),t.max_matches!==void 0&&(n.maxMatches=t.max_matches),t.max_bytes!==void 0&&(n.maxBytes=t.max_bytes),t.context_before!==void 0&&(n.contextBefore=t.context_before),t.context_after!==void 0&&(n.contextAfter=t.context_after),t.cursor!==void 0&&(n.cursor=t.cursor);let r=s.streamGrep(n);return Re(r)}),e.registerTool("info",{description:"Report cursor / capacity / closed state of the stdin ring. Cheap; safe to call repeatedly.",inputSchema:{}},async()=>{let t=s.streamInfo();return Re(t)}),e}var Dw=1e4;function dl(s,e){let t=new Map;async function n(i,a){let d=t.get(i);if(d!==void 0)return d.transport;let c=Nw(a),u=new Fw({sessionIdGenerator:()=>$w()});await c.connect(u);let l={server:c,transport:u};return t.set(i,l),e.addDisposer(i,async()=>{t.delete(i);try{await u.close()}catch{}try{await c.close()}catch{}}),u}async function r(i,a){let d=dn(i);if(d===void 0){a.code(401).send({error:"missing bearer token"});return}let c=e.lookup(d);if(c===void 0){a.code(404).send({error:"unknown stdin token"});return}let u;if(c.session!==void 0)u=c.session;else{let p,f=new Promise(k=>{p=setTimeout(()=>k(void 0),Dw)}),h=await Promise.race([c.sessionReady.catch(()=>{}),f]);if(p!==void 0&&clearTimeout(p),h===void 0){a.code(503).send({error:"session not ready"});return}u=h}let l=await n(d,u);a.hijack(),await l.handleRequest(i.raw,a.raw,i.body)}let o={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.get("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.delete("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)})}import{randomUUID as Hw}from"crypto";import{McpServer as jw}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Lw}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as Ye}from"zod";function Uw(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var cl=2e3,ul=2e4;function Bw(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return Gt([s]);let n=[],r=bn(t);r!==void 0?n.push(`Tool: ${r}`):typeof t.title=="string"&&t.title.length>0&&n.push(`Tool: ${t.title}`);let o=t.rawInput;if(o&&typeof o=="object"&&!Array.isArray(o))for(let[a,d]of Object.entries(o))typeof d=="string"&&d.length>0&&n.push(`${a}=${d}`);if(Array.isArray(t.locations))for(let a of t.locations)typeof a?.path=="string"&&a.path.length>0&&n.push(a.path);let i=ws(t);return i!==void 0&&n.push(i),n.join(`
213
- `)}function Ww(s,e){if(s.length<=148)return s;let r=Math.floor(148/2),o=e-r;o<0&&(o=0);let i=o+148;i>s.length&&(o=s.length-148,o<0&&(o=0));let a=s.slice(o,i);return o>0&&(a="\u2026"+a),i<s.length&&(a=a+"\u2026"),a}function qw(s){let e=new jw({name:"hydra-acp-recall",version:"1.0.0"},{instructions:"Search and retrieve detail from this session's pre-compaction history. After a compaction summary replaces earlier conversation in working memory, these tools let you page back specifics on demand. Use `search` to find entries by keyword, `range` to pull a contiguous slice verbatim, and `tool_calls` to enumerate prior tool invocations. These tools only return results once the session has been compacted at least once."});return e.registerTool("search",{description:"Search this session's prior conversation history (the part that was compacted out of your working memory) by keyword. Covers assistant and user messages, the arguments of every tool call including full shell commands, and what those calls printed. Returns matching entry ids with short snippets so you can decide which to pull in full via `range`. Use this when the compaction summary mentions something but you need the verbatim detail.",inputSchema:{query:Ye.string().min(1).describe("Case-insensitive substring to search for."),limit:Ye.number().int().min(1).max(50).optional().describe("Maximum number of matches to return (default 10, max 50)."),include_tool_calls:Ye.boolean().optional().describe("Whether to include tool_call entries in the search (default true).")}},async({query:t,limit:n=10,include_tool_calls:r=!0})=>{let o=await s();if(!o.summarizedThroughEntry||o.summarizedThroughEntry===0)return Re({matches:[],total_matched:0,truncated:!1,note:"This session has no compacted history. `search` retrieves detail from entries that were summarized out of the working conversation; nothing has been summarized yet."});let i=[],a=t.toLowerCase();for await(let{entryId:c,entry:u}of o.iterRecallNewestFirst()){let l=wi(u);if(!l)continue;let{kind:p,update:f}=l;if((p==="tool_call"||p==="tool_call_update")&&!r)continue;let h=Bw(u,p,f),k=h.toLowerCase().indexOf(a);if(k<0)continue;let m=Uw(p),g=Ww(h,k),y=typeof u.recordedAt=="number"?String(u.recordedAt):void 0;if(i.push({entryId:c,speaker:m,snippet:g,timestamp:y}),i.length>=n)break}i.sort((c,u)=>c.entryId-u.entryId);let d=i.length>=n;return Re({matches:i,total_matched:i.length,truncated:d})}),e.registerTool("range",{description:"Pull a contiguous range of prior conversation entries verbatim from this session's pre-compaction history, including each tool call's arguments and what it printed. Use after `search` narrows in on what you need. Capped at 50 entries per call.",inputSchema:{from_entry:Ye.number().int().min(0).describe("Zero-based index of the first entry to include (inclusive)."),to_entry:Ye.number().int().min(0).describe("Zero-based index of the last entry to include (inclusive).")}},async({from_entry:t,to_entry:n})=>{let r=await s();if(!r.summarizedThroughEntry||r.summarizedThroughEntry===0)return Re({text:"",entry_count:0,truncated:!1,note:"This session has no compacted history. `range` retrieves verbatim entries from the pre-compaction transcript; nothing has been compacted yet."});if(n<t)throw new Error(`range: to_entry (${n}) must be >= from_entry (${t})`);let o=n-t+1;if(o>50)throw new Error(`range: range size (${o}) exceeds maximum of 50 entries`);let i=await r.getRecallTotalCount();if(i===0)return Re({text:"",entry_count:0,truncated:!1});let a=Math.min(t,i-1),d=Math.min(n,i-1),c=a>t||d<n;if(a>d)return{content:[{type:"text",text:""}],structuredContent:{text:"",entry_count:0,truncated:c}};let u=await r.sliceRecallHistory(a,d),l=Gt(u,{toolOutput:{maxPerCall:cl,maxTotal:ul}});return{content:[{type:"text",text:l}],structuredContent:{text:l,entry_count:u.length,truncated:c}}}),e.registerTool("tool_calls",{description:"Search this session's prior tool invocations by tool name, ACP kind, and/or file path. Returns when each tool was called, its arguments (including the full shell command), the result status, and what the call printed. Use this to recall which files were read/edited, what shell commands ran, and what they output.",inputSchema:{tool_name:Ye.string().optional().describe("Case-insensitive substring of the tool name. Names vary by agent for the same tool (Bash, Terminal, bash), so prefer `kind` when you want every shell invocation."),kind:Ye.string().optional().describe("ACP tool kind: execute (shell), read, edit, think, other. Agent-independent, unlike tool_name."),file_path:Ye.string().optional(),limit:Ye.number().int().min(1).max(100).optional(),include_output:Ye.boolean().optional().describe("Include what each call printed (default true). Set false when you only need the commands and not their results.")}},async({tool_name:t,kind:n,file_path:r,limit:o=20,include_output:i=!0})=>{let a=await s();if(!a.summarizedThroughEntry||a.summarizedThroughEntry===0)return Re({calls:[],truncated:!1,note:"This session has no compacted history. `tool_calls` retrieves tool invocations from the pre-compaction transcript; nothing has been compacted yet."});let d=typeof t=="string"&&t.length>0,c=typeof n=="string"&&n.length>0,u=typeof r=="string"&&r.length>0;if(!d&&!c&&!u)throw new Error("tool_calls: at least one of tool_name, kind, or file_path must be provided");let l=new Map,p=Math.max(o*4,200);for await(let{entryId:y,entry:w}of a.iterRecallNewestFirst()){let v=wi(w);if(!v)continue;let{kind:S,update:b}=v;if(S!=="tool_call"&&S!=="tool_call_update")continue;let I=typeof b.toolCallId=="string"&&b.toolCallId.length>0?b.toolCallId:`__noid_${y}`,C=l.get(I);if(C||(C={entryId:y,toolName:"(unnamed)",nameAuthoritative:!1,rawInput:{},locations:[],status:"in_progress"},l.set(I,C)),y<C.entryId&&(C.entryId=y),!C.nameAuthoritative){let E=bn(b);E!==void 0?(C.toolName=E,C.nameAuthoritative=!0):typeof b.name=="string"&&b.name.length>0?(C.toolName=b.name,C.nameAuthoritative=!0):S==="tool_call"&&typeof b.title=="string"&&b.title.length>0&&(C.toolName=b.title,C.nameAuthoritative=!0)}if(C.kind===void 0&&typeof b.kind=="string"&&b.kind.length>0&&(C.kind=b.kind),C.output===void 0){let E=ws(b);E!==void 0&&(C.output=E)}let R=b.rawInput;if(R&&typeof R=="object"&&!Array.isArray(R)&&Object.keys(R).length>0)for(let[E,M]of Object.entries(R))C.rawInput[E]===void 0&&(C.rawInput[E]=M);if(Array.isArray(b.locations))for(let E of b.locations){let M=E?.path;typeof M=="string"&&M.length>0&&!C.locations.includes(M)&&C.locations.push(M)}if(typeof b.status=="string"&&C.status==="in_progress"&&(C.status=b.status),w.recordedAt!==void 0&&C.timestamp===void 0&&(C.timestamp=String(w.recordedAt)),l.size>=p)break}let f=[...l.keys()].sort((y,w)=>l.get(y).entryId-l.get(w).entryId),h=[],k=ul,m=!1;for(let y of f){let w=l.get(y);if(w.toolName=ao({name:w.toolName,rawInput:w.rawInput,...w.kind!==void 0?{kind:w.kind}:{}}),d&&!w.toolName.toLowerCase().includes(t.toLowerCase())||c&&(w.kind??"").toLowerCase()!==n.toLowerCase())continue;if(u){let b=r.toLowerCase(),I=["file_path","filePath","path"],C=!1;for(let R of I){let E=w.rawInput[R];if(typeof E=="string"&&E.toLowerCase().includes(b)){C=!0;break}}if(!C){for(let R of w.locations)if(R.toLowerCase().includes(b)){C=!0;break}}if(!C)continue}let v={};for(let[b,I]of Object.entries(w.rawInput))typeof I=="string"?v[b]=I.length>500?I.slice(0,497)+"\u2026":I:(typeof I=="number"||typeof I=="boolean")&&(v[b]=I);w.locations.length>0&&v.locations===void 0&&(v.locations=w.locations);let S={entryId:w.entryId,tool:w.toolName,args:v,status:w.status,timestamp:w.timestamp};if(w.kind!==void 0&&(S.kind=w.kind),i&&w.output!==void 0){let b=w.output,I=Math.min(cl,k);if(I<=0)m=!0;else{let C=b.length<=I?b:b.slice(0,I-1)+"\u2026";S.output=C,S.outputBytes=b.length,S.outputTruncated=C.length<b.length,k-=C.length}}if(h.push(S),h.length>=o)break}let g=h.length>=o;return Re({calls:h,truncated:g,...m?{outputBudgetExhausted:m}:{}})}),e}var zw=1e4;function ll(s,e){let t=new Map;async function n(i,a){let d=t.get(i);if(d!==void 0)return d.transport;let c=qw(a),u=new Lw({sessionIdGenerator:()=>Hw()});await c.connect(u);let l={server:c,transport:u};return t.set(i,l),e.addDisposer(i,async()=>{t.delete(i);try{await u.close()}catch{}try{await c.close()}catch{}}),u}async function r(i,a){let d=dn(i);if(d===void 0){a.code(401).send({error:"missing bearer token"});return}let c=e.lookup(d);if(c===void 0){a.code(404).send({error:"unknown recall token"});return}let l=await n(d,async()=>{if(c.session!==void 0)return c.session;let p,f=new Promise(k=>{p=setTimeout(()=>k(void 0),zw)}),h=await Promise.race([c.sessionReady.catch(()=>{}),f]);if(p!==void 0&&clearTimeout(p),h===void 0)throw new Error("recall: session not ready");return h});a.hijack(),await l.handleRequest(i.raw,a.raw,i.body)}let o={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)}),s.get("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)}),s.delete("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)})}var br=class{byName=new Map;changeHandlers=[];register(e,t,n,r){this.byName.set(e,{connection:t,instructions:n,tools:[...r]}),this.fireChanged(e,"register")}clear(e){this.byName.delete(e)&&this.fireChanged(e,"clear")}lookup(e){return this.byName.get(e)}list(){return Array.from(this.byName.keys())}onChange(e){return this.changeHandlers.push(e),()=>{let t=this.changeHandlers.indexOf(e);t>=0&&this.changeHandlers.splice(t,1)}}fireChanged(e,t){for(let n of this.changeHandlers)try{n(e,t)}catch{}}};import{StreamableHTTPServerTransport as Zw}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{isInitializeRequest as ek}from"@modelcontextprotocol/sdk/types.js";import{randomUUID as tk}from"crypto";import{Server as Jw}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Vw,ListToolsRequestSchema as Gw}from"@modelcontextprotocol/sdk/types.js";function fl(s,e,t,n){let r=typeof t=="function"?async()=>t():async()=>t,o=new Jw({name:s,version:"1.0.0"},{capabilities:{tools:{listChanged:!0}},...e.instructions!==void 0?{instructions:e.instructions}:{}}),i=a=>({name:a.name,description:a.description,inputSchema:a.inputSchema,...a.outputSchema!==void 0?{outputSchema:a.outputSchema}:{}});return o.setRequestHandler(Gw,async()=>{let a=n?.peekSessionId?.();if(a!==void 0&&n?.fetchSessionTools!==void 0)try{let d=await n.fetchSessionTools(a);if(d!==void 0)return{tools:d.map(i)}}catch{}return{tools:e.tools.map(i)}}),o.setRequestHandler(Vw,async(a,d)=>{let c=a.params.name,u=d._meta?.progressToken??d.requestId,l=Qw(u,d.sendNotification);try{let p=await r(),f=await Yw(e.connection,s,c,a.params.arguments??{},p);return Xw(f,c)}catch(p){return ki(p instanceof Error?p.message:String(p))}finally{l()}}),o}var Kw=15e3;function Qw(s,e,t=Kw){if(s===void 0)return()=>{};let n=0,r=setInterval(()=>{n+=1,e({method:"notifications/progress",params:{progressToken:s,progress:n}}).catch(()=>{})},t);return r.unref?.(),()=>clearInterval(r)}async function Yw(s,e,t,n,r){return await s.request("hydra-acp/mcp_tools/invoke",{server:e,tool:t,args:n,sessionId:r})}function Xw(s,e){if(s===null||typeof s!="object")return ki(`extension ${e} returned non-object`);let t=s;return Array.isArray(t.content)?t:ki(`extension ${e} omitted content array`)}function ki(s){return{content:[{type:"text",text:s}],isError:!0}}var nk=1e4;function pl(s,e,t){let n=new Map;async function r(u){try{await u.transport.close()}catch{}try{await u.server.close()}catch{}}function o(u){for(let l of n.values()){let p=l.get(u);p!==void 0&&(l.delete(u),r(p))}}async function i(u,l){for(let[p,f]of n){if(e.lookup(p)?.session?.sessionId!==u)continue;let k=f.get(l);if(k!==void 0)try{await k.server.sendToolListChanged()}catch{}}}t.onChange(u=>{o(u)});async function a(u,l){let p=n.get(u);p===void 0&&(p=new Map,n.set(u,p),e.addDisposer(u,async()=>{let v=n.get(u);if(v!==void 0){n.delete(u);for(let S of v.values())await r(S)}}));let f=p.get(l);if(f!==void 0)return f.transport;let h=t.lookup(l);if(h===void 0)return;let y=fl(l,h,async()=>{let v=e.lookup(u);if(v===void 0)throw new Error("mcp token no longer bound");if(v.session!==void 0)return v.session.sessionId;let S,b=new Promise(C=>{S=setTimeout(()=>C(void 0),nk)}),I=await Promise.race([v.sessionReady.catch(()=>{}),b]);if(S!==void 0&&clearTimeout(S),I===void 0)throw new Error("session not ready");return I.sessionId},{peekSessionId:()=>e.lookup(u)?.session?.sessionId,fetchSessionTools:async v=>{let S=await h.connection.request("hydra-acp/mcp_tools/list_tools",{sessionId:v});if(!S||typeof S!="object")return;let b=S.tools;if(!Array.isArray(b))return;let I=[];for(let C of b){if(!C||typeof C!="object")continue;let R=C;if(typeof R.name!="string"||R.name.length===0||typeof R.description!="string"||R.inputSchema===null||typeof R.inputSchema!="object")continue;let E={name:R.name,description:R.description,inputSchema:R.inputSchema};R.outputSchema!==null&&typeof R.outputSchema=="object"&&(E.outputSchema=R.outputSchema),I.push(E)}return I}}),w=new Zw({sessionIdGenerator:()=>tk()});return await y.connect(w),p.set(l,{server:y,transport:w}),w}async function d(u,l){let p=dn(u);if(p===void 0){l.code(401).send({error:"missing bearer token"});return}if(e.lookup(p)===void 0){l.code(404).send({error:"unknown mcp token"});return}let h=u.params.name;if(u.method==="POST"&&u.headers["mcp-session-id"]===void 0&&ek(u.body)){let m=n.get(p),g=m?.get(h);g?.transport.sessionId!==void 0&&(m?.delete(h),r(g))}let k=await a(p,h);if(k===void 0){l.code(404).send({error:`unknown mcp server: ${h}`});return}l.hijack(),await k.handleRequest(u.raw,l.raw,u.body)}let c={config:{skipAuth:!0}};return s.post("/mcp/:name",c,async(u,l)=>{await d(u,l)}),s.get("/mcp/:name",c,async(u,l)=>{await d(u,l)}),s.delete("/mcp/:name",c,async(u,l)=>{await d(u,l)}),{notifyToolListChanged:i}}async function kl(s,e){ck(s),Or(s.daemon.scrubEnv);let t=s,n=s.daemon.tls?await Xe.readFile(ce(s.daemon.tls.key)):void 0,r=s.daemon.tls?await Xe.readFile(ce(s.daemon.tls.cert)):void 0;await Xe.mkdir(T.home(),{recursive:!0});let{stream:o,fileStream:i,closeFile:a}=await ak(s.daemon.logLevel),d=sk({logger:{level:s.daemon.logLevel,stream:o},bodyLimit:256*1024*1024});await d.register(rk,{options:{handleProtocols:Li}}),Lr(F=>{d.log.info(F)}),Wr(F=>{d.log.info(F)});let c=await Qs.load(),u=await dr.load();pi(),li(u);let l=new mr(u);l.start();let p=new or(u);p.start();let f=new tr,h=new er,k=new Ys(e),m=new Zs([k,new Xs(c),h]),g=Qc({validator:m});d.addHook("onRequest",async(F,Ce)=>{F.routeOptions.config?.skipAuth||F.url==="/acp"||F.url?.startsWith("/acp?")||(await g(F,Ce),!Ce.sent&&F.authIdentity?.startsWith("script:")&&!Xc(F.method,F.routeOptions.url)&&Ce.code(403).send({error:"script tokens may only access read-only session data"}))});let y=setInterval(()=>{c.sweepExpired()},300*1e3);y.unref();let w=setInterval(()=>{f.sweepExpired()},300*1e3);w.unref();let v=new rs(s,{onFetched:()=>{Nc(v,C)},onStaleFallback:(F,Ce)=>{let un=Math.round(Ce/36e5),ln=un>=48?`${Math.round(un/24)}d`:`${un}h`;d.log.warn(`registry fetch failed (${F.message}); serving stale cache last synced ${ln} ago; agent versions may be outdated ('hydra registry refresh' to retry)`)}});ei(F=>d.log.info(F));let S={info:F=>d.log.info(F),warn:F=>d.log.warn(F)},b=F=>ct.spawn({...F,stderrTailBytes:s.daemon.agentStderrTailBytes,logger:S});Ji(s.compressToolContent);let I=new Gs,C=new Ls(v,b,void 0,{idleTimeoutMs:s.daemon.sessionIdleTimeoutSeconds*1e3,orphanTimeoutMs:s.daemon.nonInteractiveOrphanTimeoutSeconds*1e3,sessionDefaults:s.sessionDefaults,synopsisAgent:s.synopsisAgent,synopsisModel:s.synopsisModel,compactionAgent:s.compaction?.agent,compactionModel:s.compaction?.model,defaultTransformers:s.defaultTransformers,sessionHistoryMaxEntries:s.daemon.sessionHistoryMaxEntries,sessionHistoryArchiveMaxBytes:s.daemon.sessionHistoryArchiveMaxBytes,sessionHistoryArchiveTiers:s.daemon.sessionHistoryArchiveTiers,logger:S,npmRegistry:s.npmRegistry,extensionCommands:I,defaultCwd:s.defaultCwd,disableWorkspaceSnapshots:s.disableWorkspaceSnapshots}),R=new gr(u,void 0,{resolvesLocally:async F=>await C.resolveCanonicalId(F)!==void 0,cache:p}),E=new Js(Fi(s),void 0,{tokenRegistry:h}),M=new Vs(Ni(s),void 0,{tokenRegistry:h}),N=[];Su(d,ue,jc(s),()=>N);let B=new Date().toISOString();Tu(d,B);let q=new vr,V=new br,L,W=()=>{if(L!==void 0)return L;let F=d.server.address();return L=`http://127.0.0.1:${F&&typeof F=="object"?F.port:s.daemon.port}`,L},Q={agentId:s.defaultAgent,cwd:s.defaultCwd,publicHost:s.daemon.publicHost,host:s.daemon.host,port:s.daemon.port,compaction:s.compaction};vu(d,C,Q,{extensionMcp:V,mcpTokenRegistry:q,getDaemonOrigin:W},u,p),mu(d,{store:u,localMiss:{resolvesLocally:async F=>await C.resolveCanonicalId(F)!==void 0,cache:p}}),bu(d,v,C,{npmRegistry:s.npmRegistry}),Pu(d,E),Mu(d,M);let oe={host:s.daemon.host,port:s.daemon.port,...s.daemon.publicHost!==void 0?{publicHost:s.daemon.publicHost}:{},...s.daemon.tls?{tls:{cert:ce(s.daemon.tls.cert),key:ce(s.daemon.tls.key)}}:{}};_u(d,()=>({defaultAgent:t.defaultAgent,defaultCwd:t.defaultCwd,sessionDefaults:{...t.sessionDefaults},...t.synopsisAgent!==void 0?{synopsisAgent:t.synopsisAgent}:{},...t.synopsisModel!==void 0?{synopsisModel:t.synopsisModel}:{},defaultTransformers:[...t.defaultTransformers],listen:oe})),Du(d,{store:c,rateLimiter:f,staticTokenValidator:k}),Ju(d,{store:u,health:l}),Yu(d,{processRegistry:h}),dl(d,q),ll(d,q);let xe=pl(d,q,V);ol(d,{validator:m,manager:C,defaultAgent:s.defaultAgent,processRegistry:h,onExtensionVersion:(F,Ce)=>E.reportVersion(F,Ce),onTransformerVersion:(F,Ce)=>M.reportVersion(F,Ce),transformers:M,extensionCommands:I,mcpTokenRegistry:q,extensionMcp:V,extensionMcpControls:xe,getDaemonOrigin:W,registry:v,foreignSessions:R});let Ze=!!s.daemon.tls;await d.listen({host:Ze?"127.0.0.1":s.daemon.host,port:Ze?0:s.daemon.port});let te=d.server.address(),Pe=te&&typeof te=="object"?te.port:s.daemon.port,Xn,vl=s.daemon.host,vi=Pe;if(Ze&&n&&r){Xn=await dk({listenHost:s.daemon.host,listenPort:s.daemon.port,upstreamHost:"127.0.0.1",upstreamPort:Pe,tlsOptions:{key:n,cert:r},logger:d.log});let F=Xn.address();F&&typeof F=="object"&&(vi=F.port)}await Xe.mkdir(T.home(),{recursive:!0}),await Fc({pid:process.pid,host:vl,port:vi,loopbackPort:Pe,startedAt:B});let bi={daemonUrl:`http://127.0.0.1:${Pe}`,daemonHost:"127.0.0.1",daemonPort:Pe,serviceToken:e,daemonWsUrl:`ws://127.0.0.1:${Pe}/acp`,hydraHome:T.home()};E.setContext(bi),M.setContext(bi),await E.start(),await M.start();try{await C.reconcilePermissionFlags()}catch(F){d.log.warn(`permission flag reconcile failed: ${F.message}`)}try{await C.seedSessionIndex()}catch(F){d.log.warn(`session index seed failed: ${F.message}`)}C.resurrectPendingQueues().catch(F=>{d.log.warn(`queue replay scan failed: ${F.message}`)}),C.resumePendingCompactions().catch(F=>{d.log.warn(`compaction resume scan failed: ${F.message}`)}),C.resumePendingAgentSwaps().catch(F=>{d.log.warn(`agent-swap resume scan failed: ${F.message}`)});let Si=s.daemon.agentSyncIntervalMinutes*60*1e3,Ii=Si>0?Dc({registry:v,manager:C,intervalMs:Si,logger:S}):void 0,Ai=s.daemon.sessionGcIntervalMinutes*60*1e3,bl=s.daemon.sessionGcMaxAgeDays*24*60*60*1e3,Ci=Ai>0?Hc({manager:C,intervalMs:Ai,maxAgeMs:bl,logger:S}):void 0,Sl=Wc({bootConfig:s,apply:F=>{t=F,v.setConfig(F),C.setLiveConfig({sessionDefaults:F.sessionDefaults}),Q.agentId=F.defaultAgent,Q.cwd=F.defaultCwd,Or(F.daemon.scrubEnv)},onDrift:F=>{N=F},logger:S});return{app:d,manager:C,registry:v,extensions:E,transformers:M,mcpTokenRegistry:q,extensionMcp:V,processRegistry:h,shutdown:async()=>{l.stop(),p.stop(),Sl(),Ci&&Ci(),Ii&&Ii(),clearInterval(y),clearInterval(w);let F=async(Ce,un)=>{try{await un()}catch(ln){d.log.warn(`shutdown step ${Ce} failed: ${ln instanceof Error?ln.message:String(ln)}`)}};await F("sessionTokenStore.flush",()=>c.flush()),await F("extensions.stop",()=>E.stop()),await F("transformers.stop",()=>M.stop()),await F("manager.closeAll",()=>C.closeAll()),await F("manager.flushSynopsis",()=>C.flushSynopsis(3e4)),await F("manager.shutdownSynopsis",()=>C.shutdownSynopsis()),await F("manager.flushMetaWrites",()=>C.flushMetaWrites()),await F("manager.flushHistoryWrites",()=>C.flushHistoryWrites()),Lr(null),Wr(null),ei(null),Xn&&await F("tlsTerminator.close",()=>new Promise(Ce=>Xn.close(()=>Ce()))),await F("app.close",()=>d.close());try{hl.unlinkSync(T.pidFile())}catch{}await F("fileStream.flushSync",()=>i.flushSync()),await F("fileStream.close",a)}}}var ml=20;async function ik(s,e){let t=cn.dirname(s),n=cn.basename(s,".log"),r=new RegExp(`^${n}\\.(\\d+)\\.log$`),o;try{o=await Xe.readdir(t)}catch{return}let i=[];for(let d of o){let c=d.match(r);c&&i.push({name:d,n:Number(c[1])})}if(i.length<=e)return;i.sort((d,c)=>d.n-c.n);let a=i.slice(0,i.length-e);await Promise.allSettled(a.map(d=>Xe.unlink(cn.join(t,d.name))))}async function ak(s){await ik(T.logFile(),ml);let e=await ok({file:T.logFile(),size:"10m",mkdir:!0,symlink:Ws,limit:{count:ml,removeOtherLogFiles:!0}}),t=gl.destination(2),n=!1,r={write:a=>{n||e.write(a)}};return{stream:gl.multistream([{stream:r,level:s},{stream:t,level:s}]),fileStream:e,closeFile:()=>new Promise(a=>{n=!0,e.once("close",()=>a()),e.end()})}}async function dk(s){let e=wl.createServer(s.tlsOptions,t=>{let n=yl.connect({host:s.upstreamHost,port:s.upstreamPort}),r=!1,o=i=>{if(!r){r=!0,i&&s.logger.warn(`tls terminator forwarder error: ${i.message??String(i)}`);try{t.destroy()}catch{}try{n.destroy()}catch{}}};t.on("error",o),n.on("error",o),t.on("close",()=>o()),n.on("close",()=>o()),t.pipe(n),n.pipe(t)});return e.on("tlsClientError",t=>{s.logger.warn(`tls handshake error: ${t.message}`)}),await new Promise((t,n)=>{let r=o=>{n(new Error(`TLS listener could not bind ${s.listenHost}:${s.listenPort}: ${o.message}`))};e.once("error",r),e.listen({host:s.listenHost,port:s.listenPort},()=>{e.off("error",r),t()})}),e.on("error",t=>{s.logger.warn(`tls terminator error: ${t.message}`)}),e}function ck(s){let e=s.daemon.host;if(!(e==="127.0.0.1"||e==="::1"||e==="localhost"||e==="[::1]")&&!s.daemon.tls)throw new Error(`Refusing to bind to non-loopback host ${e} without TLS configured.`)}async function uk(){process.title="hydra-acp-daemon";let{installGlobalTlsTrust:s}=await Promise.resolve().then(()=>(Kn(),zu));s();let e=await gn(),t=await Ei(),n=await kl(e,t);process.stdout.write(`hydra-acp daemon listening on ${e.daemon.host}:${e.daemon.port}
204
+ `),a}function oi(s,e){let t=s<0?e+s+1:s;return t<1?1:t>e?e:t}function ay(s,e){if(!(e.from!==void 0||e.to!==void 0||e.last!==void 0)&&e.sinceMs===void 0)return{events:s};let n=[],r=0;for(let{event:f}of s)f.kind==="user-text"&&(r+=1),n.push(r===0?1:r);let o=Math.max(r,1),i=1,a=o;if(e.last!==void 0&&e.last>0?i=oi(o-e.last+1,o):(e.from!==void 0&&(i=oi(e.from,o)),e.to!==void 0&&(a=oi(e.to,o))),i>a)return{events:[],window:{from:i,to:a,total:o}};let d=e.sinceMs,c=new Set;d!==void 0&&s.forEach((f,h)=>{f.recordedAt>=d&&c.add(n[h])});let u=[],l,p;return s.forEach((f,h)=>{let k=n[h];k<i||k>a||d!==void 0&&!c.has(k)||(u.push(f),l??=k,p=k)}),{events:u,window:{from:l??i,to:p??a,total:o}}}function dy(s){let e=[];for(let t of s.history){if(t.method!=="session/update")continue;let n=t.params;if(!n||typeof n!="object")continue;let r=Qa(n.update,{cwd:s.session.cwd});r!==null&&e.push({event:r,recordedAt:t.recordedAt})}return e}function cy(s){let e=new Map;for(let{event:t}of s){if(t.kind==="tool-call"){let n=e.get(t.toolCallId);e.set(t.toolCallId,{title:t.title,status:t.status??n?.status??"pending"});continue}if(t.kind==="tool-call-update"){let n=e.get(t.toolCallId)??{title:"tool call",status:"pending"};e.set(t.toolCallId,{title:t.title??n.title,status:t.status??n.status})}}return e}function uy(s,e){let t=e.session,n=nt(t.sessionId),r=t.title?.trim()||`Hydra session ${n}`;s.push(`# ${Vn(r)}`),s.push("");let o=[];o.push(`- **Session:** \`${n}\` (lineage \`${t.lineageId}\`)`);let i=[t.agentId];t.currentModel&&i.push(`model: ${t.currentModel}`),t.currentMode&&i.push(`mode: ${t.currentMode}`),o.push(`- **Agent:** ${i.filter(Boolean).join(" \xB7 ")}`),o.push(`- **Cwd:** ${t.cwd}`),o.push(`- **Exported:** ${e.exportedAt} from ${e.exportedFrom.machine} (hydra ${e.exportedFrom.hydraVersion})`);let a=t.currentUsage;if(a&&(a.used!==void 0||a.costAmount!==void 0||a.cumulativeCost!==void 0)){let d=[];if(a.used!==void 0){let u=a.size!==void 0?`${ii(a.size)}`:void 0;d.push(u?`${ii(a.used)} / ${u} tokens`:`${ii(a.used)} tokens`)}let c=Jo(a);if(c!==void 0){let u=a.costCurrency??"USD";d.push(`$${c.toFixed(2)} ${u}`)}o.push(`- **Usage:** ${d.join(" \xB7 ")}`)}s.push(o.join(`
205
+ `)),s.push("")}function ly(s,e,t,n){let{includeTools:r,includeThoughts:o}=n;if(!e.some(k=>fy(k.event,o))){s.push("_No conversation history recorded._"),s.push("");return}let i=0,a="",d="",c=[],u=new Set,l=!1,p=()=>{if(c.length!==0){for(let k of c)s.push(k);s.push(""),c=[]}},f=()=>{p(),d.length>0&&(ou(s,d.trimEnd(),"*"),s.push(""),d=""),a.length!==0&&(s.push(a.trimEnd()),s.push(""),a="")},h=()=>{l||(l=!0)};for(let{event:k}of e)switch(k.kind){case"user-text":{f(),s.push("---"),s.push(""),i+=1,ou(s,k.text,"**"),s.push(""),l=!0;break}case"agent-text":h(),a+=k.text;break;case"agent-thought":{if(!o)break;h(),a.length>0&&(s.push(a.trimEnd()),s.push(""),a=""),d+=k.text;break}case"tool-call":{if(!r||(h(),(a.length>0||d.length>0)&&f(),u.has(k.toolCallId)))break;u.add(k.toolCallId);let m=t.get(k.toolCallId)??{title:k.title,status:k.status??"pending"};c.push(`- ${gy(m.status)} ${py(m)}`);break}case"tool-call-update":break;case"plan":{h(),f(),s.push("**Plan:**"),s.push("");for(let m of k.entries){let g=m.status==="completed"?"[x]":"[ ]";s.push(`- ${g} ${Vn(m.content)}`)}s.push("");break}case"mode-changed":h(),f(),s.push(`_mode: ${Vn(k.mode)}_`),s.push("");break;case"model-changed":h(),f(),s.push(`_model: ${Vn(k.model)}_`),s.push("");break;case"turn-complete":f();break;case"usage-update":case"available-commands":case"session-info":case"unknown":break}f()}function fy(s,e){switch(s.kind){case"agent-thought":return e;case"usage-update":case"available-commands":case"session-info":case"unknown":case"turn-complete":return!1;default:return!0}}function py(s){let e=s.status,t=e==="completed"||e===void 0?"":` _(${e})_`;return`${Vn(s.title)}${t}`}function gy(s){switch(s){case"completed":return"\u2713";case"failed":return"\u2717";case"cancelled":case"rejected":return"\u2298";case"in_progress":return"\u21BB";default:return"\xB7"}}var au=String.raw`<\/?[a-zA-Z][a-zA-Z0-9-]*(?:\s[^<>]*)?\/?>`,my=new RegExp(au);function ou(s,e,t){if(my.test(e)){hy(s,e);return}let n=e.split(/\n\s*\n/);for(let r=0;r<n.length;r++){let o=n[r];if(o.trim().length===0)continue;let i=o.split(`
206
+ `);for(let a=0;a<i.length;a++){let d=i[a];s.push(a===0&&a===i.length-1?`${t}${d}${t}`:a===0?`${t}${d}`:a===i.length-1?`${d}${t}`:d)}r<n.length-1&&s.push("")}}function hy(s,e){let t=e.replace(/\s+$/,"");if(t.length===0)return;let n=0;for(let o of t.match(/`+/g)??[])n=Math.max(n,o.length);let r="`".repeat(Math.max(3,n+1));s.push(r);for(let o of t.split(`
207
+ `))s.push(o);s.push(r)}function Vn(s){return s.replace(new RegExp(au,"g"),e=>e.replace(/</g,"&lt;").replace(/>/g,"&gt;"))}function ii(s){return s.toLocaleString("en-US")}function Ae(s){return s==="127.0.0.1"||s==="::1"||s==="localhost"||s==="[::1]"}function yy(s){let e=s.trim();if(e.length===0)return{operator:"OR",terms:[]};let t=/\w+:"[^"]*"|"[^"]*"|\S+/g,n=[],r;for(;(r=t.exec(e))!==null;)n.push(r[0]);let o="OR",i=!1,a=!1,d=[];for(let u of n){let l=u.toUpperCase();l==="AND"?i=!0:l==="OR"?a=!0:d.push(u)}i?o="AND":a&&(o="OR");let c=d.map(u=>wy(u)).filter(u=>u.term.length>0);return{operator:o,terms:c}}function wy(s){let e=/^(\w+):"([^"]*)"$/.exec(s);if(e)return{scope:du(e[1]),term:e[2]};let t=/^"([^"]*)"$/.exec(s);if(t)return{scope:"all",term:t[1]};let n=/^(prompt|response|tool|edit|edited):([\s\S]*)$/i.exec(s);return n?{scope:du(n[1]),term:n[2].trim()}:{scope:"all",term:s.trim()}}function du(s){switch(s.toLowerCase()){case"prompt":return"user";case"response":return"agent";case"tool":return"tool";case"edit":case"edited":return"edit";default:return"all"}}function ky(s,e){return e==="edit"?s==="edit":s==="edit"?!1:s==="all"?!0:s==="user"?e==="user":s==="agent"?e==="agent"||e==="thought":e==="tool"||e==="tool-input"}var vy=5,by=200,ir=72,Sy=24,Iy=512;function pu(s){return Number.isFinite(s)?Math.max(Sy,Math.min(Iy,Math.floor(s))):ir}async function gu(s,e,t={}){let n=yy(e);if(n.terms.length===0)return{query:e,truncated:!1,results:[]};let r=t.maxSnippetsPerSession??vy,o=t.maxSessions??by,i=pu(t.snippetWidth??ir),a=t.sessionIds?new Set(t.sessionIds):null,d=await s.list(),c=a?d.filter(p=>a.has(p.sessionId)):d,u=[],l=!1;for(let p of c){if(u.length>=o){l=!0;break}let f=await s.loadHistory(p.sessionId,{tools:"references"}).catch(()=>[]),h=Cy(f,n,r,i,Ay(p));if(h.snippets.length===0)continue;let k={sessionId:p.sessionId,cwd:p.cwd,status:p.status,updatedAt:p.updatedAt,totalMatches:h.totalMatches,snippets:h.snippets};p.title!==void 0&&(k.title=p.title),u.push(k)}return{query:e,truncated:l,results:u}}function Ay(s){let e=s.workspace?.sourceCwd;if(e===void 0||e.length===0||s.cwd.length===0)return;let t=s.cwd.endsWith("/")?s.cwd:s.cwd+"/";return n=>n.startsWith(t)?e.replace(/\/+$/,"")+"/"+n.slice(t.length):n}function Cy(s,e,t,n=ir,r){if(e.terms.length===0)return{totalMatches:0,snippets:[]};let o=0,i=[],a=Math.max(1,Math.floor(t/e.terms.length)),d=[];for(let{scope:c,term:u}of e.terms){let l=Ry(s,u,c,t,n,r);if(e.operator==="AND"&&l.totalMatches===0)return{totalMatches:0,snippets:[]};o+=l.totalMatches,i.push(...l.snippets.slice(0,a)),d.push(...l.snippets.slice(a))}for(let c of d){if(i.length>=t)break;i.push(c)}return{totalMatches:o,snippets:i.slice(0,t)}}function Ry(s,e,t,n,r,o){let i=e.toLowerCase(),a=0,d=[],c=new Set;for(let u of s){let l=xy(u).filter(p=>ky(t,p.kind));for(let p of l){let f=p.text.toLowerCase();if(p.kind==="edit"){let m=o?.(p.text);if(!(cu(p.text,e)||(m!==void 0&&m!==p.text?cu(m,e):!1))||c.has(p.text))continue;if(c.add(p.text),a+=1,d.length<n){let y={kind:"edit",text:p.text,recordedAt:u.recordedAt};p.toolName!==void 0&&(y.toolName=p.toolName),d.push(y)}continue}let h=f.indexOf(i);if(h===-1)continue;let k=0;for(;h!==-1;)k++,h=f.indexOf(i,h+i.length);if(a+=k,d.length<n){let m=f.indexOf(i),g={kind:p.kind,text:$y(p.text,m,i.length,r),recordedAt:u.recordedAt};p.toolName!==void 0&&(g.toolName=p.toolName),d.push(g)}}}return{totalMatches:a,snippets:d}}function xy(s){if(s.method!=="session/update")return[];let e=s.params;if(!e||typeof e!="object"||Array.isArray(e))return[];let t=e.update;if(!t||typeof t!="object"||Array.isArray(t))return[];let n=t,r=typeof n.sessionUpdate=="string"?n.sessionUpdate:n.kind;if(typeof r!="string")return[];switch(r){case"agent_message_chunk":{let o=or(n.content);return o?[{kind:"agent",text:o}]:[]}case"agent_thought":case"agent_thought_chunk":{let o=typeof n.text=="string"?be(n.text):or(n.content);return o?[{kind:"thought",text:o}]:[]}case"user_message_chunk":{if(My(n))return[];let o=or(n.content);return o?[{kind:"user",text:o}]:[]}case"prompt_received":{let o=_y(n.prompt);return o?[{kind:"user",text:o}]:[]}case"tool_call":case"tool_call_update":return Ty(n);default:return[]}}function Ty(s){let e=lu(s,"name"),t=lu(s,"title"),n=[];if(t!==void 0){let a=ie(t);if(a.length>0){let d={kind:"tool",text:a};e!==void 0&&(d.toolName=e),n.push(d)}}if(e!==void 0&&e!==t){let a=ie(e);a.length>0&&n.push({kind:"tool",toolName:e,text:a})}let r=s.rawInput;if(r&&typeof r=="object"){let a=fu(r);if(a.length>0){let d={kind:"tool-input",text:ie(a)};e!==void 0&&(d.toolName=e),n.push(d)}}for(let a of za(s)){let d={kind:"edit",text:a};e!==void 0&&(d.toolName=e),n.push(d)}let o=s.locations;if(Array.isArray(o)&&o.length>0){let a=fu(o);if(a.length>0){let d={kind:"tool-input",text:ie(a)};e!==void 0&&(d.toolName=e),n.push(d)}}let i=Ey(s);if(i!==null){let a={kind:"tool",text:i};e!==void 0&&(a.toolName=e),n.push(a)}return n}function cu(s,e){let t=uu(s.toLowerCase()),n=uu(e.toLowerCase());if(n.length===0)return!1;if(n.startsWith("/"))return t===n||t.startsWith(n+"/");let r="/"+n,o=t.indexOf(r);for(;o!==-1;){let i=o+r.length;if(i===t.length||t[i]==="/")return!0;o=t.indexOf(r,o+1)}return t===n||t.startsWith(n+"/")}function uu(s){return s.length>1&&s.endsWith("/")?s.slice(0,-1):s}function Ey(s){if(!Py(s.status))return null;let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let o=n.content;if(!o||typeof o!="object")continue;let i=o;if(i.type==="text"&&typeof i.text=="string"){let a=ie(i.text);if(a.length>0)return a}}let t=s.rawOutput;if(t&&typeof t=="object"){let n=t.error;if(typeof n=="string"){let r=ie(n);if(r.length>0)return r}}return null}function Py(s){return s==="failed"||s==="rejected"||s==="cancelled"}function My(s){let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return!1;let t=e["hydra-acp"];return!t||typeof t!="object"||Array.isArray(t)?!1:t.compatFor==="prompt_received"}function or(s){if(typeof s=="string")return be(s);if(!s||typeof s!="object"||Array.isArray(s))return"";let e=s;return typeof e.text=="string"?be(e.text):""}function _y(s){if(!Array.isArray(s))return"";let e=[];for(let t of s){let n=or(t);n.length>0&&e.push(n)}return e.join("")}function lu(s,e){let t=s[e];return typeof t=="string"?t:void 0}function fu(s){try{return JSON.stringify(s)}catch{return""}}function $y(s,e,t,n=ir){let r=s.replace(/\s+/g," ").trim();if(r.length===0)return"";let o=r.toLowerCase(),i=s.slice(e,e+t).toLowerCase().replace(/\s+/g," ").trim(),a=i.length>0?o.indexOf(i):0;a===-1&&(a=0);let d=pu(n),c=Math.max(0,d-i.length),u=Math.floor(c/2),l=Math.min(u,a),p=Math.min(c-l,r.length-(a+i.length)),f=Math.max(0,a-(c-p)),h=Math.min(r.length,a+i.length+p),k=f>0?"\u2026":"",m=h<r.length?"\u2026":"";return`${k}${r.slice(f,h)}${m}`}import{randomBytes as hu}from"crypto";function mu(s){let e=hu(32).toString("hex");return s.tokenRegistry.reserve(e).complete(s.session),s.session.onClose(()=>{s.tokenRegistry.unbind(e)}),{name:s.name,type:"http",url:`${s.getOrigin()}/mcp/${s.name}`,headers:[{name:"Authorization",value:`Bearer ${e}`}]}}function ai(s){if(s.deps.mcpTokenRegistry===void 0||s.deps.getDaemonOrigin===void 0)return;let e=s.deps.mcpTokenRegistry,t=s.deps.getDaemonOrigin;return async n=>{let r=[...s.baselineMcpServers??[]];s.stdinEnabled&&r.push(mu({name:"hydra-acp-stdin",session:n,tokenRegistry:e,getOrigin:t})),r.push(mu({name:"hydra-acp-recall",session:n,tokenRegistry:e,getOrigin:t}));let o=on(s.deps);return o!==void 0&&(o.bindToSession(n),r=[...r,...o.descriptors]),r}}function on(s){if(s.extensionMcp===void 0||s.mcpTokenRegistry===void 0||s.getDaemonOrigin===void 0)return;let e=s.extensionMcp.list();if(e.length===0)return;let t=hu(32).toString("hex"),n=s.mcpTokenRegistry.reserve(t),r=s.getDaemonOrigin(),o=e.map(a=>({name:a,type:"http",url:`${r}/mcp/${a}`,headers:[{name:"Authorization",value:`Bearer ${t}`}]})),i=s.mcpTokenRegistry;return{descriptors:o,bindToSession:a=>{n.complete(a),a.onClose(()=>{i.unbind(t)})},abandon:a=>n.abandon(a)}}var Oy=new Set(["/v1/sessions/:id/history","/v1/sessions/:id/events"]);function yu(s,e){let t=e.fetchImpl??fetch;s.addHook("preHandler",async(n,r)=>{let o=n.routeOptions.url;if(!o||!o.startsWith("/v1/sessions/:id"))return;let i=n.params,a=i.id;if(typeof a!="string")return;let d=gt(a);if(!d){if(!e.localMiss||await e.localMiss.resolvesLocally(a))return;let g=e.localMiss.cache.findByLocalId(a);if(g.length===0)return;if(g.length>1){r.code(404).send({error:`Session "${a}" exists on more than one remote (${g.map(y=>y.name).join(", ")}). Address it as "<remote>:${a}".`});return}d=g[0]}let c=e.store.get(d.name);if(!c){r.code(404).send({error:`No remote named "${d.name}". Run \`hydra remote add\` first.`});return}let u=n.query;if(Oy.has(o)&&Ny(u?.follow)){let g=c.port===$t?"":`:${c.port}`;r.code(501).send({error:`Streaming a federated session isn't supported yet. Attach directly with hydra://${c.host}${g}/${d.localId} instead.`});return}let l=Dy(o,i,d.localId,n.url),f=`${Ae(c.host)?"http":"https"}://${c.host}:${c.port}${l}`,h;try{h=await t(f,{method:n.method,headers:{Authorization:`Bearer ${c.token}`,...n.body!==void 0?{"Content-Type":"application/json"}:{}},...n.body!==void 0&&n.method!=="GET"?{body:JSON.stringify(n.body)}:{}})}catch(g){r.code(502).send({error:`Could not reach remote "${d.name}" (${c.host}:${c.port}): ${g.message}`});return}if(n.method==="DELETE"&&o==="/v1/sessions/:id"&&(h.ok||h.status===404)&&e.localMiss?.cache.evict(d.name,d.localId),h.status===204){r.code(204).send();return}let k=await h.text(),m=h.headers.get("content-type");m&&r.header("content-type",m),r.code(h.status).send(k)})}var Fy=5e3,ar=class{constructor(e,t={}){this.store=e;this.opts=t}store;opts;perPeer=new Map;timer;start(){this.timer||(this.refreshNow(),this.timer=setInterval(()=>{this.refreshNow()},this.opts.intervalMs??Fy),this.timer.unref?.())}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}async refreshNow(){let e=this.opts.fetchImpl??fetch,t=new Set(this.store.list().map(n=>n.name));for(let n of[...this.perPeer.keys()])t.has(n)||this.perPeer.delete(n);await Promise.allSettled(this.store.list().map(async n=>{let r=this.store.get(n.name);if(!r)return;let o=this.perPeer.get(n.name),i=Ae(r.host)?"http":"https",a=new URLSearchParams({includeNonInteractive:"1"}),d=o?.cursor!==void 0;d&&a.set("since",String(o.cursor));let c=`${i}://${r.host}:${r.port}/v1/sessions?${a.toString()}`,u;try{u=await e(c,{headers:{Authorization:`Bearer ${r.token}`}})}catch{return}if(!u.ok)return;let l=await u.json(),p=o?.sessions??new Map;if(d){for(let[f,h]of[...p])h.status!=="cold"&&p.delete(f);for(let f of l.removed??[])p.delete(Je({name:n.name,localId:f}))}else p.clear();for(let f of l.sessions??[]){let h=Je({name:n.name,localId:String(f.sessionId)});p.set(h,{...f,sessionId:h,remote:n.name})}this.perPeer.set(n.name,{cursor:l.cursor,sessions:p})}))}list(e){let t=[];for(let n of this.perPeer.values())t.push(...n.sessions.values());return t.filter(n=>!(e.status&&n.status!==e.status||!e.includeNonInteractive&&n.interactive!==!0))}evict(e,t){this.perPeer.get(e)?.sessions.delete(Je({name:e,localId:t}))}findByLocalId(e){let t=e.startsWith(ye)?[e]:[e,ye+e],n=[];for(let[r,o]of this.perPeer)for(let i of t)if(o.sessions.has(Je({name:r,localId:i}))){n.push({name:r,localId:i});break}return n}};async function wu(s,e,t,n=fetch){let r=s.get(e);if(!r)return{status:404,body:{error:`No remote named "${e}". Run \`hydra remote add\` first.`}};let i=`${Ae(r.host)?"http":"https"}://${r.host}:${r.port}/v1/sessions`,a;try{a=await n(i,{method:"POST",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:JSON.stringify(t)})}catch(l){return{status:502,body:{error:`Could not reach remote "${e}" (${r.host}:${r.port}): ${l.message}`}}}let d=await a.text(),c=null;try{c=d.length>0?JSON.parse(d):null}catch{c=null}if(!a.ok)return{status:a.status,body:c};let u=c;return u&&typeof u.sessionId=="string"?{status:a.status,body:{...u,sessionId:Je({name:e,localId:u.sessionId})}}:{status:a.status,body:c}}async function ku(s,e,t=fetch){let n;if(e.sessionIds===void 0)n=s.list().map(a=>({name:a.name}));else{let a=new Map;for(let d of e.sessionIds){let c=gt(d);if(!c)continue;let u=a.get(c.name)??[];u.push(c.localId),a.set(c.name,u)}n=[...a.entries()].map(([d,c])=>({name:d,sessionIds:c}))}if(n.length===0)return{query:e.q,truncated:!1,results:[]};let r=await Promise.all(n.map(async a=>{let d=s.get(a.name);if(!d)return null;let u=`${Ae(d.host)?"http":"https"}://${d.host}:${d.port}/v1/sessions/search`,l;try{l=await t(u,{method:"POST",headers:{Authorization:`Bearer ${d.token}`,"Content-Type":"application/json"},body:JSON.stringify({q:e.q,...a.sessionIds?{sessionIds:a.sessionIds}:{},...e.snippetWidth!==void 0?{snippetWidth:e.snippetWidth}:{}})})}catch{return null}if(!l.ok)return null;let p;try{p=await l.json()}catch{return null}let f=p;if(!f||!Array.isArray(f.results))return null;let h=f.results.map(k=>({...k,sessionId:Je({name:a.name,localId:k.sessionId})}));return{query:e.q,truncated:f.truncated===!0,results:h}})),o=[],i=!1;for(let a of r)a!==null&&(o.push(...a.results),i=i||a.truncated);return{query:e.q,truncated:i,results:o}}function Ny(s){return s==="1"||s==="true"||s===!0}function Dy(s,e,t,n){let r=s.replace(/:([A-Za-z_]+)/g,(i,a)=>encodeURIComponent(a==="id"?t:e[a]??"")),o=n.indexOf("?");return o===-1?r:r+n.slice(o)}var dr=new Set(["usage_update","tool_call","tool_call_update","prompt_received","turn_complete","permission_resolved"]);function vu(s){if(s.publicHost&&s.publicHost.length>0)return s.publicHost;if(s.host&&!Ae(s.host))return s.port!==void 0?`${s.host}:${s.port}`:s.host}function Su(s,e,t,n={},r,o){s.get("/v1/sessions",async(p,f)=>{let h=p.query,k=h?.includeNonInteractive==="1"||h?.includeNonInteractive==="true",m;if(h?.since!==void 0&&(m=Number(h.since),!Number.isFinite(m)||m<0))return f.code(400).send({error:`since must be a non-negative number, got ${JSON.stringify(h.since)}`});let g=h?.status==="warm"||h?.status==="cold"?h.status:void 0,y={cwd:h?.cwd,includeNonInteractive:k,...g?{status:g}:{}},w=o&&!y.cwd?o.list({includeNonInteractive:k,...g?{status:g}:{}}):[];if(m!==void 0){let S=await e.listSince(y,m);return{sessions:[...S.entries,...w],removed:S.removed,cursor:S.cursor}}let v=await e.listing(y);return{sessions:[...v.entries,...w],removed:[],cursor:v.cursor}}),s.get("/v1/sessions/:id",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=await e.getOne(k);return m||(f.code(404).send({error:"session not found"}),f)}),s.post("/v1/sessions/search",async(p,f)=>{let h=p.body??{},k=typeof h.q=="string"?h.q:"";if(k.trim().length===0)return f.code(400).send({error:"q is required"}),f;let m=Array.isArray(h.sessionIds)?h.sessionIds.filter(v=>typeof v=="string"&&v.length>0):void 0,g={sessionIds:m};typeof h.snippetWidth=="number"&&(g.snippetWidth=h.snippetWidth);let y=await gu(e,k,g);if(!r)return y;let w=await ku(r,{q:k,...m?{sessionIds:m}:{},...g.snippetWidth!==void 0?{snippetWidth:g.snippetWidth}:{}});return{query:k,truncated:y.truncated||w.truncated,results:[...y.results,...w.results]}}),s.post("/v1/sessions",async(p,f)=>{let h=p.body??{};if(h.remote){if(!r)return f.code(404).send({error:`No remote named "${h.remote}". Run \`hydra remote add\` first.`});let v=await wu(r,h.remote,{cwd:h.cwd,agentId:h.agentId,mcpServers:h.mcpServers,workspace:h.workspace});return f.code(v.status).send(v.body)}let k=ce(h.cwd??t.cwd),m=await mn(k),g=h.agentId??m.agentId??t.agentId,y=on(n),w=y!==void 0?[...h.mcpServers??[],...y.descriptors]:h.mcpServers;try{let v=await e.create({cwd:k,agentId:g,mcpServers:w,...h.workspace!==void 0?{workspace:h.workspace}:{}});y!==void 0&&y.bindToSession(v),f.code(201).send({sessionId:v.sessionId,agentId:v.agentId,cwd:v.cwd,...v.workspace!==void 0?{workspace:v.workspace}:{},...v.workspaceError!==void 0?{workspaceError:v.workspaceError}:{}})}catch(v){y!==void 0&&y.abandon(v instanceof Error?v:void 0),f.code(500).send({error:v.message})}}),s.post("/v1/sessions/collect",async(p,f)=>{let h=p.body??{},k=typeof h.maxAgeDays=="number"&&h.maxAgeDays>0?h.maxAgeDays*24*60*60*1e3:0,m=typeof h.limit=="number"&&h.limit>0?h.limit:1e3,g=h.selection==="explicit"||h.selection==="unpromoted"?h.selection:"unpromoted";try{let y=await si({manager:e,maxAgeMs:k,maxDeletions:m,selection:g,verbose:!1});f.code(200).send(y)}catch(y){f.code(500).send({error:y.message})}}),s.get("/v1/sessions/tombstones",async(p,f)=>{let h=p.query;if(h.since!==void 0&&Number.isNaN(Date.parse(h.since))){f.code(400).send({error:"since must be an ISO timestamp"});return}let k=await e.listTombstones({...h.agent?{agentId:h.agent}:{},...h.since?{since:h.since}:{},...h.grep?{grep:h.grep}:{}});f.code(200).send({tombstones:k})}),s.post("/v1/sessions/undelete",async(p,f)=>{let h=p.body??{};if(!Array.isArray(h.ids)||h.ids.length===0||!h.ids.every(k=>typeof k=="string"&&k.length>0)){f.code(400).send({error:"ids must be a non-empty array of strings"});return}try{f.code(200).send(await e.undeleteSessions(h.ids))}catch(k){f.code(500).send({error:k.message})}}),s.post("/v1/sessions/:id/kill",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k);if(m){m.close({deleteRecord:!1,by:"REST POST /kill"}).catch(()=>{}),f.code(202).send();return}if(!await e.hasRecord(k)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.post("/v1/sessions/:id/stdin/open",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k);if(!m)return f.code(404).send({error:"session not found"}),f;let g=p.body??{},y={};(g.mode==="memory"||g.mode==="file")&&(y.mode=g.mode),typeof g.capacityBytes=="number"&&(y.capacityBytes=g.capacityBytes),typeof g.fileCapBytes=="number"&&(y.fileCapBytes=g.fileCapBytes),(y.mode??"memory")==="file"&&(y.filePathFor=w=>cr.join(bu.tmpdir(),`hydra-acp-stdin-${w}.log`));try{return m.openStream(y)}catch(w){return f.code(409).send({error:w.message}),f}}),s.post("/v1/sessions/:id/stdin",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k);if(!m)return f.code(404).send({error:"session not found"}),f;let g=p.body??{},y=typeof g.chunk=="string"?g.chunk:"",w=g.eof===!0;try{return m.streamWrite(y,w)}catch(v){return f.code(409).send({error:v.message}),f}}),s.patch("/v1/sessions/:id",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=p.body??{};if(m.cwd!==void 0){if(typeof m.cwd!="string"||!cr.isAbsolute(m.cwd)){f.code(400).send({error:"cwd must be an absolute path"});return}let y=await e.setCwd(k,m.cwd);if(y==="missing"){f.code(404).send({error:"session not found"});return}if(y==="not-a-directory"){f.code(400).send({error:`${m.cwd} is not a directory`});return}if(y==="live"){f.code(409).send({error:"session is live; its agent was spawned in its cwd and cannot change directory. Moving a live session is a swap \u2014 use `workspace start` in it."});return}if(y==="bound"){f.code(409).send({error:"session is isolated, so its cwd IS its workspace. Clear the binding first (PATCH { workspace: null }) or leave the workspace from inside the session."});return}f.code(204).send();return}if("workspace"in m){if(m.workspace!==null){f.code(400).send({error:"workspace may only be set to null (clear the binding)"});return}let y=await e.clearWorkspaceBinding(k);if(y==="missing"){f.code(404).send({error:"session not found"});return}if(y==="live"){f.code(409).send({error:"session is live; its cwd is the workspace. Use `workspace stop` or `workspace detach` in the session so the agent moves with the binding."});return}f.code(204).send();return}if(m.priority!==void 0){let y=m.priority,w;if(y===null||y===0)w=void 0;else if(typeof y=="number"&&Number.isInteger(y)&&y>0)w=y;else{f.code(400).send({error:"priority must be a non-negative integer (or null to clear)"});return}if(!await e.setPriority(k,w)){f.code(404).send({error:"session not found"});return}f.code(204).send();return}if(m.read!==void 0){if(typeof m.read!="boolean"){f.code(400).send({error:"read must be a boolean"});return}if(!await e.setRead(k,m.read)){f.code(404).send({error:"session not found"});return}f.code(204).send();return}if(m.regen===!0){if(!(e.get(k)!==void 0||await e.hasRecord(k))){f.code(404).send({error:"session not found"});return}e.scheduleSynopsis(k),f.code(202).send();return}if(typeof m.title!="string"||m.title.trim().length===0){f.code(400).send({error:"title must be a non-empty string"});return}if(!await e.setTitle(k,m.title)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.delete("/v1/sessions/:id",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k);if(m){await m.close({deleteRecord:!0,by:"REST DELETE /v1/sessions"}),await e.waitForDeletion(k),await e.hasRecord(k)&&await e.deleteRecord(k),f.code(204).send();return}if(!await e.deleteRecord(k)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.get("/v1/sessions/:id/export",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=p.query?.tools,g=m==="references"?"references":wc(m),y=await e.exportBundle(k,g==="references"?{tools:"references"}:{});if(!y){f.code(404).send({error:"session not found"});return}let w=Nn({record:y.record,history:g==="summary"?kc(y.history,"summary"):y.history,promptHistory:y.promptHistory.length>0?y.promptHistory:void 0,...y.toolBlobs!==void 0?{toolBlobs:y.toolBlobs}:{},hydraVersion:ue,machine:St(),hydraHost:vu(t)}),v=new Date().toISOString().replace(/[:.]/g,"-");f.header("Content-Disposition",`attachment; filename="${k}-${v}.hydra"`),f.code(200).send(w)}),s.get("/v1/sessions/:id/diff",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=await e.exportBundle(k,{includeArchivedHistory:!0});if(!m){f.code(404).send({error:"session not found"});return}let g=p.query??{},y=g.fold==="true"||g.fold==="1",w=typeof g.paths=="string"&&g.paths.length>0?new Set(g.paths.split(",").map(S=>S.trim()).filter(S=>S.length>0)):void 0,v=su(m.history);w&&(v=v.filter(S=>w.has(S.path))),y&&(v=v.map(S=>({...S,hunks:ru(S.hunks)}))),f.code(200).send(v)}),s.get("/v1/sessions/:id/tools/:hash",async(p,f)=>{let h=p.params,k=await e.resolveCanonicalId(h.id)??h.id,m=await e.loadToolBlob(k,h.hash);if(m===null){f.code(404).send({error:"tool blob not found"});return}f.header("Content-Type","text/plain; charset=utf-8"),f.code(200).send(m)}),s.get("/v1/sessions/:id/transcript",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=await e.exportBundle(k);if(!m){f.code(404).send({error:"session not found"});return}let g=Nn({record:m.record,history:m.history,promptHistory:m.promptHistory.length>0?m.promptHistory:void 0,hydraVersion:ue,machine:St(),hydraHost:vu(t)}),y=p.query,w=b=>b==="1"||b==="true"||b==="yes",v=b=>{let I=y?.[b];if(I===void 0||I==="")return;let A=Number(I);return Number.isFinite(A)?A:"bad"},S={};for(let b of["from","to","last","since"]){let I=v(b);if(I==="bad"){f.code(400).send({error:`${b} must be a number`});return}I!==void 0&&(S[b==="since"?"sinceMs":b]=I)}f.header("Content-Type","text/markdown; charset=utf-8"),f.code(200).send(iu(g,{includeTools:w(y?.tools),includeThoughts:w(y?.thoughts),...S}))});let i=p=>async(f,h)=>{let k=f.params.id,m=await e.resolveCanonicalId(k)??k,g=f.body??{},y={};if(g.forkAt!==void 0){if(typeof g.forkAt!="string"||g.forkAt.length===0){h.code(400).send({error:"forkAt must be a non-empty string"});return}y.forkAt=g.forkAt}if(g.cwd!==void 0){if(typeof g.cwd!="string"||g.cwd.length===0){h.code(400).send({error:"cwd must be a non-empty string"});return}y.cwd=ce(g.cwd)}if(g.agentId!==void 0){if(typeof g.agentId!="string"||g.agentId.length===0){h.code(400).send({error:"agentId must be a non-empty string"});return}y.agentId=g.agentId}if(g.title!==void 0){if(typeof g.title!="string"){h.code(400).send({error:"title must be a string"});return}y.title=g.title}if(p){let w=g.selection;if(w!==void 0){if(typeof w.text!="string"||w.text.length===0){h.code(400).send({error:"selection.text must be a non-empty string"});return}y.side={selection:{text:w.text,...typeof w.responsePartId=="string"?{responsePartId:w.responsePartId}:{}}}}else y.side={}}if(g.mode!==void 0&&!p){if(g.mode!=="verbatim"&&g.mode!=="synthesis"){h.code(400).send({error:'mode must be "verbatim" or "synthesis"'});return}y.mode=g.mode}if(g.model!==void 0){if(typeof g.model!="string"||g.model.length===0){h.code(400).send({error:"model must be a non-empty string"});return}y.model=g.model}try{let w=await e.forkSession(m,y);h.code(201).send(w)}catch(w){let v=w;if(v.code===R.SessionNotFound){h.code(404).send({error:v.message});return}if(v.code===R.InvalidParams||v.code===R.AgentNotInstalled){h.code(400).send({error:v.message});return}h.code(500).send({error:v.message})}};s.post("/v1/sessions/:id/fork",i(!1)),s.post("/v1/sessions/:id/side",i(!0)),s.post("/v1/sessions/:id/rewind",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=(p.body??{}).keepThrough;if(m!==null&&(typeof m!="string"||m.length===0)){f.code(400).send({error:"keepThrough must be a non-empty messageId, or null to drop every turn"});return}try{f.code(200).send(await e.rewindSession(k,m))}catch(g){let y=g;if(y.code===R.SessionNotFound){f.code(404).send({error:y.message});return}if(y.code===R.InvalidParams){f.code(400).send({error:y.message});return}if(y.code===R.InvalidRequest){f.code(409).send({error:y.message});return}f.code(500).send({error:y.message})}}),s.post("/v1/sessions/import",async(p,f)=>{let h=p.body??{};if(h.bundle===void 0){f.code(400).send({error:"missing bundle"});return}let k;if(h.cwd!==void 0){if(typeof h.cwd!="string"||h.cwd.length===0){f.code(400).send({error:"cwd must be a non-empty string"});return}k=h.cwd}let m;try{m=xc(h.bundle)}catch(g){f.code(400).send({error:"invalid bundle",details:g.message});return}try{let g=await e.importBundle(m,{replace:h.replace===!0,...k!==void 0?{cwd:k}:{}});f.code(201).send(g)}catch(g){let y=g;if(y.code===R.BundleAlreadyImported){f.code(409).send({error:"bundle already imported",existingSessionId:y.existingSessionId});return}f.code(500).send({error:y.message})}}),s.get("/v1/sessions/:id/compact/status",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k),g;if(m?g=m.summarizedThroughEntry:g=await e.getSummarizedThroughEntry(k),g===void 0&&!await e.hasRecord(k))return f.code(404).send({error:"session not found"}),f;let y=await e.getCompactionState(k),w=await e.getRollbackBreadcrumb(k),v=await e.getPendingAgentSwap(k),S=!1,b,I=m?.currentUsage,A=typeof I?.used=="number"&&typeof I?.size=="number"&&I.size>0?{used:I.used,size:I.size}:void 0,x=await e.loadHistory(k,{tools:"references",maxEntries:1/0}).catch(()=>[]);if(x.length>0&&t.compaction){let T=g??0,M=x.length,N=T<=x.length?T:0,B=x.slice(N),q=tu(B);b=ri(q);let V=m?.currentModel,L=x.at(-1).recordedAt;S=nu({summarizedThroughEntry:T,totalEntries:M,unsummarizedChars:q,compactionInFlight:e.getCompactionInFlight(),currentModel:V,lastActivityMs:L,nowMs:Date.now(),config:t.compaction,...typeof I?.used=="number"?{agentReportedUsed:I.used}:{},...typeof I?.size=="number"?{agentReportedSize:I.size}:{}})}return{summarizedThroughEntry:g??void 0,inFlight:e.getCompactionInFlight(),shouldCompact:S,...b!=null?{approxTokens:b}:{},...A!=null?{currentUsage:A}:{},...y!=null?{compactionState:y}:{},...w!=null?{rollbackBreadcrumb:w}:{},...v!=null?{pendingAgentSwap:v}:{}}}),s.post("/v1/sessions/:id/compact",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h;if(e.get(k)){e.scheduleCompaction(k),f.code(202).send({scheduled:!0});return}if(!await e.hasRecord(k)){f.code(404).send({error:"session not found"});return}e.scheduleCompaction(k),f.code(202).send({scheduled:!0})}),s.post("/v1/sessions/:id/compact/rollback",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h;if(!await e.hasRecord(k)){f.code(404).send({error:"session not found"});return}try{await e.performUncompact(k),f.code(202).send({rolledBack:!0})}catch(m){let g=m instanceof Error?m.message:String(m);f.code(409).send({error:g})}}),s.post("/v1/sessions/:id/workspace/clean",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=p.body??{};if(m.deep!==void 0&&typeof m.deep!="boolean"){f.code(400).send({error:"deep must be a boolean"});return}if(!await e.hasRecord(k)){f.code(404).send({error:"session not found"});return}if(e.get(k)===void 0){f.code(409).send({error:"session is not live. Cleaning rewrites the workspace under a running agent, so it is only available inside a live session (`/hydra workspace clean`). For a cold workspace use `hydra workspace remove` instead."});return}try{let g=await e.runWorkspaceAction(k,"clean",void 0,{deep:m.deep===!0});f.code(202).send({report:g})}catch(g){f.code(409).send({error:g instanceof Error?g.message:String(g)})}}),s.get("/v1/sessions/:id/history/page",async(p,f)=>{let h=p.params.id,k=p.query,m=Number(k?.beforeSeq);if(k?.beforeSeq===void 0||k.beforeSeq===""||!Number.isFinite(m)){f.code(400).send({error:"beforeSeq must be a number"});return}let g=k.turns===void 0||k.turns===""?10:Number(k.turns);if(!Number.isInteger(g)||g<1){f.code(400).send({error:"turns must be a positive integer"});return}let y=await e.resolveCanonicalId(h)??h,w=await e.pageHistory(y,{beforeSeq:m,turns:Math.min(g,100)});if(!w){f.code(404).send({error:"session not found"});return}f.code(200).send({entries:w.entries,hasMore:w.hasMore})}),s.get("/v1/sessions/:id/history",async(p,f)=>{let h=p.params.id,k=p.query,m=k?.follow==="1"||k?.follow==="true",g=await e.resolveCanonicalId(h)??h,y=e.get(g),w,v,S=!1,b=1e4,I=[];if(y){m&&(v=y.onBroadcast(x=>{f.raw.writableEnded||(S?f.raw.write(JSON.stringify(x)+`
208
+ `):(I.push(x),I.length>b&&I.shift()))})),p.raw.on("close",()=>{v?.(),f.raw.writableEnded||f.raw.end()});try{w=await y.getHistorySnapshot()}catch(x){throw v?.(),x}}else{let x=await e.getHistory(g);if(x===void 0)return f.code(404).send({error:"session not found"}),f;w=x}f.raw.setHeader("Content-Type","application/x-ndjson"),f.raw.setHeader("Cache-Control","no-cache"),f.raw.statusCode=200;let A=new Set;for(let x of w??[]){f.raw.write(JSON.stringify(x)+`
209
+ `);let T=x;typeof T.recordedAt=="number"&&A.add(String(T.recordedAt))}for(;I.length>0;){let x=I.splice(0,I.length);for(let T of x){let M=T,N=typeof M.recordedAt=="number"?String(M.recordedAt):"";N&&A.has(N)||f.raw.write(JSON.stringify(T)+`
210
+ `)}}return S=!0,v||f.raw.end(),f});function a(p,f,h){let k=typeof p=="string"?p.trim():"";if(k.length===0)return null;let m;try{m=JSON.parse(k)}catch{return console.debug("events endpoint: skipping malformed JSONL line"),null}if(!m||typeof m!="object"||Array.isArray(m))return console.debug("events endpoint: skipping non-object JSONL line"),null;let g=m;if(typeof g.recordedAt!="number"||h!==void 0&&g.recordedAt<h||typeof g.params!="object"||g.params===null||Array.isArray(g.params))return null;let y=g.params;if(typeof y.update!="object"||y.update===null||Array.isArray(y.update))return null;let v=y.update.sessionUpdate;return typeof v!="string"||!f.has(v)?null:{recordedAt:g.recordedAt,entry:m}}function d(p,f,h){let m=f.params.update,g={sessionId:p,ts:new Date(f.recordedAt).toISOString(),kind:h,update:m};return m.messageId!==void 0&&m.messageId!==null&&(g.messageId=m.messageId),g}async function*c(p,f,h,k){for await(let m of f){let g=a(m,h,k);if(g){let y=g.entry.params.update.sessionUpdate;yield{ts:g.recordedAt,row:d(p,g.entry,y)}}}}async function u(p,f,h,k){let m=ci.createInterface({input:di.createReadStream(f),crlfDelay:1/0}),g=c(p,m,h,k),y=await g.next(),w=y.done?null:y.value;return{sessionId:p,rl:m,gen:g,current:w,exhausted:w===null}}async function l(p){let f=await p.gen.next();f.done?(p.exhausted=!0,p.current=null):p.current=f.value}s.get("/v1/sessions/events",async(p,f)=>{let h=p.query,k=h.kinds;if(!k||k.trim().length===0)return f.code(400).send({error:"kinds parameter is required"}),f;let m=k.split(",").map(b=>b.trim());if(m.length===0)return f.code(400).send({error:"kinds parameter is required"}),f;for(let b of m)if(!dr.has(b))return f.code(400).send({error:`kind "${b}" is not queryable; allowed kinds: ${[...dr].join(", ")}`}),f;let g=new Set(m),y;if(h.since!==void 0&&h.since.trim().length>0){let b=new Date(h.since);if(isNaN(b.getTime()))return f.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),f;y=b.getTime()}let w=await e.list({includeNonInteractive:!0}),v=y!==void 0?w.filter(b=>new Date(b.updatedAt).getTime()>=y):w;f.raw.setHeader("content-type","application/x-ndjson"),f.raw.statusCode=200;let S=[];for(let b of v)try{let I=E.historyFile(b.sessionId),A=await u(b.sessionId,I,g,y);A.exhausted||S.push(A)}catch(I){if(I.code==="ENOENT")continue;throw I}p.raw.on("close",()=>{for(let b of S)try{b.rl.close()}catch{}f.raw.writableEnded||f.raw.end()});try{for(;S.length>0;){let b=-1,I=1/0;for(let x=0;x<S.length;x++){let T=S[x];T.current!==null&&T.current.ts<I&&(I=T.current.ts,b=x)}if(b===-1)break;let A=S[b];if(f.raw.write(JSON.stringify(A.current.row)+`
211
+ `),await l(A),A.exhausted){try{A.rl.close()}catch{}S.splice(b,1)}}}catch(b){for(let I of S)try{I.rl.close()}catch{}throw b}return f.raw.end(),f}),s.get("/v1/sessions/:id/events",async(p,f)=>{let h=p.params.id,k=p.query,m=await e.resolveCanonicalId(h)??h;if(!e.get(m)&&!await e.hasRecord(m))return f.code(404).send({error:"session not found"}),f;let y=k.kinds;if(!y||y.trim().length===0)return f.code(400).send({error:"kinds parameter is required"}),f;let w=y.split(",").map(x=>x.trim());if(w.length===0)return f.code(400).send({error:"kinds parameter is required"}),f;for(let x of w)if(!dr.has(x))return f.code(400).send({error:`kind "${x}" is not queryable; allowed kinds: ${[...dr].join(", ")}`}),f;let v=new Set(w),S;if(k.since!==void 0&&k.since.trim().length>0){let x=new Date(k.since);if(isNaN(x.getTime()))return f.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),f;S=x.getTime()}let b=E.historyFile(m),I=di.createReadStream(b),A=ci.createInterface({input:I,crlfDelay:1/0});f.raw.setHeader("content-type","application/x-ndjson"),f.raw.statusCode=200;try{for await(let x of A){let T=typeof x=="string"?x.trim():"";if(T.length===0)continue;let M;try{M=JSON.parse(T)}catch{console.debug("events endpoint: skipping malformed JSONL line in %s",b);continue}if(!M||typeof M!="object"||Array.isArray(M)){console.debug("events endpoint: skipping non-object JSONL line in %s",b);continue}let N=M;if(typeof N.recordedAt!="number"||typeof N.params!="object"||N.params===null||Array.isArray(N.params))continue;let B=N.params;if(typeof B.update!="object"||B.update===null||Array.isArray(B.update))continue;let q=B.update,V=q.sessionUpdate;if(typeof V!="string"||!v.has(V)||S!==void 0&&N.recordedAt<S)continue;let L={ts:new Date(N.recordedAt).toISOString(),kind:V,update:q};q.messageId!==void 0&&q.messageId!==null&&(L.messageId=q.messageId),f.raw.write(JSON.stringify(L)+`
212
+ `)}}catch(x){if(x.code==="ENOENT")return f.raw.end(),f;throw x}return f.raw.end(),f}),s.post("/v1/sessions/:id/prompt/:messageId/notify",async(p,f)=>{let h=p.params,k=h.id,m=await e.resolveCanonicalId(k)??k,g=h.messageId,y=p.body,w=typeof y?.callbackUrl=="string"?y.callbackUrl:"",v=typeof y?.secret=="string"?y.secret:"";if(!g||!w||!v){f.code(400).send({error:"messageId, callbackUrl, and secret are all required"});return}let S;try{S=new URL(w)}catch{f.code(400).send({error:"callbackUrl must be a valid absolute URL"});return}if(S.protocol!=="https:"&&S.protocol!=="http:"){f.code(400).send({error:"callbackUrl must be http or https"});return}let b=e.get(m);if(!b){f.code(404).send({error:"session not found or not warm"});return}let I=b.registerTurnNotify(g,w,v);if(I.alreadyTerminal){f.code(200).send({status:"already_terminal",stopReason:I.stopReason});return}f.code(202).send({status:"registered"})}),s.get("/v1/sessions/:id/attention",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,m=e.get(k);return!m&&!await e.hasRecord(k)?(f.code(404).send({error:"session not found"}),f):m?{flags:m.listAttentionFlags()}:{flags:(await e.store.read(k))?.attentionFlags??[]}}),s.get("/v1/sessions/attention",async(p,f)=>{let h=p.query;if(!h.source||h.source.trim().length===0)return f.code(400).send({error:"source query parameter is required"}),f;let k=await e.list({includeNonInteractive:!0}),m=[];for(let g of k){let y=e.get(g.sessionId),w;y?w=y.listAttentionFlags():w=(await e.store.read(g.sessionId))?.attentionFlags??[];for(let v of w)v.source===h.source&&m.push({...v,sessionId:g.sessionId})}return{flags:m}}),s.post("/v1/sessions/:id/attention/clear",async(p,f)=>{let h=p.params.id,k=await e.resolveCanonicalId(h)??h,g=p.body??{},y=typeof g.source=="string"?g.source:"",w=typeof g.reason=="string"?g.reason:"";if((y.length>0||w.length>0)&&!(y.length>0&&w.length>0)){f.code(400).send({error:"both source and reason are required to clear a specific flag, or omit both to clear all"});return}y.length===0&&w.length;let v=e.get(k);if(v){if(y.length>0&&w.length>0)v.clearAttentionFlag(y,w);else{let x=Array.from(v.listAttentionFlags()).map(T=>`${T.source}::${T.reason}`);for(let T of x)v.clearAttentionFlag(T.split("::")[0],T.split("::").slice(1).join("::"))}f.code(204).send();return}if(!await e.hasRecord(k)){f.code(404).send({error:"session not found"});return}let S=e.store,b=await S.read(k);if(!b){f.code(404).send({error:"session not found"});return}let I=b.attentionFlags??[],A;if(y.length>0&&w.length>0){let x=`${y}::${w}`;A=I.filter(T=>`${T.source}::${T.reason}`!==x)}else A=[];if(A.length===I.length&&A.every((x,T)=>x.source===I[T].source&&x.reason===I[T].reason)){f.code(204).send();return}await S.write({...b,attentionFlags:A}),f.code(204).send()})}function Iu(s,e,t,n={}){s.get("/v1/agents",async()=>Ht(e)),s.get("/v1/registry",async()=>e.load()),s.post("/v1/registry/refresh",async()=>{let r=await e.refresh();return{version:r.version,agentCount:r.agents.length}}),s.post("/v1/agents/:id/install",async(r,o)=>{let i=r.params.id,a=await e.getAgent(i);if(!a){o.code(404).send({error:`agent ${i} not found in registry`});return}if(a.distribution.uvx&&!a.distribution.npx&&!a.distribution.binary){o.send({agentId:a.id,version:a.version??"current",distribution:"uvx",installed:!1,message:"uvx agents resolve on first run; nothing to pre-install."});return}try{let d=await _e(a,[],{npmRegistry:n.npmRegistry}),c=a.distribution.npx?"npx":a.distribution.binary?"binary":"unknown";o.send({agentId:a.id,version:d.version,distribution:c,installed:!0,command:d.command})}catch(d){o.code(500).send({error:d.message})}}),s.post("/v1/agents/:id/sync",async(r,o)=>{let i=r.params.id;try{let{synced:a,skipped:d}=await t.syncFromAgent(i);return{synced:a.map(c=>({sessionId:c.sessionId,upstreamSessionId:c.upstreamSessionId,agentId:c.agentId,cwd:c.cwd,title:c.title,updatedAt:c.updatedAt})),skipped:d}}catch(a){let d=a;if(d.code===R.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}Y();function Au(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:E.home(),driftedKeys:n()}))}import*as Tu from"os";Y();je();var Gn=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,ur=class s{data;constructor(e){this.data=e}static async load(){let e=await de(E.peers());return new s(Hy(e))}get(e){return this.data.entries[e]}async set(e){this.data.entries[e.name]=e,await Cu(this.data)}async delete(e){return e in this.data.entries?(delete this.data.entries[e],await Cu(this.data),!0):!1}list(){return Object.values(this.data.entries).map(({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})=>({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})).sort((e,t)=>e.addedAt.localeCompare(t.addedAt))}};function Hy(s){if(!s||typeof s!="object")return{version:1,entries:{}};let e=s,t=e.entries&&typeof e.entries=="object"?e.entries:{},n={};for(let[r,o]of Object.entries(t)){if(!o||typeof o!="object")continue;let i=o;if(typeof i.name!="string"||typeof i.host!="string"||typeof i.port!="number"||typeof i.token!="string"||typeof i.expiresAt!="string"||typeof i.addedAt!="string")continue;let a={name:i.name,host:i.host,port:i.port,token:i.token,expiresAt:i.expiresAt,addedAt:i.addedAt};typeof i.label=="string"&&(a.label=i.label),typeof i.pinnedFingerprint=="string"&&(a.pinnedFingerprint=i.pinnedFingerprint),typeof i.pinnedAt=="string"&&(a.pinnedAt=i.pinnedAt),n[r]=a}return{version:1,entries:n}}async function Cu(s){await me(E.peers(),s,{mode:384})}var jy=3600*24*365,Qe=class extends Error{status;constructor(e,t){super(e),this.name="PeerLoginError",this.status=t}};function lr(s,e){return`${Ae(s)?"http":"https"}://${s}:${e}`}async function Ru(s){let e=s.fetchImpl??fetch,t=`${s.host}:${s.port}`,n=lr(s.host,s.port),r;try{r=await e(`${n}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:s.password,label:s.label,ttlSec:s.ttlSec??jy})})}catch(i){throw new Qe(`Could not reach ${t}: ${i.message}`,502)}if(r.status===401)throw new Qe(`Wrong password for ${t}.`,401);if(r.status===403)throw new Qe(`No password is configured on ${t}. Run \`hydra-acp auth password\` on that daemon first.`,502);if(r.status===429)throw new Qe(`Too many failed login attempts on ${t}; try again later.`,429);if(!r.ok)throw new Qe(`Login to ${t} failed: HTTP ${r.status}`,502);let o=await r.json();if(!o.session_token||!o.expires_at)throw new Qe(`Login to ${t} returned a malformed response.`,502);return{token:o.session_token,expiresAt:o.expires_at}}async function ui(s){let e=s.fetchImpl??fetch,t=lr(s.host,s.port);try{await e(`${t}/v1/auth/logout`,{method:"POST",headers:{Authorization:`Bearer ${s.token}`,"Content-Type":"application/json"},body:JSON.stringify({})})}catch{}}function Eu(s){return{machine:St(),hydraVersion:ue,startedAt:s,os:{platform:process.platform,release:Tu.release(),arch:process.arch},node:process.version}}async function fr(s){let e=s.fetchImpl??fetch,t;try{t=await e(`${lr(s.host,s.port)}/v1/system`,{headers:{Authorization:`Bearer ${s.token}`},signal:s.signal})}catch(n){return{kind:"error",message:n.message}}if(t.status===401||t.status===403)return{kind:"unauthorized"};if(t.status===404)return{kind:"unsupported"};if(!t.ok)return{kind:"error",message:`HTTP ${t.status}`};try{let n=await t.json();return typeof n?.machine=="string"?{kind:"ok",system:n}:{kind:"ok"}}catch{return{kind:"ok"}}}function xu(s){return s!==void 0&&s.length<=64&&Gn.test(s)}function Pu(s,e){if(xu(s))return s;if(/^[\d.]+$/.test(e)||e.includes(":"))return;let t=e.split(".")[0];return xu(t)?t:void 0}function Mu(s,e){s.get("/v1/system",async()=>Eu(e))}var Ly=/^[A-Za-z0-9._-]+$/;function pr(s,e,t){let n=e==="extension"?"extensions":"transformers",r=`/v1/${n}`;s.get(r,async()=>({[n]:t.list()})),s.get(`${r}/:name`,async(o,i)=>{let a=o.params.name,d=t.get(a);if(!d){i.code(404).send({error:`unknown ${e}: ${a}`});return}return d}),s.post(r,async(o,i)=>{let a=o.body??{},d=Uy(a);if("error"in d){i.code(400).send({error:d.error});return}try{let c=t.register(d.config);i.code(201).send(c)}catch(c){Kn(i,c)}}),s.delete(`${r}/:name`,async(o,i)=>{let a=o.params.name;try{await t.unregister(a),i.code(204).send()}catch(d){Kn(i,d)}}),s.post(`${r}/:name/start`,async(o,i)=>{let a=o.params.name;try{let d=await t.startByName(a);i.code(200).send(d)}catch(d){Kn(i,d)}}),s.post(`${r}/:name/stop`,async(o,i)=>{let a=o.params.name;try{let d=await t.stopByName(a);i.code(200).send(d)}catch(d){Kn(i,d)}}),s.post(`${r}/:name/restart`,async(o,i)=>{let a=o.params.name;try{let d=await t.restartByName(a);i.code(200).send(d)}catch(d){Kn(i,d)}})}function Kn(s,e){let t=e.code,n=e.message??"unknown error";if(t==="NOT_FOUND"){s.code(404).send({error:n});return}if(t==="CONFLICT"){s.code(409).send({error:n});return}s.code(500).send({error:n})}function Uy(s){let e=s.name;if(typeof e!="string"||!Ly.test(e))return{error:"name must match [A-Za-z0-9._-]+"};let t=s.command;if(t!==void 0&&(!Array.isArray(t)||t.some(i=>typeof i!="string")))return{error:"command must be string[]"};let n=s.args;if(n!==void 0&&(!Array.isArray(n)||n.some(i=>typeof i!="string")))return{error:"args must be string[]"};let r=s.env;if(r!==void 0&&(typeof r!="object"||r===null||Array.isArray(r)))return{error:"env must be an object of string\u2192string"};if(r&&Object.values(r).some(i=>typeof i!="string"))return{error:"env values must be strings"};let o=s.enabled;return o!==void 0&&typeof o!="boolean"?{error:"enabled must be a boolean"}:{config:{name:e,command:t??[],args:n??[],env:r??{},enabled:o===void 0?!0:o}}}function _u(s,e){pr(s,"extension",e)}function $u(s,e){pr(s,"transformer",e)}function Ou(s,e){s.get("/v1/config",async()=>e())}import{z as wt}from"zod";Y();import*as an from"fs/promises";import*as Fu from"path";import{randomBytes as cR,scrypt as By,timingSafeEqual as Wy}from"crypto";import{promisify as qy}from"util";var zy=qy(By);function Nu(){return Fu.join(E.home(),"password-hash")}var Jy=128*1024*1024;async function Du(){try{return(await an.readFile(Nu(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function Hu(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await an.readFile(Nu(),"utf8")).trim()}catch(c){if(c.code==="ENOENT")return!1;throw c}let t=e.split("$");if(t.length!==6||t[0]!=="scrypt")return!1;let n=parseInt(t[1],10),r=parseInt(t[2],10),o=parseInt(t[3],10);if(!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(o))return!1;let i=Buffer.from(t[4],"hex"),a=Buffer.from(t[5],"hex");if(i.length===0||a.length===0)return!1;let d=await zy(s,i,a.length,{N:n,r,p:o,maxmem:Jy});return d.length!==a.length?!1:Wy(d,a)}var Vy=wt.object({password:wt.string().min(1),label:wt.string().min(1).max(256).optional(),ttlSec:wt.number().int().positive().optional()}),Gy=wt.object({id:wt.string().optional()}).optional(),Ky=wt.object({token:wt.string().min(32)});function ju(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=Qy(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=Vy.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await Du())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await Hu(o.password))return e.rateLimiter.recordFailure(r),n.code(401).send({error:"Invalid password"});e.rateLimiter.recordSuccess(r);let a=await e.store.issue({label:o.label,ttlSec:o.ttlSec});return n.code(200).send({session_token:a.token,id:a.id,expires_at:a.expiresAt})}),s.post("/v1/auth/logout",async(t,n)=>{let r;try{r=Gy.parse(t.body??void 0)}catch{return n.code(400).send({error:"Invalid request body"})}let o=r?.id??t.authIdentity;if(!o||o==="service")return n.code(200).send({revoked:!1});let i=await e.store.revoke(o);return n.code(200).send({revoked:i})}),s.get("/v1/auth/verify",async(t,n)=>n.code(200).send({ok:!0})),s.get("/v1/auth/sessions",async(t,n)=>n.code(200).send({sessions:e.store.list()})),s.delete("/v1/auth/sessions",async(t,n)=>{let r=await e.store.revokeAll();return n.code(200).send({revoked:r})}),s.delete("/v1/auth/sessions/:id",async(t,n)=>{let r=t.params.id;return await e.store.revoke(r)?n.code(204).send():n.code(404).send({error:"Not found"})}),s.post("/v1/auth/rotate-token",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=Ky.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}return e.staticTokenValidator.rotate(r.token),n.code(200).send({rotated:!0})})}function Qy(s){return s.ip||"unknown"}import{z as kt}from"zod";Yn();var dw=kt.object({name:kt.string().min(1).max(64).regex(Gn).optional(),host:kt.string().min(1),port:kt.number().int().positive().optional(),password:kt.string().min(1),label:kt.string().min(1).max(256).optional(),ttlSec:kt.number().int().positive().optional(),pinnedFingerprint:kt.string().min(1).optional()});function Gu(s,e){s.post("/v1/remotes",async(t,n)=>{let r;try{r=dw.parse(t.body)}catch{return n.code(400).send({error:`Invalid request body (name must match ${Gn} and the rest is a normal login request)`})}let o=r.port??$t;r.pinnedFingerprint&&Qn(r.host,o,r.pinnedFingerprint);let i;try{i=await Ru({host:r.host,port:o,password:r.password,label:r.label,ttlSec:r.ttlSec})}catch(p){if(p instanceof Qe)return n.code(p.status).send({error:p.message});throw p}let a=await fr({host:r.host,port:o,token:i.token}),d=a.kind==="ok"?a.system:void 0,c=r.name;if(c===void 0){c=Pu(d?.machine,r.host);let p=c!==void 0?e.store.get(c):void 0,f=p!==void 0&&(p.host!==r.host||p.port!==o);if(c===void 0||f){await ui({host:r.host,port:o,token:i.token});let h=c===void 0?`Couldn't derive a remote name for ${r.host}`:`A remote named ${c} already points at ${p.host}:${p.port}`;return n.code(c===void 0?400:409).send({error:`${h}. Pass a name: hydra-acp remote add <name> ${r.host}`})}}let u=new Date().toISOString(),l={name:c,host:r.host,port:o,token:i.token,expiresAt:i.expiresAt,addedAt:u,...r.label!==void 0?{label:r.label}:{},...r.pinnedFingerprint!==void 0?{pinnedFingerprint:r.pinnedFingerprint,pinnedAt:u}:{}};return await e.store.set(l),e.health?.markOk(l.name,d),n.code(201).send({name:l.name,host:l.host,port:l.port,expiresAt:l.expiresAt,label:l.label,addedAt:l.addedAt,pinnedFingerprint:l.pinnedFingerprint,status:e.health?.get(l.name)?.status??"unknown"})}),s.get("/v1/remotes",async(t,n)=>{let r=e.store.list().map(o=>{let i=e.health?.get(o.name);return{...o,status:i?.status??"unknown",...i?.checkedAt?{lastCheckedAt:i.checkedAt}:{},...i?.system?{system:i.system}:{}}});return n.code(200).send({remotes:r})}),s.get("/v1/remotes/:name/agents",async(t,n)=>{let r=e.store.get(t.params.name);if(!r)return n.code(404).send({error:"Not found"});let i=`${Ae(r.host)?"http":"https"}://${r.host}:${r.port}`,a={Authorization:`Bearer ${r.token}`};try{let[d,c]=await Promise.all([fetch(`${i}/v1/agents`,{headers:a}),fetch(`${i}/v1/config`,{headers:a}).catch(()=>null)]);if(!d.ok)return n.code(d.status).header("content-type","application/json").send(await d.text());let u=await d.json(),l={};if(c?.ok){let p=await c.json();l={defaultAgent:p.defaultAgent,sessionDefaults:p.sessionDefaults}}return n.code(200).send({...u,...l})}catch(d){return n.code(502).send({error:`Could not reach remote "${r.name}": ${d.message}`})}}),s.delete("/v1/remotes/:name",async(t,n)=>{let r=t.params.name,o=e.store.get(r);return o?(await ui({host:o.host,port:o.port,token:o.token}),await e.store.delete(r),e.health?.forget(r),e.store.list().some(a=>a.host===o.host&&a.port===o.port)||fi(o.host,o.port),n.code(204).send()):n.code(404).send({error:"Not found"})})}function mr(s){let e=[],t=[],n=!1,r=o=>{if(!n){n=!0;for(let i of t)i(o)}};return s.on("message",(o,i)=>{if(i)return;let a=o.toString("utf8");try{let d=JSON.parse(a);for(let c of e)c(d)}catch(d){for(let c of e)c({jsonrpc:"2.0",id:null,error:{code:R.ParseError,message:`Failed to parse WS frame: ${d.message}`}})}}),s.on("close",()=>r()),s.on("error",o=>r(o)),{async send(o){if(n)throw new Error("ws is closed");let i=JSON.stringify(o);await new Promise((a,d)=>{s.send(i,c=>{if(c){d(c);return}a()})})},onMessage(o){e.push(o)},onClose(o){t.push(o)},async close(){n||(await new Promise(o=>{let i=!1,a=()=>{i||(i=!0,clearTimeout(d),o())},d=setTimeout(a,5e3);s.once("close",a);try{s.close()}catch{a()}}),r())}}}Yn();import{WebSocket as cw}from"ws";var uw=1e4,yi=class extends Error{url;elapsedMs;constructor(e,t){super(`hydra-acp: websocket connect to ${e} timed out after ${t}ms`),this.name="WsConnectTimeoutError",this.url=e,this.elapsedMs=t}};async function Ku(s,e,t=uw){let n={};try{let r=new URL(s);if(r.protocol==="wss:"){let o=hi(r.hostname);o.rejectUnauthorized!==void 0&&(n.rejectUnauthorized=o.rejectUnauthorized),o.autoSelectFamily!==void 0&&(n.autoSelectFamily=o.autoSelectFamily),o.checkServerIdentity!==void 0&&(n.checkServerIdentity=o.checkServerIdentity)}}catch{}return new Promise((r,o)=>{let i=new cw(s,e,n),a=Date.now(),d=setTimeout(()=>{i.off("open",c),i.off("error",u),i.on("error",()=>{});try{i.terminate()}catch{}o(new yi(s,Date.now()-a))},t),c=()=>{clearTimeout(d),i.off("error",u),r(i)},u=l=>{clearTimeout(d),i.off("open",c),o(l)};i.once("open",c),i.once("error",u)})}var lw=new Set(["session/attach","session/detach","session/prompt","session/cancel","session/close","session/delete","hydra-acp/session/delete","session/set_model","session/set_mode","session/set_config_option","_session/steering","hydra-acp/prompt/cancel","hydra-acp/prompt/update","hydra-acp/prompt/amend","hydra-acp/session/tool_content","hydra-acp/session/force_cancel"]);function fw(s){return lw.has(s)}function Yu(s,e,t,n){let r=[],o=a=>{for(let d of r)d(a)},i=(a,d)=>{e.handleLocalMessage(a,d,{connection:t.connection,clientId:n}).then(c=>c?s.send(c):void 0).catch(()=>{})};return s.onMessage(a=>{if("method"in a&&fw(a.method)){let d=a.params,c=typeof d?.sessionId=="string"?d.sessionId:void 0;if(c){if(gt(c)){i(a,c);return}if(a.method==="session/attach"){let u="id"in a;e.resolveLocalMiss(c).then(l=>{if(l.ok){i(a,l.foreignId);return}if(l.ambiguous&&u){s.send(Xn(a.id,R.SessionNotFound,`Session "${c}" exists on more than one remote (${l.ambiguous.join(", ")}). Address it as "<remote>:${c}".`));return}o(a)});return}}}o(a)}),{send:a=>s.send(a),onMessage:a=>r.push(a),onClose:a=>s.onClose(a),close:()=>s.close()}}var hr=class{constructor(e,t=gw,n){this.store=e;this.dial=t;this.localMiss=n}store;dial;localMiss;attachments=new Map;async resolveLocalMiss(e){if(!this.localMiss)return{ok:!1};if(await this.localMiss.resolvesLocally(e))return{ok:!1};let t=this.localMiss.cache.findByLocalId(e);return t.length===0?{ok:!1}:t.length>1?{ok:!1,ambiguous:t.map(n=>n.name)}:{ok:!0,foreignId:Je(t[0])}}async handleLocalMessage(e,t,n){let r="id"in e,o=r?e.id:void 0,i=gt(t);if(!i)return r?Xn(o,R.SessionNotFound,`not a federated session id: ${t}`):void 0;let a=Qu(n.clientId,t),d={...e.params,sessionId:i.localId};if(e.method==="session/attach"){let u=this.store.get(i.name);if(!u)return r?Xn(o,R.SessionNotFound,`No remote named "${i.name}". Run \`hydra remote add\` first.`):void 0;let l=this.attachments.get(a);l&&(this.attachments.delete(a),l.peerConnection.close().catch(()=>{}));let p;try{p=await this.dial(u)}catch(m){return r?Xn(o,R.InternalError,`Could not reach remote "${i.name}": ${m.message}`):void 0}let f={peerConnection:p,localId:i.localId,target:n};this.wireAttachment(i.name,f);let h;try{h=await p.request("session/attach",d)}catch(m){return p.close().catch(()=>{}),r?wi(o,m):void 0}this.attachments.set(a,f);let k=h&&typeof h.sessionId=="string"?{...h,sessionId:t}:h;return r?{jsonrpc:"2.0",id:o,result:k}:void 0}let c=this.attachments.get(a);if(!c)return r?Xn(o,R.SessionNotFound,`"${t}" is not attached through this daemon.`):void 0;if(e.method==="session/detach"){let u,l;try{u=await c.peerConnection.request("session/detach",d)}catch(p){l=p}return this.attachments.delete(a),c.peerConnection.close().catch(()=>{}),l?r?wi(o,l):void 0:r?{jsonrpc:"2.0",id:o,result:u??{}}:void 0}if(r)try{let u=await c.peerConnection.request(e.method,d);return{jsonrpc:"2.0",id:o,result:u}}catch(u){return wi(o,u)}await c.peerConnection.notify(e.method,d).catch(()=>{})}detachClient(e){for(let[t,n]of[...this.attachments.entries()])n.target.clientId===e&&(this.attachments.delete(t),n.peerConnection.request("session/detach",{sessionId:n.localId}).catch(()=>{}),n.peerConnection.close().catch(()=>{}))}wireAttachment(e,t){let{peerConnection:n,localId:r,target:o}=t,i=Je({name:e,localId:r}),a=()=>{this.attachments.delete(Qu(o.clientId,i))};n.onAnyNotification((d,c)=>{let u=d;!u||u.sessionId!==r||(c==="hydra-acp/session/closed"&&a(),o.connection.notify(c,{...u,sessionId:i}).catch(()=>{}))}),n.onRequest("hydra-acp/session/request_permission",async d=>{let c=d;if(!c||c.sessionId!==r)throw{code:R.MethodNotFound,message:"unexpected sessionId"};return o.connection.request("hydra-acp/session/request_permission",{...c,sessionId:i})}),n.onClose(()=>{a(),o.connection.notify("hydra-acp/session/closed",{sessionId:i}).catch(()=>{})})}};function Qu(s,e){return`${s} ${e}`}function Xn(s,e,t){return{jsonrpc:"2.0",id:s,error:{code:e,message:t}}}function wi(s,e){let t=e,n=typeof t?.code=="number"?t.code:R.InternalError,r=typeof t?.message=="string"?t.message:String(e??"forward failed");return{jsonrpc:"2.0",id:s,error:{code:n,message:r,...t?.data!==void 0?{data:t.data}:{}}}}var pw=1e4;async function gw(s){let t=`${Ae(s.host)?"ws":"wss"}://${s.host}:${s.port}/acp`,n=await Ku(t,["acp.v1",`hydra-acp-token.${s.token}`],pw);return new qe(mr(n))}var mw=3e4,hw=5e3,yr=class{constructor(e,t={}){this.store=e;this.opts=t}store;opts;snapshots=new Map;timer;start(){this.timer||(this.checkAll(),this.timer=setInterval(()=>{this.checkAll()},this.opts.intervalMs??mw),this.timer.unref?.())}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}get(e){return this.snapshots.get(e)}markOk(e,t){this.snapshots.set(e,{status:"ok",checkedAt:new Date().toISOString(),...t?{system:t}:{}})}forget(e){this.snapshots.delete(e)}async checkAll(){let e=this.opts.fetchImpl??fetch;await Promise.allSettled(this.store.list().map(async t=>{let n=this.store.get(t.name);if(!n)return;let r=new AbortController,o=setTimeout(()=>r.abort(),hw);try{let i=await fr({host:n.host,port:n.port,token:n.token,fetchImpl:e,signal:r.signal});if(i.kind==="ok"){this.snapshots.set(t.name,{status:"ok",checkedAt:new Date().toISOString(),...i.system?{system:i.system}:{}});return}if(i.kind==="unauthorized"){this.snapshots.set(t.name,{status:"unauthorized",checkedAt:new Date().toISOString()});return}if(i.kind==="error")throw new Error(i.message);let d=`${Ae(n.host)?"http":"https"}://${n.host}:${n.port}/v1/auth/verify`,c=await e(d,{headers:{Authorization:`Bearer ${n.token}`},signal:r.signal});this.snapshots.set(t.name,{status:c.ok?"ok":"unauthorized",checkedAt:new Date().toISOString()})}catch(i){this.snapshots.set(t.name,{status:"unreachable",checkedAt:new Date().toISOString(),error:i.message})}finally{clearTimeout(o)}}))}};Yn();import{z as Xu}from"zod";var yw=Xu.object({sessionLabel:Xu.string().min(1).max(256)});function Zu(s,e){s.post("/v1/process-tokens",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=yw.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}let o=e.processRegistry.mint(r.sessionLabel,"script");return n.code(201).send({token:o})}),s.delete("/v1/process-tokens/:sessionLabel",async(t,n)=>t.authIdentity!=="service"?n.code(403).send({error:"Requires the service token"}):(e.processRegistry.revoke(t.params.sessionLabel),n.code(204).send()))}import{nanoid as ki}from"nanoid";import{randomBytes as rl}from"crypto";import*as ol from"os";import*as il from"path";var ww=200;function kw(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e[le];if(!t||typeof t!="object"||Array.isArray(t))return;let n=t.sentBy;if(!n||typeof n!="object"||Array.isArray(n))return;let r=n,o={};if(typeof r.sessionId=="string"&&r.sessionId.length>0&&(o.sessionId=r.sessionId),typeof r.label=="string"&&r.label.length>0&&(o.label=r.label.slice(0,ww)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function el(s,e,t){let n=kw(s);if(!n)return;let r={};if(n.label!==void 0&&(r.fromLabel=n.label),n.awaiting===!0&&(r.awaiting=!0),n.sessionId!==void 0){let o=await e.resolveCanonicalId(n.sessionId)??n.sessionId,i=await e.getOne(o);if(i){r.fromSession=o,i.title&&(r.fromSessionTitle=i.title);let a=e.get(o)?.currentPromptDepth;r.depth=(a??0)+1}else t?.(n.sessionId)}if(!(r.fromSession===void 0&&r.fromLabel===void 0))return r}var Zn=new Map;function tl(s,e){let t=Zn.get(s);t||(t=new Set,Zn.set(s,t)),t.add(e);let n=!1;return()=>{if(n)return;n=!0;let r=Zn.get(s);r&&(r.delete(e),r.size===0&&Zn.delete(s))}}function nl(s,e){if(s===e)return!0;let t=new Set,n=[e];for(;n.length>0;){let r=n.pop();if(t.has(r))continue;t.add(r);let o=Zn.get(r);if(o){if(o.has(s))return!0;for(let i of o)n.push(i)}}return!1}function O(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function Aw(s){if(!s||typeof s!="object")return 512;let n=s.params?.update;if(!n)return 512;let r=512,o=n.content;if(typeof o=="string")r+=o.length;else if(o&&typeof o=="object"){let a=o;typeof a.text=="string"&&(r+=a.text.length),typeof a.data=="string"&&(r+=a.data.length)}let i=n.toolCall;if(i&&(typeof i.rawInput=="string"?r+=i.rawInput.length:i.rawInput&&typeof i.rawInput=="object"&&(r+=256),typeof i.rawOutput=="string"?r+=i.rawOutput.length:i.rawOutput&&typeof i.rawOutput=="object"&&(r+=256),Array.isArray(i.content)))for(let a of i.content){if(!a||typeof a!="object")continue;let d=a;if(typeof d.text=="string"&&(r+=d.text.length),d.content&&typeof d.content=="object"){let c=d.content;typeof c.text=="string"&&(r+=c.text.length)}}return r}function Ee(s,e,t){let n=s.get(e);if(!n)throw O(R.SessionNotFound,t??`session ${e} not found`);return n}async function Mt(s,e){let t=on(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=rl(32).toString("hex"),r=s.mcpTokenRegistry.reserve(n),o={name:"hydra-acp-recall",type:"http",url:`${s.getDaemonOrigin()}/mcp/hydra-acp-recall`,headers:[{name:"Authorization",value:`Bearer ${n}`}]});let a=[...t?.descriptors??[],...o!==void 0?[o]:[]],d=ai({baselineMcpServers:void 0,stdinEnabled:!1,deps:s}),c;try{c=await s.manager.resurrect({...e,mcpServers:a,...d?{mintMcpServersForSwap:d}:{}})}catch(u){throw t!==void 0&&t.abandon(u instanceof Error?u:void 0),r!==void 0&&r.abandon(u instanceof Error?u:void 0),u}if(t!==void 0&&t.bindToSession(c),n!==void 0&&r!==void 0&&s.mcpTokenRegistry!==void 0){let u=n,l=s.mcpTokenRegistry;r.complete(c),c.onClose(()=>{l.unbind(u)})}return Ow(c,s),dl(c.sessionId,s),c}function al(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=Zc({headers:n.headers,url:n.url});if(!r||!await e.validator.validate(r)){t.close(4401,"Unauthorized");return}let o=e.processRegistry?.resolve(r),i=`hydra_client_${ki(12)}`,a=mr(t),d={},c=e.foreignSessions?Yu(a,e.foreignSessions,d,i):a,u=new qe(c);d.connection=u;let l={clientId:i,processIdentity:o,attached:new Map};u.setParamsRewriter(m=>{if(m===null||typeof m!="object")return m;let g=m.sessionId;if(typeof g!="string"||l.attached.has(g))return m;let y=ye+g;return l.attached.has(y)?{...m,sessionId:y}:m}),u.onClose(()=>{for(let m of l.attached.values())e.manager.get(m.sessionId)?.detach(m.clientId);l.attached.clear(),e.foreignSessions?.detachClient(i)});let p=(m,g)=>{if(l.attached.get(m)?.readonly)throw O(R.PermissionDenied,`${g} not permitted on a read-only attachment`)};if(u.onRequest("initialize",async m=>{let g=ha.parse(m??{});g.clientInfo?.name&&(l.clientInfo={name:g.clientInfo.name,...g.clientInfo.version!==void 0?{version:g.clientInfo.version}:{}});let y=g.clientInfo?.version;return y&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,y):e.onTransformerVersion?.(o.name,y)),$w()}),o&&e.extensionCommands){let m=e.extensionCommands;u.onRequest("hydra-acp/commands/register",async g=>{let y=g??{},w=Array.isArray(y.commands)?y.commands.map(v=>{if(!v||typeof v!="object")return;let S=v;if(typeof S.verb!="string")return;let b={verb:S.verb};return typeof S.argsHint=="string"&&(b.argsHint=S.argsHint),typeof S.description=="string"&&(b.description=S.description),b}).filter(v=>v!==void 0):[];return m.register(o.name,u,w),{ok:!0,registered:w.length}}),u.onClose(()=>{m.clear(o.name)})}if(o&&e.extensionMcp){let m=e.extensionMcp;u.onRequest("hydra-acp/mcp_tools/register",async y=>{let w=y??{},v=typeof w.instructions=="string"?w.instructions:void 0,S=Array.isArray(w.tools)?w.tools.map(b=>{if(!b||typeof b!="object")return;let I=b;if(typeof I.name!="string"||I.name.length===0||typeof I.description!="string"||I.inputSchema===null||typeof I.inputSchema!="object")return;let A={name:I.name,description:I.description,inputSchema:I.inputSchema};return I.outputSchema!==null&&typeof I.outputSchema=="object"&&(A.outputSchema=I.outputSchema),A}).filter(b=>b!==void 0):[];if(S.length===0)throw new Error("register_mcp_tools requires at least one tool");return m.register(o.name,u,v,S),{ok:!0,registered:S.length}});let g=y=>{let w=y??{};if(typeof w.sessionId!="string"||w.sessionId.length===0)throw O(R.InvalidParams,"sessionId is required");return w.sessionId};if(u.onRequest("hydra-acp/session/extension_state/get",async y=>{let w=g(y),v=y??{};if(typeof v.key!="string"||v.key.length===0)throw O(R.InvalidParams,"key is required");if(!e.manager)throw O(R.InternalError,"manager not wired");return{value:await e.manager.getExtensionStateKey(w,o.name,v.key)??null}}),u.onRequest("hydra-acp/session/extension_state/list",async y=>{let w=g(y);if(!e.manager)throw O(R.InternalError,"manager not wired");return{state:await e.manager.getExtensionState(w,o.name)}}),u.onRequest("hydra-acp/session/extension_state/set",async y=>{let w=g(y),v=y??{};if(typeof v.key!="string"||v.key.length===0)throw O(R.InvalidParams,"key is required");if(v.value===void 0)throw O(R.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw O(R.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(w,o.name,v.key,v.value)}catch(S){throw O(R.InvalidParams,S.message)}return{ok:!0}}),u.onRequest("hydra-acp/session/extension_state/delete",async y=>{let w=g(y),v=y??{};if(typeof v.key!="string"||v.key.length===0)throw O(R.InvalidParams,"key is required");if(!e.manager)throw O(R.InternalError,"manager not wired");return await e.manager.deleteExtensionStateKey(w,o.name,v.key),{ok:!0}}),e.extensionMcpControls){let y=e.extensionMcpControls;u.onRequest("hydra-acp/mcp_tools/refresh_session",async w=>{let v=w??{};if(typeof v.sessionId!="string"||v.sessionId.length===0)throw O(R.InvalidParams,"refresh_session requires sessionId");return await y.notifyToolListChanged(v.sessionId,o.name),{ok:!0}})}u.onClose(()=>{m.clear(o.name)})}o?.kind==="transformer"&&(u.onRequest("hydra-acp/transformer/initialize",async m=>{let g=m??{},y=Array.isArray(g.intercepts)?g.intercepts.filter(w=>typeof w=="string"):[];if(e.transformers&&(e.transformers.registerConnection(o.name,u,y),e.manager?.defaultTransformers.includes(o.name))){let w=e.transformers.resolveChain([o.name])[0];if(w)for(let v of e.manager.liveSessions())v.addTransformer(w)}return{ack:!0}}),u.onClose(()=>{e.transformers?.deregisterConnection(o.name)}),u.onRequest("hydra-acp/message/emit",async m=>{let g=m??{},y=typeof g.sessionId=="string"?g.sessionId:void 0,w=typeof g.method=="string"?g.method:void 0,v=g.envelope,S=g.route;if(!y)throw O(-32602,"emit_message requires sessionId");if(!w&&S!=="client_broadcast")throw O(-32602,"emit_message requires method");let b=Ee(e.manager,y),I=typeof g.respondsTo=="string"?g.respondsTo:void 0;if(I)return b.dischargeClaim(I,v),{ok:!0};if(S==="chain")return{ok:!0,response:await b.emitToChain(o.name,w,v)};if(S==="queue"){if(w!=="session/prompt")throw O(-32602,'route "queue" only supports method "session/prompt"');return{ok:!0,response:await b.emitToQueue(o.name,v)}}if(S==="daemon")return{ok:!0,response:await b.emitToChain(o.name,w,v)};if(S==="client_broadcast"){if(!v||typeof v!="object")throw O(-32602,"client_broadcast requires an envelope object");return b.broadcastClientUpdate(v),{ok:!0}}throw O(-32602,`unsupported route: ${JSON.stringify(S)}`)}),u.onRequest("hydra-acp/session/request_permission",async m=>{let g=m??{},y=typeof g.sessionId=="string"?g.sessionId:void 0;if(!y)throw O(-32602,"hydra-acp/session/request_permission requires sessionId");return Ee(e.manager,y).requestPermissionFromClients(g)}),u.onRequest("hydra-acp/transformer/attach",async m=>Ew(m,o.name,e)),u.onRequest("hydra-acp/child_session/spawn",async m=>{let g=m??{},y=typeof g.agentId=="string"?g.agentId:void 0,w=typeof g.cwd=="string"?g.cwd:void 0,v=typeof g.parentSessionId=="string"?g.parentSessionId:void 0,S=dt(g._meta??void 0),b=S.title,I=S.model,A=S.workspace;if(!w&&v){let L=e.manager.get(v);L&&(w=L.cwd)}if(!w)throw O(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let x=await mn(w),T=y??x.agentId??e.defaultAgent,M=await e.registry?.getAgent(T),N=Gr(x.configDefaults,M??{id:T})?.value,B=I??N?.model,q=typeof g.interactive=="boolean"?g.interactive:!1,V=await e.manager.create({agentId:T,cwd:w,parentSessionId:v,interactive:q,transformChain:[],title:b,model:B,configDefaults:N,...A!==void 0?{workspace:A}:{}});return{childSessionId:V.sessionId,...V.workspace!==void 0||V.workspaceError!==void 0?{_meta:{[le]:{...V.workspace!==void 0?{workspaceInfo:V.workspace}:{},...V.workspaceError!==void 0?{workspaceError:V.workspaceError}:{}}}}:{}}}));let f=async(m,g)=>{let y=m??{};if(typeof y.sessionId!="string")throw O(R.InvalidParams,"fork_session requires sessionId");let w=typeof y.forkAt=="string"?y.forkAt:void 0,v=typeof y.cwd=="string"?y.cwd:void 0,S=typeof y.agentId=="string"?y.agentId:void 0,b=g?void 0:typeof y.mode=="string"&&(y.mode==="verbatim"||y.mode==="synthesis")?y.mode:void 0,I=typeof y.model=="string"&&y.model.length>0?y.model:void 0,A;if(g){let B=y.selection;if(B!==void 0&&(typeof B.text!="string"||B.text.length===0))throw O(R.InvalidParams,"selection.text must be a non-empty string");A={...B!==void 0?{selection:{text:B.text,...typeof B.responsePartId=="string"?{responsePartId:B.responsePartId}:{}}}:{}}}let x=await e.manager.forkSession(y.sessionId,{...A!==void 0?{side:A}:{},...w!==void 0?{forkAt:w}:{},...v!==void 0?{cwd:v}:{},...S!==void 0?{agentId:S}:{},...b!==void 0?{mode:b}:{},...I!==void 0?{model:I}:{}}),T=e.manager.get(x.sessionId);if(!T){let B=await e.manager.loadFromDisk(x.sessionId);if(!B)throw O(R.InternalError,`fork ${x.sessionId} vanished before it could be attached`);T=await Mt(e,{...B,onInstallProgress:wr(u)})}dn(l,T,T.sessionId);let M=vt(u,T,l),{entries:N}=await T.attach(M,"full");l.attached.set(T.sessionId,{sessionId:T.sessionId,clientId:M.clientId,readonly:!1});for(let B of N){if(u.isClosed())break;await u.notify(B.method,We(Be(B.params,B.recordedAt),B.seq)).catch(()=>{})}return{...x,sessionId:T.sessionId}};u.onRequest("hydra-acp/session/fork",m=>f(m,!1)),u.onRequest("hydra-acp/session/side",m=>f(m,!0)),u.onRequest("hydra-acp/session/rewind",async m=>{let g=m??{};if(typeof g.sessionId!="string")throw O(R.InvalidParams,"hydra-acp/session/rewind requires sessionId");let y=g.keepThrough;if(y!==null&&(typeof y!="string"||y.length===0))throw O(R.InvalidParams,"keepThrough must be a non-empty messageId, or null to drop every turn");let w=await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId;try{return await e.manager.rewindSession(w,y)}catch(v){let S=v;throw O(S.code??R.InternalError,S.message)}}),u.onRequest("session/fork",async m=>{let g=m??{};if(typeof g.sessionId!="string")throw O(R.InvalidParams,"session/fork requires sessionId");let y=typeof g.cwd=="string"?g.cwd:void 0,w=await e.manager.forkSession(g.sessionId,{...y!==void 0?{cwd:y}:{},mode:"verbatim"}),v=e.manager.get(w.sessionId);if(!v){let I=await e.manager.loadFromDisk(w.sessionId);if(!I)throw O(R.InternalError,`fork ${w.sessionId} vanished before it could be attached`);v=await Mt(e,{...I,onInstallProgress:wr(u)})}dn(l,v,v.sessionId);let S=vt(u,v,l),{entries:b}=await v.attach(S,"full");l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:S.clientId,readonly:!1});for(let I of b){if(u.isClosed())break;await u.notify(I.method,We(Be(I.params,I.recordedAt),I.seq)).catch(()=>{})}return{sessionId:v.sessionId}});let h=async(m,g)=>{let y=m??{};if(typeof y.sessionId!="string")throw O(R.InvalidParams,`${g} requires sessionId`);let w=await e.manager.resolveCanonicalId(y.sessionId)??y.sessionId,v=e.manager.get(w);if(v)return await v.close({deleteRecord:!0,by:`session/delete ${l.clientId}`}),await e.manager.waitForDeletion(w),await e.manager.hasRecord(w)&&await e.manager.deleteRecord(w),{id:w,existed:!0};let S=await e.manager.deleteRecord(w);return{id:w,existed:S}};u.onRequest("session/delete",async m=>(await h(m,"session/delete"),{})),u.onRequest("session/close",async m=>{let g=m??{};if(typeof g.sessionId!="string")throw O(R.InvalidParams,"session/close requires sessionId");p(g.sessionId,"session/close");let y=await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId,w=e.manager.get(y);if(w)return await w.close({deleteRecord:!1,by:`session/close ${l.clientId}`+(l.processIdentity?` (${l.processIdentity.name})`:"")}),{};if(await e.manager.hasRecord(y))return{};throw O(R.SessionNotFound,`session ${y} not found`)}),u.onRequest("hydra-acp/session/delete",async m=>{let{id:g,existed:y}=await h(m,"hydra-acp/session/delete");if(!y)throw O(R.SessionNotFound,`session ${g} not found`);return{deleted:!0,sessionId:g}}),o?.kind==="transformer"&&(u.onRequest("hydra-acp/child_session/await",async m=>{let g=m??{},y=typeof g.childSessionId=="string"?g.childSessionId:void 0,w=g.until==="idle"?"idle":"turn_complete",v=typeof g.timeoutMs=="number"?Math.min(g.timeoutMs,18e5):3e5;if(!y)throw O(-32602,"await_child requires childSessionId");let S=Ee(e.manager,y,`child session ${y} not found`);return new Promise(b=>{let x=[],T=[],M=0,N=!1,B,q,V=!1,L=()=>{V||(V=!0,clearTimeout(W),B?.(),q?.(),b(N?{entries:x,truncated:!0}:{entries:x}))};B=S.onBroadcast(Q=>{let oe=Aw(Q);for(x.push(Q),T.push(oe),M+=oe;x.length>0&&(x.length>1e3||M>1048576);)x.shift(),M-=T.shift()??0,N=!0;w==="turn_complete"&&Q.params?.update?.sessionUpdate==="turn_complete"&&L()});let W=setTimeout(L,v);typeof W.unref=="function"&&W.unref(),q=S.onClose(()=>L())})}),u.onRequest("hydra-acp/child_session/close",async m=>{let g=m??{},y=typeof g.childSessionId=="string"?g.childSessionId:void 0;if(!y)throw O(-32602,"close_child_session requires childSessionId");let w=e.manager.get(y);return w&&await w.close({deleteRecord:!1,by:`child_session/close ${l.clientId}`}),{ok:!0}}),u.onRequest("hydra-acp/attention/set",async m=>Pw(m,o.name,e)),u.onRequest("hydra-acp/attention/clear",async m=>Mw(m,o.name,e)),u.onRequest("hydra-acp/connection/keep_alive",async m=>{let g=m??{},y=typeof g.token=="string"?g.token:void 0,w=typeof g.sessionId=="string"?g.sessionId:void 0,v=typeof g.estimatedRemainingMs=="number"?g.estimatedRemainingMs:void 0;return y&&w&&e.manager.get(w)?.keepAliveClaim(y,v),{ok:!0}})),u.onRequest("hydra-acp/session/tool_content",async m=>{let g=m??{};if(typeof g.sessionId!="string"||typeof g.hash!="string")throw O(R.InvalidParams,"hydra-acp/session/tool_content requires sessionId and hash");let y=await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId,w=await e.manager.loadToolBlob(y,g.hash);if(w===null)throw O(R.SessionNotFound,"tool content not found");return{content:w}}),u.onRequest("authenticate",async m=>Cw(m,e)),u.onRequest("logout",async m=>Rw(m,e)),u.onRequest("session/new",async m=>{let g=new Wt,y=ya.parse(m),w=dt(m?._meta),v=Array.isArray(w.transformers)&&w.transformers.every(te=>typeof te=="string")?w.transformers:e.manager.defaultTransformers??[],S=e.transformers?.resolveChain(v)??[],b=await mn(y.cwd),I=w.agentId??b.agentId??e.defaultAgent,A=await e.registry?.getAgent(I),x=Gr(b.configDefaults,A??{id:I})?.value,T,M,N=y.mcpServers;if(w.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){T=rl(32).toString("hex"),M=e.mcpTokenRegistry.reserve(T);let Pe={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${T}`}]};N=[...y.mcpServers??[],Pe]}let B,q,V=on(e);V!==void 0&&(N=[...N??[],...V.descriptors]);let L=ai({baselineMcpServers:y.mcpServers,stdinEnabled:w.mcpStdin===!0,deps:e});g.mark("ws.prepare");let W;try{W=await e.manager.create({timer:g,cwd:y.cwd,agentId:I,mcpServers:N,title:w.title,agentArgs:w.agentArgs,model:w.model??x?.model,configDefaults:x,onInstallProgress:wr(u),transformChain:S,originatingClient:l.clientInfo,...w.interactive!==void 0?{interactive:w.interactive}:{},...w.env!==void 0?{forwardedEnv:w.env}:{},...w.workspace!==void 0?{workspace:w.workspace}:{},...L?{mintMcpServersForSwap:L}:{}})}catch(te){throw M!==void 0&&M.abandon(te instanceof Error?te:void 0),q!==void 0&&q.abandon(te instanceof Error?te:void 0),V!==void 0&&V.abandon(te instanceof Error?te:void 0),te}if(T!==void 0&&M!==void 0&&e.mcpTokenRegistry!==void 0){let te=T,Pe=e.mcpTokenRegistry;M.complete(W),W.onClose(()=>{Pe.unbind(te)})}if(B!==void 0&&q!==void 0&&e.mcpTokenRegistry!==void 0){let te=B,Pe=e.mcpTokenRegistry;q.complete(W),W.onClose(()=>{Pe.unbind(te)})}V!==void 0&&V.bindToSession(W),g.mark("ws.bind-mcp"),dl(W.sessionId,e);let Q,oe;try{dn(l,W,W.sessionId),Q=vt(u,W,l),{entries:oe}=await W.attach(Q,"full")}catch(te){throw await W.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),te}l.attached.set(W.sessionId,{sessionId:W.sessionId,clientId:Q.clientId,readonly:!1}),g.mark("ws.attach"),e.manager.logInfo(`session/new timing agent=${I} session=${W.sessionId} ${g.summary()}`),setImmediate(()=>{(async()=>{for(let te of oe){if(u.isClosed())break;await u.notify(te.method,We(Be(te.params,te.recordedAt),te.seq)).catch(()=>{})}})()});let xe=kr(W),et=vr(W);return{sessionId:W.sessionId,...xe?{modes:xe}:{},...et?{models:et}:{},configOptions:W.buildConfigOptions(),_meta:br(e.manager,W,{clientId:Q.clientId})}}),u.onRequest("session/attach",async m=>{let g=ka.parse(m),y=g.clientInfo?.version;y&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,y):e.onTransformerVersion?.(o.name,y));let w=dt(g._meta),v=w.resume,S=w.readonly===!0,b=w.env;s.log.info(`session/attach sessionId=${g.sessionId} hasResumeHints=${!!v} readonly=${S}`);let I=v?g.sessionId:await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId,A=e.manager.get(I);if(!A&&S){let L=await e.manager.loadFromDisk(I);if(!L)throw O(R.SessionNotFound,`session ${g.sessionId} not found`);let W=Ut(await e.manager.loadHistory(I,{...w.historyLimit!==void 0?{maxEntries:w.historyLimit}:{}}),L.side),Q=g.clientId??`cli_${ki(8)}`;l.attached.set(L.hydraSessionId,{sessionId:L.hydraSessionId,clientId:Q,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${L.hydraSessionId} clientId=${Q} attachedCount=${l.attached.size} replayed=${W.length}`);for(let oe of W)await u.notify(oe.method,We(Be(oe.params,oe.recordedAt),oe.seq)).catch(()=>{});return{sessionId:L.hydraSessionId,clientId:Q,connectedClients:[Q],historyPolicy:"full",replayed:W.length,_meta:_w(L)}}let x=!A;if(!A){let L=await e.manager.loadFromDisk(I),W=await xw(I,v,L?.upstreamSessionId,e.manager);W.kind==="ignore"&&s.log.warn(W.logMessage);let Q=L;if(v&&W.kind==="honor"&&(Q={...L,hydraSessionId:g.sessionId,upstreamSessionId:v.upstreamSessionId,agentId:v.agentId,cwd:L?.workspace?.path??v.cwd,...v.title!==void 0?{title:v.title}:{},...v.agentArgs!==void 0?{agentArgs:v.agentArgs}:{}}),!Q)throw O(R.SessionNotFound,`session ${g.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(Q.agentId,Q.upstreamSessionId))throw O(R.SessionNotFound,`session ${g.sessionId} was deleted`);let oe=Q.originatingClient?Q:{...Q,originatingClient:l.clientInfo},xe=b!==void 0?{...oe,forwardedEnv:b}:oe;A=await Mt(e,{...xe,onInstallProgress:wr(u)})}dn(l,A,A.sessionId);let T=vt(u,A,l,g.clientInfo,g.clientId),M=w.replayMode==="drip",{entries:N,appliedPolicy:B}=await A.attach(T,g.historyPolicy,{afterMessageId:g.afterMessageId,afterSeq:g.afterSeq,raw:M,...w.historyLimit!==void 0?{historyLimit:w.historyLimit}:{},...w.toolContent!==void 0?{toolContent:w.toolContent}:{}});if(l.attached.set(A.sessionId,{sessionId:A.sessionId,clientId:T.clientId,readonly:S}),b!==void 0&&await e.manager.setForwardedEnv(A.sessionId,b).catch(()=>{}),s.log.info(`session/attach OK sessionId=${A.sessionId} clientId=${T.clientId} attachedCount=${l.attached.size} requestedPolicy=${g.historyPolicy} appliedPolicy=${B} replayed=${N.length} readonly=${S}${M?" replayMode=drip":""}`),M){let L=w.dripSpeed&&w.dripSpeed>0?w.dripSpeed:1,W=750;(async()=>{let Q=null;for(let oe of N){let xe=typeof oe.recordedAt=="number"?oe.recordedAt:null;if(Q!==null&&xe!==null){let et=Math.min(W,Math.max(0,(xe-Q)/L));et>0&&await new Promise(te=>setTimeout(te,et))}xe!==null&&(Q=xe);try{await u.notify(oe.method,We(Be(oe.params,xe??void 0),oe.seq))}catch{return}}})()}else for(let L=0;L<N.length&&!u.isClosed();L++){let W=N[L],Q=u.notify(W.method,We(Be(W.params,W.recordedAt),W.seq)).catch(()=>{});(L+1)%200===0&&await Q}A.replayPendingPermissions(T);let q=kr(A),V=vr(A);return{sessionId:A.sessionId,clientId:T.clientId,connectedClients:A.connectedClients(T.clientId),historyPolicy:B,replayed:N.length,...q?{modes:q}:{},...V?{models:V}:{},configOptions:A.buildConfigOptions(),_meta:br(e.manager,A,{resurrected:x})}}),u.onRequest("session/detach",async m=>{let g=va.parse(m),y=l.attached.get(g.sessionId);if(!y)throw O(R.SessionNotFound,"client not attached to that session");let w=e.manager.get(g.sessionId);return w?.detach(y.clientId),l.attached.delete(g.sessionId),w&&e.manager.reapIfOrphanedNonInteractive(g.sessionId),{sessionId:g.sessionId,_meta:{[le]:{detachStatus:"detached"}}}}),u.onRequest("session/list",async m=>{let g=ba.parse(m??{});return{sessions:(await e.manager.list({cwd:g.cwd})).filter(S=>S.originatingClient?.name!==Ds).map(Sa)}}),u.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw O(R.InternalError,"agent registry unavailable");return Ht(e.registry)}),u.onRequest("hydra-acp/agents/auth_methods",async m=>{let g=m??{};if(typeof g.agentId!="string"||g.agentId.length===0)throw O(R.InvalidParams,"hydra-acp/agents/auth_methods requires a non-empty agentId string");return{authMethods:(await e.manager.bootstrapAgentForAuth(g.agentId)).authMethods??[]}}),u.onRequest("session/prompt",async m=>{let g=Ia.parse(m);p(g.sessionId,"session/prompt");let y=await el(g,e.manager,b=>{s.log.warn(`session/prompt: dropping unknown sentBy.sessionId=${b} sessionId=${g.sessionId}`)});if(y?.fromSession!==void 0){if((y.depth??0)>3)throw s.log.warn(`session/prompt: refusing depth ${y.depth} chain from ${y.fromSession} to ${g.sessionId}`),O(R.InvalidRequest,`message chain too deep (${y.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(y.awaiting===!0&&nl(y.fromSession,g.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${y.fromSession} -> ${g.sessionId}`),O(R.InvalidRequest,`would deadlock: ${g.sessionId} is already blocked waiting on ${y.fromSession}. Send with --no-wait, or let the other turn finish first.`)}let w=l.attached.get(g.sessionId);if(!w)throw s.log.warn(`session/prompt rejected: not attached sessionId=${g.sessionId} attachedKeys=[${[...l.attached.keys()].join(",")}]`),O(R.SessionNotFound,"not attached to session");let v=e.manager.get(g.sessionId);if(!v){let b=await e.manager.loadFromDisk(g.sessionId);if(!b)throw O(R.SessionNotFound,`session ${g.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${g.sessionId}`),v=await Mt(e,b);let I=vt(u,v,l,void 0,w.clientId);await v.attach(I,"none")}let S=y?.awaiting===!0&&y.fromSession!==void 0?tl(y.fromSession,g.sessionId):void 0;try{return await v.prompt(w.clientId,g,y)}finally{S?.()}});let k=m=>{let g;try{g=cs.parse(m)}catch(v){s.log.warn(`session/cancel: invalid params: ${v.message}`);return}let y=l.attached.get(g.sessionId);if(!y)return;if(y.readonly){s.log.warn(`session/cancel dropped (readonly attachment) sessionId=${g.sessionId}`);return}let w=e.manager.get(g.sessionId);w&&w.cancel(y.clientId).catch(v=>{s.log.warn(`session/cancel for ${g.sessionId}: ${v.message}`)})};u.onNotification("session/cancel",k),u.onRequest("session/cancel",async m=>{let g=cs.parse(m);return p(g.sessionId,"session/cancel"),k(m),null}),u.onRequest("hydra-acp/prompt/cancel",async m=>{let g=Ca.parse(m);return p(g.sessionId,"hydra-acp/prompt/cancel"),Ee(e.manager,g.sessionId).cancelQueuedPrompt(g.messageId)}),u.onRequest("hydra-acp/session/force_cancel",async m=>{let g=cs.parse(m);return p(g.sessionId,"hydra-acp/session/force_cancel"),Ee(e.manager,g.sessionId).forceCancel()}),u.onRequest("hydra-acp/prompt/update",async m=>{let g=Ra.parse(m);return p(g.sessionId,"hydra-acp/prompt/update"),Ee(e.manager,g.sessionId).updateQueuedPrompt(g.messageId,g.prompt)}),u.onRequest("hydra-acp/prompt/amend",async m=>{let g=xa.parse(m);p(g.sessionId,"hydra-acp/prompt/amend");let y=l.attached.get(g.sessionId);if(!y)throw O(R.SessionNotFound,"not attached to session");return Ee(e.manager,g.sessionId).amendPrompt(y.clientId,g)}),u.onRequest("_session/steering",async m=>{let g=Ta.parse(m);p(g.sessionId,"_session/steering");let y=l.attached.get(g.sessionId);if(!y)throw O(R.SessionNotFound,"not attached to session");let w=e.manager.get(g.sessionId);if(!w){let v=await e.manager.loadFromDisk(g.sessionId);if(!v)throw O(R.SessionNotFound,`session ${g.sessionId} not found`);w=await Mt(e,v);let S=vt(u,w,l,void 0,y.clientId);await w.attach(S,"none")}return w.steer(y.clientId,g)}),u.onRequest("session/resume",async m=>{let g=m??{},y=typeof g.sessionId=="string"?g.sessionId:void 0;if(!y)throw O(R.InvalidParams,"session/resume requires sessionId");let w=await e.manager.resolveCanonicalId(y)??y,v=e.manager.get(w);if(!v){let A=await e.manager.loadFromDisk(w);if(!A)throw O(R.SessionNotFound,`session ${y} not found in memory or on disk`);v=await Mt(e,A)}dn(l,v,v.sessionId);let S=vt(u,v,l);await v.attach(S,"pending_only"),l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:S.clientId,readonly:!1}),v.replayPendingPermissions(S);let b=kr(v),I=vr(v);return{sessionId:v.sessionId,...b?{modes:b}:{},...I?{models:I}:{},configOptions:v.buildConfigOptions(),_meta:br(e.manager,v,{clientId:S.clientId})}}),u.onRequest("session/load",async m=>{let g=m??{},y=typeof g.sessionId=="string"?g.sessionId:void 0;if(!y)throw O(R.InvalidParams,"session/load requires sessionId");let w=await e.manager.resolveCanonicalId(y)??y,v=e.manager.get(w);if(!v){let x=await e.manager.loadFromDisk(w);if(!x)throw O(R.SessionNotFound,`session ${y} not found in memory or on disk`);v=await Mt(e,x)}dn(l,v,v.sessionId);let S=vt(u,v,l),{entries:b}=await v.attach(S,"full");l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:S.clientId,readonly:!1});for(let x of b){if(u.isClosed())break;await u.notify(x.method,We(Be(x.params,x.recordedAt),x.seq)).catch(()=>{})}v.replayPendingPermissions(S);let I=kr(v),A=vr(v);return{sessionId:v.sessionId,...I?{modes:I}:{},...A?{models:A}:{},configOptions:v.buildConfigOptions(),_meta:br(e.manager,v,{clientId:S.clientId})}}),u.onRequest("session/set_model",async m=>{let g=m?.sessionId;typeof g=="string"&&p(g,"session/set_model");let y=Tw(m,e.manager);if(y.kind==="error")throw s.log.warn(y.logMessage),O(y.code,y.message);if(y.kind==="no_op")return s.log.warn(y.logMessage),await u.notify("session/update",{sessionId:y.sessionId,update:{sessionUpdate:"_hydra_current_model_update",currentModel:y.currentModel}}).catch(()=>{}),null;s.log.info(y.logMessage);let{modelId:w}=y,v=await y.session.forwardModelChange(w,m);return y.session.applyAgentConfigOptionResponse(v,"model"),y.session.applyModelChange(w),v}),u.onRequest("session/set_mode",async m=>{let g=m,y=g?.sessionId;if(typeof y=="string"&&p(y,"session/set_mode"),!g||typeof g.sessionId!="string")throw O(R.InvalidParams,"session/set_mode requires string sessionId");if(typeof g.modeId!="string")throw O(R.InvalidParams,"session/set_mode requires string modeId");let w=Ee(e.manager,g.sessionId),v=await w.forwardRequest("session/set_mode",m);return w.applyModeChange(g.modeId),v}),u.onRequest("session/set_config_option",async m=>{let g=m,y=b=>O(R.InvalidParams,b),w=g?.sessionId;if(typeof w=="string"&&p(w,"session/set_config_option"),!g||typeof g.sessionId!="string")throw y("session/set_config_option requires string sessionId");if(typeof g.configId!="string")throw y("session/set_config_option requires string configId");if(typeof g.value!="string")throw y("session/set_config_option requires string value");let v=Ee(e.manager,g.sessionId),S=v.buildConfigOptions().find(b=>b.id===g.configId);if(!S)throw y(`unknown configId ${JSON.stringify(g.configId)} for this session`);if(!S.options.some(b=>b.value===g.value))throw y(`value ${JSON.stringify(g.value)} is not valid for configId ${JSON.stringify(g.configId)}`);switch(g.configId){case"model":{if(g.value!==v.currentModel){let b=await v.forwardModelChange(g.value);v.applyAgentConfigOptionResponse(b,"model")}v.applyModelChange(g.value);break}case"mode":{g.value!==v.currentMode&&await v.forwardRequest("session/set_mode",{sessionId:g.sessionId,modeId:g.value}),v.applyModeChange(g.value);break}case"agent":{g.value!==v.agentId&&await v.setAgent(g.value);break}default:{let b=await v.forwardRequest("session/set_config_option",{sessionId:g.sessionId,configId:g.configId,value:g.value});v.applyAgentConfigOptionResponse(b,g.configId)&&v.broadcastConfigOptions()}}return{configOptions:v.buildConfigOptions()}}),u.setDefaultHandler(async(m,g)=>{let y=new Set(["hydra-acp/attention/set","hydra-acp/attention/clear"]),w=g.startsWith("session/"),v=g.startsWith("hydra-acp/");if(!w&&!v||m===null||typeof m!="object"||y.has(g))throw O(R.MethodNotFound,`Method not found: ${g}`);let S=m.sessionId;if(typeof S!="string")throw O(R.MethodNotFound,`Method not found: ${g}`);return p(S,g),Ee(e.manager,S).forwardRequest(g,m)})})}async function Cw(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw O(R.InvalidParams,"authenticate requires a non-empty methodId string");let n=t.methodId,r=t._meta?.["hydra-acp"],o=typeof r?.sessionId=="string"?r.sessionId:void 0,i=typeof r?.agentId=="string"?r.agentId:void 0,a=o!==void 0?e.manager.getAgentForSession(o):void 0;if(!a||!a.isAlive()){let f=i??e.defaultAgent;a=await e.manager.bootstrapAgentForAuth(f)}let d=a.authMethods??[],c=d.find(f=>f.id===n);if(!c){let f=d.map(h=>h.id);throw O(R.InvalidParams,`authenticate: methodId ${JSON.stringify(n)} is not advertised by agent ${a.agentId}; valid: [${f.map(h=>JSON.stringify(h)).join(", ")}]`)}let u=c._meta?.type,l=(()=>{let f=c._meta?.["terminal-auth"];if(f&&typeof f=="object"&&!Array.isArray(f))return f})();if((c.type??(u==="agent"||u==="terminal"?u:l!==void 0?"terminal":"agent"))==="terminal"){let f=(w,v)=>{if(!Array.isArray(w))throw O(R.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${v} must be a string[]; got ${w===null?"null":typeof w}`);for(let S of w)if(typeof S!="string")throw O(R.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${v} must be string[]; got non-string entry ${JSON.stringify(S)}`);return w},h=await e.manager.planSpawnForAgent(a.agentId),k,m;if(l?.args!==void 0){let w=typeof l.command=="string"?l.command:void 0;k=w!==void 0&&il.isAbsolute(w)?w:h.command,m=f(l.args,'_meta["terminal-auth"].args')}else{let w=c.args!==void 0?{raw:c.args,label:"args"}:c._meta?.args!==void 0?{raw:c._meta.args,label:"_meta.args"}:void 0,v=w!==void 0?f(w.raw,w.label):[];k=h.command,m=[...h.args,...v]}let g={};for(let[w,v]of Object.entries(process.env))typeof v=="string"&&(g[w]=v);Object.assign(g,h.env);let y=ol.homedir();return console.error(`[authenticate] terminal-auth requested agentId=${a.agentId} methodId=${n}`),{kind:"terminal",command:k,args:m,env:g,cwd:y}}try{return await a.connection.request("authenticate",{methodId:n})}catch(f){throw yt(f,a)}}async function Rw(s,e){let n=(s??{})._meta?.["hydra-acp"],r=typeof n?.sessionId=="string"?n.sessionId:void 0,o=typeof n?.agentId=="string"?n.agentId:void 0,i=r!==void 0?e.manager.getAgentForSession(r):void 0;if(!i||!i.isAlive()){let a=o??e.defaultAgent;i=await e.manager.bootstrapAgentForAuth(a)}return await i.connection.request("logout",{})}function wr(s){return e=>{let t={agentId:e.agentId,version:e.version,source:e.source,phase:e.phase};"receivedBytes"in e&&(t.receivedBytes=e.receivedBytes),"totalBytes"in e&&(t.totalBytes=e.totalBytes),"packageSpec"in e&&(t.packageSpec=e.packageSpec),s.notify(Ea,t).catch(()=>{})}}function kr(s){let e=s.availableModes();if(e.length===0)return;let t=e.map(r=>{let o={id:r.id,name:r.name??r.id};return r.description!==void 0&&(o.description=r.description),o});return{currentModeId:s.currentMode??e[0].id,availableModes:t}}function vr(s){let e=s.availableModels();if(e.length===0)return;let t=e.map(r=>{let o={modelId:r.modelId};return r.name!==void 0&&(o.name=r.name),r.description!==void 0&&(o.description=r.description),o});return{currentModelId:s.currentModel??e[0].modelId,availableModels:t}}async function xw(s,e,t,n){return e?await n.isRetiredGeneration(s,e.upstreamSessionId)?{kind:"ignore",logMessage:`session/attach ignoring stale resume hint sessionId=${s} hintUpstream=${e.upstreamSessionId} recordUpstream=${t} (retired generation)`}:{kind:"honor"}:{kind:"none"}}function Tw(s,e){if(!s||typeof s!="object")return{kind:"error",code:R.InvalidParams,message:"session/set_model requires params",logMessage:"session/set_model rejected: params not an object"};let t=s;if(typeof t.sessionId!="string")return{kind:"error",code:R.InvalidParams,message:"session/set_model requires string sessionId",logMessage:"session/set_model rejected: missing/non-string sessionId"};if(typeof t.modelId!="string")return{kind:"error",code:R.InvalidParams,message:"session/set_model requires string modelId",logMessage:`session/set_model rejected: missing/non-string modelId sessionId=${t.sessionId}`};let n=e.get(t.sessionId);if(!n)return{kind:"error",code:R.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=Vt(t.modelId,r);if(o.kind==="none")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model passthrough (no availableModels) sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="exact")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model accepted sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="resolved")return{kind:"ok",session:n,modelId:o.modelId,logMessage:`session/set_model resolved sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} \u2192 ${JSON.stringify(o.modelId)}`};let i=r.map(d=>d.modelId).join(", "),a=o.kind==="ambiguous"?`ambiguous (trailing-segment matches [${o.candidates.join(", ")}])`:"not in availableModels";return n.currentModel!==void 0&&n.currentModel.length>0?{kind:"no_op",session:n,sessionId:t.sessionId,currentModel:n.currentModel,logMessage:`session/set_model no_op (resyncing client) sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} ${a} actual=${JSON.stringify(n.currentModel)} agentId=${n.agentId} known=[${i}]`}:{kind:"error",code:R.InvalidParams,message:`model "${t.modelId}" is ${a==="not in availableModels"?"not in this session's availableModels":a} (agent ${n.agentId}); known models: ${i}`,logMessage:`session/set_model rejected sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)} ${a} agentId=${n.agentId} known=[${i}] (no current model to fall back to)`}}async function Ew(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw O(R.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw O(R.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw O(R.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return Ee(t.manager,r).addTransformer(o),{ok:!0}}async function Pw(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(R.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw O(R.InvalidParams,"hydra-acp/attention/set requires string reason");return Ee(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function Mw(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(R.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw O(R.InvalidParams,"hydra-acp/attention/clear requires string reason");return Ee(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function _w(s){let e={sessionId:s.hydraSessionId,upstreamSessionId:s.upstreamSessionId,cwd:s.cwd,workspace:s.workspace,title:s.title,agentId:s.agentId,currentModel:s.currentModel,currentUsage:Dn(s.currentUsage),forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:s.interactive,updatedAt:s.createdAt??new Date().toISOString(),attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1},t={currentMode:s.currentMode,agentArgs:s.agentArgs,availableCommands:s.agentCommands,availableModes:s.agentModes,availableModels:s.agentModels,armedTaskList:[]};return{[le]:ds(e,t)}}function br(s,e,t={}){let n=s.liveListEntry(e),r={clientId:t.clientId,currentMode:e.currentMode,agentArgs:e.agentArgs,availableCommands:e.mergedAvailableCommands(),availableModes:e.availableModes(),availableModels:e.availableModels(),turnStartedAt:e.turnStartedAt,agentCapabilities:e.agentCapabilities,queue:e.queueSnapshot(),armedTaskList:e.armedBackgroundTasks,...t.resurrected===!0?{resurrected:!0}:{}};return kn(e.agentMeta,ds(n,r))}function $w(){return{protocolVersion:1,agentInfo:{name:"hydra",version:ue},agentCapabilities:{promptCapabilities:{image:!0,audio:!0,embeddedContext:!0},mcpCapabilities:{http:!0,sse:!0},loadSession:!0,auth:{logout:{}},sessionCapabilities:{attach:{},list:{},resume:{},delete:{},close:{},fork:{}}},authMethods:[{id:"proxy",name:"Hydra proxy",type:"agent",description:"Hydra proxies authentication to the downstream agent selected per session"}],_meta:{...kn(void 0,{prompt:{queueing:!0,cancelling:!0,updating:!0,amending:!0,pipelining:!1},agents:{list:!0,installProgress:!0},session:{fork:{forkAt:!0,agentSwap:!0,synthesis:!0,model:!0},side:{selection:!0},rewind:{}}}),steering:{supported:!0}}}}function Ow(s,e){if(!(!e.transformers||!e.manager))for(let t of e.manager.defaultTransformers){let n=e.transformers.resolveChain([t])[0];n&&s.addTransformer(n)}}function dl(s,e){if(!e.transformers)return;let t=e.transformers.interestedIn("lifecycle:session.starting");for(let n of t)n.connection.notify("hydra-acp/transformer/session_event",{event:"session.starting",sessionId:s}).catch(()=>{})}function vt(s,e,t,n,r){return{clientId:r??`cli_${ki(8)}`,connection:s,clientInfo:n}}function dn(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var Sr=class{byToken=new Map;reserve(e){if(this.byToken.has(e))throw new Error("mcp token already bound");let t,n,r=new Promise((i,a)=>{t=i,n=a});r.catch(()=>{});let o={session:void 0,sessionReady:r,disposers:[]};return this.byToken.set(e,o),{complete:i=>{o.session=i,t(i)},abandon:i=>{this.byToken.delete(e),n(i??new Error("mcp token reservation abandoned"))}}}bind(e,t){let{complete:n}=this.reserve(e);n(t)}lookup(e){return this.byToken.get(e)}addDisposer(e,t){let n=this.byToken.get(e);n!==void 0&&n.disposers.push(t)}async unbind(e){let t=this.byToken.get(e);if(t!==void 0){this.byToken.delete(e);for(let n of t.disposers)try{await n()}catch{}}}size(){return this.byToken.size}};import{randomUUID as Nw}from"crypto";import{McpServer as Dw}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Hw}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as we}from"zod";import{isInitializeRequest as Fw}from"@modelcontextprotocol/sdk/types.js";function cn(s,e){return s.method==="POST"&&s.headers["mcp-session-id"]===void 0&&Fw(s.body)&&e?.transport.sessionId!==void 0}async function Ye(s){try{await s.transport.close()}catch{}try{await s.server.close()}catch{}}function vi(s){if(s.method!=="session/update")return null;let t=s.params?.update;return!t||typeof t.sessionUpdate!="string"?null:{kind:t.sessionUpdate,update:t}}function Re(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var cl="Bearer ";function un(s){let e=s.headers.authorization;if(typeof e!="string"||!e.startsWith(cl))return;let t=e.slice(cl.length).trim();return t.length>0?t:void 0}function jw(s){let e=new Dw({name:"hydra-acp-stdin",version:"1.0.0"},{instructions:"Piped input from `hydra cat --stream` is exposed here as a byte stream. Use `tail` for the latest N bytes (good for finding the end of a log), `head` for the first N bytes (good for headers/preamble), `read` for windowed reads against an absolute byte cursor, `wait_for_more` to block until new bytes arrive past a cursor, and `info` for the current cursors/capacity/closed status. Byte payloads come back base64-encoded."});return e.registerTool("tail",{description:"Return the most recent `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means older bytes existed but have been evicted from the ring.",inputSchema:{bytes:we.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return Re(n)}),e.registerTool("head",{description:"Return the first `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means the head has already been evicted from the ring and the returned bytes start at the oldest still-resident cursor.",inputSchema:{bytes:we.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return Re(n)}),e.registerTool("read",{description:"Read up to `max_bytes` bytes starting at absolute byte `cursor`. Returns `{bytes, nextCursor, gap?, eof?}` \u2014 `gap` is the number of bytes silently skipped because the ring had evicted them; `eof:true` means the producer closed and there is nothing left to read.",inputSchema:{cursor:we.number().int().min(0).describe("Absolute byte offset to start reading from. Use 0 to read from the very beginning (may produce a gap if old bytes have been evicted)."),max_bytes:we.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:we.number().int().min(0).optional().describe("If no bytes are available, block up to this many ms for more (capped server-side at 60_000).")}},async({cursor:t,max_bytes:n,wait_ms:r})=>{let o=await s.streamRead(t,n,r);return Re(o)}),e.registerTool("wait_for_more",{description:"Block until bytes are available past `cursor`, the stream closes, or `timeout_ms` elapses. Returns one of {data, eof, timeout} plus the current `writeCursor`. Use this when you've consumed everything up to a cursor and want to wait for more without busy-polling.",inputSchema:{cursor:we.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:we.number().int().min(0).describe("Maximum ms to block (server caps at 60_000).")}},async({cursor:t,timeout_ms:n})=>{let r=await s.streamWaitFor(t,n),o=s.streamInfo();return Re({outcome:r,writeCursor:o.writeCursor,closed:o.closed})}),e.registerTool("grep",{description:"Scan piped stdin line-by-line and return lines matching `pattern`. Prefer this over `read` when the question is 'find lines that mention X' \u2014 it filters server-side so you don't pull and decode 64 KiB base64 windows. Returns `{matches: [{cursor, line, before?, after?}], truncated, nextCursor, gap?, scannedBytes, eof?}`. Lines come back as decoded UTF-8 strings (not base64). When `truncated:true`, re-call with `cursor: nextCursor` to resume.",inputSchema:{pattern:we.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:we.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:we.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:we.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:we.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:we.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:we.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:we.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:we.number().int().min(0).optional().describe("Optional absolute byte offset to start scanning from. Omit to scan from the oldest still-resident byte. Pass the `nextCursor` from a previous truncated call to resume.")}},async t=>{let n={pattern:t.pattern};t.regex!==void 0&&(n.regex=t.regex),t.case_insensitive!==void 0&&(n.caseInsensitive=t.case_insensitive),t.invert!==void 0&&(n.invert=t.invert),t.max_matches!==void 0&&(n.maxMatches=t.max_matches),t.max_bytes!==void 0&&(n.maxBytes=t.max_bytes),t.context_before!==void 0&&(n.contextBefore=t.context_before),t.context_after!==void 0&&(n.contextAfter=t.context_after),t.cursor!==void 0&&(n.cursor=t.cursor);let r=s.streamGrep(n);return Re(r)}),e.registerTool("info",{description:"Report cursor / capacity / closed state of the stdin ring. Cheap; safe to call repeatedly.",inputSchema:{}},async()=>{let t=s.streamInfo();return Re(t)}),e}var Lw=1e4;function ul(s,e){let t=new Map,n=new Map,r=new Set;async function o(c,u){let l=jw(u),p=new Hw({sessionIdGenerator:()=>Nw()});await l.connect(p);let f={server:l,transport:p};return t.set(c,f),r.has(c)||(r.add(c),e.addDisposer(c,async()=>{r.delete(c);let h=t.get(c);t.delete(c),h!==void 0&&await Ye(h)})),f}async function i(c,u){let l=t.get(c);if(l!==void 0)return l.transport;let p=n.get(c);return p===void 0&&(p=o(c,u).finally(()=>{n.delete(c)}),n.set(c,p)),(await p).transport}async function a(c,u){let l=un(c);if(l===void 0){u.code(401).send({error:"missing bearer token"});return}let p=e.lookup(l);if(p===void 0){u.code(404).send({error:"unknown stdin token"});return}let f;if(p.session!==void 0)f=p.session;else{let m,g=new Promise(w=>{m=setTimeout(()=>w(void 0),Lw)}),y=await Promise.race([p.sessionReady.catch(()=>{}),g]);if(m!==void 0&&clearTimeout(m),y===void 0){u.code(503).send({error:"session not ready"});return}f=y}let h=t.get(l);h!==void 0&&cn(c,h)&&(t.delete(l),Ye(h));let k=await i(l,f);u.hijack(),await k.handleRequest(c.raw,u.raw,c.body)}let d={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-stdin",d,async(c,u)=>{await a(c,u)}),s.get("/mcp/hydra-acp-stdin",d,async(c,u)=>{await a(c,u)}),s.delete("/mcp/hydra-acp-stdin",d,async(c,u)=>{await a(c,u)})}import{randomUUID as Uw}from"crypto";import{McpServer as Bw}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Ww}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as Xe}from"zod";function qw(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var ll=2e3,fl=2e4;function zw(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return Kt([s]);let n=[],r=In(t);r!==void 0?n.push(`Tool: ${r}`):typeof t.title=="string"&&t.title.length>0&&n.push(`Tool: ${t.title}`);let o=t.rawInput;if(o&&typeof o=="object"&&!Array.isArray(o))for(let[a,d]of Object.entries(o))typeof d=="string"&&d.length>0&&n.push(`${a}=${d}`);if(Array.isArray(t.locations))for(let a of t.locations)typeof a?.path=="string"&&a.path.length>0&&n.push(a.path);let i=vs(t);return i!==void 0&&n.push(i),n.join(`
213
+ `)}function Jw(s,e){if(s.length<=148)return s;let r=Math.floor(148/2),o=e-r;o<0&&(o=0);let i=o+148;i>s.length&&(o=s.length-148,o<0&&(o=0));let a=s.slice(o,i);return o>0&&(a="\u2026"+a),i<s.length&&(a=a+"\u2026"),a}function Vw(s){let e=new Bw({name:"hydra-acp-recall",version:"1.0.0"},{instructions:"Search and retrieve detail from this session's pre-compaction history. After a compaction summary replaces earlier conversation in working memory, these tools let you page back specifics on demand. Use `search` to find entries by keyword, `range` to pull a contiguous slice verbatim, and `tool_calls` to enumerate prior tool invocations. These tools only return results once the session has been compacted at least once."});return e.registerTool("search",{description:"Search this session's prior conversation history (the part that was compacted out of your working memory) by keyword. Covers assistant and user messages, the arguments of every tool call including full shell commands, and what those calls printed. Returns matching entry ids with short snippets so you can decide which to pull in full via `range`. Use this when the compaction summary mentions something but you need the verbatim detail.",inputSchema:{query:Xe.string().min(1).describe("Case-insensitive substring to search for."),limit:Xe.number().int().min(1).max(50).optional().describe("Maximum number of matches to return (default 10, max 50)."),include_tool_calls:Xe.boolean().optional().describe("Whether to include tool_call entries in the search (default true).")}},async({query:t,limit:n=10,include_tool_calls:r=!0})=>{let o=await s();if(!o.summarizedThroughEntry||o.summarizedThroughEntry===0)return Re({matches:[],total_matched:0,truncated:!1,note:"This session has no compacted history. `search` retrieves detail from entries that were summarized out of the working conversation; nothing has been summarized yet."});let i=[],a=t.toLowerCase();for await(let{entryId:c,entry:u}of o.iterRecallNewestFirst()){let l=vi(u);if(!l)continue;let{kind:p,update:f}=l;if((p==="tool_call"||p==="tool_call_update")&&!r)continue;let h=zw(u,p,f),k=h.toLowerCase().indexOf(a);if(k<0)continue;let m=qw(p),g=Jw(h,k),y=typeof u.recordedAt=="number"?String(u.recordedAt):void 0;if(i.push({entryId:c,speaker:m,snippet:g,timestamp:y}),i.length>=n)break}i.sort((c,u)=>c.entryId-u.entryId);let d=i.length>=n;return Re({matches:i,total_matched:i.length,truncated:d})}),e.registerTool("range",{description:"Pull a contiguous range of prior conversation entries verbatim from this session's pre-compaction history, including each tool call's arguments and what it printed. Use after `search` narrows in on what you need. Capped at 50 entries per call.",inputSchema:{from_entry:Xe.number().int().min(0).describe("Zero-based index of the first entry to include (inclusive)."),to_entry:Xe.number().int().min(0).describe("Zero-based index of the last entry to include (inclusive).")}},async({from_entry:t,to_entry:n})=>{let r=await s();if(!r.summarizedThroughEntry||r.summarizedThroughEntry===0)return Re({text:"",entry_count:0,truncated:!1,note:"This session has no compacted history. `range` retrieves verbatim entries from the pre-compaction transcript; nothing has been compacted yet."});if(n<t)throw new Error(`range: to_entry (${n}) must be >= from_entry (${t})`);let o=n-t+1;if(o>50)throw new Error(`range: range size (${o}) exceeds maximum of 50 entries`);let i=await r.getRecallTotalCount();if(i===0)return Re({text:"",entry_count:0,truncated:!1});let a=Math.min(t,i-1),d=Math.min(n,i-1),c=a>t||d<n;if(a>d)return{content:[{type:"text",text:""}],structuredContent:{text:"",entry_count:0,truncated:c}};let u=await r.sliceRecallHistory(a,d),l=Kt(u,{toolOutput:{maxPerCall:ll,maxTotal:fl}});return{content:[{type:"text",text:l}],structuredContent:{text:l,entry_count:u.length,truncated:c}}}),e.registerTool("tool_calls",{description:"Search this session's prior tool invocations by tool name, ACP kind, and/or file path. Returns when each tool was called, its arguments (including the full shell command), the result status, and what the call printed. Use this to recall which files were read/edited, what shell commands ran, and what they output.",inputSchema:{tool_name:Xe.string().optional().describe("Case-insensitive substring of the tool name. Names vary by agent for the same tool (Bash, Terminal, bash), so prefer `kind` when you want every shell invocation."),kind:Xe.string().optional().describe("ACP tool kind: execute (shell), read, edit, think, other. Agent-independent, unlike tool_name."),file_path:Xe.string().optional(),limit:Xe.number().int().min(1).max(100).optional(),include_output:Xe.boolean().optional().describe("Include what each call printed (default true). Set false when you only need the commands and not their results.")}},async({tool_name:t,kind:n,file_path:r,limit:o=20,include_output:i=!0})=>{let a=await s();if(!a.summarizedThroughEntry||a.summarizedThroughEntry===0)return Re({calls:[],truncated:!1,note:"This session has no compacted history. `tool_calls` retrieves tool invocations from the pre-compaction transcript; nothing has been compacted yet."});let d=typeof t=="string"&&t.length>0,c=typeof n=="string"&&n.length>0,u=typeof r=="string"&&r.length>0;if(!d&&!c&&!u)throw new Error("tool_calls: at least one of tool_name, kind, or file_path must be provided");let l=new Map,p=Math.max(o*4,200);for await(let{entryId:y,entry:w}of a.iterRecallNewestFirst()){let v=vi(w);if(!v)continue;let{kind:S,update:b}=v;if(S!=="tool_call"&&S!=="tool_call_update")continue;let I=typeof b.toolCallId=="string"&&b.toolCallId.length>0?b.toolCallId:`__noid_${y}`,A=l.get(I);if(A||(A={entryId:y,toolName:"(unnamed)",nameAuthoritative:!1,rawInput:{},locations:[],status:"in_progress"},l.set(I,A)),y<A.entryId&&(A.entryId=y),!A.nameAuthoritative){let T=In(b);T!==void 0?(A.toolName=T,A.nameAuthoritative=!0):typeof b.name=="string"&&b.name.length>0?(A.toolName=b.name,A.nameAuthoritative=!0):S==="tool_call"&&typeof b.title=="string"&&b.title.length>0&&(A.toolName=b.title,A.nameAuthoritative=!0)}if(A.kind===void 0&&typeof b.kind=="string"&&b.kind.length>0&&(A.kind=b.kind),A.output===void 0){let T=vs(b);T!==void 0&&(A.output=T)}let x=b.rawInput;if(x&&typeof x=="object"&&!Array.isArray(x)&&Object.keys(x).length>0)for(let[T,M]of Object.entries(x))A.rawInput[T]===void 0&&(A.rawInput[T]=M);if(Array.isArray(b.locations))for(let T of b.locations){let M=T?.path;typeof M=="string"&&M.length>0&&!A.locations.includes(M)&&A.locations.push(M)}if(typeof b.status=="string"&&A.status==="in_progress"&&(A.status=b.status),w.recordedAt!==void 0&&A.timestamp===void 0&&(A.timestamp=String(w.recordedAt)),l.size>=p)break}let f=[...l.keys()].sort((y,w)=>l.get(y).entryId-l.get(w).entryId),h=[],k=fl,m=!1;for(let y of f){let w=l.get(y);if(w.toolName=uo({name:w.toolName,rawInput:w.rawInput,...w.kind!==void 0?{kind:w.kind}:{}}),d&&!w.toolName.toLowerCase().includes(t.toLowerCase())||c&&(w.kind??"").toLowerCase()!==n.toLowerCase())continue;if(u){let b=r.toLowerCase(),I=["file_path","filePath","path"],A=!1;for(let x of I){let T=w.rawInput[x];if(typeof T=="string"&&T.toLowerCase().includes(b)){A=!0;break}}if(!A){for(let x of w.locations)if(x.toLowerCase().includes(b)){A=!0;break}}if(!A)continue}let v={};for(let[b,I]of Object.entries(w.rawInput))typeof I=="string"?v[b]=I.length>500?I.slice(0,497)+"\u2026":I:(typeof I=="number"||typeof I=="boolean")&&(v[b]=I);w.locations.length>0&&v.locations===void 0&&(v.locations=w.locations);let S={entryId:w.entryId,tool:w.toolName,args:v,status:w.status,timestamp:w.timestamp};if(w.kind!==void 0&&(S.kind=w.kind),i&&w.output!==void 0){let b=w.output,I=Math.min(ll,k);if(I<=0)m=!0;else{let A=b.length<=I?b:b.slice(0,I-1)+"\u2026";S.output=A,S.outputBytes=b.length,S.outputTruncated=A.length<b.length,k-=A.length}}if(h.push(S),h.length>=o)break}let g=h.length>=o;return Re({calls:h,truncated:g,...m?{outputBudgetExhausted:m}:{}})}),e}var Gw=1e4;function pl(s,e){let t=new Map,n=new Map,r=new Set;async function o(c,u){let l=Vw(u),p=new Ww({sessionIdGenerator:()=>Uw()});await l.connect(p);let f={server:l,transport:p};return t.set(c,f),r.has(c)||(r.add(c),e.addDisposer(c,async()=>{r.delete(c);let h=t.get(c);t.delete(c),h!==void 0&&await Ye(h)})),f}async function i(c,u){let l=t.get(c);if(l!==void 0)return l.transport;let p=n.get(c);return p===void 0&&(p=o(c,u).finally(()=>{n.delete(c)}),n.set(c,p)),(await p).transport}async function a(c,u){let l=un(c);if(l===void 0){u.code(401).send({error:"missing bearer token"});return}let p=e.lookup(l);if(p===void 0){u.code(404).send({error:"unknown recall token"});return}let f=async()=>{if(p.session!==void 0)return p.session;let m,g=new Promise(w=>{m=setTimeout(()=>w(void 0),Gw)}),y=await Promise.race([p.sessionReady.catch(()=>{}),g]);if(m!==void 0&&clearTimeout(m),y===void 0)throw new Error("recall: session not ready");return y},h=t.get(l);h!==void 0&&cn(c,h)&&(t.delete(l),Ye(h));let k=await i(l,f);u.hijack(),await k.handleRequest(c.raw,u.raw,c.body)}let d={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-recall",d,async(c,u)=>{await a(c,u)}),s.get("/mcp/hydra-acp-recall",d,async(c,u)=>{await a(c,u)}),s.delete("/mcp/hydra-acp-recall",d,async(c,u)=>{await a(c,u)})}var Ir=class{byName=new Map;changeHandlers=[];register(e,t,n,r){this.byName.set(e,{connection:t,instructions:n,tools:[...r]}),this.fireChanged(e,"register")}clear(e){this.byName.delete(e)&&this.fireChanged(e,"clear")}lookup(e){return this.byName.get(e)}list(){return Array.from(this.byName.keys())}onChange(e){return this.changeHandlers.push(e),()=>{let t=this.changeHandlers.indexOf(e);t>=0&&this.changeHandlers.splice(t,1)}}fireChanged(e,t){for(let n of this.changeHandlers)try{n(e,t)}catch{}}};import{StreamableHTTPServerTransport as nk}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{randomUUID as sk}from"crypto";import{Server as Kw}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Qw,ListToolsRequestSchema as Yw}from"@modelcontextprotocol/sdk/types.js";function gl(s,e,t,n){let r=typeof t=="function"?async()=>t():async()=>t,o=new Kw({name:s,version:"1.0.0"},{capabilities:{tools:{listChanged:!0}},...e.instructions!==void 0?{instructions:e.instructions}:{}}),i=a=>({name:a.name,description:a.description,inputSchema:a.inputSchema,...a.outputSchema!==void 0?{outputSchema:a.outputSchema}:{}});return o.setRequestHandler(Yw,async()=>{let a=n?.peekSessionId?.();if(a!==void 0&&n?.fetchSessionTools!==void 0)try{let d=await n.fetchSessionTools(a);if(d!==void 0)return{tools:d.map(i)}}catch{}return{tools:e.tools.map(i)}}),o.setRequestHandler(Qw,async(a,d)=>{let c=a.params.name,u=d._meta?.progressToken??d.requestId,l=Zw(u,d.sendNotification);try{let p=await r(),f=await ek(e.connection,s,c,a.params.arguments??{},p);return tk(f,c)}catch(p){return bi(p instanceof Error?p.message:String(p))}finally{l()}}),o}var Xw=15e3;function Zw(s,e,t=Xw){if(s===void 0)return()=>{};let n=0,r=setInterval(()=>{n+=1,e({method:"notifications/progress",params:{progressToken:s,progress:n}}).catch(()=>{})},t);return r.unref?.(),()=>clearInterval(r)}async function ek(s,e,t,n,r){return await s.request("hydra-acp/mcp_tools/invoke",{server:e,tool:t,args:n,sessionId:r})}function tk(s,e){if(s===null||typeof s!="object")return bi(`extension ${e} returned non-object`);let t=s;return Array.isArray(t.content)?t:bi(`extension ${e} omitted content array`)}function bi(s){return{content:[{type:"text",text:s}],isError:!0}}var rk=1e4;function ml(s,e,t){let n=new Map;function r(c){for(let u of n.values()){let l=u.get(c);l!==void 0&&(u.delete(c),Ye(l))}}async function o(c,u){for(let[l,p]of n){if(e.lookup(l)?.session?.sessionId!==c)continue;let h=p.get(u);if(h!==void 0)try{await h.server.sendToolListChanged()}catch{}}}t.onChange(c=>{r(c)});async function i(c,u){let l=n.get(c);l===void 0&&(l=new Map,n.set(c,l),e.addDisposer(c,async()=>{let w=n.get(c);if(w!==void 0){n.delete(c);for(let v of w.values())await Ye(v)}}));let p=l.get(u);if(p!==void 0)return p.transport;let f=t.lookup(u);if(f===void 0)return;let g=gl(u,f,async()=>{let w=e.lookup(c);if(w===void 0)throw new Error("mcp token no longer bound");if(w.session!==void 0)return w.session.sessionId;let v,S=new Promise(I=>{v=setTimeout(()=>I(void 0),rk)}),b=await Promise.race([w.sessionReady.catch(()=>{}),S]);if(v!==void 0&&clearTimeout(v),b===void 0)throw new Error("session not ready");return b.sessionId},{peekSessionId:()=>e.lookup(c)?.session?.sessionId,fetchSessionTools:async w=>{let v=await f.connection.request("hydra-acp/mcp_tools/list_tools",{sessionId:w});if(!v||typeof v!="object")return;let S=v.tools;if(!Array.isArray(S))return;let b=[];for(let I of S){if(!I||typeof I!="object")continue;let A=I;if(typeof A.name!="string"||A.name.length===0||typeof A.description!="string"||A.inputSchema===null||typeof A.inputSchema!="object")continue;let x={name:A.name,description:A.description,inputSchema:A.inputSchema};A.outputSchema!==null&&typeof A.outputSchema=="object"&&(x.outputSchema=A.outputSchema),b.push(x)}return b}}),y=new nk({sessionIdGenerator:()=>sk()});return await g.connect(y),l.set(u,{server:g,transport:y}),y}async function a(c,u){let l=un(c);if(l===void 0){u.code(401).send({error:"missing bearer token"});return}if(e.lookup(l)===void 0){u.code(404).send({error:"unknown mcp token"});return}let f=c.params.name,h=n.get(l),k=h?.get(f);k!==void 0&&cn(c,k)&&(h?.delete(f),Ye(k));let m=await i(l,f);if(m===void 0){u.code(404).send({error:`unknown mcp server: ${f}`});return}u.hijack(),await m.handleRequest(c.raw,u.raw,c.body)}let d={config:{skipAuth:!0}};return s.post("/mcp/:name",d,async(c,u)=>{await a(c,u)}),s.get("/mcp/:name",d,async(c,u)=>{await a(c,u)}),s.delete("/mcp/:name",d,async(c,u)=>{await a(c,u)}),{notifyToolListChanged:o}}async function bl(s,e){lk(s),Nr(s.daemon.scrubEnv);let t=s,n=s.daemon.tls?await Ze.readFile(ce(s.daemon.tls.key)):void 0,r=s.daemon.tls?await Ze.readFile(ce(s.daemon.tls.cert)):void 0;await Ze.mkdir(E.home(),{recursive:!0});let{stream:o,fileStream:i,closeFile:a}=await ck(s.daemon.logLevel),d=ok({logger:{level:s.daemon.logLevel,stream:o},bodyLimit:256*1024*1024});await d.register(ik,{options:{handleProtocols:Bi}}),Br(F=>{d.log.info(F)}),zr(F=>{d.log.info(F)});let c=await Xs.load(),u=await ur.load();mi(),pi(u);let l=new yr(u);l.start();let p=new ar(u);p.start();let f=new sr,h=new nr,k=new Zs(e),m=new tr([k,new er(c),h]),g=Xc({validator:m});d.addHook("onRequest",async(F,Ce)=>{F.routeOptions.config?.skipAuth||F.url==="/acp"||F.url?.startsWith("/acp?")||(await g(F,Ce),!Ce.sent&&F.authIdentity?.startsWith("script:")&&!eu(F.method,F.routeOptions.url)&&Ce.code(403).send({error:"script tokens may only access read-only session data"}))});let y=setInterval(()=>{c.sweepExpired()},300*1e3);y.unref();let w=setInterval(()=>{f.sweepExpired()},300*1e3);w.unref();let v=new is(s,{onFetched:()=>{Hc(v,A)},onStaleFallback:(F,Ce)=>{let fn=Math.round(Ce/36e5),pn=fn>=48?`${Math.round(fn/24)}d`:`${fn}h`;d.log.warn(`registry fetch failed (${F.message}); serving stale cache last synced ${pn} ago; agent versions may be outdated ('hydra registry refresh' to retry)`)}});ni(F=>d.log.info(F));let S={info:F=>d.log.info(F),warn:F=>d.log.warn(F)},b=F=>ut.spawn({...F,stderrTailBytes:s.daemon.agentStderrTailBytes,logger:S});Gi(s.compressToolContent);let I=new Qs,A=new Bs(v,b,void 0,{idleTimeoutMs:s.daemon.sessionIdleTimeoutSeconds*1e3,...s.daemon.backgroundTaskTracking!==void 0?{backgroundTaskTracking:s.daemon.backgroundTaskTracking}:{},orphanTimeoutMs:s.daemon.nonInteractiveOrphanTimeoutSeconds*1e3,sessionDefaults:s.sessionDefaults,synopsisAgent:s.synopsisAgent,synopsisModel:s.synopsisModel,compactionAgent:s.compaction?.agent,compactionModel:s.compaction?.model,defaultTransformers:s.defaultTransformers,sessionHistoryMaxEntries:s.daemon.sessionHistoryMaxEntries,sessionHistoryArchiveMaxBytes:s.daemon.sessionHistoryArchiveMaxBytes,sessionHistoryArchiveTiers:s.daemon.sessionHistoryArchiveTiers,logger:S,npmRegistry:s.npmRegistry,extensionCommands:I,defaultCwd:s.defaultCwd,disableWorkspaceSnapshots:s.disableWorkspaceSnapshots}),x=new hr(u,void 0,{resolvesLocally:async F=>await A.resolveCanonicalId(F)!==void 0,cache:p}),T=new Gs(Di(s),void 0,{tokenRegistry:h}),M=new Ks(Hi(s),void 0,{tokenRegistry:h}),N=[];Au(d,ue,Uc(s),()=>N);let B=new Date().toISOString();Mu(d,B);let q=new Sr,V=new Ir,L,W=()=>{if(L!==void 0)return L;let F=d.server.address();return L=`http://127.0.0.1:${F&&typeof F=="object"?F.port:s.daemon.port}`,L},Q={agentId:s.defaultAgent,cwd:s.defaultCwd,publicHost:s.daemon.publicHost,host:s.daemon.host,port:s.daemon.port,compaction:s.compaction};Su(d,A,Q,{extensionMcp:V,mcpTokenRegistry:q,getDaemonOrigin:W},u,p),yu(d,{store:u,localMiss:{resolvesLocally:async F=>await A.resolveCanonicalId(F)!==void 0,cache:p}}),Iu(d,v,A,{npmRegistry:s.npmRegistry}),_u(d,T),$u(d,M);let oe={host:s.daemon.host,port:s.daemon.port,...s.daemon.publicHost!==void 0?{publicHost:s.daemon.publicHost}:{},...s.daemon.tls?{tls:{cert:ce(s.daemon.tls.cert),key:ce(s.daemon.tls.key)}}:{}};Ou(d,()=>({defaultAgent:t.defaultAgent,defaultCwd:t.defaultCwd,sessionDefaults:{...t.sessionDefaults},...t.synopsisAgent!==void 0?{synopsisAgent:t.synopsisAgent}:{},...t.synopsisModel!==void 0?{synopsisModel:t.synopsisModel}:{},defaultTransformers:[...t.defaultTransformers],listen:oe})),ju(d,{store:c,rateLimiter:f,staticTokenValidator:k}),Gu(d,{store:u,health:l}),Zu(d,{processRegistry:h}),ul(d,q),pl(d,q);let xe=ml(d,q,V);al(d,{validator:m,manager:A,defaultAgent:s.defaultAgent,processRegistry:h,onExtensionVersion:(F,Ce)=>T.reportVersion(F,Ce),onTransformerVersion:(F,Ce)=>M.reportVersion(F,Ce),transformers:M,extensionCommands:I,mcpTokenRegistry:q,extensionMcp:V,extensionMcpControls:xe,getDaemonOrigin:W,registry:v,foreignSessions:x});let et=!!s.daemon.tls;await d.listen({host:et?"127.0.0.1":s.daemon.host,port:et?0:s.daemon.port});let te=d.server.address(),Pe=te&&typeof te=="object"?te.port:s.daemon.port,es,Sl=s.daemon.host,Si=Pe;if(et&&n&&r){es=await uk({listenHost:s.daemon.host,listenPort:s.daemon.port,upstreamHost:"127.0.0.1",upstreamPort:Pe,tlsOptions:{key:n,cert:r},logger:d.log});let F=es.address();F&&typeof F=="object"&&(Si=F.port)}await Ze.mkdir(E.home(),{recursive:!0}),await Dc({pid:process.pid,host:Sl,port:Si,loopbackPort:Pe,startedAt:B});let Ii={daemonUrl:`http://127.0.0.1:${Pe}`,daemonHost:"127.0.0.1",daemonPort:Pe,serviceToken:e,daemonWsUrl:`ws://127.0.0.1:${Pe}/acp`,hydraHome:E.home()};T.setContext(Ii),M.setContext(Ii),await T.start(),await M.start();try{await A.reconcilePermissionFlags()}catch(F){d.log.warn(`permission flag reconcile failed: ${F.message}`)}try{await A.seedSessionIndex()}catch(F){d.log.warn(`session index seed failed: ${F.message}`)}A.resurrectPendingQueues().catch(F=>{d.log.warn(`queue replay scan failed: ${F.message}`)}),A.resumePendingCompactions().catch(F=>{d.log.warn(`compaction resume scan failed: ${F.message}`)}),A.resumePendingAgentSwaps().catch(F=>{d.log.warn(`agent-swap resume scan failed: ${F.message}`)});let Ai=s.daemon.agentSyncIntervalMinutes*60*1e3,Ci=Ai>0?jc({registry:v,manager:A,intervalMs:Ai,logger:S}):void 0,Ri=s.daemon.sessionGcIntervalMinutes*60*1e3,Il=s.daemon.sessionGcMaxAgeDays*24*60*60*1e3,xi=Ri>0?Lc({manager:A,intervalMs:Ri,maxAgeMs:Il,logger:S}):void 0,Al=zc({bootConfig:s,apply:F=>{t=F,v.setConfig(F),A.setLiveConfig({sessionDefaults:F.sessionDefaults}),Q.agentId=F.defaultAgent,Q.cwd=F.defaultCwd,Nr(F.daemon.scrubEnv)},onDrift:F=>{N=F},logger:S});return{app:d,manager:A,registry:v,extensions:T,transformers:M,mcpTokenRegistry:q,extensionMcp:V,processRegistry:h,shutdown:async()=>{l.stop(),p.stop(),Al(),xi&&xi(),Ci&&Ci(),clearInterval(y),clearInterval(w);let F=async(Ce,fn)=>{try{await fn()}catch(pn){d.log.warn(`shutdown step ${Ce} failed: ${pn instanceof Error?pn.message:String(pn)}`)}};await F("sessionTokenStore.flush",()=>c.flush()),await F("extensions.stop",()=>T.stop()),await F("transformers.stop",()=>M.stop()),await F("manager.closeAll",()=>A.closeAll()),await F("manager.flushSynopsis",()=>A.flushSynopsis(3e4)),await F("manager.shutdownSynopsis",()=>A.shutdownSynopsis()),await F("manager.flushMetaWrites",()=>A.flushMetaWrites()),await F("manager.flushHistoryWrites",()=>A.flushHistoryWrites()),Br(null),zr(null),ni(null),es&&await F("tlsTerminator.close",()=>new Promise(Ce=>es.close(()=>Ce()))),await F("app.close",()=>d.close());try{wl.unlinkSync(E.pidFile())}catch{}await F("fileStream.flushSync",()=>i.flushSync()),await F("fileStream.close",a)}}}var yl=20;async function dk(s,e){let t=ln.dirname(s),n=ln.basename(s,".log"),r=new RegExp(`^${n}\\.(\\d+)\\.log$`),o;try{o=await Ze.readdir(t)}catch{return}let i=[];for(let d of o){let c=d.match(r);c&&i.push({name:d,n:Number(c[1])})}if(i.length<=e)return;i.sort((d,c)=>d.n-c.n);let a=i.slice(0,i.length-e);await Promise.allSettled(a.map(d=>Ze.unlink(ln.join(t,d.name))))}async function ck(s){await dk(E.logFile(),yl);let e=await ak({file:E.logFile(),size:"10m",mkdir:!0,symlink:zs,limit:{count:yl,removeOtherLogFiles:!0}}),t=hl.destination(2),n=!1,r={write:a=>{n||e.write(a)}};return{stream:hl.multistream([{stream:r,level:s},{stream:t,level:s}]),fileStream:e,closeFile:()=>new Promise(a=>{n=!0,e.once("close",()=>a()),e.end()})}}async function uk(s){let e=vl.createServer(s.tlsOptions,t=>{let n=kl.connect({host:s.upstreamHost,port:s.upstreamPort}),r=!1,o=i=>{if(!r){r=!0,i&&s.logger.warn(`tls terminator forwarder error: ${i.message??String(i)}`);try{t.destroy()}catch{}try{n.destroy()}catch{}}};t.on("error",o),n.on("error",o),t.on("close",()=>o()),n.on("close",()=>o()),t.pipe(n),n.pipe(t)});return e.on("tlsClientError",t=>{s.logger.warn(`tls handshake error: ${t.message}`)}),await new Promise((t,n)=>{let r=o=>{n(new Error(`TLS listener could not bind ${s.listenHost}:${s.listenPort}: ${o.message}`))};e.once("error",r),e.listen({host:s.listenHost,port:s.listenPort},()=>{e.off("error",r),t()})}),e.on("error",t=>{s.logger.warn(`tls terminator error: ${t.message}`)}),e}function lk(s){let e=s.daemon.host;if(!(e==="127.0.0.1"||e==="::1"||e==="localhost"||e==="[::1]")&&!s.daemon.tls)throw new Error(`Refusing to bind to non-loopback host ${e} without TLS configured.`)}async function fk(){process.title="hydra-acp-daemon";let{installGlobalTlsTrust:s}=await Promise.resolve().then(()=>(Yn(),Vu));s();let e=await hn(),t=await Pi(),n=await bl(e,t);process.stdout.write(`hydra-acp daemon listening on ${e.daemon.host}:${e.daemon.port}
214
214
  `);let r=1e4,o=!1,i=async()=>{o&&(process.stderr.write(`Second signal received; exiting immediately.
215
215
  `),process.exit(1)),o=!0,process.stdout.write(`Shutting down...
216
216
  `);let a=setTimeout(()=>{process.stderr.write(`Graceful shutdown did not complete within ${r}ms; forcing exit.
217
217
  `),process.exit(1)},r);a.unref();try{await n.shutdown()}catch(d){process.stderr.write(`shutdown failed: ${d instanceof Error?d.message:String(d)}
218
- `)}clearTimeout(a),process.exit(0)};process.on("SIGINT",()=>{i()}),process.on("SIGTERM",()=>{i()}),process.on("SIGHUP",()=>{})}uk().catch(s=>{let e=s instanceof Error?s.stack??s.message:String(s);process.stderr.write(`hydra-acp-daemon: ${e}
219
- `),Hi(e).catch(()=>{}).finally(()=>process.exit(1))});
218
+ `)}clearTimeout(a),process.exit(0)};process.on("SIGINT",()=>{i()}),process.on("SIGTERM",()=>{i()}),process.on("SIGHUP",()=>{})}fk().catch(s=>{let e=s instanceof Error?s.stack??s.message:String(s);process.stderr.write(`hydra-acp-daemon: ${e}
219
+ `),Li(e).catch(()=>{}).finally(()=>process.exit(1))});