@hydra-acp/cli 0.1.99 → 0.1.101

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2907,6 +2907,7 @@ interface SessionInit {
2907
2907
  scheduleCompaction?: (opts?: {
2908
2908
  targetAgentId?: string;
2909
2909
  }) => void;
2910
+ resolveAgentId?: (id: string) => Promise<string | undefined>;
2910
2911
  getCompactionState?: () => Promise<CompactionState | undefined>;
2911
2912
  getPendingAgentSwap?: () => Promise<string | undefined>;
2912
2913
  createdAt?: number;
@@ -2995,6 +2996,7 @@ declare class Session {
2995
2996
  private titleHandlers;
2996
2997
  private scheduleSynopsisHook?;
2997
2998
  private scheduleCompactionHook?;
2999
+ private resolveAgentIdHook?;
2998
3000
  private getCompactionStateHook?;
2999
3001
  private getPendingAgentSwapHook?;
3000
3002
  private _liveCompactionPhase;
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ stderr: ${t}`:e}stderrTailText(){return this.stderrTail.trim()}static spawn(e){l
26
26
  `)}function Qa(n){let e=[],t=null;for(let r=0;r<n.length;r++){let o=n[r];if(o.method!=="session/update")continue;let a=o.params?.update;if(!a||typeof a.sessionUpdate!="string")continue;let u=a.sessionUpdate;if(u==="prompt_received")t!==null&&t.user.length>0&&e.push(t),t={user:Un(a.prompt).trim(),agent:"",tools:[],startEntryIndex:r};else if(u==="agent_message_chunk"&&t!==null){let c=Dn(a.content);c.length>0&&(t.agent+=c)}else u==="tool_call"&&t!==null?t.tools.push(Bn(a)):u==="turn_complete"&&t!==null&&(e.push(t),t=null)}let s=t!==null&&t.user.length>0?t:null;return{closed:e,open:s}}import*as pe from"fs/promises";async function ut(n,e){let t=I.queueFile(n);if(e.length===0){await pe.unlink(t).catch(()=>{});return}await pe.mkdir(I.sessionDir(n),{recursive:!0});let s=e.map(r=>JSON.stringify(r)).join(`
27
27
  `)+`
28
28
  `;await pe.writeFile(t,s,"utf8")}async function xr(n){let e=I.queueFile(n),t;try{t=await pe.readFile(e,"utf8")}catch(r){if(r.code==="ENOENT")return[];throw r}let s=[];for(let r of t.split(`
29
- `))if(r.trim())try{let o=JSON.parse(r);o&&typeof o.messageId=="string"&&Array.isArray(o.prompt)&&typeof o.enqueuedAt=="number"&&s.push(o)}catch{}return s}async function Mr(n){let e=I.queueFile(n);await pe.unlink(e).catch(()=>{})}import*as Or from"fs/promises";var _r="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",$r=Tr(_r,16),qn=Tr(_r,16),Va=20,Ka=20,Ga=5,ye="hydra_session_";function ke(){return`m_${$r()}`}function Fr(n){return n.startsWith(ye)?n.slice(ye.length):n}var Ya=1e3,Bt=300*1e3,Xa=64,Pe=class n{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;agentArgs;parentSessionId;forkedFromSessionId;forkedFromMessageId;forkSynthesisState;originatingClient;_interactive;get interactive(){return this._interactive}_priority;get priority(){return this._priority}title;_summarizedThroughEntry;get summarizedThroughEntry(){return this._summarizedThroughEntry}set summarizedThroughEntry(e){this._summarizedThroughEntry=e}currentModel;currentMode;compactionState;_currentUsage;updatedAt;createdAt;clients=new Map;historyStore;promptQueue=[];currentEntry;promptInFlight=!1;modeChangeInFlight=!1;modelChangeInFlight=!1;queueWriteChain=Promise.resolve();closed=!1;closing=!1;closeInFlight;deleteRecordIntent=!1;closeHandlers=[];titleHandlers=[];scheduleSynopsisHook;scheduleCompactionHook;getCompactionStateHook;getPendingAgentSwapHook;_liveCompactionPhase;broadcastHandlers=[];lastCancelAt=0;static CANCEL_ERROR_WINDOW_MS=2e3;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}promptStartedAt;appendCount=0;historyMaxEntries;compactEvery;permissionCallbacks=new Map;attentionFlags=new Map;get hasPermissionFlag(){for(let e of this.attentionFlags.values())if(e.source==="daemon"&&e.reason.startsWith("permission:"))return!0;return!1}attentionFlagsChangeHandlers=[];internalPromptCapture;idleTimeoutMs;idleTimer;idleEventTimeoutMs;idleHandlers=[];lastRecordedAt;spawnReplacementAgent;mintMcpServersForSwap;loadExistingAgentSession;clearRollbackBreadcrumbHook;onCompactionSwapHook;uncompactHook;mcpServersConfig;forwardedEnv;listSessions;logger;transformChain;extensionCommands;extensionCommandsUnsub;pendingClaims=new Map;toolCompletionSeen=new Map;toolCallKind=new Map;filesEditedSeen=new Set;agentChangeHandlers=[];agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];availableAgentsFn;modelHandlers=[];modeHandlers=[];interactiveHandlers=[];priorityHandlers=[];usageHandlers=[];cumulativeCost=0;get currentUsage(){if(!this._currentUsage&&!this.cumulativeCost)return;let e=this._currentUsage??{},t=this.cumulativeCost+(e.costAmount??0);return{...e,costAmount:t||void 0,cumulativeCost:void 0}}amendInProgress;inFlightExtensionDispatches=new Map;recentlyTerminal=new Map;streamBuffer;streamFilePath;constructor(e){if(this.sessionId=e.sessionId??`${ye}${$r()}`,this.cwd=e.cwd,this.agentId=e.agentId,this.agent=e.agent,this.upstreamSessionId=e.upstreamSessionId,this.agentMeta=e.agentMeta,this.agentCapabilities=e.agentCapabilities,this.agentArgs=e.agentArgs,this.parentSessionId=e.parentSessionId,this.forkedFromSessionId=e.forkedFromSessionId,this.forkedFromMessageId=e.forkedFromMessageId,this.forkSynthesisState=e.forkSynthesisState,this.originatingClient=e.originatingClient,this.title=e.title,this.scheduleSynopsisHook=e.scheduleSynopsis,this.scheduleCompactionHook=e.scheduleCompaction,this.getCompactionStateHook=e.getCompactionState,this.getPendingAgentSwapHook=e.getPendingAgentSwap,this.currentModel=e.currentModel,this.currentMode=e.currentMode,this._currentUsage=e.currentUsage,this.cumulativeCost=e.currentUsage?.cumulativeCost??0,e.agentCommands&&e.agentCommands.length>0&&(this.agentAdvertisedCommands=[...e.agentCommands]),e.agentModes&&e.agentModes.length>0&&(this.agentAdvertisedModes=[...e.agentModes]),e.agentModels&&e.agentModels.length>0&&(this.agentAdvertisedModels=[...e.agentModels]),this.idleTimeoutMs=e.idleTimeoutMs??0,this.idleEventTimeoutMs=e.idleEventTimeoutMs??3e4,this.idleEventTimeoutMs>0&&this.onIdle(t=>t.notifyChain("session.idle",{}),{debounceMs:this.idleEventTimeoutMs}),this.spawnReplacementAgent=e.spawnReplacementAgent,this.mintMcpServersForSwap=e.mintMcpServersForSwap,this.loadExistingAgentSession=e.loadExistingAgentSession,this.clearRollbackBreadcrumbHook=e.clearRollbackBreadcrumbHook,this.onCompactionSwapHook=e.onCompactionSwapHook,this.uncompactHook=e.uncompactHook,this.mcpServersConfig=e.mcpServers,this.forwardedEnv=e.forwardedEnv,this.availableAgentsFn=e.availableAgents,this.listSessions=e.listSessions,this.logger=e.logger,this.transformChain=e.transformChain??[],this.extensionCommands=e.extensionCommands,this.extensionCommands&&(this.extensionCommandsUnsub=this.extensionCommands.onChange(()=>{this.closed||this.broadcastMergedCommands()})),e.firstPromptSeeded&&(this._firstPromptSeeded=!0),this._interactive=e.interactive,this._priority=e.priority,this._summarizedThroughEntry=e.summarizedThroughEntry,this.compactionState=e.compactionState,e.compactionState){let t=e.compactionState;(t.status==="requested"||t.status==="running"||t.status==="swap_pending"||t.status==="swap_deferred")&&(t.status==="swap_deferred"?this._liveCompactionPhase={phase:"deferred",attempts:t.attempts}:this._liveCompactionPhase={phase:t.status==="requested"?"started":"iteration",iter:t.iter})}if(e.attentionFlags&&e.attentionFlags.length>0)for(let t of e.attentionFlags)this.attentionFlags.set(`${t.source}::${t.reason}`,t);this.historyStore=e.historyStore,this.historyMaxEntries=e.historyMaxEntries??Ya,this.compactEvery=Math.max(1,Math.floor(this.historyMaxEntries*.2)),this.updatedAt=Date.now(),this.createdAt=e.createdAt??this.updatedAt,this.lastRecordedAt=this.updatedAt,this.wireAgent(this.agent),this.scheduleIdleCheck(),this.notifyChain("session.opened",{})}broadcastMergedCommands(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"available_commands_update",availableCommands:this.mergedAvailableCommands()}})}broadcastAvailableModes(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"available_modes_update",availableModes:this.agentAdvertisedModes}})}broadcastAvailableModels(){let e={sessionUpdate:"current_model_update",availableModels:[...this.agentAdvertisedModels]};this.currentModel!==void 0&&this.currentModel.length>0&&(e.currentModel=this.currentModel),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:e})}wireAgent(e){e.connection.onNotification("session/update",t=>{if(this.internalPromptCapture){rd(this.internalPromptCapture,t);return}this.maybeEmitToolEdges(t),this.runResponseChain(t)}),e.connection.onRequest("session/request_permission",async t=>{let s=await this.runAgentRequestChain("session/request_permission",t),r=Er(s.shortCircuit?t:s.envelope);if(s.shortCircuit)return this.notifyChain("permission.replied",{toolCallId:r??null,outcome:s.payload,sourceWasTransformer:!0}),s.payload;let o=await this.handlePermissionRequest(s.envelope);return this.notifyChain("permission.replied",{toolCallId:r??null,outcome:o,sourceWasTransformer:!1}),o}),typeof e.connection.onOrphanError=="function"&&e.connection.onOrphanError(t=>{this.handleOrphanError(t)}),e.onExit(()=>{this.agent===e&&this.markClosed({deleteRecord:!1})})}handleOrphanError(e){let t=Date.now()-this.lastCancelAt;if(this.lastCancelAt===0||t>n.CANCEL_ERROR_WINDOW_MS){this.logger?.warn(`agent ${this.agentId} sent uncorrelated error frame code=${e.code} message=${e.message}`);return}this.lastCancelAt=0,this.logger?.warn(`agent ${this.agentId} rejected session/cancel code=${e.code} message=${e.message}`),this.broadcastQueueNotification("hydra-acp/cancel_failed",{sessionId:this.sessionId,code:e.code,message:e.message})}async runResponseChain(e,t=new Set,s=0,r="session/update"){let o=e,i=r==="session/update"?this.injectCumulativeCost(e):e,a=`response:${r}`;for(let d=s;d<this.transformChain.length;d++){let l=this.transformChain[d];if(t.has(l.name)||!l.intercepts.has(a))continue;let p=`t_${qn()}`,f;try{f=await l.connection.request("hydra-acp/transformer/message",{token:p,phase:"response",method:r,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(g){this.logger?.warn(`transformer ${l.name} error on ${a}: ${g.message}`);continue}let m=f?.action??"continue";if(m==="stop")return;if(m==="processing"){let g=d,h=i,y=new Set(t),v=r;await new Promise(w=>{let b=setTimeout(()=>{this.pendingClaims.delete(p)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:p,transformerName:l.name}),this.runResponseChain(h,new Set([...y,l.name]),g+1,v).then(()=>w()).catch(()=>w()))},Bt);typeof b.unref=="function"&&b.unref(),this.pendingClaims.set(p,{resolve:()=>w(),timer:b,transformerName:l.name,method:v,envelope:h,chainIdx:g,originatedBy:y,side:"response"})});return}f?.payload&&typeof f.payload=="object"&&(i=f.payload),t.add(l.name)}if(r!=="session/update")return;let u=od(i);if(u!==null){this.setAgentAdvertisedCommands(u);return}let c=sd(i);if(c!==null){this.setAgentAdvertisedModes(c);return}if(this.maybeApplyAgentModel(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentMode(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentConfigOption(i)){this.recordAndBroadcast("session/update",this.mergeAgentOptionIntoEnvelope(i));return}if(this.maybeApplyAgentUsage(o)){this.recordAndBroadcast("session/update",i);return}this.maybeApplyAgentSessionInfo(i),this.recordAndBroadcast("session/update",i)}onAgentChange(e){this.agentChangeHandlers.push(e)}get attachedCount(){return this.clients.size}connectedClients(e){let t=[];for(let s of this.clients.values()){if(e&&s.clientId===e)continue;let r={clientId:s.clientId};s.clientInfo?.name&&(r.name=s.clientInfo.name),s.clientInfo?.version&&(r.version=s.clientInfo.version),t.push(r)}return t}get turnStartedAt(){return this.promptStartedAt}get awaitingInput(){return this.attentionFlags.size>0}async isQuiescedForSwap(){return!(this.promptInFlight||this.modeChangeInFlight||this.modelChangeInFlight||await this._hasOpenToolCall())}isQuiescedSync(){return!(this.promptInFlight||this.modeChangeInFlight||this.modelChangeInFlight)}async swapUpstream(e){if(!await this.isQuiescedForSwap())throw new Error("session is not quiesced for swap \u2014 wait for in-flight work to complete");this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let s=this.agentId,r=e.newAgentId??this.agentId,o=r!==this.agentId,i=this.cwd,a=this.agentArgs,u=this.forwardedEnv,c=this.currentModel,d=this.currentMode,l=this.spawnReplacementAgent;if(!l)throw new Error("agent spawning not configured for this session");let p=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],f=await l({agentId:r,cwd:i,agentArgs:a,...u?{forwardedEnv:u}:{},mcpServers:p});this.accumulateAndResetCost(),this.wireAgent(f.agent),o||(await Ue({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedModel:c,agentReportedModel:f.initialModel,logger:this.logger}),await Be({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedMode:d,agentReportedMode:f.initialMode,logger:this.logger})),f.agent.connection.drainBuffered("session/update");let m=[];if(this.historyStore)try{m=await this.historyStore.load(this.sessionId)}catch(A){this.logger?.warn(`swapUpstream: historyStore.load failed: ${A.message}`)}let g=Ln({synopsis:e.artifact,title:e.title,tail:m,tailK:e.tailK,tailFloor:e.tailFloor,...e.summarizedThroughEntry!==void 0?{watermark:e.summarizedThroughEntry}:{}});if(this.internalPromptCapture)throw new Error("swapUpstream: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};try{await f.agent.connection.request("session/prompt",{sessionId:f.upstreamSessionId,prompt:[{type:"text",text:g}]});let A=this.internalPromptCapture;this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${g.length} toolCalls=${A.toolCalls} thinkingChars=${A.thinkingChars} messageChars=${A.messageChars} used=${A.lastUsed??"?"} size=${A.lastSize??"?"} reply=${JSON.stringify(A.chunks.join("").slice(0,200))}`)}finally{this.internalPromptCapture=void 0}let h=this.upstreamSessionId,y=this._summarizedThroughEntry;e.summarizedThroughEntry!==void 0&&(this._summarizedThroughEntry=e.summarizedThroughEntry);let v=this.agent;this.agent=f.agent,this.upstreamSessionId=f.upstreamSessionId,this.agentMeta=f.agentMeta,this.agentCapabilities=f.agentCapabilities,o&&(this.agentId=r,this.agentAdvertisedCommands=[],this.currentModel=f.initialModel,this.currentMode=f.initialMode,this.setAgentAdvertisedModels(f.initialModels??[]),this.setAgentAdvertisedModes(f.initialModes??[])),this.broadcastMergedCommands(),this.broadcastConfigOptions();for(let A of this.agentChangeHandlers)try{A({agentId:this.agentId,upstreamSessionId:this.upstreamSessionId})}catch(C){this.logger?.warn(`swapUpstream: agentChange handler failed: ${C.message}`)}if(!o&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:h,...y!==void 0?{previousSummarizedThroughEntry:y}:{}})}catch(A){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${A.message}`)}await v.kill().catch(()=>{}),this.notifyChain("agent.swap",{phase:"post",previousUpstreamSessionId:h,upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}),o||this.broadcastCompactionPhase({phase:"swapped",...this.title!==void 0?{title:this.title}:{},summarizedThroughEntry:e.summarizedThroughEntry??this._summarizedThroughEntry??0}),o&&this.broadcastAgentSwitch(s,r);let w=o?`
29
+ `))if(r.trim())try{let o=JSON.parse(r);o&&typeof o.messageId=="string"&&Array.isArray(o.prompt)&&typeof o.enqueuedAt=="number"&&s.push(o)}catch{}return s}async function Mr(n){let e=I.queueFile(n);await pe.unlink(e).catch(()=>{})}import*as Or from"fs/promises";var _r="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",$r=Tr(_r,16),qn=Tr(_r,16),Va=20,Ka=20,Ga=5,ye="hydra_session_";function ke(){return`m_${$r()}`}function Fr(n){return n.startsWith(ye)?n.slice(ye.length):n}var Ya=1e3,Bt=300*1e3,Xa=64,Pe=class n{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;agentArgs;parentSessionId;forkedFromSessionId;forkedFromMessageId;forkSynthesisState;originatingClient;_interactive;get interactive(){return this._interactive}_priority;get priority(){return this._priority}title;_summarizedThroughEntry;get summarizedThroughEntry(){return this._summarizedThroughEntry}set summarizedThroughEntry(e){this._summarizedThroughEntry=e}currentModel;currentMode;compactionState;_currentUsage;updatedAt;createdAt;clients=new Map;historyStore;promptQueue=[];currentEntry;promptInFlight=!1;modeChangeInFlight=!1;modelChangeInFlight=!1;queueWriteChain=Promise.resolve();closed=!1;closing=!1;closeInFlight;deleteRecordIntent=!1;closeHandlers=[];titleHandlers=[];scheduleSynopsisHook;scheduleCompactionHook;resolveAgentIdHook;getCompactionStateHook;getPendingAgentSwapHook;_liveCompactionPhase;broadcastHandlers=[];lastCancelAt=0;static CANCEL_ERROR_WINDOW_MS=2e3;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}promptStartedAt;appendCount=0;historyMaxEntries;compactEvery;permissionCallbacks=new Map;attentionFlags=new Map;get hasPermissionFlag(){for(let e of this.attentionFlags.values())if(e.source==="daemon"&&e.reason.startsWith("permission:"))return!0;return!1}attentionFlagsChangeHandlers=[];internalPromptCapture;idleTimeoutMs;idleTimer;idleEventTimeoutMs;idleHandlers=[];lastRecordedAt;spawnReplacementAgent;mintMcpServersForSwap;loadExistingAgentSession;clearRollbackBreadcrumbHook;onCompactionSwapHook;uncompactHook;mcpServersConfig;forwardedEnv;listSessions;logger;transformChain;extensionCommands;extensionCommandsUnsub;pendingClaims=new Map;toolCompletionSeen=new Map;toolCallKind=new Map;filesEditedSeen=new Set;agentChangeHandlers=[];agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];availableAgentsFn;modelHandlers=[];modeHandlers=[];interactiveHandlers=[];priorityHandlers=[];usageHandlers=[];cumulativeCost=0;get currentUsage(){if(!this._currentUsage&&!this.cumulativeCost)return;let e=this._currentUsage??{},t=this.cumulativeCost+(e.costAmount??0);return{...e,costAmount:t||void 0,cumulativeCost:void 0}}amendInProgress;inFlightExtensionDispatches=new Map;recentlyTerminal=new Map;streamBuffer;streamFilePath;constructor(e){if(this.sessionId=e.sessionId??`${ye}${$r()}`,this.cwd=e.cwd,this.agentId=e.agentId,this.agent=e.agent,this.upstreamSessionId=e.upstreamSessionId,this.agentMeta=e.agentMeta,this.agentCapabilities=e.agentCapabilities,this.agentArgs=e.agentArgs,this.parentSessionId=e.parentSessionId,this.forkedFromSessionId=e.forkedFromSessionId,this.forkedFromMessageId=e.forkedFromMessageId,this.forkSynthesisState=e.forkSynthesisState,this.originatingClient=e.originatingClient,this.title=e.title,this.scheduleSynopsisHook=e.scheduleSynopsis,this.scheduleCompactionHook=e.scheduleCompaction,this.resolveAgentIdHook=e.resolveAgentId,this.getCompactionStateHook=e.getCompactionState,this.getPendingAgentSwapHook=e.getPendingAgentSwap,this.currentModel=e.currentModel,this.currentMode=e.currentMode,this._currentUsage=e.currentUsage,this.cumulativeCost=e.currentUsage?.cumulativeCost??0,e.agentCommands&&e.agentCommands.length>0&&(this.agentAdvertisedCommands=[...e.agentCommands]),e.agentModes&&e.agentModes.length>0&&(this.agentAdvertisedModes=[...e.agentModes]),e.agentModels&&e.agentModels.length>0&&(this.agentAdvertisedModels=[...e.agentModels]),this.idleTimeoutMs=e.idleTimeoutMs??0,this.idleEventTimeoutMs=e.idleEventTimeoutMs??3e4,this.idleEventTimeoutMs>0&&this.onIdle(t=>t.notifyChain("session.idle",{}),{debounceMs:this.idleEventTimeoutMs}),this.spawnReplacementAgent=e.spawnReplacementAgent,this.mintMcpServersForSwap=e.mintMcpServersForSwap,this.loadExistingAgentSession=e.loadExistingAgentSession,this.clearRollbackBreadcrumbHook=e.clearRollbackBreadcrumbHook,this.onCompactionSwapHook=e.onCompactionSwapHook,this.uncompactHook=e.uncompactHook,this.mcpServersConfig=e.mcpServers,this.forwardedEnv=e.forwardedEnv,this.availableAgentsFn=e.availableAgents,this.listSessions=e.listSessions,this.logger=e.logger,this.transformChain=e.transformChain??[],this.extensionCommands=e.extensionCommands,this.extensionCommands&&(this.extensionCommandsUnsub=this.extensionCommands.onChange(()=>{this.closed||this.broadcastMergedCommands()})),e.firstPromptSeeded&&(this._firstPromptSeeded=!0),this._interactive=e.interactive,this._priority=e.priority,this._summarizedThroughEntry=e.summarizedThroughEntry,this.compactionState=e.compactionState,e.compactionState){let t=e.compactionState;(t.status==="requested"||t.status==="running"||t.status==="swap_pending"||t.status==="swap_deferred")&&(t.status==="swap_deferred"?this._liveCompactionPhase={phase:"deferred",attempts:t.attempts}:this._liveCompactionPhase={phase:t.status==="requested"?"started":"iteration",iter:t.iter})}if(e.attentionFlags&&e.attentionFlags.length>0)for(let t of e.attentionFlags)this.attentionFlags.set(`${t.source}::${t.reason}`,t);this.historyStore=e.historyStore,this.historyMaxEntries=e.historyMaxEntries??Ya,this.compactEvery=Math.max(1,Math.floor(this.historyMaxEntries*.2)),this.updatedAt=Date.now(),this.createdAt=e.createdAt??this.updatedAt,this.lastRecordedAt=this.updatedAt,this.wireAgent(this.agent),this.scheduleIdleCheck(),this.notifyChain("session.opened",{})}broadcastMergedCommands(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"available_commands_update",availableCommands:this.mergedAvailableCommands()}})}broadcastAvailableModes(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"available_modes_update",availableModes:this.agentAdvertisedModes}})}broadcastAvailableModels(){let e={sessionUpdate:"current_model_update",availableModels:[...this.agentAdvertisedModels]};this.currentModel!==void 0&&this.currentModel.length>0&&(e.currentModel=this.currentModel),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:e})}wireAgent(e){e.connection.onNotification("session/update",t=>{if(this.internalPromptCapture){rd(this.internalPromptCapture,t);return}this.maybeEmitToolEdges(t),this.runResponseChain(t)}),e.connection.onRequest("session/request_permission",async t=>{let s=await this.runAgentRequestChain("session/request_permission",t),r=Er(s.shortCircuit?t:s.envelope);if(s.shortCircuit)return this.notifyChain("permission.replied",{toolCallId:r??null,outcome:s.payload,sourceWasTransformer:!0}),s.payload;let o=await this.handlePermissionRequest(s.envelope);return this.notifyChain("permission.replied",{toolCallId:r??null,outcome:o,sourceWasTransformer:!1}),o}),typeof e.connection.onOrphanError=="function"&&e.connection.onOrphanError(t=>{this.handleOrphanError(t)}),e.onExit(()=>{this.agent===e&&this.markClosed({deleteRecord:!1})})}handleOrphanError(e){let t=Date.now()-this.lastCancelAt;if(this.lastCancelAt===0||t>n.CANCEL_ERROR_WINDOW_MS){this.logger?.warn(`agent ${this.agentId} sent uncorrelated error frame code=${e.code} message=${e.message}`);return}this.lastCancelAt=0,this.logger?.warn(`agent ${this.agentId} rejected session/cancel code=${e.code} message=${e.message}`),this.broadcastQueueNotification("hydra-acp/cancel_failed",{sessionId:this.sessionId,code:e.code,message:e.message})}async runResponseChain(e,t=new Set,s=0,r="session/update"){let o=e,i=r==="session/update"?this.injectCumulativeCost(e):e,a=`response:${r}`;for(let d=s;d<this.transformChain.length;d++){let l=this.transformChain[d];if(t.has(l.name)||!l.intercepts.has(a))continue;let p=`t_${qn()}`,f;try{f=await l.connection.request("hydra-acp/transformer/message",{token:p,phase:"response",method:r,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(g){this.logger?.warn(`transformer ${l.name} error on ${a}: ${g.message}`);continue}let m=f?.action??"continue";if(m==="stop")return;if(m==="processing"){let g=d,h=i,y=new Set(t),v=r;await new Promise(w=>{let b=setTimeout(()=>{this.pendingClaims.delete(p)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:p,transformerName:l.name}),this.runResponseChain(h,new Set([...y,l.name]),g+1,v).then(()=>w()).catch(()=>w()))},Bt);typeof b.unref=="function"&&b.unref(),this.pendingClaims.set(p,{resolve:()=>w(),timer:b,transformerName:l.name,method:v,envelope:h,chainIdx:g,originatedBy:y,side:"response"})});return}f?.payload&&typeof f.payload=="object"&&(i=f.payload),t.add(l.name)}if(r!=="session/update")return;let u=od(i);if(u!==null){this.setAgentAdvertisedCommands(u);return}let c=sd(i);if(c!==null){this.setAgentAdvertisedModes(c);return}if(this.maybeApplyAgentModel(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentMode(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentConfigOption(i)){this.recordAndBroadcast("session/update",this.mergeAgentOptionIntoEnvelope(i));return}if(this.maybeApplyAgentUsage(o)){this.recordAndBroadcast("session/update",i);return}this.maybeApplyAgentSessionInfo(i),this.recordAndBroadcast("session/update",i)}onAgentChange(e){this.agentChangeHandlers.push(e)}get attachedCount(){return this.clients.size}connectedClients(e){let t=[];for(let s of this.clients.values()){if(e&&s.clientId===e)continue;let r={clientId:s.clientId};s.clientInfo?.name&&(r.name=s.clientInfo.name),s.clientInfo?.version&&(r.version=s.clientInfo.version),t.push(r)}return t}get turnStartedAt(){return this.promptStartedAt}get awaitingInput(){return this.attentionFlags.size>0}async isQuiescedForSwap(){return!(this.promptInFlight||this.modeChangeInFlight||this.modelChangeInFlight||await this._hasOpenToolCall())}isQuiescedSync(){return!(this.promptInFlight||this.modeChangeInFlight||this.modelChangeInFlight)}async swapUpstream(e){if(!await this.isQuiescedForSwap())throw new Error("session is not quiesced for swap \u2014 wait for in-flight work to complete");this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let s=this.agentId,r=e.newAgentId??this.agentId,o=r!==this.agentId,i=this.cwd,a=this.agentArgs,u=this.forwardedEnv,c=this.currentModel,d=this.currentMode,l=this.spawnReplacementAgent;if(!l)throw new Error("agent spawning not configured for this session");let p=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],f=await l({agentId:r,cwd:i,agentArgs:a,...u?{forwardedEnv:u}:{},mcpServers:p});this.accumulateAndResetCost(),this.wireAgent(f.agent),o||(await Ue({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedModel:c,agentReportedModel:f.initialModel,logger:this.logger}),await Be({agent:f.agent,upstreamSessionId:f.upstreamSessionId,persistedMode:d,agentReportedMode:f.initialMode,logger:this.logger})),f.agent.connection.drainBuffered("session/update");let m=[];if(this.historyStore)try{m=await this.historyStore.load(this.sessionId)}catch(A){this.logger?.warn(`swapUpstream: historyStore.load failed: ${A.message}`)}let g=Ln({synopsis:e.artifact,title:e.title,tail:m,tailK:e.tailK,tailFloor:e.tailFloor,...e.summarizedThroughEntry!==void 0?{watermark:e.summarizedThroughEntry}:{}});if(this.internalPromptCapture)throw new Error("swapUpstream: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};try{await f.agent.connection.request("session/prompt",{sessionId:f.upstreamSessionId,prompt:[{type:"text",text:g}]});let A=this.internalPromptCapture;this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${g.length} toolCalls=${A.toolCalls} thinkingChars=${A.thinkingChars} messageChars=${A.messageChars} used=${A.lastUsed??"?"} size=${A.lastSize??"?"} reply=${JSON.stringify(A.chunks.join("").slice(0,200))}`)}finally{this.internalPromptCapture=void 0}let h=this.upstreamSessionId,y=this._summarizedThroughEntry;e.summarizedThroughEntry!==void 0&&(this._summarizedThroughEntry=e.summarizedThroughEntry);let v=this.agent;this.agent=f.agent,this.upstreamSessionId=f.upstreamSessionId,this.agentMeta=f.agentMeta,this.agentCapabilities=f.agentCapabilities,o&&(this.agentId=r,this.agentAdvertisedCommands=[],this.currentModel=f.initialModel,this.currentMode=f.initialMode,this.setAgentAdvertisedModels(f.initialModels??[]),this.setAgentAdvertisedModes(f.initialModes??[])),this.broadcastMergedCommands(),this.broadcastConfigOptions();for(let A of this.agentChangeHandlers)try{A({agentId:this.agentId,upstreamSessionId:this.upstreamSessionId})}catch(C){this.logger?.warn(`swapUpstream: agentChange handler failed: ${C.message}`)}if(!o&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:h,...y!==void 0?{previousSummarizedThroughEntry:y}:{}})}catch(A){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${A.message}`)}await v.kill().catch(()=>{}),this.notifyChain("agent.swap",{phase:"post",previousUpstreamSessionId:h,upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}),o||this.broadcastCompactionPhase({phase:"swapped",...this.title!==void 0?{title:this.title}:{},summarizedThroughEntry:e.summarizedThroughEntry??this._summarizedThroughEntry??0}),o&&this.broadcastAgentSwitch(s,r);let w=o?`
30
30
  Switched to ${r}.
31
31
  `:`
32
32
  Compaction completed.
@@ -69,7 +69,7 @@ ${f}.
69
69
  ${m}:
70
70
  ${p.join(`
71
71
  `)}
72
- `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}return s==="model"?(c!==this.currentModel&&await this.forwardRequest("session/set_model",{sessionId:this.sessionId,modelId:c}),this.applyModelChange(c),{stopReason:"end_turn"}):s==="mode"?(c!==this.currentMode&&await this.forwardRequest("session/set_mode",{sessionId:this.sessionId,modeId:c}),this.applyModeChange(c),{stopReason:"end_turn"}):s==="agent"?(c!==this.agentId&&await this.runAgentCommandInline(c),{stopReason:"end_turn"}):(await this.forwardRequest("session/set_config_option",{sessionId:this.sessionId,configId:s,value:c}),{stopReason:"end_turn"})}runTitleCommand(e){return this.enqueuePrompt(()=>this.runTitleCommandInline(e))}async runTitleCommandInline(e){return e?(this.setTitle(e),{stopReason:"end_turn"}):(this.scheduleSynopsisHook?.(),{stopReason:"end_turn"})}async runInternalPrompt(e){if(this.internalPromptCapture)throw new Error("internal prompt already in flight");let t={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};this.internalPromptCapture=t;try{return await this.agent.connection.request("session/prompt",{sessionId:this.upstreamSessionId,prompt:[{type:"text",text:e}]}),t.chunks.join("")}finally{this.internalPromptCapture=void 0}}setAgent(e){return this.runAgentCommand(e)}runAgentCommand(e){return this.enqueuePrompt(()=>this.runAgentCommandInline(e))}async runAgentCommandInline(e){if(e==="status")return this.runAgentStatusCommandInline();let t=e;if(!t)throw ne(new Error("/hydra agent requires an agent id"),k.InvalidParams);if(t===this.agentId)throw ne(new Error(`already on agent ${t}`),k.InvalidParams);return this.scheduleCompactionHook?(this.scheduleCompactionHook({targetAgentId:t}),this.emitExtensionReply(`Agent switch to ${t} scheduled. The session will rotate to ${t} once synthesis completes.`),{stopReason:"end_turn"}):(this.emitExtensionReply("agent switching not configured for this session"),{stopReason:"end_turn"})}async runAgentStatusCommandInline(){let e=await this.getPendingAgentSwapHook?.();return e?(this.emitExtensionReply(`Agent switch to ${e} pending \u2014 will rotate on the next idle edge.`),{stopReason:"end_turn"}):(this.emitExtensionReply("No agent switch pending."),{stopReason:"end_turn"})}async runKillCommand(){return await this.close({deleteRecord:!1}),{stopReason:"end_turn"}}runRestartCommand(){return this.enqueuePrompt(()=>this.runRestartCommandInline())}async runRestartCommandInline(){if(!this.spawnReplacementAgent)throw ne(new Error("agent restart not configured for this session"),k.InternalError);return await this.respawnAgent(),{stopReason:"end_turn"}}runCompactCommand(e){return this.enqueuePrompt(()=>this.runCompactCommandInline(e))}async runCompactCommandInline(e){return e==="status"?this.runCompactStatusCommandInline():this.scheduleCompactionHook?(this.scheduleCompactionHook(),this.emitExtensionReply("Compaction scheduled. The session will rotate to a fresh upstream once summarization completes."),{stopReason:"end_turn"}):(this.emitExtensionReply("compaction scheduling not configured for this session"),{stopReason:"end_turn"})}async runCompactStatusCommandInline(){let e=await this.getCompactionStateHook?.(),t=this._summarizedThroughEntry;if(e==null&&t==null)return this.emitExtensionReply("This session has never been compacted."),{stopReason:"end_turn"};if(e==null)return this.emitExtensionReply(`No compaction in progress. Last summarized through entry: ${t}`),{stopReason:"end_turn"};let s=[`Compaction state: ${e.status}${e.iter!=null?` (iteration ${e.iter})`:""}`,`Summarized through entry: ${t??0}`,`Pending attempts: ${e.attempts??0}`];return this.emitExtensionReply(s.join(`
72
+ `},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}return s==="model"?(c!==this.currentModel&&await this.forwardRequest("session/set_model",{sessionId:this.sessionId,modelId:c}),this.applyModelChange(c),{stopReason:"end_turn"}):s==="mode"?(c!==this.currentMode&&await this.forwardRequest("session/set_mode",{sessionId:this.sessionId,modeId:c}),this.applyModeChange(c),{stopReason:"end_turn"}):s==="agent"?(c!==this.agentId&&await this.runAgentCommandInline(c),{stopReason:"end_turn"}):(await this.forwardRequest("session/set_config_option",{sessionId:this.sessionId,configId:s,value:c}),{stopReason:"end_turn"})}runTitleCommand(e){return this.enqueuePrompt(()=>this.runTitleCommandInline(e))}async runTitleCommandInline(e){return e?(this.setTitle(e),{stopReason:"end_turn"}):(this.scheduleSynopsisHook?.(),{stopReason:"end_turn"})}async runInternalPrompt(e){if(this.internalPromptCapture)throw new Error("internal prompt already in flight");let t={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};this.internalPromptCapture=t;try{return await this.agent.connection.request("session/prompt",{sessionId:this.upstreamSessionId,prompt:[{type:"text",text:e}]}),t.chunks.join("")}finally{this.internalPromptCapture=void 0}}setAgent(e){return this.runAgentCommand(e)}runAgentCommand(e){return this.enqueuePrompt(()=>this.runAgentCommandInline(e))}async runAgentCommandInline(e){if(e==="status")return this.runAgentStatusCommandInline();let t=e;if(!t)throw ne(new Error("/hydra agent requires an agent id"),k.InvalidParams);let r=(this.resolveAgentIdHook?await this.resolveAgentIdHook(t):void 0)??t;if(r===this.agentId)throw ne(new Error(`already on agent ${r}`),k.InvalidParams);return this.scheduleCompactionHook?(this.scheduleCompactionHook({targetAgentId:r}),this.emitExtensionReply(`Agent switch to ${r} scheduled. The session will rotate to ${r} once synthesis completes.`),{stopReason:"end_turn"}):(this.emitExtensionReply("agent switching not configured for this session"),{stopReason:"end_turn"})}async runAgentStatusCommandInline(){let e=await this.getPendingAgentSwapHook?.();return e?(this.emitExtensionReply(`Agent switch to ${e} pending \u2014 will rotate on the next idle edge.`),{stopReason:"end_turn"}):(this.emitExtensionReply("No agent switch pending."),{stopReason:"end_turn"})}async runKillCommand(){return await this.close({deleteRecord:!1}),{stopReason:"end_turn"}}runRestartCommand(){return this.enqueuePrompt(()=>this.runRestartCommandInline())}async runRestartCommandInline(){if(!this.spawnReplacementAgent)throw ne(new Error("agent restart not configured for this session"),k.InternalError);return await this.respawnAgent(),{stopReason:"end_turn"}}runCompactCommand(e){return this.enqueuePrompt(()=>this.runCompactCommandInline(e))}async runCompactCommandInline(e){return e==="status"?this.runCompactStatusCommandInline():this.scheduleCompactionHook?(this.scheduleCompactionHook(),this.emitExtensionReply("Compaction scheduled. The session will rotate to a fresh upstream once summarization completes."),{stopReason:"end_turn"}):(this.emitExtensionReply("compaction scheduling not configured for this session"),{stopReason:"end_turn"})}async runCompactStatusCommandInline(){let e=await this.getCompactionStateHook?.(),t=this._summarizedThroughEntry;if(e==null&&t==null)return this.emitExtensionReply("This session has never been compacted."),{stopReason:"end_turn"};if(e==null)return this.emitExtensionReply(`No compaction in progress. Last summarized through entry: ${t}`),{stopReason:"end_turn"};let s=[`Compaction state: ${e.status}${e.iter!=null?` (iteration ${e.iter})`:""}`,`Summarized through entry: ${t??0}`,`Pending attempts: ${e.attempts??0}`];return this.emitExtensionReply(s.join(`
73
73
  `)),{stopReason:"end_turn"}}runUncompactCommand(){return this.enqueuePrompt(()=>this.runUncompactCommandInline())}async runUncompactCommandInline(){if(!this.uncompactHook)return this.emitExtensionReply("Rollback not available: uncompact hook not configured for this session."),{stopReason:"end_turn"};try{await this.uncompactHook(),this.emitExtensionReply("Rolled back to pre-compaction upstream. The session is now using the previous agent context.")}catch(e){this.emitExtensionReply(`Rollback failed: ${e instanceof Error?e.message:String(e)}`)}return{stopReason:"end_turn"}}async forceCancel(){if(this.closed||this.closing)throw ne(new Error("session is closing"),k.SessionClosing);return this.lastCancelAt=0,this.forceCancelling=!0,await this.close({deleteRecord:!1}),{stopReason:"cancelled"}}async respawnAgent(){let e=this.spawnReplacementAgent,t=this.agentId,s=await this.buildSwitchTranscript(t),r=await e({agentId:t,cwd:this.cwd,agentArgs:this.agentArgs,...this.forwardedEnv?{forwardedEnv:this.forwardedEnv}:{}});this.accumulateAndResetCost(),this.wireAgent(r.agent);let o=this.agent;this.agent=r.agent,this.upstreamSessionId=r.upstreamSessionId,this.agentMeta=r.agentMeta,this.agentCapabilities=r.agentCapabilities,this.agentAdvertisedCommands=[],this.broadcastMergedCommands(),this.currentModel=r.initialModel,this.currentMode=r.initialMode,this.setAgentAdvertisedModels(r.initialModels??[]),this.setAgentAdvertisedModes(r.initialModes??[]),await o.kill().catch(()=>{}),s&&await this.runInternalPrompt(s).catch(()=>{}),this.broadcastAgentSwitch(t,t);let i={agentId:t,upstreamSessionId:this.upstreamSessionId};for(let a of this.agentChangeHandlers)try{a(i)}catch{}}async buildSwitchTranscript(e,t){let s=[],r=await this.getHistorySnapshot();for(let c of r){if(c.method!=="session/update")continue;let l=(c.params??{}).update;if(!l||l._meta?.["hydra-acp"]?.synthetic)continue;let f=l.sessionUpdate;if(f==="prompt_received"){let m=Je(l.prompt);m&&s.push({speaker:"user",text:m})}else if(f==="agent_message_chunk"){let g=l.content?.text;g&&s.push({speaker:`agent: ${e}`,text:g})}else if(f==="tool_call"||f==="tool_call_update"){let m=l.status,g=l.title;(m==="completed"||m==="failed")&&s.push({speaker:"tool",text:`${g??"?"} ${m}`})}}if(s.length===0)return"";let o=[],i;for(let c of s)i&&i.speaker===c.speaker?i.text+=c.text:(i&&o.push(`<${i.speaker}>: ${i.text.trim()}`),i={speaker:c.speaker,text:c.text});i&&o.push(`<${i.speaker}>: ${i.text.trim()}`);let a=t?.intro??`You are taking over this conversation from ${e}. Below is the transcript so far.`,u=t?.followup??`Each line is prefixed with its speaker. Continue from where ${e} left off, responding to the user's most recent message.`;return[a,u,"","--- begin transcript ---",...o,"--- end transcript ---"].join(`
74
74
  `)}async seedFromImport(){await this.enqueuePrompt(async()=>{let e=await this.buildSwitchTranscript(this.agentId,{intro:"You are continuing a conversation that was imported from another hydra. Below is the transcript so far.",followup:"Each line is prefixed with its speaker. Treat this as context for the next user message; do not re-respond to earlier turns."});e&&await this.runInternalPrompt(e).catch(()=>{})})}async seedFromFork(e){await this.enqueuePrompt(async()=>{let t=this.title??"(untitled)",s=[];if(this.historyStore)try{s=await this.historyStore.load(this.sessionId)}catch(o){this.logger?.warn(`seedFromFork: historyStore.load failed: ${o.message}`)}let r=Ln({synopsis:e,title:t,tail:s,tailK:Ka,tailFloor:Ga,watermark:this._summarizedThroughEntry});if(this.internalPromptCapture)throw new Error("seedFromFork: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};try{await this.agent.connection.request("session/prompt",{sessionId:this.upstreamSessionId,prompt:[{type:"text",text:r}]});let o=this.internalPromptCapture;this.logger?.info(`seedFromFork: seed processed sessionId=${this.sessionId} seedChars=${r.length} toolCalls=${o.toolCalls} thinkingChars=${o.thinkingChars} messageChars=${o.messageChars}`)}finally{this.internalPromptCapture=void 0}})}broadcastAgentSwitch(e,t){this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",_meta:{"hydra-acp":{synthetic:!0,agentId:t,pendingAgentSwap:null}}}}),this.broadcastConfigOptions()}broadcastPendingAgentSwap(e){this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",_meta:{"hydra-acp":{synthetic:!0,pendingAgentSwap:e}}}})}hasStreamBuffer(){return this.streamBuffer!==void 0}get streamPath(){return this.streamFilePath}openStream(e){if(this.streamBuffer!==void 0)throw new Error(`stream buffer already open for session ${this.sessionId}`);let s=(e.mode??"memory")==="file"&&e.filePathFor!==void 0?e.filePathFor(this.sessionId):void 0,r={};e.capacityBytes!==void 0&&(r.capacityBytes=e.capacityBytes),s!==void 0&&(r.filePath=s),e.fileCapBytes!==void 0&&(r.fileCapBytes=e.fileCapBytes),r.onFileCapReached=()=>{this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"stream_truncated",...s!==void 0?{filePath:s}:{},fileCapBytes:e.fileCapBytes}})};let o=new jt(r);this.streamBuffer=o,this.streamFilePath=s;let i={capacityBytes:o.capacity};return s!==void 0&&(i.filePath=s),e.fileCapBytes!==void 0&&(i.fileCapBytes=e.fileCapBytes),i}streamWrite(e,t){let s=this.requireStreamBuffer();if(e.length>0){let r=Buffer.from(e,"base64");s.append(r)}return t===!0&&s.close(),{writeCursor:s.writeCursorPos}}async streamRead(e,t,s){let r=this.requireStreamBuffer(),o=Math.max(0,Math.min(t??De,De)),i=r.read(e,o);if(i.bytes.length===0&&i.eof!==!0&&s!==void 0&&s>0){let u=await r.waitForData(i.nextCursor,s);(u==="data"||u==="eof")&&(i=r.read(i.nextCursor,o))}let a={bytes:i.bytes.toString("base64"),nextCursor:i.nextCursor};return i.gap!==void 0&&(a.gap=i.gap),i.eof===!0&&(a.eof=!0),a}streamTail(e){let s=this.requireStreamBuffer().tail(e);return{bytes:s.bytes.toString("base64"),startCursor:s.startCursor,endCursor:s.endCursor,truncated:s.truncated}}streamHead(e){let s=this.requireStreamBuffer().head(e);return{bytes:s.bytes.toString("base64"),startCursor:s.startCursor,endCursor:s.endCursor,truncated:s.truncated}}async streamWaitFor(e,t){return this.requireStreamBuffer().waitForData(e,t)}streamGrep(e){return this.requireStreamBuffer().grep(e)}streamInfo(){let e=this.requireStreamBuffer();return{writeCursor:e.writeCursorPos,oldestAvailable:e.oldestAvailable,capacity:e.capacity,closed:e.isClosed}}requireStreamBuffer(){if(this.streamBuffer===void 0){let e=new Error(`session ${this.sessionId} has no stream buffer; POST /v1/sessions/:id/stdin/open first`);throw e.code=k.StreamNotEnabled,e}return this.streamBuffer}markClosed(e){if(this.closed)return;e={deleteRecord:e.deleteRecord||this.deleteRecordIntent},this.closing=!0,this.closed=!0,this.cancelIdleTimer(),this.extensionCommandsUnsub&&(this.extensionCommandsUnsub(),this.extensionCommandsUnsub=void 0);for(let o of[...this.inFlightExtensionDispatches.keys()])this.cancelExtensionDispatch(o,"abandoned");this.currentEntry?.kind==="user"&&!this.recentlyTerminal.has(this.currentEntry.messageId)&&this.broadcastTurnComplete(this.currentEntry.clientId,{stopReason:"interrupted"},this.currentEntry.messageId,this.currentEntry.wasAmend),this.currentEntry=void 0;let s=this.promptQueue;this.promptQueue=[];for(let o of s){o.cancelled=!0,o.kind==="user"&&this.broadcastQueueRemoved(o.messageId,"abandoned");try{o.resolve({stopReason:"cancelled"})}catch{}}this.notifyChain("session.closed",{}),this.toolCompletionSeen.clear(),this.toolCallKind.clear(),this.filesEditedSeen.clear();let r=this.sessionId;this.queueWriteChain=this.queueWriteChain.catch(()=>{}).then(()=>Mr(r).catch(()=>{}));for(let o of this.clients.values())o.connection.notify("hydra-acp/session/closed",{sessionId:this.sessionId}).catch(()=>{});if(this.clients.clear(),this.streamBuffer!==void 0){let o=this.streamBuffer,i=this.streamFilePath;this.streamBuffer=void 0,this.streamFilePath=void 0,o.close(),i!==void 0&&o.drainFileWrites().then(()=>Or.unlink(i).catch(()=>{}))}for(let o of this.closeHandlers)o(e)}get lastActivityAt(){return this.lastRecordedAt}setAttentionFlag(e,t,s){this._setAttentionFlag(e,t,s,!0)}_setAttentionFlag(e,t,s,r){let o=`${e}::${t}`,i=this.attentionFlags.get(o);if(i){if(JSON.stringify(i.payload)===JSON.stringify(s))return;this.attentionFlags.set(o,{...i,payload:s,raisedAt:i.raisedAt})}else this.attentionFlags.set(o,{source:e,reason:t,raisedAt:Date.now(),payload:s});r&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}clearAttentionFlag(e,t){this._clearAttentionFlag(e,t,!0)}_clearAttentionFlag(e,t,s){let r=`${e}::${t}`;this.attentionFlags.delete(r)&&s&&(this.broadcastAttentionUpdated(),this.fireAttentionFlagsChange())}listAttentionFlags(){return Array.from(this.attentionFlags.values()).sort((e,t)=>e.raisedAt-t.raisedAt)}listAttentionFlagsBySource(e){return this.listAttentionFlags().filter(t=>t.source===e)}onAttentionFlagsChange(e){this.attentionFlagsChangeHandlers.push(e)}fireAttentionFlagsChange(){let e=this.listAttentionFlags();for(let t of this.attentionFlagsChangeHandlers)try{t(e)}catch{}}broadcastAttentionUpdated(){for(let e of this.clients.values())e.connection.notify("hydra-acp/session/attention_updated",{sessionId:this.sessionId,flags:this.listAttentionFlags()}).catch(()=>{})}scheduleIdleCheck(){if(this.closed||this.idleTimeoutMs<=0)return;let e=this.lastActivityAt+this.idleTimeoutMs;this.armIdleTimer(Math.max(0,e-Date.now()))}armIdleTimer(e){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{this.idleTimer=void 0,this.checkIdle()},e),typeof this.idleTimer.unref=="function"&&this.idleTimer.unref()}checkIdle(){if(this.closed||this.idleTimeoutMs<=0)return;if(this.turnStartedAt!==void 0||this.hasPermissionFlag||this.promptQueue.length>0){this.armIdleTimer(this.idleTimeoutMs);return}let e=Date.now()-this.lastActivityAt;if(e<this.idleTimeoutMs){this.armIdleTimer(this.idleTimeoutMs-e);return}let t=this.firstPromptSeeded?{deleteRecord:!1}:{deleteRecord:!0},s=Math.round(e/1e3);this.logger?.info(`session ${this.sessionId} idle timeout fired after ${s}s (window=${Math.round(this.idleTimeoutMs/1e3)}s) \u2014 closing`),this.close(t).catch(()=>{})}cancelIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=void 0),this.disposeIdleHandlers()}onIdle(e,t){let s={fn:e,once:!!t?.once,debounceMs:t?.debounceMs??0};return this.idleHandlers.push(s),()=>{let r=this.idleHandlers.indexOf(s);r>=0&&this.idleHandlers.splice(r,1),s.timer&&(clearTimeout(s.timer),s.timer=void 0)}}onceIdle(e){return this.onIdle(e,{once:!0})}dispatchIdle(){if(this.closed)return;if(!this.isQuiescedSync()){for(let s of this.idleHandlers)s.timer&&(clearTimeout(s.timer),s.timer=void 0);return}let t=[...this.idleHandlers];for(let s of t){if(s.debounceMs===0){if(s.once){let r=this.idleHandlers.indexOf(s);r>=0&&this.idleHandlers.splice(r,1)}try{s.fn(this)}catch{}continue}s.timer&&(clearTimeout(s.timer),s.timer=void 0),s.timer=setTimeout(()=>{if(s.timer=void 0,!this.closed&&this.isQuiescedSync()){if(s.once){let r=this.idleHandlers.indexOf(s);r>=0&&this.idleHandlers.splice(r,1)}try{s.fn(this)}catch{}}},s.debounceMs),typeof s.timer.unref=="function"&&s.timer.unref()}}disposeIdleHandlers(){for(let e of this.idleHandlers)e.timer&&(clearTimeout(e.timer),e.timer=void 0);this.idleHandlers.length=0}maybeEmitToolEdges(e){if(!e||typeof e!="object")return;let t=e.update;if(!t||typeof t!="object")return;let s=t,r=typeof s.sessionUpdate=="string"?s.sessionUpdate:"";if(r!=="tool_call"&&r!=="tool_call_update")return;let o=typeof s.toolCallId=="string"&&s.toolCallId.length>0?s.toolCallId:void 0;if(!o)return;let i=typeof s.kind=="string"?s.kind:void 0;i&&!this.toolCallKind.has(o)&&this.toolCallKind.set(o,i);let a=i??this.toolCallKind.get(o);if(a==="edit"&&Array.isArray(s.locations))for(let d of s.locations){if(!d||typeof d!="object")continue;let l=d.path;if(typeof l!="string"||l.length===0||this.filesEditedSeen.has(l))continue;this.filesEditedSeen.add(l);let p=d.line,f={path:l,toolCallId:o};typeof p=="number"&&(f.line=p),this.notifyChain("file.edited",f)}if(r!=="tool_call_update")return;let u=typeof s.status=="string"?s.status:void 0;if(u!=="completed"&&u!=="failed"||this.toolCompletionSeen.has(o))return;this.toolCompletionSeen.set(o,u);let c={toolCallId:o,status:u};a&&(c.kind=a),s.content!==void 0&&(c.content=s.content),Array.isArray(s.locations)&&(c.locations=s.locations),this.notifyChain("tool.completed",c)}notifyChain(e,t){let s=`lifecycle:${e}`;for(let r of this.transformChain)r.intercepts.has(s)&&r.connection.notify("hydra-acp/transformer/session_event",{event:e,sessionId:this.sessionId,payload:t}).catch(()=>{})}rewriteForClient(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(typeof t.sessionId=="string"&&t.sessionId!==this.sessionId)return{...t,sessionId:this.sessionId}}return e}recordAndBroadcast(e,t,s){let r=this.rewriteForClient(t),o=!Rr(e,r),i=o?id(e,r):r;if(o){let a={method:e,params:i,recordedAt:Date.now()};if(this.lastRecordedAt=a.recordedAt,this.appendCount+=1,this.historyStore){let u=this.historyStore;u.append(this.sessionId,a).catch(()=>{}),this.appendCount>=this.compactEvery&&(this.appendCount=0,u.compact(this.sessionId,this.historyMaxEntries).catch(()=>{}))}for(let u of this.broadcastHandlers)try{u(a)}catch{}this.scheduleIdleCheck(),this.dispatchIdle()}this.updatedAt=Date.now();for(let a of this.clients.values())s&&a.clientId===s||a.connection.notify(e,i).catch(()=>{})}async requestPermissionFromClients(e){return this.handlePermissionRequest(e)}async handlePermissionRequest(e){let t=[...this.clients.values()];if(t.length===0)throw ne(new Error("no clients attached to handle permission request"),k.PermissionDenied);let s=this.rewriteForClient(e),r=Er(s),o=ke(),{toolCall:i,options:a}=s??{};return new Promise((u,c)=>{let d=!1,l=[],p=0,f,m=this.sessionId,g=v=>{d||(d=!0,this.clearAttentionFlag("daemon",`permission:${o}`),this.permissionCallbacks.delete(o),v())},h=v=>v?.code===k.MethodNotFound;function y(v){if(d)return;let w=v.connection.request("session/request_permission",s);l.push({client:v}),p++,w.then(b=>{p--,g(()=>{let A=ad({toolCallId:r,result:b,resolver:v});for(let C of l)C.client.clientId!==v.clientId&&C.client.connection.notify("session/update",{sessionId:m,update:A}).catch(()=>{});u(b)})}).catch(b=>{if(p--,h(b)||(f=b),p===0&&!d){let A=f??ne(new Error("no client handled permission request"),k.PermissionDenied);g(()=>c(A))}})}this.setAttentionFlag("daemon",`permission:${o}`,{kind:"permission",toolCall:i??null,options:a??null}),this.permissionCallbacks.set(o,y);for(let v of t)y(v)})}async enqueuePrompt(e){return new Promise((t,s)=>{let r={kind:"internal",messageId:ke(),enqueuedAt:Date.now(),cancelled:!1,task:e,resolve:t,reject:s};this.promptQueue.push(r),this.drainQueue()})}async enqueueUserPrompt(e,t,s){let r=(t??{}).prompt??[],o={clientId:e.clientId};e.clientInfo?.name&&(o.name=e.clientInfo.name),e.clientInfo?.version&&(o.version=e.clientInfo.version);let i=this.parseQueuePosition(t);return new Promise((a,u)=>{let c={kind:"user",messageId:s,originator:o,clientId:e.clientId,prompt:r,enqueuedAt:Date.now(),cancelled:!1,resolve:a,reject:u},d=this.insertEntryAt(c,i);this.persistRewrite(),this.broadcastQueueAdded(c,{position:d}),this.drainQueue()})}parseQueuePosition(e){if(!e||typeof e!="object")return"tail";let t=e._meta;if(!t||typeof t!="object"||Array.isArray(t))return"tail";let s=t["hydra-acp"];if(!s||typeof s!="object"||Array.isArray(s))return"tail";let r=s.queuePosition;if(r==="head"||r==="tail")return r;if(r&&typeof r=="object"&&!Array.isArray(r)){let o=r.afterMessageId;if(typeof o=="string"&&o.length>0)return{afterMessageId:o}}return"tail"}insertEntryAt(e,t){let s=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled?1:0;if(t==="head")return this.promptQueue.unshift(e),s;if(typeof t=="object"){let r=t.afterMessageId,o=this.promptQueue.findIndex(i=>i.messageId===r);if(o>=0)return this.promptQueue.splice(o+1,0,e),s+o+1}return this.promptQueue.push(e),s+this.promptQueue.length-1}persistRewrite(){let e=[];for(let s of this.promptQueue)s.kind!=="user"||s.cancelled||e.push(this.persistedFromEntry(s));let t=this.sessionId;this.queueWriteChain=this.queueWriteChain.catch(()=>{}).then(()=>ut(t,e).catch(()=>{}))}persistedFromEntry(e){return{messageId:e.messageId,originator:{clientInfo:{...e.originator.name!==void 0?{name:e.originator.name}:{},...e.originator.version!==void 0?{version:e.originator.version}:{}}},prompt:e.prompt,enqueuedAt:e.enqueuedAt}}async drainQueue(){if(!this.promptInFlight){this.promptInFlight=!0,await new Promise(e=>setImmediate(e));try{for(;this.promptQueue.length>0&&!this.closing;){let e=this.promptQueue.shift();if(!e)break;if(!e.cancelled){this.currentEntry=e,e.kind==="user"&&this.persistRewrite(),e.kind==="user"&&this.broadcastQueueRemoved(e.messageId,"started");try{let t=await this.runQueueEntry(e);e.resolve(t),await new Promise(s=>setImmediate(s))}catch(t){e.reject(t)}finally{this.currentEntry=void 0}}}}finally{this.promptInFlight=!1,this.dispatchIdle()}}}async runQueueEntry(e){if(e.kind==="internal")return e.task();this.broadcastPromptReceived(e);let t=Je(e.prompt).replace(/\s+$/,""),s=!t.includes(`
75
75
  `)&&t.startsWith("/")?t.split(/\s+/)[0]??"":"",r=s.startsWith("/")?s.slice(1):"",o=r.length>0&&this.aliasableBareVerbs().has(r);if(s==="/model"||s==="/mode"||s==="/sessions"||s==="/help"||s==="/hydra"||o){let a;if(s==="/sessions")a=await this.handleSessionsCommand();else if(s==="/help")a=await this.handleHelpCommand();else if(s==="/mode")a=await this.handleModeCommand(t);else if(s==="/model")a=await this.handleModelCommand(t);else if(o){let u=t.slice(s.length).trim(),c=u?`/hydra ${r} ${u}`:`/hydra ${r}`;a=await this.handleSlashCommand(c,e.messageId)}else a=await this.handleSlashCommand(t,e.messageId);return this.closed||this.broadcastTurnComplete(e.clientId,a,e.messageId,e.wasAmend),this.clearAmendIfMatches(e.messageId),a}if(this.clearRollbackBreadcrumbHook)try{this.clearRollbackBreadcrumbHook()}catch{}let i;try{i=await this.forwardRequest("session/prompt",{sessionId:this.sessionId,prompt:e.prompt},e.emitterName?new Set([e.emitterName]):new Set,e.chainStartIdx??0)}catch(a){if(this.forceCancelling)return this.clearAmendIfMatches(e.messageId),{stopReason:"cancelled"};throw this.closed||this.broadcastTurnComplete(e.clientId,{stopReason:"error"},e.messageId,e.wasAmend),this.clearAmendIfMatches(e.messageId),a}return this.closed||this.broadcastTurnComplete(e.clientId,i,e.messageId,e.wasAmend),this.clearAmendIfMatches(e.messageId),i}clearAmendIfMatches(e){this.amendInProgress?.cancelledMessageId===e&&(this.amendInProgress=void 0)}};function ne(n,e){return n.code=e,n}var Za=new Set(["session_info_update","current_model_update","current_mode_update","available_commands_update","available_modes_update","usage_update","config_option_update","hydra_compaction"]);function Rr(n,e){if(n!=="session/update")return!1;let s=(e??{}).update?.sessionUpdate;return typeof s=="string"&&Za.has(s)}function ed(n,e){if(n.length!==e.length)return!1;for(let t=0;t<n.length;t++)if(n[t]?.name!==e[t]?.name||n[t]?.description!==e[t]?.description)return!1;return!0}function td(n,e){if(n.length!==e.length)return!1;for(let t=0;t<n.length;t++)if(n[t]?.id!==e[t]?.id||n[t]?.name!==e[t]?.name||n[t]?.description!==e[t]?.description)return!1;return!0}function nd(n,e){if(n.length!==e.length)return!1;for(let t=0;t<n.length;t++)if(n[t]?.modelId!==e[t]?.modelId||n[t]?.name!==e[t]?.name||n[t]?.description!==e[t]?.description)return!1;return!0}function We(n){if(!Array.isArray(n))return[];let e=[];for(let t of n){if(!t||typeof t!="object"||Array.isArray(t))continue;let s=t,r=typeof s.modelId=="string"&&s.modelId.trim()||typeof s.value=="string"&&s.value.trim()||typeof s.id=="string"&&s.id.trim()||void 0;if(!r)continue;let o={modelId:r};typeof s.name=="string"&&s.name.length>0&&(o.name=s.name),typeof s.description=="string"&&s.description.length>0&&(o.description=s.description),e.push(o)}return e}function lt(n){if(!Array.isArray(n))return[];let e=[];for(let t of n){if(!t||typeof t!="object"||Array.isArray(t))continue;let s=t,r=typeof s.value=="string"&&s.value.trim()||typeof s.id=="string"&&s.id.trim()||void 0;if(!r)continue;let o={id:r};typeof s.name=="string"&&s.name.length>0&&(o.name=s.name),typeof s.description=="string"&&s.description.length>0&&(o.description=s.description),e.push(o)}return e}function sd(n){let t=(n??{}).update??{};if(t.sessionUpdate!=="available_modes_update")return null;let s=t.availableModes;if(!Array.isArray(s))return[];let r=[];for(let o of s){if(!o||typeof o!="object")continue;let i=o;if(typeof i.id!="string"||i.id.length===0)continue;let a={id:i.id};typeof i.name=="string"&&(a.name=i.name),typeof i.description=="string"&&(a.description=i.description),r.push(a)}return r}function rd(n,e){let s=(e??{}).update??{},r=s.sessionUpdate;if(r==="agent_message_chunk"){let o=s.content??{};typeof o.text=="string"&&(n.chunks.push(o.text),n.messageChars+=o.text.length);return}if(r==="agent_thought_chunk"){let o=s.content??{};typeof o.text=="string"&&(n.thinkingChars+=o.text.length);return}if(r==="tool_call"){n.toolCalls++;return}if(r==="usage_update"){typeof s.used=="number"&&(n.lastUsed=s.used),typeof s.size=="number"&&(n.lastSize=s.size);return}}function od(n){let t=(n??{}).update??{};if(t.sessionUpdate!=="available_commands_update")return null;let s=t.availableCommands??t.commands;if(!Array.isArray(s))return[];let r=[];for(let o of s){if(!o||typeof o!="object")continue;let i=o;if(typeof i.name!="string"||i.name.length===0)continue;let a={name:i.name};typeof i.description=="string"&&(a.description=i.description),r.push(a)}return r}function id(n,e){if(n!=="session/update"||!e||typeof e!="object")return e;let t=e;return!t.update||typeof t.update!="object"||Array.isArray(t.update)||typeof t.update.messageId=="string"?e:{...e,update:{...t.update,messageId:ke()}}}function Jn(n,e){for(let t=0;t<n.length;t++){let s=n[t];if(!s||s.method!=="session/update")continue;if(s.params?.update?.messageId===e)return t}return-1}function Er(n){if(!n||typeof n!="object")return;let e=n.toolCall;if(!e||typeof e!="object")return;let t=e.toolCallId;return typeof t=="string"?t:void 0}function ad(n){let e=dd(n.result),t={sessionUpdate:"permission_resolved"};return n.toolCallId!==void 0&&(t.toolCallId=n.toolCallId),e&&(t.outcome=e,e.kind==="selected"&&typeof e.optionId=="string"&&(t.chosenOptionId=e.optionId)),t.resolvedBy=cd(n.resolver),t}function dd(n){if(!n||typeof n!="object")return;let e=n.outcome;if(!e||typeof e!="object")return;let t=e.kind;if(typeof t!="string")return;let s={kind:t},r=e.optionId;typeof r=="string"&&(s.optionId=r);let o=e.reason;return typeof o=="string"&&(s.reason=o),s}function cd(n){let e={clientId:n.clientId};return n.clientInfo?.name&&(e.name=n.clientInfo.name),n.clientInfo?.version&&(e.version=n.clientInfo.version),e}function Je(n){return typeof n=="string"?n:Array.isArray(n)?n.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?e.text:"").join(""):""}function zn(n){return n==="session/prompt"?{stopReason:"stopped"}:{}}function ud(n){return n==="session/request_permission"?{outcome:{outcome:"cancelled"}}:{}}function Pr(n){let e=n.name&&n.name!==n.id?`${n.id} (${n.name}) \u2014 \u25B6 ${n.currentValue}`:`${n.id} \u2014 \u25B6 ${n.currentValue}`;if(n.options.length===0)return e;let t=Math.max(...n.options.map(r=>r.value.length)),s=n.options.map(r=>{let o=r.value===n.currentValue?"\u25B6":"\xB7",i=r.name&&r.name!==r.value,a=i?r.value.padEnd(t):r.value;return i?` ${o} ${a} ${r.name}`:` ${o} ${a}`});return`${e}
@@ -117,8 +117,8 @@ ${Vn}`;return zr(n,s,Ur)}function Cd(n){if(!n||typeof n!="object")return"";let e
117
117
  `,{encoding:"utf8",mode:384})})}async load(e,t={}){if(!gt.test(e))return[];let s=(t.tools??"inline")==="inline",r=this.writeQueues.get(e);r&&await r;let o;try{o=await Z.readFile(I.historyFile(e),"utf8")}catch(p){if(p.code==="ENOENT")return[];throw p}let i=[];for(let p of o.split(`
118
118
  `)){if(p.length===0)continue;let f;try{f=JSON.parse(p)}catch{continue}if(!f||typeof f!="object"||Array.isArray(f))continue;let m=f;typeof m.method=="string"&&typeof m.recordedAt=="number"&&i.push({method:m.method,params:m.params,recordedAt:m.recordedAt})}let a=t.maxEntries??this.maxEntries,u=i.length>a?i.slice(-a):i;if(!s)return u;let c=new Map,d=async p=>{let f=c.get(p);if(f!==void 0)return f;let m=await $t(e,p);return c.set(p,m),m},l=[];for(let p of u)l.push(await io(p,d));return l}async flushAll(){let e=[...this.writeQueues.values()];e.length!==0&&await Promise.allSettled(e)}async delete(e){if(gt.test(e))return this.enqueue(e,async()=>{try{await Z.unlink(I.historyFile(e))}catch(t){if(t.code!=="ENOENT")throw t}await Ws(e);try{await Z.rmdir(I.sessionDir(e))}catch(t){let s=t;if(s.code!=="ENOENT"&&s.code!=="ENOTEMPTY")throw t}})}enqueue(e,t){let r=(this.writeQueues.get(e)??Promise.resolve()).then(t,t),o=r.catch(()=>{});return this.writeQueues.set(e,o),o.finally(()=>{this.writeQueues.get(e)===o&&this.writeQueues.delete(e)}),r}};import{promises as ao}from"fs";import*as co from"path";async function uo(n,e){await ao.mkdir(co.dirname(n),{recursive:!0});let t=e.map(s=>JSON.stringify(s));await ao.writeFile(n,t.length>0?t.join(`
119
119
  `)+`
120
- `:"")}import{z as U}from"zod";var Od=U.object({method:U.string(),params:U.unknown(),recordedAt:U.number()}),Hd=U.object({sessionId:U.string(),lineageId:U.string(),upstreamSessionId:U.string().optional(),agentId:U.string(),cwd:U.string(),title:U.string().optional(),synopsis:ft.optional(),summarizedThroughEntry:U.number().int().nonnegative().optional(),currentModel:U.string().optional(),currentMode:U.string().optional(),currentUsage:Xn.optional(),agentCommands:U.array(Gn).optional(),agentModes:U.array(Yn).optional(),interactive:U.boolean().optional(),originatingClient:Zn.optional(),priority:U.number().int().nonnegative().optional(),createdAt:U.string(),updatedAt:U.string()}),Nd=U.object({version:U.literal(1),exportedAt:U.string(),exportedFrom:U.object({hydraVersion:U.string(),machine:U.string(),hydraHost:U.string().optional()}),session:Hd,history:U.array(Od),promptHistory:U.array(U.string()).optional(),toolBlobs:U.record(U.string()).optional()});function ht(n){let e={version:1,exportedAt:new Date().toISOString(),exportedFrom:{hydraVersion:n.hydraVersion,machine:n.machine,...n.hydraHost!==void 0&&n.hydraHost.length>0?{hydraHost:n.hydraHost}:{}},session:{sessionId:n.record.sessionId,lineageId:n.record.lineageId,...n.record.upstreamSessionId?{upstreamSessionId:n.record.upstreamSessionId}:{},agentId:n.record.agentId,cwd:n.record.cwd,...n.record.title!==void 0?{title:n.record.title}:{},...n.record.synopsis!==void 0?{synopsis:n.record.synopsis}:{},...n.record.summarizedThroughEntry!==void 0?{summarizedThroughEntry:n.record.summarizedThroughEntry}:{},...n.record.currentModel!==void 0?{currentModel:n.record.currentModel}:{},...n.record.currentMode!==void 0?{currentMode:n.record.currentMode}:{},...n.record.currentUsage!==void 0?{currentUsage:n.record.currentUsage}:{},...n.record.agentCommands!==void 0?{agentCommands:n.record.agentCommands}:{},...n.record.agentModes!==void 0?{agentModes:n.record.agentModes}:{},...n.record.interactive!==void 0?{interactive:n.record.interactive}:{},...n.record.originatingClient!==void 0?{originatingClient:n.record.originatingClient}:{},...n.record.priority!==void 0&&n.record.priority>0?{priority:n.record.priority}:{},createdAt:n.record.createdAt,updatedAt:n.record.updatedAt},history:n.history};return n.promptHistory!==void 0&&(e.promptHistory=n.promptHistory),n.toolBlobs!==void 0&&Object.keys(n.toolBlobs).length>0&&(e.toolBlobs=n.toolBlobs),e}function lo(n){return Nd.parse(n)}var fo=900*1e3,Bd="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Qt=jd(Bd,16),bt=class n{constructor(e,t,s,r={}){this.registry=e;this.spawner=t??(a=>he.spawn(a)),this.store=s??new Ut,this.tombstones=r.tombstones??new Dt,this.sessionHistoryMaxEntries=r.sessionHistoryMaxEntries??1e3,this.histories=new Wt({maxEntries:this.sessionHistoryMaxEntries}),this.idleTimeoutMs=r.idleTimeoutMs??0,this.idleEventTimeoutMs=r.idleEventTimeoutMs??3e4,this.defaultModels=r.defaultModels??{},this.synopsisAgent=r.synopsisAgent,this.synopsisModel=r.synopsisModel,this.compactionAgent=r.compactionAgent,this.compactionModel=r.compactionModel,this.defaultTransformers=r.defaultTransformers??[],this.logger=r.logger,this.npmRegistry=r.npmRegistry,this.extensionCommands=r.extensionCommands,this.defaultCwd=r.defaultCwd??"~";let o=r.compaction??{},i=o.tailK??20;this.compactionTailK=i,this.synopsisCoordinator=new Jt({registry:this.registry,store:this.store,histories:this.histories,synopsisAgent:this.synopsisAgent,synopsisModel:this.synopsisModel,compactionAgent:this.compactionAgent,compactionModel:this.compactionModel,compactionMaxIterations:o.maxIterations,persistTitle:async(a,u)=>{let c=this.get(a);if(c){await c.retitle(u);return}await this.persistTitle(a,u)},persistSynopsis:(a,u,c)=>this.persistSynopsis(a,u,c),logger:this.logger,npmRegistry:this.npmRegistry,onCompactionStateChange:async(a,u,c)=>{if(c.targetAgentId)return;let d=this.get(a);d&&(d.compactionState=u),await this.mutateRecord(a,{compactionState:u})},broadcastHydraCompaction:(a,u,c)=>{this.emitSwapPhase(a,c.targetAgentId,u)},onSynthesisArtifact:async(a,u,c,d)=>{await this.dispatchSynthesisSwap(a,u,c,d)}}),this.refreshAgentCatalog()}registry;sessions=new Map;resurrectionInflight=new Map;pendingAuthAgents=new Map;spawner;store;tombstones;histories;idleTimeoutMs;defaultModels;synopsisAgent;synopsisModel;compactionAgent;compactionModel;defaultTransformers;idleEventTimeoutMs;sessionHistoryMaxEntries;metaWriteQueues=new Map;listCache=new Map;static LIST_CACHE_TTL_MS=500;logger;npmRegistry;extensionCommands;defaultCwd;synopsisCoordinator;pendingDeletions=new Map;pendingSwapDisposers=new Map;rollbackLocks=new Set;compactionTailK=20;agentCatalog=[];async dispatchSynthesisSwap(e,t,s,r){let o=this.get(e);if(!o){this.logger?.info(`compaction: persisted artifact for cold session sessionId=${e}`),await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:s});return}let i=this.compactionTailK;try{if(await o.isQuiescedForSwap()){this.pendingSwapDisposers.get(e)?.(),this.pendingSwapDisposers.delete(e),await this.performSynthesisSwap(o,t,i,s,r);return}this.pendingSwapDisposers.get(e)?.(),this.logger?.info(`compaction: session not quiesced, parking onceIdle swap sessionId=${e}`),this.emitSwapPhase(e,r,{phase:"deferred"});let u=o.onceIdle(()=>{this.pendingSwapDisposers.delete(e),this.onIdleAttemptSwap(e)});this.pendingSwapDisposers.set(e,u)}catch(a){this.logger?.warn(`compaction: dispatch failed for sessionId=${e}: ${a instanceof Error?a.message:String(a)}, leaving session as-is`)}}async onIdleAttemptSwap(e){let t=this.get(e);if(!t)return;let s=this.compactionTailK;try{if(!await t.isQuiescedForSwap()){let u=await this.store.read(e).catch(()=>{});u?.synopsis&&u.summarizedThroughEntry!==void 0&&this.dispatchSynthesisSwap(e,u.synopsis,u.summarizedThroughEntry,u.pendingAgentSwap);return}let o=await this.store.read(e).catch(()=>{});if(!o?.synopsis||o.summarizedThroughEntry===void 0){this.logger?.warn(`compaction: persisted artifact missing for sessionId=${e}, abandoning swap`),t.compactionState=void 0,await this.mutateRecord(e,{},["compactionState"]);return}let i=o.pendingAgentSwap,a=await this.histories.load(e).catch(()=>[]);if(a.length>o.summarizedThroughEntry){this.logger?.info(`compaction: history grew during deferral (have=${a.length} artifact=${o.summarizedThroughEntry}), rescheduling synopsis sessionId=${e}`),i?this.synopsisCoordinator.scheduleCompaction(e,{targetAgentId:i}):this.synopsisCoordinator.scheduleCompaction(e);return}await this.performSynthesisSwap(t,o.synopsis,s,o.summarizedThroughEntry,i)}catch(r){this.logger?.warn(`compaction: onIdleAttemptSwap failed for sessionId=${e}: ${r instanceof Error?r.message:String(r)}`)}}async performSynthesisSwap(e,t,s,r,o){try{let i=o?Math.min(5,s):0;await e.swapUpstream({artifact:t,tailK:s,tailFloor:i,summarizedThroughEntry:r,...o?{newAgentId:o}:{}}),o?await this.mutateRecord(e.sessionId,{},["pendingAgentSwap"]):(e.compactionState=void 0,await this.mutateRecord(e.sessionId,{},["compactionState"]))}catch(i){this.logger?.warn(`compaction: swap failed for sessionId=${e.sessionId}: ${i instanceof Error?i.message:String(i)}, leaving session as-is`)}}async refreshAgentCatalog(){try{let{agents:e}=await Ne(this.registry);this.agentCatalog=e.map(t=>({id:t.id,name:t.name,...t.description!==void 0?{description:t.description}:{}}))}catch{}}async create(e){let t=await this.registry.getAgent(e.agentId);t&&t.id!==e.agentId&&(e={...e,agentId:t.id});let s=await this.bootstrapAgent({agentId:e.agentId,cwd:e.cwd,agentArgs:e.agentArgs,mcpServers:e.mcpServers,model:e.model,onInstallProgress:e.onInstallProgress,forwardedEnv:e.forwardedEnv});if(e.transformChain&&e.transformChain.length>0){let o={...s.agentCapabilities??{}};for(let i of e.transformChain)if(i.intercepts.has("agent:initialize"))try{let a=await i.connection.request("hydra-acp/transformer/message",{token:`t_${Qt()}`,phase:"response",method:"initialize",direction:"agent\u2192daemon",sessionId:"(pre-session)",envelope:o});a.action==="stop"&&a.payload&&(o=a.payload)}catch{}s.agentCapabilities=o}let r=new Pe({cwd:e.cwd,agentId:e.agentId,agent:s.agent,upstreamSessionId:s.upstreamSessionId,agentMeta:s.agentMeta,agentCapabilities:s.agentCapabilities,title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,idleEventTimeoutMs:this.idleEventTimeoutMs,logger:this.logger,spawnReplacementAgent:o=>this.bootstrapAgent({...o,mcpServers:o.mcpServers??[]}),loadExistingAgentSession:(o,i)=>this.bootstrapAgentLoad(o,{...i,mcpServers:i.mcpServers??[]}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:s.initialModel,currentMode:s.initialMode,agentModes:s.initialModes,agentModels:s.initialModels,transformChain:e.transformChain,parentSessionId:e.parentSessionId,originatingClient:e.originatingClient,interactive:e.interactive,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(r.sessionId),scheduleCompaction:o=>this.scheduleCompaction(r.sessionId,o),getCompactionState:()=>this.getCompactionState(r.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(r.sessionId),uncompactHook:()=>this.performUncompact(r.sessionId),onCompactionSwapHook:o=>{this.mutateRecord(r.sessionId,{rollbackBreadcrumb:o}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(r.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(r),r}async resurrect(e){let t=this.sessions.get(e.hydraSessionId);if(t){if(t.upstreamSessionId!==e.upstreamSessionId){let o=new Error(`session ${e.hydraSessionId} already exists with a different upstream id`);throw o.code=k.AlreadyAttached,o}return t}let s=this.resurrectionInflight.get(e.hydraSessionId);if(s)return s;let r=this.doResurrect(e);this.resurrectionInflight.set(e.hydraSessionId,r);try{return await r}finally{this.resurrectionInflight.delete(e.hydraSessionId)}}async doResurrect(e){let t=this.sessions.get(e.hydraSessionId);if(t)return t;let s=await this.registry.getAgent(e.agentId);if(!s){let g=new Error(`agent ${e.agentId} not found in registry; cannot resurrect`);throw g.code=k.AgentNotInstalled,g}if(e.upstreamSessionId==="")return this.doResurrectFromImport(e);if(!await this.dirExists(e.cwd))return this.doResurrectFromImport(e);let r=await te(s,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),o=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:r,...e.forwardedEnv?{extraEnv:e.forwardedEnv}:{}}),i;try{let g=await o.connection.request("initialize",{protocolVersion:1,clientCapabilities:je,clientInfo:{name:"hydra",version:K}});i=g.agentCapabilities,o.authMethods=yt(g.authMethods)}catch(g){throw await o.kill().catch(()=>{}),Ae(g,o)}let a;try{let g=po(e.agentId,e.currentModel);a=await o.connection.request("session/load",{sessionId:e.upstreamSessionId,cwd:e.cwd,mcpServers:e.mcpServers??[],...g&&{_meta:g}})}catch(g){if(g&&typeof g=="object"&&g.code===k.AuthRequired)throw await o.kill().catch(()=>{}),Ae(g,o);return process.stderr.write(`session/load failed for upstream ${e.upstreamSessionId} on ${e.agentId} (${g.message}); recovering via import-reseed
121
- `),await o.kill().catch(()=>{}),this.doResurrectFromImport(e)}if(e.pendingHistorySync===!0)this.clearPendingHistorySync(e.hydraSessionId).catch(()=>{});else{let g=o.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain1 dropped ${g} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let u=us(a??{}),c=e.agentModes??as(cs(a??{}));this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedMode=${JSON.stringify(e.currentMode)} agentReportedMode=${JSON.stringify(u)} advertisedModes=${JSON.stringify(c?.map(g=>g.id))}`);let d=await Be({agent:o,upstreamSessionId:e.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:u,advertisedModes:c,logger:this.logger});this.logger?.info(`resurrect: effectiveMode=${JSON.stringify(d)} for sessionId=${e.hydraSessionId}`);let l=is(a??{}),p=as(ds(a??{}))??e.agentModels;if(this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedModel=${JSON.stringify(e.currentModel)} agentReportedModel=${JSON.stringify(l)} advertisedModels=${JSON.stringify(p?.map(g=>g.modelId))}`),e.pendingHistorySync!==!0){let g=o.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain2 (post-mode-restore) dropped ${g} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let f=await Ue({agent:o,upstreamSessionId:e.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:l,logger:this.logger});if(e.pendingHistorySync!==!0){let g=o.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain3 (post-model-restore) dropped ${g} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let m=new Pe({sessionId:e.hydraSessionId,cwd:e.cwd,agentId:e.agentId,agent:o,upstreamSessionId:e.upstreamSessionId,agentMeta:a?._meta,agentCapabilities:i,title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,logger:this.logger,spawnReplacementAgent:g=>this.bootstrapAgent({...g,mcpServers:g.mcpServers??e.mcpServers??[]}),loadExistingAgentSession:(g,h)=>this.bootstrapAgentLoad(g,{...h,mcpServers:h.mcpServers??e.mcpServers??[]}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:f,currentMode:d,currentUsage:e.currentUsage,agentCommands:e.agentCommands,agentModes:c,agentModels:p,summarizedThroughEntry:e.summarizedThroughEntry,compactionState:e.compactionState,firstPromptSeeded:!!e.title,createdAt:e.createdAt?new Date(e.createdAt).getTime():void 0,originatingClient:e.originatingClient,interactive:e.interactive,priority:e.priority,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,attentionFlags:e.attentionFlags,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(m.sessionId),scheduleCompaction:g=>this.scheduleCompaction(m.sessionId,g),getCompactionState:()=>this.getCompactionState(m.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(m.sessionId),uncompactHook:()=>this.performUncompact(m.sessionId),onCompactionSwapHook:g=>{this.mutateRecord(m.sessionId,{rollbackBreadcrumb:g}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(m.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(m),m}async doResurrectFromImport(e){let t=await this.resolveResurrectCwd(e.cwd),s=await this.bootstrapAgent({agentId:e.agentId,cwd:t,agentArgs:e.agentArgs,mcpServers:e.mcpServers??[],onInstallProgress:e.onInstallProgress,forwardedEnv:e.forwardedEnv,model:e.currentModel}),r=e.agentModes??s.initialModes,o=await Be({agent:s.agent,upstreamSessionId:s.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:s.initialMode,advertisedModes:r,logger:this.logger}),i=e.agentModels??s.initialModels,a=await Ue({agent:s.agent,upstreamSessionId:s.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:s.initialModel,logger:this.logger});s.agent.connection.drainBuffered("session/update");let u=new Pe({sessionId:e.hydraSessionId,cwd:t,agentId:e.agentId,agent:s.agent,upstreamSessionId:s.upstreamSessionId,agentMeta:s.agentMeta,agentCapabilities:s.agentCapabilities,title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,logger:this.logger,spawnReplacementAgent:c=>this.bootstrapAgent({...c,mcpServers:c.mcpServers??e.mcpServers??[]}),loadExistingAgentSession:(c,d)=>this.bootstrapAgentLoad(c,{...d,mcpServers:d.mcpServers??e.mcpServers??[]}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:a,currentMode:o,currentUsage:e.currentUsage,agentCommands:e.agentCommands,agentModes:r,agentModels:i,summarizedThroughEntry:e.summarizedThroughEntry,firstPromptSeeded:!!e.title,createdAt:e.createdAt?new Date(e.createdAt).getTime():void 0,originatingClient:e.originatingClient,interactive:e.interactive,priority:e.priority,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,attentionFlags:e.attentionFlags,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(u.sessionId),scheduleCompaction:c=>this.scheduleCompaction(u.sessionId,c),getCompactionState:()=>this.getCompactionState(u.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(u.sessionId),uncompactHook:()=>this.performUncompact(u.sessionId),onCompactionSwapHook:c=>{this.mutateRecord(u.sessionId,{rollbackBreadcrumb:c}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(u.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(u),e.forkedFromSessionId&&e.forkSynthesisState==="running"?this.logger?.info(`fork ${u.sessionId}: synthesis in flight \u2014 skipping seed, recall available`):e.forkedFromSessionId&&(e.synopsis||(e.summarizedThroughEntry??0)>0)?u.seedFromFork(e.synopsis).catch(()=>{}):u.seedFromImport().catch(()=>{}),u}async dirExists(e){try{return(await Te.stat(e)).isDirectory()}catch{return!1}}async reapIfOrphanedNonInteractive(e){let t=this.sessions.get(e);!t||t.attachedCount>0||t.interactive!==!0&&(this.logger?.info(`reaping orphaned non-interactive session ${e} (agent killed, cold record kept)`),await t.close({deleteRecord:!1}).catch(()=>{}))}async resolveResurrectCwd(e){return await this.dirExists(e)?e:Y(this.defaultCwd)}async syncFromAgent(e){let t=await this.registry.getAgent(e);if(!t){let f=new Error(`agent ${e} not found in registry`);throw f.code=k.AgentNotInstalled,f}let s=await te(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:Vt.homedir(),plan:s}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:je,clientInfo:{name:"hydra",version:K}})}catch(f){throw await r.kill().catch(()=>{}),Ae(f,r)}if(r.authMethods=yt(o.authMethods),(o.agentCapabilities??{}).sessionCapabilities?.list===void 0)throw await r.kill().catch(()=>{}),new Error(`agent ${e} does not advertise sessionCapabilities.list; cannot sync`);let a;try{a=await this.collectAgentSessions(r)}catch(f){throw await r.kill().catch(()=>{}),f}await r.kill().catch(()=>{});let u=new Set;for(let f of this.sessions.values())u.add(`${f.agentId}::${f.upstreamSessionId}`);let c=await this.store.list().catch(()=>[]);for(let f of c)u.add(`${f.agentId}::${f.upstreamSessionId}`);let d=I.sessionsDir(),l=[],p=0;for(let f of a){let m=`${e}::${f.sessionId}`;if(u.has(m)){p+=1;continue}if(Ud(f.cwd,d)){p+=1;continue}let g=await this.tombstones.read(e,f.sessionId).catch(()=>{});if(g){if(!Lr(g,f.updatedAt)){p+=1;continue}await this.tombstones.remove(e,f.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${f.sessionId} (upstream updatedAt advanced past ${g.upstreamUpdatedAt??"<unset>"})`)}u.add(m);let h=`${ye}${Qt()}`,y=new Date().toISOString(),v=f.updatedAt??y,w={sessionId:h,lineageId:pt(),upstreamSessionId:f.sessionId,agentId:e,cwd:f.cwd,pendingHistorySync:!0,interactive:!0,createdAt:v,updatedAt:v};f.title!==void 0&&(w.title=f.title);let b=es(w);await this.store.write(b),l.push({version:1,...b})}return{synced:l,skipped:p}}async collectAgentSessions(e){let t=[],s,r=new Set;for(let o=0;o<100;o+=1){let i={};s!==void 0&&(i.cursor=s);let a=await e.connection.request("session/list",i),u=Array.isArray(a.sessions)?a.sessions:[];for(let c of u){if(typeof c.sessionId!="string"||typeof c.cwd!="string")continue;let d={sessionId:c.sessionId,cwd:c.cwd};typeof c.title=="string"&&(d.title=c.title),typeof c.updatedAt=="string"&&(d.updatedAt=c.updatedAt),t.push(d)}if(typeof a.nextCursor!="string"||a.nextCursor.length===0||r.has(a.nextCursor))break;r.add(a.nextCursor),s=a.nextCursor}return t}async applySeedModel(e,t,s,r){try{return await e.connection.request("session/set_model",{sessionId:t,modelId:s}),this.logger?.info(`${r}: session/set_model accepted`),!0}catch(o){return this.logger?.warn(`${r} rejected by agent (${o.message}); session will use the agent's own default`),!1}}async bootstrapAgent(e){let t=await this.registry.getAgent(e.agentId);if(!t){let o=new Error(`agent ${e.agentId} not found in registry`);throw o.code=k.AgentNotInstalled,o}let s=await te(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),r=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:s,...e.forwardedEnv?{extraEnv:e.forwardedEnv}:{}});try{let o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:je,clientInfo:{name:"hydra",version:K}}),i=o.agentCapabilities;r.authMethods=yt(o.authMethods);let a=await r.connection.request("session/new",{cwd:e.cwd,mcpServers:e.mcpServers??[]}),u=a.sessionId;if(typeof u!="string")throw new Error(`agent ${e.agentId} returned a non-string sessionId from session/new`);let c=is(a),d=ds(a),l=e.model??this.defaultModels[e.agentId];if(l&&l!==c){let m=qe(l,d),g=e.model!==void 0?`model=${JSON.stringify(l)}`:`defaultModels[${e.agentId}]=${JSON.stringify(l)}`;if(m.kind==="exact"||m.kind==="none")await this.applySeedModel(r,u,l,g)&&(c=l);else if(m.kind==="resolved")(m.modelId===c||await this.applySeedModel(r,u,m.modelId,`${g} resolved to ${JSON.stringify(m.modelId)}`))&&(c=m.modelId);else if(m.kind==="ambiguous")this.logger?.warn(`${g} is ambiguous (trailing-segment matches [${m.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(c)}`);else{let h=d.map(y=>y.modelId).join(", ");this.logger?.warn(`${g} not in agent's availableModels ([${h}]); skipping session/set_model, session will use ${JSON.stringify(c)}`)}}let p=cs(a),f=us(a);return{agent:r,upstreamSessionId:u,agentMeta:a._meta,agentCapabilities:i,initialModel:c,initialModels:d.length>0?d:void 0,initialModes:p.length>0?p:void 0,initialMode:f}}catch(o){throw await r.kill().catch(()=>{}),Ae(go(o,r,e.agentId,{command:s.command,args:s.args,cwd:e.cwd}),r)}}async bootstrapAgentLoad(e,t){let s=await this.registry.getAgent(t.agentId);if(!s){let i=new Error(`agent ${t.agentId} not found in registry`);throw i.code=k.AgentNotInstalled,i}let r=await te(s,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=this.spawner({agentId:t.agentId,cwd:t.cwd,plan:r,...t.forwardedEnv?{extraEnv:t.forwardedEnv}:{}});try{let i=await o.connection.request("initialize",{protocolVersion:1,clientCapabilities:je,clientInfo:{name:"hydra",version:K}}),a=i.agentCapabilities;o.authMethods=yt(i.authMethods);let u=po(t.agentId,void 0),c=await o.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...u&&{_meta:u}}),d=is(c),l=as(ds(c)),p=cs(c),f=us(c);return{agent:o,upstreamSessionId:e,agentMeta:c._meta,agentCapabilities:a,initialModel:d,initialModels:l,initialModes:p.length>0?p:void 0,initialMode:f}}catch(i){throw await o.kill().catch(()=>{}),Ae(go(i,o,t.agentId,{command:r.command,args:r.args,cwd:t.cwd}),o)}}async performUncompact(e){if(this.rollbackLocks.has(e))throw new Error("a rollback is already in progress for this session");let t=this.get(e);if(!t)throw new Error("session is not live \u2014 cannot roll back a cold session");let s=await this.store.read(e);if(!s)throw new Error("session record not found");let r=s.rollbackBreadcrumb;if(!r)throw new Error("no rollback breadcrumb found \u2014 either the session has not been compacted, the rollback window has closed (a new turn was dispatched), or a previous rollback already consumed the breadcrumb");let o=s.compactionState;if(o!=null)throw new Error(`compaction is in progress (status: ${o.status}) \u2014 wait for it to complete before rolling back`);if(!await t.isQuiescedForSwap())throw new Error("session is not quiesced for rollback \u2014 wait for in-flight work to complete");this.rollbackLocks.add(e);try{await t.rollbackToUpstream({previousUpstreamSessionId:r.previousUpstreamSessionId,previousSummarizedThroughEntry:r.previousSummarizedThroughEntry}),await this.mutateRecord(e,{summarizedThroughEntry:r.previousSummarizedThroughEntry},["synopsis","rollbackBreadcrumb"])}finally{this.rollbackLocks.delete(e)}}async bootstrapAgentForAuth(e,t){let s=this.pendingAuthAgents.get(e);if(s&&s.isAlive())return s;let r=await this.registry.getAgent(e);if(!r){let u=new Error(`agent ${e} not found in registry`);throw u.code=k.AgentNotInstalled,u}let o=await te(r,[],{npmRegistry:this.npmRegistry}),i=t??Y(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let u=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:je,clientInfo:{name:"hydra",version:K}});a.authMethods=yt(u.authMethods)}catch(u){throw await a.kill().catch(()=>{}),Ae(u,a)}return this.pendingAuthAgents.set(e,a),a.onExit(()=>{this.pendingAuthAgents.get(e)===a&&this.pendingAuthAgents.delete(e)}),a}async planSpawnForAgent(e){let t=await this.registry.getAgent(e);if(!t){let s=new Error(`agent ${e} not found in registry`);throw s.code=k.AgentNotInstalled,s}return te(t,[],{npmRegistry:this.npmRegistry})}consumePendingAuthAgent(e){let t=this.pendingAuthAgents.get(e);if(t&&(this.pendingAuthAgents.delete(e),!!t.isAlive()))return t}getAgentForSession(e){return this.sessions.get(e)?.agent}async attachManagerHooks(e){e.onClose(({deleteRecord:t})=>{if(this.sessions.delete(e.sessionId),this.invalidateListCache(),t){if(e.upstreamSessionId){let r=Ge({interactive:e.interactive,...e.originatingClient?{originatingClient:e.originatingClient}:{}},!0),o=this.tombstones.add({agentId:e.agentId,upstreamSessionId:e.upstreamSessionId,deletedAt:new Date().toISOString(),upstreamUpdatedAt:new Date(e.updatedAt).toISOString(),cwd:e.cwd,title:e.title,reason:"user",...r!==void 0?{interactive:r}:{}}).catch(()=>{}).then(()=>this.store.delete(e.sessionId).catch(()=>{})).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===o&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,o);return}let s=this.store.delete(e.sessionId).catch(()=>{}).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===s&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,s);return}}),e.onTitleChange(t=>{this.persistTitle(e.sessionId,t).catch(()=>{})}),e.onPriorityChange(t=>{this.persistPriority(e.sessionId,t).catch(()=>{})}),e.onAgentChange(({agentId:t,upstreamSessionId:s})=>{this.persistAgentChange(e.sessionId,t,s).catch(()=>{})}),e.onModelChange(t=>{this.persistSnapshot(e.sessionId,{currentModel:t}).catch(()=>{})}),e.onModeChange(t=>{this.persistSnapshot(e.sessionId,{currentMode:t}).catch(()=>{})}),e.onInteractiveChange(t=>{this.persistSnapshot(e.sessionId,{interactive:t}).catch(()=>{})}),e.onUsageChange(t=>{this.persistSnapshot(e.sessionId,{currentUsage:yo(t)}).catch(()=>{})}),e.onAgentCommandsChange(t=>{this.persistSnapshot(e.sessionId,{agentCommands:t.map(s=>({name:s.name,...s.description!==void 0?{description:s.description}:{}}))}).catch(()=>{})}),e.onAgentModesChange(t=>{this.persistSnapshot(e.sessionId,{agentModes:t.map(s=>({id:s.id,...s.name!==void 0?{name:s.name}:{},...s.description!==void 0?{description:s.description}:{}}))}).catch(()=>{})}),e.onAgentModelsChange(t=>{this.persistSnapshot(e.sessionId,{agentModels:t.map(s=>({modelId:s.modelId,...s.name!==void 0?{name:s.name}:{},...s.description!==void 0?{description:s.description}:{}}))}).catch(()=>{})}),e.onAttentionFlagsChange(t=>{this.mutateRecord(e.sessionId,{attentionFlags:t}).catch(()=>{})}),this.sessions.set(e.sessionId,e),this.invalidateListCache(),await this.enqueueMetaWrite(e.sessionId,async()=>{let t=await this.store.read(e.sessionId),s=Dd(e,t);await this.store.write(s)}).catch(()=>{})}async getHistory(e){if(this.sessions.has(e))return this.histories.load(e).catch(()=>[]);if(await this.store.read(e))return this.histories.load(e).catch(()=>[])}async loadHistory(e){return this.histories.load(e)}async loadToolBlob(e,t){return $t(e,t)}async loadFromDisk(e){let t=await this.store.read(e);if(!t)return;let s=t.title;return s||(s=await this.deriveTitleFromHistory(e)),{hydraSessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,agentId:t.agentId,cwd:t.cwd,title:s,synopsis:t.synopsis,summarizedThroughEntry:t.summarizedThroughEntry,agentArgs:t.agentArgs,currentModel:t.currentModel,currentMode:t.currentMode,currentUsage:Ld(t.currentUsage?{...t.currentUsage,cumulativeCost:(t.currentUsage.cumulativeCost??0)+(t.currentUsage.costAmount??0),costAmount:void 0}:void 0),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,forwardedEnv:t.forwardedEnv,compactionState:t.compactionState,attentionFlags:t.attentionFlags?.filter(r=>!(r.source==="daemon"&&r.reason.startsWith("permission:")))}}async setForwardedEnv(e,t){if(t===void 0)return;let s=this.sessions.get(e);s&&(s.forwardedEnv=t),await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r)return;let o={...r,forwardedEnv:t};await this.store.write(o)})}async clearPendingHistorySync(e){await this.enqueueMetaWrite(e,async()=>{let t=await this.store.read(e);if(!t||t.pendingHistorySync!==!0)return;let s={...t};delete s.pendingHistorySync,await this.store.write(s)})}async deriveTitleFromHistory(e){let t=await this.histories.load(e).catch(()=>[]);for(let s of t){let r=s.params;if(r?.update?.sessionUpdate!=="prompt_received")continue;let o=Je(r.update.prompt),i=Wn(o,200);if(i)return i}}get(e){return this.sessions.get(e)}liveSessions(){return this.sessions.values()}activeAgentVersions(){let e=new Map;for(let t of this.sessions.values()){let s=t.agent.agentId,r=t.agent.version,o=e.get(s);o||(o=new Set,e.set(s,o)),o.add(r)}return e}async resolveCanonicalId(e){if(this.sessions.has(e)||await this.store.read(e))return e;if(e.startsWith(ye))return;let t=ye+e;if(this.sessions.has(t)||await this.store.read(t))return t}require(e){let t=this.sessions.get(e);if(!t){let s=new Error(`session ${e} not found`);throw s.code=k.SessionNotFound,s}return t}liveListEntry(e){return{sessionId:e.sessionId,upstreamSessionId:e.upstreamSessionId,cwd:e.cwd,title:e.title,agentId:e.agentId,currentModel:e.currentModel,currentUsage:e.currentUsage,parentSessionId:e.parentSessionId,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,forkSynthesisState:e.forkSynthesisState,originatingClient:e.originatingClient,interactive:e.interactive,updatedAt:new Date(e.updatedAt).toISOString(),attachedClients:e.attachedCount,status:"warm",busy:e.turnStartedAt!==void 0,awaitingInput:e.awaitingInput}}async getOne(e){let t=this.sessions.get(e);if(t){let a=await wt(t.sessionId),u=Ge({interactive:t.interactive,...t.originatingClient?{originatingClient:t.originatingClient}:{}},a.hasContent),c=a.mtime??new Date(t.updatedAt).toISOString();return{sessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,cwd:t.cwd,title:t.title,agentId:t.agentId,currentModel:t.currentModel,currentUsage:t.currentUsage,parentSessionId:t.parentSessionId,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,originatingClient:t.originatingClient,interactive:u,priority:t.priority,updatedAt:c,attachedClients:t.attachedCount,status:"warm",busy:t.turnStartedAt!==void 0,awaitingInput:t.awaitingInput}}let s=await this.store.read(e).catch(()=>{});if(!s)return;let r=await wt(s.sessionId),o=Ge(s,r.hasContent),i=r.mtime??s.updatedAt;return{sessionId:s.sessionId,upstreamSessionId:s.upstreamSessionId,cwd:s.cwd,title:s.title,agentId:s.agentId,currentModel:s.currentModel,currentUsage:s.currentUsage?{...s.currentUsage,costAmount:(s.currentUsage.cumulativeCost??0)+(s.currentUsage.costAmount??0)||void 0}:void 0,importedFromMachine:s.importedFromMachine,importedFromUpstreamSessionId:s.importedFromUpstreamSessionId,parentSessionId:s.parentSessionId,forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:o,priority:s.priority,updatedAt:i,attachedClients:0,status:"cold",busy:!1,awaitingInput:!1}}async list(e={}){let t=`${e.cwd??""}|${e.includeNonInteractive?"1":"0"}`,s=Date.now(),r=this.listCache.get(t);if(r&&r.expiresAt>s)return r.promise;let o=this.listUncached(e);return this.listCache.set(t,{expiresAt:s+n.LIST_CACHE_TTL_MS,promise:o}),o.catch(()=>{let i=this.listCache.get(t);i&&i.promise===o&&this.listCache.delete(t)}),o}invalidateListCache(){this.listCache.clear()}async listUncached(e={}){let t=[],s=new Set,r=d=>e.includeNonInteractive?!0:d===!0,o=[...this.sessions.values()].filter(d=>!e.cwd||d.cwd===e.cwd),i=await Promise.all(o.map(d=>wt(d.sessionId)));for(let d=0;d<o.length;d+=1){let l=o[d],p=i[d];s.add(l.sessionId);let f=Ge({interactive:l.interactive,...l.originatingClient?{originatingClient:l.originatingClient}:{}},p.hasContent);if(!r(f))continue;let m=p.mtime??new Date(l.updatedAt).toISOString();t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,title:l.title,agentId:l.agentId,currentModel:l.currentModel,currentUsage:l.currentUsage,parentSessionId:l.parentSessionId,forkedFromSessionId:l.forkedFromSessionId,forkedFromMessageId:l.forkedFromMessageId,originatingClient:l.originatingClient,interactive:f,priority:l.priority,updatedAt:m,attachedClients:l.attachedCount,status:"warm",busy:l.turnStartedAt!==void 0,awaitingInput:l.awaitingInput,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}let u=(await this.store.list().catch(d=>{throw this.logger?.warn(`session list: store.list() failed: ${d?.message??String(d)}`),d})).filter(d=>!s.has(d.sessionId)&&(!e.cwd||d.cwd===e.cwd)),c=await Promise.all(u.map(d=>wt(d.sessionId)));for(let d=0;d<u.length;d+=1){let l=u[d],p=c[d],f=Ge(l,p.hasContent);if(!r(f))continue;let m=p.mtime??l.updatedAt;t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,title:l.title,agentId:l.agentId,currentModel:l.currentModel,currentUsage:l.currentUsage?{...l.currentUsage,costAmount:(l.currentUsage.cumulativeCost??0)+(l.currentUsage.costAmount??0)||void 0}:void 0,importedFromMachine:l.importedFromMachine,importedFromUpstreamSessionId:l.importedFromUpstreamSessionId,parentSessionId:l.parentSessionId,forkedFromSessionId:l.forkedFromSessionId,forkedFromMessageId:l.forkedFromMessageId,originatingClient:l.originatingClient,interactive:f,priority:l.priority,updatedAt:m,attachedClients:0,status:"cold",busy:!1,awaitingInput:!1,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}return t.sort((d,l)=>d.updatedAt<l.updatedAt?1:-1),t}async exportBundle(e,t={}){let s=await this.store.read(e);if(!s)return;let r;if(s.lineageId)r=s;else{let c=pt(),d={...s,lineageId:c};await this.enqueueMetaWrite(e,async()=>{let l=await this.store.read(e);l&&(l.lineageId||await this.store.write({...l,lineageId:c}))}).catch(()=>{}),r=d}let o=t.tools??"inline",i=await this.histories.load(e,o==="references"?{tools:"references"}:{}).catch(()=>[]),a=await ho(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let u={};for(let c of ro(i)){let d=await zs(e,c);d&&(u[c]=d.toString("base64"))}return{record:r,history:i,promptHistory:a,toolBlobs:u}}async importBundle(e,t={}){let s=await this.store.findByLineageId(e.session.lineageId);if(s){if(!t.replace){let i=new Error(`bundle already imported as ${s.sessionId}`);throw i.code=k.BundleAlreadyImported,i.existingSessionId=s.sessionId,i}let o=this.sessions.get(s.sessionId);return o&&await o.close({deleteRecord:!1}).catch(()=>{}),await this.writeImportedRecord({sessionId:s.sessionId,bundle:e,preservedCreatedAt:s.createdAt,cwd:t.cwd}),{sessionId:s.sessionId,importedFromSessionId:e.session.sessionId,replaced:!0}}let r=`${ye}${Qt()}`;return await this.writeImportedRecord({sessionId:r,bundle:e,cwd:t.cwd}),{sessionId:r,importedFromSessionId:e.session.sessionId,replaced:!1}}async forkSession(e,t={}){let s=await this.store.read(e);if(!s){let w=new Error(`source session not found: ${e}`);throw w.code=k.SessionNotFound,w}let r=t.agentId??s.agentId,o=r!==s.agentId;if(o&&!await this.registry.getAgent(r)){let b=new Error(`agent ${r} not found in registry`);throw b.code=k.AgentNotInstalled,b}let i=await this.histories.load(e).catch(()=>[]),a=i,u,c=t.mode??"synthesis",d,l,p,f=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let w=Jn(i,t.forkAt);if(w<0){let b=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw b.code=k.InvalidParams,b}u=t.forkAt,a=i.slice(0,w+1)}else{let w=zd(i);w?(u=w.messageId,a=i.slice(0,w.index+1)):(u="",a=i.slice(0,0))}else{t.forkAt!==void 0&&this.logger?.warn(`synthesis fork: ignoring forkAt=${t.forkAt} (synthesis covers full history)`),u="",a=i;let w=await this.registry.getAgent(r);if(!w){let b=new Error(`agent ${r} not found in registry`);throw b.code=k.AgentNotInstalled,b}p=w,l=s.currentModel,d="running"}let m=await ho(e),g=c==="synthesis",h={...s,lineageId:pt(),agentId:r,interactive:!1,...d!==void 0?{forkSynthesisState:d}:{},summarizedThroughEntry:a.length,...t.title!==void 0?{title:t.title}:{},currentUsage:void 0,...o?{currentModel:void 0,currentMode:void 0,agentCommands:void 0,agentModes:void 0,agentModels:void 0}:{},...t.model!==void 0?{currentModel:t.model}:{}},y=ht({record:h,history:a,promptHistory:m.length>0?m:void 0,hydraVersion:K,machine:Vt.hostname()}),v=`${ye}${Qt()}`;return await this.writeImportedRecord({sessionId:v,bundle:y,cwd:t.cwd,forkedFromSessionId:e,forkedFromMessageId:u,...d!==void 0?{forkSynthesisState:d}:{}}),g&&(async()=>{try{let w=await te(p,[],{npmRegistry:this.npmRegistry}),b=await zt({agentId:r,cwd:t.cwd??I.sessionDir(e),plan:w,history:i,modelId:l,sessionId:e,logger:this.logger,timeoutMs:f});b&&b.synopsis?await this.mutateRecord(v,{synopsis:b.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(v,{},["forkSynthesisState"]))}catch(w){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${w.message}`);try{await this.mutateRecord(v,{},["forkSynthesisState"])}catch(b){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${b.message}`)}}})(),{sessionId:v,forkedFromSessionId:e,forkedAt:u}}async writeImportedRecord(e){if(await this.histories.rewrite(e.sessionId,e.bundle.history),e.bundle.toolBlobs)for(let[o,i]of Object.entries(e.bundle.toolBlobs))await Js(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await Te.utimes(I.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await uo(I.tuiHistoryFile(e.sessionId),e.bundle.promptHistory).catch(()=>{});let s=new Date().toISOString(),r=e.forkedFromSessionId!==void 0;await this.enqueueMetaWrite(e.sessionId,async()=>{await this.store.write({sessionId:e.sessionId,lineageId:e.bundle.session.lineageId,upstreamSessionId:"",...r?{forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId}:{importedFromSessionId:e.bundle.session.sessionId,importedFromUpstreamSessionId:e.bundle.session.upstreamSessionId,importedFromMachine:e.bundle.exportedFrom.machine},agentId:e.bundle.session.agentId,cwd:e.cwd??e.bundle.session.cwd,title:e.bundle.session.title,synopsis:e.bundle.session.synopsis,summarizedThroughEntry:e.bundle.session.summarizedThroughEntry,...e.forkSynthesisState!==void 0?{forkSynthesisState:e.forkSynthesisState}:{},currentModel:e.bundle.session.currentModel,currentMode:e.bundle.session.currentMode,currentUsage:e.bundle.session.currentUsage,agentCommands:e.bundle.session.agentCommands,agentModes:e.bundle.session.agentModes,interactive:e.bundle.session.interactive,originatingClient:e.bundle.session.originatingClient,priority:e.bundle.session.priority,attentionFlags:[],createdAt:e.preservedCreatedAt??s,updatedAt:e.bundle.session.updatedAt})})}async deleteRecord(e,t="user"){let s=await this.store.read(e);if(!s)return!1;if(s.upstreamSessionId){let r=await wt(e),o=Ge(s,r.hasContent);await this.tombstones.add({agentId:s.agentId,upstreamSessionId:s.upstreamSessionId,deletedAt:new Date().toISOString(),upstreamUpdatedAt:s.updatedAt,cwd:s.cwd,title:s.title,reason:t,...o!==void 0?{interactive:o}:{}}).catch(()=>{})}return await this.store.delete(e).catch(()=>{}),await this.histories.delete(e).catch(()=>{}),this.invalidateListCache(),!0}async waitForDeletion(e){let t=this.pendingDeletions.get(e);t&&await t}async isTombstoned(e,t){return(await this.tombstones.read(e,t).catch(()=>{}))?.reason==="user"}async hasRecord(e){return await this.store.read(e).catch(()=>{})!==void 0}async setPriority(e,t){let s=this.get(e);if(s)return s.setPriority(t),!0;if(!await this.hasRecord(e))return!1;let r=t===void 0||t<=0?void 0:Math.floor(t);return await this.persistPriority(e,r),!0}async persistPriority(e,t){t===void 0?await this.mutateRecord(e,{},["priority"]):await this.mutateRecord(e,{priority:t}),this.invalidateListCache()}async setTitle(e,t){let s=this.get(e);return s?(await s.retitle(t),!0):await this.hasRecord(e)?(await this.persistTitle(e,t),!0):!1}async persistTitle(e,t){await this.mutateRecord(e,{title:t})}async persistSynopsis(e,t,s){await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:s})}async persistAgentChange(e,t,s){await this.mutateRecord(e,{agentId:t,upstreamSessionId:s})}async persistSnapshot(e,t){let s={};t.currentModel!==void 0&&(s.currentModel=t.currentModel),t.currentMode!==void 0&&(s.currentMode=t.currentMode),t.currentUsage!==void 0&&(s.currentUsage=t.currentUsage),t.agentCommands!==void 0&&(s.agentCommands=t.agentCommands),t.agentModes!==void 0&&(s.agentModes=t.agentModes),t.agentModels!==void 0&&(s.agentModels=t.agentModels),t.interactive!==void 0&&(s.interactive=t.interactive),t.cwd!==void 0&&(s.cwd=t.cwd),await this.mutateRecord(e,s)}async mutateRecord(e,t,s=[]){await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r)return;let o={...r,...t,updatedAt:new Date().toISOString()};for(let i of s)delete o[i];await this.store.write(o)})}enqueueMetaWrite(e,t){let r=(this.metaWriteQueues.get(e)??Promise.resolve()).catch(()=>{}).then(t),o=r.catch(()=>{});return this.metaWriteQueues.set(e,o),o.finally(()=>{this.metaWriteQueues.get(e)===o&&this.metaWriteQueues.delete(e)}),r}async closeAll(){let e=[...this.sessions.values()];await Promise.allSettled(e.map(t=>t.close({deleteRecord:!1}))),this.sessions.clear()}async flushSynopsis(e){await this.synopsisCoordinator.flush(e)}async shutdownSynopsis(){await this.synopsisCoordinator.shutdown()}scheduleSynopsis(e){this.synopsisCoordinator.schedule(e)}scheduleCompaction(e,t){t?.targetAgentId&&this.mutateRecord(e,{pendingAgentSwap:t.targetAgentId}).catch(s=>{this.logger?.warn(`scheduleCompaction: failed to stamp pendingAgentSwap for ${e}: ${s instanceof Error?s.message:String(s)}`)}),this.synopsisCoordinator.scheduleCompaction(e,t)}getCompactionInFlight(){let e=this.synopsisCoordinator.size();return e.inflight>0||e.queued>0}async getPendingAgentSwap(e){return(await this.store.read(e).catch(()=>{}))?.pendingAgentSwap}async getCompactionState(e){return(await this.store.read(e).catch(()=>{}))?.compactionState}async getRollbackBreadcrumb(e){return(await this.store.read(e).catch(()=>{}))?.rollbackBreadcrumb}emitSwapPhase(e,t,s){let r=this.get(e);if(r){if(t){let o=s.phase==="failed";r.broadcastPendingAgentSwap(o?null:t);return}r.broadcastCompactionPhase(s)}}async getSummarizedThroughEntry(e){let t=this.sessions.get(e);return t?t.summarizedThroughEntry:(await this.store.read(e).catch(()=>{}))?.summarizedThroughEntry}async flushMetaWrites(){let e=[...this.metaWriteQueues.values()];e.length!==0&&await Promise.allSettled(e)}async flushHistoryWrites(){await this.histories.flushAll()}async reconcilePermissionFlags(){let e=await this.store.list().catch(()=>[]),t=0;for(let s of e){let r=s.attentionFlags??[],o=r.filter(i=>!(i.source==="daemon"&&i.reason.startsWith("permission:")));if(o.length!==r.length){let i=r.length-o.length;t+=i,await this.mutateRecord(s.sessionId,{attentionFlags:o}).catch(()=>{})}}t>0&&this.logger?.info(`cleared ${t} stale permission attention flags on startup`)}async resumePendingCompactions(){let e=new Set(["requested","running","swap_pending","swap_deferred"]),t=await this.store.list().catch(()=>[]);for(let s of t){let r=s.compactionState;if(r!=null){if(!e.has(r.status)){this.logger?.info(`compaction: not resuming sessionId=${s.sessionId} status=${r.status} (terminal \u2014 user must re-trigger explicitly)`);continue}this.logger?.info(`compaction: resuming sessionId=${s.sessionId} status=${r.status} from prior daemon`);try{this.scheduleCompaction(s.sessionId)}catch(o){this.logger?.warn(`compaction: resume failed for sessionId=${s.sessionId}: ${o instanceof Error?o.message:String(o)}`)}}}}async resumePendingAgentSwaps(){let e=await this.store.list().catch(()=>[]);for(let t of e){let s=t.pendingAgentSwap;if(s)try{let r=await this.histories.load(t.sessionId).catch(()=>[]);t.synopsis!==void 0&&t.summarizedThroughEntry!==void 0&&t.summarizedThroughEntry>=r.length&&t.synopsis?(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${s} with persisted synopsis (history=${r.length})`),await this.dispatchSynthesisSwap(t.sessionId,t.synopsis,t.summarizedThroughEntry??r.length,s)):(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${s} via fresh synthesis (history=${r.length} watermark=${t.summarizedThroughEntry??"(none)"})`),this.scheduleCompaction(t.sessionId,{targetAgentId:s}))}catch(r){this.logger?.warn(`agent-swap: resume failed for sessionId=${t.sessionId}: ${r instanceof Error?r.message:String(r)}`)}}}async resurrectPendingQueues(){let e=await this.store.list().catch(()=>[]);for(let t of e){let s=await xr(t.sessionId).catch(()=>[]);if(s.length===0)continue;let r=Date.now(),o=s.filter(u=>r-u.enqueuedAt<fo),i=s.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${fo/1e3}s)`),await ut(t.sessionId,o).catch(()=>{})),o.length===0)continue;let a=await this.loadFromDisk(t.sessionId).catch(()=>{});if(!a){this.logger?.warn(`queue replay: no meta for ${t.sessionId}; discarding ${o.length} entr${o.length===1?"y":"ies"}`),await ut(t.sessionId,[]).catch(()=>{});continue}try{let u=await this.resurrect(a);this.logger?.info(`queue replay: resurrected ${t.sessionId} and replaying ${o.length} prompt(s)`),u.replayPersistedQueue(o)}catch(u){this.logger?.warn(`queue replay: failed to resurrect ${t.sessionId}: ${u.message}`)}}}};function Ud(n,e){if(typeof n!="string"||n.length===0)return!1;let t=vt.resolve(n),s=vt.resolve(e);return t===s||t.startsWith(s+vt.sep)}function Dd(n,e){let s=(n.mergedAvailableCommands().length>0?n.agentOnlyAdvertisedCommands().map(d=>d.description!==void 0?{name:d.name,description:d.description}:{name:d.name}):void 0)??e?.agentCommands,r=n.availableModes(),i=(r.length>0?r.map(d=>{let l={id:d.id};return d.name!==void 0&&(l.name=d.name),d.description!==void 0&&(l.description=d.description),l}):void 0)??e?.agentModes,a=n.availableModels(),c=(a.length>0?a.map(d=>{let l={modelId:d.modelId};return d.name!==void 0&&(l.name=d.name),d.description!==void 0&&(l.description=d.description),l}):void 0)??e?.agentModels;return es({sessionId:n.sessionId,lineageId:e?.lineageId??pt(),upstreamSessionId:n.upstreamSessionId,importedFromSessionId:e?.importedFromSessionId,importedFromUpstreamSessionId:e?.importedFromUpstreamSessionId,importedFromMachine:e?.importedFromMachine,agentId:n.agentId,cwd:n.cwd,title:n.title,synopsis:e?.synopsis,summarizedThroughEntry:e?.summarizedThroughEntry,agentArgs:n.agentArgs,currentModel:n.currentModel??e?.currentModel,currentMode:n.currentMode??e?.currentMode,currentUsage:yo(n.currentUsage)??e?.currentUsage,agentCommands:s,agentModes:i,agentModels:c,parentSessionId:n.parentSessionId??e?.parentSessionId,forkedFromSessionId:n.forkedFromSessionId??e?.forkedFromSessionId,forkedFromMessageId:n.forkedFromMessageId??e?.forkedFromMessageId,originatingClient:n.originatingClient??e?.originatingClient,interactive:n.interactive??e?.interactive,priority:n.priority??e?.priority,forwardedEnv:n.forwardedEnv??e?.forwardedEnv,attentionFlags:n.listAttentionFlags(),createdAt:e?.createdAt??new Date(n.createdAt).toISOString()})}function yo(n){if(!n)return;let e={};return n.used!==void 0&&(e.used=n.used),n.size!==void 0&&(e.size=n.size),n.costAmount!==void 0&&(e.costAmount=n.costAmount),n.costCurrency!==void 0&&(e.costCurrency=n.costCurrency),n.cumulativeCost!==void 0&&(e.cumulativeCost=n.cumulativeCost),Object.keys(e).length>0?e:void 0}function Ld(n){return n?{...n}:void 0}function po(n,e){if(e&&n==="claude-acp")return{claudeCode:{options:{model:e}}}}function Kt(n,e){let t=e.fromObject(n);if(t!==void 0)return t;let s=n[e.nestedKey];if(s&&typeof s=="object"&&!Array.isArray(s)){let i=e.fromObject(s);if(i!==void 0)return i}let r=n._meta;if(r&&typeof r=="object"&&!Array.isArray(r)){for(let[i,a]of Object.entries(r))if(i!=="hydra-acp"&&a&&typeof a=="object"&&!Array.isArray(a)){let u=e.fromObject(a);if(u!==void 0)return u}}let o=qd(n,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function is(n){return Kt(n,{nestedKey:"models",configId:"model",fromObject:e=>ge(e.currentModelId)??ge(e.currentModel)??ge(e.modelId)??ge(e.model),fromConfig:e=>ge(e.currentValue)})}function Ae(n,e){if(!n||typeof n!="object")return n;let t=n;if(t.code!==k.AuthRequired)return n;let s=c=>!!c&&typeof c=="object"&&!Array.isArray(c),r=s(t.data)?t.data:{},o=s(r._meta)?r._meta:{},i=s(o["hydra-acp"])?o["hydra-acp"]:{},a=typeof t.message=="string"?t.message:"authentication required",u=new Error(a);return u.code=k.AuthRequired,u.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},u}function mo(n){return/^[A-Za-z0-9_\-./=:@]+$/.test(n)?n:`'${n.replace(/'/g,"'\\''")}'`}function go(n,e,t,s){if(n&&typeof n=="object"&&n.code===k.AuthRequired)return n;let r=n instanceof Error?n.message:String(n),o=r.includes("stderr:"),i=o?"":e.stderrTailText(),a=s?`to reproduce: (cd ${mo(s.cwd)} && ${[s.command,...s.args].map(mo).join(" ")})`:"";if(!i&&!a)return n;let u=[o?r:`agent ${t} failed to start: ${r}`];i&&u.push(`stderr: ${i}`),a&&u.push(a);let c=new Error(u.join(`
120
+ `:"")}import{z as U}from"zod";var Od=U.object({method:U.string(),params:U.unknown(),recordedAt:U.number()}),Hd=U.object({sessionId:U.string(),lineageId:U.string(),upstreamSessionId:U.string().optional(),agentId:U.string(),cwd:U.string(),title:U.string().optional(),synopsis:ft.optional(),summarizedThroughEntry:U.number().int().nonnegative().optional(),currentModel:U.string().optional(),currentMode:U.string().optional(),currentUsage:Xn.optional(),agentCommands:U.array(Gn).optional(),agentModes:U.array(Yn).optional(),interactive:U.boolean().optional(),originatingClient:Zn.optional(),priority:U.number().int().nonnegative().optional(),createdAt:U.string(),updatedAt:U.string()}),Nd=U.object({version:U.literal(1),exportedAt:U.string(),exportedFrom:U.object({hydraVersion:U.string(),machine:U.string(),hydraHost:U.string().optional()}),session:Hd,history:U.array(Od),promptHistory:U.array(U.string()).optional(),toolBlobs:U.record(U.string()).optional()});function ht(n){let e={version:1,exportedAt:new Date().toISOString(),exportedFrom:{hydraVersion:n.hydraVersion,machine:n.machine,...n.hydraHost!==void 0&&n.hydraHost.length>0?{hydraHost:n.hydraHost}:{}},session:{sessionId:n.record.sessionId,lineageId:n.record.lineageId,...n.record.upstreamSessionId?{upstreamSessionId:n.record.upstreamSessionId}:{},agentId:n.record.agentId,cwd:n.record.cwd,...n.record.title!==void 0?{title:n.record.title}:{},...n.record.synopsis!==void 0?{synopsis:n.record.synopsis}:{},...n.record.summarizedThroughEntry!==void 0?{summarizedThroughEntry:n.record.summarizedThroughEntry}:{},...n.record.currentModel!==void 0?{currentModel:n.record.currentModel}:{},...n.record.currentMode!==void 0?{currentMode:n.record.currentMode}:{},...n.record.currentUsage!==void 0?{currentUsage:n.record.currentUsage}:{},...n.record.agentCommands!==void 0?{agentCommands:n.record.agentCommands}:{},...n.record.agentModes!==void 0?{agentModes:n.record.agentModes}:{},...n.record.interactive!==void 0?{interactive:n.record.interactive}:{},...n.record.originatingClient!==void 0?{originatingClient:n.record.originatingClient}:{},...n.record.priority!==void 0&&n.record.priority>0?{priority:n.record.priority}:{},createdAt:n.record.createdAt,updatedAt:n.record.updatedAt},history:n.history};return n.promptHistory!==void 0&&(e.promptHistory=n.promptHistory),n.toolBlobs!==void 0&&Object.keys(n.toolBlobs).length>0&&(e.toolBlobs=n.toolBlobs),e}function lo(n){return Nd.parse(n)}var fo=900*1e3,Bd="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Qt=jd(Bd,16),bt=class n{constructor(e,t,s,r={}){this.registry=e;this.spawner=t??(a=>he.spawn(a)),this.store=s??new Ut,this.tombstones=r.tombstones??new Dt,this.sessionHistoryMaxEntries=r.sessionHistoryMaxEntries??1e3,this.histories=new Wt({maxEntries:this.sessionHistoryMaxEntries}),this.idleTimeoutMs=r.idleTimeoutMs??0,this.idleEventTimeoutMs=r.idleEventTimeoutMs??3e4,this.defaultModels=r.defaultModels??{},this.synopsisAgent=r.synopsisAgent,this.synopsisModel=r.synopsisModel,this.compactionAgent=r.compactionAgent,this.compactionModel=r.compactionModel,this.defaultTransformers=r.defaultTransformers??[],this.logger=r.logger,this.npmRegistry=r.npmRegistry,this.extensionCommands=r.extensionCommands,this.defaultCwd=r.defaultCwd??"~";let o=r.compaction??{},i=o.tailK??20;this.compactionTailK=i,this.synopsisCoordinator=new Jt({registry:this.registry,store:this.store,histories:this.histories,synopsisAgent:this.synopsisAgent,synopsisModel:this.synopsisModel,compactionAgent:this.compactionAgent,compactionModel:this.compactionModel,compactionMaxIterations:o.maxIterations,persistTitle:async(a,u)=>{let c=this.get(a);if(c){await c.retitle(u);return}await this.persistTitle(a,u)},persistSynopsis:(a,u,c)=>this.persistSynopsis(a,u,c),logger:this.logger,npmRegistry:this.npmRegistry,onCompactionStateChange:async(a,u,c)=>{if(c.targetAgentId)return;let d=this.get(a);d&&(d.compactionState=u),await this.mutateRecord(a,{compactionState:u})},broadcastHydraCompaction:(a,u,c)=>{this.emitSwapPhase(a,c.targetAgentId,u)},onSynthesisArtifact:async(a,u,c,d)=>{await this.dispatchSynthesisSwap(a,u,c,d)}}),this.refreshAgentCatalog()}registry;sessions=new Map;resurrectionInflight=new Map;pendingAuthAgents=new Map;spawner;store;tombstones;histories;idleTimeoutMs;defaultModels;synopsisAgent;synopsisModel;compactionAgent;compactionModel;defaultTransformers;idleEventTimeoutMs;sessionHistoryMaxEntries;metaWriteQueues=new Map;listCache=new Map;static LIST_CACHE_TTL_MS=500;logger;npmRegistry;extensionCommands;defaultCwd;synopsisCoordinator;pendingDeletions=new Map;pendingSwapDisposers=new Map;rollbackLocks=new Set;compactionTailK=20;agentCatalog=[];async dispatchSynthesisSwap(e,t,s,r){let o=this.get(e);if(!o){this.logger?.info(`compaction: persisted artifact for cold session sessionId=${e}`),await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:s});return}let i=this.compactionTailK;try{if(await o.isQuiescedForSwap()){this.pendingSwapDisposers.get(e)?.(),this.pendingSwapDisposers.delete(e),await this.performSynthesisSwap(o,t,i,s,r);return}this.pendingSwapDisposers.get(e)?.(),this.logger?.info(`compaction: session not quiesced, parking onceIdle swap sessionId=${e}`),this.emitSwapPhase(e,r,{phase:"deferred"});let u=o.onceIdle(()=>{this.pendingSwapDisposers.delete(e),this.onIdleAttemptSwap(e)});this.pendingSwapDisposers.set(e,u)}catch(a){this.logger?.warn(`compaction: dispatch failed for sessionId=${e}: ${a instanceof Error?a.message:String(a)}, leaving session as-is`)}}async onIdleAttemptSwap(e){let t=this.get(e);if(!t)return;let s=this.compactionTailK;try{if(!await t.isQuiescedForSwap()){let u=await this.store.read(e).catch(()=>{});u?.synopsis&&u.summarizedThroughEntry!==void 0&&this.dispatchSynthesisSwap(e,u.synopsis,u.summarizedThroughEntry,u.pendingAgentSwap);return}let o=await this.store.read(e).catch(()=>{});if(!o?.synopsis||o.summarizedThroughEntry===void 0){this.logger?.warn(`compaction: persisted artifact missing for sessionId=${e}, abandoning swap`),t.compactionState=void 0,await this.mutateRecord(e,{},["compactionState"]);return}let i=o.pendingAgentSwap,a=await this.histories.load(e).catch(()=>[]);if(a.length>o.summarizedThroughEntry){this.logger?.info(`compaction: history grew during deferral (have=${a.length} artifact=${o.summarizedThroughEntry}), rescheduling synopsis sessionId=${e}`),i?this.synopsisCoordinator.scheduleCompaction(e,{targetAgentId:i}):this.synopsisCoordinator.scheduleCompaction(e);return}await this.performSynthesisSwap(t,o.synopsis,s,o.summarizedThroughEntry,i)}catch(r){this.logger?.warn(`compaction: onIdleAttemptSwap failed for sessionId=${e}: ${r instanceof Error?r.message:String(r)}`)}}async performSynthesisSwap(e,t,s,r,o){try{let i=o?Math.min(5,s):0;await e.swapUpstream({artifact:t,tailK:s,tailFloor:i,summarizedThroughEntry:r,...o?{newAgentId:o}:{}}),o?await this.mutateRecord(e.sessionId,{},["pendingAgentSwap"]):(e.compactionState=void 0,await this.mutateRecord(e.sessionId,{},["compactionState"]))}catch(i){this.logger?.warn(`compaction: swap failed for sessionId=${e.sessionId}: ${i instanceof Error?i.message:String(i)}, leaving session as-is`)}}async refreshAgentCatalog(){try{let{agents:e}=await Ne(this.registry);this.agentCatalog=e.map(t=>({id:t.id,name:t.name,...t.description!==void 0?{description:t.description}:{}}))}catch{}}async create(e){let t=await this.registry.getAgent(e.agentId);t&&t.id!==e.agentId&&(e={...e,agentId:t.id});let s=await this.bootstrapAgent({agentId:e.agentId,cwd:e.cwd,agentArgs:e.agentArgs,mcpServers:e.mcpServers,model:e.model,onInstallProgress:e.onInstallProgress,forwardedEnv:e.forwardedEnv});if(e.transformChain&&e.transformChain.length>0){let o={...s.agentCapabilities??{}};for(let i of e.transformChain)if(i.intercepts.has("agent:initialize"))try{let a=await i.connection.request("hydra-acp/transformer/message",{token:`t_${Qt()}`,phase:"response",method:"initialize",direction:"agent\u2192daemon",sessionId:"(pre-session)",envelope:o});a.action==="stop"&&a.payload&&(o=a.payload)}catch{}s.agentCapabilities=o}let r=new Pe({cwd:e.cwd,agentId:e.agentId,agent:s.agent,upstreamSessionId:s.upstreamSessionId,agentMeta:s.agentMeta,agentCapabilities:s.agentCapabilities,title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,idleEventTimeoutMs:this.idleEventTimeoutMs,logger:this.logger,spawnReplacementAgent:o=>this.bootstrapAgent({...o,mcpServers:o.mcpServers??[]}),loadExistingAgentSession:(o,i)=>this.bootstrapAgentLoad(o,{...i,mcpServers:i.mcpServers??[]}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:s.initialModel,currentMode:s.initialMode,agentModes:s.initialModes,agentModels:s.initialModels,transformChain:e.transformChain,parentSessionId:e.parentSessionId,originatingClient:e.originatingClient,interactive:e.interactive,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(r.sessionId),scheduleCompaction:o=>this.scheduleCompaction(r.sessionId,o),resolveAgentId:async o=>(await this.registry.getAgent(o))?.id,getCompactionState:()=>this.getCompactionState(r.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(r.sessionId),uncompactHook:()=>this.performUncompact(r.sessionId),onCompactionSwapHook:o=>{this.mutateRecord(r.sessionId,{rollbackBreadcrumb:o}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(r.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(r),r}async resurrect(e){let t=this.sessions.get(e.hydraSessionId);if(t){if(t.upstreamSessionId!==e.upstreamSessionId){let o=new Error(`session ${e.hydraSessionId} already exists with a different upstream id`);throw o.code=k.AlreadyAttached,o}return t}let s=this.resurrectionInflight.get(e.hydraSessionId);if(s)return s;let r=this.doResurrect(e);this.resurrectionInflight.set(e.hydraSessionId,r);try{return await r}finally{this.resurrectionInflight.delete(e.hydraSessionId)}}async doResurrect(e){let t=this.sessions.get(e.hydraSessionId);if(t)return t;let s=await this.registry.getAgent(e.agentId);if(!s){let g=new Error(`agent ${e.agentId} not found in registry; cannot resurrect`);throw g.code=k.AgentNotInstalled,g}if(e.upstreamSessionId==="")return this.doResurrectFromImport(e);if(!await this.dirExists(e.cwd))return this.doResurrectFromImport(e);let r=await te(s,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),o=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:r,...e.forwardedEnv?{extraEnv:e.forwardedEnv}:{}}),i;try{let g=await o.connection.request("initialize",{protocolVersion:1,clientCapabilities:je,clientInfo:{name:"hydra",version:K}});i=g.agentCapabilities,o.authMethods=yt(g.authMethods)}catch(g){throw await o.kill().catch(()=>{}),Ae(g,o)}let a;try{let g=po(e.agentId,e.currentModel);a=await o.connection.request("session/load",{sessionId:e.upstreamSessionId,cwd:e.cwd,mcpServers:e.mcpServers??[],...g&&{_meta:g}})}catch(g){if(g&&typeof g=="object"&&g.code===k.AuthRequired)throw await o.kill().catch(()=>{}),Ae(g,o);return process.stderr.write(`session/load failed for upstream ${e.upstreamSessionId} on ${e.agentId} (${g.message}); recovering via import-reseed
121
+ `),await o.kill().catch(()=>{}),this.doResurrectFromImport(e)}if(e.pendingHistorySync===!0)this.clearPendingHistorySync(e.hydraSessionId).catch(()=>{});else{let g=o.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain1 dropped ${g} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let u=us(a??{}),c=e.agentModes??as(cs(a??{}));this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedMode=${JSON.stringify(e.currentMode)} agentReportedMode=${JSON.stringify(u)} advertisedModes=${JSON.stringify(c?.map(g=>g.id))}`);let d=await Be({agent:o,upstreamSessionId:e.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:u,advertisedModes:c,logger:this.logger});this.logger?.info(`resurrect: effectiveMode=${JSON.stringify(d)} for sessionId=${e.hydraSessionId}`);let l=is(a??{}),p=as(ds(a??{}))??e.agentModels;if(this.logger?.info(`resurrect: sessionId=${e.hydraSessionId} persistedModel=${JSON.stringify(e.currentModel)} agentReportedModel=${JSON.stringify(l)} advertisedModels=${JSON.stringify(p?.map(g=>g.modelId))}`),e.pendingHistorySync!==!0){let g=o.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain2 (post-mode-restore) dropped ${g} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let f=await Ue({agent:o,upstreamSessionId:e.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:l,logger:this.logger});if(e.pendingHistorySync!==!0){let g=o.connection.drainBuffered("session/update");this.logger?.info(`resurrect: drain3 (post-model-restore) dropped ${g} buffered session/update(s) for sessionId=${e.hydraSessionId}`)}let m=new Pe({sessionId:e.hydraSessionId,cwd:e.cwd,agentId:e.agentId,agent:o,upstreamSessionId:e.upstreamSessionId,agentMeta:a?._meta,agentCapabilities:i,title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,logger:this.logger,spawnReplacementAgent:g=>this.bootstrapAgent({...g,mcpServers:g.mcpServers??e.mcpServers??[]}),loadExistingAgentSession:(g,h)=>this.bootstrapAgentLoad(g,{...h,mcpServers:h.mcpServers??e.mcpServers??[]}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:f,currentMode:d,currentUsage:e.currentUsage,agentCommands:e.agentCommands,agentModes:c,agentModels:p,summarizedThroughEntry:e.summarizedThroughEntry,compactionState:e.compactionState,firstPromptSeeded:!!e.title,createdAt:e.createdAt?new Date(e.createdAt).getTime():void 0,originatingClient:e.originatingClient,interactive:e.interactive,priority:e.priority,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,attentionFlags:e.attentionFlags,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(m.sessionId),scheduleCompaction:g=>this.scheduleCompaction(m.sessionId,g),resolveAgentId:async g=>(await this.registry.getAgent(g))?.id,getCompactionState:()=>this.getCompactionState(m.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(m.sessionId),uncompactHook:()=>this.performUncompact(m.sessionId),onCompactionSwapHook:g=>{this.mutateRecord(m.sessionId,{rollbackBreadcrumb:g}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(m.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(m),m}async doResurrectFromImport(e){let t=await this.resolveResurrectCwd(e.cwd),s=await this.bootstrapAgent({agentId:e.agentId,cwd:t,agentArgs:e.agentArgs,mcpServers:e.mcpServers??[],onInstallProgress:e.onInstallProgress,forwardedEnv:e.forwardedEnv,model:e.currentModel}),r=e.agentModes??s.initialModes,o=await Be({agent:s.agent,upstreamSessionId:s.upstreamSessionId,persistedMode:e.currentMode,agentReportedMode:s.initialMode,advertisedModes:r,logger:this.logger}),i=e.agentModels??s.initialModels,a=await Ue({agent:s.agent,upstreamSessionId:s.upstreamSessionId,persistedModel:e.currentModel,agentReportedModel:s.initialModel,logger:this.logger});s.agent.connection.drainBuffered("session/update");let u=new Pe({sessionId:e.hydraSessionId,cwd:t,agentId:e.agentId,agent:s.agent,upstreamSessionId:s.upstreamSessionId,agentMeta:s.agentMeta,agentCapabilities:s.agentCapabilities,title:e.title,agentArgs:e.agentArgs,idleTimeoutMs:this.idleTimeoutMs,logger:this.logger,spawnReplacementAgent:c=>this.bootstrapAgent({...c,mcpServers:c.mcpServers??e.mcpServers??[]}),loadExistingAgentSession:(c,d)=>this.bootstrapAgentLoad(c,{...d,mcpServers:d.mcpServers??e.mcpServers??[]}),...e.mintMcpServersForSwap?{mintMcpServersForSwap:e.mintMcpServersForSwap}:{},listSessions:()=>this.list(),availableAgents:()=>this.agentCatalog,historyStore:this.histories,historyMaxEntries:this.sessionHistoryMaxEntries,currentModel:a,currentMode:o,currentUsage:e.currentUsage,agentCommands:e.agentCommands,agentModes:r,agentModels:i,summarizedThroughEntry:e.summarizedThroughEntry,firstPromptSeeded:!!e.title,createdAt:e.createdAt?new Date(e.createdAt).getTime():void 0,originatingClient:e.originatingClient,interactive:e.interactive,priority:e.priority,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,forwardedEnv:e.forwardedEnv,mcpServers:e.mcpServers??[],extensionCommands:this.extensionCommands,attentionFlags:e.attentionFlags,scheduleSynopsis:()=>this.synopsisCoordinator.schedule(u.sessionId),scheduleCompaction:c=>this.scheduleCompaction(u.sessionId,c),resolveAgentId:async c=>(await this.registry.getAgent(c))?.id,getCompactionState:()=>this.getCompactionState(u.sessionId),getPendingAgentSwap:()=>this.getPendingAgentSwap(u.sessionId),uncompactHook:()=>this.performUncompact(u.sessionId),onCompactionSwapHook:c=>{this.mutateRecord(u.sessionId,{rollbackBreadcrumb:c}).catch(()=>{})},clearRollbackBreadcrumbHook:()=>{this.mutateRecord(u.sessionId,{},["rollbackBreadcrumb"]).catch(()=>{})}});return await this.attachManagerHooks(u),e.forkedFromSessionId&&e.forkSynthesisState==="running"?this.logger?.info(`fork ${u.sessionId}: synthesis in flight \u2014 skipping seed, recall available`):e.forkedFromSessionId&&(e.synopsis||(e.summarizedThroughEntry??0)>0)?u.seedFromFork(e.synopsis).catch(()=>{}):u.seedFromImport().catch(()=>{}),u}async dirExists(e){try{return(await Te.stat(e)).isDirectory()}catch{return!1}}async reapIfOrphanedNonInteractive(e){let t=this.sessions.get(e);!t||t.attachedCount>0||t.interactive!==!0&&(this.logger?.info(`reaping orphaned non-interactive session ${e} (agent killed, cold record kept)`),await t.close({deleteRecord:!1}).catch(()=>{}))}async resolveResurrectCwd(e){return await this.dirExists(e)?e:Y(this.defaultCwd)}async syncFromAgent(e){let t=await this.registry.getAgent(e);if(!t){let f=new Error(`agent ${e} not found in registry`);throw f.code=k.AgentNotInstalled,f}let s=await te(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:Vt.homedir(),plan:s}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:je,clientInfo:{name:"hydra",version:K}})}catch(f){throw await r.kill().catch(()=>{}),Ae(f,r)}if(r.authMethods=yt(o.authMethods),(o.agentCapabilities??{}).sessionCapabilities?.list===void 0)throw await r.kill().catch(()=>{}),new Error(`agent ${e} does not advertise sessionCapabilities.list; cannot sync`);let a;try{a=await this.collectAgentSessions(r)}catch(f){throw await r.kill().catch(()=>{}),f}await r.kill().catch(()=>{});let u=new Set;for(let f of this.sessions.values())u.add(`${f.agentId}::${f.upstreamSessionId}`);let c=await this.store.list().catch(()=>[]);for(let f of c)u.add(`${f.agentId}::${f.upstreamSessionId}`);let d=I.sessionsDir(),l=[],p=0;for(let f of a){let m=`${e}::${f.sessionId}`;if(u.has(m)){p+=1;continue}if(Ud(f.cwd,d)){p+=1;continue}let g=await this.tombstones.read(e,f.sessionId).catch(()=>{});if(g){if(!Lr(g,f.updatedAt)){p+=1;continue}await this.tombstones.remove(e,f.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${f.sessionId} (upstream updatedAt advanced past ${g.upstreamUpdatedAt??"<unset>"})`)}u.add(m);let h=`${ye}${Qt()}`,y=new Date().toISOString(),v=f.updatedAt??y,w={sessionId:h,lineageId:pt(),upstreamSessionId:f.sessionId,agentId:e,cwd:f.cwd,pendingHistorySync:!0,interactive:!0,createdAt:v,updatedAt:v};f.title!==void 0&&(w.title=f.title);let b=es(w);await this.store.write(b),l.push({version:1,...b})}return{synced:l,skipped:p}}async collectAgentSessions(e){let t=[],s,r=new Set;for(let o=0;o<100;o+=1){let i={};s!==void 0&&(i.cursor=s);let a=await e.connection.request("session/list",i),u=Array.isArray(a.sessions)?a.sessions:[];for(let c of u){if(typeof c.sessionId!="string"||typeof c.cwd!="string")continue;let d={sessionId:c.sessionId,cwd:c.cwd};typeof c.title=="string"&&(d.title=c.title),typeof c.updatedAt=="string"&&(d.updatedAt=c.updatedAt),t.push(d)}if(typeof a.nextCursor!="string"||a.nextCursor.length===0||r.has(a.nextCursor))break;r.add(a.nextCursor),s=a.nextCursor}return t}async applySeedModel(e,t,s,r){try{return await e.connection.request("session/set_model",{sessionId:t,modelId:s}),this.logger?.info(`${r}: session/set_model accepted`),!0}catch(o){return this.logger?.warn(`${r} rejected by agent (${o.message}); session will use the agent's own default`),!1}}async bootstrapAgent(e){let t=await this.registry.getAgent(e.agentId);if(!t){let o=new Error(`agent ${e.agentId} not found in registry`);throw o.code=k.AgentNotInstalled,o}let s=await te(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),r=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:s,...e.forwardedEnv?{extraEnv:e.forwardedEnv}:{}});try{let o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:je,clientInfo:{name:"hydra",version:K}}),i=o.agentCapabilities;r.authMethods=yt(o.authMethods);let a=await r.connection.request("session/new",{cwd:e.cwd,mcpServers:e.mcpServers??[]}),u=a.sessionId;if(typeof u!="string")throw new Error(`agent ${e.agentId} returned a non-string sessionId from session/new`);let c=is(a),d=ds(a),l=e.model??this.defaultModels[e.agentId];if(l&&l!==c){let m=qe(l,d),g=e.model!==void 0?`model=${JSON.stringify(l)}`:`defaultModels[${e.agentId}]=${JSON.stringify(l)}`;if(m.kind==="exact"||m.kind==="none")await this.applySeedModel(r,u,l,g)&&(c=l);else if(m.kind==="resolved")(m.modelId===c||await this.applySeedModel(r,u,m.modelId,`${g} resolved to ${JSON.stringify(m.modelId)}`))&&(c=m.modelId);else if(m.kind==="ambiguous")this.logger?.warn(`${g} is ambiguous (trailing-segment matches [${m.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(c)}`);else{let h=d.map(y=>y.modelId).join(", ");this.logger?.warn(`${g} not in agent's availableModels ([${h}]); skipping session/set_model, session will use ${JSON.stringify(c)}`)}}let p=cs(a),f=us(a);return{agent:r,upstreamSessionId:u,agentMeta:a._meta,agentCapabilities:i,initialModel:c,initialModels:d.length>0?d:void 0,initialModes:p.length>0?p:void 0,initialMode:f}}catch(o){throw await r.kill().catch(()=>{}),Ae(go(o,r,e.agentId,{command:s.command,args:s.args,cwd:e.cwd}),r)}}async bootstrapAgentLoad(e,t){let s=await this.registry.getAgent(t.agentId);if(!s){let i=new Error(`agent ${t.agentId} not found in registry`);throw i.code=k.AgentNotInstalled,i}let r=await te(s,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=this.spawner({agentId:t.agentId,cwd:t.cwd,plan:r,...t.forwardedEnv?{extraEnv:t.forwardedEnv}:{}});try{let i=await o.connection.request("initialize",{protocolVersion:1,clientCapabilities:je,clientInfo:{name:"hydra",version:K}}),a=i.agentCapabilities;o.authMethods=yt(i.authMethods);let u=po(t.agentId,void 0),c=await o.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...u&&{_meta:u}}),d=is(c),l=as(ds(c)),p=cs(c),f=us(c);return{agent:o,upstreamSessionId:e,agentMeta:c._meta,agentCapabilities:a,initialModel:d,initialModels:l,initialModes:p.length>0?p:void 0,initialMode:f}}catch(i){throw await o.kill().catch(()=>{}),Ae(go(i,o,t.agentId,{command:r.command,args:r.args,cwd:t.cwd}),o)}}async performUncompact(e){if(this.rollbackLocks.has(e))throw new Error("a rollback is already in progress for this session");let t=this.get(e);if(!t)throw new Error("session is not live \u2014 cannot roll back a cold session");let s=await this.store.read(e);if(!s)throw new Error("session record not found");let r=s.rollbackBreadcrumb;if(!r)throw new Error("no rollback breadcrumb found \u2014 either the session has not been compacted, the rollback window has closed (a new turn was dispatched), or a previous rollback already consumed the breadcrumb");let o=s.compactionState;if(o!=null)throw new Error(`compaction is in progress (status: ${o.status}) \u2014 wait for it to complete before rolling back`);if(!await t.isQuiescedForSwap())throw new Error("session is not quiesced for rollback \u2014 wait for in-flight work to complete");this.rollbackLocks.add(e);try{await t.rollbackToUpstream({previousUpstreamSessionId:r.previousUpstreamSessionId,previousSummarizedThroughEntry:r.previousSummarizedThroughEntry}),await this.mutateRecord(e,{summarizedThroughEntry:r.previousSummarizedThroughEntry},["synopsis","rollbackBreadcrumb"])}finally{this.rollbackLocks.delete(e)}}async bootstrapAgentForAuth(e,t){let s=this.pendingAuthAgents.get(e);if(s&&s.isAlive())return s;let r=await this.registry.getAgent(e);if(!r){let u=new Error(`agent ${e} not found in registry`);throw u.code=k.AgentNotInstalled,u}let o=await te(r,[],{npmRegistry:this.npmRegistry}),i=t??Y(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let u=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:je,clientInfo:{name:"hydra",version:K}});a.authMethods=yt(u.authMethods)}catch(u){throw await a.kill().catch(()=>{}),Ae(u,a)}return this.pendingAuthAgents.set(e,a),a.onExit(()=>{this.pendingAuthAgents.get(e)===a&&this.pendingAuthAgents.delete(e)}),a}async planSpawnForAgent(e){let t=await this.registry.getAgent(e);if(!t){let s=new Error(`agent ${e} not found in registry`);throw s.code=k.AgentNotInstalled,s}return te(t,[],{npmRegistry:this.npmRegistry})}consumePendingAuthAgent(e){let t=this.pendingAuthAgents.get(e);if(t&&(this.pendingAuthAgents.delete(e),!!t.isAlive()))return t}getAgentForSession(e){return this.sessions.get(e)?.agent}async attachManagerHooks(e){e.onClose(({deleteRecord:t})=>{if(this.sessions.delete(e.sessionId),this.invalidateListCache(),t){if(e.upstreamSessionId){let r=Ge({interactive:e.interactive,...e.originatingClient?{originatingClient:e.originatingClient}:{}},!0),o=this.tombstones.add({agentId:e.agentId,upstreamSessionId:e.upstreamSessionId,deletedAt:new Date().toISOString(),upstreamUpdatedAt:new Date(e.updatedAt).toISOString(),cwd:e.cwd,title:e.title,reason:"user",...r!==void 0?{interactive:r}:{}}).catch(()=>{}).then(()=>this.store.delete(e.sessionId).catch(()=>{})).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===o&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,o);return}let s=this.store.delete(e.sessionId).catch(()=>{}).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===s&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,s);return}}),e.onTitleChange(t=>{this.persistTitle(e.sessionId,t).catch(()=>{})}),e.onPriorityChange(t=>{this.persistPriority(e.sessionId,t).catch(()=>{})}),e.onAgentChange(({agentId:t,upstreamSessionId:s})=>{this.persistAgentChange(e.sessionId,t,s).catch(()=>{})}),e.onModelChange(t=>{this.persistSnapshot(e.sessionId,{currentModel:t}).catch(()=>{})}),e.onModeChange(t=>{this.persistSnapshot(e.sessionId,{currentMode:t}).catch(()=>{})}),e.onInteractiveChange(t=>{this.persistSnapshot(e.sessionId,{interactive:t}).catch(()=>{})}),e.onUsageChange(t=>{this.persistSnapshot(e.sessionId,{currentUsage:yo(t)}).catch(()=>{})}),e.onAgentCommandsChange(t=>{this.persistSnapshot(e.sessionId,{agentCommands:t.map(s=>({name:s.name,...s.description!==void 0?{description:s.description}:{}}))}).catch(()=>{})}),e.onAgentModesChange(t=>{this.persistSnapshot(e.sessionId,{agentModes:t.map(s=>({id:s.id,...s.name!==void 0?{name:s.name}:{},...s.description!==void 0?{description:s.description}:{}}))}).catch(()=>{})}),e.onAgentModelsChange(t=>{this.persistSnapshot(e.sessionId,{agentModels:t.map(s=>({modelId:s.modelId,...s.name!==void 0?{name:s.name}:{},...s.description!==void 0?{description:s.description}:{}}))}).catch(()=>{})}),e.onAttentionFlagsChange(t=>{this.mutateRecord(e.sessionId,{attentionFlags:t}).catch(()=>{})}),this.sessions.set(e.sessionId,e),this.invalidateListCache(),await this.enqueueMetaWrite(e.sessionId,async()=>{let t=await this.store.read(e.sessionId),s=Dd(e,t);await this.store.write(s)}).catch(()=>{})}async getHistory(e){if(this.sessions.has(e))return this.histories.load(e).catch(()=>[]);if(await this.store.read(e))return this.histories.load(e).catch(()=>[])}async loadHistory(e){return this.histories.load(e)}async loadToolBlob(e,t){return $t(e,t)}async loadFromDisk(e){let t=await this.store.read(e);if(!t)return;let s=t.title;return s||(s=await this.deriveTitleFromHistory(e)),{hydraSessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,agentId:t.agentId,cwd:t.cwd,title:s,synopsis:t.synopsis,summarizedThroughEntry:t.summarizedThroughEntry,agentArgs:t.agentArgs,currentModel:t.currentModel,currentMode:t.currentMode,currentUsage:Ld(t.currentUsage?{...t.currentUsage,cumulativeCost:(t.currentUsage.cumulativeCost??0)+(t.currentUsage.costAmount??0),costAmount:void 0}:void 0),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,forwardedEnv:t.forwardedEnv,compactionState:t.compactionState,attentionFlags:t.attentionFlags?.filter(r=>!(r.source==="daemon"&&r.reason.startsWith("permission:")))}}async setForwardedEnv(e,t){if(t===void 0)return;let s=this.sessions.get(e);s&&(s.forwardedEnv=t),await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r)return;let o={...r,forwardedEnv:t};await this.store.write(o)})}async clearPendingHistorySync(e){await this.enqueueMetaWrite(e,async()=>{let t=await this.store.read(e);if(!t||t.pendingHistorySync!==!0)return;let s={...t};delete s.pendingHistorySync,await this.store.write(s)})}async deriveTitleFromHistory(e){let t=await this.histories.load(e).catch(()=>[]);for(let s of t){let r=s.params;if(r?.update?.sessionUpdate!=="prompt_received")continue;let o=Je(r.update.prompt),i=Wn(o,200);if(i)return i}}get(e){return this.sessions.get(e)}liveSessions(){return this.sessions.values()}activeAgentVersions(){let e=new Map;for(let t of this.sessions.values()){let s=t.agent.agentId,r=t.agent.version,o=e.get(s);o||(o=new Set,e.set(s,o)),o.add(r)}return e}async resolveCanonicalId(e){if(this.sessions.has(e)||await this.store.read(e))return e;if(e.startsWith(ye))return;let t=ye+e;if(this.sessions.has(t)||await this.store.read(t))return t}require(e){let t=this.sessions.get(e);if(!t){let s=new Error(`session ${e} not found`);throw s.code=k.SessionNotFound,s}return t}liveListEntry(e){return{sessionId:e.sessionId,upstreamSessionId:e.upstreamSessionId,cwd:e.cwd,title:e.title,agentId:e.agentId,currentModel:e.currentModel,currentUsage:e.currentUsage,parentSessionId:e.parentSessionId,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,forkSynthesisState:e.forkSynthesisState,originatingClient:e.originatingClient,interactive:e.interactive,updatedAt:new Date(e.updatedAt).toISOString(),attachedClients:e.attachedCount,status:"warm",busy:e.turnStartedAt!==void 0,awaitingInput:e.awaitingInput}}async getOne(e){let t=this.sessions.get(e);if(t){let a=await wt(t.sessionId),u=Ge({interactive:t.interactive,...t.originatingClient?{originatingClient:t.originatingClient}:{}},a.hasContent),c=a.mtime??new Date(t.updatedAt).toISOString();return{sessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,cwd:t.cwd,title:t.title,agentId:t.agentId,currentModel:t.currentModel,currentUsage:t.currentUsage,parentSessionId:t.parentSessionId,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,originatingClient:t.originatingClient,interactive:u,priority:t.priority,updatedAt:c,attachedClients:t.attachedCount,status:"warm",busy:t.turnStartedAt!==void 0,awaitingInput:t.awaitingInput}}let s=await this.store.read(e).catch(()=>{});if(!s)return;let r=await wt(s.sessionId),o=Ge(s,r.hasContent),i=r.mtime??s.updatedAt;return{sessionId:s.sessionId,upstreamSessionId:s.upstreamSessionId,cwd:s.cwd,title:s.title,agentId:s.agentId,currentModel:s.currentModel,currentUsage:s.currentUsage?{...s.currentUsage,costAmount:(s.currentUsage.cumulativeCost??0)+(s.currentUsage.costAmount??0)||void 0}:void 0,importedFromMachine:s.importedFromMachine,importedFromUpstreamSessionId:s.importedFromUpstreamSessionId,parentSessionId:s.parentSessionId,forkedFromSessionId:s.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId,forkSynthesisState:s.forkSynthesisState,originatingClient:s.originatingClient,interactive:o,priority:s.priority,updatedAt:i,attachedClients:0,status:"cold",busy:!1,awaitingInput:!1}}async list(e={}){let t=`${e.cwd??""}|${e.includeNonInteractive?"1":"0"}`,s=Date.now(),r=this.listCache.get(t);if(r&&r.expiresAt>s)return r.promise;let o=this.listUncached(e);return this.listCache.set(t,{expiresAt:s+n.LIST_CACHE_TTL_MS,promise:o}),o.catch(()=>{let i=this.listCache.get(t);i&&i.promise===o&&this.listCache.delete(t)}),o}invalidateListCache(){this.listCache.clear()}async listUncached(e={}){let t=[],s=new Set,r=d=>e.includeNonInteractive?!0:d===!0,o=[...this.sessions.values()].filter(d=>!e.cwd||d.cwd===e.cwd),i=await Promise.all(o.map(d=>wt(d.sessionId)));for(let d=0;d<o.length;d+=1){let l=o[d],p=i[d];s.add(l.sessionId);let f=Ge({interactive:l.interactive,...l.originatingClient?{originatingClient:l.originatingClient}:{}},p.hasContent);if(!r(f))continue;let m=p.mtime??new Date(l.updatedAt).toISOString();t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,title:l.title,agentId:l.agentId,currentModel:l.currentModel,currentUsage:l.currentUsage,parentSessionId:l.parentSessionId,forkedFromSessionId:l.forkedFromSessionId,forkedFromMessageId:l.forkedFromMessageId,originatingClient:l.originatingClient,interactive:f,priority:l.priority,updatedAt:m,attachedClients:l.attachedCount,status:"warm",busy:l.turnStartedAt!==void 0,awaitingInput:l.awaitingInput,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}let u=(await this.store.list().catch(d=>{throw this.logger?.warn(`session list: store.list() failed: ${d?.message??String(d)}`),d})).filter(d=>!s.has(d.sessionId)&&(!e.cwd||d.cwd===e.cwd)),c=await Promise.all(u.map(d=>wt(d.sessionId)));for(let d=0;d<u.length;d+=1){let l=u[d],p=c[d],f=Ge(l,p.hasContent);if(!r(f))continue;let m=p.mtime??l.updatedAt;t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,title:l.title,agentId:l.agentId,currentModel:l.currentModel,currentUsage:l.currentUsage?{...l.currentUsage,costAmount:(l.currentUsage.cumulativeCost??0)+(l.currentUsage.costAmount??0)||void 0}:void 0,importedFromMachine:l.importedFromMachine,importedFromUpstreamSessionId:l.importedFromUpstreamSessionId,parentSessionId:l.parentSessionId,forkedFromSessionId:l.forkedFromSessionId,forkedFromMessageId:l.forkedFromMessageId,originatingClient:l.originatingClient,interactive:f,priority:l.priority,updatedAt:m,attachedClients:0,status:"cold",busy:!1,awaitingInput:!1,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}return t.sort((d,l)=>d.updatedAt<l.updatedAt?1:-1),t}async exportBundle(e,t={}){let s=await this.store.read(e);if(!s)return;let r;if(s.lineageId)r=s;else{let c=pt(),d={...s,lineageId:c};await this.enqueueMetaWrite(e,async()=>{let l=await this.store.read(e);l&&(l.lineageId||await this.store.write({...l,lineageId:c}))}).catch(()=>{}),r=d}let o=t.tools??"inline",i=await this.histories.load(e,o==="references"?{tools:"references"}:{}).catch(()=>[]),a=await ho(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let u={};for(let c of ro(i)){let d=await zs(e,c);d&&(u[c]=d.toString("base64"))}return{record:r,history:i,promptHistory:a,toolBlobs:u}}async importBundle(e,t={}){let s=await this.store.findByLineageId(e.session.lineageId);if(s){if(!t.replace){let i=new Error(`bundle already imported as ${s.sessionId}`);throw i.code=k.BundleAlreadyImported,i.existingSessionId=s.sessionId,i}let o=this.sessions.get(s.sessionId);return o&&await o.close({deleteRecord:!1}).catch(()=>{}),await this.writeImportedRecord({sessionId:s.sessionId,bundle:e,preservedCreatedAt:s.createdAt,cwd:t.cwd}),{sessionId:s.sessionId,importedFromSessionId:e.session.sessionId,replaced:!0}}let r=`${ye}${Qt()}`;return await this.writeImportedRecord({sessionId:r,bundle:e,cwd:t.cwd}),{sessionId:r,importedFromSessionId:e.session.sessionId,replaced:!1}}async forkSession(e,t={}){let s=await this.store.read(e);if(!s){let w=new Error(`source session not found: ${e}`);throw w.code=k.SessionNotFound,w}let r=t.agentId??s.agentId,o=r!==s.agentId;if(o&&!await this.registry.getAgent(r)){let b=new Error(`agent ${r} not found in registry`);throw b.code=k.AgentNotInstalled,b}let i=await this.histories.load(e).catch(()=>[]),a=i,u,c=t.mode??"synthesis",d,l,p,f=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let w=Jn(i,t.forkAt);if(w<0){let b=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw b.code=k.InvalidParams,b}u=t.forkAt,a=i.slice(0,w+1)}else{let w=zd(i);w?(u=w.messageId,a=i.slice(0,w.index+1)):(u="",a=i.slice(0,0))}else{t.forkAt!==void 0&&this.logger?.warn(`synthesis fork: ignoring forkAt=${t.forkAt} (synthesis covers full history)`),u="",a=i;let w=await this.registry.getAgent(r);if(!w){let b=new Error(`agent ${r} not found in registry`);throw b.code=k.AgentNotInstalled,b}p=w,l=s.currentModel,d="running"}let m=await ho(e),g=c==="synthesis",h={...s,lineageId:pt(),agentId:r,interactive:!1,...d!==void 0?{forkSynthesisState:d}:{},summarizedThroughEntry:a.length,...t.title!==void 0?{title:t.title}:{},currentUsage:void 0,...o?{currentModel:void 0,currentMode:void 0,agentCommands:void 0,agentModes:void 0,agentModels:void 0}:{},...t.model!==void 0?{currentModel:t.model}:{}},y=ht({record:h,history:a,promptHistory:m.length>0?m:void 0,hydraVersion:K,machine:Vt.hostname()}),v=`${ye}${Qt()}`;return await this.writeImportedRecord({sessionId:v,bundle:y,cwd:t.cwd,forkedFromSessionId:e,forkedFromMessageId:u,...d!==void 0?{forkSynthesisState:d}:{}}),g&&(async()=>{try{let w=await te(p,[],{npmRegistry:this.npmRegistry}),b=await zt({agentId:r,cwd:t.cwd??I.sessionDir(e),plan:w,history:i,modelId:l,sessionId:e,logger:this.logger,timeoutMs:f});b&&b.synopsis?await this.mutateRecord(v,{synopsis:b.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(v,{},["forkSynthesisState"]))}catch(w){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${w.message}`);try{await this.mutateRecord(v,{},["forkSynthesisState"])}catch(b){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${b.message}`)}}})(),{sessionId:v,forkedFromSessionId:e,forkedAt:u}}async writeImportedRecord(e){if(await this.histories.rewrite(e.sessionId,e.bundle.history),e.bundle.toolBlobs)for(let[o,i]of Object.entries(e.bundle.toolBlobs))await Js(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await Te.utimes(I.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await uo(I.tuiHistoryFile(e.sessionId),e.bundle.promptHistory).catch(()=>{});let s=new Date().toISOString(),r=e.forkedFromSessionId!==void 0;await this.enqueueMetaWrite(e.sessionId,async()=>{await this.store.write({sessionId:e.sessionId,lineageId:e.bundle.session.lineageId,upstreamSessionId:"",...r?{forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId}:{importedFromSessionId:e.bundle.session.sessionId,importedFromUpstreamSessionId:e.bundle.session.upstreamSessionId,importedFromMachine:e.bundle.exportedFrom.machine},agentId:e.bundle.session.agentId,cwd:e.cwd??e.bundle.session.cwd,title:e.bundle.session.title,synopsis:e.bundle.session.synopsis,summarizedThroughEntry:e.bundle.session.summarizedThroughEntry,...e.forkSynthesisState!==void 0?{forkSynthesisState:e.forkSynthesisState}:{},currentModel:e.bundle.session.currentModel,currentMode:e.bundle.session.currentMode,currentUsage:e.bundle.session.currentUsage,agentCommands:e.bundle.session.agentCommands,agentModes:e.bundle.session.agentModes,interactive:e.bundle.session.interactive,originatingClient:e.bundle.session.originatingClient,priority:e.bundle.session.priority,attentionFlags:[],createdAt:e.preservedCreatedAt??s,updatedAt:e.bundle.session.updatedAt})})}async deleteRecord(e,t="user"){let s=await this.store.read(e);if(!s)return!1;if(s.upstreamSessionId){let r=await wt(e),o=Ge(s,r.hasContent);await this.tombstones.add({agentId:s.agentId,upstreamSessionId:s.upstreamSessionId,deletedAt:new Date().toISOString(),upstreamUpdatedAt:s.updatedAt,cwd:s.cwd,title:s.title,reason:t,...o!==void 0?{interactive:o}:{}}).catch(()=>{})}return await this.store.delete(e).catch(()=>{}),await this.histories.delete(e).catch(()=>{}),this.invalidateListCache(),!0}async waitForDeletion(e){let t=this.pendingDeletions.get(e);t&&await t}async isTombstoned(e,t){return(await this.tombstones.read(e,t).catch(()=>{}))?.reason==="user"}async hasRecord(e){return await this.store.read(e).catch(()=>{})!==void 0}async setPriority(e,t){let s=this.get(e);if(s)return s.setPriority(t),!0;if(!await this.hasRecord(e))return!1;let r=t===void 0||t<=0?void 0:Math.floor(t);return await this.persistPriority(e,r),!0}async persistPriority(e,t){t===void 0?await this.mutateRecord(e,{},["priority"]):await this.mutateRecord(e,{priority:t}),this.invalidateListCache()}async setTitle(e,t){let s=this.get(e);return s?(await s.retitle(t),!0):await this.hasRecord(e)?(await this.persistTitle(e,t),!0):!1}async persistTitle(e,t){await this.mutateRecord(e,{title:t})}async persistSynopsis(e,t,s){await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:s})}async persistAgentChange(e,t,s){await this.mutateRecord(e,{agentId:t,upstreamSessionId:s})}async persistSnapshot(e,t){let s={};t.currentModel!==void 0&&(s.currentModel=t.currentModel),t.currentMode!==void 0&&(s.currentMode=t.currentMode),t.currentUsage!==void 0&&(s.currentUsage=t.currentUsage),t.agentCommands!==void 0&&(s.agentCommands=t.agentCommands),t.agentModes!==void 0&&(s.agentModes=t.agentModes),t.agentModels!==void 0&&(s.agentModels=t.agentModels),t.interactive!==void 0&&(s.interactive=t.interactive),t.cwd!==void 0&&(s.cwd=t.cwd),await this.mutateRecord(e,s)}async mutateRecord(e,t,s=[]){await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r)return;let o={...r,...t,updatedAt:new Date().toISOString()};for(let i of s)delete o[i];await this.store.write(o)})}enqueueMetaWrite(e,t){let r=(this.metaWriteQueues.get(e)??Promise.resolve()).catch(()=>{}).then(t),o=r.catch(()=>{});return this.metaWriteQueues.set(e,o),o.finally(()=>{this.metaWriteQueues.get(e)===o&&this.metaWriteQueues.delete(e)}),r}async closeAll(){let e=[...this.sessions.values()];await Promise.allSettled(e.map(t=>t.close({deleteRecord:!1}))),this.sessions.clear()}async flushSynopsis(e){await this.synopsisCoordinator.flush(e)}async shutdownSynopsis(){await this.synopsisCoordinator.shutdown()}scheduleSynopsis(e){this.synopsisCoordinator.schedule(e)}scheduleCompaction(e,t){if(t?.targetAgentId){this.mutateRecord(e,{pendingAgentSwap:t.targetAgentId}).catch(r=>{this.logger?.warn(`scheduleCompaction: failed to stamp pendingAgentSwap for ${e}: ${r instanceof Error?r.message:String(r)}`)});let s=t.targetAgentId;(async()=>{try{let r=await this.store.read(e);if(!r?.synopsis||r.summarizedThroughEntry===void 0){this.synopsisCoordinator.scheduleCompaction(e,t);return}if((await this.histories.load(e,{maxEntries:1/0})).length!==r.summarizedThroughEntry){this.synopsisCoordinator.scheduleCompaction(e,t);return}this.logger?.info(`compaction: fast-path swap sessionId=${e} target=${s} (reusing artifact @${r.summarizedThroughEntry})`),await this.dispatchSynthesisSwap(e,r.synopsis,r.summarizedThroughEntry,s)}catch(r){this.logger?.warn(`scheduleCompaction: fast-path check failed for ${e}: ${r instanceof Error?r.message:String(r)} \u2014 falling back to synthesis`),this.synopsisCoordinator.scheduleCompaction(e,t)}})();return}this.synopsisCoordinator.scheduleCompaction(e,t)}getCompactionInFlight(){let e=this.synopsisCoordinator.size();return e.inflight>0||e.queued>0}async getPendingAgentSwap(e){return(await this.store.read(e).catch(()=>{}))?.pendingAgentSwap}async getCompactionState(e){return(await this.store.read(e).catch(()=>{}))?.compactionState}async getRollbackBreadcrumb(e){return(await this.store.read(e).catch(()=>{}))?.rollbackBreadcrumb}emitSwapPhase(e,t,s){let r=this.get(e);if(r){if(t){let o=s.phase==="failed";r.broadcastPendingAgentSwap(o?null:t);return}r.broadcastCompactionPhase(s)}}async getSummarizedThroughEntry(e){let t=this.sessions.get(e);return t?t.summarizedThroughEntry:(await this.store.read(e).catch(()=>{}))?.summarizedThroughEntry}async flushMetaWrites(){let e=[...this.metaWriteQueues.values()];e.length!==0&&await Promise.allSettled(e)}async flushHistoryWrites(){await this.histories.flushAll()}async reconcilePermissionFlags(){let e=await this.store.list().catch(()=>[]),t=0;for(let s of e){let r=s.attentionFlags??[],o=r.filter(i=>!(i.source==="daemon"&&i.reason.startsWith("permission:")));if(o.length!==r.length){let i=r.length-o.length;t+=i,await this.mutateRecord(s.sessionId,{attentionFlags:o}).catch(()=>{})}}t>0&&this.logger?.info(`cleared ${t} stale permission attention flags on startup`)}async resumePendingCompactions(){let e=new Set(["requested","running","swap_pending","swap_deferred"]),t=await this.store.list().catch(()=>[]);for(let s of t){let r=s.compactionState;if(r!=null){if(!e.has(r.status)){this.logger?.info(`compaction: not resuming sessionId=${s.sessionId} status=${r.status} (terminal \u2014 user must re-trigger explicitly)`);continue}this.logger?.info(`compaction: resuming sessionId=${s.sessionId} status=${r.status} from prior daemon`);try{this.scheduleCompaction(s.sessionId)}catch(o){this.logger?.warn(`compaction: resume failed for sessionId=${s.sessionId}: ${o instanceof Error?o.message:String(o)}`)}}}}async resumePendingAgentSwaps(){let e=await this.store.list().catch(()=>[]);for(let t of e){let s=t.pendingAgentSwap;if(s)try{let r=await this.histories.load(t.sessionId).catch(()=>[]);t.synopsis!==void 0&&t.summarizedThroughEntry!==void 0&&t.summarizedThroughEntry>=r.length&&t.synopsis?(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${s} with persisted synopsis (history=${r.length})`),await this.dispatchSynthesisSwap(t.sessionId,t.synopsis,t.summarizedThroughEntry??r.length,s)):(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${s} via fresh synthesis (history=${r.length} watermark=${t.summarizedThroughEntry??"(none)"})`),this.scheduleCompaction(t.sessionId,{targetAgentId:s}))}catch(r){this.logger?.warn(`agent-swap: resume failed for sessionId=${t.sessionId}: ${r instanceof Error?r.message:String(r)}`)}}}async resurrectPendingQueues(){let e=await this.store.list().catch(()=>[]);for(let t of e){let s=await xr(t.sessionId).catch(()=>[]);if(s.length===0)continue;let r=Date.now(),o=s.filter(u=>r-u.enqueuedAt<fo),i=s.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${fo/1e3}s)`),await ut(t.sessionId,o).catch(()=>{})),o.length===0)continue;let a=await this.loadFromDisk(t.sessionId).catch(()=>{});if(!a){this.logger?.warn(`queue replay: no meta for ${t.sessionId}; discarding ${o.length} entr${o.length===1?"y":"ies"}`),await ut(t.sessionId,[]).catch(()=>{});continue}try{let u=await this.resurrect(a);this.logger?.info(`queue replay: resurrected ${t.sessionId} and replaying ${o.length} prompt(s)`),u.replayPersistedQueue(o)}catch(u){this.logger?.warn(`queue replay: failed to resurrect ${t.sessionId}: ${u.message}`)}}}};function Ud(n,e){if(typeof n!="string"||n.length===0)return!1;let t=vt.resolve(n),s=vt.resolve(e);return t===s||t.startsWith(s+vt.sep)}function Dd(n,e){let s=(n.mergedAvailableCommands().length>0?n.agentOnlyAdvertisedCommands().map(d=>d.description!==void 0?{name:d.name,description:d.description}:{name:d.name}):void 0)??e?.agentCommands,r=n.availableModes(),i=(r.length>0?r.map(d=>{let l={id:d.id};return d.name!==void 0&&(l.name=d.name),d.description!==void 0&&(l.description=d.description),l}):void 0)??e?.agentModes,a=n.availableModels(),c=(a.length>0?a.map(d=>{let l={modelId:d.modelId};return d.name!==void 0&&(l.name=d.name),d.description!==void 0&&(l.description=d.description),l}):void 0)??e?.agentModels;return es({sessionId:n.sessionId,lineageId:e?.lineageId??pt(),upstreamSessionId:n.upstreamSessionId,importedFromSessionId:e?.importedFromSessionId,importedFromUpstreamSessionId:e?.importedFromUpstreamSessionId,importedFromMachine:e?.importedFromMachine,agentId:n.agentId,cwd:n.cwd,title:n.title,synopsis:e?.synopsis,summarizedThroughEntry:e?.summarizedThroughEntry,agentArgs:n.agentArgs,currentModel:n.currentModel??e?.currentModel,currentMode:n.currentMode??e?.currentMode,currentUsage:yo(n.currentUsage)??e?.currentUsage,agentCommands:s,agentModes:i,agentModels:c,parentSessionId:n.parentSessionId??e?.parentSessionId,forkedFromSessionId:n.forkedFromSessionId??e?.forkedFromSessionId,forkedFromMessageId:n.forkedFromMessageId??e?.forkedFromMessageId,originatingClient:n.originatingClient??e?.originatingClient,interactive:n.interactive??e?.interactive,priority:n.priority??e?.priority,forwardedEnv:n.forwardedEnv??e?.forwardedEnv,attentionFlags:n.listAttentionFlags(),createdAt:e?.createdAt??new Date(n.createdAt).toISOString()})}function yo(n){if(!n)return;let e={};return n.used!==void 0&&(e.used=n.used),n.size!==void 0&&(e.size=n.size),n.costAmount!==void 0&&(e.costAmount=n.costAmount),n.costCurrency!==void 0&&(e.costCurrency=n.costCurrency),n.cumulativeCost!==void 0&&(e.cumulativeCost=n.cumulativeCost),Object.keys(e).length>0?e:void 0}function Ld(n){return n?{...n}:void 0}function po(n,e){if(e&&n==="claude-acp")return{claudeCode:{options:{model:e}}}}function Kt(n,e){let t=e.fromObject(n);if(t!==void 0)return t;let s=n[e.nestedKey];if(s&&typeof s=="object"&&!Array.isArray(s)){let i=e.fromObject(s);if(i!==void 0)return i}let r=n._meta;if(r&&typeof r=="object"&&!Array.isArray(r)){for(let[i,a]of Object.entries(r))if(i!=="hydra-acp"&&a&&typeof a=="object"&&!Array.isArray(a)){let u=e.fromObject(a);if(u!==void 0)return u}}let o=qd(n,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function is(n){return Kt(n,{nestedKey:"models",configId:"model",fromObject:e=>ge(e.currentModelId)??ge(e.currentModel)??ge(e.modelId)??ge(e.model),fromConfig:e=>ge(e.currentValue)})}function Ae(n,e){if(!n||typeof n!="object")return n;let t=n;if(t.code!==k.AuthRequired)return n;let s=c=>!!c&&typeof c=="object"&&!Array.isArray(c),r=s(t.data)?t.data:{},o=s(r._meta)?r._meta:{},i=s(o["hydra-acp"])?o["hydra-acp"]:{},a=typeof t.message=="string"?t.message:"authentication required",u=new Error(a);return u.code=k.AuthRequired,u.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},u}function mo(n){return/^[A-Za-z0-9_\-./=:@]+$/.test(n)?n:`'${n.replace(/'/g,"'\\''")}'`}function go(n,e,t,s){if(n&&typeof n=="object"&&n.code===k.AuthRequired)return n;let r=n instanceof Error?n.message:String(n),o=r.includes("stderr:"),i=o?"":e.stderrTailText(),a=s?`to reproduce: (cd ${mo(s.cwd)} && ${[s.command,...s.args].map(mo).join(" ")})`:"";if(!i&&!a)return n;let u=[o?r:`agent ${t} failed to start: ${r}`];i&&u.push(`stderr: ${i}`),a&&u.push(a);let c=new Error(u.join(`
122
122
  `));if(n&&typeof n=="object"){let d=n;typeof d.code=="number"&&(c.code=d.code),d.data!==void 0&&(c.data=d.data)}return c}function yt(n){if(!Array.isArray(n))return;let e=[];for(let t of n){if(!t||typeof t!="object")continue;let s=t;if(typeof s.id!="string")continue;let r=typeof s.description=="string"?s.description:"",o=s.type==="agent"||s.type==="terminal"?s.type:void 0,i=typeof s.name=="string"?s.name:void 0,a=s._meta,u=a!==null&&typeof a=="object"&&!Array.isArray(a)?a:void 0;e.push({id:s.id,description:r,...o&&{type:o},...i!==void 0&&{name:i},...u&&{_meta:u}})}return e.length>0?e:void 0}function ge(n){if(typeof n!="string")return;let e=n.trim();return e.length>0?e:void 0}function qd(n,e){let t=n.configOptions;if(Array.isArray(t))for(let s of t){if(!s||typeof s!="object"||Array.isArray(s))continue;let r=s;if(r.id===e)return r}}function as(n){return n.length>0?n:void 0}function ds(n){return Kt(n,{nestedKey:"models",configId:"model",fromObject:e=>{let t=We(e.availableModels);return t.length>0?t:void 0},fromConfig:e=>{let t=We(e.options);return t.length>0?t:void 0}})??[]}function cs(n){return Kt(n,{nestedKey:"modes",configId:"mode",fromObject:e=>{let t=lt(e.availableModes);return t.length>0?t:void 0},fromConfig:e=>{let t=lt(e.options);return t.length>0?t:void 0}})??[]}function us(n){return Kt(n,{nestedKey:"modes",configId:"mode",fromObject:e=>ge(e.currentModeId)??ge(e.currentMode)??ge(e.modeId)??ge(e.mode),fromConfig:e=>ge(e.currentValue)})}function zd(n){for(let e=n.length-1;e>=0;e--){let t=n[e];if(!t||t.method!=="session/update")continue;let s=t.params?.update;if(s?.sessionUpdate==="turn_complete"&&!(typeof s.messageId!="string"||s.messageId.length===0))return{index:e,messageId:s.messageId}}}async function ho(n){try{let e=await Te.readFile(I.tuiHistoryFile(n),"utf8"),t=[];for(let s of e.split(`
123
123
  `))if(s.length!==0)try{let r=JSON.parse(s);typeof r=="string"&&t.push(r)}catch{}return t}catch{return[]}}async function wt(n){try{let e=await Te.stat(I.historyFile(n));return{mtime:new Date(e.mtimeMs).toISOString(),hasContent:e.size>0}}catch{return{hasContent:!1}}}function Ge(n,e){return n.interactive!==void 0?n.interactive:n.originatingClient?.name===qt?!1:e?!0:void 0}import{spawn as Jd}from"child_process";import*as Xe from"fs";import*as Ce from"fs/promises";import*as wo from"path";var Gt=class{windowMs;maxFailures;now;recentExits=[];tripped_;constructor(e={}){this.windowMs=e.windowMs??3e5,this.maxFailures=e.maxFailuresInWindow??10,this.now=e.now??Date.now}recordExit(e,t,s){if(e===78){let i=`exited with code 78 (unrecoverable); fix and run \`${s}s start ${t}\``;return this.tripped_=i,{tripped:i}}let r=this.now();this.recentExits.push(r);let o=r-this.windowMs;for(;this.recentExits.length>0&&this.recentExits[0]<o;)this.recentExits.shift();if(this.recentExits.length>this.maxFailures){let i=Math.round(this.windowMs/6e4),a=`${this.recentExits.length} exits in ${i}m (crash loop); fix and run \`${s}s start ${t}\``;return this.tripped_=a,{tripped:a}}return"restart"}reset(){this.recentExits=[],this.tripped_=void 0}get tripped(){return this.tripped_}};var Wd=1e3,Qd=6e4,ls=3e3,Ye=class{entries=new Map;stopping=!1;context;tokenRegistry;breakerOptions;restartBaseMs;restartCapMs;adapter;constructor(e,t,s,r={}){this.adapter=t,this.context=s,this.tokenRegistry=r.tokenRegistry,this.breakerOptions=r.breakerOptions,this.restartBaseMs=r.restartBaseMs??Wd,this.restartCapMs=r.restartCapMs??Qd;for(let o of e)this.entries.set(o.name,this.makeEntry(o))}setContext(e){this.context=e}reportVersion(e,t){let s=this.entries.get(e);s&&(s.version=t)}async start(){if(!this.context)throw new Error(`${this.managerName()}: setContext must be called before start`);await Ce.mkdir(this.adapter.paths.dir(),{recursive:!0}),await this.reapOrphans();for(let e of this.entries.values())e.config.enabled&&this.spawn(e,0)}async stop(){this.stopping=!0;let e=[];for(let t of this.entries.values()){t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let s=t.child;if(s){try{s.kill("SIGTERM")}catch{}e.push(new Promise(r=>{if(s.exitCode!==null||s.signalCode!==null){r();return}let o=setTimeout(()=>{try{s.kill("SIGKILL")}catch{}r()},ls);s.on("exit",()=>{clearTimeout(o),r()})}))}}await Promise.allSettled(e);for(let t of this.entries.values()){try{t.logStream?.end()}catch{}t.child=void 0,t.logStream=void 0,t.pid=void 0}}list(){return[...this.entries.values()].map(e=>this.infoFor(e))}get(e){let t=this.entries.get(e);return t?this.infoFor(t):void 0}has(e){return this.entries.has(e)}async startByName(e){let t=this.entries.get(e);if(!t)throw It(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");if(t.child)throw It(new Error(`${this.adapter.kind} ${e} already running`),"CONFLICT");return t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0),t.manuallyStopped=!1,t.restartCount=0,t.breaker.reset(),t.failureReason=void 0,this.spawn(t,0),this.infoFor(t)}async stopByName(e){let t=this.entries.get(e);if(!t)throw It(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");t.manuallyStopped=!0,t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let s=t.child;return s?(await this.terminate(t,s),this.infoFor(t)):this.infoFor(t)}async restartByName(e){return await this.stopByName(e),this.startByName(e)}register(e){if(this.entries.has(e.name))throw It(new Error(`${this.adapter.kind} ${e.name} already exists`),"CONFLICT");if(!this.context)throw new Error(`${this.managerName()}: setContext must be called before register`);let t=this.makeEntry(e);return this.entries.set(e.name,t),e.enabled&&this.spawn(t,0),this.infoFor(t)}async unregister(e){let t=this.entries.get(e);if(!t)throw It(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");t.manuallyStopped=!0,t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let s=t.child;s&&await this.terminate(t,s);try{t.logStream?.end()}catch{}this.entries.delete(e)}async terminate(e,t){if(t.exitCode!==null||t.signalCode!==null)return;let s=new Promise(o=>{e.exitWaiters.push(o)});try{t.kill("SIGTERM")}catch{}let r=setTimeout(()=>{try{t.kill("SIGKILL")}catch{}},ls);typeof r.unref=="function"&&r.unref();try{await s}finally{clearTimeout(r)}}infoFor(e){let t;return e.failureReason!==void 0?t="failed":e.child?t="running":e.restartTimer?t="restarting":e.config.enabled?t="stopped":t="disabled",{name:e.config.name,status:t,pid:e.pid,enabled:e.config.enabled,restartCount:e.restartCount,startedAt:e.startedAt,lastExitCode:e.lastExitCode,logPath:this.adapter.paths.logFile(e.config.name),version:e.version,failureReason:e.failureReason}}makeEntry(e){return{config:e,child:void 0,logStream:void 0,restartTimer:void 0,pid:void 0,startedAt:void 0,restartCount:0,lastExitCode:void 0,manuallyStopped:!1,exitWaiters:[],version:void 0,processToken:void 0,breaker:new Gt(this.breakerOptions),failureReason:void 0}}async reapOrphans(){let e;try{e=await Ce.readdir(this.adapter.paths.dir())}catch(t){if(t.code==="ENOENT")return;throw t}for(let t of e){if(!t.endsWith(".pid"))continue;let s=wo.join(this.adapter.paths.dir(),t),r;try{let o=await Ce.readFile(s,"utf8"),i=Number.parseInt(o.trim(),10);Number.isInteger(i)&&i>0&&(r=i)}catch{}if(typeof r=="number"&&fs(r)){try{process.kill(r,"SIGTERM")}catch{}let o=Date.now()+ls;for(;Date.now()<o&&fs(r);)await new Promise(i=>setTimeout(i,50));if(fs(r))try{process.kill(r,"SIGKILL")}catch{}}await Ce.unlink(s).catch(()=>{})}}spawn(e,t){if(this.stopping||e.manuallyStopped)return;let s=this.context;if(!s)throw new Error(`${this.managerName()}.spawn called before setContext`);let r=e.config,o=r.command.length>0?r.command:[r.name],i=Xe.createWriteStream(this.adapter.paths.logFile(r.name),{flags:"a"});i.write(`[hydra-acp] ${new Date().toISOString()} starting ${this.adapter.kind} ${r.name} (attempt ${t+1})
124
124
  `);let a=this.tokenRegistry?.mint(r.name,this.adapter.tokenRole)??s.serviceToken;e.processToken=a,e.version=void 0;let u={...process.env,HYDRA_ACP_DAEMON_URL:s.daemonUrl,HYDRA_ACP_DAEMON_HOST:s.daemonHost,HYDRA_ACP_DAEMON_PORT:String(s.daemonPort),HYDRA_ACP_TOKEN:a,HYDRA_ACP_WS_URL:s.daemonWsUrl,HYDRA_ACP_HOME:s.hydraHome,[this.adapter.nameEnvVar]:r.name,...r.env},[c,...d]=o;if(c===void 0){i.write(`[hydra-acp] ${this.adapter.kind} ${r.name} has empty command
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydra-acp/cli",
3
- "version": "0.1.99",
3
+ "version": "0.1.101",
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",