@hydra-acp/cli 0.1.196 → 0.1.197

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/cli.js +433 -428
  2. package/dist/daemon.js +1 -1
  3. package/package.json +1 -1
package/dist/daemon.js CHANGED
@@ -195,7 +195,7 @@ ${A}`)}await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),th
195
195
  `);let R=C;typeof R.recordedAt=="number"&&A.add(String(R.recordedAt))}for(;v.length>0;){let C=v.splice(0,v.length);for(let R of C){let T=R,_=typeof T.recordedAt=="number"?String(T.recordedAt):"";_&&A.has(_)||f.raw.write(JSON.stringify(R)+`
196
196
  `)}}return b=!0,k||f.raw.end(),f});function i(l,f,m){let h=typeof l=="string"?l.trim():"";if(h.length===0)return null;let p;try{p=JSON.parse(h)}catch{return console.debug("events endpoint: skipping malformed JSONL line"),null}if(!p||typeof p!="object"||Array.isArray(p))return console.debug("events endpoint: skipping non-object JSONL line"),null;let g=p;if(typeof g.recordedAt!="number"||m!==void 0&&g.recordedAt<m||typeof g.params!="object"||g.params===null||Array.isArray(g.params))return null;let w=g.params;if(typeof w.update!="object"||w.update===null||Array.isArray(w.update))return null;let k=w.update.sessionUpdate;return typeof k!="string"||!f.has(k)?null:{recordedAt:g.recordedAt,entry:p}}function a(l,f,m){let p=f.params.update,g={sessionId:l,ts:new Date(f.recordedAt).toISOString(),kind:m,update:p};return p.messageId!==void 0&&p.messageId!==null&&(g.messageId=p.messageId),g}async function*d(l,f,m,h){for await(let p of f){let g=i(p,m,h);if(g){let w=g.entry.params.update.sessionUpdate;yield{ts:g.recordedAt,row:a(l,g.entry,w)}}}}async function c(l,f,m,h){let p=qo.createInterface({input:Wo.createReadStream(f),crlfDelay:1/0}),g=d(l,p,m,h),w=await g.next(),y=w.done?null:w.value;return{sessionId:l,rl:p,gen:g,current:y,exhausted:y===null}}async function u(l){let f=await l.gen.next();f.done?(l.exhausted=!0,l.current=null):l.current=f.value}s.get("/v1/sessions/events",async(l,f)=>{let m=l.query,h=m.kinds;if(!h||h.trim().length===0)return f.code(400).send({error:"kinds parameter is required"}),f;let p=h.split(",").map(I=>I.trim());if(p.length===0)return f.code(400).send({error:"kinds parameter is required"}),f;for(let I of p)if(!Js.has(I))return f.code(400).send({error:`kind "${I}" is not queryable; allowed kinds: ${[...Js].join(", ")}`}),f;let g=new Set(p),w;if(m.since!==void 0&&m.since.trim().length>0){let I=new Date(m.since);if(isNaN(I.getTime()))return f.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),f;w=I.getTime()}let y=await e.list({includeNonInteractive:!0}),k=w!==void 0?y.filter(I=>new Date(I.updatedAt).getTime()>=w):y;f.raw.setHeader("content-type","application/x-ndjson"),f.raw.statusCode=200;let b=[];for(let I of k)try{let v=x.historyFile(I.sessionId),A=await c(I.sessionId,v,g,w);A.exhausted||b.push(A)}catch(v){if(v.code==="ENOENT")continue;throw v}l.raw.on("close",()=>{for(let I of b)try{I.rl.close()}catch{}f.raw.writableEnded||f.raw.end()});try{for(;b.length>0;){let I=-1,v=1/0;for(let C=0;C<b.length;C++){let R=b[C];R.current!==null&&R.current.ts<v&&(v=R.current.ts,I=C)}if(I===-1)break;let A=b[I];if(f.raw.write(JSON.stringify(A.current.row)+`
197
197
  `),await u(A),A.exhausted){try{A.rl.close()}catch{}b.splice(I,1)}}}catch(I){for(let v of b)try{v.rl.close()}catch{}throw I}return f.raw.end(),f}),s.get("/v1/sessions/:id/events",async(l,f)=>{let m=l.params.id,h=l.query,p=await e.resolveCanonicalId(m)??m;if(!e.get(p)&&!await e.hasRecord(p))return f.code(404).send({error:"session not found"}),f;let w=h.kinds;if(!w||w.trim().length===0)return f.code(400).send({error:"kinds parameter is required"}),f;let y=w.split(",").map(C=>C.trim());if(y.length===0)return f.code(400).send({error:"kinds parameter is required"}),f;for(let C of y)if(!Js.has(C))return f.code(400).send({error:`kind "${C}" is not queryable; allowed kinds: ${[...Js].join(", ")}`}),f;let k=new Set(y),b;if(h.since!==void 0&&h.since.trim().length>0){let C=new Date(h.since);if(isNaN(C.getTime()))return f.code(400).send({error:"since is not a valid ISO-8601 timestamp"}),f;b=C.getTime()}let I=x.historyFile(p),v=Wo.createReadStream(I),A=qo.createInterface({input:v,crlfDelay:1/0});f.raw.setHeader("content-type","application/x-ndjson"),f.raw.statusCode=200;try{for await(let C of A){let R=typeof C=="string"?C.trim():"";if(R.length===0)continue;let T;try{T=JSON.parse(R)}catch{console.debug("events endpoint: skipping malformed JSONL line in %s",I);continue}if(!T||typeof T!="object"||Array.isArray(T)){console.debug("events endpoint: skipping non-object JSONL line in %s",I);continue}let _=T;if(typeof _.recordedAt!="number"||typeof _.params!="object"||_.params===null||Array.isArray(_.params))continue;let U=_.params;if(typeof U.update!="object"||U.update===null||Array.isArray(U.update))continue;let J=U.update,M=J.sessionUpdate;if(typeof M!="string"||!k.has(M)||b!==void 0&&_.recordedAt<b)continue;let W={ts:new Date(_.recordedAt).toISOString(),kind:M,update:J};J.messageId!==void 0&&J.messageId!==null&&(W.messageId=J.messageId),f.raw.write(JSON.stringify(W)+`
198
- `)}}catch(C){if(C.code==="ENOENT")return f.raw.end(),f;throw C}return f.raw.end(),f}),s.post("/v1/sessions/:id/prompt/:messageId/notify",async(l,f)=>{let m=l.params,h=m.id,p=await e.resolveCanonicalId(h)??h,g=m.messageId,w=l.body,y=typeof w?.callbackUrl=="string"?w.callbackUrl:"",k=typeof w?.secret=="string"?w.secret:"";if(!g||!y||!k){f.code(400).send({error:"messageId, callbackUrl, and secret are all required"});return}let b;try{b=new URL(y)}catch{f.code(400).send({error:"callbackUrl must be a valid absolute URL"});return}if(b.protocol!=="https:"&&b.protocol!=="http:"){f.code(400).send({error:"callbackUrl must be http or https"});return}let I=e.get(p);if(!I){f.code(404).send({error:"session not found or not warm"});return}let v=I.registerTurnNotify(g,y,k);if(v.alreadyTerminal){f.code(200).send({status:"already_terminal",stopReason:v.stopReason});return}f.code(202).send({status:"registered"})}),s.get("/v1/sessions/:id/attention",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);return!p&&!await e.hasRecord(h)?(f.code(404).send({error:"session not found"}),f):p?{flags:p.listAttentionFlags()}:{flags:(await e.store.read(h))?.attentionFlags??[]}}),s.get("/v1/sessions/attention",async(l,f)=>{let m=l.query;if(!m.source||m.source.trim().length===0)return f.code(400).send({error:"source query parameter is required"}),f;let h=await e.list({includeNonInteractive:!0}),p=[];for(let g of h){let w=e.get(g.sessionId),y;w?y=w.listAttentionFlags():y=(await e.store.read(g.sessionId))?.attentionFlags??[];for(let k of y)k.source===m.source&&p.push({...k,sessionId:g.sessionId})}return{flags:p}}),s.post("/v1/sessions/:id/attention/clear",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,g=l.body??{},w=typeof g.source=="string"?g.source:"",y=typeof g.reason=="string"?g.reason:"";if((w.length>0||y.length>0)&&!(w.length>0&&y.length>0)){f.code(400).send({error:"both source and reason are required to clear a specific flag, or omit both to clear all"});return}w.length===0&&y.length;let k=e.get(h);if(k){if(w.length>0&&y.length>0)k.clearAttentionFlag(w,y);else{let C=Array.from(k.listAttentionFlags()).map(R=>`${R.source}::${R.reason}`);for(let R of C)k.clearAttentionFlag(R.split("::")[0],R.split("::").slice(1).join("::"))}f.code(204).send();return}if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}let b=e.store,I=await b.read(h);if(!I){f.code(404).send({error:"session not found"});return}let v=I.attentionFlags??[],A;if(w.length>0&&y.length>0){let C=`${w}::${y}`;A=v.filter(R=>`${R.source}::${R.reason}`!==C)}else A=[];if(A.length===v.length&&A.every((C,R)=>C.source===v[R].source&&C.reason===v[R].reason)){f.code(204).send();return}await b.write({...I,attentionFlags:A}),f.code(204).send()})}function Bc(s,e,t,n={}){s.get("/v1/agents",async()=>Nt(e)),s.get("/v1/registry",async()=>e.load()),s.post("/v1/registry/refresh",async()=>{let r=await e.refresh();return{version:r.version,agentCount:r.agents.length}}),s.post("/v1/agents/:id/install",async(r,o)=>{let i=r.params.id,a=await e.getAgent(i);if(!a){o.code(404).send({error:`agent ${i} not found in registry`});return}if(a.distribution.uvx&&!a.distribution.npx&&!a.distribution.binary){o.send({agentId:a.id,version:a.version??"current",distribution:"uvx",installed:!1,message:"uvx agents resolve on first run; nothing to pre-install."});return}try{let d=await Ee(a,[],{npmRegistry:n.npmRegistry}),c=a.distribution.npx?"npx":a.distribution.binary?"binary":"unknown";o.send({agentId:a.id,version:d.version,distribution:c,installed:!0,command:d.command})}catch(d){o.code(500).send({error:d.message})}}),s.post("/v1/agents/:id/sync",async(r,o)=>{let i=r.params.id;try{let{synced:a,skipped:d}=await t.syncFromAgent(i);return{synced:a.map(c=>({sessionId:c.sessionId,upstreamSessionId:c.upstreamSessionId,agentId:c.agentId,cwd:c.cwd,title:c.title,updatedAt:c.updatedAt})),skipped:d}}catch(a){let d=a;if(d.code===E.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}G();function Wc(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:x.home(),driftedKeys:n()}))}import*as Vc from"os";G();Ne();var Nn=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,Gs=class s{data;constructor(e){this.data=e}static async load(){let e=await ie(x.peers());return new s(Bh(e))}get(e){return this.data.entries[e]}async set(e){this.data.entries[e.name]=e,await qc(this.data)}async delete(e){return e in this.data.entries?(delete this.data.entries[e],await qc(this.data),!0):!1}list(){return Object.values(this.data.entries).map(({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})=>({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})).sort((e,t)=>e.addedAt.localeCompare(t.addedAt))}};function Bh(s){if(!s||typeof s!="object")return{version:1,entries:{}};let e=s,t=e.entries&&typeof e.entries=="object"?e.entries:{},n={};for(let[r,o]of Object.entries(t)){if(!o||typeof o!="object")continue;let i=o;if(typeof i.name!="string"||typeof i.host!="string"||typeof i.port!="number"||typeof i.token!="string"||typeof i.expiresAt!="string"||typeof i.addedAt!="string")continue;let a={name:i.name,host:i.host,port:i.port,token:i.token,expiresAt:i.expiresAt,addedAt:i.addedAt};typeof i.label=="string"&&(a.label=i.label),typeof i.pinnedFingerprint=="string"&&(a.pinnedFingerprint=i.pinnedFingerprint),typeof i.pinnedAt=="string"&&(a.pinnedAt=i.pinnedAt),n[r]=a}return{version:1,entries:n}}async function qc(s){await fe(x.peers(),s,{mode:384})}var Wh=3600*24*365,Ge=class extends Error{status;constructor(e,t){super(e),this.name="PeerLoginError",this.status=t}};function Ks(s,e){return`${ke(s)?"http":"https"}://${s}:${e}`}async function zc(s){let e=s.fetchImpl??fetch,t=`${s.host}:${s.port}`,n=Ks(s.host,s.port),r;try{r=await e(`${n}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:s.password,label:s.label,ttlSec:s.ttlSec??Wh})})}catch(i){throw new Ge(`Could not reach ${t}: ${i.message}`,502)}if(r.status===401)throw new Ge(`Wrong password for ${t}.`,401);if(r.status===403)throw new Ge(`No password is configured on ${t}. Run \`hydra-acp auth password\` on that daemon first.`,502);if(r.status===429)throw new Ge(`Too many failed login attempts on ${t}; try again later.`,429);if(!r.ok)throw new Ge(`Login to ${t} failed: HTTP ${r.status}`,502);let o=await r.json();if(!o.session_token||!o.expires_at)throw new Ge(`Login to ${t} returned a malformed response.`,502);return{token:o.session_token,expiresAt:o.expires_at}}async function zo(s){let e=s.fetchImpl??fetch,t=Ks(s.host,s.port);try{await e(`${t}/v1/auth/logout`,{method:"POST",headers:{Authorization:`Bearer ${s.token}`,"Content-Type":"application/json"},body:JSON.stringify({})})}catch{}}function Gc(s){return{machine:ht(),hydraVersion:de,startedAt:s,os:{platform:process.platform,release:Vc.release(),arch:process.arch},node:process.version}}async function Qs(s){let e=s.fetchImpl??fetch,t;try{t=await e(`${Ks(s.host,s.port)}/v1/system`,{headers:{Authorization:`Bearer ${s.token}`},signal:s.signal})}catch(n){return{kind:"error",message:n.message}}if(t.status===401||t.status===403)return{kind:"unauthorized"};if(t.status===404)return{kind:"unsupported"};if(!t.ok)return{kind:"error",message:`HTTP ${t.status}`};try{let n=await t.json();return typeof n?.machine=="string"?{kind:"ok",system:n}:{kind:"ok"}}catch{return{kind:"ok"}}}function Jc(s){return s!==void 0&&s.length<=64&&Nn.test(s)}function Kc(s,e){if(Jc(s))return s;if(/^[\d.]+$/.test(e)||e.includes(":"))return;let t=e.split(".")[0];return Jc(t)?t:void 0}function Qc(s,e){s.get("/v1/system",async()=>Gc(e))}var qh=/^[A-Za-z0-9._-]+$/;function Ys(s,e,t){let n=e==="extension"?"extensions":"transformers",r=`/v1/${n}`;s.get(r,async()=>({[n]:t.list()})),s.get(`${r}/:name`,async(o,i)=>{let a=o.params.name,d=t.get(a);if(!d){i.code(404).send({error:`unknown ${e}: ${a}`});return}return d}),s.post(r,async(o,i)=>{let a=o.body??{},d=zh(a);if("error"in d){i.code(400).send({error:d.error});return}try{let c=t.register(d.config);i.code(201).send(c)}catch(c){Dn(i,c)}}),s.delete(`${r}/:name`,async(o,i)=>{let a=o.params.name;try{await t.unregister(a),i.code(204).send()}catch(d){Dn(i,d)}}),s.post(`${r}/:name/start`,async(o,i)=>{let a=o.params.name;try{let d=await t.startByName(a);i.code(200).send(d)}catch(d){Dn(i,d)}}),s.post(`${r}/:name/stop`,async(o,i)=>{let a=o.params.name;try{let d=await t.stopByName(a);i.code(200).send(d)}catch(d){Dn(i,d)}}),s.post(`${r}/:name/restart`,async(o,i)=>{let a=o.params.name;try{let d=await t.restartByName(a);i.code(200).send(d)}catch(d){Dn(i,d)}})}function Dn(s,e){let t=e.code,n=e.message??"unknown error";if(t==="NOT_FOUND"){s.code(404).send({error:n});return}if(t==="CONFLICT"){s.code(409).send({error:n});return}s.code(500).send({error:n})}function zh(s){let e=s.name;if(typeof e!="string"||!qh.test(e))return{error:"name must match [A-Za-z0-9._-]+"};let t=s.command;if(t!==void 0&&(!Array.isArray(t)||t.some(i=>typeof i!="string")))return{error:"command must be string[]"};let n=s.args;if(n!==void 0&&(!Array.isArray(n)||n.some(i=>typeof i!="string")))return{error:"args must be string[]"};let r=s.env;if(r!==void 0&&(typeof r!="object"||r===null||Array.isArray(r)))return{error:"env must be an object of string\u2192string"};if(r&&Object.values(r).some(i=>typeof i!="string"))return{error:"env values must be strings"};let o=s.enabled;return o!==void 0&&typeof o!="boolean"?{error:"enabled must be a boolean"}:{config:{name:e,command:t??[],args:n??[],env:r??{},enabled:o===void 0?!0:o}}}function Yc(s,e){Ys(s,"extension",e)}function Xc(s,e){Ys(s,"transformer",e)}function Zc(s,e){s.get("/v1/config",async()=>e())}import{z as ft}from"zod";G();import*as Xt from"fs/promises";import*as eu from"path";import{randomBytes as DA,scrypt as Jh,timingSafeEqual as Vh}from"crypto";import{promisify as Gh}from"util";var Kh=Gh(Jh);function tu(){return eu.join(x.home(),"password-hash")}var Qh=128*1024*1024;async function nu(){try{return(await Xt.readFile(tu(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function su(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await Xt.readFile(tu(),"utf8")).trim()}catch(c){if(c.code==="ENOENT")return!1;throw c}let t=e.split("$");if(t.length!==6||t[0]!=="scrypt")return!1;let n=parseInt(t[1],10),r=parseInt(t[2],10),o=parseInt(t[3],10);if(!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(o))return!1;let i=Buffer.from(t[4],"hex"),a=Buffer.from(t[5],"hex");if(i.length===0||a.length===0)return!1;let d=await Kh(s,i,a.length,{N:n,r,p:o,maxmem:Qh});return d.length!==a.length?!1:Vh(d,a)}var Yh=ft.object({password:ft.string().min(1),label:ft.string().min(1).max(256).optional(),ttlSec:ft.number().int().positive().optional()}),Xh=ft.object({id:ft.string().optional()}).optional(),Zh=ft.object({token:ft.string().min(32)});function ru(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=ey(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=Yh.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await nu())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await su(o.password))return e.rateLimiter.recordFailure(r),n.code(401).send({error:"Invalid password"});e.rateLimiter.recordSuccess(r);let a=await e.store.issue({label:o.label,ttlSec:o.ttlSec});return n.code(200).send({session_token:a.token,id:a.id,expires_at:a.expiresAt})}),s.post("/v1/auth/logout",async(t,n)=>{let r;try{r=Xh.parse(t.body??void 0)}catch{return n.code(400).send({error:"Invalid request body"})}let o=r?.id??t.authIdentity;if(!o||o==="service")return n.code(200).send({revoked:!1});let i=await e.store.revoke(o);return n.code(200).send({revoked:i})}),s.get("/v1/auth/verify",async(t,n)=>n.code(200).send({ok:!0})),s.get("/v1/auth/sessions",async(t,n)=>n.code(200).send({sessions:e.store.list()})),s.delete("/v1/auth/sessions",async(t,n)=>{let r=await e.store.revokeAll();return n.code(200).send({revoked:r})}),s.delete("/v1/auth/sessions/:id",async(t,n)=>{let r=t.params.id;return await e.store.revoke(r)?n.code(204).send():n.code(404).send({error:"Not found"})}),s.post("/v1/auth/rotate-token",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=Zh.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}return e.staticTokenValidator.rotate(r.token),n.code(200).send({rotated:!0})})}function ey(s){return s.ip||"unknown"}import{z as pt}from"zod";Hn();var fy=pt.object({name:pt.string().min(1).max(64).regex(Nn).optional(),host:pt.string().min(1),port:pt.number().int().positive().optional(),password:pt.string().min(1),label:pt.string().min(1).max(256).optional(),ttlSec:pt.number().int().positive().optional(),pinnedFingerprint:pt.string().min(1).optional()});function pu(s,e){s.post("/v1/remotes",async(t,n)=>{let r;try{r=fy.parse(t.body)}catch{return n.code(400).send({error:`Invalid request body (name must match ${Nn} and the rest is a normal login request)`})}let o=r.port??Mt;r.pinnedFingerprint&&jn(r.host,o,r.pinnedFingerprint);let i;try{i=await zc({host:r.host,port:o,password:r.password,label:r.label,ttlSec:r.ttlSec})}catch(f){if(f instanceof Ge)return n.code(f.status).send({error:f.message});throw f}let a=await Qs({host:r.host,port:o,token:i.token}),d=a.kind==="ok"?a.system:void 0,c=r.name;if(c===void 0){c=Kc(d?.machine,r.host);let f=c!==void 0?e.store.get(c):void 0,m=f!==void 0&&(f.host!==r.host||f.port!==o);if(c===void 0||m){await zo({host:r.host,port:o,token:i.token});let h=c===void 0?`Couldn't derive a remote name for ${r.host}`:`A remote named ${c} already points at ${f.host}:${f.port}`;return n.code(c===void 0?400:409).send({error:`${h}. Pass a name: hydra-acp remote add <name> ${r.host}`})}}let u=new Date().toISOString(),l={name:c,host:r.host,port:o,token:i.token,expiresAt:i.expiresAt,addedAt:u,...r.label!==void 0?{label:r.label}:{},...r.pinnedFingerprint!==void 0?{pinnedFingerprint:r.pinnedFingerprint,pinnedAt:u}:{}};return await e.store.set(l),e.health?.markOk(l.name,d),n.code(201).send({name:l.name,host:l.host,port:l.port,expiresAt:l.expiresAt,label:l.label,addedAt:l.addedAt,pinnedFingerprint:l.pinnedFingerprint,status:e.health?.get(l.name)?.status??"unknown"})}),s.get("/v1/remotes",async(t,n)=>{let r=e.store.list().map(o=>{let i=e.health?.get(o.name);return{...o,status:i?.status??"unknown",...i?.checkedAt?{lastCheckedAt:i.checkedAt}:{},...i?.system?{system:i.system}:{}}});return n.code(200).send({remotes:r})}),s.get("/v1/remotes/:name/agents",async(t,n)=>{let r=e.store.get(t.params.name);if(!r)return n.code(404).send({error:"Not found"});let i=`${ke(r.host)?"http":"https"}://${r.host}:${r.port}`,a={Authorization:`Bearer ${r.token}`};try{let[d,c]=await Promise.all([fetch(`${i}/v1/agents`,{headers:a}),fetch(`${i}/v1/config`,{headers:a}).catch(()=>null)]);if(!d.ok)return n.code(d.status).header("content-type","application/json").send(await d.text());let u=await d.json(),l={};if(c?.ok){let f=await c.json();l={defaultAgent:f.defaultAgent,sessionDefaults:f.sessionDefaults}}return n.code(200).send({...u,...l})}catch(d){return n.code(502).send({error:`Could not reach remote "${r.name}": ${d.message}`})}}),s.delete("/v1/remotes/:name",async(t,n)=>{let r=t.params.name,o=e.store.get(r);return o?(await zo({host:o.host,port:o.port,token:o.token}),await e.store.delete(r),e.health?.forget(r),e.store.list().some(a=>a.host===o.host&&a.port===o.port)||Vo(o.host,o.port),n.code(204).send()):n.code(404).send({error:"Not found"})})}function Zs(s){let e=[],t=[],n=!1,r=o=>{if(!n){n=!0;for(let i of t)i(o)}};return s.on("message",(o,i)=>{if(i)return;let a=o.toString("utf8");try{let d=JSON.parse(a);for(let c of e)c(d)}catch(d){for(let c of e)c({jsonrpc:"2.0",id:null,error:{code:E.ParseError,message:`Failed to parse WS frame: ${d.message}`}})}}),s.on("close",()=>r()),s.on("error",o=>r(o)),{async send(o){if(n)throw new Error("ws is closed");let i=JSON.stringify(o);await new Promise((a,d)=>{s.send(i,c=>{if(c){d(c);return}a()})})},onMessage(o){e.push(o)},onClose(o){t.push(o)},async close(){n||(await new Promise(o=>{let i=!1,a=()=>{i||(i=!0,clearTimeout(d),o())},d=setTimeout(a,5e3);s.once("close",a);try{s.close()}catch{a()}}),r())}}}Hn();import{WebSocket as py}from"ws";var gy=1e4,Xo=class extends Error{url;elapsedMs;constructor(e,t){super(`hydra-acp: websocket connect to ${e} timed out after ${t}ms`),this.name="WsConnectTimeoutError",this.url=e,this.elapsedMs=t}};async function gu(s,e,t=gy){let n={};try{let r=new URL(s);if(r.protocol==="wss:"){let o=Yo(r.hostname);o.rejectUnauthorized!==void 0&&(n.rejectUnauthorized=o.rejectUnauthorized),o.autoSelectFamily!==void 0&&(n.autoSelectFamily=o.autoSelectFamily),o.checkServerIdentity!==void 0&&(n.checkServerIdentity=o.checkServerIdentity)}}catch{}return new Promise((r,o)=>{let i=new py(s,e,n),a=Date.now(),d=setTimeout(()=>{i.off("open",c),i.off("error",u),i.on("error",()=>{});try{i.terminate()}catch{}o(new Xo(s,Date.now()-a))},t),c=()=>{clearTimeout(d),i.off("error",u),r(i)},u=l=>{clearTimeout(d),i.off("open",c),o(l)};i.once("open",c),i.once("error",u)})}var my=new Set(["session/attach","session/detach","session/prompt","session/cancel","session/close","session/delete","hydra-acp/session/delete","session/set_model","session/set_mode","session/set_config_option","_session/steering","hydra-acp/prompt/cancel","hydra-acp/prompt/update","hydra-acp/prompt/amend","hydra-acp/session/tool_content","hydra-acp/session/force_cancel"]);function hy(s){return my.has(s)}function hu(s,e,t,n){let r=[],o=a=>{for(let d of r)d(a)},i=(a,d)=>{e.handleLocalMessage(a,d,{connection:t.connection,clientId:n}).then(c=>c?s.send(c):void 0).catch(()=>{})};return s.onMessage(a=>{if("method"in a&&hy(a.method)){let d=a.params,c=typeof d?.sessionId=="string"?d.sessionId:void 0;if(c){if(dt(c)){i(a,c);return}if(a.method==="session/attach"){let u="id"in a;e.resolveLocalMiss(c).then(l=>{if(l.ok){i(a,l.foreignId);return}if(l.ambiguous&&u){s.send(Ln(a.id,E.SessionNotFound,`Session "${c}" exists on more than one remote (${l.ambiguous.join(", ")}). Address it as "<remote>:${c}".`));return}o(a)});return}}}o(a)}),{send:a=>s.send(a),onMessage:a=>r.push(a),onClose:a=>s.onClose(a),close:()=>s.close()}}var er=class{constructor(e,t=wy,n){this.store=e;this.dial=t;this.localMiss=n}store;dial;localMiss;attachments=new Map;async resolveLocalMiss(e){if(!this.localMiss)return{ok:!1};if(await this.localMiss.resolvesLocally(e))return{ok:!1};let t=this.localMiss.cache.findByLocalId(e);return t.length===0?{ok:!1}:t.length>1?{ok:!1,ambiguous:t.map(n=>n.name)}:{ok:!0,foreignId:qe(t[0])}}async handleLocalMessage(e,t,n){let r="id"in e,o=r?e.id:void 0,i=dt(t);if(!i)return r?Ln(o,E.SessionNotFound,`not a federated session id: ${t}`):void 0;let a=mu(n.clientId,t),d={...e.params,sessionId:i.localId};if(e.method==="session/attach"){let u=this.store.get(i.name);if(!u)return r?Ln(o,E.SessionNotFound,`No remote named "${i.name}". Run \`hydra remote add\` first.`):void 0;let l=this.attachments.get(a);l&&(this.attachments.delete(a),l.peerConnection.close().catch(()=>{}));let f;try{f=await this.dial(u)}catch(g){return r?Ln(o,E.InternalError,`Could not reach remote "${i.name}": ${g.message}`):void 0}let m={peerConnection:f,localId:i.localId,target:n};this.wireAttachment(i.name,m);let h;try{h=await f.request("session/attach",d)}catch(g){return f.close().catch(()=>{}),r?Zo(o,g):void 0}this.attachments.set(a,m);let p=h&&typeof h.sessionId=="string"?{...h,sessionId:t}:h;return r?{jsonrpc:"2.0",id:o,result:p}:void 0}let c=this.attachments.get(a);if(!c)return r?Ln(o,E.SessionNotFound,`"${t}" is not attached through this daemon.`):void 0;if(e.method==="session/detach"){let u,l;try{u=await c.peerConnection.request("session/detach",d)}catch(f){l=f}return this.attachments.delete(a),c.peerConnection.close().catch(()=>{}),l?r?Zo(o,l):void 0:r?{jsonrpc:"2.0",id:o,result:u??{}}:void 0}if(r)try{let u=await c.peerConnection.request(e.method,d);return{jsonrpc:"2.0",id:o,result:u}}catch(u){return Zo(o,u)}await c.peerConnection.notify(e.method,d).catch(()=>{})}detachClient(e){for(let[t,n]of[...this.attachments.entries()])n.target.clientId===e&&(this.attachments.delete(t),n.peerConnection.request("session/detach",{sessionId:n.localId}).catch(()=>{}),n.peerConnection.close().catch(()=>{}))}wireAttachment(e,t){let{peerConnection:n,localId:r,target:o}=t,i=qe({name:e,localId:r}),a=()=>{this.attachments.delete(mu(o.clientId,i))};n.onAnyNotification((d,c)=>{let u=d;!u||u.sessionId!==r||(c==="hydra-acp/session/closed"&&a(),o.connection.notify(c,{...u,sessionId:i}).catch(()=>{}))}),n.onRequest("hydra-acp/session/request_permission",async d=>{let c=d;if(!c||c.sessionId!==r)throw{code:E.MethodNotFound,message:"unexpected sessionId"};return o.connection.request("hydra-acp/session/request_permission",{...c,sessionId:i})}),n.onClose(()=>{a(),o.connection.notify("hydra-acp/session/closed",{sessionId:i}).catch(()=>{})})}};function mu(s,e){return`${s} ${e}`}function Ln(s,e,t){return{jsonrpc:"2.0",id:s,error:{code:e,message:t}}}function Zo(s,e){let t=e,n=typeof t?.code=="number"?t.code:E.InternalError,r=typeof t?.message=="string"?t.message:String(e??"forward failed");return{jsonrpc:"2.0",id:s,error:{code:n,message:r,...t?.data!==void 0?{data:t.data}:{}}}}var yy=1e4;async function wy(s){let t=`${ke(s.host)?"ws":"wss"}://${s.host}:${s.port}/acp`,n=await gu(t,["acp.v1",`hydra-acp-token.${s.token}`],yy);return new Be(Zs(n))}var ky=3e4,vy=5e3,tr=class{constructor(e,t={}){this.store=e;this.opts=t}store;opts;snapshots=new Map;timer;start(){this.timer||(this.checkAll(),this.timer=setInterval(()=>{this.checkAll()},this.opts.intervalMs??ky),this.timer.unref?.())}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}get(e){return this.snapshots.get(e)}markOk(e,t){this.snapshots.set(e,{status:"ok",checkedAt:new Date().toISOString(),...t?{system:t}:{}})}forget(e){this.snapshots.delete(e)}async checkAll(){let e=this.opts.fetchImpl??fetch;await Promise.allSettled(this.store.list().map(async t=>{let n=this.store.get(t.name);if(!n)return;let r=new AbortController,o=setTimeout(()=>r.abort(),vy);try{let i=await Qs({host:n.host,port:n.port,token:n.token,fetchImpl:e,signal:r.signal});if(i.kind==="ok"){this.snapshots.set(t.name,{status:"ok",checkedAt:new Date().toISOString(),...i.system?{system:i.system}:{}});return}if(i.kind==="unauthorized"){this.snapshots.set(t.name,{status:"unauthorized",checkedAt:new Date().toISOString()});return}if(i.kind==="error")throw new Error(i.message);let d=`${ke(n.host)?"http":"https"}://${n.host}:${n.port}/v1/auth/verify`,c=await e(d,{headers:{Authorization:`Bearer ${n.token}`},signal:r.signal});this.snapshots.set(t.name,{status:c.ok?"ok":"unauthorized",checkedAt:new Date().toISOString()})}catch(i){this.snapshots.set(t.name,{status:"unreachable",checkedAt:new Date().toISOString(),error:i.message})}finally{clearTimeout(o)}}))}};Hn();import{z as yu}from"zod";var by=yu.object({sessionLabel:yu.string().min(1).max(256)});function wu(s,e){s.post("/v1/process-tokens",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=by.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}let o=e.processRegistry.mint(r.sessionLabel,"script");return n.code(201).send({token:o})}),s.delete("/v1/process-tokens/:sessionLabel",async(t,n)=>t.authIdentity!=="service"?n.code(403).send({error:"Requires the service token"}):(e.processRegistry.revoke(t.params.sessionLabel),n.code(204).send()))}import{nanoid as ei}from"nanoid";import{randomBytes as Iu}from"crypto";import*as Au from"os";import*as Cu from"path";var Sy=200;function Iy(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e[ce];if(!t||typeof t!="object"||Array.isArray(t))return;let n=t.sentBy;if(!n||typeof n!="object"||Array.isArray(n))return;let r=n,o={};if(typeof r.sessionId=="string"&&r.sessionId.length>0&&(o.sessionId=r.sessionId),typeof r.label=="string"&&r.label.length>0&&(o.label=r.label.slice(0,Sy)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function ku(s,e,t){let n=Iy(s);if(!n)return;let r={};if(n.label!==void 0&&(r.fromLabel=n.label),n.awaiting===!0&&(r.awaiting=!0),n.sessionId!==void 0){let o=await e.resolveCanonicalId(n.sessionId)??n.sessionId,i=await e.getOne(o);if(i){r.fromSession=o,i.title&&(r.fromSessionTitle=i.title);let a=e.get(o)?.currentPromptDepth;r.depth=(a??0)+1}else t?.(n.sessionId)}if(!(r.fromSession===void 0&&r.fromLabel===void 0))return r}var Un=new Map;function vu(s,e){let t=Un.get(s);t||(t=new Set,Un.set(s,t)),t.add(e);let n=!1;return()=>{if(n)return;n=!0;let r=Un.get(s);r&&(r.delete(e),r.size===0&&Un.delete(s))}}function bu(s,e){if(s===e)return!0;let t=new Set,n=[e];for(;n.length>0;){let r=n.pop();if(t.has(r))continue;t.add(r);let o=Un.get(r);if(o){if(o.has(s))return!0;for(let i of o)n.push(i)}}return!1}function N(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function Ey(s){if(!s||typeof s!="object")return 512;let n=s.params?.update;if(!n)return 512;let r=512,o=n.content;if(typeof o=="string")r+=o.length;else if(o&&typeof o=="object"){let a=o;typeof a.text=="string"&&(r+=a.text.length),typeof a.data=="string"&&(r+=a.data.length)}let i=n.toolCall;if(i&&(typeof i.rawInput=="string"?r+=i.rawInput.length:i.rawInput&&typeof i.rawInput=="object"&&(r+=256),typeof i.rawOutput=="string"?r+=i.rawOutput.length:i.rawOutput&&typeof i.rawOutput=="object"&&(r+=256),Array.isArray(i.content)))for(let a of i.content){if(!a||typeof a!="object")continue;let d=a;if(typeof d.text=="string"&&(r+=d.text.length),d.content&&typeof d.content=="object"){let c=d.content;typeof c.text=="string"&&(r+=c.text.length)}}return r}function Re(s,e,t){let n=s.get(e);if(!n)throw N(E.SessionNotFound,t??`session ${e} not found`);return n}async function Et(s,e){let t=Yt(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=Iu(32).toString("hex"),r=s.mcpTokenRegistry.reserve(n),o={name:"hydra-acp-recall",type:"http",url:`${s.getDaemonOrigin()}/mcp/hydra-acp-recall`,headers:[{name:"Authorization",value:`Bearer ${n}`}]});let a=[...t?.descriptors??[],...o!==void 0?[o]:[]],d=Bo({baselineMcpServers:void 0,stdinEnabled:!1,deps:s}),c;try{c=await s.manager.resurrect({...e,mcpServers:a,...d?{mintMcpServersForSwap:d}:{}})}catch(u){throw t!==void 0&&t.abandon(u instanceof Error?u:void 0),r!==void 0&&r.abandon(u instanceof Error?u:void 0),u}if(t!==void 0&&t.bindToSession(c),n!==void 0&&r!==void 0&&s.mcpTokenRegistry!==void 0){let u=n,l=s.mcpTokenRegistry;r.complete(c),c.onClose(()=>{l.unbind(u)})}return jy(c,s),xu(c.sessionId,s),c}function Ru(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=cc({headers:n.headers,url:n.url});if(!r||!await e.validator.validate(r)){t.close(4401,"Unauthorized");return}let o=e.processRegistry?.resolve(r),i=`hydra_client_${ei(12)}`,a=Zs(t),d={},c=e.foreignSessions?hu(a,e.foreignSessions,d,i):a,u=new Be(c);d.connection=u;let l={clientId:i,processIdentity:o,attached:new Map};u.onClose(()=>{for(let h of l.attached.values())e.manager.get(h.sessionId)?.detach(h.clientId);l.attached.clear(),e.foreignSessions?.detachClient(i)});let f=(h,p)=>{if(l.attached.get(h)?.readonly)throw N(E.PermissionDenied,`${p} not permitted on a read-only attachment`)};if(u.onRequest("initialize",async h=>{let p=Qi.parse(h??{});p.clientInfo?.name&&(l.clientInfo={name:p.clientInfo.name,...p.clientInfo.version!==void 0?{version:p.clientInfo.version}:{}});let g=p.clientInfo?.version;return g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g)),Dy()}),o&&e.extensionCommands){let h=e.extensionCommands;u.onRequest("hydra-acp/commands/register",async p=>{let g=p??{},w=Array.isArray(g.commands)?g.commands.map(y=>{if(!y||typeof y!="object")return;let k=y;if(typeof k.verb!="string")return;let b={verb:k.verb};return typeof k.argsHint=="string"&&(b.argsHint=k.argsHint),typeof k.description=="string"&&(b.description=k.description),b}).filter(y=>y!==void 0):[];return h.register(o.name,u,w),{ok:!0,registered:w.length}}),u.onClose(()=>{h.clear(o.name)})}if(o&&e.extensionMcp){let h=e.extensionMcp;u.onRequest("hydra-acp/mcp_tools/register",async g=>{let w=g??{},y=typeof w.instructions=="string"?w.instructions:void 0,k=Array.isArray(w.tools)?w.tools.map(b=>{if(!b||typeof b!="object")return;let I=b;if(typeof I.name!="string"||I.name.length===0||typeof I.description!="string"||I.inputSchema===null||typeof I.inputSchema!="object")return;let v={name:I.name,description:I.description,inputSchema:I.inputSchema};return I.outputSchema!==null&&typeof I.outputSchema=="object"&&(v.outputSchema=I.outputSchema),v}).filter(b=>b!==void 0):[];if(k.length===0)throw new Error("register_mcp_tools requires at least one tool");return h.register(o.name,u,y,k),{ok:!0,registered:k.length}});let p=g=>{let w=g??{};if(typeof w.sessionId!="string"||w.sessionId.length===0)throw N(E.InvalidParams,"sessionId is required");return w.sessionId};if(u.onRequest("hydra-acp/session/extension_state/get",async g=>{let w=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(!e.manager)throw N(E.InternalError,"manager not wired");return{value:await e.manager.getExtensionStateKey(w,o.name,y.key)??null}}),u.onRequest("hydra-acp/session/extension_state/list",async g=>{let w=p(g);if(!e.manager)throw N(E.InternalError,"manager not wired");return{state:await e.manager.getExtensionState(w,o.name)}}),u.onRequest("hydra-acp/session/extension_state/set",async g=>{let w=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(y.value===void 0)throw N(E.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw N(E.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(w,o.name,y.key,y.value)}catch(k){throw N(E.InvalidParams,k.message)}return{ok:!0}}),u.onRequest("hydra-acp/session/extension_state/delete",async g=>{let w=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(!e.manager)throw N(E.InternalError,"manager not wired");return await e.manager.deleteExtensionStateKey(w,o.name,y.key),{ok:!0}}),e.extensionMcpControls){let g=e.extensionMcpControls;u.onRequest("hydra-acp/mcp_tools/refresh_session",async w=>{let y=w??{};if(typeof y.sessionId!="string"||y.sessionId.length===0)throw N(E.InvalidParams,"refresh_session requires sessionId");return await g.notifyToolListChanged(y.sessionId,o.name),{ok:!0}})}u.onClose(()=>{h.clear(o.name)})}if(o?.kind==="transformer"){u.onRequest("hydra-acp/transformer/initialize",async p=>{let g=p??{},w=Array.isArray(g.intercepts)?g.intercepts.filter(y=>typeof y=="string"):[];if(e.transformers&&(e.transformers.registerConnection(o.name,u,w),e.manager?.defaultTransformers.includes(o.name))){let y=e.transformers.resolveChain([o.name])[0];if(y)for(let k of e.manager.liveSessions())k.addTransformer(y)}return{ack:!0}}),u.onClose(()=>{e.transformers?.deregisterConnection(o.name)}),u.onRequest("hydra-acp/message/emit",async p=>{let g=p??{},w=typeof g.sessionId=="string"?g.sessionId:void 0,y=typeof g.method=="string"?g.method:void 0,k=g.envelope,b=g.route;if(!w)throw N(-32602,"emit_message requires sessionId");if(!y&&b!=="client_broadcast")throw N(-32602,"emit_message requires method");let I=Re(e.manager,w),v=typeof g.respondsTo=="string"?g.respondsTo:void 0;if(v)return I.dischargeClaim(v,k),{ok:!0};if(b==="chain")return{ok:!0,response:await I.emitToChain(o.name,y,k)};if(b==="queue"){if(y!=="session/prompt")throw N(-32602,'route "queue" only supports method "session/prompt"');return{ok:!0,response:await I.emitToQueue(o.name,k)}}if(b==="daemon")return{ok:!0,response:await I.emitToChain(o.name,y,k)};if(b==="client_broadcast"){if(!k||typeof k!="object")throw N(-32602,"client_broadcast requires an envelope object");return I.broadcastClientUpdate(k),{ok:!0}}throw N(-32602,`unsupported route: ${JSON.stringify(b)}`)}),u.onRequest("hydra-acp/session/request_permission",async p=>{let g=p??{},w=typeof g.sessionId=="string"?g.sessionId:void 0;if(!w)throw N(-32602,"hydra-acp/session/request_permission requires sessionId");return Re(e.manager,w).requestPermissionFromClients(g)}),u.onRequest("hydra-acp/transformer/attach",async p=>$y(p,o.name,e)),u.onRequest("hydra-acp/child_session/spawn",async p=>{let g=p??{},w=typeof g.agentId=="string"?g.agentId:void 0,y=typeof g.cwd=="string"?g.cwd:void 0,k=typeof g.parentSessionId=="string"?g.parentSessionId:void 0,b=rt(g._meta??void 0),I=b.title,v=b.model,A=b.workspace;if(!y&&k){let W=e.manager.get(k);W&&(y=W.cwd)}if(!y)throw N(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let C=await on(y),R=w??C.agentId??e.defaultAgent,T=await e.registry?.getAgent(R),_=cn(C.configDefaults,T??{id:R})?.value,U=v??_?.model,J=typeof g.interactive=="boolean"?g.interactive:!1,M=await e.manager.create({agentId:R,cwd:y,parentSessionId:k,interactive:J,transformChain:[],title:I,model:U,configDefaults:_,...A!==void 0?{workspace:A}:{}});return{childSessionId:M.sessionId,...M.workspace!==void 0||M.workspaceError!==void 0?{_meta:{[ce]:{...M.workspace!==void 0?{workspaceInfo:M.workspace}:{},...M.workspaceError!==void 0?{workspaceError:M.workspaceError}:{}}}}:{}}}),u.onRequest("hydra-acp/session/fork",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.InvalidParams,"fork_session requires sessionId");let w=typeof g.forkAt=="string"?g.forkAt:void 0,y=typeof g.cwd=="string"?g.cwd:void 0,k=typeof g.agentId=="string"?g.agentId:void 0,b=typeof g.mode=="string"&&(g.mode==="verbatim"||g.mode==="synthesis")?g.mode:void 0,I=typeof g.model=="string"&&g.model.length>0?g.model:void 0,v=await e.manager.forkSession(g.sessionId,{...w!==void 0?{forkAt:w}:{},...y!==void 0?{cwd:y}:{},...k!==void 0?{agentId:k}:{},...b!==void 0?{mode:b}:{},...I!==void 0?{model:I}:{}}),A=e.manager.get(v.sessionId);if(!A){let T=await e.manager.loadFromDisk(v.sessionId);if(!T)throw N(E.InternalError,`fork ${v.sessionId} vanished before it could be attached`);A=await Et(e,{...T,onInstallProgress:nr(u)})}Zt(l,A,A.sessionId);let C=gt(u,A,l),{entries:R}=await A.attach(C,"full");l.attached.set(A.sessionId,{sessionId:A.sessionId,clientId:C.clientId,readonly:!1});for(let T of R){if(u.isClosed())break;await u.notify(T.method,Ue(Le(T.params,T.recordedAt),T.seq)).catch(()=>{})}return{...v,sessionId:A.sessionId}}),u.onRequest("session/fork",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.InvalidParams,"session/fork requires sessionId");let w=typeof g.cwd=="string"?g.cwd:void 0,y=await e.manager.forkSession(g.sessionId,{...w!==void 0?{cwd:w}:{},mode:"verbatim"}),k=e.manager.get(y.sessionId);if(!k){let v=await e.manager.loadFromDisk(y.sessionId);if(!v)throw N(E.InternalError,`fork ${y.sessionId} vanished before it could be attached`);k=await Et(e,{...v,onInstallProgress:nr(u)})}Zt(l,k,k.sessionId);let b=gt(u,k,l),{entries:I}=await k.attach(b,"full");l.attached.set(k.sessionId,{sessionId:k.sessionId,clientId:b.clientId,readonly:!1});for(let v of I){if(u.isClosed())break;await u.notify(v.method,Ue(Le(v.params,v.recordedAt),v.seq)).catch(()=>{})}return{sessionId:k.sessionId}});let h=async(p,g)=>{let w=p??{};if(typeof w.sessionId!="string")throw N(E.InvalidParams,`${g} requires sessionId`);let y=await e.manager.resolveCanonicalId(w.sessionId)??w.sessionId,k=e.manager.get(y);if(k)return await k.close({deleteRecord:!0,by:`session/delete ${l.clientId}`}),await e.manager.waitForDeletion(y),await e.manager.hasRecord(y)&&await e.manager.deleteRecord(y),{id:y,existed:!0};let b=await e.manager.deleteRecord(y);return{id:y,existed:b}};u.onRequest("session/delete",async p=>(await h(p,"session/delete"),{})),u.onRequest("session/close",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.InvalidParams,"session/close requires sessionId");f(g.sessionId,"session/close");let w=await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId,y=e.manager.get(w);if(y)return await y.close({deleteRecord:!1,by:`session/close ${l.clientId}`+(l.processIdentity?` (${l.processIdentity.name})`:"")}),{};if(await e.manager.hasRecord(w))return{};throw N(E.SessionNotFound,`session ${w} not found`)}),u.onRequest("hydra-acp/session/delete",async p=>{let{id:g,existed:w}=await h(p,"hydra-acp/session/delete");if(!w)throw N(E.SessionNotFound,`session ${g} not found`);return{deleted:!0,sessionId:g}}),u.onRequest("hydra-acp/child_session/await",async p=>{let g=p??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0,y=g.until==="idle"?"idle":"turn_complete",k=typeof g.timeoutMs=="number"?Math.min(g.timeoutMs,18e5):3e5;if(!w)throw N(-32602,"await_child requires childSessionId");let b=Re(e.manager,w,`child session ${w} not found`);return new Promise(I=>{let C=[],R=[],T=0,_=!1,U,J,M=!1,W=()=>{M||(M=!0,clearTimeout(q),U?.(),J?.(),I(_?{entries:C,truncated:!0}:{entries:C}))};U=b.onBroadcast(ee=>{let me=Ey(ee);for(C.push(ee),R.push(me),T+=me;C.length>0&&(C.length>1e3||T>1048576);)C.shift(),T-=R.shift()??0,_=!0;y==="turn_complete"&&ee.params?.update?.sessionUpdate==="turn_complete"&&W()});let q=setTimeout(W,k);typeof q.unref=="function"&&q.unref(),J=b.onClose(()=>W())})}),u.onRequest("hydra-acp/child_session/close",async p=>{let g=p??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0;if(!w)throw N(-32602,"close_child_session requires childSessionId");let y=e.manager.get(w);return y&&await y.close({deleteRecord:!1,by:`child_session/close ${l.clientId}`}),{ok:!0}}),u.onRequest("hydra-acp/attention/set",async p=>Oy(p,o.name,e)),u.onRequest("hydra-acp/attention/clear",async p=>Fy(p,o.name,e)),u.onRequest("hydra-acp/connection/keep_alive",async p=>{let g=p??{},w=typeof g.token=="string"?g.token:void 0,y=typeof g.sessionId=="string"?g.sessionId:void 0,k=typeof g.estimatedRemainingMs=="number"?g.estimatedRemainingMs:void 0;return w&&y&&e.manager.get(y)?.keepAliveClaim(w,k),{ok:!0}})}u.onRequest("hydra-acp/session/tool_content",async h=>{let p=h??{};if(typeof p.sessionId!="string"||typeof p.hash!="string")throw N(E.InvalidParams,"hydra-acp/session/tool_content requires sessionId and hash");let g=await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,w=await e.manager.loadToolBlob(g,p.hash);if(w===null)throw N(E.SessionNotFound,"tool content not found");return{content:w}}),u.onRequest("authenticate",async h=>Ty(h,e)),u.onRequest("logout",async h=>Py(h,e)),u.onRequest("session/new",async h=>{let p=Yi.parse(h),g=rt(h?._meta),w=Array.isArray(g.transformers)&&g.transformers.every(Z=>typeof Z=="string")?g.transformers:e.manager.defaultTransformers??[],y=e.transformers?.resolveChain(w)??[],k=await on(p.cwd),b=g.agentId??k.agentId??e.defaultAgent,I=await e.registry?.getAgent(b),v=cn(k.configDefaults,I??{id:b})?.value,A,C,R=p.mcpServers;if(g.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){A=Iu(32).toString("hex"),C=e.mcpTokenRegistry.reserve(A);let Me={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${A}`}]};R=[...p.mcpServers??[],Me]}let T,_,U=Yt(e);U!==void 0&&(R=[...R??[],...U.descriptors]);let J=Bo({baselineMcpServers:p.mcpServers,stdinEnabled:g.mcpStdin===!0,deps:e}),M;try{M=await e.manager.create({cwd:p.cwd,agentId:b,mcpServers:R,title:g.title,agentArgs:g.agentArgs,model:g.model??v?.model,configDefaults:v,onInstallProgress:nr(u),transformChain:y,originatingClient:l.clientInfo,...g.interactive!==void 0?{interactive:g.interactive}:{},...g.env!==void 0?{forwardedEnv:g.env}:{},...g.workspace!==void 0?{workspace:g.workspace}:{},...J?{mintMcpServersForSwap:J}:{}})}catch(Z){throw C!==void 0&&C.abandon(Z instanceof Error?Z:void 0),_!==void 0&&_.abandon(Z instanceof Error?Z:void 0),U!==void 0&&U.abandon(Z instanceof Error?Z:void 0),Z}if(A!==void 0&&C!==void 0&&e.mcpTokenRegistry!==void 0){let Z=A,Me=e.mcpTokenRegistry;C.complete(M),M.onClose(()=>{Me.unbind(Z)})}if(T!==void 0&&_!==void 0&&e.mcpTokenRegistry!==void 0){let Z=T,Me=e.mcpTokenRegistry;_.complete(M),M.onClose(()=>{Me.unbind(Z)})}U!==void 0&&U.bindToSession(M),xu(M.sessionId,e);let W,q;try{Zt(l,M,M.sessionId),W=gt(u,M,l),{entries:q}=await M.attach(W,"full")}catch(Z){throw await M.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),Z}l.attached.set(M.sessionId,{sessionId:M.sessionId,clientId:W.clientId,readonly:!1}),setImmediate(()=>{(async()=>{for(let Z of q){if(u.isClosed())break;await u.notify(Z.method,Ue(Le(Z.params,Z.recordedAt),Z.seq)).catch(()=>{})}})()});let ee=sr(M),me=rr(M);return{sessionId:M.sessionId,...ee?{modes:ee}:{},...me?{models:me}:{},configOptions:M.buildConfigOptions(),_meta:or(e.manager,M,{clientId:W.clientId})}}),u.onRequest("session/attach",async h=>{let p=Zi.parse(h),g=p.clientInfo?.version;g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g));let w=rt(p._meta),y=w.resume,k=w.readonly===!0,b=w.env;s.log.info(`session/attach sessionId=${p.sessionId} hasResumeHints=${!!y} readonly=${k}`);let I=y?p.sessionId:await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,v=e.manager.get(I);if(!v&&k){let M=await e.manager.loadFromDisk(I);if(!M)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);let W=await e.manager.loadHistory(I,{...w.historyLimit!==void 0?{maxEntries:w.historyLimit}:{}}),q=p.clientId??`cli_${ei(8)}`;l.attached.set(M.hydraSessionId,{sessionId:M.hydraSessionId,clientId:q,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${M.hydraSessionId} clientId=${q} attachedCount=${l.attached.size} replayed=${W.length}`);for(let ee of W)await u.notify(ee.method,Ue(Le(ee.params,ee.recordedAt),ee.seq)).catch(()=>{});return{sessionId:M.hydraSessionId,clientId:q,connectedClients:[q],historyPolicy:"full",replayed:W.length,_meta:Ny(M)}}let A=!v;if(!v){let M=await e.manager.loadFromDisk(I),W=await My(I,y,M?.upstreamSessionId,e.manager);W.kind==="ignore"&&s.log.warn(W.logMessage);let q=M;if(y&&W.kind==="honor"&&(q={...M,hydraSessionId:p.sessionId,upstreamSessionId:y.upstreamSessionId,agentId:y.agentId,cwd:M?.workspace?.path??y.cwd,...y.title!==void 0?{title:y.title}:{},...y.agentArgs!==void 0?{agentArgs:y.agentArgs}:{}}),!q)throw N(E.SessionNotFound,`session ${p.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(q.agentId,q.upstreamSessionId))throw N(E.SessionNotFound,`session ${p.sessionId} was deleted`);let ee=q.originatingClient?q:{...q,originatingClient:l.clientInfo},me=b!==void 0?{...ee,forwardedEnv:b}:ee;v=await Et(e,{...me,onInstallProgress:nr(u)})}Zt(l,v,v.sessionId);let C=gt(u,v,l,p.clientInfo,p.clientId),R=w.replayMode==="drip",{entries:T,appliedPolicy:_}=await v.attach(C,p.historyPolicy,{afterMessageId:p.afterMessageId,afterSeq:p.afterSeq,raw:R,...w.historyLimit!==void 0?{historyLimit:w.historyLimit}:{},...w.toolContent!==void 0?{toolContent:w.toolContent}:{}});if(l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:C.clientId,readonly:k}),b!==void 0&&await e.manager.setForwardedEnv(v.sessionId,b).catch(()=>{}),s.log.info(`session/attach OK sessionId=${v.sessionId} clientId=${C.clientId} attachedCount=${l.attached.size} requestedPolicy=${p.historyPolicy} appliedPolicy=${_} replayed=${T.length} readonly=${k}${R?" replayMode=drip":""}`),R){let M=w.dripSpeed&&w.dripSpeed>0?w.dripSpeed:1,W=750;(async()=>{let q=null;for(let ee of T){let me=typeof ee.recordedAt=="number"?ee.recordedAt:null;if(q!==null&&me!==null){let Z=Math.min(W,Math.max(0,(me-q)/M));Z>0&&await new Promise(Me=>setTimeout(Me,Z))}me!==null&&(q=me);try{await u.notify(ee.method,Ue(Le(ee.params,me??void 0),ee.seq))}catch{return}}})()}else for(let M=0;M<T.length&&!u.isClosed();M++){let W=T[M],q=u.notify(W.method,Ue(Le(W.params,W.recordedAt),W.seq)).catch(()=>{});(M+1)%200===0&&await q}v.replayPendingPermissions(C);let U=sr(v),J=rr(v);return{sessionId:v.sessionId,clientId:C.clientId,connectedClients:v.connectedClients(C.clientId),historyPolicy:_,replayed:T.length,...U?{modes:U}:{},...J?{models:J}:{},configOptions:v.buildConfigOptions(),_meta:or(e.manager,v,{resurrected:A})}}),u.onRequest("session/detach",async h=>{let p=ea.parse(h),g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"client not attached to that session");let w=e.manager.get(p.sessionId);return w?.detach(g.clientId),l.attached.delete(p.sessionId),w&&e.manager.reapIfOrphanedNonInteractive(p.sessionId),{sessionId:p.sessionId,_meta:{[ce]:{detachStatus:"detached"}}}}),u.onRequest("session/list",async h=>{let p=ta.parse(h??{});return{sessions:(await e.manager.list({cwd:p.cwd})).filter(k=>k.originatingClient?.name!==vs).map(na)}}),u.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw N(E.InternalError,"agent registry unavailable");return Nt(e.registry)}),u.onRequest("hydra-acp/agents/auth_methods",async h=>{let p=h??{};if(typeof p.agentId!="string"||p.agentId.length===0)throw N(E.InvalidParams,"hydra-acp/agents/auth_methods requires a non-empty agentId string");return{authMethods:(await e.manager.bootstrapAgentForAuth(p.agentId)).authMethods??[]}}),u.onRequest("session/prompt",async h=>{let p=sa.parse(h);f(p.sessionId,"session/prompt");let g=await ku(p,e.manager,b=>{s.log.warn(`session/prompt: dropping unknown sentBy.sessionId=${b} sessionId=${p.sessionId}`)});if(g?.fromSession!==void 0){if((g.depth??0)>3)throw s.log.warn(`session/prompt: refusing depth ${g.depth} chain from ${g.fromSession} to ${p.sessionId}`),N(E.InvalidRequest,`message chain too deep (${g.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(g.awaiting===!0&&bu(g.fromSession,p.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${g.fromSession} -> ${p.sessionId}`),N(E.InvalidRequest,`would deadlock: ${p.sessionId} is already blocked waiting on ${g.fromSession}. Send with --no-wait, or let the other turn finish first.`)}let w=l.attached.get(p.sessionId);if(!w)throw s.log.warn(`session/prompt rejected: not attached sessionId=${p.sessionId} attachedKeys=[${[...l.attached.keys()].join(",")}]`),N(E.SessionNotFound,"not attached to session");let y=e.manager.get(p.sessionId);if(!y){let b=await e.manager.loadFromDisk(p.sessionId);if(!b)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${p.sessionId}`),y=await Et(e,b);let I=gt(u,y,l,void 0,w.clientId);await y.attach(I,"none")}let k=g?.awaiting===!0&&g.fromSession!==void 0?vu(g.fromSession,p.sessionId):void 0;try{return await y.prompt(w.clientId,p,g)}finally{k?.()}});let m=h=>{let p;try{p=Yn.parse(h)}catch(y){s.log.warn(`session/cancel: invalid params: ${y.message}`);return}let g=l.attached.get(p.sessionId);if(!g)return;if(g.readonly){s.log.warn(`session/cancel dropped (readonly attachment) sessionId=${p.sessionId}`);return}let w=e.manager.get(p.sessionId);w&&w.cancel(g.clientId).catch(y=>{s.log.warn(`session/cancel for ${p.sessionId}: ${y.message}`)})};u.onNotification("session/cancel",m),u.onRequest("session/cancel",async h=>{let p=Yn.parse(h);return f(p.sessionId,"session/cancel"),m(h),null}),u.onRequest("hydra-acp/prompt/cancel",async h=>{let p=oa.parse(h);return f(p.sessionId,"hydra-acp/prompt/cancel"),Re(e.manager,p.sessionId).cancelQueuedPrompt(p.messageId)}),u.onRequest("hydra-acp/session/force_cancel",async h=>{let p=Yn.parse(h);return f(p.sessionId,"hydra-acp/session/force_cancel"),Re(e.manager,p.sessionId).forceCancel()}),u.onRequest("hydra-acp/prompt/update",async h=>{let p=ia.parse(h);return f(p.sessionId,"hydra-acp/prompt/update"),Re(e.manager,p.sessionId).updateQueuedPrompt(p.messageId,p.prompt)}),u.onRequest("hydra-acp/prompt/amend",async h=>{let p=aa.parse(h);f(p.sessionId,"hydra-acp/prompt/amend");let g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"not attached to session");return Re(e.manager,p.sessionId).amendPrompt(g.clientId,p)}),u.onRequest("_session/steering",async h=>{let p=da.parse(h);f(p.sessionId,"_session/steering");let g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"not attached to session");let w=e.manager.get(p.sessionId);if(!w){let y=await e.manager.loadFromDisk(p.sessionId);if(!y)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);w=await Et(e,y);let k=gt(u,w,l,void 0,g.clientId);await w.attach(k,"none")}return w.steer(g.clientId,p)}),u.onRequest("session/resume",async h=>{let p=h??{},g=typeof p.sessionId=="string"?p.sessionId:void 0;if(!g)throw N(E.InvalidParams,"session/resume requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let v=await e.manager.loadFromDisk(w);if(!v)throw N(E.SessionNotFound,`session ${g} not found in memory or on disk`);y=await Et(e,v)}Zt(l,y,y.sessionId);let k=gt(u,y,l);await y.attach(k,"pending_only"),l.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:k.clientId,readonly:!1}),y.replayPendingPermissions(k);let b=sr(y),I=rr(y);return{sessionId:y.sessionId,...b?{modes:b}:{},...I?{models:I}:{},configOptions:y.buildConfigOptions(),_meta:or(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/load",async h=>{let p=h??{},g=typeof p.sessionId=="string"?p.sessionId:void 0;if(!g)throw N(E.InvalidParams,"session/load requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let A=await e.manager.loadFromDisk(w);if(!A)throw N(E.SessionNotFound,`session ${g} not found in memory or on disk`);y=await Et(e,A)}Zt(l,y,y.sessionId);let k=gt(u,y,l),{entries:b}=await y.attach(k,"full");l.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:k.clientId,readonly:!1});for(let A of b){if(u.isClosed())break;await u.notify(A.method,Ue(Le(A.params,A.recordedAt),A.seq)).catch(()=>{})}y.replayPendingPermissions(k);let I=sr(y),v=rr(y);return{sessionId:y.sessionId,...I?{modes:I}:{},...v?{models:v}:{},configOptions:y.buildConfigOptions(),_meta:or(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/set_model",async h=>{let p=h?.sessionId;typeof p=="string"&&f(p,"session/set_model");let g=_y(h,e.manager);if(g.kind==="error")throw s.log.warn(g.logMessage),N(g.code,g.message);if(g.kind==="no_op")return s.log.warn(g.logMessage),await u.notify("session/update",{sessionId:g.sessionId,update:{sessionUpdate:"_hydra_current_model_update",currentModel:g.currentModel}}).catch(()=>{}),null;s.log.info(g.logMessage);let{modelId:w}=g,y=await g.session.forwardModelChange(w,h);return g.session.applyAgentConfigOptionResponse(y,"model"),g.session.applyModelChange(w),y}),u.onRequest("session/set_mode",async h=>{let p=h,g=p?.sessionId;if(typeof g=="string"&&f(g,"session/set_mode"),!p||typeof p.sessionId!="string")throw N(E.InvalidParams,"session/set_mode requires string sessionId");if(typeof p.modeId!="string")throw N(E.InvalidParams,"session/set_mode requires string modeId");let w=Re(e.manager,p.sessionId),y=await w.forwardRequest("session/set_mode",h);return w.applyModeChange(p.modeId),y}),u.onRequest("session/set_config_option",async h=>{let p=h,g=b=>N(E.InvalidParams,b),w=p?.sessionId;if(typeof w=="string"&&f(w,"session/set_config_option"),!p||typeof p.sessionId!="string")throw g("session/set_config_option requires string sessionId");if(typeof p.configId!="string")throw g("session/set_config_option requires string configId");if(typeof p.value!="string")throw g("session/set_config_option requires string value");let y=Re(e.manager,p.sessionId),k=y.buildConfigOptions().find(b=>b.id===p.configId);if(!k)throw g(`unknown configId ${JSON.stringify(p.configId)} for this session`);if(!k.options.some(b=>b.value===p.value))throw g(`value ${JSON.stringify(p.value)} is not valid for configId ${JSON.stringify(p.configId)}`);switch(p.configId){case"model":{if(p.value!==y.currentModel){let b=await y.forwardModelChange(p.value);y.applyAgentConfigOptionResponse(b,"model")}y.applyModelChange(p.value);break}case"mode":{p.value!==y.currentMode&&await y.forwardRequest("session/set_mode",{sessionId:p.sessionId,modeId:p.value}),y.applyModeChange(p.value);break}case"agent":{p.value!==y.agentId&&await y.setAgent(p.value);break}default:{let b=await y.forwardRequest("session/set_config_option",{sessionId:p.sessionId,configId:p.configId,value:p.value});y.applyAgentConfigOptionResponse(b,p.configId)&&y.broadcastConfigOptions()}}return{configOptions:y.buildConfigOptions()}}),u.setDefaultHandler(async(h,p)=>{let g=new Set(["hydra-acp/attention/set","hydra-acp/attention/clear"]),w=p.startsWith("session/"),y=p.startsWith("hydra-acp/");if(!w&&!y||h===null||typeof h!="object"||g.has(p))throw N(E.MethodNotFound,`Method not found: ${p}`);let k=h.sessionId;if(typeof k!="string")throw N(E.MethodNotFound,`Method not found: ${p}`);return f(k,p),Re(e.manager,k).forwardRequest(p,h)})})}async function Ty(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw N(E.InvalidParams,"authenticate requires a non-empty methodId string");let n=t.methodId,r=t._meta?.["hydra-acp"],o=typeof r?.sessionId=="string"?r.sessionId:void 0,i=typeof r?.agentId=="string"?r.agentId:void 0,a=o!==void 0?e.manager.getAgentForSession(o):void 0;if(!a||!a.isAlive()){let m=i??e.defaultAgent;a=await e.manager.bootstrapAgentForAuth(m)}let d=a.authMethods??[],c=d.find(m=>m.id===n);if(!c){let m=d.map(h=>h.id);throw N(E.InvalidParams,`authenticate: methodId ${JSON.stringify(n)} is not advertised by agent ${a.agentId}; valid: [${m.map(h=>JSON.stringify(h)).join(", ")}]`)}let u=c._meta?.type,l=(()=>{let m=c._meta?.["terminal-auth"];if(m&&typeof m=="object"&&!Array.isArray(m))return m})();if((c.type??(u==="agent"||u==="terminal"?u:l!==void 0?"terminal":"agent"))==="terminal"){let m=(k,b)=>{if(!Array.isArray(k))throw N(E.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be a string[]; got ${k===null?"null":typeof k}`);for(let I of k)if(typeof I!="string")throw N(E.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be string[]; got non-string entry ${JSON.stringify(I)}`);return k},h=await e.manager.planSpawnForAgent(a.agentId),p,g;if(l?.args!==void 0){let k=typeof l.command=="string"?l.command:void 0;p=k!==void 0&&Cu.isAbsolute(k)?k:h.command,g=m(l.args,'_meta["terminal-auth"].args')}else{let k=c.args!==void 0?{raw:c.args,label:"args"}:c._meta?.args!==void 0?{raw:c._meta.args,label:"_meta.args"}:void 0,b=k!==void 0?m(k.raw,k.label):[];p=h.command,g=[...h.args,...b]}let w={};for(let[k,b]of Object.entries(process.env))typeof b=="string"&&(w[k]=b);Object.assign(w,h.env);let y=Au.homedir();return console.error(`[authenticate] terminal-auth requested agentId=${a.agentId} methodId=${n}`),{kind:"terminal",command:p,args:g,env:w,cwd:y}}try{return await a.connection.request("authenticate",{methodId:n})}catch(m){throw lt(m,a)}}async function Py(s,e){let n=(s??{})._meta?.["hydra-acp"],r=typeof n?.sessionId=="string"?n.sessionId:void 0,o=typeof n?.agentId=="string"?n.agentId:void 0,i=r!==void 0?e.manager.getAgentForSession(r):void 0;if(!i||!i.isAlive()){let a=o??e.defaultAgent;i=await e.manager.bootstrapAgentForAuth(a)}return await i.connection.request("logout",{})}function nr(s){return e=>{let t={agentId:e.agentId,version:e.version,source:e.source,phase:e.phase};"receivedBytes"in e&&(t.receivedBytes=e.receivedBytes),"totalBytes"in e&&(t.totalBytes=e.totalBytes),"packageSpec"in e&&(t.packageSpec=e.packageSpec),s.notify(ca,t).catch(()=>{})}}function sr(s){let e=s.availableModes();if(e.length===0)return;let t=e.map(r=>{let o={id:r.id,name:r.name??r.id};return r.description!==void 0&&(o.description=r.description),o});return{currentModeId:s.currentMode??e[0].id,availableModes:t}}function rr(s){let e=s.availableModels();if(e.length===0)return;let t=e.map(r=>{let o={modelId:r.modelId};return r.name!==void 0&&(o.name=r.name),r.description!==void 0&&(o.description=r.description),o});return{currentModelId:s.currentModel??e[0].modelId,availableModels:t}}async function My(s,e,t,n){return e?await n.isRetiredGeneration(s,e.upstreamSessionId)?{kind:"ignore",logMessage:`session/attach ignoring stale resume hint sessionId=${s} hintUpstream=${e.upstreamSessionId} recordUpstream=${t} (retired generation)`}:{kind:"honor"}:{kind:"none"}}function _y(s,e){if(!s||typeof s!="object")return{kind:"error",code:E.InvalidParams,message:"session/set_model requires params",logMessage:"session/set_model rejected: params not an object"};let t=s;if(typeof t.sessionId!="string")return{kind:"error",code:E.InvalidParams,message:"session/set_model requires string sessionId",logMessage:"session/set_model rejected: missing/non-string sessionId"};if(typeof t.modelId!="string")return{kind:"error",code:E.InvalidParams,message:"session/set_model requires string modelId",logMessage:`session/set_model rejected: missing/non-string modelId sessionId=${t.sessionId}`};let n=e.get(t.sessionId);if(!n)return{kind:"error",code:E.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=Ut(t.modelId,r);if(o.kind==="none")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model passthrough (no availableModels) sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="exact")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model accepted sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="resolved")return{kind:"ok",session:n,modelId:o.modelId,logMessage:`session/set_model resolved sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} \u2192 ${JSON.stringify(o.modelId)}`};let i=r.map(d=>d.modelId).join(", "),a=o.kind==="ambiguous"?`ambiguous (trailing-segment matches [${o.candidates.join(", ")}])`:"not in availableModels";return n.currentModel!==void 0&&n.currentModel.length>0?{kind:"no_op",session:n,sessionId:t.sessionId,currentModel:n.currentModel,logMessage:`session/set_model no_op (resyncing client) sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} ${a} actual=${JSON.stringify(n.currentModel)} agentId=${n.agentId} known=[${i}]`}:{kind:"error",code:E.InvalidParams,message:`model "${t.modelId}" is ${a==="not in availableModels"?"not in this session's availableModels":a} (agent ${n.agentId}); known models: ${i}`,logMessage:`session/set_model rejected sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)} ${a} agentId=${n.agentId} known=[${i}] (no current model to fall back to)`}}async function $y(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw N(E.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw N(E.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw N(E.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return Re(t.manager,r).addTransformer(o),{ok:!0}}async function Oy(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw N(E.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw N(E.InvalidParams,"hydra-acp/attention/set requires string reason");return Re(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function Fy(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw N(E.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw N(E.InvalidParams,"hydra-acp/attention/clear requires string reason");return Re(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function Ny(s){let e={sessionId:s.hydraSessionId,upstreamSessionId:s.upstreamSessionId,cwd:s.cwd,workspace:s.workspace,title:s.title,agentId:s.agentId,currentModel:s.currentModel,currentUsage:An(s.currentUsage),forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:s.interactive,updatedAt:s.createdAt??new Date().toISOString(),attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1},t={currentMode:s.currentMode,agentArgs:s.agentArgs,availableCommands:s.agentCommands,availableModes:s.agentModes,availableModels:s.agentModels,armedTaskList:[]};return{[ce]:Qn(e,t)}}function or(s,e,t={}){let n=s.liveListEntry(e),r={clientId:t.clientId,currentMode:e.currentMode,agentArgs:e.agentArgs,availableCommands:e.mergedAvailableCommands(),availableModes:e.availableModes(),availableModels:e.availableModels(),turnStartedAt:e.turnStartedAt,agentCapabilities:e.agentCapabilities,queue:e.queueSnapshot(),armedTaskList:e.armedBackgroundTasks,...t.resurrected===!0?{resurrected:!0}:{}};return un(e.agentMeta,Qn(n,r))}function Dy(){return{protocolVersion:1,agentInfo:{name:"hydra",version:de},agentCapabilities:{promptCapabilities:{image:!0,audio:!0,embeddedContext:!0},mcpCapabilities:{http:!0,sse:!0},loadSession:!0,auth:{logout:{}},sessionCapabilities:{attach:{},list:{},resume:{},delete:{},close:{},fork:{}}},authMethods:[{id:"proxy",name:"Hydra proxy",type:"agent",description:"Hydra proxies authentication to the downstream agent selected per session"}],_meta:{...un(void 0,{prompt:{queueing:!0,cancelling:!0,updating:!0,amending:!0,pipelining:!1},agents:{list:!0,installProgress:!0},session:{fork:{forkAt:!0,agentSwap:!0,synthesis:!0,model:!0}}}),steering:{supported:!0}}}}function jy(s,e){if(!(!e.transformers||!e.manager))for(let t of e.manager.defaultTransformers){let n=e.transformers.resolveChain([t])[0];n&&s.addTransformer(n)}}function xu(s,e){if(!e.transformers)return;let t=e.transformers.interestedIn("lifecycle:session.starting");for(let n of t)n.connection.notify("hydra-acp/transformer/session_event",{event:"session.starting",sessionId:s}).catch(()=>{})}function gt(s,e,t,n,r){return{clientId:r??`cli_${ei(8)}`,connection:s,clientInfo:n}}function Zt(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var ir=class{byToken=new Map;reserve(e){if(this.byToken.has(e))throw new Error("mcp token already bound");let t,n,r=new Promise((i,a)=>{t=i,n=a});r.catch(()=>{});let o={session:void 0,sessionReady:r,disposers:[]};return this.byToken.set(e,o),{complete:i=>{o.session=i,t(i)},abandon:i=>{this.byToken.delete(e),n(i??new Error("mcp token reservation abandoned"))}}}bind(e,t){let{complete:n}=this.reserve(e);n(t)}lookup(e){return this.byToken.get(e)}addDisposer(e,t){let n=this.byToken.get(e);n!==void 0&&n.disposers.push(t)}async unbind(e){let t=this.byToken.get(e);if(t!==void 0){this.byToken.delete(e);for(let n of t.disposers)try{await n()}catch{}}}size(){return this.byToken.size}};import{randomUUID as Hy}from"crypto";import{McpServer as Ly}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Uy}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as ge}from"zod";function ti(s){if(s.method!=="session/update")return null;let t=s.params?.update;return!t||typeof t.sessionUpdate!="string"?null:{kind:t.sessionUpdate,update:t}}function Ie(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var Eu="Bearer ";function en(s){let e=s.headers.authorization;if(typeof e!="string"||!e.startsWith(Eu))return;let t=e.slice(Eu.length).trim();return t.length>0?t:void 0}function By(s){let e=new Ly({name:"hydra-acp-stdin",version:"1.0.0"},{instructions:"Piped input from `hydra cat --stream` is exposed here as a byte stream. Use `tail` for the latest N bytes (good for finding the end of a log), `head` for the first N bytes (good for headers/preamble), `read` for windowed reads against an absolute byte cursor, `wait_for_more` to block until new bytes arrive past a cursor, and `info` for the current cursors/capacity/closed status. Byte payloads come back base64-encoded."});return e.registerTool("tail",{description:"Return the most recent `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means older bytes existed but have been evicted from the ring.",inputSchema:{bytes:ge.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return Ie(n)}),e.registerTool("head",{description:"Return the first `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means the head has already been evicted from the ring and the returned bytes start at the oldest still-resident cursor.",inputSchema:{bytes:ge.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return Ie(n)}),e.registerTool("read",{description:"Read up to `max_bytes` bytes starting at absolute byte `cursor`. Returns `{bytes, nextCursor, gap?, eof?}` \u2014 `gap` is the number of bytes silently skipped because the ring had evicted them; `eof:true` means the producer closed and there is nothing left to read.",inputSchema:{cursor:ge.number().int().min(0).describe("Absolute byte offset to start reading from. Use 0 to read from the very beginning (may produce a gap if old bytes have been evicted)."),max_bytes:ge.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:ge.number().int().min(0).optional().describe("If no bytes are available, block up to this many ms for more (capped server-side at 60_000).")}},async({cursor:t,max_bytes:n,wait_ms:r})=>{let o=await s.streamRead(t,n,r);return Ie(o)}),e.registerTool("wait_for_more",{description:"Block until bytes are available past `cursor`, the stream closes, or `timeout_ms` elapses. Returns one of {data, eof, timeout} plus the current `writeCursor`. Use this when you've consumed everything up to a cursor and want to wait for more without busy-polling.",inputSchema:{cursor:ge.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:ge.number().int().min(0).describe("Maximum ms to block (server caps at 60_000).")}},async({cursor:t,timeout_ms:n})=>{let r=await s.streamWaitFor(t,n),o=s.streamInfo();return Ie({outcome:r,writeCursor:o.writeCursor,closed:o.closed})}),e.registerTool("grep",{description:"Scan piped stdin line-by-line and return lines matching `pattern`. Prefer this over `read` when the question is 'find lines that mention X' \u2014 it filters server-side so you don't pull and decode 64 KiB base64 windows. Returns `{matches: [{cursor, line, before?, after?}], truncated, nextCursor, gap?, scannedBytes, eof?}`. Lines come back as decoded UTF-8 strings (not base64). When `truncated:true`, re-call with `cursor: nextCursor` to resume.",inputSchema:{pattern:ge.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:ge.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:ge.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:ge.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:ge.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:ge.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:ge.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:ge.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:ge.number().int().min(0).optional().describe("Optional absolute byte offset to start scanning from. Omit to scan from the oldest still-resident byte. Pass the `nextCursor` from a previous truncated call to resume.")}},async t=>{let n={pattern:t.pattern};t.regex!==void 0&&(n.regex=t.regex),t.case_insensitive!==void 0&&(n.caseInsensitive=t.case_insensitive),t.invert!==void 0&&(n.invert=t.invert),t.max_matches!==void 0&&(n.maxMatches=t.max_matches),t.max_bytes!==void 0&&(n.maxBytes=t.max_bytes),t.context_before!==void 0&&(n.contextBefore=t.context_before),t.context_after!==void 0&&(n.contextAfter=t.context_after),t.cursor!==void 0&&(n.cursor=t.cursor);let r=s.streamGrep(n);return Ie(r)}),e.registerTool("info",{description:"Report cursor / capacity / closed state of the stdin ring. Cheap; safe to call repeatedly.",inputSchema:{}},async()=>{let t=s.streamInfo();return Ie(t)}),e}var Wy=1e4;function Tu(s,e){let t=new Map;async function n(i,a){let d=t.get(i);if(d!==void 0)return d.transport;let c=By(a),u=new Uy({sessionIdGenerator:()=>Hy()});await c.connect(u);let l={server:c,transport:u};return t.set(i,l),e.addDisposer(i,async()=>{t.delete(i);try{await u.close()}catch{}try{await c.close()}catch{}}),u}async function r(i,a){let d=en(i);if(d===void 0){a.code(401).send({error:"missing bearer token"});return}let c=e.lookup(d);if(c===void 0){a.code(404).send({error:"unknown stdin token"});return}let u;if(c.session!==void 0)u=c.session;else{let f,m=new Promise(p=>{f=setTimeout(()=>p(void 0),Wy)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(f!==void 0&&clearTimeout(f),h===void 0){a.code(503).send({error:"session not ready"});return}u=h}let l=await n(d,u);a.hijack(),await l.handleRequest(i.raw,a.raw,i.body)}let o={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.get("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.delete("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)})}import{randomUUID as qy}from"crypto";import{McpServer as zy}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Jy}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as Ke}from"zod";function Vy(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var Pu=2e3,Mu=2e4;function Gy(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return Wt([s]);let n=[],r=ln(t);r!==void 0?n.push(`Tool: ${r}`):typeof t.title=="string"&&t.title.length>0&&n.push(`Tool: ${t.title}`);let o=t.rawInput;if(o&&typeof o=="object"&&!Array.isArray(o))for(let[a,d]of Object.entries(o))typeof d=="string"&&d.length>0&&n.push(`${a}=${d}`);if(Array.isArray(t.locations))for(let a of t.locations)typeof a?.path=="string"&&a.path.length>0&&n.push(a.path);let i=ns(t);return i!==void 0&&n.push(i),n.join(`
198
+ `)}}catch(C){if(C.code==="ENOENT")return f.raw.end(),f;throw C}return f.raw.end(),f}),s.post("/v1/sessions/:id/prompt/:messageId/notify",async(l,f)=>{let m=l.params,h=m.id,p=await e.resolveCanonicalId(h)??h,g=m.messageId,w=l.body,y=typeof w?.callbackUrl=="string"?w.callbackUrl:"",k=typeof w?.secret=="string"?w.secret:"";if(!g||!y||!k){f.code(400).send({error:"messageId, callbackUrl, and secret are all required"});return}let b;try{b=new URL(y)}catch{f.code(400).send({error:"callbackUrl must be a valid absolute URL"});return}if(b.protocol!=="https:"&&b.protocol!=="http:"){f.code(400).send({error:"callbackUrl must be http or https"});return}let I=e.get(p);if(!I){f.code(404).send({error:"session not found or not warm"});return}let v=I.registerTurnNotify(g,y,k);if(v.alreadyTerminal){f.code(200).send({status:"already_terminal",stopReason:v.stopReason});return}f.code(202).send({status:"registered"})}),s.get("/v1/sessions/:id/attention",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,p=e.get(h);return!p&&!await e.hasRecord(h)?(f.code(404).send({error:"session not found"}),f):p?{flags:p.listAttentionFlags()}:{flags:(await e.store.read(h))?.attentionFlags??[]}}),s.get("/v1/sessions/attention",async(l,f)=>{let m=l.query;if(!m.source||m.source.trim().length===0)return f.code(400).send({error:"source query parameter is required"}),f;let h=await e.list({includeNonInteractive:!0}),p=[];for(let g of h){let w=e.get(g.sessionId),y;w?y=w.listAttentionFlags():y=(await e.store.read(g.sessionId))?.attentionFlags??[];for(let k of y)k.source===m.source&&p.push({...k,sessionId:g.sessionId})}return{flags:p}}),s.post("/v1/sessions/:id/attention/clear",async(l,f)=>{let m=l.params.id,h=await e.resolveCanonicalId(m)??m,g=l.body??{},w=typeof g.source=="string"?g.source:"",y=typeof g.reason=="string"?g.reason:"";if((w.length>0||y.length>0)&&!(w.length>0&&y.length>0)){f.code(400).send({error:"both source and reason are required to clear a specific flag, or omit both to clear all"});return}w.length===0&&y.length;let k=e.get(h);if(k){if(w.length>0&&y.length>0)k.clearAttentionFlag(w,y);else{let C=Array.from(k.listAttentionFlags()).map(R=>`${R.source}::${R.reason}`);for(let R of C)k.clearAttentionFlag(R.split("::")[0],R.split("::").slice(1).join("::"))}f.code(204).send();return}if(!await e.hasRecord(h)){f.code(404).send({error:"session not found"});return}let b=e.store,I=await b.read(h);if(!I){f.code(404).send({error:"session not found"});return}let v=I.attentionFlags??[],A;if(w.length>0&&y.length>0){let C=`${w}::${y}`;A=v.filter(R=>`${R.source}::${R.reason}`!==C)}else A=[];if(A.length===v.length&&A.every((C,R)=>C.source===v[R].source&&C.reason===v[R].reason)){f.code(204).send();return}await b.write({...I,attentionFlags:A}),f.code(204).send()})}function Bc(s,e,t,n={}){s.get("/v1/agents",async()=>Nt(e)),s.get("/v1/registry",async()=>e.load()),s.post("/v1/registry/refresh",async()=>{let r=await e.refresh();return{version:r.version,agentCount:r.agents.length}}),s.post("/v1/agents/:id/install",async(r,o)=>{let i=r.params.id,a=await e.getAgent(i);if(!a){o.code(404).send({error:`agent ${i} not found in registry`});return}if(a.distribution.uvx&&!a.distribution.npx&&!a.distribution.binary){o.send({agentId:a.id,version:a.version??"current",distribution:"uvx",installed:!1,message:"uvx agents resolve on first run; nothing to pre-install."});return}try{let d=await Ee(a,[],{npmRegistry:n.npmRegistry}),c=a.distribution.npx?"npx":a.distribution.binary?"binary":"unknown";o.send({agentId:a.id,version:d.version,distribution:c,installed:!0,command:d.command})}catch(d){o.code(500).send({error:d.message})}}),s.post("/v1/agents/:id/sync",async(r,o)=>{let i=r.params.id;try{let{synced:a,skipped:d}=await t.syncFromAgent(i);return{synced:a.map(c=>({sessionId:c.sessionId,upstreamSessionId:c.upstreamSessionId,agentId:c.agentId,cwd:c.cwd,title:c.title,updatedAt:c.updatedAt})),skipped:d}}catch(a){let d=a;if(d.code===E.AgentNotInstalled){o.code(404).send({error:d.message});return}o.code(409).send({error:d.message})}})}G();function Wc(s,e,t,n=()=>[]){s.get("/v1/health",{config:{skipAuth:!0}},async()=>({status:"ok",version:e,configDigest:t,home:x.home(),driftedKeys:n()}))}import*as Vc from"os";G();Ne();var Nn=/^[A-Za-z0-9][A-Za-z0-9._-]*$/,Gs=class s{data;constructor(e){this.data=e}static async load(){let e=await ie(x.peers());return new s(Bh(e))}get(e){return this.data.entries[e]}async set(e){this.data.entries[e.name]=e,await qc(this.data)}async delete(e){return e in this.data.entries?(delete this.data.entries[e],await qc(this.data),!0):!1}list(){return Object.values(this.data.entries).map(({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})=>({name:e,host:t,port:n,expiresAt:r,label:o,addedAt:i,pinnedFingerprint:a,pinnedAt:d})).sort((e,t)=>e.addedAt.localeCompare(t.addedAt))}};function Bh(s){if(!s||typeof s!="object")return{version:1,entries:{}};let e=s,t=e.entries&&typeof e.entries=="object"?e.entries:{},n={};for(let[r,o]of Object.entries(t)){if(!o||typeof o!="object")continue;let i=o;if(typeof i.name!="string"||typeof i.host!="string"||typeof i.port!="number"||typeof i.token!="string"||typeof i.expiresAt!="string"||typeof i.addedAt!="string")continue;let a={name:i.name,host:i.host,port:i.port,token:i.token,expiresAt:i.expiresAt,addedAt:i.addedAt};typeof i.label=="string"&&(a.label=i.label),typeof i.pinnedFingerprint=="string"&&(a.pinnedFingerprint=i.pinnedFingerprint),typeof i.pinnedAt=="string"&&(a.pinnedAt=i.pinnedAt),n[r]=a}return{version:1,entries:n}}async function qc(s){await fe(x.peers(),s,{mode:384})}var Wh=3600*24*365,Ge=class extends Error{status;constructor(e,t){super(e),this.name="PeerLoginError",this.status=t}};function Ks(s,e){return`${ke(s)?"http":"https"}://${s}:${e}`}async function zc(s){let e=s.fetchImpl??fetch,t=`${s.host}:${s.port}`,n=Ks(s.host,s.port),r;try{r=await e(`${n}/v1/auth/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:s.password,label:s.label,ttlSec:s.ttlSec??Wh})})}catch(i){throw new Ge(`Could not reach ${t}: ${i.message}`,502)}if(r.status===401)throw new Ge(`Wrong password for ${t}.`,401);if(r.status===403)throw new Ge(`No password is configured on ${t}. Run \`hydra-acp auth password\` on that daemon first.`,502);if(r.status===429)throw new Ge(`Too many failed login attempts on ${t}; try again later.`,429);if(!r.ok)throw new Ge(`Login to ${t} failed: HTTP ${r.status}`,502);let o=await r.json();if(!o.session_token||!o.expires_at)throw new Ge(`Login to ${t} returned a malformed response.`,502);return{token:o.session_token,expiresAt:o.expires_at}}async function zo(s){let e=s.fetchImpl??fetch,t=Ks(s.host,s.port);try{await e(`${t}/v1/auth/logout`,{method:"POST",headers:{Authorization:`Bearer ${s.token}`,"Content-Type":"application/json"},body:JSON.stringify({})})}catch{}}function Gc(s){return{machine:ht(),hydraVersion:de,startedAt:s,os:{platform:process.platform,release:Vc.release(),arch:process.arch},node:process.version}}async function Qs(s){let e=s.fetchImpl??fetch,t;try{t=await e(`${Ks(s.host,s.port)}/v1/system`,{headers:{Authorization:`Bearer ${s.token}`},signal:s.signal})}catch(n){return{kind:"error",message:n.message}}if(t.status===401||t.status===403)return{kind:"unauthorized"};if(t.status===404)return{kind:"unsupported"};if(!t.ok)return{kind:"error",message:`HTTP ${t.status}`};try{let n=await t.json();return typeof n?.machine=="string"?{kind:"ok",system:n}:{kind:"ok"}}catch{return{kind:"ok"}}}function Jc(s){return s!==void 0&&s.length<=64&&Nn.test(s)}function Kc(s,e){if(Jc(s))return s;if(/^[\d.]+$/.test(e)||e.includes(":"))return;let t=e.split(".")[0];return Jc(t)?t:void 0}function Qc(s,e){s.get("/v1/system",async()=>Gc(e))}var qh=/^[A-Za-z0-9._-]+$/;function Ys(s,e,t){let n=e==="extension"?"extensions":"transformers",r=`/v1/${n}`;s.get(r,async()=>({[n]:t.list()})),s.get(`${r}/:name`,async(o,i)=>{let a=o.params.name,d=t.get(a);if(!d){i.code(404).send({error:`unknown ${e}: ${a}`});return}return d}),s.post(r,async(o,i)=>{let a=o.body??{},d=zh(a);if("error"in d){i.code(400).send({error:d.error});return}try{let c=t.register(d.config);i.code(201).send(c)}catch(c){Dn(i,c)}}),s.delete(`${r}/:name`,async(o,i)=>{let a=o.params.name;try{await t.unregister(a),i.code(204).send()}catch(d){Dn(i,d)}}),s.post(`${r}/:name/start`,async(o,i)=>{let a=o.params.name;try{let d=await t.startByName(a);i.code(200).send(d)}catch(d){Dn(i,d)}}),s.post(`${r}/:name/stop`,async(o,i)=>{let a=o.params.name;try{let d=await t.stopByName(a);i.code(200).send(d)}catch(d){Dn(i,d)}}),s.post(`${r}/:name/restart`,async(o,i)=>{let a=o.params.name;try{let d=await t.restartByName(a);i.code(200).send(d)}catch(d){Dn(i,d)}})}function Dn(s,e){let t=e.code,n=e.message??"unknown error";if(t==="NOT_FOUND"){s.code(404).send({error:n});return}if(t==="CONFLICT"){s.code(409).send({error:n});return}s.code(500).send({error:n})}function zh(s){let e=s.name;if(typeof e!="string"||!qh.test(e))return{error:"name must match [A-Za-z0-9._-]+"};let t=s.command;if(t!==void 0&&(!Array.isArray(t)||t.some(i=>typeof i!="string")))return{error:"command must be string[]"};let n=s.args;if(n!==void 0&&(!Array.isArray(n)||n.some(i=>typeof i!="string")))return{error:"args must be string[]"};let r=s.env;if(r!==void 0&&(typeof r!="object"||r===null||Array.isArray(r)))return{error:"env must be an object of string\u2192string"};if(r&&Object.values(r).some(i=>typeof i!="string"))return{error:"env values must be strings"};let o=s.enabled;return o!==void 0&&typeof o!="boolean"?{error:"enabled must be a boolean"}:{config:{name:e,command:t??[],args:n??[],env:r??{},enabled:o===void 0?!0:o}}}function Yc(s,e){Ys(s,"extension",e)}function Xc(s,e){Ys(s,"transformer",e)}function Zc(s,e){s.get("/v1/config",async()=>e())}import{z as ft}from"zod";G();import*as Xt from"fs/promises";import*as eu from"path";import{randomBytes as HA,scrypt as Jh,timingSafeEqual as Vh}from"crypto";import{promisify as Gh}from"util";var Kh=Gh(Jh);function tu(){return eu.join(x.home(),"password-hash")}var Qh=128*1024*1024;async function nu(){try{return(await Xt.readFile(tu(),"utf8")).trim().length>0}catch(s){if(s.code==="ENOENT")return!1;throw s}}async function su(s){if(typeof s!="string"||s.length===0)return!1;let e;try{e=(await Xt.readFile(tu(),"utf8")).trim()}catch(c){if(c.code==="ENOENT")return!1;throw c}let t=e.split("$");if(t.length!==6||t[0]!=="scrypt")return!1;let n=parseInt(t[1],10),r=parseInt(t[2],10),o=parseInt(t[3],10);if(!Number.isFinite(n)||!Number.isFinite(r)||!Number.isFinite(o))return!1;let i=Buffer.from(t[4],"hex"),a=Buffer.from(t[5],"hex");if(i.length===0||a.length===0)return!1;let d=await Kh(s,i,a.length,{N:n,r,p:o,maxmem:Qh});return d.length!==a.length?!1:Vh(d,a)}var Yh=ft.object({password:ft.string().min(1),label:ft.string().min(1).max(256).optional(),ttlSec:ft.number().int().positive().optional()}),Xh=ft.object({id:ft.string().optional()}).optional(),Zh=ft.object({token:ft.string().min(32)});function ru(s,e){s.post("/v1/auth/login",{config:{skipAuth:!0}},async(t,n)=>{let r=ey(t);if(e.rateLimiter.isBlocked(r))return n.code(429).send({error:"Too many failed attempts; try again later."});let o;try{o=Yh.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}if(!await nu())return n.code(403).send({error:"No password configured. Run `hydra-acp auth password` on the daemon host."});if(!await su(o.password))return e.rateLimiter.recordFailure(r),n.code(401).send({error:"Invalid password"});e.rateLimiter.recordSuccess(r);let a=await e.store.issue({label:o.label,ttlSec:o.ttlSec});return n.code(200).send({session_token:a.token,id:a.id,expires_at:a.expiresAt})}),s.post("/v1/auth/logout",async(t,n)=>{let r;try{r=Xh.parse(t.body??void 0)}catch{return n.code(400).send({error:"Invalid request body"})}let o=r?.id??t.authIdentity;if(!o||o==="service")return n.code(200).send({revoked:!1});let i=await e.store.revoke(o);return n.code(200).send({revoked:i})}),s.get("/v1/auth/verify",async(t,n)=>n.code(200).send({ok:!0})),s.get("/v1/auth/sessions",async(t,n)=>n.code(200).send({sessions:e.store.list()})),s.delete("/v1/auth/sessions",async(t,n)=>{let r=await e.store.revokeAll();return n.code(200).send({revoked:r})}),s.delete("/v1/auth/sessions/:id",async(t,n)=>{let r=t.params.id;return await e.store.revoke(r)?n.code(204).send():n.code(404).send({error:"Not found"})}),s.post("/v1/auth/rotate-token",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=Zh.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}return e.staticTokenValidator.rotate(r.token),n.code(200).send({rotated:!0})})}function ey(s){return s.ip||"unknown"}import{z as pt}from"zod";Hn();var fy=pt.object({name:pt.string().min(1).max(64).regex(Nn).optional(),host:pt.string().min(1),port:pt.number().int().positive().optional(),password:pt.string().min(1),label:pt.string().min(1).max(256).optional(),ttlSec:pt.number().int().positive().optional(),pinnedFingerprint:pt.string().min(1).optional()});function pu(s,e){s.post("/v1/remotes",async(t,n)=>{let r;try{r=fy.parse(t.body)}catch{return n.code(400).send({error:`Invalid request body (name must match ${Nn} and the rest is a normal login request)`})}let o=r.port??Mt;r.pinnedFingerprint&&jn(r.host,o,r.pinnedFingerprint);let i;try{i=await zc({host:r.host,port:o,password:r.password,label:r.label,ttlSec:r.ttlSec})}catch(f){if(f instanceof Ge)return n.code(f.status).send({error:f.message});throw f}let a=await Qs({host:r.host,port:o,token:i.token}),d=a.kind==="ok"?a.system:void 0,c=r.name;if(c===void 0){c=Kc(d?.machine,r.host);let f=c!==void 0?e.store.get(c):void 0,m=f!==void 0&&(f.host!==r.host||f.port!==o);if(c===void 0||m){await zo({host:r.host,port:o,token:i.token});let h=c===void 0?`Couldn't derive a remote name for ${r.host}`:`A remote named ${c} already points at ${f.host}:${f.port}`;return n.code(c===void 0?400:409).send({error:`${h}. Pass a name: hydra-acp remote add <name> ${r.host}`})}}let u=new Date().toISOString(),l={name:c,host:r.host,port:o,token:i.token,expiresAt:i.expiresAt,addedAt:u,...r.label!==void 0?{label:r.label}:{},...r.pinnedFingerprint!==void 0?{pinnedFingerprint:r.pinnedFingerprint,pinnedAt:u}:{}};return await e.store.set(l),e.health?.markOk(l.name,d),n.code(201).send({name:l.name,host:l.host,port:l.port,expiresAt:l.expiresAt,label:l.label,addedAt:l.addedAt,pinnedFingerprint:l.pinnedFingerprint,status:e.health?.get(l.name)?.status??"unknown"})}),s.get("/v1/remotes",async(t,n)=>{let r=e.store.list().map(o=>{let i=e.health?.get(o.name);return{...o,status:i?.status??"unknown",...i?.checkedAt?{lastCheckedAt:i.checkedAt}:{},...i?.system?{system:i.system}:{}}});return n.code(200).send({remotes:r})}),s.get("/v1/remotes/:name/agents",async(t,n)=>{let r=e.store.get(t.params.name);if(!r)return n.code(404).send({error:"Not found"});let i=`${ke(r.host)?"http":"https"}://${r.host}:${r.port}`,a={Authorization:`Bearer ${r.token}`};try{let[d,c]=await Promise.all([fetch(`${i}/v1/agents`,{headers:a}),fetch(`${i}/v1/config`,{headers:a}).catch(()=>null)]);if(!d.ok)return n.code(d.status).header("content-type","application/json").send(await d.text());let u=await d.json(),l={};if(c?.ok){let f=await c.json();l={defaultAgent:f.defaultAgent,sessionDefaults:f.sessionDefaults}}return n.code(200).send({...u,...l})}catch(d){return n.code(502).send({error:`Could not reach remote "${r.name}": ${d.message}`})}}),s.delete("/v1/remotes/:name",async(t,n)=>{let r=t.params.name,o=e.store.get(r);return o?(await zo({host:o.host,port:o.port,token:o.token}),await e.store.delete(r),e.health?.forget(r),e.store.list().some(a=>a.host===o.host&&a.port===o.port)||Vo(o.host,o.port),n.code(204).send()):n.code(404).send({error:"Not found"})})}function Zs(s){let e=[],t=[],n=!1,r=o=>{if(!n){n=!0;for(let i of t)i(o)}};return s.on("message",(o,i)=>{if(i)return;let a=o.toString("utf8");try{let d=JSON.parse(a);for(let c of e)c(d)}catch(d){for(let c of e)c({jsonrpc:"2.0",id:null,error:{code:E.ParseError,message:`Failed to parse WS frame: ${d.message}`}})}}),s.on("close",()=>r()),s.on("error",o=>r(o)),{async send(o){if(n)throw new Error("ws is closed");let i=JSON.stringify(o);await new Promise((a,d)=>{s.send(i,c=>{if(c){d(c);return}a()})})},onMessage(o){e.push(o)},onClose(o){t.push(o)},async close(){n||(await new Promise(o=>{let i=!1,a=()=>{i||(i=!0,clearTimeout(d),o())},d=setTimeout(a,5e3);s.once("close",a);try{s.close()}catch{a()}}),r())}}}Hn();import{WebSocket as py}from"ws";var gy=1e4,Xo=class extends Error{url;elapsedMs;constructor(e,t){super(`hydra-acp: websocket connect to ${e} timed out after ${t}ms`),this.name="WsConnectTimeoutError",this.url=e,this.elapsedMs=t}};async function gu(s,e,t=gy){let n={};try{let r=new URL(s);if(r.protocol==="wss:"){let o=Yo(r.hostname);o.rejectUnauthorized!==void 0&&(n.rejectUnauthorized=o.rejectUnauthorized),o.autoSelectFamily!==void 0&&(n.autoSelectFamily=o.autoSelectFamily),o.checkServerIdentity!==void 0&&(n.checkServerIdentity=o.checkServerIdentity)}}catch{}return new Promise((r,o)=>{let i=new py(s,e,n),a=Date.now(),d=setTimeout(()=>{i.off("open",c),i.off("error",u),i.on("error",()=>{});try{i.terminate()}catch{}o(new Xo(s,Date.now()-a))},t),c=()=>{clearTimeout(d),i.off("error",u),r(i)},u=l=>{clearTimeout(d),i.off("open",c),o(l)};i.once("open",c),i.once("error",u)})}var my=new Set(["session/attach","session/detach","session/prompt","session/cancel","session/close","session/delete","hydra-acp/session/delete","session/set_model","session/set_mode","session/set_config_option","_session/steering","hydra-acp/prompt/cancel","hydra-acp/prompt/update","hydra-acp/prompt/amend","hydra-acp/session/tool_content","hydra-acp/session/force_cancel"]);function hy(s){return my.has(s)}function hu(s,e,t,n){let r=[],o=a=>{for(let d of r)d(a)},i=(a,d)=>{e.handleLocalMessage(a,d,{connection:t.connection,clientId:n}).then(c=>c?s.send(c):void 0).catch(()=>{})};return s.onMessage(a=>{if("method"in a&&hy(a.method)){let d=a.params,c=typeof d?.sessionId=="string"?d.sessionId:void 0;if(c){if(dt(c)){i(a,c);return}if(a.method==="session/attach"){let u="id"in a;e.resolveLocalMiss(c).then(l=>{if(l.ok){i(a,l.foreignId);return}if(l.ambiguous&&u){s.send(Ln(a.id,E.SessionNotFound,`Session "${c}" exists on more than one remote (${l.ambiguous.join(", ")}). Address it as "<remote>:${c}".`));return}o(a)});return}}}o(a)}),{send:a=>s.send(a),onMessage:a=>r.push(a),onClose:a=>s.onClose(a),close:()=>s.close()}}var er=class{constructor(e,t=wy,n){this.store=e;this.dial=t;this.localMiss=n}store;dial;localMiss;attachments=new Map;async resolveLocalMiss(e){if(!this.localMiss)return{ok:!1};if(await this.localMiss.resolvesLocally(e))return{ok:!1};let t=this.localMiss.cache.findByLocalId(e);return t.length===0?{ok:!1}:t.length>1?{ok:!1,ambiguous:t.map(n=>n.name)}:{ok:!0,foreignId:qe(t[0])}}async handleLocalMessage(e,t,n){let r="id"in e,o=r?e.id:void 0,i=dt(t);if(!i)return r?Ln(o,E.SessionNotFound,`not a federated session id: ${t}`):void 0;let a=mu(n.clientId,t),d={...e.params,sessionId:i.localId};if(e.method==="session/attach"){let u=this.store.get(i.name);if(!u)return r?Ln(o,E.SessionNotFound,`No remote named "${i.name}". Run \`hydra remote add\` first.`):void 0;let l=this.attachments.get(a);l&&(this.attachments.delete(a),l.peerConnection.close().catch(()=>{}));let f;try{f=await this.dial(u)}catch(g){return r?Ln(o,E.InternalError,`Could not reach remote "${i.name}": ${g.message}`):void 0}let m={peerConnection:f,localId:i.localId,target:n};this.wireAttachment(i.name,m);let h;try{h=await f.request("session/attach",d)}catch(g){return f.close().catch(()=>{}),r?Zo(o,g):void 0}this.attachments.set(a,m);let p=h&&typeof h.sessionId=="string"?{...h,sessionId:t}:h;return r?{jsonrpc:"2.0",id:o,result:p}:void 0}let c=this.attachments.get(a);if(!c)return r?Ln(o,E.SessionNotFound,`"${t}" is not attached through this daemon.`):void 0;if(e.method==="session/detach"){let u,l;try{u=await c.peerConnection.request("session/detach",d)}catch(f){l=f}return this.attachments.delete(a),c.peerConnection.close().catch(()=>{}),l?r?Zo(o,l):void 0:r?{jsonrpc:"2.0",id:o,result:u??{}}:void 0}if(r)try{let u=await c.peerConnection.request(e.method,d);return{jsonrpc:"2.0",id:o,result:u}}catch(u){return Zo(o,u)}await c.peerConnection.notify(e.method,d).catch(()=>{})}detachClient(e){for(let[t,n]of[...this.attachments.entries()])n.target.clientId===e&&(this.attachments.delete(t),n.peerConnection.request("session/detach",{sessionId:n.localId}).catch(()=>{}),n.peerConnection.close().catch(()=>{}))}wireAttachment(e,t){let{peerConnection:n,localId:r,target:o}=t,i=qe({name:e,localId:r}),a=()=>{this.attachments.delete(mu(o.clientId,i))};n.onAnyNotification((d,c)=>{let u=d;!u||u.sessionId!==r||(c==="hydra-acp/session/closed"&&a(),o.connection.notify(c,{...u,sessionId:i}).catch(()=>{}))}),n.onRequest("hydra-acp/session/request_permission",async d=>{let c=d;if(!c||c.sessionId!==r)throw{code:E.MethodNotFound,message:"unexpected sessionId"};return o.connection.request("hydra-acp/session/request_permission",{...c,sessionId:i})}),n.onClose(()=>{a(),o.connection.notify("hydra-acp/session/closed",{sessionId:i}).catch(()=>{})})}};function mu(s,e){return`${s} ${e}`}function Ln(s,e,t){return{jsonrpc:"2.0",id:s,error:{code:e,message:t}}}function Zo(s,e){let t=e,n=typeof t?.code=="number"?t.code:E.InternalError,r=typeof t?.message=="string"?t.message:String(e??"forward failed");return{jsonrpc:"2.0",id:s,error:{code:n,message:r,...t?.data!==void 0?{data:t.data}:{}}}}var yy=1e4;async function wy(s){let t=`${ke(s.host)?"ws":"wss"}://${s.host}:${s.port}/acp`,n=await gu(t,["acp.v1",`hydra-acp-token.${s.token}`],yy);return new Be(Zs(n))}var ky=3e4,vy=5e3,tr=class{constructor(e,t={}){this.store=e;this.opts=t}store;opts;snapshots=new Map;timer;start(){this.timer||(this.checkAll(),this.timer=setInterval(()=>{this.checkAll()},this.opts.intervalMs??ky),this.timer.unref?.())}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}get(e){return this.snapshots.get(e)}markOk(e,t){this.snapshots.set(e,{status:"ok",checkedAt:new Date().toISOString(),...t?{system:t}:{}})}forget(e){this.snapshots.delete(e)}async checkAll(){let e=this.opts.fetchImpl??fetch;await Promise.allSettled(this.store.list().map(async t=>{let n=this.store.get(t.name);if(!n)return;let r=new AbortController,o=setTimeout(()=>r.abort(),vy);try{let i=await Qs({host:n.host,port:n.port,token:n.token,fetchImpl:e,signal:r.signal});if(i.kind==="ok"){this.snapshots.set(t.name,{status:"ok",checkedAt:new Date().toISOString(),...i.system?{system:i.system}:{}});return}if(i.kind==="unauthorized"){this.snapshots.set(t.name,{status:"unauthorized",checkedAt:new Date().toISOString()});return}if(i.kind==="error")throw new Error(i.message);let d=`${ke(n.host)?"http":"https"}://${n.host}:${n.port}/v1/auth/verify`,c=await e(d,{headers:{Authorization:`Bearer ${n.token}`},signal:r.signal});this.snapshots.set(t.name,{status:c.ok?"ok":"unauthorized",checkedAt:new Date().toISOString()})}catch(i){this.snapshots.set(t.name,{status:"unreachable",checkedAt:new Date().toISOString(),error:i.message})}finally{clearTimeout(o)}}))}};Hn();import{z as yu}from"zod";var by=yu.object({sessionLabel:yu.string().min(1).max(256)});function wu(s,e){s.post("/v1/process-tokens",async(t,n)=>{if(t.authIdentity!=="service")return n.code(403).send({error:"Requires the service token"});let r;try{r=by.parse(t.body)}catch{return n.code(400).send({error:"Invalid request body"})}let o=e.processRegistry.mint(r.sessionLabel,"script");return n.code(201).send({token:o})}),s.delete("/v1/process-tokens/:sessionLabel",async(t,n)=>t.authIdentity!=="service"?n.code(403).send({error:"Requires the service token"}):(e.processRegistry.revoke(t.params.sessionLabel),n.code(204).send()))}import{nanoid as ei}from"nanoid";import{randomBytes as Iu}from"crypto";import*as Au from"os";import*as Cu from"path";var Sy=200;function Iy(s){if(!s||typeof s!="object")return;let e=s._meta;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e[ce];if(!t||typeof t!="object"||Array.isArray(t))return;let n=t.sentBy;if(!n||typeof n!="object"||Array.isArray(n))return;let r=n,o={};if(typeof r.sessionId=="string"&&r.sessionId.length>0&&(o.sessionId=r.sessionId),typeof r.label=="string"&&r.label.length>0&&(o.label=r.label.slice(0,Sy)),r.awaiting===!0&&(o.awaiting=!0),!(o.sessionId===void 0&&o.label===void 0))return o}async function ku(s,e,t){let n=Iy(s);if(!n)return;let r={};if(n.label!==void 0&&(r.fromLabel=n.label),n.awaiting===!0&&(r.awaiting=!0),n.sessionId!==void 0){let o=await e.resolveCanonicalId(n.sessionId)??n.sessionId,i=await e.getOne(o);if(i){r.fromSession=o,i.title&&(r.fromSessionTitle=i.title);let a=e.get(o)?.currentPromptDepth;r.depth=(a??0)+1}else t?.(n.sessionId)}if(!(r.fromSession===void 0&&r.fromLabel===void 0))return r}var Un=new Map;function vu(s,e){let t=Un.get(s);t||(t=new Set,Un.set(s,t)),t.add(e);let n=!1;return()=>{if(n)return;n=!0;let r=Un.get(s);r&&(r.delete(e),r.size===0&&Un.delete(s))}}function bu(s,e){if(s===e)return!0;let t=new Set,n=[e];for(;n.length>0;){let r=n.pop();if(t.has(r))continue;t.add(r);let o=Un.get(r);if(o){if(o.has(s))return!0;for(let i of o)n.push(i)}}return!1}function N(s,e,t){let n=new Error(e);return n.code=s,t!==void 0&&(n.data=t),n}function Ey(s){if(!s||typeof s!="object")return 512;let n=s.params?.update;if(!n)return 512;let r=512,o=n.content;if(typeof o=="string")r+=o.length;else if(o&&typeof o=="object"){let a=o;typeof a.text=="string"&&(r+=a.text.length),typeof a.data=="string"&&(r+=a.data.length)}let i=n.toolCall;if(i&&(typeof i.rawInput=="string"?r+=i.rawInput.length:i.rawInput&&typeof i.rawInput=="object"&&(r+=256),typeof i.rawOutput=="string"?r+=i.rawOutput.length:i.rawOutput&&typeof i.rawOutput=="object"&&(r+=256),Array.isArray(i.content)))for(let a of i.content){if(!a||typeof a!="object")continue;let d=a;if(typeof d.text=="string"&&(r+=d.text.length),d.content&&typeof d.content=="object"){let c=d.content;typeof c.text=="string"&&(r+=c.text.length)}}return r}function Re(s,e,t){let n=s.get(e);if(!n)throw N(E.SessionNotFound,t??`session ${e} not found`);return n}async function Et(s,e){let t=Yt(s),n,r,o;typeof e.summarizedThroughEntry=="number"&&e.summarizedThroughEntry>0&&s.mcpTokenRegistry!==void 0&&s.getDaemonOrigin!==void 0&&(n=Iu(32).toString("hex"),r=s.mcpTokenRegistry.reserve(n),o={name:"hydra-acp-recall",type:"http",url:`${s.getDaemonOrigin()}/mcp/hydra-acp-recall`,headers:[{name:"Authorization",value:`Bearer ${n}`}]});let a=[...t?.descriptors??[],...o!==void 0?[o]:[]],d=Bo({baselineMcpServers:void 0,stdinEnabled:!1,deps:s}),c;try{c=await s.manager.resurrect({...e,mcpServers:a,...d?{mintMcpServersForSwap:d}:{}})}catch(u){throw t!==void 0&&t.abandon(u instanceof Error?u:void 0),r!==void 0&&r.abandon(u instanceof Error?u:void 0),u}if(t!==void 0&&t.bindToSession(c),n!==void 0&&r!==void 0&&s.mcpTokenRegistry!==void 0){let u=n,l=s.mcpTokenRegistry;r.complete(c),c.onClose(()=>{l.unbind(u)})}return jy(c,s),xu(c.sessionId,s),c}function Ru(s,e){s.get("/acp",{websocket:!0},async(t,n)=>{let r=cc({headers:n.headers,url:n.url});if(!r||!await e.validator.validate(r)){t.close(4401,"Unauthorized");return}let o=e.processRegistry?.resolve(r),i=`hydra_client_${ei(12)}`,a=Zs(t),d={},c=e.foreignSessions?hu(a,e.foreignSessions,d,i):a,u=new Be(c);d.connection=u;let l={clientId:i,processIdentity:o,attached:new Map};u.onClose(()=>{for(let h of l.attached.values())e.manager.get(h.sessionId)?.detach(h.clientId);l.attached.clear(),e.foreignSessions?.detachClient(i)});let f=(h,p)=>{if(l.attached.get(h)?.readonly)throw N(E.PermissionDenied,`${p} not permitted on a read-only attachment`)};if(u.onRequest("initialize",async h=>{let p=Qi.parse(h??{});p.clientInfo?.name&&(l.clientInfo={name:p.clientInfo.name,...p.clientInfo.version!==void 0?{version:p.clientInfo.version}:{}});let g=p.clientInfo?.version;return g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g)),Dy()}),o&&e.extensionCommands){let h=e.extensionCommands;u.onRequest("hydra-acp/commands/register",async p=>{let g=p??{},w=Array.isArray(g.commands)?g.commands.map(y=>{if(!y||typeof y!="object")return;let k=y;if(typeof k.verb!="string")return;let b={verb:k.verb};return typeof k.argsHint=="string"&&(b.argsHint=k.argsHint),typeof k.description=="string"&&(b.description=k.description),b}).filter(y=>y!==void 0):[];return h.register(o.name,u,w),{ok:!0,registered:w.length}}),u.onClose(()=>{h.clear(o.name)})}if(o&&e.extensionMcp){let h=e.extensionMcp;u.onRequest("hydra-acp/mcp_tools/register",async g=>{let w=g??{},y=typeof w.instructions=="string"?w.instructions:void 0,k=Array.isArray(w.tools)?w.tools.map(b=>{if(!b||typeof b!="object")return;let I=b;if(typeof I.name!="string"||I.name.length===0||typeof I.description!="string"||I.inputSchema===null||typeof I.inputSchema!="object")return;let v={name:I.name,description:I.description,inputSchema:I.inputSchema};return I.outputSchema!==null&&typeof I.outputSchema=="object"&&(v.outputSchema=I.outputSchema),v}).filter(b=>b!==void 0):[];if(k.length===0)throw new Error("register_mcp_tools requires at least one tool");return h.register(o.name,u,y,k),{ok:!0,registered:k.length}});let p=g=>{let w=g??{};if(typeof w.sessionId!="string"||w.sessionId.length===0)throw N(E.InvalidParams,"sessionId is required");return w.sessionId};if(u.onRequest("hydra-acp/session/extension_state/get",async g=>{let w=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(!e.manager)throw N(E.InternalError,"manager not wired");return{value:await e.manager.getExtensionStateKey(w,o.name,y.key)??null}}),u.onRequest("hydra-acp/session/extension_state/list",async g=>{let w=p(g);if(!e.manager)throw N(E.InternalError,"manager not wired");return{state:await e.manager.getExtensionState(w,o.name)}}),u.onRequest("hydra-acp/session/extension_state/set",async g=>{let w=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(y.value===void 0)throw N(E.InvalidParams,"value is required (use extension_state/delete to remove)");if(!e.manager)throw N(E.InternalError,"manager not wired");try{await e.manager.setExtensionStateKey(w,o.name,y.key,y.value)}catch(k){throw N(E.InvalidParams,k.message)}return{ok:!0}}),u.onRequest("hydra-acp/session/extension_state/delete",async g=>{let w=p(g),y=g??{};if(typeof y.key!="string"||y.key.length===0)throw N(E.InvalidParams,"key is required");if(!e.manager)throw N(E.InternalError,"manager not wired");return await e.manager.deleteExtensionStateKey(w,o.name,y.key),{ok:!0}}),e.extensionMcpControls){let g=e.extensionMcpControls;u.onRequest("hydra-acp/mcp_tools/refresh_session",async w=>{let y=w??{};if(typeof y.sessionId!="string"||y.sessionId.length===0)throw N(E.InvalidParams,"refresh_session requires sessionId");return await g.notifyToolListChanged(y.sessionId,o.name),{ok:!0}})}u.onClose(()=>{h.clear(o.name)})}if(o?.kind==="transformer"){u.onRequest("hydra-acp/transformer/initialize",async p=>{let g=p??{},w=Array.isArray(g.intercepts)?g.intercepts.filter(y=>typeof y=="string"):[];if(e.transformers&&(e.transformers.registerConnection(o.name,u,w),e.manager?.defaultTransformers.includes(o.name))){let y=e.transformers.resolveChain([o.name])[0];if(y)for(let k of e.manager.liveSessions())k.addTransformer(y)}return{ack:!0}}),u.onClose(()=>{e.transformers?.deregisterConnection(o.name)}),u.onRequest("hydra-acp/message/emit",async p=>{let g=p??{},w=typeof g.sessionId=="string"?g.sessionId:void 0,y=typeof g.method=="string"?g.method:void 0,k=g.envelope,b=g.route;if(!w)throw N(-32602,"emit_message requires sessionId");if(!y&&b!=="client_broadcast")throw N(-32602,"emit_message requires method");let I=Re(e.manager,w),v=typeof g.respondsTo=="string"?g.respondsTo:void 0;if(v)return I.dischargeClaim(v,k),{ok:!0};if(b==="chain")return{ok:!0,response:await I.emitToChain(o.name,y,k)};if(b==="queue"){if(y!=="session/prompt")throw N(-32602,'route "queue" only supports method "session/prompt"');return{ok:!0,response:await I.emitToQueue(o.name,k)}}if(b==="daemon")return{ok:!0,response:await I.emitToChain(o.name,y,k)};if(b==="client_broadcast"){if(!k||typeof k!="object")throw N(-32602,"client_broadcast requires an envelope object");return I.broadcastClientUpdate(k),{ok:!0}}throw N(-32602,`unsupported route: ${JSON.stringify(b)}`)}),u.onRequest("hydra-acp/session/request_permission",async p=>{let g=p??{},w=typeof g.sessionId=="string"?g.sessionId:void 0;if(!w)throw N(-32602,"hydra-acp/session/request_permission requires sessionId");return Re(e.manager,w).requestPermissionFromClients(g)}),u.onRequest("hydra-acp/transformer/attach",async p=>$y(p,o.name,e)),u.onRequest("hydra-acp/child_session/spawn",async p=>{let g=p??{},w=typeof g.agentId=="string"?g.agentId:void 0,y=typeof g.cwd=="string"?g.cwd:void 0,k=typeof g.parentSessionId=="string"?g.parentSessionId:void 0,b=rt(g._meta??void 0),I=b.title,v=b.model,A=b.workspace;if(!y&&k){let W=e.manager.get(k);W&&(y=W.cwd)}if(!y)throw N(-32602,"child_session/spawn requires cwd (or a parentSessionId pointing at a live session whose cwd we can inherit)");let C=await on(y),R=w??C.agentId??e.defaultAgent,T=await e.registry?.getAgent(R),_=cn(C.configDefaults,T??{id:R})?.value,U=v??_?.model,J=typeof g.interactive=="boolean"?g.interactive:!1,M=await e.manager.create({agentId:R,cwd:y,parentSessionId:k,interactive:J,transformChain:[],title:I,model:U,configDefaults:_,...A!==void 0?{workspace:A}:{}});return{childSessionId:M.sessionId,...M.workspace!==void 0||M.workspaceError!==void 0?{_meta:{[ce]:{...M.workspace!==void 0?{workspaceInfo:M.workspace}:{},...M.workspaceError!==void 0?{workspaceError:M.workspaceError}:{}}}}:{}}}),u.onRequest("hydra-acp/session/fork",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.InvalidParams,"fork_session requires sessionId");let w=typeof g.forkAt=="string"?g.forkAt:void 0,y=typeof g.cwd=="string"?g.cwd:void 0,k=typeof g.agentId=="string"?g.agentId:void 0,b=typeof g.mode=="string"&&(g.mode==="verbatim"||g.mode==="synthesis")?g.mode:void 0,I=typeof g.model=="string"&&g.model.length>0?g.model:void 0,v=await e.manager.forkSession(g.sessionId,{...w!==void 0?{forkAt:w}:{},...y!==void 0?{cwd:y}:{},...k!==void 0?{agentId:k}:{},...b!==void 0?{mode:b}:{},...I!==void 0?{model:I}:{}}),A=e.manager.get(v.sessionId);if(!A){let T=await e.manager.loadFromDisk(v.sessionId);if(!T)throw N(E.InternalError,`fork ${v.sessionId} vanished before it could be attached`);A=await Et(e,{...T,onInstallProgress:nr(u)})}Zt(l,A,A.sessionId);let C=gt(u,A,l),{entries:R}=await A.attach(C,"full");l.attached.set(A.sessionId,{sessionId:A.sessionId,clientId:C.clientId,readonly:!1});for(let T of R){if(u.isClosed())break;await u.notify(T.method,Ue(Le(T.params,T.recordedAt),T.seq)).catch(()=>{})}return{...v,sessionId:A.sessionId}}),u.onRequest("session/fork",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.InvalidParams,"session/fork requires sessionId");let w=typeof g.cwd=="string"?g.cwd:void 0,y=await e.manager.forkSession(g.sessionId,{...w!==void 0?{cwd:w}:{},mode:"verbatim"}),k=e.manager.get(y.sessionId);if(!k){let v=await e.manager.loadFromDisk(y.sessionId);if(!v)throw N(E.InternalError,`fork ${y.sessionId} vanished before it could be attached`);k=await Et(e,{...v,onInstallProgress:nr(u)})}Zt(l,k,k.sessionId);let b=gt(u,k,l),{entries:I}=await k.attach(b,"full");l.attached.set(k.sessionId,{sessionId:k.sessionId,clientId:b.clientId,readonly:!1});for(let v of I){if(u.isClosed())break;await u.notify(v.method,Ue(Le(v.params,v.recordedAt),v.seq)).catch(()=>{})}return{sessionId:k.sessionId}});let h=async(p,g)=>{let w=p??{};if(typeof w.sessionId!="string")throw N(E.InvalidParams,`${g} requires sessionId`);let y=await e.manager.resolveCanonicalId(w.sessionId)??w.sessionId,k=e.manager.get(y);if(k)return await k.close({deleteRecord:!0,by:`session/delete ${l.clientId}`}),await e.manager.waitForDeletion(y),await e.manager.hasRecord(y)&&await e.manager.deleteRecord(y),{id:y,existed:!0};let b=await e.manager.deleteRecord(y);return{id:y,existed:b}};u.onRequest("session/delete",async p=>(await h(p,"session/delete"),{})),u.onRequest("session/close",async p=>{let g=p??{};if(typeof g.sessionId!="string")throw N(E.InvalidParams,"session/close requires sessionId");f(g.sessionId,"session/close");let w=await e.manager.resolveCanonicalId(g.sessionId)??g.sessionId,y=e.manager.get(w);if(y)return await y.close({deleteRecord:!1,by:`session/close ${l.clientId}`+(l.processIdentity?` (${l.processIdentity.name})`:"")}),{};if(await e.manager.hasRecord(w))return{};throw N(E.SessionNotFound,`session ${w} not found`)}),u.onRequest("hydra-acp/session/delete",async p=>{let{id:g,existed:w}=await h(p,"hydra-acp/session/delete");if(!w)throw N(E.SessionNotFound,`session ${g} not found`);return{deleted:!0,sessionId:g}}),u.onRequest("hydra-acp/child_session/await",async p=>{let g=p??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0,y=g.until==="idle"?"idle":"turn_complete",k=typeof g.timeoutMs=="number"?Math.min(g.timeoutMs,18e5):3e5;if(!w)throw N(-32602,"await_child requires childSessionId");let b=Re(e.manager,w,`child session ${w} not found`);return new Promise(I=>{let C=[],R=[],T=0,_=!1,U,J,M=!1,W=()=>{M||(M=!0,clearTimeout(q),U?.(),J?.(),I(_?{entries:C,truncated:!0}:{entries:C}))};U=b.onBroadcast(ee=>{let me=Ey(ee);for(C.push(ee),R.push(me),T+=me;C.length>0&&(C.length>1e3||T>1048576);)C.shift(),T-=R.shift()??0,_=!0;y==="turn_complete"&&ee.params?.update?.sessionUpdate==="turn_complete"&&W()});let q=setTimeout(W,k);typeof q.unref=="function"&&q.unref(),J=b.onClose(()=>W())})}),u.onRequest("hydra-acp/child_session/close",async p=>{let g=p??{},w=typeof g.childSessionId=="string"?g.childSessionId:void 0;if(!w)throw N(-32602,"close_child_session requires childSessionId");let y=e.manager.get(w);return y&&await y.close({deleteRecord:!1,by:`child_session/close ${l.clientId}`}),{ok:!0}}),u.onRequest("hydra-acp/attention/set",async p=>Oy(p,o.name,e)),u.onRequest("hydra-acp/attention/clear",async p=>Fy(p,o.name,e)),u.onRequest("hydra-acp/connection/keep_alive",async p=>{let g=p??{},w=typeof g.token=="string"?g.token:void 0,y=typeof g.sessionId=="string"?g.sessionId:void 0,k=typeof g.estimatedRemainingMs=="number"?g.estimatedRemainingMs:void 0;return w&&y&&e.manager.get(y)?.keepAliveClaim(w,k),{ok:!0}})}u.onRequest("hydra-acp/session/tool_content",async h=>{let p=h??{};if(typeof p.sessionId!="string"||typeof p.hash!="string")throw N(E.InvalidParams,"hydra-acp/session/tool_content requires sessionId and hash");let g=await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,w=await e.manager.loadToolBlob(g,p.hash);if(w===null)throw N(E.SessionNotFound,"tool content not found");return{content:w}}),u.onRequest("authenticate",async h=>Ty(h,e)),u.onRequest("logout",async h=>Py(h,e)),u.onRequest("session/new",async h=>{let p=Yi.parse(h),g=rt(h?._meta),w=Array.isArray(g.transformers)&&g.transformers.every(Z=>typeof Z=="string")?g.transformers:e.manager.defaultTransformers??[],y=e.transformers?.resolveChain(w)??[],k=await on(p.cwd),b=g.agentId??k.agentId??e.defaultAgent,I=await e.registry?.getAgent(b),v=cn(k.configDefaults,I??{id:b})?.value,A,C,R=p.mcpServers;if(g.mcpStdin===!0&&e.mcpTokenRegistry!==void 0&&e.getDaemonOrigin!==void 0){A=Iu(32).toString("hex"),C=e.mcpTokenRegistry.reserve(A);let Me={name:"hydra-acp-stdin",type:"http",url:`${e.getDaemonOrigin()}/mcp/hydra-acp-stdin`,headers:[{name:"Authorization",value:`Bearer ${A}`}]};R=[...p.mcpServers??[],Me]}let T,_,U=Yt(e);U!==void 0&&(R=[...R??[],...U.descriptors]);let J=Bo({baselineMcpServers:p.mcpServers,stdinEnabled:g.mcpStdin===!0,deps:e}),M;try{M=await e.manager.create({cwd:p.cwd,agentId:b,mcpServers:R,title:g.title,agentArgs:g.agentArgs,model:g.model??v?.model,configDefaults:v,onInstallProgress:nr(u),transformChain:y,originatingClient:l.clientInfo,...g.interactive!==void 0?{interactive:g.interactive}:{},...g.env!==void 0?{forwardedEnv:g.env}:{},...g.workspace!==void 0?{workspace:g.workspace}:{},...J?{mintMcpServersForSwap:J}:{}})}catch(Z){throw C!==void 0&&C.abandon(Z instanceof Error?Z:void 0),_!==void 0&&_.abandon(Z instanceof Error?Z:void 0),U!==void 0&&U.abandon(Z instanceof Error?Z:void 0),Z}if(A!==void 0&&C!==void 0&&e.mcpTokenRegistry!==void 0){let Z=A,Me=e.mcpTokenRegistry;C.complete(M),M.onClose(()=>{Me.unbind(Z)})}if(T!==void 0&&_!==void 0&&e.mcpTokenRegistry!==void 0){let Z=T,Me=e.mcpTokenRegistry;_.complete(M),M.onClose(()=>{Me.unbind(Z)})}U!==void 0&&U.bindToSession(M),xu(M.sessionId,e);let W,q;try{Zt(l,M,M.sessionId),W=gt(u,M,l),{entries:q}=await M.attach(W,"full")}catch(Z){throw await M.close({deleteRecord:!1,by:"session/new attach-failed"}).catch(()=>{}),Z}l.attached.set(M.sessionId,{sessionId:M.sessionId,clientId:W.clientId,readonly:!1}),setImmediate(()=>{(async()=>{for(let Z of q){if(u.isClosed())break;await u.notify(Z.method,Ue(Le(Z.params,Z.recordedAt),Z.seq)).catch(()=>{})}})()});let ee=sr(M),me=rr(M);return{sessionId:M.sessionId,...ee?{modes:ee}:{},...me?{models:me}:{},configOptions:M.buildConfigOptions(),_meta:or(e.manager,M,{clientId:W.clientId})}}),u.onRequest("session/attach",async h=>{let p=Zi.parse(h),g=p.clientInfo?.version;g&&o&&(o.kind==="extension"?e.onExtensionVersion?.(o.name,g):e.onTransformerVersion?.(o.name,g));let w=rt(p._meta),y=w.resume,k=w.readonly===!0,b=w.env;s.log.info(`session/attach sessionId=${p.sessionId} hasResumeHints=${!!y} readonly=${k}`);let I=y?p.sessionId:await e.manager.resolveCanonicalId(p.sessionId)??p.sessionId,v=e.manager.get(I);if(!v&&k){let M=await e.manager.loadFromDisk(I);if(!M)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);let W=await e.manager.loadHistory(I,{...w.historyLimit!==void 0?{maxEntries:w.historyLimit}:{}}),q=p.clientId??`cli_${ei(8)}`;l.attached.set(M.hydraSessionId,{sessionId:M.hydraSessionId,clientId:q,readonly:!0}),s.log.info(`session/attach OK (viewer) sessionId=${M.hydraSessionId} clientId=${q} attachedCount=${l.attached.size} replayed=${W.length}`);for(let ee of W)await u.notify(ee.method,Ue(Le(ee.params,ee.recordedAt),ee.seq)).catch(()=>{});return{sessionId:M.hydraSessionId,clientId:q,connectedClients:[q],historyPolicy:"full",replayed:W.length,_meta:Ny(M)}}let A=!v;if(!v){let M=await e.manager.loadFromDisk(I),W=await My(I,y,M?.upstreamSessionId,e.manager);W.kind==="ignore"&&s.log.warn(W.logMessage);let q=M;if(y&&W.kind==="honor"&&(q={...M,hydraSessionId:p.sessionId,upstreamSessionId:y.upstreamSessionId,agentId:y.agentId,cwd:M?.workspace?.path??y.cwd,...y.title!==void 0?{title:y.title}:{},...y.agentArgs!==void 0?{agentArgs:y.agentArgs}:{}}),!q)throw N(E.SessionNotFound,`session ${p.sessionId} not found and no resume hints provided`);if(await e.manager.isTombstoned(q.agentId,q.upstreamSessionId))throw N(E.SessionNotFound,`session ${p.sessionId} was deleted`);let ee=q.originatingClient?q:{...q,originatingClient:l.clientInfo},me=b!==void 0?{...ee,forwardedEnv:b}:ee;v=await Et(e,{...me,onInstallProgress:nr(u)})}Zt(l,v,v.sessionId);let C=gt(u,v,l,p.clientInfo,p.clientId),R=w.replayMode==="drip",{entries:T,appliedPolicy:_}=await v.attach(C,p.historyPolicy,{afterMessageId:p.afterMessageId,afterSeq:p.afterSeq,raw:R,...w.historyLimit!==void 0?{historyLimit:w.historyLimit}:{},...w.toolContent!==void 0?{toolContent:w.toolContent}:{}});if(l.attached.set(v.sessionId,{sessionId:v.sessionId,clientId:C.clientId,readonly:k}),b!==void 0&&await e.manager.setForwardedEnv(v.sessionId,b).catch(()=>{}),s.log.info(`session/attach OK sessionId=${v.sessionId} clientId=${C.clientId} attachedCount=${l.attached.size} requestedPolicy=${p.historyPolicy} appliedPolicy=${_} replayed=${T.length} readonly=${k}${R?" replayMode=drip":""}`),R){let M=w.dripSpeed&&w.dripSpeed>0?w.dripSpeed:1,W=750;(async()=>{let q=null;for(let ee of T){let me=typeof ee.recordedAt=="number"?ee.recordedAt:null;if(q!==null&&me!==null){let Z=Math.min(W,Math.max(0,(me-q)/M));Z>0&&await new Promise(Me=>setTimeout(Me,Z))}me!==null&&(q=me);try{await u.notify(ee.method,Ue(Le(ee.params,me??void 0),ee.seq))}catch{return}}})()}else for(let M=0;M<T.length&&!u.isClosed();M++){let W=T[M],q=u.notify(W.method,Ue(Le(W.params,W.recordedAt),W.seq)).catch(()=>{});(M+1)%200===0&&await q}v.replayPendingPermissions(C);let U=sr(v),J=rr(v);return{sessionId:v.sessionId,clientId:C.clientId,connectedClients:v.connectedClients(C.clientId),historyPolicy:_,replayed:T.length,...U?{modes:U}:{},...J?{models:J}:{},configOptions:v.buildConfigOptions(),_meta:or(e.manager,v,{resurrected:A})}}),u.onRequest("session/detach",async h=>{let p=ea.parse(h),g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"client not attached to that session");let w=e.manager.get(p.sessionId);return w?.detach(g.clientId),l.attached.delete(p.sessionId),w&&e.manager.reapIfOrphanedNonInteractive(p.sessionId),{sessionId:p.sessionId,_meta:{[ce]:{detachStatus:"detached"}}}}),u.onRequest("session/list",async h=>{let p=ta.parse(h??{});return{sessions:(await e.manager.list({cwd:p.cwd})).filter(k=>k.originatingClient?.name!==vs).map(na)}}),u.onRequest("hydra-acp/agents/list",async()=>{if(!e.registry)throw N(E.InternalError,"agent registry unavailable");return Nt(e.registry)}),u.onRequest("hydra-acp/agents/auth_methods",async h=>{let p=h??{};if(typeof p.agentId!="string"||p.agentId.length===0)throw N(E.InvalidParams,"hydra-acp/agents/auth_methods requires a non-empty agentId string");return{authMethods:(await e.manager.bootstrapAgentForAuth(p.agentId)).authMethods??[]}}),u.onRequest("session/prompt",async h=>{let p=sa.parse(h);f(p.sessionId,"session/prompt");let g=await ku(p,e.manager,b=>{s.log.warn(`session/prompt: dropping unknown sentBy.sessionId=${b} sessionId=${p.sessionId}`)});if(g?.fromSession!==void 0){if((g.depth??0)>3)throw s.log.warn(`session/prompt: refusing depth ${g.depth} chain from ${g.fromSession} to ${p.sessionId}`),N(E.InvalidRequest,`message chain too deep (${g.depth} hops, max ${3}): refusing to continue a session-to-session loop`);if(g.awaiting===!0&&bu(g.fromSession,p.sessionId))throw s.log.warn(`session/prompt: refusing deadlock ${g.fromSession} -> ${p.sessionId}`),N(E.InvalidRequest,`would deadlock: ${p.sessionId} is already blocked waiting on ${g.fromSession}. Send with --no-wait, or let the other turn finish first.`)}let w=l.attached.get(p.sessionId);if(!w)throw s.log.warn(`session/prompt rejected: not attached sessionId=${p.sessionId} attachedKeys=[${[...l.attached.keys()].join(",")}]`),N(E.SessionNotFound,"not attached to session");let y=e.manager.get(p.sessionId);if(!y){let b=await e.manager.loadFromDisk(p.sessionId);if(!b)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);s.log.info(`session/prompt auto-resurrecting cold sessionId=${p.sessionId}`),y=await Et(e,b);let I=gt(u,y,l,void 0,w.clientId);await y.attach(I,"none")}let k=g?.awaiting===!0&&g.fromSession!==void 0?vu(g.fromSession,p.sessionId):void 0;try{return await y.prompt(w.clientId,p,g)}finally{k?.()}});let m=h=>{let p;try{p=Yn.parse(h)}catch(y){s.log.warn(`session/cancel: invalid params: ${y.message}`);return}let g=l.attached.get(p.sessionId);if(!g)return;if(g.readonly){s.log.warn(`session/cancel dropped (readonly attachment) sessionId=${p.sessionId}`);return}let w=e.manager.get(p.sessionId);w&&w.cancel(g.clientId).catch(y=>{s.log.warn(`session/cancel for ${p.sessionId}: ${y.message}`)})};u.onNotification("session/cancel",m),u.onRequest("session/cancel",async h=>{let p=Yn.parse(h);return f(p.sessionId,"session/cancel"),m(h),null}),u.onRequest("hydra-acp/prompt/cancel",async h=>{let p=oa.parse(h);return f(p.sessionId,"hydra-acp/prompt/cancel"),Re(e.manager,p.sessionId).cancelQueuedPrompt(p.messageId)}),u.onRequest("hydra-acp/session/force_cancel",async h=>{let p=Yn.parse(h);return f(p.sessionId,"hydra-acp/session/force_cancel"),Re(e.manager,p.sessionId).forceCancel()}),u.onRequest("hydra-acp/prompt/update",async h=>{let p=ia.parse(h);return f(p.sessionId,"hydra-acp/prompt/update"),Re(e.manager,p.sessionId).updateQueuedPrompt(p.messageId,p.prompt)}),u.onRequest("hydra-acp/prompt/amend",async h=>{let p=aa.parse(h);f(p.sessionId,"hydra-acp/prompt/amend");let g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"not attached to session");return Re(e.manager,p.sessionId).amendPrompt(g.clientId,p)}),u.onRequest("_session/steering",async h=>{let p=da.parse(h);f(p.sessionId,"_session/steering");let g=l.attached.get(p.sessionId);if(!g)throw N(E.SessionNotFound,"not attached to session");let w=e.manager.get(p.sessionId);if(!w){let y=await e.manager.loadFromDisk(p.sessionId);if(!y)throw N(E.SessionNotFound,`session ${p.sessionId} not found`);w=await Et(e,y);let k=gt(u,w,l,void 0,g.clientId);await w.attach(k,"none")}return w.steer(g.clientId,p)}),u.onRequest("session/resume",async h=>{let p=h??{},g=typeof p.sessionId=="string"?p.sessionId:void 0;if(!g)throw N(E.InvalidParams,"session/resume requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let v=await e.manager.loadFromDisk(w);if(!v)throw N(E.SessionNotFound,`session ${g} not found in memory or on disk`);y=await Et(e,v)}Zt(l,y,y.sessionId);let k=gt(u,y,l);await y.attach(k,"pending_only"),l.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:k.clientId,readonly:!1}),y.replayPendingPermissions(k);let b=sr(y),I=rr(y);return{sessionId:y.sessionId,...b?{modes:b}:{},...I?{models:I}:{},configOptions:y.buildConfigOptions(),_meta:or(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/load",async h=>{let p=h??{},g=typeof p.sessionId=="string"?p.sessionId:void 0;if(!g)throw N(E.InvalidParams,"session/load requires sessionId");let w=await e.manager.resolveCanonicalId(g)??g,y=e.manager.get(w);if(!y){let A=await e.manager.loadFromDisk(w);if(!A)throw N(E.SessionNotFound,`session ${g} not found in memory or on disk`);y=await Et(e,A)}Zt(l,y,y.sessionId);let k=gt(u,y,l),{entries:b}=await y.attach(k,"full");l.attached.set(y.sessionId,{sessionId:y.sessionId,clientId:k.clientId,readonly:!1});for(let A of b){if(u.isClosed())break;await u.notify(A.method,Ue(Le(A.params,A.recordedAt),A.seq)).catch(()=>{})}y.replayPendingPermissions(k);let I=sr(y),v=rr(y);return{sessionId:y.sessionId,...I?{modes:I}:{},...v?{models:v}:{},configOptions:y.buildConfigOptions(),_meta:or(e.manager,y,{clientId:k.clientId})}}),u.onRequest("session/set_model",async h=>{let p=h?.sessionId;typeof p=="string"&&f(p,"session/set_model");let g=_y(h,e.manager);if(g.kind==="error")throw s.log.warn(g.logMessage),N(g.code,g.message);if(g.kind==="no_op")return s.log.warn(g.logMessage),await u.notify("session/update",{sessionId:g.sessionId,update:{sessionUpdate:"_hydra_current_model_update",currentModel:g.currentModel}}).catch(()=>{}),null;s.log.info(g.logMessage);let{modelId:w}=g,y=await g.session.forwardModelChange(w,h);return g.session.applyAgentConfigOptionResponse(y,"model"),g.session.applyModelChange(w),y}),u.onRequest("session/set_mode",async h=>{let p=h,g=p?.sessionId;if(typeof g=="string"&&f(g,"session/set_mode"),!p||typeof p.sessionId!="string")throw N(E.InvalidParams,"session/set_mode requires string sessionId");if(typeof p.modeId!="string")throw N(E.InvalidParams,"session/set_mode requires string modeId");let w=Re(e.manager,p.sessionId),y=await w.forwardRequest("session/set_mode",h);return w.applyModeChange(p.modeId),y}),u.onRequest("session/set_config_option",async h=>{let p=h,g=b=>N(E.InvalidParams,b),w=p?.sessionId;if(typeof w=="string"&&f(w,"session/set_config_option"),!p||typeof p.sessionId!="string")throw g("session/set_config_option requires string sessionId");if(typeof p.configId!="string")throw g("session/set_config_option requires string configId");if(typeof p.value!="string")throw g("session/set_config_option requires string value");let y=Re(e.manager,p.sessionId),k=y.buildConfigOptions().find(b=>b.id===p.configId);if(!k)throw g(`unknown configId ${JSON.stringify(p.configId)} for this session`);if(!k.options.some(b=>b.value===p.value))throw g(`value ${JSON.stringify(p.value)} is not valid for configId ${JSON.stringify(p.configId)}`);switch(p.configId){case"model":{if(p.value!==y.currentModel){let b=await y.forwardModelChange(p.value);y.applyAgentConfigOptionResponse(b,"model")}y.applyModelChange(p.value);break}case"mode":{p.value!==y.currentMode&&await y.forwardRequest("session/set_mode",{sessionId:p.sessionId,modeId:p.value}),y.applyModeChange(p.value);break}case"agent":{p.value!==y.agentId&&await y.setAgent(p.value);break}default:{let b=await y.forwardRequest("session/set_config_option",{sessionId:p.sessionId,configId:p.configId,value:p.value});y.applyAgentConfigOptionResponse(b,p.configId)&&y.broadcastConfigOptions()}}return{configOptions:y.buildConfigOptions()}}),u.setDefaultHandler(async(h,p)=>{let g=new Set(["hydra-acp/attention/set","hydra-acp/attention/clear"]),w=p.startsWith("session/"),y=p.startsWith("hydra-acp/");if(!w&&!y||h===null||typeof h!="object"||g.has(p))throw N(E.MethodNotFound,`Method not found: ${p}`);let k=h.sessionId;if(typeof k!="string")throw N(E.MethodNotFound,`Method not found: ${p}`);return f(k,p),Re(e.manager,k).forwardRequest(p,h)})})}async function Ty(s,e){let t=s??{};if(typeof t.methodId!="string"||t.methodId.length===0)throw N(E.InvalidParams,"authenticate requires a non-empty methodId string");let n=t.methodId,r=t._meta?.["hydra-acp"],o=typeof r?.sessionId=="string"?r.sessionId:void 0,i=typeof r?.agentId=="string"?r.agentId:void 0,a=o!==void 0?e.manager.getAgentForSession(o):void 0;if(!a||!a.isAlive()){let m=i??e.defaultAgent;a=await e.manager.bootstrapAgentForAuth(m)}let d=a.authMethods??[],c=d.find(m=>m.id===n);if(!c){let m=d.map(h=>h.id);throw N(E.InvalidParams,`authenticate: methodId ${JSON.stringify(n)} is not advertised by agent ${a.agentId}; valid: [${m.map(h=>JSON.stringify(h)).join(", ")}]`)}let u=c._meta?.type,l=(()=>{let m=c._meta?.["terminal-auth"];if(m&&typeof m=="object"&&!Array.isArray(m))return m})();if((c.type??(u==="agent"||u==="terminal"?u:l!==void 0?"terminal":"agent"))==="terminal"){let m=(k,b)=>{if(!Array.isArray(k))throw N(E.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be a string[]; got ${k===null?"null":typeof k}`);for(let I of k)if(typeof I!="string")throw N(E.InvalidParams,`authenticate: method ${JSON.stringify(n)} ${b} must be string[]; got non-string entry ${JSON.stringify(I)}`);return k},h=await e.manager.planSpawnForAgent(a.agentId),p,g;if(l?.args!==void 0){let k=typeof l.command=="string"?l.command:void 0;p=k!==void 0&&Cu.isAbsolute(k)?k:h.command,g=m(l.args,'_meta["terminal-auth"].args')}else{let k=c.args!==void 0?{raw:c.args,label:"args"}:c._meta?.args!==void 0?{raw:c._meta.args,label:"_meta.args"}:void 0,b=k!==void 0?m(k.raw,k.label):[];p=h.command,g=[...h.args,...b]}let w={};for(let[k,b]of Object.entries(process.env))typeof b=="string"&&(w[k]=b);Object.assign(w,h.env);let y=Au.homedir();return console.error(`[authenticate] terminal-auth requested agentId=${a.agentId} methodId=${n}`),{kind:"terminal",command:p,args:g,env:w,cwd:y}}try{return await a.connection.request("authenticate",{methodId:n})}catch(m){throw lt(m,a)}}async function Py(s,e){let n=(s??{})._meta?.["hydra-acp"],r=typeof n?.sessionId=="string"?n.sessionId:void 0,o=typeof n?.agentId=="string"?n.agentId:void 0,i=r!==void 0?e.manager.getAgentForSession(r):void 0;if(!i||!i.isAlive()){let a=o??e.defaultAgent;i=await e.manager.bootstrapAgentForAuth(a)}return await i.connection.request("logout",{})}function nr(s){return e=>{let t={agentId:e.agentId,version:e.version,source:e.source,phase:e.phase};"receivedBytes"in e&&(t.receivedBytes=e.receivedBytes),"totalBytes"in e&&(t.totalBytes=e.totalBytes),"packageSpec"in e&&(t.packageSpec=e.packageSpec),s.notify(ca,t).catch(()=>{})}}function sr(s){let e=s.availableModes();if(e.length===0)return;let t=e.map(r=>{let o={id:r.id,name:r.name??r.id};return r.description!==void 0&&(o.description=r.description),o});return{currentModeId:s.currentMode??e[0].id,availableModes:t}}function rr(s){let e=s.availableModels();if(e.length===0)return;let t=e.map(r=>{let o={modelId:r.modelId};return r.name!==void 0&&(o.name=r.name),r.description!==void 0&&(o.description=r.description),o});return{currentModelId:s.currentModel??e[0].modelId,availableModels:t}}async function My(s,e,t,n){return e?await n.isRetiredGeneration(s,e.upstreamSessionId)?{kind:"ignore",logMessage:`session/attach ignoring stale resume hint sessionId=${s} hintUpstream=${e.upstreamSessionId} recordUpstream=${t} (retired generation)`}:{kind:"honor"}:{kind:"none"}}function _y(s,e){if(!s||typeof s!="object")return{kind:"error",code:E.InvalidParams,message:"session/set_model requires params",logMessage:"session/set_model rejected: params not an object"};let t=s;if(typeof t.sessionId!="string")return{kind:"error",code:E.InvalidParams,message:"session/set_model requires string sessionId",logMessage:"session/set_model rejected: missing/non-string sessionId"};if(typeof t.modelId!="string")return{kind:"error",code:E.InvalidParams,message:"session/set_model requires string modelId",logMessage:`session/set_model rejected: missing/non-string modelId sessionId=${t.sessionId}`};let n=e.get(t.sessionId);if(!n)return{kind:"error",code:E.SessionNotFound,message:`session ${t.sessionId} not found`,logMessage:`session/set_model rejected: session not found sessionId=${t.sessionId}`};let r=n.availableModels(),o=Ut(t.modelId,r);if(o.kind==="none")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model passthrough (no availableModels) sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="exact")return{kind:"ok",session:n,modelId:t.modelId,logMessage:`session/set_model accepted sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)}`};if(o.kind==="resolved")return{kind:"ok",session:n,modelId:o.modelId,logMessage:`session/set_model resolved sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} \u2192 ${JSON.stringify(o.modelId)}`};let i=r.map(d=>d.modelId).join(", "),a=o.kind==="ambiguous"?`ambiguous (trailing-segment matches [${o.candidates.join(", ")}])`:"not in availableModels";return n.currentModel!==void 0&&n.currentModel.length>0?{kind:"no_op",session:n,sessionId:t.sessionId,currentModel:n.currentModel,logMessage:`session/set_model no_op (resyncing client) sessionId=${t.sessionId} requested=${JSON.stringify(t.modelId)} ${a} actual=${JSON.stringify(n.currentModel)} agentId=${n.agentId} known=[${i}]`}:{kind:"error",code:E.InvalidParams,message:`model "${t.modelId}" is ${a==="not in availableModels"?"not in this session's availableModels":a} (agent ${n.agentId}); known models: ${i}`,logMessage:`session/set_model rejected sessionId=${t.sessionId} modelId=${JSON.stringify(t.modelId)} ${a} agentId=${n.agentId} known=[${i}] (no current model to fall back to)`}}async function $y(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0;if(!r)throw N(E.InvalidParams,"transformer/attach requires sessionId");if(!t.transformers)throw N(E.InternalError,"transformer manager not configured");let o=t.transformers.resolveChain([e])[0];if(!o)throw N(E.InternalError,`transformer ${e} is not connected (call hydra-acp/transformer/initialize first)`);return Re(t.manager,r).addTransformer(o),{ok:!0}}async function Oy(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw N(E.InvalidParams,"hydra-acp/attention/set requires string sessionId");if(!o)throw N(E.InvalidParams,"hydra-acp/attention/set requires string reason");return Re(t.manager,r).setAttentionFlag(e,o,n.payload),{ok:!0}}async function Fy(s,e,t){let n=s??{},r=typeof n.sessionId=="string"?n.sessionId:void 0,o=typeof n.reason=="string"?n.reason:void 0;if(!r)throw N(E.InvalidParams,"hydra-acp/attention/clear requires string sessionId");if(!o)throw N(E.InvalidParams,"hydra-acp/attention/clear requires string reason");return Re(t.manager,r).clearAttentionFlag(e,o),{ok:!0}}function Ny(s){let e={sessionId:s.hydraSessionId,upstreamSessionId:s.upstreamSessionId,cwd:s.cwd,workspace:s.workspace,title:s.title,agentId:s.agentId,currentModel:s.currentModel,currentUsage:An(s.currentUsage),forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:s.interactive,updatedAt:s.createdAt??new Date().toISOString(),attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1},t={currentMode:s.currentMode,agentArgs:s.agentArgs,availableCommands:s.agentCommands,availableModes:s.agentModes,availableModels:s.agentModels,armedTaskList:[]};return{[ce]:Qn(e,t)}}function or(s,e,t={}){let n=s.liveListEntry(e),r={clientId:t.clientId,currentMode:e.currentMode,agentArgs:e.agentArgs,availableCommands:e.mergedAvailableCommands(),availableModes:e.availableModes(),availableModels:e.availableModels(),turnStartedAt:e.turnStartedAt,agentCapabilities:e.agentCapabilities,queue:e.queueSnapshot(),armedTaskList:e.armedBackgroundTasks,...t.resurrected===!0?{resurrected:!0}:{}};return un(e.agentMeta,Qn(n,r))}function Dy(){return{protocolVersion:1,agentInfo:{name:"hydra",version:de},agentCapabilities:{promptCapabilities:{image:!0,audio:!0,embeddedContext:!0},mcpCapabilities:{http:!0,sse:!0},loadSession:!0,auth:{logout:{}},sessionCapabilities:{attach:{},list:{},resume:{},delete:{},close:{},fork:{}}},authMethods:[{id:"proxy",name:"Hydra proxy",type:"agent",description:"Hydra proxies authentication to the downstream agent selected per session"}],_meta:{...un(void 0,{prompt:{queueing:!0,cancelling:!0,updating:!0,amending:!0,pipelining:!1},agents:{list:!0,installProgress:!0},session:{fork:{forkAt:!0,agentSwap:!0,synthesis:!0,model:!0}}}),steering:{supported:!0}}}}function jy(s,e){if(!(!e.transformers||!e.manager))for(let t of e.manager.defaultTransformers){let n=e.transformers.resolveChain([t])[0];n&&s.addTransformer(n)}}function xu(s,e){if(!e.transformers)return;let t=e.transformers.interestedIn("lifecycle:session.starting");for(let n of t)n.connection.notify("hydra-acp/transformer/session_event",{event:"session.starting",sessionId:s}).catch(()=>{})}function gt(s,e,t,n,r){return{clientId:r??`cli_${ei(8)}`,connection:s,clientInfo:n}}function Zt(s,e,t){let n=s.attached.get(t);n&&(e.detach(n.clientId),s.attached.delete(t))}var ir=class{byToken=new Map;reserve(e){if(this.byToken.has(e))throw new Error("mcp token already bound");let t,n,r=new Promise((i,a)=>{t=i,n=a});r.catch(()=>{});let o={session:void 0,sessionReady:r,disposers:[]};return this.byToken.set(e,o),{complete:i=>{o.session=i,t(i)},abandon:i=>{this.byToken.delete(e),n(i??new Error("mcp token reservation abandoned"))}}}bind(e,t){let{complete:n}=this.reserve(e);n(t)}lookup(e){return this.byToken.get(e)}addDisposer(e,t){let n=this.byToken.get(e);n!==void 0&&n.disposers.push(t)}async unbind(e){let t=this.byToken.get(e);if(t!==void 0){this.byToken.delete(e);for(let n of t.disposers)try{await n()}catch{}}}size(){return this.byToken.size}};import{randomUUID as Hy}from"crypto";import{McpServer as Ly}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Uy}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as ge}from"zod";function ti(s){if(s.method!=="session/update")return null;let t=s.params?.update;return!t||typeof t.sessionUpdate!="string"?null:{kind:t.sessionUpdate,update:t}}function Ie(s){return{content:[{type:"text",text:JSON.stringify(s)}],structuredContent:s}}var Eu="Bearer ";function en(s){let e=s.headers.authorization;if(typeof e!="string"||!e.startsWith(Eu))return;let t=e.slice(Eu.length).trim();return t.length>0?t:void 0}function By(s){let e=new Ly({name:"hydra-acp-stdin",version:"1.0.0"},{instructions:"Piped input from `hydra cat --stream` is exposed here as a byte stream. Use `tail` for the latest N bytes (good for finding the end of a log), `head` for the first N bytes (good for headers/preamble), `read` for windowed reads against an absolute byte cursor, `wait_for_more` to block until new bytes arrive past a cursor, and `info` for the current cursors/capacity/closed status. Byte payloads come back base64-encoded."});return e.registerTool("tail",{description:"Return the most recent `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means older bytes existed but have been evicted from the ring.",inputSchema:{bytes:ge.number().int().min(1).describe("How many trailing bytes to return.")}},async({bytes:t})=>{let n=s.streamTail(t);return Ie(n)}),e.registerTool("head",{description:"Return the first `bytes` bytes of piped stdin (capped server-side, default 64 KiB max). `truncated:true` means the head has already been evicted from the ring and the returned bytes start at the oldest still-resident cursor.",inputSchema:{bytes:ge.number().int().min(1).describe("How many leading bytes to return.")}},async({bytes:t})=>{let n=s.streamHead(t);return Ie(n)}),e.registerTool("read",{description:"Read up to `max_bytes` bytes starting at absolute byte `cursor`. Returns `{bytes, nextCursor, gap?, eof?}` \u2014 `gap` is the number of bytes silently skipped because the ring had evicted them; `eof:true` means the producer closed and there is nothing left to read.",inputSchema:{cursor:ge.number().int().min(0).describe("Absolute byte offset to start reading from. Use 0 to read from the very beginning (may produce a gap if old bytes have been evicted)."),max_bytes:ge.number().int().min(1).optional().describe("Optional cap on how many bytes to return. Server caps at 64 KiB regardless."),wait_ms:ge.number().int().min(0).optional().describe("If no bytes are available, block up to this many ms for more (capped server-side at 60_000).")}},async({cursor:t,max_bytes:n,wait_ms:r})=>{let o=await s.streamRead(t,n,r);return Ie(o)}),e.registerTool("wait_for_more",{description:"Block until bytes are available past `cursor`, the stream closes, or `timeout_ms` elapses. Returns one of {data, eof, timeout} plus the current `writeCursor`. Use this when you've consumed everything up to a cursor and want to wait for more without busy-polling.",inputSchema:{cursor:ge.number().int().min(0).describe("The cursor you've already consumed up to."),timeout_ms:ge.number().int().min(0).describe("Maximum ms to block (server caps at 60_000).")}},async({cursor:t,timeout_ms:n})=>{let r=await s.streamWaitFor(t,n),o=s.streamInfo();return Ie({outcome:r,writeCursor:o.writeCursor,closed:o.closed})}),e.registerTool("grep",{description:"Scan piped stdin line-by-line and return lines matching `pattern`. Prefer this over `read` when the question is 'find lines that mention X' \u2014 it filters server-side so you don't pull and decode 64 KiB base64 windows. Returns `{matches: [{cursor, line, before?, after?}], truncated, nextCursor, gap?, scannedBytes, eof?}`. Lines come back as decoded UTF-8 strings (not base64). When `truncated:true`, re-call with `cursor: nextCursor` to resume.",inputSchema:{pattern:ge.string().min(1).describe("Search pattern. Treated as a JavaScript regular expression by default (set `regex:false` for a literal substring match)."),regex:ge.boolean().optional().describe("Default true. Pass false to treat `pattern` as a literal substring."),case_insensitive:ge.boolean().optional().describe("Default false. Pass true for case-insensitive matching."),invert:ge.boolean().optional().describe("Default false. Pass true to return lines that do NOT match the pattern."),max_matches:ge.number().int().min(1).optional().describe("Default 100. Capped server-side at 1000."),max_bytes:ge.number().int().min(1).optional().describe("Default 64 KiB output. Capped server-side at 256 KiB."),context_before:ge.number().int().min(0).optional().describe("Default 0. Number of lines before each match to include (capped at 20)."),context_after:ge.number().int().min(0).optional().describe("Default 0. Number of lines after each match to include (capped at 20)."),cursor:ge.number().int().min(0).optional().describe("Optional absolute byte offset to start scanning from. Omit to scan from the oldest still-resident byte. Pass the `nextCursor` from a previous truncated call to resume.")}},async t=>{let n={pattern:t.pattern};t.regex!==void 0&&(n.regex=t.regex),t.case_insensitive!==void 0&&(n.caseInsensitive=t.case_insensitive),t.invert!==void 0&&(n.invert=t.invert),t.max_matches!==void 0&&(n.maxMatches=t.max_matches),t.max_bytes!==void 0&&(n.maxBytes=t.max_bytes),t.context_before!==void 0&&(n.contextBefore=t.context_before),t.context_after!==void 0&&(n.contextAfter=t.context_after),t.cursor!==void 0&&(n.cursor=t.cursor);let r=s.streamGrep(n);return Ie(r)}),e.registerTool("info",{description:"Report cursor / capacity / closed state of the stdin ring. Cheap; safe to call repeatedly.",inputSchema:{}},async()=>{let t=s.streamInfo();return Ie(t)}),e}var Wy=1e4;function Tu(s,e){let t=new Map;async function n(i,a){let d=t.get(i);if(d!==void 0)return d.transport;let c=By(a),u=new Uy({sessionIdGenerator:()=>Hy()});await c.connect(u);let l={server:c,transport:u};return t.set(i,l),e.addDisposer(i,async()=>{t.delete(i);try{await u.close()}catch{}try{await c.close()}catch{}}),u}async function r(i,a){let d=en(i);if(d===void 0){a.code(401).send({error:"missing bearer token"});return}let c=e.lookup(d);if(c===void 0){a.code(404).send({error:"unknown stdin token"});return}let u;if(c.session!==void 0)u=c.session;else{let f,m=new Promise(p=>{f=setTimeout(()=>p(void 0),Wy)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(f!==void 0&&clearTimeout(f),h===void 0){a.code(503).send({error:"session not ready"});return}u=h}let l=await n(d,u);a.hijack(),await l.handleRequest(i.raw,a.raw,i.body)}let o={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.get("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)}),s.delete("/mcp/hydra-acp-stdin",o,async(i,a)=>{await r(i,a)})}import{randomUUID as qy}from"crypto";import{McpServer as zy}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport as Jy}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{z as Ke}from"zod";function Vy(s){switch(s){case"prompt_received":return"user";case"tool_call":case"tool_call_update":return"tool";default:return"agent"}}var Pu=2e3,Mu=2e4;function Gy(s,e,t){if(e!=="tool_call"&&e!=="tool_call_update")return Wt([s]);let n=[],r=ln(t);r!==void 0?n.push(`Tool: ${r}`):typeof t.title=="string"&&t.title.length>0&&n.push(`Tool: ${t.title}`);let o=t.rawInput;if(o&&typeof o=="object"&&!Array.isArray(o))for(let[a,d]of Object.entries(o))typeof d=="string"&&d.length>0&&n.push(`${a}=${d}`);if(Array.isArray(t.locations))for(let a of t.locations)typeof a?.path=="string"&&a.path.length>0&&n.push(a.path);let i=ns(t);return i!==void 0&&n.push(i),n.join(`
199
199
  `)}function Ky(s,e){if(s.length<=148)return s;let r=Math.floor(148/2),o=e-r;o<0&&(o=0);let i=o+148;i>s.length&&(o=s.length-148,o<0&&(o=0));let a=s.slice(o,i);return o>0&&(a="\u2026"+a),i<s.length&&(a=a+"\u2026"),a}function Qy(s){let e=new zy({name:"hydra-acp-recall",version:"1.0.0"},{instructions:"Search and retrieve detail from this session's pre-compaction history. After a compaction summary replaces earlier conversation in working memory, these tools let you page back specifics on demand. Use `search` to find entries by keyword, `range` to pull a contiguous slice verbatim, and `tool_calls` to enumerate prior tool invocations. These tools only return results once the session has been compacted at least once."});return e.registerTool("search",{description:"Search this session's prior conversation history (the part that was compacted out of your working memory) by keyword. Covers assistant and user messages, the arguments of every tool call including full shell commands, and what those calls printed. Returns matching entry ids with short snippets so you can decide which to pull in full via `range`. Use this when the compaction summary mentions something but you need the verbatim detail.",inputSchema:{query:Ke.string().min(1).describe("Case-insensitive substring to search for."),limit:Ke.number().int().min(1).max(50).optional().describe("Maximum number of matches to return (default 10, max 50)."),include_tool_calls:Ke.boolean().optional().describe("Whether to include tool_call entries in the search (default true).")}},async({query:t,limit:n=10,include_tool_calls:r=!0})=>{let o=await s();if(!o.summarizedThroughEntry||o.summarizedThroughEntry===0)return Ie({matches:[],total_matched:0,truncated:!1,note:"This session has no compacted history. `search` retrieves detail from entries that were summarized out of the working conversation; nothing has been summarized yet."});let i=[],a=t.toLowerCase();for await(let{entryId:c,entry:u}of o.iterRecallNewestFirst()){let l=ti(u);if(!l)continue;let{kind:f,update:m}=l;if((f==="tool_call"||f==="tool_call_update")&&!r)continue;let h=Gy(u,f,m),p=h.toLowerCase().indexOf(a);if(p<0)continue;let g=Vy(f),w=Ky(h,p),y=typeof u.recordedAt=="number"?String(u.recordedAt):void 0;if(i.push({entryId:c,speaker:g,snippet:w,timestamp:y}),i.length>=n)break}i.sort((c,u)=>c.entryId-u.entryId);let d=i.length>=n;return Ie({matches:i,total_matched:i.length,truncated:d})}),e.registerTool("range",{description:"Pull a contiguous range of prior conversation entries verbatim from this session's pre-compaction history, including each tool call's arguments and what it printed. Use after `search` narrows in on what you need. Capped at 50 entries per call.",inputSchema:{from_entry:Ke.number().int().min(0).describe("Zero-based index of the first entry to include (inclusive)."),to_entry:Ke.number().int().min(0).describe("Zero-based index of the last entry to include (inclusive).")}},async({from_entry:t,to_entry:n})=>{let r=await s();if(!r.summarizedThroughEntry||r.summarizedThroughEntry===0)return Ie({text:"",entry_count:0,truncated:!1,note:"This session has no compacted history. `range` retrieves verbatim entries from the pre-compaction transcript; nothing has been compacted yet."});if(n<t)throw new Error(`range: to_entry (${n}) must be >= from_entry (${t})`);let o=n-t+1;if(o>50)throw new Error(`range: range size (${o}) exceeds maximum of 50 entries`);let i=await r.getRecallTotalCount();if(i===0)return Ie({text:"",entry_count:0,truncated:!1});let a=Math.min(t,i-1),d=Math.min(n,i-1),c=a>t||d<n;if(a>d)return{content:[{type:"text",text:""}],structuredContent:{text:"",entry_count:0,truncated:c}};let u=await r.sliceRecallHistory(a,d),l=Wt(u,{toolOutput:{maxPerCall:Pu,maxTotal:Mu}});return{content:[{type:"text",text:l}],structuredContent:{text:l,entry_count:u.length,truncated:c}}}),e.registerTool("tool_calls",{description:"Search this session's prior tool invocations by tool name, ACP kind, and/or file path. Returns when each tool was called, its arguments (including the full shell command), the result status, and what the call printed. Use this to recall which files were read/edited, what shell commands ran, and what they output.",inputSchema:{tool_name:Ke.string().optional().describe("Case-insensitive substring of the tool name. Names vary by agent for the same tool (Bash, Terminal, bash), so prefer `kind` when you want every shell invocation."),kind:Ke.string().optional().describe("ACP tool kind: execute (shell), read, edit, think, other. Agent-independent, unlike tool_name."),file_path:Ke.string().optional(),limit:Ke.number().int().min(1).max(100).optional(),include_output:Ke.boolean().optional().describe("Include what each call printed (default true). Set false when you only need the commands and not their results.")}},async({tool_name:t,kind:n,file_path:r,limit:o=20,include_output:i=!0})=>{let a=await s();if(!a.summarizedThroughEntry||a.summarizedThroughEntry===0)return Ie({calls:[],truncated:!1,note:"This session has no compacted history. `tool_calls` retrieves tool invocations from the pre-compaction transcript; nothing has been compacted yet."});let d=typeof t=="string"&&t.length>0,c=typeof n=="string"&&n.length>0,u=typeof r=="string"&&r.length>0;if(!d&&!c&&!u)throw new Error("tool_calls: at least one of tool_name, kind, or file_path must be provided");let l=new Map,f=Math.max(o*4,200);for await(let{entryId:y,entry:k}of a.iterRecallNewestFirst()){let b=ti(k);if(!b)continue;let{kind:I,update:v}=b;if(I!=="tool_call"&&I!=="tool_call_update")continue;let A=typeof v.toolCallId=="string"&&v.toolCallId.length>0?v.toolCallId:`__noid_${y}`,C=l.get(A);if(C||(C={entryId:y,toolName:"(unnamed)",nameAuthoritative:!1,rawInput:{},locations:[],status:"in_progress"},l.set(A,C)),y<C.entryId&&(C.entryId=y),!C.nameAuthoritative){let T=ln(v);T!==void 0?(C.toolName=T,C.nameAuthoritative=!0):typeof v.name=="string"&&v.name.length>0?(C.toolName=v.name,C.nameAuthoritative=!0):I==="tool_call"&&typeof v.title=="string"&&v.title.length>0&&(C.toolName=v.title,C.nameAuthoritative=!0)}if(C.kind===void 0&&typeof v.kind=="string"&&v.kind.length>0&&(C.kind=v.kind),C.output===void 0){let T=ns(v);T!==void 0&&(C.output=T)}let R=v.rawInput;if(R&&typeof R=="object"&&!Array.isArray(R)&&Object.keys(R).length>0)for(let[T,_]of Object.entries(R))C.rawInput[T]===void 0&&(C.rawInput[T]=_);if(Array.isArray(v.locations))for(let T of v.locations){let _=T?.path;typeof _=="string"&&_.length>0&&!C.locations.includes(_)&&C.locations.push(_)}if(typeof v.status=="string"&&C.status==="in_progress"&&(C.status=v.status),k.recordedAt!==void 0&&C.timestamp===void 0&&(C.timestamp=String(k.recordedAt)),l.size>=f)break}let m=[...l.keys()].sort((y,k)=>l.get(y).entryId-l.get(k).entryId),h=[],p=Mu,g=!1;for(let y of m){let k=l.get(y);if(k.toolName=Br({name:k.toolName,rawInput:k.rawInput,...k.kind!==void 0?{kind:k.kind}:{}}),d&&!k.toolName.toLowerCase().includes(t.toLowerCase())||c&&(k.kind??"").toLowerCase()!==n.toLowerCase())continue;if(u){let v=r.toLowerCase(),A=["file_path","filePath","path"],C=!1;for(let R of A){let T=k.rawInput[R];if(typeof T=="string"&&T.toLowerCase().includes(v)){C=!0;break}}if(!C){for(let R of k.locations)if(R.toLowerCase().includes(v)){C=!0;break}}if(!C)continue}let b={};for(let[v,A]of Object.entries(k.rawInput))typeof A=="string"?b[v]=A.length>500?A.slice(0,497)+"\u2026":A:(typeof A=="number"||typeof A=="boolean")&&(b[v]=A);k.locations.length>0&&b.locations===void 0&&(b.locations=k.locations);let I={entryId:k.entryId,tool:k.toolName,args:b,status:k.status,timestamp:k.timestamp};if(k.kind!==void 0&&(I.kind=k.kind),i&&k.output!==void 0){let v=k.output,A=Math.min(Pu,p);if(A<=0)g=!0;else{let C=v.length<=A?v:v.slice(0,A-1)+"\u2026";I.output=C,I.outputBytes=v.length,I.outputTruncated=C.length<v.length,p-=C.length}}if(h.push(I),h.length>=o)break}let w=h.length>=o;return Ie({calls:h,truncated:w,...g?{outputBudgetExhausted:g}:{}})}),e}var Yy=1e4;function _u(s,e){let t=new Map;async function n(i,a){let d=t.get(i);if(d!==void 0)return d.transport;let c=Qy(a),u=new Jy({sessionIdGenerator:()=>qy()});await c.connect(u);let l={server:c,transport:u};return t.set(i,l),e.addDisposer(i,async()=>{t.delete(i);try{await u.close()}catch{}try{await c.close()}catch{}}),u}async function r(i,a){let d=en(i);if(d===void 0){a.code(401).send({error:"missing bearer token"});return}let c=e.lookup(d);if(c===void 0){a.code(404).send({error:"unknown recall token"});return}let l=await n(d,async()=>{if(c.session!==void 0)return c.session;let f,m=new Promise(p=>{f=setTimeout(()=>p(void 0),Yy)}),h=await Promise.race([c.sessionReady.catch(()=>{}),m]);if(f!==void 0&&clearTimeout(f),h===void 0)throw new Error("recall: session not ready");return h});a.hijack(),await l.handleRequest(i.raw,a.raw,i.body)}let o={config:{skipAuth:!0}};s.post("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)}),s.get("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)}),s.delete("/mcp/hydra-acp-recall",o,async(i,a)=>{await r(i,a)})}var ar=class{byName=new Map;changeHandlers=[];register(e,t,n,r){this.byName.set(e,{connection:t,instructions:n,tools:[...r]}),this.fireChanged(e,"register")}clear(e){this.byName.delete(e)&&this.fireChanged(e,"clear")}lookup(e){return this.byName.get(e)}list(){return Array.from(this.byName.keys())}onChange(e){return this.changeHandlers.push(e),()=>{let t=this.changeHandlers.indexOf(e);t>=0&&this.changeHandlers.splice(t,1)}}fireChanged(e,t){for(let n of this.changeHandlers)try{n(e,t)}catch{}}};import{StreamableHTTPServerTransport as ow}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{randomUUID as iw}from"crypto";import{Server as Xy}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as Zy,ListToolsRequestSchema as ew}from"@modelcontextprotocol/sdk/types.js";function $u(s,e,t,n){let r=typeof t=="function"?async()=>t():async()=>t,o=new Xy({name:s,version:"1.0.0"},{capabilities:{tools:{listChanged:!0}},...e.instructions!==void 0?{instructions:e.instructions}:{}}),i=a=>({name:a.name,description:a.description,inputSchema:a.inputSchema,...a.outputSchema!==void 0?{outputSchema:a.outputSchema}:{}});return o.setRequestHandler(ew,async()=>{let a=n?.peekSessionId?.();if(a!==void 0&&n?.fetchSessionTools!==void 0)try{let d=await n.fetchSessionTools(a);if(d!==void 0)return{tools:d.map(i)}}catch{}return{tools:e.tools.map(i)}}),o.setRequestHandler(Zy,async(a,d)=>{let c=a.params.name,u=d._meta?.progressToken??d.requestId,l=nw(u,d.sendNotification);try{let f=await r(),m=await sw(e.connection,s,c,a.params.arguments??{},f);return rw(m,c)}catch(f){return ni(f instanceof Error?f.message:String(f))}finally{l()}}),o}var tw=15e3;function nw(s,e,t=tw){if(s===void 0)return()=>{};let n=0,r=setInterval(()=>{n+=1,e({method:"notifications/progress",params:{progressToken:s,progress:n}}).catch(()=>{})},t);return r.unref?.(),()=>clearInterval(r)}async function sw(s,e,t,n,r){return await s.request("hydra-acp/mcp_tools/invoke",{server:e,tool:t,args:n,sessionId:r})}function rw(s,e){if(s===null||typeof s!="object")return ni(`extension ${e} returned non-object`);let t=s;return Array.isArray(t.content)?t:ni(`extension ${e} omitted content array`)}function ni(s){return{content:[{type:"text",text:s}],isError:!0}}var aw=1e4;function Ou(s,e,t){let n=new Map;async function r(u){try{await u.transport.close()}catch{}try{await u.server.close()}catch{}}function o(u){for(let l of n.values()){let f=l.get(u);f!==void 0&&(l.delete(u),r(f))}}async function i(u,l){for(let[f,m]of n){if(e.lookup(f)?.session?.sessionId!==u)continue;let p=m.get(l);if(p!==void 0)try{await p.server.sendToolListChanged()}catch{}}}t.onChange(u=>{o(u)});async function a(u,l){let f=n.get(u);f===void 0&&(f=new Map,n.set(u,f),e.addDisposer(u,async()=>{let b=n.get(u);if(b!==void 0){n.delete(u);for(let I of b.values())await r(I)}}));let m=f.get(l);if(m!==void 0)return m.transport;let h=t.lookup(l);if(h===void 0)return;let y=$u(l,h,async()=>{let b=e.lookup(u);if(b===void 0)throw new Error("mcp token no longer bound");if(b.session!==void 0)return b.session.sessionId;let I,v=new Promise(C=>{I=setTimeout(()=>C(void 0),aw)}),A=await Promise.race([b.sessionReady.catch(()=>{}),v]);if(I!==void 0&&clearTimeout(I),A===void 0)throw new Error("session not ready");return A.sessionId},{peekSessionId:()=>e.lookup(u)?.session?.sessionId,fetchSessionTools:async b=>{let I=await h.connection.request("hydra-acp/mcp_tools/list_tools",{sessionId:b});if(!I||typeof I!="object")return;let v=I.tools;if(!Array.isArray(v))return;let A=[];for(let C of v){if(!C||typeof C!="object")continue;let R=C;if(typeof R.name!="string"||R.name.length===0||typeof R.description!="string"||R.inputSchema===null||typeof R.inputSchema!="object")continue;let T={name:R.name,description:R.description,inputSchema:R.inputSchema};R.outputSchema!==null&&typeof R.outputSchema=="object"&&(T.outputSchema=R.outputSchema),A.push(T)}return A}}),k=new ow({sessionIdGenerator:()=>iw()});return await y.connect(k),f.set(l,{server:y,transport:k}),k}async function d(u,l){let f=en(u);if(f===void 0){l.code(401).send({error:"missing bearer token"});return}if(e.lookup(f)===void 0){l.code(404).send({error:"unknown mcp token"});return}let h=u.params.name,p=await a(f,h);if(p===void 0){l.code(404).send({error:`unknown mcp server: ${h}`});return}l.hijack(),await p.handleRequest(u.raw,l.raw,u.body)}let c={config:{skipAuth:!0}};return s.post("/mcp/:name",c,async(u,l)=>{await d(u,l)}),s.get("/mcp/:name",c,async(u,l)=>{await d(u,l)}),s.delete("/mcp/:name",c,async(u,l)=>{await d(u,l)}),{notifyToolListChanged:i}}async function Lu(s,e){gw(s),br(s.daemon.scrubEnv);let t=s,n=s.daemon.tls?await Qe.readFile(ae(s.daemon.tls.key)):void 0,r=s.daemon.tls?await Qe.readFile(ae(s.daemon.tls.cert)):void 0;await Qe.mkdir(x.home(),{recursive:!0});let{stream:o,fileStream:i}=await fw(s.daemon.logLevel),a=dw({logger:{level:s.daemon.logLevel,stream:o},bodyLimit:256*1024*1024});await a.register(cw,{options:{handleProtocols:Ii}}),xr(F=>{a.log.info(F)}),Pr(F=>{a.log.info(F)});let d=await Fs.load(),c=await Gs.load();Qo(),Go(c);let u=new tr(c);u.start();let l=new zs(c);l.start();let f=new Ls,m=new Hs,h=new Ns(e),p=new js([h,new Ds(d),m]),g=dc({validator:p});a.addHook("onRequest",async(F,ve)=>{F.routeOptions.config?.skipAuth||F.url==="/acp"||F.url?.startsWith("/acp?")||(await g(F,ve),!ve.sent&&F.authIdentity?.startsWith("script:")&&!uc(F.method,F.routeOptions.url)&&ve.code(403).send({error:"script tokens may only access read-only session data"}))});let w=setInterval(()=>{d.sweepExpired()},300*1e3);w.unref();let y=setInterval(()=>{f.sweepExpired()},300*1e3);y.unref();let k=new Gn(s,{onFetched:()=>{Gd(k,A)},onStaleFallback:(F,ve)=>{let nn=Math.round(ve/36e5),sn=nn>=48?`${Math.round(nn/24)}d`:`${nn}h`;a.log.warn(`registry fetch failed (${F.message}); serving stale cache last synced ${sn} ago; agent versions may be outdated ('hydra registry refresh' to retry)`)}});Fo(F=>a.log.info(F));let b={info:F=>a.log.info(F),warn:F=>a.log.warn(F)},I=F=>it.spawn({...F,stderrTailBytes:s.daemon.agentStderrTailBytes,logger:b});Ti(s.compressToolContent);let v=new $s,A=new Cs(k,I,void 0,{idleTimeoutMs:s.daemon.sessionIdleTimeoutSeconds*1e3,orphanTimeoutMs:s.daemon.nonInteractiveOrphanTimeoutSeconds*1e3,sessionDefaults:s.sessionDefaults,synopsisAgent:s.synopsisAgent,synopsisModel:s.synopsisModel,compactionAgent:s.compaction?.agent,compactionModel:s.compaction?.model,defaultTransformers:s.defaultTransformers,sessionHistoryMaxEntries:s.daemon.sessionHistoryMaxEntries,sessionHistoryArchiveMaxBytes:s.daemon.sessionHistoryArchiveMaxBytes,sessionHistoryArchiveTiers:s.daemon.sessionHistoryArchiveTiers,logger:b,npmRegistry:s.npmRegistry,extensionCommands:v,defaultCwd:s.defaultCwd,disableWorkspaceSnapshots:s.disableWorkspaceSnapshots}),C=new er(c,void 0,{resolvesLocally:async F=>await A.resolveCanonicalId(F)!==void 0,cache:l}),R=new Ms(wi(s),void 0,{tokenRegistry:m}),T=new _s(ki(s),void 0,{tokenRegistry:m}),_=[];Wc(a,de,Yd(s),()=>_);let U=new Date().toISOString();Qc(a,U);let J=new ir,M=new ar,W,q=()=>{if(W!==void 0)return W;let F=a.server.address();return W=`http://127.0.0.1:${F&&typeof F=="object"?F.port:s.daemon.port}`,W},ee={agentId:s.defaultAgent,cwd:s.defaultCwd,publicHost:s.daemon.publicHost,host:s.daemon.host,port:s.daemon.port,compaction:s.compaction};Uc(a,A,ee,{extensionMcp:M,mcpTokenRegistry:J,getDaemonOrigin:q},c,l),Nc(a,{store:c,localMiss:{resolvesLocally:async F=>await A.resolveCanonicalId(F)!==void 0,cache:l}}),Bc(a,k,A,{npmRegistry:s.npmRegistry}),Yc(a,R),Xc(a,T);let me={host:s.daemon.host,port:s.daemon.port,...s.daemon.publicHost!==void 0?{publicHost:s.daemon.publicHost}:{},...s.daemon.tls?{tls:{cert:ae(s.daemon.tls.cert),key:ae(s.daemon.tls.key)}}:{}};Zc(a,()=>({defaultAgent:t.defaultAgent,defaultCwd:t.defaultCwd,sessionDefaults:{...t.sessionDefaults},...t.synopsisAgent!==void 0?{synopsisAgent:t.synopsisAgent}:{},...t.synopsisModel!==void 0?{synopsisModel:t.synopsisModel}:{},defaultTransformers:[...t.defaultTransformers],listen:me})),ru(a,{store:d,rateLimiter:f,staticTokenValidator:h}),pu(a,{store:c,health:u}),wu(a,{processRegistry:m}),Tu(a,J),_u(a,J);let Z=Ou(a,J,M);Ru(a,{validator:p,manager:A,defaultAgent:s.defaultAgent,processRegistry:m,onExtensionVersion:(F,ve)=>R.reportVersion(F,ve),onTransformerVersion:(F,ve)=>T.reportVersion(F,ve),transformers:T,extensionCommands:v,mcpTokenRegistry:J,extensionMcp:M,extensionMcpControls:Z,getDaemonOrigin:q,registry:k,foreignSessions:C});let Me=!!s.daemon.tls;await a.listen({host:Me?"127.0.0.1":s.daemon.host,port:Me?0:s.daemon.port});let dr=a.server.address(),Tt=dr&&typeof dr=="object"?dr.port:s.daemon.port,Bn,Uu=s.daemon.host,si=Tt;if(Me&&n&&r){Bn=await pw({listenHost:s.daemon.host,listenPort:s.daemon.port,upstreamHost:"127.0.0.1",upstreamPort:Tt,tlsOptions:{key:n,cert:r},logger:a.log});let F=Bn.address();F&&typeof F=="object"&&(si=F.port)}await Qe.mkdir(x.home(),{recursive:!0}),await Vd({pid:process.pid,host:Uu,port:si,loopbackPort:Tt,startedAt:U});let ri={daemonUrl:`http://127.0.0.1:${Tt}`,daemonHost:"127.0.0.1",daemonPort:Tt,serviceToken:e,daemonWsUrl:`ws://127.0.0.1:${Tt}/acp`,hydraHome:x.home()};R.setContext(ri),T.setContext(ri),await R.start(),await T.start();try{await A.reconcilePermissionFlags()}catch(F){a.log.warn(`permission flag reconcile failed: ${F.message}`)}try{await A.seedSessionIndex()}catch(F){a.log.warn(`session index seed failed: ${F.message}`)}A.resurrectPendingQueues().catch(F=>{a.log.warn(`queue replay scan failed: ${F.message}`)}),A.resumePendingCompactions().catch(F=>{a.log.warn(`compaction resume scan failed: ${F.message}`)}),A.resumePendingAgentSwaps().catch(F=>{a.log.warn(`agent-swap resume scan failed: ${F.message}`)});let oi=s.daemon.agentSyncIntervalMinutes*60*1e3,ii=oi>0?Kd({registry:k,manager:A,intervalMs:oi,logger:b}):void 0,ai=s.daemon.sessionGcIntervalMinutes*60*1e3,Bu=s.daemon.sessionGcMaxAgeDays*24*60*60*1e3,di=ai>0?Qd({manager:A,intervalMs:ai,maxAgeMs:Bu,logger:b}):void 0,Wu=tc({bootConfig:s,apply:F=>{t=F,k.setConfig(F),A.setLiveConfig({sessionDefaults:F.sessionDefaults}),ee.agentId=F.defaultAgent,ee.cwd=F.defaultCwd,br(F.daemon.scrubEnv)},onDrift:F=>{_=F},logger:b});return{app:a,manager:A,registry:k,extensions:R,transformers:T,mcpTokenRegistry:J,extensionMcp:M,processRegistry:m,shutdown:async()=>{u.stop(),l.stop(),Wu(),di&&di(),ii&&ii(),clearInterval(w),clearInterval(y);let F=async(ve,nn)=>{try{await nn()}catch(sn){a.log.warn(`shutdown step ${ve} failed: ${sn instanceof Error?sn.message:String(sn)}`)}};await F("sessionTokenStore.flush",()=>d.flush()),await F("extensions.stop",()=>R.stop()),await F("transformers.stop",()=>T.stop()),await F("manager.closeAll",()=>A.closeAll()),await F("manager.flushSynopsis",()=>A.flushSynopsis(3e4)),await F("manager.shutdownSynopsis",()=>A.shutdownSynopsis()),await F("manager.flushMetaWrites",()=>A.flushMetaWrites()),await F("manager.flushHistoryWrites",()=>A.flushHistoryWrites()),xr(null),Pr(null),Fo(null),Bn&&await F("tlsTerminator.close",()=>new Promise(ve=>Bn.close(()=>ve()))),await F("app.close",()=>a.close());try{Du.unlinkSync(x.pidFile())}catch{}await F("fileStream.flushSync",()=>i.flushSync())}}}var Nu=20;async function lw(s,e){let t=tn.dirname(s),n=tn.basename(s,".log"),r=new RegExp(`^${n}\\.(\\d+)\\.log$`),o;try{o=await Qe.readdir(t)}catch{return}let i=[];for(let d of o){let c=d.match(r);c&&i.push({name:d,n:Number(c[1])})}if(i.length<=e)return;i.sort((d,c)=>d.n-c.n);let a=i.slice(0,i.length-e);await Promise.allSettled(a.map(d=>Qe.unlink(tn.join(t,d.name))))}async function fw(s){await lw(x.logFile(),Nu);let e=await uw({file:x.logFile(),size:"10m",mkdir:!0,symlink:Es,limit:{count:Nu,removeOtherLogFiles:!0}}),t=Fu.destination(2);return{stream:Fu.multistream([{stream:e,level:s},{stream:t,level:s}]),fileStream:e}}async function pw(s){let e=Hu.createServer(s.tlsOptions,t=>{let n=ju.connect({host:s.upstreamHost,port:s.upstreamPort}),r=!1,o=i=>{if(!r){r=!0,i&&s.logger.warn(`tls terminator forwarder error: ${i.message??String(i)}`);try{t.destroy()}catch{}try{n.destroy()}catch{}}};t.on("error",o),n.on("error",o),t.on("close",()=>o()),n.on("close",()=>o()),t.pipe(n),n.pipe(t)});return e.on("tlsClientError",t=>{s.logger.warn(`tls handshake error: ${t.message}`)}),await new Promise((t,n)=>{let r=o=>{n(new Error(`TLS listener could not bind ${s.listenHost}:${s.listenPort}: ${o.message}`))};e.once("error",r),e.listen({host:s.listenHost,port:s.listenPort},()=>{e.off("error",r),t()})}),e.on("error",t=>{s.logger.warn(`tls terminator error: ${t.message}`)}),e}function gw(s){let e=s.daemon.host;if(!(e==="127.0.0.1"||e==="::1"||e==="localhost"||e==="[::1]")&&!s.daemon.tls)throw new Error(`Refusing to bind to non-loopback host ${e} without TLS configured.`)}async function mw(){process.title="hydra-acp-daemon";let{installGlobalTlsTrust:s}=await Promise.resolve().then(()=>(Hn(),fu));s();let e=await an(),t=await li(),n=await Lu(e,t);process.stdout.write(`hydra-acp daemon listening on ${e.daemon.host}:${e.daemon.port}
200
200
  `);let r=1e4,o=!1,i=async()=>{o&&(process.stderr.write(`Second signal received; exiting immediately.
201
201
  `),process.exit(1)),o=!0,process.stdout.write(`Shutting down...
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydra-acp/cli",
3
- "version": "0.1.196",
3
+ "version": "0.1.197",
4
4
  "description": "Multi-client ACP session daemon: spawn agents, attach over WSS, multiplex sessions across editors.",
5
5
  "license": "MIT",
6
6
  "type": "module",