@hydra-acp/cli 0.1.195 → 0.1.197
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -19
- package/dist/cli.js +493 -455
- package/dist/daemon.js +92 -92
- package/package.json +1 -1
package/dist/daemon.js
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`))}function B(){let s=process.env[
|
|
4
|
-
`;await
|
|
5
|
-
`,{encoding:"utf8",mode:384})}async function
|
|
6
|
-
`),e}Ne();import*as ci from"fs/promises";import*as nn from"os";import*as De from"path";var ee="read by the daemon, which loads config.json at startup",di={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"}},Gu={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 ar(s){return di[s]??{reload:"restart",overlay:"inert"}}function dr(s){return Gu[s]??{reload:"restart",overlay:"inert"}}function cr(){let s=[];for(let[e,t]of Object.entries(di))t.overlay!=="effective"&&s.push({key:e,effect:t.overlay,note:t.overlayNote??ee});return s}var Ku=".hydra-acp.json",ur="home",Qu=64,yw=cr().map(s=>s.key);function Yu(s){return s==="~"?nn.homedir():s.startsWith("~/")?De.join(nn.homedir(),s.slice(2)):s.startsWith("$HOME/")?De.join(nn.homedir(),s.slice(6)):s}function lr(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function fr(s,e){let t={...s};for(let[n,r]of Object.entries(e)){let o=t[n];t[n]=lr(o)&&lr(r)?fr(o,r):r}return t}async function Xu(s,e=nn.homedir()){let t=[],n=[],r=De.resolve(e),o=De.resolve(s);for(let i=0;i<Qu;i+=1){let a=De.join(o,Ku),d;try{d=await ci.readFile(a,"utf8")}catch{d=void 0}if(d!==void 0)try{let u=JSON.parse(d);lr(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=De.dirname(o);if(c===o)break;o=c}return t.reverse(),{layers:t,notices:n}}function Zu(s){let e=new Map(cr().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 el(s=process.cwd()){let{layers:e,notices:t}=await Xu(s);t.push(...Zu(e));let n={};for(let i of e)n=fr(n,i.data);let r,o=n[ur];return typeof o=="string"&&o.length>0?r=De.resolve(Yu(o)):o!==void 0&&t.push({file:e[e.length-1].file,key:ur,message:"`home` must be a non-empty string; ignoring it"}),delete n[ur],{layers:e,notices:t,merged:n,...r!==void 0?{homeRequest:r}:{}}}function tl(s,e){let t=s[e];return typeof t=="string"&&t.length>0?t:void 0}function nl(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 sn(s){let e={};try{e=(await el(s)).merged}catch{return{}}let t=tl(e,"defaultAgent"),n=nl(e,"sessionDefaults");return{...t!==void 0?{agentId:t}:{},...n!==void 0?{configDefaults:n}:{}}}var fi="https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",sl=S.object({cert:S.string(),key:S.string()}),Tt=55514,rl=S.object({host:S.string().default("127.0.0.1"),port:S.number().int().positive().default(Tt),logLevel:S.enum(["debug","info","warn","error"]).default("info"),tls:sl.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)}),ol=S.object({url:S.string().url().default(fi),ttlHours:S.number().positive().default(24),pinned:S.boolean().default(!1)}),il=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()}),al=S.object({packageSpec:S.string().optional(),extraArgs:S.array(S.string()).optional(),env:S.record(S.string()).optional()}),dl=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"]),cl=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()]),ul=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(),ll=S.union([S.string(),ul]),ui=S.array(cl);function gr(s,e){return S.object({left:ui.default(s),right:ui.default(e)}).default({})}var fl=["status",{field:"elapsed",separator:" "},"sessionId","queued","scroll"],pl=["usage"],gl=[],ml=["helpHint"],hl=["cwd","title"],yl=["agentModel"],wl=S.object({composer:S.object({top:gr(fl,pl),bottom:gr(gl,ml),hintTurns:S.number().int().nonnegative().nullable().default(3)}).default({}),sessionbar:gr(hl,yl),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(!0),width:S.number().int().positive().optional(),border:S.enum(["none","rule","frame"]).default("frame"),gadgets:S.array(ll).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(),defaultHost:S.string().min(1).default("remote:all"),hotkeys:S.record(dl,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()}),li=S.string().min(1).regex(/^[A-Za-z0-9._-]+$/,"extension name must be filename-safe"),kl=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)}),vl=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)}),bl=S.object({daemon:rl.default({}),registry:ol.default({url:fi,ttlHours:24,pinned:!1}),agents:S.record(S.string(),il).default({}),agentOverrides:S.record(S.string(),al).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(li,kl).default({}),transformers:S.record(li,vl).default({}),defaultTransformers:S.array(S.string()).default([]),npmRegistry:S.string().url().optional(),tui:wl.default({})});function pi(s){return Object.entries(s.extensions).map(([e,t])=>({name:e,...t}))}function gi(s){return Object.entries(s.transformers).map(([e,t])=>({name:e,...t}))}async function mr(){return await Sl(),await ie(x.config())??{}}async function Sl(){let s;try{s=await nt.lstat(x.config())}catch(e){if(e.code==="ENOENT")return;throw e}if(s.isSymbolicLink())try{await nt.stat(x.config())}catch(e){if(e.code!=="ENOENT")throw e;let t=await nt.readlink(x.config()).catch(()=>"<unknown>");throw new Error(`config.json at ${x.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 Il(){let s=await mr(),e=s.daemon,t=e&&typeof e.authToken=="string"?e.authToken:void 0;if(!t)return;let n=!1;try{await nt.access(x.authToken()),n=!0}catch(r){if(r.code!=="ENOENT")throw r}if(n)throw new Error(`Auth token present in both ${x.authToken()} and ${x.config()} (daemon.authToken). Remove daemon.authToken from config.json to resolve.`);await ir(t),delete e.authToken,Object.keys(e).length===0&&delete s.daemon,await pe(x.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated auth token from ${x.config()} to ${x.authToken()}.
|
|
7
|
-
`)}async function
|
|
8
|
-
`)}async function
|
|
9
|
-
`;if(await Ye.mkdir(
|
|
10
|
-
`)};function
|
|
11
|
-
`))}async function
|
|
12
|
-
`)};function
|
|
13
|
-
`))}async function
|
|
14
|
-
stderr: ${l}`:`npm install ${s.packageSpec} failed (${u})`))})})}catch(t){if(t.code==="ETXTBSY"&&e<Zl)return await new Promise(r=>setTimeout(r,ef*(e+1))),Ni(s,e+1);throw t}}function nf(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 sf(s){let e=s.lastIndexOf("/");return e===-1?s:s.slice(e+1)}async function Di(s,e){let t=He.join(s,"node_modules",e,"package.json");try{let n=await Ce.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 Oi(s){let e=He.join(s.installDir,"node_modules",".bin"),t=He.join(e,s.hint);if(await mt(t))return{binName:s.hint,binPath:t};let n=await Di(s.installDir,s.packageName);if(typeof n=="object"&&n!==null){let r=Object.keys(n);if(r.length===1){let o=r[0],i=He.join(e,o);if(await mt(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=He.join(e,o);if(await mt(i))return{binName:o,binPath:i}}}}if(s.basename!==s.hint){let r=He.join(e,s.basename);if(await mt(r))return{binName:s.basename,binPath:r}}}async function mt(s){try{return await Ce.access(s),!0}catch{return!1}}var rf=L.object({package:L.string(),bin:L.string().optional(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),$t=L.object({archive:L.string().url().optional(),cmd:L.string().optional(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),of=L.object({"darwin-aarch64":$t.optional(),"darwin-x86_64":$t.optional(),"linux-aarch64":$t.optional(),"linux-x86_64":$t.optional(),"windows-x86_64":$t.optional(),"windows-aarch64":$t.optional()}),af=L.object({package:L.string(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),df=L.object({command:L.string(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),cf=L.object({command:L.string().optional(),url:L.string().optional(),description:L.string().optional()}),uf=L.object({npx:rf.optional(),binary:of.optional(),uvx:af.optional(),exec:df.optional()}),lf=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:uf,onboarding:cf.optional(),requiredEnv:L.array(L.string().min(1)).optional()}),ji=8;function Bi(s){return s.installId??s.id}function xr(s){let e=s.extendsChain;return e&&e.length>0?e[e.length-1]:s.id}function an(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 Hi=L.object({version:L.string(),agents:L.array(lf),extensions:L.array(L.unknown()).optional()}),Jn=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{...Rr(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>=ji)throw new Error(`agent ${n.id}: extends chain deeper than ${ji} (${[...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(pf(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=>Er(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])=>Rr(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=gf(n.packageSpec),i=t.id,r={...r,npx:{...r.npx,package:n.packageSpec}}),n.extraArgs?.length&&(r=ff(r,n.extraArgs)),n.env&&Object.keys(n.env).length>0&&(r=qi(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=Hi.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 ie(x.registryCache());if(!(!e||typeof e.fetchedAt!="number"||e.data===void 0))try{let t=Hi.parse(e.data);return{fetchedAt:e.fetchedAt,raw:e.data,data:t}}catch{return}}async writeDiskCache(e){await pe(x.registryCache(),{fetchedAt:e.fetchedAt,data:e.raw})}};function Wi(s){return s&&Object.fromEntries(Object.entries(s).map(([e,t])=>[e,ce(t)]))}function Rr(s,e){return{id:s,name:e.name??s,description:e.description,version:"local",distribution:{exec:{command:ce(e.command??s),args:e.args?.map(ce),env:Wi(e.env)}}}}function qi(s,e){let t=e.args?.map(ce),n=Wi(e.env),r=o=>({...o,...t?{args:t}:{},...n?{env:{...o.env,...n}}:{}});return{...s.npx?{npx:r(s.npx)}:{},...s.uvx?{uvx:r(s.uvx)}:{},...s.exec?{exec:r(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([o,i])=>[o,i&&r(i)]))}:{}}}function ff(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 pf(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?Rr(s,e).distribution:qi(t.distribution,e),installId:n?s:t.installId??t.id,extendsChain:[s,...t.extendsChain??[t.id]]}}function gf(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 Er(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 Ot(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 Tr(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 Tr(s){let e=je();if(!e)return"no";let t=s.version??"current",n=Bi(s);if(s.distribution.exec)return"yes";if(s.distribution.binary){let r=br(s.distribution.binary,e);if(r?.cmd){let o=Vn.resolve(x.agentInstallDir(n,e,t),r.cmd);if(await Li(o))return"yes"}}if(s.distribution.npx){let r=s.distribution.npx,o=r.bin??Er(s)??r.package,i=x.agentNpmInstallDir(n,e,t),a=Vn.join(i,"node_modules",".bin",o);if(await Li(a))return"yes"}return!s.distribution.npx&&!s.distribution.binary&&s.distribution.uvx?"lazy":"no"}async function Li(s){try{return await Ui.access(s),!0}catch{return!1}}async function Te(s,e=[],t={}){let n=s.version??"current",r=Bi(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??Er(s)??o.package,d=t.onInstallProgress;return{command:await Fi({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=br(s.distribution.binary);if(!o)throw new Error(`Agent ${s.id} has no binary distribution for ${je()??"this platform"}.`);let i=t.onInstallProgress,a=await Mi({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 kf,spawnSync as vf}from"child_process";import*as Qn from"fs";import*as aa from"path";var E={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603,AuthRequired:-32e3,SessionNotFound:-32001,NotAuthorisedToAttach:-32002,MultiClientNotSupported:-32003,AgentNotInstalled:-32005,BundleAlreadyImported:-32010,PermissionDenied:-32011,AlreadyAttached:-32012,StreamNotEnabled:-32013,SessionClosing:-32014};import{z as K}from"zod";var zi=K.object({protocolVersion:K.number().optional(),clientCapabilities:K.record(K.unknown()).optional(),clientInfo:K.object({name:K.string(),version:K.string().optional()}).optional()}),mf=K.enum(["full","pending_only","none","after_message"]),Ji=K.object({cwd:K.string(),mcpServers:K.array(K.unknown()).optional(),_meta:K.record(K.unknown()).optional()}),Vi=K.object({upstreamSessionId:K.string(),agentId:K.string(),cwd:K.string(),title:K.string().optional(),agentArgs:K.array(K.string()).optional()}),Gi=K.object({sessionId:K.string(),historyPolicy:mf.default("full"),afterMessageId:K.string().optional(),afterSeq:K.number().optional(),clientId:K.string().optional(),clientInfo:K.object({name:K.string(),version:K.string().optional()}).optional(),_meta:K.record(K.unknown()).optional()});import{z as D}from"zod";var Ki=D.object({sessionId:D.string()}),Qi=D.object({cwd:D.string().optional(),cursor:D.string().optional()}),Pr=D.object({used:D.number().optional(),size:D.number().optional(),costAmount:D.number().optional(),costCurrency:D.string().optional()}),ak=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:Pr.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),turnStartedAt:D.number().optional(),armedTasks:D.number().int().nonnegative().optional(),armedSince:D.number().int().positive().optional(),compactionState:D.any().optional(),agentPid:D.number().int().positive().optional(),forkSynthesisState:D.enum(["running","failed"]).optional(),_meta:D.record(D.unknown()).optional()}),hf=D.object({sessionId:D.string(),cwd:D.string(),title:D.string().optional(),updatedAt:D.string().optional(),_meta:D.record(D.unknown()).optional()}),dk=D.object({sessions:D.array(hf),nextCursor:D.string().optional()});function Gn(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 Yi(s){let e={sessionId:s.sessionId,cwd:s.cwd,updatedAt:s.updatedAt,_meta:dn(s._meta,Gn(s))};return s.title!==void 0&&(e.title=s.title),e}var ae="hydra-acp";function yf(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 rt(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),r.adopt===!0&&(o.adopt=!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=Vi.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=Pr.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=yf(t.env);r!==void 0&&(n.env=r)}return n}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.recordedAt=="number"?s:{...t,_meta:{...n,[ae]:{...o,recordedAt:e}}}}function Ue(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 dn(s,e){return{...s??{},[ae]:e}}import{z as $}from"zod";var Xi=$.object({sessionId:$.string(),prompt:$.array($.unknown()),_meta:$.record($.unknown()).optional()}),Kn=$.object({sessionId:$.string()}),Zi=$.object({clientId:$.string(),name:$.string().optional(),version:$.string().optional()}),gk=$.object({sessionId:$.string(),messageId:$.string(),originator:Zi,prompt:$.array($.unknown()),position:$.number().int().nonnegative(),queueDepth:$.number().int().positive(),enqueuedAt:$.number()}),mk=$.object({sessionId:$.string(),messageId:$.string(),prompt:$.array($.unknown())}),hk=$.object({sessionId:$.string(),messageId:$.string(),reason:$.enum(["started","cancelled","abandoned"])}),ea=$.object({sessionId:$.string(),messageId:$.string()}),yk=$.object({cancelled:$.boolean(),reason:$.enum(["ok","not_found","already_running"])}),ta=$.object({sessionId:$.string(),messageId:$.string(),prompt:$.array($.unknown())}),wk=$.object({updated:$.boolean(),reason:$.enum(["ok","not_found","already_running"])}),na=$.object({sessionId:$.string(),targetMessageId:$.string(),prompt:$.array($.unknown()),replaceQueue:$.boolean().optional(),onTargetCompleted:$.enum(["reject","send_anyway"]).optional()}),kk=$.object({amended:$.boolean(),reason:$.enum(["ok","target_completed","target_cancelled","target_not_found"]),messageId:$.string().optional()}),sa=$.object({sessionId:$.string(),prompt:$.array($.unknown()),_meta:$.object({steering:$.object({idleBehavior:$.literal("promptRequired").optional()}).optional()}).optional()}),vk=$.object({outcome:$.enum(["injected","startedNewTurn","promptRequired","failed"]),reason:$.literal("noRunningTurn").optional(),detached:$.boolean().optional()}),bk=$.object({sessionId:$.string(),cancelledMessageId:$.string(),newMessageId:$.string(),prompt:$.array($.unknown()),originator:Zi,amendedAt:$.number()});import{z as ot}from"zod";var Ak=ot.object({agentId:ot.string(),version:ot.string(),source:ot.enum(["binary","npm"]),phase:ot.enum(["download_start","download_progress","download_done","extract","install_start","installed"]),receivedBytes:ot.number().optional(),totalBytes:ot.number().optional(),packageSpec:ot.string().optional()}),ra="hydra-acp/agents/install_progress",Ft={auth:{terminal:!0},_meta:{"terminal-auth":!0}};function oa(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(`
|
|
2
|
+
var qu=Object.defineProperty;var Wn=(s,e)=>()=>(s&&(e=s(s=0)),e);var zu=(s,e)=>{for(var t in e)qu(s,t,{get:e[t],enumerable:!0})};import*as L from"path";import*as cr from"os";function O(s){let e=cr.homedir();if(!e)return s;let t=o=>process.platform==="win32"?o.replace(/\\/g,"/").toLowerCase():o,n=t(e),r=t(s);return r===n?"~":r.startsWith(n+"/")?"~"+s.slice(e.length):s}function Ju(){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 Vu(s,e){ci||L.isAbsolute(s)||(ci=!0,process.stderr.write(`hydra-acp: ${ui} is relative (${JSON.stringify(s)}); resolved against the current directory to ${e}. Processes started from elsewhere will use a different home and will not see each other's daemon. Set an absolute path.
|
|
3
|
+
`))}function B(){let s=process.env[ui];if(s&&s.length>0){let t=L.resolve(s);return Vu(s,t),t}let e=Ju();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 L.join(cr.homedir(),".hydra-acp")}var ui,ci,x,G=Wn(()=>{"use strict";ui="HYDRA_ACP_HOME";ci=!1;x={home:B,config:()=>L.join(B(),"config.json"),authToken:()=>L.join(B(),"auth-token"),remotes:()=>L.join(B(),"remotes.json"),peers:()=>L.join(B(),"peers.json"),tlsDir:()=>L.join(B(),"tls"),pidFile:()=>L.join(B(),"daemon.pid"),logFile:()=>L.join(B(),"daemon.log"),daemonBootLog:()=>L.join(B(),"daemon-boot.log"),currentLogFile:()=>L.join(B(),"current.log"),registryCache:()=>L.join(B(),"registry.json"),themesDir:()=>L.join(B(),"themes"),ttySessionDir:()=>L.join(B(),"tty"),ttySessionFile:s=>L.join(B(),"tty",s),agentsDir:()=>L.join(B(),"agents"),agentLogFile:s=>L.join(B(),"agents","logs",`${s}.log`),agentInstallDir:(s,e,t)=>L.join(B(),"agents",e,s,t),agentNpmInstallDir:(s,e,t)=>L.join(B(),"agents",e,s,t,`node${process.versions.modules}`),sessionsDir:()=>L.join(B(),"sessions"),sessionDir:s=>L.join(B(),"sessions",s),sessionFile:s=>L.join(B(),"sessions",s,"meta.json"),historyFile:s=>L.join(B(),"sessions",s,"history.jsonl"),historyArchiveFile:(s,e)=>L.join(B(),"sessions",s,`history.jsonl.${e}`),toolsDir:s=>L.join(B(),"sessions",s,"tools"),toolBlobFile:(s,e)=>L.join(B(),"sessions",s,"tools",e),queueFile:s=>L.join(B(),"sessions",s,"queue.ndjson"),tombstonesDir:()=>L.join(B(),"sessions",".tombstones"),tombstoneAgentDir:s=>L.join(B(),"sessions",".tombstones",encodeURIComponent(s)),tombstoneFile:(s,e)=>L.join(B(),"sessions",".tombstones",encodeURIComponent(s),encodeURIComponent(e)),extensionsDir:()=>L.join(B(),"extensions"),extensionLogDir:s=>L.join(B(),"extensions",s),extensionLogFile:s=>L.join(B(),"extensions",s,"current.log"),extensionPidFile:s=>L.join(B(),"extensions",s,"extension.pid"),transformersDir:()=>L.join(B(),"transformers"),transformerLogDir:s=>L.join(B(),"transformers",s),transformerLogFile:s=>L.join(B(),"transformers",s,"current.log"),transformerPidFile:s=>L.join(B(),"transformers",s,"transformer.pid"),transformerState:(s,e)=>L.join(B(),"sessions",s,"transformer-state",e),tuiHistoryFile:s=>L.join(B(),"sessions",s,"prompt-history"),globalTuiHistoryFile:()=>L.join(B(),"prompt-history"),tuiLogFile:()=>L.join(B(),"tui.log"),shimWireLogFile:()=>L.join(B(),"shim-wire.log")}});import*as le from"fs/promises";import*as fi from"fs";import*as xe from"path";import{randomBytes as Ku}from"crypto";async function fe(s,e,t={}){let r=(t.pretty??!0?JSON.stringify(e,null,2):JSON.stringify(e))+`
|
|
4
|
+
`;await Zu(s,r,t)}async function Xu(s,e,t={}){let n=t.rename??le.rename,r=t.platform??process.platform,o=t.sleep??(i=>new Promise(a=>setTimeout(a,i)));for(let i=0;;i++)try{await n(s,e);return}catch(a){let d=a.code??"";if(!(r==="win32"&&Qu.has(d)&&i<Yu-1))throw a;await o(10*(i+1))}}async function Zu(s,e,t={}){let n=await el(s),r=xe.dirname(n);await le.mkdir(r,{recursive:!0});let o=`${n}.tmp-${process.pid}-${tl()}`;try{let i={encoding:"utf8"};t.mode!==void 0&&(i.mode=t.mode),await le.writeFile(o,e,i),await Xu(o,n)}catch(i){throw await le.unlink(o).catch(()=>{}),i}if(t.mode!==void 0)try{fi.chmodSync(n,t.mode)}catch{}}async function el(s){let e;try{e=await le.lstat(s)}catch(r){if(r.code==="ENOENT")return s;throw r}if(!e.isSymbolicLink())return s;let t=await le.readlink(s),n=xe.isAbsolute(t)?t:xe.resolve(xe.dirname(s),t);try{let r=await le.realpath(xe.dirname(n));return xe.join(r,xe.basename(n))}catch(r){if(r.code==="ENOENT")return n;throw r}}async function ie(s){let e;try{e=await le.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 tl(){return Ku(4).toString("hex")}var Qu,Yu,Ne=Wn(()=>{"use strict";Qu=new Set(["EPERM","EACCES","EBUSY"]),Yu=10});function Xs(s,e){return`${s}:${e}`}var ou=Wn(()=>{"use strict";G();Ne()});var fu={};zu(fu,{_resetForTests:()=>ly,clearPin:()=>Vo,fetchPeerFingerprint:()=>cy,formatFingerprint:()=>au,getPin:()=>ay,installGlobalTlsTrust:()=>Qo,loadPinsFromPeerStore:()=>Go,loadPinsFromStore:()=>dy,setPin:()=>jn,sha256Hex:()=>Ko,wsTlsOptions:()=>Yo});import{createHash as ty}from"crypto";import*as iu from"tls";import{Agent as ny,Dispatcher as sy,buildConnector as ry,getGlobalDispatcher as oy,setGlobalDispatcher as iy}from"undici";function jn(s,e,t){xt.set(Xs(s,e),du(t))}function Vo(s,e){xt.delete(Xs(s,e))}function ay(s,e){return xt.get(Xs(s,e))}function dy(s){xt.clear();for(let e of s.list())e.entry.pinnedFingerprint&&jn(e.host,e.port,e.entry.pinnedFingerprint)}function Go(s){for(let e of s.list())e.pinnedFingerprint&&jn(e.host,e.port,e.pinnedFingerprint)}async function cy(s,e,t={}){let n=t.timeoutMs??1e4;return new Promise((r,o)=>{let i=iu.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,Ko(u.raw))}),i.once("error",u=>d(u))})}function Ko(s){return ty("sha256").update(s).digest("hex")}function au(s){let e=du(s),t=e.match(/.{2}/g);return t?t.join(":"):e}function du(s){return s.replace(/:/g,"").toLowerCase()}function Qo(){if(Jo)return;Jo=!0;let s=oy(),e=new ny({connect:ry({rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(n,r)=>uu(n,r)})}),t=new sy;t.dispatch=(n,r)=>{let o=uy(n.origin);return(o&&cu(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(()=>{})),iy(t)}function uy(s){if(!s)return null;try{return new URL(String(s)).hostname}catch{return null}}function cu(s){for(let e of xt.keys())if(lu(e)?.host===s)return!0;return!1}function uu(s,e){if(!e||!e.raw)return new Error(`TLS peer ${s} did not present a certificate`);let t=Ko(e.raw);for(let[n,r]of xt.entries()){let o=lu(n);if(o&&o.host===s&&r===t)return}return new Error(`TLS pin mismatch for ${s} (cert sha256 ${au(t)})`)}function lu(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 Yo(s){return cu(s)?{rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(e,t)=>uu(e,t)}:{autoSelectFamily:!0}}function ly(){xt.clear(),Jo=!1}var xt,Jo,Hn=Wn(()=>{"use strict";ou();xt=new Map,Jo=!1});G();import*as nt from"fs/promises";import{homedir as wr}from"os";import{z as S}from"zod";G();import*as Pt from"fs/promises";function ur(){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 Gu(){try{let e=(await Pt.readFile(x.authToken(),"utf8")).trim();return e.length>0?e:void 0}catch(s){if(s.code==="ENOENT")return;throw s}}async function lr(s){await Pt.mkdir(x.home(),{recursive:!0}),await Pt.writeFile(x.authToken(),s+`
|
|
5
|
+
`,{encoding:"utf8",mode:384})}async function li(){let s=await Gu();if(s)return s;let e=ur();return await lr(e),process.stderr.write(`hydra-acp: initialized ${x.authToken()} with a fresh service token.
|
|
6
|
+
`),e}Ne();import*as gi from"fs/promises";import*as rn from"os";import*as De from"path";var te="read by the daemon, which loads config.json at startup",pi={daemon:{reload:"restart",overlay:"partial",overlayNote:"only changes which daemon this client dials; a daemon started from here still binds config.json's host/port. Use `home` for a separate daemon",nested:!0},agents:{reload:"live",overlay:"inert",overlayNote:te},agentOverrides:{reload:"live",overlay:"inert",overlayNote:te},registry:{reload:"live",overlay:"inert",overlayNote:te},npmRegistry:{reload:"live",overlay:"inert",overlayNote:te},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:te},synopsisModel:{reload:"warn",overlay:"inert",overlayNote:te},compaction:{reload:"warn",overlay:"inert",overlayNote:te},defaultTransformers:{reload:"warn",overlay:"inert",overlayNote:te},disableWorkspaceSnapshots:{reload:"warn",overlay:"inert",overlayNote:te},compressToolContent:{reload:"warn",overlay:"inert",overlayNote:te},extensions:{reload:"warn",overlay:"inert",overlayNote:te},transformers:{reload:"warn",overlay:"inert",overlayNote:te},tui:{reload:"client",overlay:"effective"},sessionListColdLimit:{reload:"client",overlay:"effective"}},nl={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:te},logLevel:{reload:"warn",overlay:"inert",overlayNote:te},sessionIdleTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:te},nonInteractiveOrphanTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:te},sessionHistoryMaxEntries:{reload:"warn",overlay:"inert",overlayNote:te},sessionHistoryArchiveMaxBytes:{reload:"warn",overlay:"inert",overlayNote:te},sessionHistoryArchiveTiers:{reload:"warn",overlay:"inert",overlayNote:te},agentStderrTailBytes:{reload:"warn",overlay:"inert",overlayNote:te},agentSyncIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:te},sessionGcIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:te},sessionGcMaxAgeDays:{reload:"warn",overlay:"inert",overlayNote:te}};function fr(s){return pi[s]??{reload:"restart",overlay:"inert"}}function pr(s){return nl[s]??{reload:"restart",overlay:"inert"}}function gr(){let s=[];for(let[e,t]of Object.entries(pi))t.overlay!=="effective"&&s.push({key:e,effect:t.overlay,note:t.overlayNote??te});return s}var sl=".hydra-acp.json",mr="home",rl=64,Cw=gr().map(s=>s.key);function ol(s){return s==="~"?rn.homedir():s.startsWith("~/")?De.join(rn.homedir(),s.slice(2)):s.startsWith("$HOME/")?De.join(rn.homedir(),s.slice(6)):s}function hr(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function yr(s,e){let t={...s};for(let[n,r]of Object.entries(e)){let o=t[n];t[n]=hr(o)&&hr(r)?yr(o,r):r}return t}async function il(s,e=rn.homedir()){let t=[],n=[],r=De.resolve(e),o=De.resolve(s);for(let i=0;i<rl;i+=1){let a=De.join(o,sl),d;try{d=await gi.readFile(a,"utf8")}catch{d=void 0}if(d!==void 0)try{let u=JSON.parse(d);hr(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=De.dirname(o);if(c===o)break;o=c}return t.reverse(),{layers:t,notices:n}}function al(s){let e=new Map(gr().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 dl(s=process.cwd()){let{layers:e,notices:t}=await il(s);t.push(...al(e));let n={};for(let i of e)n=yr(n,i.data);let r,o=n[mr];return typeof o=="string"&&o.length>0?r=De.resolve(ol(o)):o!==void 0&&t.push({file:e[e.length-1].file,key:mr,message:"`home` must be a non-empty string; ignoring it"}),delete n[mr],{layers:e,notices:t,merged:n,...r!==void 0?{homeRequest:r}:{}}}function cl(s,e){let t=s[e];return typeof t=="string"&&t.length>0?t:void 0}function ul(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 on(s){let e={};try{e=(await dl(s)).merged}catch{return{}}let t=cl(e,"defaultAgent"),n=ul(e,"sessionDefaults");return{...t!==void 0?{agentId:t}:{},...n!==void 0?{configDefaults:n}:{}}}var yi="https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",ll=S.object({cert:S.string(),key:S.string()}),Mt=55514,fl=S.object({host:S.string().default("127.0.0.1"),port:S.number().int().positive().default(Mt),logLevel:S.enum(["debug","info","warn","error"]).default("info"),tls:ll.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)}),pl=S.object({url:S.string().url().default(yi),ttlHours:S.number().positive().default(24),pinned:S.boolean().default(!1)}),gl=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()}),ml=S.object({packageSpec:S.string().optional(),extraArgs:S.array(S.string()).optional(),env:S.record(S.string()).optional()}),hl=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"]),yl=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()]),wl=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(),kl=S.union([S.string(),wl]),mi=S.array(yl);function kr(s,e){return S.object({left:mi.default(s),right:mi.default(e)}).default({})}var vl=["status",{field:"elapsed",separator:" "},"sessionId","queued","scroll"],bl=["usage"],Sl=[],Il=["helpHint"],Al=["cwd","title"],Cl=["agentModel"],Rl=S.object({composer:S.object({top:kr(vl,bl),bottom:kr(Sl,Il),hintTurns:S.number().int().nonnegative().nullable().default(3)}).default({}),sessionbar:kr(Al,Cl),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(!0),width:S.number().int().positive().optional(),border:S.enum(["none","rule","frame"]).default("frame"),gadgets:S.array(kl).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(),defaultHost:S.string().min(1).default("remote:all"),hotkeys:S.record(hl,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()}),hi=S.string().min(1).regex(/^[A-Za-z0-9._-]+$/,"extension name must be filename-safe"),xl=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)}),El=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)}),Tl=S.object({daemon:fl.default({}),registry:pl.default({url:yi,ttlHours:24,pinned:!1}),agents:S.record(S.string(),gl).default({}),agentOverrides:S.record(S.string(),ml).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(hi,xl).default({}),transformers:S.record(hi,El).default({}),defaultTransformers:S.array(S.string()).default([]),npmRegistry:S.string().url().optional(),tui:Rl.default({})});function wi(s){return Object.entries(s.extensions).map(([e,t])=>({name:e,...t}))}function ki(s){return Object.entries(s.transformers).map(([e,t])=>({name:e,...t}))}async function vr(){return await Pl(),await ie(x.config())??{}}async function Pl(){let s;try{s=await nt.lstat(x.config())}catch(e){if(e.code==="ENOENT")return;throw e}if(s.isSymbolicLink())try{await nt.stat(x.config())}catch(e){if(e.code!=="ENOENT")throw e;let t=await nt.readlink(x.config()).catch(()=>"<unknown>");throw new Error(`config.json at ${x.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 Ml(){let s=await vr(),e=s.daemon,t=e&&typeof e.authToken=="string"?e.authToken:void 0;if(!t)return;let n=!1;try{await nt.access(x.authToken()),n=!0}catch(r){if(r.code!=="ENOENT")throw r}if(n)throw new Error(`Auth token present in both ${x.authToken()} and ${x.config()} (daemon.authToken). Remove daemon.authToken from config.json to resolve.`);await lr(t),delete e.authToken,Object.keys(e).length===0&&delete s.daemon,await fe(x.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated auth token from ${x.config()} to ${x.authToken()}.
|
|
7
|
+
`)}async function _l(){let s=await vr(),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 fe(x.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated defaultModels to sessionDefaults in ${x.config()}.
|
|
8
|
+
`)}async function an(){return await Ml(),await _l(),Tl.parse(await vr())}function ae(s){return s==="~"||s==="$HOME"?wr():s.startsWith("~/")?wr()+s.slice(1):s.startsWith("$HOME/")?wr()+s.slice(5):s}G();import*as Ye from"fs/promises";import*as vi from"path";var $l=64*1024;async function bi(s){let e=x.daemonBootLog(),t=`[${new Date().toISOString()}] pid=${process.pid} ${s}
|
|
9
|
+
`;if(await Ye.mkdir(vi.dirname(e),{recursive:!0}),await Ye.stat(e).then(r=>r.size).catch(()=>0)>$l){await Ye.writeFile(e,t,{encoding:"utf8",mode:384});return}await Ye.appendFile(e,t,{encoding:"utf8",mode:384})}import*as Du from"fs";import*as Qe from"fs/promises";import*as ju from"net";import*as tn from"path";import*as Hu from"tls";import dw from"fastify";import cw from"@fastify/websocket";var Si="acp.v1";function Ii(s,e){return s.has(Si)?Si:!1}import Fu from"pino";import uw from"pino-roll";var Ol={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"]},Ai="HYDRA_ACP_SESSION",Fl=[Ai],Nl=[...Object.values(Ol).flat(),...Fl];function qn(s,e){return s?{...e??{},[Ai]:s}:e}var Ci=[];function br(s){Ci=s?[...s]:[]}function Dl(s,e){return e.endsWith("*")?s.startsWith(e.slice(0,-1)):s===e}function jl(){return[...Nl,...Ci]}function zn(s=process.env){let e=jl(),t={};for(let[n,r]of Object.entries(s))r!==void 0&&(e.some(o=>Dl(n,o))||(t[n]=r));return t}G();import*as pe from"fs/promises";import{createHash as Hl}from"crypto";import{gzip as Ll,gunzip as Ul}from"zlib";import{promisify as Ri}from"util";var xi=Ri(Ll),Bl=Ri(Ul),Ei=/^[A-Za-z0-9_-]+$/,Wl=/^[a-f0-9]{64}$/,Sr=!0;function Ti(s){Sr=s}function Jn(s,e){return Ei.test(s)?e===void 0||Wl.test(e):!1}function Vn(s,e){return`${x.toolBlobFile(s,e)}.gz`}async function Ir(s,e){if(!Jn(s))return null;let t=Hl("sha256").update(e,"utf8").digest("hex"),n=Vn(s,t),r=x.toolBlobFile(s,t);for(let a of[n,r])try{return await pe.access(a),t}catch{}await pe.mkdir(x.toolsDir(s),{recursive:!0});let o=Sr?n:r,i=Sr?await xi(Buffer.from(e,"utf8")):Buffer.from(e,"utf8");return await pe.writeFile(o,i,{mode:384,flag:"wx"}).catch(async a=>{if(a.code!=="EEXIST")throw a}),t}async function dn(s,e){if(!Jn(s,e))return null;try{let t=await pe.readFile(Vn(s,e));return(await Bl(t)).toString("utf8")}catch{}try{return await pe.readFile(x.toolBlobFile(s,e),"utf8")}catch{return null}}async function Pi(s,e){if(!Jn(s,e))return null;try{return await pe.readFile(Vn(s,e))}catch{}try{let t=await pe.readFile(x.toolBlobFile(s,e));return await xi(t)}catch{return null}}async function Mi(s,e,t){if(!Jn(s,e))return;let n=Vn(s,e);try{await pe.access(n);return}catch{}await pe.mkdir(x.toolsDir(s),{recursive:!0}),await pe.writeFile(n,t,{mode:384,flag:"wx"}).catch(r=>{if(r.code!=="EEXIST")throw r})}async function _i(s){Ei.test(s)&&await pe.rm(x.toolsDir(s),{recursive:!0,force:!0}).catch(()=>{})}G();import*as Ji from"fs/promises";import*as Kn from"path";import{z as H}from"zod";Ne();G();import*as Oi from"fs";import*as he from"fs/promises";import*as st from"path";import{spawn as Fi}from"child_process";import{Readable as ql}from"stream";function je(){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 Rr(s,e=je()){if(e)return s[e]}var _t=s=>{process.stderr.write(s+`
|
|
10
|
+
`)};function xr(s){_t=s??(e=>process.stderr.write(e+`
|
|
11
|
+
`))}async function Ni(s){if(!s.target.archive)throw new Error(`Agent ${s.agentId} has no archive URL for ${je()??"this platform"}`);if(!s.target.cmd)throw new Error(`Agent ${s.agentId} has no cmd in its binary target`);let e=je();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=x.agentInstallDir(s.agentId,e,s.version),n=st.resolve(t,s.target.cmd);if(await Cr(n))return n;if(await zl({agentId:s.agentId,version:s.version,archiveUrl:s.target.archive,installDir:t,onProgress:s.onProgress}),!await Cr(n))throw new Error(`Agent ${s.agentId}: extracted archive did not contain ${s.target.cmd} (looked in ${t})`);return process.platform!=="win32"&&await he.chmod(n,493).catch(()=>{}),n}async function zl(s){await he.mkdir(st.dirname(s.installDir),{recursive:!0});let e=await he.mkdtemp(`${s.installDir}.partial-`);try{_t(`hydra-acp: downloading ${s.agentId} from ${s.archiveUrl}`);let t=await Jl({url:s.archiveUrl,dir:e,agentId:s.agentId,version:s.version,onProgress:s.onProgress});_t(`hydra-acp: extracting ${s.agentId}`),$t(s.onProgress,{phase:"extract",agentId:s.agentId,version:s.version}),await Gl(t,e),await he.unlink(t).catch(()=>{});try{await he.rename(e,s.installDir)}catch(n){let r=n;if((r.code==="EEXIST"||r.code==="ENOTEMPTY")&&await Cr(s.installDir)){await he.rm(e,{recursive:!0,force:!0}).catch(()=>{}),$t(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw n}_t(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),$t(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await he.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function $t(s,e){if(s)try{s(e)}catch{}}async function Jl(s){let e=Vl(s.url),t=st.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=Oi.createWriteStream(t),i=ql.fromWeb(n.body);$t(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",f=>{a+=f.length;let m=Date.now();m-c>=l&&(c=m,$t(s.onProgress,{phase:"download_progress",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r})),m-d>=u&&(d=m,_t($i(s.agentId,a,r)))}),await new Promise((f,m)=>{i.on("error",m),o.on("error",m),o.on("finish",()=>f()),i.pipe(o)}),_t($i(s.agentId,a,r,!0)),$t(s.onProgress,{phase:"download_done",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r}),t}function $i(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 Vl(s){let e=new URL(s);return st.posix.basename(e.pathname)||"archive"}async function Gl(s,e){let t=s.toLowerCase();if(t.endsWith(".tar.gz")||t.endsWith(".tgz")||t.endsWith(".tar")){await Ar("tar",["-xf",s,"-C",e]);return}if(t.endsWith(".zip")){if(await Kl("unzip")){await Ar("unzip",["-q",s,"-d",e]);return}await Ar("tar",["-xf",s,"-C",e]);return}throw new Error(`Unsupported archive format: ${s}`)}function Ar(s,e){return new Promise((t,n)=>{let r=Fi(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 Kl(s){return new Promise(e=>{let t=process.platform==="win32"?"where":"which",n=Fi(t,[s],{stdio:"ignore"});n.on("error",()=>e(!1)),n.on("exit",r=>e(r===0))})}async function Cr(s){try{return await he.access(s),!0}catch{return!1}}G();import*as Ae from"fs/promises";import*as He from"path";import{delimiter as rf}from"path";import{spawn as of}from"child_process";import{statSync as Ql}from"fs";import{delimiter as Yl,join as Xl}from"path";var Zl=".COM;.EXE;.BAT;.CMD";function Di(s){try{return Ql(s).isFile()}catch{return!1}}function ef(s){let e=(s.PATHEXT??Zl).split(";").map(n=>n.trim()).filter(n=>n.length>0),t=[];for(let n of e)for(let r of[n,n.toLowerCase(),n.toUpperCase()])t.includes(r)||t.push(r);return t}function tf(s,e){let t=s.toLowerCase();return e.some(n=>t.endsWith(n.toLowerCase()))}function nf(s,e={}){if((e.platform??process.platform)!=="win32")return s;let n=e.env??process.env,r=ef(n);if(tf(s,r))return s;if(/[\\/]/.test(s)){for(let i of r){let a=s+i;if(Di(a))return a}return s}let o=n.PATH??n.Path??"";for(let i of o.split(Yl).filter(a=>a.length>0))for(let a of r){let d=Xl(i,s+a);if(Di(d))return d}return s}var sf=/["%\r\n]/;function ji(s){if(sf.test(s))throw new Error(`cannot pass ${JSON.stringify(s)} through cmd.exe: it contains a quote, a percent sign, or a newline, none of which can be escaped unambiguously`);return/[\s&|<>^()]/.test(s)?`"${s}"`:s}function Ot(s,e,t={}){let n=t.platform??process.platform,r=nf(s,t);return n!=="win32"||!/\.(cmd|bat)$/i.test(r)?{command:r,args:[...e],shell:!1}:{command:ji(r),args:e.map(ji),shell:!0}}var Tr=s=>{process.stderr.write(s+`
|
|
12
|
+
`)};function Pr(s){Tr=s??(e=>process.stderr.write(e+`
|
|
13
|
+
`))}async function Li(s){let e=je();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=x.agentNpmInstallDir(s.agentId,e,s.version),n=lf(s.packageSpec),r=ff(n),o={installDir:t,packageName:n,hint:s.bin,basename:r},i=He.join(t,"node_modules",".bin",s.bin);if(await mt(i))return i;if(await mt(t)){let l=await Hi(o);if(l)return l.binPath}await af({agentId:s.agentId,version:s.version,packageSpec:s.packageSpec,installDir:t,registry:s.registry,onProgress:s.onProgress});let a=await Hi(o);if(a)return a.binPath;let d=await Bi(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 af(s){await Ae.mkdir(He.dirname(s.installDir),{recursive:!0});let e=await Ae.mkdtemp(`${s.installDir}.partial-`);try{Tr(`hydra-acp: installing ${s.packageSpec} for ${s.agentId} into ${e}`),Er(s.onProgress,{phase:"install_start",agentId:s.agentId,version:s.version,packageSpec:s.packageSpec}),await uf({packageSpec:s.packageSpec,cwd:e,registry:s.registry});try{await Ae.rename(e,s.installDir)}catch(t){let n=t;if((n.code==="EEXIST"||n.code==="ENOTEMPTY")&&await mt(s.installDir)){await Ae.rm(e,{recursive:!0,force:!0}).catch(()=>{}),Er(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw t}Tr(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),Er(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await Ae.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function Er(s,e){if(s)try{s(e)}catch{}}var df=5,cf=25;function uf(s){return Ui(s,0)}async function Ui(s,e){try{await new Promise((t,n)=>{let r=s.registry?["--registry",s.registry]:[],o=Ot("npm",["install","--no-audit","--no-fund","--silent",...r,s.packageSpec]),i;try{i=of(o.command,o.args,{cwd:s.cwd,stdio:["ignore","pipe","pipe"],shell:o.shell,windowsHide:!0})}catch(d){n(d);return}let a="";i.stdout?.on("data",d=>{}),i.stderr?.setEncoding("utf8"),i.stderr?.on("data",d=>{a=(a+d).slice(-4096)}),i.on("error",d=>{if(d.code==="ENOENT"){let u=(process.env.PATH??process.env.Path??"").split(rf).filter(l=>l.length>0);n(new Error(`npm not found on PATH: tried to run ${JSON.stringify(o.command)}${o.shell?" through a shell":""} against ${u.length} PATH entries. Install Node.js / npm, or use a binary-distributed agent.`));return}n(d)}),i.on("exit",(d,c)=>{if(d===0){t();return}let u=d!==null?`exit code ${d}`:`signal ${c??"unknown"}`,l=a.trim();n(new Error(l?`npm install ${s.packageSpec} failed (${u})
|
|
14
|
+
stderr: ${l}`:`npm install ${s.packageSpec} failed (${u})`))})})}catch(t){if(t.code==="ETXTBSY"&&e<df)return await new Promise(r=>setTimeout(r,cf*(e+1))),Ui(s,e+1);throw t}}function lf(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 ff(s){let e=s.lastIndexOf("/");return e===-1?s:s.slice(e+1)}async function Bi(s,e){let t=He.join(s,"node_modules",e,"package.json");try{let n=await Ae.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 Hi(s){let e=He.join(s.installDir,"node_modules",".bin"),t=He.join(e,s.hint);if(await mt(t))return{binName:s.hint,binPath:t};let n=await Bi(s.installDir,s.packageName);if(typeof n=="object"&&n!==null){let r=Object.keys(n);if(r.length===1){let o=r[0],i=He.join(e,o);if(await mt(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=He.join(e,o);if(await mt(i))return{binName:o,binPath:i}}}}if(s.basename!==s.hint){let r=He.join(e,s.basename);if(await mt(r))return{binName:s.basename,binPath:r}}}async function mt(s){try{return await Ae.access(s),!0}catch{return!1}}var pf=H.object({package:H.string(),bin:H.string().optional(),args:H.array(H.string()).optional(),env:H.record(H.string()).optional()}),Ft=H.object({archive:H.string().url().optional(),cmd:H.string().optional(),args:H.array(H.string()).optional(),env:H.record(H.string()).optional()}),gf=H.object({"darwin-aarch64":Ft.optional(),"darwin-x86_64":Ft.optional(),"linux-aarch64":Ft.optional(),"linux-x86_64":Ft.optional(),"windows-x86_64":Ft.optional(),"windows-aarch64":Ft.optional()}),mf=H.object({package:H.string(),args:H.array(H.string()).optional(),env:H.record(H.string()).optional()}),hf=H.object({command:H.string(),args:H.array(H.string()).optional(),env:H.record(H.string()).optional()}),yf=H.object({command:H.string().optional(),url:H.string().optional(),description:H.string().optional()}),wf=H.object({npx:pf.optional(),binary:gf.optional(),uvx:mf.optional(),exec:hf.optional()}),kf=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:wf,onboarding:yf.optional(),requiredEnv:H.array(H.string().min(1)).optional()}),Wi=8;function Vi(s){return s.installId??s.id}function _r(s){let e=s.extendsChain;return e&&e.length>0?e[e.length-1]:s.id}function cn(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 qi=H.object({version:H.string(),agents:H.array(kf),extensions:H.array(H.unknown()).optional()}),Gn=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{...Mr(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>=Wi)throw new Error(`agent ${n.id}: extends chain deeper than ${Wi} (${[...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(bf(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=>$r(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])=>Mr(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=Sf(n.packageSpec),i=t.id,r={...r,npx:{...r.npx,package:n.packageSpec}}),n.extraArgs?.length&&(r=vf(r,n.extraArgs)),n.env&&Object.keys(n.env).length>0&&(r=Ki(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=qi.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 ie(x.registryCache());if(!(!e||typeof e.fetchedAt!="number"||e.data===void 0))try{let t=qi.parse(e.data);return{fetchedAt:e.fetchedAt,raw:e.data,data:t}}catch{return}}async writeDiskCache(e){await fe(x.registryCache(),{fetchedAt:e.fetchedAt,data:e.raw})}};function Gi(s){return s&&Object.fromEntries(Object.entries(s).map(([e,t])=>[e,ae(t)]))}function Mr(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:Gi(e.env)}}}}function Ki(s,e){let t=e.args?.map(ae),n=Gi(e.env),r=o=>({...o,...t?{args:t}:{},...n?{env:{...o.env,...n}}:{}});return{...s.npx?{npx:r(s.npx)}:{},...s.uvx?{uvx:r(s.uvx)}:{},...s.exec?{exec:r(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([o,i])=>[o,i&&r(i)]))}:{}}}function vf(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 bf(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?Mr(s,e).distribution:Ki(t.distribution,e),installId:n?s:t.installId??t.id,extendsChain:[s,...t.extendsChain??[t.id]]}}function Sf(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 $r(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 Nt(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 Or(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 Or(s){let e=je();if(!e)return"no";let t=s.version??"current",n=Vi(s);if(s.distribution.exec)return"yes";if(s.distribution.binary){let r=Rr(s.distribution.binary,e);if(r?.cmd){let o=Kn.resolve(x.agentInstallDir(n,e,t),r.cmd);if(await zi(o))return"yes"}}if(s.distribution.npx){let r=s.distribution.npx,o=r.bin??$r(s)??r.package,i=x.agentNpmInstallDir(n,e,t),a=Kn.join(i,"node_modules",".bin",o);if(await zi(a))return"yes"}return!s.distribution.npx&&!s.distribution.binary&&s.distribution.uvx?"lazy":"no"}async function zi(s){try{return await Ji.access(s),!0}catch{return!1}}async function Ee(s,e=[],t={}){let n=s.version??"current",r=Vi(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??$r(s)??o.package,d=t.onInstallProgress;return{command:await Li({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=Rr(s.distribution.binary);if(!o)throw new Error(`Agent ${s.id} has no binary distribution for ${je()??"this platform"}.`);let i=t.onInstallProgress,a=await Ni({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 xf,spawnSync as Ef}from"child_process";import*as Xn from"fs";import*as fa from"path";var E={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603,AuthRequired:-32e3,SessionNotFound:-32001,NotAuthorisedToAttach:-32002,MultiClientNotSupported:-32003,AgentNotInstalled:-32005,BundleAlreadyImported:-32010,PermissionDenied:-32011,AlreadyAttached:-32012,StreamNotEnabled:-32013,SessionClosing:-32014};import{z as K}from"zod";var Qi=K.object({protocolVersion:K.number().optional(),clientCapabilities:K.record(K.unknown()).optional(),clientInfo:K.object({name:K.string(),version:K.string().optional()}).optional()}),If=K.enum(["full","pending_only","none","after_message"]),Yi=K.object({cwd:K.string(),mcpServers:K.array(K.unknown()).optional(),_meta:K.record(K.unknown()).optional()}),Xi=K.object({upstreamSessionId:K.string(),agentId:K.string(),cwd:K.string(),title:K.string().optional(),agentArgs:K.array(K.string()).optional()}),Zi=K.object({sessionId:K.string(),historyPolicy:If.default("full"),afterMessageId:K.string().optional(),afterSeq:K.number().optional(),clientId:K.string().optional(),clientInfo:K.object({name:K.string(),version:K.string().optional()}).optional(),_meta:K.record(K.unknown()).optional()});import{z as D}from"zod";var ea=D.object({sessionId:D.string()}),ta=D.object({cwd:D.string().optional(),cursor:D.string().optional()}),Fr=D.object({used:D.number().optional(),size:D.number().optional(),costAmount:D.number().optional(),costCurrency:D.string().optional()}),mk=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:Fr.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),turnStartedAt:D.number().optional(),armedTasks:D.number().int().nonnegative().optional(),armedSince:D.number().int().positive().optional(),compactionState:D.any().optional(),agentPid:D.number().int().positive().optional(),forkSynthesisState:D.enum(["running","failed"]).optional(),_meta:D.record(D.unknown()).optional()}),Af=D.object({sessionId:D.string(),cwd:D.string(),title:D.string().optional(),updatedAt:D.string().optional(),_meta:D.record(D.unknown()).optional()}),hk=D.object({sessions:D.array(Af),nextCursor:D.string().optional()});function Qn(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 na(s){let e={sessionId:s.sessionId,cwd:s.cwd,updatedAt:s.updatedAt,_meta:un(s._meta,Qn(s))};return s.title!==void 0&&(e.title=s.title),e}var ce="hydra-acp";function Cf(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 rt(s){if(!s)return{};let e=s[ce];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),r.adopt===!0&&(o.adopt=!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=Xi.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=Fr.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=Cf(t.env);r!==void 0&&(n.env=r)}return n}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[ce],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.recordedAt=="number"?s:{...t,_meta:{...n,[ce]:{...o,recordedAt:e}}}}function Ue(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[ce],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.seq=="number"?s:{...t,_meta:{...n,[ce]:{...o,seq:e}}}}function un(s,e){return{...s??{},[ce]:e}}import{z as $}from"zod";var sa=$.object({sessionId:$.string(),prompt:$.array($.unknown()),_meta:$.record($.unknown()).optional()}),Yn=$.object({sessionId:$.string()}),ra=$.object({clientId:$.string(),name:$.string().optional(),version:$.string().optional()}),Sk=$.object({sessionId:$.string(),messageId:$.string(),originator:ra,prompt:$.array($.unknown()),position:$.number().int().nonnegative(),queueDepth:$.number().int().positive(),enqueuedAt:$.number()}),Ik=$.object({sessionId:$.string(),messageId:$.string(),prompt:$.array($.unknown())}),Ak=$.object({sessionId:$.string(),messageId:$.string(),reason:$.enum(["started","cancelled","abandoned"])}),oa=$.object({sessionId:$.string(),messageId:$.string()}),Ck=$.object({cancelled:$.boolean(),reason:$.enum(["ok","not_found","already_running"])}),ia=$.object({sessionId:$.string(),messageId:$.string(),prompt:$.array($.unknown())}),Rk=$.object({updated:$.boolean(),reason:$.enum(["ok","not_found","already_running"])}),aa=$.object({sessionId:$.string(),targetMessageId:$.string(),prompt:$.array($.unknown()),replaceQueue:$.boolean().optional(),onTargetCompleted:$.enum(["reject","send_anyway"]).optional()}),xk=$.object({amended:$.boolean(),reason:$.enum(["ok","target_completed","target_cancelled","target_not_found"]),messageId:$.string().optional()}),da=$.object({sessionId:$.string(),prompt:$.array($.unknown()),_meta:$.object({steering:$.object({idleBehavior:$.literal("promptRequired").optional()}).optional()}).optional()}),Ek=$.object({outcome:$.enum(["injected","startedNewTurn","promptRequired","failed"]),reason:$.literal("noRunningTurn").optional(),detached:$.boolean().optional()}),Tk=$.object({sessionId:$.string(),cancelledMessageId:$.string(),newMessageId:$.string(),prompt:$.array($.unknown()),originator:ra,amendedAt:$.number()});import{z as ot}from"zod";var _k=ot.object({agentId:ot.string(),version:ot.string(),source:ot.enum(["binary","npm"]),phase:ot.enum(["download_start","download_progress","download_done","extract","install_start","installed"]),receivedBytes:ot.number().optional(),totalBytes:ot.number().optional(),packageSpec:ot.string().optional()}),ca="hydra-acp/agents/install_progress",Dt={auth:{terminal:!0},_meta:{"terminal-auth":!0}};function ua(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(`
|
|
15
15
|
`);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:E.ParseError,message:`Failed to parse ndjson line: ${u.message}`}})}d=t.indexOf(`
|
|
16
16
|
`)}}),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)+`
|
|
17
|
-
`;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
|
|
18
|
-
`),!t.stdout||!t.stdin)throw new Error("agent subprocess missing stdio");let n=
|
|
17
|
+
`;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 Rf}from"nanoid";var Nr=class extends Error{code="ERR_CONNECTION_CLOSED";constructor(e="connection is closed"){super(e),this.name="ConnectionClosedError"}},Be=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;anyNotificationHandlers=[];bufferedNotifications=new Map;static MAX_BUFFERED_PER_METHOD=64;static MAX_BUFFERED_METHODS=256;pending=new Map;closed=!1;closeHandlers=[];orphanErrorHandlers=[];onRequest(e,t){this.requestHandlers.set(e,t)}setDefaultHandler(e){this.defaultRequestHandler=e}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}onAnyNotification(e){this.anyNotificationHandlers.push(e)}onClose(e){this.closeHandlers.push(e)}isClosed(){return this.closed}onOrphanError(e){this.orphanErrorHandlers.push(e)}async request(e,t){return this.requestWithId(e,t).response}requestWithId(e,t){if(this.closed)throw new Nr;let n=Rf(),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:E.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??E.InternalError,message:r.message,data:r.data}).catch(()=>{})}}handleNotification(e){for(let r of this.anyNotificationHandlers)try{r(e.params,e.method)}catch{}let t=this.notificationHandlers.get(e.method);if(t){t(e.params,e.method);return}let n=this.bufferedNotifications.get(e.method);if(!n){if(this.bufferedNotifications.size>=s.MAX_BUFFERED_METHODS){let r=this.bufferedNotifications.keys().next().value;r!==void 0&&this.bufferedNotifications.delete(r)}n=[],this.bufferedNotifications.set(e.method,n)}n.push(e),n.length>s.MAX_BUFFERED_PER_METHOD&&n.shift()}handleResponse(e){let t=e.id===null?void 0:this.pending.get(e.id);if(!t){if(e.error)for(let n of this.orphanErrorHandlers)try{n({code:e.error.code,message:e.error.message,data:e.error.data})}catch{}return}if(this.pending.delete(e.id),e.error){let n=new Error(e.error.message);n.code=e.error.code,n.data=e.error.data,t.reject(n)}else t.resolve(e.result)}async sendError(e,t){let n={jsonrpc:"2.0",id:e,error:t};await this.stream.send(n)}handleClose(e){if(!this.closed){this.closed=!0;for(let t of this.pending.values())t.reject(e??new Error("connection closed"));this.pending.clear();for(let t of this.closeHandlers)t(e)}}};G();var Tf=4096,it=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??Tf,this.killEscalationMs=e.killEscalationMs??Pf,this.logger=e.logger,this.fileLog=Mf(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()} ---
|
|
18
|
+
`),!t.stdout||!t.stdin)throw new Error("agent subprocess missing stdio");let n=ua(t.stdout,t.stdin);this.connection=new Be(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()} ---
|
|
19
19
|
`),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()} ---
|
|
20
20
|
`),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}
|
|
21
|
-
stderr: ${t}`:e}stderrTailText(){return this.stderrTail.trim()}static spawn(e){let t={...
|
|
21
|
+
stderr: ${t}`:e}stderrTailText(){return this.stderrTail.trim()}static spawn(e){let t={...zn(),...e.plan.env,...e.extraEnv??{}},n=Ot(e.plan.command,e.plan.args),r=xf(n.command,n.args,{cwd:e.cwd,env:t,stdio:["pipe","pipe","pipe"],shell:n.shell,windowsHide:!0,detached:!0});return r.unref(),new s(e,r)}onExit(e){this.exitHandlers.push(e)}isAlive(){return!this.exited}async kill(e="SIGTERM"){this.exited||(this.killed=!0,this.writeLog(`--- kill requested signal=${e} time=${new Date().toISOString()} ---
|
|
22
22
|
`),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()} ---
|
|
23
|
-
`),this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} did not exit after ${e}; sending SIGKILL`),this.signalProcessGroup("SIGKILL"),await this.waitForExit(ia),this.exited||this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} still has not exited ${ia}ms after SIGKILL; giving up on the reap`)))}signalProcessGroup(e){let t=this.child.pid;if(t!==void 0){if(process.platform==="win32"){try{vf("taskkill",["/pid",String(t),"/T","/F"],{stdio:"ignore",windowsHide:!0})}catch{try{this.child.kill()}catch{}}return}try{process.kill(-t,e)}catch{try{this.child.kill(e)}catch{}}}}waitForExit(e){return this.exited?Promise.resolve():new Promise(t=>{let n=setTimeout(()=>{this.child.off("exit",r),t()},e),r=()=>{clearTimeout(n),t()};this.child.once("exit",r)})}},Sf=2e3,ia=5e3;function If(s){try{let e=x.agentLogFile(s);Qn.mkdirSync(aa.dirname(e),{recursive:!0});let t=Qn.createWriteStream(e,{flags:"a"});return t.on("error",()=>{}),t}catch{return}}import*as At from"fs/promises";import*as jd from"os";import*as da from"os";function cn(){return da.hostname()}import*as xn from"path";import{customAlphabet as Vg}from"nanoid";var We="session/set_model",$r="session/set_config_option",la="model";function _r(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.availableModels)}function fa(s){return Array.isArray(s)&&s.some(e=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.id===la)}function Nt(s){if(!s)return;if(_r(s)||_r(s.models))return We;let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){for(let[t,n]of Object.entries(e))if(t!=="hydra-acp"&&_r(n))return We}if(fa(s.configOptions))return $r}function pa(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.sessionUpdate;if(e==="_hydra_current_model_update")return We;if(e==="config_option_update"&&fa(s.configOptions))return $r}function ca(s){return typeof s=="object"&&s!==null&&s.code===E.MethodNotFound}function ua(s,e,t,n){let r={...n??{}};return delete r.sessionId,delete r.modelId,delete r.configId,delete r.value,s===We?{...r,sessionId:e,modelId:t}:{...r,sessionId:e,configId:la,value:t}}function Af(s){return s===We?$r:We}async function at(s){let{request:e,sessionId:t,modelId:n,extraParams:r,logger:o}=s,i=s.verb??We;try{let a=await e(i,ua(i,t,n,r));return{verb:i,result:a}}catch(a){if(!ca(a))throw a;let d=Af(i);o?.info(`agent does not implement ${i} (MethodNotFound); retrying model change via ${d} modelId=${JSON.stringify(n)}`);try{let c=await e(d,ua(d,t,n,r));return{verb:d,result:c}}catch(c){throw ca(c)?a:c}}}async function ht(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 yt(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 at({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 La}from"nanoid";function qe(s){return`${s.name}:${s.localId}`}function dt(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 Cf}from"crypto";function Rf(s,e){return Cf("sha256",s).update(e).digest("hex")}function Or(s,e){let t=JSON.stringify(e),n=Rf(s.secret,t);fetch(s.callbackUrl,{method:"POST",headers:{"Content-Type":"application/json","X-Hydra-Turn-Notify-Signature":n},body:t}).catch(()=>{})}var ga="edit",Yn=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 ma(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 ya from"fs/promises";var xf=64*1024*1024,Ef=1*1024*1024,Dt=64*1024,Tf=6e4,Pf=100,Mf=1e3,_f=64*1024,$f=256*1024,ha=20;function Of(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Xn=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??xf,this.maxCapacityBytes<=0)throw new Error("capacityBytes must be > 0");this.currentCapacityBytes=Math.min(Ef,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,Dt));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,Dt)),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,Dt)),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,Tf));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(Of(e.pattern),d),u=e.invert??!1,l=Math.max(1,Math.min(e.maxMatches??Pf,Mf)),f=Math.max(1,Math.min(e.maxBytes??_f,$f)),m=Math.max(0,Math.min(e.contextBefore??0,ha)),h=Math.max(0,Math.min(e.contextAfter??0,ha)),p=[],g=[],w=[],y=0,k=!1,b=0,I=0,v=(R,T)=>{for(let M of w)M.remaining>0&&(M.match.after===void 0&&(M.match.after=[]),M.match.after.push({cursor:R,line:T}),M.remaining--,y+=T.length);for(;w.length>0&&w[0].remaining===0;)w.shift();if(c.test(T)!==u&&p.length<l){let M={cursor:R,line:T};if(m>0&&g.length>0){M.before=g.slice();for(let W of M.before)y+=W.line.length}y+=T.length,p.push(M),h>0&&w.push({match:M,remaining:h})}if(m>0)for(g.push({cursor:R,line:T});g.length>m;)g.shift();let H=p.length>=l&&w.length===0,J=y>=f;return H||J};for(let R=0;R<i.length;R++){if(i[R]!==10)continue;let T=i.subarray(b,R).toString("utf8"),_=r+b;if(b=R+1,I=b,v(_,T)){k=!0;break}}if(!k&&b<i.length&&this.closed){let R=i.subarray(b).toString("utf8"),T=r+b;v(T,R)&&(k=!0),I=i.length}let A=Math.min(r+I,this.writeCursor),C={matches:p,truncated:k,nextCursor:A,scannedBytes:I};return o>0&&(C.gap=o),this.closed&&A>=this.writeCursor&&(C.eof=!0),C}wakeWaiters(e){if(this.waiters.length===0)return;let t=this.waiters;this.waiters=[];for(let n of t)n.resolve(e)}growIfNeeded(e){if(this.currentCapacityBytes>=this.maxCapacityBytes)return;let t=this.writeCursor+e;if(t<=this.currentCapacityBytes)return;let n=this.currentCapacityBytes;for(;n<t&&n<this.maxCapacityBytes;)n=Math.min(this.maxCapacityBytes,n*2);if(n===this.currentCapacityBytes)return;let r=Buffer.alloc(n);this.storage.copy(r,0,0,this.writeCursor),this.storage=r,this.currentCapacityBytes=n}writeRing(e){let t=e.length;if(this.growIfNeeded(t),t>=this.currentCapacityBytes){let o=t-this.currentCapacityBytes;e.copy(this.storage,0,o,t);return}let n=this.writeCursor%this.currentCapacityBytes,r=this.currentCapacityBytes-n;t<=r?e.copy(this.storage,n,0,t):(e.copy(this.storage,n,0,r),e.copy(this.storage,0,r,t))}sliceFromRing(e,t){if(t<=0)return Buffer.alloc(0);let n=Buffer.alloc(t),r=e%this.currentCapacityBytes,o=Math.min(t,this.currentCapacityBytes-r);return this.storage.copy(n,0,r,r+o),o<t&&this.storage.copy(n,o,0,t-o),n}scheduleFileWrite(e){let t=this.filePath;if(t===void 0||this.fileCapReached)return;let n=this.fileCapBytes-this.fileBytesWritten;if(n<=0){this.fileCapReached=!0,this.onFileCapReached?.();return}let r=e.length<=n?e:e.subarray(0,n);this.fileBytesWritten+=r.length;let o=this.fileBytesWritten>=this.fileCapBytes;this.fileWriteChain=this.fileWriteChain.then(()=>ya.appendFile(t,r)).catch(i=>{this.logWriteError?.(i)}),o&&!this.fileCapReached&&(this.fileCapReached=!0,this.onFileCapReached?.())}async drainFileWrites(){await this.fileWriteChain.catch(()=>{})}};var jt=[{verb:"title",name:"hydra title",description:"Regenerate the session title + synopsis via the agent (or set title manually with an arg)"},{verb:"agent",name:"hydra agent",argsHint:"<agent | status>",description:"Schedule a swap to a different agent (synthesizes a brief in the target's idiom, rotates on idle); `status` reports any pending swap"},{verb:"workspace",name:"hydra workspace",argsHint:"<start [name] [--clean] | sync | merge | apply | stop | detach | clean [--deep] | discard | status>",description:"Move this session into an isolated workspace so its edits cannot collide with other work, then land or discard them. `start` copies your uncommitted changes in and leaves the real tree untouched; `start --clean` leaves them behind so the workspace begins at the last commit. `stop` merges and returns; `discard` throws the work away and returns; `detach` returns without merging, leaving the workspace and its branch intact; `merge` lands the work without leaving; `apply` also stays, but delivers the work as ONE staged, uncommitted changeset instead of as the agent's commits, so you review and commit it yourself, with no fast-forward needed, which is what makes it work once the source has moved on; `clean` throws away everything done in the workspace and stays there, putting it back exactly as `start --clean` would have made it (add `--deep` to rebuild dependencies and carried config files too, rather than keeping them); `sync` pulls the source's committed history INTO the workspace, so you can test against what you will land onto, and because landing is fast-forward-only, syncing is also how you recover once the source has moved on. `start <name>` naming a workspace another live session is already in JOINS it instead of making a second one, so two sessions can share a checkout deliberately: edits interleave, `stop` behaves as `detach` while anyone else is still there, and the work lands when the last of them leaves."},{verb:"kill",name:"hydra kill",description:"Close this session (kills the agent; record is kept so it can be resumed later)"},{verb:"restart",name:"hydra restart",description:"Restart the agent with a fresh session/new while preserving conversation history (useful when the proxy has changed available models)"},{verb:"compact",name:"hydra compact",description:"Compact this session's history. Use '/hydra compact status' to inspect current compaction state without triggering."},{verb:"uncompact",name:"hydra uncompact",description:"Roll back the most recent compaction swap (only available immediately after a swap, before any new turns)"},{verb:"fork",name:"hydra fork",argsHint:"[--verbatim] [prompt]",description:"Fork this conversation into a new session (default: synthesis mode with a synopsis brief; pass --verbatim to slice at the last completed turn instead). A prompt is sent to the fork as its first turn once it's ready."},{verb:"config",name:"hydra config",argsHint:"[<id> [<value>]]",description:"List or set an agent-advertised configOption (model, mode, effort, etc.). With no args, lists all options; with <id>, shows its choices; with <id> <value>, applies it."}],tv=new Map(jt.map(s=>[s.verb,s]));function wa(s){let e=s.lastIndexOf("/");return(e===-1?s:s.slice(e+1)).toLowerCase()}function Ht(s,e){return Lt(s,e.map(t=>t.modelId))}function Lt(s,e){if(e.length===0)return{kind:"none",requested:s};if(e.includes(s))return{kind:"exact",modelId:s};let t=wa(s),n=e.filter(o=>wa(o)===t);if(n.length===1)return{kind:"resolved",modelId:n[0],requested:s};if(n.length>1)return{kind:"ambiguous",requested:s,candidates:n};let r=s.toLowerCase();if(r.length>0){let o=e.filter(i=>i.toLowerCase().includes(r));if(o.length===1)return{kind:"resolved",modelId:o[0],requested:s};if(o.length>1)return{kind:"ambiguous",requested:s,candidates:o}}return{kind:"unknown",requested:s}}var Ff="Compact conversation",Nf="contextCompaction",Df=`
|
|
23
|
+
`),this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} did not exit after ${e}; sending SIGKILL`),this.signalProcessGroup("SIGKILL"),await this.waitForExit(la),this.exited||this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} still has not exited ${la}ms after SIGKILL; giving up on the reap`)))}signalProcessGroup(e){let t=this.child.pid;if(t!==void 0){if(process.platform==="win32"){try{Ef("taskkill",["/pid",String(t),"/T","/F"],{stdio:"ignore",windowsHide:!0})}catch{try{this.child.kill()}catch{}}return}try{process.kill(-t,e)}catch{try{this.child.kill(e)}catch{}}}}waitForExit(e){return this.exited?Promise.resolve():new Promise(t=>{let n=setTimeout(()=>{this.child.off("exit",r),t()},e),r=()=>{clearTimeout(n),t()};this.child.once("exit",r)})}},Pf=2e3,la=5e3;function Mf(s){try{let e=x.agentLogFile(s);Xn.mkdirSync(fa.dirname(e),{recursive:!0});let t=Xn.createWriteStream(e,{flags:"a"});return t.on("error",()=>{}),t}catch{return}}import*as Ct from"fs/promises";import*as Wd from"os";import*as pa from"os";function ht(){return pa.hostname()}import*as En from"path";import{customAlphabet as tm}from"nanoid";var We="session/set_model",jr="session/set_config_option",ha="model";function Dr(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.availableModels)}function ya(s){return Array.isArray(s)&&s.some(e=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.id===ha)}function jt(s){if(!s)return;if(Dr(s)||Dr(s.models))return We;let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){for(let[t,n]of Object.entries(e))if(t!=="hydra-acp"&&Dr(n))return We}if(ya(s.configOptions))return jr}function wa(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.sessionUpdate;if(e==="_hydra_current_model_update")return We;if(e==="config_option_update"&&ya(s.configOptions))return jr}function ga(s){return typeof s=="object"&&s!==null&&s.code===E.MethodNotFound}function ma(s,e,t,n){let r={...n??{}};return delete r.sessionId,delete r.modelId,delete r.configId,delete r.value,s===We?{...r,sessionId:e,modelId:t}:{...r,sessionId:e,configId:ha,value:t}}function _f(s){return s===We?jr:We}async function at(s){let{request:e,sessionId:t,modelId:n,extraParams:r,logger:o}=s,i=s.verb??We;try{let a=await e(i,ma(i,t,n,r));return{verb:i,result:a}}catch(a){if(!ga(a))throw a;let d=_f(i);o?.info(`agent does not implement ${i} (MethodNotFound); retrying model change via ${d} modelId=${JSON.stringify(n)}`);try{let c=await e(d,ma(d,t,n,r));return{verb:d,result:c}}catch(c){throw ga(c)?a:c}}}async function yt(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 wt(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 at({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 za}from"nanoid";function qe(s){return`${s.name}:${s.localId}`}function dt(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 $f}from"crypto";function Of(s,e){return $f("sha256",s).update(e).digest("hex")}function Hr(s,e){let t=JSON.stringify(e),n=Of(s.secret,t);fetch(s.callbackUrl,{method:"POST",headers:{"Content-Type":"application/json","X-Hydra-Turn-Notify-Signature":n},body:t}).catch(()=>{})}var ka="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 va(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 Sa from"fs/promises";var Ff=64*1024*1024,Nf=1*1024*1024,Ht=64*1024,Df=6e4,jf=100,Hf=1e3,Lf=64*1024,Uf=256*1024,ba=20;function Bf(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var es=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??Ff,this.maxCapacityBytes<=0)throw new Error("capacityBytes must be > 0");this.currentCapacityBytes=Math.min(Nf,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,Ht));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,Ht)),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,Ht)),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,Df));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(Bf(e.pattern),d),u=e.invert??!1,l=Math.max(1,Math.min(e.maxMatches??jf,Hf)),f=Math.max(1,Math.min(e.maxBytes??Lf,Uf)),m=Math.max(0,Math.min(e.contextBefore??0,ba)),h=Math.max(0,Math.min(e.contextAfter??0,ba)),p=[],g=[],w=[],y=0,k=!1,b=0,I=0,v=(R,T)=>{for(let M of w)M.remaining>0&&(M.match.after===void 0&&(M.match.after=[]),M.match.after.push({cursor:R,line:T}),M.remaining--,y+=T.length);for(;w.length>0&&w[0].remaining===0;)w.shift();if(c.test(T)!==u&&p.length<l){let M={cursor:R,line:T};if(m>0&&g.length>0){M.before=g.slice();for(let W of M.before)y+=W.line.length}y+=T.length,p.push(M),h>0&&w.push({match:M,remaining:h})}if(m>0)for(g.push({cursor:R,line:T});g.length>m;)g.shift();let U=p.length>=l&&w.length===0,J=y>=f;return U||J};for(let R=0;R<i.length;R++){if(i[R]!==10)continue;let T=i.subarray(b,R).toString("utf8"),_=r+b;if(b=R+1,I=b,v(_,T)){k=!0;break}}if(!k&&b<i.length&&this.closed){let R=i.subarray(b).toString("utf8"),T=r+b;v(T,R)&&(k=!0),I=i.length}let A=Math.min(r+I,this.writeCursor),C={matches:p,truncated:k,nextCursor:A,scannedBytes:I};return o>0&&(C.gap=o),this.closed&&A>=this.writeCursor&&(C.eof=!0),C}wakeWaiters(e){if(this.waiters.length===0)return;let t=this.waiters;this.waiters=[];for(let n of t)n.resolve(e)}growIfNeeded(e){if(this.currentCapacityBytes>=this.maxCapacityBytes)return;let t=this.writeCursor+e;if(t<=this.currentCapacityBytes)return;let n=this.currentCapacityBytes;for(;n<t&&n<this.maxCapacityBytes;)n=Math.min(this.maxCapacityBytes,n*2);if(n===this.currentCapacityBytes)return;let r=Buffer.alloc(n);this.storage.copy(r,0,0,this.writeCursor),this.storage=r,this.currentCapacityBytes=n}writeRing(e){let t=e.length;if(this.growIfNeeded(t),t>=this.currentCapacityBytes){let o=t-this.currentCapacityBytes;e.copy(this.storage,0,o,t);return}let n=this.writeCursor%this.currentCapacityBytes,r=this.currentCapacityBytes-n;t<=r?e.copy(this.storage,n,0,t):(e.copy(this.storage,n,0,r),e.copy(this.storage,0,r,t))}sliceFromRing(e,t){if(t<=0)return Buffer.alloc(0);let n=Buffer.alloc(t),r=e%this.currentCapacityBytes,o=Math.min(t,this.currentCapacityBytes-r);return this.storage.copy(n,0,r,r+o),o<t&&this.storage.copy(n,o,0,t-o),n}scheduleFileWrite(e){let t=this.filePath;if(t===void 0||this.fileCapReached)return;let n=this.fileCapBytes-this.fileBytesWritten;if(n<=0){this.fileCapReached=!0,this.onFileCapReached?.();return}let r=e.length<=n?e:e.subarray(0,n);this.fileBytesWritten+=r.length;let o=this.fileBytesWritten>=this.fileCapBytes;this.fileWriteChain=this.fileWriteChain.then(()=>Sa.appendFile(t,r)).catch(i=>{this.logWriteError?.(i)}),o&&!this.fileCapReached&&(this.fileCapReached=!0,this.onFileCapReached?.())}async drainFileWrites(){await this.fileWriteChain.catch(()=>{})}};var Lt=[{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] [prompt]",description:"Fork this conversation into a new session (default: synthesis mode with a synopsis brief; pass --verbatim to slice at the last completed turn instead). A prompt is sent to the fork as its first turn once it's ready."},{verb:"config",name:"hydra config",argsHint:"[<id> [<value>]]",description:"List or set an agent-advertised configOption (model, mode, effort, etc.). With no args, lists all options; with <id>, shows its choices; with <id> <value>, applies it."}],cv=new Map(Lt.map(s=>[s.verb,s]));function Ia(s){let e=s.lastIndexOf("/");return(e===-1?s:s.slice(e+1)).toLowerCase()}function Ut(s,e){return Bt(s,e.map(t=>t.modelId))}function Bt(s,e){if(e.length===0)return{kind:"none",requested:s};if(e.includes(s))return{kind:"exact",modelId:s};let t=Ia(s),n=e.filter(o=>Ia(o)===t);if(n.length===1)return{kind:"resolved",modelId:n[0],requested:s};if(n.length>1)return{kind:"ambiguous",requested:s,candidates:n};let r=s.toLowerCase();if(r.length>0){let o=e.filter(i=>i.toLowerCase().includes(r));if(o.length===1)return{kind:"resolved",modelId:o[0],requested:s};if(o.length>1)return{kind:"ambiguous",requested:s,candidates:o}}return{kind:"unknown",requested:s}}var Wf="Compact conversation",qf="contextCompaction",zf=`
|
|
24
24
|
|
|
25
|
-
Compacting completed.`;function
|
|
26
|
-
`,
|
|
27
|
-
`),t)}function
|
|
28
|
-
`)}function
|
|
29
|
-
`);for(;t.length>0;){let n=
|
|
30
|
-
`);if(n.length<=e)return n;t.shift()}return
|
|
31
|
-
`)}function
|
|
32
|
-
`)}`}function
|
|
33
|
-
`)}function
|
|
34
|
-
`)}function
|
|
35
|
-
`)}function
|
|
25
|
+
Compacting completed.`;function Jf(s){if(!s||s.status!=="completed"||s.sessionUpdate!=="tool_call"&&s.sessionUpdate!=="tool_call_update")return!1;let e=s._meta,t=e!==null&&typeof e=="object"&&qf in e;return s.title===Wf||t}function Vf(s){if(!s||s.sessionUpdate!=="agent_message_chunk")return!1;let e=s.content;return!e||typeof e!="object"||Array.isArray(e)?!1:e.text===zf}function Aa(s){return Jf(s)||Vf(s)}function ts(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=Lr(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 Xf){if(!Ca(c[l]))continue;let f=n.get(u);f===void 0?n.set(u,new Map([[l,c[l]]])):f.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=Lr(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?(Qf(r,o.outIndex,Gf(c.content)),Kf(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 f=l!==void 0&&t.has(l)?Yf(d,t.get(l)??[]):d,m=l===void 0?void 0:n.get(l);if(m!==void 0)for(let[h,p]of m)Ca(Lr(f)?.[h])||(f=Zf(f,h,p));r.push(f);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 Lr(s){if(s.method!=="session/update")return;let t=s.params?.update;if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function Gf(s){if(!s||typeof s!="object")return"";let e=s;return typeof e.text=="string"?e.text:""}function Kf(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 Qf(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 Yf(s,e){let t=s.params??{},n=t.update??{};return{...s,params:{...t,update:{...n,content:e}}}}var Xf=["rawInput","locations"];function Ca(s){return s==null||typeof s!="object"?!1:Array.isArray(s)?s.length>0:Object.keys(s).length>0}function Zf(s,e,t){let n=s.params??{},r=n.update??{};return{...s,params:{...n,update:{...r,[e]:t}}}}var Ra=`[older history truncated]
|
|
26
|
+
`,xa=["file_path","filePath","path","command","pattern","query"];function Wt(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 f=zr(u.prompt).trim();f.length>0&&r.push(`User: ${f}`)}else if(l==="agent_message_chunk"){let f=Jr(u.content);f.length>0&&(o+=f)}else if(l==="tool_call"){if(a(),r.push(qr(u,n)),e.toolOutput!==void 0){let f=Wr(u),m=f!==void 0?n.get(f)?.output:void 0;if(m!==void 0&&i>0){let h=Math.min(e.toolOutput.maxPerCall,i),p=m.length<=h?m:`${m.slice(0,h)}\u2026[${m.length-h} more chars]`;r.push(`Output: ${p}`),i-=Math.min(p.length,h)}}}else l==="turn_complete"&&a()}return a(),ip(r.join(`
|
|
27
|
+
`),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=Wr(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=tp(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=ns(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=Br(t);return e}function Br(s){return ep(s)?s.kind??"(unnamed)":s.name}function ep(s){for(let e of xa){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 tp(s,e){let t=ln(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 Wr(s){let e=s.toolCallId;if(typeof e=="string"&&e.length>0)return e}function ns(s){let e=np(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 np(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(`
|
|
28
|
+
`)}function ln(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 qr(s,e){let t=Wr(s),n=t!==void 0?e?.get(t):void 0,r=n?.name??sp(s),o=rp(n?.rawInput??s.rawInput);return o.length===0?`Tool: ${r}`:`Tool: ${r}(${o.join(", ")})`}function sp(s){let e=ln(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 rp(s){if(!s||typeof s!="object"||Array.isArray(s))return[];let e=s,t=[];for(let n of xa){let r=e[n];typeof r=="string"&&r.length>0&&t.push(`${n}=${op(r,600)}`)}return t}function zr(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 Jr(s){if(!s||typeof s!="object")return"";let e=s.text;return typeof e=="string"?e:""}function op(s,e){return s.length<=e?s:s.slice(0,e-1)+"\u2026"}function ip(s,e){if(s.length<=e)return s;let t=s.split(`
|
|
29
|
+
`);for(;t.length>0;){let n=Ra+t.join(`
|
|
30
|
+
`);if(n.length<=e)return n;t.shift()}return Ra}var Ea="(untitled)";function Vr(s){let e=[],t=s.synopsis;if(t!==void 0){e.push("--- begin prior session compaction ---"),e.push(`[Title] ${s.title??Ea}`),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=fn("Open threads",t.open_threads);d.length>0&&e.push(d);let c=fn("Decisions",t.decisions);c.length>0&&e.push(c);let u=fn("File edit intentions",t.file_edit_intentions);u.length>0&&e.push(u);let l=fn("Unresolved errors",t.unresolved_errors);l.length>0&&e.push(l);let f=fn("Tool state",t.tool_state);f.length>0&&e.push(f);let m=Ta(t.files_touched);m.length>0&&e.push(`[Files previously touched] ${m}`);let h=Ta(t.tools_used);h.length>0&&e.push(`[Tools previously used] ${h}`),e.push("--- end prior session compaction ---")}else e.push(`[Title] ${s.title??Ea}`);s.note!==void 0&&s.note.trim().length>0&&e.push(`[Situation] ${s.note.trim()}`);let{closedText:n,openText:r,keptCount:o}=ap(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(`
|
|
31
|
+
`)}function fn(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(`
|
|
32
|
+
`)}`}function Ta(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 ap(s,e,t,n){if(s.length===0)return{closedText:"",openText:"",keptCount:0};let{closed:r,open:o}=dp(s),i=0,a=[];if(e>0&&r.length>0){let u=r.filter(m=>m.startEntryIndex>=t).length,l=Math.max(u,n),f=Math.min(l,e,r.length);i=f,a=f>0?r.slice(-f):[]}let d=a.length>0?Pa(a):"",c=o?Pa([o]):"";return{closedText:d,openText:c,keptCount:i}}function Pa(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(`
|
|
33
|
+
`)}function dp(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:zr(d.prompt).trim(),agent:"",tools:[],startEntryIndex:o};else if(c==="agent_message_chunk"&&t!==null){let u=Jr(d.content);u.length>0&&(t.agent+=u)}else c==="tool_call"&&t!==null?t.tools.push(qr(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 _a(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:cp(a),unknownCount:r.filter(d=>d.reason===void 0&&d.inferredReason===void 0&&!d.notCompaction).length}}function cp(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 up(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 Ma(s){if(s<1e3)return String(s);let e=s/1e3;return e<100?`${e.toFixed(1)}k`:`${Math.round(e)}k`}function lp(s){return s.usedBefore===void 0||s.usedAfter===void 0?"":` ${Ma(s.usedBefore)} \u2192 ${Ma(s.usedAfter)}`}function $a(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=lp(r),i=r.cost!==void 0?` $${r.cost.toFixed(2)}`:"",a=r.current?" (current)":"",d=r.swaps>1?` (${r.swaps} swaps)`:"";n.push(` ${up(r.at)} ${r.upstreamSessionId}${o}${i}${d}${a}`)}}if(t>0){let r=t===1?"rotation":"rotations";n.push(e.length>0?`${t} earlier ${r}, cause not recorded; the count above is a lower bound.`:`No compactions on record. ${t} ${r} predate reason tracking, and any of them may have been a compaction.`)}return n}import*as ct from"path";function fp(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Gr(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(`${fp(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 Kr(s,e){if(e.length===0)return!1;let t=e.endsWith("/")?e.slice(0,-1):e;return s.includes(t)}function Oa(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(`
|
|
34
|
+
`)}function Fa(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(`
|
|
35
|
+
`)}function Na(s,e,t){return s.length===0||!ct.isAbsolute(s)||ss(s,t)?!1:ss(s,e)}function ss(s,e){let t=ct.relative(ct.resolve(e),ct.resolve(s));return!(t.length===0||t.startsWith("..")||ct.isAbsolute(t))}G();import*as ze from"fs/promises";async function pn(s,e){let t=x.queueFile(s);if(e.length===0){await ze.unlink(t).catch(()=>{});return}await ze.mkdir(x.sessionDir(s),{recursive:!0});let n=e.map(r=>JSON.stringify(r)).join(`
|
|
36
36
|
`)+`
|
|
37
|
-
`;await ze.writeFile(t,n,"utf8")}async function
|
|
38
|
-
`))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
|
|
39
|
-
`).map(t=>t.trim()).filter(t=>t!=="");return e.length===0?"":e[e.length-1]}var hp=128,yp=new Set(["local_bash"]),wp=1e3,Bt=class s{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=We;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;lastUnsolicitedCancelAt=0;cancelReopenStreak=0;static UNSOLICITED_REOPEN_WINDOW_MS=1e4;static UNSOLICITED_REOPEN_LIMIT=3;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}_titleSeedPending=!0;_upstreamRespawned=!1;promptStartedAt;turnRanTool=!1;unsolicitedTurn;pendingSteerDetach;supersededAutonomousTurn;autonomousSalvage;lastBackgroundTask;toolLabels=new Map;armedTasks=new Map;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 Yn;filesEditedSeen=new Set;openToolCalls=new Map;agentChangeHandlers=[];retiringGenerationCost;retiringGenerationUsed;rotationLifetimeCost;agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];configOptionsHandlers=[];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??`${Ie}${Ba()}`,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),e.upstreamRespawned&&(this._upstreamRespawned=!0),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??cp,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){Mp(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=Da(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 f=`t_${zr()}`,m;try{m=await l.connection.request("hydra-acp/transformer/message",{token:f,phase:"response",method:r,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(p){this.logger?.warn(`transformer ${l.name} error on ${a}: ${p.message}`);continue}let h=m?.action??"continue";if(h==="stop")return;if(h==="processing"){let p=u,g=i,w=new Set(t),y=r;await new Promise(k=>{let b=setTimeout(()=>{this.pendingClaims.delete(f)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:f,transformerName:l.name}),this.runResponseChain(g,new Set([...w,l.name]),p+1,y).then(()=>k()).catch(()=>k()))},ns);typeof b.unref=="function"&&b.unref(),this.pendingClaims.set(f,{resolve:()=>k(),timer:b,transformerName:l.name,method:y,envelope:g,chainIdx:p,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),ka(i.update)&&this.armRecallInPlace().catch(u=>{this.logger?.warn(`armRecallInPlace failed: ${u.message}`)});let d=_p(i);if(d!==null){this.setAgentAdvertisedCommands(d);return}let c=Pp(i);if(c!==null){this.setAgentAdvertisedModes(c);return}if(this.noteModelVerbHint(pa(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)}async armRecallInPlace(){if(!this.historyStore)return;let e=await this.historyStore.getRecallTotalCount(this.sessionId).catch(()=>0);if(!(e<=(this._summarizedThroughEntry??0))){if(this._summarizedThroughEntry=e,this.persistWatermarkHook)try{this.persistWatermarkHook(e)}catch(t){this.logger?.warn(`armRecallInPlace: persistWatermarkHook failed: ${t.message}`)}this.broadcastQueueNotification("hydra-acp/context_self_compacted",{sessionId:this.sessionId})}}onAgentChange(e){this.agentChangeHandlers.push(e)}get attachedCount(){return this.clients.size}connectedClients(e){let t=[];for(let n of this.clients.values()){if(e&&n.clientId===e)continue;let r={clientId:n.clientId};n.clientInfo?.name&&(r.name=n.clientInfo.name),n.clientInfo?.version&&(r.version=n.clientInfo.version),t.push(r)}return t}get turnStartedAt(){return this.promptStartedAt}get inUnsolicitedTurn(){return this.unsolicitedTurn!==void 0}get agentPid(){return this.agent.pid}get awaitingInput(){return this.attentionFlags.size>0}async isQuiescedForSwap(){return await this.quiesceBlocker()===void 0}async quiesceBlocker(){if(this.agentTurnInFlight)return"the agent is still working; wait for the current turn to finish, then try again";if(this.unsolicitedTurn!==void 0)return"the agent is part-way through a turn it started by itself; wait for it to finish or interrupt it (^C), then try again";if(this.internalPromptCapture!==void 0)return"hydra is driving the agent right now (compaction seed or transcript injection); this clears by itself, so try again in a moment";if(this.modelChangeInFlight)return"a model change is still settling; try again in a moment";if(this.modeChangeInFlight)return"a mode change is still settling; try again in a moment";let e=this.pendingOneShotBackgroundTasks();if(e.length>0)return`${e.length} background task(s) still running (${e.join(", ")}); a swap would kill the agent process and abandon them. Wait for them to finish, or cancel them, then try again`;let t=await this.openToolCallIdsInHistory();if(t.length>0)return`${t.length} tool call(s) from an earlier turn never reported a result, so the session still reads as busy. ^C closes an abandoned chain; failing that it clears as new history accumulates`}isQuiescedSync(){return!(this.promptInFlight||this.unsolicitedTurn!==void 0||this.modeChangeInFlight||this.modelChangeInFlight)}async swapIntoWorkspace(e){await this.swapUpstream({...e.synopsis!==void 0?{artifact:e.synopsis}:{},note:e.note,framing:"swap",...e.title!==void 0?{title:e.title}:{},tailK:8,tailFloor:4,summarizedThroughEntry:e.historyLength,newCwd:e.cwd,reason:e.workspace!==void 0?"workspace-enter":"workspace-leave"}),this.workspace=e.workspace,e.left!==void 0?(this.formerWorkspace={path:e.left.path,sourceCwd:e.cwd,removed:e.left.removed},this.departureNoteSent=!1):this.formerWorkspace=void 0}async swapUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for swap: ${t}`);if(this.swapInFlight)throw new Error("a swap is already in progress for this session");this.swapInFlight=!0;try{await this.doSwapUpstream(e)}finally{this.swapInFlight=!1}}async doSwapUpstream(e){this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let t=this.agentId,n=e.newAgentId??this.agentId,r=n!==this.agentId,o=e.reason!==void 0&&e.reason!=="compaction"?e.reason:r?"agent-swap":"compaction",i=e.newCwd??this.cwd,a=this.agentArgs,d=this.forwardedEnv,c=this.currentModel,u=this.currentMode,l=this.spawnReplacementAgent;if(!l)throw new Error("agent spawning not configured for this session");let f=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],m=await l({agentId:n,cwd:i,agentArgs:a,...d?{forwardedEnv:d}:{},mcpServers:f});if(this.accumulateAndResetCost(),this.cwd=i,this.wireAgent(m.agent,{respawn:!0}),!r){let _=await yt({agent:m.agent,upstreamSessionId:m.upstreamSessionId,persistedModel:c,agentReportedModel:m.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(_.result,"model"),await ht({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(_){this.logger?.warn(`swapUpstream: historyStore.load failed: ${_.message}`)}let p=Br({...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:p}]});let _=this.internalPromptCapture;g=_.lastUsed,w=_.lastSize,this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${p.length} toolCalls=${_.toolCalls} thinkingChars=${_.thinkingChars} messageChars=${_.messageChars} used=${_.lastUsed??"?"} size=${_.lastSize??"?"} reply=${JSON.stringify(_.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(_){this.logger?.warn(`swapUpstream: persistWatermarkHook failed: ${_.message}`)}if(!r&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:y,...k!==void 0?{previousSummarizedThroughEntry:k}:{},...e.runId!==void 0?{runId:e.runId}:{}})}catch(_){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${_.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: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=I.length>0?`
|
|
37
|
+
`;await ze.writeFile(t,n,"utf8")}async function Da(s){let e=x.queueFile(s),t;try{t=await ze.readFile(e,"utf8")}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t.split(`
|
|
38
|
+
`))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 ja(s){let e=x.queueFile(s);await ze.unlink(e).catch(()=>{})}import*as Ga from"fs/promises";var Ja="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Va=za(Ja,16),Qr=za(Ja,16),pp=20,gp=20,mp=5,hp=32,Se="hydra_session_";function Je(){return`m_${Va()}`}function Xe(s){let e=dt(s)?.localId??s;return e.startsWith(Se)?e.slice(Se.length):e}var Ha=["start","merge","apply","sync","stop","detach","discard","clean","status"],yp=1e3,rs=300*1e3,wp=64,kp=new Set(["task-notification","peer","coordinator","observer","observer-activity"]);function vp(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"&&kp.has(r)}function La(s){let e=s?.update;return!!e&&typeof e=="object"&&e.sessionUpdate==="usage_update"}function bp(s){let e=s?.update;return!!e&&typeof e=="object"&&e.sessionUpdate==="tool_call_update"}function Sp(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 Yr=120;function Ip(s){let e=s.split(`
|
|
39
|
+
`).map(t=>t.trim()).filter(t=>t!=="");return e.length===0?"":e[e.length-1]}var Ap=128,Cp=new Set(["local_bash"]),Rp=1e3,qt=class s{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=We;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;lastUnsolicitedCancelAt=0;cancelReopenStreak=0;static UNSOLICITED_REOPEN_WINDOW_MS=1e4;static UNSOLICITED_REOPEN_LIMIT=3;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}_titleSeedPending=!0;_upstreamRespawned=!1;promptStartedAt;turnRanTool=!1;unsolicitedTurn;pendingSteerDetach;supersededAutonomousTurn;autonomousSalvage;lastBackgroundTask;toolLabels=new Map;armedTasks=new Map;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 Map;agentChangeHandlers=[];retiringGenerationCost;retiringGenerationUsed;rotationLifetimeCost;agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];configOptionsHandlers=[];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??`${Se}${Va()}`,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),e.upstreamRespawned&&(this._upstreamRespawned=!0),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??yp,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){Hp(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 f=`t_${Qr()}`,m;try{m=await l.connection.request("hydra-acp/transformer/message",{token:f,phase:"response",method:r,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(p){this.logger?.warn(`transformer ${l.name} error on ${a}: ${p.message}`);continue}let h=m?.action??"continue";if(h==="stop")return;if(h==="processing"){let p=u,g=i,w=new Set(t),y=r;await new Promise(k=>{let b=setTimeout(()=>{this.pendingClaims.delete(f)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:f,transformerName:l.name}),this.runResponseChain(g,new Set([...w,l.name]),p+1,y).then(()=>k()).catch(()=>k()))},rs);typeof b.unref=="function"&&b.unref(),this.pendingClaims.set(f,{resolve:()=>k(),timer:b,transformerName:l.name,method:y,envelope:g,chainIdx:p,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),Aa(i.update)&&this.armRecallInPlace().catch(u=>{this.logger?.warn(`armRecallInPlace failed: ${u.message}`)});let d=Lp(i);if(d!==null){this.setAgentAdvertisedCommands(d);return}let c=jp(i);if(c!==null){this.setAgentAdvertisedModes(c);return}if(this.noteModelVerbHint(wa(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)}async armRecallInPlace(){if(!this.historyStore)return;let e=await this.historyStore.getRecallTotalCount(this.sessionId).catch(()=>0);if(!(e<=(this._summarizedThroughEntry??0))){if(this._summarizedThroughEntry=e,this.persistWatermarkHook)try{this.persistWatermarkHook(e)}catch(t){this.logger?.warn(`armRecallInPlace: persistWatermarkHook failed: ${t.message}`)}this.broadcastQueueNotification("hydra-acp/context_self_compacted",{sessionId:this.sessionId})}}onAgentChange(e){this.agentChangeHandlers.push(e)}get attachedCount(){return this.clients.size}connectedClients(e){let t=[];for(let n of this.clients.values()){if(e&&n.clientId===e)continue;let r={clientId:n.clientId};n.clientInfo?.name&&(r.name=n.clientInfo.name),n.clientInfo?.version&&(r.version=n.clientInfo.version),t.push(r)}return t}get turnStartedAt(){return this.promptStartedAt}get inUnsolicitedTurn(){return this.unsolicitedTurn!==void 0}get agentPid(){return this.agent.pid}get awaitingInput(){return this.attentionFlags.size>0}async isQuiescedForSwap(){return await this.quiesceBlocker()===void 0}async quiesceBlocker(){if(this.agentTurnInFlight)return"the agent is still working; wait for the current turn to finish, then try again";if(this.unsolicitedTurn!==void 0)return"the agent is part-way through a turn it started by itself; wait for it to finish or interrupt it (^C), then try again";if(this.internalPromptCapture!==void 0)return"hydra is driving the agent right now (compaction seed or transcript injection); this clears by itself, so try again in a moment";if(this.modelChangeInFlight)return"a model change is still settling; try again in a moment";if(this.modeChangeInFlight)return"a mode change is still settling; try again in a moment";let e=this.pendingOneShotBackgroundTasks();if(e.length>0)return`${e.length} background task(s) still running (${e.join(", ")}); a swap would kill the agent process and abandon them. Wait for them to finish, or cancel them, then try again`;let t=await this.openToolCallIdsInHistory();if(t.length>0)return`${t.length} tool call(s) from an earlier turn never reported a result, so the session still reads as busy. ^C closes an abandoned chain; failing that it clears as new history accumulates`}isQuiescedSync(){return!(this.promptInFlight||this.unsolicitedTurn!==void 0||this.modeChangeInFlight||this.modelChangeInFlight)}async swapIntoWorkspace(e){await this.swapUpstream({...e.synopsis!==void 0?{artifact:e.synopsis}:{},note:e.note,framing:"swap",...e.title!==void 0?{title:e.title}:{},tailK:8,tailFloor:4,summarizedThroughEntry:e.historyLength,newCwd:e.cwd,reason:e.workspace!==void 0?"workspace-enter":"workspace-leave"}),this.workspace=e.workspace,e.left!==void 0?(this.formerWorkspace={path:e.left.path,sourceCwd:e.cwd,removed:e.left.removed},this.departureNoteSent=!1):this.formerWorkspace=void 0}async swapUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for swap: ${t}`);if(this.swapInFlight)throw new Error("a swap is already in progress for this session");this.swapInFlight=!0;try{await this.doSwapUpstream(e)}finally{this.swapInFlight=!1}}async doSwapUpstream(e){this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let t=this.agentId,n=e.newAgentId??this.agentId,r=n!==this.agentId,o=e.reason!==void 0&&e.reason!=="compaction"?e.reason:r?"agent-swap":"compaction",i=e.newCwd??this.cwd,a=this.agentArgs,d=this.forwardedEnv,c=this.currentModel,u=this.currentMode,l=this.spawnReplacementAgent;if(!l)throw new Error("agent spawning not configured for this session");let f=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],m=await l({agentId:n,cwd:i,agentArgs:a,...d?{forwardedEnv:d}:{},mcpServers:f});if(this.accumulateAndResetCost(),this.cwd=i,this.wireAgent(m.agent,{respawn:!0}),!r){let _=await wt({agent:m.agent,upstreamSessionId:m.upstreamSessionId,persistedModel:c,agentReportedModel:m.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(_.result,"model"),await yt({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(_){this.logger?.warn(`swapUpstream: historyStore.load failed: ${_.message}`)}let p=Vr({...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:p}]});let _=this.internalPromptCapture;g=_.lastUsed,w=_.lastSize,this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${p.length} toolCalls=${_.toolCalls} thinkingChars=${_.thinkingChars} messageChars=${_.messageChars} used=${_.lastUsed??"?"} size=${_.lastSize??"?"} reply=${JSON.stringify(_.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(_){this.logger?.warn(`swapUpstream: persistWatermarkHook failed: ${_.message}`)}if(!r&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:y,...k!==void 0?{previousSummarizedThroughEntry:k}:{},...e.runId!==void 0?{runId:e.runId}:{}})}catch(_){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${_.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: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=I.length>0?`
|
|
40
40
|
Stopped ${I.length} background task(s) with the previous agent: ${I.join(", ")}. Re-arm anything still needed.
|
|
41
41
|
`:"",R=(e.reason==="workspace-enter"||e.reason==="workspace-leave"?"":r?`
|
|
42
42
|
Switched to ${n}.
|
|
43
43
|
`:`
|
|
44
44
|
Compaction completed.
|
|
45
|
-
`)+v,T=R===""?void 0:R;if(T!==void 0){let _=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",_).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 yt({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedModel:d,agentReportedModel:u.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(l.result,"model"),await ht({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedMode:c,agentReportedMode:u.initialMode,logger:this.logger}),u.agent.connection.drainBuffered("session/update");let f=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(f,"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 yt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:t,agentReportedModel:r.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(o.result,"model"),await ht({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=op){if(!this.historyStore)return[];let t=await this.historyStore.load(this.sessionId),n=t.length>e?t.slice(-e):t,r=new Set,o=new Set;for(let i of n){let d=i.params?.update;if(!d||typeof d.sessionUpdate!="string")continue;let c=d.sessionUpdate,u=typeof d.toolCallId=="string"?d.toolCallId:void 0;if(!u)continue;let l=d.status;c==="tool_call"&&r.add(u),(c==="tool_call"||c==="tool_call_update")&&(l==="completed"||l==="failed")&&o.add(u)}return[...r].filter(i=>!o.has(i))}async getHistorySnapshot(e="inline",t){return this.historyStore?this.historyStore.load(this.sessionId,{tools:e,...t!==void 0?{maxEntries:t}:{}}).catch(()=>[]):[]}async*iterRecallNewestFirst(){this.historyStore&&(yield*this.historyStore.iterRecallNewestFirst(this.sessionId))}async getRecallTotalCount(){return this.historyStore?this.historyStore.getRecallTotalCount(this.sessionId).catch(()=>0):0}async sliceRecallHistory(e,t){return this.historyStore?(await this.historyStore.rangeSlice(this.sessionId,e,t).catch(()=>[])).map(r=>r.entry):[]}onBroadcast(e){return this.broadcastHandlers.push(e),()=>{let t=this.broadcastHandlers.indexOf(e);t>=0&&this.broadcastHandlers.splice(t,1)}}broadcastClientUpdate(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:e});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}broadcastCompactionPhase(e){let t=e.phase;t==="swapped"||t==="failed"||t==="rolled_back"?this._liveCompactionPhase=void 0:this._liveCompactionPhase=e;let n=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_compaction",...e}});for(let r of this.broadcastHandlers)try{r({method:"session/update",params:n,recordedAt:Date.now()})}catch{}for(let r of this.clients.values())r.connection.notify("session/update",n).catch(()=>{});this.notifyChain("compaction",{...e})}broadcastWorkspacePhase(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_workspace",...e}});for(let n of this.broadcastHandlers)try{n({method:"session/update",params:t,recordedAt:Date.now()})}catch{}for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{});this.notifyChain("workspace",{...e})}broadcastSyntheticText(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:e},_meta:{"hydra-acp":{synthetic:!0}}}});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}attach(e,t,n={}){if(this.closed)throw Se(new Error("session is closed"),E.SessionNotFound);if(this.clients.has(e.clientId))throw Se(new Error(`client ${e.clientId} is already attached`),E.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:Zn(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=Op(o.filter(d=>!pn(d.method,d.params)),r),a=this.buildStateSnapshotReplay();if(e==="after_message"){let d=t.afterSeq!==void 0?Fp(i,t.afterSeq):t.afterMessageId?rs(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&&ts(e,r.path)&&(this.logger?.warn?.(`STALE WORKSPACE WRITE on session ${this.sessionId}: the agent wrote ${e}, which is inside the workspace this session already left. That work will not reach ${r.sourceCwd}.`),this.notifyChain("workspace.staleWrite",{path:e,formerWorkspacePath:r.path,sourceCwd:r.sourceCwd,toolCallId:t}));return}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=ja(e,o=>qr(o,t.path)?(n=!0,Wr(o,t.path,t.sourceCwd).text):o);if(!this.departureNoteSent||n){let o=Ta({sourceCwd:t.sourceCwd,formerWorkspacePath:t.path,removed:t.removed});r=Vr(r,`${o}
|
|
45
|
+
`)+v,T=R===""?void 0:R;if(T!==void 0){let _=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:T},_meta:{"hydra-acp":{synthetic:!0}}}});for(let U of this.clients.values())U.connection.notify("session/update",_).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 wt({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedModel:d,agentReportedModel:u.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(l.result,"model"),await yt({agent:u.agent,upstreamSessionId:u.upstreamSessionId,persistedMode:c,agentReportedMode:u.initialMode,logger:this.logger}),u.agent.connection.drainBuffered("session/update");let f=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(f,"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 wt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:t,agentReportedModel:r.initialModel,logger:this.logger});this.applyAgentConfigOptionResponse(o.result,"model"),await yt({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=pp){if(!this.historyStore)return[];let t=await this.historyStore.load(this.sessionId),n=t.length>e?t.slice(-e):t,r=new Set,o=new Set;for(let i of n){let d=i.params?.update;if(!d||typeof d.sessionUpdate!="string")continue;let c=d.sessionUpdate,u=typeof d.toolCallId=="string"?d.toolCallId:void 0;if(!u)continue;let l=d.status;c==="tool_call"&&r.add(u),(c==="tool_call"||c==="tool_call_update")&&(l==="completed"||l==="failed")&&o.add(u)}return[...r].filter(i=>!o.has(i))}async getHistorySnapshot(e="inline",t){return this.historyStore?this.historyStore.load(this.sessionId,{tools:e,...t!==void 0?{maxEntries:t}:{}}).catch(()=>[]):[]}async*iterRecallNewestFirst(){this.historyStore&&(yield*this.historyStore.iterRecallNewestFirst(this.sessionId))}async getRecallTotalCount(){return this.historyStore?this.historyStore.getRecallTotalCount(this.sessionId).catch(()=>0):0}async sliceRecallHistory(e,t){return this.historyStore?(await this.historyStore.rangeSlice(this.sessionId,e,t).catch(()=>[])).map(r=>r.entry):[]}onBroadcast(e){return this.broadcastHandlers.push(e),()=>{let t=this.broadcastHandlers.indexOf(e);t>=0&&this.broadcastHandlers.splice(t,1)}}broadcastClientUpdate(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:e});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}broadcastCompactionPhase(e){let t=e.phase;t==="swapped"||t==="failed"||t==="rolled_back"?this._liveCompactionPhase=void 0:this._liveCompactionPhase=e;let n=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_compaction",...e}});for(let r of this.broadcastHandlers)try{r({method:"session/update",params:n,recordedAt:Date.now()})}catch{}for(let r of this.clients.values())r.connection.notify("session/update",n).catch(()=>{});this.notifyChain("compaction",{...e})}broadcastWorkspacePhase(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_workspace",...e}});for(let n of this.broadcastHandlers)try{n({method:"session/update",params:t,recordedAt:Date.now()})}catch{}for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{});this.notifyChain("workspace",{...e})}broadcastSyntheticText(e){let t=this.rewriteForClient({sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:e},_meta:{"hydra-acp":{synthetic:!0}}}});for(let n of this.clients.values())n.connection.notify("session/update",t).catch(()=>{})}attach(e,t,n={}){if(this.closed)throw be(new Error("session is closed"),E.SessionNotFound);if(this.clients.has(e.clientId))throw be(new Error(`client ${e.clientId} is already attached`),E.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:ts(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=Bp(o.filter(d=>!gn(d.method,d.params)),r),a=this.buildStateSnapshotReplay();if(e==="after_message"){let d=t.afterSeq!==void 0?Wp(i,t.afterSeq):t.afterMessageId?is(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&&ss(e,r.path)&&(this.logger?.warn?.(`STALE WORKSPACE WRITE on session ${this.sessionId}: the agent wrote ${e}, which is inside the workspace this session already left. That work will not reach ${r.sourceCwd}.`),this.notifyChain("workspace.staleWrite",{path:e,formerWorkspacePath:r.path,sourceCwd:r.sourceCwd,toolCallId:t}));return}Na(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=Wa(e,o=>Kr(o,t.path)?(n=!0,Gr(o,t.path,t.sourceCwd).text):o);if(!this.departureNoteSent||n){let o=Oa({sourceCwd:t.sourceCwd,formerWorkspacePath:t.path,removed:t.removed});r=Xr(r,`${o}
|
|
46
46
|
|
|
47
|
-
`),this.departureNoteSent=!0}return r}applyWorkspacePromptRewrite(e){let t=this.workspace;if(t===void 0)return this.applyDepartedPromptRewrite(e);let n=!1,r=
|
|
47
|
+
`),this.departureNoteSent=!0}return r}applyWorkspacePromptRewrite(e){let t=this.workspace;if(t===void 0)return this.applyDepartedPromptRewrite(e);let n=!1,r=Wa(e,i=>Kr(i,t.sourceCwd)?(n=!0,Gr(i,t.sourceCwd,t.path).text):i);if(!this.workspacePreambleSent||n){let i=Fa({workspacePath:t.path,sourceCwd:t.sourceCwd,notes:this.workspaceNotes,...this.workspacePreambleSent?{reassert:!0}:{}});r=Xr(r,`${i}
|
|
48
48
|
|
|
49
|
-
`),this.workspacePreambleSent=!0}return r}async prompt(e,t,n,r){let o=this.clients.get(e);if(!o)throw Se(new Error("client not attached"),E.SessionNotFound);if(this.closing)throw Se(new Error("session is closing; new prompts cannot be accepted"),E.SessionClosing);let i=Je();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(rt((t??{})._meta).ancillary===!0)&&this._interactive!==!0){this._interactive=!0,this.cancelOrphanTimer();for(let d of this.interactiveHandlers)try{d(!0)}catch{}}return this.enqueueUserPrompt(o,t,i,n,r)}broadcastPromptReceived(e){this.closeUnsolicitedTurn("superseded",`prompt:${e.messageId}`);let t={clientId:e.originator.clientId};e.originator.name&&(t.name=e.originator.name),e.originator.version&&(t.version=e.originator.version),e.originator.fromSession&&(t.fromSession=e.originator.fromSession),e.originator.fromSessionTitle&&(t.fromSessionTitle=e.originator.fromSessionTitle),e.originator.fromLabel&&(t.fromLabel=e.originator.fromLabel),e.originator.depth!==void 0&&(t.depth=e.originator.depth),this.promptStartedAt=Date.now(),this.turnRanTool=!1,this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"prompt_received",messageId:e.messageId,prompt:e.prompt,sentBy:t}},e.clientId);let n=wt(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=rt(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),Or(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.armOpenToolCalls(),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(fp(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&&Fa(e)&&(this.pendingSteerDetach=void 0),!pn("session/update",e)&&(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||pp(e)||this.openUnsolicitedTurn()))}}steerCausedTurnTerminal(e){return this.unsolicitedTurn?.steerCaused!==!0?!1:Fa(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=Rp(t._meta);this.rememberToolLabel(n,t,r,o),this.noteBackgroundTaskStopped(t,r,o);let i=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:Cp(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,f=Ap(t.title,o,r)||u?.repeating===!0;this.armedTasks.set(n,{label:d,...l!==void 0?{taskId:l}:{},repeating:f,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=>yp.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);for(let[n,r]of this.armedTasks)r.openToolCall===!0&&this.openToolCalls.delete(n);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,Jr),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,Jr),fromDescription:!1})}for(;this.toolLabels.size>hp;){let i=this.toolLabels.keys().next().value;if(i===void 0)break;this.toolLabels.delete(i)}}openUnsolicitedTurn(){let e=Date.now();if(this.lastUnsolicitedCancelAt!==0&&e-this.lastUnsolicitedCancelAt<=s.UNSOLICITED_REOPEN_WINDOW_MS?this.cancelReopenStreak+=1:this.cancelReopenStreak=0,this.lastUnsolicitedCancelAt=0,this.cancelReopenStreak>=s.UNSOLICITED_REOPEN_LIMIT){this.escalateUnresponsiveCancel();return}let t=this.lastBackgroundTask,n=!1;for(let[i,a]of this.armedTasks)a.repeating||a.openToolCall===!0||(this.armedTasks.delete(i),n=!0);n&&this.onArmedTasksChanged();let r={messageId: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,wp);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,e==="cancelled"?this.lastUnsolicitedCancelAt=Date.now():(this.lastUnsolicitedCancelAt=0,this.cancelReopenStreak=0),this.logger?.info(`session ${this.sessionId} unsolicited turn ${n.messageId} closed reason=${e} durationMs=${r}`+(t?` by=${t}`:"")+(n.cause?` cause=${JSON.stringify(n.cause.label)}`:"")),e==="superseded"&&(this.supersededAutonomousTurn={turnMessageId:n.messageId,cause:n.cause,supersededAt:Date.now()}),this.recordCurrentUsageSnapshot(),!this.closed&&(e==="cancelled"?this.closeOpenToolCalls("cancelled"):e==="completed"&&this.armOpenToolCalls(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"_hydra_turn_ended",messageId: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:{[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>up;){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>dp;){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 Se(new Error("client not attached"),E.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 Se(new Error("client not attached"),E.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=wt(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 Se(new Error("client not attached"),E.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_${zr()}`,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 f=l?.action??"continue";if(f==="stop")return o==="notification"?void 0:l?.payload??Gr(e);if(f==="continue"){l?.payload&&typeof l.payload=="object"&&(i=l.payload),n.add(d.name);continue}if(f==="processing"){let m=a,h=i,p=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([...p,d.name]),m+1,o).then(g).catch(()=>g(o==="notification"?void 0:Gr(e))))},ns);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(u,{resolve:g,timer:w,transformerName:d.name,method:e,envelope:h,chainIdx:m,originatedBy:p,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 at({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??We,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_${zr()}`,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(f){this.logger?.warn(`transformer ${d.name} error on ${i}: ${f.message}`);continue}let l=u?.action??"continue";if(l==="stop")return{shortCircuit:!0,payload:u?.payload??Lp(e)};if(l==="continue"){u?.payload&&typeof u.payload=="object"&&(o=u.payload),n.add(d.name);continue}if(l==="processing"){let f=a,m=o,h=new Set(n),p=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(p,m,new Set([...h,d.name]),f+1).then(g).catch(()=>g({shortCircuit:!1,envelope:m})))},ns);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(c,{resolve:y=>g({shortCircuit:!0,payload:y}),timer:w,transformerName:d.name,method:p,envelope:m,chainIdx:f,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):ns,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:Gr(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},f=this.insertEntryAt(l,"tail");this.persistRewrite(),this.broadcastQueueAdded(l,{position:f}),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||rt((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let r=wt((e??{}).prompt),o=Qr(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=gn(n.availableModels);r.length>0&&this.setAgentAdvertisedModels(r);let o=typeof n.currentModel=="string"?n.currentModel:typeof n.model=="string"?n.model:void 0;if(o===void 0)return!0;let i=o.trim();if(!i||i===this.currentModel)return!0;this.logger?.info(`live current_model_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(i)}`),this.currentModel=i;for(let a of this.modelHandlers)try{a(i)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentConfigOption(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="config_option_update")return!1;let r=n.configOptions;if(!Array.isArray(r))return!0;for(let i of r)this.applyOneConfigOptionEntry(i);let o=new Set(r.filter(i=>!!i&&typeof i=="object").map(i=>typeof i.id=="string"?i.id.trim():void 0).filter(i=>!!i&&i!=="model"&&i!=="mode"&&i!=="agent"));return this.agentAdvertisedConfigOptions=this.agentAdvertisedConfigOptions.filter(i=>o.has(i.id)),this.fireConfigOptionsHandlers(),!0}applyAgentConfigOptionResponse(e,t){let n=e?.configOptions;if(!Array.isArray(n))return!1;let r=JSON.stringify(this.agentAdvertisedConfigOptions);for(let o of n){let i=o?.id;i==="model"||i==="mode"||i==="agent"||this.applyOneConfigOptionEntry(o)}if(gp(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 p=gn(t.options);p.length>0&&this.setAgentAdvertisedModels(p);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 p=ss(t.options);p.length>0&&this.setAgentAdvertisedModes(p);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=Kr(t.options);if(r.length===0)return;let o=t.name,i=typeof o=="string"&&o.trim()?o.trim():n,a=t.category,d=typeof a=="string"&&a.trim()?a.trim():"other",c=t.description,u=typeof c=="string"&&c.trim()?c.trim():void 0,l=t.currentValue,f=typeof l=="string"&&l.trim()?l.trim():r[0].value,m={id:n,name:i,category:d,type:"select",currentValue:f,options:r,...u?{description:u}:{}},h=this.agentAdvertisedConfigOptions.findIndex(p=>p.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(xp(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(Ep(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(",")}]`),Tp(this.agentAdvertisedModels,e)){this.broadcastAvailableModels();return}this.agentAdvertisedModels=e;for(let t of this.agentModelsHandlers)try{t(e)}catch{}this.broadcastAvailableModels()}onAgentCommandsChange(e){this.agentCommandsHandlers.push(e)}onAgentModesChange(e){this.agentModesHandlers.push(e)}onAgentModelsChange(e){this.agentModelsHandlers.push(e)}onConfigOptionsChange(e){this.configOptionsHandlers.push(e)}extraConfigOptionValues(){return Object.fromEntries(this.agentAdvertisedConfigOptions.map(e=>[e.id,e.currentValue]))}onModelChange(e){this.modelHandlers.push(e)}onModeChange(e){this.modeHandlers.push(e)}onInteractiveChange(e){this.interactiveHandlers.push(e)}onPriorityChange(e){this.priorityHandlers.push(e)}setPriority(e){let t=e===void 0||e<=0?void 0:Math.floor(e);if(t!==this._priority){this._priority=t,this.updatedAt=Date.now();for(let n of this.priorityHandlers)try{n(t)}catch{}}}applyModelChange(e){let t=e.trim();if(t){this.modelChangeInFlight=!0;try{if(t!==this.currentModel){this.logger?.info(`applyModelChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(t)}`),this.currentModel=t;for(let r of this.modelHandlers)try{r(t)}catch{}}let n={sessionUpdate:"_hydra_current_model_update",currentModel:t};this.agentAdvertisedModels.length>0&&(n.availableModels=[...this.agentAdvertisedModels]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modelChangeInFlight=!1}}}applyModeChange(e){let t=e.trim();if(t){this.modeChangeInFlight=!0;try{if(t!==this.currentMode){this.logger?.info(`applyModeChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(t)}`),this.currentMode=t;for(let r of this.modeHandlers)try{r(t)}catch{}}let n={sessionUpdate:"current_mode_update",currentModeId:t};this.agentAdvertisedModes.length>0&&(n.availableModes=[...this.agentAdvertisedModes]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modeChangeInFlight=!1}}}buildConfigOptions(){let e=[];if(this.agentAdvertisedModels.length>0){let r=this.agentAdvertisedModels.map(i=>({value:i.modelId,name:i.name??i.modelId,...i.description!==void 0?{description:i.description}:{}}));this.currentModel&&!r.some(i=>i.value===this.currentModel)&&r.unshift({value:this.currentModel,name:this.currentModel});let o=this.currentModel||r[0].value;e.push({id:"model",name:"Model",category:"model",type:"select",currentValue:o,options:r})}if(this.agentAdvertisedModes.length>0){let r=this.agentAdvertisedModes.map(i=>({value:i.id,name:i.name??i.id,...i.description!==void 0?{description:i.description}:{}}));this.currentMode&&!r.some(i=>i.value===this.currentMode)&&r.unshift({value:this.currentMode,name:this.currentMode});let o=this.currentMode||r[0].value;e.push({id:"mode",name:"Session Mode",category:"mode",type:"select",currentValue:o,options:r})}let n=(this.availableAgentsFn?.()??[]).map(r=>({value:r.id,name:r.name??r.id,...r.description!==void 0?{description:r.description}:{}}));return n.some(r=>r.value===this.agentId)||n.unshift({value:this.agentId,name:this.agentId}),e.push({id:"agent",name:"Agent",category:"_hydra_agent",type:"select",currentValue:this.agentId,options:n}),e.push(...this.agentAdvertisedConfigOptions),e}broadcastConfigOptions(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"config_option_update",configOptions:this.buildConfigOptions()}}),this.fireConfigOptionsHandlers()}fireConfigOptionsHandlers(){for(let e of this.configOptionsHandlers)try{e(this.agentAdvertisedConfigOptions)}catch{}}mergeAgentOptionIntoEnvelope(e){if(!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let n=t.update,r=Array.isArray(n.configOptions)?[...n.configOptions]:[];if(r.some(a=>a&&typeof a=="object"&&a.id==="agent"))return e;let i=this.buildConfigOptions().find(a=>a.id==="agent");return i?{...t,update:{...n,configOptions:[...r,i]}}:e}onUsageChange(e){this.usageHandlers.push(e)}mergedAvailableCommands(){let e=this.daemonTopLevelCommands(),t=this.aliasableBareVerbs();for(let n of jt){if(t.get(n.verb)!=="__hydra__")continue;let r=n.argsHint?`${n.verb} ${n.argsHint}`:n.verb;e.push({name:r,description:`Alias for '/hydra ${n.verb}': ${n.description}`})}if(this.extensionCommands)for(let{name:n,command:r}of this.extensionCommands.list()){let o=r.verb?`hydra ${n} ${r.verb}`:`hydra ${n}`,a={name:r.argsHint?`${o} ${r.argsHint}`:o};r.description&&(a.description=r.description),e.push(a);let d=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 jt)e.has(i.verb)||n.set(i.verb,"__hydra__");if(!this.extensionCommands)return n;let r=new Map,o=new Set;for(let{name:i}of this.extensionCommands.list()){if(o.has(i))continue;o.add(i);let a=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(jt.some(l=>l.verb===o))switch(o){case"title":return a?this.runTitleCommandInline(i):this.runTitleCommand(i);case"agent":return this.runAgentCommandInline(i);case"config":return this.handleConfigCommand(`/config ${i}`);case"kill":return this.runKillCommand();case"workspace":return this.runWorkspaceCommand(i);case"restart":return a?this.runRestartCommandInline():this.runRestartCommand();case"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=E.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=jt.map(l=>l.verb);if(this.extensionCommands){let l=new Set;for(let{name:f}of this.extensionCommands.list())l.has(f)||(c.push(f),l.add(f))}let u=new Error(`unknown /hydra verb: ${o} (known: ${c.join(", ")})`);throw u.code=E.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(p=>p.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,f=!1;try{let h=r.connection.request("hydra-acp/commands/invoke",d),p=await Promise.race([h,u]);if(p&&typeof p=="object"&&p.stopReason==="cancelled"&&"reason"in p)return f=!0,this.logger?.info(`extension ${e} ${i} cancelled (cancelExtensionDispatch); abandoning in-flight commands/invoke`),{stopReason:"cancelled"};l=p}catch(h){return this.emitExtensionReply(`${e} ${i}: ${h.message}`)}finally{n!==void 0&&!f&&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:`
|
|
49
|
+
`),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"),E.SessionNotFound);if(this.closing)throw be(new Error("session is closing; new prompts cannot be accepted"),E.SessionClosing);let i=Je();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(rt((t??{})._meta).ancillary===!0)&&this._interactive!==!0){this._interactive=!0,this.cancelOrphanTimer();for(let d of this.interactiveHandlers)try{d(!0)}catch{}}return this.enqueueUserPrompt(o,t,i,n,r)}broadcastPromptReceived(e){this.closeUnsolicitedTurn("superseded",`prompt:${e.messageId}`);let t={clientId:e.originator.clientId};e.originator.name&&(t.name=e.originator.name),e.originator.version&&(t.version=e.originator.version),e.originator.fromSession&&(t.fromSession=e.originator.fromSession),e.originator.fromSessionTitle&&(t.fromSessionTitle=e.originator.fromSessionTitle),e.originator.fromLabel&&(t.fromLabel=e.originator.fromLabel),e.originator.depth!==void 0&&(t.depth=e.originator.depth),this.promptStartedAt=Date.now(),this.turnRanTool=!1,this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"prompt_received",messageId:e.messageId,prompt:e.prompt,sentBy:t}},e.clientId);let n=kt(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=rt(t?._meta).salvaged;a!==void 0&&(i._meta={[ce]:{salvaged:a}}),this.supersededAutonomousTurn=void 0;let d=this.amendInProgress;if(d&&n!==void 0&&d.cancelledMessageId===n&&(i._meta={[ce]:{...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),Hr(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.armOpenToolCalls(),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(vp(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&&La(e)&&(this.pendingSteerDetach=void 0),!gn("session/update",e)&&(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||bp(e)||this.openUnsolicitedTurn()))}}steerCausedTurnTerminal(e){return this.unsolicitedTurn?.steerCaused!==!0?!1:La(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=Op(t._meta);this.rememberToolLabel(n,t,r,o),this.noteBackgroundTaskStopped(t,r,o);let i=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:$p(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,f=_p(t.title,o,r)||u?.repeating===!0;this.armedTasks.set(n,{label:d,...l!==void 0?{taskId:l}:{},repeating:f,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=>Cp.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);for(let[n,r]of this.armedTasks)r.openToolCall===!0&&this.openToolCalls.delete(n);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,Yr),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,Yr),fromDescription:!1})}for(;this.toolLabels.size>Ap;){let i=this.toolLabels.keys().next().value;if(i===void 0)break;this.toolLabels.delete(i)}}openUnsolicitedTurn(){let e=Date.now();if(this.lastUnsolicitedCancelAt!==0&&e-this.lastUnsolicitedCancelAt<=s.UNSOLICITED_REOPEN_WINDOW_MS?this.cancelReopenStreak+=1:this.cancelReopenStreak=0,this.lastUnsolicitedCancelAt=0,this.cancelReopenStreak>=s.UNSOLICITED_REOPEN_LIMIT){this.escalateUnresponsiveCancel();return}let t=this.lastBackgroundTask,n=!1;for(let[i,a]of this.armedTasks)a.repeating||a.openToolCall===!0||(this.armedTasks.delete(i),n=!0);n&&this.onArmedTasksChanged();let r={messageId: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,Rp);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,e==="cancelled"?this.lastUnsolicitedCancelAt=Date.now():(this.lastUnsolicitedCancelAt=0,this.cancelReopenStreak=0),this.logger?.info(`session ${this.sessionId} unsolicited turn ${n.messageId} closed reason=${e} durationMs=${r}`+(t?` by=${t}`:"")+(n.cause?` cause=${JSON.stringify(n.cause.label)}`:"")),e==="superseded"&&(this.supersededAutonomousTurn={turnMessageId:n.messageId,cause:n.cause,supersededAt:Date.now()}),this.recordCurrentUsageSnapshot(),!this.closed&&(e==="cancelled"?this.closeOpenToolCalls("cancelled"):e==="completed"&&this.armOpenToolCalls(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"_hydra_turn_ended",messageId: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:{[ce]:{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>wp;){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>hp;){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"),E.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 be(new Error("client not attached"),E.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=kt(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 be(new Error("client not attached"),E.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_${Qr()}`,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 f=l?.action??"continue";if(f==="stop")return o==="notification"?void 0:l?.payload??Zr(e);if(f==="continue"){l?.payload&&typeof l.payload=="object"&&(i=l.payload),n.add(d.name);continue}if(f==="processing"){let m=a,h=i,p=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([...p,d.name]),m+1,o).then(g).catch(()=>g(o==="notification"?void 0:Zr(e))))},rs);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(u,{resolve:g,timer:w,transformerName:d.name,method:e,envelope:h,chainIdx:m,originatedBy:p,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 at({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??We,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_${Qr()}`,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(f){this.logger?.warn(`transformer ${d.name} error on ${i}: ${f.message}`);continue}let l=u?.action??"continue";if(l==="stop")return{shortCircuit:!0,payload:u?.payload??Gp(e)};if(l==="continue"){u?.payload&&typeof u.payload=="object"&&(o=u.payload),n.add(d.name);continue}if(l==="processing"){let f=a,m=o,h=new Set(n),p=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(p,m,new Set([...h,d.name]),f+1).then(g).catch(()=>g({shortCircuit:!1,envelope:m})))},rs);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(c,{resolve:y=>g({shortCircuit:!0,payload:y}),timer:w,transformerName:d.name,method:p,envelope:m,chainIdx:f,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):rs,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:Zr(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},f=this.insertEntryAt(l,"tail");this.persistRewrite(),this.broadcastQueueAdded(l,{position:f}),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||rt((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let r=kt((e??{}).prompt),o=to(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=mn(n.availableModels);r.length>0&&this.setAgentAdvertisedModels(r);let o=typeof n.currentModel=="string"?n.currentModel:typeof n.model=="string"?n.model:void 0;if(o===void 0)return!0;let i=o.trim();if(!i||i===this.currentModel)return!0;this.logger?.info(`live current_model_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(i)}`),this.currentModel=i;for(let a of this.modelHandlers)try{a(i)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentConfigOption(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="config_option_update")return!1;let r=n.configOptions;if(!Array.isArray(r))return!0;for(let i of r)this.applyOneConfigOptionEntry(i);let o=new Set(r.filter(i=>!!i&&typeof i=="object").map(i=>typeof i.id=="string"?i.id.trim():void 0).filter(i=>!!i&&i!=="model"&&i!=="mode"&&i!=="agent"));return this.agentAdvertisedConfigOptions=this.agentAdvertisedConfigOptions.filter(i=>o.has(i.id)),this.fireConfigOptionsHandlers(),!0}applyAgentConfigOptionResponse(e,t){let n=e?.configOptions;if(!Array.isArray(n))return!1;let r=JSON.stringify(this.agentAdvertisedConfigOptions);for(let o of n){let i=o?.id;i==="model"||i==="mode"||i==="agent"||this.applyOneConfigOptionEntry(o)}if(Sp(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 p=mn(t.options);p.length>0&&this.setAgentAdvertisedModels(p);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 p=os(t.options);p.length>0&&this.setAgentAdvertisedModes(p);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=eo(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,f=typeof l=="string"&&l.trim()?l.trim():r[0].value,m={id:n,name:i,category:d,type:"select",currentValue:f,options:r,...u?{description:u}:{}},h=this.agentAdvertisedConfigOptions.findIndex(p=>p.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(Fp(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(Np(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(",")}]`),Dp(this.agentAdvertisedModels,e)){this.broadcastAvailableModels();return}this.agentAdvertisedModels=e;for(let t of this.agentModelsHandlers)try{t(e)}catch{}this.broadcastAvailableModels()}onAgentCommandsChange(e){this.agentCommandsHandlers.push(e)}onAgentModesChange(e){this.agentModesHandlers.push(e)}onAgentModelsChange(e){this.agentModelsHandlers.push(e)}onConfigOptionsChange(e){this.configOptionsHandlers.push(e)}extraConfigOptionValues(){return Object.fromEntries(this.agentAdvertisedConfigOptions.map(e=>[e.id,e.currentValue]))}onModelChange(e){this.modelHandlers.push(e)}onModeChange(e){this.modeHandlers.push(e)}onInteractiveChange(e){this.interactiveHandlers.push(e)}onPriorityChange(e){this.priorityHandlers.push(e)}setPriority(e){let t=e===void 0||e<=0?void 0:Math.floor(e);if(t!==this._priority){this._priority=t,this.updatedAt=Date.now();for(let n of this.priorityHandlers)try{n(t)}catch{}}}applyModelChange(e){let t=e.trim();if(t){this.modelChangeInFlight=!0;try{if(t!==this.currentModel){this.logger?.info(`applyModelChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(t)}`),this.currentModel=t;for(let r of this.modelHandlers)try{r(t)}catch{}}let n={sessionUpdate:"_hydra_current_model_update",currentModel:t};this.agentAdvertisedModels.length>0&&(n.availableModels=[...this.agentAdvertisedModels]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modelChangeInFlight=!1}}}applyModeChange(e){let t=e.trim();if(t){this.modeChangeInFlight=!0;try{if(t!==this.currentMode){this.logger?.info(`applyModeChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(t)}`),this.currentMode=t;for(let r of this.modeHandlers)try{r(t)}catch{}}let n={sessionUpdate:"current_mode_update",currentModeId:t};this.agentAdvertisedModes.length>0&&(n.availableModes=[...this.agentAdvertisedModes]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modeChangeInFlight=!1}}}buildConfigOptions(){let e=[];if(this.agentAdvertisedModels.length>0){let r=this.agentAdvertisedModels.map(i=>({value:i.modelId,name:i.name??i.modelId,...i.description!==void 0?{description:i.description}:{}}));this.currentModel&&!r.some(i=>i.value===this.currentModel)&&r.unshift({value:this.currentModel,name:this.currentModel});let o=this.currentModel||r[0].value;e.push({id:"model",name:"Model",category:"model",type:"select",currentValue:o,options:r})}if(this.agentAdvertisedModes.length>0){let r=this.agentAdvertisedModes.map(i=>({value:i.id,name:i.name??i.id,...i.description!==void 0?{description:i.description}:{}}));this.currentMode&&!r.some(i=>i.value===this.currentMode)&&r.unshift({value:this.currentMode,name:this.currentMode});let o=this.currentMode||r[0].value;e.push({id:"mode",name:"Session Mode",category:"mode",type:"select",currentValue:o,options:r})}let n=(this.availableAgentsFn?.()??[]).map(r=>({value:r.id,name:r.name??r.id,...r.description!==void 0?{description:r.description}:{}}));return n.some(r=>r.value===this.agentId)||n.unshift({value:this.agentId,name:this.agentId}),e.push({id:"agent",name:"Agent",category:"_hydra_agent",type:"select",currentValue:this.agentId,options:n}),e.push(...this.agentAdvertisedConfigOptions),e}broadcastConfigOptions(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"config_option_update",configOptions:this.buildConfigOptions()}}),this.fireConfigOptionsHandlers()}fireConfigOptionsHandlers(){for(let e of this.configOptionsHandlers)try{e(this.agentAdvertisedConfigOptions)}catch{}}mergeAgentOptionIntoEnvelope(e){if(!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let n=t.update,r=Array.isArray(n.configOptions)?[...n.configOptions]:[];if(r.some(a=>a&&typeof a=="object"&&a.id==="agent"))return e;let i=this.buildConfigOptions().find(a=>a.id==="agent");return i?{...t,update:{...n,configOptions:[...r,i]}}:e}onUsageChange(e){this.usageHandlers.push(e)}mergedAvailableCommands(){let e=this.daemonTopLevelCommands(),t=this.aliasableBareVerbs();for(let n of Lt){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 Lt)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(Lt.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=E.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=Lt.map(l=>l.verb);if(this.extensionCommands){let l=new Set;for(let{name:f}of this.extensionCommands.list())l.has(f)||(c.push(f),l.add(f))}let u=new Error(`unknown /hydra verb: ${o} (known: ${c.join(", ")})`);throw u.code=E.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(p=>p.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,f=!1;try{let h=r.connection.request("hydra-acp/commands/invoke",d),p=await Promise.race([h,u]);if(p&&typeof p=="object"&&p.stopReason==="cancelled"&&"reason"in p)return f=!0,this.logger?.info(`extension ${e} ${i} cancelled (cancelExtensionDispatch); abandoning in-flight commands/invoke`),{stopReason:"cancelled"};l=p}catch(h){return this.emitExtensionReply(`${e} ${i}: ${h.message}`)}finally{n!==void 0&&!f&&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:`
|
|
50
50
|
${e}
|
|
51
51
|
`},_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}):
|
|
52
52
|
${n.join(`
|
|
@@ -59,7 +59,7 @@ ${n}
|
|
|
59
59
|
`},_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 f=l.modelId===a?"\u25B6 ":" ",m=l.name&&l.name!==l.modelId?` ${l.name}`:"";return`${f}${l.modelId}${m}`});!c&&a&&u.unshift(`\u25B6 ${a}`),d=u.join(`
|
|
60
60
|
`)}return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
|
|
61
61
|
${d}
|
|
62
|
-
`},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}let n=
|
|
62
|
+
`},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}let n=Ut(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(f=>f.modelId),a=t.toLowerCase(),d=n.kind==="ambiguous"?n.candidates:i.filter(f=>f.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:`
|
|
63
63
|
${u}.
|
|
64
64
|
${l}:
|
|
65
65
|
${c.join(`
|
|
@@ -67,9 +67,9 @@ ${l}:
|
|
|
67
67
|
`},_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(`
|
|
68
68
|
`)}return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
|
|
69
69
|
${i}
|
|
70
|
-
`},_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
|
|
70
|
+
`},_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})`),E.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:`
|
|
71
71
|
_(no config options advertised yet)_
|
|
72
|
-
`},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let f=l.map(m=>
|
|
72
|
+
`},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let f=l.map(m=>qa(m));return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
|
|
73
73
|
${f.join(`
|
|
74
74
|
|
|
75
75
|
`)}
|
|
@@ -79,18 +79,18 @@ ${f.join(`
|
|
|
79
79
|
Available options:
|
|
80
80
|
${l}
|
|
81
81
|
`},_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:`
|
|
82
|
-
${
|
|
83
|
-
`},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let a=i.options.map(l=>l.value),d=
|
|
82
|
+
${qa(i)}
|
|
83
|
+
`},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"};let a=i.options.map(l=>l.value),d=Bt(r,a),c=r;if(d.kind==="resolved")c=d.modelId;else if(d.kind==="ambiguous"||d.kind==="unknown"){let l=r.toLowerCase(),f=d.kind==="ambiguous"?d.candidates:a.filter(g=>g.toLowerCase().includes(l)),m=f.length>0?f:a,h=d.kind==="ambiguous"?`"${r}" matches multiple values for "${n}": ${d.candidates.join(", ")}`:f.length>0?`"${r}" is not a valid value for "${n}". Did you mean`:`"${r}" is not a valid value for "${n}"`,p=d.kind==="ambiguous"||f.length===0?"Valid values":"Matching values";return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
|
|
84
84
|
${h}.
|
|
85
85
|
${p}:
|
|
86
86
|
${m.join(`
|
|
87
87
|
`)}
|
|
88
|
-
`},_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
|
|
89
|
-
`)),{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(!
|
|
90
|
-
`)}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=Br({synopsis:e,title:t,tail:n,tailK:ip,tailFloor:ap,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 Xn(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??Dt,Dt)),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=E.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),Or(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(()=>$a(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(()=>Wa.unlink(i).catch(()=>{}))}for(let o of this.closeHandlers)o(e)}get lastActivityAt(){return this.lastRecordedAt}setAttentionFlag(e,t,n){this._setAttentionFlag(e,t,n,!0)}_setAttentionFlag(e,t,n,r){let o=`${e}::${t}`,i=this.attentionFlags.get(o);if(i){if(JSON.stringify(i.payload)===JSON.stringify(n))return;this.attentionFlags.set(o,{...i,payload:n,raisedAt:i.raisedAt})}else this.attentionFlags.set(o,{source:e,reason:t,raisedAt:Date.now(),payload:n});r&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}clearAttentionFlag(e,t){this._clearAttentionFlag(e,t,!0)}_clearAttentionFlag(e,t,n){let r=`${e}::${t}`;this.attentionFlags.delete(r)&&n&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}listAttentionFlags(){return Array.from(this.attentionFlags.values()).sort((e,t)=>e.raisedAt-t.raisedAt)}listAttentionFlagsBySource(e){return this.listAttentionFlags().filter(t=>t.source===e)}onAttentionFlagsChange(e){this.attentionFlagsChangeHandlers.push(e)}fireAttentionFlagsChange(){let e=this.listAttentionFlags();for(let t of this.attentionFlagsChangeHandlers)try{t(e)}catch{}}broadcastAttentionUpdated(){for(let e of this.clients.values())e.connection.notify("hydra-acp/session/attention_updated",{sessionId:this.sessionId,flags:this.listAttentionFlags()}).catch(()=>{})}scheduleIdleCheck(){if(this.closed||this.idleTimeoutMs<=0)return;let e=this.lastActivityAt+this.idleTimeoutMs;this.armIdleTimer(Math.max(0,e-Date.now()))}armIdleTimer(e){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{this.idleTimer=void 0,this.checkIdle()},e),typeof this.idleTimer.unref=="function"&&this.idleTimer.unref()}checkIdle(){if(this.closed||this.idleTimeoutMs<=0)return;if(this.hasWorkInFlight){this.armIdleTimer(this.idleTimeoutMs);return}let e=Date.now()-this.lastActivityAt;if(e<this.idleTimeoutMs){this.armIdleTimer(this.idleTimeoutMs-e);return}let t=this.firstPromptSeeded?{deleteRecord:!1}:{deleteRecord:!0},n=Math.round(e/1e3);this.logger?.info(`session ${this.sessionId} idle timeout fired after ${n}s (window=${Math.round(this.idleTimeoutMs/1e3)}s) \u2014 closing`),this.close(t).catch(()=>{})}cancelIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=void 0),this.disposeIdleHandlers()}scheduleOrphanCheck(){this.closed||this.orphanTimeoutMs<=0||this.clients.size>0||this._interactive===!0||this.armOrphanTimer(this.orphanTimeoutMs)}armOrphanTimer(e){this.orphanTimer&&clearTimeout(this.orphanTimer),this.orphanTimer=setTimeout(()=>{this.orphanTimer=void 0,this.checkOrphan()},e),typeof this.orphanTimer.unref=="function"&&this.orphanTimer.unref()}checkOrphan(){if(!this.closed&&!(this.clients.size>0||this._interactive===!0)){if(this.hasWorkInFlight){this.armOrphanTimer(this.orphanTimeoutMs);return}this.logger?.info(`session ${this.sessionId} orphan timeout fired after ${Math.round(this.orphanTimeoutMs/1e3)}s with no attached client and no prompt ever received \u2014 closing`),this.close({deleteRecord:!1,by:"reap-orphaned"}).catch(()=>{})}}cancelOrphanTimer(){this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=void 0)}get currentPromptDepth(){if(this.currentEntry?.kind==="user")return this.currentEntry.originator.depth??0}get hasWorkInFlight(){return this.turnStartedAt!==void 0||this.hasPermissionFlag||this.promptQueue.length>0||this.armedBackgroundTasks.length>0}onIdle(e,t){let n={fn:e,once:!!t?.once,debounceMs:t?.debounceMs??0};return this.idleHandlers.push(n),()=>{let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1),n.timer&&(clearTimeout(n.timer),n.timer=void 0)}}onceIdle(e){return this.onIdle(e,{once:!0})}dispatchIdle(){if(this.closed)return;if(!this.isQuiescedSync()){for(let n of this.idleHandlers)n.timer&&(clearTimeout(n.timer),n.timer=void 0);return}let t=[...this.idleHandlers];for(let n of t){if(n.debounceMs===0){if(n.once){let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1)}try{n.fn(this)}catch{}continue}n.timer&&(clearTimeout(n.timer),n.timer=void 0),n.timer=setTimeout(()=>{if(n.timer=void 0,!this.closed&&this.isQuiescedSync()){if(n.once){let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1)}try{n.fn(this)}catch{}}},n.debounceMs),typeof n.timer.unref=="function"&&n.timer.unref()}}disposeIdleHandlers(){for(let e of this.idleHandlers)e.timer&&(clearTimeout(e.timer),e.timer=void 0);this.idleHandlers.length=0}noteRecordedToolCall(e,t){if(e!=="session/update")return;let n=t?.update;if(n===void 0)return;let r=typeof n.toolCallId=="string"?n.toolCallId:"";if(r.length===0)return;let o=typeof n.title=="string"&&n.title!==""?n.title:void 0;if(n.sessionUpdate==="tool_call"){this.turnRanTool=!0,n.status!=="completed"&&n.status!=="failed"&&this.openToolCalls.set(r,{startedAt:Date.now(),...o!==void 0?{title:o}:{}});return}if(n.sessionUpdate!=="tool_call_update")return;if(n.status==="completed"||n.status==="failed"){this.openToolCalls.delete(r),this.disarmOpenToolCall(r);return}let i=this.openToolCalls.get(r);i!==void 0&&o!==void 0&&(i.title=o)}armOpenToolCalls(){let e=!1;for(let[t,n]of this.openToolCalls){if(this.armedTasks.has(t))continue;let r=this.toolLabels.get(t),o=r?.fromDescription===!0?r.label:mp(n.title??r?.label??"").slice(0,Jr);this.armedTasks.set(t,{label:o===""?"running tool":o,repeating:!1,armedAt:n.startedAt,openToolCall:!0}),e=!0}e&&this.onArmedTasksChanged()}disarmOpenToolCall(e){this.armedTasks.get(e)?.openToolCall===!0&&(this.armedTasks.delete(e),this.onArmedTasksChanged())}closeOpenToolCalls(e){if(this.openToolCalls.size===0||this.closed)return;let t=[...this.openToolCalls.keys()];this.openToolCalls.clear();for(let n of t)this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"tool_call_update",toolCallId:n,status:"failed",_meta:{[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===ga&&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 f=u.line,m={path:l,toolCallId:o};typeof f=="number"&&(m.line=f),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=!pn(e,r),i=o?$p(e,r):r,a=Date.now(),d=o?this.lastSeq=Math.max(this.lastSeq+1,a):void 0,c=o?Ue(Le(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 Se(new Error("no clients attached to handle permission request"),E.PermissionDenied);let n=this.rewriteForClient(e),r=Da(n),o=Je(),{toolCall:i,options:a}=n??{};return new Promise((d,c)=>{let u=!1,l=[],f=0,m,h=this.sessionId,p=y=>{u||(u=!0,this.clearAttentionFlag("daemon",`permission:${o}`),this.permissionCallbacks.delete(o),y())},g=y=>y?.code===E.MethodNotFound;function w(y){if(u)return;let k=y.connection.request("session/request_permission",n);l.push({client:y}),f++,k.then(b=>{f--,p(()=>{let I=Np({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:I}).catch(()=>{});d(b)})}).catch(b=>{if(f--,g(b)||(m=b),f===0&&!u){let I=m??Se(new Error("no client handled permission request"),E.PermissionDenied);p(()=>c(I))}})}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: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 f=this.insertEntryAt(l,d);this.persistRewrite(),this.broadcastQueueAdded(l,{position:f}),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(()=>fn(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=wt(e.prompt).replace(/\s+$/,""),n=!t.includes(`
|
|
91
|
-
`)&&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=
|
|
88
|
+
`},_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"),E.InvalidParams);let r=(this.resolveAgentIdHook?await this.resolveAgentIdHook(t):void 0)??t;if(r===this.agentId)throw be(new Error(`already on agent ${r}`),E.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"),E.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=_a(n,t),o=$a(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(`
|
|
89
|
+
`)),{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(!Ha.includes(t))return this.emitExtensionReply(`Unknown workspace verb "${t}". Use one of: ${Ha.join(", ")}.`),{stopReason:"end_turn"};let r=n.filter(d=>d.startsWith("--")),o=r.filter(d=>d!=="--clean"&&d!=="--deep");if(o.length>0)return this.emitExtensionReply(`Unknown workspace flag(s) ${o.join(", ")}. Supported: --clean (start), --deep (clean).`),{stopReason:"end_turn"};let i={clean:r.includes("--clean"),deep:r.includes("--deep")};if(i.clean&&t!=="start")return this.emitExtensionReply(`--clean applies to \`start\`, not to \`${t}\`.`),{stopReason:"end_turn"};if(i.deep&&t!=="clean")return this.emitExtensionReply(`--deep applies to \`clean\`, not to \`${t}\`.`),{stopReason:"end_turn"};let a=n.filter(d=>!d.startsWith("--")).join(" ").trim();try{let d=await this.workspaceHook(t,a.length>0?a:void 0,i);this.emitExtensionReply(d)}catch(d){this.emitExtensionReply(`Workspace ${t} failed: ${d instanceof Error?d.message:String(d)}`)}return{stopReason:"end_turn"}}async runUncompactCommandInline(){if(!this.uncompactHook)return this.emitExtensionReply("Rollback not available: uncompact hook not configured for this session."),{stopReason:"end_turn"};try{await this.uncompactHook(),this.emitExtensionReply("Rolled back to pre-compaction upstream. The session is now using the previous agent context.")}catch(e){this.emitExtensionReply(`Rollback failed: ${e instanceof Error?e.message:String(e)}`)}return{stopReason:"end_turn"}}runForkCommand(e){return this.enqueuePrompt("fork",()=>this.runForkCommandInline(e,void 0))}async findMessageIdBefore(e){if(!this.historyStore)return;let t=await this.historyStore.load(this.sessionId),n;for(let r of t){if(r.method!=="session/update")continue;let i=r.params?.update?.messageId;if(typeof i=="string"){if(i===e)return n;n=i}}}async runForkCommandInline(e,t){if(!this.forkHook)return this.emitExtensionReply("Fork not configured for this session."),{stopReason:"end_turn"};let n=(e??"").trim(),r=n.match(/^--verbatim(?:\s+([\s\S]*))?$/),o=r?"verbatim":void 0,i=(r?r[1]??"":n).trim();try{let a={};if(o&&(a.mode=o),i!==""&&(a.prompt=i),t&&this.historyStore){let u=await this.findMessageIdBefore(t).catch(()=>{});u&&(a.forkAt=u)}let c=(await this.forkHook(Object.keys(a).length>0?a:void 0)).sessionId.replace(/^hydra_session_/,"");this.emitExtensionReply(i!==""?`Forked to [\`${c}\`](hydra://sessions/${c}) and sent the prompt.`:`Forked to [\`${c}\`](hydra://sessions/${c}).`)}catch(a){this.emitExtensionReply(`Fork failed: ${a instanceof Error?a.message:String(a)}`)}return{stopReason:"end_turn"}}escalateUnresponsiveCancel(){this.cancelReopenStreak=0,this.logger?.warn(`session ${this.sessionId} agent ${this.agentId} reopened an unsolicited turn right after cancel ${s.UNSOLICITED_REOPEN_LIMIT} times in a row; forcing a restart`),this.broadcastQueueNotification("hydra-acp/cancel_failed",{sessionId:this.sessionId,reason:"unresponsive",message:`${this.agentId} kept resuming after repeated cancels; restarting the agent`}),this.forceCancel().catch(e=>{this.logger?.warn(`session ${this.sessionId} forceCancel after unresponsive-cancel escalation failed: ${e instanceof Error?e.message:String(e)}`)})}async forceCancel(){if(this.closed||this.closing)throw be(new Error("session is closing"),E.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=kt(l.prompt);h&&n.push({speaker:"user",text:h})}else if(m==="agent_message_chunk"){let p=l.content?.text;p&&n.push({speaker:`agent: ${e}`,text:p})}else if(m==="tool_call"||m==="tool_call_update"){let h=l.status,p=l.title;(h==="completed"||h==="failed")&&n.push({speaker:"tool",text:`${p??"?"} ${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(`
|
|
90
|
+
`)}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=Vr({synopsis:e,title:t,tail:n,tailK:gp,tailFloor:mp,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 es(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??Ht,Ht)),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=E.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),Hr(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(()=>ja(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(()=>Ga.unlink(i).catch(()=>{}))}for(let o of this.closeHandlers)o(e)}get lastActivityAt(){return this.lastRecordedAt}setAttentionFlag(e,t,n){this._setAttentionFlag(e,t,n,!0)}_setAttentionFlag(e,t,n,r){let o=`${e}::${t}`,i=this.attentionFlags.get(o);if(i){if(JSON.stringify(i.payload)===JSON.stringify(n))return;this.attentionFlags.set(o,{...i,payload:n,raisedAt:i.raisedAt})}else this.attentionFlags.set(o,{source:e,reason:t,raisedAt:Date.now(),payload:n});r&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}clearAttentionFlag(e,t){this._clearAttentionFlag(e,t,!0)}_clearAttentionFlag(e,t,n){let r=`${e}::${t}`;this.attentionFlags.delete(r)&&n&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}listAttentionFlags(){return Array.from(this.attentionFlags.values()).sort((e,t)=>e.raisedAt-t.raisedAt)}listAttentionFlagsBySource(e){return this.listAttentionFlags().filter(t=>t.source===e)}onAttentionFlagsChange(e){this.attentionFlagsChangeHandlers.push(e)}fireAttentionFlagsChange(){let e=this.listAttentionFlags();for(let t of this.attentionFlagsChangeHandlers)try{t(e)}catch{}}broadcastAttentionUpdated(){for(let e of this.clients.values())e.connection.notify("hydra-acp/session/attention_updated",{sessionId:this.sessionId,flags:this.listAttentionFlags()}).catch(()=>{})}scheduleIdleCheck(){if(this.closed||this.idleTimeoutMs<=0)return;let e=this.lastActivityAt+this.idleTimeoutMs;this.armIdleTimer(Math.max(0,e-Date.now()))}armIdleTimer(e){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{this.idleTimer=void 0,this.checkIdle()},e),typeof this.idleTimer.unref=="function"&&this.idleTimer.unref()}checkIdle(){if(this.closed||this.idleTimeoutMs<=0)return;if(this.hasWorkInFlight){this.armIdleTimer(this.idleTimeoutMs);return}let e=Date.now()-this.lastActivityAt;if(e<this.idleTimeoutMs){this.armIdleTimer(this.idleTimeoutMs-e);return}let t=this.firstPromptSeeded?{deleteRecord:!1}:{deleteRecord:!0},n=Math.round(e/1e3);this.logger?.info(`session ${this.sessionId} idle timeout fired after ${n}s (window=${Math.round(this.idleTimeoutMs/1e3)}s) \u2014 closing`),this.close(t).catch(()=>{})}cancelIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=void 0),this.disposeIdleHandlers()}scheduleOrphanCheck(){this.closed||this.orphanTimeoutMs<=0||this.clients.size>0||this._interactive===!0||this.armOrphanTimer(this.orphanTimeoutMs)}armOrphanTimer(e){this.orphanTimer&&clearTimeout(this.orphanTimer),this.orphanTimer=setTimeout(()=>{this.orphanTimer=void 0,this.checkOrphan()},e),typeof this.orphanTimer.unref=="function"&&this.orphanTimer.unref()}checkOrphan(){if(!this.closed&&!(this.clients.size>0||this._interactive===!0)){if(this.hasWorkInFlight){this.armOrphanTimer(this.orphanTimeoutMs);return}this.logger?.info(`session ${this.sessionId} orphan timeout fired after ${Math.round(this.orphanTimeoutMs/1e3)}s with no attached client and no prompt ever received \u2014 closing`),this.close({deleteRecord:!1,by:"reap-orphaned"}).catch(()=>{})}}cancelOrphanTimer(){this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=void 0)}get currentPromptDepth(){if(this.currentEntry?.kind==="user")return this.currentEntry.originator.depth??0}get hasWorkInFlight(){return this.turnStartedAt!==void 0||this.hasPermissionFlag||this.promptQueue.length>0||this.armedBackgroundTasks.length>0}onIdle(e,t){let n={fn:e,once:!!t?.once,debounceMs:t?.debounceMs??0};return this.idleHandlers.push(n),()=>{let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1),n.timer&&(clearTimeout(n.timer),n.timer=void 0)}}onceIdle(e){return this.onIdle(e,{once:!0})}dispatchIdle(){if(this.closed)return;if(!this.isQuiescedSync()){for(let n of this.idleHandlers)n.timer&&(clearTimeout(n.timer),n.timer=void 0);return}let t=[...this.idleHandlers];for(let n of t){if(n.debounceMs===0){if(n.once){let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1)}try{n.fn(this)}catch{}continue}n.timer&&(clearTimeout(n.timer),n.timer=void 0),n.timer=setTimeout(()=>{if(n.timer=void 0,!this.closed&&this.isQuiescedSync()){if(n.once){let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1)}try{n.fn(this)}catch{}}},n.debounceMs),typeof n.timer.unref=="function"&&n.timer.unref()}}disposeIdleHandlers(){for(let e of this.idleHandlers)e.timer&&(clearTimeout(e.timer),e.timer=void 0);this.idleHandlers.length=0}noteRecordedToolCall(e,t){if(e!=="session/update")return;let n=t?.update;if(n===void 0)return;let r=typeof n.toolCallId=="string"?n.toolCallId:"";if(r.length===0)return;let o=typeof n.title=="string"&&n.title!==""?n.title:void 0;if(n.sessionUpdate==="tool_call"){this.turnRanTool=!0,n.status!=="completed"&&n.status!=="failed"&&this.openToolCalls.set(r,{startedAt:Date.now(),...o!==void 0?{title:o}:{}});return}if(n.sessionUpdate!=="tool_call_update")return;if(n.status==="completed"||n.status==="failed"){this.openToolCalls.delete(r),this.disarmOpenToolCall(r);return}let i=this.openToolCalls.get(r);i!==void 0&&o!==void 0&&(i.title=o)}armOpenToolCalls(){let e=!1;for(let[t,n]of this.openToolCalls){if(this.armedTasks.has(t))continue;let r=this.toolLabels.get(t),o=r?.fromDescription===!0?r.label:Ip(n.title??r?.label??"").slice(0,Yr);this.armedTasks.set(t,{label:o===""?"running tool":o,repeating:!1,armedAt:n.startedAt,openToolCall:!0}),e=!0}e&&this.onArmedTasksChanged()}disarmOpenToolCall(e){this.armedTasks.get(e)?.openToolCall===!0&&(this.armedTasks.delete(e),this.onArmedTasksChanged())}closeOpenToolCalls(e){if(this.openToolCalls.size===0||this.closed)return;let t=[...this.openToolCalls.keys()];this.openToolCalls.clear();for(let n of t)this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"tool_call_update",toolCallId:n,status:"failed",_meta:{[ce]:{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===ka&&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 f=u.line,m={path:l,toolCallId:o};typeof f=="number"&&(m.line=f),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=!gn(e,r),i=o?Up(e,r):r,a=Date.now(),d=o?this.lastSeq=Math.max(this.lastSeq+1,a):void 0,c=o?Ue(Le(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"),E.PermissionDenied);let n=this.rewriteForClient(e),r=Ba(n),o=Je(),{toolCall:i,options:a}=n??{};return new Promise((d,c)=>{let u=!1,l=[],f=0,m,h=this.sessionId,p=y=>{u||(u=!0,this.clearAttentionFlag("daemon",`permission:${o}`),this.permissionCallbacks.delete(o),y())},g=y=>y?.code===E.MethodNotFound;function w(y){if(u)return;let k=y.connection.request("session/request_permission",n);l.push({client:y}),f++,k.then(b=>{f--,p(()=>{let I=qp({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:I}).catch(()=>{});d(b)})}).catch(b=>{if(f--,g(b)||(m=b),f===0&&!u){let I=m??be(new Error("no client handled permission request"),E.PermissionDenied);p(()=>c(I))}})}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: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 f=this.insertEntryAt(l,d);this.persistRewrite(),this.broadcastQueueAdded(l,{position:f}),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[ce];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(()=>pn(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=kt(e.prompt).replace(/\s+$/,""),n=!t.includes(`
|
|
91
|
+
`)&&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=Xr(e.prompt,Vp));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&&Ep(r))return this.logger?.warn(`agent ${this.agentId} no longer knows upstream session ${this.upstreamSessionId} for ${this.sessionId}; reloading it onto a fresh process and retrying the prompt once`),await this.reloadUpstreamAfterAgentLoss(),await n();if(!Pp(r)||this.turnRanTool||(this.logger?.warn(`agent ${this.agentId} hit a transient auth failure for ${this.sessionId}; retrying the prompt once in ${Ua}ms`),await new Promise(o=>setTimeout(o,Ua)),e.cancelled))throw r;return await n()}}clearAmendIfMatches(e){this.amendInProgress?.cancelledMessageId===e&&(this.amendInProgress=void 0)}},xp=["session not found","the claude agent session has ended"];function Ka(s){let e=s;if(e?.code!==E.InternalError)return;let t=e.data?.details;return`${typeof e.message=="string"?e.message:""} ${typeof t=="string"?t:""}`.toLowerCase()}function Ep(s){let e=Ka(s);return e!==void 0&&xp.some(t=>e.includes(t))}var Tp=["failed to refresh oauth token"],Ua=6e4;function Pp(s){let e=Ka(s);return e!==void 0&&Tp.some(t=>e.includes(t))}function be(s,e){return s.code=e,s}var Mp=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 _p(s,e,t){return t?.run_in_background===!0?!1:e?.toolName==="Monitor"||s==="Monitor"||typeof e?.toolResponse?.taskId=="string"}function $p(s){return typeof s!="string"?void 0:/Command running in background with ID: ([A-Za-z0-9_-]+)/.exec(s)?.[1]}function Op(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 gn(s,e){if(s!=="session/update")return!1;let n=(e??{}).update?.sessionUpdate;return typeof n=="string"&&Mp.has(n)}function Fp(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 Np(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 Dp(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 mn(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 os(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 eo(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 jp(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 Hp(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 Lp(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 Up(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 Bp(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 Wp(s,e){for(let t=s.length-1;t>=0;t--)if(s[t]?.seq===e)return t;return-1}function is(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 qp(s){let e=zp(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=Jp(s.resolver),t}function zp(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 Jp(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 kt(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?e.text:"").join(""):""}var Vp="\u200B";function Wa(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 Xr(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 Zr(s){return s==="session/prompt"?{stopReason:"stopped"}:{}}function Gp(s){return s==="session/request_permission"?{outcome:{outcome:"cancelled"}}:{}}function qa(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}
|
|
92
92
|
${n.join(`
|
|
93
|
-
`)}`}function
|
|
93
|
+
`)}`}function to(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}}G();Ne();import*as Te from"fs/promises";import*as Wv from"path";import{customAlphabet as Yp}from"nanoid";import{z as P}from"zod";import{z as zt}from"zod";var Kp=zt.object({source:zt.string(),reason:zt.string(),raisedAt:zt.number(),payload:zt.unknown()}),Qa=zt.array(Kp);import{z as Q}from"zod";var Ya=Q.object({status:Q.enum(["requested","running","swap_pending","swap_deferred","failed"]),requestedAt:Q.number(),runId:Q.string().optional(),iter:Q.number().int().nonnegative().optional(),attempts:Q.number().int().nonnegative().optional(),lastError:Q.string().optional(),worker:Q.object({upstreamSessionId:Q.string(),pid:Q.number().int().nonnegative()}).optional()}),hn=Q.object({goal:Q.string().optional(),outcome:Q.string().optional(),files_touched:Q.array(Q.string()).optional(),tools_used:Q.array(Q.string()).optional(),rejected_approaches:Q.array(Q.string()).optional(),open_threads:Q.array(Q.string()).optional(),decisions:Q.array(Q.string()).optional(),file_edit_intentions:Q.array(Q.string()).optional(),unresolved_errors:Q.array(Q.string()).optional(),tool_state:Q.array(Q.string()).optional()}),Xa=200,no=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
|
|
94
94
|
{
|
|
95
95
|
"title": "short summary, max 80 chars",
|
|
96
96
|
"synopsis": {
|
|
@@ -100,7 +100,7 @@ ${n.join(`
|
|
|
100
100
|
"open_threads": ["work started but not finished"]
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
-
Use empty arrays/strings where a field doesn't apply.`;function
|
|
103
|
+
Use empty arrays/strings where a field doesn't apply.`;function Za(s){let e=s.trim();if(e.length===0)return;let t=Jt(e);if(t===void 0){let o=e.indexOf("{"),i=e.lastIndexOf("}");o>=0&&i>o&&(t=Jt(e.slice(o,i+1)))}if(t===void 0){let o=td(e);o!==void 0&&(t=Jt(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,Xa))}if(n.synopsis!==void 0&&n.synopsis!==null){let o=hn.safeParse(n.synopsis);o.success&&Qp(o.data)&&(r.synopsis=o.data)}if(!(r.title===void 0&&r.synopsis===void 0))return r}var so=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
|
|
104
104
|
{
|
|
105
105
|
"title": "short summary, max 80 chars",
|
|
106
106
|
"goal": "the user's original ask",
|
|
@@ -112,47 +112,47 @@ Use empty arrays/strings where a field doesn't apply.`;function Ga(s){let e=s.tr
|
|
|
112
112
|
"unresolved_errors": ["errors left open at session end"],
|
|
113
113
|
"tool_state": ["runtime state relevant for recall"]
|
|
114
114
|
}
|
|
115
|
-
Use empty arrays/strings where a field doesn't apply.`;function Ka(s){let e=s.trim();if(e.length===0)return;let t=qt(e);if(t===void 0){let c=e.indexOf("{"),u=e.lastIndexOf("}");c>=0&&u>c&&(t=qt(e.slice(c,u+1)))}if(t===void 0){let c=Qa(e);c!==void 0&&(t=qt(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,Va))}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=Q.array(Q.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 qt(s){try{return JSON.parse(s)}catch{return}}function Qa(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 Bp(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 qp="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",zp=Wp(qp,16),Jp="hydra_lineage_";function yn(){return`${Jp}${zp()}`}var Zr=P.object({name:P.string(),description:P.string().optional()}),eo=P.object({id:P.string(),name:P.string().optional(),description:P.string().optional()}),Vp=P.object({modelId:P.string(),name:P.string().optional(),description:P.string().optional()}),to=P.object({used:P.number().optional(),size:P.number().optional(),costAmount:P.number().optional(),costCurrency:P.string().optional(),cumulativeCost:P.number().optional()}),no=P.object({name:P.string(),version:P.string().optional()}),Gp=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()}),Kp=P.object({previousUpstreamSessionId:P.string(),previousSummarizedThroughEntry:P.number().int().nonnegative().optional(),runId:P.string().optional()}),Qp=P.enum(["compaction","agent-swap","workspace-enter","workspace-leave","rollback","restart"]),Yp=P.object({upstreamSessionId:P.string(),agentId:P.string(),reason:Qp.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()}),Xp=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:mn.optional(),compactionState:Ja.optional(),rollbackBreadcrumb:Kp.optional(),upstreamGenerations:P.array(Yp).optional(),summarizedThroughEntry:P.number().int().nonnegative().optional(),agentArgs:P.array(P.string()).optional(),currentModel:P.string().optional(),currentMode:P.string().optional(),currentUsage:to.optional(),agentCommands:P.array(Zr).optional(),agentModes:P.array(eo).optional(),agentModels:P.array(Vp).optional(),configOptionValues:P.record(P.string(),P.string()).optional(),pendingHistorySync:P.boolean().optional(),pendingAgentSwap:P.string().optional(),parentSessionId:P.string().optional(),forkedFromSessionId:P.string().optional(),forkedFromMessageId:P.string().optional(),forkSynthesisState:P.enum(["running","failed"]).optional(),originatingClient:no.optional(),interactive:P.boolean().optional(),priority:P.number().int().nonnegative().optional(),forwardedEnv:P.record(P.string(),P.string()).optional(),workspace:Gp.optional(),attentionFlags:za.default([]).optional(),extensionState:P.record(P.string(),P.record(P.string(),P.unknown())).default({}).optional(),createdAt:P.string(),updatedAt:P.string()}),hn=/^[A-Za-z0-9_-]+$/;function Zp(s){if(!hn.test(s))throw new Error(`unsafe session id: ${s}`)}var os=class{index;indexSeed;async write(e){Zp(e.sessionId);let t={version:1,...e};await pe(x.sessionFile(e.sessionId),t,{mode:384}),await this.reindex(e.sessionId)}async touch(e){if(!hn.test(e))return;let t=new Date;try{await Pe.utimes(x.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 Pe.readdir(x.sessionsDir())}catch(n){if(n.code!=="ENOENT")throw n}await Promise.all(t.map(async n=>{if(hn.test(n))try{let r=await Pe.stat(x.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 Pe.stat(x.sessionFile(e));this.index.set(e,{mtimeMs:t.mtimeMs,deleted:!1})}catch{}}}async read(e){if(!hn.test(e))return;let t=await ie(x.sessionFile(e));if(t!==void 0)try{return Xp.parse(t)}catch{return}}async delete(e){if(hn.test(e)){this.indexSeed&&(await this.indexSeed,this.index.set(e,{mtimeMs:Date.now(),deleted:!0}));try{await Pe.unlink(x.sessionFile(e))}catch(t){if(t.code!=="ENOENT")throw t}try{await Pe.rmdir(x.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 Pe.readdir(x.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 so(s){let e=new Date().toISOString(),t=s.createdAt??e,n=(s.currentUsage?.cumulativeCost??0)+(s.currentUsage?.costAmount??0),r=s.upstreamGenerations??(s.upstreamSessionId?[{upstreamSessionId:s.upstreamSessionId,agentId:s.agentId,startedAt:t,...n===0?{lifetimeCostAtStart:0}:{}}]:[]);return{sessionId:s.sessionId,lineageId:s.lineageId,upstreamSessionId:s.upstreamSessionId,importedFromSessionId:s.importedFromSessionId,importedFromUpstreamSessionId:s.importedFromUpstreamSessionId,importedFromMachine:s.importedFromMachine,agentId:s.agentId,cwd:s.cwd,title:s.title,synopsis:s.synopsis,summarizedThroughEntry:s.summarizedThroughEntry,compactionState:s.compactionState,rollbackBreadcrumb:s.rollbackBreadcrumb,upstreamGenerations:r,agentArgs:s.agentArgs,currentModel:s.currentModel,currentMode:s.currentMode,currentUsage:s.currentUsage,agentCommands:s.agentCommands,agentModes:s.agentModes,agentModels:s.agentModels,configOptionValues:s.configOptionValues,pendingHistorySync:s.pendingHistorySync,pendingAgentSwap:s.pendingAgentSwap,parentSessionId:s.parentSessionId,forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,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}}Ne();G();import*as oe from"fs/promises";import*as ye from"path";G();import*as is from"path";import{createHash as eg}from"crypto";var _e=class extends Error{constructor(e,t){super(`provider "${e}" does not support ${t}; check capabilities().supports before calling`),this.name="WorkspaceUnsupportedError"}};function zt(s){let e=eg("sha256").update(is.resolve(s)).digest("hex").slice(0,12);return is.join(B(),"workspaces",e)}async function as(s,e,t=100){if(await e(s))return s;for(let n=2;n<=t;n+=1){let r=`${s}-${n}`;if(await e(r))return r}}function kt(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 ro(s){return s.changedPaths.length>0||s.recorded!==void 0&&s.recorded!==s.actual}function tg(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 oo(s,e){let t=new Set(e.map(r=>r.relPath));return[...s.filter(r=>!t.has(r.replace(/\/$/,""))),...tg(e.filter(ro))]}function ds(s){let e=s.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return e.length>0?e.slice(0,64):"workspace"}var io="copy",Xa=new Set([".git"]);function wn(s){return`${s}.manifest.json`}async function Ya(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 oe.readdir(n,{withFileTypes:!0})}catch{continue}for(let o of r){let i=ye.join(n,o.name);if(!(n===s&&Xa.has(o.name))){if(o.isDirectory()){t.push(i);continue}if(o.isFile())try{let a=await oe.stat(i);e.set(ye.relative(s,i),{size:a.size,mtimeMs:a.mtimeMs})}catch{continue}}}}return e}var cs=class{kind=io;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=ye.resolve(e.sourceCwd),n=e.contentFrom!==void 0?ye.resolve(e.contentFrom):t;try{n=await oe.realpath(n)}catch{}try{if(!(await oe.stat(n)).isDirectory())return{ok:!1,reason:`${n} is not a directory`}}catch{return{ok:!1,reason:`${n} does not exist`}}let r=zt(t);try{await oe.mkdir(r,{recursive:!0})}catch(u){return{ok:!1,reason:`could not create workspace root: ${String(u)}`}}let o=await as(ds(e.label),async u=>oe.access(ye.join(r,u)).then(()=>!1).catch(()=>!0));if(o===void 0)return{ok:!1,reason:`no free name available for "${e.label}"`};let i=ye.join(r,o),a;try{a=await oe.readdir(n)}catch(u){return{ok:!1,reason:`copy failed: ${String(u)}`}}try{await oe.mkdir(i,{recursive:!0});for(let u of a)Xa.has(u)||await oe.cp(ye.join(n,u),ye.join(i,u),{recursive:!0,errorOnExist:!1,force:!0})}catch(u){return await oe.rm(i,{recursive:!0,force:!0}).catch(()=>{}),{ok:!1,reason:`copy failed: ${String(u)}`}}let d=await Ya(i),c={sourceCwd:t,label:o,createdAt:new Date().toISOString(),entries:Object.fromEntries(d)};return await pe(wn(i),c,{pretty:!1}),{ok:!0,workspace:{path:i,sourceCwd:t,label:o,provider:this.kind}}}async removeWorkspace(e,t){if(!t.force){let n=await this.status(e);if(!n.clean)throw new Error(`workspace ${e.path} has ${n.changedPaths.length} changed path(s); pass force to remove`)}await oe.rm(e.path,{recursive:!0,force:!0}),await oe.rm(wn(e.path),{force:!0})}async listWorkspaces(e){let t=zt(ye.resolve(e)),n;try{n=await oe.readdir(t)}catch{return[]}let r=[];for(let o of n){if(o.endsWith(".manifest.json"))continue;let i=ye.join(t,o),a=await ie(wn(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 ie(wn(e.path)),n=await Ya(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:`,...kt(t.map(r=>` ${r}`))];return n.push(`Not tracking ${O(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 _e(this.kind,"captureWorkingState")}async record(){throw new _e(this.kind,"record")}async attributeOrphan(e){let t=await ie(wn(e));if(t?.sourceCwd!==void 0)return{path:e,sourceCwd:t.sourceCwd,label:t.label??ye.basename(e),provider:this.kind}}async discardLine(){return{ok:!0,dropped:0}}ownsLine(){return!1}async pruneStale(){}async changedPaths(){throw new _e(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 _e(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 _e(this.kind,"lock")}async unlock(){throw new _e(this.kind,"unlock")}};G();import{execFile as sd}from"child_process";import{randomBytes as og}from"crypto";import*as $e from"fs/promises";import*as rd from"os";import*as Y from"path";function ng(s){let e=s.indexOf(" ");return e===-1?{key:s,value:""}:{key:s.slice(0,e),value:s.slice(e+1)}}function Za(s){let e=[],t,n=()=>{t!==void 0&&(e.push(t),t=void 0)};for(let r of s.split(`
|
|
116
|
-
`)){let o=r.replace(/\r$/,"");if(o.length===0){n();continue}let{key:i,value:a}=
|
|
117
|
-
`)){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
|
|
118
|
-
`).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
|
|
119
|
-
`).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,ue);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
|
|
120
|
-
`).map(n=>n.replace(/\r$/,"").trim()).filter(n=>n.length>0):[]}async record(e,t){let n=await j(["add","-A"],e.path,ue);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,ue);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=
|
|
121
|
-
`)){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||!
|
|
122
|
-
`)){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
|
|
115
|
+
Use empty arrays/strings where a field doesn't apply.`;function ed(s){let e=s.trim();if(e.length===0)return;let t=Jt(e);if(t===void 0){let c=e.indexOf("{"),u=e.lastIndexOf("}");c>=0&&u>c&&(t=Jt(e.slice(c,u+1)))}if(t===void 0){let c=td(e);c!==void 0&&(t=Jt(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,Xa))}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=Q.array(Q.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 Jt(s){try{return JSON.parse(s)}catch{return}}function td(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 Qp(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 Xp="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Zp=Yp(Xp,16),eg="hydra_lineage_";function wn(){return`${eg}${Zp()}`}var ro=P.object({name:P.string(),description:P.string().optional()}),oo=P.object({id:P.string(),name:P.string().optional(),description:P.string().optional()}),tg=P.object({modelId:P.string(),name:P.string().optional(),description:P.string().optional()}),io=P.object({used:P.number().optional(),size:P.number().optional(),costAmount:P.number().optional(),costCurrency:P.string().optional(),cumulativeCost:P.number().optional()}),ao=P.object({name:P.string(),version:P.string().optional()}),ng=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()}),sg=P.object({previousUpstreamSessionId:P.string(),previousSummarizedThroughEntry:P.number().int().nonnegative().optional(),runId:P.string().optional()}),rg=P.enum(["compaction","agent-swap","workspace-enter","workspace-leave","rollback","restart"]),og=P.object({upstreamSessionId:P.string(),agentId:P.string(),reason:rg.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()}),ig=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:hn.optional(),compactionState:Ya.optional(),rollbackBreadcrumb:sg.optional(),upstreamGenerations:P.array(og).optional(),summarizedThroughEntry:P.number().int().nonnegative().optional(),agentArgs:P.array(P.string()).optional(),currentModel:P.string().optional(),currentMode:P.string().optional(),currentUsage:io.optional(),agentCommands:P.array(ro).optional(),agentModes:P.array(oo).optional(),agentModels:P.array(tg).optional(),configOptionValues:P.record(P.string(),P.string()).optional(),pendingHistorySync:P.boolean().optional(),pendingAgentSwap:P.string().optional(),parentSessionId:P.string().optional(),forkedFromSessionId:P.string().optional(),forkedFromMessageId:P.string().optional(),forkSynthesisState:P.enum(["running","failed"]).optional(),originatingClient:ao.optional(),interactive:P.boolean().optional(),priority:P.number().int().nonnegative().optional(),forwardedEnv:P.record(P.string(),P.string()).optional(),workspace:ng.optional(),attentionFlags:Qa.default([]).optional(),extensionState:P.record(P.string(),P.record(P.string(),P.unknown())).default({}).optional(),createdAt:P.string(),updatedAt:P.string()}),yn=/^[A-Za-z0-9_-]+$/;function ag(s){if(!yn.test(s))throw new Error(`unsafe session id: ${s}`)}var as=class{index;indexSeed;async write(e){ag(e.sessionId);let t={version:1,...e};await fe(x.sessionFile(e.sessionId),t,{mode:384}),await this.reindex(e.sessionId)}async touch(e){if(!yn.test(e))return;let t=new Date;try{await Te.utimes(x.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 Te.readdir(x.sessionsDir())}catch(n){if(n.code!=="ENOENT")throw n}await Promise.all(t.map(async n=>{if(yn.test(n))try{let r=await Te.stat(x.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 Te.stat(x.sessionFile(e));this.index.set(e,{mtimeMs:t.mtimeMs,deleted:!1})}catch{}}}async read(e){if(!yn.test(e))return;let t=await ie(x.sessionFile(e));if(t!==void 0)try{return ig.parse(t)}catch{return}}async delete(e){if(yn.test(e)){this.indexSeed&&(await this.indexSeed,this.index.set(e,{mtimeMs:Date.now(),deleted:!0}));try{await Te.unlink(x.sessionFile(e))}catch(t){if(t.code!=="ENOENT")throw t}try{await Te.rmdir(x.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 Te.readdir(x.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 co(s){let e=new Date().toISOString(),t=s.createdAt??e,n=(s.currentUsage?.cumulativeCost??0)+(s.currentUsage?.costAmount??0),r=s.upstreamGenerations??(s.upstreamSessionId?[{upstreamSessionId:s.upstreamSessionId,agentId:s.agentId,startedAt:t,...n===0?{lifetimeCostAtStart:0}:{}}]:[]);return{sessionId:s.sessionId,lineageId:s.lineageId,upstreamSessionId:s.upstreamSessionId,importedFromSessionId:s.importedFromSessionId,importedFromUpstreamSessionId:s.importedFromUpstreamSessionId,importedFromMachine:s.importedFromMachine,agentId:s.agentId,cwd:s.cwd,title:s.title,synopsis:s.synopsis,summarizedThroughEntry:s.summarizedThroughEntry,compactionState:s.compactionState,rollbackBreadcrumb:s.rollbackBreadcrumb,upstreamGenerations:r,agentArgs:s.agentArgs,currentModel:s.currentModel,currentMode:s.currentMode,currentUsage:s.currentUsage,agentCommands:s.agentCommands,agentModes:s.agentModes,agentModels:s.agentModels,configOptionValues:s.configOptionValues,pendingHistorySync:s.pendingHistorySync,pendingAgentSwap:s.pendingAgentSwap,parentSessionId:s.parentSessionId,forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,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}}Ne();G();import*as oe from"fs/promises";import*as ye from"path";G();import*as ds from"path";import{createHash as dg}from"crypto";var _e=class extends Error{constructor(e,t){super(`provider "${e}" does not support ${t}; check capabilities().supports before calling`),this.name="WorkspaceUnsupportedError"}};function Vt(s){let e=dg("sha256").update(ds.resolve(s)).digest("hex").slice(0,12);return ds.join(B(),"workspaces",e)}async function cs(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 vt(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 uo(s){return s.changedPaths.length>0||s.recorded!==void 0&&s.recorded!==s.actual}function cg(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 lo(s,e){let t=new Set(e.map(r=>r.relPath));return[...s.filter(r=>!t.has(r.replace(/\/$/,""))),...cg(e.filter(uo))]}function us(s){let e=s.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"");return e.length>0?e.slice(0,64):"workspace"}var fo="copy",sd=new Set([".git"]);function kn(s){return`${s}.manifest.json`}async function nd(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 oe.readdir(n,{withFileTypes:!0})}catch{continue}for(let o of r){let i=ye.join(n,o.name);if(!(n===s&&sd.has(o.name))){if(o.isDirectory()){t.push(i);continue}if(o.isFile())try{let a=await oe.stat(i);e.set(ye.relative(s,i),{size:a.size,mtimeMs:a.mtimeMs})}catch{continue}}}}return e}var ls=class{kind=fo;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=ye.resolve(e.sourceCwd),n=e.contentFrom!==void 0?ye.resolve(e.contentFrom):t;try{n=await oe.realpath(n)}catch{}try{if(!(await oe.stat(n)).isDirectory())return{ok:!1,reason:`${n} is not a directory`}}catch{return{ok:!1,reason:`${n} does not exist`}}let r=Vt(t);try{await oe.mkdir(r,{recursive:!0})}catch(u){return{ok:!1,reason:`could not create workspace root: ${String(u)}`}}let o=await cs(us(e.label),async u=>oe.access(ye.join(r,u)).then(()=>!1).catch(()=>!0));if(o===void 0)return{ok:!1,reason:`no free name available for "${e.label}"`};let i=ye.join(r,o),a;try{a=await oe.readdir(n)}catch(u){return{ok:!1,reason:`copy failed: ${String(u)}`}}try{await oe.mkdir(i,{recursive:!0});for(let u of a)sd.has(u)||await oe.cp(ye.join(n,u),ye.join(i,u),{recursive:!0,errorOnExist:!1,force:!0})}catch(u){return await oe.rm(i,{recursive:!0,force:!0}).catch(()=>{}),{ok:!1,reason:`copy failed: ${String(u)}`}}let d=await nd(i),c={sourceCwd:t,label:o,createdAt:new Date().toISOString(),entries:Object.fromEntries(d)};return await fe(kn(i),c,{pretty:!1}),{ok:!0,workspace:{path:i,sourceCwd:t,label:o,provider:this.kind}}}async removeWorkspace(e,t){if(!t.force){let n=await this.status(e);if(!n.clean)throw new Error(`workspace ${e.path} has ${n.changedPaths.length} changed path(s); pass force to remove`)}await oe.rm(e.path,{recursive:!0,force:!0}),await oe.rm(kn(e.path),{force:!0})}async listWorkspaces(e){let t=Vt(ye.resolve(e)),n;try{n=await oe.readdir(t)}catch{return[]}let r=[];for(let o of n){if(o.endsWith(".manifest.json"))continue;let i=ye.join(t,o),a=await ie(kn(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 ie(kn(e.path)),n=await nd(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:`,...vt(t.map(r=>` ${r}`))];return n.push(`Not tracking ${O(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 _e(this.kind,"captureWorkingState")}async record(){throw new _e(this.kind,"record")}async attributeOrphan(e){let t=await ie(kn(e));if(t?.sourceCwd!==void 0)return{path:e,sourceCwd:t.sourceCwd,label:t.label??ye.basename(e),provider:this.kind}}async discardLine(){return{ok:!0,dropped:0}}ownsLine(){return!1}async pruneStale(){}async changedPaths(){throw new _e(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 _e(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 _e(this.kind,"lock")}async unlock(){throw new _e(this.kind,"unlock")}};G();import{execFile as dd}from"child_process";import{randomBytes as pg}from"crypto";import*as $e from"fs/promises";import*as cd from"os";import*as Y from"path";function ug(s){let e=s.indexOf(" ");return e===-1?{key:s,value:""}:{key:s.slice(0,e),value:s.slice(e+1)}}function rd(s){let e=[],t,n=()=>{t!==void 0&&(e.push(t),t=void 0)};for(let r of s.split(`
|
|
116
|
+
`)){let o=r.replace(/\r$/,"");if(o.length===0){n();continue}let{key:i,value:a}=ug(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 od(s){if(s===void 0)return;let e="refs/heads/";return s.startsWith(e)?s.slice(e.length):s}var gs="git",id="hydra-acp:",po="hydra",z=5e3,ue=12e4,fs=9e5;function ad(s){return $e.access(s).then(()=>!0).catch(()=>!1)}function vn(s){return s.length===0?s:Y.normalize(s)}function gg(s){return $e.realpath(s).catch(()=>s)}function j(s,e,t,n){return new Promise(r=>{dd("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 go(s,e,t,n=ue){return new Promise(r=>{let o=dd("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 mo(s){let e=[];for(let t of s.split(`
|
|
117
|
+
`)){let n=t.replace(/\r$/,"");if(n.length<4)continue;let r=n.slice(3),o=r.indexOf(" -> ");e.push({code:n.slice(0,2),path:o===-1?r:r.slice(o+4)})}return e}var ps=class{kind=gs;refRoot(e){return e.vcs?.repoRoot??e.sourceCwd}ownsLine(e){return e.startsWith(`${po}/`)}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 ad(Y.join(e.path,".gitmodules")))return{ok:!0,count:0};let r=await j(["submodule","update","--init","--recursive",...t?.discardLocal===!0?["--force"]:[]],e.path,fs);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,fs);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,fs);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(`
|
|
118
|
+
`).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 ad(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,ue);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=vn(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=us(e.label),d=Vt(t);try{await $e.mkdir(d,{recursive:!0})}catch(m){return{ok:!1,reason:`could not create workspace root: ${String(m)}`}}let c=await cs(a,async m=>await $e.access(Y.join(d,m)).then(()=>!0).catch(()=>!1)?!1:!(await j(["rev-parse","--verify","--quiet",`refs/heads/${po}/${m}`],r,z)).ok);if(c===void 0)return{ok:!1,reason:`no free name available for "${a}"`};let u=Y.join(d,c),l=`${po}/${c}`,f=await j(["worktree","add","--no-track","-b",l,u,i],r,ue);return f.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: ${f.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,ue);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=Y.resolve(e),n=await j(["rev-parse","--show-toplevel"],t,z);if(!n.ok)return[];let r=vn(n.stdout.trim()),o=await j(["worktree","list","--porcelain"],r,z);if(!o.ok)return[];let i=Vt(t),a=await gg(i),d=[];for(let c of rd(o.stdout)){let u=vn(c.path),l=Y.dirname(u);if(l!==i&&l!==a)continue;let f=Y.join(i,Y.basename(u)),m={kind:"git",repoRoot:r},h=od(c.branch);h!==void 0&&(m.branch=h),c.head!==void 0&&(m.head=c.head),c.lockedReason!==void 0&&(m.locked=c.lockedReason);let p=c.lockedReason?.startsWith(id)===!0;d.push({path:f,sourceCwd:t,label:Y.basename(f),...p?{heldByUs:!0}:{},provider:this.kind,...h!==void 0?{line:h}:{},vcs:m})}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=mo(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",`${id}${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(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=mo(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(...vt(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=O(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(f=>Number.parseInt(f,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(cd.tmpdir(),`hydra-index-${process.pid}-${pg(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,ue,r);if(!l.ok)throw new Error(`could not seed the snapshot index: ${l.stderr.trim()}`)}let a=await j(["add","-A"],e,ue,r);if(!a.ok)throw new Error(`could not stage working state: ${a.stderr.trim()}`);let d=await j(["write-tree"],e,ue,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,ue,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=vn(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(`
|
|
119
|
+
`).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,ue);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 go(["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 go(["apply","--reverse","--check"],e,t)).ok)return{ok:!0,alreadyPresent:!0};let a=await go(["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,ue);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,ue);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,ue)}async conflictedPaths(e){let t=await j(["diff","--name-only","--diff-filter=U"],e,z);return t.ok?t.stdout.split(`
|
|
120
|
+
`).map(n=>n.replace(/\r$/,"").trim()).filter(n=>n.length>0):[]}async record(e,t){let n=await j(["add","-A"],e.path,ue);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,ue);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=vn(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 _e(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,ue);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,ue);if(!t.ok)return[];let n=[];for(let r of t.stdout.split(`
|
|
121
|
+
`)){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||!mg(e,c))continue;let u=Y.join(e,c),[l,f,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=f.ok?f.stdout.trim():"";n.push({relPath:c,actual:l,...h.length>0?{recorded:h}:{},changedPaths:m.ok?mo(m.stdout).map(p=>p.path):[]})}return n}async captureNested(e,t){let n=[];for(let r of t){if(!uo(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(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 f=u.recorded!==void 0&&u.recorded!==u.actual,m=l?.delta!==void 0;if(!f&&!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=Y.join(e,c),p=Y.join(t,c);if(f&&u.recorded!==void 0){let g=await this.alignNested(h,p,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,fs)).ok)return`could not transfer ${n.slice(0,8)} from the other copy`;if(!(await j(["checkout","--detach",n],e,ue)).ok)return`could not move to ${n.slice(0,8)}`}};function mg(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 hg=gs,yg=new Map([[gs,new ps],[fo,new ls]]);function ne(s){return yg.get(s??hg)}var ms="refs/hydra";function Gt(s){let e=`${ms}/workspaces/${s}`;return{autosave:`${e}/autosave`,start:`${e}/start`,baseline:`${e}/baseline`}}function ho(s){return`${ms}/landing/${s}`}function ud(s){return`${ms}/sync/${s}`}function ld(s,e){return`${ms}/retired/${s}-${e.slice(0,12)}`}function fd(s){let e=Gt(s);return[e.autosave,e.start,e.baseline]}async function yo(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 f=await i.resolveRetained(t,l).catch(()=>{});if(f!==void 0){d=f;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 bt(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 bn(s){s.capture.retainedRef===void 0||s.provider===void 0||await s.provider.dropSnapshotRef({...s.ws,path:s.source},s.capture.retainedRef).catch(()=>{})}Ne();import{exec as wg}from"child_process";import*as Ve from"fs/promises";import*as Ce from"path";var kg=".hydra/worktree.json",vg=".worktreeinclude",bg=120;async function hs(s){let e=await ie(Ce.join(s,kg))??{},t=new Set(Array.isArray(e.carry)?e.carry:[]),n=await Ve.readFile(Ce.join(s,vg),"utf8").catch(()=>{});if(n!==void 0)for(let o of n.split(`
|
|
122
|
+
`)){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 wo(s,e,t){let n=[],r=[],o=Ce.resolve(s),i=Ce.resolve(e);for(let a of t){let d=Ce.resolve(o,a),c=Ce.resolve(i,a);if(!d.startsWith(o+Ce.sep)||!c.startsWith(i+Ce.sep)){r.push(a);continue}if(await Ve.access(c).then(()=>!0).catch(()=>!1)){r.push(a);continue}let l=await Ve.stat(d).catch(()=>{});if(l===void 0){r.push(a);continue}try{await Ve.mkdir(Ce.dirname(c),{recursive:!0}),await Ve.cp(d,c,{recursive:l.isDirectory(),dereference:!0}),n.push(a)}catch{r.push(a)}}return{copied:n,skipped:r}}async function ys(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??bg)*1e3;return new Promise(r=>{let o=wg(s,{cwd:e.workspacePath,timeout:n,maxBuffer:8388608,windowsHide:!0,env:{...process.env,HYDRA_WORKSPACE_PATH:e.workspacePath,HYDRA_SOURCE_CWD:e.sourceCwd,HYDRA_WORKSPACE_LABEL:e.label,...e.sessionId!==void 0?{HYDRA_SESSION_ID:e.sessionId}:{}}},(i,a,d)=>{if(i){let c=(d||i.message||"").trim().slice(0,500);r({ok:!1,reason:c.length>0?c:"hook failed"});return}r({ok:!0})});o.stdin?.on("error",()=>{}),o.stdin?.end(t)})}G();Ne();import*as Ze from"fs/promises";import{z as Oe}from"zod";var Sg=Oe.object({version:Oe.literal(1),agentId:Oe.string(),upstreamSessionId:Oe.string(),sessionId:Oe.string().optional(),deletedAt:Oe.string(),upstreamUpdatedAt:Oe.string().optional(),cwd:Oe.string().optional(),title:Oe.string().optional(),reason:Oe.enum(["user","expired"]).optional(),interactive:Oe.boolean().optional()}),ws=class{async add(e){let t={version:1,...e};await fe(x.tombstoneFile(e.agentId,e.upstreamSessionId),t,{mode:384})}async has(e,t){try{return await Ze.access(x.tombstoneFile(e,t)),!0}catch{return!1}}async read(e,t){let n=x.tombstoneFile(e,t),r=await ie(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 Sg.parse(r)}catch{return{version:1,agentId:e,upstreamSessionId:t,deletedAt:new Date(0).toISOString()}}}async remove(e,t){try{await Ze.unlink(x.tombstoneFile(e,t))}catch(n){if(n.code!=="ENOENT")throw n}try{await Ze.rmdir(x.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(x.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(x.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 pd(s,e){return s.reason==="user"||e===void 0?!1:s.upstreamUpdatedAt===void 0?!0:e>s.upstreamUpdatedAt}import*as xd from"fs/promises";import{customAlphabet as _g}from"nanoid";import{fileURLToPath as Ig}from"url";import*as Sn from"path";import*as ks from"fs";function Ag(){try{let s=Sn.dirname(Ig(import.meta.url));for(let e=0;e<8;e+=1){let t=Sn.join(s,"package.json");if(ks.existsSync(t)){let r=JSON.parse(ks.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=Sn.dirname(s);if(n===s)break;s=n}}catch{}return"0.0.0"}var de=Ag(),vs="hydra-acp-cat";var Cg=12e4;async function md(s,e,t){let n=s.timeoutMs??Cg,r,o,i=!1;try{let a=(async()=>{r=it.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:de}}),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=xg(c);if(h.size===0||h.has(s.modelId)){let p=r.connection;try{await at({request:(g,w)=>p.request(g,w),sessionId:u,modelId:s.modelId,verb:jt(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 p=Rg(h);p.length>0&&l.push(p)}),await r.connection.request("session/prompt",{sessionId:u,prompt:[{type:"text",text:e}]});let f=l.join(""),m=t(f);if(!m){let h=JSON.stringify(f.slice(0,200));s.logger?.warn(`synopsis: agent ${s.agentId} reply did not parse (replyLen=${f.length} preview=${h})`);let p=f.slice(0,120).replace(/\s+/g," ").trim();s.onFailure?.(`agent ${s.agentId} returned unparseable JSON (${f.length} chars): ${p}${f.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 bs(s){let e=Wt(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}
|
|
123
123
|
|
|
124
124
|
${e}
|
|
125
125
|
|
|
126
|
-
${
|
|
126
|
+
${no}`:`${t}
|
|
127
127
|
|
|
128
|
-
${
|
|
128
|
+
${no}`;return md(s,n,Za)}async function hd(s){let e=Wt(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}
|
|
129
129
|
|
|
130
130
|
${e}
|
|
131
131
|
|
|
132
|
-
${
|
|
132
|
+
${so}`:`${t}
|
|
133
133
|
|
|
134
|
-
${Xr}`;return ud(s,n,Ka)}function wg(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 kg(s){let e=new Set;cd(e,s.availableModels);let t=s.models;return t&&typeof t=="object"&&!Array.isArray(t)&&cd(e,t.availableModels),e}function cd(s,e){if(Array.isArray(e)){for(let t of e)if(t&&typeof t=="object"){let n=t.modelId??t.value??t.id;typeof n=="string"&&n.length>0&&s.add(n)}}}var vg="guardian_assessment:",bg="Guardian Review";function fd(s,e){return s!==void 0&&s.startsWith(vg)||e===bg}function Sg(s){let e=new Map;for(let t of wd(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 md(s){return Sg(s).map(e=>e.name)}function Ig(s){let e=new Map;for(let t of wd(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 hd(s){return Ig(s).map(e=>e.path)}function yd(s){let e=0;for(let t of s)t.params?.update?.sessionUpdate==="prompt_received"&&(e+=1);return e}function wd(s){let e=new Map,t=0;for(let n of s){let o=n.params?.update;if(!o)continue;let i=o.sessionUpdate;if(i!=="tool_call"&&i!=="tool_call_update")continue;if(i==="tool_call"){let d=typeof o.toolCallId=="string"&&o.toolCallId.length>0?o.toolCallId:void 0,c=typeof o.title=="string"?o.title:void 0;if(fd(d,c))continue;let u=d??`__synth_${t++}`,l=e.get(u);l===void 0?(l={toolName:pd(o),paths:new Set},e.set(u,l)):l.toolName=pd(o);for(let f of gd(o.rawInput,o.locations))l.paths.add(f);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 gd(o.rawInput,o.locations))a.paths.add(d)}return e}function pd(s){return typeof s.name=="string"&&s.name.length>0?s.name:typeof s.title=="string"&&s.title.length>0?s.title:"(unnamed)"}function gd(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 ma(e))t.add(n);return t}G();var Cg=Ag("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",12),Rg=2,vs=class{constructor(e){this.opts=e;this.maxConcurrent=e.maxConcurrent??Rg}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 Te(c,[],{npmRegistry:this.opts.npmRegistry}),l=this.opts.compactionAgent===void 0&&r===void 0,f=n==="compaction"?this.opts.compactionModel??(l?o.currentModel:void 0):this.opts.synopsisModel,m=x.sessionDir(e);if(await Sd.mkdir(m,{recursive:!0}).catch(()=>{}),this.opts.logger?.info(`synopsis: start sessionId=${e} agentId=${d} historyLen=${i.length} model=${JSON.stringify(f??"(default)")} cwd=${m}`),n==="compaction"){let h=this.opts.compactionMaxIterations??3,p=0,g=a??0,w,y=0,k,b=Date.now(),I=Cg(),v={targetAgentId:r},A=R=>this.opts.onCompactionStateChange?.(e,{runId:I,...R},v)??Promise.resolve(),C=R=>{this.opts.broadcastHydraCompaction?.(e,R,v)};await A({status:"requested",requestedAt:b}),C({sessionUpdate:"_hydra_compaction",phase:"started",requestedAt:b});try{do{p++,this.opts.logger?.info(`synopsis: compaction iteration ${p} sessionId=${e} historyLen=${i.length} watermark=${g}`);let R=await this.opts.histories.load(e,{maxEntries:1/0});if(R.length===g)break;let T=await ld({agentId:d,cwd:m,plan:u,history:R,modelId:f,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs,onWorkerSpawned:(H,J)=>{A({status:"running",requestedAt:b,iter:p,worker:{upstreamSessionId:H,pid:J??0}})},onFailure:H=>{k=H}});if(T){let H=kd(T.synopsis,R);H&&vd(H)&&(await this.opts.persistSynopsis(e,H,R.length),w=H,y=R.length,k=void 0,await A({status:"running",requestedAt:b,iter:p}),C({sessionUpdate:"_hydra_compaction",phase:"iteration",iter:p,historyLen:R.length}),await this.opts.onSynthesisArtifact?.(e,H,y,r,I),this.opts.logger?.info(`synopsis: persisted compaction sessionId=${e} iteration=${p} fields=${bd(H)}`))}else this.opts.logger?.warn(`synopsis: sessionId=${e} compaction iteration ${p} returned no result`);if(g=R.length,(await this.opts.histories.load(e,{maxEntries:1/0})).length===g)break}while(p<h);if(w)this.opts.logger?.info(`synopsis: compaction converged sessionId=${e} runId=${I} watermark=${y} iterations=${p}`+(p>=h?` (hit maxIterations=${h})`:"")),C({sessionUpdate:"_hydra_compaction",phase:"converged",iter:p,summarizedThroughEntry:y});else{p>0&&this.opts.logger?.warn(`synopsis: compaction hit maxIterations=${h} without producing artifact sessionId=${e}: ${k??"no reason captured"}`);let R=k??(p===0?"no new history to compact since last summary":`compaction did not produce an artifact after ${p} iteration(s)`);await A({status:"failed",requestedAt:b,iter:p,lastError:R}),C({sessionUpdate:"_hydra_compaction",phase:"failed",error:R}),r&&await this.opts.onSynthesisUnavailable?.(e,r,R)}}catch(R){let T=R instanceof Error?R.message:String(R);if(this.opts.logger?.warn(`synopsis: compaction threw for sessionId=${e}: ${T}`),await A({status:"failed",requestedAt:b,iter:p,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 ks({agentId:d,cwd:m,plan:u,history:i,modelId:f,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 p=kd(h.synopsis,i);p&&vd(p)?(await this.opts.persistSynopsis(e,p,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=${bd(p)}`)):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 kd(s,e){let t=hd(e),n=md(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 vd(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 bd(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(",")}]`}G();import*as X from"fs/promises";import{createReadStream as $g}from"fs";import{createGunzip as Og,gzip as Fg,gunzip as Ng}from"zlib";import{createInterface as Dg}from"readline";import{promisify as Ed}from"util";function Id(s){return s==="summary"?"summary":"inline"}var go=256,xg=["totalMatches","totalFiles","referenceCount","truncated","exitCode"],Eg=["content","stdout","stderr"];function Ad(s,e){return e!=="summary"?s:s.map(Tg)}function Tg(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(Cd));let i=r.rawOutput;if(i&&typeof i=="object"&&!Array.isArray(i)){let a=i,d={};a.error!==void 0&&(d.error=bs(a.error)),a.metadata!==void 0&&(d.metadata=a.metadata);for(let c of xg)a[c]!==void 0&&(d[c]=a[c]);for(let c of Eg)typeof a[c]=="string"&&(d[c]=bs(a[c]));o.rawOutput=d}return{...s,params:{...t,update:o}}}function Pg(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&s.type==="diff"}function Cd(s){if(Pg(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=bs(e.text)),typeof e.content=="string"?t.content=bs(e.content):e.content&&typeof e.content=="object"&&(t.content=Cd(e.content)),t}function bs(s){if(typeof s=="string"&&s.length>go){let e=s.length-go;return`${s.slice(0,go)}\u2026[+${e} chars omitted from summary export]`}return s}var Mg=2048;function Rd(s){let e=new Set,t=n=>{if(xd(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 xd(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&typeof s.__hydraBlob=="string"}function _g(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 yo(s,e){if(!_g(s))return s;let t=s.params,n=t.update,r=await mo(n,e);return{...s,params:{...t,update:r}}}async function mo(s,e){if(typeof s=="string"){if(s.length<=Mg)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 mo(n,e));return t}if(s&&typeof s=="object"){let t={};for(let[n,r]of Object.entries(s))t[n]=await mo(r,e);return t}return s}async function wo(s,e){let t=s.params;if(!t||typeof t!="object"||Array.isArray(t))return s;let n=await ho(t,e);return n===t?s:{...s,params:n}}async function ho(s,e){if(xd(s))return await e(s.__hydraBlob)??"";if(Array.isArray(s)){let t=!1,n=[];for(let r of s){let o=await ho(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 ho(o,e);i!==o&&(t=!0),n[r]=i}return t?n:s}return s}var jg=Ed(Fg),Hg=Ed(Ng),Lg=/^history\.jsonl\.(\d+)(\.gz)?$/,Fe=/^[A-Za-z0-9_-]+$/,Ug=1e3,Bg=1e7,Wg=10,Ss=class{writeQueues=new Map;maxEntries;archiveMaxBytes;archiveTiers;nextArchiveIndex=new Map;archiveLineCounts=new Map;constructor(e={}){this.maxEntries=e.maxEntries??Ug,this.archiveMaxBytes=e.archiveMaxBytes??Bg,this.archiveTiers=e.archiveTiers??Wg}async append(e,t){if(Fe.test(e))return this.enqueue(e,async()=>{await X.mkdir(x.sessionDir(e),{recursive:!0});let n=await yo(t,o=>wr(e,o)),r=JSON.stringify(n)+`
|
|
135
|
-
`;await X.appendFile(x.historyFile(e),r,{encoding:"utf8",mode:384})})}async rewrite(e,t){if(Fe.test(e))return this.enqueue(e,async()=>{await X.mkdir(x.sessionDir(e),{recursive:!0});let n=[];for(let o of t)n.push(await
|
|
134
|
+
${so}`;return md(s,n,ed)}function Rg(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 xg(s){let e=new Set;gd(e,s.availableModels);let t=s.models;return t&&typeof t=="object"&&!Array.isArray(t)&&gd(e,t.availableModels),e}function gd(s,e){if(Array.isArray(e)){for(let t of e)if(t&&typeof t=="object"){let n=t.modelId??t.value??t.id;typeof n=="string"&&n.length>0&&s.add(n)}}}var Eg="guardian_assessment:",Tg="Guardian Review";function yd(s,e){return s!==void 0&&s.startsWith(Eg)||e===Tg}function Pg(s){let e=new Map;for(let t of Id(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 vd(s){return Pg(s).map(e=>e.name)}function Mg(s){let e=new Map;for(let t of Id(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 bd(s){return Mg(s).map(e=>e.path)}function Sd(s){let e=0;for(let t of s)t.params?.update?.sessionUpdate==="prompt_received"&&(e+=1);return e}function Id(s){let e=new Map,t=0;for(let n of s){let o=n.params?.update;if(!o)continue;let i=o.sessionUpdate;if(i!=="tool_call"&&i!=="tool_call_update")continue;if(i==="tool_call"){let d=typeof o.toolCallId=="string"&&o.toolCallId.length>0?o.toolCallId:void 0,c=typeof o.title=="string"?o.title:void 0;if(yd(d,c))continue;let u=d??`__synth_${t++}`,l=e.get(u);l===void 0?(l={toolName:wd(o),paths:new Set},e.set(u,l)):l.toolName=wd(o);for(let f of kd(o.rawInput,o.locations))l.paths.add(f);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 kd(o.rawInput,o.locations))a.paths.add(d)}return e}function wd(s){return typeof s.name=="string"&&s.name.length>0?s.name:typeof s.title=="string"&&s.title.length>0?s.title:"(unnamed)"}function kd(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 va(e))t.add(n);return t}G();var $g=_g("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",12),Og=2,Ss=class{constructor(e){this.opts=e;this.maxConcurrent=e.maxConcurrent??Og}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 Ee(c,[],{npmRegistry:this.opts.npmRegistry}),l=this.opts.compactionAgent===void 0&&r===void 0,f=n==="compaction"?this.opts.compactionModel??(l?o.currentModel:void 0):this.opts.synopsisModel,m=x.sessionDir(e);if(await xd.mkdir(m,{recursive:!0}).catch(()=>{}),this.opts.logger?.info(`synopsis: start sessionId=${e} agentId=${d} historyLen=${i.length} model=${JSON.stringify(f??"(default)")} cwd=${m}`),n==="compaction"){let h=this.opts.compactionMaxIterations??3,p=0,g=a??0,w,y=0,k,b=Date.now(),I=$g(),v={targetAgentId:r},A=R=>this.opts.onCompactionStateChange?.(e,{runId:I,...R},v)??Promise.resolve(),C=R=>{this.opts.broadcastHydraCompaction?.(e,R,v)};await A({status:"requested",requestedAt:b}),C({sessionUpdate:"_hydra_compaction",phase:"started",requestedAt:b});try{do{p++,this.opts.logger?.info(`synopsis: compaction iteration ${p} sessionId=${e} historyLen=${i.length} watermark=${g}`);let R=await this.opts.histories.load(e,{maxEntries:1/0});if(R.length===g)break;let T=await hd({agentId:d,cwd:m,plan:u,history:R,modelId:f,sessionId:e,logger:this.opts.logger,timeoutMs:this.opts.generateTimeoutMs,onWorkerSpawned:(U,J)=>{A({status:"running",requestedAt:b,iter:p,worker:{upstreamSessionId:U,pid:J??0}})},onFailure:U=>{k=U}});if(T){let U=Ad(T.synopsis,R);U&&Cd(U)&&(await this.opts.persistSynopsis(e,U,R.length),w=U,y=R.length,k=void 0,await A({status:"running",requestedAt:b,iter:p}),C({sessionUpdate:"_hydra_compaction",phase:"iteration",iter:p,historyLen:R.length}),await this.opts.onSynthesisArtifact?.(e,U,y,r,I),this.opts.logger?.info(`synopsis: persisted compaction sessionId=${e} iteration=${p} fields=${Rd(U)}`))}else this.opts.logger?.warn(`synopsis: sessionId=${e} compaction iteration ${p} returned no result`);if(g=R.length,(await this.opts.histories.load(e,{maxEntries:1/0})).length===g)break}while(p<h);if(w)this.opts.logger?.info(`synopsis: compaction converged sessionId=${e} runId=${I} watermark=${y} iterations=${p}`+(p>=h?` (hit maxIterations=${h})`:"")),C({sessionUpdate:"_hydra_compaction",phase:"converged",iter:p,summarizedThroughEntry:y});else{p>0&&this.opts.logger?.warn(`synopsis: compaction hit maxIterations=${h} without producing artifact sessionId=${e}: ${k??"no reason captured"}`);let R=k??(p===0?"no new history to compact since last summary":`compaction did not produce an artifact after ${p} iteration(s)`);await A({status:"failed",requestedAt:b,iter:p,lastError:R}),C({sessionUpdate:"_hydra_compaction",phase:"failed",error:R}),r&&await this.opts.onSynthesisUnavailable?.(e,r,R)}}catch(R){let T=R instanceof Error?R.message:String(R);if(this.opts.logger?.warn(`synopsis: compaction threw for sessionId=${e}: ${T}`),await A({status:"failed",requestedAt:b,iter:p,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 bs({agentId:d,cwd:m,plan:u,history:i,modelId:f,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 p=Ad(h.synopsis,i);p&&Cd(p)?(await this.opts.persistSynopsis(e,p,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=${Rd(p)}`)):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 Ad(s,e){let t=bd(e),n=vd(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 Cd(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 Rd(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(",")}]`}G();import*as X from"fs/promises";import{createReadStream as Ug}from"fs";import{createGunzip as Bg,gzip as Wg,gunzip as qg}from"zlib";import{createInterface as zg}from"readline";import{promisify as $d}from"util";function Ed(s){return s==="summary"?"summary":"inline"}var ko=256,Fg=["totalMatches","totalFiles","referenceCount","truncated","exitCode"],Ng=["content","stdout","stderr"];function Td(s,e){return e!=="summary"?s:s.map(Dg)}function Dg(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(Pd));let i=r.rawOutput;if(i&&typeof i=="object"&&!Array.isArray(i)){let a=i,d={};a.error!==void 0&&(d.error=Is(a.error)),a.metadata!==void 0&&(d.metadata=a.metadata);for(let c of Fg)a[c]!==void 0&&(d[c]=a[c]);for(let c of Ng)typeof a[c]=="string"&&(d[c]=Is(a[c]));o.rawOutput=d}return{...s,params:{...t,update:o}}}function jg(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&s.type==="diff"}function Pd(s){if(jg(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=Is(e.text)),typeof e.content=="string"?t.content=Is(e.content):e.content&&typeof e.content=="object"&&(t.content=Pd(e.content)),t}function Is(s){if(typeof s=="string"&&s.length>ko){let e=s.length-ko;return`${s.slice(0,ko)}\u2026[+${e} chars omitted from summary export]`}return s}var Hg=2048;function Md(s){let e=new Set,t=n=>{if(_d(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 _d(s){return!!s&&typeof s=="object"&&!Array.isArray(s)&&typeof s.__hydraBlob=="string"}function Lg(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 So(s,e){if(!Lg(s))return s;let t=s.params,n=t.update,r=await vo(n,e);return{...s,params:{...t,update:r}}}async function vo(s,e){if(typeof s=="string"){if(s.length<=Hg)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 vo(n,e));return t}if(s&&typeof s=="object"){let t={};for(let[n,r]of Object.entries(s))t[n]=await vo(r,e);return t}return s}async function Io(s,e){let t=s.params;if(!t||typeof t!="object"||Array.isArray(t))return s;let n=await bo(t,e);return n===t?s:{...s,params:n}}async function bo(s,e){if(_d(s))return await e(s.__hydraBlob)??"";if(Array.isArray(s)){let t=!1,n=[];for(let r of s){let o=await bo(r,e);o!==r&&(t=!0),n.push(o)}return t?n:s}if(s&&typeof s=="object"){let t=!1,n={};for(let[r,o]of Object.entries(s)){let i=await bo(o,e);i!==o&&(t=!0),n[r]=i}return t?n:s}return s}var Jg=$d(Wg),Vg=$d(qg),Gg=/^history\.jsonl\.(\d+)(\.gz)?$/,Fe=/^[A-Za-z0-9_-]+$/,Kg=1e3,Qg=1e7,Yg=10,As=class{writeQueues=new Map;maxEntries;archiveMaxBytes;archiveTiers;nextArchiveIndex=new Map;archiveLineCounts=new Map;constructor(e={}){this.maxEntries=e.maxEntries??Kg,this.archiveMaxBytes=e.archiveMaxBytes??Qg,this.archiveTiers=e.archiveTiers??Yg}async append(e,t){if(Fe.test(e))return this.enqueue(e,async()=>{await X.mkdir(x.sessionDir(e),{recursive:!0});let n=await So(t,o=>Ir(e,o)),r=JSON.stringify(n)+`
|
|
135
|
+
`;await X.appendFile(x.historyFile(e),r,{encoding:"utf8",mode:384})})}async rewrite(e,t){if(Fe.test(e))return this.enqueue(e,async()=>{await X.mkdir(x.sessionDir(e),{recursive:!0});let n=[];for(let o of t)n.push(await So(o,i=>Ir(e,i)));let r=n.length===0?"":n.map(o=>JSON.stringify(o)).join(`
|
|
136
136
|
`)+`
|
|
137
137
|
`;await X.writeFile(x.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 X.readFile(x.historyFile(e),"utf8")}catch(a){if(a.code==="ENOENT")return;throw a}let r=n.split(`
|
|
138
138
|
`).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 X.writeFile(x.historyFile(e),i.join(`
|
|
139
139
|
`)+`
|
|
140
140
|
`,{encoding:"utf8",mode:384})})}async spillToArchive(e,t){let n=t.join(`
|
|
141
141
|
`)+`
|
|
142
|
-
`,r=await this.resolveNextArchiveIndex(e);await this.enforceArchiveTierCap(e,r);let o=x.historyArchiveFile(e,r);await X.mkdir(x.sessionDir(e),{recursive:!0}),await X.appendFile(o,n,{encoding:"utf8",mode:384});let i=0;try{i=(await X.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=x.historyArchiveFile(e,t),r;try{r=await X.readFile(n)}catch(i){if(i.code==="ENOENT")return;throw i}let o=await
|
|
143
|
-
`)){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
|
|
144
|
-
`)){if(f.length===0)continue;let m;try{m=JSON.parse(f)}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 f=>{let m=c.get(f);if(m!==void 0)return m;let h=await
|
|
142
|
+
`,r=await this.resolveNextArchiveIndex(e);await this.enforceArchiveTierCap(e,r);let o=x.historyArchiveFile(e,r);await X.mkdir(x.sessionDir(e),{recursive:!0}),await X.appendFile(o,n,{encoding:"utf8",mode:384});let i=0;try{i=(await X.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=x.historyArchiveFile(e,t),r;try{r=await X.readFile(n)}catch(i){if(i.code==="ENOENT")return;throw i}let o=await Jg(r);await X.writeFile(n+".gz",o,{mode:384});try{await X.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=x.historyArchiveFile(e,r),a=i+".gz",d=!1;try{await X.access(a),d=!0}catch{d=!1}if(d)o=r+1;else try{(await X.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=x.historyArchiveFile(e,t);for(let r of[n,n+".gz"])try{await X.unlink(r)}catch(o){if(o.code!=="ENOENT")throw o}this.archiveLineCounts.delete(e)}async listArchiveIndices(e){let t;try{t=await X.readdir(x.sessionDir(e))}catch(r){if(r.code==="ENOENT")return[];throw r}let n=new Set;for(let r of t){let o=Gg.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=x.historyArchiveFile(e,r),i=o+".gz",a=o;try{await X.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 X.readFile(o);i=(await Vg(a)).toString("utf8")}else i=await X.readFile(o,"utf8")}catch(a){if(a.code==="ENOENT")continue;throw a}for(let a of i.split(`
|
|
143
|
+
`)){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=Ug(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(Bg()):t,o=zg({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 Io(t,async r=>{let o=n.get(r);if(o!==void 0)return o;let i=await dn(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(x.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 f=a[c];for(let m=l.length-1;m>=0;m--){let h=await this.hydrateEntry(e,l[m],o);yield{entryId:f+m,entry:h}}}}async pageBefore(e,t){let n=[],r=0,o=!1,i=!1;for await(let{entry:a}of this.iterRecallNewestFirst(e)){if(!o){if(a.seq===void 0||a.seq>=t.beforeSeq)continue;o=!0}if(t.skip?.(a))continue;if(r>=t.turns){i=!0;break}let d=a.params?.update;n.push(a),d?.sessionUpdate==="prompt_received"&&(r+=1)}return n.reverse(),{entries:n,hasMore:i}}async rangeSlice(e,t,n){if(!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,f=c+u.lineCount;if(c=f,f<=t)continue;if(l>n)break;let m=0;for await(let h of this.streamFile(u.path)){let p=l+m;if(m+=1,p<t)continue;if(p>n)break;let g=await this.hydrateEntry(e,h,d);a.push({entryId:p,entry:g})}}if(n>=i){let u=Math.max(t-i,0),l=n-i,f=0;for await(let m of this.streamFile(x.historyFile(e))){if(f>l)break;if(f>=u){let h=await this.hydrateEntry(e,m,d);a.push({entryId:i+f,entry:h})}f+=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(x.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 X.readFile(x.historyFile(e),"utf8")}catch(f){if(f.code==="ENOENT")return[];throw f}let i=[];for(let f of o.split(`
|
|
144
|
+
`)){if(f.length===0)continue;let m;try{m=JSON.parse(f)}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 f=>{let m=c.get(f);if(m!==void 0)return m;let h=await dn(e,f);return c.set(f,h),h},l=[];for(let f of d)l.push(await Io(f,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 X.unlink(x.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 _i(e);try{await X.rmdir(x.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}};G();import{promises as Od}from"fs";import*as Fd from"path";async function Nd(s,e){await Od.mkdir(Fd.dirname(s),{recursive:!0});let t=e.map(n=>JSON.stringify(n));await Od.writeFile(s,t.length>0?t.join(`
|
|
145
145
|
`)+`
|
|
146
|
-
`:"")}import{z as V}from"zod";var qg=V.object({method:V.string(),params:V.unknown(),recordedAt:V.number()}),zg=V.object({sessionId:V.string(),lineageId:V.string(),upstreamSessionId:V.string().optional(),agentId:V.string(),cwd:V.string(),title:V.string().optional(),synopsis:mn.optional(),summarizedThroughEntry:V.number().int().nonnegative().optional(),currentModel:V.string().optional(),currentMode:V.string().optional(),currentUsage:to.optional(),agentCommands:V.array(Zr).optional(),agentModes:V.array(eo).optional(),interactive:V.boolean().optional(),originatingClient:no.optional(),priority:V.number().int().nonnegative().optional(),createdAt:V.string(),updatedAt:V.string()}),Jg=V.object({version:V.literal(1),exportedAt:V.string(),exportedFrom:V.object({hydraVersion:V.string(),machine:V.string(),hydraHost:V.string().optional()}),session:zg,history:V.array(qg),promptHistory:V.array(V.string()).optional(),toolBlobs:V.record(V.string()).optional()});function Sn(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 _d(s){return Jg.parse(s)}function ko(s){if(s&&!(s.costAmount===void 0&&s.cumulativeCost===void 0))return(s.cumulativeCost??0)+(s.costAmount??0)}function In(s){if(!s)return;let e={};s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size);let t=ko(s);return t&&(e.costAmount=t),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),e}var $d=900*1e3,Gg=12,Kg="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",bt=Vg(Kg,16);function Qg(){let s,e,t=!1;return{send(n){if(t)return Promise.resolve();if("method"in n&&"id"in n){let r={jsonrpc:"2.0",id:n.id,error:{code:E.MethodNotFound,message:`no handler for ${n.method} (headless fork-prompt client)`}};queueMicrotask(()=>s?.(r))}return Promise.resolve()},onMessage(n){s=n},onClose(n){e=n},close(){return t||(t=!0,e?.()),Promise.resolve()}}}var Is=class s{constructor(e,t,n,r={}){this.registry=e;this.spawner=t??(a=>it.spawn(a)),this.store=n??new os,this.tombstones=r.tombstones??new hs,this.sessionHistoryMaxEntries=r.sessionHistoryMaxEntries??1e3,this.histories=new Ss({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 vs({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?Gg: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 Ot(this.registry);this.agentCatalog=e.map(t=>({id:t.id,name:t.name,...t.description!==void 0?{description:t.description}:{}}))}catch{}}async adoptWorkspace(e,t,n){let r=t.label;if(r===void 0)throw new Error("workspace.adopt requires workspace.label");let o=this.liveSessionsWithLabel(n.cwd,r)[0]?.workspace,i=o!==void 0?this.asWorkspace(o):(await e.listWorkspaces(n.cwd).catch(()=>[])).find(a=>a.label===r);if(i===void 0)throw new Error(`cannot adopt workspace "${r}": no workspace by that name derived from ${O(n.cwd)}`);return await this.enqueueKeyed(this.workspaceQueues,i.path,async()=>(e.capabilities().locking&&await e.lock(i,`session ${n.title??"live"}`).catch(()=>{}),{cwd:i.path,workspace:{path:i.path,sourceCwd:i.sourceCwd,label:i.label,provider:i.provider,...i.snapshot!==void 0?{snapshot:i.snapshot}:{},...i.line!==void 0?{line:i.line}:{},...i.vcs!==void 0?{vcs:{...i.vcs}}:{},...o?.clean!==void 0?{clean:o.clean}:{}}}))}async resolveWorkspace(e){let t=e.workspace;if(t===void 0)return{cwd:e.cwd};let n=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}}if(t.adopt===!0)return await this.adoptWorkspace(n,t,e);let r=t.label??`s-${bt().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 gs(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 po(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 ms(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=`${Ie}${bt()}`,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_${bt()}`,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 Bt({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=E.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=E.AgentNotInstalled,k}if(e.upstreamSessionId==="")return this.doResurrectFromImport(e);if(!await this.dirExists(e.cwd))return this.doResurrectFromImport(e);let r=await Te(n,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),o=Bn(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:Ft,clientInfo:{name:"hydra",version:le}});a=k.agentCapabilities,i.authMethods=Cn(k.authMethods),i.steeringSupported=An(k)}catch(k){throw await i.kill().catch(()=>{}),lt(k,i)}let d;try{let k=bo(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===E.AuthRequired)throw await i.kill().catch(()=>{}),lt(k,i);return process.stderr.write(`session/load failed for upstream ${e.upstreamSessionId} on ${e.agentId} (${k.message}); recovering via import-reseed
|
|
147
|
-
`),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=Co(d??{}),u=e.agentModes??ut(Ao(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 ht({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 f=So(d??{}),m=ut(Io(d??{}))??e.agentModels;if(this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedModel=${JSON.stringify(e.currentModel)} agentReportedModel=${JSON.stringify(f)} 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=Nt(d),p=await yt({agent:i,upstreamSessionId:e.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:f,...h?{modelVerb:h}:{},logger:this.logger}),g=p.modelId,w=ut(It(St(p.result)?p.result:d??{}));if(w=ut(await this.restoreConfigOptionValues(i,e.upstreamSessionId,e.configOptionValues,w??[])),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 Bt({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,upstreamRespawned:!0,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,I)=>this.runWorkspaceAction(y.sessionId,k,b,I),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 ht({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:r.initialMode,advertisedModes:o,logger:this.logger}),a=e.agentModels??r.initialModels,d=await yt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:r.initialModel,...r.modelVerb?{modelVerb:r.modelVerb}:{},logger:this.logger}),c=d.modelId,u=St(d.result)?ut(It(d.result)):void 0;u=ut(await this.restoreConfigOptionValues(r.agent,r.upstreamSessionId,e.configOptionValues,u??r.initialConfigOptions??[])),r.agent.connection.drainBuffered("session/update");let l=new Bt({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:f=>this.bootstrapAgent({...f,mcpServers:f.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),loadExistingAgentSession:(f,m)=>this.bootstrapAgentLoad(f,{...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,upstreamRespawned:!0,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:f=>this.scheduleCompaction(l.sessionId,f),resolveAgentId:async f=>(await this.registry.getAgent(f))?.id,getCompactionState:()=>this.getCompactionState(l.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(l.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(l.sessionId),uncompactHook:()=>this.performUncompact(l.sessionId),forkHook:f=>this.forkSession(l.sessionId,f??{}),workspaceHook:(f,m,h)=>this.runWorkspaceAction(l.sessionId,f,m,h),onCompactionSwapHook:f=>{this.persistRollbackBreadcrumb(l.sessionId,f).catch(()=>{})},persistWatermarkHook:f=>{this.mutateRecord(l.sessionId,{summarizedThroughEntry:f}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(l.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(l),e.forkedFromSessionId&&e.forkSynthesisState==="running"?this.logger?.info(`fork ${l.sessionId}: synthesis in flight \u2014 skipping seed, recall available`):e.forkedFromSessionId&&(e.synopsis||(e.summarizedThroughEntry??0)>0)?l.seedFromFork(e.synopsis).catch(()=>{}):l.seedFromImport().catch(()=>{}),l}async dirExists(e){try{return(await At.stat(e)).isDirectory()}catch{return!1}}async reapIfOrphanedNonInteractive(e){let t=this.sessions.get(e);if(!(!t||t.attachedCount>0)&&t.interactive!==!0){if(t.hasWorkInFlight){this.logger?.info(`deferring reap of ${e}: work still in flight after detach`),t.onceIdle(n=>{this.reapIfOrphanedNonInteractive(n.sessionId).catch(()=>{})});return}this.logger?.info(`reaping orphaned non-interactive session ${e} (agent killed, cold record kept)`),await t.close({deleteRecord:!1,by:"reap-orphaned"}).catch(()=>{})}}async resolveResurrectTarget(e,t){if(await this.dirExists(e))return t!==void 0?{cwd:e,workspace:t}:{cwd:e};if(t!==void 0){let n=await this.recoverWorkspace(t);if(n!==void 0)return{cwd:n.path,workspace:n}}return{cwd:ce(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(`${O(t.path)} is shared with ${r.map(m=>Xe(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 ${O(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 p=m.length>0?`
|
|
146
|
+
`:"")}import{z as V}from"zod";var Xg=V.object({method:V.string(),params:V.unknown(),recordedAt:V.number()}),Zg=V.object({sessionId:V.string(),lineageId:V.string(),upstreamSessionId:V.string().optional(),agentId:V.string(),cwd:V.string(),title:V.string().optional(),synopsis:hn.optional(),summarizedThroughEntry:V.number().int().nonnegative().optional(),currentModel:V.string().optional(),currentMode:V.string().optional(),currentUsage:io.optional(),agentCommands:V.array(ro).optional(),agentModes:V.array(oo).optional(),interactive:V.boolean().optional(),originatingClient:ao.optional(),priority:V.number().int().nonnegative().optional(),createdAt:V.string(),updatedAt:V.string()}),em=V.object({version:V.literal(1),exportedAt:V.string(),exportedFrom:V.object({hydraVersion:V.string(),machine:V.string(),hydraHost:V.string().optional()}),session:Zg,history:V.array(Xg),promptHistory:V.array(V.string()).optional(),toolBlobs:V.record(V.string()).optional()});function In(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 Dd(s){return em.parse(s)}function Ao(s){if(s&&!(s.costAmount===void 0&&s.cumulativeCost===void 0))return(s.cumulativeCost??0)+(s.costAmount??0)}function An(s){if(!s)return;let e={};s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size);let t=Ao(s);return t&&(e.costAmount=t),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),e}var jd=900*1e3,nm=12,sm="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",St=tm(sm,16);function rm(){let s,e,t=!1;return{send(n){if(t)return Promise.resolve();if("method"in n&&"id"in n){let r={jsonrpc:"2.0",id:n.id,error:{code:E.MethodNotFound,message:`no handler for ${n.method} (headless fork-prompt client)`}};queueMicrotask(()=>s?.(r))}return Promise.resolve()},onMessage(n){s=n},onClose(n){e=n},close(){return t||(t=!0,e?.()),Promise.resolve()}}}var Cs=class s{constructor(e,t,n,r={}){this.registry=e;this.spawner=t??(a=>it.spawn(a)),this.store=n??new as,this.tombstones=r.tombstones??new ws,this.sessionHistoryMaxEntries=r.sessionHistoryMaxEntries??1e3,this.histories=new As({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 Ss({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?nm: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 Nt(this.registry);this.agentCatalog=e.map(t=>({id:t.id,name:t.name,...t.description!==void 0?{description:t.description}:{}}))}catch{}}async adoptWorkspace(e,t,n){let r=t.label;if(r===void 0)throw new Error("workspace.adopt requires workspace.label");let o=this.liveSessionsWithLabel(n.cwd,r)[0]?.workspace,i=o!==void 0?this.asWorkspace(o):(await e.listWorkspaces(n.cwd).catch(()=>[])).find(a=>a.label===r);if(i===void 0)throw new Error(`cannot adopt workspace "${r}": no workspace by that name derived from ${O(n.cwd)}`);return await this.enqueueKeyed(this.workspaceQueues,i.path,async()=>(e.capabilities().locking&&await e.lock(i,`session ${n.title??"live"}`).catch(()=>{}),{cwd:i.path,workspace:{path:i.path,sourceCwd:i.sourceCwd,label:i.label,provider:i.provider,...i.snapshot!==void 0?{snapshot:i.snapshot}:{},...i.line!==void 0?{line:i.line}:{},...i.vcs!==void 0?{vcs:{...i.vcs}}:{},...o?.clean!==void 0?{clean:o.clean}:{}}}))}async resolveWorkspace(e){let t=e.workspace;if(t===void 0)return{cwd:e.cwd};let n=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}}if(t.adopt===!0)return await this.adoptWorkspace(n,t,e);let r=t.label??`s-${St().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 hs(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 wo(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 ys(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=`${Se}${St()}`,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_${St()}`,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 qt({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=E.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=E.AgentNotInstalled,k}if(e.upstreamSessionId==="")return this.doResurrectFromImport(e);if(!await this.dirExists(e.cwd))return this.doResurrectFromImport(e);let r=await Ee(n,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),o=qn(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:Dt,clientInfo:{name:"hydra",version:de}});a=k.agentCapabilities,i.authMethods=Rn(k.authMethods),i.steeringSupported=Cn(k)}catch(k){throw await i.kill().catch(()=>{}),lt(k,i)}let d;try{let k=Ro(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===E.AuthRequired)throw await i.kill().catch(()=>{}),lt(k,i);return process.stderr.write(`session/load failed for upstream ${e.upstreamSessionId} on ${e.agentId} (${k.message}); recovering via import-reseed
|
|
147
|
+
`),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=Po(d??{}),u=e.agentModes??ut(To(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 yt({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 f=xo(d??{}),m=ut(Eo(d??{}))??e.agentModels;if(this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedModel=${JSON.stringify(e.currentModel)} agentReportedModel=${JSON.stringify(f)} 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=jt(d),p=await wt({agent:i,upstreamSessionId:e.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:f,...h?{modelVerb:h}:{},logger:this.logger}),g=p.modelId,w=ut(At(It(p.result)?p.result:d??{}));if(w=ut(await this.restoreConfigOptionValues(i,e.upstreamSessionId,e.configOptionValues,w??[])),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 qt({sessionId:e.hydraSessionId,cwd:e.cwd,...e.workspace!==void 0?{workspace:e.workspace}:{},agentId:e.agentId,agent:i,upstreamSessionId:e.upstreamSessionId,agentMeta:d?._meta,agentCapabilities:a,...h?{modelVerb:h}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,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,upstreamRespawned:!0,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,I)=>this.runWorkspaceAction(y.sessionId,k,b,I),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 yt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:r.initialMode,advertisedModes:o,logger:this.logger}),a=e.agentModels??r.initialModels,d=await wt({agent:r.agent,upstreamSessionId:r.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:r.initialModel,...r.modelVerb?{modelVerb:r.modelVerb}:{},logger:this.logger}),c=d.modelId,u=It(d.result)?ut(At(d.result)):void 0;u=ut(await this.restoreConfigOptionValues(r.agent,r.upstreamSessionId,e.configOptionValues,u??r.initialConfigOptions??[])),r.agent.connection.drainBuffered("session/update");let l=new qt({sessionId:e.hydraSessionId,cwd:n,...t.workspace!==void 0?{workspace:t.workspace}:{},agentId:e.agentId,agent:r.agent,upstreamSessionId:r.upstreamSessionId,agentMeta:r.agentMeta,agentCapabilities:r.agentCapabilities,...r.modelVerb?{modelVerb:r.modelVerb}:{},title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,orphanTimeoutMs:this.orphanTimeoutMs,logger:this.logger,spawnReplacementAgent:f=>this.bootstrapAgent({...f,mcpServers:f.mcpServers??e.mcpServers??[],selfSessionId:e.hydraSessionId}),loadExistingAgentSession:(f,m)=>this.bootstrapAgentLoad(f,{...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,upstreamRespawned:!0,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:f=>this.scheduleCompaction(l.sessionId,f),resolveAgentId:async f=>(await this.registry.getAgent(f))?.id,getCompactionState:()=>this.getCompactionState(l.sessionId),getUpstreamGenerations:()=>this.getUpstreamGenerations(l.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(l.sessionId),uncompactHook:()=>this.performUncompact(l.sessionId),forkHook:f=>this.forkSession(l.sessionId,f??{}),workspaceHook:(f,m,h)=>this.runWorkspaceAction(l.sessionId,f,m,h),onCompactionSwapHook:f=>{this.persistRollbackBreadcrumb(l.sessionId,f).catch(()=>{})},persistWatermarkHook:f=>{this.mutateRecord(l.sessionId,{summarizedThroughEntry:f}).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=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(`${O(t.path)} is shared with ${r.map(m=>Xe(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 ${O(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 p=m.length>0?`
|
|
148
148
|
${m.map(g=>` ${g}`).join(`
|
|
149
149
|
`)}`:` (${l.reason??"the integration failed"})`;return m.length===0?{ok:!1,message:`the source could not be merged into ${O(t.path)}; nothing changed.${p}
|
|
150
150
|
`+(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:${p}`}):{ok:!1,message:`Synced with conflicts. ${m.length} file(s) need resolving in ${O(t.path)}:${p}
|
|
151
|
-
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 f=(await i.changedPathsBetween(t.path,d,l.snapshot)).length;return{ok:!0,message:`Synced ${O(t.path)} with ${O(t.sourceCwd)}: ${u} commit(s), ${f} 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=
|
|
151
|
+
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 f=(await i.changedPathsBetween(t.path,d,l.snapshot)).length;return{ok:!0,message:`Synced ${O(t.path)} with ${O(t.sourceCwd)}: ${u} commit(s), ${f} 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=ud(e.label);if(await n.retainSnapshot(a,u,c).then(()=>n.resolveRetained(a,u)).catch(()=>{})===void 0)return;let f={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 bt({source:e.path,capture:f,provider:n});return{ok:!1,message:`Could not clear ${O(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 bt({source:e.path,capture:f,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.
|
|
152
152
|
`+(b?`Your uncommitted work is back in place (unstaged) and nothing else changed. Commit it in ${O(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:
|
|
153
|
-
${m}`)}}let g=await
|
|
153
|
+
${m}`)}}let g=await bt({source:e.path,capture:f,provider:n}),w=await n.currentState(e.path),y=w===void 0?0:(await n.changedPathsBetween(e.path,r,w)).length,k=`Synced ${O(e.path)} with ${O(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}
|
|
154
154
|
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:
|
|
155
|
-
${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`${O(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
|
|
155
|
+
${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`${O(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 hs(t.sourceCwd).catch(()=>({}));if(o.preRemove!==void 0){let a=await ys(o.preRemove,{workspacePath:t.path,sourceCwd:t.sourceCwd,label:t.label,...n!==void 0?{sessionId:n}:{},...o.hookTimeoutSeconds!==void 0?{timeoutSeconds:o.hookTimeoutSeconds}:{}});a.ok||this.logger?.warn?.(`session workspace: preRemove failed for ${t.path}: ${a.reason??"unknown"}`)}let i=await e.status(r).catch(()=>({clean:!1,changedPaths:["<unknown>"],hasRecordedWork:!1}));if(i.changedPaths.length>0){await e.dropSnapshotRef(r,Gt(t.label).autosave).catch(()=>{}),this.logger?.warn?.(`session workspace: keeping ${t.path} \u2014 it has ${i.changedPaths.length} uncommitted change(s) that removal would destroy. Remove it by hand once you have salvaged or discarded them.`);return}for(let a of fd(t.label))await e.dropSnapshotRef(r,a).catch(()=>{});await e.removeWorkspace(r,{force:!0}).catch(a=>this.logger?.warn?.(`session workspace: could not remove ${t.path}: ${String(a)}`))}snapshotRefFor(e){return Gt(e).autosave}startRefFor(e){return Gt(e).start}baselineRefFor(e){return Gt(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(`
|
|
156
156
|
${O(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.
|
|
157
157
|
`))}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(o.cwd)}.
|
|
158
158
|
Use \`/hydra workspace start\` to move into an isolated workspace.`;let d=this.liveSessionsIn(a.path,o.sessionId).map(m=>Xe(m.sessionId)),c=a.line,u=[`Isolated in ${O(a.path)}`,` source: ${O(a.sourceCwd)}`,` provider: ${a.provider}${c!==void 0?` (${c})`:""}`];d.length>0&&u.push(` shared with: ${d.join(", ")}`);let f=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 f??[])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(`
|
|
@@ -162,44 +162,44 @@ Use \`/hydra workspace start\` to move into an isolated workspace.`;let d=this.l
|
|
|
162
162
|
`)}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(`
|
|
163
163
|
`)}if(t==="discard"){let a=this.liveSessionsIn(i.path,o.sessionId);if(a.length>0)throw new Error(`${O(i.path)} is shared with ${a.map(u=>Xe(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 ${O(i.path)} and its branch ${i.line??"(none)"}; returned to ${O(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(`
|
|
164
164
|
`)}return o.broadcastWorkspacePhase({phase:"returning"}),await this.leaveWorkspace(o,i,{exit:"detached"}),[`Returned to ${O(i.sourceCwd)} WITHOUT merging.`,`The workspace is still at ${O(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(`
|
|
165
|
-
`)}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=
|
|
166
|
-
`)})}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 ${O(n)} no longer exists`);let i=ne(e.provider),a=this.asWorkspace(e),d=await
|
|
165
|
+
`)}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=ld(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(`${O(t.path)} is shared with ${r.map(k=>Xe(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,f=(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 p=await i.resetTo(t.path,d,{purgeIgnored:n.deep});if(!p.ok)throw new Error(`could not return ${O(t.path)} to its base: ${p.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 ${O(t.path)} back to the state it was created in.`];if(u>0||f>0){let k=[];u>0&&k.push(`${u} uncommitted change(s)`),f>0&&k.push(`${f} 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}`),f>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 ${O(t.sourceCwd)} was never touched by this.`),y.join(`
|
|
166
|
+
`)})}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 ${O(n)} no longer exists`);let i=ne(e.provider),a=this.asWorkspace(e),d=await yo({source:n,ws:a,startSnapshotRef:this.startRefFor(e.label),baselineRef:this.baselineRefFor(e.label),retainRef:ho(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 ${O(n)}`);let u=await i.contains(n,{state:c,within:r}),l=[];if(!u){let v=this.get(t),A="";if(v!==void 0)try{let C=await this.syncWorkspaceFromSource(v,e,{onConflict:"abort"});C.ok?(l.push(`
|
|
167
167
|
synced with the source first: ${C.message}`),u=await i.contains(n,{state:c,within:r})):A=`
|
|
168
168
|
A sync was attempted first and could not complete: ${C.message}`}catch(C){A=`
|
|
169
169
|
A sync was attempted first but was refused: ${C instanceof Error?C.message:String(C)}`}if(!u){let C=await i.currentLineName(n)??"the source";throw new Error(`cannot fast-forward ${C} in ${O(n)} to ${r}. The source has moved on since this workspace was created. The source is untouched.${A}
|
|
170
|
-
`+(A.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 f=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 ${O(e.path)}; nothing was changed`);if(!d.clean&&!(await i.resetTo(n,c)).ok)throw new Error(`could not clear ${O(n)} for the merge; your work is preserved at ${d.retainedRef}. Nothing was merged.`);let p=await i.integrate({into:n,from:r,fastForwardOnly:!0});if(!p.ok)throw new Error(`merge failed: ${p.reason??"unknown error"}`);let g=!0;if(m!==void 0){let v=await i.captureDelta(n,p.snapshot,m);v!==void 0&&(g=(await i.applyDelta(n,v)).ok)}let w=await
|
|
170
|
+
`+(A.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 f=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 ${O(e.path)}; nothing was changed`);if(!d.clean&&!(await i.resetTo(n,c)).ok)throw new Error(`could not clear ${O(n)} for the merge; your work is preserved at ${d.retainedRef}. Nothing was merged.`);let p=await i.integrate({into:n,from:r,fastForwardOnly:!0});if(!p.ok)throw new Error(`merge failed: ${p.reason??"unknown error"}`);let g=!0;if(m!==void 0){let v=await i.captureDelta(n,p.snapshot,m);v!==void 0&&(g=(await i.applyDelta(n,v)).ok)}let w=await bt({source:n,capture:d,provider:i});w&&await bn({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,f).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 I=[];g||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 ${O(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)I.push(` WARNING: nested tree ${v.path} was NOT reconciled: ${v.reason}. ${O(n)} now records a different state for it, so it will report it as modified until you resolve that.`);return{merged:`Merged ${r} into ${O(n)}${l.join("")}`,warnings:I}}async applyWorkspaceToSource(e,t){let n=e.sourceCwd;if(!await this.dirExists(n))throw new Error(`source tree ${O(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(`${O(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 ${O(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 yo({source:n,ws:o,startSnapshotRef:this.startRefFor(e.label),baselineRef:this.baselineRefFor(e.label),retainRef:ho(t),provider:r}),f=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 ${O(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; ${O(n)} was not touched`);if(h.trim().length===0)return await bn({source:n,ws:o,capture:l,provider:r}),{applied:`Nothing to apply: ${e.label} holds no changes ${O(n)} does not already have.`,warnings:[]};if(!l.clean&&!(await r.resetTo(n,a)).ok)throw new Error(`could not clear ${O(n)} to apply onto; your work is preserved at ${l.retainedRef}. Nothing was applied.`);let p=await r.applyDelta(n,h,{stage:!0,tolerant:!c});if(!p.ok){await r.resetTo(n,a).catch(()=>{});let k=await bt({source:n,capture:l,provider:r});throw k&&await bn({source:n,ws:o,capture:l,provider:r}),new Error(`could not apply ${e.label} into ${O(n)}: ${p.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?` ${O(n)} is as you left it.`:` Your uncommitted work there is preserved at ${l.retainedRef}.`))}let g=await bt({source:n,capture:l,provider:r});g&&await bn({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=[];p.alreadyPresent===!0&&y.push(` Nothing was staged: ${O(n)} already had every one of those changes.`),g||y.push(` WARNING: your own edits to ${O(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 f)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 ${O(n)} as staged changes; still working in ${O(e.path)}.
|
|
171
171
|
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 ${O(t)} with ${O(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`${O(t)} and ${O(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(`${O(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=>Xe(u.sessionId)),c=[`Joined workspace ${O(n.path)}`,` source: ${O(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(`
|
|
172
|
-
`)})}async startWorkspace(e,t,n){if(e.workspace!==void 0)throw new Error(`already isolated in ${O(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,f=[],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 A=a.supports.nestedTrees&&v!==void 0&&v.changedPaths.length>0?await o.listNested(r).catch(()=>[]):[];if(v!==void 0&&v.changedPaths.length>0&&h)f=
|
|
173
|
-
${A}`)}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 I=[`Moved into workspace ${O(g.path)}`,` source: ${O(r)}`];if(g.line!==void 0&&I.push(` branch: ${g.line}`),t!==void 0&&t!==g.label&&I.push(` note: "${t}" was already taken by a surviving branch, so this is "${g.label}"`),d!==void 0){I.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
|
|
174
|
-
`)}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 gs(e.sourceCwd).catch(()=>({})),r=[];if(n.carry!==void 0&&n.carry.length>0){let o=await po(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 ms(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 p=new Error(`agent ${e} not found in registry`);throw p.code=E.AgentNotInstalled,p}let n=await Te(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:jd.homedir(),plan:n}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:Ft,clientInfo:{name:"hydra",version:le}})}catch(p){throw await r.kill().catch(()=>{}),lt(p,r)}if(r.authMethods=Cn(o.authMethods),r.steeringSupported=An(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(p){throw await r.kill().catch(()=>{}),p}await r.kill().catch(()=>{});let d=new Map,c=xr(t);d.set(e,c);let u=new Set;for(let p of this.sessions.values()){let g=await this.agentStoreKey(p.agentId,d);u.add(`${g}::${p.upstreamSessionId}`)}let l=await this.store.list().catch(()=>[]);for(let p of l){u.add(`${await this.agentStoreKey(p.agentId,d)}::${p.upstreamSessionId}`);for(let g of p.upstreamGenerations??[])u.add(`${await this.agentStoreKey(g.agentId,d)}::${g.upstreamSessionId}`)}let f=x.sessionsDir(),m=[],h=0;for(let p of a){let g=`${c}::${p.sessionId}`;if(u.has(g)){h+=1;continue}if(Yg(p.cwd,f)){h+=1;continue}let w=c,y=await this.tombstones.read(w,p.sessionId).catch(()=>{});if(!y&&c!==e&&(w=e,y=await this.tombstones.read(w,p.sessionId).catch(()=>{})),y){if(!dd(y,p.updatedAt)){h+=1;continue}await this.tombstones.remove(w,p.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${p.sessionId} (upstream updatedAt advanced past ${y.upstreamUpdatedAt??"<unset>"})`)}u.add(g);let k=`${Ie}${bt()}`,b=new Date().toISOString(),I=p.updatedAt??b,v={sessionId:k,lineageId:yn(),upstreamSessionId:p.sessionId,agentId:e,cwd:p.cwd,pendingHistorySync:!0,interactive:!Xg(p.title),createdAt:I,updatedAt:I};p.title!==void 0&&(v.title=p.title);let A=so(v);await this.store.write(A),m.push({version:1,...A})}return{synced:m,skipped:h}}async listTombstones(e={}){let t=e.grep?.toLowerCase();return(await this.tombstones.list(e.agentId)).filter(r=>e.since===void 0||r.deletedAt>=e.since).filter(r=>t===void 0||[r.title,r.cwd,r.sessionId,r.upstreamSessionId].some(o=>o?.toLowerCase().includes(t))).sort((r,o)=>r.deletedAt<o.deletedAt?1:-1)}async undeleteSessions(e){let t=await this.tombstones.list(),n=[],r=[],o=[];for(let a of e){let d=t.filter(u=>u.upstreamSessionId===a),c=d.length>0?d:t.filter(u=>u.sessionId===a||u.sessionId===`${Ie}${a}`);if(c.length===0){r.push({id:a,reason:"no tombstone found"});continue}if(c.length>1){r.push({id:a,reason:"ambiguous: several tombstones match; pass an upstream id",candidates:c.map(u=>u.upstreamSessionId)});continue}o.push({id:a,tombstone:c[0]})}let i=new Map;for(let a of o){let d=i.get(a.tombstone.agentId)??[];d.push(a),i.set(a.tombstone.agentId,d)}for(let[a,d]of i){let c=l=>{let{version:f,...m}=l;return this.tombstones.add(m).catch(()=>{})};for(let l of d)await this.tombstones.remove(a,l.tombstone.upstreamSessionId);let u;try{u=(await this.syncFromAgent(a)).synced}catch(l){for(let f of d)await c(f.tombstone),r.push({id:f.id,reason:`agent sync failed: ${l.message}`});continue}for(let l of d){let f=u.find(m=>m.upstreamSessionId===l.tombstone.upstreamSessionId);if(!f){await c(l.tombstone),r.push({id:l.id,reason:`agent ${a} no longer lists this session`});continue}n.push({id:l.id,sessionId:f.sessionId,upstreamSessionId:l.tombstone.upstreamSessionId})}}return{restored:n,failed:r}}async collectAgentSessions(e){let t=[],n,r=new Set;for(let o=0;o<100;o+=1){let i={};n!==void 0&&(i.cursor=n);let a=await e.connection.request("session/list",i),d=Array.isArray(a.sessions)?a.sessions:[];for(let c of d){if(typeof c.sessionId!="string"||typeof c.cwd!="string")continue;let u={sessionId:c.sessionId,cwd:c.cwd};typeof c.title=="string"&&(u.title=c.title),typeof c.updatedAt=="string"&&(u.updatedAt=c.updatedAt),t.push(u)}if(typeof a.nextCursor!="string"||a.nextCursor.length===0||r.has(a.nextCursor))break;r.add(a.nextCursor),n=a.nextCursor}return t}async applySeedModel(e,t,n,r,o){try{let{verb:i,result:a}=await at({request:(d,c)=>e.connection.request(d,c),sessionId:t,modelId:n,...o?{verb:o}:{},logger:this.logger});return this.logger?.info(`${r}: ${i} accepted`),{accepted:!0,result:a}}catch(i){return this.logger?.warn(`${r} rejected by agent (${i.message}); session will use the agent's own default`),{accepted:!1}}}async applySeedMode(e,t,n,r){try{let o=await e.connection.request("session/set_mode",{sessionId:t,modeId:n});return this.logger?.info(`${r}: session/set_mode accepted`),{accepted:!0,result:o}}catch(o){return this.logger?.warn(`${r} rejected by agent (${o.message}); session will use the agent's own default mode`),{accepted:!1}}}async restoreConfigOptionValues(e,t,n,r){if(!n||Object.keys(n).length===0)return r;let o=r;for(let[i,a]of Object.entries(n)){let d=`resurrect: persisted configOptionValues.${i}=${JSON.stringify(a)}`,c=o.find(f=>f.id===i);if(!c){this.logger?.warn(`${d}: agent does not currently advertise configId=${i}; skipping session/set_config_option`);continue}if(a===c.currentValue)continue;let u=Lt(a,c.options.map(f=>f.value));if(u.kind!=="exact"&&u.kind!=="resolved"){this.logger?.warn(`${d} ${u.kind}; skipping session/set_config_option`);continue}let l=u.kind==="resolved"?u.modelId:a;try{let f=await e.connection.request("session/set_config_option",{sessionId:t,configId:i,value:l});this.logger?.info(`${d}: session/set_config_option accepted`),o=St(f)?It(f):o.map(m=>m.id===i?{...m,currentValue:l}:m)}catch(f){this.logger?.warn(`${d}: session/set_config_option rejected by agent (${f.message})`)}}return o}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=E.AgentNotInstalled,i}let n=await Te(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),r=Bn(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:Ft,clientInfo:{name:"hydra",version:le}}),a=i.agentCapabilities;o.authMethods=Cn(i.authMethods),o.steeringSupported=An(i);let d=bo(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=So(c),f=Io(c),m=Nt(c),h=an(this.sessionDefaults,t),p=h?.value,g=e.configDefaults,w=h?.from??e.agentId,y=e.model??g?.model??p?.model,k;if(y&&y!==l){let R=Ht(y,f),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(R.kind==="exact"||R.kind==="none"){let _=await this.applySeedModel(o,u,y,T,m);_.accepted&&(l=y,k=_.result)}else if(R.kind==="resolved")if(R.modelId===l)l=R.modelId;else{let _=await this.applySeedModel(o,u,R.modelId,`${T} resolved to ${JSON.stringify(R.modelId)}`,m);_.accepted&&(l=R.modelId,k=_.result)}else if(R.kind==="ambiguous")this.logger?.warn(`${T} is ambiguous (trailing-segment matches [${R.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(l)}`);else{let _=f.map(H=>H.modelId).join(", ");this.logger?.warn(`${T} not in agent's availableModels ([${_}]); skipping session/set_model, session will use ${JSON.stringify(l)}`)}}let b=Ao(c),I=Co(c),v=g?.mode??p?.mode;if(v&&v!==I){let R=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(_=>_.id).join(", ");this.logger?.warn(`${R} not in agent's availableModes ([${T}]); skipping session/set_mode, session will use ${JSON.stringify(I)}`)}else{let T=await this.applySeedMode(o,u,v,R);T.accepted&&(I=v,St(T.result)&&(k=T.result))}}let A={...p??{},...g??{}};if(delete A.model,delete A.mode,Object.keys(A).length>0){let R=It(St(k)?k:c);for(let[T,_]of Object.entries(A)){let H=`sessionDefaults[${w}].${T}=${JSON.stringify(_)}`,J=R.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 M=Lt(_,J.options.map(q=>q.value));if(M.kind!=="exact"&&M.kind!=="resolved"){this.logger?.warn(`${H} ${M.kind}; skipping session/set_config_option`);continue}let W=M.kind==="resolved"?M.modelId:_;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`),St(q)&&(R=It(q),k=q)}catch(q){this.logger?.warn(`${H}: session/set_config_option rejected by agent (${q.message})`)}}}let C=It(St(k)?k:c);return{agent:o,upstreamSessionId:u,agentMeta:c._meta,agentCapabilities:a,initialModel:l,initialModels:f.length>0?f:void 0,initialModes:b.length>0?b:void 0,initialMode:I,initialConfigOptions:C.length>0?C:void 0,modelVerb:m}}catch(i){throw await o.kill().catch(()=>{}),lt(Nd(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=E.AgentNotInstalled,a}let r=await Te(n,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=Bn(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:Ft,clientInfo:{name:"hydra",version:le}}),d=a.agentCapabilities;i.authMethods=Cn(a.authMethods),i.steeringSupported=An(a);let c=bo(n),u=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),l=So(u),f=ut(Io(u)),m=Ao(u),h=Co(u),p=ut(It(u));return{agent:i,upstreamSessionId:e,agentMeta:u._meta,agentCapabilities:d,initialModel:l,initialModels:f,initialModes:m.length>0?m:void 0,initialMode:h,initialConfigOptions:p,modelVerb:Nt(u)}}catch(a){throw await i.kill().catch(()=>{}),lt(Nd(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=E.AgentNotInstalled,d}let o=await Te(r,[],{npmRegistry:this.npmRegistry}),i=t??ce(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let d=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:Ft,clientInfo:{name:"hydra",version:le}});a.authMethods=Cn(d.authMethods),a.steeringSupported=An(d)}catch(d){throw await a.kill().catch(()=>{}),lt(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=E.AgentNotInstalled,n}return Te(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=Vt({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:Hd(t)}).catch(()=>{})}),e.onAgentCommandsChange(t=>{this.persistSnapshot(e.sessionId,{agentCommands:t.map(n=>({name:n.name,...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModesChange(t=>{this.persistSnapshot(e.sessionId,{agentModes:t.map(n=>({id:n.id,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModelsChange(t=>{this.persistSnapshot(e.sessionId,{agentModels:t.map(n=>({modelId:n.modelId,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onConfigOptionsChange(t=>{this.persistSnapshot(e.sessionId,{configOptionValues:Object.fromEntries(t.map(n=>[n.id,n.currentValue]))}).catch(()=>{})}),e.onAttentionFlagsChange(t=>{this.mutateRecord(e.sessionId,{attentionFlags:t}).catch(()=>{})}),this.sessions.set(e.sessionId,e),this.invalidateListCache(),await this.enqueueMetaWrite(e.sessionId,async()=>{let t=await this.store.read(e.sessionId),n=Zg(e,t);await this.store.write(n)}).catch(t=>{this.logger?.warn(`failed to persist session record for ${e.sessionId}: ${t instanceof Error?t.message:String(t)}`)})}async getHistory(e){if(this.sessions.has(e))return this.histories.load(e).catch(()=>[]);if(await this.store.read(e))return this.histories.load(e).catch(()=>[])}async pageHistory(e,t){if(!(!this.sessions.has(e)&&!await this.store.read(e)))return this.histories.pageBefore(e,{...t,skip:n=>pn(n.method,n.params)})}async loadHistory(e,t={}){return this.histories.load(e,t)}async loadToolBlob(e,t){return on(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:em(t.currentUsage),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,configOptionValues:t.configOptionValues,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,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=wt(r.update.prompt),a=Qr(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(Ie))return;let t=Ie+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=E.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,turnStartedAt:e.turnStartedAt,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 Rn(t.sessionId),d=Vt({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,turnStartedAt:t.turnStartedAt,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 Rn(n.sessionId),o=Vt(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:In(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=>Od(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=>Rn(i.sessionId)));for(let i=0;i<o.length;i+=1){let a=r[i],d=o[i];n.add(a.sessionId);let c=Vt({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,turnStartedAt:a.turnStartedAt,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)&&Od(n.cwd,a)),i=await Promise.all(o.map(a=>Rn(a.sessionId)));for(let a=0;a<o.length;a+=1){let d=o[a],c=i[a],u=Vt(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:In(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=yn(),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 Dd(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let d={};for(let c of Rd(i)){let u=await Ci(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=E.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=`${Ie}${bt()}`;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 v=new Error(`source session not found: ${e}`);throw v.code=E.SessionNotFound,v}let r=t.agentId??n.agentId,o=r!==n.agentId;if(o&&!await this.registry.getAgent(r)){let A=new Error(`agent ${r} not found in registry`);throw A.code=E.AgentNotInstalled,A}let i=await this.histories.load(e).catch(()=>[]),a=i,d,c=t.mode??"synthesis",u,l,f,m=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let v=rs(i,t.forkAt);if(v<0){let A=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw A.code=E.InvalidParams,A}d=t.forkAt,a=i.slice(0,v+1)}else{let v=rm(i);v?(d=v.messageId,a=i.slice(0,v.index+1)):(d="",a=i.slice(0,0))}else{if(t.forkAt!==void 0&&t.forkAt!==""){let A=rs(i,t.forkAt);if(A<0){let C=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw C.code=E.InvalidParams,C}d=t.forkAt,a=i.slice(0,A+1)}else d="",a=i;let v=await this.registry.getAgent(r);if(!v){let A=new Error(`agent ${r} not found in registry`);throw A.code=E.AgentNotInstalled,A}f=v,l=n.currentModel,u="running"}let h=await Dd(e),p=c==="synthesis",g={...n,lineageId:yn(),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=Sn({record:g,history:a,promptHistory:h.length>0?h:void 0,hydraVersion:le,machine:cn()}),y=`${Ie}${bt()}`,k=t.cwd,b;if(t.cwd===void 0&&n.workspace!==void 0){let v=await this.deriveForkWorkspace(n.workspace,`${n.workspace.label}-fork-${y.slice(-6)}`);v!==void 0?(b=v,k=v.path):(k=n.workspace.sourceCwd,this.logger?.warn?.(`fork ${y}: could not derive an isolated workspace from ${n.workspace.path}; running unisolated in ${k}`))}await this.writeImportedRecord({sessionId:y,bundle:w,cwd:k,...b!==void 0?{workspace:b}:{},forkedFromSessionId:e,forkedFromMessageId:d,...u!==void 0?{forkSynthesisState:u}:{}});let I=p?(async()=>{try{let v=await Te(f,[],{npmRegistry:this.npmRegistry}),A=await ks({agentId:r,cwd:t.cwd??x.sessionDir(e),plan:v,history:a,modelId:l,sessionId:e,logger:this.logger,timeoutMs:m});A&&A.synopsis?await this.mutateRecord(y,{synopsis:A.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(y,{},["forkSynthesisState"]))}catch(v){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${v.message}`);try{await this.mutateRecord(y,{},["forkSynthesisState"])}catch(A){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${A.message}`)}}})():Promise.resolve();if(t.prompt!==void 0&&t.prompt.trim()!==""){let v=t.prompt;I.catch(()=>{}).then(()=>this.deliverHeadlessPrompt(y,v)).catch(A=>{this.logger?.warn(`forkSession(${e}): headless prompt delivery to ${y} failed: ${A.message}`)})}return{sessionId:y,forkedFromSessionId:e,forkedAt:d}}async deliverHeadlessPrompt(e,t){let n=await this.loadFromDisk(e);if(!n){this.logger?.warn(`deliverHeadlessPrompt: ${e} vanished before its prompt could be sent`);return}let r=this.sessions.get(e)??await this.resurrect(n),o=Qg(),i={clientId:`fork-prompt-${bt().slice(0,8)}`,connection:new Be(o),clientInfo:{name:"hydra-acp-fork",version:le}};await r.attach(i,"none");try{await r.prompt(i.clientId,{sessionId:e,prompt:[{type:"text",text:t}]})}finally{r.detach(i.clientId),o.close()}}async writeImportedRecord(e){if(await this.histories.rewrite(e.sessionId,e.bundle.history),e.bundle.toolBlobs)for(let[o,i]of Object.entries(e.bundle.toolBlobs))await Ri(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await At.utimes(x.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await Md(x.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=xr(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 Rn(e),o=Vt(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:Ld(o,t,n,void 0,r)}))}async persistSnapshot(e,t){let n={};t.currentModel!==void 0&&(n.currentModel=t.currentModel),t.currentMode!==void 0&&(n.currentMode=t.currentMode),t.currentUsage!==void 0&&(n.currentUsage=t.currentUsage),t.agentCommands!==void 0&&(n.agentCommands=t.agentCommands),t.agentModes!==void 0&&(n.agentModes=t.agentModes),t.agentModels!==void 0&&(n.agentModels=t.agentModels),t.configOptionValues!==void 0&&(n.configOptionValues=t.configOptionValues),t.interactive!==void 0&&(n.interactive=t.interactive),t.cwd!==void 0&&(n.cwd=t.cwd),await this.mutateRecord(e,n)}async 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(yd(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 _a(t.sessionId).catch(()=>[]);if(n.length===0)continue;let r=Date.now(),o=n.filter(d=>r-d.enqueuedAt<$d),i=n.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${$d/1e3}s)`),await fn(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 fn(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 Yg(s,e){if(typeof s!="string"||s.length===0)return!1;let t=xn.resolve(s),n=xn.resolve(e);return t===n||t.startsWith(n+xn.sep)}function Xg(s){return s!==void 0&&/^\{\s*"session_id"\s*:\s*"[^"]*"\s*,\s*"(?:transcript_path|cwd|permission_mode|hook_event_name)"\s*:/.test(s)}function Od(s,e){if(s===void 0||s.length===0)return!0;let t=vo(s);if(vo(e.cwd)===t)return!0;let n=e.workspace?.sourceCwd;return n!==void 0&&vo(n)===t}function vo(s){return s.length>1&&s.endsWith("/")?s.replace(/\/+$/,""):s}function Zg(s,e){let n=(s.mergedAvailableCommands().length>0?s.agentOnlyAdvertisedCommands().map(f=>f.description!==void 0?{name:f.name,description:f.description}:{name:f.name}):void 0)??e?.agentCommands,r=s.availableModes(),i=(r.length>0?r.map(f=>{let m={id:f.id};return f.name!==void 0&&(m.name=f.name),f.description!==void 0&&(m.description=f.description),m}):void 0)??e?.agentModes,a=s.availableModels(),c=(a.length>0?a.map(f=>{let m={modelId:f.modelId};return f.name!==void 0&&(m.name=f.name),f.description!==void 0&&(m.description=f.description),m}):void 0)??e?.agentModels,u=s.extraConfigOptionValues(),l=Object.keys(u).length>0?u:e?.configOptionValues;return so({sessionId:s.sessionId,lineageId:e?.lineageId??yn(),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:Hd(s.persistableUsage)??e?.currentUsage,agentCommands:n,agentModes:i,agentModels:c,configOptionValues:l,parentSessionId:s.parentSessionId??e?.parentSessionId,forkedFromSessionId:s.forkedFromSessionId??e?.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId??e?.forkedFromMessageId,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?Ld(e,s.agentId,s.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(s.createdAt).toISOString()})}function Hd(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 em(s){return s?{...s}:void 0}function tm(s){return(s.extendsChain??[s.id]).some(t=>t==="claude-acp"||t.startsWith("claude-acp-"))}var nm=[{type:"system",subtype:"background_tasks_changed"}];function bo(s,e={}){if(!tm(s))return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t,emitRawSDKMessages:nm}}}function As(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=sm(s,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function So(s){return As(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 lt(s,e){if(!s||typeof s!="object")return s;let t=s;if(t.code!==E.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=E.AuthRequired,d.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function Fd(s){return/^[A-Za-z0-9_\-./=:@]+$/.test(s)?s:`'${s.replace(/'/g,"'\\''")}'`}function Nd(s,e,t,n){if(s&&typeof s=="object"&&s.code===E.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 ${Fd(n.cwd)} && ${[n.command,...n.args].map(Fd).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(`
|
|
175
|
-
`));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
|
|
176
|
-
`))if(n.length!==0)try{let r=JSON.parse(n);typeof r=="string"&&t.push(r)}catch{}return t}catch{return[]}}function
|
|
177
|
-
`);let d=this.tokenRegistry?.mint(r.name,this.adapter.tokenRole)??n.serviceToken;e.processToken=d,e.version=void 0;let c={...
|
|
178
|
-
`),a.end();return}let f=
|
|
179
|
-
`),a.end(),this.scheduleRestart(e,t);return}let p=g=>{try{a.write(typeof g=="string"?g:g.toString())}catch{}};if(h.stdout?.on("data",p),h.stderr?.on("data",p),typeof h.pid=="number")try{
|
|
172
|
+
`)})}async startWorkspace(e,t,n){if(e.workspace!==void 0)throw new Error(`already isolated in ${O(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,f=[],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 A=a.supports.nestedTrees&&v!==void 0&&v.changedPaths.length>0?await o.listNested(r).catch(()=>[]):[];if(v!==void 0&&v.changedPaths.length>0&&h)f=lo(v.changedPaths,A);else if(v!==void 0&&v.changedPaths.length>0&&(c=lo(v.changedPaths,A),m=await o.captureNested(r,A).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 p=await o.createWorkspace({sourceCwd:r,label:t??`s-${e.sessionId.slice(-8)}`});if(!p.ok)throw e.broadcastWorkspacePhase({phase:"failed",error:p.reason}),new Error(p.reason);let g=p.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 A=await this.materializeNestedTrees(g);if(m.length>0){let R=await o.reproduceNested(g.path,r,m).catch(T=>({applied:[],failed:m.map(_=>({path:_.relPath,reason:T instanceof Error?T.message:String(T)}))}));R.failed.length>0&&(k=!1,b=R.failed)}y=await this.applyWorkspaceSetup(g,e.sessionId),A!==void 0&&(y=y===void 0?A:`${A}; ${y}`),e.broadcastWorkspacePhase({phase:"swapping"});let C=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:C.length,note:`Continuing in an isolated workspace at ${g.path}, derived from ${r}.`,...await this.recordSynopsisFor(e.sessionId)})}catch(v){let A=await this.unwindStartWorkspace({provider:o,ws:g,startRef:w,carried:d}),C=v instanceof Error?v.message:String(v);throw e.broadcastWorkspacePhase({phase:"failed",error:C}),new Error(A===void 0?C:`${C}
|
|
173
|
+
${A}`)}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 I=[`Moved into workspace ${O(g.path)}`,` source: ${O(r)}`];if(g.line!==void 0&&I.push(` branch: ${g.line}`),t!==void 0&&t!==g.label&&I.push(` note: "${t}" was already taken by a surviving branch, so this is "${g.label}"`),d!==void 0){I.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 vt(c))I.push(` ${v}`);k&&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(f.length>0){I.push(` started clean: ${f.length} uncommitted file(s) stayed in the source and did NOT come along:`);for(let v of vt(f))I.push(` ${v}`)}else l&&I.push(" source tree was clean; nothing carried in");return y!==void 0&&I.push(` ${y}`),I.push("Use `/hydra workspace stop` to merge back and return."),I.join(`
|
|
174
|
+
`)}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 hs(e.sourceCwd).catch(()=>({})),r=[];if(n.carry!==void 0&&n.carry.length>0){let o=await wo(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 ys(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 p=new Error(`agent ${e} not found in registry`);throw p.code=E.AgentNotInstalled,p}let n=await Ee(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:Wd.homedir(),plan:n}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:Dt,clientInfo:{name:"hydra",version:de}})}catch(p){throw await r.kill().catch(()=>{}),lt(p,r)}if(r.authMethods=Rn(o.authMethods),r.steeringSupported=Cn(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(p){throw await r.kill().catch(()=>{}),p}await r.kill().catch(()=>{});let d=new Map,c=_r(t);d.set(e,c);let u=new Set;for(let p of this.sessions.values()){let g=await this.agentStoreKey(p.agentId,d);u.add(`${g}::${p.upstreamSessionId}`)}let l=await this.store.list().catch(()=>[]);for(let p of l){u.add(`${await this.agentStoreKey(p.agentId,d)}::${p.upstreamSessionId}`);for(let g of p.upstreamGenerations??[])u.add(`${await this.agentStoreKey(g.agentId,d)}::${g.upstreamSessionId}`)}let f=x.sessionsDir(),m=[],h=0;for(let p of a){let g=`${c}::${p.sessionId}`;if(u.has(g)){h+=1;continue}if(om(p.cwd,f)){h+=1;continue}let w=c,y=await this.tombstones.read(w,p.sessionId).catch(()=>{});if(!y&&c!==e&&(w=e,y=await this.tombstones.read(w,p.sessionId).catch(()=>{})),y){if(!pd(y,p.updatedAt)){h+=1;continue}await this.tombstones.remove(w,p.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${p.sessionId} (upstream updatedAt advanced past ${y.upstreamUpdatedAt??"<unset>"})`)}u.add(g);let k=`${Se}${St()}`,b=new Date().toISOString(),I=p.updatedAt??b,v={sessionId:k,lineageId:wn(),upstreamSessionId:p.sessionId,agentId:e,cwd:p.cwd,pendingHistorySync:!0,interactive:!im(p.title),createdAt:I,updatedAt:I};p.title!==void 0&&(v.title=p.title);let A=co(v);await this.store.write(A),m.push({version:1,...A})}return{synced:m,skipped:h}}async listTombstones(e={}){let t=e.grep?.toLowerCase();return(await this.tombstones.list(e.agentId)).filter(r=>e.since===void 0||r.deletedAt>=e.since).filter(r=>t===void 0||[r.title,r.cwd,r.sessionId,r.upstreamSessionId].some(o=>o?.toLowerCase().includes(t))).sort((r,o)=>r.deletedAt<o.deletedAt?1:-1)}async undeleteSessions(e){let t=await this.tombstones.list(),n=[],r=[],o=[];for(let a of e){let d=t.filter(u=>u.upstreamSessionId===a),c=d.length>0?d:t.filter(u=>u.sessionId===a||u.sessionId===`${Se}${a}`);if(c.length===0){r.push({id:a,reason:"no tombstone found"});continue}if(c.length>1){r.push({id:a,reason:"ambiguous: several tombstones match; pass an upstream id",candidates:c.map(u=>u.upstreamSessionId)});continue}o.push({id:a,tombstone:c[0]})}let i=new Map;for(let a of o){let d=i.get(a.tombstone.agentId)??[];d.push(a),i.set(a.tombstone.agentId,d)}for(let[a,d]of i){let c=l=>{let{version:f,...m}=l;return this.tombstones.add(m).catch(()=>{})};for(let l of d)await this.tombstones.remove(a,l.tombstone.upstreamSessionId);let u;try{u=(await this.syncFromAgent(a)).synced}catch(l){for(let f of d)await c(f.tombstone),r.push({id:f.id,reason:`agent sync failed: ${l.message}`});continue}for(let l of d){let f=u.find(m=>m.upstreamSessionId===l.tombstone.upstreamSessionId);if(!f){await c(l.tombstone),r.push({id:l.id,reason:`agent ${a} no longer lists this session`});continue}n.push({id:l.id,sessionId:f.sessionId,upstreamSessionId:l.tombstone.upstreamSessionId})}}return{restored:n,failed:r}}async collectAgentSessions(e){let t=[],n,r=new Set;for(let o=0;o<100;o+=1){let i={};n!==void 0&&(i.cursor=n);let a=await e.connection.request("session/list",i),d=Array.isArray(a.sessions)?a.sessions:[];for(let c of d){if(typeof c.sessionId!="string"||typeof c.cwd!="string")continue;let u={sessionId:c.sessionId,cwd:c.cwd};typeof c.title=="string"&&(u.title=c.title),typeof c.updatedAt=="string"&&(u.updatedAt=c.updatedAt),t.push(u)}if(typeof a.nextCursor!="string"||a.nextCursor.length===0||r.has(a.nextCursor))break;r.add(a.nextCursor),n=a.nextCursor}return t}async applySeedModel(e,t,n,r,o){try{let{verb:i,result:a}=await at({request:(d,c)=>e.connection.request(d,c),sessionId:t,modelId:n,...o?{verb:o}:{},logger:this.logger});return this.logger?.info(`${r}: ${i} accepted`),{accepted:!0,result:a}}catch(i){return this.logger?.warn(`${r} rejected by agent (${i.message}); session will use the agent's own default`),{accepted:!1}}}async applySeedMode(e,t,n,r){try{let o=await e.connection.request("session/set_mode",{sessionId:t,modeId:n});return this.logger?.info(`${r}: session/set_mode accepted`),{accepted:!0,result:o}}catch(o){return this.logger?.warn(`${r} rejected by agent (${o.message}); session will use the agent's own default mode`),{accepted:!1}}}async restoreConfigOptionValues(e,t,n,r){if(!n||Object.keys(n).length===0)return r;let o=r;for(let[i,a]of Object.entries(n)){let d=`resurrect: persisted configOptionValues.${i}=${JSON.stringify(a)}`,c=o.find(f=>f.id===i);if(!c){this.logger?.warn(`${d}: agent does not currently advertise configId=${i}; skipping session/set_config_option`);continue}if(a===c.currentValue)continue;let u=Bt(a,c.options.map(f=>f.value));if(u.kind!=="exact"&&u.kind!=="resolved"){this.logger?.warn(`${d} ${u.kind}; skipping session/set_config_option`);continue}let l=u.kind==="resolved"?u.modelId:a;try{let f=await e.connection.request("session/set_config_option",{sessionId:t,configId:i,value:l});this.logger?.info(`${d}: session/set_config_option accepted`),o=It(f)?At(f):o.map(m=>m.id===i?{...m,currentValue:l}:m)}catch(f){this.logger?.warn(`${d}: session/set_config_option rejected by agent (${f.message})`)}}return o}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=E.AgentNotInstalled,i}let n=await Ee(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),r=qn(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:Dt,clientInfo:{name:"hydra",version:de}}),a=i.agentCapabilities;o.authMethods=Rn(i.authMethods),o.steeringSupported=Cn(i);let d=Ro(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=xo(c),f=Eo(c),m=jt(c),h=cn(this.sessionDefaults,t),p=h?.value,g=e.configDefaults,w=h?.from??e.agentId,y=e.model??g?.model??p?.model,k;if(y&&y!==l){let R=Ut(y,f),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(R.kind==="exact"||R.kind==="none"){let _=await this.applySeedModel(o,u,y,T,m);_.accepted&&(l=y,k=_.result)}else if(R.kind==="resolved")if(R.modelId===l)l=R.modelId;else{let _=await this.applySeedModel(o,u,R.modelId,`${T} resolved to ${JSON.stringify(R.modelId)}`,m);_.accepted&&(l=R.modelId,k=_.result)}else if(R.kind==="ambiguous")this.logger?.warn(`${T} is ambiguous (trailing-segment matches [${R.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(l)}`);else{let _=f.map(U=>U.modelId).join(", ");this.logger?.warn(`${T} not in agent's availableModels ([${_}]); skipping session/set_model, session will use ${JSON.stringify(l)}`)}}let b=To(c),I=Po(c),v=g?.mode??p?.mode;if(v&&v!==I){let R=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(_=>_.id).join(", ");this.logger?.warn(`${R} not in agent's availableModes ([${T}]); skipping session/set_mode, session will use ${JSON.stringify(I)}`)}else{let T=await this.applySeedMode(o,u,v,R);T.accepted&&(I=v,It(T.result)&&(k=T.result))}}let A={...p??{},...g??{}};if(delete A.model,delete A.mode,Object.keys(A).length>0){let R=At(It(k)?k:c);for(let[T,_]of Object.entries(A)){let U=`sessionDefaults[${w}].${T}=${JSON.stringify(_)}`,J=R.find(q=>q.id===T);if(!J){this.logger?.warn(`${U}: agent does not currently advertise configId=${T}; skipping session/set_config_option`);continue}let M=Bt(_,J.options.map(q=>q.value));if(M.kind!=="exact"&&M.kind!=="resolved"){this.logger?.warn(`${U} ${M.kind}; skipping session/set_config_option`);continue}let W=M.kind==="resolved"?M.modelId:_;if(W!==J.currentValue)try{let q=await o.connection.request("session/set_config_option",{sessionId:u,configId:T,value:W});this.logger?.info(`${U}: session/set_config_option accepted`),It(q)&&(R=At(q),k=q)}catch(q){this.logger?.warn(`${U}: session/set_config_option rejected by agent (${q.message})`)}}}let C=At(It(k)?k:c);return{agent:o,upstreamSessionId:u,agentMeta:c._meta,agentCapabilities:a,initialModel:l,initialModels:f.length>0?f:void 0,initialModes:b.length>0?b:void 0,initialMode:I,initialConfigOptions:C.length>0?C:void 0,modelVerb:m}}catch(i){throw await o.kill().catch(()=>{}),lt(Ud(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=E.AgentNotInstalled,a}let r=await Ee(n,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=qn(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:Dt,clientInfo:{name:"hydra",version:de}}),d=a.agentCapabilities;i.authMethods=Rn(a.authMethods),i.steeringSupported=Cn(a);let c=Ro(n),u=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),l=xo(u),f=ut(Eo(u)),m=To(u),h=Po(u),p=ut(At(u));return{agent:i,upstreamSessionId:e,agentMeta:u._meta,agentCapabilities:d,initialModel:l,initialModels:f,initialModes:m.length>0?m:void 0,initialMode:h,initialConfigOptions:p,modelVerb:jt(u)}}catch(a){throw await i.kill().catch(()=>{}),lt(Ud(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=E.AgentNotInstalled,d}let o=await Ee(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:Dt,clientInfo:{name:"hydra",version:de}});a.authMethods=Rn(d.authMethods),a.steeringSupported=Cn(d)}catch(d){throw await a.kill().catch(()=>{}),lt(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=E.AgentNotInstalled,n}return Ee(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=Kt({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:qd(t)}).catch(()=>{})}),e.onAgentCommandsChange(t=>{this.persistSnapshot(e.sessionId,{agentCommands:t.map(n=>({name:n.name,...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModesChange(t=>{this.persistSnapshot(e.sessionId,{agentModes:t.map(n=>({id:n.id,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModelsChange(t=>{this.persistSnapshot(e.sessionId,{agentModels:t.map(n=>({modelId:n.modelId,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onConfigOptionsChange(t=>{this.persistSnapshot(e.sessionId,{configOptionValues:Object.fromEntries(t.map(n=>[n.id,n.currentValue]))}).catch(()=>{})}),e.onAttentionFlagsChange(t=>{this.mutateRecord(e.sessionId,{attentionFlags:t}).catch(()=>{})}),this.sessions.set(e.sessionId,e),this.invalidateListCache(),await this.enqueueMetaWrite(e.sessionId,async()=>{let t=await this.store.read(e.sessionId),n=am(e,t);await this.store.write(n)}).catch(t=>{this.logger?.warn(`failed to persist session record for ${e.sessionId}: ${t instanceof Error?t.message:String(t)}`)})}async getHistory(e){if(this.sessions.has(e))return this.histories.load(e).catch(()=>[]);if(await this.store.read(e))return this.histories.load(e).catch(()=>[])}async pageHistory(e,t){if(!(!this.sessions.has(e)&&!await this.store.read(e)))return this.histories.pageBefore(e,{...t,skip:n=>gn(n.method,n.params)})}async loadHistory(e,t={}){return this.histories.load(e,t)}async loadToolBlob(e,t){return dn(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:dm(t.currentUsage),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,configOptionValues:t.configOptionValues,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,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=kt(r.update.prompt),a=to(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(Se))return;let t=Se+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=E.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,turnStartedAt:e.turnStartedAt,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 xn(t.sessionId),d=Kt({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,turnStartedAt:t.turnStartedAt,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 xn(n.sessionId),o=Kt(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:An(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=>xn(i.sessionId)));for(let i=0;i<o.length;i+=1){let a=r[i],d=o[i];n.add(a.sessionId);let c=Kt({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,turnStartedAt:a.turnStartedAt,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=>xn(a.sessionId)));for(let a=0;a<o.length;a+=1){let d=o[a],c=i[a],u=Kt(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:An(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=wn(),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 Bd(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let d={};for(let c of Md(i)){let u=await Pi(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=E.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=`${Se}${St()}`;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 v=new Error(`source session not found: ${e}`);throw v.code=E.SessionNotFound,v}let r=t.agentId??n.agentId,o=r!==n.agentId;if(o&&!await this.registry.getAgent(r)){let A=new Error(`agent ${r} not found in registry`);throw A.code=E.AgentNotInstalled,A}let i=await this.histories.load(e).catch(()=>[]),a=i,d,c=t.mode??"synthesis",u,l,f,m=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let v=is(i,t.forkAt);if(v<0){let A=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw A.code=E.InvalidParams,A}d=t.forkAt,a=i.slice(0,v+1)}else{let v=fm(i);v?(d=v.messageId,a=i.slice(0,v.index+1)):(d="",a=i.slice(0,0))}else{if(t.forkAt!==void 0&&t.forkAt!==""){let A=is(i,t.forkAt);if(A<0){let C=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw C.code=E.InvalidParams,C}d=t.forkAt,a=i.slice(0,A+1)}else d="",a=i;let v=await this.registry.getAgent(r);if(!v){let A=new Error(`agent ${r} not found in registry`);throw A.code=E.AgentNotInstalled,A}f=v,l=n.currentModel,u="running"}let h=await Bd(e),p=c==="synthesis",g={...n,lineageId:wn(),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=In({record:g,history:a,promptHistory:h.length>0?h:void 0,hydraVersion:de,machine:ht()}),y=`${Se}${St()}`,k=t.cwd,b;if(t.cwd===void 0&&n.workspace!==void 0){let v=await this.deriveForkWorkspace(n.workspace,`${n.workspace.label}-fork-${y.slice(-6)}`);v!==void 0?(b=v,k=v.path):(k=n.workspace.sourceCwd,this.logger?.warn?.(`fork ${y}: could not derive an isolated workspace from ${n.workspace.path}; running unisolated in ${k}`))}await this.writeImportedRecord({sessionId:y,bundle:w,cwd:k,...b!==void 0?{workspace:b}:{},forkedFromSessionId:e,forkedFromMessageId:d,...u!==void 0?{forkSynthesisState:u}:{}});let I=p?(async()=>{try{let v=await Ee(f,[],{npmRegistry:this.npmRegistry}),A=await bs({agentId:r,cwd:t.cwd??x.sessionDir(e),plan:v,history:a,modelId:l,sessionId:e,logger:this.logger,timeoutMs:m});A&&A.synopsis?await this.mutateRecord(y,{synopsis:A.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(y,{},["forkSynthesisState"]))}catch(v){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${v.message}`);try{await this.mutateRecord(y,{},["forkSynthesisState"])}catch(A){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${A.message}`)}}})():Promise.resolve();if(t.prompt!==void 0&&t.prompt.trim()!==""){let v=t.prompt;I.catch(()=>{}).then(()=>this.deliverHeadlessPrompt(y,v)).catch(A=>{this.logger?.warn(`forkSession(${e}): headless prompt delivery to ${y} failed: ${A.message}`)})}return{sessionId:y,forkedFromSessionId:e,forkedAt:d}}async deliverHeadlessPrompt(e,t){let n=await this.loadFromDisk(e);if(!n){this.logger?.warn(`deliverHeadlessPrompt: ${e} vanished before its prompt could be sent`);return}let r=this.sessions.get(e)??await this.resurrect(n),o=rm(),i={clientId:`fork-prompt-${St().slice(0,8)}`,connection:new Be(o),clientInfo:{name:"hydra-acp-fork",version:de}};await r.attach(i,"none");try{await r.prompt(i.clientId,{sessionId:e,prompt:[{type:"text",text:t}]})}finally{r.detach(i.clientId),o.close()}}async writeImportedRecord(e){if(await this.histories.rewrite(e.sessionId,e.bundle.history),e.bundle.toolBlobs)for(let[o,i]of Object.entries(e.bundle.toolBlobs))await Mi(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await Ct.utimes(x.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await Nd(x.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=_r(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 xn(e),o=Kt(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:zd(o,t,n,void 0,r)}))}async persistSnapshot(e,t){let n={};t.currentModel!==void 0&&(n.currentModel=t.currentModel),t.currentMode!==void 0&&(n.currentMode=t.currentMode),t.currentUsage!==void 0&&(n.currentUsage=t.currentUsage),t.agentCommands!==void 0&&(n.agentCommands=t.agentCommands),t.agentModes!==void 0&&(n.agentModes=t.agentModes),t.agentModels!==void 0&&(n.agentModels=t.agentModels),t.configOptionValues!==void 0&&(n.configOptionValues=t.configOptionValues),t.interactive!==void 0&&(n.interactive=t.interactive),t.cwd!==void 0&&(n.cwd=t.cwd),await this.mutateRecord(e,n)}async 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(Sd(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 Da(t.sessionId).catch(()=>[]);if(n.length===0)continue;let r=Date.now(),o=n.filter(d=>r-d.enqueuedAt<jd),i=n.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${jd/1e3}s)`),await pn(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 pn(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 om(s,e){if(typeof s!="string"||s.length===0)return!1;let t=En.resolve(s),n=En.resolve(e);return t===n||t.startsWith(n+En.sep)}function im(s){return s!==void 0&&/^\{\s*"session_id"\s*:\s*"[^"]*"\s*,\s*"(?:transcript_path|cwd|permission_mode|hook_event_name)"\s*:/.test(s)}function Hd(s,e){if(s===void 0||s.length===0)return!0;let t=Co(s);if(Co(e.cwd)===t)return!0;let n=e.workspace?.sourceCwd;return n!==void 0&&Co(n)===t}function Co(s){return s.length>1&&s.endsWith("/")?s.replace(/\/+$/,""):s}function am(s,e){let n=(s.mergedAvailableCommands().length>0?s.agentOnlyAdvertisedCommands().map(f=>f.description!==void 0?{name:f.name,description:f.description}:{name:f.name}):void 0)??e?.agentCommands,r=s.availableModes(),i=(r.length>0?r.map(f=>{let m={id:f.id};return f.name!==void 0&&(m.name=f.name),f.description!==void 0&&(m.description=f.description),m}):void 0)??e?.agentModes,a=s.availableModels(),c=(a.length>0?a.map(f=>{let m={modelId:f.modelId};return f.name!==void 0&&(m.name=f.name),f.description!==void 0&&(m.description=f.description),m}):void 0)??e?.agentModels,u=s.extraConfigOptionValues(),l=Object.keys(u).length>0?u:e?.configOptionValues;return co({sessionId:s.sessionId,lineageId:e?.lineageId??wn(),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:qd(s.persistableUsage)??e?.currentUsage,agentCommands:n,agentModes:i,agentModels:c,configOptionValues:l,parentSessionId:s.parentSessionId??e?.parentSessionId,forkedFromSessionId:s.forkedFromSessionId??e?.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId??e?.forkedFromMessageId,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?zd(e,s.agentId,s.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(s.createdAt).toISOString()})}function qd(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 dm(s){return s?{...s}:void 0}function cm(s){return(s.extendsChain??[s.id]).some(t=>t==="claude-acp"||t.startsWith("claude-acp-"))}var um=[{type:"system",subtype:"background_tasks_changed"}];function Ro(s,e={}){if(!cm(s))return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t,emitRawSDKMessages:um}}}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=lm(s,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function xo(s){return Rs(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 lt(s,e){if(!s||typeof s!="object")return s;let t=s;if(t.code!==E.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=E.AuthRequired,d.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function Ld(s){return/^[A-Za-z0-9_\-./=:@]+$/.test(s)?s:`'${s.replace(/'/g,"'\\''")}'`}function Ud(s,e,t,n){if(s&&typeof s=="object"&&s.code===E.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 ${Ld(n.cwd)} && ${[n.command,...n.args].map(Ld).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(`
|
|
175
|
+
`));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 Cn(s){return s._meta?.steering?.supported===!0}function Rn(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 lm(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 It(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.configOptions)}function At(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=eo(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 Eo(s){return Rs(s,{nestedKey:"models",configId:"model",fromObject:e=>{let t=mn(e.availableModels);return t.length>0?t:void 0},fromConfig:e=>{let t=mn(e.options);return t.length>0?t:void 0}})??[]}function To(s){return Rs(s,{nestedKey:"modes",configId:"mode",fromObject:e=>{let t=os(e.availableModes);return t.length>0?t:void 0},fromConfig:e=>{let t=os(e.options);return t.length>0?t:void 0}})??[]}function Po(s){return Rs(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 fm(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 Bd(s){try{let e=await Ct.readFile(x.tuiHistoryFile(s),"utf8"),t=[];for(let n of e.split(`
|
|
176
|
+
`))if(n.length!==0)try{let r=JSON.parse(n);typeof r=="string"&&t.push(r)}catch{}return t}catch{return[]}}function zd(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,f=s.upstreamGenerations&&s.upstreamGenerations.length>0?[...s.upstreamGenerations]:s.upstreamSessionId?[{upstreamSessionId:s.upstreamSessionId,agentId:s.agentId}]:[],m=f[f.length-1];if(m&&m.upstreamSessionId===t){if(f.length>=2){let h=f[f.length-2];if(h){let p=l(h);f[f.length-2]={...h,...p!==void 0&&h.cost===void 0?{cost:p}:{},...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)&&(f[f.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}:{}}),f}return m&&m.endedAt===void 0&&(f[f.length-1]={...m,endedAt:n,...(()=>{let h=l(m);return h!==void 0?{cost:h}:{}})(),...i!==void 0?{usedAtEnd:i}:{}}),f.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}:{}}),f}async function xn(s){try{let e=await Ct.stat(x.historyFile(s));return{mtime:new Date(e.mtimeMs).toISOString(),hasContent:e.size>0}}catch{return{hasContent:!1}}}function Kt(s,e){return s.interactive!==void 0?s.interactive:s.originatingClient?.name===vs?!1:e?!0:void 0}import{spawn as pm}from"child_process";import*as Ts from"fs";import*as tt from"fs/promises";import*as Ps from"path";import gm from"pino-roll";var xs=class{windowMs;maxFailures;now;recentExits=[];tripped_;constructor(e={}){this.windowMs=e.windowMs??3e5,this.maxFailures=e.maxFailuresInWindow??10,this.now=e.now??Date.now}recordExit(e,t,n){if(e===78){let i=`exited with code 78 (unrecoverable); fix and run \`${n}s start ${t}\``;return this.tripped_=i,{tripped:i}}let r=this.now();this.recentExits.push(r);let o=r-this.windowMs;for(;this.recentExits.length>0&&this.recentExits[0]<o;)this.recentExits.shift();if(this.recentExits.length>this.maxFailures){let i=Math.round(this.windowMs/6e4),a=`${this.recentExits.length} exits in ${i}m (crash loop); fix and run \`${n}s start ${t}\``;return this.tripped_=a,{tripped:a}}return"restart"}reset(){this.recentExits=[],this.tripped_=void 0}get tripped(){return this.tripped_}};import*as Jd from"fs/promises";import*as Mo from"path";var Es=process.platform!=="win32";var mm=1e3,hm=6e4,_o=3e3,Qt=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??mm,this.restartCapMs=r.restartCapMs??hm;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 tt.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()},_o);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 Tn(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");if(t.child)throw Tn(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 Tn(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 Tn(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 Tn(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{}},_o);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 xs(this.breakerOptions),failureReason:void 0}}async reapOrphans(){let e;try{e=await tt.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 tt.readFile(n,"utf8"),i=Number.parseInt(o.trim(),10);Number.isInteger(i)&&i>0&&(r=i)}catch{}if(typeof r=="number"&&$o(r)){try{process.kill(r,"SIGTERM")}catch{}let o=Date.now()+_o;for(;Date.now()<o&&$o(r);)await new Promise(i=>setTimeout(i,50));if($o(r))try{process.kill(r,"SIGKILL")}catch{}}await tt.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=Ps.dirname(this.adapter.paths.logFile(r.name)),a;try{await tt.mkdir(i,{recursive:!0}),a=await gm({file:Ps.join(i,`${r.name}.log`),size:"5m",mkdir:!0,symlink:Es,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})
|
|
177
|
+
`);let d=this.tokenRegistry?.mint(r.name,this.adapter.tokenRole)??n.serviceToken;e.processToken=d,e.version=void 0;let c={...zn(),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
|
|
178
|
+
`),a.end();return}let f=ae(u),m=[...l,...r.args].map(ae),h;try{let g=Ot(f,m);h=pm(g.command,g.args,{env:c,stdio:["ignore","pipe","pipe"],detached:!1,shell:g.shell,windowsHide:!0})}catch(g){a.write(`[hydra-acp] failed to spawn ${r.name}: ${g.message}
|
|
179
|
+
`),a.end(),this.scheduleRestart(e,t);return}let p=g=>{try{a.write(typeof g=="string"?g:g.toString())}catch{}};if(h.stdout?.on("data",p),h.stderr?.on("data",p),typeof h.pid=="number")try{Ts.writeFileSync(this.adapter.paths.pidFile(r.name),`${h.pid}
|
|
180
180
|
`,{encoding:"utf8",mode:384})}catch(g){a.write(`[hydra-acp] failed to write pid file for ${r.name}: ${g.message}
|
|
181
181
|
`)}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}
|
|
182
|
-
`)}),h.on("exit",(g,w)=>{try{
|
|
182
|
+
`)}),h.on("exit",(g,w)=>{try{Ts.unlinkSync(this.adapter.paths.pidFile(r.name))}catch{}a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} exited code=${g??"null"} signal=${w??"null"}
|
|
183
183
|
`),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}
|
|
184
|
-
`);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
|
|
185
|
-
`,{encoding:"utf8",mode:384})}G();import*as
|
|
186
|
-
`)};function
|
|
187
|
-
`))}async function Wd(s,e){let t=je();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=_s.join(x.agentsDir(),t),a;try{a=await Pn.readdir(i,{withFileTypes:!0})}catch(d){let c=d;if(c.code==="ENOENT")return;Tn(`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,f=_s.join(i,c),m;try{m=await Pn.readdir(f,{withFileTypes:!0})}catch(h){Tn(`hydra-acp: prune: failed to read ${f}: ${h.message}`);continue}for(let h of m){if(!h.isDirectory())continue;let p=h.name;if(p===u||l.has(p)||p.includes(".partial-"))continue;let g=_s.join(f,p);try{await Pn.rm(g,{recursive:!0,force:!0}),Tn(`hydra-acp: pruned stale ${c} ${p} (${g})`)}catch(w){Tn(`hydra-acp: prune: failed to remove ${g}: ${w.message}`)}}}}function qd(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 Tr(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 Mo(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 p=Date.parse(m.updatedAt);Number.isFinite(p)&&(s.maxAgeMs>0&&p>r||i.push({sessionId:m.sessionId,lastUsedMs:p}))}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 ${lm(s.maxAgeMs)}`+(u>0?`; ${u} failed`:"")+(l>0?`; ${l} deferred to next sweep`:""))}let f={considered:i.length,deleted:c,failed:u,deferred:l};return d!==void 0&&(f.oldestLastUsedMs=d),f}function zd(s){let e,t=!1,n=!1,r=o=>{t||(e=setTimeout(()=>{(async()=>{if(!n){n=!0;try{await Mo({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 lm(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 fm}from"crypto";function Mn(s){if(Array.isArray(s))return s.map(Mn);if(s!==null&&typeof s=="object"){let e={};for(let t of Object.keys(s).sort())e[t]=Mn(s[t]);return e}return s}function Jd(s){let e={};for(let[n,r]of Object.entries(s)){let o=ar(n);if(o.nested){let i={};for(let[a,d]of Object.entries(r??{}))dr(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(Mn(e));return fm("sha256").update(t).digest("hex").slice(0,16)}function Vd(s,e){let t=[],n=(r,o)=>JSON.stringify(Mn(r))!==JSON.stringify(Mn(o));for(let r of Object.keys(e)){let o=ar(r),i=e[r],a=s[r];if(o.nested){for(let d of Object.keys(i??{})){if(dr(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 Kd from"fs/promises";G();var pm=3e3;async function Gd(){try{return(await Kd.stat(x.config())).mtimeMs}catch{return}}function Qd(s){let e=s.intervalMs??pm,t=!1,n,r,o=Gd().then(d=>{r=d}),i=async()=>{await o;let d=await Gd();if(d===r)return;r=d;let c;try{c=await rn()}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=Vd(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)}}G();Ne();import*as Zd from"path";import{createHash as gm,randomBytes as mm,timingSafeEqual as hm}from"crypto";var ec="hydra_session_",ym=3600*24*30,Yd=12,wm=32,km=50;function vm(){return Zd.join(x.home(),"session-tokens.json")}function Xd(s){return gm("sha256").update(s).digest("hex")}function tc(s){return mm(s).toString("hex")}function bm(){return tc(Yd).slice(0,Yd*2)}function Sm(){return`${ec}${tc(wm)}`}var $s=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=vm(),n=await ie(t);n&&Array.isArray(n.records)&&(e=n.records.filter(Im));let r=new s(e,t);return r.sweepExpired(new Date)>0&&await r.flush(),r}async issue(e={}){let t=Sm(),n=Xd(t),r=bm(),o=new Date,i=e.ttlSec&&e.ttlSec>0?e.ttlSec:ym,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(ec))return;let t=Xd(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||!hm(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(()=>{})},km))}persist(){let e=(this.writeInflight??Promise.resolve()).catch(()=>{}).then(()=>pe(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 Im(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 nc="Bearer ",Os=class{constructor(e){this.token=e}token;async validate(e){return Cm(e,this.token)?"service":void 0}rotate(e){this.token=e}},Fs=class{constructor(e){this.store=e}store;async validate(e){return this.store.verify(e)}},Ns=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 sc(s){return async function(t,n){let r=t.headers.authorization;if(!r||!r.startsWith(nc)){n.code(401).send({error:"Missing bearer token"});return}let o=r.slice(nc.length).trim(),i=await s.validator.validate(o);if(!i){n.code(403).send({error:"Invalid token"});return}t.authIdentity=i}}function rc(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 Ds=class{tokens=new Map;mint(e,t){let n=or();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}`}},Am=new Set(["GET /v1/sessions","GET /v1/sessions/:id","GET /v1/config"]);function oc(s,e){return e?Am.has(`${s} ${e}`):!1}function Cm(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 js=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 jo from"fs";import*as Fc from"os";import*as zs from"path";import*as Ho from"readline";G();function _o(s){return Math.floor(s/4)}function ic(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+=Ct(i.content);break;case"tool_call":case"tool_call_update":{let a=typeof i.toolCallId=="string"?i.toolCallId:"",d=Rm(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 Rm(s){let e=0;return typeof s.title=="string"&&(e+=s.title.length),e+=Hs(s.rawInput),e+=Ct(s.content),e+=Hs(s.rawOutput),e}function Hs(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+=Hs(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+=Hs(n);return t}return 0}function Ct(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+=Ct(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?Ct(e.text):e.type==="diff"?Ct(e.oldText)+Ct(e.newText):e.content!==void 0?Ct(e.content):0}function ac(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=_o(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}G();import{posix as xm}from"path";import Em from"strip-ansi";function _n(s){if(!s||typeof s!="object")return;let e=s;return typeof e.workerTaskId=="string"?e.workerTaskId:void 0}function $o(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 Tm=/[\x00-\x08\x0b-\x1f\x7f]/g;function Me(s){return Em(s).replace(Tm,"")}function re(s){return Me(s).replace(/[\n\t]+/g," ").replace(/ +/g," ").trim()}function lc(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 Nm(t);case"agent_thought_chunk":case"agent_thought":return Dm(t);case"user_message_chunk":return jm(t);case"prompt_received":return Hm(t);case"tool_call":return Lm(t,e);case"tool_call_update":return zm(t,e);case"plan":return Km(t);case"current_mode_update":return Qm(t);case"_hydra_current_model_update":return Ym(t);case"turn_complete":return Xm(t);case"_hydra_turn_started":return uc(t,"turn-started");case"_hydra_turn_ended":return uc(t,"turn-ended");case"usage_update":return Fm(t);case"available_commands_update":return $m(t);case"_hydra_available_modes_update":return Om(t);case"session_info_update":return Mm(t);case"config_option_update":return Pm(t);default:return{kind:"unknown",sessionUpdate:n,raw:s}}}function Pm(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 Mm(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 _m(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 $m(s){let e=s.availableCommands??s.commands;return Array.isArray(e)?{kind:"available-commands",commands:_m(e)}:null}function Om(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 Fm(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 Nm(s){let e=$n(s.content);return e===null?null:{kind:"agent-text",text:e,workerTaskId:_n(s)}}function Dm(s){let e=typeof s.text=="string"?Me(s.text):$n(s.content);return e===null?null:{kind:"agent-thought",text:e,workerTaskId:_n(s)}}function jm(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=$n(s.content);return t===null?null:{kind:"user-text",text:t}}function Hm(s){let e=Zm(s.prompt);return e===null?null:{kind:"user-text",text:e}}function fc(s){return s?s.toLowerCase().replace(/[_\s-]/g,"")==="exitplanmode":!1}function dc(s){if(typeof s=="string")return{text:s};if(s&&typeof s=="object"&&!Array.isArray(s)){let e=s;if(typeof e.__hydraBlob=="string")return{ref:{hash:e.__hydraBlob,bytes:typeof e.bytes=="number"?e.bytes:0}}}}function Ls(s){let e=s.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=dc(r.oldText),i=dc(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 pc(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:Me(t)}function Lm(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(fc(r)){let p=pc(s);if(p!==null){let g=se(s,"status"),w={kind:"exit-plan-mode",toolCallId:t,plan:p};return g!==void 0&&(w.status=g),w}}let o=hc(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=Ls(s);c!==null&&(d.editDiff=c);let u=mc(s);u!==void 0&&(d.detail=u);let l=Oo(s);l!==void 0&&(d.detailFull=l);let f=gc(s);f!==void 0&&(d.locations=f);let m=_n(s);m!==void 0&&(d.workerTaskId=m);let h=$o(s);return h!==void 0&&(d.parentToolUseId=h),d}function gc(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 cc=64;function mc(s){let e=Oo(s);if(e===void 0)return;let t=re(e),n=s.rawInput;return n&&typeof n.command=="string"?Wm(t,cc):qm(t,cc)}function Oo(s){let e=s.rawInput;if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(typeof t.command=="string"&&t.command.trim().length>0)return Me(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 O(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 O(re(n))}}}var Um=["home/","Users/","root/","tmp/","var/","opt/","etc/","usr/","mnt/","private/"];function Bm(s){for(let e of Um)if(s.startsWith(e))return!0;return!1}function hc(s,e,t={}){if(s.length===0)return s;if(s.startsWith("/"))return O(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 O(i)}return Bm(s)?O(`/${s}`):t.cwd&&t.cwd.length>0?O(xm.resolve(t.cwd,s)):s}function Wm(s,e){return s.length>e?`${s.slice(0,e-1)}\u2026`:s}function qm(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 zm(s,e={}){let t=se(s,"toolCallId")??se(s,"id");if(!t)return null;let n=se(s,"title"),r=n!==void 0?hc(re(n),s,e):void 0,o=se(s,"status"),i=Ls(s),a=mc(s),d=Jm(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(fc(u)){let g={kind:"exit-plan-mode",toolCallId:t},w=pc(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 f=Oo(s);f!==void 0&&(l.detailFull=f);let m=gc(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=Vm(s);g!==null&&(l.errorText=g),Gm(s,g)&&(l.upstreamInterrupted=!0)}let h=_n(s);h!==void 0&&(l.workerTaskId=h);let p=$o(s);return p!==void 0&&(l.parentToolUseId=p),l}function Jm(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,f=`${l}s`)=>`${u} ${u===1?l:f}`,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 Vm(s){let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let o=$n(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 Me(n)}return null}function Gm(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 Km(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 Qm(s){let e=se(s,"currentModeId")??se(s,"currentMode")??se(s,"mode");return e?{kind:"mode-changed",mode:re(e)}:null}function Ym(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 Xm(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 uc(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 $n(s){if(typeof s=="string")return Me(s);if(!s||typeof s!="object")return null;let e=s;return e.type==="text"&&typeof e.text=="string"||typeof e.text=="string"?Me(e.text):null}function Zm(s){if(!Array.isArray(s))return null;let e=[];for(let t of s){let n=$n(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 yc(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=th(i);if(c.length===0)continue;let u=c;if(d!==void 0){let l=e.get(d)??[],f=[];for(let m of c)l.some(h=>h.path===m.path&&h.oldText===m.oldText&&h.newText===m.newText)||f.push(m);if(f.length===0)continue;e.set(d,[...l,...f]),u=f}for(let l of u)eh(t,l)}let n=[];for(let[r,o]of t)n.push({path:r,hunks:o.hunks,created:o.created});return n}function wc(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 eh(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 th(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=Ls(s);return r&&r.path&&e.push({path:r.path,oldText:r.oldText,newText:r.newText}),e}function vc(s,e={}){let t=sh(s),{events:n,window:r}=nh(t,e),o=rh(n),i=[];oh(i,s),r&&(r.from>1||r.to<r.total)&&(i.push(`_Showing turns ${r.from}-${r.to} of ${r.total}._`),i.push("")),ih(i,n,o,{includeTools:e.includeTools??!1,includeThoughts:e.includeThoughts??!1});let a=i.join(`
|
|
184
|
+
`);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 $o(s){try{return process.kill(s,0),!0}catch{return!1}}function Tn(s,e){return s.code=e,s}G();var ym={kind:"extension",nameEnvVar:"HYDRA_ACP_EXTENSION_NAME",tokenRole:"extension",paths:{dir:x.extensionsDir,logFile:x.extensionLogFile,pidFile:x.extensionPidFile}},Ms=class extends Qt{constructor(e,t,n={}){super(e,ym,t,n)}};G();var wm={kind:"transformer",nameEnvVar:"HYDRA_ACP_TRANSFORMER_NAME",tokenRole:"transformer",paths:{dir:x.transformersDir,logFile:x.transformerLogFile,pidFile:x.transformerPidFile}},_s=class extends Qt{connected=new Map;constructor(e,t,n={}){super(e,wm,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 $s=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{}}};G();G();import*as Oo from"fs/promises";async function Vd(s){await Oo.writeFile(x.pidFile(),JSON.stringify(s)+`
|
|
185
|
+
`,{encoding:"utf8",mode:384})}G();import*as Mn from"fs/promises";import*as Os from"path";var Pn=s=>{process.stderr.write(s+`
|
|
186
|
+
`)};function Fo(s){Pn=s??(e=>process.stderr.write(e+`
|
|
187
|
+
`))}async function Gd(s,e){let t=je();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=Os.join(x.agentsDir(),t),a;try{a=await Mn.readdir(i,{withFileTypes:!0})}catch(d){let c=d;if(c.code==="ENOENT")return;Pn(`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,f=Os.join(i,c),m;try{m=await Mn.readdir(f,{withFileTypes:!0})}catch(h){Pn(`hydra-acp: prune: failed to read ${f}: ${h.message}`);continue}for(let h of m){if(!h.isDirectory())continue;let p=h.name;if(p===u||l.has(p)||p.includes(".partial-"))continue;let g=Os.join(f,p);try{await Mn.rm(g,{recursive:!0,force:!0}),Pn(`hydra-acp: pruned stale ${c} ${p} (${g})`)}catch(w){Pn(`hydra-acp: prune: failed to remove ${g}: ${w.message}`)}}}}function Kd(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 Or(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 No(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 p=Date.parse(m.updatedAt);Number.isFinite(p)&&(s.maxAgeMs>0&&p>r||i.push({sessionId:m.sessionId,lastUsedMs:p}))}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 ${km(s.maxAgeMs)}`+(u>0?`; ${u} failed`:"")+(l>0?`; ${l} deferred to next sweep`:""))}let f={considered:i.length,deleted:c,failed:u,deferred:l};return d!==void 0&&(f.oldestLastUsedMs=d),f}function Qd(s){let e,t=!1,n=!1,r=o=>{t||(e=setTimeout(()=>{(async()=>{if(!n){n=!0;try{await No({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 km(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 vm}from"crypto";function _n(s){if(Array.isArray(s))return s.map(_n);if(s!==null&&typeof s=="object"){let e={};for(let t of Object.keys(s).sort())e[t]=_n(s[t]);return e}return s}function Yd(s){let e={};for(let[n,r]of Object.entries(s)){let o=fr(n);if(o.nested){let i={};for(let[a,d]of Object.entries(r??{}))pr(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(_n(e));return vm("sha256").update(t).digest("hex").slice(0,16)}function Xd(s,e){let t=[],n=(r,o)=>JSON.stringify(_n(r))!==JSON.stringify(_n(o));for(let r of Object.keys(e)){let o=fr(r),i=e[r],a=s[r];if(o.nested){for(let d of Object.keys(i??{})){if(pr(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 ec from"fs/promises";G();var bm=3e3;async function Zd(){try{return(await ec.stat(x.config())).mtimeMs}catch{return}}function tc(s){let e=s.intervalMs??bm,t=!1,n,r,o=Zd().then(d=>{r=d}),i=async()=>{await o;let d=await Zd();if(d===r)return;r=d;let c;try{c=await an()}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=Xd(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)}}G();Ne();import*as rc from"path";import{createHash as Sm,randomBytes as Im,timingSafeEqual as Am}from"crypto";var oc="hydra_session_",Cm=3600*24*30,nc=12,Rm=32,xm=50;function Em(){return rc.join(x.home(),"session-tokens.json")}function sc(s){return Sm("sha256").update(s).digest("hex")}function ic(s){return Im(s).toString("hex")}function Tm(){return ic(nc).slice(0,nc*2)}function Pm(){return`${oc}${ic(Rm)}`}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=Em(),n=await ie(t);n&&Array.isArray(n.records)&&(e=n.records.filter(Mm));let r=new s(e,t);return r.sweepExpired(new Date)>0&&await r.flush(),r}async issue(e={}){let t=Pm(),n=sc(t),r=Tm(),o=new Date,i=e.ttlSec&&e.ttlSec>0?e.ttlSec:Cm,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(oc))return;let t=sc(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||!Am(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(()=>{})},xm))}persist(){let e=(this.writeInflight??Promise.resolve()).catch(()=>{}).then(()=>fe(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 Mm(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 ac="Bearer ",Ns=class{constructor(e){this.token=e}token;async validate(e){return $m(e,this.token)?"service":void 0}rotate(e){this.token=e}},Ds=class{constructor(e){this.store=e}store;async validate(e){return this.store.verify(e)}},js=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 dc(s){return async function(t,n){let r=t.headers.authorization;if(!r||!r.startsWith(ac)){n.code(401).send({error:"Missing bearer token"});return}let o=r.slice(ac.length).trim(),i=await s.validator.validate(o);if(!i){n.code(403).send({error:"Invalid token"});return}t.authIdentity=i}}function cc(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=ur();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}`}},_m=new Set(["GET /v1/sessions","GET /v1/sessions/:id","GET /v1/config","GET /v1/system"]);function uc(s,e){return e?_m.has(`${s} ${e}`):!1}function $m(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 Ls=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 Wo from"fs";import*as Lc from"os";import*as Vs from"path";import*as qo from"readline";G();function Do(s){return Math.floor(s/4)}function lc(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+=Rt(i.content);break;case"tool_call":case"tool_call_update":{let a=typeof i.toolCallId=="string"?i.toolCallId:"",d=Om(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 Om(s){let e=0;return typeof s.title=="string"&&(e+=s.title.length),e+=Us(s.rawInput),e+=Rt(s.content),e+=Us(s.rawOutput),e}function Us(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+=Us(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+=Us(n);return t}return 0}function Rt(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+=Rt(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?Rt(e.text):e.type==="diff"?Rt(e.oldText)+Rt(e.newText):e.content!==void 0?Rt(e.content):0}function fc(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=Do(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}G();import{posix as Fm}from"path";import Nm from"strip-ansi";function $n(s){if(!s||typeof s!="object")return;let e=s;return typeof e.workerTaskId=="string"?e.workerTaskId:void 0}function jo(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 Dm=/[\x00-\x08\x0b-\x1f\x7f]/g;function Pe(s){return Nm(s).replace(Dm,"")}function re(s){return Pe(s).replace(/[\n\t]+/g," ").replace(/ +/g," ").trim()}function hc(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 qm(t);case"agent_thought_chunk":case"agent_thought":return zm(t);case"user_message_chunk":return Jm(t);case"prompt_received":return Vm(t);case"tool_call":return Gm(t,e);case"tool_call_update":return Zm(t,e);case"plan":return sh(t);case"current_mode_update":return rh(t);case"_hydra_current_model_update":return oh(t);case"turn_complete":return ih(t);case"_hydra_turn_started":return mc(t,"turn-started");case"_hydra_turn_ended":return mc(t,"turn-ended");case"usage_update":return Wm(t);case"available_commands_update":return Um(t);case"_hydra_available_modes_update":return Bm(t);case"session_info_update":return Hm(t);case"config_option_update":return jm(t);default:return{kind:"unknown",sessionUpdate:n,raw:s}}}function jm(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 Hm(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 Lm(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 Um(s){let e=s.availableCommands??s.commands;return Array.isArray(e)?{kind:"available-commands",commands:Lm(e)}:null}function Bm(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 Wm(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 qm(s){let e=On(s.content);return e===null?null:{kind:"agent-text",text:e,workerTaskId:$n(s)}}function zm(s){let e=typeof s.text=="string"?Pe(s.text):On(s.content);return e===null?null:{kind:"agent-thought",text:e,workerTaskId:$n(s)}}function Jm(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=On(s.content);return t===null?null:{kind:"user-text",text:t}}function Vm(s){let e=ah(s.prompt);return e===null?null:{kind:"user-text",text:e}}function yc(s){return s?s.toLowerCase().replace(/[_\s-]/g,"")==="exitplanmode":!1}function pc(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 Bs(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=pc(r.oldText),i=pc(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 wc(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:Pe(t)}function Gm(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(yc(r)){let p=wc(s);if(p!==null){let g=se(s,"status"),w={kind:"exit-plan-mode",toolCallId:t,plan:p};return g!==void 0&&(w.status=g),w}}let o=bc(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=Bs(s);c!==null&&(d.editDiff=c);let u=vc(s);u!==void 0&&(d.detail=u);let l=Ho(s);l!==void 0&&(d.detailFull=l);let f=kc(s);f!==void 0&&(d.locations=f);let m=$n(s);m!==void 0&&(d.workerTaskId=m);let h=jo(s);return h!==void 0&&(d.parentToolUseId=h),d}function kc(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 gc=64;function vc(s){let e=Ho(s);if(e===void 0)return;let t=re(e),n=s.rawInput;return n&&typeof n.command=="string"?Ym(t,gc):Xm(t,gc)}function Ho(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 Pe(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 O(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 O(re(n))}}}var Km=["home/","Users/","root/","tmp/","var/","opt/","etc/","usr/","mnt/","private/"];function Qm(s){for(let e of Km)if(s.startsWith(e))return!0;return!1}function bc(s,e,t={}){if(s.length===0)return s;if(s.startsWith("/"))return O(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 O(i)}return Qm(s)?O(`/${s}`):t.cwd&&t.cwd.length>0?O(Fm.resolve(t.cwd,s)):s}function Ym(s,e){return s.length>e?`${s.slice(0,e-1)}\u2026`:s}function Xm(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 Zm(s,e={}){let t=se(s,"toolCallId")??se(s,"id");if(!t)return null;let n=se(s,"title"),r=n!==void 0?bc(re(n),s,e):void 0,o=se(s,"status"),i=Bs(s),a=vc(s),d=eh(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(yc(u)){let g={kind:"exit-plan-mode",toolCallId:t},w=wc(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 f=Ho(s);f!==void 0&&(l.detailFull=f);let m=kc(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=th(s);g!==null&&(l.errorText=g),nh(s,g)&&(l.upstreamInterrupted=!0)}let h=$n(s);h!==void 0&&(l.workerTaskId=h);let p=jo(s);return p!==void 0&&(l.parentToolUseId=p),l}function eh(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,f=`${l}s`)=>`${u} ${u===1?l:f}`,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 th(s){let e=s.content;if(Array.isArray(e))for(let n of e){if(!n||typeof n!="object")continue;let o=On(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 Pe(n)}return null}function nh(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 sh(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 rh(s){let e=se(s,"currentModeId")??se(s,"currentMode")??se(s,"mode");return e?{kind:"mode-changed",mode:re(e)}:null}function oh(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 ih(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 mc(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 On(s){if(typeof s=="string")return Pe(s);if(!s||typeof s!="object")return null;let e=s;return e.type==="text"&&typeof e.text=="string"||typeof e.text=="string"?Pe(e.text):null}function ah(s){if(!Array.isArray(s))return null;let e=[];for(let t of s){let n=On(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 Sc(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=ch(i);if(c.length===0)continue;let u=c;if(d!==void 0){let l=e.get(d)??[],f=[];for(let m of c)l.some(h=>h.path===m.path&&h.oldText===m.oldText&&h.newText===m.newText)||f.push(m);if(f.length===0)continue;e.set(d,[...l,...f]),u=f}for(let l of u)dh(t,l)}let n=[];for(let[r,o]of t)n.push({path:r,hunks:o.hunks,created:o.created});return n}function Ic(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 dh(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 ch(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=Bs(s);return r&&r.path&&e.push({path:r.path,oldText:r.oldText,newText:r.newText}),e}function Cc(s,e={}){let t=lh(s),{events:n,window:r}=uh(t,e),o=fh(n),i=[];ph(i,s),r&&(r.from>1||r.to<r.total)&&(i.push(`_Showing turns ${r.from}-${r.to} of ${r.total}._`),i.push("")),gh(i,n,o,{includeTools:e.includeTools??!1,includeThoughts:e.includeThoughts??!1});let a=i.join(`
|
|
188
188
|
`);return a.endsWith(`
|
|
189
189
|
`)||(a+=`
|
|
190
|
-
`),a}function
|
|
191
|
-
`)),s.push("")}function
|
|
192
|
-
`);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
|
|
193
|
-
`))s.push(o);s.push(r)}function On(s){return s.replace(new RegExp(bc,"g"),e=>e.replace(/</g,"<").replace(/>/g,">"))}function No(s){return s.toLocaleString("en-US")}function ke(s){return s==="127.0.0.1"||s==="::1"||s==="localhost"||s==="[::1]"}function fh(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=>ph(u)).filter(u=>u.term.length>0);return{operator:o,terms:c}}function ph(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 gh(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 mh=5,hh=200,Bs=72,yh=24,wh=512;function xc(s){return Number.isFinite(s)?Math.max(yh,Math.min(wh,Math.floor(s))):Bs}async function Ec(s,e,t={}){let n=fh(e);if(n.terms.length===0)return{query:e,truncated:!1,results:[]};let r=t.maxSnippetsPerSession??mh,o=t.maxSessions??hh,i=xc(t.snippetWidth??Bs),a=t.sessionIds?new Set(t.sessionIds):null,d=await s.list(),c=a?d.filter(f=>a.has(f.sessionId)):d,u=[],l=!1;for(let f of c){if(u.length>=o){l=!0;break}let m=await s.loadHistory(f.sessionId,{tools:"references"}).catch(()=>[]),h=vh(m,n,r,i,kh(f));if(h.snippets.length===0)continue;let p={sessionId:f.sessionId,cwd:f.cwd,status:f.status,updatedAt:f.updatedAt,totalMatches:h.totalMatches,snippets:h.snippets};f.title!==void 0&&(p.title=f.title),u.push(p)}return{query:e,truncated:l,results:u}}function kh(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 vh(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=bh(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 bh(s,e,t,n,r,o){let i=e.toLowerCase(),a=0,d=[],c=new Set;for(let u of s){let l=Sh(u).filter(f=>gh(t,f.kind));for(let f of l){let m=f.text.toLowerCase();if(f.kind==="edit"){let g=o?.(f.text);if(!(Ic(f.text,e)||(g!==void 0&&g!==f.text?Ic(g,e):!1))||c.has(f.text))continue;if(c.add(f.text),a+=1,d.length<n){let y={kind:"edit",text:f.text,recordedAt:u.recordedAt};f.toolName!==void 0&&(y.toolName=f.toolName),d.push(y)}continue}let h=m.indexOf(i);if(h===-1)continue;let p=0;for(;h!==-1;)p++,h=m.indexOf(i,h+i.length);if(a+=p,d.length<n){let g=m.indexOf(i),w={kind:f.kind,text:Th(f.text,g,i.length,r),recordedAt:u.recordedAt};f.toolName!==void 0&&(w.toolName=f.toolName),d.push(w)}}}return{totalMatches:a,snippets:d}}function Sh(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=Us(n.content);return o?[{kind:"agent",text:o}]:[]}case"agent_thought":case"agent_thought_chunk":{let o=typeof n.text=="string"?Me(n.text):Us(n.content);return o?[{kind:"thought",text:o}]:[]}case"user_message_chunk":{if(xh(n))return[];let o=Us(n.content);return o?[{kind:"user",text:o}]:[]}case"prompt_received":{let o=Eh(n.prompt);return o?[{kind:"user",text:o}]:[]}case"tool_call":case"tool_call_update":return Ih(n);default:return[]}}function Ih(s){let e=Cc(s,"name"),t=Cc(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=Rc(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 Ah(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=Rc(o);if(a.length>0){let d={kind:"tool-input",text:re(a)};e!==void 0&&(d.toolName=e),n.push(d)}}let i=Ch(s);if(i!==null){let a={kind:"tool",text:i};e!==void 0&&(a.toolName=e),n.push(a)}return n}function Ah(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 Ic(s,e){let t=Ac(s.toLowerCase()),n=Ac(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 Ac(s){return s.length>1&&s.endsWith("/")?s.slice(0,-1):s}function Ch(s){if(!Rh(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 Rh(s){return s==="failed"||s==="rejected"||s==="cancelled"}function xh(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 Us(s){if(typeof s=="string")return Me(s);if(!s||typeof s!="object"||Array.isArray(s))return"";let e=s;return typeof e.text=="string"?Me(e.text):""}function Eh(s){if(!Array.isArray(s))return"";let e=[];for(let t of s){let n=Us(t);n.length>0&&e.push(n)}return e.join("")}function Cc(s,e){let t=s[e];return typeof t=="string"?t:void 0}function Rc(s){try{return JSON.stringify(s)}catch{return""}}function Th(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=xc(n),c=Math.max(0,d-i.length),u=Math.floor(c/2),l=Math.min(u,a),f=Math.min(c-l,r.length-(a+i.length)),m=Math.max(0,a-(c-f)),h=Math.min(r.length,a+i.length+f),p=m>0?"\u2026":"",g=h<r.length?"\u2026":"";return`${p}${r.slice(m,h)}${g}`}import{randomBytes as Pc}from"crypto";function Tc(s){let e=Pc(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 Do(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(Tc({name:"hydra-acp-stdin",session:n,tokenRegistry:e,getOrigin:t})),r.push(Tc({name:"hydra-acp-recall",session:n,tokenRegistry:e,getOrigin:t}));let o=Kt(s.deps);return o!==void 0&&(o.bindToSession(n),r=[...r,...o.descriptors]),r}}function Kt(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=Pc(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 Ph=new Set(["/v1/sessions/:id/history","/v1/sessions/:id/events"]);function Mc(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=dt(a);if(!d){if(!e.localMiss||await e.localMiss.resolvesLocally(a))return;let w=e.localMiss.cache.findByLocalId(a);if(w.length===0)return;if(w.length>1){r.code(404).send({error:`Session "${a}" exists on more than one remote (${w.map(y=>y.name).join(", ")}). Address it as "<remote>:${a}".`});return}d=w[0]}let c=e.store.get(d.name);if(!c){r.code(404).send({error:`No remote named "${d.name}". Run \`hydra remote add\` first.`});return}let u=n.query;if(Ph.has(o)&&_h(u?.follow)){let w=c.port===Tt?"":`:${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=$h(o,i,d.localId,n.url),m=`${ke(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(n.method==="DELETE"&&o==="/v1/sessions/:id"&&(h.ok||h.status===404)&&e.localMiss?.cache.evict(d.name,d.localId),h.status===204){r.code(204).send();return}let p=await h.text(),g=h.headers.get("content-type");g&&r.header("content-type",g),r.code(h.status).send(p)})}var Mh=5e3,Ws=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??Mh),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=ke(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(),f=o?.sessions??new Map;if(d){for(let[m,h]of[...f])h.status!=="cold"&&f.delete(m);for(let m of l.removed??[])f.delete(qe({name:n.name,localId:m}))}else f.clear();for(let m of l.sessions??[]){let h=qe({name:n.name,localId:String(m.sessionId)});f.set(h,{...m,sessionId:h,remote:n.name})}this.perPeer.set(n.name,{cursor:l.cursor,sessions:f})}))}list(e){let t=[];for(let n of this.perPeer.values())t.push(...n.sessions.values());return t.filter(n=>!(e.status&&n.status!==e.status||!e.includeNonInteractive&&n.interactive!==!0))}evict(e,t){this.perPeer.get(e)?.sessions.delete(qe({name:e,localId:t}))}findByLocalId(e){let t=e.startsWith(Ie)?[e]:[e,Ie+e],n=[];for(let[r,o]of this.perPeer)for(let i of t)if(o.sessions.has(qe({name:r,localId:i}))){n.push({name:r,localId:i});break}return n}};async function _c(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=`${ke(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:qe({name:e,localId:u.sessionId})}}:{status:a.status,body:c}}async function $c(s,e,t=fetch){let n;if(e.sessionIds===void 0)n=s.list().map(a=>({name:a.name}));else{let a=new Map;for(let d of e.sessionIds){let c=dt(d);if(!c)continue;let u=a.get(c.name)??[];u.push(c.localId),a.set(c.name,u)}n=[...a.entries()].map(([d,c])=>({name:d,sessionIds:c}))}if(n.length===0)return{query:e.q,truncated:!1,results:[]};let r=await Promise.all(n.map(async a=>{let d=s.get(a.name);if(!d)return null;let u=`${ke(d.host)?"http":"https"}://${d.host}:${d.port}/v1/sessions/search`,l;try{l=await t(u,{method:"POST",headers:{Authorization:`Bearer ${d.token}`,"Content-Type":"application/json"},body:JSON.stringify({q:e.q,...a.sessionIds?{sessionIds:a.sessionIds}:{},...e.snippetWidth!==void 0?{snippetWidth:e.snippetWidth}:{}})})}catch{return null}if(!l.ok)return null;let f;try{f=await l.json()}catch{return null}let m=f;if(!m||!Array.isArray(m.results))return null;let h=m.results.map(p=>({...p,sessionId:qe({name:a.name,localId:p.sessionId})}));return{query:e.q,truncated:m.truncated===!0,results:h}})),o=[],i=!1;for(let a of r)a!==null&&(o.push(...a.results),i=i||a.truncated);return{query:e.q,truncated:i,results:o}}function _h(s){return s==="1"||s==="true"||s===!0}function $h(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 qs=new Set(["usage_update","tool_call","tool_call_update","prompt_received","turn_complete","permission_resolved"]);function Oc(s){if(s.publicHost&&s.publicHost.length>0)return s.publicHost;if(s.host&&!ke(s.host))return s.port!==void 0?`${s.host}:${s.port}`:s.host}function Nc(s,e,t,n={},r,o){s.get("/v1/sessions",async(l,f)=>{let m=l.query,h=m?.includeNonInteractive==="1"||m?.includeNonInteractive==="true",p;if(m?.since!==void 0&&(p=Number(m.since),!Number.isFinite(p)||p<0))return f.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(p!==void 0){let b=await e.listSince(w,p);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,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=await e.getOne(h);return p||(f.code(404).send({error:"session not found"}),f)}),s.post("/v1/sessions/search",async(l,f)=>{let m=l.body??{},h=typeof m.q=="string"?m.q:"";if(h.trim().length===0)return f.code(400).send({error:"q is required"}),f;let p=Array.isArray(m.sessionIds)?m.sessionIds.filter(k=>typeof k=="string"&&k.length>0):void 0,g={sessionIds:p};typeof m.snippetWidth=="number"&&(g.snippetWidth=m.snippetWidth);let w=await Ec(e,h,g);if(!r)return w;let y=await $c(r,{q:h,...p?{sessionIds:p}:{},...g.snippetWidth!==void 0?{snippetWidth:g.snippetWidth}:{}});return{query:h,truncated:w.truncated||y.truncated,results:[...w.results,...y.results]}}),s.post("/v1/sessions",async(l,f)=>{let m=l.body??{};if(m.remote){if(!r)return f.code(404).send({error:`No remote named "${m.remote}". Run \`hydra remote add\` first.`});let k=await _c(r,m.remote,{cwd:m.cwd,agentId:m.agentId,mcpServers:m.mcpServers,workspace:m.workspace});return f.code(k.status).send(k.body)}let h=ce(m.cwd??t.cwd),p=await sn(h),g=m.agentId??p.agentId??t.agentId,w=Kt(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),f.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),f.code(500).send({error:k.message})}}),s.post("/v1/sessions/collect",async(l,f)=>{let m=l.body??{},h=typeof m.maxAgeDays=="number"&&m.maxAgeDays>0?m.maxAgeDays*24*60*60*1e3:0,p=typeof m.limit=="number"&&m.limit>0?m.limit:1e3,g=m.selection==="explicit"||m.selection==="unpromoted"?m.selection:"unpromoted";try{let w=await Mo({manager:e,maxAgeMs:h,maxDeletions:p,selection:g,verbose:!1});f.code(200).send(w)}catch(w){f.code(500).send({error:w.message})}}),s.get("/v1/sessions/tombstones",async(l,f)=>{let m=l.query;if(m.since!==void 0&&Number.isNaN(Date.parse(m.since))){f.code(400).send({error:"since must be an ISO timestamp"});return}let h=await e.listTombstones({...m.agent?{agentId:m.agent}:{},...m.since?{since:m.since}:{},...m.grep?{grep:m.grep}:{}});f.code(200).send({tombstones:h})}),s.post("/v1/sessions/undelete",async(l,f)=>{let m=l.body??{};if(!Array.isArray(m.ids)||m.ids.length===0||!m.ids.every(h=>typeof h=="string"&&h.length>0)){f.code(400).send({error:"ids must be a non-empty array of strings"});return}try{f.code(200).send(await e.undeleteSessions(m.ids))}catch(h){f.code(500).send({error:h.message})}}),s.post("/v1/sessions/:id/kill",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);if(p){p.close({deleteRecord:!1,by:"REST POST /kill"}).catch(()=>{}),f.code(202).send();return}if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.post("/v1/sessions/:id/stdin/open",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);if(!p)return f.code(404).send({error:"session not found"}),f;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=>zs.join(Fc.tmpdir(),`hydra-acp-stdin-${y}.log`));try{return p.openStream(w)}catch(y){return f.code(409).send({error:y.message}),f}}),s.post("/v1/sessions/:id/stdin",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);if(!p)return f.code(404).send({error:"session not found"}),f;let g=l.body??{},w=typeof g.chunk=="string"?g.chunk:"",y=g.eof===!0;try{return p.streamWrite(w,y)}catch(k){return f.code(409).send({error:k.message}),f}}),s.patch("/v1/sessions/:id",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=l.body??{};if(p.cwd!==void 0){if(typeof p.cwd!="string"||!zs.isAbsolute(p.cwd)){f.code(400).send({error:"cwd must be an absolute path"});return}let w=await e.setCwd(h,p.cwd);if(w==="missing"){f.code(404).send({error:"session not found"});return}if(w==="not-a-directory"){f.code(400).send({error:`${p.cwd} is not a directory`});return}if(w==="live"){f.code(409).send({error:"session is live; its agent was spawned in its cwd and cannot change directory. Moving a live session is a swap \u2014 use `workspace start` in it."});return}if(w==="bound"){f.code(409).send({error:"session is isolated, so its cwd IS its workspace. Clear the binding first (PATCH { workspace: null }) or leave the workspace from inside the session."});return}f.code(204).send();return}if("workspace"in p){if(p.workspace!==null){f.code(400).send({error:"workspace may only be set to null (clear the binding)"});return}let w=await e.clearWorkspaceBinding(h);if(w==="missing"){f.code(404).send({error:"session not found"});return}if(w==="live"){f.code(409).send({error:"session is live; its cwd is the workspace. Use `workspace stop` or `workspace detach` in the session so the agent moves with the binding."});return}f.code(204).send();return}if(p.priority!==void 0){let w=p.priority,y;if(w===null||w===0)y=void 0;else if(typeof w=="number"&&Number.isInteger(w)&&w>0)y=w;else{f.code(400).send({error:"priority must be a non-negative integer (or null to clear)"});return}if(!await e.setPriority(h,y)){f.code(404).send({error:"session not found"});return}f.code(204).send();return}if(p.regen===!0){if(!(e.get(h)!==void 0||await e.hasRecord(h))){f.code(404).send({error:"session not found"});return}e.scheduleSynopsis(h),f.code(202).send();return}if(typeof p.title!="string"||p.title.trim().length===0){f.code(400).send({error:"title must be a non-empty string"});return}if(!await e.setTitle(h,p.title)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.delete("/v1/sessions/:id",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);if(p){await p.close({deleteRecord:!0,by:"REST DELETE /v1/sessions"}),await e.waitForDeletion(h),await e.hasRecord(h)&&await e.deleteRecord(h),f.code(204).send();return}if(!await e.deleteRecord(h)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.get("/v1/sessions/:id/export",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=l.query?.tools,g=p==="references"?"references":Id(p),w=await e.exportBundle(h,g==="references"?{tools:"references"}:{});if(!w){f.code(404).send({error:"session not found"});return}let y=Sn({record:w.record,history:g==="summary"?Ad(w.history,"summary"):w.history,promptHistory:w.promptHistory.length>0?w.promptHistory:void 0,...w.toolBlobs!==void 0?{toolBlobs:w.toolBlobs}:{},hydraVersion:le,machine:cn(),hydraHost:Oc(t)}),k=new Date().toISOString().replace(/[:.]/g,"-");f.header("Content-Disposition",`attachment; filename="${h}-${k}.hydra"`),f.code(200).send(y)}),s.get("/v1/sessions/:id/diff",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=await e.exportBundle(h);if(!p){f.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=yc(p.history);y&&(k=k.filter(b=>y.has(b.path))),w&&(k=k.map(b=>({...b,hunks:wc(b.hunks)}))),f.code(200).send(k)}),s.get("/v1/sessions/:id/tools/:hash",async(l,f)=>{let m=l.params,h=await e.resolveCanonicalId(m.id)??m.id,p=await e.loadToolBlob(h,m.hash);if(p===null){f.code(404).send({error:"tool blob not found"});return}f.header("Content-Type","text/plain; charset=utf-8"),f.code(200).send(p)}),s.get("/v1/sessions/:id/transcript",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=await e.exportBundle(h);if(!p){f.code(404).send({error:"session not found"});return}let g=Sn({record:p.record,history:p.history,promptHistory:p.promptHistory.length>0?p.promptHistory:void 0,hydraVersion:le,machine:cn(),hydraHost:Oc(t)}),w=l.query,y=I=>I==="1"||I==="true"||I==="yes",k=I=>{let v=w?.[I];if(v===void 0||v==="")return;let A=Number(v);return Number.isFinite(A)?A:"bad"},b={};for(let I of["from","to","last","since"]){let v=k(I);if(v==="bad"){f.code(400).send({error:`${I} must be a number`});return}v!==void 0&&(b[I==="since"?"sinceMs":I]=v)}f.header("Content-Type","text/markdown; charset=utf-8"),f.code(200).send(vc(g,{includeTools:y(w?.tools),includeThoughts:y(w?.thoughts),...b}))}),s.post("/v1/sessions/:id/fork",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=l.body??{},g={};if(p.forkAt!==void 0){if(typeof p.forkAt!="string"||p.forkAt.length===0){f.code(400).send({error:"forkAt must be a non-empty string"});return}g.forkAt=p.forkAt}if(p.cwd!==void 0){if(typeof p.cwd!="string"||p.cwd.length===0){f.code(400).send({error:"cwd must be a non-empty string"});return}g.cwd=ce(p.cwd)}if(p.agentId!==void 0){if(typeof p.agentId!="string"||p.agentId.length===0){f.code(400).send({error:"agentId must be a non-empty string"});return}g.agentId=p.agentId}if(p.title!==void 0){if(typeof p.title!="string"){f.code(400).send({error:"title must be a string"});return}g.title=p.title}if(p.mode!==void 0){if(p.mode!=="verbatim"&&p.mode!=="synthesis"){f.code(400).send({error:'mode must be "verbatim" or "synthesis"'});return}g.mode=p.mode}if(p.model!==void 0){if(typeof p.model!="string"||p.model.length===0){f.code(400).send({error:"model must be a non-empty string"});return}g.model=p.model}try{let w=await e.forkSession(h,g);f.code(201).send(w)}catch(w){let y=w;if(y.code===E.SessionNotFound){f.code(404).send({error:y.message});return}if(y.code===E.InvalidParams||y.code===E.AgentNotInstalled){f.code(400).send({error:y.message});return}f.code(500).send({error:y.message})}}),s.post("/v1/sessions/import",async(l,f)=>{let m=l.body??{};if(m.bundle===void 0){f.code(400).send({error:"missing bundle"});return}let h;if(m.cwd!==void 0){if(typeof m.cwd!="string"||m.cwd.length===0){f.code(400).send({error:"cwd must be a non-empty string"});return}h=m.cwd}let p;try{p=_d(m.bundle)}catch(g){f.code(400).send({error:"invalid bundle",details:g.message});return}try{let g=await e.importBundle(p,{replace:m.replace===!0,...h!==void 0?{cwd:h}:{}});f.code(201).send(g)}catch(g){let w=g;if(w.code===E.BundleAlreadyImported){f.code(409).send({error:"bundle already imported",existingSessionId:w.existingSessionId});return}f.code(500).send({error:w.message})}}),s.get("/v1/sessions/:id/compact/status",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h),g;if(p?g=p.summarizedThroughEntry:g=await e.getSummarizedThroughEntry(h),g===void 0&&!await e.hasRecord(h))return f.code(404).send({error:"session not found"}),f;let w=await e.getCompactionState(h),y=await e.getRollbackBreadcrumb(h),k=await e.getPendingAgentSwap(h),b=!1,I,v=p?.currentUsage,A=typeof v?.used=="number"&&typeof v?.size=="number"&&v.size>0?{used:v.used,size:v.size}:void 0,C=await e.loadHistory(h,{tools:"references",maxEntries:1/0}).catch(()=>[]);if(C.length>0&&t.compaction){let R=g??0,T=C.length,_=R<=C.length?R:0,H=C.slice(_),J=ic(H);I=_o(J);let M=p?.currentModel,W=C.at(-1).recordedAt;b=ac({summarizedThroughEntry:R,totalEntries:T,unsummarizedChars:J,compactionInFlight:e.getCompactionInFlight(),currentModel:M,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,...I!=null?{approxTokens:I}:{},...A!=null?{currentUsage:A}:{},...w!=null?{compactionState:w}:{},...y!=null?{rollbackBreadcrumb:y}:{},...k!=null?{pendingAgentSwap:k}:{}}}),s.post("/v1/sessions/:id/compact",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m;if(e.get(h)){e.scheduleCompaction(h),f.code(202).send({scheduled:!0});return}if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}e.scheduleCompaction(h),f.code(202).send({scheduled:!0})}),s.post("/v1/sessions/:id/compact/rollback",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m;if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}try{await e.performUncompact(h),f.code(202).send({rolledBack:!0})}catch(p){let g=p instanceof Error?p.message:String(p);f.code(409).send({error:g})}}),s.post("/v1/sessions/:id/workspace/clean",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=l.body??{};if(p.deep!==void 0&&typeof p.deep!="boolean"){f.code(400).send({error:"deep must be a boolean"});return}if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}if(e.get(h)===void 0){f.code(409).send({error:"session is not live. Cleaning rewrites the workspace under a running agent, so it is only available inside a live session (`/hydra workspace clean`). For a cold workspace use `hydra workspace remove` instead."});return}try{let g=await e.runWorkspaceAction(h,"clean",void 0,{deep:p.deep===!0});f.code(202).send({report:g})}catch(g){f.code(409).send({error:g instanceof Error?g.message:String(g)})}}),s.get("/v1/sessions/:id/history/page",async(l,f)=>{let m=l.params.id,h=l.query,p=Number(h?.beforeSeq);if(h?.beforeSeq===void 0||h.beforeSeq===""||!Number.isFinite(p)){f.code(400).send({error:"beforeSeq must be a number"});return}let g=h.turns===void 0||h.turns===""?10:Number(h.turns);if(!Number.isInteger(g)||g<1){f.code(400).send({error:"turns must be a positive integer"});return}let w=await e.resolveCanonicalId(m)??m,y=await e.pageHistory(w,{beforeSeq:p,turns:Math.min(g,100)});if(!y){f.code(404).send({error:"session not found"});return}f.code(200).send({entries:Zn(y.entries),hasMore:y.hasMore})}),s.get("/v1/sessions/:id/history",async(l,f)=>{let m=l.params.id,h=l.query,p=h?.follow==="1"||h?.follow==="true",g=await e.resolveCanonicalId(m)??m,w=e.get(g),y,k,b=!1,I=1e4,v=[];if(w){p&&(k=w.onBroadcast(C=>{f.raw.writableEnded||(b?f.raw.write(JSON.stringify(C)+`
|
|
190
|
+
`),a}function Lo(s,e){let t=s<0?e+s+1:s;return t<1?1:t>e?e:t}function uh(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=Lo(o-e.last+1,o):(e.from!==void 0&&(i=Lo(e.from,o)),e.to!==void 0&&(a=Lo(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,f;return s.forEach((m,h)=>{let p=n[h];p<i||p>a||d!==void 0&&!c.has(p)||(u.push(m),l??=p,f=p)}),{events:u,window:{from:l??i,to:f??a,total:o}}}function lh(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=hc(n.update,{cwd:s.session.cwd});r!==null&&e.push({event:r,recordedAt:t.recordedAt})}return e}function fh(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 ph(s,e){let t=e.session,n=Xe(t.sessionId),r=t.title?.trim()||`Hydra session ${n}`;s.push(`# ${Fn(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?`${Uo(a.size)}`:void 0;d.push(u?`${Uo(a.used)} / ${u} tokens`:`${Uo(a.used)} tokens`)}let c=Ao(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(`
|
|
191
|
+
`)),s.push("")}function gh(s,e,t,n){let{includeTools:r,includeThoughts:o}=n;if(!e.some(p=>mh(p.event,o))){s.push("_No conversation history recorded._"),s.push("");return}let i=0,a="",d="",c=[],u=new Set,l=!1,f=()=>{if(c.length!==0){for(let p of c)s.push(p);s.push(""),c=[]}},m=()=>{f(),d.length>0&&(Ac(s,d.trimEnd(),"*"),s.push(""),d=""),a.length!==0&&(s.push(a.trimEnd()),s.push(""),a="")},h=()=>{l||(l=!0)};for(let{event:p}of e)switch(p.kind){case"user-text":{m(),s.push("---"),s.push(""),i+=1,Ac(s,p.text,"**"),s.push(""),l=!0;break}case"agent-text":h(),a+=p.text;break;case"agent-thought":{if(!o)break;h(),a.length>0&&(s.push(a.trimEnd()),s.push(""),a=""),d+=p.text;break}case"tool-call":{if(!r||(h(),(a.length>0||d.length>0)&&m(),u.has(p.toolCallId)))break;u.add(p.toolCallId);let g=t.get(p.toolCallId)??{title:p.title,status:p.status??"pending"};c.push(`- ${yh(g.status)} ${hh(g)}`);break}case"tool-call-update":break;case"plan":{h(),m(),s.push("**Plan:**"),s.push("");for(let g of p.entries){let w=g.status==="completed"?"[x]":"[ ]";s.push(`- ${w} ${Fn(g.content)}`)}s.push("");break}case"mode-changed":h(),m(),s.push(`_mode: ${Fn(p.mode)}_`),s.push("");break;case"model-changed":h(),m(),s.push(`_model: ${Fn(p.model)}_`),s.push("");break;case"turn-complete":m();break;case"usage-update":case"available-commands":case"session-info":case"unknown":break}m()}function mh(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 hh(s){let e=s.status,t=e==="completed"||e===void 0?"":` _(${e})_`;return`${Fn(s.title)}${t}`}function yh(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 Rc=String.raw`<\/?[a-zA-Z][a-zA-Z0-9-]*(?:\s[^<>]*)?\/?>`,wh=new RegExp(Rc);function Ac(s,e,t){if(wh.test(e)){kh(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(`
|
|
192
|
+
`);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 kh(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(`
|
|
193
|
+
`))s.push(o);s.push(r)}function Fn(s){return s.replace(new RegExp(Rc,"g"),e=>e.replace(/</g,"<").replace(/>/g,">"))}function Uo(s){return s.toLocaleString("en-US")}function ke(s){return s==="127.0.0.1"||s==="::1"||s==="localhost"||s==="[::1]"}function vh(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=>bh(u)).filter(u=>u.term.length>0);return{operator:o,terms:c}}function bh(s){let e=/^(\w+):"([^"]*)"$/.exec(s);if(e)return{scope:xc(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:xc(n[1]),term:n[2].trim()}:{scope:"all",term:s.trim()}}function xc(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 Sh(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 Ih=5,Ah=200,qs=72,Ch=24,Rh=512;function _c(s){return Number.isFinite(s)?Math.max(Ch,Math.min(Rh,Math.floor(s))):qs}async function $c(s,e,t={}){let n=vh(e);if(n.terms.length===0)return{query:e,truncated:!1,results:[]};let r=t.maxSnippetsPerSession??Ih,o=t.maxSessions??Ah,i=_c(t.snippetWidth??qs),a=t.sessionIds?new Set(t.sessionIds):null,d=await s.list(),c=a?d.filter(f=>a.has(f.sessionId)):d,u=[],l=!1;for(let f of c){if(u.length>=o){l=!0;break}let m=await s.loadHistory(f.sessionId,{tools:"references"}).catch(()=>[]),h=Eh(m,n,r,i,xh(f));if(h.snippets.length===0)continue;let p={sessionId:f.sessionId,cwd:f.cwd,status:f.status,updatedAt:f.updatedAt,totalMatches:h.totalMatches,snippets:h.snippets};f.title!==void 0&&(p.title=f.title),u.push(p)}return{query:e,truncated:l,results:u}}function xh(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 Eh(s,e,t,n=qs,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=Th(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 Th(s,e,t,n,r,o){let i=e.toLowerCase(),a=0,d=[],c=new Set;for(let u of s){let l=Ph(u).filter(f=>Sh(t,f.kind));for(let f of l){let m=f.text.toLowerCase();if(f.kind==="edit"){let g=o?.(f.text);if(!(Ec(f.text,e)||(g!==void 0&&g!==f.text?Ec(g,e):!1))||c.has(f.text))continue;if(c.add(f.text),a+=1,d.length<n){let y={kind:"edit",text:f.text,recordedAt:u.recordedAt};f.toolName!==void 0&&(y.toolName=f.toolName),d.push(y)}continue}let h=m.indexOf(i);if(h===-1)continue;let p=0;for(;h!==-1;)p++,h=m.indexOf(i,h+i.length);if(a+=p,d.length<n){let g=m.indexOf(i),w={kind:f.kind,text:Dh(f.text,g,i.length,r),recordedAt:u.recordedAt};f.toolName!==void 0&&(w.toolName=f.toolName),d.push(w)}}}return{totalMatches:a,snippets:d}}function Ph(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=Ws(n.content);return o?[{kind:"agent",text:o}]:[]}case"agent_thought":case"agent_thought_chunk":{let o=typeof n.text=="string"?Pe(n.text):Ws(n.content);return o?[{kind:"thought",text:o}]:[]}case"user_message_chunk":{if(Fh(n))return[];let o=Ws(n.content);return o?[{kind:"user",text:o}]:[]}case"prompt_received":{let o=Nh(n.prompt);return o?[{kind:"user",text:o}]:[]}case"tool_call":case"tool_call_update":return Mh(n);default:return[]}}function Mh(s){let e=Pc(s,"name"),t=Pc(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=Mc(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 _h(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=Mc(o);if(a.length>0){let d={kind:"tool-input",text:re(a)};e!==void 0&&(d.toolName=e),n.push(d)}}let i=$h(s);if(i!==null){let a={kind:"tool",text:i};e!==void 0&&(a.toolName=e),n.push(a)}return n}function _h(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 Ec(s,e){let t=Tc(s.toLowerCase()),n=Tc(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 Tc(s){return s.length>1&&s.endsWith("/")?s.slice(0,-1):s}function $h(s){if(!Oh(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 Oh(s){return s==="failed"||s==="rejected"||s==="cancelled"}function Fh(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 Ws(s){if(typeof s=="string")return Pe(s);if(!s||typeof s!="object"||Array.isArray(s))return"";let e=s;return typeof e.text=="string"?Pe(e.text):""}function Nh(s){if(!Array.isArray(s))return"";let e=[];for(let t of s){let n=Ws(t);n.length>0&&e.push(n)}return e.join("")}function Pc(s,e){let t=s[e];return typeof t=="string"?t:void 0}function Mc(s){try{return JSON.stringify(s)}catch{return""}}function Dh(s,e,t,n=qs){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=_c(n),c=Math.max(0,d-i.length),u=Math.floor(c/2),l=Math.min(u,a),f=Math.min(c-l,r.length-(a+i.length)),m=Math.max(0,a-(c-f)),h=Math.min(r.length,a+i.length+f),p=m>0?"\u2026":"",g=h<r.length?"\u2026":"";return`${p}${r.slice(m,h)}${g}`}import{randomBytes as Fc}from"crypto";function Oc(s){let e=Fc(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 Bo(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(Oc({name:"hydra-acp-stdin",session:n,tokenRegistry:e,getOrigin:t})),r.push(Oc({name:"hydra-acp-recall",session:n,tokenRegistry:e,getOrigin:t}));let o=Yt(s.deps);return o!==void 0&&(o.bindToSession(n),r=[...r,...o.descriptors]),r}}function Yt(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=Fc(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 jh=new Set(["/v1/sessions/:id/history","/v1/sessions/:id/events"]);function Nc(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=dt(a);if(!d){if(!e.localMiss||await e.localMiss.resolvesLocally(a))return;let w=e.localMiss.cache.findByLocalId(a);if(w.length===0)return;if(w.length>1){r.code(404).send({error:`Session "${a}" exists on more than one remote (${w.map(y=>y.name).join(", ")}). Address it as "<remote>:${a}".`});return}d=w[0]}let c=e.store.get(d.name);if(!c){r.code(404).send({error:`No remote named "${d.name}". Run \`hydra remote add\` first.`});return}let u=n.query;if(jh.has(o)&&Lh(u?.follow)){let w=c.port===Mt?"":`:${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=Uh(o,i,d.localId,n.url),m=`${ke(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(n.method==="DELETE"&&o==="/v1/sessions/:id"&&(h.ok||h.status===404)&&e.localMiss?.cache.evict(d.name,d.localId),h.status===204){r.code(204).send();return}let p=await h.text(),g=h.headers.get("content-type");g&&r.header("content-type",g),r.code(h.status).send(p)})}var Hh=5e3,zs=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??Hh),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=ke(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(),f=o?.sessions??new Map;if(d){for(let[m,h]of[...f])h.status!=="cold"&&f.delete(m);for(let m of l.removed??[])f.delete(qe({name:n.name,localId:m}))}else f.clear();for(let m of l.sessions??[]){let h=qe({name:n.name,localId:String(m.sessionId)});f.set(h,{...m,sessionId:h,remote:n.name})}this.perPeer.set(n.name,{cursor:l.cursor,sessions:f})}))}list(e){let t=[];for(let n of this.perPeer.values())t.push(...n.sessions.values());return t.filter(n=>!(e.status&&n.status!==e.status||!e.includeNonInteractive&&n.interactive!==!0))}evict(e,t){this.perPeer.get(e)?.sessions.delete(qe({name:e,localId:t}))}findByLocalId(e){let t=e.startsWith(Se)?[e]:[e,Se+e],n=[];for(let[r,o]of this.perPeer)for(let i of t)if(o.sessions.has(qe({name:r,localId:i}))){n.push({name:r,localId:i});break}return n}};async function Dc(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=`${ke(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:qe({name:e,localId:u.sessionId})}}:{status:a.status,body:c}}async function jc(s,e,t=fetch){let n;if(e.sessionIds===void 0)n=s.list().map(a=>({name:a.name}));else{let a=new Map;for(let d of e.sessionIds){let c=dt(d);if(!c)continue;let u=a.get(c.name)??[];u.push(c.localId),a.set(c.name,u)}n=[...a.entries()].map(([d,c])=>({name:d,sessionIds:c}))}if(n.length===0)return{query:e.q,truncated:!1,results:[]};let r=await Promise.all(n.map(async a=>{let d=s.get(a.name);if(!d)return null;let u=`${ke(d.host)?"http":"https"}://${d.host}:${d.port}/v1/sessions/search`,l;try{l=await t(u,{method:"POST",headers:{Authorization:`Bearer ${d.token}`,"Content-Type":"application/json"},body:JSON.stringify({q:e.q,...a.sessionIds?{sessionIds:a.sessionIds}:{},...e.snippetWidth!==void 0?{snippetWidth:e.snippetWidth}:{}})})}catch{return null}if(!l.ok)return null;let f;try{f=await l.json()}catch{return null}let m=f;if(!m||!Array.isArray(m.results))return null;let h=m.results.map(p=>({...p,sessionId:qe({name:a.name,localId:p.sessionId})}));return{query:e.q,truncated:m.truncated===!0,results:h}})),o=[],i=!1;for(let a of r)a!==null&&(o.push(...a.results),i=i||a.truncated);return{query:e.q,truncated:i,results:o}}function Lh(s){return s==="1"||s==="true"||s===!0}function Uh(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 Js=new Set(["usage_update","tool_call","tool_call_update","prompt_received","turn_complete","permission_resolved"]);function Hc(s){if(s.publicHost&&s.publicHost.length>0)return s.publicHost;if(s.host&&!ke(s.host))return s.port!==void 0?`${s.host}:${s.port}`:s.host}function Uc(s,e,t,n={},r,o){s.get("/v1/sessions",async(l,f)=>{let m=l.query,h=m?.includeNonInteractive==="1"||m?.includeNonInteractive==="true",p;if(m?.since!==void 0&&(p=Number(m.since),!Number.isFinite(p)||p<0))return f.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(p!==void 0){let b=await e.listSince(w,p);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,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=await e.getOne(h);return p||(f.code(404).send({error:"session not found"}),f)}),s.post("/v1/sessions/search",async(l,f)=>{let m=l.body??{},h=typeof m.q=="string"?m.q:"";if(h.trim().length===0)return f.code(400).send({error:"q is required"}),f;let p=Array.isArray(m.sessionIds)?m.sessionIds.filter(k=>typeof k=="string"&&k.length>0):void 0,g={sessionIds:p};typeof m.snippetWidth=="number"&&(g.snippetWidth=m.snippetWidth);let w=await $c(e,h,g);if(!r)return w;let y=await jc(r,{q:h,...p?{sessionIds:p}:{},...g.snippetWidth!==void 0?{snippetWidth:g.snippetWidth}:{}});return{query:h,truncated:w.truncated||y.truncated,results:[...w.results,...y.results]}}),s.post("/v1/sessions",async(l,f)=>{let m=l.body??{};if(m.remote){if(!r)return f.code(404).send({error:`No remote named "${m.remote}". Run \`hydra remote add\` first.`});let k=await Dc(r,m.remote,{cwd:m.cwd,agentId:m.agentId,mcpServers:m.mcpServers,workspace:m.workspace});return f.code(k.status).send(k.body)}let h=ae(m.cwd??t.cwd),p=await on(h),g=m.agentId??p.agentId??t.agentId,w=Yt(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),f.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),f.code(500).send({error:k.message})}}),s.post("/v1/sessions/collect",async(l,f)=>{let m=l.body??{},h=typeof m.maxAgeDays=="number"&&m.maxAgeDays>0?m.maxAgeDays*24*60*60*1e3:0,p=typeof m.limit=="number"&&m.limit>0?m.limit:1e3,g=m.selection==="explicit"||m.selection==="unpromoted"?m.selection:"unpromoted";try{let w=await No({manager:e,maxAgeMs:h,maxDeletions:p,selection:g,verbose:!1});f.code(200).send(w)}catch(w){f.code(500).send({error:w.message})}}),s.get("/v1/sessions/tombstones",async(l,f)=>{let m=l.query;if(m.since!==void 0&&Number.isNaN(Date.parse(m.since))){f.code(400).send({error:"since must be an ISO timestamp"});return}let h=await e.listTombstones({...m.agent?{agentId:m.agent}:{},...m.since?{since:m.since}:{},...m.grep?{grep:m.grep}:{}});f.code(200).send({tombstones:h})}),s.post("/v1/sessions/undelete",async(l,f)=>{let m=l.body??{};if(!Array.isArray(m.ids)||m.ids.length===0||!m.ids.every(h=>typeof h=="string"&&h.length>0)){f.code(400).send({error:"ids must be a non-empty array of strings"});return}try{f.code(200).send(await e.undeleteSessions(m.ids))}catch(h){f.code(500).send({error:h.message})}}),s.post("/v1/sessions/:id/kill",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);if(p){p.close({deleteRecord:!1,by:"REST POST /kill"}).catch(()=>{}),f.code(202).send();return}if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.post("/v1/sessions/:id/stdin/open",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);if(!p)return f.code(404).send({error:"session not found"}),f;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=>Vs.join(Lc.tmpdir(),`hydra-acp-stdin-${y}.log`));try{return p.openStream(w)}catch(y){return f.code(409).send({error:y.message}),f}}),s.post("/v1/sessions/:id/stdin",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);if(!p)return f.code(404).send({error:"session not found"}),f;let g=l.body??{},w=typeof g.chunk=="string"?g.chunk:"",y=g.eof===!0;try{return p.streamWrite(w,y)}catch(k){return f.code(409).send({error:k.message}),f}}),s.patch("/v1/sessions/:id",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=l.body??{};if(p.cwd!==void 0){if(typeof p.cwd!="string"||!Vs.isAbsolute(p.cwd)){f.code(400).send({error:"cwd must be an absolute path"});return}let w=await e.setCwd(h,p.cwd);if(w==="missing"){f.code(404).send({error:"session not found"});return}if(w==="not-a-directory"){f.code(400).send({error:`${p.cwd} is not a directory`});return}if(w==="live"){f.code(409).send({error:"session is live; its agent was spawned in its cwd and cannot change directory. Moving a live session is a swap \u2014 use `workspace start` in it."});return}if(w==="bound"){f.code(409).send({error:"session is isolated, so its cwd IS its workspace. Clear the binding first (PATCH { workspace: null }) or leave the workspace from inside the session."});return}f.code(204).send();return}if("workspace"in p){if(p.workspace!==null){f.code(400).send({error:"workspace may only be set to null (clear the binding)"});return}let w=await e.clearWorkspaceBinding(h);if(w==="missing"){f.code(404).send({error:"session not found"});return}if(w==="live"){f.code(409).send({error:"session is live; its cwd is the workspace. Use `workspace stop` or `workspace detach` in the session so the agent moves with the binding."});return}f.code(204).send();return}if(p.priority!==void 0){let w=p.priority,y;if(w===null||w===0)y=void 0;else if(typeof w=="number"&&Number.isInteger(w)&&w>0)y=w;else{f.code(400).send({error:"priority must be a non-negative integer (or null to clear)"});return}if(!await e.setPriority(h,y)){f.code(404).send({error:"session not found"});return}f.code(204).send();return}if(p.regen===!0){if(!(e.get(h)!==void 0||await e.hasRecord(h))){f.code(404).send({error:"session not found"});return}e.scheduleSynopsis(h),f.code(202).send();return}if(typeof p.title!="string"||p.title.trim().length===0){f.code(400).send({error:"title must be a non-empty string"});return}if(!await e.setTitle(h,p.title)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.delete("/v1/sessions/:id",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);if(p){await p.close({deleteRecord:!0,by:"REST DELETE /v1/sessions"}),await e.waitForDeletion(h),await e.hasRecord(h)&&await e.deleteRecord(h),f.code(204).send();return}if(!await e.deleteRecord(h)){f.code(404).send({error:"session not found"});return}f.code(204).send()}),s.get("/v1/sessions/:id/export",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=l.query?.tools,g=p==="references"?"references":Ed(p),w=await e.exportBundle(h,g==="references"?{tools:"references"}:{});if(!w){f.code(404).send({error:"session not found"});return}let y=In({record:w.record,history:g==="summary"?Td(w.history,"summary"):w.history,promptHistory:w.promptHistory.length>0?w.promptHistory:void 0,...w.toolBlobs!==void 0?{toolBlobs:w.toolBlobs}:{},hydraVersion:de,machine:ht(),hydraHost:Hc(t)}),k=new Date().toISOString().replace(/[:.]/g,"-");f.header("Content-Disposition",`attachment; filename="${h}-${k}.hydra"`),f.code(200).send(y)}),s.get("/v1/sessions/:id/diff",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=await e.exportBundle(h);if(!p){f.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=Sc(p.history);y&&(k=k.filter(b=>y.has(b.path))),w&&(k=k.map(b=>({...b,hunks:Ic(b.hunks)}))),f.code(200).send(k)}),s.get("/v1/sessions/:id/tools/:hash",async(l,f)=>{let m=l.params,h=await e.resolveCanonicalId(m.id)??m.id,p=await e.loadToolBlob(h,m.hash);if(p===null){f.code(404).send({error:"tool blob not found"});return}f.header("Content-Type","text/plain; charset=utf-8"),f.code(200).send(p)}),s.get("/v1/sessions/:id/transcript",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=await e.exportBundle(h);if(!p){f.code(404).send({error:"session not found"});return}let g=In({record:p.record,history:p.history,promptHistory:p.promptHistory.length>0?p.promptHistory:void 0,hydraVersion:de,machine:ht(),hydraHost:Hc(t)}),w=l.query,y=I=>I==="1"||I==="true"||I==="yes",k=I=>{let v=w?.[I];if(v===void 0||v==="")return;let A=Number(v);return Number.isFinite(A)?A:"bad"},b={};for(let I of["from","to","last","since"]){let v=k(I);if(v==="bad"){f.code(400).send({error:`${I} must be a number`});return}v!==void 0&&(b[I==="since"?"sinceMs":I]=v)}f.header("Content-Type","text/markdown; charset=utf-8"),f.code(200).send(Cc(g,{includeTools:y(w?.tools),includeThoughts:y(w?.thoughts),...b}))}),s.post("/v1/sessions/:id/fork",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=l.body??{},g={};if(p.forkAt!==void 0){if(typeof p.forkAt!="string"||p.forkAt.length===0){f.code(400).send({error:"forkAt must be a non-empty string"});return}g.forkAt=p.forkAt}if(p.cwd!==void 0){if(typeof p.cwd!="string"||p.cwd.length===0){f.code(400).send({error:"cwd must be a non-empty string"});return}g.cwd=ae(p.cwd)}if(p.agentId!==void 0){if(typeof p.agentId!="string"||p.agentId.length===0){f.code(400).send({error:"agentId must be a non-empty string"});return}g.agentId=p.agentId}if(p.title!==void 0){if(typeof p.title!="string"){f.code(400).send({error:"title must be a string"});return}g.title=p.title}if(p.mode!==void 0){if(p.mode!=="verbatim"&&p.mode!=="synthesis"){f.code(400).send({error:'mode must be "verbatim" or "synthesis"'});return}g.mode=p.mode}if(p.model!==void 0){if(typeof p.model!="string"||p.model.length===0){f.code(400).send({error:"model must be a non-empty string"});return}g.model=p.model}try{let w=await e.forkSession(h,g);f.code(201).send(w)}catch(w){let y=w;if(y.code===E.SessionNotFound){f.code(404).send({error:y.message});return}if(y.code===E.InvalidParams||y.code===E.AgentNotInstalled){f.code(400).send({error:y.message});return}f.code(500).send({error:y.message})}}),s.post("/v1/sessions/import",async(l,f)=>{let m=l.body??{};if(m.bundle===void 0){f.code(400).send({error:"missing bundle"});return}let h;if(m.cwd!==void 0){if(typeof m.cwd!="string"||m.cwd.length===0){f.code(400).send({error:"cwd must be a non-empty string"});return}h=m.cwd}let p;try{p=Dd(m.bundle)}catch(g){f.code(400).send({error:"invalid bundle",details:g.message});return}try{let g=await e.importBundle(p,{replace:m.replace===!0,...h!==void 0?{cwd:h}:{}});f.code(201).send(g)}catch(g){let w=g;if(w.code===E.BundleAlreadyImported){f.code(409).send({error:"bundle already imported",existingSessionId:w.existingSessionId});return}f.code(500).send({error:w.message})}}),s.get("/v1/sessions/:id/compact/status",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h),g;if(p?g=p.summarizedThroughEntry:g=await e.getSummarizedThroughEntry(h),g===void 0&&!await e.hasRecord(h))return f.code(404).send({error:"session not found"}),f;let w=await e.getCompactionState(h),y=await e.getRollbackBreadcrumb(h),k=await e.getPendingAgentSwap(h),b=!1,I,v=p?.currentUsage,A=typeof v?.used=="number"&&typeof v?.size=="number"&&v.size>0?{used:v.used,size:v.size}:void 0,C=await e.loadHistory(h,{tools:"references",maxEntries:1/0}).catch(()=>[]);if(C.length>0&&t.compaction){let R=g??0,T=C.length,_=R<=C.length?R:0,U=C.slice(_),J=lc(U);I=Do(J);let M=p?.currentModel,W=C.at(-1).recordedAt;b=fc({summarizedThroughEntry:R,totalEntries:T,unsummarizedChars:J,compactionInFlight:e.getCompactionInFlight(),currentModel:M,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,...I!=null?{approxTokens:I}:{},...A!=null?{currentUsage:A}:{},...w!=null?{compactionState:w}:{},...y!=null?{rollbackBreadcrumb:y}:{},...k!=null?{pendingAgentSwap:k}:{}}}),s.post("/v1/sessions/:id/compact",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m;if(e.get(h)){e.scheduleCompaction(h),f.code(202).send({scheduled:!0});return}if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}e.scheduleCompaction(h),f.code(202).send({scheduled:!0})}),s.post("/v1/sessions/:id/compact/rollback",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m;if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}try{await e.performUncompact(h),f.code(202).send({rolledBack:!0})}catch(p){let g=p instanceof Error?p.message:String(p);f.code(409).send({error:g})}}),s.post("/v1/sessions/:id/workspace/clean",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=l.body??{};if(p.deep!==void 0&&typeof p.deep!="boolean"){f.code(400).send({error:"deep must be a boolean"});return}if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}if(e.get(h)===void 0){f.code(409).send({error:"session is not live. Cleaning rewrites the workspace under a running agent, so it is only available inside a live session (`/hydra workspace clean`). For a cold workspace use `hydra workspace remove` instead."});return}try{let g=await e.runWorkspaceAction(h,"clean",void 0,{deep:p.deep===!0});f.code(202).send({report:g})}catch(g){f.code(409).send({error:g instanceof Error?g.message:String(g)})}}),s.get("/v1/sessions/:id/history/page",async(l,f)=>{let m=l.params.id,h=l.query,p=Number(h?.beforeSeq);if(h?.beforeSeq===void 0||h.beforeSeq===""||!Number.isFinite(p)){f.code(400).send({error:"beforeSeq must be a number"});return}let g=h.turns===void 0||h.turns===""?10:Number(h.turns);if(!Number.isInteger(g)||g<1){f.code(400).send({error:"turns must be a positive integer"});return}let w=await e.resolveCanonicalId(m)??m,y=await e.pageHistory(w,{beforeSeq:p,turns:Math.min(g,100)});if(!y){f.code(404).send({error:"session not found"});return}f.code(200).send({entries:ts(y.entries),hasMore:y.hasMore})}),s.get("/v1/sessions/:id/history",async(l,f)=>{let m=l.params.id,h=l.query,p=h?.follow==="1"||h?.follow==="true",g=await e.resolveCanonicalId(m)??m,w=e.get(g),y,k,b=!1,I=1e4,v=[];if(w){p&&(k=w.onBroadcast(C=>{f.raw.writableEnded||(b?f.raw.write(JSON.stringify(C)+`
|
|
194
194
|
`):(v.push(C),v.length>I&&v.shift()))})),l.raw.on("close",()=>{k?.(),f.raw.writableEnded||f.raw.end()});try{y=await w.getHistorySnapshot()}catch(C){throw k?.(),C}}else{let C=await e.getHistory(g);if(C===void 0)return f.code(404).send({error:"session not found"}),f;y=C}f.raw.setHeader("Content-Type","application/x-ndjson"),f.raw.setHeader("Cache-Control","no-cache"),f.raw.statusCode=200;let A=new Set;for(let C of y??[]){f.raw.write(JSON.stringify(C)+`
|
|
195
195
|
`);let R=C;typeof R.recordedAt=="number"&&A.add(String(R.recordedAt))}for(;v.length>0;){let C=v.splice(0,v.length);for(let R of C){let T=R,_=typeof T.recordedAt=="number"?String(T.recordedAt):"";_&&A.has(_)||f.raw.write(JSON.stringify(R)+`
|
|
196
|
-
`)}}return b=!0,k||f.raw.end(),f});function i(l,f,m){let h=typeof l=="string"?l.trim():"";if(h.length===0)return null;let p;try{p=JSON.parse(h)}catch{return console.debug("events endpoint: skipping malformed JSONL line"),null}if(!p||typeof p!="object"||Array.isArray(p))return console.debug("events endpoint: skipping non-object JSONL line"),null;let g=p;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"||!f.has(k)?null:{recordedAt:g.recordedAt,entry:p}}function a(l,f,m){let p=f.params.update,g={sessionId:l,ts:new Date(f.recordedAt).toISOString(),kind:m,update:p};return p.messageId!==void 0&&p.messageId!==null&&(g.messageId=p.messageId),g}async function*d(l,f,m,h){for await(let p of f){let g=i(p,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,f,m,h){let p=
|
|
197
|
-
`),await u(A),A.exhausted){try{A.rl.close()}catch{}b.splice(I,1)}}}catch(I){for(let v of b)try{v.rl.close()}catch{}throw I}return f.raw.end(),f}),s.get("/v1/sessions/:id/events",async(l,f)=>{let m=l.params.id,h=l.query,p=await e.resolveCanonicalId(m)??m;if(!e.get(p)&&!await e.hasRecord(p))return f.code(404).send({error:"session not found"}),f;let w=h.kinds;if(!w||w.trim().length===0)return f.code(400).send({error:"kinds parameter is required"}),f;let y=w.split(",").map(C=>C.trim());if(y.length===0)return f.code(400).send({error:"kinds parameter is required"}),f;for(let C of y)if(!
|
|
198
|
-
`)}}catch(C){if(C.code==="ENOENT")return f.raw.end(),f;throw C}return f.raw.end(),f}),s.post("/v1/sessions/:id/prompt/:messageId/notify",async(l,f)=>{let m=l.params,h=m.id,p=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){f.code(400).send({error:"messageId, callbackUrl, and secret are all required"});return}let b;try{b=new URL(y)}catch{f.code(400).send({error:"callbackUrl must be a valid absolute URL"});return}if(b.protocol!=="https:"&&b.protocol!=="http:"){f.code(400).send({error:"callbackUrl must be http or https"});return}let I=e.get(p);if(!I){f.code(404).send({error:"session not found or not warm"});return}let v=I.registerTurnNotify(g,y,k);if(v.alreadyTerminal){f.code(200).send({status:"already_terminal",stopReason:v.stopReason});return}f.code(202).send({status:"registered"})}),s.get("/v1/sessions/:id/attention",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);return!p&&!await e.hasRecord(h)?(f.code(404).send({error:"session not found"}),f):p?{flags:p.listAttentionFlags()}:{flags:(await e.store.read(h))?.attentionFlags??[]}}),s.get("/v1/sessions/attention",async(l,f)=>{let m=l.query;if(!m.source||m.source.trim().length===0)return f.code(400).send({error:"source query parameter is required"}),f;let h=await e.list({includeNonInteractive:!0}),p=[];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&&p.push({...k,sessionId:g.sessionId})}return{flags:p}}),s.post("/v1/sessions/:id/attention/clear",async(l,f)=>{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)){f.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 C=Array.from(k.listAttentionFlags()).map(R=>`${R.source}::${R.reason}`);for(let R of C)k.clearAttentionFlag(R.split("::")[0],R.split("::").slice(1).join("::"))}f.code(204).send();return}if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}let b=e.store,I=await b.read(h);if(!I){f.code(404).send({error:"session not found"});return}let v=I.attentionFlags??[],A;if(w.length>0&&y.length>0){let C=`${w}::${y}`;A=v.filter(R=>`${R.source}::${R.reason}`!==C)}else A=[];if(A.length===v.length&&A.every((C,R)=>C.source===v[R].source&&C.reason===v[R].reason)){f.code(204).send();return}await b.write({...I,attentionFlags:A}),f.code(204).send()})}function Dc(s,e,t,n={}){s.get("/v1/agents",async()=>Ot(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 Te(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===E.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}G();function jc(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:x.home(),driftedKeys:n()}))}var Oh=/^[A-Za-z0-9._-]+$/;function Js(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=Fh(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){Fn(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){Fn(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){Fn(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){Fn(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){Fn(i,d)}})}function Fn(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 Fh(s){let e=s.name;if(typeof e!="string"||!Oh.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 Hc(s,e){Js(s,"extension",e)}function Lc(s,e){Js(s,"transformer",e)}function Uc(s,e){s.get("/v1/config",async()=>e())}import{z as ft}from"zod";G();import*as Qt from"fs/promises";import*as Bc from"path";import{randomBytes as yA,scrypt as Nh,timingSafeEqual as Dh}from"crypto";import{promisify as jh}from"util";var Hh=jh(Nh);function Wc(){return Bc.join(x.home(),"password-hash")}var Lh=128*1024*1024;async function qc(){try{return(await Qt.readFile(Wc(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function zc(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await Qt.readFile(Wc(),"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 Hh(s,i,a.length,{N:n,r,p:o,maxmem:Lh});return d.length!==a.length?!1:Dh(d,a)}var Uh=ft.object({password:ft.string().min(1),label:ft.string().min(1).max(256).optional(),ttlSec:ft.number().int().positive().optional()}),Bh=ft.object({id:ft.string().optional()}).optional(),Wh=ft.object({token:ft.string().min(32)});function Jc(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=qh(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=Uh.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await qc())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await zc(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=Bh.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=Wh.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 qh(s){return s.ip||"unknown"}import{z as pt}from"zod";G();Ne();var Lo=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,Vs=class s{data;constructor(e){this.data=e}static async load(){let e=await ie(x.peers());return new s(zh(e))}get(e){return this.data.entries[e]}async set(e){this.data.entries[e.name]=e,await Vc(this.data)}async delete(e){return e in this.data.entries?(delete this.data.entries[e],await Vc(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 zh(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 Vc(s){await pe(x.peers(),s,{mode:384})}var Jh=3600*24*365,Ge=class extends Error{status;constructor(e,t){super(e),this.name="PeerLoginError",this.status=t}};function Gc(s,e){return`${ke(s)?"http":"https"}://${s}:${e}`}async function Kc(s){let e=s.fetchImpl??fetch,t=`${s.host}:${s.port}`,n=Gc(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??Jh})})}catch(i){throw new Ge(`Could not reach ${t}: ${i.message}`,502)}if(r.status===401)throw new Ge(`Wrong password for ${t}.`,401);if(r.status===403)throw new Ge(`No password is configured on ${t}. Run \`hydra-acp auth password\` on that daemon first.`,502);if(r.status===429)throw new Ge(`Too many failed login attempts on ${t}; try again later.`,429);if(!r.ok)throw new Ge(`Login to ${t} failed: HTTP ${r.status}`,502);let o=await r.json();if(!o.session_token||!o.expires_at)throw new Ge(`Login to ${t} returned a malformed response.`,502);return{token:o.session_token,expiresAt:o.expires_at}}async function Qc(s){let e=s.fetchImpl??fetch,t=Gc(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{}}Dn();var ry=pt.object({name:pt.string().min(1).max(64).regex(Lo),host:pt.string().min(1),port:pt.number().int().positive().optional(),password:pt.string().min(1),label:pt.string().min(1).max(256).optional(),ttlSec:pt.number().int().positive().optional(),pinnedFingerprint:pt.string().min(1).optional()});function ou(s,e){s.post("/v1/remotes",async(t,n)=>{let r;try{r=ry.parse(t.body)}catch{return n.code(400).send({error:`Invalid request body (name must match ${Lo} and the rest is a normal login request)`})}let o=r.port??Tt;r.pinnedFingerprint&&Nn(r.host,o,r.pinnedFingerprint);let i;try{i=await Kc({host:r.host,port:o,password:r.password,label:r.label,ttlSec:r.ttlSec})}catch(c){if(c instanceof Ge)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.get("/v1/remotes/:name/agents",async(t,n)=>{let r=e.store.get(t.params.name);if(!r)return n.code(404).send({error:"Not found"});let i=`${ke(r.host)?"http":"https"}://${r.host}:${r.port}`,a={Authorization:`Bearer ${r.token}`};try{let[d,c]=await Promise.all([fetch(`${i}/v1/agents`,{headers:a}),fetch(`${i}/v1/config`,{headers:a}).catch(()=>null)]);if(!d.ok)return n.code(d.status).header("content-type","application/json").send(await d.text());let u=await d.json(),l={};if(c?.ok){let f=await c.json();l={defaultAgent:f.defaultAgent,sessionDefaults:f.sessionDefaults}}return n.code(200).send({...u,...l})}catch(d){return n.code(502).send({error:`Could not reach remote "${r.name}": ${d.message}`})}}),s.delete("/v1/remotes/:name",async(t,n)=>{let r=t.params.name,o=e.store.get(r);return o?(await Qc({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)||Bo(o.host,o.port),n.code(204).send()):n.code(404).send({error:"Not found"})})}function Ks(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:E.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())}}}Dn();import{WebSocket as oy}from"ws";var iy=1e4,Vo=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 iu(s,e,t=iy){let n={};try{let r=new URL(s);if(r.protocol==="wss:"){let o=Jo(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 oy(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 Vo(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 ay=new Set(["session/attach","session/detach","session/prompt","session/cancel","session/close","session/delete","hydra-acp/session/delete","session/set_model","session/set_mode","session/set_config_option","_session/steering","hydra-acp/prompt/cancel","hydra-acp/prompt/update","hydra-acp/prompt/amend","hydra-acp/session/tool_content","hydra-acp/session/force_cancel"]);function dy(s){return ay.has(s)}function du(s,e,t,n){let r=[],o=a=>{for(let d of r)d(a)},i=(a,d)=>{e.handleLocalMessage(a,d,{connection:t.connection,clientId:n}).then(c=>c?s.send(c):void 0).catch(()=>{})};return s.onMessage(a=>{if("method"in a&&dy(a.method)){let d=a.params,c=typeof d?.sessionId=="string"?d.sessionId:void 0;if(c){if(dt(c)){i(a,c);return}if(a.method==="session/attach"){let u="id"in a;e.resolveLocalMiss(c).then(l=>{if(l.ok){i(a,l.foreignId);return}if(l.ambiguous&&u){s.send(jn(a.id,E.SessionNotFound,`Session "${c}" exists on more than one remote (${l.ambiguous.join(", ")}). Address it as "<remote>:${c}".`));return}o(a)});return}}}o(a)}),{send:a=>s.send(a),onMessage:a=>r.push(a),onClose:a=>s.onClose(a),close:()=>s.close()}}var Qs=class{constructor(e,t=uy,n){this.store=e;this.dial=t;this.localMiss=n}store;dial;localMiss;attachments=new Map;async resolveLocalMiss(e){if(!this.localMiss)return{ok:!1};if(await this.localMiss.resolvesLocally(e))return{ok:!1};let t=this.localMiss.cache.findByLocalId(e);return t.length===0?{ok:!1}:t.length>1?{ok:!1,ambiguous:t.map(n=>n.name)}:{ok:!0,foreignId:qe(t[0])}}async handleLocalMessage(e,t,n){let r="id"in e,o=r?e.id:void 0,i=dt(t);if(!i)return r?jn(o,E.SessionNotFound,`not a federated session id: ${t}`):void 0;let a=au(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?jn(o,E.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 f;try{f=await this.dial(u)}catch(g){return r?jn(o,E.InternalError,`Could not reach remote "${i.name}": ${g.message}`):void 0}let m={peerConnection:f,localId:i.localId,target:n};this.wireAttachment(i.name,m);let h;try{h=await f.request("session/attach",d)}catch(g){return f.close().catch(()=>{}),r?Go(o,g):void 0}this.attachments.set(a,m);let p=h&&typeof h.sessionId=="string"?{...h,sessionId:t}:h;return r?{jsonrpc:"2.0",id:o,result:p}:void 0}let c=this.attachments.get(a);if(!c)return r?jn(o,E.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(f){l=f}return this.attachments.delete(a),c.peerConnection.close().catch(()=>{}),l?r?Go(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 Go(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=qe({name:e,localId:r}),a=()=>{this.attachments.delete(au(o.clientId,i))};n.onAnyNotification((d,c)=>{let u=d;!u||u.sessionId!==r||(c==="hydra-acp/session/closed"&&a(),o.connection.notify(c,{...u,sessionId:i}).catch(()=>{}))}),n.onRequest("hydra-acp/session/request_permission",async d=>{let c=d;if(!c||c.sessionId!==r)throw{code:E.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 au(s,e){return`${s} ${e}`}function jn(s,e,t){return{jsonrpc:"2.0",id:s,error:{code:e,message:t}}}function Go(s,e){let t=e,n=typeof t?.code=="number"?t.code:E.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 cy=1e4;async function uy(s){let t=`${ke(s.host)?"ws":"wss"}://${s.host}:${s.port}/acp`,n=await iu(t,["acp.v1",`hydra-acp-token.${s.token}`],cy);return new Be(Ks(n))}var ly=3e4,fy=5e3,Ys=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??ly),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=`${ke(n.host)?"http":"https"}://${n.host}:${n.port}/v1/auth/verify`,i=new AbortController,a=setTimeout(()=>i.abort(),fy);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)}}))}};Dn();import{z as cu}from"zod";var py=cu.object({sessionLabel:cu.string().min(1).max(256)});function uu(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=py.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 Ko}from"nanoid";import{randomBytes as mu}from"crypto";import*as hu from"os";import*as yu from"path";var gy=200;function my(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,gy)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function lu(s,e,t){let n=my(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 Hn=new Map;function fu(s,e){let t=Hn.get(s);t||(t=new Set,Hn.set(s,t)),t.add(e);let n=!1;return()=>{if(n)return;n=!0;let r=Hn.get(s);r&&(r.delete(e),r.size===0&&Hn.delete(s))}}function pu(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=Hn.get(r);if(o){if(o.has(s))return!0;for(let i of o)n.push(i)}}return!1}function N(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function vy(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 xe(s,e,t){let n=s.get(e);if(!n)throw N(E.SessionNotFound,t??`session ${e} not found`);return n}async function xt(s,e){let t=Kt(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=mu(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=Do({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 Py(c,s),ku(c.sessionId,s),c}function wu(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=rc({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_${Ko(12)}`,a=Ks(t),d={},c=e.foreignSessions?du(a,e.foreignSessions,d,i):a,u=new Be(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 f=(h,p)=>{if(l.attached.get(h)?.readonly)throw N(E.PermissionDenied,`${p} not permitted on a read-only attachment`)};if(u.onRequest("initialize",async h=>{let p=zi.parse(h??{});p.clientInfo?.name&&(l.clientInfo={name:p.clientInfo.name,...p.clientInfo.version!==void 0?{version:p.clientInfo.version}:{}});let g=p.clientInfo?.version;return g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g)),Ty()}),o&&e.extensionCommands){let h=e.extensionCommands;u.onRequest("hydra-acp/commands/register",async p=>{let g=p??{},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 I=b;if(typeof I.name!="string"||I.name.length===0||typeof I.description!="string"||I.inputSchema===null||typeof I.inputSchema!="object")return;let v={name:I.name,description:I.description,inputSchema:I.inputSchema};return I.outputSchema!==null&&typeof I.outputSchema=="object"&&(v.outputSchema=I.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 p=g=>{let w=g??{};if(typeof w.sessionId!="string"||w.sessionId.length===0)throw N(E.InvalidParams,"sessionId is required");return w.sessionId};if(u.onRequest("hydra-acp/session/extension_state/get",async g=>{let w=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(!e.manager)throw N(E.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=p(g);if(!e.manager)throw N(E.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=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(y.value===void 0)throw N(E.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw N(E.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(w,o.name,y.key,y.value)}catch(k){throw N(E.InvalidParams,k.message)}return{ok:!0}}),u.onRequest("hydra-acp/session/extension_state/delete",async g=>{let w=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(!e.manager)throw N(E.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 N(E.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 p=>{let g=p??{},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 p=>{let g=p??{},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 N(-32602,"emit_message requires sessionId");if(!y&&b!=="client_broadcast")throw N(-32602,"emit_message requires method");let I=xe(e.manager,w),v=typeof g.respondsTo=="string"?g.respondsTo:void 0;if(v)return I.dischargeClaim(v,k),{ok:!0};if(b==="chain")return{ok:!0,response:await I.emitToChain(o.name,y,k)};if(b==="queue"){if(y!=="session/prompt")throw N(-32602,'route "queue" only supports method "session/prompt"');return{ok:!0,response:await I.emitToQueue(o.name,k)}}if(b==="daemon")return{ok:!0,response:await I.emitToChain(o.name,y,k)};if(b==="client_broadcast"){if(!k||typeof k!="object")throw N(-32602,"client_broadcast requires an envelope object");return I.broadcastClientUpdate(k),{ok:!0}}throw N(-32602,`unsupported route: ${JSON.stringify(b)}`)}),u.onRequest("hydra-acp/session/request_permission",async p=>{let g=p??{},w=typeof g.sessionId=="string"?g.sessionId:void 0;if(!w)throw N(-32602,"hydra-acp/session/request_permission requires sessionId");return xe(e.manager,w).requestPermissionFromClients(g)}),u.onRequest("hydra-acp/transformer/attach",async p=>Cy(p,o.name,e)),u.onRequest("hydra-acp/child_session/spawn",async p=>{let g=p??{},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=rt(g._meta??void 0),I=b.title,v=b.model,A=b.workspace;if(!y&&k){let W=e.manager.get(k);W&&(y=W.cwd)}if(!y)throw N(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let C=await sn(y),R=w??C.agentId??e.defaultAgent,T=await e.registry?.getAgent(R),_=an(C.configDefaults,T??{id:R})?.value,H=v??_?.model,J=typeof g.interactive=="boolean"?g.interactive:!1,M=await e.manager.create({agentId:R,cwd:y,parentSessionId:k,interactive:J,transformChain:[],title:I,model:H,configDefaults:_,...A!==void 0?{workspace:A}:{}});return{childSessionId:M.sessionId,...M.workspace!==void 0||M.workspaceError!==void 0?{_meta:{[ae]:{...M.workspace!==void 0?{workspaceInfo:M.workspace}:{},...M.workspaceError!==void 0?{workspaceError:M.workspaceError}:{}}}}:{}}}),u.onRequest("hydra-acp/session/fork",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.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,I=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}:{},...I!==void 0?{model:I}:{}}),A=e.manager.get(v.sessionId);if(!A){let T=await e.manager.loadFromDisk(v.sessionId);if(!T)throw N(E.InternalError,`fork ${v.sessionId} vanished before it could be attached`);A=await xt(e,{...T,onInstallProgress:Xs(u)})}Yt(l,A,A.sessionId);let C=gt(u,A,l),{entries:R}=await A.attach(C,"full");l.attached.set(A.sessionId,{sessionId:A.sessionId,clientId:C.clientId,readonly:!1});for(let T of R){if(u.isClosed())break;await u.notify(T.method,Ue(Le(T.params,T.recordedAt),T.seq)).catch(()=>{})}return{...v,sessionId:A.sessionId}}),u.onRequest("session/fork",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.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 N(E.InternalError,`fork ${y.sessionId} vanished before it could be attached`);k=await xt(e,{...v,onInstallProgress:Xs(u)})}Yt(l,k,k.sessionId);let b=gt(u,k,l),{entries:I}=await k.attach(b,"full");l.attached.set(k.sessionId,{sessionId:k.sessionId,clientId:b.clientId,readonly:!1});for(let v of I){if(u.isClosed())break;await u.notify(v.method,Ue(Le(v.params,v.recordedAt),v.seq)).catch(()=>{})}return{sessionId:k.sessionId}});let h=async(p,g)=>{let w=p??{};if(typeof w.sessionId!="string")throw N(E.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 p=>(await h(p,"session/delete"),{})),u.onRequest("session/close",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.InvalidParams,"session/close requires sessionId");f(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 N(E.SessionNotFound,`session ${w} not found`)}),u.onRequest("hydra-acp/session/delete",async p=>{let{id:g,existed:w}=await h(p,"hydra-acp/session/delete");if(!w)throw N(E.SessionNotFound,`session ${g} not found`);return{deleted:!0,sessionId:g}}),u.onRequest("hydra-acp/child_session/await",async p=>{let g=p??{},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 N(-32602,"await_child requires childSessionId");let b=xe(e.manager,w,`child session ${w} not found`);return new Promise(I=>{let C=[],R=[],T=0,_=!1,H,J,M=!1,W=()=>{M||(M=!0,clearTimeout(q),H?.(),J?.(),I(_?{entries:C,truncated:!0}:{entries:C}))};H=b.onBroadcast(te=>{let de=vy(te);for(C.push(te),R.push(de),T+=de;C.length>0&&(C.length>1e3||T>1048576);)C.shift(),T-=R.shift()??0,_=!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 p=>{let g=p??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0;if(!w)throw N(-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 p=>Ry(p,o.name,e)),u.onRequest("hydra-acp/attention/clear",async p=>xy(p,o.name,e)),u.onRequest("hydra-acp/connection/keep_alive",async p=>{let g=p??{},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 p=h??{};if(typeof p.sessionId!="string"||typeof p.hash!="string")throw N(E.InvalidParams,"hydra-acp/session/tool_content requires sessionId and hash");let g=await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,w=await e.manager.loadToolBlob(g,p.hash);if(w===null)throw N(E.SessionNotFound,"tool content not found");return{content:w}}),u.onRequest("authenticate",async h=>by(h,e)),u.onRequest("logout",async h=>Sy(h,e)),u.onRequest("session/new",async h=>{let p=Ji.parse(h),g=rt(h?._meta),w=Array.isArray(g.transformers)&&g.transformers.every(Z=>typeof Z=="string")?g.transformers:e.manager.defaultTransformers??[],y=e.transformers?.resolveChain(w)??[],k=await sn(p.cwd),b=g.agentId??k.agentId??e.defaultAgent,I=await e.registry?.getAgent(b),v=an(k.configDefaults,I??{id:b})?.value,A,C,R=p.mcpServers;if(g.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){A=mu(32).toString("hex"),C=e.mcpTokenRegistry.reserve(A);let ve={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${A}`}]};R=[...p.mcpServers??[],ve]}let T,_,H=Kt(e);H!==void 0&&(R=[...R??[],...H.descriptors]);let J=Do({baselineMcpServers:p.mcpServers,stdinEnabled:g.mcpStdin===!0,deps:e}),M;try{M=await e.manager.create({cwd:p.cwd,agentId:b,mcpServers:R,title:g.title,agentArgs:g.agentArgs,model:g.model??v?.model,configDefaults:v,onInstallProgress:Xs(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(Z){throw C!==void 0&&C.abandon(Z instanceof Error?Z:void 0),_!==void 0&&_.abandon(Z instanceof Error?Z:void 0),H!==void 0&&H.abandon(Z instanceof Error?Z:void 0),Z}if(A!==void 0&&C!==void 0&&e.mcpTokenRegistry!==void 0){let Z=A,ve=e.mcpTokenRegistry;C.complete(M),M.onClose(()=>{ve.unbind(Z)})}if(T!==void 0&&_!==void 0&&e.mcpTokenRegistry!==void 0){let Z=T,ve=e.mcpTokenRegistry;_.complete(M),M.onClose(()=>{ve.unbind(Z)})}H!==void 0&&H.bindToSession(M),ku(M.sessionId,e);let W,q;try{Yt(l,M,M.sessionId),W=gt(u,M,l),{entries:q}=await M.attach(W,"full")}catch(Z){throw await M.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),Z}l.attached.set(M.sessionId,{sessionId:M.sessionId,clientId:W.clientId,readonly:!1}),setImmediate(()=>{(async()=>{for(let Z of q){if(u.isClosed())break;await u.notify(Z.method,Ue(Le(Z.params,Z.recordedAt),Z.seq)).catch(()=>{})}})()});let te=Zs(M),de=er(M);return{sessionId:M.sessionId,...te?{modes:te}:{},...de?{models:de}:{},configOptions:M.buildConfigOptions(),_meta:tr(e.manager,M,{clientId:W.clientId})}}),u.onRequest("session/attach",async h=>{let p=Gi.parse(h),g=p.clientInfo?.version;g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g));let w=rt(p._meta),y=w.resume,k=w.readonly===!0,b=w.env;s.log.info(`session/attach sessionId=${p.sessionId} hasResumeHints=${!!y} readonly=${k}`);let I=y?p.sessionId:await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,v=e.manager.get(I);if(!v&&k){let M=await e.manager.loadFromDisk(I);if(!M)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);let W=await e.manager.loadHistory(I,{...w.historyLimit!==void 0?{maxEntries:w.historyLimit}:{}}),q=p.clientId??`cli_${Ko(8)}`;l.attached.set(M.hydraSessionId,{sessionId:M.hydraSessionId,clientId:q,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${M.hydraSessionId} clientId=${q} attachedCount=${l.attached.size} replayed=${W.length}`);for(let te of W)await u.notify(te.method,Ue(Le(te.params,te.recordedAt),te.seq)).catch(()=>{});return{sessionId:M.hydraSessionId,clientId:q,connectedClients:[q],historyPolicy:"full",replayed:W.length,_meta:Ey(M)}}let A=!v;if(!v){let M=await e.manager.loadFromDisk(I),W=await Iy(I,y,M?.upstreamSessionId,e.manager);W.kind==="ignore"&&s.log.warn(W.logMessage);let q=M;if(y&&W.kind==="honor"&&(q={...M,hydraSessionId:p.sessionId,upstreamSessionId:y.upstreamSessionId,agentId:y.agentId,cwd:M?.workspace?.path??y.cwd,...y.title!==void 0?{title:y.title}:{},...y.agentArgs!==void 0?{agentArgs:y.agentArgs}:{}}),!q)throw N(E.SessionNotFound,`session ${p.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(q.agentId,q.upstreamSessionId))throw N(E.SessionNotFound,`session ${p.sessionId} was deleted`);let te=q.originatingClient?q:{...q,originatingClient:l.clientInfo},de=b!==void 0?{...te,forwardedEnv:b}:te;v=await xt(e,{...de,onInstallProgress:Xs(u)})}Yt(l,v,v.sessionId);let C=gt(u,v,l,p.clientInfo,p.clientId),R=w.replayMode==="drip",{entries:T,appliedPolicy:_}=await v.attach(C,p.historyPolicy,{afterMessageId:p.afterMessageId,afterSeq:p.afterSeq,raw:R,...w.historyLimit!==void 0?{historyLimit:w.historyLimit}:{},...w.toolContent!==void 0?{toolContent:w.toolContent}:{}});if(l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:C.clientId,readonly:k}),b!==void 0&&await e.manager.setForwardedEnv(v.sessionId,b).catch(()=>{}),s.log.info(`session/attach OK sessionId=${v.sessionId} clientId=${C.clientId} attachedCount=${l.attached.size} requestedPolicy=${p.historyPolicy} appliedPolicy=${_} replayed=${T.length} readonly=${k}${R?" replayMode=drip":""}`),R){let M=w.dripSpeed&&w.dripSpeed>0?w.dripSpeed:1,W=750;(async()=>{let q=null;for(let te of T){let de=typeof te.recordedAt=="number"?te.recordedAt:null;if(q!==null&&de!==null){let Z=Math.min(W,Math.max(0,(de-q)/M));Z>0&&await new Promise(ve=>setTimeout(ve,Z))}de!==null&&(q=de);try{await u.notify(te.method,Ue(Le(te.params,de??void 0),te.seq))}catch{return}}})()}else for(let M=0;M<T.length&&!u.isClosed();M++){let W=T[M],q=u.notify(W.method,Ue(Le(W.params,W.recordedAt),W.seq)).catch(()=>{});(M+1)%200===0&&await q}v.replayPendingPermissions(C);let H=Zs(v),J=er(v);return{sessionId:v.sessionId,clientId:C.clientId,connectedClients:v.connectedClients(C.clientId),historyPolicy:_,replayed:T.length,...H?{modes:H}:{},...J?{models:J}:{},configOptions:v.buildConfigOptions(),_meta:tr(e.manager,v,{resurrected:A})}}),u.onRequest("session/detach",async h=>{let p=Ki.parse(h),g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"client not attached to that session");let w=e.manager.get(p.sessionId);return w?.detach(g.clientId),l.attached.delete(p.sessionId),w&&e.manager.reapIfOrphanedNonInteractive(p.sessionId),{sessionId:p.sessionId,_meta:{[ae]:{detachStatus:"detached"}}}}),u.onRequest("session/list",async h=>{let p=Qi.parse(h??{});return{sessions:(await e.manager.list({cwd:p.cwd})).filter(k=>k.originatingClient?.name!==ws).map(Yi)}}),u.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw N(E.InternalError,"agent registry unavailable");return Ot(e.registry)}),u.onRequest("hydra-acp/agents/auth_methods",async h=>{let p=h??{};if(typeof p.agentId!="string"||p.agentId.length===0)throw N(E.InvalidParams,"hydra-acp/agents/auth_methods requires a non-empty agentId string");return{authMethods:(await e.manager.bootstrapAgentForAuth(p.agentId)).authMethods??[]}}),u.onRequest("session/prompt",async h=>{let p=Xi.parse(h);f(p.sessionId,"session/prompt");let g=await lu(p,e.manager,b=>{s.log.warn(`session/prompt: dropping unknown sentBy.sessionId=${b} sessionId=${p.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 ${p.sessionId}`),N(E.InvalidRequest,`message chain too deep (${g.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(g.awaiting===!0&&pu(g.fromSession,p.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${g.fromSession} -> ${p.sessionId}`),N(E.InvalidRequest,`would deadlock: ${p.sessionId} is already blocked waiting on ${g.fromSession}. Send with --no-wait, or let the other turn finish first.`)}let w=l.attached.get(p.sessionId);if(!w)throw s.log.warn(`session/prompt rejected: not attached sessionId=${p.sessionId} attachedKeys=[${[...l.attached.keys()].join(",")}]`),N(E.SessionNotFound,"not attached to session");let y=e.manager.get(p.sessionId);if(!y){let b=await e.manager.loadFromDisk(p.sessionId);if(!b)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${p.sessionId}`),y=await xt(e,b);let I=gt(u,y,l,void 0,w.clientId);await y.attach(I,"none")}let k=g?.awaiting===!0&&g.fromSession!==void 0?fu(g.fromSession,p.sessionId):void 0;try{return await y.prompt(w.clientId,p,g)}finally{k?.()}});let m=h=>{let p;try{p=Kn.parse(h)}catch(y){s.log.warn(`session/cancel: invalid params: ${y.message}`);return}let g=l.attached.get(p.sessionId);if(!g)return;if(g.readonly){s.log.warn(`session/cancel dropped (readonly attachment) sessionId=${p.sessionId}`);return}let w=e.manager.get(p.sessionId);w&&w.cancel(g.clientId).catch(y=>{s.log.warn(`session/cancel for ${p.sessionId}: ${y.message}`)})};u.onNotification("session/cancel",m),u.onRequest("session/cancel",async h=>{let p=Kn.parse(h);return f(p.sessionId,"session/cancel"),m(h),null}),u.onRequest("hydra-acp/prompt/cancel",async h=>{let p=ea.parse(h);return f(p.sessionId,"hydra-acp/prompt/cancel"),xe(e.manager,p.sessionId).cancelQueuedPrompt(p.messageId)}),u.onRequest("hydra-acp/session/force_cancel",async h=>{let p=Kn.parse(h);return f(p.sessionId,"hydra-acp/session/force_cancel"),xe(e.manager,p.sessionId).forceCancel()}),u.onRequest("hydra-acp/prompt/update",async h=>{let p=ta.parse(h);return f(p.sessionId,"hydra-acp/prompt/update"),xe(e.manager,p.sessionId).updateQueuedPrompt(p.messageId,p.prompt)}),u.onRequest("hydra-acp/prompt/amend",async h=>{let p=na.parse(h);f(p.sessionId,"hydra-acp/prompt/amend");let g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"not attached to session");return xe(e.manager,p.sessionId).amendPrompt(g.clientId,p)}),u.onRequest("_session/steering",async h=>{let p=sa.parse(h);f(p.sessionId,"_session/steering");let g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"not attached to session");let w=e.manager.get(p.sessionId);if(!w){let y=await e.manager.loadFromDisk(p.sessionId);if(!y)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);w=await xt(e,y);let k=gt(u,w,l,void 0,g.clientId);await w.attach(k,"none")}return w.steer(g.clientId,p)}),u.onRequest("session/resume",async h=>{let p=h??{},g=typeof p.sessionId=="string"?p.sessionId:void 0;if(!g)throw N(E.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 N(E.SessionNotFound,`session ${g} not found in memory or on disk`);y=await xt(e,v)}Yt(l,y,y.sessionId);let k=gt(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),I=er(y);return{sessionId:y.sessionId,...b?{modes:b}:{},...I?{models:I}:{},configOptions:y.buildConfigOptions(),_meta:tr(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/load",async h=>{let p=h??{},g=typeof p.sessionId=="string"?p.sessionId:void 0;if(!g)throw N(E.InvalidParams,"session/load requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let A=await e.manager.loadFromDisk(w);if(!A)throw N(E.SessionNotFound,`session ${g} not found in memory or on disk`);y=await xt(e,A)}Yt(l,y,y.sessionId);let k=gt(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 A of b){if(u.isClosed())break;await u.notify(A.method,Ue(Le(A.params,A.recordedAt),A.seq)).catch(()=>{})}y.replayPendingPermissions(k);let I=Zs(y),v=er(y);return{sessionId:y.sessionId,...I?{modes:I}:{},...v?{models:v}:{},configOptions:y.buildConfigOptions(),_meta:tr(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/set_model",async h=>{let p=h?.sessionId;typeof p=="string"&&f(p,"session/set_model");let g=Ay(h,e.manager);if(g.kind==="error")throw s.log.warn(g.logMessage),N(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 p=h,g=p?.sessionId;if(typeof g=="string"&&f(g,"session/set_mode"),!p||typeof p.sessionId!="string")throw N(E.InvalidParams,"session/set_mode requires string sessionId");if(typeof p.modeId!="string")throw N(E.InvalidParams,"session/set_mode requires string modeId");let w=xe(e.manager,p.sessionId),y=await w.forwardRequest("session/set_mode",h);return w.applyModeChange(p.modeId),y}),u.onRequest("session/set_config_option",async h=>{let p=h,g=b=>N(E.InvalidParams,b),w=p?.sessionId;if(typeof w=="string"&&f(w,"session/set_config_option"),!p||typeof p.sessionId!="string")throw g("session/set_config_option requires string sessionId");if(typeof p.configId!="string")throw g("session/set_config_option requires string configId");if(typeof p.value!="string")throw g("session/set_config_option requires string value");let y=xe(e.manager,p.sessionId),k=y.buildConfigOptions().find(b=>b.id===p.configId);if(!k)throw g(`unknown configId ${JSON.stringify(p.configId)} for this session`);if(!k.options.some(b=>b.value===p.value))throw g(`value ${JSON.stringify(p.value)} is not valid for configId ${JSON.stringify(p.configId)}`);switch(p.configId){case"model":{if(p.value!==y.currentModel){let b=await y.forwardModelChange(p.value);y.applyAgentConfigOptionResponse(b,"model")}y.applyModelChange(p.value);break}case"mode":{p.value!==y.currentMode&&await y.forwardRequest("session/set_mode",{sessionId:p.sessionId,modeId:p.value}),y.applyModeChange(p.value);break}case"agent":{p.value!==y.agentId&&await y.setAgent(p.value);break}default:{let b=await y.forwardRequest("session/set_config_option",{sessionId:p.sessionId,configId:p.configId,value:p.value});y.applyAgentConfigOptionResponse(b,p.configId)&&y.broadcastConfigOptions()}}return{configOptions:y.buildConfigOptions()}}),u.setDefaultHandler(async(h,p)=>{let g=new Set(["hydra-acp/attention/set","hydra-acp/attention/clear"]),w=p.startsWith("session/"),y=p.startsWith("hydra-acp/");if(!w&&!y||h===null||typeof h!="object"||g.has(p))throw N(E.MethodNotFound,`Method not found: ${p}`);let k=h.sessionId;if(typeof k!="string")throw N(E.MethodNotFound,`Method not found: ${p}`);return f(k,p),xe(e.manager,k).forwardRequest(p,h)})})}async function by(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw N(E.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 N(E.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 N(E.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be a string[]; got ${k===null?"null":typeof k}`);for(let I of k)if(typeof I!="string")throw N(E.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be string[]; got non-string entry ${JSON.stringify(I)}`);return k},h=await e.manager.planSpawnForAgent(a.agentId),p,g;if(l?.args!==void 0){let k=typeof l.command=="string"?l.command:void 0;p=k!==void 0&&yu.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):[];p=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=hu.homedir();return console.error(`[authenticate] terminal-auth requested agentId=${a.agentId} methodId=${n}`),{kind:"terminal",command:p,args:g,env:w,cwd:y}}try{return await a.connection.request("authenticate",{methodId:n})}catch(m){throw lt(m,a)}}async function Sy(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 Xs(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(ra,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 er(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 Iy(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 Ay(s,e){if(!s||typeof s!="object")return{kind:"error",code:E.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:E.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:E.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:E.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=Ht(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:E.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 Cy(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw N(E.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw N(E.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw N(E.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return xe(t.manager,r).addTransformer(o),{ok:!0}}async function Ry(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 N(E.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw N(E.InvalidParams,"hydra-acp/attention/set requires string reason");return xe(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function xy(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 N(E.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw N(E.InvalidParams,"hydra-acp/attention/clear requires string reason");return xe(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function Ey(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:In(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]:Gn(e,t)}}function tr(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 dn(e.agentMeta,Gn(n,r))}function Ty(){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:{...dn(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 Py(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 ku(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 gt(s,e,t,n,r){return{clientId:r??`cli_${Ko(8)}`,connection:s,clientInfo:n}}function Yt(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var nr=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 My}from"crypto";import{McpServer as _y}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as $y}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as me}from"zod";function Qo(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 Ae(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var vu="Bearer ";function Xt(s){let e=s.headers.authorization;if(typeof e!="string"||!e.startsWith(vu))return;let t=e.slice(vu.length).trim();return t.length>0?t:void 0}function Oy(s){let e=new _y({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:me.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return Ae(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:me.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return Ae(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:me.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:me.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:me.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 Ae(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:me.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:me.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 Ae({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:me.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:me.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:me.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:me.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:me.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:me.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:me.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:me.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:me.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 Ae(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 Ae(t)}),e}var Fy=1e4;function bu(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=Oy(a),u=new $y({sessionIdGenerator:()=>My()});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=Xt(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 f,m=new Promise(p=>{f=setTimeout(()=>p(void 0),Fy)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(f!==void 0&&clearTimeout(f),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 Ny}from"crypto";import{McpServer as Dy}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as jy}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as Ke}from"zod";function Hy(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var Su=2e3,Iu=2e4;function Ly(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return Ut([s]);let n=[],r=un(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=es(t);return i!==void 0&&n.push(i),n.join(`
|
|
199
|
-
`)}function Uy(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 By(s){let e=new Dy({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:Ke.string().min(1).describe("Case-insensitive substring to search for."),limit:Ke.number().int().min(1).max(50).optional().describe("Maximum number of matches to return (default 10, max 50)."),include_tool_calls:Ke.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 Ae({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=Qo(u);if(!l)continue;let{kind:f,update:m}=l;if((f==="tool_call"||f==="tool_call_update")&&!r)continue;let h=Ly(u,f,m),p=h.toLowerCase().indexOf(a);if(p<0)continue;let g=Hy(f),w=Uy(h,p),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 Ae({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:Ke.number().int().min(0).describe("Zero-based index of the first entry to include (inclusive)."),to_entry:Ke.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 Ae({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 Ae({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=Ut(u,{toolOutput:{maxPerCall:Su,maxTotal:Iu}});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:Ke.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:Ke.string().optional().describe("ACP tool kind: execute (shell), read, edit, think, other. Agent-independent, unlike tool_name."),file_path:Ke.string().optional(),limit:Ke.number().int().min(1).max(100).optional(),include_output:Ke.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 Ae({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,f=Math.max(o*4,200);for await(let{entryId:y,entry:k}of a.iterRecallNewestFirst()){let b=Qo(k);if(!b)continue;let{kind:I,update:v}=b;if(I!=="tool_call"&&I!=="tool_call_update")continue;let A=typeof v.toolCallId=="string"&&v.toolCallId.length>0?v.toolCallId:`__noid_${y}`,C=l.get(A);if(C||(C={entryId:y,toolName:"(unnamed)",nameAuthoritative:!1,rawInput:{},locations:[],status:"in_progress"},l.set(A,C)),y<C.entryId&&(C.entryId=y),!C.nameAuthoritative){let T=un(v);T!==void 0?(C.toolName=T,C.nameAuthoritative=!0):typeof v.name=="string"&&v.name.length>0?(C.toolName=v.name,C.nameAuthoritative=!0):I==="tool_call"&&typeof v.title=="string"&&v.title.length>0&&(C.toolName=v.title,C.nameAuthoritative=!0)}if(C.kind===void 0&&typeof v.kind=="string"&&v.kind.length>0&&(C.kind=v.kind),C.output===void 0){let T=es(v);T!==void 0&&(C.output=T)}let R=v.rawInput;if(R&&typeof R=="object"&&!Array.isArray(R)&&Object.keys(R).length>0)for(let[T,_]of Object.entries(R))C.rawInput[T]===void 0&&(C.rawInput[T]=_);if(Array.isArray(v.locations))for(let T of v.locations){let _=T?.path;typeof _=="string"&&_.length>0&&!C.locations.includes(_)&&C.locations.push(_)}if(typeof v.status=="string"&&C.status==="in_progress"&&(C.status=v.status),k.recordedAt!==void 0&&C.timestamp===void 0&&(C.timestamp=String(k.recordedAt)),l.size>=f)break}let m=[...l.keys()].sort((y,k)=>l.get(y).entryId-l.get(k).entryId),h=[],p=Iu,g=!1;for(let y of m){let k=l.get(y);if(k.toolName=Dr({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(),A=["file_path","filePath","path"],C=!1;for(let R of A){let T=k.rawInput[R];if(typeof T=="string"&&T.toLowerCase().includes(v)){C=!0;break}}if(!C){for(let R of k.locations)if(R.toLowerCase().includes(v)){C=!0;break}}if(!C)continue}let b={};for(let[v,A]of Object.entries(k.rawInput))typeof A=="string"?b[v]=A.length>500?A.slice(0,497)+"\u2026":A:(typeof A=="number"||typeof A=="boolean")&&(b[v]=A);k.locations.length>0&&b.locations===void 0&&(b.locations=k.locations);let I={entryId:k.entryId,tool:k.toolName,args:b,status:k.status,timestamp:k.timestamp};if(k.kind!==void 0&&(I.kind=k.kind),i&&k.output!==void 0){let v=k.output,A=Math.min(Su,p);if(A<=0)g=!0;else{let C=v.length<=A?v:v.slice(0,A-1)+"\u2026";I.output=C,I.outputBytes=v.length,I.outputTruncated=C.length<v.length,p-=C.length}}if(h.push(I),h.length>=o)break}let w=h.length>=o;return Ae({calls:h,truncated:w,...g?{outputBudgetExhausted:g}:{}})}),e}var Wy=1e4;function Au(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=By(a),u=new jy({sessionIdGenerator:()=>Ny()});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=Xt(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 f,m=new Promise(p=>{f=setTimeout(()=>p(void 0),Wy)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(f!==void 0&&clearTimeout(f),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 sr=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 Yy}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{randomUUID as Xy}from"crypto";import{Server as qy}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as zy,ListToolsRequestSchema as Jy}from"@modelcontextprotocol/sdk/types.js";function Cu(s,e,t,n){let r=typeof t=="function"?async()=>t():async()=>t,o=new qy({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(Jy,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(zy,async(a,d)=>{let c=a.params.name,u=d._meta?.progressToken??d.requestId,l=Gy(u,d.sendNotification);try{let f=await r(),m=await Ky(e.connection,s,c,a.params.arguments??{},f);return Qy(m,c)}catch(f){return Yo(f instanceof Error?f.message:String(f))}finally{l()}}),o}var Vy=15e3;function Gy(s,e,t=Vy){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 Ky(s,e,t,n,r){return await s.request("hydra-acp/mcp_tools/invoke",{server:e,tool:t,args:n,sessionId:r})}function Qy(s,e){if(s===null||typeof s!="object")return Yo(`extension ${e} returned non-object`);let t=s;return Array.isArray(t.content)?t:Yo(`extension ${e} omitted content array`)}function Yo(s){return{content:[{type:"text",text:s}],isError:!0}}var Zy=1e4;function Ru(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 f=l.get(u);f!==void 0&&(l.delete(u),r(f))}}async function i(u,l){for(let[f,m]of n){if(e.lookup(f)?.session?.sessionId!==u)continue;let p=m.get(l);if(p!==void 0)try{await p.server.sendToolListChanged()}catch{}}}t.onChange(u=>{o(u)});async function a(u,l){let f=n.get(u);f===void 0&&(f=new Map,n.set(u,f),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 m=f.get(l);if(m!==void 0)return m.transport;let h=t.lookup(l);if(h===void 0)return;let y=Cu(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 I,v=new Promise(C=>{I=setTimeout(()=>C(void 0),Zy)}),A=await Promise.race([b.sessionReady.catch(()=>{}),v]);if(I!==void 0&&clearTimeout(I),A===void 0)throw new Error("session not ready");return A.sessionId},{peekSessionId:()=>e.lookup(u)?.session?.sessionId,fetchSessionTools:async b=>{let I=await h.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 A=[];for(let C of v){if(!C||typeof C!="object")continue;let R=C;if(typeof R.name!="string"||R.name.length===0||typeof R.description!="string"||R.inputSchema===null||typeof R.inputSchema!="object")continue;let T={name:R.name,description:R.description,inputSchema:R.inputSchema};R.outputSchema!==null&&typeof R.outputSchema=="object"&&(T.outputSchema=R.outputSchema),A.push(T)}return A}}),k=new Yy({sessionIdGenerator:()=>Xy()});return await y.connect(k),f.set(l,{server:y,transport:k}),k}async function d(u,l){let f=Xt(u);if(f===void 0){l.code(401).send({error:"missing bearer token"});return}if(e.lookup(f)===void 0){l.code(404).send({error:"unknown mcp token"});return}let h=u.params.name,p=await a(f,h);if(p===void 0){l.code(404).send({error:`unknown mcp server: ${h}`});return}l.hijack(),await p.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 _u(s,e){iw(s),hr(s.daemon.scrubEnv);let t=s,n=s.daemon.tls?await Qe.readFile(ce(s.daemon.tls.key)):void 0,r=s.daemon.tls?await Qe.readFile(ce(s.daemon.tls.cert)):void 0;await Qe.mkdir(x.home(),{recursive:!0});let{stream:o,fileStream:i}=await rw(s.daemon.logLevel),a=ew({logger:{level:s.daemon.logLevel,stream:o},bodyLimit:256*1024*1024});await a.register(tw,{options:{handleProtocols:wi}}),Sr(F=>{a.log.info(F)}),Cr(F=>{a.log.info(F)});let d=await $s.load(),c=await Vs.load();zo(),Wo(c);let u=new Ys(c);u.start();let l=new Ws(c);l.start();let f=new js,m=new Ds,h=new Os(e),p=new Ns([h,new Fs(d),m]),g=sc({validator:p});a.addHook("onRequest",async(F,be)=>{F.routeOptions.config?.skipAuth||F.url==="/acp"||F.url?.startsWith("/acp?")||(await g(F,be),!be.sent&&F.authIdentity?.startsWith("script:")&&!oc(F.method,F.routeOptions.url)&&be.code(403).send({error:"script tokens may only access read-only session data"}))});let w=setInterval(()=>{d.sweepExpired()},300*1e3);w.unref();let y=setInterval(()=>{f.sweepExpired()},300*1e3);y.unref();let k=new Jn(s,{onFetched:()=>{Wd(k,A)},onStaleFallback:(F,be)=>{let en=Math.round(be/36e5),tn=en>=48?`${Math.round(en/24)}d`:`${en}h`;a.log.warn(`registry fetch failed (${F.message}); serving stale cache last synced ${tn} ago; agent versions may be outdated ('hydra registry refresh' to retry)`)}});Po(F=>a.log.info(F));let b={info:F=>a.log.info(F),warn:F=>a.log.warn(F)},I=F=>it.spawn({...F,stderrTailBytes:s.daemon.agentStderrTailBytes,logger:b});Ai(s.compressToolContent);let v=new Ms,A=new Is(k,I,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:b,npmRegistry:s.npmRegistry,extensionCommands:v,defaultCwd:s.defaultCwd,disableWorkspaceSnapshots:s.disableWorkspaceSnapshots}),C=new Qs(c,void 0,{resolvesLocally:async F=>await A.resolveCanonicalId(F)!==void 0,cache:l}),R=new Ts(pi(s),void 0,{tokenRegistry:m}),T=new Ps(gi(s),void 0,{tokenRegistry:m}),_=[];jc(a,le,Jd(s),()=>_);let H=new nr,J=new sr,M,W=()=>{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},q={agentId:s.defaultAgent,cwd:s.defaultCwd,publicHost:s.daemon.publicHost,host:s.daemon.host,port:s.daemon.port,compaction:s.compaction};Nc(a,A,q,{extensionMcp:J,mcpTokenRegistry:H,getDaemonOrigin:W},c,l),Mc(a,{store:c,localMiss:{resolvesLocally:async F=>await A.resolveCanonicalId(F)!==void 0,cache:l}}),Dc(a,k,A,{npmRegistry:s.npmRegistry}),Hc(a,R),Lc(a,T),Uc(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]})),Jc(a,{store:d,rateLimiter:f,staticTokenValidator:h}),ou(a,{store:c,health:u}),uu(a,{processRegistry:m}),bu(a,H),Au(a,H);let te=Ru(a,H,J);wu(a,{validator:p,manager:A,defaultAgent:s.defaultAgent,processRegistry:m,onExtensionVersion:(F,be)=>R.reportVersion(F,be),onTransformerVersion:(F,be)=>T.reportVersion(F,be),transformers:T,extensionCommands:v,mcpTokenRegistry:H,extensionMcp:J,extensionMcpControls:te,getDaemonOrigin:W,registry:k,foreignSessions:C});let de=!!s.daemon.tls;await a.listen({host:de?"127.0.0.1":s.daemon.host,port:de?0:s.daemon.port});let Z=a.server.address(),ve=Z&&typeof Z=="object"?Z.port:s.daemon.port,Ln,$u=s.daemon.host,Xo=ve;if(de&&n&&r){Ln=ow({listenHost:s.daemon.host,listenPort:s.daemon.port,upstreamHost:"127.0.0.1",upstreamPort:ve,tlsOptions:{key:n,cert:r},logger:a.log});let F=Ln.address();F&&typeof F=="object"&&(Xo=F.port)}await Qe.mkdir(x.home(),{recursive:!0}),await Bd({pid:process.pid,host:$u,port:Xo,loopbackPort:ve,startedAt:new Date().toISOString()});let Zo={daemonUrl:`http://127.0.0.1:${ve}`,daemonHost:"127.0.0.1",daemonPort:ve,serviceToken:e,daemonWsUrl:`ws://127.0.0.1:${ve}/acp`,hydraHome:x.home()};R.setContext(Zo),T.setContext(Zo),await R.start(),await T.start();try{await A.reconcilePermissionFlags()}catch(F){a.log.warn(`permission flag reconcile failed: ${F.message}`)}try{await A.seedSessionIndex()}catch(F){a.log.warn(`session index seed failed: ${F.message}`)}A.resurrectPendingQueues().catch(F=>{a.log.warn(`queue replay scan failed: ${F.message}`)}),A.resumePendingCompactions().catch(F=>{a.log.warn(`compaction resume scan failed: ${F.message}`)}),A.resumePendingAgentSwaps().catch(F=>{a.log.warn(`agent-swap resume scan failed: ${F.message}`)});let ei=s.daemon.agentSyncIntervalMinutes*60*1e3,ti=ei>0?qd({registry:k,manager:A,intervalMs:ei,logger:b}):void 0,ni=s.daemon.sessionGcIntervalMinutes*60*1e3,Ou=s.daemon.sessionGcMaxAgeDays*24*60*60*1e3,si=ni>0?zd({manager:A,intervalMs:ni,maxAgeMs:Ou,logger:b}):void 0,Fu=Qd({bootConfig:s,apply:F=>{t=F,k.setConfig(F),A.setLiveConfig({sessionDefaults:F.sessionDefaults}),q.agentId=F.defaultAgent,q.cwd=F.defaultCwd,hr(F.daemon.scrubEnv)},onDrift:F=>{_=F},logger:b});return{app:a,manager:A,registry:k,extensions:R,transformers:T,mcpTokenRegistry:H,extensionMcp:J,processRegistry:m,shutdown:async()=>{u.stop(),l.stop(),Fu(),si&&si(),ti&&ti(),clearInterval(w),clearInterval(y);let F=async(be,en)=>{try{await en()}catch(tn){a.log.warn(`shutdown step ${be} failed: ${tn instanceof Error?tn.message:String(tn)}`)}};await F("sessionTokenStore.flush",()=>d.flush()),await F("extensions.stop",()=>R.stop()),await F("transformers.stop",()=>T.stop()),await F("manager.closeAll",()=>A.closeAll()),await F("manager.flushSynopsis",()=>A.flushSynopsis(3e4)),await F("manager.shutdownSynopsis",()=>A.shutdownSynopsis()),await F("manager.flushMetaWrites",()=>A.flushMetaWrites()),await F("manager.flushHistoryWrites",()=>A.flushHistoryWrites()),Sr(null),Cr(null),Po(null),Ln&&await F("tlsTerminator.close",()=>new Promise(be=>Ln.close(()=>be()))),await F("app.close",()=>a.close());try{Tu.unlinkSync(x.pidFile())}catch{}await F("fileStream.flushSync",()=>i.flushSync())}}}var Eu=20;async function sw(s,e){let t=Zt.dirname(s),n=Zt.basename(s,".log"),r=new RegExp(`^${n}\\.(\\d+)\\.log$`),o;try{o=await Qe.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=>Qe.unlink(Zt.join(t,d.name))))}async function rw(s){await sw(x.logFile(),Eu);let e=await nw({file:x.logFile(),size:"10m",mkdir:!0,symlink:Rs,limit:{count:Eu,removeOtherLogFiles:!0}}),t=xu.destination(2);return{stream:xu.multistream([{stream:e,level:s},{stream:t,level:s}]),fileStream:e}}function ow(s){let e=Mu.createServer(s.tlsOptions,t=>{let n=Pu.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 iw(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 aw(){process.title="hydra-acp-daemon";let{installGlobalTlsTrust:s}=await Promise.resolve().then(()=>(Dn(),ru));s();let e=await rn(),t=await ii(),n=await _u(e,t);process.stdout.write(`hydra-acp daemon listening on ${e.daemon.host}:${e.daemon.port}
|
|
196
|
+
`)}}return b=!0,k||f.raw.end(),f});function i(l,f,m){let h=typeof l=="string"?l.trim():"";if(h.length===0)return null;let p;try{p=JSON.parse(h)}catch{return console.debug("events endpoint: skipping malformed JSONL line"),null}if(!p||typeof p!="object"||Array.isArray(p))return console.debug("events endpoint: skipping non-object JSONL line"),null;let g=p;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"||!f.has(k)?null:{recordedAt:g.recordedAt,entry:p}}function a(l,f,m){let p=f.params.update,g={sessionId:l,ts:new Date(f.recordedAt).toISOString(),kind:m,update:p};return p.messageId!==void 0&&p.messageId!==null&&(g.messageId=p.messageId),g}async function*d(l,f,m,h){for await(let p of f){let g=i(p,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,f,m,h){let p=qo.createInterface({input:Wo.createReadStream(f),crlfDelay:1/0}),g=d(l,p,m,h),w=await g.next(),y=w.done?null:w.value;return{sessionId:l,rl:p,gen:g,current:y,exhausted:y===null}}async function u(l){let f=await l.gen.next();f.done?(l.exhausted=!0,l.current=null):l.current=f.value}s.get("/v1/sessions/events",async(l,f)=>{let m=l.query,h=m.kinds;if(!h||h.trim().length===0)return f.code(400).send({error:"kinds parameter is required"}),f;let p=h.split(",").map(I=>I.trim());if(p.length===0)return f.code(400).send({error:"kinds parameter is required"}),f;for(let I of p)if(!Js.has(I))return f.code(400).send({error:`kind "${I}" is not queryable; allowed kinds: ${[...Js].join(", ")}`}),f;let g=new Set(p),w;if(m.since!==void 0&&m.since.trim().length>0){let I=new Date(m.since);if(isNaN(I.getTime()))return f.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),f;w=I.getTime()}let y=await e.list({includeNonInteractive:!0}),k=w!==void 0?y.filter(I=>new Date(I.updatedAt).getTime()>=w):y;f.raw.setHeader("content-type","application/x-ndjson"),f.raw.statusCode=200;let b=[];for(let I of k)try{let v=x.historyFile(I.sessionId),A=await c(I.sessionId,v,g,w);A.exhausted||b.push(A)}catch(v){if(v.code==="ENOENT")continue;throw v}l.raw.on("close",()=>{for(let I of b)try{I.rl.close()}catch{}f.raw.writableEnded||f.raw.end()});try{for(;b.length>0;){let I=-1,v=1/0;for(let C=0;C<b.length;C++){let R=b[C];R.current!==null&&R.current.ts<v&&(v=R.current.ts,I=C)}if(I===-1)break;let A=b[I];if(f.raw.write(JSON.stringify(A.current.row)+`
|
|
197
|
+
`),await u(A),A.exhausted){try{A.rl.close()}catch{}b.splice(I,1)}}}catch(I){for(let v of b)try{v.rl.close()}catch{}throw I}return f.raw.end(),f}),s.get("/v1/sessions/:id/events",async(l,f)=>{let m=l.params.id,h=l.query,p=await e.resolveCanonicalId(m)??m;if(!e.get(p)&&!await e.hasRecord(p))return f.code(404).send({error:"session not found"}),f;let w=h.kinds;if(!w||w.trim().length===0)return f.code(400).send({error:"kinds parameter is required"}),f;let y=w.split(",").map(C=>C.trim());if(y.length===0)return f.code(400).send({error:"kinds parameter is required"}),f;for(let C of y)if(!Js.has(C))return f.code(400).send({error:`kind "${C}" is not queryable; allowed kinds: ${[...Js].join(", ")}`}),f;let k=new Set(y),b;if(h.since!==void 0&&h.since.trim().length>0){let C=new Date(h.since);if(isNaN(C.getTime()))return f.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),f;b=C.getTime()}let I=x.historyFile(p),v=Wo.createReadStream(I),A=qo.createInterface({input:v,crlfDelay:1/0});f.raw.setHeader("content-type","application/x-ndjson"),f.raw.statusCode=200;try{for await(let C of A){let R=typeof C=="string"?C.trim():"";if(R.length===0)continue;let T;try{T=JSON.parse(R)}catch{console.debug("events endpoint: skipping malformed JSONL line in %s",I);continue}if(!T||typeof T!="object"||Array.isArray(T)){console.debug("events endpoint: skipping non-object JSONL line in %s",I);continue}let _=T;if(typeof _.recordedAt!="number"||typeof _.params!="object"||_.params===null||Array.isArray(_.params))continue;let U=_.params;if(typeof U.update!="object"||U.update===null||Array.isArray(U.update))continue;let J=U.update,M=J.sessionUpdate;if(typeof M!="string"||!k.has(M)||b!==void 0&&_.recordedAt<b)continue;let W={ts:new Date(_.recordedAt).toISOString(),kind:M,update:J};J.messageId!==void 0&&J.messageId!==null&&(W.messageId=J.messageId),f.raw.write(JSON.stringify(W)+`
|
|
198
|
+
`)}}catch(C){if(C.code==="ENOENT")return f.raw.end(),f;throw C}return f.raw.end(),f}),s.post("/v1/sessions/:id/prompt/:messageId/notify",async(l,f)=>{let m=l.params,h=m.id,p=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){f.code(400).send({error:"messageId, callbackUrl, and secret are all required"});return}let b;try{b=new URL(y)}catch{f.code(400).send({error:"callbackUrl must be a valid absolute URL"});return}if(b.protocol!=="https:"&&b.protocol!=="http:"){f.code(400).send({error:"callbackUrl must be http or https"});return}let I=e.get(p);if(!I){f.code(404).send({error:"session not found or not warm"});return}let v=I.registerTurnNotify(g,y,k);if(v.alreadyTerminal){f.code(200).send({status:"already_terminal",stopReason:v.stopReason});return}f.code(202).send({status:"registered"})}),s.get("/v1/sessions/:id/attention",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);return!p&&!await e.hasRecord(h)?(f.code(404).send({error:"session not found"}),f):p?{flags:p.listAttentionFlags()}:{flags:(await e.store.read(h))?.attentionFlags??[]}}),s.get("/v1/sessions/attention",async(l,f)=>{let m=l.query;if(!m.source||m.source.trim().length===0)return f.code(400).send({error:"source query parameter is required"}),f;let h=await e.list({includeNonInteractive:!0}),p=[];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&&p.push({...k,sessionId:g.sessionId})}return{flags:p}}),s.post("/v1/sessions/:id/attention/clear",async(l,f)=>{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)){f.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 C=Array.from(k.listAttentionFlags()).map(R=>`${R.source}::${R.reason}`);for(let R of C)k.clearAttentionFlag(R.split("::")[0],R.split("::").slice(1).join("::"))}f.code(204).send();return}if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}let b=e.store,I=await b.read(h);if(!I){f.code(404).send({error:"session not found"});return}let v=I.attentionFlags??[],A;if(w.length>0&&y.length>0){let C=`${w}::${y}`;A=v.filter(R=>`${R.source}::${R.reason}`!==C)}else A=[];if(A.length===v.length&&A.every((C,R)=>C.source===v[R].source&&C.reason===v[R].reason)){f.code(204).send();return}await b.write({...I,attentionFlags:A}),f.code(204).send()})}function Bc(s,e,t,n={}){s.get("/v1/agents",async()=>Nt(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 Ee(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===E.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}G();function Wc(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:x.home(),driftedKeys:n()}))}import*as Vc from"os";G();Ne();var Nn=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,Gs=class s{data;constructor(e){this.data=e}static async load(){let e=await ie(x.peers());return new s(Bh(e))}get(e){return this.data.entries[e]}async set(e){this.data.entries[e.name]=e,await qc(this.data)}async delete(e){return e in this.data.entries?(delete this.data.entries[e],await qc(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 Bh(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 qc(s){await fe(x.peers(),s,{mode:384})}var Wh=3600*24*365,Ge=class extends Error{status;constructor(e,t){super(e),this.name="PeerLoginError",this.status=t}};function Ks(s,e){return`${ke(s)?"http":"https"}://${s}:${e}`}async function zc(s){let e=s.fetchImpl??fetch,t=`${s.host}:${s.port}`,n=Ks(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??Wh})})}catch(i){throw new Ge(`Could not reach ${t}: ${i.message}`,502)}if(r.status===401)throw new Ge(`Wrong password for ${t}.`,401);if(r.status===403)throw new Ge(`No password is configured on ${t}. Run \`hydra-acp auth password\` on that daemon first.`,502);if(r.status===429)throw new Ge(`Too many failed login attempts on ${t}; try again later.`,429);if(!r.ok)throw new Ge(`Login to ${t} failed: HTTP ${r.status}`,502);let o=await r.json();if(!o.session_token||!o.expires_at)throw new Ge(`Login to ${t} returned a malformed response.`,502);return{token:o.session_token,expiresAt:o.expires_at}}async function zo(s){let e=s.fetchImpl??fetch,t=Ks(s.host,s.port);try{await e(`${t}/v1/auth/logout`,{method:"POST",headers:{Authorization:`Bearer ${s.token}`,"Content-Type":"application/json"},body:JSON.stringify({})})}catch{}}function Gc(s){return{machine:ht(),hydraVersion:de,startedAt:s,os:{platform:process.platform,release:Vc.release(),arch:process.arch},node:process.version}}async function Qs(s){let e=s.fetchImpl??fetch,t;try{t=await e(`${Ks(s.host,s.port)}/v1/system`,{headers:{Authorization:`Bearer ${s.token}`},signal:s.signal})}catch(n){return{kind:"error",message:n.message}}if(t.status===401||t.status===403)return{kind:"unauthorized"};if(t.status===404)return{kind:"unsupported"};if(!t.ok)return{kind:"error",message:`HTTP ${t.status}`};try{let n=await t.json();return typeof n?.machine=="string"?{kind:"ok",system:n}:{kind:"ok"}}catch{return{kind:"ok"}}}function Jc(s){return s!==void 0&&s.length<=64&&Nn.test(s)}function Kc(s,e){if(Jc(s))return s;if(/^[\d.]+$/.test(e)||e.includes(":"))return;let t=e.split(".")[0];return Jc(t)?t:void 0}function Qc(s,e){s.get("/v1/system",async()=>Gc(e))}var qh=/^[A-Za-z0-9._-]+$/;function Ys(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=zh(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){Dn(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){Dn(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){Dn(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){Dn(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){Dn(i,d)}})}function Dn(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 zh(s){let e=s.name;if(typeof e!="string"||!qh.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 Yc(s,e){Ys(s,"extension",e)}function Xc(s,e){Ys(s,"transformer",e)}function Zc(s,e){s.get("/v1/config",async()=>e())}import{z as ft}from"zod";G();import*as Xt from"fs/promises";import*as eu from"path";import{randomBytes as HA,scrypt as Jh,timingSafeEqual as Vh}from"crypto";import{promisify as Gh}from"util";var Kh=Gh(Jh);function tu(){return eu.join(x.home(),"password-hash")}var Qh=128*1024*1024;async function nu(){try{return(await Xt.readFile(tu(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function su(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await Xt.readFile(tu(),"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 Kh(s,i,a.length,{N:n,r,p:o,maxmem:Qh});return d.length!==a.length?!1:Vh(d,a)}var Yh=ft.object({password:ft.string().min(1),label:ft.string().min(1).max(256).optional(),ttlSec:ft.number().int().positive().optional()}),Xh=ft.object({id:ft.string().optional()}).optional(),Zh=ft.object({token:ft.string().min(32)});function ru(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=ey(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=Yh.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await nu())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await su(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=Xh.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=Zh.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 ey(s){return s.ip||"unknown"}import{z as pt}from"zod";Hn();var fy=pt.object({name:pt.string().min(1).max(64).regex(Nn).optional(),host:pt.string().min(1),port:pt.number().int().positive().optional(),password:pt.string().min(1),label:pt.string().min(1).max(256).optional(),ttlSec:pt.number().int().positive().optional(),pinnedFingerprint:pt.string().min(1).optional()});function pu(s,e){s.post("/v1/remotes",async(t,n)=>{let r;try{r=fy.parse(t.body)}catch{return n.code(400).send({error:`Invalid request body (name must match ${Nn} and the rest is a normal login request)`})}let o=r.port??Mt;r.pinnedFingerprint&&jn(r.host,o,r.pinnedFingerprint);let i;try{i=await zc({host:r.host,port:o,password:r.password,label:r.label,ttlSec:r.ttlSec})}catch(f){if(f instanceof Ge)return n.code(f.status).send({error:f.message});throw f}let a=await Qs({host:r.host,port:o,token:i.token}),d=a.kind==="ok"?a.system:void 0,c=r.name;if(c===void 0){c=Kc(d?.machine,r.host);let f=c!==void 0?e.store.get(c):void 0,m=f!==void 0&&(f.host!==r.host||f.port!==o);if(c===void 0||m){await zo({host:r.host,port:o,token:i.token});let h=c===void 0?`Couldn't derive a remote name for ${r.host}`:`A remote named ${c} already points at ${f.host}:${f.port}`;return n.code(c===void 0?400:409).send({error:`${h}. Pass a name: hydra-acp remote add <name> ${r.host}`})}}let u=new Date().toISOString(),l={name:c,host:r.host,port:o,token:i.token,expiresAt:i.expiresAt,addedAt:u,...r.label!==void 0?{label:r.label}:{},...r.pinnedFingerprint!==void 0?{pinnedFingerprint:r.pinnedFingerprint,pinnedAt:u}:{}};return await e.store.set(l),e.health?.markOk(l.name,d),n.code(201).send({name:l.name,host:l.host,port:l.port,expiresAt:l.expiresAt,label:l.label,addedAt:l.addedAt,pinnedFingerprint:l.pinnedFingerprint,status:e.health?.get(l.name)?.status??"unknown"})}),s.get("/v1/remotes",async(t,n)=>{let r=e.store.list().map(o=>{let i=e.health?.get(o.name);return{...o,status:i?.status??"unknown",...i?.checkedAt?{lastCheckedAt:i.checkedAt}:{},...i?.system?{system:i.system}:{}}});return n.code(200).send({remotes:r})}),s.get("/v1/remotes/:name/agents",async(t,n)=>{let r=e.store.get(t.params.name);if(!r)return n.code(404).send({error:"Not found"});let i=`${ke(r.host)?"http":"https"}://${r.host}:${r.port}`,a={Authorization:`Bearer ${r.token}`};try{let[d,c]=await Promise.all([fetch(`${i}/v1/agents`,{headers:a}),fetch(`${i}/v1/config`,{headers:a}).catch(()=>null)]);if(!d.ok)return n.code(d.status).header("content-type","application/json").send(await d.text());let u=await d.json(),l={};if(c?.ok){let f=await c.json();l={defaultAgent:f.defaultAgent,sessionDefaults:f.sessionDefaults}}return n.code(200).send({...u,...l})}catch(d){return n.code(502).send({error:`Could not reach remote "${r.name}": ${d.message}`})}}),s.delete("/v1/remotes/:name",async(t,n)=>{let r=t.params.name,o=e.store.get(r);return o?(await zo({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)||Vo(o.host,o.port),n.code(204).send()):n.code(404).send({error:"Not found"})})}function Zs(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:E.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())}}}Hn();import{WebSocket as py}from"ws";var gy=1e4,Xo=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 gu(s,e,t=gy){let n={};try{let r=new URL(s);if(r.protocol==="wss:"){let o=Yo(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 py(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 Xo(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 my=new Set(["session/attach","session/detach","session/prompt","session/cancel","session/close","session/delete","hydra-acp/session/delete","session/set_model","session/set_mode","session/set_config_option","_session/steering","hydra-acp/prompt/cancel","hydra-acp/prompt/update","hydra-acp/prompt/amend","hydra-acp/session/tool_content","hydra-acp/session/force_cancel"]);function hy(s){return my.has(s)}function hu(s,e,t,n){let r=[],o=a=>{for(let d of r)d(a)},i=(a,d)=>{e.handleLocalMessage(a,d,{connection:t.connection,clientId:n}).then(c=>c?s.send(c):void 0).catch(()=>{})};return s.onMessage(a=>{if("method"in a&&hy(a.method)){let d=a.params,c=typeof d?.sessionId=="string"?d.sessionId:void 0;if(c){if(dt(c)){i(a,c);return}if(a.method==="session/attach"){let u="id"in a;e.resolveLocalMiss(c).then(l=>{if(l.ok){i(a,l.foreignId);return}if(l.ambiguous&&u){s.send(Ln(a.id,E.SessionNotFound,`Session "${c}" exists on more than one remote (${l.ambiguous.join(", ")}). Address it as "<remote>:${c}".`));return}o(a)});return}}}o(a)}),{send:a=>s.send(a),onMessage:a=>r.push(a),onClose:a=>s.onClose(a),close:()=>s.close()}}var er=class{constructor(e,t=wy,n){this.store=e;this.dial=t;this.localMiss=n}store;dial;localMiss;attachments=new Map;async resolveLocalMiss(e){if(!this.localMiss)return{ok:!1};if(await this.localMiss.resolvesLocally(e))return{ok:!1};let t=this.localMiss.cache.findByLocalId(e);return t.length===0?{ok:!1}:t.length>1?{ok:!1,ambiguous:t.map(n=>n.name)}:{ok:!0,foreignId:qe(t[0])}}async handleLocalMessage(e,t,n){let r="id"in e,o=r?e.id:void 0,i=dt(t);if(!i)return r?Ln(o,E.SessionNotFound,`not a federated session id: ${t}`):void 0;let a=mu(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?Ln(o,E.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 f;try{f=await this.dial(u)}catch(g){return r?Ln(o,E.InternalError,`Could not reach remote "${i.name}": ${g.message}`):void 0}let m={peerConnection:f,localId:i.localId,target:n};this.wireAttachment(i.name,m);let h;try{h=await f.request("session/attach",d)}catch(g){return f.close().catch(()=>{}),r?Zo(o,g):void 0}this.attachments.set(a,m);let p=h&&typeof h.sessionId=="string"?{...h,sessionId:t}:h;return r?{jsonrpc:"2.0",id:o,result:p}:void 0}let c=this.attachments.get(a);if(!c)return r?Ln(o,E.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(f){l=f}return this.attachments.delete(a),c.peerConnection.close().catch(()=>{}),l?r?Zo(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 Zo(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=qe({name:e,localId:r}),a=()=>{this.attachments.delete(mu(o.clientId,i))};n.onAnyNotification((d,c)=>{let u=d;!u||u.sessionId!==r||(c==="hydra-acp/session/closed"&&a(),o.connection.notify(c,{...u,sessionId:i}).catch(()=>{}))}),n.onRequest("hydra-acp/session/request_permission",async d=>{let c=d;if(!c||c.sessionId!==r)throw{code:E.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 mu(s,e){return`${s} ${e}`}function Ln(s,e,t){return{jsonrpc:"2.0",id:s,error:{code:e,message:t}}}function Zo(s,e){let t=e,n=typeof t?.code=="number"?t.code:E.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 yy=1e4;async function wy(s){let t=`${ke(s.host)?"ws":"wss"}://${s.host}:${s.port}/acp`,n=await gu(t,["acp.v1",`hydra-acp-token.${s.token}`],yy);return new Be(Zs(n))}var ky=3e4,vy=5e3,tr=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??ky),this.timer.unref?.())}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}get(e){return this.snapshots.get(e)}markOk(e,t){this.snapshots.set(e,{status:"ok",checkedAt:new Date().toISOString(),...t?{system:t}:{}})}forget(e){this.snapshots.delete(e)}async checkAll(){let e=this.opts.fetchImpl??fetch;await Promise.allSettled(this.store.list().map(async t=>{let n=this.store.get(t.name);if(!n)return;let r=new AbortController,o=setTimeout(()=>r.abort(),vy);try{let i=await Qs({host:n.host,port:n.port,token:n.token,fetchImpl:e,signal:r.signal});if(i.kind==="ok"){this.snapshots.set(t.name,{status:"ok",checkedAt:new Date().toISOString(),...i.system?{system:i.system}:{}});return}if(i.kind==="unauthorized"){this.snapshots.set(t.name,{status:"unauthorized",checkedAt:new Date().toISOString()});return}if(i.kind==="error")throw new Error(i.message);let d=`${ke(n.host)?"http":"https"}://${n.host}:${n.port}/v1/auth/verify`,c=await e(d,{headers:{Authorization:`Bearer ${n.token}`},signal:r.signal});this.snapshots.set(t.name,{status:c.ok?"ok":"unauthorized",checkedAt:new Date().toISOString()})}catch(i){this.snapshots.set(t.name,{status:"unreachable",checkedAt:new Date().toISOString(),error:i.message})}finally{clearTimeout(o)}}))}};Hn();import{z as yu}from"zod";var by=yu.object({sessionLabel:yu.string().min(1).max(256)});function wu(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=by.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 ei}from"nanoid";import{randomBytes as Iu}from"crypto";import*as Au from"os";import*as Cu from"path";var Sy=200;function Iy(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e[ce];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,Sy)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function ku(s,e,t){let n=Iy(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 Un=new Map;function vu(s,e){let t=Un.get(s);t||(t=new Set,Un.set(s,t)),t.add(e);let n=!1;return()=>{if(n)return;n=!0;let r=Un.get(s);r&&(r.delete(e),r.size===0&&Un.delete(s))}}function bu(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=Un.get(r);if(o){if(o.has(s))return!0;for(let i of o)n.push(i)}}return!1}function N(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function Ey(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 Re(s,e,t){let n=s.get(e);if(!n)throw N(E.SessionNotFound,t??`session ${e} not found`);return n}async function Et(s,e){let t=Yt(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=Iu(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=Bo({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 jy(c,s),xu(c.sessionId,s),c}function Ru(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=cc({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_${ei(12)}`,a=Zs(t),d={},c=e.foreignSessions?hu(a,e.foreignSessions,d,i):a,u=new Be(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 f=(h,p)=>{if(l.attached.get(h)?.readonly)throw N(E.PermissionDenied,`${p} not permitted on a read-only attachment`)};if(u.onRequest("initialize",async h=>{let p=Qi.parse(h??{});p.clientInfo?.name&&(l.clientInfo={name:p.clientInfo.name,...p.clientInfo.version!==void 0?{version:p.clientInfo.version}:{}});let g=p.clientInfo?.version;return g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g)),Dy()}),o&&e.extensionCommands){let h=e.extensionCommands;u.onRequest("hydra-acp/commands/register",async p=>{let g=p??{},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 I=b;if(typeof I.name!="string"||I.name.length===0||typeof I.description!="string"||I.inputSchema===null||typeof I.inputSchema!="object")return;let v={name:I.name,description:I.description,inputSchema:I.inputSchema};return I.outputSchema!==null&&typeof I.outputSchema=="object"&&(v.outputSchema=I.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 p=g=>{let w=g??{};if(typeof w.sessionId!="string"||w.sessionId.length===0)throw N(E.InvalidParams,"sessionId is required");return w.sessionId};if(u.onRequest("hydra-acp/session/extension_state/get",async g=>{let w=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(!e.manager)throw N(E.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=p(g);if(!e.manager)throw N(E.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=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(y.value===void 0)throw N(E.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw N(E.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(w,o.name,y.key,y.value)}catch(k){throw N(E.InvalidParams,k.message)}return{ok:!0}}),u.onRequest("hydra-acp/session/extension_state/delete",async g=>{let w=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(!e.manager)throw N(E.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 N(E.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 p=>{let g=p??{},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 p=>{let g=p??{},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 N(-32602,"emit_message requires sessionId");if(!y&&b!=="client_broadcast")throw N(-32602,"emit_message requires method");let I=Re(e.manager,w),v=typeof g.respondsTo=="string"?g.respondsTo:void 0;if(v)return I.dischargeClaim(v,k),{ok:!0};if(b==="chain")return{ok:!0,response:await I.emitToChain(o.name,y,k)};if(b==="queue"){if(y!=="session/prompt")throw N(-32602,'route "queue" only supports method "session/prompt"');return{ok:!0,response:await I.emitToQueue(o.name,k)}}if(b==="daemon")return{ok:!0,response:await I.emitToChain(o.name,y,k)};if(b==="client_broadcast"){if(!k||typeof k!="object")throw N(-32602,"client_broadcast requires an envelope object");return I.broadcastClientUpdate(k),{ok:!0}}throw N(-32602,`unsupported route: ${JSON.stringify(b)}`)}),u.onRequest("hydra-acp/session/request_permission",async p=>{let g=p??{},w=typeof g.sessionId=="string"?g.sessionId:void 0;if(!w)throw N(-32602,"hydra-acp/session/request_permission requires sessionId");return Re(e.manager,w).requestPermissionFromClients(g)}),u.onRequest("hydra-acp/transformer/attach",async p=>$y(p,o.name,e)),u.onRequest("hydra-acp/child_session/spawn",async p=>{let g=p??{},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=rt(g._meta??void 0),I=b.title,v=b.model,A=b.workspace;if(!y&&k){let W=e.manager.get(k);W&&(y=W.cwd)}if(!y)throw N(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let C=await on(y),R=w??C.agentId??e.defaultAgent,T=await e.registry?.getAgent(R),_=cn(C.configDefaults,T??{id:R})?.value,U=v??_?.model,J=typeof g.interactive=="boolean"?g.interactive:!1,M=await e.manager.create({agentId:R,cwd:y,parentSessionId:k,interactive:J,transformChain:[],title:I,model:U,configDefaults:_,...A!==void 0?{workspace:A}:{}});return{childSessionId:M.sessionId,...M.workspace!==void 0||M.workspaceError!==void 0?{_meta:{[ce]:{...M.workspace!==void 0?{workspaceInfo:M.workspace}:{},...M.workspaceError!==void 0?{workspaceError:M.workspaceError}:{}}}}:{}}}),u.onRequest("hydra-acp/session/fork",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.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,I=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}:{},...I!==void 0?{model:I}:{}}),A=e.manager.get(v.sessionId);if(!A){let T=await e.manager.loadFromDisk(v.sessionId);if(!T)throw N(E.InternalError,`fork ${v.sessionId} vanished before it could be attached`);A=await Et(e,{...T,onInstallProgress:nr(u)})}Zt(l,A,A.sessionId);let C=gt(u,A,l),{entries:R}=await A.attach(C,"full");l.attached.set(A.sessionId,{sessionId:A.sessionId,clientId:C.clientId,readonly:!1});for(let T of R){if(u.isClosed())break;await u.notify(T.method,Ue(Le(T.params,T.recordedAt),T.seq)).catch(()=>{})}return{...v,sessionId:A.sessionId}}),u.onRequest("session/fork",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.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 N(E.InternalError,`fork ${y.sessionId} vanished before it could be attached`);k=await Et(e,{...v,onInstallProgress:nr(u)})}Zt(l,k,k.sessionId);let b=gt(u,k,l),{entries:I}=await k.attach(b,"full");l.attached.set(k.sessionId,{sessionId:k.sessionId,clientId:b.clientId,readonly:!1});for(let v of I){if(u.isClosed())break;await u.notify(v.method,Ue(Le(v.params,v.recordedAt),v.seq)).catch(()=>{})}return{sessionId:k.sessionId}});let h=async(p,g)=>{let w=p??{};if(typeof w.sessionId!="string")throw N(E.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 p=>(await h(p,"session/delete"),{})),u.onRequest("session/close",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.InvalidParams,"session/close requires sessionId");f(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 N(E.SessionNotFound,`session ${w} not found`)}),u.onRequest("hydra-acp/session/delete",async p=>{let{id:g,existed:w}=await h(p,"hydra-acp/session/delete");if(!w)throw N(E.SessionNotFound,`session ${g} not found`);return{deleted:!0,sessionId:g}}),u.onRequest("hydra-acp/child_session/await",async p=>{let g=p??{},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 N(-32602,"await_child requires childSessionId");let b=Re(e.manager,w,`child session ${w} not found`);return new Promise(I=>{let C=[],R=[],T=0,_=!1,U,J,M=!1,W=()=>{M||(M=!0,clearTimeout(q),U?.(),J?.(),I(_?{entries:C,truncated:!0}:{entries:C}))};U=b.onBroadcast(ee=>{let me=Ey(ee);for(C.push(ee),R.push(me),T+=me;C.length>0&&(C.length>1e3||T>1048576);)C.shift(),T-=R.shift()??0,_=!0;y==="turn_complete"&&ee.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 p=>{let g=p??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0;if(!w)throw N(-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 p=>Oy(p,o.name,e)),u.onRequest("hydra-acp/attention/clear",async p=>Fy(p,o.name,e)),u.onRequest("hydra-acp/connection/keep_alive",async p=>{let g=p??{},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 p=h??{};if(typeof p.sessionId!="string"||typeof p.hash!="string")throw N(E.InvalidParams,"hydra-acp/session/tool_content requires sessionId and hash");let g=await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,w=await e.manager.loadToolBlob(g,p.hash);if(w===null)throw N(E.SessionNotFound,"tool content not found");return{content:w}}),u.onRequest("authenticate",async h=>Ty(h,e)),u.onRequest("logout",async h=>Py(h,e)),u.onRequest("session/new",async h=>{let p=Yi.parse(h),g=rt(h?._meta),w=Array.isArray(g.transformers)&&g.transformers.every(Z=>typeof Z=="string")?g.transformers:e.manager.defaultTransformers??[],y=e.transformers?.resolveChain(w)??[],k=await on(p.cwd),b=g.agentId??k.agentId??e.defaultAgent,I=await e.registry?.getAgent(b),v=cn(k.configDefaults,I??{id:b})?.value,A,C,R=p.mcpServers;if(g.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){A=Iu(32).toString("hex"),C=e.mcpTokenRegistry.reserve(A);let Me={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${A}`}]};R=[...p.mcpServers??[],Me]}let T,_,U=Yt(e);U!==void 0&&(R=[...R??[],...U.descriptors]);let J=Bo({baselineMcpServers:p.mcpServers,stdinEnabled:g.mcpStdin===!0,deps:e}),M;try{M=await e.manager.create({cwd:p.cwd,agentId:b,mcpServers:R,title:g.title,agentArgs:g.agentArgs,model:g.model??v?.model,configDefaults:v,onInstallProgress:nr(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(Z){throw C!==void 0&&C.abandon(Z instanceof Error?Z:void 0),_!==void 0&&_.abandon(Z instanceof Error?Z:void 0),U!==void 0&&U.abandon(Z instanceof Error?Z:void 0),Z}if(A!==void 0&&C!==void 0&&e.mcpTokenRegistry!==void 0){let Z=A,Me=e.mcpTokenRegistry;C.complete(M),M.onClose(()=>{Me.unbind(Z)})}if(T!==void 0&&_!==void 0&&e.mcpTokenRegistry!==void 0){let Z=T,Me=e.mcpTokenRegistry;_.complete(M),M.onClose(()=>{Me.unbind(Z)})}U!==void 0&&U.bindToSession(M),xu(M.sessionId,e);let W,q;try{Zt(l,M,M.sessionId),W=gt(u,M,l),{entries:q}=await M.attach(W,"full")}catch(Z){throw await M.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),Z}l.attached.set(M.sessionId,{sessionId:M.sessionId,clientId:W.clientId,readonly:!1}),setImmediate(()=>{(async()=>{for(let Z of q){if(u.isClosed())break;await u.notify(Z.method,Ue(Le(Z.params,Z.recordedAt),Z.seq)).catch(()=>{})}})()});let ee=sr(M),me=rr(M);return{sessionId:M.sessionId,...ee?{modes:ee}:{},...me?{models:me}:{},configOptions:M.buildConfigOptions(),_meta:or(e.manager,M,{clientId:W.clientId})}}),u.onRequest("session/attach",async h=>{let p=Zi.parse(h),g=p.clientInfo?.version;g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g));let w=rt(p._meta),y=w.resume,k=w.readonly===!0,b=w.env;s.log.info(`session/attach sessionId=${p.sessionId} hasResumeHints=${!!y} readonly=${k}`);let I=y?p.sessionId:await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,v=e.manager.get(I);if(!v&&k){let M=await e.manager.loadFromDisk(I);if(!M)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);let W=await e.manager.loadHistory(I,{...w.historyLimit!==void 0?{maxEntries:w.historyLimit}:{}}),q=p.clientId??`cli_${ei(8)}`;l.attached.set(M.hydraSessionId,{sessionId:M.hydraSessionId,clientId:q,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${M.hydraSessionId} clientId=${q} attachedCount=${l.attached.size} replayed=${W.length}`);for(let ee of W)await u.notify(ee.method,Ue(Le(ee.params,ee.recordedAt),ee.seq)).catch(()=>{});return{sessionId:M.hydraSessionId,clientId:q,connectedClients:[q],historyPolicy:"full",replayed:W.length,_meta:Ny(M)}}let A=!v;if(!v){let M=await e.manager.loadFromDisk(I),W=await My(I,y,M?.upstreamSessionId,e.manager);W.kind==="ignore"&&s.log.warn(W.logMessage);let q=M;if(y&&W.kind==="honor"&&(q={...M,hydraSessionId:p.sessionId,upstreamSessionId:y.upstreamSessionId,agentId:y.agentId,cwd:M?.workspace?.path??y.cwd,...y.title!==void 0?{title:y.title}:{},...y.agentArgs!==void 0?{agentArgs:y.agentArgs}:{}}),!q)throw N(E.SessionNotFound,`session ${p.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(q.agentId,q.upstreamSessionId))throw N(E.SessionNotFound,`session ${p.sessionId} was deleted`);let ee=q.originatingClient?q:{...q,originatingClient:l.clientInfo},me=b!==void 0?{...ee,forwardedEnv:b}:ee;v=await Et(e,{...me,onInstallProgress:nr(u)})}Zt(l,v,v.sessionId);let C=gt(u,v,l,p.clientInfo,p.clientId),R=w.replayMode==="drip",{entries:T,appliedPolicy:_}=await v.attach(C,p.historyPolicy,{afterMessageId:p.afterMessageId,afterSeq:p.afterSeq,raw:R,...w.historyLimit!==void 0?{historyLimit:w.historyLimit}:{},...w.toolContent!==void 0?{toolContent:w.toolContent}:{}});if(l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:C.clientId,readonly:k}),b!==void 0&&await e.manager.setForwardedEnv(v.sessionId,b).catch(()=>{}),s.log.info(`session/attach OK sessionId=${v.sessionId} clientId=${C.clientId} attachedCount=${l.attached.size} requestedPolicy=${p.historyPolicy} appliedPolicy=${_} replayed=${T.length} readonly=${k}${R?" replayMode=drip":""}`),R){let M=w.dripSpeed&&w.dripSpeed>0?w.dripSpeed:1,W=750;(async()=>{let q=null;for(let ee of T){let me=typeof ee.recordedAt=="number"?ee.recordedAt:null;if(q!==null&&me!==null){let Z=Math.min(W,Math.max(0,(me-q)/M));Z>0&&await new Promise(Me=>setTimeout(Me,Z))}me!==null&&(q=me);try{await u.notify(ee.method,Ue(Le(ee.params,me??void 0),ee.seq))}catch{return}}})()}else for(let M=0;M<T.length&&!u.isClosed();M++){let W=T[M],q=u.notify(W.method,Ue(Le(W.params,W.recordedAt),W.seq)).catch(()=>{});(M+1)%200===0&&await q}v.replayPendingPermissions(C);let U=sr(v),J=rr(v);return{sessionId:v.sessionId,clientId:C.clientId,connectedClients:v.connectedClients(C.clientId),historyPolicy:_,replayed:T.length,...U?{modes:U}:{},...J?{models:J}:{},configOptions:v.buildConfigOptions(),_meta:or(e.manager,v,{resurrected:A})}}),u.onRequest("session/detach",async h=>{let p=ea.parse(h),g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"client not attached to that session");let w=e.manager.get(p.sessionId);return w?.detach(g.clientId),l.attached.delete(p.sessionId),w&&e.manager.reapIfOrphanedNonInteractive(p.sessionId),{sessionId:p.sessionId,_meta:{[ce]:{detachStatus:"detached"}}}}),u.onRequest("session/list",async h=>{let p=ta.parse(h??{});return{sessions:(await e.manager.list({cwd:p.cwd})).filter(k=>k.originatingClient?.name!==vs).map(na)}}),u.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw N(E.InternalError,"agent registry unavailable");return Nt(e.registry)}),u.onRequest("hydra-acp/agents/auth_methods",async h=>{let p=h??{};if(typeof p.agentId!="string"||p.agentId.length===0)throw N(E.InvalidParams,"hydra-acp/agents/auth_methods requires a non-empty agentId string");return{authMethods:(await e.manager.bootstrapAgentForAuth(p.agentId)).authMethods??[]}}),u.onRequest("session/prompt",async h=>{let p=sa.parse(h);f(p.sessionId,"session/prompt");let g=await ku(p,e.manager,b=>{s.log.warn(`session/prompt: dropping unknown sentBy.sessionId=${b} sessionId=${p.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 ${p.sessionId}`),N(E.InvalidRequest,`message chain too deep (${g.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(g.awaiting===!0&&bu(g.fromSession,p.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${g.fromSession} -> ${p.sessionId}`),N(E.InvalidRequest,`would deadlock: ${p.sessionId} is already blocked waiting on ${g.fromSession}. Send with --no-wait, or let the other turn finish first.`)}let w=l.attached.get(p.sessionId);if(!w)throw s.log.warn(`session/prompt rejected: not attached sessionId=${p.sessionId} attachedKeys=[${[...l.attached.keys()].join(",")}]`),N(E.SessionNotFound,"not attached to session");let y=e.manager.get(p.sessionId);if(!y){let b=await e.manager.loadFromDisk(p.sessionId);if(!b)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${p.sessionId}`),y=await Et(e,b);let I=gt(u,y,l,void 0,w.clientId);await y.attach(I,"none")}let k=g?.awaiting===!0&&g.fromSession!==void 0?vu(g.fromSession,p.sessionId):void 0;try{return await y.prompt(w.clientId,p,g)}finally{k?.()}});let m=h=>{let p;try{p=Yn.parse(h)}catch(y){s.log.warn(`session/cancel: invalid params: ${y.message}`);return}let g=l.attached.get(p.sessionId);if(!g)return;if(g.readonly){s.log.warn(`session/cancel dropped (readonly attachment) sessionId=${p.sessionId}`);return}let w=e.manager.get(p.sessionId);w&&w.cancel(g.clientId).catch(y=>{s.log.warn(`session/cancel for ${p.sessionId}: ${y.message}`)})};u.onNotification("session/cancel",m),u.onRequest("session/cancel",async h=>{let p=Yn.parse(h);return f(p.sessionId,"session/cancel"),m(h),null}),u.onRequest("hydra-acp/prompt/cancel",async h=>{let p=oa.parse(h);return f(p.sessionId,"hydra-acp/prompt/cancel"),Re(e.manager,p.sessionId).cancelQueuedPrompt(p.messageId)}),u.onRequest("hydra-acp/session/force_cancel",async h=>{let p=Yn.parse(h);return f(p.sessionId,"hydra-acp/session/force_cancel"),Re(e.manager,p.sessionId).forceCancel()}),u.onRequest("hydra-acp/prompt/update",async h=>{let p=ia.parse(h);return f(p.sessionId,"hydra-acp/prompt/update"),Re(e.manager,p.sessionId).updateQueuedPrompt(p.messageId,p.prompt)}),u.onRequest("hydra-acp/prompt/amend",async h=>{let p=aa.parse(h);f(p.sessionId,"hydra-acp/prompt/amend");let g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"not attached to session");return Re(e.manager,p.sessionId).amendPrompt(g.clientId,p)}),u.onRequest("_session/steering",async h=>{let p=da.parse(h);f(p.sessionId,"_session/steering");let g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"not attached to session");let w=e.manager.get(p.sessionId);if(!w){let y=await e.manager.loadFromDisk(p.sessionId);if(!y)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);w=await Et(e,y);let k=gt(u,w,l,void 0,g.clientId);await w.attach(k,"none")}return w.steer(g.clientId,p)}),u.onRequest("session/resume",async h=>{let p=h??{},g=typeof p.sessionId=="string"?p.sessionId:void 0;if(!g)throw N(E.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 N(E.SessionNotFound,`session ${g} not found in memory or on disk`);y=await Et(e,v)}Zt(l,y,y.sessionId);let k=gt(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=sr(y),I=rr(y);return{sessionId:y.sessionId,...b?{modes:b}:{},...I?{models:I}:{},configOptions:y.buildConfigOptions(),_meta:or(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/load",async h=>{let p=h??{},g=typeof p.sessionId=="string"?p.sessionId:void 0;if(!g)throw N(E.InvalidParams,"session/load requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let A=await e.manager.loadFromDisk(w);if(!A)throw N(E.SessionNotFound,`session ${g} not found in memory or on disk`);y=await Et(e,A)}Zt(l,y,y.sessionId);let k=gt(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 A of b){if(u.isClosed())break;await u.notify(A.method,Ue(Le(A.params,A.recordedAt),A.seq)).catch(()=>{})}y.replayPendingPermissions(k);let I=sr(y),v=rr(y);return{sessionId:y.sessionId,...I?{modes:I}:{},...v?{models:v}:{},configOptions:y.buildConfigOptions(),_meta:or(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/set_model",async h=>{let p=h?.sessionId;typeof p=="string"&&f(p,"session/set_model");let g=_y(h,e.manager);if(g.kind==="error")throw s.log.warn(g.logMessage),N(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 p=h,g=p?.sessionId;if(typeof g=="string"&&f(g,"session/set_mode"),!p||typeof p.sessionId!="string")throw N(E.InvalidParams,"session/set_mode requires string sessionId");if(typeof p.modeId!="string")throw N(E.InvalidParams,"session/set_mode requires string modeId");let w=Re(e.manager,p.sessionId),y=await w.forwardRequest("session/set_mode",h);return w.applyModeChange(p.modeId),y}),u.onRequest("session/set_config_option",async h=>{let p=h,g=b=>N(E.InvalidParams,b),w=p?.sessionId;if(typeof w=="string"&&f(w,"session/set_config_option"),!p||typeof p.sessionId!="string")throw g("session/set_config_option requires string sessionId");if(typeof p.configId!="string")throw g("session/set_config_option requires string configId");if(typeof p.value!="string")throw g("session/set_config_option requires string value");let y=Re(e.manager,p.sessionId),k=y.buildConfigOptions().find(b=>b.id===p.configId);if(!k)throw g(`unknown configId ${JSON.stringify(p.configId)} for this session`);if(!k.options.some(b=>b.value===p.value))throw g(`value ${JSON.stringify(p.value)} is not valid for configId ${JSON.stringify(p.configId)}`);switch(p.configId){case"model":{if(p.value!==y.currentModel){let b=await y.forwardModelChange(p.value);y.applyAgentConfigOptionResponse(b,"model")}y.applyModelChange(p.value);break}case"mode":{p.value!==y.currentMode&&await y.forwardRequest("session/set_mode",{sessionId:p.sessionId,modeId:p.value}),y.applyModeChange(p.value);break}case"agent":{p.value!==y.agentId&&await y.setAgent(p.value);break}default:{let b=await y.forwardRequest("session/set_config_option",{sessionId:p.sessionId,configId:p.configId,value:p.value});y.applyAgentConfigOptionResponse(b,p.configId)&&y.broadcastConfigOptions()}}return{configOptions:y.buildConfigOptions()}}),u.setDefaultHandler(async(h,p)=>{let g=new Set(["hydra-acp/attention/set","hydra-acp/attention/clear"]),w=p.startsWith("session/"),y=p.startsWith("hydra-acp/");if(!w&&!y||h===null||typeof h!="object"||g.has(p))throw N(E.MethodNotFound,`Method not found: ${p}`);let k=h.sessionId;if(typeof k!="string")throw N(E.MethodNotFound,`Method not found: ${p}`);return f(k,p),Re(e.manager,k).forwardRequest(p,h)})})}async function Ty(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw N(E.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 N(E.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 N(E.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be a string[]; got ${k===null?"null":typeof k}`);for(let I of k)if(typeof I!="string")throw N(E.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be string[]; got non-string entry ${JSON.stringify(I)}`);return k},h=await e.manager.planSpawnForAgent(a.agentId),p,g;if(l?.args!==void 0){let k=typeof l.command=="string"?l.command:void 0;p=k!==void 0&&Cu.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):[];p=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=Au.homedir();return console.error(`[authenticate] terminal-auth requested agentId=${a.agentId} methodId=${n}`),{kind:"terminal",command:p,args:g,env:w,cwd:y}}try{return await a.connection.request("authenticate",{methodId:n})}catch(m){throw lt(m,a)}}async function Py(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 nr(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(ca,t).catch(()=>{})}}function sr(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 rr(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 My(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 _y(s,e){if(!s||typeof s!="object")return{kind:"error",code:E.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:E.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:E.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:E.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=Ut(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:E.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 $y(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw N(E.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw N(E.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw N(E.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return Re(t.manager,r).addTransformer(o),{ok:!0}}async function Oy(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 N(E.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw N(E.InvalidParams,"hydra-acp/attention/set requires string reason");return Re(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function Fy(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 N(E.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw N(E.InvalidParams,"hydra-acp/attention/clear requires string reason");return Re(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function Ny(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:An(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{[ce]:Qn(e,t)}}function or(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 un(e.agentMeta,Qn(n,r))}function Dy(){return{protocolVersion:1,agentInfo:{name:"hydra",version:de},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:{...un(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 jy(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 xu(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 gt(s,e,t,n,r){return{clientId:r??`cli_${ei(8)}`,connection:s,clientInfo:n}}function Zt(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var ir=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 Hy}from"crypto";import{McpServer as Ly}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Uy}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as ge}from"zod";function ti(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 Ie(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var Eu="Bearer ";function en(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 By(s){let e=new Ly({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:ge.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return Ie(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:ge.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return Ie(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:ge.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:ge.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:ge.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 Ie(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:ge.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:ge.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 Ie({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:ge.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:ge.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:ge.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:ge.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:ge.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:ge.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:ge.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:ge.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:ge.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 Ie(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 Ie(t)}),e}var Wy=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=By(a),u=new Uy({sessionIdGenerator:()=>Hy()});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=en(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 f,m=new Promise(p=>{f=setTimeout(()=>p(void 0),Wy)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(f!==void 0&&clearTimeout(f),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 qy}from"crypto";import{McpServer as zy}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Jy}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as Ke}from"zod";function Vy(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var Pu=2e3,Mu=2e4;function Gy(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return Wt([s]);let n=[],r=ln(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=ns(t);return i!==void 0&&n.push(i),n.join(`
|
|
199
|
+
`)}function Ky(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 Qy(s){let e=new zy({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:Ke.string().min(1).describe("Case-insensitive substring to search for."),limit:Ke.number().int().min(1).max(50).optional().describe("Maximum number of matches to return (default 10, max 50)."),include_tool_calls:Ke.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 Ie({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=ti(u);if(!l)continue;let{kind:f,update:m}=l;if((f==="tool_call"||f==="tool_call_update")&&!r)continue;let h=Gy(u,f,m),p=h.toLowerCase().indexOf(a);if(p<0)continue;let g=Vy(f),w=Ky(h,p),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 Ie({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:Ke.number().int().min(0).describe("Zero-based index of the first entry to include (inclusive)."),to_entry:Ke.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 Ie({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 Ie({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=Wt(u,{toolOutput:{maxPerCall:Pu,maxTotal:Mu}});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:Ke.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:Ke.string().optional().describe("ACP tool kind: execute (shell), read, edit, think, other. Agent-independent, unlike tool_name."),file_path:Ke.string().optional(),limit:Ke.number().int().min(1).max(100).optional(),include_output:Ke.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 Ie({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,f=Math.max(o*4,200);for await(let{entryId:y,entry:k}of a.iterRecallNewestFirst()){let b=ti(k);if(!b)continue;let{kind:I,update:v}=b;if(I!=="tool_call"&&I!=="tool_call_update")continue;let A=typeof v.toolCallId=="string"&&v.toolCallId.length>0?v.toolCallId:`__noid_${y}`,C=l.get(A);if(C||(C={entryId:y,toolName:"(unnamed)",nameAuthoritative:!1,rawInput:{},locations:[],status:"in_progress"},l.set(A,C)),y<C.entryId&&(C.entryId=y),!C.nameAuthoritative){let T=ln(v);T!==void 0?(C.toolName=T,C.nameAuthoritative=!0):typeof v.name=="string"&&v.name.length>0?(C.toolName=v.name,C.nameAuthoritative=!0):I==="tool_call"&&typeof v.title=="string"&&v.title.length>0&&(C.toolName=v.title,C.nameAuthoritative=!0)}if(C.kind===void 0&&typeof v.kind=="string"&&v.kind.length>0&&(C.kind=v.kind),C.output===void 0){let T=ns(v);T!==void 0&&(C.output=T)}let R=v.rawInput;if(R&&typeof R=="object"&&!Array.isArray(R)&&Object.keys(R).length>0)for(let[T,_]of Object.entries(R))C.rawInput[T]===void 0&&(C.rawInput[T]=_);if(Array.isArray(v.locations))for(let T of v.locations){let _=T?.path;typeof _=="string"&&_.length>0&&!C.locations.includes(_)&&C.locations.push(_)}if(typeof v.status=="string"&&C.status==="in_progress"&&(C.status=v.status),k.recordedAt!==void 0&&C.timestamp===void 0&&(C.timestamp=String(k.recordedAt)),l.size>=f)break}let m=[...l.keys()].sort((y,k)=>l.get(y).entryId-l.get(k).entryId),h=[],p=Mu,g=!1;for(let y of m){let k=l.get(y);if(k.toolName=Br({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(),A=["file_path","filePath","path"],C=!1;for(let R of A){let T=k.rawInput[R];if(typeof T=="string"&&T.toLowerCase().includes(v)){C=!0;break}}if(!C){for(let R of k.locations)if(R.toLowerCase().includes(v)){C=!0;break}}if(!C)continue}let b={};for(let[v,A]of Object.entries(k.rawInput))typeof A=="string"?b[v]=A.length>500?A.slice(0,497)+"\u2026":A:(typeof A=="number"||typeof A=="boolean")&&(b[v]=A);k.locations.length>0&&b.locations===void 0&&(b.locations=k.locations);let I={entryId:k.entryId,tool:k.toolName,args:b,status:k.status,timestamp:k.timestamp};if(k.kind!==void 0&&(I.kind=k.kind),i&&k.output!==void 0){let v=k.output,A=Math.min(Pu,p);if(A<=0)g=!0;else{let C=v.length<=A?v:v.slice(0,A-1)+"\u2026";I.output=C,I.outputBytes=v.length,I.outputTruncated=C.length<v.length,p-=C.length}}if(h.push(I),h.length>=o)break}let w=h.length>=o;return Ie({calls:h,truncated:w,...g?{outputBudgetExhausted:g}:{}})}),e}var Yy=1e4;function _u(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=Qy(a),u=new Jy({sessionIdGenerator:()=>qy()});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=en(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 f,m=new Promise(p=>{f=setTimeout(()=>p(void 0),Yy)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(f!==void 0&&clearTimeout(f),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 ar=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 ow}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{randomUUID as iw}from"crypto";import{Server as Xy}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Zy,ListToolsRequestSchema as ew}from"@modelcontextprotocol/sdk/types.js";function $u(s,e,t,n){let r=typeof t=="function"?async()=>t():async()=>t,o=new Xy({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(ew,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(Zy,async(a,d)=>{let c=a.params.name,u=d._meta?.progressToken??d.requestId,l=nw(u,d.sendNotification);try{let f=await r(),m=await sw(e.connection,s,c,a.params.arguments??{},f);return rw(m,c)}catch(f){return ni(f instanceof Error?f.message:String(f))}finally{l()}}),o}var tw=15e3;function nw(s,e,t=tw){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 sw(s,e,t,n,r){return await s.request("hydra-acp/mcp_tools/invoke",{server:e,tool:t,args:n,sessionId:r})}function rw(s,e){if(s===null||typeof s!="object")return ni(`extension ${e} returned non-object`);let t=s;return Array.isArray(t.content)?t:ni(`extension ${e} omitted content array`)}function ni(s){return{content:[{type:"text",text:s}],isError:!0}}var aw=1e4;function Ou(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 f=l.get(u);f!==void 0&&(l.delete(u),r(f))}}async function i(u,l){for(let[f,m]of n){if(e.lookup(f)?.session?.sessionId!==u)continue;let p=m.get(l);if(p!==void 0)try{await p.server.sendToolListChanged()}catch{}}}t.onChange(u=>{o(u)});async function a(u,l){let f=n.get(u);f===void 0&&(f=new Map,n.set(u,f),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 m=f.get(l);if(m!==void 0)return m.transport;let h=t.lookup(l);if(h===void 0)return;let y=$u(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 I,v=new Promise(C=>{I=setTimeout(()=>C(void 0),aw)}),A=await Promise.race([b.sessionReady.catch(()=>{}),v]);if(I!==void 0&&clearTimeout(I),A===void 0)throw new Error("session not ready");return A.sessionId},{peekSessionId:()=>e.lookup(u)?.session?.sessionId,fetchSessionTools:async b=>{let I=await h.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 A=[];for(let C of v){if(!C||typeof C!="object")continue;let R=C;if(typeof R.name!="string"||R.name.length===0||typeof R.description!="string"||R.inputSchema===null||typeof R.inputSchema!="object")continue;let T={name:R.name,description:R.description,inputSchema:R.inputSchema};R.outputSchema!==null&&typeof R.outputSchema=="object"&&(T.outputSchema=R.outputSchema),A.push(T)}return A}}),k=new ow({sessionIdGenerator:()=>iw()});return await y.connect(k),f.set(l,{server:y,transport:k}),k}async function d(u,l){let f=en(u);if(f===void 0){l.code(401).send({error:"missing bearer token"});return}if(e.lookup(f)===void 0){l.code(404).send({error:"unknown mcp token"});return}let h=u.params.name,p=await a(f,h);if(p===void 0){l.code(404).send({error:`unknown mcp server: ${h}`});return}l.hijack(),await p.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 Lu(s,e){gw(s),br(s.daemon.scrubEnv);let t=s,n=s.daemon.tls?await Qe.readFile(ae(s.daemon.tls.key)):void 0,r=s.daemon.tls?await Qe.readFile(ae(s.daemon.tls.cert)):void 0;await Qe.mkdir(x.home(),{recursive:!0});let{stream:o,fileStream:i}=await fw(s.daemon.logLevel),a=dw({logger:{level:s.daemon.logLevel,stream:o},bodyLimit:256*1024*1024});await a.register(cw,{options:{handleProtocols:Ii}}),xr(F=>{a.log.info(F)}),Pr(F=>{a.log.info(F)});let d=await Fs.load(),c=await Gs.load();Qo(),Go(c);let u=new tr(c);u.start();let l=new zs(c);l.start();let f=new Ls,m=new Hs,h=new Ns(e),p=new js([h,new Ds(d),m]),g=dc({validator:p});a.addHook("onRequest",async(F,ve)=>{F.routeOptions.config?.skipAuth||F.url==="/acp"||F.url?.startsWith("/acp?")||(await g(F,ve),!ve.sent&&F.authIdentity?.startsWith("script:")&&!uc(F.method,F.routeOptions.url)&&ve.code(403).send({error:"script tokens may only access read-only session data"}))});let w=setInterval(()=>{d.sweepExpired()},300*1e3);w.unref();let y=setInterval(()=>{f.sweepExpired()},300*1e3);y.unref();let k=new Gn(s,{onFetched:()=>{Gd(k,A)},onStaleFallback:(F,ve)=>{let nn=Math.round(ve/36e5),sn=nn>=48?`${Math.round(nn/24)}d`:`${nn}h`;a.log.warn(`registry fetch failed (${F.message}); serving stale cache last synced ${sn} ago; agent versions may be outdated ('hydra registry refresh' to retry)`)}});Fo(F=>a.log.info(F));let b={info:F=>a.log.info(F),warn:F=>a.log.warn(F)},I=F=>it.spawn({...F,stderrTailBytes:s.daemon.agentStderrTailBytes,logger:b});Ti(s.compressToolContent);let v=new $s,A=new Cs(k,I,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:b,npmRegistry:s.npmRegistry,extensionCommands:v,defaultCwd:s.defaultCwd,disableWorkspaceSnapshots:s.disableWorkspaceSnapshots}),C=new er(c,void 0,{resolvesLocally:async F=>await A.resolveCanonicalId(F)!==void 0,cache:l}),R=new Ms(wi(s),void 0,{tokenRegistry:m}),T=new _s(ki(s),void 0,{tokenRegistry:m}),_=[];Wc(a,de,Yd(s),()=>_);let U=new Date().toISOString();Qc(a,U);let J=new ir,M=new ar,W,q=()=>{if(W!==void 0)return W;let F=a.server.address();return W=`http://127.0.0.1:${F&&typeof F=="object"?F.port:s.daemon.port}`,W},ee={agentId:s.defaultAgent,cwd:s.defaultCwd,publicHost:s.daemon.publicHost,host:s.daemon.host,port:s.daemon.port,compaction:s.compaction};Uc(a,A,ee,{extensionMcp:M,mcpTokenRegistry:J,getDaemonOrigin:q},c,l),Nc(a,{store:c,localMiss:{resolvesLocally:async F=>await A.resolveCanonicalId(F)!==void 0,cache:l}}),Bc(a,k,A,{npmRegistry:s.npmRegistry}),Yc(a,R),Xc(a,T);let me={host:s.daemon.host,port:s.daemon.port,...s.daemon.publicHost!==void 0?{publicHost:s.daemon.publicHost}:{},...s.daemon.tls?{tls:{cert:ae(s.daemon.tls.cert),key:ae(s.daemon.tls.key)}}:{}};Zc(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],listen:me})),ru(a,{store:d,rateLimiter:f,staticTokenValidator:h}),pu(a,{store:c,health:u}),wu(a,{processRegistry:m}),Tu(a,J),_u(a,J);let Z=Ou(a,J,M);Ru(a,{validator:p,manager:A,defaultAgent:s.defaultAgent,processRegistry:m,onExtensionVersion:(F,ve)=>R.reportVersion(F,ve),onTransformerVersion:(F,ve)=>T.reportVersion(F,ve),transformers:T,extensionCommands:v,mcpTokenRegistry:J,extensionMcp:M,extensionMcpControls:Z,getDaemonOrigin:q,registry:k,foreignSessions:C});let Me=!!s.daemon.tls;await a.listen({host:Me?"127.0.0.1":s.daemon.host,port:Me?0:s.daemon.port});let dr=a.server.address(),Tt=dr&&typeof dr=="object"?dr.port:s.daemon.port,Bn,Uu=s.daemon.host,si=Tt;if(Me&&n&&r){Bn=await pw({listenHost:s.daemon.host,listenPort:s.daemon.port,upstreamHost:"127.0.0.1",upstreamPort:Tt,tlsOptions:{key:n,cert:r},logger:a.log});let F=Bn.address();F&&typeof F=="object"&&(si=F.port)}await Qe.mkdir(x.home(),{recursive:!0}),await Vd({pid:process.pid,host:Uu,port:si,loopbackPort:Tt,startedAt:U});let ri={daemonUrl:`http://127.0.0.1:${Tt}`,daemonHost:"127.0.0.1",daemonPort:Tt,serviceToken:e,daemonWsUrl:`ws://127.0.0.1:${Tt}/acp`,hydraHome:x.home()};R.setContext(ri),T.setContext(ri),await R.start(),await T.start();try{await A.reconcilePermissionFlags()}catch(F){a.log.warn(`permission flag reconcile failed: ${F.message}`)}try{await A.seedSessionIndex()}catch(F){a.log.warn(`session index seed failed: ${F.message}`)}A.resurrectPendingQueues().catch(F=>{a.log.warn(`queue replay scan failed: ${F.message}`)}),A.resumePendingCompactions().catch(F=>{a.log.warn(`compaction resume scan failed: ${F.message}`)}),A.resumePendingAgentSwaps().catch(F=>{a.log.warn(`agent-swap resume scan failed: ${F.message}`)});let oi=s.daemon.agentSyncIntervalMinutes*60*1e3,ii=oi>0?Kd({registry:k,manager:A,intervalMs:oi,logger:b}):void 0,ai=s.daemon.sessionGcIntervalMinutes*60*1e3,Bu=s.daemon.sessionGcMaxAgeDays*24*60*60*1e3,di=ai>0?Qd({manager:A,intervalMs:ai,maxAgeMs:Bu,logger:b}):void 0,Wu=tc({bootConfig:s,apply:F=>{t=F,k.setConfig(F),A.setLiveConfig({sessionDefaults:F.sessionDefaults}),ee.agentId=F.defaultAgent,ee.cwd=F.defaultCwd,br(F.daemon.scrubEnv)},onDrift:F=>{_=F},logger:b});return{app:a,manager:A,registry:k,extensions:R,transformers:T,mcpTokenRegistry:J,extensionMcp:M,processRegistry:m,shutdown:async()=>{u.stop(),l.stop(),Wu(),di&&di(),ii&&ii(),clearInterval(w),clearInterval(y);let F=async(ve,nn)=>{try{await nn()}catch(sn){a.log.warn(`shutdown step ${ve} failed: ${sn instanceof Error?sn.message:String(sn)}`)}};await F("sessionTokenStore.flush",()=>d.flush()),await F("extensions.stop",()=>R.stop()),await F("transformers.stop",()=>T.stop()),await F("manager.closeAll",()=>A.closeAll()),await F("manager.flushSynopsis",()=>A.flushSynopsis(3e4)),await F("manager.shutdownSynopsis",()=>A.shutdownSynopsis()),await F("manager.flushMetaWrites",()=>A.flushMetaWrites()),await F("manager.flushHistoryWrites",()=>A.flushHistoryWrites()),xr(null),Pr(null),Fo(null),Bn&&await F("tlsTerminator.close",()=>new Promise(ve=>Bn.close(()=>ve()))),await F("app.close",()=>a.close());try{Du.unlinkSync(x.pidFile())}catch{}await F("fileStream.flushSync",()=>i.flushSync())}}}var Nu=20;async function lw(s,e){let t=tn.dirname(s),n=tn.basename(s,".log"),r=new RegExp(`^${n}\\.(\\d+)\\.log$`),o;try{o=await Qe.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=>Qe.unlink(tn.join(t,d.name))))}async function fw(s){await lw(x.logFile(),Nu);let e=await uw({file:x.logFile(),size:"10m",mkdir:!0,symlink:Es,limit:{count:Nu,removeOtherLogFiles:!0}}),t=Fu.destination(2);return{stream:Fu.multistream([{stream:e,level:s},{stream:t,level:s}]),fileStream:e}}async function pw(s){let e=Hu.createServer(s.tlsOptions,t=>{let n=ju.connect({host:s.upstreamHost,port:s.upstreamPort}),r=!1,o=i=>{if(!r){r=!0,i&&s.logger.warn(`tls terminator forwarder error: ${i.message??String(i)}`);try{t.destroy()}catch{}try{n.destroy()}catch{}}};t.on("error",o),n.on("error",o),t.on("close",()=>o()),n.on("close",()=>o()),t.pipe(n),n.pipe(t)});return e.on("tlsClientError",t=>{s.logger.warn(`tls handshake error: ${t.message}`)}),await new Promise((t,n)=>{let r=o=>{n(new Error(`TLS listener could not bind ${s.listenHost}:${s.listenPort}: ${o.message}`))};e.once("error",r),e.listen({host:s.listenHost,port:s.listenPort},()=>{e.off("error",r),t()})}),e.on("error",t=>{s.logger.warn(`tls terminator error: ${t.message}`)}),e}function gw(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 mw(){process.title="hydra-acp-daemon";let{installGlobalTlsTrust:s}=await Promise.resolve().then(()=>(Hn(),fu));s();let e=await an(),t=await li(),n=await Lu(e,t);process.stdout.write(`hydra-acp daemon listening on ${e.daemon.host}:${e.daemon.port}
|
|
200
200
|
`);let r=1e4,o=!1,i=async()=>{o&&(process.stderr.write(`Second signal received; exiting immediately.
|
|
201
201
|
`),process.exit(1)),o=!0,process.stdout.write(`Shutting down...
|
|
202
202
|
`);let a=setTimeout(()=>{process.stderr.write(`Graceful shutdown did not complete within ${r}ms; forcing exit.
|
|
203
203
|
`),process.exit(1)},r);a.unref();try{await n.shutdown()}catch(d){process.stderr.write(`shutdown failed: ${d instanceof Error?d.message:String(d)}
|
|
204
|
-
`)}clearTimeout(a),process.exit(0)};process.on("SIGINT",()=>{i()}),process.on("SIGTERM",()=>{i()}),process.on("SIGHUP",()=>{})}
|
|
205
|
-
`),
|
|
204
|
+
`)}clearTimeout(a),process.exit(0)};process.on("SIGINT",()=>{i()}),process.on("SIGTERM",()=>{i()}),process.on("SIGHUP",()=>{})}mw().catch(s=>{let e=s instanceof Error?s.stack??s.message:String(s);process.stderr.write(`hydra-acp-daemon: ${e}
|
|
205
|
+
`),bi(e).catch(()=>{}).finally(()=>process.exit(1))});
|