@hydra-acp/cli 0.1.167 → 0.1.169

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.
Files changed (3) hide show
  1. package/dist/cli.js +346 -346
  2. package/dist/daemon.js +64 -64
  3. package/package.json +1 -1
package/dist/daemon.js CHANGED
@@ -1,46 +1,46 @@
1
1
  #!/usr/bin/env node
2
- var Oc=Object.defineProperty;var wn=(s,e)=>()=>(s&&(e=s(s=0)),e);var Fc=(s,e)=>{for(var t in e)Oc(s,t,{get:e[t],enumerable:!0})};import*as U from"path";import*as Es from"os";function _(s){let e=Es.homedir();return e?s===e?"~":s.startsWith(e+"/")?"~"+s.slice(e.length):s:s}function Hc(){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 L(){let s=process.env[Nc];if(s&&s.length>0)return U.resolve(s);let e=Hc();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(Es.homedir(),".hydra-acp")}var Nc,C,Q=wn(()=>{"use strict";Nc="HYDRA_ACP_HOME";C={home:L,config:()=>U.join(L(),"config.json"),authToken:()=>U.join(L(),"auth-token"),remotes:()=>U.join(L(),"remotes.json"),pidFile:()=>U.join(L(),"daemon.pid"),logFile:()=>U.join(L(),"daemon.log"),currentLogFile:()=>U.join(L(),"current.log"),registryCache:()=>U.join(L(),"registry.json"),themesDir:()=>U.join(L(),"themes"),ttySessionDir:()=>U.join(L(),"tty"),ttySessionFile:s=>U.join(L(),"tty",s),agentsDir:()=>U.join(L(),"agents"),agentLogFile:s=>U.join(L(),"agents","logs",`${s}.log`),agentInstallDir:(s,e,t)=>U.join(L(),"agents",e,s,t),agentNpmInstallDir:(s,e,t)=>U.join(L(),"agents",e,s,t,`node${process.versions.modules}`),sessionsDir:()=>U.join(L(),"sessions"),sessionDir:s=>U.join(L(),"sessions",s),sessionFile:s=>U.join(L(),"sessions",s,"meta.json"),historyFile:s=>U.join(L(),"sessions",s,"history.jsonl"),historyArchiveFile:(s,e)=>U.join(L(),"sessions",s,`history.jsonl.${e}`),toolsDir:s=>U.join(L(),"sessions",s,"tools"),toolBlobFile:(s,e)=>U.join(L(),"sessions",s,"tools",e),queueFile:s=>U.join(L(),"sessions",s,"queue.ndjson"),tombstonesDir:()=>U.join(L(),"sessions",".tombstones"),tombstoneAgentDir:s=>U.join(L(),"sessions",".tombstones",encodeURIComponent(s)),tombstoneFile:(s,e)=>U.join(L(),"sessions",".tombstones",encodeURIComponent(s),encodeURIComponent(e)),extensionsDir:()=>U.join(L(),"extensions"),extensionLogDir:s=>U.join(L(),"extensions",s),extensionLogFile:s=>U.join(L(),"extensions",s,"current.log"),extensionPidFile:s=>U.join(L(),"extensions",s,"extension.pid"),transformersDir:()=>U.join(L(),"transformers"),transformerLogDir:s=>U.join(L(),"transformers",s),transformerLogFile:s=>U.join(L(),"transformers",s,"current.log"),transformerPidFile:s=>U.join(L(),"transformers",s,"transformer.pid"),transformerState:(s,e)=>U.join(L(),"sessions",s,"transformer-state",e),tuiHistoryFile:s=>U.join(L(),"sessions",s,"prompt-history"),globalTuiHistoryFile:()=>U.join(L(),"prompt-history"),tuiLogFile:()=>U.join(L(),"tui.log"),shimWireLogFile:()=>U.join(L(),"shim-wire.log")}});import*as oe from"fs/promises";import*as So from"fs";import*as Ce from"path";import{randomBytes as Dc}from"crypto";async function ye(s,e,t={}){let r=(t.pretty??!0?JSON.stringify(e,null,2):JSON.stringify(e))+`
3
- `;await Uc(s,r,t)}async function Uc(s,e,t={}){let n=await Lc(s),r=Bc(n);await oe.mkdir(r,{recursive:!0});let o=`${n}.tmp-${process.pid}-${Wc()}`;try{let i={encoding:"utf8"};t.mode!==void 0&&(i.mode=t.mode),await oe.writeFile(o,e,i),await oe.rename(o,n)}catch(i){throw await oe.unlink(o).catch(()=>{}),i}if(t.mode!==void 0)try{So.chmodSync(n,t.mode)}catch{}}async function Lc(s){let e;try{e=await oe.lstat(s)}catch(r){if(r.code==="ENOENT")return s;throw r}if(!e.isSymbolicLink())return s;let t=await oe.readlink(s),n=Ce.isAbsolute(t)?t:Ce.resolve(Ce.dirname(s),t);try{let r=await oe.realpath(Ce.dirname(n));return Ce.join(r,Ce.basename(n))}catch(r){if(r.code==="ENOENT")return n;throw r}}async function se(s){let e;try{e=await oe.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 Bc(s){let e=s.lastIndexOf("/");return e<=0?".":s.slice(0,e)}function Wc(){return Dc(4).toString("hex")}var Le=wn(()=>{"use strict"});function xs(s,e){return`${s}:${e}`}var bc=wn(()=>{"use strict";Q();Le()});var Tc={};Fc(Tc,{_resetForTests:()=>lh,clearPin:()=>rh,fetchPeerFingerprint:()=>ah,formatFingerprint:()=>Ac,getPin:()=>oh,installGlobalTlsTrust:()=>dh,loadPinsFromStore:()=>ih,setPin:()=>Ic,sha256Hex:()=>go,wsTlsOptions:()=>uh});import{createHash as Xm}from"crypto";import*as Sc from"tls";import{Agent as Zm,Dispatcher as eh,buildConnector as th,getGlobalDispatcher as nh,setGlobalDispatcher as sh}from"undici";function Ic(s,e,t){ut.set(xs(s,e),Cc(t))}function rh(s,e){ut.delete(xs(s,e))}function oh(s,e){return ut.get(xs(s,e))}function ih(s){ut.clear();for(let e of s.list())e.entry.pinnedFingerprint&&Ic(e.host,e.port,e.entry.pinnedFingerprint)}async function ah(s,e,t={}){let n=t.timeoutMs??1e4;return new Promise((r,o)=>{let i=Sc.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,go(u.raw))}),i.once("error",u=>d(u))})}function go(s){return Xm("sha256").update(s).digest("hex")}function Ac(s){let e=Cc(s),t=e.match(/.{2}/g);return t?t.join(":"):e}function Cc(s){return s.replace(/:/g,"").toLowerCase()}function dh(){if(po)return;po=!0;let s=nh(),e=new Zm({connect:th({rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(n,r)=>xc(n,r)})}),t=new eh;t.dispatch=(n,r)=>{let o=ch(n.origin);return(o&&Rc(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(()=>{})),sh(t)}function ch(s){if(!s)return null;try{return new URL(String(s)).hostname}catch{return null}}function Rc(s){for(let e of ut.keys())if(Ec(e)?.host===s)return!0;return!1}function xc(s,e){if(!e||!e.raw)return new Error(`TLS peer ${s} did not present a certificate`);let t=go(e.raw);for(let[n,r]of ut.entries()){let o=Ec(n);if(o&&o.host===s&&r===t)return}return new Error(`TLS pin mismatch for ${s} (cert sha256 ${Ac(t)})`)}function Ec(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 uh(s){return Rc(s)?{rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(e,t)=>xc(e,t)}:{autoSelectFamily:!0}}function lh(){ut.clear(),po=!1}var ut,po,Pc=wn(()=>{"use strict";bc();ut=new Map,po=!1});Q();import*as Je from"fs/promises";import{homedir as Hs}from"os";import{z as S}from"zod";Q();import*as lt from"fs/promises";function Ts(){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 jc(){try{let e=(await lt.readFile(C.authToken(),"utf8")).trim();return e.length>0?e:void 0}catch(s){if(s.code==="ENOENT")return;throw s}}async function Ps(s){await lt.mkdir(C.home(),{recursive:!0}),await lt.writeFile(C.authToken(),s+`
4
- `,{encoding:"utf8",mode:384})}async function bo(){let s=await jc();if(s)return s;let e=Ts();return await Ps(e),process.stderr.write(`hydra-acp: initialized ${C.authToken()} with a fresh service token.
5
- `),e}Le();import*as Ao from"fs/promises";import*as Dt from"os";import*as Te from"path";var X="read by the daemon, which loads config.json at startup",Io={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:X},agentOverrides:{reload:"live",overlay:"inert",overlayNote:X},registry:{reload:"live",overlay:"inert",overlayNote:X},npmRegistry:{reload:"live",overlay:"inert",overlayNote:X},defaultAgent:{reload:"live",overlay:"effective"},defaultCwd:{reload:"live",overlay:"effective"},defaultModels:{reload:"live",overlay:"partial",overlayNote:"applies to WS session/new and child_session/spawn; POST /v1/sessions has no model field to apply it to"},synopsisAgent:{reload:"warn",overlay:"inert",overlayNote:X},synopsisModel:{reload:"warn",overlay:"inert",overlayNote:X},compaction:{reload:"warn",overlay:"inert",overlayNote:X},defaultTransformers:{reload:"warn",overlay:"inert",overlayNote:X},disableWorkspaceSnapshots:{reload:"warn",overlay:"inert",overlayNote:X},compressToolContent:{reload:"warn",overlay:"inert",overlayNote:X},extensions:{reload:"warn",overlay:"inert",overlayNote:X},transformers:{reload:"warn",overlay:"inert",overlayNote:X},tui:{reload:"client",overlay:"effective"},sessionListColdLimit:{reload:"client",overlay:"effective"}},qc={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:X},logLevel:{reload:"warn",overlay:"inert",overlayNote:X},sessionIdleTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:X},nonInteractiveOrphanTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:X},sessionHistoryMaxEntries:{reload:"warn",overlay:"inert",overlayNote:X},sessionHistoryArchiveMaxBytes:{reload:"warn",overlay:"inert",overlayNote:X},sessionHistoryArchiveTiers:{reload:"warn",overlay:"inert",overlayNote:X},agentStderrTailBytes:{reload:"warn",overlay:"inert",overlayNote:X},agentSyncIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:X},sessionGcIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:X},sessionGcMaxAgeDays:{reload:"warn",overlay:"inert",overlayNote:X}};function Ms(s){return Io[s]??{reload:"restart",overlay:"inert"}}function _s(s){return qc[s]??{reload:"restart",overlay:"inert"}}function $s(){let s=[];for(let[e,t]of Object.entries(Io))t.overlay!=="effective"&&s.push({key:e,effect:t.overlay,note:t.overlayNote??X});return s}var zc=".hydra-acp.json",Os="home",Jc=64,Sh=$s().map(s=>s.key);function Vc(s){return s==="~"?Dt.homedir():s.startsWith("~/")?Te.join(Dt.homedir(),s.slice(2)):s.startsWith("$HOME/")?Te.join(Dt.homedir(),s.slice(6)):s}function Fs(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function Ns(s,e){let t={...s};for(let[n,r]of Object.entries(e)){let o=t[n];t[n]=Fs(o)&&Fs(r)?Ns(o,r):r}return t}async function Gc(s,e=Dt.homedir()){let t=[],n=[],r=Te.resolve(e),o=Te.resolve(s);for(let i=0;i<Jc;i+=1){let a=Te.join(o,zc),d;try{d=await Ao.readFile(a,"utf8")}catch{d=void 0}if(d!==void 0)try{let u=JSON.parse(d);Fs(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=Te.dirname(o);if(c===o)break;o=c}return t.reverse(),{layers:t,notices:n}}function Kc(s){let e=new Map($s().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 Qc(s=process.cwd()){let{layers:e,notices:t}=await Gc(s);t.push(...Kc(e));let n={};for(let i of e)n=Ns(n,i.data);let r,o=n[Os];return typeof o=="string"&&o.length>0?r=Te.resolve(Vc(o)):o!==void 0&&t.push({file:e[e.length-1].file,key:Os,message:"`home` must be a non-empty string; ignoring it"}),delete n[Os],{layers:e,notices:t,merged:n,...r!==void 0?{homeRequest:r}:{}}}function Yc(s,e){let t=s[e];return typeof t=="string"&&t.length>0?t:void 0}function Xc(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))typeof o=="string"&&(n[r]=o);return Object.keys(n).length>0?n:void 0}async function Ut(s){let e={};try{e=(await Qc(s)).merged}catch{return{}}let t=Yc(e,"defaultAgent"),n=Xc(e,"defaultModels");return{...t!==void 0?{agentId:t}:{},...n!==void 0?{models:n}:{}}}var xo="https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",Zc=S.object({cert:S.string(),key:S.string()}),Eo=55514,eu=S.object({host:S.string().default("127.0.0.1"),port:S.number().int().positive().default(Eo),logLevel:S.enum(["debug","info","warn","error"]).default("info"),tls:Zc.optional(),sessionIdleTimeoutSeconds:S.number().int().nonnegative().default(3600),nonInteractiveOrphanTimeoutSeconds:S.number().int().nonnegative().default(180),sessionHistoryMaxEntries:S.number().int().positive().default(1e4),sessionHistoryArchiveMaxBytes:S.number().int().nonnegative().default(1e7),sessionHistoryArchiveTiers:S.number().int().positive().default(10),agentStderrTailBytes:S.number().int().positive().default(4096),publicHost:S.string().optional(),agentSyncIntervalMinutes:S.number().nonnegative().default(60),scrubEnv:S.array(S.string()).default([]),sessionGcIntervalMinutes:S.number().nonnegative().default(60),sessionGcMaxAgeDays:S.number().positive().default(2)}),tu=S.object({url:S.string().url().default(xo),ttlHours:S.number().positive().default(24),pinned:S.boolean().default(!1)}),nu=S.object({extends:S.string().optional(),name:S.string().optional(),description:S.string().optional(),command:S.string().optional(),args:S.array(S.string()).optional(),env:S.record(S.string()).optional()}),su=S.object({packageSpec:S.string().optional(),extraArgs:S.array(S.string()).optional(),env:S.record(S.string()).optional()}),ru=S.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-y","ctrl-underscore","alt-underscore","escape"]),ou=S.union([S.string(),S.object({field:S.string().optional(),text:S.string().optional(),script:S.string().optional(),refreshMs:S.number().int().positive().optional(),maxWidth:S.number().int().positive().optional(),minWidth:S.number().int().nonnegative().optional(),truncate:S.boolean().optional(),priority:S.number().optional(),prefix:S.string().optional(),suffix:S.string().optional(),separator:S.string().optional(),style:S.string().optional(),onClick:S.string().optional(),onDoubleClick:S.string().optional()}).strict()]),Co=S.array(ou);function js(s,e){return S.object({left:Co.default(s),right:Co.default(e)}).default({})}var iu=["status",{field:"elapsed",separator:" "},"sessionId","queued","scroll"],au=["usage"],du=[],cu=["helpHint"],uu=["cwd","title"],lu=["agentModel"],fu=S.object({composer:S.object({top:js(iu,au),bottom:js(du,cu),hintTurns:S.number().int().nonnegative().nullable().default(3)}).default({}),sessionbar:js(uu,lu),scriptRefreshMs:S.number().int().positive().default(5e3),repaintThrottleMs:S.number().int().nonnegative().default(1e3),maxScrollbackLines:S.number().int().positive().default(1e4),mouse:S.boolean().default(!0),inAppSelection:S.boolean().optional(),selectionClipboard:S.enum(["primary","clipboard","both"]).default("both"),openFileCommand:S.union([S.string(),S.array(S.string())]).optional(),openFileInTerminal:S.boolean().optional(),logMaxBytes:S.number().int().positive().default(5*1024*1024),cwdColumnMaxWidth:S.number().int().positive().default(32),progressIndicator:S.boolean().default(!0),launcherModeWhenHosted:S.boolean().default(!1),skipPermissions:S.boolean().default(!1),defaultEnterAction:S.enum(["enqueue","amend"]).default("amend"),showThoughts:S.boolean().default(!0),ambiguousWidth:S.enum(["auto","narrow","wide"]).default("auto"),toolContent:S.enum(["inline","references"]).default("references"),diffContextLines:S.number().int().min(0).default(3),promptHistoryMaxEntries:S.number().int().positive().default(2e3),maxToolItems:S.number().int().nonnegative().default(5),maxPlanItems:S.number().int().nonnegative().default(5),sidebar:S.object({enabled:S.boolean().default(!1),width:S.number().int().positive().optional(),border:S.enum(["none","rule","frame"]).default("frame"),gadgets:S.array(S.string()).default(["activity","sessions","tasks","context","queue","todo","files","git","resources","info","tools"])}).default({}),showFileUpdates:S.enum(["none","edit","diff"]).default("edit"),sessionColumns:S.array(S.enum(["session","upstream","host","state","agent","model","age","cwd","title","cost"])).nonempty().optional(),hotkeys:S.record(ru,S.object({command:S.union([S.string(),S.array(S.string())])})).default({}),theme:S.union([S.string(),S.record(S.string(),S.unknown())]).optional(),themeBackground:S.string().optional()}),Ro=S.string().min(1).regex(/^[A-Za-z0-9._-]+$/,"extension name must be filename-safe"),pu=S.object({command:S.array(S.string()).default([]),args:S.array(S.string()).default([]),env:S.record(S.string()).default({}),enabled:S.boolean().default(!0)}),gu=S.object({command:S.array(S.string()).default([]),args:S.array(S.string()).default([]),env:S.record(S.string()).default({}),enabled:S.boolean().default(!0)}),mu=S.object({daemon:eu.default({}),registry:tu.default({url:xo,ttlHours:24,pinned:!1}),agents:S.record(S.string(),nu).default({}),agentOverrides:S.record(S.string(),su).default({}),defaultAgent:S.string().default("opencode"),defaultModels:S.record(S.string(),S.string()).default({}),synopsisAgent:S.string().optional(),synopsisModel:S.string().optional(),compaction:S.object({agent:S.string().optional(),model:S.string().optional(),tailK:S.number().int().nonnegative().default(20),maxIterations:S.number().int().positive().default(3),contextFraction:S.number().min(0).max(1).default(.5),hardCeilingFraction:S.number().min(0).max(1).default(.85),absoluteFallback:S.number().int().positive().default(2e5),idleBeforePromptMs:S.number().int().nonnegative().default(3e5),modelContextWindows:S.record(S.string(),S.number().int().positive()).default({})}).default({}),defaultCwd:S.string().default("~"),disableWorkspaceSnapshots:S.boolean().optional(),compressToolContent:S.boolean().default(!0),sessionListColdLimit:S.number().int().nonnegative().default(20),extensions:S.record(Ro,pu).default({}),transformers:S.record(Ro,gu).default({}),defaultTransformers:S.array(S.string()).default([]),npmRegistry:S.string().url().optional(),tui:fu.default({})});function To(s){return Object.entries(s.extensions).map(([e,t])=>({name:e,...t}))}function Po(s){return Object.entries(s.transformers).map(([e,t])=>({name:e,...t}))}async function Mo(){return await hu(),await se(C.config())??{}}async function hu(){let s;try{s=await Je.lstat(C.config())}catch(e){if(e.code==="ENOENT")return;throw e}if(s.isSymbolicLink())try{await Je.stat(C.config())}catch(e){if(e.code!=="ENOENT")throw e;let t=await Je.readlink(C.config()).catch(()=>"<unknown>");throw new Error(`config.json at ${C.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 yu(){let s=await Mo(),e=s.daemon,t=e&&typeof e.authToken=="string"?e.authToken:void 0;if(!t)return;let n=!1;try{await Je.access(C.authToken()),n=!0}catch(r){if(r.code!=="ENOENT")throw r}if(n)throw new Error(`Auth token present in both ${C.authToken()} and ${C.config()} (daemon.authToken). Remove daemon.authToken from config.json to resolve.`);await Ps(t),delete e.authToken,Object.keys(e).length===0&&delete s.daemon,await ye(C.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated auth token from ${C.config()} to ${C.authToken()}.
6
- `)}async function Lt(){return await yu(),mu.parse(await Mo())}function ie(s){return s==="~"||s==="$HOME"?Hs():s.startsWith("~/")?Hs()+s.slice(1):s.startsWith("$HOME/")?Hs()+s.slice(5):s}import*as yc from"fs";import*as Ue from"fs/promises";import*as wc from"net";import*as Nt from"path";import*as kc from"tls";import zm from"fastify";import Jm from"@fastify/websocket";var _o="acp.v1";function $o(s,e){return s.has(_o)?_o:!1}import mc from"pino";import Vm from"pino-roll";var wu={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"]},Oo="HYDRA_ACP_SESSION",ku=[Oo],vu=[...Object.values(wu).flat(),...ku];function kn(s,e){return s?{...e??{},[Oo]:s}:e}var Fo=[];function Ds(s){Fo=s?[...s]:[]}function bu(s,e){return e.endsWith("*")?s.startsWith(e.slice(0,-1)):s===e}function Su(){return[...vu,...Fo]}function vn(s=process.env){let e=Su(),t={};for(let[n,r]of Object.entries(s))r!==void 0&&(e.some(o=>bu(n,o))||(t[n]=r));return t}Q();import*as ae from"fs/promises";import{createHash as Iu}from"crypto";import{gzip as Au,gunzip as Cu}from"zlib";import{promisify as No}from"util";var Ho=No(Au),Ru=No(Cu),jo=/^[A-Za-z0-9_-]+$/,xu=/^[a-f0-9]{64}$/,Us=!0;function Do(s){Us=s}function bn(s,e){return jo.test(s)?e===void 0||xu.test(e):!1}function Sn(s,e){return`${C.toolBlobFile(s,e)}.gz`}async function Ls(s,e){if(!bn(s))return null;let t=Iu("sha256").update(e,"utf8").digest("hex"),n=Sn(s,t),r=C.toolBlobFile(s,t);for(let a of[n,r])try{return await ae.access(a),t}catch{}await ae.mkdir(C.toolsDir(s),{recursive:!0});let o=Us?n:r,i=Us?await Ho(Buffer.from(e,"utf8")):Buffer.from(e,"utf8");return await ae.writeFile(o,i,{mode:384,flag:"wx"}).catch(async a=>{if(a.code!=="EEXIST")throw a}),t}async function Bt(s,e){if(!bn(s,e))return null;try{let t=await ae.readFile(Sn(s,e));return(await Ru(t)).toString("utf8")}catch{}try{return await ae.readFile(C.toolBlobFile(s,e),"utf8")}catch{return null}}async function Uo(s,e){if(!bn(s,e))return null;try{return await ae.readFile(Sn(s,e))}catch{}try{let t=await ae.readFile(C.toolBlobFile(s,e));return await Ho(t)}catch{return null}}async function Lo(s,e,t){if(!bn(s,e))return;let n=Sn(s,e);try{await ae.access(n);return}catch{}await ae.mkdir(C.toolsDir(s),{recursive:!0}),await ae.writeFile(n,t,{mode:384,flag:"wx"}).catch(r=>{if(r.code!=="EEXIST")throw r})}async function Bo(s){jo.test(s)&&await ae.rm(C.toolsDir(s),{recursive:!0,force:!0}).catch(()=>{})}Q();import*as ei from"fs/promises";import*as An from"path";import{z as D}from"zod";Le();Q();import*as qo from"fs";import*as fe from"fs/promises";import*as Ve from"path";import{spawn as zo}from"child_process";import{Readable as Eu}from"stream";function Pe(){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 qs(s,e=Pe()){if(e)return s[e]}var ft=s=>{process.stderr.write(s+`
2
+ var Fc=Object.defineProperty;var wn=(s,e)=>()=>(s&&(e=s(s=0)),e);var Nc=(s,e)=>{for(var t in e)Fc(s,t,{get:e[t],enumerable:!0})};import*as U from"path";import*as Es from"os";function _(s){let e=Es.homedir();return e?s===e?"~":s.startsWith(e+"/")?"~"+s.slice(e.length):s:s}function jc(){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 L(){let s=process.env[Hc];if(s&&s.length>0)return U.resolve(s);let e=jc();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(Es.homedir(),".hydra-acp")}var Hc,C,Q=wn(()=>{"use strict";Hc="HYDRA_ACP_HOME";C={home:L,config:()=>U.join(L(),"config.json"),authToken:()=>U.join(L(),"auth-token"),remotes:()=>U.join(L(),"remotes.json"),pidFile:()=>U.join(L(),"daemon.pid"),logFile:()=>U.join(L(),"daemon.log"),currentLogFile:()=>U.join(L(),"current.log"),registryCache:()=>U.join(L(),"registry.json"),themesDir:()=>U.join(L(),"themes"),ttySessionDir:()=>U.join(L(),"tty"),ttySessionFile:s=>U.join(L(),"tty",s),agentsDir:()=>U.join(L(),"agents"),agentLogFile:s=>U.join(L(),"agents","logs",`${s}.log`),agentInstallDir:(s,e,t)=>U.join(L(),"agents",e,s,t),agentNpmInstallDir:(s,e,t)=>U.join(L(),"agents",e,s,t,`node${process.versions.modules}`),sessionsDir:()=>U.join(L(),"sessions"),sessionDir:s=>U.join(L(),"sessions",s),sessionFile:s=>U.join(L(),"sessions",s,"meta.json"),historyFile:s=>U.join(L(),"sessions",s,"history.jsonl"),historyArchiveFile:(s,e)=>U.join(L(),"sessions",s,`history.jsonl.${e}`),toolsDir:s=>U.join(L(),"sessions",s,"tools"),toolBlobFile:(s,e)=>U.join(L(),"sessions",s,"tools",e),queueFile:s=>U.join(L(),"sessions",s,"queue.ndjson"),tombstonesDir:()=>U.join(L(),"sessions",".tombstones"),tombstoneAgentDir:s=>U.join(L(),"sessions",".tombstones",encodeURIComponent(s)),tombstoneFile:(s,e)=>U.join(L(),"sessions",".tombstones",encodeURIComponent(s),encodeURIComponent(e)),extensionsDir:()=>U.join(L(),"extensions"),extensionLogDir:s=>U.join(L(),"extensions",s),extensionLogFile:s=>U.join(L(),"extensions",s,"current.log"),extensionPidFile:s=>U.join(L(),"extensions",s,"extension.pid"),transformersDir:()=>U.join(L(),"transformers"),transformerLogDir:s=>U.join(L(),"transformers",s),transformerLogFile:s=>U.join(L(),"transformers",s,"current.log"),transformerPidFile:s=>U.join(L(),"transformers",s,"transformer.pid"),transformerState:(s,e)=>U.join(L(),"sessions",s,"transformer-state",e),tuiHistoryFile:s=>U.join(L(),"sessions",s,"prompt-history"),globalTuiHistoryFile:()=>U.join(L(),"prompt-history"),tuiLogFile:()=>U.join(L(),"tui.log"),shimWireLogFile:()=>U.join(L(),"shim-wire.log")}});import*as oe from"fs/promises";import*as Io from"fs";import*as Ce from"path";import{randomBytes as Uc}from"crypto";async function ye(s,e,t={}){let r=(t.pretty??!0?JSON.stringify(e,null,2):JSON.stringify(e))+`
3
+ `;await Lc(s,r,t)}async function Lc(s,e,t={}){let n=await Bc(s),r=Wc(n);await oe.mkdir(r,{recursive:!0});let o=`${n}.tmp-${process.pid}-${qc()}`;try{let i={encoding:"utf8"};t.mode!==void 0&&(i.mode=t.mode),await oe.writeFile(o,e,i),await oe.rename(o,n)}catch(i){throw await oe.unlink(o).catch(()=>{}),i}if(t.mode!==void 0)try{Io.chmodSync(n,t.mode)}catch{}}async function Bc(s){let e;try{e=await oe.lstat(s)}catch(r){if(r.code==="ENOENT")return s;throw r}if(!e.isSymbolicLink())return s;let t=await oe.readlink(s),n=Ce.isAbsolute(t)?t:Ce.resolve(Ce.dirname(s),t);try{let r=await oe.realpath(Ce.dirname(n));return Ce.join(r,Ce.basename(n))}catch(r){if(r.code==="ENOENT")return n;throw r}}async function se(s){let e;try{e=await oe.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 Wc(s){let e=s.lastIndexOf("/");return e<=0?".":s.slice(0,e)}function qc(){return Uc(4).toString("hex")}var Le=wn(()=>{"use strict"});function xs(s,e){return`${s}:${e}`}var Sc=wn(()=>{"use strict";Q();Le()});var Pc={};Nc(Pc,{_resetForTests:()=>fh,clearPin:()=>oh,fetchPeerFingerprint:()=>dh,formatFingerprint:()=>Cc,getPin:()=>ih,installGlobalTlsTrust:()=>ch,loadPinsFromStore:()=>ah,setPin:()=>Ac,sha256Hex:()=>mo,wsTlsOptions:()=>lh});import{createHash as Zm}from"crypto";import*as Ic from"tls";import{Agent as eh,Dispatcher as th,buildConnector as nh,getGlobalDispatcher as sh,setGlobalDispatcher as rh}from"undici";function Ac(s,e,t){ut.set(xs(s,e),Rc(t))}function oh(s,e){ut.delete(xs(s,e))}function ih(s,e){return ut.get(xs(s,e))}function ah(s){ut.clear();for(let e of s.list())e.entry.pinnedFingerprint&&Ac(e.host,e.port,e.entry.pinnedFingerprint)}async function dh(s,e,t={}){let n=t.timeoutMs??1e4;return new Promise((r,o)=>{let i=Ic.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,mo(u.raw))}),i.once("error",u=>d(u))})}function mo(s){return Zm("sha256").update(s).digest("hex")}function Cc(s){let e=Rc(s),t=e.match(/.{2}/g);return t?t.join(":"):e}function Rc(s){return s.replace(/:/g,"").toLowerCase()}function ch(){if(go)return;go=!0;let s=sh(),e=new eh({connect:nh({rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(n,r)=>Ec(n,r)})}),t=new th;t.dispatch=(n,r)=>{let o=uh(n.origin);return(o&&xc(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(()=>{})),rh(t)}function uh(s){if(!s)return null;try{return new URL(String(s)).hostname}catch{return null}}function xc(s){for(let e of ut.keys())if(Tc(e)?.host===s)return!0;return!1}function Ec(s,e){if(!e||!e.raw)return new Error(`TLS peer ${s} did not present a certificate`);let t=mo(e.raw);for(let[n,r]of ut.entries()){let o=Tc(n);if(o&&o.host===s&&r===t)return}return new Error(`TLS pin mismatch for ${s} (cert sha256 ${Cc(t)})`)}function Tc(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 lh(s){return xc(s)?{rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(e,t)=>Ec(e,t)}:{autoSelectFamily:!0}}function fh(){ut.clear(),go=!1}var ut,go,Mc=wn(()=>{"use strict";Sc();ut=new Map,go=!1});Q();import*as Je from"fs/promises";import{homedir as Hs}from"os";import{z as S}from"zod";Q();import*as lt from"fs/promises";function Ts(){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 Dc(){try{let e=(await lt.readFile(C.authToken(),"utf8")).trim();return e.length>0?e:void 0}catch(s){if(s.code==="ENOENT")return;throw s}}async function Ps(s){await lt.mkdir(C.home(),{recursive:!0}),await lt.writeFile(C.authToken(),s+`
4
+ `,{encoding:"utf8",mode:384})}async function So(){let s=await Dc();if(s)return s;let e=Ts();return await Ps(e),process.stderr.write(`hydra-acp: initialized ${C.authToken()} with a fresh service token.
5
+ `),e}Le();import*as Co from"fs/promises";import*as Dt from"os";import*as Te from"path";var X="read by the daemon, which loads config.json at startup",Ao={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:X},agentOverrides:{reload:"live",overlay:"inert",overlayNote:X},registry:{reload:"live",overlay:"inert",overlayNote:X},npmRegistry:{reload:"live",overlay:"inert",overlayNote:X},defaultAgent:{reload:"live",overlay:"effective"},defaultCwd:{reload:"live",overlay:"effective"},defaultModels:{reload:"live",overlay:"partial",overlayNote:"applies to WS session/new and child_session/spawn; POST /v1/sessions has no model field to apply it to"},synopsisAgent:{reload:"warn",overlay:"inert",overlayNote:X},synopsisModel:{reload:"warn",overlay:"inert",overlayNote:X},compaction:{reload:"warn",overlay:"inert",overlayNote:X},defaultTransformers:{reload:"warn",overlay:"inert",overlayNote:X},disableWorkspaceSnapshots:{reload:"warn",overlay:"inert",overlayNote:X},compressToolContent:{reload:"warn",overlay:"inert",overlayNote:X},extensions:{reload:"warn",overlay:"inert",overlayNote:X},transformers:{reload:"warn",overlay:"inert",overlayNote:X},tui:{reload:"client",overlay:"effective"},sessionListColdLimit:{reload:"client",overlay:"effective"}},zc={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:X},logLevel:{reload:"warn",overlay:"inert",overlayNote:X},sessionIdleTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:X},nonInteractiveOrphanTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:X},sessionHistoryMaxEntries:{reload:"warn",overlay:"inert",overlayNote:X},sessionHistoryArchiveMaxBytes:{reload:"warn",overlay:"inert",overlayNote:X},sessionHistoryArchiveTiers:{reload:"warn",overlay:"inert",overlayNote:X},agentStderrTailBytes:{reload:"warn",overlay:"inert",overlayNote:X},agentSyncIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:X},sessionGcIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:X},sessionGcMaxAgeDays:{reload:"warn",overlay:"inert",overlayNote:X}};function Ms(s){return Ao[s]??{reload:"restart",overlay:"inert"}}function _s(s){return zc[s]??{reload:"restart",overlay:"inert"}}function $s(){let s=[];for(let[e,t]of Object.entries(Ao))t.overlay!=="effective"&&s.push({key:e,effect:t.overlay,note:t.overlayNote??X});return s}var Jc=".hydra-acp.json",Os="home",Vc=64,Ih=$s().map(s=>s.key);function Gc(s){return s==="~"?Dt.homedir():s.startsWith("~/")?Te.join(Dt.homedir(),s.slice(2)):s.startsWith("$HOME/")?Te.join(Dt.homedir(),s.slice(6)):s}function Fs(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function Ns(s,e){let t={...s};for(let[n,r]of Object.entries(e)){let o=t[n];t[n]=Fs(o)&&Fs(r)?Ns(o,r):r}return t}async function Kc(s,e=Dt.homedir()){let t=[],n=[],r=Te.resolve(e),o=Te.resolve(s);for(let i=0;i<Vc;i+=1){let a=Te.join(o,Jc),d;try{d=await Co.readFile(a,"utf8")}catch{d=void 0}if(d!==void 0)try{let u=JSON.parse(d);Fs(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=Te.dirname(o);if(c===o)break;o=c}return t.reverse(),{layers:t,notices:n}}function Qc(s){let e=new Map($s().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 Yc(s=process.cwd()){let{layers:e,notices:t}=await Kc(s);t.push(...Qc(e));let n={};for(let i of e)n=Ns(n,i.data);let r,o=n[Os];return typeof o=="string"&&o.length>0?r=Te.resolve(Gc(o)):o!==void 0&&t.push({file:e[e.length-1].file,key:Os,message:"`home` must be a non-empty string; ignoring it"}),delete n[Os],{layers:e,notices:t,merged:n,...r!==void 0?{homeRequest:r}:{}}}function Xc(s,e){let t=s[e];return typeof t=="string"&&t.length>0?t:void 0}function Zc(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))typeof o=="string"&&(n[r]=o);return Object.keys(n).length>0?n:void 0}async function Ut(s){let e={};try{e=(await Yc(s)).merged}catch{return{}}let t=Xc(e,"defaultAgent"),n=Zc(e,"defaultModels");return{...t!==void 0?{agentId:t}:{},...n!==void 0?{models:n}:{}}}var Eo="https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",eu=S.object({cert:S.string(),key:S.string()}),To=55514,tu=S.object({host:S.string().default("127.0.0.1"),port:S.number().int().positive().default(To),logLevel:S.enum(["debug","info","warn","error"]).default("info"),tls:eu.optional(),sessionIdleTimeoutSeconds:S.number().int().nonnegative().default(3600),nonInteractiveOrphanTimeoutSeconds:S.number().int().nonnegative().default(180),sessionHistoryMaxEntries:S.number().int().positive().default(1e4),sessionHistoryArchiveMaxBytes:S.number().int().nonnegative().default(1e7),sessionHistoryArchiveTiers:S.number().int().positive().default(10),agentStderrTailBytes:S.number().int().positive().default(4096),publicHost:S.string().optional(),agentSyncIntervalMinutes:S.number().nonnegative().default(60),scrubEnv:S.array(S.string()).default([]),sessionGcIntervalMinutes:S.number().nonnegative().default(60),sessionGcMaxAgeDays:S.number().positive().default(2)}),nu=S.object({url:S.string().url().default(Eo),ttlHours:S.number().positive().default(24),pinned:S.boolean().default(!1)}),su=S.object({extends:S.string().optional(),name:S.string().optional(),description:S.string().optional(),command:S.string().optional(),args:S.array(S.string()).optional(),env:S.record(S.string()).optional()}),ru=S.object({packageSpec:S.string().optional(),extraArgs:S.array(S.string()).optional(),env:S.record(S.string()).optional()}),ou=S.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-y","ctrl-underscore","alt-underscore","escape"]),iu=S.union([S.string(),S.object({field:S.string().optional(),text:S.string().optional(),script:S.string().optional(),refreshMs:S.number().int().positive().optional(),maxWidth:S.number().int().positive().optional(),minWidth:S.number().int().nonnegative().optional(),truncate:S.boolean().optional(),priority:S.number().optional(),prefix:S.string().optional(),suffix:S.string().optional(),separator:S.string().optional(),style:S.string().optional(),onClick:S.string().optional(),onDoubleClick:S.string().optional()}).strict()]),Ro=S.array(iu);function js(s,e){return S.object({left:Ro.default(s),right:Ro.default(e)}).default({})}var au=["status",{field:"elapsed",separator:" "},"sessionId","queued","scroll"],du=["usage"],cu=[],uu=["helpHint"],lu=["cwd","title"],fu=["agentModel"],pu=S.object({composer:S.object({top:js(au,du),bottom:js(cu,uu),hintTurns:S.number().int().nonnegative().nullable().default(3)}).default({}),sessionbar:js(lu,fu),scriptRefreshMs:S.number().int().positive().default(5e3),repaintThrottleMs:S.number().int().nonnegative().default(1e3),maxScrollbackLines:S.number().int().positive().default(1e4),mouse:S.boolean().default(!0),inAppSelection:S.boolean().optional(),selectionClipboard:S.enum(["primary","clipboard","both"]).default("both"),openFileCommand:S.union([S.string(),S.array(S.string())]).optional(),openFileInTerminal:S.boolean().optional(),logMaxBytes:S.number().int().positive().default(5*1024*1024),cwdColumnMaxWidth:S.number().int().positive().default(32),progressIndicator:S.boolean().default(!0),launcherModeWhenHosted:S.boolean().default(!1),skipPermissions:S.boolean().default(!1),defaultEnterAction:S.enum(["enqueue","amend"]).default("amend"),showThoughts:S.boolean().default(!0),ambiguousWidth:S.enum(["auto","narrow","wide"]).default("auto"),toolContent:S.enum(["inline","references"]).default("references"),diffContextLines:S.number().int().min(0).default(3),promptHistoryMaxEntries:S.number().int().positive().default(2e3),maxToolItems:S.number().int().nonnegative().default(5),maxPlanItems:S.number().int().nonnegative().default(5),sidebar:S.object({enabled:S.boolean().default(!1),width:S.number().int().positive().optional(),border:S.enum(["none","rule","frame"]).default("frame"),gadgets:S.array(S.string()).default(["activity","sessions","tasks","context","queue","todo","files","git","resources","info","tools"])}).default({}),showFileUpdates:S.enum(["none","edit","diff"]).default("edit"),sessionColumns:S.array(S.enum(["session","upstream","host","state","agent","model","age","cwd","title","cost"])).nonempty().optional(),hotkeys:S.record(ou,S.object({command:S.union([S.string(),S.array(S.string())])})).default({}),theme:S.union([S.string(),S.record(S.string(),S.unknown())]).optional(),themeBackground:S.string().optional()}),xo=S.string().min(1).regex(/^[A-Za-z0-9._-]+$/,"extension name must be filename-safe"),gu=S.object({command:S.array(S.string()).default([]),args:S.array(S.string()).default([]),env:S.record(S.string()).default({}),enabled:S.boolean().default(!0)}),mu=S.object({command:S.array(S.string()).default([]),args:S.array(S.string()).default([]),env:S.record(S.string()).default({}),enabled:S.boolean().default(!0)}),hu=S.object({daemon:tu.default({}),registry:nu.default({url:Eo,ttlHours:24,pinned:!1}),agents:S.record(S.string(),su).default({}),agentOverrides:S.record(S.string(),ru).default({}),defaultAgent:S.string().default("opencode"),defaultModels:S.record(S.string(),S.string()).default({}),synopsisAgent:S.string().optional(),synopsisModel:S.string().optional(),compaction:S.object({agent:S.string().optional(),model:S.string().optional(),tailK:S.number().int().nonnegative().default(20),maxIterations:S.number().int().positive().default(3),contextFraction:S.number().min(0).max(1).default(.5),hardCeilingFraction:S.number().min(0).max(1).default(.85),absoluteFallback:S.number().int().positive().default(2e5),idleBeforePromptMs:S.number().int().nonnegative().default(3e5),modelContextWindows:S.record(S.string(),S.number().int().positive()).default({})}).default({}),defaultCwd:S.string().default("~"),disableWorkspaceSnapshots:S.boolean().optional(),compressToolContent:S.boolean().default(!0),sessionListColdLimit:S.number().int().nonnegative().default(20),extensions:S.record(xo,gu).default({}),transformers:S.record(xo,mu).default({}),defaultTransformers:S.array(S.string()).default([]),npmRegistry:S.string().url().optional(),tui:pu.default({})});function Po(s){return Object.entries(s.extensions).map(([e,t])=>({name:e,...t}))}function Mo(s){return Object.entries(s.transformers).map(([e,t])=>({name:e,...t}))}async function _o(){return await yu(),await se(C.config())??{}}async function yu(){let s;try{s=await Je.lstat(C.config())}catch(e){if(e.code==="ENOENT")return;throw e}if(s.isSymbolicLink())try{await Je.stat(C.config())}catch(e){if(e.code!=="ENOENT")throw e;let t=await Je.readlink(C.config()).catch(()=>"<unknown>");throw new Error(`config.json at ${C.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 wu(){let s=await _o(),e=s.daemon,t=e&&typeof e.authToken=="string"?e.authToken:void 0;if(!t)return;let n=!1;try{await Je.access(C.authToken()),n=!0}catch(r){if(r.code!=="ENOENT")throw r}if(n)throw new Error(`Auth token present in both ${C.authToken()} and ${C.config()} (daemon.authToken). Remove daemon.authToken from config.json to resolve.`);await Ps(t),delete e.authToken,Object.keys(e).length===0&&delete s.daemon,await ye(C.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated auth token from ${C.config()} to ${C.authToken()}.
6
+ `)}async function Lt(){return await wu(),hu.parse(await _o())}function ie(s){return s==="~"||s==="$HOME"?Hs():s.startsWith("~/")?Hs()+s.slice(1):s.startsWith("$HOME/")?Hs()+s.slice(5):s}import*as wc from"fs";import*as Ue from"fs/promises";import*as kc from"net";import*as Nt from"path";import*as vc from"tls";import Jm from"fastify";import Vm from"@fastify/websocket";var $o="acp.v1";function Oo(s,e){return s.has($o)?$o:!1}import hc from"pino";import Gm from"pino-roll";var ku={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"]},Fo="HYDRA_ACP_SESSION",vu=[Fo],bu=[...Object.values(ku).flat(),...vu];function kn(s,e){return s?{...e??{},[Fo]:s}:e}var No=[];function Ds(s){No=s?[...s]:[]}function Su(s,e){return e.endsWith("*")?s.startsWith(e.slice(0,-1)):s===e}function Iu(){return[...bu,...No]}function vn(s=process.env){let e=Iu(),t={};for(let[n,r]of Object.entries(s))r!==void 0&&(e.some(o=>Su(n,o))||(t[n]=r));return t}Q();import*as ae from"fs/promises";import{createHash as Au}from"crypto";import{gzip as Cu,gunzip as Ru}from"zlib";import{promisify as Ho}from"util";var jo=Ho(Cu),xu=Ho(Ru),Do=/^[A-Za-z0-9_-]+$/,Eu=/^[a-f0-9]{64}$/,Us=!0;function Uo(s){Us=s}function bn(s,e){return Do.test(s)?e===void 0||Eu.test(e):!1}function Sn(s,e){return`${C.toolBlobFile(s,e)}.gz`}async function Ls(s,e){if(!bn(s))return null;let t=Au("sha256").update(e,"utf8").digest("hex"),n=Sn(s,t),r=C.toolBlobFile(s,t);for(let a of[n,r])try{return await ae.access(a),t}catch{}await ae.mkdir(C.toolsDir(s),{recursive:!0});let o=Us?n:r,i=Us?await jo(Buffer.from(e,"utf8")):Buffer.from(e,"utf8");return await ae.writeFile(o,i,{mode:384,flag:"wx"}).catch(async a=>{if(a.code!=="EEXIST")throw a}),t}async function Bt(s,e){if(!bn(s,e))return null;try{let t=await ae.readFile(Sn(s,e));return(await xu(t)).toString("utf8")}catch{}try{return await ae.readFile(C.toolBlobFile(s,e),"utf8")}catch{return null}}async function Lo(s,e){if(!bn(s,e))return null;try{return await ae.readFile(Sn(s,e))}catch{}try{let t=await ae.readFile(C.toolBlobFile(s,e));return await jo(t)}catch{return null}}async function Bo(s,e,t){if(!bn(s,e))return;let n=Sn(s,e);try{await ae.access(n);return}catch{}await ae.mkdir(C.toolsDir(s),{recursive:!0}),await ae.writeFile(n,t,{mode:384,flag:"wx"}).catch(r=>{if(r.code!=="EEXIST")throw r})}async function Wo(s){Do.test(s)&&await ae.rm(C.toolsDir(s),{recursive:!0,force:!0}).catch(()=>{})}Q();import*as ti from"fs/promises";import*as An from"path";import{z as D}from"zod";Le();Q();import*as zo from"fs";import*as fe from"fs/promises";import*as Ve from"path";import{spawn as Jo}from"child_process";import{Readable as Tu}from"stream";function Pe(){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 qs(s,e=Pe()){if(e)return s[e]}var ft=s=>{process.stderr.write(s+`
7
7
  `)};function zs(s){ft=s??(e=>process.stderr.write(e+`
8
- `))}async function Jo(s){if(!s.target.archive)throw new Error(`Agent ${s.agentId} has no archive URL for ${Pe()??"this platform"}`);if(!s.target.cmd)throw new Error(`Agent ${s.agentId} has no cmd in its binary target`);let e=Pe();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=C.agentInstallDir(s.agentId,e,s.version),n=Ve.resolve(t,s.target.cmd);if(await Ws(n))return n;if(await Tu({agentId:s.agentId,version:s.version,archiveUrl:s.target.archive,installDir:t,onProgress:s.onProgress}),!await Ws(n))throw new Error(`Agent ${s.agentId}: extracted archive did not contain ${s.target.cmd} (looked in ${t})`);return process.platform!=="win32"&&await fe.chmod(n,493).catch(()=>{}),n}async function Tu(s){await fe.mkdir(Ve.dirname(s.installDir),{recursive:!0});let e=await fe.mkdtemp(`${s.installDir}.partial-`);try{ft(`hydra-acp: downloading ${s.agentId} from ${s.archiveUrl}`);let t=await Pu({url:s.archiveUrl,dir:e,agentId:s.agentId,version:s.version,onProgress:s.onProgress});ft(`hydra-acp: extracting ${s.agentId}`),pt(s.onProgress,{phase:"extract",agentId:s.agentId,version:s.version}),await _u(t,e),await fe.unlink(t).catch(()=>{});try{await fe.rename(e,s.installDir)}catch(n){let r=n;if((r.code==="EEXIST"||r.code==="ENOTEMPTY")&&await Ws(s.installDir)){await fe.rm(e,{recursive:!0,force:!0}).catch(()=>{}),pt(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw n}ft(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),pt(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await fe.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function pt(s,e){if(s)try{s(e)}catch{}}async function Pu(s){let e=Mu(s.url),t=Ve.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=qo.createWriteStream(t),i=Eu.fromWeb(n.body);pt(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,pt(s.onProgress,{phase:"download_progress",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r})),f-d>=u&&(d=f,ft(Wo(s.agentId,a,r)))}),await new Promise((p,f)=>{i.on("error",f),o.on("error",f),o.on("finish",()=>p()),i.pipe(o)}),ft(Wo(s.agentId,a,r,!0)),pt(s.onProgress,{phase:"download_done",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r}),t}function Wo(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 Mu(s){let e=new URL(s);return Ve.posix.basename(e.pathname)||"archive"}async function _u(s,e){let t=s.toLowerCase();if(t.endsWith(".tar.gz")||t.endsWith(".tgz")||t.endsWith(".tar")){await Bs("tar",["-xf",s,"-C",e]);return}if(t.endsWith(".zip")){if(await $u("unzip")){await Bs("unzip",["-q",s,"-d",e]);return}await Bs("tar",["-xf",s,"-C",e]);return}throw new Error(`Unsupported archive format: ${s}`)}function Bs(s,e){return new Promise((t,n)=>{let r=zo(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 $u(s){return new Promise(e=>{let t=process.platform==="win32"?"where":"which",n=zo(t,[s],{stdio:"ignore"});n.on("error",()=>e(!1)),n.on("exit",r=>e(r===0))})}async function Ws(s){try{return await fe.access(s),!0}catch{return!1}}Q();import*as we from"fs/promises";import*as Me from"path";import{spawn as Ou}from"child_process";var Vs=s=>{process.stderr.write(s+`
8
+ `))}async function Vo(s){if(!s.target.archive)throw new Error(`Agent ${s.agentId} has no archive URL for ${Pe()??"this platform"}`);if(!s.target.cmd)throw new Error(`Agent ${s.agentId} has no cmd in its binary target`);let e=Pe();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=C.agentInstallDir(s.agentId,e,s.version),n=Ve.resolve(t,s.target.cmd);if(await Ws(n))return n;if(await Pu({agentId:s.agentId,version:s.version,archiveUrl:s.target.archive,installDir:t,onProgress:s.onProgress}),!await Ws(n))throw new Error(`Agent ${s.agentId}: extracted archive did not contain ${s.target.cmd} (looked in ${t})`);return process.platform!=="win32"&&await fe.chmod(n,493).catch(()=>{}),n}async function Pu(s){await fe.mkdir(Ve.dirname(s.installDir),{recursive:!0});let e=await fe.mkdtemp(`${s.installDir}.partial-`);try{ft(`hydra-acp: downloading ${s.agentId} from ${s.archiveUrl}`);let t=await Mu({url:s.archiveUrl,dir:e,agentId:s.agentId,version:s.version,onProgress:s.onProgress});ft(`hydra-acp: extracting ${s.agentId}`),pt(s.onProgress,{phase:"extract",agentId:s.agentId,version:s.version}),await $u(t,e),await fe.unlink(t).catch(()=>{});try{await fe.rename(e,s.installDir)}catch(n){let r=n;if((r.code==="EEXIST"||r.code==="ENOTEMPTY")&&await Ws(s.installDir)){await fe.rm(e,{recursive:!0,force:!0}).catch(()=>{}),pt(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw n}ft(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),pt(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await fe.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function pt(s,e){if(s)try{s(e)}catch{}}async function Mu(s){let e=_u(s.url),t=Ve.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=zo.createWriteStream(t),i=Tu.fromWeb(n.body);pt(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,pt(s.onProgress,{phase:"download_progress",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r})),f-d>=u&&(d=f,ft(qo(s.agentId,a,r)))}),await new Promise((p,f)=>{i.on("error",f),o.on("error",f),o.on("finish",()=>p()),i.pipe(o)}),ft(qo(s.agentId,a,r,!0)),pt(s.onProgress,{phase:"download_done",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r}),t}function qo(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 _u(s){let e=new URL(s);return Ve.posix.basename(e.pathname)||"archive"}async function $u(s,e){let t=s.toLowerCase();if(t.endsWith(".tar.gz")||t.endsWith(".tgz")||t.endsWith(".tar")){await Bs("tar",["-xf",s,"-C",e]);return}if(t.endsWith(".zip")){if(await Ou("unzip")){await Bs("unzip",["-q",s,"-d",e]);return}await Bs("tar",["-xf",s,"-C",e]);return}throw new Error(`Unsupported archive format: ${s}`)}function Bs(s,e){return new Promise((t,n)=>{let r=Jo(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 Ou(s){return new Promise(e=>{let t=process.platform==="win32"?"where":"which",n=Jo(t,[s],{stdio:"ignore"});n.on("error",()=>e(!1)),n.on("exit",r=>e(r===0))})}async function Ws(s){try{return await fe.access(s),!0}catch{return!1}}Q();import*as we from"fs/promises";import*as Me from"path";import{spawn as Fu}from"child_process";var Vs=s=>{process.stderr.write(s+`
9
9
  `)};function Gs(s){Vs=s??(e=>process.stderr.write(e+`
10
- `))}async function Go(s){let e=Pe();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=C.agentNpmInstallDir(s.agentId,e,s.version),n=Du(s.packageSpec),r=Uu(n),o={installDir:t,packageName:n,hint:s.bin,basename:r},i=Me.join(t,"node_modules",".bin",s.bin);if(await et(i))return i;if(await et(t)){let l=await Vo(o);if(l)return l.binPath}await Fu({agentId:s.agentId,version:s.version,packageSpec:s.packageSpec,installDir:t,registry:s.registry,onProgress:s.onProgress});let a=await Vo(o);if(a)return a.binPath;let d=await Qo(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 Fu(s){await we.mkdir(Me.dirname(s.installDir),{recursive:!0});let e=await we.mkdtemp(`${s.installDir}.partial-`);try{Vs(`hydra-acp: installing ${s.packageSpec} for ${s.agentId} into ${e}`),Js(s.onProgress,{phase:"install_start",agentId:s.agentId,version:s.version,packageSpec:s.packageSpec}),await ju({packageSpec:s.packageSpec,cwd:e,registry:s.registry});try{await we.rename(e,s.installDir)}catch(t){let n=t;if((n.code==="EEXIST"||n.code==="ENOTEMPTY")&&await et(s.installDir)){await we.rm(e,{recursive:!0,force:!0}).catch(()=>{}),Js(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw t}Vs(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),Js(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await we.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function Js(s,e){if(s)try{s(e)}catch{}}var Nu=5,Hu=25;function ju(s){return Ko(s,0)}async function Ko(s,e){try{await new Promise((t,n)=>{let r=s.registry?["--registry",s.registry]:[],o;try{o=Ou("npm",["install","--no-audit","--no-fund","--silent",...r,s.packageSpec],{cwd:s.cwd,stdio:["ignore","pipe","pipe"]})}catch(a){n(a);return}let i="";o.stdout?.on("data",a=>{}),o.stderr?.setEncoding("utf8"),o.stderr?.on("data",a=>{i=(i+a).slice(-4096)}),o.on("error",a=>{if(a.code==="ENOENT"){n(new Error("npm not found on PATH (install Node.js / npm, or use a binary-distributed agent)"));return}n(a)}),o.on("exit",(a,d)=>{if(a===0){t();return}let c=a!==null?`exit code ${a}`:`signal ${d??"unknown"}`,u=i.trim();n(new Error(u?`npm install ${s.packageSpec} failed (${c})
11
- stderr: ${u}`:`npm install ${s.packageSpec} failed (${c})`))})})}catch(t){if(t.code==="ETXTBSY"&&e<Nu)return await new Promise(r=>setTimeout(r,Hu*(e+1))),Ko(s,e+1);throw t}}function Du(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 Uu(s){let e=s.lastIndexOf("/");return e===-1?s:s.slice(e+1)}async function Qo(s,e){let t=Me.join(s,"node_modules",e,"package.json");try{let n=await we.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 Vo(s){let e=Me.join(s.installDir,"node_modules",".bin"),t=Me.join(e,s.hint);if(await et(t))return{binName:s.hint,binPath:t};let n=await Qo(s.installDir,s.packageName);if(typeof n=="object"&&n!==null){let r=Object.keys(n);if(r.length===1){let o=r[0],i=Me.join(e,o);if(await et(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=Me.join(e,o);if(await et(i))return{binName:o,binPath:i}}}}if(s.basename!==s.hint){let r=Me.join(e,s.basename);if(await et(r))return{binName:s.basename,binPath:r}}}async function et(s){try{return await we.access(s),!0}catch{return!1}}var Lu=D.object({package:D.string(),bin:D.string().optional(),args:D.array(D.string()).optional(),env:D.record(D.string()).optional()}),gt=D.object({archive:D.string().url().optional(),cmd:D.string().optional(),args:D.array(D.string()).optional(),env:D.record(D.string()).optional()}),Bu=D.object({"darwin-aarch64":gt.optional(),"darwin-x86_64":gt.optional(),"linux-aarch64":gt.optional(),"linux-x86_64":gt.optional(),"windows-x86_64":gt.optional(),"windows-aarch64":gt.optional()}),Wu=D.object({package:D.string(),args:D.array(D.string()).optional(),env:D.record(D.string()).optional()}),qu=D.object({command:D.string(),args:D.array(D.string()).optional(),env:D.record(D.string()).optional()}),zu=D.object({command:D.string().optional(),url:D.string().optional(),description:D.string().optional()}),Ju=D.object({npx:Lu.optional(),binary:Bu.optional(),uvx:Wu.optional(),exec:qu.optional()}),Vu=D.object({id:D.string(),name:D.string(),version:D.string().optional(),description:D.string().optional(),authors:D.array(D.string()).optional(),license:D.string().optional(),icon:D.string().optional(),repository:D.string().optional(),website:D.string().optional(),distribution:Ju,onboarding:zu.optional(),requiredEnv:D.array(D.string().min(1)).optional()}),Yo=8;function ti(s){return s.installId??s.id}function Qs(s){let e=s.extendsChain;return e&&e.length>0?e[e.length-1]:s.id}function Wt(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}}}var Xo=D.object({version:D.string(),agents:D.array(Vu),extensions:D.array(D.unknown()).optional()}),In=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{...Ks(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>=Yo)throw new Error(`agent ${n.id}: extends chain deeper than ${Yo} (${[...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(Ku(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=>Ys(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])=>Ks(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=Qu(n.packageSpec),i=t.id,r={...r,npx:{...r.npx,package:n.packageSpec}}),n.extraArgs?.length&&(r=Gu(r,n.extraArgs)),n.env&&Object.keys(n.env).length>0&&(r=ni(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=Xo.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 se(C.registryCache());if(!(!e||typeof e.fetchedAt!="number"||e.data===void 0))try{let t=Xo.parse(e.data);return{fetchedAt:e.fetchedAt,raw:e.data,data:t}}catch{return}}async writeDiskCache(e){await ye(C.registryCache(),{fetchedAt:e.fetchedAt,data:e.raw})}};function Ks(s,e){return{id:s,name:e.name??s,description:e.description,version:"local",distribution:{exec:{command:ie(e.command??s),args:e.args?.map(ie),env:e.env}}}}function ni(s,e){let t=e.args?.map(ie),n=r=>({...r,...t?{args:t}:{},...e.env?{env:{...r.env,...e.env}}:{}});return{...s.npx?{npx:n(s.npx)}:{},...s.uvx?{uvx:n(s.uvx)}:{},...s.exec?{exec:n(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([r,o])=>[r,o&&n(o)]))}:{}}}function Gu(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 Ku(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?Ks(s,e).distribution:ni(t.distribution,e),installId:n?s:t.installId??t.id,extendsChain:[s,...t.extendsChain??[t.id]]}}function Qu(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 Ys(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 mt(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 Xs(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 Xs(s){let e=Pe();if(!e)return"no";let t=s.version??"current",n=ti(s);if(s.distribution.exec)return"yes";if(s.distribution.binary){let r=qs(s.distribution.binary,e);if(r?.cmd){let o=An.resolve(C.agentInstallDir(n,e,t),r.cmd);if(await Zo(o))return"yes"}}if(s.distribution.npx){let r=s.distribution.npx,o=r.bin??Ys(s)??r.package,i=C.agentNpmInstallDir(n,e,t),a=An.join(i,"node_modules",".bin",o);if(await Zo(a))return"yes"}return!s.distribution.npx&&!s.distribution.binary&&s.distribution.uvx?"lazy":"no"}async function Zo(s){try{return await ei.access(s),!0}catch{return!1}}async function Ie(s,e=[],t={}){let n=s.version??"current",r=ti(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??Ys(s)??o.package,d=t.onInstallProgress;return{command:await Go({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=qs(s.distribution.binary);if(!o)throw new Error(`Agent ${s.id} has no binary distribution for ${Pe()??"this platform"}.`);let i=t.onInstallProgress,a=await Jo({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 tl}from"child_process";import*as xn from"fs";import*as ki from"path";var A={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 K}from"zod";var si=K.object({protocolVersion:K.number().optional(),clientCapabilities:K.record(K.unknown()).optional(),clientInfo:K.object({name:K.string(),version:K.string().optional()}).optional()}),Yu=K.enum(["full","pending_only","none","after_message"]),ri=K.object({cwd:K.string(),mcpServers:K.array(K.unknown()).optional(),_meta:K.record(K.unknown()).optional()}),oi=K.object({upstreamSessionId:K.string(),agentId:K.string(),cwd:K.string(),title:K.string().optional(),agentArgs:K.array(K.string()).optional()}),ii=K.object({sessionId:K.string(),historyPolicy:Yu.default("full"),afterMessageId:K.string().optional(),clientId:K.string().optional(),clientInfo:K.object({name:K.string(),version:K.string().optional()}).optional(),_meta:K.record(K.unknown()).optional()});import{z as N}from"zod";var ai=N.object({sessionId:N.string()}),di=N.object({cwd:N.string().optional(),cursor:N.string().optional()}),Zs=N.object({used:N.number().optional(),size:N.number().optional(),costAmount:N.number().optional(),costCurrency:N.string().optional()}),oy=N.object({sessionId:N.string(),upstreamSessionId:N.string().optional(),cwd:N.string(),workspace:N.object({path:N.string(),sourceCwd:N.string(),label:N.string(),provider:N.string(),snapshot:N.string().optional(),vcs:N.record(N.string(),N.string()).optional()}).optional(),workspaceError:N.string().optional(),title:N.string().optional(),agentId:N.string().optional(),currentModel:N.string().optional(),currentUsage:Zs.optional(),importedFromMachine:N.string().optional(),importedFromUpstreamSessionId:N.string().optional(),parentSessionId:N.string().optional(),forkedFromSessionId:N.string().optional(),forkedFromMessageId:N.string().optional(),originatingClient:N.object({name:N.string(),version:N.string().optional()}).optional(),interactive:N.boolean().optional(),priority:N.number().int().nonnegative().optional(),updatedAt:N.string(),attachedClients:N.number().int().nonnegative(),status:N.enum(["warm","cold"]).default("warm"),busy:N.boolean().default(!1),awaitingInput:N.boolean().default(!1),armedTasks:N.number().int().nonnegative().optional(),armedSince:N.number().int().positive().optional(),compactionState:N.any().optional(),agentPid:N.number().int().positive().optional(),forkSynthesisState:N.enum(["running","failed"]).optional(),_meta:N.record(N.unknown()).optional()}),Xu=N.object({sessionId:N.string(),cwd:N.string(),title:N.string().optional(),updatedAt:N.string().optional(),_meta:N.record(N.unknown()).optional()}),iy=N.object({sessions:N.array(Xu),nextCursor:N.string().optional()});function Cn(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.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.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.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 ci(s){let e={sessionId:s.sessionId,cwd:s.cwd,updatedAt:s.updatedAt,_meta:qt(s._meta,Cn(s))};return s.title!==void 0&&(e.title=s.title),e}var pe="hydra-acp";function Zu(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 tt(s){if(!s)return{};let e=s[pe];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 r=t.workspace,o={};typeof r.label=="string"&&(o.label=r.label),typeof r.from=="string"&&(o.from=r.from),r.required===!0&&(o.required=!0),typeof r.provider=="string"&&(o.provider=r.provider),n.workspace=o}if(t.workspaceInfo!==null&&typeof t.workspaceInfo=="object"&&!Array.isArray(t.workspaceInfo)){let r=t.workspaceInfo;if(typeof r.path=="string"&&typeof r.sourceCwd=="string"&&typeof r.label=="string"&&typeof r.provider=="string"){let o={path:r.path,sourceCwd:r.sourceCwd,label:r.label,provider:r.provider};if(typeof r.snapshot=="string"&&(o.snapshot=r.snapshot),r.vcs!==null&&typeof r.vcs=="object"&&!Array.isArray(r.vcs)){let i={};for(let[a,d]of Object.entries(r.vcs))typeof d=="string"&&(i[a]=d);o.vcs=i}n.workspaceInfo=o}}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),(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(r=>typeof r=="string")&&(n.agentArgs=t.agentArgs),Array.isArray(t.transformers)&&t.transformers.every(r=>typeof r=="string")&&(n.transformers=t.transformers),t.resume){let r=oi.safeParse(t.resume);r.success&&(n.resume=r.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 r=Zs.safeParse(t.currentUsage);r.success&&(n.currentUsage=r.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 r=[];for(let o of t.armedTaskList){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;typeof i.label!="string"||typeof i.since!="number"||r.push({label:i.label,since:i.since,...typeof i.taskId=="string"?{taskId:i.taskId}:{},...typeof i.taskType=="string"?{taskType:i.taskType}:{},...typeof i.toolCallId=="string"?{toolCallId:i.toolCallId}:{}})}n.armedTaskList=r}if(Array.isArray(t.availableCommands)){let r=[];for(let o of t.availableCommands){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.name!="string")continue;let a={name:i.name};typeof i.description=="string"&&(a.description=i.description),r.push(a)}r.length>0&&(n.availableCommands=r)}if(t.prompt&&typeof t.prompt=="object"&&!Array.isArray(t.prompt)){let r=t.prompt,o={};typeof r.queueing=="boolean"&&(o.queueing=r.queueing),typeof r.cancelling=="boolean"&&(o.cancelling=r.cancelling),typeof r.updating=="boolean"&&(o.updating=r.updating),typeof r.amending=="boolean"&&(o.amending=r.amending),typeof r.pipelining=="boolean"&&(o.pipelining=r.pipelining),n.prompt=o}if(t.agents&&typeof t.agents=="object"&&!Array.isArray(t.agents)){let r=t.agents,o={};typeof r.list=="boolean"&&(o.list=r.list),typeof r.installProgress=="boolean"&&(o.installProgress=r.installProgress),n.agents=o}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 r=t.salvaged;typeof r.reason=="string"&&typeof r.supersededMessageId=="string"&&(n.salvaged={reason:r.reason,supersededMessageId:r.supersededMessageId})}if(Array.isArray(t.queue)){let r=[];for(let o of t.queue){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o,a=i.originator;if(typeof i.messageId!="string"||!a||typeof a.clientId!="string"||!Array.isArray(i.prompt)||typeof i.position!="number"||typeof i.enqueuedAt!="number")continue;let d={clientId:a.clientId};typeof a.name=="string"&&(d.name=a.name),typeof a.version=="string"&&(d.version=a.version),r.push({messageId:i.messageId,originator:d,prompt:i.prompt,position:i.position,enqueuedAt:i.enqueuedAt})}r.length>0&&(n.queue=r)}if(Array.isArray(t.availableModes)){let r=[];for(let o of t.availableModes){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.id!="string")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)}r.length>0&&(n.availableModes=r)}if(Array.isArray(t.availableModels)){let r=[];for(let o of t.availableModels){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.modelId!="string")continue;let a={modelId:i.modelId};typeof i.name=="string"&&(a.name=i.name),typeof i.description=="string"&&(a.description=i.description),r.push(a)}r.length>0&&(n.availableModels=r)}if((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),t.originatingClient&&typeof t.originatingClient=="object"&&!Array.isArray(t.originatingClient)&&typeof t.originatingClient.name=="string"){let r=t.originatingClient;n.originatingClient={name:r.name,...typeof r.version=="string"?{version:r.version}:{}}}if(t.agentCapabilities!==void 0&&(n.agentCapabilities=t.agentCapabilities),t.env!==void 0){let r=Zu(t.env);r!==void 0&&(n.env=r)}return n}function _e(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[pe],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.recordedAt=="number"?s:{...t,_meta:{...n,[pe]:{...o,recordedAt:e}}}}function qt(s,e){return{...s??{},[pe]:e}}import{z as M}from"zod";var ui=M.object({sessionId:M.string(),prompt:M.array(M.unknown()),_meta:M.record(M.unknown()).optional()}),Rn=M.object({sessionId:M.string()}),li=M.object({clientId:M.string(),name:M.string().optional(),version:M.string().optional()}),fy=M.object({sessionId:M.string(),messageId:M.string(),originator:li,prompt:M.array(M.unknown()),position:M.number().int().nonnegative(),queueDepth:M.number().int().positive(),enqueuedAt:M.number()}),py=M.object({sessionId:M.string(),messageId:M.string(),prompt:M.array(M.unknown())}),gy=M.object({sessionId:M.string(),messageId:M.string(),reason:M.enum(["started","cancelled","abandoned"])}),fi=M.object({sessionId:M.string(),messageId:M.string()}),my=M.object({cancelled:M.boolean(),reason:M.enum(["ok","not_found","already_running"])}),pi=M.object({sessionId:M.string(),messageId:M.string(),prompt:M.array(M.unknown())}),hy=M.object({updated:M.boolean(),reason:M.enum(["ok","not_found","already_running"])}),gi=M.object({sessionId:M.string(),targetMessageId:M.string(),prompt:M.array(M.unknown()),replaceQueue:M.boolean().optional(),onTargetCompleted:M.enum(["reject","send_anyway"]).optional()}),yy=M.object({amended:M.boolean(),reason:M.enum(["ok","target_completed","target_cancelled","target_not_found"]),messageId:M.string().optional()}),mi=M.object({sessionId:M.string(),prompt:M.array(M.unknown()),_meta:M.object({steering:M.object({idleBehavior:M.literal("promptRequired").optional()}).optional()}).optional()}),wy=M.object({outcome:M.enum(["injected","startedNewTurn","promptRequired","failed"]),reason:M.literal("noRunningTurn").optional()}),ky=M.object({sessionId:M.string(),cancelledMessageId:M.string(),newMessageId:M.string(),prompt:M.array(M.unknown()),originator:li,amendedAt:M.number()});import{z as Ge}from"zod";var Sy=Ge.object({agentId:Ge.string(),version:Ge.string(),source:Ge.enum(["binary","npm"]),phase:Ge.enum(["download_start","download_progress","download_done","extract","install_start","installed"]),receivedBytes:Ge.number().optional(),totalBytes:Ge.number().optional(),packageSpec:Ge.string().optional()}),hi="hydra-acp/agents/install_progress",ht={auth:{terminal:!0},_meta:{"terminal-auth":!0}};function yi(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(`
10
+ `))}async function Ko(s){let e=Pe();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=C.agentNpmInstallDir(s.agentId,e,s.version),n=Uu(s.packageSpec),r=Lu(n),o={installDir:t,packageName:n,hint:s.bin,basename:r},i=Me.join(t,"node_modules",".bin",s.bin);if(await et(i))return i;if(await et(t)){let l=await Go(o);if(l)return l.binPath}await Nu({agentId:s.agentId,version:s.version,packageSpec:s.packageSpec,installDir:t,registry:s.registry,onProgress:s.onProgress});let a=await Go(o);if(a)return a.binPath;let d=await Yo(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 Nu(s){await we.mkdir(Me.dirname(s.installDir),{recursive:!0});let e=await we.mkdtemp(`${s.installDir}.partial-`);try{Vs(`hydra-acp: installing ${s.packageSpec} for ${s.agentId} into ${e}`),Js(s.onProgress,{phase:"install_start",agentId:s.agentId,version:s.version,packageSpec:s.packageSpec}),await Du({packageSpec:s.packageSpec,cwd:e,registry:s.registry});try{await we.rename(e,s.installDir)}catch(t){let n=t;if((n.code==="EEXIST"||n.code==="ENOTEMPTY")&&await et(s.installDir)){await we.rm(e,{recursive:!0,force:!0}).catch(()=>{}),Js(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw t}Vs(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),Js(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await we.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function Js(s,e){if(s)try{s(e)}catch{}}var Hu=5,ju=25;function Du(s){return Qo(s,0)}async function Qo(s,e){try{await new Promise((t,n)=>{let r=s.registry?["--registry",s.registry]:[],o;try{o=Fu("npm",["install","--no-audit","--no-fund","--silent",...r,s.packageSpec],{cwd:s.cwd,stdio:["ignore","pipe","pipe"]})}catch(a){n(a);return}let i="";o.stdout?.on("data",a=>{}),o.stderr?.setEncoding("utf8"),o.stderr?.on("data",a=>{i=(i+a).slice(-4096)}),o.on("error",a=>{if(a.code==="ENOENT"){n(new Error("npm not found on PATH (install Node.js / npm, or use a binary-distributed agent)"));return}n(a)}),o.on("exit",(a,d)=>{if(a===0){t();return}let c=a!==null?`exit code ${a}`:`signal ${d??"unknown"}`,u=i.trim();n(new Error(u?`npm install ${s.packageSpec} failed (${c})
11
+ stderr: ${u}`:`npm install ${s.packageSpec} failed (${c})`))})})}catch(t){if(t.code==="ETXTBSY"&&e<Hu)return await new Promise(r=>setTimeout(r,ju*(e+1))),Qo(s,e+1);throw t}}function Uu(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 Lu(s){let e=s.lastIndexOf("/");return e===-1?s:s.slice(e+1)}async function Yo(s,e){let t=Me.join(s,"node_modules",e,"package.json");try{let n=await we.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 Go(s){let e=Me.join(s.installDir,"node_modules",".bin"),t=Me.join(e,s.hint);if(await et(t))return{binName:s.hint,binPath:t};let n=await Yo(s.installDir,s.packageName);if(typeof n=="object"&&n!==null){let r=Object.keys(n);if(r.length===1){let o=r[0],i=Me.join(e,o);if(await et(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=Me.join(e,o);if(await et(i))return{binName:o,binPath:i}}}}if(s.basename!==s.hint){let r=Me.join(e,s.basename);if(await et(r))return{binName:s.basename,binPath:r}}}async function et(s){try{return await we.access(s),!0}catch{return!1}}var Bu=D.object({package:D.string(),bin:D.string().optional(),args:D.array(D.string()).optional(),env:D.record(D.string()).optional()}),gt=D.object({archive:D.string().url().optional(),cmd:D.string().optional(),args:D.array(D.string()).optional(),env:D.record(D.string()).optional()}),Wu=D.object({"darwin-aarch64":gt.optional(),"darwin-x86_64":gt.optional(),"linux-aarch64":gt.optional(),"linux-x86_64":gt.optional(),"windows-x86_64":gt.optional(),"windows-aarch64":gt.optional()}),qu=D.object({package:D.string(),args:D.array(D.string()).optional(),env:D.record(D.string()).optional()}),zu=D.object({command:D.string(),args:D.array(D.string()).optional(),env:D.record(D.string()).optional()}),Ju=D.object({command:D.string().optional(),url:D.string().optional(),description:D.string().optional()}),Vu=D.object({npx:Bu.optional(),binary:Wu.optional(),uvx:qu.optional(),exec:zu.optional()}),Gu=D.object({id:D.string(),name:D.string(),version:D.string().optional(),description:D.string().optional(),authors:D.array(D.string()).optional(),license:D.string().optional(),icon:D.string().optional(),repository:D.string().optional(),website:D.string().optional(),distribution:Vu,onboarding:Ju.optional(),requiredEnv:D.array(D.string().min(1)).optional()}),Xo=8;function ni(s){return s.installId??s.id}function Qs(s){let e=s.extendsChain;return e&&e.length>0?e[e.length-1]:s.id}function Wt(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}}}var Zo=D.object({version:D.string(),agents:D.array(Gu),extensions:D.array(D.unknown()).optional()}),In=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{...Ks(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>=Xo)throw new Error(`agent ${n.id}: extends chain deeper than ${Xo} (${[...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(Qu(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=>Ys(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])=>Ks(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=Yu(n.packageSpec),i=t.id,r={...r,npx:{...r.npx,package:n.packageSpec}}),n.extraArgs?.length&&(r=Ku(r,n.extraArgs)),n.env&&Object.keys(n.env).length>0&&(r=si(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=Zo.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 se(C.registryCache());if(!(!e||typeof e.fetchedAt!="number"||e.data===void 0))try{let t=Zo.parse(e.data);return{fetchedAt:e.fetchedAt,raw:e.data,data:t}}catch{return}}async writeDiskCache(e){await ye(C.registryCache(),{fetchedAt:e.fetchedAt,data:e.raw})}};function Ks(s,e){return{id:s,name:e.name??s,description:e.description,version:"local",distribution:{exec:{command:ie(e.command??s),args:e.args?.map(ie),env:e.env}}}}function si(s,e){let t=e.args?.map(ie),n=r=>({...r,...t?{args:t}:{},...e.env?{env:{...r.env,...e.env}}:{}});return{...s.npx?{npx:n(s.npx)}:{},...s.uvx?{uvx:n(s.uvx)}:{},...s.exec?{exec:n(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([r,o])=>[r,o&&n(o)]))}:{}}}function Ku(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 Qu(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?Ks(s,e).distribution:si(t.distribution,e),installId:n?s:t.installId??t.id,extendsChain:[s,...t.extendsChain??[t.id]]}}function Yu(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 Ys(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 mt(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 Xs(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 Xs(s){let e=Pe();if(!e)return"no";let t=s.version??"current",n=ni(s);if(s.distribution.exec)return"yes";if(s.distribution.binary){let r=qs(s.distribution.binary,e);if(r?.cmd){let o=An.resolve(C.agentInstallDir(n,e,t),r.cmd);if(await ei(o))return"yes"}}if(s.distribution.npx){let r=s.distribution.npx,o=r.bin??Ys(s)??r.package,i=C.agentNpmInstallDir(n,e,t),a=An.join(i,"node_modules",".bin",o);if(await ei(a))return"yes"}return!s.distribution.npx&&!s.distribution.binary&&s.distribution.uvx?"lazy":"no"}async function ei(s){try{return await ti.access(s),!0}catch{return!1}}async function Ie(s,e=[],t={}){let n=s.version??"current",r=ni(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??Ys(s)??o.package,d=t.onInstallProgress;return{command:await Ko({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=qs(s.distribution.binary);if(!o)throw new Error(`Agent ${s.id} has no binary distribution for ${Pe()??"this platform"}.`);let i=t.onInstallProgress,a=await Vo({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 nl}from"child_process";import*as xn from"fs";import*as vi from"path";var A={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 K}from"zod";var ri=K.object({protocolVersion:K.number().optional(),clientCapabilities:K.record(K.unknown()).optional(),clientInfo:K.object({name:K.string(),version:K.string().optional()}).optional()}),Xu=K.enum(["full","pending_only","none","after_message"]),oi=K.object({cwd:K.string(),mcpServers:K.array(K.unknown()).optional(),_meta:K.record(K.unknown()).optional()}),ii=K.object({upstreamSessionId:K.string(),agentId:K.string(),cwd:K.string(),title:K.string().optional(),agentArgs:K.array(K.string()).optional()}),ai=K.object({sessionId:K.string(),historyPolicy:Xu.default("full"),afterMessageId:K.string().optional(),clientId:K.string().optional(),clientInfo:K.object({name:K.string(),version:K.string().optional()}).optional(),_meta:K.record(K.unknown()).optional()});import{z as N}from"zod";var di=N.object({sessionId:N.string()}),ci=N.object({cwd:N.string().optional(),cursor:N.string().optional()}),Zs=N.object({used:N.number().optional(),size:N.number().optional(),costAmount:N.number().optional(),costCurrency:N.string().optional()}),iy=N.object({sessionId:N.string(),upstreamSessionId:N.string().optional(),cwd:N.string(),workspace:N.object({path:N.string(),sourceCwd:N.string(),label:N.string(),provider:N.string(),snapshot:N.string().optional(),vcs:N.record(N.string(),N.string()).optional()}).optional(),workspaceError:N.string().optional(),title:N.string().optional(),agentId:N.string().optional(),currentModel:N.string().optional(),currentUsage:Zs.optional(),importedFromMachine:N.string().optional(),importedFromUpstreamSessionId:N.string().optional(),parentSessionId:N.string().optional(),forkedFromSessionId:N.string().optional(),forkedFromMessageId:N.string().optional(),originatingClient:N.object({name:N.string(),version:N.string().optional()}).optional(),interactive:N.boolean().optional(),priority:N.number().int().nonnegative().optional(),updatedAt:N.string(),attachedClients:N.number().int().nonnegative(),status:N.enum(["warm","cold"]).default("warm"),busy:N.boolean().default(!1),awaitingInput:N.boolean().default(!1),armedTasks:N.number().int().nonnegative().optional(),armedSince:N.number().int().positive().optional(),compactionState:N.any().optional(),agentPid:N.number().int().positive().optional(),forkSynthesisState:N.enum(["running","failed"]).optional(),_meta:N.record(N.unknown()).optional()}),Zu=N.object({sessionId:N.string(),cwd:N.string(),title:N.string().optional(),updatedAt:N.string().optional(),_meta:N.record(N.unknown()).optional()}),ay=N.object({sessions:N.array(Zu),nextCursor:N.string().optional()});function Cn(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.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.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.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 ui(s){let e={sessionId:s.sessionId,cwd:s.cwd,updatedAt:s.updatedAt,_meta:qt(s._meta,Cn(s))};return s.title!==void 0&&(e.title=s.title),e}var pe="hydra-acp";function el(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 tt(s){if(!s)return{};let e=s[pe];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 r=t.workspace,o={};typeof r.label=="string"&&(o.label=r.label),typeof r.from=="string"&&(o.from=r.from),r.required===!0&&(o.required=!0),typeof r.provider=="string"&&(o.provider=r.provider),n.workspace=o}if(t.workspaceInfo!==null&&typeof t.workspaceInfo=="object"&&!Array.isArray(t.workspaceInfo)){let r=t.workspaceInfo;if(typeof r.path=="string"&&typeof r.sourceCwd=="string"&&typeof r.label=="string"&&typeof r.provider=="string"){let o={path:r.path,sourceCwd:r.sourceCwd,label:r.label,provider:r.provider};if(typeof r.snapshot=="string"&&(o.snapshot=r.snapshot),r.vcs!==null&&typeof r.vcs=="object"&&!Array.isArray(r.vcs)){let i={};for(let[a,d]of Object.entries(r.vcs))typeof d=="string"&&(i[a]=d);o.vcs=i}n.workspaceInfo=o}}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),(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(r=>typeof r=="string")&&(n.agentArgs=t.agentArgs),Array.isArray(t.transformers)&&t.transformers.every(r=>typeof r=="string")&&(n.transformers=t.transformers),t.resume){let r=ii.safeParse(t.resume);r.success&&(n.resume=r.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 r=Zs.safeParse(t.currentUsage);r.success&&(n.currentUsage=r.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 r=[];for(let o of t.armedTaskList){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;typeof i.label!="string"||typeof i.since!="number"||r.push({label:i.label,since:i.since,...typeof i.taskId=="string"?{taskId:i.taskId}:{},...typeof i.taskType=="string"?{taskType:i.taskType}:{},...typeof i.toolCallId=="string"?{toolCallId:i.toolCallId}:{}})}n.armedTaskList=r}if(Array.isArray(t.availableCommands)){let r=[];for(let o of t.availableCommands){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.name!="string")continue;let a={name:i.name};typeof i.description=="string"&&(a.description=i.description),r.push(a)}r.length>0&&(n.availableCommands=r)}if(t.prompt&&typeof t.prompt=="object"&&!Array.isArray(t.prompt)){let r=t.prompt,o={};typeof r.queueing=="boolean"&&(o.queueing=r.queueing),typeof r.cancelling=="boolean"&&(o.cancelling=r.cancelling),typeof r.updating=="boolean"&&(o.updating=r.updating),typeof r.amending=="boolean"&&(o.amending=r.amending),typeof r.pipelining=="boolean"&&(o.pipelining=r.pipelining),n.prompt=o}if(t.agents&&typeof t.agents=="object"&&!Array.isArray(t.agents)){let r=t.agents,o={};typeof r.list=="boolean"&&(o.list=r.list),typeof r.installProgress=="boolean"&&(o.installProgress=r.installProgress),n.agents=o}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 r=t.salvaged;typeof r.reason=="string"&&typeof r.supersededMessageId=="string"&&(n.salvaged={reason:r.reason,supersededMessageId:r.supersededMessageId})}if(Array.isArray(t.queue)){let r=[];for(let o of t.queue){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o,a=i.originator;if(typeof i.messageId!="string"||!a||typeof a.clientId!="string"||!Array.isArray(i.prompt)||typeof i.position!="number"||typeof i.enqueuedAt!="number")continue;let d={clientId:a.clientId};typeof a.name=="string"&&(d.name=a.name),typeof a.version=="string"&&(d.version=a.version),r.push({messageId:i.messageId,originator:d,prompt:i.prompt,position:i.position,enqueuedAt:i.enqueuedAt})}r.length>0&&(n.queue=r)}if(Array.isArray(t.availableModes)){let r=[];for(let o of t.availableModes){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.id!="string")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)}r.length>0&&(n.availableModes=r)}if(Array.isArray(t.availableModels)){let r=[];for(let o of t.availableModels){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.modelId!="string")continue;let a={modelId:i.modelId};typeof i.name=="string"&&(a.name=i.name),typeof i.description=="string"&&(a.description=i.description),r.push(a)}r.length>0&&(n.availableModels=r)}if((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),t.originatingClient&&typeof t.originatingClient=="object"&&!Array.isArray(t.originatingClient)&&typeof t.originatingClient.name=="string"){let r=t.originatingClient;n.originatingClient={name:r.name,...typeof r.version=="string"?{version:r.version}:{}}}if(t.agentCapabilities!==void 0&&(n.agentCapabilities=t.agentCapabilities),t.env!==void 0){let r=el(t.env);r!==void 0&&(n.env=r)}return n}function _e(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[pe],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.recordedAt=="number"?s:{...t,_meta:{...n,[pe]:{...o,recordedAt:e}}}}function qt(s,e){return{...s??{},[pe]:e}}import{z as M}from"zod";var li=M.object({sessionId:M.string(),prompt:M.array(M.unknown()),_meta:M.record(M.unknown()).optional()}),Rn=M.object({sessionId:M.string()}),fi=M.object({clientId:M.string(),name:M.string().optional(),version:M.string().optional()}),py=M.object({sessionId:M.string(),messageId:M.string(),originator:fi,prompt:M.array(M.unknown()),position:M.number().int().nonnegative(),queueDepth:M.number().int().positive(),enqueuedAt:M.number()}),gy=M.object({sessionId:M.string(),messageId:M.string(),prompt:M.array(M.unknown())}),my=M.object({sessionId:M.string(),messageId:M.string(),reason:M.enum(["started","cancelled","abandoned"])}),pi=M.object({sessionId:M.string(),messageId:M.string()}),hy=M.object({cancelled:M.boolean(),reason:M.enum(["ok","not_found","already_running"])}),gi=M.object({sessionId:M.string(),messageId:M.string(),prompt:M.array(M.unknown())}),yy=M.object({updated:M.boolean(),reason:M.enum(["ok","not_found","already_running"])}),mi=M.object({sessionId:M.string(),targetMessageId:M.string(),prompt:M.array(M.unknown()),replaceQueue:M.boolean().optional(),onTargetCompleted:M.enum(["reject","send_anyway"]).optional()}),wy=M.object({amended:M.boolean(),reason:M.enum(["ok","target_completed","target_cancelled","target_not_found"]),messageId:M.string().optional()}),hi=M.object({sessionId:M.string(),prompt:M.array(M.unknown()),_meta:M.object({steering:M.object({idleBehavior:M.literal("promptRequired").optional()}).optional()}).optional()}),ky=M.object({outcome:M.enum(["injected","startedNewTurn","promptRequired","failed"]),reason:M.literal("noRunningTurn").optional(),detached:M.boolean().optional()}),vy=M.object({sessionId:M.string(),cancelledMessageId:M.string(),newMessageId:M.string(),prompt:M.array(M.unknown()),originator:fi,amendedAt:M.number()});import{z as Ge}from"zod";var Iy=Ge.object({agentId:Ge.string(),version:Ge.string(),source:Ge.enum(["binary","npm"]),phase:Ge.enum(["download_start","download_progress","download_done","extract","install_start","installed"]),receivedBytes:Ge.number().optional(),totalBytes:Ge.number().optional(),packageSpec:Ge.string().optional()}),yi="hydra-acp/agents/install_progress",ht={auth:{terminal:!0},_meta:{"terminal-auth":!0}};function wi(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(`
12
12
  `);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:A.ParseError,message:`Failed to parse ndjson line: ${u.message}`}})}d=t.indexOf(`
13
13
  `)}}),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)+`
14
- `;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 el}from"nanoid";var er=class extends Error{code="ERR_CONNECTION_CLOSED";constructor(e="connection is closed"){super(e),this.name="ConnectionClosedError"}},yt=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;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}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}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 er;let n=el(),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?"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:A.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??A.InternalError,message:r.message,data:r.data}).catch(()=>{})}}handleNotification(e){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)}}};Q();var nl=4096,Ke=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??nl,this.killEscalationMs=e.killEscalationMs??sl,this.logger=e.logger,this.fileLog=rl(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()} ---
15
- `),!t.stdout||!t.stdin)throw new Error("agent subprocess missing stdio");let n=yi(t.stdout,t.stdin);this.connection=new yt(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()} ---
14
+ `;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 tl}from"nanoid";var er=class extends Error{code="ERR_CONNECTION_CLOSED";constructor(e="connection is closed"){super(e),this.name="ConnectionClosedError"}},yt=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;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}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}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 er;let n=tl(),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?"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:A.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??A.InternalError,message:r.message,data:r.data}).catch(()=>{})}}handleNotification(e){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)}}};Q();var sl=4096,Ke=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??sl,this.killEscalationMs=e.killEscalationMs??rl,this.logger=e.logger,this.fileLog=ol(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()} ---
15
+ `),!t.stdout||!t.stdin)throw new Error("agent subprocess missing stdio");let n=wi(t.stdout,t.stdin);this.connection=new yt(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()} ---
16
16
  `),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()} ---
17
17
  `),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}
18
- stderr: ${t}`:e}stderrTailText(){return this.stderrTail.trim()}static spawn(e){let t={...vn(),...e.plan.env,...e.extraEnv??{}},n=tl(e.plan.command,e.plan.args,{cwd:e.cwd,env:t,stdio:["pipe","pipe","pipe"],detached:!0});return n.unref(),new s(e,n)}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()} ---
18
+ stderr: ${t}`:e}stderrTailText(){return this.stderrTail.trim()}static spawn(e){let t={...vn(),...e.plan.env,...e.extraEnv??{}},n=nl(e.plan.command,e.plan.args,{cwd:e.cwd,env:t,stdio:["pipe","pipe","pipe"],detached:!0});return n.unref(),new s(e,n)}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()} ---
19
19
  `),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()} ---
20
- `),this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} did not exit after ${e}; sending SIGKILL`),this.signalProcessGroup("SIGKILL"),await this.waitForExit(wi),this.exited||this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} still has not exited ${wi}ms after SIGKILL; giving up on the reap`)))}signalProcessGroup(e){let t=this.child.pid;if(t!==void 0)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)})}},sl=2e3,wi=5e3;function rl(s){try{let e=C.agentLogFile(s);xn.mkdirSync(ki.dirname(e),{recursive:!0});let t=xn.createWriteStream(e,{flags:"a"});return t.on("error",()=>{}),t}catch{return}}import*as at from"fs/promises";import*as Va from"os";import*as vi from"os";function zt(){return vi.hostname()}import*as dn from"path";import{customAlphabet as gp}from"nanoid";var $e="session/set_model",nr="session/set_config_option",Ii="model";function tr(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.availableModels)}function Ai(s){return Array.isArray(s)&&s.some(e=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.id===Ii)}function wt(s){if(!s)return;if(tr(s)||tr(s.models))return $e;let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){for(let[t,n]of Object.entries(e))if(t!=="hydra-acp"&&tr(n))return $e}if(Ai(s.configOptions))return nr}function Ci(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.sessionUpdate;if(e==="_hydra_current_model_update")return $e;if(e==="config_option_update"&&Ai(s.configOptions))return nr}function bi(s){return typeof s=="object"&&s!==null&&s.code===A.MethodNotFound}function Si(s,e,t,n){let r={...n??{}};return delete r.sessionId,delete r.modelId,delete r.configId,delete r.value,s===$e?{...r,sessionId:e,modelId:t}:{...r,sessionId:e,configId:Ii,value:t}}function ol(s){return s===$e?nr:$e}async function Qe(s){let{request:e,sessionId:t,modelId:n,extraParams:r,logger:o}=s,i=s.verb??$e;try{let a=await e(i,Si(i,t,n,r));return{verb:i,result:a}}catch(a){if(!bi(a))throw a;let d=ol(i);o?.info(`agent does not implement ${i} (MethodNotFound); retrying model change via ${d} modelId=${JSON.stringify(n)}`);try{let c=await e(d,Si(d,t,n,r));return{verb:d,result:c}}catch(c){throw bi(c)?a:c}}}async function nt(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 st(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 Qe({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}}}import{customAlphabet as Xi}from"nanoid";import{createHmac as il}from"crypto";function al(s,e){return il("sha256",s).update(e).digest("hex")}function sr(s,e){let t=JSON.stringify(e),n=al(s.secret,t);fetch(s.callbackUrl,{method:"POST",headers:{"Content-Type":"application/json","X-Hydra-Turn-Notify-Signature":n},body:t}).catch(()=>{})}var Ri="edit",En=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 xi(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}import*as Ti from"fs/promises";var dl=64*1024*1024,cl=1*1024*1024,kt=64*1024,ul=6e4,ll=100,fl=1e3,pl=64*1024,gl=256*1024,Ei=20;function ml(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Tn=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??dl,this.maxCapacityBytes<=0)throw new Error("capacityBytes must be > 0");this.currentCapacityBytes=Math.min(cl,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,kt));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,kt)),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,kt)),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,ul));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(ml(e.pattern),d),u=e.invert??!1,l=Math.max(1,Math.min(e.maxMatches??ll,fl)),p=Math.max(1,Math.min(e.maxBytes??pl,gl)),f=Math.max(0,Math.min(e.contextBefore??0,Ei)),m=Math.max(0,Math.min(e.contextAfter??0,Ei)),g=[],h=[],w=[],k=0,y=!1,b=0,I=0,v=(E,O)=>{for(let q of w)q.remaining>0&&(q.match.after===void 0&&(q.match.after=[]),q.match.after.push({cursor:E,line:O}),q.remaining--,k+=O.length);for(;w.length>0&&w[0].remaining===0;)w.shift();if(c.test(O)!==u&&g.length<l){let q={cursor:E,line:O};if(f>0&&h.length>0){q.before=h.slice();for(let ne of q.before)k+=ne.line.length}k+=O.length,g.push(q),m>0&&w.push({match:q,remaining:m})}if(f>0)for(h.push({cursor:E,line:O});h.length>f;)h.shift();let j=g.length>=l&&w.length===0,W=k>=p;return j||W};for(let E=0;E<i.length;E++){if(i[E]!==10)continue;let O=i.subarray(b,E).toString("utf8"),T=r+b;if(b=E+1,I=b,v(T,O)){y=!0;break}}if(!y&&b<i.length&&this.closed){let E=i.subarray(b).toString("utf8"),O=r+b;v(O,E)&&(y=!0),I=i.length}let R=Math.min(r+I,this.writeCursor),x={matches:g,truncated:y,nextCursor:R,scannedBytes:I};return o>0&&(x.gap=o),this.closed&&R>=this.writeCursor&&(x.eof=!0),x}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(()=>Ti.appendFile(t,r)).catch(i=>{this.logWriteError?.(i)}),o&&!this.fileCapReached&&(this.fileCapReached=!0,this.onFileCapReached?.())}async drainFileWrites(){await this.fileWriteChain.catch(()=>{})}};var vt=[{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:"fork",name:"hydra fork",argsHint:"[verbatim]",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)"},{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."}],Yy=new Map(vt.map(s=>[s.verb,s]));function Pi(s){let e=s.lastIndexOf("/");return(e===-1?s:s.slice(e+1)).toLowerCase()}function bt(s,e){return rr(s,e.map(t=>t.modelId))}function rr(s,e){if(e.length===0)return{kind:"none",requested:s};if(e.includes(s))return{kind:"exact",modelId:s};let t=Pi(s),n=e.filter(o=>Pi(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}}function _i(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=or(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 kl){if(!Mi(c[l]))continue;let p=n.get(u);p===void 0?n.set(u,new Map([[l,c[l]]])):p.set(l,c[l])}if(Array.isArray(c.content)&&c.content.length>0){let l=t.get(u);l?l.push(...c.content):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=or(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?yl(r,o.outIndex,hl(c.content)):(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)?wl(d,t.get(l)??[]):d,f=l===void 0?void 0:n.get(l);if(f!==void 0)for(let[m,g]of f)Mi(or(p)?.[m])||(p=vl(p,m,g));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 or(s){if(s.method!=="session/update")return;let t=s.params?.update;if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function hl(s){if(!s||typeof s!="object")return"";let e=s;return typeof e.text=="string"?e.text:""}function yl(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 wl(s,e){let t=s.params??{},n=t.update??{};return{...s,params:{...t,update:{...n,content:e}}}}var kl=["rawInput","locations"];function Mi(s){return s==null||typeof s!="object"?!1:Array.isArray(s)?s.length>0:Object.keys(s).length>0}function vl(s,e,t){let n=s.params??{},r=n.update??{};return{...s,params:{...n,update:{...r,[e]:t}}}}var $i=`[older history truncated]
21
- `,Oi=["file_path","filePath","path","command","pattern","query"];function St(s,e={}){let t=e.maxChars??4e5,n=ir(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=ur(u.prompt).trim();p.length>0&&r.push(`User: ${p}`)}else if(l==="agent_message_chunk"){let p=lr(u.content);p.length>0&&(o+=p)}else if(l==="tool_call"){if(a(),r.push(cr(u,n)),e.toolOutput!==void 0){let p=dr(u),f=p!==void 0?n.get(p)?.output:void 0;if(f!==void 0&&i>0){let m=Math.min(e.toolOutput.maxPerCall,i),g=f.length<=m?f:`${f.slice(0,m)}\u2026[${f.length-m} more chars]`;r.push(`Output: ${g}`),i-=Math.min(g.length,m)}}}else l==="turn_complete"&&a()}return a(),xl(r.join(`
22
- `),t)}function ir(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=dr(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=Sl(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=Pn(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=ar(t);return e}function ar(s){return bl(s)?s.kind??"(unnamed)":s.name}function bl(s){for(let e of Oi){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 Sl(s,e){let t=Jt(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 dr(s){let e=s.toolCallId;if(typeof e=="string"&&e.length>0)return e}function Pn(s){let e=Il(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 Il(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(`
23
- `)}function Jt(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 cr(s,e){let t=dr(s),n=t!==void 0?e?.get(t):void 0,r=n?.name??Al(s),o=Cl(n?.rawInput??s.rawInput);return o.length===0?`Tool: ${r}`:`Tool: ${r}(${o.join(", ")})`}function Al(s){let e=Jt(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 Cl(s){if(!s||typeof s!="object"||Array.isArray(s))return[];let e=s,t=[];for(let n of Oi){let r=e[n];typeof r=="string"&&r.length>0&&t.push(`${n}=${Rl(r,600)}`)}return t}function ur(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 lr(s){if(!s||typeof s!="object")return"";let e=s.text;return typeof e=="string"?e:""}function Rl(s,e){return s.length<=e?s:s.slice(0,e-1)+"\u2026"}function xl(s,e){if(s.length<=e)return s;let t=s.split(`
24
- `);for(;t.length>0;){let n=$i+t.join(`
25
- `);if(n.length<=e)return n;t.shift()}return $i}var Fi="(untitled)";function fr(s){let e=[],t=s.synopsis;if(t!==void 0){e.push("--- begin prior session compaction ---"),e.push(`[Title] ${s.title??Fi}`),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=Vt("Open threads",t.open_threads);d.length>0&&e.push(d);let c=Vt("Decisions",t.decisions);c.length>0&&e.push(c);let u=Vt("File edit intentions",t.file_edit_intentions);u.length>0&&e.push(u);let l=Vt("Unresolved errors",t.unresolved_errors);l.length>0&&e.push(l);let p=Vt("Tool state",t.tool_state);p.length>0&&e.push(p);let f=Ni(t.files_touched);f.length>0&&e.push(`[Files previously touched] ${f}`);let m=Ni(t.tools_used);m.length>0&&e.push(`[Tools previously used] ${m}`),e.push("--- end prior session compaction ---")}else e.push(`[Title] ${s.title??Fi}`);s.note!==void 0&&s.note.trim().length>0&&e.push(`[Situation] ${s.note.trim()}`);let{closedText:n,openText:r,keptCount:o}=El(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(`
20
+ `),this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} did not exit after ${e}; sending SIGKILL`),this.signalProcessGroup("SIGKILL"),await this.waitForExit(ki),this.exited||this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} still has not exited ${ki}ms after SIGKILL; giving up on the reap`)))}signalProcessGroup(e){let t=this.child.pid;if(t!==void 0)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)})}},rl=2e3,ki=5e3;function ol(s){try{let e=C.agentLogFile(s);xn.mkdirSync(vi.dirname(e),{recursive:!0});let t=xn.createWriteStream(e,{flags:"a"});return t.on("error",()=>{}),t}catch{return}}import*as at from"fs/promises";import*as Ga from"os";import*as bi from"os";function zt(){return bi.hostname()}import*as dn from"path";import{customAlphabet as mp}from"nanoid";var $e="session/set_model",nr="session/set_config_option",Ai="model";function tr(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.availableModels)}function Ci(s){return Array.isArray(s)&&s.some(e=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.id===Ai)}function wt(s){if(!s)return;if(tr(s)||tr(s.models))return $e;let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){for(let[t,n]of Object.entries(e))if(t!=="hydra-acp"&&tr(n))return $e}if(Ci(s.configOptions))return nr}function Ri(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.sessionUpdate;if(e==="_hydra_current_model_update")return $e;if(e==="config_option_update"&&Ci(s.configOptions))return nr}function Si(s){return typeof s=="object"&&s!==null&&s.code===A.MethodNotFound}function Ii(s,e,t,n){let r={...n??{}};return delete r.sessionId,delete r.modelId,delete r.configId,delete r.value,s===$e?{...r,sessionId:e,modelId:t}:{...r,sessionId:e,configId:Ai,value:t}}function il(s){return s===$e?nr:$e}async function Qe(s){let{request:e,sessionId:t,modelId:n,extraParams:r,logger:o}=s,i=s.verb??$e;try{let a=await e(i,Ii(i,t,n,r));return{verb:i,result:a}}catch(a){if(!Si(a))throw a;let d=il(i);o?.info(`agent does not implement ${i} (MethodNotFound); retrying model change via ${d} modelId=${JSON.stringify(n)}`);try{let c=await e(d,Ii(d,t,n,r));return{verb:d,result:c}}catch(c){throw Si(c)?a:c}}}async function nt(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 st(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 Qe({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}}}import{customAlphabet as Zi}from"nanoid";import{createHmac as al}from"crypto";function dl(s,e){return al("sha256",s).update(e).digest("hex")}function sr(s,e){let t=JSON.stringify(e),n=dl(s.secret,t);fetch(s.callbackUrl,{method:"POST",headers:{"Content-Type":"application/json","X-Hydra-Turn-Notify-Signature":n},body:t}).catch(()=>{})}var xi="edit",En=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 Ei(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}import*as Pi from"fs/promises";var cl=64*1024*1024,ul=1*1024*1024,kt=64*1024,ll=6e4,fl=100,pl=1e3,gl=64*1024,ml=256*1024,Ti=20;function hl(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Tn=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??cl,this.maxCapacityBytes<=0)throw new Error("capacityBytes must be > 0");this.currentCapacityBytes=Math.min(ul,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,kt));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,kt)),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,kt)),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,ll));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(hl(e.pattern),d),u=e.invert??!1,l=Math.max(1,Math.min(e.maxMatches??fl,pl)),p=Math.max(1,Math.min(e.maxBytes??gl,ml)),f=Math.max(0,Math.min(e.contextBefore??0,Ti)),m=Math.max(0,Math.min(e.contextAfter??0,Ti)),g=[],h=[],w=[],k=0,y=!1,b=0,I=0,v=(E,O)=>{for(let q of w)q.remaining>0&&(q.match.after===void 0&&(q.match.after=[]),q.match.after.push({cursor:E,line:O}),q.remaining--,k+=O.length);for(;w.length>0&&w[0].remaining===0;)w.shift();if(c.test(O)!==u&&g.length<l){let q={cursor:E,line:O};if(f>0&&h.length>0){q.before=h.slice();for(let ne of q.before)k+=ne.line.length}k+=O.length,g.push(q),m>0&&w.push({match:q,remaining:m})}if(f>0)for(h.push({cursor:E,line:O});h.length>f;)h.shift();let j=g.length>=l&&w.length===0,W=k>=p;return j||W};for(let E=0;E<i.length;E++){if(i[E]!==10)continue;let O=i.subarray(b,E).toString("utf8"),T=r+b;if(b=E+1,I=b,v(T,O)){y=!0;break}}if(!y&&b<i.length&&this.closed){let E=i.subarray(b).toString("utf8"),O=r+b;v(O,E)&&(y=!0),I=i.length}let R=Math.min(r+I,this.writeCursor),x={matches:g,truncated:y,nextCursor:R,scannedBytes:I};return o>0&&(x.gap=o),this.closed&&R>=this.writeCursor&&(x.eof=!0),x}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(()=>Pi.appendFile(t,r)).catch(i=>{this.logWriteError?.(i)}),o&&!this.fileCapReached&&(this.fileCapReached=!0,this.onFileCapReached?.())}async drainFileWrites(){await this.fileWriteChain.catch(()=>{})}};var vt=[{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:"fork",name:"hydra fork",argsHint:"[verbatim]",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)"},{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."}],Xy=new Map(vt.map(s=>[s.verb,s]));function Mi(s){let e=s.lastIndexOf("/");return(e===-1?s:s.slice(e+1)).toLowerCase()}function bt(s,e){return rr(s,e.map(t=>t.modelId))}function rr(s,e){if(e.length===0)return{kind:"none",requested:s};if(e.includes(s))return{kind:"exact",modelId:s};let t=Mi(s),n=e.filter(o=>Mi(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}}function $i(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=or(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 vl){if(!_i(c[l]))continue;let p=n.get(u);p===void 0?n.set(u,new Map([[l,c[l]]])):p.set(l,c[l])}if(Array.isArray(c.content)&&c.content.length>0){let l=t.get(u);l?l.push(...c.content):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=or(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?wl(r,o.outIndex,yl(c.content)):(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)?kl(d,t.get(l)??[]):d,f=l===void 0?void 0:n.get(l);if(f!==void 0)for(let[m,g]of f)_i(or(p)?.[m])||(p=bl(p,m,g));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 or(s){if(s.method!=="session/update")return;let t=s.params?.update;if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function yl(s){if(!s||typeof s!="object")return"";let e=s;return typeof e.text=="string"?e.text:""}function wl(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 kl(s,e){let t=s.params??{},n=t.update??{};return{...s,params:{...t,update:{...n,content:e}}}}var vl=["rawInput","locations"];function _i(s){return s==null||typeof s!="object"?!1:Array.isArray(s)?s.length>0:Object.keys(s).length>0}function bl(s,e,t){let n=s.params??{},r=n.update??{};return{...s,params:{...n,update:{...r,[e]:t}}}}var Oi=`[older history truncated]
21
+ `,Fi=["file_path","filePath","path","command","pattern","query"];function St(s,e={}){let t=e.maxChars??4e5,n=ir(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=ur(u.prompt).trim();p.length>0&&r.push(`User: ${p}`)}else if(l==="agent_message_chunk"){let p=lr(u.content);p.length>0&&(o+=p)}else if(l==="tool_call"){if(a(),r.push(cr(u,n)),e.toolOutput!==void 0){let p=dr(u),f=p!==void 0?n.get(p)?.output:void 0;if(f!==void 0&&i>0){let m=Math.min(e.toolOutput.maxPerCall,i),g=f.length<=m?f:`${f.slice(0,m)}\u2026[${f.length-m} more chars]`;r.push(`Output: ${g}`),i-=Math.min(g.length,m)}}}else l==="turn_complete"&&a()}return a(),El(r.join(`
22
+ `),t)}function ir(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=dr(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=Il(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=Pn(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=ar(t);return e}function ar(s){return Sl(s)?s.kind??"(unnamed)":s.name}function Sl(s){for(let e of Fi){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 Il(s,e){let t=Jt(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 dr(s){let e=s.toolCallId;if(typeof e=="string"&&e.length>0)return e}function Pn(s){let e=Al(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 Al(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(`
23
+ `)}function Jt(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 cr(s,e){let t=dr(s),n=t!==void 0?e?.get(t):void 0,r=n?.name??Cl(s),o=Rl(n?.rawInput??s.rawInput);return o.length===0?`Tool: ${r}`:`Tool: ${r}(${o.join(", ")})`}function Cl(s){let e=Jt(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 Rl(s){if(!s||typeof s!="object"||Array.isArray(s))return[];let e=s,t=[];for(let n of Fi){let r=e[n];typeof r=="string"&&r.length>0&&t.push(`${n}=${xl(r,600)}`)}return t}function ur(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 lr(s){if(!s||typeof s!="object")return"";let e=s.text;return typeof e=="string"?e:""}function xl(s,e){return s.length<=e?s:s.slice(0,e-1)+"\u2026"}function El(s,e){if(s.length<=e)return s;let t=s.split(`
24
+ `);for(;t.length>0;){let n=Oi+t.join(`
25
+ `);if(n.length<=e)return n;t.shift()}return Oi}var Ni="(untitled)";function fr(s){let e=[],t=s.synopsis;if(t!==void 0){e.push("--- begin prior session compaction ---"),e.push(`[Title] ${s.title??Ni}`),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=Vt("Open threads",t.open_threads);d.length>0&&e.push(d);let c=Vt("Decisions",t.decisions);c.length>0&&e.push(c);let u=Vt("File edit intentions",t.file_edit_intentions);u.length>0&&e.push(u);let l=Vt("Unresolved errors",t.unresolved_errors);l.length>0&&e.push(l);let p=Vt("Tool state",t.tool_state);p.length>0&&e.push(p);let f=Hi(t.files_touched);f.length>0&&e.push(`[Files previously touched] ${f}`);let m=Hi(t.tools_used);m.length>0&&e.push(`[Tools previously used] ${m}`),e.push("--- end prior session compaction ---")}else e.push(`[Title] ${s.title??Ni}`);s.note!==void 0&&s.note.trim().length>0&&e.push(`[Situation] ${s.note.trim()}`);let{closedText:n,openText:r,keptCount:o}=Tl(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(`
26
26
  `)}function Vt(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(`
27
- `)}`}function Ni(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 El(s,e,t,n){if(s.length===0)return{closedText:"",openText:"",keptCount:0};let{closed:r,open:o}=Tl(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?Hi(a):"",c=o?Hi([o]):"";return{closedText:d,openText:c,keptCount:i}}function Hi(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(`
28
- `)}function Tl(s){let e=[],t=null,n=ir(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:ur(d.prompt).trim(),agent:"",tools:[],startEntryIndex:o};else if(c==="agent_message_chunk"&&t!==null){let u=lr(d.content);u.length>0&&(t.agent+=u)}else c==="tool_call"&&t!==null?t.tools.push(cr(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 Di(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:Pl(a),unknownCount:r.filter(d=>d.reason===void 0&&d.inferredReason===void 0&&!d.notCompaction).length}}function Pl(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 Ml(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 ji(s){if(s<1e3)return String(s);let e=s/1e3;return e<100?`${e.toFixed(1)}k`:`${Math.round(e)}k`}function _l(s){return s.usedBefore===void 0||s.usedAfter===void 0?"":` ${ji(s.usedBefore)} \u2192 ${ji(s.usedAfter)}`}function Ui(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=_l(r),i=r.cost!==void 0?` $${r.cost.toFixed(2)}`:"",a=r.current?" (current)":"",d=r.swaps>1?` (${r.swaps} swaps)`:"";n.push(` ${Ml(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}function $l(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function pr(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(`${$l(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 gr(s,e){if(e.length===0)return!1;let t=e.endsWith("/")?e.slice(0,-1):e;return s.includes(t)}function Li(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(`
29
- `)}function Bi(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(`
30
- `)}function Wi(s,e,t){if(s.length===0||!s.startsWith("/"))return!1;let n=e.endsWith("/")?e:`${e}/`,r=t.endsWith("/")?t:`${t}/`;return s.startsWith(r)?!1:s.startsWith(n)}Q();import*as Oe from"fs/promises";async function Gt(s,e){let t=C.queueFile(s);if(e.length===0){await Oe.unlink(t).catch(()=>{});return}await Oe.mkdir(C.sessionDir(s),{recursive:!0});let n=e.map(r=>JSON.stringify(r)).join(`
27
+ `)}`}function Hi(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 Tl(s,e,t,n){if(s.length===0)return{closedText:"",openText:"",keptCount:0};let{closed:r,open:o}=Pl(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?ji(a):"",c=o?ji([o]):"";return{closedText:d,openText:c,keptCount:i}}function ji(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(`
28
+ `)}function Pl(s){let e=[],t=null,n=ir(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:ur(d.prompt).trim(),agent:"",tools:[],startEntryIndex:o};else if(c==="agent_message_chunk"&&t!==null){let u=lr(d.content);u.length>0&&(t.agent+=u)}else c==="tool_call"&&t!==null?t.tools.push(cr(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 Ui(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:Ml(a),unknownCount:r.filter(d=>d.reason===void 0&&d.inferredReason===void 0&&!d.notCompaction).length}}function Ml(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 _l(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 Di(s){if(s<1e3)return String(s);let e=s/1e3;return e<100?`${e.toFixed(1)}k`:`${Math.round(e)}k`}function $l(s){return s.usedBefore===void 0||s.usedAfter===void 0?"":` ${Di(s.usedBefore)} \u2192 ${Di(s.usedAfter)}`}function Li(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=$l(r),i=r.cost!==void 0?` $${r.cost.toFixed(2)}`:"",a=r.current?" (current)":"",d=r.swaps>1?` (${r.swaps} swaps)`:"";n.push(` ${_l(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}function Ol(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function pr(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(`${Ol(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 gr(s,e){if(e.length===0)return!1;let t=e.endsWith("/")?e.slice(0,-1):e;return s.includes(t)}function Bi(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(`
29
+ `)}function Wi(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(`
30
+ `)}function qi(s,e,t){if(s.length===0||!s.startsWith("/"))return!1;let n=e.endsWith("/")?e:`${e}/`,r=t.endsWith("/")?t:`${t}/`;return s.startsWith(r)?!1:s.startsWith(n)}Q();import*as Oe from"fs/promises";async function Gt(s,e){let t=C.queueFile(s);if(e.length===0){await Oe.unlink(t).catch(()=>{});return}await Oe.mkdir(C.sessionDir(s),{recursive:!0});let n=e.map(r=>JSON.stringify(r)).join(`
31
31
  `)+`
32
- `;await Oe.writeFile(t,n,"utf8")}async function qi(s){let e=C.queueFile(s),t;try{t=await Oe.readFile(e,"utf8")}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t.split(`
33
- `))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 zi(s){let e=C.queueFile(s);await Oe.unlink(e).catch(()=>{})}import*as ta from"fs/promises";var Zi="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",ea=Xi(Zi,16),mr=Xi(Zi,16),Ol=20,Fl=20,Nl=5,Hl=32,Ne="hydra_session_";function Fe(){return`m_${ea()}`}function Be(s){return s.startsWith(Ne)?s.slice(Ne.length):s}var Ji=["start","merge","apply","sync","stop","detach","discard","clean","status"],jl=1e3,Mn=300*1e3,Dl=64,Ul=new Set(["task-notification","peer","coordinator","observer","observer-activity"]);function Ll(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"&&Ul.has(r)}function Vi(s){let e=s?.update;return!!e&&typeof e=="object"&&e.sessionUpdate==="usage_update"}function Bl(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 Gi=120,Wl=128,ql=1e3,It=class s{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=$e;modelVerbConfirmed=!1;agentArgs;parentSessionId;forkedFromSessionId;forkedFromMessageId;forkSynthesisState;originatingClient;_interactive;get interactive(){return this._interactive}_priority;get priority(){return this._priority}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;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;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}_titleSeedPending=!0;promptStartedAt;unsolicitedTurn;pendingSteerDetach;supersededAutonomousTurn;autonomousSalvage;lastBackgroundTask;toolLabels=new Map;armedTasks=new Map;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;spawnReplacementAgent;mintMcpServersForSwap;loadExistingAgentSession;clearRollbackBreadcrumbHook;onCompactionSwapHook;persistWatermarkHook;uncompactHook;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 En;filesEditedSeen=new Set;openToolCalls=new Set;agentChangeHandlers=[];retiringGenerationCost;retiringGenerationUsed;rotationLifetimeCost;agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];availableAgentsFn;modelHandlers=[];modeHandlers=[];interactiveHandlers=[];priorityHandlers=[];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??`${Ne}${ea()}`,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.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),this._interactive=e.interactive,this._priority=e.priority,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??jl,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){this.resetBackgroundTaskLevel(),e.connection.onNotification("session/update",t=>{if(this.internalPromptCapture){tf(this.internalPromptCapture,t);return}this.maybeEmitToolEdges(t),this.runResponseChain(t)}),e.connection.onNotification("_claude/sdkMessage",t=>{this.applyBackgroundTaskLevel(t)}),e.connection.onRequest("session/request_permission",async t=>{let n=await this.runAgentRequestChain("session/request_permission",t),r=Ki(n.shortCircuit?t:n.envelope);if(n.shortCircuit)return this.notifyChain("permission.replied",{toolCallId:r??null,outcome:n.payload,sourceWasTransformer:!0}),n.payload;let o=await this.handlePermissionRequest(n.envelope);return this.notifyChain("permission.replied",{toolCallId:r??null,outcome:o,sourceWasTransformer:!1}),o}),typeof e.connection.onOrphanError=="function"&&e.connection.onOrphanError(t=>{this.handleOrphanError(t)}),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 u=n;u<this.transformChain.length;u++){let l=this.transformChain[u];if(t.has(l.name)||!l.intercepts.has(a))continue;let p=`t_${mr()}`,f;try{f=await l.connection.request("hydra-acp/transformer/message",{token:p,phase:"response",method:r,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(g){this.logger?.warn(`transformer ${l.name} error on ${a}: ${g.message}`);continue}let m=f?.action??"continue";if(m==="stop")return;if(m==="processing"){let g=u,h=i,w=new Set(t),k=r;await new Promise(y=>{let b=setTimeout(()=>{this.pendingClaims.delete(p)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:p,transformerName:l.name}),this.runResponseChain(h,new Set([...w,l.name]),g+1,k).then(()=>y()).catch(()=>y()))},Mn);typeof b.unref=="function"&&b.unref(),this.pendingClaims.set(p,{resolve:()=>y(),timer:b,transformerName:l.name,method:k,envelope:h,chainIdx:g,originatedBy:w,side:"response"})});return}f?.payload&&typeof f.payload=="object"&&(i=f.payload),t.add(l.name)}if(r!=="session/update")return;this.noteAgentActivity(i);let d=nf(i);if(d!==null){this.setAgentAdvertisedCommands(d);return}let c=ef(i);if(c!==null){this.setAgentAdvertisedModes(c);return}if(this.noteModelVerbHint(Ci(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",i)}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=await this.openToolCallIdsInHistory();if(e.length>0)return`${e.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),!r){let T=await st({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedModel:c,agentReportedModel:f.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(T.result,"model"),await nt({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedMode:u,agentReportedMode:f.initialMode,logger:this.logger})}f.agent.connection.drainBuffered("session/update");let m=[];if(this.historyStore)try{m=await this.historyStore.load(this.sessionId)}catch(T){this.logger?.warn(`swapUpstream: historyStore.load failed: ${T.message}`)}let g=fr({...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:m,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 h,w;try{await f.agent.connection.request("session/prompt",{sessionId:f.upstreamSessionId,prompt:[{type:"text",text:g}]});let T=this.internalPromptCapture;h=T.lastUsed,w=T.lastSize,this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${g.length} toolCalls=${T.toolCalls} thinkingChars=${T.thinkingChars} messageChars=${T.messageChars} used=${T.lastUsed??"?"} size=${T.lastSize??"?"} reply=${JSON.stringify(T.chunks.join("").slice(0,200))}`)}finally{this.internalPromptCapture=void 0}h!==void 0&&(this.maybeApplyAgentUsage({update:{sessionUpdate:"usage_update",used:h,...w!==void 0?{size:w}:{}}}),this.broadcastCurrentUsage());let k=this.upstreamSessionId,y=this._summarizedThroughEntry;e.summarizedThroughEntry!==void 0&&(this._summarizedThroughEntry=e.summarizedThroughEntry);let b=this.agent;if(this.agent=f.agent,this.upstreamSessionId=f.upstreamSessionId,this.agentMeta=f.agentMeta,this.agentCapabilities=f.agentCapabilities,this.resetModelVerb(f.modelVerb),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,h),e.summarizedThroughEntry!==void 0&&this.persistWatermarkHook)try{this.persistWatermarkHook(e.summarizedThroughEntry)}catch(T){this.logger?.warn(`swapUpstream: persistWatermarkHook failed: ${T.message}`)}if(!r&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:k,...y!==void 0?{previousSummarizedThroughEntry:y}:{},...e.runId!==void 0?{runId:e.runId}:{}})}catch(T){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${T.message}`)}let I=await this.retireAgent(b,r?"agent switch":e.reason==="workspace-enter"||e.reason==="workspace-leave"?"workspace move":"compaction swap");this.notifyChain("agent.swap",{phase:"post",previousUpstreamSessionId:k,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 v=I.length>0?`
32
+ `;await Oe.writeFile(t,n,"utf8")}async function zi(s){let e=C.queueFile(s),t;try{t=await Oe.readFile(e,"utf8")}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t.split(`
33
+ `))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 Ji(s){let e=C.queueFile(s);await Oe.unlink(e).catch(()=>{})}import*as na from"fs/promises";var ea="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",ta=Zi(ea,16),mr=Zi(ea,16),Fl=20,Nl=20,Hl=5,jl=32,Ne="hydra_session_";function Fe(){return`m_${ta()}`}function Be(s){return s.startsWith(Ne)?s.slice(Ne.length):s}var Vi=["start","merge","apply","sync","stop","detach","discard","clean","status"],Dl=1e3,Mn=300*1e3,Ul=64,Ll=new Set(["task-notification","peer","coordinator","observer","observer-activity"]);function Bl(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"&&Ll.has(r)}function Gi(s){let e=s?.update;return!!e&&typeof e=="object"&&e.sessionUpdate==="usage_update"}function Wl(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 Ki=120,ql=128,zl=1e3,It=class s{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=$e;modelVerbConfirmed=!1;agentArgs;parentSessionId;forkedFromSessionId;forkedFromMessageId;forkSynthesisState;originatingClient;_interactive;get interactive(){return this._interactive}_priority;get priority(){return this._priority}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;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;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}_titleSeedPending=!0;_upstreamRespawned=!1;promptStartedAt;unsolicitedTurn;pendingSteerDetach;supersededAutonomousTurn;autonomousSalvage;lastBackgroundTask;toolLabels=new Map;armedTasks=new Map;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;spawnReplacementAgent;mintMcpServersForSwap;loadExistingAgentSession;clearRollbackBreadcrumbHook;onCompactionSwapHook;persistWatermarkHook;uncompactHook;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 En;filesEditedSeen=new Set;openToolCalls=new Set;agentChangeHandlers=[];retiringGenerationCost;retiringGenerationUsed;rotationLifetimeCost;agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];availableAgentsFn;modelHandlers=[];modeHandlers=[];interactiveHandlers=[];priorityHandlers=[];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??`${Ne}${ta()}`,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.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),this._interactive=e.interactive,this._priority=e.priority,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??Dl,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){nf(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=Qi(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 u=n;u<this.transformChain.length;u++){let l=this.transformChain[u];if(t.has(l.name)||!l.intercepts.has(a))continue;let p=`t_${mr()}`,f;try{f=await l.connection.request("hydra-acp/transformer/message",{token:p,phase:"response",method:r,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(g){this.logger?.warn(`transformer ${l.name} error on ${a}: ${g.message}`);continue}let m=f?.action??"continue";if(m==="stop")return;if(m==="processing"){let g=u,h=i,w=new Set(t),k=r;await new Promise(y=>{let b=setTimeout(()=>{this.pendingClaims.delete(p)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:p,transformerName:l.name}),this.runResponseChain(h,new Set([...w,l.name]),g+1,k).then(()=>y()).catch(()=>y()))},Mn);typeof b.unref=="function"&&b.unref(),this.pendingClaims.set(p,{resolve:()=>y(),timer:b,transformerName:l.name,method:k,envelope:h,chainIdx:g,originatedBy:w,side:"response"})});return}f?.payload&&typeof f.payload=="object"&&(i=f.payload),t.add(l.name)}if(r!=="session/update")return;this.noteAgentActivity(i);let d=sf(i);if(d!==null){this.setAgentAdvertisedCommands(d);return}let c=tf(i);if(c!==null){this.setAgentAdvertisedModes(c);return}if(this.noteModelVerbHint(Ri(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",i)}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=await this.openToolCallIdsInHistory();if(e.length>0)return`${e.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 T=await st({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedModel:c,agentReportedModel:f.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(T.result,"model"),await nt({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedMode:u,agentReportedMode:f.initialMode,logger:this.logger})}f.agent.connection.drainBuffered("session/update");let m=[];if(this.historyStore)try{m=await this.historyStore.load(this.sessionId)}catch(T){this.logger?.warn(`swapUpstream: historyStore.load failed: ${T.message}`)}let g=fr({...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:m,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 h,w;try{await f.agent.connection.request("session/prompt",{sessionId:f.upstreamSessionId,prompt:[{type:"text",text:g}]});let T=this.internalPromptCapture;h=T.lastUsed,w=T.lastSize,this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${g.length} toolCalls=${T.toolCalls} thinkingChars=${T.thinkingChars} messageChars=${T.messageChars} used=${T.lastUsed??"?"} size=${T.lastSize??"?"} reply=${JSON.stringify(T.chunks.join("").slice(0,200))}`)}finally{this.internalPromptCapture=void 0}h!==void 0&&(this.maybeApplyAgentUsage({update:{sessionUpdate:"usage_update",used:h,...w!==void 0?{size:w}:{}}}),this.broadcastCurrentUsage());let k=this.upstreamSessionId,y=this._summarizedThroughEntry;e.summarizedThroughEntry!==void 0&&(this._summarizedThroughEntry=e.summarizedThroughEntry);let b=this.agent;if(this.agent=f.agent,this.upstreamSessionId=f.upstreamSessionId,this.agentMeta=f.agentMeta,this.agentCapabilities=f.agentCapabilities,this.resetModelVerb(f.modelVerb),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,h),e.summarizedThroughEntry!==void 0&&this.persistWatermarkHook)try{this.persistWatermarkHook(e.summarizedThroughEntry)}catch(T){this.logger?.warn(`swapUpstream: persistWatermarkHook failed: ${T.message}`)}if(!r&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:k,...y!==void 0?{previousSummarizedThroughEntry:y}:{},...e.runId!==void 0?{runId:e.runId}:{}})}catch(T){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${T.message}`)}let I=await this.retireAgent(b,r?"agent switch":e.reason==="workspace-enter"||e.reason==="workspace-leave"?"workspace move":"compaction swap");this.notifyChain("agent.swap",{phase:"post",previousUpstreamSessionId:k,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 v=I.length>0?`
34
34
  Stopped ${I.length} background task(s) with the previous agent: ${I.join(", ")}. Re-arm anything still needed.
35
35
  `:"",E=(e.reason==="workspace-enter"||e.reason==="workspace-leave"?"":r?`
36
36
  Switched to ${n}.
37
37
  `:`
38
38
  Compaction completed.
39
- `)+v,O=E===""?void 0:E;if(O!==void 0){let T=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:O},_meta:{"hydra-acp":{synthetic:!0}}}});for(let j of this.clients.values())j.connection.notify("session/update",T).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);let l=await st({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedModel:d,agentReportedModel:u.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(l.result,"model"),await nt({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);let o=await st({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:t,agentReportedModel:r.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(o.result,"model"),await nt({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=Ol){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){if(c==="tool_call")r.add(u);else if(c==="tool_call_update"){let l=d.status;(l==="completed"||l==="failed")&&o.add(u)}}}return[...r].filter(i=>!o.has(i))}async getHistorySnapshot(e="inline"){return this.historyStore?this.historyStore.load(this.sessionId,{tools:e}).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 me(new Error("session is closed"),A.SessionNotFound);if(this.clients.has(e.clientId))throw me(new Error(`client ${e.clientId} is already attached`),A.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=a=>t.raw?a:_i(a),o=(await this.getHistorySnapshot(t.toolContent??"inline")).filter(a=>!hr(a.method,a.params)),i=this.buildStateSnapshotReplay();if(e==="after_message"){let a=t.afterMessageId?$n(o,t.afterMessageId):-1;return a<0?{entries:[...i,...n(o)],appliedPolicy:"full"}:{entries:[...i,...n(o.slice(a+1))],appliedPolicy:"after_message"}}return{entries:[...i,...n(o)],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&&e.startsWith(`${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}Wi(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=Qi(e,o=>gr(o,t.path)?(n=!0,pr(o,t.path,t.sourceCwd).text):o);if(!this.departureNoteSent||n){let o=Li({sourceCwd:t.sourceCwd,formerWorkspacePath:t.path,removed:t.removed});r=yr(r,`${o}
39
+ `)+v,O=E===""?void 0:E;if(O!==void 0){let T=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:O},_meta:{"hydra-acp":{synthetic:!0}}}});for(let j of this.clients.values())j.connection.notify("session/update",T).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 st({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedModel:d,agentReportedModel:u.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(l.result,"model"),await nt({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 st({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:t,agentReportedModel:r.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(o.result,"model"),await nt({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=Fl){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){if(c==="tool_call")r.add(u);else if(c==="tool_call_update"){let l=d.status;(l==="completed"||l==="failed")&&o.add(u)}}}return[...r].filter(i=>!o.has(i))}async getHistorySnapshot(e="inline"){return this.historyStore?this.historyStore.load(this.sessionId,{tools:e}).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 me(new Error("session is closed"),A.SessionNotFound);if(this.clients.has(e.clientId))throw me(new Error(`client ${e.clientId} is already attached`),A.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=a=>t.raw?a:$i(a),o=(await this.getHistorySnapshot(t.toolContent??"inline")).filter(a=>!hr(a.method,a.params)),i=this.buildStateSnapshotReplay();if(e==="after_message"){let a=t.afterMessageId?$n(o,t.afterMessageId):-1;return a<0?{entries:[...i,...n(o)],appliedPolicy:"full"}:{entries:[...i,...n(o.slice(a+1))],appliedPolicy:"after_message"}}return{entries:[...i,...n(o)],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&&e.startsWith(`${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}qi(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=Yi(e,o=>gr(o,t.path)?(n=!0,pr(o,t.path,t.sourceCwd).text):o);if(!this.departureNoteSent||n){let o=Bi({sourceCwd:t.sourceCwd,formerWorkspacePath:t.path,removed:t.removed});r=yr(r,`${o}
40
40
 
41
- `),this.departureNoteSent=!0}return r}applyWorkspacePromptRewrite(e){let t=this.workspace;if(t===void 0)return this.applyDepartedPromptRewrite(e);let n=!1,r=Qi(e,i=>gr(i,t.sourceCwd)?(n=!0,pr(i,t.sourceCwd,t.path).text):i);if(!this.workspacePreambleSent||n){let i=Bi({workspacePath:t.path,sourceCwd:t.sourceCwd,notes:this.workspaceNotes,...this.workspacePreambleSent?{reassert:!0}:{}});r=yr(r,`${i}
41
+ `),this.departureNoteSent=!0}return r}applyWorkspacePromptRewrite(e){let t=this.workspace;if(t===void 0)return this.applyDepartedPromptRewrite(e);let n=!1,r=Yi(e,i=>gr(i,t.sourceCwd)?(n=!0,pr(i,t.sourceCwd,t.path).text):i);if(!this.workspacePreambleSent||n){let i=Wi({workspacePath:t.path,sourceCwd:t.sourceCwd,notes:this.workspaceNotes,...this.workspacePreambleSent?{reassert:!0}:{}});r=yr(r,`${i}
42
42
 
43
- `),this.workspacePreambleSent=!0}return r}async prompt(e,t,n){let r=this.clients.get(e);if(!r)throw me(new Error("client not attached"),A.SessionNotFound);if(this.closing)throw me(new Error("session is closing; new prompts cannot be accepted"),A.SessionClosing);let o=Fe();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(tt((t??{})._meta).ancillary===!0)&&this._interactive!==!0){this._interactive=!0,this.cancelOrphanTimer();for(let a of this.interactiveHandlers)try{a(!0)}catch{}}return this.enqueueUserPrompt(r,t,o,n)}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.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"prompt_received",messageId:e.messageId,prompt:e.prompt,sentBy:t}},e.clientId);let n=rt(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(()=>{})}broadcastTurnComplete(e,t,n,r){let o=t&&typeof t=="object"&&"stopReason"in t&&typeof t.stopReason=="string"?t.stopReason:void 0,i={sessionUpdate:"turn_complete",messageId:Fe()};o!==void 0&&(i.stopReason=o);let a=tt(t?._meta).salvaged;a!==void 0&&(i._meta={[pe]:{salvaged:a}}),this.supersededAutonomousTurn=void 0;let d=this.amendInProgress;if(d&&n!==void 0&&d.cancelledMessageId===n&&(i._meta={[pe]:{...a!==void 0?{salvaged:a}:{},amended:{cancelledMessageId:d.cancelledMessageId,newMessageId:d.newMessageId}}}),this.promptStartedAt=void 0,this.sawTurnComplete=!0,this.scheduleWorkspaceSnapshotHook?.(),n!==void 0&&o!==void 0){this.recordTerminal(n,o);let c=this.pendingTurnNotifiers.get(n);c&&(this.pendingTurnNotifiers.delete(n),sr(c,{sessionId:this.sessionId,messageId:c.originalMessageId,stopReason:o,deliveredAt:Date.now(),...n!==c.originalMessageId?{amendedTo:n}:{}}))}(o==="cancelled"||o==="error"||o==="refusal")&&this.closeOpenToolCalls(o),this.recordCurrentUsageSnapshot(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:i},r?void 0:e),d&&n!==void 0&&d.cancelledMessageId===n&&this.broadcastPromptAmended(d)}noteAgentActivity(e){if(!(this.closing||this.closed)){if(Ll(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&&Vi(e)&&(this.pendingSteerDetach=void 0),!hr("session/update",e)&&(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||this.openUnsolicitedTurn()))}}steerCausedTurnTerminal(e){return this.unsolicitedTurn?.steerCaused!==!0?!1:Vi(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=Ql(t._meta);this.rememberToolLabel(n,t,r,o),this.noteBackgroundTaskStopped(t,r,o);let i=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:Kl(t.rawOutput);if(!(i!==void 0||r!==void 0&&r.run_in_background===!0))return;let d=this.toolLabels.get(n)?.label??"background task";this.lastBackgroundTask={toolCallId:n,label:d};let c=Date.now(),u=this.armedTasks.get(n),l=i??u?.taskId,p=Gl(t.title,o,r)||u?.repeating===!0;this.armedTasks.set(n,{label:d,...l!==void 0?{taskId:l}:{},repeating:p,armedAt:u?.armedAt??c}),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}))}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}))}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);return this.armedTasks.clear(),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,Gi),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,Gi),fromDescription:!1})}for(;this.toolLabels.size>Wl;){let i=this.toolLabels.keys().next().value;if(i===void 0)break;this.toolLabels.delete(i)}}openUnsolicitedTurn(){let e=Date.now(),t=this.lastBackgroundTask,n=!1;for(let[i,a]of this.armedTasks)a.repeating||(this.armedTasks.delete(i),n=!0);n&&this.onArmedTasksChanged();let r={messageId:Fe(),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,ql);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.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"),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"_hydra_turn_ended",messageId:Fe(),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:{[pe]:{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>Dl;){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>Hl;){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 me(new Error("client not attached"),A.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=Fe(),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 me(new Error("client not attached"),A.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}return r?(this.amendOnHead(n,t.prompt,this.currentEntry.messageId,!1),{outcome:"startedNewTurn"}):t._meta?.steering?.idleBehavior==="promptRequired"?{outcome:"promptRequired",reason:"noRunningTurn"}:(await this.prompt(e,{sessionId:t.sessionId,prompt:t.prompt}),{outcome:"startedNewTurn"})}recordSteerAsUserMessageChunk(e,t){let n=rt(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=Fe(),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 me(new Error("client not attached"),A.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_${mr()}`,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??wr(e);if(p==="continue"){l?.payload&&typeof l.payload=="object"&&(i=l.payload),n.add(d.name);continue}if(p==="processing"){let f=a,m=i,g=new Set(n);return new Promise(h=>{let w=setTimeout(()=>{this.pendingClaims.delete(u)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:u,transformerName:d.name}),this.forwardRequest(e,m,new Set([...g,d.name]),f+1,o).then(h).catch(()=>h(o==="notification"?void 0:wr(e))))},Mn);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(u,{resolve:h,timer:w,transformerName:d.name,method:e,envelope:m,chainIdx:f,originatedBy:g,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 Qe({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??$e,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_${mr()}`,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??cf(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,m=new Set(n),g=e;return new Promise(h=>{let w=setTimeout(()=>{this.pendingClaims.delete(c)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:c,transformerName:d.name}),this.runAgentRequestChain(g,f,new Set([...m,d.name]),p+1).then(h).catch(()=>h({shortCircuit:!1,envelope:f})))},Mn);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(c,{resolve:k=>h({shortCircuit:!0,payload:k}),timer:w,transformerName:d.name,method:g,envelope:f,chainIdx:p,originatedBy:m,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):Mn,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:wr(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=Fe(),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();for(let n of this.pendingClaims.values())clearTimeout(n.timer);this.pendingClaims.clear(),await this.agent.kill().catch(()=>{}),this.markClosed({deleteRecord:e.deleteRecord??!1})}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||tt((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let r=rt((e??{}).prompt),o=vr(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=Kt(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)),!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(Bl(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 g=Kt(t.options);g.length>0&&this.setAgentAdvertisedModels(g);let h=t.currentValue;if(typeof h=="string"){let w=h.trim();w&&w!==this.currentModel&&(this.logger?.info(`live config_option_update(model): sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(w)}`),this.applyModelChange(w))}return}if(t.id==="mode"){let g=_n(t.options);g.length>0&&this.setAgentAdvertisedModes(g);let h=t.currentValue;if(typeof h=="string"){let w=h.trim();w&&w!==this.currentMode&&(this.logger?.info(`live config_option_update(mode): sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(w)}`),this.applyModeChange(w))}return}if(typeof t.id!="string"||!t.id.trim())return;let n=t.id.trim(),r=kr(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}:{}},m=this.agentAdvertisedConfigOptions.findIndex(g=>g.id===n);m>=0?this.agentAdvertisedConfigOptions[m]=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"&&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(Yl(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(Xl(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(",")}]`),Zl(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)}onModelChange(e){this.modelHandlers.push(e)}onModeChange(e){this.modeHandlers.push(e)}onInteractiveChange(e){this.interactiveHandlers.push(e)}onPriorityChange(e){this.priorityHandlers.push(e)}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}:{}})),o=this.currentModel&&r.some(i=>i.value===this.currentModel)?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}:{}})),o=this.currentMode&&r.some(i=>i.value===this.currentMode)?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()}})}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 vt){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=n.startsWith("hydra-acp-")?n.slice(10):n;if(n.startsWith("hydra-acp-")&&d.length>0){let c=r.verb?`hydra ${d} ${r.verb}`:`hydra ${d}`,l={name:r.argsHint?`${c} ${r.argsHint}`:c};r.description&&(l.description=r.description),e.push(l)}if(d.length>0&&t.get(d)===n){let c=r.verb?`${d} ${r.verb}`:d,l={name:r.argsHint?`${c} ${r.argsHint}`:c};r.description&&(l.description=r.description),e.push(l)}}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 vt)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=i.startsWith("hydra-acp-")?i.slice(10):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")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(vt.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"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=A.InternalError,l}}if(this.extensionCommands?.has(o))return a?this.runExtensionCommandInline(o,i,t):this.runExtensionCommand(o,i);let d=`hydra-acp-${o}`;if(this.extensionCommands?.has(d))return a?this.runExtensionCommandInline(d,i,t):this.runExtensionCommand(d,i);let c=vt.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=A.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(m=>m.verb===i)){let m=r.commands.map(g=>g.verb).join(", ");return this.emitExtensionReply(`/hydra ${e}${i?` ${i}`:""}: unknown verb (known: ${m||"(none)"})`)}let d={sessionId:this.sessionId,verb:i,args:a};n!==void 0&&(d.messageId=n);let c=()=>{},u=new Promise(m=>{c=m});n!==void 0&&this.inFlightExtensionDispatches.set(n,{extensionName:e,connection:r.connection,cancel:m=>c({stopReason:"cancelled",reason:m})});let l,p=!1;try{let m=r.connection.request("hydra-acp/commands/invoke",d),g=await Promise.race([m,u]);if(g&&typeof g=="object"&&g.stopReason==="cancelled"&&"reason"in g)return p=!0,this.logger?.info(`extension ${e} ${i} cancelled (cancelExtensionDispatch); abandoning in-flight commands/invoke`),{stopReason:"cancelled"};l=g}catch(m){return this.emitExtensionReply(`${e} ${i}: ${m.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:`
43
+ `),this.workspacePreambleSent=!0}return r}async prompt(e,t,n,r){let o=this.clients.get(e);if(!o)throw me(new Error("client not attached"),A.SessionNotFound);if(this.closing)throw me(new Error("session is closing; new prompts cannot be accepted"),A.SessionClosing);let i=Fe();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(tt((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.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"prompt_received",messageId:e.messageId,prompt:e.prompt,sentBy:t}},e.clientId);let n=rt(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){let o=t&&typeof t=="object"&&"stopReason"in t&&typeof t.stopReason=="string"?t.stopReason:void 0,i={sessionUpdate:"turn_complete",messageId:Fe()};o!==void 0&&(i.stopReason=o);let a=tt(t?._meta).salvaged;a!==void 0&&(i._meta={[pe]:{salvaged:a}}),this.supersededAutonomousTurn=void 0;let d=this.amendInProgress;if(d&&n!==void 0&&d.cancelledMessageId===n&&(i._meta={[pe]:{...a!==void 0?{salvaged:a}:{},amended:{cancelledMessageId:d.cancelledMessageId,newMessageId:d.newMessageId}}}),this.promptStartedAt=void 0,this.sawTurnComplete=!0,this.scheduleWorkspaceSnapshotHook?.(),n!==void 0&&o!==void 0){this.recordTerminal(n,o);let c=this.pendingTurnNotifiers.get(n);c&&(this.pendingTurnNotifiers.delete(n),sr(c,{sessionId:this.sessionId,messageId:c.originalMessageId,stopReason:o,deliveredAt:Date.now(),...n!==c.originalMessageId?{amendedTo:n}:{}}))}(o==="cancelled"||o==="error"||o==="refusal")&&this.closeOpenToolCalls(o),this.recordCurrentUsageSnapshot(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:i},r?void 0:e),d&&n!==void 0&&d.cancelledMessageId===n&&this.broadcastPromptAmended(d)}noteAgentActivity(e){if(!(this.closing||this.closed)){if(Bl(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&&Gi(e)&&(this.pendingSteerDetach=void 0),!hr("session/update",e)&&(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||this.openUnsolicitedTurn()))}}steerCausedTurnTerminal(e){return this.unsolicitedTurn?.steerCaused!==!0?!1:Gi(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=Yl(t._meta);this.rememberToolLabel(n,t,r,o),this.noteBackgroundTaskStopped(t,r,o);let i=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:Ql(t.rawOutput);if(!(i!==void 0||r!==void 0&&r.run_in_background===!0))return;let d=this.toolLabels.get(n)?.label??"background task";this.lastBackgroundTask={toolCallId:n,label:d};let c=Date.now(),u=this.armedTasks.get(n),l=i??u?.taskId,p=Kl(t.title,o,r)||u?.repeating===!0;this.armedTasks.set(n,{label:d,...l!==void 0?{taskId:l}:{},repeating:p,armedAt:u?.armedAt??c}),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}))}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}))}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);return this.armedTasks.clear(),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,Ki),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,Ki),fromDescription:!1})}for(;this.toolLabels.size>ql;){let i=this.toolLabels.keys().next().value;if(i===void 0)break;this.toolLabels.delete(i)}}openUnsolicitedTurn(){let e=Date.now(),t=this.lastBackgroundTask,n=!1;for(let[i,a]of this.armedTasks)a.repeating||(this.armedTasks.delete(i),n=!0);n&&this.onArmedTasksChanged();let r={messageId:Fe(),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,zl);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.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"),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"_hydra_turn_ended",messageId:Fe(),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:{[pe]:{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>Ul;){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>jl;){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 me(new Error("client not attached"),A.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=Fe(),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 me(new Error("client not attached"),A.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=rt(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=Fe(),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 me(new Error("client not attached"),A.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_${mr()}`,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??wr(e);if(p==="continue"){l?.payload&&typeof l.payload=="object"&&(i=l.payload),n.add(d.name);continue}if(p==="processing"){let f=a,m=i,g=new Set(n);return new Promise(h=>{let w=setTimeout(()=>{this.pendingClaims.delete(u)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:u,transformerName:d.name}),this.forwardRequest(e,m,new Set([...g,d.name]),f+1,o).then(h).catch(()=>h(o==="notification"?void 0:wr(e))))},Mn);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(u,{resolve:h,timer:w,transformerName:d.name,method:e,envelope:m,chainIdx:f,originatedBy:g,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 Qe({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??$e,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_${mr()}`,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??uf(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,m=new Set(n),g=e;return new Promise(h=>{let w=setTimeout(()=>{this.pendingClaims.delete(c)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:c,transformerName:d.name}),this.runAgentRequestChain(g,f,new Set([...m,d.name]),p+1).then(h).catch(()=>h({shortCircuit:!1,envelope:f})))},Mn);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(c,{resolve:k=>h({shortCircuit:!0,payload:k}),timer:w,transformerName:d.name,method:g,envelope:f,chainIdx:p,originatedBy:m,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):Mn,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:wr(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=Fe(),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();for(let n of this.pendingClaims.values())clearTimeout(n.timer);this.pendingClaims.clear(),await this.agent.kill().catch(()=>{}),this.markClosed({deleteRecord:e.deleteRecord??!1})}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||tt((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let r=rt((e??{}).prompt),o=vr(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=Kt(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)),!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(Wl(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 g=Kt(t.options);g.length>0&&this.setAgentAdvertisedModels(g);let h=t.currentValue;if(typeof h=="string"){let w=h.trim();w&&w!==this.currentModel&&(this.logger?.info(`live config_option_update(model): sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(w)}`),this.applyModelChange(w))}return}if(t.id==="mode"){let g=_n(t.options);g.length>0&&this.setAgentAdvertisedModes(g);let h=t.currentValue;if(typeof h=="string"){let w=h.trim();w&&w!==this.currentMode&&(this.logger?.info(`live config_option_update(mode): sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(w)}`),this.applyModeChange(w))}return}if(typeof t.id!="string"||!t.id.trim())return;let n=t.id.trim(),r=kr(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}:{}},m=this.agentAdvertisedConfigOptions.findIndex(g=>g.id===n);m>=0?this.agentAdvertisedConfigOptions[m]=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"&&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(Xl(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(Zl(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(",")}]`),ef(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)}onModelChange(e){this.modelHandlers.push(e)}onModeChange(e){this.modeHandlers.push(e)}onInteractiveChange(e){this.interactiveHandlers.push(e)}onPriorityChange(e){this.priorityHandlers.push(e)}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}:{}})),o=this.currentModel&&r.some(i=>i.value===this.currentModel)?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}:{}})),o=this.currentMode&&r.some(i=>i.value===this.currentMode)?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()}})}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 vt){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=n.startsWith("hydra-acp-")?n.slice(10):n;if(n.startsWith("hydra-acp-")&&d.length>0){let c=r.verb?`hydra ${d} ${r.verb}`:`hydra ${d}`,l={name:r.argsHint?`${c} ${r.argsHint}`:c};r.description&&(l.description=r.description),e.push(l)}if(d.length>0&&t.get(d)===n){let c=r.verb?`${d} ${r.verb}`:d,l={name:r.argsHint?`${c} ${r.argsHint}`:c};r.description&&(l.description=r.description),e.push(l)}}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 vt)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=i.startsWith("hydra-acp-")?i.slice(10):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(vt.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"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=A.InternalError,l}}if(this.extensionCommands?.has(o))return a?this.runExtensionCommandInline(o,i,t):this.runExtensionCommand(o,i);let d=`hydra-acp-${o}`;if(this.extensionCommands?.has(d))return a?this.runExtensionCommandInline(d,i,t):this.runExtensionCommand(d,i);let c=vt.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=A.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(m=>m.verb===i)){let m=r.commands.map(g=>g.verb).join(", ");return this.emitExtensionReply(`/hydra ${e}${i?` ${i}`:""}: unknown verb (known: ${m||"(none)"})`)}let d={sessionId:this.sessionId,verb:i,args:a};n!==void 0&&(d.messageId=n);let c=()=>{},u=new Promise(m=>{c=m});n!==void 0&&this.inFlightExtensionDispatches.set(n,{extensionName:e,connection:r.connection,cancel:m=>c({stopReason:"cancelled",reason:m})});let l,p=!1;try{let m=r.connection.request("hydra-acp/commands/invoke",d),g=await Promise.race([m,u]);if(g&&typeof g=="object"&&g.stopReason==="cancelled"&&"reason"in g)return p=!0,this.logger?.info(`extension ${e} ${i} cancelled (cancelExtensionDispatch); abandoning in-flight commands/invoke`),{stopReason:"cancelled"};l=g}catch(m){return this.emitExtensionReply(`${e} ${i}: ${m.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:`
44
44
  ${e}
45
45
  `},_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}):
46
46
  ${n.join(`
@@ -63,7 +63,7 @@ ${l}:
63
63
  ${i}
64
64
  `},_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 me(new Error(`unknown mode: ${t} (known: ${r})`),A.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:`
65
65
  _(no config options advertised yet)_
66
- `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let p=l.map(f=>Yi(f));return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
66
+ `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let p=l.map(f=>Xi(f));return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
67
67
  ${p.join(`
68
68
 
69
69
  `)}
@@ -73,18 +73,18 @@ ${p.join(`
73
73
  Available options:
74
74
  ${l}
75
75
  `},_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:`
76
- ${Yi(i)}
76
+ ${Xi(i)}
77
77
  `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let a=i.options.map(l=>l.value),d=rr(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(h=>h.toLowerCase().includes(l)),f=p.length>0?p:a,m=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}"`,g=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:`
78
78
  ${m}.
79
79
  ${g}:
80
80
  ${f.join(`
81
81
  `)}
82
- `},_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 me(new Error("/hydra agent requires an agent id"),A.InvalidParams);let r=(this.resolveAgentIdHook?await this.resolveAgentIdHook(t):void 0)??t;if(r===this.agentId)throw me(new Error(`already on agent ${r}`),A.InvalidParams);if(!this.scheduleCompactionHook)return this.emitExtensionReply("agent switching not configured for this session"),{stopReason:"end_turn"};this.scheduleCompactionHook({targetAgentId:r});let o=this.promptInFlight||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 me(new Error("agent restart not configured for this session"),A.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=Di(n,t),o=Ui(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(`
83
- `)),{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(!Ji.includes(t))return this.emitExtensionReply(`Unknown workspace verb "${t}". Use one of: ${Ji.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;if(n==="verbatim")r="verbatim";else if(n==="synthesis"||n==="")r=void 0;else return this.emitExtensionReply(`Unknown fork argument: \`${n}\`. Use \`/hydra fork\` or \`/hydra fork verbatim\`.`),{stopReason:"end_turn"};try{let o={};if(r&&(o.mode=r),t&&this.historyStore){let d=await this.findMessageIdBefore(t).catch(()=>{});d&&(o.forkAt=d)}let a=(await this.forkHook(Object.keys(o).length>0?o:void 0)).sessionId.replace(/^hydra_session_/,"");this.emitExtensionReply(`Forked to [\`${a}\`](hydra://sessions/${a}).`)}catch(o){this.emitExtensionReply(`Fork failed: ${o instanceof Error?o.message:String(o)}`)}return{stopReason:"end_turn"}}async forceCancel(){if(this.closed||this.closing)throw me(new Error("session is closing"),A.SessionClosing);return this.lastCancelAt=0,this.forceCancelling=!0,await this.close({deleteRecord:!1,by:"force-cancel"}),{stopReason:"cancelled"}}async respawnAgent(){let e=this.spawnReplacementAgent,t=this.agentId,n=await this.buildSwitchTranscript(t),r=await e({agentId:t,cwd:this.cwd,agentArgs:this.agentArgs,...this.forwardedEnv?{forwardedEnv:this.forwardedEnv}:{}});this.accumulateAndResetCost(),this.wireAgent(r.agent);let o=this.agent;this.agent=r.agent,this.upstreamSessionId=r.upstreamSessionId,this.agentMeta=r.agentMeta,this.agentCapabilities=r.agentCapabilities,this.resetModelVerb(r.modelVerb),this.agentAdvertisedCommands=[],this.broadcastMergedCommands(),this.currentModel=r.initialModel,this.currentMode=r.initialMode,this.setAgentAdvertisedModels(r.initialModels??[]),this.setAgentAdvertisedModes(r.initialModes??[]),this.agentAdvertisedConfigOptions=r.initialConfigOptions??[],await this.retireAgent(o,"agent restart"),n&&await this.runInternalPrompt(n).catch(()=>{}),this.broadcastAgentSwitch(t,t),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 m=rt(l.prompt);m&&n.push({speaker:"user",text:m})}else if(f==="agent_message_chunk"){let g=l.content?.text;g&&n.push({speaker:`agent: ${e}`,text:g})}else if(f==="tool_call"||f==="tool_call_update"){let m=l.status,g=l.title;(m==="completed"||m==="failed")&&n.push({speaker:"tool",text:`${g??"?"} ${m}`})}}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(`
84
- `)}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=fr({synopsis:e,title:t,tail:n,tailK:Fl,tailFloor:Nl,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 Tn(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??kt,kt)),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=A.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.currentEntry.wasAmend),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),sr(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(()=>zi(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(()=>ta.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){if(n.sessionUpdate==="tool_call"){this.openToolCalls.add(r);return}n.sessionUpdate==="tool_call_update"&&(n.status==="completed"||n.status==="failed")&&this.openToolCalls.delete(r)}}closeOpenToolCalls(e){if(this.openToolCalls.size===0||this.closed)return;let t=[...this.openToolCalls];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:{[pe]:{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===Ri&&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=!hr(e,r),i=o?sf(e,r):r,a=Date.now(),d=o?_e(i,a):i;if(o){this.noteRecordedToolCall(e,i);let c={method:e,params:i,recordedAt:a};if(this.lastRecordedAt=c.recordedAt,this.appendCount+=1,this.historyStore){let u=this.historyStore;u.append(this.sessionId,c).catch(()=>{}),this.appendCount>=this.compactEvery&&(this.appendCount=0,u.compact(this.sessionId,this.historyMaxEntries).catch(()=>{}))}for(let u of this.broadcastHandlers)try{u(c)}catch{}this.scheduleIdleCheck(),this.dispatchIdle()}this.updatedAt=Date.now();for(let c of this.clients.values())n&&c.clientId===n||c.connection.notify(e,d).catch(()=>{})}async requestPermissionFromClients(e){return this.handlePermissionRequest(e)}async handlePermissionRequest(e){let t=[...this.clients.values()];if(t.length===0)throw me(new Error("no clients attached to handle permission request"),A.PermissionDenied);let n=this.rewriteForClient(e),r=Ki(n),o=Fe(),{toolCall:i,options:a}=n??{};return new Promise((d,c)=>{let u=!1,l=[],p=0,f,m=this.sessionId,g=k=>{u||(u=!0,this.clearAttentionFlag("daemon",`permission:${o}`),this.permissionCallbacks.delete(o),k())},h=k=>k?.code===A.MethodNotFound;function w(k){if(u)return;let y=k.connection.request("session/request_permission",n);l.push({client:k}),p++,y.then(b=>{p--,g(()=>{let I=rf({toolCallId:r,result:b,resolver:k});for(let v of l)v.client.clientId!==k.clientId&&v.client.connection.notify("session/update",{sessionId:m,update:I}).catch(()=>{});d(b)})}).catch(b=>{if(p--,h(b)||(f=b),p===0&&!u){let I=f??me(new Error("no client handled permission request"),A.PermissionDenied);g(()=>c(I))}})}this.setAttentionFlag("daemon",`permission:${o}`,{kind:"permission",toolCall:i??null,options:a??null}),this.permissionCallbacks.set(o,w);for(let k of t)w(k)})}async enqueuePrompt(e,t){return new Promise((n,r)=>{let o={kind:"internal",messageId:Fe(),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){let o=(t??{}).prompt??[],i={clientId:e.clientId};e.clientInfo?.name&&(i.name=e.clientInfo.name),e.clientInfo?.version&&(i.version=e.clientInfo.version),r?.fromSession&&(i.fromSession=r.fromSession),r?.fromSessionTitle&&(i.fromSessionTitle=r.fromSessionTitle),r?.fromLabel&&(i.fromLabel=r.fromLabel),r?.depth!==void 0&&(i.depth=r.depth);let a=this.parseQueuePosition(t);return new Promise((d,c)=>{let u={kind:"user",messageId:n,originator:i,clientId:e.clientId,prompt:o,enqueuedAt:Date.now(),cancelled:!1,resolve:d,reject:c},l=this.insertEntryAt(u,a);this.persistRewrite(),this.broadcastQueueAdded(u,{position:l}),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[pe];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(()=>Gt(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=rt(e.prompt).replace(/\s+$/,""),n=!t.includes(`
85
- `)&&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;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);return this.closed||this.broadcastTurnComplete(e.clientId,d,e.messageId,e.wasAmend),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=yr(e.prompt,df));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,e.wasAmend),this.clearAmendIfMatches(e.messageId),d}finally{this.agentTurnInFlight=!1}return this.closed||this.broadcastTurnComplete(e.clientId,a,e.messageId,e.wasAmend),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||!Jl(r))throw 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()}}clearAmendIfMatches(e){this.amendInProgress?.cancelledMessageId===e&&(this.amendInProgress=void 0)}},zl=["session not found","the claude agent session has ended"];function Jl(s){let e=s;if(e?.code!==A.InternalError)return!1;let t=e.data?.details,n=`${typeof e.message=="string"?e.message:""} ${typeof t=="string"?t:""}`.toLowerCase();return zl.some(r=>n.includes(r))}function me(s,e){return s.code=e,s}var Vl=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 Gl(s,e,t){return t?.run_in_background===!0?!1:e?.toolName==="Monitor"||s==="Monitor"||typeof e?.toolResponse?.taskId=="string"}function Kl(s){return typeof s!="string"?void 0:/Command running in background with ID: ([A-Za-z0-9_-]+)/.exec(s)?.[1]}function Ql(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 hr(s,e){if(s!=="session/update")return!1;let n=(e??{}).update?.sessionUpdate;return typeof n=="string"&&Vl.has(n)}function Yl(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 Xl(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 Zl(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 Kt(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 _n(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 kr(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 ef(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 tf(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 nf(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 sf(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:Fe()}}}function $n(s,e){for(let t=0;t<s.length;t++){let n=s[t];if(!n||n.method!=="session/update")continue;if(n.params?.update?.messageId===e)return t}return-1}function Ki(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 rf(s){let e=of(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=af(s.resolver),t}function of(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 af(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 rt(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?e.text:"").join(""):""}var df="\u200B";function Qi(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 yr(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 wr(s){return s==="session/prompt"?{stopReason:"stopped"}:{}}function cf(s){return s==="session/request_permission"?{outcome:{outcome:"cancelled"}}:{}}function Yi(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}
82
+ `},_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 me(new Error("/hydra agent requires an agent id"),A.InvalidParams);let r=(this.resolveAgentIdHook?await this.resolveAgentIdHook(t):void 0)??t;if(r===this.agentId)throw me(new Error(`already on agent ${r}`),A.InvalidParams);if(!this.scheduleCompactionHook)return this.emitExtensionReply("agent switching not configured for this session"),{stopReason:"end_turn"};this.scheduleCompactionHook({targetAgentId:r});let o=this.promptInFlight||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 me(new Error("agent restart not configured for this session"),A.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=Ui(n,t),o=Li(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(`
83
+ `)),{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(!Vi.includes(t))return this.emitExtensionReply(`Unknown workspace verb "${t}". Use one of: ${Vi.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;if(n==="verbatim")r="verbatim";else if(n==="synthesis"||n==="")r=void 0;else return this.emitExtensionReply(`Unknown fork argument: \`${n}\`. Use \`/hydra fork\` or \`/hydra fork verbatim\`.`),{stopReason:"end_turn"};try{let o={};if(r&&(o.mode=r),t&&this.historyStore){let d=await this.findMessageIdBefore(t).catch(()=>{});d&&(o.forkAt=d)}let a=(await this.forkHook(Object.keys(o).length>0?o:void 0)).sessionId.replace(/^hydra_session_/,"");this.emitExtensionReply(`Forked to [\`${a}\`](hydra://sessions/${a}).`)}catch(o){this.emitExtensionReply(`Fork failed: ${o instanceof Error?o.message:String(o)}`)}return{stopReason:"end_turn"}}async forceCancel(){if(this.closed||this.closing)throw me(new Error("session is closing"),A.SessionClosing);return this.lastCancelAt=0,this.forceCancelling=!0,await this.close({deleteRecord:!1,by:"force-cancel"}),{stopReason:"cancelled"}}async respawnAgent(){let e=this.spawnReplacementAgent,t=this.agentId,n=await this.buildSwitchTranscript(t),r=await e({agentId:t,cwd:this.cwd,agentArgs:this.agentArgs,...this.forwardedEnv?{forwardedEnv:this.forwardedEnv}:{}});this.accumulateAndResetCost(),this.wireAgent(r.agent,{respawn:!0});let o=this.agent;this.agent=r.agent,this.upstreamSessionId=r.upstreamSessionId,this.agentMeta=r.agentMeta,this.agentCapabilities=r.agentCapabilities,this.resetModelVerb(r.modelVerb),this.agentAdvertisedCommands=[],this.broadcastMergedCommands(),this.currentModel=r.initialModel,this.currentMode=r.initialMode,this.setAgentAdvertisedModels(r.initialModels??[]),this.setAgentAdvertisedModes(r.initialModes??[]),this.agentAdvertisedConfigOptions=r.initialConfigOptions??[],await this.retireAgent(o,"agent restart"),n&&await this.runInternalPrompt(n).catch(()=>{}),this.broadcastAgentSwitch(t,t),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 m=rt(l.prompt);m&&n.push({speaker:"user",text:m})}else if(f==="agent_message_chunk"){let g=l.content?.text;g&&n.push({speaker:`agent: ${e}`,text:g})}else if(f==="tool_call"||f==="tool_call_update"){let m=l.status,g=l.title;(m==="completed"||m==="failed")&&n.push({speaker:"tool",text:`${g??"?"} ${m}`})}}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(`
84
+ `)}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=fr({synopsis:e,title:t,tail:n,tailK:Nl,tailFloor:Hl,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 Tn(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??kt,kt)),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=A.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),sr(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(()=>Ji(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(()=>na.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){if(n.sessionUpdate==="tool_call"){this.openToolCalls.add(r);return}n.sessionUpdate==="tool_call_update"&&(n.status==="completed"||n.status==="failed")&&this.openToolCalls.delete(r)}}closeOpenToolCalls(e){if(this.openToolCalls.size===0||this.closed)return;let t=[...this.openToolCalls];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:{[pe]:{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===xi&&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=!hr(e,r),i=o?rf(e,r):r,a=Date.now(),d=o?_e(i,a):i;if(o){this.noteRecordedToolCall(e,i);let c={method:e,params:i,recordedAt:a};if(this.lastRecordedAt=c.recordedAt,this.appendCount+=1,this.historyStore){let u=this.historyStore;u.append(this.sessionId,c).catch(()=>{}),this.appendCount>=this.compactEvery&&(this.appendCount=0,u.compact(this.sessionId,this.historyMaxEntries).catch(()=>{}))}for(let u of this.broadcastHandlers)try{u(c)}catch{}this.scheduleIdleCheck(),this.dispatchIdle()}this.updatedAt=Date.now();for(let c of this.clients.values())n&&c.clientId===n||c.connection.notify(e,d).catch(()=>{})}async requestPermissionFromClients(e){return this.handlePermissionRequest(e)}async handlePermissionRequest(e){let t=[...this.clients.values()];if(t.length===0)throw me(new Error("no clients attached to handle permission request"),A.PermissionDenied);let n=this.rewriteForClient(e),r=Qi(n),o=Fe(),{toolCall:i,options:a}=n??{};return new Promise((d,c)=>{let u=!1,l=[],p=0,f,m=this.sessionId,g=k=>{u||(u=!0,this.clearAttentionFlag("daemon",`permission:${o}`),this.permissionCallbacks.delete(o),k())},h=k=>k?.code===A.MethodNotFound;function w(k){if(u)return;let y=k.connection.request("session/request_permission",n);l.push({client:k}),p++,y.then(b=>{p--,g(()=>{let I=of({toolCallId:r,result:b,resolver:k});for(let v of l)v.client.clientId!==k.clientId&&v.client.connection.notify("session/update",{sessionId:m,update:I}).catch(()=>{});d(b)})}).catch(b=>{if(p--,h(b)||(f=b),p===0&&!u){let I=f??me(new Error("no client handled permission request"),A.PermissionDenied);g(()=>c(I))}})}this.setAttentionFlag("daemon",`permission:${o}`,{kind:"permission",toolCall:i??null,options:a??null}),this.permissionCallbacks.set(o,w);for(let k of t)w(k)})}async enqueuePrompt(e,t){return new Promise((n,r)=>{let o={kind:"internal",messageId:Fe(),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[pe];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(()=>Gt(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=rt(e.prompt).replace(/\s+$/,""),n=!t.includes(`
85
+ `)&&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;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);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=yr(e.prompt,cf));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)),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||!Vl(r))throw 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()}}clearAmendIfMatches(e){this.amendInProgress?.cancelledMessageId===e&&(this.amendInProgress=void 0)}},Jl=["session not found","the claude agent session has ended"];function Vl(s){let e=s;if(e?.code!==A.InternalError)return!1;let t=e.data?.details,n=`${typeof e.message=="string"?e.message:""} ${typeof t=="string"?t:""}`.toLowerCase();return Jl.some(r=>n.includes(r))}function me(s,e){return s.code=e,s}var Gl=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 Kl(s,e,t){return t?.run_in_background===!0?!1:e?.toolName==="Monitor"||s==="Monitor"||typeof e?.toolResponse?.taskId=="string"}function Ql(s){return typeof s!="string"?void 0:/Command running in background with ID: ([A-Za-z0-9_-]+)/.exec(s)?.[1]}function Yl(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 hr(s,e){if(s!=="session/update")return!1;let n=(e??{}).update?.sessionUpdate;return typeof n=="string"&&Gl.has(n)}function Xl(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 Zl(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 ef(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 Kt(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 _n(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 kr(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 tf(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 nf(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 sf(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 rf(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:Fe()}}}function $n(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 Qi(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 of(s){let e=af(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=df(s.resolver),t}function af(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 df(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 rt(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?e.text:"").join(""):""}var cf="\u200B";function Yi(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 yr(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 wr(s){return s==="session/prompt"?{stopReason:"stopped"}:{}}function uf(s){return s==="session/request_permission"?{outcome:{outcome:"cancelled"}}:{}}function Xi(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}
86
86
  ${n.join(`
87
- `)}`}function vr(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}}Q();Le();import*as Rt from"fs/promises";import*as Ew from"path";import{customAlphabet as ff}from"nanoid";import{z as P}from"zod";import{z as At}from"zod";var uf=At.object({source:At.string(),reason:At.string(),raisedAt:At.number(),payload:At.unknown()}),na=At.array(uf);import{z as V}from"zod";var sa=V.object({status:V.enum(["requested","running","swap_pending","swap_deferred","failed"]),requestedAt:V.number(),runId:V.string().optional(),iter:V.number().int().nonnegative().optional(),attempts:V.number().int().nonnegative().optional(),lastError:V.string().optional(),worker:V.object({upstreamSessionId:V.string(),pid:V.number().int().nonnegative()}).optional()}),Qt=V.object({goal:V.string().optional(),outcome:V.string().optional(),files_touched:V.array(V.string()).optional(),tools_used:V.array(V.string()).optional(),rejected_approaches:V.array(V.string()).optional(),open_threads:V.array(V.string()).optional(),decisions:V.array(V.string()).optional(),file_edit_intentions:V.array(V.string()).optional(),unresolved_errors:V.array(V.string()).optional(),tool_state:V.array(V.string()).optional()}),ra=200,br=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
87
+ `)}`}function vr(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}}Q();Le();import*as Rt from"fs/promises";import*as Tw from"path";import{customAlphabet as pf}from"nanoid";import{z as P}from"zod";import{z as At}from"zod";var lf=At.object({source:At.string(),reason:At.string(),raisedAt:At.number(),payload:At.unknown()}),sa=At.array(lf);import{z as V}from"zod";var ra=V.object({status:V.enum(["requested","running","swap_pending","swap_deferred","failed"]),requestedAt:V.number(),runId:V.string().optional(),iter:V.number().int().nonnegative().optional(),attempts:V.number().int().nonnegative().optional(),lastError:V.string().optional(),worker:V.object({upstreamSessionId:V.string(),pid:V.number().int().nonnegative()}).optional()}),Qt=V.object({goal:V.string().optional(),outcome:V.string().optional(),files_touched:V.array(V.string()).optional(),tools_used:V.array(V.string()).optional(),rejected_approaches:V.array(V.string()).optional(),open_threads:V.array(V.string()).optional(),decisions:V.array(V.string()).optional(),file_edit_intentions:V.array(V.string()).optional(),unresolved_errors:V.array(V.string()).optional(),tool_state:V.array(V.string()).optional()}),oa=200,br=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
88
88
  {
89
89
  "title": "short summary, max 80 chars",
90
90
  "synopsis": {
@@ -94,7 +94,7 @@ ${n.join(`
94
94
  "open_threads": ["work started but not finished"]
95
95
  }
96
96
  }
97
- Use empty arrays/strings where a field doesn't apply.`;function oa(s){let e=s.trim();if(e.length===0)return;let t=Ct(e);if(t===void 0){let o=e.indexOf("{"),i=e.lastIndexOf("}");o>=0&&i>o&&(t=Ct(e.slice(o,i+1)))}if(t===void 0){let o=aa(e);o!==void 0&&(t=Ct(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,ra))}if(n.synopsis!==void 0&&n.synopsis!==null){let o=Qt.safeParse(n.synopsis);o.success&&lf(o.data)&&(r.synopsis=o.data)}if(!(r.title===void 0&&r.synopsis===void 0))return r}var Sr=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
97
+ Use empty arrays/strings where a field doesn't apply.`;function ia(s){let e=s.trim();if(e.length===0)return;let t=Ct(e);if(t===void 0){let o=e.indexOf("{"),i=e.lastIndexOf("}");o>=0&&i>o&&(t=Ct(e.slice(o,i+1)))}if(t===void 0){let o=da(e);o!==void 0&&(t=Ct(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,oa))}if(n.synopsis!==void 0&&n.synopsis!==null){let o=Qt.safeParse(n.synopsis);o.success&&ff(o.data)&&(r.synopsis=o.data)}if(!(r.title===void 0&&r.synopsis===void 0))return r}var Sr=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
98
98
  {
99
99
  "title": "short summary, max 80 chars",
100
100
  "goal": "the user's original ask",
@@ -106,26 +106,26 @@ Use empty arrays/strings where a field doesn't apply.`;function oa(s){let e=s.tr
106
106
  "unresolved_errors": ["errors left open at session end"],
107
107
  "tool_state": ["runtime state relevant for recall"]
108
108
  }
109
- Use empty arrays/strings where a field doesn't apply.`;function ia(s){let e=s.trim();if(e.length===0)return;let t=Ct(e);if(t===void 0){let c=e.indexOf("{"),u=e.lastIndexOf("}");c>=0&&u>c&&(t=Ct(e.slice(c,u+1)))}if(t===void 0){let c=aa(e);c!==void 0&&(t=Ct(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,ra))}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=V.array(V.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 Ct(s){try{return JSON.parse(s)}catch{return}}function aa(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 lf(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 pf="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",gf=ff(pf,16),mf="hydra_lineage_";function Yt(){return`${mf}${gf()}`}var Ar=P.object({name:P.string(),description:P.string().optional()}),Cr=P.object({id:P.string(),name:P.string().optional(),description:P.string().optional()}),hf=P.object({modelId:P.string(),name:P.string().optional(),description:P.string().optional()}),Rr=P.object({used:P.number().optional(),size:P.number().optional(),costAmount:P.number().optional(),costCurrency:P.string().optional(),cumulativeCost:P.number().optional()}),xr=P.object({name:P.string(),version:P.string().optional()}),yf=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()}),wf=P.object({previousUpstreamSessionId:P.string(),previousSummarizedThroughEntry:P.number().int().nonnegative().optional(),runId:P.string().optional()}),kf=P.enum(["compaction","agent-swap","workspace-enter","workspace-leave","rollback","restart"]),vf=P.object({upstreamSessionId:P.string(),agentId:P.string(),reason:kf.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()}),bf=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:Qt.optional(),compactionState:sa.optional(),rollbackBreadcrumb:wf.optional(),upstreamGenerations:P.array(vf).optional(),summarizedThroughEntry:P.number().int().nonnegative().optional(),agentArgs:P.array(P.string()).optional(),currentModel:P.string().optional(),currentMode:P.string().optional(),currentUsage:Rr.optional(),agentCommands:P.array(Ar).optional(),agentModes:P.array(Cr).optional(),agentModels:P.array(hf).optional(),pendingHistorySync:P.boolean().optional(),pendingAgentSwap:P.string().optional(),parentSessionId:P.string().optional(),forkedFromSessionId:P.string().optional(),forkedFromMessageId:P.string().optional(),forkSynthesisState:P.enum(["running","failed"]).optional(),originatingClient:xr.optional(),interactive:P.boolean().optional(),priority:P.number().int().nonnegative().optional(),forwardedEnv:P.record(P.string(),P.string()).optional(),workspace:yf.optional(),attentionFlags:na.default([]).optional(),extensionState:P.record(P.string(),P.record(P.string(),P.unknown())).default({}).optional(),createdAt:P.string(),updatedAt:P.string()}),Ir=/^[A-Za-z0-9_-]+$/;function Sf(s){if(!Ir.test(s))throw new Error(`unsafe session id: ${s}`)}var On=class{async write(e){Sf(e.sessionId);let t={version:1,...e};await ye(C.sessionFile(e.sessionId),t,{mode:384})}async read(e){if(!Ir.test(e))return;let t=await se(C.sessionFile(e));if(t!==void 0)try{return bf.parse(t)}catch{return}}async delete(e){if(Ir.test(e)){try{await Rt.unlink(C.sessionFile(e))}catch(t){if(t.code!=="ENOENT")throw t}try{await Rt.rmdir(C.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 Rt.readdir(C.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 Er(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,pendingHistorySync:s.pendingHistorySync,pendingAgentSwap:s.pendingAgentSwap,parentSessionId:s.parentSessionId,forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:s.interactive,priority:s.priority,forwardedEnv:s.forwardedEnv,workspace:s.workspace,attentionFlags:s.attentionFlags??[],extensionState:s.extensionState??{},createdAt:t,updatedAt:s.updatedAt??e}}Le();Q();import*as de from"fs/promises";import*as ce from"path";Q();import*as Fn from"path";import{createHash as If}from"crypto";var Re=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=If("sha256").update(Fn.resolve(s)).digest("hex").slice(0,12);return Fn.join(L(),"workspaces",e)}async function Nn(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 ot(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 Tr(s){return s.changedPaths.length>0||s.recorded!==void 0&&s.recorded!==s.actual}function Af(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 Pr(s,e){let t=new Set(e.map(r=>r.relPath));return[...s.filter(r=>!t.has(r.replace(/\/$/,""))),...Af(e.filter(Tr))]}function Hn(s){let e=s.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return e.length>0?e.slice(0,64):"workspace"}var Mr="copy",ca=new Set([".git"]);function Xt(s){return`${s}.manifest.json`}async function da(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 de.readdir(n,{withFileTypes:!0})}catch{continue}for(let o of r){let i=ce.join(n,o.name);if(!(n===s&&ca.has(o.name))){if(o.isDirectory()){t.push(i);continue}if(o.isFile())try{let a=await de.stat(i);e.set(ce.relative(s,i),{size:a.size,mtimeMs:a.mtimeMs})}catch{continue}}}}return e}var jn=class{kind=Mr;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=ce.resolve(e.sourceCwd),n=e.contentFrom!==void 0?ce.resolve(e.contentFrom):t;try{if(!(await de.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 de.mkdir(r,{recursive:!0})}catch(c){return{ok:!1,reason:`could not create workspace root: ${String(c)}`}}let o=await Nn(Hn(e.label),async c=>de.access(ce.join(r,c)).then(()=>!1).catch(()=>!0));if(o===void 0)return{ok:!1,reason:`no free name available for "${e.label}"`};let i=ce.join(r,o);try{await de.cp(n,i,{recursive:!0,errorOnExist:!1,force:!0,filter:c=>{let u=ce.relative(n,c);if(u.length===0)return!0;let l=u.split(ce.sep)[0];return l===void 0||!ca.has(l)}})}catch(c){return await de.rm(i,{recursive:!0,force:!0}).catch(()=>{}),{ok:!1,reason:`copy failed: ${String(c)}`}}let a=await da(i),d={sourceCwd:t,label:o,createdAt:new Date().toISOString(),entries:Object.fromEntries(a)};return await ye(Xt(i),d,{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 de.rm(e.path,{recursive:!0,force:!0}),await de.rm(Xt(e.path),{force:!0})}async listWorkspaces(e){let t=xt(ce.resolve(e)),n;try{n=await de.readdir(t)}catch{return[]}let r=[];for(let o of n){if(o.endsWith(".manifest.json"))continue;let i=ce.join(t,o),a=await se(Xt(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 se(Xt(e.path)),n=await da(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:`,...ot(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 Re(this.kind,"captureWorkingState")}async record(){throw new Re(this.kind,"record")}async attributeOrphan(e){let t=await se(Xt(e));if(t?.sourceCwd!==void 0)return{path:e,sourceCwd:t.sourceCwd,label:t.label??ce.basename(e),provider:this.kind}}async discardLine(){return{ok:!0,dropped:0}}ownsLine(){return!1}async pruneStale(){}async changedPaths(){throw new Re(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 Re(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 Re(this.kind,"lock")}async unlock(){throw new Re(this.kind,"unlock")}};Q();import{execFile as ga}from"child_process";import{randomBytes as Ef}from"crypto";import*as xe from"fs/promises";import*as ma from"os";import*as Y from"path";function Cf(s){let e=s.indexOf(" ");return e===-1?{key:s,value:""}:{key:s.slice(0,e),value:s.slice(e+1)}}function ua(s){let e=[],t,n=()=>{t!==void 0&&(e.push(t),t=void 0)};for(let r of s.split(`
110
- `)){let o=r.replace(/\r$/,"");if(o.length===0){n();continue}let{key:i,value:a}=Cf(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 la(s){if(s===void 0)return;let e="refs/heads/";return s.startsWith(e)?s.slice(e.length):s}var Ln="git",fa="hydra-acp:",_r="hydra",B=5e3,re=12e4,Dn=9e5;function pa(s){return xe.access(s).then(()=>!0).catch(()=>!1)}function Tf(s){return xe.realpath(s).catch(()=>s)}function H(s,e,t,n){return new Promise(r=>{ga("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 $r(s,e,t,n=re){return new Promise(r=>{let o=ga("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 Or(s){let e=[];for(let t of s.split(`
111
- `)){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 Un=class{kind=Ln;refRoot(e){return e.vcs?.repoRoot??e.sourceCwd}ownsLine(e){return e.startsWith(`${_r}/`)}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 pa(Y.join(e.path,".gitmodules")))return{ok:!0,count:0};let r=await H(["submodule","update","--init","--recursive",...t?.discardLocal===!0?["--force"]:[]],e.path,Dn);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,Dn);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,Dn);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,B);return{ok:!0,count:o.ok?o.stdout.split(`
112
- `).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 pa(n))return{ok:!1,reason:`source repository ${n} no longer exists`};let r=await H(["rev-parse","--verify","--quiet",`refs/heads/${t}`],n,B);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,B),await H(["worktree","prune"],n,B);let o=await H(["worktree","add",e.path,t],n,re);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=Y.resolve(e.sourceCwd),n=await H(["rev-parse","--show-toplevel"],t,B);if(!n.ok)return{ok:!1,reason:`${t} is not a git repository (or git is unavailable)`};let r=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,B);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=Hn(e.label),d=xt(t);try{await xe.mkdir(d,{recursive:!0})}catch(f){return{ok:!1,reason:`could not create workspace root: ${String(f)}`}}let c=await Nn(a,async f=>await xe.access(Y.join(d,f)).then(()=>!0).catch(()=>!1)?!1:!(await H(["rev-parse","--verify","--quiet",`refs/heads/${_r}/${f}`],r,B)).ok);if(c===void 0)return{ok:!1,reason:`no free name available for "${a}"`};let u=Y.join(d,c),l=`${_r}/${c}`,p=await H(["worktree","add","--no-track","-b",l,u,i],r,re);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,re);t.discardLine===!0&&e.vcs?.branch!==void 0&&await H(["branch","-D",e.vcs.branch],n,B),r.ok||(await xe.rm(e.path,{recursive:!0,force:!0}),await H(["worktree","prune"],n,B))}async listWorkspaces(e){let t=Y.resolve(e),n=await H(["rev-parse","--show-toplevel"],t,B);if(!n.ok)return[];let r=n.stdout.trim(),o=await H(["worktree","list","--porcelain"],r,B);if(!o.ok)return[];let i=xt(t),a=await Tf(i),d=[];for(let c of ua(o.stdout)){let u=Y.dirname(c.path);if(u!==i&&u!==a)continue;let l=Y.join(i,Y.basename(c.path)),p={kind:"git",repoRoot:r},f=la(c.branch);f!==void 0&&(p.branch=f),c.head!==void 0&&(p.head=c.head),c.lockedReason!==void 0&&(p.locked=c.lockedReason);let m=c.lockedReason?.startsWith(fa)===!0;d.push({path:l,sourceCwd:t,label:Y.basename(l),...m?{heldByUs:!0}:{},provider:this.kind,...f!==void 0?{line:f}:{},vcs:p})}return d}async status(e){let t=await H(["status","--porcelain","--untracked-files=all"],e.path,B);if(!t.ok)return{clean:!1,changedPaths:[],hasRecordedWork:!1};let n=Or(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,B);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",`${fa}${t}`,e.path],n,B)}async unlock(e){let t=this.refRoot(e);await H(["worktree","unlock",e.path],t,B)}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 xe.access(Y.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,B);if(n.ok){let r=Or(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(...ot(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,B),H(["rev-parse","HEAD"],e.path,B)]),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,B),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=Y.join(ma.tmpdir(),`hydra-index-${process.pid}-${Ef(6).toString("hex")}`),r={GIT_INDEX_FILE:n};try{let o=await H(["rev-parse","--verify","HEAD"],e,B),i=o.ok&&o.stdout.trim().length>0;if(i){let l=await H(["read-tree","HEAD"],e,re,r);if(!l.ok)throw new Error(`could not seed the snapshot index: ${l.stderr.trim()}`)}let a=await H(["add","-A"],e,re,r);if(!a.ok)throw new Error(`could not stage working state: ${a.stderr.trim()}`);let d=await H(["write-tree"],e,re,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,re,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 xe.rm(n,{force:!0}).catch(()=>{})}}async retainSnapshot(e,t,n){let r=this.refRoot(e);await H(["update-ref","--create-reflog",t,n],r,B)}async dropSnapshotRef(e,t){let n=this.refRoot(e);await H(["update-ref","-d",t],n,B)}async currentState(e){let t=await H(["rev-parse","HEAD"],e,B),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,B),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,B),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,B),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),B),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,B)).ok}async divergence(e,t,n){let r=await H(["rev-list","--left-right","--count",`${t}...${n}`],e,B);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,B);return r.ok?r.stdout.split(`
109
+ Use empty arrays/strings where a field doesn't apply.`;function aa(s){let e=s.trim();if(e.length===0)return;let t=Ct(e);if(t===void 0){let c=e.indexOf("{"),u=e.lastIndexOf("}");c>=0&&u>c&&(t=Ct(e.slice(c,u+1)))}if(t===void 0){let c=da(e);c!==void 0&&(t=Ct(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,oa))}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=V.array(V.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 Ct(s){try{return JSON.parse(s)}catch{return}}function da(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 ff(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 gf="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",mf=pf(gf,16),hf="hydra_lineage_";function Yt(){return`${hf}${mf()}`}var Ar=P.object({name:P.string(),description:P.string().optional()}),Cr=P.object({id:P.string(),name:P.string().optional(),description:P.string().optional()}),yf=P.object({modelId:P.string(),name:P.string().optional(),description:P.string().optional()}),Rr=P.object({used:P.number().optional(),size:P.number().optional(),costAmount:P.number().optional(),costCurrency:P.string().optional(),cumulativeCost:P.number().optional()}),xr=P.object({name:P.string(),version:P.string().optional()}),wf=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()}),kf=P.object({previousUpstreamSessionId:P.string(),previousSummarizedThroughEntry:P.number().int().nonnegative().optional(),runId:P.string().optional()}),vf=P.enum(["compaction","agent-swap","workspace-enter","workspace-leave","rollback","restart"]),bf=P.object({upstreamSessionId:P.string(),agentId:P.string(),reason:vf.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()}),Sf=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:Qt.optional(),compactionState:ra.optional(),rollbackBreadcrumb:kf.optional(),upstreamGenerations:P.array(bf).optional(),summarizedThroughEntry:P.number().int().nonnegative().optional(),agentArgs:P.array(P.string()).optional(),currentModel:P.string().optional(),currentMode:P.string().optional(),currentUsage:Rr.optional(),agentCommands:P.array(Ar).optional(),agentModes:P.array(Cr).optional(),agentModels:P.array(yf).optional(),pendingHistorySync:P.boolean().optional(),pendingAgentSwap:P.string().optional(),parentSessionId:P.string().optional(),forkedFromSessionId:P.string().optional(),forkedFromMessageId:P.string().optional(),forkSynthesisState:P.enum(["running","failed"]).optional(),originatingClient:xr.optional(),interactive:P.boolean().optional(),priority:P.number().int().nonnegative().optional(),forwardedEnv:P.record(P.string(),P.string()).optional(),workspace:wf.optional(),attentionFlags:sa.default([]).optional(),extensionState:P.record(P.string(),P.record(P.string(),P.unknown())).default({}).optional(),createdAt:P.string(),updatedAt:P.string()}),Ir=/^[A-Za-z0-9_-]+$/;function If(s){if(!Ir.test(s))throw new Error(`unsafe session id: ${s}`)}var On=class{async write(e){If(e.sessionId);let t={version:1,...e};await ye(C.sessionFile(e.sessionId),t,{mode:384})}async read(e){if(!Ir.test(e))return;let t=await se(C.sessionFile(e));if(t!==void 0)try{return Sf.parse(t)}catch{return}}async delete(e){if(Ir.test(e)){try{await Rt.unlink(C.sessionFile(e))}catch(t){if(t.code!=="ENOENT")throw t}try{await Rt.rmdir(C.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 Rt.readdir(C.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 Er(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,pendingHistorySync:s.pendingHistorySync,pendingAgentSwap:s.pendingAgentSwap,parentSessionId:s.parentSessionId,forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:s.interactive,priority:s.priority,forwardedEnv:s.forwardedEnv,workspace:s.workspace,attentionFlags:s.attentionFlags??[],extensionState:s.extensionState??{},createdAt:t,updatedAt:s.updatedAt??e}}Le();Q();import*as de from"fs/promises";import*as ce from"path";Q();import*as Fn from"path";import{createHash as Af}from"crypto";var Re=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=Af("sha256").update(Fn.resolve(s)).digest("hex").slice(0,12);return Fn.join(L(),"workspaces",e)}async function Nn(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 ot(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 Tr(s){return s.changedPaths.length>0||s.recorded!==void 0&&s.recorded!==s.actual}function Cf(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 Pr(s,e){let t=new Set(e.map(r=>r.relPath));return[...s.filter(r=>!t.has(r.replace(/\/$/,""))),...Cf(e.filter(Tr))]}function Hn(s){let e=s.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return e.length>0?e.slice(0,64):"workspace"}var Mr="copy",ua=new Set([".git"]);function Xt(s){return`${s}.manifest.json`}async function ca(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 de.readdir(n,{withFileTypes:!0})}catch{continue}for(let o of r){let i=ce.join(n,o.name);if(!(n===s&&ua.has(o.name))){if(o.isDirectory()){t.push(i);continue}if(o.isFile())try{let a=await de.stat(i);e.set(ce.relative(s,i),{size:a.size,mtimeMs:a.mtimeMs})}catch{continue}}}}return e}var jn=class{kind=Mr;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=ce.resolve(e.sourceCwd),n=e.contentFrom!==void 0?ce.resolve(e.contentFrom):t;try{if(!(await de.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 de.mkdir(r,{recursive:!0})}catch(c){return{ok:!1,reason:`could not create workspace root: ${String(c)}`}}let o=await Nn(Hn(e.label),async c=>de.access(ce.join(r,c)).then(()=>!1).catch(()=>!0));if(o===void 0)return{ok:!1,reason:`no free name available for "${e.label}"`};let i=ce.join(r,o);try{await de.cp(n,i,{recursive:!0,errorOnExist:!1,force:!0,filter:c=>{let u=ce.relative(n,c);if(u.length===0)return!0;let l=u.split(ce.sep)[0];return l===void 0||!ua.has(l)}})}catch(c){return await de.rm(i,{recursive:!0,force:!0}).catch(()=>{}),{ok:!1,reason:`copy failed: ${String(c)}`}}let a=await ca(i),d={sourceCwd:t,label:o,createdAt:new Date().toISOString(),entries:Object.fromEntries(a)};return await ye(Xt(i),d,{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 de.rm(e.path,{recursive:!0,force:!0}),await de.rm(Xt(e.path),{force:!0})}async listWorkspaces(e){let t=xt(ce.resolve(e)),n;try{n=await de.readdir(t)}catch{return[]}let r=[];for(let o of n){if(o.endsWith(".manifest.json"))continue;let i=ce.join(t,o),a=await se(Xt(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 se(Xt(e.path)),n=await ca(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:`,...ot(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 Re(this.kind,"captureWorkingState")}async record(){throw new Re(this.kind,"record")}async attributeOrphan(e){let t=await se(Xt(e));if(t?.sourceCwd!==void 0)return{path:e,sourceCwd:t.sourceCwd,label:t.label??ce.basename(e),provider:this.kind}}async discardLine(){return{ok:!0,dropped:0}}ownsLine(){return!1}async pruneStale(){}async changedPaths(){throw new Re(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 Re(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 Re(this.kind,"lock")}async unlock(){throw new Re(this.kind,"unlock")}};Q();import{execFile as ma}from"child_process";import{randomBytes as Tf}from"crypto";import*as xe from"fs/promises";import*as ha from"os";import*as Y from"path";function Rf(s){let e=s.indexOf(" ");return e===-1?{key:s,value:""}:{key:s.slice(0,e),value:s.slice(e+1)}}function la(s){let e=[],t,n=()=>{t!==void 0&&(e.push(t),t=void 0)};for(let r of s.split(`
110
+ `)){let o=r.replace(/\r$/,"");if(o.length===0){n();continue}let{key:i,value:a}=Rf(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 fa(s){if(s===void 0)return;let e="refs/heads/";return s.startsWith(e)?s.slice(e.length):s}var Ln="git",pa="hydra-acp:",_r="hydra",B=5e3,re=12e4,Dn=9e5;function ga(s){return xe.access(s).then(()=>!0).catch(()=>!1)}function Pf(s){return xe.realpath(s).catch(()=>s)}function H(s,e,t,n){return new Promise(r=>{ma("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 $r(s,e,t,n=re){return new Promise(r=>{let o=ma("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 Or(s){let e=[];for(let t of s.split(`
111
+ `)){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 Un=class{kind=Ln;refRoot(e){return e.vcs?.repoRoot??e.sourceCwd}ownsLine(e){return e.startsWith(`${_r}/`)}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 ga(Y.join(e.path,".gitmodules")))return{ok:!0,count:0};let r=await H(["submodule","update","--init","--recursive",...t?.discardLocal===!0?["--force"]:[]],e.path,Dn);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,Dn);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,Dn);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,B);return{ok:!0,count:o.ok?o.stdout.split(`
112
+ `).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 ga(n))return{ok:!1,reason:`source repository ${n} no longer exists`};let r=await H(["rev-parse","--verify","--quiet",`refs/heads/${t}`],n,B);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,B),await H(["worktree","prune"],n,B);let o=await H(["worktree","add",e.path,t],n,re);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=Y.resolve(e.sourceCwd),n=await H(["rev-parse","--show-toplevel"],t,B);if(!n.ok)return{ok:!1,reason:`${t} is not a git repository (or git is unavailable)`};let r=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,B);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=Hn(e.label),d=xt(t);try{await xe.mkdir(d,{recursive:!0})}catch(f){return{ok:!1,reason:`could not create workspace root: ${String(f)}`}}let c=await Nn(a,async f=>await xe.access(Y.join(d,f)).then(()=>!0).catch(()=>!1)?!1:!(await H(["rev-parse","--verify","--quiet",`refs/heads/${_r}/${f}`],r,B)).ok);if(c===void 0)return{ok:!1,reason:`no free name available for "${a}"`};let u=Y.join(d,c),l=`${_r}/${c}`,p=await H(["worktree","add","--no-track","-b",l,u,i],r,re);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,re);t.discardLine===!0&&e.vcs?.branch!==void 0&&await H(["branch","-D",e.vcs.branch],n,B),r.ok||(await xe.rm(e.path,{recursive:!0,force:!0}),await H(["worktree","prune"],n,B))}async listWorkspaces(e){let t=Y.resolve(e),n=await H(["rev-parse","--show-toplevel"],t,B);if(!n.ok)return[];let r=n.stdout.trim(),o=await H(["worktree","list","--porcelain"],r,B);if(!o.ok)return[];let i=xt(t),a=await Pf(i),d=[];for(let c of la(o.stdout)){let u=Y.dirname(c.path);if(u!==i&&u!==a)continue;let l=Y.join(i,Y.basename(c.path)),p={kind:"git",repoRoot:r},f=fa(c.branch);f!==void 0&&(p.branch=f),c.head!==void 0&&(p.head=c.head),c.lockedReason!==void 0&&(p.locked=c.lockedReason);let m=c.lockedReason?.startsWith(pa)===!0;d.push({path:l,sourceCwd:t,label:Y.basename(l),...m?{heldByUs:!0}:{},provider:this.kind,...f!==void 0?{line:f}:{},vcs:p})}return d}async status(e){let t=await H(["status","--porcelain","--untracked-files=all"],e.path,B);if(!t.ok)return{clean:!1,changedPaths:[],hasRecordedWork:!1};let n=Or(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,B);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",`${pa}${t}`,e.path],n,B)}async unlock(e){let t=this.refRoot(e);await H(["worktree","unlock",e.path],t,B)}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 xe.access(Y.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,B);if(n.ok){let r=Or(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(...ot(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,B),H(["rev-parse","HEAD"],e.path,B)]),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,B),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=Y.join(ha.tmpdir(),`hydra-index-${process.pid}-${Tf(6).toString("hex")}`),r={GIT_INDEX_FILE:n};try{let o=await H(["rev-parse","--verify","HEAD"],e,B),i=o.ok&&o.stdout.trim().length>0;if(i){let l=await H(["read-tree","HEAD"],e,re,r);if(!l.ok)throw new Error(`could not seed the snapshot index: ${l.stderr.trim()}`)}let a=await H(["add","-A"],e,re,r);if(!a.ok)throw new Error(`could not stage working state: ${a.stderr.trim()}`);let d=await H(["write-tree"],e,re,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,re,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 xe.rm(n,{force:!0}).catch(()=>{})}}async retainSnapshot(e,t,n){let r=this.refRoot(e);await H(["update-ref","--create-reflog",t,n],r,B)}async dropSnapshotRef(e,t){let n=this.refRoot(e);await H(["update-ref","-d",t],n,B)}async currentState(e){let t=await H(["rev-parse","HEAD"],e,B),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,B),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,B),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,B),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),B),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,B)).ok}async divergence(e,t,n){let r=await H(["rev-list","--left-right","--count",`${t}...${n}`],e,B);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,B);return r.ok?r.stdout.split(`
113
113
  `).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,re);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 $r(["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 $r(["apply","--reverse","--check"],e,t)).ok)return{ok:!0,alreadyPresent:!0};let a=await $r(["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,re);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,re);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,B)).ok}async abortIntegration(e){await H(["merge","--abort"],e,re)}async conflictedPaths(e){let t=await H(["diff","--name-only","--diff-filter=U"],e,B);return t.ok?t.stdout.split(`
114
114
  `).map(n=>n.replace(/\r$/,"").trim()).filter(n=>n.length>0):[]}async record(e,t){let n=await H(["add","-A"],e.path,re);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,re);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,B),n=t.stdout.trim();if(!t.ok||n.length===0)return;let r=Y.dirname(n),o=await this.currentLineName(e);return{path:e,sourceCwd:r,label:Y.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,B);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),B)}async changedPaths(){throw new Re(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,re);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,re);if(!t.ok)return[];let n=[];for(let r of t.stdout.split(`
115
- `)){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||!Pf(e,c))continue;let u=Y.join(e,c),[l,p,f]=await Promise.all([this.currentState(u),H(["rev-parse",`HEAD:${c}`],e,B),H(["status","--porcelain","--untracked-files=all"],u,B)]);if(l===void 0)continue;let m=p.ok?p.stdout.trim():"";n.push({relPath:c,actual:l,...m.length>0?{recorded:m}:{},changedPaths:f.ok?Or(f.stdout).map(g=>g.path):[]})}return n}async captureNested(e,t){let n=[];for(let r of t){if(!Tr(r))continue;if(r.changedPaths.length===0){n.push(r);continue}let o=Y.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=Y.join(e,i.relPath),d=Y.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(h=>h.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 m=Y.join(e,c),g=Y.join(t,c);if(p&&u.recorded!==void 0){let h=await this.alignNested(m,g,u.recorded);if(h!==void 0){o.push({path:c,reason:h});continue}}if(l?.delta!==void 0){let h=await this.applyDelta(m,l.delta);if(!h.ok){o.push({path:c,reason:h.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,B)).ok&&!(await H(["fetch","--no-tags",t,n],e,Dn)).ok)return`could not transfer ${n.slice(0,8)} from the other copy`;if(!(await H(["checkout","--detach",n],e,re)).ok)return`could not move to ${n.slice(0,8)}`}};function Pf(s,e){if(Y.isAbsolute(e))return!1;let t=Y.resolve(s),n=Y.resolve(t,e);return n!==t&&n.startsWith(t+Y.sep)}var Mf=Ln,_f=new Map([[Ln,new Un],[Mr,new jn]]);function Z(s){return _f.get(s??Mf)}var Bn="refs/hydra";function Zt(s){let e=`${Bn}/workspaces/${s}`;return{autosave:`${e}/autosave`,start:`${e}/start`,baseline:`${e}/baseline`}}function Fr(s){return`${Bn}/landing/${s}`}function ha(s){return`${Bn}/sync/${s}`}function ya(s,e){return`${Bn}/retired/${s}-${e.slice(0,12)}`}function wa(s){let e=Zt(s);return[e.autosave,e.start,e.baseline]}async function Nr(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 it(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 en(s){s.capture.retainedRef===void 0||s.provider===void 0||await s.provider.dropSnapshotRef({...s.ws,path:s.source},s.capture.retainedRef).catch(()=>{})}Le();import{execFile as $f}from"child_process";import*as He from"fs/promises";import*as ke from"path";var Of=".hydra/worktree.json",Ff=".worktreeinclude",Nf=120;async function Wn(s){let e=await se(ke.join(s,Of))??{},t=new Set(Array.isArray(e.carry)?e.carry:[]),n=await He.readFile(ke.join(s,Ff),"utf8").catch(()=>{});if(n!==void 0)for(let o of n.split(`
116
- `)){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 Hr(s,e,t){let n=[],r=[],o=ke.resolve(s),i=ke.resolve(e);for(let a of t){let d=ke.resolve(o,a),c=ke.resolve(i,a);if(!d.startsWith(o+ke.sep)||!c.startsWith(i+ke.sep)){r.push(a);continue}if(await He.access(c).then(()=>!0).catch(()=>!1)){r.push(a);continue}let l=await He.stat(d).catch(()=>{});if(l===void 0){r.push(a);continue}try{await He.mkdir(ke.dirname(c),{recursive:!0}),await He.cp(d,c,{recursive:l.isDirectory()}),n.push(a)}catch{r.push(a)}}return{copied:n,skipped:r}}async function qn(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??Nf)*1e3;return new Promise(r=>{let o=$f("/bin/sh",["-c",s],{cwd:e.workspacePath,timeout:n,maxBuffer:8388608,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)})}Q();Le();import*as We from"fs/promises";import{z as je}from"zod";var Hf=je.object({version:je.literal(1),agentId:je.string(),upstreamSessionId:je.string(),deletedAt:je.string(),upstreamUpdatedAt:je.string().optional(),cwd:je.string().optional(),title:je.string().optional(),reason:je.enum(["user","expired"]).optional(),interactive:je.boolean().optional()}),zn=class{async add(e){let t={version:1,...e};await ye(C.tombstoneFile(e.agentId,e.upstreamSessionId),t,{mode:384})}async has(e,t){try{return await We.access(C.tombstoneFile(e,t)),!0}catch{return!1}}async read(e,t){let n=C.tombstoneFile(e,t),r=await se(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 Hf.parse(r)}catch{return{version:1,agentId:e,upstreamSessionId:t,deletedAt:new Date(0).toISOString()}}}async remove(e,t){try{await We.unlink(C.tombstoneFile(e,t))}catch(n){if(n.code!=="ENOENT")throw n}try{await We.rmdir(C.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 We.readdir(C.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 We.readdir(C.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 ka(s,e){return s.reason==="user"||e===void 0?!1:s.upstreamUpdatedAt===void 0?!0:e>s.upstreamUpdatedAt}import*as Ma from"fs/promises";import{customAlphabet as zf}from"nanoid";import{fileURLToPath as jf}from"url";import*as tn from"path";import*as Jn from"fs";function Df(){try{let s=tn.dirname(jf(import.meta.url));for(let e=0;e<8;e+=1){let t=tn.join(s,"package.json");if(Jn.existsSync(t)){let r=JSON.parse(Jn.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=tn.dirname(s);if(n===s)break;s=n}}catch{}return"0.0.0"}var ue=Df(),Vn="hydra-acp-cat";var Uf=12e4;async function ba(s,e,t){let n=s.timeoutMs??Uf,r,o,i=!1;try{let a=(async()=>{r=Ke.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 m=Bf(c);if(m.size===0||m.has(s.modelId)){let g=r.connection;try{await Qe({request:(h,w)=>g.request(h,w),sessionId:u,modelId:s.modelId,verb:wt(c),logger:s.logger})}catch(h){s.logger?.warn(`synopsis: agent ${s.agentId} rejected model change to ${JSON.stringify(s.modelId)}: ${h.message}; continuing on default`)}}else s.logger?.warn(`synopsis: model ${JSON.stringify(s.modelId)} not advertised by agent ${s.agentId} (have [${[...m].join(", ")}]); continuing on default`)}let l=[];r.connection.onNotification("session/update",m=>{let g=Lf(m);g.length>0&&l.push(g)}),await r.connection.request("session/prompt",{sessionId:u,prompt:[{type:"text",text:e}]});let p=l.join(""),f=t(p);if(!f){let m=JSON.stringify(p.slice(0,200));s.logger?.warn(`synopsis: agent ${s.agentId} reply did not parse (replyLen=${p.length} preview=${m})`);let g=p.slice(0,120).replace(/\s+/g," ").trim();s.onFailure?.(`agent ${s.agentId} returned unparseable JSON (${p.length} chars): ${g}${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 Gn(s){let e=St(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}
115
+ `)){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||!Mf(e,c))continue;let u=Y.join(e,c),[l,p,f]=await Promise.all([this.currentState(u),H(["rev-parse",`HEAD:${c}`],e,B),H(["status","--porcelain","--untracked-files=all"],u,B)]);if(l===void 0)continue;let m=p.ok?p.stdout.trim():"";n.push({relPath:c,actual:l,...m.length>0?{recorded:m}:{},changedPaths:f.ok?Or(f.stdout).map(g=>g.path):[]})}return n}async captureNested(e,t){let n=[];for(let r of t){if(!Tr(r))continue;if(r.changedPaths.length===0){n.push(r);continue}let o=Y.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=Y.join(e,i.relPath),d=Y.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(h=>h.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 m=Y.join(e,c),g=Y.join(t,c);if(p&&u.recorded!==void 0){let h=await this.alignNested(m,g,u.recorded);if(h!==void 0){o.push({path:c,reason:h});continue}}if(l?.delta!==void 0){let h=await this.applyDelta(m,l.delta);if(!h.ok){o.push({path:c,reason:h.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,B)).ok&&!(await H(["fetch","--no-tags",t,n],e,Dn)).ok)return`could not transfer ${n.slice(0,8)} from the other copy`;if(!(await H(["checkout","--detach",n],e,re)).ok)return`could not move to ${n.slice(0,8)}`}};function Mf(s,e){if(Y.isAbsolute(e))return!1;let t=Y.resolve(s),n=Y.resolve(t,e);return n!==t&&n.startsWith(t+Y.sep)}var _f=Ln,$f=new Map([[Ln,new Un],[Mr,new jn]]);function Z(s){return $f.get(s??_f)}var Bn="refs/hydra";function Zt(s){let e=`${Bn}/workspaces/${s}`;return{autosave:`${e}/autosave`,start:`${e}/start`,baseline:`${e}/baseline`}}function Fr(s){return`${Bn}/landing/${s}`}function ya(s){return`${Bn}/sync/${s}`}function wa(s,e){return`${Bn}/retired/${s}-${e.slice(0,12)}`}function ka(s){let e=Zt(s);return[e.autosave,e.start,e.baseline]}async function Nr(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 it(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 en(s){s.capture.retainedRef===void 0||s.provider===void 0||await s.provider.dropSnapshotRef({...s.ws,path:s.source},s.capture.retainedRef).catch(()=>{})}Le();import{execFile as Of}from"child_process";import*as He from"fs/promises";import*as ke from"path";var Ff=".hydra/worktree.json",Nf=".worktreeinclude",Hf=120;async function Wn(s){let e=await se(ke.join(s,Ff))??{},t=new Set(Array.isArray(e.carry)?e.carry:[]),n=await He.readFile(ke.join(s,Nf),"utf8").catch(()=>{});if(n!==void 0)for(let o of n.split(`
116
+ `)){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 Hr(s,e,t){let n=[],r=[],o=ke.resolve(s),i=ke.resolve(e);for(let a of t){let d=ke.resolve(o,a),c=ke.resolve(i,a);if(!d.startsWith(o+ke.sep)||!c.startsWith(i+ke.sep)){r.push(a);continue}if(await He.access(c).then(()=>!0).catch(()=>!1)){r.push(a);continue}let l=await He.stat(d).catch(()=>{});if(l===void 0){r.push(a);continue}try{await He.mkdir(ke.dirname(c),{recursive:!0}),await He.cp(d,c,{recursive:l.isDirectory()}),n.push(a)}catch{r.push(a)}}return{copied:n,skipped:r}}async function qn(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??Hf)*1e3;return new Promise(r=>{let o=Of("/bin/sh",["-c",s],{cwd:e.workspacePath,timeout:n,maxBuffer:8388608,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)})}Q();Le();import*as We from"fs/promises";import{z as je}from"zod";var jf=je.object({version:je.literal(1),agentId:je.string(),upstreamSessionId:je.string(),deletedAt:je.string(),upstreamUpdatedAt:je.string().optional(),cwd:je.string().optional(),title:je.string().optional(),reason:je.enum(["user","expired"]).optional(),interactive:je.boolean().optional()}),zn=class{async add(e){let t={version:1,...e};await ye(C.tombstoneFile(e.agentId,e.upstreamSessionId),t,{mode:384})}async has(e,t){try{return await We.access(C.tombstoneFile(e,t)),!0}catch{return!1}}async read(e,t){let n=C.tombstoneFile(e,t),r=await se(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 jf.parse(r)}catch{return{version:1,agentId:e,upstreamSessionId:t,deletedAt:new Date(0).toISOString()}}}async remove(e,t){try{await We.unlink(C.tombstoneFile(e,t))}catch(n){if(n.code!=="ENOENT")throw n}try{await We.rmdir(C.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 We.readdir(C.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 We.readdir(C.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 va(s,e){return s.reason==="user"||e===void 0?!1:s.upstreamUpdatedAt===void 0?!0:e>s.upstreamUpdatedAt}import*as _a from"fs/promises";import{customAlphabet as Jf}from"nanoid";import{fileURLToPath as Df}from"url";import*as tn from"path";import*as Jn from"fs";function Uf(){try{let s=tn.dirname(Df(import.meta.url));for(let e=0;e<8;e+=1){let t=tn.join(s,"package.json");if(Jn.existsSync(t)){let r=JSON.parse(Jn.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=tn.dirname(s);if(n===s)break;s=n}}catch{}return"0.0.0"}var ue=Uf(),Vn="hydra-acp-cat";var Lf=12e4;async function Sa(s,e,t){let n=s.timeoutMs??Lf,r,o,i=!1;try{let a=(async()=>{r=Ke.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 m=Wf(c);if(m.size===0||m.has(s.modelId)){let g=r.connection;try{await Qe({request:(h,w)=>g.request(h,w),sessionId:u,modelId:s.modelId,verb:wt(c),logger:s.logger})}catch(h){s.logger?.warn(`synopsis: agent ${s.agentId} rejected model change to ${JSON.stringify(s.modelId)}: ${h.message}; continuing on default`)}}else s.logger?.warn(`synopsis: model ${JSON.stringify(s.modelId)} not advertised by agent ${s.agentId} (have [${[...m].join(", ")}]); continuing on default`)}let l=[];r.connection.onNotification("session/update",m=>{let g=Bf(m);g.length>0&&l.push(g)}),await r.connection.request("session/prompt",{sessionId:u,prompt:[{type:"text",text:e}]});let p=l.join(""),f=t(p);if(!f){let m=JSON.stringify(p.slice(0,200));s.logger?.warn(`synopsis: agent ${s.agentId} reply did not parse (replyLen=${p.length} preview=${m})`);let g=p.slice(0,120).replace(/\s+/g," ").trim();s.onFailure?.(`agent ${s.agentId} returned unparseable JSON (${p.length} chars): ${g}${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 Gn(s){let e=St(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}
117
117
 
118
118
  ${e}
119
119
 
120
120
  ${br}`:`${t}
121
121
 
122
- ${br}`;return ba(s,n,oa)}async function Sa(s){let e=St(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}
122
+ ${br}`;return Sa(s,n,ia)}async function Ia(s){let e=St(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}
123
123
 
124
124
  ${e}
125
125
 
126
126
  ${Sr}`:`${t}
127
127
 
128
- ${Sr}`;return ba(s,n,ia)}function Lf(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 Bf(s){let e=new Set;va(e,s.availableModels);let t=s.models;return t&&typeof t=="object"&&!Array.isArray(t)&&va(e,t.availableModels),e}function va(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)}}}function Wf(s){let e=new Map;for(let t of xa(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 Ca(s){return Wf(s).map(e=>e.name)}function qf(s){let e=new Map;for(let t of xa(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 Ra(s){return qf(s).map(e=>e.path)}function xa(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:`__synth_${t++}`,c=e.get(d);c===void 0?(c={toolName:Ia(o),paths:new Set},e.set(d,c)):c.toolName=Ia(o);for(let u of Aa(o.rawInput,o.locations))c.paths.add(u);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 Aa(o.rawInput,o.locations))a.paths.add(d)}return e}function Ia(s){return typeof s.name=="string"&&s.name.length>0?s.name:typeof s.title=="string"&&s.title.length>0?s.title:"(unnamed)"}function Aa(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 xi(e))t.add(n);return t}Q();var Jf=zf("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",12),Vf=2,Kn=class{constructor(e){this.opts=e;this.maxConcurrent=e.maxConcurrent??Vf}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 Ie(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=C.sessionDir(e);if(await Ma.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 m=this.opts.compactionMaxIterations??3,g=0,h=a??0,w,k=0,y,b=Date.now(),I=Jf(),v={targetAgentId:r},R=E=>this.opts.onCompactionStateChange?.(e,{runId:I,...E},v)??Promise.resolve(),x=E=>{this.opts.broadcastHydraCompaction?.(e,E,v)};await R({status:"requested",requestedAt:b}),x({sessionUpdate:"_hydra_compaction",phase:"started",requestedAt:b});try{do{g++,this.opts.logger?.info(`synopsis: compaction iteration ${g} sessionId=${e} historyLen=${i.length} watermark=${h}`);let E=await this.opts.histories.load(e,{maxEntries:1/0});if(E.length===h)break;let O=await Sa({agentId:d,cwd:f,plan:u,history:E,modelId:p,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs,onWorkerSpawned:(j,W)=>{R({status:"running",requestedAt:b,iter:g,worker:{upstreamSessionId:j,pid:W??0}})},onFailure:j=>{y=j}});if(O){let j=Ea(O.synopsis,E);j&&Ta(j)&&(await this.opts.persistSynopsis(e,j,E.length),w=j,k=E.length,y=void 0,await R({status:"running",requestedAt:b,iter:g}),x({sessionUpdate:"_hydra_compaction",phase:"iteration",iter:g,historyLen:E.length}),await this.opts.onSynthesisArtifact?.(e,j,k,r,I),this.opts.logger?.info(`synopsis: persisted compaction sessionId=${e} iteration=${g} fields=${Pa(j)}`))}else this.opts.logger?.warn(`synopsis: sessionId=${e} compaction iteration ${g} returned no result`);if(h=E.length,(await this.opts.histories.load(e,{maxEntries:1/0})).length===h)break}while(g<m);if(w)this.opts.logger?.info(`synopsis: compaction converged sessionId=${e} runId=${I} watermark=${k} iterations=${g}`+(g>=m?` (hit maxIterations=${m})`:"")),x({sessionUpdate:"_hydra_compaction",phase:"converged",iter:g,summarizedThroughEntry:k});else{g>0&&this.opts.logger?.warn(`synopsis: compaction hit maxIterations=${m} without producing artifact sessionId=${e}: ${y??"no reason captured"}`);let E=y??(g===0?"no new history to compact since last summary":`compaction did not produce an artifact after ${g} iteration(s)`);await R({status:"failed",requestedAt:b,iter:g,lastError:E}),x({sessionUpdate:"_hydra_compaction",phase:"failed",error:E}),r&&await this.opts.onSynthesisUnavailable?.(e,r,E)}}catch(E){let O=E instanceof Error?E.message:String(E);if(this.opts.logger?.warn(`synopsis: compaction threw for sessionId=${e}: ${O}`),await R({status:"failed",requestedAt:b,iter:g,lastError:O}),this.opts.broadcastHydraCompaction?.(e,{sessionUpdate:"_hydra_compaction",phase:"failed",error:O},{targetAgentId:r}),r)try{await this.opts.onSynthesisUnavailable?.(e,r,O)}catch{}}}else{let m=await Gn({agentId:d,cwd:f,plan:u,history:i,modelId:p,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs});if(!m){this.opts.logger?.warn(`synopsis: sessionId=${e} no parseable result; not persisting`);return}let g=Ea(m.synopsis,i);g&&Ta(g)?(await this.opts.persistSynopsis(e,g,i.length),m.title&&await this.opts.persistTitle(e,m.title),this.opts.logger?.info(`synopsis: persisted sessionId=${e} title=${JSON.stringify(!!m.title)} fields=${Pa(g)}`)):m.title&&(await this.opts.persistTitle(e,m.title),this.opts.logger?.info(`synopsis: persisted title only sessionId=${e}`))}}catch(o){this.opts.logger?.warn(`synopsis: sessionId=${e} failed: ${o.message}`)}}};function Ea(s,e){let t=Ra(e),n=Ca(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 Ta(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 Pa(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(",")}]`}Q();import*as G from"fs/promises";import{createReadStream as ep}from"fs";import{createGunzip as tp,gzip as np,gunzip as sp}from"zlib";import{createInterface as rp}from"readline";import{promisify as Ha}from"util";function _a(s){return s==="summary"?"summary":"inline"}var jr=256,Gf=["totalMatches","totalFiles","referenceCount","truncated","exitCode"],Kf=["content","stdout","stderr"];function $a(s,e){return e!=="summary"?s:s.map(Qf)}function Qf(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(Oa));let i=r.rawOutput;if(i&&typeof i=="object"&&!Array.isArray(i)){let a=i,d={};a.error!==void 0&&(d.error=Qn(a.error)),a.metadata!==void 0&&(d.metadata=a.metadata);for(let c of Gf)a[c]!==void 0&&(d[c]=a[c]);for(let c of Kf)typeof a[c]=="string"&&(d[c]=Qn(a[c]));o.rawOutput=d}return{...s,params:{...t,update:o}}}function Yf(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&s.type==="diff"}function Oa(s){if(Yf(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=Qn(e.text)),typeof e.content=="string"?t.content=Qn(e.content):e.content&&typeof e.content=="object"&&(t.content=Oa(e.content)),t}function Qn(s){if(typeof s=="string"&&s.length>jr){let e=s.length-jr;return`${s.slice(0,jr)}\u2026[+${e} chars omitted from summary export]`}return s}var Xf=2048;function Fa(s){let e=new Set,t=n=>{if(Na(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 Na(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&typeof s.__hydraBlob=="string"}function Zf(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 Lr(s,e){if(!Zf(s))return s;let t=s.params,n=t.update,r=await Dr(n,e);return{...s,params:{...t,update:r}}}async function Dr(s,e){if(typeof s=="string"){if(s.length<=Xf)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 Dr(n,e));return t}if(s&&typeof s=="object"){let t={};for(let[n,r]of Object.entries(s))t[n]=await Dr(r,e);return t}return s}async function Br(s,e){let t=s.params;if(!t||typeof t!="object"||Array.isArray(t))return s;let n=await Ur(t,e);return n===t?s:{...s,params:n}}async function Ur(s,e){if(Na(s))return await e(s.__hydraBlob)??"";if(Array.isArray(s)){let t=!1,n=[];for(let r of s){let o=await Ur(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 Ur(o,e);i!==o&&(t=!0),n[r]=i}return t?n:s}return s}var op=Ha(np),ip=Ha(sp),ap=/^history\.jsonl\.(\d+)(\.gz)?$/,Ee=/^[A-Za-z0-9_-]+$/,dp=1e3,cp=1e7,up=10,Yn=class{writeQueues=new Map;maxEntries;archiveMaxBytes;archiveTiers;nextArchiveIndex=new Map;archiveLineCounts=new Map;constructor(e={}){this.maxEntries=e.maxEntries??dp,this.archiveMaxBytes=e.archiveMaxBytes??cp,this.archiveTiers=e.archiveTiers??up}async append(e,t){if(Ee.test(e))return this.enqueue(e,async()=>{await G.mkdir(C.sessionDir(e),{recursive:!0});let n=await Lr(t,o=>Ls(e,o)),r=JSON.stringify(n)+`
128
+ ${Sr}`;return Sa(s,n,aa)}function Bf(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 Wf(s){let e=new Set;ba(e,s.availableModels);let t=s.models;return t&&typeof t=="object"&&!Array.isArray(t)&&ba(e,t.availableModels),e}function ba(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)}}}function qf(s){let e=new Map;for(let t of Ea(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 Ra(s){return qf(s).map(e=>e.name)}function zf(s){let e=new Map;for(let t of Ea(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 xa(s){return zf(s).map(e=>e.path)}function Ea(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:`__synth_${t++}`,c=e.get(d);c===void 0?(c={toolName:Aa(o),paths:new Set},e.set(d,c)):c.toolName=Aa(o);for(let u of Ca(o.rawInput,o.locations))c.paths.add(u);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 Ca(o.rawInput,o.locations))a.paths.add(d)}return e}function Aa(s){return typeof s.name=="string"&&s.name.length>0?s.name:typeof s.title=="string"&&s.title.length>0?s.title:"(unnamed)"}function Ca(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 Ei(e))t.add(n);return t}Q();var Vf=Jf("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",12),Gf=2,Kn=class{constructor(e){this.opts=e;this.maxConcurrent=e.maxConcurrent??Gf}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 Ie(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=C.sessionDir(e);if(await _a.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 m=this.opts.compactionMaxIterations??3,g=0,h=a??0,w,k=0,y,b=Date.now(),I=Vf(),v={targetAgentId:r},R=E=>this.opts.onCompactionStateChange?.(e,{runId:I,...E},v)??Promise.resolve(),x=E=>{this.opts.broadcastHydraCompaction?.(e,E,v)};await R({status:"requested",requestedAt:b}),x({sessionUpdate:"_hydra_compaction",phase:"started",requestedAt:b});try{do{g++,this.opts.logger?.info(`synopsis: compaction iteration ${g} sessionId=${e} historyLen=${i.length} watermark=${h}`);let E=await this.opts.histories.load(e,{maxEntries:1/0});if(E.length===h)break;let O=await Ia({agentId:d,cwd:f,plan:u,history:E,modelId:p,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs,onWorkerSpawned:(j,W)=>{R({status:"running",requestedAt:b,iter:g,worker:{upstreamSessionId:j,pid:W??0}})},onFailure:j=>{y=j}});if(O){let j=Ta(O.synopsis,E);j&&Pa(j)&&(await this.opts.persistSynopsis(e,j,E.length),w=j,k=E.length,y=void 0,await R({status:"running",requestedAt:b,iter:g}),x({sessionUpdate:"_hydra_compaction",phase:"iteration",iter:g,historyLen:E.length}),await this.opts.onSynthesisArtifact?.(e,j,k,r,I),this.opts.logger?.info(`synopsis: persisted compaction sessionId=${e} iteration=${g} fields=${Ma(j)}`))}else this.opts.logger?.warn(`synopsis: sessionId=${e} compaction iteration ${g} returned no result`);if(h=E.length,(await this.opts.histories.load(e,{maxEntries:1/0})).length===h)break}while(g<m);if(w)this.opts.logger?.info(`synopsis: compaction converged sessionId=${e} runId=${I} watermark=${k} iterations=${g}`+(g>=m?` (hit maxIterations=${m})`:"")),x({sessionUpdate:"_hydra_compaction",phase:"converged",iter:g,summarizedThroughEntry:k});else{g>0&&this.opts.logger?.warn(`synopsis: compaction hit maxIterations=${m} without producing artifact sessionId=${e}: ${y??"no reason captured"}`);let E=y??(g===0?"no new history to compact since last summary":`compaction did not produce an artifact after ${g} iteration(s)`);await R({status:"failed",requestedAt:b,iter:g,lastError:E}),x({sessionUpdate:"_hydra_compaction",phase:"failed",error:E}),r&&await this.opts.onSynthesisUnavailable?.(e,r,E)}}catch(E){let O=E instanceof Error?E.message:String(E);if(this.opts.logger?.warn(`synopsis: compaction threw for sessionId=${e}: ${O}`),await R({status:"failed",requestedAt:b,iter:g,lastError:O}),this.opts.broadcastHydraCompaction?.(e,{sessionUpdate:"_hydra_compaction",phase:"failed",error:O},{targetAgentId:r}),r)try{await this.opts.onSynthesisUnavailable?.(e,r,O)}catch{}}}else{let m=await Gn({agentId:d,cwd:f,plan:u,history:i,modelId:p,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs});if(!m){this.opts.logger?.warn(`synopsis: sessionId=${e} no parseable result; not persisting`);return}let g=Ta(m.synopsis,i);g&&Pa(g)?(await this.opts.persistSynopsis(e,g,i.length),m.title&&await this.opts.persistTitle(e,m.title),this.opts.logger?.info(`synopsis: persisted sessionId=${e} title=${JSON.stringify(!!m.title)} fields=${Ma(g)}`)):m.title&&(await this.opts.persistTitle(e,m.title),this.opts.logger?.info(`synopsis: persisted title only sessionId=${e}`))}}catch(o){this.opts.logger?.warn(`synopsis: sessionId=${e} failed: ${o.message}`)}}};function Ta(s,e){let t=xa(e),n=Ra(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 Pa(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 Ma(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(",")}]`}Q();import*as G from"fs/promises";import{createReadStream as tp}from"fs";import{createGunzip as np,gzip as sp,gunzip as rp}from"zlib";import{createInterface as op}from"readline";import{promisify as ja}from"util";function $a(s){return s==="summary"?"summary":"inline"}var jr=256,Kf=["totalMatches","totalFiles","referenceCount","truncated","exitCode"],Qf=["content","stdout","stderr"];function Oa(s,e){return e!=="summary"?s:s.map(Yf)}function Yf(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(Fa));let i=r.rawOutput;if(i&&typeof i=="object"&&!Array.isArray(i)){let a=i,d={};a.error!==void 0&&(d.error=Qn(a.error)),a.metadata!==void 0&&(d.metadata=a.metadata);for(let c of Kf)a[c]!==void 0&&(d[c]=a[c]);for(let c of Qf)typeof a[c]=="string"&&(d[c]=Qn(a[c]));o.rawOutput=d}return{...s,params:{...t,update:o}}}function Xf(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&s.type==="diff"}function Fa(s){if(Xf(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=Qn(e.text)),typeof e.content=="string"?t.content=Qn(e.content):e.content&&typeof e.content=="object"&&(t.content=Fa(e.content)),t}function Qn(s){if(typeof s=="string"&&s.length>jr){let e=s.length-jr;return`${s.slice(0,jr)}\u2026[+${e} chars omitted from summary export]`}return s}var Zf=2048;function Na(s){let e=new Set,t=n=>{if(Ha(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 Ha(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&typeof s.__hydraBlob=="string"}function ep(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 Lr(s,e){if(!ep(s))return s;let t=s.params,n=t.update,r=await Dr(n,e);return{...s,params:{...t,update:r}}}async function Dr(s,e){if(typeof s=="string"){if(s.length<=Zf)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 Dr(n,e));return t}if(s&&typeof s=="object"){let t={};for(let[n,r]of Object.entries(s))t[n]=await Dr(r,e);return t}return s}async function Br(s,e){let t=s.params;if(!t||typeof t!="object"||Array.isArray(t))return s;let n=await Ur(t,e);return n===t?s:{...s,params:n}}async function Ur(s,e){if(Ha(s))return await e(s.__hydraBlob)??"";if(Array.isArray(s)){let t=!1,n=[];for(let r of s){let o=await Ur(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 Ur(o,e);i!==o&&(t=!0),n[r]=i}return t?n:s}return s}var ip=ja(sp),ap=ja(rp),dp=/^history\.jsonl\.(\d+)(\.gz)?$/,Ee=/^[A-Za-z0-9_-]+$/,cp=1e3,up=1e7,lp=10,Yn=class{writeQueues=new Map;maxEntries;archiveMaxBytes;archiveTiers;nextArchiveIndex=new Map;archiveLineCounts=new Map;constructor(e={}){this.maxEntries=e.maxEntries??cp,this.archiveMaxBytes=e.archiveMaxBytes??up,this.archiveTiers=e.archiveTiers??lp}async append(e,t){if(Ee.test(e))return this.enqueue(e,async()=>{await G.mkdir(C.sessionDir(e),{recursive:!0});let n=await Lr(t,o=>Ls(e,o)),r=JSON.stringify(n)+`
129
129
  `;await G.appendFile(C.historyFile(e),r,{encoding:"utf8",mode:384})})}async rewrite(e,t){if(Ee.test(e))return this.enqueue(e,async()=>{await G.mkdir(C.sessionDir(e),{recursive:!0});let n=[];for(let o of t)n.push(await Lr(o,i=>Ls(e,i)));let r=n.length===0?"":n.map(o=>JSON.stringify(o)).join(`
130
130
  `)+`
131
131
  `;await G.writeFile(C.historyFile(e),r,{encoding:"utf8",mode:384})})}async compact(e,t){if(Ee.test(e))return this.enqueue(e,async()=>{let n;try{n=await G.readFile(C.historyFile(e),"utf8")}catch(a){if(a.code==="ENOENT")return;throw a}let r=n.split(`
@@ -133,20 +133,20 @@ ${Sr}`;return ba(s,n,ia)}function Lf(s){if(!s||typeof s!="object")return"";let e
133
133
  `)+`
134
134
  `,{encoding:"utf8",mode:384})})}async spillToArchive(e,t){let n=t.join(`
135
135
  `)+`
136
- `,r=await this.resolveNextArchiveIndex(e);await this.enforceArchiveTierCap(e,r);let o=C.historyArchiveFile(e,r);await G.mkdir(C.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=C.historyArchiveFile(e,t),r;try{r=await G.readFile(n)}catch(i){if(i.code==="ENOENT")return;throw i}let o=await op(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=C.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=C.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(C.sessionDir(e))}catch(r){if(r.code==="ENOENT")return[];throw r}let n=new Set;for(let r of t){let o=ap.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(!Ee.test(e))return[];let t=await this.listArchiveIndices(e),n=[];for(let r of t){let o=C.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(!Ee.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 ip(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(`
137
- `)){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})}}return r}async*streamFile(e){let t;try{t=ep(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(tp()):t,o=rp({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})}}finally{o.close(),t.destroy()}}async getArchiveLineCounts(e){if(!Ee.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 hydrateEntry(e,t,n){return Br(t,async r=>{let o=n.get(r);if(o!==void 0)return o;let i=await Bt(e,r);return n.set(r,i),i})}async*iterRecallNewestFirst(e){if(!Ee.test(e))return;let t=this.writeQueues.get(e);t&&await t;let n=await this.getArchiveLineCounts(e),r=0;for(let c of n)r+=c.lineCount;let o=new Map,i=[];for await(let c of this.streamFile(C.historyFile(e)))i.push(c);for(let c=i.length-1;c>=0;c--){let u=await this.hydrateEntry(e,i[c],o);yield{entryId:r+c,entry:u}}let a=new Array(n.length),d=0;for(let c=0;c<n.length;c++)a[c]=d,d+=n[c].lineCount;for(let c=n.length-1;c>=0;c--){let u=n[c],l=[];for await(let f of this.streamFile(u.path))l.push(f);let p=a[c];for(let f=l.length-1;f>=0;f--){let m=await this.hydrateEntry(e,l[f],o);yield{entryId:p+f,entry:m}}}}async rangeSlice(e,t,n){if(!Ee.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 m of this.streamFile(u.path)){let g=l+f;if(f+=1,g<t)continue;if(g>n)break;let h=await this.hydrateEntry(e,m,d);a.push({entryId:g,entry:h})}}if(n>=i){let u=Math.max(t-i,0),l=n-i,p=0;for await(let f of this.streamFile(C.historyFile(e))){if(p>l)break;if(p>=u){let m=await this.hydrateEntry(e,f,d);a.push({entryId:i+p,entry:m})}p+=1}}return a}async getRecallTotalCount(e){if(!Ee.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(C.historyFile(e)))r+=1;return n+r}async load(e,t={}){if(!Ee.test(e))return[];let n=(t.tools??"inline")==="inline",r=this.writeQueues.get(e);r&&await r;let o;try{o=await G.readFile(C.historyFile(e),"utf8")}catch(p){if(p.code==="ENOENT")return[];throw p}let i=[];for(let p of o.split(`
138
- `)){if(p.length===0)continue;let f;try{f=JSON.parse(p)}catch{continue}if(!f||typeof f!="object"||Array.isArray(f))continue;let m=f;typeof m.method=="string"&&typeof m.recordedAt=="number"&&i.push({method:m.method,params:m.params,recordedAt:m.recordedAt})}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 m=await Bt(e,p);return c.set(p,m),m},l=[];for(let p of d)l.push(await Br(p,u));return l}async flushAll(){let e=[...this.writeQueues.values()];e.length!==0&&await Promise.allSettled(e)}async delete(e){if(Ee.test(e))return this.enqueue(e,async()=>{try{await G.unlink(C.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 Bo(e);try{await G.rmdir(C.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}};Q();import{promises as ja}from"fs";import*as Da from"path";async function Ua(s,e){await ja.mkdir(Da.dirname(s),{recursive:!0});let t=e.map(n=>JSON.stringify(n));await ja.writeFile(s,t.length>0?t.join(`
136
+ `,r=await this.resolveNextArchiveIndex(e);await this.enforceArchiveTierCap(e,r);let o=C.historyArchiveFile(e,r);await G.mkdir(C.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=C.historyArchiveFile(e,t),r;try{r=await G.readFile(n)}catch(i){if(i.code==="ENOENT")return;throw i}let o=await ip(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=C.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=C.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(C.sessionDir(e))}catch(r){if(r.code==="ENOENT")return[];throw r}let n=new Set;for(let r of t){let o=dp.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(!Ee.test(e))return[];let t=await this.listArchiveIndices(e),n=[];for(let r of t){let o=C.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(!Ee.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 ap(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(`
137
+ `)){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})}}return r}async*streamFile(e){let t;try{t=tp(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(np()):t,o=op({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})}}finally{o.close(),t.destroy()}}async getArchiveLineCounts(e){if(!Ee.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 hydrateEntry(e,t,n){return Br(t,async r=>{let o=n.get(r);if(o!==void 0)return o;let i=await Bt(e,r);return n.set(r,i),i})}async*iterRecallNewestFirst(e){if(!Ee.test(e))return;let t=this.writeQueues.get(e);t&&await t;let n=await this.getArchiveLineCounts(e),r=0;for(let c of n)r+=c.lineCount;let o=new Map,i=[];for await(let c of this.streamFile(C.historyFile(e)))i.push(c);for(let c=i.length-1;c>=0;c--){let u=await this.hydrateEntry(e,i[c],o);yield{entryId:r+c,entry:u}}let a=new Array(n.length),d=0;for(let c=0;c<n.length;c++)a[c]=d,d+=n[c].lineCount;for(let c=n.length-1;c>=0;c--){let u=n[c],l=[];for await(let f of this.streamFile(u.path))l.push(f);let p=a[c];for(let f=l.length-1;f>=0;f--){let m=await this.hydrateEntry(e,l[f],o);yield{entryId:p+f,entry:m}}}}async rangeSlice(e,t,n){if(!Ee.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 m of this.streamFile(u.path)){let g=l+f;if(f+=1,g<t)continue;if(g>n)break;let h=await this.hydrateEntry(e,m,d);a.push({entryId:g,entry:h})}}if(n>=i){let u=Math.max(t-i,0),l=n-i,p=0;for await(let f of this.streamFile(C.historyFile(e))){if(p>l)break;if(p>=u){let m=await this.hydrateEntry(e,f,d);a.push({entryId:i+p,entry:m})}p+=1}}return a}async getRecallTotalCount(e){if(!Ee.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(C.historyFile(e)))r+=1;return n+r}async load(e,t={}){if(!Ee.test(e))return[];let n=(t.tools??"inline")==="inline",r=this.writeQueues.get(e);r&&await r;let o;try{o=await G.readFile(C.historyFile(e),"utf8")}catch(p){if(p.code==="ENOENT")return[];throw p}let i=[];for(let p of o.split(`
138
+ `)){if(p.length===0)continue;let f;try{f=JSON.parse(p)}catch{continue}if(!f||typeof f!="object"||Array.isArray(f))continue;let m=f;typeof m.method=="string"&&typeof m.recordedAt=="number"&&i.push({method:m.method,params:m.params,recordedAt:m.recordedAt})}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 m=await Bt(e,p);return c.set(p,m),m},l=[];for(let p of d)l.push(await Br(p,u));return l}async flushAll(){let e=[...this.writeQueues.values()];e.length!==0&&await Promise.allSettled(e)}async delete(e){if(Ee.test(e))return this.enqueue(e,async()=>{try{await G.unlink(C.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 Wo(e);try{await G.rmdir(C.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}};Q();import{promises as Da}from"fs";import*as Ua from"path";async function La(s,e){await Da.mkdir(Ua.dirname(s),{recursive:!0});let t=e.map(n=>JSON.stringify(n));await Da.writeFile(s,t.length>0?t.join(`
139
139
  `)+`
140
- `:"")}import{z}from"zod";var lp=z.object({method:z.string(),params:z.unknown(),recordedAt:z.number()}),fp=z.object({sessionId:z.string(),lineageId:z.string(),upstreamSessionId:z.string().optional(),agentId:z.string(),cwd:z.string(),title:z.string().optional(),synopsis:Qt.optional(),summarizedThroughEntry:z.number().int().nonnegative().optional(),currentModel:z.string().optional(),currentMode:z.string().optional(),currentUsage:Rr.optional(),agentCommands:z.array(Ar).optional(),agentModes:z.array(Cr).optional(),interactive:z.boolean().optional(),originatingClient:xr.optional(),priority:z.number().int().nonnegative().optional(),createdAt:z.string(),updatedAt:z.string()}),pp=z.object({version:z.literal(1),exportedAt:z.string(),exportedFrom:z.object({hydraVersion:z.string(),machine:z.string(),hydraHost:z.string().optional()}),session:fp,history:z.array(lp),promptHistory:z.array(z.string()).optional(),toolBlobs:z.record(z.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 La(s){return pp.parse(s)}function Wr(s){if(s&&!(s.costAmount===void 0&&s.cumulativeCost===void 0))return(s.cumulativeCost??0)+(s.costAmount??0)}function sn(s){if(!s)return;let e={};s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size);let t=Wr(s);return t&&(e.costAmount=t),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),e}var Ba=900*1e3,mp=12,hp="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Et=gp(hp,16),Zn=class s{constructor(e,t,n,r={}){this.registry=e;this.spawner=t??(a=>Ke.spawn(a)),this.store=n??new On,this.tombstones=r.tombstones??new zn,this.sessionHistoryMaxEntries=r.sessionHistoryMaxEntries??1e3,this.histories=new Yn({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.defaultModels=r.defaultModels??{},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 Kn({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;defaultModels;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?mp: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`)}}async refreshAgentCatalog(){try{let{agents:e}=await mt(this.registry);this.agentCatalog=e.map(t=>({id:t.id,name:t.name,...t.description!==void 0?{description:t.description}:{}}))}catch{}}async resolveWorkspace(e){let t=e.workspace;if(t===void 0)return{cwd:e.cwd};let n=Z(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}}let r=t.label??`s-${Et().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 Wn(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 Hr(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 qn(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}:{}}}async create(e){let t=await this.registry.getAgent(e.agentId);t&&t.id!==e.agentId&&(e={...e,agentId:t.id});let n=`${Ne}${Et()}`,r=await this.resolveWorkspace(e),o=r.cwd,i=await this.bootstrapAgent({agentId:e.agentId,cwd:o,agentArgs:e.agentArgs,mcpServers:e.mcpServers,model:e.model,onInstallProgress:e.onInstallProgress,forwardedEnv:e.forwardedEnv,selfSessionId:n});if(e.transformChain&&e.transformChain.length>0){let d={...i.agentCapabilities??{}};for(let c of e.transformChain)if(c.intercepts.has("agent:initialize"))try{let u=await c.connection.request("hydra-acp/transformer/message",{token:`t_${Et()}`,phase:"response",method:"initialize",direction:"agent\u2192daemon",sessionId:"(pre-session)",envelope:d});u.action==="stop"&&u.payload&&(d=u.payload)}catch{}i.agentCapabilities=d}let a=new It({sessionId:n,cwd:o,...r.workspace!==void 0?{workspace:r.workspace}:{},...r.isolationError!==void 0?{workspaceError:r.isolationError}:{},agentId:e.agentId,agent:i.agent,upstreamSessionId:i.upstreamSessionId,agentMeta:i.agentMeta,agentCapabilities:i.agentCapabilities,...i.modelVerb?{modelVerb:i.modelVerb}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,orphanTimeoutMs:this.orphanTimeoutMs,idleEventTimeoutMs:this.idleEventTimeoutMs,logger:this.logger,spawnReplacementAgent:d=>this.bootstrapAgent({...d,mcpServers:d.mcpServers??[],selfSessionId:n}),loadExistingAgentSession:(d,c)=>this.bootstrapAgentLoad(d,{...c,mcpServers:c.mcpServers??[],selfSessionId:n}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:i.initialModel,currentMode:i.initialMode,agentModes:i.initialModes,agentModels:i.initialModels,agentConfigOptions:i.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(a.sessionId),scheduleWorkspaceSnapshot:()=>this.scheduleWorkspaceSnapshot(a),scheduleCompaction:d=>this.scheduleCompaction(a.sessionId,d),resolveAgentId:async d=>(await this.registry.getAgent(d))?.id,getCompactionState:()=>this.getCompactionState(a.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(a.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(a.sessionId),uncompactHook:()=>this.performUncompact(a.sessionId),forkHook:d=>this.forkSession(a.sessionId,d??{}),workspaceHook:(d,c,u)=>this.runWorkspaceAction(a.sessionId,d,c,u),onCompactionSwapHook:d=>{this.persistRollbackBreadcrumb(a.sessionId,d).catch(()=>{})},persistWatermarkHook:d=>{this.mutateRecord(a.sessionId,{summarizedThroughEntry:d}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(a.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});if(r.workspace!==void 0){let d=Z(r.workspace.provider);d!==void 0&&d.capabilities().supports.environmentNotes&&(a.workspaceNotes=await d.environmentNotes({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}:{}}).catch(()=>[]))}return await this.attachManagerHooks(a),a}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=A.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 y=new Error(`agent ${e.agentId} not found in registry; cannot resurrect`);throw y.code=A.AgentNotInstalled,y}if(e.upstreamSessionId==="")return this.doResurrectFromImport(e);if(!await this.dirExists(e.cwd))return this.doResurrectFromImport(e);let r=await Ie(n,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),o=kn(e.hydraSessionId,e.forwardedEnv),i=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:r,...o?{extraEnv:o}:{}}),a;try{let y=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:ht,clientInfo:{name:"hydra",version:ue}});a=y.agentCapabilities,i.authMethods=on(y.authMethods),i.steeringSupported=rn(y)}catch(y){throw await i.kill().catch(()=>{}),Ye(y,i)}let d;try{let y=zr(n,{model:e.currentModel});d=await i.connection.request("session/load",{sessionId:e.upstreamSessionId,cwd:e.cwd,mcpServers:e.mcpServers??[],...y&&{_meta:y}})}catch(y){if(y&&typeof y=="object"&&y.code===A.AuthRequired)throw await i.kill().catch(()=>{}),Ye(y,i);return process.stderr.write(`session/load failed for upstream ${e.upstreamSessionId} on ${e.agentId} (${y.message}); recovering via import-reseed
140
+ `:"")}import{z}from"zod";var fp=z.object({method:z.string(),params:z.unknown(),recordedAt:z.number()}),pp=z.object({sessionId:z.string(),lineageId:z.string(),upstreamSessionId:z.string().optional(),agentId:z.string(),cwd:z.string(),title:z.string().optional(),synopsis:Qt.optional(),summarizedThroughEntry:z.number().int().nonnegative().optional(),currentModel:z.string().optional(),currentMode:z.string().optional(),currentUsage:Rr.optional(),agentCommands:z.array(Ar).optional(),agentModes:z.array(Cr).optional(),interactive:z.boolean().optional(),originatingClient:xr.optional(),priority:z.number().int().nonnegative().optional(),createdAt:z.string(),updatedAt:z.string()}),gp=z.object({version:z.literal(1),exportedAt:z.string(),exportedFrom:z.object({hydraVersion:z.string(),machine:z.string(),hydraHost:z.string().optional()}),session:pp,history:z.array(fp),promptHistory:z.array(z.string()).optional(),toolBlobs:z.record(z.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 Ba(s){return gp.parse(s)}function Wr(s){if(s&&!(s.costAmount===void 0&&s.cumulativeCost===void 0))return(s.cumulativeCost??0)+(s.costAmount??0)}function sn(s){if(!s)return;let e={};s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size);let t=Wr(s);return t&&(e.costAmount=t),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),e}var Wa=900*1e3,hp=12,yp="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Et=mp(yp,16),Zn=class s{constructor(e,t,n,r={}){this.registry=e;this.spawner=t??(a=>Ke.spawn(a)),this.store=n??new On,this.tombstones=r.tombstones??new zn,this.sessionHistoryMaxEntries=r.sessionHistoryMaxEntries??1e3,this.histories=new Yn({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.defaultModels=r.defaultModels??{},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 Kn({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;defaultModels;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?hp: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`)}}async refreshAgentCatalog(){try{let{agents:e}=await mt(this.registry);this.agentCatalog=e.map(t=>({id:t.id,name:t.name,...t.description!==void 0?{description:t.description}:{}}))}catch{}}async resolveWorkspace(e){let t=e.workspace;if(t===void 0)return{cwd:e.cwd};let n=Z(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}}let r=t.label??`s-${Et().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 Wn(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 Hr(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 qn(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}:{}}}async create(e){let t=await this.registry.getAgent(e.agentId);t&&t.id!==e.agentId&&(e={...e,agentId:t.id});let n=`${Ne}${Et()}`,r=await this.resolveWorkspace(e),o=r.cwd,i=await this.bootstrapAgent({agentId:e.agentId,cwd:o,agentArgs:e.agentArgs,mcpServers:e.mcpServers,model:e.model,onInstallProgress:e.onInstallProgress,forwardedEnv:e.forwardedEnv,selfSessionId:n});if(e.transformChain&&e.transformChain.length>0){let d={...i.agentCapabilities??{}};for(let c of e.transformChain)if(c.intercepts.has("agent:initialize"))try{let u=await c.connection.request("hydra-acp/transformer/message",{token:`t_${Et()}`,phase:"response",method:"initialize",direction:"agent\u2192daemon",sessionId:"(pre-session)",envelope:d});u.action==="stop"&&u.payload&&(d=u.payload)}catch{}i.agentCapabilities=d}let a=new It({sessionId:n,cwd:o,...r.workspace!==void 0?{workspace:r.workspace}:{},...r.isolationError!==void 0?{workspaceError:r.isolationError}:{},agentId:e.agentId,agent:i.agent,upstreamSessionId:i.upstreamSessionId,agentMeta:i.agentMeta,agentCapabilities:i.agentCapabilities,...i.modelVerb?{modelVerb:i.modelVerb}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,orphanTimeoutMs:this.orphanTimeoutMs,idleEventTimeoutMs:this.idleEventTimeoutMs,logger:this.logger,spawnReplacementAgent:d=>this.bootstrapAgent({...d,mcpServers:d.mcpServers??[],selfSessionId:n}),loadExistingAgentSession:(d,c)=>this.bootstrapAgentLoad(d,{...c,mcpServers:c.mcpServers??[],selfSessionId:n}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:i.initialModel,currentMode:i.initialMode,agentModes:i.initialModes,agentModels:i.initialModels,agentConfigOptions:i.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(a.sessionId),scheduleWorkspaceSnapshot:()=>this.scheduleWorkspaceSnapshot(a),scheduleCompaction:d=>this.scheduleCompaction(a.sessionId,d),resolveAgentId:async d=>(await this.registry.getAgent(d))?.id,getCompactionState:()=>this.getCompactionState(a.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(a.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(a.sessionId),uncompactHook:()=>this.performUncompact(a.sessionId),forkHook:d=>this.forkSession(a.sessionId,d??{}),workspaceHook:(d,c,u)=>this.runWorkspaceAction(a.sessionId,d,c,u),onCompactionSwapHook:d=>{this.persistRollbackBreadcrumb(a.sessionId,d).catch(()=>{})},persistWatermarkHook:d=>{this.mutateRecord(a.sessionId,{summarizedThroughEntry:d}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(a.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});if(r.workspace!==void 0){let d=Z(r.workspace.provider);d!==void 0&&d.capabilities().supports.environmentNotes&&(a.workspaceNotes=await d.environmentNotes({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}:{}}).catch(()=>[]))}return await this.attachManagerHooks(a),a}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=A.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 y=new Error(`agent ${e.agentId} not found in registry; cannot resurrect`);throw y.code=A.AgentNotInstalled,y}if(e.upstreamSessionId==="")return this.doResurrectFromImport(e);if(!await this.dirExists(e.cwd))return this.doResurrectFromImport(e);let r=await Ie(n,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),o=kn(e.hydraSessionId,e.forwardedEnv),i=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:r,...o?{extraEnv:o}:{}}),a;try{let y=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:ht,clientInfo:{name:"hydra",version:ue}});a=y.agentCapabilities,i.authMethods=on(y.authMethods),i.steeringSupported=rn(y)}catch(y){throw await i.kill().catch(()=>{}),Ye(y,i)}let d;try{let y=zr(n,{model:e.currentModel});d=await i.connection.request("session/load",{sessionId:e.upstreamSessionId,cwd:e.cwd,mcpServers:e.mcpServers??[],...y&&{_meta:y}})}catch(y){if(y&&typeof y=="object"&&y.code===A.AuthRequired)throw await i.kill().catch(()=>{}),Ye(y,i);return process.stderr.write(`session/load failed for upstream ${e.upstreamSessionId} on ${e.agentId} (${y.message}); recovering via import-reseed
141
141
  `),await i.kill().catch(()=>{}),this.doResurrectFromImport(e)}if(e.pendingHistorySync===!0)this.clearPendingHistorySync(e.hydraSessionId).catch(()=>{});else{let y=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain1 dropped ${y} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let c=Qr(d??{}),u=e.agentModes??Tt(Kr(d??{}));this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedMode=${JSON.stringify(e.currentMode)} agentReportedMode=${JSON.stringify(c)} advertisedModes=${JSON.stringify(u?.map(y=>y.id))}`);let l=await nt({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=Jr(d??{}),f=Tt(Gr(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(y=>y.modelId))}`),e.pendingHistorySync!==!0){let y=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain2 (post-mode-restore) dropped ${y} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let m=wt(d),g=await st({agent:i,upstreamSessionId:e.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:p,...m?{modelVerb:m}:{},logger:this.logger}),h=g.modelId,w=Tt(Xn(Vr(g.result)?g.result:d??{}));if(e.pendingHistorySync!==!0){let y=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain3 (post-model-restore) dropped ${y} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let k=new It({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,...m?{modelVerb:m}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,orphanTimeoutMs:this.orphanTimeoutMs,logger:this.logger,spawnReplacementAgent:y=>this.bootstrapAgent({...y,mcpServers:y.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),loadExistingAgentSession:(y,b)=>this.bootstrapAgentLoad(y,{...b,mcpServers:b.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:h,currentMode:l,currentUsage:e.currentUsage,reloadsUpstreamLedger:!0,agentCommands:e.agentCommands,agentModes:u,agentModels:f,agentConfigOptions:w,summarizedThroughEntry:e.summarizedThroughEntry,compactionState:e.compactionState,firstPromptSeeded:!!e.title,createdAt:e.createdAt?new Date(e.createdAt).getTime():void 0,originatingClient:e.originatingClient,interactive:e.interactive,priority:e.priority,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,attentionFlags:e.attentionFlags,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(k.sessionId),scheduleWorkspaceSnapshot:()=>this.scheduleWorkspaceSnapshot(k),scheduleCompaction:y=>this.scheduleCompaction(k.sessionId,y),resolveAgentId:async y=>(await this.registry.getAgent(y))?.id,getCompactionState:()=>this.getCompactionState(k.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(k.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(k.sessionId),uncompactHook:()=>this.performUncompact(k.sessionId),forkHook:y=>this.forkSession(k.sessionId,y??{}),workspaceHook:(y,b,I)=>this.runWorkspaceAction(k.sessionId,y,b,I),onCompactionSwapHook:y=>{this.persistRollbackBreadcrumb(k.sessionId,y).catch(()=>{})},persistWatermarkHook:y=>{this.mutateRecord(k.sessionId,{summarizedThroughEntry:y}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(k.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(k),k}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 nt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:r.initialMode,advertisedModes:o,logger:this.logger}),a=e.agentModels??r.initialModels,d=await st({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:r.initialModel,...r.modelVerb?{modelVerb:r.modelVerb}:{},logger:this.logger}),c=d.modelId,u=Vr(d.result)?Tt(Xn(d.result)):void 0;r.agent.connection.drainBuffered("session/update");let l=new It({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,createdAt:e.createdAt?new Date(e.createdAt).getTime():void 0,originatingClient:e.originatingClient,interactive:e.interactive,priority:e.priority,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,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,m)=>this.runWorkspaceAction(l.sessionId,p,f,m),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 at.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:ie(this.defaultCwd)}}async releaseWorkspace(e,t){let n=Z(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=>Be(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=Z(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,m=await i.integrationInProgress(t.path);if(f.length===0&&!m){let h=await this.syncOverDirtyTree(t,{provider:i,before:d,sourceHead:a,incoming:u});if(h!==void 0)return h}let g=f.length>0?`
142
142
  ${f.map(h=>` ${h}`).join(`
143
143
  `)}`:` (${l.reason??"the integration failed"})`;return f.length===0?{ok:!1,message:`the source could not be merged into ${_(t.path)}; nothing changed.${g}
144
144
  `+(m?"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:${g}`}):{ok:!1,message:`Synced with conflicts. ${f.length} file(s) need resolving in ${_(t.path)}:${g}
145
- 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=ha(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 b=await it({source:e.path,capture:p,provider:n});return{ok:!1,message:`Could not clear ${_(e.path)} to merge into it, so nothing was synced. ${b?"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 b=await it({source:e.path,capture:p,provider:n});return b&&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.
145
+ 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=ya(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 b=await it({source:e.path,capture:p,provider:n});return{ok:!1,message:`Could not clear ${_(e.path)} to merge into it, so nothing was synced. ${b?"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 b=await it({source:e.path,capture:p,provider:n});return b&&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.
146
146
  `+(b?`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:
147
147
  ${f}`)}}let h=await it({source:e.path,capture:p,provider:n}),w=await n.currentState(e.path),k=w===void 0?0:(await n.changedPathsBetween(e.path,r,w)).length,y=`Synced ${_(e.path)} with ${_(e.sourceCwd)}: ${i} commit(s), ${k} file(s) changed.`;return h?(await n.dropSnapshotRef(a,u).catch(()=>{}),{ok:!0,message:`${y} Your uncommitted work was set aside for the merge and restored on top.`}):{ok:!1,message:`${y}
148
148
  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:
149
- ${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=Z(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 Wn(t.sourceCwd).catch(()=>({}));if(o.preRemove!==void 0){let a=await qn(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"}`)}for(let a of wa(t.label))await e.dropSnapshotRef(r,a).catch(()=>{});let i=await e.status(r).catch(()=>({clean:!1,changedPaths:["<unknown>"],hasRecordedWork:!1}));if(i.changedPaths.length>0){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}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=Z(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=Z(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(`
149
+ ${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=Z(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 Wn(t.sourceCwd).catch(()=>({}));if(o.preRemove!==void 0){let a=await qn(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"}`)}for(let a of ka(t.label))await e.dropSnapshotRef(r,a).catch(()=>{});let i=await e.status(r).catch(()=>({clean:!1,changedPaths:["<unknown>"],hasRecordedWork:!1}));if(i.changedPaths.length>0){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}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=Z(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=Z(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(`
150
150
  ${_(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.
151
151
  `))}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)}.
152
152
  Use \`/hydra workspace start\` to move into an isolated workspace.`;let d=this.liveSessionsIn(a.path,o.sessionId).map(f=>Be(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 Z(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(`
@@ -156,7 +156,7 @@ Use \`/hydra workspace start\` to move into an isolated workspace.`;let d=this.l
156
156
  `)}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(`
157
157
  `)}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=>Be(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(`
158
158
  `)}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(`
159
- `)}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=Z(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=ya(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(y=>Be(y.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=Z(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)??"",m=await this.retireAutosave(t);e.broadcastWorkspacePhase({phase:"cleaning",label:t.label});let g=await i.resetTo(t.path,d,{purgeIgnored:n.deep});if(!g.ok)throw new Error(`could not return ${_(t.path)} to its base: ${g.reason??"unknown error"}. Nothing was changed.`);let h=n.deep?await this.applyWorkspaceSetup(t,e.sessionId):void 0;await i.retainSnapshot(a,this.startRefFor(t.label),t.snapshot).catch(()=>{});let w={...t,clean:!0};e.workspace=w,await this.mutateRecord(e.sessionId,{workspace:w}),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:t.sourceCwd,label:t.label,...a.line!==void 0?{branch:a.line}:{}});let k=[`Cleaned ${_(t.path)} back to the state it was created in.`];if(u>0||p>0){let y=[];u>0&&y.push(`${u} uncommitted change(s)`),p>0&&y.push(`${p} commit(s)`),k.push(` discarded ${y.join(" and ")}`)}else k.push(" nothing to discard; it was already at its base");return h!==void 0&&k.push(` ${h}`),m!==void 0&&k.push(` last autosave kept at ${m}: git -C ${t.sourceCwd} checkout ${m}`),p>0&&f.length>0&&k.push(` discarded commits are still at ${f.slice(0,12)} (and in the reflog for ${t.line??"this branch"})`),k.push(`Your uncommitted work in ${_(t.sourceCwd)} was never touched by this.`),k.join(`
159
+ `)}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=Z(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=wa(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(y=>Be(y.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=Z(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)??"",m=await this.retireAutosave(t);e.broadcastWorkspacePhase({phase:"cleaning",label:t.label});let g=await i.resetTo(t.path,d,{purgeIgnored:n.deep});if(!g.ok)throw new Error(`could not return ${_(t.path)} to its base: ${g.reason??"unknown error"}. Nothing was changed.`);let h=n.deep?await this.applyWorkspaceSetup(t,e.sessionId):void 0;await i.retainSnapshot(a,this.startRefFor(t.label),t.snapshot).catch(()=>{});let w={...t,clean:!0};e.workspace=w,await this.mutateRecord(e.sessionId,{workspace:w}),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:t.sourceCwd,label:t.label,...a.line!==void 0?{branch:a.line}:{}});let k=[`Cleaned ${_(t.path)} back to the state it was created in.`];if(u>0||p>0){let y=[];u>0&&y.push(`${u} uncommitted change(s)`),p>0&&y.push(`${p} commit(s)`),k.push(` discarded ${y.join(" and ")}`)}else k.push(" nothing to discard; it was already at its base");return h!==void 0&&k.push(` ${h}`),m!==void 0&&k.push(` last autosave kept at ${m}: git -C ${t.sourceCwd} checkout ${m}`),p>0&&f.length>0&&k.push(` discarded commits are still at ${f.slice(0,12)} (and in the reflog for ${t.line??"this branch"})`),k.push(`Your uncommitted work in ${_(t.sourceCwd)} was never touched by this.`),k.join(`
160
160
  `)})}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=Z(e.provider),a=this.asWorkspace(e),d=await Nr({source:n,ws:a,startSnapshotRef:this.startRefFor(e.label),baselineRef:this.baselineRefFor(e.label),retainRef:Fr(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 v=this.get(t),R="";if(v!==void 0)try{let x=await this.syncWorkspaceFromSource(v,e,{onConflict:"abort"});x.ok?(l.push(`
161
161
  synced with the source first: ${x.message}`),u=await i.contains(n,{state:c,within:r})):R=`
162
162
  A sync was attempted first and could not complete: ${x.message}`}catch(x){R=`
@@ -165,35 +165,35 @@ A sync was attempted first but was refused: ${x instanceof Error?x.message:Strin
165
165
  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:k}}async leaveWorkspace(e,t,n){let r=n.exit!=="detached",o=Z(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=Z(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=>Be(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(`
166
166
  `)})}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=Z();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 v=this.liveSessionsWithLabel(r,t)[0];if(v!==void 0&&v.workspace!==void 0)return await this.joinWorkspace(e,v,v.workspace,r)}let d,c=[],u=!1,l=!1,p=[],f=[],m=n?.clean===!0;if(a.supports.captureWorkingState){let v=await o.status({path:r,sourceCwd:r,label:"source",provider:o.kind}).catch(()=>{});l=v!==void 0;let R=a.supports.nestedTrees&&v!==void 0&&v.changedPaths.length>0?await o.listNested(r).catch(()=>[]):[];if(v!==void 0&&v.changedPaths.length>0&&m)p=Pr(v.changedPaths,R);else if(v!==void 0&&v.changedPaths.length>0&&(c=Pr(v.changedPaths,R),f=await o.captureNested(r,R).catch(()=>[]),u=v.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 g=await o.createWorkspace({sourceCwd:r,label:t??`s-${e.sessionId.slice(-8)}`});if(!g.ok)throw e.broadcastWorkspacePhase({phase:"failed",error:g.reason}),new Error(g.reason);let h=g.workspace,w=this.startRefFor(h.label),k,y=!1,b=[];try{a.locking&&await o.lock(h,`session ${e.sessionId}`).catch(()=>{});let v=d??h.snapshot;if(v===void 0)throw new Error(`provider "${h.provider}" gave the workspace no base to anchor landing against`);await o.retainSnapshot(h,w,v),e.broadcastWorkspacePhase({phase:"setup"}),y=d!==void 0?await this.copyCarriedWork(h,d,r):!0;let R=await this.materializeNestedTrees(h);if(f.length>0){let E=await o.reproduceNested(h.path,r,f).catch(O=>({applied:[],failed:f.map(T=>({path:T.relPath,reason:O instanceof Error?O.message:String(O)}))}));E.failed.length>0&&(y=!1,b=E.failed)}k=await this.applyWorkspaceSetup(h,e.sessionId),R!==void 0&&(k=k===void 0?R:`${R}; ${k}`),e.broadcastWorkspacePhase({phase:"swapping"});let x=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:h.path,workspace:{path:h.path,sourceCwd:h.sourceCwd,label:h.label,...t!==void 0&&t!==h.label?{requestedLabel:t}:{},provider:h.provider,...h.snapshot!==void 0?{snapshot:h.snapshot}:{},...h.line!==void 0?{line:h.line}:{},...h.vcs!==void 0?{vcs:{...h.vcs}}:{},...d===void 0?{clean:!0}:{}},historyLength:x.length,note:`Continuing in an isolated workspace at ${h.path}, derived from ${r}.`,...await this.recordSynopsisFor(e.sessionId)})}catch(v){let R=await this.unwindStartWorkspace({provider:o,ws:h,startRef:w,carried:d}),x=v instanceof Error?v.message:String(v);throw e.broadcastWorkspacePhase({phase:"failed",error:x}),new Error(R===void 0?x:`${x}
167
167
  ${R}`)}await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:h.sourceCwd,label:h.label,...h.line!==void 0?{branch:h.line}:{}});let I=[`Moved into workspace ${_(h.path)}`,` source: ${_(r)}`];if(h.line!==void 0&&I.push(` branch: ${h.line}`),t!==void 0&&t!==h.label&&I.push(` note: "${t}" was already taken by a surviving branch, so this is "${h.label}"`),d!==void 0){I.push(y?` 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 v of ot(c))I.push(` ${v}`);y&&u&&I.push(" staging did not come along; everything above is unstaged here");for(let v of b)I.push(` nested tree ${v.path}: ${v.reason}`)}else if(p.length>0){I.push(` started clean: ${p.length} uncommitted file(s) stayed in the source and did NOT come along:`);for(let v of ot(p))I.push(` ${v}`)}else l&&I.push(" source tree was clean; nothing carried in");return k!==void 0&&I.push(` ${k}`),I.push("Use `/hydra workspace stop` to merge back and return."),I.join(`
168
- `)}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=Z(e.provider);return o===void 0?!1:(await o.applyDelta(e.path,r)).ok}async patchFromSnapshot(e,t,n){let r=Z(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=Z(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 Wn(e.sourceCwd).catch(()=>({})),r=[];if(n.carry!==void 0&&n.carry.length>0){let o=await Hr(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 qn(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=Z(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=Z(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=Z(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 g=new Error(`agent ${e} not found in registry`);throw g.code=A.AgentNotInstalled,g}let n=await Ie(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:Va.homedir(),plan:n}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:ht,clientInfo:{name:"hydra",version:ue}})}catch(g){throw await r.kill().catch(()=>{}),Ye(g,r)}if(r.authMethods=on(o.authMethods),r.steeringSupported=rn(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(g){throw await r.kill().catch(()=>{}),g}await r.kill().catch(()=>{});let d=new Map,c=Qs(t);d.set(e,c);let u=new Set;for(let g of this.sessions.values()){let h=await this.agentStoreKey(g.agentId,d);u.add(`${h}::${g.upstreamSessionId}`)}let l=await this.store.list().catch(()=>[]);for(let g of l){u.add(`${await this.agentStoreKey(g.agentId,d)}::${g.upstreamSessionId}`);for(let h of g.upstreamGenerations??[])u.add(`${await this.agentStoreKey(h.agentId,d)}::${h.upstreamSessionId}`)}let p=C.sessionsDir(),f=[],m=0;for(let g of a){let h=`${c}::${g.sessionId}`;if(u.has(h)){m+=1;continue}if(yp(g.cwd,p)){m+=1;continue}let w=c,k=await this.tombstones.read(w,g.sessionId).catch(()=>{});if(!k&&c!==e&&(w=e,k=await this.tombstones.read(w,g.sessionId).catch(()=>{})),k){if(!ka(k,g.updatedAt)){m+=1;continue}await this.tombstones.remove(w,g.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${g.sessionId} (upstream updatedAt advanced past ${k.upstreamUpdatedAt??"<unset>"})`)}u.add(h);let y=`${Ne}${Et()}`,b=new Date().toISOString(),I=g.updatedAt??b,v={sessionId:y,lineageId:Yt(),upstreamSessionId:g.sessionId,agentId:e,cwd:g.cwd,pendingHistorySync:!0,interactive:!0,createdAt:I,updatedAt:I};g.title!==void 0&&(v.title=g.title);let R=Er(v);await this.store.write(R),f.push({version:1,...R})}return{synced:f,skipped:m}}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 Qe({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 bootstrapAgent(e){let t=await this.registry.getAgent(e.agentId);if(!t){let i=new Error(`agent ${e.agentId} not found in registry`);throw i.code=A.AgentNotInstalled,i}let n=await Ie(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),r=kn(e.selfSessionId,e.forwardedEnv),o=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:n,...r?{extraEnv:r}:{}});try{let i=await o.connection.request("initialize",{protocolVersion:1,clientCapabilities:ht,clientInfo:{name:"hydra",version:ue}}),a=i.agentCapabilities;o.authMethods=on(i.authMethods),o.steeringSupported=rn(i);let d=zr(t),c=await o.connection.request("session/new",{cwd:e.cwd,mcpServers:e.mcpServers??[],...d&&{_meta:d}}),u=c.sessionId;if(typeof u!="string")throw new Error(`agent ${e.agentId} returned a non-string sessionId from session/new`);let l=Jr(c),p=Gr(c),f=wt(c),m=Wt(this.defaultModels,t),g=e.model??m?.value,h;if(g&&g!==l){let b=bt(g,p),I=e.model!==void 0?`model=${JSON.stringify(g)}`:`defaultModels[${m?.from??e.agentId}]=${JSON.stringify(g)}`;if(b.kind==="exact"||b.kind==="none"){let v=await this.applySeedModel(o,u,g,I,f);v.accepted&&(l=g,h=v.result)}else if(b.kind==="resolved")if(b.modelId===l)l=b.modelId;else{let v=await this.applySeedModel(o,u,b.modelId,`${I} resolved to ${JSON.stringify(b.modelId)}`,f);v.accepted&&(l=b.modelId,h=v.result)}else if(b.kind==="ambiguous")this.logger?.warn(`${I} is ambiguous (trailing-segment matches [${b.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(l)}`);else{let v=p.map(R=>R.modelId).join(", ");this.logger?.warn(`${I} not in agent's availableModels ([${v}]); skipping session/set_model, session will use ${JSON.stringify(l)}`)}}let w=Kr(c),k=Qr(c),y=Xn(Vr(h)?h:c);return{agent:o,upstreamSessionId:u,agentMeta:c._meta,agentCapabilities:a,initialModel:l,initialModels:p.length>0?p:void 0,initialModes:w.length>0?w:void 0,initialMode:k,initialConfigOptions:y.length>0?y:void 0,modelVerb:f}}catch(i){throw await o.kill().catch(()=>{}),Ye(za(i,o,e.agentId,{command:n.command,args:n.args,cwd:e.cwd}),o)}}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=A.AgentNotInstalled,a}let r=await Ie(n,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=kn(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:ht,clientInfo:{name:"hydra",version:ue}}),d=a.agentCapabilities;i.authMethods=on(a.authMethods),i.steeringSupported=rn(a);let c=zr(n),u=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),l=Jr(u),p=Tt(Gr(u)),f=Kr(u),m=Qr(u),g=Tt(Xn(u));return{agent:i,upstreamSessionId:e,agentMeta:u._meta,agentCapabilities:d,initialModel:l,initialModels:p,initialModes:f.length>0?f:void 0,initialMode:m,initialConfigOptions:g,modelVerb:wt(u)}}catch(a){throw await i.kill().catch(()=>{}),Ye(za(a,i,t.agentId,{command:r.command,args:r.args,cwd:t.cwd}),i)}}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=A.AgentNotInstalled,d}let o=await Ie(r,[],{npmRegistry:this.npmRegistry}),i=t??ie(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let d=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:ht,clientInfo:{name:"hydra",version:ue}});a.authMethods=on(d.authMethods),a.steeringSupported=rn(d)}catch(d){throw await a.kill().catch(()=>{}),Ye(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=A.AgentNotInstalled,n}return Ie(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&&e.workspace!==void 0&&this.releaseWorkspace(e.workspace,e.sessionId).catch(()=>{}),t){if(e.upstreamSessionId){let r=Pt({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.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:Ga(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.onAttentionFlagsChange(t=>{this.mutateRecord(e.sessionId,{attentionFlags:t}).catch(()=>{})}),this.sessions.set(e.sessionId,e),this.invalidateListCache(),await this.enqueueMetaWrite(e.sessionId,async()=>{let t=await this.store.read(e.sessionId),n=wp(e,t);await this.store.write(n)}).catch(()=>{})}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 loadHistory(e,t={}){return this.histories.load(e,t)}async loadToolBlob(e,t){return Bt(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:kp(t.currentUsage),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,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=rt(r.update.prompt),a=vr(i,200);if(a&&!a.startsWith("/"))return a}}get(e){return this.sessions.get(e)}liveSessions(){return this.sessions.values()}setLiveConfig(e){e.defaultModels&&(this.defaultModels=e.defaultModels)}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(Ne))return;let t=Ne+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=A.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,forkSynthesisState:e.forkSynthesisState,originatingClient:e.originatingClient,interactive:e.interactive,updatedAt:new Date(e.updatedAt).toISOString(),attachedClients:e.attachedCount,status:"warm",busy:e.turnStartedAt!==void 0,armedTasks:e.armedBackgroundTasks.length,...e.armedSince!==void 0?{armedSince:e.armedSince}:{},awaitingInput:e.awaitingInput,agentPid:e.agentPid}}async getOne(e){let t=this.sessions.get(e);if(t){let a=await an(t.sessionId),d=Pt({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,forkSynthesisState:t.forkSynthesisState,originatingClient:t.originatingClient,interactive:d,priority:t.priority,updatedAt:c,attachedClients:t.attachedCount,status:"warm",agentPid:t.agentPid,busy:t.turnStartedAt!==void 0,armedTasks:t.armedBackgroundTasks.length,...t.armedSince!==void 0?{armedSince:t.armedSince}:{},awaitingInput:t.awaitingInput}}let n=await this.store.read(e).catch(()=>{});if(!n)return;let r=await an(n.sessionId),o=Pt(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:sn(n.currentUsage),importedFromMachine:n.importedFromMachine,importedFromUpstreamSessionId:n.importedFromUpstreamSessionId,parentSessionId:n.parentSessionId,forkedFromSessionId:n.forkedFromSessionId,forkedFromMessageId:n.forkedFromMessageId,forkSynthesisState:n.forkSynthesisState,originatingClient:n.originatingClient,interactive:o,priority:n.priority,updatedAt:i,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1}}async list(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=[],n=new Set,r=u=>e.includeNonInteractive?!0:u===!0,o=[...this.sessions.values()].filter(u=>Wa(e.cwd,u));if(e.status==="cold")for(let u of o)n.add(u.sessionId);let i=e.status==="cold"?[]:await Promise.all(o.map(u=>an(u.sessionId)));for(let u=0;u<i.length;u+=1){let l=o[u],p=i[u];n.add(l.sessionId);let f=Pt({interactive:l.interactive,...l.originatingClient?{originatingClient:l.originatingClient}:{}},p.hasContent);if(!r(f))continue;let m=p.mtime??new Date(l.updatedAt).toISOString();t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,workspace:l.workspace,workspaceError:l.workspaceError,title:l.title,agentId:l.agentId,currentModel:l.currentModel,currentUsage:l.currentUsage,parentSessionId:l.parentSessionId,forkedFromSessionId:l.forkedFromSessionId,forkedFromMessageId:l.forkedFromMessageId,originatingClient:l.originatingClient,interactive:f,priority:l.priority,updatedAt:m,attachedClients:l.attachedCount,status:"warm",agentPid:l.agentPid,busy:l.turnStartedAt!==void 0,armedTasks:l.armedBackgroundTasks.length,...l.armedSince!==void 0?{armedSince:l.armedSince}:{},awaitingInput:l.awaitingInput,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}if(e.status==="warm")return t;let d=(await this.store.list().catch(u=>{throw this.logger?.warn(`session list: store.list() failed: ${u?.message??String(u)}`),u})).filter(u=>!n.has(u.sessionId)&&Wa(e.cwd,u)),c=await Promise.all(d.map(u=>an(u.sessionId)));for(let u=0;u<d.length;u+=1){let l=d[u],p=c[u],f=Pt(l,p.hasContent);if(!r(f))continue;let m=p.mtime??l.updatedAt;t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,workspace:l.workspace,title:l.title,agentId:l.agentId,currentModel:l.currentModel,currentUsage:sn(l.currentUsage),importedFromMachine:l.importedFromMachine,importedFromUpstreamSessionId:l.importedFromUpstreamSessionId,parentSessionId:l.parentSessionId,forkedFromSessionId:l.forkedFromSessionId,forkedFromMessageId:l.forkedFromMessageId,originatingClient:l.originatingClient,interactive:f,priority:l.priority,updatedAt:m,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}return t.sort((u,l)=>u.updatedAt<l.updatedAt?1:-1),t}async exportBundle(e,t={}){let n=await this.store.read(e);if(!n)return;let r;if(n.lineageId)r=n;else{let c=Yt(),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=await this.histories.load(e,o==="references"?{tools:"references"}:{}).catch(()=>[]),a=await Ja(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let d={};for(let c of Fa(i)){let u=await Uo(e,c);u&&(d[c]=u.toString("base64"))}return{record:r,history:i,promptHistory:a,toolBlobs:d}}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=A.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=`${Ne}${Et()}`;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 I=new Error(`source session not found: ${e}`);throw I.code=A.SessionNotFound,I}let r=t.agentId??n.agentId,o=r!==n.agentId;if(o&&!await this.registry.getAgent(r)){let v=new Error(`agent ${r} not found in registry`);throw v.code=A.AgentNotInstalled,v}let i=await this.histories.load(e).catch(()=>[]),a=i,d,c=t.mode??"synthesis",u,l,p,f=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let I=$n(i,t.forkAt);if(I<0){let v=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw v.code=A.InvalidParams,v}d=t.forkAt,a=i.slice(0,I+1)}else{let I=Ip(i);I?(d=I.messageId,a=i.slice(0,I.index+1)):(d="",a=i.slice(0,0))}else{if(t.forkAt!==void 0&&t.forkAt!==""){let v=$n(i,t.forkAt);if(v<0){let R=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw R.code=A.InvalidParams,R}d=t.forkAt,a=i.slice(0,v+1)}else d="",a=i;let I=await this.registry.getAgent(r);if(!I){let v=new Error(`agent ${r} not found in registry`);throw v.code=A.AgentNotInstalled,v}p=I,l=n.currentModel,u="running"}let m=await Ja(e),g=c==="synthesis",h={...n,lineageId:Yt(),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}:{}},w=nn({record:h,history:a,promptHistory:m.length>0?m:void 0,hydraVersion:ue,machine:zt()}),k=`${Ne}${Et()}`,y=t.cwd,b;if(t.cwd===void 0&&n.workspace!==void 0){let I=await this.deriveForkWorkspace(n.workspace,`${n.workspace.label}-fork-${k.slice(-6)}`);I!==void 0?(b=I,y=I.path):(y=n.workspace.sourceCwd,this.logger?.warn?.(`fork ${k}: could not derive an isolated workspace from ${n.workspace.path}; running unisolated in ${y}`))}return await this.writeImportedRecord({sessionId:k,bundle:w,cwd:y,...b!==void 0?{workspace:b}:{},forkedFromSessionId:e,forkedFromMessageId:d,...u!==void 0?{forkSynthesisState:u}:{}}),g&&(async()=>{try{let I=await Ie(p,[],{npmRegistry:this.npmRegistry}),v=await Gn({agentId:r,cwd:t.cwd??C.sessionDir(e),plan:I,history:a,modelId:l,sessionId:e,logger:this.logger,timeoutMs:f});v&&v.synopsis?await this.mutateRecord(k,{synopsis:v.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(k,{},["forkSynthesisState"]))}catch(I){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${I.message}`);try{await this.mutateRecord(k,{},["forkSynthesisState"])}catch(v){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${v.message}`)}}})(),{sessionId:k,forkedFromSessionId:e,forkedAt:d}}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 Lo(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await at.utimes(C.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await Ua(C.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}:{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=Qs(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,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 an(e),o=Pt(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:Ka(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.interactive!==void 0&&(n.interactive=t.interactive),t.cwd!==void 0&&(n.cwd=t.cwd),await this.mutateRecord(e,n)}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);if(!r?.synopsis||r.summarizedThroughEntry===void 0){this.synopsisCoordinator.scheduleCompaction(e,t);return}if((await this.histories.load(e,{maxEntries:1/0})).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){let o=n.phase==="failed";r.broadcastPendingAgentSwap(o?null: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 qi(t.sessionId).catch(()=>[]);if(n.length===0)continue;let r=Date.now(),o=n.filter(d=>r-d.enqueuedAt<Ba),i=n.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${Ba/1e3}s)`),await Gt(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 Gt(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 yp(s,e){if(typeof s!="string"||s.length===0)return!1;let t=dn.resolve(s),n=dn.resolve(e);return t===n||t.startsWith(n+dn.sep)}function Wa(s,e){if(s===void 0||s.length===0)return!0;let t=qr(s);if(qr(e.cwd)===t)return!0;let n=e.workspace?.sourceCwd;return n!==void 0&&qr(n)===t}function qr(s){return s.length>1&&s.endsWith("/")?s.replace(/\/+$/,""):s}function wp(s,e){let n=(s.mergedAvailableCommands().length>0?s.agentOnlyAdvertisedCommands().map(u=>u.description!==void 0?{name:u.name,description:u.description}:{name:u.name}):void 0)??e?.agentCommands,r=s.availableModes(),i=(r.length>0?r.map(u=>{let l={id:u.id};return u.name!==void 0&&(l.name=u.name),u.description!==void 0&&(l.description=u.description),l}):void 0)??e?.agentModes,a=s.availableModels(),c=(a.length>0?a.map(u=>{let l={modelId:u.modelId};return u.name!==void 0&&(l.name=u.name),u.description!==void 0&&(l.description=u.description),l}):void 0)??e?.agentModels;return Er({sessionId:s.sessionId,lineageId:e?.lineageId??Yt(),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:Ga(s.persistableUsage)??e?.currentUsage,agentCommands:n,agentModes:i,agentModels:c,parentSessionId:s.parentSessionId??e?.parentSessionId,forkedFromSessionId:s.forkedFromSessionId??e?.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId??e?.forkedFromMessageId,originatingClient:s.originatingClient??e?.originatingClient,interactive:s.interactive??e?.interactive,priority:s.priority??e?.priority,forwardedEnv:s.forwardedEnv??e?.forwardedEnv,workspace:s.workspace,attentionFlags:s.listAttentionFlags(),extensionState:e?.extensionState,upstreamGenerations:e?Ka(e,s.agentId,s.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(s.createdAt).toISOString()})}function Ga(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 kp(s){return s?{...s}:void 0}function vp(s){return(s.extendsChain??[s.id]).some(t=>t==="claude-acp"||t.startsWith("claude-acp-"))}var bp=[{type:"system",subtype:"background_tasks_changed"}];function zr(s,e={}){if(!vp(s))return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t,emitRawSDKMessages:bp}}}function es(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=Sp(s,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function Jr(s){return es(s,{nestedKey:"models",configId:"model",fromObject:e=>ge(e.currentModelId)??ge(e.currentModel)??ge(e.modelId)??ge(e.model),fromConfig:e=>ge(e.currentValue)})}function Ye(s,e){if(!s||typeof s!="object")return s;let t=s;if(t.code!==A.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=A.AuthRequired,d.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function qa(s){return/^[A-Za-z0-9_\-./=:@]+$/.test(s)?s:`'${s.replace(/'/g,"'\\''")}'`}function za(s,e,t,n){if(s&&typeof s=="object"&&s.code===A.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 ${qa(n.cwd)} && ${[n.command,...n.args].map(qa).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(`
169
- `));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 rn(s){return s._meta?.steering?.supported===!0}function on(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 ge(s){if(typeof s!="string")return;let e=s.trim();return e.length>0?e:void 0}function Sp(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 Vr(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.configOptions)}function Xn(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=ge(r.id);if(!o||o==="model"||o==="mode"||o==="agent")continue;let i=kr(r.options);if(i.length===0)continue;let a=ge(r.description);t.push({id:o,name:ge(r.name)??o,...a?{description:a}:{},category:ge(r.category)??"other",type:"select",currentValue:ge(r.currentValue)??i[0].value,options:i})}return t}function Tt(s){return s.length>0?s:void 0}function Gr(s){return es(s,{nestedKey:"models",configId:"model",fromObject:e=>{let t=Kt(e.availableModels);return t.length>0?t:void 0},fromConfig:e=>{let t=Kt(e.options);return t.length>0?t:void 0}})??[]}function Kr(s){return es(s,{nestedKey:"modes",configId:"mode",fromObject:e=>{let t=_n(e.availableModes);return t.length>0?t:void 0},fromConfig:e=>{let t=_n(e.options);return t.length>0?t:void 0}})??[]}function Qr(s){return es(s,{nestedKey:"modes",configId:"mode",fromObject:e=>ge(e.currentModeId)??ge(e.currentMode)??ge(e.modeId)??ge(e.mode),fromConfig:e=>ge(e.currentValue)})}function Ip(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 Ja(s){try{let e=await at.readFile(C.tuiHistoryFile(s),"utf8"),t=[];for(let n of e.split(`
170
- `))if(n.length!==0)try{let r=JSON.parse(n);typeof r=="string"&&t.push(r)}catch{}return t}catch{return[]}}function Ka(s,e,t,n=new Date().toISOString(),r={}){let{retiredCost:o,retiredUsed:i,startedUsed:a,lifetimeCost:d,reason:c,runId:u}=r,l=m=>d!==void 0&&m.lifetimeCostAtStart!==void 0?Math.max(0,d-m.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 m=p[p.length-2];if(m){let g=l(m);p[p.length-2]={...m,...g!==void 0&&m.cost===void 0?{cost:g}:{},...i!==void 0&&m.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 m=l(f);return m!==void 0?{cost:m}:{}})(),...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 an(s){try{let e=await at.stat(C.historyFile(s));return{mtime:new Date(e.mtimeMs).toISOString(),hasContent:e.size>0}}catch{return{hasContent:!1}}}function Pt(s,e){return s.interactive!==void 0?s.interactive:s.originatingClient?.name===Vn?!1:e?!0:void 0}import{spawn as Ap}from"child_process";import*as ns from"fs";import*as ze from"fs/promises";import*as ss from"path";import Cp from"pino-roll";var ts=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_}};var Rp=1e3,xp=6e4,Yr=3e3,Mt=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??Rp,this.restartCapMs=r.restartCapMs??xp;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 ze.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()},Yr);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 cn(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");if(t.child)throw cn(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 cn(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 cn(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 cn(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{}},Yr);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 ts(this.breakerOptions),failureReason:void 0}}async reapOrphans(){let e;try{e=await ze.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 ze.readFile(n,"utf8"),i=Number.parseInt(o.trim(),10);Number.isInteger(i)&&i>0&&(r=i)}catch{}if(typeof r=="number"&&Xr(r)){try{process.kill(r,"SIGTERM")}catch{}let o=Date.now()+Yr;for(;Date.now()<o&&Xr(r);)await new Promise(i=>setTimeout(i,50));if(Xr(r))try{process.kill(r,"SIGKILL")}catch{}}await ze.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=ss.dirname(this.adapter.paths.logFile(r.name)),a;try{await ze.mkdir(i,{recursive:!0}),a=await Cp({file:ss.join(i,`${r.name}.log`),size:"5m",mkdir:!0,symlink:!0,limit:{count:5}}),a.on("error",h=>{e.failureReason=`log stream: ${h.message}`})}catch(h){if(this.stopping||e.manuallyStopped)return;e.failureReason=`log setup: ${h.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})
168
+ `)}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=Z(e.provider);return o===void 0?!1:(await o.applyDelta(e.path,r)).ok}async patchFromSnapshot(e,t,n){let r=Z(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=Z(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 Wn(e.sourceCwd).catch(()=>({})),r=[];if(n.carry!==void 0&&n.carry.length>0){let o=await Hr(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 qn(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=Z(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=Z(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=Z(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 g=new Error(`agent ${e} not found in registry`);throw g.code=A.AgentNotInstalled,g}let n=await Ie(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:Ga.homedir(),plan:n}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:ht,clientInfo:{name:"hydra",version:ue}})}catch(g){throw await r.kill().catch(()=>{}),Ye(g,r)}if(r.authMethods=on(o.authMethods),r.steeringSupported=rn(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(g){throw await r.kill().catch(()=>{}),g}await r.kill().catch(()=>{});let d=new Map,c=Qs(t);d.set(e,c);let u=new Set;for(let g of this.sessions.values()){let h=await this.agentStoreKey(g.agentId,d);u.add(`${h}::${g.upstreamSessionId}`)}let l=await this.store.list().catch(()=>[]);for(let g of l){u.add(`${await this.agentStoreKey(g.agentId,d)}::${g.upstreamSessionId}`);for(let h of g.upstreamGenerations??[])u.add(`${await this.agentStoreKey(h.agentId,d)}::${h.upstreamSessionId}`)}let p=C.sessionsDir(),f=[],m=0;for(let g of a){let h=`${c}::${g.sessionId}`;if(u.has(h)){m+=1;continue}if(wp(g.cwd,p)){m+=1;continue}let w=c,k=await this.tombstones.read(w,g.sessionId).catch(()=>{});if(!k&&c!==e&&(w=e,k=await this.tombstones.read(w,g.sessionId).catch(()=>{})),k){if(!va(k,g.updatedAt)){m+=1;continue}await this.tombstones.remove(w,g.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${g.sessionId} (upstream updatedAt advanced past ${k.upstreamUpdatedAt??"<unset>"})`)}u.add(h);let y=`${Ne}${Et()}`,b=new Date().toISOString(),I=g.updatedAt??b,v={sessionId:y,lineageId:Yt(),upstreamSessionId:g.sessionId,agentId:e,cwd:g.cwd,pendingHistorySync:!0,interactive:!0,createdAt:I,updatedAt:I};g.title!==void 0&&(v.title=g.title);let R=Er(v);await this.store.write(R),f.push({version:1,...R})}return{synced:f,skipped:m}}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 Qe({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 bootstrapAgent(e){let t=await this.registry.getAgent(e.agentId);if(!t){let i=new Error(`agent ${e.agentId} not found in registry`);throw i.code=A.AgentNotInstalled,i}let n=await Ie(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),r=kn(e.selfSessionId,e.forwardedEnv),o=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:n,...r?{extraEnv:r}:{}});try{let i=await o.connection.request("initialize",{protocolVersion:1,clientCapabilities:ht,clientInfo:{name:"hydra",version:ue}}),a=i.agentCapabilities;o.authMethods=on(i.authMethods),o.steeringSupported=rn(i);let d=zr(t),c=await o.connection.request("session/new",{cwd:e.cwd,mcpServers:e.mcpServers??[],...d&&{_meta:d}}),u=c.sessionId;if(typeof u!="string")throw new Error(`agent ${e.agentId} returned a non-string sessionId from session/new`);let l=Jr(c),p=Gr(c),f=wt(c),m=Wt(this.defaultModels,t),g=e.model??m?.value,h;if(g&&g!==l){let b=bt(g,p),I=e.model!==void 0?`model=${JSON.stringify(g)}`:`defaultModels[${m?.from??e.agentId}]=${JSON.stringify(g)}`;if(b.kind==="exact"||b.kind==="none"){let v=await this.applySeedModel(o,u,g,I,f);v.accepted&&(l=g,h=v.result)}else if(b.kind==="resolved")if(b.modelId===l)l=b.modelId;else{let v=await this.applySeedModel(o,u,b.modelId,`${I} resolved to ${JSON.stringify(b.modelId)}`,f);v.accepted&&(l=b.modelId,h=v.result)}else if(b.kind==="ambiguous")this.logger?.warn(`${I} is ambiguous (trailing-segment matches [${b.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(l)}`);else{let v=p.map(R=>R.modelId).join(", ");this.logger?.warn(`${I} not in agent's availableModels ([${v}]); skipping session/set_model, session will use ${JSON.stringify(l)}`)}}let w=Kr(c),k=Qr(c),y=Xn(Vr(h)?h:c);return{agent:o,upstreamSessionId:u,agentMeta:c._meta,agentCapabilities:a,initialModel:l,initialModels:p.length>0?p:void 0,initialModes:w.length>0?w:void 0,initialMode:k,initialConfigOptions:y.length>0?y:void 0,modelVerb:f}}catch(i){throw await o.kill().catch(()=>{}),Ye(Ja(i,o,e.agentId,{command:n.command,args:n.args,cwd:e.cwd}),o)}}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=A.AgentNotInstalled,a}let r=await Ie(n,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=kn(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:ht,clientInfo:{name:"hydra",version:ue}}),d=a.agentCapabilities;i.authMethods=on(a.authMethods),i.steeringSupported=rn(a);let c=zr(n),u=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),l=Jr(u),p=Tt(Gr(u)),f=Kr(u),m=Qr(u),g=Tt(Xn(u));return{agent:i,upstreamSessionId:e,agentMeta:u._meta,agentCapabilities:d,initialModel:l,initialModels:p,initialModes:f.length>0?f:void 0,initialMode:m,initialConfigOptions:g,modelVerb:wt(u)}}catch(a){throw await i.kill().catch(()=>{}),Ye(Ja(a,i,t.agentId,{command:r.command,args:r.args,cwd:t.cwd}),i)}}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=A.AgentNotInstalled,d}let o=await Ie(r,[],{npmRegistry:this.npmRegistry}),i=t??ie(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let d=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:ht,clientInfo:{name:"hydra",version:ue}});a.authMethods=on(d.authMethods),a.steeringSupported=rn(d)}catch(d){throw await a.kill().catch(()=>{}),Ye(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=A.AgentNotInstalled,n}return Ie(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&&e.workspace!==void 0&&this.releaseWorkspace(e.workspace,e.sessionId).catch(()=>{}),t){if(e.upstreamSessionId){let r=Pt({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.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:Ka(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.onAttentionFlagsChange(t=>{this.mutateRecord(e.sessionId,{attentionFlags:t}).catch(()=>{})}),this.sessions.set(e.sessionId,e),this.invalidateListCache(),await this.enqueueMetaWrite(e.sessionId,async()=>{let t=await this.store.read(e.sessionId),n=kp(e,t);await this.store.write(n)}).catch(()=>{})}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 loadHistory(e,t={}){return this.histories.load(e,t)}async loadToolBlob(e,t){return Bt(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:vp(t.currentUsage),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,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=rt(r.update.prompt),a=vr(i,200);if(a&&!a.startsWith("/"))return a}}get(e){return this.sessions.get(e)}liveSessions(){return this.sessions.values()}setLiveConfig(e){e.defaultModels&&(this.defaultModels=e.defaultModels)}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(Ne))return;let t=Ne+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=A.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,forkSynthesisState:e.forkSynthesisState,originatingClient:e.originatingClient,interactive:e.interactive,updatedAt:new Date(e.updatedAt).toISOString(),attachedClients:e.attachedCount,status:"warm",busy:e.turnStartedAt!==void 0,armedTasks:e.armedBackgroundTasks.length,...e.armedSince!==void 0?{armedSince:e.armedSince}:{},awaitingInput:e.awaitingInput,agentPid:e.agentPid}}async getOne(e){let t=this.sessions.get(e);if(t){let a=await an(t.sessionId),d=Pt({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,forkSynthesisState:t.forkSynthesisState,originatingClient:t.originatingClient,interactive:d,priority:t.priority,updatedAt:c,attachedClients:t.attachedCount,status:"warm",agentPid:t.agentPid,busy:t.turnStartedAt!==void 0,armedTasks:t.armedBackgroundTasks.length,...t.armedSince!==void 0?{armedSince:t.armedSince}:{},awaitingInput:t.awaitingInput}}let n=await this.store.read(e).catch(()=>{});if(!n)return;let r=await an(n.sessionId),o=Pt(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:sn(n.currentUsage),importedFromMachine:n.importedFromMachine,importedFromUpstreamSessionId:n.importedFromUpstreamSessionId,parentSessionId:n.parentSessionId,forkedFromSessionId:n.forkedFromSessionId,forkedFromMessageId:n.forkedFromMessageId,forkSynthesisState:n.forkSynthesisState,originatingClient:n.originatingClient,interactive:o,priority:n.priority,updatedAt:i,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1}}async list(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=[],n=new Set,r=u=>e.includeNonInteractive?!0:u===!0,o=[...this.sessions.values()].filter(u=>qa(e.cwd,u));if(e.status==="cold")for(let u of o)n.add(u.sessionId);let i=e.status==="cold"?[]:await Promise.all(o.map(u=>an(u.sessionId)));for(let u=0;u<i.length;u+=1){let l=o[u],p=i[u];n.add(l.sessionId);let f=Pt({interactive:l.interactive,...l.originatingClient?{originatingClient:l.originatingClient}:{}},p.hasContent);if(!r(f))continue;let m=p.mtime??new Date(l.updatedAt).toISOString();t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,workspace:l.workspace,workspaceError:l.workspaceError,title:l.title,agentId:l.agentId,currentModel:l.currentModel,currentUsage:l.currentUsage,parentSessionId:l.parentSessionId,forkedFromSessionId:l.forkedFromSessionId,forkedFromMessageId:l.forkedFromMessageId,originatingClient:l.originatingClient,interactive:f,priority:l.priority,updatedAt:m,attachedClients:l.attachedCount,status:"warm",agentPid:l.agentPid,busy:l.turnStartedAt!==void 0,armedTasks:l.armedBackgroundTasks.length,...l.armedSince!==void 0?{armedSince:l.armedSince}:{},awaitingInput:l.awaitingInput,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}if(e.status==="warm")return t;let d=(await this.store.list().catch(u=>{throw this.logger?.warn(`session list: store.list() failed: ${u?.message??String(u)}`),u})).filter(u=>!n.has(u.sessionId)&&qa(e.cwd,u)),c=await Promise.all(d.map(u=>an(u.sessionId)));for(let u=0;u<d.length;u+=1){let l=d[u],p=c[u],f=Pt(l,p.hasContent);if(!r(f))continue;let m=p.mtime??l.updatedAt;t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,workspace:l.workspace,title:l.title,agentId:l.agentId,currentModel:l.currentModel,currentUsage:sn(l.currentUsage),importedFromMachine:l.importedFromMachine,importedFromUpstreamSessionId:l.importedFromUpstreamSessionId,parentSessionId:l.parentSessionId,forkedFromSessionId:l.forkedFromSessionId,forkedFromMessageId:l.forkedFromMessageId,originatingClient:l.originatingClient,interactive:f,priority:l.priority,updatedAt:m,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}return t.sort((u,l)=>u.updatedAt<l.updatedAt?1:-1),t}async exportBundle(e,t={}){let n=await this.store.read(e);if(!n)return;let r;if(n.lineageId)r=n;else{let c=Yt(),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=await this.histories.load(e,o==="references"?{tools:"references"}:{}).catch(()=>[]),a=await Va(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let d={};for(let c of Na(i)){let u=await Lo(e,c);u&&(d[c]=u.toString("base64"))}return{record:r,history:i,promptHistory:a,toolBlobs:d}}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=A.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=`${Ne}${Et()}`;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 I=new Error(`source session not found: ${e}`);throw I.code=A.SessionNotFound,I}let r=t.agentId??n.agentId,o=r!==n.agentId;if(o&&!await this.registry.getAgent(r)){let v=new Error(`agent ${r} not found in registry`);throw v.code=A.AgentNotInstalled,v}let i=await this.histories.load(e).catch(()=>[]),a=i,d,c=t.mode??"synthesis",u,l,p,f=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let I=$n(i,t.forkAt);if(I<0){let v=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw v.code=A.InvalidParams,v}d=t.forkAt,a=i.slice(0,I+1)}else{let I=Ap(i);I?(d=I.messageId,a=i.slice(0,I.index+1)):(d="",a=i.slice(0,0))}else{if(t.forkAt!==void 0&&t.forkAt!==""){let v=$n(i,t.forkAt);if(v<0){let R=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw R.code=A.InvalidParams,R}d=t.forkAt,a=i.slice(0,v+1)}else d="",a=i;let I=await this.registry.getAgent(r);if(!I){let v=new Error(`agent ${r} not found in registry`);throw v.code=A.AgentNotInstalled,v}p=I,l=n.currentModel,u="running"}let m=await Va(e),g=c==="synthesis",h={...n,lineageId:Yt(),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}:{}},w=nn({record:h,history:a,promptHistory:m.length>0?m:void 0,hydraVersion:ue,machine:zt()}),k=`${Ne}${Et()}`,y=t.cwd,b;if(t.cwd===void 0&&n.workspace!==void 0){let I=await this.deriveForkWorkspace(n.workspace,`${n.workspace.label}-fork-${k.slice(-6)}`);I!==void 0?(b=I,y=I.path):(y=n.workspace.sourceCwd,this.logger?.warn?.(`fork ${k}: could not derive an isolated workspace from ${n.workspace.path}; running unisolated in ${y}`))}return await this.writeImportedRecord({sessionId:k,bundle:w,cwd:y,...b!==void 0?{workspace:b}:{},forkedFromSessionId:e,forkedFromMessageId:d,...u!==void 0?{forkSynthesisState:u}:{}}),g&&(async()=>{try{let I=await Ie(p,[],{npmRegistry:this.npmRegistry}),v=await Gn({agentId:r,cwd:t.cwd??C.sessionDir(e),plan:I,history:a,modelId:l,sessionId:e,logger:this.logger,timeoutMs:f});v&&v.synopsis?await this.mutateRecord(k,{synopsis:v.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(k,{},["forkSynthesisState"]))}catch(I){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${I.message}`);try{await this.mutateRecord(k,{},["forkSynthesisState"])}catch(v){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${v.message}`)}}})(),{sessionId:k,forkedFromSessionId:e,forkedAt:d}}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 Bo(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await at.utimes(C.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await La(C.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}:{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=Qs(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,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 an(e),o=Pt(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:Qa(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.interactive!==void 0&&(n.interactive=t.interactive),t.cwd!==void 0&&(n.cwd=t.cwd),await this.mutateRecord(e,n)}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);if(!r?.synopsis||r.summarizedThroughEntry===void 0){this.synopsisCoordinator.scheduleCompaction(e,t);return}if((await this.histories.load(e,{maxEntries:1/0})).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){let o=n.phase==="failed";r.broadcastPendingAgentSwap(o?null: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 zi(t.sessionId).catch(()=>[]);if(n.length===0)continue;let r=Date.now(),o=n.filter(d=>r-d.enqueuedAt<Wa),i=n.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${Wa/1e3}s)`),await Gt(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 Gt(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 wp(s,e){if(typeof s!="string"||s.length===0)return!1;let t=dn.resolve(s),n=dn.resolve(e);return t===n||t.startsWith(n+dn.sep)}function qa(s,e){if(s===void 0||s.length===0)return!0;let t=qr(s);if(qr(e.cwd)===t)return!0;let n=e.workspace?.sourceCwd;return n!==void 0&&qr(n)===t}function qr(s){return s.length>1&&s.endsWith("/")?s.replace(/\/+$/,""):s}function kp(s,e){let n=(s.mergedAvailableCommands().length>0?s.agentOnlyAdvertisedCommands().map(u=>u.description!==void 0?{name:u.name,description:u.description}:{name:u.name}):void 0)??e?.agentCommands,r=s.availableModes(),i=(r.length>0?r.map(u=>{let l={id:u.id};return u.name!==void 0&&(l.name=u.name),u.description!==void 0&&(l.description=u.description),l}):void 0)??e?.agentModes,a=s.availableModels(),c=(a.length>0?a.map(u=>{let l={modelId:u.modelId};return u.name!==void 0&&(l.name=u.name),u.description!==void 0&&(l.description=u.description),l}):void 0)??e?.agentModels;return Er({sessionId:s.sessionId,lineageId:e?.lineageId??Yt(),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:Ka(s.persistableUsage)??e?.currentUsage,agentCommands:n,agentModes:i,agentModels:c,parentSessionId:s.parentSessionId??e?.parentSessionId,forkedFromSessionId:s.forkedFromSessionId??e?.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId??e?.forkedFromMessageId,originatingClient:s.originatingClient??e?.originatingClient,interactive:s.interactive??e?.interactive,priority:s.priority??e?.priority,forwardedEnv:s.forwardedEnv??e?.forwardedEnv,workspace:s.workspace,attentionFlags:s.listAttentionFlags(),extensionState:e?.extensionState,upstreamGenerations:e?Qa(e,s.agentId,s.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(s.createdAt).toISOString()})}function Ka(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 vp(s){return s?{...s}:void 0}function bp(s){return(s.extendsChain??[s.id]).some(t=>t==="claude-acp"||t.startsWith("claude-acp-"))}var Sp=[{type:"system",subtype:"background_tasks_changed"}];function zr(s,e={}){if(!bp(s))return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t,emitRawSDKMessages:Sp}}}function es(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=Ip(s,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function Jr(s){return es(s,{nestedKey:"models",configId:"model",fromObject:e=>ge(e.currentModelId)??ge(e.currentModel)??ge(e.modelId)??ge(e.model),fromConfig:e=>ge(e.currentValue)})}function Ye(s,e){if(!s||typeof s!="object")return s;let t=s;if(t.code!==A.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=A.AuthRequired,d.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function za(s){return/^[A-Za-z0-9_\-./=:@]+$/.test(s)?s:`'${s.replace(/'/g,"'\\''")}'`}function Ja(s,e,t,n){if(s&&typeof s=="object"&&s.code===A.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 ${za(n.cwd)} && ${[n.command,...n.args].map(za).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(`
169
+ `));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 rn(s){return s._meta?.steering?.supported===!0}function on(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 ge(s){if(typeof s!="string")return;let e=s.trim();return e.length>0?e:void 0}function Ip(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 Vr(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.configOptions)}function Xn(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=ge(r.id);if(!o||o==="model"||o==="mode"||o==="agent")continue;let i=kr(r.options);if(i.length===0)continue;let a=ge(r.description);t.push({id:o,name:ge(r.name)??o,...a?{description:a}:{},category:ge(r.category)??"other",type:"select",currentValue:ge(r.currentValue)??i[0].value,options:i})}return t}function Tt(s){return s.length>0?s:void 0}function Gr(s){return es(s,{nestedKey:"models",configId:"model",fromObject:e=>{let t=Kt(e.availableModels);return t.length>0?t:void 0},fromConfig:e=>{let t=Kt(e.options);return t.length>0?t:void 0}})??[]}function Kr(s){return es(s,{nestedKey:"modes",configId:"mode",fromObject:e=>{let t=_n(e.availableModes);return t.length>0?t:void 0},fromConfig:e=>{let t=_n(e.options);return t.length>0?t:void 0}})??[]}function Qr(s){return es(s,{nestedKey:"modes",configId:"mode",fromObject:e=>ge(e.currentModeId)??ge(e.currentMode)??ge(e.modeId)??ge(e.mode),fromConfig:e=>ge(e.currentValue)})}function Ap(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 Va(s){try{let e=await at.readFile(C.tuiHistoryFile(s),"utf8"),t=[];for(let n of e.split(`
170
+ `))if(n.length!==0)try{let r=JSON.parse(n);typeof r=="string"&&t.push(r)}catch{}return t}catch{return[]}}function Qa(s,e,t,n=new Date().toISOString(),r={}){let{retiredCost:o,retiredUsed:i,startedUsed:a,lifetimeCost:d,reason:c,runId:u}=r,l=m=>d!==void 0&&m.lifetimeCostAtStart!==void 0?Math.max(0,d-m.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 m=p[p.length-2];if(m){let g=l(m);p[p.length-2]={...m,...g!==void 0&&m.cost===void 0?{cost:g}:{},...i!==void 0&&m.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 m=l(f);return m!==void 0?{cost:m}:{}})(),...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 an(s){try{let e=await at.stat(C.historyFile(s));return{mtime:new Date(e.mtimeMs).toISOString(),hasContent:e.size>0}}catch{return{hasContent:!1}}}function Pt(s,e){return s.interactive!==void 0?s.interactive:s.originatingClient?.name===Vn?!1:e?!0:void 0}import{spawn as Cp}from"child_process";import*as ns from"fs";import*as ze from"fs/promises";import*as ss from"path";import Rp from"pino-roll";var ts=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_}};var xp=1e3,Ep=6e4,Yr=3e3,Mt=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??xp,this.restartCapMs=r.restartCapMs??Ep;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 ze.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()},Yr);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 cn(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");if(t.child)throw cn(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 cn(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 cn(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 cn(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{}},Yr);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 ts(this.breakerOptions),failureReason:void 0}}async reapOrphans(){let e;try{e=await ze.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 ze.readFile(n,"utf8"),i=Number.parseInt(o.trim(),10);Number.isInteger(i)&&i>0&&(r=i)}catch{}if(typeof r=="number"&&Xr(r)){try{process.kill(r,"SIGTERM")}catch{}let o=Date.now()+Yr;for(;Date.now()<o&&Xr(r);)await new Promise(i=>setTimeout(i,50));if(Xr(r))try{process.kill(r,"SIGKILL")}catch{}}await ze.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=ss.dirname(this.adapter.paths.logFile(r.name)),a;try{await ze.mkdir(i,{recursive:!0}),a=await Rp({file:ss.join(i,`${r.name}.log`),size:"5m",mkdir:!0,symlink:!0,limit:{count:5}}),a.on("error",h=>{e.failureReason=`log stream: ${h.message}`})}catch(h){if(this.stopping||e.manuallyStopped)return;e.failureReason=`log setup: ${h.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})
171
171
  `);let d=this.tokenRegistry?.mint(r.name,this.adapter.tokenRole)??n.serviceToken;e.processToken=d,e.version=void 0;let c={...vn(),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
172
- `),a.end();return}let p=ie(u),f=[...l,...r.args].map(ie),m;try{m=Ap(p,f,{env:c,stdio:["ignore","pipe","pipe"],detached:!1})}catch(h){a.write(`[hydra-acp] failed to spawn ${r.name}: ${h.message}
172
+ `),a.end();return}let p=ie(u),f=[...l,...r.args].map(ie),m;try{m=Cp(p,f,{env:c,stdio:["ignore","pipe","pipe"],detached:!1})}catch(h){a.write(`[hydra-acp] failed to spawn ${r.name}: ${h.message}
173
173
  `),a.end(),this.scheduleRestart(e,t);return}let g=h=>{try{a.write(typeof h=="string"?h:h.toString())}catch{}};if(m.stdout?.on("data",g),m.stderr?.on("data",g),typeof m.pid=="number")try{ns.writeFileSync(this.adapter.paths.pidFile(r.name),`${m.pid}
174
174
  `,{encoding:"utf8",mode:384})}catch(h){a.write(`[hydra-acp] failed to write pid file for ${r.name}: ${h.message}
175
175
  `)}e.child=m,e.logStream=a,e.pid=typeof m.pid=="number"?m.pid:void 0,e.startedAt=Date.now(),e.lastExitCode=void 0,m.on("error",h=>{a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} error: ${h.message}
176
176
  `)}),m.on("exit",(h,w)=>{try{ns.unlinkSync(this.adapter.paths.pidFile(r.name))}catch{}a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} exited code=${h??"null"} signal=${w??"null"}
177
177
  `),e.child=void 0,e.pid=void 0,e.lastExitCode=typeof h=="number"?h:void 0,e.processToken&&(this.tokenRegistry?.revoke(r.name),e.processToken=void 0);let k=e.exitWaiters.splice(0);for(let b of k)b();if(this.stopping||e.manuallyStopped){try{a.end()}catch{}e.logStream=void 0;return}e.restartCount+=1;let y=e.breaker.recordExit(h,r.name,this.adapter.kind);if(typeof y=="object"){e.failureReason=y.tripped,a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} circuit breaker tripped: ${y.tripped}
178
- `);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 Xr(s){try{return process.kill(s,0),!0}catch{return!1}}function cn(s,e){return s.code=e,s}Q();var Ep={kind:"extension",nameEnvVar:"HYDRA_ACP_EXTENSION_NAME",tokenRole:"extension",paths:{dir:C.extensionsDir,logFile:C.extensionLogFile,pidFile:C.extensionPidFile}},rs=class extends Mt{constructor(e,t,n={}){super(e,Ep,t,n)}};Q();var Tp={kind:"transformer",nameEnvVar:"HYDRA_ACP_TRANSFORMER_NAME",tokenRole:"transformer",paths:{dir:C.transformersDir,logFile:C.transformerLogFile,pidFile:C.transformerPidFile}},os=class extends Mt{connected=new Map;constructor(e,t,n={}){super(e,Tp,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 is=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{}}};Q();Q();import*as Zr from"fs/promises";async function Qa(s){await Zr.writeFile(C.pidFile(),JSON.stringify(s)+`
178
+ `);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 Xr(s){try{return process.kill(s,0),!0}catch{return!1}}function cn(s,e){return s.code=e,s}Q();var Tp={kind:"extension",nameEnvVar:"HYDRA_ACP_EXTENSION_NAME",tokenRole:"extension",paths:{dir:C.extensionsDir,logFile:C.extensionLogFile,pidFile:C.extensionPidFile}},rs=class extends Mt{constructor(e,t,n={}){super(e,Tp,t,n)}};Q();var Pp={kind:"transformer",nameEnvVar:"HYDRA_ACP_TRANSFORMER_NAME",tokenRole:"transformer",paths:{dir:C.transformersDir,logFile:C.transformerLogFile,pidFile:C.transformerPidFile}},os=class extends Mt{connected=new Map;constructor(e,t,n={}){super(e,Pp,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 is=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{}}};Q();Q();import*as Zr from"fs/promises";async function Ya(s){await Zr.writeFile(C.pidFile(),JSON.stringify(s)+`
179
179
  `,{encoding:"utf8",mode:384})}Q();import*as ln from"fs/promises";import*as as from"path";var un=s=>{process.stderr.write(s+`
180
180
  `)};function eo(s){un=s??(e=>process.stderr.write(e+`
181
- `))}async function Ya(s,e){let t=Pe();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=as.join(C.agentsDir(),t),a;try{a=await ln.readdir(i,{withFileTypes:!0})}catch(d){let c=d;if(c.code==="ENOENT")return;un(`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=as.join(i,c),f;try{f=await ln.readdir(p,{withFileTypes:!0})}catch(m){un(`hydra-acp: prune: failed to read ${p}: ${m.message}`);continue}for(let m of f){if(!m.isDirectory())continue;let g=m.name;if(g===u||l.has(g)||g.includes(".partial-"))continue;let h=as.join(p,g);try{await ln.rm(h,{recursive:!0,force:!0}),un(`hydra-acp: pruned stale ${c} ${g} (${h})`)}catch(w){un(`hydra-acp: prune: failed to remove ${h}: ${w.message}`)}}}}function Xa(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 Xs(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 to(s){let e=s.maxDeletions??200,t=(f,m)=>{s.logger&&s.logger[f](`session-gc: ${m}`)},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 g=Date.parse(f.updatedAt);Number.isFinite(g)&&(s.maxAgeMs>0&&g>r||i.push({sessionId:f.sessionId,lastUsedMs:g}))}if(i.length===0)return s.verbose&&t("info","no candidates"),{considered:0,deleted:0,failed:0,deferred:0};i.sort((f,m)=>f.lastUsedMs-m.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(m){u+=1,t("warn",`delete ${f} failed: ${m.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 ${Pp(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 Za(s){let e,t=!1,n=!1,r=o=>{t||(e=setTimeout(()=>{(async()=>{if(!n){n=!0;try{await to({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 Pp(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 Mp}from"crypto";function fn(s){if(Array.isArray(s))return s.map(fn);if(s!==null&&typeof s=="object"){let e={};for(let t of Object.keys(s).sort())e[t]=fn(s[t]);return e}return s}function ed(s){let e={};for(let[n,r]of Object.entries(s)){let o=Ms(n);if(o.nested){let i={};for(let[a,d]of Object.entries(r??{}))_s(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(fn(e));return Mp("sha256").update(t).digest("hex").slice(0,16)}function td(s,e){let t=[],n=(r,o)=>JSON.stringify(fn(r))!==JSON.stringify(fn(o));for(let r of Object.keys(e)){let o=Ms(r),i=e[r],a=s[r];if(o.nested){for(let d of Object.keys(i??{})){if(_s(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 sd from"fs/promises";Q();var _p=3e3;async function nd(){try{return(await sd.stat(C.config())).mtimeMs}catch{return}}function rd(s){let e=s.intervalMs??_p,t=!1,n,r,o=nd().then(d=>{r=d}),i=async()=>{await o;let d=await nd();if(d===r)return;r=d;let c;try{c=await Lt()}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=td(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)}}Q();Le();import*as ad from"path";import{createHash as $p,randomBytes as Op,timingSafeEqual as Fp}from"crypto";var dd="hydra_session_",Np=3600*24*30,od=12,Hp=32,jp=50;function Dp(){return ad.join(C.home(),"session-tokens.json")}function id(s){return $p("sha256").update(s).digest("hex")}function cd(s){return Op(s).toString("hex")}function Up(){return cd(od).slice(0,od*2)}function Lp(){return`${dd}${cd(Hp)}`}var ds=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=Dp(),n=await se(t);n&&Array.isArray(n.records)&&(e=n.records.filter(Bp));let r=new s(e,t);return r.sweepExpired(new Date)>0&&await r.flush(),r}async issue(e={}){let t=Lp(),n=id(t),r=Up(),o=new Date,i=e.ttlSec&&e.ttlSec>0?e.ttlSec:Np,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(dd))return;let t=id(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||!Fp(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(()=>{})},jp))}persist(){let e=(this.writeInflight??Promise.resolve()).catch(()=>{}).then(()=>ye(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 Bp(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 ud="Bearer ",cs=class{constructor(e){this.token=e}token;async validate(e){return Wp(e,this.token)?"service":void 0}rotate(e){this.token=e}},us=class{constructor(e){this.store=e}store;async validate(e){return this.store.verify(e)}},ls=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 ld(s){return async function(t,n){let r=t.headers.authorization;if(!r||!r.startsWith(ud)){n.code(401).send({error:"Missing bearer token"});return}let o=r.slice(ud.length).trim(),i=await s.validator.validate(o);if(!i){n.code(403).send({error:"Invalid token"});return}t.authIdentity=i}}function fd(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 fs=class{tokens=new Map;mint(e,t){let n=Ts();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}`}};function Wp(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 ps=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 ao from"fs";import*as Ud from"os";import*as ks from"path";import*as co from"readline";Q();function no(s){return Math.floor(s/4)}function pd(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+=dt(i.content);break;case"tool_call":case"tool_call_update":{let a=typeof i.toolCallId=="string"?i.toolCallId:"",d=qp(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 qp(s){let e=0;return typeof s.title=="string"&&(e+=s.title.length),e+=gs(s.rawInput),e+=dt(s.content),e+=gs(s.rawOutput),e}function gs(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+=gs(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+=gs(n);return t}return 0}function dt(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+=dt(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?dt(e.text):e.type==="diff"?dt(e.oldText)+dt(e.newText):e.content!==void 0?dt(e.content):0}function gd(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=no(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}Q();import{posix as zp}from"path";import Jp from"strip-ansi";function pn(s){if(!s||typeof s!="object")return;let e=s;return typeof e.workerTaskId=="string"?e.workerTaskId:void 0}var Vp=/[\x00-\x08\x0b-\x1f\x7f]/g;function Ae(s){return Jp(s).replace(Vp,"")}function te(s){return Ae(s).replace(/[\n\t]+/g," ").replace(/ +/g," ").trim()}function wd(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 eg(t);case"agent_thought_chunk":case"agent_thought":return tg(t);case"user_message_chunk":return ng(t);case"prompt_received":return sg(t);case"tool_call":return rg(t,e);case"tool_call_update":return cg(t,e);case"plan":return pg(t);case"current_mode_update":return gg(t);case"_hydra_current_model_update":return mg(t);case"turn_complete":return hg(t);case"_hydra_turn_started":return yd(t,"turn-started");case"_hydra_turn_ended":return yd(t,"turn-ended");case"usage_update":return Zp(t);case"available_commands_update":return Yp(t);case"_hydra_available_modes_update":return Xp(t);case"session_info_update":return Kp(t);case"config_option_update":return Gp(t);default:return{kind:"unknown",sessionUpdate:n,raw:s}}}function Gp(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 Kp(s){let e=ee(s,"title"),t=e!==void 0?te(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 Qp(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:te(r)};typeof n.description=="string"&&(o.description=te(n.description)),e.push(o)}return e}function Yp(s){let e=s.availableCommands??s.commands;return Array.isArray(e)?{kind:"available-commands",commands:Qp(e)}:null}function Xp(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:te(r.id)};typeof r.name=="string"&&(o.name=te(r.name)),typeof r.description=="string"&&(o.description=te(r.description)),t.push(o)}return{kind:"available-modes",modes:t}}function Zp(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 eg(s){let e=gn(s.content);return e===null?null:{kind:"agent-text",text:e,workerTaskId:pn(s)}}function tg(s){let e=typeof s.text=="string"?Ae(s.text):gn(s.content);return e===null?null:{kind:"agent-thought",text:e,workerTaskId:pn(s)}}function ng(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=gn(s.content);return t===null?null:{kind:"user-text",text:t}}function sg(s){let e=yg(s.prompt);return e===null?null:{kind:"user-text",text:e}}function kd(s){return s?s.toLowerCase().replace(/[_\s-]/g,"")==="exitplanmode":!1}function md(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 ms(s){let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let r=n;if(r.type!=="diff")continue;let o=md(r.oldText),i=md(r.newText);if(o===void 0&&i===void 0)continue;let a=typeof r.path=="string"?r.path:void 0;return{...a!==void 0?{path:a}:{},oldText:o?.text??"",newText:i?.text??"",...o?.ref?{oldRef:o.ref}:{},...i?.ref?{newRef:i.ref}:{}}}let t=s.rawInput;if(t&&typeof t=="object"&&!Array.isArray(t)){let n=t,r=typeof n.file_path=="string"?n.file_path:typeof n.path=="string"?n.path:void 0;if(typeof n.old_string=="string"&&typeof n.new_string=="string")return{...r!==void 0?{path:r}:{},oldText:n.old_string,newText:n.new_string};if(typeof n.content=="string")return{...r!==void 0?{path:r}:{},oldText:"",newText:n.content}}return null}function vd(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:Ae(t)}function rg(s,e={}){let t=ee(s,"toolCallId")??ee(s,"id");if(!t)return null;let n=ee(s,"title")??ee(s,"name")??ee(s,"label")??"tool call",r=ee(s,"name")??ee(s,"title");if(kd(r)){let m=vd(s);if(m!==null){let g=ee(s,"status"),h={kind:"exit-plan-mode",toolCallId:t,plan:m};return g!==void 0&&(h.status=g),h}}let o=Id(te(n),s,e),i=ee(s,"status"),a=ee(s,"kind"),d={kind:"tool-call",toolCallId:t,title:o};i!==void 0&&(d.status=i),a!==void 0&&(d.rawKind=a);let c=ms(s);c!==null&&(d.editDiff=c);let u=Sd(s);u!==void 0&&(d.detail=u);let l=so(s);l!==void 0&&(d.detailFull=l);let p=bd(s);p!==void 0&&(d.locations=p);let f=pn(s);return f!==void 0&&(d.workerTaskId=f),d}function bd(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 hd=64;function Sd(s){let e=so(s);if(e===void 0)return;let t=te(e),n=s.rawInput;return n&&typeof n.command=="string"?ag(t,hd):dg(t,hd)}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 Ae(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 _(te(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 _(te(n))}}}var og=["home/","Users/","root/","tmp/","var/","opt/","etc/","usr/","mnt/","private/"];function ig(s){for(let e of og)if(s.startsWith(e))return!0;return!1}function Id(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 ig(s)?_(`/${s}`):t.cwd&&t.cwd.length>0?_(zp.resolve(t.cwd,s)):s}function ag(s,e){return s.length>e?`${s.slice(0,e-1)}\u2026`:s}function dg(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 cg(s,e={}){let t=ee(s,"toolCallId")??ee(s,"id");if(!t)return null;let n=ee(s,"title"),r=n!==void 0?Id(te(n),s,e):void 0,o=ee(s,"status"),i=ms(s),a=Sd(s),d=ug(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=ee(s,"name")??n;if(kd(u)){let g={kind:"exit-plan-mode",toolCallId:t},h=vd(s);return h!==null&&(g.plan=h),o!==void 0&&(g.status=o),g}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=bd(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 g=lg(s);g!==null&&(l.errorText=g),fg(s,g)&&(l.upstreamInterrupted=!0)}let m=pn(s);return m!==void 0&&(l.workerTaskId=m),l}function ug(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 lg(s){let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let o=gn(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 Ae(n)}return null}function fg(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 pg(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"?te(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 gg(s){let e=ee(s,"currentModeId")??ee(s,"currentMode")??ee(s,"mode");return e?{kind:"mode-changed",mode:te(e)}:null}function mg(s){let e=ee(s,"currentModel")??ee(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:te(e),...n&&n.length>0?{availableModels:n}:{}}}function hg(s){let e=ee(s,"stopReason"),t=s._meta,n=t?.["hydra-acp"]?.amended!==void 0&&t["hydra-acp"].amended!==null,r={kind:"turn-complete"};return e!==void 0&&(r.stopReason=e),n&&(r.amended=!0),r}function yd(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 gn(s){if(typeof s=="string")return Ae(s);if(!s||typeof s!="object")return null;let e=s;return e.type==="text"&&typeof e.text=="string"||typeof e.text=="string"?Ae(e.text):null}function yg(s){if(!Array.isArray(s))return null;let e=[];for(let t of s){let n=gn(t);n!==null&&e.push(n)}return e.length===0?null:e.join("")}function ee(s,e){let t=s[e];return typeof t=="string"?t:void 0}function Ad(s){let e=new Map,t=new Map;for(let r of s){let i=r.params?.update;if(!i||typeof i!="object")continue;let a=i.sessionUpdate;if(a!=="tool_call"&&a!=="tool_call_update")continue;let d=typeof i.toolCallId=="string"&&i.toolCallId.length>0?i.toolCallId:void 0,c=kg(i);if(c.length===0)continue;let u=c;if(d!==void 0){let l=e.get(d)??[],p=[];for(let f of c)l.some(m=>m.path===f.path&&m.oldText===f.oldText&&m.newText===f.newText)||p.push(f);if(p.length===0)continue;e.set(d,[...l,...p]),u=p}for(let l of u)wg(t,l)}let n=[];for(let[r,o]of t)n.push({path:r,hunks:o.hunks,created:o.created});return n}function Cd(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})}return e}function wg(s,e){let t={oldText:e.oldText,newText:e.newText},n=s.get(e.path);if(n===void 0){s.set(e.path,{hunks:[t],created:e.oldText.length===0});return}n.hunks.push(t)}function kg(s){let e=[],t=s.rawInput;if(t&&typeof t=="object"&&!Array.isArray(t)){let o=t,i=typeof o.file_path=="string"?o.file_path:typeof o.path=="string"?o.path:void 0,a=o.edits;if(i!==void 0&&Array.isArray(a)){for(let d of a){if(!d||typeof d!="object")continue;let c=d,u=typeof c.old_string=="string"?c.old_string:void 0,l=typeof c.new_string=="string"?c.new_string:void 0;u===void 0||l===void 0||e.push({path:i,oldText:u,newText:l})}if(e.length>0)return e}}let n=s.content;if(Array.isArray(n)){for(let o of n){if(!o||typeof o!="object")continue;let i=o;if(i.type!=="diff")continue;let a=typeof i.path=="string"?i.path:void 0;if(a===void 0)continue;let d=typeof i.oldText=="string"?i.oldText:"",c=typeof i.newText=="string"?i.newText:"";e.push({path:a,oldText:d,newText:c})}if(e.length>0)return e}let r=ms(s);return r&&r.path&&e.push({path:r.path,oldText:r.oldText,newText:r.newText}),e}function xd(s,e={}){let t=bg(s),{events:n,window:r}=vg(t,e),o=Sg(n),i=[];Ig(i,s),r&&(r.from>1||r.to<r.total)&&(i.push(`_Showing turns ${r.from}-${r.to} of ${r.total}._`),i.push("")),Ag(i,n,o,{includeTools:e.includeTools??!1,includeThoughts:e.includeThoughts??!1});let a=i.join(`
181
+ `))}async function Xa(s,e){let t=Pe();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=as.join(C.agentsDir(),t),a;try{a=await ln.readdir(i,{withFileTypes:!0})}catch(d){let c=d;if(c.code==="ENOENT")return;un(`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=as.join(i,c),f;try{f=await ln.readdir(p,{withFileTypes:!0})}catch(m){un(`hydra-acp: prune: failed to read ${p}: ${m.message}`);continue}for(let m of f){if(!m.isDirectory())continue;let g=m.name;if(g===u||l.has(g)||g.includes(".partial-"))continue;let h=as.join(p,g);try{await ln.rm(h,{recursive:!0,force:!0}),un(`hydra-acp: pruned stale ${c} ${g} (${h})`)}catch(w){un(`hydra-acp: prune: failed to remove ${h}: ${w.message}`)}}}}function Za(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 Xs(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 to(s){let e=s.maxDeletions??200,t=(f,m)=>{s.logger&&s.logger[f](`session-gc: ${m}`)},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 g=Date.parse(f.updatedAt);Number.isFinite(g)&&(s.maxAgeMs>0&&g>r||i.push({sessionId:f.sessionId,lastUsedMs:g}))}if(i.length===0)return s.verbose&&t("info","no candidates"),{considered:0,deleted:0,failed:0,deferred:0};i.sort((f,m)=>f.lastUsedMs-m.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(m){u+=1,t("warn",`delete ${f} failed: ${m.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 ${Mp(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 ed(s){let e,t=!1,n=!1,r=o=>{t||(e=setTimeout(()=>{(async()=>{if(!n){n=!0;try{await to({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 Mp(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 _p}from"crypto";function fn(s){if(Array.isArray(s))return s.map(fn);if(s!==null&&typeof s=="object"){let e={};for(let t of Object.keys(s).sort())e[t]=fn(s[t]);return e}return s}function td(s){let e={};for(let[n,r]of Object.entries(s)){let o=Ms(n);if(o.nested){let i={};for(let[a,d]of Object.entries(r??{}))_s(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(fn(e));return _p("sha256").update(t).digest("hex").slice(0,16)}function nd(s,e){let t=[],n=(r,o)=>JSON.stringify(fn(r))!==JSON.stringify(fn(o));for(let r of Object.keys(e)){let o=Ms(r),i=e[r],a=s[r];if(o.nested){for(let d of Object.keys(i??{})){if(_s(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 rd from"fs/promises";Q();var $p=3e3;async function sd(){try{return(await rd.stat(C.config())).mtimeMs}catch{return}}function od(s){let e=s.intervalMs??$p,t=!1,n,r,o=sd().then(d=>{r=d}),i=async()=>{await o;let d=await sd();if(d===r)return;r=d;let c;try{c=await Lt()}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=nd(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)}}Q();Le();import*as dd from"path";import{createHash as Op,randomBytes as Fp,timingSafeEqual as Np}from"crypto";var cd="hydra_session_",Hp=3600*24*30,id=12,jp=32,Dp=50;function Up(){return dd.join(C.home(),"session-tokens.json")}function ad(s){return Op("sha256").update(s).digest("hex")}function ud(s){return Fp(s).toString("hex")}function Lp(){return ud(id).slice(0,id*2)}function Bp(){return`${cd}${ud(jp)}`}var ds=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=Up(),n=await se(t);n&&Array.isArray(n.records)&&(e=n.records.filter(Wp));let r=new s(e,t);return r.sweepExpired(new Date)>0&&await r.flush(),r}async issue(e={}){let t=Bp(),n=ad(t),r=Lp(),o=new Date,i=e.ttlSec&&e.ttlSec>0?e.ttlSec:Hp,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(cd))return;let t=ad(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||!Np(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(()=>{})},Dp))}persist(){let e=(this.writeInflight??Promise.resolve()).catch(()=>{}).then(()=>ye(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 Wp(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 ld="Bearer ",cs=class{constructor(e){this.token=e}token;async validate(e){return qp(e,this.token)?"service":void 0}rotate(e){this.token=e}},us=class{constructor(e){this.store=e}store;async validate(e){return this.store.verify(e)}},ls=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 fd(s){return async function(t,n){let r=t.headers.authorization;if(!r||!r.startsWith(ld)){n.code(401).send({error:"Missing bearer token"});return}let o=r.slice(ld.length).trim(),i=await s.validator.validate(o);if(!i){n.code(403).send({error:"Invalid token"});return}t.authIdentity=i}}function pd(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 fs=class{tokens=new Map;mint(e,t){let n=Ts();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}`}};function qp(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 ps=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 co from"fs";import*as Ld from"os";import*as ks from"path";import*as uo from"readline";Q();function no(s){return Math.floor(s/4)}function gd(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+=dt(i.content);break;case"tool_call":case"tool_call_update":{let a=typeof i.toolCallId=="string"?i.toolCallId:"",d=zp(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 zp(s){let e=0;return typeof s.title=="string"&&(e+=s.title.length),e+=gs(s.rawInput),e+=dt(s.content),e+=gs(s.rawOutput),e}function gs(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+=gs(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+=gs(n);return t}return 0}function dt(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+=dt(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?dt(e.text):e.type==="diff"?dt(e.oldText)+dt(e.newText):e.content!==void 0?dt(e.content):0}function md(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=no(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}Q();import{posix as Jp}from"path";import Vp from"strip-ansi";function pn(s){if(!s||typeof s!="object")return;let e=s;return typeof e.workerTaskId=="string"?e.workerTaskId:void 0}function so(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 Gp=/[\x00-\x08\x0b-\x1f\x7f]/g;function Ae(s){return Vp(s).replace(Gp,"")}function te(s){return Ae(s).replace(/[\n\t]+/g," ").replace(/ +/g," ").trim()}function kd(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 tg(t);case"agent_thought_chunk":case"agent_thought":return ng(t);case"user_message_chunk":return sg(t);case"prompt_received":return rg(t);case"tool_call":return og(t,e);case"tool_call_update":return ug(t,e);case"plan":return gg(t);case"current_mode_update":return mg(t);case"_hydra_current_model_update":return hg(t);case"turn_complete":return yg(t);case"_hydra_turn_started":return wd(t,"turn-started");case"_hydra_turn_ended":return wd(t,"turn-ended");case"usage_update":return eg(t);case"available_commands_update":return Xp(t);case"_hydra_available_modes_update":return Zp(t);case"session_info_update":return Qp(t);case"config_option_update":return Kp(t);default:return{kind:"unknown",sessionUpdate:n,raw:s}}}function Kp(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 Qp(s){let e=ee(s,"title"),t=e!==void 0?te(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 Yp(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:te(r)};typeof n.description=="string"&&(o.description=te(n.description)),e.push(o)}return e}function Xp(s){let e=s.availableCommands??s.commands;return Array.isArray(e)?{kind:"available-commands",commands:Yp(e)}:null}function Zp(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:te(r.id)};typeof r.name=="string"&&(o.name=te(r.name)),typeof r.description=="string"&&(o.description=te(r.description)),t.push(o)}return{kind:"available-modes",modes:t}}function eg(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 tg(s){let e=gn(s.content);return e===null?null:{kind:"agent-text",text:e,workerTaskId:pn(s)}}function ng(s){let e=typeof s.text=="string"?Ae(s.text):gn(s.content);return e===null?null:{kind:"agent-thought",text:e,workerTaskId:pn(s)}}function sg(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=gn(s.content);return t===null?null:{kind:"user-text",text:t}}function rg(s){let e=wg(s.prompt);return e===null?null:{kind:"user-text",text:e}}function vd(s){return s?s.toLowerCase().replace(/[_\s-]/g,"")==="exitplanmode":!1}function hd(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 ms(s){let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let r=n;if(r.type!=="diff")continue;let o=hd(r.oldText),i=hd(r.newText);if(o===void 0&&i===void 0)continue;let a=typeof r.path=="string"?r.path:void 0;return{...a!==void 0?{path:a}:{},oldText:o?.text??"",newText:i?.text??"",...o?.ref?{oldRef:o.ref}:{},...i?.ref?{newRef:i.ref}:{}}}let t=s.rawInput;if(t&&typeof t=="object"&&!Array.isArray(t)){let n=t,r=typeof n.file_path=="string"?n.file_path:typeof n.path=="string"?n.path:void 0;if(typeof n.old_string=="string"&&typeof n.new_string=="string")return{...r!==void 0?{path:r}:{},oldText:n.old_string,newText:n.new_string};if(typeof n.content=="string")return{...r!==void 0?{path:r}:{},oldText:"",newText:n.content}}return null}function bd(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:Ae(t)}function og(s,e={}){let t=ee(s,"toolCallId")??ee(s,"id");if(!t)return null;let n=ee(s,"title")??ee(s,"name")??ee(s,"label")??"tool call",r=ee(s,"name")??ee(s,"title");if(vd(r)){let g=bd(s);if(g!==null){let h=ee(s,"status"),w={kind:"exit-plan-mode",toolCallId:t,plan:g};return h!==void 0&&(w.status=h),w}}let o=Ad(te(n),s,e),i=ee(s,"status"),a=ee(s,"kind"),d={kind:"tool-call",toolCallId:t,title:o};i!==void 0&&(d.status=i),a!==void 0&&(d.rawKind=a);let c=ms(s);c!==null&&(d.editDiff=c);let u=Id(s);u!==void 0&&(d.detail=u);let l=ro(s);l!==void 0&&(d.detailFull=l);let p=Sd(s);p!==void 0&&(d.locations=p);let f=pn(s);f!==void 0&&(d.workerTaskId=f);let m=so(s);return m!==void 0&&(d.parentToolUseId=m),d}function Sd(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 yd=64;function Id(s){let e=ro(s);if(e===void 0)return;let t=te(e),n=s.rawInput;return n&&typeof n.command=="string"?dg(t,yd):cg(t,yd)}function ro(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 Ae(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 _(te(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 _(te(n))}}}var ig=["home/","Users/","root/","tmp/","var/","opt/","etc/","usr/","mnt/","private/"];function ag(s){for(let e of ig)if(s.startsWith(e))return!0;return!1}function Ad(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 ag(s)?_(`/${s}`):t.cwd&&t.cwd.length>0?_(Jp.resolve(t.cwd,s)):s}function dg(s,e){return s.length>e?`${s.slice(0,e-1)}\u2026`:s}function cg(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 ug(s,e={}){let t=ee(s,"toolCallId")??ee(s,"id");if(!t)return null;let n=ee(s,"title"),r=n!==void 0?Ad(te(n),s,e):void 0,o=ee(s,"status"),i=ms(s),a=Id(s),d=lg(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=ee(s,"name")??n;if(vd(u)){let h={kind:"exit-plan-mode",toolCallId:t},w=bd(s);return w!==null&&(h.plan=w),o!==void 0&&(h.status=o),h}let l={kind:"tool-call-update",toolCallId:t};r!==void 0&&(l.title=r),a!==void 0&&(l.detail=a);let p=ro(s);p!==void 0&&(l.detailFull=p);let f=Sd(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 h=fg(s);h!==null&&(l.errorText=h),pg(s,h)&&(l.upstreamInterrupted=!0)}let m=pn(s);m!==void 0&&(l.workerTaskId=m);let g=so(s);return g!==void 0&&(l.parentToolUseId=g),l}function lg(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 fg(s){let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let o=gn(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 Ae(n)}return null}function pg(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 gg(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"?te(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 mg(s){let e=ee(s,"currentModeId")??ee(s,"currentMode")??ee(s,"mode");return e?{kind:"mode-changed",mode:te(e)}:null}function hg(s){let e=ee(s,"currentModel")??ee(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:te(e),...n&&n.length>0?{availableModels:n}:{}}}function yg(s){let e=ee(s,"stopReason"),t=s._meta,n=t?.["hydra-acp"]?.amended!==void 0&&t["hydra-acp"].amended!==null,r={kind:"turn-complete"};return e!==void 0&&(r.stopReason=e),n&&(r.amended=!0),r}function wd(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 gn(s){if(typeof s=="string")return Ae(s);if(!s||typeof s!="object")return null;let e=s;return e.type==="text"&&typeof e.text=="string"||typeof e.text=="string"?Ae(e.text):null}function wg(s){if(!Array.isArray(s))return null;let e=[];for(let t of s){let n=gn(t);n!==null&&e.push(n)}return e.length===0?null:e.join("")}function ee(s,e){let t=s[e];return typeof t=="string"?t:void 0}function Cd(s){let e=new Map,t=new Map;for(let r of s){let i=r.params?.update;if(!i||typeof i!="object")continue;let a=i.sessionUpdate;if(a!=="tool_call"&&a!=="tool_call_update")continue;let d=typeof i.toolCallId=="string"&&i.toolCallId.length>0?i.toolCallId:void 0,c=vg(i);if(c.length===0)continue;let u=c;if(d!==void 0){let l=e.get(d)??[],p=[];for(let f of c)l.some(m=>m.path===f.path&&m.oldText===f.oldText&&m.newText===f.newText)||p.push(f);if(p.length===0)continue;e.set(d,[...l,...p]),u=p}for(let l of u)kg(t,l)}let n=[];for(let[r,o]of t)n.push({path:r,hunks:o.hunks,created:o.created});return n}function Rd(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})}return e}function kg(s,e){let t={oldText:e.oldText,newText:e.newText},n=s.get(e.path);if(n===void 0){s.set(e.path,{hunks:[t],created:e.oldText.length===0});return}n.hunks.push(t)}function vg(s){let e=[],t=s.rawInput;if(t&&typeof t=="object"&&!Array.isArray(t)){let o=t,i=typeof o.file_path=="string"?o.file_path:typeof o.path=="string"?o.path:void 0,a=o.edits;if(i!==void 0&&Array.isArray(a)){for(let d of a){if(!d||typeof d!="object")continue;let c=d,u=typeof c.old_string=="string"?c.old_string:void 0,l=typeof c.new_string=="string"?c.new_string:void 0;u===void 0||l===void 0||e.push({path:i,oldText:u,newText:l})}if(e.length>0)return e}}let n=s.content;if(Array.isArray(n)){for(let o of n){if(!o||typeof o!="object")continue;let i=o;if(i.type!=="diff")continue;let a=typeof i.path=="string"?i.path:void 0;if(a===void 0)continue;let d=typeof i.oldText=="string"?i.oldText:"",c=typeof i.newText=="string"?i.newText:"";e.push({path:a,oldText:d,newText:c})}if(e.length>0)return e}let r=ms(s);return r&&r.path&&e.push({path:r.path,oldText:r.oldText,newText:r.newText}),e}function Ed(s,e={}){let t=Sg(s),{events:n,window:r}=bg(t,e),o=Ig(n),i=[];Ag(i,s),r&&(r.from>1||r.to<r.total)&&(i.push(`_Showing turns ${r.from}-${r.to} of ${r.total}._`),i.push("")),Cg(i,n,o,{includeTools:e.includeTools??!1,includeThoughts:e.includeThoughts??!1});let a=i.join(`
182
182
  `);return a.endsWith(`
183
183
  `)||(a+=`
184
- `),a}function ro(s,e){let t=s<0?e+s+1:s;return t<1?1:t>e?e:t}function vg(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=ro(o-e.last+1,o):(e.from!==void 0&&(i=ro(e.from,o)),e.to!==void 0&&(a=ro(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,m)=>{f.recordedAt>=d&&c.add(n[m])});let u=[],l,p;return s.forEach((f,m)=>{let g=n[m];g<i||g>a||d!==void 0&&!c.has(g)||(u.push(f),l??=g,p=g)}),{events:u,window:{from:l??i,to:p??a,total:o}}}function bg(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=wd(n.update,{cwd:s.session.cwd});r!==null&&e.push({event:r,recordedAt:t.recordedAt})}return e}function Sg(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 Ig(s,e){let t=e.session,n=Be(t.sessionId),r=t.title?.trim()||`Hydra session ${n}`;s.push(`# ${mn(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?`${oo(a.size)}`:void 0;d.push(u?`${oo(a.used)} / ${u} tokens`:`${oo(a.used)} tokens`)}let c=Wr(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(`
185
- `)),s.push("")}function Ag(s,e,t,n){let{includeTools:r,includeThoughts:o}=n;if(!e.some(g=>Cg(g.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 g of c)s.push(g);s.push(""),c=[]}},f=()=>{p(),d.length>0&&(Rd(s,d.trimEnd(),"*"),s.push(""),d=""),a.length!==0&&(s.push(a.trimEnd()),s.push(""),a="")},m=()=>{l||(l=!0)};for(let{event:g}of e)switch(g.kind){case"user-text":{f(),s.push("---"),s.push(""),i+=1,Rd(s,g.text,"**"),s.push(""),l=!0;break}case"agent-text":m(),a+=g.text;break;case"agent-thought":{if(!o)break;m(),a.length>0&&(s.push(a.trimEnd()),s.push(""),a=""),d+=g.text;break}case"tool-call":{if(!r||(m(),(a.length>0||d.length>0)&&f(),u.has(g.toolCallId)))break;u.add(g.toolCallId);let h=t.get(g.toolCallId)??{title:g.title,status:g.status??"pending"};c.push(`- ${xg(h.status)} ${Rg(h)}`);break}case"tool-call-update":break;case"plan":{m(),f(),s.push("**Plan:**"),s.push("");for(let h of g.entries){let w=h.status==="completed"?"[x]":"[ ]";s.push(`- ${w} ${mn(h.content)}`)}s.push("");break}case"mode-changed":m(),f(),s.push(`_mode: ${mn(g.mode)}_`),s.push("");break;case"model-changed":m(),f(),s.push(`_model: ${mn(g.model)}_`),s.push("");break;case"turn-complete":f();break;case"usage-update":case"available-commands":case"session-info":case"unknown":break}f()}function Cg(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 Rg(s){let e=s.status,t=e==="completed"||e===void 0?"":` _(${e})_`;return`${mn(s.title)}${t}`}function xg(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 Ed=String.raw`<\/?[a-zA-Z][a-zA-Z0-9-]*(?:\s[^<>]*)?\/?>`,Eg=new RegExp(Ed);function Rd(s,e,t){if(Eg.test(e)){Tg(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(`
186
- `);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 Tg(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(`
187
- `))s.push(o);s.push(r)}function mn(s){return s.replace(new RegExp(Ed,"g"),e=>e.replace(/</g,"&lt;").replace(/>/g,"&gt;"))}function oo(s){return s.toLocaleString("en-US")}function Td(s){return s==="127.0.0.1"||s==="::1"||s==="localhost"||s==="[::1]"}function Pg(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=>Mg(u)).filter(u=>u.term.length>0);return{operator:o,terms:c}}function Mg(s){let e=/^(\w+):"([^"]*)"$/.exec(s);if(e)return{scope:Pd(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:Pd(n[1]),term:n[2].trim()}:{scope:"all",term:s.trim()}}function Pd(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 _g(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 $g=5,Og=200,ys=72,Fg=24,Ng=512;function Fd(s){return Number.isFinite(s)?Math.max(Fg,Math.min(Ng,Math.floor(s))):ys}async function Nd(s,e,t={}){let n=Pg(e);if(n.terms.length===0)return{query:e,truncated:!1,results:[]};let r=t.maxSnippetsPerSession??$g,o=t.maxSessions??Og,i=Fd(t.snippetWidth??ys),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(()=>[]),m=jg(f,n,r,i,Hg(p));if(m.snippets.length===0)continue;let g={sessionId:p.sessionId,cwd:p.cwd,status:p.status,updatedAt:p.updatedAt,totalMatches:m.totalMatches,snippets:m.snippets};p.title!==void 0&&(g.title=p.title),u.push(g)}return{query:e,truncated:l,results:u}}function Hg(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 jg(s,e,t,n=ys,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=Dg(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 Dg(s,e,t,n,r,o){let i=e.toLowerCase(),a=0,d=[],c=new Set;for(let u of s){let l=Ug(u).filter(p=>_g(t,p.kind));for(let p of l){let f=p.text.toLowerCase();if(p.kind==="edit"){let h=o?.(p.text);if(!(Md(p.text,e)||(h!==void 0&&h!==p.text?Md(h,e):!1))||c.has(p.text))continue;if(c.add(p.text),a+=1,d.length<n){let k={kind:"edit",text:p.text,recordedAt:u.recordedAt};p.toolName!==void 0&&(k.toolName=p.toolName),d.push(k)}continue}let m=f.indexOf(i);if(m===-1)continue;let g=0;for(;m!==-1;)g++,m=f.indexOf(i,m+i.length);if(a+=g,d.length<n){let h=f.indexOf(i),w={kind:p.kind,text:Vg(p.text,h,i.length,r),recordedAt:u.recordedAt};p.toolName!==void 0&&(w.toolName=p.toolName),d.push(w)}}}return{totalMatches:a,snippets:d}}function Ug(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=hs(n.content);return o?[{kind:"agent",text:o}]:[]}case"agent_thought":case"agent_thought_chunk":{let o=typeof n.text=="string"?Ae(n.text):hs(n.content);return o?[{kind:"thought",text:o}]:[]}case"user_message_chunk":{if(zg(n))return[];let o=hs(n.content);return o?[{kind:"user",text:o}]:[]}case"prompt_received":{let o=Jg(n.prompt);return o?[{kind:"user",text:o}]:[]}case"tool_call":case"tool_call_update":return Lg(n);default:return[]}}function Lg(s){let e=$d(s,"name"),t=$d(s,"title"),n=[];if(t!==void 0){let a=te(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=te(e);a.length>0&&n.push({kind:"tool",toolName:e,text:a})}let r=s.rawInput;if(r&&typeof r=="object"){let a=Od(r);if(a.length>0){let d={kind:"tool-input",text:te(a)};e!==void 0&&(d.toolName=e),n.push(d)}}for(let a of Bg(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=Od(o);if(a.length>0){let d={kind:"tool-input",text:te(a)};e!==void 0&&(d.toolName=e),n.push(d)}}let i=Wg(s);if(i!==null){let a={kind:"tool",text:i};e!==void 0&&(a.toolName=e),n.push(a)}return n}function Bg(s){let e=[],t=new Set,n=i=>{typeof i!="string"||i.length===0||t.has(i)||(t.add(i),e.push(i))},r=s.content;if(Array.isArray(r))for(let i of r){if(!i||typeof i!="object")continue;let a=i;a.type==="diff"&&n(a.path)}let o=s.rawInput;if(o&&typeof o=="object"&&!Array.isArray(o)){let i=o;(i.old_string!==void 0||i.new_string!==void 0||i.content!==void 0||Array.isArray(i.edits))&&n(typeof i.file_path=="string"?i.file_path:i.path)}return e}function Md(s,e){let t=_d(s.toLowerCase()),n=_d(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 _d(s){return s.length>1&&s.endsWith("/")?s.slice(0,-1):s}function Wg(s){if(!qg(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=te(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=te(n);if(r.length>0)return r}}return null}function qg(s){return s==="failed"||s==="rejected"||s==="cancelled"}function zg(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 hs(s){if(typeof s=="string")return Ae(s);if(!s||typeof s!="object"||Array.isArray(s))return"";let e=s;return typeof e.text=="string"?Ae(e.text):""}function Jg(s){if(!Array.isArray(s))return"";let e=[];for(let t of s){let n=hs(t);n.length>0&&e.push(n)}return e.join("")}function $d(s,e){let t=s[e];return typeof t=="string"?t:void 0}function Od(s){try{return JSON.stringify(s)}catch{return""}}function Vg(s,e,t,n=ys){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=Fd(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)),m=Math.min(r.length,a+i.length+p),g=f>0?"\u2026":"",h=m<r.length?"\u2026":"";return`${g}${r.slice(f,m)}${h}`}import{randomBytes as jd}from"crypto";function Hd(s){let e=jd(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 io(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(Hd({name:"hydra-acp-stdin",session:n,tokenRegistry:e,getOrigin:t})),r.push(Hd({name:"hydra-acp-recall",session:n,tokenRegistry:e,getOrigin:t}));let o=_t(s.deps);return o!==void 0&&(o.bindToSession(n),r=[...r,...o.descriptors]),r}}function _t(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=jd(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 ws=new Set(["usage_update","tool_call","tool_call_update","prompt_received","turn_complete","permission_resolved"]);function Dd(s){if(s.publicHost&&s.publicHost.length>0)return s.publicHost;if(s.host&&!Td(s.host))return s.port!==void 0?`${s.host}:${s.port}`:s.host}function Ld(s,e,t,n={}){s.get("/v1/sessions",async c=>{let u=c.query,l=u?.includeNonInteractive==="1"||u?.includeNonInteractive==="true",p=u?.status==="warm"||u?.status==="cold"?u.status:void 0;return{sessions:await e.list({cwd:u?.cwd,includeNonInteractive:l,...p?{status:p}:{}})}}),s.get("/v1/sessions/:id",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=await e.getOne(p);return f||(u.code(404).send({error:"session not found"}),u)}),s.post("/v1/sessions/search",async(c,u)=>{let l=c.body??{},p=typeof l.q=="string"?l.q:"";if(p.trim().length===0)return u.code(400).send({error:"q is required"}),u;let m={sessionIds:Array.isArray(l.sessionIds)?l.sessionIds.filter(h=>typeof h=="string"&&h.length>0):void 0};return typeof l.snippetWidth=="number"&&(m.snippetWidth=l.snippetWidth),await Nd(e,p,m)}),s.post("/v1/sessions",async(c,u)=>{let l=c.body??{},p=ie(l.cwd??t.cwd),f=await Ut(p),m=l.agentId??f.agentId??t.agentId,g=_t(n),h=g!==void 0?[...l.mcpServers??[],...g.descriptors]:l.mcpServers;try{let w=await e.create({cwd:p,agentId:m,mcpServers:h,...l.workspace!==void 0?{workspace:l.workspace}:{}});g!==void 0&&g.bindToSession(w),u.code(201).send({sessionId:w.sessionId,agentId:w.agentId,cwd:w.cwd,...w.workspace!==void 0?{workspace:w.workspace}:{},...w.workspaceError!==void 0?{workspaceError:w.workspaceError}:{}})}catch(w){g!==void 0&&g.abandon(w instanceof Error?w:void 0),u.code(500).send({error:w.message})}}),s.post("/v1/sessions/collect",async(c,u)=>{let l=c.body??{},p=typeof l.maxAgeDays=="number"&&l.maxAgeDays>0?l.maxAgeDays*24*60*60*1e3:0,f=typeof l.limit=="number"&&l.limit>0?l.limit:1e3,m=l.selection==="explicit"||l.selection==="unpromoted"?l.selection:"unpromoted";try{let g=await to({manager:e,maxAgeMs:p,maxDeletions:f,selection:m,verbose:!1});u.code(200).send(g)}catch(g){u.code(500).send({error:g.message})}}),s.post("/v1/sessions/:id/kill",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p);if(f){f.close({deleteRecord:!1,by:"REST POST /kill"}).catch(()=>{}),u.code(202).send();return}if(!await e.hasRecord(p)){u.code(404).send({error:"session not found"});return}u.code(204).send()}),s.post("/v1/sessions/:id/stdin/open",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p);if(!f)return u.code(404).send({error:"session not found"}),u;let m=c.body??{},g={};(m.mode==="memory"||m.mode==="file")&&(g.mode=m.mode),typeof m.capacityBytes=="number"&&(g.capacityBytes=m.capacityBytes),typeof m.fileCapBytes=="number"&&(g.fileCapBytes=m.fileCapBytes),(g.mode??"memory")==="file"&&(g.filePathFor=h=>ks.join(Ud.tmpdir(),`hydra-acp-stdin-${h}.log`));try{return f.openStream(g)}catch(h){return u.code(409).send({error:h.message}),u}}),s.post("/v1/sessions/:id/stdin",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p);if(!f)return u.code(404).send({error:"session not found"}),u;let m=c.body??{},g=typeof m.chunk=="string"?m.chunk:"",h=m.eof===!0;try{return f.streamWrite(g,h)}catch(w){return u.code(409).send({error:w.message}),u}}),s.patch("/v1/sessions/:id",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=c.body??{};if(f.cwd!==void 0){if(typeof f.cwd!="string"||!ks.isAbsolute(f.cwd)){u.code(400).send({error:"cwd must be an absolute path"});return}let g=await e.setCwd(p,f.cwd);if(g==="missing"){u.code(404).send({error:"session not found"});return}if(g==="not-a-directory"){u.code(400).send({error:`${f.cwd} is not a directory`});return}if(g==="live"){u.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(g==="bound"){u.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}u.code(204).send();return}if("workspace"in f){if(f.workspace!==null){u.code(400).send({error:"workspace may only be set to null (clear the binding)"});return}let g=await e.clearWorkspaceBinding(p);if(g==="missing"){u.code(404).send({error:"session not found"});return}if(g==="live"){u.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}u.code(204).send();return}if(f.priority!==void 0){let g=f.priority,h;if(g===null||g===0)h=void 0;else if(typeof g=="number"&&Number.isInteger(g)&&g>0)h=g;else{u.code(400).send({error:"priority must be a non-negative integer (or null to clear)"});return}if(!await e.setPriority(p,h)){u.code(404).send({error:"session not found"});return}u.code(204).send();return}if(f.regen===!0){if(!(e.get(p)!==void 0||await e.hasRecord(p))){u.code(404).send({error:"session not found"});return}e.scheduleSynopsis(p),u.code(202).send();return}if(typeof f.title!="string"||f.title.trim().length===0){u.code(400).send({error:"title must be a non-empty string"});return}if(!await e.setTitle(p,f.title)){u.code(404).send({error:"session not found"});return}u.code(204).send()}),s.delete("/v1/sessions/:id",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p);if(f){await f.close({deleteRecord:!0,by:"REST DELETE /v1/sessions"}),await e.waitForDeletion(p),await e.hasRecord(p)&&await e.deleteRecord(p),u.code(204).send();return}if(!await e.deleteRecord(p)){u.code(404).send({error:"session not found"});return}u.code(204).send()}),s.get("/v1/sessions/:id/export",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=c.query?.tools,m=f==="references"?"references":_a(f),g=await e.exportBundle(p,m==="references"?{tools:"references"}:{});if(!g){u.code(404).send({error:"session not found"});return}let h=nn({record:g.record,history:m==="summary"?$a(g.history,"summary"):g.history,promptHistory:g.promptHistory.length>0?g.promptHistory:void 0,...g.toolBlobs!==void 0?{toolBlobs:g.toolBlobs}:{},hydraVersion:ue,machine:zt(),hydraHost:Dd(t)}),w=new Date().toISOString().replace(/[:.]/g,"-");u.header("Content-Disposition",`attachment; filename="${p}-${w}.hydra"`),u.code(200).send(h)}),s.get("/v1/sessions/:id/diff",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=await e.exportBundle(p);if(!f){u.code(404).send({error:"session not found"});return}let m=c.query??{},g=m.fold==="true"||m.fold==="1",h=typeof m.paths=="string"&&m.paths.length>0?new Set(m.paths.split(",").map(k=>k.trim()).filter(k=>k.length>0)):void 0,w=Ad(f.history);h&&(w=w.filter(k=>h.has(k.path))),g&&(w=w.map(k=>({...k,hunks:Cd(k.hunks)}))),u.code(200).send(w)}),s.get("/v1/sessions/:id/tools/:hash",async(c,u)=>{let l=c.params,p=await e.resolveCanonicalId(l.id)??l.id,f=await e.loadToolBlob(p,l.hash);if(f===null){u.code(404).send({error:"tool blob not found"});return}u.header("Content-Type","text/plain; charset=utf-8"),u.code(200).send(f)}),s.get("/v1/sessions/:id/transcript",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=await e.exportBundle(p);if(!f){u.code(404).send({error:"session not found"});return}let m=nn({record:f.record,history:f.history,promptHistory:f.promptHistory.length>0?f.promptHistory:void 0,hydraVersion:ue,machine:zt(),hydraHost:Dd(t)}),g=c.query,h=y=>y==="1"||y==="true"||y==="yes",w=y=>{let b=g?.[y];if(b===void 0||b==="")return;let I=Number(b);return Number.isFinite(I)?I:"bad"},k={};for(let y of["from","to","last","since"]){let b=w(y);if(b==="bad"){u.code(400).send({error:`${y} must be a number`});return}b!==void 0&&(k[y==="since"?"sinceMs":y]=b)}u.header("Content-Type","text/markdown; charset=utf-8"),u.code(200).send(xd(m,{includeTools:h(g?.tools),includeThoughts:h(g?.thoughts),...k}))}),s.post("/v1/sessions/:id/fork",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=c.body??{},m={};if(f.forkAt!==void 0){if(typeof f.forkAt!="string"||f.forkAt.length===0){u.code(400).send({error:"forkAt must be a non-empty string"});return}m.forkAt=f.forkAt}if(f.cwd!==void 0){if(typeof f.cwd!="string"||f.cwd.length===0){u.code(400).send({error:"cwd must be a non-empty string"});return}m.cwd=ie(f.cwd)}if(f.agentId!==void 0){if(typeof f.agentId!="string"||f.agentId.length===0){u.code(400).send({error:"agentId must be a non-empty string"});return}m.agentId=f.agentId}if(f.title!==void 0){if(typeof f.title!="string"){u.code(400).send({error:"title must be a string"});return}m.title=f.title}if(f.mode!==void 0){if(f.mode!=="verbatim"&&f.mode!=="synthesis"){u.code(400).send({error:'mode must be "verbatim" or "synthesis"'});return}m.mode=f.mode}if(f.model!==void 0){if(typeof f.model!="string"||f.model.length===0){u.code(400).send({error:"model must be a non-empty string"});return}m.model=f.model}try{let g=await e.forkSession(p,m);u.code(201).send(g)}catch(g){let h=g;if(h.code===A.SessionNotFound){u.code(404).send({error:h.message});return}if(h.code===A.InvalidParams||h.code===A.AgentNotInstalled){u.code(400).send({error:h.message});return}u.code(500).send({error:h.message})}}),s.post("/v1/sessions/import",async(c,u)=>{let l=c.body??{};if(l.bundle===void 0){u.code(400).send({error:"missing bundle"});return}let p;if(l.cwd!==void 0){if(typeof l.cwd!="string"||l.cwd.length===0){u.code(400).send({error:"cwd must be a non-empty string"});return}p=l.cwd}let f;try{f=La(l.bundle)}catch(m){u.code(400).send({error:"invalid bundle",details:m.message});return}try{let m=await e.importBundle(f,{replace:l.replace===!0,...p!==void 0?{cwd:p}:{}});u.code(201).send(m)}catch(m){let g=m;if(g.code===A.BundleAlreadyImported){u.code(409).send({error:"bundle already imported",existingSessionId:g.existingSessionId});return}u.code(500).send({error:g.message})}}),s.get("/v1/sessions/:id/compact/status",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p),m;if(f?m=f.summarizedThroughEntry:m=await e.getSummarizedThroughEntry(p),m===void 0&&!await e.hasRecord(p))return u.code(404).send({error:"session not found"}),u;let g=await e.getCompactionState(p),h=await e.getRollbackBreadcrumb(p),w=await e.getPendingAgentSwap(p),k=!1,y,b=f?.currentUsage,I=typeof b?.used=="number"&&typeof b?.size=="number"&&b.size>0?{used:b.used,size:b.size}:void 0,v=await e.loadHistory(p,{tools:"references",maxEntries:1/0}).catch(()=>[]);if(v.length>0&&t.compaction){let R=m??0,x=v.length,E=R<=v.length?R:0,O=v.slice(E),T=pd(O);y=no(T);let j=f?.currentModel,W=v.at(-1).recordedAt;k=gd({summarizedThroughEntry:R,totalEntries:x,unsummarizedChars:T,compactionInFlight:e.getCompactionInFlight(),currentModel:j,lastActivityMs:W,nowMs:Date.now(),config:t.compaction,...typeof b?.used=="number"?{agentReportedUsed:b.used}:{},...typeof b?.size=="number"?{agentReportedSize:b.size}:{}})}return{summarizedThroughEntry:m??void 0,inFlight:e.getCompactionInFlight(),shouldCompact:k,...y!=null?{approxTokens:y}:{},...I!=null?{currentUsage:I}:{},...g!=null?{compactionState:g}:{},...h!=null?{rollbackBreadcrumb:h}:{},...w!=null?{pendingAgentSwap:w}:{}}}),s.post("/v1/sessions/:id/compact",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l;if(e.get(p)){e.scheduleCompaction(p),u.code(202).send({scheduled:!0});return}if(!await e.hasRecord(p)){u.code(404).send({error:"session not found"});return}e.scheduleCompaction(p),u.code(202).send({scheduled:!0})}),s.post("/v1/sessions/:id/compact/rollback",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l;if(!await e.hasRecord(p)){u.code(404).send({error:"session not found"});return}try{await e.performUncompact(p),u.code(202).send({rolledBack:!0})}catch(f){let m=f instanceof Error?f.message:String(f);u.code(409).send({error:m})}}),s.post("/v1/sessions/:id/workspace/clean",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=c.body??{};if(f.deep!==void 0&&typeof f.deep!="boolean"){u.code(400).send({error:"deep must be a boolean"});return}if(!await e.hasRecord(p)){u.code(404).send({error:"session not found"});return}if(e.get(p)===void 0){u.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 m=await e.runWorkspaceAction(p,"clean",void 0,{deep:f.deep===!0});u.code(202).send({report:m})}catch(m){u.code(409).send({error:m instanceof Error?m.message:String(m)})}}),s.get("/v1/sessions/:id/history",async(c,u)=>{let l=c.params.id,p=c.query,f=p?.follow==="1"||p?.follow==="true",m=await e.resolveCanonicalId(l)??l,g=e.get(m),h,w,k=!1,y=1e4,b=[];if(g){f&&(w=g.onBroadcast(v=>{u.raw.writableEnded||(k?u.raw.write(JSON.stringify(v)+`
184
+ `),a}function oo(s,e){let t=s<0?e+s+1:s;return t<1?1:t>e?e:t}function bg(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=oo(o-e.last+1,o):(e.from!==void 0&&(i=oo(e.from,o)),e.to!==void 0&&(a=oo(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,m)=>{f.recordedAt>=d&&c.add(n[m])});let u=[],l,p;return s.forEach((f,m)=>{let g=n[m];g<i||g>a||d!==void 0&&!c.has(g)||(u.push(f),l??=g,p=g)}),{events:u,window:{from:l??i,to:p??a,total:o}}}function Sg(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=kd(n.update,{cwd:s.session.cwd});r!==null&&e.push({event:r,recordedAt:t.recordedAt})}return e}function Ig(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 Ag(s,e){let t=e.session,n=Be(t.sessionId),r=t.title?.trim()||`Hydra session ${n}`;s.push(`# ${mn(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?`${io(a.size)}`:void 0;d.push(u?`${io(a.used)} / ${u} tokens`:`${io(a.used)} tokens`)}let c=Wr(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(`
185
+ `)),s.push("")}function Cg(s,e,t,n){let{includeTools:r,includeThoughts:o}=n;if(!e.some(g=>Rg(g.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 g of c)s.push(g);s.push(""),c=[]}},f=()=>{p(),d.length>0&&(xd(s,d.trimEnd(),"*"),s.push(""),d=""),a.length!==0&&(s.push(a.trimEnd()),s.push(""),a="")},m=()=>{l||(l=!0)};for(let{event:g}of e)switch(g.kind){case"user-text":{f(),s.push("---"),s.push(""),i+=1,xd(s,g.text,"**"),s.push(""),l=!0;break}case"agent-text":m(),a+=g.text;break;case"agent-thought":{if(!o)break;m(),a.length>0&&(s.push(a.trimEnd()),s.push(""),a=""),d+=g.text;break}case"tool-call":{if(!r||(m(),(a.length>0||d.length>0)&&f(),u.has(g.toolCallId)))break;u.add(g.toolCallId);let h=t.get(g.toolCallId)??{title:g.title,status:g.status??"pending"};c.push(`- ${Eg(h.status)} ${xg(h)}`);break}case"tool-call-update":break;case"plan":{m(),f(),s.push("**Plan:**"),s.push("");for(let h of g.entries){let w=h.status==="completed"?"[x]":"[ ]";s.push(`- ${w} ${mn(h.content)}`)}s.push("");break}case"mode-changed":m(),f(),s.push(`_mode: ${mn(g.mode)}_`),s.push("");break;case"model-changed":m(),f(),s.push(`_model: ${mn(g.model)}_`),s.push("");break;case"turn-complete":f();break;case"usage-update":case"available-commands":case"session-info":case"unknown":break}f()}function Rg(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 xg(s){let e=s.status,t=e==="completed"||e===void 0?"":` _(${e})_`;return`${mn(s.title)}${t}`}function Eg(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 Td=String.raw`<\/?[a-zA-Z][a-zA-Z0-9-]*(?:\s[^<>]*)?\/?>`,Tg=new RegExp(Td);function xd(s,e,t){if(Tg.test(e)){Pg(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(`
186
+ `);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 Pg(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(`
187
+ `))s.push(o);s.push(r)}function mn(s){return s.replace(new RegExp(Td,"g"),e=>e.replace(/</g,"&lt;").replace(/>/g,"&gt;"))}function io(s){return s.toLocaleString("en-US")}function Pd(s){return s==="127.0.0.1"||s==="::1"||s==="localhost"||s==="[::1]"}function Mg(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=>_g(u)).filter(u=>u.term.length>0);return{operator:o,terms:c}}function _g(s){let e=/^(\w+):"([^"]*)"$/.exec(s);if(e)return{scope:Md(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:Md(n[1]),term:n[2].trim()}:{scope:"all",term:s.trim()}}function Md(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 $g(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 Og=5,Fg=200,ys=72,Ng=24,Hg=512;function Nd(s){return Number.isFinite(s)?Math.max(Ng,Math.min(Hg,Math.floor(s))):ys}async function Hd(s,e,t={}){let n=Mg(e);if(n.terms.length===0)return{query:e,truncated:!1,results:[]};let r=t.maxSnippetsPerSession??Og,o=t.maxSessions??Fg,i=Nd(t.snippetWidth??ys),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(()=>[]),m=Dg(f,n,r,i,jg(p));if(m.snippets.length===0)continue;let g={sessionId:p.sessionId,cwd:p.cwd,status:p.status,updatedAt:p.updatedAt,totalMatches:m.totalMatches,snippets:m.snippets};p.title!==void 0&&(g.title=p.title),u.push(g)}return{query:e,truncated:l,results:u}}function jg(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 Dg(s,e,t,n=ys,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=Ug(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 Ug(s,e,t,n,r,o){let i=e.toLowerCase(),a=0,d=[],c=new Set;for(let u of s){let l=Lg(u).filter(p=>$g(t,p.kind));for(let p of l){let f=p.text.toLowerCase();if(p.kind==="edit"){let h=o?.(p.text);if(!(_d(p.text,e)||(h!==void 0&&h!==p.text?_d(h,e):!1))||c.has(p.text))continue;if(c.add(p.text),a+=1,d.length<n){let k={kind:"edit",text:p.text,recordedAt:u.recordedAt};p.toolName!==void 0&&(k.toolName=p.toolName),d.push(k)}continue}let m=f.indexOf(i);if(m===-1)continue;let g=0;for(;m!==-1;)g++,m=f.indexOf(i,m+i.length);if(a+=g,d.length<n){let h=f.indexOf(i),w={kind:p.kind,text:Gg(p.text,h,i.length,r),recordedAt:u.recordedAt};p.toolName!==void 0&&(w.toolName=p.toolName),d.push(w)}}}return{totalMatches:a,snippets:d}}function Lg(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=hs(n.content);return o?[{kind:"agent",text:o}]:[]}case"agent_thought":case"agent_thought_chunk":{let o=typeof n.text=="string"?Ae(n.text):hs(n.content);return o?[{kind:"thought",text:o}]:[]}case"user_message_chunk":{if(Jg(n))return[];let o=hs(n.content);return o?[{kind:"user",text:o}]:[]}case"prompt_received":{let o=Vg(n.prompt);return o?[{kind:"user",text:o}]:[]}case"tool_call":case"tool_call_update":return Bg(n);default:return[]}}function Bg(s){let e=Od(s,"name"),t=Od(s,"title"),n=[];if(t!==void 0){let a=te(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=te(e);a.length>0&&n.push({kind:"tool",toolName:e,text:a})}let r=s.rawInput;if(r&&typeof r=="object"){let a=Fd(r);if(a.length>0){let d={kind:"tool-input",text:te(a)};e!==void 0&&(d.toolName=e),n.push(d)}}for(let a of Wg(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=Fd(o);if(a.length>0){let d={kind:"tool-input",text:te(a)};e!==void 0&&(d.toolName=e),n.push(d)}}let i=qg(s);if(i!==null){let a={kind:"tool",text:i};e!==void 0&&(a.toolName=e),n.push(a)}return n}function Wg(s){let e=[],t=new Set,n=i=>{typeof i!="string"||i.length===0||t.has(i)||(t.add(i),e.push(i))},r=s.content;if(Array.isArray(r))for(let i of r){if(!i||typeof i!="object")continue;let a=i;a.type==="diff"&&n(a.path)}let o=s.rawInput;if(o&&typeof o=="object"&&!Array.isArray(o)){let i=o;(i.old_string!==void 0||i.new_string!==void 0||i.content!==void 0||Array.isArray(i.edits))&&n(typeof i.file_path=="string"?i.file_path:i.path)}return e}function _d(s,e){let t=$d(s.toLowerCase()),n=$d(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 $d(s){return s.length>1&&s.endsWith("/")?s.slice(0,-1):s}function qg(s){if(!zg(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=te(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=te(n);if(r.length>0)return r}}return null}function zg(s){return s==="failed"||s==="rejected"||s==="cancelled"}function Jg(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 hs(s){if(typeof s=="string")return Ae(s);if(!s||typeof s!="object"||Array.isArray(s))return"";let e=s;return typeof e.text=="string"?Ae(e.text):""}function Vg(s){if(!Array.isArray(s))return"";let e=[];for(let t of s){let n=hs(t);n.length>0&&e.push(n)}return e.join("")}function Od(s,e){let t=s[e];return typeof t=="string"?t:void 0}function Fd(s){try{return JSON.stringify(s)}catch{return""}}function Gg(s,e,t,n=ys){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=Nd(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)),m=Math.min(r.length,a+i.length+p),g=f>0?"\u2026":"",h=m<r.length?"\u2026":"";return`${g}${r.slice(f,m)}${h}`}import{randomBytes as Dd}from"crypto";function jd(s){let e=Dd(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 ao(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(jd({name:"hydra-acp-stdin",session:n,tokenRegistry:e,getOrigin:t})),r.push(jd({name:"hydra-acp-recall",session:n,tokenRegistry:e,getOrigin:t}));let o=_t(s.deps);return o!==void 0&&(o.bindToSession(n),r=[...r,...o.descriptors]),r}}function _t(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=Dd(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 ws=new Set(["usage_update","tool_call","tool_call_update","prompt_received","turn_complete","permission_resolved"]);function Ud(s){if(s.publicHost&&s.publicHost.length>0)return s.publicHost;if(s.host&&!Pd(s.host))return s.port!==void 0?`${s.host}:${s.port}`:s.host}function Bd(s,e,t,n={}){s.get("/v1/sessions",async c=>{let u=c.query,l=u?.includeNonInteractive==="1"||u?.includeNonInteractive==="true",p=u?.status==="warm"||u?.status==="cold"?u.status:void 0;return{sessions:await e.list({cwd:u?.cwd,includeNonInteractive:l,...p?{status:p}:{}})}}),s.get("/v1/sessions/:id",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=await e.getOne(p);return f||(u.code(404).send({error:"session not found"}),u)}),s.post("/v1/sessions/search",async(c,u)=>{let l=c.body??{},p=typeof l.q=="string"?l.q:"";if(p.trim().length===0)return u.code(400).send({error:"q is required"}),u;let m={sessionIds:Array.isArray(l.sessionIds)?l.sessionIds.filter(h=>typeof h=="string"&&h.length>0):void 0};return typeof l.snippetWidth=="number"&&(m.snippetWidth=l.snippetWidth),await Hd(e,p,m)}),s.post("/v1/sessions",async(c,u)=>{let l=c.body??{},p=ie(l.cwd??t.cwd),f=await Ut(p),m=l.agentId??f.agentId??t.agentId,g=_t(n),h=g!==void 0?[...l.mcpServers??[],...g.descriptors]:l.mcpServers;try{let w=await e.create({cwd:p,agentId:m,mcpServers:h,...l.workspace!==void 0?{workspace:l.workspace}:{}});g!==void 0&&g.bindToSession(w),u.code(201).send({sessionId:w.sessionId,agentId:w.agentId,cwd:w.cwd,...w.workspace!==void 0?{workspace:w.workspace}:{},...w.workspaceError!==void 0?{workspaceError:w.workspaceError}:{}})}catch(w){g!==void 0&&g.abandon(w instanceof Error?w:void 0),u.code(500).send({error:w.message})}}),s.post("/v1/sessions/collect",async(c,u)=>{let l=c.body??{},p=typeof l.maxAgeDays=="number"&&l.maxAgeDays>0?l.maxAgeDays*24*60*60*1e3:0,f=typeof l.limit=="number"&&l.limit>0?l.limit:1e3,m=l.selection==="explicit"||l.selection==="unpromoted"?l.selection:"unpromoted";try{let g=await to({manager:e,maxAgeMs:p,maxDeletions:f,selection:m,verbose:!1});u.code(200).send(g)}catch(g){u.code(500).send({error:g.message})}}),s.post("/v1/sessions/:id/kill",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p);if(f){f.close({deleteRecord:!1,by:"REST POST /kill"}).catch(()=>{}),u.code(202).send();return}if(!await e.hasRecord(p)){u.code(404).send({error:"session not found"});return}u.code(204).send()}),s.post("/v1/sessions/:id/stdin/open",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p);if(!f)return u.code(404).send({error:"session not found"}),u;let m=c.body??{},g={};(m.mode==="memory"||m.mode==="file")&&(g.mode=m.mode),typeof m.capacityBytes=="number"&&(g.capacityBytes=m.capacityBytes),typeof m.fileCapBytes=="number"&&(g.fileCapBytes=m.fileCapBytes),(g.mode??"memory")==="file"&&(g.filePathFor=h=>ks.join(Ld.tmpdir(),`hydra-acp-stdin-${h}.log`));try{return f.openStream(g)}catch(h){return u.code(409).send({error:h.message}),u}}),s.post("/v1/sessions/:id/stdin",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p);if(!f)return u.code(404).send({error:"session not found"}),u;let m=c.body??{},g=typeof m.chunk=="string"?m.chunk:"",h=m.eof===!0;try{return f.streamWrite(g,h)}catch(w){return u.code(409).send({error:w.message}),u}}),s.patch("/v1/sessions/:id",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=c.body??{};if(f.cwd!==void 0){if(typeof f.cwd!="string"||!ks.isAbsolute(f.cwd)){u.code(400).send({error:"cwd must be an absolute path"});return}let g=await e.setCwd(p,f.cwd);if(g==="missing"){u.code(404).send({error:"session not found"});return}if(g==="not-a-directory"){u.code(400).send({error:`${f.cwd} is not a directory`});return}if(g==="live"){u.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(g==="bound"){u.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}u.code(204).send();return}if("workspace"in f){if(f.workspace!==null){u.code(400).send({error:"workspace may only be set to null (clear the binding)"});return}let g=await e.clearWorkspaceBinding(p);if(g==="missing"){u.code(404).send({error:"session not found"});return}if(g==="live"){u.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}u.code(204).send();return}if(f.priority!==void 0){let g=f.priority,h;if(g===null||g===0)h=void 0;else if(typeof g=="number"&&Number.isInteger(g)&&g>0)h=g;else{u.code(400).send({error:"priority must be a non-negative integer (or null to clear)"});return}if(!await e.setPriority(p,h)){u.code(404).send({error:"session not found"});return}u.code(204).send();return}if(f.regen===!0){if(!(e.get(p)!==void 0||await e.hasRecord(p))){u.code(404).send({error:"session not found"});return}e.scheduleSynopsis(p),u.code(202).send();return}if(typeof f.title!="string"||f.title.trim().length===0){u.code(400).send({error:"title must be a non-empty string"});return}if(!await e.setTitle(p,f.title)){u.code(404).send({error:"session not found"});return}u.code(204).send()}),s.delete("/v1/sessions/:id",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p);if(f){await f.close({deleteRecord:!0,by:"REST DELETE /v1/sessions"}),await e.waitForDeletion(p),await e.hasRecord(p)&&await e.deleteRecord(p),u.code(204).send();return}if(!await e.deleteRecord(p)){u.code(404).send({error:"session not found"});return}u.code(204).send()}),s.get("/v1/sessions/:id/export",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=c.query?.tools,m=f==="references"?"references":$a(f),g=await e.exportBundle(p,m==="references"?{tools:"references"}:{});if(!g){u.code(404).send({error:"session not found"});return}let h=nn({record:g.record,history:m==="summary"?Oa(g.history,"summary"):g.history,promptHistory:g.promptHistory.length>0?g.promptHistory:void 0,...g.toolBlobs!==void 0?{toolBlobs:g.toolBlobs}:{},hydraVersion:ue,machine:zt(),hydraHost:Ud(t)}),w=new Date().toISOString().replace(/[:.]/g,"-");u.header("Content-Disposition",`attachment; filename="${p}-${w}.hydra"`),u.code(200).send(h)}),s.get("/v1/sessions/:id/diff",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=await e.exportBundle(p);if(!f){u.code(404).send({error:"session not found"});return}let m=c.query??{},g=m.fold==="true"||m.fold==="1",h=typeof m.paths=="string"&&m.paths.length>0?new Set(m.paths.split(",").map(k=>k.trim()).filter(k=>k.length>0)):void 0,w=Cd(f.history);h&&(w=w.filter(k=>h.has(k.path))),g&&(w=w.map(k=>({...k,hunks:Rd(k.hunks)}))),u.code(200).send(w)}),s.get("/v1/sessions/:id/tools/:hash",async(c,u)=>{let l=c.params,p=await e.resolveCanonicalId(l.id)??l.id,f=await e.loadToolBlob(p,l.hash);if(f===null){u.code(404).send({error:"tool blob not found"});return}u.header("Content-Type","text/plain; charset=utf-8"),u.code(200).send(f)}),s.get("/v1/sessions/:id/transcript",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=await e.exportBundle(p);if(!f){u.code(404).send({error:"session not found"});return}let m=nn({record:f.record,history:f.history,promptHistory:f.promptHistory.length>0?f.promptHistory:void 0,hydraVersion:ue,machine:zt(),hydraHost:Ud(t)}),g=c.query,h=y=>y==="1"||y==="true"||y==="yes",w=y=>{let b=g?.[y];if(b===void 0||b==="")return;let I=Number(b);return Number.isFinite(I)?I:"bad"},k={};for(let y of["from","to","last","since"]){let b=w(y);if(b==="bad"){u.code(400).send({error:`${y} must be a number`});return}b!==void 0&&(k[y==="since"?"sinceMs":y]=b)}u.header("Content-Type","text/markdown; charset=utf-8"),u.code(200).send(Ed(m,{includeTools:h(g?.tools),includeThoughts:h(g?.thoughts),...k}))}),s.post("/v1/sessions/:id/fork",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=c.body??{},m={};if(f.forkAt!==void 0){if(typeof f.forkAt!="string"||f.forkAt.length===0){u.code(400).send({error:"forkAt must be a non-empty string"});return}m.forkAt=f.forkAt}if(f.cwd!==void 0){if(typeof f.cwd!="string"||f.cwd.length===0){u.code(400).send({error:"cwd must be a non-empty string"});return}m.cwd=ie(f.cwd)}if(f.agentId!==void 0){if(typeof f.agentId!="string"||f.agentId.length===0){u.code(400).send({error:"agentId must be a non-empty string"});return}m.agentId=f.agentId}if(f.title!==void 0){if(typeof f.title!="string"){u.code(400).send({error:"title must be a string"});return}m.title=f.title}if(f.mode!==void 0){if(f.mode!=="verbatim"&&f.mode!=="synthesis"){u.code(400).send({error:'mode must be "verbatim" or "synthesis"'});return}m.mode=f.mode}if(f.model!==void 0){if(typeof f.model!="string"||f.model.length===0){u.code(400).send({error:"model must be a non-empty string"});return}m.model=f.model}try{let g=await e.forkSession(p,m);u.code(201).send(g)}catch(g){let h=g;if(h.code===A.SessionNotFound){u.code(404).send({error:h.message});return}if(h.code===A.InvalidParams||h.code===A.AgentNotInstalled){u.code(400).send({error:h.message});return}u.code(500).send({error:h.message})}}),s.post("/v1/sessions/import",async(c,u)=>{let l=c.body??{};if(l.bundle===void 0){u.code(400).send({error:"missing bundle"});return}let p;if(l.cwd!==void 0){if(typeof l.cwd!="string"||l.cwd.length===0){u.code(400).send({error:"cwd must be a non-empty string"});return}p=l.cwd}let f;try{f=Ba(l.bundle)}catch(m){u.code(400).send({error:"invalid bundle",details:m.message});return}try{let m=await e.importBundle(f,{replace:l.replace===!0,...p!==void 0?{cwd:p}:{}});u.code(201).send(m)}catch(m){let g=m;if(g.code===A.BundleAlreadyImported){u.code(409).send({error:"bundle already imported",existingSessionId:g.existingSessionId});return}u.code(500).send({error:g.message})}}),s.get("/v1/sessions/:id/compact/status",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p),m;if(f?m=f.summarizedThroughEntry:m=await e.getSummarizedThroughEntry(p),m===void 0&&!await e.hasRecord(p))return u.code(404).send({error:"session not found"}),u;let g=await e.getCompactionState(p),h=await e.getRollbackBreadcrumb(p),w=await e.getPendingAgentSwap(p),k=!1,y,b=f?.currentUsage,I=typeof b?.used=="number"&&typeof b?.size=="number"&&b.size>0?{used:b.used,size:b.size}:void 0,v=await e.loadHistory(p,{tools:"references",maxEntries:1/0}).catch(()=>[]);if(v.length>0&&t.compaction){let R=m??0,x=v.length,E=R<=v.length?R:0,O=v.slice(E),T=gd(O);y=no(T);let j=f?.currentModel,W=v.at(-1).recordedAt;k=md({summarizedThroughEntry:R,totalEntries:x,unsummarizedChars:T,compactionInFlight:e.getCompactionInFlight(),currentModel:j,lastActivityMs:W,nowMs:Date.now(),config:t.compaction,...typeof b?.used=="number"?{agentReportedUsed:b.used}:{},...typeof b?.size=="number"?{agentReportedSize:b.size}:{}})}return{summarizedThroughEntry:m??void 0,inFlight:e.getCompactionInFlight(),shouldCompact:k,...y!=null?{approxTokens:y}:{},...I!=null?{currentUsage:I}:{},...g!=null?{compactionState:g}:{},...h!=null?{rollbackBreadcrumb:h}:{},...w!=null?{pendingAgentSwap:w}:{}}}),s.post("/v1/sessions/:id/compact",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l;if(e.get(p)){e.scheduleCompaction(p),u.code(202).send({scheduled:!0});return}if(!await e.hasRecord(p)){u.code(404).send({error:"session not found"});return}e.scheduleCompaction(p),u.code(202).send({scheduled:!0})}),s.post("/v1/sessions/:id/compact/rollback",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l;if(!await e.hasRecord(p)){u.code(404).send({error:"session not found"});return}try{await e.performUncompact(p),u.code(202).send({rolledBack:!0})}catch(f){let m=f instanceof Error?f.message:String(f);u.code(409).send({error:m})}}),s.post("/v1/sessions/:id/workspace/clean",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=c.body??{};if(f.deep!==void 0&&typeof f.deep!="boolean"){u.code(400).send({error:"deep must be a boolean"});return}if(!await e.hasRecord(p)){u.code(404).send({error:"session not found"});return}if(e.get(p)===void 0){u.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 m=await e.runWorkspaceAction(p,"clean",void 0,{deep:f.deep===!0});u.code(202).send({report:m})}catch(m){u.code(409).send({error:m instanceof Error?m.message:String(m)})}}),s.get("/v1/sessions/:id/history",async(c,u)=>{let l=c.params.id,p=c.query,f=p?.follow==="1"||p?.follow==="true",m=await e.resolveCanonicalId(l)??l,g=e.get(m),h,w,k=!1,y=1e4,b=[];if(g){f&&(w=g.onBroadcast(v=>{u.raw.writableEnded||(k?u.raw.write(JSON.stringify(v)+`
188
188
  `):(b.push(v),b.length>y&&b.shift()))})),c.raw.on("close",()=>{w?.(),u.raw.writableEnded||u.raw.end()});try{h=await g.getHistorySnapshot()}catch(v){throw w?.(),v}}else{let v=await e.getHistory(m);if(v===void 0)return u.code(404).send({error:"session not found"}),u;h=v}u.raw.setHeader("Content-Type","application/x-ndjson"),u.raw.setHeader("Cache-Control","no-cache"),u.raw.statusCode=200;let I=new Set;for(let v of h??[]){u.raw.write(JSON.stringify(v)+`
189
189
  `);let R=v;typeof R.recordedAt=="number"&&I.add(String(R.recordedAt))}for(;b.length>0;){let v=b.splice(0,b.length);for(let R of v){let x=R,E=typeof x.recordedAt=="number"?String(x.recordedAt):"";E&&I.has(E)||u.raw.write(JSON.stringify(R)+`
190
- `)}}return k=!0,w||u.raw.end(),u});function r(c,u,l){let p=typeof c=="string"?c.trim():"";if(p.length===0)return null;let f;try{f=JSON.parse(p)}catch{return console.debug("events endpoint: skipping malformed JSONL line"),null}if(!f||typeof f!="object"||Array.isArray(f))return console.debug("events endpoint: skipping non-object JSONL line"),null;let m=f;if(typeof m.recordedAt!="number"||l!==void 0&&m.recordedAt<l||typeof m.params!="object"||m.params===null||Array.isArray(m.params))return null;let g=m.params;if(typeof g.update!="object"||g.update===null||Array.isArray(g.update))return null;let w=g.update.sessionUpdate;return typeof w!="string"||!u.has(w)?null:{recordedAt:m.recordedAt,entry:f}}function o(c,u,l){let f=u.params.update,m={sessionId:c,ts:new Date(u.recordedAt).toISOString(),kind:l,update:f};return f.messageId!==void 0&&f.messageId!==null&&(m.messageId=f.messageId),m}async function*i(c,u,l,p){for await(let f of u){let m=r(f,l,p);if(m){let g=m.entry.params.update.sessionUpdate;yield{ts:m.recordedAt,row:o(c,m.entry,g)}}}}async function a(c,u,l,p){let f=co.createInterface({input:ao.createReadStream(u),crlfDelay:1/0}),m=i(c,f,l,p),g=await m.next(),h=g.done?null:g.value;return{sessionId:c,rl:f,gen:m,current:h,exhausted:h===null}}async function d(c){let u=await c.gen.next();u.done?(c.exhausted=!0,c.current=null):c.current=u.value}s.get("/v1/sessions/events",async(c,u)=>{let l=c.query,p=l.kinds;if(!p||p.trim().length===0)return u.code(400).send({error:"kinds parameter is required"}),u;let f=p.split(",").map(y=>y.trim());if(f.length===0)return u.code(400).send({error:"kinds parameter is required"}),u;for(let y of f)if(!ws.has(y))return u.code(400).send({error:`kind "${y}" is not queryable; allowed kinds: ${[...ws].join(", ")}`}),u;let m=new Set(f),g;if(l.since!==void 0&&l.since.trim().length>0){let y=new Date(l.since);if(isNaN(y.getTime()))return u.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),u;g=y.getTime()}let h=await e.list({includeNonInteractive:!0}),w=g!==void 0?h.filter(y=>new Date(y.updatedAt).getTime()>=g):h;u.raw.setHeader("content-type","application/x-ndjson"),u.raw.statusCode=200;let k=[];for(let y of w)try{let b=C.historyFile(y.sessionId),I=await a(y.sessionId,b,m,g);I.exhausted||k.push(I)}catch(b){if(b.code==="ENOENT")continue;throw b}c.raw.on("close",()=>{for(let y of k)try{y.rl.close()}catch{}u.raw.writableEnded||u.raw.end()});try{for(;k.length>0;){let y=-1,b=1/0;for(let v=0;v<k.length;v++){let R=k[v];R.current!==null&&R.current.ts<b&&(b=R.current.ts,y=v)}if(y===-1)break;let I=k[y];if(u.raw.write(JSON.stringify(I.current.row)+`
191
- `),await d(I),I.exhausted){try{I.rl.close()}catch{}k.splice(y,1)}}}catch(y){for(let b of k)try{b.rl.close()}catch{}throw y}return u.raw.end(),u}),s.get("/v1/sessions/:id/events",async(c,u)=>{let l=c.params.id,p=c.query,f=await e.resolveCanonicalId(l)??l;if(!e.get(f)&&!await e.hasRecord(f))return u.code(404).send({error:"session not found"}),u;let g=p.kinds;if(!g||g.trim().length===0)return u.code(400).send({error:"kinds parameter is required"}),u;let h=g.split(",").map(v=>v.trim());if(h.length===0)return u.code(400).send({error:"kinds parameter is required"}),u;for(let v of h)if(!ws.has(v))return u.code(400).send({error:`kind "${v}" is not queryable; allowed kinds: ${[...ws].join(", ")}`}),u;let w=new Set(h),k;if(p.since!==void 0&&p.since.trim().length>0){let v=new Date(p.since);if(isNaN(v.getTime()))return u.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),u;k=v.getTime()}let y=C.historyFile(f),b=ao.createReadStream(y),I=co.createInterface({input:b,crlfDelay:1/0});u.raw.setHeader("content-type","application/x-ndjson"),u.raw.statusCode=200;try{for await(let v of I){let R=typeof v=="string"?v.trim():"";if(R.length===0)continue;let x;try{x=JSON.parse(R)}catch{console.debug("events endpoint: skipping malformed JSONL line in %s",y);continue}if(!x||typeof x!="object"||Array.isArray(x)){console.debug("events endpoint: skipping non-object JSONL line in %s",y);continue}let E=x;if(typeof E.recordedAt!="number"||typeof E.params!="object"||E.params===null||Array.isArray(E.params))continue;let O=E.params;if(typeof O.update!="object"||O.update===null||Array.isArray(O.update))continue;let T=O.update,j=T.sessionUpdate;if(typeof j!="string"||!w.has(j)||k!==void 0&&E.recordedAt<k)continue;let W={ts:new Date(E.recordedAt).toISOString(),kind:j,update:T};T.messageId!==void 0&&T.messageId!==null&&(W.messageId=T.messageId),u.raw.write(JSON.stringify(W)+`
192
- `)}}catch(v){if(v.code==="ENOENT")return u.raw.end(),u;throw v}return u.raw.end(),u}),s.post("/v1/sessions/:id/prompt/:messageId/notify",async(c,u)=>{let l=c.params,p=l.id,f=await e.resolveCanonicalId(p)??p,m=l.messageId,g=c.body,h=typeof g?.callbackUrl=="string"?g.callbackUrl:"",w=typeof g?.secret=="string"?g.secret:"";if(!m||!h||!w){u.code(400).send({error:"messageId, callbackUrl, and secret are all required"});return}let k;try{k=new URL(h)}catch{u.code(400).send({error:"callbackUrl must be a valid absolute URL"});return}if(k.protocol!=="https:"&&k.protocol!=="http:"){u.code(400).send({error:"callbackUrl must be http or https"});return}let y=e.get(f);if(!y){u.code(404).send({error:"session not found or not warm"});return}let b=y.registerTurnNotify(m,h,w);if(b.alreadyTerminal){u.code(200).send({status:"already_terminal",stopReason:b.stopReason});return}u.code(202).send({status:"registered"})}),s.get("/v1/sessions/:id/attention",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p);return!f&&!await e.hasRecord(p)?(u.code(404).send({error:"session not found"}),u):f?{flags:f.listAttentionFlags()}:{flags:(await e.store.read(p))?.attentionFlags??[]}}),s.get("/v1/sessions/attention",async(c,u)=>{let l=c.query;if(!l.source||l.source.trim().length===0)return u.code(400).send({error:"source query parameter is required"}),u;let p=await e.list({includeNonInteractive:!0}),f=[];for(let m of p){let g=e.get(m.sessionId),h;g?h=g.listAttentionFlags():h=(await e.store.read(m.sessionId))?.attentionFlags??[];for(let w of h)w.source===l.source&&f.push({...w,sessionId:m.sessionId})}return{flags:f}}),s.post("/v1/sessions/:id/attention/clear",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,m=c.body??{},g=typeof m.source=="string"?m.source:"",h=typeof m.reason=="string"?m.reason:"";if((g.length>0||h.length>0)&&!(g.length>0&&h.length>0)){u.code(400).send({error:"both source and reason are required to clear a specific flag, or omit both to clear all"});return}g.length===0&&h.length;let w=e.get(p);if(w){if(g.length>0&&h.length>0)w.clearAttentionFlag(g,h);else{let v=Array.from(w.listAttentionFlags()).map(R=>`${R.source}::${R.reason}`);for(let R of v)w.clearAttentionFlag(R.split("::")[0],R.split("::").slice(1).join("::"))}u.code(204).send();return}if(!await e.hasRecord(p)){u.code(404).send({error:"session not found"});return}let k=e.store,y=await k.read(p);if(!y){u.code(404).send({error:"session not found"});return}let b=y.attentionFlags??[],I;if(g.length>0&&h.length>0){let v=`${g}::${h}`;I=b.filter(R=>`${R.source}::${R.reason}`!==v)}else I=[];if(I.length===b.length&&I.every((v,R)=>v.source===b[R].source&&v.reason===b[R].reason)){u.code(204).send();return}await k.write({...y,attentionFlags:I}),u.code(204).send()})}function Bd(s,e,t,n={}){s.get("/v1/agents",async()=>mt(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 Ie(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===A.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}Q();function Wd(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:C.home(),driftedKeys:n()}))}var Gg=/^[A-Za-z0-9._-]+$/;function vs(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=Kg(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){hn(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){hn(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){hn(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){hn(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){hn(i,d)}})}function hn(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 Kg(s){let e=s.name;if(typeof e!="string"||!Gg.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 qd(s,e){vs(s,"extension",e)}function zd(s,e){vs(s,"transformer",e)}function Jd(s,e){s.get("/v1/config",async()=>e())}import{z as Xe}from"zod";Q();import*as $t from"fs/promises";import*as Vd from"path";import{randomBytes as Kb,scrypt as Qg,timingSafeEqual as Yg}from"crypto";import{promisify as Xg}from"util";var Zg=Xg(Qg);function Gd(){return Vd.join(C.home(),"password-hash")}var em=128*1024*1024;async function Kd(){try{return(await $t.readFile(Gd(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function Qd(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await $t.readFile(Gd(),"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 Zg(s,i,a.length,{N:n,r,p:o,maxmem:em});return d.length!==a.length?!1:Yg(d,a)}var tm=Xe.object({password:Xe.string().min(1),label:Xe.string().min(1).max(256).optional(),ttlSec:Xe.number().int().positive().optional()}),nm=Xe.object({id:Xe.string().optional()}).optional(),sm=Xe.object({token:Xe.string().min(32)});function Yd(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=rm(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=tm.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await Kd())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await Qd(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=nm.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=sm.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 rm(s){return s.ip||"unknown"}import{nanoid as uo}from"nanoid";function Xd(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:A.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())}}}import{randomBytes as sc}from"crypto";import*as rc from"os";import*as oc from"path";var om=200;function im(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e[pe];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,om)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function Zd(s,e,t){let n=im(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 ec(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 tc(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 $(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function lm(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 ve(s,e,t){let n=s.get(e);if(!n)throw $(A.SessionNotFound,t??`session ${e} not found`);return n}async function ct(s,e){let t=_t(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=sc(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=io({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 bm(c,s),ac(c.sessionId,s),c}function ic(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=fd({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=Xd(t),a=new yt(i),d={clientId:`hydra_client_${uo(12)}`,processIdentity:o,attached:new Map};a.onClose(()=>{for(let l of d.attached.values())e.manager.get(l.sessionId)?.detach(l.clientId);d.attached.clear()});let c=(l,p)=>{if(d.attached.get(l)?.readonly)throw $(A.PermissionDenied,`${p} not permitted on a read-only attachment`)};if(a.onRequest("initialize",async l=>{let p=si.parse(l??{});p.clientInfo?.name&&(d.clientInfo={name:p.clientInfo.name,...p.clientInfo.version!==void 0?{version:p.clientInfo.version}:{}});let f=p.clientInfo?.version;return f&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,f):e.onTransformerVersion?.(o.name,f)),vm()}),o&&e.extensionCommands){let l=e.extensionCommands;a.onRequest("hydra-acp/commands/register",async p=>{let f=p??{},m=Array.isArray(f.commands)?f.commands.map(g=>{if(!g||typeof g!="object")return;let h=g;if(typeof h.verb!="string")return;let w={verb:h.verb};return typeof h.argsHint=="string"&&(w.argsHint=h.argsHint),typeof h.description=="string"&&(w.description=h.description),w}).filter(g=>g!==void 0):[];return l.register(o.name,a,m),{ok:!0,registered:m.length}}),a.onClose(()=>{l.clear(o.name)})}if(o&&e.extensionMcp){let l=e.extensionMcp;a.onRequest("hydra-acp/mcp_tools/register",async f=>{let m=f??{},g=typeof m.instructions=="string"?m.instructions:void 0,h=Array.isArray(m.tools)?m.tools.map(w=>{if(!w||typeof w!="object")return;let k=w;if(typeof k.name!="string"||k.name.length===0||typeof k.description!="string"||k.inputSchema===null||typeof k.inputSchema!="object")return;let y={name:k.name,description:k.description,inputSchema:k.inputSchema};return k.outputSchema!==null&&typeof k.outputSchema=="object"&&(y.outputSchema=k.outputSchema),y}).filter(w=>w!==void 0):[];if(h.length===0)throw new Error("register_mcp_tools requires at least one tool");return l.register(o.name,a,g,h),{ok:!0,registered:h.length}});let p=f=>{let m=f??{};if(typeof m.sessionId!="string"||m.sessionId.length===0)throw $(A.InvalidParams,"sessionId is required");return m.sessionId};if(a.onRequest("hydra-acp/session/extension_state/get",async f=>{let m=p(f),g=f??{};if(typeof g.key!="string"||g.key.length===0)throw $(A.InvalidParams,"key is required");if(!e.manager)throw $(A.InternalError,"manager not wired");return{value:await e.manager.getExtensionStateKey(m,o.name,g.key)??null}}),a.onRequest("hydra-acp/session/extension_state/list",async f=>{let m=p(f);if(!e.manager)throw $(A.InternalError,"manager not wired");return{state:await e.manager.getExtensionState(m,o.name)}}),a.onRequest("hydra-acp/session/extension_state/set",async f=>{let m=p(f),g=f??{};if(typeof g.key!="string"||g.key.length===0)throw $(A.InvalidParams,"key is required");if(g.value===void 0)throw $(A.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw $(A.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(m,o.name,g.key,g.value)}catch(h){throw $(A.InvalidParams,h.message)}return{ok:!0}}),a.onRequest("hydra-acp/session/extension_state/delete",async f=>{let m=p(f),g=f??{};if(typeof g.key!="string"||g.key.length===0)throw $(A.InvalidParams,"key is required");if(!e.manager)throw $(A.InternalError,"manager not wired");return await e.manager.deleteExtensionStateKey(m,o.name,g.key),{ok:!0}}),e.extensionMcpControls){let f=e.extensionMcpControls;a.onRequest("hydra-acp/mcp_tools/refresh_session",async m=>{let g=m??{};if(typeof g.sessionId!="string"||g.sessionId.length===0)throw $(A.InvalidParams,"refresh_session requires sessionId");return await f.notifyToolListChanged(g.sessionId,o.name),{ok:!0}})}a.onClose(()=>{l.clear(o.name)})}if(o?.kind==="transformer"){a.onRequest("hydra-acp/transformer/initialize",async p=>{let f=p??{},m=Array.isArray(f.intercepts)?f.intercepts.filter(g=>typeof g=="string"):[];if(e.transformers&&(e.transformers.registerConnection(o.name,a,m),e.manager?.defaultTransformers.includes(o.name))){let g=e.transformers.resolveChain([o.name])[0];if(g)for(let h of e.manager.liveSessions())h.addTransformer(g)}return{ack:!0}}),a.onClose(()=>{e.transformers?.deregisterConnection(o.name)}),a.onRequest("hydra-acp/message/emit",async p=>{let f=p??{},m=typeof f.sessionId=="string"?f.sessionId:void 0,g=typeof f.method=="string"?f.method:void 0,h=f.envelope,w=f.route;if(!m)throw $(-32602,"emit_message requires sessionId");if(!g&&w!=="client_broadcast")throw $(-32602,"emit_message requires method");let k=ve(e.manager,m),y=typeof f.respondsTo=="string"?f.respondsTo:void 0;if(y)return k.dischargeClaim(y,h),{ok:!0};if(w==="chain")return{ok:!0,response:await k.emitToChain(o.name,g,h)};if(w==="queue"){if(g!=="session/prompt")throw $(-32602,'route "queue" only supports method "session/prompt"');return{ok:!0,response:await k.emitToQueue(o.name,h)}}if(w==="daemon")return{ok:!0,response:await k.emitToChain(o.name,g,h)};if(w==="client_broadcast"){if(!h||typeof h!="object")throw $(-32602,"client_broadcast requires an envelope object");return k.broadcastClientUpdate(h),{ok:!0}}throw $(-32602,`unsupported route: ${JSON.stringify(w)}`)}),a.onRequest("hydra-acp/session/request_permission",async p=>{let f=p??{},m=typeof f.sessionId=="string"?f.sessionId:void 0;if(!m)throw $(-32602,"hydra-acp/session/request_permission requires sessionId");return ve(e.manager,m).requestPermissionFromClients(f)}),a.onRequest("hydra-acp/transformer/attach",async p=>hm(p,o.name,e)),a.onRequest("hydra-acp/child_session/spawn",async p=>{let f=p??{},m=typeof f.agentId=="string"?f.agentId:void 0,g=typeof f.cwd=="string"?f.cwd:void 0,h=typeof f.parentSessionId=="string"?f.parentSessionId:void 0,w=f._meta&&typeof f._meta=="object"?f._meta:void 0,k=w&&w["hydra-acp"]&&typeof w["hydra-acp"]=="object"?w["hydra-acp"]:void 0,y=k&&typeof k.title=="string"?k.title:void 0,b=k&&typeof k.model=="string"?k.model:void 0;if(!g&&h){let j=e.manager.get(h);j&&(g=j.cwd)}if(!g)throw $(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let I=await Ut(g),v=m??I.agentId??e.defaultAgent,R=await e.registry?.getAgent(v),x=Wt(I.models,R??{id:v})?.value,E=b??x,O=typeof f.interactive=="boolean"?f.interactive:!1;return{childSessionId:(await e.manager.create({agentId:v,cwd:g,parentSessionId:h,interactive:O,transformChain:[],title:y,model:E})).sessionId}}),a.onRequest("hydra-acp/session/fork",async p=>{let f=p??{};if(typeof f.sessionId!="string")throw $(A.InvalidParams,"fork_session requires sessionId");let m=typeof f.forkAt=="string"?f.forkAt:void 0,g=typeof f.cwd=="string"?f.cwd:void 0,h=typeof f.agentId=="string"?f.agentId:void 0,w=typeof f.mode=="string"&&(f.mode==="verbatim"||f.mode==="synthesis")?f.mode:void 0,k=typeof f.model=="string"&&f.model.length>0?f.model:void 0,y=await e.manager.forkSession(f.sessionId,{...m!==void 0?{forkAt:m}:{},...g!==void 0?{cwd:g}:{},...h!==void 0?{agentId:h}:{},...w!==void 0?{mode:w}:{},...k!==void 0?{model:k}:{}}),b=e.manager.get(y.sessionId);if(!b){let R=await e.manager.loadFromDisk(y.sessionId);if(!R)throw $(A.InternalError,`fork ${y.sessionId} vanished before it could be attached`);b=await ct(e,{...R,onInstallProgress:bs(a)})}Ot(d,b,b.sessionId);let I=Ze(a,b,d),{entries:v}=await b.attach(I,"full");d.attached.set(b.sessionId,{sessionId:b.sessionId,clientId:I.clientId,readonly:!1});for(let R of v){if(a.isClosed())break;await a.notify(R.method,_e(R.params,R.recordedAt)).catch(()=>{})}return{...y,sessionId:b.sessionId}}),a.onRequest("session/fork",async p=>{let f=p??{};if(typeof f.sessionId!="string")throw $(A.InvalidParams,"session/fork requires sessionId");let m=typeof f.cwd=="string"?f.cwd:void 0,g=await e.manager.forkSession(f.sessionId,{...m!==void 0?{cwd:m}:{},mode:"verbatim"}),h=e.manager.get(g.sessionId);if(!h){let y=await e.manager.loadFromDisk(g.sessionId);if(!y)throw $(A.InternalError,`fork ${g.sessionId} vanished before it could be attached`);h=await ct(e,{...y,onInstallProgress:bs(a)})}Ot(d,h,h.sessionId);let w=Ze(a,h,d),{entries:k}=await h.attach(w,"full");d.attached.set(h.sessionId,{sessionId:h.sessionId,clientId:w.clientId,readonly:!1});for(let y of k){if(a.isClosed())break;await a.notify(y.method,_e(y.params,y.recordedAt)).catch(()=>{})}return{sessionId:h.sessionId}});let l=async(p,f)=>{let m=p??{};if(typeof m.sessionId!="string")throw $(A.InvalidParams,`${f} requires sessionId`);let g=await e.manager.resolveCanonicalId(m.sessionId)??m.sessionId,h=e.manager.get(g);if(h)return await h.close({deleteRecord:!0,by:`session/delete ${d.clientId}`}),await e.manager.waitForDeletion(g),await e.manager.hasRecord(g)&&await e.manager.deleteRecord(g),{id:g,existed:!0};let w=await e.manager.deleteRecord(g);return{id:g,existed:w}};a.onRequest("session/delete",async p=>(await l(p,"session/delete"),{})),a.onRequest("session/close",async p=>{let f=p??{};if(typeof f.sessionId!="string")throw $(A.InvalidParams,"session/close requires sessionId");c(f.sessionId,"session/close");let m=await e.manager.resolveCanonicalId(f.sessionId)??f.sessionId,g=e.manager.get(m);if(g)return await g.close({deleteRecord:!1,by:`session/close ${d.clientId}`+(d.processIdentity?` (${d.processIdentity.name})`:"")}),{};if(await e.manager.hasRecord(m))return{};throw $(A.SessionNotFound,`session ${m} not found`)}),a.onRequest("hydra-acp/session/delete",async p=>{let{id:f,existed:m}=await l(p,"hydra-acp/session/delete");if(!m)throw $(A.SessionNotFound,`session ${f} not found`);return{deleted:!0,sessionId:f}}),a.onRequest("hydra-acp/child_session/await",async p=>{let f=p??{},m=typeof f.childSessionId=="string"?f.childSessionId:void 0,g=f.until==="idle"?"idle":"turn_complete",h=typeof f.timeoutMs=="number"?Math.min(f.timeoutMs,18e5):3e5;if(!m)throw $(-32602,"await_child requires childSessionId");let w=ve(e.manager,m,`child session ${m} not found`);return new Promise(k=>{let I=[],v=[],R=0,x=!1,E,O,T=!1,j=()=>{T||(T=!0,clearTimeout(W),E?.(),O?.(),k(x?{entries:I,truncated:!0}:{entries:I}))};E=w.onBroadcast(q=>{let ne=lm(q);for(I.push(q),v.push(ne),R+=ne;I.length>0&&(I.length>1e3||R>1048576);)I.shift(),R-=v.shift()??0,x=!0;g==="turn_complete"&&q.params?.update?.sessionUpdate==="turn_complete"&&j()});let W=setTimeout(j,h);typeof W.unref=="function"&&W.unref(),O=w.onClose(()=>j())})}),a.onRequest("hydra-acp/child_session/close",async p=>{let f=p??{},m=typeof f.childSessionId=="string"?f.childSessionId:void 0;if(!m)throw $(-32602,"close_child_session requires childSessionId");let g=e.manager.get(m);return g&&await g.close({deleteRecord:!1,by:`child_session/close ${d.clientId}`}),{ok:!0}}),a.onRequest("hydra-acp/attention/set",async p=>ym(p,o.name,e)),a.onRequest("hydra-acp/attention/clear",async p=>wm(p,o.name,e)),a.onRequest("hydra-acp/connection/keep_alive",async p=>{let f=p??{},m=typeof f.token=="string"?f.token:void 0,g=typeof f.sessionId=="string"?f.sessionId:void 0,h=typeof f.estimatedRemainingMs=="number"?f.estimatedRemainingMs:void 0;return m&&g&&e.manager.get(g)?.keepAliveClaim(m,h),{ok:!0}})}a.onRequest("hydra-acp/session/tool_content",async l=>{let p=l??{};if(typeof p.sessionId!="string"||typeof p.hash!="string")throw $(A.InvalidParams,"hydra-acp/session/tool_content requires sessionId and hash");let f=await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,m=await e.manager.loadToolBlob(f,p.hash);if(m===null)throw $(A.SessionNotFound,"tool content not found");return{content:m}}),a.onRequest("authenticate",async l=>fm(l,e)),a.onRequest("logout",async l=>pm(l,e)),a.onRequest("session/new",async l=>{let p=ri.parse(l),f=tt(l?._meta),m=Array.isArray(f.transformers)&&f.transformers.every(J=>typeof J=="string")?f.transformers:e.manager.defaultTransformers??[],g=e.transformers?.resolveChain(m)??[],h=await Ut(p.cwd),w=f.agentId??h.agentId??e.defaultAgent,k=await e.registry?.getAgent(w),y=Wt(h.models,k??{id:w})?.value,b,I,v=p.mcpServers;if(f.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){b=sc(32).toString("hex"),I=e.mcpTokenRegistry.reserve(b);let be={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${b}`}]};v=[...p.mcpServers??[],be]}let R,x,E=_t(e);E!==void 0&&(v=[...v??[],...E.descriptors]);let O=io({baselineMcpServers:p.mcpServers,stdinEnabled:f.mcpStdin===!0,deps:e}),T;try{T=await e.manager.create({cwd:p.cwd,agentId:w,mcpServers:v,title:f.title,agentArgs:f.agentArgs,model:f.model??y,onInstallProgress:bs(a),transformChain:g,originatingClient:d.clientInfo,...f.interactive!==void 0?{interactive:f.interactive}:{},...f.env!==void 0?{forwardedEnv:f.env}:{},...f.workspace!==void 0?{workspace:f.workspace}:{},...O?{mintMcpServersForSwap:O}:{}})}catch(J){throw I!==void 0&&I.abandon(J instanceof Error?J:void 0),x!==void 0&&x.abandon(J instanceof Error?J:void 0),E!==void 0&&E.abandon(J instanceof Error?J:void 0),J}if(b!==void 0&&I!==void 0&&e.mcpTokenRegistry!==void 0){let J=b,be=e.mcpTokenRegistry;I.complete(T),T.onClose(()=>{be.unbind(J)})}if(R!==void 0&&x!==void 0&&e.mcpTokenRegistry!==void 0){let J=R,be=e.mcpTokenRegistry;x.complete(T),T.onClose(()=>{be.unbind(J)})}E!==void 0&&E.bindToSession(T),ac(T.sessionId,e);let j,W;try{Ot(d,T,T.sessionId),j=Ze(a,T,d),{entries:W}=await T.attach(j,"full")}catch(J){throw await T.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),J}d.attached.set(T.sessionId,{sessionId:T.sessionId,clientId:j.clientId,readonly:!1}),setImmediate(()=>{(async()=>{for(let J of W){if(a.isClosed())break;await a.notify(J.method,_e(J.params,J.recordedAt)).catch(()=>{})}})()});let q=Ss(T),ne=Is(T);return{sessionId:T.sessionId,...q?{modes:q}:{},...ne?{models:ne}:{},configOptions:T.buildConfigOptions(),_meta:As(e.manager,T,{clientId:j.clientId})}}),a.onRequest("session/attach",async l=>{let p=ii.parse(l),f=p.clientInfo?.version;f&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,f):e.onTransformerVersion?.(o.name,f));let m=tt(p._meta),g=m.resume,h=m.readonly===!0,w=m.env;s.log.info(`session/attach sessionId=${p.sessionId} hasResumeHints=${!!g} readonly=${h}`);let k=g?p.sessionId:await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,y=e.manager.get(k);if(!y&&h){let T=await e.manager.loadFromDisk(k);if(!T)throw $(A.SessionNotFound,`session ${p.sessionId} not found`);let j=await e.manager.loadHistory(k),W=p.clientId??`cli_${uo(8)}`;d.attached.set(T.hydraSessionId,{sessionId:T.hydraSessionId,clientId:W,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${T.hydraSessionId} clientId=${W} attachedCount=${d.attached.size} replayed=${j.length}`);for(let q of j)await a.notify(q.method,_e(q.params,q.recordedAt)).catch(()=>{});return{sessionId:T.hydraSessionId,clientId:W,connectedClients:[W],historyPolicy:"full",replayed:j.length,_meta:km(T)}}let b=!y;if(!y){let T=await e.manager.loadFromDisk(k),j=await gm(k,g,T?.upstreamSessionId,e.manager);j.kind==="ignore"&&s.log.warn(j.logMessage);let W=T;if(g&&j.kind==="honor"&&(W={...T,hydraSessionId:p.sessionId,upstreamSessionId:g.upstreamSessionId,agentId:g.agentId,cwd:T?.workspace?.path??g.cwd,...g.title!==void 0?{title:g.title}:{},...g.agentArgs!==void 0?{agentArgs:g.agentArgs}:{}}),!W)throw $(A.SessionNotFound,`session ${p.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(W.agentId,W.upstreamSessionId))throw $(A.SessionNotFound,`session ${p.sessionId} was deleted`);let q=W.originatingClient?W:{...W,originatingClient:d.clientInfo},ne=w!==void 0?{...q,forwardedEnv:w}:q;y=await ct(e,{...ne,onInstallProgress:bs(a)})}Ot(d,y,y.sessionId);let I=Ze(a,y,d,p.clientInfo,p.clientId),v=m.replayMode==="drip",{entries:R,appliedPolicy:x}=await y.attach(I,p.historyPolicy,{afterMessageId:p.afterMessageId,raw:v,...m.toolContent!==void 0?{toolContent:m.toolContent}:{}});if(d.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:I.clientId,readonly:h}),w!==void 0&&await e.manager.setForwardedEnv(y.sessionId,w).catch(()=>{}),s.log.info(`session/attach OK sessionId=${y.sessionId} clientId=${I.clientId} attachedCount=${d.attached.size} requestedPolicy=${p.historyPolicy} appliedPolicy=${x} replayed=${R.length} readonly=${h}${v?" replayMode=drip":""}`),v){let T=m.dripSpeed&&m.dripSpeed>0?m.dripSpeed:1,j=750;(async()=>{let W=null;for(let q of R){let ne=typeof q.recordedAt=="number"?q.recordedAt:null;if(W!==null&&ne!==null){let J=Math.min(j,Math.max(0,(ne-W)/T));J>0&&await new Promise(be=>setTimeout(be,J))}ne!==null&&(W=ne);try{await a.notify(q.method,_e(q.params,ne??void 0))}catch{return}}})()}else for(let T=0;T<R.length&&!a.isClosed();T++){let j=R[T],W=a.notify(j.method,_e(j.params,j.recordedAt)).catch(()=>{});(T+1)%200===0&&await W}y.replayPendingPermissions(I);let E=Ss(y),O=Is(y);return{sessionId:y.sessionId,clientId:I.clientId,connectedClients:y.connectedClients(I.clientId),historyPolicy:x,replayed:R.length,...E?{modes:E}:{},...O?{models:O}:{},configOptions:y.buildConfigOptions(),_meta:As(e.manager,y,{resurrected:b})}}),a.onRequest("session/detach",async l=>{let p=ai.parse(l),f=d.attached.get(p.sessionId);if(!f)throw $(A.SessionNotFound,"client not attached to that session");let m=e.manager.get(p.sessionId);return m?.detach(f.clientId),d.attached.delete(p.sessionId),m&&e.manager.reapIfOrphanedNonInteractive(p.sessionId),{sessionId:p.sessionId,_meta:{[pe]:{detachStatus:"detached"}}}}),a.onRequest("session/list",async l=>{let p=di.parse(l??{});return{sessions:(await e.manager.list({cwd:p.cwd})).filter(h=>h.originatingClient?.name!==Vn).map(ci)}}),a.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw $(A.InternalError,"agent registry unavailable");return mt(e.registry)}),a.onRequest("hydra-acp/agents/auth_methods",async l=>{let p=l??{};if(typeof p.agentId!="string"||p.agentId.length===0)throw $(A.InvalidParams,"hydra-acp/agents/auth_methods requires a non-empty agentId string");return{authMethods:(await e.manager.bootstrapAgentForAuth(p.agentId)).authMethods??[]}}),a.onRequest("session/prompt",async l=>{let p=ui.parse(l);c(p.sessionId,"session/prompt");let f=await Zd(p,e.manager,w=>{s.log.warn(`session/prompt: dropping unknown sentBy.sessionId=${w} sessionId=${p.sessionId}`)});if(f?.fromSession!==void 0){if((f.depth??0)>3)throw s.log.warn(`session/prompt: refusing depth ${f.depth} chain from ${f.fromSession} to ${p.sessionId}`),$(A.InvalidRequest,`message chain too deep (${f.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(f.awaiting===!0&&tc(f.fromSession,p.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${f.fromSession} -> ${p.sessionId}`),$(A.InvalidRequest,`would deadlock: ${p.sessionId} is already blocked waiting on ${f.fromSession}. Send with --no-wait, or let the other turn finish first.`)}let m=d.attached.get(p.sessionId);if(!m)throw s.log.warn(`session/prompt rejected: not attached sessionId=${p.sessionId} attachedKeys=[${[...d.attached.keys()].join(",")}]`),$(A.SessionNotFound,"not attached to session");let g=e.manager.get(p.sessionId);if(!g){let w=await e.manager.loadFromDisk(p.sessionId);if(!w)throw $(A.SessionNotFound,`session ${p.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${p.sessionId}`),g=await ct(e,w);let k=Ze(a,g,d,void 0,m.clientId);await g.attach(k,"none")}let h=f?.awaiting===!0&&f.fromSession!==void 0?ec(f.fromSession,p.sessionId):void 0;try{return await g.prompt(m.clientId,p,f)}finally{h?.()}});let u=l=>{let p;try{p=Rn.parse(l)}catch(g){s.log.warn(`session/cancel: invalid params: ${g.message}`);return}let f=d.attached.get(p.sessionId);if(!f)return;if(f.readonly){s.log.warn(`session/cancel dropped (readonly attachment) sessionId=${p.sessionId}`);return}let m=e.manager.get(p.sessionId);m&&m.cancel(f.clientId).catch(g=>{s.log.warn(`session/cancel for ${p.sessionId}: ${g.message}`)})};a.onNotification("session/cancel",u),a.onRequest("session/cancel",async l=>{let p=Rn.parse(l);return c(p.sessionId,"session/cancel"),u(l),null}),a.onRequest("hydra-acp/prompt/cancel",async l=>{let p=fi.parse(l);return c(p.sessionId,"hydra-acp/prompt/cancel"),ve(e.manager,p.sessionId).cancelQueuedPrompt(p.messageId)}),a.onRequest("hydra-acp/session/force_cancel",async l=>{let p=Rn.parse(l);return c(p.sessionId,"hydra-acp/session/force_cancel"),ve(e.manager,p.sessionId).forceCancel()}),a.onRequest("hydra-acp/prompt/update",async l=>{let p=pi.parse(l);return c(p.sessionId,"hydra-acp/prompt/update"),ve(e.manager,p.sessionId).updateQueuedPrompt(p.messageId,p.prompt)}),a.onRequest("hydra-acp/prompt/amend",async l=>{let p=gi.parse(l);c(p.sessionId,"hydra-acp/prompt/amend");let f=d.attached.get(p.sessionId);if(!f)throw $(A.SessionNotFound,"not attached to session");return ve(e.manager,p.sessionId).amendPrompt(f.clientId,p)}),a.onRequest("_session/steering",async l=>{let p=mi.parse(l);c(p.sessionId,"_session/steering");let f=d.attached.get(p.sessionId);if(!f)throw $(A.SessionNotFound,"not attached to session");let m=e.manager.get(p.sessionId);if(!m){let g=await e.manager.loadFromDisk(p.sessionId);if(!g)throw $(A.SessionNotFound,`session ${p.sessionId} not found`);m=await ct(e,g);let h=Ze(a,m,d,void 0,f.clientId);await m.attach(h,"none")}return m.steer(f.clientId,p)}),a.onRequest("session/resume",async l=>{let p=l??{},f=typeof p.sessionId=="string"?p.sessionId:void 0;if(!f)throw $(A.InvalidParams,"session/resume requires sessionId");let m=await e.manager.resolveCanonicalId(f)??f,g=e.manager.get(m);if(!g){let y=await e.manager.loadFromDisk(m);if(!y)throw $(A.SessionNotFound,`session ${f} not found in memory or on disk`);g=await ct(e,y)}Ot(d,g,g.sessionId);let h=Ze(a,g,d);await g.attach(h,"pending_only"),d.attached.set(g.sessionId,{sessionId:g.sessionId,clientId:h.clientId,readonly:!1}),g.replayPendingPermissions(h);let w=Ss(g),k=Is(g);return{sessionId:g.sessionId,...w?{modes:w}:{},...k?{models:k}:{},configOptions:g.buildConfigOptions(),_meta:As(e.manager,g,{clientId:h.clientId})}}),a.onRequest("session/load",async l=>{let p=l??{},f=typeof p.sessionId=="string"?p.sessionId:void 0;if(!f)throw $(A.InvalidParams,"session/load requires sessionId");let m=await e.manager.resolveCanonicalId(f)??f,g=e.manager.get(m);if(!g){let b=await e.manager.loadFromDisk(m);if(!b)throw $(A.SessionNotFound,`session ${f} not found in memory or on disk`);g=await ct(e,b)}Ot(d,g,g.sessionId);let h=Ze(a,g,d),{entries:w}=await g.attach(h,"full");d.attached.set(g.sessionId,{sessionId:g.sessionId,clientId:h.clientId,readonly:!1});for(let b of w){if(a.isClosed())break;await a.notify(b.method,_e(b.params,b.recordedAt)).catch(()=>{})}g.replayPendingPermissions(h);let k=Ss(g),y=Is(g);return{sessionId:g.sessionId,...k?{modes:k}:{},...y?{models:y}:{},configOptions:g.buildConfigOptions(),_meta:As(e.manager,g,{clientId:h.clientId})}}),a.onRequest("session/set_model",async l=>{let p=l?.sessionId;typeof p=="string"&&c(p,"session/set_model");let f=mm(l,e.manager);if(f.kind==="error")throw s.log.warn(f.logMessage),$(f.code,f.message);if(f.kind==="no_op")return s.log.warn(f.logMessage),await a.notify("session/update",{sessionId:f.sessionId,update:{sessionUpdate:"_hydra_current_model_update",currentModel:f.currentModel}}).catch(()=>{}),null;s.log.info(f.logMessage);let{modelId:m}=f,g=await f.session.forwardModelChange(m,l);return f.session.applyAgentConfigOptionResponse(g,"model"),f.session.applyModelChange(m),g}),a.onRequest("session/set_mode",async l=>{let p=l,f=p?.sessionId;if(typeof f=="string"&&c(f,"session/set_mode"),!p||typeof p.sessionId!="string")throw $(A.InvalidParams,"session/set_mode requires string sessionId");if(typeof p.modeId!="string")throw $(A.InvalidParams,"session/set_mode requires string modeId");let m=ve(e.manager,p.sessionId),g=await m.forwardRequest("session/set_mode",l);return m.applyModeChange(p.modeId),g}),a.onRequest("session/set_config_option",async l=>{let p=l,f=w=>$(A.InvalidParams,w),m=p?.sessionId;if(typeof m=="string"&&c(m,"session/set_config_option"),!p||typeof p.sessionId!="string")throw f("session/set_config_option requires string sessionId");if(typeof p.configId!="string")throw f("session/set_config_option requires string configId");if(typeof p.value!="string")throw f("session/set_config_option requires string value");let g=ve(e.manager,p.sessionId),h=g.buildConfigOptions().find(w=>w.id===p.configId);if(!h)throw f(`unknown configId ${JSON.stringify(p.configId)} for this session`);if(!h.options.some(w=>w.value===p.value))throw f(`value ${JSON.stringify(p.value)} is not valid for configId ${JSON.stringify(p.configId)}`);switch(p.configId){case"model":{if(p.value!==g.currentModel){let w=await g.forwardModelChange(p.value);g.applyAgentConfigOptionResponse(w,"model")}g.applyModelChange(p.value);break}case"mode":{p.value!==g.currentMode&&await g.forwardRequest("session/set_mode",{sessionId:p.sessionId,modeId:p.value}),g.applyModeChange(p.value);break}case"agent":{p.value!==g.agentId&&await g.setAgent(p.value);break}default:{let w=await g.forwardRequest("session/set_config_option",{sessionId:p.sessionId,configId:p.configId,value:p.value});g.applyAgentConfigOptionResponse(w,p.configId)&&g.broadcastConfigOptions()}}return{configOptions:g.buildConfigOptions()}}),a.setDefaultHandler(async(l,p)=>{let f=new Set(["hydra-acp/attention/set","hydra-acp/attention/clear"]),m=p.startsWith("session/"),g=p.startsWith("hydra-acp/");if(!m&&!g||l===null||typeof l!="object"||f.has(p))throw $(A.MethodNotFound,`Method not found: ${p}`);let h=l.sessionId;if(typeof h!="string")throw $(A.MethodNotFound,`Method not found: ${p}`);return c(h,p),ve(e.manager,h).forwardRequest(p,l)})})}async function fm(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw $(A.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(m=>m.id);throw $(A.InvalidParams,`authenticate: methodId ${JSON.stringify(n)} is not advertised by agent ${a.agentId}; valid: [${f.map(m=>JSON.stringify(m)).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=(y,b)=>{if(!Array.isArray(y))throw $(A.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be a string[]; got ${y===null?"null":typeof y}`);for(let I of y)if(typeof I!="string")throw $(A.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be string[]; got non-string entry ${JSON.stringify(I)}`);return y},m=await e.manager.planSpawnForAgent(a.agentId),g,h;if(l?.args!==void 0){let y=typeof l.command=="string"?l.command:void 0;g=y!==void 0&&oc.isAbsolute(y)?y:m.command,h=f(l.args,'_meta["terminal-auth"].args')}else{let y=c.args!==void 0?{raw:c.args,label:"args"}:c._meta?.args!==void 0?{raw:c._meta.args,label:"_meta.args"}:void 0,b=y!==void 0?f(y.raw,y.label):[];g=m.command,h=[...m.args,...b]}let w={};for(let[y,b]of Object.entries(process.env))typeof b=="string"&&(w[y]=b);Object.assign(w,m.env);let k=rc.homedir();return console.error(`[authenticate] terminal-auth requested agentId=${a.agentId} methodId=${n}`),{kind:"terminal",command:g,args:h,env:w,cwd:k}}try{return await a.connection.request("authenticate",{methodId:n})}catch(f){throw Ye(f,a)}}async function pm(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 bs(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(hi,t).catch(()=>{})}}function Ss(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 Is(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 gm(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 mm(s,e){if(!s||typeof s!="object")return{kind:"error",code:A.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:A.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:A.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:A.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=bt(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:A.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 hm(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw $(A.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw $(A.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw $(A.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return ve(t.manager,r).addTransformer(o),{ok:!0}}async function ym(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 $(A.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw $(A.InvalidParams,"hydra-acp/attention/set requires string reason");return ve(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function wm(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 $(A.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw $(A.InvalidParams,"hydra-acp/attention/clear requires string reason");return ve(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function km(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:sn(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{[pe]:Cn(e,t)}}function As(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 qt(e.agentMeta,Cn(n,r))}function vm(){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:{...qt(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}}}),steering:{supported:!0}}}}function bm(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 ac(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 Ze(s,e,t,n,r){return{clientId:r??`cli_${uo(8)}`,connection:s,clientInfo:n}}function Ot(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var Cs=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 Sm}from"crypto";import{McpServer as Im}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Am}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as le}from"zod";function lo(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 he(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var dc="Bearer ";function Ft(s){let e=s.headers.authorization;if(typeof e!="string"||!e.startsWith(dc))return;let t=e.slice(dc.length).trim();return t.length>0?t:void 0}function Cm(s){let e=new Im({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:le.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return he(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:le.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return he(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:le.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:le.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:le.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 he(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:le.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:le.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 he({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:le.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:le.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:le.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:le.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:le.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:le.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:le.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:le.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:le.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 he(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 he(t)}),e}var Rm=1e4;function cc(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=Cm(a),u=new Am({sessionIdGenerator:()=>Sm()});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=Ft(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(g=>{p=setTimeout(()=>g(void 0),Rm)}),m=await Promise.race([c.sessionReady.catch(()=>{}),f]);if(p!==void 0&&clearTimeout(p),m===void 0){a.code(503).send({error:"session not ready"});return}u=m}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 xm}from"crypto";import{McpServer as Em}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Tm}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as De}from"zod";function Pm(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var uc=2e3,lc=2e4;function Mm(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return St([s]);let n=[],r=Jt(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=Pn(t);return i!==void 0&&n.push(i),n.join(`
193
- `)}function _m(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 $m(s){let e=new Em({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:De.string().min(1).describe("Case-insensitive substring to search for."),limit:De.number().int().min(1).max(50).optional().describe("Maximum number of matches to return (default 10, max 50)."),include_tool_calls:De.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 he({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=lo(u);if(!l)continue;let{kind:p,update:f}=l;if((p==="tool_call"||p==="tool_call_update")&&!r)continue;let m=Mm(u,p,f),g=m.toLowerCase().indexOf(a);if(g<0)continue;let h=Pm(p),w=_m(m,g),k=typeof u.recordedAt=="number"?String(u.recordedAt):void 0;if(i.push({entryId:c,speaker:h,snippet:w,timestamp:k}),i.length>=n)break}i.sort((c,u)=>c.entryId-u.entryId);let d=i.length>=n;return he({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:De.number().int().min(0).describe("Zero-based index of the first entry to include (inclusive)."),to_entry:De.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 he({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 he({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=St(u,{toolOutput:{maxPerCall:uc,maxTotal:lc}});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:De.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:De.string().optional().describe("ACP tool kind: execute (shell), read, edit, think, other. Agent-independent, unlike tool_name."),file_path:De.string().optional(),limit:De.number().int().min(1).max(100).optional(),include_output:De.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 he({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:k,entry:y}of a.iterRecallNewestFirst()){let b=lo(y);if(!b)continue;let{kind:I,update:v}=b;if(I!=="tool_call"&&I!=="tool_call_update")continue;let R=typeof v.toolCallId=="string"&&v.toolCallId.length>0?v.toolCallId:`__noid_${k}`,x=l.get(R);if(x||(x={entryId:k,toolName:"(unnamed)",nameAuthoritative:!1,rawInput:{},locations:[],status:"in_progress"},l.set(R,x)),k<x.entryId&&(x.entryId=k),!x.nameAuthoritative){let O=Jt(v);O!==void 0?(x.toolName=O,x.nameAuthoritative=!0):typeof v.name=="string"&&v.name.length>0?(x.toolName=v.name,x.nameAuthoritative=!0):I==="tool_call"&&typeof v.title=="string"&&v.title.length>0&&(x.toolName=v.title,x.nameAuthoritative=!0)}if(x.kind===void 0&&typeof v.kind=="string"&&v.kind.length>0&&(x.kind=v.kind),x.output===void 0){let O=Pn(v);O!==void 0&&(x.output=O)}let E=v.rawInput;if(E&&typeof E=="object"&&!Array.isArray(E)&&Object.keys(E).length>0)for(let[O,T]of Object.entries(E))x.rawInput[O]===void 0&&(x.rawInput[O]=T);if(Array.isArray(v.locations))for(let O of v.locations){let T=O?.path;typeof T=="string"&&T.length>0&&!x.locations.includes(T)&&x.locations.push(T)}if(typeof v.status=="string"&&x.status==="in_progress"&&(x.status=v.status),y.recordedAt!==void 0&&x.timestamp===void 0&&(x.timestamp=String(y.recordedAt)),l.size>=p)break}let f=[...l.keys()].sort((k,y)=>l.get(k).entryId-l.get(y).entryId),m=[],g=lc,h=!1;for(let k of f){let y=l.get(k);if(y.toolName=ar({name:y.toolName,rawInput:y.rawInput,...y.kind!==void 0?{kind:y.kind}:{}}),d&&!y.toolName.toLowerCase().includes(t.toLowerCase())||c&&(y.kind??"").toLowerCase()!==n.toLowerCase())continue;if(u){let v=r.toLowerCase(),R=["file_path","filePath","path"],x=!1;for(let E of R){let O=y.rawInput[E];if(typeof O=="string"&&O.toLowerCase().includes(v)){x=!0;break}}if(!x){for(let E of y.locations)if(E.toLowerCase().includes(v)){x=!0;break}}if(!x)continue}let b={};for(let[v,R]of Object.entries(y.rawInput))typeof R=="string"?b[v]=R.length>500?R.slice(0,497)+"\u2026":R:(typeof R=="number"||typeof R=="boolean")&&(b[v]=R);y.locations.length>0&&b.locations===void 0&&(b.locations=y.locations);let I={entryId:y.entryId,tool:y.toolName,args:b,status:y.status,timestamp:y.timestamp};if(y.kind!==void 0&&(I.kind=y.kind),i&&y.output!==void 0){let v=y.output,R=Math.min(uc,g);if(R<=0)h=!0;else{let x=v.length<=R?v:v.slice(0,R-1)+"\u2026";I.output=x,I.outputBytes=v.length,I.outputTruncated=x.length<v.length,g-=x.length}}if(m.push(I),m.length>=o)break}let w=m.length>=o;return he({calls:m,truncated:w,...h?{outputBudgetExhausted:h}:{}})}),e}var Om=1e4;function fc(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=$m(a),u=new Tm({sessionIdGenerator:()=>xm()});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=Ft(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(g=>{p=setTimeout(()=>g(void 0),Om)}),m=await Promise.race([c.sessionReady.catch(()=>{}),f]);if(p!==void 0&&clearTimeout(p),m===void 0)throw new Error("recall: session not ready");return m});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 Rs=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 Bm}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{randomUUID as Wm}from"crypto";import{Server as Fm}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Nm,ListToolsRequestSchema as Hm}from"@modelcontextprotocol/sdk/types.js";function pc(s,e,t,n){let r=typeof t=="function"?async()=>t():async()=>t,o=new Fm({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(Hm,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(Nm,async(a,d)=>{let c=a.params.name,u=d._meta?.progressToken??d.requestId,l=Dm(u,d.sendNotification);try{let p=await r(),f=await Um(e.connection,s,c,a.params.arguments??{},p);return Lm(f,c)}catch(p){return fo(p instanceof Error?p.message:String(p))}finally{l()}}),o}var jm=15e3;function Dm(s,e,t=jm){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 Um(s,e,t,n,r){return await s.request("hydra-acp/mcp_tools/invoke",{server:e,tool:t,args:n,sessionId:r})}function Lm(s,e){if(s===null||typeof s!="object")return fo(`extension ${e} returned non-object`);let t=s;return Array.isArray(t.content)?t:fo(`extension ${e} omitted content array`)}function fo(s){return{content:[{type:"text",text:s}],isError:!0}}var qm=1e4;function gc(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 g=f.get(l);if(g!==void 0)try{await g.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 b=n.get(u);if(b!==void 0){n.delete(u);for(let I of b.values())await r(I)}}));let f=p.get(l);if(f!==void 0)return f.transport;let m=t.lookup(l);if(m===void 0)return;let k=pc(l,m,async()=>{let b=e.lookup(u);if(b===void 0)throw new Error("mcp token no longer bound");if(b.session!==void 0)return b.session.sessionId;let I,v=new Promise(x=>{I=setTimeout(()=>x(void 0),qm)}),R=await Promise.race([b.sessionReady.catch(()=>{}),v]);if(I!==void 0&&clearTimeout(I),R===void 0)throw new Error("session not ready");return R.sessionId},{peekSessionId:()=>e.lookup(u)?.session?.sessionId,fetchSessionTools:async b=>{let I=await m.connection.request("hydra-acp/mcp_tools/list_tools",{sessionId:b});if(!I||typeof I!="object")return;let v=I.tools;if(!Array.isArray(v))return;let R=[];for(let x of v){if(!x||typeof x!="object")continue;let E=x;if(typeof E.name!="string"||E.name.length===0||typeof E.description!="string"||E.inputSchema===null||typeof E.inputSchema!="object")continue;let O={name:E.name,description:E.description,inputSchema:E.inputSchema};E.outputSchema!==null&&typeof E.outputSchema=="object"&&(O.outputSchema=E.outputSchema),R.push(O)}return R}}),y=new Bm({sessionIdGenerator:()=>Wm()});return await k.connect(y),p.set(l,{server:k,transport:y}),y}async function d(u,l){let p=Ft(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 m=u.params.name,g=await a(p,m);if(g===void 0){l.code(404).send({error:`unknown mcp server: ${m}`});return}l.hijack(),await g.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 vc(s,e){Ym(s),Ds(s.daemon.scrubEnv);let t=s,n=s.daemon.tls?await Ue.readFile(ie(s.daemon.tls.key)):void 0,r=s.daemon.tls?await Ue.readFile(ie(s.daemon.tls.cert)):void 0;await Ue.mkdir(C.home(),{recursive:!0});let{stream:o,fileStream:i}=await Km(s.daemon.logLevel),a=zm({logger:{level:s.daemon.logLevel,stream:o},bodyLimit:256*1024*1024});await a.register(Jm,{options:{handleProtocols:$o}}),zs(F=>{a.log.info(F)}),Gs(F=>{a.log.info(F)});let d=await ds.load(),c=new ps,u=new fs,l=new cs(e),p=new ls([l,new us(d),u]),f=ld({validator:p});a.addHook("onRequest",async(F,Se)=>{F.routeOptions.config?.skipAuth||F.url==="/acp"||F.url?.startsWith("/acp?")||await f(F,Se)});let m=setInterval(()=>{d.sweepExpired()},300*1e3);m.unref();let g=setInterval(()=>{c.sweepExpired()},300*1e3);g.unref();let h=new In(s,{onFetched:()=>{Ya(h,b)},onStaleFallback:(F,Se)=>{let Ht=Math.round(Se/36e5),jt=Ht>=48?`${Math.round(Ht/24)}d`:`${Ht}h`;a.log.warn(`registry fetch failed (${F.message}); serving stale cache last synced ${jt} ago; agent versions may be outdated ('hydra registry refresh' to retry)`)}});eo(F=>a.log.info(F));let w={info:F=>a.log.info(F),warn:F=>a.log.warn(F)},k=F=>Ke.spawn({...F,stderrTailBytes:s.daemon.agentStderrTailBytes,logger:w});Do(s.compressToolContent);let y=new is,b=new Zn(h,k,void 0,{idleTimeoutMs:s.daemon.sessionIdleTimeoutSeconds*1e3,orphanTimeoutMs:s.daemon.nonInteractiveOrphanTimeoutSeconds*1e3,defaultModels:s.defaultModels,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:w,npmRegistry:s.npmRegistry,extensionCommands:y,defaultCwd:s.defaultCwd,disableWorkspaceSnapshots:s.disableWorkspaceSnapshots}),I=new rs(To(s),void 0,{tokenRegistry:u}),v=new os(Po(s),void 0,{tokenRegistry:u}),R=[];Wd(a,ue,ed(s),()=>R);let x=new Cs,E=new Rs,O,T=()=>{if(O!==void 0)return O;let F=a.server.address();return O=`http://127.0.0.1:${F&&typeof F=="object"?F.port:s.daemon.port}`,O},j={agentId:s.defaultAgent,cwd:s.defaultCwd,publicHost:s.daemon.publicHost,host:s.daemon.host,port:s.daemon.port,compaction:s.compaction};Ld(a,b,j,{extensionMcp:E,mcpTokenRegistry:x,getDaemonOrigin:T}),Bd(a,h,b,{npmRegistry:s.npmRegistry}),qd(a,I),zd(a,v),Jd(a,()=>({defaultAgent:t.defaultAgent,defaultCwd:t.defaultCwd,defaultModels:{...t.defaultModels},...t.synopsisAgent!==void 0?{synopsisAgent:t.synopsisAgent}:{},...t.synopsisModel!==void 0?{synopsisModel:t.synopsisModel}:{},defaultTransformers:[...t.defaultTransformers]})),Yd(a,{store:d,rateLimiter:c,staticTokenValidator:l}),cc(a,x),fc(a,x);let W=gc(a,x,E);ic(a,{validator:p,manager:b,defaultAgent:s.defaultAgent,processRegistry:u,onExtensionVersion:(F,Se)=>I.reportVersion(F,Se),onTransformerVersion:(F,Se)=>v.reportVersion(F,Se),transformers:v,extensionCommands:y,mcpTokenRegistry:x,extensionMcp:E,extensionMcpControls:W,getDaemonOrigin:T,registry:h});let q=!!s.daemon.tls;await a.listen({host:q?"127.0.0.1":s.daemon.host,port:q?0:s.daemon.port});let ne=a.server.address(),J=ne&&typeof ne=="object"?ne.port:s.daemon.port,be,Mc=s.daemon.host,mo=J;if(q&&n&&r){be=Qm({listenHost:s.daemon.host,listenPort:s.daemon.port,upstreamHost:"127.0.0.1",upstreamPort:J,tlsOptions:{key:n,cert:r},logger:a.log});let F=be.address();F&&typeof F=="object"&&(mo=F.port)}await Ue.mkdir(C.home(),{recursive:!0}),await Qa({pid:process.pid,host:Mc,port:mo,loopbackPort:J,startedAt:new Date().toISOString()});let ho={daemonUrl:`http://127.0.0.1:${J}`,daemonHost:"127.0.0.1",daemonPort:J,serviceToken:e,daemonWsUrl:`ws://127.0.0.1:${J}/acp`,hydraHome:C.home()};I.setContext(ho),v.setContext(ho),await I.start(),await v.start();try{await b.reconcilePermissionFlags()}catch(F){a.log.warn(`permission flag reconcile failed: ${F.message}`)}b.resurrectPendingQueues().catch(F=>{a.log.warn(`queue replay scan failed: ${F.message}`)}),b.resumePendingCompactions().catch(F=>{a.log.warn(`compaction resume scan failed: ${F.message}`)}),b.resumePendingAgentSwaps().catch(F=>{a.log.warn(`agent-swap resume scan failed: ${F.message}`)});let yo=s.daemon.agentSyncIntervalMinutes*60*1e3,wo=yo>0?Xa({registry:h,manager:b,intervalMs:yo,logger:w}):void 0,ko=s.daemon.sessionGcIntervalMinutes*60*1e3,_c=s.daemon.sessionGcMaxAgeDays*24*60*60*1e3,vo=ko>0?Za({manager:b,intervalMs:ko,maxAgeMs:_c,logger:w}):void 0,$c=rd({bootConfig:s,apply:F=>{t=F,h.setConfig(F),b.setLiveConfig({defaultModels:F.defaultModels}),j.agentId=F.defaultAgent,j.cwd=F.defaultCwd,Ds(F.daemon.scrubEnv)},onDrift:F=>{R=F},logger:w});return{app:a,manager:b,registry:h,extensions:I,transformers:v,mcpTokenRegistry:x,extensionMcp:E,processRegistry:u,shutdown:async()=>{$c(),vo&&vo(),wo&&wo(),clearInterval(m),clearInterval(g);let F=async(Se,Ht)=>{try{await Ht()}catch(jt){a.log.warn(`shutdown step ${Se} failed: ${jt instanceof Error?jt.message:String(jt)}`)}};await F("sessionTokenStore.flush",()=>d.flush()),await F("extensions.stop",()=>I.stop()),await F("transformers.stop",()=>v.stop()),await F("manager.closeAll",()=>b.closeAll()),await F("manager.flushSynopsis",()=>b.flushSynopsis(3e4)),await F("manager.shutdownSynopsis",()=>b.shutdownSynopsis()),await F("manager.flushMetaWrites",()=>b.flushMetaWrites()),await F("manager.flushHistoryWrites",()=>b.flushHistoryWrites()),zs(null),Gs(null),eo(null),be&&await F("tlsTerminator.close",()=>new Promise(Se=>be.close(()=>Se()))),await F("app.close",()=>a.close());try{yc.unlinkSync(C.pidFile())}catch{}await F("fileStream.flushSync",()=>i.flushSync())}}}var hc=20;async function Gm(s,e){let t=Nt.dirname(s),n=Nt.basename(s,".log"),r=new RegExp(`^${n}\\.(\\d+)\\.log$`),o;try{o=await Ue.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=>Ue.unlink(Nt.join(t,d.name))))}async function Km(s){await Gm(C.logFile(),hc);let e=await Vm({file:C.logFile(),size:"10m",mkdir:!0,symlink:!0,limit:{count:hc,removeOtherLogFiles:!0}}),t=mc.destination(2);return{stream:mc.multistream([{stream:e,level:s},{stream:t,level:s}]),fileStream:e}}function Qm(s){let e=kc.createServer(s.tlsOptions,t=>{let n=wc.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}`)}),e.listen({host:s.listenHost,port:s.listenPort}),e}function Ym(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 fh(){process.title="hydra-acp-daemon";let{installGlobalTlsTrust:s}=await Promise.resolve().then(()=>(Pc(),Tc));s();let e=await Lt(),t=await bo(),n=await vc(e,t);process.stdout.write(`hydra-acp daemon listening on ${e.daemon.host}:${e.daemon.port}
190
+ `)}}return k=!0,w||u.raw.end(),u});function r(c,u,l){let p=typeof c=="string"?c.trim():"";if(p.length===0)return null;let f;try{f=JSON.parse(p)}catch{return console.debug("events endpoint: skipping malformed JSONL line"),null}if(!f||typeof f!="object"||Array.isArray(f))return console.debug("events endpoint: skipping non-object JSONL line"),null;let m=f;if(typeof m.recordedAt!="number"||l!==void 0&&m.recordedAt<l||typeof m.params!="object"||m.params===null||Array.isArray(m.params))return null;let g=m.params;if(typeof g.update!="object"||g.update===null||Array.isArray(g.update))return null;let w=g.update.sessionUpdate;return typeof w!="string"||!u.has(w)?null:{recordedAt:m.recordedAt,entry:f}}function o(c,u,l){let f=u.params.update,m={sessionId:c,ts:new Date(u.recordedAt).toISOString(),kind:l,update:f};return f.messageId!==void 0&&f.messageId!==null&&(m.messageId=f.messageId),m}async function*i(c,u,l,p){for await(let f of u){let m=r(f,l,p);if(m){let g=m.entry.params.update.sessionUpdate;yield{ts:m.recordedAt,row:o(c,m.entry,g)}}}}async function a(c,u,l,p){let f=uo.createInterface({input:co.createReadStream(u),crlfDelay:1/0}),m=i(c,f,l,p),g=await m.next(),h=g.done?null:g.value;return{sessionId:c,rl:f,gen:m,current:h,exhausted:h===null}}async function d(c){let u=await c.gen.next();u.done?(c.exhausted=!0,c.current=null):c.current=u.value}s.get("/v1/sessions/events",async(c,u)=>{let l=c.query,p=l.kinds;if(!p||p.trim().length===0)return u.code(400).send({error:"kinds parameter is required"}),u;let f=p.split(",").map(y=>y.trim());if(f.length===0)return u.code(400).send({error:"kinds parameter is required"}),u;for(let y of f)if(!ws.has(y))return u.code(400).send({error:`kind "${y}" is not queryable; allowed kinds: ${[...ws].join(", ")}`}),u;let m=new Set(f),g;if(l.since!==void 0&&l.since.trim().length>0){let y=new Date(l.since);if(isNaN(y.getTime()))return u.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),u;g=y.getTime()}let h=await e.list({includeNonInteractive:!0}),w=g!==void 0?h.filter(y=>new Date(y.updatedAt).getTime()>=g):h;u.raw.setHeader("content-type","application/x-ndjson"),u.raw.statusCode=200;let k=[];for(let y of w)try{let b=C.historyFile(y.sessionId),I=await a(y.sessionId,b,m,g);I.exhausted||k.push(I)}catch(b){if(b.code==="ENOENT")continue;throw b}c.raw.on("close",()=>{for(let y of k)try{y.rl.close()}catch{}u.raw.writableEnded||u.raw.end()});try{for(;k.length>0;){let y=-1,b=1/0;for(let v=0;v<k.length;v++){let R=k[v];R.current!==null&&R.current.ts<b&&(b=R.current.ts,y=v)}if(y===-1)break;let I=k[y];if(u.raw.write(JSON.stringify(I.current.row)+`
191
+ `),await d(I),I.exhausted){try{I.rl.close()}catch{}k.splice(y,1)}}}catch(y){for(let b of k)try{b.rl.close()}catch{}throw y}return u.raw.end(),u}),s.get("/v1/sessions/:id/events",async(c,u)=>{let l=c.params.id,p=c.query,f=await e.resolveCanonicalId(l)??l;if(!e.get(f)&&!await e.hasRecord(f))return u.code(404).send({error:"session not found"}),u;let g=p.kinds;if(!g||g.trim().length===0)return u.code(400).send({error:"kinds parameter is required"}),u;let h=g.split(",").map(v=>v.trim());if(h.length===0)return u.code(400).send({error:"kinds parameter is required"}),u;for(let v of h)if(!ws.has(v))return u.code(400).send({error:`kind "${v}" is not queryable; allowed kinds: ${[...ws].join(", ")}`}),u;let w=new Set(h),k;if(p.since!==void 0&&p.since.trim().length>0){let v=new Date(p.since);if(isNaN(v.getTime()))return u.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),u;k=v.getTime()}let y=C.historyFile(f),b=co.createReadStream(y),I=uo.createInterface({input:b,crlfDelay:1/0});u.raw.setHeader("content-type","application/x-ndjson"),u.raw.statusCode=200;try{for await(let v of I){let R=typeof v=="string"?v.trim():"";if(R.length===0)continue;let x;try{x=JSON.parse(R)}catch{console.debug("events endpoint: skipping malformed JSONL line in %s",y);continue}if(!x||typeof x!="object"||Array.isArray(x)){console.debug("events endpoint: skipping non-object JSONL line in %s",y);continue}let E=x;if(typeof E.recordedAt!="number"||typeof E.params!="object"||E.params===null||Array.isArray(E.params))continue;let O=E.params;if(typeof O.update!="object"||O.update===null||Array.isArray(O.update))continue;let T=O.update,j=T.sessionUpdate;if(typeof j!="string"||!w.has(j)||k!==void 0&&E.recordedAt<k)continue;let W={ts:new Date(E.recordedAt).toISOString(),kind:j,update:T};T.messageId!==void 0&&T.messageId!==null&&(W.messageId=T.messageId),u.raw.write(JSON.stringify(W)+`
192
+ `)}}catch(v){if(v.code==="ENOENT")return u.raw.end(),u;throw v}return u.raw.end(),u}),s.post("/v1/sessions/:id/prompt/:messageId/notify",async(c,u)=>{let l=c.params,p=l.id,f=await e.resolveCanonicalId(p)??p,m=l.messageId,g=c.body,h=typeof g?.callbackUrl=="string"?g.callbackUrl:"",w=typeof g?.secret=="string"?g.secret:"";if(!m||!h||!w){u.code(400).send({error:"messageId, callbackUrl, and secret are all required"});return}let k;try{k=new URL(h)}catch{u.code(400).send({error:"callbackUrl must be a valid absolute URL"});return}if(k.protocol!=="https:"&&k.protocol!=="http:"){u.code(400).send({error:"callbackUrl must be http or https"});return}let y=e.get(f);if(!y){u.code(404).send({error:"session not found or not warm"});return}let b=y.registerTurnNotify(m,h,w);if(b.alreadyTerminal){u.code(200).send({status:"already_terminal",stopReason:b.stopReason});return}u.code(202).send({status:"registered"})}),s.get("/v1/sessions/:id/attention",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,f=e.get(p);return!f&&!await e.hasRecord(p)?(u.code(404).send({error:"session not found"}),u):f?{flags:f.listAttentionFlags()}:{flags:(await e.store.read(p))?.attentionFlags??[]}}),s.get("/v1/sessions/attention",async(c,u)=>{let l=c.query;if(!l.source||l.source.trim().length===0)return u.code(400).send({error:"source query parameter is required"}),u;let p=await e.list({includeNonInteractive:!0}),f=[];for(let m of p){let g=e.get(m.sessionId),h;g?h=g.listAttentionFlags():h=(await e.store.read(m.sessionId))?.attentionFlags??[];for(let w of h)w.source===l.source&&f.push({...w,sessionId:m.sessionId})}return{flags:f}}),s.post("/v1/sessions/:id/attention/clear",async(c,u)=>{let l=c.params.id,p=await e.resolveCanonicalId(l)??l,m=c.body??{},g=typeof m.source=="string"?m.source:"",h=typeof m.reason=="string"?m.reason:"";if((g.length>0||h.length>0)&&!(g.length>0&&h.length>0)){u.code(400).send({error:"both source and reason are required to clear a specific flag, or omit both to clear all"});return}g.length===0&&h.length;let w=e.get(p);if(w){if(g.length>0&&h.length>0)w.clearAttentionFlag(g,h);else{let v=Array.from(w.listAttentionFlags()).map(R=>`${R.source}::${R.reason}`);for(let R of v)w.clearAttentionFlag(R.split("::")[0],R.split("::").slice(1).join("::"))}u.code(204).send();return}if(!await e.hasRecord(p)){u.code(404).send({error:"session not found"});return}let k=e.store,y=await k.read(p);if(!y){u.code(404).send({error:"session not found"});return}let b=y.attentionFlags??[],I;if(g.length>0&&h.length>0){let v=`${g}::${h}`;I=b.filter(R=>`${R.source}::${R.reason}`!==v)}else I=[];if(I.length===b.length&&I.every((v,R)=>v.source===b[R].source&&v.reason===b[R].reason)){u.code(204).send();return}await k.write({...y,attentionFlags:I}),u.code(204).send()})}function Wd(s,e,t,n={}){s.get("/v1/agents",async()=>mt(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 Ie(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===A.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}Q();function qd(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:C.home(),driftedKeys:n()}))}var Kg=/^[A-Za-z0-9._-]+$/;function vs(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=Qg(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){hn(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){hn(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){hn(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){hn(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){hn(i,d)}})}function hn(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 Qg(s){let e=s.name;if(typeof e!="string"||!Kg.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 zd(s,e){vs(s,"extension",e)}function Jd(s,e){vs(s,"transformer",e)}function Vd(s,e){s.get("/v1/config",async()=>e())}import{z as Xe}from"zod";Q();import*as $t from"fs/promises";import*as Gd from"path";import{randomBytes as Qb,scrypt as Yg,timingSafeEqual as Xg}from"crypto";import{promisify as Zg}from"util";var em=Zg(Yg);function Kd(){return Gd.join(C.home(),"password-hash")}var tm=128*1024*1024;async function Qd(){try{return(await $t.readFile(Kd(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function Yd(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await $t.readFile(Kd(),"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 em(s,i,a.length,{N:n,r,p:o,maxmem:tm});return d.length!==a.length?!1:Xg(d,a)}var nm=Xe.object({password:Xe.string().min(1),label:Xe.string().min(1).max(256).optional(),ttlSec:Xe.number().int().positive().optional()}),sm=Xe.object({id:Xe.string().optional()}).optional(),rm=Xe.object({token:Xe.string().min(32)});function Xd(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=om(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=nm.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await Qd())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await Yd(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=sm.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=rm.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 om(s){return s.ip||"unknown"}import{nanoid as lo}from"nanoid";function Zd(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:A.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())}}}import{randomBytes as rc}from"crypto";import*as oc from"os";import*as ic from"path";var im=200;function am(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e[pe];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,im)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function ec(s,e,t){let n=am(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 tc(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 nc(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 $(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function fm(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 ve(s,e,t){let n=s.get(e);if(!n)throw $(A.SessionNotFound,t??`session ${e} not found`);return n}async function ct(s,e){let t=_t(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=rc(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=ao({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 Sm(c,s),dc(c.sessionId,s),c}function ac(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=pd({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=Zd(t),a=new yt(i),d={clientId:`hydra_client_${lo(12)}`,processIdentity:o,attached:new Map};a.onClose(()=>{for(let l of d.attached.values())e.manager.get(l.sessionId)?.detach(l.clientId);d.attached.clear()});let c=(l,p)=>{if(d.attached.get(l)?.readonly)throw $(A.PermissionDenied,`${p} not permitted on a read-only attachment`)};if(a.onRequest("initialize",async l=>{let p=ri.parse(l??{});p.clientInfo?.name&&(d.clientInfo={name:p.clientInfo.name,...p.clientInfo.version!==void 0?{version:p.clientInfo.version}:{}});let f=p.clientInfo?.version;return f&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,f):e.onTransformerVersion?.(o.name,f)),bm()}),o&&e.extensionCommands){let l=e.extensionCommands;a.onRequest("hydra-acp/commands/register",async p=>{let f=p??{},m=Array.isArray(f.commands)?f.commands.map(g=>{if(!g||typeof g!="object")return;let h=g;if(typeof h.verb!="string")return;let w={verb:h.verb};return typeof h.argsHint=="string"&&(w.argsHint=h.argsHint),typeof h.description=="string"&&(w.description=h.description),w}).filter(g=>g!==void 0):[];return l.register(o.name,a,m),{ok:!0,registered:m.length}}),a.onClose(()=>{l.clear(o.name)})}if(o&&e.extensionMcp){let l=e.extensionMcp;a.onRequest("hydra-acp/mcp_tools/register",async f=>{let m=f??{},g=typeof m.instructions=="string"?m.instructions:void 0,h=Array.isArray(m.tools)?m.tools.map(w=>{if(!w||typeof w!="object")return;let k=w;if(typeof k.name!="string"||k.name.length===0||typeof k.description!="string"||k.inputSchema===null||typeof k.inputSchema!="object")return;let y={name:k.name,description:k.description,inputSchema:k.inputSchema};return k.outputSchema!==null&&typeof k.outputSchema=="object"&&(y.outputSchema=k.outputSchema),y}).filter(w=>w!==void 0):[];if(h.length===0)throw new Error("register_mcp_tools requires at least one tool");return l.register(o.name,a,g,h),{ok:!0,registered:h.length}});let p=f=>{let m=f??{};if(typeof m.sessionId!="string"||m.sessionId.length===0)throw $(A.InvalidParams,"sessionId is required");return m.sessionId};if(a.onRequest("hydra-acp/session/extension_state/get",async f=>{let m=p(f),g=f??{};if(typeof g.key!="string"||g.key.length===0)throw $(A.InvalidParams,"key is required");if(!e.manager)throw $(A.InternalError,"manager not wired");return{value:await e.manager.getExtensionStateKey(m,o.name,g.key)??null}}),a.onRequest("hydra-acp/session/extension_state/list",async f=>{let m=p(f);if(!e.manager)throw $(A.InternalError,"manager not wired");return{state:await e.manager.getExtensionState(m,o.name)}}),a.onRequest("hydra-acp/session/extension_state/set",async f=>{let m=p(f),g=f??{};if(typeof g.key!="string"||g.key.length===0)throw $(A.InvalidParams,"key is required");if(g.value===void 0)throw $(A.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw $(A.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(m,o.name,g.key,g.value)}catch(h){throw $(A.InvalidParams,h.message)}return{ok:!0}}),a.onRequest("hydra-acp/session/extension_state/delete",async f=>{let m=p(f),g=f??{};if(typeof g.key!="string"||g.key.length===0)throw $(A.InvalidParams,"key is required");if(!e.manager)throw $(A.InternalError,"manager not wired");return await e.manager.deleteExtensionStateKey(m,o.name,g.key),{ok:!0}}),e.extensionMcpControls){let f=e.extensionMcpControls;a.onRequest("hydra-acp/mcp_tools/refresh_session",async m=>{let g=m??{};if(typeof g.sessionId!="string"||g.sessionId.length===0)throw $(A.InvalidParams,"refresh_session requires sessionId");return await f.notifyToolListChanged(g.sessionId,o.name),{ok:!0}})}a.onClose(()=>{l.clear(o.name)})}if(o?.kind==="transformer"){a.onRequest("hydra-acp/transformer/initialize",async p=>{let f=p??{},m=Array.isArray(f.intercepts)?f.intercepts.filter(g=>typeof g=="string"):[];if(e.transformers&&(e.transformers.registerConnection(o.name,a,m),e.manager?.defaultTransformers.includes(o.name))){let g=e.transformers.resolveChain([o.name])[0];if(g)for(let h of e.manager.liveSessions())h.addTransformer(g)}return{ack:!0}}),a.onClose(()=>{e.transformers?.deregisterConnection(o.name)}),a.onRequest("hydra-acp/message/emit",async p=>{let f=p??{},m=typeof f.sessionId=="string"?f.sessionId:void 0,g=typeof f.method=="string"?f.method:void 0,h=f.envelope,w=f.route;if(!m)throw $(-32602,"emit_message requires sessionId");if(!g&&w!=="client_broadcast")throw $(-32602,"emit_message requires method");let k=ve(e.manager,m),y=typeof f.respondsTo=="string"?f.respondsTo:void 0;if(y)return k.dischargeClaim(y,h),{ok:!0};if(w==="chain")return{ok:!0,response:await k.emitToChain(o.name,g,h)};if(w==="queue"){if(g!=="session/prompt")throw $(-32602,'route "queue" only supports method "session/prompt"');return{ok:!0,response:await k.emitToQueue(o.name,h)}}if(w==="daemon")return{ok:!0,response:await k.emitToChain(o.name,g,h)};if(w==="client_broadcast"){if(!h||typeof h!="object")throw $(-32602,"client_broadcast requires an envelope object");return k.broadcastClientUpdate(h),{ok:!0}}throw $(-32602,`unsupported route: ${JSON.stringify(w)}`)}),a.onRequest("hydra-acp/session/request_permission",async p=>{let f=p??{},m=typeof f.sessionId=="string"?f.sessionId:void 0;if(!m)throw $(-32602,"hydra-acp/session/request_permission requires sessionId");return ve(e.manager,m).requestPermissionFromClients(f)}),a.onRequest("hydra-acp/transformer/attach",async p=>ym(p,o.name,e)),a.onRequest("hydra-acp/child_session/spawn",async p=>{let f=p??{},m=typeof f.agentId=="string"?f.agentId:void 0,g=typeof f.cwd=="string"?f.cwd:void 0,h=typeof f.parentSessionId=="string"?f.parentSessionId:void 0,w=f._meta&&typeof f._meta=="object"?f._meta:void 0,k=w&&w["hydra-acp"]&&typeof w["hydra-acp"]=="object"?w["hydra-acp"]:void 0,y=k&&typeof k.title=="string"?k.title:void 0,b=k&&typeof k.model=="string"?k.model:void 0;if(!g&&h){let j=e.manager.get(h);j&&(g=j.cwd)}if(!g)throw $(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let I=await Ut(g),v=m??I.agentId??e.defaultAgent,R=await e.registry?.getAgent(v),x=Wt(I.models,R??{id:v})?.value,E=b??x,O=typeof f.interactive=="boolean"?f.interactive:!1;return{childSessionId:(await e.manager.create({agentId:v,cwd:g,parentSessionId:h,interactive:O,transformChain:[],title:y,model:E})).sessionId}}),a.onRequest("hydra-acp/session/fork",async p=>{let f=p??{};if(typeof f.sessionId!="string")throw $(A.InvalidParams,"fork_session requires sessionId");let m=typeof f.forkAt=="string"?f.forkAt:void 0,g=typeof f.cwd=="string"?f.cwd:void 0,h=typeof f.agentId=="string"?f.agentId:void 0,w=typeof f.mode=="string"&&(f.mode==="verbatim"||f.mode==="synthesis")?f.mode:void 0,k=typeof f.model=="string"&&f.model.length>0?f.model:void 0,y=await e.manager.forkSession(f.sessionId,{...m!==void 0?{forkAt:m}:{},...g!==void 0?{cwd:g}:{},...h!==void 0?{agentId:h}:{},...w!==void 0?{mode:w}:{},...k!==void 0?{model:k}:{}}),b=e.manager.get(y.sessionId);if(!b){let R=await e.manager.loadFromDisk(y.sessionId);if(!R)throw $(A.InternalError,`fork ${y.sessionId} vanished before it could be attached`);b=await ct(e,{...R,onInstallProgress:bs(a)})}Ot(d,b,b.sessionId);let I=Ze(a,b,d),{entries:v}=await b.attach(I,"full");d.attached.set(b.sessionId,{sessionId:b.sessionId,clientId:I.clientId,readonly:!1});for(let R of v){if(a.isClosed())break;await a.notify(R.method,_e(R.params,R.recordedAt)).catch(()=>{})}return{...y,sessionId:b.sessionId}}),a.onRequest("session/fork",async p=>{let f=p??{};if(typeof f.sessionId!="string")throw $(A.InvalidParams,"session/fork requires sessionId");let m=typeof f.cwd=="string"?f.cwd:void 0,g=await e.manager.forkSession(f.sessionId,{...m!==void 0?{cwd:m}:{},mode:"verbatim"}),h=e.manager.get(g.sessionId);if(!h){let y=await e.manager.loadFromDisk(g.sessionId);if(!y)throw $(A.InternalError,`fork ${g.sessionId} vanished before it could be attached`);h=await ct(e,{...y,onInstallProgress:bs(a)})}Ot(d,h,h.sessionId);let w=Ze(a,h,d),{entries:k}=await h.attach(w,"full");d.attached.set(h.sessionId,{sessionId:h.sessionId,clientId:w.clientId,readonly:!1});for(let y of k){if(a.isClosed())break;await a.notify(y.method,_e(y.params,y.recordedAt)).catch(()=>{})}return{sessionId:h.sessionId}});let l=async(p,f)=>{let m=p??{};if(typeof m.sessionId!="string")throw $(A.InvalidParams,`${f} requires sessionId`);let g=await e.manager.resolveCanonicalId(m.sessionId)??m.sessionId,h=e.manager.get(g);if(h)return await h.close({deleteRecord:!0,by:`session/delete ${d.clientId}`}),await e.manager.waitForDeletion(g),await e.manager.hasRecord(g)&&await e.manager.deleteRecord(g),{id:g,existed:!0};let w=await e.manager.deleteRecord(g);return{id:g,existed:w}};a.onRequest("session/delete",async p=>(await l(p,"session/delete"),{})),a.onRequest("session/close",async p=>{let f=p??{};if(typeof f.sessionId!="string")throw $(A.InvalidParams,"session/close requires sessionId");c(f.sessionId,"session/close");let m=await e.manager.resolveCanonicalId(f.sessionId)??f.sessionId,g=e.manager.get(m);if(g)return await g.close({deleteRecord:!1,by:`session/close ${d.clientId}`+(d.processIdentity?` (${d.processIdentity.name})`:"")}),{};if(await e.manager.hasRecord(m))return{};throw $(A.SessionNotFound,`session ${m} not found`)}),a.onRequest("hydra-acp/session/delete",async p=>{let{id:f,existed:m}=await l(p,"hydra-acp/session/delete");if(!m)throw $(A.SessionNotFound,`session ${f} not found`);return{deleted:!0,sessionId:f}}),a.onRequest("hydra-acp/child_session/await",async p=>{let f=p??{},m=typeof f.childSessionId=="string"?f.childSessionId:void 0,g=f.until==="idle"?"idle":"turn_complete",h=typeof f.timeoutMs=="number"?Math.min(f.timeoutMs,18e5):3e5;if(!m)throw $(-32602,"await_child requires childSessionId");let w=ve(e.manager,m,`child session ${m} not found`);return new Promise(k=>{let I=[],v=[],R=0,x=!1,E,O,T=!1,j=()=>{T||(T=!0,clearTimeout(W),E?.(),O?.(),k(x?{entries:I,truncated:!0}:{entries:I}))};E=w.onBroadcast(q=>{let ne=fm(q);for(I.push(q),v.push(ne),R+=ne;I.length>0&&(I.length>1e3||R>1048576);)I.shift(),R-=v.shift()??0,x=!0;g==="turn_complete"&&q.params?.update?.sessionUpdate==="turn_complete"&&j()});let W=setTimeout(j,h);typeof W.unref=="function"&&W.unref(),O=w.onClose(()=>j())})}),a.onRequest("hydra-acp/child_session/close",async p=>{let f=p??{},m=typeof f.childSessionId=="string"?f.childSessionId:void 0;if(!m)throw $(-32602,"close_child_session requires childSessionId");let g=e.manager.get(m);return g&&await g.close({deleteRecord:!1,by:`child_session/close ${d.clientId}`}),{ok:!0}}),a.onRequest("hydra-acp/attention/set",async p=>wm(p,o.name,e)),a.onRequest("hydra-acp/attention/clear",async p=>km(p,o.name,e)),a.onRequest("hydra-acp/connection/keep_alive",async p=>{let f=p??{},m=typeof f.token=="string"?f.token:void 0,g=typeof f.sessionId=="string"?f.sessionId:void 0,h=typeof f.estimatedRemainingMs=="number"?f.estimatedRemainingMs:void 0;return m&&g&&e.manager.get(g)?.keepAliveClaim(m,h),{ok:!0}})}a.onRequest("hydra-acp/session/tool_content",async l=>{let p=l??{};if(typeof p.sessionId!="string"||typeof p.hash!="string")throw $(A.InvalidParams,"hydra-acp/session/tool_content requires sessionId and hash");let f=await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,m=await e.manager.loadToolBlob(f,p.hash);if(m===null)throw $(A.SessionNotFound,"tool content not found");return{content:m}}),a.onRequest("authenticate",async l=>pm(l,e)),a.onRequest("logout",async l=>gm(l,e)),a.onRequest("session/new",async l=>{let p=oi.parse(l),f=tt(l?._meta),m=Array.isArray(f.transformers)&&f.transformers.every(J=>typeof J=="string")?f.transformers:e.manager.defaultTransformers??[],g=e.transformers?.resolveChain(m)??[],h=await Ut(p.cwd),w=f.agentId??h.agentId??e.defaultAgent,k=await e.registry?.getAgent(w),y=Wt(h.models,k??{id:w})?.value,b,I,v=p.mcpServers;if(f.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){b=rc(32).toString("hex"),I=e.mcpTokenRegistry.reserve(b);let be={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${b}`}]};v=[...p.mcpServers??[],be]}let R,x,E=_t(e);E!==void 0&&(v=[...v??[],...E.descriptors]);let O=ao({baselineMcpServers:p.mcpServers,stdinEnabled:f.mcpStdin===!0,deps:e}),T;try{T=await e.manager.create({cwd:p.cwd,agentId:w,mcpServers:v,title:f.title,agentArgs:f.agentArgs,model:f.model??y,onInstallProgress:bs(a),transformChain:g,originatingClient:d.clientInfo,...f.interactive!==void 0?{interactive:f.interactive}:{},...f.env!==void 0?{forwardedEnv:f.env}:{},...f.workspace!==void 0?{workspace:f.workspace}:{},...O?{mintMcpServersForSwap:O}:{}})}catch(J){throw I!==void 0&&I.abandon(J instanceof Error?J:void 0),x!==void 0&&x.abandon(J instanceof Error?J:void 0),E!==void 0&&E.abandon(J instanceof Error?J:void 0),J}if(b!==void 0&&I!==void 0&&e.mcpTokenRegistry!==void 0){let J=b,be=e.mcpTokenRegistry;I.complete(T),T.onClose(()=>{be.unbind(J)})}if(R!==void 0&&x!==void 0&&e.mcpTokenRegistry!==void 0){let J=R,be=e.mcpTokenRegistry;x.complete(T),T.onClose(()=>{be.unbind(J)})}E!==void 0&&E.bindToSession(T),dc(T.sessionId,e);let j,W;try{Ot(d,T,T.sessionId),j=Ze(a,T,d),{entries:W}=await T.attach(j,"full")}catch(J){throw await T.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),J}d.attached.set(T.sessionId,{sessionId:T.sessionId,clientId:j.clientId,readonly:!1}),setImmediate(()=>{(async()=>{for(let J of W){if(a.isClosed())break;await a.notify(J.method,_e(J.params,J.recordedAt)).catch(()=>{})}})()});let q=Ss(T),ne=Is(T);return{sessionId:T.sessionId,...q?{modes:q}:{},...ne?{models:ne}:{},configOptions:T.buildConfigOptions(),_meta:As(e.manager,T,{clientId:j.clientId})}}),a.onRequest("session/attach",async l=>{let p=ai.parse(l),f=p.clientInfo?.version;f&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,f):e.onTransformerVersion?.(o.name,f));let m=tt(p._meta),g=m.resume,h=m.readonly===!0,w=m.env;s.log.info(`session/attach sessionId=${p.sessionId} hasResumeHints=${!!g} readonly=${h}`);let k=g?p.sessionId:await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,y=e.manager.get(k);if(!y&&h){let T=await e.manager.loadFromDisk(k);if(!T)throw $(A.SessionNotFound,`session ${p.sessionId} not found`);let j=await e.manager.loadHistory(k),W=p.clientId??`cli_${lo(8)}`;d.attached.set(T.hydraSessionId,{sessionId:T.hydraSessionId,clientId:W,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${T.hydraSessionId} clientId=${W} attachedCount=${d.attached.size} replayed=${j.length}`);for(let q of j)await a.notify(q.method,_e(q.params,q.recordedAt)).catch(()=>{});return{sessionId:T.hydraSessionId,clientId:W,connectedClients:[W],historyPolicy:"full",replayed:j.length,_meta:vm(T)}}let b=!y;if(!y){let T=await e.manager.loadFromDisk(k),j=await mm(k,g,T?.upstreamSessionId,e.manager);j.kind==="ignore"&&s.log.warn(j.logMessage);let W=T;if(g&&j.kind==="honor"&&(W={...T,hydraSessionId:p.sessionId,upstreamSessionId:g.upstreamSessionId,agentId:g.agentId,cwd:T?.workspace?.path??g.cwd,...g.title!==void 0?{title:g.title}:{},...g.agentArgs!==void 0?{agentArgs:g.agentArgs}:{}}),!W)throw $(A.SessionNotFound,`session ${p.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(W.agentId,W.upstreamSessionId))throw $(A.SessionNotFound,`session ${p.sessionId} was deleted`);let q=W.originatingClient?W:{...W,originatingClient:d.clientInfo},ne=w!==void 0?{...q,forwardedEnv:w}:q;y=await ct(e,{...ne,onInstallProgress:bs(a)})}Ot(d,y,y.sessionId);let I=Ze(a,y,d,p.clientInfo,p.clientId),v=m.replayMode==="drip",{entries:R,appliedPolicy:x}=await y.attach(I,p.historyPolicy,{afterMessageId:p.afterMessageId,raw:v,...m.toolContent!==void 0?{toolContent:m.toolContent}:{}});if(d.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:I.clientId,readonly:h}),w!==void 0&&await e.manager.setForwardedEnv(y.sessionId,w).catch(()=>{}),s.log.info(`session/attach OK sessionId=${y.sessionId} clientId=${I.clientId} attachedCount=${d.attached.size} requestedPolicy=${p.historyPolicy} appliedPolicy=${x} replayed=${R.length} readonly=${h}${v?" replayMode=drip":""}`),v){let T=m.dripSpeed&&m.dripSpeed>0?m.dripSpeed:1,j=750;(async()=>{let W=null;for(let q of R){let ne=typeof q.recordedAt=="number"?q.recordedAt:null;if(W!==null&&ne!==null){let J=Math.min(j,Math.max(0,(ne-W)/T));J>0&&await new Promise(be=>setTimeout(be,J))}ne!==null&&(W=ne);try{await a.notify(q.method,_e(q.params,ne??void 0))}catch{return}}})()}else for(let T=0;T<R.length&&!a.isClosed();T++){let j=R[T],W=a.notify(j.method,_e(j.params,j.recordedAt)).catch(()=>{});(T+1)%200===0&&await W}y.replayPendingPermissions(I);let E=Ss(y),O=Is(y);return{sessionId:y.sessionId,clientId:I.clientId,connectedClients:y.connectedClients(I.clientId),historyPolicy:x,replayed:R.length,...E?{modes:E}:{},...O?{models:O}:{},configOptions:y.buildConfigOptions(),_meta:As(e.manager,y,{resurrected:b})}}),a.onRequest("session/detach",async l=>{let p=di.parse(l),f=d.attached.get(p.sessionId);if(!f)throw $(A.SessionNotFound,"client not attached to that session");let m=e.manager.get(p.sessionId);return m?.detach(f.clientId),d.attached.delete(p.sessionId),m&&e.manager.reapIfOrphanedNonInteractive(p.sessionId),{sessionId:p.sessionId,_meta:{[pe]:{detachStatus:"detached"}}}}),a.onRequest("session/list",async l=>{let p=ci.parse(l??{});return{sessions:(await e.manager.list({cwd:p.cwd})).filter(h=>h.originatingClient?.name!==Vn).map(ui)}}),a.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw $(A.InternalError,"agent registry unavailable");return mt(e.registry)}),a.onRequest("hydra-acp/agents/auth_methods",async l=>{let p=l??{};if(typeof p.agentId!="string"||p.agentId.length===0)throw $(A.InvalidParams,"hydra-acp/agents/auth_methods requires a non-empty agentId string");return{authMethods:(await e.manager.bootstrapAgentForAuth(p.agentId)).authMethods??[]}}),a.onRequest("session/prompt",async l=>{let p=li.parse(l);c(p.sessionId,"session/prompt");let f=await ec(p,e.manager,w=>{s.log.warn(`session/prompt: dropping unknown sentBy.sessionId=${w} sessionId=${p.sessionId}`)});if(f?.fromSession!==void 0){if((f.depth??0)>3)throw s.log.warn(`session/prompt: refusing depth ${f.depth} chain from ${f.fromSession} to ${p.sessionId}`),$(A.InvalidRequest,`message chain too deep (${f.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(f.awaiting===!0&&nc(f.fromSession,p.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${f.fromSession} -> ${p.sessionId}`),$(A.InvalidRequest,`would deadlock: ${p.sessionId} is already blocked waiting on ${f.fromSession}. Send with --no-wait, or let the other turn finish first.`)}let m=d.attached.get(p.sessionId);if(!m)throw s.log.warn(`session/prompt rejected: not attached sessionId=${p.sessionId} attachedKeys=[${[...d.attached.keys()].join(",")}]`),$(A.SessionNotFound,"not attached to session");let g=e.manager.get(p.sessionId);if(!g){let w=await e.manager.loadFromDisk(p.sessionId);if(!w)throw $(A.SessionNotFound,`session ${p.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${p.sessionId}`),g=await ct(e,w);let k=Ze(a,g,d,void 0,m.clientId);await g.attach(k,"none")}let h=f?.awaiting===!0&&f.fromSession!==void 0?tc(f.fromSession,p.sessionId):void 0;try{return await g.prompt(m.clientId,p,f)}finally{h?.()}});let u=l=>{let p;try{p=Rn.parse(l)}catch(g){s.log.warn(`session/cancel: invalid params: ${g.message}`);return}let f=d.attached.get(p.sessionId);if(!f)return;if(f.readonly){s.log.warn(`session/cancel dropped (readonly attachment) sessionId=${p.sessionId}`);return}let m=e.manager.get(p.sessionId);m&&m.cancel(f.clientId).catch(g=>{s.log.warn(`session/cancel for ${p.sessionId}: ${g.message}`)})};a.onNotification("session/cancel",u),a.onRequest("session/cancel",async l=>{let p=Rn.parse(l);return c(p.sessionId,"session/cancel"),u(l),null}),a.onRequest("hydra-acp/prompt/cancel",async l=>{let p=pi.parse(l);return c(p.sessionId,"hydra-acp/prompt/cancel"),ve(e.manager,p.sessionId).cancelQueuedPrompt(p.messageId)}),a.onRequest("hydra-acp/session/force_cancel",async l=>{let p=Rn.parse(l);return c(p.sessionId,"hydra-acp/session/force_cancel"),ve(e.manager,p.sessionId).forceCancel()}),a.onRequest("hydra-acp/prompt/update",async l=>{let p=gi.parse(l);return c(p.sessionId,"hydra-acp/prompt/update"),ve(e.manager,p.sessionId).updateQueuedPrompt(p.messageId,p.prompt)}),a.onRequest("hydra-acp/prompt/amend",async l=>{let p=mi.parse(l);c(p.sessionId,"hydra-acp/prompt/amend");let f=d.attached.get(p.sessionId);if(!f)throw $(A.SessionNotFound,"not attached to session");return ve(e.manager,p.sessionId).amendPrompt(f.clientId,p)}),a.onRequest("_session/steering",async l=>{let p=hi.parse(l);c(p.sessionId,"_session/steering");let f=d.attached.get(p.sessionId);if(!f)throw $(A.SessionNotFound,"not attached to session");let m=e.manager.get(p.sessionId);if(!m){let g=await e.manager.loadFromDisk(p.sessionId);if(!g)throw $(A.SessionNotFound,`session ${p.sessionId} not found`);m=await ct(e,g);let h=Ze(a,m,d,void 0,f.clientId);await m.attach(h,"none")}return m.steer(f.clientId,p)}),a.onRequest("session/resume",async l=>{let p=l??{},f=typeof p.sessionId=="string"?p.sessionId:void 0;if(!f)throw $(A.InvalidParams,"session/resume requires sessionId");let m=await e.manager.resolveCanonicalId(f)??f,g=e.manager.get(m);if(!g){let y=await e.manager.loadFromDisk(m);if(!y)throw $(A.SessionNotFound,`session ${f} not found in memory or on disk`);g=await ct(e,y)}Ot(d,g,g.sessionId);let h=Ze(a,g,d);await g.attach(h,"pending_only"),d.attached.set(g.sessionId,{sessionId:g.sessionId,clientId:h.clientId,readonly:!1}),g.replayPendingPermissions(h);let w=Ss(g),k=Is(g);return{sessionId:g.sessionId,...w?{modes:w}:{},...k?{models:k}:{},configOptions:g.buildConfigOptions(),_meta:As(e.manager,g,{clientId:h.clientId})}}),a.onRequest("session/load",async l=>{let p=l??{},f=typeof p.sessionId=="string"?p.sessionId:void 0;if(!f)throw $(A.InvalidParams,"session/load requires sessionId");let m=await e.manager.resolveCanonicalId(f)??f,g=e.manager.get(m);if(!g){let b=await e.manager.loadFromDisk(m);if(!b)throw $(A.SessionNotFound,`session ${f} not found in memory or on disk`);g=await ct(e,b)}Ot(d,g,g.sessionId);let h=Ze(a,g,d),{entries:w}=await g.attach(h,"full");d.attached.set(g.sessionId,{sessionId:g.sessionId,clientId:h.clientId,readonly:!1});for(let b of w){if(a.isClosed())break;await a.notify(b.method,_e(b.params,b.recordedAt)).catch(()=>{})}g.replayPendingPermissions(h);let k=Ss(g),y=Is(g);return{sessionId:g.sessionId,...k?{modes:k}:{},...y?{models:y}:{},configOptions:g.buildConfigOptions(),_meta:As(e.manager,g,{clientId:h.clientId})}}),a.onRequest("session/set_model",async l=>{let p=l?.sessionId;typeof p=="string"&&c(p,"session/set_model");let f=hm(l,e.manager);if(f.kind==="error")throw s.log.warn(f.logMessage),$(f.code,f.message);if(f.kind==="no_op")return s.log.warn(f.logMessage),await a.notify("session/update",{sessionId:f.sessionId,update:{sessionUpdate:"_hydra_current_model_update",currentModel:f.currentModel}}).catch(()=>{}),null;s.log.info(f.logMessage);let{modelId:m}=f,g=await f.session.forwardModelChange(m,l);return f.session.applyAgentConfigOptionResponse(g,"model"),f.session.applyModelChange(m),g}),a.onRequest("session/set_mode",async l=>{let p=l,f=p?.sessionId;if(typeof f=="string"&&c(f,"session/set_mode"),!p||typeof p.sessionId!="string")throw $(A.InvalidParams,"session/set_mode requires string sessionId");if(typeof p.modeId!="string")throw $(A.InvalidParams,"session/set_mode requires string modeId");let m=ve(e.manager,p.sessionId),g=await m.forwardRequest("session/set_mode",l);return m.applyModeChange(p.modeId),g}),a.onRequest("session/set_config_option",async l=>{let p=l,f=w=>$(A.InvalidParams,w),m=p?.sessionId;if(typeof m=="string"&&c(m,"session/set_config_option"),!p||typeof p.sessionId!="string")throw f("session/set_config_option requires string sessionId");if(typeof p.configId!="string")throw f("session/set_config_option requires string configId");if(typeof p.value!="string")throw f("session/set_config_option requires string value");let g=ve(e.manager,p.sessionId),h=g.buildConfigOptions().find(w=>w.id===p.configId);if(!h)throw f(`unknown configId ${JSON.stringify(p.configId)} for this session`);if(!h.options.some(w=>w.value===p.value))throw f(`value ${JSON.stringify(p.value)} is not valid for configId ${JSON.stringify(p.configId)}`);switch(p.configId){case"model":{if(p.value!==g.currentModel){let w=await g.forwardModelChange(p.value);g.applyAgentConfigOptionResponse(w,"model")}g.applyModelChange(p.value);break}case"mode":{p.value!==g.currentMode&&await g.forwardRequest("session/set_mode",{sessionId:p.sessionId,modeId:p.value}),g.applyModeChange(p.value);break}case"agent":{p.value!==g.agentId&&await g.setAgent(p.value);break}default:{let w=await g.forwardRequest("session/set_config_option",{sessionId:p.sessionId,configId:p.configId,value:p.value});g.applyAgentConfigOptionResponse(w,p.configId)&&g.broadcastConfigOptions()}}return{configOptions:g.buildConfigOptions()}}),a.setDefaultHandler(async(l,p)=>{let f=new Set(["hydra-acp/attention/set","hydra-acp/attention/clear"]),m=p.startsWith("session/"),g=p.startsWith("hydra-acp/");if(!m&&!g||l===null||typeof l!="object"||f.has(p))throw $(A.MethodNotFound,`Method not found: ${p}`);let h=l.sessionId;if(typeof h!="string")throw $(A.MethodNotFound,`Method not found: ${p}`);return c(h,p),ve(e.manager,h).forwardRequest(p,l)})})}async function pm(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw $(A.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(m=>m.id);throw $(A.InvalidParams,`authenticate: methodId ${JSON.stringify(n)} is not advertised by agent ${a.agentId}; valid: [${f.map(m=>JSON.stringify(m)).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=(y,b)=>{if(!Array.isArray(y))throw $(A.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be a string[]; got ${y===null?"null":typeof y}`);for(let I of y)if(typeof I!="string")throw $(A.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be string[]; got non-string entry ${JSON.stringify(I)}`);return y},m=await e.manager.planSpawnForAgent(a.agentId),g,h;if(l?.args!==void 0){let y=typeof l.command=="string"?l.command:void 0;g=y!==void 0&&ic.isAbsolute(y)?y:m.command,h=f(l.args,'_meta["terminal-auth"].args')}else{let y=c.args!==void 0?{raw:c.args,label:"args"}:c._meta?.args!==void 0?{raw:c._meta.args,label:"_meta.args"}:void 0,b=y!==void 0?f(y.raw,y.label):[];g=m.command,h=[...m.args,...b]}let w={};for(let[y,b]of Object.entries(process.env))typeof b=="string"&&(w[y]=b);Object.assign(w,m.env);let k=oc.homedir();return console.error(`[authenticate] terminal-auth requested agentId=${a.agentId} methodId=${n}`),{kind:"terminal",command:g,args:h,env:w,cwd:k}}try{return await a.connection.request("authenticate",{methodId:n})}catch(f){throw Ye(f,a)}}async function gm(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 bs(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(yi,t).catch(()=>{})}}function Ss(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 Is(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 mm(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 hm(s,e){if(!s||typeof s!="object")return{kind:"error",code:A.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:A.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:A.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:A.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=bt(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:A.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 ym(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw $(A.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw $(A.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw $(A.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return ve(t.manager,r).addTransformer(o),{ok:!0}}async function wm(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 $(A.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw $(A.InvalidParams,"hydra-acp/attention/set requires string reason");return ve(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function km(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 $(A.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw $(A.InvalidParams,"hydra-acp/attention/clear requires string reason");return ve(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function vm(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:sn(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{[pe]:Cn(e,t)}}function As(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 qt(e.agentMeta,Cn(n,r))}function bm(){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:{...qt(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}}}),steering:{supported:!0}}}}function Sm(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 dc(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 Ze(s,e,t,n,r){return{clientId:r??`cli_${lo(8)}`,connection:s,clientInfo:n}}function Ot(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var Cs=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 Im}from"crypto";import{McpServer as Am}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Cm}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as le}from"zod";function fo(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 he(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var cc="Bearer ";function Ft(s){let e=s.headers.authorization;if(typeof e!="string"||!e.startsWith(cc))return;let t=e.slice(cc.length).trim();return t.length>0?t:void 0}function Rm(s){let e=new Am({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:le.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return he(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:le.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return he(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:le.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:le.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:le.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 he(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:le.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:le.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 he({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:le.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:le.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:le.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:le.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:le.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:le.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:le.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:le.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:le.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 he(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 he(t)}),e}var xm=1e4;function uc(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=Rm(a),u=new Cm({sessionIdGenerator:()=>Im()});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=Ft(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(g=>{p=setTimeout(()=>g(void 0),xm)}),m=await Promise.race([c.sessionReady.catch(()=>{}),f]);if(p!==void 0&&clearTimeout(p),m===void 0){a.code(503).send({error:"session not ready"});return}u=m}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 Em}from"crypto";import{McpServer as Tm}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Pm}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as De}from"zod";function Mm(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var lc=2e3,fc=2e4;function _m(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return St([s]);let n=[],r=Jt(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=Pn(t);return i!==void 0&&n.push(i),n.join(`
193
+ `)}function $m(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 Om(s){let e=new Tm({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:De.string().min(1).describe("Case-insensitive substring to search for."),limit:De.number().int().min(1).max(50).optional().describe("Maximum number of matches to return (default 10, max 50)."),include_tool_calls:De.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 he({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=fo(u);if(!l)continue;let{kind:p,update:f}=l;if((p==="tool_call"||p==="tool_call_update")&&!r)continue;let m=_m(u,p,f),g=m.toLowerCase().indexOf(a);if(g<0)continue;let h=Mm(p),w=$m(m,g),k=typeof u.recordedAt=="number"?String(u.recordedAt):void 0;if(i.push({entryId:c,speaker:h,snippet:w,timestamp:k}),i.length>=n)break}i.sort((c,u)=>c.entryId-u.entryId);let d=i.length>=n;return he({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:De.number().int().min(0).describe("Zero-based index of the first entry to include (inclusive)."),to_entry:De.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 he({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 he({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=St(u,{toolOutput:{maxPerCall:lc,maxTotal:fc}});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:De.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:De.string().optional().describe("ACP tool kind: execute (shell), read, edit, think, other. Agent-independent, unlike tool_name."),file_path:De.string().optional(),limit:De.number().int().min(1).max(100).optional(),include_output:De.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 he({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:k,entry:y}of a.iterRecallNewestFirst()){let b=fo(y);if(!b)continue;let{kind:I,update:v}=b;if(I!=="tool_call"&&I!=="tool_call_update")continue;let R=typeof v.toolCallId=="string"&&v.toolCallId.length>0?v.toolCallId:`__noid_${k}`,x=l.get(R);if(x||(x={entryId:k,toolName:"(unnamed)",nameAuthoritative:!1,rawInput:{},locations:[],status:"in_progress"},l.set(R,x)),k<x.entryId&&(x.entryId=k),!x.nameAuthoritative){let O=Jt(v);O!==void 0?(x.toolName=O,x.nameAuthoritative=!0):typeof v.name=="string"&&v.name.length>0?(x.toolName=v.name,x.nameAuthoritative=!0):I==="tool_call"&&typeof v.title=="string"&&v.title.length>0&&(x.toolName=v.title,x.nameAuthoritative=!0)}if(x.kind===void 0&&typeof v.kind=="string"&&v.kind.length>0&&(x.kind=v.kind),x.output===void 0){let O=Pn(v);O!==void 0&&(x.output=O)}let E=v.rawInput;if(E&&typeof E=="object"&&!Array.isArray(E)&&Object.keys(E).length>0)for(let[O,T]of Object.entries(E))x.rawInput[O]===void 0&&(x.rawInput[O]=T);if(Array.isArray(v.locations))for(let O of v.locations){let T=O?.path;typeof T=="string"&&T.length>0&&!x.locations.includes(T)&&x.locations.push(T)}if(typeof v.status=="string"&&x.status==="in_progress"&&(x.status=v.status),y.recordedAt!==void 0&&x.timestamp===void 0&&(x.timestamp=String(y.recordedAt)),l.size>=p)break}let f=[...l.keys()].sort((k,y)=>l.get(k).entryId-l.get(y).entryId),m=[],g=fc,h=!1;for(let k of f){let y=l.get(k);if(y.toolName=ar({name:y.toolName,rawInput:y.rawInput,...y.kind!==void 0?{kind:y.kind}:{}}),d&&!y.toolName.toLowerCase().includes(t.toLowerCase())||c&&(y.kind??"").toLowerCase()!==n.toLowerCase())continue;if(u){let v=r.toLowerCase(),R=["file_path","filePath","path"],x=!1;for(let E of R){let O=y.rawInput[E];if(typeof O=="string"&&O.toLowerCase().includes(v)){x=!0;break}}if(!x){for(let E of y.locations)if(E.toLowerCase().includes(v)){x=!0;break}}if(!x)continue}let b={};for(let[v,R]of Object.entries(y.rawInput))typeof R=="string"?b[v]=R.length>500?R.slice(0,497)+"\u2026":R:(typeof R=="number"||typeof R=="boolean")&&(b[v]=R);y.locations.length>0&&b.locations===void 0&&(b.locations=y.locations);let I={entryId:y.entryId,tool:y.toolName,args:b,status:y.status,timestamp:y.timestamp};if(y.kind!==void 0&&(I.kind=y.kind),i&&y.output!==void 0){let v=y.output,R=Math.min(lc,g);if(R<=0)h=!0;else{let x=v.length<=R?v:v.slice(0,R-1)+"\u2026";I.output=x,I.outputBytes=v.length,I.outputTruncated=x.length<v.length,g-=x.length}}if(m.push(I),m.length>=o)break}let w=m.length>=o;return he({calls:m,truncated:w,...h?{outputBudgetExhausted:h}:{}})}),e}var Fm=1e4;function pc(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=Om(a),u=new Pm({sessionIdGenerator:()=>Em()});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=Ft(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(g=>{p=setTimeout(()=>g(void 0),Fm)}),m=await Promise.race([c.sessionReady.catch(()=>{}),f]);if(p!==void 0&&clearTimeout(p),m===void 0)throw new Error("recall: session not ready");return m});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 Rs=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 Wm}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{randomUUID as qm}from"crypto";import{Server as Nm}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Hm,ListToolsRequestSchema as jm}from"@modelcontextprotocol/sdk/types.js";function gc(s,e,t,n){let r=typeof t=="function"?async()=>t():async()=>t,o=new Nm({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(jm,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(Hm,async(a,d)=>{let c=a.params.name,u=d._meta?.progressToken??d.requestId,l=Um(u,d.sendNotification);try{let p=await r(),f=await Lm(e.connection,s,c,a.params.arguments??{},p);return Bm(f,c)}catch(p){return po(p instanceof Error?p.message:String(p))}finally{l()}}),o}var Dm=15e3;function Um(s,e,t=Dm){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 Lm(s,e,t,n,r){return await s.request("hydra-acp/mcp_tools/invoke",{server:e,tool:t,args:n,sessionId:r})}function Bm(s,e){if(s===null||typeof s!="object")return po(`extension ${e} returned non-object`);let t=s;return Array.isArray(t.content)?t:po(`extension ${e} omitted content array`)}function po(s){return{content:[{type:"text",text:s}],isError:!0}}var zm=1e4;function mc(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 g=f.get(l);if(g!==void 0)try{await g.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 b=n.get(u);if(b!==void 0){n.delete(u);for(let I of b.values())await r(I)}}));let f=p.get(l);if(f!==void 0)return f.transport;let m=t.lookup(l);if(m===void 0)return;let k=gc(l,m,async()=>{let b=e.lookup(u);if(b===void 0)throw new Error("mcp token no longer bound");if(b.session!==void 0)return b.session.sessionId;let I,v=new Promise(x=>{I=setTimeout(()=>x(void 0),zm)}),R=await Promise.race([b.sessionReady.catch(()=>{}),v]);if(I!==void 0&&clearTimeout(I),R===void 0)throw new Error("session not ready");return R.sessionId},{peekSessionId:()=>e.lookup(u)?.session?.sessionId,fetchSessionTools:async b=>{let I=await m.connection.request("hydra-acp/mcp_tools/list_tools",{sessionId:b});if(!I||typeof I!="object")return;let v=I.tools;if(!Array.isArray(v))return;let R=[];for(let x of v){if(!x||typeof x!="object")continue;let E=x;if(typeof E.name!="string"||E.name.length===0||typeof E.description!="string"||E.inputSchema===null||typeof E.inputSchema!="object")continue;let O={name:E.name,description:E.description,inputSchema:E.inputSchema};E.outputSchema!==null&&typeof E.outputSchema=="object"&&(O.outputSchema=E.outputSchema),R.push(O)}return R}}),y=new Wm({sessionIdGenerator:()=>qm()});return await k.connect(y),p.set(l,{server:k,transport:y}),y}async function d(u,l){let p=Ft(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 m=u.params.name,g=await a(p,m);if(g===void 0){l.code(404).send({error:`unknown mcp server: ${m}`});return}l.hijack(),await g.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 bc(s,e){Xm(s),Ds(s.daemon.scrubEnv);let t=s,n=s.daemon.tls?await Ue.readFile(ie(s.daemon.tls.key)):void 0,r=s.daemon.tls?await Ue.readFile(ie(s.daemon.tls.cert)):void 0;await Ue.mkdir(C.home(),{recursive:!0});let{stream:o,fileStream:i}=await Qm(s.daemon.logLevel),a=Jm({logger:{level:s.daemon.logLevel,stream:o},bodyLimit:256*1024*1024});await a.register(Vm,{options:{handleProtocols:Oo}}),zs(F=>{a.log.info(F)}),Gs(F=>{a.log.info(F)});let d=await ds.load(),c=new ps,u=new fs,l=new cs(e),p=new ls([l,new us(d),u]),f=fd({validator:p});a.addHook("onRequest",async(F,Se)=>{F.routeOptions.config?.skipAuth||F.url==="/acp"||F.url?.startsWith("/acp?")||await f(F,Se)});let m=setInterval(()=>{d.sweepExpired()},300*1e3);m.unref();let g=setInterval(()=>{c.sweepExpired()},300*1e3);g.unref();let h=new In(s,{onFetched:()=>{Xa(h,b)},onStaleFallback:(F,Se)=>{let Ht=Math.round(Se/36e5),jt=Ht>=48?`${Math.round(Ht/24)}d`:`${Ht}h`;a.log.warn(`registry fetch failed (${F.message}); serving stale cache last synced ${jt} ago; agent versions may be outdated ('hydra registry refresh' to retry)`)}});eo(F=>a.log.info(F));let w={info:F=>a.log.info(F),warn:F=>a.log.warn(F)},k=F=>Ke.spawn({...F,stderrTailBytes:s.daemon.agentStderrTailBytes,logger:w});Uo(s.compressToolContent);let y=new is,b=new Zn(h,k,void 0,{idleTimeoutMs:s.daemon.sessionIdleTimeoutSeconds*1e3,orphanTimeoutMs:s.daemon.nonInteractiveOrphanTimeoutSeconds*1e3,defaultModels:s.defaultModels,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:w,npmRegistry:s.npmRegistry,extensionCommands:y,defaultCwd:s.defaultCwd,disableWorkspaceSnapshots:s.disableWorkspaceSnapshots}),I=new rs(Po(s),void 0,{tokenRegistry:u}),v=new os(Mo(s),void 0,{tokenRegistry:u}),R=[];qd(a,ue,td(s),()=>R);let x=new Cs,E=new Rs,O,T=()=>{if(O!==void 0)return O;let F=a.server.address();return O=`http://127.0.0.1:${F&&typeof F=="object"?F.port:s.daemon.port}`,O},j={agentId:s.defaultAgent,cwd:s.defaultCwd,publicHost:s.daemon.publicHost,host:s.daemon.host,port:s.daemon.port,compaction:s.compaction};Bd(a,b,j,{extensionMcp:E,mcpTokenRegistry:x,getDaemonOrigin:T}),Wd(a,h,b,{npmRegistry:s.npmRegistry}),zd(a,I),Jd(a,v),Vd(a,()=>({defaultAgent:t.defaultAgent,defaultCwd:t.defaultCwd,defaultModels:{...t.defaultModels},...t.synopsisAgent!==void 0?{synopsisAgent:t.synopsisAgent}:{},...t.synopsisModel!==void 0?{synopsisModel:t.synopsisModel}:{},defaultTransformers:[...t.defaultTransformers]})),Xd(a,{store:d,rateLimiter:c,staticTokenValidator:l}),uc(a,x),pc(a,x);let W=mc(a,x,E);ac(a,{validator:p,manager:b,defaultAgent:s.defaultAgent,processRegistry:u,onExtensionVersion:(F,Se)=>I.reportVersion(F,Se),onTransformerVersion:(F,Se)=>v.reportVersion(F,Se),transformers:v,extensionCommands:y,mcpTokenRegistry:x,extensionMcp:E,extensionMcpControls:W,getDaemonOrigin:T,registry:h});let q=!!s.daemon.tls;await a.listen({host:q?"127.0.0.1":s.daemon.host,port:q?0:s.daemon.port});let ne=a.server.address(),J=ne&&typeof ne=="object"?ne.port:s.daemon.port,be,_c=s.daemon.host,ho=J;if(q&&n&&r){be=Ym({listenHost:s.daemon.host,listenPort:s.daemon.port,upstreamHost:"127.0.0.1",upstreamPort:J,tlsOptions:{key:n,cert:r},logger:a.log});let F=be.address();F&&typeof F=="object"&&(ho=F.port)}await Ue.mkdir(C.home(),{recursive:!0}),await Ya({pid:process.pid,host:_c,port:ho,loopbackPort:J,startedAt:new Date().toISOString()});let yo={daemonUrl:`http://127.0.0.1:${J}`,daemonHost:"127.0.0.1",daemonPort:J,serviceToken:e,daemonWsUrl:`ws://127.0.0.1:${J}/acp`,hydraHome:C.home()};I.setContext(yo),v.setContext(yo),await I.start(),await v.start();try{await b.reconcilePermissionFlags()}catch(F){a.log.warn(`permission flag reconcile failed: ${F.message}`)}b.resurrectPendingQueues().catch(F=>{a.log.warn(`queue replay scan failed: ${F.message}`)}),b.resumePendingCompactions().catch(F=>{a.log.warn(`compaction resume scan failed: ${F.message}`)}),b.resumePendingAgentSwaps().catch(F=>{a.log.warn(`agent-swap resume scan failed: ${F.message}`)});let wo=s.daemon.agentSyncIntervalMinutes*60*1e3,ko=wo>0?Za({registry:h,manager:b,intervalMs:wo,logger:w}):void 0,vo=s.daemon.sessionGcIntervalMinutes*60*1e3,$c=s.daemon.sessionGcMaxAgeDays*24*60*60*1e3,bo=vo>0?ed({manager:b,intervalMs:vo,maxAgeMs:$c,logger:w}):void 0,Oc=od({bootConfig:s,apply:F=>{t=F,h.setConfig(F),b.setLiveConfig({defaultModels:F.defaultModels}),j.agentId=F.defaultAgent,j.cwd=F.defaultCwd,Ds(F.daemon.scrubEnv)},onDrift:F=>{R=F},logger:w});return{app:a,manager:b,registry:h,extensions:I,transformers:v,mcpTokenRegistry:x,extensionMcp:E,processRegistry:u,shutdown:async()=>{Oc(),bo&&bo(),ko&&ko(),clearInterval(m),clearInterval(g);let F=async(Se,Ht)=>{try{await Ht()}catch(jt){a.log.warn(`shutdown step ${Se} failed: ${jt instanceof Error?jt.message:String(jt)}`)}};await F("sessionTokenStore.flush",()=>d.flush()),await F("extensions.stop",()=>I.stop()),await F("transformers.stop",()=>v.stop()),await F("manager.closeAll",()=>b.closeAll()),await F("manager.flushSynopsis",()=>b.flushSynopsis(3e4)),await F("manager.shutdownSynopsis",()=>b.shutdownSynopsis()),await F("manager.flushMetaWrites",()=>b.flushMetaWrites()),await F("manager.flushHistoryWrites",()=>b.flushHistoryWrites()),zs(null),Gs(null),eo(null),be&&await F("tlsTerminator.close",()=>new Promise(Se=>be.close(()=>Se()))),await F("app.close",()=>a.close());try{wc.unlinkSync(C.pidFile())}catch{}await F("fileStream.flushSync",()=>i.flushSync())}}}var yc=20;async function Km(s,e){let t=Nt.dirname(s),n=Nt.basename(s,".log"),r=new RegExp(`^${n}\\.(\\d+)\\.log$`),o;try{o=await Ue.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=>Ue.unlink(Nt.join(t,d.name))))}async function Qm(s){await Km(C.logFile(),yc);let e=await Gm({file:C.logFile(),size:"10m",mkdir:!0,symlink:!0,limit:{count:yc,removeOtherLogFiles:!0}}),t=hc.destination(2);return{stream:hc.multistream([{stream:e,level:s},{stream:t,level:s}]),fileStream:e}}function Ym(s){let e=vc.createServer(s.tlsOptions,t=>{let n=kc.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}`)}),e.listen({host:s.listenHost,port:s.listenPort}),e}function Xm(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 ph(){process.title="hydra-acp-daemon";let{installGlobalTlsTrust:s}=await Promise.resolve().then(()=>(Mc(),Pc));s();let e=await Lt(),t=await So(),n=await bc(e,t);process.stdout.write(`hydra-acp daemon listening on ${e.daemon.host}:${e.daemon.port}
194
194
  `);let r=1e4,o=!1,i=async()=>{o&&(process.stderr.write(`Second signal received; exiting immediately.
195
195
  `),process.exit(1)),o=!0,process.stdout.write(`Shutting down...
196
196
  `);let a=setTimeout(()=>{process.stderr.write(`Graceful shutdown did not complete within ${r}ms; forcing exit.
197
197
  `),process.exit(1)},r);a.unref();try{await n.shutdown()}catch(d){process.stderr.write(`shutdown failed: ${d instanceof Error?d.message:String(d)}
198
- `)}clearTimeout(a),process.exit(0)};process.on("SIGINT",()=>{i()}),process.on("SIGTERM",()=>{i()}),process.on("SIGHUP",()=>{})}fh().catch(s=>{process.stderr.write(`hydra-acp-daemon: ${s instanceof Error?s.message:String(s)}
198
+ `)}clearTimeout(a),process.exit(0)};process.on("SIGINT",()=>{i()}),process.on("SIGTERM",()=>{i()}),process.on("SIGHUP",()=>{})}ph().catch(s=>{process.stderr.write(`hydra-acp-daemon: ${s instanceof Error?s.message:String(s)}
199
199
  `),process.exit(1)});