@hydra-acp/cli 0.1.176 → 0.1.178

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 +503 -481
  2. package/dist/daemon.js +116 -116
  3. package/package.json +1 -1
package/dist/daemon.js CHANGED
@@ -1,47 +1,47 @@
1
1
  #!/usr/bin/env node
2
- var Lc=Object.defineProperty;var In=(s,e)=>()=>(s&&(e=s(s=0)),e);var Uc=(s,e)=>{for(var t in e)Lc(s,t,{get:e[t],enumerable:!0})};import*as U from"path";import*as _s from"os";function $(s){let e=_s.homedir();return e?s===e?"~":s.startsWith(e+"/")?"~"+s.slice(e.length):s:s}function Wc(){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 W(){let s=process.env[Bc];if(s&&s.length>0)return U.resolve(s);let e=Wc();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(_s.homedir(),".hydra-acp")}var Bc,A,Q=In(()=>{"use strict";Bc="HYDRA_ACP_HOME";A={home:W,config:()=>U.join(W(),"config.json"),authToken:()=>U.join(W(),"auth-token"),remotes:()=>U.join(W(),"remotes.json"),pidFile:()=>U.join(W(),"daemon.pid"),logFile:()=>U.join(W(),"daemon.log"),currentLogFile:()=>U.join(W(),"current.log"),registryCache:()=>U.join(W(),"registry.json"),themesDir:()=>U.join(W(),"themes"),ttySessionDir:()=>U.join(W(),"tty"),ttySessionFile:s=>U.join(W(),"tty",s),agentsDir:()=>U.join(W(),"agents"),agentLogFile:s=>U.join(W(),"agents","logs",`${s}.log`),agentInstallDir:(s,e,t)=>U.join(W(),"agents",e,s,t),agentNpmInstallDir:(s,e,t)=>U.join(W(),"agents",e,s,t,`node${process.versions.modules}`),sessionsDir:()=>U.join(W(),"sessions"),sessionDir:s=>U.join(W(),"sessions",s),sessionFile:s=>U.join(W(),"sessions",s,"meta.json"),historyFile:s=>U.join(W(),"sessions",s,"history.jsonl"),historyArchiveFile:(s,e)=>U.join(W(),"sessions",s,`history.jsonl.${e}`),toolsDir:s=>U.join(W(),"sessions",s,"tools"),toolBlobFile:(s,e)=>U.join(W(),"sessions",s,"tools",e),queueFile:s=>U.join(W(),"sessions",s,"queue.ndjson"),tombstonesDir:()=>U.join(W(),"sessions",".tombstones"),tombstoneAgentDir:s=>U.join(W(),"sessions",".tombstones",encodeURIComponent(s)),tombstoneFile:(s,e)=>U.join(W(),"sessions",".tombstones",encodeURIComponent(s),encodeURIComponent(e)),extensionsDir:()=>U.join(W(),"extensions"),extensionLogDir:s=>U.join(W(),"extensions",s),extensionLogFile:s=>U.join(W(),"extensions",s,"current.log"),extensionPidFile:s=>U.join(W(),"extensions",s,"extension.pid"),transformersDir:()=>U.join(W(),"transformers"),transformerLogDir:s=>U.join(W(),"transformers",s),transformerLogFile:s=>U.join(W(),"transformers",s,"current.log"),transformerPidFile:s=>U.join(W(),"transformers",s,"transformer.pid"),transformerState:(s,e)=>U.join(W(),"sessions",s,"transformer-state",e),tuiHistoryFile:s=>U.join(W(),"sessions",s,"prompt-history"),globalTuiHistoryFile:()=>U.join(W(),"prompt-history"),tuiLogFile:()=>U.join(W(),"tui.log"),shimWireLogFile:()=>U.join(W(),"shim-wire.log")}});import*as ie from"fs/promises";import*as Co from"fs";import*as xe from"path";import{randomBytes as zc}from"crypto";async function he(s,e,t={}){let r=(t.pretty??!0?JSON.stringify(e,null,2):JSON.stringify(e))+`
3
- `;await Jc(s,r,t)}async function Jc(s,e,t={}){let n=await Vc(s),r=Gc(n);await ie.mkdir(r,{recursive:!0});let o=`${n}.tmp-${process.pid}-${Kc()}`;try{let i={encoding:"utf8"};t.mode!==void 0&&(i.mode=t.mode),await ie.writeFile(o,e,i),await ie.rename(o,n)}catch(i){throw await ie.unlink(o).catch(()=>{}),i}if(t.mode!==void 0)try{Co.chmodSync(n,t.mode)}catch{}}async function Vc(s){let e;try{e=await ie.lstat(s)}catch(r){if(r.code==="ENOENT")return s;throw r}if(!e.isSymbolicLink())return s;let t=await ie.readlink(s),n=xe.isAbsolute(t)?t:xe.resolve(xe.dirname(s),t);try{let r=await ie.realpath(xe.dirname(n));return xe.join(r,xe.basename(n))}catch(r){if(r.code==="ENOENT")return n;throw r}}async function se(s){let e;try{e=await ie.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 Gc(s){let e=s.lastIndexOf("/");return e<=0?".":s.slice(0,e)}function Kc(){return zc(4).toString("hex")}var We=In(()=>{"use strict"});function Ms(s,e){return`${s}:${e}`}var Rc=In(()=>{"use strict";Q();We()});var Fc={};Uc(Fc,{_resetForTests:()=>xh,clearPin:()=>kh,fetchPeerFingerprint:()=>Sh,formatFingerprint:()=>Pc,getPin:()=>vh,installGlobalTlsTrust:()=>Ih,loadPinsFromStore:()=>bh,setPin:()=>Tc,sha256Hex:()=>yo,wsTlsOptions:()=>Ch});import{createHash as ph}from"crypto";import*as Ec from"tls";import{Agent as gh,Dispatcher as mh,buildConnector as hh,getGlobalDispatcher as yh,setGlobalDispatcher as wh}from"undici";function Tc(s,e,t){ft.set(Ms(s,e),Mc(t))}function kh(s,e){ft.delete(Ms(s,e))}function vh(s,e){return ft.get(Ms(s,e))}function bh(s){ft.clear();for(let e of s.list())e.entry.pinnedFingerprint&&Tc(e.host,e.port,e.entry.pinnedFingerprint)}async function Sh(s,e,t={}){let n=t.timeoutMs??1e4;return new Promise((r,o)=>{let i=Ec.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,yo(u.raw))}),i.once("error",u=>d(u))})}function yo(s){return ph("sha256").update(s).digest("hex")}function Pc(s){let e=Mc(s),t=e.match(/.{2}/g);return t?t.join(":"):e}function Mc(s){return s.replace(/:/g,"").toLowerCase()}function Ih(){if(ho)return;ho=!0;let s=yh(),e=new gh({connect:hh({rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(n,r)=>$c(n,r)})}),t=new mh;t.dispatch=(n,r)=>{let o=Ah(n.origin);return(o&&_c(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(()=>{})),wh(t)}function Ah(s){if(!s)return null;try{return new URL(String(s)).hostname}catch{return null}}function _c(s){for(let e of ft.keys())if(Oc(e)?.host===s)return!0;return!1}function $c(s,e){if(!e||!e.raw)return new Error(`TLS peer ${s} did not present a certificate`);let t=yo(e.raw);for(let[n,r]of ft.entries()){let o=Oc(n);if(o&&o.host===s&&r===t)return}return new Error(`TLS pin mismatch for ${s} (cert sha256 ${Pc(t)})`)}function Oc(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 Ch(s){return _c(s)?{rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(e,t)=>$c(e,t)}:{autoSelectFamily:!0}}function xh(){ft.clear(),ho=!1}var ft,ho,Nc=In(()=>{"use strict";Rc();ft=new Map,ho=!1});Q();import*as Ge from"fs/promises";import{homedir as Us}from"os";import{z as S}from"zod";Q();import*as pt from"fs/promises";function $s(){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 qc(){try{let e=(await pt.readFile(A.authToken(),"utf8")).trim();return e.length>0?e:void 0}catch(s){if(s.code==="ENOENT")return;throw s}}async function Os(s){await pt.mkdir(A.home(),{recursive:!0}),await pt.writeFile(A.authToken(),s+`
4
- `,{encoding:"utf8",mode:384})}async function Ao(){let s=await qc();if(s)return s;let e=$s();return await Os(e),process.stderr.write(`hydra-acp: initialized ${A.authToken()} with a fresh service token.
5
- `),e}We();import*as Ro from"fs/promises";import*as Bt from"os";import*as Me from"path";var X="read by the daemon, which loads config.json at startup",xo={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"},sessionDefaults:{reload:"live",overlay:"partial",overlayNote:"applies to WS session/new and child_session/spawn; POST /v1/sessions has no model/mode/effort field to apply any of it to"},synopsisAgent:{reload:"warn",overlay:"inert",overlayNote: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 Fs(s){return xo[s]??{reload:"restart",overlay:"inert"}}function Ns(s){return Qc[s]??{reload:"restart",overlay:"inert"}}function Ds(){let s=[];for(let[e,t]of Object.entries(xo))t.overlay!=="effective"&&s.push({key:e,effect:t.overlay,note:t.overlayNote??X});return s}var Yc=".hydra-acp.json",js="home",Xc=64,Dh=Ds().map(s=>s.key);function Zc(s){return s==="~"?Bt.homedir():s.startsWith("~/")?Me.join(Bt.homedir(),s.slice(2)):s.startsWith("$HOME/")?Me.join(Bt.homedir(),s.slice(6)):s}function Hs(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function Ls(s,e){let t={...s};for(let[n,r]of Object.entries(e)){let o=t[n];t[n]=Hs(o)&&Hs(r)?Ls(o,r):r}return t}async function eu(s,e=Bt.homedir()){let t=[],n=[],r=Me.resolve(e),o=Me.resolve(s);for(let i=0;i<Xc;i+=1){let a=Me.join(o,Yc),d;try{d=await Ro.readFile(a,"utf8")}catch{d=void 0}if(d!==void 0)try{let u=JSON.parse(d);Hs(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=Me.dirname(o);if(c===o)break;o=c}return t.reverse(),{layers:t,notices:n}}function tu(s){let e=new Map(Ds().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 nu(s=process.cwd()){let{layers:e,notices:t}=await eu(s);t.push(...tu(e));let n={};for(let i of e)n=Ls(n,i.data);let r,o=n[js];return typeof o=="string"&&o.length>0?r=Me.resolve(Zc(o)):o!==void 0&&t.push({file:e[e.length-1].file,key:js,message:"`home` must be a non-empty string; ignoring it"}),delete n[js],{layers:e,notices:t,merged:n,...r!==void 0?{homeRequest:r}:{}}}function su(s,e){let t=s[e];return typeof t=="string"&&t.length>0?t:void 0}function ru(s,e){let t=s[e];if(t===null||typeof t!="object"||Array.isArray(t))return;let n={};for(let[r,o]of Object.entries(t)){if(o===null||typeof o!="object"||Array.isArray(o))continue;let i={};for(let[a,d]of Object.entries(o))typeof d=="string"&&(i[a]=d);Object.keys(i).length>0&&(n[r]=i)}return Object.keys(n).length>0?n:void 0}async function Wt(s){let e={};try{e=(await nu(s)).merged}catch{return{}}let t=su(e,"defaultAgent"),n=ru(e,"sessionDefaults");return{...t!==void 0?{agentId:t}:{},...n!==void 0?{configDefaults:n}:{}}}var Po="https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",ou=S.object({cert:S.string(),key:S.string()}),Mo=55514,iu=S.object({host:S.string().default("127.0.0.1"),port:S.number().int().positive().default(Mo),logLevel:S.enum(["debug","info","warn","error"]).default("info"),tls:ou.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)}),au=S.object({url:S.string().url().default(Po),ttlHours:S.number().positive().default(24),pinned:S.boolean().default(!1)}),du=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()}),cu=S.object({packageSpec:S.string().optional(),extraArgs:S.array(S.string()).optional(),env:S.record(S.string()).optional()}),uu=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-x-ctrl-e","ctrl-y","ctrl-underscore","alt-underscore","escape"]),lu=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()]),fu=S.object({id:S.string().min(1),script:S.string().min(1),refreshMs:S.number().int().positive().optional(),title:S.string().optional(),cap:S.number().int().positive().optional()}).strict(),pu=S.union([S.string(),fu]),Eo=S.array(lu);function Bs(s,e){return S.object({left:Eo.default(s),right:Eo.default(e)}).default({})}var gu=["status",{field:"elapsed",separator:" "},"sessionId","queued","scroll"],mu=["usage"],hu=[],yu=["helpHint"],wu=["cwd","title"],ku=["agentModel"],vu=S.object({composer:S.object({top:Bs(gu,mu),bottom:Bs(hu,yu),hintTurns:S.number().int().nonnegative().nullable().default(3)}).default({}),sessionbar:Bs(wu,ku),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),terminalHost:S.union([S.boolean(),S.enum(["auto","paseo","herdr","tmux"])]).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(pu).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(uu,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()}),To=S.string().min(1).regex(/^[A-Za-z0-9._-]+$/,"extension name must be filename-safe"),bu=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)}),Su=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)}),Iu=S.object({daemon:iu.default({}),registry:au.default({url:Po,ttlHours:24,pinned:!1}),agents:S.record(S.string(),du).default({}),agentOverrides:S.record(S.string(),cu).default({}),defaultAgent:S.string().default("opencode"),sessionDefaults:S.record(S.string(),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(To,bu).default({}),transformers:S.record(To,Su).default({}),defaultTransformers:S.array(S.string()).default([]),npmRegistry:S.string().url().optional(),tui:vu.default({})});function _o(s){return Object.entries(s.extensions).map(([e,t])=>({name:e,...t}))}function $o(s){return Object.entries(s.transformers).map(([e,t])=>({name:e,...t}))}async function Ws(){return await Au(),await se(A.config())??{}}async function Au(){let s;try{s=await Ge.lstat(A.config())}catch(e){if(e.code==="ENOENT")return;throw e}if(s.isSymbolicLink())try{await Ge.stat(A.config())}catch(e){if(e.code!=="ENOENT")throw e;let t=await Ge.readlink(A.config()).catch(()=>"<unknown>");throw new Error(`config.json at ${A.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 Cu(){let s=await Ws(),e=s.daemon,t=e&&typeof e.authToken=="string"?e.authToken:void 0;if(!t)return;let n=!1;try{await Ge.access(A.authToken()),n=!0}catch(r){if(r.code!=="ENOENT")throw r}if(n)throw new Error(`Auth token present in both ${A.authToken()} and ${A.config()} (daemon.authToken). Remove daemon.authToken from config.json to resolve.`);await Os(t),delete e.authToken,Object.keys(e).length===0&&delete s.daemon,await he(A.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated auth token from ${A.config()} to ${A.authToken()}.
6
- `)}async function xu(){let s=await Ws(),e=s.defaultModels&&typeof s.defaultModels=="object"&&!Array.isArray(s.defaultModels)?s.defaultModels:void 0;if(!e)return;let t=s.sessionDefaults&&typeof s.sessionDefaults=="object"&&!Array.isArray(s.sessionDefaults)?s.sessionDefaults:{};for(let[n,r]of Object.entries(e)){if(typeof r!="string")continue;let o=t[n]&&typeof t[n]=="object"&&!Array.isArray(t[n])?t[n]:{};o.model===void 0&&(o.model=r),t[n]=o}s.sessionDefaults=t,delete s.defaultModels,await he(A.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated defaultModels to sessionDefaults in ${A.config()}.
7
- `)}async function qt(){return await Cu(),await xu(),Iu.parse(await Ws())}function ae(s){return s==="~"||s==="$HOME"?Us():s.startsWith("~/")?Us()+s.slice(1):s.startsWith("$HOME/")?Us()+s.slice(5):s}import*as Ic from"fs";import*as Be from"fs/promises";import*as Ac from"net";import*as Ht from"path";import*as Cc from"tls";import ih from"fastify";import ah from"@fastify/websocket";var Oo="acp.v1";function Fo(s,e){return s.has(Oo)?Oo:!1}import bc from"pino";import dh from"pino-roll";var Ru={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"]},No="HYDRA_ACP_SESSION",Eu=[No],Tu=[...Object.values(Ru).flat(),...Eu];function An(s,e){return s?{...e??{},[No]:s}:e}var Do=[];function qs(s){Do=s?[...s]:[]}function Pu(s,e){return e.endsWith("*")?s.startsWith(e.slice(0,-1)):s===e}function Mu(){return[...Tu,...Do]}function Cn(s=process.env){let e=Mu(),t={};for(let[n,r]of Object.entries(s))r!==void 0&&(e.some(o=>Pu(n,o))||(t[n]=r));return t}Q();import*as de from"fs/promises";import{createHash as _u}from"crypto";import{gzip as $u,gunzip as Ou}from"zlib";import{promisify as jo}from"util";var Ho=jo($u),Fu=jo(Ou),Lo=/^[A-Za-z0-9_-]+$/,Nu=/^[a-f0-9]{64}$/,zs=!0;function Uo(s){zs=s}function xn(s,e){return Lo.test(s)?e===void 0||Nu.test(e):!1}function Rn(s,e){return`${A.toolBlobFile(s,e)}.gz`}async function Js(s,e){if(!xn(s))return null;let t=_u("sha256").update(e,"utf8").digest("hex"),n=Rn(s,t),r=A.toolBlobFile(s,t);for(let a of[n,r])try{return await de.access(a),t}catch{}await de.mkdir(A.toolsDir(s),{recursive:!0});let o=zs?n:r,i=zs?await Ho(Buffer.from(e,"utf8")):Buffer.from(e,"utf8");return await de.writeFile(o,i,{mode:384,flag:"wx"}).catch(async a=>{if(a.code!=="EEXIST")throw a}),t}async function zt(s,e){if(!xn(s,e))return null;try{let t=await de.readFile(Rn(s,e));return(await Fu(t)).toString("utf8")}catch{}try{return await de.readFile(A.toolBlobFile(s,e),"utf8")}catch{return null}}async function Bo(s,e){if(!xn(s,e))return null;try{return await de.readFile(Rn(s,e))}catch{}try{let t=await de.readFile(A.toolBlobFile(s,e));return await Ho(t)}catch{return null}}async function Wo(s,e,t){if(!xn(s,e))return;let n=Rn(s,e);try{await de.access(n);return}catch{}await de.mkdir(A.toolsDir(s),{recursive:!0}),await de.writeFile(n,t,{mode:384,flag:"wx"}).catch(r=>{if(r.code!=="EEXIST")throw r})}async function qo(s){Lo.test(s)&&await de.rm(A.toolsDir(s),{recursive:!0,force:!0}).catch(()=>{})}Q();import*as ni from"fs/promises";import*as Tn from"path";import{z as H}from"zod";We();Q();import*as Jo from"fs";import*as pe from"fs/promises";import*as Ke from"path";import{spawn as Vo}from"child_process";import{Readable as Du}from"stream";function _e(){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 Ks(s,e=_e()){if(e)return s[e]}var gt=s=>{process.stderr.write(s+`
8
- `)};function Qs(s){gt=s??(e=>process.stderr.write(e+`
9
- `))}async function Go(s){if(!s.target.archive)throw new Error(`Agent ${s.agentId} has no archive URL for ${_e()??"this platform"}`);if(!s.target.cmd)throw new Error(`Agent ${s.agentId} has no cmd in its binary target`);let e=_e();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=A.agentInstallDir(s.agentId,e,s.version),n=Ke.resolve(t,s.target.cmd);if(await Gs(n))return n;if(await ju({agentId:s.agentId,version:s.version,archiveUrl:s.target.archive,installDir:t,onProgress:s.onProgress}),!await Gs(n))throw new Error(`Agent ${s.agentId}: extracted archive did not contain ${s.target.cmd} (looked in ${t})`);return process.platform!=="win32"&&await pe.chmod(n,493).catch(()=>{}),n}async function ju(s){await pe.mkdir(Ke.dirname(s.installDir),{recursive:!0});let e=await pe.mkdtemp(`${s.installDir}.partial-`);try{gt(`hydra-acp: downloading ${s.agentId} from ${s.archiveUrl}`);let t=await Hu({url:s.archiveUrl,dir:e,agentId:s.agentId,version:s.version,onProgress:s.onProgress});gt(`hydra-acp: extracting ${s.agentId}`),mt(s.onProgress,{phase:"extract",agentId:s.agentId,version:s.version}),await Uu(t,e),await pe.unlink(t).catch(()=>{});try{await pe.rename(e,s.installDir)}catch(n){let r=n;if((r.code==="EEXIST"||r.code==="ENOTEMPTY")&&await Gs(s.installDir)){await pe.rm(e,{recursive:!0,force:!0}).catch(()=>{}),mt(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw n}gt(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),mt(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await pe.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function mt(s,e){if(s)try{s(e)}catch{}}async function Hu(s){let e=Lu(s.url),t=Ke.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=Jo.createWriteStream(t),i=Du.fromWeb(n.body);mt(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,mt(s.onProgress,{phase:"download_progress",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r})),f-d>=u&&(d=f,gt(zo(s.agentId,a,r)))}),await new Promise((p,f)=>{i.on("error",f),o.on("error",f),o.on("finish",()=>p()),i.pipe(o)}),gt(zo(s.agentId,a,r,!0)),mt(s.onProgress,{phase:"download_done",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r}),t}function zo(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 Lu(s){let e=new URL(s);return Ke.posix.basename(e.pathname)||"archive"}async function Uu(s,e){let t=s.toLowerCase();if(t.endsWith(".tar.gz")||t.endsWith(".tgz")||t.endsWith(".tar")){await Vs("tar",["-xf",s,"-C",e]);return}if(t.endsWith(".zip")){if(await Bu("unzip")){await Vs("unzip",["-q",s,"-d",e]);return}await Vs("tar",["-xf",s,"-C",e]);return}throw new Error(`Unsupported archive format: ${s}`)}function Vs(s,e){return new Promise((t,n)=>{let r=Vo(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 Bu(s){return new Promise(e=>{let t=process.platform==="win32"?"where":"which",n=Vo(t,[s],{stdio:"ignore"});n.on("error",()=>e(!1)),n.on("exit",r=>e(r===0))})}async function Gs(s){try{return await pe.access(s),!0}catch{return!1}}Q();import*as ke from"fs/promises";import*as $e from"path";import{spawn as Wu}from"child_process";var Xs=s=>{process.stderr.write(s+`
10
- `)};function Zs(s){Xs=s??(e=>process.stderr.write(e+`
11
- `))}async function Qo(s){let e=_e();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=A.agentNpmInstallDir(s.agentId,e,s.version),n=Gu(s.packageSpec),r=Ku(n),o={installDir:t,packageName:n,hint:s.bin,basename:r},i=$e.join(t,"node_modules",".bin",s.bin);if(await nt(i))return i;if(await nt(t)){let l=await Ko(o);if(l)return l.binPath}await qu({agentId:s.agentId,version:s.version,packageSpec:s.packageSpec,installDir:t,registry:s.registry,onProgress:s.onProgress});let a=await Ko(o);if(a)return a.binPath;let d=await Xo(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 qu(s){await ke.mkdir($e.dirname(s.installDir),{recursive:!0});let e=await ke.mkdtemp(`${s.installDir}.partial-`);try{Xs(`hydra-acp: installing ${s.packageSpec} for ${s.agentId} into ${e}`),Ys(s.onProgress,{phase:"install_start",agentId:s.agentId,version:s.version,packageSpec:s.packageSpec}),await Vu({packageSpec:s.packageSpec,cwd:e,registry:s.registry});try{await ke.rename(e,s.installDir)}catch(t){let n=t;if((n.code==="EEXIST"||n.code==="ENOTEMPTY")&&await nt(s.installDir)){await ke.rm(e,{recursive:!0,force:!0}).catch(()=>{}),Ys(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw t}Xs(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),Ys(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await ke.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function Ys(s,e){if(s)try{s(e)}catch{}}var zu=5,Ju=25;function Vu(s){return Yo(s,0)}async function Yo(s,e){try{await new Promise((t,n)=>{let r=s.registry?["--registry",s.registry]:[],o;try{o=Wu("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})
12
- stderr: ${u}`:`npm install ${s.packageSpec} failed (${c})`))})})}catch(t){if(t.code==="ETXTBSY"&&e<zu)return await new Promise(r=>setTimeout(r,Ju*(e+1))),Yo(s,e+1);throw t}}function Gu(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 Ku(s){let e=s.lastIndexOf("/");return e===-1?s:s.slice(e+1)}async function Xo(s,e){let t=$e.join(s,"node_modules",e,"package.json");try{let n=await ke.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 Ko(s){let e=$e.join(s.installDir,"node_modules",".bin"),t=$e.join(e,s.hint);if(await nt(t))return{binName:s.hint,binPath:t};let n=await Xo(s.installDir,s.packageName);if(typeof n=="object"&&n!==null){let r=Object.keys(n);if(r.length===1){let o=r[0],i=$e.join(e,o);if(await nt(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=$e.join(e,o);if(await nt(i))return{binName:o,binPath:i}}}}if(s.basename!==s.hint){let r=$e.join(e,s.basename);if(await nt(r))return{binName:s.basename,binPath:r}}}async function nt(s){try{return await ke.access(s),!0}catch{return!1}}var Qu=H.object({package:H.string(),bin:H.string().optional(),args:H.array(H.string()).optional(),env:H.record(H.string()).optional()}),ht=H.object({archive:H.string().url().optional(),cmd:H.string().optional(),args:H.array(H.string()).optional(),env:H.record(H.string()).optional()}),Yu=H.object({"darwin-aarch64":ht.optional(),"darwin-x86_64":ht.optional(),"linux-aarch64":ht.optional(),"linux-x86_64":ht.optional(),"windows-x86_64":ht.optional(),"windows-aarch64":ht.optional()}),Xu=H.object({package:H.string(),args:H.array(H.string()).optional(),env:H.record(H.string()).optional()}),Zu=H.object({command:H.string(),args:H.array(H.string()).optional(),env:H.record(H.string()).optional()}),el=H.object({command:H.string().optional(),url:H.string().optional(),description:H.string().optional()}),tl=H.object({npx:Qu.optional(),binary:Yu.optional(),uvx:Xu.optional(),exec:Zu.optional()}),nl=H.object({id:H.string(),name:H.string(),version:H.string().optional(),description:H.string().optional(),authors:H.array(H.string()).optional(),license:H.string().optional(),icon:H.string().optional(),repository:H.string().optional(),website:H.string().optional(),distribution:tl,onboarding:el.optional(),requiredEnv:H.array(H.string().min(1)).optional()}),Zo=8;function si(s){return s.installId??s.id}function tr(s){let e=s.extendsChain;return e&&e.length>0?e[e.length-1]:s.id}function Jt(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 ei=H.object({version:H.string(),agents:H.array(nl),extensions:H.array(H.unknown()).optional()}),En=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{...er(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>=Zo)throw new Error(`agent ${n.id}: extends chain deeper than ${Zo} (${[...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(rl(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=>nr(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])=>er(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=ol(n.packageSpec),i=t.id,r={...r,npx:{...r.npx,package:n.packageSpec}}),n.extraArgs?.length&&(r=sl(r,n.extraArgs)),n.env&&Object.keys(n.env).length>0&&(r=ri(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=ei.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(A.registryCache());if(!(!e||typeof e.fetchedAt!="number"||e.data===void 0))try{let t=ei.parse(e.data);return{fetchedAt:e.fetchedAt,raw:e.data,data:t}}catch{return}}async writeDiskCache(e){await he(A.registryCache(),{fetchedAt:e.fetchedAt,data:e.raw})}};function er(s,e){return{id:s,name:e.name??s,description:e.description,version:"local",distribution:{exec:{command:ae(e.command??s),args:e.args?.map(ae),env:e.env}}}}function ri(s,e){let t=e.args?.map(ae),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 sl(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 rl(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?er(s,e).distribution:ri(t.distribution,e),installId:n?s:t.installId??t.id,extendsChain:[s,...t.extendsChain??[t.id]]}}function ol(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 nr(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 yt(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 sr(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 sr(s){let e=_e();if(!e)return"no";let t=s.version??"current",n=si(s);if(s.distribution.exec)return"yes";if(s.distribution.binary){let r=Ks(s.distribution.binary,e);if(r?.cmd){let o=Tn.resolve(A.agentInstallDir(n,e,t),r.cmd);if(await ti(o))return"yes"}}if(s.distribution.npx){let r=s.distribution.npx,o=r.bin??nr(s)??r.package,i=A.agentNpmInstallDir(n,e,t),a=Tn.join(i,"node_modules",".bin",o);if(await ti(a))return"yes"}return!s.distribution.npx&&!s.distribution.binary&&s.distribution.uvx?"lazy":"no"}async function ti(s){try{return await ni.access(s),!0}catch{return!1}}async function Ie(s,e=[],t={}){let n=s.version??"current",r=si(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??nr(s)??o.package,d=t.onInstallProgress;return{command:await Qo({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=Ks(s.distribution.binary);if(!o)throw new Error(`Agent ${s.id} has no binary distribution for ${_e()??"this platform"}.`);let i=t.onInstallProgress,a=await Go({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 ul}from"child_process";import*as _n from"fs";import*as bi from"path";var C={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 V}from"zod";var oi=V.object({protocolVersion:V.number().optional(),clientCapabilities:V.record(V.unknown()).optional(),clientInfo:V.object({name:V.string(),version:V.string().optional()}).optional()}),il=V.enum(["full","pending_only","none","after_message"]),ii=V.object({cwd:V.string(),mcpServers:V.array(V.unknown()).optional(),_meta:V.record(V.unknown()).optional()}),ai=V.object({upstreamSessionId:V.string(),agentId:V.string(),cwd:V.string(),title:V.string().optional(),agentArgs:V.array(V.string()).optional()}),di=V.object({sessionId:V.string(),historyPolicy:il.default("full"),afterMessageId:V.string().optional(),afterSeq:V.number().optional(),clientId:V.string().optional(),clientInfo:V.object({name:V.string(),version:V.string().optional()}).optional(),_meta:V.record(V.unknown()).optional()});import{z as N}from"zod";var ci=N.object({sessionId:N.string()}),ui=N.object({cwd:N.string().optional(),cursor:N.string().optional()}),rr=N.object({used:N.number().optional(),size:N.number().optional(),costAmount:N.number().optional(),costCurrency:N.string().optional()}),vy=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:rr.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()}),al=N.object({sessionId:N.string(),cwd:N.string(),title:N.string().optional(),updatedAt:N.string().optional(),_meta:N.record(N.unknown()).optional()}),by=N.object({sessions:N.array(al),nextCursor:N.string().optional()});function Pn(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 li(s){let e={sessionId:s.sessionId,cwd:s.cwd,updatedAt:s.updatedAt,_meta:Vt(s._meta,Pn(s))};return s.title!==void 0&&(e.title=s.title),e}var re="hydra-acp";function dl(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 st(s){if(!s)return{};let e=s[re];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),typeof t.historyLimit=="number"&&Number.isFinite(t.historyLimit)&&t.historyLimit>=0&&(n.historyLimit=t.historyLimit),(t.toolContent==="inline"||t.toolContent==="references")&&(n.toolContent=t.toolContent),t.detachStatus==="detached"&&(n.detachStatus=t.detachStatus),typeof t.title=="string"&&(n.title=t.title),Array.isArray(t.agentArgs)&&t.agentArgs.every(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=ai.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=rr.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=dl(t.env);r!==void 0&&(n.env=r)}return n}function Oe(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[re],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.recordedAt=="number"?s:{...t,_meta:{...n,[re]:{...o,recordedAt:e}}}}function Fe(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[re],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.seq=="number"?s:{...t,_meta:{...n,[re]:{...o,seq:e}}}}function Vt(s,e){return{...s??{},[re]:e}}import{z as _}from"zod";var fi=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.record(_.unknown()).optional()}),Mn=_.object({sessionId:_.string()}),pi=_.object({clientId:_.string(),name:_.string().optional(),version:_.string().optional()}),Ry=_.object({sessionId:_.string(),messageId:_.string(),originator:pi,prompt:_.array(_.unknown()),position:_.number().int().nonnegative(),queueDepth:_.number().int().positive(),enqueuedAt:_.number()}),Ey=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),Ty=_.object({sessionId:_.string(),messageId:_.string(),reason:_.enum(["started","cancelled","abandoned"])}),gi=_.object({sessionId:_.string(),messageId:_.string()}),Py=_.object({cancelled:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),mi=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),My=_.object({updated:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),hi=_.object({sessionId:_.string(),targetMessageId:_.string(),prompt:_.array(_.unknown()),replaceQueue:_.boolean().optional(),onTargetCompleted:_.enum(["reject","send_anyway"]).optional()}),_y=_.object({amended:_.boolean(),reason:_.enum(["ok","target_completed","target_cancelled","target_not_found"]),messageId:_.string().optional()}),yi=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.object({steering:_.object({idleBehavior:_.literal("promptRequired").optional()}).optional()}).optional()}),$y=_.object({outcome:_.enum(["injected","startedNewTurn","promptRequired","failed"]),reason:_.literal("noRunningTurn").optional(),detached:_.boolean().optional()}),Oy=_.object({sessionId:_.string(),cancelledMessageId:_.string(),newMessageId:_.string(),prompt:_.array(_.unknown()),originator:pi,amendedAt:_.number()});import{z as Qe}from"zod";var Dy=Qe.object({agentId:Qe.string(),version:Qe.string(),source:Qe.enum(["binary","npm"]),phase:Qe.enum(["download_start","download_progress","download_done","extract","install_start","installed"]),receivedBytes:Qe.number().optional(),totalBytes:Qe.number().optional(),packageSpec:Qe.string().optional()}),wi="hydra-acp/agents/install_progress",wt={auth:{terminal:!0},_meta:{"terminal-auth":!0}};function ki(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(`
13
- `);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:C.ParseError,message:`Failed to parse ndjson line: ${u.message}`}})}d=t.indexOf(`
2
+ var hu=Object.defineProperty;var On=(s,e)=>()=>(s&&(e=s(s=0)),e);var yu=(s,e)=>{for(var t in e)hu(s,t,{get:e[t],enumerable:!0})};import*as U from"path";import*as Qs from"os";function F(s){let e=Qs.homedir();return e?s===e?"~":s.startsWith(e+"/")?"~"+s.slice(e.length):s:s}function ku(){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 B(){let s=process.env[wu];if(s&&s.length>0)return U.resolve(s);let e=ku();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(Qs.homedir(),".hydra-acp")}var wu,R,Y=On(()=>{"use strict";wu="HYDRA_ACP_HOME";R={home:B,config:()=>U.join(B(),"config.json"),authToken:()=>U.join(B(),"auth-token"),remotes:()=>U.join(B(),"remotes.json"),peers:()=>U.join(B(),"peers.json"),pidFile:()=>U.join(B(),"daemon.pid"),logFile:()=>U.join(B(),"daemon.log"),currentLogFile:()=>U.join(B(),"current.log"),registryCache:()=>U.join(B(),"registry.json"),themesDir:()=>U.join(B(),"themes"),ttySessionDir:()=>U.join(B(),"tty"),ttySessionFile:s=>U.join(B(),"tty",s),agentsDir:()=>U.join(B(),"agents"),agentLogFile:s=>U.join(B(),"agents","logs",`${s}.log`),agentInstallDir:(s,e,t)=>U.join(B(),"agents",e,s,t),agentNpmInstallDir:(s,e,t)=>U.join(B(),"agents",e,s,t,`node${process.versions.modules}`),sessionsDir:()=>U.join(B(),"sessions"),sessionDir:s=>U.join(B(),"sessions",s),sessionFile:s=>U.join(B(),"sessions",s,"meta.json"),historyFile:s=>U.join(B(),"sessions",s,"history.jsonl"),historyArchiveFile:(s,e)=>U.join(B(),"sessions",s,`history.jsonl.${e}`),toolsDir:s=>U.join(B(),"sessions",s,"tools"),toolBlobFile:(s,e)=>U.join(B(),"sessions",s,"tools",e),queueFile:s=>U.join(B(),"sessions",s,"queue.ndjson"),tombstonesDir:()=>U.join(B(),"sessions",".tombstones"),tombstoneAgentDir:s=>U.join(B(),"sessions",".tombstones",encodeURIComponent(s)),tombstoneFile:(s,e)=>U.join(B(),"sessions",".tombstones",encodeURIComponent(s),encodeURIComponent(e)),extensionsDir:()=>U.join(B(),"extensions"),extensionLogDir:s=>U.join(B(),"extensions",s),extensionLogFile:s=>U.join(B(),"extensions",s,"current.log"),extensionPidFile:s=>U.join(B(),"extensions",s,"extension.pid"),transformersDir:()=>U.join(B(),"transformers"),transformerLogDir:s=>U.join(B(),"transformers",s),transformerLogFile:s=>U.join(B(),"transformers",s,"current.log"),transformerPidFile:s=>U.join(B(),"transformers",s,"transformer.pid"),transformerState:(s,e)=>U.join(B(),"sessions",s,"transformer-state",e),tuiHistoryFile:s=>U.join(B(),"sessions",s,"prompt-history"),globalTuiHistoryFile:()=>U.join(B(),"prompt-history"),tuiLogFile:()=>U.join(B(),"tui.log"),shimWireLogFile:()=>U.join(B(),"shim-wire.log")}});import*as ce from"fs/promises";import*as Qo from"fs";import*as Pe from"path";import{randomBytes as bu}from"crypto";async function ue(s,e,t={}){let r=(t.pretty??!0?JSON.stringify(e,null,2):JSON.stringify(e))+`
3
+ `;await Su(s,r,t)}async function Su(s,e,t={}){let n=await Iu(s),r=Au(n);await ce.mkdir(r,{recursive:!0});let o=`${n}.tmp-${process.pid}-${Cu()}`;try{let i={encoding:"utf8"};t.mode!==void 0&&(i.mode=t.mode),await ce.writeFile(o,e,i),await ce.rename(o,n)}catch(i){throw await ce.unlink(o).catch(()=>{}),i}if(t.mode!==void 0)try{Qo.chmodSync(n,t.mode)}catch{}}async function Iu(s){let e;try{e=await ce.lstat(s)}catch(r){if(r.code==="ENOENT")return s;throw r}if(!e.isSymbolicLink())return s;let t=await ce.readlink(s),n=Pe.isAbsolute(t)?t:Pe.resolve(Pe.dirname(s),t);try{let r=await ce.realpath(Pe.dirname(n));return Pe.join(r,Pe.basename(n))}catch(r){if(r.code==="ENOENT")return n;throw r}}async function oe(s){let e;try{e=await ce.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 Au(s){let e=s.lastIndexOf("/");return e<=0?".":s.slice(0,e)}function Cu(){return bu(4).toString("hex")}var Oe=On(()=>{"use strict"});function Hs(s,e){return`${s}:${e}`}var Mc=On(()=>{"use strict";Y();Oe()});var jc={};yu(jc,{_resetForTests:()=>uh,clearPin:()=>$o,fetchPeerFingerprint:()=>dh,formatFingerprint:()=>$c,getPin:()=>ih,installGlobalTlsTrust:()=>No,loadPinsFromPeerStore:()=>Fo,loadPinsFromStore:()=>ah,setPin:()=>Mn,sha256Hex:()=>Oo,wsTlsOptions:()=>Do});import{createHash as eh}from"crypto";import*as _c from"tls";import{Agent as th,Dispatcher as nh,buildConnector as sh,getGlobalDispatcher as rh,setGlobalDispatcher as oh}from"undici";function Mn(s,e,t){kt.set(Hs(s,e),Fc(t))}function $o(s,e){kt.delete(Hs(s,e))}function ih(s,e){return kt.get(Hs(s,e))}function ah(s){kt.clear();for(let e of s.list())e.entry.pinnedFingerprint&&Mn(e.host,e.port,e.entry.pinnedFingerprint)}function Fo(s){for(let e of s.list())e.pinnedFingerprint&&Mn(e.host,e.port,e.pinnedFingerprint)}async function dh(s,e,t={}){let n=t.timeoutMs??1e4;return new Promise((r,o)=>{let i=_c.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,Oo(u.raw))}),i.once("error",u=>d(u))})}function Oo(s){return eh("sha256").update(s).digest("hex")}function $c(s){let e=Fc(s),t=e.match(/.{2}/g);return t?t.join(":"):e}function Fc(s){return s.replace(/:/g,"").toLowerCase()}function No(){if(_o)return;_o=!0;let s=rh(),e=new th({connect:sh({rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(n,r)=>Nc(n,r)})}),t=new nh;t.dispatch=(n,r)=>{let o=ch(n.origin);return(o&&Oc(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(()=>{})),oh(t)}function ch(s){if(!s)return null;try{return new URL(String(s)).hostname}catch{return null}}function Oc(s){for(let e of kt.keys())if(Dc(e)?.host===s)return!0;return!1}function Nc(s,e){if(!e||!e.raw)return new Error(`TLS peer ${s} did not present a certificate`);let t=Oo(e.raw);for(let[n,r]of kt.entries()){let o=Dc(n);if(o&&o.host===s&&r===t)return}return new Error(`TLS pin mismatch for ${s} (cert sha256 ${$c(t)})`)}function Dc(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 Do(s){return Oc(s)?{rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(e,t)=>Nc(e,t)}:{autoSelectFamily:!0}}function uh(){kt.clear(),_o=!1}var kt,_o,_n=On(()=>{"use strict";Mc();kt=new Map,_o=!1});Y();import*as Ze from"fs/promises";import{homedir as or}from"os";import{z as I}from"zod";Y();import*as bt from"fs/promises";function Ys(){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 vu(){try{let e=(await bt.readFile(R.authToken(),"utf8")).trim();return e.length>0?e:void 0}catch(s){if(s.code==="ENOENT")return;throw s}}async function Xs(s){await bt.mkdir(R.home(),{recursive:!0}),await bt.writeFile(R.authToken(),s+`
4
+ `,{encoding:"utf8",mode:384})}async function Ko(){let s=await vu();if(s)return s;let e=Ys();return await Xs(e),process.stderr.write(`hydra-acp: initialized ${R.authToken()} with a fresh service token.
5
+ `),e}Oe();import*as Xo from"fs/promises";import*as Yt from"os";import*as Ne from"path";var ee="read by the daemon, which loads config.json at startup",Yo={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:ee},agentOverrides:{reload:"live",overlay:"inert",overlayNote:ee},registry:{reload:"live",overlay:"inert",overlayNote:ee},npmRegistry:{reload:"live",overlay:"inert",overlayNote:ee},defaultAgent:{reload:"live",overlay:"effective"},defaultCwd:{reload:"live",overlay:"effective"},sessionDefaults:{reload:"live",overlay:"partial",overlayNote:"applies to WS session/new and child_session/spawn; POST /v1/sessions has no model/mode/effort field to apply any of it to"},synopsisAgent:{reload:"warn",overlay:"inert",overlayNote:ee},synopsisModel:{reload:"warn",overlay:"inert",overlayNote:ee},compaction:{reload:"warn",overlay:"inert",overlayNote:ee},defaultTransformers:{reload:"warn",overlay:"inert",overlayNote:ee},disableWorkspaceSnapshots:{reload:"warn",overlay:"inert",overlayNote:ee},compressToolContent:{reload:"warn",overlay:"inert",overlayNote:ee},extensions:{reload:"warn",overlay:"inert",overlayNote:ee},transformers:{reload:"warn",overlay:"inert",overlayNote:ee},tui:{reload:"client",overlay:"effective"},sessionListColdLimit:{reload:"client",overlay:"effective"}},Ru={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:ee},logLevel:{reload:"warn",overlay:"inert",overlayNote:ee},sessionIdleTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:ee},nonInteractiveOrphanTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:ee},sessionHistoryMaxEntries:{reload:"warn",overlay:"inert",overlayNote:ee},sessionHistoryArchiveMaxBytes:{reload:"warn",overlay:"inert",overlayNote:ee},sessionHistoryArchiveTiers:{reload:"warn",overlay:"inert",overlayNote:ee},agentStderrTailBytes:{reload:"warn",overlay:"inert",overlayNote:ee},agentSyncIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:ee},sessionGcIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:ee},sessionGcMaxAgeDays:{reload:"warn",overlay:"inert",overlayNote:ee}};function Zs(s){return Yo[s]??{reload:"restart",overlay:"inert"}}function er(s){return Ru[s]??{reload:"restart",overlay:"inert"}}function tr(){let s=[];for(let[e,t]of Object.entries(Yo))t.overlay!=="effective"&&s.push({key:e,effect:t.overlay,note:t.overlayNote??ee});return s}var xu=".hydra-acp.json",nr="home",Eu=64,Ay=tr().map(s=>s.key);function Tu(s){return s==="~"?Yt.homedir():s.startsWith("~/")?Ne.join(Yt.homedir(),s.slice(2)):s.startsWith("$HOME/")?Ne.join(Yt.homedir(),s.slice(6)):s}function sr(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function rr(s,e){let t={...s};for(let[n,r]of Object.entries(e)){let o=t[n];t[n]=sr(o)&&sr(r)?rr(o,r):r}return t}async function Pu(s,e=Yt.homedir()){let t=[],n=[],r=Ne.resolve(e),o=Ne.resolve(s);for(let i=0;i<Eu;i+=1){let a=Ne.join(o,xu),d;try{d=await Xo.readFile(a,"utf8")}catch{d=void 0}if(d!==void 0)try{let u=JSON.parse(d);sr(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=Ne.dirname(o);if(c===o)break;o=c}return t.reverse(),{layers:t,notices:n}}function Mu(s){let e=new Map(tr().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 _u(s=process.cwd()){let{layers:e,notices:t}=await Pu(s);t.push(...Mu(e));let n={};for(let i of e)n=rr(n,i.data);let r,o=n[nr];return typeof o=="string"&&o.length>0?r=Ne.resolve(Tu(o)):o!==void 0&&t.push({file:e[e.length-1].file,key:nr,message:"`home` must be a non-empty string; ignoring it"}),delete n[nr],{layers:e,notices:t,merged:n,...r!==void 0?{homeRequest:r}:{}}}function $u(s,e){let t=s[e];return typeof t=="string"&&t.length>0?t:void 0}function Fu(s,e){let t=s[e];if(t===null||typeof t!="object"||Array.isArray(t))return;let n={};for(let[r,o]of Object.entries(t)){if(o===null||typeof o!="object"||Array.isArray(o))continue;let i={};for(let[a,d]of Object.entries(o))typeof d=="string"&&(i[a]=d);Object.keys(i).length>0&&(n[r]=i)}return Object.keys(n).length>0?n:void 0}async function Xt(s){let e={};try{e=(await _u(s)).merged}catch{return{}}let t=$u(e,"defaultAgent"),n=Fu(e,"sessionDefaults");return{...t!==void 0?{agentId:t}:{},...n!==void 0?{configDefaults:n}:{}}}var ti="https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",Ou=I.object({cert:I.string(),key:I.string()}),St=55514,Nu=I.object({host:I.string().default("127.0.0.1"),port:I.number().int().positive().default(St),logLevel:I.enum(["debug","info","warn","error"]).default("info"),tls:Ou.optional(),sessionIdleTimeoutSeconds:I.number().int().nonnegative().default(3600),nonInteractiveOrphanTimeoutSeconds:I.number().int().nonnegative().default(180),sessionHistoryMaxEntries:I.number().int().positive().default(1e4),sessionHistoryArchiveMaxBytes:I.number().int().nonnegative().default(1e7),sessionHistoryArchiveTiers:I.number().int().positive().default(10),agentStderrTailBytes:I.number().int().positive().default(4096),publicHost:I.string().optional(),agentSyncIntervalMinutes:I.number().nonnegative().default(60),scrubEnv:I.array(I.string()).default([]),sessionGcIntervalMinutes:I.number().nonnegative().default(60),sessionGcMaxAgeDays:I.number().positive().default(2)}),Du=I.object({url:I.string().url().default(ti),ttlHours:I.number().positive().default(24),pinned:I.boolean().default(!1)}),ju=I.object({extends:I.string().optional(),name:I.string().optional(),description:I.string().optional(),command:I.string().optional(),args:I.array(I.string()).optional(),env:I.record(I.string()).optional()}),Hu=I.object({packageSpec:I.string().optional(),extraArgs:I.array(I.string()).optional(),env:I.record(I.string()).optional()}),Lu=I.enum(["enter","alt-enter","shift-enter","ctrl-enter","alt-b","alt-f","alt-n","alt-tab","shift-tab","tab","up","down","left","right","home","end","backspace","alt-backspace","delete","ctrl-a","ctrl-b","ctrl-c","ctrl-d","ctrl-e","ctrl-f","ctrl-g","ctrl-k","ctrl-l","ctrl-n","ctrl-o","ctrl-p","ctrl-q","ctrl-r","ctrl-s","ctrl-u","ctrl-v","ctrl-t","ctrl-w","ctrl-x","ctrl-x-ctrl-e","ctrl-y","ctrl-underscore","alt-underscore","escape"]),Uu=I.union([I.string(),I.object({field:I.string().optional(),text:I.string().optional(),script:I.string().optional(),refreshMs:I.number().int().positive().optional(),maxWidth:I.number().int().positive().optional(),minWidth:I.number().int().nonnegative().optional(),truncate:I.boolean().optional(),priority:I.number().optional(),prefix:I.string().optional(),suffix:I.string().optional(),separator:I.string().optional(),style:I.string().optional(),onClick:I.string().optional(),onDoubleClick:I.string().optional()}).strict()]),Bu=I.object({id:I.string().min(1),script:I.string().min(1),refreshMs:I.number().int().positive().optional(),title:I.string().optional(),cap:I.number().int().positive().optional()}).strict(),Wu=I.union([I.string(),Bu]),Zo=I.array(Uu);function ir(s,e){return I.object({left:Zo.default(s),right:Zo.default(e)}).default({})}var qu=["status",{field:"elapsed",separator:" "},"sessionId","queued","scroll"],zu=["usage"],Ju=[],Vu=["helpHint"],Gu=["cwd","title"],Ku=["agentModel"],Qu=I.object({composer:I.object({top:ir(qu,zu),bottom:ir(Ju,Vu),hintTurns:I.number().int().nonnegative().nullable().default(3)}).default({}),sessionbar:ir(Gu,Ku),scriptRefreshMs:I.number().int().positive().default(5e3),repaintThrottleMs:I.number().int().nonnegative().default(1e3),maxScrollbackLines:I.number().int().positive().default(1e4),mouse:I.boolean().default(!0),inAppSelection:I.boolean().optional(),selectionClipboard:I.enum(["primary","clipboard","both"]).default("both"),openFileCommand:I.union([I.string(),I.array(I.string())]).optional(),openFileInTerminal:I.boolean().optional(),logMaxBytes:I.number().int().positive().default(5*1024*1024),cwdColumnMaxWidth:I.number().int().positive().default(32),progressIndicator:I.boolean().default(!0),terminalHost:I.union([I.boolean(),I.enum(["auto","paseo","herdr","tmux"])]).default(!0),launcherModeWhenHosted:I.boolean().default(!1),skipPermissions:I.boolean().default(!1),defaultEnterAction:I.enum(["enqueue","amend"]).default("amend"),showThoughts:I.boolean().default(!0),ambiguousWidth:I.enum(["auto","narrow","wide"]).default("auto"),toolContent:I.enum(["inline","references"]).default("references"),diffContextLines:I.number().int().min(0).default(3),promptHistoryMaxEntries:I.number().int().positive().default(2e3),maxToolItems:I.number().int().nonnegative().default(5),maxPlanItems:I.number().int().nonnegative().default(5),sidebar:I.object({enabled:I.boolean().default(!1),width:I.number().int().positive().optional(),border:I.enum(["none","rule","frame"]).default("frame"),gadgets:I.array(Wu).default(["activity","sessions","tasks","context","queue","todo","files","git","resources","info","tools"])}).default({}),showFileUpdates:I.enum(["none","edit","diff"]).default("edit"),sessionColumns:I.array(I.enum(["session","upstream","host","state","agent","model","age","cwd","title","cost"])).nonempty().optional(),hotkeys:I.record(Lu,I.object({command:I.union([I.string(),I.array(I.string())])})).default({}),theme:I.union([I.string(),I.record(I.string(),I.unknown())]).optional(),themeBackground:I.string().optional()}),ei=I.string().min(1).regex(/^[A-Za-z0-9._-]+$/,"extension name must be filename-safe"),Yu=I.object({command:I.array(I.string()).default([]),args:I.array(I.string()).default([]),env:I.record(I.string()).default({}),enabled:I.boolean().default(!0)}),Xu=I.object({command:I.array(I.string()).default([]),args:I.array(I.string()).default([]),env:I.record(I.string()).default({}),enabled:I.boolean().default(!0)}),Zu=I.object({daemon:Nu.default({}),registry:Du.default({url:ti,ttlHours:24,pinned:!1}),agents:I.record(I.string(),ju).default({}),agentOverrides:I.record(I.string(),Hu).default({}),defaultAgent:I.string().default("opencode"),sessionDefaults:I.record(I.string(),I.record(I.string(),I.string())).default({}),synopsisAgent:I.string().optional(),synopsisModel:I.string().optional(),compaction:I.object({agent:I.string().optional(),model:I.string().optional(),tailK:I.number().int().nonnegative().default(20),maxIterations:I.number().int().positive().default(3),contextFraction:I.number().min(0).max(1).default(.5),hardCeilingFraction:I.number().min(0).max(1).default(.85),absoluteFallback:I.number().int().positive().default(2e5),idleBeforePromptMs:I.number().int().nonnegative().default(3e5),modelContextWindows:I.record(I.string(),I.number().int().positive()).default({})}).default({}),defaultCwd:I.string().default("~"),disableWorkspaceSnapshots:I.boolean().optional(),compressToolContent:I.boolean().default(!0),sessionListColdLimit:I.number().int().nonnegative().default(20),extensions:I.record(ei,Yu).default({}),transformers:I.record(ei,Xu).default({}),defaultTransformers:I.array(I.string()).default([]),npmRegistry:I.string().url().optional(),tui:Qu.default({})});function ni(s){return Object.entries(s.extensions).map(([e,t])=>({name:e,...t}))}function si(s){return Object.entries(s.transformers).map(([e,t])=>({name:e,...t}))}async function ar(){return await el(),await oe(R.config())??{}}async function el(){let s;try{s=await Ze.lstat(R.config())}catch(e){if(e.code==="ENOENT")return;throw e}if(s.isSymbolicLink())try{await Ze.stat(R.config())}catch(e){if(e.code!=="ENOENT")throw e;let t=await Ze.readlink(R.config()).catch(()=>"<unknown>");throw new Error(`config.json at ${R.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 tl(){let s=await ar(),e=s.daemon,t=e&&typeof e.authToken=="string"?e.authToken:void 0;if(!t)return;let n=!1;try{await Ze.access(R.authToken()),n=!0}catch(r){if(r.code!=="ENOENT")throw r}if(n)throw new Error(`Auth token present in both ${R.authToken()} and ${R.config()} (daemon.authToken). Remove daemon.authToken from config.json to resolve.`);await Xs(t),delete e.authToken,Object.keys(e).length===0&&delete s.daemon,await ue(R.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated auth token from ${R.config()} to ${R.authToken()}.
6
+ `)}async function nl(){let s=await ar(),e=s.defaultModels&&typeof s.defaultModels=="object"&&!Array.isArray(s.defaultModels)?s.defaultModels:void 0;if(!e)return;let t=s.sessionDefaults&&typeof s.sessionDefaults=="object"&&!Array.isArray(s.sessionDefaults)?s.sessionDefaults:{};for(let[n,r]of Object.entries(e)){if(typeof r!="string")continue;let o=t[n]&&typeof t[n]=="object"&&!Array.isArray(t[n])?t[n]:{};o.model===void 0&&(o.model=r),t[n]=o}s.sessionDefaults=t,delete s.defaultModels,await ue(R.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated defaultModels to sessionDefaults in ${R.config()}.
7
+ `)}async function Zt(){return await tl(),await nl(),Zu.parse(await ar())}function le(s){return s==="~"||s==="$HOME"?or():s.startsWith("~/")?or()+s.slice(1):s.startsWith("$HOME/")?or()+s.slice(5):s}import*as cu from"fs";import*as Ge from"fs/promises";import*as uu from"net";import*as Gt from"path";import*as lu from"tls";import ay from"fastify";import dy from"@fastify/websocket";var ri="acp.v1";function oi(s,e){return s.has(ri)?ri:!1}import au from"pino";import cy from"pino-roll";var sl={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"]},ii="HYDRA_ACP_SESSION",rl=[ii],ol=[...Object.values(sl).flat(),...rl];function Nn(s,e){return s?{...e??{},[ii]:s}:e}var ai=[];function dr(s){ai=s?[...s]:[]}function il(s,e){return e.endsWith("*")?s.startsWith(e.slice(0,-1)):s===e}function al(){return[...ol,...ai]}function Dn(s=process.env){let e=al(),t={};for(let[n,r]of Object.entries(s))r!==void 0&&(e.some(o=>il(n,o))||(t[n]=r));return t}Y();import*as fe from"fs/promises";import{createHash as dl}from"crypto";import{gzip as cl,gunzip as ul}from"zlib";import{promisify as di}from"util";var ci=di(cl),ll=di(ul),ui=/^[A-Za-z0-9_-]+$/,fl=/^[a-f0-9]{64}$/,cr=!0;function li(s){cr=s}function jn(s,e){return ui.test(s)?e===void 0||fl.test(e):!1}function Hn(s,e){return`${R.toolBlobFile(s,e)}.gz`}async function ur(s,e){if(!jn(s))return null;let t=dl("sha256").update(e,"utf8").digest("hex"),n=Hn(s,t),r=R.toolBlobFile(s,t);for(let a of[n,r])try{return await fe.access(a),t}catch{}await fe.mkdir(R.toolsDir(s),{recursive:!0});let o=cr?n:r,i=cr?await ci(Buffer.from(e,"utf8")):Buffer.from(e,"utf8");return await fe.writeFile(o,i,{mode:384,flag:"wx"}).catch(async a=>{if(a.code!=="EEXIST")throw a}),t}async function en(s,e){if(!jn(s,e))return null;try{let t=await fe.readFile(Hn(s,e));return(await ll(t)).toString("utf8")}catch{}try{return await fe.readFile(R.toolBlobFile(s,e),"utf8")}catch{return null}}async function fi(s,e){if(!jn(s,e))return null;try{return await fe.readFile(Hn(s,e))}catch{}try{let t=await fe.readFile(R.toolBlobFile(s,e));return await ci(t)}catch{return null}}async function pi(s,e,t){if(!jn(s,e))return;let n=Hn(s,e);try{await fe.access(n);return}catch{}await fe.mkdir(R.toolsDir(s),{recursive:!0}),await fe.writeFile(n,t,{mode:384,flag:"wx"}).catch(r=>{if(r.code!=="EEXIST")throw r})}async function gi(s){ui.test(s)&&await fe.rm(R.toolsDir(s),{recursive:!0,force:!0}).catch(()=>{})}Y();import*as Ri from"fs/promises";import*as Un from"path";import{z as L}from"zod";Oe();Y();import*as hi from"fs";import*as ye from"fs/promises";import*as et from"path";import{spawn as yi}from"child_process";import{Readable as pl}from"stream";function De(){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 pr(s,e=De()){if(e)return s[e]}var It=s=>{process.stderr.write(s+`
8
+ `)};function gr(s){It=s??(e=>process.stderr.write(e+`
9
+ `))}async function wi(s){if(!s.target.archive)throw new Error(`Agent ${s.agentId} has no archive URL for ${De()??"this platform"}`);if(!s.target.cmd)throw new Error(`Agent ${s.agentId} has no cmd in its binary target`);let e=De();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=R.agentInstallDir(s.agentId,e,s.version),n=et.resolve(t,s.target.cmd);if(await fr(n))return n;if(await gl({agentId:s.agentId,version:s.version,archiveUrl:s.target.archive,installDir:t,onProgress:s.onProgress}),!await fr(n))throw new Error(`Agent ${s.agentId}: extracted archive did not contain ${s.target.cmd} (looked in ${t})`);return process.platform!=="win32"&&await ye.chmod(n,493).catch(()=>{}),n}async function gl(s){await ye.mkdir(et.dirname(s.installDir),{recursive:!0});let e=await ye.mkdtemp(`${s.installDir}.partial-`);try{It(`hydra-acp: downloading ${s.agentId} from ${s.archiveUrl}`);let t=await ml({url:s.archiveUrl,dir:e,agentId:s.agentId,version:s.version,onProgress:s.onProgress});It(`hydra-acp: extracting ${s.agentId}`),At(s.onProgress,{phase:"extract",agentId:s.agentId,version:s.version}),await yl(t,e),await ye.unlink(t).catch(()=>{});try{await ye.rename(e,s.installDir)}catch(n){let r=n;if((r.code==="EEXIST"||r.code==="ENOTEMPTY")&&await fr(s.installDir)){await ye.rm(e,{recursive:!0,force:!0}).catch(()=>{}),At(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw n}It(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),At(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await ye.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function At(s,e){if(s)try{s(e)}catch{}}async function ml(s){let e=hl(s.url),t=et.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=hi.createWriteStream(t),i=pl.fromWeb(n.body);At(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 m=Date.now();m-c>=l&&(c=m,At(s.onProgress,{phase:"download_progress",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r})),m-d>=u&&(d=m,It(mi(s.agentId,a,r)))}),await new Promise((p,m)=>{i.on("error",m),o.on("error",m),o.on("finish",()=>p()),i.pipe(o)}),It(mi(s.agentId,a,r,!0)),At(s.onProgress,{phase:"download_done",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r}),t}function mi(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 hl(s){let e=new URL(s);return et.posix.basename(e.pathname)||"archive"}async function yl(s,e){let t=s.toLowerCase();if(t.endsWith(".tar.gz")||t.endsWith(".tgz")||t.endsWith(".tar")){await lr("tar",["-xf",s,"-C",e]);return}if(t.endsWith(".zip")){if(await wl("unzip")){await lr("unzip",["-q",s,"-d",e]);return}await lr("tar",["-xf",s,"-C",e]);return}throw new Error(`Unsupported archive format: ${s}`)}function lr(s,e){return new Promise((t,n)=>{let r=yi(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 wl(s){return new Promise(e=>{let t=process.platform==="win32"?"where":"which",n=yi(t,[s],{stdio:"ignore"});n.on("error",()=>e(!1)),n.on("exit",r=>e(r===0))})}async function fr(s){try{return await ye.access(s),!0}catch{return!1}}Y();import*as Ie from"fs/promises";import*as je from"path";import{spawn as kl}from"child_process";var hr=s=>{process.stderr.write(s+`
10
+ `)};function yr(s){hr=s??(e=>process.stderr.write(e+`
11
+ `))}async function vi(s){let e=De();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=R.agentNpmInstallDir(s.agentId,e,s.version),n=Al(s.packageSpec),r=Cl(n),o={installDir:t,packageName:n,hint:s.bin,basename:r},i=je.join(t,"node_modules",".bin",s.bin);if(await ct(i))return i;if(await ct(t)){let l=await ki(o);if(l)return l.binPath}await vl({agentId:s.agentId,version:s.version,packageSpec:s.packageSpec,installDir:t,registry:s.registry,onProgress:s.onProgress});let a=await ki(o);if(a)return a.binPath;let d=await Si(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 vl(s){await Ie.mkdir(je.dirname(s.installDir),{recursive:!0});let e=await Ie.mkdtemp(`${s.installDir}.partial-`);try{hr(`hydra-acp: installing ${s.packageSpec} for ${s.agentId} into ${e}`),mr(s.onProgress,{phase:"install_start",agentId:s.agentId,version:s.version,packageSpec:s.packageSpec}),await Il({packageSpec:s.packageSpec,cwd:e,registry:s.registry});try{await Ie.rename(e,s.installDir)}catch(t){let n=t;if((n.code==="EEXIST"||n.code==="ENOTEMPTY")&&await ct(s.installDir)){await Ie.rm(e,{recursive:!0,force:!0}).catch(()=>{}),mr(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw t}hr(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),mr(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await Ie.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function mr(s,e){if(s)try{s(e)}catch{}}var bl=5,Sl=25;function Il(s){return bi(s,0)}async function bi(s,e){try{await new Promise((t,n)=>{let r=s.registry?["--registry",s.registry]:[],o;try{o=kl("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})
12
+ stderr: ${u}`:`npm install ${s.packageSpec} failed (${c})`))})})}catch(t){if(t.code==="ETXTBSY"&&e<bl)return await new Promise(r=>setTimeout(r,Sl*(e+1))),bi(s,e+1);throw t}}function Al(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 Cl(s){let e=s.lastIndexOf("/");return e===-1?s:s.slice(e+1)}async function Si(s,e){let t=je.join(s,"node_modules",e,"package.json");try{let n=await Ie.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 ki(s){let e=je.join(s.installDir,"node_modules",".bin"),t=je.join(e,s.hint);if(await ct(t))return{binName:s.hint,binPath:t};let n=await Si(s.installDir,s.packageName);if(typeof n=="object"&&n!==null){let r=Object.keys(n);if(r.length===1){let o=r[0],i=je.join(e,o);if(await ct(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=je.join(e,o);if(await ct(i))return{binName:o,binPath:i}}}}if(s.basename!==s.hint){let r=je.join(e,s.basename);if(await ct(r))return{binName:s.basename,binPath:r}}}async function ct(s){try{return await Ie.access(s),!0}catch{return!1}}var Rl=L.object({package:L.string(),bin:L.string().optional(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),Ct=L.object({archive:L.string().url().optional(),cmd:L.string().optional(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),xl=L.object({"darwin-aarch64":Ct.optional(),"darwin-x86_64":Ct.optional(),"linux-aarch64":Ct.optional(),"linux-x86_64":Ct.optional(),"windows-x86_64":Ct.optional(),"windows-aarch64":Ct.optional()}),El=L.object({package:L.string(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),Tl=L.object({command:L.string(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),Pl=L.object({command:L.string().optional(),url:L.string().optional(),description:L.string().optional()}),Ml=L.object({npx:Rl.optional(),binary:xl.optional(),uvx:El.optional(),exec:Tl.optional()}),_l=L.object({id:L.string(),name:L.string(),version:L.string().optional(),description:L.string().optional(),authors:L.array(L.string()).optional(),license:L.string().optional(),icon:L.string().optional(),repository:L.string().optional(),website:L.string().optional(),distribution:Ml,onboarding:Pl.optional(),requiredEnv:L.array(L.string().min(1)).optional()}),Ii=8;function xi(s){return s.installId??s.id}function kr(s){let e=s.extendsChain;return e&&e.length>0?e[e.length-1]:s.id}function tn(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 Ai=L.object({version:L.string(),agents:L.array(_l),extensions:L.array(L.unknown()).optional()}),Ln=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{...wr(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>=Ii)throw new Error(`agent ${n.id}: extends chain deeper than ${Ii} (${[...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(Fl(n.id,n.def,c))}let r=await this.load(),o=r.agents.find(c=>c.id===e);if(o)return this.applyOverride(o);let i=r.agents.find(c=>vr(c)===e);if(i)return this.applyOverride(i);let a=e.toLowerCase(),d=r.agents.find(c=>c.id.toLowerCase()===`${a}-acp`);if(d)return this.applyOverride(d);if(a.length>0){let c=r.agents.filter(u=>u.id.toLowerCase().startsWith(a));if(c.length===1)return this.applyOverride(c[0])}}findLocalDef(e){let t=this.config.agents??{},n=t[e];if(n)return{id:e,def:n};let r=e.toLowerCase();for(let[o,i]of Object.entries(t))if(o.toLowerCase()===`${r}-acp`)return{id:o,def:i}}localAgents(){return Object.entries(this.config.agents??{}).filter(([,e])=>e.extends===void 0).map(([e,t])=>wr(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=Ol(n.packageSpec),i=t.id,r={...r,npx:{...r.npx,package:n.packageSpec}}),n.extraArgs?.length&&(r=$l(r,n.extraArgs)),n.env&&Object.keys(n.env).length>0&&(r=Ei(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=Ai.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 oe(R.registryCache());if(!(!e||typeof e.fetchedAt!="number"||e.data===void 0))try{let t=Ai.parse(e.data);return{fetchedAt:e.fetchedAt,raw:e.data,data:t}}catch{return}}async writeDiskCache(e){await ue(R.registryCache(),{fetchedAt:e.fetchedAt,data:e.raw})}};function wr(s,e){return{id:s,name:e.name??s,description:e.description,version:"local",distribution:{exec:{command:le(e.command??s),args:e.args?.map(le),env:e.env}}}}function Ei(s,e){let t=e.args?.map(le),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 $l(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 Fl(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?wr(s,e).distribution:Ei(t.distribution,e),installId:n?s:t.installId??t.id,extendsChain:[s,...t.extendsChain??[t.id]]}}function Ol(s){let e=s.lastIndexOf("@"),n=(e>0?s.slice(e+1):"").replace(/[^a-zA-Z0-9._-]/g,"_");return n.length>0?`pin-${n}`:"pinned"}function vr(s){let e=s.distribution.npx?.package;if(!e)return;let t=e.lastIndexOf("/"),n=t===-1?e:e.slice(t+1),r=n.lastIndexOf("@");return r<=0?n:n.slice(0,r)}async function Rt(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 br(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 br(s){let e=De();if(!e)return"no";let t=s.version??"current",n=xi(s);if(s.distribution.exec)return"yes";if(s.distribution.binary){let r=pr(s.distribution.binary,e);if(r?.cmd){let o=Un.resolve(R.agentInstallDir(n,e,t),r.cmd);if(await Ci(o))return"yes"}}if(s.distribution.npx){let r=s.distribution.npx,o=r.bin??vr(s)??r.package,i=R.agentNpmInstallDir(n,e,t),a=Un.join(i,"node_modules",".bin",o);if(await Ci(a))return"yes"}return!s.distribution.npx&&!s.distribution.binary&&s.distribution.uvx?"lazy":"no"}async function Ci(s){try{return await Ri.access(s),!0}catch{return!1}}async function Re(s,e=[],t={}){let n=s.version??"current",r=xi(s);if(s.distribution.npx){let o=s.distribution.npx,i=e.length>0?e:o.args??[];if(process.env.HYDRA_ACP_SKIP_NPM_PREFETCH)return{command:"npx",args:["-y",o.package,...i],env:o.env??{},version:n,installId:r};let a=o.bin??vr(s)??o.package,d=t.onInstallProgress;return{command:await vi({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=pr(s.distribution.binary);if(!o)throw new Error(`Agent ${s.id} has no binary distribution for ${De()??"this platform"}.`);let i=t.onInstallProgress,a=await wi({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 Ll}from"child_process";import*as qn from"fs";import*as zi from"path";var x={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603,AuthRequired:-32e3,SessionNotFound:-32001,NotAuthorisedToAttach:-32002,MultiClientNotSupported:-32003,AgentNotInstalled:-32005,BundleAlreadyImported:-32010,PermissionDenied:-32011,AlreadyAttached:-32012,StreamNotEnabled:-32013,SessionClosing:-32014};import{z as G}from"zod";var Ti=G.object({protocolVersion:G.number().optional(),clientCapabilities:G.record(G.unknown()).optional(),clientInfo:G.object({name:G.string(),version:G.string().optional()}).optional()}),Nl=G.enum(["full","pending_only","none","after_message"]),Pi=G.object({cwd:G.string(),mcpServers:G.array(G.unknown()).optional(),_meta:G.record(G.unknown()).optional()}),Mi=G.object({upstreamSessionId:G.string(),agentId:G.string(),cwd:G.string(),title:G.string().optional(),agentArgs:G.array(G.string()).optional()}),_i=G.object({sessionId:G.string(),historyPolicy:Nl.default("full"),afterMessageId:G.string().optional(),afterSeq:G.number().optional(),clientId:G.string().optional(),clientInfo:G.object({name:G.string(),version:G.string().optional()}).optional(),_meta:G.record(G.unknown()).optional()});import{z as D}from"zod";var $i=D.object({sessionId:D.string()}),Fi=D.object({cwd:D.string().optional(),cursor:D.string().optional()}),Sr=D.object({used:D.number().optional(),size:D.number().optional(),costAmount:D.number().optional(),costCurrency:D.string().optional()}),aw=D.object({sessionId:D.string(),upstreamSessionId:D.string().optional(),cwd:D.string(),workspace:D.object({path:D.string(),sourceCwd:D.string(),label:D.string(),provider:D.string(),snapshot:D.string().optional(),vcs:D.record(D.string(),D.string()).optional()}).optional(),workspaceError:D.string().optional(),title:D.string().optional(),agentId:D.string().optional(),currentModel:D.string().optional(),currentUsage:Sr.optional(),importedFromMachine:D.string().optional(),importedFromUpstreamSessionId:D.string().optional(),parentSessionId:D.string().optional(),forkedFromSessionId:D.string().optional(),forkedFromMessageId:D.string().optional(),originatingClient:D.object({name:D.string(),version:D.string().optional()}).optional(),interactive:D.boolean().optional(),priority:D.number().int().nonnegative().optional(),updatedAt:D.string(),attachedClients:D.number().int().nonnegative(),status:D.enum(["warm","cold"]).default("warm"),busy:D.boolean().default(!1),awaitingInput:D.boolean().default(!1),armedTasks:D.number().int().nonnegative().optional(),armedSince:D.number().int().positive().optional(),compactionState:D.any().optional(),agentPid:D.number().int().positive().optional(),forkSynthesisState:D.enum(["running","failed"]).optional(),_meta:D.record(D.unknown()).optional()}),Dl=D.object({sessionId:D.string(),cwd:D.string(),title:D.string().optional(),updatedAt:D.string().optional(),_meta:D.record(D.unknown()).optional()}),dw=D.object({sessions:D.array(Dl),nextCursor:D.string().optional()});function Bn(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 Oi(s){let e={sessionId:s.sessionId,cwd:s.cwd,updatedAt:s.updatedAt,_meta:nn(s._meta,Bn(s))};return s.title!==void 0&&(e.title=s.title),e}var ae="hydra-acp";function jl(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 ut(s){if(!s)return{};let e=s[ae];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),typeof t.historyLimit=="number"&&Number.isFinite(t.historyLimit)&&t.historyLimit>=0&&(n.historyLimit=t.historyLimit),(t.toolContent==="inline"||t.toolContent==="references")&&(n.toolContent=t.toolContent),t.detachStatus==="detached"&&(n.detachStatus=t.detachStatus),typeof t.title=="string"&&(n.title=t.title),Array.isArray(t.agentArgs)&&t.agentArgs.every(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=Mi.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=Sr.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=jl(t.env);r!==void 0&&(n.env=r)}return n}function He(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[ae],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.recordedAt=="number"?s:{...t,_meta:{...n,[ae]:{...o,recordedAt:e}}}}function Le(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[ae],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.seq=="number"?s:{...t,_meta:{...n,[ae]:{...o,seq:e}}}}function nn(s,e){return{...s??{},[ae]:e}}import{z as _}from"zod";var Ni=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.record(_.unknown()).optional()}),Wn=_.object({sessionId:_.string()}),Di=_.object({clientId:_.string(),name:_.string().optional(),version:_.string().optional()}),gw=_.object({sessionId:_.string(),messageId:_.string(),originator:Di,prompt:_.array(_.unknown()),position:_.number().int().nonnegative(),queueDepth:_.number().int().positive(),enqueuedAt:_.number()}),mw=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),hw=_.object({sessionId:_.string(),messageId:_.string(),reason:_.enum(["started","cancelled","abandoned"])}),ji=_.object({sessionId:_.string(),messageId:_.string()}),yw=_.object({cancelled:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),Hi=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),ww=_.object({updated:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),Li=_.object({sessionId:_.string(),targetMessageId:_.string(),prompt:_.array(_.unknown()),replaceQueue:_.boolean().optional(),onTargetCompleted:_.enum(["reject","send_anyway"]).optional()}),kw=_.object({amended:_.boolean(),reason:_.enum(["ok","target_completed","target_cancelled","target_not_found"]),messageId:_.string().optional()}),Ui=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.object({steering:_.object({idleBehavior:_.literal("promptRequired").optional()}).optional()}).optional()}),vw=_.object({outcome:_.enum(["injected","startedNewTurn","promptRequired","failed"]),reason:_.literal("noRunningTurn").optional(),detached:_.boolean().optional()}),bw=_.object({sessionId:_.string(),cancelledMessageId:_.string(),newMessageId:_.string(),prompt:_.array(_.unknown()),originator:Di,amendedAt:_.number()});import{z as tt}from"zod";var Aw=tt.object({agentId:tt.string(),version:tt.string(),source:tt.enum(["binary","npm"]),phase:tt.enum(["download_start","download_progress","download_done","extract","install_start","installed"]),receivedBytes:tt.number().optional(),totalBytes:tt.number().optional(),packageSpec:tt.string().optional()}),Bi="hydra-acp/agents/install_progress",xt={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(`
13
+ `);for(;d!==-1;){let c=t.slice(0,d).trim();if(t=t.slice(d+1),c.length>0)try{let u=JSON.parse(c);for(let l of n)l(u)}catch(u){for(let l of n)l({jsonrpc:"2.0",id:null,error:{code:x.ParseError,message:`Failed to parse ndjson line: ${u.message}`}})}d=t.indexOf(`
14
14
  `)}}),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)+`
15
- `;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 cl}from"nanoid";var or=class extends Error{code="ERR_CONNECTION_CLOSED";constructor(e="connection is closed"){super(e),this.name="ConnectionClosedError"}},kt=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 or;let n=cl(),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:C.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??C.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 ll=4096,Ye=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??ll,this.killEscalationMs=e.killEscalationMs??fl,this.logger=e.logger,this.fileLog=pl(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()} ---
16
- `),!t.stdout||!t.stdin)throw new Error("agent subprocess missing stdio");let n=ki(t.stdout,t.stdin);this.connection=new kt(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()} ---
15
+ `;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 Hl}from"nanoid";var Ir=class extends Error{code="ERR_CONNECTION_CLOSED";constructor(e="connection is closed"){super(e),this.name="ConnectionClosedError"}},nt=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 Ir;let n=Hl(),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:x.MethodNotFound,message:`Method not found: ${e.method}`}).catch(()=>{});return}try{let n=await t(e.params,e.method),r={jsonrpc:"2.0",id:e.id,result:n};await this.stream.send(r).catch(()=>{})}catch(n){let r=n;await this.sendError(e.id,{code:r.code??x.InternalError,message:r.message,data:r.data}).catch(()=>{})}}handleNotification(e){let t=this.notificationHandlers.get(e.method);if(t){t(e.params,e.method);return}let n=this.bufferedNotifications.get(e.method);if(!n){if(this.bufferedNotifications.size>=s.MAX_BUFFERED_METHODS){let r=this.bufferedNotifications.keys().next().value;r!==void 0&&this.bufferedNotifications.delete(r)}n=[],this.bufferedNotifications.set(e.method,n)}n.push(e),n.length>s.MAX_BUFFERED_PER_METHOD&&n.shift()}handleResponse(e){let t=e.id===null?void 0:this.pending.get(e.id);if(!t){if(e.error)for(let n of this.orphanErrorHandlers)try{n({code:e.error.code,message:e.error.message,data:e.error.data})}catch{}return}if(this.pending.delete(e.id),e.error){let n=new Error(e.error.message);n.code=e.error.code,n.data=e.error.data,t.reject(n)}else t.resolve(e.result)}async sendError(e,t){let n={jsonrpc:"2.0",id:e,error:t};await this.stream.send(n)}handleClose(e){if(!this.closed){this.closed=!0;for(let t of this.pending.values())t.reject(e??new Error("connection closed"));this.pending.clear();for(let t of this.closeHandlers)t(e)}}};Y();var Ul=4096,st=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??Ul,this.killEscalationMs=e.killEscalationMs??Bl,this.logger=e.logger,this.fileLog=Wl(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()} ---
16
+ `),!t.stdout||!t.stdin)throw new Error("agent subprocess missing stdio");let n=Wi(t.stdout,t.stdin);this.connection=new nt(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()} ---
17
17
  `),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()} ---
18
18
  `),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}
19
- stderr: ${t}`:e}stderrTailText(){return this.stderrTail.trim()}static spawn(e){let t={...Cn(),...e.plan.env,...e.extraEnv??{}},n=ul(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
+ stderr: ${t}`:e}stderrTailText(){return this.stderrTail.trim()}static spawn(e){let t={...Dn(),...e.plan.env,...e.extraEnv??{}},n=Ll(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()} ---
20
20
  `),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()} ---
21
- `),this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} did not exit after ${e}; sending SIGKILL`),this.signalProcessGroup("SIGKILL"),await this.waitForExit(vi),this.exited||this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} still has not exited ${vi}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)})}},fl=2e3,vi=5e3;function pl(s){try{let e=A.agentLogFile(s);_n.mkdirSync(bi.dirname(e),{recursive:!0});let t=_n.createWriteStream(e,{flags:"a"});return t.on("error",()=>{}),t}catch{return}}import*as ct from"fs/promises";import*as Qa from"os";import*as Si from"os";function Gt(){return Si.hostname()}import*as pn from"path";import{customAlphabet as Rp}from"nanoid";var Ne="session/set_model",ar="session/set_config_option",Ci="model";function ir(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.availableModels)}function xi(s){return Array.isArray(s)&&s.some(e=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.id===Ci)}function vt(s){if(!s)return;if(ir(s)||ir(s.models))return Ne;let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){for(let[t,n]of Object.entries(e))if(t!=="hydra-acp"&&ir(n))return Ne}if(xi(s.configOptions))return ar}function Ri(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.sessionUpdate;if(e==="_hydra_current_model_update")return Ne;if(e==="config_option_update"&&xi(s.configOptions))return ar}function Ii(s){return typeof s=="object"&&s!==null&&s.code===C.MethodNotFound}function Ai(s,e,t,n){let r={...n??{}};return delete r.sessionId,delete r.modelId,delete r.configId,delete r.value,s===Ne?{...r,sessionId:e,modelId:t}:{...r,sessionId:e,configId:Ci,value:t}}function gl(s){return s===Ne?ar:Ne}async function Xe(s){let{request:e,sessionId:t,modelId:n,extraParams:r,logger:o}=s,i=s.verb??Ne;try{let a=await e(i,Ai(i,t,n,r));return{verb:i,result:a}}catch(a){if(!Ii(a))throw a;let d=gl(i);o?.info(`agent does not implement ${i} (MethodNotFound); retrying model change via ${d} modelId=${JSON.stringify(n)}`);try{let c=await e(d,Ai(d,t,n,r));return{verb:d,result:c}}catch(c){throw Ii(c)?a:c}}}async function rt(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 ot(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 Xe({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 ea}from"nanoid";import{createHmac as ml}from"crypto";function hl(s,e){return ml("sha256",s).update(e).digest("hex")}function dr(s,e){let t=JSON.stringify(e),n=hl(s.secret,t);fetch(s.callbackUrl,{method:"POST",headers:{"Content-Type":"application/json","X-Hydra-Turn-Notify-Signature":n},body:t}).catch(()=>{})}var Ei="edit",$n=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 Ti(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 Mi from"fs/promises";var yl=64*1024*1024,wl=1*1024*1024,bt=64*1024,kl=6e4,vl=100,bl=1e3,Sl=64*1024,Il=256*1024,Pi=20;function Al(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var On=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??yl,this.maxCapacityBytes<=0)throw new Error("capacityBytes must be > 0");this.currentCapacityBytes=Math.min(wl,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,bt));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,bt)),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,bt)),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,kl));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(Al(e.pattern),d),u=e.invert??!1,l=Math.max(1,Math.min(e.maxMatches??vl,bl)),p=Math.max(1,Math.min(e.maxBytes??Sl,Il)),f=Math.max(0,Math.min(e.contextBefore??0,Pi)),m=Math.max(0,Math.min(e.contextAfter??0,Pi)),g=[],h=[],w=[],k=0,y=!1,b=0,I=0,v=(R,M)=>{for(let B of w)B.remaining>0&&(B.match.after===void 0&&(B.match.after=[]),B.match.after.push({cursor:R,line:M}),B.remaining--,k+=M.length);for(;w.length>0&&w[0].remaining===0;)w.shift();if(c.test(M)!==u&&g.length<l){let B={cursor:R,line:M};if(f>0&&h.length>0){B.before=h.slice();for(let Z of B.before)k+=Z.line.length}k+=M.length,g.push(B),m>0&&w.push({match:B,remaining:m})}if(f>0)for(h.push({cursor:R,line:M});h.length>f;)h.shift();let D=g.length>=l&&w.length===0,q=k>=p;return D||q};for(let R=0;R<i.length;R++){if(i[R]!==10)continue;let M=i.subarray(b,R).toString("utf8"),T=r+b;if(b=R+1,I=b,v(T,M)){y=!0;break}}if(!y&&b<i.length&&this.closed){let R=i.subarray(b).toString("utf8"),M=r+b;v(M,R)&&(y=!0),I=i.length}let x=Math.min(r+I,this.writeCursor),E={matches:g,truncated:y,nextCursor:x,scannedBytes:I};return o>0&&(E.gap=o),this.closed&&x>=this.writeCursor&&(E.eof=!0),E}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(()=>Mi.appendFile(t,r)).catch(i=>{this.logWriteError?.(i)}),o&&!this.fileCapReached&&(this.fileCapReached=!0,this.onFileCapReached?.())}async drainFileWrites(){await this.fileWriteChain.catch(()=>{})}};var St=[{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."}],fw=new Map(St.map(s=>[s.verb,s]));function _i(s){let e=s.lastIndexOf("/");return(e===-1?s:s.slice(e+1)).toLowerCase()}function It(s,e){return Kt(s,e.map(t=>t.modelId))}function Kt(s,e){if(e.length===0)return{kind:"none",requested:s};if(e.includes(s))return{kind:"exact",modelId:s};let t=_i(s),n=e.filter(o=>_i(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 Oi(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=cr(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 Tl){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=cr(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?(Rl(r,o.outIndex,Cl(c.content)),xl(r,o.outIndex,d.seq)):(r.push(d),o={outIndex:r.length-1,kind:u});continue}if(o=null,u==="tool_call_update"){let l=typeof c.toolCallId=="string"?c.toolCallId:void 0;if(l!==void 0&&e.get(l)!==a)continue;let p=l!==void 0&&t.has(l)?El(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(cr(p)?.[m])||(p=Pl(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 cr(s){if(s.method!=="session/update")return;let t=s.params?.update;if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function Cl(s){if(!s||typeof s!="object")return"";let e=s;return typeof e.text=="string"?e.text:""}function xl(s,e,t){let n=s[e];n===void 0||typeof t!="number"||n.seq!==void 0&&n.seq>=t||(s[e]={...n,seq:t})}function Rl(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 El(s,e){let t=s.params??{},n=t.update??{};return{...s,params:{...t,update:{...n,content:e}}}}var Tl=["rawInput","locations"];function $i(s){return s==null||typeof s!="object"?!1:Array.isArray(s)?s.length>0:Object.keys(s).length>0}function Pl(s,e,t){let n=s.params??{},r=n.update??{};return{...s,params:{...n,update:{...r,[e]:t}}}}var Fi=`[older history truncated]
22
- `,Ni=["file_path","filePath","path","command","pattern","query"];function At(s,e={}){let t=e.maxChars??4e5,n=ur(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=gr(u.prompt).trim();p.length>0&&r.push(`User: ${p}`)}else if(l==="agent_message_chunk"){let p=mr(u.content);p.length>0&&(o+=p)}else if(l==="tool_call"){if(a(),r.push(pr(u,n)),e.toolOutput!==void 0){let p=fr(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(),Dl(r.join(`
23
- `),t)}function ur(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=fr(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=_l(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=Fn(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=lr(t);return e}function lr(s){return Ml(s)?s.kind??"(unnamed)":s.name}function Ml(s){for(let e of Ni){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 _l(s,e){let t=Qt(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 fr(s){let e=s.toolCallId;if(typeof e=="string"&&e.length>0)return e}function Fn(s){let e=$l(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 $l(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(`
24
- `)}function Qt(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 pr(s,e){let t=fr(s),n=t!==void 0?e?.get(t):void 0,r=n?.name??Ol(s),o=Fl(n?.rawInput??s.rawInput);return o.length===0?`Tool: ${r}`:`Tool: ${r}(${o.join(", ")})`}function Ol(s){let e=Qt(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 Fl(s){if(!s||typeof s!="object"||Array.isArray(s))return[];let e=s,t=[];for(let n of Ni){let r=e[n];typeof r=="string"&&r.length>0&&t.push(`${n}=${Nl(r,600)}`)}return t}function gr(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 mr(s){if(!s||typeof s!="object")return"";let e=s.text;return typeof e=="string"?e:""}function Nl(s,e){return s.length<=e?s:s.slice(0,e-1)+"\u2026"}function Dl(s,e){if(s.length<=e)return s;let t=s.split(`
25
- `);for(;t.length>0;){let n=Fi+t.join(`
26
- `);if(n.length<=e)return n;t.shift()}return Fi}var Di="(untitled)";function hr(s){let e=[],t=s.synopsis;if(t!==void 0){e.push("--- begin prior session compaction ---"),e.push(`[Title] ${s.title??Di}`),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=Yt("Open threads",t.open_threads);d.length>0&&e.push(d);let c=Yt("Decisions",t.decisions);c.length>0&&e.push(c);let u=Yt("File edit intentions",t.file_edit_intentions);u.length>0&&e.push(u);let l=Yt("Unresolved errors",t.unresolved_errors);l.length>0&&e.push(l);let p=Yt("Tool state",t.tool_state);p.length>0&&e.push(p);let f=ji(t.files_touched);f.length>0&&e.push(`[Files previously touched] ${f}`);let m=ji(t.tools_used);m.length>0&&e.push(`[Tools previously used] ${m}`),e.push("--- end prior session compaction ---")}else e.push(`[Title] ${s.title??Di}`);s.note!==void 0&&s.note.trim().length>0&&e.push(`[Situation] ${s.note.trim()}`);let{closedText:n,openText:r,keptCount:o}=jl(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(`
27
- `)}function Yt(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(`
28
- `)}`}function ji(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 jl(s,e,t,n){if(s.length===0)return{closedText:"",openText:"",keptCount:0};let{closed:r,open:o}=Hl(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(`
29
- `)}function Hl(s){let e=[],t=null,n=ur(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:gr(d.prompt).trim(),agent:"",tools:[],startEntryIndex:o};else if(c==="agent_message_chunk"&&t!==null){let u=mr(d.content);u.length>0&&(t.agent+=u)}else c==="tool_call"&&t!==null?t.tools.push(pr(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:Ll(a),unknownCount:r.filter(d=>d.reason===void 0&&d.inferredReason===void 0&&!d.notCompaction).length}}function Ll(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 Ul(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 Li(s){if(s<1e3)return String(s);let e=s/1e3;return e<100?`${e.toFixed(1)}k`:`${Math.round(e)}k`}function Bl(s){return s.usedBefore===void 0||s.usedAfter===void 0?"":` ${Li(s.usedBefore)} \u2192 ${Li(s.usedAfter)}`}function Bi(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=Bl(r),i=r.cost!==void 0?` $${r.cost.toFixed(2)}`:"",a=r.current?" (current)":"",d=r.swaps>1?` (${r.swaps} swaps)`:"";n.push(` ${Ul(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 Wl(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function yr(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(`${Wl(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 wr(s,e){if(e.length===0)return!1;let t=e.endsWith("/")?e.slice(0,-1):e;return s.includes(t)}function Wi(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(`
30
- `)}function qi(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(`
31
- `)}function zi(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 De from"fs/promises";async function Xt(s,e){let t=A.queueFile(s);if(e.length===0){await De.unlink(t).catch(()=>{});return}await De.mkdir(A.sessionDir(s),{recursive:!0});let n=e.map(r=>JSON.stringify(r)).join(`
21
+ `),this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} did not exit after ${e}; sending SIGKILL`),this.signalProcessGroup("SIGKILL"),await this.waitForExit(qi),this.exited||this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} still has not exited ${qi}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)})}},Bl=2e3,qi=5e3;function Wl(s){try{let e=R.agentLogFile(s);qn.mkdirSync(zi.dirname(e),{recursive:!0});let t=qn.createWriteStream(e,{flags:"a"});return t.on("error",()=>{}),t}catch{return}}import*as yt from"fs/promises";import*as vd from"os";import*as Ji from"os";function sn(){return Ji.hostname()}import*as Sn from"path";import{customAlphabet as sg}from"nanoid";var Ue="session/set_model",Cr="session/set_config_option",Ki="model";function Ar(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.availableModels)}function Qi(s){return Array.isArray(s)&&s.some(e=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.id===Ki)}function Et(s){if(!s)return;if(Ar(s)||Ar(s.models))return Ue;let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){for(let[t,n]of Object.entries(e))if(t!=="hydra-acp"&&Ar(n))return Ue}if(Qi(s.configOptions))return Cr}function Yi(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.sessionUpdate;if(e==="_hydra_current_model_update")return Ue;if(e==="config_option_update"&&Qi(s.configOptions))return Cr}function Vi(s){return typeof s=="object"&&s!==null&&s.code===x.MethodNotFound}function Gi(s,e,t,n){let r={...n??{}};return delete r.sessionId,delete r.modelId,delete r.configId,delete r.value,s===Ue?{...r,sessionId:e,modelId:t}:{...r,sessionId:e,configId:Ki,value:t}}function ql(s){return s===Ue?Cr:Ue}async function rt(s){let{request:e,sessionId:t,modelId:n,extraParams:r,logger:o}=s,i=s.verb??Ue;try{let a=await e(i,Gi(i,t,n,r));return{verb:i,result:a}}catch(a){if(!Vi(a))throw a;let d=ql(i);o?.info(`agent does not implement ${i} (MethodNotFound); retrying model change via ${d} modelId=${JSON.stringify(n)}`);try{let c=await e(d,Gi(d,t,n,r));return{verb:d,result:c}}catch(c){throw Vi(c)?a:c}}}async function lt(s){let{agent:e,upstreamSessionId:t,persistedMode:n,agentReportedMode:r,advertisedModes:o,logger:i}=s;if(!n)return r;if(n===r)return n;if(o&&o.length>0&&!o.some(a=>a.id===n)){let a=o.map(d=>d.id).join(", ");return i?.warn(`resurrect: persisted currentMode=${JSON.stringify(n)} not in agent's availableModes ([${a}]); skipping session/set_mode, session will use ${JSON.stringify(r)}`),r}try{return i?.info(`resurrect: pushing persisted modeId=${JSON.stringify(n)} to agent (agentReported=${JSON.stringify(r)})`),await e.connection.request("session/set_mode",{sessionId:t,modeId:n}),i?.info(`resurrect: session/set_mode accepted, effectiveMode=${JSON.stringify(n)}`),n}catch(a){return i?.warn(`resurrect: session/set_mode rejected by agent for modeId=${JSON.stringify(n)} (${a.message}); session will use ${JSON.stringify(r)}`),r}}async function ft(s){let{agent:e,upstreamSessionId:t,persistedModel:n,agentReportedModel:r,modelVerb:o,logger:i}=s;if(!n)return{modelId:r};if(n===r)return{modelId:n};try{i?.info(`resurrect: pushing persisted modelId=${JSON.stringify(n)} to agent (agentReported=${JSON.stringify(r)})`);let{verb:a,result:d}=await rt({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 Aa}from"nanoid";function Tt(s){return`${s.name}:${s.localId}`}function pt(s){let e=s.indexOf(":");if(e===-1)return;let t=s.slice(0,e),n=s.slice(e+1);if(!(t.length===0||n.length===0))return{name:t,localId:n}}import{createHmac as zl}from"crypto";function Jl(s,e){return zl("sha256",s).update(e).digest("hex")}function Rr(s,e){let t=JSON.stringify(e),n=Jl(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",zn=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 Zi(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 ta from"fs/promises";var Vl=64*1024*1024,Gl=1*1024*1024,Pt=64*1024,Kl=6e4,Ql=100,Yl=1e3,Xl=64*1024,Zl=256*1024,ea=20;function ef(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Jn=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??Vl,this.maxCapacityBytes<=0)throw new Error("capacityBytes must be > 0");this.currentCapacityBytes=Math.min(Gl,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,Pt));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,Pt)),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,Pt)),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,Kl));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(ef(e.pattern),d),u=e.invert??!1,l=Math.max(1,Math.min(e.maxMatches??Ql,Yl)),p=Math.max(1,Math.min(e.maxBytes??Xl,Zl)),m=Math.max(0,Math.min(e.contextBefore??0,ea)),h=Math.max(0,Math.min(e.contextAfter??0,ea)),f=[],g=[],w=[],y=0,k=!1,b=0,S=0,v=(C,T)=>{for(let $ of w)$.remaining>0&&($.match.after===void 0&&($.match.after=[]),$.match.after.push({cursor:C,line:T}),$.remaining--,y+=T.length);for(;w.length>0&&w[0].remaining===0;)w.shift();if(c.test(T)!==u&&f.length<l){let $={cursor:C,line:T};if(m>0&&g.length>0){$.before=g.slice();for(let W of $.before)y+=W.line.length}y+=T.length,f.push($),h>0&&w.push({match:$,remaining:h})}if(m>0)for(g.push({cursor:C,line:T});g.length>m;)g.shift();let H=f.length>=l&&w.length===0,J=y>=p;return H||J};for(let C=0;C<i.length;C++){if(i[C]!==10)continue;let T=i.subarray(b,C).toString("utf8"),M=r+b;if(b=C+1,S=b,v(M,T)){k=!0;break}}if(!k&&b<i.length&&this.closed){let C=i.subarray(b).toString("utf8"),T=r+b;v(T,C)&&(k=!0),S=i.length}let E=Math.min(r+S,this.writeCursor),A={matches:f,truncated:k,nextCursor:E,scannedBytes:S};return o>0&&(A.gap=o),this.closed&&E>=this.writeCursor&&(A.eof=!0),A}wakeWaiters(e){if(this.waiters.length===0)return;let t=this.waiters;this.waiters=[];for(let n of t)n.resolve(e)}growIfNeeded(e){if(this.currentCapacityBytes>=this.maxCapacityBytes)return;let t=this.writeCursor+e;if(t<=this.currentCapacityBytes)return;let n=this.currentCapacityBytes;for(;n<t&&n<this.maxCapacityBytes;)n=Math.min(this.maxCapacityBytes,n*2);if(n===this.currentCapacityBytes)return;let r=Buffer.alloc(n);this.storage.copy(r,0,0,this.writeCursor),this.storage=r,this.currentCapacityBytes=n}writeRing(e){let t=e.length;if(this.growIfNeeded(t),t>=this.currentCapacityBytes){let o=t-this.currentCapacityBytes;e.copy(this.storage,0,o,t);return}let n=this.writeCursor%this.currentCapacityBytes,r=this.currentCapacityBytes-n;t<=r?e.copy(this.storage,n,0,t):(e.copy(this.storage,n,0,r),e.copy(this.storage,0,r,t))}sliceFromRing(e,t){if(t<=0)return Buffer.alloc(0);let n=Buffer.alloc(t),r=e%this.currentCapacityBytes,o=Math.min(t,this.currentCapacityBytes-r);return this.storage.copy(n,0,r,r+o),o<t&&this.storage.copy(n,o,0,t-o),n}scheduleFileWrite(e){let t=this.filePath;if(t===void 0||this.fileCapReached)return;let n=this.fileCapBytes-this.fileBytesWritten;if(n<=0){this.fileCapReached=!0,this.onFileCapReached?.();return}let r=e.length<=n?e:e.subarray(0,n);this.fileBytesWritten+=r.length;let o=this.fileBytesWritten>=this.fileCapBytes;this.fileWriteChain=this.fileWriteChain.then(()=>ta.appendFile(t,r)).catch(i=>{this.logWriteError?.(i)}),o&&!this.fileCapReached&&(this.fileCapReached=!0,this.onFileCapReached?.())}async drainFileWrites(){await this.fileWriteChain.catch(()=>{})}};var Mt=[{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."}],ek=new Map(Mt.map(s=>[s.verb,s]));function na(s){let e=s.lastIndexOf("/");return(e===-1?s:s.slice(e+1)).toLowerCase()}function _t(s,e){return rn(s,e.map(t=>t.modelId))}function rn(s,e){if(e.length===0)return{kind:"none",requested:s};if(e.includes(s))return{kind:"exact",modelId:s};let t=na(s),n=e.filter(o=>na(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 ra(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=xr(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 of){if(!sa(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=xr(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?(sf(r,o.outIndex,tf(c.content)),nf(r,o.outIndex,d.seq)):(r.push(d),o={outIndex:r.length-1,kind:u});continue}if(o=null,u==="tool_call_update"){let l=typeof c.toolCallId=="string"?c.toolCallId:void 0;if(l!==void 0&&e.get(l)!==a)continue;let p=l!==void 0&&t.has(l)?rf(d,t.get(l)??[]):d,m=l===void 0?void 0:n.get(l);if(m!==void 0)for(let[h,f]of m)sa(xr(p)?.[h])||(p=af(p,h,f));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 xr(s){if(s.method!=="session/update")return;let t=s.params?.update;if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function tf(s){if(!s||typeof s!="object")return"";let e=s;return typeof e.text=="string"?e.text:""}function nf(s,e,t){let n=s[e];n===void 0||typeof t!="number"||n.seq!==void 0&&n.seq>=t||(s[e]={...n,seq:t})}function sf(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 rf(s,e){let t=s.params??{},n=t.update??{};return{...s,params:{...t,update:{...n,content:e}}}}var of=["rawInput","locations"];function sa(s){return s==null||typeof s!="object"?!1:Array.isArray(s)?s.length>0:Object.keys(s).length>0}function af(s,e,t){let n=s.params??{},r=n.update??{};return{...s,params:{...n,update:{...r,[e]:t}}}}var oa=`[older history truncated]
22
+ `,ia=["file_path","filePath","path","command","pattern","query"];function $t(s,e={}){let t=e.maxChars??4e5,n=Er(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=_r(u.prompt).trim();p.length>0&&r.push(`User: ${p}`)}else if(l==="agent_message_chunk"){let p=$r(u.content);p.length>0&&(o+=p)}else if(l==="tool_call"){if(a(),r.push(Mr(u,n)),e.toolOutput!==void 0){let p=Pr(u),m=p!==void 0?n.get(p)?.output:void 0;if(m!==void 0&&i>0){let h=Math.min(e.toolOutput.maxPerCall,i),f=m.length<=h?m:`${m.slice(0,h)}\u2026[${m.length-h} more chars]`;r.push(`Output: ${f}`),i-=Math.min(f.length,h)}}}else l==="turn_complete"&&a()}return a(),gf(r.join(`
23
+ `),t)}function Er(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=Pr(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=cf(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=Vn(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=Tr(t);return e}function Tr(s){return df(s)?s.kind??"(unnamed)":s.name}function df(s){for(let e of ia){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 cf(s,e){let t=on(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 Pr(s){let e=s.toolCallId;if(typeof e=="string"&&e.length>0)return e}function Vn(s){let e=uf(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 uf(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(`
24
+ `)}function on(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 Mr(s,e){let t=Pr(s),n=t!==void 0?e?.get(t):void 0,r=n?.name??lf(s),o=ff(n?.rawInput??s.rawInput);return o.length===0?`Tool: ${r}`:`Tool: ${r}(${o.join(", ")})`}function lf(s){let e=on(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 ff(s){if(!s||typeof s!="object"||Array.isArray(s))return[];let e=s,t=[];for(let n of ia){let r=e[n];typeof r=="string"&&r.length>0&&t.push(`${n}=${pf(r,600)}`)}return t}function _r(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 $r(s){if(!s||typeof s!="object")return"";let e=s.text;return typeof e=="string"?e:""}function pf(s,e){return s.length<=e?s:s.slice(0,e-1)+"\u2026"}function gf(s,e){if(s.length<=e)return s;let t=s.split(`
25
+ `);for(;t.length>0;){let n=oa+t.join(`
26
+ `);if(n.length<=e)return n;t.shift()}return oa}var aa="(untitled)";function Fr(s){let e=[],t=s.synopsis;if(t!==void 0){e.push("--- begin prior session compaction ---"),e.push(`[Title] ${s.title??aa}`),t.goal!==void 0&&t.goal.trim().length>0&&e.push(`[Goal] ${t.goal}`),t.outcome!==void 0&&t.outcome.trim().length>0&&e.push(`[Outcome] ${t.outcome}`);let d=an("Open threads",t.open_threads);d.length>0&&e.push(d);let c=an("Decisions",t.decisions);c.length>0&&e.push(c);let u=an("File edit intentions",t.file_edit_intentions);u.length>0&&e.push(u);let l=an("Unresolved errors",t.unresolved_errors);l.length>0&&e.push(l);let p=an("Tool state",t.tool_state);p.length>0&&e.push(p);let m=da(t.files_touched);m.length>0&&e.push(`[Files previously touched] ${m}`);let h=da(t.tools_used);h.length>0&&e.push(`[Tools previously used] ${h}`),e.push("--- end prior session compaction ---")}else e.push(`[Title] ${s.title??aa}`);s.note!==void 0&&s.note.trim().length>0&&e.push(`[Situation] ${s.note.trim()}`);let{closedText:n,openText:r,keptCount:o}=mf(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(`
27
+ `)}function an(s,e){if(!e||!Array.isArray(e))return"";let t=e.filter(r=>typeof r=="string"&&r.trim().length>0);if(t.length===0)return"";let n=t.map(r=>"- "+r.trim());return`[${s}] ${n.join(`
28
+ `)}`}function da(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 mf(s,e,t,n){if(s.length===0)return{closedText:"",openText:"",keptCount:0};let{closed:r,open:o}=hf(s),i=0,a=[];if(e>0&&r.length>0){let u=r.filter(m=>m.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?ca(a):"",c=o?ca([o]):"";return{closedText:d,openText:c,keptCount:i}}function ca(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(`
29
+ `)}function hf(s){let e=[],t=null,n=Er(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:_r(d.prompt).trim(),agent:"",tools:[],startEntryIndex:o};else if(c==="agent_message_chunk"&&t!==null){let u=$r(d.content);u.length>0&&(t.agent+=u)}else c==="tool_call"&&t!==null?t.tools.push(Mr(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 la(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:yf(a),unknownCount:r.filter(d=>d.reason===void 0&&d.inferredReason===void 0&&!d.notCompaction).length}}function yf(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 wf(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 ua(s){if(s<1e3)return String(s);let e=s/1e3;return e<100?`${e.toFixed(1)}k`:`${Math.round(e)}k`}function kf(s){return s.usedBefore===void 0||s.usedAfter===void 0?"":` ${ua(s.usedBefore)} \u2192 ${ua(s.usedAfter)}`}function fa(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=kf(r),i=r.cost!==void 0?` $${r.cost.toFixed(2)}`:"",a=r.current?" (current)":"",d=r.swaps>1?` (${r.swaps} swaps)`:"";n.push(` ${wf(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 vf(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Or(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(`${vf(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 Nr(s,e){if(e.length===0)return!1;let t=e.endsWith("/")?e.slice(0,-1):e;return s.includes(t)}function pa(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(`
30
+ `)}function ga(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(`
31
+ `)}function ma(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)}Y();import*as Be from"fs/promises";async function dn(s,e){let t=R.queueFile(s);if(e.length===0){await Be.unlink(t).catch(()=>{});return}await Be.mkdir(R.sessionDir(s),{recursive:!0});let n=e.map(r=>JSON.stringify(r)).join(`
32
32
  `)+`
33
- `;await De.writeFile(t,n,"utf8")}async function Ji(s){let e=A.queueFile(s),t;try{t=await De.readFile(e,"utf8")}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t.split(`
34
- `))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 Vi(s){let e=A.queueFile(s);await De.unlink(e).catch(()=>{})}import*as sa from"fs/promises";var ta="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",na=ea(ta,16),kr=ea(ta,16),ql=20,zl=20,Jl=5,Vl=32,He="hydra_session_";function je(){return`m_${na()}`}function qe(s){return s.startsWith(He)?s.slice(He.length):s}var Gi=["start","merge","apply","sync","stop","detach","discard","clean","status"],Gl=1e3,Nn=300*1e3,Kl=64,Ql=new Set(["task-notification","peer","coordinator","observer","observer-activity"]);function Yl(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"&&Ql.has(r)}function Ki(s){let e=s?.update;return!!e&&typeof e=="object"&&e.sessionUpdate==="usage_update"}function Xl(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 Qi=120,Zl=128,ef=new Set(["local_bash"]),tf=1e3,Ct=class s{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=Ne;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;lastSeq=0;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 $n;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??`${He}${na()}`,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??Gl,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){pf(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=Yi(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_${kr()}`,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()))},Nn);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=gf(i);if(d!==null){this.setAgentAdvertisedCommands(d);return}let c=ff(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=this.pendingOneShotBackgroundTasks();if(e.length>0)return`${e.length} background task(s) still running (${e.join(", ")}); a swap would kill the agent process and abandon them. Wait for them to finish, or cancel them, then try again`;let t=await this.openToolCallIdsInHistory();if(t.length>0)return`${t.length} tool call(s) from an earlier turn never reported a result, so the session still reads as busy. ^C closes an abandoned chain; failing that it clears as new history accumulates`}isQuiescedSync(){return!(this.promptInFlight||this.unsolicitedTurn!==void 0||this.modeChangeInFlight||this.modelChangeInFlight)}async swapIntoWorkspace(e){await this.swapUpstream({...e.synopsis!==void 0?{artifact:e.synopsis}:{},note:e.note,framing:"swap",...e.title!==void 0?{title:e.title}:{},tailK:8,tailFloor:4,summarizedThroughEntry:e.historyLength,newCwd:e.cwd,reason:e.workspace!==void 0?"workspace-enter":"workspace-leave"}),this.workspace=e.workspace,e.left!==void 0?(this.formerWorkspace={path:e.left.path,sourceCwd:e.cwd,removed:e.left.removed},this.departureNoteSent=!1):this.formerWorkspace=void 0}async swapUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for swap: ${t}`);if(this.swapInFlight)throw new Error("a swap is already in progress for this session");this.swapInFlight=!0;try{await this.doSwapUpstream(e)}finally{this.swapInFlight=!1}}async doSwapUpstream(e){this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let t=this.agentId,n=e.newAgentId??this.agentId,r=n!==this.agentId,o=e.reason!==void 0&&e.reason!=="compaction"?e.reason:r?"agent-swap":"compaction",i=e.newCwd??this.cwd,a=this.agentArgs,d=this.forwardedEnv,c=this.currentModel,u=this.currentMode,l=this.spawnReplacementAgent;if(!l)throw new Error("agent spawning not configured for this session");let p=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],f=await l({agentId:n,cwd:i,agentArgs:a,...d?{forwardedEnv:d}:{},mcpServers:p});if(this.accumulateAndResetCost(),this.cwd=i,this.wireAgent(f.agent,{respawn:!0}),!r){let T=await ot({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedModel:c,agentReportedModel:f.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(T.result,"model"),await rt({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=hr({...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?`
35
- Stopped ${I.length} background task(s) with the previous agent: ${I.join(", ")}. Re-arm anything still needed.
36
- `:"",R=(e.reason==="workspace-enter"||e.reason==="workspace-leave"?"":r?`
33
+ `;await Be.writeFile(t,n,"utf8")}async function ha(s){let e=R.queueFile(s),t;try{t=await Be.readFile(e,"utf8")}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t.split(`
34
+ `))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 ya(s){let e=R.queueFile(s);await Be.unlink(e).catch(()=>{})}import*as xa from"fs/promises";var Ca="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Ra=Aa(Ca,16),Dr=Aa(Ca,16),bf=20,Sf=20,If=5,Af=32,qe="hydra_session_";function We(){return`m_${Ra()}`}function Ke(s){let e=pt(s)?.localId??s;return e.startsWith(qe)?e.slice(qe.length):e}var wa=["start","merge","apply","sync","stop","detach","discard","clean","status"],Cf=1e3,Gn=300*1e3,Rf=64,xf=new Set(["task-notification","peer","coordinator","observer","observer-activity"]);function Ef(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"&&xf.has(r)}function ka(s){let e=s?.update;return!!e&&typeof e=="object"&&e.sessionUpdate==="usage_update"}function Tf(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 va=120,Pf=128,Mf=new Set(["local_bash"]),_f=1e3,Ft=class s{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=Ue;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;lastSeq=0;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 zn;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??`${qe}${Ra()}`,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??Cf,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){Wf(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=ba(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_${Dr()}`,m;try{m=await l.connection.request("hydra-acp/transformer/message",{token:p,phase:"response",method:r,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(f){this.logger?.warn(`transformer ${l.name} error on ${a}: ${f.message}`);continue}let h=m?.action??"continue";if(h==="stop")return;if(h==="processing"){let f=u,g=i,w=new Set(t),y=r;await new Promise(k=>{let b=setTimeout(()=>{this.pendingClaims.delete(p)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:p,transformerName:l.name}),this.runResponseChain(g,new Set([...w,l.name]),f+1,y).then(()=>k()).catch(()=>k()))},Gn);typeof b.unref=="function"&&b.unref(),this.pendingClaims.set(p,{resolve:()=>k(),timer:b,transformerName:l.name,method:y,envelope:g,chainIdx:f,originatedBy:w,side:"response"})});return}m?.payload&&typeof m.payload=="object"&&(i=m.payload),t.add(l.name)}if(r!=="session/update")return;this.noteAgentActivity(i);let d=qf(i);if(d!==null){this.setAgentAdvertisedCommands(d);return}let c=Bf(i);if(c!==null){this.setAgentAdvertisedModes(c);return}if(this.noteModelVerbHint(Yi(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=this.pendingOneShotBackgroundTasks();if(e.length>0)return`${e.length} background task(s) still running (${e.join(", ")}); a swap would kill the agent process and abandon them. Wait for them to finish, or cancel them, then try again`;let t=await this.openToolCallIdsInHistory();if(t.length>0)return`${t.length} tool call(s) from an earlier turn never reported a result, so the session still reads as busy. ^C closes an abandoned chain; failing that it clears as new history accumulates`}isQuiescedSync(){return!(this.promptInFlight||this.unsolicitedTurn!==void 0||this.modeChangeInFlight||this.modelChangeInFlight)}async swapIntoWorkspace(e){await this.swapUpstream({...e.synopsis!==void 0?{artifact:e.synopsis}:{},note:e.note,framing:"swap",...e.title!==void 0?{title:e.title}:{},tailK:8,tailFloor:4,summarizedThroughEntry:e.historyLength,newCwd:e.cwd,reason:e.workspace!==void 0?"workspace-enter":"workspace-leave"}),this.workspace=e.workspace,e.left!==void 0?(this.formerWorkspace={path:e.left.path,sourceCwd:e.cwd,removed:e.left.removed},this.departureNoteSent=!1):this.formerWorkspace=void 0}async swapUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for swap: ${t}`);if(this.swapInFlight)throw new Error("a swap is already in progress for this session");this.swapInFlight=!0;try{await this.doSwapUpstream(e)}finally{this.swapInFlight=!1}}async doSwapUpstream(e){this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let t=this.agentId,n=e.newAgentId??this.agentId,r=n!==this.agentId,o=e.reason!==void 0&&e.reason!=="compaction"?e.reason:r?"agent-swap":"compaction",i=e.newCwd??this.cwd,a=this.agentArgs,d=this.forwardedEnv,c=this.currentModel,u=this.currentMode,l=this.spawnReplacementAgent;if(!l)throw new Error("agent spawning not configured for this session");let p=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],m=await l({agentId:n,cwd:i,agentArgs:a,...d?{forwardedEnv:d}:{},mcpServers:p});if(this.accumulateAndResetCost(),this.cwd=i,this.wireAgent(m.agent,{respawn:!0}),!r){let M=await ft({agent:m.agent,upstreamSessionId:m.upstreamSessionId,persistedModel:c,agentReportedModel:m.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(M.result,"model"),await lt({agent:m.agent,upstreamSessionId:m.upstreamSessionId,persistedMode:u,agentReportedMode:m.initialMode,logger:this.logger})}m.agent.connection.drainBuffered("session/update");let h=[];if(this.historyStore)try{h=await this.historyStore.load(this.sessionId)}catch(M){this.logger?.warn(`swapUpstream: historyStore.load failed: ${M.message}`)}let f=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:h,tailK:e.tailK,tailFloor:e.tailFloor,...e.summarizedThroughEntry!==void 0?{watermark:e.summarizedThroughEntry}:{},recallArmed:(e.summarizedThroughEntry??this._summarizedThroughEntry??0)>0});if(this.internalPromptCapture)throw new Error("swapUpstream: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};let g,w;try{await m.agent.connection.request("session/prompt",{sessionId:m.upstreamSessionId,prompt:[{type:"text",text:f}]});let M=this.internalPromptCapture;g=M.lastUsed,w=M.lastSize,this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${f.length} toolCalls=${M.toolCalls} thinkingChars=${M.thinkingChars} messageChars=${M.messageChars} used=${M.lastUsed??"?"} size=${M.lastSize??"?"} reply=${JSON.stringify(M.chunks.join("").slice(0,200))}`)}finally{this.internalPromptCapture=void 0}g!==void 0&&(this.maybeApplyAgentUsage({update:{sessionUpdate:"usage_update",used:g,...w!==void 0?{size:w}:{}}}),this.broadcastCurrentUsage());let y=this.upstreamSessionId,k=this._summarizedThroughEntry;e.summarizedThroughEntry!==void 0&&(this._summarizedThroughEntry=e.summarizedThroughEntry);let b=this.agent;if(this.agent=m.agent,this.upstreamSessionId=m.upstreamSessionId,this.agentMeta=m.agentMeta,this.agentCapabilities=m.agentCapabilities,this.resetModelVerb(m.modelVerb),r&&(this.agentId=n,this.agentAdvertisedCommands=[],this.currentModel=m.initialModel,this.currentMode=m.initialMode,this.setAgentAdvertisedModels(m.initialModels??[]),this.setAgentAdvertisedModes(m.initialModes??[]),this.agentAdvertisedConfigOptions=m.initialConfigOptions??[]),this.broadcastMergedCommands(),this.broadcastConfigOptions(),this.notifyAgentChange("swapUpstream",o,e.runId,g),e.summarizedThroughEntry!==void 0&&this.persistWatermarkHook)try{this.persistWatermarkHook(e.summarizedThroughEntry)}catch(M){this.logger?.warn(`swapUpstream: persistWatermarkHook failed: ${M.message}`)}if(!r&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:y,...k!==void 0?{previousSummarizedThroughEntry:k}:{},...e.runId!==void 0?{runId:e.runId}:{}})}catch(M){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${M.message}`)}let S=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:y,upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}),r||this.broadcastCompactionPhase({phase:"swapped",...this.title!==void 0?{title:this.title}:{},summarizedThroughEntry:e.summarizedThroughEntry??this._summarizedThroughEntry??0}),r&&this.broadcastAgentSwitch(t,n);let v=S.length>0?`
35
+ Stopped ${S.length} background task(s) with the previous agent: ${S.join(", ")}. Re-arm anything still needed.
36
+ `:"",C=(e.reason==="workspace-enter"||e.reason==="workspace-leave"?"":r?`
37
37
  Switched to ${n}.
38
38
  `:`
39
39
  Compaction completed.
40
- `)+v,M=R===""?void 0:R;if(M!==void 0){let T=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:M},_meta:{"hydra-acp":{synthetic:!0}}}});for(let D of this.clients.values())D.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 ot({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedModel:d,agentReportedModel:u.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(l.result,"model"),await rt({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 ot({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:t,agentReportedModel:r.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(o.result,"model"),await rt({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=ql){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",t){return this.historyStore?this.historyStore.load(this.sessionId,{tools:e,...t!==void 0?{maxEntries:t}:{}}).catch(()=>[]):[]}async*iterRecallNewestFirst(){this.historyStore&&(yield*this.historyStore.iterRecallNewestFirst(this.sessionId))}async getRecallTotalCount(){return this.historyStore?this.historyStore.getRecallTotalCount(this.sessionId).catch(()=>0):0}async sliceRecallHistory(e,t){return this.historyStore?(await this.historyStore.rangeSlice(this.sessionId,e,t).catch(()=>[])).map(r=>r.entry):[]}onBroadcast(e){return this.broadcastHandlers.push(e),()=>{let t=this.broadcastHandlers.indexOf(e);t>=0&&this.broadcastHandlers.splice(t,1)}}broadcastClientUpdate(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:e});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}broadcastCompactionPhase(e){let t=e.phase;t==="swapped"||t==="failed"||t==="rolled_back"?this._liveCompactionPhase=void 0:this._liveCompactionPhase=e;let n=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_compaction",...e}});for(let r of this.broadcastHandlers)try{r({method:"session/update",params:n,recordedAt:Date.now()})}catch{}for(let r of this.clients.values())r.connection.notify("session/update",n).catch(()=>{});this.notifyChain("compaction",{...e})}broadcastWorkspacePhase(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_workspace",...e}});for(let n of this.broadcastHandlers)try{n({method:"session/update",params:t,recordedAt:Date.now()})}catch{}for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{});this.notifyChain("workspace",{...e})}broadcastSyntheticText(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:e},_meta:{"hydra-acp":{synthetic:!0}}}});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}attach(e,t,n={}){if(this.closed)throw ye(new Error("session is closed"),C.SessionNotFound);if(this.clients.has(e.clientId))throw ye(new Error(`client ${e.clientId} is already attached`),C.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=d=>t.raw?d:Oi(d),r=t.historyLimit===0?1/0:t.historyLimit??this.historyMaxEntries,o=await this.getHistorySnapshot(t.toolContent??"inline",r===1/0?1/0:r*2),i=hf(o.filter(d=>!vr(d.method,d.params)),r),a=this.buildStateSnapshotReplay();if(e==="after_message"){let d=t.afterSeq!==void 0?yf(i,t.afterSeq):t.afterMessageId?jn(i,t.afterMessageId):-1;return d<0?{entries:[...a,...n(i)],appliedPolicy:"full"}:{entries:[...a,...n(i.slice(d+1))],appliedPolicy:"after_message"}}return{entries:[...a,...n(i)],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}zi(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=Xi(e,o=>wr(o,t.path)?(n=!0,yr(o,t.path,t.sourceCwd).text):o);if(!this.departureNoteSent||n){let o=Wi({sourceCwd:t.sourceCwd,formerWorkspacePath:t.path,removed:t.removed});r=br(r,`${o}
40
+ `)+v,T=C===""?void 0:C;if(T!==void 0){let M=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:T},_meta:{"hydra-acp":{synthetic:!0}}}});for(let H of this.clients.values())H.connection.notify("session/update",M).catch(()=>{})}this.updatedAt=Date.now()}async rollbackToUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for rollback: ${t}`);let n=this.loadExistingAgentSession;if(!n)throw new Error("loadExistingAgentSession not configured for this session");let r=this.agentId,o=this.cwd,i=this.agentArgs,a=this.forwardedEnv,d=this.currentModel,c=this.currentMode,u=await n(e.previousUpstreamSessionId,{agentId:r,cwd:o,agentArgs:i,...a?{forwardedEnv:a}:{},mcpServers:this.mcpServersConfig??[]});this.accumulateAndResetCost(),this.wireAgent(u.agent,{respawn:!0});let l=await ft({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedModel:d,agentReportedModel:u.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(l.result,"model"),await lt({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedMode:c,agentReportedMode:u.initialMode,logger:this.logger}),u.agent.connection.drainBuffered("session/update");let p=this.agent;this.agent=u.agent,this.upstreamSessionId=u.upstreamSessionId,this.agentMeta=u.agentMeta,this.agentCapabilities=u.agentCapabilities,this.resetModelVerb(u.modelVerb),this.broadcastMergedCommands(),this.broadcastConfigOptions(),await this.retireAgent(p,"rollback"),this._summarizedThroughEntry=e.previousSummarizedThroughEntry,this.broadcastCompactionPhase({phase:"rolled_back",summarizedThroughEntry:e.previousSummarizedThroughEntry??0}),this.notifyAgentChange("rollbackToUpstream","rollback"),this.updatedAt=Date.now()}async reloadUpstreamAfterAgentLoss(){let e=this.loadExistingAgentSession;if(!e)throw new Error("loadExistingAgentSession not configured for this session");let t=this.currentModel,n=this.currentMode,r=await e(this.upstreamSessionId,{agentId:this.agentId,cwd:this.cwd,agentArgs:this.agentArgs,...this.forwardedEnv?{forwardedEnv:this.forwardedEnv}:{},mcpServers:this.mcpServersConfig??[]});this.accumulateAndResetCost(),this.wireAgent(r.agent,{respawn:!0});let o=await ft({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:t,agentReportedModel:r.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(o.result,"model"),await lt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedMode:n,agentReportedMode:r.initialMode,logger:this.logger}),r.agent.connection.drainBuffered("session/update");let i=this.agent;this.agent=r.agent,this.upstreamSessionId=r.upstreamSessionId,this.agentMeta=r.agentMeta,this.agentCapabilities=r.agentCapabilities,this.resetModelVerb(r.modelVerb),this.broadcastMergedCommands(),this.broadcastConfigOptions(),await this.retireAgent(i,"upstream-lost"),this.notifyAgentChange("reloadUpstreamAfterAgentLoss"),this.updatedAt=Date.now()}async openToolCallIdsInHistory(e=bf){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",t){return this.historyStore?this.historyStore.load(this.sessionId,{tools:e,...t!==void 0?{maxEntries:t}:{}}).catch(()=>[]):[]}async*iterRecallNewestFirst(){this.historyStore&&(yield*this.historyStore.iterRecallNewestFirst(this.sessionId))}async getRecallTotalCount(){return this.historyStore?this.historyStore.getRecallTotalCount(this.sessionId).catch(()=>0):0}async sliceRecallHistory(e,t){return this.historyStore?(await this.historyStore.rangeSlice(this.sessionId,e,t).catch(()=>[])).map(r=>r.entry):[]}onBroadcast(e){return this.broadcastHandlers.push(e),()=>{let t=this.broadcastHandlers.indexOf(e);t>=0&&this.broadcastHandlers.splice(t,1)}}broadcastClientUpdate(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:e});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}broadcastCompactionPhase(e){let t=e.phase;t==="swapped"||t==="failed"||t==="rolled_back"?this._liveCompactionPhase=void 0:this._liveCompactionPhase=e;let n=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_compaction",...e}});for(let r of this.broadcastHandlers)try{r({method:"session/update",params:n,recordedAt:Date.now()})}catch{}for(let r of this.clients.values())r.connection.notify("session/update",n).catch(()=>{});this.notifyChain("compaction",{...e})}broadcastWorkspacePhase(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_workspace",...e}});for(let n of this.broadcastHandlers)try{n({method:"session/update",params:t,recordedAt:Date.now()})}catch{}for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{});this.notifyChain("workspace",{...e})}broadcastSyntheticText(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:e},_meta:{"hydra-acp":{synthetic:!0}}}});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}attach(e,t,n={}){if(this.closed)throw be(new Error("session is closed"),x.SessionNotFound);if(this.clients.has(e.clientId))throw be(new Error(`client ${e.clientId} is already attached`),x.AlreadyAttached);return this.clients.set(e.clientId,e),this.cancelOrphanTimer(),this.updatedAt=Date.now(),t==="none"?Promise.resolve({entries:[],appliedPolicy:t}):t==="pending_only"?Promise.resolve({entries:this.buildStateSnapshotReplay(),appliedPolicy:t}):this.loadReplay(t,n)}async loadReplay(e,t){let n=d=>t.raw?d:ra(d),r=t.historyLimit===0?1/0:t.historyLimit??this.historyMaxEntries,o=await this.getHistorySnapshot(t.toolContent??"inline",r===1/0?1/0:r*2),i=Jf(o.filter(d=>!jr(d.method,d.params)),r),a=this.buildStateSnapshotReplay();if(e==="after_message"){let d=t.afterSeq!==void 0?Vf(i,t.afterSeq):t.afterMessageId?Qn(i,t.afterMessageId):-1;return d<0?{entries:[...a,...n(i)],appliedPolicy:"full"}:{entries:[...a,...n(i.slice(d+1))],appliedPolicy:"after_message"}}return{entries:[...a,...n(i)],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}ma(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=Sa(e,o=>Nr(o,t.path)?(n=!0,Or(o,t.path,t.sourceCwd).text):o);if(!this.departureNoteSent||n){let o=pa({sourceCwd:t.sourceCwd,formerWorkspacePath:t.path,removed:t.removed});r=Hr(r,`${o}
41
41
 
42
- `),this.departureNoteSent=!0}return r}applyWorkspacePromptRewrite(e){let t=this.workspace;if(t===void 0)return this.applyDepartedPromptRewrite(e);let n=!1,r=Xi(e,i=>wr(i,t.sourceCwd)?(n=!0,yr(i,t.sourceCwd,t.path).text):i);if(!this.workspacePreambleSent||n){let i=qi({workspacePath:t.path,sourceCwd:t.sourceCwd,notes:this.workspaceNotes,...this.workspacePreambleSent?{reassert:!0}:{}});r=br(r,`${i}
42
+ `),this.departureNoteSent=!0}return r}applyWorkspacePromptRewrite(e){let t=this.workspace;if(t===void 0)return this.applyDepartedPromptRewrite(e);let n=!1,r=Sa(e,i=>Nr(i,t.sourceCwd)?(n=!0,Or(i,t.sourceCwd,t.path).text):i);if(!this.workspacePreambleSent||n){let i=ga({workspacePath:t.path,sourceCwd:t.sourceCwd,notes:this.workspaceNotes,...this.workspacePreambleSent?{reassert:!0}:{}});r=Hr(r,`${i}
43
43
 
44
- `),this.workspacePreambleSent=!0}return r}async prompt(e,t,n,r){let o=this.clients.get(e);if(!o)throw ye(new Error("client not attached"),C.SessionNotFound);if(this.closing)throw ye(new Error("session is closing; new prompts cannot be accepted"),C.SessionClosing);let i=je();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(st((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=it(e.prompt);n.length>0&&this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"user_message_chunk",content:{type:"text",text:n},_meta:{"hydra-acp":{compatFor:"prompt_received"}}}},e.clientId)}recordCurrentUsageSnapshot(){if(this.historyStore===void 0)return;let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let r={};typeof e.costAmount=="number"&&(r.amount=e.costAmount),typeof e.costCurrency=="string"&&(r.currency=e.costCurrency),t.cost=r}if(Object.keys(t).length<=1)return;t._meta={"hydra-acp":{upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}};let n={sessionId:this.sessionId,update:t};this.historyStore.append(this.sessionId,{method:"session/update",params:n,recordedAt:Date.now()}).catch(()=>{})}originatorNeedsTurnComplete(e){return e.wasAmend===!0||e.wasSteer===!0}broadcastTurnComplete(e,t,n,r){let o=t&&typeof t=="object"&&"stopReason"in t&&typeof t.stopReason=="string"?t.stopReason:void 0,i={sessionUpdate:"turn_complete",messageId:je()};o!==void 0&&(i.stopReason=o);let a=st(t?._meta).salvaged;a!==void 0&&(i._meta={[re]:{salvaged:a}}),this.supersededAutonomousTurn=void 0;let d=this.amendInProgress;if(d&&n!==void 0&&d.cancelledMessageId===n&&(i._meta={[re]:{...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),dr(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(Yl(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&&Ki(e)&&(this.pendingSteerDetach=void 0),!vr("session/update",e)&&(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||this.openUnsolicitedTurn()))}}steerCausedTurnTerminal(e){return this.unsolicitedTurn?.steerCaused!==!0?!1:Ki(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=df(t._meta);this.rememberToolLabel(n,t,r,o),this.noteBackgroundTaskStopped(t,r,o);let i=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:af(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=of(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}))}pendingOneShotBackgroundTasks(){return this.sawBackgroundTaskLevel?[...this.liveBackgroundTasks.values()].filter(e=>ef.has(e.taskType)).map(e=>e.description||e.taskType):[...this.armedTasks.values()].filter(e=>!e.repeating).map(e=>e.label)}get armedSince(){let e;if(this.sawBackgroundTaskLevel){for(let t of this.liveBackgroundTasks.values())(e===void 0||t.firstSeen<e)&&(e=t.firstSeen);return e}for(let t of this.armedTasks.values())(e===void 0||t.armedAt<e)&&(e=t.armedAt);return e}onArmedTasksChanged(){let e=this.armedBackgroundTasks,t=e.length,n=this.armedSince,r=e.map(o=>o.taskId??o.toolCallId??o.label).sort().join("\0");r===this.lastArmedBroadcast?.key&&n===this.lastArmedBroadcast?.since||this.closed||(this.lastArmedBroadcast={key:r,since:n},this.broadcastQueueNotification("hydra-acp/session/armed_tasks_updated",{sessionId:this.sessionId,count:t,...n!==void 0?{since:n}:{},tasks:e}),this.dispatchIdle())}async retireAgent(e,t){return await e.kill().catch(()=>{}),this.resetBackgroundTaskLevel(),this.discardArmedTasks(t)}resetBackgroundTaskLevel(){this.liveBackgroundTasks.clear(),this.sawBackgroundTaskLevel=!1}discardArmedTasks(e){if(this.armedTasks.size===0)return[];let t=[...this.armedTasks.values()].map(n=>n.label);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,Qi),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,Qi),fromDescription:!1})}for(;this.toolLabels.size>Zl;){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:je(),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,tf);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:je(),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:{[re]:{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>Kl;){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>Vl;){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 ye(new Error("client not attached"),C.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=je(),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 ye(new Error("client not attached"),C.SessionNotFound);let r=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled;if(r&&this.agent.steeringSupported){this.pendingSteerDetach={messageId:this.currentEntry.messageId};let o;try{o=await this.forwardRequest("_session/steering",t)}catch(d){throw this.pendingSteerDetach=void 0,d}let i=o?.outcome,a=i==="injected"||i==="startedNewTurn"||i==="promptRequired"||i==="failed"?o:{outcome:"failed"};return a.outcome!=="startedNewTurn"&&(this.pendingSteerDetach=void 0),a.outcome==="injected"&&this.recordSteerAsUserMessageChunk(t.prompt,e),a.outcome==="startedNewTurn"?{...a,detached:!0}:a}return r?(this.amendOnHead(n,t.prompt,this.currentEntry.messageId,!1),{outcome:"startedNewTurn"}):t._meta?.steering?.idleBehavior==="promptRequired"?{outcome:"promptRequired",reason:"noRunningTurn"}:(this.prompt(e,{sessionId:t.sessionId,prompt:t.prompt},void 0,{steerOriginated:!0}).catch(o=>{this.logger?.warn(`steer-originated prompt failed to enqueue: ${o.message}`)}),{outcome:"startedNewTurn"})}recordSteerAsUserMessageChunk(e,t){let n=it(e);n.length!==0&&this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"user_message_chunk",content:{type:"text",text:n},_meta:{"hydra-acp":{steered:!0}}}},t)}enqueueAmendmentAsFollowUp(e,t){let n=je(),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 ye(new Error("client not attached"),C.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_${kr()}`,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??Sr(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:Sr(e))))},Nn);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 Xe({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??Ne,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_${kr()}`,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??Sf(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})))},Nn);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):Nn,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:Sr(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=je(),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||st((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let r=it((e??{}).prompt),o=Ar(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=Zt(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(Xl(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=Zt(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=Dn(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=Ir(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(cf(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(uf(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(",")}]`),lf(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 St){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 St)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(St.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=C.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=St.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=C.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
+ `),this.workspacePreambleSent=!0}return r}async prompt(e,t,n,r){let o=this.clients.get(e);if(!o)throw be(new Error("client not attached"),x.SessionNotFound);if(this.closing)throw be(new Error("session is closing; new prompts cannot be accepted"),x.SessionClosing);let i=We();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(ut((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=gt(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:We()};o!==void 0&&(i.stopReason=o);let a=ut(t?._meta).salvaged;a!==void 0&&(i._meta={[ae]:{salvaged:a}}),this.supersededAutonomousTurn=void 0;let d=this.amendInProgress;if(d&&n!==void 0&&d.cancelledMessageId===n&&(i._meta={[ae]:{...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),Rr(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(Ef(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&&ka(e)&&(this.pendingSteerDetach=void 0),!jr("session/update",e)&&(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||this.openUnsolicitedTurn()))}}steerCausedTurnTerminal(e){return this.unsolicitedTurn?.steerCaused!==!0?!1:ka(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=jf(t._meta);this.rememberToolLabel(n,t,r,o),this.noteBackgroundTaskStopped(t,r,o);let i=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:Df(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=Nf(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}))}pendingOneShotBackgroundTasks(){return this.sawBackgroundTaskLevel?[...this.liveBackgroundTasks.values()].filter(e=>Mf.has(e.taskType)).map(e=>e.description||e.taskType):[...this.armedTasks.values()].filter(e=>!e.repeating).map(e=>e.label)}get armedSince(){let e;if(this.sawBackgroundTaskLevel){for(let t of this.liveBackgroundTasks.values())(e===void 0||t.firstSeen<e)&&(e=t.firstSeen);return e}for(let t of this.armedTasks.values())(e===void 0||t.armedAt<e)&&(e=t.armedAt);return e}onArmedTasksChanged(){let e=this.armedBackgroundTasks,t=e.length,n=this.armedSince,r=e.map(o=>o.taskId??o.toolCallId??o.label).sort().join("\0");r===this.lastArmedBroadcast?.key&&n===this.lastArmedBroadcast?.since||this.closed||(this.lastArmedBroadcast={key:r,since:n},this.broadcastQueueNotification("hydra-acp/session/armed_tasks_updated",{sessionId:this.sessionId,count:t,...n!==void 0?{since:n}:{},tasks:e}),this.dispatchIdle())}async retireAgent(e,t){return await e.kill().catch(()=>{}),this.resetBackgroundTaskLevel(),this.discardArmedTasks(t)}resetBackgroundTaskLevel(){this.liveBackgroundTasks.clear(),this.sawBackgroundTaskLevel=!1}discardArmedTasks(e){if(this.armedTasks.size===0)return[];let t=[...this.armedTasks.values()].map(n=>n.label);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,va),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,va),fromDescription:!1})}for(;this.toolLabels.size>Pf;){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:We(),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,_f);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:We(),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:{[ae]:{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>Rf;){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>Af;){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 be(new Error("client not attached"),x.SessionNotFound);let{targetMessageId:r,prompt:o,replaceQueue:i,onTargetCompleted:a}=t;if(this.currentEntry?.messageId===r&&this.currentEntry.kind==="user"&&!this.currentEntry.cancelled&&this.amendInProgress===void 0)return this.amendOnHead(n,o,r,i);let d=this.promptQueue.find(u=>u.messageId===r&&u.kind==="user");if(d&&d.kind==="user"&&!d.cancelled)return d.prompt=o,this.broadcastQueueUpdated(r,o),this.persistRewrite(),{amended:!0,reason:"ok",messageId:r};let c=this.recentlyTerminal.get(r);return c?c.stopReason==="cancelled"?{amended:!1,reason:"target_cancelled"}:a==="send_anyway"?{amended:!1,reason:"target_completed",messageId:this.enqueueAmendmentAsFollowUp(n,o)}:{amended:!1,reason:"target_completed"}:{amended:!1,reason:"target_not_found"}}amendOnHead(e,t,n,r){let o=We(),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 be(new Error("client not attached"),x.SessionNotFound);let r=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled;if(r&&this.agent.steeringSupported){this.pendingSteerDetach={messageId:this.currentEntry.messageId};let o;try{o=await this.forwardRequest("_session/steering",t)}catch(d){throw this.pendingSteerDetach=void 0,d}let i=o?.outcome,a=i==="injected"||i==="startedNewTurn"||i==="promptRequired"||i==="failed"?o:{outcome:"failed"};return a.outcome!=="startedNewTurn"&&(this.pendingSteerDetach=void 0),a.outcome==="injected"&&this.recordSteerAsUserMessageChunk(t.prompt,e),a.outcome==="startedNewTurn"?{...a,detached:!0}:a}return r?(this.amendOnHead(n,t.prompt,this.currentEntry.messageId,!1),{outcome:"startedNewTurn"}):t._meta?.steering?.idleBehavior==="promptRequired"?{outcome:"promptRequired",reason:"noRunningTurn"}:(this.prompt(e,{sessionId:t.sessionId,prompt:t.prompt},void 0,{steerOriginated:!0}).catch(o=>{this.logger?.warn(`steer-originated prompt failed to enqueue: ${o.message}`)}),{outcome:"startedNewTurn"})}recordSteerAsUserMessageChunk(e,t){let n=gt(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=We(),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 be(new Error("client not attached"),x.SessionNotFound);this.logger?.info(`session ${this.sessionId} session/cancel from ${e} promptInFlight=${this.promptInFlight} agentTurnInFlight=${this.agentTurnInFlight} unsolicitedTurn=${this.unsolicitedTurn!==void 0} queued=${this.promptQueue.length}`),this.lastCancelAt=Date.now(),this.currentEntry?.kind==="user"&&this.currentEntry.messageId!==void 0&&this.cancelExtensionDispatch(this.currentEntry.messageId,"cancelled"),this.closeUnsolicitedTurn("cancelled"),this.agentTurnInFlight||this.closeOpenToolCalls("cancelled"),await this.forwardRequest("session/cancel",{sessionId:this.sessionId},new Set,0,"notification")}addTransformer(e){let t=this.transformChain.findIndex(n=>n.name===e.name);t>=0?this.transformChain[t]=e:this.transformChain.push(e),e.intercepts.has("lifecycle:session.opened")&&e.connection.notify("hydra-acp/transformer/session_event",{event:"session.opened",sessionId:this.sessionId}).catch(()=>{})}async forwardRequest(e,t,n=new Set,r=0,o="request"){let i=this.rewriteForAgent(t);for(let a=r;a<this.transformChain.length;a++){let d=this.transformChain[a];if(n.has(d.name))continue;let c=`request:${e}`;if(!d.intercepts.has(c))continue;let u=`t_${Dr()}`,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(m){this.logger?.warn(`transformer ${d.name} error on ${c}: ${m.message}`);continue}let p=l?.action??"continue";if(p==="stop")return o==="notification"?void 0:l?.payload??Lr(e);if(p==="continue"){l?.payload&&typeof l.payload=="object"&&(i=l.payload),n.add(d.name);continue}if(p==="processing"){let m=a,h=i,f=new Set(n);return new Promise(g=>{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,h,new Set([...f,d.name]),m+1,o).then(g).catch(()=>g(o==="notification"?void 0:Lr(e))))},Gn);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(u,{resolve:g,timer:w,transformerName:d.name,method:e,envelope:h,chainIdx:m,originatedBy:f,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 rt({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??Ue,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_${Dr()}`,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??Xf(e)};if(l==="continue"){u?.payload&&typeof u.payload=="object"&&(o=u.payload),n.add(d.name);continue}if(l==="processing"){let p=a,m=o,h=new Set(n),f=e;return new Promise(g=>{let w=setTimeout(()=>{this.pendingClaims.delete(c)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:c,transformerName:d.name}),this.runAgentRequestChain(f,m,new Set([...h,d.name]),p+1).then(g).catch(()=>g({shortCircuit:!1,envelope:m})))},Gn);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(c,{resolve:y=>g({shortCircuit:!0,payload:y}),timer:w,transformerName:d.name,method:f,envelope:m,chainIdx:p,originatedBy:h,side:"agent-request"})})}n.add(d.name)}return{shortCircuit:!1,envelope:o}}dischargeClaim(e,t){let n=this.pendingClaims.get(e);return n?(clearTimeout(n.timer),this.pendingClaims.delete(e),n.resolve(t),!0):!1}keepAliveClaim(e,t){let n=this.pendingClaims.get(e);if(!n)return!1;clearTimeout(n.timer);let r=typeof t=="number"&&t>0?Math.min(t*1.5,1800*1e3):Gn,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:Lr(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=We(),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||ut((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let r=gt((e??{}).prompt),o=Br(r,200);!o||o.startsWith("/")||(this._titleSeedPending=!1,this.setTitle(o))}maybeApplyAgentModel(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="_hydra_current_model_update")return!1;let r=cn(n.availableModels);r.length>0&&this.setAgentAdvertisedModels(r);let o=typeof n.currentModel=="string"?n.currentModel:typeof n.model=="string"?n.model:void 0;if(o===void 0)return!0;let i=o.trim();if(!i||i===this.currentModel)return!0;this.logger?.info(`live current_model_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(i)}`),this.currentModel=i;for(let a of this.modelHandlers)try{a(i)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentConfigOption(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="config_option_update")return!1;let r=n.configOptions;if(!Array.isArray(r))return!0;for(let i of r)this.applyOneConfigOptionEntry(i);let o=new Set(r.filter(i=>!!i&&typeof i=="object").map(i=>typeof i.id=="string"?i.id.trim():void 0).filter(i=>!!i&&i!=="model"&&i!=="mode"&&i!=="agent"));return this.agentAdvertisedConfigOptions=this.agentAdvertisedConfigOptions.filter(i=>o.has(i.id)),!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(Tf(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 f=cn(t.options);f.length>0&&this.setAgentAdvertisedModels(f);let g=t.currentValue;if(typeof g=="string"){let w=g.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 f=Kn(t.options);f.length>0&&this.setAgentAdvertisedModes(f);let g=t.currentValue;if(typeof g=="string"){let w=g.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=Ur(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,m={id:n,name:i,category:d,type:"select",currentValue:p,options:r,...u?{description:u}:{}},h=this.agentAdvertisedConfigOptions.findIndex(f=>f.id===n);h>=0?this.agentAdvertisedConfigOptions[h]=m:this.agentAdvertisedConfigOptions.push(m)}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(Hf(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(Lf(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(",")}]`),Uf(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 Mt){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 Mt)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(Mt.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=x.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=Mt.map(l=>l.verb);if(this.extensionCommands){let l=new Set;for(let{name:p}of this.extensionCommands.list())l.has(p)||(c.push(p),l.add(p))}let u=new Error(`unknown /hydra verb: ${o} (known: ${c.join(", ")})`);throw u.code=x.InvalidParams,u}runExtensionCommand(e,t){return this.enqueuePrompt(`extension:${e}`,()=>this.runExtensionCommandInline(e,t,void 0))}async runExtensionCommandInline(e,t,n){let r=this.extensionCommands?.get(e);if(!r)return this.emitExtensionReply(`extension "${e}" is no longer connected`);let o=t.match(/^(\S+)(?:\s+([\s\S]*))?$/),i=o?.[1]??"",a=(o?.[2]??"").trim();if(!r.commands.some(h=>h.verb===i)){let h=r.commands.map(f=>f.verb).join(", ");return this.emitExtensionReply(`/hydra ${e}${i?` ${i}`:""}: unknown verb (known: ${h||"(none)"})`)}let d={sessionId:this.sessionId,verb:i,args:a};n!==void 0&&(d.messageId=n);let c=()=>{},u=new Promise(h=>{c=h});n!==void 0&&this.inFlightExtensionDispatches.set(n,{extensionName:e,connection:r.connection,cancel:h=>c({stopReason:"cancelled",reason:h})});let l,p=!1;try{let h=r.connection.request("hydra-acp/commands/invoke",d),f=await Promise.race([h,u]);if(f&&typeof f=="object"&&f.stopReason==="cancelled"&&"reason"in f)return p=!0,this.logger?.info(`extension ${e} ${i} cancelled (cancelExtensionDispatch); abandoning in-flight commands/invoke`),{stopReason:"cancelled"};l=f}catch(h){return this.emitExtensionReply(`${e} ${i}: ${h.message}`)}finally{n!==void 0&&!p&&this.inFlightExtensionDispatches.delete(n)}let m=l&&typeof l=="object"&&typeof l.text=="string"?l.text:"";return m.length>0?this.emitExtensionReply(m):{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:`
45
45
  ${e}
46
46
  `},_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}):
47
47
  ${n.join(`
@@ -51,10 +51,10 @@ ${e}
51
51
  ${t.join(`
52
52
  `)}`:"_(no commands advertised)_";return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
53
53
  ${n}
54
- `},_meta:{"hydra-acp":{synthetic:!0}}}}),Promise.resolve({stopReason:"end_turn"})}async handleModelCommand(e){let t=e.slice(6).trim();if(t===""){let i=this.agentAdvertisedModels,a=this.currentModel,d;if(i.length===0)d=a?`Current model: ${a}`:"_(no models advertised yet)_";else{let c=a?i.some(l=>l.modelId===a):!0,u=i.map(l=>{let p=l.modelId===a?"\u25B6 ":" ",f=l.name&&l.name!==l.modelId?` ${l.name}`:"";return`${p}${l.modelId}${f}`});!c&&a&&u.unshift(`\u25B6 ${a}`),d=u.join(`
54
+ `},_meta:{"hydra-acp":{synthetic:!0}}}}),Promise.resolve({stopReason:"end_turn"})}async handleModelCommand(e){let t=e.slice(6).trim();if(t===""){let i=this.agentAdvertisedModels,a=this.currentModel,d;if(i.length===0)d=a?`Current model: ${a}`:"_(no models advertised yet)_";else{let c=a?i.some(l=>l.modelId===a):!0,u=i.map(l=>{let p=l.modelId===a?"\u25B6 ":" ",m=l.name&&l.name!==l.modelId?` ${l.name}`:"";return`${p}${l.modelId}${m}`});!c&&a&&u.unshift(`\u25B6 ${a}`),d=u.join(`
55
55
  `)}return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
56
56
  ${d}
57
- `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}let n=It(t,this.agentAdvertisedModels),r=t;if(n.kind==="resolved")r=n.modelId;else if(n.kind==="ambiguous"||n.kind==="unknown"){let i=this.agentAdvertisedModels.map(p=>p.modelId),a=t.toLowerCase(),d=n.kind==="ambiguous"?n.candidates:i.filter(p=>p.toLowerCase().includes(a)),c=d.length>0?d:i,u=n.kind==="ambiguous"?`"${t}" matches multiple models: ${n.candidates.join(", ")}`:d.length>0?`"${t}" is not an available model. Did you mean`:`"${t}" is not an available model`,l=n.kind==="ambiguous"||d.length===0?"Available models":"Matching models";return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
57
+ `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}let n=_t(t,this.agentAdvertisedModels),r=t;if(n.kind==="resolved")r=n.modelId;else if(n.kind==="ambiguous"||n.kind==="unknown"){let i=this.agentAdvertisedModels.map(p=>p.modelId),a=t.toLowerCase(),d=n.kind==="ambiguous"?n.candidates:i.filter(p=>p.toLowerCase().includes(a)),c=d.length>0?d:i,u=n.kind==="ambiguous"?`"${t}" matches multiple models: ${n.candidates.join(", ")}`:d.length>0?`"${t}" is not an available model. Did you mean`:`"${t}" is not an available model`,l=n.kind==="ambiguous"||d.length===0?"Available models":"Matching models";return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
58
58
  ${u}.
59
59
  ${l}:
60
60
  ${c.join(`
@@ -62,9 +62,9 @@ ${l}:
62
62
  `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}let o=await this.forwardModelChange(r);return this.applyAgentConfigOptionResponse(o,"model"),this.applyModelChange(r),{stopReason:"end_turn"}}async handleModeCommand(e){let t=e.slice(5).trim();if(t===""){let r=this.agentAdvertisedModes,o=this.currentMode,i;if(r.length===0)i=o?`Current mode: ${o}`:"_(no modes advertised yet)_";else{let a=o?r.some(c=>c.id===o):!0,d=r.map(c=>{let u=c.id===o?"\u25B6 ":" ",l=c.name&&c.name!==c.id?` ${c.name}`:"";return`${u}${c.id}${l}`});!a&&o&&d.unshift(`\u25B6 ${o}`),i=d.join(`
63
63
  `)}return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
64
64
  ${i}
65
- `},_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 ye(new Error(`unknown mode: ${t} (known: ${r})`),C.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
+ `},_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 be(new Error(`unknown mode: ${t} (known: ${r})`),x.InvalidParams)}return await this.forwardRequest("session/set_mode",{sessionId:this.sessionId,modeId:t}),this.applyModeChange(t),{stopReason:"end_turn"}}async handleConfigCommand(e){let t=e.slice(7).trim().match(/^(\S+)(?:\s+([\s\S]*))?$/),n=t?.[1],r=t?.[2]??"";if(!n){let l=this.buildConfigOptions();if(l.length===0)return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
66
66
  _(no config options advertised yet)_
67
- `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let p=l.map(f=>Zi(f));return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
67
+ `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let p=l.map(m=>Ia(m));return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
68
68
  ${p.join(`
69
69
 
70
70
  `)}
@@ -74,18 +74,18 @@ ${p.join(`
74
74
  Available options:
75
75
  ${l}
76
76
  `},_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:`
77
- ${Zi(i)}
78
- `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let a=i.options.map(l=>l.value),d=Kt(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:`
79
- ${m}.
80
- ${g}:
81
- ${f.join(`
77
+ ${Ia(i)}
78
+ `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let a=i.options.map(l=>l.value),d=rn(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(g=>g.toLowerCase().includes(l)),m=p.length>0?p:a,h=d.kind==="ambiguous"?`"${r}" matches multiple values for "${n}": ${d.candidates.join(", ")}`:p.length>0?`"${r}" is not a valid value for "${n}". Did you mean`:`"${r}" is not a valid value for "${n}"`,f=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:`
79
+ ${h}.
80
+ ${f}:
81
+ ${m.join(`
82
82
  `)}
83
- `},_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 ye(new Error("/hydra agent requires an agent id"),C.InvalidParams);let r=(this.resolveAgentIdHook?await this.resolveAgentIdHook(t):void 0)??t;if(r===this.agentId)throw ye(new Error(`already on agent ${r}`),C.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 ye(new Error("agent restart not configured for this session"),C.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=Bi(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(`
84
- `)),{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(!Gi.includes(t))return this.emitExtensionReply(`Unknown workspace verb "${t}". Use one of: ${Gi.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 ye(new Error("session is closing"),C.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=it(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(`
85
- `)}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=hr({synopsis:e,title:t,tail:n,tailK:zl,tailFloor:Jl,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 On(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??bt,bt)),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=C.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),dr(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(()=>Vi(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(()=>sa.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:{[re]:{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===Ei&&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=!vr(e,r),i=o?mf(e,r):r,a=Date.now(),d=o?this.lastSeq=Math.max(this.lastSeq+1,a):void 0,c=o?Fe(Oe(i,a),d):i;if(o){this.noteRecordedToolCall(e,i);let u={method:e,params:i,recordedAt:a,seq:d};if(this.lastRecordedAt=u.recordedAt,this.appendCount+=1,this.historyStore){let l=this.historyStore;l.append(this.sessionId,u).catch(()=>{}),this.appendCount>=this.compactEvery&&(this.appendCount=0,l.compact(this.sessionId,this.historyMaxEntries).catch(()=>{}))}for(let l of this.broadcastHandlers)try{l(u)}catch{}this.scheduleIdleCheck(),this.dispatchIdle()}this.updatedAt=Date.now();for(let u of this.clients.values())n&&u.clientId===n||u.connection.notify(e,c).catch(()=>{})}async requestPermissionFromClients(e){return this.handlePermissionRequest(e)}async handlePermissionRequest(e){let t=[...this.clients.values()];if(t.length===0)throw ye(new Error("no clients attached to handle permission request"),C.PermissionDenied);let n=this.rewriteForClient(e),r=Yi(n),o=je(),{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===C.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=wf({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??ye(new Error("no client handled permission request"),C.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:je(),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[re];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(()=>Xt(t,e).catch(()=>{}))}persistedFromEntry(e){return{messageId:e.messageId,originator:{clientInfo:{...e.originator.name!==void 0?{name:e.originator.name}:{},...e.originator.version!==void 0?{version:e.originator.version}:{}}},prompt:e.prompt,enqueuedAt:e.enqueuedAt}}async drainQueue(){if(!this.promptInFlight){this.promptInFlight=!0,await new Promise(e=>setImmediate(e));try{for(;this.promptQueue.length>0&&!this.closing;){let e=this.promptQueue[0];if(e?.kind==="user"&&(await this.holdForUnsolicitedTurn(e),this.closing))break;let t=this.promptQueue.shift();if(!t)break;if(!t.cancelled){this.currentEntry=t,t.kind==="user"&&this.persistRewrite(),t.kind==="user"&&this.broadcastQueueRemoved(t.messageId,"started");try{let n=await this.runQueueEntry(t);t.resolve(n),await new Promise(r=>setImmediate(r))}catch(n){t.reject(n)}finally{this.currentEntry=void 0}}}}finally{this.promptInFlight=!1,this.supersededAutonomousTurn=void 0,this.dispatchIdle()}}}async runQueueEntry(e){if(e.kind==="internal")return this.closeUnsolicitedTurn("superseded",`internal:${e.label}`),e.task();this.broadcastPromptReceived(e);let t=it(e.prompt).replace(/\s+$/,""),n=!t.includes(`
86
- `)&&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=br(e.prompt,bf));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||!sf(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)}},nf=["session not found","the claude agent session has ended"];function sf(s){let e=s;if(e?.code!==C.InternalError)return!1;let t=e.data?.details,n=`${typeof e.message=="string"?e.message:""} ${typeof t=="string"?t:""}`.toLowerCase();return nf.some(r=>n.includes(r))}function ye(s,e){return s.code=e,s}var rf=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 of(s,e,t){return t?.run_in_background===!0?!1:e?.toolName==="Monitor"||s==="Monitor"||typeof e?.toolResponse?.taskId=="string"}function af(s){return typeof s!="string"?void 0:/Command running in background with ID: ([A-Za-z0-9_-]+)/.exec(s)?.[1]}function df(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 vr(s,e){if(s!=="session/update")return!1;let n=(e??{}).update?.sessionUpdate;return typeof n=="string"&&rf.has(n)}function cf(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 uf(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 lf(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 Zt(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 Dn(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 Ir(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 ff(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 pf(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 gf(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 mf(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:je()}}}function hf(s,e){if(s.length<=e)return s;let t=s.length-e;for(let n=t;n>=0;n--)if(s[n]?.params?.update?.sessionUpdate==="prompt_received")return s.slice(n);return s.slice(t)}function yf(s,e){for(let t=s.length-1;t>=0;t--)if(s[t]?.seq===e)return t;return-1}function jn(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 Yi(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 wf(s){let e=kf(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=vf(s.resolver),t}function kf(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 vf(s){let e={clientId:s.clientId};return s.clientInfo?.name&&(e.name=s.clientInfo.name),s.clientInfo?.version&&(e.version=s.clientInfo.version),e}function it(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?e.text:"").join(""):""}var bf="\u200B";function Xi(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 br(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 Sr(s){return s==="session/prompt"?{stopReason:"stopped"}:{}}function Sf(s){return s==="session/request_permission"?{outcome:{outcome:"cancelled"}}:{}}function Zi(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}
83
+ `},_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 be(new Error("/hydra agent requires an agent id"),x.InvalidParams);let r=(this.resolveAgentIdHook?await this.resolveAgentIdHook(t):void 0)??t;if(r===this.agentId)throw be(new Error(`already on agent ${r}`),x.InvalidParams);if(!this.scheduleCompactionHook)return this.emitExtensionReply("agent switching not configured for this session"),{stopReason:"end_turn"};this.scheduleCompactionHook({targetAgentId:r});let o=this.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 be(new Error("agent restart not configured for this session"),x.InternalError);return await this.respawnAgent(),{stopReason:"end_turn"}}runCompactCommand(e){return this.enqueuePrompt("compact",()=>this.runCompactCommandInline(e))}async runCompactCommandInline(e){return e==="status"?this.runCompactStatusCommandInline():this.scheduleCompactionHook?(this.scheduleCompactionHook(),this.emitExtensionReply("Compaction scheduled. The session will rotate to a fresh upstream once summarization completes."),{stopReason:"end_turn"}):(this.emitExtensionReply("compaction scheduling not configured for this session"),{stopReason:"end_turn"})}async runCompactStatusCommandInline(){let e=await this.getCompactionStateHook?.(),t=this._summarizedThroughEntry,n=await this.getUpstreamGenerationsHook?.()??[],r=la(n,t),o=fa(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(`
84
+ `)),{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(!wa.includes(t))return this.emitExtensionReply(`Unknown workspace verb "${t}". Use one of: ${wa.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 be(new Error("session is closing"),x.SessionClosing);return this.lastCancelAt=0,this.forceCancelling=!0,await this.close({deleteRecord:!1,by:"force-cancel"}),{stopReason:"cancelled"}}async 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 m=l.sessionUpdate;if(m==="prompt_received"){let h=gt(l.prompt);h&&n.push({speaker:"user",text:h})}else if(m==="agent_message_chunk"){let f=l.content?.text;f&&n.push({speaker:`agent: ${e}`,text:f})}else if(m==="tool_call"||m==="tool_call_update"){let h=l.status,f=l.title;(h==="completed"||h==="failed")&&n.push({speaker:"tool",text:`${f??"?"} ${h}`})}}if(n.length===0)return"";let o=[],i;for(let c of n)i&&i.speaker===c.speaker?i.text+=c.text:(i&&o.push(`<${i.speaker}>: ${i.text.trim()}`),i={speaker:c.speaker,text:c.text});i&&o.push(`<${i.speaker}>: ${i.text.trim()}`);let a=t?.intro??`You are taking over this conversation from ${e}. Below is the transcript so far.`,d=t?.followup??`Each line is prefixed with its speaker. Continue from where ${e} left off, responding to the user's most recent message.`;return[a,d,"","--- begin transcript ---",...o,"--- end transcript ---"].join(`
85
+ `)}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:Sf,tailFloor:If,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 Jn(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??Pt,Pt)),i=r.read(e,o);if(i.bytes.length===0&&i.eof!==!0&&n!==void 0&&n>0){let d=await r.waitForData(i.nextCursor,n);(d==="data"||d==="eof")&&(i=r.read(i.nextCursor,o))}let a={bytes:i.bytes.toString("base64"),nextCursor:i.nextCursor};return i.gap!==void 0&&(a.gap=i.gap),i.eof===!0&&(a.eof=!0),a}streamTail(e){let n=this.requireStreamBuffer().tail(e);return{bytes:n.bytes.toString("base64"),startCursor:n.startCursor,endCursor:n.endCursor,truncated:n.truncated}}streamHead(e){let n=this.requireStreamBuffer().head(e);return{bytes:n.bytes.toString("base64"),startCursor:n.startCursor,endCursor:n.endCursor,truncated:n.truncated}}async streamWaitFor(e,t){return this.requireStreamBuffer().waitForData(e,t)}streamGrep(e){return this.requireStreamBuffer().grep(e)}streamInfo(){let e=this.requireStreamBuffer();return{writeCursor:e.writeCursorPos,oldestAvailable:e.oldestAvailable,capacity:e.capacity,closed:e.isClosed}}requireStreamBuffer(){if(this.streamBuffer===void 0){let e=new Error(`session ${this.sessionId} has no stream buffer; POST /v1/sessions/:id/stdin/open first`);throw e.code=x.StreamNotEnabled,e}return this.streamBuffer}markClosed(e){if(this.closed)return;this.closeUnsolicitedTurn("closed"),e={deleteRecord:e.deleteRecord||this.deleteRecordIntent},this.closing=!0,this.closed=!0,this.cancelIdleTimer(),this.cancelOrphanTimer(),this.extensionCommandsUnsub&&(this.extensionCommandsUnsub(),this.extensionCommandsUnsub=void 0);for(let o of[...this.inFlightExtensionDispatches.keys()])this.cancelExtensionDispatch(o,"abandoned");this.currentEntry?.kind==="user"&&!this.recentlyTerminal.has(this.currentEntry.messageId)&&this.broadcastTurnComplete(this.currentEntry.clientId,{stopReason:"interrupted"},this.currentEntry.messageId,this.originatorNeedsTurnComplete(this.currentEntry)),this.currentEntry=void 0;let n=this.promptQueue;this.promptQueue=[];for(let o of n){o.cancelled=!0,o.kind==="user"&&this.broadcastQueueRemoved(o.messageId,"abandoned");let i=this.pendingTurnNotifiers.get(o.messageId);i&&(this.pendingTurnNotifiers.delete(o.messageId),Rr(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(()=>ya(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(()=>xa.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:{[ae]:{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,m={path:l,toolCallId:o};typeof p=="number"&&(m.line=p),this.notifyChain("file.edited",m),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=!jr(e,r),i=o?zf(e,r):r,a=Date.now(),d=o?this.lastSeq=Math.max(this.lastSeq+1,a):void 0,c=o?Le(He(i,a),d):i;if(o){this.noteRecordedToolCall(e,i);let u={method:e,params:i,recordedAt:a,seq:d};if(this.lastRecordedAt=u.recordedAt,this.appendCount+=1,this.historyStore){let l=this.historyStore;l.append(this.sessionId,u).catch(()=>{}),this.appendCount>=this.compactEvery&&(this.appendCount=0,l.compact(this.sessionId,this.historyMaxEntries).catch(()=>{}))}for(let l of this.broadcastHandlers)try{l(u)}catch{}this.scheduleIdleCheck(),this.dispatchIdle()}this.updatedAt=Date.now();for(let u of this.clients.values())n&&u.clientId===n||u.connection.notify(e,c).catch(()=>{})}async requestPermissionFromClients(e){return this.handlePermissionRequest(e)}async handlePermissionRequest(e){let t=[...this.clients.values()];if(t.length===0)throw be(new Error("no clients attached to handle permission request"),x.PermissionDenied);let n=this.rewriteForClient(e),r=ba(n),o=We(),{toolCall:i,options:a}=n??{};return new Promise((d,c)=>{let u=!1,l=[],p=0,m,h=this.sessionId,f=y=>{u||(u=!0,this.clearAttentionFlag("daemon",`permission:${o}`),this.permissionCallbacks.delete(o),y())},g=y=>y?.code===x.MethodNotFound;function w(y){if(u)return;let k=y.connection.request("session/request_permission",n);l.push({client:y}),p++,k.then(b=>{p--,f(()=>{let S=Gf({toolCallId:r,result:b,resolver:y});for(let v of l)v.client.clientId!==y.clientId&&v.client.connection.notify("session/update",{sessionId:h,update:S}).catch(()=>{});d(b)})}).catch(b=>{if(p--,g(b)||(m=b),p===0&&!u){let S=m??be(new Error("no client handled permission request"),x.PermissionDenied);f(()=>c(S))}})}this.setAttentionFlag("daemon",`permission:${o}`,{kind:"permission",toolCall:i??null,options:a??null}),this.permissionCallbacks.set(o,w);for(let y of t)w(y)})}async enqueuePrompt(e,t){return new Promise((n,r)=>{let o={kind:"internal",messageId:We(),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[ae];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(()=>dn(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=gt(e.prompt).replace(/\s+$/,""),n=!t.includes(`
86
+ `)&&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=Hr(e.prompt,Yf));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||!Ff(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)}},$f=["session not found","the claude agent session has ended"];function Ff(s){let e=s;if(e?.code!==x.InternalError)return!1;let t=e.data?.details,n=`${typeof e.message=="string"?e.message:""} ${typeof t=="string"?t:""}`.toLowerCase();return $f.some(r=>n.includes(r))}function be(s,e){return s.code=e,s}var Of=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 Nf(s,e,t){return t?.run_in_background===!0?!1:e?.toolName==="Monitor"||s==="Monitor"||typeof e?.toolResponse?.taskId=="string"}function Df(s){return typeof s!="string"?void 0:/Command running in background with ID: ([A-Za-z0-9_-]+)/.exec(s)?.[1]}function jf(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 jr(s,e){if(s!=="session/update")return!1;let n=(e??{}).update?.sessionUpdate;return typeof n=="string"&&Of.has(n)}function Hf(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 Lf(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 Uf(s,e){if(s.length!==e.length)return!1;for(let t=0;t<s.length;t++)if(s[t]?.modelId!==e[t]?.modelId||s[t]?.name!==e[t]?.name||s[t]?.description!==e[t]?.description)return!1;return!0}function cn(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object"||Array.isArray(t))continue;let n=t,r=typeof n.modelId=="string"&&n.modelId.trim()||typeof n.value=="string"&&n.value.trim()||typeof n.id=="string"&&n.id.trim()||void 0;if(!r)continue;let o={modelId:r};typeof n.name=="string"&&n.name.length>0&&(o.name=n.name),typeof n.description=="string"&&n.description.length>0&&(o.description=n.description),e.push(o)}return e}function Kn(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 Ur(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 Bf(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 Wf(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 qf(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 zf(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:We()}}}function Jf(s,e){if(s.length<=e)return s;let t=s.length-e;for(let n=t;n>=0;n--)if(s[n]?.params?.update?.sessionUpdate==="prompt_received")return s.slice(n);return s.slice(t)}function Vf(s,e){for(let t=s.length-1;t>=0;t--)if(s[t]?.seq===e)return t;return-1}function Qn(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 ba(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 Gf(s){let e=Kf(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=Qf(s.resolver),t}function Kf(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 Qf(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 gt(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?e.text:"").join(""):""}var Yf="\u200B";function Sa(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 Hr(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 Lr(s){return s==="session/prompt"?{stopReason:"stopped"}:{}}function Xf(s){return s==="session/request_permission"?{outcome:{outcome:"cancelled"}}:{}}function Ia(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}
87
87
  ${n.join(`
88
- `)}`}function Ar(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();We();import*as Ae from"fs/promises";import*as Ww from"path";import{customAlphabet as Cf}from"nanoid";import{z as P}from"zod";import{z as xt}from"zod";var If=xt.object({source:xt.string(),reason:xt.string(),raisedAt:xt.number(),payload:xt.unknown()}),ra=xt.array(If);import{z as G}from"zod";var oa=G.object({status:G.enum(["requested","running","swap_pending","swap_deferred","failed"]),requestedAt:G.number(),runId:G.string().optional(),iter:G.number().int().nonnegative().optional(),attempts:G.number().int().nonnegative().optional(),lastError:G.string().optional(),worker:G.object({upstreamSessionId:G.string(),pid:G.number().int().nonnegative()}).optional()}),en=G.object({goal:G.string().optional(),outcome:G.string().optional(),files_touched:G.array(G.string()).optional(),tools_used:G.array(G.string()).optional(),rejected_approaches:G.array(G.string()).optional(),open_threads:G.array(G.string()).optional(),decisions:G.array(G.string()).optional(),file_edit_intentions:G.array(G.string()).optional(),unresolved_errors:G.array(G.string()).optional(),tool_state:G.array(G.string()).optional()}),ia=200,Cr=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
88
+ `)}`}function Br(s,e){for(let t of s.split(/\r?\n/)){let n=t.trim();if(n)return n.length>e?`${n.slice(0,e)}\u2026`:n}}Y();Oe();import*as xe from"fs/promises";import*as _k from"path";import{customAlphabet as tp}from"nanoid";import{z as P}from"zod";import{z as Ot}from"zod";var Zf=Ot.object({source:Ot.string(),reason:Ot.string(),raisedAt:Ot.number(),payload:Ot.unknown()}),Ea=Ot.array(Zf);import{z as K}from"zod";var Ta=K.object({status:K.enum(["requested","running","swap_pending","swap_deferred","failed"]),requestedAt:K.number(),runId:K.string().optional(),iter:K.number().int().nonnegative().optional(),attempts:K.number().int().nonnegative().optional(),lastError:K.string().optional(),worker:K.object({upstreamSessionId:K.string(),pid:K.number().int().nonnegative()}).optional()}),un=K.object({goal:K.string().optional(),outcome:K.string().optional(),files_touched:K.array(K.string()).optional(),tools_used:K.array(K.string()).optional(),rejected_approaches:K.array(K.string()).optional(),open_threads:K.array(K.string()).optional(),decisions:K.array(K.string()).optional(),file_edit_intentions:K.array(K.string()).optional(),unresolved_errors:K.array(K.string()).optional(),tool_state:K.array(K.string()).optional()}),Pa=200,Wr=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
89
89
  {
90
90
  "title": "short summary, max 80 chars",
91
91
  "synopsis": {
@@ -95,7 +95,7 @@ ${n.join(`
95
95
  "open_threads": ["work started but not finished"]
96
96
  }
97
97
  }
98
- Use empty arrays/strings where a field doesn't apply.`;function aa(s){let e=s.trim();if(e.length===0)return;let t=Rt(e);if(t===void 0){let o=e.indexOf("{"),i=e.lastIndexOf("}");o>=0&&i>o&&(t=Rt(e.slice(o,i+1)))}if(t===void 0){let o=ca(e);o!==void 0&&(t=Rt(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,ia))}if(n.synopsis!==void 0&&n.synopsis!==null){let o=en.safeParse(n.synopsis);o.success&&Af(o.data)&&(r.synopsis=o.data)}if(!(r.title===void 0&&r.synopsis===void 0))return r}var xr=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
98
+ Use empty arrays/strings where a field doesn't apply.`;function Ma(s){let e=s.trim();if(e.length===0)return;let t=Nt(e);if(t===void 0){let o=e.indexOf("{"),i=e.lastIndexOf("}");o>=0&&i>o&&(t=Nt(e.slice(o,i+1)))}if(t===void 0){let o=$a(e);o!==void 0&&(t=Nt(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,Pa))}if(n.synopsis!==void 0&&n.synopsis!==null){let o=un.safeParse(n.synopsis);o.success&&ep(o.data)&&(r.synopsis=o.data)}if(!(r.title===void 0&&r.synopsis===void 0))return r}var qr=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
99
99
  {
100
100
  "title": "short summary, max 80 chars",
101
101
  "goal": "the user's original ask",
@@ -107,94 +107,94 @@ Use empty arrays/strings where a field doesn't apply.`;function aa(s){let e=s.tr
107
107
  "unresolved_errors": ["errors left open at session end"],
108
108
  "tool_state": ["runtime state relevant for recall"]
109
109
  }
110
- Use empty arrays/strings where a field doesn't apply.`;function da(s){let e=s.trim();if(e.length===0)return;let t=Rt(e);if(t===void 0){let c=e.indexOf("{"),u=e.lastIndexOf("}");c>=0&&u>c&&(t=Rt(e.slice(c,u+1)))}if(t===void 0){let c=ca(e);c!==void 0&&(t=Rt(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,ia))}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=G.array(G.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 Rt(s){try{return JSON.parse(s)}catch{return}}function ca(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 Af(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 xf="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Rf=Cf(xf,16),Ef="hydra_lineage_";function nn(){return`${Ef}${Rf()}`}var Rr=P.object({name:P.string(),description:P.string().optional()}),Er=P.object({id:P.string(),name:P.string().optional(),description:P.string().optional()}),Tf=P.object({modelId:P.string(),name:P.string().optional(),description:P.string().optional()}),Tr=P.object({used:P.number().optional(),size:P.number().optional(),costAmount:P.number().optional(),costCurrency:P.string().optional(),cumulativeCost:P.number().optional()}),Pr=P.object({name:P.string(),version:P.string().optional()}),Pf=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()}),Mf=P.object({previousUpstreamSessionId:P.string(),previousSummarizedThroughEntry:P.number().int().nonnegative().optional(),runId:P.string().optional()}),_f=P.enum(["compaction","agent-swap","workspace-enter","workspace-leave","rollback","restart"]),$f=P.object({upstreamSessionId:P.string(),agentId:P.string(),reason:_f.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()}),Of=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:en.optional(),compactionState:oa.optional(),rollbackBreadcrumb:Mf.optional(),upstreamGenerations:P.array($f).optional(),summarizedThroughEntry:P.number().int().nonnegative().optional(),agentArgs:P.array(P.string()).optional(),currentModel:P.string().optional(),currentMode:P.string().optional(),currentUsage:Tr.optional(),agentCommands:P.array(Rr).optional(),agentModes:P.array(Er).optional(),agentModels:P.array(Tf).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:Pr.optional(),interactive:P.boolean().optional(),priority:P.number().int().nonnegative().optional(),forwardedEnv:P.record(P.string(),P.string()).optional(),workspace:Pf.optional(),attentionFlags:ra.default([]).optional(),extensionState:P.record(P.string(),P.record(P.string(),P.unknown())).default({}).optional(),createdAt:P.string(),updatedAt:P.string()}),tn=/^[A-Za-z0-9_-]+$/;function Ff(s){if(!tn.test(s))throw new Error(`unsafe session id: ${s}`)}var Hn=class{index;indexSeed;async write(e){Ff(e.sessionId);let t={version:1,...e};await he(A.sessionFile(e.sessionId),t,{mode:384}),await this.reindex(e.sessionId)}async touch(e){if(!tn.test(e))return;let t=new Date;try{await Ae.utimes(A.sessionFile(e),t,t)}catch(n){if(n.code!=="ENOENT")throw n;return}await this.reindex(e)}async markDeleted(e,t){await this.ensureIndex();let n=this.index.get(e);n&&!n.deleted||n&&n.mtimeMs>=t||this.index.set(e,{mtimeMs:t,deleted:!0})}async cursor(){await this.ensureIndex();let e=0;for(let t of this.index.values())t.mtimeMs>e&&(e=t.mtimeMs);return e}async listChangedSince(e){let t=await this.cursor(),n=[],r=[];for(let[a,d]of this.index)d.mtimeMs<e||(d.deleted?r.push(a):n.push(a));let o=await Promise.all(n.map(a=>this.read(a).catch(()=>{}))),i=[];for(let a of o)a&&i.push(a);return{records:i,removed:r,cursor:t}}async ensureIndex(){this.index||(this.indexSeed||(this.indexSeed=this.seedIndex()),await this.indexSeed)}async seedIndex(){let e=new Map,t=[];try{t=await Ae.readdir(A.sessionsDir())}catch(n){if(n.code!=="ENOENT")throw n}await Promise.all(t.map(async n=>{if(tn.test(n))try{let r=await Ae.stat(A.sessionFile(n));e.set(n,{mtimeMs:r.mtimeMs,deleted:!1})}catch{}})),this.index=e}async reindex(e){if(this.indexSeed){await this.indexSeed;try{let t=await Ae.stat(A.sessionFile(e));this.index.set(e,{mtimeMs:t.mtimeMs,deleted:!1})}catch{}}}async read(e){if(!tn.test(e))return;let t=await se(A.sessionFile(e));if(t!==void 0)try{return Of.parse(t)}catch{return}}async delete(e){if(tn.test(e)){this.indexSeed&&(await this.indexSeed,this.index.set(e,{mtimeMs:Date.now(),deleted:!0}));try{await Ae.unlink(A.sessionFile(e))}catch(t){if(t.code!=="ENOENT")throw t}try{await Ae.rmdir(A.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 Ae.readdir(A.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 Mr(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}}We();Q();import*as ce from"fs/promises";import*as ue from"path";Q();import*as Ln from"path";import{createHash as Nf}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 Et(s){let e=Nf("sha256").update(Ln.resolve(s)).digest("hex").slice(0,12);return Ln.join(W(),"workspaces",e)}async function Un(s,e,t=100){if(await e(s))return s;for(let n=2;n<=t;n+=1){let r=`${s}-${n}`;if(await e(r))return r}}function at(s,e=10){if(s.length<=e)return[...s];let t=s.slice(0,e),n=s.length-e;return[...t,`... and ${n} more`]}function _r(s){return s.changedPaths.length>0||s.recorded!==void 0&&s.recorded!==s.actual}function Df(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 $r(s,e){let t=new Set(e.map(r=>r.relPath));return[...s.filter(r=>!t.has(r.replace(/\/$/,""))),...Df(e.filter(_r))]}function Bn(s){let e=s.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return e.length>0?e.slice(0,64):"workspace"}var Or="copy",la=new Set([".git"]);function sn(s){return`${s}.manifest.json`}async function ua(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 ce.readdir(n,{withFileTypes:!0})}catch{continue}for(let o of r){let i=ue.join(n,o.name);if(!(n===s&&la.has(o.name))){if(o.isDirectory()){t.push(i);continue}if(o.isFile())try{let a=await ce.stat(i);e.set(ue.relative(s,i),{size:a.size,mtimeMs:a.mtimeMs})}catch{continue}}}}return e}var Wn=class{kind=Or;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=ue.resolve(e.sourceCwd),n=e.contentFrom!==void 0?ue.resolve(e.contentFrom):t;try{if(!(await ce.stat(n)).isDirectory())return{ok:!1,reason:`${n} is not a directory`}}catch{return{ok:!1,reason:`${n} does not exist`}}let r=Et(t);try{await ce.mkdir(r,{recursive:!0})}catch(c){return{ok:!1,reason:`could not create workspace root: ${String(c)}`}}let o=await Un(Bn(e.label),async c=>ce.access(ue.join(r,c)).then(()=>!1).catch(()=>!0));if(o===void 0)return{ok:!1,reason:`no free name available for "${e.label}"`};let i=ue.join(r,o);try{await ce.cp(n,i,{recursive:!0,errorOnExist:!1,force:!0,filter:c=>{let u=ue.relative(n,c);if(u.length===0)return!0;let l=u.split(ue.sep)[0];return l===void 0||!la.has(l)}})}catch(c){return await ce.rm(i,{recursive:!0,force:!0}).catch(()=>{}),{ok:!1,reason:`copy failed: ${String(c)}`}}let a=await ua(i),d={sourceCwd:t,label:o,createdAt:new Date().toISOString(),entries:Object.fromEntries(a)};return await he(sn(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 ce.rm(e.path,{recursive:!0,force:!0}),await ce.rm(sn(e.path),{force:!0})}async listWorkspaces(e){let t=Et(ue.resolve(e)),n;try{n=await ce.readdir(t)}catch{return[]}let r=[];for(let o of n){if(o.endsWith(".manifest.json"))continue;let i=ue.join(t,o),a=await se(sn(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(sn(e.path)),n=await ua(e.path);if(t===void 0)return{clean:!1,changedPaths:[...n.keys()].sort(),hasRecordedWork:!1};let r=[];for(let[o,i]of n){let a=t.entries[o];(a===void 0||a.size!==i.size||a.mtimeMs!==i.mtimeMs)&&r.push(o)}for(let o of Object.keys(t.entries))n.has(o)||r.push(o);return r.sort(),{clean:r.length===0,changedPaths:r,hasRecordedWork:!1}}async statusReport(e){let{changedPaths:t}=await this.status(e),n=t.length===0?["no changes since this copy was made"]:[`${t.length} changed file(s) since this copy was made:`,...at(t.map(r=>` ${r}`))];return n.push(`Not tracking ${$(e.sourceCwd)}: a copied directory has no shared history, so there is nothing to be in or out of sync with.`),n}async environmentNotes(e){return[`This directory is an isolated copy of ${e.sourceCwd}. It is not under version control: there is no history, no branches, and version-control commands will not behave as they would in the original.`,"Changes here are not automatically returned to the original directory."]}async captureWorkingState(){throw new Re(this.kind,"captureWorkingState")}async record(){throw new Re(this.kind,"record")}async attributeOrphan(e){let t=await se(sn(e));if(t?.sourceCwd!==void 0)return{path:e,sourceCwd:t.sourceCwd,label:t.label??ue.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 ha}from"child_process";import{randomBytes as Uf}from"crypto";import*as Ee from"fs/promises";import*as ya from"os";import*as Y from"path";function jf(s){let e=s.indexOf(" ");return e===-1?{key:s,value:""}:{key:s.slice(0,e),value:s.slice(e+1)}}function fa(s){let e=[],t,n=()=>{t!==void 0&&(e.push(t),t=void 0)};for(let r of s.split(`
111
- `)){let o=r.replace(/\r$/,"");if(o.length===0){n();continue}let{key:i,value:a}=jf(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 pa(s){if(s===void 0)return;let e="refs/heads/";return s.startsWith(e)?s.slice(e.length):s}var Jn="git",ga="hydra-acp:",Fr="hydra",z=5e3,oe=12e4,qn=9e5;function ma(s){return Ee.access(s).then(()=>!0).catch(()=>!1)}function Bf(s){return Ee.realpath(s).catch(()=>s)}function j(s,e,t,n){return new Promise(r=>{ha("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 Nr(s,e,t,n=oe){return new Promise(r=>{let o=ha("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 Dr(s){let e=[];for(let t of s.split(`
112
- `)){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 zn=class{kind=Jn;refRoot(e){return e.vcs?.repoRoot??e.sourceCwd}ownsLine(e){return e.startsWith(`${Fr}/`)}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 ma(Y.join(e.path,".gitmodules")))return{ok:!0,count:0};let r=await j(["submodule","update","--init","--recursive",...t?.discardLocal===!0?["--force"]:[]],e.path,qn);if(!r.ok)return{ok:!1,count:0,reason:r.stderr.trim()||"git submodule update --init failed"};if(t?.discardLocal===!0){let a=await j(["submodule","foreach","--recursive","git","reset","--hard"],e.path,qn);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 j(["submodule","foreach","--recursive","git","clean",d],e.path,qn);if(!c.ok)return{ok:!1,count:0,reason:c.stderr.trim()||"could not clean submodules"}}let o=await j(["submodule","status","--recursive"],e.path,z);return{ok:!0,count:o.ok?o.stdout.split(`
113
- `).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 ma(n))return{ok:!1,reason:`source repository ${n} no longer exists`};let r=await j(["rev-parse","--verify","--quiet",`refs/heads/${t}`],n,z);if(!r.ok||r.stdout.trim().length===0)return{ok:!1,reason:`branch ${t} no longer exists in ${n}`};await j(["worktree","unlock",e.path],n,z),await j(["worktree","prune"],n,z);let o=await j(["worktree","add",e.path,t],n,oe);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 j(["rev-parse","--show-toplevel"],t,z);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 j(["rev-parse","HEAD"],r,z);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=Bn(e.label),d=Et(t);try{await Ee.mkdir(d,{recursive:!0})}catch(f){return{ok:!1,reason:`could not create workspace root: ${String(f)}`}}let c=await Un(a,async f=>await Ee.access(Y.join(d,f)).then(()=>!0).catch(()=>!1)?!1:!(await j(["rev-parse","--verify","--quiet",`refs/heads/${Fr}/${f}`],r,z)).ok);if(c===void 0)return{ok:!1,reason:`no free name available for "${a}"`};let u=Y.join(d,c),l=`${Fr}/${c}`,p=await j(["worktree","add","--no-track","-b",l,u,i],r,oe);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 j(["worktree","remove","--force",e.path],n,oe);t.discardLine===!0&&e.vcs?.branch!==void 0&&await j(["branch","-D",e.vcs.branch],n,z),r.ok||(await Ee.rm(e.path,{recursive:!0,force:!0}),await j(["worktree","prune"],n,z))}async listWorkspaces(e){let t=Y.resolve(e),n=await j(["rev-parse","--show-toplevel"],t,z);if(!n.ok)return[];let r=n.stdout.trim(),o=await j(["worktree","list","--porcelain"],r,z);if(!o.ok)return[];let i=Et(t),a=await Bf(i),d=[];for(let c of fa(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=pa(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(ga)===!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 j(["status","--porcelain","--untracked-files=all"],e.path,z);if(!t.ok)return{clean:!1,changedPaths:[],hasRecordedWork:!1};let n=Dr(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 j(["rev-list","--count",`${e.snapshot}..HEAD`],e.path,z);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 j(["worktree","lock","--reason",`${ga}${t}`,e.path],n,z)}async unlock(e){let t=this.refRoot(e);await j(["worktree","unlock",e.path],t,z)}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 Ee.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 j(["status","--porcelain","--untracked-files=all"],e.path,z);if(n.ok){let r=Dr(n.stdout);if(r.length===0)t.push("no uncommitted changes");else{let o=0,i=0,a=0;for(let{code:c}of r){if(c==="??"){a+=1;continue}c[0]!==" "&&c[0]!=="?"&&(o+=1),c[1]!==" "&&c[1]!=="?"&&(i+=1)}let d=[];o>0&&d.push(`${o} staged`),i>0&&d.push(`${i} unstaged`),a>0&&d.push(`${a} untracked`),t.push(`${d.join(", ")}:`),t.push(...at(r.map(c=>` ${c.code} ${c.path}`)))}}return t.push(...await this.syncLines(e)),t}async syncLines(e){if(e.vcs?.branch===void 0)return[];let[t,n]=await Promise.all([j(["rev-parse","HEAD"],e.sourceCwd,z),j(["rev-parse","HEAD"],e.path,z)]),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 j(["rev-list","--left-right","--count",`${r}...${o}`],e.path,z),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(ya.tmpdir(),`hydra-index-${process.pid}-${Uf(6).toString("hex")}`),r={GIT_INDEX_FILE:n};try{let o=await j(["rev-parse","--verify","HEAD"],e,z),i=o.ok&&o.stdout.trim().length>0;if(i){let l=await j(["read-tree","HEAD"],e,oe,r);if(!l.ok)throw new Error(`could not seed the snapshot index: ${l.stderr.trim()}`)}let a=await j(["add","-A"],e,oe,r);if(!a.ok)throw new Error(`could not stage working state: ${a.stderr.trim()}`);let d=await j(["write-tree"],e,oe,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 j(c,e,oe,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 Ee.rm(n,{force:!0}).catch(()=>{})}}async retainSnapshot(e,t,n){let r=this.refRoot(e);await j(["update-ref","--create-reflog",t,n],r,z)}async dropSnapshotRef(e,t){let n=this.refRoot(e);await j(["update-ref","-d",t],n,z)}async currentState(e){let t=await j(["rev-parse","HEAD"],e,z),n=t.stdout.trim();return t.ok&&n.length>0?n:void 0}async contentId(e,t){let n=await j(["rev-parse",`${t}^{tree}`],e,z),r=n.stdout.trim();return n.ok&&r.length>0?r:void 0}async currentLineName(e){let t=await j(["rev-parse","--abbrev-ref","HEAD"],e,z),n=t.stdout.trim();return t.ok&&n.length>0?n:void 0}async resolveRoot(e){let t=await j(["rev-parse","--show-toplevel"],e,z),n=t.stdout.trim();return t.ok&&n.length>0?n:void 0}async resolveRetained(e,t){let n=await j(["rev-parse","--verify","--quiet",`${t}^{commit}`],this.refRoot(e),z),r=n.stdout.trim();return n.ok&&r.length>0?r:void 0}async contains(e,t){return(await j(["merge-base","--is-ancestor",t.state,t.within],e,z)).ok}async divergence(e,t,n){let r=await j(["rev-list","--left-right","--count",`${t}...${n}`],e,z);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 j(["diff","--name-only",t,n],e,z);return r.ok?r.stdout.split(`
114
- `).map(o=>o.replace(/\r$/,"").trim()).filter(o=>o.length>0):[]}async captureDelta(e,t,n){let r=await j(["diff","--binary","--ignore-submodules=all",t,n],e,oe);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 Nr(["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 Nr(["apply","--reverse","--check"],e,t)).ok)return{ok:!0,alreadyPresent:!0};let a=await Nr(["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 j(["reset","--hard",t],e,oe);if(!r.ok)return{ok:!1,reason:r.stderr.trim()||"could not return to that state"};let o=await j(["clean",n?.purgeIgnored===!0?"-ffdx":"-fd"],e,oe);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 j(["rev-parse","-q","--verify","MERGE_HEAD"],e,z)).ok}async abortIntegration(e){await j(["merge","--abort"],e,oe)}async conflictedPaths(e){let t=await j(["diff","--name-only","--diff-filter=U"],e,z);return t.ok?t.stdout.split(`
115
- `).map(n=>n.replace(/\r$/,"").trim()).filter(n=>n.length>0):[]}async record(e,t){let n=await j(["add","-A"],e.path,oe);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 j(["commit","-m",t],e.path,oe);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 j(["rev-parse","--path-format=absolute","--git-common-dir"],e,z),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 j(["branch","-D",t],n,z);return i.ok?{ok:!0,dropped:o}:{ok:!1,dropped:o,reason:i.stderr.trim()||"could not discard the line"}}async pruneStale(e){await j(["worktree","prune"],this.refRoot(e),z)}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 j(o,t,oe);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 j(["submodule","status","--recursive"],e,oe);if(!t.ok)return[];let n=[];for(let r of t.stdout.split(`
116
- `)){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||!Wf(e,c))continue;let u=Y.join(e,c),[l,p,f]=await Promise.all([this.currentState(u),j(["rev-parse",`HEAD:${c}`],e,z),j(["status","--porcelain","--untracked-files=all"],u,z)]);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?Dr(f.stdout).map(g=>g.path):[]})}return n}async captureNested(e,t){let n=[];for(let r of t){if(!_r(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 j(["cat-file","-e",`${n}^{commit}`],e,z)).ok&&!(await j(["fetch","--no-tags",t,n],e,qn)).ok)return`could not transfer ${n.slice(0,8)} from the other copy`;if(!(await j(["checkout","--detach",n],e,oe)).ok)return`could not move to ${n.slice(0,8)}`}};function Wf(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 qf=Jn,zf=new Map([[Jn,new zn],[Or,new Wn]]);function ee(s){return zf.get(s??qf)}var Vn="refs/hydra";function rn(s){let e=`${Vn}/workspaces/${s}`;return{autosave:`${e}/autosave`,start:`${e}/start`,baseline:`${e}/baseline`}}function jr(s){return`${Vn}/landing/${s}`}function wa(s){return`${Vn}/sync/${s}`}function ka(s,e){return`${Vn}/retired/${s}-${e.slice(0,12)}`}function va(s){let e=rn(s);return[e.autosave,e.start,e.baseline]}async function Hr(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 dt(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 on(s){s.capture.retainedRef===void 0||s.provider===void 0||await s.provider.dropSnapshotRef({...s.ws,path:s.source},s.capture.retainedRef).catch(()=>{})}We();import{execFile as Jf}from"child_process";import*as Le from"fs/promises";import*as ve from"path";var Vf=".hydra/worktree.json",Gf=".worktreeinclude",Kf=120;async function Gn(s){let e=await se(ve.join(s,Vf))??{},t=new Set(Array.isArray(e.carry)?e.carry:[]),n=await Le.readFile(ve.join(s,Gf),"utf8").catch(()=>{});if(n!==void 0)for(let o of n.split(`
117
- `)){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 Lr(s,e,t){let n=[],r=[],o=ve.resolve(s),i=ve.resolve(e);for(let a of t){let d=ve.resolve(o,a),c=ve.resolve(i,a);if(!d.startsWith(o+ve.sep)||!c.startsWith(i+ve.sep)){r.push(a);continue}if(await Le.access(c).then(()=>!0).catch(()=>!1)){r.push(a);continue}let l=await Le.stat(d).catch(()=>{});if(l===void 0){r.push(a);continue}try{await Le.mkdir(ve.dirname(c),{recursive:!0}),await Le.cp(d,c,{recursive:l.isDirectory()}),n.push(a)}catch{r.push(a)}}return{copied:n,skipped:r}}async function Kn(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??Kf)*1e3;return new Promise(r=>{let o=Jf("/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();We();import*as ze from"fs/promises";import{z as Te}from"zod";var Qf=Te.object({version:Te.literal(1),agentId:Te.string(),upstreamSessionId:Te.string(),sessionId:Te.string().optional(),deletedAt:Te.string(),upstreamUpdatedAt:Te.string().optional(),cwd:Te.string().optional(),title:Te.string().optional(),reason:Te.enum(["user","expired"]).optional(),interactive:Te.boolean().optional()}),Qn=class{async add(e){let t={version:1,...e};await he(A.tombstoneFile(e.agentId,e.upstreamSessionId),t,{mode:384})}async has(e,t){try{return await ze.access(A.tombstoneFile(e,t)),!0}catch{return!1}}async read(e,t){let n=A.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 Qf.parse(r)}catch{return{version:1,agentId:e,upstreamSessionId:t,deletedAt:new Date(0).toISOString()}}}async remove(e,t){try{await ze.unlink(A.tombstoneFile(e,t))}catch(n){if(n.code!=="ENOENT")throw n}try{await ze.rmdir(A.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 ze.readdir(A.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 ze.readdir(A.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 ba(s,e){return s.reason==="user"||e===void 0?!1:s.upstreamUpdatedAt===void 0?!0:e>s.upstreamUpdatedAt}import*as Oa from"fs/promises";import{customAlphabet as rp}from"nanoid";import{fileURLToPath as Yf}from"url";import*as an from"path";import*as Yn from"fs";function Xf(){try{let s=an.dirname(Yf(import.meta.url));for(let e=0;e<8;e+=1){let t=an.join(s,"package.json");if(Yn.existsSync(t)){let r=JSON.parse(Yn.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=an.dirname(s);if(n===s)break;s=n}}catch{}return"0.0.0"}var le=Xf(),Xn="hydra-acp-cat";var Zf=12e4;async function Ia(s,e,t){let n=s.timeoutMs??Zf,r,o,i=!1;try{let a=(async()=>{r=Ye.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:le}}),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=tp(c);if(m.size===0||m.has(s.modelId)){let g=r.connection;try{await Xe({request:(h,w)=>g.request(h,w),sessionId:u,modelId:s.modelId,verb:vt(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=ep(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 Zn(s){let e=At(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}
110
+ Use empty arrays/strings where a field doesn't apply.`;function _a(s){let e=s.trim();if(e.length===0)return;let t=Nt(e);if(t===void 0){let c=e.indexOf("{"),u=e.lastIndexOf("}");c>=0&&u>c&&(t=Nt(e.slice(c,u+1)))}if(t===void 0){let c=$a(e);c!==void 0&&(t=Nt(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,Pa))}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=K.array(K.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 Nt(s){try{return JSON.parse(s)}catch{return}}function $a(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 ep(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 np="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",sp=tp(np,16),rp="hydra_lineage_";function fn(){return`${rp}${sp()}`}var zr=P.object({name:P.string(),description:P.string().optional()}),Jr=P.object({id:P.string(),name:P.string().optional(),description:P.string().optional()}),op=P.object({modelId:P.string(),name:P.string().optional(),description:P.string().optional()}),Vr=P.object({used:P.number().optional(),size:P.number().optional(),costAmount:P.number().optional(),costCurrency:P.string().optional(),cumulativeCost:P.number().optional()}),Gr=P.object({name:P.string(),version:P.string().optional()}),ip=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()}),ap=P.object({previousUpstreamSessionId:P.string(),previousSummarizedThroughEntry:P.number().int().nonnegative().optional(),runId:P.string().optional()}),dp=P.enum(["compaction","agent-swap","workspace-enter","workspace-leave","rollback","restart"]),cp=P.object({upstreamSessionId:P.string(),agentId:P.string(),reason:dp.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()}),up=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:un.optional(),compactionState:Ta.optional(),rollbackBreadcrumb:ap.optional(),upstreamGenerations:P.array(cp).optional(),summarizedThroughEntry:P.number().int().nonnegative().optional(),agentArgs:P.array(P.string()).optional(),currentModel:P.string().optional(),currentMode:P.string().optional(),currentUsage:Vr.optional(),agentCommands:P.array(zr).optional(),agentModes:P.array(Jr).optional(),agentModels:P.array(op).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:Gr.optional(),interactive:P.boolean().optional(),priority:P.number().int().nonnegative().optional(),forwardedEnv:P.record(P.string(),P.string()).optional(),workspace:ip.optional(),attentionFlags:Ea.default([]).optional(),extensionState:P.record(P.string(),P.record(P.string(),P.unknown())).default({}).optional(),createdAt:P.string(),updatedAt:P.string()}),ln=/^[A-Za-z0-9_-]+$/;function lp(s){if(!ln.test(s))throw new Error(`unsafe session id: ${s}`)}var Yn=class{index;indexSeed;async write(e){lp(e.sessionId);let t={version:1,...e};await ue(R.sessionFile(e.sessionId),t,{mode:384}),await this.reindex(e.sessionId)}async touch(e){if(!ln.test(e))return;let t=new Date;try{await xe.utimes(R.sessionFile(e),t,t)}catch(n){if(n.code!=="ENOENT")throw n;return}await this.reindex(e)}async markDeleted(e,t){await this.ensureIndex();let n=this.index.get(e);n&&!n.deleted||n&&n.mtimeMs>=t||this.index.set(e,{mtimeMs:t,deleted:!0})}async cursor(){await this.ensureIndex();let e=0;for(let t of this.index.values())t.mtimeMs>e&&(e=t.mtimeMs);return e}async listChangedSince(e){let t=await this.cursor(),n=[],r=[];for(let[a,d]of this.index)d.mtimeMs<e||(d.deleted?r.push(a):n.push(a));let o=await Promise.all(n.map(a=>this.read(a).catch(()=>{}))),i=[];for(let a of o)a&&i.push(a);return{records:i,removed:r,cursor:t}}async ensureIndex(){this.index||(this.indexSeed||(this.indexSeed=this.seedIndex()),await this.indexSeed)}async seedIndex(){let e=new Map,t=[];try{t=await xe.readdir(R.sessionsDir())}catch(n){if(n.code!=="ENOENT")throw n}await Promise.all(t.map(async n=>{if(ln.test(n))try{let r=await xe.stat(R.sessionFile(n));e.set(n,{mtimeMs:r.mtimeMs,deleted:!1})}catch{}})),this.index=e}async reindex(e){if(this.indexSeed){await this.indexSeed;try{let t=await xe.stat(R.sessionFile(e));this.index.set(e,{mtimeMs:t.mtimeMs,deleted:!1})}catch{}}}async read(e){if(!ln.test(e))return;let t=await oe(R.sessionFile(e));if(t!==void 0)try{return up.parse(t)}catch{return}}async delete(e){if(ln.test(e)){this.indexSeed&&(await this.indexSeed,this.index.set(e,{mtimeMs:Date.now(),deleted:!0}));try{await xe.unlink(R.sessionFile(e))}catch(t){if(t.code!=="ENOENT")throw t}try{await xe.rmdir(R.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 xe.readdir(R.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 Kr(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}}Oe();Y();import*as pe from"fs/promises";import*as ge from"path";Y();import*as Xn from"path";import{createHash as fp}from"crypto";var Me=class extends Error{constructor(e,t){super(`provider "${e}" does not support ${t}; check capabilities().supports before calling`),this.name="WorkspaceUnsupportedError"}};function Dt(s){let e=fp("sha256").update(Xn.resolve(s)).digest("hex").slice(0,12);return Xn.join(B(),"workspaces",e)}async function Zn(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 mt(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 Qr(s){return s.changedPaths.length>0||s.recorded!==void 0&&s.recorded!==s.actual}function pp(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 Yr(s,e){let t=new Set(e.map(r=>r.relPath));return[...s.filter(r=>!t.has(r.replace(/\/$/,""))),...pp(e.filter(Qr))]}function es(s){let e=s.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return e.length>0?e.slice(0,64):"workspace"}var Xr="copy",Oa=new Set([".git"]);function pn(s){return`${s}.manifest.json`}async function Fa(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 pe.readdir(n,{withFileTypes:!0})}catch{continue}for(let o of r){let i=ge.join(n,o.name);if(!(n===s&&Oa.has(o.name))){if(o.isDirectory()){t.push(i);continue}if(o.isFile())try{let a=await pe.stat(i);e.set(ge.relative(s,i),{size:a.size,mtimeMs:a.mtimeMs})}catch{continue}}}}return e}var ts=class{kind=Xr;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=ge.resolve(e.sourceCwd),n=e.contentFrom!==void 0?ge.resolve(e.contentFrom):t;try{if(!(await pe.stat(n)).isDirectory())return{ok:!1,reason:`${n} is not a directory`}}catch{return{ok:!1,reason:`${n} does not exist`}}let r=Dt(t);try{await pe.mkdir(r,{recursive:!0})}catch(c){return{ok:!1,reason:`could not create workspace root: ${String(c)}`}}let o=await Zn(es(e.label),async c=>pe.access(ge.join(r,c)).then(()=>!1).catch(()=>!0));if(o===void 0)return{ok:!1,reason:`no free name available for "${e.label}"`};let i=ge.join(r,o);try{await pe.cp(n,i,{recursive:!0,errorOnExist:!1,force:!0,filter:c=>{let u=ge.relative(n,c);if(u.length===0)return!0;let l=u.split(ge.sep)[0];return l===void 0||!Oa.has(l)}})}catch(c){return await pe.rm(i,{recursive:!0,force:!0}).catch(()=>{}),{ok:!1,reason:`copy failed: ${String(c)}`}}let a=await Fa(i),d={sourceCwd:t,label:o,createdAt:new Date().toISOString(),entries:Object.fromEntries(a)};return await ue(pn(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 pe.rm(e.path,{recursive:!0,force:!0}),await pe.rm(pn(e.path),{force:!0})}async listWorkspaces(e){let t=Dt(ge.resolve(e)),n;try{n=await pe.readdir(t)}catch{return[]}let r=[];for(let o of n){if(o.endsWith(".manifest.json"))continue;let i=ge.join(t,o),a=await oe(pn(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 oe(pn(e.path)),n=await Fa(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:`,...mt(t.map(r=>` ${r}`))];return n.push(`Not tracking ${F(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 Me(this.kind,"captureWorkingState")}async record(){throw new Me(this.kind,"record")}async attributeOrphan(e){let t=await oe(pn(e));if(t?.sourceCwd!==void 0)return{path:e,sourceCwd:t.sourceCwd,label:t.label??ge.basename(e),provider:this.kind}}async discardLine(){return{ok:!0,dropped:0}}ownsLine(){return!1}async pruneStale(){}async changedPaths(){throw new Me(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 Me(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 Me(this.kind,"lock")}async unlock(){throw new Me(this.kind,"unlock")}};Y();import{execFile as La}from"child_process";import{randomBytes as yp}from"crypto";import*as _e from"fs/promises";import*as Ua from"os";import*as Z from"path";function gp(s){let e=s.indexOf(" ");return e===-1?{key:s,value:""}:{key:s.slice(0,e),value:s.slice(e+1)}}function Na(s){let e=[],t,n=()=>{t!==void 0&&(e.push(t),t=void 0)};for(let r of s.split(`
111
+ `)){let o=r.replace(/\r$/,"");if(o.length===0){n();continue}let{key:i,value:a}=gp(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 Da(s){if(s===void 0)return;let e="refs/heads/";return s.startsWith(e)?s.slice(e.length):s}var rs="git",ja="hydra-acp:",Zr="hydra",z=5e3,de=12e4,ns=9e5;function Ha(s){return _e.access(s).then(()=>!0).catch(()=>!1)}function wp(s){return _e.realpath(s).catch(()=>s)}function j(s,e,t,n){return new Promise(r=>{La("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 eo(s,e,t,n=de){return new Promise(r=>{let o=La("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 to(s){let e=[];for(let t of s.split(`
112
+ `)){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 ss=class{kind=rs;refRoot(e){return e.vcs?.repoRoot??e.sourceCwd}ownsLine(e){return e.startsWith(`${Zr}/`)}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 Ha(Z.join(e.path,".gitmodules")))return{ok:!0,count:0};let r=await j(["submodule","update","--init","--recursive",...t?.discardLocal===!0?["--force"]:[]],e.path,ns);if(!r.ok)return{ok:!1,count:0,reason:r.stderr.trim()||"git submodule update --init failed"};if(t?.discardLocal===!0){let a=await j(["submodule","foreach","--recursive","git","reset","--hard"],e.path,ns);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 j(["submodule","foreach","--recursive","git","clean",d],e.path,ns);if(!c.ok)return{ok:!1,count:0,reason:c.stderr.trim()||"could not clean submodules"}}let o=await j(["submodule","status","--recursive"],e.path,z);return{ok:!0,count:o.ok?o.stdout.split(`
113
+ `).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 Ha(n))return{ok:!1,reason:`source repository ${n} no longer exists`};let r=await j(["rev-parse","--verify","--quiet",`refs/heads/${t}`],n,z);if(!r.ok||r.stdout.trim().length===0)return{ok:!1,reason:`branch ${t} no longer exists in ${n}`};await j(["worktree","unlock",e.path],n,z),await j(["worktree","prune"],n,z);let o=await j(["worktree","add",e.path,t],n,de);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=Z.resolve(e.sourceCwd),n=await j(["rev-parse","--show-toplevel"],t,z);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 j(["rev-parse","HEAD"],r,z);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=es(e.label),d=Dt(t);try{await _e.mkdir(d,{recursive:!0})}catch(m){return{ok:!1,reason:`could not create workspace root: ${String(m)}`}}let c=await Zn(a,async m=>await _e.access(Z.join(d,m)).then(()=>!0).catch(()=>!1)?!1:!(await j(["rev-parse","--verify","--quiet",`refs/heads/${Zr}/${m}`],r,z)).ok);if(c===void 0)return{ok:!1,reason:`no free name available for "${a}"`};let u=Z.join(d,c),l=`${Zr}/${c}`,p=await j(["worktree","add","--no-track","-b",l,u,i],r,de);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 j(["worktree","remove","--force",e.path],n,de);t.discardLine===!0&&e.vcs?.branch!==void 0&&await j(["branch","-D",e.vcs.branch],n,z),r.ok||(await _e.rm(e.path,{recursive:!0,force:!0}),await j(["worktree","prune"],n,z))}async listWorkspaces(e){let t=Z.resolve(e),n=await j(["rev-parse","--show-toplevel"],t,z);if(!n.ok)return[];let r=n.stdout.trim(),o=await j(["worktree","list","--porcelain"],r,z);if(!o.ok)return[];let i=Dt(t),a=await wp(i),d=[];for(let c of Na(o.stdout)){let u=Z.dirname(c.path);if(u!==i&&u!==a)continue;let l=Z.join(i,Z.basename(c.path)),p={kind:"git",repoRoot:r},m=Da(c.branch);m!==void 0&&(p.branch=m),c.head!==void 0&&(p.head=c.head),c.lockedReason!==void 0&&(p.locked=c.lockedReason);let h=c.lockedReason?.startsWith(ja)===!0;d.push({path:l,sourceCwd:t,label:Z.basename(l),...h?{heldByUs:!0}:{},provider:this.kind,...m!==void 0?{line:m}:{},vcs:p})}return d}async status(e){let t=await j(["status","--porcelain","--untracked-files=all"],e.path,z);if(!t.ok)return{clean:!1,changedPaths:[],hasRecordedWork:!1};let n=to(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 j(["rev-list","--count",`${e.snapshot}..HEAD`],e.path,z);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 j(["worktree","lock","--reason",`${ja}${t}`,e.path],n,z)}async unlock(e){let t=this.refRoot(e);await j(["worktree","unlock",e.path],t,z)}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 _e.access(Z.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 j(["status","--porcelain","--untracked-files=all"],e.path,z);if(n.ok){let r=to(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(...mt(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([j(["rev-parse","HEAD"],e.sourceCwd,z),j(["rev-parse","HEAD"],e.path,z)]),r=t.stdout.trim(),o=n.stdout.trim();if(!t.ok||!n.ok||r.length===0||o.length===0)return[];let i=F(e.sourceCwd);if(r===o)return[`in sync with ${i}`];let a=await j(["rev-list","--left-right","--count",`${r}...${o}`],e.path,z),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=Z.join(Ua.tmpdir(),`hydra-index-${process.pid}-${yp(6).toString("hex")}`),r={GIT_INDEX_FILE:n};try{let o=await j(["rev-parse","--verify","HEAD"],e,z),i=o.ok&&o.stdout.trim().length>0;if(i){let l=await j(["read-tree","HEAD"],e,de,r);if(!l.ok)throw new Error(`could not seed the snapshot index: ${l.stderr.trim()}`)}let a=await j(["add","-A"],e,de,r);if(!a.ok)throw new Error(`could not stage working state: ${a.stderr.trim()}`);let d=await j(["write-tree"],e,de,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 j(c,e,de,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 _e.rm(n,{force:!0}).catch(()=>{})}}async retainSnapshot(e,t,n){let r=this.refRoot(e);await j(["update-ref","--create-reflog",t,n],r,z)}async dropSnapshotRef(e,t){let n=this.refRoot(e);await j(["update-ref","-d",t],n,z)}async currentState(e){let t=await j(["rev-parse","HEAD"],e,z),n=t.stdout.trim();return t.ok&&n.length>0?n:void 0}async contentId(e,t){let n=await j(["rev-parse",`${t}^{tree}`],e,z),r=n.stdout.trim();return n.ok&&r.length>0?r:void 0}async currentLineName(e){let t=await j(["rev-parse","--abbrev-ref","HEAD"],e,z),n=t.stdout.trim();return t.ok&&n.length>0?n:void 0}async resolveRoot(e){let t=await j(["rev-parse","--show-toplevel"],e,z),n=t.stdout.trim();return t.ok&&n.length>0?n:void 0}async resolveRetained(e,t){let n=await j(["rev-parse","--verify","--quiet",`${t}^{commit}`],this.refRoot(e),z),r=n.stdout.trim();return n.ok&&r.length>0?r:void 0}async contains(e,t){return(await j(["merge-base","--is-ancestor",t.state,t.within],e,z)).ok}async divergence(e,t,n){let r=await j(["rev-list","--left-right","--count",`${t}...${n}`],e,z);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 j(["diff","--name-only",t,n],e,z);return r.ok?r.stdout.split(`
114
+ `).map(o=>o.replace(/\r$/,"").trim()).filter(o=>o.length>0):[]}async captureDelta(e,t,n){let r=await j(["diff","--binary","--ignore-submodules=all",t,n],e,de);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 eo(["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 eo(["apply","--reverse","--check"],e,t)).ok)return{ok:!0,alreadyPresent:!0};let a=await eo(["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 j(["reset","--hard",t],e,de);if(!r.ok)return{ok:!1,reason:r.stderr.trim()||"could not return to that state"};let o=await j(["clean",n?.purgeIgnored===!0?"-ffdx":"-fd"],e,de);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 j(["rev-parse","-q","--verify","MERGE_HEAD"],e,z)).ok}async abortIntegration(e){await j(["merge","--abort"],e,de)}async conflictedPaths(e){let t=await j(["diff","--name-only","--diff-filter=U"],e,z);return t.ok?t.stdout.split(`
115
+ `).map(n=>n.replace(/\r$/,"").trim()).filter(n=>n.length>0):[]}async record(e,t){let n=await j(["add","-A"],e.path,de);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 j(["commit","-m",t],e.path,de);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 j(["rev-parse","--path-format=absolute","--git-common-dir"],e,z),n=t.stdout.trim();if(!t.ok||n.length===0)return;let r=Z.dirname(n),o=await this.currentLineName(e);return{path:e,sourceCwd:r,label:Z.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 j(["branch","-D",t],n,z);return i.ok?{ok:!0,dropped:o}:{ok:!1,dropped:o,reason:i.stderr.trim()||"could not discard the line"}}async pruneStale(e){await j(["worktree","prune"],this.refRoot(e),z)}async changedPaths(){throw new Me(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 j(o,t,de);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 j(["submodule","status","--recursive"],e,de);if(!t.ok)return[];let n=[];for(let r of t.stdout.split(`
116
+ `)){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||!kp(e,c))continue;let u=Z.join(e,c),[l,p,m]=await Promise.all([this.currentState(u),j(["rev-parse",`HEAD:${c}`],e,z),j(["status","--porcelain","--untracked-files=all"],u,z)]);if(l===void 0)continue;let h=p.ok?p.stdout.trim():"";n.push({relPath:c,actual:l,...h.length>0?{recorded:h}:{},changedPaths:m.ok?to(m.stdout).map(f=>f.path):[]})}return n}async captureNested(e,t){let n=[];for(let r of t){if(!Qr(r))continue;if(r.changedPaths.length===0){n.push(r);continue}let o=Z.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=Z.join(e,i.relPath),d=Z.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(g=>g.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,m=l?.delta!==void 0;if(!p&&!m)continue;if(u.changedPaths.length>0){o.push({path:c,reason:`it has ${u.changedPaths.length} uncommitted change(s) of its own, and nothing can tell those apart from what was integrated`});continue}let h=Z.join(e,c),f=Z.join(t,c);if(p&&u.recorded!==void 0){let g=await this.alignNested(h,f,u.recorded);if(g!==void 0){o.push({path:c,reason:g});continue}}if(l?.delta!==void 0){let g=await this.applyDelta(h,l.delta);if(!g.ok){o.push({path:c,reason:g.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 j(["cat-file","-e",`${n}^{commit}`],e,z)).ok&&!(await j(["fetch","--no-tags",t,n],e,ns)).ok)return`could not transfer ${n.slice(0,8)} from the other copy`;if(!(await j(["checkout","--detach",n],e,de)).ok)return`could not move to ${n.slice(0,8)}`}};function kp(s,e){if(Z.isAbsolute(e))return!1;let t=Z.resolve(s),n=Z.resolve(t,e);return n!==t&&n.startsWith(t+Z.sep)}var vp=rs,bp=new Map([[rs,new ss],[Xr,new ts]]);function ne(s){return bp.get(s??vp)}var os="refs/hydra";function gn(s){let e=`${os}/workspaces/${s}`;return{autosave:`${e}/autosave`,start:`${e}/start`,baseline:`${e}/baseline`}}function no(s){return`${os}/landing/${s}`}function Ba(s){return`${os}/sync/${s}`}function Wa(s,e){return`${os}/retired/${s}-${e.slice(0,12)}`}function qa(s){let e=gn(s);return[e.autosave,e.start,e.baseline]}async function so(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 ht(s){let{source:e,capture:t,provider:n}=s;if(t.clean||t.snapshot===void 0||n===void 0)return!0;let r=await n.captureDelta(e,t.base,t.snapshot).catch(()=>{});return r===void 0?!1:(await n.applyDelta(e,r,{tolerant:!0})).ok}async function mn(s){s.capture.retainedRef===void 0||s.provider===void 0||await s.provider.dropSnapshotRef({...s.ws,path:s.source},s.capture.retainedRef).catch(()=>{})}Oe();import{execFile as Sp}from"child_process";import*as ze from"fs/promises";import*as Ae from"path";var Ip=".hydra/worktree.json",Ap=".worktreeinclude",Cp=120;async function is(s){let e=await oe(Ae.join(s,Ip))??{},t=new Set(Array.isArray(e.carry)?e.carry:[]),n=await ze.readFile(Ae.join(s,Ap),"utf8").catch(()=>{});if(n!==void 0)for(let o of n.split(`
117
+ `)){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 ro(s,e,t){let n=[],r=[],o=Ae.resolve(s),i=Ae.resolve(e);for(let a of t){let d=Ae.resolve(o,a),c=Ae.resolve(i,a);if(!d.startsWith(o+Ae.sep)||!c.startsWith(i+Ae.sep)){r.push(a);continue}if(await ze.access(c).then(()=>!0).catch(()=>!1)){r.push(a);continue}let l=await ze.stat(d).catch(()=>{});if(l===void 0){r.push(a);continue}try{await ze.mkdir(Ae.dirname(c),{recursive:!0}),await ze.cp(d,c,{recursive:l.isDirectory()}),n.push(a)}catch{r.push(a)}}return{copied:n,skipped:r}}async function as(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??Cp)*1e3;return new Promise(r=>{let o=Sp("/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)})}Y();Oe();import*as Qe from"fs/promises";import{z as $e}from"zod";var Rp=$e.object({version:$e.literal(1),agentId:$e.string(),upstreamSessionId:$e.string(),sessionId:$e.string().optional(),deletedAt:$e.string(),upstreamUpdatedAt:$e.string().optional(),cwd:$e.string().optional(),title:$e.string().optional(),reason:$e.enum(["user","expired"]).optional(),interactive:$e.boolean().optional()}),ds=class{async add(e){let t={version:1,...e};await ue(R.tombstoneFile(e.agentId,e.upstreamSessionId),t,{mode:384})}async has(e,t){try{return await Qe.access(R.tombstoneFile(e,t)),!0}catch{return!1}}async read(e,t){let n=R.tombstoneFile(e,t),r=await oe(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 Rp.parse(r)}catch{return{version:1,agentId:e,upstreamSessionId:t,deletedAt:new Date(0).toISOString()}}}async remove(e,t){try{await Qe.unlink(R.tombstoneFile(e,t))}catch(n){if(n.code!=="ENOENT")throw n}try{await Qe.rmdir(R.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 Qe.readdir(R.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 Qe.readdir(R.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 za(s,e){return s.reason==="user"||e===void 0?!1:s.upstreamUpdatedAt===void 0?!0:e>s.upstreamUpdatedAt}import*as rd from"fs/promises";import{customAlphabet as Fp}from"nanoid";import{fileURLToPath as xp}from"url";import*as hn from"path";import*as cs from"fs";function Ep(){try{let s=hn.dirname(xp(import.meta.url));for(let e=0;e<8;e+=1){let t=hn.join(s,"package.json");if(cs.existsSync(t)){let r=JSON.parse(cs.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=hn.dirname(s);if(n===s)break;s=n}}catch{}return"0.0.0"}var me=Ep(),us="hydra-acp-cat";var Tp=12e4;async function Va(s,e,t){let n=s.timeoutMs??Tp,r,o,i=!1;try{let a=(async()=>{r=st.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:me}}),c=await r.connection.request("session/new",{cwd:s.cwd,mcpServers:[]}),u=c.sessionId;if(typeof u!="string"){s.logger?.warn(`synopsis: agent ${s.agentId} returned non-string sessionId from session/new`),s.onFailure?.(`agent ${s.agentId} did not return a sessionId from session/new`);return}if(s.onWorkerSpawned?.(u,r.pid),s.modelId){let h=Mp(c);if(h.size===0||h.has(s.modelId)){let f=r.connection;try{await rt({request:(g,w)=>f.request(g,w),sessionId:u,modelId:s.modelId,verb:Et(c),logger:s.logger})}catch(g){s.logger?.warn(`synopsis: agent ${s.agentId} rejected model change to ${JSON.stringify(s.modelId)}: ${g.message}; continuing on default`)}}else s.logger?.warn(`synopsis: model ${JSON.stringify(s.modelId)} not advertised by agent ${s.agentId} (have [${[...h].join(", ")}]); continuing on default`)}let l=[];r.connection.onNotification("session/update",h=>{let f=Pp(h);f.length>0&&l.push(f)}),await r.connection.request("session/prompt",{sessionId:u,prompt:[{type:"text",text:e}]});let p=l.join(""),m=t(p);if(!m){let h=JSON.stringify(p.slice(0,200));s.logger?.warn(`synopsis: agent ${s.agentId} reply did not parse (replyLen=${p.length} preview=${h})`);let f=p.slice(0,120).replace(/\s+/g," ").trim();s.onFailure?.(`agent ${s.agentId} returned unparseable JSON (${p.length} chars): ${f}${p.length>120?"\u2026":""}`)}return m})();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 ls(s){let e=$t(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}
118
118
 
119
119
  ${e}
120
120
 
121
- ${Cr}`:`${t}
121
+ ${Wr}`:`${t}
122
122
 
123
- ${Cr}`;return Ia(s,n,aa)}async function Aa(s){let e=At(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
+ ${Wr}`;return Va(s,n,Ma)}async function Ga(s){let e=$t(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}
124
124
 
125
125
  ${e}
126
126
 
127
- ${xr}`:`${t}
127
+ ${qr}`:`${t}
128
128
 
129
- ${xr}`;return Ia(s,n,da)}function ep(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 tp(s){let e=new Set;Sa(e,s.availableModels);let t=s.models;return t&&typeof t=="object"&&!Array.isArray(t)&&Sa(e,t.availableModels),e}function Sa(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 np(s){let e=new Map;for(let t of Pa(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 np(s).map(e=>e.name)}function sp(s){let e=new Map;for(let t of Pa(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 Ea(s){return sp(s).map(e=>e.path)}function Ta(s){let e=0;for(let t of s)t.params?.update?.sessionUpdate==="prompt_received"&&(e+=1);return e}function Pa(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:Ca(o),paths:new Set},e.set(d,c)):c.toolName=Ca(o);for(let u of xa(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 xa(o.rawInput,o.locations))a.paths.add(d)}return e}function Ca(s){return typeof s.name=="string"&&s.name.length>0?s.name:typeof s.title=="string"&&s.title.length>0?s.title:"(unnamed)"}function xa(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 Ti(e))t.add(n);return t}Q();var op=rp("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",12),ip=2,es=class{constructor(e){this.opts=e;this.maxConcurrent=e.maxConcurrent??ip}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=A.sessionDir(e);if(await Oa.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=op(),v={targetAgentId:r},x=R=>this.opts.onCompactionStateChange?.(e,{runId:I,...R},v)??Promise.resolve(),E=R=>{this.opts.broadcastHydraCompaction?.(e,R,v)};await x({status:"requested",requestedAt:b}),E({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 R=await this.opts.histories.load(e,{maxEntries:1/0});if(R.length===h)break;let M=await Aa({agentId:d,cwd:f,plan:u,history:R,modelId:p,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs,onWorkerSpawned:(D,q)=>{x({status:"running",requestedAt:b,iter:g,worker:{upstreamSessionId:D,pid:q??0}})},onFailure:D=>{y=D}});if(M){let D=Ma(M.synopsis,R);D&&_a(D)&&(await this.opts.persistSynopsis(e,D,R.length),w=D,k=R.length,y=void 0,await x({status:"running",requestedAt:b,iter:g}),E({sessionUpdate:"_hydra_compaction",phase:"iteration",iter:g,historyLen:R.length}),await this.opts.onSynthesisArtifact?.(e,D,k,r,I),this.opts.logger?.info(`synopsis: persisted compaction sessionId=${e} iteration=${g} fields=${$a(D)}`))}else this.opts.logger?.warn(`synopsis: sessionId=${e} compaction iteration ${g} returned no result`);if(h=R.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})`:"")),E({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 R=y??(g===0?"no new history to compact since last summary":`compaction did not produce an artifact after ${g} iteration(s)`);await x({status:"failed",requestedAt:b,iter:g,lastError:R}),E({sessionUpdate:"_hydra_compaction",phase:"failed",error:R}),r&&await this.opts.onSynthesisUnavailable?.(e,r,R)}}catch(R){let M=R instanceof Error?R.message:String(R);if(this.opts.logger?.warn(`synopsis: compaction threw for sessionId=${e}: ${M}`),await x({status:"failed",requestedAt:b,iter:g,lastError:M}),this.opts.broadcastHydraCompaction?.(e,{sessionUpdate:"_hydra_compaction",phase:"failed",error:M},{targetAgentId:r}),r)try{await this.opts.onSynthesisUnavailable?.(e,r,M)}catch{}}}else{let m=await Zn({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=Ma(m.synopsis,i);g&&_a(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=${$a(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 Ma(s,e){let t=Ea(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 _a(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 $a(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 K from"fs/promises";import{createReadStream as pp}from"fs";import{createGunzip as gp,gzip as mp,gunzip as hp}from"zlib";import{createInterface as yp}from"readline";import{promisify as La}from"util";function Fa(s){return s==="summary"?"summary":"inline"}var Ur=256,ap=["totalMatches","totalFiles","referenceCount","truncated","exitCode"],dp=["content","stdout","stderr"];function Na(s,e){return e!=="summary"?s:s.map(cp)}function cp(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(Da));let i=r.rawOutput;if(i&&typeof i=="object"&&!Array.isArray(i)){let a=i,d={};a.error!==void 0&&(d.error=ts(a.error)),a.metadata!==void 0&&(d.metadata=a.metadata);for(let c of ap)a[c]!==void 0&&(d[c]=a[c]);for(let c of dp)typeof a[c]=="string"&&(d[c]=ts(a[c]));o.rawOutput=d}return{...s,params:{...t,update:o}}}function up(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&s.type==="diff"}function Da(s){if(up(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=ts(e.text)),typeof e.content=="string"?t.content=ts(e.content):e.content&&typeof e.content=="object"&&(t.content=Da(e.content)),t}function ts(s){if(typeof s=="string"&&s.length>Ur){let e=s.length-Ur;return`${s.slice(0,Ur)}\u2026[+${e} chars omitted from summary export]`}return s}var lp=2048;function ja(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 fp(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 qr(s,e){if(!fp(s))return s;let t=s.params,n=t.update,r=await Br(n,e);return{...s,params:{...t,update:r}}}async function Br(s,e){if(typeof s=="string"){if(s.length<=lp)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 Br(n,e));return t}if(s&&typeof s=="object"){let t={};for(let[n,r]of Object.entries(s))t[n]=await Br(r,e);return t}return s}async function zr(s,e){let t=s.params;if(!t||typeof t!="object"||Array.isArray(t))return s;let n=await Wr(t,e);return n===t?s:{...s,params:n}}async function Wr(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 Wr(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 Wr(o,e);i!==o&&(t=!0),n[r]=i}return t?n:s}return s}var wp=La(mp),kp=La(hp),vp=/^history\.jsonl\.(\d+)(\.gz)?$/,Pe=/^[A-Za-z0-9_-]+$/,bp=1e3,Sp=1e7,Ip=10,ns=class{writeQueues=new Map;maxEntries;archiveMaxBytes;archiveTiers;nextArchiveIndex=new Map;archiveLineCounts=new Map;constructor(e={}){this.maxEntries=e.maxEntries??bp,this.archiveMaxBytes=e.archiveMaxBytes??Sp,this.archiveTiers=e.archiveTiers??Ip}async append(e,t){if(Pe.test(e))return this.enqueue(e,async()=>{await K.mkdir(A.sessionDir(e),{recursive:!0});let n=await qr(t,o=>Js(e,o)),r=JSON.stringify(n)+`
130
- `;await K.appendFile(A.historyFile(e),r,{encoding:"utf8",mode:384})})}async rewrite(e,t){if(Pe.test(e))return this.enqueue(e,async()=>{await K.mkdir(A.sessionDir(e),{recursive:!0});let n=[];for(let o of t)n.push(await qr(o,i=>Js(e,i)));let r=n.length===0?"":n.map(o=>JSON.stringify(o)).join(`
129
+ ${qr}`;return Va(s,n,_a)}function Pp(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 Mp(s){let e=new Set;Ja(e,s.availableModels);let t=s.models;return t&&typeof t=="object"&&!Array.isArray(t)&&Ja(e,t.availableModels),e}function Ja(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 _p(s){let e=new Map;for(let t of ed(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 Ya(s){return _p(s).map(e=>e.name)}function $p(s){let e=new Map;for(let t of ed(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 $p(s).map(e=>e.path)}function Za(s){let e=0;for(let t of s)t.params?.update?.sessionUpdate==="prompt_received"&&(e+=1);return e}function ed(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:Ka(o),paths:new Set},e.set(d,c)):c.toolName=Ka(o);for(let u of Qa(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 Qa(o.rawInput,o.locations))a.paths.add(d)}return e}function Ka(s){return typeof s.name=="string"&&s.name.length>0?s.name:typeof s.title=="string"&&s.title.length>0?s.title:"(unnamed)"}function Qa(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 Zi(e))t.add(n);return t}Y();var Op=Fp("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",12),Np=2,fs=class{constructor(e){this.opts=e;this.maxConcurrent=e.maxConcurrent??Np}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 Re(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,m=R.sessionDir(e);if(await rd.mkdir(m,{recursive:!0}).catch(()=>{}),this.opts.logger?.info(`synopsis: start sessionId=${e} agentId=${d} historyLen=${i.length} model=${JSON.stringify(p??"(default)")} cwd=${m}`),n==="compaction"){let h=this.opts.compactionMaxIterations??3,f=0,g=a??0,w,y=0,k,b=Date.now(),S=Op(),v={targetAgentId:r},E=C=>this.opts.onCompactionStateChange?.(e,{runId:S,...C},v)??Promise.resolve(),A=C=>{this.opts.broadcastHydraCompaction?.(e,C,v)};await E({status:"requested",requestedAt:b}),A({sessionUpdate:"_hydra_compaction",phase:"started",requestedAt:b});try{do{f++,this.opts.logger?.info(`synopsis: compaction iteration ${f} sessionId=${e} historyLen=${i.length} watermark=${g}`);let C=await this.opts.histories.load(e,{maxEntries:1/0});if(C.length===g)break;let T=await Ga({agentId:d,cwd:m,plan:u,history:C,modelId:p,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs,onWorkerSpawned:(H,J)=>{E({status:"running",requestedAt:b,iter:f,worker:{upstreamSessionId:H,pid:J??0}})},onFailure:H=>{k=H}});if(T){let H=td(T.synopsis,C);H&&nd(H)&&(await this.opts.persistSynopsis(e,H,C.length),w=H,y=C.length,k=void 0,await E({status:"running",requestedAt:b,iter:f}),A({sessionUpdate:"_hydra_compaction",phase:"iteration",iter:f,historyLen:C.length}),await this.opts.onSynthesisArtifact?.(e,H,y,r,S),this.opts.logger?.info(`synopsis: persisted compaction sessionId=${e} iteration=${f} fields=${sd(H)}`))}else this.opts.logger?.warn(`synopsis: sessionId=${e} compaction iteration ${f} returned no result`);if(g=C.length,(await this.opts.histories.load(e,{maxEntries:1/0})).length===g)break}while(f<h);if(w)this.opts.logger?.info(`synopsis: compaction converged sessionId=${e} runId=${S} watermark=${y} iterations=${f}`+(f>=h?` (hit maxIterations=${h})`:"")),A({sessionUpdate:"_hydra_compaction",phase:"converged",iter:f,summarizedThroughEntry:y});else{f>0&&this.opts.logger?.warn(`synopsis: compaction hit maxIterations=${h} without producing artifact sessionId=${e}: ${k??"no reason captured"}`);let C=k??(f===0?"no new history to compact since last summary":`compaction did not produce an artifact after ${f} iteration(s)`);await E({status:"failed",requestedAt:b,iter:f,lastError:C}),A({sessionUpdate:"_hydra_compaction",phase:"failed",error:C}),r&&await this.opts.onSynthesisUnavailable?.(e,r,C)}}catch(C){let T=C instanceof Error?C.message:String(C);if(this.opts.logger?.warn(`synopsis: compaction threw for sessionId=${e}: ${T}`),await E({status:"failed",requestedAt:b,iter:f,lastError:T}),this.opts.broadcastHydraCompaction?.(e,{sessionUpdate:"_hydra_compaction",phase:"failed",error:T},{targetAgentId:r}),r)try{await this.opts.onSynthesisUnavailable?.(e,r,T)}catch{}}}else{let h=await ls({agentId:d,cwd:m,plan:u,history:i,modelId:p,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs});if(!h){this.opts.logger?.warn(`synopsis: sessionId=${e} no parseable result; not persisting`);return}let f=td(h.synopsis,i);f&&nd(f)?(await this.opts.persistSynopsis(e,f,i.length),h.title&&await this.opts.persistTitle(e,h.title),this.opts.logger?.info(`synopsis: persisted sessionId=${e} title=${JSON.stringify(!!h.title)} fields=${sd(f)}`)):h.title&&(await this.opts.persistTitle(e,h.title),this.opts.logger?.info(`synopsis: persisted title only sessionId=${e}`))}}catch(o){this.opts.logger?.warn(`synopsis: sessionId=${e} failed: ${o.message}`)}}};function td(s,e){let t=Xa(e),n=Ya(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 nd(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 sd(s){let e=[];return s.goal&&e.push("goal"),s.outcome&&e.push("outcome"),s.files_touched&&s.files_touched.length>0&&e.push(`files=${s.files_touched.length}`),s.tools_used&&s.tools_used.length>0&&e.push(`tools=${s.tools_used.length}`),s.rejected_approaches&&s.rejected_approaches.length>0&&e.push(`rejected=${s.rejected_approaches.length}`),s.open_threads&&s.open_threads.length>0&&e.push(`open=${s.open_threads.length}`),`[${e.join(",")}]`}Y();import*as Q from"fs/promises";import{createReadStream as Wp}from"fs";import{createGunzip as qp,gzip as zp,gunzip as Jp}from"zlib";import{createInterface as Vp}from"readline";import{promisify as ud}from"util";function od(s){return s==="summary"?"summary":"inline"}var oo=256,Dp=["totalMatches","totalFiles","referenceCount","truncated","exitCode"],jp=["content","stdout","stderr"];function id(s,e){return e!=="summary"?s:s.map(Hp)}function Hp(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(ad));let i=r.rawOutput;if(i&&typeof i=="object"&&!Array.isArray(i)){let a=i,d={};a.error!==void 0&&(d.error=ps(a.error)),a.metadata!==void 0&&(d.metadata=a.metadata);for(let c of Dp)a[c]!==void 0&&(d[c]=a[c]);for(let c of jp)typeof a[c]=="string"&&(d[c]=ps(a[c]));o.rawOutput=d}return{...s,params:{...t,update:o}}}function Lp(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&s.type==="diff"}function ad(s){if(Lp(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=ps(e.text)),typeof e.content=="string"?t.content=ps(e.content):e.content&&typeof e.content=="object"&&(t.content=ad(e.content)),t}function ps(s){if(typeof s=="string"&&s.length>oo){let e=s.length-oo;return`${s.slice(0,oo)}\u2026[+${e} chars omitted from summary export]`}return s}var Up=2048;function dd(s){let e=new Set,t=n=>{if(cd(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 cd(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&typeof s.__hydraBlob=="string"}function Bp(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 co(s,e){if(!Bp(s))return s;let t=s.params,n=t.update,r=await io(n,e);return{...s,params:{...t,update:r}}}async function io(s,e){if(typeof s=="string"){if(s.length<=Up)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 io(n,e));return t}if(s&&typeof s=="object"){let t={};for(let[n,r]of Object.entries(s))t[n]=await io(r,e);return t}return s}async function uo(s,e){let t=s.params;if(!t||typeof t!="object"||Array.isArray(t))return s;let n=await ao(t,e);return n===t?s:{...s,params:n}}async function ao(s,e){if(cd(s))return await e(s.__hydraBlob)??"";if(Array.isArray(s)){let t=!1,n=[];for(let r of s){let o=await ao(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 ao(o,e);i!==o&&(t=!0),n[r]=i}return t?n:s}return s}var Gp=ud(zp),Kp=ud(Jp),Qp=/^history\.jsonl\.(\d+)(\.gz)?$/,Fe=/^[A-Za-z0-9_-]+$/,Yp=1e3,Xp=1e7,Zp=10,gs=class{writeQueues=new Map;maxEntries;archiveMaxBytes;archiveTiers;nextArchiveIndex=new Map;archiveLineCounts=new Map;constructor(e={}){this.maxEntries=e.maxEntries??Yp,this.archiveMaxBytes=e.archiveMaxBytes??Xp,this.archiveTiers=e.archiveTiers??Zp}async append(e,t){if(Fe.test(e))return this.enqueue(e,async()=>{await Q.mkdir(R.sessionDir(e),{recursive:!0});let n=await co(t,o=>ur(e,o)),r=JSON.stringify(n)+`
130
+ `;await Q.appendFile(R.historyFile(e),r,{encoding:"utf8",mode:384})})}async rewrite(e,t){if(Fe.test(e))return this.enqueue(e,async()=>{await Q.mkdir(R.sessionDir(e),{recursive:!0});let n=[];for(let o of t)n.push(await co(o,i=>ur(e,i)));let r=n.length===0?"":n.map(o=>JSON.stringify(o)).join(`
131
131
  `)+`
132
- `;await K.writeFile(A.historyFile(e),r,{encoding:"utf8",mode:384})})}async compact(e,t){if(Pe.test(e))return this.enqueue(e,async()=>{let n;try{n=await K.readFile(A.historyFile(e),"utf8")}catch(a){if(a.code==="ENOENT")return;throw a}let r=n.split(`
133
- `).filter(a=>a.length>0);if(r.length<=t)return;let o=r.slice(0,r.length-t),i=r.slice(-t);this.archiveMaxBytes>0&&o.length>0&&await this.spillToArchive(e,o),await K.writeFile(A.historyFile(e),i.join(`
132
+ `;await Q.writeFile(R.historyFile(e),r,{encoding:"utf8",mode:384})})}async compact(e,t){if(Fe.test(e))return this.enqueue(e,async()=>{let n;try{n=await Q.readFile(R.historyFile(e),"utf8")}catch(a){if(a.code==="ENOENT")return;throw a}let r=n.split(`
133
+ `).filter(a=>a.length>0);if(r.length<=t)return;let o=r.slice(0,r.length-t),i=r.slice(-t);this.archiveMaxBytes>0&&o.length>0&&await this.spillToArchive(e,o),await Q.writeFile(R.historyFile(e),i.join(`
134
134
  `)+`
135
135
  `,{encoding:"utf8",mode:384})})}async spillToArchive(e,t){let n=t.join(`
136
136
  `)+`
137
- `,r=await this.resolveNextArchiveIndex(e);await this.enforceArchiveTierCap(e,r);let o=A.historyArchiveFile(e,r);await K.mkdir(A.sessionDir(e),{recursive:!0}),await K.appendFile(o,n,{encoding:"utf8",mode:384});let i=0;try{i=(await K.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=A.historyArchiveFile(e,t),r;try{r=await K.readFile(n)}catch(i){if(i.code==="ENOENT")return;throw i}let o=await wp(r);await K.writeFile(n+".gz",o,{mode:384});try{await K.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=A.historyArchiveFile(e,r),a=i+".gz",d=!1;try{await K.access(a),d=!0}catch{d=!1}if(d)o=r+1;else try{(await K.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=A.historyArchiveFile(e,t);for(let r of[n,n+".gz"])try{await K.unlink(r)}catch(o){if(o.code!=="ENOENT")throw o}this.archiveLineCounts.delete(e)}async listArchiveIndices(e){let t;try{t=await K.readdir(A.sessionDir(e))}catch(r){if(r.code==="ENOENT")return[];throw r}let n=new Set;for(let r of t){let o=vp.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(!Pe.test(e))return[];let t=await this.listArchiveIndices(e),n=[];for(let r of t){let o=A.historyArchiveFile(e,r),i=o+".gz",a=o;try{await K.access(i),a=i}catch{a=o}n.push({index:r,path:a})}return n}async loadArchives(e){if(!Pe.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 K.readFile(o);i=(await kp(a)).toString("utf8")}else i=await K.readFile(o,"utf8")}catch(a){if(a.code==="ENOENT")continue;throw a}for(let a of i.split(`
138
- `)){if(a.length===0)continue;let d;try{d=JSON.parse(a)}catch{continue}if(!d||typeof d!="object"||Array.isArray(d))continue;let c=d;typeof c.method=="string"&&typeof c.recordedAt=="number"&&r.push({method:c.method,params:c.params,recordedAt:c.recordedAt,...typeof c.seq=="number"?{seq:c.seq}:{}})}}return r}async*streamFile(e){let t;try{t=pp(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(gp()):t,o=yp({input:r,crlfDelay:1/0});try{for await(let i of o){if(i.length===0)continue;let a;try{a=JSON.parse(i)}catch{continue}if(!a||typeof a!="object"||Array.isArray(a))continue;let d=a;typeof d.method=="string"&&typeof d.recordedAt=="number"&&(yield{method:d.method,params:d.params,recordedAt:d.recordedAt,...typeof d.seq=="number"?{seq:d.seq}:{}})}}finally{o.close(),t.destroy()}}async getArchiveLineCounts(e){if(!Pe.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 zr(t,async r=>{let o=n.get(r);if(o!==void 0)return o;let i=await zt(e,r);return n.set(r,i),i})}async*iterRecallNewestFirst(e){if(!Pe.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(A.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(!Pe.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(A.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(!Pe.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(A.historyFile(e)))r+=1;return n+r}async load(e,t={}){if(!Pe.test(e))return[];let n=(t.tools??"inline")==="inline",r=this.writeQueues.get(e);r&&await r;let o;try{o=await K.readFile(A.historyFile(e),"utf8")}catch(p){if(p.code==="ENOENT")return[];throw p}let i=[];for(let p of o.split(`
139
- `)){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,...typeof m.seq=="number"?{seq:m.seq}:{}})}let a=t.maxEntries??this.maxEntries,d=i.length>a?i.slice(-a):i;if(!n)return d;let c=new Map,u=async p=>{let f=c.get(p);if(f!==void 0)return f;let m=await zt(e,p);return c.set(p,m),m},l=[];for(let p of d)l.push(await zr(p,u));return l}async flushAll(){let e=[...this.writeQueues.values()];e.length!==0&&await Promise.allSettled(e)}async delete(e){if(Pe.test(e))return this.enqueue(e,async()=>{try{await K.unlink(A.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 qo(e);try{await K.rmdir(A.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 Ua}from"fs";import*as Ba from"path";async function Wa(s,e){await Ua.mkdir(Ba.dirname(s),{recursive:!0});let t=e.map(n=>JSON.stringify(n));await Ua.writeFile(s,t.length>0?t.join(`
137
+ `,r=await this.resolveNextArchiveIndex(e);await this.enforceArchiveTierCap(e,r);let o=R.historyArchiveFile(e,r);await Q.mkdir(R.sessionDir(e),{recursive:!0}),await Q.appendFile(o,n,{encoding:"utf8",mode:384});let i=0;try{i=(await Q.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=R.historyArchiveFile(e,t),r;try{r=await Q.readFile(n)}catch(i){if(i.code==="ENOENT")return;throw i}let o=await Gp(r);await Q.writeFile(n+".gz",o,{mode:384});try{await Q.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=R.historyArchiveFile(e,r),a=i+".gz",d=!1;try{await Q.access(a),d=!0}catch{d=!1}if(d)o=r+1;else try{(await Q.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=R.historyArchiveFile(e,t);for(let r of[n,n+".gz"])try{await Q.unlink(r)}catch(o){if(o.code!=="ENOENT")throw o}this.archiveLineCounts.delete(e)}async listArchiveIndices(e){let t;try{t=await Q.readdir(R.sessionDir(e))}catch(r){if(r.code==="ENOENT")return[];throw r}let n=new Set;for(let r of t){let o=Qp.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(!Fe.test(e))return[];let t=await this.listArchiveIndices(e),n=[];for(let r of t){let o=R.historyArchiveFile(e,r),i=o+".gz",a=o;try{await Q.access(i),a=i}catch{a=o}n.push({index:r,path:a})}return n}async loadArchives(e){if(!Fe.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 Q.readFile(o);i=(await Kp(a)).toString("utf8")}else i=await Q.readFile(o,"utf8")}catch(a){if(a.code==="ENOENT")continue;throw a}for(let a of i.split(`
138
+ `)){if(a.length===0)continue;let d;try{d=JSON.parse(a)}catch{continue}if(!d||typeof d!="object"||Array.isArray(d))continue;let c=d;typeof c.method=="string"&&typeof c.recordedAt=="number"&&r.push({method:c.method,params:c.params,recordedAt:c.recordedAt,...typeof c.seq=="number"?{seq:c.seq}:{}})}}return r}async*streamFile(e){let t;try{t=Wp(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(qp()):t,o=Vp({input:r,crlfDelay:1/0});try{for await(let i of o){if(i.length===0)continue;let a;try{a=JSON.parse(i)}catch{continue}if(!a||typeof a!="object"||Array.isArray(a))continue;let d=a;typeof d.method=="string"&&typeof d.recordedAt=="number"&&(yield{method:d.method,params:d.params,recordedAt:d.recordedAt,...typeof d.seq=="number"?{seq:d.seq}:{}})}}finally{o.close(),t.destroy()}}async getArchiveLineCounts(e){if(!Fe.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 uo(t,async r=>{let o=n.get(r);if(o!==void 0)return o;let i=await en(e,r);return n.set(r,i),i})}async*iterRecallNewestFirst(e){if(!Fe.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(R.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 m of this.streamFile(u.path))l.push(m);let p=a[c];for(let m=l.length-1;m>=0;m--){let h=await this.hydrateEntry(e,l[m],o);yield{entryId:p+m,entry:h}}}}async rangeSlice(e,t,n){if(!Fe.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 m=0;for await(let h of this.streamFile(u.path)){let f=l+m;if(m+=1,f<t)continue;if(f>n)break;let g=await this.hydrateEntry(e,h,d);a.push({entryId:f,entry:g})}}if(n>=i){let u=Math.max(t-i,0),l=n-i,p=0;for await(let m of this.streamFile(R.historyFile(e))){if(p>l)break;if(p>=u){let h=await this.hydrateEntry(e,m,d);a.push({entryId:i+p,entry:h})}p+=1}}return a}async getRecallTotalCount(e){if(!Fe.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(R.historyFile(e)))r+=1;return n+r}async load(e,t={}){if(!Fe.test(e))return[];let n=(t.tools??"inline")==="inline",r=this.writeQueues.get(e);r&&await r;let o;try{o=await Q.readFile(R.historyFile(e),"utf8")}catch(p){if(p.code==="ENOENT")return[];throw p}let i=[];for(let p of o.split(`
139
+ `)){if(p.length===0)continue;let m;try{m=JSON.parse(p)}catch{continue}if(!m||typeof m!="object"||Array.isArray(m))continue;let h=m;typeof h.method=="string"&&typeof h.recordedAt=="number"&&i.push({method:h.method,params:h.params,recordedAt:h.recordedAt,...typeof h.seq=="number"?{seq:h.seq}:{}})}let a=t.maxEntries??this.maxEntries,d=i.length>a?i.slice(-a):i;if(!n)return d;let c=new Map,u=async p=>{let m=c.get(p);if(m!==void 0)return m;let h=await en(e,p);return c.set(p,h),h},l=[];for(let p of d)l.push(await uo(p,u));return l}async flushAll(){let e=[...this.writeQueues.values()];e.length!==0&&await Promise.allSettled(e)}async delete(e){if(Fe.test(e))return this.enqueue(e,async()=>{try{await Q.unlink(R.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 gi(e);try{await Q.rmdir(R.sessionDir(e))}catch(n){let r=n;if(r.code!=="ENOENT"&&r.code!=="ENOTEMPTY")throw n}})}enqueue(e,t){let r=(this.writeQueues.get(e)??Promise.resolve()).then(t,t),o=r.catch(()=>{});return this.writeQueues.set(e,o),o.finally(()=>{this.writeQueues.get(e)===o&&this.writeQueues.delete(e)}),r}};Y();import{promises as ld}from"fs";import*as fd from"path";async function pd(s,e){await ld.mkdir(fd.dirname(s),{recursive:!0});let t=e.map(n=>JSON.stringify(n));await ld.writeFile(s,t.length>0?t.join(`
140
140
  `)+`
141
- `:"")}import{z as J}from"zod";var Ap=J.object({method:J.string(),params:J.unknown(),recordedAt:J.number()}),Cp=J.object({sessionId:J.string(),lineageId:J.string(),upstreamSessionId:J.string().optional(),agentId:J.string(),cwd:J.string(),title:J.string().optional(),synopsis:en.optional(),summarizedThroughEntry:J.number().int().nonnegative().optional(),currentModel:J.string().optional(),currentMode:J.string().optional(),currentUsage:Tr.optional(),agentCommands:J.array(Rr).optional(),agentModes:J.array(Er).optional(),interactive:J.boolean().optional(),originatingClient:Pr.optional(),priority:J.number().int().nonnegative().optional(),createdAt:J.string(),updatedAt:J.string()}),xp=J.object({version:J.literal(1),exportedAt:J.string(),exportedFrom:J.object({hydraVersion:J.string(),machine:J.string(),hydraHost:J.string().optional()}),session:Cp,history:J.array(Ap),promptHistory:J.array(J.string()).optional(),toolBlobs:J.record(J.string()).optional()});function dn(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 qa(s){return xp.parse(s)}function Jr(s){if(s&&!(s.costAmount===void 0&&s.cumulativeCost===void 0))return(s.cumulativeCost??0)+(s.costAmount??0)}function cn(s){if(!s)return;let e={};s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size);let t=Jr(s);return t&&(e.costAmount=t),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),e}var za=900*1e3,Ep=12,Tp="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Tt=Rp(Tp,16),ss=class s{constructor(e,t,n,r={}){this.registry=e;this.spawner=t??(a=>Ye.spawn(a)),this.store=n??new Hn,this.tombstones=r.tombstones??new Qn,this.sessionHistoryMaxEntries=r.sessionHistoryMaxEntries??1e3,this.histories=new ns({maxEntries:this.sessionHistoryMaxEntries,archiveMaxBytes:r.sessionHistoryArchiveMaxBytes,archiveTiers:r.sessionHistoryArchiveTiers}),this.workspaceSnapshotsDisabled=r.disableWorkspaceSnapshots===!0,this.idleTimeoutMs=r.idleTimeoutMs??0,this.orphanTimeoutMs=r.orphanTimeoutMs??0,this.idleEventTimeoutMs=r.idleEventTimeoutMs??3e4,this.sessionDefaults=r.sessionDefaults??{},this.synopsisAgent=r.synopsisAgent,this.synopsisModel=r.synopsisModel,this.compactionAgent=r.compactionAgent,this.compactionModel=r.compactionModel,this.defaultTransformers=r.defaultTransformers??[],this.logger=r.logger,this.npmRegistry=r.npmRegistry,this.extensionCommands=r.extensionCommands,this.defaultCwd=r.defaultCwd??"~";let o=r.compaction??{},i=o.tailK??20;this.compactionTailK=i,this.synopsisCoordinator=new es({registry:this.registry,store:this.store,histories:this.histories,synopsisAgent:this.synopsisAgent,synopsisModel:this.synopsisModel,compactionAgent:this.compactionAgent,compactionModel:this.compactionModel,compactionMaxIterations:o.maxIterations,persistTitle:async(a,d)=>{let c=this.get(a);if(c){await c.retitle(d);return}await this.persistTitle(a,d)},persistSynopsis:(a,d,c)=>this.persistSynopsis(a,d,c),logger:this.logger,npmRegistry:this.npmRegistry,onCompactionStateChange:async(a,d,c)=>{if(c.targetAgentId)return;let u=this.get(a);u&&(u.compactionState=d),await this.mutateRecord(a,{compactionState:d})},broadcastHydraCompaction:(a,d,c)=>{this.emitSwapPhase(a,c.targetAgentId,d)},onSynthesisArtifact:async(a,d,c,u,l)=>{await this.dispatchSynthesisSwap(a,d,c,u,l)},onSynthesisUnavailable:async(a,d,c)=>{let u=await this.store.read(a).catch(()=>{});if(u?.synopsis&&u.summarizedThroughEntry!==void 0){this.logger?.info(`agent switch: synthesis produced no new artifact for sessionId=${a} (${c}); swapping to ${d} on the persisted synopsis`),await this.dispatchSynthesisSwap(a,u.synopsis,u.summarizedThroughEntry,d);return}let l=(await this.histories.load(a).catch(()=>[])).length;this.logger?.warn(`agent switch: synthesis unavailable for sessionId=${a} (${c}); swapping to ${d} on verbatim tail`),await this.dispatchSynthesisSwap(a,void 0,l,d)}}),this.refreshAgentCatalog()}registry;sessions=new Map;resurrectionInflight=new Map;snapshotInFlight=new Set;snapshotPending=new Set;workspaceSnapshotsDisabled=!1;driftNoticed=new Map;pendingAuthAgents=new Map;spawner;store;tombstones;histories;idleTimeoutMs;orphanTimeoutMs;sessionDefaults;synopsisAgent;synopsisModel;compactionAgent;compactionModel;defaultTransformers;idleEventTimeoutMs;sessionHistoryMaxEntries;metaWriteQueues=new Map;workspaceQueues=new Map;listCache=new Map;static LIST_CACHE_TTL_MS=500;logger;npmRegistry;extensionCommands;defaultCwd;synopsisCoordinator;pendingDeletions=new Map;pendingSwapDisposers=new Map;rollbackLocks=new Set;compactionTailK=20;agentCatalog=[];async dispatchSynthesisSwap(e,t,n,r,o){let i=this.get(e);if(t===void 0&&r===void 0)return;if(!i){if(this.logger?.info(`compaction: persisted artifact for cold session sessionId=${e}`),t===void 0)return;await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:n});return}let a=this.compactionTailK;try{if(await i.isQuiescedForSwap()){this.pendingSwapDisposers.get(e)?.(),this.pendingSwapDisposers.delete(e),await this.performSynthesisSwap(i,t,a,n,r,o);return}this.pendingSwapDisposers.get(e)?.(),this.logger?.info(`compaction: session not quiesced, parking onceIdle swap sessionId=${e}`),this.emitSwapPhase(e,r,{phase:"deferred"});let c=i.onceIdle(()=>{this.pendingSwapDisposers.delete(e),this.onIdleAttemptSwap(e)});this.pendingSwapDisposers.set(e,c)}catch(d){this.logger?.warn(`compaction: dispatch failed for sessionId=${e}: ${d instanceof Error?d.message:String(d)}, leaving session as-is`)}}async onIdleAttemptSwap(e){let t=this.get(e);if(!t)return;let n=this.compactionTailK;try{if(!await t.isQuiescedForSwap()){let d=await this.store.read(e).catch(()=>{});d?.synopsis&&d.summarizedThroughEntry!==void 0?this.dispatchSynthesisSwap(e,d.synopsis,d.summarizedThroughEntry,d.pendingAgentSwap):d?.pendingAgentSwap&&this.dispatchSynthesisSwap(e,void 0,(await this.histories.load(e).catch(()=>[])).length,d.pendingAgentSwap);return}let o=await this.store.read(e).catch(()=>{});if(!o?.synopsis||o.summarizedThroughEntry===void 0){if(o?.pendingAgentSwap){let d=(await this.histories.load(e).catch(()=>[])).length;this.logger?.info(`compaction: no artifact for sessionId=${e}, swapping to ${o.pendingAgentSwap} on verbatim tail`),await this.performSynthesisSwap(t,void 0,n,d,o.pendingAgentSwap);return}this.logger?.warn(`compaction: persisted artifact missing for sessionId=${e}, abandoning swap`),t.compactionState=void 0,await this.mutateRecord(e,{},["compactionState"]);return}let i=o.pendingAgentSwap,a=await this.histories.load(e).catch(()=>[]);if(a.length>o.summarizedThroughEntry){this.logger?.info(`compaction: history grew during deferral (have=${a.length} artifact=${o.summarizedThroughEntry}), rescheduling synopsis sessionId=${e}`),i?this.synopsisCoordinator.scheduleCompaction(e,{targetAgentId:i}):this.synopsisCoordinator.scheduleCompaction(e);return}await this.performSynthesisSwap(t,o.synopsis,n,o.summarizedThroughEntry,i,o.compactionState?.runId)}catch(r){this.logger?.warn(`compaction: onIdleAttemptSwap failed for sessionId=${e}: ${r instanceof Error?r.message:String(r)}`)}}async recordSynopsisFor(e){let t=await this.store.read(e).catch(()=>{});return t?.synopsis?{synopsis:t.synopsis}:{}}async performSynthesisSwap(e,t,n,r,o,i){try{let a=o?Math.min(t===void 0?Ep: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 yt(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=ee(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-${Tt().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 Gn(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 Lr(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 Kn(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=`${He}${Tt()}`,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,configDefaults:e.configDefaults,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_${Tt()}`,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 Ct({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=ee(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=C.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=C.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=An(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:wt,clientInfo:{name:"hydra",version:le}});a=y.agentCapabilities,i.authMethods=ln(y.authMethods),i.steeringSupported=un(y)}catch(y){throw await i.kill().catch(()=>{}),Ze(y,i)}let d;try{let y=Gr(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===C.AuthRequired)throw await i.kill().catch(()=>{}),Ze(y,i);return process.stderr.write(`session/load failed for upstream ${e.upstreamSessionId} on ${e.agentId} (${y.message}); recovering via import-reseed
142
- `),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=Xr(d??{}),u=e.agentModes??_t(Yr(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 rt({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=Kr(d??{}),f=_t(Qr(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=vt(d),g=await ot({agent:i,upstreamSessionId:e.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:p,...m?{modelVerb:m}:{},logger:this.logger}),h=g.modelId,w=_t(Mt(Pt(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 Ct({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 rt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:r.initialMode,advertisedModes:o,logger:this.logger}),a=e.agentModels??r.initialModels,d=await ot({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:r.initialModel,...r.modelVerb?{modelVerb:r.modelVerb}:{},logger:this.logger}),c=d.modelId,u=Pt(d.result)?_t(Mt(d.result)):void 0;r.agent.connection.drainBuffered("session/update");let l=new Ct({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 ct.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:ae(this.defaultCwd)}}async releaseWorkspace(e,t){let n=ee(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=>qe(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=ee(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?`
143
- ${f.map(h=>` ${h}`).join(`
144
- `)}`:` (${l.reason??"the integration failed"})`;return f.length===0?{ok:!1,message:`the source could not be merged into ${$(t.path)}; nothing changed.${g}
145
- `+(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}
146
- 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=wa(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 dt({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 dt({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.
147
- `+(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:
148
- ${f}`)}}let h=await dt({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}
141
+ `:"")}import{z as V}from"zod";var eg=V.object({method:V.string(),params:V.unknown(),recordedAt:V.number()}),tg=V.object({sessionId:V.string(),lineageId:V.string(),upstreamSessionId:V.string().optional(),agentId:V.string(),cwd:V.string(),title:V.string().optional(),synopsis:un.optional(),summarizedThroughEntry:V.number().int().nonnegative().optional(),currentModel:V.string().optional(),currentMode:V.string().optional(),currentUsage:Vr.optional(),agentCommands:V.array(zr).optional(),agentModes:V.array(Jr).optional(),interactive:V.boolean().optional(),originatingClient:Gr.optional(),priority:V.number().int().nonnegative().optional(),createdAt:V.string(),updatedAt:V.string()}),ng=V.object({version:V.literal(1),exportedAt:V.string(),exportedFrom:V.object({hydraVersion:V.string(),machine:V.string(),hydraHost:V.string().optional()}),session:tg,history:V.array(eg),promptHistory:V.array(V.string()).optional(),toolBlobs:V.record(V.string()).optional()});function yn(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 gd(s){return ng.parse(s)}function lo(s){if(s&&!(s.costAmount===void 0&&s.cumulativeCost===void 0))return(s.cumulativeCost??0)+(s.costAmount??0)}function wn(s){if(!s)return;let e={};s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size);let t=lo(s);return t&&(e.costAmount=t),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),e}var md=900*1e3,rg=12,og="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",jt=sg(og,16),ms=class s{constructor(e,t,n,r={}){this.registry=e;this.spawner=t??(a=>st.spawn(a)),this.store=n??new Yn,this.tombstones=r.tombstones??new ds,this.sessionHistoryMaxEntries=r.sessionHistoryMaxEntries??1e3,this.histories=new gs({maxEntries:this.sessionHistoryMaxEntries,archiveMaxBytes:r.sessionHistoryArchiveMaxBytes,archiveTiers:r.sessionHistoryArchiveTiers}),this.workspaceSnapshotsDisabled=r.disableWorkspaceSnapshots===!0,this.idleTimeoutMs=r.idleTimeoutMs??0,this.orphanTimeoutMs=r.orphanTimeoutMs??0,this.idleEventTimeoutMs=r.idleEventTimeoutMs??3e4,this.sessionDefaults=r.sessionDefaults??{},this.synopsisAgent=r.synopsisAgent,this.synopsisModel=r.synopsisModel,this.compactionAgent=r.compactionAgent,this.compactionModel=r.compactionModel,this.defaultTransformers=r.defaultTransformers??[],this.logger=r.logger,this.npmRegistry=r.npmRegistry,this.extensionCommands=r.extensionCommands,this.defaultCwd=r.defaultCwd??"~";let o=r.compaction??{},i=o.tailK??20;this.compactionTailK=i,this.synopsisCoordinator=new fs({registry:this.registry,store:this.store,histories:this.histories,synopsisAgent:this.synopsisAgent,synopsisModel:this.synopsisModel,compactionAgent:this.compactionAgent,compactionModel:this.compactionModel,compactionMaxIterations:o.maxIterations,persistTitle:async(a,d)=>{let c=this.get(a);if(c){await c.retitle(d);return}await this.persistTitle(a,d)},persistSynopsis:(a,d,c)=>this.persistSynopsis(a,d,c),logger:this.logger,npmRegistry:this.npmRegistry,onCompactionStateChange:async(a,d,c)=>{if(c.targetAgentId)return;let u=this.get(a);u&&(u.compactionState=d),await this.mutateRecord(a,{compactionState:d})},broadcastHydraCompaction:(a,d,c)=>{this.emitSwapPhase(a,c.targetAgentId,d)},onSynthesisArtifact:async(a,d,c,u,l)=>{await this.dispatchSynthesisSwap(a,d,c,u,l)},onSynthesisUnavailable:async(a,d,c)=>{let u=await this.store.read(a).catch(()=>{});if(u?.synopsis&&u.summarizedThroughEntry!==void 0){this.logger?.info(`agent switch: synthesis produced no new artifact for sessionId=${a} (${c}); swapping to ${d} on the persisted synopsis`),await this.dispatchSynthesisSwap(a,u.synopsis,u.summarizedThroughEntry,d);return}let l=(await this.histories.load(a).catch(()=>[])).length;this.logger?.warn(`agent switch: synthesis unavailable for sessionId=${a} (${c}); swapping to ${d} on verbatim tail`),await this.dispatchSynthesisSwap(a,void 0,l,d)}}),this.refreshAgentCatalog()}registry;sessions=new Map;resurrectionInflight=new Map;snapshotInFlight=new Set;snapshotPending=new Set;workspaceSnapshotsDisabled=!1;driftNoticed=new Map;pendingAuthAgents=new Map;spawner;store;tombstones;histories;idleTimeoutMs;orphanTimeoutMs;sessionDefaults;synopsisAgent;synopsisModel;compactionAgent;compactionModel;defaultTransformers;idleEventTimeoutMs;sessionHistoryMaxEntries;metaWriteQueues=new Map;workspaceQueues=new Map;listCache=new Map;static LIST_CACHE_TTL_MS=500;logger;npmRegistry;extensionCommands;defaultCwd;synopsisCoordinator;pendingDeletions=new Map;pendingSwapDisposers=new Map;rollbackLocks=new Set;compactionTailK=20;agentCatalog=[];async dispatchSynthesisSwap(e,t,n,r,o){let i=this.get(e);if(t===void 0&&r===void 0)return;if(!i){if(this.logger?.info(`compaction: persisted artifact for cold session sessionId=${e}`),t===void 0)return;await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:n});return}let a=this.compactionTailK;try{if(await i.isQuiescedForSwap()){this.pendingSwapDisposers.get(e)?.(),this.pendingSwapDisposers.delete(e),await this.performSynthesisSwap(i,t,a,n,r,o);return}this.pendingSwapDisposers.get(e)?.(),this.logger?.info(`compaction: session not quiesced, parking onceIdle swap sessionId=${e}`),this.emitSwapPhase(e,r,{phase:"deferred"});let c=i.onceIdle(()=>{this.pendingSwapDisposers.delete(e),this.onIdleAttemptSwap(e)});this.pendingSwapDisposers.set(e,c)}catch(d){this.logger?.warn(`compaction: dispatch failed for sessionId=${e}: ${d instanceof Error?d.message:String(d)}, leaving session as-is`)}}async onIdleAttemptSwap(e){let t=this.get(e);if(!t)return;let n=this.compactionTailK;try{if(!await t.isQuiescedForSwap()){let d=await this.store.read(e).catch(()=>{});d?.synopsis&&d.summarizedThroughEntry!==void 0?this.dispatchSynthesisSwap(e,d.synopsis,d.summarizedThroughEntry,d.pendingAgentSwap):d?.pendingAgentSwap&&this.dispatchSynthesisSwap(e,void 0,(await this.histories.load(e).catch(()=>[])).length,d.pendingAgentSwap);return}let o=await this.store.read(e).catch(()=>{});if(!o?.synopsis||o.summarizedThroughEntry===void 0){if(o?.pendingAgentSwap){let d=(await this.histories.load(e).catch(()=>[])).length;this.logger?.info(`compaction: no artifact for sessionId=${e}, swapping to ${o.pendingAgentSwap} on verbatim tail`),await this.performSynthesisSwap(t,void 0,n,d,o.pendingAgentSwap);return}this.logger?.warn(`compaction: persisted artifact missing for sessionId=${e}, abandoning swap`),t.compactionState=void 0,await this.mutateRecord(e,{},["compactionState"]);return}let i=o.pendingAgentSwap,a=await this.histories.load(e).catch(()=>[]);if(a.length>o.summarizedThroughEntry){this.logger?.info(`compaction: history grew during deferral (have=${a.length} artifact=${o.summarizedThroughEntry}), rescheduling synopsis sessionId=${e}`),i?this.synopsisCoordinator.scheduleCompaction(e,{targetAgentId:i}):this.synopsisCoordinator.scheduleCompaction(e);return}await this.performSynthesisSwap(t,o.synopsis,n,o.summarizedThroughEntry,i,o.compactionState?.runId)}catch(r){this.logger?.warn(`compaction: onIdleAttemptSwap failed for sessionId=${e}: ${r instanceof Error?r.message:String(r)}`)}}async recordSynopsisFor(e){let t=await this.store.read(e).catch(()=>{});return t?.synopsis?{synopsis:t.synopsis}:{}}async performSynthesisSwap(e,t,n,r,o,i){try{let a=o?Math.min(t===void 0?rg: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 Rt(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=ne(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-${jt().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 is(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 ro(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 as(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=`${qe}${jt()}`,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,configDefaults:e.configDefaults,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_${jt()}`,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 Ft({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=ne(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=x.AlreadyAttached,o}return t}let n=this.resurrectionInflight.get(e.hydraSessionId);if(n)return n;let r=this.doResurrect(e);this.resurrectionInflight.set(e.hydraSessionId,r);try{return await r}finally{this.resurrectionInflight.delete(e.hydraSessionId)}}async doResurrect(e){let t=this.sessions.get(e.hydraSessionId);if(t)return t;let n=await this.registry.getAgent(e.agentId);if(!n){let k=new Error(`agent ${e.agentId} not found in registry; cannot resurrect`);throw k.code=x.AgentNotInstalled,k}if(e.upstreamSessionId==="")return this.doResurrectFromImport(e);if(!await this.dirExists(e.cwd))return this.doResurrectFromImport(e);let r=await Re(n,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),o=Nn(e.hydraSessionId,e.forwardedEnv),i=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:r,...o?{extraEnv:o}:{}}),a;try{let k=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:xt,clientInfo:{name:"hydra",version:me}});a=k.agentCapabilities,i.authMethods=vn(k.authMethods),i.steeringSupported=kn(k)}catch(k){throw await i.kill().catch(()=>{}),ot(k,i)}let d;try{let k=po(n,{model:e.currentModel});d=await i.connection.request("session/load",{sessionId:e.upstreamSessionId,cwd:e.cwd,mcpServers:e.mcpServers??[],...k&&{_meta:k}})}catch(k){if(k&&typeof k=="object"&&k.code===x.AuthRequired)throw await i.kill().catch(()=>{}),ot(k,i);return process.stderr.write(`session/load failed for upstream ${e.upstreamSessionId} on ${e.agentId} (${k.message}); recovering via import-reseed
142
+ `),await i.kill().catch(()=>{}),this.doResurrectFromImport(e)}if(e.pendingHistorySync===!0)this.clearPendingHistorySync(e.hydraSessionId).catch(()=>{});else{let k=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain1 dropped ${k} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let c=yo(d??{}),u=e.agentModes??Ut(ho(d??{}));this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedMode=${JSON.stringify(e.currentMode)} agentReportedMode=${JSON.stringify(c)} advertisedModes=${JSON.stringify(u?.map(k=>k.id))}`);let l=await lt({agent:i,upstreamSessionId:e.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:c,advertisedModes:u,logger:this.logger});this.logger?.info(`resurrect: effectiveMode=${JSON.stringify(l)} for sessionId=${e.hydraSessionId}`);let p=go(d??{}),m=Ut(mo(d??{}))??e.agentModels;if(this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedModel=${JSON.stringify(e.currentModel)} agentReportedModel=${JSON.stringify(p)} advertisedModels=${JSON.stringify(m?.map(k=>k.modelId))}`),e.pendingHistorySync!==!0){let k=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain2 (post-mode-restore) dropped ${k} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let h=Et(d),f=await ft({agent:i,upstreamSessionId:e.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:p,...h?{modelVerb:h}:{},logger:this.logger}),g=f.modelId,w=Ut(Lt(Ht(f.result)?f.result:d??{}));if(e.pendingHistorySync!==!0){let k=i.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain3 (post-model-restore) dropped ${k} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let y=new Ft({sessionId:e.hydraSessionId,cwd:e.cwd,...e.workspace!==void 0?{workspace:e.workspace}:{},agentId:e.agentId,agent:i,upstreamSessionId:e.upstreamSessionId,agentMeta:d?._meta,agentCapabilities:a,...h?{modelVerb:h}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,orphanTimeoutMs:this.orphanTimeoutMs,logger:this.logger,spawnReplacementAgent:k=>this.bootstrapAgent({...k,mcpServers:k.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),loadExistingAgentSession:(k,b)=>this.bootstrapAgentLoad(k,{...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:g,currentMode:l,currentUsage:e.currentUsage,reloadsUpstreamLedger:!0,agentCommands:e.agentCommands,agentModes:u,agentModels:m,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(y.sessionId),scheduleWorkspaceSnapshot:()=>this.scheduleWorkspaceSnapshot(y),scheduleCompaction:k=>this.scheduleCompaction(y.sessionId,k),resolveAgentId:async k=>(await this.registry.getAgent(k))?.id,getCompactionState:()=>this.getCompactionState(y.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(y.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(y.sessionId),uncompactHook:()=>this.performUncompact(y.sessionId),forkHook:k=>this.forkSession(y.sessionId,k??{}),workspaceHook:(k,b,S)=>this.runWorkspaceAction(y.sessionId,k,b,S),onCompactionSwapHook:k=>{this.persistRollbackBreadcrumb(y.sessionId,k).catch(()=>{})},persistWatermarkHook:k=>{this.mutateRecord(y.sessionId,{summarizedThroughEntry:k}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(y.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(y),y}async doResurrectFromImport(e){let t=await this.resolveResurrectTarget(e.cwd,e.workspace),n=t.cwd,r=await this.bootstrapAgent({agentId:e.agentId,cwd:n,agentArgs:e.agentArgs,mcpServers:e.mcpServers??[],onInstallProgress:e.onInstallProgress,forwardedEnv:e.forwardedEnv,model:e.currentModel}),o=e.agentModes??r.initialModes,i=await lt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:r.initialMode,advertisedModes:o,logger:this.logger}),a=e.agentModels??r.initialModels,d=await ft({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:r.initialModel,...r.modelVerb?{modelVerb:r.modelVerb}:{},logger:this.logger}),c=d.modelId,u=Ht(d.result)?Ut(Lt(d.result)):void 0;r.agent.connection.drainBuffered("session/update");let l=new Ft({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,m)=>this.bootstrapAgentLoad(p,{...m,mcpServers:m.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,m,h)=>this.runWorkspaceAction(l.sessionId,p,m,h),onCompactionSwapHook:p=>{this.persistRollbackBreadcrumb(l.sessionId,p).catch(()=>{})},persistWatermarkHook:p=>{this.mutateRecord(l.sessionId,{summarizedThroughEntry:p}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(l.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(l),e.forkedFromSessionId&&e.forkSynthesisState==="running"?this.logger?.info(`fork ${l.sessionId}: synthesis in flight \u2014 skipping seed, recall available`):e.forkedFromSessionId&&(e.synopsis||(e.summarizedThroughEntry??0)>0)?l.seedFromFork(e.synopsis).catch(()=>{}):l.seedFromImport().catch(()=>{}),l}async dirExists(e){try{return(await yt.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:le(this.defaultCwd)}}async releaseWorkspace(e,t){let n=ne(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(`${F(t.path)} is shared with ${r.map(m=>Ke(m.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=ne(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 ${F(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 m=l.conflicts,h=await i.integrationInProgress(t.path);if(m.length===0&&!h){let g=await this.syncOverDirtyTree(t,{provider:i,before:d,sourceHead:a,incoming:u});if(g!==void 0)return g}let f=m.length>0?`
143
+ ${m.map(g=>` ${g}`).join(`
144
+ `)}`:` (${l.reason??"the integration failed"})`;return m.length===0?{ok:!1,message:`the source could not be merged into ${F(t.path)}; nothing changed.${f}
145
+ `+(h?"A merge is already in progress there. Finish it \u2014 resolve, commit \u2014 then `/hydra workspace sync` again.":"Clear that in the workspace, then `/hydra workspace sync` again.")}:n.onConflict==="abort"?(await i.abortIntegration(t.path).catch(()=>{}),{ok:!1,message:`${m.length} file(s) conflict between the source and this workspace:${f}`}):{ok:!1,message:`Synced with conflicts. ${m.length} file(s) need resolving in ${F(t.path)}:${f}
146
+ 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 ${F(t.path)} with ${F(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=Ba(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},m=`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 ht({source:e.path,capture:p,provider:n});return{ok:!1,message:`Could not clear ${F(e.path)} to merge into it, so nothing was synced. ${b?"Your uncommitted work is back in place.":`Your uncommitted work is at ${u}: ${m}`}`}}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 ht({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.
147
+ `+(b?`Your uncommitted work is back in place (unstaged) and nothing else changed. Commit it in ${F(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:
148
+ ${m}`)}}let g=await ht({source:e.path,capture:p,provider:n}),w=await n.currentState(e.path),y=w===void 0?0:(await n.changedPathsBetween(e.path,r,w)).length,k=`Synced ${F(e.path)} with ${F(e.sourceCwd)}: ${i} commit(s), ${y} file(s) changed.`;return g?(await n.dropSnapshotRef(a,u).catch(()=>{}),{ok:!0,message:`${k} Your uncommitted work was set aside for the merge and restored on top.`}):{ok:!1,message:`${k}
149
149
  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:
150
- ${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=ee(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 Gn(t.sourceCwd).catch(()=>({}));if(o.preRemove!==void 0){let a=await Kn(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 va(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 rn(e).autosave}startRefFor(e){return rn(e).start}baselineRefFor(e){return rn(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=ee(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=ee(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(`
151
- ${$(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.
152
- `))}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)}.
153
- Use \`/hydra workspace start\` to move into an isolated workspace.`;let d=this.liveSessionsIn(a.path,o.sessionId).map(f=>qe(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 ee(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(`
154
- `)}if(t==="start")return this.startWorkspace(o,n,{clean:r?.clean===!0});let i=o.workspace;if(i===void 0)throw new Error("this session is not in a workspace. Use `/hydra workspace start` first.");if(t==="sync")return(await this.syncWorkspaceFromSource(o,i,{onConflict:"keep"})).message;if(t==="clean")return await this.cleanWorkspace(o,i,{deep:r?.deep===!0});if(t==="merge"){o.broadcastWorkspacePhase({phase:"landing"});let a;try{a=await this.mergeWorkspaceIntoSource(i,o.sessionId)}catch(d){let c=d instanceof Error?d.message:String(d);throw o.broadcastWorkspacePhase({phase:"failed",error:c}),d}return o.broadcastWorkspacePhase({phase:"entered",cwd:o.cwd,sourceCwd:i.sourceCwd,label:i.label}),[`${a.merged}; still working in ${$(i.path)}.`,...a.warnings].join(`
150
+ ${m}`}}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=ne(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`${F(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 is(t.sourceCwd).catch(()=>({}));if(o.preRemove!==void 0){let a=await as(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 qa(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 gn(e).autosave}startRefFor(e){return gn(e).start}baselineRefFor(e){return gn(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=ne(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=ne(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(`
151
+ ${F(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.
152
+ `))}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 ${F(o.cwd)}.
153
+ Use \`/hydra workspace start\` to move into an isolated workspace.`;let d=this.liveSessionsIn(a.path,o.sessionId).map(m=>Ke(m.sessionId)),c=a.line,u=[`Isolated in ${F(a.path)}`,` source: ${F(a.sourceCwd)}`,` provider: ${a.provider}${c!==void 0?` (${c})`:""}`];d.length>0&&u.push(` shared with: ${d.join(", ")}`);let p=await ne(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 m of p??[])u.push(` ${m}`);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(`
154
+ `)}if(t==="start")return this.startWorkspace(o,n,{clean:r?.clean===!0});let i=o.workspace;if(i===void 0)throw new Error("this session is not in a workspace. Use `/hydra workspace start` first.");if(t==="sync")return(await this.syncWorkspaceFromSource(o,i,{onConflict:"keep"})).message;if(t==="clean")return await this.cleanWorkspace(o,i,{deep:r?.deep===!0});if(t==="merge"){o.broadcastWorkspacePhase({phase:"landing"});let a;try{a=await this.mergeWorkspaceIntoSource(i,o.sessionId)}catch(d){let c=d instanceof Error?d.message:String(d);throw o.broadcastWorkspacePhase({phase:"failed",error:c}),d}return o.broadcastWorkspacePhase({phase:"entered",cwd:o.cwd,sourceCwd:i.sourceCwd,label:i.label}),[`${a.merged}; still working in ${F(i.path)}.`,...a.warnings].join(`
155
155
  `)}if(t==="apply"){o.broadcastWorkspacePhase({phase:"applying"});let a;try{a=await this.applyWorkspaceToSource(i,o.sessionId)}catch(d){let c=d instanceof Error?d.message:String(d);throw o.broadcastWorkspacePhase({phase:"failed",error:c}),d}return o.broadcastWorkspacePhase({phase:"entered",cwd:o.cwd,sourceCwd:i.sourceCwd,label:i.label}),[a.applied,...a.warnings].join(`
156
- `)}if(t==="stop"){let a=this.liveSessionsIn(i.path,o.sessionId);if(a.length>0){o.broadcastWorkspacePhase({phase:"returning"}),await this.leaveWorkspace(o,i,{exit:"detached"});let c=a.map(p=>qe(p.sessionId)).join(", "),u=[`Left ${$(i.path)} and returned to ${$(i.sourceCwd)}.`,`Nothing landed yet: ${c} still working there. It lands when the last session leaves.`],l=await this.fastForwardBlocked(i);return l!==void 0&&u.push(`WARNING: that merge will not fast-forward as things stand \u2014 ${l}`),u.join(`
156
+ `)}if(t==="stop"){let a=this.liveSessionsIn(i.path,o.sessionId);if(a.length>0){o.broadcastWorkspacePhase({phase:"returning"}),await this.leaveWorkspace(o,i,{exit:"detached"});let c=a.map(p=>Ke(p.sessionId)).join(", "),u=[`Left ${F(i.path)} and returned to ${F(i.sourceCwd)}.`,`Nothing landed yet: ${c} still working there. It lands when the last session leaves.`],l=await this.fastForwardBlocked(i);return l!==void 0&&u.push(`WARNING: that merge will not fast-forward as things stand \u2014 ${l}`),u.join(`
157
157
  `)}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(`
158
- `)}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=>qe(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(`
159
- `)}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(`
160
- `)}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=ee(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=ka(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=>qe(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=ee(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(`
161
- `)})}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=ee(e.provider),a=this.asWorkspace(e),d=await Hr({source:n,ws:a,startSnapshotRef:this.startRefFor(e.label),baselineRef:this.baselineRefFor(e.label),retainRef:jr(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),x="";if(v!==void 0)try{let E=await this.syncWorkspaceFromSource(v,e,{onConflict:"abort"});E.ok?(l.push(`
162
- synced with the source first: ${E.message}`),u=await i.contains(n,{state:c,within:r})):x=`
163
- A sync was attempted first and could not complete: ${E.message}`}catch(E){x=`
164
- A sync was attempted first but was refused: ${E instanceof Error?E.message:String(E)}`}if(!u){let E=await i.currentLineName(n)??"the source";throw new Error(`cannot fast-forward ${E} in ${$(n)} to ${r}. The source has moved on since this workspace was created. The source is untouched.${x}
165
- `+(x.length>0?`Or land it by hand with: git -C ${n} merge ${r}`:`Resolve it in the workspace with \`/hydra workspace sync\` (which leaves the conflict there to fix), or land it by hand with: git -C ${n} merge ${r}`))}}let p=i!==void 0&&i.capabilities().supports.nestedTrees?await i.captureNested(e.path,await i.listNested(e.path)).catch(()=>[]):[],f,m=await i.status(a).catch(()=>{});if(m!==void 0&&m.changedPaths.length>0&&(f=await i.captureWorkingState(e.path,`hydra: uncommitted work in ${e.label}`).catch(()=>{}),f===void 0))throw new Error(`could not capture the uncommitted work in ${$(e.path)}; nothing was changed`);if(!d.clean&&!(await i.resetTo(n,c)).ok)throw new Error(`could not clear ${$(n)} for the merge; your work is preserved at ${d.retainedRef}. Nothing was merged.`);let g=await i.integrate({into:n,from:r,fastForwardOnly:!0});if(!g.ok)throw new Error(`merge failed: ${g.reason??"unknown error"}`);let h=!0;if(f!==void 0){let v=await i.captureDelta(n,g.snapshot,f);v!==void 0&&(h=(await i.applyDelta(n,v)).ok)}let w=await dt({source:n,capture:d,provider:i});w&&await on({source:n,ws:a,capture:d,provider:i});let k={applied:[],failed:[]},y=i!==void 0&&i.capabilities().supports.nestedTrees?await i.integrateNested(n,e.path,p).catch(()=>k):k,b=await i.captureWorkingState(n,`hydra: source state after landing ${e.label}`).catch(()=>{});b!==void 0&&await i.retainSnapshot({...a,path:n},this.baselineRefFor(e.label),b).catch(()=>{});let I=[];h||I.push(` WARNING: the workspace's uncommitted changes could not be replayed; they remain reachable from ${r}.`),w||I.push(e.clean===!0?` WARNING: this workspace started clean, so your uncommitted work was never copied in. The whole of it is being replayed now and it overlaps what the agent changed. All of it is preserved at ${d.retainedRef}; recover with: git -C ${n} diff ${d.base} ${d.retainedRef}`:` WARNING: your own edits to ${$(n)} overlap the workspace's changes and could not be replayed on top. They are preserved at ${d.retainedRef}; recover with: git -C ${n} diff ${d.base} ${d.retainedRef}`);for(let v of y.failed)I.push(` WARNING: nested tree ${v.path} was NOT reconciled: ${v.reason}. ${$(n)} now records a different state for it, so it will report it as modified until you resolve that.`);return{merged:`Merged ${r} into ${$(n)}${l.join("")}`,warnings:I}}async applyWorkspaceToSource(e,t){let n=e.sourceCwd;if(!await this.dirExists(n))throw new Error(`source tree ${$(n)} no longer exists`);let r=ee(e.provider);if(r===void 0)throw new Error(`no provider "${e.provider}" available to apply this workspace`);if(!r.capabilities().supports.captureWorkingState)throw new Error(`provider "${e.provider}" cannot snapshot a working tree, so there is no change set to apply. Use \`/hydra workspace stop\` to land this workspace instead.`);let o=this.asWorkspace(e);if((await r.status({...o,path:n}).catch(()=>{}))?.hasStagedWork===!0)throw new Error(`${$(n)} already has changes staged for its next commit, and \`apply\` delivers into that same index: the two sets would be indistinguishable, and unstaging one would unstage both. Commit or unstage them first, or use \`/hydra workspace merge\`, which lands the work as commits and does not touch the index.`);let a=await r.currentState(n);if(a===void 0)throw new Error(`could not read the state of ${$(n)}`);let d=e.line,c=d!==void 0&&await r.contains(n,{state:a,within:d}).catch(()=>!1),u=c?a:e.snapshot??"";if(u.length===0)throw new Error(`workspace ${e.label} has no recorded base to measure its changes against, so there is no way to tell its work apart from what the source already had`);let l=await Hr({source:n,ws:o,startSnapshotRef:this.startRefFor(e.label),baselineRef:this.baselineRefFor(e.label),retainRef:jr(t),provider:r}),p=r.capabilities().supports.nestedTrees?(await r.listNested(e.path).catch(()=>[])).filter(y=>y.changedPaths.length>0||y.recorded!==void 0&&y.recorded!==y.actual):[],f=await r.captureWorkingState(e.path,`hydra: apply from ${e.label}`).catch(()=>{});if(f===void 0)throw new Error(`could not snapshot the work in ${$(e.path)}; nothing was changed`);let m=await r.captureDelta(n,u,f);if(m===void 0)throw new Error(`could not work out what ${e.label} changed; ${$(n)} was not touched`);if(m.trim().length===0)return await on({source:n,ws:o,capture:l,provider:r}),{applied:`Nothing to apply: ${e.label} holds no changes ${$(n)} does not already have.`,warnings:[]};if(!l.clean&&!(await r.resetTo(n,a)).ok)throw new Error(`could not clear ${$(n)} to apply onto; your work is preserved at ${l.retainedRef}. Nothing was applied.`);let g=await r.applyDelta(n,m,{stage:!0,tolerant:!c});if(!g.ok){await r.resetTo(n,a).catch(()=>{});let y=await dt({source:n,capture:l,provider:r});throw y&&await on({source:n,ws:o,capture:l,provider:r}),new Error(`could not apply ${e.label} into ${$(n)}: ${g.reason??"the change set did not apply"}.`+(c?"":" The source has moved on since this workspace was created; `/hydra workspace sync` brings those commits in here, which is what lets the change set apply against them.")+(y?` ${$(n)} is as you left it.`:` Your uncommitted work there is preserved at ${l.retainedRef}.`))}let h=await dt({source:n,capture:l,provider:r});h&&await on({source:n,ws:o,capture:l,provider:r});let w=await r.captureWorkingState(n,`hydra: source state after applying ${e.label}`).catch(()=>{});w!==void 0&&await r.retainSnapshot({...o,path:n},this.baselineRefFor(e.label),w).catch(()=>{});let k=[];g.alreadyPresent===!0&&k.push(` Nothing was staged: ${$(n)} already had every one of those changes.`),h||k.push(` WARNING: your own edits to ${$(n)} overlap the workspace's changes and could not be replayed on top. They are preserved at ${l.retainedRef}; recover with: git -C ${n} diff ${l.base} ${l.retainedRef}`);for(let y of p)k.push(` WARNING: nested tree ${y.relPath} was NOT included: a change set can only move the pointer to it, not what is inside. Land it with \`/hydra workspace stop\`, or copy that work across by hand.`);return{applied:`Applied ${e.label} into ${$(n)} as staged changes; still working in ${$(e.path)}.
166
- 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=ee(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=ee(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=>qe(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(`
167
- `)})}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=ee();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 x=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=$r(v.changedPaths,x);else if(v!==void 0&&v.changedPaths.length>0&&(c=$r(v.changedPaths,x),f=await o.captureNested(r,x).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 x=await this.materializeNestedTrees(h);if(f.length>0){let R=await o.reproduceNested(h.path,r,f).catch(M=>({applied:[],failed:f.map(T=>({path:T.relPath,reason:M instanceof Error?M.message:String(M)}))}));R.failed.length>0&&(y=!1,b=R.failed)}k=await this.applyWorkspaceSetup(h,e.sessionId),x!==void 0&&(k=k===void 0?x:`${x}; ${k}`),e.broadcastWorkspacePhase({phase:"swapping"});let E=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:E.length,note:`Continuing in an isolated workspace at ${h.path}, derived from ${r}.`,...await this.recordSynopsisFor(e.sessionId)})}catch(v){let x=await this.unwindStartWorkspace({provider:o,ws:h,startRef:w,carried:d}),E=v instanceof Error?v.message:String(v);throw e.broadcastWorkspacePhase({phase:"failed",error:E}),new Error(x===void 0?E:`${E}
168
- ${x}`)}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 at(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 at(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(`
169
- `)}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=ee(e.provider);return o===void 0?!1:(await o.applyDelta(e.path,r)).ok}async patchFromSnapshot(e,t,n){let r=ee(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=ee(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 Gn(e.sourceCwd).catch(()=>({})),r=[];if(n.carry!==void 0&&n.carry.length>0){let o=await Lr(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 Kn(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=ee(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=ee(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=ee(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=C.AgentNotInstalled,g}let n=await Ie(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:Qa.homedir(),plan:n}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:wt,clientInfo:{name:"hydra",version:le}})}catch(g){throw await r.kill().catch(()=>{}),Ze(g,r)}if(r.authMethods=ln(o.authMethods),r.steeringSupported=un(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=tr(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=A.sessionsDir(),f=[],m=0;for(let g of a){let h=`${c}::${g.sessionId}`;if(u.has(h)){m+=1;continue}if(Pp(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(!ba(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=`${He}${Tt()}`,b=new Date().toISOString(),I=g.updatedAt??b,v={sessionId:y,lineageId:nn(),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 x=Mr(v);await this.store.write(x),f.push({version:1,...x})}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 Xe({request:(d,c)=>e.connection.request(d,c),sessionId:t,modelId:n,...o?{verb:o}:{},logger:this.logger});return this.logger?.info(`${r}: ${i} accepted`),{accepted:!0,result:a}}catch(i){return this.logger?.warn(`${r} rejected by agent (${i.message}); session will use the agent's own default`),{accepted:!1}}}async applySeedMode(e,t,n,r){try{let o=await e.connection.request("session/set_mode",{sessionId:t,modeId:n});return this.logger?.info(`${r}: session/set_mode accepted`),{accepted:!0,result:o}}catch(o){return this.logger?.warn(`${r} rejected by agent (${o.message}); session will use the agent's own default mode`),{accepted:!1}}}async 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=C.AgentNotInstalled,i}let n=await Ie(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),r=An(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:wt,clientInfo:{name:"hydra",version:le}}),a=i.agentCapabilities;o.authMethods=ln(i.authMethods),o.steeringSupported=un(i);let d=Gr(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=Kr(c),p=Qr(c),f=vt(c),m=Jt(this.sessionDefaults,t),g=m?.value,h=e.configDefaults,w=m?.from??e.agentId,k=e.model??h?.model??g?.model,y;if(k&&k!==l){let R=It(k,p),M=e.model!==void 0?`model=${JSON.stringify(k)}`:h?.model!==void 0?`configDefaults.model=${JSON.stringify(k)}`:`sessionDefaults[${w}].model=${JSON.stringify(k)}`;if(R.kind==="exact"||R.kind==="none"){let T=await this.applySeedModel(o,u,k,M,f);T.accepted&&(l=k,y=T.result)}else if(R.kind==="resolved")if(R.modelId===l)l=R.modelId;else{let T=await this.applySeedModel(o,u,R.modelId,`${M} resolved to ${JSON.stringify(R.modelId)}`,f);T.accepted&&(l=R.modelId,y=T.result)}else if(R.kind==="ambiguous")this.logger?.warn(`${M} is ambiguous (trailing-segment matches [${R.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(l)}`);else{let T=p.map(D=>D.modelId).join(", ");this.logger?.warn(`${M} not in agent's availableModels ([${T}]); skipping session/set_model, session will use ${JSON.stringify(l)}`)}}let b=Yr(c),I=Xr(c),v=h?.mode??g?.mode;if(v&&v!==I){let R=h?.mode!==void 0?`configDefaults.mode=${JSON.stringify(v)}`:`sessionDefaults[${w}].mode=${JSON.stringify(v)}`;if(b.length>0&&!b.some(M=>M.id===v)){let M=b.map(T=>T.id).join(", ");this.logger?.warn(`${R} not in agent's availableModes ([${M}]); skipping session/set_mode, session will use ${JSON.stringify(I)}`)}else{let M=await this.applySeedMode(o,u,v,R);M.accepted&&(I=v,Pt(M.result)&&(y=M.result))}}let x={...g??{},...h??{}};if(delete x.model,delete x.mode,Object.keys(x).length>0){let R=Mt(Pt(y)?y:c);for(let[M,T]of Object.entries(x)){let D=`sessionDefaults[${w}].${M}=${JSON.stringify(T)}`,q=R.find(L=>L.id===M);if(!q){this.logger?.warn(`${D}: agent does not currently advertise configId=${M}; skipping session/set_config_option`);continue}let B=Kt(T,q.options.map(L=>L.value));if(B.kind!=="exact"&&B.kind!=="resolved"){this.logger?.warn(`${D} ${B.kind}; skipping session/set_config_option`);continue}let Z=B.kind==="resolved"?B.modelId:T;if(Z!==q.currentValue)try{let L=await o.connection.request("session/set_config_option",{sessionId:u,configId:M,value:Z});this.logger?.info(`${D}: session/set_config_option accepted`),Pt(L)&&(R=Mt(L),y=L)}catch(L){this.logger?.warn(`${D}: session/set_config_option rejected by agent (${L.message})`)}}}let E=Mt(Pt(y)?y:c);return{agent:o,upstreamSessionId:u,agentMeta:c._meta,agentCapabilities:a,initialModel:l,initialModels:p.length>0?p:void 0,initialModes:b.length>0?b:void 0,initialMode:I,initialConfigOptions:E.length>0?E:void 0,modelVerb:f}}catch(i){throw await o.kill().catch(()=>{}),Ze(Ga(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=C.AgentNotInstalled,a}let r=await Ie(n,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=An(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:wt,clientInfo:{name:"hydra",version:le}}),d=a.agentCapabilities;i.authMethods=ln(a.authMethods),i.steeringSupported=un(a);let c=Gr(n),u=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),l=Kr(u),p=_t(Qr(u)),f=Yr(u),m=Xr(u),g=_t(Mt(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:vt(u)}}catch(a){throw await i.kill().catch(()=>{}),Ze(Ga(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=C.AgentNotInstalled,d}let o=await Ie(r,[],{npmRegistry:this.npmRegistry}),i=t??ae(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let d=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:wt,clientInfo:{name:"hydra",version:le}});a.authMethods=ln(d.authMethods),a.steeringSupported=un(d)}catch(d){throw await a.kill().catch(()=>{}),Ze(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=C.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||this.store.touch(e.sessionId).catch(()=>{}),t&&e.workspace!==void 0&&this.releaseWorkspace(e.workspace,e.sessionId).catch(()=>{}),t){if(e.upstreamSessionId){let r=$t({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:Ya(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=Mp(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 zt(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:_p(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=it(r.update.prompt),a=Ar(i,200);if(a&&!a.startsWith("/"))return a}}get(e){return this.sessions.get(e)}liveSessions(){return this.sessions.values()}setLiveConfig(e){e.sessionDefaults&&(this.sessionDefaults=e.sessionDefaults)}activeAgentVersions(){let e=new Map;for(let t of this.sessions.values()){let n=t.agent.installId,r=t.agent.version,o=e.get(n);o||(o=new Set,e.set(n,o)),o.add(r)}return e}async resolveCanonicalId(e){if(this.sessions.has(e)||await this.store.read(e))return e;if(e.startsWith(He))return;let t=He+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=C.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 fn(t.sessionId),d=$t({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 fn(n.sessionId),o=$t(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:cn(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={}){return(await this.listing(e)).entries}async listing(e={}){let t=`${e.cwd??""}|${e.includeNonInteractive?"1":"0"}|${e.status??""}`,n=Date.now(),r=this.listCache.get(t);if(r&&r.expiresAt>n)return r.promise;let o=this.listUncached(e);return this.listCache.set(t,{expiresAt:n+s.LIST_CACHE_TTL_MS,promise:o}),o.catch(()=>{let i=this.listCache.get(t);i&&i.promise===o&&this.listCache.delete(t)}),o}invalidateListCache(){this.listCache.clear()}async listUncached(e={}){let t=await this.store.cursor(),{entries:n,liveIds:r}=await this.warmRows(e);if(e.status==="warm")return{entries:n,cursor:t};let o=await this.store.list().catch(i=>{throw this.logger?.warn(`session list: store.list() failed: ${i?.message??String(i)}`),i});return n.push(...await this.coldRows(o,r,e)),n.sort((i,a)=>i.updatedAt<a.updatedAt?1:-1),{entries:n,cursor:t}}async listSince(e,t){let{entries:n,liveIds:r}=await this.warmRows(e);if(e.status==="warm")return{entries:n,removed:[],cursor:await this.store.cursor()};let o=await this.store.listChangedSince(t);return n.push(...await this.coldRows(o.records,r,e)),n.sort((i,a)=>i.updatedAt<a.updatedAt?1:-1),{entries:n,removed:o.removed,cursor:o.cursor}}async seedSessionIndex(){await this.store.ensureIndex();let e=await this.tombstones.list().catch(()=>[]);for(let t of e){if(t.sessionId===void 0)continue;let n=Date.parse(t.deletedAt);Number.isNaN(n)||await this.store.markDeleted(t.sessionId,n)}}static includeRow(e,t){return e.includeNonInteractive?!0:t===!0}async warmRows(e){let t=[],n=new Set,r=[...this.sessions.values()].filter(i=>Ja(e.cwd,i));if(e.status==="cold"){for(let i of r)n.add(i.sessionId);return{entries:t,liveIds:n}}let o=await Promise.all(r.map(i=>fn(i.sessionId)));for(let i=0;i<o.length;i+=1){let a=r[i],d=o[i];n.add(a.sessionId);let c=$t({interactive:a.interactive,...a.originatingClient?{originatingClient:a.originatingClient}:{}},d.hasContent);if(!s.includeRow(e,c))continue;let u=d.mtime??new Date(a.updatedAt).toISOString();t.push({sessionId:a.sessionId,upstreamSessionId:a.upstreamSessionId,cwd:a.cwd,workspace:a.workspace,workspaceError:a.workspaceError,title:a.title,agentId:a.agentId,currentModel:a.currentModel,currentUsage:a.currentUsage,parentSessionId:a.parentSessionId,forkedFromSessionId:a.forkedFromSessionId,forkedFromMessageId:a.forkedFromMessageId,originatingClient:a.originatingClient,interactive:c,priority:a.priority,updatedAt:u,attachedClients:a.attachedCount,status:"warm",agentPid:a.agentPid,busy:a.turnStartedAt!==void 0,armedTasks:a.armedBackgroundTasks.length,...a.armedSince!==void 0?{armedSince:a.armedSince}:{},awaitingInput:a.awaitingInput,compactionState:a.compactionState,forkSynthesisState:a.forkSynthesisState})}return{entries:t,liveIds:n}}async coldRows(e,t,n){let r=[],o=e.filter(a=>!t.has(a.sessionId)&&Ja(n.cwd,a)),i=await Promise.all(o.map(a=>fn(a.sessionId)));for(let a=0;a<o.length;a+=1){let d=o[a],c=i[a],u=$t(d,c.hasContent);if(!s.includeRow(n,u))continue;let l=c.mtime??d.updatedAt;r.push({sessionId:d.sessionId,upstreamSessionId:d.upstreamSessionId,cwd:d.cwd,workspace:d.workspace,title:d.title,agentId:d.agentId,currentModel:d.currentModel,currentUsage:cn(d.currentUsage),importedFromMachine:d.importedFromMachine,importedFromUpstreamSessionId:d.importedFromUpstreamSessionId,parentSessionId:d.parentSessionId,forkedFromSessionId:d.forkedFromSessionId,forkedFromMessageId:d.forkedFromMessageId,originatingClient:d.originatingClient,interactive:u,priority:d.priority,updatedAt:l,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,compactionState:d.compactionState,forkSynthesisState:d.forkSynthesisState})}return r}async exportBundle(e,t={}){let n=await this.store.read(e);if(!n)return;let r;if(n.lineageId)r=n;else{let c=nn(),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 Ka(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let d={};for(let c of ja(i)){let u=await Bo(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=C.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=`${He}${Tt()}`;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=C.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=C.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=jn(i,t.forkAt);if(I<0){let v=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw v.code=C.InvalidParams,v}d=t.forkAt,a=i.slice(0,I+1)}else{let I=Np(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=jn(i,t.forkAt);if(v<0){let x=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw x.code=C.InvalidParams,x}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=C.AgentNotInstalled,v}p=I,l=n.currentModel,u="running"}let m=await Ka(e),g=c==="synthesis",h={...n,lineageId:nn(),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=dn({record:h,history:a,promptHistory:m.length>0?m:void 0,hydraVersion:le,machine:Gt()}),k=`${He}${Tt()}`,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 Zn({agentId:r,cwd:t.cwd??A.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 Wo(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await ct.utimes(A.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await Wa(A.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=tr(o))}catch{}return t.set(e,r),r}async tombstoneAllGenerations(e,t,n){let r=await this.store.read(e).catch(()=>{}),o=new Map;for(let d of r?.upstreamGenerations??[])d.upstreamSessionId&&o.set(`${d.agentId}::${d.upstreamSessionId}`,{agentId:d.agentId,upstreamSessionId:d.upstreamSessionId});o.set(`${t.agentId}::${t.upstreamSessionId}`,{agentId:t.agentId,upstreamSessionId:t.upstreamSessionId});let i=new Date().toISOString(),a=new Map;for(let d of o.values())await this.tombstones.add({agentId:await this.agentStoreKey(d.agentId,a),upstreamSessionId:d.upstreamSessionId,sessionId:e,deletedAt:i,upstreamUpdatedAt:t.upstreamUpdatedAt,cwd:t.cwd,...t.title!==void 0?{title:t.title}:{},reason:n,...t.interactive!==void 0?{interactive:t.interactive}:{}}).catch(()=>{})}async deleteRecord(e,t="user"){let n=await this.store.read(e);if(!n)return!1;if(n.upstreamSessionId){let r=await fn(e),o=$t(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:Xa(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),o=await this.histories.load(e,{maxEntries:1/0});if(Ta(o)===0){this.logger?.info(`compaction: zero-turn fast-path swap sessionId=${e} target=${n}`),await this.dispatchSynthesisSwap(e,void 0,o.length,n);return}if(!r?.synopsis||r.summarizedThroughEntry===void 0){this.synopsisCoordinator.scheduleCompaction(e,t);return}if(o.length!==r.summarizedThroughEntry){this.synopsisCoordinator.scheduleCompaction(e,t);return}this.logger?.info(`compaction: fast-path swap sessionId=${e} target=${n} (reusing artifact @${r.summarizedThroughEntry})`),await this.dispatchSynthesisSwap(e,r.synopsis,r.summarizedThroughEntry,n)}catch(r){this.logger?.warn(`scheduleCompaction: fast-path check failed for ${e}: ${r instanceof Error?r.message:String(r)} \u2014 falling back to synthesis`),this.synopsisCoordinator.scheduleCompaction(e,t)}})();return}this.synopsisCoordinator.scheduleCompaction(e,t)}getCompactionInFlight(){let e=this.synopsisCoordinator.size();return e.inflight>0||e.queued>0}async getPendingAgentSwap(e){return(await this.store.read(e).catch(()=>{}))?.pendingAgentSwap}async getCompactionState(e){return(await this.store.read(e).catch(()=>{}))?.compactionState}async persistRollbackBreadcrumb(e,t){await this.mutateRecord(e,{},void 0,n=>{let r=n.rollbackBreadcrumb;return r!==void 0&&t.runId!==void 0&&r.runId===t.runId?(this.logger?.info(`compaction: keeping rollback breadcrumb pinned at ${r.previousUpstreamSessionId} for runId=${t.runId} sessionId=${e} (later swap of the same run)`),{}):{rollbackBreadcrumb:t}})}async getUpstreamGenerations(e){return(await this.store.read(e).catch(()=>{}))?.upstreamGenerations??[]}async getRollbackBreadcrumb(e){return(await this.store.read(e).catch(()=>{}))?.rollbackBreadcrumb}emitSwapPhase(e,t,n){let r=this.get(e);if(r){if(t){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 Ji(t.sessionId).catch(()=>[]);if(n.length===0)continue;let r=Date.now(),o=n.filter(d=>r-d.enqueuedAt<za),i=n.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${za/1e3}s)`),await Xt(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 Xt(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 Pp(s,e){if(typeof s!="string"||s.length===0)return!1;let t=pn.resolve(s),n=pn.resolve(e);return t===n||t.startsWith(n+pn.sep)}function Ja(s,e){if(s===void 0||s.length===0)return!0;let t=Vr(s);if(Vr(e.cwd)===t)return!0;let n=e.workspace?.sourceCwd;return n!==void 0&&Vr(n)===t}function Vr(s){return s.length>1&&s.endsWith("/")?s.replace(/\/+$/,""):s}function Mp(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 Mr({sessionId:s.sessionId,lineageId:e?.lineageId??nn(),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:Ya(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?Xa(e,s.agentId,s.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(s.createdAt).toISOString()})}function Ya(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 _p(s){return s?{...s}:void 0}function $p(s){return(s.extendsChain??[s.id]).some(t=>t==="claude-acp"||t.startsWith("claude-acp-"))}var Op=[{type:"system",subtype:"background_tasks_changed"}];function Gr(s,e={}){if(!$p(s))return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t,emitRawSDKMessages:Op}}}function rs(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=Fp(s,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function Kr(s){return rs(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 Ze(s,e){if(!s||typeof s!="object")return s;let t=s;if(t.code!==C.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=C.AuthRequired,d.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function Va(s){return/^[A-Za-z0-9_\-./=:@]+$/.test(s)?s:`'${s.replace(/'/g,"'\\''")}'`}function Ga(s,e,t,n){if(s&&typeof s=="object"&&s.code===C.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 ${Va(n.cwd)} && ${[n.command,...n.args].map(Va).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(`
170
- `));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 un(s){return s._meta?.steering?.supported===!0}function ln(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 Fp(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 Pt(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.configOptions)}function Mt(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=Ir(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 _t(s){return s.length>0?s:void 0}function Qr(s){return rs(s,{nestedKey:"models",configId:"model",fromObject:e=>{let t=Zt(e.availableModels);return t.length>0?t:void 0},fromConfig:e=>{let t=Zt(e.options);return t.length>0?t:void 0}})??[]}function Yr(s){return rs(s,{nestedKey:"modes",configId:"mode",fromObject:e=>{let t=Dn(e.availableModes);return t.length>0?t:void 0},fromConfig:e=>{let t=Dn(e.options);return t.length>0?t:void 0}})??[]}function Xr(s){return rs(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 Np(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 Ka(s){try{let e=await ct.readFile(A.tuiHistoryFile(s),"utf8"),t=[];for(let n of e.split(`
171
- `))if(n.length!==0)try{let r=JSON.parse(n);typeof r=="string"&&t.push(r)}catch{}return t}catch{return[]}}function Xa(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 fn(s){try{let e=await ct.stat(A.historyFile(s));return{mtime:new Date(e.mtimeMs).toISOString(),hasContent:e.size>0}}catch{return{hasContent:!1}}}function $t(s,e){return s.interactive!==void 0?s.interactive:s.originatingClient?.name===Xn?!1:e?!0:void 0}import{spawn as Dp}from"child_process";import*as is from"fs";import*as Ve from"fs/promises";import*as as from"path";import jp from"pino-roll";var os=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 Hp=1e3,Lp=6e4,Zr=3e3,Ot=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??Hp,this.restartCapMs=r.restartCapMs??Lp;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 Ve.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()},Zr);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 gn(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");if(t.child)throw gn(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 gn(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 gn(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 gn(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{}},Zr);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 os(this.breakerOptions),failureReason:void 0}}async reapOrphans(){let e;try{e=await Ve.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 Ve.readFile(n,"utf8"),i=Number.parseInt(o.trim(),10);Number.isInteger(i)&&i>0&&(r=i)}catch{}if(typeof r=="number"&&eo(r)){try{process.kill(r,"SIGTERM")}catch{}let o=Date.now()+Zr;for(;Date.now()<o&&eo(r);)await new Promise(i=>setTimeout(i,50));if(eo(r))try{process.kill(r,"SIGKILL")}catch{}}await Ve.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=as.dirname(this.adapter.paths.logFile(r.name)),a;try{await Ve.mkdir(i,{recursive:!0}),a=await jp({file:as.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})
172
- `);let d=this.tokenRegistry?.mint(r.name,this.adapter.tokenRole)??n.serviceToken;e.processToken=d,e.version=void 0;let c={...Cn(),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
173
- `),a.end();return}let p=ae(u),f=[...l,...r.args].map(ae),m;try{m=Dp(p,f,{env:c,stdio:["ignore","pipe","pipe"],detached:!1})}catch(h){a.write(`[hydra-acp] failed to spawn ${r.name}: ${h.message}
174
- `),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{is.writeFileSync(this.adapter.paths.pidFile(r.name),`${m.pid}
175
- `,{encoding:"utf8",mode:384})}catch(h){a.write(`[hydra-acp] failed to write pid file for ${r.name}: ${h.message}
176
- `)}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}
177
- `)}),m.on("exit",(h,w)=>{try{is.unlinkSync(this.adapter.paths.pidFile(r.name))}catch{}a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} exited code=${h??"null"} signal=${w??"null"}
178
- `),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}
179
- `);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 eo(s){try{return process.kill(s,0),!0}catch{return!1}}function gn(s,e){return s.code=e,s}Q();var Up={kind:"extension",nameEnvVar:"HYDRA_ACP_EXTENSION_NAME",tokenRole:"extension",paths:{dir:A.extensionsDir,logFile:A.extensionLogFile,pidFile:A.extensionPidFile}},ds=class extends Ot{constructor(e,t,n={}){super(e,Up,t,n)}};Q();var Bp={kind:"transformer",nameEnvVar:"HYDRA_ACP_TRANSFORMER_NAME",tokenRole:"transformer",paths:{dir:A.transformersDir,logFile:A.transformerLogFile,pidFile:A.transformerPidFile}},cs=class extends Ot{connected=new Map;constructor(e,t,n={}){super(e,Bp,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 us=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 to from"fs/promises";async function Za(s){await to.writeFile(A.pidFile(),JSON.stringify(s)+`
180
- `,{encoding:"utf8",mode:384})}Q();import*as hn from"fs/promises";import*as ls from"path";var mn=s=>{process.stderr.write(s+`
181
- `)};function no(s){mn=s??(e=>process.stderr.write(e+`
182
- `))}async function ed(s,e){let t=_e();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=ls.join(A.agentsDir(),t),a;try{a=await hn.readdir(i,{withFileTypes:!0})}catch(d){let c=d;if(c.code==="ENOENT")return;mn(`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=ls.join(i,c),f;try{f=await hn.readdir(p,{withFileTypes:!0})}catch(m){mn(`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=ls.join(p,g);try{await hn.rm(h,{recursive:!0,force:!0}),mn(`hydra-acp: pruned stale ${c} ${g} (${h})`)}catch(w){mn(`hydra-acp: prune: failed to remove ${h}: ${w.message}`)}}}}function td(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 sr(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 so(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 ${Wp(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 nd(s){let e,t=!1,n=!1,r=o=>{t||(e=setTimeout(()=>{(async()=>{if(!n){n=!0;try{await so({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 Wp(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 qp}from"crypto";function yn(s){if(Array.isArray(s))return s.map(yn);if(s!==null&&typeof s=="object"){let e={};for(let t of Object.keys(s).sort())e[t]=yn(s[t]);return e}return s}function sd(s){let e={};for(let[n,r]of Object.entries(s)){let o=Fs(n);if(o.nested){let i={};for(let[a,d]of Object.entries(r??{}))Ns(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(yn(e));return qp("sha256").update(t).digest("hex").slice(0,16)}function rd(s,e){let t=[],n=(r,o)=>JSON.stringify(yn(r))!==JSON.stringify(yn(o));for(let r of Object.keys(e)){let o=Fs(r),i=e[r],a=s[r];if(o.nested){for(let d of Object.keys(i??{})){if(Ns(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 id from"fs/promises";Q();var zp=3e3;async function od(){try{return(await id.stat(A.config())).mtimeMs}catch{return}}function ad(s){let e=s.intervalMs??zp,t=!1,n,r,o=od().then(d=>{r=d}),i=async()=>{await o;let d=await od();if(d===r)return;r=d;let c;try{c=await qt()}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=rd(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();We();import*as ud from"path";import{createHash as Jp,randomBytes as Vp,timingSafeEqual as Gp}from"crypto";var ld="hydra_session_",Kp=3600*24*30,dd=12,Qp=32,Yp=50;function Xp(){return ud.join(A.home(),"session-tokens.json")}function cd(s){return Jp("sha256").update(s).digest("hex")}function fd(s){return Vp(s).toString("hex")}function Zp(){return fd(dd).slice(0,dd*2)}function eg(){return`${ld}${fd(Qp)}`}var fs=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=Xp(),n=await se(t);n&&Array.isArray(n.records)&&(e=n.records.filter(tg));let r=new s(e,t);return r.sweepExpired(new Date)>0&&await r.flush(),r}async issue(e={}){let t=eg(),n=cd(t),r=Zp(),o=new Date,i=e.ttlSec&&e.ttlSec>0?e.ttlSec:Kp,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(ld))return;let t=cd(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||!Gp(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(()=>{})},Yp))}persist(){let e=(this.writeInflight??Promise.resolve()).catch(()=>{}).then(()=>he(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 tg(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 pd="Bearer ",ps=class{constructor(e){this.token=e}token;async validate(e){return sg(e,this.token)?"service":void 0}rotate(e){this.token=e}},gs=class{constructor(e){this.store=e}store;async validate(e){return this.store.verify(e)}},ms=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 gd(s){return async function(t,n){let r=t.headers.authorization;if(!r||!r.startsWith(pd)){n.code(401).send({error:"Missing bearer token"});return}let o=r.slice(pd.length).trim(),i=await s.validator.validate(o);if(!i){n.code(403).send({error:"Invalid token"});return}t.authIdentity=i}}function md(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 hs=class{tokens=new Map;mint(e,t){let n=$s();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}`}},ng=new Set(["GET /v1/sessions","GET /v1/sessions/:id","GET /v1/config"]);function hd(s,e){return e?ng.has(`${s} ${e}`):!1}function sg(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 ys=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 lo from"fs";import*as qd from"os";import*as Is from"path";import*as fo from"readline";Q();function ro(s){return Math.floor(s/4)}function yd(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+=ut(i.content);break;case"tool_call":case"tool_call_update":{let a=typeof i.toolCallId=="string"?i.toolCallId:"",d=rg(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 rg(s){let e=0;return typeof s.title=="string"&&(e+=s.title.length),e+=ws(s.rawInput),e+=ut(s.content),e+=ws(s.rawOutput),e}function ws(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+=ws(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+=ws(n);return t}return 0}function ut(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+=ut(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?ut(e.text):e.type==="diff"?ut(e.oldText)+ut(e.newText):e.content!==void 0?ut(e.content):0}function wd(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=ro(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 og}from"path";import ig from"strip-ansi";function wn(s){if(!s||typeof s!="object")return;let e=s;return typeof e.workerTaskId=="string"?e.workerTaskId:void 0}function oo(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 ag=/[\x00-\x08\x0b-\x1f\x7f]/g;function Ce(s){return ig(s).replace(ag,"")}function ne(s){return Ce(s).replace(/[\n\t]+/g," ").replace(/ +/g," ").trim()}function Sd(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 gg(t);case"agent_thought_chunk":case"agent_thought":return mg(t);case"user_message_chunk":return hg(t);case"prompt_received":return yg(t);case"tool_call":return wg(t,e);case"tool_call_update":return Ig(t,e);case"plan":return Rg(t);case"current_mode_update":return Eg(t);case"_hydra_current_model_update":return Tg(t);case"turn_complete":return Pg(t);case"_hydra_turn_started":return bd(t,"turn-started");case"_hydra_turn_ended":return bd(t,"turn-ended");case"usage_update":return pg(t);case"available_commands_update":return lg(t);case"_hydra_available_modes_update":return fg(t);case"session_info_update":return cg(t);case"config_option_update":return dg(t);default:return{kind:"unknown",sessionUpdate:n,raw:s}}}function dg(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 cg(s){let e=te(s,"title"),t=e!==void 0?ne(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 ug(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:ne(r)};typeof n.description=="string"&&(o.description=ne(n.description)),e.push(o)}return e}function lg(s){let e=s.availableCommands??s.commands;return Array.isArray(e)?{kind:"available-commands",commands:ug(e)}:null}function fg(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:ne(r.id)};typeof r.name=="string"&&(o.name=ne(r.name)),typeof r.description=="string"&&(o.description=ne(r.description)),t.push(o)}return{kind:"available-modes",modes:t}}function pg(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 gg(s){let e=kn(s.content);return e===null?null:{kind:"agent-text",text:e,workerTaskId:wn(s)}}function mg(s){let e=typeof s.text=="string"?Ce(s.text):kn(s.content);return e===null?null:{kind:"agent-thought",text:e,workerTaskId:wn(s)}}function hg(s){let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){let n=e["hydra-acp"];if(n&&typeof n=="object"&&!Array.isArray(n)&&n.compatFor==="prompt_received")return null}let t=kn(s.content);return t===null?null:{kind:"user-text",text:t}}function yg(s){let e=Mg(s.prompt);return e===null?null:{kind:"user-text",text:e}}function Id(s){return s?s.toLowerCase().replace(/[_\s-]/g,"")==="exitplanmode":!1}function kd(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 ks(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=kd(r.oldText),i=kd(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 Ad(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:Ce(t)}function wg(s,e={}){let t=te(s,"toolCallId")??te(s,"id");if(!t)return null;let n=te(s,"title")??te(s,"name")??te(s,"label")??"tool call",r=te(s,"name")??te(s,"title");if(Id(r)){let g=Ad(s);if(g!==null){let h=te(s,"status"),w={kind:"exit-plan-mode",toolCallId:t,plan:g};return h!==void 0&&(w.status=h),w}}let o=Rd(ne(n),s,e),i=te(s,"status"),a=te(s,"kind"),d={kind:"tool-call",toolCallId:t,title:o};i!==void 0&&(d.status=i),a!==void 0&&(d.rawKind=a);let c=ks(s);c!==null&&(d.editDiff=c);let u=xd(s);u!==void 0&&(d.detail=u);let l=io(s);l!==void 0&&(d.detailFull=l);let p=Cd(s);p!==void 0&&(d.locations=p);let f=wn(s);f!==void 0&&(d.workerTaskId=f);let m=oo(s);return m!==void 0&&(d.parentToolUseId=m),d}function Cd(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 vd=64;function xd(s){let e=io(s);if(e===void 0)return;let t=ne(e),n=s.rawInput;return n&&typeof n.command=="string"?bg(t,vd):Sg(t,vd)}function io(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 Ce(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 $(ne(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 $(ne(n))}}}var kg=["home/","Users/","root/","tmp/","var/","opt/","etc/","usr/","mnt/","private/"];function vg(s){for(let e of kg)if(s.startsWith(e))return!0;return!1}function Rd(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 vg(s)?$(`/${s}`):t.cwd&&t.cwd.length>0?$(og.resolve(t.cwd,s)):s}function bg(s,e){return s.length>e?`${s.slice(0,e-1)}\u2026`:s}function Sg(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 Ig(s,e={}){let t=te(s,"toolCallId")??te(s,"id");if(!t)return null;let n=te(s,"title"),r=n!==void 0?Rd(ne(n),s,e):void 0,o=te(s,"status"),i=ks(s),a=xd(s),d=Ag(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=te(s,"name")??n;if(Id(u)){let h={kind:"exit-plan-mode",toolCallId:t},w=Ad(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=io(s);p!==void 0&&(l.detailFull=p);let f=Cd(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=Cg(s);h!==null&&(l.errorText=h),xg(s,h)&&(l.upstreamInterrupted=!0)}let m=wn(s);m!==void 0&&(l.workerTaskId=m);let g=oo(s);return g!==void 0&&(l.parentToolUseId=g),l}function Ag(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 Cg(s){let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let o=kn(n.content);if(o!==null&&o.length>0)return o}let t=s.rawOutput;if(t&&typeof t=="object"){let n=t.error;if(typeof n=="string"&&n.length>0)return Ce(n)}return null}function xg(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 Rg(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"?ne(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 Eg(s){let e=te(s,"currentModeId")??te(s,"currentMode")??te(s,"mode");return e?{kind:"mode-changed",mode:ne(e)}:null}function Tg(s){let e=te(s,"currentModel")??te(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:ne(e),...n&&n.length>0?{availableModels:n}:{}}}function Pg(s){let e=te(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 bd(s,e){let n=s._meta?.["hydra-acp"],r=n?.unsolicited===!0;if(e==="turn-started"){let i=n?.cause?.label,a={kind:e,unsolicited:r};return typeof i=="string"&&i.length>0&&(a.cause=i),a}let o={kind:e,unsolicited:r};return typeof n?.reason=="string"&&(o.reason=n.reason),o}function kn(s){if(typeof s=="string")return Ce(s);if(!s||typeof s!="object")return null;let e=s;return e.type==="text"&&typeof e.text=="string"||typeof e.text=="string"?Ce(e.text):null}function Mg(s){if(!Array.isArray(s))return null;let e=[];for(let t of s){let n=kn(t);n!==null&&e.push(n)}return e.length===0?null:e.join("")}function te(s,e){let t=s[e];return typeof t=="string"?t:void 0}function Ed(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=$g(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)_g(t,l)}let n=[];for(let[r,o]of t)n.push({path:r,hunks:o.hunks,created:o.created});return n}function Td(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 _g(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 $g(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=ks(s);return r&&r.path&&e.push({path:r.path,oldText:r.oldText,newText:r.newText}),e}function Md(s,e={}){let t=Fg(s),{events:n,window:r}=Og(t,e),o=Ng(n),i=[];Dg(i,s),r&&(r.from>1||r.to<r.total)&&(i.push(`_Showing turns ${r.from}-${r.to} of ${r.total}._`),i.push("")),jg(i,n,o,{includeTools:e.includeTools??!1,includeThoughts:e.includeThoughts??!1});let a=i.join(`
158
+ `)}if(t==="discard"){let a=this.liveSessionsIn(i.path,o.sessionId);if(a.length>0)throw new Error(`${F(i.path)} is shared with ${a.map(u=>Ke(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 ${F(i.path)} and its branch ${i.line??"(none)"}; returned to ${F(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(`
159
+ `)}return o.broadcastWorkspacePhase({phase:"returning"}),await this.leaveWorkspace(o,i,{exit:"detached"}),[`Returned to ${F(i.sourceCwd)} WITHOUT merging.`,`The workspace is still at ${F(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(`
160
+ `)}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=ne(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(`${F(t.path)} is shared with ${r.map(k=>Ke(k.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=ne(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,m=await i.currentState(t.path)??"",h=await this.retireAutosave(t);e.broadcastWorkspacePhase({phase:"cleaning",label:t.label});let f=await i.resetTo(t.path,d,{purgeIgnored:n.deep});if(!f.ok)throw new Error(`could not return ${F(t.path)} to its base: ${f.reason??"unknown error"}. Nothing was changed.`);let g=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 y=[`Cleaned ${F(t.path)} back to the state it was created in.`];if(u>0||p>0){let k=[];u>0&&k.push(`${u} uncommitted change(s)`),p>0&&k.push(`${p} commit(s)`),y.push(` discarded ${k.join(" and ")}`)}else y.push(" nothing to discard; it was already at its base");return g!==void 0&&y.push(` ${g}`),h!==void 0&&y.push(` last autosave kept at ${h}: git -C ${t.sourceCwd} checkout ${h}`),p>0&&m.length>0&&y.push(` discarded commits are still at ${m.slice(0,12)} (and in the reflog for ${t.line??"this branch"})`),y.push(`Your uncommitted work in ${F(t.sourceCwd)} was never touched by this.`),y.join(`
161
+ `)})}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 ${F(n)} no longer exists`);let i=ne(e.provider),a=this.asWorkspace(e),d=await so({source:n,ws:a,startSnapshotRef:this.startRefFor(e.label),baselineRef:this.baselineRefFor(e.label),retainRef:no(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 ${F(n)}`);let u=await i.contains(n,{state:c,within:r}),l=[];if(!u){let v=this.get(t),E="";if(v!==void 0)try{let A=await this.syncWorkspaceFromSource(v,e,{onConflict:"abort"});A.ok?(l.push(`
162
+ synced with the source first: ${A.message}`),u=await i.contains(n,{state:c,within:r})):E=`
163
+ A sync was attempted first and could not complete: ${A.message}`}catch(A){E=`
164
+ A sync was attempted first but was refused: ${A instanceof Error?A.message:String(A)}`}if(!u){let A=await i.currentLineName(n)??"the source";throw new Error(`cannot fast-forward ${A} in ${F(n)} to ${r}. The source has moved on since this workspace was created. The source is untouched.${E}
165
+ `+(E.length>0?`Or land it by hand with: git -C ${n} merge ${r}`:`Resolve it in the workspace with \`/hydra workspace sync\` (which leaves the conflict there to fix), or land it by hand with: git -C ${n} merge ${r}`))}}let p=i!==void 0&&i.capabilities().supports.nestedTrees?await i.captureNested(e.path,await i.listNested(e.path)).catch(()=>[]):[],m,h=await i.status(a).catch(()=>{});if(h!==void 0&&h.changedPaths.length>0&&(m=await i.captureWorkingState(e.path,`hydra: uncommitted work in ${e.label}`).catch(()=>{}),m===void 0))throw new Error(`could not capture the uncommitted work in ${F(e.path)}; nothing was changed`);if(!d.clean&&!(await i.resetTo(n,c)).ok)throw new Error(`could not clear ${F(n)} for the merge; your work is preserved at ${d.retainedRef}. Nothing was merged.`);let f=await i.integrate({into:n,from:r,fastForwardOnly:!0});if(!f.ok)throw new Error(`merge failed: ${f.reason??"unknown error"}`);let g=!0;if(m!==void 0){let v=await i.captureDelta(n,f.snapshot,m);v!==void 0&&(g=(await i.applyDelta(n,v)).ok)}let w=await ht({source:n,capture:d,provider:i});w&&await mn({source:n,ws:a,capture:d,provider:i});let y={applied:[],failed:[]},k=i!==void 0&&i.capabilities().supports.nestedTrees?await i.integrateNested(n,e.path,p).catch(()=>y):y,b=await i.captureWorkingState(n,`hydra: source state after landing ${e.label}`).catch(()=>{});b!==void 0&&await i.retainSnapshot({...a,path:n},this.baselineRefFor(e.label),b).catch(()=>{});let S=[];g||S.push(` WARNING: the workspace's uncommitted changes could not be replayed; they remain reachable from ${r}.`),w||S.push(e.clean===!0?` WARNING: this workspace started clean, so your uncommitted work was never copied in. The whole of it is being replayed now and it overlaps what the agent changed. All of it is preserved at ${d.retainedRef}; recover with: git -C ${n} diff ${d.base} ${d.retainedRef}`:` WARNING: your own edits to ${F(n)} overlap the workspace's changes and could not be replayed on top. They are preserved at ${d.retainedRef}; recover with: git -C ${n} diff ${d.base} ${d.retainedRef}`);for(let v of k.failed)S.push(` WARNING: nested tree ${v.path} was NOT reconciled: ${v.reason}. ${F(n)} now records a different state for it, so it will report it as modified until you resolve that.`);return{merged:`Merged ${r} into ${F(n)}${l.join("")}`,warnings:S}}async applyWorkspaceToSource(e,t){let n=e.sourceCwd;if(!await this.dirExists(n))throw new Error(`source tree ${F(n)} no longer exists`);let r=ne(e.provider);if(r===void 0)throw new Error(`no provider "${e.provider}" available to apply this workspace`);if(!r.capabilities().supports.captureWorkingState)throw new Error(`provider "${e.provider}" cannot snapshot a working tree, so there is no change set to apply. Use \`/hydra workspace stop\` to land this workspace instead.`);let o=this.asWorkspace(e);if((await r.status({...o,path:n}).catch(()=>{}))?.hasStagedWork===!0)throw new Error(`${F(n)} already has changes staged for its next commit, and \`apply\` delivers into that same index: the two sets would be indistinguishable, and unstaging one would unstage both. Commit or unstage them first, or use \`/hydra workspace merge\`, which lands the work as commits and does not touch the index.`);let a=await r.currentState(n);if(a===void 0)throw new Error(`could not read the state of ${F(n)}`);let d=e.line,c=d!==void 0&&await r.contains(n,{state:a,within:d}).catch(()=>!1),u=c?a:e.snapshot??"";if(u.length===0)throw new Error(`workspace ${e.label} has no recorded base to measure its changes against, so there is no way to tell its work apart from what the source already had`);let l=await so({source:n,ws:o,startSnapshotRef:this.startRefFor(e.label),baselineRef:this.baselineRefFor(e.label),retainRef:no(t),provider:r}),p=r.capabilities().supports.nestedTrees?(await r.listNested(e.path).catch(()=>[])).filter(k=>k.changedPaths.length>0||k.recorded!==void 0&&k.recorded!==k.actual):[],m=await r.captureWorkingState(e.path,`hydra: apply from ${e.label}`).catch(()=>{});if(m===void 0)throw new Error(`could not snapshot the work in ${F(e.path)}; nothing was changed`);let h=await r.captureDelta(n,u,m);if(h===void 0)throw new Error(`could not work out what ${e.label} changed; ${F(n)} was not touched`);if(h.trim().length===0)return await mn({source:n,ws:o,capture:l,provider:r}),{applied:`Nothing to apply: ${e.label} holds no changes ${F(n)} does not already have.`,warnings:[]};if(!l.clean&&!(await r.resetTo(n,a)).ok)throw new Error(`could not clear ${F(n)} to apply onto; your work is preserved at ${l.retainedRef}. Nothing was applied.`);let f=await r.applyDelta(n,h,{stage:!0,tolerant:!c});if(!f.ok){await r.resetTo(n,a).catch(()=>{});let k=await ht({source:n,capture:l,provider:r});throw k&&await mn({source:n,ws:o,capture:l,provider:r}),new Error(`could not apply ${e.label} into ${F(n)}: ${f.reason??"the change set did not apply"}.`+(c?"":" The source has moved on since this workspace was created; `/hydra workspace sync` brings those commits in here, which is what lets the change set apply against them.")+(k?` ${F(n)} is as you left it.`:` Your uncommitted work there is preserved at ${l.retainedRef}.`))}let g=await ht({source:n,capture:l,provider:r});g&&await mn({source:n,ws:o,capture:l,provider:r});let w=await r.captureWorkingState(n,`hydra: source state after applying ${e.label}`).catch(()=>{});w!==void 0&&await r.retainSnapshot({...o,path:n},this.baselineRefFor(e.label),w).catch(()=>{});let y=[];f.alreadyPresent===!0&&y.push(` Nothing was staged: ${F(n)} already had every one of those changes.`),g||y.push(` WARNING: your own edits to ${F(n)} overlap the workspace's changes and could not be replayed on top. They are preserved at ${l.retainedRef}; recover with: git -C ${n} diff ${l.base} ${l.retainedRef}`);for(let k of p)y.push(` WARNING: nested tree ${k.relPath} was NOT included: a change set can only move the pointer to it, not what is inside. Land it with \`/hydra workspace stop\`, or copy that work across by hand.`);return{applied:`Applied ${e.label} into ${F(n)} as staged changes; still working in ${F(e.path)}.
166
+ Nothing was committed: review it with \`git -C ${n} diff --cached\` and commit it however you like. The workspace and its history are untouched.`,warnings:y}}async leaveWorkspace(e,t,n){let r=n.exit!=="detached",o=ne(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 ${F(t)} with ${F(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`${F(t)} and ${F(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=ne(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(`${F(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=>Ke(u.sessionId)),c=[`Joined workspace ${F(n.path)}`,` source: ${F(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(`
167
+ `)})}async startWorkspace(e,t,n){if(e.workspace!==void 0)throw new Error(`already isolated in ${F(e.workspace.path)}. Use \`/hydra workspace stop\` to merge and return first, or \`detach\` to leave it behind.`);let r=e.cwd,o=ne();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=[],m=[],h=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 E=a.supports.nestedTrees&&v!==void 0&&v.changedPaths.length>0?await o.listNested(r).catch(()=>[]):[];if(v!==void 0&&v.changedPaths.length>0&&h)p=Yr(v.changedPaths,E);else if(v!==void 0&&v.changedPaths.length>0&&(c=Yr(v.changedPaths,E),m=await o.captureNested(r,E).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 f=await o.createWorkspace({sourceCwd:r,label:t??`s-${e.sessionId.slice(-8)}`});if(!f.ok)throw e.broadcastWorkspacePhase({phase:"failed",error:f.reason}),new Error(f.reason);let g=f.workspace,w=this.startRefFor(g.label),y,k=!1,b=[];try{a.locking&&await o.lock(g,`session ${e.sessionId}`).catch(()=>{});let v=d??g.snapshot;if(v===void 0)throw new Error(`provider "${g.provider}" gave the workspace no base to anchor landing against`);await o.retainSnapshot(g,w,v),e.broadcastWorkspacePhase({phase:"setup"}),k=d!==void 0?await this.copyCarriedWork(g,d,r):!0;let E=await this.materializeNestedTrees(g);if(m.length>0){let C=await o.reproduceNested(g.path,r,m).catch(T=>({applied:[],failed:m.map(M=>({path:M.relPath,reason:T instanceof Error?T.message:String(T)}))}));C.failed.length>0&&(k=!1,b=C.failed)}y=await this.applyWorkspaceSetup(g,e.sessionId),E!==void 0&&(y=y===void 0?E:`${E}; ${y}`),e.broadcastWorkspacePhase({phase:"swapping"});let A=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:g.path,workspace:{path:g.path,sourceCwd:g.sourceCwd,label:g.label,...t!==void 0&&t!==g.label?{requestedLabel:t}:{},provider:g.provider,...g.snapshot!==void 0?{snapshot:g.snapshot}:{},...g.line!==void 0?{line:g.line}:{},...g.vcs!==void 0?{vcs:{...g.vcs}}:{},...d===void 0?{clean:!0}:{}},historyLength:A.length,note:`Continuing in an isolated workspace at ${g.path}, derived from ${r}.`,...await this.recordSynopsisFor(e.sessionId)})}catch(v){let E=await this.unwindStartWorkspace({provider:o,ws:g,startRef:w,carried:d}),A=v instanceof Error?v.message:String(v);throw e.broadcastWorkspacePhase({phase:"failed",error:A}),new Error(E===void 0?A:`${A}
168
+ ${E}`)}await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:g.sourceCwd,label:g.label,...g.line!==void 0?{branch:g.line}:{}});let S=[`Moved into workspace ${F(g.path)}`,` source: ${F(r)}`];if(g.line!==void 0&&S.push(` branch: ${g.line}`),t!==void 0&&t!==g.label&&S.push(` note: "${t}" was already taken by a surviving branch, so this is "${g.label}"`),d!==void 0){S.push(k?` 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 mt(c))S.push(` ${v}`);k&&u&&S.push(" staging did not come along; everything above is unstaged here");for(let v of b)S.push(` nested tree ${v.path}: ${v.reason}`)}else if(p.length>0){S.push(` started clean: ${p.length} uncommitted file(s) stayed in the source and did NOT come along:`);for(let v of mt(p))S.push(` ${v}`)}else l&&S.push(" source tree was clean; nothing carried in");return y!==void 0&&S.push(` ${y}`),S.push("Use `/hydra workspace stop` to merge back and return."),S.join(`
169
+ `)}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=ne(e.provider);return o===void 0?!1:(await o.applyDelta(e.path,r)).ok}async patchFromSnapshot(e,t,n){let r=ne(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=ne(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 is(e.sourceCwd).catch(()=>({})),r=[];if(n.carry!==void 0&&n.carry.length>0){let o=await ro(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 as(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=ne(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=ne(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=ne(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 f=new Error(`agent ${e} not found in registry`);throw f.code=x.AgentNotInstalled,f}let n=await Re(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:vd.homedir(),plan:n}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:xt,clientInfo:{name:"hydra",version:me}})}catch(f){throw await r.kill().catch(()=>{}),ot(f,r)}if(r.authMethods=vn(o.authMethods),r.steeringSupported=kn(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(f){throw await r.kill().catch(()=>{}),f}await r.kill().catch(()=>{});let d=new Map,c=kr(t);d.set(e,c);let u=new Set;for(let f of this.sessions.values()){let g=await this.agentStoreKey(f.agentId,d);u.add(`${g}::${f.upstreamSessionId}`)}let l=await this.store.list().catch(()=>[]);for(let f of l){u.add(`${await this.agentStoreKey(f.agentId,d)}::${f.upstreamSessionId}`);for(let g of f.upstreamGenerations??[])u.add(`${await this.agentStoreKey(g.agentId,d)}::${g.upstreamSessionId}`)}let p=R.sessionsDir(),m=[],h=0;for(let f of a){let g=`${c}::${f.sessionId}`;if(u.has(g)){h+=1;continue}if(ig(f.cwd,p)){h+=1;continue}let w=c,y=await this.tombstones.read(w,f.sessionId).catch(()=>{});if(!y&&c!==e&&(w=e,y=await this.tombstones.read(w,f.sessionId).catch(()=>{})),y){if(!za(y,f.updatedAt)){h+=1;continue}await this.tombstones.remove(w,f.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${f.sessionId} (upstream updatedAt advanced past ${y.upstreamUpdatedAt??"<unset>"})`)}u.add(g);let k=`${qe}${jt()}`,b=new Date().toISOString(),S=f.updatedAt??b,v={sessionId:k,lineageId:fn(),upstreamSessionId:f.sessionId,agentId:e,cwd:f.cwd,pendingHistorySync:!0,interactive:!0,createdAt:S,updatedAt:S};f.title!==void 0&&(v.title=f.title);let E=Kr(v);await this.store.write(E),m.push({version:1,...E})}return{synced:m,skipped:h}}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 rt({request:(d,c)=>e.connection.request(d,c),sessionId:t,modelId:n,...o?{verb:o}:{},logger:this.logger});return this.logger?.info(`${r}: ${i} accepted`),{accepted:!0,result:a}}catch(i){return this.logger?.warn(`${r} rejected by agent (${i.message}); session will use the agent's own default`),{accepted:!1}}}async applySeedMode(e,t,n,r){try{let o=await e.connection.request("session/set_mode",{sessionId:t,modeId:n});return this.logger?.info(`${r}: session/set_mode accepted`),{accepted:!0,result:o}}catch(o){return this.logger?.warn(`${r} rejected by agent (${o.message}); session will use the agent's own default mode`),{accepted:!1}}}async 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=x.AgentNotInstalled,i}let n=await Re(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),r=Nn(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:xt,clientInfo:{name:"hydra",version:me}}),a=i.agentCapabilities;o.authMethods=vn(i.authMethods),o.steeringSupported=kn(i);let d=po(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=go(c),p=mo(c),m=Et(c),h=tn(this.sessionDefaults,t),f=h?.value,g=e.configDefaults,w=h?.from??e.agentId,y=e.model??g?.model??f?.model,k;if(y&&y!==l){let C=_t(y,p),T=e.model!==void 0?`model=${JSON.stringify(y)}`:g?.model!==void 0?`configDefaults.model=${JSON.stringify(y)}`:`sessionDefaults[${w}].model=${JSON.stringify(y)}`;if(C.kind==="exact"||C.kind==="none"){let M=await this.applySeedModel(o,u,y,T,m);M.accepted&&(l=y,k=M.result)}else if(C.kind==="resolved")if(C.modelId===l)l=C.modelId;else{let M=await this.applySeedModel(o,u,C.modelId,`${T} resolved to ${JSON.stringify(C.modelId)}`,m);M.accepted&&(l=C.modelId,k=M.result)}else if(C.kind==="ambiguous")this.logger?.warn(`${T} is ambiguous (trailing-segment matches [${C.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(l)}`);else{let M=p.map(H=>H.modelId).join(", ");this.logger?.warn(`${T} not in agent's availableModels ([${M}]); skipping session/set_model, session will use ${JSON.stringify(l)}`)}}let b=ho(c),S=yo(c),v=g?.mode??f?.mode;if(v&&v!==S){let C=g?.mode!==void 0?`configDefaults.mode=${JSON.stringify(v)}`:`sessionDefaults[${w}].mode=${JSON.stringify(v)}`;if(b.length>0&&!b.some(T=>T.id===v)){let T=b.map(M=>M.id).join(", ");this.logger?.warn(`${C} not in agent's availableModes ([${T}]); skipping session/set_mode, session will use ${JSON.stringify(S)}`)}else{let T=await this.applySeedMode(o,u,v,C);T.accepted&&(S=v,Ht(T.result)&&(k=T.result))}}let E={...f??{},...g??{}};if(delete E.model,delete E.mode,Object.keys(E).length>0){let C=Lt(Ht(k)?k:c);for(let[T,M]of Object.entries(E)){let H=`sessionDefaults[${w}].${T}=${JSON.stringify(M)}`,J=C.find(q=>q.id===T);if(!J){this.logger?.warn(`${H}: agent does not currently advertise configId=${T}; skipping session/set_config_option`);continue}let $=rn(M,J.options.map(q=>q.value));if($.kind!=="exact"&&$.kind!=="resolved"){this.logger?.warn(`${H} ${$.kind}; skipping session/set_config_option`);continue}let W=$.kind==="resolved"?$.modelId:M;if(W!==J.currentValue)try{let q=await o.connection.request("session/set_config_option",{sessionId:u,configId:T,value:W});this.logger?.info(`${H}: session/set_config_option accepted`),Ht(q)&&(C=Lt(q),k=q)}catch(q){this.logger?.warn(`${H}: session/set_config_option rejected by agent (${q.message})`)}}}let A=Lt(Ht(k)?k:c);return{agent:o,upstreamSessionId:u,agentMeta:c._meta,agentCapabilities:a,initialModel:l,initialModels:p.length>0?p:void 0,initialModes:b.length>0?b:void 0,initialMode:S,initialConfigOptions:A.length>0?A:void 0,modelVerb:m}}catch(i){throw await o.kill().catch(()=>{}),ot(wd(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=x.AgentNotInstalled,a}let r=await Re(n,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=Nn(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:xt,clientInfo:{name:"hydra",version:me}}),d=a.agentCapabilities;i.authMethods=vn(a.authMethods),i.steeringSupported=kn(a);let c=po(n),u=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),l=go(u),p=Ut(mo(u)),m=ho(u),h=yo(u),f=Ut(Lt(u));return{agent:i,upstreamSessionId:e,agentMeta:u._meta,agentCapabilities:d,initialModel:l,initialModels:p,initialModes:m.length>0?m:void 0,initialMode:h,initialConfigOptions:f,modelVerb:Et(u)}}catch(a){throw await i.kill().catch(()=>{}),ot(wd(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=x.AgentNotInstalled,d}let o=await Re(r,[],{npmRegistry:this.npmRegistry}),i=t??le(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let d=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:xt,clientInfo:{name:"hydra",version:me}});a.authMethods=vn(d.authMethods),a.steeringSupported=kn(d)}catch(d){throw await a.kill().catch(()=>{}),ot(d,a)}return this.pendingAuthAgents.set(e,a),a.onExit(()=>{this.pendingAuthAgents.get(e)===a&&this.pendingAuthAgents.delete(e)}),a}async planSpawnForAgent(e){let t=await this.registry.getAgent(e);if(!t){let n=new Error(`agent ${e} not found in registry`);throw n.code=x.AgentNotInstalled,n}return Re(t,[],{npmRegistry:this.npmRegistry})}consumePendingAuthAgent(e){let t=this.pendingAuthAgents.get(e);if(t&&(this.pendingAuthAgents.delete(e),!!t.isAlive()))return t}getAgentForSession(e){return this.sessions.get(e)?.agent}async attachManagerHooks(e){e.onClose(({deleteRecord:t})=>{if(this.sessions.delete(e.sessionId),this.driftNoticed.delete(e.sessionId),this.invalidateListCache(),t||this.store.touch(e.sessionId).catch(()=>{}),t&&e.workspace!==void 0&&this.releaseWorkspace(e.workspace,e.sessionId).catch(()=>{}),t){if(e.upstreamSessionId){let r=Bt({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:bd(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=ag(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 en(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:dg(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=gt(r.update.prompt),a=Br(i,200);if(a&&!a.startsWith("/"))return a}}get(e){return this.sessions.get(e)}liveSessions(){return this.sessions.values()}setLiveConfig(e){e.sessionDefaults&&(this.sessionDefaults=e.sessionDefaults)}activeAgentVersions(){let e=new Map;for(let t of this.sessions.values()){let n=t.agent.installId,r=t.agent.version,o=e.get(n);o||(o=new Set,e.set(n,o)),o.add(r)}return e}async resolveCanonicalId(e){if(this.sessions.has(e)||await this.store.read(e))return e;if(e.startsWith(qe))return;let t=qe+e;if(this.sessions.has(t)||await this.store.read(t))return t}require(e){let t=this.sessions.get(e);if(!t){let n=new Error(`session ${e} not found`);throw n.code=x.SessionNotFound,n}return t}liveListEntry(e){return{sessionId:e.sessionId,upstreamSessionId:e.upstreamSessionId,cwd:e.cwd,workspace:e.workspace,workspaceError:e.workspaceError,title:e.title,agentId:e.agentId,currentModel:e.currentModel,currentUsage:e.currentUsage,parentSessionId:e.parentSessionId,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,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 bn(t.sessionId),d=Bt({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 bn(n.sessionId),o=Bt(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:wn(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={}){return(await this.listing(e)).entries}async listing(e={}){let t=`${e.cwd??""}|${e.includeNonInteractive?"1":"0"}|${e.status??""}`,n=Date.now(),r=this.listCache.get(t);if(r&&r.expiresAt>n)return r.promise;let o=this.listUncached(e);return this.listCache.set(t,{expiresAt:n+s.LIST_CACHE_TTL_MS,promise:o}),o.catch(()=>{let i=this.listCache.get(t);i&&i.promise===o&&this.listCache.delete(t)}),o}invalidateListCache(){this.listCache.clear()}async listUncached(e={}){let t=await this.store.cursor(),{entries:n,liveIds:r}=await this.warmRows(e);if(e.status==="warm")return{entries:n,cursor:t};let o=await this.store.list().catch(i=>{throw this.logger?.warn(`session list: store.list() failed: ${i?.message??String(i)}`),i});return n.push(...await this.coldRows(o,r,e)),n.sort((i,a)=>i.updatedAt<a.updatedAt?1:-1),{entries:n,cursor:t}}async listSince(e,t){let{entries:n,liveIds:r}=await this.warmRows(e);if(e.status==="warm")return{entries:n,removed:[],cursor:await this.store.cursor()};let o=await this.store.listChangedSince(t);return n.push(...await this.coldRows(o.records,r,e)),n.sort((i,a)=>i.updatedAt<a.updatedAt?1:-1),{entries:n,removed:o.removed,cursor:o.cursor}}async seedSessionIndex(){await this.store.ensureIndex();let e=await this.tombstones.list().catch(()=>[]);for(let t of e){if(t.sessionId===void 0)continue;let n=Date.parse(t.deletedAt);Number.isNaN(n)||await this.store.markDeleted(t.sessionId,n)}}static includeRow(e,t){return e.includeNonInteractive?!0:t===!0}async warmRows(e){let t=[],n=new Set,r=[...this.sessions.values()].filter(i=>hd(e.cwd,i));if(e.status==="cold"){for(let i of r)n.add(i.sessionId);return{entries:t,liveIds:n}}let o=await Promise.all(r.map(i=>bn(i.sessionId)));for(let i=0;i<o.length;i+=1){let a=r[i],d=o[i];n.add(a.sessionId);let c=Bt({interactive:a.interactive,...a.originatingClient?{originatingClient:a.originatingClient}:{}},d.hasContent);if(!s.includeRow(e,c))continue;let u=d.mtime??new Date(a.updatedAt).toISOString();t.push({sessionId:a.sessionId,upstreamSessionId:a.upstreamSessionId,cwd:a.cwd,workspace:a.workspace,workspaceError:a.workspaceError,title:a.title,agentId:a.agentId,currentModel:a.currentModel,currentUsage:a.currentUsage,parentSessionId:a.parentSessionId,forkedFromSessionId:a.forkedFromSessionId,forkedFromMessageId:a.forkedFromMessageId,originatingClient:a.originatingClient,interactive:c,priority:a.priority,updatedAt:u,attachedClients:a.attachedCount,status:"warm",agentPid:a.agentPid,busy:a.turnStartedAt!==void 0,armedTasks:a.armedBackgroundTasks.length,...a.armedSince!==void 0?{armedSince:a.armedSince}:{},awaitingInput:a.awaitingInput,compactionState:a.compactionState,forkSynthesisState:a.forkSynthesisState})}return{entries:t,liveIds:n}}async coldRows(e,t,n){let r=[],o=e.filter(a=>!t.has(a.sessionId)&&hd(n.cwd,a)),i=await Promise.all(o.map(a=>bn(a.sessionId)));for(let a=0;a<o.length;a+=1){let d=o[a],c=i[a],u=Bt(d,c.hasContent);if(!s.includeRow(n,u))continue;let l=c.mtime??d.updatedAt;r.push({sessionId:d.sessionId,upstreamSessionId:d.upstreamSessionId,cwd:d.cwd,workspace:d.workspace,title:d.title,agentId:d.agentId,currentModel:d.currentModel,currentUsage:wn(d.currentUsage),importedFromMachine:d.importedFromMachine,importedFromUpstreamSessionId:d.importedFromUpstreamSessionId,parentSessionId:d.parentSessionId,forkedFromSessionId:d.forkedFromSessionId,forkedFromMessageId:d.forkedFromMessageId,originatingClient:d.originatingClient,interactive:u,priority:d.priority,updatedAt:l,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,compactionState:d.compactionState,forkSynthesisState:d.forkSynthesisState})}return r}async exportBundle(e,t={}){let n=await this.store.read(e);if(!n)return;let r;if(n.lineageId)r=n;else{let c=fn(),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 kd(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let d={};for(let c of dd(i)){let u=await fi(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=x.BundleAlreadyImported,i.existingSessionId=n.sessionId,i}let o=this.sessions.get(n.sessionId);return o&&await o.close({deleteRecord:!1,by:"bundle-import-overwrite"}).catch(()=>{}),await this.writeImportedRecord({sessionId:n.sessionId,bundle:e,preservedCreatedAt:n.createdAt,cwd:t.cwd}),{sessionId:n.sessionId,importedFromSessionId:e.session.sessionId,replaced:!0}}let r=`${qe}${jt()}`;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 S=new Error(`source session not found: ${e}`);throw S.code=x.SessionNotFound,S}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=x.AgentNotInstalled,v}let i=await this.histories.load(e).catch(()=>[]),a=i,d,c=t.mode??"synthesis",u,l,p,m=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let S=Qn(i,t.forkAt);if(S<0){let v=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw v.code=x.InvalidParams,v}d=t.forkAt,a=i.slice(0,S+1)}else{let S=fg(i);S?(d=S.messageId,a=i.slice(0,S.index+1)):(d="",a=i.slice(0,0))}else{if(t.forkAt!==void 0&&t.forkAt!==""){let v=Qn(i,t.forkAt);if(v<0){let E=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw E.code=x.InvalidParams,E}d=t.forkAt,a=i.slice(0,v+1)}else d="",a=i;let S=await this.registry.getAgent(r);if(!S){let v=new Error(`agent ${r} not found in registry`);throw v.code=x.AgentNotInstalled,v}p=S,l=n.currentModel,u="running"}let h=await kd(e),f=c==="synthesis",g={...n,lineageId:fn(),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=yn({record:g,history:a,promptHistory:h.length>0?h:void 0,hydraVersion:me,machine:sn()}),y=`${qe}${jt()}`,k=t.cwd,b;if(t.cwd===void 0&&n.workspace!==void 0){let S=await this.deriveForkWorkspace(n.workspace,`${n.workspace.label}-fork-${y.slice(-6)}`);S!==void 0?(b=S,k=S.path):(k=n.workspace.sourceCwd,this.logger?.warn?.(`fork ${y}: could not derive an isolated workspace from ${n.workspace.path}; running unisolated in ${k}`))}return await this.writeImportedRecord({sessionId:y,bundle:w,cwd:k,...b!==void 0?{workspace:b}:{},forkedFromSessionId:e,forkedFromMessageId:d,...u!==void 0?{forkSynthesisState:u}:{}}),f&&(async()=>{try{let S=await Re(p,[],{npmRegistry:this.npmRegistry}),v=await ls({agentId:r,cwd:t.cwd??R.sessionDir(e),plan:S,history:a,modelId:l,sessionId:e,logger:this.logger,timeoutMs:m});v&&v.synopsis?await this.mutateRecord(y,{synopsis:v.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(y,{},["forkSynthesisState"]))}catch(S){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${S.message}`);try{await this.mutateRecord(y,{},["forkSynthesisState"])}catch(v){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${v.message}`)}}})(),{sessionId:y,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 pi(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await yt.utimes(R.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await pd(R.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=kr(o))}catch{}return t.set(e,r),r}async tombstoneAllGenerations(e,t,n){let r=await this.store.read(e).catch(()=>{}),o=new Map;for(let d of r?.upstreamGenerations??[])d.upstreamSessionId&&o.set(`${d.agentId}::${d.upstreamSessionId}`,{agentId:d.agentId,upstreamSessionId:d.upstreamSessionId});o.set(`${t.agentId}::${t.upstreamSessionId}`,{agentId:t.agentId,upstreamSessionId:t.upstreamSessionId});let i=new Date().toISOString(),a=new Map;for(let d of o.values())await this.tombstones.add({agentId:await this.agentStoreKey(d.agentId,a),upstreamSessionId:d.upstreamSessionId,sessionId:e,deletedAt:i,upstreamUpdatedAt:t.upstreamUpdatedAt,cwd:t.cwd,...t.title!==void 0?{title:t.title}:{},reason:n,...t.interactive!==void 0?{interactive:t.interactive}:{}}).catch(()=>{})}async deleteRecord(e,t="user"){let n=await this.store.read(e);if(!n)return!1;if(n.upstreamSessionId){let r=await bn(e),o=Bt(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:Sd(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),o=await this.histories.load(e,{maxEntries:1/0});if(Za(o)===0){this.logger?.info(`compaction: zero-turn fast-path swap sessionId=${e} target=${n}`),await this.dispatchSynthesisSwap(e,void 0,o.length,n);return}if(!r?.synopsis||r.summarizedThroughEntry===void 0){this.synopsisCoordinator.scheduleCompaction(e,t);return}if(o.length!==r.summarizedThroughEntry){this.synopsisCoordinator.scheduleCompaction(e,t);return}this.logger?.info(`compaction: fast-path swap sessionId=${e} target=${n} (reusing artifact @${r.summarizedThroughEntry})`),await this.dispatchSynthesisSwap(e,r.synopsis,r.summarizedThroughEntry,n)}catch(r){this.logger?.warn(`scheduleCompaction: fast-path check failed for ${e}: ${r instanceof Error?r.message:String(r)} \u2014 falling back to synthesis`),this.synopsisCoordinator.scheduleCompaction(e,t)}})();return}this.synopsisCoordinator.scheduleCompaction(e,t)}getCompactionInFlight(){let e=this.synopsisCoordinator.size();return e.inflight>0||e.queued>0}async getPendingAgentSwap(e){return(await this.store.read(e).catch(()=>{}))?.pendingAgentSwap}async getCompactionState(e){return(await this.store.read(e).catch(()=>{}))?.compactionState}async persistRollbackBreadcrumb(e,t){await this.mutateRecord(e,{},void 0,n=>{let r=n.rollbackBreadcrumb;return r!==void 0&&t.runId!==void 0&&r.runId===t.runId?(this.logger?.info(`compaction: keeping rollback breadcrumb pinned at ${r.previousUpstreamSessionId} for runId=${t.runId} sessionId=${e} (later swap of the same run)`),{}):{rollbackBreadcrumb:t}})}async getUpstreamGenerations(e){return(await this.store.read(e).catch(()=>{}))?.upstreamGenerations??[]}async getRollbackBreadcrumb(e){return(await this.store.read(e).catch(()=>{}))?.rollbackBreadcrumb}emitSwapPhase(e,t,n){let r=this.get(e);if(r){if(t){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 ha(t.sessionId).catch(()=>[]);if(n.length===0)continue;let r=Date.now(),o=n.filter(d=>r-d.enqueuedAt<md),i=n.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${md/1e3}s)`),await dn(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 dn(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 ig(s,e){if(typeof s!="string"||s.length===0)return!1;let t=Sn.resolve(s),n=Sn.resolve(e);return t===n||t.startsWith(n+Sn.sep)}function hd(s,e){if(s===void 0||s.length===0)return!0;let t=fo(s);if(fo(e.cwd)===t)return!0;let n=e.workspace?.sourceCwd;return n!==void 0&&fo(n)===t}function fo(s){return s.length>1&&s.endsWith("/")?s.replace(/\/+$/,""):s}function ag(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 Kr({sessionId:s.sessionId,lineageId:e?.lineageId??fn(),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:bd(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?Sd(e,s.agentId,s.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(s.createdAt).toISOString()})}function bd(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 dg(s){return s?{...s}:void 0}function cg(s){return(s.extendsChain??[s.id]).some(t=>t==="claude-acp"||t.startsWith("claude-acp-"))}var ug=[{type:"system",subtype:"background_tasks_changed"}];function po(s,e={}){if(!cg(s))return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t,emitRawSDKMessages:ug}}}function hs(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=lg(s,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function go(s){return hs(s,{nestedKey:"models",configId:"model",fromObject:e=>we(e.currentModelId)??we(e.currentModel)??we(e.modelId)??we(e.model),fromConfig:e=>we(e.currentValue)})}function ot(s,e){if(!s||typeof s!="object")return s;let t=s;if(t.code!==x.AuthRequired)return s;let n=c=>!!c&&typeof c=="object"&&!Array.isArray(c),r=n(t.data)?t.data:{},o=n(r._meta)?r._meta:{},i=n(o["hydra-acp"])?o["hydra-acp"]:{},a=typeof t.message=="string"?t.message:"authentication required",d=new Error(a);return d.code=x.AuthRequired,d.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function yd(s){return/^[A-Za-z0-9_\-./=:@]+$/.test(s)?s:`'${s.replace(/'/g,"'\\''")}'`}function wd(s,e,t,n){if(s&&typeof s=="object"&&s.code===x.AuthRequired)return s;let r=s instanceof Error?s.message:String(s),o=r.includes("stderr:"),i=o?"":e.stderrTailText(),a=n?`to reproduce: (cd ${yd(n.cwd)} && ${[n.command,...n.args].map(yd).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(`
170
+ `));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 kn(s){return s._meta?.steering?.supported===!0}function vn(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 we(s){if(typeof s!="string")return;let e=s.trim();return e.length>0?e:void 0}function lg(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 Ht(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.configOptions)}function Lt(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=we(r.id);if(!o||o==="model"||o==="mode"||o==="agent")continue;let i=Ur(r.options);if(i.length===0)continue;let a=we(r.description);t.push({id:o,name:we(r.name)??o,...a?{description:a}:{},category:we(r.category)??"other",type:"select",currentValue:we(r.currentValue)??i[0].value,options:i})}return t}function Ut(s){return s.length>0?s:void 0}function mo(s){return hs(s,{nestedKey:"models",configId:"model",fromObject:e=>{let t=cn(e.availableModels);return t.length>0?t:void 0},fromConfig:e=>{let t=cn(e.options);return t.length>0?t:void 0}})??[]}function ho(s){return hs(s,{nestedKey:"modes",configId:"mode",fromObject:e=>{let t=Kn(e.availableModes);return t.length>0?t:void 0},fromConfig:e=>{let t=Kn(e.options);return t.length>0?t:void 0}})??[]}function yo(s){return hs(s,{nestedKey:"modes",configId:"mode",fromObject:e=>we(e.currentModeId)??we(e.currentMode)??we(e.modeId)??we(e.mode),fromConfig:e=>we(e.currentValue)})}function fg(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 kd(s){try{let e=await yt.readFile(R.tuiHistoryFile(s),"utf8"),t=[];for(let n of e.split(`
171
+ `))if(n.length!==0)try{let r=JSON.parse(n);typeof r=="string"&&t.push(r)}catch{}return t}catch{return[]}}function Sd(s,e,t,n=new Date().toISOString(),r={}){let{retiredCost:o,retiredUsed:i,startedUsed:a,lifetimeCost:d,reason:c,runId:u}=r,l=h=>d!==void 0&&h.lifetimeCostAtStart!==void 0?Math.max(0,d-h.lifetimeCostAtStart):o,p=s.upstreamGenerations&&s.upstreamGenerations.length>0?[...s.upstreamGenerations]:s.upstreamSessionId?[{upstreamSessionId:s.upstreamSessionId,agentId:s.agentId}]:[],m=p[p.length-1];if(m&&m.upstreamSessionId===t){if(p.length>=2){let h=p[p.length-2];if(h){let f=l(h);p[p.length-2]={...h,...f!==void 0&&h.cost===void 0?{cost:f}:{},...i!==void 0&&h.usedAtEnd===void 0?{usedAtEnd:i}:{}}}}return(c!==void 0&&m.reason===void 0||a!==void 0&&m.usedAtStart===void 0||d!==void 0&&m.lifetimeCostAtStart===void 0)&&(p[p.length-1]={...m,...c!==void 0&&m.reason===void 0?{reason:c,...u!==void 0?{runId:u}:{}}:{},...a!==void 0&&m.usedAtStart===void 0?{usedAtStart:a}:{},...d!==void 0&&m.lifetimeCostAtStart===void 0?{lifetimeCostAtStart:d}:{}}),p}return m&&m.endedAt===void 0&&(p[p.length-1]={...m,endedAt:n,...(()=>{let h=l(m);return h!==void 0?{cost:h}:{}})(),...i!==void 0?{usedAtEnd:i}:{}}),p.push({upstreamSessionId:t,agentId:e,startedAt:n,...c!==void 0?{reason:c}:{},...u!==void 0?{runId:u}:{},...a!==void 0?{usedAtStart:a}:{},...d!==void 0?{lifetimeCostAtStart:d}:{}}),p}async function bn(s){try{let e=await yt.stat(R.historyFile(s));return{mtime:new Date(e.mtimeMs).toISOString(),hasContent:e.size>0}}catch{return{hasContent:!1}}}function Bt(s,e){return s.interactive!==void 0?s.interactive:s.originatingClient?.name===us?!1:e?!0:void 0}import{spawn as pg}from"child_process";import*as ws from"fs";import*as Xe from"fs/promises";import*as ks from"path";import gg from"pino-roll";var ys=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 mg=1e3,hg=6e4,wo=3e3,Wt=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??mg,this.restartCapMs=r.restartCapMs??hg;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 Xe.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()},wo);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 In(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");if(t.child)throw In(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 In(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 In(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 In(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{}},wo);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 ys(this.breakerOptions),failureReason:void 0}}async reapOrphans(){let e;try{e=await Xe.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 Xe.readFile(n,"utf8"),i=Number.parseInt(o.trim(),10);Number.isInteger(i)&&i>0&&(r=i)}catch{}if(typeof r=="number"&&ko(r)){try{process.kill(r,"SIGTERM")}catch{}let o=Date.now()+wo;for(;Date.now()<o&&ko(r);)await new Promise(i=>setTimeout(i,50));if(ko(r))try{process.kill(r,"SIGKILL")}catch{}}await Xe.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=ks.dirname(this.adapter.paths.logFile(r.name)),a;try{await Xe.mkdir(i,{recursive:!0}),a=await gg({file:ks.join(i,`${r.name}.log`),size:"5m",mkdir:!0,symlink:!0,limit:{count:5}}),a.on("error",g=>{e.failureReason=`log stream: ${g.message}`})}catch(g){if(this.stopping||e.manuallyStopped)return;e.failureReason=`log setup: ${g.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})
172
+ `);let d=this.tokenRegistry?.mint(r.name,this.adapter.tokenRole)??n.serviceToken;e.processToken=d,e.version=void 0;let c={...Dn(),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
173
+ `),a.end();return}let p=le(u),m=[...l,...r.args].map(le),h;try{h=pg(p,m,{env:c,stdio:["ignore","pipe","pipe"],detached:!1})}catch(g){a.write(`[hydra-acp] failed to spawn ${r.name}: ${g.message}
174
+ `),a.end(),this.scheduleRestart(e,t);return}let f=g=>{try{a.write(typeof g=="string"?g:g.toString())}catch{}};if(h.stdout?.on("data",f),h.stderr?.on("data",f),typeof h.pid=="number")try{ws.writeFileSync(this.adapter.paths.pidFile(r.name),`${h.pid}
175
+ `,{encoding:"utf8",mode:384})}catch(g){a.write(`[hydra-acp] failed to write pid file for ${r.name}: ${g.message}
176
+ `)}e.child=h,e.logStream=a,e.pid=typeof h.pid=="number"?h.pid:void 0,e.startedAt=Date.now(),e.lastExitCode=void 0,h.on("error",g=>{a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} error: ${g.message}
177
+ `)}),h.on("exit",(g,w)=>{try{ws.unlinkSync(this.adapter.paths.pidFile(r.name))}catch{}a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} exited code=${g??"null"} signal=${w??"null"}
178
+ `),e.child=void 0,e.pid=void 0,e.lastExitCode=typeof g=="number"?g:void 0,e.processToken&&(this.tokenRegistry?.revoke(r.name),e.processToken=void 0);let y=e.exitWaiters.splice(0);for(let b of y)b();if(this.stopping||e.manuallyStopped){try{a.end()}catch{}e.logStream=void 0;return}e.restartCount+=1;let k=e.breaker.recordExit(g,r.name,this.adapter.kind);if(typeof k=="object"){e.failureReason=k.tripped,a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} circuit breaker tripped: ${k.tripped}
179
+ `);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 ko(s){try{return process.kill(s,0),!0}catch{return!1}}function In(s,e){return s.code=e,s}Y();var yg={kind:"extension",nameEnvVar:"HYDRA_ACP_EXTENSION_NAME",tokenRole:"extension",paths:{dir:R.extensionsDir,logFile:R.extensionLogFile,pidFile:R.extensionPidFile}},vs=class extends Wt{constructor(e,t,n={}){super(e,yg,t,n)}};Y();var wg={kind:"transformer",nameEnvVar:"HYDRA_ACP_TRANSFORMER_NAME",tokenRole:"transformer",paths:{dir:R.transformersDir,logFile:R.transformerLogFile,pidFile:R.transformerPidFile}},bs=class extends Wt{connected=new Map;constructor(e,t,n={}){super(e,wg,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 Ss=class{entries=new Map;changeHandlers=[];register(e,t,n){this.entries.set(e,{connection:t,commands:[...n]}),this.fireChanged()}clear(e){this.entries.delete(e)&&this.fireChanged()}get(e){return this.entries.get(e)}has(e){return this.entries.has(e)}list(){let e=[];for(let[t,n]of this.entries)for(let r of n.commands)e.push({name:t,command:r});return e}onChange(e){return this.changeHandlers.push(e),()=>{let t=this.changeHandlers.indexOf(e);t>=0&&this.changeHandlers.splice(t,1)}}fireChanged(){for(let e of this.changeHandlers)try{e()}catch{}}};Y();Y();import*as vo from"fs/promises";async function Id(s){await vo.writeFile(R.pidFile(),JSON.stringify(s)+`
180
+ `,{encoding:"utf8",mode:384})}Y();import*as Cn from"fs/promises";import*as Is from"path";var An=s=>{process.stderr.write(s+`
181
+ `)};function bo(s){An=s??(e=>process.stderr.write(e+`
182
+ `))}async function Ad(s,e){let t=De();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=Is.join(R.agentsDir(),t),a;try{a=await Cn.readdir(i,{withFileTypes:!0})}catch(d){let c=d;if(c.code==="ENOENT")return;An(`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=Is.join(i,c),m;try{m=await Cn.readdir(p,{withFileTypes:!0})}catch(h){An(`hydra-acp: prune: failed to read ${p}: ${h.message}`);continue}for(let h of m){if(!h.isDirectory())continue;let f=h.name;if(f===u||l.has(f)||f.includes(".partial-"))continue;let g=Is.join(p,f);try{await Cn.rm(g,{recursive:!0,force:!0}),An(`hydra-acp: pruned stale ${c} ${f} (${g})`)}catch(w){An(`hydra-acp: prune: failed to remove ${g}: ${w.message}`)}}}}function Cd(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 br(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 So(s){let e=s.maxDeletions??200,t=(m,h)=>{s.logger&&s.logger[m](`session-gc: ${h}`)},n=Date.now(),r=s.maxAgeMs>0?n-s.maxAgeMs:Number.POSITIVE_INFINITY,o=await s.manager.list({includeNonInteractive:!0}).catch(m=>(t("warn",`manager.list failed: ${m.message}`),[])),i=[];for(let m of o){if(m.status!=="cold")continue;if((s.selection??"explicit")==="explicit"){if(m.interactive!==!1)continue}else if(m.interactive===!0)continue;let f=Date.parse(m.updatedAt);Number.isFinite(f)&&(s.maxAgeMs>0&&f>r||i.push({sessionId:m.sessionId,lastUsedMs:f}))}if(i.length===0)return s.verbose&&t("info","no candidates"),{considered:0,deleted:0,failed:0,deferred:0};i.sort((m,h)=>m.lastUsedMs-h.lastUsedMs);let a=i.slice(0,e),d=a[0]?.lastUsedMs,c=0,u=0;for(let{sessionId:m}of a)try{await s.manager.deleteRecord(m,"expired")&&(c+=1)}catch(h){u+=1,t("warn",`delete ${m} failed: ${h.message}`)}let l=i.length-a.length;if(s.verbose||c>0||u>0){let m=(s.selection??"explicit")==="unpromoted"?"unpromoted":"non-interactive";t("info",`swept ${c} ${m} session(s) older than ${kg(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 Rd(s){let e,t=!1,n=!1,r=o=>{t||(e=setTimeout(()=>{(async()=>{if(!n){n=!0;try{await So({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 kg(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 vg}from"crypto";function Rn(s){if(Array.isArray(s))return s.map(Rn);if(s!==null&&typeof s=="object"){let e={};for(let t of Object.keys(s).sort())e[t]=Rn(s[t]);return e}return s}function xd(s){let e={};for(let[n,r]of Object.entries(s)){let o=Zs(n);if(o.nested){let i={};for(let[a,d]of Object.entries(r??{}))er(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(Rn(e));return vg("sha256").update(t).digest("hex").slice(0,16)}function Ed(s,e){let t=[],n=(r,o)=>JSON.stringify(Rn(r))!==JSON.stringify(Rn(o));for(let r of Object.keys(e)){let o=Zs(r),i=e[r],a=s[r];if(o.nested){for(let d of Object.keys(i??{})){if(er(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 Pd from"fs/promises";Y();var bg=3e3;async function Td(){try{return(await Pd.stat(R.config())).mtimeMs}catch{return}}function Md(s){let e=s.intervalMs??bg,t=!1,n,r,o=Td().then(d=>{r=d}),i=async()=>{await o;let d=await Td();if(d===r)return;r=d;let c;try{c=await Zt()}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=Ed(s.bootConfig,c);s.onDrift?.(u),s.logger?.info(u.length>0?`config-reload: applied live config; restart-only keys differing from boot: ${u.join(", ")}`:"config-reload: applied live config")},a=()=>{t||(n=setTimeout(()=>{i().finally(a)},e),n.unref?.())};return a(),()=>{t=!0,n&&clearTimeout(n)}}Y();Oe();import*as Fd from"path";import{createHash as Sg,randomBytes as Ig,timingSafeEqual as Ag}from"crypto";var Od="hydra_session_",Cg=3600*24*30,_d=12,Rg=32,xg=50;function Eg(){return Fd.join(R.home(),"session-tokens.json")}function $d(s){return Sg("sha256").update(s).digest("hex")}function Nd(s){return Ig(s).toString("hex")}function Tg(){return Nd(_d).slice(0,_d*2)}function Pg(){return`${Od}${Nd(Rg)}`}var As=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=Eg(),n=await oe(t);n&&Array.isArray(n.records)&&(e=n.records.filter(Mg));let r=new s(e,t);return r.sweepExpired(new Date)>0&&await r.flush(),r}async issue(e={}){let t=Pg(),n=$d(t),r=Tg(),o=new Date,i=e.ttlSec&&e.ttlSec>0?e.ttlSec:Cg,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(Od))return;let t=$d(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||!Ag(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(()=>{})},xg))}persist(){let e=(this.writeInflight??Promise.resolve()).catch(()=>{}).then(()=>ue(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 Mg(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 Dd="Bearer ",Cs=class{constructor(e){this.token=e}token;async validate(e){return $g(e,this.token)?"service":void 0}rotate(e){this.token=e}},Rs=class{constructor(e){this.store=e}store;async validate(e){return this.store.verify(e)}},xs=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 jd(s){return async function(t,n){let r=t.headers.authorization;if(!r||!r.startsWith(Dd)){n.code(401).send({error:"Missing bearer token"});return}let o=r.slice(Dd.length).trim(),i=await s.validator.validate(o);if(!i){n.code(403).send({error:"Invalid token"});return}t.authIdentity=i}}function Hd(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 Es=class{tokens=new Map;mint(e,t){let n=Ys();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}`}},_g=new Set(["GET /v1/sessions","GET /v1/sessions/:id","GET /v1/config"]);function Ld(s,e){return e?_g.has(`${s} ${e}`):!1}function $g(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 Ts=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 To from"fs";import*as mc from"os";import*as Ns from"path";import*as Po from"readline";Y();function Io(s){return Math.floor(s/4)}function Ud(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+=wt(i.content);break;case"tool_call":case"tool_call_update":{let a=typeof i.toolCallId=="string"?i.toolCallId:"",d=Fg(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 Fg(s){let e=0;return typeof s.title=="string"&&(e+=s.title.length),e+=Ps(s.rawInput),e+=wt(s.content),e+=Ps(s.rawOutput),e}function Ps(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+=Ps(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+=Ps(n);return t}return 0}function wt(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+=wt(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?wt(e.text):e.type==="diff"?wt(e.oldText)+wt(e.newText):e.content!==void 0?wt(e.content):0}function Bd(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=Io(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}Y();import{posix as Og}from"path";import Ng from"strip-ansi";function xn(s){if(!s||typeof s!="object")return;let e=s;return typeof e.workerTaskId=="string"?e.workerTaskId:void 0}function Ao(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 Dg=/[\x00-\x08\x0b-\x1f\x7f]/g;function Ee(s){return Ng(s).replace(Dg,"")}function re(s){return Ee(s).replace(/[\n\t]+/g," ").replace(/ +/g," ").trim()}function Jd(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 qg(t);case"agent_thought_chunk":case"agent_thought":return zg(t);case"user_message_chunk":return Jg(t);case"prompt_received":return Vg(t);case"tool_call":return Gg(t,e);case"tool_call_update":return Zg(t,e);case"plan":return sm(t);case"current_mode_update":return rm(t);case"_hydra_current_model_update":return om(t);case"turn_complete":return im(t);case"_hydra_turn_started":return zd(t,"turn-started");case"_hydra_turn_ended":return zd(t,"turn-ended");case"usage_update":return Wg(t);case"available_commands_update":return Ug(t);case"_hydra_available_modes_update":return Bg(t);case"session_info_update":return Hg(t);case"config_option_update":return jg(t);default:return{kind:"unknown",sessionUpdate:n,raw:s}}}function jg(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 Hg(s){let e=se(s,"title"),t=e!==void 0?re(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 Lg(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:re(r)};typeof n.description=="string"&&(o.description=re(n.description)),e.push(o)}return e}function Ug(s){let e=s.availableCommands??s.commands;return Array.isArray(e)?{kind:"available-commands",commands:Lg(e)}:null}function Bg(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:re(r.id)};typeof r.name=="string"&&(o.name=re(r.name)),typeof r.description=="string"&&(o.description=re(r.description)),t.push(o)}return{kind:"available-modes",modes:t}}function Wg(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 qg(s){let e=En(s.content);return e===null?null:{kind:"agent-text",text:e,workerTaskId:xn(s)}}function zg(s){let e=typeof s.text=="string"?Ee(s.text):En(s.content);return e===null?null:{kind:"agent-thought",text:e,workerTaskId:xn(s)}}function Jg(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=En(s.content);return t===null?null:{kind:"user-text",text:t}}function Vg(s){let e=am(s.prompt);return e===null?null:{kind:"user-text",text:e}}function Vd(s){return s?s.toLowerCase().replace(/[_\s-]/g,"")==="exitplanmode":!1}function Wd(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=Wd(r.oldText),i=Wd(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 Gd(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:Ee(t)}function Gg(s,e={}){let t=se(s,"toolCallId")??se(s,"id");if(!t)return null;let n=se(s,"title")??se(s,"name")??se(s,"label")??"tool call",r=se(s,"name")??se(s,"title");if(Vd(r)){let f=Gd(s);if(f!==null){let g=se(s,"status"),w={kind:"exit-plan-mode",toolCallId:t,plan:f};return g!==void 0&&(w.status=g),w}}let o=Yd(re(n),s,e),i=se(s,"status"),a=se(s,"kind"),d={kind:"tool-call",toolCallId:t,title:o};i!==void 0&&(d.status=i),a!==void 0&&(d.rawKind=a);let c=Ms(s);c!==null&&(d.editDiff=c);let u=Qd(s);u!==void 0&&(d.detail=u);let l=Co(s);l!==void 0&&(d.detailFull=l);let p=Kd(s);p!==void 0&&(d.locations=p);let m=xn(s);m!==void 0&&(d.workerTaskId=m);let h=Ao(s);return h!==void 0&&(d.parentToolUseId=h),d}function Kd(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 qd=64;function Qd(s){let e=Co(s);if(e===void 0)return;let t=re(e),n=s.rawInput;return n&&typeof n.command=="string"?Yg(t,qd):Xg(t,qd)}function Co(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 Ee(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 F(re(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 F(re(n))}}}var Kg=["home/","Users/","root/","tmp/","var/","opt/","etc/","usr/","mnt/","private/"];function Qg(s){for(let e of Kg)if(s.startsWith(e))return!0;return!1}function Yd(s,e,t={}){if(s.length===0)return s;if(s.startsWith("/"))return F(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 F(i)}return Qg(s)?F(`/${s}`):t.cwd&&t.cwd.length>0?F(Og.resolve(t.cwd,s)):s}function Yg(s,e){return s.length>e?`${s.slice(0,e-1)}\u2026`:s}function Xg(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 Zg(s,e={}){let t=se(s,"toolCallId")??se(s,"id");if(!t)return null;let n=se(s,"title"),r=n!==void 0?Yd(re(n),s,e):void 0,o=se(s,"status"),i=Ms(s),a=Qd(s),d=em(s);if(!(r!==void 0||i!==null||a!==void 0||d!==void 0||o==="completed"||o==="failed"||o==="rejected"||o==="cancelled"))return null;let u=se(s,"name")??n;if(Vd(u)){let g={kind:"exit-plan-mode",toolCallId:t},w=Gd(s);return w!==null&&(g.plan=w),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=Co(s);p!==void 0&&(l.detailFull=p);let m=Kd(s);if(m!==void 0&&(l.locations=m),d!==void 0&&(l.resultSummary=d),o!==void 0&&(l.status=o),i!==null&&(l.editDiff=i),o==="failed"){let g=tm(s);g!==null&&(l.errorText=g),nm(s,g)&&(l.upstreamInterrupted=!0)}let h=xn(s);h!==void 0&&(l.workerTaskId=h);let f=Ao(s);return f!==void 0&&(l.parentToolUseId=f),l}function em(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 tm(s){let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let o=En(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 Ee(n)}return null}function nm(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 sm(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"?re(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 rm(s){let e=se(s,"currentModeId")??se(s,"currentMode")??se(s,"mode");return e?{kind:"mode-changed",mode:re(e)}:null}function om(s){let e=se(s,"currentModel")??se(s,"model");if(!e)return null;let t=s.availableModels,n=Array.isArray(t)?t.map(r=>typeof r=="object"&&r!==null?r.modelId:typeof r=="string"?r:void 0).filter(r=>typeof r=="string"&&r.length>0):void 0;return{kind:"model-changed",model:re(e),...n&&n.length>0?{availableModels:n}:{}}}function im(s){let e=se(s,"stopReason"),t=s._meta,n=t?.["hydra-acp"]?.amended!==void 0&&t["hydra-acp"].amended!==null,r={kind:"turn-complete"};return e!==void 0&&(r.stopReason=e),n&&(r.amended=!0),r}function zd(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 En(s){if(typeof s=="string")return Ee(s);if(!s||typeof s!="object")return null;let e=s;return e.type==="text"&&typeof e.text=="string"||typeof e.text=="string"?Ee(e.text):null}function am(s){if(!Array.isArray(s))return null;let e=[];for(let t of s){let n=En(t);n!==null&&e.push(n)}return e.length===0?null:e.join("")}function se(s,e){let t=s[e];return typeof t=="string"?t:void 0}function Xd(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=cm(i);if(c.length===0)continue;let u=c;if(d!==void 0){let l=e.get(d)??[],p=[];for(let m of c)l.some(h=>h.path===m.path&&h.oldText===m.oldText&&h.newText===m.newText)||p.push(m);if(p.length===0)continue;e.set(d,[...l,...p]),u=p}for(let l of u)dm(t,l)}let n=[];for(let[r,o]of t)n.push({path:r,hunks:o.hunks,created:o.created});return n}function Zd(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 dm(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 cm(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 tc(s,e={}){let t=lm(s),{events:n,window:r}=um(t,e),o=fm(n),i=[];pm(i,s),r&&(r.from>1||r.to<r.total)&&(i.push(`_Showing turns ${r.from}-${r.to} of ${r.total}._`),i.push("")),gm(i,n,o,{includeTools:e.includeTools??!1,includeThoughts:e.includeThoughts??!1});let a=i.join(`
183
183
  `);return a.endsWith(`
184
184
  `)||(a+=`
185
- `),a}function ao(s,e){let t=s<0?e+s+1:s;return t<1?1:t>e?e:t}function Og(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=ao(o-e.last+1,o):(e.from!==void 0&&(i=ao(e.from,o)),e.to!==void 0&&(a=ao(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 Fg(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=Sd(n.update,{cwd:s.session.cwd});r!==null&&e.push({event:r,recordedAt:t.recordedAt})}return e}function Ng(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 Dg(s,e){let t=e.session,n=qe(t.sessionId),r=t.title?.trim()||`Hydra session ${n}`;s.push(`# ${vn(r)}`),s.push("");let o=[];o.push(`- **Session:** \`${n}\` (lineage \`${t.lineageId}\`)`);let i=[t.agentId];t.currentModel&&i.push(`model: ${t.currentModel}`),t.currentMode&&i.push(`mode: ${t.currentMode}`),o.push(`- **Agent:** ${i.filter(Boolean).join(" \xB7 ")}`),o.push(`- **Cwd:** ${t.cwd}`),o.push(`- **Exported:** ${e.exportedAt} from ${e.exportedFrom.machine} (hydra ${e.exportedFrom.hydraVersion})`);let a=t.currentUsage;if(a&&(a.used!==void 0||a.costAmount!==void 0||a.cumulativeCost!==void 0)){let d=[];if(a.used!==void 0){let u=a.size!==void 0?`${co(a.size)}`:void 0;d.push(u?`${co(a.used)} / ${u} tokens`:`${co(a.used)} tokens`)}let c=Jr(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(`
186
- `)),s.push("")}function jg(s,e,t,n){let{includeTools:r,includeThoughts:o}=n;if(!e.some(g=>Hg(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&&(Pd(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,Pd(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(`- ${Ug(h.status)} ${Lg(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} ${vn(h.content)}`)}s.push("");break}case"mode-changed":m(),f(),s.push(`_mode: ${vn(g.mode)}_`),s.push("");break;case"model-changed":m(),f(),s.push(`_model: ${vn(g.model)}_`),s.push("");break;case"turn-complete":f();break;case"usage-update":case"available-commands":case"session-info":case"unknown":break}f()}function Hg(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 Lg(s){let e=s.status,t=e==="completed"||e===void 0?"":` _(${e})_`;return`${vn(s.title)}${t}`}function Ug(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 _d=String.raw`<\/?[a-zA-Z][a-zA-Z0-9-]*(?:\s[^<>]*)?\/?>`,Bg=new RegExp(_d);function Pd(s,e,t){if(Bg.test(e)){Wg(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(`
187
- `);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 Wg(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(`
188
- `))s.push(o);s.push(r)}function vn(s){return s.replace(new RegExp(_d,"g"),e=>e.replace(/</g,"&lt;").replace(/>/g,"&gt;"))}function co(s){return s.toLocaleString("en-US")}function $d(s){return s==="127.0.0.1"||s==="::1"||s==="localhost"||s==="[::1]"}function qg(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=>zg(u)).filter(u=>u.term.length>0);return{operator:o,terms:c}}function zg(s){let e=/^(\w+):"([^"]*)"$/.exec(s);if(e)return{scope:Od(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:Od(n[1]),term:n[2].trim()}:{scope:"all",term:s.trim()}}function Od(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 Jg(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 Vg=5,Gg=200,bs=72,Kg=24,Qg=512;function Hd(s){return Number.isFinite(s)?Math.max(Kg,Math.min(Qg,Math.floor(s))):bs}async function Ld(s,e,t={}){let n=qg(e);if(n.terms.length===0)return{query:e,truncated:!1,results:[]};let r=t.maxSnippetsPerSession??Vg,o=t.maxSessions??Gg,i=Hd(t.snippetWidth??bs),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=Xg(f,n,r,i,Yg(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 Yg(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 Xg(s,e,t,n=bs,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=Zg(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 Zg(s,e,t,n,r,o){let i=e.toLowerCase(),a=0,d=[],c=new Set;for(let u of s){let l=em(u).filter(p=>Jg(t,p.kind));for(let p of l){let f=p.text.toLowerCase();if(p.kind==="edit"){let h=o?.(p.text);if(!(Fd(p.text,e)||(h!==void 0&&h!==p.text?Fd(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:am(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 em(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=vs(n.content);return o?[{kind:"agent",text:o}]:[]}case"agent_thought":case"agent_thought_chunk":{let o=typeof n.text=="string"?Ce(n.text):vs(n.content);return o?[{kind:"thought",text:o}]:[]}case"user_message_chunk":{if(om(n))return[];let o=vs(n.content);return o?[{kind:"user",text:o}]:[]}case"prompt_received":{let o=im(n.prompt);return o?[{kind:"user",text:o}]:[]}case"tool_call":case"tool_call_update":return tm(n);default:return[]}}function tm(s){let e=Dd(s,"name"),t=Dd(s,"title"),n=[];if(t!==void 0){let a=ne(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=ne(e);a.length>0&&n.push({kind:"tool",toolName:e,text:a})}let r=s.rawInput;if(r&&typeof r=="object"){let a=jd(r);if(a.length>0){let d={kind:"tool-input",text:ne(a)};e!==void 0&&(d.toolName=e),n.push(d)}}for(let a of nm(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=jd(o);if(a.length>0){let d={kind:"tool-input",text:ne(a)};e!==void 0&&(d.toolName=e),n.push(d)}}let i=sm(s);if(i!==null){let a={kind:"tool",text:i};e!==void 0&&(a.toolName=e),n.push(a)}return n}function nm(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 Fd(s,e){let t=Nd(s.toLowerCase()),n=Nd(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 Nd(s){return s.length>1&&s.endsWith("/")?s.slice(0,-1):s}function sm(s){if(!rm(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=ne(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=ne(n);if(r.length>0)return r}}return null}function rm(s){return s==="failed"||s==="rejected"||s==="cancelled"}function om(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 vs(s){if(typeof s=="string")return Ce(s);if(!s||typeof s!="object"||Array.isArray(s))return"";let e=s;return typeof e.text=="string"?Ce(e.text):""}function im(s){if(!Array.isArray(s))return"";let e=[];for(let t of s){let n=vs(t);n.length>0&&e.push(n)}return e.join("")}function Dd(s,e){let t=s[e];return typeof t=="string"?t:void 0}function jd(s){try{return JSON.stringify(s)}catch{return""}}function am(s,e,t,n=bs){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=Hd(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 Bd}from"crypto";function Ud(s){let e=Bd(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 uo(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(Ud({name:"hydra-acp-stdin",session:n,tokenRegistry:e,getOrigin:t})),r.push(Ud({name:"hydra-acp-recall",session:n,tokenRegistry:e,getOrigin:t}));let o=Ft(s.deps);return o!==void 0&&(o.bindToSession(n),r=[...r,...o.descriptors]),r}}function Ft(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=Bd(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 Ss=new Set(["usage_update","tool_call","tool_call_update","prompt_received","turn_complete","permission_resolved"]);function Wd(s){if(s.publicHost&&s.publicHost.length>0)return s.publicHost;if(s.host&&!$d(s.host))return s.port!==void 0?`${s.host}:${s.port}`:s.host}function zd(s,e,t,n={}){s.get("/v1/sessions",async(c,u)=>{let l=c.query,p=l?.includeNonInteractive==="1"||l?.includeNonInteractive==="true",f;if(l?.since!==void 0&&(f=Number(l.since),!Number.isFinite(f)||f<0))return u.code(400).send({error:`since must be a non-negative number, got ${JSON.stringify(l.since)}`});let m=l?.status==="warm"||l?.status==="cold"?l.status:void 0,g={cwd:l?.cwd,includeNonInteractive:p,...m?{status:m}:{}};if(f!==void 0){let w=await e.listSince(g,f);return{sessions:w.entries,removed:w.removed,cursor:w.cursor}}let h=await e.listing(g);return{sessions:h.entries,removed:[],cursor:h.cursor}}),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 Ld(e,p,m)}),s.post("/v1/sessions",async(c,u)=>{let l=c.body??{},p=ae(l.cwd??t.cwd),f=await Wt(p),m=l.agentId??f.agentId??t.agentId,g=Ft(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 so({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=>Is.join(qd.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"||!Is.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":Fa(f),g=await e.exportBundle(p,m==="references"?{tools:"references"}:{});if(!g){u.code(404).send({error:"session not found"});return}let h=dn({record:g.record,history:m==="summary"?Na(g.history,"summary"):g.history,promptHistory:g.promptHistory.length>0?g.promptHistory:void 0,...g.toolBlobs!==void 0?{toolBlobs:g.toolBlobs}:{},hydraVersion:le,machine:Gt(),hydraHost:Wd(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=Ed(f.history);h&&(w=w.filter(k=>h.has(k.path))),g&&(w=w.map(k=>({...k,hunks:Td(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=dn({record:f.record,history:f.history,promptHistory:f.promptHistory.length>0?f.promptHistory:void 0,hydraVersion:le,machine:Gt(),hydraHost:Wd(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(Md(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=ae(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===C.SessionNotFound){u.code(404).send({error:h.message});return}if(h.code===C.InvalidParams||h.code===C.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=qa(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===C.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 x=m??0,E=v.length,R=x<=v.length?x:0,M=v.slice(R),T=yd(M);y=ro(T);let D=f?.currentModel,q=v.at(-1).recordedAt;k=wd({summarizedThroughEntry:x,totalEntries:E,unsummarizedChars:T,compactionInFlight:e.getCompactionInFlight(),currentModel:D,lastActivityMs:q,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)+`
189
- `):(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)+`
190
- `);let x=v;typeof x.recordedAt=="number"&&I.add(String(x.recordedAt))}for(;b.length>0;){let v=b.splice(0,b.length);for(let x of v){let E=x,R=typeof E.recordedAt=="number"?String(E.recordedAt):"";R&&I.has(R)||u.raw.write(JSON.stringify(x)+`
191
- `)}}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=fo.createInterface({input:lo.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(!Ss.has(y))return u.code(400).send({error:`kind "${y}" is not queryable; allowed kinds: ${[...Ss].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=A.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 x=k[v];x.current!==null&&x.current.ts<b&&(b=x.current.ts,y=v)}if(y===-1)break;let I=k[y];if(u.raw.write(JSON.stringify(I.current.row)+`
192
- `),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(!Ss.has(v))return u.code(400).send({error:`kind "${v}" is not queryable; allowed kinds: ${[...Ss].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=A.historyFile(f),b=lo.createReadStream(y),I=fo.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 x=typeof v=="string"?v.trim():"";if(x.length===0)continue;let E;try{E=JSON.parse(x)}catch{console.debug("events endpoint: skipping malformed JSONL line in %s",y);continue}if(!E||typeof E!="object"||Array.isArray(E)){console.debug("events endpoint: skipping non-object JSONL line in %s",y);continue}let R=E;if(typeof R.recordedAt!="number"||typeof R.params!="object"||R.params===null||Array.isArray(R.params))continue;let M=R.params;if(typeof M.update!="object"||M.update===null||Array.isArray(M.update))continue;let T=M.update,D=T.sessionUpdate;if(typeof D!="string"||!w.has(D)||k!==void 0&&R.recordedAt<k)continue;let q={ts:new Date(R.recordedAt).toISOString(),kind:D,update:T};T.messageId!==void 0&&T.messageId!==null&&(q.messageId=T.messageId),u.raw.write(JSON.stringify(q)+`
193
- `)}}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(x=>`${x.source}::${x.reason}`);for(let x of v)w.clearAttentionFlag(x.split("::")[0],x.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(x=>`${x.source}::${x.reason}`!==v)}else I=[];if(I.length===b.length&&I.every((v,x)=>v.source===b[x].source&&v.reason===b[x].reason)){u.code(204).send();return}await k.write({...y,attentionFlags:I}),u.code(204).send()})}function Jd(s,e,t,n={}){s.get("/v1/agents",async()=>yt(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===C.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}Q();function Vd(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:A.home(),driftedKeys:n()}))}var dm=/^[A-Za-z0-9._-]+$/;function As(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=cm(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){bn(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){bn(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){bn(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){bn(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){bn(i,d)}})}function bn(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 cm(s){let e=s.name;if(typeof e!="string"||!dm.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 Gd(s,e){As(s,"extension",e)}function Kd(s,e){As(s,"transformer",e)}function Qd(s,e){s.get("/v1/config",async()=>e())}import{z as et}from"zod";Q();import*as Nt from"fs/promises";import*as Yd from"path";import{randomBytes as lS,scrypt as um,timingSafeEqual as lm}from"crypto";import{promisify as fm}from"util";var pm=fm(um);function Xd(){return Yd.join(A.home(),"password-hash")}var gm=128*1024*1024;async function Zd(){try{return(await Nt.readFile(Xd(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function ec(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await Nt.readFile(Xd(),"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 pm(s,i,a.length,{N:n,r,p:o,maxmem:gm});return d.length!==a.length?!1:lm(d,a)}var mm=et.object({password:et.string().min(1),label:et.string().min(1).max(256).optional(),ttlSec:et.number().int().positive().optional()}),hm=et.object({id:et.string().optional()}).optional(),ym=et.object({token:et.string().min(32)});function tc(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=wm(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=mm.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await Zd())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await ec(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=hm.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=ym.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 wm(s){return s.ip||"unknown"}import{z as nc}from"zod";var km=nc.object({sessionLabel:nc.string().min(1).max(256)});function sc(s,e){s.post("/v1/process-tokens",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=km.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}let o=e.processRegistry.mint(r.sessionLabel,"script");return n.code(201).send({token:o})}),s.delete("/v1/process-tokens/:sessionLabel",async(t,n)=>t.authIdentity!=="service"?n.code(403).send({error:"Requires the service token"}):(e.processRegistry.revoke(t.params.sessionLabel),n.code(204).send()))}import{nanoid as po}from"nanoid";function rc(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:C.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 cc}from"crypto";import*as uc from"os";import*as lc from"path";var vm=200;function bm(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e[re];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,vm)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function oc(s,e,t){let n=bm(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 Sn=new Map;function ic(s,e){let t=Sn.get(s);t||(t=new Set,Sn.set(s,t)),t.add(e);let n=!1;return()=>{if(n)return;n=!0;let r=Sn.get(s);r&&(r.delete(e),r.size===0&&Sn.delete(s))}}function ac(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=Sn.get(r);if(o){if(o.has(s))return!0;for(let i of o)n.push(i)}}return!1}function O(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function xm(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 be(s,e,t){let n=s.get(e);if(!n)throw O(C.SessionNotFound,t??`session ${e} not found`);return n}async function lt(s,e){let t=Ft(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=cc(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=uo({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 Nm(c,s),pc(c.sessionId,s),c}function fc(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=md({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=rc(t),a=new kt(i),d={clientId:`hydra_client_${po(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 O(C.PermissionDenied,`${p} not permitted on a read-only attachment`)};if(a.onRequest("initialize",async l=>{let p=oi.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)),Fm()}),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 O(C.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 O(C.InvalidParams,"key is required");if(!e.manager)throw O(C.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 O(C.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 O(C.InvalidParams,"key is required");if(g.value===void 0)throw O(C.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw O(C.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(m,o.name,g.key,g.value)}catch(h){throw O(C.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 O(C.InvalidParams,"key is required");if(!e.manager)throw O(C.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 O(C.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 O(-32602,"emit_message requires sessionId");if(!g&&w!=="client_broadcast")throw O(-32602,"emit_message requires method");let k=be(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 O(-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 O(-32602,"client_broadcast requires an envelope object");return k.broadcastClientUpdate(h),{ok:!0}}throw O(-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 O(-32602,"hydra-acp/session/request_permission requires sessionId");return be(e.manager,m).requestPermissionFromClients(f)}),a.onRequest("hydra-acp/transformer/attach",async p=>Mm(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 D=e.manager.get(h);D&&(g=D.cwd)}if(!g)throw O(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let I=await Wt(g),v=m??I.agentId??e.defaultAgent,x=await e.registry?.getAgent(v),E=Jt(I.configDefaults,x??{id:v})?.value,R=b??E?.model,M=typeof f.interactive=="boolean"?f.interactive:!1;return{childSessionId:(await e.manager.create({agentId:v,cwd:g,parentSessionId:h,interactive:M,transformChain:[],title:y,model:R,configDefaults:E})).sessionId}}),a.onRequest("hydra-acp/session/fork",async p=>{let f=p??{};if(typeof f.sessionId!="string")throw O(C.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 x=await e.manager.loadFromDisk(y.sessionId);if(!x)throw O(C.InternalError,`fork ${y.sessionId} vanished before it could be attached`);b=await lt(e,{...x,onInstallProgress:Cs(a)})}Dt(d,b,b.sessionId);let I=tt(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 x of v){if(a.isClosed())break;await a.notify(x.method,Fe(Oe(x.params,x.recordedAt),x.seq)).catch(()=>{})}return{...y,sessionId:b.sessionId}}),a.onRequest("session/fork",async p=>{let f=p??{};if(typeof f.sessionId!="string")throw O(C.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 O(C.InternalError,`fork ${g.sessionId} vanished before it could be attached`);h=await lt(e,{...y,onInstallProgress:Cs(a)})}Dt(d,h,h.sessionId);let w=tt(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,Fe(Oe(y.params,y.recordedAt),y.seq)).catch(()=>{})}return{sessionId:h.sessionId}});let l=async(p,f)=>{let m=p??{};if(typeof m.sessionId!="string")throw O(C.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 O(C.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 O(C.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 O(C.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 O(-32602,"await_child requires childSessionId");let w=be(e.manager,m,`child session ${m} not found`);return new Promise(k=>{let I=[],v=[],x=0,E=!1,R,M,T=!1,D=()=>{T||(T=!0,clearTimeout(q),R?.(),M?.(),k(E?{entries:I,truncated:!0}:{entries:I}))};R=w.onBroadcast(B=>{let Z=xm(B);for(I.push(B),v.push(Z),x+=Z;I.length>0&&(I.length>1e3||x>1048576);)I.shift(),x-=v.shift()??0,E=!0;g==="turn_complete"&&B.params?.update?.sessionUpdate==="turn_complete"&&D()});let q=setTimeout(D,h);typeof q.unref=="function"&&q.unref(),M=w.onClose(()=>D())})}),a.onRequest("hydra-acp/child_session/close",async p=>{let f=p??{},m=typeof f.childSessionId=="string"?f.childSessionId:void 0;if(!m)throw O(-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=>_m(p,o.name,e)),a.onRequest("hydra-acp/attention/clear",async p=>$m(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 O(C.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 O(C.SessionNotFound,"tool content not found");return{content:m}}),a.onRequest("authenticate",async l=>Rm(l,e)),a.onRequest("logout",async l=>Em(l,e)),a.onRequest("session/new",async l=>{let p=ii.parse(l),f=st(l?._meta),m=Array.isArray(f.transformers)&&f.transformers.every(L=>typeof L=="string")?f.transformers:e.manager.defaultTransformers??[],g=e.transformers?.resolveChain(m)??[],h=await Wt(p.cwd),w=f.agentId??h.agentId??e.defaultAgent,k=await e.registry?.getAgent(w),y=Jt(h.configDefaults,k??{id:w})?.value,b,I,v=p.mcpServers;if(f.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){b=cc(32).toString("hex"),I=e.mcpTokenRegistry.reserve(b);let Se={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${b}`}]};v=[...p.mcpServers??[],Se]}let x,E,R=Ft(e);R!==void 0&&(v=[...v??[],...R.descriptors]);let M=uo({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?.model,configDefaults:y,onInstallProgress:Cs(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}:{},...M?{mintMcpServersForSwap:M}:{}})}catch(L){throw I!==void 0&&I.abandon(L instanceof Error?L:void 0),E!==void 0&&E.abandon(L instanceof Error?L:void 0),R!==void 0&&R.abandon(L instanceof Error?L:void 0),L}if(b!==void 0&&I!==void 0&&e.mcpTokenRegistry!==void 0){let L=b,Se=e.mcpTokenRegistry;I.complete(T),T.onClose(()=>{Se.unbind(L)})}if(x!==void 0&&E!==void 0&&e.mcpTokenRegistry!==void 0){let L=x,Se=e.mcpTokenRegistry;E.complete(T),T.onClose(()=>{Se.unbind(L)})}R!==void 0&&R.bindToSession(T),pc(T.sessionId,e);let D,q;try{Dt(d,T,T.sessionId),D=tt(a,T,d),{entries:q}=await T.attach(D,"full")}catch(L){throw await T.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),L}d.attached.set(T.sessionId,{sessionId:T.sessionId,clientId:D.clientId,readonly:!1}),setImmediate(()=>{(async()=>{for(let L of q){if(a.isClosed())break;await a.notify(L.method,Fe(Oe(L.params,L.recordedAt),L.seq)).catch(()=>{})}})()});let B=xs(T),Z=Rs(T);return{sessionId:T.sessionId,...B?{modes:B}:{},...Z?{models:Z}:{},configOptions:T.buildConfigOptions(),_meta:Es(e.manager,T,{clientId:D.clientId})}}),a.onRequest("session/attach",async l=>{let p=di.parse(l),f=p.clientInfo?.version;f&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,f):e.onTransformerVersion?.(o.name,f));let m=st(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 O(C.SessionNotFound,`session ${p.sessionId} not found`);let D=await e.manager.loadHistory(k),q=p.clientId??`cli_${po(8)}`;d.attached.set(T.hydraSessionId,{sessionId:T.hydraSessionId,clientId:q,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${T.hydraSessionId} clientId=${q} attachedCount=${d.attached.size} replayed=${D.length}`);for(let B of D)await a.notify(B.method,Fe(Oe(B.params,B.recordedAt),B.seq)).catch(()=>{});return{sessionId:T.hydraSessionId,clientId:q,connectedClients:[q],historyPolicy:"full",replayed:D.length,_meta:Om(T)}}let b=!y;if(!y){let T=await e.manager.loadFromDisk(k),D=await Tm(k,g,T?.upstreamSessionId,e.manager);D.kind==="ignore"&&s.log.warn(D.logMessage);let q=T;if(g&&D.kind==="honor"&&(q={...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}:{}}),!q)throw O(C.SessionNotFound,`session ${p.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(q.agentId,q.upstreamSessionId))throw O(C.SessionNotFound,`session ${p.sessionId} was deleted`);let B=q.originatingClient?q:{...q,originatingClient:d.clientInfo},Z=w!==void 0?{...B,forwardedEnv:w}:B;y=await lt(e,{...Z,onInstallProgress:Cs(a)})}Dt(d,y,y.sessionId);let I=tt(a,y,d,p.clientInfo,p.clientId),v=m.replayMode==="drip",{entries:x,appliedPolicy:E}=await y.attach(I,p.historyPolicy,{afterMessageId:p.afterMessageId,afterSeq:p.afterSeq,raw:v,...m.historyLimit!==void 0?{historyLimit:m.historyLimit}:{},...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=${E} replayed=${x.length} readonly=${h}${v?" replayMode=drip":""}`),v){let T=m.dripSpeed&&m.dripSpeed>0?m.dripSpeed:1,D=750;(async()=>{let q=null;for(let B of x){let Z=typeof B.recordedAt=="number"?B.recordedAt:null;if(q!==null&&Z!==null){let L=Math.min(D,Math.max(0,(Z-q)/T));L>0&&await new Promise(Se=>setTimeout(Se,L))}Z!==null&&(q=Z);try{await a.notify(B.method,Fe(Oe(B.params,Z??void 0),B.seq))}catch{return}}})()}else for(let T=0;T<x.length&&!a.isClosed();T++){let D=x[T],q=a.notify(D.method,Fe(Oe(D.params,D.recordedAt),D.seq)).catch(()=>{});(T+1)%200===0&&await q}y.replayPendingPermissions(I);let R=xs(y),M=Rs(y);return{sessionId:y.sessionId,clientId:I.clientId,connectedClients:y.connectedClients(I.clientId),historyPolicy:E,replayed:x.length,...R?{modes:R}:{},...M?{models:M}:{},configOptions:y.buildConfigOptions(),_meta:Es(e.manager,y,{resurrected:b})}}),a.onRequest("session/detach",async l=>{let p=ci.parse(l),f=d.attached.get(p.sessionId);if(!f)throw O(C.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:{[re]:{detachStatus:"detached"}}}}),a.onRequest("session/list",async l=>{let p=ui.parse(l??{});return{sessions:(await e.manager.list({cwd:p.cwd})).filter(h=>h.originatingClient?.name!==Xn).map(li)}}),a.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw O(C.InternalError,"agent registry unavailable");return yt(e.registry)}),a.onRequest("hydra-acp/agents/auth_methods",async l=>{let p=l??{};if(typeof p.agentId!="string"||p.agentId.length===0)throw O(C.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=fi.parse(l);c(p.sessionId,"session/prompt");let f=await oc(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}`),O(C.InvalidRequest,`message chain too deep (${f.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(f.awaiting===!0&&ac(f.fromSession,p.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${f.fromSession} -> ${p.sessionId}`),O(C.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(",")}]`),O(C.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 O(C.SessionNotFound,`session ${p.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${p.sessionId}`),g=await lt(e,w);let k=tt(a,g,d,void 0,m.clientId);await g.attach(k,"none")}let h=f?.awaiting===!0&&f.fromSession!==void 0?ic(f.fromSession,p.sessionId):void 0;try{return await g.prompt(m.clientId,p,f)}finally{h?.()}});let u=l=>{let p;try{p=Mn.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=Mn.parse(l);return c(p.sessionId,"session/cancel"),u(l),null}),a.onRequest("hydra-acp/prompt/cancel",async l=>{let p=gi.parse(l);return c(p.sessionId,"hydra-acp/prompt/cancel"),be(e.manager,p.sessionId).cancelQueuedPrompt(p.messageId)}),a.onRequest("hydra-acp/session/force_cancel",async l=>{let p=Mn.parse(l);return c(p.sessionId,"hydra-acp/session/force_cancel"),be(e.manager,p.sessionId).forceCancel()}),a.onRequest("hydra-acp/prompt/update",async l=>{let p=mi.parse(l);return c(p.sessionId,"hydra-acp/prompt/update"),be(e.manager,p.sessionId).updateQueuedPrompt(p.messageId,p.prompt)}),a.onRequest("hydra-acp/prompt/amend",async l=>{let p=hi.parse(l);c(p.sessionId,"hydra-acp/prompt/amend");let f=d.attached.get(p.sessionId);if(!f)throw O(C.SessionNotFound,"not attached to session");return be(e.manager,p.sessionId).amendPrompt(f.clientId,p)}),a.onRequest("_session/steering",async l=>{let p=yi.parse(l);c(p.sessionId,"_session/steering");let f=d.attached.get(p.sessionId);if(!f)throw O(C.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 O(C.SessionNotFound,`session ${p.sessionId} not found`);m=await lt(e,g);let h=tt(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 O(C.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 O(C.SessionNotFound,`session ${f} not found in memory or on disk`);g=await lt(e,y)}Dt(d,g,g.sessionId);let h=tt(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=xs(g),k=Rs(g);return{sessionId:g.sessionId,...w?{modes:w}:{},...k?{models:k}:{},configOptions:g.buildConfigOptions(),_meta:Es(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 O(C.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 O(C.SessionNotFound,`session ${f} not found in memory or on disk`);g=await lt(e,b)}Dt(d,g,g.sessionId);let h=tt(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,Fe(Oe(b.params,b.recordedAt),b.seq)).catch(()=>{})}g.replayPendingPermissions(h);let k=xs(g),y=Rs(g);return{sessionId:g.sessionId,...k?{modes:k}:{},...y?{models:y}:{},configOptions:g.buildConfigOptions(),_meta:Es(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=Pm(l,e.manager);if(f.kind==="error")throw s.log.warn(f.logMessage),O(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 O(C.InvalidParams,"session/set_mode requires string sessionId");if(typeof p.modeId!="string")throw O(C.InvalidParams,"session/set_mode requires string modeId");let m=be(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=>O(C.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=be(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 O(C.MethodNotFound,`Method not found: ${p}`);let h=l.sessionId;if(typeof h!="string")throw O(C.MethodNotFound,`Method not found: ${p}`);return c(h,p),be(e.manager,h).forwardRequest(p,l)})})}async function Rm(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw O(C.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 O(C.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 O(C.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 O(C.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&&lc.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=uc.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 Ze(f,a)}}async function Em(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 Cs(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(wi,t).catch(()=>{})}}function xs(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 Rs(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 Tm(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 Pm(s,e){if(!s||typeof s!="object")return{kind:"error",code:C.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:C.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:C.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:C.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=It(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:C.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 Mm(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw O(C.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw O(C.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw O(C.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return be(t.manager,r).addTransformer(o),{ok:!0}}async function _m(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(C.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw O(C.InvalidParams,"hydra-acp/attention/set requires string reason");return be(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function $m(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(C.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw O(C.InvalidParams,"hydra-acp/attention/clear requires string reason");return be(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function Om(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:cn(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{[re]:Pn(e,t)}}function Es(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 Vt(e.agentMeta,Pn(n,r))}function Fm(){return{protocolVersion:1,agentInfo:{name:"hydra",version:le},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:{...Vt(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 Nm(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 pc(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 tt(s,e,t,n,r){return{clientId:r??`cli_${po(8)}`,connection:s,clientInfo:n}}function Dt(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var Ts=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 Dm}from"crypto";import{McpServer as jm}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Hm}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as fe}from"zod";function go(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 we(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var gc="Bearer ";function jt(s){let e=s.headers.authorization;if(typeof e!="string"||!e.startsWith(gc))return;let t=e.slice(gc.length).trim();return t.length>0?t:void 0}function Lm(s){let e=new jm({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:fe.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return we(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:fe.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return we(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:fe.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:fe.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:fe.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 we(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:fe.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:fe.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 we({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:fe.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:fe.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:fe.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:fe.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:fe.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:fe.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:fe.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:fe.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:fe.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 we(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 we(t)}),e}var Um=1e4;function mc(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=Lm(a),u=new Hm({sessionIdGenerator:()=>Dm()});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=jt(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),Um)}),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 Bm}from"crypto";import{McpServer as Wm}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as qm}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as Ue}from"zod";function zm(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var hc=2e3,yc=2e4;function Jm(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return At([s]);let n=[],r=Qt(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=Fn(t);return i!==void 0&&n.push(i),n.join(`
194
- `)}function Vm(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 Gm(s){let e=new Wm({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:Ue.string().min(1).describe("Case-insensitive substring to search for."),limit:Ue.number().int().min(1).max(50).optional().describe("Maximum number of matches to return (default 10, max 50)."),include_tool_calls:Ue.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 we({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=go(u);if(!l)continue;let{kind:p,update:f}=l;if((p==="tool_call"||p==="tool_call_update")&&!r)continue;let m=Jm(u,p,f),g=m.toLowerCase().indexOf(a);if(g<0)continue;let h=zm(p),w=Vm(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 we({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:Ue.number().int().min(0).describe("Zero-based index of the first entry to include (inclusive)."),to_entry:Ue.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 we({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 we({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=At(u,{toolOutput:{maxPerCall:hc,maxTotal:yc}});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:Ue.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:Ue.string().optional().describe("ACP tool kind: execute (shell), read, edit, think, other. Agent-independent, unlike tool_name."),file_path:Ue.string().optional(),limit:Ue.number().int().min(1).max(100).optional(),include_output:Ue.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 we({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=go(y);if(!b)continue;let{kind:I,update:v}=b;if(I!=="tool_call"&&I!=="tool_call_update")continue;let x=typeof v.toolCallId=="string"&&v.toolCallId.length>0?v.toolCallId:`__noid_${k}`,E=l.get(x);if(E||(E={entryId:k,toolName:"(unnamed)",nameAuthoritative:!1,rawInput:{},locations:[],status:"in_progress"},l.set(x,E)),k<E.entryId&&(E.entryId=k),!E.nameAuthoritative){let M=Qt(v);M!==void 0?(E.toolName=M,E.nameAuthoritative=!0):typeof v.name=="string"&&v.name.length>0?(E.toolName=v.name,E.nameAuthoritative=!0):I==="tool_call"&&typeof v.title=="string"&&v.title.length>0&&(E.toolName=v.title,E.nameAuthoritative=!0)}if(E.kind===void 0&&typeof v.kind=="string"&&v.kind.length>0&&(E.kind=v.kind),E.output===void 0){let M=Fn(v);M!==void 0&&(E.output=M)}let R=v.rawInput;if(R&&typeof R=="object"&&!Array.isArray(R)&&Object.keys(R).length>0)for(let[M,T]of Object.entries(R))E.rawInput[M]===void 0&&(E.rawInput[M]=T);if(Array.isArray(v.locations))for(let M of v.locations){let T=M?.path;typeof T=="string"&&T.length>0&&!E.locations.includes(T)&&E.locations.push(T)}if(typeof v.status=="string"&&E.status==="in_progress"&&(E.status=v.status),y.recordedAt!==void 0&&E.timestamp===void 0&&(E.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=yc,h=!1;for(let k of f){let y=l.get(k);if(y.toolName=lr({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(),x=["file_path","filePath","path"],E=!1;for(let R of x){let M=y.rawInput[R];if(typeof M=="string"&&M.toLowerCase().includes(v)){E=!0;break}}if(!E){for(let R of y.locations)if(R.toLowerCase().includes(v)){E=!0;break}}if(!E)continue}let b={};for(let[v,x]of Object.entries(y.rawInput))typeof x=="string"?b[v]=x.length>500?x.slice(0,497)+"\u2026":x:(typeof x=="number"||typeof x=="boolean")&&(b[v]=x);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,x=Math.min(hc,g);if(x<=0)h=!0;else{let E=v.length<=x?v:v.slice(0,x-1)+"\u2026";I.output=E,I.outputBytes=v.length,I.outputTruncated=E.length<v.length,g-=E.length}}if(m.push(I),m.length>=o)break}let w=m.length>=o;return we({calls:m,truncated:w,...h?{outputBudgetExhausted:h}:{}})}),e}var Km=1e4;function wc(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=Gm(a),u=new qm({sessionIdGenerator:()=>Bm()});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=jt(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),Km)}),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 Ps=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 sh}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{randomUUID as rh}from"crypto";import{Server as Qm}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Ym,ListToolsRequestSchema as Xm}from"@modelcontextprotocol/sdk/types.js";function kc(s,e,t,n){let r=typeof t=="function"?async()=>t():async()=>t,o=new Qm({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(Xm,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(Ym,async(a,d)=>{let c=a.params.name,u=d._meta?.progressToken??d.requestId,l=eh(u,d.sendNotification);try{let p=await r(),f=await th(e.connection,s,c,a.params.arguments??{},p);return nh(f,c)}catch(p){return mo(p instanceof Error?p.message:String(p))}finally{l()}}),o}var Zm=15e3;function eh(s,e,t=Zm){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 th(s,e,t,n,r){return await s.request("hydra-acp/mcp_tools/invoke",{server:e,tool:t,args:n,sessionId:r})}function nh(s,e){if(s===null||typeof s!="object")return mo(`extension ${e} returned non-object`);let t=s;return Array.isArray(t.content)?t:mo(`extension ${e} omitted content array`)}function mo(s){return{content:[{type:"text",text:s}],isError:!0}}var oh=1e4;function vc(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=kc(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(E=>{I=setTimeout(()=>E(void 0),oh)}),x=await Promise.race([b.sessionReady.catch(()=>{}),v]);if(I!==void 0&&clearTimeout(I),x===void 0)throw new Error("session not ready");return x.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 x=[];for(let E of v){if(!E||typeof E!="object")continue;let R=E;if(typeof R.name!="string"||R.name.length===0||typeof R.description!="string"||R.inputSchema===null||typeof R.inputSchema!="object")continue;let M={name:R.name,description:R.description,inputSchema:R.inputSchema};R.outputSchema!==null&&typeof R.outputSchema=="object"&&(M.outputSchema=R.outputSchema),x.push(M)}return x}}),y=new sh({sessionIdGenerator:()=>rh()});return await k.connect(y),p.set(l,{server:k,transport:y}),y}async function d(u,l){let p=jt(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 xc(s,e){fh(s),qs(s.daemon.scrubEnv);let t=s,n=s.daemon.tls?await Be.readFile(ae(s.daemon.tls.key)):void 0,r=s.daemon.tls?await Be.readFile(ae(s.daemon.tls.cert)):void 0;await Be.mkdir(A.home(),{recursive:!0});let{stream:o,fileStream:i}=await uh(s.daemon.logLevel),a=ih({logger:{level:s.daemon.logLevel,stream:o},bodyLimit:256*1024*1024});await a.register(ah,{options:{handleProtocols:Fo}}),Qs(F=>{a.log.info(F)}),Zs(F=>{a.log.info(F)});let d=await fs.load(),c=new ys,u=new hs,l=new ps(e),p=new ms([l,new gs(d),u]),f=gd({validator:p});a.addHook("onRequest",async(F,me)=>{F.routeOptions.config?.skipAuth||F.url==="/acp"||F.url?.startsWith("/acp?")||(await f(F,me),!me.sent&&F.authIdentity?.startsWith("script:")&&!hd(F.method,F.routeOptions.url)&&me.code(403).send({error:"script tokens may only access read-only session data"}))});let m=setInterval(()=>{d.sweepExpired()},300*1e3);m.unref();let g=setInterval(()=>{c.sweepExpired()},300*1e3);g.unref();let h=new En(s,{onFetched:()=>{ed(h,b)},onStaleFallback:(F,me)=>{let Lt=Math.round(me/36e5),Ut=Lt>=48?`${Math.round(Lt/24)}d`:`${Lt}h`;a.log.warn(`registry fetch failed (${F.message}); serving stale cache last synced ${Ut} ago; agent versions may be outdated ('hydra registry refresh' to retry)`)}});no(F=>a.log.info(F));let w={info:F=>a.log.info(F),warn:F=>a.log.warn(F)},k=F=>Ye.spawn({...F,stderrTailBytes:s.daemon.agentStderrTailBytes,logger:w});Uo(s.compressToolContent);let y=new us,b=new ss(h,k,void 0,{idleTimeoutMs:s.daemon.sessionIdleTimeoutSeconds*1e3,orphanTimeoutMs:s.daemon.nonInteractiveOrphanTimeoutSeconds*1e3,sessionDefaults:s.sessionDefaults,synopsisAgent:s.synopsisAgent,synopsisModel:s.synopsisModel,compactionAgent:s.compaction?.agent,compactionModel:s.compaction?.model,defaultTransformers:s.defaultTransformers,sessionHistoryMaxEntries:s.daemon.sessionHistoryMaxEntries,sessionHistoryArchiveMaxBytes:s.daemon.sessionHistoryArchiveMaxBytes,sessionHistoryArchiveTiers:s.daemon.sessionHistoryArchiveTiers,logger:w,npmRegistry:s.npmRegistry,extensionCommands:y,defaultCwd:s.defaultCwd,disableWorkspaceSnapshots:s.disableWorkspaceSnapshots}),I=new ds(_o(s),void 0,{tokenRegistry:u}),v=new cs($o(s),void 0,{tokenRegistry:u}),x=[];Vd(a,le,sd(s),()=>x);let E=new Ts,R=new Ps,M,T=()=>{if(M!==void 0)return M;let F=a.server.address();return M=`http://127.0.0.1:${F&&typeof F=="object"?F.port:s.daemon.port}`,M},D={agentId:s.defaultAgent,cwd:s.defaultCwd,publicHost:s.daemon.publicHost,host:s.daemon.host,port:s.daemon.port,compaction:s.compaction};zd(a,b,D,{extensionMcp:R,mcpTokenRegistry:E,getDaemonOrigin:T}),Jd(a,h,b,{npmRegistry:s.npmRegistry}),Gd(a,I),Kd(a,v),Qd(a,()=>({defaultAgent:t.defaultAgent,defaultCwd:t.defaultCwd,sessionDefaults:{...t.sessionDefaults},...t.synopsisAgent!==void 0?{synopsisAgent:t.synopsisAgent}:{},...t.synopsisModel!==void 0?{synopsisModel:t.synopsisModel}:{},defaultTransformers:[...t.defaultTransformers]})),tc(a,{store:d,rateLimiter:c,staticTokenValidator:l}),sc(a,{processRegistry:u}),mc(a,E),wc(a,E);let q=vc(a,E,R);fc(a,{validator:p,manager:b,defaultAgent:s.defaultAgent,processRegistry:u,onExtensionVersion:(F,me)=>I.reportVersion(F,me),onTransformerVersion:(F,me)=>v.reportVersion(F,me),transformers:v,extensionCommands:y,mcpTokenRegistry:E,extensionMcp:R,extensionMcpControls:q,getDaemonOrigin:T,registry:h});let B=!!s.daemon.tls;await a.listen({host:B?"127.0.0.1":s.daemon.host,port:B?0:s.daemon.port});let Z=a.server.address(),L=Z&&typeof Z=="object"?Z.port:s.daemon.port,Se,Dc=s.daemon.host,wo=L;if(B&&n&&r){Se=lh({listenHost:s.daemon.host,listenPort:s.daemon.port,upstreamHost:"127.0.0.1",upstreamPort:L,tlsOptions:{key:n,cert:r},logger:a.log});let F=Se.address();F&&typeof F=="object"&&(wo=F.port)}await Be.mkdir(A.home(),{recursive:!0}),await Za({pid:process.pid,host:Dc,port:wo,loopbackPort:L,startedAt:new Date().toISOString()});let ko={daemonUrl:`http://127.0.0.1:${L}`,daemonHost:"127.0.0.1",daemonPort:L,serviceToken:e,daemonWsUrl:`ws://127.0.0.1:${L}/acp`,hydraHome:A.home()};I.setContext(ko),v.setContext(ko),await I.start(),await v.start();try{await b.reconcilePermissionFlags()}catch(F){a.log.warn(`permission flag reconcile failed: ${F.message}`)}try{await b.seedSessionIndex()}catch(F){a.log.warn(`session index seed 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 vo=s.daemon.agentSyncIntervalMinutes*60*1e3,bo=vo>0?td({registry:h,manager:b,intervalMs:vo,logger:w}):void 0,So=s.daemon.sessionGcIntervalMinutes*60*1e3,jc=s.daemon.sessionGcMaxAgeDays*24*60*60*1e3,Io=So>0?nd({manager:b,intervalMs:So,maxAgeMs:jc,logger:w}):void 0,Hc=ad({bootConfig:s,apply:F=>{t=F,h.setConfig(F),b.setLiveConfig({sessionDefaults:F.sessionDefaults}),D.agentId=F.defaultAgent,D.cwd=F.defaultCwd,qs(F.daemon.scrubEnv)},onDrift:F=>{x=F},logger:w});return{app:a,manager:b,registry:h,extensions:I,transformers:v,mcpTokenRegistry:E,extensionMcp:R,processRegistry:u,shutdown:async()=>{Hc(),Io&&Io(),bo&&bo(),clearInterval(m),clearInterval(g);let F=async(me,Lt)=>{try{await Lt()}catch(Ut){a.log.warn(`shutdown step ${me} failed: ${Ut instanceof Error?Ut.message:String(Ut)}`)}};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()),Qs(null),Zs(null),no(null),Se&&await F("tlsTerminator.close",()=>new Promise(me=>Se.close(()=>me()))),await F("app.close",()=>a.close());try{Ic.unlinkSync(A.pidFile())}catch{}await F("fileStream.flushSync",()=>i.flushSync())}}}var Sc=20;async function ch(s,e){let t=Ht.dirname(s),n=Ht.basename(s,".log"),r=new RegExp(`^${n}\\.(\\d+)\\.log$`),o;try{o=await Be.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=>Be.unlink(Ht.join(t,d.name))))}async function uh(s){await ch(A.logFile(),Sc);let e=await dh({file:A.logFile(),size:"10m",mkdir:!0,symlink:!0,limit:{count:Sc,removeOtherLogFiles:!0}}),t=bc.destination(2);return{stream:bc.multistream([{stream:e,level:s},{stream:t,level:s}]),fileStream:e}}function lh(s){let e=Cc.createServer(s.tlsOptions,t=>{let n=Ac.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 fh(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 Rh(){process.title="hydra-acp-daemon";let{installGlobalTlsTrust:s}=await Promise.resolve().then(()=>(Nc(),Fc));s();let e=await qt(),t=await Ao(),n=await xc(e,t);process.stdout.write(`hydra-acp daemon listening on ${e.daemon.host}:${e.daemon.port}
185
+ `),a}function Ro(s,e){let t=s<0?e+s+1:s;return t<1?1:t>e?e:t}function um(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:m}of s)m.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((m,h)=>{m.recordedAt>=d&&c.add(n[h])});let u=[],l,p;return s.forEach((m,h)=>{let f=n[h];f<i||f>a||d!==void 0&&!c.has(f)||(u.push(m),l??=f,p=f)}),{events:u,window:{from:l??i,to:p??a,total:o}}}function lm(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=Jd(n.update,{cwd:s.session.cwd});r!==null&&e.push({event:r,recordedAt:t.recordedAt})}return e}function fm(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 pm(s,e){let t=e.session,n=Ke(t.sessionId),r=t.title?.trim()||`Hydra session ${n}`;s.push(`# ${Tn(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?`${xo(a.size)}`:void 0;d.push(u?`${xo(a.used)} / ${u} tokens`:`${xo(a.used)} tokens`)}let c=lo(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(`
186
+ `)),s.push("")}function gm(s,e,t,n){let{includeTools:r,includeThoughts:o}=n;if(!e.some(f=>mm(f.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 f of c)s.push(f);s.push(""),c=[]}},m=()=>{p(),d.length>0&&(ec(s,d.trimEnd(),"*"),s.push(""),d=""),a.length!==0&&(s.push(a.trimEnd()),s.push(""),a="")},h=()=>{l||(l=!0)};for(let{event:f}of e)switch(f.kind){case"user-text":{m(),s.push("---"),s.push(""),i+=1,ec(s,f.text,"**"),s.push(""),l=!0;break}case"agent-text":h(),a+=f.text;break;case"agent-thought":{if(!o)break;h(),a.length>0&&(s.push(a.trimEnd()),s.push(""),a=""),d+=f.text;break}case"tool-call":{if(!r||(h(),(a.length>0||d.length>0)&&m(),u.has(f.toolCallId)))break;u.add(f.toolCallId);let g=t.get(f.toolCallId)??{title:f.title,status:f.status??"pending"};c.push(`- ${ym(g.status)} ${hm(g)}`);break}case"tool-call-update":break;case"plan":{h(),m(),s.push("**Plan:**"),s.push("");for(let g of f.entries){let w=g.status==="completed"?"[x]":"[ ]";s.push(`- ${w} ${Tn(g.content)}`)}s.push("");break}case"mode-changed":h(),m(),s.push(`_mode: ${Tn(f.mode)}_`),s.push("");break;case"model-changed":h(),m(),s.push(`_model: ${Tn(f.model)}_`),s.push("");break;case"turn-complete":m();break;case"usage-update":case"available-commands":case"session-info":case"unknown":break}m()}function mm(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 hm(s){let e=s.status,t=e==="completed"||e===void 0?"":` _(${e})_`;return`${Tn(s.title)}${t}`}function ym(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 nc=String.raw`<\/?[a-zA-Z][a-zA-Z0-9-]*(?:\s[^<>]*)?\/?>`,wm=new RegExp(nc);function ec(s,e,t){if(wm.test(e)){km(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(`
187
+ `);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 km(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(`
188
+ `))s.push(o);s.push(r)}function Tn(s){return s.replace(new RegExp(nc,"g"),e=>e.replace(/</g,"&lt;").replace(/>/g,"&gt;"))}function xo(s){return s.toLocaleString("en-US")}function Te(s){return s==="127.0.0.1"||s==="::1"||s==="localhost"||s==="[::1]"}function vm(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=>bm(u)).filter(u=>u.term.length>0);return{operator:o,terms:c}}function bm(s){let e=/^(\w+):"([^"]*)"$/.exec(s);if(e)return{scope:sc(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:sc(n[1]),term:n[2].trim()}:{scope:"all",term:s.trim()}}function sc(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 Sm(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 Im=5,Am=200,$s=72,Cm=24,Rm=512;function dc(s){return Number.isFinite(s)?Math.max(Cm,Math.min(Rm,Math.floor(s))):$s}async function cc(s,e,t={}){let n=vm(e);if(n.terms.length===0)return{query:e,truncated:!1,results:[]};let r=t.maxSnippetsPerSession??Im,o=t.maxSessions??Am,i=dc(t.snippetWidth??$s),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 m=await s.loadHistory(p.sessionId,{tools:"references"}).catch(()=>[]),h=Em(m,n,r,i,xm(p));if(h.snippets.length===0)continue;let f={sessionId:p.sessionId,cwd:p.cwd,status:p.status,updatedAt:p.updatedAt,totalMatches:h.totalMatches,snippets:h.snippets};p.title!==void 0&&(f.title=p.title),u.push(f)}return{query:e,truncated:l,results:u}}function xm(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 Em(s,e,t,n=$s,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=Tm(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 Tm(s,e,t,n,r,o){let i=e.toLowerCase(),a=0,d=[],c=new Set;for(let u of s){let l=Pm(u).filter(p=>Sm(t,p.kind));for(let p of l){let m=p.text.toLowerCase();if(p.kind==="edit"){let g=o?.(p.text);if(!(rc(p.text,e)||(g!==void 0&&g!==p.text?rc(g,e):!1))||c.has(p.text))continue;if(c.add(p.text),a+=1,d.length<n){let y={kind:"edit",text:p.text,recordedAt:u.recordedAt};p.toolName!==void 0&&(y.toolName=p.toolName),d.push(y)}continue}let h=m.indexOf(i);if(h===-1)continue;let f=0;for(;h!==-1;)f++,h=m.indexOf(i,h+i.length);if(a+=f,d.length<n){let g=m.indexOf(i),w={kind:p.kind,text:Dm(p.text,g,i.length,r),recordedAt:u.recordedAt};p.toolName!==void 0&&(w.toolName=p.toolName),d.push(w)}}}return{totalMatches:a,snippets:d}}function Pm(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=_s(n.content);return o?[{kind:"agent",text:o}]:[]}case"agent_thought":case"agent_thought_chunk":{let o=typeof n.text=="string"?Ee(n.text):_s(n.content);return o?[{kind:"thought",text:o}]:[]}case"user_message_chunk":{if(Om(n))return[];let o=_s(n.content);return o?[{kind:"user",text:o}]:[]}case"prompt_received":{let o=Nm(n.prompt);return o?[{kind:"user",text:o}]:[]}case"tool_call":case"tool_call_update":return Mm(n);default:return[]}}function Mm(s){let e=ic(s,"name"),t=ic(s,"title"),n=[];if(t!==void 0){let a=re(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=re(e);a.length>0&&n.push({kind:"tool",toolName:e,text:a})}let r=s.rawInput;if(r&&typeof r=="object"){let a=ac(r);if(a.length>0){let d={kind:"tool-input",text:re(a)};e!==void 0&&(d.toolName=e),n.push(d)}}for(let a of _m(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=ac(o);if(a.length>0){let d={kind:"tool-input",text:re(a)};e!==void 0&&(d.toolName=e),n.push(d)}}let i=$m(s);if(i!==null){let a={kind:"tool",text:i};e!==void 0&&(a.toolName=e),n.push(a)}return n}function _m(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 rc(s,e){let t=oc(s.toLowerCase()),n=oc(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 oc(s){return s.length>1&&s.endsWith("/")?s.slice(0,-1):s}function $m(s){if(!Fm(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=re(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=re(n);if(r.length>0)return r}}return null}function Fm(s){return s==="failed"||s==="rejected"||s==="cancelled"}function Om(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 _s(s){if(typeof s=="string")return Ee(s);if(!s||typeof s!="object"||Array.isArray(s))return"";let e=s;return typeof e.text=="string"?Ee(e.text):""}function Nm(s){if(!Array.isArray(s))return"";let e=[];for(let t of s){let n=_s(t);n.length>0&&e.push(n)}return e.join("")}function ic(s,e){let t=s[e];return typeof t=="string"?t:void 0}function ac(s){try{return JSON.stringify(s)}catch{return""}}function Dm(s,e,t,n=$s){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=dc(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)),m=Math.max(0,a-(c-p)),h=Math.min(r.length,a+i.length+p),f=m>0?"\u2026":"",g=h<r.length?"\u2026":"";return`${f}${r.slice(m,h)}${g}`}import{randomBytes as lc}from"crypto";function uc(s){let e=lc(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 Eo(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(uc({name:"hydra-acp-stdin",session:n,tokenRegistry:e,getOrigin:t})),r.push(uc({name:"hydra-acp-recall",session:n,tokenRegistry:e,getOrigin:t}));let o=qt(s.deps);return o!==void 0&&(o.bindToSession(n),r=[...r,...o.descriptors]),r}}function qt(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=lc(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 jm=new Set(["/v1/sessions/:id/history","/v1/sessions/:id/events"]);function fc(s,e){let t=e.fetchImpl??fetch;s.addHook("preHandler",async(n,r)=>{let o=n.routeOptions.url;if(!o||!o.startsWith("/v1/sessions/:id"))return;let i=n.params,a=i.id;if(typeof a!="string")return;let d=pt(a);if(!d)return;let c=e.store.get(d.name);if(!c){r.code(404).send({error:`No remote named "${d.name}". Run \`hydra remote add\` first.`});return}let u=n.query;if(jm.has(o)&&Lm(u?.follow)){let w=c.port===St?"":`:${c.port}`;r.code(501).send({error:`Streaming a federated session isn't supported yet. Attach directly with hydra://${c.host}${w}/${d.localId} instead.`});return}let l=Um(o,i,d.localId,n.url),m=`${Te(c.host)?"http":"https"}://${c.host}:${c.port}${l}`,h;try{h=await t(m,{method:n.method,headers:{Authorization:`Bearer ${c.token}`,...n.body!==void 0?{"Content-Type":"application/json"}:{}},...n.body!==void 0&&n.method!=="GET"?{body:JSON.stringify(n.body)}:{}})}catch(w){r.code(502).send({error:`Could not reach remote "${d.name}" (${c.host}:${c.port}): ${w.message}`});return}if(h.status===204){r.code(204).send();return}let f=await h.text(),g=h.headers.get("content-type");g&&r.header("content-type",g),r.code(h.status).send(f)})}var Hm=5e3,Fs=class{constructor(e,t={}){this.store=e;this.opts=t}store;opts;perPeer=new Map;timer;start(){this.timer||(this.refreshNow(),this.timer=setInterval(()=>{this.refreshNow()},this.opts.intervalMs??Hm),this.timer.unref?.())}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}async refreshNow(){let e=this.opts.fetchImpl??fetch,t=new Set(this.store.list().map(n=>n.name));for(let n of[...this.perPeer.keys()])t.has(n)||this.perPeer.delete(n);await Promise.allSettled(this.store.list().map(async n=>{let r=this.store.get(n.name);if(!r)return;let o=this.perPeer.get(n.name),i=Te(r.host)?"http":"https",a=new URLSearchParams({includeNonInteractive:"1"}),d=o?.cursor!==void 0;d&&a.set("since",String(o.cursor));let c=`${i}://${r.host}:${r.port}/v1/sessions?${a.toString()}`,u;try{u=await e(c,{headers:{Authorization:`Bearer ${r.token}`}})}catch{return}if(!u.ok)return;let l=await u.json(),p=o?.sessions??new Map;if(d){for(let[m,h]of[...p])h.status!=="cold"&&p.delete(m);for(let m of l.removed??[])p.delete(Tt({name:n.name,localId:m}))}else p.clear();for(let m of l.sessions??[]){let h=Tt({name:n.name,localId:String(m.sessionId)});p.set(h,{...m,sessionId:h,remote:n.name})}this.perPeer.set(n.name,{cursor:l.cursor,sessions:p})}))}list(e){let t=[];for(let n of this.perPeer.values())t.push(...n.sessions.values());return t.filter(n=>!(e.status&&n.status!==e.status||!e.includeNonInteractive&&n.interactive!==!0))}};async function pc(s,e,t,n=fetch){let r=s.get(e);if(!r)return{status:404,body:{error:`No remote named "${e}". Run \`hydra remote add\` first.`}};let i=`${Te(r.host)?"http":"https"}://${r.host}:${r.port}/v1/sessions`,a;try{a=await n(i,{method:"POST",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:JSON.stringify(t)})}catch(l){return{status:502,body:{error:`Could not reach remote "${e}" (${r.host}:${r.port}): ${l.message}`}}}let d=await a.text(),c=null;try{c=d.length>0?JSON.parse(d):null}catch{c=null}if(!a.ok)return{status:a.status,body:c};let u=c;return u&&typeof u.sessionId=="string"?{status:a.status,body:{...u,sessionId:Tt({name:e,localId:u.sessionId})}}:{status:a.status,body:c}}function Lm(s){return s==="1"||s==="true"||s===!0}function Um(s,e,t,n){let r=s.replace(/:([A-Za-z_]+)/g,(i,a)=>encodeURIComponent(a==="id"?t:e[a]??"")),o=n.indexOf("?");return o===-1?r:r+n.slice(o)}var Os=new Set(["usage_update","tool_call","tool_call_update","prompt_received","turn_complete","permission_resolved"]);function gc(s){if(s.publicHost&&s.publicHost.length>0)return s.publicHost;if(s.host&&!Te(s.host))return s.port!==void 0?`${s.host}:${s.port}`:s.host}function hc(s,e,t,n={},r,o){s.get("/v1/sessions",async(l,p)=>{let m=l.query,h=m?.includeNonInteractive==="1"||m?.includeNonInteractive==="true",f;if(m?.since!==void 0&&(f=Number(m.since),!Number.isFinite(f)||f<0))return p.code(400).send({error:`since must be a non-negative number, got ${JSON.stringify(m.since)}`});let g=m?.status==="warm"||m?.status==="cold"?m.status:void 0,w={cwd:m?.cwd,includeNonInteractive:h,...g?{status:g}:{}},y=o&&!w.cwd?o.list({includeNonInteractive:h,...g?{status:g}:{}}):[];if(f!==void 0){let b=await e.listSince(w,f);return{sessions:[...b.entries,...y],removed:b.removed,cursor:b.cursor}}let k=await e.listing(w);return{sessions:[...k.entries,...y],removed:[],cursor:k.cursor}}),s.get("/v1/sessions/:id",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=await e.getOne(h);return f||(p.code(404).send({error:"session not found"}),p)}),s.post("/v1/sessions/search",async(l,p)=>{let m=l.body??{},h=typeof m.q=="string"?m.q:"";if(h.trim().length===0)return p.code(400).send({error:"q is required"}),p;let g={sessionIds:Array.isArray(m.sessionIds)?m.sessionIds.filter(y=>typeof y=="string"&&y.length>0):void 0};return typeof m.snippetWidth=="number"&&(g.snippetWidth=m.snippetWidth),await cc(e,h,g)}),s.post("/v1/sessions",async(l,p)=>{let m=l.body??{};if(m.remote){if(!r)return p.code(404).send({error:`No remote named "${m.remote}". Run \`hydra remote add\` first.`});let k=await pc(r,m.remote,{cwd:m.cwd,agentId:m.agentId,mcpServers:m.mcpServers,workspace:m.workspace});return p.code(k.status).send(k.body)}let h=le(m.cwd??t.cwd),f=await Xt(h),g=m.agentId??f.agentId??t.agentId,w=qt(n),y=w!==void 0?[...m.mcpServers??[],...w.descriptors]:m.mcpServers;try{let k=await e.create({cwd:h,agentId:g,mcpServers:y,...m.workspace!==void 0?{workspace:m.workspace}:{}});w!==void 0&&w.bindToSession(k),p.code(201).send({sessionId:k.sessionId,agentId:k.agentId,cwd:k.cwd,...k.workspace!==void 0?{workspace:k.workspace}:{},...k.workspaceError!==void 0?{workspaceError:k.workspaceError}:{}})}catch(k){w!==void 0&&w.abandon(k instanceof Error?k:void 0),p.code(500).send({error:k.message})}}),s.post("/v1/sessions/collect",async(l,p)=>{let m=l.body??{},h=typeof m.maxAgeDays=="number"&&m.maxAgeDays>0?m.maxAgeDays*24*60*60*1e3:0,f=typeof m.limit=="number"&&m.limit>0?m.limit:1e3,g=m.selection==="explicit"||m.selection==="unpromoted"?m.selection:"unpromoted";try{let w=await So({manager:e,maxAgeMs:h,maxDeletions:f,selection:g,verbose:!1});p.code(200).send(w)}catch(w){p.code(500).send({error:w.message})}}),s.post("/v1/sessions/:id/kill",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=e.get(h);if(f){f.close({deleteRecord:!1,by:"REST POST /kill"}).catch(()=>{}),p.code(202).send();return}if(!await e.hasRecord(h)){p.code(404).send({error:"session not found"});return}p.code(204).send()}),s.post("/v1/sessions/:id/stdin/open",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=e.get(h);if(!f)return p.code(404).send({error:"session not found"}),p;let g=l.body??{},w={};(g.mode==="memory"||g.mode==="file")&&(w.mode=g.mode),typeof g.capacityBytes=="number"&&(w.capacityBytes=g.capacityBytes),typeof g.fileCapBytes=="number"&&(w.fileCapBytes=g.fileCapBytes),(w.mode??"memory")==="file"&&(w.filePathFor=y=>Ns.join(mc.tmpdir(),`hydra-acp-stdin-${y}.log`));try{return f.openStream(w)}catch(y){return p.code(409).send({error:y.message}),p}}),s.post("/v1/sessions/:id/stdin",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=e.get(h);if(!f)return p.code(404).send({error:"session not found"}),p;let g=l.body??{},w=typeof g.chunk=="string"?g.chunk:"",y=g.eof===!0;try{return f.streamWrite(w,y)}catch(k){return p.code(409).send({error:k.message}),p}}),s.patch("/v1/sessions/:id",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=l.body??{};if(f.cwd!==void 0){if(typeof f.cwd!="string"||!Ns.isAbsolute(f.cwd)){p.code(400).send({error:"cwd must be an absolute path"});return}let w=await e.setCwd(h,f.cwd);if(w==="missing"){p.code(404).send({error:"session not found"});return}if(w==="not-a-directory"){p.code(400).send({error:`${f.cwd} is not a directory`});return}if(w==="live"){p.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(w==="bound"){p.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}p.code(204).send();return}if("workspace"in f){if(f.workspace!==null){p.code(400).send({error:"workspace may only be set to null (clear the binding)"});return}let w=await e.clearWorkspaceBinding(h);if(w==="missing"){p.code(404).send({error:"session not found"});return}if(w==="live"){p.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}p.code(204).send();return}if(f.priority!==void 0){let w=f.priority,y;if(w===null||w===0)y=void 0;else if(typeof w=="number"&&Number.isInteger(w)&&w>0)y=w;else{p.code(400).send({error:"priority must be a non-negative integer (or null to clear)"});return}if(!await e.setPriority(h,y)){p.code(404).send({error:"session not found"});return}p.code(204).send();return}if(f.regen===!0){if(!(e.get(h)!==void 0||await e.hasRecord(h))){p.code(404).send({error:"session not found"});return}e.scheduleSynopsis(h),p.code(202).send();return}if(typeof f.title!="string"||f.title.trim().length===0){p.code(400).send({error:"title must be a non-empty string"});return}if(!await e.setTitle(h,f.title)){p.code(404).send({error:"session not found"});return}p.code(204).send()}),s.delete("/v1/sessions/:id",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=e.get(h);if(f){await f.close({deleteRecord:!0,by:"REST DELETE /v1/sessions"}),await e.waitForDeletion(h),await e.hasRecord(h)&&await e.deleteRecord(h),p.code(204).send();return}if(!await e.deleteRecord(h)){p.code(404).send({error:"session not found"});return}p.code(204).send()}),s.get("/v1/sessions/:id/export",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=l.query?.tools,g=f==="references"?"references":od(f),w=await e.exportBundle(h,g==="references"?{tools:"references"}:{});if(!w){p.code(404).send({error:"session not found"});return}let y=yn({record:w.record,history:g==="summary"?id(w.history,"summary"):w.history,promptHistory:w.promptHistory.length>0?w.promptHistory:void 0,...w.toolBlobs!==void 0?{toolBlobs:w.toolBlobs}:{},hydraVersion:me,machine:sn(),hydraHost:gc(t)}),k=new Date().toISOString().replace(/[:.]/g,"-");p.header("Content-Disposition",`attachment; filename="${h}-${k}.hydra"`),p.code(200).send(y)}),s.get("/v1/sessions/:id/diff",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=await e.exportBundle(h);if(!f){p.code(404).send({error:"session not found"});return}let g=l.query??{},w=g.fold==="true"||g.fold==="1",y=typeof g.paths=="string"&&g.paths.length>0?new Set(g.paths.split(",").map(b=>b.trim()).filter(b=>b.length>0)):void 0,k=Xd(f.history);y&&(k=k.filter(b=>y.has(b.path))),w&&(k=k.map(b=>({...b,hunks:Zd(b.hunks)}))),p.code(200).send(k)}),s.get("/v1/sessions/:id/tools/:hash",async(l,p)=>{let m=l.params,h=await e.resolveCanonicalId(m.id)??m.id,f=await e.loadToolBlob(h,m.hash);if(f===null){p.code(404).send({error:"tool blob not found"});return}p.header("Content-Type","text/plain; charset=utf-8"),p.code(200).send(f)}),s.get("/v1/sessions/:id/transcript",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=await e.exportBundle(h);if(!f){p.code(404).send({error:"session not found"});return}let g=yn({record:f.record,history:f.history,promptHistory:f.promptHistory.length>0?f.promptHistory:void 0,hydraVersion:me,machine:sn(),hydraHost:gc(t)}),w=l.query,y=S=>S==="1"||S==="true"||S==="yes",k=S=>{let v=w?.[S];if(v===void 0||v==="")return;let E=Number(v);return Number.isFinite(E)?E:"bad"},b={};for(let S of["from","to","last","since"]){let v=k(S);if(v==="bad"){p.code(400).send({error:`${S} must be a number`});return}v!==void 0&&(b[S==="since"?"sinceMs":S]=v)}p.header("Content-Type","text/markdown; charset=utf-8"),p.code(200).send(tc(g,{includeTools:y(w?.tools),includeThoughts:y(w?.thoughts),...b}))}),s.post("/v1/sessions/:id/fork",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=l.body??{},g={};if(f.forkAt!==void 0){if(typeof f.forkAt!="string"||f.forkAt.length===0){p.code(400).send({error:"forkAt must be a non-empty string"});return}g.forkAt=f.forkAt}if(f.cwd!==void 0){if(typeof f.cwd!="string"||f.cwd.length===0){p.code(400).send({error:"cwd must be a non-empty string"});return}g.cwd=le(f.cwd)}if(f.agentId!==void 0){if(typeof f.agentId!="string"||f.agentId.length===0){p.code(400).send({error:"agentId must be a non-empty string"});return}g.agentId=f.agentId}if(f.title!==void 0){if(typeof f.title!="string"){p.code(400).send({error:"title must be a string"});return}g.title=f.title}if(f.mode!==void 0){if(f.mode!=="verbatim"&&f.mode!=="synthesis"){p.code(400).send({error:'mode must be "verbatim" or "synthesis"'});return}g.mode=f.mode}if(f.model!==void 0){if(typeof f.model!="string"||f.model.length===0){p.code(400).send({error:"model must be a non-empty string"});return}g.model=f.model}try{let w=await e.forkSession(h,g);p.code(201).send(w)}catch(w){let y=w;if(y.code===x.SessionNotFound){p.code(404).send({error:y.message});return}if(y.code===x.InvalidParams||y.code===x.AgentNotInstalled){p.code(400).send({error:y.message});return}p.code(500).send({error:y.message})}}),s.post("/v1/sessions/import",async(l,p)=>{let m=l.body??{};if(m.bundle===void 0){p.code(400).send({error:"missing bundle"});return}let h;if(m.cwd!==void 0){if(typeof m.cwd!="string"||m.cwd.length===0){p.code(400).send({error:"cwd must be a non-empty string"});return}h=m.cwd}let f;try{f=gd(m.bundle)}catch(g){p.code(400).send({error:"invalid bundle",details:g.message});return}try{let g=await e.importBundle(f,{replace:m.replace===!0,...h!==void 0?{cwd:h}:{}});p.code(201).send(g)}catch(g){let w=g;if(w.code===x.BundleAlreadyImported){p.code(409).send({error:"bundle already imported",existingSessionId:w.existingSessionId});return}p.code(500).send({error:w.message})}}),s.get("/v1/sessions/:id/compact/status",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=e.get(h),g;if(f?g=f.summarizedThroughEntry:g=await e.getSummarizedThroughEntry(h),g===void 0&&!await e.hasRecord(h))return p.code(404).send({error:"session not found"}),p;let w=await e.getCompactionState(h),y=await e.getRollbackBreadcrumb(h),k=await e.getPendingAgentSwap(h),b=!1,S,v=f?.currentUsage,E=typeof v?.used=="number"&&typeof v?.size=="number"&&v.size>0?{used:v.used,size:v.size}:void 0,A=await e.loadHistory(h,{tools:"references",maxEntries:1/0}).catch(()=>[]);if(A.length>0&&t.compaction){let C=g??0,T=A.length,M=C<=A.length?C:0,H=A.slice(M),J=Ud(H);S=Io(J);let $=f?.currentModel,W=A.at(-1).recordedAt;b=Bd({summarizedThroughEntry:C,totalEntries:T,unsummarizedChars:J,compactionInFlight:e.getCompactionInFlight(),currentModel:$,lastActivityMs:W,nowMs:Date.now(),config:t.compaction,...typeof v?.used=="number"?{agentReportedUsed:v.used}:{},...typeof v?.size=="number"?{agentReportedSize:v.size}:{}})}return{summarizedThroughEntry:g??void 0,inFlight:e.getCompactionInFlight(),shouldCompact:b,...S!=null?{approxTokens:S}:{},...E!=null?{currentUsage:E}:{},...w!=null?{compactionState:w}:{},...y!=null?{rollbackBreadcrumb:y}:{},...k!=null?{pendingAgentSwap:k}:{}}}),s.post("/v1/sessions/:id/compact",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m;if(e.get(h)){e.scheduleCompaction(h),p.code(202).send({scheduled:!0});return}if(!await e.hasRecord(h)){p.code(404).send({error:"session not found"});return}e.scheduleCompaction(h),p.code(202).send({scheduled:!0})}),s.post("/v1/sessions/:id/compact/rollback",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m;if(!await e.hasRecord(h)){p.code(404).send({error:"session not found"});return}try{await e.performUncompact(h),p.code(202).send({rolledBack:!0})}catch(f){let g=f instanceof Error?f.message:String(f);p.code(409).send({error:g})}}),s.post("/v1/sessions/:id/workspace/clean",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=l.body??{};if(f.deep!==void 0&&typeof f.deep!="boolean"){p.code(400).send({error:"deep must be a boolean"});return}if(!await e.hasRecord(h)){p.code(404).send({error:"session not found"});return}if(e.get(h)===void 0){p.code(409).send({error:"session is not live. Cleaning rewrites the workspace under a running agent, so it is only available inside a live session (`/hydra workspace clean`). For a cold workspace use `hydra workspace remove` instead."});return}try{let g=await e.runWorkspaceAction(h,"clean",void 0,{deep:f.deep===!0});p.code(202).send({report:g})}catch(g){p.code(409).send({error:g instanceof Error?g.message:String(g)})}}),s.get("/v1/sessions/:id/history",async(l,p)=>{let m=l.params.id,h=l.query,f=h?.follow==="1"||h?.follow==="true",g=await e.resolveCanonicalId(m)??m,w=e.get(g),y,k,b=!1,S=1e4,v=[];if(w){f&&(k=w.onBroadcast(A=>{p.raw.writableEnded||(b?p.raw.write(JSON.stringify(A)+`
189
+ `):(v.push(A),v.length>S&&v.shift()))})),l.raw.on("close",()=>{k?.(),p.raw.writableEnded||p.raw.end()});try{y=await w.getHistorySnapshot()}catch(A){throw k?.(),A}}else{let A=await e.getHistory(g);if(A===void 0)return p.code(404).send({error:"session not found"}),p;y=A}p.raw.setHeader("Content-Type","application/x-ndjson"),p.raw.setHeader("Cache-Control","no-cache"),p.raw.statusCode=200;let E=new Set;for(let A of y??[]){p.raw.write(JSON.stringify(A)+`
190
+ `);let C=A;typeof C.recordedAt=="number"&&E.add(String(C.recordedAt))}for(;v.length>0;){let A=v.splice(0,v.length);for(let C of A){let T=C,M=typeof T.recordedAt=="number"?String(T.recordedAt):"";M&&E.has(M)||p.raw.write(JSON.stringify(C)+`
191
+ `)}}return b=!0,k||p.raw.end(),p});function i(l,p,m){let h=typeof l=="string"?l.trim():"";if(h.length===0)return null;let f;try{f=JSON.parse(h)}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 g=f;if(typeof g.recordedAt!="number"||m!==void 0&&g.recordedAt<m||typeof g.params!="object"||g.params===null||Array.isArray(g.params))return null;let w=g.params;if(typeof w.update!="object"||w.update===null||Array.isArray(w.update))return null;let k=w.update.sessionUpdate;return typeof k!="string"||!p.has(k)?null:{recordedAt:g.recordedAt,entry:f}}function a(l,p,m){let f=p.params.update,g={sessionId:l,ts:new Date(p.recordedAt).toISOString(),kind:m,update:f};return f.messageId!==void 0&&f.messageId!==null&&(g.messageId=f.messageId),g}async function*d(l,p,m,h){for await(let f of p){let g=i(f,m,h);if(g){let w=g.entry.params.update.sessionUpdate;yield{ts:g.recordedAt,row:a(l,g.entry,w)}}}}async function c(l,p,m,h){let f=Po.createInterface({input:To.createReadStream(p),crlfDelay:1/0}),g=d(l,f,m,h),w=await g.next(),y=w.done?null:w.value;return{sessionId:l,rl:f,gen:g,current:y,exhausted:y===null}}async function u(l){let p=await l.gen.next();p.done?(l.exhausted=!0,l.current=null):l.current=p.value}s.get("/v1/sessions/events",async(l,p)=>{let m=l.query,h=m.kinds;if(!h||h.trim().length===0)return p.code(400).send({error:"kinds parameter is required"}),p;let f=h.split(",").map(S=>S.trim());if(f.length===0)return p.code(400).send({error:"kinds parameter is required"}),p;for(let S of f)if(!Os.has(S))return p.code(400).send({error:`kind "${S}" is not queryable; allowed kinds: ${[...Os].join(", ")}`}),p;let g=new Set(f),w;if(m.since!==void 0&&m.since.trim().length>0){let S=new Date(m.since);if(isNaN(S.getTime()))return p.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),p;w=S.getTime()}let y=await e.list({includeNonInteractive:!0}),k=w!==void 0?y.filter(S=>new Date(S.updatedAt).getTime()>=w):y;p.raw.setHeader("content-type","application/x-ndjson"),p.raw.statusCode=200;let b=[];for(let S of k)try{let v=R.historyFile(S.sessionId),E=await c(S.sessionId,v,g,w);E.exhausted||b.push(E)}catch(v){if(v.code==="ENOENT")continue;throw v}l.raw.on("close",()=>{for(let S of b)try{S.rl.close()}catch{}p.raw.writableEnded||p.raw.end()});try{for(;b.length>0;){let S=-1,v=1/0;for(let A=0;A<b.length;A++){let C=b[A];C.current!==null&&C.current.ts<v&&(v=C.current.ts,S=A)}if(S===-1)break;let E=b[S];if(p.raw.write(JSON.stringify(E.current.row)+`
192
+ `),await u(E),E.exhausted){try{E.rl.close()}catch{}b.splice(S,1)}}}catch(S){for(let v of b)try{v.rl.close()}catch{}throw S}return p.raw.end(),p}),s.get("/v1/sessions/:id/events",async(l,p)=>{let m=l.params.id,h=l.query,f=await e.resolveCanonicalId(m)??m;if(!e.get(f)&&!await e.hasRecord(f))return p.code(404).send({error:"session not found"}),p;let w=h.kinds;if(!w||w.trim().length===0)return p.code(400).send({error:"kinds parameter is required"}),p;let y=w.split(",").map(A=>A.trim());if(y.length===0)return p.code(400).send({error:"kinds parameter is required"}),p;for(let A of y)if(!Os.has(A))return p.code(400).send({error:`kind "${A}" is not queryable; allowed kinds: ${[...Os].join(", ")}`}),p;let k=new Set(y),b;if(h.since!==void 0&&h.since.trim().length>0){let A=new Date(h.since);if(isNaN(A.getTime()))return p.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),p;b=A.getTime()}let S=R.historyFile(f),v=To.createReadStream(S),E=Po.createInterface({input:v,crlfDelay:1/0});p.raw.setHeader("content-type","application/x-ndjson"),p.raw.statusCode=200;try{for await(let A of E){let C=typeof A=="string"?A.trim():"";if(C.length===0)continue;let T;try{T=JSON.parse(C)}catch{console.debug("events endpoint: skipping malformed JSONL line in %s",S);continue}if(!T||typeof T!="object"||Array.isArray(T)){console.debug("events endpoint: skipping non-object JSONL line in %s",S);continue}let M=T;if(typeof M.recordedAt!="number"||typeof M.params!="object"||M.params===null||Array.isArray(M.params))continue;let H=M.params;if(typeof H.update!="object"||H.update===null||Array.isArray(H.update))continue;let J=H.update,$=J.sessionUpdate;if(typeof $!="string"||!k.has($)||b!==void 0&&M.recordedAt<b)continue;let W={ts:new Date(M.recordedAt).toISOString(),kind:$,update:J};J.messageId!==void 0&&J.messageId!==null&&(W.messageId=J.messageId),p.raw.write(JSON.stringify(W)+`
193
+ `)}}catch(A){if(A.code==="ENOENT")return p.raw.end(),p;throw A}return p.raw.end(),p}),s.post("/v1/sessions/:id/prompt/:messageId/notify",async(l,p)=>{let m=l.params,h=m.id,f=await e.resolveCanonicalId(h)??h,g=m.messageId,w=l.body,y=typeof w?.callbackUrl=="string"?w.callbackUrl:"",k=typeof w?.secret=="string"?w.secret:"";if(!g||!y||!k){p.code(400).send({error:"messageId, callbackUrl, and secret are all required"});return}let b;try{b=new URL(y)}catch{p.code(400).send({error:"callbackUrl must be a valid absolute URL"});return}if(b.protocol!=="https:"&&b.protocol!=="http:"){p.code(400).send({error:"callbackUrl must be http or https"});return}let S=e.get(f);if(!S){p.code(404).send({error:"session not found or not warm"});return}let v=S.registerTurnNotify(g,y,k);if(v.alreadyTerminal){p.code(200).send({status:"already_terminal",stopReason:v.stopReason});return}p.code(202).send({status:"registered"})}),s.get("/v1/sessions/:id/attention",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=e.get(h);return!f&&!await e.hasRecord(h)?(p.code(404).send({error:"session not found"}),p):f?{flags:f.listAttentionFlags()}:{flags:(await e.store.read(h))?.attentionFlags??[]}}),s.get("/v1/sessions/attention",async(l,p)=>{let m=l.query;if(!m.source||m.source.trim().length===0)return p.code(400).send({error:"source query parameter is required"}),p;let h=await e.list({includeNonInteractive:!0}),f=[];for(let g of h){let w=e.get(g.sessionId),y;w?y=w.listAttentionFlags():y=(await e.store.read(g.sessionId))?.attentionFlags??[];for(let k of y)k.source===m.source&&f.push({...k,sessionId:g.sessionId})}return{flags:f}}),s.post("/v1/sessions/:id/attention/clear",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,g=l.body??{},w=typeof g.source=="string"?g.source:"",y=typeof g.reason=="string"?g.reason:"";if((w.length>0||y.length>0)&&!(w.length>0&&y.length>0)){p.code(400).send({error:"both source and reason are required to clear a specific flag, or omit both to clear all"});return}w.length===0&&y.length;let k=e.get(h);if(k){if(w.length>0&&y.length>0)k.clearAttentionFlag(w,y);else{let A=Array.from(k.listAttentionFlags()).map(C=>`${C.source}::${C.reason}`);for(let C of A)k.clearAttentionFlag(C.split("::")[0],C.split("::").slice(1).join("::"))}p.code(204).send();return}if(!await e.hasRecord(h)){p.code(404).send({error:"session not found"});return}let b=e.store,S=await b.read(h);if(!S){p.code(404).send({error:"session not found"});return}let v=S.attentionFlags??[],E;if(w.length>0&&y.length>0){let A=`${w}::${y}`;E=v.filter(C=>`${C.source}::${C.reason}`!==A)}else E=[];if(E.length===v.length&&E.every((A,C)=>A.source===v[C].source&&A.reason===v[C].reason)){p.code(204).send();return}await b.write({...S,attentionFlags:E}),p.code(204).send()})}function yc(s,e,t,n={}){s.get("/v1/agents",async()=>Rt(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 Re(a,[],{npmRegistry:n.npmRegistry}),c=a.distribution.npx?"npx":a.distribution.binary?"binary":"unknown";o.send({agentId:a.id,version:d.version,distribution:c,installed:!0,command:d.command})}catch(d){o.code(500).send({error:d.message})}}),s.post("/v1/agents/:id/sync",async(r,o)=>{let i=r.params.id;try{let{synced:a,skipped:d}=await t.syncFromAgent(i);return{synced:a.map(c=>({sessionId:c.sessionId,upstreamSessionId:c.upstreamSessionId,agentId:c.agentId,cwd:c.cwd,title:c.title,updatedAt:c.updatedAt})),skipped:d}}catch(a){let d=a;if(d.code===x.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}Y();function wc(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:R.home(),driftedKeys:n()}))}var Bm=/^[A-Za-z0-9._-]+$/;function Ds(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=Wm(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){Pn(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){Pn(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){Pn(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){Pn(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){Pn(i,d)}})}function Pn(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 Wm(s){let e=s.name;if(typeof e!="string"||!Bm.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 kc(s,e){Ds(s,"extension",e)}function vc(s,e){Ds(s,"transformer",e)}function bc(s,e){s.get("/v1/config",async()=>e())}import{z as it}from"zod";Y();import*as zt from"fs/promises";import*as Sc from"path";import{randomBytes as iI,scrypt as qm,timingSafeEqual as zm}from"crypto";import{promisify as Jm}from"util";var Vm=Jm(qm);function Ic(){return Sc.join(R.home(),"password-hash")}var Gm=128*1024*1024;async function Ac(){try{return(await zt.readFile(Ic(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function Cc(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await zt.readFile(Ic(),"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 Vm(s,i,a.length,{N:n,r,p:o,maxmem:Gm});return d.length!==a.length?!1:zm(d,a)}var Km=it.object({password:it.string().min(1),label:it.string().min(1).max(256).optional(),ttlSec:it.number().int().positive().optional()}),Qm=it.object({id:it.string().optional()}).optional(),Ym=it.object({token:it.string().min(32)});function Rc(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=Xm(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=Km.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await Ac())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await Cc(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=Qm.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=Ym.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 Xm(s){return s.ip||"unknown"}import{z as at}from"zod";Y();Oe();var Mo=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,js=class s{data;constructor(e){this.data=e}static async load(){let e=await oe(R.peers());return new s(Zm(e))}get(e){return this.data.entries[e]}async set(e){this.data.entries[e.name]=e,await xc(this.data)}async delete(e){return e in this.data.entries?(delete this.data.entries[e],await xc(this.data),!0):!1}list(){return Object.values(this.data.entries).map(({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})=>({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})).sort((e,t)=>e.addedAt.localeCompare(t.addedAt))}};function Zm(s){if(!s||typeof s!="object")return{version:1,entries:{}};let e=s,t=e.entries&&typeof e.entries=="object"?e.entries:{},n={};for(let[r,o]of Object.entries(t)){if(!o||typeof o!="object")continue;let i=o;if(typeof i.name!="string"||typeof i.host!="string"||typeof i.port!="number"||typeof i.token!="string"||typeof i.expiresAt!="string"||typeof i.addedAt!="string")continue;let a={name:i.name,host:i.host,port:i.port,token:i.token,expiresAt:i.expiresAt,addedAt:i.addedAt};typeof i.label=="string"&&(a.label=i.label),typeof i.pinnedFingerprint=="string"&&(a.pinnedFingerprint=i.pinnedFingerprint),typeof i.pinnedAt=="string"&&(a.pinnedAt=i.pinnedAt),n[r]=a}return{version:1,entries:n}}async function xc(s){await ue(R.peers(),s,{mode:384})}var Je=class extends Error{status;constructor(e,t){super(e),this.name="PeerLoginError",this.status=t}};function Ec(s,e){return`${Te(s)?"http":"https"}://${s}:${e}`}async function Tc(s){let e=s.fetchImpl??fetch,t=`${s.host}:${s.port}`,n=Ec(s.host,s.port),r;try{r=await e(`${n}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:s.password,label:s.label,ttlSec:s.ttlSec})})}catch(i){throw new Je(`Could not reach ${t}: ${i.message}`,502)}if(r.status===401)throw new Je(`Wrong password for ${t}.`,401);if(r.status===403)throw new Je(`No password is configured on ${t}. Run \`hydra-acp auth password\` on that daemon first.`,502);if(r.status===429)throw new Je(`Too many failed login attempts on ${t}; try again later.`,429);if(!r.ok)throw new Je(`Login to ${t} failed: HTTP ${r.status}`,502);let o=await r.json();if(!o.session_token||!o.expires_at)throw new Je(`Login to ${t} returned a malformed response.`,502);return{token:o.session_token,expiresAt:o.expires_at}}async function Pc(s){let e=s.fetchImpl??fetch,t=Ec(s.host,s.port);try{await e(`${t}/v1/auth/logout`,{method:"POST",headers:{Authorization:`Bearer ${s.token}`,"Content-Type":"application/json"},body:JSON.stringify({})})}catch{}}_n();var lh=at.object({name:at.string().min(1).max(64).regex(Mo),host:at.string().min(1),port:at.number().int().positive().optional(),password:at.string().min(1),label:at.string().min(1).max(256).optional(),ttlSec:at.number().int().positive().optional(),pinnedFingerprint:at.string().min(1).optional()});function Hc(s,e){s.post("/v1/remotes",async(t,n)=>{let r;try{r=lh.parse(t.body)}catch{return n.code(400).send({error:`Invalid request body (name must match ${Mo} and the rest is a normal login request)`})}let o=r.port??St;r.pinnedFingerprint&&Mn(r.host,o,r.pinnedFingerprint);let i;try{i=await Tc({host:r.host,port:o,password:r.password,label:r.label,ttlSec:r.ttlSec})}catch(c){if(c instanceof Je)return n.code(c.status).send({error:c.message});throw c}let a=new Date().toISOString(),d={name:r.name,host:r.host,port:o,token:i.token,expiresAt:i.expiresAt,addedAt:a,...r.label!==void 0?{label:r.label}:{},...r.pinnedFingerprint!==void 0?{pinnedFingerprint:r.pinnedFingerprint,pinnedAt:a}:{}};return await e.store.set(d),e.health?.markOk(d.name),n.code(201).send({name:d.name,host:d.host,port:d.port,expiresAt:d.expiresAt,label:d.label,addedAt:d.addedAt,pinnedFingerprint:d.pinnedFingerprint,status:e.health?.get(d.name)?.status??"unknown"})}),s.get("/v1/remotes",async(t,n)=>{let r=e.store.list().map(o=>{let i=e.health?.get(o.name);return{...o,status:i?.status??"unknown",...i?.checkedAt?{lastCheckedAt:i.checkedAt}:{}}});return n.code(200).send({remotes:r})}),s.delete("/v1/remotes/:name",async(t,n)=>{let r=t.params.name,o=e.store.get(r);return o?(await Pc({host:o.host,port:o.port,token:o.token}),await e.store.delete(r),e.health?.forget(r),e.store.list().some(a=>a.host===o.host&&a.port===o.port)||$o(o.host,o.port),n.code(204).send()):n.code(404).send({error:"Not found"})})}function Ls(s){let e=[],t=[],n=!1,r=o=>{if(!n){n=!0;for(let i of t)i(o)}};return s.on("message",(o,i)=>{if(i)return;let a=o.toString("utf8");try{let d=JSON.parse(a);for(let c of e)c(d)}catch(d){for(let c of e)c({jsonrpc:"2.0",id:null,error:{code:x.ParseError,message:`Failed to parse WS frame: ${d.message}`}})}}),s.on("close",()=>r()),s.on("error",o=>r(o)),{async send(o){if(n)throw new Error("ws is closed");let i=JSON.stringify(o);await new Promise((a,d)=>{s.send(i,c=>{if(c){d(c);return}a()})})},onMessage(o){e.push(o)},onClose(o){t.push(o)},async close(){n||(await new Promise(o=>{let i=!1,a=()=>{i||(i=!0,clearTimeout(d),o())},d=setTimeout(a,5e3);s.once("close",a);try{s.close()}catch{a()}}),r())}}}_n();import{WebSocket as fh}from"ws";var ph=1e4,jo=class extends Error{url;elapsedMs;constructor(e,t){super(`hydra-acp: websocket connect to ${e} timed out after ${t}ms`),this.name="WsConnectTimeoutError",this.url=e,this.elapsedMs=t}};async function Lc(s,e,t=ph){let n={};try{let r=new URL(s);if(r.protocol==="wss:"){let o=Do(r.hostname);o.rejectUnauthorized!==void 0&&(n.rejectUnauthorized=o.rejectUnauthorized),o.autoSelectFamily!==void 0&&(n.autoSelectFamily=o.autoSelectFamily),o.checkServerIdentity!==void 0&&(n.checkServerIdentity=o.checkServerIdentity)}}catch{}return new Promise((r,o)=>{let i=new fh(s,e,n),a=Date.now(),d=setTimeout(()=>{i.off("open",c),i.off("error",u),i.on("error",()=>{});try{i.terminate()}catch{}o(new jo(s,Date.now()-a))},t),c=()=>{clearTimeout(d),i.off("error",u),r(i)},u=l=>{clearTimeout(d),i.off("open",c),o(l)};i.once("open",c),i.once("error",u)})}var gh=new Set(["session/attach","session/detach","session/prompt","session/cancel"]);function mh(s){return gh.has(s)}function Bc(s,e,t,n){let r=[];return s.onMessage(o=>{if("method"in o&&mh(o.method)){let i=o.params,a=typeof i?.sessionId=="string"?i.sessionId:void 0;if(a&&pt(a)){e.handleLocalMessage(o,a,{connection:t.connection,clientId:n}).then(d=>d?s.send(d):void 0).catch(()=>{});return}}for(let i of r)i(o)}),{send:o=>s.send(o),onMessage:o=>r.push(o),onClose:o=>s.onClose(o),close:()=>s.close()}}var Bs=class{constructor(e,t=yh){this.store=e;this.dial=t}store;dial;attachments=new Map;async handleLocalMessage(e,t,n){let r="id"in e,o=r?e.id:void 0,i=pt(t);if(!i)return r?Us(o,x.SessionNotFound,`not a federated session id: ${t}`):void 0;let a=Uc(n.clientId,t),d={...e.params,sessionId:i.localId};if(e.method==="session/attach"){let u=this.store.get(i.name);if(!u)return r?Us(o,x.SessionNotFound,`No remote named "${i.name}". Run \`hydra remote add\` first.`):void 0;let l=this.attachments.get(a);l&&(this.attachments.delete(a),l.peerConnection.close().catch(()=>{}));let p;try{p=await this.dial(u)}catch(g){return r?Us(o,x.InternalError,`Could not reach remote "${i.name}": ${g.message}`):void 0}let m;try{m=await p.request("session/attach",d)}catch(g){return p.close().catch(()=>{}),r?Ho(o,g):void 0}let h={peerConnection:p,localId:i.localId,target:n};this.wireAttachment(i.name,h),this.attachments.set(a,h);let f=m&&typeof m.sessionId=="string"?{...m,sessionId:t}:m;return r?{jsonrpc:"2.0",id:o,result:f}:void 0}let c=this.attachments.get(a);if(!c)return r?Us(o,x.SessionNotFound,`"${t}" is not attached through this daemon.`):void 0;if(e.method==="session/detach"){let u,l;try{u=await c.peerConnection.request("session/detach",d)}catch(p){l=p}return this.attachments.delete(a),c.peerConnection.close().catch(()=>{}),l?r?Ho(o,l):void 0:r?{jsonrpc:"2.0",id:o,result:u??{}}:void 0}if(r)try{let u=await c.peerConnection.request(e.method,d);return{jsonrpc:"2.0",id:o,result:u}}catch(u){return Ho(o,u)}await c.peerConnection.notify(e.method,d).catch(()=>{})}detachClient(e){for(let[t,n]of[...this.attachments.entries()])n.target.clientId===e&&(this.attachments.delete(t),n.peerConnection.request("session/detach",{sessionId:n.localId}).catch(()=>{}),n.peerConnection.close().catch(()=>{}))}wireAttachment(e,t){let{peerConnection:n,localId:r,target:o}=t,i=Tt({name:e,localId:r}),a=()=>{this.attachments.delete(Uc(o.clientId,i))};n.onNotification("session/update",d=>{let c=d;!c||c.sessionId!==r||o.connection.notify("session/update",{...c,sessionId:i}).catch(()=>{})}),n.onNotification("hydra-acp/session/closed",d=>{let c=d;!c||c.sessionId!==r||(a(),o.connection.notify("hydra-acp/session/closed",{sessionId:i}).catch(()=>{}))}),n.onRequest("hydra-acp/session/request_permission",async d=>{let c=d;if(!c||c.sessionId!==r)throw{code:x.MethodNotFound,message:"unexpected sessionId"};return o.connection.request("hydra-acp/session/request_permission",{...c,sessionId:i})}),n.onClose(()=>{a(),o.connection.notify("hydra-acp/session/closed",{sessionId:i}).catch(()=>{})})}};function Uc(s,e){return`${s} ${e}`}function Us(s,e,t){return{jsonrpc:"2.0",id:s,error:{code:e,message:t}}}function Ho(s,e){let t=e,n=typeof t?.code=="number"?t.code:x.InternalError,r=typeof t?.message=="string"?t.message:String(e??"forward failed");return{jsonrpc:"2.0",id:s,error:{code:n,message:r,...t?.data!==void 0?{data:t.data}:{}}}}var hh=1e4;async function yh(s){let t=`${Te(s.host)?"ws":"wss"}://${s.host}:${s.port}/acp`,n=await Lc(t,["acp.v1",`hydra-acp-token.${s.token}`],hh);return new nt(Ls(n))}var wh=3e4,kh=5e3,Ws=class{constructor(e,t={}){this.store=e;this.opts=t}store;opts;snapshots=new Map;timer;start(){this.timer||(this.checkAll(),this.timer=setInterval(()=>{this.checkAll()},this.opts.intervalMs??wh),this.timer.unref?.())}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}get(e){return this.snapshots.get(e)}markOk(e){this.snapshots.set(e,{status:"ok",checkedAt:new Date().toISOString()})}forget(e){this.snapshots.delete(e)}async checkAll(){let e=this.opts.fetchImpl??fetch;await Promise.allSettled(this.store.list().map(async t=>{let n=this.store.get(t.name);if(!n)return;let o=`${Te(n.host)?"http":"https"}://${n.host}:${n.port}/v1/auth/verify`,i=new AbortController,a=setTimeout(()=>i.abort(),kh);try{let d=await e(o,{headers:{Authorization:`Bearer ${n.token}`},signal:i.signal});this.snapshots.set(t.name,{status:d.ok?"ok":"unauthorized",checkedAt:new Date().toISOString()})}catch(d){this.snapshots.set(t.name,{status:"unreachable",checkedAt:new Date().toISOString(),error:d.message})}finally{clearTimeout(a)}}))}};_n();import{z as Wc}from"zod";var vh=Wc.object({sessionLabel:Wc.string().min(1).max(256)});function qc(s,e){s.post("/v1/process-tokens",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=vh.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}let o=e.processRegistry.mint(r.sessionLabel,"script");return n.code(201).send({token:o})}),s.delete("/v1/process-tokens/:sessionLabel",async(t,n)=>t.authIdentity!=="service"?n.code(403).send({error:"Requires the service token"}):(e.processRegistry.revoke(t.params.sessionLabel),n.code(204).send()))}import{nanoid as Lo}from"nanoid";import{randomBytes as Kc}from"crypto";import*as Qc from"os";import*as Yc from"path";var bh=200;function Sh(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e[ae];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,bh)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function zc(s,e,t){let n=Sh(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 $n=new Map;function Jc(s,e){let t=$n.get(s);t||(t=new Set,$n.set(s,t)),t.add(e);let n=!1;return()=>{if(n)return;n=!0;let r=$n.get(s);r&&(r.delete(e),r.size===0&&$n.delete(s))}}function Vc(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=$n.get(r);if(o){if(o.has(s))return!0;for(let i of o)n.push(i)}}return!1}function O(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function xh(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 Ce(s,e,t){let n=s.get(e);if(!n)throw O(x.SessionNotFound,t??`session ${e} not found`);return n}async function vt(s,e){let t=qt(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=Kc(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=Eo({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 Dh(c,s),Zc(c.sessionId,s),c}function Xc(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=Hd({headers:n.headers,url:n.url});if(!r||!await e.validator.validate(r)){t.close(4401,"Unauthorized");return}let o=e.processRegistry?.resolve(r),i=`hydra_client_${Lo(12)}`,a=Ls(t),d={},c=e.foreignSessions?Bc(a,e.foreignSessions,d,i):a,u=new nt(c);d.connection=u;let l={clientId:i,processIdentity:o,attached:new Map};u.onClose(()=>{for(let h of l.attached.values())e.manager.get(h.sessionId)?.detach(h.clientId);l.attached.clear(),e.foreignSessions?.detachClient(i)});let p=(h,f)=>{if(l.attached.get(h)?.readonly)throw O(x.PermissionDenied,`${f} not permitted on a read-only attachment`)};if(u.onRequest("initialize",async h=>{let f=Ti.parse(h??{});f.clientInfo?.name&&(l.clientInfo={name:f.clientInfo.name,...f.clientInfo.version!==void 0?{version:f.clientInfo.version}:{}});let g=f.clientInfo?.version;return g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g)),Nh()}),o&&e.extensionCommands){let h=e.extensionCommands;u.onRequest("hydra-acp/commands/register",async f=>{let g=f??{},w=Array.isArray(g.commands)?g.commands.map(y=>{if(!y||typeof y!="object")return;let k=y;if(typeof k.verb!="string")return;let b={verb:k.verb};return typeof k.argsHint=="string"&&(b.argsHint=k.argsHint),typeof k.description=="string"&&(b.description=k.description),b}).filter(y=>y!==void 0):[];return h.register(o.name,u,w),{ok:!0,registered:w.length}}),u.onClose(()=>{h.clear(o.name)})}if(o&&e.extensionMcp){let h=e.extensionMcp;u.onRequest("hydra-acp/mcp_tools/register",async g=>{let w=g??{},y=typeof w.instructions=="string"?w.instructions:void 0,k=Array.isArray(w.tools)?w.tools.map(b=>{if(!b||typeof b!="object")return;let S=b;if(typeof S.name!="string"||S.name.length===0||typeof S.description!="string"||S.inputSchema===null||typeof S.inputSchema!="object")return;let v={name:S.name,description:S.description,inputSchema:S.inputSchema};return S.outputSchema!==null&&typeof S.outputSchema=="object"&&(v.outputSchema=S.outputSchema),v}).filter(b=>b!==void 0):[];if(k.length===0)throw new Error("register_mcp_tools requires at least one tool");return h.register(o.name,u,y,k),{ok:!0,registered:k.length}});let f=g=>{let w=g??{};if(typeof w.sessionId!="string"||w.sessionId.length===0)throw O(x.InvalidParams,"sessionId is required");return w.sessionId};if(u.onRequest("hydra-acp/session/extension_state/get",async g=>{let w=f(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw O(x.InvalidParams,"key is required");if(!e.manager)throw O(x.InternalError,"manager not wired");return{value:await e.manager.getExtensionStateKey(w,o.name,y.key)??null}}),u.onRequest("hydra-acp/session/extension_state/list",async g=>{let w=f(g);if(!e.manager)throw O(x.InternalError,"manager not wired");return{state:await e.manager.getExtensionState(w,o.name)}}),u.onRequest("hydra-acp/session/extension_state/set",async g=>{let w=f(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw O(x.InvalidParams,"key is required");if(y.value===void 0)throw O(x.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw O(x.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(w,o.name,y.key,y.value)}catch(k){throw O(x.InvalidParams,k.message)}return{ok:!0}}),u.onRequest("hydra-acp/session/extension_state/delete",async g=>{let w=f(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw O(x.InvalidParams,"key is required");if(!e.manager)throw O(x.InternalError,"manager not wired");return await e.manager.deleteExtensionStateKey(w,o.name,y.key),{ok:!0}}),e.extensionMcpControls){let g=e.extensionMcpControls;u.onRequest("hydra-acp/mcp_tools/refresh_session",async w=>{let y=w??{};if(typeof y.sessionId!="string"||y.sessionId.length===0)throw O(x.InvalidParams,"refresh_session requires sessionId");return await g.notifyToolListChanged(y.sessionId,o.name),{ok:!0}})}u.onClose(()=>{h.clear(o.name)})}if(o?.kind==="transformer"){u.onRequest("hydra-acp/transformer/initialize",async f=>{let g=f??{},w=Array.isArray(g.intercepts)?g.intercepts.filter(y=>typeof y=="string"):[];if(e.transformers&&(e.transformers.registerConnection(o.name,u,w),e.manager?.defaultTransformers.includes(o.name))){let y=e.transformers.resolveChain([o.name])[0];if(y)for(let k of e.manager.liveSessions())k.addTransformer(y)}return{ack:!0}}),u.onClose(()=>{e.transformers?.deregisterConnection(o.name)}),u.onRequest("hydra-acp/message/emit",async f=>{let g=f??{},w=typeof g.sessionId=="string"?g.sessionId:void 0,y=typeof g.method=="string"?g.method:void 0,k=g.envelope,b=g.route;if(!w)throw O(-32602,"emit_message requires sessionId");if(!y&&b!=="client_broadcast")throw O(-32602,"emit_message requires method");let S=Ce(e.manager,w),v=typeof g.respondsTo=="string"?g.respondsTo:void 0;if(v)return S.dischargeClaim(v,k),{ok:!0};if(b==="chain")return{ok:!0,response:await S.emitToChain(o.name,y,k)};if(b==="queue"){if(y!=="session/prompt")throw O(-32602,'route "queue" only supports method "session/prompt"');return{ok:!0,response:await S.emitToQueue(o.name,k)}}if(b==="daemon")return{ok:!0,response:await S.emitToChain(o.name,y,k)};if(b==="client_broadcast"){if(!k||typeof k!="object")throw O(-32602,"client_broadcast requires an envelope object");return S.broadcastClientUpdate(k),{ok:!0}}throw O(-32602,`unsupported route: ${JSON.stringify(b)}`)}),u.onRequest("hydra-acp/session/request_permission",async f=>{let g=f??{},w=typeof g.sessionId=="string"?g.sessionId:void 0;if(!w)throw O(-32602,"hydra-acp/session/request_permission requires sessionId");return Ce(e.manager,w).requestPermissionFromClients(g)}),u.onRequest("hydra-acp/transformer/attach",async f=>_h(f,o.name,e)),u.onRequest("hydra-acp/child_session/spawn",async f=>{let g=f??{},w=typeof g.agentId=="string"?g.agentId:void 0,y=typeof g.cwd=="string"?g.cwd:void 0,k=typeof g.parentSessionId=="string"?g.parentSessionId:void 0,b=g._meta&&typeof g._meta=="object"?g._meta:void 0,S=b&&b["hydra-acp"]&&typeof b["hydra-acp"]=="object"?b["hydra-acp"]:void 0,v=S&&typeof S.title=="string"?S.title:void 0,E=S&&typeof S.model=="string"?S.model:void 0;if(!y&&k){let W=e.manager.get(k);W&&(y=W.cwd)}if(!y)throw O(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let A=await Xt(y),C=w??A.agentId??e.defaultAgent,T=await e.registry?.getAgent(C),M=tn(A.configDefaults,T??{id:C})?.value,H=E??M?.model,J=typeof g.interactive=="boolean"?g.interactive:!1;return{childSessionId:(await e.manager.create({agentId:C,cwd:y,parentSessionId:k,interactive:J,transformChain:[],title:v,model:H,configDefaults:M})).sessionId}}),u.onRequest("hydra-acp/session/fork",async f=>{let g=f??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"fork_session requires sessionId");let w=typeof g.forkAt=="string"?g.forkAt:void 0,y=typeof g.cwd=="string"?g.cwd:void 0,k=typeof g.agentId=="string"?g.agentId:void 0,b=typeof g.mode=="string"&&(g.mode==="verbatim"||g.mode==="synthesis")?g.mode:void 0,S=typeof g.model=="string"&&g.model.length>0?g.model:void 0,v=await e.manager.forkSession(g.sessionId,{...w!==void 0?{forkAt:w}:{},...y!==void 0?{cwd:y}:{},...k!==void 0?{agentId:k}:{},...b!==void 0?{mode:b}:{},...S!==void 0?{model:S}:{}}),E=e.manager.get(v.sessionId);if(!E){let T=await e.manager.loadFromDisk(v.sessionId);if(!T)throw O(x.InternalError,`fork ${v.sessionId} vanished before it could be attached`);E=await vt(e,{...T,onInstallProgress:qs(u)})}Jt(l,E,E.sessionId);let A=dt(u,E,l),{entries:C}=await E.attach(A,"full");l.attached.set(E.sessionId,{sessionId:E.sessionId,clientId:A.clientId,readonly:!1});for(let T of C){if(u.isClosed())break;await u.notify(T.method,Le(He(T.params,T.recordedAt),T.seq)).catch(()=>{})}return{...v,sessionId:E.sessionId}}),u.onRequest("session/fork",async f=>{let g=f??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"session/fork requires sessionId");let w=typeof g.cwd=="string"?g.cwd:void 0,y=await e.manager.forkSession(g.sessionId,{...w!==void 0?{cwd:w}:{},mode:"verbatim"}),k=e.manager.get(y.sessionId);if(!k){let v=await e.manager.loadFromDisk(y.sessionId);if(!v)throw O(x.InternalError,`fork ${y.sessionId} vanished before it could be attached`);k=await vt(e,{...v,onInstallProgress:qs(u)})}Jt(l,k,k.sessionId);let b=dt(u,k,l),{entries:S}=await k.attach(b,"full");l.attached.set(k.sessionId,{sessionId:k.sessionId,clientId:b.clientId,readonly:!1});for(let v of S){if(u.isClosed())break;await u.notify(v.method,Le(He(v.params,v.recordedAt),v.seq)).catch(()=>{})}return{sessionId:k.sessionId}});let h=async(f,g)=>{let w=f??{};if(typeof w.sessionId!="string")throw O(x.InvalidParams,`${g} requires sessionId`);let y=await e.manager.resolveCanonicalId(w.sessionId)??w.sessionId,k=e.manager.get(y);if(k)return await k.close({deleteRecord:!0,by:`session/delete ${l.clientId}`}),await e.manager.waitForDeletion(y),await e.manager.hasRecord(y)&&await e.manager.deleteRecord(y),{id:y,existed:!0};let b=await e.manager.deleteRecord(y);return{id:y,existed:b}};u.onRequest("session/delete",async f=>(await h(f,"session/delete"),{})),u.onRequest("session/close",async f=>{let g=f??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"session/close requires sessionId");p(g.sessionId,"session/close");let w=await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId,y=e.manager.get(w);if(y)return await y.close({deleteRecord:!1,by:`session/close ${l.clientId}`+(l.processIdentity?` (${l.processIdentity.name})`:"")}),{};if(await e.manager.hasRecord(w))return{};throw O(x.SessionNotFound,`session ${w} not found`)}),u.onRequest("hydra-acp/session/delete",async f=>{let{id:g,existed:w}=await h(f,"hydra-acp/session/delete");if(!w)throw O(x.SessionNotFound,`session ${g} not found`);return{deleted:!0,sessionId:g}}),u.onRequest("hydra-acp/child_session/await",async f=>{let g=f??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0,y=g.until==="idle"?"idle":"turn_complete",k=typeof g.timeoutMs=="number"?Math.min(g.timeoutMs,18e5):3e5;if(!w)throw O(-32602,"await_child requires childSessionId");let b=Ce(e.manager,w,`child session ${w} not found`);return new Promise(S=>{let A=[],C=[],T=0,M=!1,H,J,$=!1,W=()=>{$||($=!0,clearTimeout(q),H?.(),J?.(),S(M?{entries:A,truncated:!0}:{entries:A}))};H=b.onBroadcast(te=>{let ie=xh(te);for(A.push(te),C.push(ie),T+=ie;A.length>0&&(A.length>1e3||T>1048576);)A.shift(),T-=C.shift()??0,M=!0;y==="turn_complete"&&te.params?.update?.sessionUpdate==="turn_complete"&&W()});let q=setTimeout(W,k);typeof q.unref=="function"&&q.unref(),J=b.onClose(()=>W())})}),u.onRequest("hydra-acp/child_session/close",async f=>{let g=f??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0;if(!w)throw O(-32602,"close_child_session requires childSessionId");let y=e.manager.get(w);return y&&await y.close({deleteRecord:!1,by:`child_session/close ${l.clientId}`}),{ok:!0}}),u.onRequest("hydra-acp/attention/set",async f=>$h(f,o.name,e)),u.onRequest("hydra-acp/attention/clear",async f=>Fh(f,o.name,e)),u.onRequest("hydra-acp/connection/keep_alive",async f=>{let g=f??{},w=typeof g.token=="string"?g.token:void 0,y=typeof g.sessionId=="string"?g.sessionId:void 0,k=typeof g.estimatedRemainingMs=="number"?g.estimatedRemainingMs:void 0;return w&&y&&e.manager.get(y)?.keepAliveClaim(w,k),{ok:!0}})}u.onRequest("hydra-acp/session/tool_content",async h=>{let f=h??{};if(typeof f.sessionId!="string"||typeof f.hash!="string")throw O(x.InvalidParams,"hydra-acp/session/tool_content requires sessionId and hash");let g=await e.manager.resolveCanonicalId(f.sessionId)??f.sessionId,w=await e.manager.loadToolBlob(g,f.hash);if(w===null)throw O(x.SessionNotFound,"tool content not found");return{content:w}}),u.onRequest("authenticate",async h=>Eh(h,e)),u.onRequest("logout",async h=>Th(h,e)),u.onRequest("session/new",async h=>{let f=Pi.parse(h),g=ut(h?._meta),w=Array.isArray(g.transformers)&&g.transformers.every(X=>typeof X=="string")?g.transformers:e.manager.defaultTransformers??[],y=e.transformers?.resolveChain(w)??[],k=await Xt(f.cwd),b=g.agentId??k.agentId??e.defaultAgent,S=await e.registry?.getAgent(b),v=tn(k.configDefaults,S??{id:b})?.value,E,A,C=f.mcpServers;if(g.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){E=Kc(32).toString("hex"),A=e.mcpTokenRegistry.reserve(E);let ke={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${E}`}]};C=[...f.mcpServers??[],ke]}let T,M,H=qt(e);H!==void 0&&(C=[...C??[],...H.descriptors]);let J=Eo({baselineMcpServers:f.mcpServers,stdinEnabled:g.mcpStdin===!0,deps:e}),$;try{$=await e.manager.create({cwd:f.cwd,agentId:b,mcpServers:C,title:g.title,agentArgs:g.agentArgs,model:g.model??v?.model,configDefaults:v,onInstallProgress:qs(u),transformChain:y,originatingClient:l.clientInfo,...g.interactive!==void 0?{interactive:g.interactive}:{},...g.env!==void 0?{forwardedEnv:g.env}:{},...g.workspace!==void 0?{workspace:g.workspace}:{},...J?{mintMcpServersForSwap:J}:{}})}catch(X){throw A!==void 0&&A.abandon(X instanceof Error?X:void 0),M!==void 0&&M.abandon(X instanceof Error?X:void 0),H!==void 0&&H.abandon(X instanceof Error?X:void 0),X}if(E!==void 0&&A!==void 0&&e.mcpTokenRegistry!==void 0){let X=E,ke=e.mcpTokenRegistry;A.complete($),$.onClose(()=>{ke.unbind(X)})}if(T!==void 0&&M!==void 0&&e.mcpTokenRegistry!==void 0){let X=T,ke=e.mcpTokenRegistry;M.complete($),$.onClose(()=>{ke.unbind(X)})}H!==void 0&&H.bindToSession($),Zc($.sessionId,e);let W,q;try{Jt(l,$,$.sessionId),W=dt(u,$,l),{entries:q}=await $.attach(W,"full")}catch(X){throw await $.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),X}l.attached.set($.sessionId,{sessionId:$.sessionId,clientId:W.clientId,readonly:!1}),setImmediate(()=>{(async()=>{for(let X of q){if(u.isClosed())break;await u.notify(X.method,Le(He(X.params,X.recordedAt),X.seq)).catch(()=>{})}})()});let te=zs($),ie=Js($);return{sessionId:$.sessionId,...te?{modes:te}:{},...ie?{models:ie}:{},configOptions:$.buildConfigOptions(),_meta:Vs(e.manager,$,{clientId:W.clientId})}}),u.onRequest("session/attach",async h=>{let f=_i.parse(h),g=f.clientInfo?.version;g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g));let w=ut(f._meta),y=w.resume,k=w.readonly===!0,b=w.env;s.log.info(`session/attach sessionId=${f.sessionId} hasResumeHints=${!!y} readonly=${k}`);let S=y?f.sessionId:await e.manager.resolveCanonicalId(f.sessionId)??f.sessionId,v=e.manager.get(S);if(!v&&k){let $=await e.manager.loadFromDisk(S);if(!$)throw O(x.SessionNotFound,`session ${f.sessionId} not found`);let W=await e.manager.loadHistory(S),q=f.clientId??`cli_${Lo(8)}`;l.attached.set($.hydraSessionId,{sessionId:$.hydraSessionId,clientId:q,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${$.hydraSessionId} clientId=${q} attachedCount=${l.attached.size} replayed=${W.length}`);for(let te of W)await u.notify(te.method,Le(He(te.params,te.recordedAt),te.seq)).catch(()=>{});return{sessionId:$.hydraSessionId,clientId:q,connectedClients:[q],historyPolicy:"full",replayed:W.length,_meta:Oh($)}}let E=!v;if(!v){let $=await e.manager.loadFromDisk(S),W=await Ph(S,y,$?.upstreamSessionId,e.manager);W.kind==="ignore"&&s.log.warn(W.logMessage);let q=$;if(y&&W.kind==="honor"&&(q={...$,hydraSessionId:f.sessionId,upstreamSessionId:y.upstreamSessionId,agentId:y.agentId,cwd:$?.workspace?.path??y.cwd,...y.title!==void 0?{title:y.title}:{},...y.agentArgs!==void 0?{agentArgs:y.agentArgs}:{}}),!q)throw O(x.SessionNotFound,`session ${f.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(q.agentId,q.upstreamSessionId))throw O(x.SessionNotFound,`session ${f.sessionId} was deleted`);let te=q.originatingClient?q:{...q,originatingClient:l.clientInfo},ie=b!==void 0?{...te,forwardedEnv:b}:te;v=await vt(e,{...ie,onInstallProgress:qs(u)})}Jt(l,v,v.sessionId);let A=dt(u,v,l,f.clientInfo,f.clientId),C=w.replayMode==="drip",{entries:T,appliedPolicy:M}=await v.attach(A,f.historyPolicy,{afterMessageId:f.afterMessageId,afterSeq:f.afterSeq,raw:C,...w.historyLimit!==void 0?{historyLimit:w.historyLimit}:{},...w.toolContent!==void 0?{toolContent:w.toolContent}:{}});if(l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:A.clientId,readonly:k}),b!==void 0&&await e.manager.setForwardedEnv(v.sessionId,b).catch(()=>{}),s.log.info(`session/attach OK sessionId=${v.sessionId} clientId=${A.clientId} attachedCount=${l.attached.size} requestedPolicy=${f.historyPolicy} appliedPolicy=${M} replayed=${T.length} readonly=${k}${C?" replayMode=drip":""}`),C){let $=w.dripSpeed&&w.dripSpeed>0?w.dripSpeed:1,W=750;(async()=>{let q=null;for(let te of T){let ie=typeof te.recordedAt=="number"?te.recordedAt:null;if(q!==null&&ie!==null){let X=Math.min(W,Math.max(0,(ie-q)/$));X>0&&await new Promise(ke=>setTimeout(ke,X))}ie!==null&&(q=ie);try{await u.notify(te.method,Le(He(te.params,ie??void 0),te.seq))}catch{return}}})()}else for(let $=0;$<T.length&&!u.isClosed();$++){let W=T[$],q=u.notify(W.method,Le(He(W.params,W.recordedAt),W.seq)).catch(()=>{});($+1)%200===0&&await q}v.replayPendingPermissions(A);let H=zs(v),J=Js(v);return{sessionId:v.sessionId,clientId:A.clientId,connectedClients:v.connectedClients(A.clientId),historyPolicy:M,replayed:T.length,...H?{modes:H}:{},...J?{models:J}:{},configOptions:v.buildConfigOptions(),_meta:Vs(e.manager,v,{resurrected:E})}}),u.onRequest("session/detach",async h=>{let f=$i.parse(h),g=l.attached.get(f.sessionId);if(!g)throw O(x.SessionNotFound,"client not attached to that session");let w=e.manager.get(f.sessionId);return w?.detach(g.clientId),l.attached.delete(f.sessionId),w&&e.manager.reapIfOrphanedNonInteractive(f.sessionId),{sessionId:f.sessionId,_meta:{[ae]:{detachStatus:"detached"}}}}),u.onRequest("session/list",async h=>{let f=Fi.parse(h??{});return{sessions:(await e.manager.list({cwd:f.cwd})).filter(k=>k.originatingClient?.name!==us).map(Oi)}}),u.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw O(x.InternalError,"agent registry unavailable");return Rt(e.registry)}),u.onRequest("hydra-acp/agents/auth_methods",async h=>{let f=h??{};if(typeof f.agentId!="string"||f.agentId.length===0)throw O(x.InvalidParams,"hydra-acp/agents/auth_methods requires a non-empty agentId string");return{authMethods:(await e.manager.bootstrapAgentForAuth(f.agentId)).authMethods??[]}}),u.onRequest("session/prompt",async h=>{let f=Ni.parse(h);p(f.sessionId,"session/prompt");let g=await zc(f,e.manager,b=>{s.log.warn(`session/prompt: dropping unknown sentBy.sessionId=${b} sessionId=${f.sessionId}`)});if(g?.fromSession!==void 0){if((g.depth??0)>3)throw s.log.warn(`session/prompt: refusing depth ${g.depth} chain from ${g.fromSession} to ${f.sessionId}`),O(x.InvalidRequest,`message chain too deep (${g.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(g.awaiting===!0&&Vc(g.fromSession,f.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${g.fromSession} -> ${f.sessionId}`),O(x.InvalidRequest,`would deadlock: ${f.sessionId} is already blocked waiting on ${g.fromSession}. Send with --no-wait, or let the other turn finish first.`)}let w=l.attached.get(f.sessionId);if(!w)throw s.log.warn(`session/prompt rejected: not attached sessionId=${f.sessionId} attachedKeys=[${[...l.attached.keys()].join(",")}]`),O(x.SessionNotFound,"not attached to session");let y=e.manager.get(f.sessionId);if(!y){let b=await e.manager.loadFromDisk(f.sessionId);if(!b)throw O(x.SessionNotFound,`session ${f.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${f.sessionId}`),y=await vt(e,b);let S=dt(u,y,l,void 0,w.clientId);await y.attach(S,"none")}let k=g?.awaiting===!0&&g.fromSession!==void 0?Jc(g.fromSession,f.sessionId):void 0;try{return await y.prompt(w.clientId,f,g)}finally{k?.()}});let m=h=>{let f;try{f=Wn.parse(h)}catch(y){s.log.warn(`session/cancel: invalid params: ${y.message}`);return}let g=l.attached.get(f.sessionId);if(!g)return;if(g.readonly){s.log.warn(`session/cancel dropped (readonly attachment) sessionId=${f.sessionId}`);return}let w=e.manager.get(f.sessionId);w&&w.cancel(g.clientId).catch(y=>{s.log.warn(`session/cancel for ${f.sessionId}: ${y.message}`)})};u.onNotification("session/cancel",m),u.onRequest("session/cancel",async h=>{let f=Wn.parse(h);return p(f.sessionId,"session/cancel"),m(h),null}),u.onRequest("hydra-acp/prompt/cancel",async h=>{let f=ji.parse(h);return p(f.sessionId,"hydra-acp/prompt/cancel"),Ce(e.manager,f.sessionId).cancelQueuedPrompt(f.messageId)}),u.onRequest("hydra-acp/session/force_cancel",async h=>{let f=Wn.parse(h);return p(f.sessionId,"hydra-acp/session/force_cancel"),Ce(e.manager,f.sessionId).forceCancel()}),u.onRequest("hydra-acp/prompt/update",async h=>{let f=Hi.parse(h);return p(f.sessionId,"hydra-acp/prompt/update"),Ce(e.manager,f.sessionId).updateQueuedPrompt(f.messageId,f.prompt)}),u.onRequest("hydra-acp/prompt/amend",async h=>{let f=Li.parse(h);p(f.sessionId,"hydra-acp/prompt/amend");let g=l.attached.get(f.sessionId);if(!g)throw O(x.SessionNotFound,"not attached to session");return Ce(e.manager,f.sessionId).amendPrompt(g.clientId,f)}),u.onRequest("_session/steering",async h=>{let f=Ui.parse(h);p(f.sessionId,"_session/steering");let g=l.attached.get(f.sessionId);if(!g)throw O(x.SessionNotFound,"not attached to session");let w=e.manager.get(f.sessionId);if(!w){let y=await e.manager.loadFromDisk(f.sessionId);if(!y)throw O(x.SessionNotFound,`session ${f.sessionId} not found`);w=await vt(e,y);let k=dt(u,w,l,void 0,g.clientId);await w.attach(k,"none")}return w.steer(g.clientId,f)}),u.onRequest("session/resume",async h=>{let f=h??{},g=typeof f.sessionId=="string"?f.sessionId:void 0;if(!g)throw O(x.InvalidParams,"session/resume requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let v=await e.manager.loadFromDisk(w);if(!v)throw O(x.SessionNotFound,`session ${g} not found in memory or on disk`);y=await vt(e,v)}Jt(l,y,y.sessionId);let k=dt(u,y,l);await y.attach(k,"pending_only"),l.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:k.clientId,readonly:!1}),y.replayPendingPermissions(k);let b=zs(y),S=Js(y);return{sessionId:y.sessionId,...b?{modes:b}:{},...S?{models:S}:{},configOptions:y.buildConfigOptions(),_meta:Vs(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/load",async h=>{let f=h??{},g=typeof f.sessionId=="string"?f.sessionId:void 0;if(!g)throw O(x.InvalidParams,"session/load requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let E=await e.manager.loadFromDisk(w);if(!E)throw O(x.SessionNotFound,`session ${g} not found in memory or on disk`);y=await vt(e,E)}Jt(l,y,y.sessionId);let k=dt(u,y,l),{entries:b}=await y.attach(k,"full");l.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:k.clientId,readonly:!1});for(let E of b){if(u.isClosed())break;await u.notify(E.method,Le(He(E.params,E.recordedAt),E.seq)).catch(()=>{})}y.replayPendingPermissions(k);let S=zs(y),v=Js(y);return{sessionId:y.sessionId,...S?{modes:S}:{},...v?{models:v}:{},configOptions:y.buildConfigOptions(),_meta:Vs(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/set_model",async h=>{let f=h?.sessionId;typeof f=="string"&&p(f,"session/set_model");let g=Mh(h,e.manager);if(g.kind==="error")throw s.log.warn(g.logMessage),O(g.code,g.message);if(g.kind==="no_op")return s.log.warn(g.logMessage),await u.notify("session/update",{sessionId:g.sessionId,update:{sessionUpdate:"_hydra_current_model_update",currentModel:g.currentModel}}).catch(()=>{}),null;s.log.info(g.logMessage);let{modelId:w}=g,y=await g.session.forwardModelChange(w,h);return g.session.applyAgentConfigOptionResponse(y,"model"),g.session.applyModelChange(w),y}),u.onRequest("session/set_mode",async h=>{let f=h,g=f?.sessionId;if(typeof g=="string"&&p(g,"session/set_mode"),!f||typeof f.sessionId!="string")throw O(x.InvalidParams,"session/set_mode requires string sessionId");if(typeof f.modeId!="string")throw O(x.InvalidParams,"session/set_mode requires string modeId");let w=Ce(e.manager,f.sessionId),y=await w.forwardRequest("session/set_mode",h);return w.applyModeChange(f.modeId),y}),u.onRequest("session/set_config_option",async h=>{let f=h,g=b=>O(x.InvalidParams,b),w=f?.sessionId;if(typeof w=="string"&&p(w,"session/set_config_option"),!f||typeof f.sessionId!="string")throw g("session/set_config_option requires string sessionId");if(typeof f.configId!="string")throw g("session/set_config_option requires string configId");if(typeof f.value!="string")throw g("session/set_config_option requires string value");let y=Ce(e.manager,f.sessionId),k=y.buildConfigOptions().find(b=>b.id===f.configId);if(!k)throw g(`unknown configId ${JSON.stringify(f.configId)} for this session`);if(!k.options.some(b=>b.value===f.value))throw g(`value ${JSON.stringify(f.value)} is not valid for configId ${JSON.stringify(f.configId)}`);switch(f.configId){case"model":{if(f.value!==y.currentModel){let b=await y.forwardModelChange(f.value);y.applyAgentConfigOptionResponse(b,"model")}y.applyModelChange(f.value);break}case"mode":{f.value!==y.currentMode&&await y.forwardRequest("session/set_mode",{sessionId:f.sessionId,modeId:f.value}),y.applyModeChange(f.value);break}case"agent":{f.value!==y.agentId&&await y.setAgent(f.value);break}default:{let b=await y.forwardRequest("session/set_config_option",{sessionId:f.sessionId,configId:f.configId,value:f.value});y.applyAgentConfigOptionResponse(b,f.configId)&&y.broadcastConfigOptions()}}return{configOptions:y.buildConfigOptions()}}),u.setDefaultHandler(async(h,f)=>{let g=new Set(["hydra-acp/attention/set","hydra-acp/attention/clear"]),w=f.startsWith("session/"),y=f.startsWith("hydra-acp/");if(!w&&!y||h===null||typeof h!="object"||g.has(f))throw O(x.MethodNotFound,`Method not found: ${f}`);let k=h.sessionId;if(typeof k!="string")throw O(x.MethodNotFound,`Method not found: ${f}`);return p(k,f),Ce(e.manager,k).forwardRequest(f,h)})})}async function Eh(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw O(x.InvalidParams,"authenticate requires a non-empty methodId string");let n=t.methodId,r=t._meta?.["hydra-acp"],o=typeof r?.sessionId=="string"?r.sessionId:void 0,i=typeof r?.agentId=="string"?r.agentId:void 0,a=o!==void 0?e.manager.getAgentForSession(o):void 0;if(!a||!a.isAlive()){let m=i??e.defaultAgent;a=await e.manager.bootstrapAgentForAuth(m)}let d=a.authMethods??[],c=d.find(m=>m.id===n);if(!c){let m=d.map(h=>h.id);throw O(x.InvalidParams,`authenticate: methodId ${JSON.stringify(n)} is not advertised by agent ${a.agentId}; valid: [${m.map(h=>JSON.stringify(h)).join(", ")}]`)}let u=c._meta?.type,l=(()=>{let m=c._meta?.["terminal-auth"];if(m&&typeof m=="object"&&!Array.isArray(m))return m})();if((c.type??(u==="agent"||u==="terminal"?u:l!==void 0?"terminal":"agent"))==="terminal"){let m=(k,b)=>{if(!Array.isArray(k))throw O(x.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be a string[]; got ${k===null?"null":typeof k}`);for(let S of k)if(typeof S!="string")throw O(x.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be string[]; got non-string entry ${JSON.stringify(S)}`);return k},h=await e.manager.planSpawnForAgent(a.agentId),f,g;if(l?.args!==void 0){let k=typeof l.command=="string"?l.command:void 0;f=k!==void 0&&Yc.isAbsolute(k)?k:h.command,g=m(l.args,'_meta["terminal-auth"].args')}else{let k=c.args!==void 0?{raw:c.args,label:"args"}:c._meta?.args!==void 0?{raw:c._meta.args,label:"_meta.args"}:void 0,b=k!==void 0?m(k.raw,k.label):[];f=h.command,g=[...h.args,...b]}let w={};for(let[k,b]of Object.entries(process.env))typeof b=="string"&&(w[k]=b);Object.assign(w,h.env);let y=Qc.homedir();return console.error(`[authenticate] terminal-auth requested agentId=${a.agentId} methodId=${n}`),{kind:"terminal",command:f,args:g,env:w,cwd:y}}try{return await a.connection.request("authenticate",{methodId:n})}catch(m){throw ot(m,a)}}async function Th(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 qs(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(Bi,t).catch(()=>{})}}function zs(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 Js(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 Ph(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 Mh(s,e){if(!s||typeof s!="object")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires params",logMessage:"session/set_model rejected: params not an object"};let t=s;if(typeof t.sessionId!="string")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires string sessionId",logMessage:"session/set_model rejected: missing/non-string sessionId"};if(typeof t.modelId!="string")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires string modelId",logMessage:`session/set_model rejected: missing/non-string modelId sessionId=${t.sessionId}`};let n=e.get(t.sessionId);if(!n)return{kind:"error",code:x.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=_t(t.modelId,r);if(o.kind==="none")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model passthrough (no availableModels) sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="exact")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model accepted sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="resolved")return{kind:"ok",session:n,modelId:o.modelId,logMessage:`session/set_model resolved sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} \u2192 ${JSON.stringify(o.modelId)}`};let i=r.map(d=>d.modelId).join(", "),a=o.kind==="ambiguous"?`ambiguous (trailing-segment matches [${o.candidates.join(", ")}])`:"not in availableModels";return n.currentModel!==void 0&&n.currentModel.length>0?{kind:"no_op",session:n,sessionId:t.sessionId,currentModel:n.currentModel,logMessage:`session/set_model no_op (resyncing client) sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} ${a} actual=${JSON.stringify(n.currentModel)} agentId=${n.agentId} known=[${i}]`}:{kind:"error",code:x.InvalidParams,message:`model "${t.modelId}" is ${a==="not in availableModels"?"not in this session's availableModels":a} (agent ${n.agentId}); known models: ${i}`,logMessage:`session/set_model rejected sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)} ${a} agentId=${n.agentId} known=[${i}] (no current model to fall back to)`}}async function _h(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw O(x.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw O(x.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw O(x.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return Ce(t.manager,r).addTransformer(o),{ok:!0}}async function $h(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(x.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw O(x.InvalidParams,"hydra-acp/attention/set requires string reason");return Ce(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function Fh(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(x.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw O(x.InvalidParams,"hydra-acp/attention/clear requires string reason");return Ce(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function Oh(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:wn(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{[ae]:Bn(e,t)}}function Vs(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 nn(e.agentMeta,Bn(n,r))}function Nh(){return{protocolVersion:1,agentInfo:{name:"hydra",version:me},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:{...nn(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 Dh(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 Zc(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 dt(s,e,t,n,r){return{clientId:r??`cli_${Lo(8)}`,connection:s,clientInfo:n}}function Jt(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var Gs=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 jh}from"crypto";import{McpServer as Hh}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Lh}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as he}from"zod";function Uo(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 Se(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var eu="Bearer ";function Vt(s){let e=s.headers.authorization;if(typeof e!="string"||!e.startsWith(eu))return;let t=e.slice(eu.length).trim();return t.length>0?t:void 0}function Uh(s){let e=new Hh({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:he.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return Se(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:he.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return Se(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:he.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:he.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:he.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 Se(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:he.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:he.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 Se({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:he.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:he.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:he.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:he.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:he.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:he.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:he.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:he.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:he.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 Se(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 Se(t)}),e}var Bh=1e4;function tu(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=Uh(a),u=new Lh({sessionIdGenerator:()=>jh()});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=Vt(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,m=new Promise(f=>{p=setTimeout(()=>f(void 0),Bh)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(p!==void 0&&clearTimeout(p),h===void 0){a.code(503).send({error:"session not ready"});return}u=h}let l=await n(d,u);a.hijack(),await l.handleRequest(i.raw,a.raw,i.body)}let o={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.get("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.delete("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)})}import{randomUUID as Wh}from"crypto";import{McpServer as qh}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as zh}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as Ve}from"zod";function Jh(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var nu=2e3,su=2e4;function Vh(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return $t([s]);let n=[],r=on(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=Vn(t);return i!==void 0&&n.push(i),n.join(`
194
+ `)}function Gh(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 Kh(s){let e=new qh({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:Ve.string().min(1).describe("Case-insensitive substring to search for."),limit:Ve.number().int().min(1).max(50).optional().describe("Maximum number of matches to return (default 10, max 50)."),include_tool_calls:Ve.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 Se({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=Uo(u);if(!l)continue;let{kind:p,update:m}=l;if((p==="tool_call"||p==="tool_call_update")&&!r)continue;let h=Vh(u,p,m),f=h.toLowerCase().indexOf(a);if(f<0)continue;let g=Jh(p),w=Gh(h,f),y=typeof u.recordedAt=="number"?String(u.recordedAt):void 0;if(i.push({entryId:c,speaker:g,snippet:w,timestamp:y}),i.length>=n)break}i.sort((c,u)=>c.entryId-u.entryId);let d=i.length>=n;return Se({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:Ve.number().int().min(0).describe("Zero-based index of the first entry to include (inclusive)."),to_entry:Ve.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 Se({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 Se({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=$t(u,{toolOutput:{maxPerCall:nu,maxTotal:su}});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:Ve.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:Ve.string().optional().describe("ACP tool kind: execute (shell), read, edit, think, other. Agent-independent, unlike tool_name."),file_path:Ve.string().optional(),limit:Ve.number().int().min(1).max(100).optional(),include_output:Ve.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 Se({calls:[],truncated:!1,note:"This session has no compacted history. `tool_calls` retrieves tool invocations from the pre-compaction transcript; nothing has been compacted yet."});let d=typeof t=="string"&&t.length>0,c=typeof n=="string"&&n.length>0,u=typeof r=="string"&&r.length>0;if(!d&&!c&&!u)throw new Error("tool_calls: at least one of tool_name, kind, or file_path must be provided");let l=new Map,p=Math.max(o*4,200);for await(let{entryId:y,entry:k}of a.iterRecallNewestFirst()){let b=Uo(k);if(!b)continue;let{kind:S,update:v}=b;if(S!=="tool_call"&&S!=="tool_call_update")continue;let E=typeof v.toolCallId=="string"&&v.toolCallId.length>0?v.toolCallId:`__noid_${y}`,A=l.get(E);if(A||(A={entryId:y,toolName:"(unnamed)",nameAuthoritative:!1,rawInput:{},locations:[],status:"in_progress"},l.set(E,A)),y<A.entryId&&(A.entryId=y),!A.nameAuthoritative){let T=on(v);T!==void 0?(A.toolName=T,A.nameAuthoritative=!0):typeof v.name=="string"&&v.name.length>0?(A.toolName=v.name,A.nameAuthoritative=!0):S==="tool_call"&&typeof v.title=="string"&&v.title.length>0&&(A.toolName=v.title,A.nameAuthoritative=!0)}if(A.kind===void 0&&typeof v.kind=="string"&&v.kind.length>0&&(A.kind=v.kind),A.output===void 0){let T=Vn(v);T!==void 0&&(A.output=T)}let C=v.rawInput;if(C&&typeof C=="object"&&!Array.isArray(C)&&Object.keys(C).length>0)for(let[T,M]of Object.entries(C))A.rawInput[T]===void 0&&(A.rawInput[T]=M);if(Array.isArray(v.locations))for(let T of v.locations){let M=T?.path;typeof M=="string"&&M.length>0&&!A.locations.includes(M)&&A.locations.push(M)}if(typeof v.status=="string"&&A.status==="in_progress"&&(A.status=v.status),k.recordedAt!==void 0&&A.timestamp===void 0&&(A.timestamp=String(k.recordedAt)),l.size>=p)break}let m=[...l.keys()].sort((y,k)=>l.get(y).entryId-l.get(k).entryId),h=[],f=su,g=!1;for(let y of m){let k=l.get(y);if(k.toolName=Tr({name:k.toolName,rawInput:k.rawInput,...k.kind!==void 0?{kind:k.kind}:{}}),d&&!k.toolName.toLowerCase().includes(t.toLowerCase())||c&&(k.kind??"").toLowerCase()!==n.toLowerCase())continue;if(u){let v=r.toLowerCase(),E=["file_path","filePath","path"],A=!1;for(let C of E){let T=k.rawInput[C];if(typeof T=="string"&&T.toLowerCase().includes(v)){A=!0;break}}if(!A){for(let C of k.locations)if(C.toLowerCase().includes(v)){A=!0;break}}if(!A)continue}let b={};for(let[v,E]of Object.entries(k.rawInput))typeof E=="string"?b[v]=E.length>500?E.slice(0,497)+"\u2026":E:(typeof E=="number"||typeof E=="boolean")&&(b[v]=E);k.locations.length>0&&b.locations===void 0&&(b.locations=k.locations);let S={entryId:k.entryId,tool:k.toolName,args:b,status:k.status,timestamp:k.timestamp};if(k.kind!==void 0&&(S.kind=k.kind),i&&k.output!==void 0){let v=k.output,E=Math.min(nu,f);if(E<=0)g=!0;else{let A=v.length<=E?v:v.slice(0,E-1)+"\u2026";S.output=A,S.outputBytes=v.length,S.outputTruncated=A.length<v.length,f-=A.length}}if(h.push(S),h.length>=o)break}let w=h.length>=o;return Se({calls:h,truncated:w,...g?{outputBudgetExhausted:g}:{}})}),e}var Qh=1e4;function ru(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=Kh(a),u=new zh({sessionIdGenerator:()=>Wh()});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=Vt(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,m=new Promise(f=>{p=setTimeout(()=>f(void 0),Qh)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(p!==void 0&&clearTimeout(p),h===void 0)throw new Error("recall: session not ready");return h});a.hijack(),await l.handleRequest(i.raw,a.raw,i.body)}let o={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)}),s.get("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)}),s.delete("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)})}var Ks=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 ry}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{randomUUID as oy}from"crypto";import{Server as Yh}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Xh,ListToolsRequestSchema as Zh}from"@modelcontextprotocol/sdk/types.js";function ou(s,e,t,n){let r=typeof t=="function"?async()=>t():async()=>t,o=new Yh({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(Zh,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(Xh,async(a,d)=>{let c=a.params.name,u=d._meta?.progressToken??d.requestId,l=ty(u,d.sendNotification);try{let p=await r(),m=await ny(e.connection,s,c,a.params.arguments??{},p);return sy(m,c)}catch(p){return Bo(p instanceof Error?p.message:String(p))}finally{l()}}),o}var ey=15e3;function ty(s,e,t=ey){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 ny(s,e,t,n,r){return await s.request("hydra-acp/mcp_tools/invoke",{server:e,tool:t,args:n,sessionId:r})}function sy(s,e){if(s===null||typeof s!="object")return Bo(`extension ${e} returned non-object`);let t=s;return Array.isArray(t.content)?t:Bo(`extension ${e} omitted content array`)}function Bo(s){return{content:[{type:"text",text:s}],isError:!0}}var iy=1e4;function iu(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,m]of n){if(e.lookup(p)?.session?.sessionId!==u)continue;let f=m.get(l);if(f!==void 0)try{await f.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 S of b.values())await r(S)}}));let m=p.get(l);if(m!==void 0)return m.transport;let h=t.lookup(l);if(h===void 0)return;let y=ou(l,h,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 S,v=new Promise(A=>{S=setTimeout(()=>A(void 0),iy)}),E=await Promise.race([b.sessionReady.catch(()=>{}),v]);if(S!==void 0&&clearTimeout(S),E===void 0)throw new Error("session not ready");return E.sessionId},{peekSessionId:()=>e.lookup(u)?.session?.sessionId,fetchSessionTools:async b=>{let S=await h.connection.request("hydra-acp/mcp_tools/list_tools",{sessionId:b});if(!S||typeof S!="object")return;let v=S.tools;if(!Array.isArray(v))return;let E=[];for(let A of v){if(!A||typeof A!="object")continue;let C=A;if(typeof C.name!="string"||C.name.length===0||typeof C.description!="string"||C.inputSchema===null||typeof C.inputSchema!="object")continue;let T={name:C.name,description:C.description,inputSchema:C.inputSchema};C.outputSchema!==null&&typeof C.outputSchema=="object"&&(T.outputSchema=C.outputSchema),E.push(T)}return E}}),k=new ry({sessionIdGenerator:()=>oy()});return await y.connect(k),p.set(l,{server:y,transport:k}),k}async function d(u,l){let p=Vt(u);if(p===void 0){l.code(401).send({error:"missing bearer token"});return}if(e.lookup(p)===void 0){l.code(404).send({error:"unknown mcp token"});return}let h=u.params.name,f=await a(p,h);if(f===void 0){l.code(404).send({error:`unknown mcp server: ${h}`});return}l.hijack(),await f.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 fu(s,e){py(s),dr(s.daemon.scrubEnv);let t=s,n=s.daemon.tls?await Ge.readFile(le(s.daemon.tls.key)):void 0,r=s.daemon.tls?await Ge.readFile(le(s.daemon.tls.cert)):void 0;await Ge.mkdir(R.home(),{recursive:!0});let{stream:o,fileStream:i}=await ly(s.daemon.logLevel),a=ay({logger:{level:s.daemon.logLevel,stream:o},bodyLimit:256*1024*1024});await a.register(dy,{options:{handleProtocols:oi}}),gr(N=>{a.log.info(N)}),yr(N=>{a.log.info(N)});let d=await As.load(),c=await js.load();No(),Fo(c);let u=new Bs(c),l=new Ws(c);l.start();let p=new Fs(c);p.start();let m=new Ts,h=new Es,f=new Cs(e),g=new xs([f,new Rs(d),h]),w=jd({validator:g});a.addHook("onRequest",async(N,ve)=>{N.routeOptions.config?.skipAuth||N.url==="/acp"||N.url?.startsWith("/acp?")||(await w(N,ve),!ve.sent&&N.authIdentity?.startsWith("script:")&&!Ld(N.method,N.routeOptions.url)&&ve.code(403).send({error:"script tokens may only access read-only session data"}))});let y=setInterval(()=>{d.sweepExpired()},300*1e3);y.unref();let k=setInterval(()=>{m.sweepExpired()},300*1e3);k.unref();let b=new Ln(s,{onFetched:()=>{Ad(b,A)},onStaleFallback:(N,ve)=>{let Kt=Math.round(ve/36e5),Qt=Kt>=48?`${Math.round(Kt/24)}d`:`${Kt}h`;a.log.warn(`registry fetch failed (${N.message}); serving stale cache last synced ${Qt} ago; agent versions may be outdated ('hydra registry refresh' to retry)`)}});bo(N=>a.log.info(N));let S={info:N=>a.log.info(N),warn:N=>a.log.warn(N)},v=N=>st.spawn({...N,stderrTailBytes:s.daemon.agentStderrTailBytes,logger:S});li(s.compressToolContent);let E=new Ss,A=new ms(b,v,void 0,{idleTimeoutMs:s.daemon.sessionIdleTimeoutSeconds*1e3,orphanTimeoutMs:s.daemon.nonInteractiveOrphanTimeoutSeconds*1e3,sessionDefaults:s.sessionDefaults,synopsisAgent:s.synopsisAgent,synopsisModel:s.synopsisModel,compactionAgent:s.compaction?.agent,compactionModel:s.compaction?.model,defaultTransformers:s.defaultTransformers,sessionHistoryMaxEntries:s.daemon.sessionHistoryMaxEntries,sessionHistoryArchiveMaxBytes:s.daemon.sessionHistoryArchiveMaxBytes,sessionHistoryArchiveTiers:s.daemon.sessionHistoryArchiveTiers,logger:S,npmRegistry:s.npmRegistry,extensionCommands:E,defaultCwd:s.defaultCwd,disableWorkspaceSnapshots:s.disableWorkspaceSnapshots}),C=new vs(ni(s),void 0,{tokenRegistry:h}),T=new bs(si(s),void 0,{tokenRegistry:h}),M=[];wc(a,me,xd(s),()=>M);let H=new Gs,J=new Ks,$,W=()=>{if($!==void 0)return $;let N=a.server.address();return $=`http://127.0.0.1:${N&&typeof N=="object"?N.port:s.daemon.port}`,$},q={agentId:s.defaultAgent,cwd:s.defaultCwd,publicHost:s.daemon.publicHost,host:s.daemon.host,port:s.daemon.port,compaction:s.compaction};hc(a,A,q,{extensionMcp:J,mcpTokenRegistry:H,getDaemonOrigin:W},c,p),fc(a,{store:c}),yc(a,b,A,{npmRegistry:s.npmRegistry}),kc(a,C),vc(a,T),bc(a,()=>({defaultAgent:t.defaultAgent,defaultCwd:t.defaultCwd,sessionDefaults:{...t.sessionDefaults},...t.synopsisAgent!==void 0?{synopsisAgent:t.synopsisAgent}:{},...t.synopsisModel!==void 0?{synopsisModel:t.synopsisModel}:{},defaultTransformers:[...t.defaultTransformers]})),Rc(a,{store:d,rateLimiter:m,staticTokenValidator:f}),Hc(a,{store:c,health:l}),qc(a,{processRegistry:h}),tu(a,H),ru(a,H);let te=iu(a,H,J);Xc(a,{validator:g,manager:A,defaultAgent:s.defaultAgent,processRegistry:h,onExtensionVersion:(N,ve)=>C.reportVersion(N,ve),onTransformerVersion:(N,ve)=>T.reportVersion(N,ve),transformers:T,extensionCommands:E,mcpTokenRegistry:H,extensionMcp:J,extensionMcpControls:te,getDaemonOrigin:W,registry:b,foreignSessions:u});let ie=!!s.daemon.tls;await a.listen({host:ie?"127.0.0.1":s.daemon.host,port:ie?0:s.daemon.port});let X=a.server.address(),ke=X&&typeof X=="object"?X.port:s.daemon.port,Fn,pu=s.daemon.host,Wo=ke;if(ie&&n&&r){Fn=fy({listenHost:s.daemon.host,listenPort:s.daemon.port,upstreamHost:"127.0.0.1",upstreamPort:ke,tlsOptions:{key:n,cert:r},logger:a.log});let N=Fn.address();N&&typeof N=="object"&&(Wo=N.port)}await Ge.mkdir(R.home(),{recursive:!0}),await Id({pid:process.pid,host:pu,port:Wo,loopbackPort:ke,startedAt:new Date().toISOString()});let qo={daemonUrl:`http://127.0.0.1:${ke}`,daemonHost:"127.0.0.1",daemonPort:ke,serviceToken:e,daemonWsUrl:`ws://127.0.0.1:${ke}/acp`,hydraHome:R.home()};C.setContext(qo),T.setContext(qo),await C.start(),await T.start();try{await A.reconcilePermissionFlags()}catch(N){a.log.warn(`permission flag reconcile failed: ${N.message}`)}try{await A.seedSessionIndex()}catch(N){a.log.warn(`session index seed failed: ${N.message}`)}A.resurrectPendingQueues().catch(N=>{a.log.warn(`queue replay scan failed: ${N.message}`)}),A.resumePendingCompactions().catch(N=>{a.log.warn(`compaction resume scan failed: ${N.message}`)}),A.resumePendingAgentSwaps().catch(N=>{a.log.warn(`agent-swap resume scan failed: ${N.message}`)});let zo=s.daemon.agentSyncIntervalMinutes*60*1e3,Jo=zo>0?Cd({registry:b,manager:A,intervalMs:zo,logger:S}):void 0,Vo=s.daemon.sessionGcIntervalMinutes*60*1e3,gu=s.daemon.sessionGcMaxAgeDays*24*60*60*1e3,Go=Vo>0?Rd({manager:A,intervalMs:Vo,maxAgeMs:gu,logger:S}):void 0,mu=Md({bootConfig:s,apply:N=>{t=N,b.setConfig(N),A.setLiveConfig({sessionDefaults:N.sessionDefaults}),q.agentId=N.defaultAgent,q.cwd=N.defaultCwd,dr(N.daemon.scrubEnv)},onDrift:N=>{M=N},logger:S});return{app:a,manager:A,registry:b,extensions:C,transformers:T,mcpTokenRegistry:H,extensionMcp:J,processRegistry:h,shutdown:async()=>{l.stop(),p.stop(),mu(),Go&&Go(),Jo&&Jo(),clearInterval(y),clearInterval(k);let N=async(ve,Kt)=>{try{await Kt()}catch(Qt){a.log.warn(`shutdown step ${ve} failed: ${Qt instanceof Error?Qt.message:String(Qt)}`)}};await N("sessionTokenStore.flush",()=>d.flush()),await N("extensions.stop",()=>C.stop()),await N("transformers.stop",()=>T.stop()),await N("manager.closeAll",()=>A.closeAll()),await N("manager.flushSynopsis",()=>A.flushSynopsis(3e4)),await N("manager.shutdownSynopsis",()=>A.shutdownSynopsis()),await N("manager.flushMetaWrites",()=>A.flushMetaWrites()),await N("manager.flushHistoryWrites",()=>A.flushHistoryWrites()),gr(null),yr(null),bo(null),Fn&&await N("tlsTerminator.close",()=>new Promise(ve=>Fn.close(()=>ve()))),await N("app.close",()=>a.close());try{cu.unlinkSync(R.pidFile())}catch{}await N("fileStream.flushSync",()=>i.flushSync())}}}var du=20;async function uy(s,e){let t=Gt.dirname(s),n=Gt.basename(s,".log"),r=new RegExp(`^${n}\\.(\\d+)\\.log$`),o;try{o=await Ge.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=>Ge.unlink(Gt.join(t,d.name))))}async function ly(s){await uy(R.logFile(),du);let e=await cy({file:R.logFile(),size:"10m",mkdir:!0,symlink:!0,limit:{count:du,removeOtherLogFiles:!0}}),t=au.destination(2);return{stream:au.multistream([{stream:e,level:s},{stream:t,level:s}]),fileStream:e}}function fy(s){let e=lu.createServer(s.tlsOptions,t=>{let n=uu.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 py(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 gy(){process.title="hydra-acp-daemon";let{installGlobalTlsTrust:s}=await Promise.resolve().then(()=>(_n(),jc));s();let e=await Zt(),t=await Ko(),n=await fu(e,t);process.stdout.write(`hydra-acp daemon listening on ${e.daemon.host}:${e.daemon.port}
195
195
  `);let r=1e4,o=!1,i=async()=>{o&&(process.stderr.write(`Second signal received; exiting immediately.
196
196
  `),process.exit(1)),o=!0,process.stdout.write(`Shutting down...
197
197
  `);let a=setTimeout(()=>{process.stderr.write(`Graceful shutdown did not complete within ${r}ms; forcing exit.
198
198
  `),process.exit(1)},r);a.unref();try{await n.shutdown()}catch(d){process.stderr.write(`shutdown failed: ${d instanceof Error?d.message:String(d)}
199
- `)}clearTimeout(a),process.exit(0)};process.on("SIGINT",()=>{i()}),process.on("SIGTERM",()=>{i()}),process.on("SIGHUP",()=>{})}Rh().catch(s=>{process.stderr.write(`hydra-acp-daemon: ${s instanceof Error?s.message:String(s)}
199
+ `)}clearTimeout(a),process.exit(0)};process.on("SIGINT",()=>{i()}),process.on("SIGTERM",()=>{i()}),process.on("SIGHUP",()=>{})}gy().catch(s=>{process.stderr.write(`hydra-acp-daemon: ${s instanceof Error?s.message:String(s)}
200
200
  `),process.exit(1)});