@hydra-acp/cli 0.1.178 → 0.1.179
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +127 -127
- package/dist/daemon.js +9 -9
- package/package.json +1 -1
package/dist/daemon.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var hu=Object.defineProperty;var On=(s,e)=>()=>(s&&(e=s(s=0)),e);var yu=(s,e)=>{for(var t in e)hu(s,t,{get:e[t],enumerable:!0})};import*as U from"path";import*as Qs from"os";function F(s){let e=Qs.homedir();return e?s===e?"~":s.startsWith(e+"/")?"~"+s.slice(e.length):s:s}function ku(){if(process.env.VITEST)return"vitest";if(process.versions.bun||typeof globalThis.Bun<"u")return"bun";if(process.env.JEST_WORKER_ID!==void 0)return"jest";if(process.env.NODE_TEST_CONTEXT!==void 0)return"node:test"}function B(){let s=process.env[wu];if(s&&s.length>0)return U.resolve(s);let e=ku();if(e)throw new Error(`HYDRA_ACP_HOME is unset under a test runner (${e}); refusing to fall back to ~/.hydra-acp. The harness must set HYDRA_ACP_HOME \u2014 vitest.setup.ts does this, but \`bun test\` bypasses the vitest config and does not. Run the suite with \`npx vitest run\`, not \`bun test\`.`);return U.join(Qs.homedir(),".hydra-acp")}var wu,R,Y=On(()=>{"use strict";wu="HYDRA_ACP_HOME";R={home:B,config:()=>U.join(B(),"config.json"),authToken:()=>U.join(B(),"auth-token"),remotes:()=>U.join(B(),"remotes.json"),peers:()=>U.join(B(),"peers.json"),pidFile:()=>U.join(B(),"daemon.pid"),logFile:()=>U.join(B(),"daemon.log"),currentLogFile:()=>U.join(B(),"current.log"),registryCache:()=>U.join(B(),"registry.json"),themesDir:()=>U.join(B(),"themes"),ttySessionDir:()=>U.join(B(),"tty"),ttySessionFile:s=>U.join(B(),"tty",s),agentsDir:()=>U.join(B(),"agents"),agentLogFile:s=>U.join(B(),"agents","logs",`${s}.log`),agentInstallDir:(s,e,t)=>U.join(B(),"agents",e,s,t),agentNpmInstallDir:(s,e,t)=>U.join(B(),"agents",e,s,t,`node${process.versions.modules}`),sessionsDir:()=>U.join(B(),"sessions"),sessionDir:s=>U.join(B(),"sessions",s),sessionFile:s=>U.join(B(),"sessions",s,"meta.json"),historyFile:s=>U.join(B(),"sessions",s,"history.jsonl"),historyArchiveFile:(s,e)=>U.join(B(),"sessions",s,`history.jsonl.${e}`),toolsDir:s=>U.join(B(),"sessions",s,"tools"),toolBlobFile:(s,e)=>U.join(B(),"sessions",s,"tools",e),queueFile:s=>U.join(B(),"sessions",s,"queue.ndjson"),tombstonesDir:()=>U.join(B(),"sessions",".tombstones"),tombstoneAgentDir:s=>U.join(B(),"sessions",".tombstones",encodeURIComponent(s)),tombstoneFile:(s,e)=>U.join(B(),"sessions",".tombstones",encodeURIComponent(s),encodeURIComponent(e)),extensionsDir:()=>U.join(B(),"extensions"),extensionLogDir:s=>U.join(B(),"extensions",s),extensionLogFile:s=>U.join(B(),"extensions",s,"current.log"),extensionPidFile:s=>U.join(B(),"extensions",s,"extension.pid"),transformersDir:()=>U.join(B(),"transformers"),transformerLogDir:s=>U.join(B(),"transformers",s),transformerLogFile:s=>U.join(B(),"transformers",s,"current.log"),transformerPidFile:s=>U.join(B(),"transformers",s,"transformer.pid"),transformerState:(s,e)=>U.join(B(),"sessions",s,"transformer-state",e),tuiHistoryFile:s=>U.join(B(),"sessions",s,"prompt-history"),globalTuiHistoryFile:()=>U.join(B(),"prompt-history"),tuiLogFile:()=>U.join(B(),"tui.log"),shimWireLogFile:()=>U.join(B(),"shim-wire.log")}});import*as ce from"fs/promises";import*as Qo from"fs";import*as Pe from"path";import{randomBytes as bu}from"crypto";async function ue(s,e,t={}){let r=(t.pretty??!0?JSON.stringify(e,null,2):JSON.stringify(e))+`
|
|
3
|
-
`;await Su(s,r,t)}async function Su(s,e,t={}){let n=await Iu(s),r=Au(n);await ce.mkdir(r,{recursive:!0});let o=`${n}.tmp-${process.pid}-${Cu()}`;try{let i={encoding:"utf8"};t.mode!==void 0&&(i.mode=t.mode),await ce.writeFile(o,e,i),await ce.rename(o,n)}catch(i){throw await ce.unlink(o).catch(()=>{}),i}if(t.mode!==void 0)try{Qo.chmodSync(n,t.mode)}catch{}}async function Iu(s){let e;try{e=await ce.lstat(s)}catch(r){if(r.code==="ENOENT")return s;throw r}if(!e.isSymbolicLink())return s;let t=await ce.readlink(s),n=Pe.isAbsolute(t)?t:Pe.resolve(Pe.dirname(s),t);try{let r=await ce.realpath(Pe.dirname(n));return Pe.join(r,Pe.basename(n))}catch(r){if(r.code==="ENOENT")return n;throw r}}async function oe(s){let e;try{e=await ce.readFile(s,"utf8")}catch(t){if(t.code==="ENOENT")return;throw t}if(e.trim().length!==0)try{return JSON.parse(e)}catch{return}}function Au(s){let e=s.lastIndexOf("/");return e<=0?".":s.slice(0,e)}function Cu(){return bu(4).toString("hex")}var Oe=On(()=>{"use strict"});function Hs(s,e){return`${s}:${e}`}var Mc=On(()=>{"use strict";Y();Oe()});var jc={};yu(jc,{_resetForTests:()=>
|
|
3
|
+
`;await Su(s,r,t)}async function Su(s,e,t={}){let n=await Iu(s),r=Au(n);await ce.mkdir(r,{recursive:!0});let o=`${n}.tmp-${process.pid}-${Cu()}`;try{let i={encoding:"utf8"};t.mode!==void 0&&(i.mode=t.mode),await ce.writeFile(o,e,i),await ce.rename(o,n)}catch(i){throw await ce.unlink(o).catch(()=>{}),i}if(t.mode!==void 0)try{Qo.chmodSync(n,t.mode)}catch{}}async function Iu(s){let e;try{e=await ce.lstat(s)}catch(r){if(r.code==="ENOENT")return s;throw r}if(!e.isSymbolicLink())return s;let t=await ce.readlink(s),n=Pe.isAbsolute(t)?t:Pe.resolve(Pe.dirname(s),t);try{let r=await ce.realpath(Pe.dirname(n));return Pe.join(r,Pe.basename(n))}catch(r){if(r.code==="ENOENT")return n;throw r}}async function oe(s){let e;try{e=await ce.readFile(s,"utf8")}catch(t){if(t.code==="ENOENT")return;throw t}if(e.trim().length!==0)try{return JSON.parse(e)}catch{return}}function Au(s){let e=s.lastIndexOf("/");return e<=0?".":s.slice(0,e)}function Cu(){return bu(4).toString("hex")}var Oe=On(()=>{"use strict"});function Hs(s,e){return`${s}:${e}`}var Mc=On(()=>{"use strict";Y();Oe()});var jc={};yu(jc,{_resetForTests:()=>lh,clearPin:()=>$o,fetchPeerFingerprint:()=>ch,formatFingerprint:()=>$c,getPin:()=>ah,installGlobalTlsTrust:()=>No,loadPinsFromPeerStore:()=>Fo,loadPinsFromStore:()=>dh,setPin:()=>Mn,sha256Hex:()=>Oo,wsTlsOptions:()=>Do});import{createHash as th}from"crypto";import*as _c from"tls";import{Agent as nh,Dispatcher as sh,buildConnector as rh,getGlobalDispatcher as oh,setGlobalDispatcher as ih}from"undici";function Mn(s,e,t){kt.set(Hs(s,e),Fc(t))}function $o(s,e){kt.delete(Hs(s,e))}function ah(s,e){return kt.get(Hs(s,e))}function dh(s){kt.clear();for(let e of s.list())e.entry.pinnedFingerprint&&Mn(e.host,e.port,e.entry.pinnedFingerprint)}function Fo(s){for(let e of s.list())e.pinnedFingerprint&&Mn(e.host,e.port,e.pinnedFingerprint)}async function ch(s,e,t={}){let n=t.timeoutMs??1e4;return new Promise((r,o)=>{let i=_c.connect({host:s,port:e,servername:s,rejectUnauthorized:!1,autoSelectFamily:!0}),a=!1,d=(u,l)=>{if(!a){a=!0,clearTimeout(c);try{i.destroy()}catch{}u?o(u):l&&r(l)}},c=setTimeout(()=>{d(new Error(`TLS connect to ${s}:${e} timed out`))},n);i.once("secureConnect",()=>{let u=i.getPeerCertificate(!1);if(!u||!u.raw){d(new Error(`${s}:${e} did not present a TLS certificate`));return}d(null,Oo(u.raw))}),i.once("error",u=>d(u))})}function Oo(s){return th("sha256").update(s).digest("hex")}function $c(s){let e=Fc(s),t=e.match(/.{2}/g);return t?t.join(":"):e}function Fc(s){return s.replace(/:/g,"").toLowerCase()}function No(){if(_o)return;_o=!0;let s=oh(),e=new nh({connect:rh({rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(n,r)=>Nc(n,r)})}),t=new sh;t.dispatch=(n,r)=>{let o=uh(n.origin);return(o&&Oc(o)?e:s).dispatch(n,r)},t.close=(()=>Promise.all([e.close(),s.close()]).then(()=>{})),t.destroy=(n=>Promise.all([e.destroy(n??null),s.destroy(n??null)]).then(()=>{})),ih(t)}function uh(s){if(!s)return null;try{return new URL(String(s)).hostname}catch{return null}}function Oc(s){for(let e of kt.keys())if(Dc(e)?.host===s)return!0;return!1}function Nc(s,e){if(!e||!e.raw)return new Error(`TLS peer ${s} did not present a certificate`);let t=Oo(e.raw);for(let[n,r]of kt.entries()){let o=Dc(n);if(o&&o.host===s&&r===t)return}return new Error(`TLS pin mismatch for ${s} (cert sha256 ${$c(t)})`)}function Dc(s){let e=s.lastIndexOf(":");if(e<0)return null;let t=s.slice(0,e),n=Number(s.slice(e+1));return Number.isInteger(n)?{host:t,port:n}:null}function Do(s){return Oc(s)?{rejectUnauthorized:!1,autoSelectFamily:!0,checkServerIdentity:(e,t)=>Nc(e,t)}:{autoSelectFamily:!0}}function lh(){kt.clear(),_o=!1}var kt,_o,_n=On(()=>{"use strict";Mc();kt=new Map,_o=!1});Y();import*as Ze from"fs/promises";import{homedir as or}from"os";import{z as I}from"zod";Y();import*as bt from"fs/promises";function Ys(){let s=new Uint8Array(32);crypto.getRandomValues(s);let e="";for(let t of s)e+=t.toString(16).padStart(2,"0");return`hydra_token_${e}`}async function vu(){try{let e=(await bt.readFile(R.authToken(),"utf8")).trim();return e.length>0?e:void 0}catch(s){if(s.code==="ENOENT")return;throw s}}async function Xs(s){await bt.mkdir(R.home(),{recursive:!0}),await bt.writeFile(R.authToken(),s+`
|
|
4
4
|
`,{encoding:"utf8",mode:384})}async function Ko(){let s=await vu();if(s)return s;let e=Ys();return await Xs(e),process.stderr.write(`hydra-acp: initialized ${R.authToken()} with a fresh service token.
|
|
5
|
-
`),e}Oe();import*as Xo from"fs/promises";import*as Yt from"os";import*as Ne from"path";var ee="read by the daemon, which loads config.json at startup",Yo={daemon:{reload:"restart",overlay:"partial",overlayNote:"only changes which daemon this client dials; a daemon started from here still binds config.json's host/port. Use `home` for a separate daemon",nested:!0},agents:{reload:"live",overlay:"inert",overlayNote:ee},agentOverrides:{reload:"live",overlay:"inert",overlayNote:ee},registry:{reload:"live",overlay:"inert",overlayNote:ee},npmRegistry:{reload:"live",overlay:"inert",overlayNote:ee},defaultAgent:{reload:"live",overlay:"effective"},defaultCwd:{reload:"live",overlay:"effective"},sessionDefaults:{reload:"live",overlay:"partial",overlayNote:"applies to WS session/new and child_session/spawn; POST /v1/sessions has no model/mode/effort field to apply any of it to"},synopsisAgent:{reload:"warn",overlay:"inert",overlayNote:ee},synopsisModel:{reload:"warn",overlay:"inert",overlayNote:ee},compaction:{reload:"warn",overlay:"inert",overlayNote:ee},defaultTransformers:{reload:"warn",overlay:"inert",overlayNote:ee},disableWorkspaceSnapshots:{reload:"warn",overlay:"inert",overlayNote:ee},compressToolContent:{reload:"warn",overlay:"inert",overlayNote:ee},extensions:{reload:"warn",overlay:"inert",overlayNote:ee},transformers:{reload:"warn",overlay:"inert",overlayNote:ee},tui:{reload:"client",overlay:"effective"},sessionListColdLimit:{reload:"client",overlay:"effective"}},Ru={host:{reload:"restart",overlay:"inert"},port:{reload:"restart",overlay:"inert"},publicHost:{reload:"restart",overlay:"inert"},tls:{reload:"restart",overlay:"inert"},scrubEnv:{reload:"live",overlay:"inert",overlayNote:ee},logLevel:{reload:"warn",overlay:"inert",overlayNote:ee},sessionIdleTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:ee},nonInteractiveOrphanTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:ee},sessionHistoryMaxEntries:{reload:"warn",overlay:"inert",overlayNote:ee},sessionHistoryArchiveMaxBytes:{reload:"warn",overlay:"inert",overlayNote:ee},sessionHistoryArchiveTiers:{reload:"warn",overlay:"inert",overlayNote:ee},agentStderrTailBytes:{reload:"warn",overlay:"inert",overlayNote:ee},agentSyncIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:ee},sessionGcIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:ee},sessionGcMaxAgeDays:{reload:"warn",overlay:"inert",overlayNote:ee}};function Zs(s){return Yo[s]??{reload:"restart",overlay:"inert"}}function er(s){return Ru[s]??{reload:"restart",overlay:"inert"}}function tr(){let s=[];for(let[e,t]of Object.entries(Yo))t.overlay!=="effective"&&s.push({key:e,effect:t.overlay,note:t.overlayNote??ee});return s}var xu=".hydra-acp.json",nr="home",Eu=64,Ay=tr().map(s=>s.key);function Tu(s){return s==="~"?Yt.homedir():s.startsWith("~/")?Ne.join(Yt.homedir(),s.slice(2)):s.startsWith("$HOME/")?Ne.join(Yt.homedir(),s.slice(6)):s}function sr(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function rr(s,e){let t={...s};for(let[n,r]of Object.entries(e)){let o=t[n];t[n]=sr(o)&&sr(r)?rr(o,r):r}return t}async function Pu(s,e=Yt.homedir()){let t=[],n=[],r=Ne.resolve(e),o=Ne.resolve(s);for(let i=0;i<Eu;i+=1){let a=Ne.join(o,xu),d;try{d=await Xo.readFile(a,"utf8")}catch{d=void 0}if(d!==void 0)try{let u=JSON.parse(d);sr(u)?t.push({file:a,data:u}):n.push({file:a,key:"",message:"expected a JSON object; ignoring this file"})}catch(u){n.push({file:a,key:"",message:`is not valid JSON (${u.message}); ignoring this file`})}if(o===r)break;let c=Ne.dirname(o);if(c===o)break;o=c}return t.reverse(),{layers:t,notices:n}}function Mu(s){let e=new Map(tr().map(n=>[n.key,n])),t=[];for(let n of s)for(let r of Object.keys(n.data)){let o=e.get(r);if(!o)continue;let i=o.effect==="partial"?`\`${r}\` ${o.note}`:`\`${r}\` is ${o.note}, so it has no effect in a directory config`;t.push({file:n.file,key:r,message:i})}return t}async function _u(s=process.cwd()){let{layers:e,notices:t}=await Pu(s);t.push(...Mu(e));let n={};for(let i of e)n=rr(n,i.data);let r,o=n[nr];return typeof o=="string"&&o.length>0?r=Ne.resolve(Tu(o)):o!==void 0&&t.push({file:e[e.length-1].file,key:nr,message:"`home` must be a non-empty string; ignoring it"}),delete n[nr],{layers:e,notices:t,merged:n,...r!==void 0?{homeRequest:r}:{}}}function $u(s,e){let t=s[e];return typeof t=="string"&&t.length>0?t:void 0}function Fu(s,e){let t=s[e];if(t===null||typeof t!="object"||Array.isArray(t))return;let n={};for(let[r,o]of Object.entries(t)){if(o===null||typeof o!="object"||Array.isArray(o))continue;let i={};for(let[a,d]of Object.entries(o))typeof d=="string"&&(i[a]=d);Object.keys(i).length>0&&(n[r]=i)}return Object.keys(n).length>0?n:void 0}async function Xt(s){let e={};try{e=(await _u(s)).merged}catch{return{}}let t=$u(e,"defaultAgent"),n=Fu(e,"sessionDefaults");return{...t!==void 0?{agentId:t}:{},...n!==void 0?{configDefaults:n}:{}}}var ti="https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",Ou=I.object({cert:I.string(),key:I.string()}),St=55514,Nu=I.object({host:I.string().default("127.0.0.1"),port:I.number().int().positive().default(St),logLevel:I.enum(["debug","info","warn","error"]).default("info"),tls:Ou.optional(),sessionIdleTimeoutSeconds:I.number().int().nonnegative().default(3600),nonInteractiveOrphanTimeoutSeconds:I.number().int().nonnegative().default(180),sessionHistoryMaxEntries:I.number().int().positive().default(1e4),sessionHistoryArchiveMaxBytes:I.number().int().nonnegative().default(1e7),sessionHistoryArchiveTiers:I.number().int().positive().default(10),agentStderrTailBytes:I.number().int().positive().default(4096),publicHost:I.string().optional(),agentSyncIntervalMinutes:I.number().nonnegative().default(60),scrubEnv:I.array(I.string()).default([]),sessionGcIntervalMinutes:I.number().nonnegative().default(60),sessionGcMaxAgeDays:I.number().positive().default(2)}),Du=I.object({url:I.string().url().default(ti),ttlHours:I.number().positive().default(24),pinned:I.boolean().default(!1)}),ju=I.object({extends:I.string().optional(),name:I.string().optional(),description:I.string().optional(),command:I.string().optional(),args:I.array(I.string()).optional(),env:I.record(I.string()).optional()}),Hu=I.object({packageSpec:I.string().optional(),extraArgs:I.array(I.string()).optional(),env:I.record(I.string()).optional()}),Lu=I.enum(["enter","alt-enter","shift-enter","ctrl-enter","alt-b","alt-f","alt-n","alt-tab","shift-tab","tab","up","down","left","right","home","end","backspace","alt-backspace","delete","ctrl-a","ctrl-b","ctrl-c","ctrl-d","ctrl-e","ctrl-f","ctrl-g","ctrl-k","ctrl-l","ctrl-n","ctrl-o","ctrl-p","ctrl-q","ctrl-r","ctrl-s","ctrl-u","ctrl-v","ctrl-t","ctrl-w","ctrl-x","ctrl-x-ctrl-e","ctrl-y","ctrl-underscore","alt-underscore","escape"]),Uu=I.union([I.string(),I.object({field:I.string().optional(),text:I.string().optional(),script:I.string().optional(),refreshMs:I.number().int().positive().optional(),maxWidth:I.number().int().positive().optional(),minWidth:I.number().int().nonnegative().optional(),truncate:I.boolean().optional(),priority:I.number().optional(),prefix:I.string().optional(),suffix:I.string().optional(),separator:I.string().optional(),style:I.string().optional(),onClick:I.string().optional(),onDoubleClick:I.string().optional()}).strict()]),Bu=I.object({id:I.string().min(1),script:I.string().min(1),refreshMs:I.number().int().positive().optional(),title:I.string().optional(),cap:I.number().int().positive().optional()}).strict(),Wu=I.union([I.string(),Bu]),Zo=I.array(Uu);function ir(s,e){return I.object({left:Zo.default(s),right:Zo.default(e)}).default({})}var qu=["status",{field:"elapsed",separator:" "},"sessionId","queued","scroll"],zu=["usage"],Ju=[],Vu=["helpHint"],Gu=["cwd","title"],Ku=["agentModel"],Qu=I.object({composer:I.object({top:ir(qu,zu),bottom:ir(Ju,Vu),hintTurns:I.number().int().nonnegative().nullable().default(3)}).default({}),sessionbar:ir(Gu,Ku),scriptRefreshMs:I.number().int().positive().default(5e3),repaintThrottleMs:I.number().int().nonnegative().default(1e3),maxScrollbackLines:I.number().int().positive().default(1e4),mouse:I.boolean().default(!0),inAppSelection:I.boolean().optional(),selectionClipboard:I.enum(["primary","clipboard","both"]).default("both"),openFileCommand:I.union([I.string(),I.array(I.string())]).optional(),openFileInTerminal:I.boolean().optional(),logMaxBytes:I.number().int().positive().default(5*1024*1024),cwdColumnMaxWidth:I.number().int().positive().default(32),progressIndicator:I.boolean().default(!0),terminalHost:I.union([I.boolean(),I.enum(["auto","paseo","herdr","tmux"])]).default(!0),launcherModeWhenHosted:I.boolean().default(!1),skipPermissions:I.boolean().default(!1),defaultEnterAction:I.enum(["enqueue","amend"]).default("amend"),showThoughts:I.boolean().default(!0),ambiguousWidth:I.enum(["auto","narrow","wide"]).default("auto"),toolContent:I.enum(["inline","references"]).default("references"),diffContextLines:I.number().int().min(0).default(3),promptHistoryMaxEntries:I.number().int().positive().default(2e3),maxToolItems:I.number().int().nonnegative().default(5),maxPlanItems:I.number().int().nonnegative().default(5),sidebar:I.object({enabled:I.boolean().default(!1),width:I.number().int().positive().optional(),border:I.enum(["none","rule","frame"]).default("frame"),gadgets:I.array(Wu).default(["activity","sessions","tasks","context","queue","todo","files","git","resources","info","tools"])}).default({}),showFileUpdates:I.enum(["none","edit","diff"]).default("edit"),sessionColumns:I.array(I.enum(["session","upstream","host","state","agent","model","age","cwd","title","cost"])).nonempty().optional(),hotkeys:I.record(Lu,I.object({command:I.union([I.string(),I.array(I.string())])})).default({}),theme:I.union([I.string(),I.record(I.string(),I.unknown())]).optional(),themeBackground:I.string().optional()}),ei=I.string().min(1).regex(/^[A-Za-z0-9._-]+$/,"extension name must be filename-safe"),Yu=I.object({command:I.array(I.string()).default([]),args:I.array(I.string()).default([]),env:I.record(I.string()).default({}),enabled:I.boolean().default(!0)}),Xu=I.object({command:I.array(I.string()).default([]),args:I.array(I.string()).default([]),env:I.record(I.string()).default({}),enabled:I.boolean().default(!0)}),Zu=I.object({daemon:Nu.default({}),registry:Du.default({url:ti,ttlHours:24,pinned:!1}),agents:I.record(I.string(),ju).default({}),agentOverrides:I.record(I.string(),Hu).default({}),defaultAgent:I.string().default("opencode"),sessionDefaults:I.record(I.string(),I.record(I.string(),I.string())).default({}),synopsisAgent:I.string().optional(),synopsisModel:I.string().optional(),compaction:I.object({agent:I.string().optional(),model:I.string().optional(),tailK:I.number().int().nonnegative().default(20),maxIterations:I.number().int().positive().default(3),contextFraction:I.number().min(0).max(1).default(.5),hardCeilingFraction:I.number().min(0).max(1).default(.85),absoluteFallback:I.number().int().positive().default(2e5),idleBeforePromptMs:I.number().int().nonnegative().default(3e5),modelContextWindows:I.record(I.string(),I.number().int().positive()).default({})}).default({}),defaultCwd:I.string().default("~"),disableWorkspaceSnapshots:I.boolean().optional(),compressToolContent:I.boolean().default(!0),sessionListColdLimit:I.number().int().nonnegative().default(20),extensions:I.record(ei,Yu).default({}),transformers:I.record(ei,Xu).default({}),defaultTransformers:I.array(I.string()).default([]),npmRegistry:I.string().url().optional(),tui:Qu.default({})});function ni(s){return Object.entries(s.extensions).map(([e,t])=>({name:e,...t}))}function si(s){return Object.entries(s.transformers).map(([e,t])=>({name:e,...t}))}async function ar(){return await el(),await oe(R.config())??{}}async function el(){let s;try{s=await Ze.lstat(R.config())}catch(e){if(e.code==="ENOENT")return;throw e}if(s.isSymbolicLink())try{await Ze.stat(R.config())}catch(e){if(e.code!=="ENOENT")throw e;let t=await Ze.readlink(R.config()).catch(()=>"<unknown>");throw new Error(`config.json at ${R.config()} is a broken symlink (-> ${t}); its target is missing. Refusing to treat this as "no config" and overwrite it. Restore the target (e.g. decrypt/check out your dotfiles) or remove the dangling link.`)}}async function tl(){let s=await ar(),e=s.daemon,t=e&&typeof e.authToken=="string"?e.authToken:void 0;if(!t)return;let n=!1;try{await Ze.access(R.authToken()),n=!0}catch(r){if(r.code!=="ENOENT")throw r}if(n)throw new Error(`Auth token present in both ${R.authToken()} and ${R.config()} (daemon.authToken). Remove daemon.authToken from config.json to resolve.`);await Xs(t),delete e.authToken,Object.keys(e).length===0&&delete s.daemon,await ue(R.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated auth token from ${R.config()} to ${R.authToken()}.
|
|
5
|
+
`),e}Oe();import*as Xo from"fs/promises";import*as Yt from"os";import*as Ne from"path";var ee="read by the daemon, which loads config.json at startup",Yo={daemon:{reload:"restart",overlay:"partial",overlayNote:"only changes which daemon this client dials; a daemon started from here still binds config.json's host/port. Use `home` for a separate daemon",nested:!0},agents:{reload:"live",overlay:"inert",overlayNote:ee},agentOverrides:{reload:"live",overlay:"inert",overlayNote:ee},registry:{reload:"live",overlay:"inert",overlayNote:ee},npmRegistry:{reload:"live",overlay:"inert",overlayNote:ee},defaultAgent:{reload:"live",overlay:"effective"},defaultCwd:{reload:"live",overlay:"effective"},sessionDefaults:{reload:"live",overlay:"partial",overlayNote:"applies to WS session/new and child_session/spawn; POST /v1/sessions has no model/mode/effort field to apply any of it to"},synopsisAgent:{reload:"warn",overlay:"inert",overlayNote:ee},synopsisModel:{reload:"warn",overlay:"inert",overlayNote:ee},compaction:{reload:"warn",overlay:"inert",overlayNote:ee},defaultTransformers:{reload:"warn",overlay:"inert",overlayNote:ee},disableWorkspaceSnapshots:{reload:"warn",overlay:"inert",overlayNote:ee},compressToolContent:{reload:"warn",overlay:"inert",overlayNote:ee},extensions:{reload:"warn",overlay:"inert",overlayNote:ee},transformers:{reload:"warn",overlay:"inert",overlayNote:ee},tui:{reload:"client",overlay:"effective"},sessionListColdLimit:{reload:"client",overlay:"effective"}},Ru={host:{reload:"restart",overlay:"inert"},port:{reload:"restart",overlay:"inert"},publicHost:{reload:"restart",overlay:"inert"},tls:{reload:"restart",overlay:"inert"},scrubEnv:{reload:"live",overlay:"inert",overlayNote:ee},logLevel:{reload:"warn",overlay:"inert",overlayNote:ee},sessionIdleTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:ee},nonInteractiveOrphanTimeoutSeconds:{reload:"warn",overlay:"inert",overlayNote:ee},sessionHistoryMaxEntries:{reload:"warn",overlay:"inert",overlayNote:ee},sessionHistoryArchiveMaxBytes:{reload:"warn",overlay:"inert",overlayNote:ee},sessionHistoryArchiveTiers:{reload:"warn",overlay:"inert",overlayNote:ee},agentStderrTailBytes:{reload:"warn",overlay:"inert",overlayNote:ee},agentSyncIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:ee},sessionGcIntervalMinutes:{reload:"warn",overlay:"inert",overlayNote:ee},sessionGcMaxAgeDays:{reload:"warn",overlay:"inert",overlayNote:ee}};function Zs(s){return Yo[s]??{reload:"restart",overlay:"inert"}}function er(s){return Ru[s]??{reload:"restart",overlay:"inert"}}function tr(){let s=[];for(let[e,t]of Object.entries(Yo))t.overlay!=="effective"&&s.push({key:e,effect:t.overlay,note:t.overlayNote??ee});return s}var xu=".hydra-acp.json",nr="home",Eu=64,Cy=tr().map(s=>s.key);function Tu(s){return s==="~"?Yt.homedir():s.startsWith("~/")?Ne.join(Yt.homedir(),s.slice(2)):s.startsWith("$HOME/")?Ne.join(Yt.homedir(),s.slice(6)):s}function sr(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function rr(s,e){let t={...s};for(let[n,r]of Object.entries(e)){let o=t[n];t[n]=sr(o)&&sr(r)?rr(o,r):r}return t}async function Pu(s,e=Yt.homedir()){let t=[],n=[],r=Ne.resolve(e),o=Ne.resolve(s);for(let i=0;i<Eu;i+=1){let a=Ne.join(o,xu),d;try{d=await Xo.readFile(a,"utf8")}catch{d=void 0}if(d!==void 0)try{let u=JSON.parse(d);sr(u)?t.push({file:a,data:u}):n.push({file:a,key:"",message:"expected a JSON object; ignoring this file"})}catch(u){n.push({file:a,key:"",message:`is not valid JSON (${u.message}); ignoring this file`})}if(o===r)break;let c=Ne.dirname(o);if(c===o)break;o=c}return t.reverse(),{layers:t,notices:n}}function Mu(s){let e=new Map(tr().map(n=>[n.key,n])),t=[];for(let n of s)for(let r of Object.keys(n.data)){let o=e.get(r);if(!o)continue;let i=o.effect==="partial"?`\`${r}\` ${o.note}`:`\`${r}\` is ${o.note}, so it has no effect in a directory config`;t.push({file:n.file,key:r,message:i})}return t}async function _u(s=process.cwd()){let{layers:e,notices:t}=await Pu(s);t.push(...Mu(e));let n={};for(let i of e)n=rr(n,i.data);let r,o=n[nr];return typeof o=="string"&&o.length>0?r=Ne.resolve(Tu(o)):o!==void 0&&t.push({file:e[e.length-1].file,key:nr,message:"`home` must be a non-empty string; ignoring it"}),delete n[nr],{layers:e,notices:t,merged:n,...r!==void 0?{homeRequest:r}:{}}}function $u(s,e){let t=s[e];return typeof t=="string"&&t.length>0?t:void 0}function Fu(s,e){let t=s[e];if(t===null||typeof t!="object"||Array.isArray(t))return;let n={};for(let[r,o]of Object.entries(t)){if(o===null||typeof o!="object"||Array.isArray(o))continue;let i={};for(let[a,d]of Object.entries(o))typeof d=="string"&&(i[a]=d);Object.keys(i).length>0&&(n[r]=i)}return Object.keys(n).length>0?n:void 0}async function Xt(s){let e={};try{e=(await _u(s)).merged}catch{return{}}let t=$u(e,"defaultAgent"),n=Fu(e,"sessionDefaults");return{...t!==void 0?{agentId:t}:{},...n!==void 0?{configDefaults:n}:{}}}var ti="https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",Ou=I.object({cert:I.string(),key:I.string()}),St=55514,Nu=I.object({host:I.string().default("127.0.0.1"),port:I.number().int().positive().default(St),logLevel:I.enum(["debug","info","warn","error"]).default("info"),tls:Ou.optional(),sessionIdleTimeoutSeconds:I.number().int().nonnegative().default(3600),nonInteractiveOrphanTimeoutSeconds:I.number().int().nonnegative().default(180),sessionHistoryMaxEntries:I.number().int().positive().default(1e4),sessionHistoryArchiveMaxBytes:I.number().int().nonnegative().default(1e7),sessionHistoryArchiveTiers:I.number().int().positive().default(10),agentStderrTailBytes:I.number().int().positive().default(4096),publicHost:I.string().optional(),agentSyncIntervalMinutes:I.number().nonnegative().default(60),scrubEnv:I.array(I.string()).default([]),sessionGcIntervalMinutes:I.number().nonnegative().default(60),sessionGcMaxAgeDays:I.number().positive().default(2)}),Du=I.object({url:I.string().url().default(ti),ttlHours:I.number().positive().default(24),pinned:I.boolean().default(!1)}),ju=I.object({extends:I.string().optional(),name:I.string().optional(),description:I.string().optional(),command:I.string().optional(),args:I.array(I.string()).optional(),env:I.record(I.string()).optional()}),Hu=I.object({packageSpec:I.string().optional(),extraArgs:I.array(I.string()).optional(),env:I.record(I.string()).optional()}),Lu=I.enum(["enter","alt-enter","shift-enter","ctrl-enter","alt-b","alt-f","alt-n","alt-tab","shift-tab","tab","up","down","left","right","home","end","backspace","alt-backspace","delete","ctrl-a","ctrl-b","ctrl-c","ctrl-d","ctrl-e","ctrl-f","ctrl-g","ctrl-k","ctrl-l","ctrl-n","ctrl-o","ctrl-p","ctrl-q","ctrl-r","ctrl-s","ctrl-u","ctrl-v","ctrl-t","ctrl-w","ctrl-x","ctrl-x-ctrl-e","ctrl-y","ctrl-underscore","alt-underscore","escape"]),Uu=I.union([I.string(),I.object({field:I.string().optional(),text:I.string().optional(),script:I.string().optional(),refreshMs:I.number().int().positive().optional(),maxWidth:I.number().int().positive().optional(),minWidth:I.number().int().nonnegative().optional(),truncate:I.boolean().optional(),priority:I.number().optional(),prefix:I.string().optional(),suffix:I.string().optional(),separator:I.string().optional(),style:I.string().optional(),onClick:I.string().optional(),onDoubleClick:I.string().optional()}).strict()]),Bu=I.object({id:I.string().min(1),script:I.string().min(1),refreshMs:I.number().int().positive().optional(),title:I.string().optional(),cap:I.number().int().positive().optional()}).strict(),Wu=I.union([I.string(),Bu]),Zo=I.array(Uu);function ir(s,e){return I.object({left:Zo.default(s),right:Zo.default(e)}).default({})}var qu=["status",{field:"elapsed",separator:" "},"sessionId","queued","scroll"],zu=["usage"],Ju=[],Vu=["helpHint"],Gu=["cwd","title"],Ku=["agentModel"],Qu=I.object({composer:I.object({top:ir(qu,zu),bottom:ir(Ju,Vu),hintTurns:I.number().int().nonnegative().nullable().default(3)}).default({}),sessionbar:ir(Gu,Ku),scriptRefreshMs:I.number().int().positive().default(5e3),repaintThrottleMs:I.number().int().nonnegative().default(1e3),maxScrollbackLines:I.number().int().positive().default(1e4),mouse:I.boolean().default(!0),inAppSelection:I.boolean().optional(),selectionClipboard:I.enum(["primary","clipboard","both"]).default("both"),openFileCommand:I.union([I.string(),I.array(I.string())]).optional(),openFileInTerminal:I.boolean().optional(),logMaxBytes:I.number().int().positive().default(5*1024*1024),cwdColumnMaxWidth:I.number().int().positive().default(32),progressIndicator:I.boolean().default(!0),terminalHost:I.union([I.boolean(),I.enum(["auto","paseo","herdr","tmux"])]).default(!0),launcherModeWhenHosted:I.boolean().default(!1),skipPermissions:I.boolean().default(!1),defaultEnterAction:I.enum(["enqueue","amend"]).default("amend"),showThoughts:I.boolean().default(!0),ambiguousWidth:I.enum(["auto","narrow","wide"]).default("auto"),toolContent:I.enum(["inline","references"]).default("references"),diffContextLines:I.number().int().min(0).default(3),promptHistoryMaxEntries:I.number().int().positive().default(2e3),maxToolItems:I.number().int().nonnegative().default(5),maxPlanItems:I.number().int().nonnegative().default(5),sidebar:I.object({enabled:I.boolean().default(!1),width:I.number().int().positive().optional(),border:I.enum(["none","rule","frame"]).default("frame"),gadgets:I.array(Wu).default(["activity","sessions","tasks","context","queue","todo","files","git","resources","info","tools"])}).default({}),showFileUpdates:I.enum(["none","edit","diff"]).default("edit"),sessionColumns:I.array(I.enum(["session","upstream","host","state","agent","model","age","cwd","title","cost"])).nonempty().optional(),hotkeys:I.record(Lu,I.object({command:I.union([I.string(),I.array(I.string())])})).default({}),theme:I.union([I.string(),I.record(I.string(),I.unknown())]).optional(),themeBackground:I.string().optional()}),ei=I.string().min(1).regex(/^[A-Za-z0-9._-]+$/,"extension name must be filename-safe"),Yu=I.object({command:I.array(I.string()).default([]),args:I.array(I.string()).default([]),env:I.record(I.string()).default({}),enabled:I.boolean().default(!0)}),Xu=I.object({command:I.array(I.string()).default([]),args:I.array(I.string()).default([]),env:I.record(I.string()).default({}),enabled:I.boolean().default(!0)}),Zu=I.object({daemon:Nu.default({}),registry:Du.default({url:ti,ttlHours:24,pinned:!1}),agents:I.record(I.string(),ju).default({}),agentOverrides:I.record(I.string(),Hu).default({}),defaultAgent:I.string().default("opencode"),sessionDefaults:I.record(I.string(),I.record(I.string(),I.string())).default({}),synopsisAgent:I.string().optional(),synopsisModel:I.string().optional(),compaction:I.object({agent:I.string().optional(),model:I.string().optional(),tailK:I.number().int().nonnegative().default(20),maxIterations:I.number().int().positive().default(3),contextFraction:I.number().min(0).max(1).default(.5),hardCeilingFraction:I.number().min(0).max(1).default(.85),absoluteFallback:I.number().int().positive().default(2e5),idleBeforePromptMs:I.number().int().nonnegative().default(3e5),modelContextWindows:I.record(I.string(),I.number().int().positive()).default({})}).default({}),defaultCwd:I.string().default("~"),disableWorkspaceSnapshots:I.boolean().optional(),compressToolContent:I.boolean().default(!0),sessionListColdLimit:I.number().int().nonnegative().default(20),extensions:I.record(ei,Yu).default({}),transformers:I.record(ei,Xu).default({}),defaultTransformers:I.array(I.string()).default([]),npmRegistry:I.string().url().optional(),tui:Qu.default({})});function ni(s){return Object.entries(s.extensions).map(([e,t])=>({name:e,...t}))}function si(s){return Object.entries(s.transformers).map(([e,t])=>({name:e,...t}))}async function ar(){return await el(),await oe(R.config())??{}}async function el(){let s;try{s=await Ze.lstat(R.config())}catch(e){if(e.code==="ENOENT")return;throw e}if(s.isSymbolicLink())try{await Ze.stat(R.config())}catch(e){if(e.code!=="ENOENT")throw e;let t=await Ze.readlink(R.config()).catch(()=>"<unknown>");throw new Error(`config.json at ${R.config()} is a broken symlink (-> ${t}); its target is missing. Refusing to treat this as "no config" and overwrite it. Restore the target (e.g. decrypt/check out your dotfiles) or remove the dangling link.`)}}async function tl(){let s=await ar(),e=s.daemon,t=e&&typeof e.authToken=="string"?e.authToken:void 0;if(!t)return;let n=!1;try{await Ze.access(R.authToken()),n=!0}catch(r){if(r.code!=="ENOENT")throw r}if(n)throw new Error(`Auth token present in both ${R.authToken()} and ${R.config()} (daemon.authToken). Remove daemon.authToken from config.json to resolve.`);await Xs(t),delete e.authToken,Object.keys(e).length===0&&delete s.daemon,await ue(R.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated auth token from ${R.config()} to ${R.authToken()}.
|
|
6
6
|
`)}async function nl(){let s=await ar(),e=s.defaultModels&&typeof s.defaultModels=="object"&&!Array.isArray(s.defaultModels)?s.defaultModels:void 0;if(!e)return;let t=s.sessionDefaults&&typeof s.sessionDefaults=="object"&&!Array.isArray(s.sessionDefaults)?s.sessionDefaults:{};for(let[n,r]of Object.entries(e)){if(typeof r!="string")continue;let o=t[n]&&typeof t[n]=="object"&&!Array.isArray(t[n])?t[n]:{};o.model===void 0&&(o.model=r),t[n]=o}s.sessionDefaults=t,delete s.defaultModels,await ue(R.config(),s,{mode:384}),process.stderr.write(`hydra-acp: migrated defaultModels to sessionDefaults in ${R.config()}.
|
|
7
|
-
`)}async function Zt(){return await tl(),await nl(),Zu.parse(await ar())}function le(s){return s==="~"||s==="$HOME"?or():s.startsWith("~/")?or()+s.slice(1):s.startsWith("$HOME/")?or()+s.slice(5):s}import*as cu from"fs";import*as Ge from"fs/promises";import*as uu from"net";import*as Gt from"path";import*as lu from"tls";import
|
|
7
|
+
`)}async function Zt(){return await tl(),await nl(),Zu.parse(await ar())}function le(s){return s==="~"||s==="$HOME"?or():s.startsWith("~/")?or()+s.slice(1):s.startsWith("$HOME/")?or()+s.slice(5):s}import*as cu from"fs";import*as Ge from"fs/promises";import*as uu from"net";import*as Gt from"path";import*as lu from"tls";import dy from"fastify";import cy from"@fastify/websocket";var ri="acp.v1";function oi(s,e){return s.has(ri)?ri:!1}import au from"pino";import uy from"pino-roll";var sl={herdr:["HERDR_PANE_ID","HERDR_TAB_ID","HERDR_WORKSPACE_ID","HERDR_STARTUP_CWD"],tmux:["TMUX_PANE"],zellij:["ZELLIJ_PANE_ID","ZELLIJ_SESSION_NAME"],wezterm:["WEZTERM_PANE"],kitty:["KITTY_WINDOW_ID"],screen:["STY"],iterm2:["ITERM_SESSION_ID"],paseo:["PASEO_TERMINAL_ID","PASEO_ACTIVITY_TOKEN"],hydra:["HYDRA_TAB_LABEL"]},ii="HYDRA_ACP_SESSION",rl=[ii],ol=[...Object.values(sl).flat(),...rl];function Nn(s,e){return s?{...e??{},[ii]:s}:e}var ai=[];function dr(s){ai=s?[...s]:[]}function il(s,e){return e.endsWith("*")?s.startsWith(e.slice(0,-1)):s===e}function al(){return[...ol,...ai]}function Dn(s=process.env){let e=al(),t={};for(let[n,r]of Object.entries(s))r!==void 0&&(e.some(o=>il(n,o))||(t[n]=r));return t}Y();import*as fe from"fs/promises";import{createHash as dl}from"crypto";import{gzip as cl,gunzip as ul}from"zlib";import{promisify as di}from"util";var ci=di(cl),ll=di(ul),ui=/^[A-Za-z0-9_-]+$/,fl=/^[a-f0-9]{64}$/,cr=!0;function li(s){cr=s}function jn(s,e){return ui.test(s)?e===void 0||fl.test(e):!1}function Hn(s,e){return`${R.toolBlobFile(s,e)}.gz`}async function ur(s,e){if(!jn(s))return null;let t=dl("sha256").update(e,"utf8").digest("hex"),n=Hn(s,t),r=R.toolBlobFile(s,t);for(let a of[n,r])try{return await fe.access(a),t}catch{}await fe.mkdir(R.toolsDir(s),{recursive:!0});let o=cr?n:r,i=cr?await ci(Buffer.from(e,"utf8")):Buffer.from(e,"utf8");return await fe.writeFile(o,i,{mode:384,flag:"wx"}).catch(async a=>{if(a.code!=="EEXIST")throw a}),t}async function en(s,e){if(!jn(s,e))return null;try{let t=await fe.readFile(Hn(s,e));return(await ll(t)).toString("utf8")}catch{}try{return await fe.readFile(R.toolBlobFile(s,e),"utf8")}catch{return null}}async function fi(s,e){if(!jn(s,e))return null;try{return await fe.readFile(Hn(s,e))}catch{}try{let t=await fe.readFile(R.toolBlobFile(s,e));return await ci(t)}catch{return null}}async function pi(s,e,t){if(!jn(s,e))return;let n=Hn(s,e);try{await fe.access(n);return}catch{}await fe.mkdir(R.toolsDir(s),{recursive:!0}),await fe.writeFile(n,t,{mode:384,flag:"wx"}).catch(r=>{if(r.code!=="EEXIST")throw r})}async function gi(s){ui.test(s)&&await fe.rm(R.toolsDir(s),{recursive:!0,force:!0}).catch(()=>{})}Y();import*as Ri from"fs/promises";import*as Un from"path";import{z as L}from"zod";Oe();Y();import*as hi from"fs";import*as ye from"fs/promises";import*as et from"path";import{spawn as yi}from"child_process";import{Readable as pl}from"stream";function De(){let s=process.platform==="darwin"?"darwin":process.platform==="linux"?"linux":process.platform==="win32"?"windows":void 0,e=process.arch==="arm64"?"aarch64":process.arch==="x64"?"x86_64":void 0;if(!(!s||!e))return`${s}-${e}`}function pr(s,e=De()){if(e)return s[e]}var It=s=>{process.stderr.write(s+`
|
|
8
8
|
`)};function gr(s){It=s??(e=>process.stderr.write(e+`
|
|
9
9
|
`))}async function wi(s){if(!s.target.archive)throw new Error(`Agent ${s.agentId} has no archive URL for ${De()??"this platform"}`);if(!s.target.cmd)throw new Error(`Agent ${s.agentId} has no cmd in its binary target`);let e=De();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=R.agentInstallDir(s.agentId,e,s.version),n=et.resolve(t,s.target.cmd);if(await fr(n))return n;if(await gl({agentId:s.agentId,version:s.version,archiveUrl:s.target.archive,installDir:t,onProgress:s.onProgress}),!await fr(n))throw new Error(`Agent ${s.agentId}: extracted archive did not contain ${s.target.cmd} (looked in ${t})`);return process.platform!=="win32"&&await ye.chmod(n,493).catch(()=>{}),n}async function gl(s){await ye.mkdir(et.dirname(s.installDir),{recursive:!0});let e=await ye.mkdtemp(`${s.installDir}.partial-`);try{It(`hydra-acp: downloading ${s.agentId} from ${s.archiveUrl}`);let t=await ml({url:s.archiveUrl,dir:e,agentId:s.agentId,version:s.version,onProgress:s.onProgress});It(`hydra-acp: extracting ${s.agentId}`),At(s.onProgress,{phase:"extract",agentId:s.agentId,version:s.version}),await yl(t,e),await ye.unlink(t).catch(()=>{});try{await ye.rename(e,s.installDir)}catch(n){let r=n;if((r.code==="EEXIST"||r.code==="ENOTEMPTY")&&await fr(s.installDir)){await ye.rm(e,{recursive:!0,force:!0}).catch(()=>{}),At(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw n}It(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),At(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await ye.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function At(s,e){if(s)try{s(e)}catch{}}async function ml(s){let e=hl(s.url),t=et.join(s.dir,e),n=await fetch(s.url,{redirect:"follow"});if(!n.ok||!n.body)throw new Error(`Failed to download ${s.url}: HTTP ${n.status} ${n.statusText}`);let r=Number(n.headers.get("content-length")??"0"),o=hi.createWriteStream(t),i=pl.fromWeb(n.body);At(s.onProgress,{phase:"download_start",agentId:s.agentId,version:s.version,totalBytes:r});let a=0,d=Date.now(),c=0,u=2e3,l=150;return i.on("data",p=>{a+=p.length;let m=Date.now();m-c>=l&&(c=m,At(s.onProgress,{phase:"download_progress",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r})),m-d>=u&&(d=m,It(mi(s.agentId,a,r)))}),await new Promise((p,m)=>{i.on("error",m),o.on("error",m),o.on("finish",()=>p()),i.pipe(o)}),It(mi(s.agentId,a,r,!0)),At(s.onProgress,{phase:"download_done",agentId:s.agentId,version:s.version,receivedBytes:a,totalBytes:r}),t}function mi(s,e,t,n=!1){let r=(e/1e6).toFixed(1);if(t>0){let i=(t/1e6).toFixed(1),a=Math.min(100,Math.floor(e/t*100));return`hydra-acp: ${n?"downloaded":"downloading"} ${s} ${r}/${i} MB (${a}%)`}return`hydra-acp: ${n?"downloaded":"downloading"} ${s} ${r} MB`}function hl(s){let e=new URL(s);return et.posix.basename(e.pathname)||"archive"}async function yl(s,e){let t=s.toLowerCase();if(t.endsWith(".tar.gz")||t.endsWith(".tgz")||t.endsWith(".tar")){await lr("tar",["-xf",s,"-C",e]);return}if(t.endsWith(".zip")){if(await wl("unzip")){await lr("unzip",["-q",s,"-d",e]);return}await lr("tar",["-xf",s,"-C",e]);return}throw new Error(`Unsupported archive format: ${s}`)}function lr(s,e){return new Promise((t,n)=>{let r=yi(s,e,{stdio:["ignore","ignore","inherit"]});r.on("error",n),r.on("exit",(o,i)=>{if(o===0){t();return}n(new Error(`${s} ${e.join(" ")} exited with ${o!==null?`code ${o}`:`signal ${i}`}`))})})}async function wl(s){return new Promise(e=>{let t=process.platform==="win32"?"where":"which",n=yi(t,[s],{stdio:"ignore"});n.on("error",()=>e(!1)),n.on("exit",r=>e(r===0))})}async function fr(s){try{return await ye.access(s),!0}catch{return!1}}Y();import*as Ie from"fs/promises";import*as je from"path";import{spawn as kl}from"child_process";var hr=s=>{process.stderr.write(s+`
|
|
10
10
|
`)};function yr(s){hr=s??(e=>process.stderr.write(e+`
|
|
11
11
|
`))}async function vi(s){let e=De();if(!e)throw new Error(`Agent ${s.agentId}: cannot determine platform key for ${process.platform}/${process.arch}`);let t=R.agentNpmInstallDir(s.agentId,e,s.version),n=Al(s.packageSpec),r=Cl(n),o={installDir:t,packageName:n,hint:s.bin,basename:r},i=je.join(t,"node_modules",".bin",s.bin);if(await ct(i))return i;if(await ct(t)){let l=await ki(o);if(l)return l.binPath}await vl({agentId:s.agentId,version:s.version,packageSpec:s.packageSpec,installDir:t,registry:s.registry,onProgress:s.onProgress});let a=await ki(o);if(a)return a.binPath;let d=await Si(t,n),c=typeof d=="object"&&d!==null?Object.keys(d):typeof d=="string"?[r]:[],u=c.length>0?` (package declares bins: ${c.join(", ")})`:"";throw new Error(`Agent ${s.agentId}: npm install of ${s.packageSpec} did not produce bin ${s.bin} (looked in ${t}/node_modules/.bin/)${u}`)}async function vl(s){await Ie.mkdir(je.dirname(s.installDir),{recursive:!0});let e=await Ie.mkdtemp(`${s.installDir}.partial-`);try{hr(`hydra-acp: installing ${s.packageSpec} for ${s.agentId} into ${e}`),mr(s.onProgress,{phase:"install_start",agentId:s.agentId,version:s.version,packageSpec:s.packageSpec}),await Il({packageSpec:s.packageSpec,cwd:e,registry:s.registry});try{await Ie.rename(e,s.installDir)}catch(t){let n=t;if((n.code==="EEXIST"||n.code==="ENOTEMPTY")&&await ct(s.installDir)){await Ie.rm(e,{recursive:!0,force:!0}).catch(()=>{}),mr(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version});return}throw t}hr(`hydra-acp: installed ${s.agentId} to ${s.installDir}`),mr(s.onProgress,{phase:"installed",agentId:s.agentId,version:s.version})}catch(t){throw await Ie.rm(e,{recursive:!0,force:!0}).catch(()=>{}),t}}function mr(s,e){if(s)try{s(e)}catch{}}var bl=5,Sl=25;function Il(s){return bi(s,0)}async function bi(s,e){try{await new Promise((t,n)=>{let r=s.registry?["--registry",s.registry]:[],o;try{o=kl("npm",["install","--no-audit","--no-fund","--silent",...r,s.packageSpec],{cwd:s.cwd,stdio:["ignore","pipe","pipe"]})}catch(a){n(a);return}let i="";o.stdout?.on("data",a=>{}),o.stderr?.setEncoding("utf8"),o.stderr?.on("data",a=>{i=(i+a).slice(-4096)}),o.on("error",a=>{if(a.code==="ENOENT"){n(new Error("npm not found on PATH (install Node.js / npm, or use a binary-distributed agent)"));return}n(a)}),o.on("exit",(a,d)=>{if(a===0){t();return}let c=a!==null?`exit code ${a}`:`signal ${d??"unknown"}`,u=i.trim();n(new Error(u?`npm install ${s.packageSpec} failed (${c})
|
|
12
|
-
stderr: ${u}`:`npm install ${s.packageSpec} failed (${c})`))})})}catch(t){if(t.code==="ETXTBSY"&&e<bl)return await new Promise(r=>setTimeout(r,Sl*(e+1))),bi(s,e+1);throw t}}function Al(s){if(s.startsWith("@")){let t=s.indexOf("/");if(t===-1)return s;let r=s.slice(t+1).indexOf("@");return r===-1?s:s.slice(0,t+1+r)}let e=s.indexOf("@");return e<=0?s:s.slice(0,e)}function Cl(s){let e=s.lastIndexOf("/");return e===-1?s:s.slice(e+1)}async function Si(s,e){let t=je.join(s,"node_modules",e,"package.json");try{let n=await Ie.readFile(t,"utf8"),r=JSON.parse(n);return typeof r.bin=="string"||typeof r.bin=="object"&&r.bin!==null&&!Array.isArray(r.bin)?r.bin:void 0}catch{return}}async function ki(s){let e=je.join(s.installDir,"node_modules",".bin"),t=je.join(e,s.hint);if(await ct(t))return{binName:s.hint,binPath:t};let n=await Si(s.installDir,s.packageName);if(typeof n=="object"&&n!==null){let r=Object.keys(n);if(r.length===1){let o=r[0],i=je.join(e,o);if(await ct(i))return{binName:o,binPath:i}}else if(r.length>1){for(let o of[s.hint,s.basename])if(r.includes(o)){let i=je.join(e,o);if(await ct(i))return{binName:o,binPath:i}}}}if(s.basename!==s.hint){let r=je.join(e,s.basename);if(await ct(r))return{binName:s.basename,binPath:r}}}async function ct(s){try{return await Ie.access(s),!0}catch{return!1}}var Rl=L.object({package:L.string(),bin:L.string().optional(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),Ct=L.object({archive:L.string().url().optional(),cmd:L.string().optional(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),xl=L.object({"darwin-aarch64":Ct.optional(),"darwin-x86_64":Ct.optional(),"linux-aarch64":Ct.optional(),"linux-x86_64":Ct.optional(),"windows-x86_64":Ct.optional(),"windows-aarch64":Ct.optional()}),El=L.object({package:L.string(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),Tl=L.object({command:L.string(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),Pl=L.object({command:L.string().optional(),url:L.string().optional(),description:L.string().optional()}),Ml=L.object({npx:Rl.optional(),binary:xl.optional(),uvx:El.optional(),exec:Tl.optional()}),_l=L.object({id:L.string(),name:L.string(),version:L.string().optional(),description:L.string().optional(),authors:L.array(L.string()).optional(),license:L.string().optional(),icon:L.string().optional(),repository:L.string().optional(),website:L.string().optional(),distribution:Ml,onboarding:Pl.optional(),requiredEnv:L.array(L.string().min(1)).optional()}),Ii=8;function xi(s){return s.installId??s.id}function kr(s){let e=s.extendsChain;return e&&e.length>0?e[e.length-1]:s.id}function tn(s,e){if(s)for(let t of e.extendsChain??[e.id]){let n=s[t];if(n!==void 0)return{value:n,from:t}}}var Ai=L.object({version:L.string(),agents:L.array(_l),extensions:L.array(L.unknown()).optional()}),Ln=class{constructor(e,t={}){this.config=e;this.options=t}config;options;cache;async load(){if(this.cache&&(this.isPinned()||this.isFresh(this.cache.fetchedAt)))return this.cache.data;let e=await this.readDiskCache();if(e&&(this.isPinned()||this.isFresh(e.fetchedAt)))return this.cache=e,e.data;try{let t=await this.fetchFromNetwork();return this.cache=t,await this.writeDiskCache(t),t.data}catch(t){if(e){let n=this.options.onStaleFallback;if(n)try{n(t,Date.now()-e.fetchedAt)}catch{}return this.cache=e,e.data}throw t}}async refresh(){let e=await this.fetchFromNetwork();return this.cache=e,await this.writeDiskCache(e),e.data}lastFetchedAt(){return this.cache?.fetchedAt}setConfig(e){this.config=e}async getAgent(e){return this.resolveAgent(e,[])}async resolveAgent(e,t){let n=this.findLocalDef(e);if(n){if(n.def.extends===void 0)return{...wr(n.id,n.def),extendsChain:[n.id]};if(t.includes(n.id))throw new Error(`agent ${n.id}: extends cycle (${[...t,n.id].join(" -> ")})`);if(t.length+1>=Ii)throw new Error(`agent ${n.id}: extends chain deeper than ${Ii} (${[...t,n.id].join(" -> ")})`);let c=await this.resolveAgent(n.def.extends,[...t,n.id]);if(!c)throw new Error(`agent ${n.id}: extends ${JSON.stringify(n.def.extends)}, which is not a known agent`);return this.applyOverride(Fl(n.id,n.def,c))}let r=await this.load(),o=r.agents.find(c=>c.id===e);if(o)return this.applyOverride(o);let i=r.agents.find(c=>vr(c)===e);if(i)return this.applyOverride(i);let a=e.toLowerCase(),d=r.agents.find(c=>c.id.toLowerCase()===`${a}-acp`);if(d)return this.applyOverride(d);if(a.length>0){let c=r.agents.filter(u=>u.id.toLowerCase().startsWith(a));if(c.length===1)return this.applyOverride(c[0])}}findLocalDef(e){let t=this.config.agents??{},n=t[e];if(n)return{id:e,def:n};let r=e.toLowerCase();for(let[o,i]of Object.entries(t))if(o.toLowerCase()===`${r}-acp`)return{id:o,def:i}}localAgents(){return Object.entries(this.config.agents??{}).filter(([,e])=>e.extends===void 0).map(([e,t])=>wr(e,t))}async resolvedLocalAgents(){let e=[];for(let t of Object.keys(this.config.agents??{}))try{let n=await this.resolveAgent(t,[]);n&&e.push(n)}catch(n){this.options.onResolveError?.(t,n)}return e}applyOverride(e){let t=e.extendsChain?e:{...e,extendsChain:[e.id]},n=this.config.agentOverrides?.[t.id];if(!n)return t;let r=t.distribution,o=t.version,i=t.installId;return n.packageSpec&&r.npx&&(o=Ol(n.packageSpec),i=t.id,r={...r,npx:{...r.npx,package:n.packageSpec}}),n.extraArgs?.length&&(r=$l(r,n.extraArgs)),n.env&&Object.keys(n.env).length>0&&(r=Ei(r,{env:n.env})),r===t.distribution?t:{...t,version:o,installId:i,distribution:r}}isPinned(){return this.config.registry?.pinned===!0}isFresh(e){let t=Date.now()-e,n=this.config.registry.ttlHours*60*60*1e3;return t<n}async fetchFromNetwork(){let e=await fetch(this.config.registry.url);if(!e.ok)throw new Error(`Registry fetch failed: HTTP ${e.status}`);let t=await e.json(),n=Ai.parse(t),r={fetchedAt:Date.now(),raw:t,data:n},o=this.options.onFetched;return o&&Promise.resolve().then(()=>o(n)).catch(()=>{}),r}async readDiskCache(){let e=await oe(R.registryCache());if(!(!e||typeof e.fetchedAt!="number"||e.data===void 0))try{let t=Ai.parse(e.data);return{fetchedAt:e.fetchedAt,raw:e.data,data:t}}catch{return}}async writeDiskCache(e){await ue(R.registryCache(),{fetchedAt:e.fetchedAt,data:e.raw})}};function wr(s,e){return{id:s,name:e.name??s,description:e.description,version:"local",distribution:{exec:{command:le(e.command??s),args:e.args?.map(le),env:e.env}}}}function Ei(s,e){let t=e.args?.map(le),n=r=>({...r,...t?{args:t}:{},...e.env?{env:{...r.env,...e.env}}:{}});return{...s.npx?{npx:n(s.npx)}:{},...s.uvx?{uvx:n(s.uvx)}:{},...s.exec?{exec:n(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([r,o])=>[r,o&&n(o)]))}:{}}}function $l(s,e){let t=n=>({...n,args:[...n.args??[],...e]});return{...s.npx?{npx:t(s.npx)}:{},...s.uvx?{uvx:t(s.uvx)}:{},...s.exec?{exec:t(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([n,r])=>[n,r&&t(r)]))}:{}}}function Fl(s,e,t){let n=e.command!==void 0;return{...t,id:s,name:e.name??t.name,description:e.description??t.description,version:n?"local":t.version,distribution:n?wr(s,e).distribution:Ei(t.distribution,e),installId:n?s:t.installId??t.id,extendsChain:[s,...t.extendsChain??[t.id]]}}function Ol(s){let e=s.lastIndexOf("@"),n=(e>0?s.slice(e+1):"").replace(/[^a-zA-Z0-9._-]/g,"_");return n.length>0?`pin-${n}`:"pinned"}function vr(s){let e=s.distribution.npx?.package;if(!e)return;let t=e.lastIndexOf("/"),n=t===-1?e:e.slice(t+1),r=n.lastIndexOf("@");return r<=0?n:n.slice(0,r)}async function Rt(s){let e=typeof s.resolvedLocalAgents=="function"?await s.resolvedLocalAgents():typeof s.localAgents=="function"?s.localAgents():[],t;try{t=await s.load()}catch(i){if(e.length===0)throw i;t={version:"local-only",agents:[]}}let n=new Set(e.map(i=>i.id)),r=[...e,...t.agents.filter(i=>!n.has(i.id))],o=await Promise.all(r.map(async i=>({id:i.id,name:i.name,version:i.version,description:i.description,distributions:Object.keys(i.distribution),installed:await br(i),...i.extendsChain?{extendsChain:i.extendsChain}:{},source:n.has(i.id)?"local":"registry",...i.onboarding?{onboarding:i.onboarding}:{}})));return{version:t.version,fetchedAt:s.lastFetchedAt(),agents:o}}async function br(s){let e=De();if(!e)return"no";let t=s.version??"current",n=xi(s);if(s.distribution.exec)return"yes";if(s.distribution.binary){let r=pr(s.distribution.binary,e);if(r?.cmd){let o=Un.resolve(R.agentInstallDir(n,e,t),r.cmd);if(await Ci(o))return"yes"}}if(s.distribution.npx){let r=s.distribution.npx,o=r.bin??vr(s)??r.package,i=R.agentNpmInstallDir(n,e,t),a=Un.join(i,"node_modules",".bin",o);if(await Ci(a))return"yes"}return!s.distribution.npx&&!s.distribution.binary&&s.distribution.uvx?"lazy":"no"}async function Ci(s){try{return await Ri.access(s),!0}catch{return!1}}async function Re(s,e=[],t={}){let n=s.version??"current",r=xi(s);if(s.distribution.npx){let o=s.distribution.npx,i=e.length>0?e:o.args??[];if(process.env.HYDRA_ACP_SKIP_NPM_PREFETCH)return{command:"npx",args:["-y",o.package,...i],env:o.env??{},version:n,installId:r};let a=o.bin??vr(s)??o.package,d=t.onInstallProgress;return{command:await vi({agentId:r,version:n,packageSpec:o.package,bin:a,registry:t.npmRegistry,onProgress:d?u=>d({source:"npm",...u}):void 0}),args:i,env:o.env??{},version:n,installId:r}}if(s.distribution.binary){let o=pr(s.distribution.binary);if(!o)throw new Error(`Agent ${s.id} has no binary distribution for ${De()??"this platform"}.`);let i=t.onInstallProgress,a=await wi({agentId:r,version:n,target:o,onProgress:i?c=>i({source:"binary",...c}):void 0}),d=e.length>0?e:o.args??[];return{command:a,args:d,env:o.env??{},version:n,installId:r}}if(s.distribution.uvx){let o=s.distribution.uvx,i=e.length>0?e:o.args??[];return{command:"uvx",args:[o.package,...i],env:o.env??{},version:n,installId:r}}if(s.distribution.exec){let o=s.distribution.exec,i=e.length>0?e:o.args??[];return{command:o.command,args:i,env:o.env??{},version:n,installId:r}}throw new Error(`Agent ${s.id} has no usable distribution method.`)}import{spawn as Ll}from"child_process";import*as qn from"fs";import*as zi from"path";var x={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603,AuthRequired:-32e3,SessionNotFound:-32001,NotAuthorisedToAttach:-32002,MultiClientNotSupported:-32003,AgentNotInstalled:-32005,BundleAlreadyImported:-32010,PermissionDenied:-32011,AlreadyAttached:-32012,StreamNotEnabled:-32013,SessionClosing:-32014};import{z as G}from"zod";var Ti=G.object({protocolVersion:G.number().optional(),clientCapabilities:G.record(G.unknown()).optional(),clientInfo:G.object({name:G.string(),version:G.string().optional()}).optional()}),Nl=G.enum(["full","pending_only","none","after_message"]),Pi=G.object({cwd:G.string(),mcpServers:G.array(G.unknown()).optional(),_meta:G.record(G.unknown()).optional()}),Mi=G.object({upstreamSessionId:G.string(),agentId:G.string(),cwd:G.string(),title:G.string().optional(),agentArgs:G.array(G.string()).optional()}),_i=G.object({sessionId:G.string(),historyPolicy:Nl.default("full"),afterMessageId:G.string().optional(),afterSeq:G.number().optional(),clientId:G.string().optional(),clientInfo:G.object({name:G.string(),version:G.string().optional()}).optional(),_meta:G.record(G.unknown()).optional()});import{z as D}from"zod";var $i=D.object({sessionId:D.string()}),Fi=D.object({cwd:D.string().optional(),cursor:D.string().optional()}),Sr=D.object({used:D.number().optional(),size:D.number().optional(),costAmount:D.number().optional(),costCurrency:D.string().optional()}),aw=D.object({sessionId:D.string(),upstreamSessionId:D.string().optional(),cwd:D.string(),workspace:D.object({path:D.string(),sourceCwd:D.string(),label:D.string(),provider:D.string(),snapshot:D.string().optional(),vcs:D.record(D.string(),D.string()).optional()}).optional(),workspaceError:D.string().optional(),title:D.string().optional(),agentId:D.string().optional(),currentModel:D.string().optional(),currentUsage:Sr.optional(),importedFromMachine:D.string().optional(),importedFromUpstreamSessionId:D.string().optional(),parentSessionId:D.string().optional(),forkedFromSessionId:D.string().optional(),forkedFromMessageId:D.string().optional(),originatingClient:D.object({name:D.string(),version:D.string().optional()}).optional(),interactive:D.boolean().optional(),priority:D.number().int().nonnegative().optional(),updatedAt:D.string(),attachedClients:D.number().int().nonnegative(),status:D.enum(["warm","cold"]).default("warm"),busy:D.boolean().default(!1),awaitingInput:D.boolean().default(!1),armedTasks:D.number().int().nonnegative().optional(),armedSince:D.number().int().positive().optional(),compactionState:D.any().optional(),agentPid:D.number().int().positive().optional(),forkSynthesisState:D.enum(["running","failed"]).optional(),_meta:D.record(D.unknown()).optional()}),Dl=D.object({sessionId:D.string(),cwd:D.string(),title:D.string().optional(),updatedAt:D.string().optional(),_meta:D.record(D.unknown()).optional()}),dw=D.object({sessions:D.array(Dl),nextCursor:D.string().optional()});function Bn(s,e){let t={attachedClients:s.attachedClients,status:s.status,busy:s.busy,awaitingInput:s.awaitingInput};return s.cwd!==void 0&&(t.cwd=s.cwd),s.workspace!==void 0&&(t.workspaceInfo=s.workspace),s.workspaceError!==void 0&&(t.workspaceError=s.workspaceError),s.title!==void 0&&(t.title=s.title),s.agentId!==void 0&&(t.agentId=s.agentId),s.upstreamSessionId!==void 0&&(t.upstreamSessionId=s.upstreamSessionId),s.currentModel!==void 0&&(t.currentModel=s.currentModel),s.currentUsage!==void 0&&(t.currentUsage=s.currentUsage),s.importedFromMachine!==void 0&&(t.importedFromMachine=s.importedFromMachine),s.importedFromUpstreamSessionId!==void 0&&(t.importedFromUpstreamSessionId=s.importedFromUpstreamSessionId),s.parentSessionId!==void 0&&(t.parentSessionId=s.parentSessionId),s.forkedFromSessionId!==void 0&&(t.forkedFromSessionId=s.forkedFromSessionId),s.forkedFromMessageId!==void 0&&(t.forkedFromMessageId=s.forkedFromMessageId),s.originatingClient!==void 0&&(t.originatingClient=s.originatingClient),s.interactive!==void 0&&(t.interactive=s.interactive),s.priority!==void 0&&s.priority>0&&(t.priority=s.priority),s.armedTasks!==void 0&&(t.armedTasks=s.armedTasks),s.armedSince!==void 0&&(t.armedSince=s.armedSince),s.compactionState!==void 0&&(t.compactionState=s.compactionState),s.forkSynthesisState!==void 0&&(t.forkSynthesisState=s.forkSynthesisState),e&&(e.clientId!==void 0&&(t.clientId=e.clientId),e.currentMode!==void 0&&(t.currentMode=e.currentMode),e.agentArgs!==void 0&&e.agentArgs.length>0&&(t.agentArgs=e.agentArgs),e.availableCommands!==void 0&&e.availableCommands.length>0&&(t.availableCommands=e.availableCommands),e.availableModes!==void 0&&e.availableModes.length>0&&(t.availableModes=e.availableModes),e.availableModels!==void 0&&e.availableModels.length>0&&(t.availableModels=e.availableModels),e.turnStartedAt!==void 0&&(t.turnStartedAt=e.turnStartedAt),e.agentCapabilities!==void 0&&(t.agentCapabilities=e.agentCapabilities),e.queue!==void 0&&e.queue.length>0&&(t.queue=e.queue),e.resurrected===!0&&(t.resurrected=!0),e.armedTaskList!==void 0&&(t.armedTaskList=e.armedTaskList)),t}function Oi(s){let e={sessionId:s.sessionId,cwd:s.cwd,updatedAt:s.updatedAt,_meta:nn(s._meta,Bn(s))};return s.title!==void 0&&(e.title=s.title),e}var ae="hydra-acp";function jl(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e={};for(let[t,n]of Object.entries(s)){if(typeof t!="string"||t.length===0||typeof n!="string")return;e[t]=n}return e}function ut(s){if(!s)return{};let e=s[ae];if(!e||typeof e!="object"||Array.isArray(e))return{};let t=e,n={};if(typeof t.upstreamSessionId=="string"&&(n.upstreamSessionId=t.upstreamSessionId),typeof t.agentId=="string"&&(n.agentId=t.agentId),typeof t.cwd=="string"&&(n.cwd=t.cwd),t.workspace!==null&&typeof t.workspace=="object"&&!Array.isArray(t.workspace)){let r=t.workspace,o={};typeof r.label=="string"&&(o.label=r.label),typeof r.from=="string"&&(o.from=r.from),r.required===!0&&(o.required=!0),typeof r.provider=="string"&&(o.provider=r.provider),n.workspace=o}if(t.workspaceInfo!==null&&typeof t.workspaceInfo=="object"&&!Array.isArray(t.workspaceInfo)){let r=t.workspaceInfo;if(typeof r.path=="string"&&typeof r.sourceCwd=="string"&&typeof r.label=="string"&&typeof r.provider=="string"){let o={path:r.path,sourceCwd:r.sourceCwd,label:r.label,provider:r.provider};if(typeof r.snapshot=="string"&&(o.snapshot=r.snapshot),r.vcs!==null&&typeof r.vcs=="object"&&!Array.isArray(r.vcs)){let i={};for(let[a,d]of Object.entries(r.vcs))typeof d=="string"&&(i[a]=d);o.vcs=i}n.workspaceInfo=o}}if(typeof t.workspaceError=="string"&&(n.workspaceError=t.workspaceError),typeof t.clientId=="string"&&(n.clientId=t.clientId),typeof t.readonly=="boolean"&&(n.readonly=t.readonly),(t.replayMode==="instant"||t.replayMode==="drip")&&(n.replayMode=t.replayMode),typeof t.dripSpeed=="number"&&t.dripSpeed>0&&(n.dripSpeed=t.dripSpeed),typeof t.historyLimit=="number"&&Number.isFinite(t.historyLimit)&&t.historyLimit>=0&&(n.historyLimit=t.historyLimit),(t.toolContent==="inline"||t.toolContent==="references")&&(n.toolContent=t.toolContent),t.detachStatus==="detached"&&(n.detachStatus=t.detachStatus),typeof t.title=="string"&&(n.title=t.title),Array.isArray(t.agentArgs)&&t.agentArgs.every(r=>typeof r=="string")&&(n.agentArgs=t.agentArgs),Array.isArray(t.transformers)&&t.transformers.every(r=>typeof r=="string")&&(n.transformers=t.transformers),t.resume){let r=Mi.safeParse(t.resume);r.success&&(n.resume=r.data)}if(typeof t.model=="string"&&(n.model=t.model),typeof t.currentModel=="string"&&(n.currentModel=t.currentModel),typeof t.currentMode=="string"&&(n.currentMode=t.currentMode),t.currentUsage){let r=Sr.safeParse(t.currentUsage);r.success&&(n.currentUsage=r.data)}if(typeof t.turnStartedAt=="number"&&t.turnStartedAt>0&&(n.turnStartedAt=t.turnStartedAt),typeof t.armedTasks=="number"&&t.armedTasks>=0&&(n.armedTasks=t.armedTasks),typeof t.armedSince=="number"&&t.armedSince>0&&(n.armedSince=t.armedSince),Array.isArray(t.armedTaskList)){let r=[];for(let o of t.armedTaskList){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;typeof i.label!="string"||typeof i.since!="number"||r.push({label:i.label,since:i.since,...typeof i.taskId=="string"?{taskId:i.taskId}:{},...typeof i.taskType=="string"?{taskType:i.taskType}:{},...typeof i.toolCallId=="string"?{toolCallId:i.toolCallId}:{}})}n.armedTaskList=r}if(Array.isArray(t.availableCommands)){let r=[];for(let o of t.availableCommands){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.name!="string")continue;let a={name:i.name};typeof i.description=="string"&&(a.description=i.description),r.push(a)}r.length>0&&(n.availableCommands=r)}if(t.prompt&&typeof t.prompt=="object"&&!Array.isArray(t.prompt)){let r=t.prompt,o={};typeof r.queueing=="boolean"&&(o.queueing=r.queueing),typeof r.cancelling=="boolean"&&(o.cancelling=r.cancelling),typeof r.updating=="boolean"&&(o.updating=r.updating),typeof r.amending=="boolean"&&(o.amending=r.amending),typeof r.pipelining=="boolean"&&(o.pipelining=r.pipelining),n.prompt=o}if(t.agents&&typeof t.agents=="object"&&!Array.isArray(t.agents)){let r=t.agents,o={};typeof r.list=="boolean"&&(o.list=r.list),typeof r.installProgress=="boolean"&&(o.installProgress=r.installProgress),n.agents=o}if(typeof t.mcpStdin=="boolean"&&(n.mcpStdin=t.mcpStdin),typeof t.interactive=="boolean"&&(n.interactive=t.interactive),typeof t.ancillary=="boolean"&&(n.ancillary=t.ancillary),t.salvaged&&typeof t.salvaged=="object"&&!Array.isArray(t.salvaged)){let r=t.salvaged;typeof r.reason=="string"&&typeof r.supersededMessageId=="string"&&(n.salvaged={reason:r.reason,supersededMessageId:r.supersededMessageId})}if(Array.isArray(t.queue)){let r=[];for(let o of t.queue){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o,a=i.originator;if(typeof i.messageId!="string"||!a||typeof a.clientId!="string"||!Array.isArray(i.prompt)||typeof i.position!="number"||typeof i.enqueuedAt!="number")continue;let d={clientId:a.clientId};typeof a.name=="string"&&(d.name=a.name),typeof a.version=="string"&&(d.version=a.version),r.push({messageId:i.messageId,originator:d,prompt:i.prompt,position:i.position,enqueuedAt:i.enqueuedAt})}r.length>0&&(n.queue=r)}if(Array.isArray(t.availableModes)){let r=[];for(let o of t.availableModes){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.id!="string")continue;let a={id:i.id};typeof i.name=="string"&&(a.name=i.name),typeof i.description=="string"&&(a.description=i.description),r.push(a)}r.length>0&&(n.availableModes=r)}if(Array.isArray(t.availableModels)){let r=[];for(let o of t.availableModels){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.modelId!="string")continue;let a={modelId:i.modelId};typeof i.name=="string"&&(a.name=i.name),typeof i.description=="string"&&(a.description=i.description),r.push(a)}r.length>0&&(n.availableModels=r)}if((t.status==="warm"||t.status==="cold")&&(n.status=t.status),typeof t.busy=="boolean"&&(n.busy=t.busy),typeof t.awaitingInput=="boolean"&&(n.awaitingInput=t.awaitingInput),typeof t.attachedClients=="number"&&(n.attachedClients=t.attachedClients),typeof t.resurrected=="boolean"&&(n.resurrected=t.resurrected),typeof t.importedFromMachine=="string"&&(n.importedFromMachine=t.importedFromMachine),typeof t.importedFromUpstreamSessionId=="string"&&(n.importedFromUpstreamSessionId=t.importedFromUpstreamSessionId),typeof t.parentSessionId=="string"&&(n.parentSessionId=t.parentSessionId),typeof t.forkedFromSessionId=="string"&&(n.forkedFromSessionId=t.forkedFromSessionId),typeof t.forkedFromMessageId=="string"&&(n.forkedFromMessageId=t.forkedFromMessageId),t.originatingClient&&typeof t.originatingClient=="object"&&!Array.isArray(t.originatingClient)&&typeof t.originatingClient.name=="string"){let r=t.originatingClient;n.originatingClient={name:r.name,...typeof r.version=="string"?{version:r.version}:{}}}if(t.agentCapabilities!==void 0&&(n.agentCapabilities=t.agentCapabilities),t.env!==void 0){let r=jl(t.env);r!==void 0&&(n.env=r)}return n}function He(s,e){if(typeof e!="number"||!Number.isFinite(e)||!s||typeof s!="object"||Array.isArray(s))return s;let t=s,n=t._meta&&typeof t._meta=="object"&&!Array.isArray(t._meta)?t._meta:{},r=n[ae],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.recordedAt=="number"?s:{...t,_meta:{...n,[ae]:{...o,recordedAt:e}}}}function Le(s,e){if(typeof e!="number"||!Number.isFinite(e)||!s||typeof s!="object"||Array.isArray(s))return s;let t=s,n=t._meta&&typeof t._meta=="object"&&!Array.isArray(t._meta)?t._meta:{},r=n[ae],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.seq=="number"?s:{...t,_meta:{...n,[ae]:{...o,seq:e}}}}function nn(s,e){return{...s??{},[ae]:e}}import{z as _}from"zod";var Ni=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.record(_.unknown()).optional()}),Wn=_.object({sessionId:_.string()}),Di=_.object({clientId:_.string(),name:_.string().optional(),version:_.string().optional()}),gw=_.object({sessionId:_.string(),messageId:_.string(),originator:Di,prompt:_.array(_.unknown()),position:_.number().int().nonnegative(),queueDepth:_.number().int().positive(),enqueuedAt:_.number()}),mw=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),hw=_.object({sessionId:_.string(),messageId:_.string(),reason:_.enum(["started","cancelled","abandoned"])}),ji=_.object({sessionId:_.string(),messageId:_.string()}),yw=_.object({cancelled:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),Hi=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),ww=_.object({updated:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),Li=_.object({sessionId:_.string(),targetMessageId:_.string(),prompt:_.array(_.unknown()),replaceQueue:_.boolean().optional(),onTargetCompleted:_.enum(["reject","send_anyway"]).optional()}),kw=_.object({amended:_.boolean(),reason:_.enum(["ok","target_completed","target_cancelled","target_not_found"]),messageId:_.string().optional()}),Ui=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.object({steering:_.object({idleBehavior:_.literal("promptRequired").optional()}).optional()}).optional()}),vw=_.object({outcome:_.enum(["injected","startedNewTurn","promptRequired","failed"]),reason:_.literal("noRunningTurn").optional(),detached:_.boolean().optional()}),bw=_.object({sessionId:_.string(),cancelledMessageId:_.string(),newMessageId:_.string(),prompt:_.array(_.unknown()),originator:Di,amendedAt:_.number()});import{z as tt}from"zod";var Aw=tt.object({agentId:tt.string(),version:tt.string(),source:tt.enum(["binary","npm"]),phase:tt.enum(["download_start","download_progress","download_done","extract","install_start","installed"]),receivedBytes:tt.number().optional(),totalBytes:tt.number().optional(),packageSpec:tt.string().optional()}),Bi="hydra-acp/agents/install_progress",xt={auth:{terminal:!0},_meta:{"terminal-auth":!0}};function Wi(s,e){let t="",n=[],r=[],o=!1,i=a=>{if(!o){o=!0;for(let d of r)d(a)}};return s.setEncoding("utf8"),s.on("data",a=>{t+=a;let d=t.indexOf(`
|
|
12
|
+
stderr: ${u}`:`npm install ${s.packageSpec} failed (${c})`))})})}catch(t){if(t.code==="ETXTBSY"&&e<bl)return await new Promise(r=>setTimeout(r,Sl*(e+1))),bi(s,e+1);throw t}}function Al(s){if(s.startsWith("@")){let t=s.indexOf("/");if(t===-1)return s;let r=s.slice(t+1).indexOf("@");return r===-1?s:s.slice(0,t+1+r)}let e=s.indexOf("@");return e<=0?s:s.slice(0,e)}function Cl(s){let e=s.lastIndexOf("/");return e===-1?s:s.slice(e+1)}async function Si(s,e){let t=je.join(s,"node_modules",e,"package.json");try{let n=await Ie.readFile(t,"utf8"),r=JSON.parse(n);return typeof r.bin=="string"||typeof r.bin=="object"&&r.bin!==null&&!Array.isArray(r.bin)?r.bin:void 0}catch{return}}async function ki(s){let e=je.join(s.installDir,"node_modules",".bin"),t=je.join(e,s.hint);if(await ct(t))return{binName:s.hint,binPath:t};let n=await Si(s.installDir,s.packageName);if(typeof n=="object"&&n!==null){let r=Object.keys(n);if(r.length===1){let o=r[0],i=je.join(e,o);if(await ct(i))return{binName:o,binPath:i}}else if(r.length>1){for(let o of[s.hint,s.basename])if(r.includes(o)){let i=je.join(e,o);if(await ct(i))return{binName:o,binPath:i}}}}if(s.basename!==s.hint){let r=je.join(e,s.basename);if(await ct(r))return{binName:s.basename,binPath:r}}}async function ct(s){try{return await Ie.access(s),!0}catch{return!1}}var Rl=L.object({package:L.string(),bin:L.string().optional(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),Ct=L.object({archive:L.string().url().optional(),cmd:L.string().optional(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),xl=L.object({"darwin-aarch64":Ct.optional(),"darwin-x86_64":Ct.optional(),"linux-aarch64":Ct.optional(),"linux-x86_64":Ct.optional(),"windows-x86_64":Ct.optional(),"windows-aarch64":Ct.optional()}),El=L.object({package:L.string(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),Tl=L.object({command:L.string(),args:L.array(L.string()).optional(),env:L.record(L.string()).optional()}),Pl=L.object({command:L.string().optional(),url:L.string().optional(),description:L.string().optional()}),Ml=L.object({npx:Rl.optional(),binary:xl.optional(),uvx:El.optional(),exec:Tl.optional()}),_l=L.object({id:L.string(),name:L.string(),version:L.string().optional(),description:L.string().optional(),authors:L.array(L.string()).optional(),license:L.string().optional(),icon:L.string().optional(),repository:L.string().optional(),website:L.string().optional(),distribution:Ml,onboarding:Pl.optional(),requiredEnv:L.array(L.string().min(1)).optional()}),Ii=8;function xi(s){return s.installId??s.id}function kr(s){let e=s.extendsChain;return e&&e.length>0?e[e.length-1]:s.id}function tn(s,e){if(s)for(let t of e.extendsChain??[e.id]){let n=s[t];if(n!==void 0)return{value:n,from:t}}}var Ai=L.object({version:L.string(),agents:L.array(_l),extensions:L.array(L.unknown()).optional()}),Ln=class{constructor(e,t={}){this.config=e;this.options=t}config;options;cache;async load(){if(this.cache&&(this.isPinned()||this.isFresh(this.cache.fetchedAt)))return this.cache.data;let e=await this.readDiskCache();if(e&&(this.isPinned()||this.isFresh(e.fetchedAt)))return this.cache=e,e.data;try{let t=await this.fetchFromNetwork();return this.cache=t,await this.writeDiskCache(t),t.data}catch(t){if(e){let n=this.options.onStaleFallback;if(n)try{n(t,Date.now()-e.fetchedAt)}catch{}return this.cache=e,e.data}throw t}}async refresh(){let e=await this.fetchFromNetwork();return this.cache=e,await this.writeDiskCache(e),e.data}lastFetchedAt(){return this.cache?.fetchedAt}setConfig(e){this.config=e}async getAgent(e){return this.resolveAgent(e,[])}async resolveAgent(e,t){let n=this.findLocalDef(e);if(n){if(n.def.extends===void 0)return{...wr(n.id,n.def),extendsChain:[n.id]};if(t.includes(n.id))throw new Error(`agent ${n.id}: extends cycle (${[...t,n.id].join(" -> ")})`);if(t.length+1>=Ii)throw new Error(`agent ${n.id}: extends chain deeper than ${Ii} (${[...t,n.id].join(" -> ")})`);let c=await this.resolveAgent(n.def.extends,[...t,n.id]);if(!c)throw new Error(`agent ${n.id}: extends ${JSON.stringify(n.def.extends)}, which is not a known agent`);return this.applyOverride(Fl(n.id,n.def,c))}let r=await this.load(),o=r.agents.find(c=>c.id===e);if(o)return this.applyOverride(o);let i=r.agents.find(c=>vr(c)===e);if(i)return this.applyOverride(i);let a=e.toLowerCase(),d=r.agents.find(c=>c.id.toLowerCase()===`${a}-acp`);if(d)return this.applyOverride(d);if(a.length>0){let c=r.agents.filter(u=>u.id.toLowerCase().startsWith(a));if(c.length===1)return this.applyOverride(c[0])}}findLocalDef(e){let t=this.config.agents??{},n=t[e];if(n)return{id:e,def:n};let r=e.toLowerCase();for(let[o,i]of Object.entries(t))if(o.toLowerCase()===`${r}-acp`)return{id:o,def:i}}localAgents(){return Object.entries(this.config.agents??{}).filter(([,e])=>e.extends===void 0).map(([e,t])=>wr(e,t))}async resolvedLocalAgents(){let e=[];for(let t of Object.keys(this.config.agents??{}))try{let n=await this.resolveAgent(t,[]);n&&e.push(n)}catch(n){this.options.onResolveError?.(t,n)}return e}applyOverride(e){let t=e.extendsChain?e:{...e,extendsChain:[e.id]},n=this.config.agentOverrides?.[t.id];if(!n)return t;let r=t.distribution,o=t.version,i=t.installId;return n.packageSpec&&r.npx&&(o=Ol(n.packageSpec),i=t.id,r={...r,npx:{...r.npx,package:n.packageSpec}}),n.extraArgs?.length&&(r=$l(r,n.extraArgs)),n.env&&Object.keys(n.env).length>0&&(r=Ei(r,{env:n.env})),r===t.distribution?t:{...t,version:o,installId:i,distribution:r}}isPinned(){return this.config.registry?.pinned===!0}isFresh(e){let t=Date.now()-e,n=this.config.registry.ttlHours*60*60*1e3;return t<n}async fetchFromNetwork(){let e=await fetch(this.config.registry.url);if(!e.ok)throw new Error(`Registry fetch failed: HTTP ${e.status}`);let t=await e.json(),n=Ai.parse(t),r={fetchedAt:Date.now(),raw:t,data:n},o=this.options.onFetched;return o&&Promise.resolve().then(()=>o(n)).catch(()=>{}),r}async readDiskCache(){let e=await oe(R.registryCache());if(!(!e||typeof e.fetchedAt!="number"||e.data===void 0))try{let t=Ai.parse(e.data);return{fetchedAt:e.fetchedAt,raw:e.data,data:t}}catch{return}}async writeDiskCache(e){await ue(R.registryCache(),{fetchedAt:e.fetchedAt,data:e.raw})}};function wr(s,e){return{id:s,name:e.name??s,description:e.description,version:"local",distribution:{exec:{command:le(e.command??s),args:e.args?.map(le),env:e.env}}}}function Ei(s,e){let t=e.args?.map(le),n=r=>({...r,...t?{args:t}:{},...e.env?{env:{...r.env,...e.env}}:{}});return{...s.npx?{npx:n(s.npx)}:{},...s.uvx?{uvx:n(s.uvx)}:{},...s.exec?{exec:n(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([r,o])=>[r,o&&n(o)]))}:{}}}function $l(s,e){let t=n=>({...n,args:[...n.args??[],...e]});return{...s.npx?{npx:t(s.npx)}:{},...s.uvx?{uvx:t(s.uvx)}:{},...s.exec?{exec:t(s.exec)}:{},...s.binary?{binary:Object.fromEntries(Object.entries(s.binary).map(([n,r])=>[n,r&&t(r)]))}:{}}}function Fl(s,e,t){let n=e.command!==void 0;return{...t,id:s,name:e.name??t.name,description:e.description??t.description,version:n?"local":t.version,distribution:n?wr(s,e).distribution:Ei(t.distribution,e),installId:n?s:t.installId??t.id,extendsChain:[s,...t.extendsChain??[t.id]]}}function Ol(s){let e=s.lastIndexOf("@"),n=(e>0?s.slice(e+1):"").replace(/[^a-zA-Z0-9._-]/g,"_");return n.length>0?`pin-${n}`:"pinned"}function vr(s){let e=s.distribution.npx?.package;if(!e)return;let t=e.lastIndexOf("/"),n=t===-1?e:e.slice(t+1),r=n.lastIndexOf("@");return r<=0?n:n.slice(0,r)}async function Rt(s){let e=typeof s.resolvedLocalAgents=="function"?await s.resolvedLocalAgents():typeof s.localAgents=="function"?s.localAgents():[],t;try{t=await s.load()}catch(i){if(e.length===0)throw i;t={version:"local-only",agents:[]}}let n=new Set(e.map(i=>i.id)),r=[...e,...t.agents.filter(i=>!n.has(i.id))],o=await Promise.all(r.map(async i=>({id:i.id,name:i.name,version:i.version,description:i.description,distributions:Object.keys(i.distribution),installed:await br(i),...i.extendsChain?{extendsChain:i.extendsChain}:{},source:n.has(i.id)?"local":"registry",...i.onboarding?{onboarding:i.onboarding}:{}})));return{version:t.version,fetchedAt:s.lastFetchedAt(),agents:o}}async function br(s){let e=De();if(!e)return"no";let t=s.version??"current",n=xi(s);if(s.distribution.exec)return"yes";if(s.distribution.binary){let r=pr(s.distribution.binary,e);if(r?.cmd){let o=Un.resolve(R.agentInstallDir(n,e,t),r.cmd);if(await Ci(o))return"yes"}}if(s.distribution.npx){let r=s.distribution.npx,o=r.bin??vr(s)??r.package,i=R.agentNpmInstallDir(n,e,t),a=Un.join(i,"node_modules",".bin",o);if(await Ci(a))return"yes"}return!s.distribution.npx&&!s.distribution.binary&&s.distribution.uvx?"lazy":"no"}async function Ci(s){try{return await Ri.access(s),!0}catch{return!1}}async function Re(s,e=[],t={}){let n=s.version??"current",r=xi(s);if(s.distribution.npx){let o=s.distribution.npx,i=e.length>0?e:o.args??[];if(process.env.HYDRA_ACP_SKIP_NPM_PREFETCH)return{command:"npx",args:["-y",o.package,...i],env:o.env??{},version:n,installId:r};let a=o.bin??vr(s)??o.package,d=t.onInstallProgress;return{command:await vi({agentId:r,version:n,packageSpec:o.package,bin:a,registry:t.npmRegistry,onProgress:d?u=>d({source:"npm",...u}):void 0}),args:i,env:o.env??{},version:n,installId:r}}if(s.distribution.binary){let o=pr(s.distribution.binary);if(!o)throw new Error(`Agent ${s.id} has no binary distribution for ${De()??"this platform"}.`);let i=t.onInstallProgress,a=await wi({agentId:r,version:n,target:o,onProgress:i?c=>i({source:"binary",...c}):void 0}),d=e.length>0?e:o.args??[];return{command:a,args:d,env:o.env??{},version:n,installId:r}}if(s.distribution.uvx){let o=s.distribution.uvx,i=e.length>0?e:o.args??[];return{command:"uvx",args:[o.package,...i],env:o.env??{},version:n,installId:r}}if(s.distribution.exec){let o=s.distribution.exec,i=e.length>0?e:o.args??[];return{command:o.command,args:i,env:o.env??{},version:n,installId:r}}throw new Error(`Agent ${s.id} has no usable distribution method.`)}import{spawn as Ll}from"child_process";import*as qn from"fs";import*as zi from"path";var x={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603,AuthRequired:-32e3,SessionNotFound:-32001,NotAuthorisedToAttach:-32002,MultiClientNotSupported:-32003,AgentNotInstalled:-32005,BundleAlreadyImported:-32010,PermissionDenied:-32011,AlreadyAttached:-32012,StreamNotEnabled:-32013,SessionClosing:-32014};import{z as G}from"zod";var Ti=G.object({protocolVersion:G.number().optional(),clientCapabilities:G.record(G.unknown()).optional(),clientInfo:G.object({name:G.string(),version:G.string().optional()}).optional()}),Nl=G.enum(["full","pending_only","none","after_message"]),Pi=G.object({cwd:G.string(),mcpServers:G.array(G.unknown()).optional(),_meta:G.record(G.unknown()).optional()}),Mi=G.object({upstreamSessionId:G.string(),agentId:G.string(),cwd:G.string(),title:G.string().optional(),agentArgs:G.array(G.string()).optional()}),_i=G.object({sessionId:G.string(),historyPolicy:Nl.default("full"),afterMessageId:G.string().optional(),afterSeq:G.number().optional(),clientId:G.string().optional(),clientInfo:G.object({name:G.string(),version:G.string().optional()}).optional(),_meta:G.record(G.unknown()).optional()});import{z as D}from"zod";var $i=D.object({sessionId:D.string()}),Fi=D.object({cwd:D.string().optional(),cursor:D.string().optional()}),Sr=D.object({used:D.number().optional(),size:D.number().optional(),costAmount:D.number().optional(),costCurrency:D.string().optional()}),dw=D.object({sessionId:D.string(),upstreamSessionId:D.string().optional(),cwd:D.string(),workspace:D.object({path:D.string(),sourceCwd:D.string(),label:D.string(),provider:D.string(),snapshot:D.string().optional(),vcs:D.record(D.string(),D.string()).optional()}).optional(),workspaceError:D.string().optional(),title:D.string().optional(),agentId:D.string().optional(),currentModel:D.string().optional(),currentUsage:Sr.optional(),importedFromMachine:D.string().optional(),importedFromUpstreamSessionId:D.string().optional(),parentSessionId:D.string().optional(),forkedFromSessionId:D.string().optional(),forkedFromMessageId:D.string().optional(),originatingClient:D.object({name:D.string(),version:D.string().optional()}).optional(),interactive:D.boolean().optional(),priority:D.number().int().nonnegative().optional(),updatedAt:D.string(),attachedClients:D.number().int().nonnegative(),status:D.enum(["warm","cold"]).default("warm"),busy:D.boolean().default(!1),awaitingInput:D.boolean().default(!1),armedTasks:D.number().int().nonnegative().optional(),armedSince:D.number().int().positive().optional(),compactionState:D.any().optional(),agentPid:D.number().int().positive().optional(),forkSynthesisState:D.enum(["running","failed"]).optional(),_meta:D.record(D.unknown()).optional()}),Dl=D.object({sessionId:D.string(),cwd:D.string(),title:D.string().optional(),updatedAt:D.string().optional(),_meta:D.record(D.unknown()).optional()}),cw=D.object({sessions:D.array(Dl),nextCursor:D.string().optional()});function Bn(s,e){let t={attachedClients:s.attachedClients,status:s.status,busy:s.busy,awaitingInput:s.awaitingInput};return s.cwd!==void 0&&(t.cwd=s.cwd),s.workspace!==void 0&&(t.workspaceInfo=s.workspace),s.workspaceError!==void 0&&(t.workspaceError=s.workspaceError),s.title!==void 0&&(t.title=s.title),s.agentId!==void 0&&(t.agentId=s.agentId),s.upstreamSessionId!==void 0&&(t.upstreamSessionId=s.upstreamSessionId),s.currentModel!==void 0&&(t.currentModel=s.currentModel),s.currentUsage!==void 0&&(t.currentUsage=s.currentUsage),s.importedFromMachine!==void 0&&(t.importedFromMachine=s.importedFromMachine),s.importedFromUpstreamSessionId!==void 0&&(t.importedFromUpstreamSessionId=s.importedFromUpstreamSessionId),s.parentSessionId!==void 0&&(t.parentSessionId=s.parentSessionId),s.forkedFromSessionId!==void 0&&(t.forkedFromSessionId=s.forkedFromSessionId),s.forkedFromMessageId!==void 0&&(t.forkedFromMessageId=s.forkedFromMessageId),s.originatingClient!==void 0&&(t.originatingClient=s.originatingClient),s.interactive!==void 0&&(t.interactive=s.interactive),s.priority!==void 0&&s.priority>0&&(t.priority=s.priority),s.armedTasks!==void 0&&(t.armedTasks=s.armedTasks),s.armedSince!==void 0&&(t.armedSince=s.armedSince),s.compactionState!==void 0&&(t.compactionState=s.compactionState),s.forkSynthesisState!==void 0&&(t.forkSynthesisState=s.forkSynthesisState),e&&(e.clientId!==void 0&&(t.clientId=e.clientId),e.currentMode!==void 0&&(t.currentMode=e.currentMode),e.agentArgs!==void 0&&e.agentArgs.length>0&&(t.agentArgs=e.agentArgs),e.availableCommands!==void 0&&e.availableCommands.length>0&&(t.availableCommands=e.availableCommands),e.availableModes!==void 0&&e.availableModes.length>0&&(t.availableModes=e.availableModes),e.availableModels!==void 0&&e.availableModels.length>0&&(t.availableModels=e.availableModels),e.turnStartedAt!==void 0&&(t.turnStartedAt=e.turnStartedAt),e.agentCapabilities!==void 0&&(t.agentCapabilities=e.agentCapabilities),e.queue!==void 0&&e.queue.length>0&&(t.queue=e.queue),e.resurrected===!0&&(t.resurrected=!0),e.armedTaskList!==void 0&&(t.armedTaskList=e.armedTaskList)),t}function Oi(s){let e={sessionId:s.sessionId,cwd:s.cwd,updatedAt:s.updatedAt,_meta:nn(s._meta,Bn(s))};return s.title!==void 0&&(e.title=s.title),e}var ae="hydra-acp";function jl(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e={};for(let[t,n]of Object.entries(s)){if(typeof t!="string"||t.length===0||typeof n!="string")return;e[t]=n}return e}function ut(s){if(!s)return{};let e=s[ae];if(!e||typeof e!="object"||Array.isArray(e))return{};let t=e,n={};if(typeof t.upstreamSessionId=="string"&&(n.upstreamSessionId=t.upstreamSessionId),typeof t.agentId=="string"&&(n.agentId=t.agentId),typeof t.cwd=="string"&&(n.cwd=t.cwd),t.workspace!==null&&typeof t.workspace=="object"&&!Array.isArray(t.workspace)){let r=t.workspace,o={};typeof r.label=="string"&&(o.label=r.label),typeof r.from=="string"&&(o.from=r.from),r.required===!0&&(o.required=!0),typeof r.provider=="string"&&(o.provider=r.provider),n.workspace=o}if(t.workspaceInfo!==null&&typeof t.workspaceInfo=="object"&&!Array.isArray(t.workspaceInfo)){let r=t.workspaceInfo;if(typeof r.path=="string"&&typeof r.sourceCwd=="string"&&typeof r.label=="string"&&typeof r.provider=="string"){let o={path:r.path,sourceCwd:r.sourceCwd,label:r.label,provider:r.provider};if(typeof r.snapshot=="string"&&(o.snapshot=r.snapshot),r.vcs!==null&&typeof r.vcs=="object"&&!Array.isArray(r.vcs)){let i={};for(let[a,d]of Object.entries(r.vcs))typeof d=="string"&&(i[a]=d);o.vcs=i}n.workspaceInfo=o}}if(typeof t.workspaceError=="string"&&(n.workspaceError=t.workspaceError),typeof t.clientId=="string"&&(n.clientId=t.clientId),typeof t.readonly=="boolean"&&(n.readonly=t.readonly),(t.replayMode==="instant"||t.replayMode==="drip")&&(n.replayMode=t.replayMode),typeof t.dripSpeed=="number"&&t.dripSpeed>0&&(n.dripSpeed=t.dripSpeed),typeof t.historyLimit=="number"&&Number.isFinite(t.historyLimit)&&t.historyLimit>=0&&(n.historyLimit=t.historyLimit),(t.toolContent==="inline"||t.toolContent==="references")&&(n.toolContent=t.toolContent),t.detachStatus==="detached"&&(n.detachStatus=t.detachStatus),typeof t.title=="string"&&(n.title=t.title),Array.isArray(t.agentArgs)&&t.agentArgs.every(r=>typeof r=="string")&&(n.agentArgs=t.agentArgs),Array.isArray(t.transformers)&&t.transformers.every(r=>typeof r=="string")&&(n.transformers=t.transformers),t.resume){let r=Mi.safeParse(t.resume);r.success&&(n.resume=r.data)}if(typeof t.model=="string"&&(n.model=t.model),typeof t.currentModel=="string"&&(n.currentModel=t.currentModel),typeof t.currentMode=="string"&&(n.currentMode=t.currentMode),t.currentUsage){let r=Sr.safeParse(t.currentUsage);r.success&&(n.currentUsage=r.data)}if(typeof t.turnStartedAt=="number"&&t.turnStartedAt>0&&(n.turnStartedAt=t.turnStartedAt),typeof t.armedTasks=="number"&&t.armedTasks>=0&&(n.armedTasks=t.armedTasks),typeof t.armedSince=="number"&&t.armedSince>0&&(n.armedSince=t.armedSince),Array.isArray(t.armedTaskList)){let r=[];for(let o of t.armedTaskList){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;typeof i.label!="string"||typeof i.since!="number"||r.push({label:i.label,since:i.since,...typeof i.taskId=="string"?{taskId:i.taskId}:{},...typeof i.taskType=="string"?{taskType:i.taskType}:{},...typeof i.toolCallId=="string"?{toolCallId:i.toolCallId}:{}})}n.armedTaskList=r}if(Array.isArray(t.availableCommands)){let r=[];for(let o of t.availableCommands){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.name!="string")continue;let a={name:i.name};typeof i.description=="string"&&(a.description=i.description),r.push(a)}r.length>0&&(n.availableCommands=r)}if(t.prompt&&typeof t.prompt=="object"&&!Array.isArray(t.prompt)){let r=t.prompt,o={};typeof r.queueing=="boolean"&&(o.queueing=r.queueing),typeof r.cancelling=="boolean"&&(o.cancelling=r.cancelling),typeof r.updating=="boolean"&&(o.updating=r.updating),typeof r.amending=="boolean"&&(o.amending=r.amending),typeof r.pipelining=="boolean"&&(o.pipelining=r.pipelining),n.prompt=o}if(t.agents&&typeof t.agents=="object"&&!Array.isArray(t.agents)){let r=t.agents,o={};typeof r.list=="boolean"&&(o.list=r.list),typeof r.installProgress=="boolean"&&(o.installProgress=r.installProgress),n.agents=o}if(typeof t.mcpStdin=="boolean"&&(n.mcpStdin=t.mcpStdin),typeof t.interactive=="boolean"&&(n.interactive=t.interactive),typeof t.ancillary=="boolean"&&(n.ancillary=t.ancillary),t.salvaged&&typeof t.salvaged=="object"&&!Array.isArray(t.salvaged)){let r=t.salvaged;typeof r.reason=="string"&&typeof r.supersededMessageId=="string"&&(n.salvaged={reason:r.reason,supersededMessageId:r.supersededMessageId})}if(Array.isArray(t.queue)){let r=[];for(let o of t.queue){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o,a=i.originator;if(typeof i.messageId!="string"||!a||typeof a.clientId!="string"||!Array.isArray(i.prompt)||typeof i.position!="number"||typeof i.enqueuedAt!="number")continue;let d={clientId:a.clientId};typeof a.name=="string"&&(d.name=a.name),typeof a.version=="string"&&(d.version=a.version),r.push({messageId:i.messageId,originator:d,prompt:i.prompt,position:i.position,enqueuedAt:i.enqueuedAt})}r.length>0&&(n.queue=r)}if(Array.isArray(t.availableModes)){let r=[];for(let o of t.availableModes){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.id!="string")continue;let a={id:i.id};typeof i.name=="string"&&(a.name=i.name),typeof i.description=="string"&&(a.description=i.description),r.push(a)}r.length>0&&(n.availableModes=r)}if(Array.isArray(t.availableModels)){let r=[];for(let o of t.availableModels){if(!o||typeof o!="object"||Array.isArray(o))continue;let i=o;if(typeof i.modelId!="string")continue;let a={modelId:i.modelId};typeof i.name=="string"&&(a.name=i.name),typeof i.description=="string"&&(a.description=i.description),r.push(a)}r.length>0&&(n.availableModels=r)}if((t.status==="warm"||t.status==="cold")&&(n.status=t.status),typeof t.busy=="boolean"&&(n.busy=t.busy),typeof t.awaitingInput=="boolean"&&(n.awaitingInput=t.awaitingInput),typeof t.attachedClients=="number"&&(n.attachedClients=t.attachedClients),typeof t.resurrected=="boolean"&&(n.resurrected=t.resurrected),typeof t.importedFromMachine=="string"&&(n.importedFromMachine=t.importedFromMachine),typeof t.importedFromUpstreamSessionId=="string"&&(n.importedFromUpstreamSessionId=t.importedFromUpstreamSessionId),typeof t.parentSessionId=="string"&&(n.parentSessionId=t.parentSessionId),typeof t.forkedFromSessionId=="string"&&(n.forkedFromSessionId=t.forkedFromSessionId),typeof t.forkedFromMessageId=="string"&&(n.forkedFromMessageId=t.forkedFromMessageId),t.originatingClient&&typeof t.originatingClient=="object"&&!Array.isArray(t.originatingClient)&&typeof t.originatingClient.name=="string"){let r=t.originatingClient;n.originatingClient={name:r.name,...typeof r.version=="string"?{version:r.version}:{}}}if(t.agentCapabilities!==void 0&&(n.agentCapabilities=t.agentCapabilities),t.env!==void 0){let r=jl(t.env);r!==void 0&&(n.env=r)}return n}function He(s,e){if(typeof e!="number"||!Number.isFinite(e)||!s||typeof s!="object"||Array.isArray(s))return s;let t=s,n=t._meta&&typeof t._meta=="object"&&!Array.isArray(t._meta)?t._meta:{},r=n[ae],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.recordedAt=="number"?s:{...t,_meta:{...n,[ae]:{...o,recordedAt:e}}}}function Le(s,e){if(typeof e!="number"||!Number.isFinite(e)||!s||typeof s!="object"||Array.isArray(s))return s;let t=s,n=t._meta&&typeof t._meta=="object"&&!Array.isArray(t._meta)?t._meta:{},r=n[ae],o=r&&typeof r=="object"&&!Array.isArray(r)?r:{};return typeof o.seq=="number"?s:{...t,_meta:{...n,[ae]:{...o,seq:e}}}}function nn(s,e){return{...s??{},[ae]:e}}import{z as _}from"zod";var Ni=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.record(_.unknown()).optional()}),Wn=_.object({sessionId:_.string()}),Di=_.object({clientId:_.string(),name:_.string().optional(),version:_.string().optional()}),mw=_.object({sessionId:_.string(),messageId:_.string(),originator:Di,prompt:_.array(_.unknown()),position:_.number().int().nonnegative(),queueDepth:_.number().int().positive(),enqueuedAt:_.number()}),hw=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),yw=_.object({sessionId:_.string(),messageId:_.string(),reason:_.enum(["started","cancelled","abandoned"])}),ji=_.object({sessionId:_.string(),messageId:_.string()}),ww=_.object({cancelled:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),Hi=_.object({sessionId:_.string(),messageId:_.string(),prompt:_.array(_.unknown())}),kw=_.object({updated:_.boolean(),reason:_.enum(["ok","not_found","already_running"])}),Li=_.object({sessionId:_.string(),targetMessageId:_.string(),prompt:_.array(_.unknown()),replaceQueue:_.boolean().optional(),onTargetCompleted:_.enum(["reject","send_anyway"]).optional()}),vw=_.object({amended:_.boolean(),reason:_.enum(["ok","target_completed","target_cancelled","target_not_found"]),messageId:_.string().optional()}),Ui=_.object({sessionId:_.string(),prompt:_.array(_.unknown()),_meta:_.object({steering:_.object({idleBehavior:_.literal("promptRequired").optional()}).optional()}).optional()}),bw=_.object({outcome:_.enum(["injected","startedNewTurn","promptRequired","failed"]),reason:_.literal("noRunningTurn").optional(),detached:_.boolean().optional()}),Sw=_.object({sessionId:_.string(),cancelledMessageId:_.string(),newMessageId:_.string(),prompt:_.array(_.unknown()),originator:Di,amendedAt:_.number()});import{z as tt}from"zod";var Cw=tt.object({agentId:tt.string(),version:tt.string(),source:tt.enum(["binary","npm"]),phase:tt.enum(["download_start","download_progress","download_done","extract","install_start","installed"]),receivedBytes:tt.number().optional(),totalBytes:tt.number().optional(),packageSpec:tt.string().optional()}),Bi="hydra-acp/agents/install_progress",xt={auth:{terminal:!0},_meta:{"terminal-auth":!0}};function Wi(s,e){let t="",n=[],r=[],o=!1,i=a=>{if(!o){o=!0;for(let d of r)d(a)}};return s.setEncoding("utf8"),s.on("data",a=>{t+=a;let d=t.indexOf(`
|
|
13
13
|
`);for(;d!==-1;){let c=t.slice(0,d).trim();if(t=t.slice(d+1),c.length>0)try{let u=JSON.parse(c);for(let l of n)l(u)}catch(u){for(let l of n)l({jsonrpc:"2.0",id:null,error:{code:x.ParseError,message:`Failed to parse ndjson line: ${u.message}`}})}d=t.indexOf(`
|
|
14
14
|
`)}}),s.on("end",()=>i()),s.on("error",a=>i(a)),e.on("error",a=>i(a)),{async send(a){if(o)throw new Error("stream is closed");let d=JSON.stringify(a)+`
|
|
15
15
|
`;await new Promise((c,u)=>{e.write(d,l=>{if(l){u(l);return}c()})})},onMessage(a){n.push(a)},onClose(a){r.push(a)},async close(){e.end(),i()}}}import{nanoid as Hl}from"nanoid";var Ir=class extends Error{code="ERR_CONNECTION_CLOSED";constructor(e="connection is closed"){super(e),this.name="ConnectionClosedError"}},nt=class s{constructor(e){this.stream=e;this.stream.onMessage(t=>this.handleIncoming(t)),this.stream.onClose(t=>this.handleClose(t))}stream;requestHandlers=new Map;defaultRequestHandler;notificationHandlers=new Map;bufferedNotifications=new Map;static MAX_BUFFERED_PER_METHOD=64;static MAX_BUFFERED_METHODS=256;pending=new Map;closed=!1;closeHandlers=[];orphanErrorHandlers=[];onRequest(e,t){this.requestHandlers.set(e,t)}setDefaultHandler(e){this.defaultRequestHandler=e}onNotification(e,t){this.notificationHandlers.set(e,t);let n=this.bufferedNotifications.get(e);if(n){this.bufferedNotifications.delete(e);for(let r of n)try{t(r.params,r.method)}catch{}}}drainBuffered(e){let n=this.bufferedNotifications.get(e)?.length??0;return this.bufferedNotifications.delete(e),n}onClose(e){this.closeHandlers.push(e)}isClosed(){return this.closed}onOrphanError(e){this.orphanErrorHandlers.push(e)}async request(e,t){return this.requestWithId(e,t).response}requestWithId(e,t){if(this.closed)throw new Ir;let n=Hl(),r={jsonrpc:"2.0",id:n,method:e,params:t},o=new Promise((i,a)=>{this.pending.set(n,{resolve:d=>i(d),reject:a}),this.stream.send(r).catch(d=>{this.pending.delete(n),a(d)})});return{id:n,response:o}}notify(e,t){if(this.closed)return Promise.resolve();let n={jsonrpc:"2.0",method:e,params:t};return this.stream.send(n)}async close(){this.closed||await this.stream.close()}fail(e){this.handleClose(e)}handleIncoming(e){"method"in e?"id"in e&&e.id!==void 0?this.handleRequest(e).catch(()=>{}):this.handleNotification(e):"id"in e?this.handleResponse(e):"error"in e&&this.handleResponse(e)}async handleRequest(e){let t=this.requestHandlers.get(e.method)??this.defaultRequestHandler;if(!t){await this.sendError(e.id,{code:x.MethodNotFound,message:`Method not found: ${e.method}`}).catch(()=>{});return}try{let n=await t(e.params,e.method),r={jsonrpc:"2.0",id:e.id,result:n};await this.stream.send(r).catch(()=>{})}catch(n){let r=n;await this.sendError(e.id,{code:r.code??x.InternalError,message:r.message,data:r.data}).catch(()=>{})}}handleNotification(e){let t=this.notificationHandlers.get(e.method);if(t){t(e.params,e.method);return}let n=this.bufferedNotifications.get(e.method);if(!n){if(this.bufferedNotifications.size>=s.MAX_BUFFERED_METHODS){let r=this.bufferedNotifications.keys().next().value;r!==void 0&&this.bufferedNotifications.delete(r)}n=[],this.bufferedNotifications.set(e.method,n)}n.push(e),n.length>s.MAX_BUFFERED_PER_METHOD&&n.shift()}handleResponse(e){let t=e.id===null?void 0:this.pending.get(e.id);if(!t){if(e.error)for(let n of this.orphanErrorHandlers)try{n({code:e.error.code,message:e.error.message,data:e.error.data})}catch{}return}if(this.pending.delete(e.id),e.error){let n=new Error(e.error.message);n.code=e.error.code,n.data=e.error.data,t.reject(n)}else t.resolve(e.result)}async sendError(e,t){let n={jsonrpc:"2.0",id:e,error:t};await this.stream.send(n)}handleClose(e){if(!this.closed){this.closed=!0;for(let t of this.pending.values())t.reject(e??new Error("connection closed"));this.pending.clear();for(let t of this.closeHandlers)t(e)}}};Y();var Ul=4096,st=class s{agentId;version;installId;cwd;connection;authMethods;steeringSupported;child;get pid(){return this.child.pid}exited=!1;killed=!1;stderrTail="";stderrTailBytes;killEscalationMs;logger;fileLog;exitHandlers=[];constructor(e,t){if(this.agentId=e.agentId,this.version=e.plan.version,this.installId=e.plan.installId??e.agentId,this.cwd=e.cwd,this.child=t,this.stderrTailBytes=e.stderrTailBytes??Ul,this.killEscalationMs=e.killEscalationMs??Bl,this.logger=e.logger,this.fileLog=Wl(e.agentId),this.writeLog(`--- spawn pid=${t.pid} version=${e.plan.version} cwd=${e.cwd} cmd=${e.plan.command} args=${JSON.stringify(e.plan.args)} time=${new Date().toISOString()} ---
|
|
@@ -18,7 +18,7 @@ stderr: ${u}`:`npm install ${s.packageSpec} failed (${c})`))})})}catch(t){if(t.c
|
|
|
18
18
|
`),this.fileLog?.end(),this.fileLog=void 0,this.killed)this.logger?.info(`agent ${e.agentId} pid=${t.pid} exited after kill code=${r} signal=${o}`);else{let i=`agent ${e.agentId} exited before responding (code=${r} signal=${o})`;this.connection.fail(new Error(this.formatFailure(i))),this.logger?.warn(`agent ${e.agentId} pid=${t.pid} exited unexpectedly code=${r} signal=${o}`)}for(let i of this.exitHandlers)i(r,o)})}writeLog(e){if(this.fileLog)try{this.fileLog.write(e)}catch{}}formatFailure(e){let t=this.stderrTail.trim();return t?`${e}
|
|
19
19
|
stderr: ${t}`:e}stderrTailText(){return this.stderrTail.trim()}static spawn(e){let t={...Dn(),...e.plan.env,...e.extraEnv??{}},n=Ll(e.plan.command,e.plan.args,{cwd:e.cwd,env:t,stdio:["pipe","pipe","pipe"],detached:!0});return n.unref(),new s(e,n)}onExit(e){this.exitHandlers.push(e)}isAlive(){return!this.exited}async kill(e="SIGTERM"){this.exited||(this.killed=!0,this.writeLog(`--- kill requested signal=${e} time=${new Date().toISOString()} ---
|
|
20
20
|
`),this.logger?.info(`agent ${this.agentId} pid=${this.child.pid} kill requested signal=${e}`),await this.connection.close().catch(()=>{}),this.signalProcessGroup(e),await this.waitForExit(this.killEscalationMs),!this.exited&&(this.writeLog(`--- kill escalating signal=SIGKILL time=${new Date().toISOString()} ---
|
|
21
|
-
`),this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} did not exit after ${e}; sending SIGKILL`),this.signalProcessGroup("SIGKILL"),await this.waitForExit(qi),this.exited||this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} still has not exited ${qi}ms after SIGKILL; giving up on the reap`)))}signalProcessGroup(e){let t=this.child.pid;if(t!==void 0)try{process.kill(-t,e)}catch{try{this.child.kill(e)}catch{}}}waitForExit(e){return this.exited?Promise.resolve():new Promise(t=>{let n=setTimeout(()=>{this.child.off("exit",r),t()},e),r=()=>{clearTimeout(n),t()};this.child.once("exit",r)})}},Bl=2e3,qi=5e3;function Wl(s){try{let e=R.agentLogFile(s);qn.mkdirSync(zi.dirname(e),{recursive:!0});let t=qn.createWriteStream(e,{flags:"a"});return t.on("error",()=>{}),t}catch{return}}import*as yt from"fs/promises";import*as vd from"os";import*as Ji from"os";function sn(){return Ji.hostname()}import*as Sn from"path";import{customAlphabet as sg}from"nanoid";var Ue="session/set_model",Cr="session/set_config_option",Ki="model";function Ar(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.availableModels)}function Qi(s){return Array.isArray(s)&&s.some(e=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.id===Ki)}function Et(s){if(!s)return;if(Ar(s)||Ar(s.models))return Ue;let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){for(let[t,n]of Object.entries(e))if(t!=="hydra-acp"&&Ar(n))return Ue}if(Qi(s.configOptions))return Cr}function Yi(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.sessionUpdate;if(e==="_hydra_current_model_update")return Ue;if(e==="config_option_update"&&Qi(s.configOptions))return Cr}function Vi(s){return typeof s=="object"&&s!==null&&s.code===x.MethodNotFound}function Gi(s,e,t,n){let r={...n??{}};return delete r.sessionId,delete r.modelId,delete r.configId,delete r.value,s===Ue?{...r,sessionId:e,modelId:t}:{...r,sessionId:e,configId:Ki,value:t}}function ql(s){return s===Ue?Cr:Ue}async function rt(s){let{request:e,sessionId:t,modelId:n,extraParams:r,logger:o}=s,i=s.verb??Ue;try{let a=await e(i,Gi(i,t,n,r));return{verb:i,result:a}}catch(a){if(!Vi(a))throw a;let d=ql(i);o?.info(`agent does not implement ${i} (MethodNotFound); retrying model change via ${d} modelId=${JSON.stringify(n)}`);try{let c=await e(d,Gi(d,t,n,r));return{verb:d,result:c}}catch(c){throw Vi(c)?a:c}}}async function lt(s){let{agent:e,upstreamSessionId:t,persistedMode:n,agentReportedMode:r,advertisedModes:o,logger:i}=s;if(!n)return r;if(n===r)return n;if(o&&o.length>0&&!o.some(a=>a.id===n)){let a=o.map(d=>d.id).join(", ");return i?.warn(`resurrect: persisted currentMode=${JSON.stringify(n)} not in agent's availableModes ([${a}]); skipping session/set_mode, session will use ${JSON.stringify(r)}`),r}try{return i?.info(`resurrect: pushing persisted modeId=${JSON.stringify(n)} to agent (agentReported=${JSON.stringify(r)})`),await e.connection.request("session/set_mode",{sessionId:t,modeId:n}),i?.info(`resurrect: session/set_mode accepted, effectiveMode=${JSON.stringify(n)}`),n}catch(a){return i?.warn(`resurrect: session/set_mode rejected by agent for modeId=${JSON.stringify(n)} (${a.message}); session will use ${JSON.stringify(r)}`),r}}async function ft(s){let{agent:e,upstreamSessionId:t,persistedModel:n,agentReportedModel:r,modelVerb:o,logger:i}=s;if(!n)return{modelId:r};if(n===r)return{modelId:n};try{i?.info(`resurrect: pushing persisted modelId=${JSON.stringify(n)} to agent (agentReported=${JSON.stringify(r)})`);let{verb:a,result:d}=await rt({request:(c,u)=>e.connection.request(c,u),sessionId:t,modelId:n,...o?{verb:o}:{},logger:i});return i?.info(`resurrect: ${a} accepted, effectiveModel=${JSON.stringify(n)}`),{modelId:n,result:d}}catch(a){return i?.warn(`resurrect: session/set_model rejected by agent for modelId=${JSON.stringify(n)} (${a.message}); session will use ${JSON.stringify(r)}`),{modelId:r}}}import{customAlphabet as Aa}from"nanoid";function Tt(s){return`${s.name}:${s.localId}`}function pt(s){let e=s.indexOf(":");if(e===-1)return;let t=s.slice(0,e),n=s.slice(e+1);if(!(t.length===0||n.length===0))return{name:t,localId:n}}import{createHmac as zl}from"crypto";function Jl(s,e){return zl("sha256",s).update(e).digest("hex")}function Rr(s,e){let t=JSON.stringify(e),n=Jl(s.secret,t);fetch(s.callbackUrl,{method:"POST",headers:{"Content-Type":"application/json","X-Hydra-Turn-Notify-Signature":n},body:t}).catch(()=>{})}var Xi="edit",zn=class{kinds=new Map;note(e,t){t!==void 0&&t.length>0&&!this.kinds.has(e)&&this.kinds.set(e,t)}get(e){return this.kinds.get(e)}effective(e,t){return t!==void 0&&t.length>0?t:this.kinds.get(e)}clear(){this.kinds.clear()}get size(){return this.kinds.size}};function Zi(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(t===null||typeof t!="object")continue;let n=t.path;typeof n=="string"&&n.length>0&&e.push(n)}return e}import*as ta from"fs/promises";var Vl=64*1024*1024,Gl=1*1024*1024,Pt=64*1024,Kl=6e4,Ql=100,Yl=1e3,Xl=64*1024,Zl=256*1024,ea=20;function ef(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Jn=class{storage;maxCapacityBytes;currentCapacityBytes;writeCursor=0;closed=!1;waiters=[];filePath;fileCapBytes;fileBytesWritten=0;fileCapReached=!1;onFileCapReached;logWriteError;fileWriteChain=Promise.resolve();constructor(e={}){if(this.maxCapacityBytes=e.capacityBytes??Vl,this.maxCapacityBytes<=0)throw new Error("capacityBytes must be > 0");this.currentCapacityBytes=Math.min(Gl,this.maxCapacityBytes),this.storage=Buffer.alloc(this.currentCapacityBytes),this.filePath=e.filePath,this.fileCapBytes=e.fileCapBytes??Number.POSITIVE_INFINITY,this.onFileCapReached=e.onFileCapReached,this.logWriteError=e.logWriteError}get capacity(){return this.maxCapacityBytes}get allocatedBytes(){return this.currentCapacityBytes}get writeCursorPos(){return this.writeCursor}get oldestAvailable(){return Math.max(0,this.writeCursor-this.currentCapacityBytes)}get isClosed(){return this.closed}append(e){this.closed||e.length===0||(this.writeRing(e),this.writeCursor+=e.length,this.filePath!==void 0&&this.scheduleFileWrite(e),this.wakeWaiters("data"))}close(){this.closed||(this.closed=!0,this.wakeWaiters("eof"))}read(e,t){let n=Math.max(0,Math.min(t,Pt));if(n===0){let l={bytes:Buffer.alloc(0),nextCursor:e};return this.closed&&e>=this.writeCursor&&(l.eof=!0),l}let r=e,o=0,i=this.oldestAvailable;r<i&&(o=i-r,r=i);let a=this.writeCursor-r;if(a<=0){let l={bytes:Buffer.alloc(0),nextCursor:r};return o>0&&(l.gap=o),this.closed&&(l.eof=!0),l}let d=Math.min(a,n),u={bytes:this.sliceFromRing(r,d),nextCursor:r+d};return o>0&&(u.gap=o),this.closed&&r+d>=this.writeCursor&&(u.eof=!0),u}tail(e){let t=Math.max(0,Math.min(e,Pt)),n=this.oldestAvailable,r=this.writeCursor-t,o=Math.max(n,r),i=r<n;return{bytes:this.sliceFromRing(o,this.writeCursor-o),startCursor:o,endCursor:this.writeCursor,truncated:i}}head(e){let t=Math.max(0,Math.min(e,Pt)),n=this.oldestAvailable,r=n>0,o=n,i=Math.min(this.writeCursor,o+t);return{bytes:this.sliceFromRing(o,i-o),startCursor:o,endCursor:i,truncated:r}}waitForData(e,t){if(e<this.writeCursor)return Promise.resolve("data");if(this.closed)return Promise.resolve("eof");let n=Math.max(0,Math.min(t,Kl));return n===0?Promise.resolve("timeout"):new Promise(r=>{let o={resolve:i=>{o.timer!==void 0&&(clearTimeout(o.timer),o.timer=void 0),r(i)},timer:setTimeout(()=>{let i=this.waiters.indexOf(o);i>=0&&this.waiters.splice(i,1),o.timer=void 0,r("timeout")},n)};this.waiters.push(o)})}grep(e){let t=this.oldestAvailable,n=e.cursor,r=n??t,o=0;n!==void 0&&n<t&&(o=t-n,r=t),r>this.writeCursor&&(r=this.writeCursor);let i=this.sliceFromRing(r,this.writeCursor-r),a=e.regex??!0,d=e.caseInsensitive===!0?"i":"",c=a?new RegExp(e.pattern,d):new RegExp(ef(e.pattern),d),u=e.invert??!1,l=Math.max(1,Math.min(e.maxMatches??Ql,Yl)),p=Math.max(1,Math.min(e.maxBytes??Xl,Zl)),m=Math.max(0,Math.min(e.contextBefore??0,ea)),h=Math.max(0,Math.min(e.contextAfter??0,ea)),f=[],g=[],w=[],y=0,k=!1,b=0,S=0,v=(C,T)=>{for(let $ of w)$.remaining>0&&($.match.after===void 0&&($.match.after=[]),$.match.after.push({cursor:C,line:T}),$.remaining--,y+=T.length);for(;w.length>0&&w[0].remaining===0;)w.shift();if(c.test(T)!==u&&f.length<l){let $={cursor:C,line:T};if(m>0&&g.length>0){$.before=g.slice();for(let W of $.before)y+=W.line.length}y+=T.length,f.push($),h>0&&w.push({match:$,remaining:h})}if(m>0)for(g.push({cursor:C,line:T});g.length>m;)g.shift();let H=f.length>=l&&w.length===0,J=y>=p;return H||J};for(let C=0;C<i.length;C++){if(i[C]!==10)continue;let T=i.subarray(b,C).toString("utf8"),M=r+b;if(b=C+1,S=b,v(M,T)){k=!0;break}}if(!k&&b<i.length&&this.closed){let C=i.subarray(b).toString("utf8"),T=r+b;v(T,C)&&(k=!0),S=i.length}let E=Math.min(r+S,this.writeCursor),A={matches:f,truncated:k,nextCursor:E,scannedBytes:S};return o>0&&(A.gap=o),this.closed&&E>=this.writeCursor&&(A.eof=!0),A}wakeWaiters(e){if(this.waiters.length===0)return;let t=this.waiters;this.waiters=[];for(let n of t)n.resolve(e)}growIfNeeded(e){if(this.currentCapacityBytes>=this.maxCapacityBytes)return;let t=this.writeCursor+e;if(t<=this.currentCapacityBytes)return;let n=this.currentCapacityBytes;for(;n<t&&n<this.maxCapacityBytes;)n=Math.min(this.maxCapacityBytes,n*2);if(n===this.currentCapacityBytes)return;let r=Buffer.alloc(n);this.storage.copy(r,0,0,this.writeCursor),this.storage=r,this.currentCapacityBytes=n}writeRing(e){let t=e.length;if(this.growIfNeeded(t),t>=this.currentCapacityBytes){let o=t-this.currentCapacityBytes;e.copy(this.storage,0,o,t);return}let n=this.writeCursor%this.currentCapacityBytes,r=this.currentCapacityBytes-n;t<=r?e.copy(this.storage,n,0,t):(e.copy(this.storage,n,0,r),e.copy(this.storage,0,r,t))}sliceFromRing(e,t){if(t<=0)return Buffer.alloc(0);let n=Buffer.alloc(t),r=e%this.currentCapacityBytes,o=Math.min(t,this.currentCapacityBytes-r);return this.storage.copy(n,0,r,r+o),o<t&&this.storage.copy(n,o,0,t-o),n}scheduleFileWrite(e){let t=this.filePath;if(t===void 0||this.fileCapReached)return;let n=this.fileCapBytes-this.fileBytesWritten;if(n<=0){this.fileCapReached=!0,this.onFileCapReached?.();return}let r=e.length<=n?e:e.subarray(0,n);this.fileBytesWritten+=r.length;let o=this.fileBytesWritten>=this.fileCapBytes;this.fileWriteChain=this.fileWriteChain.then(()=>ta.appendFile(t,r)).catch(i=>{this.logWriteError?.(i)}),o&&!this.fileCapReached&&(this.fileCapReached=!0,this.onFileCapReached?.())}async drainFileWrites(){await this.fileWriteChain.catch(()=>{})}};var Mt=[{verb:"title",name:"hydra title",description:"Regenerate the session title + synopsis via the agent (or set title manually with an arg)"},{verb:"agent",name:"hydra agent",argsHint:"<agent | status>",description:"Schedule a swap to a different agent (synthesizes a brief in the target's idiom, rotates on idle); `status` reports any pending swap"},{verb:"workspace",name:"hydra workspace",argsHint:"<start [name] [--clean] | sync | merge | apply | stop | detach | clean [--deep] | discard | status>",description:"Move this session into an isolated workspace so its edits cannot collide with other work, then land or discard them. `start` copies your uncommitted changes in and leaves the real tree untouched; `start --clean` leaves them behind so the workspace begins at the last commit. `stop` merges and returns; `discard` throws the work away and returns; `detach` returns without merging, leaving the workspace and its branch intact; `merge` lands the work without leaving; `apply` also stays, but delivers the work as ONE staged, uncommitted changeset instead of as the agent's commits, so you review and commit it yourself, with no fast-forward needed, which is what makes it work once the source has moved on; `clean` throws away everything done in the workspace and stays there, putting it back exactly as `start --clean` would have made it (add `--deep` to rebuild dependencies and carried config files too, rather than keeping them); `sync` pulls the source's committed history INTO the workspace, so you can test against what you will land onto, and because landing is fast-forward-only, syncing is also how you recover once the source has moved on. `start <name>` naming a workspace another live session is already in JOINS it instead of making a second one, so two sessions can share a checkout deliberately: edits interleave, `stop` behaves as `detach` while anyone else is still there, and the work lands when the last of them leaves."},{verb:"kill",name:"hydra kill",description:"Close this session (kills the agent; record is kept so it can be resumed later)"},{verb:"restart",name:"hydra restart",description:"Restart the agent with a fresh session/new while preserving conversation history (useful when the proxy has changed available models)"},{verb:"compact",name:"hydra compact",description:"Compact this session's history. Use '/hydra compact status' to inspect current compaction state without triggering."},{verb:"uncompact",name:"hydra uncompact",description:"Roll back the most recent compaction swap (only available immediately after a swap, before any new turns)"},{verb:"fork",name:"hydra fork",argsHint:"[verbatim]",description:"Fork this conversation into a new session (default: synthesis mode with a synopsis brief; pass 'verbatim' to slice at the last completed turn instead)"},{verb:"config",name:"hydra config",argsHint:"[<id> [<value>]]",description:"List or set an agent-advertised configOption (model, mode, effort, etc.). With no args, lists all options; with <id>, shows its choices; with <id> <value>, applies it."}],ek=new Map(Mt.map(s=>[s.verb,s]));function na(s){let e=s.lastIndexOf("/");return(e===-1?s:s.slice(e+1)).toLowerCase()}function _t(s,e){return rn(s,e.map(t=>t.modelId))}function rn(s,e){if(e.length===0)return{kind:"none",requested:s};if(e.includes(s))return{kind:"exact",modelId:s};let t=na(s),n=e.filter(o=>na(o)===t);if(n.length===1)return{kind:"resolved",modelId:n[0],requested:s};if(n.length>1)return{kind:"ambiguous",requested:s,candidates:n};let r=s.toLowerCase();if(r.length>0){let o=e.filter(i=>i.toLowerCase().includes(r));if(o.length===1)return{kind:"resolved",modelId:o[0],requested:s};if(o.length>1)return{kind:"ambiguous",requested:s,candidates:o}}return{kind:"unknown",requested:s}}function ra(s){if(s.length===0)return s;let e=new Map,t=new Map,n=new Map;for(let a=0;a<s.length;a++){let d=s[a];if(d===void 0)continue;let c=xr(d);if(c?.sessionUpdate!=="tool_call_update")continue;let u=typeof c.toolCallId=="string"?c.toolCallId:void 0;if(u!==void 0){e.set(u,a);for(let l of of){if(!sa(c[l]))continue;let p=n.get(u);p===void 0?n.set(u,new Map([[l,c[l]]])):p.set(l,c[l])}if(Array.isArray(c.content)&&c.content.length>0){let l=t.get(u);l?l.push(...c.content):t.set(u,[...c.content])}}}let r=[],o=null,i=null;for(let a=0;a<s.length;a++){let d=s[a];if(d===void 0)continue;let c=xr(d);if(!c||typeof c.sessionUpdate!="string"){r.push(d),o=null;continue}let u=c.sessionUpdate;if(u==="agent_message_chunk"||u==="agent_thought_chunk"||u==="user_message_chunk"){o&&o.kind===u?(sf(r,o.outIndex,tf(c.content)),nf(r,o.outIndex,d.seq)):(r.push(d),o={outIndex:r.length-1,kind:u});continue}if(o=null,u==="tool_call_update"){let l=typeof c.toolCallId=="string"?c.toolCallId:void 0;if(l!==void 0&&e.get(l)!==a)continue;let p=l!==void 0&&t.has(l)?rf(d,t.get(l)??[]):d,m=l===void 0?void 0:n.get(l);if(m!==void 0)for(let[h,f]of m)sa(xr(p)?.[h])||(p=af(p,h,f));r.push(p);continue}if(u==="plan"){i!==null?r[i]=d:(r.push(d),i=r.length-1);continue}(u==="prompt_received"||u==="turn_complete")&&(i=null),r.push(d)}return r}function xr(s){if(s.method!=="session/update")return;let t=s.params?.update;if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function tf(s){if(!s||typeof s!="object")return"";let e=s;return typeof e.text=="string"?e.text:""}function nf(s,e,t){let n=s[e];n===void 0||typeof t!="number"||n.seq!==void 0&&n.seq>=t||(s[e]={...n,seq:t})}function sf(s,e,t){if(t.length===0)return;let n=s[e];if(n===void 0)return;let r=n.params??{},o=r.update??{},i=o.content??{},a=typeof i.text=="string"?i.text:"";s[e]={...n,params:{...r,update:{...o,content:{...i,text:a+t}}}}}function rf(s,e){let t=s.params??{},n=t.update??{};return{...s,params:{...t,update:{...n,content:e}}}}var of=["rawInput","locations"];function sa(s){return s==null||typeof s!="object"?!1:Array.isArray(s)?s.length>0:Object.keys(s).length>0}function af(s,e,t){let n=s.params??{},r=n.update??{};return{...s,params:{...n,update:{...r,[e]:t}}}}var oa=`[older history truncated]
|
|
21
|
+
`),this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} did not exit after ${e}; sending SIGKILL`),this.signalProcessGroup("SIGKILL"),await this.waitForExit(qi),this.exited||this.logger?.warn(`agent ${this.agentId} pid=${this.child.pid} still has not exited ${qi}ms after SIGKILL; giving up on the reap`)))}signalProcessGroup(e){let t=this.child.pid;if(t!==void 0)try{process.kill(-t,e)}catch{try{this.child.kill(e)}catch{}}}waitForExit(e){return this.exited?Promise.resolve():new Promise(t=>{let n=setTimeout(()=>{this.child.off("exit",r),t()},e),r=()=>{clearTimeout(n),t()};this.child.once("exit",r)})}},Bl=2e3,qi=5e3;function Wl(s){try{let e=R.agentLogFile(s);qn.mkdirSync(zi.dirname(e),{recursive:!0});let t=qn.createWriteStream(e,{flags:"a"});return t.on("error",()=>{}),t}catch{return}}import*as yt from"fs/promises";import*as vd from"os";import*as Ji from"os";function sn(){return Ji.hostname()}import*as Sn from"path";import{customAlphabet as sg}from"nanoid";var Ue="session/set_model",Cr="session/set_config_option",Ki="model";function Ar(s){return!s||typeof s!="object"||Array.isArray(s)?!1:Array.isArray(s.availableModels)}function Qi(s){return Array.isArray(s)&&s.some(e=>e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.id===Ki)}function Et(s){if(!s)return;if(Ar(s)||Ar(s.models))return Ue;let e=s._meta;if(e&&typeof e=="object"&&!Array.isArray(e)){for(let[t,n]of Object.entries(e))if(t!=="hydra-acp"&&Ar(n))return Ue}if(Qi(s.configOptions))return Cr}function Yi(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.sessionUpdate;if(e==="_hydra_current_model_update")return Ue;if(e==="config_option_update"&&Qi(s.configOptions))return Cr}function Vi(s){return typeof s=="object"&&s!==null&&s.code===x.MethodNotFound}function Gi(s,e,t,n){let r={...n??{}};return delete r.sessionId,delete r.modelId,delete r.configId,delete r.value,s===Ue?{...r,sessionId:e,modelId:t}:{...r,sessionId:e,configId:Ki,value:t}}function ql(s){return s===Ue?Cr:Ue}async function rt(s){let{request:e,sessionId:t,modelId:n,extraParams:r,logger:o}=s,i=s.verb??Ue;try{let a=await e(i,Gi(i,t,n,r));return{verb:i,result:a}}catch(a){if(!Vi(a))throw a;let d=ql(i);o?.info(`agent does not implement ${i} (MethodNotFound); retrying model change via ${d} modelId=${JSON.stringify(n)}`);try{let c=await e(d,Gi(d,t,n,r));return{verb:d,result:c}}catch(c){throw Vi(c)?a:c}}}async function lt(s){let{agent:e,upstreamSessionId:t,persistedMode:n,agentReportedMode:r,advertisedModes:o,logger:i}=s;if(!n)return r;if(n===r)return n;if(o&&o.length>0&&!o.some(a=>a.id===n)){let a=o.map(d=>d.id).join(", ");return i?.warn(`resurrect: persisted currentMode=${JSON.stringify(n)} not in agent's availableModes ([${a}]); skipping session/set_mode, session will use ${JSON.stringify(r)}`),r}try{return i?.info(`resurrect: pushing persisted modeId=${JSON.stringify(n)} to agent (agentReported=${JSON.stringify(r)})`),await e.connection.request("session/set_mode",{sessionId:t,modeId:n}),i?.info(`resurrect: session/set_mode accepted, effectiveMode=${JSON.stringify(n)}`),n}catch(a){return i?.warn(`resurrect: session/set_mode rejected by agent for modeId=${JSON.stringify(n)} (${a.message}); session will use ${JSON.stringify(r)}`),r}}async function ft(s){let{agent:e,upstreamSessionId:t,persistedModel:n,agentReportedModel:r,modelVerb:o,logger:i}=s;if(!n)return{modelId:r};if(n===r)return{modelId:n};try{i?.info(`resurrect: pushing persisted modelId=${JSON.stringify(n)} to agent (agentReported=${JSON.stringify(r)})`);let{verb:a,result:d}=await rt({request:(c,u)=>e.connection.request(c,u),sessionId:t,modelId:n,...o?{verb:o}:{},logger:i});return i?.info(`resurrect: ${a} accepted, effectiveModel=${JSON.stringify(n)}`),{modelId:n,result:d}}catch(a){return i?.warn(`resurrect: session/set_model rejected by agent for modelId=${JSON.stringify(n)} (${a.message}); session will use ${JSON.stringify(r)}`),{modelId:r}}}import{customAlphabet as Aa}from"nanoid";function Tt(s){return`${s.name}:${s.localId}`}function pt(s){let e=s.indexOf(":");if(e===-1)return;let t=s.slice(0,e),n=s.slice(e+1);if(!(t.length===0||n.length===0))return{name:t,localId:n}}import{createHmac as zl}from"crypto";function Jl(s,e){return zl("sha256",s).update(e).digest("hex")}function Rr(s,e){let t=JSON.stringify(e),n=Jl(s.secret,t);fetch(s.callbackUrl,{method:"POST",headers:{"Content-Type":"application/json","X-Hydra-Turn-Notify-Signature":n},body:t}).catch(()=>{})}var Xi="edit",zn=class{kinds=new Map;note(e,t){t!==void 0&&t.length>0&&!this.kinds.has(e)&&this.kinds.set(e,t)}get(e){return this.kinds.get(e)}effective(e,t){return t!==void 0&&t.length>0?t:this.kinds.get(e)}clear(){this.kinds.clear()}get size(){return this.kinds.size}};function Zi(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(t===null||typeof t!="object")continue;let n=t.path;typeof n=="string"&&n.length>0&&e.push(n)}return e}import*as ta from"fs/promises";var Vl=64*1024*1024,Gl=1*1024*1024,Pt=64*1024,Kl=6e4,Ql=100,Yl=1e3,Xl=64*1024,Zl=256*1024,ea=20;function ef(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var Jn=class{storage;maxCapacityBytes;currentCapacityBytes;writeCursor=0;closed=!1;waiters=[];filePath;fileCapBytes;fileBytesWritten=0;fileCapReached=!1;onFileCapReached;logWriteError;fileWriteChain=Promise.resolve();constructor(e={}){if(this.maxCapacityBytes=e.capacityBytes??Vl,this.maxCapacityBytes<=0)throw new Error("capacityBytes must be > 0");this.currentCapacityBytes=Math.min(Gl,this.maxCapacityBytes),this.storage=Buffer.alloc(this.currentCapacityBytes),this.filePath=e.filePath,this.fileCapBytes=e.fileCapBytes??Number.POSITIVE_INFINITY,this.onFileCapReached=e.onFileCapReached,this.logWriteError=e.logWriteError}get capacity(){return this.maxCapacityBytes}get allocatedBytes(){return this.currentCapacityBytes}get writeCursorPos(){return this.writeCursor}get oldestAvailable(){return Math.max(0,this.writeCursor-this.currentCapacityBytes)}get isClosed(){return this.closed}append(e){this.closed||e.length===0||(this.writeRing(e),this.writeCursor+=e.length,this.filePath!==void 0&&this.scheduleFileWrite(e),this.wakeWaiters("data"))}close(){this.closed||(this.closed=!0,this.wakeWaiters("eof"))}read(e,t){let n=Math.max(0,Math.min(t,Pt));if(n===0){let l={bytes:Buffer.alloc(0),nextCursor:e};return this.closed&&e>=this.writeCursor&&(l.eof=!0),l}let r=e,o=0,i=this.oldestAvailable;r<i&&(o=i-r,r=i);let a=this.writeCursor-r;if(a<=0){let l={bytes:Buffer.alloc(0),nextCursor:r};return o>0&&(l.gap=o),this.closed&&(l.eof=!0),l}let d=Math.min(a,n),u={bytes:this.sliceFromRing(r,d),nextCursor:r+d};return o>0&&(u.gap=o),this.closed&&r+d>=this.writeCursor&&(u.eof=!0),u}tail(e){let t=Math.max(0,Math.min(e,Pt)),n=this.oldestAvailable,r=this.writeCursor-t,o=Math.max(n,r),i=r<n;return{bytes:this.sliceFromRing(o,this.writeCursor-o),startCursor:o,endCursor:this.writeCursor,truncated:i}}head(e){let t=Math.max(0,Math.min(e,Pt)),n=this.oldestAvailable,r=n>0,o=n,i=Math.min(this.writeCursor,o+t);return{bytes:this.sliceFromRing(o,i-o),startCursor:o,endCursor:i,truncated:r}}waitForData(e,t){if(e<this.writeCursor)return Promise.resolve("data");if(this.closed)return Promise.resolve("eof");let n=Math.max(0,Math.min(t,Kl));return n===0?Promise.resolve("timeout"):new Promise(r=>{let o={resolve:i=>{o.timer!==void 0&&(clearTimeout(o.timer),o.timer=void 0),r(i)},timer:setTimeout(()=>{let i=this.waiters.indexOf(o);i>=0&&this.waiters.splice(i,1),o.timer=void 0,r("timeout")},n)};this.waiters.push(o)})}grep(e){let t=this.oldestAvailable,n=e.cursor,r=n??t,o=0;n!==void 0&&n<t&&(o=t-n,r=t),r>this.writeCursor&&(r=this.writeCursor);let i=this.sliceFromRing(r,this.writeCursor-r),a=e.regex??!0,d=e.caseInsensitive===!0?"i":"",c=a?new RegExp(e.pattern,d):new RegExp(ef(e.pattern),d),u=e.invert??!1,l=Math.max(1,Math.min(e.maxMatches??Ql,Yl)),p=Math.max(1,Math.min(e.maxBytes??Xl,Zl)),m=Math.max(0,Math.min(e.contextBefore??0,ea)),h=Math.max(0,Math.min(e.contextAfter??0,ea)),f=[],g=[],w=[],y=0,k=!1,b=0,S=0,v=(C,T)=>{for(let $ of w)$.remaining>0&&($.match.after===void 0&&($.match.after=[]),$.match.after.push({cursor:C,line:T}),$.remaining--,y+=T.length);for(;w.length>0&&w[0].remaining===0;)w.shift();if(c.test(T)!==u&&f.length<l){let $={cursor:C,line:T};if(m>0&&g.length>0){$.before=g.slice();for(let W of $.before)y+=W.line.length}y+=T.length,f.push($),h>0&&w.push({match:$,remaining:h})}if(m>0)for(g.push({cursor:C,line:T});g.length>m;)g.shift();let H=f.length>=l&&w.length===0,J=y>=p;return H||J};for(let C=0;C<i.length;C++){if(i[C]!==10)continue;let T=i.subarray(b,C).toString("utf8"),M=r+b;if(b=C+1,S=b,v(M,T)){k=!0;break}}if(!k&&b<i.length&&this.closed){let C=i.subarray(b).toString("utf8"),T=r+b;v(T,C)&&(k=!0),S=i.length}let E=Math.min(r+S,this.writeCursor),A={matches:f,truncated:k,nextCursor:E,scannedBytes:S};return o>0&&(A.gap=o),this.closed&&E>=this.writeCursor&&(A.eof=!0),A}wakeWaiters(e){if(this.waiters.length===0)return;let t=this.waiters;this.waiters=[];for(let n of t)n.resolve(e)}growIfNeeded(e){if(this.currentCapacityBytes>=this.maxCapacityBytes)return;let t=this.writeCursor+e;if(t<=this.currentCapacityBytes)return;let n=this.currentCapacityBytes;for(;n<t&&n<this.maxCapacityBytes;)n=Math.min(this.maxCapacityBytes,n*2);if(n===this.currentCapacityBytes)return;let r=Buffer.alloc(n);this.storage.copy(r,0,0,this.writeCursor),this.storage=r,this.currentCapacityBytes=n}writeRing(e){let t=e.length;if(this.growIfNeeded(t),t>=this.currentCapacityBytes){let o=t-this.currentCapacityBytes;e.copy(this.storage,0,o,t);return}let n=this.writeCursor%this.currentCapacityBytes,r=this.currentCapacityBytes-n;t<=r?e.copy(this.storage,n,0,t):(e.copy(this.storage,n,0,r),e.copy(this.storage,0,r,t))}sliceFromRing(e,t){if(t<=0)return Buffer.alloc(0);let n=Buffer.alloc(t),r=e%this.currentCapacityBytes,o=Math.min(t,this.currentCapacityBytes-r);return this.storage.copy(n,0,r,r+o),o<t&&this.storage.copy(n,o,0,t-o),n}scheduleFileWrite(e){let t=this.filePath;if(t===void 0||this.fileCapReached)return;let n=this.fileCapBytes-this.fileBytesWritten;if(n<=0){this.fileCapReached=!0,this.onFileCapReached?.();return}let r=e.length<=n?e:e.subarray(0,n);this.fileBytesWritten+=r.length;let o=this.fileBytesWritten>=this.fileCapBytes;this.fileWriteChain=this.fileWriteChain.then(()=>ta.appendFile(t,r)).catch(i=>{this.logWriteError?.(i)}),o&&!this.fileCapReached&&(this.fileCapReached=!0,this.onFileCapReached?.())}async drainFileWrites(){await this.fileWriteChain.catch(()=>{})}};var Mt=[{verb:"title",name:"hydra title",description:"Regenerate the session title + synopsis via the agent (or set title manually with an arg)"},{verb:"agent",name:"hydra agent",argsHint:"<agent | status>",description:"Schedule a swap to a different agent (synthesizes a brief in the target's idiom, rotates on idle); `status` reports any pending swap"},{verb:"workspace",name:"hydra workspace",argsHint:"<start [name] [--clean] | sync | merge | apply | stop | detach | clean [--deep] | discard | status>",description:"Move this session into an isolated workspace so its edits cannot collide with other work, then land or discard them. `start` copies your uncommitted changes in and leaves the real tree untouched; `start --clean` leaves them behind so the workspace begins at the last commit. `stop` merges and returns; `discard` throws the work away and returns; `detach` returns without merging, leaving the workspace and its branch intact; `merge` lands the work without leaving; `apply` also stays, but delivers the work as ONE staged, uncommitted changeset instead of as the agent's commits, so you review and commit it yourself, with no fast-forward needed, which is what makes it work once the source has moved on; `clean` throws away everything done in the workspace and stays there, putting it back exactly as `start --clean` would have made it (add `--deep` to rebuild dependencies and carried config files too, rather than keeping them); `sync` pulls the source's committed history INTO the workspace, so you can test against what you will land onto, and because landing is fast-forward-only, syncing is also how you recover once the source has moved on. `start <name>` naming a workspace another live session is already in JOINS it instead of making a second one, so two sessions can share a checkout deliberately: edits interleave, `stop` behaves as `detach` while anyone else is still there, and the work lands when the last of them leaves."},{verb:"kill",name:"hydra kill",description:"Close this session (kills the agent; record is kept so it can be resumed later)"},{verb:"restart",name:"hydra restart",description:"Restart the agent with a fresh session/new while preserving conversation history (useful when the proxy has changed available models)"},{verb:"compact",name:"hydra compact",description:"Compact this session's history. Use '/hydra compact status' to inspect current compaction state without triggering."},{verb:"uncompact",name:"hydra uncompact",description:"Roll back the most recent compaction swap (only available immediately after a swap, before any new turns)"},{verb:"fork",name:"hydra fork",argsHint:"[verbatim]",description:"Fork this conversation into a new session (default: synthesis mode with a synopsis brief; pass 'verbatim' to slice at the last completed turn instead)"},{verb:"config",name:"hydra config",argsHint:"[<id> [<value>]]",description:"List or set an agent-advertised configOption (model, mode, effort, etc.). With no args, lists all options; with <id>, shows its choices; with <id> <value>, applies it."}],tk=new Map(Mt.map(s=>[s.verb,s]));function na(s){let e=s.lastIndexOf("/");return(e===-1?s:s.slice(e+1)).toLowerCase()}function _t(s,e){return rn(s,e.map(t=>t.modelId))}function rn(s,e){if(e.length===0)return{kind:"none",requested:s};if(e.includes(s))return{kind:"exact",modelId:s};let t=na(s),n=e.filter(o=>na(o)===t);if(n.length===1)return{kind:"resolved",modelId:n[0],requested:s};if(n.length>1)return{kind:"ambiguous",requested:s,candidates:n};let r=s.toLowerCase();if(r.length>0){let o=e.filter(i=>i.toLowerCase().includes(r));if(o.length===1)return{kind:"resolved",modelId:o[0],requested:s};if(o.length>1)return{kind:"ambiguous",requested:s,candidates:o}}return{kind:"unknown",requested:s}}function ra(s){if(s.length===0)return s;let e=new Map,t=new Map,n=new Map;for(let a=0;a<s.length;a++){let d=s[a];if(d===void 0)continue;let c=xr(d);if(c?.sessionUpdate!=="tool_call_update")continue;let u=typeof c.toolCallId=="string"?c.toolCallId:void 0;if(u!==void 0){e.set(u,a);for(let l of of){if(!sa(c[l]))continue;let p=n.get(u);p===void 0?n.set(u,new Map([[l,c[l]]])):p.set(l,c[l])}if(Array.isArray(c.content)&&c.content.length>0){let l=t.get(u);l?l.push(...c.content):t.set(u,[...c.content])}}}let r=[],o=null,i=null;for(let a=0;a<s.length;a++){let d=s[a];if(d===void 0)continue;let c=xr(d);if(!c||typeof c.sessionUpdate!="string"){r.push(d),o=null;continue}let u=c.sessionUpdate;if(u==="agent_message_chunk"||u==="agent_thought_chunk"||u==="user_message_chunk"){o&&o.kind===u?(sf(r,o.outIndex,tf(c.content)),nf(r,o.outIndex,d.seq)):(r.push(d),o={outIndex:r.length-1,kind:u});continue}if(o=null,u==="tool_call_update"){let l=typeof c.toolCallId=="string"?c.toolCallId:void 0;if(l!==void 0&&e.get(l)!==a)continue;let p=l!==void 0&&t.has(l)?rf(d,t.get(l)??[]):d,m=l===void 0?void 0:n.get(l);if(m!==void 0)for(let[h,f]of m)sa(xr(p)?.[h])||(p=af(p,h,f));r.push(p);continue}if(u==="plan"){i!==null?r[i]=d:(r.push(d),i=r.length-1);continue}(u==="prompt_received"||u==="turn_complete")&&(i=null),r.push(d)}return r}function xr(s){if(s.method!=="session/update")return;let t=s.params?.update;if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function tf(s){if(!s||typeof s!="object")return"";let e=s;return typeof e.text=="string"?e.text:""}function nf(s,e,t){let n=s[e];n===void 0||typeof t!="number"||n.seq!==void 0&&n.seq>=t||(s[e]={...n,seq:t})}function sf(s,e,t){if(t.length===0)return;let n=s[e];if(n===void 0)return;let r=n.params??{},o=r.update??{},i=o.content??{},a=typeof i.text=="string"?i.text:"";s[e]={...n,params:{...r,update:{...o,content:{...i,text:a+t}}}}}function rf(s,e){let t=s.params??{},n=t.update??{};return{...s,params:{...t,update:{...n,content:e}}}}var of=["rawInput","locations"];function sa(s){return s==null||typeof s!="object"?!1:Array.isArray(s)?s.length>0:Object.keys(s).length>0}function af(s,e,t){let n=s.params??{},r=n.update??{};return{...s,params:{...n,update:{...r,[e]:t}}}}var oa=`[older history truncated]
|
|
22
22
|
`,ia=["file_path","filePath","path","command","pattern","query"];function $t(s,e={}){let t=e.maxChars??4e5,n=Er(s),r=[],o="",i=e.toolOutput?.maxTotal??0,a=()=>{o.length!==0&&(r.push(`Assistant: ${o}`),o="")};for(let d of s){if(d.method!=="session/update")continue;let u=d.params?.update;if(!u||typeof u.sessionUpdate!="string")continue;let l=u.sessionUpdate;if(l==="prompt_received"){a();let p=_r(u.prompt).trim();p.length>0&&r.push(`User: ${p}`)}else if(l==="agent_message_chunk"){let p=$r(u.content);p.length>0&&(o+=p)}else if(l==="tool_call"){if(a(),r.push(Mr(u,n)),e.toolOutput!==void 0){let p=Pr(u),m=p!==void 0?n.get(p)?.output:void 0;if(m!==void 0&&i>0){let h=Math.min(e.toolOutput.maxPerCall,i),f=m.length<=h?m:`${m.slice(0,h)}\u2026[${m.length-h} more chars]`;r.push(`Output: ${f}`),i-=Math.min(f.length,h)}}}else l==="turn_complete"&&a()}return a(),gf(r.join(`
|
|
23
23
|
`),t)}function Er(s){let e=new Map;for(let t of s){if(t.method!=="session/update")continue;let r=t.params?.update;if(!r)continue;let o=r.sessionUpdate;if(o!=="tool_call"&&o!=="tool_call_update")continue;let i=Pr(r);if(i===void 0)continue;let a=e.get(i);if(a===void 0&&(a={name:"(unnamed)",rawInput:{}},e.set(i,a)),a.name==="(unnamed)"){let c=cf(r,o);c!==void 0&&(a.name=c)}if(a.kind===void 0&&typeof r.kind=="string"&&r.kind.length>0&&(a.kind=r.kind),a.output===void 0){let c=Vn(r);c!==void 0&&(a.output=c)}let d=r.rawInput;d&&typeof d=="object"&&!Array.isArray(d)&&Object.assign(a.rawInput,d)}for(let t of e.values())t.name=Tr(t);return e}function Tr(s){return df(s)?s.kind??"(unnamed)":s.name}function df(s){for(let e of ia){let t=s.rawInput[e];if(!(typeof t!="string"||t.length===0)&&(t===s.name||s.name.length>=12&&t.startsWith(s.name)))return!0}return!1}function cf(s,e){let t=on(s);if(t!==void 0)return t;if(typeof s.name=="string"&&s.name.length>0)return s.name;if(e==="tool_call"&&typeof s.title=="string"&&s.title.length>0)return s.title}function Pr(s){let e=s.toolCallId;if(typeof e=="string"&&e.length>0)return e}function Vn(s){let e=uf(s);if(e!==void 0)return e;let t=s.rawOutput;if(typeof t=="string")return t.length>0?t:void 0;if(t&&typeof t=="object"&&!Array.isArray(t)){let n=t.output;if(typeof n=="string")return n.length>0?n:void 0}}function uf(s){let e=s._meta;if(!e||typeof e!="object")return;let t=e.claudeCode;if(!t||typeof t!="object")return;let n=t.toolResponse;if(typeof n=="string")return n.length>0?n:void 0;if(!n||typeof n!="object")return;let{stdout:r,stderr:o}=n,i=[];if(typeof r=="string"&&r.length>0&&i.push(r),typeof o=="string"&&o.length>0&&i.push(`[stderr] ${o}`),i.length!==0)return i.join(`
|
|
24
24
|
`)}function on(s){let e=s._meta;if(!e||typeof e!="object")return;let t=e.claudeCode;if(!t||typeof t!="object")return;let n=t.toolName;if(typeof n=="string"&&n.length>0)return n}function Mr(s,e){let t=Pr(s),n=t!==void 0?e?.get(t):void 0,r=n?.name??lf(s),o=ff(n?.rawInput??s.rawInput);return o.length===0?`Tool: ${r}`:`Tool: ${r}(${o.join(", ")})`}function lf(s){let e=on(s);return e!==void 0?e:typeof s.name=="string"&&s.name.length>0?s.name:typeof s.title=="string"&&s.title.length>0?s.title:"(unnamed)"}function ff(s){if(!s||typeof s!="object"||Array.isArray(s))return[];let e=s,t=[];for(let n of ia){let r=e[n];typeof r=="string"&&r.length>0&&t.push(`${n}=${pf(r,600)}`)}return t}function _r(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>{if(e&&typeof e=="object"){let t=e.text;if(typeof t=="string")return t}return""}).join(""):""}function $r(s){if(!s||typeof s!="object")return"";let e=s.text;return typeof e=="string"?e:""}function pf(s,e){return s.length<=e?s:s.slice(0,e-1)+"\u2026"}function gf(s,e){if(s.length<=e)return s;let t=s.split(`
|
|
@@ -85,7 +85,7 @@ ${f}:
|
|
|
85
85
|
`)}async seedFromImport(){await this.enqueuePrompt("seed:import",async()=>{let e=await this.buildSwitchTranscript(this.agentId,{intro:"You are continuing a conversation that was imported from another hydra. Below is the transcript so far.",followup:"Each line is prefixed with its speaker. Treat this as context for the next user message; do not re-respond to earlier turns."});e&&await this.runInternalPrompt(e).catch(()=>{})})}async seedFromFork(e){await this.enqueuePrompt("seed:fork",async()=>{let t=this.title??"(untitled)",n=[];if(this.historyStore)try{n=await this.historyStore.load(this.sessionId)}catch(o){this.logger?.warn(`seedFromFork: historyStore.load failed: ${o.message}`)}let r=Fr({synopsis:e,title:t,tail:n,tailK:Sf,tailFloor:If,watermark:this._summarizedThroughEntry,recallArmed:(this._summarizedThroughEntry??0)>0});if(this.internalPromptCapture)throw new Error("seedFromFork: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};try{await this.agent.connection.request("session/prompt",{sessionId:this.upstreamSessionId,prompt:[{type:"text",text:r}]});let o=this.internalPromptCapture;this.logger?.info(`seedFromFork: seed processed sessionId=${this.sessionId} seedChars=${r.length} toolCalls=${o.toolCalls} thinkingChars=${o.thinkingChars} messageChars=${o.messageChars}`)}finally{this.internalPromptCapture=void 0}})}broadcastAgentSwitch(e,t){this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",_meta:{"hydra-acp":{synthetic:!0,agentId:t,pendingAgentSwap:null}}}}),this.broadcastConfigOptions()}broadcastPendingAgentSwap(e){this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",_meta:{"hydra-acp":{synthetic:!0,pendingAgentSwap:e}}}})}hasStreamBuffer(){return this.streamBuffer!==void 0}get streamPath(){return this.streamFilePath}openStream(e){if(this.streamBuffer!==void 0)throw new Error(`stream buffer already open for session ${this.sessionId}`);let n=(e.mode??"memory")==="file"&&e.filePathFor!==void 0?e.filePathFor(this.sessionId):void 0,r={};e.capacityBytes!==void 0&&(r.capacityBytes=e.capacityBytes),n!==void 0&&(r.filePath=n),e.fileCapBytes!==void 0&&(r.fileCapBytes=e.fileCapBytes),r.onFileCapReached=()=>{this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"_hydra_stream_truncated",...n!==void 0?{filePath:n}:{},fileCapBytes:e.fileCapBytes}})};let o=new Jn(r);this.streamBuffer=o,this.streamFilePath=n;let i={capacityBytes:o.capacity};return n!==void 0&&(i.filePath=n),e.fileCapBytes!==void 0&&(i.fileCapBytes=e.fileCapBytes),i}streamWrite(e,t){let n=this.requireStreamBuffer();if(e.length>0){let r=Buffer.from(e,"base64");n.append(r)}return t===!0&&n.close(),{writeCursor:n.writeCursorPos}}async streamRead(e,t,n){let r=this.requireStreamBuffer(),o=Math.max(0,Math.min(t??Pt,Pt)),i=r.read(e,o);if(i.bytes.length===0&&i.eof!==!0&&n!==void 0&&n>0){let d=await r.waitForData(i.nextCursor,n);(d==="data"||d==="eof")&&(i=r.read(i.nextCursor,o))}let a={bytes:i.bytes.toString("base64"),nextCursor:i.nextCursor};return i.gap!==void 0&&(a.gap=i.gap),i.eof===!0&&(a.eof=!0),a}streamTail(e){let n=this.requireStreamBuffer().tail(e);return{bytes:n.bytes.toString("base64"),startCursor:n.startCursor,endCursor:n.endCursor,truncated:n.truncated}}streamHead(e){let n=this.requireStreamBuffer().head(e);return{bytes:n.bytes.toString("base64"),startCursor:n.startCursor,endCursor:n.endCursor,truncated:n.truncated}}async streamWaitFor(e,t){return this.requireStreamBuffer().waitForData(e,t)}streamGrep(e){return this.requireStreamBuffer().grep(e)}streamInfo(){let e=this.requireStreamBuffer();return{writeCursor:e.writeCursorPos,oldestAvailable:e.oldestAvailable,capacity:e.capacity,closed:e.isClosed}}requireStreamBuffer(){if(this.streamBuffer===void 0){let e=new Error(`session ${this.sessionId} has no stream buffer; POST /v1/sessions/:id/stdin/open first`);throw e.code=x.StreamNotEnabled,e}return this.streamBuffer}markClosed(e){if(this.closed)return;this.closeUnsolicitedTurn("closed"),e={deleteRecord:e.deleteRecord||this.deleteRecordIntent},this.closing=!0,this.closed=!0,this.cancelIdleTimer(),this.cancelOrphanTimer(),this.extensionCommandsUnsub&&(this.extensionCommandsUnsub(),this.extensionCommandsUnsub=void 0);for(let o of[...this.inFlightExtensionDispatches.keys()])this.cancelExtensionDispatch(o,"abandoned");this.currentEntry?.kind==="user"&&!this.recentlyTerminal.has(this.currentEntry.messageId)&&this.broadcastTurnComplete(this.currentEntry.clientId,{stopReason:"interrupted"},this.currentEntry.messageId,this.originatorNeedsTurnComplete(this.currentEntry)),this.currentEntry=void 0;let n=this.promptQueue;this.promptQueue=[];for(let o of n){o.cancelled=!0,o.kind==="user"&&this.broadcastQueueRemoved(o.messageId,"abandoned");let i=this.pendingTurnNotifiers.get(o.messageId);i&&(this.pendingTurnNotifiers.delete(o.messageId),Rr(i,{sessionId:this.sessionId,messageId:i.originalMessageId,stopReason:"cancelled",deliveredAt:Date.now(),...o.messageId!==i.originalMessageId?{amendedTo:o.messageId}:{}}));try{o.resolve({stopReason:"cancelled"})}catch{}}this.notifyChain("session.closed",{}),this.toolCompletionSeen.clear(),this.toolCallKind.clear(),this.filesEditedSeen.clear(),this.openToolCalls.clear();let r=this.sessionId;this.queueWriteChain=this.queueWriteChain.catch(()=>{}).then(()=>ya(r).catch(()=>{}));for(let o of this.clients.values())o.connection.notify("hydra-acp/session/closed",{sessionId:this.sessionId}).catch(()=>{});if(this.clients.clear(),this.streamBuffer!==void 0){let o=this.streamBuffer,i=this.streamFilePath;this.streamBuffer=void 0,this.streamFilePath=void 0,o.close(),i!==void 0&&o.drainFileWrites().then(()=>xa.unlink(i).catch(()=>{}))}for(let o of this.closeHandlers)o(e)}get lastActivityAt(){return this.lastRecordedAt}setAttentionFlag(e,t,n){this._setAttentionFlag(e,t,n,!0)}_setAttentionFlag(e,t,n,r){let o=`${e}::${t}`,i=this.attentionFlags.get(o);if(i){if(JSON.stringify(i.payload)===JSON.stringify(n))return;this.attentionFlags.set(o,{...i,payload:n,raisedAt:i.raisedAt})}else this.attentionFlags.set(o,{source:e,reason:t,raisedAt:Date.now(),payload:n});r&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}clearAttentionFlag(e,t){this._clearAttentionFlag(e,t,!0)}_clearAttentionFlag(e,t,n){let r=`${e}::${t}`;this.attentionFlags.delete(r)&&n&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}listAttentionFlags(){return Array.from(this.attentionFlags.values()).sort((e,t)=>e.raisedAt-t.raisedAt)}listAttentionFlagsBySource(e){return this.listAttentionFlags().filter(t=>t.source===e)}onAttentionFlagsChange(e){this.attentionFlagsChangeHandlers.push(e)}fireAttentionFlagsChange(){let e=this.listAttentionFlags();for(let t of this.attentionFlagsChangeHandlers)try{t(e)}catch{}}broadcastAttentionUpdated(){for(let e of this.clients.values())e.connection.notify("hydra-acp/session/attention_updated",{sessionId:this.sessionId,flags:this.listAttentionFlags()}).catch(()=>{})}scheduleIdleCheck(){if(this.closed||this.idleTimeoutMs<=0)return;let e=this.lastActivityAt+this.idleTimeoutMs;this.armIdleTimer(Math.max(0,e-Date.now()))}armIdleTimer(e){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{this.idleTimer=void 0,this.checkIdle()},e),typeof this.idleTimer.unref=="function"&&this.idleTimer.unref()}checkIdle(){if(this.closed||this.idleTimeoutMs<=0)return;if(this.hasWorkInFlight){this.armIdleTimer(this.idleTimeoutMs);return}let e=Date.now()-this.lastActivityAt;if(e<this.idleTimeoutMs){this.armIdleTimer(this.idleTimeoutMs-e);return}let t=this.firstPromptSeeded?{deleteRecord:!1}:{deleteRecord:!0},n=Math.round(e/1e3);this.logger?.info(`session ${this.sessionId} idle timeout fired after ${n}s (window=${Math.round(this.idleTimeoutMs/1e3)}s) \u2014 closing`),this.close(t).catch(()=>{})}cancelIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=void 0),this.disposeIdleHandlers()}scheduleOrphanCheck(){this.closed||this.orphanTimeoutMs<=0||this.clients.size>0||this._interactive===!0||this.armOrphanTimer(this.orphanTimeoutMs)}armOrphanTimer(e){this.orphanTimer&&clearTimeout(this.orphanTimer),this.orphanTimer=setTimeout(()=>{this.orphanTimer=void 0,this.checkOrphan()},e),typeof this.orphanTimer.unref=="function"&&this.orphanTimer.unref()}checkOrphan(){if(!this.closed&&!(this.clients.size>0||this._interactive===!0)){if(this.hasWorkInFlight){this.armOrphanTimer(this.orphanTimeoutMs);return}this.logger?.info(`session ${this.sessionId} orphan timeout fired after ${Math.round(this.orphanTimeoutMs/1e3)}s with no attached client and no prompt ever received \u2014 closing`),this.close({deleteRecord:!1,by:"reap-orphaned"}).catch(()=>{})}}cancelOrphanTimer(){this.orphanTimer&&(clearTimeout(this.orphanTimer),this.orphanTimer=void 0)}get currentPromptDepth(){if(this.currentEntry?.kind==="user")return this.currentEntry.originator.depth??0}get hasWorkInFlight(){return this.turnStartedAt!==void 0||this.hasPermissionFlag||this.promptQueue.length>0||this.armedBackgroundTasks.length>0}onIdle(e,t){let n={fn:e,once:!!t?.once,debounceMs:t?.debounceMs??0};return this.idleHandlers.push(n),()=>{let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1),n.timer&&(clearTimeout(n.timer),n.timer=void 0)}}onceIdle(e){return this.onIdle(e,{once:!0})}dispatchIdle(){if(this.closed)return;if(!this.isQuiescedSync()){for(let n of this.idleHandlers)n.timer&&(clearTimeout(n.timer),n.timer=void 0);return}let t=[...this.idleHandlers];for(let n of t){if(n.debounceMs===0){if(n.once){let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1)}try{n.fn(this)}catch{}continue}n.timer&&(clearTimeout(n.timer),n.timer=void 0),n.timer=setTimeout(()=>{if(n.timer=void 0,!this.closed&&this.isQuiescedSync()){if(n.once){let r=this.idleHandlers.indexOf(n);r>=0&&this.idleHandlers.splice(r,1)}try{n.fn(this)}catch{}}},n.debounceMs),typeof n.timer.unref=="function"&&n.timer.unref()}}disposeIdleHandlers(){for(let e of this.idleHandlers)e.timer&&(clearTimeout(e.timer),e.timer=void 0);this.idleHandlers.length=0}noteRecordedToolCall(e,t){if(e!=="session/update")return;let n=t?.update;if(n===void 0)return;let r=typeof n.toolCallId=="string"?n.toolCallId:"";if(r.length!==0){if(n.sessionUpdate==="tool_call"){this.openToolCalls.add(r);return}n.sessionUpdate==="tool_call_update"&&(n.status==="completed"||n.status==="failed")&&this.openToolCalls.delete(r)}}closeOpenToolCalls(e){if(this.openToolCalls.size===0||this.closed)return;let t=[...this.openToolCalls];this.openToolCalls.clear();for(let n of t)this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"tool_call_update",toolCallId:n,status:"failed",_meta:{[ae]:{synthetic:!0,closedBy:e}}}});this.logger?.info(`session ${this.sessionId} closed ${t.length} open tool call(s) on ${e}`)}maybeEmitToolEdges(e){if(!e||typeof e!="object")return;let t=e.update;if(!t||typeof t!="object")return;let n=t,r=typeof n.sessionUpdate=="string"?n.sessionUpdate:"";if(r!=="tool_call"&&r!=="tool_call_update")return;let o=typeof n.toolCallId=="string"&&n.toolCallId.length>0?n.toolCallId:void 0;if(!o)return;let i=typeof n.kind=="string"?n.kind:void 0;this.toolCallKind.note(o,i);let a=this.toolCallKind.effective(o,i);if(a===Xi&&Array.isArray(n.locations))for(let u of n.locations){if(!u||typeof u!="object")continue;let l=u.path;if(typeof l!="string"||l.length===0||this.filesEditedSeen.has(l))continue;this.filesEditedSeen.add(l);let p=u.line,m={path:l,toolCallId:o};typeof p=="number"&&(m.line=p),this.notifyChain("file.edited",m),this.reportIsolationBreach(l,o)}if(r!=="tool_call_update")return;let d=typeof n.status=="string"?n.status:void 0;if(d!=="completed"&&d!=="failed"||this.toolCompletionSeen.has(o))return;this.toolCompletionSeen.set(o,d);let c={toolCallId:o,status:d};a&&(c.kind=a),n.content!==void 0&&(c.content=n.content),Array.isArray(n.locations)&&(c.locations=n.locations),this.notifyChain("tool.completed",c)}notifyChain(e,t){let n=`lifecycle:${e}`;for(let r of this.transformChain)r.intercepts.has(n)&&r.connection.notify("hydra-acp/transformer/session_event",{event:e,sessionId:this.sessionId,payload:t}).catch(()=>{})}rewriteForClient(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(typeof t.sessionId=="string"&&t.sessionId!==this.sessionId)return{...t,sessionId:this.sessionId}}return e}recordAndBroadcast(e,t,n){let r=this.rewriteForClient(t),o=!jr(e,r),i=o?zf(e,r):r,a=Date.now(),d=o?this.lastSeq=Math.max(this.lastSeq+1,a):void 0,c=o?Le(He(i,a),d):i;if(o){this.noteRecordedToolCall(e,i);let u={method:e,params:i,recordedAt:a,seq:d};if(this.lastRecordedAt=u.recordedAt,this.appendCount+=1,this.historyStore){let l=this.historyStore;l.append(this.sessionId,u).catch(()=>{}),this.appendCount>=this.compactEvery&&(this.appendCount=0,l.compact(this.sessionId,this.historyMaxEntries).catch(()=>{}))}for(let l of this.broadcastHandlers)try{l(u)}catch{}this.scheduleIdleCheck(),this.dispatchIdle()}this.updatedAt=Date.now();for(let u of this.clients.values())n&&u.clientId===n||u.connection.notify(e,c).catch(()=>{})}async requestPermissionFromClients(e){return this.handlePermissionRequest(e)}async handlePermissionRequest(e){let t=[...this.clients.values()];if(t.length===0)throw be(new Error("no clients attached to handle permission request"),x.PermissionDenied);let n=this.rewriteForClient(e),r=ba(n),o=We(),{toolCall:i,options:a}=n??{};return new Promise((d,c)=>{let u=!1,l=[],p=0,m,h=this.sessionId,f=y=>{u||(u=!0,this.clearAttentionFlag("daemon",`permission:${o}`),this.permissionCallbacks.delete(o),y())},g=y=>y?.code===x.MethodNotFound;function w(y){if(u)return;let k=y.connection.request("session/request_permission",n);l.push({client:y}),p++,k.then(b=>{p--,f(()=>{let S=Gf({toolCallId:r,result:b,resolver:y});for(let v of l)v.client.clientId!==y.clientId&&v.client.connection.notify("session/update",{sessionId:h,update:S}).catch(()=>{});d(b)})}).catch(b=>{if(p--,g(b)||(m=b),p===0&&!u){let S=m??be(new Error("no client handled permission request"),x.PermissionDenied);f(()=>c(S))}})}this.setAttentionFlag("daemon",`permission:${o}`,{kind:"permission",toolCall:i??null,options:a??null}),this.permissionCallbacks.set(o,w);for(let y of t)w(y)})}async enqueuePrompt(e,t){return new Promise((n,r)=>{let o={kind:"internal",messageId:We(),label:e,enqueuedAt:Date.now(),cancelled:!1,task:t,resolve:n,reject:r};this.promptQueue.push(o),this.drainQueue()})}async enqueueUserPrompt(e,t,n,r,o){let i=(t??{}).prompt??[],a={clientId:e.clientId};e.clientInfo?.name&&(a.name=e.clientInfo.name),e.clientInfo?.version&&(a.version=e.clientInfo.version),r?.fromSession&&(a.fromSession=r.fromSession),r?.fromSessionTitle&&(a.fromSessionTitle=r.fromSessionTitle),r?.fromLabel&&(a.fromLabel=r.fromLabel),r?.depth!==void 0&&(a.depth=r.depth);let d=this.parseQueuePosition(t);return new Promise((c,u)=>{let l={kind:"user",messageId:n,originator:a,clientId:e.clientId,prompt:i,enqueuedAt:Date.now(),cancelled:!1,resolve:c,reject:u};o?.steerOriginated===!0&&(l.wasSteer=!0);let p=this.insertEntryAt(l,d);this.persistRewrite(),this.broadcastQueueAdded(l,{position:p}),this.drainQueue()})}promptCarriesSentBy(e){if(!e||typeof e!="object")return!1;let t=e._meta;if(!t||typeof t!="object"||Array.isArray(t))return!1;let n=t[ae];if(!n||typeof n!="object"||Array.isArray(n))return!1;let r=n.sentBy;return!!r&&typeof r=="object"}parseQueuePosition(e){if(!e||typeof e!="object")return"tail";let t=e._meta;if(!t||typeof t!="object"||Array.isArray(t))return"tail";let n=t["hydra-acp"];if(!n||typeof n!="object"||Array.isArray(n))return"tail";let r=n.queuePosition;if(r==="head"||r==="tail")return r;if(r&&typeof r=="object"&&!Array.isArray(r)){let o=r.afterMessageId;if(typeof o=="string"&&o.length>0)return{afterMessageId:o}}return"tail"}insertEntryAt(e,t){let n=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled?1:0;if(t==="head")return this.promptQueue.unshift(e),n;if(typeof t=="object"){let r=t.afterMessageId,o=this.promptQueue.findIndex(i=>i.messageId===r);if(o>=0)return this.promptQueue.splice(o+1,0,e),n+o+1}return this.promptQueue.push(e),n+this.promptQueue.length-1}persistRewrite(){let e=[];for(let n of this.promptQueue)n.kind!=="user"||n.cancelled||e.push(this.persistedFromEntry(n));let t=this.sessionId;this.queueWriteChain=this.queueWriteChain.catch(()=>{}).then(()=>dn(t,e).catch(()=>{}))}persistedFromEntry(e){return{messageId:e.messageId,originator:{clientInfo:{...e.originator.name!==void 0?{name:e.originator.name}:{},...e.originator.version!==void 0?{version:e.originator.version}:{}}},prompt:e.prompt,enqueuedAt:e.enqueuedAt}}async drainQueue(){if(!this.promptInFlight){this.promptInFlight=!0,await new Promise(e=>setImmediate(e));try{for(;this.promptQueue.length>0&&!this.closing;){let e=this.promptQueue[0];if(e?.kind==="user"&&(await this.holdForUnsolicitedTurn(e),this.closing))break;let t=this.promptQueue.shift();if(!t)break;if(!t.cancelled){this.currentEntry=t,t.kind==="user"&&this.persistRewrite(),t.kind==="user"&&this.broadcastQueueRemoved(t.messageId,"started");try{let n=await this.runQueueEntry(t);t.resolve(n),await new Promise(r=>setImmediate(r))}catch(n){t.reject(n)}finally{this.currentEntry=void 0}}}}finally{this.promptInFlight=!1,this.supersededAutonomousTurn=void 0,this.dispatchIdle()}}}async runQueueEntry(e){if(e.kind==="internal")return this.closeUnsolicitedTurn("superseded",`internal:${e.label}`),e.task();this.broadcastPromptReceived(e);let t=gt(e.prompt).replace(/\s+$/,""),n=!t.includes(`
|
|
86
86
|
`)&&t.startsWith("/")?t.split(/\s+/)[0]??"":"",r=n.startsWith("/")?n.slice(1):"",o=r.length>0&&this.aliasableBareVerbs().has(r);if(n==="/model"||n==="/mode"||n==="/sessions"||n==="/help"||n==="/hydra"||o){let d;if(n==="/sessions")d=await this.handleSessionsCommand();else if(n==="/help")d=await this.handleHelpCommand();else if(n==="/mode")d=await this.handleModeCommand(t);else if(n==="/model")d=await this.handleModelCommand(t);else if(o){let c=t.slice(n.length).trim(),u=c?`/hydra ${r} ${c}`:`/hydra ${r}`;d=await this.handleSlashCommand(u,e.messageId)}else d=await this.handleSlashCommand(t,e.messageId);return this.closed||this.broadcastTurnComplete(e.clientId,d,e.messageId,this.originatorNeedsTurnComplete(e)),this.clearAmendIfMatches(e.messageId),d}if(this.clearRollbackBreadcrumbHook)try{this.clearRollbackBreadcrumbHook()}catch{}let i=e.prompt;n&&this.agentAdvertisedCommands.length>0&&!this.agentKnowsSlashCommand(n)&&(i=Hr(e.prompt,Yf));let a;this.agentTurnInFlight=!0;try{i=this.applyWorkspacePromptRewrite(i),a=await this.dispatchPrompt(e,i)}catch(d){if(this.forceCancelling)return this.clearAmendIfMatches(e.messageId),{stopReason:"cancelled"};throw this.closed||this.broadcastTurnComplete(e.clientId,{stopReason:"error"},e.messageId,this.originatorNeedsTurnComplete(e)),this.clearAmendIfMatches(e.messageId),d}finally{this.agentTurnInFlight=!1}return this.closed||this.broadcastTurnComplete(e.clientId,a,e.messageId,this.originatorNeedsTurnComplete(e)),this.clearAmendIfMatches(e.messageId),a}async dispatchPrompt(e,t){let n=()=>this.awaitPromptResponse(this.forwardRequest("session/prompt",{sessionId:this.sessionId,prompt:t},e.emitterName?new Set([e.emitterName]):new Set,e.chainStartIdx??0));try{return await n()}catch(r){if(!this.loadExistingAgentSession||!Ff(r))throw r;return this.logger?.warn(`agent ${this.agentId} no longer knows upstream session ${this.upstreamSessionId} for ${this.sessionId}; reloading it onto a fresh process and retrying the prompt once`),await this.reloadUpstreamAfterAgentLoss(),await n()}}clearAmendIfMatches(e){this.amendInProgress?.cancelledMessageId===e&&(this.amendInProgress=void 0)}},$f=["session not found","the claude agent session has ended"];function Ff(s){let e=s;if(e?.code!==x.InternalError)return!1;let t=e.data?.details,n=`${typeof e.message=="string"?e.message:""} ${typeof t=="string"?t:""}`.toLowerCase();return $f.some(r=>n.includes(r))}function be(s,e){return s.code=e,s}var Of=new Set(["session_info_update","_hydra_current_model_update","current_mode_update","available_commands_update","_hydra_available_modes_update","usage_update","config_option_update","_hydra_compaction"]);function Nf(s,e,t){return t?.run_in_background===!0?!1:e?.toolName==="Monitor"||s==="Monitor"||typeof e?.toolResponse?.taskId=="string"}function Df(s){return typeof s!="string"?void 0:/Command running in background with ID: ([A-Za-z0-9_-]+)/.exec(s)?.[1]}function jf(s){if(!s||typeof s!="object"||Array.isArray(s))return;let e=s.claudeCode;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,n={};return t.toolName!==void 0&&(n.toolName=t.toolName),t.toolResponse&&typeof t.toolResponse=="object"&&(n.toolResponse=t.toolResponse),n}function jr(s,e){if(s!=="session/update")return!1;let n=(e??{}).update?.sessionUpdate;return typeof n=="string"&&Of.has(n)}function Hf(s,e){if(s.length!==e.length)return!1;for(let t=0;t<s.length;t++)if(s[t]?.name!==e[t]?.name||s[t]?.description!==e[t]?.description)return!1;return!0}function Lf(s,e){if(s.length!==e.length)return!1;for(let t=0;t<s.length;t++)if(s[t]?.id!==e[t]?.id||s[t]?.name!==e[t]?.name||s[t]?.description!==e[t]?.description)return!1;return!0}function Uf(s,e){if(s.length!==e.length)return!1;for(let t=0;t<s.length;t++)if(s[t]?.modelId!==e[t]?.modelId||s[t]?.name!==e[t]?.name||s[t]?.description!==e[t]?.description)return!1;return!0}function cn(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object"||Array.isArray(t))continue;let n=t,r=typeof n.modelId=="string"&&n.modelId.trim()||typeof n.value=="string"&&n.value.trim()||typeof n.id=="string"&&n.id.trim()||void 0;if(!r)continue;let o={modelId:r};typeof n.name=="string"&&n.name.length>0&&(o.name=n.name),typeof n.description=="string"&&n.description.length>0&&(o.description=n.description),e.push(o)}return e}function Kn(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object"||Array.isArray(t))continue;let n=t,r=typeof n.value=="string"&&n.value.trim()||typeof n.id=="string"&&n.id.trim()||void 0;if(!r)continue;let o={id:r};typeof n.name=="string"&&n.name.length>0&&(o.name=n.name),typeof n.description=="string"&&n.description.length>0&&(o.description=n.description),e.push(o)}return e}function Ur(s){if(!Array.isArray(s))return[];let e=[];for(let t of s){if(!t||typeof t!="object"||Array.isArray(t))continue;let n=t,r=typeof n.value=="string"&&n.value.trim()||typeof n.id=="string"&&n.id.trim()||void 0;if(!r)continue;let o=typeof n.name=="string"&&n.name.trim()?n.name.trim():r,i={value:r,name:o};typeof n.description=="string"&&n.description.length>0&&(i.description=n.description),e.push(i)}return e}function Bf(s){let t=(s??{}).update??{};if(t.sessionUpdate!=="_hydra_available_modes_update")return null;let n=t.availableModes;if(!Array.isArray(n))return[];let r=[];for(let o of n){if(!o||typeof o!="object")continue;let i=o;if(typeof i.id!="string"||i.id.length===0)continue;let a={id:i.id};typeof i.name=="string"&&(a.name=i.name),typeof i.description=="string"&&(a.description=i.description),r.push(a)}return r}function Wf(s,e){let n=(e??{}).update??{},r=n.sessionUpdate;if(r==="agent_message_chunk"){let o=n.content??{};typeof o.text=="string"&&(s.chunks.push(o.text),s.messageChars+=o.text.length);return}if(r==="agent_thought_chunk"){let o=n.content??{};typeof o.text=="string"&&(s.thinkingChars+=o.text.length);return}if(r==="tool_call"){s.toolCalls++;return}if(r==="usage_update"){typeof n.used=="number"&&(s.lastUsed=n.used),typeof n.size=="number"&&(s.lastSize=n.size);return}}function qf(s){let t=(s??{}).update??{};if(t.sessionUpdate!=="available_commands_update")return null;let n=t.availableCommands??t.commands;if(!Array.isArray(n))return[];let r=[];for(let o of n){if(!o||typeof o!="object")continue;let i=o;if(typeof i.name!="string"||i.name.length===0)continue;let a={name:i.name};typeof i.description=="string"&&(a.description=i.description),r.push(a)}return r}function zf(s,e){if(s!=="session/update"||!e||typeof e!="object")return e;let t=e;return!t.update||typeof t.update!="object"||Array.isArray(t.update)||typeof t.update.messageId=="string"?e:{...e,update:{...t.update,messageId:We()}}}function Jf(s,e){if(s.length<=e)return s;let t=s.length-e;for(let n=t;n>=0;n--)if(s[n]?.params?.update?.sessionUpdate==="prompt_received")return s.slice(n);return s.slice(t)}function Vf(s,e){for(let t=s.length-1;t>=0;t--)if(s[t]?.seq===e)return t;return-1}function Qn(s,e){for(let t=s.length-1;t>=0;t--){let n=s[t];if(!n||n.method!=="session/update")continue;if(n.params?.update?.messageId===e)return t}return-1}function ba(s){if(!s||typeof s!="object")return;let e=s.toolCall;if(!e||typeof e!="object")return;let t=e.toolCallId;return typeof t=="string"?t:void 0}function Gf(s){let e=Kf(s.result),t={sessionUpdate:"permission_resolved"};return s.toolCallId!==void 0&&(t.toolCallId=s.toolCallId),e&&(t.outcome=e,e.kind==="selected"&&typeof e.optionId=="string"&&(t.chosenOptionId=e.optionId)),t.resolvedBy=Qf(s.resolver),t}function Kf(s){if(!s||typeof s!="object")return;let e=s.outcome;if(!e||typeof e!="object")return;let t=e.kind;if(typeof t!="string")return;let n={kind:t},r=e.optionId;typeof r=="string"&&(n.optionId=r);let o=e.reason;return typeof o=="string"&&(n.reason=o),n}function Qf(s){let e={clientId:s.clientId};return s.clientInfo?.name&&(e.name=s.clientInfo.name),s.clientInfo?.version&&(e.version=s.clientInfo.version),e}function gt(s){return typeof s=="string"?s:Array.isArray(s)?s.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?e.text:"").join(""):""}var Yf="\u200B";function Sa(s,e){return s.map(t=>{if(t&&typeof t=="object"&&typeof t.text=="string"){let n=t;return{...n,text:e(n.text)}}return t})}function Hr(s,e){let t=s.findIndex(o=>o&&typeof o=="object"&&typeof o.text=="string");if(t<0)return s;let n=s[t],r=[...s];return r[t]={...n,text:`${e}${n.text}`},r}function Lr(s){return s==="session/prompt"?{stopReason:"stopped"}:{}}function Xf(s){return s==="session/request_permission"?{outcome:{outcome:"cancelled"}}:{}}function Ia(s){let e=s.name&&s.name!==s.id?`${s.id} (${s.name}) \u2014 \u25B6 ${s.currentValue}`:`${s.id} \u2014 \u25B6 ${s.currentValue}`;if(s.options.length===0)return e;let t=Math.max(...s.options.map(r=>r.value.length)),n=s.options.map(r=>{let o=r.value===s.currentValue?"\u25B6":"\xB7",i=r.name&&r.name!==r.value,a=i?r.value.padEnd(t):r.value;return i?` ${o} ${a} ${r.name}`:` ${o} ${a}`});return`${e}
|
|
87
87
|
${n.join(`
|
|
88
|
-
`)}`}function Br(s,e){for(let t of s.split(/\r?\n/)){let n=t.trim();if(n)return n.length>e?`${n.slice(0,e)}\u2026`:n}}Y();Oe();import*as xe from"fs/promises";import*as
|
|
88
|
+
`)}`}function Br(s,e){for(let t of s.split(/\r?\n/)){let n=t.trim();if(n)return n.length>e?`${n.slice(0,e)}\u2026`:n}}Y();Oe();import*as xe from"fs/promises";import*as $k from"path";import{customAlphabet as tp}from"nanoid";import{z as P}from"zod";import{z as Ot}from"zod";var Zf=Ot.object({source:Ot.string(),reason:Ot.string(),raisedAt:Ot.number(),payload:Ot.unknown()}),Ea=Ot.array(Zf);import{z as K}from"zod";var Ta=K.object({status:K.enum(["requested","running","swap_pending","swap_deferred","failed"]),requestedAt:K.number(),runId:K.string().optional(),iter:K.number().int().nonnegative().optional(),attempts:K.number().int().nonnegative().optional(),lastError:K.string().optional(),worker:K.object({upstreamSessionId:K.string(),pid:K.number().int().nonnegative()}).optional()}),un=K.object({goal:K.string().optional(),outcome:K.string().optional(),files_touched:K.array(K.string()).optional(),tools_used:K.array(K.string()).optional(),rejected_approaches:K.array(K.string()).optional(),open_threads:K.array(K.string()).optional(),decisions:K.array(K.string()).optional(),file_edit_intentions:K.array(K.string()).optional(),unresolved_errors:K.array(K.string()).optional(),tool_state:K.array(K.string()).optional()}),Pa=200,Wr=`Reply with ONLY a JSON object with exactly these keys, no prose, no markdown, no code fences:
|
|
89
89
|
{
|
|
90
90
|
"title": "short summary, max 80 chars",
|
|
91
91
|
"synopsis": {
|
|
@@ -190,11 +190,11 @@ ${E}`)}await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),th
|
|
|
190
190
|
`);let C=A;typeof C.recordedAt=="number"&&E.add(String(C.recordedAt))}for(;v.length>0;){let A=v.splice(0,v.length);for(let C of A){let T=C,M=typeof T.recordedAt=="number"?String(T.recordedAt):"";M&&E.has(M)||p.raw.write(JSON.stringify(C)+`
|
|
191
191
|
`)}}return b=!0,k||p.raw.end(),p});function i(l,p,m){let h=typeof l=="string"?l.trim():"";if(h.length===0)return null;let f;try{f=JSON.parse(h)}catch{return console.debug("events endpoint: skipping malformed JSONL line"),null}if(!f||typeof f!="object"||Array.isArray(f))return console.debug("events endpoint: skipping non-object JSONL line"),null;let g=f;if(typeof g.recordedAt!="number"||m!==void 0&&g.recordedAt<m||typeof g.params!="object"||g.params===null||Array.isArray(g.params))return null;let w=g.params;if(typeof w.update!="object"||w.update===null||Array.isArray(w.update))return null;let k=w.update.sessionUpdate;return typeof k!="string"||!p.has(k)?null:{recordedAt:g.recordedAt,entry:f}}function a(l,p,m){let f=p.params.update,g={sessionId:l,ts:new Date(p.recordedAt).toISOString(),kind:m,update:f};return f.messageId!==void 0&&f.messageId!==null&&(g.messageId=f.messageId),g}async function*d(l,p,m,h){for await(let f of p){let g=i(f,m,h);if(g){let w=g.entry.params.update.sessionUpdate;yield{ts:g.recordedAt,row:a(l,g.entry,w)}}}}async function c(l,p,m,h){let f=Po.createInterface({input:To.createReadStream(p),crlfDelay:1/0}),g=d(l,f,m,h),w=await g.next(),y=w.done?null:w.value;return{sessionId:l,rl:f,gen:g,current:y,exhausted:y===null}}async function u(l){let p=await l.gen.next();p.done?(l.exhausted=!0,l.current=null):l.current=p.value}s.get("/v1/sessions/events",async(l,p)=>{let m=l.query,h=m.kinds;if(!h||h.trim().length===0)return p.code(400).send({error:"kinds parameter is required"}),p;let f=h.split(",").map(S=>S.trim());if(f.length===0)return p.code(400).send({error:"kinds parameter is required"}),p;for(let S of f)if(!Os.has(S))return p.code(400).send({error:`kind "${S}" is not queryable; allowed kinds: ${[...Os].join(", ")}`}),p;let g=new Set(f),w;if(m.since!==void 0&&m.since.trim().length>0){let S=new Date(m.since);if(isNaN(S.getTime()))return p.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),p;w=S.getTime()}let y=await e.list({includeNonInteractive:!0}),k=w!==void 0?y.filter(S=>new Date(S.updatedAt).getTime()>=w):y;p.raw.setHeader("content-type","application/x-ndjson"),p.raw.statusCode=200;let b=[];for(let S of k)try{let v=R.historyFile(S.sessionId),E=await c(S.sessionId,v,g,w);E.exhausted||b.push(E)}catch(v){if(v.code==="ENOENT")continue;throw v}l.raw.on("close",()=>{for(let S of b)try{S.rl.close()}catch{}p.raw.writableEnded||p.raw.end()});try{for(;b.length>0;){let S=-1,v=1/0;for(let A=0;A<b.length;A++){let C=b[A];C.current!==null&&C.current.ts<v&&(v=C.current.ts,S=A)}if(S===-1)break;let E=b[S];if(p.raw.write(JSON.stringify(E.current.row)+`
|
|
192
192
|
`),await u(E),E.exhausted){try{E.rl.close()}catch{}b.splice(S,1)}}}catch(S){for(let v of b)try{v.rl.close()}catch{}throw S}return p.raw.end(),p}),s.get("/v1/sessions/:id/events",async(l,p)=>{let m=l.params.id,h=l.query,f=await e.resolveCanonicalId(m)??m;if(!e.get(f)&&!await e.hasRecord(f))return p.code(404).send({error:"session not found"}),p;let w=h.kinds;if(!w||w.trim().length===0)return p.code(400).send({error:"kinds parameter is required"}),p;let y=w.split(",").map(A=>A.trim());if(y.length===0)return p.code(400).send({error:"kinds parameter is required"}),p;for(let A of y)if(!Os.has(A))return p.code(400).send({error:`kind "${A}" is not queryable; allowed kinds: ${[...Os].join(", ")}`}),p;let k=new Set(y),b;if(h.since!==void 0&&h.since.trim().length>0){let A=new Date(h.since);if(isNaN(A.getTime()))return p.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),p;b=A.getTime()}let S=R.historyFile(f),v=To.createReadStream(S),E=Po.createInterface({input:v,crlfDelay:1/0});p.raw.setHeader("content-type","application/x-ndjson"),p.raw.statusCode=200;try{for await(let A of E){let C=typeof A=="string"?A.trim():"";if(C.length===0)continue;let T;try{T=JSON.parse(C)}catch{console.debug("events endpoint: skipping malformed JSONL line in %s",S);continue}if(!T||typeof T!="object"||Array.isArray(T)){console.debug("events endpoint: skipping non-object JSONL line in %s",S);continue}let M=T;if(typeof M.recordedAt!="number"||typeof M.params!="object"||M.params===null||Array.isArray(M.params))continue;let H=M.params;if(typeof H.update!="object"||H.update===null||Array.isArray(H.update))continue;let J=H.update,$=J.sessionUpdate;if(typeof $!="string"||!k.has($)||b!==void 0&&M.recordedAt<b)continue;let W={ts:new Date(M.recordedAt).toISOString(),kind:$,update:J};J.messageId!==void 0&&J.messageId!==null&&(W.messageId=J.messageId),p.raw.write(JSON.stringify(W)+`
|
|
193
|
-
`)}}catch(A){if(A.code==="ENOENT")return p.raw.end(),p;throw A}return p.raw.end(),p}),s.post("/v1/sessions/:id/prompt/:messageId/notify",async(l,p)=>{let m=l.params,h=m.id,f=await e.resolveCanonicalId(h)??h,g=m.messageId,w=l.body,y=typeof w?.callbackUrl=="string"?w.callbackUrl:"",k=typeof w?.secret=="string"?w.secret:"";if(!g||!y||!k){p.code(400).send({error:"messageId, callbackUrl, and secret are all required"});return}let b;try{b=new URL(y)}catch{p.code(400).send({error:"callbackUrl must be a valid absolute URL"});return}if(b.protocol!=="https:"&&b.protocol!=="http:"){p.code(400).send({error:"callbackUrl must be http or https"});return}let S=e.get(f);if(!S){p.code(404).send({error:"session not found or not warm"});return}let v=S.registerTurnNotify(g,y,k);if(v.alreadyTerminal){p.code(200).send({status:"already_terminal",stopReason:v.stopReason});return}p.code(202).send({status:"registered"})}),s.get("/v1/sessions/:id/attention",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=e.get(h);return!f&&!await e.hasRecord(h)?(p.code(404).send({error:"session not found"}),p):f?{flags:f.listAttentionFlags()}:{flags:(await e.store.read(h))?.attentionFlags??[]}}),s.get("/v1/sessions/attention",async(l,p)=>{let m=l.query;if(!m.source||m.source.trim().length===0)return p.code(400).send({error:"source query parameter is required"}),p;let h=await e.list({includeNonInteractive:!0}),f=[];for(let g of h){let w=e.get(g.sessionId),y;w?y=w.listAttentionFlags():y=(await e.store.read(g.sessionId))?.attentionFlags??[];for(let k of y)k.source===m.source&&f.push({...k,sessionId:g.sessionId})}return{flags:f}}),s.post("/v1/sessions/:id/attention/clear",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,g=l.body??{},w=typeof g.source=="string"?g.source:"",y=typeof g.reason=="string"?g.reason:"";if((w.length>0||y.length>0)&&!(w.length>0&&y.length>0)){p.code(400).send({error:"both source and reason are required to clear a specific flag, or omit both to clear all"});return}w.length===0&&y.length;let k=e.get(h);if(k){if(w.length>0&&y.length>0)k.clearAttentionFlag(w,y);else{let A=Array.from(k.listAttentionFlags()).map(C=>`${C.source}::${C.reason}`);for(let C of A)k.clearAttentionFlag(C.split("::")[0],C.split("::").slice(1).join("::"))}p.code(204).send();return}if(!await e.hasRecord(h)){p.code(404).send({error:"session not found"});return}let b=e.store,S=await b.read(h);if(!S){p.code(404).send({error:"session not found"});return}let v=S.attentionFlags??[],E;if(w.length>0&&y.length>0){let A=`${w}::${y}`;E=v.filter(C=>`${C.source}::${C.reason}`!==A)}else E=[];if(E.length===v.length&&E.every((A,C)=>A.source===v[C].source&&A.reason===v[C].reason)){p.code(204).send();return}await b.write({...S,attentionFlags:E}),p.code(204).send()})}function yc(s,e,t,n={}){s.get("/v1/agents",async()=>Rt(e)),s.get("/v1/registry",async()=>e.load()),s.post("/v1/registry/refresh",async()=>{let r=await e.refresh();return{version:r.version,agentCount:r.agents.length}}),s.post("/v1/agents/:id/install",async(r,o)=>{let i=r.params.id,a=await e.getAgent(i);if(!a){o.code(404).send({error:`agent ${i} not found in registry`});return}if(a.distribution.uvx&&!a.distribution.npx&&!a.distribution.binary){o.send({agentId:a.id,version:a.version??"current",distribution:"uvx",installed:!1,message:"uvx agents resolve on first run; nothing to pre-install."});return}try{let d=await Re(a,[],{npmRegistry:n.npmRegistry}),c=a.distribution.npx?"npx":a.distribution.binary?"binary":"unknown";o.send({agentId:a.id,version:d.version,distribution:c,installed:!0,command:d.command})}catch(d){o.code(500).send({error:d.message})}}),s.post("/v1/agents/:id/sync",async(r,o)=>{let i=r.params.id;try{let{synced:a,skipped:d}=await t.syncFromAgent(i);return{synced:a.map(c=>({sessionId:c.sessionId,upstreamSessionId:c.upstreamSessionId,agentId:c.agentId,cwd:c.cwd,title:c.title,updatedAt:c.updatedAt})),skipped:d}}catch(a){let d=a;if(d.code===x.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}Y();function wc(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:R.home(),driftedKeys:n()}))}var Bm=/^[A-Za-z0-9._-]+$/;function Ds(s,e,t){let n=e==="extension"?"extensions":"transformers",r=`/v1/${n}`;s.get(r,async()=>({[n]:t.list()})),s.get(`${r}/:name`,async(o,i)=>{let a=o.params.name,d=t.get(a);if(!d){i.code(404).send({error:`unknown ${e}: ${a}`});return}return d}),s.post(r,async(o,i)=>{let a=o.body??{},d=Wm(a);if("error"in d){i.code(400).send({error:d.error});return}try{let c=t.register(d.config);i.code(201).send(c)}catch(c){Pn(i,c)}}),s.delete(`${r}/:name`,async(o,i)=>{let a=o.params.name;try{await t.unregister(a),i.code(204).send()}catch(d){Pn(i,d)}}),s.post(`${r}/:name/start`,async(o,i)=>{let a=o.params.name;try{let d=await t.startByName(a);i.code(200).send(d)}catch(d){Pn(i,d)}}),s.post(`${r}/:name/stop`,async(o,i)=>{let a=o.params.name;try{let d=await t.stopByName(a);i.code(200).send(d)}catch(d){Pn(i,d)}}),s.post(`${r}/:name/restart`,async(o,i)=>{let a=o.params.name;try{let d=await t.restartByName(a);i.code(200).send(d)}catch(d){Pn(i,d)}})}function Pn(s,e){let t=e.code,n=e.message??"unknown error";if(t==="NOT_FOUND"){s.code(404).send({error:n});return}if(t==="CONFLICT"){s.code(409).send({error:n});return}s.code(500).send({error:n})}function Wm(s){let e=s.name;if(typeof e!="string"||!Bm.test(e))return{error:"name must match [A-Za-z0-9._-]+"};let t=s.command;if(t!==void 0&&(!Array.isArray(t)||t.some(i=>typeof i!="string")))return{error:"command must be string[]"};let n=s.args;if(n!==void 0&&(!Array.isArray(n)||n.some(i=>typeof i!="string")))return{error:"args must be string[]"};let r=s.env;if(r!==void 0&&(typeof r!="object"||r===null||Array.isArray(r)))return{error:"env must be an object of string\u2192string"};if(r&&Object.values(r).some(i=>typeof i!="string"))return{error:"env values must be strings"};let o=s.enabled;return o!==void 0&&typeof o!="boolean"?{error:"enabled must be a boolean"}:{config:{name:e,command:t??[],args:n??[],env:r??{},enabled:o===void 0?!0:o}}}function kc(s,e){Ds(s,"extension",e)}function vc(s,e){Ds(s,"transformer",e)}function bc(s,e){s.get("/v1/config",async()=>e())}import{z as it}from"zod";Y();import*as zt from"fs/promises";import*as Sc from"path";import{randomBytes as iI,scrypt as qm,timingSafeEqual as zm}from"crypto";import{promisify as Jm}from"util";var Vm=Jm(qm);function Ic(){return Sc.join(R.home(),"password-hash")}var Gm=128*1024*1024;async function Ac(){try{return(await zt.readFile(Ic(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function Cc(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await zt.readFile(Ic(),"utf8")).trim()}catch(c){if(c.code==="ENOENT")return!1;throw c}let t=e.split("$");if(t.length!==6||t[0]!=="scrypt")return!1;let n=parseInt(t[1],10),r=parseInt(t[2],10),o=parseInt(t[3],10);if(!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(o))return!1;let i=Buffer.from(t[4],"hex"),a=Buffer.from(t[5],"hex");if(i.length===0||a.length===0)return!1;let d=await Vm(s,i,a.length,{N:n,r,p:o,maxmem:Gm});return d.length!==a.length?!1:zm(d,a)}var Km=it.object({password:it.string().min(1),label:it.string().min(1).max(256).optional(),ttlSec:it.number().int().positive().optional()}),Qm=it.object({id:it.string().optional()}).optional(),Ym=it.object({token:it.string().min(32)});function Rc(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=Xm(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=Km.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await Ac())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await Cc(o.password))return e.rateLimiter.recordFailure(r),n.code(401).send({error:"Invalid password"});e.rateLimiter.recordSuccess(r);let a=await e.store.issue({label:o.label,ttlSec:o.ttlSec});return n.code(200).send({session_token:a.token,id:a.id,expires_at:a.expiresAt})}),s.post("/v1/auth/logout",async(t,n)=>{let r;try{r=Qm.parse(t.body??void 0)}catch{return n.code(400).send({error:"Invalid request body"})}let o=r?.id??t.authIdentity;if(!o||o==="service")return n.code(200).send({revoked:!1});let i=await e.store.revoke(o);return n.code(200).send({revoked:i})}),s.get("/v1/auth/verify",async(t,n)=>n.code(200).send({ok:!0})),s.get("/v1/auth/sessions",async(t,n)=>n.code(200).send({sessions:e.store.list()})),s.delete("/v1/auth/sessions",async(t,n)=>{let r=await e.store.revokeAll();return n.code(200).send({revoked:r})}),s.delete("/v1/auth/sessions/:id",async(t,n)=>{let r=t.params.id;return await e.store.revoke(r)?n.code(204).send():n.code(404).send({error:"Not found"})}),s.post("/v1/auth/rotate-token",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=Ym.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}return e.staticTokenValidator.rotate(r.token),n.code(200).send({rotated:!0})})}function Xm(s){return s.ip||"unknown"}import{z as at}from"zod";Y();Oe();var Mo=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,js=class s{data;constructor(e){this.data=e}static async load(){let e=await oe(R.peers());return new s(Zm(e))}get(e){return this.data.entries[e]}async set(e){this.data.entries[e.name]=e,await xc(this.data)}async delete(e){return e in this.data.entries?(delete this.data.entries[e],await xc(this.data),!0):!1}list(){return Object.values(this.data.entries).map(({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})=>({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})).sort((e,t)=>e.addedAt.localeCompare(t.addedAt))}};function Zm(s){if(!s||typeof s!="object")return{version:1,entries:{}};let e=s,t=e.entries&&typeof e.entries=="object"?e.entries:{},n={};for(let[r,o]of Object.entries(t)){if(!o||typeof o!="object")continue;let i=o;if(typeof i.name!="string"||typeof i.host!="string"||typeof i.port!="number"||typeof i.token!="string"||typeof i.expiresAt!="string"||typeof i.addedAt!="string")continue;let a={name:i.name,host:i.host,port:i.port,token:i.token,expiresAt:i.expiresAt,addedAt:i.addedAt};typeof i.label=="string"&&(a.label=i.label),typeof i.pinnedFingerprint=="string"&&(a.pinnedFingerprint=i.pinnedFingerprint),typeof i.pinnedAt=="string"&&(a.pinnedAt=i.pinnedAt),n[r]=a}return{version:1,entries:n}}async function xc(s){await ue(R.peers(),s,{mode:384})}var Je=class extends Error{status;constructor(e,t){super(e),this.name="PeerLoginError",this.status=t}};function Ec(s,e){return`${Te(s)?"http":"https"}://${s}:${e}`}async function Tc(s){let e=s.fetchImpl??fetch,t=`${s.host}:${s.port}`,n=Ec(s.host,s.port),r;try{r=await e(`${n}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:s.password,label:s.label,ttlSec:s.ttlSec})})}catch(i){throw new Je(`Could not reach ${t}: ${i.message}`,502)}if(r.status===401)throw new Je(`Wrong password for ${t}.`,401);if(r.status===403)throw new Je(`No password is configured on ${t}. Run \`hydra-acp auth password\` on that daemon first.`,502);if(r.status===429)throw new Je(`Too many failed login attempts on ${t}; try again later.`,429);if(!r.ok)throw new Je(`Login to ${t} failed: HTTP ${r.status}`,502);let o=await r.json();if(!o.session_token||!o.expires_at)throw new Je(`Login to ${t} returned a malformed response.`,502);return{token:o.session_token,expiresAt:o.expires_at}}async function Pc(s){let e=s.fetchImpl??fetch,t=Ec(s.host,s.port);try{await e(`${t}/v1/auth/logout`,{method:"POST",headers:{Authorization:`Bearer ${s.token}`,"Content-Type":"application/json"},body:JSON.stringify({})})}catch{}}_n();var lh=at.object({name:at.string().min(1).max(64).regex(Mo),host:at.string().min(1),port:at.number().int().positive().optional(),password:at.string().min(1),label:at.string().min(1).max(256).optional(),ttlSec:at.number().int().positive().optional(),pinnedFingerprint:at.string().min(1).optional()});function Hc(s,e){s.post("/v1/remotes",async(t,n)=>{let r;try{r=lh.parse(t.body)}catch{return n.code(400).send({error:`Invalid request body (name must match ${Mo} and the rest is a normal login request)`})}let o=r.port??St;r.pinnedFingerprint&&Mn(r.host,o,r.pinnedFingerprint);let i;try{i=await Tc({host:r.host,port:o,password:r.password,label:r.label,ttlSec:r.ttlSec})}catch(c){if(c instanceof Je)return n.code(c.status).send({error:c.message});throw c}let a=new Date().toISOString(),d={name:r.name,host:r.host,port:o,token:i.token,expiresAt:i.expiresAt,addedAt:a,...r.label!==void 0?{label:r.label}:{},...r.pinnedFingerprint!==void 0?{pinnedFingerprint:r.pinnedFingerprint,pinnedAt:a}:{}};return await e.store.set(d),e.health?.markOk(d.name),n.code(201).send({name:d.name,host:d.host,port:d.port,expiresAt:d.expiresAt,label:d.label,addedAt:d.addedAt,pinnedFingerprint:d.pinnedFingerprint,status:e.health?.get(d.name)?.status??"unknown"})}),s.get("/v1/remotes",async(t,n)=>{let r=e.store.list().map(o=>{let i=e.health?.get(o.name);return{...o,status:i?.status??"unknown",...i?.checkedAt?{lastCheckedAt:i.checkedAt}:{}}});return n.code(200).send({remotes:r})}),s.delete("/v1/remotes/:name",async(t,n)=>{let r=t.params.name,o=e.store.get(r);return o?(await Pc({host:o.host,port:o.port,token:o.token}),await e.store.delete(r),e.health?.forget(r),e.store.list().some(a=>a.host===o.host&&a.port===o.port)||$o(o.host,o.port),n.code(204).send()):n.code(404).send({error:"Not found"})})}function Ls(s){let e=[],t=[],n=!1,r=o=>{if(!n){n=!0;for(let i of t)i(o)}};return s.on("message",(o,i)=>{if(i)return;let a=o.toString("utf8");try{let d=JSON.parse(a);for(let c of e)c(d)}catch(d){for(let c of e)c({jsonrpc:"2.0",id:null,error:{code:x.ParseError,message:`Failed to parse WS frame: ${d.message}`}})}}),s.on("close",()=>r()),s.on("error",o=>r(o)),{async send(o){if(n)throw new Error("ws is closed");let i=JSON.stringify(o);await new Promise((a,d)=>{s.send(i,c=>{if(c){d(c);return}a()})})},onMessage(o){e.push(o)},onClose(o){t.push(o)},async close(){n||(await new Promise(o=>{let i=!1,a=()=>{i||(i=!0,clearTimeout(d),o())},d=setTimeout(a,5e3);s.once("close",a);try{s.close()}catch{a()}}),r())}}}_n();import{WebSocket as fh}from"ws";var ph=1e4,jo=class extends Error{url;elapsedMs;constructor(e,t){super(`hydra-acp: websocket connect to ${e} timed out after ${t}ms`),this.name="WsConnectTimeoutError",this.url=e,this.elapsedMs=t}};async function Lc(s,e,t=ph){let n={};try{let r=new URL(s);if(r.protocol==="wss:"){let o=Do(r.hostname);o.rejectUnauthorized!==void 0&&(n.rejectUnauthorized=o.rejectUnauthorized),o.autoSelectFamily!==void 0&&(n.autoSelectFamily=o.autoSelectFamily),o.checkServerIdentity!==void 0&&(n.checkServerIdentity=o.checkServerIdentity)}}catch{}return new Promise((r,o)=>{let i=new fh(s,e,n),a=Date.now(),d=setTimeout(()=>{i.off("open",c),i.off("error",u),i.on("error",()=>{});try{i.terminate()}catch{}o(new jo(s,Date.now()-a))},t),c=()=>{clearTimeout(d),i.off("error",u),r(i)},u=l=>{clearTimeout(d),i.off("open",c),o(l)};i.once("open",c),i.once("error",u)})}var gh=new Set(["session/attach","session/detach","session/prompt","session/cancel"]);function mh(s){return gh.has(s)}function Bc(s,e,t,n){let r=[];return s.onMessage(o=>{if("method"in o&&mh(o.method)){let i=o.params,a=typeof i?.sessionId=="string"?i.sessionId:void 0;if(a&&pt(a)){e.handleLocalMessage(o,a,{connection:t.connection,clientId:n}).then(d=>d?s.send(d):void 0).catch(()=>{});return}}for(let i of r)i(o)}),{send:o=>s.send(o),onMessage:o=>r.push(o),onClose:o=>s.onClose(o),close:()=>s.close()}}var Bs=class{constructor(e,t=yh){this.store=e;this.dial=t}store;dial;attachments=new Map;async handleLocalMessage(e,t,n){let r="id"in e,o=r?e.id:void 0,i=pt(t);if(!i)return r?Us(o,x.SessionNotFound,`not a federated session id: ${t}`):void 0;let a=Uc(n.clientId,t),d={...e.params,sessionId:i.localId};if(e.method==="session/attach"){let u=this.store.get(i.name);if(!u)return r?Us(o,x.SessionNotFound,`No remote named "${i.name}". Run \`hydra remote add\` first.`):void 0;let l=this.attachments.get(a);l&&(this.attachments.delete(a),l.peerConnection.close().catch(()=>{}));let p;try{p=await this.dial(u)}catch(g){return r?Us(o,x.InternalError,`Could not reach remote "${i.name}": ${g.message}`):void 0}let m;try{m=await p.request("session/attach",d)}catch(g){return p.close().catch(()=>{}),r?Ho(o,g):void 0}let h={peerConnection:p,localId:i.localId,target:n};this.wireAttachment(i.name,h),this.attachments.set(a,h);let f=m&&typeof m.sessionId=="string"?{...m,sessionId:t}:m;return r?{jsonrpc:"2.0",id:o,result:f}:void 0}let c=this.attachments.get(a);if(!c)return r?Us(o,x.SessionNotFound,`"${t}" is not attached through this daemon.`):void 0;if(e.method==="session/detach"){let u,l;try{u=await c.peerConnection.request("session/detach",d)}catch(p){l=p}return this.attachments.delete(a),c.peerConnection.close().catch(()=>{}),l?r?Ho(o,l):void 0:r?{jsonrpc:"2.0",id:o,result:u??{}}:void 0}if(r)try{let u=await c.peerConnection.request(e.method,d);return{jsonrpc:"2.0",id:o,result:u}}catch(u){return Ho(o,u)}await c.peerConnection.notify(e.method,d).catch(()=>{})}detachClient(e){for(let[t,n]of[...this.attachments.entries()])n.target.clientId===e&&(this.attachments.delete(t),n.peerConnection.request("session/detach",{sessionId:n.localId}).catch(()=>{}),n.peerConnection.close().catch(()=>{}))}wireAttachment(e,t){let{peerConnection:n,localId:r,target:o}=t,i=Tt({name:e,localId:r}),a=()=>{this.attachments.delete(Uc(o.clientId,i))};n.onNotification("session/update",d=>{let c=d;!c||c.sessionId!==r||o.connection.notify("session/update",{...c,sessionId:i}).catch(()=>{})}),n.onNotification("hydra-acp/session/closed",d=>{let c=d;!c||c.sessionId!==r||(a(),o.connection.notify("hydra-acp/session/closed",{sessionId:i}).catch(()=>{}))}),n.onRequest("hydra-acp/session/request_permission",async d=>{let c=d;if(!c||c.sessionId!==r)throw{code:x.MethodNotFound,message:"unexpected sessionId"};return o.connection.request("hydra-acp/session/request_permission",{...c,sessionId:i})}),n.onClose(()=>{a(),o.connection.notify("hydra-acp/session/closed",{sessionId:i}).catch(()=>{})})}};function Uc(s,e){return`${s} ${e}`}function Us(s,e,t){return{jsonrpc:"2.0",id:s,error:{code:e,message:t}}}function Ho(s,e){let t=e,n=typeof t?.code=="number"?t.code:x.InternalError,r=typeof t?.message=="string"?t.message:String(e??"forward failed");return{jsonrpc:"2.0",id:s,error:{code:n,message:r,...t?.data!==void 0?{data:t.data}:{}}}}var hh=1e4;async function yh(s){let t=`${Te(s.host)?"ws":"wss"}://${s.host}:${s.port}/acp`,n=await Lc(t,["acp.v1",`hydra-acp-token.${s.token}`],hh);return new nt(Ls(n))}var wh=3e4,kh=5e3,Ws=class{constructor(e,t={}){this.store=e;this.opts=t}store;opts;snapshots=new Map;timer;start(){this.timer||(this.checkAll(),this.timer=setInterval(()=>{this.checkAll()},this.opts.intervalMs??wh),this.timer.unref?.())}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}get(e){return this.snapshots.get(e)}markOk(e){this.snapshots.set(e,{status:"ok",checkedAt:new Date().toISOString()})}forget(e){this.snapshots.delete(e)}async checkAll(){let e=this.opts.fetchImpl??fetch;await Promise.allSettled(this.store.list().map(async t=>{let n=this.store.get(t.name);if(!n)return;let o=`${Te(n.host)?"http":"https"}://${n.host}:${n.port}/v1/auth/verify`,i=new AbortController,a=setTimeout(()=>i.abort(),kh);try{let d=await e(o,{headers:{Authorization:`Bearer ${n.token}`},signal:i.signal});this.snapshots.set(t.name,{status:d.ok?"ok":"unauthorized",checkedAt:new Date().toISOString()})}catch(d){this.snapshots.set(t.name,{status:"unreachable",checkedAt:new Date().toISOString(),error:d.message})}finally{clearTimeout(a)}}))}};_n();import{z as Wc}from"zod";var vh=Wc.object({sessionLabel:Wc.string().min(1).max(256)});function qc(s,e){s.post("/v1/process-tokens",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=vh.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}let o=e.processRegistry.mint(r.sessionLabel,"script");return n.code(201).send({token:o})}),s.delete("/v1/process-tokens/:sessionLabel",async(t,n)=>t.authIdentity!=="service"?n.code(403).send({error:"Requires the service token"}):(e.processRegistry.revoke(t.params.sessionLabel),n.code(204).send()))}import{nanoid as Lo}from"nanoid";import{randomBytes as Kc}from"crypto";import*as Qc from"os";import*as Yc from"path";var bh=200;function Sh(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e[ae];if(!t||typeof t!="object"||Array.isArray(t))return;let n=t.sentBy;if(!n||typeof n!="object"||Array.isArray(n))return;let r=n,o={};if(typeof r.sessionId=="string"&&r.sessionId.length>0&&(o.sessionId=r.sessionId),typeof r.label=="string"&&r.label.length>0&&(o.label=r.label.slice(0,bh)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function zc(s,e,t){let n=Sh(s);if(!n)return;let r={};if(n.label!==void 0&&(r.fromLabel=n.label),n.awaiting===!0&&(r.awaiting=!0),n.sessionId!==void 0){let o=await e.resolveCanonicalId(n.sessionId)??n.sessionId,i=await e.getOne(o);if(i){r.fromSession=o,i.title&&(r.fromSessionTitle=i.title);let a=e.get(o)?.currentPromptDepth;r.depth=(a??0)+1}else t?.(n.sessionId)}if(!(r.fromSession===void 0&&r.fromLabel===void 0))return r}var $n=new Map;function Jc(s,e){let t=$n.get(s);t||(t=new Set,$n.set(s,t)),t.add(e);let n=!1;return()=>{if(n)return;n=!0;let r=$n.get(s);r&&(r.delete(e),r.size===0&&$n.delete(s))}}function Vc(s,e){if(s===e)return!0;let t=new Set,n=[e];for(;n.length>0;){let r=n.pop();if(t.has(r))continue;t.add(r);let o=$n.get(r);if(o){if(o.has(s))return!0;for(let i of o)n.push(i)}}return!1}function O(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function xh(s){if(!s||typeof s!="object")return 512;let n=s.params?.update;if(!n)return 512;let r=512,o=n.content;if(typeof o=="string")r+=o.length;else if(o&&typeof o=="object"){let a=o;typeof a.text=="string"&&(r+=a.text.length),typeof a.data=="string"&&(r+=a.data.length)}let i=n.toolCall;if(i&&(typeof i.rawInput=="string"?r+=i.rawInput.length:i.rawInput&&typeof i.rawInput=="object"&&(r+=256),typeof i.rawOutput=="string"?r+=i.rawOutput.length:i.rawOutput&&typeof i.rawOutput=="object"&&(r+=256),Array.isArray(i.content)))for(let a of i.content){if(!a||typeof a!="object")continue;let d=a;if(typeof d.text=="string"&&(r+=d.text.length),d.content&&typeof d.content=="object"){let c=d.content;typeof c.text=="string"&&(r+=c.text.length)}}return r}function Ce(s,e,t){let n=s.get(e);if(!n)throw O(x.SessionNotFound,t??`session ${e} not found`);return n}async function vt(s,e){let t=qt(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=Kc(32).toString("hex"),r=s.mcpTokenRegistry.reserve(n),o={name:"hydra-acp-recall",type:"http",url:`${s.getDaemonOrigin()}/mcp/hydra-acp-recall`,headers:[{name:"Authorization",value:`Bearer ${n}`}]});let a=[...t?.descriptors??[],...o!==void 0?[o]:[]],d=Eo({baselineMcpServers:void 0,stdinEnabled:!1,deps:s}),c;try{c=await s.manager.resurrect({...e,mcpServers:a,...d?{mintMcpServersForSwap:d}:{}})}catch(u){throw t!==void 0&&t.abandon(u instanceof Error?u:void 0),r!==void 0&&r.abandon(u instanceof Error?u:void 0),u}if(t!==void 0&&t.bindToSession(c),n!==void 0&&r!==void 0&&s.mcpTokenRegistry!==void 0){let u=n,l=s.mcpTokenRegistry;r.complete(c),c.onClose(()=>{l.unbind(u)})}return Dh(c,s),Zc(c.sessionId,s),c}function Xc(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=Hd({headers:n.headers,url:n.url});if(!r||!await e.validator.validate(r)){t.close(4401,"Unauthorized");return}let o=e.processRegistry?.resolve(r),i=`hydra_client_${Lo(12)}`,a=Ls(t),d={},c=e.foreignSessions?Bc(a,e.foreignSessions,d,i):a,u=new nt(c);d.connection=u;let l={clientId:i,processIdentity:o,attached:new Map};u.onClose(()=>{for(let h of l.attached.values())e.manager.get(h.sessionId)?.detach(h.clientId);l.attached.clear(),e.foreignSessions?.detachClient(i)});let p=(h,f)=>{if(l.attached.get(h)?.readonly)throw O(x.PermissionDenied,`${f} not permitted on a read-only attachment`)};if(u.onRequest("initialize",async h=>{let f=Ti.parse(h??{});f.clientInfo?.name&&(l.clientInfo={name:f.clientInfo.name,...f.clientInfo.version!==void 0?{version:f.clientInfo.version}:{}});let g=f.clientInfo?.version;return g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g)),Nh()}),o&&e.extensionCommands){let h=e.extensionCommands;u.onRequest("hydra-acp/commands/register",async f=>{let g=f??{},w=Array.isArray(g.commands)?g.commands.map(y=>{if(!y||typeof y!="object")return;let k=y;if(typeof k.verb!="string")return;let b={verb:k.verb};return typeof k.argsHint=="string"&&(b.argsHint=k.argsHint),typeof k.description=="string"&&(b.description=k.description),b}).filter(y=>y!==void 0):[];return h.register(o.name,u,w),{ok:!0,registered:w.length}}),u.onClose(()=>{h.clear(o.name)})}if(o&&e.extensionMcp){let h=e.extensionMcp;u.onRequest("hydra-acp/mcp_tools/register",async g=>{let w=g??{},y=typeof w.instructions=="string"?w.instructions:void 0,k=Array.isArray(w.tools)?w.tools.map(b=>{if(!b||typeof b!="object")return;let S=b;if(typeof S.name!="string"||S.name.length===0||typeof S.description!="string"||S.inputSchema===null||typeof S.inputSchema!="object")return;let v={name:S.name,description:S.description,inputSchema:S.inputSchema};return S.outputSchema!==null&&typeof S.outputSchema=="object"&&(v.outputSchema=S.outputSchema),v}).filter(b=>b!==void 0):[];if(k.length===0)throw new Error("register_mcp_tools requires at least one tool");return h.register(o.name,u,y,k),{ok:!0,registered:k.length}});let f=g=>{let w=g??{};if(typeof w.sessionId!="string"||w.sessionId.length===0)throw O(x.InvalidParams,"sessionId is required");return w.sessionId};if(u.onRequest("hydra-acp/session/extension_state/get",async g=>{let w=f(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw O(x.InvalidParams,"key is required");if(!e.manager)throw O(x.InternalError,"manager not wired");return{value:await e.manager.getExtensionStateKey(w,o.name,y.key)??null}}),u.onRequest("hydra-acp/session/extension_state/list",async g=>{let w=f(g);if(!e.manager)throw O(x.InternalError,"manager not wired");return{state:await e.manager.getExtensionState(w,o.name)}}),u.onRequest("hydra-acp/session/extension_state/set",async g=>{let w=f(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw O(x.InvalidParams,"key is required");if(y.value===void 0)throw O(x.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw O(x.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(w,o.name,y.key,y.value)}catch(k){throw O(x.InvalidParams,k.message)}return{ok:!0}}),u.onRequest("hydra-acp/session/extension_state/delete",async g=>{let w=f(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw O(x.InvalidParams,"key is required");if(!e.manager)throw O(x.InternalError,"manager not wired");return await e.manager.deleteExtensionStateKey(w,o.name,y.key),{ok:!0}}),e.extensionMcpControls){let g=e.extensionMcpControls;u.onRequest("hydra-acp/mcp_tools/refresh_session",async w=>{let y=w??{};if(typeof y.sessionId!="string"||y.sessionId.length===0)throw O(x.InvalidParams,"refresh_session requires sessionId");return await g.notifyToolListChanged(y.sessionId,o.name),{ok:!0}})}u.onClose(()=>{h.clear(o.name)})}if(o?.kind==="transformer"){u.onRequest("hydra-acp/transformer/initialize",async f=>{let g=f??{},w=Array.isArray(g.intercepts)?g.intercepts.filter(y=>typeof y=="string"):[];if(e.transformers&&(e.transformers.registerConnection(o.name,u,w),e.manager?.defaultTransformers.includes(o.name))){let y=e.transformers.resolveChain([o.name])[0];if(y)for(let k of e.manager.liveSessions())k.addTransformer(y)}return{ack:!0}}),u.onClose(()=>{e.transformers?.deregisterConnection(o.name)}),u.onRequest("hydra-acp/message/emit",async f=>{let g=f??{},w=typeof g.sessionId=="string"?g.sessionId:void 0,y=typeof g.method=="string"?g.method:void 0,k=g.envelope,b=g.route;if(!w)throw O(-32602,"emit_message requires sessionId");if(!y&&b!=="client_broadcast")throw O(-32602,"emit_message requires method");let S=Ce(e.manager,w),v=typeof g.respondsTo=="string"?g.respondsTo:void 0;if(v)return S.dischargeClaim(v,k),{ok:!0};if(b==="chain")return{ok:!0,response:await S.emitToChain(o.name,y,k)};if(b==="queue"){if(y!=="session/prompt")throw O(-32602,'route "queue" only supports method "session/prompt"');return{ok:!0,response:await S.emitToQueue(o.name,k)}}if(b==="daemon")return{ok:!0,response:await S.emitToChain(o.name,y,k)};if(b==="client_broadcast"){if(!k||typeof k!="object")throw O(-32602,"client_broadcast requires an envelope object");return S.broadcastClientUpdate(k),{ok:!0}}throw O(-32602,`unsupported route: ${JSON.stringify(b)}`)}),u.onRequest("hydra-acp/session/request_permission",async f=>{let g=f??{},w=typeof g.sessionId=="string"?g.sessionId:void 0;if(!w)throw O(-32602,"hydra-acp/session/request_permission requires sessionId");return Ce(e.manager,w).requestPermissionFromClients(g)}),u.onRequest("hydra-acp/transformer/attach",async f=>_h(f,o.name,e)),u.onRequest("hydra-acp/child_session/spawn",async f=>{let g=f??{},w=typeof g.agentId=="string"?g.agentId:void 0,y=typeof g.cwd=="string"?g.cwd:void 0,k=typeof g.parentSessionId=="string"?g.parentSessionId:void 0,b=g._meta&&typeof g._meta=="object"?g._meta:void 0,S=b&&b["hydra-acp"]&&typeof b["hydra-acp"]=="object"?b["hydra-acp"]:void 0,v=S&&typeof S.title=="string"?S.title:void 0,E=S&&typeof S.model=="string"?S.model:void 0;if(!y&&k){let W=e.manager.get(k);W&&(y=W.cwd)}if(!y)throw O(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let A=await Xt(y),C=w??A.agentId??e.defaultAgent,T=await e.registry?.getAgent(C),M=tn(A.configDefaults,T??{id:C})?.value,H=E??M?.model,J=typeof g.interactive=="boolean"?g.interactive:!1;return{childSessionId:(await e.manager.create({agentId:C,cwd:y,parentSessionId:k,interactive:J,transformChain:[],title:v,model:H,configDefaults:M})).sessionId}}),u.onRequest("hydra-acp/session/fork",async f=>{let g=f??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"fork_session requires sessionId");let w=typeof g.forkAt=="string"?g.forkAt:void 0,y=typeof g.cwd=="string"?g.cwd:void 0,k=typeof g.agentId=="string"?g.agentId:void 0,b=typeof g.mode=="string"&&(g.mode==="verbatim"||g.mode==="synthesis")?g.mode:void 0,S=typeof g.model=="string"&&g.model.length>0?g.model:void 0,v=await e.manager.forkSession(g.sessionId,{...w!==void 0?{forkAt:w}:{},...y!==void 0?{cwd:y}:{},...k!==void 0?{agentId:k}:{},...b!==void 0?{mode:b}:{},...S!==void 0?{model:S}:{}}),E=e.manager.get(v.sessionId);if(!E){let T=await e.manager.loadFromDisk(v.sessionId);if(!T)throw O(x.InternalError,`fork ${v.sessionId} vanished before it could be attached`);E=await vt(e,{...T,onInstallProgress:qs(u)})}Jt(l,E,E.sessionId);let A=dt(u,E,l),{entries:C}=await E.attach(A,"full");l.attached.set(E.sessionId,{sessionId:E.sessionId,clientId:A.clientId,readonly:!1});for(let T of C){if(u.isClosed())break;await u.notify(T.method,Le(He(T.params,T.recordedAt),T.seq)).catch(()=>{})}return{...v,sessionId:E.sessionId}}),u.onRequest("session/fork",async f=>{let g=f??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"session/fork requires sessionId");let w=typeof g.cwd=="string"?g.cwd:void 0,y=await e.manager.forkSession(g.sessionId,{...w!==void 0?{cwd:w}:{},mode:"verbatim"}),k=e.manager.get(y.sessionId);if(!k){let v=await e.manager.loadFromDisk(y.sessionId);if(!v)throw O(x.InternalError,`fork ${y.sessionId} vanished before it could be attached`);k=await vt(e,{...v,onInstallProgress:qs(u)})}Jt(l,k,k.sessionId);let b=dt(u,k,l),{entries:S}=await k.attach(b,"full");l.attached.set(k.sessionId,{sessionId:k.sessionId,clientId:b.clientId,readonly:!1});for(let v of S){if(u.isClosed())break;await u.notify(v.method,Le(He(v.params,v.recordedAt),v.seq)).catch(()=>{})}return{sessionId:k.sessionId}});let h=async(f,g)=>{let w=f??{};if(typeof w.sessionId!="string")throw O(x.InvalidParams,`${g} requires sessionId`);let y=await e.manager.resolveCanonicalId(w.sessionId)??w.sessionId,k=e.manager.get(y);if(k)return await k.close({deleteRecord:!0,by:`session/delete ${l.clientId}`}),await e.manager.waitForDeletion(y),await e.manager.hasRecord(y)&&await e.manager.deleteRecord(y),{id:y,existed:!0};let b=await e.manager.deleteRecord(y);return{id:y,existed:b}};u.onRequest("session/delete",async f=>(await h(f,"session/delete"),{})),u.onRequest("session/close",async f=>{let g=f??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"session/close requires sessionId");p(g.sessionId,"session/close");let w=await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId,y=e.manager.get(w);if(y)return await y.close({deleteRecord:!1,by:`session/close ${l.clientId}`+(l.processIdentity?` (${l.processIdentity.name})`:"")}),{};if(await e.manager.hasRecord(w))return{};throw O(x.SessionNotFound,`session ${w} not found`)}),u.onRequest("hydra-acp/session/delete",async f=>{let{id:g,existed:w}=await h(f,"hydra-acp/session/delete");if(!w)throw O(x.SessionNotFound,`session ${g} not found`);return{deleted:!0,sessionId:g}}),u.onRequest("hydra-acp/child_session/await",async f=>{let g=f??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0,y=g.until==="idle"?"idle":"turn_complete",k=typeof g.timeoutMs=="number"?Math.min(g.timeoutMs,18e5):3e5;if(!w)throw O(-32602,"await_child requires childSessionId");let b=Ce(e.manager,w,`child session ${w} not found`);return new Promise(S=>{let A=[],C=[],T=0,M=!1,H,J,$=!1,W=()=>{$||($=!0,clearTimeout(q),H?.(),J?.(),S(M?{entries:A,truncated:!0}:{entries:A}))};H=b.onBroadcast(te=>{let ie=xh(te);for(A.push(te),C.push(ie),T+=ie;A.length>0&&(A.length>1e3||T>1048576);)A.shift(),T-=C.shift()??0,M=!0;y==="turn_complete"&&te.params?.update?.sessionUpdate==="turn_complete"&&W()});let q=setTimeout(W,k);typeof q.unref=="function"&&q.unref(),J=b.onClose(()=>W())})}),u.onRequest("hydra-acp/child_session/close",async f=>{let g=f??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0;if(!w)throw O(-32602,"close_child_session requires childSessionId");let y=e.manager.get(w);return y&&await y.close({deleteRecord:!1,by:`child_session/close ${l.clientId}`}),{ok:!0}}),u.onRequest("hydra-acp/attention/set",async f=>$h(f,o.name,e)),u.onRequest("hydra-acp/attention/clear",async f=>Fh(f,o.name,e)),u.onRequest("hydra-acp/connection/keep_alive",async f=>{let g=f??{},w=typeof g.token=="string"?g.token:void 0,y=typeof g.sessionId=="string"?g.sessionId:void 0,k=typeof g.estimatedRemainingMs=="number"?g.estimatedRemainingMs:void 0;return w&&y&&e.manager.get(y)?.keepAliveClaim(w,k),{ok:!0}})}u.onRequest("hydra-acp/session/tool_content",async h=>{let f=h??{};if(typeof f.sessionId!="string"||typeof f.hash!="string")throw O(x.InvalidParams,"hydra-acp/session/tool_content requires sessionId and hash");let g=await e.manager.resolveCanonicalId(f.sessionId)??f.sessionId,w=await e.manager.loadToolBlob(g,f.hash);if(w===null)throw O(x.SessionNotFound,"tool content not found");return{content:w}}),u.onRequest("authenticate",async h=>Eh(h,e)),u.onRequest("logout",async h=>Th(h,e)),u.onRequest("session/new",async h=>{let f=Pi.parse(h),g=ut(h?._meta),w=Array.isArray(g.transformers)&&g.transformers.every(X=>typeof X=="string")?g.transformers:e.manager.defaultTransformers??[],y=e.transformers?.resolveChain(w)??[],k=await Xt(f.cwd),b=g.agentId??k.agentId??e.defaultAgent,S=await e.registry?.getAgent(b),v=tn(k.configDefaults,S??{id:b})?.value,E,A,C=f.mcpServers;if(g.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){E=Kc(32).toString("hex"),A=e.mcpTokenRegistry.reserve(E);let ke={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${E}`}]};C=[...f.mcpServers??[],ke]}let T,M,H=qt(e);H!==void 0&&(C=[...C??[],...H.descriptors]);let J=Eo({baselineMcpServers:f.mcpServers,stdinEnabled:g.mcpStdin===!0,deps:e}),$;try{$=await e.manager.create({cwd:f.cwd,agentId:b,mcpServers:C,title:g.title,agentArgs:g.agentArgs,model:g.model??v?.model,configDefaults:v,onInstallProgress:qs(u),transformChain:y,originatingClient:l.clientInfo,...g.interactive!==void 0?{interactive:g.interactive}:{},...g.env!==void 0?{forwardedEnv:g.env}:{},...g.workspace!==void 0?{workspace:g.workspace}:{},...J?{mintMcpServersForSwap:J}:{}})}catch(X){throw A!==void 0&&A.abandon(X instanceof Error?X:void 0),M!==void 0&&M.abandon(X instanceof Error?X:void 0),H!==void 0&&H.abandon(X instanceof Error?X:void 0),X}if(E!==void 0&&A!==void 0&&e.mcpTokenRegistry!==void 0){let X=E,ke=e.mcpTokenRegistry;A.complete($),$.onClose(()=>{ke.unbind(X)})}if(T!==void 0&&M!==void 0&&e.mcpTokenRegistry!==void 0){let X=T,ke=e.mcpTokenRegistry;M.complete($),$.onClose(()=>{ke.unbind(X)})}H!==void 0&&H.bindToSession($),Zc($.sessionId,e);let W,q;try{Jt(l,$,$.sessionId),W=dt(u,$,l),{entries:q}=await $.attach(W,"full")}catch(X){throw await $.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),X}l.attached.set($.sessionId,{sessionId:$.sessionId,clientId:W.clientId,readonly:!1}),setImmediate(()=>{(async()=>{for(let X of q){if(u.isClosed())break;await u.notify(X.method,Le(He(X.params,X.recordedAt),X.seq)).catch(()=>{})}})()});let te=zs($),ie=Js($);return{sessionId:$.sessionId,...te?{modes:te}:{},...ie?{models:ie}:{},configOptions:$.buildConfigOptions(),_meta:Vs(e.manager,$,{clientId:W.clientId})}}),u.onRequest("session/attach",async h=>{let f=_i.parse(h),g=f.clientInfo?.version;g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g));let w=ut(f._meta),y=w.resume,k=w.readonly===!0,b=w.env;s.log.info(`session/attach sessionId=${f.sessionId} hasResumeHints=${!!y} readonly=${k}`);let S=y?f.sessionId:await e.manager.resolveCanonicalId(f.sessionId)??f.sessionId,v=e.manager.get(S);if(!v&&k){let $=await e.manager.loadFromDisk(S);if(!$)throw O(x.SessionNotFound,`session ${f.sessionId} not found`);let W=await e.manager.loadHistory(S),q=f.clientId??`cli_${Lo(8)}`;l.attached.set($.hydraSessionId,{sessionId:$.hydraSessionId,clientId:q,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${$.hydraSessionId} clientId=${q} attachedCount=${l.attached.size} replayed=${W.length}`);for(let te of W)await u.notify(te.method,Le(He(te.params,te.recordedAt),te.seq)).catch(()=>{});return{sessionId:$.hydraSessionId,clientId:q,connectedClients:[q],historyPolicy:"full",replayed:W.length,_meta:Oh($)}}let E=!v;if(!v){let $=await e.manager.loadFromDisk(S),W=await Ph(S,y,$?.upstreamSessionId,e.manager);W.kind==="ignore"&&s.log.warn(W.logMessage);let q=$;if(y&&W.kind==="honor"&&(q={...$,hydraSessionId:f.sessionId,upstreamSessionId:y.upstreamSessionId,agentId:y.agentId,cwd:$?.workspace?.path??y.cwd,...y.title!==void 0?{title:y.title}:{},...y.agentArgs!==void 0?{agentArgs:y.agentArgs}:{}}),!q)throw O(x.SessionNotFound,`session ${f.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(q.agentId,q.upstreamSessionId))throw O(x.SessionNotFound,`session ${f.sessionId} was deleted`);let te=q.originatingClient?q:{...q,originatingClient:l.clientInfo},ie=b!==void 0?{...te,forwardedEnv:b}:te;v=await vt(e,{...ie,onInstallProgress:qs(u)})}Jt(l,v,v.sessionId);let A=dt(u,v,l,f.clientInfo,f.clientId),C=w.replayMode==="drip",{entries:T,appliedPolicy:M}=await v.attach(A,f.historyPolicy,{afterMessageId:f.afterMessageId,afterSeq:f.afterSeq,raw:C,...w.historyLimit!==void 0?{historyLimit:w.historyLimit}:{},...w.toolContent!==void 0?{toolContent:w.toolContent}:{}});if(l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:A.clientId,readonly:k}),b!==void 0&&await e.manager.setForwardedEnv(v.sessionId,b).catch(()=>{}),s.log.info(`session/attach OK sessionId=${v.sessionId} clientId=${A.clientId} attachedCount=${l.attached.size} requestedPolicy=${f.historyPolicy} appliedPolicy=${M} replayed=${T.length} readonly=${k}${C?" replayMode=drip":""}`),C){let $=w.dripSpeed&&w.dripSpeed>0?w.dripSpeed:1,W=750;(async()=>{let q=null;for(let te of T){let ie=typeof te.recordedAt=="number"?te.recordedAt:null;if(q!==null&&ie!==null){let X=Math.min(W,Math.max(0,(ie-q)/$));X>0&&await new Promise(ke=>setTimeout(ke,X))}ie!==null&&(q=ie);try{await u.notify(te.method,Le(He(te.params,ie??void 0),te.seq))}catch{return}}})()}else for(let $=0;$<T.length&&!u.isClosed();$++){let W=T[$],q=u.notify(W.method,Le(He(W.params,W.recordedAt),W.seq)).catch(()=>{});($+1)%200===0&&await q}v.replayPendingPermissions(A);let H=zs(v),J=Js(v);return{sessionId:v.sessionId,clientId:A.clientId,connectedClients:v.connectedClients(A.clientId),historyPolicy:M,replayed:T.length,...H?{modes:H}:{},...J?{models:J}:{},configOptions:v.buildConfigOptions(),_meta:Vs(e.manager,v,{resurrected:E})}}),u.onRequest("session/detach",async h=>{let f=$i.parse(h),g=l.attached.get(f.sessionId);if(!g)throw O(x.SessionNotFound,"client not attached to that session");let w=e.manager.get(f.sessionId);return w?.detach(g.clientId),l.attached.delete(f.sessionId),w&&e.manager.reapIfOrphanedNonInteractive(f.sessionId),{sessionId:f.sessionId,_meta:{[ae]:{detachStatus:"detached"}}}}),u.onRequest("session/list",async h=>{let f=Fi.parse(h??{});return{sessions:(await e.manager.list({cwd:f.cwd})).filter(k=>k.originatingClient?.name!==us).map(Oi)}}),u.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw O(x.InternalError,"agent registry unavailable");return Rt(e.registry)}),u.onRequest("hydra-acp/agents/auth_methods",async h=>{let f=h??{};if(typeof f.agentId!="string"||f.agentId.length===0)throw O(x.InvalidParams,"hydra-acp/agents/auth_methods requires a non-empty agentId string");return{authMethods:(await e.manager.bootstrapAgentForAuth(f.agentId)).authMethods??[]}}),u.onRequest("session/prompt",async h=>{let f=Ni.parse(h);p(f.sessionId,"session/prompt");let g=await zc(f,e.manager,b=>{s.log.warn(`session/prompt: dropping unknown sentBy.sessionId=${b} sessionId=${f.sessionId}`)});if(g?.fromSession!==void 0){if((g.depth??0)>3)throw s.log.warn(`session/prompt: refusing depth ${g.depth} chain from ${g.fromSession} to ${f.sessionId}`),O(x.InvalidRequest,`message chain too deep (${g.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(g.awaiting===!0&&Vc(g.fromSession,f.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${g.fromSession} -> ${f.sessionId}`),O(x.InvalidRequest,`would deadlock: ${f.sessionId} is already blocked waiting on ${g.fromSession}. Send with --no-wait, or let the other turn finish first.`)}let w=l.attached.get(f.sessionId);if(!w)throw s.log.warn(`session/prompt rejected: not attached sessionId=${f.sessionId} attachedKeys=[${[...l.attached.keys()].join(",")}]`),O(x.SessionNotFound,"not attached to session");let y=e.manager.get(f.sessionId);if(!y){let b=await e.manager.loadFromDisk(f.sessionId);if(!b)throw O(x.SessionNotFound,`session ${f.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${f.sessionId}`),y=await vt(e,b);let S=dt(u,y,l,void 0,w.clientId);await y.attach(S,"none")}let k=g?.awaiting===!0&&g.fromSession!==void 0?Jc(g.fromSession,f.sessionId):void 0;try{return await y.prompt(w.clientId,f,g)}finally{k?.()}});let m=h=>{let f;try{f=Wn.parse(h)}catch(y){s.log.warn(`session/cancel: invalid params: ${y.message}`);return}let g=l.attached.get(f.sessionId);if(!g)return;if(g.readonly){s.log.warn(`session/cancel dropped (readonly attachment) sessionId=${f.sessionId}`);return}let w=e.manager.get(f.sessionId);w&&w.cancel(g.clientId).catch(y=>{s.log.warn(`session/cancel for ${f.sessionId}: ${y.message}`)})};u.onNotification("session/cancel",m),u.onRequest("session/cancel",async h=>{let f=Wn.parse(h);return p(f.sessionId,"session/cancel"),m(h),null}),u.onRequest("hydra-acp/prompt/cancel",async h=>{let f=ji.parse(h);return p(f.sessionId,"hydra-acp/prompt/cancel"),Ce(e.manager,f.sessionId).cancelQueuedPrompt(f.messageId)}),u.onRequest("hydra-acp/session/force_cancel",async h=>{let f=Wn.parse(h);return p(f.sessionId,"hydra-acp/session/force_cancel"),Ce(e.manager,f.sessionId).forceCancel()}),u.onRequest("hydra-acp/prompt/update",async h=>{let f=Hi.parse(h);return p(f.sessionId,"hydra-acp/prompt/update"),Ce(e.manager,f.sessionId).updateQueuedPrompt(f.messageId,f.prompt)}),u.onRequest("hydra-acp/prompt/amend",async h=>{let f=Li.parse(h);p(f.sessionId,"hydra-acp/prompt/amend");let g=l.attached.get(f.sessionId);if(!g)throw O(x.SessionNotFound,"not attached to session");return Ce(e.manager,f.sessionId).amendPrompt(g.clientId,f)}),u.onRequest("_session/steering",async h=>{let f=Ui.parse(h);p(f.sessionId,"_session/steering");let g=l.attached.get(f.sessionId);if(!g)throw O(x.SessionNotFound,"not attached to session");let w=e.manager.get(f.sessionId);if(!w){let y=await e.manager.loadFromDisk(f.sessionId);if(!y)throw O(x.SessionNotFound,`session ${f.sessionId} not found`);w=await vt(e,y);let k=dt(u,w,l,void 0,g.clientId);await w.attach(k,"none")}return w.steer(g.clientId,f)}),u.onRequest("session/resume",async h=>{let f=h??{},g=typeof f.sessionId=="string"?f.sessionId:void 0;if(!g)throw O(x.InvalidParams,"session/resume requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let v=await e.manager.loadFromDisk(w);if(!v)throw O(x.SessionNotFound,`session ${g} not found in memory or on disk`);y=await vt(e,v)}Jt(l,y,y.sessionId);let k=dt(u,y,l);await y.attach(k,"pending_only"),l.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:k.clientId,readonly:!1}),y.replayPendingPermissions(k);let b=zs(y),S=Js(y);return{sessionId:y.sessionId,...b?{modes:b}:{},...S?{models:S}:{},configOptions:y.buildConfigOptions(),_meta:Vs(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/load",async h=>{let f=h??{},g=typeof f.sessionId=="string"?f.sessionId:void 0;if(!g)throw O(x.InvalidParams,"session/load requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let E=await e.manager.loadFromDisk(w);if(!E)throw O(x.SessionNotFound,`session ${g} not found in memory or on disk`);y=await vt(e,E)}Jt(l,y,y.sessionId);let k=dt(u,y,l),{entries:b}=await y.attach(k,"full");l.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:k.clientId,readonly:!1});for(let E of b){if(u.isClosed())break;await u.notify(E.method,Le(He(E.params,E.recordedAt),E.seq)).catch(()=>{})}y.replayPendingPermissions(k);let S=zs(y),v=Js(y);return{sessionId:y.sessionId,...S?{modes:S}:{},...v?{models:v}:{},configOptions:y.buildConfigOptions(),_meta:Vs(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/set_model",async h=>{let f=h?.sessionId;typeof f=="string"&&p(f,"session/set_model");let g=Mh(h,e.manager);if(g.kind==="error")throw s.log.warn(g.logMessage),O(g.code,g.message);if(g.kind==="no_op")return s.log.warn(g.logMessage),await u.notify("session/update",{sessionId:g.sessionId,update:{sessionUpdate:"_hydra_current_model_update",currentModel:g.currentModel}}).catch(()=>{}),null;s.log.info(g.logMessage);let{modelId:w}=g,y=await g.session.forwardModelChange(w,h);return g.session.applyAgentConfigOptionResponse(y,"model"),g.session.applyModelChange(w),y}),u.onRequest("session/set_mode",async h=>{let f=h,g=f?.sessionId;if(typeof g=="string"&&p(g,"session/set_mode"),!f||typeof f.sessionId!="string")throw O(x.InvalidParams,"session/set_mode requires string sessionId");if(typeof f.modeId!="string")throw O(x.InvalidParams,"session/set_mode requires string modeId");let w=Ce(e.manager,f.sessionId),y=await w.forwardRequest("session/set_mode",h);return w.applyModeChange(f.modeId),y}),u.onRequest("session/set_config_option",async h=>{let f=h,g=b=>O(x.InvalidParams,b),w=f?.sessionId;if(typeof w=="string"&&p(w,"session/set_config_option"),!f||typeof f.sessionId!="string")throw g("session/set_config_option requires string sessionId");if(typeof f.configId!="string")throw g("session/set_config_option requires string configId");if(typeof f.value!="string")throw g("session/set_config_option requires string value");let y=Ce(e.manager,f.sessionId),k=y.buildConfigOptions().find(b=>b.id===f.configId);if(!k)throw g(`unknown configId ${JSON.stringify(f.configId)} for this session`);if(!k.options.some(b=>b.value===f.value))throw g(`value ${JSON.stringify(f.value)} is not valid for configId ${JSON.stringify(f.configId)}`);switch(f.configId){case"model":{if(f.value!==y.currentModel){let b=await y.forwardModelChange(f.value);y.applyAgentConfigOptionResponse(b,"model")}y.applyModelChange(f.value);break}case"mode":{f.value!==y.currentMode&&await y.forwardRequest("session/set_mode",{sessionId:f.sessionId,modeId:f.value}),y.applyModeChange(f.value);break}case"agent":{f.value!==y.agentId&&await y.setAgent(f.value);break}default:{let b=await y.forwardRequest("session/set_config_option",{sessionId:f.sessionId,configId:f.configId,value:f.value});y.applyAgentConfigOptionResponse(b,f.configId)&&y.broadcastConfigOptions()}}return{configOptions:y.buildConfigOptions()}}),u.setDefaultHandler(async(h,f)=>{let g=new Set(["hydra-acp/attention/set","hydra-acp/attention/clear"]),w=f.startsWith("session/"),y=f.startsWith("hydra-acp/");if(!w&&!y||h===null||typeof h!="object"||g.has(f))throw O(x.MethodNotFound,`Method not found: ${f}`);let k=h.sessionId;if(typeof k!="string")throw O(x.MethodNotFound,`Method not found: ${f}`);return p(k,f),Ce(e.manager,k).forwardRequest(f,h)})})}async function Eh(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw O(x.InvalidParams,"authenticate requires a non-empty methodId string");let n=t.methodId,r=t._meta?.["hydra-acp"],o=typeof r?.sessionId=="string"?r.sessionId:void 0,i=typeof r?.agentId=="string"?r.agentId:void 0,a=o!==void 0?e.manager.getAgentForSession(o):void 0;if(!a||!a.isAlive()){let m=i??e.defaultAgent;a=await e.manager.bootstrapAgentForAuth(m)}let d=a.authMethods??[],c=d.find(m=>m.id===n);if(!c){let m=d.map(h=>h.id);throw O(x.InvalidParams,`authenticate: methodId ${JSON.stringify(n)} is not advertised by agent ${a.agentId}; valid: [${m.map(h=>JSON.stringify(h)).join(", ")}]`)}let u=c._meta?.type,l=(()=>{let m=c._meta?.["terminal-auth"];if(m&&typeof m=="object"&&!Array.isArray(m))return m})();if((c.type??(u==="agent"||u==="terminal"?u:l!==void 0?"terminal":"agent"))==="terminal"){let m=(k,b)=>{if(!Array.isArray(k))throw O(x.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be a string[]; got ${k===null?"null":typeof k}`);for(let S of k)if(typeof S!="string")throw O(x.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be string[]; got non-string entry ${JSON.stringify(S)}`);return k},h=await e.manager.planSpawnForAgent(a.agentId),f,g;if(l?.args!==void 0){let k=typeof l.command=="string"?l.command:void 0;f=k!==void 0&&Yc.isAbsolute(k)?k:h.command,g=m(l.args,'_meta["terminal-auth"].args')}else{let k=c.args!==void 0?{raw:c.args,label:"args"}:c._meta?.args!==void 0?{raw:c._meta.args,label:"_meta.args"}:void 0,b=k!==void 0?m(k.raw,k.label):[];f=h.command,g=[...h.args,...b]}let w={};for(let[k,b]of Object.entries(process.env))typeof b=="string"&&(w[k]=b);Object.assign(w,h.env);let y=Qc.homedir();return console.error(`[authenticate] terminal-auth requested agentId=${a.agentId} methodId=${n}`),{kind:"terminal",command:f,args:g,env:w,cwd:y}}try{return await a.connection.request("authenticate",{methodId:n})}catch(m){throw ot(m,a)}}async function Th(s,e){let n=(s??{})._meta?.["hydra-acp"],r=typeof n?.sessionId=="string"?n.sessionId:void 0,o=typeof n?.agentId=="string"?n.agentId:void 0,i=r!==void 0?e.manager.getAgentForSession(r):void 0;if(!i||!i.isAlive()){let a=o??e.defaultAgent;i=await e.manager.bootstrapAgentForAuth(a)}return await i.connection.request("logout",{})}function qs(s){return e=>{let t={agentId:e.agentId,version:e.version,source:e.source,phase:e.phase};"receivedBytes"in e&&(t.receivedBytes=e.receivedBytes),"totalBytes"in e&&(t.totalBytes=e.totalBytes),"packageSpec"in e&&(t.packageSpec=e.packageSpec),s.notify(Bi,t).catch(()=>{})}}function zs(s){let e=s.availableModes();if(e.length===0)return;let t=e.map(r=>{let o={id:r.id,name:r.name??r.id};return r.description!==void 0&&(o.description=r.description),o});return{currentModeId:s.currentMode??e[0].id,availableModes:t}}function Js(s){let e=s.availableModels();if(e.length===0)return;let t=e.map(r=>{let o={modelId:r.modelId};return r.name!==void 0&&(o.name=r.name),r.description!==void 0&&(o.description=r.description),o});return{currentModelId:s.currentModel??e[0].modelId,availableModels:t}}async function Ph(s,e,t,n){return e?await n.isRetiredGeneration(s,e.upstreamSessionId)?{kind:"ignore",logMessage:`session/attach ignoring stale resume hint sessionId=${s} hintUpstream=${e.upstreamSessionId} recordUpstream=${t} (retired generation)`}:{kind:"honor"}:{kind:"none"}}function Mh(s,e){if(!s||typeof s!="object")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires params",logMessage:"session/set_model rejected: params not an object"};let t=s;if(typeof t.sessionId!="string")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires string sessionId",logMessage:"session/set_model rejected: missing/non-string sessionId"};if(typeof t.modelId!="string")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires string modelId",logMessage:`session/set_model rejected: missing/non-string modelId sessionId=${t.sessionId}`};let n=e.get(t.sessionId);if(!n)return{kind:"error",code:x.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=_t(t.modelId,r);if(o.kind==="none")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model passthrough (no availableModels) sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="exact")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model accepted sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="resolved")return{kind:"ok",session:n,modelId:o.modelId,logMessage:`session/set_model resolved sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} \u2192 ${JSON.stringify(o.modelId)}`};let i=r.map(d=>d.modelId).join(", "),a=o.kind==="ambiguous"?`ambiguous (trailing-segment matches [${o.candidates.join(", ")}])`:"not in availableModels";return n.currentModel!==void 0&&n.currentModel.length>0?{kind:"no_op",session:n,sessionId:t.sessionId,currentModel:n.currentModel,logMessage:`session/set_model no_op (resyncing client) sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} ${a} actual=${JSON.stringify(n.currentModel)} agentId=${n.agentId} known=[${i}]`}:{kind:"error",code:x.InvalidParams,message:`model "${t.modelId}" is ${a==="not in availableModels"?"not in this session's availableModels":a} (agent ${n.agentId}); known models: ${i}`,logMessage:`session/set_model rejected sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)} ${a} agentId=${n.agentId} known=[${i}] (no current model to fall back to)`}}async function _h(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw O(x.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw O(x.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw O(x.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return Ce(t.manager,r).addTransformer(o),{ok:!0}}async function $h(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(x.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw O(x.InvalidParams,"hydra-acp/attention/set requires string reason");return Ce(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function Fh(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(x.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw O(x.InvalidParams,"hydra-acp/attention/clear requires string reason");return Ce(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function Oh(s){let e={sessionId:s.hydraSessionId,upstreamSessionId:s.upstreamSessionId,cwd:s.cwd,workspace:s.workspace,title:s.title,agentId:s.agentId,currentModel:s.currentModel,currentUsage:wn(s.currentUsage),forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:s.interactive,updatedAt:s.createdAt??new Date().toISOString(),attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1},t={currentMode:s.currentMode,agentArgs:s.agentArgs,availableCommands:s.agentCommands,availableModes:s.agentModes,availableModels:s.agentModels,armedTaskList:[]};return{[ae]:Bn(e,t)}}function Vs(s,e,t={}){let n=s.liveListEntry(e),r={clientId:t.clientId,currentMode:e.currentMode,agentArgs:e.agentArgs,availableCommands:e.mergedAvailableCommands(),availableModes:e.availableModes(),availableModels:e.availableModels(),turnStartedAt:e.turnStartedAt,agentCapabilities:e.agentCapabilities,queue:e.queueSnapshot(),armedTaskList:e.armedBackgroundTasks,...t.resurrected===!0?{resurrected:!0}:{}};return nn(e.agentMeta,Bn(n,r))}function Nh(){return{protocolVersion:1,agentInfo:{name:"hydra",version:me},agentCapabilities:{promptCapabilities:{image:!0,audio:!0,embeddedContext:!0},mcpCapabilities:{http:!0,sse:!0},loadSession:!0,auth:{logout:{}},sessionCapabilities:{attach:{},list:{},resume:{},delete:{},close:{},fork:{}}},authMethods:[{id:"proxy",name:"Hydra proxy",type:"agent",description:"Hydra proxies authentication to the downstream agent selected per session"}],_meta:{...nn(void 0,{prompt:{queueing:!0,cancelling:!0,updating:!0,amending:!0,pipelining:!1},agents:{list:!0,installProgress:!0},session:{fork:{forkAt:!0,agentSwap:!0,synthesis:!0,model:!0}}}),steering:{supported:!0}}}}function Dh(s,e){if(!(!e.transformers||!e.manager))for(let t of e.manager.defaultTransformers){let n=e.transformers.resolveChain([t])[0];n&&s.addTransformer(n)}}function Zc(s,e){if(!e.transformers)return;let t=e.transformers.interestedIn("lifecycle:session.starting");for(let n of t)n.connection.notify("hydra-acp/transformer/session_event",{event:"session.starting",sessionId:s}).catch(()=>{})}function dt(s,e,t,n,r){return{clientId:r??`cli_${Lo(8)}`,connection:s,clientInfo:n}}function Jt(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var Gs=class{byToken=new Map;reserve(e){if(this.byToken.has(e))throw new Error("mcp token already bound");let t,n,r=new Promise((i,a)=>{t=i,n=a});r.catch(()=>{});let o={session:void 0,sessionReady:r,disposers:[]};return this.byToken.set(e,o),{complete:i=>{o.session=i,t(i)},abandon:i=>{this.byToken.delete(e),n(i??new Error("mcp token reservation abandoned"))}}}bind(e,t){let{complete:n}=this.reserve(e);n(t)}lookup(e){return this.byToken.get(e)}addDisposer(e,t){let n=this.byToken.get(e);n!==void 0&&n.disposers.push(t)}async unbind(e){let t=this.byToken.get(e);if(t!==void 0){this.byToken.delete(e);for(let n of t.disposers)try{await n()}catch{}}}size(){return this.byToken.size}};import{randomUUID as jh}from"crypto";import{McpServer as Hh}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Lh}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as he}from"zod";function Uo(s){if(s.method!=="session/update")return null;let t=s.params?.update;return!t||typeof t.sessionUpdate!="string"?null:{kind:t.sessionUpdate,update:t}}function Se(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var eu="Bearer ";function Vt(s){let e=s.headers.authorization;if(typeof e!="string"||!e.startsWith(eu))return;let t=e.slice(eu.length).trim();return t.length>0?t:void 0}function Uh(s){let e=new Hh({name:"hydra-acp-stdin",version:"1.0.0"},{instructions:"Piped input from `hydra cat --stream` is exposed here as a byte stream. Use `tail` for the latest N bytes (good for finding the end of a log), `head` for the first N bytes (good for headers/preamble), `read` for windowed reads against an absolute byte cursor, `wait_for_more` to block until new bytes arrive past a cursor, and `info` for the current cursors/capacity/closed status. Byte payloads come back base64-encoded."});return e.registerTool("tail",{description:"Return the most recent `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means older bytes existed but have been evicted from the ring.",inputSchema:{bytes:he.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return Se(n)}),e.registerTool("head",{description:"Return the first `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means the head has already been evicted from the ring and the returned bytes start at the oldest still-resident cursor.",inputSchema:{bytes:he.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return Se(n)}),e.registerTool("read",{description:"Read up to `max_bytes` bytes starting at absolute byte `cursor`. Returns `{bytes, nextCursor, gap?, eof?}` \u2014 `gap` is the number of bytes silently skipped because the ring had evicted them; `eof:true` means the producer closed and there is nothing left to read.",inputSchema:{cursor:he.number().int().min(0).describe("Absolute byte offset to start reading from. Use 0 to read from the very beginning (may produce a gap if old bytes have been evicted)."),max_bytes:he.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:he.number().int().min(0).optional().describe("If no bytes are available, block up to this many ms for more (capped server-side at 60_000).")}},async({cursor:t,max_bytes:n,wait_ms:r})=>{let o=await s.streamRead(t,n,r);return Se(o)}),e.registerTool("wait_for_more",{description:"Block until bytes are available past `cursor`, the stream closes, or `timeout_ms` elapses. Returns one of {data, eof, timeout} plus the current `writeCursor`. Use this when you've consumed everything up to a cursor and want to wait for more without busy-polling.",inputSchema:{cursor:he.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:he.number().int().min(0).describe("Maximum ms to block (server caps at 60_000).")}},async({cursor:t,timeout_ms:n})=>{let r=await s.streamWaitFor(t,n),o=s.streamInfo();return Se({outcome:r,writeCursor:o.writeCursor,closed:o.closed})}),e.registerTool("grep",{description:"Scan piped stdin line-by-line and return lines matching `pattern`. Prefer this over `read` when the question is 'find lines that mention X' \u2014 it filters server-side so you don't pull and decode 64 KiB base64 windows. Returns `{matches: [{cursor, line, before?, after?}], truncated, nextCursor, gap?, scannedBytes, eof?}`. Lines come back as decoded UTF-8 strings (not base64). When `truncated:true`, re-call with `cursor: nextCursor` to resume.",inputSchema:{pattern:he.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:he.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:he.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:he.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:he.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:he.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:he.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:he.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:he.number().int().min(0).optional().describe("Optional absolute byte offset to start scanning from. Omit to scan from the oldest still-resident byte. Pass the `nextCursor` from a previous truncated call to resume.")}},async t=>{let n={pattern:t.pattern};t.regex!==void 0&&(n.regex=t.regex),t.case_insensitive!==void 0&&(n.caseInsensitive=t.case_insensitive),t.invert!==void 0&&(n.invert=t.invert),t.max_matches!==void 0&&(n.maxMatches=t.max_matches),t.max_bytes!==void 0&&(n.maxBytes=t.max_bytes),t.context_before!==void 0&&(n.contextBefore=t.context_before),t.context_after!==void 0&&(n.contextAfter=t.context_after),t.cursor!==void 0&&(n.cursor=t.cursor);let r=s.streamGrep(n);return Se(r)}),e.registerTool("info",{description:"Report cursor / capacity / closed state of the stdin ring. Cheap; safe to call repeatedly.",inputSchema:{}},async()=>{let t=s.streamInfo();return Se(t)}),e}var Bh=1e4;function tu(s,e){let t=new Map;async function n(i,a){let d=t.get(i);if(d!==void 0)return d.transport;let c=Uh(a),u=new Lh({sessionIdGenerator:()=>jh()});await c.connect(u);let l={server:c,transport:u};return t.set(i,l),e.addDisposer(i,async()=>{t.delete(i);try{await u.close()}catch{}try{await c.close()}catch{}}),u}async function r(i,a){let d=Vt(i);if(d===void 0){a.code(401).send({error:"missing bearer token"});return}let c=e.lookup(d);if(c===void 0){a.code(404).send({error:"unknown stdin token"});return}let u;if(c.session!==void 0)u=c.session;else{let p,m=new Promise(f=>{p=setTimeout(()=>f(void 0),Bh)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(p!==void 0&&clearTimeout(p),h===void 0){a.code(503).send({error:"session not ready"});return}u=h}let l=await n(d,u);a.hijack(),await l.handleRequest(i.raw,a.raw,i.body)}let o={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.get("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.delete("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)})}import{randomUUID as Wh}from"crypto";import{McpServer as qh}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as zh}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as Ve}from"zod";function Jh(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var nu=2e3,su=2e4;function Vh(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return $t([s]);let n=[],r=on(t);r!==void 0?n.push(`Tool: ${r}`):typeof t.title=="string"&&t.title.length>0&&n.push(`Tool: ${t.title}`);let o=t.rawInput;if(o&&typeof o=="object"&&!Array.isArray(o))for(let[a,d]of Object.entries(o))typeof d=="string"&&d.length>0&&n.push(`${a}=${d}`);if(Array.isArray(t.locations))for(let a of t.locations)typeof a?.path=="string"&&a.path.length>0&&n.push(a.path);let i=Vn(t);return i!==void 0&&n.push(i),n.join(`
|
|
194
|
-
`)}function Gh(s,e){if(s.length<=148)return s;let r=Math.floor(148/2),o=e-r;o<0&&(o=0);let i=o+148;i>s.length&&(o=s.length-148,o<0&&(o=0));let a=s.slice(o,i);return o>0&&(a="\u2026"+a),i<s.length&&(a=a+"\u2026"),a}function Kh(s){let e=new qh({name:"hydra-acp-recall",version:"1.0.0"},{instructions:"Search and retrieve detail from this session's pre-compaction history. After a compaction summary replaces earlier conversation in working memory, these tools let you page back specifics on demand. Use `search` to find entries by keyword, `range` to pull a contiguous slice verbatim, and `tool_calls` to enumerate prior tool invocations. These tools only return results once the session has been compacted at least once."});return e.registerTool("search",{description:"Search this session's prior conversation history (the part that was compacted out of your working memory) by keyword. Covers assistant and user messages, the arguments of every tool call including full shell commands, and what those calls printed. Returns matching entry ids with short snippets so you can decide which to pull in full via `range`. Use this when the compaction summary mentions something but you need the verbatim detail.",inputSchema:{query:Ve.string().min(1).describe("Case-insensitive substring to search for."),limit:Ve.number().int().min(1).max(50).optional().describe("Maximum number of matches to return (default 10, max 50)."),include_tool_calls:Ve.boolean().optional().describe("Whether to include tool_call entries in the search (default true).")}},async({query:t,limit:n=10,include_tool_calls:r=!0})=>{let o=await s();if(!o.summarizedThroughEntry||o.summarizedThroughEntry===0)return Se({matches:[],total_matched:0,truncated:!1,note:"This session has no compacted history. `search` retrieves detail from entries that were summarized out of the working conversation; nothing has been summarized yet."});let i=[],a=t.toLowerCase();for await(let{entryId:c,entry:u}of o.iterRecallNewestFirst()){let l=Uo(u);if(!l)continue;let{kind:p,update:m}=l;if((p==="tool_call"||p==="tool_call_update")&&!r)continue;let h=Vh(u,p,m),f=h.toLowerCase().indexOf(a);if(f<0)continue;let g=Jh(p),w=Gh(h,f),y=typeof u.recordedAt=="number"?String(u.recordedAt):void 0;if(i.push({entryId:c,speaker:g,snippet:w,timestamp:y}),i.length>=n)break}i.sort((c,u)=>c.entryId-u.entryId);let d=i.length>=n;return Se({matches:i,total_matched:i.length,truncated:d})}),e.registerTool("range",{description:"Pull a contiguous range of prior conversation entries verbatim from this session's pre-compaction history, including each tool call's arguments and what it printed. Use after `search` narrows in on what you need. Capped at 50 entries per call.",inputSchema:{from_entry:Ve.number().int().min(0).describe("Zero-based index of the first entry to include (inclusive)."),to_entry:Ve.number().int().min(0).describe("Zero-based index of the last entry to include (inclusive).")}},async({from_entry:t,to_entry:n})=>{let r=await s();if(!r.summarizedThroughEntry||r.summarizedThroughEntry===0)return Se({text:"",entry_count:0,truncated:!1,note:"This session has no compacted history. `range` retrieves verbatim entries from the pre-compaction transcript; nothing has been compacted yet."});if(n<t)throw new Error(`range: to_entry (${n}) must be >= from_entry (${t})`);let o=n-t+1;if(o>50)throw new Error(`range: range size (${o}) exceeds maximum of 50 entries`);let i=await r.getRecallTotalCount();if(i===0)return Se({text:"",entry_count:0,truncated:!1});let a=Math.min(t,i-1),d=Math.min(n,i-1),c=a>t||d<n;if(a>d)return{content:[{type:"text",text:""}],structuredContent:{text:"",entry_count:0,truncated:c}};let u=await r.sliceRecallHistory(a,d),l=$t(u,{toolOutput:{maxPerCall:nu,maxTotal:su}});return{content:[{type:"text",text:l}],structuredContent:{text:l,entry_count:u.length,truncated:c}}}),e.registerTool("tool_calls",{description:"Search this session's prior tool invocations by tool name, ACP kind, and/or file path. Returns when each tool was called, its arguments (including the full shell command), the result status, and what the call printed. Use this to recall which files were read/edited, what shell commands ran, and what they output.",inputSchema:{tool_name:Ve.string().optional().describe("Case-insensitive substring of the tool name. Names vary by agent for the same tool (Bash, Terminal, bash), so prefer `kind` when you want every shell invocation."),kind:Ve.string().optional().describe("ACP tool kind: execute (shell), read, edit, think, other. Agent-independent, unlike tool_name."),file_path:Ve.string().optional(),limit:Ve.number().int().min(1).max(100).optional(),include_output:Ve.boolean().optional().describe("Include what each call printed (default true). Set false when you only need the commands and not their results.")}},async({tool_name:t,kind:n,file_path:r,limit:o=20,include_output:i=!0})=>{let a=await s();if(!a.summarizedThroughEntry||a.summarizedThroughEntry===0)return Se({calls:[],truncated:!1,note:"This session has no compacted history. `tool_calls` retrieves tool invocations from the pre-compaction transcript; nothing has been compacted yet."});let d=typeof t=="string"&&t.length>0,c=typeof n=="string"&&n.length>0,u=typeof r=="string"&&r.length>0;if(!d&&!c&&!u)throw new Error("tool_calls: at least one of tool_name, kind, or file_path must be provided");let l=new Map,p=Math.max(o*4,200);for await(let{entryId:y,entry:k}of a.iterRecallNewestFirst()){let b=Uo(k);if(!b)continue;let{kind:S,update:v}=b;if(S!=="tool_call"&&S!=="tool_call_update")continue;let E=typeof v.toolCallId=="string"&&v.toolCallId.length>0?v.toolCallId:`__noid_${y}`,A=l.get(E);if(A||(A={entryId:y,toolName:"(unnamed)",nameAuthoritative:!1,rawInput:{},locations:[],status:"in_progress"},l.set(E,A)),y<A.entryId&&(A.entryId=y),!A.nameAuthoritative){let T=on(v);T!==void 0?(A.toolName=T,A.nameAuthoritative=!0):typeof v.name=="string"&&v.name.length>0?(A.toolName=v.name,A.nameAuthoritative=!0):S==="tool_call"&&typeof v.title=="string"&&v.title.length>0&&(A.toolName=v.title,A.nameAuthoritative=!0)}if(A.kind===void 0&&typeof v.kind=="string"&&v.kind.length>0&&(A.kind=v.kind),A.output===void 0){let T=Vn(v);T!==void 0&&(A.output=T)}let C=v.rawInput;if(C&&typeof C=="object"&&!Array.isArray(C)&&Object.keys(C).length>0)for(let[T,M]of Object.entries(C))A.rawInput[T]===void 0&&(A.rawInput[T]=M);if(Array.isArray(v.locations))for(let T of v.locations){let M=T?.path;typeof M=="string"&&M.length>0&&!A.locations.includes(M)&&A.locations.push(M)}if(typeof v.status=="string"&&A.status==="in_progress"&&(A.status=v.status),k.recordedAt!==void 0&&A.timestamp===void 0&&(A.timestamp=String(k.recordedAt)),l.size>=p)break}let m=[...l.keys()].sort((y,k)=>l.get(y).entryId-l.get(k).entryId),h=[],f=su,g=!1;for(let y of m){let k=l.get(y);if(k.toolName=Tr({name:k.toolName,rawInput:k.rawInput,...k.kind!==void 0?{kind:k.kind}:{}}),d&&!k.toolName.toLowerCase().includes(t.toLowerCase())||c&&(k.kind??"").toLowerCase()!==n.toLowerCase())continue;if(u){let v=r.toLowerCase(),E=["file_path","filePath","path"],A=!1;for(let C of E){let T=k.rawInput[C];if(typeof T=="string"&&T.toLowerCase().includes(v)){A=!0;break}}if(!A){for(let C of k.locations)if(C.toLowerCase().includes(v)){A=!0;break}}if(!A)continue}let b={};for(let[v,E]of Object.entries(k.rawInput))typeof E=="string"?b[v]=E.length>500?E.slice(0,497)+"\u2026":E:(typeof E=="number"||typeof E=="boolean")&&(b[v]=E);k.locations.length>0&&b.locations===void 0&&(b.locations=k.locations);let S={entryId:k.entryId,tool:k.toolName,args:b,status:k.status,timestamp:k.timestamp};if(k.kind!==void 0&&(S.kind=k.kind),i&&k.output!==void 0){let v=k.output,E=Math.min(nu,f);if(E<=0)g=!0;else{let A=v.length<=E?v:v.slice(0,E-1)+"\u2026";S.output=A,S.outputBytes=v.length,S.outputTruncated=A.length<v.length,f-=A.length}}if(h.push(S),h.length>=o)break}let w=h.length>=o;return Se({calls:h,truncated:w,...g?{outputBudgetExhausted:g}:{}})}),e}var Qh=1e4;function ru(s,e){let t=new Map;async function n(i,a){let d=t.get(i);if(d!==void 0)return d.transport;let c=Kh(a),u=new zh({sessionIdGenerator:()=>Wh()});await c.connect(u);let l={server:c,transport:u};return t.set(i,l),e.addDisposer(i,async()=>{t.delete(i);try{await u.close()}catch{}try{await c.close()}catch{}}),u}async function r(i,a){let d=Vt(i);if(d===void 0){a.code(401).send({error:"missing bearer token"});return}let c=e.lookup(d);if(c===void 0){a.code(404).send({error:"unknown recall token"});return}let l=await n(d,async()=>{if(c.session!==void 0)return c.session;let p,m=new Promise(f=>{p=setTimeout(()=>f(void 0),Qh)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(p!==void 0&&clearTimeout(p),h===void 0)throw new Error("recall: session not ready");return h});a.hijack(),await l.handleRequest(i.raw,a.raw,i.body)}let o={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)}),s.get("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)}),s.delete("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)})}var Ks=class{byName=new Map;changeHandlers=[];register(e,t,n,r){this.byName.set(e,{connection:t,instructions:n,tools:[...r]}),this.fireChanged(e,"register")}clear(e){this.byName.delete(e)&&this.fireChanged(e,"clear")}lookup(e){return this.byName.get(e)}list(){return Array.from(this.byName.keys())}onChange(e){return this.changeHandlers.push(e),()=>{let t=this.changeHandlers.indexOf(e);t>=0&&this.changeHandlers.splice(t,1)}}fireChanged(e,t){for(let n of this.changeHandlers)try{n(e,t)}catch{}}};import{StreamableHTTPServerTransport as ry}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{randomUUID as oy}from"crypto";import{Server as Yh}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Xh,ListToolsRequestSchema as Zh}from"@modelcontextprotocol/sdk/types.js";function ou(s,e,t,n){let r=typeof t=="function"?async()=>t():async()=>t,o=new Yh({name:s,version:"1.0.0"},{capabilities:{tools:{listChanged:!0}},...e.instructions!==void 0?{instructions:e.instructions}:{}}),i=a=>({name:a.name,description:a.description,inputSchema:a.inputSchema,...a.outputSchema!==void 0?{outputSchema:a.outputSchema}:{}});return o.setRequestHandler(Zh,async()=>{let a=n?.peekSessionId?.();if(a!==void 0&&n?.fetchSessionTools!==void 0)try{let d=await n.fetchSessionTools(a);if(d!==void 0)return{tools:d.map(i)}}catch{}return{tools:e.tools.map(i)}}),o.setRequestHandler(Xh,async(a,d)=>{let c=a.params.name,u=d._meta?.progressToken??d.requestId,l=ty(u,d.sendNotification);try{let p=await r(),m=await ny(e.connection,s,c,a.params.arguments??{},p);return sy(m,c)}catch(p){return Bo(p instanceof Error?p.message:String(p))}finally{l()}}),o}var ey=15e3;function ty(s,e,t=ey){if(s===void 0)return()=>{};let n=0,r=setInterval(()=>{n+=1,e({method:"notifications/progress",params:{progressToken:s,progress:n}}).catch(()=>{})},t);return r.unref?.(),()=>clearInterval(r)}async function ny(s,e,t,n,r){return await s.request("hydra-acp/mcp_tools/invoke",{server:e,tool:t,args:n,sessionId:r})}function sy(s,e){if(s===null||typeof s!="object")return Bo(`extension ${e} returned non-object`);let t=s;return Array.isArray(t.content)?t:Bo(`extension ${e} omitted content array`)}function Bo(s){return{content:[{type:"text",text:s}],isError:!0}}var iy=1e4;function iu(s,e,t){let n=new Map;async function r(u){try{await u.transport.close()}catch{}try{await u.server.close()}catch{}}function o(u){for(let l of n.values()){let p=l.get(u);p!==void 0&&(l.delete(u),r(p))}}async function i(u,l){for(let[p,m]of n){if(e.lookup(p)?.session?.sessionId!==u)continue;let f=m.get(l);if(f!==void 0)try{await f.server.sendToolListChanged()}catch{}}}t.onChange(u=>{o(u)});async function a(u,l){let p=n.get(u);p===void 0&&(p=new Map,n.set(u,p),e.addDisposer(u,async()=>{let b=n.get(u);if(b!==void 0){n.delete(u);for(let S of b.values())await r(S)}}));let m=p.get(l);if(m!==void 0)return m.transport;let h=t.lookup(l);if(h===void 0)return;let y=ou(l,h,async()=>{let b=e.lookup(u);if(b===void 0)throw new Error("mcp token no longer bound");if(b.session!==void 0)return b.session.sessionId;let S,v=new Promise(A=>{S=setTimeout(()=>A(void 0),iy)}),E=await Promise.race([b.sessionReady.catch(()=>{}),v]);if(S!==void 0&&clearTimeout(S),E===void 0)throw new Error("session not ready");return E.sessionId},{peekSessionId:()=>e.lookup(u)?.session?.sessionId,fetchSessionTools:async b=>{let S=await h.connection.request("hydra-acp/mcp_tools/list_tools",{sessionId:b});if(!S||typeof S!="object")return;let v=S.tools;if(!Array.isArray(v))return;let E=[];for(let A of v){if(!A||typeof A!="object")continue;let C=A;if(typeof C.name!="string"||C.name.length===0||typeof C.description!="string"||C.inputSchema===null||typeof C.inputSchema!="object")continue;let T={name:C.name,description:C.description,inputSchema:C.inputSchema};C.outputSchema!==null&&typeof C.outputSchema=="object"&&(T.outputSchema=C.outputSchema),E.push(T)}return E}}),k=new ry({sessionIdGenerator:()=>oy()});return await y.connect(k),p.set(l,{server:y,transport:k}),k}async function d(u,l){let p=Vt(u);if(p===void 0){l.code(401).send({error:"missing bearer token"});return}if(e.lookup(p)===void 0){l.code(404).send({error:"unknown mcp token"});return}let h=u.params.name,f=await a(p,h);if(f===void 0){l.code(404).send({error:`unknown mcp server: ${h}`});return}l.hijack(),await f.handleRequest(u.raw,l.raw,u.body)}let c={config:{skipAuth:!0}};return s.post("/mcp/:name",c,async(u,l)=>{await d(u,l)}),s.get("/mcp/:name",c,async(u,l)=>{await d(u,l)}),s.delete("/mcp/:name",c,async(u,l)=>{await d(u,l)}),{notifyToolListChanged:i}}async function fu(s,e){py(s),dr(s.daemon.scrubEnv);let t=s,n=s.daemon.tls?await Ge.readFile(le(s.daemon.tls.key)):void 0,r=s.daemon.tls?await Ge.readFile(le(s.daemon.tls.cert)):void 0;await Ge.mkdir(R.home(),{recursive:!0});let{stream:o,fileStream:i}=await ly(s.daemon.logLevel),a=ay({logger:{level:s.daemon.logLevel,stream:o},bodyLimit:256*1024*1024});await a.register(dy,{options:{handleProtocols:oi}}),gr(N=>{a.log.info(N)}),yr(N=>{a.log.info(N)});let d=await As.load(),c=await js.load();No(),Fo(c);let u=new Bs(c),l=new Ws(c);l.start();let p=new Fs(c);p.start();let m=new Ts,h=new Es,f=new Cs(e),g=new xs([f,new Rs(d),h]),w=jd({validator:g});a.addHook("onRequest",async(N,ve)=>{N.routeOptions.config?.skipAuth||N.url==="/acp"||N.url?.startsWith("/acp?")||(await w(N,ve),!ve.sent&&N.authIdentity?.startsWith("script:")&&!Ld(N.method,N.routeOptions.url)&&ve.code(403).send({error:"script tokens may only access read-only session data"}))});let y=setInterval(()=>{d.sweepExpired()},300*1e3);y.unref();let k=setInterval(()=>{m.sweepExpired()},300*1e3);k.unref();let b=new Ln(s,{onFetched:()=>{Ad(b,A)},onStaleFallback:(N,ve)=>{let Kt=Math.round(ve/36e5),Qt=Kt>=48?`${Math.round(Kt/24)}d`:`${Kt}h`;a.log.warn(`registry fetch failed (${N.message}); serving stale cache last synced ${Qt} ago; agent versions may be outdated ('hydra registry refresh' to retry)`)}});bo(N=>a.log.info(N));let S={info:N=>a.log.info(N),warn:N=>a.log.warn(N)},v=N=>st.spawn({...N,stderrTailBytes:s.daemon.agentStderrTailBytes,logger:S});li(s.compressToolContent);let E=new Ss,A=new ms(b,v,void 0,{idleTimeoutMs:s.daemon.sessionIdleTimeoutSeconds*1e3,orphanTimeoutMs:s.daemon.nonInteractiveOrphanTimeoutSeconds*1e3,sessionDefaults:s.sessionDefaults,synopsisAgent:s.synopsisAgent,synopsisModel:s.synopsisModel,compactionAgent:s.compaction?.agent,compactionModel:s.compaction?.model,defaultTransformers:s.defaultTransformers,sessionHistoryMaxEntries:s.daemon.sessionHistoryMaxEntries,sessionHistoryArchiveMaxBytes:s.daemon.sessionHistoryArchiveMaxBytes,sessionHistoryArchiveTiers:s.daemon.sessionHistoryArchiveTiers,logger:S,npmRegistry:s.npmRegistry,extensionCommands:E,defaultCwd:s.defaultCwd,disableWorkspaceSnapshots:s.disableWorkspaceSnapshots}),C=new vs(ni(s),void 0,{tokenRegistry:h}),T=new bs(si(s),void 0,{tokenRegistry:h}),M=[];wc(a,me,xd(s),()=>M);let H=new Gs,J=new Ks,$,W=()=>{if($!==void 0)return $;let N=a.server.address();return $=`http://127.0.0.1:${N&&typeof N=="object"?N.port:s.daemon.port}`,$},q={agentId:s.defaultAgent,cwd:s.defaultCwd,publicHost:s.daemon.publicHost,host:s.daemon.host,port:s.daemon.port,compaction:s.compaction};hc(a,A,q,{extensionMcp:J,mcpTokenRegistry:H,getDaemonOrigin:W},c,p),fc(a,{store:c}),yc(a,b,A,{npmRegistry:s.npmRegistry}),kc(a,C),vc(a,T),bc(a,()=>({defaultAgent:t.defaultAgent,defaultCwd:t.defaultCwd,sessionDefaults:{...t.sessionDefaults},...t.synopsisAgent!==void 0?{synopsisAgent:t.synopsisAgent}:{},...t.synopsisModel!==void 0?{synopsisModel:t.synopsisModel}:{},defaultTransformers:[...t.defaultTransformers]})),Rc(a,{store:d,rateLimiter:m,staticTokenValidator:f}),Hc(a,{store:c,health:l}),qc(a,{processRegistry:h}),tu(a,H),ru(a,H);let te=iu(a,H,J);Xc(a,{validator:g,manager:A,defaultAgent:s.defaultAgent,processRegistry:h,onExtensionVersion:(N,ve)=>C.reportVersion(N,ve),onTransformerVersion:(N,ve)=>T.reportVersion(N,ve),transformers:T,extensionCommands:E,mcpTokenRegistry:H,extensionMcp:J,extensionMcpControls:te,getDaemonOrigin:W,registry:b,foreignSessions:u});let ie=!!s.daemon.tls;await a.listen({host:ie?"127.0.0.1":s.daemon.host,port:ie?0:s.daemon.port});let X=a.server.address(),ke=X&&typeof X=="object"?X.port:s.daemon.port,Fn,pu=s.daemon.host,Wo=ke;if(ie&&n&&r){Fn=fy({listenHost:s.daemon.host,listenPort:s.daemon.port,upstreamHost:"127.0.0.1",upstreamPort:ke,tlsOptions:{key:n,cert:r},logger:a.log});let N=Fn.address();N&&typeof N=="object"&&(Wo=N.port)}await Ge.mkdir(R.home(),{recursive:!0}),await Id({pid:process.pid,host:pu,port:Wo,loopbackPort:ke,startedAt:new Date().toISOString()});let qo={daemonUrl:`http://127.0.0.1:${ke}`,daemonHost:"127.0.0.1",daemonPort:ke,serviceToken:e,daemonWsUrl:`ws://127.0.0.1:${ke}/acp`,hydraHome:R.home()};C.setContext(qo),T.setContext(qo),await C.start(),await T.start();try{await A.reconcilePermissionFlags()}catch(N){a.log.warn(`permission flag reconcile failed: ${N.message}`)}try{await A.seedSessionIndex()}catch(N){a.log.warn(`session index seed failed: ${N.message}`)}A.resurrectPendingQueues().catch(N=>{a.log.warn(`queue replay scan failed: ${N.message}`)}),A.resumePendingCompactions().catch(N=>{a.log.warn(`compaction resume scan failed: ${N.message}`)}),A.resumePendingAgentSwaps().catch(N=>{a.log.warn(`agent-swap resume scan failed: ${N.message}`)});let zo=s.daemon.agentSyncIntervalMinutes*60*1e3,Jo=zo>0?Cd({registry:b,manager:A,intervalMs:zo,logger:S}):void 0,Vo=s.daemon.sessionGcIntervalMinutes*60*1e3,gu=s.daemon.sessionGcMaxAgeDays*24*60*60*1e3,Go=Vo>0?Rd({manager:A,intervalMs:Vo,maxAgeMs:gu,logger:S}):void 0,mu=Md({bootConfig:s,apply:N=>{t=N,b.setConfig(N),A.setLiveConfig({sessionDefaults:N.sessionDefaults}),q.agentId=N.defaultAgent,q.cwd=N.defaultCwd,dr(N.daemon.scrubEnv)},onDrift:N=>{M=N},logger:S});return{app:a,manager:A,registry:b,extensions:C,transformers:T,mcpTokenRegistry:H,extensionMcp:J,processRegistry:h,shutdown:async()=>{l.stop(),p.stop(),mu(),Go&&Go(),Jo&&Jo(),clearInterval(y),clearInterval(k);let N=async(ve,Kt)=>{try{await Kt()}catch(Qt){a.log.warn(`shutdown step ${ve} failed: ${Qt instanceof Error?Qt.message:String(Qt)}`)}};await N("sessionTokenStore.flush",()=>d.flush()),await N("extensions.stop",()=>C.stop()),await N("transformers.stop",()=>T.stop()),await N("manager.closeAll",()=>A.closeAll()),await N("manager.flushSynopsis",()=>A.flushSynopsis(3e4)),await N("manager.shutdownSynopsis",()=>A.shutdownSynopsis()),await N("manager.flushMetaWrites",()=>A.flushMetaWrites()),await N("manager.flushHistoryWrites",()=>A.flushHistoryWrites()),gr(null),yr(null),bo(null),Fn&&await N("tlsTerminator.close",()=>new Promise(ve=>Fn.close(()=>ve()))),await N("app.close",()=>a.close());try{cu.unlinkSync(R.pidFile())}catch{}await N("fileStream.flushSync",()=>i.flushSync())}}}var du=20;async function uy(s,e){let t=Gt.dirname(s),n=Gt.basename(s,".log"),r=new RegExp(`^${n}\\.(\\d+)\\.log$`),o;try{o=await Ge.readdir(t)}catch{return}let i=[];for(let d of o){let c=d.match(r);c&&i.push({name:d,n:Number(c[1])})}if(i.length<=e)return;i.sort((d,c)=>d.n-c.n);let a=i.slice(0,i.length-e);await Promise.allSettled(a.map(d=>Ge.unlink(Gt.join(t,d.name))))}async function ly(s){await uy(R.logFile(),du);let e=await cy({file:R.logFile(),size:"10m",mkdir:!0,symlink:!0,limit:{count:du,removeOtherLogFiles:!0}}),t=au.destination(2);return{stream:au.multistream([{stream:e,level:s},{stream:t,level:s}]),fileStream:e}}function fy(s){let e=lu.createServer(s.tlsOptions,t=>{let n=uu.connect({host:s.upstreamHost,port:s.upstreamPort}),r=!1,o=i=>{if(!r){r=!0,i&&s.logger.warn(`tls terminator forwarder error: ${i.message??String(i)}`);try{t.destroy()}catch{}try{n.destroy()}catch{}}};t.on("error",o),n.on("error",o),t.on("close",()=>o()),n.on("close",()=>o()),t.pipe(n),n.pipe(t)});return e.on("tlsClientError",t=>{s.logger.warn(`tls handshake error: ${t.message}`)}),e.listen({host:s.listenHost,port:s.listenPort}),e}function py(s){let e=s.daemon.host;if(!(e==="127.0.0.1"||e==="::1"||e==="localhost"||e==="[::1]")&&!s.daemon.tls)throw new Error(`Refusing to bind to non-loopback host ${e} without TLS configured.`)}async function gy(){process.title="hydra-acp-daemon";let{installGlobalTlsTrust:s}=await Promise.resolve().then(()=>(_n(),jc));s();let e=await Zt(),t=await Ko(),n=await fu(e,t);process.stdout.write(`hydra-acp daemon listening on ${e.daemon.host}:${e.daemon.port}
|
|
193
|
+
`)}}catch(A){if(A.code==="ENOENT")return p.raw.end(),p;throw A}return p.raw.end(),p}),s.post("/v1/sessions/:id/prompt/:messageId/notify",async(l,p)=>{let m=l.params,h=m.id,f=await e.resolveCanonicalId(h)??h,g=m.messageId,w=l.body,y=typeof w?.callbackUrl=="string"?w.callbackUrl:"",k=typeof w?.secret=="string"?w.secret:"";if(!g||!y||!k){p.code(400).send({error:"messageId, callbackUrl, and secret are all required"});return}let b;try{b=new URL(y)}catch{p.code(400).send({error:"callbackUrl must be a valid absolute URL"});return}if(b.protocol!=="https:"&&b.protocol!=="http:"){p.code(400).send({error:"callbackUrl must be http or https"});return}let S=e.get(f);if(!S){p.code(404).send({error:"session not found or not warm"});return}let v=S.registerTurnNotify(g,y,k);if(v.alreadyTerminal){p.code(200).send({status:"already_terminal",stopReason:v.stopReason});return}p.code(202).send({status:"registered"})}),s.get("/v1/sessions/:id/attention",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,f=e.get(h);return!f&&!await e.hasRecord(h)?(p.code(404).send({error:"session not found"}),p):f?{flags:f.listAttentionFlags()}:{flags:(await e.store.read(h))?.attentionFlags??[]}}),s.get("/v1/sessions/attention",async(l,p)=>{let m=l.query;if(!m.source||m.source.trim().length===0)return p.code(400).send({error:"source query parameter is required"}),p;let h=await e.list({includeNonInteractive:!0}),f=[];for(let g of h){let w=e.get(g.sessionId),y;w?y=w.listAttentionFlags():y=(await e.store.read(g.sessionId))?.attentionFlags??[];for(let k of y)k.source===m.source&&f.push({...k,sessionId:g.sessionId})}return{flags:f}}),s.post("/v1/sessions/:id/attention/clear",async(l,p)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,g=l.body??{},w=typeof g.source=="string"?g.source:"",y=typeof g.reason=="string"?g.reason:"";if((w.length>0||y.length>0)&&!(w.length>0&&y.length>0)){p.code(400).send({error:"both source and reason are required to clear a specific flag, or omit both to clear all"});return}w.length===0&&y.length;let k=e.get(h);if(k){if(w.length>0&&y.length>0)k.clearAttentionFlag(w,y);else{let A=Array.from(k.listAttentionFlags()).map(C=>`${C.source}::${C.reason}`);for(let C of A)k.clearAttentionFlag(C.split("::")[0],C.split("::").slice(1).join("::"))}p.code(204).send();return}if(!await e.hasRecord(h)){p.code(404).send({error:"session not found"});return}let b=e.store,S=await b.read(h);if(!S){p.code(404).send({error:"session not found"});return}let v=S.attentionFlags??[],E;if(w.length>0&&y.length>0){let A=`${w}::${y}`;E=v.filter(C=>`${C.source}::${C.reason}`!==A)}else E=[];if(E.length===v.length&&E.every((A,C)=>A.source===v[C].source&&A.reason===v[C].reason)){p.code(204).send();return}await b.write({...S,attentionFlags:E}),p.code(204).send()})}function yc(s,e,t,n={}){s.get("/v1/agents",async()=>Rt(e)),s.get("/v1/registry",async()=>e.load()),s.post("/v1/registry/refresh",async()=>{let r=await e.refresh();return{version:r.version,agentCount:r.agents.length}}),s.post("/v1/agents/:id/install",async(r,o)=>{let i=r.params.id,a=await e.getAgent(i);if(!a){o.code(404).send({error:`agent ${i} not found in registry`});return}if(a.distribution.uvx&&!a.distribution.npx&&!a.distribution.binary){o.send({agentId:a.id,version:a.version??"current",distribution:"uvx",installed:!1,message:"uvx agents resolve on first run; nothing to pre-install."});return}try{let d=await Re(a,[],{npmRegistry:n.npmRegistry}),c=a.distribution.npx?"npx":a.distribution.binary?"binary":"unknown";o.send({agentId:a.id,version:d.version,distribution:c,installed:!0,command:d.command})}catch(d){o.code(500).send({error:d.message})}}),s.post("/v1/agents/:id/sync",async(r,o)=>{let i=r.params.id;try{let{synced:a,skipped:d}=await t.syncFromAgent(i);return{synced:a.map(c=>({sessionId:c.sessionId,upstreamSessionId:c.upstreamSessionId,agentId:c.agentId,cwd:c.cwd,title:c.title,updatedAt:c.updatedAt})),skipped:d}}catch(a){let d=a;if(d.code===x.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}Y();function wc(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:R.home(),driftedKeys:n()}))}var Bm=/^[A-Za-z0-9._-]+$/;function Ds(s,e,t){let n=e==="extension"?"extensions":"transformers",r=`/v1/${n}`;s.get(r,async()=>({[n]:t.list()})),s.get(`${r}/:name`,async(o,i)=>{let a=o.params.name,d=t.get(a);if(!d){i.code(404).send({error:`unknown ${e}: ${a}`});return}return d}),s.post(r,async(o,i)=>{let a=o.body??{},d=Wm(a);if("error"in d){i.code(400).send({error:d.error});return}try{let c=t.register(d.config);i.code(201).send(c)}catch(c){Pn(i,c)}}),s.delete(`${r}/:name`,async(o,i)=>{let a=o.params.name;try{await t.unregister(a),i.code(204).send()}catch(d){Pn(i,d)}}),s.post(`${r}/:name/start`,async(o,i)=>{let a=o.params.name;try{let d=await t.startByName(a);i.code(200).send(d)}catch(d){Pn(i,d)}}),s.post(`${r}/:name/stop`,async(o,i)=>{let a=o.params.name;try{let d=await t.stopByName(a);i.code(200).send(d)}catch(d){Pn(i,d)}}),s.post(`${r}/:name/restart`,async(o,i)=>{let a=o.params.name;try{let d=await t.restartByName(a);i.code(200).send(d)}catch(d){Pn(i,d)}})}function Pn(s,e){let t=e.code,n=e.message??"unknown error";if(t==="NOT_FOUND"){s.code(404).send({error:n});return}if(t==="CONFLICT"){s.code(409).send({error:n});return}s.code(500).send({error:n})}function Wm(s){let e=s.name;if(typeof e!="string"||!Bm.test(e))return{error:"name must match [A-Za-z0-9._-]+"};let t=s.command;if(t!==void 0&&(!Array.isArray(t)||t.some(i=>typeof i!="string")))return{error:"command must be string[]"};let n=s.args;if(n!==void 0&&(!Array.isArray(n)||n.some(i=>typeof i!="string")))return{error:"args must be string[]"};let r=s.env;if(r!==void 0&&(typeof r!="object"||r===null||Array.isArray(r)))return{error:"env must be an object of string\u2192string"};if(r&&Object.values(r).some(i=>typeof i!="string"))return{error:"env values must be strings"};let o=s.enabled;return o!==void 0&&typeof o!="boolean"?{error:"enabled must be a boolean"}:{config:{name:e,command:t??[],args:n??[],env:r??{},enabled:o===void 0?!0:o}}}function kc(s,e){Ds(s,"extension",e)}function vc(s,e){Ds(s,"transformer",e)}function bc(s,e){s.get("/v1/config",async()=>e())}import{z as it}from"zod";Y();import*as zt from"fs/promises";import*as Sc from"path";import{randomBytes as aI,scrypt as qm,timingSafeEqual as zm}from"crypto";import{promisify as Jm}from"util";var Vm=Jm(qm);function Ic(){return Sc.join(R.home(),"password-hash")}var Gm=128*1024*1024;async function Ac(){try{return(await zt.readFile(Ic(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function Cc(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await zt.readFile(Ic(),"utf8")).trim()}catch(c){if(c.code==="ENOENT")return!1;throw c}let t=e.split("$");if(t.length!==6||t[0]!=="scrypt")return!1;let n=parseInt(t[1],10),r=parseInt(t[2],10),o=parseInt(t[3],10);if(!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(o))return!1;let i=Buffer.from(t[4],"hex"),a=Buffer.from(t[5],"hex");if(i.length===0||a.length===0)return!1;let d=await Vm(s,i,a.length,{N:n,r,p:o,maxmem:Gm});return d.length!==a.length?!1:zm(d,a)}var Km=it.object({password:it.string().min(1),label:it.string().min(1).max(256).optional(),ttlSec:it.number().int().positive().optional()}),Qm=it.object({id:it.string().optional()}).optional(),Ym=it.object({token:it.string().min(32)});function Rc(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=Xm(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=Km.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await Ac())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await Cc(o.password))return e.rateLimiter.recordFailure(r),n.code(401).send({error:"Invalid password"});e.rateLimiter.recordSuccess(r);let a=await e.store.issue({label:o.label,ttlSec:o.ttlSec});return n.code(200).send({session_token:a.token,id:a.id,expires_at:a.expiresAt})}),s.post("/v1/auth/logout",async(t,n)=>{let r;try{r=Qm.parse(t.body??void 0)}catch{return n.code(400).send({error:"Invalid request body"})}let o=r?.id??t.authIdentity;if(!o||o==="service")return n.code(200).send({revoked:!1});let i=await e.store.revoke(o);return n.code(200).send({revoked:i})}),s.get("/v1/auth/verify",async(t,n)=>n.code(200).send({ok:!0})),s.get("/v1/auth/sessions",async(t,n)=>n.code(200).send({sessions:e.store.list()})),s.delete("/v1/auth/sessions",async(t,n)=>{let r=await e.store.revokeAll();return n.code(200).send({revoked:r})}),s.delete("/v1/auth/sessions/:id",async(t,n)=>{let r=t.params.id;return await e.store.revoke(r)?n.code(204).send():n.code(404).send({error:"Not found"})}),s.post("/v1/auth/rotate-token",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=Ym.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}return e.staticTokenValidator.rotate(r.token),n.code(200).send({rotated:!0})})}function Xm(s){return s.ip||"unknown"}import{z as at}from"zod";Y();Oe();var Mo=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,js=class s{data;constructor(e){this.data=e}static async load(){let e=await oe(R.peers());return new s(Zm(e))}get(e){return this.data.entries[e]}async set(e){this.data.entries[e.name]=e,await xc(this.data)}async delete(e){return e in this.data.entries?(delete this.data.entries[e],await xc(this.data),!0):!1}list(){return Object.values(this.data.entries).map(({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})=>({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})).sort((e,t)=>e.addedAt.localeCompare(t.addedAt))}};function Zm(s){if(!s||typeof s!="object")return{version:1,entries:{}};let e=s,t=e.entries&&typeof e.entries=="object"?e.entries:{},n={};for(let[r,o]of Object.entries(t)){if(!o||typeof o!="object")continue;let i=o;if(typeof i.name!="string"||typeof i.host!="string"||typeof i.port!="number"||typeof i.token!="string"||typeof i.expiresAt!="string"||typeof i.addedAt!="string")continue;let a={name:i.name,host:i.host,port:i.port,token:i.token,expiresAt:i.expiresAt,addedAt:i.addedAt};typeof i.label=="string"&&(a.label=i.label),typeof i.pinnedFingerprint=="string"&&(a.pinnedFingerprint=i.pinnedFingerprint),typeof i.pinnedAt=="string"&&(a.pinnedAt=i.pinnedAt),n[r]=a}return{version:1,entries:n}}async function xc(s){await ue(R.peers(),s,{mode:384})}var eh=3600*24*365,Je=class extends Error{status;constructor(e,t){super(e),this.name="PeerLoginError",this.status=t}};function Ec(s,e){return`${Te(s)?"http":"https"}://${s}:${e}`}async function Tc(s){let e=s.fetchImpl??fetch,t=`${s.host}:${s.port}`,n=Ec(s.host,s.port),r;try{r=await e(`${n}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:s.password,label:s.label,ttlSec:s.ttlSec??eh})})}catch(i){throw new Je(`Could not reach ${t}: ${i.message}`,502)}if(r.status===401)throw new Je(`Wrong password for ${t}.`,401);if(r.status===403)throw new Je(`No password is configured on ${t}. Run \`hydra-acp auth password\` on that daemon first.`,502);if(r.status===429)throw new Je(`Too many failed login attempts on ${t}; try again later.`,429);if(!r.ok)throw new Je(`Login to ${t} failed: HTTP ${r.status}`,502);let o=await r.json();if(!o.session_token||!o.expires_at)throw new Je(`Login to ${t} returned a malformed response.`,502);return{token:o.session_token,expiresAt:o.expires_at}}async function Pc(s){let e=s.fetchImpl??fetch,t=Ec(s.host,s.port);try{await e(`${t}/v1/auth/logout`,{method:"POST",headers:{Authorization:`Bearer ${s.token}`,"Content-Type":"application/json"},body:JSON.stringify({})})}catch{}}_n();var fh=at.object({name:at.string().min(1).max(64).regex(Mo),host:at.string().min(1),port:at.number().int().positive().optional(),password:at.string().min(1),label:at.string().min(1).max(256).optional(),ttlSec:at.number().int().positive().optional(),pinnedFingerprint:at.string().min(1).optional()});function Hc(s,e){s.post("/v1/remotes",async(t,n)=>{let r;try{r=fh.parse(t.body)}catch{return n.code(400).send({error:`Invalid request body (name must match ${Mo} and the rest is a normal login request)`})}let o=r.port??St;r.pinnedFingerprint&&Mn(r.host,o,r.pinnedFingerprint);let i;try{i=await Tc({host:r.host,port:o,password:r.password,label:r.label,ttlSec:r.ttlSec})}catch(c){if(c instanceof Je)return n.code(c.status).send({error:c.message});throw c}let a=new Date().toISOString(),d={name:r.name,host:r.host,port:o,token:i.token,expiresAt:i.expiresAt,addedAt:a,...r.label!==void 0?{label:r.label}:{},...r.pinnedFingerprint!==void 0?{pinnedFingerprint:r.pinnedFingerprint,pinnedAt:a}:{}};return await e.store.set(d),e.health?.markOk(d.name),n.code(201).send({name:d.name,host:d.host,port:d.port,expiresAt:d.expiresAt,label:d.label,addedAt:d.addedAt,pinnedFingerprint:d.pinnedFingerprint,status:e.health?.get(d.name)?.status??"unknown"})}),s.get("/v1/remotes",async(t,n)=>{let r=e.store.list().map(o=>{let i=e.health?.get(o.name);return{...o,status:i?.status??"unknown",...i?.checkedAt?{lastCheckedAt:i.checkedAt}:{}}});return n.code(200).send({remotes:r})}),s.delete("/v1/remotes/:name",async(t,n)=>{let r=t.params.name,o=e.store.get(r);return o?(await Pc({host:o.host,port:o.port,token:o.token}),await e.store.delete(r),e.health?.forget(r),e.store.list().some(a=>a.host===o.host&&a.port===o.port)||$o(o.host,o.port),n.code(204).send()):n.code(404).send({error:"Not found"})})}function Ls(s){let e=[],t=[],n=!1,r=o=>{if(!n){n=!0;for(let i of t)i(o)}};return s.on("message",(o,i)=>{if(i)return;let a=o.toString("utf8");try{let d=JSON.parse(a);for(let c of e)c(d)}catch(d){for(let c of e)c({jsonrpc:"2.0",id:null,error:{code:x.ParseError,message:`Failed to parse WS frame: ${d.message}`}})}}),s.on("close",()=>r()),s.on("error",o=>r(o)),{async send(o){if(n)throw new Error("ws is closed");let i=JSON.stringify(o);await new Promise((a,d)=>{s.send(i,c=>{if(c){d(c);return}a()})})},onMessage(o){e.push(o)},onClose(o){t.push(o)},async close(){n||(await new Promise(o=>{let i=!1,a=()=>{i||(i=!0,clearTimeout(d),o())},d=setTimeout(a,5e3);s.once("close",a);try{s.close()}catch{a()}}),r())}}}_n();import{WebSocket as ph}from"ws";var gh=1e4,jo=class extends Error{url;elapsedMs;constructor(e,t){super(`hydra-acp: websocket connect to ${e} timed out after ${t}ms`),this.name="WsConnectTimeoutError",this.url=e,this.elapsedMs=t}};async function Lc(s,e,t=gh){let n={};try{let r=new URL(s);if(r.protocol==="wss:"){let o=Do(r.hostname);o.rejectUnauthorized!==void 0&&(n.rejectUnauthorized=o.rejectUnauthorized),o.autoSelectFamily!==void 0&&(n.autoSelectFamily=o.autoSelectFamily),o.checkServerIdentity!==void 0&&(n.checkServerIdentity=o.checkServerIdentity)}}catch{}return new Promise((r,o)=>{let i=new ph(s,e,n),a=Date.now(),d=setTimeout(()=>{i.off("open",c),i.off("error",u),i.on("error",()=>{});try{i.terminate()}catch{}o(new jo(s,Date.now()-a))},t),c=()=>{clearTimeout(d),i.off("error",u),r(i)},u=l=>{clearTimeout(d),i.off("open",c),o(l)};i.once("open",c),i.once("error",u)})}var mh=new Set(["session/attach","session/detach","session/prompt","session/cancel"]);function hh(s){return mh.has(s)}function Bc(s,e,t,n){let r=[];return s.onMessage(o=>{if("method"in o&&hh(o.method)){let i=o.params,a=typeof i?.sessionId=="string"?i.sessionId:void 0;if(a&&pt(a)){e.handleLocalMessage(o,a,{connection:t.connection,clientId:n}).then(d=>d?s.send(d):void 0).catch(()=>{});return}}for(let i of r)i(o)}),{send:o=>s.send(o),onMessage:o=>r.push(o),onClose:o=>s.onClose(o),close:()=>s.close()}}var Bs=class{constructor(e,t=wh){this.store=e;this.dial=t}store;dial;attachments=new Map;async handleLocalMessage(e,t,n){let r="id"in e,o=r?e.id:void 0,i=pt(t);if(!i)return r?Us(o,x.SessionNotFound,`not a federated session id: ${t}`):void 0;let a=Uc(n.clientId,t),d={...e.params,sessionId:i.localId};if(e.method==="session/attach"){let u=this.store.get(i.name);if(!u)return r?Us(o,x.SessionNotFound,`No remote named "${i.name}". Run \`hydra remote add\` first.`):void 0;let l=this.attachments.get(a);l&&(this.attachments.delete(a),l.peerConnection.close().catch(()=>{}));let p;try{p=await this.dial(u)}catch(g){return r?Us(o,x.InternalError,`Could not reach remote "${i.name}": ${g.message}`):void 0}let m;try{m=await p.request("session/attach",d)}catch(g){return p.close().catch(()=>{}),r?Ho(o,g):void 0}let h={peerConnection:p,localId:i.localId,target:n};this.wireAttachment(i.name,h),this.attachments.set(a,h);let f=m&&typeof m.sessionId=="string"?{...m,sessionId:t}:m;return r?{jsonrpc:"2.0",id:o,result:f}:void 0}let c=this.attachments.get(a);if(!c)return r?Us(o,x.SessionNotFound,`"${t}" is not attached through this daemon.`):void 0;if(e.method==="session/detach"){let u,l;try{u=await c.peerConnection.request("session/detach",d)}catch(p){l=p}return this.attachments.delete(a),c.peerConnection.close().catch(()=>{}),l?r?Ho(o,l):void 0:r?{jsonrpc:"2.0",id:o,result:u??{}}:void 0}if(r)try{let u=await c.peerConnection.request(e.method,d);return{jsonrpc:"2.0",id:o,result:u}}catch(u){return Ho(o,u)}await c.peerConnection.notify(e.method,d).catch(()=>{})}detachClient(e){for(let[t,n]of[...this.attachments.entries()])n.target.clientId===e&&(this.attachments.delete(t),n.peerConnection.request("session/detach",{sessionId:n.localId}).catch(()=>{}),n.peerConnection.close().catch(()=>{}))}wireAttachment(e,t){let{peerConnection:n,localId:r,target:o}=t,i=Tt({name:e,localId:r}),a=()=>{this.attachments.delete(Uc(o.clientId,i))};n.onNotification("session/update",d=>{let c=d;!c||c.sessionId!==r||o.connection.notify("session/update",{...c,sessionId:i}).catch(()=>{})}),n.onNotification("hydra-acp/session/closed",d=>{let c=d;!c||c.sessionId!==r||(a(),o.connection.notify("hydra-acp/session/closed",{sessionId:i}).catch(()=>{}))}),n.onRequest("hydra-acp/session/request_permission",async d=>{let c=d;if(!c||c.sessionId!==r)throw{code:x.MethodNotFound,message:"unexpected sessionId"};return o.connection.request("hydra-acp/session/request_permission",{...c,sessionId:i})}),n.onClose(()=>{a(),o.connection.notify("hydra-acp/session/closed",{sessionId:i}).catch(()=>{})})}};function Uc(s,e){return`${s} ${e}`}function Us(s,e,t){return{jsonrpc:"2.0",id:s,error:{code:e,message:t}}}function Ho(s,e){let t=e,n=typeof t?.code=="number"?t.code:x.InternalError,r=typeof t?.message=="string"?t.message:String(e??"forward failed");return{jsonrpc:"2.0",id:s,error:{code:n,message:r,...t?.data!==void 0?{data:t.data}:{}}}}var yh=1e4;async function wh(s){let t=`${Te(s.host)?"ws":"wss"}://${s.host}:${s.port}/acp`,n=await Lc(t,["acp.v1",`hydra-acp-token.${s.token}`],yh);return new nt(Ls(n))}var kh=3e4,vh=5e3,Ws=class{constructor(e,t={}){this.store=e;this.opts=t}store;opts;snapshots=new Map;timer;start(){this.timer||(this.checkAll(),this.timer=setInterval(()=>{this.checkAll()},this.opts.intervalMs??kh),this.timer.unref?.())}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}get(e){return this.snapshots.get(e)}markOk(e){this.snapshots.set(e,{status:"ok",checkedAt:new Date().toISOString()})}forget(e){this.snapshots.delete(e)}async checkAll(){let e=this.opts.fetchImpl??fetch;await Promise.allSettled(this.store.list().map(async t=>{let n=this.store.get(t.name);if(!n)return;let o=`${Te(n.host)?"http":"https"}://${n.host}:${n.port}/v1/auth/verify`,i=new AbortController,a=setTimeout(()=>i.abort(),vh);try{let d=await e(o,{headers:{Authorization:`Bearer ${n.token}`},signal:i.signal});this.snapshots.set(t.name,{status:d.ok?"ok":"unauthorized",checkedAt:new Date().toISOString()})}catch(d){this.snapshots.set(t.name,{status:"unreachable",checkedAt:new Date().toISOString(),error:d.message})}finally{clearTimeout(a)}}))}};_n();import{z as Wc}from"zod";var bh=Wc.object({sessionLabel:Wc.string().min(1).max(256)});function qc(s,e){s.post("/v1/process-tokens",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=bh.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}let o=e.processRegistry.mint(r.sessionLabel,"script");return n.code(201).send({token:o})}),s.delete("/v1/process-tokens/:sessionLabel",async(t,n)=>t.authIdentity!=="service"?n.code(403).send({error:"Requires the service token"}):(e.processRegistry.revoke(t.params.sessionLabel),n.code(204).send()))}import{nanoid as Lo}from"nanoid";import{randomBytes as Kc}from"crypto";import*as Qc from"os";import*as Yc from"path";var Sh=200;function Ih(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,Sh)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function zc(s,e,t){let n=Ih(s);if(!n)return;let r={};if(n.label!==void 0&&(r.fromLabel=n.label),n.awaiting===!0&&(r.awaiting=!0),n.sessionId!==void 0){let o=await e.resolveCanonicalId(n.sessionId)??n.sessionId,i=await e.getOne(o);if(i){r.fromSession=o,i.title&&(r.fromSessionTitle=i.title);let a=e.get(o)?.currentPromptDepth;r.depth=(a??0)+1}else t?.(n.sessionId)}if(!(r.fromSession===void 0&&r.fromLabel===void 0))return r}var $n=new Map;function Jc(s,e){let t=$n.get(s);t||(t=new Set,$n.set(s,t)),t.add(e);let n=!1;return()=>{if(n)return;n=!0;let r=$n.get(s);r&&(r.delete(e),r.size===0&&$n.delete(s))}}function Vc(s,e){if(s===e)return!0;let t=new Set,n=[e];for(;n.length>0;){let r=n.pop();if(t.has(r))continue;t.add(r);let o=$n.get(r);if(o){if(o.has(s))return!0;for(let i of o)n.push(i)}}return!1}function O(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function Eh(s){if(!s||typeof s!="object")return 512;let n=s.params?.update;if(!n)return 512;let r=512,o=n.content;if(typeof o=="string")r+=o.length;else if(o&&typeof o=="object"){let a=o;typeof a.text=="string"&&(r+=a.text.length),typeof a.data=="string"&&(r+=a.data.length)}let i=n.toolCall;if(i&&(typeof i.rawInput=="string"?r+=i.rawInput.length:i.rawInput&&typeof i.rawInput=="object"&&(r+=256),typeof i.rawOutput=="string"?r+=i.rawOutput.length:i.rawOutput&&typeof i.rawOutput=="object"&&(r+=256),Array.isArray(i.content)))for(let a of i.content){if(!a||typeof a!="object")continue;let d=a;if(typeof d.text=="string"&&(r+=d.text.length),d.content&&typeof d.content=="object"){let c=d.content;typeof c.text=="string"&&(r+=c.text.length)}}return r}function Ce(s,e,t){let n=s.get(e);if(!n)throw O(x.SessionNotFound,t??`session ${e} not found`);return n}async function vt(s,e){let t=qt(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=Kc(32).toString("hex"),r=s.mcpTokenRegistry.reserve(n),o={name:"hydra-acp-recall",type:"http",url:`${s.getDaemonOrigin()}/mcp/hydra-acp-recall`,headers:[{name:"Authorization",value:`Bearer ${n}`}]});let a=[...t?.descriptors??[],...o!==void 0?[o]:[]],d=Eo({baselineMcpServers:void 0,stdinEnabled:!1,deps:s}),c;try{c=await s.manager.resurrect({...e,mcpServers:a,...d?{mintMcpServersForSwap:d}:{}})}catch(u){throw t!==void 0&&t.abandon(u instanceof Error?u:void 0),r!==void 0&&r.abandon(u instanceof Error?u:void 0),u}if(t!==void 0&&t.bindToSession(c),n!==void 0&&r!==void 0&&s.mcpTokenRegistry!==void 0){let u=n,l=s.mcpTokenRegistry;r.complete(c),c.onClose(()=>{l.unbind(u)})}return jh(c,s),Zc(c.sessionId,s),c}function Xc(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=Hd({headers:n.headers,url:n.url});if(!r||!await e.validator.validate(r)){t.close(4401,"Unauthorized");return}let o=e.processRegistry?.resolve(r),i=`hydra_client_${Lo(12)}`,a=Ls(t),d={},c=e.foreignSessions?Bc(a,e.foreignSessions,d,i):a,u=new nt(c);d.connection=u;let l={clientId:i,processIdentity:o,attached:new Map};u.onClose(()=>{for(let h of l.attached.values())e.manager.get(h.sessionId)?.detach(h.clientId);l.attached.clear(),e.foreignSessions?.detachClient(i)});let p=(h,f)=>{if(l.attached.get(h)?.readonly)throw O(x.PermissionDenied,`${f} not permitted on a read-only attachment`)};if(u.onRequest("initialize",async h=>{let f=Ti.parse(h??{});f.clientInfo?.name&&(l.clientInfo={name:f.clientInfo.name,...f.clientInfo.version!==void 0?{version:f.clientInfo.version}:{}});let g=f.clientInfo?.version;return g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g)),Dh()}),o&&e.extensionCommands){let h=e.extensionCommands;u.onRequest("hydra-acp/commands/register",async f=>{let g=f??{},w=Array.isArray(g.commands)?g.commands.map(y=>{if(!y||typeof y!="object")return;let k=y;if(typeof k.verb!="string")return;let b={verb:k.verb};return typeof k.argsHint=="string"&&(b.argsHint=k.argsHint),typeof k.description=="string"&&(b.description=k.description),b}).filter(y=>y!==void 0):[];return h.register(o.name,u,w),{ok:!0,registered:w.length}}),u.onClose(()=>{h.clear(o.name)})}if(o&&e.extensionMcp){let h=e.extensionMcp;u.onRequest("hydra-acp/mcp_tools/register",async g=>{let w=g??{},y=typeof w.instructions=="string"?w.instructions:void 0,k=Array.isArray(w.tools)?w.tools.map(b=>{if(!b||typeof b!="object")return;let S=b;if(typeof S.name!="string"||S.name.length===0||typeof S.description!="string"||S.inputSchema===null||typeof S.inputSchema!="object")return;let v={name:S.name,description:S.description,inputSchema:S.inputSchema};return S.outputSchema!==null&&typeof S.outputSchema=="object"&&(v.outputSchema=S.outputSchema),v}).filter(b=>b!==void 0):[];if(k.length===0)throw new Error("register_mcp_tools requires at least one tool");return h.register(o.name,u,y,k),{ok:!0,registered:k.length}});let f=g=>{let w=g??{};if(typeof w.sessionId!="string"||w.sessionId.length===0)throw O(x.InvalidParams,"sessionId is required");return w.sessionId};if(u.onRequest("hydra-acp/session/extension_state/get",async g=>{let w=f(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw O(x.InvalidParams,"key is required");if(!e.manager)throw O(x.InternalError,"manager not wired");return{value:await e.manager.getExtensionStateKey(w,o.name,y.key)??null}}),u.onRequest("hydra-acp/session/extension_state/list",async g=>{let w=f(g);if(!e.manager)throw O(x.InternalError,"manager not wired");return{state:await e.manager.getExtensionState(w,o.name)}}),u.onRequest("hydra-acp/session/extension_state/set",async g=>{let w=f(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw O(x.InvalidParams,"key is required");if(y.value===void 0)throw O(x.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw O(x.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(w,o.name,y.key,y.value)}catch(k){throw O(x.InvalidParams,k.message)}return{ok:!0}}),u.onRequest("hydra-acp/session/extension_state/delete",async g=>{let w=f(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw O(x.InvalidParams,"key is required");if(!e.manager)throw O(x.InternalError,"manager not wired");return await e.manager.deleteExtensionStateKey(w,o.name,y.key),{ok:!0}}),e.extensionMcpControls){let g=e.extensionMcpControls;u.onRequest("hydra-acp/mcp_tools/refresh_session",async w=>{let y=w??{};if(typeof y.sessionId!="string"||y.sessionId.length===0)throw O(x.InvalidParams,"refresh_session requires sessionId");return await g.notifyToolListChanged(y.sessionId,o.name),{ok:!0}})}u.onClose(()=>{h.clear(o.name)})}if(o?.kind==="transformer"){u.onRequest("hydra-acp/transformer/initialize",async f=>{let g=f??{},w=Array.isArray(g.intercepts)?g.intercepts.filter(y=>typeof y=="string"):[];if(e.transformers&&(e.transformers.registerConnection(o.name,u,w),e.manager?.defaultTransformers.includes(o.name))){let y=e.transformers.resolveChain([o.name])[0];if(y)for(let k of e.manager.liveSessions())k.addTransformer(y)}return{ack:!0}}),u.onClose(()=>{e.transformers?.deregisterConnection(o.name)}),u.onRequest("hydra-acp/message/emit",async f=>{let g=f??{},w=typeof g.sessionId=="string"?g.sessionId:void 0,y=typeof g.method=="string"?g.method:void 0,k=g.envelope,b=g.route;if(!w)throw O(-32602,"emit_message requires sessionId");if(!y&&b!=="client_broadcast")throw O(-32602,"emit_message requires method");let S=Ce(e.manager,w),v=typeof g.respondsTo=="string"?g.respondsTo:void 0;if(v)return S.dischargeClaim(v,k),{ok:!0};if(b==="chain")return{ok:!0,response:await S.emitToChain(o.name,y,k)};if(b==="queue"){if(y!=="session/prompt")throw O(-32602,'route "queue" only supports method "session/prompt"');return{ok:!0,response:await S.emitToQueue(o.name,k)}}if(b==="daemon")return{ok:!0,response:await S.emitToChain(o.name,y,k)};if(b==="client_broadcast"){if(!k||typeof k!="object")throw O(-32602,"client_broadcast requires an envelope object");return S.broadcastClientUpdate(k),{ok:!0}}throw O(-32602,`unsupported route: ${JSON.stringify(b)}`)}),u.onRequest("hydra-acp/session/request_permission",async f=>{let g=f??{},w=typeof g.sessionId=="string"?g.sessionId:void 0;if(!w)throw O(-32602,"hydra-acp/session/request_permission requires sessionId");return Ce(e.manager,w).requestPermissionFromClients(g)}),u.onRequest("hydra-acp/transformer/attach",async f=>$h(f,o.name,e)),u.onRequest("hydra-acp/child_session/spawn",async f=>{let g=f??{},w=typeof g.agentId=="string"?g.agentId:void 0,y=typeof g.cwd=="string"?g.cwd:void 0,k=typeof g.parentSessionId=="string"?g.parentSessionId:void 0,b=g._meta&&typeof g._meta=="object"?g._meta:void 0,S=b&&b["hydra-acp"]&&typeof b["hydra-acp"]=="object"?b["hydra-acp"]:void 0,v=S&&typeof S.title=="string"?S.title:void 0,E=S&&typeof S.model=="string"?S.model:void 0;if(!y&&k){let W=e.manager.get(k);W&&(y=W.cwd)}if(!y)throw O(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let A=await Xt(y),C=w??A.agentId??e.defaultAgent,T=await e.registry?.getAgent(C),M=tn(A.configDefaults,T??{id:C})?.value,H=E??M?.model,J=typeof g.interactive=="boolean"?g.interactive:!1;return{childSessionId:(await e.manager.create({agentId:C,cwd:y,parentSessionId:k,interactive:J,transformChain:[],title:v,model:H,configDefaults:M})).sessionId}}),u.onRequest("hydra-acp/session/fork",async f=>{let g=f??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"fork_session requires sessionId");let w=typeof g.forkAt=="string"?g.forkAt:void 0,y=typeof g.cwd=="string"?g.cwd:void 0,k=typeof g.agentId=="string"?g.agentId:void 0,b=typeof g.mode=="string"&&(g.mode==="verbatim"||g.mode==="synthesis")?g.mode:void 0,S=typeof g.model=="string"&&g.model.length>0?g.model:void 0,v=await e.manager.forkSession(g.sessionId,{...w!==void 0?{forkAt:w}:{},...y!==void 0?{cwd:y}:{},...k!==void 0?{agentId:k}:{},...b!==void 0?{mode:b}:{},...S!==void 0?{model:S}:{}}),E=e.manager.get(v.sessionId);if(!E){let T=await e.manager.loadFromDisk(v.sessionId);if(!T)throw O(x.InternalError,`fork ${v.sessionId} vanished before it could be attached`);E=await vt(e,{...T,onInstallProgress:qs(u)})}Jt(l,E,E.sessionId);let A=dt(u,E,l),{entries:C}=await E.attach(A,"full");l.attached.set(E.sessionId,{sessionId:E.sessionId,clientId:A.clientId,readonly:!1});for(let T of C){if(u.isClosed())break;await u.notify(T.method,Le(He(T.params,T.recordedAt),T.seq)).catch(()=>{})}return{...v,sessionId:E.sessionId}}),u.onRequest("session/fork",async f=>{let g=f??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"session/fork requires sessionId");let w=typeof g.cwd=="string"?g.cwd:void 0,y=await e.manager.forkSession(g.sessionId,{...w!==void 0?{cwd:w}:{},mode:"verbatim"}),k=e.manager.get(y.sessionId);if(!k){let v=await e.manager.loadFromDisk(y.sessionId);if(!v)throw O(x.InternalError,`fork ${y.sessionId} vanished before it could be attached`);k=await vt(e,{...v,onInstallProgress:qs(u)})}Jt(l,k,k.sessionId);let b=dt(u,k,l),{entries:S}=await k.attach(b,"full");l.attached.set(k.sessionId,{sessionId:k.sessionId,clientId:b.clientId,readonly:!1});for(let v of S){if(u.isClosed())break;await u.notify(v.method,Le(He(v.params,v.recordedAt),v.seq)).catch(()=>{})}return{sessionId:k.sessionId}});let h=async(f,g)=>{let w=f??{};if(typeof w.sessionId!="string")throw O(x.InvalidParams,`${g} requires sessionId`);let y=await e.manager.resolveCanonicalId(w.sessionId)??w.sessionId,k=e.manager.get(y);if(k)return await k.close({deleteRecord:!0,by:`session/delete ${l.clientId}`}),await e.manager.waitForDeletion(y),await e.manager.hasRecord(y)&&await e.manager.deleteRecord(y),{id:y,existed:!0};let b=await e.manager.deleteRecord(y);return{id:y,existed:b}};u.onRequest("session/delete",async f=>(await h(f,"session/delete"),{})),u.onRequest("session/close",async f=>{let g=f??{};if(typeof g.sessionId!="string")throw O(x.InvalidParams,"session/close requires sessionId");p(g.sessionId,"session/close");let w=await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId,y=e.manager.get(w);if(y)return await y.close({deleteRecord:!1,by:`session/close ${l.clientId}`+(l.processIdentity?` (${l.processIdentity.name})`:"")}),{};if(await e.manager.hasRecord(w))return{};throw O(x.SessionNotFound,`session ${w} not found`)}),u.onRequest("hydra-acp/session/delete",async f=>{let{id:g,existed:w}=await h(f,"hydra-acp/session/delete");if(!w)throw O(x.SessionNotFound,`session ${g} not found`);return{deleted:!0,sessionId:g}}),u.onRequest("hydra-acp/child_session/await",async f=>{let g=f??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0,y=g.until==="idle"?"idle":"turn_complete",k=typeof g.timeoutMs=="number"?Math.min(g.timeoutMs,18e5):3e5;if(!w)throw O(-32602,"await_child requires childSessionId");let b=Ce(e.manager,w,`child session ${w} not found`);return new Promise(S=>{let A=[],C=[],T=0,M=!1,H,J,$=!1,W=()=>{$||($=!0,clearTimeout(q),H?.(),J?.(),S(M?{entries:A,truncated:!0}:{entries:A}))};H=b.onBroadcast(te=>{let ie=Eh(te);for(A.push(te),C.push(ie),T+=ie;A.length>0&&(A.length>1e3||T>1048576);)A.shift(),T-=C.shift()??0,M=!0;y==="turn_complete"&&te.params?.update?.sessionUpdate==="turn_complete"&&W()});let q=setTimeout(W,k);typeof q.unref=="function"&&q.unref(),J=b.onClose(()=>W())})}),u.onRequest("hydra-acp/child_session/close",async f=>{let g=f??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0;if(!w)throw O(-32602,"close_child_session requires childSessionId");let y=e.manager.get(w);return y&&await y.close({deleteRecord:!1,by:`child_session/close ${l.clientId}`}),{ok:!0}}),u.onRequest("hydra-acp/attention/set",async f=>Fh(f,o.name,e)),u.onRequest("hydra-acp/attention/clear",async f=>Oh(f,o.name,e)),u.onRequest("hydra-acp/connection/keep_alive",async f=>{let g=f??{},w=typeof g.token=="string"?g.token:void 0,y=typeof g.sessionId=="string"?g.sessionId:void 0,k=typeof g.estimatedRemainingMs=="number"?g.estimatedRemainingMs:void 0;return w&&y&&e.manager.get(y)?.keepAliveClaim(w,k),{ok:!0}})}u.onRequest("hydra-acp/session/tool_content",async h=>{let f=h??{};if(typeof f.sessionId!="string"||typeof f.hash!="string")throw O(x.InvalidParams,"hydra-acp/session/tool_content requires sessionId and hash");let g=await e.manager.resolveCanonicalId(f.sessionId)??f.sessionId,w=await e.manager.loadToolBlob(g,f.hash);if(w===null)throw O(x.SessionNotFound,"tool content not found");return{content:w}}),u.onRequest("authenticate",async h=>Th(h,e)),u.onRequest("logout",async h=>Ph(h,e)),u.onRequest("session/new",async h=>{let f=Pi.parse(h),g=ut(h?._meta),w=Array.isArray(g.transformers)&&g.transformers.every(X=>typeof X=="string")?g.transformers:e.manager.defaultTransformers??[],y=e.transformers?.resolveChain(w)??[],k=await Xt(f.cwd),b=g.agentId??k.agentId??e.defaultAgent,S=await e.registry?.getAgent(b),v=tn(k.configDefaults,S??{id:b})?.value,E,A,C=f.mcpServers;if(g.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){E=Kc(32).toString("hex"),A=e.mcpTokenRegistry.reserve(E);let ke={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${E}`}]};C=[...f.mcpServers??[],ke]}let T,M,H=qt(e);H!==void 0&&(C=[...C??[],...H.descriptors]);let J=Eo({baselineMcpServers:f.mcpServers,stdinEnabled:g.mcpStdin===!0,deps:e}),$;try{$=await e.manager.create({cwd:f.cwd,agentId:b,mcpServers:C,title:g.title,agentArgs:g.agentArgs,model:g.model??v?.model,configDefaults:v,onInstallProgress:qs(u),transformChain:y,originatingClient:l.clientInfo,...g.interactive!==void 0?{interactive:g.interactive}:{},...g.env!==void 0?{forwardedEnv:g.env}:{},...g.workspace!==void 0?{workspace:g.workspace}:{},...J?{mintMcpServersForSwap:J}:{}})}catch(X){throw A!==void 0&&A.abandon(X instanceof Error?X:void 0),M!==void 0&&M.abandon(X instanceof Error?X:void 0),H!==void 0&&H.abandon(X instanceof Error?X:void 0),X}if(E!==void 0&&A!==void 0&&e.mcpTokenRegistry!==void 0){let X=E,ke=e.mcpTokenRegistry;A.complete($),$.onClose(()=>{ke.unbind(X)})}if(T!==void 0&&M!==void 0&&e.mcpTokenRegistry!==void 0){let X=T,ke=e.mcpTokenRegistry;M.complete($),$.onClose(()=>{ke.unbind(X)})}H!==void 0&&H.bindToSession($),Zc($.sessionId,e);let W,q;try{Jt(l,$,$.sessionId),W=dt(u,$,l),{entries:q}=await $.attach(W,"full")}catch(X){throw await $.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),X}l.attached.set($.sessionId,{sessionId:$.sessionId,clientId:W.clientId,readonly:!1}),setImmediate(()=>{(async()=>{for(let X of q){if(u.isClosed())break;await u.notify(X.method,Le(He(X.params,X.recordedAt),X.seq)).catch(()=>{})}})()});let te=zs($),ie=Js($);return{sessionId:$.sessionId,...te?{modes:te}:{},...ie?{models:ie}:{},configOptions:$.buildConfigOptions(),_meta:Vs(e.manager,$,{clientId:W.clientId})}}),u.onRequest("session/attach",async h=>{let f=_i.parse(h),g=f.clientInfo?.version;g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g));let w=ut(f._meta),y=w.resume,k=w.readonly===!0,b=w.env;s.log.info(`session/attach sessionId=${f.sessionId} hasResumeHints=${!!y} readonly=${k}`);let S=y?f.sessionId:await e.manager.resolveCanonicalId(f.sessionId)??f.sessionId,v=e.manager.get(S);if(!v&&k){let $=await e.manager.loadFromDisk(S);if(!$)throw O(x.SessionNotFound,`session ${f.sessionId} not found`);let W=await e.manager.loadHistory(S),q=f.clientId??`cli_${Lo(8)}`;l.attached.set($.hydraSessionId,{sessionId:$.hydraSessionId,clientId:q,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${$.hydraSessionId} clientId=${q} attachedCount=${l.attached.size} replayed=${W.length}`);for(let te of W)await u.notify(te.method,Le(He(te.params,te.recordedAt),te.seq)).catch(()=>{});return{sessionId:$.hydraSessionId,clientId:q,connectedClients:[q],historyPolicy:"full",replayed:W.length,_meta:Nh($)}}let E=!v;if(!v){let $=await e.manager.loadFromDisk(S),W=await Mh(S,y,$?.upstreamSessionId,e.manager);W.kind==="ignore"&&s.log.warn(W.logMessage);let q=$;if(y&&W.kind==="honor"&&(q={...$,hydraSessionId:f.sessionId,upstreamSessionId:y.upstreamSessionId,agentId:y.agentId,cwd:$?.workspace?.path??y.cwd,...y.title!==void 0?{title:y.title}:{},...y.agentArgs!==void 0?{agentArgs:y.agentArgs}:{}}),!q)throw O(x.SessionNotFound,`session ${f.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(q.agentId,q.upstreamSessionId))throw O(x.SessionNotFound,`session ${f.sessionId} was deleted`);let te=q.originatingClient?q:{...q,originatingClient:l.clientInfo},ie=b!==void 0?{...te,forwardedEnv:b}:te;v=await vt(e,{...ie,onInstallProgress:qs(u)})}Jt(l,v,v.sessionId);let A=dt(u,v,l,f.clientInfo,f.clientId),C=w.replayMode==="drip",{entries:T,appliedPolicy:M}=await v.attach(A,f.historyPolicy,{afterMessageId:f.afterMessageId,afterSeq:f.afterSeq,raw:C,...w.historyLimit!==void 0?{historyLimit:w.historyLimit}:{},...w.toolContent!==void 0?{toolContent:w.toolContent}:{}});if(l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:A.clientId,readonly:k}),b!==void 0&&await e.manager.setForwardedEnv(v.sessionId,b).catch(()=>{}),s.log.info(`session/attach OK sessionId=${v.sessionId} clientId=${A.clientId} attachedCount=${l.attached.size} requestedPolicy=${f.historyPolicy} appliedPolicy=${M} replayed=${T.length} readonly=${k}${C?" replayMode=drip":""}`),C){let $=w.dripSpeed&&w.dripSpeed>0?w.dripSpeed:1,W=750;(async()=>{let q=null;for(let te of T){let ie=typeof te.recordedAt=="number"?te.recordedAt:null;if(q!==null&&ie!==null){let X=Math.min(W,Math.max(0,(ie-q)/$));X>0&&await new Promise(ke=>setTimeout(ke,X))}ie!==null&&(q=ie);try{await u.notify(te.method,Le(He(te.params,ie??void 0),te.seq))}catch{return}}})()}else for(let $=0;$<T.length&&!u.isClosed();$++){let W=T[$],q=u.notify(W.method,Le(He(W.params,W.recordedAt),W.seq)).catch(()=>{});($+1)%200===0&&await q}v.replayPendingPermissions(A);let H=zs(v),J=Js(v);return{sessionId:v.sessionId,clientId:A.clientId,connectedClients:v.connectedClients(A.clientId),historyPolicy:M,replayed:T.length,...H?{modes:H}:{},...J?{models:J}:{},configOptions:v.buildConfigOptions(),_meta:Vs(e.manager,v,{resurrected:E})}}),u.onRequest("session/detach",async h=>{let f=$i.parse(h),g=l.attached.get(f.sessionId);if(!g)throw O(x.SessionNotFound,"client not attached to that session");let w=e.manager.get(f.sessionId);return w?.detach(g.clientId),l.attached.delete(f.sessionId),w&&e.manager.reapIfOrphanedNonInteractive(f.sessionId),{sessionId:f.sessionId,_meta:{[ae]:{detachStatus:"detached"}}}}),u.onRequest("session/list",async h=>{let f=Fi.parse(h??{});return{sessions:(await e.manager.list({cwd:f.cwd})).filter(k=>k.originatingClient?.name!==us).map(Oi)}}),u.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw O(x.InternalError,"agent registry unavailable");return Rt(e.registry)}),u.onRequest("hydra-acp/agents/auth_methods",async h=>{let f=h??{};if(typeof f.agentId!="string"||f.agentId.length===0)throw O(x.InvalidParams,"hydra-acp/agents/auth_methods requires a non-empty agentId string");return{authMethods:(await e.manager.bootstrapAgentForAuth(f.agentId)).authMethods??[]}}),u.onRequest("session/prompt",async h=>{let f=Ni.parse(h);p(f.sessionId,"session/prompt");let g=await zc(f,e.manager,b=>{s.log.warn(`session/prompt: dropping unknown sentBy.sessionId=${b} sessionId=${f.sessionId}`)});if(g?.fromSession!==void 0){if((g.depth??0)>3)throw s.log.warn(`session/prompt: refusing depth ${g.depth} chain from ${g.fromSession} to ${f.sessionId}`),O(x.InvalidRequest,`message chain too deep (${g.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(g.awaiting===!0&&Vc(g.fromSession,f.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${g.fromSession} -> ${f.sessionId}`),O(x.InvalidRequest,`would deadlock: ${f.sessionId} is already blocked waiting on ${g.fromSession}. Send with --no-wait, or let the other turn finish first.`)}let w=l.attached.get(f.sessionId);if(!w)throw s.log.warn(`session/prompt rejected: not attached sessionId=${f.sessionId} attachedKeys=[${[...l.attached.keys()].join(",")}]`),O(x.SessionNotFound,"not attached to session");let y=e.manager.get(f.sessionId);if(!y){let b=await e.manager.loadFromDisk(f.sessionId);if(!b)throw O(x.SessionNotFound,`session ${f.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${f.sessionId}`),y=await vt(e,b);let S=dt(u,y,l,void 0,w.clientId);await y.attach(S,"none")}let k=g?.awaiting===!0&&g.fromSession!==void 0?Jc(g.fromSession,f.sessionId):void 0;try{return await y.prompt(w.clientId,f,g)}finally{k?.()}});let m=h=>{let f;try{f=Wn.parse(h)}catch(y){s.log.warn(`session/cancel: invalid params: ${y.message}`);return}let g=l.attached.get(f.sessionId);if(!g)return;if(g.readonly){s.log.warn(`session/cancel dropped (readonly attachment) sessionId=${f.sessionId}`);return}let w=e.manager.get(f.sessionId);w&&w.cancel(g.clientId).catch(y=>{s.log.warn(`session/cancel for ${f.sessionId}: ${y.message}`)})};u.onNotification("session/cancel",m),u.onRequest("session/cancel",async h=>{let f=Wn.parse(h);return p(f.sessionId,"session/cancel"),m(h),null}),u.onRequest("hydra-acp/prompt/cancel",async h=>{let f=ji.parse(h);return p(f.sessionId,"hydra-acp/prompt/cancel"),Ce(e.manager,f.sessionId).cancelQueuedPrompt(f.messageId)}),u.onRequest("hydra-acp/session/force_cancel",async h=>{let f=Wn.parse(h);return p(f.sessionId,"hydra-acp/session/force_cancel"),Ce(e.manager,f.sessionId).forceCancel()}),u.onRequest("hydra-acp/prompt/update",async h=>{let f=Hi.parse(h);return p(f.sessionId,"hydra-acp/prompt/update"),Ce(e.manager,f.sessionId).updateQueuedPrompt(f.messageId,f.prompt)}),u.onRequest("hydra-acp/prompt/amend",async h=>{let f=Li.parse(h);p(f.sessionId,"hydra-acp/prompt/amend");let g=l.attached.get(f.sessionId);if(!g)throw O(x.SessionNotFound,"not attached to session");return Ce(e.manager,f.sessionId).amendPrompt(g.clientId,f)}),u.onRequest("_session/steering",async h=>{let f=Ui.parse(h);p(f.sessionId,"_session/steering");let g=l.attached.get(f.sessionId);if(!g)throw O(x.SessionNotFound,"not attached to session");let w=e.manager.get(f.sessionId);if(!w){let y=await e.manager.loadFromDisk(f.sessionId);if(!y)throw O(x.SessionNotFound,`session ${f.sessionId} not found`);w=await vt(e,y);let k=dt(u,w,l,void 0,g.clientId);await w.attach(k,"none")}return w.steer(g.clientId,f)}),u.onRequest("session/resume",async h=>{let f=h??{},g=typeof f.sessionId=="string"?f.sessionId:void 0;if(!g)throw O(x.InvalidParams,"session/resume requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let v=await e.manager.loadFromDisk(w);if(!v)throw O(x.SessionNotFound,`session ${g} not found in memory or on disk`);y=await vt(e,v)}Jt(l,y,y.sessionId);let k=dt(u,y,l);await y.attach(k,"pending_only"),l.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:k.clientId,readonly:!1}),y.replayPendingPermissions(k);let b=zs(y),S=Js(y);return{sessionId:y.sessionId,...b?{modes:b}:{},...S?{models:S}:{},configOptions:y.buildConfigOptions(),_meta:Vs(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/load",async h=>{let f=h??{},g=typeof f.sessionId=="string"?f.sessionId:void 0;if(!g)throw O(x.InvalidParams,"session/load requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let E=await e.manager.loadFromDisk(w);if(!E)throw O(x.SessionNotFound,`session ${g} not found in memory or on disk`);y=await vt(e,E)}Jt(l,y,y.sessionId);let k=dt(u,y,l),{entries:b}=await y.attach(k,"full");l.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:k.clientId,readonly:!1});for(let E of b){if(u.isClosed())break;await u.notify(E.method,Le(He(E.params,E.recordedAt),E.seq)).catch(()=>{})}y.replayPendingPermissions(k);let S=zs(y),v=Js(y);return{sessionId:y.sessionId,...S?{modes:S}:{},...v?{models:v}:{},configOptions:y.buildConfigOptions(),_meta:Vs(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/set_model",async h=>{let f=h?.sessionId;typeof f=="string"&&p(f,"session/set_model");let g=_h(h,e.manager);if(g.kind==="error")throw s.log.warn(g.logMessage),O(g.code,g.message);if(g.kind==="no_op")return s.log.warn(g.logMessage),await u.notify("session/update",{sessionId:g.sessionId,update:{sessionUpdate:"_hydra_current_model_update",currentModel:g.currentModel}}).catch(()=>{}),null;s.log.info(g.logMessage);let{modelId:w}=g,y=await g.session.forwardModelChange(w,h);return g.session.applyAgentConfigOptionResponse(y,"model"),g.session.applyModelChange(w),y}),u.onRequest("session/set_mode",async h=>{let f=h,g=f?.sessionId;if(typeof g=="string"&&p(g,"session/set_mode"),!f||typeof f.sessionId!="string")throw O(x.InvalidParams,"session/set_mode requires string sessionId");if(typeof f.modeId!="string")throw O(x.InvalidParams,"session/set_mode requires string modeId");let w=Ce(e.manager,f.sessionId),y=await w.forwardRequest("session/set_mode",h);return w.applyModeChange(f.modeId),y}),u.onRequest("session/set_config_option",async h=>{let f=h,g=b=>O(x.InvalidParams,b),w=f?.sessionId;if(typeof w=="string"&&p(w,"session/set_config_option"),!f||typeof f.sessionId!="string")throw g("session/set_config_option requires string sessionId");if(typeof f.configId!="string")throw g("session/set_config_option requires string configId");if(typeof f.value!="string")throw g("session/set_config_option requires string value");let y=Ce(e.manager,f.sessionId),k=y.buildConfigOptions().find(b=>b.id===f.configId);if(!k)throw g(`unknown configId ${JSON.stringify(f.configId)} for this session`);if(!k.options.some(b=>b.value===f.value))throw g(`value ${JSON.stringify(f.value)} is not valid for configId ${JSON.stringify(f.configId)}`);switch(f.configId){case"model":{if(f.value!==y.currentModel){let b=await y.forwardModelChange(f.value);y.applyAgentConfigOptionResponse(b,"model")}y.applyModelChange(f.value);break}case"mode":{f.value!==y.currentMode&&await y.forwardRequest("session/set_mode",{sessionId:f.sessionId,modeId:f.value}),y.applyModeChange(f.value);break}case"agent":{f.value!==y.agentId&&await y.setAgent(f.value);break}default:{let b=await y.forwardRequest("session/set_config_option",{sessionId:f.sessionId,configId:f.configId,value:f.value});y.applyAgentConfigOptionResponse(b,f.configId)&&y.broadcastConfigOptions()}}return{configOptions:y.buildConfigOptions()}}),u.setDefaultHandler(async(h,f)=>{let g=new Set(["hydra-acp/attention/set","hydra-acp/attention/clear"]),w=f.startsWith("session/"),y=f.startsWith("hydra-acp/");if(!w&&!y||h===null||typeof h!="object"||g.has(f))throw O(x.MethodNotFound,`Method not found: ${f}`);let k=h.sessionId;if(typeof k!="string")throw O(x.MethodNotFound,`Method not found: ${f}`);return p(k,f),Ce(e.manager,k).forwardRequest(f,h)})})}async function Th(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw O(x.InvalidParams,"authenticate requires a non-empty methodId string");let n=t.methodId,r=t._meta?.["hydra-acp"],o=typeof r?.sessionId=="string"?r.sessionId:void 0,i=typeof r?.agentId=="string"?r.agentId:void 0,a=o!==void 0?e.manager.getAgentForSession(o):void 0;if(!a||!a.isAlive()){let m=i??e.defaultAgent;a=await e.manager.bootstrapAgentForAuth(m)}let d=a.authMethods??[],c=d.find(m=>m.id===n);if(!c){let m=d.map(h=>h.id);throw O(x.InvalidParams,`authenticate: methodId ${JSON.stringify(n)} is not advertised by agent ${a.agentId}; valid: [${m.map(h=>JSON.stringify(h)).join(", ")}]`)}let u=c._meta?.type,l=(()=>{let m=c._meta?.["terminal-auth"];if(m&&typeof m=="object"&&!Array.isArray(m))return m})();if((c.type??(u==="agent"||u==="terminal"?u:l!==void 0?"terminal":"agent"))==="terminal"){let m=(k,b)=>{if(!Array.isArray(k))throw O(x.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be a string[]; got ${k===null?"null":typeof k}`);for(let S of k)if(typeof S!="string")throw O(x.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be string[]; got non-string entry ${JSON.stringify(S)}`);return k},h=await e.manager.planSpawnForAgent(a.agentId),f,g;if(l?.args!==void 0){let k=typeof l.command=="string"?l.command:void 0;f=k!==void 0&&Yc.isAbsolute(k)?k:h.command,g=m(l.args,'_meta["terminal-auth"].args')}else{let k=c.args!==void 0?{raw:c.args,label:"args"}:c._meta?.args!==void 0?{raw:c._meta.args,label:"_meta.args"}:void 0,b=k!==void 0?m(k.raw,k.label):[];f=h.command,g=[...h.args,...b]}let w={};for(let[k,b]of Object.entries(process.env))typeof b=="string"&&(w[k]=b);Object.assign(w,h.env);let y=Qc.homedir();return console.error(`[authenticate] terminal-auth requested agentId=${a.agentId} methodId=${n}`),{kind:"terminal",command:f,args:g,env:w,cwd:y}}try{return await a.connection.request("authenticate",{methodId:n})}catch(m){throw ot(m,a)}}async function Ph(s,e){let n=(s??{})._meta?.["hydra-acp"],r=typeof n?.sessionId=="string"?n.sessionId:void 0,o=typeof n?.agentId=="string"?n.agentId:void 0,i=r!==void 0?e.manager.getAgentForSession(r):void 0;if(!i||!i.isAlive()){let a=o??e.defaultAgent;i=await e.manager.bootstrapAgentForAuth(a)}return await i.connection.request("logout",{})}function qs(s){return e=>{let t={agentId:e.agentId,version:e.version,source:e.source,phase:e.phase};"receivedBytes"in e&&(t.receivedBytes=e.receivedBytes),"totalBytes"in e&&(t.totalBytes=e.totalBytes),"packageSpec"in e&&(t.packageSpec=e.packageSpec),s.notify(Bi,t).catch(()=>{})}}function zs(s){let e=s.availableModes();if(e.length===0)return;let t=e.map(r=>{let o={id:r.id,name:r.name??r.id};return r.description!==void 0&&(o.description=r.description),o});return{currentModeId:s.currentMode??e[0].id,availableModes:t}}function Js(s){let e=s.availableModels();if(e.length===0)return;let t=e.map(r=>{let o={modelId:r.modelId};return r.name!==void 0&&(o.name=r.name),r.description!==void 0&&(o.description=r.description),o});return{currentModelId:s.currentModel??e[0].modelId,availableModels:t}}async function Mh(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 _h(s,e){if(!s||typeof s!="object")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires params",logMessage:"session/set_model rejected: params not an object"};let t=s;if(typeof t.sessionId!="string")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires string sessionId",logMessage:"session/set_model rejected: missing/non-string sessionId"};if(typeof t.modelId!="string")return{kind:"error",code:x.InvalidParams,message:"session/set_model requires string modelId",logMessage:`session/set_model rejected: missing/non-string modelId sessionId=${t.sessionId}`};let n=e.get(t.sessionId);if(!n)return{kind:"error",code:x.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=_t(t.modelId,r);if(o.kind==="none")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model passthrough (no availableModels) sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="exact")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model accepted sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="resolved")return{kind:"ok",session:n,modelId:o.modelId,logMessage:`session/set_model resolved sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} \u2192 ${JSON.stringify(o.modelId)}`};let i=r.map(d=>d.modelId).join(", "),a=o.kind==="ambiguous"?`ambiguous (trailing-segment matches [${o.candidates.join(", ")}])`:"not in availableModels";return n.currentModel!==void 0&&n.currentModel.length>0?{kind:"no_op",session:n,sessionId:t.sessionId,currentModel:n.currentModel,logMessage:`session/set_model no_op (resyncing client) sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} ${a} actual=${JSON.stringify(n.currentModel)} agentId=${n.agentId} known=[${i}]`}:{kind:"error",code:x.InvalidParams,message:`model "${t.modelId}" is ${a==="not in availableModels"?"not in this session's availableModels":a} (agent ${n.agentId}); known models: ${i}`,logMessage:`session/set_model rejected sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)} ${a} agentId=${n.agentId} known=[${i}] (no current model to fall back to)`}}async function $h(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw O(x.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw O(x.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw O(x.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return Ce(t.manager,r).addTransformer(o),{ok:!0}}async function Fh(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(x.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw O(x.InvalidParams,"hydra-acp/attention/set requires string reason");return Ce(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function Oh(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw O(x.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw O(x.InvalidParams,"hydra-acp/attention/clear requires string reason");return Ce(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function Nh(s){let e={sessionId:s.hydraSessionId,upstreamSessionId:s.upstreamSessionId,cwd:s.cwd,workspace:s.workspace,title:s.title,agentId:s.agentId,currentModel:s.currentModel,currentUsage:wn(s.currentUsage),forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:s.interactive,updatedAt:s.createdAt??new Date().toISOString(),attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1},t={currentMode:s.currentMode,agentArgs:s.agentArgs,availableCommands:s.agentCommands,availableModes:s.agentModes,availableModels:s.agentModels,armedTaskList:[]};return{[ae]:Bn(e,t)}}function Vs(s,e,t={}){let n=s.liveListEntry(e),r={clientId:t.clientId,currentMode:e.currentMode,agentArgs:e.agentArgs,availableCommands:e.mergedAvailableCommands(),availableModes:e.availableModes(),availableModels:e.availableModels(),turnStartedAt:e.turnStartedAt,agentCapabilities:e.agentCapabilities,queue:e.queueSnapshot(),armedTaskList:e.armedBackgroundTasks,...t.resurrected===!0?{resurrected:!0}:{}};return nn(e.agentMeta,Bn(n,r))}function Dh(){return{protocolVersion:1,agentInfo:{name:"hydra",version:me},agentCapabilities:{promptCapabilities:{image:!0,audio:!0,embeddedContext:!0},mcpCapabilities:{http:!0,sse:!0},loadSession:!0,auth:{logout:{}},sessionCapabilities:{attach:{},list:{},resume:{},delete:{},close:{},fork:{}}},authMethods:[{id:"proxy",name:"Hydra proxy",type:"agent",description:"Hydra proxies authentication to the downstream agent selected per session"}],_meta:{...nn(void 0,{prompt:{queueing:!0,cancelling:!0,updating:!0,amending:!0,pipelining:!1},agents:{list:!0,installProgress:!0},session:{fork:{forkAt:!0,agentSwap:!0,synthesis:!0,model:!0}}}),steering:{supported:!0}}}}function jh(s,e){if(!(!e.transformers||!e.manager))for(let t of e.manager.defaultTransformers){let n=e.transformers.resolveChain([t])[0];n&&s.addTransformer(n)}}function Zc(s,e){if(!e.transformers)return;let t=e.transformers.interestedIn("lifecycle:session.starting");for(let n of t)n.connection.notify("hydra-acp/transformer/session_event",{event:"session.starting",sessionId:s}).catch(()=>{})}function dt(s,e,t,n,r){return{clientId:r??`cli_${Lo(8)}`,connection:s,clientInfo:n}}function Jt(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var Gs=class{byToken=new Map;reserve(e){if(this.byToken.has(e))throw new Error("mcp token already bound");let t,n,r=new Promise((i,a)=>{t=i,n=a});r.catch(()=>{});let o={session:void 0,sessionReady:r,disposers:[]};return this.byToken.set(e,o),{complete:i=>{o.session=i,t(i)},abandon:i=>{this.byToken.delete(e),n(i??new Error("mcp token reservation abandoned"))}}}bind(e,t){let{complete:n}=this.reserve(e);n(t)}lookup(e){return this.byToken.get(e)}addDisposer(e,t){let n=this.byToken.get(e);n!==void 0&&n.disposers.push(t)}async unbind(e){let t=this.byToken.get(e);if(t!==void 0){this.byToken.delete(e);for(let n of t.disposers)try{await n()}catch{}}}size(){return this.byToken.size}};import{randomUUID as Hh}from"crypto";import{McpServer as Lh}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Uh}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as he}from"zod";function Uo(s){if(s.method!=="session/update")return null;let t=s.params?.update;return!t||typeof t.sessionUpdate!="string"?null:{kind:t.sessionUpdate,update:t}}function Se(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var eu="Bearer ";function Vt(s){let e=s.headers.authorization;if(typeof e!="string"||!e.startsWith(eu))return;let t=e.slice(eu.length).trim();return t.length>0?t:void 0}function Bh(s){let e=new Lh({name:"hydra-acp-stdin",version:"1.0.0"},{instructions:"Piped input from `hydra cat --stream` is exposed here as a byte stream. Use `tail` for the latest N bytes (good for finding the end of a log), `head` for the first N bytes (good for headers/preamble), `read` for windowed reads against an absolute byte cursor, `wait_for_more` to block until new bytes arrive past a cursor, and `info` for the current cursors/capacity/closed status. Byte payloads come back base64-encoded."});return e.registerTool("tail",{description:"Return the most recent `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means older bytes existed but have been evicted from the ring.",inputSchema:{bytes:he.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return Se(n)}),e.registerTool("head",{description:"Return the first `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means the head has already been evicted from the ring and the returned bytes start at the oldest still-resident cursor.",inputSchema:{bytes:he.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return Se(n)}),e.registerTool("read",{description:"Read up to `max_bytes` bytes starting at absolute byte `cursor`. Returns `{bytes, nextCursor, gap?, eof?}` \u2014 `gap` is the number of bytes silently skipped because the ring had evicted them; `eof:true` means the producer closed and there is nothing left to read.",inputSchema:{cursor:he.number().int().min(0).describe("Absolute byte offset to start reading from. Use 0 to read from the very beginning (may produce a gap if old bytes have been evicted)."),max_bytes:he.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:he.number().int().min(0).optional().describe("If no bytes are available, block up to this many ms for more (capped server-side at 60_000).")}},async({cursor:t,max_bytes:n,wait_ms:r})=>{let o=await s.streamRead(t,n,r);return Se(o)}),e.registerTool("wait_for_more",{description:"Block until bytes are available past `cursor`, the stream closes, or `timeout_ms` elapses. Returns one of {data, eof, timeout} plus the current `writeCursor`. Use this when you've consumed everything up to a cursor and want to wait for more without busy-polling.",inputSchema:{cursor:he.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:he.number().int().min(0).describe("Maximum ms to block (server caps at 60_000).")}},async({cursor:t,timeout_ms:n})=>{let r=await s.streamWaitFor(t,n),o=s.streamInfo();return Se({outcome:r,writeCursor:o.writeCursor,closed:o.closed})}),e.registerTool("grep",{description:"Scan piped stdin line-by-line and return lines matching `pattern`. Prefer this over `read` when the question is 'find lines that mention X' \u2014 it filters server-side so you don't pull and decode 64 KiB base64 windows. Returns `{matches: [{cursor, line, before?, after?}], truncated, nextCursor, gap?, scannedBytes, eof?}`. Lines come back as decoded UTF-8 strings (not base64). When `truncated:true`, re-call with `cursor: nextCursor` to resume.",inputSchema:{pattern:he.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:he.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:he.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:he.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:he.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:he.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:he.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:he.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:he.number().int().min(0).optional().describe("Optional absolute byte offset to start scanning from. Omit to scan from the oldest still-resident byte. Pass the `nextCursor` from a previous truncated call to resume.")}},async t=>{let n={pattern:t.pattern};t.regex!==void 0&&(n.regex=t.regex),t.case_insensitive!==void 0&&(n.caseInsensitive=t.case_insensitive),t.invert!==void 0&&(n.invert=t.invert),t.max_matches!==void 0&&(n.maxMatches=t.max_matches),t.max_bytes!==void 0&&(n.maxBytes=t.max_bytes),t.context_before!==void 0&&(n.contextBefore=t.context_before),t.context_after!==void 0&&(n.contextAfter=t.context_after),t.cursor!==void 0&&(n.cursor=t.cursor);let r=s.streamGrep(n);return Se(r)}),e.registerTool("info",{description:"Report cursor / capacity / closed state of the stdin ring. Cheap; safe to call repeatedly.",inputSchema:{}},async()=>{let t=s.streamInfo();return Se(t)}),e}var Wh=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=Bh(a),u=new Uh({sessionIdGenerator:()=>Hh()});await c.connect(u);let l={server:c,transport:u};return t.set(i,l),e.addDisposer(i,async()=>{t.delete(i);try{await u.close()}catch{}try{await c.close()}catch{}}),u}async function r(i,a){let d=Vt(i);if(d===void 0){a.code(401).send({error:"missing bearer token"});return}let c=e.lookup(d);if(c===void 0){a.code(404).send({error:"unknown stdin token"});return}let u;if(c.session!==void 0)u=c.session;else{let p,m=new Promise(f=>{p=setTimeout(()=>f(void 0),Wh)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(p!==void 0&&clearTimeout(p),h===void 0){a.code(503).send({error:"session not ready"});return}u=h}let l=await n(d,u);a.hijack(),await l.handleRequest(i.raw,a.raw,i.body)}let o={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.get("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.delete("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)})}import{randomUUID as qh}from"crypto";import{McpServer as zh}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Jh}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as Ve}from"zod";function Vh(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var nu=2e3,su=2e4;function Gh(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return $t([s]);let n=[],r=on(t);r!==void 0?n.push(`Tool: ${r}`):typeof t.title=="string"&&t.title.length>0&&n.push(`Tool: ${t.title}`);let o=t.rawInput;if(o&&typeof o=="object"&&!Array.isArray(o))for(let[a,d]of Object.entries(o))typeof d=="string"&&d.length>0&&n.push(`${a}=${d}`);if(Array.isArray(t.locations))for(let a of t.locations)typeof a?.path=="string"&&a.path.length>0&&n.push(a.path);let i=Vn(t);return i!==void 0&&n.push(i),n.join(`
|
|
194
|
+
`)}function Kh(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 Qh(s){let e=new zh({name:"hydra-acp-recall",version:"1.0.0"},{instructions:"Search and retrieve detail from this session's pre-compaction history. After a compaction summary replaces earlier conversation in working memory, these tools let you page back specifics on demand. Use `search` to find entries by keyword, `range` to pull a contiguous slice verbatim, and `tool_calls` to enumerate prior tool invocations. These tools only return results once the session has been compacted at least once."});return e.registerTool("search",{description:"Search this session's prior conversation history (the part that was compacted out of your working memory) by keyword. Covers assistant and user messages, the arguments of every tool call including full shell commands, and what those calls printed. Returns matching entry ids with short snippets so you can decide which to pull in full via `range`. Use this when the compaction summary mentions something but you need the verbatim detail.",inputSchema:{query:Ve.string().min(1).describe("Case-insensitive substring to search for."),limit:Ve.number().int().min(1).max(50).optional().describe("Maximum number of matches to return (default 10, max 50)."),include_tool_calls:Ve.boolean().optional().describe("Whether to include tool_call entries in the search (default true).")}},async({query:t,limit:n=10,include_tool_calls:r=!0})=>{let o=await s();if(!o.summarizedThroughEntry||o.summarizedThroughEntry===0)return Se({matches:[],total_matched:0,truncated:!1,note:"This session has no compacted history. `search` retrieves detail from entries that were summarized out of the working conversation; nothing has been summarized yet."});let i=[],a=t.toLowerCase();for await(let{entryId:c,entry:u}of o.iterRecallNewestFirst()){let l=Uo(u);if(!l)continue;let{kind:p,update:m}=l;if((p==="tool_call"||p==="tool_call_update")&&!r)continue;let h=Gh(u,p,m),f=h.toLowerCase().indexOf(a);if(f<0)continue;let g=Vh(p),w=Kh(h,f),y=typeof u.recordedAt=="number"?String(u.recordedAt):void 0;if(i.push({entryId:c,speaker:g,snippet:w,timestamp:y}),i.length>=n)break}i.sort((c,u)=>c.entryId-u.entryId);let d=i.length>=n;return Se({matches:i,total_matched:i.length,truncated:d})}),e.registerTool("range",{description:"Pull a contiguous range of prior conversation entries verbatim from this session's pre-compaction history, including each tool call's arguments and what it printed. Use after `search` narrows in on what you need. Capped at 50 entries per call.",inputSchema:{from_entry:Ve.number().int().min(0).describe("Zero-based index of the first entry to include (inclusive)."),to_entry:Ve.number().int().min(0).describe("Zero-based index of the last entry to include (inclusive).")}},async({from_entry:t,to_entry:n})=>{let r=await s();if(!r.summarizedThroughEntry||r.summarizedThroughEntry===0)return Se({text:"",entry_count:0,truncated:!1,note:"This session has no compacted history. `range` retrieves verbatim entries from the pre-compaction transcript; nothing has been compacted yet."});if(n<t)throw new Error(`range: to_entry (${n}) must be >= from_entry (${t})`);let o=n-t+1;if(o>50)throw new Error(`range: range size (${o}) exceeds maximum of 50 entries`);let i=await r.getRecallTotalCount();if(i===0)return Se({text:"",entry_count:0,truncated:!1});let a=Math.min(t,i-1),d=Math.min(n,i-1),c=a>t||d<n;if(a>d)return{content:[{type:"text",text:""}],structuredContent:{text:"",entry_count:0,truncated:c}};let u=await r.sliceRecallHistory(a,d),l=$t(u,{toolOutput:{maxPerCall:nu,maxTotal:su}});return{content:[{type:"text",text:l}],structuredContent:{text:l,entry_count:u.length,truncated:c}}}),e.registerTool("tool_calls",{description:"Search this session's prior tool invocations by tool name, ACP kind, and/or file path. Returns when each tool was called, its arguments (including the full shell command), the result status, and what the call printed. Use this to recall which files were read/edited, what shell commands ran, and what they output.",inputSchema:{tool_name:Ve.string().optional().describe("Case-insensitive substring of the tool name. Names vary by agent for the same tool (Bash, Terminal, bash), so prefer `kind` when you want every shell invocation."),kind:Ve.string().optional().describe("ACP tool kind: execute (shell), read, edit, think, other. Agent-independent, unlike tool_name."),file_path:Ve.string().optional(),limit:Ve.number().int().min(1).max(100).optional(),include_output:Ve.boolean().optional().describe("Include what each call printed (default true). Set false when you only need the commands and not their results.")}},async({tool_name:t,kind:n,file_path:r,limit:o=20,include_output:i=!0})=>{let a=await s();if(!a.summarizedThroughEntry||a.summarizedThroughEntry===0)return Se({calls:[],truncated:!1,note:"This session has no compacted history. `tool_calls` retrieves tool invocations from the pre-compaction transcript; nothing has been compacted yet."});let d=typeof t=="string"&&t.length>0,c=typeof n=="string"&&n.length>0,u=typeof r=="string"&&r.length>0;if(!d&&!c&&!u)throw new Error("tool_calls: at least one of tool_name, kind, or file_path must be provided");let l=new Map,p=Math.max(o*4,200);for await(let{entryId:y,entry:k}of a.iterRecallNewestFirst()){let b=Uo(k);if(!b)continue;let{kind:S,update:v}=b;if(S!=="tool_call"&&S!=="tool_call_update")continue;let E=typeof v.toolCallId=="string"&&v.toolCallId.length>0?v.toolCallId:`__noid_${y}`,A=l.get(E);if(A||(A={entryId:y,toolName:"(unnamed)",nameAuthoritative:!1,rawInput:{},locations:[],status:"in_progress"},l.set(E,A)),y<A.entryId&&(A.entryId=y),!A.nameAuthoritative){let T=on(v);T!==void 0?(A.toolName=T,A.nameAuthoritative=!0):typeof v.name=="string"&&v.name.length>0?(A.toolName=v.name,A.nameAuthoritative=!0):S==="tool_call"&&typeof v.title=="string"&&v.title.length>0&&(A.toolName=v.title,A.nameAuthoritative=!0)}if(A.kind===void 0&&typeof v.kind=="string"&&v.kind.length>0&&(A.kind=v.kind),A.output===void 0){let T=Vn(v);T!==void 0&&(A.output=T)}let C=v.rawInput;if(C&&typeof C=="object"&&!Array.isArray(C)&&Object.keys(C).length>0)for(let[T,M]of Object.entries(C))A.rawInput[T]===void 0&&(A.rawInput[T]=M);if(Array.isArray(v.locations))for(let T of v.locations){let M=T?.path;typeof M=="string"&&M.length>0&&!A.locations.includes(M)&&A.locations.push(M)}if(typeof v.status=="string"&&A.status==="in_progress"&&(A.status=v.status),k.recordedAt!==void 0&&A.timestamp===void 0&&(A.timestamp=String(k.recordedAt)),l.size>=p)break}let m=[...l.keys()].sort((y,k)=>l.get(y).entryId-l.get(k).entryId),h=[],f=su,g=!1;for(let y of m){let k=l.get(y);if(k.toolName=Tr({name:k.toolName,rawInput:k.rawInput,...k.kind!==void 0?{kind:k.kind}:{}}),d&&!k.toolName.toLowerCase().includes(t.toLowerCase())||c&&(k.kind??"").toLowerCase()!==n.toLowerCase())continue;if(u){let v=r.toLowerCase(),E=["file_path","filePath","path"],A=!1;for(let C of E){let T=k.rawInput[C];if(typeof T=="string"&&T.toLowerCase().includes(v)){A=!0;break}}if(!A){for(let C of k.locations)if(C.toLowerCase().includes(v)){A=!0;break}}if(!A)continue}let b={};for(let[v,E]of Object.entries(k.rawInput))typeof E=="string"?b[v]=E.length>500?E.slice(0,497)+"\u2026":E:(typeof E=="number"||typeof E=="boolean")&&(b[v]=E);k.locations.length>0&&b.locations===void 0&&(b.locations=k.locations);let S={entryId:k.entryId,tool:k.toolName,args:b,status:k.status,timestamp:k.timestamp};if(k.kind!==void 0&&(S.kind=k.kind),i&&k.output!==void 0){let v=k.output,E=Math.min(nu,f);if(E<=0)g=!0;else{let A=v.length<=E?v:v.slice(0,E-1)+"\u2026";S.output=A,S.outputBytes=v.length,S.outputTruncated=A.length<v.length,f-=A.length}}if(h.push(S),h.length>=o)break}let w=h.length>=o;return Se({calls:h,truncated:w,...g?{outputBudgetExhausted:g}:{}})}),e}var Yh=1e4;function ru(s,e){let t=new Map;async function n(i,a){let d=t.get(i);if(d!==void 0)return d.transport;let c=Qh(a),u=new Jh({sessionIdGenerator:()=>qh()});await c.connect(u);let l={server:c,transport:u};return t.set(i,l),e.addDisposer(i,async()=>{t.delete(i);try{await u.close()}catch{}try{await c.close()}catch{}}),u}async function r(i,a){let d=Vt(i);if(d===void 0){a.code(401).send({error:"missing bearer token"});return}let c=e.lookup(d);if(c===void 0){a.code(404).send({error:"unknown recall token"});return}let l=await n(d,async()=>{if(c.session!==void 0)return c.session;let p,m=new Promise(f=>{p=setTimeout(()=>f(void 0),Yh)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(p!==void 0&&clearTimeout(p),h===void 0)throw new Error("recall: session not ready");return h});a.hijack(),await l.handleRequest(i.raw,a.raw,i.body)}let o={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)}),s.get("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)}),s.delete("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)})}var Ks=class{byName=new Map;changeHandlers=[];register(e,t,n,r){this.byName.set(e,{connection:t,instructions:n,tools:[...r]}),this.fireChanged(e,"register")}clear(e){this.byName.delete(e)&&this.fireChanged(e,"clear")}lookup(e){return this.byName.get(e)}list(){return Array.from(this.byName.keys())}onChange(e){return this.changeHandlers.push(e),()=>{let t=this.changeHandlers.indexOf(e);t>=0&&this.changeHandlers.splice(t,1)}}fireChanged(e,t){for(let n of this.changeHandlers)try{n(e,t)}catch{}}};import{StreamableHTTPServerTransport as oy}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{randomUUID as iy}from"crypto";import{Server as Xh}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Zh,ListToolsRequestSchema as ey}from"@modelcontextprotocol/sdk/types.js";function ou(s,e,t,n){let r=typeof t=="function"?async()=>t():async()=>t,o=new Xh({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(ey,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(Zh,async(a,d)=>{let c=a.params.name,u=d._meta?.progressToken??d.requestId,l=ny(u,d.sendNotification);try{let p=await r(),m=await sy(e.connection,s,c,a.params.arguments??{},p);return ry(m,c)}catch(p){return Bo(p instanceof Error?p.message:String(p))}finally{l()}}),o}var ty=15e3;function ny(s,e,t=ty){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 sy(s,e,t,n,r){return await s.request("hydra-acp/mcp_tools/invoke",{server:e,tool:t,args:n,sessionId:r})}function ry(s,e){if(s===null||typeof s!="object")return Bo(`extension ${e} returned non-object`);let t=s;return Array.isArray(t.content)?t:Bo(`extension ${e} omitted content array`)}function Bo(s){return{content:[{type:"text",text:s}],isError:!0}}var ay=1e4;function iu(s,e,t){let n=new Map;async function r(u){try{await u.transport.close()}catch{}try{await u.server.close()}catch{}}function o(u){for(let l of n.values()){let p=l.get(u);p!==void 0&&(l.delete(u),r(p))}}async function i(u,l){for(let[p,m]of n){if(e.lookup(p)?.session?.sessionId!==u)continue;let f=m.get(l);if(f!==void 0)try{await f.server.sendToolListChanged()}catch{}}}t.onChange(u=>{o(u)});async function a(u,l){let p=n.get(u);p===void 0&&(p=new Map,n.set(u,p),e.addDisposer(u,async()=>{let b=n.get(u);if(b!==void 0){n.delete(u);for(let S of b.values())await r(S)}}));let m=p.get(l);if(m!==void 0)return m.transport;let h=t.lookup(l);if(h===void 0)return;let y=ou(l,h,async()=>{let b=e.lookup(u);if(b===void 0)throw new Error("mcp token no longer bound");if(b.session!==void 0)return b.session.sessionId;let S,v=new Promise(A=>{S=setTimeout(()=>A(void 0),ay)}),E=await Promise.race([b.sessionReady.catch(()=>{}),v]);if(S!==void 0&&clearTimeout(S),E===void 0)throw new Error("session not ready");return E.sessionId},{peekSessionId:()=>e.lookup(u)?.session?.sessionId,fetchSessionTools:async b=>{let S=await h.connection.request("hydra-acp/mcp_tools/list_tools",{sessionId:b});if(!S||typeof S!="object")return;let v=S.tools;if(!Array.isArray(v))return;let E=[];for(let A of v){if(!A||typeof A!="object")continue;let C=A;if(typeof C.name!="string"||C.name.length===0||typeof C.description!="string"||C.inputSchema===null||typeof C.inputSchema!="object")continue;let T={name:C.name,description:C.description,inputSchema:C.inputSchema};C.outputSchema!==null&&typeof C.outputSchema=="object"&&(T.outputSchema=C.outputSchema),E.push(T)}return E}}),k=new oy({sessionIdGenerator:()=>iy()});return await y.connect(k),p.set(l,{server:y,transport:k}),k}async function d(u,l){let p=Vt(u);if(p===void 0){l.code(401).send({error:"missing bearer token"});return}if(e.lookup(p)===void 0){l.code(404).send({error:"unknown mcp token"});return}let h=u.params.name,f=await a(p,h);if(f===void 0){l.code(404).send({error:`unknown mcp server: ${h}`});return}l.hijack(),await f.handleRequest(u.raw,l.raw,u.body)}let c={config:{skipAuth:!0}};return s.post("/mcp/:name",c,async(u,l)=>{await d(u,l)}),s.get("/mcp/:name",c,async(u,l)=>{await d(u,l)}),s.delete("/mcp/:name",c,async(u,l)=>{await d(u,l)}),{notifyToolListChanged:i}}async function fu(s,e){gy(s),dr(s.daemon.scrubEnv);let t=s,n=s.daemon.tls?await Ge.readFile(le(s.daemon.tls.key)):void 0,r=s.daemon.tls?await Ge.readFile(le(s.daemon.tls.cert)):void 0;await Ge.mkdir(R.home(),{recursive:!0});let{stream:o,fileStream:i}=await fy(s.daemon.logLevel),a=dy({logger:{level:s.daemon.logLevel,stream:o},bodyLimit:256*1024*1024});await a.register(cy,{options:{handleProtocols:oi}}),gr(N=>{a.log.info(N)}),yr(N=>{a.log.info(N)});let d=await As.load(),c=await js.load();No(),Fo(c);let u=new Bs(c),l=new Ws(c);l.start();let p=new Fs(c);p.start();let m=new Ts,h=new Es,f=new Cs(e),g=new xs([f,new Rs(d),h]),w=jd({validator:g});a.addHook("onRequest",async(N,ve)=>{N.routeOptions.config?.skipAuth||N.url==="/acp"||N.url?.startsWith("/acp?")||(await w(N,ve),!ve.sent&&N.authIdentity?.startsWith("script:")&&!Ld(N.method,N.routeOptions.url)&&ve.code(403).send({error:"script tokens may only access read-only session data"}))});let y=setInterval(()=>{d.sweepExpired()},300*1e3);y.unref();let k=setInterval(()=>{m.sweepExpired()},300*1e3);k.unref();let b=new Ln(s,{onFetched:()=>{Ad(b,A)},onStaleFallback:(N,ve)=>{let Kt=Math.round(ve/36e5),Qt=Kt>=48?`${Math.round(Kt/24)}d`:`${Kt}h`;a.log.warn(`registry fetch failed (${N.message}); serving stale cache last synced ${Qt} ago; agent versions may be outdated ('hydra registry refresh' to retry)`)}});bo(N=>a.log.info(N));let S={info:N=>a.log.info(N),warn:N=>a.log.warn(N)},v=N=>st.spawn({...N,stderrTailBytes:s.daemon.agentStderrTailBytes,logger:S});li(s.compressToolContent);let E=new Ss,A=new ms(b,v,void 0,{idleTimeoutMs:s.daemon.sessionIdleTimeoutSeconds*1e3,orphanTimeoutMs:s.daemon.nonInteractiveOrphanTimeoutSeconds*1e3,sessionDefaults:s.sessionDefaults,synopsisAgent:s.synopsisAgent,synopsisModel:s.synopsisModel,compactionAgent:s.compaction?.agent,compactionModel:s.compaction?.model,defaultTransformers:s.defaultTransformers,sessionHistoryMaxEntries:s.daemon.sessionHistoryMaxEntries,sessionHistoryArchiveMaxBytes:s.daemon.sessionHistoryArchiveMaxBytes,sessionHistoryArchiveTiers:s.daemon.sessionHistoryArchiveTiers,logger:S,npmRegistry:s.npmRegistry,extensionCommands:E,defaultCwd:s.defaultCwd,disableWorkspaceSnapshots:s.disableWorkspaceSnapshots}),C=new vs(ni(s),void 0,{tokenRegistry:h}),T=new bs(si(s),void 0,{tokenRegistry:h}),M=[];wc(a,me,xd(s),()=>M);let H=new Gs,J=new Ks,$,W=()=>{if($!==void 0)return $;let N=a.server.address();return $=`http://127.0.0.1:${N&&typeof N=="object"?N.port:s.daemon.port}`,$},q={agentId:s.defaultAgent,cwd:s.defaultCwd,publicHost:s.daemon.publicHost,host:s.daemon.host,port:s.daemon.port,compaction:s.compaction};hc(a,A,q,{extensionMcp:J,mcpTokenRegistry:H,getDaemonOrigin:W},c,p),fc(a,{store:c}),yc(a,b,A,{npmRegistry:s.npmRegistry}),kc(a,C),vc(a,T),bc(a,()=>({defaultAgent:t.defaultAgent,defaultCwd:t.defaultCwd,sessionDefaults:{...t.sessionDefaults},...t.synopsisAgent!==void 0?{synopsisAgent:t.synopsisAgent}:{},...t.synopsisModel!==void 0?{synopsisModel:t.synopsisModel}:{},defaultTransformers:[...t.defaultTransformers]})),Rc(a,{store:d,rateLimiter:m,staticTokenValidator:f}),Hc(a,{store:c,health:l}),qc(a,{processRegistry:h}),tu(a,H),ru(a,H);let te=iu(a,H,J);Xc(a,{validator:g,manager:A,defaultAgent:s.defaultAgent,processRegistry:h,onExtensionVersion:(N,ve)=>C.reportVersion(N,ve),onTransformerVersion:(N,ve)=>T.reportVersion(N,ve),transformers:T,extensionCommands:E,mcpTokenRegistry:H,extensionMcp:J,extensionMcpControls:te,getDaemonOrigin:W,registry:b,foreignSessions:u});let ie=!!s.daemon.tls;await a.listen({host:ie?"127.0.0.1":s.daemon.host,port:ie?0:s.daemon.port});let X=a.server.address(),ke=X&&typeof X=="object"?X.port:s.daemon.port,Fn,pu=s.daemon.host,Wo=ke;if(ie&&n&&r){Fn=py({listenHost:s.daemon.host,listenPort:s.daemon.port,upstreamHost:"127.0.0.1",upstreamPort:ke,tlsOptions:{key:n,cert:r},logger:a.log});let N=Fn.address();N&&typeof N=="object"&&(Wo=N.port)}await Ge.mkdir(R.home(),{recursive:!0}),await Id({pid:process.pid,host:pu,port:Wo,loopbackPort:ke,startedAt:new Date().toISOString()});let qo={daemonUrl:`http://127.0.0.1:${ke}`,daemonHost:"127.0.0.1",daemonPort:ke,serviceToken:e,daemonWsUrl:`ws://127.0.0.1:${ke}/acp`,hydraHome:R.home()};C.setContext(qo),T.setContext(qo),await C.start(),await T.start();try{await A.reconcilePermissionFlags()}catch(N){a.log.warn(`permission flag reconcile failed: ${N.message}`)}try{await A.seedSessionIndex()}catch(N){a.log.warn(`session index seed failed: ${N.message}`)}A.resurrectPendingQueues().catch(N=>{a.log.warn(`queue replay scan failed: ${N.message}`)}),A.resumePendingCompactions().catch(N=>{a.log.warn(`compaction resume scan failed: ${N.message}`)}),A.resumePendingAgentSwaps().catch(N=>{a.log.warn(`agent-swap resume scan failed: ${N.message}`)});let zo=s.daemon.agentSyncIntervalMinutes*60*1e3,Jo=zo>0?Cd({registry:b,manager:A,intervalMs:zo,logger:S}):void 0,Vo=s.daemon.sessionGcIntervalMinutes*60*1e3,gu=s.daemon.sessionGcMaxAgeDays*24*60*60*1e3,Go=Vo>0?Rd({manager:A,intervalMs:Vo,maxAgeMs:gu,logger:S}):void 0,mu=Md({bootConfig:s,apply:N=>{t=N,b.setConfig(N),A.setLiveConfig({sessionDefaults:N.sessionDefaults}),q.agentId=N.defaultAgent,q.cwd=N.defaultCwd,dr(N.daemon.scrubEnv)},onDrift:N=>{M=N},logger:S});return{app:a,manager:A,registry:b,extensions:C,transformers:T,mcpTokenRegistry:H,extensionMcp:J,processRegistry:h,shutdown:async()=>{l.stop(),p.stop(),mu(),Go&&Go(),Jo&&Jo(),clearInterval(y),clearInterval(k);let N=async(ve,Kt)=>{try{await Kt()}catch(Qt){a.log.warn(`shutdown step ${ve} failed: ${Qt instanceof Error?Qt.message:String(Qt)}`)}};await N("sessionTokenStore.flush",()=>d.flush()),await N("extensions.stop",()=>C.stop()),await N("transformers.stop",()=>T.stop()),await N("manager.closeAll",()=>A.closeAll()),await N("manager.flushSynopsis",()=>A.flushSynopsis(3e4)),await N("manager.shutdownSynopsis",()=>A.shutdownSynopsis()),await N("manager.flushMetaWrites",()=>A.flushMetaWrites()),await N("manager.flushHistoryWrites",()=>A.flushHistoryWrites()),gr(null),yr(null),bo(null),Fn&&await N("tlsTerminator.close",()=>new Promise(ve=>Fn.close(()=>ve()))),await N("app.close",()=>a.close());try{cu.unlinkSync(R.pidFile())}catch{}await N("fileStream.flushSync",()=>i.flushSync())}}}var du=20;async function ly(s,e){let t=Gt.dirname(s),n=Gt.basename(s,".log"),r=new RegExp(`^${n}\\.(\\d+)\\.log$`),o;try{o=await Ge.readdir(t)}catch{return}let i=[];for(let d of o){let c=d.match(r);c&&i.push({name:d,n:Number(c[1])})}if(i.length<=e)return;i.sort((d,c)=>d.n-c.n);let a=i.slice(0,i.length-e);await Promise.allSettled(a.map(d=>Ge.unlink(Gt.join(t,d.name))))}async function fy(s){await ly(R.logFile(),du);let e=await uy({file:R.logFile(),size:"10m",mkdir:!0,symlink:!0,limit:{count:du,removeOtherLogFiles:!0}}),t=au.destination(2);return{stream:au.multistream([{stream:e,level:s},{stream:t,level:s}]),fileStream:e}}function py(s){let e=lu.createServer(s.tlsOptions,t=>{let n=uu.connect({host:s.upstreamHost,port:s.upstreamPort}),r=!1,o=i=>{if(!r){r=!0,i&&s.logger.warn(`tls terminator forwarder error: ${i.message??String(i)}`);try{t.destroy()}catch{}try{n.destroy()}catch{}}};t.on("error",o),n.on("error",o),t.on("close",()=>o()),n.on("close",()=>o()),t.pipe(n),n.pipe(t)});return e.on("tlsClientError",t=>{s.logger.warn(`tls handshake error: ${t.message}`)}),e.listen({host:s.listenHost,port:s.listenPort}),e}function gy(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 my(){process.title="hydra-acp-daemon";let{installGlobalTlsTrust:s}=await Promise.resolve().then(()=>(_n(),jc));s();let e=await Zt(),t=await Ko(),n=await fu(e,t);process.stdout.write(`hydra-acp daemon listening on ${e.daemon.host}:${e.daemon.port}
|
|
195
195
|
`);let r=1e4,o=!1,i=async()=>{o&&(process.stderr.write(`Second signal received; exiting immediately.
|
|
196
196
|
`),process.exit(1)),o=!0,process.stdout.write(`Shutting down...
|
|
197
197
|
`);let a=setTimeout(()=>{process.stderr.write(`Graceful shutdown did not complete within ${r}ms; forcing exit.
|
|
198
198
|
`),process.exit(1)},r);a.unref();try{await n.shutdown()}catch(d){process.stderr.write(`shutdown failed: ${d instanceof Error?d.message:String(d)}
|
|
199
|
-
`)}clearTimeout(a),process.exit(0)};process.on("SIGINT",()=>{i()}),process.on("SIGTERM",()=>{i()}),process.on("SIGHUP",()=>{})}
|
|
199
|
+
`)}clearTimeout(a),process.exit(0)};process.on("SIGINT",()=>{i()}),process.on("SIGTERM",()=>{i()}),process.on("SIGHUP",()=>{})}my().catch(s=>{process.stderr.write(`hydra-acp-daemon: ${s instanceof Error?s.message:String(s)}
|
|
200
200
|
`),process.exit(1)});
|