@hydra-acp/cli 0.1.156 → 0.1.157
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +3 -3
- package/dist/daemon.js +3 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -29,7 +29,7 @@ var $P=Object.defineProperty;var G=(n,e)=>()=>(n&&(e=n(n=0)),e);var rc=(n,e)=>{f
|
|
|
29
29
|
`;await ds.writeFile(t,r,"utf8")}async function FS(n){let e=D.queueFile(n),t;try{t=await ds.readFile(e,"utf8")}catch(s){if(s.code==="ENOENT")return[];throw s}let r=[];for(let s of t.split(`
|
|
30
30
|
`))if(s.trim())try{let o=JSON.parse(s);o&&typeof o.messageId=="string"&&Array.isArray(o.prompt)&&typeof o.enqueuedAt=="number"&&r.push(o)}catch{}return r}async function LS(n){let e=D.queueFile(n);await ds.unlink(e).catch(()=>{})}var yg=G(()=>{"use strict";Ie()});import{customAlphabet as WS}from"nanoid";import*as zS from"fs/promises";function cs(){return`m_${qS()}`}function Ue(n){return n.startsWith(fn)?n.slice(fn.length):n}function g$(n){let e=n?.update;if(!e||typeof e!="object"||e.sessionUpdate!=="usage_update")return!1;let t=e._meta;if(!t||typeof t!="object")return!1;let r=t["_claude/origin"];if(!r||typeof r!="object")return!1;let s=r.kind;return typeof s=="string"&&m$.has(s)}function Gn(n,e){return n.code=e,n}function k$(n,e,t){return t?.run_in_background===!0?!1:e?.toolName==="Monitor"||n==="Monitor"||typeof e?.toolResponse?.taskId=="string"}function v$(n){return typeof n!="string"?void 0:/Command running in background with ID: ([A-Za-z0-9_-]+)/.exec(n)?.[1]}function S$(n){if(!n||typeof n!="object"||Array.isArray(n))return;let e=n.claudeCode;if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,r={};return t.toolName!==void 0&&(r.toolName=t.toolName),t.toolResponse&&typeof t.toolResponse=="object"&&(r.toolResponse=t.toolResponse),r}function bg(n,e){if(n!=="session/update")return!1;let r=(e??{}).update?.sessionUpdate;return typeof r=="string"&&b$.has(r)}function x$(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 I$(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 C$(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 Qa(n){if(!Array.isArray(n))return[];let e=[];for(let t of n){if(!t||typeof t!="object"||Array.isArray(t))continue;let r=t,s=typeof r.modelId=="string"&&r.modelId.trim()||typeof r.value=="string"&&r.value.trim()||typeof r.id=="string"&&r.id.trim()||void 0;if(!s)continue;let o={modelId:s};typeof r.name=="string"&&r.name.length>0&&(o.name=r.name),typeof r.description=="string"&&r.description.length>0&&(o.description=r.description),e.push(o)}return e}function Tc(n){if(!Array.isArray(n))return[];let e=[];for(let t of n){if(!t||typeof t!="object"||Array.isArray(t))continue;let r=t,s=typeof r.value=="string"&&r.value.trim()||typeof r.id=="string"&&r.id.trim()||void 0;if(!s)continue;let o={id:s};typeof r.name=="string"&&r.name.length>0&&(o.name=r.name),typeof r.description=="string"&&r.description.length>0&&(o.description=r.description),e.push(o)}return e}function R$(n){let t=(n??{}).update??{};if(t.sessionUpdate!=="available_modes_update")return null;let r=t.availableModes;if(!Array.isArray(r))return[];let s=[];for(let o of r){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),s.push(a)}return s}function A$(n,e){let r=(e??{}).update??{},s=r.sessionUpdate;if(s==="agent_message_chunk"){let o=r.content??{};typeof o.text=="string"&&(n.chunks.push(o.text),n.messageChars+=o.text.length);return}if(s==="agent_thought_chunk"){let o=r.content??{};typeof o.text=="string"&&(n.thinkingChars+=o.text.length);return}if(s==="tool_call"){n.toolCalls++;return}if(s==="usage_update"){typeof r.used=="number"&&(n.lastUsed=r.used),typeof r.size=="number"&&(n.lastSize=r.size);return}}function T$(n){let t=(n??{}).update??{};if(t.sessionUpdate!=="available_commands_update")return null;let r=t.availableCommands??t.commands;if(!Array.isArray(r))return[];let s=[];for(let o of r){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),s.push(a)}return s}function E$(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:cs()}}}function Wu(n,e){for(let t=0;t<n.length;t++){let r=n[t];if(!r||r.method!=="session/update")continue;if(r.params?.update?.messageId===e)return t}return-1}function DS(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 P$(n){let e=M$(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=_$(n.resolver),t}function M$(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 r={kind:t},s=e.optionId;typeof s=="string"&&(r.optionId=s);let o=e.reason;return typeof o=="string"&&(r.reason=o),r}function _$(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 Ya(n){return typeof n=="string"?n:Array.isArray(n)?n.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?e.text:"").join(""):""}function HS(n,e){return n.map(t=>{if(t&&typeof t=="object"&&typeof t.text=="string"){let r=t;return{...r,text:e(r.text)}}return t})}function kg(n,e){let t=n.findIndex(o=>o&&typeof o=="object"&&typeof o.text=="string");if(t<0)return n;let r=n[t],s=[...n];return s[t]={...r,text:`${e}${r.text}`},s}function vg(n){return n==="session/prompt"?{stopReason:"stopped"}:{}}function O$(n){return n==="session/request_permission"?{outcome:{outcome:"cancelled"}}:{}}function US(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(s=>s.value.length)),r=n.options.map(s=>{let o=s.value===n.currentValue?"\u25B6":"\xB7",i=s.name&&s.name!==s.value,a=i?s.value.padEnd(t):s.value;return i?` ${o} ${a} ${s.name}`:` ${o} ${a}`});return`${e}
|
|
31
31
|
${r.join(`
|
|
32
|
-
`)}`}function Sg(n,e){for(let t of n.split(/\r?\n/)){let r=t.trim();if(r)return r.length>e?`${r.slice(0,e)}\u2026`:r}}var jS,qS,wg,l$,u$,f$,fn,NS,p$,Uu,h$,m$,BS,y$,w$,Xa,b$,$$,fr=G(()=>{"use strict";sg();Ic();gS();yS();Bu();xc();vS();AS();PS();OS();yg();un();Ua();jS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",qS=WS(jS,16),wg=WS(jS,16),l$=20,u$=20,f$=5,fn="hydra_session_";NS=["start","merge","apply","sync","stop","detach","discard","clean","status"],p$=1e3,Uu=300*1e3,h$=64,m$=new Set(["task-notification","peer","coordinator","observer","observer-activity"]);BS=120,y$=128,w$=1e3,Xa=class n{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=as;modelVerbConfirmed=!1;agentArgs;parentSessionId;forkedFromSessionId;forkedFromMessageId;forkSynthesisState;originatingClient;_interactive;get interactive(){return this._interactive}_priority;get priority(){return this._priority}title;_summarizedThroughEntry;get summarizedThroughEntry(){return this._summarizedThroughEntry}set summarizedThroughEntry(e){this._summarizedThroughEntry=e}currentModel;currentMode;compactionState;_currentUsage;updatedAt;createdAt;clients=new Map;historyStore;promptQueue=[];currentEntry;promptInFlight=!1;agentTurnInFlight=!1;swapInFlight=!1;modeChangeInFlight=!1;modelChangeInFlight=!1;queueWriteChain=Promise.resolve();closed=!1;closing=!1;closeInFlight;deleteRecordIntent=!1;closeHandlers=[];titleHandlers=[];scheduleSynopsisHook;scheduleWorkspaceSnapshotHook;scheduleCompactionHook;resolveAgentIdHook;getCompactionStateHook;getUpstreamGenerationsHook;getPendingAgentSwapHook;_liveCompactionPhase;broadcastHandlers=[];lastCancelAt=0;static CANCEL_ERROR_WINDOW_MS=2e3;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}promptStartedAt;unsolicitedTurn;supersededAutonomousTurn;autonomousSalvage;lastBackgroundTask;toolLabels=new Map;armedTasks=new Map;lastArmedBroadcast;sawTurnComplete=!1;appendCount=0;historyMaxEntries;compactEvery;permissionCallbacks=new Map;attentionFlags=new Map;get hasPermissionFlag(){for(let e of this.attentionFlags.values())if(e.source==="daemon"&&e.reason.startsWith("permission:"))return!0;return!1}attentionFlagsChangeHandlers=[];internalPromptCapture;idleTimeoutMs;idleTimer;idleEventTimeoutMs;idleHandlers=[];lastRecordedAt;spawnReplacementAgent;mintMcpServersForSwap;loadExistingAgentSession;clearRollbackBreadcrumbHook;onCompactionSwapHook;persistWatermarkHook;uncompactHook;forkHook;mcpServersConfig;forwardedEnv;workspace;workspaceError;workspaceNotes=[];workspaceHook;workspacePreambleSent=!1;formerWorkspace;departureNoteSent=!1;listSessions;logger;transformChain;extensionCommands;extensionCommandsUnsub;pendingClaims=new Map;toolCompletionSeen=new Map;toolCallKind=new Fu;filesEditedSeen=new Set;openToolCalls=new Set;agentChangeHandlers=[];retiringGenerationCost;agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];availableAgentsFn;modelHandlers=[];modeHandlers=[];interactiveHandlers=[];priorityHandlers=[];usageHandlers=[];cumulativeCost=0;costLedgerProbe;get persistableUsage(){if(!(!this._currentUsage&&!this.cumulativeCost))return{...this._currentUsage??{},...this.cumulativeCost?{cumulativeCost:this.cumulativeCost}:{cumulativeCost:void 0}}}get currentUsage(){if(!this._currentUsage&&!this.cumulativeCost)return;let e=this._currentUsage??{},t=this.cumulativeCost+(e.costAmount??0);return{...e,costAmount:t||void 0,cumulativeCost:void 0}}amendInProgress;inFlightExtensionDispatches=new Map;recentlyTerminal=new Map;streamBuffer;streamFilePath;constructor(e){if(this.sessionId=e.sessionId??`${fn}${qS()}`,this.cwd=e.cwd,this.workspace=e.workspace,this.workspaceError=e.workspaceError,this.workspaceHook=e.workspaceHook,this.agentId=e.agentId,this.agent=e.agent,this.upstreamSessionId=e.upstreamSessionId,this.agentMeta=e.agentMeta,this.agentCapabilities=e.agentCapabilities,this.agentArgs=e.agentArgs,this.parentSessionId=e.parentSessionId,this.forkedFromSessionId=e.forkedFromSessionId,this.forkedFromMessageId=e.forkedFromMessageId,this.forkSynthesisState=e.forkSynthesisState,this.originatingClient=e.originatingClient,this.title=e.title,this.scheduleSynopsisHook=e.scheduleSynopsis,this.scheduleWorkspaceSnapshotHook=e.scheduleWorkspaceSnapshot,this.scheduleCompactionHook=e.scheduleCompaction,this.resolveAgentIdHook=e.resolveAgentId,this.getCompactionStateHook=e.getCompactionState,this.getUpstreamGenerationsHook=e.getUpstreamGenerations,this.getPendingAgentSwapHook=e.getPendingAgentSwap,this.currentModel=e.currentModel,this.currentMode=e.currentMode,this._currentUsage=e.currentUsage,this.cumulativeCost=e.currentUsage?.cumulativeCost??0,e.reloadsUpstreamLedger&&this.armCostLedgerProbe(),e.agentCommands&&e.agentCommands.length>0&&(this.agentAdvertisedCommands=[...e.agentCommands]),e.agentModes&&e.agentModes.length>0&&(this.agentAdvertisedModes=[...e.agentModes]),e.agentModels&&e.agentModels.length>0&&(this.agentAdvertisedModels=[...e.agentModels]),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.persistWatermarkHook=e.persistWatermarkHook,this.uncompactHook=e.uncompactHook,this.forkHook=e.forkHook,this.mcpServersConfig=e.mcpServers,this.forwardedEnv=e.forwardedEnv,this.availableAgentsFn=e.availableAgents,this.listSessions=e.listSessions,this.logger=e.logger,this.transformChain=e.transformChain??[],this.extensionCommands=e.extensionCommands,this.extensionCommands&&(this.extensionCommandsUnsub=this.extensionCommands.onChange(()=>{this.closed||this.broadcastMergedCommands()})),e.firstPromptSeeded&&(this._firstPromptSeeded=!0),this._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??p$,this.compactEvery=Math.max(1,Math.floor(this.historyMaxEntries*.2)),this.updatedAt=Date.now(),this.createdAt=e.createdAt??this.updatedAt,this.lastRecordedAt=this.updatedAt,this.resetModelVerb(e.modelVerb),this.wireAgent(this.agent),this.scheduleIdleCheck(),this.notifyChain("session.opened",{})}broadcastMergedCommands(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"available_commands_update",availableCommands:this.mergedAvailableCommands()}})}broadcastAvailableModes(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"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){A$(this.internalPromptCapture,t);return}this.maybeEmitToolEdges(t),this.runResponseChain(t)}),e.connection.onRequest("session/request_permission",async t=>{let r=await this.runAgentRequestChain("session/request_permission",t),s=DS(r.shortCircuit?t:r.envelope);if(r.shortCircuit)return this.notifyChain("permission.replied",{toolCallId:s??null,outcome:r.payload,sourceWasTransformer:!0}),r.payload;let o=await this.handlePermissionRequest(r.envelope);return this.notifyChain("permission.replied",{toolCallId:s??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,r=0,s="session/update"){let o=e,i=s==="session/update"?this.injectCumulativeCost(e):e,a=`response:${s}`;for(let l=r;l<this.transformChain.length;l++){let u=this.transformChain[l];if(t.has(u.name)||!u.intercepts.has(a))continue;let f=`t_${wg()}`,p;try{p=await u.connection.request("hydra-acp/transformer/message",{token:f,phase:"response",method:s,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(m){this.logger?.warn(`transformer ${u.name} error on ${a}: ${m.message}`);continue}let h=p?.action??"continue";if(h==="stop")return;if(h==="processing"){let m=l,y=i,w=new Set(t),v=s;await new Promise(b=>{let S=setTimeout(()=>{this.pendingClaims.delete(f)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:f,transformerName:u.name}),this.runResponseChain(y,new Set([...w,u.name]),m+1,v).then(()=>b()).catch(()=>b()))},Uu);typeof S.unref=="function"&&S.unref(),this.pendingClaims.set(f,{resolve:()=>b(),timer:S,transformerName:u.name,method:v,envelope:y,chainIdx:m,originatedBy:w,side:"response"})});return}p?.payload&&typeof p.payload=="object"&&(i=p.payload),t.add(u.name)}if(s!=="session/update")return;this.noteAgentActivity(i);let d=T$(i);if(d!==null){this.setAgentAdvertisedCommands(d);return}let c=R$(i);if(c!==null){this.setAgentAdvertisedModes(c);return}if(this.noteModelVerbHint(uS(i.update),"session/update"),this.maybeApplyAgentModel(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentMode(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentConfigOption(i)){this.recordAndBroadcast("session/update",this.mergeAgentOptionIntoEnvelope(i));return}if(this.maybeApplyAgentUsage(o)){this.recordAndBroadcast("session/update",i);return}this.maybeApplyAgentSessionInfo(i),this.recordAndBroadcast("session/update",i)}onAgentChange(e){this.agentChangeHandlers.push(e)}get attachedCount(){return this.clients.size}connectedClients(e){let t=[];for(let r of this.clients.values()){if(e&&r.clientId===e)continue;let s={clientId:r.clientId};r.clientInfo?.name&&(s.name=r.clientInfo.name),r.clientInfo?.version&&(s.version=r.clientInfo.version),t.push(s)}return t}get turnStartedAt(){return this.promptStartedAt}get inUnsolicitedTurn(){return this.unsolicitedTurn!==void 0}get agentPid(){return this.agent.pid}get awaitingInput(){return this.attentionFlags.size>0}async isQuiescedForSwap(){return await this.quiesceBlocker()===void 0}async quiesceBlocker(){if(this.agentTurnInFlight)return"the agent is still working; wait for the current turn to finish, then try again";if(this.unsolicitedTurn!==void 0)return"the agent is part-way through a turn it started by itself; wait for it to finish or interrupt it (^C), then try again";if(this.internalPromptCapture!==void 0)return"hydra is driving the agent right now (compaction seed or transcript injection); this clears by itself, so try again in a moment";if(this.modelChangeInFlight)return"a model change is still settling; try again in a moment";if(this.modeChangeInFlight)return"a mode change is still settling; try again in a moment";let e=await this.openToolCallIdsInHistory();if(e.length>0)return`${e.length} tool call(s) from an earlier turn never reported a result, so the session still reads as busy. ^C closes an abandoned chain; failing that it clears as new history accumulates`}isQuiescedSync(){return!(this.promptInFlight||this.unsolicitedTurn!==void 0||this.modeChangeInFlight||this.modelChangeInFlight)}async swapIntoWorkspace(e){await this.swapUpstream({...e.synopsis!==void 0?{artifact:e.synopsis}:{},note:e.note,framing:"swap",...e.title!==void 0?{title:e.title}:{},tailK:8,tailFloor:4,summarizedThroughEntry:e.historyLength,newCwd:e.cwd,reason:e.workspace!==void 0?"workspace-enter":"workspace-leave"}),this.workspace=e.workspace,e.left!==void 0?(this.formerWorkspace={path:e.left.path,sourceCwd:e.cwd,removed:e.left.removed},this.departureNoteSent=!1):this.formerWorkspace=void 0}async swapUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for swap: ${t}`);if(this.swapInFlight)throw new Error("a swap is already in progress for this session");this.swapInFlight=!0;try{await this.doSwapUpstream(e)}finally{this.swapInFlight=!1}}async doSwapUpstream(e){this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let t=this.agentId,r=e.newAgentId??this.agentId,s=r!==this.agentId,o=e.reason!==void 0&&e.reason!=="compaction"?e.reason:s?"agent-swap":"compaction",i=e.newCwd??this.cwd,a=this.agentArgs,d=this.forwardedEnv,c=this.currentModel,l=this.currentMode,u=this.spawnReplacementAgent;if(!u)throw new Error("agent spawning not configured for this session");let f=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],p=await u({agentId:r,cwd:i,agentArgs:a,...d?{forwardedEnv:d}:{},mcpServers:f});this.accumulateAndResetCost(),this.cwd=i,this.wireAgent(p.agent),s||(await za({agent:p.agent,upstreamSessionId:p.upstreamSessionId,persistedModel:c,agentReportedModel:p.initialModel,logger:this.logger}),await qa({agent:p.agent,upstreamSessionId:p.upstreamSessionId,persistedMode:l,agentReportedMode:p.initialMode,logger:this.logger})),p.agent.connection.drainBuffered("session/update");let h=[];if(this.historyStore)try{h=await this.historyStore.load(this.sessionId)}catch(B){this.logger?.warn(`swapUpstream: historyStore.load failed: ${B.message}`)}let m=hg({...e.artifact!==void 0?{synopsis:e.artifact}:{},...e.note!==void 0?{note:e.note}:{},...e.framing!==void 0?{framing:e.framing}:{},title:e.title,tail:h,tailK:e.tailK,tailFloor:e.tailFloor,...e.summarizedThroughEntry!==void 0?{watermark:e.summarizedThroughEntry}:{},recallArmed:(e.summarizedThroughEntry??this._summarizedThroughEntry??0)>0});if(this.internalPromptCapture)throw new Error("swapUpstream: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};let y,w;try{await p.agent.connection.request("session/prompt",{sessionId:p.upstreamSessionId,prompt:[{type:"text",text:m}]});let B=this.internalPromptCapture;y=B.lastUsed,w=B.lastSize,this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${m.length} toolCalls=${B.toolCalls} thinkingChars=${B.thinkingChars} messageChars=${B.messageChars} used=${B.lastUsed??"?"} size=${B.lastSize??"?"} reply=${JSON.stringify(B.chunks.join("").slice(0,200))}`)}finally{this.internalPromptCapture=void 0}y!==void 0&&(this.maybeApplyAgentUsage({update:{sessionUpdate:"usage_update",used:y,...w!==void 0?{size:w}:{}}}),this.broadcastCurrentUsage());let v=this.upstreamSessionId,b=this._summarizedThroughEntry;e.summarizedThroughEntry!==void 0&&(this._summarizedThroughEntry=e.summarizedThroughEntry);let S=this.agent;if(this.agent=p.agent,this.upstreamSessionId=p.upstreamSessionId,this.agentMeta=p.agentMeta,this.agentCapabilities=p.agentCapabilities,this.resetModelVerb(p.modelVerb),s&&(this.agentId=r,this.agentAdvertisedCommands=[],this.currentModel=p.initialModel,this.currentMode=p.initialMode,this.setAgentAdvertisedModels(p.initialModels??[]),this.setAgentAdvertisedModes(p.initialModes??[])),this.broadcastMergedCommands(),this.broadcastConfigOptions(),this.notifyAgentChange("swapUpstream",o,e.runId),e.summarizedThroughEntry!==void 0&&this.persistWatermarkHook)try{this.persistWatermarkHook(e.summarizedThroughEntry)}catch(B){this.logger?.warn(`swapUpstream: persistWatermarkHook failed: ${B.message}`)}if(!s&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:v,...b!==void 0?{previousSummarizedThroughEntry:b}:{},...e.runId!==void 0?{runId:e.runId}:{}})}catch(B){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${B.message}`)}let R=await this.retireAgent(S,s?"agent switch":e.reason==="workspace-enter"||e.reason==="workspace-leave"?"workspace move":"compaction swap");this.notifyChain("agent.swap",{phase:"post",previousUpstreamSessionId:v,upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}),s||this.broadcastCompactionPhase({phase:"swapped",...this.title!==void 0?{title:this.title}:{},summarizedThroughEntry:e.summarizedThroughEntry??this._summarizedThroughEntry??0}),s&&this.broadcastAgentSwitch(t,r);let C=R.length>0?`
|
|
32
|
+
`)}`}function Sg(n,e){for(let t of n.split(/\r?\n/)){let r=t.trim();if(r)return r.length>e?`${r.slice(0,e)}\u2026`:r}}var jS,qS,wg,l$,u$,f$,fn,NS,p$,Uu,h$,m$,BS,y$,w$,Xa,b$,$$,fr=G(()=>{"use strict";sg();Ic();gS();yS();Bu();xc();vS();AS();PS();OS();yg();un();Ua();jS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",qS=WS(jS,16),wg=WS(jS,16),l$=20,u$=20,f$=5,fn="hydra_session_";NS=["start","merge","apply","sync","stop","detach","discard","clean","status"],p$=1e3,Uu=300*1e3,h$=64,m$=new Set(["task-notification","peer","coordinator","observer","observer-activity"]);BS=120,y$=128,w$=1e3,Xa=class n{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=as;modelVerbConfirmed=!1;agentArgs;parentSessionId;forkedFromSessionId;forkedFromMessageId;forkSynthesisState;originatingClient;_interactive;get interactive(){return this._interactive}_priority;get priority(){return this._priority}title;_summarizedThroughEntry;get summarizedThroughEntry(){return this._summarizedThroughEntry}set summarizedThroughEntry(e){this._summarizedThroughEntry=e}currentModel;currentMode;compactionState;_currentUsage;updatedAt;createdAt;clients=new Map;historyStore;promptQueue=[];currentEntry;promptInFlight=!1;agentTurnInFlight=!1;swapInFlight=!1;modeChangeInFlight=!1;modelChangeInFlight=!1;queueWriteChain=Promise.resolve();closed=!1;closing=!1;closeInFlight;deleteRecordIntent=!1;closeHandlers=[];titleHandlers=[];scheduleSynopsisHook;scheduleWorkspaceSnapshotHook;scheduleCompactionHook;resolveAgentIdHook;getCompactionStateHook;getUpstreamGenerationsHook;getPendingAgentSwapHook;_liveCompactionPhase;broadcastHandlers=[];lastCancelAt=0;static CANCEL_ERROR_WINDOW_MS=2e3;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}_titleSeedPending=!0;promptStartedAt;unsolicitedTurn;supersededAutonomousTurn;autonomousSalvage;lastBackgroundTask;toolLabels=new Map;armedTasks=new Map;lastArmedBroadcast;sawTurnComplete=!1;appendCount=0;historyMaxEntries;compactEvery;permissionCallbacks=new Map;attentionFlags=new Map;get hasPermissionFlag(){for(let e of this.attentionFlags.values())if(e.source==="daemon"&&e.reason.startsWith("permission:"))return!0;return!1}attentionFlagsChangeHandlers=[];internalPromptCapture;idleTimeoutMs;idleTimer;idleEventTimeoutMs;idleHandlers=[];lastRecordedAt;spawnReplacementAgent;mintMcpServersForSwap;loadExistingAgentSession;clearRollbackBreadcrumbHook;onCompactionSwapHook;persistWatermarkHook;uncompactHook;forkHook;mcpServersConfig;forwardedEnv;workspace;workspaceError;workspaceNotes=[];workspaceHook;workspacePreambleSent=!1;formerWorkspace;departureNoteSent=!1;listSessions;logger;transformChain;extensionCommands;extensionCommandsUnsub;pendingClaims=new Map;toolCompletionSeen=new Map;toolCallKind=new Fu;filesEditedSeen=new Set;openToolCalls=new Set;agentChangeHandlers=[];retiringGenerationCost;agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];availableAgentsFn;modelHandlers=[];modeHandlers=[];interactiveHandlers=[];priorityHandlers=[];usageHandlers=[];cumulativeCost=0;costLedgerProbe;get persistableUsage(){if(!(!this._currentUsage&&!this.cumulativeCost))return{...this._currentUsage??{},...this.cumulativeCost?{cumulativeCost:this.cumulativeCost}:{cumulativeCost:void 0}}}get currentUsage(){if(!this._currentUsage&&!this.cumulativeCost)return;let e=this._currentUsage??{},t=this.cumulativeCost+(e.costAmount??0);return{...e,costAmount:t||void 0,cumulativeCost:void 0}}amendInProgress;inFlightExtensionDispatches=new Map;recentlyTerminal=new Map;streamBuffer;streamFilePath;constructor(e){if(this.sessionId=e.sessionId??`${fn}${qS()}`,this.cwd=e.cwd,this.workspace=e.workspace,this.workspaceError=e.workspaceError,this.workspaceHook=e.workspaceHook,this.agentId=e.agentId,this.agent=e.agent,this.upstreamSessionId=e.upstreamSessionId,this.agentMeta=e.agentMeta,this.agentCapabilities=e.agentCapabilities,this.agentArgs=e.agentArgs,this.parentSessionId=e.parentSessionId,this.forkedFromSessionId=e.forkedFromSessionId,this.forkedFromMessageId=e.forkedFromMessageId,this.forkSynthesisState=e.forkSynthesisState,this.originatingClient=e.originatingClient,this.title=e.title,this.scheduleSynopsisHook=e.scheduleSynopsis,this.scheduleWorkspaceSnapshotHook=e.scheduleWorkspaceSnapshot,this.scheduleCompactionHook=e.scheduleCompaction,this.resolveAgentIdHook=e.resolveAgentId,this.getCompactionStateHook=e.getCompactionState,this.getUpstreamGenerationsHook=e.getUpstreamGenerations,this.getPendingAgentSwapHook=e.getPendingAgentSwap,this.currentModel=e.currentModel,this.currentMode=e.currentMode,this._currentUsage=e.currentUsage,this.cumulativeCost=e.currentUsage?.cumulativeCost??0,e.reloadsUpstreamLedger&&this.armCostLedgerProbe(),e.agentCommands&&e.agentCommands.length>0&&(this.agentAdvertisedCommands=[...e.agentCommands]),e.agentModes&&e.agentModes.length>0&&(this.agentAdvertisedModes=[...e.agentModes]),e.agentModels&&e.agentModels.length>0&&(this.agentAdvertisedModels=[...e.agentModels]),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.persistWatermarkHook=e.persistWatermarkHook,this.uncompactHook=e.uncompactHook,this.forkHook=e.forkHook,this.mcpServersConfig=e.mcpServers,this.forwardedEnv=e.forwardedEnv,this.availableAgentsFn=e.availableAgents,this.listSessions=e.listSessions,this.logger=e.logger,this.transformChain=e.transformChain??[],this.extensionCommands=e.extensionCommands,this.extensionCommands&&(this.extensionCommandsUnsub=this.extensionCommands.onChange(()=>{this.closed||this.broadcastMergedCommands()})),e.firstPromptSeeded&&(this._firstPromptSeeded=!0,this._titleSeedPending=!1),this._interactive=e.interactive,this._priority=e.priority,this._summarizedThroughEntry=e.summarizedThroughEntry,this.compactionState=e.compactionState,e.compactionState){let t=e.compactionState;(t.status==="requested"||t.status==="running"||t.status==="swap_pending"||t.status==="swap_deferred")&&(t.status==="swap_deferred"?this._liveCompactionPhase={phase:"deferred",attempts:t.attempts}:this._liveCompactionPhase={phase:t.status==="requested"?"started":"iteration",iter:t.iter})}if(e.attentionFlags&&e.attentionFlags.length>0)for(let t of e.attentionFlags)this.attentionFlags.set(`${t.source}::${t.reason}`,t);this.historyStore=e.historyStore,this.historyMaxEntries=e.historyMaxEntries??p$,this.compactEvery=Math.max(1,Math.floor(this.historyMaxEntries*.2)),this.updatedAt=Date.now(),this.createdAt=e.createdAt??this.updatedAt,this.lastRecordedAt=this.updatedAt,this.resetModelVerb(e.modelVerb),this.wireAgent(this.agent),this.scheduleIdleCheck(),this.notifyChain("session.opened",{})}broadcastMergedCommands(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"available_commands_update",availableCommands:this.mergedAvailableCommands()}})}broadcastAvailableModes(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"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){A$(this.internalPromptCapture,t);return}this.maybeEmitToolEdges(t),this.runResponseChain(t)}),e.connection.onRequest("session/request_permission",async t=>{let r=await this.runAgentRequestChain("session/request_permission",t),s=DS(r.shortCircuit?t:r.envelope);if(r.shortCircuit)return this.notifyChain("permission.replied",{toolCallId:s??null,outcome:r.payload,sourceWasTransformer:!0}),r.payload;let o=await this.handlePermissionRequest(r.envelope);return this.notifyChain("permission.replied",{toolCallId:s??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,r=0,s="session/update"){let o=e,i=s==="session/update"?this.injectCumulativeCost(e):e,a=`response:${s}`;for(let l=r;l<this.transformChain.length;l++){let u=this.transformChain[l];if(t.has(u.name)||!u.intercepts.has(a))continue;let f=`t_${wg()}`,p;try{p=await u.connection.request("hydra-acp/transformer/message",{token:f,phase:"response",method:s,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(m){this.logger?.warn(`transformer ${u.name} error on ${a}: ${m.message}`);continue}let h=p?.action??"continue";if(h==="stop")return;if(h==="processing"){let m=l,y=i,w=new Set(t),v=s;await new Promise(b=>{let S=setTimeout(()=>{this.pendingClaims.delete(f)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:f,transformerName:u.name}),this.runResponseChain(y,new Set([...w,u.name]),m+1,v).then(()=>b()).catch(()=>b()))},Uu);typeof S.unref=="function"&&S.unref(),this.pendingClaims.set(f,{resolve:()=>b(),timer:S,transformerName:u.name,method:v,envelope:y,chainIdx:m,originatedBy:w,side:"response"})});return}p?.payload&&typeof p.payload=="object"&&(i=p.payload),t.add(u.name)}if(s!=="session/update")return;this.noteAgentActivity(i);let d=T$(i);if(d!==null){this.setAgentAdvertisedCommands(d);return}let c=R$(i);if(c!==null){this.setAgentAdvertisedModes(c);return}if(this.noteModelVerbHint(uS(i.update),"session/update"),this.maybeApplyAgentModel(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentMode(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentConfigOption(i)){this.recordAndBroadcast("session/update",this.mergeAgentOptionIntoEnvelope(i));return}if(this.maybeApplyAgentUsage(o)){this.recordAndBroadcast("session/update",i);return}this.maybeApplyAgentSessionInfo(i),this.recordAndBroadcast("session/update",i)}onAgentChange(e){this.agentChangeHandlers.push(e)}get attachedCount(){return this.clients.size}connectedClients(e){let t=[];for(let r of this.clients.values()){if(e&&r.clientId===e)continue;let s={clientId:r.clientId};r.clientInfo?.name&&(s.name=r.clientInfo.name),r.clientInfo?.version&&(s.version=r.clientInfo.version),t.push(s)}return t}get turnStartedAt(){return this.promptStartedAt}get inUnsolicitedTurn(){return this.unsolicitedTurn!==void 0}get agentPid(){return this.agent.pid}get awaitingInput(){return this.attentionFlags.size>0}async isQuiescedForSwap(){return await this.quiesceBlocker()===void 0}async quiesceBlocker(){if(this.agentTurnInFlight)return"the agent is still working; wait for the current turn to finish, then try again";if(this.unsolicitedTurn!==void 0)return"the agent is part-way through a turn it started by itself; wait for it to finish or interrupt it (^C), then try again";if(this.internalPromptCapture!==void 0)return"hydra is driving the agent right now (compaction seed or transcript injection); this clears by itself, so try again in a moment";if(this.modelChangeInFlight)return"a model change is still settling; try again in a moment";if(this.modeChangeInFlight)return"a mode change is still settling; try again in a moment";let e=await this.openToolCallIdsInHistory();if(e.length>0)return`${e.length} tool call(s) from an earlier turn never reported a result, so the session still reads as busy. ^C closes an abandoned chain; failing that it clears as new history accumulates`}isQuiescedSync(){return!(this.promptInFlight||this.unsolicitedTurn!==void 0||this.modeChangeInFlight||this.modelChangeInFlight)}async swapIntoWorkspace(e){await this.swapUpstream({...e.synopsis!==void 0?{artifact:e.synopsis}:{},note:e.note,framing:"swap",...e.title!==void 0?{title:e.title}:{},tailK:8,tailFloor:4,summarizedThroughEntry:e.historyLength,newCwd:e.cwd,reason:e.workspace!==void 0?"workspace-enter":"workspace-leave"}),this.workspace=e.workspace,e.left!==void 0?(this.formerWorkspace={path:e.left.path,sourceCwd:e.cwd,removed:e.left.removed},this.departureNoteSent=!1):this.formerWorkspace=void 0}async swapUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for swap: ${t}`);if(this.swapInFlight)throw new Error("a swap is already in progress for this session");this.swapInFlight=!0;try{await this.doSwapUpstream(e)}finally{this.swapInFlight=!1}}async doSwapUpstream(e){this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let t=this.agentId,r=e.newAgentId??this.agentId,s=r!==this.agentId,o=e.reason!==void 0&&e.reason!=="compaction"?e.reason:s?"agent-swap":"compaction",i=e.newCwd??this.cwd,a=this.agentArgs,d=this.forwardedEnv,c=this.currentModel,l=this.currentMode,u=this.spawnReplacementAgent;if(!u)throw new Error("agent spawning not configured for this session");let f=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],p=await u({agentId:r,cwd:i,agentArgs:a,...d?{forwardedEnv:d}:{},mcpServers:f});this.accumulateAndResetCost(),this.cwd=i,this.wireAgent(p.agent),s||(await za({agent:p.agent,upstreamSessionId:p.upstreamSessionId,persistedModel:c,agentReportedModel:p.initialModel,logger:this.logger}),await qa({agent:p.agent,upstreamSessionId:p.upstreamSessionId,persistedMode:l,agentReportedMode:p.initialMode,logger:this.logger})),p.agent.connection.drainBuffered("session/update");let h=[];if(this.historyStore)try{h=await this.historyStore.load(this.sessionId)}catch(B){this.logger?.warn(`swapUpstream: historyStore.load failed: ${B.message}`)}let m=hg({...e.artifact!==void 0?{synopsis:e.artifact}:{},...e.note!==void 0?{note:e.note}:{},...e.framing!==void 0?{framing:e.framing}:{},title:e.title,tail:h,tailK:e.tailK,tailFloor:e.tailFloor,...e.summarizedThroughEntry!==void 0?{watermark:e.summarizedThroughEntry}:{},recallArmed:(e.summarizedThroughEntry??this._summarizedThroughEntry??0)>0});if(this.internalPromptCapture)throw new Error("swapUpstream: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};let y,w;try{await p.agent.connection.request("session/prompt",{sessionId:p.upstreamSessionId,prompt:[{type:"text",text:m}]});let B=this.internalPromptCapture;y=B.lastUsed,w=B.lastSize,this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${m.length} toolCalls=${B.toolCalls} thinkingChars=${B.thinkingChars} messageChars=${B.messageChars} used=${B.lastUsed??"?"} size=${B.lastSize??"?"} reply=${JSON.stringify(B.chunks.join("").slice(0,200))}`)}finally{this.internalPromptCapture=void 0}y!==void 0&&(this.maybeApplyAgentUsage({update:{sessionUpdate:"usage_update",used:y,...w!==void 0?{size:w}:{}}}),this.broadcastCurrentUsage());let v=this.upstreamSessionId,b=this._summarizedThroughEntry;e.summarizedThroughEntry!==void 0&&(this._summarizedThroughEntry=e.summarizedThroughEntry);let S=this.agent;if(this.agent=p.agent,this.upstreamSessionId=p.upstreamSessionId,this.agentMeta=p.agentMeta,this.agentCapabilities=p.agentCapabilities,this.resetModelVerb(p.modelVerb),s&&(this.agentId=r,this.agentAdvertisedCommands=[],this.currentModel=p.initialModel,this.currentMode=p.initialMode,this.setAgentAdvertisedModels(p.initialModels??[]),this.setAgentAdvertisedModes(p.initialModes??[])),this.broadcastMergedCommands(),this.broadcastConfigOptions(),this.notifyAgentChange("swapUpstream",o,e.runId),e.summarizedThroughEntry!==void 0&&this.persistWatermarkHook)try{this.persistWatermarkHook(e.summarizedThroughEntry)}catch(B){this.logger?.warn(`swapUpstream: persistWatermarkHook failed: ${B.message}`)}if(!s&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:v,...b!==void 0?{previousSummarizedThroughEntry:b}:{},...e.runId!==void 0?{runId:e.runId}:{}})}catch(B){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${B.message}`)}let R=await this.retireAgent(S,s?"agent switch":e.reason==="workspace-enter"||e.reason==="workspace-leave"?"workspace move":"compaction swap");this.notifyChain("agent.swap",{phase:"post",previousUpstreamSessionId:v,upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}),s||this.broadcastCompactionPhase({phase:"swapped",...this.title!==void 0?{title:this.title}:{},summarizedThroughEntry:e.summarizedThroughEntry??this._summarizedThroughEntry??0}),s&&this.broadcastAgentSwitch(t,r);let C=R.length>0?`
|
|
33
33
|
Stopped ${R.length} background task(s) with the previous agent: ${R.join(", ")}. Re-arm anything still needed.
|
|
34
34
|
`:"",E=(e.reason==="workspace-enter"||e.reason==="workspace-leave"?"":s?`
|
|
35
35
|
Switched to ${r}.
|
|
@@ -39,7 +39,7 @@ Compaction completed.
|
|
|
39
39
|
|
|
40
40
|
`),this.departureNoteSent=!0}return s}applyWorkspacePromptRewrite(e){let t=this.workspace;if(t===void 0)return this.applyDepartedPromptRewrite(e);let r=!1,s=HS(e,i=>gg(i,t.sourceCwd)?(r=!0,mg(i,t.sourceCwd,t.path).text):i);if(!this.workspacePreambleSent||r){let i=_S({workspacePath:t.path,sourceCwd:t.sourceCwd,notes:this.workspaceNotes,...this.workspacePreambleSent?{reassert:!0}:{}});s=kg(s,`${i}
|
|
41
41
|
|
|
42
|
-
`),this.workspacePreambleSent=!0}return s}async prompt(e,t,r){let s=this.clients.get(e);if(!s)throw Gn(new Error("client not attached"),V.SessionNotFound);if(this.closing)throw Gn(new Error("session is closing; new prompts cannot be accepted"),V.SessionClosing);let o=cs();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(En((t??{})._meta).ancillary===!0)&&this._interactive!==!0){this._interactive=!0;for(let a of this.interactiveHandlers)try{a(!0)}catch{}}return this.enqueueUserPrompt(s,t,o,r)}broadcastPromptReceived(e){this.closeUnsolicitedTurn("superseded",`prompt:${e.messageId}`);let t={clientId:e.originator.clientId};e.originator.name&&(t.name=e.originator.name),e.originator.version&&(t.version=e.originator.version),e.originator.fromSession&&(t.fromSession=e.originator.fromSession),e.originator.fromSessionTitle&&(t.fromSessionTitle=e.originator.fromSessionTitle),e.originator.fromLabel&&(t.fromLabel=e.originator.fromLabel),e.originator.depth!==void 0&&(t.depth=e.originator.depth),this.promptStartedAt=Date.now(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"prompt_received",messageId:e.messageId,prompt:e.prompt,sentBy:t}},e.clientId);let r=Ya(e.prompt);r.length>0&&this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"user_message_chunk",content:{type:"text",text:r},_meta:{"hydra-acp":{compatFor:"prompt_received"}}}},e.clientId)}recordCurrentUsageSnapshot(){if(this.historyStore===void 0)return;let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let s={};typeof e.costAmount=="number"&&(s.amount=e.costAmount),typeof e.costCurrency=="string"&&(s.currency=e.costCurrency),t.cost=s}if(Object.keys(t).length<=1)return;t._meta={"hydra-acp":{upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}};let r={sessionId:this.sessionId,update:t};this.historyStore.append(this.sessionId,{method:"session/update",params:r,recordedAt:Date.now()}).catch(()=>{})}broadcastTurnComplete(e,t,r,s){let o=t&&typeof t=="object"&&"stopReason"in t&&typeof t.stopReason=="string"?t.stopReason:void 0,i={sessionUpdate:"turn_complete",messageId:cs()};o!==void 0&&(i.stopReason=o);let a=En(t?._meta).salvaged;a!==void 0&&(i._meta={[kt]:{salvaged:a}}),this.supersededAutonomousTurn=void 0;let d=this.amendInProgress;d&&r!==void 0&&d.cancelledMessageId===r&&(i._meta={[kt]:{...a!==void 0?{salvaged:a}:{},amended:{cancelledMessageId:d.cancelledMessageId,newMessageId:d.newMessageId}}}),this.promptStartedAt=void 0,this.sawTurnComplete=!0,this.scheduleWorkspaceSnapshotHook?.(),r!==void 0&&o!==void 0&&this.recordTerminal(r,o),(o==="cancelled"||o==="error"||o==="refusal")&&this.closeOpenToolCalls(o),this.recordCurrentUsageSnapshot(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:i},s?void 0:e),d&&r!==void 0&&d.cancelledMessageId===r&&this.broadcastPromptAmended(d)}noteAgentActivity(e){if(!(this.closing||this.closed)){if(g$(e)){if(this.unsolicitedTurn!==void 0){this.closeUnsolicitedTurn("completed");return}this.salvageSupersededTerminal();return}bg("session/update",e)||(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||this.openUnsolicitedTurn()))}}noteBackgroundTaskArming(e){let t=e?.update;if(!t||typeof t!="object")return;let r=typeof t.toolCallId=="string"?t.toolCallId:void 0;if(r===void 0)return;let s=t.rawInput,o=S$(t._meta);this.rememberToolLabel(r,t,s,o),this.noteBackgroundTaskStopped(t,s,o);let i=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:v$(t.rawOutput);if(!(i!==void 0||s!==void 0&&s.run_in_background===!0))return;let d=this.toolLabels.get(r)?.label??"background task";this.lastBackgroundTask={toolCallId:r,label:d};let c=Date.now(),l=this.armedTasks.get(r),u=i??l?.taskId,f=k$(t.title,o,s)||l?.repeating===!0;this.armedTasks.set(r,{label:d,...u!==void 0?{taskId:u}:{},repeating:f,armedAt:l?.armedAt??c}),this.onArmedTasksChanged()}get armedBackgroundTasks(){return[...this.armedTasks.entries()].map(([e,t])=>({toolCallId:e,label:t.label,...t.taskId!==void 0?{taskId:t.taskId}:{}}))}get armedSince(){let e;for(let t of this.armedTasks.values())(e===void 0||t.armedAt<e)&&(e=t.armedAt);return e}onArmedTasksChanged(){let e=this.armedTasks.size,t=this.armedSince;e===this.lastArmedBroadcast?.count&&t===this.lastArmedBroadcast?.since||this.closed||(this.lastArmedBroadcast={count:e,since:t},this.broadcastQueueNotification("hydra-acp/session/armed_tasks_updated",{sessionId:this.sessionId,count:e,...t!==void 0?{since:t}:{},tasks:this.armedBackgroundTasks}))}async retireAgent(e,t){return await e.kill().catch(()=>{}),this.discardArmedTasks(t)}discardArmedTasks(e){if(this.armedTasks.size===0)return[];let t=[...this.armedTasks.values()].map(r=>r.label);return this.armedTasks.clear(),this.logger?.info(`session ${this.sessionId} discarded ${t.length} armed task(s) on ${e}: ${t.join(", ")}`),this.onArmedTasksChanged(),t}noteBackgroundTaskStopped(e,t,r){if(!(r?.toolName==="TaskStop"||e.title==="TaskStop"))return;let o=t?.task_id;if(typeof o!="string"||o.length===0)return;let i=!1;for(let[a,d]of this.armedTasks)d.taskId===o&&(this.armedTasks.delete(a),i=!0);i&&this.onArmedTasksChanged()}rememberToolLabel(e,t,r,s){let o=r!==void 0&&typeof r.description=="string"&&r.description?r.description:void 0;if(o!==void 0)this.toolLabels.set(e,{label:o.slice(0,BS),fromDescription:!0});else if(this.toolLabels.get(e)?.fromDescription!==!0){let i=typeof t.title=="string"&&t.title?t.title:typeof s?.toolName=="string"&&s.toolName?s.toolName:void 0;i!==void 0&&this.toolLabels.set(e,{label:i.slice(0,BS),fromDescription:!1})}for(;this.toolLabels.size>y$;){let i=this.toolLabels.keys().next().value;if(i===void 0)break;this.toolLabels.delete(i)}}openUnsolicitedTurn(){let e=Date.now(),t=this.lastBackgroundTask,r=!1;for(let[i,a]of this.armedTasks)a.repeating||(this.armedTasks.delete(i),r=!0);r&&this.onArmedTasksChanged();let s={messageId:cs(),startedAt:e,cause:t};this.unsolicitedTurn=s,this.promptStartedAt=e,this.logger?.info(`session ${this.sessionId} agent resumed with no prompt in flight`+(t?` (after ${t.label})`:""));let o={unsolicited:!0};t&&(o.cause=t),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"turn_started",messageId:s.messageId,_meta:{"hydra-acp":o}}})}async holdForUnsolicitedTurn(e){if(this.unsolicitedTurn===void 0){this.logger?.info(`session ${this.sessionId} queue hold skipped for ${e.messageId} (no unsolicited turn open)`);return}let t=Date.now(),r=this.unsolicitedTurn.cause;this.logger?.info(`session ${this.sessionId} holding ${e.messageId} behind unsolicited turn ${this.unsolicitedTurn.messageId}`+(r?` cause=${JSON.stringify(r.label)}`:"")),this.broadcastQueueNotification("hydra-acp/prompt_queue/held",{sessionId:this.sessionId,messageId:e.messageId,reason:"agent_resumed",...r?{cause:r}:{}});let s="turn_ended";for(;;){if(this.closing||this.closed){s="closing";break}if(e.cancelled){s="cancelled";break}if(this.unsolicitedTurn===void 0){s="turn_ended";break}await new Promise(i=>{let a=setTimeout(i,w$);typeof a.unref=="function"&&a.unref()})}let o=Date.now()-t;this.logger?.info(`session ${this.sessionId} released ${e.messageId} reason=${s} heldMs=${o}`),this.broadcastQueueNotification("hydra-acp/prompt_queue/released",{sessionId:this.sessionId,messageId:e.messageId,reason:s,heldMs:o})}closeUnsolicitedTurn(e,t){let r=this.unsolicitedTurn;if(r===void 0)return;let s=Date.now()-r.startedAt;this.unsolicitedTurn=void 0,this.promptStartedAt=void 0,this.logger?.info(`session ${this.sessionId} unsolicited turn ${r.messageId} closed reason=${e} durationMs=${s}`+(t?` by=${t}`:"")+(r.cause?` cause=${JSON.stringify(r.cause.label)}`:"")),e==="superseded"&&(this.supersededAutonomousTurn={turnMessageId:r.messageId,cause:r.cause,supersededAt:Date.now()}),this.recordCurrentUsageSnapshot(),!this.closed&&(e==="cancelled"&&this.closeOpenToolCalls("cancelled"),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"turn_ended",messageId:cs(),startedMessageId:r.messageId,durationMs:s,_meta:{"hydra-acp":{unsolicited:!0,reason:e}}}}))}salvageSupersededTerminal(){let e=this.supersededAutonomousTurn;if(e===void 0)return;this.supersededAutonomousTurn=void 0;let t=this.autonomousSalvage;t!==void 0&&(this.autonomousSalvage=void 0,this.logger?.warn(`session ${this.sessionId} salvaged session/prompt from autonomous terminal (superseded turn ${e.turnMessageId}, ${Date.now()-e.supersededAt}ms earlier)`+(e.cause?` cause=${JSON.stringify(e.cause.label)}`:"")),t({stopReason:"end_turn",_meta:{[kt]:{salvaged:{reason:"autonomous_terminal",supersededMessageId:e.turnMessageId}}}}))}async awaitPromptResponse(e){if(this.supersededAutonomousTurn===void 0)return e;try{return await new Promise((t,r)=>{this.autonomousSalvage=t,e.then(t,r)})}finally{this.autonomousSalvage=void 0}}recordTerminal(e,t){for(this.recentlyTerminal.set(e,{stopReason:t,terminatedAt:Date.now()});this.recentlyTerminal.size>h$;){let r=this.recentlyTerminal.keys().next().value;if(r===void 0)break;this.recentlyTerminal.delete(r)}}broadcastPromptAmended(e){let t=this.findUserEntry(e.newMessageId);if(!t)return;let r={sessionId:this.sessionId,cancelledMessageId:e.cancelledMessageId,newMessageId:e.newMessageId,prompt:t.prompt,originator:t.originator,amendedAt:Date.now()};this.broadcastQueueNotification("hydra-acp/prompt/amended",r)}findUserEntry(e){if(this.currentEntry?.messageId===e&&this.currentEntry.kind==="user")return this.currentEntry;let t=this.promptQueue.find(r=>r.messageId===e&&r.kind==="user");return t?.kind==="user"?t:void 0}visibleQueueDepth(){let e=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled?1:0;for(let t of this.promptQueue)t.kind==="user"&&!t.cancelled&&(e+=1);return e}broadcastQueueAdded(e,t){let r=this.visibleQueueDepth(),s=t?.position??Math.max(0,r-1),o={sessionId:this.sessionId,messageId:e.messageId,originator:e.originator,prompt:e.prompt,position:s,queueDepth:r,enqueuedAt:e.enqueuedAt};t?.amending!==void 0&&(o._meta={"hydra-acp":{amending:t.amending}}),this.broadcastQueueNotification("hydra-acp/prompt_queue/added",o)}broadcastQueueUpdated(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/updated",{sessionId:this.sessionId,messageId:e,prompt:t})}broadcastQueueRemoved(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/removed",{sessionId:this.sessionId,messageId:e,reason:t})}broadcastQueueNotification(e,t){for(let r of this.clients.values())r.connection.notify(e,t).catch(()=>{})}queueSnapshot(){let e=[],t=0;this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled&&e.push({messageId:this.currentEntry.messageId,originator:this.currentEntry.originator,prompt:this.currentEntry.prompt,position:t++,enqueuedAt:this.currentEntry.enqueuedAt});for(let r of this.promptQueue)r.kind!=="user"||r.cancelled||e.push({messageId:r.messageId,originator:r.originator,prompt:r.prompt,position:t++,enqueuedAt:r.enqueuedAt});return e}async flushPersistWrites(){await this.queueWriteChain.catch(()=>{})}replayPersistedQueue(e){for(let t of e){let r={clientId:`hydra-resurrected_${t.messageId}`};t.originator.clientInfo.name!==void 0&&(r.name=t.originator.clientInfo.name),t.originator.clientInfo.version!==void 0&&(r.version=t.originator.clientInfo.version);let s={kind:"user",messageId:t.messageId,originator:r,clientId:r.clientId,prompt:t.prompt,enqueuedAt:t.enqueuedAt,cancelled:!1,resolve:()=>{},reject:()=>{}};this.promptQueue.push(s),this.broadcastQueueAdded(s)}this.drainQueue()}cancelQueuedPrompt(e){if(this.currentEntry?.messageId===e)return{cancelled:!1,reason:"already_running"};let t=this.promptQueue.findIndex(s=>s.messageId===e);if(t<0)return{cancelled:!1,reason:"not_found"};let r=this.promptQueue[t];return r.cancelled=!0,this.promptQueue.splice(t,1),r.kind==="user"&&(this.broadcastQueueRemoved(e,"cancelled"),this.persistRewrite()),this.amendInProgress?.newMessageId===e&&(this.amendInProgress=void 0),r.resolve({stopReason:"cancelled"}),{cancelled:!0,reason:"ok"}}updateQueuedPrompt(e,t){if(this.currentEntry?.messageId===e)return{updated:!1,reason:"already_running"};let r=this.promptQueue.find(s=>s.messageId===e);return!r||r.kind!=="user"?{updated:!1,reason:"not_found"}:(r.prompt=t,this.broadcastQueueUpdated(e,t),this.persistRewrite(),{updated:!0,reason:"ok"})}amendPrompt(e,t){let r=this.clients.get(e);if(!r)throw Gn(new Error("client not attached"),V.SessionNotFound);let{targetMessageId:s,prompt:o,replaceQueue:i,onTargetCompleted:a}=t;if(this.currentEntry?.messageId===s&&this.currentEntry.kind==="user"&&!this.currentEntry.cancelled&&this.amendInProgress===void 0)return this.amendOnHead(r,o,s,i);let d=this.promptQueue.find(l=>l.messageId===s&&l.kind==="user");if(d&&d.kind==="user"&&!d.cancelled)return d.prompt=o,this.broadcastQueueUpdated(s,o),this.persistRewrite(),{amended:!0,reason:"ok",messageId:s};let c=this.recentlyTerminal.get(s);return c?c.stopReason==="cancelled"?{amended:!1,reason:"target_cancelled"}:a==="send_anyway"?{amended:!1,reason:"target_completed",messageId:this.enqueueAmendmentAsFollowUp(r,o)}:{amended:!1,reason:"target_completed"}:{amended:!1,reason:"target_not_found"}}amendOnHead(e,t,r,s){let o=cs(),i={clientId:e.clientId};if(e.clientInfo?.name&&(i.name=e.clientInfo.name),e.clientInfo?.version&&(i.version=e.clientInfo.version),s){let d=[];for(let c of this.promptQueue){if(c.kind==="user"&&!c.cancelled){c.cancelled=!0,this.broadcastQueueRemoved(c.messageId,"cancelled"),c.resolve({stopReason:"cancelled"});continue}d.push(c)}this.promptQueue=d}let a={kind:"user",messageId:o,originator:i,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,wasAmend:!0,resolve:()=>{},reject:()=>{}};return this.promptQueue.unshift(a),this.persistRewrite(),this.broadcastQueueAdded(a,{amending:r,position:1}),this.amendInProgress={cancelledMessageId:r,newMessageId:o},this.cancelExtensionDispatch(r,"amended"),this.agent.connection.notify("session/cancel",{sessionId:this.upstreamSessionId}).catch(()=>{}),{amended:!0,reason:"ok",messageId:o}}enqueueAmendmentAsFollowUp(e,t){let r=cs(),s={clientId:e.clientId};e.clientInfo?.name&&(s.name=e.clientInfo.name),e.clientInfo?.version&&(s.version=e.clientInfo.version);let o={kind:"user",messageId:r,originator:s,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,resolve:()=>{},reject:()=>{}};return this.promptQueue.push(o),this.persistRewrite(),this.broadcastQueueAdded(o),this.drainQueue(),r}async cancel(e){if(!this.clients.get(e))throw Gn(new Error("client not attached"),V.SessionNotFound);this.lastCancelAt=Date.now(),this.currentEntry?.kind==="user"&&this.currentEntry.messageId!==void 0&&this.cancelExtensionDispatch(this.currentEntry.messageId,"cancelled"),this.closeUnsolicitedTurn("cancelled"),this.agentTurnInFlight||this.closeOpenToolCalls("cancelled"),await this.forwardRequest("session/cancel",{sessionId:this.sessionId},new Set,0,"notification")}addTransformer(e){let t=this.transformChain.findIndex(r=>r.name===e.name);t>=0?this.transformChain[t]=e:this.transformChain.push(e),e.intercepts.has("lifecycle:session.opened")&&e.connection.notify("hydra-acp/transformer/session_event",{event:"session.opened",sessionId:this.sessionId}).catch(()=>{})}async forwardRequest(e,t,r=new Set,s=0,o="request"){let i=this.rewriteForAgent(t);for(let a=s;a<this.transformChain.length;a++){let d=this.transformChain[a];if(r.has(d.name))continue;let c=`request:${e}`;if(!d.intercepts.has(c))continue;let l=`t_${wg()}`,u;try{u=await d.connection.request("hydra-acp/transformer/message",{token:l,phase:"request",method:e,direction:"client\u2192agent",sessionId:this.sessionId,envelope:i})}catch(p){this.logger?.warn(`transformer ${d.name} error on ${c}: ${p.message}`);continue}let f=u?.action??"continue";if(f==="stop")return o==="notification"?void 0:u?.payload??vg(e);if(f==="continue"){u?.payload&&typeof u.payload=="object"&&(i=u.payload),r.add(d.name);continue}if(f==="processing"){let p=a,h=i,m=new Set(r);return new Promise(y=>{let w=setTimeout(()=>{this.pendingClaims.delete(l)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:l,transformerName:d.name}),this.forwardRequest(e,h,new Set([...m,d.name]),p+1,o).then(y).catch(()=>y(o==="notification"?void 0:vg(e))))},Uu);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(l,{resolve:y,timer:w,transformerName:d.name,method:e,envelope:h,chainIdx:p,originatedBy:m,side:"request",tailKind:o})})}r.add(d.name)}if(o==="notification"){await this.agent.connection.notify(e,i);return}return this.agent.connection.request(e,i)}async forwardModelChange(e,t){let r=await xo({request:(s,o)=>this.forwardRequest(s,o),sessionId:this.sessionId,modelId:e,verb:this.modelVerb,extraParams:t,logger:this.logger});return this.modelVerb=r.verb,this.modelVerbConfirmed=!0,r.result}noteModelVerbHint(e,t){e===void 0||this.modelVerbConfirmed||e===this.modelVerb||(this.logger?.info(`model verb for agent ${this.agentId} inferred as ${e} from ${t} (was ${this.modelVerb})`),this.modelVerb=e)}resetModelVerb(e){this.modelVerb=e??as,this.modelVerbConfirmed=!1}async runAgentRequestChain(e,t,r=new Set,s=0){let o=t,i=`request:${e}`;for(let a=s;a<this.transformChain.length;a++){let d=this.transformChain[a];if(r.has(d.name)||!d.intercepts.has(i))continue;let c=`t_${wg()}`,l;try{l=await d.connection.request("hydra-acp/transformer/message",{token:c,phase:"request",method:e,direction:"agent\u2192client",sessionId:this.sessionId,envelope:o})}catch(f){this.logger?.warn(`transformer ${d.name} error on ${i}: ${f.message}`);continue}let u=l?.action??"continue";if(u==="stop")return{shortCircuit:!0,payload:l?.payload??O$(e)};if(u==="continue"){l?.payload&&typeof l.payload=="object"&&(o=l.payload),r.add(d.name);continue}if(u==="processing"){let f=a,p=o,h=new Set(r),m=e;return new Promise(y=>{let w=setTimeout(()=>{this.pendingClaims.delete(c)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:c,transformerName:d.name}),this.runAgentRequestChain(m,p,new Set([...h,d.name]),f+1).then(y).catch(()=>y({shortCircuit:!1,envelope:p})))},Uu);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(c,{resolve:v=>y({shortCircuit:!0,payload:v}),timer:w,transformerName:d.name,method:m,envelope:p,chainIdx:f,originatedBy:h,side:"agent-request"})})}r.add(d.name)}return{shortCircuit:!1,envelope:o}}dischargeClaim(e,t){let r=this.pendingClaims.get(e);return r?(clearTimeout(r.timer),this.pendingClaims.delete(e),r.resolve(t),!0):!1}keepAliveClaim(e,t){let r=this.pendingClaims.get(e);if(!r)return!1;clearTimeout(r.timer);let s=typeof t=="number"&&t>0?Math.min(t*1.5,1800*1e3):Uu,o=setTimeout(()=>{if(this.pendingClaims.delete(e))if(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:e,transformerName:r.transformerName}),r.side==="response")this.runResponseChain(r.envelope,new Set([...r.originatedBy,r.transformerName]),r.chainIdx+1).then(()=>r.resolve(void 0)).catch(()=>r.resolve(void 0));else if(r.side==="agent-request")this.runAgentRequestChain(r.method,r.envelope,new Set([...r.originatedBy,r.transformerName]),r.chainIdx+1).then(r.resolve).catch(()=>r.resolve({shortCircuit:!1,envelope:r.envelope}));else{let i=r.tailKind??"request";this.forwardRequest(r.method,r.envelope,new Set([...r.originatedBy,r.transformerName]),r.chainIdx+1,i).then(r.resolve).catch(()=>r.resolve(i==="notification"?void 0:vg(r.method)))}},s);return typeof o.unref=="function"&&o.unref(),r.timer=o,!0}async emitToChain(e,t,r){let s=this.transformChain.findIndex(a=>a.name===e),o=s>=0?s+1:0,i=new Set([e]);if(t==="session/update"){await this.runResponseChain(r,i,o);return}return this.forwardRequest(t,r,i,o)}async emitToQueue(e,t){let r=this.transformChain.findIndex(c=>c.name===e),s=r>=0?r+1:0,o=(t??{}).prompt??[],i=cs(),a=`transformer:${e}`,d={clientId:a,name:e};return new Promise((c,l)=>{let u={kind:"user",messageId:i,originator:d,clientId:a,prompt:o,enqueuedAt:Date.now(),cancelled:!1,emitterName:e,chainStartIdx:s,resolve:c,reject:l},f=this.insertEntryAt(u,"tail");this.persistRewrite(),this.broadcastQueueAdded(u,{position:f}),this.drainQueue()})}rewriteForAgent(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(t.sessionId===this.sessionId)return{...t,sessionId:this.upstreamSessionId}}return e}async close(e={}){if(e.deleteRecord&&(this.deleteRecordIntent=!0),!this.closed)return this.closeInFlight?this.closeInFlight:(this.closing=!0,this.closeInFlight=this.doClose(e),this.closeInFlight)}async doClose(e){let t=this.turnStartedAt!==void 0;this.logger?.info(`session ${this.sessionId} closing deleteRecord=${e.deleteRecord??!1} by=${e.by??"unknown"} midTurn=${t} unsolicitedTurn=${this.unsolicitedTurn!==void 0} queued=${this.promptQueue.length} awaitingPermission=${this.hasPermissionFlag}`),t&&this.logger?.warn(`session ${this.sessionId} closed mid-turn by=${e.by??"unknown"}; the in-flight turn will not settle and the agent is being killed`),this.cancelIdleTimer();for(let r of this.pendingClaims.values())clearTimeout(r.timer);this.pendingClaims.clear(),await this.agent.kill().catch(()=>{}),this.markClosed({deleteRecord:e.deleteRecord??!1})}onClose(e){return this.closeHandlers.push(e),()=>{let t=this.closeHandlers.indexOf(e);t>=0&&this.closeHandlers.splice(t,1)}}onTitleChange(e){this.titleHandlers.push(e)}retitle(e){return this.runTitleCommand(e)}retitleFromAgent(){return this.runTitleCommand("")}setTitle(e){let t=e.trim();if(!(!t||t===this.title)){this.title=t,this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",title:t,updatedAt:new Date().toISOString()}});for(let r of this.titleHandlers)try{r(t)}catch{}}}maybeSeedTitleFromPrompt(e){if(this.firstPromptSeeded||En((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let s=Ya((e??{}).prompt),o=Sg(s,200);o&&(o.startsWith("/")||(this._firstPromptSeeded=!0,this.setTitle(o)))}maybeApplyAgentModel(e){let r=(e??{}).update??{};if(r.sessionUpdate!=="current_model_update")return!1;let s=Qa(r.availableModels);s.length>0&&this.setAgentAdvertisedModels(s);let o=typeof r.currentModel=="string"?r.currentModel:typeof r.model=="string"?r.model:void 0;if(o===void 0)return!0;let i=o.trim();if(!i||i===this.currentModel)return!0;this.logger?.info(`live current_model_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(i)}`),this.currentModel=i;for(let a of this.modelHandlers)try{a(i)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentConfigOption(e){let r=(e??{}).update??{};if(r.sessionUpdate!=="config_option_update")return!1;let s=r.configOptions;if(!Array.isArray(s))return!0;for(let o of s){if(!o||typeof o!="object")continue;let i=o;if(i.id==="model"){let a=Qa(i.options);a.length>0&&this.setAgentAdvertisedModels(a);let d=i.currentValue;if(typeof d=="string"){let c=d.trim();c&&c!==this.currentModel&&(this.logger?.info(`live config_option_update(model): sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(c)}`),this.applyModelChange(c))}}else if(i.id==="mode"){let a=Tc(i.options);a.length>0&&this.setAgentAdvertisedModes(a);let d=i.currentValue;if(typeof d=="string"){let c=d.trim();c&&c!==this.currentMode&&(this.logger?.info(`live config_option_update(mode): sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(c)}`),this.applyModeChange(c))}}else if(typeof i.id=="string"&&i.id.trim()){let a=i.id.trim(),d=Qa(i.options);if(d.length>0){let c=Tc(i.options),l=c.length>0?c.map(y=>({value:y.id,name:y.name??y.id})):d.map(y=>({value:y.modelId,name:y.name??y.modelId})),u=i.name,f=typeof u=="string"&&u.trim()?u.trim():a,p=i.currentValue,h=typeof p=="string"&&p.trim()?p.trim():l[0]?.value??"",m=this.agentAdvertisedConfigOptions.findIndex(y=>y.id===a);if(m>=0){let y={...this.agentAdvertisedConfigOptions[m]};y.options=l,typeof p=="string"&&p.trim()&&(y.currentValue=p.trim()),this.agentAdvertisedConfigOptions[m]=y}else this.agentAdvertisedConfigOptions.push({id:a,name:f,category:"other",type:"select",currentValue:h,options:l})}}}return!0}maybeApplyAgentMode(e){let r=(e??{}).update??{};if(r.sessionUpdate!=="current_mode_update")return!1;let s=typeof r.currentModeId=="string"?r.currentModeId:typeof r.currentMode=="string"?r.currentMode:typeof r.mode=="string"?r.mode:void 0;if(s===void 0)return!0;let o=s.trim();if(!o||o===this.currentMode)return!0;this.logger?.info(`current_mode_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(o)}`),this.currentMode=o;for(let i of this.modeHandlers)try{i(o)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentUsage(e){let r=(e??{}).update??{};if(r.sessionUpdate!=="usage_update")return!1;let s={...this._currentUsage??{}},o=!1;if(typeof r.used=="number"&&s.used!==r.used&&(s.used=r.used,o=!0),typeof r.size=="number"&&s.size!==r.size&&(s.size=r.size,o=!0),r.cost&&typeof r.cost=="object"){let a=r.cost;typeof a.amount=="number"&&(this.reconcileCostLedger(a.amount)&&(o=!0),s.costAmount!==a.amount&&(s.costAmount=a.amount,o=!0)),typeof a.currency=="string"&&s.costCurrency!==a.currency&&(s.costCurrency=a.currency,o=!0)}if(!o)return!0;this._currentUsage=s;let i=this.persistableUsage??s;for(let a of this.usageHandlers)try{a(i)}catch{}return!0}armCostLedgerProbe(){let e=this._currentUsage?.costAmount;typeof e=="number"&&e>0&&(this.costLedgerProbe=e)}reconcileCostLedger(e){let t=this.costLedgerProbe;return t===void 0||(this.costLedgerProbe=void 0,e>=t-1e-6)?!1:(this.cumulativeCost+=t,!0)}notifyAgentChange(e,t,r){let s=this.retiringGenerationCost;this.retiringGenerationCost=void 0;for(let o of this.agentChangeHandlers)try{o({agentId:this.agentId,upstreamSessionId:this.upstreamSessionId,...s!==void 0?{retiredCost:s}:{},...t!==void 0?{reason:t}:{},...r!==void 0?{runId:r}:{}})}catch(i){this.logger?.warn(`${e}: agentChange handler failed: ${i.message}`)}}accumulateAndResetCost(){let e=this._currentUsage?.costAmount;e&&(this.cumulativeCost+=e,this.retiringGenerationCost=e);let t={used:0,cumulativeCost:this.cumulativeCost,...typeof this._currentUsage?.size=="number"?{size:this._currentUsage.size}:{},...this._currentUsage?.costCurrency?{costCurrency:this._currentUsage.costCurrency}:{}};this._currentUsage=t;for(let r of this.usageHandlers)try{r(t)}catch{}this.broadcastCurrentUsage()}broadcastCurrentUsage(){let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let r={};typeof e.costAmount=="number"&&(r.amount=e.costAmount),typeof e.costCurrency=="string"&&(r.currency=e.costCurrency),t.cost=r}this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:t})}injectCumulativeCost(e){if(!this.cumulativeCost||!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let r=t.update;if(r.sessionUpdate!=="usage_update"||!r.cost||typeof r.cost!="object")return e;let s=r.cost;return typeof s.amount!="number"?e:{...t,update:{...r,cost:{...s,amount:this.cumulativeCost+s.amount}}}}get totalUsage(){return this.currentUsage}setAgentAdvertisedCommands(e){if(x$(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(I$(this.agentAdvertisedModes,e)){this.broadcastAvailableModes();return}this.agentAdvertisedModes=e;for(let t of this.agentModesHandlers)try{t(e)}catch{}this.broadcastAvailableModes()}setAgentAdvertisedModels(e){if(this.logger?.info(`setAgentAdvertisedModels: sessionId=${this.sessionId} currentModel=${JSON.stringify(this.currentModel)} newList=[${e.map(t=>t.modelId).join(",")}]`),C$(this.agentAdvertisedModels,e)){this.broadcastAvailableModels();return}this.agentAdvertisedModels=e;for(let t of this.agentModelsHandlers)try{t(e)}catch{}this.broadcastAvailableModels()}onAgentCommandsChange(e){this.agentCommandsHandlers.push(e)}onAgentModesChange(e){this.agentModesHandlers.push(e)}onAgentModelsChange(e){this.agentModelsHandlers.push(e)}onModelChange(e){this.modelHandlers.push(e)}onModeChange(e){this.modeHandlers.push(e)}onInteractiveChange(e){this.interactiveHandlers.push(e)}onPriorityChange(e){this.priorityHandlers.push(e)}setPriority(e){let t=e===void 0||e<=0?void 0:Math.floor(e);if(t!==this._priority){this._priority=t,this.updatedAt=Date.now();for(let r of this.priorityHandlers)try{r(t)}catch{}}}applyModelChange(e){let t=e.trim();if(t){this.modelChangeInFlight=!0;try{if(t!==this.currentModel){this.logger?.info(`applyModelChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(t)}`),this.currentModel=t;for(let s of this.modelHandlers)try{s(t)}catch{}}let r={sessionUpdate:"current_model_update",currentModel:t};this.agentAdvertisedModels.length>0&&(r.availableModels=[...this.agentAdvertisedModels]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:r}),this.broadcastConfigOptions()}finally{this.modelChangeInFlight=!1}}}applyModeChange(e){let t=e.trim();if(t){this.modeChangeInFlight=!0;try{if(t!==this.currentMode){this.logger?.info(`applyModeChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(t)}`),this.currentMode=t;for(let s of this.modeHandlers)try{s(t)}catch{}}let r={sessionUpdate:"current_mode_update",currentModeId:t};this.agentAdvertisedModes.length>0&&(r.availableModes=[...this.agentAdvertisedModes]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:r}),this.broadcastConfigOptions()}finally{this.modeChangeInFlight=!1}}}buildConfigOptions(){let e=[];if(this.agentAdvertisedModels.length>0){let s=this.agentAdvertisedModels.map(i=>({value:i.modelId,name:i.name??i.modelId,...i.description!==void 0?{description:i.description}:{}})),o=this.currentModel&&s.some(i=>i.value===this.currentModel)?this.currentModel:s[0].value;e.push({id:"model",name:"Model",category:"model",type:"select",currentValue:o,options:s})}if(this.agentAdvertisedModes.length>0){let s=this.agentAdvertisedModes.map(i=>({value:i.id,name:i.name??i.id,...i.description!==void 0?{description:i.description}:{}})),o=this.currentMode&&s.some(i=>i.value===this.currentMode)?this.currentMode:s[0].value;e.push({id:"mode",name:"Session Mode",category:"mode",type:"select",currentValue:o,options:s})}let r=(this.availableAgentsFn?.()??[]).map(s=>({value:s.id,name:s.name??s.id,...s.description!==void 0?{description:s.description}:{}}));return r.some(s=>s.value===this.agentId)||r.unshift({value:this.agentId,name:this.agentId}),e.push({id:"agent",name:"Agent",category:"_hydra_agent",type:"select",currentValue:this.agentId,options:r}),e.push(...this.agentAdvertisedConfigOptions),e}broadcastConfigOptions(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"config_option_update",configOptions:this.buildConfigOptions()}})}mergeAgentOptionIntoEnvelope(e){if(!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let r=t.update,s=Array.isArray(r.configOptions)?[...r.configOptions]:[];if(s.some(a=>a&&typeof a=="object"&&a.id==="agent"))return e;let i=this.buildConfigOptions().find(a=>a.id==="agent");return i?{...t,update:{...r,configOptions:[...s,i]}}:e}onUsageChange(e){this.usageHandlers.push(e)}mergedAvailableCommands(){let e=this.daemonTopLevelCommands(),t=this.aliasableBareVerbs();for(let r of Ga){if(t.get(r.verb)!=="__hydra__")continue;let s=r.argsHint?`${r.verb} ${r.argsHint}`:r.verb;e.push({name:s,description:`Alias for '/hydra ${r.verb}': ${r.description}`})}if(this.extensionCommands)for(let{name:r,command:s}of this.extensionCommands.list()){let o=s.verb?`hydra ${r} ${s.verb}`:`hydra ${r}`,a={name:s.argsHint?`${o} ${s.argsHint}`:o};s.description&&(a.description=s.description),e.push(a);let d=r.startsWith("hydra-acp-")?r.slice(10):r;if(r.startsWith("hydra-acp-")&&d.length>0){let c=s.verb?`hydra ${d} ${s.verb}`:`hydra ${d}`,u={name:s.argsHint?`${c} ${s.argsHint}`:c};s.description&&(u.description=s.description),e.push(u)}if(d.length>0&&t.get(d)===r){let c=s.verb?`${d} ${s.verb}`:d,u={name:s.argsHint?`${c} ${s.argsHint}`:c};s.description&&(u.description=s.description),e.push(u)}}return e.push(...this.agentAdvertisedCommands),e}daemonTopLevelCommands(){return[{name:"hydra",description:"Hydra session command (kill, restart, title, agent <agent>)"},{name:"model",description:"Switch model; omit arg to list available models"},{name:"mode",description:"Switch mode; omit arg to list available modes"},{name:"sessions",description:"List all sessions"},{name:"help",description:"Show available commands"}]}aliasableBareVerbs(){let e=new Set,t=i=>i.split(/\s+/)[0]??"";for(let i of this.daemonTopLevelCommands()){let a=t(i.name);a&&e.add(a)}for(let i of this.agentAdvertisedCommands){let a=t(i.name),d=a.startsWith("/")?a.slice(1):a;d&&e.add(d)}let r=new Map;for(let i of Ga)e.has(i.verb)||r.set(i.verb,"__hydra__");if(!this.extensionCommands)return r;let s=new Map,o=new Set;for(let{name:i}of this.extensionCommands.list()){if(o.has(i))continue;o.add(i);let a=i.startsWith("hydra-acp-")?i.slice(10):i;if(!a||e.has(a)||r.has(a))continue;let d=s.get(a);d===void 0?s.set(a,i):d!==i&&s.set(a,"__conflict__")}for(let[i,a]of s)a!=="__conflict__"&&r.set(i,a);return r}agentOnlyAdvertisedCommands(){return[...this.agentAdvertisedCommands]}agentKnowsSlashCommand(e){let t=s=>s.startsWith("/")?s.slice(1):s,r=t(e);if(!r)return!1;for(let s of this.agentAdvertisedCommands)if(t(s.name.split(/\s+/)[0]??"")===r)return!0;return!1}availableModes(){return[...this.agentAdvertisedModes]}availableModels(){return[...this.agentAdvertisedModels]}maybeApplyAgentSessionInfo(e){let r=(e??{}).update??{};if(r.sessionUpdate!=="session_info_update"||typeof r.title!="string")return;let s=r.title.trim();if(!(!s||s===this.title)){this.title=s,this._firstPromptSeeded=!0;for(let o of this.titleHandlers)try{o(s)}catch{}}}async handleSlashCommand(e,t){let s=e.slice(6).trim().match(/^(\S+)(?:\s+([\s\S]*))?$/),o=s?.[1]??"",i=(s?.[2]??"").trim();if(o==="")return{stopReason:"end_turn"};let a=t!==void 0;if(Ga.some(u=>u.verb===o))switch(o){case"title":return a?this.runTitleCommandInline(i):this.runTitleCommand(i);case"agent":return this.runAgentCommandInline(i);case"config":return this.handleConfigCommand(`/config ${i}`);case"kill":return this.runKillCommand();case"workspace":return this.runWorkspaceCommand(i);case"restart":return a?this.runRestartCommandInline():this.runRestartCommand();case"compact":return a?this.runCompactCommandInline(i):this.runCompactCommand(i);case"uncompact":return a?this.runUncompactCommandInline():this.runUncompactCommand();case"fork":return a?this.runForkCommandInline(i,t):this.runForkCommand(i);default:{let u=new Error(`no dispatcher for /hydra verb ${o}`);throw u.code=V.InternalError,u}}if(this.extensionCommands?.has(o))return a?this.runExtensionCommandInline(o,i,t):this.runExtensionCommand(o,i);let d=`hydra-acp-${o}`;if(this.extensionCommands?.has(d))return a?this.runExtensionCommandInline(d,i,t):this.runExtensionCommand(d,i);let c=Ga.map(u=>u.verb);if(this.extensionCommands){let u=new Set;for(let{name:f}of this.extensionCommands.list())u.has(f)||(c.push(f),u.add(f))}let l=new Error(`unknown /hydra verb: ${o} (known: ${c.join(", ")})`);throw l.code=V.InvalidParams,l}runExtensionCommand(e,t){return this.enqueuePrompt(`extension:${e}`,()=>this.runExtensionCommandInline(e,t,void 0))}async runExtensionCommandInline(e,t,r){let s=this.extensionCommands?.get(e);if(!s)return this.emitExtensionReply(`extension "${e}" is no longer connected`);let o=t.match(/^(\S+)(?:\s+([\s\S]*))?$/),i=o?.[1]??"",a=(o?.[2]??"").trim();if(!s.commands.some(h=>h.verb===i)){let h=s.commands.map(m=>m.verb).join(", ");return this.emitExtensionReply(`/hydra ${e}${i?` ${i}`:""}: unknown verb (known: ${h||"(none)"})`)}let d={sessionId:this.sessionId,verb:i,args:a};r!==void 0&&(d.messageId=r);let c=()=>{},l=new Promise(h=>{c=h});r!==void 0&&this.inFlightExtensionDispatches.set(r,{extensionName:e,connection:s.connection,cancel:h=>c({stopReason:"cancelled",reason:h})});let u,f=!1;try{let h=s.connection.request("hydra-acp/commands/invoke",d),m=await Promise.race([h,l]);if(m&&typeof m=="object"&&m.stopReason==="cancelled"&&"reason"in m)return f=!0,this.logger?.info(`extension ${e} ${i} cancelled (cancelExtensionDispatch); abandoning in-flight commands/invoke`),{stopReason:"cancelled"};u=m}catch(h){return this.emitExtensionReply(`${e} ${i}: ${h.message}`)}finally{r!==void 0&&!f&&this.inFlightExtensionDispatches.delete(r)}let p=u&&typeof u=="object"&&typeof u.text=="string"?u.text:"";return p.length>0?this.emitExtensionReply(p):{stopReason:"end_turn"}}cancelExtensionDispatch(e,t){let r=this.inFlightExtensionDispatches.get(e);if(!r)return!1;this.inFlightExtensionDispatches.delete(e);try{r.connection.notify("hydra-acp/commands/cancel",{sessionId:this.sessionId,messageId:e,reason:t})}catch(s){this.logger?.warn(`notify commands/cancel to ${r.extensionName} failed: ${s.message}`)}return r.cancel(t),!0}emitExtensionReply(e){return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
|
|
42
|
+
`),this.workspacePreambleSent=!0}return s}async prompt(e,t,r){let s=this.clients.get(e);if(!s)throw Gn(new Error("client not attached"),V.SessionNotFound);if(this.closing)throw Gn(new Error("session is closing; new prompts cannot be accepted"),V.SessionClosing);let o=cs();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(En((t??{})._meta).ancillary===!0)&&this._interactive!==!0){this._interactive=!0;for(let a of this.interactiveHandlers)try{a(!0)}catch{}}return this.enqueueUserPrompt(s,t,o,r)}broadcastPromptReceived(e){this.closeUnsolicitedTurn("superseded",`prompt:${e.messageId}`);let t={clientId:e.originator.clientId};e.originator.name&&(t.name=e.originator.name),e.originator.version&&(t.version=e.originator.version),e.originator.fromSession&&(t.fromSession=e.originator.fromSession),e.originator.fromSessionTitle&&(t.fromSessionTitle=e.originator.fromSessionTitle),e.originator.fromLabel&&(t.fromLabel=e.originator.fromLabel),e.originator.depth!==void 0&&(t.depth=e.originator.depth),this.promptStartedAt=Date.now(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"prompt_received",messageId:e.messageId,prompt:e.prompt,sentBy:t}},e.clientId);let r=Ya(e.prompt);r.length>0&&this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"user_message_chunk",content:{type:"text",text:r},_meta:{"hydra-acp":{compatFor:"prompt_received"}}}},e.clientId)}recordCurrentUsageSnapshot(){if(this.historyStore===void 0)return;let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let s={};typeof e.costAmount=="number"&&(s.amount=e.costAmount),typeof e.costCurrency=="string"&&(s.currency=e.costCurrency),t.cost=s}if(Object.keys(t).length<=1)return;t._meta={"hydra-acp":{upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}};let r={sessionId:this.sessionId,update:t};this.historyStore.append(this.sessionId,{method:"session/update",params:r,recordedAt:Date.now()}).catch(()=>{})}broadcastTurnComplete(e,t,r,s){let o=t&&typeof t=="object"&&"stopReason"in t&&typeof t.stopReason=="string"?t.stopReason:void 0,i={sessionUpdate:"turn_complete",messageId:cs()};o!==void 0&&(i.stopReason=o);let a=En(t?._meta).salvaged;a!==void 0&&(i._meta={[kt]:{salvaged:a}}),this.supersededAutonomousTurn=void 0;let d=this.amendInProgress;d&&r!==void 0&&d.cancelledMessageId===r&&(i._meta={[kt]:{...a!==void 0?{salvaged:a}:{},amended:{cancelledMessageId:d.cancelledMessageId,newMessageId:d.newMessageId}}}),this.promptStartedAt=void 0,this.sawTurnComplete=!0,this.scheduleWorkspaceSnapshotHook?.(),r!==void 0&&o!==void 0&&this.recordTerminal(r,o),(o==="cancelled"||o==="error"||o==="refusal")&&this.closeOpenToolCalls(o),this.recordCurrentUsageSnapshot(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:i},s?void 0:e),d&&r!==void 0&&d.cancelledMessageId===r&&this.broadcastPromptAmended(d)}noteAgentActivity(e){if(!(this.closing||this.closed)){if(g$(e)){if(this.unsolicitedTurn!==void 0){this.closeUnsolicitedTurn("completed");return}this.salvageSupersededTerminal();return}bg("session/update",e)||(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||this.openUnsolicitedTurn()))}}noteBackgroundTaskArming(e){let t=e?.update;if(!t||typeof t!="object")return;let r=typeof t.toolCallId=="string"?t.toolCallId:void 0;if(r===void 0)return;let s=t.rawInput,o=S$(t._meta);this.rememberToolLabel(r,t,s,o),this.noteBackgroundTaskStopped(t,s,o);let i=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:v$(t.rawOutput);if(!(i!==void 0||s!==void 0&&s.run_in_background===!0))return;let d=this.toolLabels.get(r)?.label??"background task";this.lastBackgroundTask={toolCallId:r,label:d};let c=Date.now(),l=this.armedTasks.get(r),u=i??l?.taskId,f=k$(t.title,o,s)||l?.repeating===!0;this.armedTasks.set(r,{label:d,...u!==void 0?{taskId:u}:{},repeating:f,armedAt:l?.armedAt??c}),this.onArmedTasksChanged()}get armedBackgroundTasks(){return[...this.armedTasks.entries()].map(([e,t])=>({toolCallId:e,label:t.label,...t.taskId!==void 0?{taskId:t.taskId}:{}}))}get armedSince(){let e;for(let t of this.armedTasks.values())(e===void 0||t.armedAt<e)&&(e=t.armedAt);return e}onArmedTasksChanged(){let e=this.armedTasks.size,t=this.armedSince;e===this.lastArmedBroadcast?.count&&t===this.lastArmedBroadcast?.since||this.closed||(this.lastArmedBroadcast={count:e,since:t},this.broadcastQueueNotification("hydra-acp/session/armed_tasks_updated",{sessionId:this.sessionId,count:e,...t!==void 0?{since:t}:{},tasks:this.armedBackgroundTasks}))}async retireAgent(e,t){return await e.kill().catch(()=>{}),this.discardArmedTasks(t)}discardArmedTasks(e){if(this.armedTasks.size===0)return[];let t=[...this.armedTasks.values()].map(r=>r.label);return this.armedTasks.clear(),this.logger?.info(`session ${this.sessionId} discarded ${t.length} armed task(s) on ${e}: ${t.join(", ")}`),this.onArmedTasksChanged(),t}noteBackgroundTaskStopped(e,t,r){if(!(r?.toolName==="TaskStop"||e.title==="TaskStop"))return;let o=t?.task_id;if(typeof o!="string"||o.length===0)return;let i=!1;for(let[a,d]of this.armedTasks)d.taskId===o&&(this.armedTasks.delete(a),i=!0);i&&this.onArmedTasksChanged()}rememberToolLabel(e,t,r,s){let o=r!==void 0&&typeof r.description=="string"&&r.description?r.description:void 0;if(o!==void 0)this.toolLabels.set(e,{label:o.slice(0,BS),fromDescription:!0});else if(this.toolLabels.get(e)?.fromDescription!==!0){let i=typeof t.title=="string"&&t.title?t.title:typeof s?.toolName=="string"&&s.toolName?s.toolName:void 0;i!==void 0&&this.toolLabels.set(e,{label:i.slice(0,BS),fromDescription:!1})}for(;this.toolLabels.size>y$;){let i=this.toolLabels.keys().next().value;if(i===void 0)break;this.toolLabels.delete(i)}}openUnsolicitedTurn(){let e=Date.now(),t=this.lastBackgroundTask,r=!1;for(let[i,a]of this.armedTasks)a.repeating||(this.armedTasks.delete(i),r=!0);r&&this.onArmedTasksChanged();let s={messageId:cs(),startedAt:e,cause:t};this.unsolicitedTurn=s,this.promptStartedAt=e,this.logger?.info(`session ${this.sessionId} agent resumed with no prompt in flight`+(t?` (after ${t.label})`:""));let o={unsolicited:!0};t&&(o.cause=t),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"turn_started",messageId:s.messageId,_meta:{"hydra-acp":o}}})}async holdForUnsolicitedTurn(e){if(this.unsolicitedTurn===void 0){this.logger?.info(`session ${this.sessionId} queue hold skipped for ${e.messageId} (no unsolicited turn open)`);return}let t=Date.now(),r=this.unsolicitedTurn.cause;this.logger?.info(`session ${this.sessionId} holding ${e.messageId} behind unsolicited turn ${this.unsolicitedTurn.messageId}`+(r?` cause=${JSON.stringify(r.label)}`:"")),this.broadcastQueueNotification("hydra-acp/prompt_queue/held",{sessionId:this.sessionId,messageId:e.messageId,reason:"agent_resumed",...r?{cause:r}:{}});let s="turn_ended";for(;;){if(this.closing||this.closed){s="closing";break}if(e.cancelled){s="cancelled";break}if(this.unsolicitedTurn===void 0){s="turn_ended";break}await new Promise(i=>{let a=setTimeout(i,w$);typeof a.unref=="function"&&a.unref()})}let o=Date.now()-t;this.logger?.info(`session ${this.sessionId} released ${e.messageId} reason=${s} heldMs=${o}`),this.broadcastQueueNotification("hydra-acp/prompt_queue/released",{sessionId:this.sessionId,messageId:e.messageId,reason:s,heldMs:o})}closeUnsolicitedTurn(e,t){let r=this.unsolicitedTurn;if(r===void 0)return;let s=Date.now()-r.startedAt;this.unsolicitedTurn=void 0,this.promptStartedAt=void 0,this.logger?.info(`session ${this.sessionId} unsolicited turn ${r.messageId} closed reason=${e} durationMs=${s}`+(t?` by=${t}`:"")+(r.cause?` cause=${JSON.stringify(r.cause.label)}`:"")),e==="superseded"&&(this.supersededAutonomousTurn={turnMessageId:r.messageId,cause:r.cause,supersededAt:Date.now()}),this.recordCurrentUsageSnapshot(),!this.closed&&(e==="cancelled"&&this.closeOpenToolCalls("cancelled"),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"turn_ended",messageId:cs(),startedMessageId:r.messageId,durationMs:s,_meta:{"hydra-acp":{unsolicited:!0,reason:e}}}}))}salvageSupersededTerminal(){let e=this.supersededAutonomousTurn;if(e===void 0)return;this.supersededAutonomousTurn=void 0;let t=this.autonomousSalvage;t!==void 0&&(this.autonomousSalvage=void 0,this.logger?.warn(`session ${this.sessionId} salvaged session/prompt from autonomous terminal (superseded turn ${e.turnMessageId}, ${Date.now()-e.supersededAt}ms earlier)`+(e.cause?` cause=${JSON.stringify(e.cause.label)}`:"")),t({stopReason:"end_turn",_meta:{[kt]:{salvaged:{reason:"autonomous_terminal",supersededMessageId:e.turnMessageId}}}}))}async awaitPromptResponse(e){if(this.supersededAutonomousTurn===void 0)return e;try{return await new Promise((t,r)=>{this.autonomousSalvage=t,e.then(t,r)})}finally{this.autonomousSalvage=void 0}}recordTerminal(e,t){for(this.recentlyTerminal.set(e,{stopReason:t,terminatedAt:Date.now()});this.recentlyTerminal.size>h$;){let r=this.recentlyTerminal.keys().next().value;if(r===void 0)break;this.recentlyTerminal.delete(r)}}broadcastPromptAmended(e){let t=this.findUserEntry(e.newMessageId);if(!t)return;let r={sessionId:this.sessionId,cancelledMessageId:e.cancelledMessageId,newMessageId:e.newMessageId,prompt:t.prompt,originator:t.originator,amendedAt:Date.now()};this.broadcastQueueNotification("hydra-acp/prompt/amended",r)}findUserEntry(e){if(this.currentEntry?.messageId===e&&this.currentEntry.kind==="user")return this.currentEntry;let t=this.promptQueue.find(r=>r.messageId===e&&r.kind==="user");return t?.kind==="user"?t:void 0}visibleQueueDepth(){let e=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled?1:0;for(let t of this.promptQueue)t.kind==="user"&&!t.cancelled&&(e+=1);return e}broadcastQueueAdded(e,t){let r=this.visibleQueueDepth(),s=t?.position??Math.max(0,r-1),o={sessionId:this.sessionId,messageId:e.messageId,originator:e.originator,prompt:e.prompt,position:s,queueDepth:r,enqueuedAt:e.enqueuedAt};t?.amending!==void 0&&(o._meta={"hydra-acp":{amending:t.amending}}),this.broadcastQueueNotification("hydra-acp/prompt_queue/added",o)}broadcastQueueUpdated(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/updated",{sessionId:this.sessionId,messageId:e,prompt:t})}broadcastQueueRemoved(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/removed",{sessionId:this.sessionId,messageId:e,reason:t})}broadcastQueueNotification(e,t){for(let r of this.clients.values())r.connection.notify(e,t).catch(()=>{})}queueSnapshot(){let e=[],t=0;this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled&&e.push({messageId:this.currentEntry.messageId,originator:this.currentEntry.originator,prompt:this.currentEntry.prompt,position:t++,enqueuedAt:this.currentEntry.enqueuedAt});for(let r of this.promptQueue)r.kind!=="user"||r.cancelled||e.push({messageId:r.messageId,originator:r.originator,prompt:r.prompt,position:t++,enqueuedAt:r.enqueuedAt});return e}async flushPersistWrites(){await this.queueWriteChain.catch(()=>{})}replayPersistedQueue(e){for(let t of e){let r={clientId:`hydra-resurrected_${t.messageId}`};t.originator.clientInfo.name!==void 0&&(r.name=t.originator.clientInfo.name),t.originator.clientInfo.version!==void 0&&(r.version=t.originator.clientInfo.version);let s={kind:"user",messageId:t.messageId,originator:r,clientId:r.clientId,prompt:t.prompt,enqueuedAt:t.enqueuedAt,cancelled:!1,resolve:()=>{},reject:()=>{}};this.promptQueue.push(s),this.broadcastQueueAdded(s)}this.drainQueue()}cancelQueuedPrompt(e){if(this.currentEntry?.messageId===e)return{cancelled:!1,reason:"already_running"};let t=this.promptQueue.findIndex(s=>s.messageId===e);if(t<0)return{cancelled:!1,reason:"not_found"};let r=this.promptQueue[t];return r.cancelled=!0,this.promptQueue.splice(t,1),r.kind==="user"&&(this.broadcastQueueRemoved(e,"cancelled"),this.persistRewrite()),this.amendInProgress?.newMessageId===e&&(this.amendInProgress=void 0),r.resolve({stopReason:"cancelled"}),{cancelled:!0,reason:"ok"}}updateQueuedPrompt(e,t){if(this.currentEntry?.messageId===e)return{updated:!1,reason:"already_running"};let r=this.promptQueue.find(s=>s.messageId===e);return!r||r.kind!=="user"?{updated:!1,reason:"not_found"}:(r.prompt=t,this.broadcastQueueUpdated(e,t),this.persistRewrite(),{updated:!0,reason:"ok"})}amendPrompt(e,t){let r=this.clients.get(e);if(!r)throw Gn(new Error("client not attached"),V.SessionNotFound);let{targetMessageId:s,prompt:o,replaceQueue:i,onTargetCompleted:a}=t;if(this.currentEntry?.messageId===s&&this.currentEntry.kind==="user"&&!this.currentEntry.cancelled&&this.amendInProgress===void 0)return this.amendOnHead(r,o,s,i);let d=this.promptQueue.find(l=>l.messageId===s&&l.kind==="user");if(d&&d.kind==="user"&&!d.cancelled)return d.prompt=o,this.broadcastQueueUpdated(s,o),this.persistRewrite(),{amended:!0,reason:"ok",messageId:s};let c=this.recentlyTerminal.get(s);return c?c.stopReason==="cancelled"?{amended:!1,reason:"target_cancelled"}:a==="send_anyway"?{amended:!1,reason:"target_completed",messageId:this.enqueueAmendmentAsFollowUp(r,o)}:{amended:!1,reason:"target_completed"}:{amended:!1,reason:"target_not_found"}}amendOnHead(e,t,r,s){let o=cs(),i={clientId:e.clientId};if(e.clientInfo?.name&&(i.name=e.clientInfo.name),e.clientInfo?.version&&(i.version=e.clientInfo.version),s){let d=[];for(let c of this.promptQueue){if(c.kind==="user"&&!c.cancelled){c.cancelled=!0,this.broadcastQueueRemoved(c.messageId,"cancelled"),c.resolve({stopReason:"cancelled"});continue}d.push(c)}this.promptQueue=d}let a={kind:"user",messageId:o,originator:i,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,wasAmend:!0,resolve:()=>{},reject:()=>{}};return this.promptQueue.unshift(a),this.persistRewrite(),this.broadcastQueueAdded(a,{amending:r,position:1}),this.amendInProgress={cancelledMessageId:r,newMessageId:o},this.cancelExtensionDispatch(r,"amended"),this.agent.connection.notify("session/cancel",{sessionId:this.upstreamSessionId}).catch(()=>{}),{amended:!0,reason:"ok",messageId:o}}enqueueAmendmentAsFollowUp(e,t){let r=cs(),s={clientId:e.clientId};e.clientInfo?.name&&(s.name=e.clientInfo.name),e.clientInfo?.version&&(s.version=e.clientInfo.version);let o={kind:"user",messageId:r,originator:s,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,resolve:()=>{},reject:()=>{}};return this.promptQueue.push(o),this.persistRewrite(),this.broadcastQueueAdded(o),this.drainQueue(),r}async cancel(e){if(!this.clients.get(e))throw Gn(new Error("client not attached"),V.SessionNotFound);this.lastCancelAt=Date.now(),this.currentEntry?.kind==="user"&&this.currentEntry.messageId!==void 0&&this.cancelExtensionDispatch(this.currentEntry.messageId,"cancelled"),this.closeUnsolicitedTurn("cancelled"),this.agentTurnInFlight||this.closeOpenToolCalls("cancelled"),await this.forwardRequest("session/cancel",{sessionId:this.sessionId},new Set,0,"notification")}addTransformer(e){let t=this.transformChain.findIndex(r=>r.name===e.name);t>=0?this.transformChain[t]=e:this.transformChain.push(e),e.intercepts.has("lifecycle:session.opened")&&e.connection.notify("hydra-acp/transformer/session_event",{event:"session.opened",sessionId:this.sessionId}).catch(()=>{})}async forwardRequest(e,t,r=new Set,s=0,o="request"){let i=this.rewriteForAgent(t);for(let a=s;a<this.transformChain.length;a++){let d=this.transformChain[a];if(r.has(d.name))continue;let c=`request:${e}`;if(!d.intercepts.has(c))continue;let l=`t_${wg()}`,u;try{u=await d.connection.request("hydra-acp/transformer/message",{token:l,phase:"request",method:e,direction:"client\u2192agent",sessionId:this.sessionId,envelope:i})}catch(p){this.logger?.warn(`transformer ${d.name} error on ${c}: ${p.message}`);continue}let f=u?.action??"continue";if(f==="stop")return o==="notification"?void 0:u?.payload??vg(e);if(f==="continue"){u?.payload&&typeof u.payload=="object"&&(i=u.payload),r.add(d.name);continue}if(f==="processing"){let p=a,h=i,m=new Set(r);return new Promise(y=>{let w=setTimeout(()=>{this.pendingClaims.delete(l)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:l,transformerName:d.name}),this.forwardRequest(e,h,new Set([...m,d.name]),p+1,o).then(y).catch(()=>y(o==="notification"?void 0:vg(e))))},Uu);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(l,{resolve:y,timer:w,transformerName:d.name,method:e,envelope:h,chainIdx:p,originatedBy:m,side:"request",tailKind:o})})}r.add(d.name)}if(o==="notification"){await this.agent.connection.notify(e,i);return}return this.agent.connection.request(e,i)}async forwardModelChange(e,t){let r=await xo({request:(s,o)=>this.forwardRequest(s,o),sessionId:this.sessionId,modelId:e,verb:this.modelVerb,extraParams:t,logger:this.logger});return this.modelVerb=r.verb,this.modelVerbConfirmed=!0,r.result}noteModelVerbHint(e,t){e===void 0||this.modelVerbConfirmed||e===this.modelVerb||(this.logger?.info(`model verb for agent ${this.agentId} inferred as ${e} from ${t} (was ${this.modelVerb})`),this.modelVerb=e)}resetModelVerb(e){this.modelVerb=e??as,this.modelVerbConfirmed=!1}async runAgentRequestChain(e,t,r=new Set,s=0){let o=t,i=`request:${e}`;for(let a=s;a<this.transformChain.length;a++){let d=this.transformChain[a];if(r.has(d.name)||!d.intercepts.has(i))continue;let c=`t_${wg()}`,l;try{l=await d.connection.request("hydra-acp/transformer/message",{token:c,phase:"request",method:e,direction:"agent\u2192client",sessionId:this.sessionId,envelope:o})}catch(f){this.logger?.warn(`transformer ${d.name} error on ${i}: ${f.message}`);continue}let u=l?.action??"continue";if(u==="stop")return{shortCircuit:!0,payload:l?.payload??O$(e)};if(u==="continue"){l?.payload&&typeof l.payload=="object"&&(o=l.payload),r.add(d.name);continue}if(u==="processing"){let f=a,p=o,h=new Set(r),m=e;return new Promise(y=>{let w=setTimeout(()=>{this.pendingClaims.delete(c)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:c,transformerName:d.name}),this.runAgentRequestChain(m,p,new Set([...h,d.name]),f+1).then(y).catch(()=>y({shortCircuit:!1,envelope:p})))},Uu);typeof w.unref=="function"&&w.unref(),this.pendingClaims.set(c,{resolve:v=>y({shortCircuit:!0,payload:v}),timer:w,transformerName:d.name,method:m,envelope:p,chainIdx:f,originatedBy:h,side:"agent-request"})})}r.add(d.name)}return{shortCircuit:!1,envelope:o}}dischargeClaim(e,t){let r=this.pendingClaims.get(e);return r?(clearTimeout(r.timer),this.pendingClaims.delete(e),r.resolve(t),!0):!1}keepAliveClaim(e,t){let r=this.pendingClaims.get(e);if(!r)return!1;clearTimeout(r.timer);let s=typeof t=="number"&&t>0?Math.min(t*1.5,1800*1e3):Uu,o=setTimeout(()=>{if(this.pendingClaims.delete(e))if(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:e,transformerName:r.transformerName}),r.side==="response")this.runResponseChain(r.envelope,new Set([...r.originatedBy,r.transformerName]),r.chainIdx+1).then(()=>r.resolve(void 0)).catch(()=>r.resolve(void 0));else if(r.side==="agent-request")this.runAgentRequestChain(r.method,r.envelope,new Set([...r.originatedBy,r.transformerName]),r.chainIdx+1).then(r.resolve).catch(()=>r.resolve({shortCircuit:!1,envelope:r.envelope}));else{let i=r.tailKind??"request";this.forwardRequest(r.method,r.envelope,new Set([...r.originatedBy,r.transformerName]),r.chainIdx+1,i).then(r.resolve).catch(()=>r.resolve(i==="notification"?void 0:vg(r.method)))}},s);return typeof o.unref=="function"&&o.unref(),r.timer=o,!0}async emitToChain(e,t,r){let s=this.transformChain.findIndex(a=>a.name===e),o=s>=0?s+1:0,i=new Set([e]);if(t==="session/update"){await this.runResponseChain(r,i,o);return}return this.forwardRequest(t,r,i,o)}async emitToQueue(e,t){let r=this.transformChain.findIndex(c=>c.name===e),s=r>=0?r+1:0,o=(t??{}).prompt??[],i=cs(),a=`transformer:${e}`,d={clientId:a,name:e};return new Promise((c,l)=>{let u={kind:"user",messageId:i,originator:d,clientId:a,prompt:o,enqueuedAt:Date.now(),cancelled:!1,emitterName:e,chainStartIdx:s,resolve:c,reject:l},f=this.insertEntryAt(u,"tail");this.persistRewrite(),this.broadcastQueueAdded(u,{position:f}),this.drainQueue()})}rewriteForAgent(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(t.sessionId===this.sessionId)return{...t,sessionId:this.upstreamSessionId}}return e}async close(e={}){if(e.deleteRecord&&(this.deleteRecordIntent=!0),!this.closed)return this.closeInFlight?this.closeInFlight:(this.closing=!0,this.closeInFlight=this.doClose(e),this.closeInFlight)}async doClose(e){let t=this.turnStartedAt!==void 0;this.logger?.info(`session ${this.sessionId} closing deleteRecord=${e.deleteRecord??!1} by=${e.by??"unknown"} midTurn=${t} unsolicitedTurn=${this.unsolicitedTurn!==void 0} queued=${this.promptQueue.length} awaitingPermission=${this.hasPermissionFlag}`),t&&this.logger?.warn(`session ${this.sessionId} closed mid-turn by=${e.by??"unknown"}; the in-flight turn will not settle and the agent is being killed`),this.cancelIdleTimer();for(let r of this.pendingClaims.values())clearTimeout(r.timer);this.pendingClaims.clear(),await this.agent.kill().catch(()=>{}),this.markClosed({deleteRecord:e.deleteRecord??!1})}onClose(e){return this.closeHandlers.push(e),()=>{let t=this.closeHandlers.indexOf(e);t>=0&&this.closeHandlers.splice(t,1)}}onTitleChange(e){this.titleHandlers.push(e)}retitle(e){return this.runTitleCommand(e)}retitleFromAgent(){return this.runTitleCommand("")}setTitle(e){let t=e.trim();if(!(!t||t===this.title)){this._titleSeedPending=!1,this.title=t,this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",title:t,updatedAt:new Date().toISOString()}});for(let r of this.titleHandlers)try{r(t)}catch{}}}maybeSeedTitleFromPrompt(e){if(!this._titleSeedPending||En((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let s=Ya((e??{}).prompt),o=Sg(s,200);!o||o.startsWith("/")||(this._titleSeedPending=!1,this.setTitle(o))}maybeApplyAgentModel(e){let r=(e??{}).update??{};if(r.sessionUpdate!=="current_model_update")return!1;let s=Qa(r.availableModels);s.length>0&&this.setAgentAdvertisedModels(s);let o=typeof r.currentModel=="string"?r.currentModel:typeof r.model=="string"?r.model:void 0;if(o===void 0)return!0;let i=o.trim();if(!i||i===this.currentModel)return!0;this.logger?.info(`live current_model_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(i)}`),this.currentModel=i;for(let a of this.modelHandlers)try{a(i)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentConfigOption(e){let r=(e??{}).update??{};if(r.sessionUpdate!=="config_option_update")return!1;let s=r.configOptions;if(!Array.isArray(s))return!0;for(let o of s){if(!o||typeof o!="object")continue;let i=o;if(i.id==="model"){let a=Qa(i.options);a.length>0&&this.setAgentAdvertisedModels(a);let d=i.currentValue;if(typeof d=="string"){let c=d.trim();c&&c!==this.currentModel&&(this.logger?.info(`live config_option_update(model): sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(c)}`),this.applyModelChange(c))}}else if(i.id==="mode"){let a=Tc(i.options);a.length>0&&this.setAgentAdvertisedModes(a);let d=i.currentValue;if(typeof d=="string"){let c=d.trim();c&&c!==this.currentMode&&(this.logger?.info(`live config_option_update(mode): sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(c)}`),this.applyModeChange(c))}}else if(typeof i.id=="string"&&i.id.trim()){let a=i.id.trim(),d=Qa(i.options);if(d.length>0){let c=Tc(i.options),l=c.length>0?c.map(y=>({value:y.id,name:y.name??y.id})):d.map(y=>({value:y.modelId,name:y.name??y.modelId})),u=i.name,f=typeof u=="string"&&u.trim()?u.trim():a,p=i.currentValue,h=typeof p=="string"&&p.trim()?p.trim():l[0]?.value??"",m=this.agentAdvertisedConfigOptions.findIndex(y=>y.id===a);if(m>=0){let y={...this.agentAdvertisedConfigOptions[m]};y.options=l,typeof p=="string"&&p.trim()&&(y.currentValue=p.trim()),this.agentAdvertisedConfigOptions[m]=y}else this.agentAdvertisedConfigOptions.push({id:a,name:f,category:"other",type:"select",currentValue:h,options:l})}}}return!0}maybeApplyAgentMode(e){let r=(e??{}).update??{};if(r.sessionUpdate!=="current_mode_update")return!1;let s=typeof r.currentModeId=="string"?r.currentModeId:typeof r.currentMode=="string"?r.currentMode:typeof r.mode=="string"?r.mode:void 0;if(s===void 0)return!0;let o=s.trim();if(!o||o===this.currentMode)return!0;this.logger?.info(`current_mode_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(o)}`),this.currentMode=o;for(let i of this.modeHandlers)try{i(o)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentUsage(e){let r=(e??{}).update??{};if(r.sessionUpdate!=="usage_update")return!1;let s={...this._currentUsage??{}},o=!1;if(typeof r.used=="number"&&s.used!==r.used&&(s.used=r.used,o=!0),typeof r.size=="number"&&s.size!==r.size&&(s.size=r.size,o=!0),r.cost&&typeof r.cost=="object"){let a=r.cost;typeof a.amount=="number"&&(this.reconcileCostLedger(a.amount)&&(o=!0),s.costAmount!==a.amount&&(s.costAmount=a.amount,o=!0)),typeof a.currency=="string"&&s.costCurrency!==a.currency&&(s.costCurrency=a.currency,o=!0)}if(!o)return!0;this._currentUsage=s;let i=this.persistableUsage??s;for(let a of this.usageHandlers)try{a(i)}catch{}return!0}armCostLedgerProbe(){let e=this._currentUsage?.costAmount;typeof e=="number"&&e>0&&(this.costLedgerProbe=e)}reconcileCostLedger(e){let t=this.costLedgerProbe;return t===void 0||(this.costLedgerProbe=void 0,e>=t-1e-6)?!1:(this.cumulativeCost+=t,!0)}notifyAgentChange(e,t,r){let s=this.retiringGenerationCost;this.retiringGenerationCost=void 0;for(let o of this.agentChangeHandlers)try{o({agentId:this.agentId,upstreamSessionId:this.upstreamSessionId,...s!==void 0?{retiredCost:s}:{},...t!==void 0?{reason:t}:{},...r!==void 0?{runId:r}:{}})}catch(i){this.logger?.warn(`${e}: agentChange handler failed: ${i.message}`)}}accumulateAndResetCost(){let e=this._currentUsage?.costAmount;e&&(this.cumulativeCost+=e,this.retiringGenerationCost=e);let t={used:0,cumulativeCost:this.cumulativeCost,...typeof this._currentUsage?.size=="number"?{size:this._currentUsage.size}:{},...this._currentUsage?.costCurrency?{costCurrency:this._currentUsage.costCurrency}:{}};this._currentUsage=t;for(let r of this.usageHandlers)try{r(t)}catch{}this.broadcastCurrentUsage()}broadcastCurrentUsage(){let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let r={};typeof e.costAmount=="number"&&(r.amount=e.costAmount),typeof e.costCurrency=="string"&&(r.currency=e.costCurrency),t.cost=r}this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:t})}injectCumulativeCost(e){if(!this.cumulativeCost||!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let r=t.update;if(r.sessionUpdate!=="usage_update"||!r.cost||typeof r.cost!="object")return e;let s=r.cost;return typeof s.amount!="number"?e:{...t,update:{...r,cost:{...s,amount:this.cumulativeCost+s.amount}}}}get totalUsage(){return this.currentUsage}setAgentAdvertisedCommands(e){if(x$(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(I$(this.agentAdvertisedModes,e)){this.broadcastAvailableModes();return}this.agentAdvertisedModes=e;for(let t of this.agentModesHandlers)try{t(e)}catch{}this.broadcastAvailableModes()}setAgentAdvertisedModels(e){if(this.logger?.info(`setAgentAdvertisedModels: sessionId=${this.sessionId} currentModel=${JSON.stringify(this.currentModel)} newList=[${e.map(t=>t.modelId).join(",")}]`),C$(this.agentAdvertisedModels,e)){this.broadcastAvailableModels();return}this.agentAdvertisedModels=e;for(let t of this.agentModelsHandlers)try{t(e)}catch{}this.broadcastAvailableModels()}onAgentCommandsChange(e){this.agentCommandsHandlers.push(e)}onAgentModesChange(e){this.agentModesHandlers.push(e)}onAgentModelsChange(e){this.agentModelsHandlers.push(e)}onModelChange(e){this.modelHandlers.push(e)}onModeChange(e){this.modeHandlers.push(e)}onInteractiveChange(e){this.interactiveHandlers.push(e)}onPriorityChange(e){this.priorityHandlers.push(e)}setPriority(e){let t=e===void 0||e<=0?void 0:Math.floor(e);if(t!==this._priority){this._priority=t,this.updatedAt=Date.now();for(let r of this.priorityHandlers)try{r(t)}catch{}}}applyModelChange(e){let t=e.trim();if(t){this.modelChangeInFlight=!0;try{if(t!==this.currentModel){this.logger?.info(`applyModelChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(t)}`),this.currentModel=t;for(let s of this.modelHandlers)try{s(t)}catch{}}let r={sessionUpdate:"current_model_update",currentModel:t};this.agentAdvertisedModels.length>0&&(r.availableModels=[...this.agentAdvertisedModels]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:r}),this.broadcastConfigOptions()}finally{this.modelChangeInFlight=!1}}}applyModeChange(e){let t=e.trim();if(t){this.modeChangeInFlight=!0;try{if(t!==this.currentMode){this.logger?.info(`applyModeChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(t)}`),this.currentMode=t;for(let s of this.modeHandlers)try{s(t)}catch{}}let r={sessionUpdate:"current_mode_update",currentModeId:t};this.agentAdvertisedModes.length>0&&(r.availableModes=[...this.agentAdvertisedModes]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:r}),this.broadcastConfigOptions()}finally{this.modeChangeInFlight=!1}}}buildConfigOptions(){let e=[];if(this.agentAdvertisedModels.length>0){let s=this.agentAdvertisedModels.map(i=>({value:i.modelId,name:i.name??i.modelId,...i.description!==void 0?{description:i.description}:{}})),o=this.currentModel&&s.some(i=>i.value===this.currentModel)?this.currentModel:s[0].value;e.push({id:"model",name:"Model",category:"model",type:"select",currentValue:o,options:s})}if(this.agentAdvertisedModes.length>0){let s=this.agentAdvertisedModes.map(i=>({value:i.id,name:i.name??i.id,...i.description!==void 0?{description:i.description}:{}})),o=this.currentMode&&s.some(i=>i.value===this.currentMode)?this.currentMode:s[0].value;e.push({id:"mode",name:"Session Mode",category:"mode",type:"select",currentValue:o,options:s})}let r=(this.availableAgentsFn?.()??[]).map(s=>({value:s.id,name:s.name??s.id,...s.description!==void 0?{description:s.description}:{}}));return r.some(s=>s.value===this.agentId)||r.unshift({value:this.agentId,name:this.agentId}),e.push({id:"agent",name:"Agent",category:"_hydra_agent",type:"select",currentValue:this.agentId,options:r}),e.push(...this.agentAdvertisedConfigOptions),e}broadcastConfigOptions(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"config_option_update",configOptions:this.buildConfigOptions()}})}mergeAgentOptionIntoEnvelope(e){if(!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let r=t.update,s=Array.isArray(r.configOptions)?[...r.configOptions]:[];if(s.some(a=>a&&typeof a=="object"&&a.id==="agent"))return e;let i=this.buildConfigOptions().find(a=>a.id==="agent");return i?{...t,update:{...r,configOptions:[...s,i]}}:e}onUsageChange(e){this.usageHandlers.push(e)}mergedAvailableCommands(){let e=this.daemonTopLevelCommands(),t=this.aliasableBareVerbs();for(let r of Ga){if(t.get(r.verb)!=="__hydra__")continue;let s=r.argsHint?`${r.verb} ${r.argsHint}`:r.verb;e.push({name:s,description:`Alias for '/hydra ${r.verb}': ${r.description}`})}if(this.extensionCommands)for(let{name:r,command:s}of this.extensionCommands.list()){let o=s.verb?`hydra ${r} ${s.verb}`:`hydra ${r}`,a={name:s.argsHint?`${o} ${s.argsHint}`:o};s.description&&(a.description=s.description),e.push(a);let d=r.startsWith("hydra-acp-")?r.slice(10):r;if(r.startsWith("hydra-acp-")&&d.length>0){let c=s.verb?`hydra ${d} ${s.verb}`:`hydra ${d}`,u={name:s.argsHint?`${c} ${s.argsHint}`:c};s.description&&(u.description=s.description),e.push(u)}if(d.length>0&&t.get(d)===r){let c=s.verb?`${d} ${s.verb}`:d,u={name:s.argsHint?`${c} ${s.argsHint}`:c};s.description&&(u.description=s.description),e.push(u)}}return e.push(...this.agentAdvertisedCommands),e}daemonTopLevelCommands(){return[{name:"hydra",description:"Hydra session command (kill, restart, title, agent <agent>)"},{name:"model",description:"Switch model; omit arg to list available models"},{name:"mode",description:"Switch mode; omit arg to list available modes"},{name:"sessions",description:"List all sessions"},{name:"help",description:"Show available commands"}]}aliasableBareVerbs(){let e=new Set,t=i=>i.split(/\s+/)[0]??"";for(let i of this.daemonTopLevelCommands()){let a=t(i.name);a&&e.add(a)}for(let i of this.agentAdvertisedCommands){let a=t(i.name),d=a.startsWith("/")?a.slice(1):a;d&&e.add(d)}let r=new Map;for(let i of Ga)e.has(i.verb)||r.set(i.verb,"__hydra__");if(!this.extensionCommands)return r;let s=new Map,o=new Set;for(let{name:i}of this.extensionCommands.list()){if(o.has(i))continue;o.add(i);let a=i.startsWith("hydra-acp-")?i.slice(10):i;if(!a||e.has(a)||r.has(a))continue;let d=s.get(a);d===void 0?s.set(a,i):d!==i&&s.set(a,"__conflict__")}for(let[i,a]of s)a!=="__conflict__"&&r.set(i,a);return r}agentOnlyAdvertisedCommands(){return[...this.agentAdvertisedCommands]}agentKnowsSlashCommand(e){let t=s=>s.startsWith("/")?s.slice(1):s,r=t(e);if(!r)return!1;for(let s of this.agentAdvertisedCommands)if(t(s.name.split(/\s+/)[0]??"")===r)return!0;return!1}availableModes(){return[...this.agentAdvertisedModes]}availableModels(){return[...this.agentAdvertisedModels]}maybeApplyAgentSessionInfo(e){let r=(e??{}).update??{};if(r.sessionUpdate!=="session_info_update"||typeof r.title!="string")return;let s=r.title.trim();if(!(!s||s===this.title)){this.title=s,this._firstPromptSeeded=!0,this._titleSeedPending=!1;for(let o of this.titleHandlers)try{o(s)}catch{}}}async handleSlashCommand(e,t){let s=e.slice(6).trim().match(/^(\S+)(?:\s+([\s\S]*))?$/),o=s?.[1]??"",i=(s?.[2]??"").trim();if(o==="")return{stopReason:"end_turn"};let a=t!==void 0;if(Ga.some(u=>u.verb===o))switch(o){case"title":return a?this.runTitleCommandInline(i):this.runTitleCommand(i);case"agent":return this.runAgentCommandInline(i);case"config":return this.handleConfigCommand(`/config ${i}`);case"kill":return this.runKillCommand();case"workspace":return this.runWorkspaceCommand(i);case"restart":return a?this.runRestartCommandInline():this.runRestartCommand();case"compact":return a?this.runCompactCommandInline(i):this.runCompactCommand(i);case"uncompact":return a?this.runUncompactCommandInline():this.runUncompactCommand();case"fork":return a?this.runForkCommandInline(i,t):this.runForkCommand(i);default:{let u=new Error(`no dispatcher for /hydra verb ${o}`);throw u.code=V.InternalError,u}}if(this.extensionCommands?.has(o))return a?this.runExtensionCommandInline(o,i,t):this.runExtensionCommand(o,i);let d=`hydra-acp-${o}`;if(this.extensionCommands?.has(d))return a?this.runExtensionCommandInline(d,i,t):this.runExtensionCommand(d,i);let c=Ga.map(u=>u.verb);if(this.extensionCommands){let u=new Set;for(let{name:f}of this.extensionCommands.list())u.has(f)||(c.push(f),u.add(f))}let l=new Error(`unknown /hydra verb: ${o} (known: ${c.join(", ")})`);throw l.code=V.InvalidParams,l}runExtensionCommand(e,t){return this.enqueuePrompt(`extension:${e}`,()=>this.runExtensionCommandInline(e,t,void 0))}async runExtensionCommandInline(e,t,r){let s=this.extensionCommands?.get(e);if(!s)return this.emitExtensionReply(`extension "${e}" is no longer connected`);let o=t.match(/^(\S+)(?:\s+([\s\S]*))?$/),i=o?.[1]??"",a=(o?.[2]??"").trim();if(!s.commands.some(h=>h.verb===i)){let h=s.commands.map(m=>m.verb).join(", ");return this.emitExtensionReply(`/hydra ${e}${i?` ${i}`:""}: unknown verb (known: ${h||"(none)"})`)}let d={sessionId:this.sessionId,verb:i,args:a};r!==void 0&&(d.messageId=r);let c=()=>{},l=new Promise(h=>{c=h});r!==void 0&&this.inFlightExtensionDispatches.set(r,{extensionName:e,connection:s.connection,cancel:h=>c({stopReason:"cancelled",reason:h})});let u,f=!1;try{let h=s.connection.request("hydra-acp/commands/invoke",d),m=await Promise.race([h,l]);if(m&&typeof m=="object"&&m.stopReason==="cancelled"&&"reason"in m)return f=!0,this.logger?.info(`extension ${e} ${i} cancelled (cancelExtensionDispatch); abandoning in-flight commands/invoke`),{stopReason:"cancelled"};u=m}catch(h){return this.emitExtensionReply(`${e} ${i}: ${h.message}`)}finally{r!==void 0&&!f&&this.inFlightExtensionDispatches.delete(r)}let p=u&&typeof u=="object"&&typeof u.text=="string"?u.text:"";return p.length>0?this.emitExtensionReply(p):{stopReason:"end_turn"}}cancelExtensionDispatch(e,t){let r=this.inFlightExtensionDispatches.get(e);if(!r)return!1;this.inFlightExtensionDispatches.delete(e);try{r.connection.notify("hydra-acp/commands/cancel",{sessionId:this.sessionId,messageId:e,reason:t})}catch(s){this.logger?.warn(`notify commands/cancel to ${r.extensionName} failed: ${s.message}`)}return r.cancel(t),!0}emitExtensionReply(e){return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
|
|
43
43
|
${e}
|
|
44
44
|
`},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}async handleSessionsCommand(){let e;if(!this.listSessions)e="_(session listing not available)_";else{let t=await this.listSessions();if(t.length===0)e="_(no sessions)_";else{let r=t.map(s=>{let o=s.sessionId.replace(/^hydra_session_/,"").slice(0,12),i=s.currentModel?` \xB7 ${s.currentModel}`:"",a=s.sessionId===this.sessionId?" \u25C0":"",d=s.title?` ${s.title}`:"";return`\`${o}\` ${s.cwd}${i}${a}${d}`});e=`Sessions (${t.length}):
|
|
45
45
|
${r.join(`
|
|
@@ -352,7 +352,7 @@ A sync was attempted first but was refused: ${O instanceof Error?O.message:Strin
|
|
|
352
352
|
Nothing was committed: review it with \`git -C ${r} diff --cached\` and commit it however you like. The workspace and its history are untouched.`,warnings:v}}async leaveWorkspace(e,t,r){let s=r.exit!=="detached",o=Me(t.provider),i={path:t.path,sourceCwd:t.sourceCwd,label:t.label,provider:t.provider,...t.snapshot!==void 0?{snapshot:t.snapshot}:{},...t.vcs!==void 0?{vcs:t.vcs}:{}},a=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:t.sourceCwd,workspace:void 0,historyLength:a.length,note:`Returned to the source tree at ${t.sourceCwd}`+(r.exit==="landed"?" after merging the workspace.":r.exit==="discarded"?" after discarding the workspace and its work.":" without merging."),...await this.recordSynopsisFor(e.sessionId),left:{path:t.path,removed:s}}),await this.mutateRecord(e.sessionId,{cwd:e.cwd},["workspace"]),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"left",cwd:e.cwd,sourceCwd:t.sourceCwd,integrated:r.exit==="landed"}),o!==void 0&&await this.enqueueKeyed(this.workspaceQueues,t.path,async()=>{let d=this.liveSessionsIn(t.path,e.sessionId);if(d.length>0){this.logger?.info?.(`session workspace: ${e.sessionId} left ${t.path}; ${d.length} live session(s) remain, so it stays`);return}await this.reclaimAfterLastLeaver(o,i,t,e.sessionId,r)})}async reclaimAfterLastLeaver(e,t,r,s,o){await e.unlock(t).catch(()=>{});for(let i of[this.startRefFor(r.label),this.baselineRefFor(r.label)])await e.dropSnapshotRef(t,i).catch(()=>{});o.exit!=="detached"&&(o.exit==="landed"&&await e.dropSnapshotRef(t,this.snapshotRefFor(r.label)).catch(()=>{}),await e.removeWorkspace(t,{force:!0,discardLine:!0}).catch(()=>{}))}async joinDivergence(e,t,r){let[s,o]=await Promise.all([e.captureWorkingState(t,"hydra: source state at join").catch(()=>{}),e.captureWorkingState(r.path,"hydra: workspace state at join").catch(()=>{})]);if(s===void 0||o===void 0)return`could not compare ${q(t)} with ${q(r.path)}, so refusing to join a workspace that may not match your tree`;let i=await Promise.all([s,o].map(a=>e.contentId(t,a).catch(()=>{})));if(!(i[0]!==void 0&&i[0]===i[1]))return`${q(t)} and ${q(r.path)} have diverged, and joining does not carry work across \u2014 whichever side you are not in would be left behind. Land or stash one of them first: \`git -C ${t} stash\` if the difference is yours, or \`/hydra workspace merge\` from the session already in there if it is theirs.`}liveSessionsWithLabel(e,t){let r=[];for(let s of this.sessions.values()){let o=s.workspace;o===void 0||o.sourceCwd!==e||(o.label===t||o.requestedLabel===t)&&r.push(s)}return r}async joinWorkspace(e,t,r,s){let o=Me(r.provider);if(o===void 0)throw new Error(`no provider "${r.provider}" to join that workspace with`);if(o.capabilities().supports.captureWorkingState){let i=await this.joinDivergence(o,s,r);if(i!==void 0)throw new Error(i)}return await this.enqueueKeyed(this.workspaceQueues,r.path,async()=>{if(this.sessions.get(t.sessionId)?.workspace?.path!==r.path)throw new Error(`${q(r.path)} was released while joining it; run the command again`);e.broadcastWorkspacePhase({phase:"swapping"});let i=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:r.path,workspace:{path:r.path,sourceCwd:r.sourceCwd,label:r.label,...r.requestedLabel!==void 0?{requestedLabel:r.requestedLabel}:{},provider:r.provider,...r.snapshot!==void 0?{snapshot:r.snapshot}:{},...r.line!==void 0?{line:r.line}:{},...r.vcs!==void 0?{vcs:{...r.vcs}}:{}},historyLength:i.length,note:`Continuing in an isolated workspace at ${r.path}, derived from ${s}, shared with another session.`,...await this.recordSynopsisFor(e.sessionId)}),await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),this.invalidateListCache();let a=r.line;e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:r.sourceCwd,label:r.label,...a!==void 0?{branch:a}:{}});let d=this.liveSessionsIn(r.path,e.sessionId).map(l=>Ue(l.sessionId)),c=[`Joined workspace ${q(r.path)}`,` source: ${q(r.sourceCwd)}`];return a!==void 0&&c.push(` branch: ${a}`),c.push(` shared with: ${d.join(", ")}`),c.push(" your edits will interleave with that session's"),c.push("Use `/hydra workspace stop` to leave; the work lands when the last session leaves."),c.join(`
|
|
353
353
|
`)})}async startWorkspace(e,t,r){if(e.workspace!==void 0)throw new Error(`already isolated in ${q(e.workspace.path)}. Use \`/hydra workspace stop\` to merge and return first, or \`detach\` to leave it behind.`);let s=e.cwd,o=Me();if(o===void 0)throw new Error("no workspace provider available");let i=await e.quiesceBlocker();if(i!==void 0)throw new Error(i);let a=o.capabilities();if(t!==void 0){let C=this.liveSessionsWithLabel(s,t)[0];if(C!==void 0&&C.workspace!==void 0)return await this.joinWorkspace(e,C,C.workspace,s)}let d,c=[],l=!1,u=!1,f=[],p=[],h=r?.clean===!0;if(a.supports.captureWorkingState){let C=await o.status({path:s,sourceCwd:s,label:"source",provider:o.kind}).catch(()=>{});u=C!==void 0;let T=a.supports.nestedTrees&&C!==void 0&&C.changedPaths.length>0?await o.listNested(s).catch(()=>[]):[];if(C!==void 0&&C.changedPaths.length>0&&h)f=$g(C.changedPaths,T);else if(C!==void 0&&C.changedPaths.length>0&&(c=$g(C.changedPaths,T),p=await o.captureNested(s,T).catch(()=>[]),l=C.hasStagedWork===!0,d=await o.captureWorkingState(s,"hydra: work carried into workspace").catch(()=>{}),d===void 0))throw new Error("could not snapshot your uncommitted work, so refusing to move it. Commit or stash first.")}e.broadcastWorkspacePhase({phase:"provisioning"});let m=await o.createWorkspace({sourceCwd:s,label:t??`s-${e.sessionId.slice(-8)}`});if(!m.ok)throw e.broadcastWorkspacePhase({phase:"failed",error:m.reason}),new Error(m.reason);let y=m.workspace,w=this.startRefFor(y.label),v,b=!1,S=[];try{a.locking&&await o.lock(y,`session ${e.sessionId}`).catch(()=>{});let C=d??y.snapshot;if(C===void 0)throw new Error(`provider "${y.provider}" gave the workspace no base to anchor landing against`);await o.retainSnapshot(y,w,C),e.broadcastWorkspacePhase({phase:"setup"}),b=d!==void 0?await this.copyCarriedWork(y,d,s):!0;let T=await this.materializeNestedTrees(y);if(p.length>0){let E=await o.reproduceNested(y.path,s,p).catch(M=>({applied:[],failed:p.map(B=>({path:B.relPath,reason:M instanceof Error?M.message:String(M)}))}));E.failed.length>0&&(b=!1,S=E.failed)}v=await this.applyWorkspaceSetup(y,e.sessionId),T!==void 0&&(v=v===void 0?T:`${T}; ${v}`),e.broadcastWorkspacePhase({phase:"swapping"});let O=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:y.path,workspace:{path:y.path,sourceCwd:y.sourceCwd,label:y.label,...t!==void 0&&t!==y.label?{requestedLabel:t}:{},provider:y.provider,...y.snapshot!==void 0?{snapshot:y.snapshot}:{},...y.line!==void 0?{line:y.line}:{},...y.vcs!==void 0?{vcs:{...y.vcs}}:{},...d===void 0?{clean:!0}:{}},historyLength:O.length,note:`Continuing in an isolated workspace at ${y.path}, derived from ${s}.`,...await this.recordSynopsisFor(e.sessionId)})}catch(C){let T=await this.unwindStartWorkspace({provider:o,ws:y,startRef:w,carried:d}),O=C instanceof Error?C.message:String(C);throw e.broadcastWorkspacePhase({phase:"failed",error:O}),new Error(T===void 0?O:`${O}
|
|
354
354
|
${T}`)}await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:y.sourceCwd,label:y.label,...y.line!==void 0?{branch:y.line}:{}});let R=[`Moved into workspace ${q(y.path)}`,` source: ${q(s)}`];if(y.line!==void 0&&R.push(` branch: ${y.line}`),t!==void 0&&t!==y.label&&R.push(` note: "${t}" was already taken by a surviving branch, so this is "${y.label}"`),d!==void 0){R.push(b?` carried ${c.length} uncommitted file(s) in; the source tree is untouched:`:` WARNING: could not copy ${c.length} uncommitted file(s); the workspace starts from HEAD. They are untouched in the source tree:`);for(let C of ki(c))R.push(` ${C}`);b&&l&&R.push(" staging did not come along; everything above is unstaged here");for(let C of S)R.push(` nested tree ${C.path}: ${C.reason}`)}else if(f.length>0){R.push(` started clean: ${f.length} uncommitted file(s) stayed in the source and did NOT come along:`);for(let C of ki(f))R.push(` ${C}`)}else u&&R.push(" source tree was clean; nothing carried in");return v!==void 0&&R.push(` ${v}`),R.push("Use `/hydra workspace stop` to merge back and return."),R.join(`
|
|
355
|
-
`)}async copyCarriedWork(e,t,r){let s=await this.patchFromSnapshot(r,t,e.provider);if(s===void 0)return!1;if(s.length===0)return!0;let o=Me(e.provider);return o===void 0?!1:(await o.applyDelta(e.path,s)).ok}async patchFromSnapshot(e,t,r){let s=Me(r);if(s===void 0)return;let o=await s.currentState(e);if(o!==void 0)return await s.captureDelta(e,o,t).catch(()=>{})}async unwindStartWorkspace(e){let{provider:t,ws:r,startRef:s,carried:o}=e;await t.unlock(r).catch(()=>{}),o!==void 0&&await t.dropSnapshotRef(r,s).catch(()=>{}),await t.removeWorkspace(r,{force:!0}).catch(()=>{})}async materializeNestedTrees(e,t){let r=Me(e.provider);if(r?.capabilities().supports.nestedTrees!==!0)return;let s=await r.materializeNested({path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:r.kind},t).catch(o=>({ok:!1,count:0,reason:o instanceof Error?o.message:String(o)}));return s.ok?s.count>0?`populated ${s.count} nested tree(s)`:void 0:`nested trees FAILED: ${s.reason??"unknown"}`}async applyWorkspaceSetup(e,t){let r=await tf(e.sourceCwd).catch(()=>({})),s=[];if(r.carry!==void 0&&r.carry.length>0){let o=await Bg(e.sourceCwd,e.path,r.carry).catch(()=>{});o!==void 0&&o.copied.length>0&&s.push(`carried ${o.copied.length} config file(s)`)}if(r.postCreate!==void 0){let o=await nf(r.postCreate,{workspacePath:e.path,sourceCwd:e.sourceCwd,label:e.label,sessionId:t,...r.hookTimeoutSeconds!==void 0?{timeoutSeconds:r.hookTimeoutSeconds}:{}});s.push(o.ok?"ran postCreate":`postCreate FAILED: ${o.reason??"unknown"}`)}return s.length>0?s.join("; "):void 0}async deriveForkWorkspace(e,t){let r=Me(e.provider);if(r===void 0)return;let s=r.capabilities(),o=s.sharedHistory?await r.currentState(e.path)??"":"",i=await r.createWorkspace({sourceCwd:e.sourceCwd,label:t,...o.length>0?{from:o}:{contentFrom:e.path}}).catch(d=>({ok:!1,reason:String(d)}));if(!i.ok){this.logger?.warn?.(`fork workspace: could not derive from ${e.path}: ${i.reason}`);return}let a=i.workspace;if(o.length>0&&s.supports.captureWorkingState){let d=await r.captureWorkingState(e.path,`hydra: fork carry from ${e.label}`).catch(()=>{});d!==void 0&&d!==o&&await this.copyUncommittedInto(e.path,a.path,o,d,a.provider).catch(()=>{})}return{path:a.path,sourceCwd:a.sourceCwd,label:a.label,provider:a.provider,...a.snapshot!==void 0?{snapshot:a.snapshot}:{},...a.line!==void 0?{line:a.line}:{},...a.vcs!==void 0?{vcs:{...a.vcs}}:{}}}async copyUncommittedInto(e,t,r,s,o){let i=Me(o);if(i===void 0)return!1;let a=await i.captureDelta(e,r,s).catch(()=>{});return a===void 0||a.trim().length===0?!1:(await i.applyDelta(t,a,{stage:!0})).ok}async recoverWorkspace(e){let t=Me(e.provider);if(t===void 0)return;let r={path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:e.provider,...e.snapshot!==void 0?{snapshot:e.snapshot}:{},...e.vcs!==void 0?{vcs:e.vcs}:{}};if(t.capabilities().supports.rematerialize){let o=await t.rematerialize(r).catch(i=>({ok:!1,reason:String(i)}));if(o.ok)return this.logger?.info?.(`session workspace: restored ${o.workspace.path} from retained state`),{...e,path:o.workspace.path};this.logger?.warn?.(`session workspace: could not restore: ${o.reason}`)}if(!await this.dirExists(e.sourceCwd))return;let s=await t.createWorkspace({sourceCwd:e.sourceCwd,label:`${e.label}-r`}).catch(o=>({ok:!1,reason:String(o)}));if(s.ok)return this.logger?.warn?.(`session workspace: ${e.path} is gone and could not be restored; resurrecting in a fresh workspace ${s.workspace.path} from ${e.sourceCwd}. Uncommitted work from the old workspace is not recoverable.`),{path:s.workspace.path,sourceCwd:s.workspace.sourceCwd,label:s.workspace.label,provider:s.workspace.provider,...s.workspace.snapshot!==void 0?{snapshot:s.workspace.snapshot}:{},...s.workspace.vcs!==void 0?{vcs:{...s.workspace.vcs}}:{}}}async syncFromAgent(e){let t=await this.registry.getAgent(e);if(!t){let p=new Error(`agent ${e} not found in registry`);throw p.code=V.AgentNotInstalled,p}let r=await ur(t,[],{npmRegistry:this.npmRegistry}),s=this.spawner({agentId:e,cwd:Dx.homedir(),plan:r}),o;try{o=await s.connection.request("initialize",{protocolVersion:1,clientCapabilities:Wa,clientInfo:{name:"hydra",version:_e}})}catch(p){throw await s.kill().catch(()=>{}),Co(p,s)}if(s.authMethods=Hc(o.authMethods),(o.agentCapabilities??{}).sessionCapabilities?.list===void 0)throw await s.kill().catch(()=>{}),new Error(`agent ${e} does not advertise sessionCapabilities.list; cannot sync`);let a;try{a=await this.collectAgentSessions(s)}catch(p){throw await s.kill().catch(()=>{}),p}await s.kill().catch(()=>{});let d=new Set;for(let p of this.sessions.values())d.add(`${p.agentId}::${p.upstreamSessionId}`);let c=await this.store.list().catch(()=>[]);for(let p of c){d.add(`${p.agentId}::${p.upstreamSessionId}`);for(let h of p.upstreamGenerations??[])d.add(`${h.agentId}::${h.upstreamSessionId}`)}let l=D.sessionsDir(),u=[],f=0;for(let p of a){let h=`${e}::${p.sessionId}`;if(d.has(h)){f+=1;continue}if(DO(p.cwd,l)){f+=1;continue}let m=await this.tombstones.read(e,p.sessionId).catch(()=>{});if(m){if(!ux(m,p.updatedAt)){f+=1;continue}await this.tombstones.remove(e,p.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${p.sessionId} (upstream updatedAt advanced past ${m.upstreamUpdatedAt??"<unset>"})`)}d.add(h);let y=`${fn}${sd()}`,w=new Date().toISOString(),v=p.updatedAt??w,b={sessionId:y,lineageId:Pc(),upstreamSessionId:p.sessionId,agentId:e,cwd:p.cwd,pendingHistorySync:!0,interactive:!0,createdAt:v,updatedAt:v};p.title!==void 0&&(b.title=p.title);let S=Pg(b);await this.store.write(S),u.push({version:1,...S})}return{synced:u,skipped:f}}async collectAgentSessions(e){let t=[],r,s=new Set;for(let o=0;o<100;o+=1){let i={};r!==void 0&&(i.cursor=r);let a=await e.connection.request("session/list",i),d=Array.isArray(a.sessions)?a.sessions:[];for(let c of d){if(typeof c.sessionId!="string"||typeof c.cwd!="string")continue;let l={sessionId:c.sessionId,cwd:c.cwd};typeof c.title=="string"&&(l.title=c.title),typeof c.updatedAt=="string"&&(l.updatedAt=c.updatedAt),t.push(l)}if(typeof a.nextCursor!="string"||a.nextCursor.length===0||s.has(a.nextCursor))break;s.add(a.nextCursor),r=a.nextCursor}return t}async applySeedModel(e,t,r,s,o){try{let{verb:i}=await xo({request:(a,d)=>e.connection.request(a,d),sessionId:t,modelId:r,...o?{verb:o}:{},logger:this.logger});return this.logger?.info(`${s}: ${i} accepted`),!0}catch(i){return this.logger?.warn(`${s} rejected by agent (${i.message}); session will use the agent's own default`),!1}}async bootstrapAgent(e){let t=await this.registry.getAgent(e.agentId);if(!t){let i=new Error(`agent ${e.agentId} not found in registry`);throw i.code=V.AgentNotInstalled,i}let r=await ur(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),s=Iu(e.selfSessionId,e.forwardedEnv),o=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:r,...s?{extraEnv:s}:{}});try{let i=await o.connection.request("initialize",{protocolVersion:1,clientCapabilities:Wa,clientInfo:{name:"hydra",version:_e}}),a=i.agentCapabilities;o.authMethods=Hc(i.authMethods);let d=Yg(e.agentId),c=await o.connection.request("session/new",{cwd:e.cwd,mcpServers:e.mcpServers??[],...d&&{_meta:d}}),l=c.sessionId;if(typeof l!="string")throw new Error(`agent ${e.agentId} returned a non-string sessionId from session/new`);let u=Qg(c),f=Zg(c),p=ja(c),h=e.model??this.defaultModels[e.agentId];if(h&&h!==u){let w=Va(h,f),v=e.model!==void 0?`model=${JSON.stringify(h)}`:`defaultModels[${e.agentId}]=${JSON.stringify(h)}`;if(w.kind==="exact"||w.kind==="none")await this.applySeedModel(o,l,h,v,p)&&(u=h);else if(w.kind==="resolved")(w.modelId===u||await this.applySeedModel(o,l,w.modelId,`${v} resolved to ${JSON.stringify(w.modelId)}`,p))&&(u=w.modelId);else if(w.kind==="ambiguous")this.logger?.warn(`${v} is ambiguous (trailing-segment matches [${w.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(u)}`);else{let b=f.map(S=>S.modelId).join(", ");this.logger?.warn(`${v} not in agent's availableModels ([${b}]); skipping session/set_model, session will use ${JSON.stringify(u)}`)}}let m=ey(c),y=ty(c);return{agent:o,upstreamSessionId:l,agentMeta:c._meta,agentCapabilities:a,initialModel:u,initialModels:f.length>0?f:void 0,initialModes:m.length>0?m:void 0,initialMode:y,modelVerb:p}}catch(i){throw await o.kill().catch(()=>{}),Co(Nx(i,o,e.agentId,{command:r.command,args:r.args,cwd:e.cwd}),o)}}async bootstrapAgentLoad(e,t){let r=await this.registry.getAgent(t.agentId);if(!r){let a=new Error(`agent ${t.agentId} not found in registry`);throw a.code=V.AgentNotInstalled,a}let s=await ur(r,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=Iu(t.selfSessionId,t.forwardedEnv),i=this.spawner({agentId:t.agentId,cwd:t.cwd,plan:s,...o?{extraEnv:o}:{}});try{let a=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:Wa,clientInfo:{name:"hydra",version:_e}}),d=a.agentCapabilities;i.authMethods=Hc(a.authMethods);let c=Yg(t.agentId),l=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),u=Qg(l),f=Xg(Zg(l)),p=ey(l),h=ty(l);return{agent:i,upstreamSessionId:e,agentMeta:l._meta,agentCapabilities:d,initialModel:u,initialModels:f,initialModes:p.length>0?p:void 0,initialMode:h,modelVerb:ja(l)}}catch(a){throw await i.kill().catch(()=>{}),Co(Nx(a,i,t.agentId,{command:s.command,args:s.args,cwd:t.cwd}),i)}}async performUncompact(e){if(this.rollbackLocks.has(e))throw new Error("a rollback is already in progress for this session");let t=this.get(e);if(!t)throw new Error("session is not live \u2014 cannot roll back a cold session");let r=await this.store.read(e);if(!r)throw new Error("session record not found");let s=r.rollbackBreadcrumb;if(!s)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=r.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:s.previousUpstreamSessionId,previousSummarizedThroughEntry:s.previousSummarizedThroughEntry}),await this.mutateRecord(e,{summarizedThroughEntry:s.previousSummarizedThroughEntry},["synopsis","rollbackBreadcrumb"])}finally{this.rollbackLocks.delete(e)}}async bootstrapAgentForAuth(e,t){let r=this.pendingAuthAgents.get(e);if(r&&r.isAlive())return r;let s=await this.registry.getAgent(e);if(!s){let d=new Error(`agent ${e} not found in registry`);throw d.code=V.AgentNotInstalled,d}let o=await ur(s,[],{npmRegistry:this.npmRegistry}),i=t??yt(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let d=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:Wa,clientInfo:{name:"hydra",version:_e}});a.authMethods=Hc(d.authMethods)}catch(d){throw await a.kill().catch(()=>{}),Co(d,a)}return this.pendingAuthAgents.set(e,a),a.onExit(()=>{this.pendingAuthAgents.get(e)===a&&this.pendingAuthAgents.delete(e)}),a}async planSpawnForAgent(e){let t=await this.registry.getAgent(e);if(!t){let r=new Error(`agent ${e} not found in registry`);throw r.code=V.AgentNotInstalled,r}return ur(t,[],{npmRegistry:this.npmRegistry})}consumePendingAuthAgent(e){let t=this.pendingAuthAgents.get(e);if(t&&(this.pendingAuthAgents.delete(e),!!t.isAlive()))return t}getAgentForSession(e){return this.sessions.get(e)?.agent}async attachManagerHooks(e){e.onClose(({deleteRecord:t})=>{if(this.sessions.delete(e.sessionId),this.driftNoticed.delete(e.sessionId),this.invalidateListCache(),t&&e.workspace!==void 0&&this.releaseWorkspace(e.workspace,e.sessionId).catch(()=>{}),t){if(e.upstreamSessionId){let s=od({interactive:e.interactive,...e.originatingClient?{originatingClient:e.originatingClient}:{}},!0),o=this.tombstoneAllGenerations(e.sessionId,{agentId:e.agentId,upstreamSessionId:e.upstreamSessionId,upstreamUpdatedAt:new Date(e.updatedAt).toISOString(),cwd:e.cwd,...e.title!==void 0?{title:e.title}:{},...s!==void 0?{interactive:s}:{}},"user").catch(()=>{}).then(()=>this.store.delete(e.sessionId).catch(()=>{})).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===o&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,o);return}let r=this.store.delete(e.sessionId).catch(()=>{}).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===r&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,r);return}}),e.onTitleChange(t=>{this.persistTitle(e.sessionId,t).catch(()=>{})}),e.onPriorityChange(t=>{this.persistPriority(e.sessionId,t).catch(()=>{})}),e.onAgentChange(({agentId:t,upstreamSessionId:r,retiredCost:s,reason:o,runId:i})=>{this.persistAgentChange(e.sessionId,t,r,s,o,i).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:Hx(t)}).catch(()=>{})}),e.onAgentCommandsChange(t=>{this.persistSnapshot(e.sessionId,{agentCommands:t.map(r=>({name:r.name,...r.description!==void 0?{description:r.description}:{}}))}).catch(()=>{})}),e.onAgentModesChange(t=>{this.persistSnapshot(e.sessionId,{agentModes:t.map(r=>({id:r.id,...r.name!==void 0?{name:r.name}:{},...r.description!==void 0?{description:r.description}:{}}))}).catch(()=>{})}),e.onAgentModelsChange(t=>{this.persistSnapshot(e.sessionId,{agentModels:t.map(r=>({modelId:r.modelId,...r.name!==void 0?{name:r.name}:{},...r.description!==void 0?{description:r.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),r=HO(e,t);await this.store.write(r)}).catch(()=>{})}async getHistory(e){if(this.sessions.has(e))return this.histories.load(e).catch(()=>[]);if(await this.store.read(e))return this.histories.load(e).catch(()=>[])}async loadHistory(e,t={}){return this.histories.load(e,t)}async loadToolBlob(e,t){return bc(e,t)}async loadFromDisk(e){let t=await this.store.read(e);if(!t)return;let r=t.title;return r||(r=await this.deriveTitleFromHistory(e)),{hydraSessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,agentId:t.agentId,cwd:t.cwd,title:r,synopsis:t.synopsis,summarizedThroughEntry:t.summarizedThroughEntry,agentArgs:t.agentArgs,currentModel:t.currentModel,currentMode:t.currentMode,currentUsage:UO(t.currentUsage),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,forwardedEnv:t.forwardedEnv,workspace:t.workspace,compactionState:t.compactionState,attentionFlags:t.attentionFlags?.filter(s=>!(s.source==="daemon"&&s.reason.startsWith("permission:")))}}async setForwardedEnv(e,t){if(t===void 0)return;let r=this.sessions.get(e);r&&(r.forwardedEnv=t),await this.enqueueMetaWrite(e,async()=>{let s=await this.store.read(e);if(!s)return;let o={...s,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 r={...t};delete r.pendingHistorySync,await this.store.write(r)})}async deriveTitleFromHistory(e){let t=await this.histories.load(e).catch(()=>[]);for(let r of t){let s=r.params;if(s?.update?.sessionUpdate!=="prompt_received")continue;let o=Ya(s.update.prompt),i=Sg(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 r=t.agent.agentId,s=t.agent.version,o=e.get(r);o||(o=new Set,e.set(r,o)),o.add(s)}return e}async resolveCanonicalId(e){if(this.sessions.has(e)||await this.store.read(e))return e;if(e.startsWith(fn))return;let t=fn+e;if(this.sessions.has(t)||await this.store.read(t))return t}require(e){let t=this.sessions.get(e);if(!t){let r=new Error(`session ${e} not found`);throw r.code=V.SessionNotFound,r}return t}liveListEntry(e){return{sessionId:e.sessionId,upstreamSessionId:e.upstreamSessionId,cwd:e.cwd,workspace:e.workspace,workspaceError:e.workspaceError,title:e.title,agentId:e.agentId,currentModel:e.currentModel,currentUsage:e.currentUsage,parentSessionId:e.parentSessionId,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,forkSynthesisState:e.forkSynthesisState,originatingClient:e.originatingClient,interactive:e.interactive,updatedAt:new Date(e.updatedAt).toISOString(),attachedClients:e.attachedCount,status:"warm",busy:e.turnStartedAt!==void 0,armedTasks:e.armedBackgroundTasks.length,...e.armedSince!==void 0?{armedSince:e.armedSince}:{},awaitingInput:e.awaitingInput,agentPid:e.agentPid}}async getOne(e){let t=this.sessions.get(e);if(t){let a=await Uc(t.sessionId),d=od({interactive:t.interactive,...t.originatingClient?{originatingClient:t.originatingClient}:{}},a.hasContent),c=a.mtime??new Date(t.updatedAt).toISOString();return{sessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,cwd:t.cwd,title:t.title,agentId:t.agentId,currentModel:t.currentModel,currentUsage:t.currentUsage,parentSessionId:t.parentSessionId,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,originatingClient:t.originatingClient,interactive:d,priority:t.priority,updatedAt:c,attachedClients:t.attachedCount,status:"warm",agentPid:t.agentPid,busy:t.turnStartedAt!==void 0,armedTasks:t.armedBackgroundTasks.length,...t.armedSince!==void 0?{armedSince:t.armedSince}:{},awaitingInput:t.awaitingInput}}let r=await this.store.read(e).catch(()=>{});if(!r)return;let s=await Uc(r.sessionId),o=od(r,s.hasContent),i=s.mtime??r.updatedAt;return{sessionId:r.sessionId,upstreamSessionId:r.upstreamSessionId,cwd:r.cwd,title:r.title,agentId:r.agentId,currentModel:r.currentModel,currentUsage:Ii(r.currentUsage),importedFromMachine:r.importedFromMachine,importedFromUpstreamSessionId:r.importedFromUpstreamSessionId,parentSessionId:r.parentSessionId,forkedFromSessionId:r.forkedFromSessionId,forkedFromMessageId:r.forkedFromMessageId,forkSynthesisState:r.forkSynthesisState,originatingClient:r.originatingClient,interactive:o,priority:r.priority,updatedAt:i,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1}}async list(e={}){let t=`${e.cwd??""}|${e.includeNonInteractive?"1":"0"}|${e.status??""}`,r=Date.now(),s=this.listCache.get(t);if(s&&s.expiresAt>r)return s.promise;let o=this.listUncached(e);return this.listCache.set(t,{expiresAt:r+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=[],r=new Set,s=l=>e.includeNonInteractive?!0:l===!0,o=[...this.sessions.values()].filter(l=>Fx(e.cwd,l));if(e.status==="cold")for(let l of o)r.add(l.sessionId);let i=e.status==="cold"?[]:await Promise.all(o.map(l=>Uc(l.sessionId)));for(let l=0;l<i.length;l+=1){let u=o[l],f=i[l];r.add(u.sessionId);let p=od({interactive:u.interactive,...u.originatingClient?{originatingClient:u.originatingClient}:{}},f.hasContent);if(!s(p))continue;let h=f.mtime??new Date(u.updatedAt).toISOString();t.push({sessionId:u.sessionId,upstreamSessionId:u.upstreamSessionId,cwd:u.cwd,workspace:u.workspace,workspaceError:u.workspaceError,title:u.title,agentId:u.agentId,currentModel:u.currentModel,currentUsage:u.currentUsage,parentSessionId:u.parentSessionId,forkedFromSessionId:u.forkedFromSessionId,forkedFromMessageId:u.forkedFromMessageId,originatingClient:u.originatingClient,interactive:p,priority:u.priority,updatedAt:h,attachedClients:u.attachedCount,status:"warm",agentPid:u.agentPid,busy:u.turnStartedAt!==void 0,armedTasks:u.armedBackgroundTasks.length,...u.armedSince!==void 0?{armedSince:u.armedSince}:{},awaitingInput:u.awaitingInput,compactionState:u.compactionState,forkSynthesisState:u.forkSynthesisState})}if(e.status==="warm")return t;let d=(await this.store.list().catch(l=>{throw this.logger?.warn(`session list: store.list() failed: ${l?.message??String(l)}`),l})).filter(l=>!r.has(l.sessionId)&&Fx(e.cwd,l)),c=await Promise.all(d.map(l=>Uc(l.sessionId)));for(let l=0;l<d.length;l+=1){let u=d[l],f=c[l],p=od(u,f.hasContent);if(!s(p))continue;let h=f.mtime??u.updatedAt;t.push({sessionId:u.sessionId,upstreamSessionId:u.upstreamSessionId,cwd:u.cwd,workspace:u.workspace,title:u.title,agentId:u.agentId,currentModel:u.currentModel,currentUsage:Ii(u.currentUsage),importedFromMachine:u.importedFromMachine,importedFromUpstreamSessionId:u.importedFromUpstreamSessionId,parentSessionId:u.parentSessionId,forkedFromSessionId:u.forkedFromSessionId,forkedFromMessageId:u.forkedFromMessageId,originatingClient:u.originatingClient,interactive:p,priority:u.priority,updatedAt:h,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,compactionState:u.compactionState,forkSynthesisState:u.forkSynthesisState})}return t.sort((l,u)=>l.updatedAt<u.updatedAt?1:-1),t}async exportBundle(e,t={}){let r=await this.store.read(e);if(!r)return;let s;if(r.lineageId)s=r;else{let c=Pc(),l={...r,lineageId:c};await this.enqueueMetaWrite(e,async()=>{let u=await this.store.read(e);u&&(u.lineageId||await this.store.write({...u,lineageId:c}))}).catch(()=>{}),s=l}let o=t.tools??"inline",i=await this.histories.load(e,o==="references"?{tools:"references"}:{}).catch(()=>[]),a=await Bx(e);if(o!=="references")return{record:s,history:i,promptHistory:a};let d={};for(let c of Tx(i)){let l=await Tv(e,c);l&&(d[c]=l.toString("base64"))}return{record:s,history:i,promptHistory:a,toolBlobs:d}}async importBundle(e,t={}){let r=await this.store.findByLineageId(e.session.lineageId);if(r){if(!t.replace){let i=new Error(`bundle already imported as ${r.sessionId}`);throw i.code=V.BundleAlreadyImported,i.existingSessionId=r.sessionId,i}let o=this.sessions.get(r.sessionId);return o&&await o.close({deleteRecord:!1,by:"bundle-import-overwrite"}).catch(()=>{}),await this.writeImportedRecord({sessionId:r.sessionId,bundle:e,preservedCreatedAt:r.createdAt,cwd:t.cwd}),{sessionId:r.sessionId,importedFromSessionId:e.session.sessionId,replaced:!0}}let s=`${fn}${sd()}`;return await this.writeImportedRecord({sessionId:s,bundle:e,cwd:t.cwd}),{sessionId:s,importedFromSessionId:e.session.sessionId,replaced:!1}}async forkSession(e,t={}){let r=await this.store.read(e);if(!r){let R=new Error(`source session not found: ${e}`);throw R.code=V.SessionNotFound,R}let s=t.agentId??r.agentId,o=s!==r.agentId;if(o&&!await this.registry.getAgent(s)){let C=new Error(`agent ${s} not found in registry`);throw C.code=V.AgentNotInstalled,C}let i=await this.histories.load(e).catch(()=>[]),a=i,d,c=t.mode??"synthesis",l,u,f,p=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let R=Wu(i,t.forkAt);if(R<0){let C=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw C.code=V.InvalidParams,C}d=t.forkAt,a=i.slice(0,R+1)}else{let R=jO(i);R?(d=R.messageId,a=i.slice(0,R.index+1)):(d="",a=i.slice(0,0))}else{if(t.forkAt!==void 0&&t.forkAt!==""){let C=Wu(i,t.forkAt);if(C<0){let T=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw T.code=V.InvalidParams,T}d=t.forkAt,a=i.slice(0,C+1)}else d="",a=i;let R=await this.registry.getAgent(s);if(!R){let C=new Error(`agent ${s} not found in registry`);throw C.code=V.AgentNotInstalled,C}f=R,u=r.currentModel,l="running"}let h=await Bx(e),m=c==="synthesis",y={...r,lineageId:Pc(),agentId:s,interactive:!1,...l!==void 0?{forkSynthesisState:l}:{},summarizedThroughEntry:a.length,...t.title!==void 0?{title:t.title}:{},currentUsage:void 0,...o?{currentModel:void 0,currentMode:void 0,agentCommands:void 0,agentModes:void 0,agentModels:void 0}:{},...t.model!==void 0?{currentModel:t.model}:{}},w=Bc({record:y,history:a,promptHistory:h.length>0?h:void 0,hydraVersion:_e,machine:So()}),v=`${fn}${sd()}`,b=t.cwd,S;if(t.cwd===void 0&&r.workspace!==void 0){let R=await this.deriveForkWorkspace(r.workspace,`${r.workspace.label}-fork-${v.slice(-6)}`);R!==void 0?(S=R,b=R.path):(b=r.workspace.sourceCwd,this.logger?.warn?.(`fork ${v}: could not derive an isolated workspace from ${r.workspace.path}; running unisolated in ${b}`))}return await this.writeImportedRecord({sessionId:v,bundle:w,cwd:b,...S!==void 0?{workspace:S}:{},forkedFromSessionId:e,forkedFromMessageId:d,...l!==void 0?{forkSynthesisState:l}:{}}),m&&(async()=>{try{let R=await ur(f,[],{npmRegistry:this.npmRegistry}),C=await of({agentId:s,cwd:t.cwd??D.sessionDir(e),plan:R,history:a,modelId:u,sessionId:e,logger:this.logger,timeoutMs:p});C&&C.synopsis?await this.mutateRecord(v,{synopsis:C.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(v,{},["forkSynthesisState"]))}catch(R){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${R.message}`);try{await this.mutateRecord(v,{},["forkSynthesisState"])}catch(C){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${C.message}`)}}})(),{sessionId:v,forkedFromSessionId:e,forkedAt:d}}async writeImportedRecord(e){if(await this.histories.rewrite(e.sessionId,e.bundle.history),e.bundle.toolBlobs)for(let[o,i]of Object.entries(e.bundle.toolBlobs))await Ev(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await Ci.utimes(D.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await Si(D.tuiHistoryFile(e.sessionId),e.bundle.promptHistory).catch(()=>{});let r=new Date().toISOString(),s=e.forkedFromSessionId!==void 0;await this.enqueueMetaWrite(e.sessionId,async()=>{await this.store.write({sessionId:e.sessionId,lineageId:e.bundle.session.lineageId,upstreamSessionId:"",...s?{forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId}:{importedFromSessionId:e.bundle.session.sessionId,importedFromUpstreamSessionId:e.bundle.session.upstreamSessionId,importedFromMachine:e.bundle.exportedFrom.machine},agentId:e.bundle.session.agentId,cwd:e.cwd??e.bundle.session.cwd,workspace:e.workspace,title:e.bundle.session.title,synopsis:e.bundle.session.synopsis,summarizedThroughEntry:e.bundle.session.summarizedThroughEntry,...e.forkSynthesisState!==void 0?{forkSynthesisState:e.forkSynthesisState}:{},currentModel:e.bundle.session.currentModel,currentMode:e.bundle.session.currentMode,currentUsage:e.bundle.session.currentUsage,agentCommands:e.bundle.session.agentCommands,agentModes:e.bundle.session.agentModes,interactive:e.bundle.session.interactive,originatingClient:e.bundle.session.originatingClient,priority:e.bundle.session.priority,attentionFlags:[],createdAt:e.preservedCreatedAt??r,updatedAt:e.bundle.session.updatedAt})})}async tombstoneAllGenerations(e,t,r){let s=await this.store.read(e).catch(()=>{}),o=new Map;for(let a of s?.upstreamGenerations??[])a.upstreamSessionId&&o.set(`${a.agentId}::${a.upstreamSessionId}`,{agentId:a.agentId,upstreamSessionId:a.upstreamSessionId});o.set(`${t.agentId}::${t.upstreamSessionId}`,{agentId:t.agentId,upstreamSessionId:t.upstreamSessionId});let i=new Date().toISOString();for(let a of o.values())await this.tombstones.add({agentId:a.agentId,upstreamSessionId:a.upstreamSessionId,deletedAt:i,upstreamUpdatedAt:t.upstreamUpdatedAt,cwd:t.cwd,...t.title!==void 0?{title:t.title}:{},reason:r,...t.interactive!==void 0?{interactive:t.interactive}:{}}).catch(()=>{})}async deleteRecord(e,t="user"){let r=await this.store.read(e);if(!r)return!1;if(r.upstreamSessionId){let s=await Uc(e),o=od(r,s.hasContent);await this.tombstoneAllGenerations(e,{agentId:r.agentId,upstreamSessionId:r.upstreamSessionId,upstreamUpdatedAt:r.updatedAt,cwd:r.cwd,...r.title!==void 0?{title:r.title}:{},...o!==void 0?{interactive:o}:{}},t)}return r.workspace!==void 0&&await this.releaseWorkspace(r.workspace,e).catch(()=>{}),await this.store.delete(e).catch(()=>{}),await this.histories.delete(e).catch(()=>{}),this.invalidateListCache(),!0}async waitForDeletion(e){let t=this.pendingDeletions.get(e);t&&await t}async isTombstoned(e,t){return(await this.tombstones.read(e,t).catch(()=>{}))?.reason==="user"}async hasRecord(e){return await this.store.read(e).catch(()=>{})!==void 0}async clearWorkspaceBinding(e){if(this.get(e)!==void 0)return"live";let t=await this.store.read(e).catch(()=>{});if(!t)return"missing";let r=t.workspace?.sourceCwd;return await this.mutateRecord(e,r!==void 0?{cwd:r}:{},["workspace"]),"cleared"}async setCwd(e,t){if(this.get(e)!==void 0)return"live";let r=await this.store.read(e).catch(()=>{});return r?r.workspace!==void 0?"bound":await this.dirExists(t)?(await this.mutateRecord(e,{cwd:t}),this.invalidateListCache(),"set"):"not-a-directory":"missing"}async setPriority(e,t){let r=this.get(e);if(r)return r.setPriority(t),!0;if(!await this.hasRecord(e))return!1;let s=t===void 0||t<=0?void 0:Math.floor(t);return await this.persistPriority(e,s),!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 r=this.get(e);return r?(await r.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,r){await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:r})}async persistAgentChange(e,t,r,s,o,i){await this.mutateRecord(e,{agentId:t,upstreamSessionId:r},void 0,a=>({upstreamGenerations:Ux(a,t,r,void 0,s,o,i)}))}async persistSnapshot(e,t){let r={};t.currentModel!==void 0&&(r.currentModel=t.currentModel),t.currentMode!==void 0&&(r.currentMode=t.currentMode),t.currentUsage!==void 0&&(r.currentUsage=t.currentUsage),t.agentCommands!==void 0&&(r.agentCommands=t.agentCommands),t.agentModes!==void 0&&(r.agentModes=t.agentModes),t.agentModels!==void 0&&(r.agentModels=t.agentModels),t.interactive!==void 0&&(r.interactive=t.interactive),t.cwd!==void 0&&(r.cwd=t.cwd),await this.mutateRecord(e,r)}async mutateRecord(e,t,r=[],s){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o,...t,...s?s(o):{},updatedAt:new Date().toISOString()};for(let a of r)delete i[a];await this.store.write(i)})}static EXTENSION_STATE_CAP_BYTES=64*1024;async getExtensionState(e,t){return(await this.store.read(e))?.extensionState?.[t]??{}}async getExtensionStateKey(e,t,r){return(await this.getExtensionState(e,t))[r]}async setExtensionStateKey(e,t,r,s){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o.extensionState??{}},a={...i[t]??{},[r]:s},d=Buffer.byteLength(JSON.stringify(a),"utf8");if(d>n.EXTENSION_STATE_CAP_BYTES)throw new Error(`extension_state: bucket for ${t} would be ${d} bytes; cap is ${n.EXTENSION_STATE_CAP_BYTES}`);i[t]=a;let c={...o,extensionState:i,updatedAt:new Date().toISOString()};await this.store.write(c)})}async deleteExtensionStateKey(e,t,r){await this.enqueueMetaWrite(e,async()=>{let s=await this.store.read(e);if(!s?.extensionState?.[t])return;let o={...s.extensionState},i={...o[t]};if(!(r in i))return;delete i[r],Object.keys(i).length===0?delete o[t]:o[t]=i;let a={...s,extensionState:o,updatedAt:new Date().toISOString()};await this.store.write(a)})}enqueueMetaWrite(e,t){return this.enqueueKeyed(this.metaWriteQueues,e,t)}enqueueKeyed(e,t,r){let o=(e.get(t)??Promise.resolve()).catch(()=>{}).then(r),i=o.catch(()=>{});return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)}),o}liveSessionsIn(e,t){let r=[];for(let s of this.sessions.values())s.sessionId!==t&&s.workspace?.path===e&&r.push(s);return r}async closeAll(){let e=[...this.sessions.values()];await Promise.allSettled(e.map(t=>t.close({deleteRecord:!1,by:"daemon-shutdown"}))),this.sessions.clear()}async flushSynopsis(e){await this.synopsisCoordinator.flush(e)}async shutdownSynopsis(){await this.synopsisCoordinator.shutdown()}scheduleSynopsis(e){this.synopsisCoordinator.schedule(e)}scheduleCompaction(e,t){if(t?.targetAgentId){this.mutateRecord(e,{pendingAgentSwap:t.targetAgentId}).catch(s=>{this.logger?.warn(`scheduleCompaction: failed to stamp pendingAgentSwap for ${e}: ${s instanceof Error?s.message:String(s)}`)});let r=t.targetAgentId;(async()=>{try{let s=await this.store.read(e);if(!s?.synopsis||s.summarizedThroughEntry===void 0){this.synopsisCoordinator.scheduleCompaction(e,t);return}if((await this.histories.load(e,{maxEntries:1/0})).length!==s.summarizedThroughEntry){this.synopsisCoordinator.scheduleCompaction(e,t);return}this.logger?.info(`compaction: fast-path swap sessionId=${e} target=${r} (reusing artifact @${s.summarizedThroughEntry})`),await this.dispatchSynthesisSwap(e,s.synopsis,s.summarizedThroughEntry,r)}catch(s){this.logger?.warn(`scheduleCompaction: fast-path check failed for ${e}: ${s instanceof Error?s.message:String(s)} \u2014 falling back to synthesis`),this.synopsisCoordinator.scheduleCompaction(e,t)}})();return}this.synopsisCoordinator.scheduleCompaction(e,t)}getCompactionInFlight(){let e=this.synopsisCoordinator.size();return e.inflight>0||e.queued>0}async getPendingAgentSwap(e){return(await this.store.read(e).catch(()=>{}))?.pendingAgentSwap}async getCompactionState(e){return(await this.store.read(e).catch(()=>{}))?.compactionState}async persistRollbackBreadcrumb(e,t){await this.mutateRecord(e,{},void 0,r=>{let s=r.rollbackBreadcrumb;return s!==void 0&&t.runId!==void 0&&s.runId===t.runId?(this.logger?.info(`compaction: keeping rollback breadcrumb pinned at ${s.previousUpstreamSessionId} for runId=${t.runId} sessionId=${e} (later swap of the same run)`),{}):{rollbackBreadcrumb:t}})}async getUpstreamGenerations(e){return(await this.store.read(e).catch(()=>{}))?.upstreamGenerations??[]}async getRollbackBreadcrumb(e){return(await this.store.read(e).catch(()=>{}))?.rollbackBreadcrumb}emitSwapPhase(e,t,r){let s=this.get(e);if(s){if(t){let o=r.phase==="failed";s.broadcastPendingAgentSwap(o?null:t);return}s.broadcastCompactionPhase(r)}}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 r of e){let s=r.attentionFlags??[],o=s.filter(i=>!(i.source==="daemon"&&i.reason.startsWith("permission:")));if(o.length!==s.length){let i=s.length-o.length;t+=i,await this.mutateRecord(r.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 r of t){let s=r.compactionState;if(s!=null){if(!e.has(s.status)){this.logger?.info(`compaction: not resuming sessionId=${r.sessionId} status=${s.status} (terminal \u2014 user must re-trigger explicitly)`);continue}this.logger?.info(`compaction: resuming sessionId=${r.sessionId} status=${s.status} from prior daemon`);try{this.scheduleCompaction(r.sessionId)}catch(o){this.logger?.warn(`compaction: resume failed for sessionId=${r.sessionId}: ${o instanceof Error?o.message:String(o)}`)}}}}async resumePendingAgentSwaps(){let e=await this.store.list().catch(()=>[]);for(let t of e){let r=t.pendingAgentSwap;if(r)try{let s=await this.histories.load(t.sessionId).catch(()=>[]);t.synopsis!==void 0&&t.summarizedThroughEntry!==void 0&&t.summarizedThroughEntry>=s.length&&t.synopsis?(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${r} with persisted synopsis (history=${s.length})`),await this.dispatchSynthesisSwap(t.sessionId,t.synopsis,t.summarizedThroughEntry??s.length,r)):(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${r} via fresh synthesis (history=${s.length} watermark=${t.summarizedThroughEntry??"(none)"})`),this.scheduleCompaction(t.sessionId,{targetAgentId:r}))}catch(s){this.logger?.warn(`agent-swap: resume failed for sessionId=${t.sessionId}: ${s instanceof Error?s.message:String(s)}`)}}}async resurrectPendingQueues(){let e=await this.store.list().catch(()=>[]);for(let t of e){let r=await FS(t.sessionId).catch(()=>[]);if(r.length===0)continue;let s=Date.now(),o=r.filter(d=>s-d.enqueuedAt<Ox),i=r.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${Ox/1e3}s)`),await Ac(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 Ac(t.sessionId,[]).catch(()=>{});continue}try{let d=await this.resurrect(a);this.logger?.info(`queue replay: resurrected ${t.sessionId} and replaying ${o.length} prompt(s)`),d.replayPersistedQueue(o)}catch(d){this.logger?.warn(`queue replay: failed to resurrect ${t.sessionId}: ${d.message}`)}}}};function DO(n,e){if(typeof n!="string"||n.length===0)return!1;let t=Wc.resolve(n),r=Wc.resolve(e);return t===r||t.startsWith(r+Wc.sep)}function Fx(n,e){if(n===void 0||n.length===0)return!0;let t=Jg(n);if(Jg(e.cwd)===t)return!0;let r=e.workspace?.sourceCwd;return r!==void 0&&Jg(r)===t}function Jg(n){return n.length>1&&n.endsWith("/")?n.replace(/\/+$/,""):n}function HO(n,e){let r=(n.mergedAvailableCommands().length>0?n.agentOnlyAdvertisedCommands().map(l=>l.description!==void 0?{name:l.name,description:l.description}:{name:l.name}):void 0)??e?.agentCommands,s=n.availableModes(),i=(s.length>0?s.map(l=>{let u={id:l.id};return l.name!==void 0&&(u.name=l.name),l.description!==void 0&&(u.description=l.description),u}):void 0)??e?.agentModes,a=n.availableModels(),c=(a.length>0?a.map(l=>{let u={modelId:l.modelId};return l.name!==void 0&&(u.name=l.name),l.description!==void 0&&(u.description=l.description),u}):void 0)??e?.agentModels;return Pg({sessionId:n.sessionId,lineageId:e?.lineageId??Pc(),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:Hx(n.persistableUsage)??e?.currentUsage,agentCommands:r,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,workspace:n.workspace,attentionFlags:n.listAttentionFlags(),extensionState:e?.extensionState,upstreamGenerations:e?Ux(e,n.agentId,n.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(n.createdAt).toISOString()})}function Hx(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 UO(n){return n?{...n}:void 0}function Yg(n,e={}){if(n!=="claude-acp")return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t}}}function pf(n,e){let t=e.fromObject(n);if(t!==void 0)return t;let r=n[e.nestedKey];if(r&&typeof r=="object"&&!Array.isArray(r)){let i=e.fromObject(r);if(i!==void 0)return i}let s=n._meta;if(s&&typeof s=="object"&&!Array.isArray(s)){for(let[i,a]of Object.entries(s))if(i!=="hydra-acp"&&a&&typeof a=="object"&&!Array.isArray(a)){let d=e.fromObject(a);if(d!==void 0)return d}}let o=WO(n,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function Qg(n){return pf(n,{nestedKey:"models",configId:"model",fromObject:e=>fs(e.currentModelId)??fs(e.currentModel)??fs(e.modelId)??fs(e.model),fromConfig:e=>fs(e.currentValue)})}function Co(n,e){if(!n||typeof n!="object")return n;let t=n;if(t.code!==V.AuthRequired)return n;let r=c=>!!c&&typeof c=="object"&&!Array.isArray(c),s=r(t.data)?t.data:{},o=r(s._meta)?s._meta:{},i=r(o["hydra-acp"])?o["hydra-acp"]:{},a=typeof t.message=="string"?t.message:"authentication required",d=new Error(a);return d.code=V.AuthRequired,d.data={...s,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function Lx(n){return/^[A-Za-z0-9_\-./=:@]+$/.test(n)?n:`'${n.replace(/'/g,"'\\''")}'`}function Nx(n,e,t,r){if(n&&typeof n=="object"&&n.code===V.AuthRequired)return n;let s=n instanceof Error?n.message:String(n),o=s.includes("stderr:"),i=o?"":e.stderrTailText(),a=r?`to reproduce: (cd ${Lx(r.cwd)} && ${[r.command,...r.args].map(Lx).join(" ")})`:"";if(!i&&!a)return n;let d=[o?s:`agent ${t} failed to start: ${s}`];i&&d.push(`stderr: ${i}`),a&&d.push(a);let c=new Error(d.join(`
|
|
355
|
+
`)}async copyCarriedWork(e,t,r){let s=await this.patchFromSnapshot(r,t,e.provider);if(s===void 0)return!1;if(s.length===0)return!0;let o=Me(e.provider);return o===void 0?!1:(await o.applyDelta(e.path,s)).ok}async patchFromSnapshot(e,t,r){let s=Me(r);if(s===void 0)return;let o=await s.currentState(e);if(o!==void 0)return await s.captureDelta(e,o,t).catch(()=>{})}async unwindStartWorkspace(e){let{provider:t,ws:r,startRef:s,carried:o}=e;await t.unlock(r).catch(()=>{}),o!==void 0&&await t.dropSnapshotRef(r,s).catch(()=>{}),await t.removeWorkspace(r,{force:!0}).catch(()=>{})}async materializeNestedTrees(e,t){let r=Me(e.provider);if(r?.capabilities().supports.nestedTrees!==!0)return;let s=await r.materializeNested({path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:r.kind},t).catch(o=>({ok:!1,count:0,reason:o instanceof Error?o.message:String(o)}));return s.ok?s.count>0?`populated ${s.count} nested tree(s)`:void 0:`nested trees FAILED: ${s.reason??"unknown"}`}async applyWorkspaceSetup(e,t){let r=await tf(e.sourceCwd).catch(()=>({})),s=[];if(r.carry!==void 0&&r.carry.length>0){let o=await Bg(e.sourceCwd,e.path,r.carry).catch(()=>{});o!==void 0&&o.copied.length>0&&s.push(`carried ${o.copied.length} config file(s)`)}if(r.postCreate!==void 0){let o=await nf(r.postCreate,{workspacePath:e.path,sourceCwd:e.sourceCwd,label:e.label,sessionId:t,...r.hookTimeoutSeconds!==void 0?{timeoutSeconds:r.hookTimeoutSeconds}:{}});s.push(o.ok?"ran postCreate":`postCreate FAILED: ${o.reason??"unknown"}`)}return s.length>0?s.join("; "):void 0}async deriveForkWorkspace(e,t){let r=Me(e.provider);if(r===void 0)return;let s=r.capabilities(),o=s.sharedHistory?await r.currentState(e.path)??"":"",i=await r.createWorkspace({sourceCwd:e.sourceCwd,label:t,...o.length>0?{from:o}:{contentFrom:e.path}}).catch(d=>({ok:!1,reason:String(d)}));if(!i.ok){this.logger?.warn?.(`fork workspace: could not derive from ${e.path}: ${i.reason}`);return}let a=i.workspace;if(o.length>0&&s.supports.captureWorkingState){let d=await r.captureWorkingState(e.path,`hydra: fork carry from ${e.label}`).catch(()=>{});d!==void 0&&d!==o&&await this.copyUncommittedInto(e.path,a.path,o,d,a.provider).catch(()=>{})}return{path:a.path,sourceCwd:a.sourceCwd,label:a.label,provider:a.provider,...a.snapshot!==void 0?{snapshot:a.snapshot}:{},...a.line!==void 0?{line:a.line}:{},...a.vcs!==void 0?{vcs:{...a.vcs}}:{}}}async copyUncommittedInto(e,t,r,s,o){let i=Me(o);if(i===void 0)return!1;let a=await i.captureDelta(e,r,s).catch(()=>{});return a===void 0||a.trim().length===0?!1:(await i.applyDelta(t,a,{stage:!0})).ok}async recoverWorkspace(e){let t=Me(e.provider);if(t===void 0)return;let r={path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:e.provider,...e.snapshot!==void 0?{snapshot:e.snapshot}:{},...e.vcs!==void 0?{vcs:e.vcs}:{}};if(t.capabilities().supports.rematerialize){let o=await t.rematerialize(r).catch(i=>({ok:!1,reason:String(i)}));if(o.ok)return this.logger?.info?.(`session workspace: restored ${o.workspace.path} from retained state`),{...e,path:o.workspace.path};this.logger?.warn?.(`session workspace: could not restore: ${o.reason}`)}if(!await this.dirExists(e.sourceCwd))return;let s=await t.createWorkspace({sourceCwd:e.sourceCwd,label:`${e.label}-r`}).catch(o=>({ok:!1,reason:String(o)}));if(s.ok)return this.logger?.warn?.(`session workspace: ${e.path} is gone and could not be restored; resurrecting in a fresh workspace ${s.workspace.path} from ${e.sourceCwd}. Uncommitted work from the old workspace is not recoverable.`),{path:s.workspace.path,sourceCwd:s.workspace.sourceCwd,label:s.workspace.label,provider:s.workspace.provider,...s.workspace.snapshot!==void 0?{snapshot:s.workspace.snapshot}:{},...s.workspace.vcs!==void 0?{vcs:{...s.workspace.vcs}}:{}}}async syncFromAgent(e){let t=await this.registry.getAgent(e);if(!t){let p=new Error(`agent ${e} not found in registry`);throw p.code=V.AgentNotInstalled,p}let r=await ur(t,[],{npmRegistry:this.npmRegistry}),s=this.spawner({agentId:e,cwd:Dx.homedir(),plan:r}),o;try{o=await s.connection.request("initialize",{protocolVersion:1,clientCapabilities:Wa,clientInfo:{name:"hydra",version:_e}})}catch(p){throw await s.kill().catch(()=>{}),Co(p,s)}if(s.authMethods=Hc(o.authMethods),(o.agentCapabilities??{}).sessionCapabilities?.list===void 0)throw await s.kill().catch(()=>{}),new Error(`agent ${e} does not advertise sessionCapabilities.list; cannot sync`);let a;try{a=await this.collectAgentSessions(s)}catch(p){throw await s.kill().catch(()=>{}),p}await s.kill().catch(()=>{});let d=new Set;for(let p of this.sessions.values())d.add(`${p.agentId}::${p.upstreamSessionId}`);let c=await this.store.list().catch(()=>[]);for(let p of c){d.add(`${p.agentId}::${p.upstreamSessionId}`);for(let h of p.upstreamGenerations??[])d.add(`${h.agentId}::${h.upstreamSessionId}`)}let l=D.sessionsDir(),u=[],f=0;for(let p of a){let h=`${e}::${p.sessionId}`;if(d.has(h)){f+=1;continue}if(DO(p.cwd,l)){f+=1;continue}let m=await this.tombstones.read(e,p.sessionId).catch(()=>{});if(m){if(!ux(m,p.updatedAt)){f+=1;continue}await this.tombstones.remove(e,p.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${p.sessionId} (upstream updatedAt advanced past ${m.upstreamUpdatedAt??"<unset>"})`)}d.add(h);let y=`${fn}${sd()}`,w=new Date().toISOString(),v=p.updatedAt??w,b={sessionId:y,lineageId:Pc(),upstreamSessionId:p.sessionId,agentId:e,cwd:p.cwd,pendingHistorySync:!0,interactive:!0,createdAt:v,updatedAt:v};p.title!==void 0&&(b.title=p.title);let S=Pg(b);await this.store.write(S),u.push({version:1,...S})}return{synced:u,skipped:f}}async collectAgentSessions(e){let t=[],r,s=new Set;for(let o=0;o<100;o+=1){let i={};r!==void 0&&(i.cursor=r);let a=await e.connection.request("session/list",i),d=Array.isArray(a.sessions)?a.sessions:[];for(let c of d){if(typeof c.sessionId!="string"||typeof c.cwd!="string")continue;let l={sessionId:c.sessionId,cwd:c.cwd};typeof c.title=="string"&&(l.title=c.title),typeof c.updatedAt=="string"&&(l.updatedAt=c.updatedAt),t.push(l)}if(typeof a.nextCursor!="string"||a.nextCursor.length===0||s.has(a.nextCursor))break;s.add(a.nextCursor),r=a.nextCursor}return t}async applySeedModel(e,t,r,s,o){try{let{verb:i}=await xo({request:(a,d)=>e.connection.request(a,d),sessionId:t,modelId:r,...o?{verb:o}:{},logger:this.logger});return this.logger?.info(`${s}: ${i} accepted`),!0}catch(i){return this.logger?.warn(`${s} rejected by agent (${i.message}); session will use the agent's own default`),!1}}async bootstrapAgent(e){let t=await this.registry.getAgent(e.agentId);if(!t){let i=new Error(`agent ${e.agentId} not found in registry`);throw i.code=V.AgentNotInstalled,i}let r=await ur(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),s=Iu(e.selfSessionId,e.forwardedEnv),o=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:r,...s?{extraEnv:s}:{}});try{let i=await o.connection.request("initialize",{protocolVersion:1,clientCapabilities:Wa,clientInfo:{name:"hydra",version:_e}}),a=i.agentCapabilities;o.authMethods=Hc(i.authMethods);let d=Yg(e.agentId),c=await o.connection.request("session/new",{cwd:e.cwd,mcpServers:e.mcpServers??[],...d&&{_meta:d}}),l=c.sessionId;if(typeof l!="string")throw new Error(`agent ${e.agentId} returned a non-string sessionId from session/new`);let u=Qg(c),f=Zg(c),p=ja(c),h=e.model??this.defaultModels[e.agentId];if(h&&h!==u){let w=Va(h,f),v=e.model!==void 0?`model=${JSON.stringify(h)}`:`defaultModels[${e.agentId}]=${JSON.stringify(h)}`;if(w.kind==="exact"||w.kind==="none")await this.applySeedModel(o,l,h,v,p)&&(u=h);else if(w.kind==="resolved")(w.modelId===u||await this.applySeedModel(o,l,w.modelId,`${v} resolved to ${JSON.stringify(w.modelId)}`,p))&&(u=w.modelId);else if(w.kind==="ambiguous")this.logger?.warn(`${v} is ambiguous (trailing-segment matches [${w.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(u)}`);else{let b=f.map(S=>S.modelId).join(", ");this.logger?.warn(`${v} not in agent's availableModels ([${b}]); skipping session/set_model, session will use ${JSON.stringify(u)}`)}}let m=ey(c),y=ty(c);return{agent:o,upstreamSessionId:l,agentMeta:c._meta,agentCapabilities:a,initialModel:u,initialModels:f.length>0?f:void 0,initialModes:m.length>0?m:void 0,initialMode:y,modelVerb:p}}catch(i){throw await o.kill().catch(()=>{}),Co(Nx(i,o,e.agentId,{command:r.command,args:r.args,cwd:e.cwd}),o)}}async bootstrapAgentLoad(e,t){let r=await this.registry.getAgent(t.agentId);if(!r){let a=new Error(`agent ${t.agentId} not found in registry`);throw a.code=V.AgentNotInstalled,a}let s=await ur(r,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=Iu(t.selfSessionId,t.forwardedEnv),i=this.spawner({agentId:t.agentId,cwd:t.cwd,plan:s,...o?{extraEnv:o}:{}});try{let a=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:Wa,clientInfo:{name:"hydra",version:_e}}),d=a.agentCapabilities;i.authMethods=Hc(a.authMethods);let c=Yg(t.agentId),l=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),u=Qg(l),f=Xg(Zg(l)),p=ey(l),h=ty(l);return{agent:i,upstreamSessionId:e,agentMeta:l._meta,agentCapabilities:d,initialModel:u,initialModels:f,initialModes:p.length>0?p:void 0,initialMode:h,modelVerb:ja(l)}}catch(a){throw await i.kill().catch(()=>{}),Co(Nx(a,i,t.agentId,{command:s.command,args:s.args,cwd:t.cwd}),i)}}async performUncompact(e){if(this.rollbackLocks.has(e))throw new Error("a rollback is already in progress for this session");let t=this.get(e);if(!t)throw new Error("session is not live \u2014 cannot roll back a cold session");let r=await this.store.read(e);if(!r)throw new Error("session record not found");let s=r.rollbackBreadcrumb;if(!s)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=r.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:s.previousUpstreamSessionId,previousSummarizedThroughEntry:s.previousSummarizedThroughEntry}),await this.mutateRecord(e,{summarizedThroughEntry:s.previousSummarizedThroughEntry},["synopsis","rollbackBreadcrumb"])}finally{this.rollbackLocks.delete(e)}}async bootstrapAgentForAuth(e,t){let r=this.pendingAuthAgents.get(e);if(r&&r.isAlive())return r;let s=await this.registry.getAgent(e);if(!s){let d=new Error(`agent ${e} not found in registry`);throw d.code=V.AgentNotInstalled,d}let o=await ur(s,[],{npmRegistry:this.npmRegistry}),i=t??yt(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let d=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:Wa,clientInfo:{name:"hydra",version:_e}});a.authMethods=Hc(d.authMethods)}catch(d){throw await a.kill().catch(()=>{}),Co(d,a)}return this.pendingAuthAgents.set(e,a),a.onExit(()=>{this.pendingAuthAgents.get(e)===a&&this.pendingAuthAgents.delete(e)}),a}async planSpawnForAgent(e){let t=await this.registry.getAgent(e);if(!t){let r=new Error(`agent ${e} not found in registry`);throw r.code=V.AgentNotInstalled,r}return ur(t,[],{npmRegistry:this.npmRegistry})}consumePendingAuthAgent(e){let t=this.pendingAuthAgents.get(e);if(t&&(this.pendingAuthAgents.delete(e),!!t.isAlive()))return t}getAgentForSession(e){return this.sessions.get(e)?.agent}async attachManagerHooks(e){e.onClose(({deleteRecord:t})=>{if(this.sessions.delete(e.sessionId),this.driftNoticed.delete(e.sessionId),this.invalidateListCache(),t&&e.workspace!==void 0&&this.releaseWorkspace(e.workspace,e.sessionId).catch(()=>{}),t){if(e.upstreamSessionId){let s=od({interactive:e.interactive,...e.originatingClient?{originatingClient:e.originatingClient}:{}},!0),o=this.tombstoneAllGenerations(e.sessionId,{agentId:e.agentId,upstreamSessionId:e.upstreamSessionId,upstreamUpdatedAt:new Date(e.updatedAt).toISOString(),cwd:e.cwd,...e.title!==void 0?{title:e.title}:{},...s!==void 0?{interactive:s}:{}},"user").catch(()=>{}).then(()=>this.store.delete(e.sessionId).catch(()=>{})).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===o&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,o);return}let r=this.store.delete(e.sessionId).catch(()=>{}).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===r&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,r);return}}),e.onTitleChange(t=>{this.persistTitle(e.sessionId,t).catch(()=>{})}),e.onPriorityChange(t=>{this.persistPriority(e.sessionId,t).catch(()=>{})}),e.onAgentChange(({agentId:t,upstreamSessionId:r,retiredCost:s,reason:o,runId:i})=>{this.persistAgentChange(e.sessionId,t,r,s,o,i).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:Hx(t)}).catch(()=>{})}),e.onAgentCommandsChange(t=>{this.persistSnapshot(e.sessionId,{agentCommands:t.map(r=>({name:r.name,...r.description!==void 0?{description:r.description}:{}}))}).catch(()=>{})}),e.onAgentModesChange(t=>{this.persistSnapshot(e.sessionId,{agentModes:t.map(r=>({id:r.id,...r.name!==void 0?{name:r.name}:{},...r.description!==void 0?{description:r.description}:{}}))}).catch(()=>{})}),e.onAgentModelsChange(t=>{this.persistSnapshot(e.sessionId,{agentModels:t.map(r=>({modelId:r.modelId,...r.name!==void 0?{name:r.name}:{},...r.description!==void 0?{description:r.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),r=HO(e,t);await this.store.write(r)}).catch(()=>{})}async getHistory(e){if(this.sessions.has(e))return this.histories.load(e).catch(()=>[]);if(await this.store.read(e))return this.histories.load(e).catch(()=>[])}async loadHistory(e,t={}){return this.histories.load(e,t)}async loadToolBlob(e,t){return bc(e,t)}async loadFromDisk(e){let t=await this.store.read(e);if(!t)return;let r=t.title;return r||(r=await this.deriveTitleFromHistory(e)),{hydraSessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,agentId:t.agentId,cwd:t.cwd,title:r,synopsis:t.synopsis,summarizedThroughEntry:t.summarizedThroughEntry,agentArgs:t.agentArgs,currentModel:t.currentModel,currentMode:t.currentMode,currentUsage:UO(t.currentUsage),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,forwardedEnv:t.forwardedEnv,workspace:t.workspace,compactionState:t.compactionState,attentionFlags:t.attentionFlags?.filter(s=>!(s.source==="daemon"&&s.reason.startsWith("permission:")))}}async setForwardedEnv(e,t){if(t===void 0)return;let r=this.sessions.get(e);r&&(r.forwardedEnv=t),await this.enqueueMetaWrite(e,async()=>{let s=await this.store.read(e);if(!s)return;let o={...s,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 r={...t};delete r.pendingHistorySync,await this.store.write(r)})}async deriveTitleFromHistory(e){let t=await this.histories.load(e).catch(()=>[]);for(let r of t){let s=r.params;if(s?.update?.sessionUpdate!=="prompt_received")continue;let o=s.update.sentBy;if(typeof o?.fromSession=="string"||typeof o?.clientId=="string"&&o.clientId.startsWith("transformer:"))continue;let i=Ya(s.update.prompt),a=Sg(i,200);if(a&&!a.startsWith("/"))return a}}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 r=t.agent.agentId,s=t.agent.version,o=e.get(r);o||(o=new Set,e.set(r,o)),o.add(s)}return e}async resolveCanonicalId(e){if(this.sessions.has(e)||await this.store.read(e))return e;if(e.startsWith(fn))return;let t=fn+e;if(this.sessions.has(t)||await this.store.read(t))return t}require(e){let t=this.sessions.get(e);if(!t){let r=new Error(`session ${e} not found`);throw r.code=V.SessionNotFound,r}return t}liveListEntry(e){return{sessionId:e.sessionId,upstreamSessionId:e.upstreamSessionId,cwd:e.cwd,workspace:e.workspace,workspaceError:e.workspaceError,title:e.title,agentId:e.agentId,currentModel:e.currentModel,currentUsage:e.currentUsage,parentSessionId:e.parentSessionId,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,forkSynthesisState:e.forkSynthesisState,originatingClient:e.originatingClient,interactive:e.interactive,updatedAt:new Date(e.updatedAt).toISOString(),attachedClients:e.attachedCount,status:"warm",busy:e.turnStartedAt!==void 0,armedTasks:e.armedBackgroundTasks.length,...e.armedSince!==void 0?{armedSince:e.armedSince}:{},awaitingInput:e.awaitingInput,agentPid:e.agentPid}}async getOne(e){let t=this.sessions.get(e);if(t){let a=await Uc(t.sessionId),d=od({interactive:t.interactive,...t.originatingClient?{originatingClient:t.originatingClient}:{}},a.hasContent),c=a.mtime??new Date(t.updatedAt).toISOString();return{sessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,cwd:t.cwd,title:t.title,agentId:t.agentId,currentModel:t.currentModel,currentUsage:t.currentUsage,parentSessionId:t.parentSessionId,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,originatingClient:t.originatingClient,interactive:d,priority:t.priority,updatedAt:c,attachedClients:t.attachedCount,status:"warm",agentPid:t.agentPid,busy:t.turnStartedAt!==void 0,armedTasks:t.armedBackgroundTasks.length,...t.armedSince!==void 0?{armedSince:t.armedSince}:{},awaitingInput:t.awaitingInput}}let r=await this.store.read(e).catch(()=>{});if(!r)return;let s=await Uc(r.sessionId),o=od(r,s.hasContent),i=s.mtime??r.updatedAt;return{sessionId:r.sessionId,upstreamSessionId:r.upstreamSessionId,cwd:r.cwd,title:r.title,agentId:r.agentId,currentModel:r.currentModel,currentUsage:Ii(r.currentUsage),importedFromMachine:r.importedFromMachine,importedFromUpstreamSessionId:r.importedFromUpstreamSessionId,parentSessionId:r.parentSessionId,forkedFromSessionId:r.forkedFromSessionId,forkedFromMessageId:r.forkedFromMessageId,forkSynthesisState:r.forkSynthesisState,originatingClient:r.originatingClient,interactive:o,priority:r.priority,updatedAt:i,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1}}async list(e={}){let t=`${e.cwd??""}|${e.includeNonInteractive?"1":"0"}|${e.status??""}`,r=Date.now(),s=this.listCache.get(t);if(s&&s.expiresAt>r)return s.promise;let o=this.listUncached(e);return this.listCache.set(t,{expiresAt:r+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=[],r=new Set,s=l=>e.includeNonInteractive?!0:l===!0,o=[...this.sessions.values()].filter(l=>Fx(e.cwd,l));if(e.status==="cold")for(let l of o)r.add(l.sessionId);let i=e.status==="cold"?[]:await Promise.all(o.map(l=>Uc(l.sessionId)));for(let l=0;l<i.length;l+=1){let u=o[l],f=i[l];r.add(u.sessionId);let p=od({interactive:u.interactive,...u.originatingClient?{originatingClient:u.originatingClient}:{}},f.hasContent);if(!s(p))continue;let h=f.mtime??new Date(u.updatedAt).toISOString();t.push({sessionId:u.sessionId,upstreamSessionId:u.upstreamSessionId,cwd:u.cwd,workspace:u.workspace,workspaceError:u.workspaceError,title:u.title,agentId:u.agentId,currentModel:u.currentModel,currentUsage:u.currentUsage,parentSessionId:u.parentSessionId,forkedFromSessionId:u.forkedFromSessionId,forkedFromMessageId:u.forkedFromMessageId,originatingClient:u.originatingClient,interactive:p,priority:u.priority,updatedAt:h,attachedClients:u.attachedCount,status:"warm",agentPid:u.agentPid,busy:u.turnStartedAt!==void 0,armedTasks:u.armedBackgroundTasks.length,...u.armedSince!==void 0?{armedSince:u.armedSince}:{},awaitingInput:u.awaitingInput,compactionState:u.compactionState,forkSynthesisState:u.forkSynthesisState})}if(e.status==="warm")return t;let d=(await this.store.list().catch(l=>{throw this.logger?.warn(`session list: store.list() failed: ${l?.message??String(l)}`),l})).filter(l=>!r.has(l.sessionId)&&Fx(e.cwd,l)),c=await Promise.all(d.map(l=>Uc(l.sessionId)));for(let l=0;l<d.length;l+=1){let u=d[l],f=c[l],p=od(u,f.hasContent);if(!s(p))continue;let h=f.mtime??u.updatedAt;t.push({sessionId:u.sessionId,upstreamSessionId:u.upstreamSessionId,cwd:u.cwd,workspace:u.workspace,title:u.title,agentId:u.agentId,currentModel:u.currentModel,currentUsage:Ii(u.currentUsage),importedFromMachine:u.importedFromMachine,importedFromUpstreamSessionId:u.importedFromUpstreamSessionId,parentSessionId:u.parentSessionId,forkedFromSessionId:u.forkedFromSessionId,forkedFromMessageId:u.forkedFromMessageId,originatingClient:u.originatingClient,interactive:p,priority:u.priority,updatedAt:h,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,compactionState:u.compactionState,forkSynthesisState:u.forkSynthesisState})}return t.sort((l,u)=>l.updatedAt<u.updatedAt?1:-1),t}async exportBundle(e,t={}){let r=await this.store.read(e);if(!r)return;let s;if(r.lineageId)s=r;else{let c=Pc(),l={...r,lineageId:c};await this.enqueueMetaWrite(e,async()=>{let u=await this.store.read(e);u&&(u.lineageId||await this.store.write({...u,lineageId:c}))}).catch(()=>{}),s=l}let o=t.tools??"inline",i=await this.histories.load(e,o==="references"?{tools:"references"}:{}).catch(()=>[]),a=await Bx(e);if(o!=="references")return{record:s,history:i,promptHistory:a};let d={};for(let c of Tx(i)){let l=await Tv(e,c);l&&(d[c]=l.toString("base64"))}return{record:s,history:i,promptHistory:a,toolBlobs:d}}async importBundle(e,t={}){let r=await this.store.findByLineageId(e.session.lineageId);if(r){if(!t.replace){let i=new Error(`bundle already imported as ${r.sessionId}`);throw i.code=V.BundleAlreadyImported,i.existingSessionId=r.sessionId,i}let o=this.sessions.get(r.sessionId);return o&&await o.close({deleteRecord:!1,by:"bundle-import-overwrite"}).catch(()=>{}),await this.writeImportedRecord({sessionId:r.sessionId,bundle:e,preservedCreatedAt:r.createdAt,cwd:t.cwd}),{sessionId:r.sessionId,importedFromSessionId:e.session.sessionId,replaced:!0}}let s=`${fn}${sd()}`;return await this.writeImportedRecord({sessionId:s,bundle:e,cwd:t.cwd}),{sessionId:s,importedFromSessionId:e.session.sessionId,replaced:!1}}async forkSession(e,t={}){let r=await this.store.read(e);if(!r){let R=new Error(`source session not found: ${e}`);throw R.code=V.SessionNotFound,R}let s=t.agentId??r.agentId,o=s!==r.agentId;if(o&&!await this.registry.getAgent(s)){let C=new Error(`agent ${s} not found in registry`);throw C.code=V.AgentNotInstalled,C}let i=await this.histories.load(e).catch(()=>[]),a=i,d,c=t.mode??"synthesis",l,u,f,p=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let R=Wu(i,t.forkAt);if(R<0){let C=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw C.code=V.InvalidParams,C}d=t.forkAt,a=i.slice(0,R+1)}else{let R=jO(i);R?(d=R.messageId,a=i.slice(0,R.index+1)):(d="",a=i.slice(0,0))}else{if(t.forkAt!==void 0&&t.forkAt!==""){let C=Wu(i,t.forkAt);if(C<0){let T=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw T.code=V.InvalidParams,T}d=t.forkAt,a=i.slice(0,C+1)}else d="",a=i;let R=await this.registry.getAgent(s);if(!R){let C=new Error(`agent ${s} not found in registry`);throw C.code=V.AgentNotInstalled,C}f=R,u=r.currentModel,l="running"}let h=await Bx(e),m=c==="synthesis",y={...r,lineageId:Pc(),agentId:s,interactive:!1,...l!==void 0?{forkSynthesisState:l}:{},summarizedThroughEntry:a.length,...t.title!==void 0?{title:t.title}:{},currentUsage:void 0,...o?{currentModel:void 0,currentMode:void 0,agentCommands:void 0,agentModes:void 0,agentModels:void 0}:{},...t.model!==void 0?{currentModel:t.model}:{}},w=Bc({record:y,history:a,promptHistory:h.length>0?h:void 0,hydraVersion:_e,machine:So()}),v=`${fn}${sd()}`,b=t.cwd,S;if(t.cwd===void 0&&r.workspace!==void 0){let R=await this.deriveForkWorkspace(r.workspace,`${r.workspace.label}-fork-${v.slice(-6)}`);R!==void 0?(S=R,b=R.path):(b=r.workspace.sourceCwd,this.logger?.warn?.(`fork ${v}: could not derive an isolated workspace from ${r.workspace.path}; running unisolated in ${b}`))}return await this.writeImportedRecord({sessionId:v,bundle:w,cwd:b,...S!==void 0?{workspace:S}:{},forkedFromSessionId:e,forkedFromMessageId:d,...l!==void 0?{forkSynthesisState:l}:{}}),m&&(async()=>{try{let R=await ur(f,[],{npmRegistry:this.npmRegistry}),C=await of({agentId:s,cwd:t.cwd??D.sessionDir(e),plan:R,history:a,modelId:u,sessionId:e,logger:this.logger,timeoutMs:p});C&&C.synopsis?await this.mutateRecord(v,{synopsis:C.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(v,{},["forkSynthesisState"]))}catch(R){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${R.message}`);try{await this.mutateRecord(v,{},["forkSynthesisState"])}catch(C){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${C.message}`)}}})(),{sessionId:v,forkedFromSessionId:e,forkedAt:d}}async writeImportedRecord(e){if(await this.histories.rewrite(e.sessionId,e.bundle.history),e.bundle.toolBlobs)for(let[o,i]of Object.entries(e.bundle.toolBlobs))await Ev(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await Ci.utimes(D.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await Si(D.tuiHistoryFile(e.sessionId),e.bundle.promptHistory).catch(()=>{});let r=new Date().toISOString(),s=e.forkedFromSessionId!==void 0;await this.enqueueMetaWrite(e.sessionId,async()=>{await this.store.write({sessionId:e.sessionId,lineageId:e.bundle.session.lineageId,upstreamSessionId:"",...s?{forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId}:{importedFromSessionId:e.bundle.session.sessionId,importedFromUpstreamSessionId:e.bundle.session.upstreamSessionId,importedFromMachine:e.bundle.exportedFrom.machine},agentId:e.bundle.session.agentId,cwd:e.cwd??e.bundle.session.cwd,workspace:e.workspace,title:e.bundle.session.title,synopsis:e.bundle.session.synopsis,summarizedThroughEntry:e.bundle.session.summarizedThroughEntry,...e.forkSynthesisState!==void 0?{forkSynthesisState:e.forkSynthesisState}:{},currentModel:e.bundle.session.currentModel,currentMode:e.bundle.session.currentMode,currentUsage:e.bundle.session.currentUsage,agentCommands:e.bundle.session.agentCommands,agentModes:e.bundle.session.agentModes,interactive:e.bundle.session.interactive,originatingClient:e.bundle.session.originatingClient,priority:e.bundle.session.priority,attentionFlags:[],createdAt:e.preservedCreatedAt??r,updatedAt:e.bundle.session.updatedAt})})}async tombstoneAllGenerations(e,t,r){let s=await this.store.read(e).catch(()=>{}),o=new Map;for(let a of s?.upstreamGenerations??[])a.upstreamSessionId&&o.set(`${a.agentId}::${a.upstreamSessionId}`,{agentId:a.agentId,upstreamSessionId:a.upstreamSessionId});o.set(`${t.agentId}::${t.upstreamSessionId}`,{agentId:t.agentId,upstreamSessionId:t.upstreamSessionId});let i=new Date().toISOString();for(let a of o.values())await this.tombstones.add({agentId:a.agentId,upstreamSessionId:a.upstreamSessionId,deletedAt:i,upstreamUpdatedAt:t.upstreamUpdatedAt,cwd:t.cwd,...t.title!==void 0?{title:t.title}:{},reason:r,...t.interactive!==void 0?{interactive:t.interactive}:{}}).catch(()=>{})}async deleteRecord(e,t="user"){let r=await this.store.read(e);if(!r)return!1;if(r.upstreamSessionId){let s=await Uc(e),o=od(r,s.hasContent);await this.tombstoneAllGenerations(e,{agentId:r.agentId,upstreamSessionId:r.upstreamSessionId,upstreamUpdatedAt:r.updatedAt,cwd:r.cwd,...r.title!==void 0?{title:r.title}:{},...o!==void 0?{interactive:o}:{}},t)}return r.workspace!==void 0&&await this.releaseWorkspace(r.workspace,e).catch(()=>{}),await this.store.delete(e).catch(()=>{}),await this.histories.delete(e).catch(()=>{}),this.invalidateListCache(),!0}async waitForDeletion(e){let t=this.pendingDeletions.get(e);t&&await t}async isTombstoned(e,t){return(await this.tombstones.read(e,t).catch(()=>{}))?.reason==="user"}async hasRecord(e){return await this.store.read(e).catch(()=>{})!==void 0}async clearWorkspaceBinding(e){if(this.get(e)!==void 0)return"live";let t=await this.store.read(e).catch(()=>{});if(!t)return"missing";let r=t.workspace?.sourceCwd;return await this.mutateRecord(e,r!==void 0?{cwd:r}:{},["workspace"]),"cleared"}async setCwd(e,t){if(this.get(e)!==void 0)return"live";let r=await this.store.read(e).catch(()=>{});return r?r.workspace!==void 0?"bound":await this.dirExists(t)?(await this.mutateRecord(e,{cwd:t}),this.invalidateListCache(),"set"):"not-a-directory":"missing"}async setPriority(e,t){let r=this.get(e);if(r)return r.setPriority(t),!0;if(!await this.hasRecord(e))return!1;let s=t===void 0||t<=0?void 0:Math.floor(t);return await this.persistPriority(e,s),!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 r=this.get(e);return r?(await r.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,r){await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:r})}async persistAgentChange(e,t,r,s,o,i){await this.mutateRecord(e,{agentId:t,upstreamSessionId:r},void 0,a=>({upstreamGenerations:Ux(a,t,r,void 0,s,o,i)}))}async persistSnapshot(e,t){let r={};t.currentModel!==void 0&&(r.currentModel=t.currentModel),t.currentMode!==void 0&&(r.currentMode=t.currentMode),t.currentUsage!==void 0&&(r.currentUsage=t.currentUsage),t.agentCommands!==void 0&&(r.agentCommands=t.agentCommands),t.agentModes!==void 0&&(r.agentModes=t.agentModes),t.agentModels!==void 0&&(r.agentModels=t.agentModels),t.interactive!==void 0&&(r.interactive=t.interactive),t.cwd!==void 0&&(r.cwd=t.cwd),await this.mutateRecord(e,r)}async mutateRecord(e,t,r=[],s){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o,...t,...s?s(o):{},updatedAt:new Date().toISOString()};for(let a of r)delete i[a];await this.store.write(i)})}static EXTENSION_STATE_CAP_BYTES=64*1024;async getExtensionState(e,t){return(await this.store.read(e))?.extensionState?.[t]??{}}async getExtensionStateKey(e,t,r){return(await this.getExtensionState(e,t))[r]}async setExtensionStateKey(e,t,r,s){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o.extensionState??{}},a={...i[t]??{},[r]:s},d=Buffer.byteLength(JSON.stringify(a),"utf8");if(d>n.EXTENSION_STATE_CAP_BYTES)throw new Error(`extension_state: bucket for ${t} would be ${d} bytes; cap is ${n.EXTENSION_STATE_CAP_BYTES}`);i[t]=a;let c={...o,extensionState:i,updatedAt:new Date().toISOString()};await this.store.write(c)})}async deleteExtensionStateKey(e,t,r){await this.enqueueMetaWrite(e,async()=>{let s=await this.store.read(e);if(!s?.extensionState?.[t])return;let o={...s.extensionState},i={...o[t]};if(!(r in i))return;delete i[r],Object.keys(i).length===0?delete o[t]:o[t]=i;let a={...s,extensionState:o,updatedAt:new Date().toISOString()};await this.store.write(a)})}enqueueMetaWrite(e,t){return this.enqueueKeyed(this.metaWriteQueues,e,t)}enqueueKeyed(e,t,r){let o=(e.get(t)??Promise.resolve()).catch(()=>{}).then(r),i=o.catch(()=>{});return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)}),o}liveSessionsIn(e,t){let r=[];for(let s of this.sessions.values())s.sessionId!==t&&s.workspace?.path===e&&r.push(s);return r}async closeAll(){let e=[...this.sessions.values()];await Promise.allSettled(e.map(t=>t.close({deleteRecord:!1,by:"daemon-shutdown"}))),this.sessions.clear()}async flushSynopsis(e){await this.synopsisCoordinator.flush(e)}async shutdownSynopsis(){await this.synopsisCoordinator.shutdown()}scheduleSynopsis(e){this.synopsisCoordinator.schedule(e)}scheduleCompaction(e,t){if(t?.targetAgentId){this.mutateRecord(e,{pendingAgentSwap:t.targetAgentId}).catch(s=>{this.logger?.warn(`scheduleCompaction: failed to stamp pendingAgentSwap for ${e}: ${s instanceof Error?s.message:String(s)}`)});let r=t.targetAgentId;(async()=>{try{let s=await this.store.read(e);if(!s?.synopsis||s.summarizedThroughEntry===void 0){this.synopsisCoordinator.scheduleCompaction(e,t);return}if((await this.histories.load(e,{maxEntries:1/0})).length!==s.summarizedThroughEntry){this.synopsisCoordinator.scheduleCompaction(e,t);return}this.logger?.info(`compaction: fast-path swap sessionId=${e} target=${r} (reusing artifact @${s.summarizedThroughEntry})`),await this.dispatchSynthesisSwap(e,s.synopsis,s.summarizedThroughEntry,r)}catch(s){this.logger?.warn(`scheduleCompaction: fast-path check failed for ${e}: ${s instanceof Error?s.message:String(s)} \u2014 falling back to synthesis`),this.synopsisCoordinator.scheduleCompaction(e,t)}})();return}this.synopsisCoordinator.scheduleCompaction(e,t)}getCompactionInFlight(){let e=this.synopsisCoordinator.size();return e.inflight>0||e.queued>0}async getPendingAgentSwap(e){return(await this.store.read(e).catch(()=>{}))?.pendingAgentSwap}async getCompactionState(e){return(await this.store.read(e).catch(()=>{}))?.compactionState}async persistRollbackBreadcrumb(e,t){await this.mutateRecord(e,{},void 0,r=>{let s=r.rollbackBreadcrumb;return s!==void 0&&t.runId!==void 0&&s.runId===t.runId?(this.logger?.info(`compaction: keeping rollback breadcrumb pinned at ${s.previousUpstreamSessionId} for runId=${t.runId} sessionId=${e} (later swap of the same run)`),{}):{rollbackBreadcrumb:t}})}async getUpstreamGenerations(e){return(await this.store.read(e).catch(()=>{}))?.upstreamGenerations??[]}async getRollbackBreadcrumb(e){return(await this.store.read(e).catch(()=>{}))?.rollbackBreadcrumb}emitSwapPhase(e,t,r){let s=this.get(e);if(s){if(t){let o=r.phase==="failed";s.broadcastPendingAgentSwap(o?null:t);return}s.broadcastCompactionPhase(r)}}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 r of e){let s=r.attentionFlags??[],o=s.filter(i=>!(i.source==="daemon"&&i.reason.startsWith("permission:")));if(o.length!==s.length){let i=s.length-o.length;t+=i,await this.mutateRecord(r.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 r of t){let s=r.compactionState;if(s!=null){if(!e.has(s.status)){this.logger?.info(`compaction: not resuming sessionId=${r.sessionId} status=${s.status} (terminal \u2014 user must re-trigger explicitly)`);continue}this.logger?.info(`compaction: resuming sessionId=${r.sessionId} status=${s.status} from prior daemon`);try{this.scheduleCompaction(r.sessionId)}catch(o){this.logger?.warn(`compaction: resume failed for sessionId=${r.sessionId}: ${o instanceof Error?o.message:String(o)}`)}}}}async resumePendingAgentSwaps(){let e=await this.store.list().catch(()=>[]);for(let t of e){let r=t.pendingAgentSwap;if(r)try{let s=await this.histories.load(t.sessionId).catch(()=>[]);t.synopsis!==void 0&&t.summarizedThroughEntry!==void 0&&t.summarizedThroughEntry>=s.length&&t.synopsis?(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${r} with persisted synopsis (history=${s.length})`),await this.dispatchSynthesisSwap(t.sessionId,t.synopsis,t.summarizedThroughEntry??s.length,r)):(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${r} via fresh synthesis (history=${s.length} watermark=${t.summarizedThroughEntry??"(none)"})`),this.scheduleCompaction(t.sessionId,{targetAgentId:r}))}catch(s){this.logger?.warn(`agent-swap: resume failed for sessionId=${t.sessionId}: ${s instanceof Error?s.message:String(s)}`)}}}async resurrectPendingQueues(){let e=await this.store.list().catch(()=>[]);for(let t of e){let r=await FS(t.sessionId).catch(()=>[]);if(r.length===0)continue;let s=Date.now(),o=r.filter(d=>s-d.enqueuedAt<Ox),i=r.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${Ox/1e3}s)`),await Ac(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 Ac(t.sessionId,[]).catch(()=>{});continue}try{let d=await this.resurrect(a);this.logger?.info(`queue replay: resurrected ${t.sessionId} and replaying ${o.length} prompt(s)`),d.replayPersistedQueue(o)}catch(d){this.logger?.warn(`queue replay: failed to resurrect ${t.sessionId}: ${d.message}`)}}}};function DO(n,e){if(typeof n!="string"||n.length===0)return!1;let t=Wc.resolve(n),r=Wc.resolve(e);return t===r||t.startsWith(r+Wc.sep)}function Fx(n,e){if(n===void 0||n.length===0)return!0;let t=Jg(n);if(Jg(e.cwd)===t)return!0;let r=e.workspace?.sourceCwd;return r!==void 0&&Jg(r)===t}function Jg(n){return n.length>1&&n.endsWith("/")?n.replace(/\/+$/,""):n}function HO(n,e){let r=(n.mergedAvailableCommands().length>0?n.agentOnlyAdvertisedCommands().map(l=>l.description!==void 0?{name:l.name,description:l.description}:{name:l.name}):void 0)??e?.agentCommands,s=n.availableModes(),i=(s.length>0?s.map(l=>{let u={id:l.id};return l.name!==void 0&&(u.name=l.name),l.description!==void 0&&(u.description=l.description),u}):void 0)??e?.agentModes,a=n.availableModels(),c=(a.length>0?a.map(l=>{let u={modelId:l.modelId};return l.name!==void 0&&(u.name=l.name),l.description!==void 0&&(u.description=l.description),u}):void 0)??e?.agentModels;return Pg({sessionId:n.sessionId,lineageId:e?.lineageId??Pc(),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:Hx(n.persistableUsage)??e?.currentUsage,agentCommands:r,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,workspace:n.workspace,attentionFlags:n.listAttentionFlags(),extensionState:e?.extensionState,upstreamGenerations:e?Ux(e,n.agentId,n.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(n.createdAt).toISOString()})}function Hx(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 UO(n){return n?{...n}:void 0}function Yg(n,e={}){if(n!=="claude-acp")return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t}}}function pf(n,e){let t=e.fromObject(n);if(t!==void 0)return t;let r=n[e.nestedKey];if(r&&typeof r=="object"&&!Array.isArray(r)){let i=e.fromObject(r);if(i!==void 0)return i}let s=n._meta;if(s&&typeof s=="object"&&!Array.isArray(s)){for(let[i,a]of Object.entries(s))if(i!=="hydra-acp"&&a&&typeof a=="object"&&!Array.isArray(a)){let d=e.fromObject(a);if(d!==void 0)return d}}let o=WO(n,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function Qg(n){return pf(n,{nestedKey:"models",configId:"model",fromObject:e=>fs(e.currentModelId)??fs(e.currentModel)??fs(e.modelId)??fs(e.model),fromConfig:e=>fs(e.currentValue)})}function Co(n,e){if(!n||typeof n!="object")return n;let t=n;if(t.code!==V.AuthRequired)return n;let r=c=>!!c&&typeof c=="object"&&!Array.isArray(c),s=r(t.data)?t.data:{},o=r(s._meta)?s._meta:{},i=r(o["hydra-acp"])?o["hydra-acp"]:{},a=typeof t.message=="string"?t.message:"authentication required",d=new Error(a);return d.code=V.AuthRequired,d.data={...s,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function Lx(n){return/^[A-Za-z0-9_\-./=:@]+$/.test(n)?n:`'${n.replace(/'/g,"'\\''")}'`}function Nx(n,e,t,r){if(n&&typeof n=="object"&&n.code===V.AuthRequired)return n;let s=n instanceof Error?n.message:String(n),o=s.includes("stderr:"),i=o?"":e.stderrTailText(),a=r?`to reproduce: (cd ${Lx(r.cwd)} && ${[r.command,...r.args].map(Lx).join(" ")})`:"";if(!i&&!a)return n;let d=[o?s:`agent ${t} failed to start: ${s}`];i&&d.push(`stderr: ${i}`),a&&d.push(a);let c=new Error(d.join(`
|
|
356
356
|
`));if(n&&typeof n=="object"){let l=n;typeof l.code=="number"&&(c.code=l.code),l.data!==void 0&&(c.data=l.data)}return c}function Hc(n){if(!Array.isArray(n))return;let e=[];for(let t of n){if(!t||typeof t!="object")continue;let r=t;if(typeof r.id!="string")continue;let s=typeof r.description=="string"?r.description:"",o=r.type==="agent"||r.type==="terminal"?r.type:void 0,i=typeof r.name=="string"?r.name:void 0,a=r._meta,d=a!==null&&typeof a=="object"&&!Array.isArray(a)?a:void 0;e.push({id:r.id,description:s,...o&&{type:o},...i!==void 0&&{name:i},...d&&{_meta:d}})}return e.length>0?e:void 0}function fs(n){if(typeof n!="string")return;let e=n.trim();return e.length>0?e:void 0}function WO(n,e){let t=n.configOptions;if(Array.isArray(t))for(let r of t){if(!r||typeof r!="object"||Array.isArray(r))continue;let s=r;if(s.id===e)return s}}function Xg(n){return n.length>0?n:void 0}function Zg(n){return pf(n,{nestedKey:"models",configId:"model",fromObject:e=>{let t=Qa(e.availableModels);return t.length>0?t:void 0},fromConfig:e=>{let t=Qa(e.options);return t.length>0?t:void 0}})??[]}function ey(n){return pf(n,{nestedKey:"modes",configId:"mode",fromObject:e=>{let t=Tc(e.availableModes);return t.length>0?t:void 0},fromConfig:e=>{let t=Tc(e.options);return t.length>0?t:void 0}})??[]}function ty(n){return pf(n,{nestedKey:"modes",configId:"mode",fromObject:e=>fs(e.currentModeId)??fs(e.currentMode)??fs(e.modeId)??fs(e.mode),fromConfig:e=>fs(e.currentValue)})}function jO(n){for(let e=n.length-1;e>=0;e--){let t=n[e];if(!t||t.method!=="session/update")continue;let r=t.params?.update;if(r?.sessionUpdate==="turn_complete"&&!(typeof r.messageId!="string"||r.messageId.length===0))return{index:e,messageId:r.messageId}}}async function Bx(n){try{let e=await Ci.readFile(D.tuiHistoryFile(n),"utf8"),t=[];for(let r of e.split(`
|
|
357
357
|
`))if(r.length!==0)try{let s=JSON.parse(r);typeof s=="string"&&t.push(s)}catch{}return t}catch{return[]}}function Ux(n,e,t,r=new Date().toISOString(),s,o,i){let a=n.upstreamGenerations&&n.upstreamGenerations.length>0?[...n.upstreamGenerations]:n.upstreamSessionId?[{upstreamSessionId:n.upstreamSessionId,agentId:n.agentId}]:[],d=a[a.length-1];if(d&&d.upstreamSessionId===t){if(s!==void 0&&a.length>=2){let c=a[a.length-2];c&&c.cost===void 0&&(a[a.length-2]={...c,cost:s})}return o!==void 0&&d.reason===void 0&&(a[a.length-1]={...d,reason:o,...i!==void 0?{runId:i}:{}}),a}return d&&d.endedAt===void 0&&(a[a.length-1]={...d,endedAt:r,...s!==void 0?{cost:s}:{}}),a.push({upstreamSessionId:t,agentId:e,startedAt:r,...o!==void 0?{reason:o}:{},...i!==void 0?{runId:i}:{}}),a}async function Uc(n){try{let e=await Ci.stat(D.historyFile(n));return{mtime:new Date(e.mtimeMs).toISOString(),hasContent:e.size>0}}catch{return{hasContent:!1}}}function od(n,e){return n.interactive!==void 0?n.interactive:n.originatingClient?.name===vi?!1:e?!0:void 0}import{spawn as qO}from"child_process";import*as mf from"fs";import*as Ws from"fs/promises";import*as gf from"path";import zO from"pino-roll";var hf=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,r){if(e===78){let i=`exited with code 78 (unrecoverable); fix and run \`${r}s start ${t}\``;return this.tripped_=i,{tripped:i}}let s=this.now();this.recentExits.push(s);let o=s-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 \`${r}s start ${t}\``;return this.tripped_=a,{tripped:a}}return"restart"}reset(){this.recentExits=[],this.tripped_=void 0}get tripped(){return this.tripped_}};at();Fa();var KO=1e3,GO=6e4,ny=3e3,id=class{entries=new Map;stopping=!1;context;tokenRegistry;breakerOptions;restartBaseMs;restartCapMs;adapter;constructor(e,t,r,s={}){this.adapter=t,this.context=r,this.tokenRegistry=s.tokenRegistry,this.breakerOptions=s.breakerOptions,this.restartBaseMs=s.restartBaseMs??KO,this.restartCapMs=s.restartCapMs??GO;for(let o of e)this.entries.set(o.name,this.makeEntry(o))}setContext(e){this.context=e}reportVersion(e,t){let r=this.entries.get(e);r&&(r.version=t)}async start(){if(!this.context)throw new Error(`${this.managerName()}: setContext must be called before start`);await Ws.mkdir(this.adapter.paths.dir(),{recursive:!0}),await this.reapOrphans();let e=[];for(let t of this.entries.values())t.config.enabled&&e.push(this.spawn(t,0));await Promise.all(e)}async stop(){this.stopping=!0;let e=[];for(let t of this.entries.values()){t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let r=t.child;if(r){try{r.kill("SIGTERM")}catch{}e.push(new Promise(s=>{if(r.exitCode!==null||r.signalCode!==null){s();return}let o=setTimeout(()=>{try{r.kill("SIGKILL")}catch{}s()},ny);r.on("exit",()=>{clearTimeout(o),s()})}))}}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 jc(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");if(t.child)throw jc(new Error(`${this.adapter.kind} ${e} already running`),"CONFLICT");return t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0),t.manuallyStopped=!1,t.restartCount=0,t.breaker.reset(),t.failureReason=void 0,await this.spawn(t,0),this.infoFor(t)}async stopByName(e){let t=this.entries.get(e);if(!t)throw jc(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");t.manuallyStopped=!0,t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let r=t.child;return r?(await this.terminate(t,r),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 jc(new Error(`${this.adapter.kind} ${e.name} already exists`),"CONFLICT");if(!this.context)throw new Error(`${this.managerName()}: setContext must be called before register`);let t=this.makeEntry(e);return this.entries.set(e.name,t),e.enabled&&this.spawn(t,0).catch(r=>{t.failureReason=`spawn: ${r.message}`}),this.infoFor(t)}async unregister(e){let t=this.entries.get(e);if(!t)throw jc(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");t.manuallyStopped=!0,t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let r=t.child;r&&await this.terminate(t,r);try{t.logStream?.end()}catch{}this.entries.delete(e)}async terminate(e,t){if(t.exitCode!==null||t.signalCode!==null)return;let r=new Promise(o=>{e.exitWaiters.push(o)});try{t.kill("SIGTERM")}catch{}let s=setTimeout(()=>{try{t.kill("SIGKILL")}catch{}},ny);typeof s.unref=="function"&&s.unref();try{await r}finally{clearTimeout(s)}}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 hf(this.breakerOptions),failureReason:void 0}}async reapOrphans(){let e;try{e=await Ws.readdir(this.adapter.paths.dir(),{withFileTypes:!0})}catch(t){if(t.code==="ENOENT")return;throw t}for(let t of e){if(!t.isDirectory())continue;let r=this.adapter.paths.pidFile(t.name),s;try{let o=await Ws.readFile(r,"utf8"),i=Number.parseInt(o.trim(),10);Number.isInteger(i)&&i>0&&(s=i)}catch{}if(typeof s=="number"&&ry(s)){try{process.kill(s,"SIGTERM")}catch{}let o=Date.now()+ny;for(;Date.now()<o&&ry(s);)await new Promise(i=>setTimeout(i,50));if(ry(s))try{process.kill(s,"SIGKILL")}catch{}}await Ws.unlink(r).catch(()=>{})}}async spawn(e,t){if(this.stopping||e.manuallyStopped)return;let r=this.context;if(!r)throw new Error(`${this.managerName()}.spawn called before setContext`);let s=e.config,o=s.command.length>0?s.command:[s.name],i=gf.dirname(this.adapter.paths.logFile(s.name)),a;try{await Ws.mkdir(i,{recursive:!0}),a=await zO({file:gf.join(i,`${s.name}.log`),size:"5m",mkdir:!0,symlink:!0,limit:{count:5}}),a.on("error",y=>{e.failureReason=`log stream: ${y.message}`})}catch(y){if(this.stopping||e.manuallyStopped)return;e.failureReason=`log setup: ${y.message}`,this.scheduleRestart(e,t+1);return}if(this.stopping||e.manuallyStopped){try{a.end()}catch{}return}a.write(`[hydra-acp] ${new Date().toISOString()} starting ${this.adapter.kind} ${s.name} (attempt ${t+1})
|
|
358
358
|
`);let d=this.tokenRegistry?.mint(s.name,this.adapter.tokenRole)??r.serviceToken;e.processToken=d,e.version=void 0;let c={...Oa(),HYDRA_ACP_DAEMON_URL:r.daemonUrl,HYDRA_ACP_DAEMON_HOST:r.daemonHost,HYDRA_ACP_DAEMON_PORT:String(r.daemonPort),HYDRA_ACP_TOKEN:d,HYDRA_ACP_WS_URL:r.daemonWsUrl,HYDRA_ACP_HOME:r.hydraHome,[this.adapter.nameEnvVar]:s.name,...s.env},[l,...u]=o;if(l===void 0){a.write(`[hydra-acp] ${this.adapter.kind} ${s.name} has empty command
|
package/dist/daemon.js
CHANGED
|
@@ -30,7 +30,7 @@ stderr: ${t}`:e}stderrTailText(){return this.stderrTail.trim()}static spawn(e){l
|
|
|
30
30
|
`)}function fi(s,e,t){if(s.length===0||!s.startsWith("/"))return!1;let n=e.endsWith("/")?e:`${e}/`,r=t.endsWith("/")?t:`${t}/`;return s.startsWith(r)?!1:s.startsWith(n)}K();import*as Ee from"fs/promises";async function Ot(s,e){let t=C.queueFile(s);if(e.length===0){await Ee.unlink(t).catch(()=>{});return}await Ee.mkdir(C.sessionDir(s),{recursive:!0});let n=e.map(r=>JSON.stringify(r)).join(`
|
|
31
31
|
`)+`
|
|
32
32
|
`;await Ee.writeFile(t,n,"utf8")}async function gi(s){let e=C.queueFile(s),t;try{t=await Ee.readFile(e,"utf8")}catch(r){if(r.code==="ENOENT")return[];throw r}let n=[];for(let r of t.split(`
|
|
33
|
-
`))if(r.trim())try{let o=JSON.parse(r);o&&typeof o.messageId=="string"&&Array.isArray(o.prompt)&&typeof o.enqueuedAt=="number"&&n.push(o)}catch{}return n}async function mi(s){let e=C.queueFile(s);await Ee.unlink(e).catch(()=>{})}import*as Ai from"fs/promises";var Si="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Ii=vi(Si,16),Gs=vi(Si,16),Uu=20,Du=20,Bu=5,Me="hydra_session_";function Pe(){return`m_${Ii()}`}function He(s){return s.startsWith(Me)?s.slice(Me.length):s}var hi=["start","merge","apply","sync","stop","detach","discard","clean","status"],Lu=1e3,kn=300*1e3,Wu=64,qu=new Set(["task-notification","peer","coordinator","observer","observer-activity"]);function zu(s){let e=s?.update;if(!e||typeof e!="object"||e.sessionUpdate!=="usage_update")return!1;let t=e._meta;if(!t||typeof t!="object")return!1;let n=t["_claude/origin"];if(!n||typeof n!="object")return!1;let r=n.kind;return typeof r=="string"&&qu.has(r)}var yi=120,Ju=128,Vu=1e3,wt=class s{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=Re;modelVerbConfirmed=!1;agentArgs;parentSessionId;forkedFromSessionId;forkedFromMessageId;forkSynthesisState;originatingClient;_interactive;get interactive(){return this._interactive}_priority;get priority(){return this._priority}title;_summarizedThroughEntry;get summarizedThroughEntry(){return this._summarizedThroughEntry}set summarizedThroughEntry(e){this._summarizedThroughEntry=e}currentModel;currentMode;compactionState;_currentUsage;updatedAt;createdAt;clients=new Map;historyStore;promptQueue=[];currentEntry;promptInFlight=!1;agentTurnInFlight=!1;swapInFlight=!1;modeChangeInFlight=!1;modelChangeInFlight=!1;queueWriteChain=Promise.resolve();closed=!1;closing=!1;closeInFlight;deleteRecordIntent=!1;closeHandlers=[];titleHandlers=[];scheduleSynopsisHook;scheduleWorkspaceSnapshotHook;scheduleCompactionHook;resolveAgentIdHook;getCompactionStateHook;getUpstreamGenerationsHook;getPendingAgentSwapHook;_liveCompactionPhase;broadcastHandlers=[];lastCancelAt=0;static CANCEL_ERROR_WINDOW_MS=2e3;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}promptStartedAt;unsolicitedTurn;supersededAutonomousTurn;autonomousSalvage;lastBackgroundTask;toolLabels=new Map;armedTasks=new Map;lastArmedBroadcast;sawTurnComplete=!1;appendCount=0;historyMaxEntries;compactEvery;permissionCallbacks=new Map;attentionFlags=new Map;get hasPermissionFlag(){for(let e of this.attentionFlags.values())if(e.source==="daemon"&&e.reason.startsWith("permission:"))return!0;return!1}attentionFlagsChangeHandlers=[];internalPromptCapture;idleTimeoutMs;idleTimer;idleEventTimeoutMs;idleHandlers=[];lastRecordedAt;spawnReplacementAgent;mintMcpServersForSwap;loadExistingAgentSession;clearRollbackBreadcrumbHook;onCompactionSwapHook;persistWatermarkHook;uncompactHook;forkHook;mcpServersConfig;forwardedEnv;workspace;workspaceError;workspaceNotes=[];workspaceHook;workspacePreambleSent=!1;formerWorkspace;departureNoteSent=!1;listSessions;logger;transformChain;extensionCommands;extensionCommandsUnsub;pendingClaims=new Map;toolCompletionSeen=new Map;toolCallKind=new hn;filesEditedSeen=new Set;openToolCalls=new Set;agentChangeHandlers=[];retiringGenerationCost;agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];availableAgentsFn;modelHandlers=[];modeHandlers=[];interactiveHandlers=[];priorityHandlers=[];usageHandlers=[];cumulativeCost=0;costLedgerProbe;get persistableUsage(){if(!(!this._currentUsage&&!this.cumulativeCost))return{...this._currentUsage??{},...this.cumulativeCost?{cumulativeCost:this.cumulativeCost}:{cumulativeCost:void 0}}}get currentUsage(){if(!this._currentUsage&&!this.cumulativeCost)return;let e=this._currentUsage??{},t=this.cumulativeCost+(e.costAmount??0);return{...e,costAmount:t||void 0,cumulativeCost:void 0}}amendInProgress;inFlightExtensionDispatches=new Map;recentlyTerminal=new Map;streamBuffer;streamFilePath;constructor(e){if(this.sessionId=e.sessionId??`${Me}${Ii()}`,this.cwd=e.cwd,this.workspace=e.workspace,this.workspaceError=e.workspaceError,this.workspaceHook=e.workspaceHook,this.agentId=e.agentId,this.agent=e.agent,this.upstreamSessionId=e.upstreamSessionId,this.agentMeta=e.agentMeta,this.agentCapabilities=e.agentCapabilities,this.agentArgs=e.agentArgs,this.parentSessionId=e.parentSessionId,this.forkedFromSessionId=e.forkedFromSessionId,this.forkedFromMessageId=e.forkedFromMessageId,this.forkSynthesisState=e.forkSynthesisState,this.originatingClient=e.originatingClient,this.title=e.title,this.scheduleSynopsisHook=e.scheduleSynopsis,this.scheduleWorkspaceSnapshotHook=e.scheduleWorkspaceSnapshot,this.scheduleCompactionHook=e.scheduleCompaction,this.resolveAgentIdHook=e.resolveAgentId,this.getCompactionStateHook=e.getCompactionState,this.getUpstreamGenerationsHook=e.getUpstreamGenerations,this.getPendingAgentSwapHook=e.getPendingAgentSwap,this.currentModel=e.currentModel,this.currentMode=e.currentMode,this._currentUsage=e.currentUsage,this.cumulativeCost=e.currentUsage?.cumulativeCost??0,e.reloadsUpstreamLedger&&this.armCostLedgerProbe(),e.agentCommands&&e.agentCommands.length>0&&(this.agentAdvertisedCommands=[...e.agentCommands]),e.agentModes&&e.agentModes.length>0&&(this.agentAdvertisedModes=[...e.agentModes]),e.agentModels&&e.agentModels.length>0&&(this.agentAdvertisedModels=[...e.agentModels]),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.persistWatermarkHook=e.persistWatermarkHook,this.uncompactHook=e.uncompactHook,this.forkHook=e.forkHook,this.mcpServersConfig=e.mcpServers,this.forwardedEnv=e.forwardedEnv,this.availableAgentsFn=e.availableAgents,this.listSessions=e.listSessions,this.logger=e.logger,this.transformChain=e.transformChain??[],this.extensionCommands=e.extensionCommands,this.extensionCommands&&(this.extensionCommandsUnsub=this.extensionCommands.onChange(()=>{this.closed||this.broadcastMergedCommands()})),e.firstPromptSeeded&&(this._firstPromptSeeded=!0),this._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??Lu,this.compactEvery=Math.max(1,Math.floor(this.historyMaxEntries*.2)),this.updatedAt=Date.now(),this.createdAt=e.createdAt??this.updatedAt,this.lastRecordedAt=this.updatedAt,this.resetModelVerb(e.modelVerb),this.wireAgent(this.agent),this.scheduleIdleCheck(),this.notifyChain("session.opened",{})}broadcastMergedCommands(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"available_commands_update",availableCommands:this.mergedAvailableCommands()}})}broadcastAvailableModes(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"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){nl(this.internalPromptCapture,t);return}this.maybeEmitToolEdges(t),this.runResponseChain(t)}),e.connection.onRequest("session/request_permission",async t=>{let n=await this.runAgentRequestChain("session/request_permission",t),r=wi(n.shortCircuit?t:n.envelope);if(n.shortCircuit)return this.notifyChain("permission.replied",{toolCallId:r??null,outcome:n.payload,sourceWasTransformer:!0}),n.payload;let o=await this.handlePermissionRequest(n.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>s.CANCEL_ERROR_WINDOW_MS){this.logger?.warn(`agent ${this.agentId} sent uncorrelated error frame code=${e.code} message=${e.message}`);return}this.lastCancelAt=0,this.logger?.warn(`agent ${this.agentId} rejected session/cancel code=${e.code} message=${e.message}`),this.broadcastQueueNotification("hydra-acp/cancel_failed",{sessionId:this.sessionId,code:e.code,message:e.message})}async runResponseChain(e,t=new Set,n=0,r="session/update"){let o=e,i=r==="session/update"?this.injectCumulativeCost(e):e,a=`response:${r}`;for(let u=n;u<this.transformChain.length;u++){let l=this.transformChain[u];if(t.has(l.name)||!l.intercepts.has(a))continue;let f=`t_${Gs()}`,p;try{p=await l.connection.request("hydra-acp/transformer/message",{token:f,phase:"response",method:r,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(m){this.logger?.warn(`transformer ${l.name} error on ${a}: ${m.message}`);continue}let g=p?.action??"continue";if(g==="stop")return;if(g==="processing"){let m=u,h=i,y=new Set(t),k=r;await new Promise(w=>{let S=setTimeout(()=>{this.pendingClaims.delete(f)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:f,transformerName:l.name}),this.runResponseChain(h,new Set([...y,l.name]),m+1,k).then(()=>w()).catch(()=>w()))},kn);typeof S.unref=="function"&&S.unref(),this.pendingClaims.set(f,{resolve:()=>w(),timer:S,transformerName:l.name,method:k,envelope:h,chainIdx:m,originatedBy:y,side:"response"})});return}p?.payload&&typeof p.payload=="object"&&(i=p.payload),t.add(l.name)}if(r!=="session/update")return;this.noteAgentActivity(i);let d=sl(i);if(d!==null){this.setAgentAdvertisedCommands(d);return}let c=tl(i);if(c!==null){this.setAgentAdvertisedModes(c);return}if(this.noteModelVerbHint(Ko(i.update),"session/update"),this.maybeApplyAgentModel(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentMode(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentConfigOption(i)){this.recordAndBroadcast("session/update",this.mergeAgentOptionIntoEnvelope(i));return}if(this.maybeApplyAgentUsage(o)){this.recordAndBroadcast("session/update",i);return}this.maybeApplyAgentSessionInfo(i),this.recordAndBroadcast("session/update",i)}onAgentChange(e){this.agentChangeHandlers.push(e)}get attachedCount(){return this.clients.size}connectedClients(e){let t=[];for(let n of this.clients.values()){if(e&&n.clientId===e)continue;let r={clientId:n.clientId};n.clientInfo?.name&&(r.name=n.clientInfo.name),n.clientInfo?.version&&(r.version=n.clientInfo.version),t.push(r)}return t}get turnStartedAt(){return this.promptStartedAt}get inUnsolicitedTurn(){return this.unsolicitedTurn!==void 0}get agentPid(){return this.agent.pid}get awaitingInput(){return this.attentionFlags.size>0}async isQuiescedForSwap(){return await this.quiesceBlocker()===void 0}async quiesceBlocker(){if(this.agentTurnInFlight)return"the agent is still working; wait for the current turn to finish, then try again";if(this.unsolicitedTurn!==void 0)return"the agent is part-way through a turn it started by itself; wait for it to finish or interrupt it (^C), then try again";if(this.internalPromptCapture!==void 0)return"hydra is driving the agent right now (compaction seed or transcript injection); this clears by itself, so try again in a moment";if(this.modelChangeInFlight)return"a model change is still settling; try again in a moment";if(this.modeChangeInFlight)return"a mode change is still settling; try again in a moment";let e=await this.openToolCallIdsInHistory();if(e.length>0)return`${e.length} tool call(s) from an earlier turn never reported a result, so the session still reads as busy. ^C closes an abandoned chain; failing that it clears as new history accumulates`}isQuiescedSync(){return!(this.promptInFlight||this.unsolicitedTurn!==void 0||this.modeChangeInFlight||this.modelChangeInFlight)}async swapIntoWorkspace(e){await this.swapUpstream({...e.synopsis!==void 0?{artifact:e.synopsis}:{},note:e.note,framing:"swap",...e.title!==void 0?{title:e.title}:{},tailK:8,tailFloor:4,summarizedThroughEntry:e.historyLength,newCwd:e.cwd,reason:e.workspace!==void 0?"workspace-enter":"workspace-leave"}),this.workspace=e.workspace,e.left!==void 0?(this.formerWorkspace={path:e.left.path,sourceCwd:e.cwd,removed:e.left.removed},this.departureNoteSent=!1):this.formerWorkspace=void 0}async swapUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for swap: ${t}`);if(this.swapInFlight)throw new Error("a swap is already in progress for this session");this.swapInFlight=!0;try{await this.doSwapUpstream(e)}finally{this.swapInFlight=!1}}async doSwapUpstream(e){this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let t=this.agentId,n=e.newAgentId??this.agentId,r=n!==this.agentId,o=e.reason!==void 0&&e.reason!=="compaction"?e.reason:r?"agent-swap":"compaction",i=e.newCwd??this.cwd,a=this.agentArgs,d=this.forwardedEnv,c=this.currentModel,u=this.currentMode,l=this.spawnReplacementAgent;if(!l)throw new Error("agent spawning not configured for this session");let f=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],p=await l({agentId:n,cwd:i,agentArgs:a,...d?{forwardedEnv:d}:{},mcpServers:f});this.accumulateAndResetCost(),this.cwd=i,this.wireAgent(p.agent),r||(await lt({agent:p.agent,upstreamSessionId:p.upstreamSessionId,persistedModel:c,agentReportedModel:p.initialModel,logger:this.logger}),await ut({agent:p.agent,upstreamSessionId:p.upstreamSessionId,persistedMode:u,agentReportedMode:p.initialMode,logger:this.logger})),p.agent.connection.drainBuffered("session/update");let g=[];if(this.historyStore)try{g=await this.historyStore.load(this.sessionId)}catch(_){this.logger?.warn(`swapUpstream: historyStore.load failed: ${_.message}`)}let m=zs({...e.artifact!==void 0?{synopsis:e.artifact}:{},...e.note!==void 0?{note:e.note}:{},...e.framing!==void 0?{framing:e.framing}:{},title:e.title,tail:g,tailK:e.tailK,tailFloor:e.tailFloor,...e.summarizedThroughEntry!==void 0?{watermark:e.summarizedThroughEntry}:{},recallArmed:(e.summarizedThroughEntry??this._summarizedThroughEntry??0)>0});if(this.internalPromptCapture)throw new Error("swapUpstream: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};let h,y;try{await p.agent.connection.request("session/prompt",{sessionId:p.upstreamSessionId,prompt:[{type:"text",text:m}]});let _=this.internalPromptCapture;h=_.lastUsed,y=_.lastSize,this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${m.length} toolCalls=${_.toolCalls} thinkingChars=${_.thinkingChars} messageChars=${_.messageChars} used=${_.lastUsed??"?"} size=${_.lastSize??"?"} reply=${JSON.stringify(_.chunks.join("").slice(0,200))}`)}finally{this.internalPromptCapture=void 0}h!==void 0&&(this.maybeApplyAgentUsage({update:{sessionUpdate:"usage_update",used:h,...y!==void 0?{size:y}:{}}}),this.broadcastCurrentUsage());let k=this.upstreamSessionId,w=this._summarizedThroughEntry;e.summarizedThroughEntry!==void 0&&(this._summarizedThroughEntry=e.summarizedThroughEntry);let S=this.agent;if(this.agent=p.agent,this.upstreamSessionId=p.upstreamSessionId,this.agentMeta=p.agentMeta,this.agentCapabilities=p.agentCapabilities,this.resetModelVerb(p.modelVerb),r&&(this.agentId=n,this.agentAdvertisedCommands=[],this.currentModel=p.initialModel,this.currentMode=p.initialMode,this.setAgentAdvertisedModels(p.initialModels??[]),this.setAgentAdvertisedModes(p.initialModes??[])),this.broadcastMergedCommands(),this.broadcastConfigOptions(),this.notifyAgentChange("swapUpstream",o,e.runId),e.summarizedThroughEntry!==void 0&&this.persistWatermarkHook)try{this.persistWatermarkHook(e.summarizedThroughEntry)}catch(_){this.logger?.warn(`swapUpstream: persistWatermarkHook failed: ${_.message}`)}if(!r&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:k,...w!==void 0?{previousSummarizedThroughEntry:w}:{},...e.runId!==void 0?{runId:e.runId}:{}})}catch(_){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${_.message}`)}let I=await this.retireAgent(S,r?"agent switch":e.reason==="workspace-enter"||e.reason==="workspace-leave"?"workspace move":"compaction swap");this.notifyChain("agent.swap",{phase:"post",previousUpstreamSessionId:k,upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}),r||this.broadcastCompactionPhase({phase:"swapped",...this.title!==void 0?{title:this.title}:{},summarizedThroughEntry:e.summarizedThroughEntry??this._summarizedThroughEntry??0}),r&&this.broadcastAgentSwitch(t,n);let b=I.length>0?`
|
|
33
|
+
`))if(r.trim())try{let o=JSON.parse(r);o&&typeof o.messageId=="string"&&Array.isArray(o.prompt)&&typeof o.enqueuedAt=="number"&&n.push(o)}catch{}return n}async function mi(s){let e=C.queueFile(s);await Ee.unlink(e).catch(()=>{})}import*as Ai from"fs/promises";var Si="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Ii=vi(Si,16),Gs=vi(Si,16),Uu=20,Du=20,Bu=5,Me="hydra_session_";function Pe(){return`m_${Ii()}`}function He(s){return s.startsWith(Me)?s.slice(Me.length):s}var hi=["start","merge","apply","sync","stop","detach","discard","clean","status"],Lu=1e3,kn=300*1e3,Wu=64,qu=new Set(["task-notification","peer","coordinator","observer","observer-activity"]);function zu(s){let e=s?.update;if(!e||typeof e!="object"||e.sessionUpdate!=="usage_update")return!1;let t=e._meta;if(!t||typeof t!="object")return!1;let n=t["_claude/origin"];if(!n||typeof n!="object")return!1;let r=n.kind;return typeof r=="string"&&qu.has(r)}var yi=120,Ju=128,Vu=1e3,wt=class s{sessionId;cwd;agentId;agent;upstreamSessionId;agentMeta;agentCapabilities;modelVerb=Re;modelVerbConfirmed=!1;agentArgs;parentSessionId;forkedFromSessionId;forkedFromMessageId;forkSynthesisState;originatingClient;_interactive;get interactive(){return this._interactive}_priority;get priority(){return this._priority}title;_summarizedThroughEntry;get summarizedThroughEntry(){return this._summarizedThroughEntry}set summarizedThroughEntry(e){this._summarizedThroughEntry=e}currentModel;currentMode;compactionState;_currentUsage;updatedAt;createdAt;clients=new Map;historyStore;promptQueue=[];currentEntry;promptInFlight=!1;agentTurnInFlight=!1;swapInFlight=!1;modeChangeInFlight=!1;modelChangeInFlight=!1;queueWriteChain=Promise.resolve();closed=!1;closing=!1;closeInFlight;deleteRecordIntent=!1;closeHandlers=[];titleHandlers=[];scheduleSynopsisHook;scheduleWorkspaceSnapshotHook;scheduleCompactionHook;resolveAgentIdHook;getCompactionStateHook;getUpstreamGenerationsHook;getPendingAgentSwapHook;_liveCompactionPhase;broadcastHandlers=[];lastCancelAt=0;static CANCEL_ERROR_WINDOW_MS=2e3;forceCancelling=!1;_firstPromptSeeded=!1;get firstPromptSeeded(){return this._firstPromptSeeded}_titleSeedPending=!0;promptStartedAt;unsolicitedTurn;supersededAutonomousTurn;autonomousSalvage;lastBackgroundTask;toolLabels=new Map;armedTasks=new Map;lastArmedBroadcast;sawTurnComplete=!1;appendCount=0;historyMaxEntries;compactEvery;permissionCallbacks=new Map;attentionFlags=new Map;get hasPermissionFlag(){for(let e of this.attentionFlags.values())if(e.source==="daemon"&&e.reason.startsWith("permission:"))return!0;return!1}attentionFlagsChangeHandlers=[];internalPromptCapture;idleTimeoutMs;idleTimer;idleEventTimeoutMs;idleHandlers=[];lastRecordedAt;spawnReplacementAgent;mintMcpServersForSwap;loadExistingAgentSession;clearRollbackBreadcrumbHook;onCompactionSwapHook;persistWatermarkHook;uncompactHook;forkHook;mcpServersConfig;forwardedEnv;workspace;workspaceError;workspaceNotes=[];workspaceHook;workspacePreambleSent=!1;formerWorkspace;departureNoteSent=!1;listSessions;logger;transformChain;extensionCommands;extensionCommandsUnsub;pendingClaims=new Map;toolCompletionSeen=new Map;toolCallKind=new hn;filesEditedSeen=new Set;openToolCalls=new Set;agentChangeHandlers=[];retiringGenerationCost;agentAdvertisedCommands=[];agentAdvertisedModes=[];agentAdvertisedModels=[];agentAdvertisedConfigOptions=[];agentCommandsHandlers=[];agentModesHandlers=[];agentModelsHandlers=[];availableAgentsFn;modelHandlers=[];modeHandlers=[];interactiveHandlers=[];priorityHandlers=[];usageHandlers=[];cumulativeCost=0;costLedgerProbe;get persistableUsage(){if(!(!this._currentUsage&&!this.cumulativeCost))return{...this._currentUsage??{},...this.cumulativeCost?{cumulativeCost:this.cumulativeCost}:{cumulativeCost:void 0}}}get currentUsage(){if(!this._currentUsage&&!this.cumulativeCost)return;let e=this._currentUsage??{},t=this.cumulativeCost+(e.costAmount??0);return{...e,costAmount:t||void 0,cumulativeCost:void 0}}amendInProgress;inFlightExtensionDispatches=new Map;recentlyTerminal=new Map;streamBuffer;streamFilePath;constructor(e){if(this.sessionId=e.sessionId??`${Me}${Ii()}`,this.cwd=e.cwd,this.workspace=e.workspace,this.workspaceError=e.workspaceError,this.workspaceHook=e.workspaceHook,this.agentId=e.agentId,this.agent=e.agent,this.upstreamSessionId=e.upstreamSessionId,this.agentMeta=e.agentMeta,this.agentCapabilities=e.agentCapabilities,this.agentArgs=e.agentArgs,this.parentSessionId=e.parentSessionId,this.forkedFromSessionId=e.forkedFromSessionId,this.forkedFromMessageId=e.forkedFromMessageId,this.forkSynthesisState=e.forkSynthesisState,this.originatingClient=e.originatingClient,this.title=e.title,this.scheduleSynopsisHook=e.scheduleSynopsis,this.scheduleWorkspaceSnapshotHook=e.scheduleWorkspaceSnapshot,this.scheduleCompactionHook=e.scheduleCompaction,this.resolveAgentIdHook=e.resolveAgentId,this.getCompactionStateHook=e.getCompactionState,this.getUpstreamGenerationsHook=e.getUpstreamGenerations,this.getPendingAgentSwapHook=e.getPendingAgentSwap,this.currentModel=e.currentModel,this.currentMode=e.currentMode,this._currentUsage=e.currentUsage,this.cumulativeCost=e.currentUsage?.cumulativeCost??0,e.reloadsUpstreamLedger&&this.armCostLedgerProbe(),e.agentCommands&&e.agentCommands.length>0&&(this.agentAdvertisedCommands=[...e.agentCommands]),e.agentModes&&e.agentModes.length>0&&(this.agentAdvertisedModes=[...e.agentModes]),e.agentModels&&e.agentModels.length>0&&(this.agentAdvertisedModels=[...e.agentModels]),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.persistWatermarkHook=e.persistWatermarkHook,this.uncompactHook=e.uncompactHook,this.forkHook=e.forkHook,this.mcpServersConfig=e.mcpServers,this.forwardedEnv=e.forwardedEnv,this.availableAgentsFn=e.availableAgents,this.listSessions=e.listSessions,this.logger=e.logger,this.transformChain=e.transformChain??[],this.extensionCommands=e.extensionCommands,this.extensionCommands&&(this.extensionCommandsUnsub=this.extensionCommands.onChange(()=>{this.closed||this.broadcastMergedCommands()})),e.firstPromptSeeded&&(this._firstPromptSeeded=!0,this._titleSeedPending=!1),this._interactive=e.interactive,this._priority=e.priority,this._summarizedThroughEntry=e.summarizedThroughEntry,this.compactionState=e.compactionState,e.compactionState){let t=e.compactionState;(t.status==="requested"||t.status==="running"||t.status==="swap_pending"||t.status==="swap_deferred")&&(t.status==="swap_deferred"?this._liveCompactionPhase={phase:"deferred",attempts:t.attempts}:this._liveCompactionPhase={phase:t.status==="requested"?"started":"iteration",iter:t.iter})}if(e.attentionFlags&&e.attentionFlags.length>0)for(let t of e.attentionFlags)this.attentionFlags.set(`${t.source}::${t.reason}`,t);this.historyStore=e.historyStore,this.historyMaxEntries=e.historyMaxEntries??Lu,this.compactEvery=Math.max(1,Math.floor(this.historyMaxEntries*.2)),this.updatedAt=Date.now(),this.createdAt=e.createdAt??this.updatedAt,this.lastRecordedAt=this.updatedAt,this.resetModelVerb(e.modelVerb),this.wireAgent(this.agent),this.scheduleIdleCheck(),this.notifyChain("session.opened",{})}broadcastMergedCommands(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"available_commands_update",availableCommands:this.mergedAvailableCommands()}})}broadcastAvailableModes(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"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){nl(this.internalPromptCapture,t);return}this.maybeEmitToolEdges(t),this.runResponseChain(t)}),e.connection.onRequest("session/request_permission",async t=>{let n=await this.runAgentRequestChain("session/request_permission",t),r=wi(n.shortCircuit?t:n.envelope);if(n.shortCircuit)return this.notifyChain("permission.replied",{toolCallId:r??null,outcome:n.payload,sourceWasTransformer:!0}),n.payload;let o=await this.handlePermissionRequest(n.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>s.CANCEL_ERROR_WINDOW_MS){this.logger?.warn(`agent ${this.agentId} sent uncorrelated error frame code=${e.code} message=${e.message}`);return}this.lastCancelAt=0,this.logger?.warn(`agent ${this.agentId} rejected session/cancel code=${e.code} message=${e.message}`),this.broadcastQueueNotification("hydra-acp/cancel_failed",{sessionId:this.sessionId,code:e.code,message:e.message})}async runResponseChain(e,t=new Set,n=0,r="session/update"){let o=e,i=r==="session/update"?this.injectCumulativeCost(e):e,a=`response:${r}`;for(let u=n;u<this.transformChain.length;u++){let l=this.transformChain[u];if(t.has(l.name)||!l.intercepts.has(a))continue;let f=`t_${Gs()}`,p;try{p=await l.connection.request("hydra-acp/transformer/message",{token:f,phase:"response",method:r,direction:"agent\u2192client",sessionId:this.sessionId,envelope:i})}catch(m){this.logger?.warn(`transformer ${l.name} error on ${a}: ${m.message}`);continue}let g=p?.action??"continue";if(g==="stop")return;if(g==="processing"){let m=u,h=i,y=new Set(t),k=r;await new Promise(w=>{let S=setTimeout(()=>{this.pendingClaims.delete(f)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:f,transformerName:l.name}),this.runResponseChain(h,new Set([...y,l.name]),m+1,k).then(()=>w()).catch(()=>w()))},kn);typeof S.unref=="function"&&S.unref(),this.pendingClaims.set(f,{resolve:()=>w(),timer:S,transformerName:l.name,method:k,envelope:h,chainIdx:m,originatedBy:y,side:"response"})});return}p?.payload&&typeof p.payload=="object"&&(i=p.payload),t.add(l.name)}if(r!=="session/update")return;this.noteAgentActivity(i);let d=sl(i);if(d!==null){this.setAgentAdvertisedCommands(d);return}let c=tl(i);if(c!==null){this.setAgentAdvertisedModes(c);return}if(this.noteModelVerbHint(Ko(i.update),"session/update"),this.maybeApplyAgentModel(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentMode(i)){this.recordAndBroadcast("session/update",i);return}if(this.maybeApplyAgentConfigOption(i)){this.recordAndBroadcast("session/update",this.mergeAgentOptionIntoEnvelope(i));return}if(this.maybeApplyAgentUsage(o)){this.recordAndBroadcast("session/update",i);return}this.maybeApplyAgentSessionInfo(i),this.recordAndBroadcast("session/update",i)}onAgentChange(e){this.agentChangeHandlers.push(e)}get attachedCount(){return this.clients.size}connectedClients(e){let t=[];for(let n of this.clients.values()){if(e&&n.clientId===e)continue;let r={clientId:n.clientId};n.clientInfo?.name&&(r.name=n.clientInfo.name),n.clientInfo?.version&&(r.version=n.clientInfo.version),t.push(r)}return t}get turnStartedAt(){return this.promptStartedAt}get inUnsolicitedTurn(){return this.unsolicitedTurn!==void 0}get agentPid(){return this.agent.pid}get awaitingInput(){return this.attentionFlags.size>0}async isQuiescedForSwap(){return await this.quiesceBlocker()===void 0}async quiesceBlocker(){if(this.agentTurnInFlight)return"the agent is still working; wait for the current turn to finish, then try again";if(this.unsolicitedTurn!==void 0)return"the agent is part-way through a turn it started by itself; wait for it to finish or interrupt it (^C), then try again";if(this.internalPromptCapture!==void 0)return"hydra is driving the agent right now (compaction seed or transcript injection); this clears by itself, so try again in a moment";if(this.modelChangeInFlight)return"a model change is still settling; try again in a moment";if(this.modeChangeInFlight)return"a mode change is still settling; try again in a moment";let e=await this.openToolCallIdsInHistory();if(e.length>0)return`${e.length} tool call(s) from an earlier turn never reported a result, so the session still reads as busy. ^C closes an abandoned chain; failing that it clears as new history accumulates`}isQuiescedSync(){return!(this.promptInFlight||this.unsolicitedTurn!==void 0||this.modeChangeInFlight||this.modelChangeInFlight)}async swapIntoWorkspace(e){await this.swapUpstream({...e.synopsis!==void 0?{artifact:e.synopsis}:{},note:e.note,framing:"swap",...e.title!==void 0?{title:e.title}:{},tailK:8,tailFloor:4,summarizedThroughEntry:e.historyLength,newCwd:e.cwd,reason:e.workspace!==void 0?"workspace-enter":"workspace-leave"}),this.workspace=e.workspace,e.left!==void 0?(this.formerWorkspace={path:e.left.path,sourceCwd:e.cwd,removed:e.left.removed},this.departureNoteSent=!1):this.formerWorkspace=void 0}async swapUpstream(e){let t=await this.quiesceBlocker();if(t!==void 0)throw new Error(`session is not quiesced for swap: ${t}`);if(this.swapInFlight)throw new Error("a swap is already in progress for this session");this.swapInFlight=!0;try{await this.doSwapUpstream(e)}finally{this.swapInFlight=!1}}async doSwapUpstream(e){this.notifyChain("agent.swap",{phase:"pre",previousUpstreamSessionId:this.upstreamSessionId,agentId:this.agentId});let t=this.agentId,n=e.newAgentId??this.agentId,r=n!==this.agentId,o=e.reason!==void 0&&e.reason!=="compaction"?e.reason:r?"agent-swap":"compaction",i=e.newCwd??this.cwd,a=this.agentArgs,d=this.forwardedEnv,c=this.currentModel,u=this.currentMode,l=this.spawnReplacementAgent;if(!l)throw new Error("agent spawning not configured for this session");let f=this.mintMcpServersForSwap?await this.mintMcpServersForSwap(this):this.mcpServersConfig??[],p=await l({agentId:n,cwd:i,agentArgs:a,...d?{forwardedEnv:d}:{},mcpServers:f});this.accumulateAndResetCost(),this.cwd=i,this.wireAgent(p.agent),r||(await lt({agent:p.agent,upstreamSessionId:p.upstreamSessionId,persistedModel:c,agentReportedModel:p.initialModel,logger:this.logger}),await ut({agent:p.agent,upstreamSessionId:p.upstreamSessionId,persistedMode:u,agentReportedMode:p.initialMode,logger:this.logger})),p.agent.connection.drainBuffered("session/update");let g=[];if(this.historyStore)try{g=await this.historyStore.load(this.sessionId)}catch(_){this.logger?.warn(`swapUpstream: historyStore.load failed: ${_.message}`)}let m=zs({...e.artifact!==void 0?{synopsis:e.artifact}:{},...e.note!==void 0?{note:e.note}:{},...e.framing!==void 0?{framing:e.framing}:{},title:e.title,tail:g,tailK:e.tailK,tailFloor:e.tailFloor,...e.summarizedThroughEntry!==void 0?{watermark:e.summarizedThroughEntry}:{},recallArmed:(e.summarizedThroughEntry??this._summarizedThroughEntry??0)>0});if(this.internalPromptCapture)throw new Error("swapUpstream: internal prompt already in flight");this.internalPromptCapture={chunks:[],toolCalls:0,thinkingChars:0,messageChars:0};let h,y;try{await p.agent.connection.request("session/prompt",{sessionId:p.upstreamSessionId,prompt:[{type:"text",text:m}]});let _=this.internalPromptCapture;h=_.lastUsed,y=_.lastSize,this.logger?.info(`swapUpstream: seed processed sessionId=${this.sessionId} seedChars=${m.length} toolCalls=${_.toolCalls} thinkingChars=${_.thinkingChars} messageChars=${_.messageChars} used=${_.lastUsed??"?"} size=${_.lastSize??"?"} reply=${JSON.stringify(_.chunks.join("").slice(0,200))}`)}finally{this.internalPromptCapture=void 0}h!==void 0&&(this.maybeApplyAgentUsage({update:{sessionUpdate:"usage_update",used:h,...y!==void 0?{size:y}:{}}}),this.broadcastCurrentUsage());let k=this.upstreamSessionId,w=this._summarizedThroughEntry;e.summarizedThroughEntry!==void 0&&(this._summarizedThroughEntry=e.summarizedThroughEntry);let S=this.agent;if(this.agent=p.agent,this.upstreamSessionId=p.upstreamSessionId,this.agentMeta=p.agentMeta,this.agentCapabilities=p.agentCapabilities,this.resetModelVerb(p.modelVerb),r&&(this.agentId=n,this.agentAdvertisedCommands=[],this.currentModel=p.initialModel,this.currentMode=p.initialMode,this.setAgentAdvertisedModels(p.initialModels??[]),this.setAgentAdvertisedModes(p.initialModes??[])),this.broadcastMergedCommands(),this.broadcastConfigOptions(),this.notifyAgentChange("swapUpstream",o,e.runId),e.summarizedThroughEntry!==void 0&&this.persistWatermarkHook)try{this.persistWatermarkHook(e.summarizedThroughEntry)}catch(_){this.logger?.warn(`swapUpstream: persistWatermarkHook failed: ${_.message}`)}if(!r&&this.onCompactionSwapHook)try{this.onCompactionSwapHook({previousUpstreamSessionId:k,...w!==void 0?{previousSummarizedThroughEntry:w}:{},...e.runId!==void 0?{runId:e.runId}:{}})}catch(_){this.logger?.warn(`swapUpstream: onCompactionSwapHook failed: ${_.message}`)}let I=await this.retireAgent(S,r?"agent switch":e.reason==="workspace-enter"||e.reason==="workspace-leave"?"workspace move":"compaction swap");this.notifyChain("agent.swap",{phase:"post",previousUpstreamSessionId:k,upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}),r||this.broadcastCompactionPhase({phase:"swapped",...this.title!==void 0?{title:this.title}:{},summarizedThroughEntry:e.summarizedThroughEntry??this._summarizedThroughEntry??0}),r&&this.broadcastAgentSwitch(t,n);let b=I.length>0?`
|
|
34
34
|
Stopped ${I.length} background task(s) with the previous agent: ${I.join(", ")}. Re-arm anything still needed.
|
|
35
35
|
`:"",E=(e.reason==="workspace-enter"||e.reason==="workspace-leave"?"":r?`
|
|
36
36
|
Switched to ${n}.
|
|
@@ -40,7 +40,7 @@ Compaction completed.
|
|
|
40
40
|
|
|
41
41
|
`),this.departureNoteSent=!0}return r}applyWorkspacePromptRewrite(e){let t=this.workspace;if(t===void 0)return this.applyDepartedPromptRewrite(e);let n=!1,r=ki(e,i=>Vs(i,t.sourceCwd)?(n=!0,Js(i,t.sourceCwd,t.path).text):i);if(!this.workspacePreambleSent||n){let i=pi({workspacePath:t.path,sourceCwd:t.sourceCwd,notes:this.workspaceNotes,...this.workspacePreambleSent?{reassert:!0}:{}});r=Ks(r,`${i}
|
|
42
42
|
|
|
43
|
-
`),this.workspacePreambleSent=!0}return r}async prompt(e,t,n){let r=this.clients.get(e);if(!r)throw me(new Error("client not attached"),x.SessionNotFound);if(this.closing)throw me(new Error("session is closing; new prompts cannot be accepted"),x.SessionClosing);let o=Pe();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(Qe((t??{})._meta).ancillary===!0)&&this._interactive!==!0){this._interactive=!0;for(let a of this.interactiveHandlers)try{a(!0)}catch{}}return this.enqueueUserPrompt(r,t,o,n)}broadcastPromptReceived(e){this.closeUnsolicitedTurn("superseded",`prompt:${e.messageId}`);let t={clientId:e.originator.clientId};e.originator.name&&(t.name=e.originator.name),e.originator.version&&(t.version=e.originator.version),e.originator.fromSession&&(t.fromSession=e.originator.fromSession),e.originator.fromSessionTitle&&(t.fromSessionTitle=e.originator.fromSessionTitle),e.originator.fromLabel&&(t.fromLabel=e.originator.fromLabel),e.originator.depth!==void 0&&(t.depth=e.originator.depth),this.promptStartedAt=Date.now(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"prompt_received",messageId:e.messageId,prompt:e.prompt,sentBy:t}},e.clientId);let n=ht(e.prompt);n.length>0&&this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"user_message_chunk",content:{type:"text",text:n},_meta:{"hydra-acp":{compatFor:"prompt_received"}}}},e.clientId)}recordCurrentUsageSnapshot(){if(this.historyStore===void 0)return;let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let r={};typeof e.costAmount=="number"&&(r.amount=e.costAmount),typeof e.costCurrency=="string"&&(r.currency=e.costCurrency),t.cost=r}if(Object.keys(t).length<=1)return;t._meta={"hydra-acp":{upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}};let n={sessionId:this.sessionId,update:t};this.historyStore.append(this.sessionId,{method:"session/update",params:n,recordedAt:Date.now()}).catch(()=>{})}broadcastTurnComplete(e,t,n,r){let o=t&&typeof t=="object"&&"stopReason"in t&&typeof t.stopReason=="string"?t.stopReason:void 0,i={sessionUpdate:"turn_complete",messageId:Pe()};o!==void 0&&(i.stopReason=o);let a=Qe(t?._meta).salvaged;a!==void 0&&(i._meta={[ue]:{salvaged:a}}),this.supersededAutonomousTurn=void 0;let d=this.amendInProgress;d&&n!==void 0&&d.cancelledMessageId===n&&(i._meta={[ue]:{...a!==void 0?{salvaged:a}:{},amended:{cancelledMessageId:d.cancelledMessageId,newMessageId:d.newMessageId}}}),this.promptStartedAt=void 0,this.sawTurnComplete=!0,this.scheduleWorkspaceSnapshotHook?.(),n!==void 0&&o!==void 0&&this.recordTerminal(n,o),(o==="cancelled"||o==="error"||o==="refusal")&&this.closeOpenToolCalls(o),this.recordCurrentUsageSnapshot(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:i},r?void 0:e),d&&n!==void 0&&d.cancelledMessageId===n&&this.broadcastPromptAmended(d)}noteAgentActivity(e){if(!(this.closing||this.closed)){if(zu(e)){if(this.unsolicitedTurn!==void 0){this.closeUnsolicitedTurn("completed");return}this.salvageSupersededTerminal();return}Qs("session/update",e)||(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||this.openUnsolicitedTurn()))}}noteBackgroundTaskArming(e){let t=e?.update;if(!t||typeof t!="object")return;let n=typeof t.toolCallId=="string"?t.toolCallId:void 0;if(n===void 0)return;let r=t.rawInput,o=Yu(t._meta);this.rememberToolLabel(n,t,r,o),this.noteBackgroundTaskStopped(t,r,o);let i=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:Ku(t.rawOutput);if(!(i!==void 0||r!==void 0&&r.run_in_background===!0))return;let d=this.toolLabels.get(n)?.label??"background task";this.lastBackgroundTask={toolCallId:n,label:d};let c=Date.now(),u=this.armedTasks.get(n),l=i??u?.taskId,f=Qu(t.title,o,r)||u?.repeating===!0;this.armedTasks.set(n,{label:d,...l!==void 0?{taskId:l}:{},repeating:f,armedAt:u?.armedAt??c}),this.onArmedTasksChanged()}get armedBackgroundTasks(){return[...this.armedTasks.entries()].map(([e,t])=>({toolCallId:e,label:t.label,...t.taskId!==void 0?{taskId:t.taskId}:{}}))}get armedSince(){let e;for(let t of this.armedTasks.values())(e===void 0||t.armedAt<e)&&(e=t.armedAt);return e}onArmedTasksChanged(){let e=this.armedTasks.size,t=this.armedSince;e===this.lastArmedBroadcast?.count&&t===this.lastArmedBroadcast?.since||this.closed||(this.lastArmedBroadcast={count:e,since:t},this.broadcastQueueNotification("hydra-acp/session/armed_tasks_updated",{sessionId:this.sessionId,count:e,...t!==void 0?{since:t}:{},tasks:this.armedBackgroundTasks}))}async retireAgent(e,t){return await e.kill().catch(()=>{}),this.discardArmedTasks(t)}discardArmedTasks(e){if(this.armedTasks.size===0)return[];let t=[...this.armedTasks.values()].map(n=>n.label);return this.armedTasks.clear(),this.logger?.info(`session ${this.sessionId} discarded ${t.length} armed task(s) on ${e}: ${t.join(", ")}`),this.onArmedTasksChanged(),t}noteBackgroundTaskStopped(e,t,n){if(!(n?.toolName==="TaskStop"||e.title==="TaskStop"))return;let o=t?.task_id;if(typeof o!="string"||o.length===0)return;let i=!1;for(let[a,d]of this.armedTasks)d.taskId===o&&(this.armedTasks.delete(a),i=!0);i&&this.onArmedTasksChanged()}rememberToolLabel(e,t,n,r){let o=n!==void 0&&typeof n.description=="string"&&n.description?n.description:void 0;if(o!==void 0)this.toolLabels.set(e,{label:o.slice(0,yi),fromDescription:!0});else if(this.toolLabels.get(e)?.fromDescription!==!0){let i=typeof t.title=="string"&&t.title?t.title:typeof r?.toolName=="string"&&r.toolName?r.toolName:void 0;i!==void 0&&this.toolLabels.set(e,{label:i.slice(0,yi),fromDescription:!1})}for(;this.toolLabels.size>Ju;){let i=this.toolLabels.keys().next().value;if(i===void 0)break;this.toolLabels.delete(i)}}openUnsolicitedTurn(){let e=Date.now(),t=this.lastBackgroundTask,n=!1;for(let[i,a]of this.armedTasks)a.repeating||(this.armedTasks.delete(i),n=!0);n&&this.onArmedTasksChanged();let r={messageId:Pe(),startedAt:e,cause:t};this.unsolicitedTurn=r,this.promptStartedAt=e,this.logger?.info(`session ${this.sessionId} agent resumed with no prompt in flight`+(t?` (after ${t.label})`:""));let o={unsolicited:!0};t&&(o.cause=t),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"turn_started",messageId:r.messageId,_meta:{"hydra-acp":o}}})}async holdForUnsolicitedTurn(e){if(this.unsolicitedTurn===void 0){this.logger?.info(`session ${this.sessionId} queue hold skipped for ${e.messageId} (no unsolicited turn open)`);return}let t=Date.now(),n=this.unsolicitedTurn.cause;this.logger?.info(`session ${this.sessionId} holding ${e.messageId} behind unsolicited turn ${this.unsolicitedTurn.messageId}`+(n?` cause=${JSON.stringify(n.label)}`:"")),this.broadcastQueueNotification("hydra-acp/prompt_queue/held",{sessionId:this.sessionId,messageId:e.messageId,reason:"agent_resumed",...n?{cause:n}:{}});let r="turn_ended";for(;;){if(this.closing||this.closed){r="closing";break}if(e.cancelled){r="cancelled";break}if(this.unsolicitedTurn===void 0){r="turn_ended";break}await new Promise(i=>{let a=setTimeout(i,Vu);typeof a.unref=="function"&&a.unref()})}let o=Date.now()-t;this.logger?.info(`session ${this.sessionId} released ${e.messageId} reason=${r} heldMs=${o}`),this.broadcastQueueNotification("hydra-acp/prompt_queue/released",{sessionId:this.sessionId,messageId:e.messageId,reason:r,heldMs:o})}closeUnsolicitedTurn(e,t){let n=this.unsolicitedTurn;if(n===void 0)return;let r=Date.now()-n.startedAt;this.unsolicitedTurn=void 0,this.promptStartedAt=void 0,this.logger?.info(`session ${this.sessionId} unsolicited turn ${n.messageId} closed reason=${e} durationMs=${r}`+(t?` by=${t}`:"")+(n.cause?` cause=${JSON.stringify(n.cause.label)}`:"")),e==="superseded"&&(this.supersededAutonomousTurn={turnMessageId:n.messageId,cause:n.cause,supersededAt:Date.now()}),this.recordCurrentUsageSnapshot(),!this.closed&&(e==="cancelled"&&this.closeOpenToolCalls("cancelled"),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"turn_ended",messageId:Pe(),startedMessageId:n.messageId,durationMs:r,_meta:{"hydra-acp":{unsolicited:!0,reason:e}}}}))}salvageSupersededTerminal(){let e=this.supersededAutonomousTurn;if(e===void 0)return;this.supersededAutonomousTurn=void 0;let t=this.autonomousSalvage;t!==void 0&&(this.autonomousSalvage=void 0,this.logger?.warn(`session ${this.sessionId} salvaged session/prompt from autonomous terminal (superseded turn ${e.turnMessageId}, ${Date.now()-e.supersededAt}ms earlier)`+(e.cause?` cause=${JSON.stringify(e.cause.label)}`:"")),t({stopReason:"end_turn",_meta:{[ue]:{salvaged:{reason:"autonomous_terminal",supersededMessageId:e.turnMessageId}}}}))}async awaitPromptResponse(e){if(this.supersededAutonomousTurn===void 0)return e;try{return await new Promise((t,n)=>{this.autonomousSalvage=t,e.then(t,n)})}finally{this.autonomousSalvage=void 0}}recordTerminal(e,t){for(this.recentlyTerminal.set(e,{stopReason:t,terminatedAt:Date.now()});this.recentlyTerminal.size>Wu;){let n=this.recentlyTerminal.keys().next().value;if(n===void 0)break;this.recentlyTerminal.delete(n)}}broadcastPromptAmended(e){let t=this.findUserEntry(e.newMessageId);if(!t)return;let n={sessionId:this.sessionId,cancelledMessageId:e.cancelledMessageId,newMessageId:e.newMessageId,prompt:t.prompt,originator:t.originator,amendedAt:Date.now()};this.broadcastQueueNotification("hydra-acp/prompt/amended",n)}findUserEntry(e){if(this.currentEntry?.messageId===e&&this.currentEntry.kind==="user")return this.currentEntry;let t=this.promptQueue.find(n=>n.messageId===e&&n.kind==="user");return t?.kind==="user"?t:void 0}visibleQueueDepth(){let e=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled?1:0;for(let t of this.promptQueue)t.kind==="user"&&!t.cancelled&&(e+=1);return e}broadcastQueueAdded(e,t){let n=this.visibleQueueDepth(),r=t?.position??Math.max(0,n-1),o={sessionId:this.sessionId,messageId:e.messageId,originator:e.originator,prompt:e.prompt,position:r,queueDepth:n,enqueuedAt:e.enqueuedAt};t?.amending!==void 0&&(o._meta={"hydra-acp":{amending:t.amending}}),this.broadcastQueueNotification("hydra-acp/prompt_queue/added",o)}broadcastQueueUpdated(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/updated",{sessionId:this.sessionId,messageId:e,prompt:t})}broadcastQueueRemoved(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/removed",{sessionId:this.sessionId,messageId:e,reason:t})}broadcastQueueNotification(e,t){for(let n of this.clients.values())n.connection.notify(e,t).catch(()=>{})}queueSnapshot(){let e=[],t=0;this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled&&e.push({messageId:this.currentEntry.messageId,originator:this.currentEntry.originator,prompt:this.currentEntry.prompt,position:t++,enqueuedAt:this.currentEntry.enqueuedAt});for(let n of this.promptQueue)n.kind!=="user"||n.cancelled||e.push({messageId:n.messageId,originator:n.originator,prompt:n.prompt,position:t++,enqueuedAt:n.enqueuedAt});return e}async flushPersistWrites(){await this.queueWriteChain.catch(()=>{})}replayPersistedQueue(e){for(let t of e){let n={clientId:`hydra-resurrected_${t.messageId}`};t.originator.clientInfo.name!==void 0&&(n.name=t.originator.clientInfo.name),t.originator.clientInfo.version!==void 0&&(n.version=t.originator.clientInfo.version);let r={kind:"user",messageId:t.messageId,originator:n,clientId:n.clientId,prompt:t.prompt,enqueuedAt:t.enqueuedAt,cancelled:!1,resolve:()=>{},reject:()=>{}};this.promptQueue.push(r),this.broadcastQueueAdded(r)}this.drainQueue()}cancelQueuedPrompt(e){if(this.currentEntry?.messageId===e)return{cancelled:!1,reason:"already_running"};let t=this.promptQueue.findIndex(r=>r.messageId===e);if(t<0)return{cancelled:!1,reason:"not_found"};let n=this.promptQueue[t];return n.cancelled=!0,this.promptQueue.splice(t,1),n.kind==="user"&&(this.broadcastQueueRemoved(e,"cancelled"),this.persistRewrite()),this.amendInProgress?.newMessageId===e&&(this.amendInProgress=void 0),n.resolve({stopReason:"cancelled"}),{cancelled:!0,reason:"ok"}}updateQueuedPrompt(e,t){if(this.currentEntry?.messageId===e)return{updated:!1,reason:"already_running"};let n=this.promptQueue.find(r=>r.messageId===e);return!n||n.kind!=="user"?{updated:!1,reason:"not_found"}:(n.prompt=t,this.broadcastQueueUpdated(e,t),this.persistRewrite(),{updated:!0,reason:"ok"})}amendPrompt(e,t){let n=this.clients.get(e);if(!n)throw me(new Error("client not attached"),x.SessionNotFound);let{targetMessageId:r,prompt:o,replaceQueue:i,onTargetCompleted:a}=t;if(this.currentEntry?.messageId===r&&this.currentEntry.kind==="user"&&!this.currentEntry.cancelled&&this.amendInProgress===void 0)return this.amendOnHead(n,o,r,i);let d=this.promptQueue.find(u=>u.messageId===r&&u.kind==="user");if(d&&d.kind==="user"&&!d.cancelled)return d.prompt=o,this.broadcastQueueUpdated(r,o),this.persistRewrite(),{amended:!0,reason:"ok",messageId:r};let c=this.recentlyTerminal.get(r);return c?c.stopReason==="cancelled"?{amended:!1,reason:"target_cancelled"}:a==="send_anyway"?{amended:!1,reason:"target_completed",messageId:this.enqueueAmendmentAsFollowUp(n,o)}:{amended:!1,reason:"target_completed"}:{amended:!1,reason:"target_not_found"}}amendOnHead(e,t,n,r){let o=Pe(),i={clientId:e.clientId};if(e.clientInfo?.name&&(i.name=e.clientInfo.name),e.clientInfo?.version&&(i.version=e.clientInfo.version),r){let d=[];for(let c of this.promptQueue){if(c.kind==="user"&&!c.cancelled){c.cancelled=!0,this.broadcastQueueRemoved(c.messageId,"cancelled"),c.resolve({stopReason:"cancelled"});continue}d.push(c)}this.promptQueue=d}let a={kind:"user",messageId:o,originator:i,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,wasAmend:!0,resolve:()=>{},reject:()=>{}};return this.promptQueue.unshift(a),this.persistRewrite(),this.broadcastQueueAdded(a,{amending:n,position:1}),this.amendInProgress={cancelledMessageId:n,newMessageId:o},this.cancelExtensionDispatch(n,"amended"),this.agent.connection.notify("session/cancel",{sessionId:this.upstreamSessionId}).catch(()=>{}),{amended:!0,reason:"ok",messageId:o}}enqueueAmendmentAsFollowUp(e,t){let n=Pe(),r={clientId:e.clientId};e.clientInfo?.name&&(r.name=e.clientInfo.name),e.clientInfo?.version&&(r.version=e.clientInfo.version);let o={kind:"user",messageId:n,originator:r,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,resolve:()=>{},reject:()=>{}};return this.promptQueue.push(o),this.persistRewrite(),this.broadcastQueueAdded(o),this.drainQueue(),n}async cancel(e){if(!this.clients.get(e))throw me(new Error("client not attached"),x.SessionNotFound);this.lastCancelAt=Date.now(),this.currentEntry?.kind==="user"&&this.currentEntry.messageId!==void 0&&this.cancelExtensionDispatch(this.currentEntry.messageId,"cancelled"),this.closeUnsolicitedTurn("cancelled"),this.agentTurnInFlight||this.closeOpenToolCalls("cancelled"),await this.forwardRequest("session/cancel",{sessionId:this.sessionId},new Set,0,"notification")}addTransformer(e){let t=this.transformChain.findIndex(n=>n.name===e.name);t>=0?this.transformChain[t]=e:this.transformChain.push(e),e.intercepts.has("lifecycle:session.opened")&&e.connection.notify("hydra-acp/transformer/session_event",{event:"session.opened",sessionId:this.sessionId}).catch(()=>{})}async forwardRequest(e,t,n=new Set,r=0,o="request"){let i=this.rewriteForAgent(t);for(let a=r;a<this.transformChain.length;a++){let d=this.transformChain[a];if(n.has(d.name))continue;let c=`request:${e}`;if(!d.intercepts.has(c))continue;let u=`t_${Gs()}`,l;try{l=await d.connection.request("hydra-acp/transformer/message",{token:u,phase:"request",method:e,direction:"client\u2192agent",sessionId:this.sessionId,envelope:i})}catch(p){this.logger?.warn(`transformer ${d.name} error on ${c}: ${p.message}`);continue}let f=l?.action??"continue";if(f==="stop")return o==="notification"?void 0:l?.payload??Ys(e);if(f==="continue"){l?.payload&&typeof l.payload=="object"&&(i=l.payload),n.add(d.name);continue}if(f==="processing"){let p=a,g=i,m=new Set(n);return new Promise(h=>{let y=setTimeout(()=>{this.pendingClaims.delete(u)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:u,transformerName:d.name}),this.forwardRequest(e,g,new Set([...m,d.name]),p+1,o).then(h).catch(()=>h(o==="notification"?void 0:Ys(e))))},kn);typeof y.unref=="function"&&y.unref(),this.pendingClaims.set(u,{resolve:h,timer:y,transformerName:d.name,method:e,envelope:g,chainIdx:p,originatedBy:m,side:"request",tailKind:o})})}n.add(d.name)}if(o==="notification"){await this.agent.connection.notify(e,i);return}return this.agent.connection.request(e,i)}async forwardModelChange(e,t){let n=await Je({request:(r,o)=>this.forwardRequest(r,o),sessionId:this.sessionId,modelId:e,verb:this.modelVerb,extraParams:t,logger:this.logger});return this.modelVerb=n.verb,this.modelVerbConfirmed=!0,n.result}noteModelVerbHint(e,t){e===void 0||this.modelVerbConfirmed||e===this.modelVerb||(this.logger?.info(`model verb for agent ${this.agentId} inferred as ${e} from ${t} (was ${this.modelVerb})`),this.modelVerb=e)}resetModelVerb(e){this.modelVerb=e??Re,this.modelVerbConfirmed=!1}async runAgentRequestChain(e,t,n=new Set,r=0){let o=t,i=`request:${e}`;for(let a=r;a<this.transformChain.length;a++){let d=this.transformChain[a];if(n.has(d.name)||!d.intercepts.has(i))continue;let c=`t_${Gs()}`,u;try{u=await d.connection.request("hydra-acp/transformer/message",{token:c,phase:"request",method:e,direction:"agent\u2192client",sessionId:this.sessionId,envelope:o})}catch(f){this.logger?.warn(`transformer ${d.name} error on ${i}: ${f.message}`);continue}let l=u?.action??"continue";if(l==="stop")return{shortCircuit:!0,payload:u?.payload??cl(e)};if(l==="continue"){u?.payload&&typeof u.payload=="object"&&(o=u.payload),n.add(d.name);continue}if(l==="processing"){let f=a,p=o,g=new Set(n),m=e;return new Promise(h=>{let y=setTimeout(()=>{this.pendingClaims.delete(c)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:c,transformerName:d.name}),this.runAgentRequestChain(m,p,new Set([...g,d.name]),f+1).then(h).catch(()=>h({shortCircuit:!1,envelope:p})))},kn);typeof y.unref=="function"&&y.unref(),this.pendingClaims.set(c,{resolve:k=>h({shortCircuit:!0,payload:k}),timer:y,transformerName:d.name,method:m,envelope:p,chainIdx:f,originatedBy:g,side:"agent-request"})})}n.add(d.name)}return{shortCircuit:!1,envelope:o}}dischargeClaim(e,t){let n=this.pendingClaims.get(e);return n?(clearTimeout(n.timer),this.pendingClaims.delete(e),n.resolve(t),!0):!1}keepAliveClaim(e,t){let n=this.pendingClaims.get(e);if(!n)return!1;clearTimeout(n.timer);let r=typeof t=="number"&&t>0?Math.min(t*1.5,1800*1e3):kn,o=setTimeout(()=>{if(this.pendingClaims.delete(e))if(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:e,transformerName:n.transformerName}),n.side==="response")this.runResponseChain(n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1).then(()=>n.resolve(void 0)).catch(()=>n.resolve(void 0));else if(n.side==="agent-request")this.runAgentRequestChain(n.method,n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1).then(n.resolve).catch(()=>n.resolve({shortCircuit:!1,envelope:n.envelope}));else{let i=n.tailKind??"request";this.forwardRequest(n.method,n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1,i).then(n.resolve).catch(()=>n.resolve(i==="notification"?void 0:Ys(n.method)))}},r);return typeof o.unref=="function"&&o.unref(),n.timer=o,!0}async emitToChain(e,t,n){let r=this.transformChain.findIndex(a=>a.name===e),o=r>=0?r+1:0,i=new Set([e]);if(t==="session/update"){await this.runResponseChain(n,i,o);return}return this.forwardRequest(t,n,i,o)}async emitToQueue(e,t){let n=this.transformChain.findIndex(c=>c.name===e),r=n>=0?n+1:0,o=(t??{}).prompt??[],i=Pe(),a=`transformer:${e}`,d={clientId:a,name:e};return new Promise((c,u)=>{let l={kind:"user",messageId:i,originator:d,clientId:a,prompt:o,enqueuedAt:Date.now(),cancelled:!1,emitterName:e,chainStartIdx:r,resolve:c,reject:u},f=this.insertEntryAt(l,"tail");this.persistRewrite(),this.broadcastQueueAdded(l,{position:f}),this.drainQueue()})}rewriteForAgent(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(t.sessionId===this.sessionId)return{...t,sessionId:this.upstreamSessionId}}return e}async close(e={}){if(e.deleteRecord&&(this.deleteRecordIntent=!0),!this.closed)return this.closeInFlight?this.closeInFlight:(this.closing=!0,this.closeInFlight=this.doClose(e),this.closeInFlight)}async doClose(e){let t=this.turnStartedAt!==void 0;this.logger?.info(`session ${this.sessionId} closing deleteRecord=${e.deleteRecord??!1} by=${e.by??"unknown"} midTurn=${t} unsolicitedTurn=${this.unsolicitedTurn!==void 0} queued=${this.promptQueue.length} awaitingPermission=${this.hasPermissionFlag}`),t&&this.logger?.warn(`session ${this.sessionId} closed mid-turn by=${e.by??"unknown"}; the in-flight turn will not settle and the agent is being killed`),this.cancelIdleTimer();for(let n of this.pendingClaims.values())clearTimeout(n.timer);this.pendingClaims.clear(),await this.agent.kill().catch(()=>{}),this.markClosed({deleteRecord:e.deleteRecord??!1})}onClose(e){return this.closeHandlers.push(e),()=>{let t=this.closeHandlers.indexOf(e);t>=0&&this.closeHandlers.splice(t,1)}}onTitleChange(e){this.titleHandlers.push(e)}retitle(e){return this.runTitleCommand(e)}retitleFromAgent(){return this.runTitleCommand("")}setTitle(e){let t=e.trim();if(!(!t||t===this.title)){this.title=t,this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",title:t,updatedAt:new Date().toISOString()}});for(let n of this.titleHandlers)try{n(t)}catch{}}}maybeSeedTitleFromPrompt(e){if(this.firstPromptSeeded||Qe((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let r=ht((e??{}).prompt),o=Xs(r,200);o&&(o.startsWith("/")||(this._firstPromptSeeded=!0,this.setTitle(o)))}maybeApplyAgentModel(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="current_model_update")return!1;let r=yt(n.availableModels);r.length>0&&this.setAgentAdvertisedModels(r);let o=typeof n.currentModel=="string"?n.currentModel:typeof n.model=="string"?n.model:void 0;if(o===void 0)return!0;let i=o.trim();if(!i||i===this.currentModel)return!0;this.logger?.info(`live current_model_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(i)}`),this.currentModel=i;for(let a of this.modelHandlers)try{a(i)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentConfigOption(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="config_option_update")return!1;let r=n.configOptions;if(!Array.isArray(r))return!0;for(let o of r){if(!o||typeof o!="object")continue;let i=o;if(i.id==="model"){let a=yt(i.options);a.length>0&&this.setAgentAdvertisedModels(a);let d=i.currentValue;if(typeof d=="string"){let c=d.trim();c&&c!==this.currentModel&&(this.logger?.info(`live config_option_update(model): sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(c)}`),this.applyModelChange(c))}}else if(i.id==="mode"){let a=Ht(i.options);a.length>0&&this.setAgentAdvertisedModes(a);let d=i.currentValue;if(typeof d=="string"){let c=d.trim();c&&c!==this.currentMode&&(this.logger?.info(`live config_option_update(mode): sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(c)}`),this.applyModeChange(c))}}else if(typeof i.id=="string"&&i.id.trim()){let a=i.id.trim(),d=yt(i.options);if(d.length>0){let c=Ht(i.options),u=c.length>0?c.map(h=>({value:h.id,name:h.name??h.id})):d.map(h=>({value:h.modelId,name:h.name??h.modelId})),l=i.name,f=typeof l=="string"&&l.trim()?l.trim():a,p=i.currentValue,g=typeof p=="string"&&p.trim()?p.trim():u[0]?.value??"",m=this.agentAdvertisedConfigOptions.findIndex(h=>h.id===a);if(m>=0){let h={...this.agentAdvertisedConfigOptions[m]};h.options=u,typeof p=="string"&&p.trim()&&(h.currentValue=p.trim()),this.agentAdvertisedConfigOptions[m]=h}else this.agentAdvertisedConfigOptions.push({id:a,name:f,category:"other",type:"select",currentValue:g,options:u})}}}return!0}maybeApplyAgentMode(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="current_mode_update")return!1;let r=typeof n.currentModeId=="string"?n.currentModeId:typeof n.currentMode=="string"?n.currentMode:typeof n.mode=="string"?n.mode:void 0;if(r===void 0)return!0;let o=r.trim();if(!o||o===this.currentMode)return!0;this.logger?.info(`current_mode_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(o)}`),this.currentMode=o;for(let i of this.modeHandlers)try{i(o)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentUsage(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="usage_update")return!1;let r={...this._currentUsage??{}},o=!1;if(typeof n.used=="number"&&r.used!==n.used&&(r.used=n.used,o=!0),typeof n.size=="number"&&r.size!==n.size&&(r.size=n.size,o=!0),n.cost&&typeof n.cost=="object"){let a=n.cost;typeof a.amount=="number"&&(this.reconcileCostLedger(a.amount)&&(o=!0),r.costAmount!==a.amount&&(r.costAmount=a.amount,o=!0)),typeof a.currency=="string"&&r.costCurrency!==a.currency&&(r.costCurrency=a.currency,o=!0)}if(!o)return!0;this._currentUsage=r;let i=this.persistableUsage??r;for(let a of this.usageHandlers)try{a(i)}catch{}return!0}armCostLedgerProbe(){let e=this._currentUsage?.costAmount;typeof e=="number"&&e>0&&(this.costLedgerProbe=e)}reconcileCostLedger(e){let t=this.costLedgerProbe;return t===void 0||(this.costLedgerProbe=void 0,e>=t-1e-6)?!1:(this.cumulativeCost+=t,!0)}notifyAgentChange(e,t,n){let r=this.retiringGenerationCost;this.retiringGenerationCost=void 0;for(let o of this.agentChangeHandlers)try{o({agentId:this.agentId,upstreamSessionId:this.upstreamSessionId,...r!==void 0?{retiredCost:r}:{},...t!==void 0?{reason:t}:{},...n!==void 0?{runId:n}:{}})}catch(i){this.logger?.warn(`${e}: agentChange handler failed: ${i.message}`)}}accumulateAndResetCost(){let e=this._currentUsage?.costAmount;e&&(this.cumulativeCost+=e,this.retiringGenerationCost=e);let t={used:0,cumulativeCost:this.cumulativeCost,...typeof this._currentUsage?.size=="number"?{size:this._currentUsage.size}:{},...this._currentUsage?.costCurrency?{costCurrency:this._currentUsage.costCurrency}:{}};this._currentUsage=t;for(let n of this.usageHandlers)try{n(t)}catch{}this.broadcastCurrentUsage()}broadcastCurrentUsage(){let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let n={};typeof e.costAmount=="number"&&(n.amount=e.costAmount),typeof e.costCurrency=="string"&&(n.currency=e.costCurrency),t.cost=n}this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:t})}injectCumulativeCost(e){if(!this.cumulativeCost||!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let n=t.update;if(n.sessionUpdate!=="usage_update"||!n.cost||typeof n.cost!="object")return e;let r=n.cost;return typeof r.amount!="number"?e:{...t,update:{...n,cost:{...r,amount:this.cumulativeCost+r.amount}}}}get totalUsage(){return this.currentUsage}setAgentAdvertisedCommands(e){if(Xu(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(Zu(this.agentAdvertisedModes,e)){this.broadcastAvailableModes();return}this.agentAdvertisedModes=e;for(let t of this.agentModesHandlers)try{t(e)}catch{}this.broadcastAvailableModes()}setAgentAdvertisedModels(e){if(this.logger?.info(`setAgentAdvertisedModels: sessionId=${this.sessionId} currentModel=${JSON.stringify(this.currentModel)} newList=[${e.map(t=>t.modelId).join(",")}]`),el(this.agentAdvertisedModels,e)){this.broadcastAvailableModels();return}this.agentAdvertisedModels=e;for(let t of this.agentModelsHandlers)try{t(e)}catch{}this.broadcastAvailableModels()}onAgentCommandsChange(e){this.agentCommandsHandlers.push(e)}onAgentModesChange(e){this.agentModesHandlers.push(e)}onAgentModelsChange(e){this.agentModelsHandlers.push(e)}onModelChange(e){this.modelHandlers.push(e)}onModeChange(e){this.modeHandlers.push(e)}onInteractiveChange(e){this.interactiveHandlers.push(e)}onPriorityChange(e){this.priorityHandlers.push(e)}setPriority(e){let t=e===void 0||e<=0?void 0:Math.floor(e);if(t!==this._priority){this._priority=t,this.updatedAt=Date.now();for(let n of this.priorityHandlers)try{n(t)}catch{}}}applyModelChange(e){let t=e.trim();if(t){this.modelChangeInFlight=!0;try{if(t!==this.currentModel){this.logger?.info(`applyModelChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(t)}`),this.currentModel=t;for(let r of this.modelHandlers)try{r(t)}catch{}}let n={sessionUpdate:"current_model_update",currentModel:t};this.agentAdvertisedModels.length>0&&(n.availableModels=[...this.agentAdvertisedModels]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modelChangeInFlight=!1}}}applyModeChange(e){let t=e.trim();if(t){this.modeChangeInFlight=!0;try{if(t!==this.currentMode){this.logger?.info(`applyModeChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(t)}`),this.currentMode=t;for(let r of this.modeHandlers)try{r(t)}catch{}}let n={sessionUpdate:"current_mode_update",currentModeId:t};this.agentAdvertisedModes.length>0&&(n.availableModes=[...this.agentAdvertisedModes]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modeChangeInFlight=!1}}}buildConfigOptions(){let e=[];if(this.agentAdvertisedModels.length>0){let r=this.agentAdvertisedModels.map(i=>({value:i.modelId,name:i.name??i.modelId,...i.description!==void 0?{description:i.description}:{}})),o=this.currentModel&&r.some(i=>i.value===this.currentModel)?this.currentModel:r[0].value;e.push({id:"model",name:"Model",category:"model",type:"select",currentValue:o,options:r})}if(this.agentAdvertisedModes.length>0){let r=this.agentAdvertisedModes.map(i=>({value:i.id,name:i.name??i.id,...i.description!==void 0?{description:i.description}:{}})),o=this.currentMode&&r.some(i=>i.value===this.currentMode)?this.currentMode:r[0].value;e.push({id:"mode",name:"Session Mode",category:"mode",type:"select",currentValue:o,options:r})}let n=(this.availableAgentsFn?.()??[]).map(r=>({value:r.id,name:r.name??r.id,...r.description!==void 0?{description:r.description}:{}}));return n.some(r=>r.value===this.agentId)||n.unshift({value:this.agentId,name:this.agentId}),e.push({id:"agent",name:"Agent",category:"_hydra_agent",type:"select",currentValue:this.agentId,options:n}),e.push(...this.agentAdvertisedConfigOptions),e}broadcastConfigOptions(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"config_option_update",configOptions:this.buildConfigOptions()}})}mergeAgentOptionIntoEnvelope(e){if(!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let n=t.update,r=Array.isArray(n.configOptions)?[...n.configOptions]:[];if(r.some(a=>a&&typeof a=="object"&&a.id==="agent"))return e;let i=this.buildConfigOptions().find(a=>a.id==="agent");return i?{...t,update:{...n,configOptions:[...r,i]}}:e}onUsageChange(e){this.usageHandlers.push(e)}mergedAvailableCommands(){let e=this.daemonTopLevelCommands(),t=this.aliasableBareVerbs();for(let n of ft){if(t.get(n.verb)!=="__hydra__")continue;let r=n.argsHint?`${n.verb} ${n.argsHint}`:n.verb;e.push({name:r,description:`Alias for '/hydra ${n.verb}': ${n.description}`})}if(this.extensionCommands)for(let{name:n,command:r}of this.extensionCommands.list()){let o=r.verb?`hydra ${n} ${r.verb}`:`hydra ${n}`,a={name:r.argsHint?`${o} ${r.argsHint}`:o};r.description&&(a.description=r.description),e.push(a);let d=n.startsWith("hydra-acp-")?n.slice(10):n;if(n.startsWith("hydra-acp-")&&d.length>0){let c=r.verb?`hydra ${d} ${r.verb}`:`hydra ${d}`,l={name:r.argsHint?`${c} ${r.argsHint}`:c};r.description&&(l.description=r.description),e.push(l)}if(d.length>0&&t.get(d)===n){let c=r.verb?`${d} ${r.verb}`:d,l={name:r.argsHint?`${c} ${r.argsHint}`:c};r.description&&(l.description=r.description),e.push(l)}}return e.push(...this.agentAdvertisedCommands),e}daemonTopLevelCommands(){return[{name:"hydra",description:"Hydra session command (kill, restart, title, agent <agent>)"},{name:"model",description:"Switch model; omit arg to list available models"},{name:"mode",description:"Switch mode; omit arg to list available modes"},{name:"sessions",description:"List all sessions"},{name:"help",description:"Show available commands"}]}aliasableBareVerbs(){let e=new Set,t=i=>i.split(/\s+/)[0]??"";for(let i of this.daemonTopLevelCommands()){let a=t(i.name);a&&e.add(a)}for(let i of this.agentAdvertisedCommands){let a=t(i.name),d=a.startsWith("/")?a.slice(1):a;d&&e.add(d)}let n=new Map;for(let i of ft)e.has(i.verb)||n.set(i.verb,"__hydra__");if(!this.extensionCommands)return n;let r=new Map,o=new Set;for(let{name:i}of this.extensionCommands.list()){if(o.has(i))continue;o.add(i);let a=i.startsWith("hydra-acp-")?i.slice(10):i;if(!a||e.has(a)||n.has(a))continue;let d=r.get(a);d===void 0?r.set(a,i):d!==i&&r.set(a,"__conflict__")}for(let[i,a]of r)a!=="__conflict__"&&n.set(i,a);return n}agentOnlyAdvertisedCommands(){return[...this.agentAdvertisedCommands]}agentKnowsSlashCommand(e){let t=r=>r.startsWith("/")?r.slice(1):r,n=t(e);if(!n)return!1;for(let r of this.agentAdvertisedCommands)if(t(r.name.split(/\s+/)[0]??"")===n)return!0;return!1}availableModes(){return[...this.agentAdvertisedModes]}availableModels(){return[...this.agentAdvertisedModels]}maybeApplyAgentSessionInfo(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="session_info_update"||typeof n.title!="string")return;let r=n.title.trim();if(!(!r||r===this.title)){this.title=r,this._firstPromptSeeded=!0;for(let o of this.titleHandlers)try{o(r)}catch{}}}async handleSlashCommand(e,t){let r=e.slice(6).trim().match(/^(\S+)(?:\s+([\s\S]*))?$/),o=r?.[1]??"",i=(r?.[2]??"").trim();if(o==="")return{stopReason:"end_turn"};let a=t!==void 0;if(ft.some(l=>l.verb===o))switch(o){case"title":return a?this.runTitleCommandInline(i):this.runTitleCommand(i);case"agent":return this.runAgentCommandInline(i);case"config":return this.handleConfigCommand(`/config ${i}`);case"kill":return this.runKillCommand();case"workspace":return this.runWorkspaceCommand(i);case"restart":return a?this.runRestartCommandInline():this.runRestartCommand();case"compact":return a?this.runCompactCommandInline(i):this.runCompactCommand(i);case"uncompact":return a?this.runUncompactCommandInline():this.runUncompactCommand();case"fork":return a?this.runForkCommandInline(i,t):this.runForkCommand(i);default:{let l=new Error(`no dispatcher for /hydra verb ${o}`);throw l.code=x.InternalError,l}}if(this.extensionCommands?.has(o))return a?this.runExtensionCommandInline(o,i,t):this.runExtensionCommand(o,i);let d=`hydra-acp-${o}`;if(this.extensionCommands?.has(d))return a?this.runExtensionCommandInline(d,i,t):this.runExtensionCommand(d,i);let c=ft.map(l=>l.verb);if(this.extensionCommands){let l=new Set;for(let{name:f}of this.extensionCommands.list())l.has(f)||(c.push(f),l.add(f))}let u=new Error(`unknown /hydra verb: ${o} (known: ${c.join(", ")})`);throw u.code=x.InvalidParams,u}runExtensionCommand(e,t){return this.enqueuePrompt(`extension:${e}`,()=>this.runExtensionCommandInline(e,t,void 0))}async runExtensionCommandInline(e,t,n){let r=this.extensionCommands?.get(e);if(!r)return this.emitExtensionReply(`extension "${e}" is no longer connected`);let o=t.match(/^(\S+)(?:\s+([\s\S]*))?$/),i=o?.[1]??"",a=(o?.[2]??"").trim();if(!r.commands.some(g=>g.verb===i)){let g=r.commands.map(m=>m.verb).join(", ");return this.emitExtensionReply(`/hydra ${e}${i?` ${i}`:""}: unknown verb (known: ${g||"(none)"})`)}let d={sessionId:this.sessionId,verb:i,args:a};n!==void 0&&(d.messageId=n);let c=()=>{},u=new Promise(g=>{c=g});n!==void 0&&this.inFlightExtensionDispatches.set(n,{extensionName:e,connection:r.connection,cancel:g=>c({stopReason:"cancelled",reason:g})});let l,f=!1;try{let g=r.connection.request("hydra-acp/commands/invoke",d),m=await Promise.race([g,u]);if(m&&typeof m=="object"&&m.stopReason==="cancelled"&&"reason"in m)return f=!0,this.logger?.info(`extension ${e} ${i} cancelled (cancelExtensionDispatch); abandoning in-flight commands/invoke`),{stopReason:"cancelled"};l=m}catch(g){return this.emitExtensionReply(`${e} ${i}: ${g.message}`)}finally{n!==void 0&&!f&&this.inFlightExtensionDispatches.delete(n)}let p=l&&typeof l=="object"&&typeof l.text=="string"?l.text:"";return p.length>0?this.emitExtensionReply(p):{stopReason:"end_turn"}}cancelExtensionDispatch(e,t){let n=this.inFlightExtensionDispatches.get(e);if(!n)return!1;this.inFlightExtensionDispatches.delete(e);try{n.connection.notify("hydra-acp/commands/cancel",{sessionId:this.sessionId,messageId:e,reason:t})}catch(r){this.logger?.warn(`notify commands/cancel to ${n.extensionName} failed: ${r.message}`)}return n.cancel(t),!0}emitExtensionReply(e){return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
|
|
43
|
+
`),this.workspacePreambleSent=!0}return r}async prompt(e,t,n){let r=this.clients.get(e);if(!r)throw me(new Error("client not attached"),x.SessionNotFound);if(this.closing)throw me(new Error("session is closing; new prompts cannot be accepted"),x.SessionClosing);let o=Pe();if(this.maybeSeedTitleFromPrompt(t),this._firstPromptSeeded=!0,!(Qe((t??{})._meta).ancillary===!0)&&this._interactive!==!0){this._interactive=!0;for(let a of this.interactiveHandlers)try{a(!0)}catch{}}return this.enqueueUserPrompt(r,t,o,n)}broadcastPromptReceived(e){this.closeUnsolicitedTurn("superseded",`prompt:${e.messageId}`);let t={clientId:e.originator.clientId};e.originator.name&&(t.name=e.originator.name),e.originator.version&&(t.version=e.originator.version),e.originator.fromSession&&(t.fromSession=e.originator.fromSession),e.originator.fromSessionTitle&&(t.fromSessionTitle=e.originator.fromSessionTitle),e.originator.fromLabel&&(t.fromLabel=e.originator.fromLabel),e.originator.depth!==void 0&&(t.depth=e.originator.depth),this.promptStartedAt=Date.now(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"prompt_received",messageId:e.messageId,prompt:e.prompt,sentBy:t}},e.clientId);let n=ht(e.prompt);n.length>0&&this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"user_message_chunk",content:{type:"text",text:n},_meta:{"hydra-acp":{compatFor:"prompt_received"}}}},e.clientId)}recordCurrentUsageSnapshot(){if(this.historyStore===void 0)return;let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let r={};typeof e.costAmount=="number"&&(r.amount=e.costAmount),typeof e.costCurrency=="string"&&(r.currency=e.costCurrency),t.cost=r}if(Object.keys(t).length<=1)return;t._meta={"hydra-acp":{upstreamSessionId:this.upstreamSessionId,agentId:this.agentId}};let n={sessionId:this.sessionId,update:t};this.historyStore.append(this.sessionId,{method:"session/update",params:n,recordedAt:Date.now()}).catch(()=>{})}broadcastTurnComplete(e,t,n,r){let o=t&&typeof t=="object"&&"stopReason"in t&&typeof t.stopReason=="string"?t.stopReason:void 0,i={sessionUpdate:"turn_complete",messageId:Pe()};o!==void 0&&(i.stopReason=o);let a=Qe(t?._meta).salvaged;a!==void 0&&(i._meta={[ue]:{salvaged:a}}),this.supersededAutonomousTurn=void 0;let d=this.amendInProgress;d&&n!==void 0&&d.cancelledMessageId===n&&(i._meta={[ue]:{...a!==void 0?{salvaged:a}:{},amended:{cancelledMessageId:d.cancelledMessageId,newMessageId:d.newMessageId}}}),this.promptStartedAt=void 0,this.sawTurnComplete=!0,this.scheduleWorkspaceSnapshotHook?.(),n!==void 0&&o!==void 0&&this.recordTerminal(n,o),(o==="cancelled"||o==="error"||o==="refusal")&&this.closeOpenToolCalls(o),this.recordCurrentUsageSnapshot(),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:i},r?void 0:e),d&&n!==void 0&&d.cancelledMessageId===n&&this.broadcastPromptAmended(d)}noteAgentActivity(e){if(!(this.closing||this.closed)){if(zu(e)){if(this.unsolicitedTurn!==void 0){this.closeUnsolicitedTurn("completed");return}this.salvageSupersededTerminal();return}Qs("session/update",e)||(this.noteBackgroundTaskArming(e),this.unsolicitedTurn===void 0&&(this.promptInFlight||!this.sawTurnComplete||this.openUnsolicitedTurn()))}}noteBackgroundTaskArming(e){let t=e?.update;if(!t||typeof t!="object")return;let n=typeof t.toolCallId=="string"?t.toolCallId:void 0;if(n===void 0)return;let r=t.rawInput,o=Yu(t._meta);this.rememberToolLabel(n,t,r,o),this.noteBackgroundTaskStopped(t,r,o);let i=typeof o?.toolResponse?.taskId=="string"?o.toolResponse.taskId:Ku(t.rawOutput);if(!(i!==void 0||r!==void 0&&r.run_in_background===!0))return;let d=this.toolLabels.get(n)?.label??"background task";this.lastBackgroundTask={toolCallId:n,label:d};let c=Date.now(),u=this.armedTasks.get(n),l=i??u?.taskId,f=Qu(t.title,o,r)||u?.repeating===!0;this.armedTasks.set(n,{label:d,...l!==void 0?{taskId:l}:{},repeating:f,armedAt:u?.armedAt??c}),this.onArmedTasksChanged()}get armedBackgroundTasks(){return[...this.armedTasks.entries()].map(([e,t])=>({toolCallId:e,label:t.label,...t.taskId!==void 0?{taskId:t.taskId}:{}}))}get armedSince(){let e;for(let t of this.armedTasks.values())(e===void 0||t.armedAt<e)&&(e=t.armedAt);return e}onArmedTasksChanged(){let e=this.armedTasks.size,t=this.armedSince;e===this.lastArmedBroadcast?.count&&t===this.lastArmedBroadcast?.since||this.closed||(this.lastArmedBroadcast={count:e,since:t},this.broadcastQueueNotification("hydra-acp/session/armed_tasks_updated",{sessionId:this.sessionId,count:e,...t!==void 0?{since:t}:{},tasks:this.armedBackgroundTasks}))}async retireAgent(e,t){return await e.kill().catch(()=>{}),this.discardArmedTasks(t)}discardArmedTasks(e){if(this.armedTasks.size===0)return[];let t=[...this.armedTasks.values()].map(n=>n.label);return this.armedTasks.clear(),this.logger?.info(`session ${this.sessionId} discarded ${t.length} armed task(s) on ${e}: ${t.join(", ")}`),this.onArmedTasksChanged(),t}noteBackgroundTaskStopped(e,t,n){if(!(n?.toolName==="TaskStop"||e.title==="TaskStop"))return;let o=t?.task_id;if(typeof o!="string"||o.length===0)return;let i=!1;for(let[a,d]of this.armedTasks)d.taskId===o&&(this.armedTasks.delete(a),i=!0);i&&this.onArmedTasksChanged()}rememberToolLabel(e,t,n,r){let o=n!==void 0&&typeof n.description=="string"&&n.description?n.description:void 0;if(o!==void 0)this.toolLabels.set(e,{label:o.slice(0,yi),fromDescription:!0});else if(this.toolLabels.get(e)?.fromDescription!==!0){let i=typeof t.title=="string"&&t.title?t.title:typeof r?.toolName=="string"&&r.toolName?r.toolName:void 0;i!==void 0&&this.toolLabels.set(e,{label:i.slice(0,yi),fromDescription:!1})}for(;this.toolLabels.size>Ju;){let i=this.toolLabels.keys().next().value;if(i===void 0)break;this.toolLabels.delete(i)}}openUnsolicitedTurn(){let e=Date.now(),t=this.lastBackgroundTask,n=!1;for(let[i,a]of this.armedTasks)a.repeating||(this.armedTasks.delete(i),n=!0);n&&this.onArmedTasksChanged();let r={messageId:Pe(),startedAt:e,cause:t};this.unsolicitedTurn=r,this.promptStartedAt=e,this.logger?.info(`session ${this.sessionId} agent resumed with no prompt in flight`+(t?` (after ${t.label})`:""));let o={unsolicited:!0};t&&(o.cause=t),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"turn_started",messageId:r.messageId,_meta:{"hydra-acp":o}}})}async holdForUnsolicitedTurn(e){if(this.unsolicitedTurn===void 0){this.logger?.info(`session ${this.sessionId} queue hold skipped for ${e.messageId} (no unsolicited turn open)`);return}let t=Date.now(),n=this.unsolicitedTurn.cause;this.logger?.info(`session ${this.sessionId} holding ${e.messageId} behind unsolicited turn ${this.unsolicitedTurn.messageId}`+(n?` cause=${JSON.stringify(n.label)}`:"")),this.broadcastQueueNotification("hydra-acp/prompt_queue/held",{sessionId:this.sessionId,messageId:e.messageId,reason:"agent_resumed",...n?{cause:n}:{}});let r="turn_ended";for(;;){if(this.closing||this.closed){r="closing";break}if(e.cancelled){r="cancelled";break}if(this.unsolicitedTurn===void 0){r="turn_ended";break}await new Promise(i=>{let a=setTimeout(i,Vu);typeof a.unref=="function"&&a.unref()})}let o=Date.now()-t;this.logger?.info(`session ${this.sessionId} released ${e.messageId} reason=${r} heldMs=${o}`),this.broadcastQueueNotification("hydra-acp/prompt_queue/released",{sessionId:this.sessionId,messageId:e.messageId,reason:r,heldMs:o})}closeUnsolicitedTurn(e,t){let n=this.unsolicitedTurn;if(n===void 0)return;let r=Date.now()-n.startedAt;this.unsolicitedTurn=void 0,this.promptStartedAt=void 0,this.logger?.info(`session ${this.sessionId} unsolicited turn ${n.messageId} closed reason=${e} durationMs=${r}`+(t?` by=${t}`:"")+(n.cause?` cause=${JSON.stringify(n.cause.label)}`:"")),e==="superseded"&&(this.supersededAutonomousTurn={turnMessageId:n.messageId,cause:n.cause,supersededAt:Date.now()}),this.recordCurrentUsageSnapshot(),!this.closed&&(e==="cancelled"&&this.closeOpenToolCalls("cancelled"),this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"turn_ended",messageId:Pe(),startedMessageId:n.messageId,durationMs:r,_meta:{"hydra-acp":{unsolicited:!0,reason:e}}}}))}salvageSupersededTerminal(){let e=this.supersededAutonomousTurn;if(e===void 0)return;this.supersededAutonomousTurn=void 0;let t=this.autonomousSalvage;t!==void 0&&(this.autonomousSalvage=void 0,this.logger?.warn(`session ${this.sessionId} salvaged session/prompt from autonomous terminal (superseded turn ${e.turnMessageId}, ${Date.now()-e.supersededAt}ms earlier)`+(e.cause?` cause=${JSON.stringify(e.cause.label)}`:"")),t({stopReason:"end_turn",_meta:{[ue]:{salvaged:{reason:"autonomous_terminal",supersededMessageId:e.turnMessageId}}}}))}async awaitPromptResponse(e){if(this.supersededAutonomousTurn===void 0)return e;try{return await new Promise((t,n)=>{this.autonomousSalvage=t,e.then(t,n)})}finally{this.autonomousSalvage=void 0}}recordTerminal(e,t){for(this.recentlyTerminal.set(e,{stopReason:t,terminatedAt:Date.now()});this.recentlyTerminal.size>Wu;){let n=this.recentlyTerminal.keys().next().value;if(n===void 0)break;this.recentlyTerminal.delete(n)}}broadcastPromptAmended(e){let t=this.findUserEntry(e.newMessageId);if(!t)return;let n={sessionId:this.sessionId,cancelledMessageId:e.cancelledMessageId,newMessageId:e.newMessageId,prompt:t.prompt,originator:t.originator,amendedAt:Date.now()};this.broadcastQueueNotification("hydra-acp/prompt/amended",n)}findUserEntry(e){if(this.currentEntry?.messageId===e&&this.currentEntry.kind==="user")return this.currentEntry;let t=this.promptQueue.find(n=>n.messageId===e&&n.kind==="user");return t?.kind==="user"?t:void 0}visibleQueueDepth(){let e=this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled?1:0;for(let t of this.promptQueue)t.kind==="user"&&!t.cancelled&&(e+=1);return e}broadcastQueueAdded(e,t){let n=this.visibleQueueDepth(),r=t?.position??Math.max(0,n-1),o={sessionId:this.sessionId,messageId:e.messageId,originator:e.originator,prompt:e.prompt,position:r,queueDepth:n,enqueuedAt:e.enqueuedAt};t?.amending!==void 0&&(o._meta={"hydra-acp":{amending:t.amending}}),this.broadcastQueueNotification("hydra-acp/prompt_queue/added",o)}broadcastQueueUpdated(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/updated",{sessionId:this.sessionId,messageId:e,prompt:t})}broadcastQueueRemoved(e,t){this.broadcastQueueNotification("hydra-acp/prompt_queue/removed",{sessionId:this.sessionId,messageId:e,reason:t})}broadcastQueueNotification(e,t){for(let n of this.clients.values())n.connection.notify(e,t).catch(()=>{})}queueSnapshot(){let e=[],t=0;this.currentEntry?.kind==="user"&&!this.currentEntry.cancelled&&e.push({messageId:this.currentEntry.messageId,originator:this.currentEntry.originator,prompt:this.currentEntry.prompt,position:t++,enqueuedAt:this.currentEntry.enqueuedAt});for(let n of this.promptQueue)n.kind!=="user"||n.cancelled||e.push({messageId:n.messageId,originator:n.originator,prompt:n.prompt,position:t++,enqueuedAt:n.enqueuedAt});return e}async flushPersistWrites(){await this.queueWriteChain.catch(()=>{})}replayPersistedQueue(e){for(let t of e){let n={clientId:`hydra-resurrected_${t.messageId}`};t.originator.clientInfo.name!==void 0&&(n.name=t.originator.clientInfo.name),t.originator.clientInfo.version!==void 0&&(n.version=t.originator.clientInfo.version);let r={kind:"user",messageId:t.messageId,originator:n,clientId:n.clientId,prompt:t.prompt,enqueuedAt:t.enqueuedAt,cancelled:!1,resolve:()=>{},reject:()=>{}};this.promptQueue.push(r),this.broadcastQueueAdded(r)}this.drainQueue()}cancelQueuedPrompt(e){if(this.currentEntry?.messageId===e)return{cancelled:!1,reason:"already_running"};let t=this.promptQueue.findIndex(r=>r.messageId===e);if(t<0)return{cancelled:!1,reason:"not_found"};let n=this.promptQueue[t];return n.cancelled=!0,this.promptQueue.splice(t,1),n.kind==="user"&&(this.broadcastQueueRemoved(e,"cancelled"),this.persistRewrite()),this.amendInProgress?.newMessageId===e&&(this.amendInProgress=void 0),n.resolve({stopReason:"cancelled"}),{cancelled:!0,reason:"ok"}}updateQueuedPrompt(e,t){if(this.currentEntry?.messageId===e)return{updated:!1,reason:"already_running"};let n=this.promptQueue.find(r=>r.messageId===e);return!n||n.kind!=="user"?{updated:!1,reason:"not_found"}:(n.prompt=t,this.broadcastQueueUpdated(e,t),this.persistRewrite(),{updated:!0,reason:"ok"})}amendPrompt(e,t){let n=this.clients.get(e);if(!n)throw me(new Error("client not attached"),x.SessionNotFound);let{targetMessageId:r,prompt:o,replaceQueue:i,onTargetCompleted:a}=t;if(this.currentEntry?.messageId===r&&this.currentEntry.kind==="user"&&!this.currentEntry.cancelled&&this.amendInProgress===void 0)return this.amendOnHead(n,o,r,i);let d=this.promptQueue.find(u=>u.messageId===r&&u.kind==="user");if(d&&d.kind==="user"&&!d.cancelled)return d.prompt=o,this.broadcastQueueUpdated(r,o),this.persistRewrite(),{amended:!0,reason:"ok",messageId:r};let c=this.recentlyTerminal.get(r);return c?c.stopReason==="cancelled"?{amended:!1,reason:"target_cancelled"}:a==="send_anyway"?{amended:!1,reason:"target_completed",messageId:this.enqueueAmendmentAsFollowUp(n,o)}:{amended:!1,reason:"target_completed"}:{amended:!1,reason:"target_not_found"}}amendOnHead(e,t,n,r){let o=Pe(),i={clientId:e.clientId};if(e.clientInfo?.name&&(i.name=e.clientInfo.name),e.clientInfo?.version&&(i.version=e.clientInfo.version),r){let d=[];for(let c of this.promptQueue){if(c.kind==="user"&&!c.cancelled){c.cancelled=!0,this.broadcastQueueRemoved(c.messageId,"cancelled"),c.resolve({stopReason:"cancelled"});continue}d.push(c)}this.promptQueue=d}let a={kind:"user",messageId:o,originator:i,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,wasAmend:!0,resolve:()=>{},reject:()=>{}};return this.promptQueue.unshift(a),this.persistRewrite(),this.broadcastQueueAdded(a,{amending:n,position:1}),this.amendInProgress={cancelledMessageId:n,newMessageId:o},this.cancelExtensionDispatch(n,"amended"),this.agent.connection.notify("session/cancel",{sessionId:this.upstreamSessionId}).catch(()=>{}),{amended:!0,reason:"ok",messageId:o}}enqueueAmendmentAsFollowUp(e,t){let n=Pe(),r={clientId:e.clientId};e.clientInfo?.name&&(r.name=e.clientInfo.name),e.clientInfo?.version&&(r.version=e.clientInfo.version);let o={kind:"user",messageId:n,originator:r,clientId:e.clientId,prompt:t,enqueuedAt:Date.now(),cancelled:!1,resolve:()=>{},reject:()=>{}};return this.promptQueue.push(o),this.persistRewrite(),this.broadcastQueueAdded(o),this.drainQueue(),n}async cancel(e){if(!this.clients.get(e))throw me(new Error("client not attached"),x.SessionNotFound);this.lastCancelAt=Date.now(),this.currentEntry?.kind==="user"&&this.currentEntry.messageId!==void 0&&this.cancelExtensionDispatch(this.currentEntry.messageId,"cancelled"),this.closeUnsolicitedTurn("cancelled"),this.agentTurnInFlight||this.closeOpenToolCalls("cancelled"),await this.forwardRequest("session/cancel",{sessionId:this.sessionId},new Set,0,"notification")}addTransformer(e){let t=this.transformChain.findIndex(n=>n.name===e.name);t>=0?this.transformChain[t]=e:this.transformChain.push(e),e.intercepts.has("lifecycle:session.opened")&&e.connection.notify("hydra-acp/transformer/session_event",{event:"session.opened",sessionId:this.sessionId}).catch(()=>{})}async forwardRequest(e,t,n=new Set,r=0,o="request"){let i=this.rewriteForAgent(t);for(let a=r;a<this.transformChain.length;a++){let d=this.transformChain[a];if(n.has(d.name))continue;let c=`request:${e}`;if(!d.intercepts.has(c))continue;let u=`t_${Gs()}`,l;try{l=await d.connection.request("hydra-acp/transformer/message",{token:u,phase:"request",method:e,direction:"client\u2192agent",sessionId:this.sessionId,envelope:i})}catch(p){this.logger?.warn(`transformer ${d.name} error on ${c}: ${p.message}`);continue}let f=l?.action??"continue";if(f==="stop")return o==="notification"?void 0:l?.payload??Ys(e);if(f==="continue"){l?.payload&&typeof l.payload=="object"&&(i=l.payload),n.add(d.name);continue}if(f==="processing"){let p=a,g=i,m=new Set(n);return new Promise(h=>{let y=setTimeout(()=>{this.pendingClaims.delete(u)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:u,transformerName:d.name}),this.forwardRequest(e,g,new Set([...m,d.name]),p+1,o).then(h).catch(()=>h(o==="notification"?void 0:Ys(e))))},kn);typeof y.unref=="function"&&y.unref(),this.pendingClaims.set(u,{resolve:h,timer:y,transformerName:d.name,method:e,envelope:g,chainIdx:p,originatedBy:m,side:"request",tailKind:o})})}n.add(d.name)}if(o==="notification"){await this.agent.connection.notify(e,i);return}return this.agent.connection.request(e,i)}async forwardModelChange(e,t){let n=await Je({request:(r,o)=>this.forwardRequest(r,o),sessionId:this.sessionId,modelId:e,verb:this.modelVerb,extraParams:t,logger:this.logger});return this.modelVerb=n.verb,this.modelVerbConfirmed=!0,n.result}noteModelVerbHint(e,t){e===void 0||this.modelVerbConfirmed||e===this.modelVerb||(this.logger?.info(`model verb for agent ${this.agentId} inferred as ${e} from ${t} (was ${this.modelVerb})`),this.modelVerb=e)}resetModelVerb(e){this.modelVerb=e??Re,this.modelVerbConfirmed=!1}async runAgentRequestChain(e,t,n=new Set,r=0){let o=t,i=`request:${e}`;for(let a=r;a<this.transformChain.length;a++){let d=this.transformChain[a];if(n.has(d.name)||!d.intercepts.has(i))continue;let c=`t_${Gs()}`,u;try{u=await d.connection.request("hydra-acp/transformer/message",{token:c,phase:"request",method:e,direction:"agent\u2192client",sessionId:this.sessionId,envelope:o})}catch(f){this.logger?.warn(`transformer ${d.name} error on ${i}: ${f.message}`);continue}let l=u?.action??"continue";if(l==="stop")return{shortCircuit:!0,payload:u?.payload??cl(e)};if(l==="continue"){u?.payload&&typeof u.payload=="object"&&(o=u.payload),n.add(d.name);continue}if(l==="processing"){let f=a,p=o,g=new Set(n),m=e;return new Promise(h=>{let y=setTimeout(()=>{this.pendingClaims.delete(c)&&(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:c,transformerName:d.name}),this.runAgentRequestChain(m,p,new Set([...g,d.name]),f+1).then(h).catch(()=>h({shortCircuit:!1,envelope:p})))},kn);typeof y.unref=="function"&&y.unref(),this.pendingClaims.set(c,{resolve:k=>h({shortCircuit:!0,payload:k}),timer:y,transformerName:d.name,method:m,envelope:p,chainIdx:f,originatedBy:g,side:"agent-request"})})}n.add(d.name)}return{shortCircuit:!1,envelope:o}}dischargeClaim(e,t){let n=this.pendingClaims.get(e);return n?(clearTimeout(n.timer),this.pendingClaims.delete(e),n.resolve(t),!0):!1}keepAliveClaim(e,t){let n=this.pendingClaims.get(e);if(!n)return!1;clearTimeout(n.timer);let r=typeof t=="number"&&t>0?Math.min(t*1.5,1800*1e3):kn,o=setTimeout(()=>{if(this.pendingClaims.delete(e))if(this.broadcastQueueNotification("hydra-acp/transformer/abandoned_request",{sessionId:this.sessionId,token:e,transformerName:n.transformerName}),n.side==="response")this.runResponseChain(n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1).then(()=>n.resolve(void 0)).catch(()=>n.resolve(void 0));else if(n.side==="agent-request")this.runAgentRequestChain(n.method,n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1).then(n.resolve).catch(()=>n.resolve({shortCircuit:!1,envelope:n.envelope}));else{let i=n.tailKind??"request";this.forwardRequest(n.method,n.envelope,new Set([...n.originatedBy,n.transformerName]),n.chainIdx+1,i).then(n.resolve).catch(()=>n.resolve(i==="notification"?void 0:Ys(n.method)))}},r);return typeof o.unref=="function"&&o.unref(),n.timer=o,!0}async emitToChain(e,t,n){let r=this.transformChain.findIndex(a=>a.name===e),o=r>=0?r+1:0,i=new Set([e]);if(t==="session/update"){await this.runResponseChain(n,i,o);return}return this.forwardRequest(t,n,i,o)}async emitToQueue(e,t){let n=this.transformChain.findIndex(c=>c.name===e),r=n>=0?n+1:0,o=(t??{}).prompt??[],i=Pe(),a=`transformer:${e}`,d={clientId:a,name:e};return new Promise((c,u)=>{let l={kind:"user",messageId:i,originator:d,clientId:a,prompt:o,enqueuedAt:Date.now(),cancelled:!1,emitterName:e,chainStartIdx:r,resolve:c,reject:u},f=this.insertEntryAt(l,"tail");this.persistRewrite(),this.broadcastQueueAdded(l,{position:f}),this.drainQueue()})}rewriteForAgent(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;if(t.sessionId===this.sessionId)return{...t,sessionId:this.upstreamSessionId}}return e}async close(e={}){if(e.deleteRecord&&(this.deleteRecordIntent=!0),!this.closed)return this.closeInFlight?this.closeInFlight:(this.closing=!0,this.closeInFlight=this.doClose(e),this.closeInFlight)}async doClose(e){let t=this.turnStartedAt!==void 0;this.logger?.info(`session ${this.sessionId} closing deleteRecord=${e.deleteRecord??!1} by=${e.by??"unknown"} midTurn=${t} unsolicitedTurn=${this.unsolicitedTurn!==void 0} queued=${this.promptQueue.length} awaitingPermission=${this.hasPermissionFlag}`),t&&this.logger?.warn(`session ${this.sessionId} closed mid-turn by=${e.by??"unknown"}; the in-flight turn will not settle and the agent is being killed`),this.cancelIdleTimer();for(let n of this.pendingClaims.values())clearTimeout(n.timer);this.pendingClaims.clear(),await this.agent.kill().catch(()=>{}),this.markClosed({deleteRecord:e.deleteRecord??!1})}onClose(e){return this.closeHandlers.push(e),()=>{let t=this.closeHandlers.indexOf(e);t>=0&&this.closeHandlers.splice(t,1)}}onTitleChange(e){this.titleHandlers.push(e)}retitle(e){return this.runTitleCommand(e)}retitleFromAgent(){return this.runTitleCommand("")}setTitle(e){let t=e.trim();if(!(!t||t===this.title)){this._titleSeedPending=!1,this.title=t,this.recordAndBroadcast("session/update",{sessionId:this.sessionId,update:{sessionUpdate:"session_info_update",title:t,updatedAt:new Date().toISOString()}});for(let n of this.titleHandlers)try{n(t)}catch{}}}maybeSeedTitleFromPrompt(e){if(!this._titleSeedPending||Qe((e??{})._meta).ancillary===!0||this.promptCarriesSentBy(e))return;let r=ht((e??{}).prompt),o=Xs(r,200);!o||o.startsWith("/")||(this._titleSeedPending=!1,this.setTitle(o))}maybeApplyAgentModel(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="current_model_update")return!1;let r=yt(n.availableModels);r.length>0&&this.setAgentAdvertisedModels(r);let o=typeof n.currentModel=="string"?n.currentModel:typeof n.model=="string"?n.model:void 0;if(o===void 0)return!0;let i=o.trim();if(!i||i===this.currentModel)return!0;this.logger?.info(`live current_model_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(i)}`),this.currentModel=i;for(let a of this.modelHandlers)try{a(i)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentConfigOption(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="config_option_update")return!1;let r=n.configOptions;if(!Array.isArray(r))return!0;for(let o of r){if(!o||typeof o!="object")continue;let i=o;if(i.id==="model"){let a=yt(i.options);a.length>0&&this.setAgentAdvertisedModels(a);let d=i.currentValue;if(typeof d=="string"){let c=d.trim();c&&c!==this.currentModel&&(this.logger?.info(`live config_option_update(model): sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(c)}`),this.applyModelChange(c))}}else if(i.id==="mode"){let a=Ht(i.options);a.length>0&&this.setAgentAdvertisedModes(a);let d=i.currentValue;if(typeof d=="string"){let c=d.trim();c&&c!==this.currentMode&&(this.logger?.info(`live config_option_update(mode): sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(c)}`),this.applyModeChange(c))}}else if(typeof i.id=="string"&&i.id.trim()){let a=i.id.trim(),d=yt(i.options);if(d.length>0){let c=Ht(i.options),u=c.length>0?c.map(h=>({value:h.id,name:h.name??h.id})):d.map(h=>({value:h.modelId,name:h.name??h.modelId})),l=i.name,f=typeof l=="string"&&l.trim()?l.trim():a,p=i.currentValue,g=typeof p=="string"&&p.trim()?p.trim():u[0]?.value??"",m=this.agentAdvertisedConfigOptions.findIndex(h=>h.id===a);if(m>=0){let h={...this.agentAdvertisedConfigOptions[m]};h.options=u,typeof p=="string"&&p.trim()&&(h.currentValue=p.trim()),this.agentAdvertisedConfigOptions[m]=h}else this.agentAdvertisedConfigOptions.push({id:a,name:f,category:"other",type:"select",currentValue:g,options:u})}}}return!0}maybeApplyAgentMode(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="current_mode_update")return!1;let r=typeof n.currentModeId=="string"?n.currentModeId:typeof n.currentMode=="string"?n.currentMode:typeof n.mode=="string"?n.mode:void 0;if(r===void 0)return!0;let o=r.trim();if(!o||o===this.currentMode)return!0;this.logger?.info(`current_mode_update: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(o)}`),this.currentMode=o;for(let i of this.modeHandlers)try{i(o)}catch{}return this.broadcastConfigOptions(),!0}maybeApplyAgentUsage(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="usage_update")return!1;let r={...this._currentUsage??{}},o=!1;if(typeof n.used=="number"&&r.used!==n.used&&(r.used=n.used,o=!0),typeof n.size=="number"&&r.size!==n.size&&(r.size=n.size,o=!0),n.cost&&typeof n.cost=="object"){let a=n.cost;typeof a.amount=="number"&&(this.reconcileCostLedger(a.amount)&&(o=!0),r.costAmount!==a.amount&&(r.costAmount=a.amount,o=!0)),typeof a.currency=="string"&&r.costCurrency!==a.currency&&(r.costCurrency=a.currency,o=!0)}if(!o)return!0;this._currentUsage=r;let i=this.persistableUsage??r;for(let a of this.usageHandlers)try{a(i)}catch{}return!0}armCostLedgerProbe(){let e=this._currentUsage?.costAmount;typeof e=="number"&&e>0&&(this.costLedgerProbe=e)}reconcileCostLedger(e){let t=this.costLedgerProbe;return t===void 0||(this.costLedgerProbe=void 0,e>=t-1e-6)?!1:(this.cumulativeCost+=t,!0)}notifyAgentChange(e,t,n){let r=this.retiringGenerationCost;this.retiringGenerationCost=void 0;for(let o of this.agentChangeHandlers)try{o({agentId:this.agentId,upstreamSessionId:this.upstreamSessionId,...r!==void 0?{retiredCost:r}:{},...t!==void 0?{reason:t}:{},...n!==void 0?{runId:n}:{}})}catch(i){this.logger?.warn(`${e}: agentChange handler failed: ${i.message}`)}}accumulateAndResetCost(){let e=this._currentUsage?.costAmount;e&&(this.cumulativeCost+=e,this.retiringGenerationCost=e);let t={used:0,cumulativeCost:this.cumulativeCost,...typeof this._currentUsage?.size=="number"?{size:this._currentUsage.size}:{},...this._currentUsage?.costCurrency?{costCurrency:this._currentUsage.costCurrency}:{}};this._currentUsage=t;for(let n of this.usageHandlers)try{n(t)}catch{}this.broadcastCurrentUsage()}broadcastCurrentUsage(){let e=this.currentUsage;if(e===void 0)return;let t={sessionUpdate:"usage_update"};if(typeof e.used=="number"&&(t.used=e.used),typeof e.size=="number"&&(t.size=e.size),typeof e.costAmount=="number"||typeof e.costCurrency=="string"){let n={};typeof e.costAmount=="number"&&(n.amount=e.costAmount),typeof e.costCurrency=="string"&&(n.currency=e.costCurrency),t.cost=n}this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:t})}injectCumulativeCost(e){if(!this.cumulativeCost||!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let n=t.update;if(n.sessionUpdate!=="usage_update"||!n.cost||typeof n.cost!="object")return e;let r=n.cost;return typeof r.amount!="number"?e:{...t,update:{...n,cost:{...r,amount:this.cumulativeCost+r.amount}}}}get totalUsage(){return this.currentUsage}setAgentAdvertisedCommands(e){if(Xu(this.agentAdvertisedCommands,e)){this.broadcastMergedCommands();return}this.agentAdvertisedCommands=e;for(let t of this.agentCommandsHandlers)try{t(e)}catch{}this.broadcastMergedCommands()}setAgentAdvertisedModes(e){if(Zu(this.agentAdvertisedModes,e)){this.broadcastAvailableModes();return}this.agentAdvertisedModes=e;for(let t of this.agentModesHandlers)try{t(e)}catch{}this.broadcastAvailableModes()}setAgentAdvertisedModels(e){if(this.logger?.info(`setAgentAdvertisedModels: sessionId=${this.sessionId} currentModel=${JSON.stringify(this.currentModel)} newList=[${e.map(t=>t.modelId).join(",")}]`),el(this.agentAdvertisedModels,e)){this.broadcastAvailableModels();return}this.agentAdvertisedModels=e;for(let t of this.agentModelsHandlers)try{t(e)}catch{}this.broadcastAvailableModels()}onAgentCommandsChange(e){this.agentCommandsHandlers.push(e)}onAgentModesChange(e){this.agentModesHandlers.push(e)}onAgentModelsChange(e){this.agentModelsHandlers.push(e)}onModelChange(e){this.modelHandlers.push(e)}onModeChange(e){this.modeHandlers.push(e)}onInteractiveChange(e){this.interactiveHandlers.push(e)}onPriorityChange(e){this.priorityHandlers.push(e)}setPriority(e){let t=e===void 0||e<=0?void 0:Math.floor(e);if(t!==this._priority){this._priority=t,this.updatedAt=Date.now();for(let n of this.priorityHandlers)try{n(t)}catch{}}}applyModelChange(e){let t=e.trim();if(t){this.modelChangeInFlight=!0;try{if(t!==this.currentModel){this.logger?.info(`applyModelChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentModel)} \u2192 ${JSON.stringify(t)}`),this.currentModel=t;for(let r of this.modelHandlers)try{r(t)}catch{}}let n={sessionUpdate:"current_model_update",currentModel:t};this.agentAdvertisedModels.length>0&&(n.availableModels=[...this.agentAdvertisedModels]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modelChangeInFlight=!1}}}applyModeChange(e){let t=e.trim();if(t){this.modeChangeInFlight=!0;try{if(t!==this.currentMode){this.logger?.info(`applyModeChange: sessionId=${this.sessionId} ${JSON.stringify(this.currentMode)} \u2192 ${JSON.stringify(t)}`),this.currentMode=t;for(let r of this.modeHandlers)try{r(t)}catch{}}let n={sessionUpdate:"current_mode_update",currentModeId:t};this.agentAdvertisedModes.length>0&&(n.availableModes=[...this.agentAdvertisedModes]),this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:n}),this.broadcastConfigOptions()}finally{this.modeChangeInFlight=!1}}}buildConfigOptions(){let e=[];if(this.agentAdvertisedModels.length>0){let r=this.agentAdvertisedModels.map(i=>({value:i.modelId,name:i.name??i.modelId,...i.description!==void 0?{description:i.description}:{}})),o=this.currentModel&&r.some(i=>i.value===this.currentModel)?this.currentModel:r[0].value;e.push({id:"model",name:"Model",category:"model",type:"select",currentValue:o,options:r})}if(this.agentAdvertisedModes.length>0){let r=this.agentAdvertisedModes.map(i=>({value:i.id,name:i.name??i.id,...i.description!==void 0?{description:i.description}:{}})),o=this.currentMode&&r.some(i=>i.value===this.currentMode)?this.currentMode:r[0].value;e.push({id:"mode",name:"Session Mode",category:"mode",type:"select",currentValue:o,options:r})}let n=(this.availableAgentsFn?.()??[]).map(r=>({value:r.id,name:r.name??r.id,...r.description!==void 0?{description:r.description}:{}}));return n.some(r=>r.value===this.agentId)||n.unshift({value:this.agentId,name:this.agentId}),e.push({id:"agent",name:"Agent",category:"_hydra_agent",type:"select",currentValue:this.agentId,options:n}),e.push(...this.agentAdvertisedConfigOptions),e}broadcastConfigOptions(){this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"config_option_update",configOptions:this.buildConfigOptions()}})}mergeAgentOptionIntoEnvelope(e){if(!e||typeof e!="object")return e;let t=e;if(!t.update||typeof t.update!="object")return e;let n=t.update,r=Array.isArray(n.configOptions)?[...n.configOptions]:[];if(r.some(a=>a&&typeof a=="object"&&a.id==="agent"))return e;let i=this.buildConfigOptions().find(a=>a.id==="agent");return i?{...t,update:{...n,configOptions:[...r,i]}}:e}onUsageChange(e){this.usageHandlers.push(e)}mergedAvailableCommands(){let e=this.daemonTopLevelCommands(),t=this.aliasableBareVerbs();for(let n of ft){if(t.get(n.verb)!=="__hydra__")continue;let r=n.argsHint?`${n.verb} ${n.argsHint}`:n.verb;e.push({name:r,description:`Alias for '/hydra ${n.verb}': ${n.description}`})}if(this.extensionCommands)for(let{name:n,command:r}of this.extensionCommands.list()){let o=r.verb?`hydra ${n} ${r.verb}`:`hydra ${n}`,a={name:r.argsHint?`${o} ${r.argsHint}`:o};r.description&&(a.description=r.description),e.push(a);let d=n.startsWith("hydra-acp-")?n.slice(10):n;if(n.startsWith("hydra-acp-")&&d.length>0){let c=r.verb?`hydra ${d} ${r.verb}`:`hydra ${d}`,l={name:r.argsHint?`${c} ${r.argsHint}`:c};r.description&&(l.description=r.description),e.push(l)}if(d.length>0&&t.get(d)===n){let c=r.verb?`${d} ${r.verb}`:d,l={name:r.argsHint?`${c} ${r.argsHint}`:c};r.description&&(l.description=r.description),e.push(l)}}return e.push(...this.agentAdvertisedCommands),e}daemonTopLevelCommands(){return[{name:"hydra",description:"Hydra session command (kill, restart, title, agent <agent>)"},{name:"model",description:"Switch model; omit arg to list available models"},{name:"mode",description:"Switch mode; omit arg to list available modes"},{name:"sessions",description:"List all sessions"},{name:"help",description:"Show available commands"}]}aliasableBareVerbs(){let e=new Set,t=i=>i.split(/\s+/)[0]??"";for(let i of this.daemonTopLevelCommands()){let a=t(i.name);a&&e.add(a)}for(let i of this.agentAdvertisedCommands){let a=t(i.name),d=a.startsWith("/")?a.slice(1):a;d&&e.add(d)}let n=new Map;for(let i of ft)e.has(i.verb)||n.set(i.verb,"__hydra__");if(!this.extensionCommands)return n;let r=new Map,o=new Set;for(let{name:i}of this.extensionCommands.list()){if(o.has(i))continue;o.add(i);let a=i.startsWith("hydra-acp-")?i.slice(10):i;if(!a||e.has(a)||n.has(a))continue;let d=r.get(a);d===void 0?r.set(a,i):d!==i&&r.set(a,"__conflict__")}for(let[i,a]of r)a!=="__conflict__"&&n.set(i,a);return n}agentOnlyAdvertisedCommands(){return[...this.agentAdvertisedCommands]}agentKnowsSlashCommand(e){let t=r=>r.startsWith("/")?r.slice(1):r,n=t(e);if(!n)return!1;for(let r of this.agentAdvertisedCommands)if(t(r.name.split(/\s+/)[0]??"")===n)return!0;return!1}availableModes(){return[...this.agentAdvertisedModes]}availableModels(){return[...this.agentAdvertisedModels]}maybeApplyAgentSessionInfo(e){let n=(e??{}).update??{};if(n.sessionUpdate!=="session_info_update"||typeof n.title!="string")return;let r=n.title.trim();if(!(!r||r===this.title)){this.title=r,this._firstPromptSeeded=!0,this._titleSeedPending=!1;for(let o of this.titleHandlers)try{o(r)}catch{}}}async handleSlashCommand(e,t){let r=e.slice(6).trim().match(/^(\S+)(?:\s+([\s\S]*))?$/),o=r?.[1]??"",i=(r?.[2]??"").trim();if(o==="")return{stopReason:"end_turn"};let a=t!==void 0;if(ft.some(l=>l.verb===o))switch(o){case"title":return a?this.runTitleCommandInline(i):this.runTitleCommand(i);case"agent":return this.runAgentCommandInline(i);case"config":return this.handleConfigCommand(`/config ${i}`);case"kill":return this.runKillCommand();case"workspace":return this.runWorkspaceCommand(i);case"restart":return a?this.runRestartCommandInline():this.runRestartCommand();case"compact":return a?this.runCompactCommandInline(i):this.runCompactCommand(i);case"uncompact":return a?this.runUncompactCommandInline():this.runUncompactCommand();case"fork":return a?this.runForkCommandInline(i,t):this.runForkCommand(i);default:{let l=new Error(`no dispatcher for /hydra verb ${o}`);throw l.code=x.InternalError,l}}if(this.extensionCommands?.has(o))return a?this.runExtensionCommandInline(o,i,t):this.runExtensionCommand(o,i);let d=`hydra-acp-${o}`;if(this.extensionCommands?.has(d))return a?this.runExtensionCommandInline(d,i,t):this.runExtensionCommand(d,i);let c=ft.map(l=>l.verb);if(this.extensionCommands){let l=new Set;for(let{name:f}of this.extensionCommands.list())l.has(f)||(c.push(f),l.add(f))}let u=new Error(`unknown /hydra verb: ${o} (known: ${c.join(", ")})`);throw u.code=x.InvalidParams,u}runExtensionCommand(e,t){return this.enqueuePrompt(`extension:${e}`,()=>this.runExtensionCommandInline(e,t,void 0))}async runExtensionCommandInline(e,t,n){let r=this.extensionCommands?.get(e);if(!r)return this.emitExtensionReply(`extension "${e}" is no longer connected`);let o=t.match(/^(\S+)(?:\s+([\s\S]*))?$/),i=o?.[1]??"",a=(o?.[2]??"").trim();if(!r.commands.some(g=>g.verb===i)){let g=r.commands.map(m=>m.verb).join(", ");return this.emitExtensionReply(`/hydra ${e}${i?` ${i}`:""}: unknown verb (known: ${g||"(none)"})`)}let d={sessionId:this.sessionId,verb:i,args:a};n!==void 0&&(d.messageId=n);let c=()=>{},u=new Promise(g=>{c=g});n!==void 0&&this.inFlightExtensionDispatches.set(n,{extensionName:e,connection:r.connection,cancel:g=>c({stopReason:"cancelled",reason:g})});let l,f=!1;try{let g=r.connection.request("hydra-acp/commands/invoke",d),m=await Promise.race([g,u]);if(m&&typeof m=="object"&&m.stopReason==="cancelled"&&"reason"in m)return f=!0,this.logger?.info(`extension ${e} ${i} cancelled (cancelExtensionDispatch); abandoning in-flight commands/invoke`),{stopReason:"cancelled"};l=m}catch(g){return this.emitExtensionReply(`${e} ${i}: ${g.message}`)}finally{n!==void 0&&!f&&this.inFlightExtensionDispatches.delete(n)}let p=l&&typeof l=="object"&&typeof l.text=="string"?l.text:"";return p.length>0?this.emitExtensionReply(p):{stopReason:"end_turn"}}cancelExtensionDispatch(e,t){let n=this.inFlightExtensionDispatches.get(e);if(!n)return!1;this.inFlightExtensionDispatches.delete(e);try{n.connection.notify("hydra-acp/commands/cancel",{sessionId:this.sessionId,messageId:e,reason:t})}catch(r){this.logger?.warn(`notify commands/cancel to ${n.extensionName} failed: ${r.message}`)}return n.cancel(t),!0}emitExtensionReply(e){return this.recordAndBroadcast("session/update",{sessionId:this.upstreamSessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:`
|
|
44
44
|
${e}
|
|
45
45
|
`},_meta:{"hydra-acp":{synthetic:!0}}}}),{stopReason:"end_turn"}}async handleSessionsCommand(){let e;if(!this.listSessions)e="_(session listing not available)_";else{let t=await this.listSessions();if(t.length===0)e="_(no sessions)_";else{let n=t.map(r=>{let o=r.sessionId.replace(/^hydra_session_/,"").slice(0,12),i=r.currentModel?` \xB7 ${r.currentModel}`:"",a=r.sessionId===this.sessionId?" \u25C0":"",d=r.title?` ${r.title}`:"";return`\`${o}\` ${r.cwd}${i}${a}${d}`});e=`Sessions (${t.length}):
|
|
46
46
|
${n.join(`
|
|
@@ -165,7 +165,7 @@ A sync was attempted first but was refused: ${R instanceof Error?R.message:Strin
|
|
|
165
165
|
Nothing was committed: review it with \`git -C ${n} diff --cached\` and commit it however you like. The workspace and its history are untouched.`,warnings:k}}async leaveWorkspace(e,t,n){let r=n.exit!=="detached",o=Y(t.provider),i={path:t.path,sourceCwd:t.sourceCwd,label:t.label,provider:t.provider,...t.snapshot!==void 0?{snapshot:t.snapshot}:{},...t.vcs!==void 0?{vcs:t.vcs}:{}},a=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:t.sourceCwd,workspace:void 0,historyLength:a.length,note:`Returned to the source tree at ${t.sourceCwd}`+(n.exit==="landed"?" after merging the workspace.":n.exit==="discarded"?" after discarding the workspace and its work.":" without merging."),...await this.recordSynopsisFor(e.sessionId),left:{path:t.path,removed:r}}),await this.mutateRecord(e.sessionId,{cwd:e.cwd},["workspace"]),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"left",cwd:e.cwd,sourceCwd:t.sourceCwd,integrated:n.exit==="landed"}),o!==void 0&&await this.enqueueKeyed(this.workspaceQueues,t.path,async()=>{let d=this.liveSessionsIn(t.path,e.sessionId);if(d.length>0){this.logger?.info?.(`session workspace: ${e.sessionId} left ${t.path}; ${d.length} live session(s) remain, so it stays`);return}await this.reclaimAfterLastLeaver(o,i,t,e.sessionId,n)})}async reclaimAfterLastLeaver(e,t,n,r,o){await e.unlock(t).catch(()=>{});for(let i of[this.startRefFor(n.label),this.baselineRefFor(n.label)])await e.dropSnapshotRef(t,i).catch(()=>{});o.exit!=="detached"&&(o.exit==="landed"&&await e.dropSnapshotRef(t,this.snapshotRefFor(n.label)).catch(()=>{}),await e.removeWorkspace(t,{force:!0,discardLine:!0}).catch(()=>{}))}async joinDivergence(e,t,n){let[r,o]=await Promise.all([e.captureWorkingState(t,"hydra: source state at join").catch(()=>{}),e.captureWorkingState(n.path,"hydra: workspace state at join").catch(()=>{})]);if(r===void 0||o===void 0)return`could not compare ${T(t)} with ${T(n.path)}, so refusing to join a workspace that may not match your tree`;let i=await Promise.all([r,o].map(a=>e.contentId(t,a).catch(()=>{})));if(!(i[0]!==void 0&&i[0]===i[1]))return`${T(t)} and ${T(n.path)} have diverged, and joining does not carry work across \u2014 whichever side you are not in would be left behind. Land or stash one of them first: \`git -C ${t} stash\` if the difference is yours, or \`/hydra workspace merge\` from the session already in there if it is theirs.`}liveSessionsWithLabel(e,t){let n=[];for(let r of this.sessions.values()){let o=r.workspace;o===void 0||o.sourceCwd!==e||(o.label===t||o.requestedLabel===t)&&n.push(r)}return n}async joinWorkspace(e,t,n,r){let o=Y(n.provider);if(o===void 0)throw new Error(`no provider "${n.provider}" to join that workspace with`);if(o.capabilities().supports.captureWorkingState){let i=await this.joinDivergence(o,r,n);if(i!==void 0)throw new Error(i)}return await this.enqueueKeyed(this.workspaceQueues,n.path,async()=>{if(this.sessions.get(t.sessionId)?.workspace?.path!==n.path)throw new Error(`${T(n.path)} was released while joining it; run the command again`);e.broadcastWorkspacePhase({phase:"swapping"});let i=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:n.path,workspace:{path:n.path,sourceCwd:n.sourceCwd,label:n.label,...n.requestedLabel!==void 0?{requestedLabel:n.requestedLabel}:{},provider:n.provider,...n.snapshot!==void 0?{snapshot:n.snapshot}:{},...n.line!==void 0?{line:n.line}:{},...n.vcs!==void 0?{vcs:{...n.vcs}}:{}},historyLength:i.length,note:`Continuing in an isolated workspace at ${n.path}, derived from ${r}, shared with another session.`,...await this.recordSynopsisFor(e.sessionId)}),await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),this.invalidateListCache();let a=n.line;e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:n.sourceCwd,label:n.label,...a!==void 0?{branch:a}:{}});let d=this.liveSessionsIn(n.path,e.sessionId).map(u=>He(u.sessionId)),c=[`Joined workspace ${T(n.path)}`,` source: ${T(n.sourceCwd)}`];return a!==void 0&&c.push(` branch: ${a}`),c.push(` shared with: ${d.join(", ")}`),c.push(" your edits will interleave with that session's"),c.push("Use `/hydra workspace stop` to leave; the work lands when the last session leaves."),c.join(`
|
|
166
166
|
`)})}async startWorkspace(e,t,n){if(e.workspace!==void 0)throw new Error(`already isolated in ${T(e.workspace.path)}. Use \`/hydra workspace stop\` to merge and return first, or \`detach\` to leave it behind.`);let r=e.cwd,o=Y();if(o===void 0)throw new Error("no workspace provider available");let i=await e.quiesceBlocker();if(i!==void 0)throw new Error(i);let a=o.capabilities();if(t!==void 0){let b=this.liveSessionsWithLabel(r,t)[0];if(b!==void 0&&b.workspace!==void 0)return await this.joinWorkspace(e,b,b.workspace,r)}let d,c=[],u=!1,l=!1,f=[],p=[],g=n?.clean===!0;if(a.supports.captureWorkingState){let b=await o.status({path:r,sourceCwd:r,label:"source",provider:o.kind}).catch(()=>{});l=b!==void 0;let A=a.supports.nestedTrees&&b!==void 0&&b.changedPaths.length>0?await o.listNested(r).catch(()=>[]):[];if(b!==void 0&&b.changedPaths.length>0&&g)f=dr(b.changedPaths,A);else if(b!==void 0&&b.changedPaths.length>0&&(c=dr(b.changedPaths,A),p=await o.captureNested(r,A).catch(()=>[]),u=b.hasStagedWork===!0,d=await o.captureWorkingState(r,"hydra: work carried into workspace").catch(()=>{}),d===void 0))throw new Error("could not snapshot your uncommitted work, so refusing to move it. Commit or stash first.")}e.broadcastWorkspacePhase({phase:"provisioning"});let m=await o.createWorkspace({sourceCwd:r,label:t??`s-${e.sessionId.slice(-8)}`});if(!m.ok)throw e.broadcastWorkspacePhase({phase:"failed",error:m.reason}),new Error(m.reason);let h=m.workspace,y=this.startRefFor(h.label),k,w=!1,S=[];try{a.locking&&await o.lock(h,`session ${e.sessionId}`).catch(()=>{});let b=d??h.snapshot;if(b===void 0)throw new Error(`provider "${h.provider}" gave the workspace no base to anchor landing against`);await o.retainSnapshot(h,y,b),e.broadcastWorkspacePhase({phase:"setup"}),w=d!==void 0?await this.copyCarriedWork(h,d,r):!0;let A=await this.materializeNestedTrees(h);if(p.length>0){let E=await o.reproduceNested(h.path,r,p).catch($=>({applied:[],failed:p.map(_=>({path:_.relPath,reason:$ instanceof Error?$.message:String($)}))}));E.failed.length>0&&(w=!1,S=E.failed)}k=await this.applyWorkspaceSetup(h,e.sessionId),A!==void 0&&(k=k===void 0?A:`${A}; ${k}`),e.broadcastWorkspacePhase({phase:"swapping"});let R=await this.histories.load(e.sessionId).catch(()=>[]);await e.swapIntoWorkspace({cwd:h.path,workspace:{path:h.path,sourceCwd:h.sourceCwd,label:h.label,...t!==void 0&&t!==h.label?{requestedLabel:t}:{},provider:h.provider,...h.snapshot!==void 0?{snapshot:h.snapshot}:{},...h.line!==void 0?{line:h.line}:{},...h.vcs!==void 0?{vcs:{...h.vcs}}:{},...d===void 0?{clean:!0}:{}},historyLength:R.length,note:`Continuing in an isolated workspace at ${h.path}, derived from ${r}.`,...await this.recordSynopsisFor(e.sessionId)})}catch(b){let A=await this.unwindStartWorkspace({provider:o,ws:h,startRef:y,carried:d}),R=b instanceof Error?b.message:String(b);throw e.broadcastWorkspacePhase({phase:"failed",error:R}),new Error(A===void 0?R:`${R}
|
|
167
167
|
${A}`)}await this.mutateRecord(e.sessionId,{cwd:e.cwd,workspace:e.workspace}),this.invalidateListCache(),e.broadcastWorkspacePhase({phase:"entered",cwd:e.cwd,sourceCwd:h.sourceCwd,label:h.label,...h.line!==void 0?{branch:h.line}:{}});let I=[`Moved into workspace ${T(h.path)}`,` source: ${T(r)}`];if(h.line!==void 0&&I.push(` branch: ${h.line}`),t!==void 0&&t!==h.label&&I.push(` note: "${t}" was already taken by a surviving branch, so this is "${h.label}"`),d!==void 0){I.push(w?` carried ${c.length} uncommitted file(s) in; the source tree is untouched:`:` WARNING: could not copy ${c.length} uncommitted file(s); the workspace starts from HEAD. They are untouched in the source tree:`);for(let b of Ke(c))I.push(` ${b}`);w&&u&&I.push(" staging did not come along; everything above is unstaged here");for(let b of S)I.push(` nested tree ${b.path}: ${b.reason}`)}else if(f.length>0){I.push(` started clean: ${f.length} uncommitted file(s) stayed in the source and did NOT come along:`);for(let b of Ke(f))I.push(` ${b}`)}else l&&I.push(" source tree was clean; nothing carried in");return k!==void 0&&I.push(` ${k}`),I.push("Use `/hydra workspace stop` to merge back and return."),I.join(`
|
|
168
|
-
`)}async copyCarriedWork(e,t,n){let r=await this.patchFromSnapshot(n,t,e.provider);if(r===void 0)return!1;if(r.length===0)return!0;let o=Y(e.provider);return o===void 0?!1:(await o.applyDelta(e.path,r)).ok}async patchFromSnapshot(e,t,n){let r=Y(n);if(r===void 0)return;let o=await r.currentState(e);if(o!==void 0)return await r.captureDelta(e,o,t).catch(()=>{})}async unwindStartWorkspace(e){let{provider:t,ws:n,startRef:r,carried:o}=e;await t.unlock(n).catch(()=>{}),o!==void 0&&await t.dropSnapshotRef(n,r).catch(()=>{}),await t.removeWorkspace(n,{force:!0}).catch(()=>{})}async materializeNestedTrees(e,t){let n=Y(e.provider);if(n?.capabilities().supports.nestedTrees!==!0)return;let r=await n.materializeNested({path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:n.kind},t).catch(o=>({ok:!1,count:0,reason:o instanceof Error?o.message:String(o)}));return r.ok?r.count>0?`populated ${r.count} nested tree(s)`:void 0:`nested trees FAILED: ${r.reason??"unknown"}`}async applyWorkspaceSetup(e,t){let n=await Mn(e.sourceCwd).catch(()=>({})),r=[];if(n.carry!==void 0&&n.carry.length>0){let o=await mr(e.sourceCwd,e.path,n.carry).catch(()=>{});o!==void 0&&o.copied.length>0&&r.push(`carried ${o.copied.length} config file(s)`)}if(n.postCreate!==void 0){let o=await Tn(n.postCreate,{workspacePath:e.path,sourceCwd:e.sourceCwd,label:e.label,sessionId:t,...n.hookTimeoutSeconds!==void 0?{timeoutSeconds:n.hookTimeoutSeconds}:{}});r.push(o.ok?"ran postCreate":`postCreate FAILED: ${o.reason??"unknown"}`)}return r.length>0?r.join("; "):void 0}async deriveForkWorkspace(e,t){let n=Y(e.provider);if(n===void 0)return;let r=n.capabilities(),o=r.sharedHistory?await n.currentState(e.path)??"":"",i=await n.createWorkspace({sourceCwd:e.sourceCwd,label:t,...o.length>0?{from:o}:{contentFrom:e.path}}).catch(d=>({ok:!1,reason:String(d)}));if(!i.ok){this.logger?.warn?.(`fork workspace: could not derive from ${e.path}: ${i.reason}`);return}let a=i.workspace;if(o.length>0&&r.supports.captureWorkingState){let d=await n.captureWorkingState(e.path,`hydra: fork carry from ${e.label}`).catch(()=>{});d!==void 0&&d!==o&&await this.copyUncommittedInto(e.path,a.path,o,d,a.provider).catch(()=>{})}return{path:a.path,sourceCwd:a.sourceCwd,label:a.label,provider:a.provider,...a.snapshot!==void 0?{snapshot:a.snapshot}:{},...a.line!==void 0?{line:a.line}:{},...a.vcs!==void 0?{vcs:{...a.vcs}}:{}}}async copyUncommittedInto(e,t,n,r,o){let i=Y(o);if(i===void 0)return!1;let a=await i.captureDelta(e,n,r).catch(()=>{});return a===void 0||a.trim().length===0?!1:(await i.applyDelta(t,a,{stage:!0})).ok}async recoverWorkspace(e){let t=Y(e.provider);if(t===void 0)return;let n={path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:e.provider,...e.snapshot!==void 0?{snapshot:e.snapshot}:{},...e.vcs!==void 0?{vcs:e.vcs}:{}};if(t.capabilities().supports.rematerialize){let o=await t.rematerialize(n).catch(i=>({ok:!1,reason:String(i)}));if(o.ok)return this.logger?.info?.(`session workspace: restored ${o.workspace.path} from retained state`),{...e,path:o.workspace.path};this.logger?.warn?.(`session workspace: could not restore: ${o.reason}`)}if(!await this.dirExists(e.sourceCwd))return;let r=await t.createWorkspace({sourceCwd:e.sourceCwd,label:`${e.label}-r`}).catch(o=>({ok:!1,reason:String(o)}));if(r.ok)return this.logger?.warn?.(`session workspace: ${e.path} is gone and could not be restored; resurrecting in a fresh workspace ${r.workspace.path} from ${e.sourceCwd}. Uncommitted work from the old workspace is not recoverable.`),{path:r.workspace.path,sourceCwd:r.workspace.sourceCwd,label:r.workspace.label,provider:r.workspace.provider,...r.workspace.snapshot!==void 0?{snapshot:r.workspace.snapshot}:{},...r.workspace.vcs!==void 0?{vcs:{...r.workspace.vcs}}:{}}}async syncFromAgent(e){let t=await this.registry.getAgent(e);if(!t){let p=new Error(`agent ${e} not found in registry`);throw p.code=x.AgentNotInstalled,p}let n=await we(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:ha.homedir(),plan:n}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:at,clientInfo:{name:"hydra",version:ie}})}catch(p){throw await r.kill().catch(()=>{}),Ve(p,r)}if(r.authMethods=Jt(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(p){throw await r.kill().catch(()=>{}),p}await r.kill().catch(()=>{});let d=new Set;for(let p of this.sessions.values())d.add(`${p.agentId}::${p.upstreamSessionId}`);let c=await this.store.list().catch(()=>[]);for(let p of c){d.add(`${p.agentId}::${p.upstreamSessionId}`);for(let g of p.upstreamGenerations??[])d.add(`${g.agentId}::${g.upstreamSessionId}`)}let u=C.sessionsDir(),l=[],f=0;for(let p of a){let g=`${e}::${p.sessionId}`;if(d.has(g)){f+=1;continue}if(yp(p.cwd,u)){f+=1;continue}let m=await this.tombstones.read(e,p.sessionId).catch(()=>{});if(m){if(!Li(m,p.updatedAt)){f+=1;continue}await this.tombstones.remove(e,p.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${p.sessionId} (upstream updatedAt advanced past ${m.upstreamUpdatedAt??"<unset>"})`)}d.add(g);let h=`${Me}${It()}`,y=new Date().toISOString(),k=p.updatedAt??y,w={sessionId:h,lineageId:Ut(),upstreamSessionId:p.sessionId,agentId:e,cwd:p.cwd,pendingHistorySync:!0,interactive:!0,createdAt:k,updatedAt:k};p.title!==void 0&&(w.title=p.title);let S=ir(w);await this.store.write(S),l.push({version:1,...S})}return{synced:l,skipped:f}}async collectAgentSessions(e){let t=[],n,r=new Set;for(let o=0;o<100;o+=1){let i={};n!==void 0&&(i.cursor=n);let a=await e.connection.request("session/list",i),d=Array.isArray(a.sessions)?a.sessions:[];for(let c of d){if(typeof c.sessionId!="string"||typeof c.cwd!="string")continue;let u={sessionId:c.sessionId,cwd:c.cwd};typeof c.title=="string"&&(u.title=c.title),typeof c.updatedAt=="string"&&(u.updatedAt=c.updatedAt),t.push(u)}if(typeof a.nextCursor!="string"||a.nextCursor.length===0||r.has(a.nextCursor))break;r.add(a.nextCursor),n=a.nextCursor}return t}async applySeedModel(e,t,n,r,o){try{let{verb:i}=await Je({request:(a,d)=>e.connection.request(a,d),sessionId:t,modelId:n,...o?{verb:o}:{},logger:this.logger});return this.logger?.info(`${r}: ${i} accepted`),!0}catch(i){return this.logger?.warn(`${r} rejected by agent (${i.message}); session will use the agent's own default`),!1}}async bootstrapAgent(e){let t=await this.registry.getAgent(e.agentId);if(!t){let i=new Error(`agent ${e.agentId} not found in registry`);throw i.code=x.AgentNotInstalled,i}let n=await we(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),r=an(e.selfSessionId,e.forwardedEnv),o=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:n,...r?{extraEnv:r}:{}});try{let i=await o.connection.request("initialize",{protocolVersion:1,clientCapabilities:at,clientInfo:{name:"hydra",version:ie}}),a=i.agentCapabilities;o.authMethods=Jt(i.authMethods);let d=Ir(e.agentId),c=await o.connection.request("session/new",{cwd:e.cwd,mcpServers:e.mcpServers??[],...d&&{_meta:d}}),u=c.sessionId;if(typeof u!="string")throw new Error(`agent ${e.agentId} returned a non-string sessionId from session/new`);let l=Ar(c),f=xr(c),p=ct(c),g=e.model??this.defaultModels[e.agentId];if(g&&g!==l){let y=gt(g,f),k=e.model!==void 0?`model=${JSON.stringify(g)}`:`defaultModels[${e.agentId}]=${JSON.stringify(g)}`;if(y.kind==="exact"||y.kind==="none")await this.applySeedModel(o,u,g,k,p)&&(l=g);else if(y.kind==="resolved")(y.modelId===l||await this.applySeedModel(o,u,y.modelId,`${k} resolved to ${JSON.stringify(y.modelId)}`,p))&&(l=y.modelId);else if(y.kind==="ambiguous")this.logger?.warn(`${k} is ambiguous (trailing-segment matches [${y.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(l)}`);else{let w=f.map(S=>S.modelId).join(", ");this.logger?.warn(`${k} not in agent's availableModels ([${w}]); skipping session/set_model, session will use ${JSON.stringify(l)}`)}}let m=Rr(c),h=Er(c);return{agent:o,upstreamSessionId:u,agentMeta:c._meta,agentCapabilities:a,initialModel:l,initialModels:f.length>0?f:void 0,initialModes:m.length>0?m:void 0,initialMode:h,modelVerb:p}}catch(i){throw await o.kill().catch(()=>{}),Ve(ga(i,o,e.agentId,{command:n.command,args:n.args,cwd:e.cwd}),o)}}async bootstrapAgentLoad(e,t){let n=await this.registry.getAgent(t.agentId);if(!n){let a=new Error(`agent ${t.agentId} not found in registry`);throw a.code=x.AgentNotInstalled,a}let r=await we(n,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=an(t.selfSessionId,t.forwardedEnv),i=this.spawner({agentId:t.agentId,cwd:t.cwd,plan:r,...o?{extraEnv:o}:{}});try{let a=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:at,clientInfo:{name:"hydra",version:ie}}),d=a.agentCapabilities;i.authMethods=Jt(a.authMethods);let c=Ir(t.agentId),u=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),l=Ar(u),f=Cr(xr(u)),p=Rr(u),g=Er(u);return{agent:i,upstreamSessionId:e,agentMeta:u._meta,agentCapabilities:d,initialModel:l,initialModels:f,initialModes:p.length>0?p:void 0,initialMode:g,modelVerb:ct(u)}}catch(a){throw await i.kill().catch(()=>{}),Ve(ga(a,i,t.agentId,{command:r.command,args:r.args,cwd:t.cwd}),i)}}async performUncompact(e){if(this.rollbackLocks.has(e))throw new Error("a rollback is already in progress for this session");let t=this.get(e);if(!t)throw new Error("session is not live \u2014 cannot roll back a cold session");let n=await this.store.read(e);if(!n)throw new Error("session record not found");let r=n.rollbackBreadcrumb;if(!r)throw new Error("no rollback breadcrumb found \u2014 either the session has not been compacted, the rollback window has closed (a new turn was dispatched), or a previous rollback already consumed the breadcrumb");let o=n.compactionState;if(o!=null)throw new Error(`compaction is in progress (status: ${o.status}) \u2014 wait for it to complete before rolling back`);if(!await t.isQuiescedForSwap())throw new Error("session is not quiesced for rollback \u2014 wait for in-flight work to complete");this.rollbackLocks.add(e);try{await t.rollbackToUpstream({previousUpstreamSessionId:r.previousUpstreamSessionId,previousSummarizedThroughEntry:r.previousSummarizedThroughEntry}),await this.mutateRecord(e,{summarizedThroughEntry:r.previousSummarizedThroughEntry},["synopsis","rollbackBreadcrumb"])}finally{this.rollbackLocks.delete(e)}}async bootstrapAgentForAuth(e,t){let n=this.pendingAuthAgents.get(e);if(n&&n.isAlive())return n;let r=await this.registry.getAgent(e);if(!r){let d=new Error(`agent ${e} not found in registry`);throw d.code=x.AgentNotInstalled,d}let o=await we(r,[],{npmRegistry:this.npmRegistry}),i=t??de(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let d=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:at,clientInfo:{name:"hydra",version:ie}});a.authMethods=Jt(d.authMethods)}catch(d){throw await a.kill().catch(()=>{}),Ve(d,a)}return this.pendingAuthAgents.set(e,a),a.onExit(()=>{this.pendingAuthAgents.get(e)===a&&this.pendingAuthAgents.delete(e)}),a}async planSpawnForAgent(e){let t=await this.registry.getAgent(e);if(!t){let n=new Error(`agent ${e} not found in registry`);throw n.code=x.AgentNotInstalled,n}return we(t,[],{npmRegistry:this.npmRegistry})}consumePendingAuthAgent(e){let t=this.pendingAuthAgents.get(e);if(t&&(this.pendingAuthAgents.delete(e),!!t.isAlive()))return t}getAgentForSession(e){return this.sessions.get(e)?.agent}async attachManagerHooks(e){e.onClose(({deleteRecord:t})=>{if(this.sessions.delete(e.sessionId),this.driftNoticed.delete(e.sessionId),this.invalidateListCache(),t&&e.workspace!==void 0&&this.releaseWorkspace(e.workspace,e.sessionId).catch(()=>{}),t){if(e.upstreamSessionId){let r=At({interactive:e.interactive,...e.originatingClient?{originatingClient:e.originatingClient}:{}},!0),o=this.tombstoneAllGenerations(e.sessionId,{agentId:e.agentId,upstreamSessionId:e.upstreamSessionId,upstreamUpdatedAt:new Date(e.updatedAt).toISOString(),cwd:e.cwd,...e.title!==void 0?{title:e.title}:{},...r!==void 0?{interactive:r}:{}},"user").catch(()=>{}).then(()=>this.store.delete(e.sessionId).catch(()=>{})).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===o&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,o);return}let n=this.store.delete(e.sessionId).catch(()=>{}).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===n&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,n);return}}),e.onTitleChange(t=>{this.persistTitle(e.sessionId,t).catch(()=>{})}),e.onPriorityChange(t=>{this.persistPriority(e.sessionId,t).catch(()=>{})}),e.onAgentChange(({agentId:t,upstreamSessionId:n,retiredCost:r,reason:o,runId:i})=>{this.persistAgentChange(e.sessionId,t,n,r,o,i).catch(()=>{})}),e.onModelChange(t=>{this.persistSnapshot(e.sessionId,{currentModel:t}).catch(()=>{})}),e.onModeChange(t=>{this.persistSnapshot(e.sessionId,{currentMode:t}).catch(()=>{})}),e.onInteractiveChange(t=>{this.persistSnapshot(e.sessionId,{interactive:t}).catch(()=>{})}),e.onUsageChange(t=>{this.persistSnapshot(e.sessionId,{currentUsage:ya(t)}).catch(()=>{})}),e.onAgentCommandsChange(t=>{this.persistSnapshot(e.sessionId,{agentCommands:t.map(n=>({name:n.name,...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModesChange(t=>{this.persistSnapshot(e.sessionId,{agentModes:t.map(n=>({id:n.id,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModelsChange(t=>{this.persistSnapshot(e.sessionId,{agentModels:t.map(n=>({modelId:n.modelId,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAttentionFlagsChange(t=>{this.mutateRecord(e.sessionId,{attentionFlags:t}).catch(()=>{})}),this.sessions.set(e.sessionId,e),this.invalidateListCache(),await this.enqueueMetaWrite(e.sessionId,async()=>{let t=await this.store.read(e.sessionId),n=wp(e,t);await this.store.write(n)}).catch(()=>{})}async getHistory(e){if(this.sessions.has(e))return this.histories.load(e).catch(()=>[]);if(await this.store.read(e))return this.histories.load(e).catch(()=>[])}async loadHistory(e,t={}){return this.histories.load(e,t)}async loadToolBlob(e,t){return Tt(e,t)}async loadFromDisk(e){let t=await this.store.read(e);if(!t)return;let n=t.title;return n||(n=await this.deriveTitleFromHistory(e)),{hydraSessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,agentId:t.agentId,cwd:t.cwd,title:n,synopsis:t.synopsis,summarizedThroughEntry:t.summarizedThroughEntry,agentArgs:t.agentArgs,currentModel:t.currentModel,currentMode:t.currentMode,currentUsage:kp(t.currentUsage),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,forwardedEnv:t.forwardedEnv,workspace:t.workspace,compactionState:t.compactionState,attentionFlags:t.attentionFlags?.filter(r=>!(r.source==="daemon"&&r.reason.startsWith("permission:")))}}async setForwardedEnv(e,t){if(t===void 0)return;let n=this.sessions.get(e);n&&(n.forwardedEnv=t),await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r)return;let o={...r,forwardedEnv:t};await this.store.write(o)})}async clearPendingHistorySync(e){await this.enqueueMetaWrite(e,async()=>{let t=await this.store.read(e);if(!t||t.pendingHistorySync!==!0)return;let n={...t};delete n.pendingHistorySync,await this.store.write(n)})}async deriveTitleFromHistory(e){let t=await this.histories.load(e).catch(()=>[]);for(let n of t){let r=n.params;if(r?.update?.sessionUpdate!=="prompt_received")continue;let o=ht(r.update.prompt),i=Xs(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 n=t.agent.agentId,r=t.agent.version,o=e.get(n);o||(o=new Set,e.set(n,o)),o.add(r)}return e}async resolveCanonicalId(e){if(this.sessions.has(e)||await this.store.read(e))return e;if(e.startsWith(Me))return;let t=Me+e;if(this.sessions.has(t)||await this.store.read(t))return t}require(e){let t=this.sessions.get(e);if(!t){let n=new Error(`session ${e} not found`);throw n.code=x.SessionNotFound,n}return t}liveListEntry(e){return{sessionId:e.sessionId,upstreamSessionId:e.upstreamSessionId,cwd:e.cwd,workspace:e.workspace,workspaceError:e.workspaceError,title:e.title,agentId:e.agentId,currentModel:e.currentModel,currentUsage:e.currentUsage,parentSessionId:e.parentSessionId,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,forkSynthesisState:e.forkSynthesisState,originatingClient:e.originatingClient,interactive:e.interactive,updatedAt:new Date(e.updatedAt).toISOString(),attachedClients:e.attachedCount,status:"warm",busy:e.turnStartedAt!==void 0,armedTasks:e.armedBackgroundTasks.length,...e.armedSince!==void 0?{armedSince:e.armedSince}:{},awaitingInput:e.awaitingInput,agentPid:e.agentPid}}async getOne(e){let t=this.sessions.get(e);if(t){let a=await Vt(t.sessionId),d=At({interactive:t.interactive,...t.originatingClient?{originatingClient:t.originatingClient}:{}},a.hasContent),c=a.mtime??new Date(t.updatedAt).toISOString();return{sessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,cwd:t.cwd,title:t.title,agentId:t.agentId,currentModel:t.currentModel,currentUsage:t.currentUsage,parentSessionId:t.parentSessionId,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,originatingClient:t.originatingClient,interactive:d,priority:t.priority,updatedAt:c,attachedClients:t.attachedCount,status:"warm",agentPid:t.agentPid,busy:t.turnStartedAt!==void 0,armedTasks:t.armedBackgroundTasks.length,...t.armedSince!==void 0?{armedSince:t.armedSince}:{},awaitingInput:t.awaitingInput}}let n=await this.store.read(e).catch(()=>{});if(!n)return;let r=await Vt(n.sessionId),o=At(n,r.hasContent),i=r.mtime??n.updatedAt;return{sessionId:n.sessionId,upstreamSessionId:n.upstreamSessionId,cwd:n.cwd,title:n.title,agentId:n.agentId,currentModel:n.currentModel,currentUsage:zt(n.currentUsage),importedFromMachine:n.importedFromMachine,importedFromUpstreamSessionId:n.importedFromUpstreamSessionId,parentSessionId:n.parentSessionId,forkedFromSessionId:n.forkedFromSessionId,forkedFromMessageId:n.forkedFromMessageId,forkSynthesisState:n.forkSynthesisState,originatingClient:n.originatingClient,interactive:o,priority:n.priority,updatedAt:i,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1}}async list(e={}){let t=`${e.cwd??""}|${e.includeNonInteractive?"1":"0"}|${e.status??""}`,n=Date.now(),r=this.listCache.get(t);if(r&&r.expiresAt>n)return r.promise;let o=this.listUncached(e);return this.listCache.set(t,{expiresAt:n+s.LIST_CACHE_TTL_MS,promise:o}),o.catch(()=>{let i=this.listCache.get(t);i&&i.promise===o&&this.listCache.delete(t)}),o}invalidateListCache(){this.listCache.clear()}async listUncached(e={}){let t=[],n=new Set,r=u=>e.includeNonInteractive?!0:u===!0,o=[...this.sessions.values()].filter(u=>pa(e.cwd,u));if(e.status==="cold")for(let u of o)n.add(u.sessionId);let i=e.status==="cold"?[]:await Promise.all(o.map(u=>Vt(u.sessionId)));for(let u=0;u<i.length;u+=1){let l=o[u],f=i[u];n.add(l.sessionId);let p=At({interactive:l.interactive,...l.originatingClient?{originatingClient:l.originatingClient}:{}},f.hasContent);if(!r(p))continue;let g=f.mtime??new Date(l.updatedAt).toISOString();t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,workspace:l.workspace,workspaceError:l.workspaceError,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:p,priority:l.priority,updatedAt:g,attachedClients:l.attachedCount,status:"warm",agentPid:l.agentPid,busy:l.turnStartedAt!==void 0,armedTasks:l.armedBackgroundTasks.length,...l.armedSince!==void 0?{armedSince:l.armedSince}:{},awaitingInput:l.awaitingInput,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}if(e.status==="warm")return t;let d=(await this.store.list().catch(u=>{throw this.logger?.warn(`session list: store.list() failed: ${u?.message??String(u)}`),u})).filter(u=>!n.has(u.sessionId)&&pa(e.cwd,u)),c=await Promise.all(d.map(u=>Vt(u.sessionId)));for(let u=0;u<d.length;u+=1){let l=d[u],f=c[u],p=At(l,f.hasContent);if(!r(p))continue;let g=f.mtime??l.updatedAt;t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,workspace:l.workspace,title:l.title,agentId:l.agentId,currentModel:l.currentModel,currentUsage:zt(l.currentUsage),importedFromMachine:l.importedFromMachine,importedFromUpstreamSessionId:l.importedFromUpstreamSessionId,parentSessionId:l.parentSessionId,forkedFromSessionId:l.forkedFromSessionId,forkedFromMessageId:l.forkedFromMessageId,originatingClient:l.originatingClient,interactive:p,priority:l.priority,updatedAt:g,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}return t.sort((u,l)=>u.updatedAt<l.updatedAt?1:-1),t}async exportBundle(e,t={}){let n=await this.store.read(e);if(!n)return;let r;if(n.lineageId)r=n;else{let c=Ut(),u={...n,lineageId:c};await this.enqueueMetaWrite(e,async()=>{let l=await this.store.read(e);l&&(l.lineageId||await this.store.write({...l,lineageId:c}))}).catch(()=>{}),r=u}let o=t.tools??"inline",i=await this.histories.load(e,o==="references"?{tools:"references"}:{}).catch(()=>[]),a=await ma(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let d={};for(let c of ra(i)){let u=await mo(e,c);u&&(d[c]=u.toString("base64"))}return{record:r,history:i,promptHistory:a,toolBlobs:d}}async importBundle(e,t={}){let n=await this.store.findByLineageId(e.session.lineageId);if(n){if(!t.replace){let i=new Error(`bundle already imported as ${n.sessionId}`);throw i.code=x.BundleAlreadyImported,i.existingSessionId=n.sessionId,i}let o=this.sessions.get(n.sessionId);return o&&await o.close({deleteRecord:!1,by:"bundle-import-overwrite"}).catch(()=>{}),await this.writeImportedRecord({sessionId:n.sessionId,bundle:e,preservedCreatedAt:n.createdAt,cwd:t.cwd}),{sessionId:n.sessionId,importedFromSessionId:e.session.sessionId,replaced:!0}}let r=`${Me}${It()}`;return await this.writeImportedRecord({sessionId:r,bundle:e,cwd:t.cwd}),{sessionId:r,importedFromSessionId:e.session.sessionId,replaced:!1}}async forkSession(e,t={}){let n=await this.store.read(e);if(!n){let I=new Error(`source session not found: ${e}`);throw I.code=x.SessionNotFound,I}let r=t.agentId??n.agentId,o=r!==n.agentId;if(o&&!await this.registry.getAgent(r)){let b=new Error(`agent ${r} not found in registry`);throw b.code=x.AgentNotInstalled,b}let i=await this.histories.load(e).catch(()=>[]),a=i,d,c=t.mode??"synthesis",u,l,f,p=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let I=bn(i,t.forkAt);if(I<0){let b=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw b.code=x.InvalidParams,b}d=t.forkAt,a=i.slice(0,I+1)}else{let I=vp(i);I?(d=I.messageId,a=i.slice(0,I.index+1)):(d="",a=i.slice(0,0))}else{if(t.forkAt!==void 0&&t.forkAt!==""){let b=bn(i,t.forkAt);if(b<0){let A=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw A.code=x.InvalidParams,A}d=t.forkAt,a=i.slice(0,b+1)}else d="",a=i;let I=await this.registry.getAgent(r);if(!I){let b=new Error(`agent ${r} not found in registry`);throw b.code=x.AgentNotInstalled,b}f=I,l=n.currentModel,u="running"}let g=await ma(e),m=c==="synthesis",h={...n,lineageId:Ut(),agentId:r,interactive:!1,...u!==void 0?{forkSynthesisState:u}:{},summarizedThroughEntry:a.length,...t.title!==void 0?{title:t.title}:{},currentUsage:void 0,...o?{currentModel:void 0,currentMode:void 0,agentCommands:void 0,agentModes:void 0,agentModels:void 0}:{},...t.model!==void 0?{currentModel:t.model}:{}},y=qt({record:h,history:a,promptHistory:g.length>0?g:void 0,hydraVersion:ie,machine:$t()}),k=`${Me}${It()}`,w=t.cwd,S;if(t.cwd===void 0&&n.workspace!==void 0){let I=await this.deriveForkWorkspace(n.workspace,`${n.workspace.label}-fork-${k.slice(-6)}`);I!==void 0?(S=I,w=I.path):(w=n.workspace.sourceCwd,this.logger?.warn?.(`fork ${k}: could not derive an isolated workspace from ${n.workspace.path}; running unisolated in ${w}`))}return await this.writeImportedRecord({sessionId:k,bundle:y,cwd:w,...S!==void 0?{workspace:S}:{},forkedFromSessionId:e,forkedFromMessageId:d,...u!==void 0?{forkSynthesisState:u}:{}}),m&&(async()=>{try{let I=await we(f,[],{npmRegistry:this.npmRegistry}),b=await Nn({agentId:r,cwd:t.cwd??C.sessionDir(e),plan:I,history:a,modelId:l,sessionId:e,logger:this.logger,timeoutMs:p});b&&b.synopsis?await this.mutateRecord(k,{synopsis:b.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(k,{},["forkSynthesisState"]))}catch(I){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${I.message}`);try{await this.mutateRecord(k,{},["forkSynthesisState"])}catch(b){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${b.message}`)}}})(),{sessionId:k,forkedFromSessionId:e,forkedAt:d}}async writeImportedRecord(e){if(await this.histories.rewrite(e.sessionId,e.bundle.history),e.bundle.toolBlobs)for(let[o,i]of Object.entries(e.bundle.toolBlobs))await ho(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await Xe.utimes(C.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await ca(C.tuiHistoryFile(e.sessionId),e.bundle.promptHistory).catch(()=>{});let n=new Date().toISOString(),r=e.forkedFromSessionId!==void 0;await this.enqueueMetaWrite(e.sessionId,async()=>{await this.store.write({sessionId:e.sessionId,lineageId:e.bundle.session.lineageId,upstreamSessionId:"",...r?{forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId}:{importedFromSessionId:e.bundle.session.sessionId,importedFromUpstreamSessionId:e.bundle.session.upstreamSessionId,importedFromMachine:e.bundle.exportedFrom.machine},agentId:e.bundle.session.agentId,cwd:e.cwd??e.bundle.session.cwd,workspace:e.workspace,title:e.bundle.session.title,synopsis:e.bundle.session.synopsis,summarizedThroughEntry:e.bundle.session.summarizedThroughEntry,...e.forkSynthesisState!==void 0?{forkSynthesisState:e.forkSynthesisState}:{},currentModel:e.bundle.session.currentModel,currentMode:e.bundle.session.currentMode,currentUsage:e.bundle.session.currentUsage,agentCommands:e.bundle.session.agentCommands,agentModes:e.bundle.session.agentModes,interactive:e.bundle.session.interactive,originatingClient:e.bundle.session.originatingClient,priority:e.bundle.session.priority,attentionFlags:[],createdAt:e.preservedCreatedAt??n,updatedAt:e.bundle.session.updatedAt})})}async tombstoneAllGenerations(e,t,n){let r=await this.store.read(e).catch(()=>{}),o=new Map;for(let a of r?.upstreamGenerations??[])a.upstreamSessionId&&o.set(`${a.agentId}::${a.upstreamSessionId}`,{agentId:a.agentId,upstreamSessionId:a.upstreamSessionId});o.set(`${t.agentId}::${t.upstreamSessionId}`,{agentId:t.agentId,upstreamSessionId:t.upstreamSessionId});let i=new Date().toISOString();for(let a of o.values())await this.tombstones.add({agentId:a.agentId,upstreamSessionId:a.upstreamSessionId,deletedAt:i,upstreamUpdatedAt:t.upstreamUpdatedAt,cwd:t.cwd,...t.title!==void 0?{title:t.title}:{},reason:n,...t.interactive!==void 0?{interactive:t.interactive}:{}}).catch(()=>{})}async deleteRecord(e,t="user"){let n=await this.store.read(e);if(!n)return!1;if(n.upstreamSessionId){let r=await Vt(e),o=At(n,r.hasContent);await this.tombstoneAllGenerations(e,{agentId:n.agentId,upstreamSessionId:n.upstreamSessionId,upstreamUpdatedAt:n.updatedAt,cwd:n.cwd,...n.title!==void 0?{title:n.title}:{},...o!==void 0?{interactive:o}:{}},t)}return n.workspace!==void 0&&await this.releaseWorkspace(n.workspace,e).catch(()=>{}),await this.store.delete(e).catch(()=>{}),await this.histories.delete(e).catch(()=>{}),this.invalidateListCache(),!0}async waitForDeletion(e){let t=this.pendingDeletions.get(e);t&&await t}async isTombstoned(e,t){return(await this.tombstones.read(e,t).catch(()=>{}))?.reason==="user"}async hasRecord(e){return await this.store.read(e).catch(()=>{})!==void 0}async clearWorkspaceBinding(e){if(this.get(e)!==void 0)return"live";let t=await this.store.read(e).catch(()=>{});if(!t)return"missing";let n=t.workspace?.sourceCwd;return await this.mutateRecord(e,n!==void 0?{cwd:n}:{},["workspace"]),"cleared"}async setCwd(e,t){if(this.get(e)!==void 0)return"live";let n=await this.store.read(e).catch(()=>{});return n?n.workspace!==void 0?"bound":await this.dirExists(t)?(await this.mutateRecord(e,{cwd:t}),this.invalidateListCache(),"set"):"not-a-directory":"missing"}async setPriority(e,t){let n=this.get(e);if(n)return n.setPriority(t),!0;if(!await this.hasRecord(e))return!1;let r=t===void 0||t<=0?void 0:Math.floor(t);return await this.persistPriority(e,r),!0}async persistPriority(e,t){t===void 0?await this.mutateRecord(e,{},["priority"]):await this.mutateRecord(e,{priority:t}),this.invalidateListCache()}async setTitle(e,t){let n=this.get(e);return n?(await n.retitle(t),!0):await this.hasRecord(e)?(await this.persistTitle(e,t),!0):!1}async persistTitle(e,t){await this.mutateRecord(e,{title:t})}async persistSynopsis(e,t,n){await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:n})}async persistAgentChange(e,t,n,r,o,i){await this.mutateRecord(e,{agentId:t,upstreamSessionId:n},void 0,a=>({upstreamGenerations:wa(a,t,n,void 0,r,o,i)}))}async persistSnapshot(e,t){let n={};t.currentModel!==void 0&&(n.currentModel=t.currentModel),t.currentMode!==void 0&&(n.currentMode=t.currentMode),t.currentUsage!==void 0&&(n.currentUsage=t.currentUsage),t.agentCommands!==void 0&&(n.agentCommands=t.agentCommands),t.agentModes!==void 0&&(n.agentModes=t.agentModes),t.agentModels!==void 0&&(n.agentModels=t.agentModels),t.interactive!==void 0&&(n.interactive=t.interactive),t.cwd!==void 0&&(n.cwd=t.cwd),await this.mutateRecord(e,n)}async mutateRecord(e,t,n=[],r){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o,...t,...r?r(o):{},updatedAt:new Date().toISOString()};for(let a of n)delete i[a];await this.store.write(i)})}static EXTENSION_STATE_CAP_BYTES=64*1024;async getExtensionState(e,t){return(await this.store.read(e))?.extensionState?.[t]??{}}async getExtensionStateKey(e,t,n){return(await this.getExtensionState(e,t))[n]}async setExtensionStateKey(e,t,n,r){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o.extensionState??{}},a={...i[t]??{},[n]:r},d=Buffer.byteLength(JSON.stringify(a),"utf8");if(d>s.EXTENSION_STATE_CAP_BYTES)throw new Error(`extension_state: bucket for ${t} would be ${d} bytes; cap is ${s.EXTENSION_STATE_CAP_BYTES}`);i[t]=a;let c={...o,extensionState:i,updatedAt:new Date().toISOString()};await this.store.write(c)})}async deleteExtensionStateKey(e,t,n){await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r?.extensionState?.[t])return;let o={...r.extensionState},i={...o[t]};if(!(n in i))return;delete i[n],Object.keys(i).length===0?delete o[t]:o[t]=i;let a={...r,extensionState:o,updatedAt:new Date().toISOString()};await this.store.write(a)})}enqueueMetaWrite(e,t){return this.enqueueKeyed(this.metaWriteQueues,e,t)}enqueueKeyed(e,t,n){let o=(e.get(t)??Promise.resolve()).catch(()=>{}).then(n),i=o.catch(()=>{});return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)}),o}liveSessionsIn(e,t){let n=[];for(let r of this.sessions.values())r.sessionId!==t&&r.workspace?.path===e&&n.push(r);return n}async closeAll(){let e=[...this.sessions.values()];await Promise.allSettled(e.map(t=>t.close({deleteRecord:!1,by:"daemon-shutdown"}))),this.sessions.clear()}async flushSynopsis(e){await this.synopsisCoordinator.flush(e)}async shutdownSynopsis(){await this.synopsisCoordinator.shutdown()}scheduleSynopsis(e){this.synopsisCoordinator.schedule(e)}scheduleCompaction(e,t){if(t?.targetAgentId){this.mutateRecord(e,{pendingAgentSwap:t.targetAgentId}).catch(r=>{this.logger?.warn(`scheduleCompaction: failed to stamp pendingAgentSwap for ${e}: ${r instanceof Error?r.message:String(r)}`)});let n=t.targetAgentId;(async()=>{try{let r=await this.store.read(e);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=${n} (reusing artifact @${r.summarizedThroughEntry})`),await this.dispatchSynthesisSwap(e,r.synopsis,r.summarizedThroughEntry,n)}catch(r){this.logger?.warn(`scheduleCompaction: fast-path check failed for ${e}: ${r instanceof Error?r.message:String(r)} \u2014 falling back to synthesis`),this.synopsisCoordinator.scheduleCompaction(e,t)}})();return}this.synopsisCoordinator.scheduleCompaction(e,t)}getCompactionInFlight(){let e=this.synopsisCoordinator.size();return e.inflight>0||e.queued>0}async getPendingAgentSwap(e){return(await this.store.read(e).catch(()=>{}))?.pendingAgentSwap}async getCompactionState(e){return(await this.store.read(e).catch(()=>{}))?.compactionState}async persistRollbackBreadcrumb(e,t){await this.mutateRecord(e,{},void 0,n=>{let r=n.rollbackBreadcrumb;return r!==void 0&&t.runId!==void 0&&r.runId===t.runId?(this.logger?.info(`compaction: keeping rollback breadcrumb pinned at ${r.previousUpstreamSessionId} for runId=${t.runId} sessionId=${e} (later swap of the same run)`),{}):{rollbackBreadcrumb:t}})}async getUpstreamGenerations(e){return(await this.store.read(e).catch(()=>{}))?.upstreamGenerations??[]}async getRollbackBreadcrumb(e){return(await this.store.read(e).catch(()=>{}))?.rollbackBreadcrumb}emitSwapPhase(e,t,n){let r=this.get(e);if(r){if(t){let o=n.phase==="failed";r.broadcastPendingAgentSwap(o?null:t);return}r.broadcastCompactionPhase(n)}}async getSummarizedThroughEntry(e){let t=this.sessions.get(e);return t?t.summarizedThroughEntry:(await this.store.read(e).catch(()=>{}))?.summarizedThroughEntry}async flushMetaWrites(){let e=[...this.metaWriteQueues.values()];e.length!==0&&await Promise.allSettled(e)}async flushHistoryWrites(){await this.histories.flushAll()}async reconcilePermissionFlags(){let e=await this.store.list().catch(()=>[]),t=0;for(let n of e){let r=n.attentionFlags??[],o=r.filter(i=>!(i.source==="daemon"&&i.reason.startsWith("permission:")));if(o.length!==r.length){let i=r.length-o.length;t+=i,await this.mutateRecord(n.sessionId,{attentionFlags:o}).catch(()=>{})}}t>0&&this.logger?.info(`cleared ${t} stale permission attention flags on startup`)}async resumePendingCompactions(){let e=new Set(["requested","running","swap_pending","swap_deferred"]),t=await this.store.list().catch(()=>[]);for(let n of t){let r=n.compactionState;if(r!=null){if(!e.has(r.status)){this.logger?.info(`compaction: not resuming sessionId=${n.sessionId} status=${r.status} (terminal \u2014 user must re-trigger explicitly)`);continue}this.logger?.info(`compaction: resuming sessionId=${n.sessionId} status=${r.status} from prior daemon`);try{this.scheduleCompaction(n.sessionId)}catch(o){this.logger?.warn(`compaction: resume failed for sessionId=${n.sessionId}: ${o instanceof Error?o.message:String(o)}`)}}}}async resumePendingAgentSwaps(){let e=await this.store.list().catch(()=>[]);for(let t of e){let n=t.pendingAgentSwap;if(n)try{let r=await this.histories.load(t.sessionId).catch(()=>[]);t.synopsis!==void 0&&t.summarizedThroughEntry!==void 0&&t.summarizedThroughEntry>=r.length&&t.synopsis?(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${n} with persisted synopsis (history=${r.length})`),await this.dispatchSynthesisSwap(t.sessionId,t.synopsis,t.summarizedThroughEntry??r.length,n)):(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${n} via fresh synthesis (history=${r.length} watermark=${t.summarizedThroughEntry??"(none)"})`),this.scheduleCompaction(t.sessionId,{targetAgentId:n}))}catch(r){this.logger?.warn(`agent-swap: resume failed for sessionId=${t.sessionId}: ${r instanceof Error?r.message:String(r)}`)}}}async resurrectPendingQueues(){let e=await this.store.list().catch(()=>[]);for(let t of e){let n=await gi(t.sessionId).catch(()=>[]);if(n.length===0)continue;let r=Date.now(),o=n.filter(d=>r-d.enqueuedAt<la),i=n.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${la/1e3}s)`),await Ot(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 Ot(t.sessionId,[]).catch(()=>{});continue}try{let d=await this.resurrect(a);this.logger?.info(`queue replay: resurrected ${t.sessionId} and replaying ${o.length} prompt(s)`),d.replayPersistedQueue(o)}catch(d){this.logger?.warn(`queue replay: failed to resurrect ${t.sessionId}: ${d.message}`)}}}};function yp(s,e){if(typeof s!="string"||s.length===0)return!1;let t=Gt.resolve(s),n=Gt.resolve(e);return t===n||t.startsWith(n+Gt.sep)}function pa(s,e){if(s===void 0||s.length===0)return!0;let t=Sr(s);if(Sr(e.cwd)===t)return!0;let n=e.workspace?.sourceCwd;return n!==void 0&&Sr(n)===t}function Sr(s){return s.length>1&&s.endsWith("/")?s.replace(/\/+$/,""):s}function wp(s,e){let n=(s.mergedAvailableCommands().length>0?s.agentOnlyAdvertisedCommands().map(u=>u.description!==void 0?{name:u.name,description:u.description}:{name:u.name}):void 0)??e?.agentCommands,r=s.availableModes(),i=(r.length>0?r.map(u=>{let l={id:u.id};return u.name!==void 0&&(l.name=u.name),u.description!==void 0&&(l.description=u.description),l}):void 0)??e?.agentModes,a=s.availableModels(),c=(a.length>0?a.map(u=>{let l={modelId:u.modelId};return u.name!==void 0&&(l.name=u.name),u.description!==void 0&&(l.description=u.description),l}):void 0)??e?.agentModels;return ir({sessionId:s.sessionId,lineageId:e?.lineageId??Ut(),upstreamSessionId:s.upstreamSessionId,importedFromSessionId:e?.importedFromSessionId,importedFromUpstreamSessionId:e?.importedFromUpstreamSessionId,importedFromMachine:e?.importedFromMachine,agentId:s.agentId,cwd:s.cwd,title:s.title,synopsis:e?.synopsis,summarizedThroughEntry:e?.summarizedThroughEntry,agentArgs:s.agentArgs,currentModel:s.currentModel??e?.currentModel,currentMode:s.currentMode??e?.currentMode,currentUsage:ya(s.persistableUsage)??e?.currentUsage,agentCommands:n,agentModes:i,agentModels:c,parentSessionId:s.parentSessionId??e?.parentSessionId,forkedFromSessionId:s.forkedFromSessionId??e?.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId??e?.forkedFromMessageId,originatingClient:s.originatingClient??e?.originatingClient,interactive:s.interactive??e?.interactive,priority:s.priority??e?.priority,forwardedEnv:s.forwardedEnv??e?.forwardedEnv,workspace:s.workspace,attentionFlags:s.listAttentionFlags(),extensionState:e?.extensionState,upstreamGenerations:e?wa(e,s.agentId,s.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(s.createdAt).toISOString()})}function ya(s){if(!s)return;let e={};return s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size),s.costAmount!==void 0&&(e.costAmount=s.costAmount),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),s.cumulativeCost!==void 0&&(e.cumulativeCost=s.cumulativeCost),Object.keys(e).length>0?e:void 0}function kp(s){return s?{...s}:void 0}function Ir(s,e={}){if(s!=="claude-acp")return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t}}}function Dn(s,e){let t=e.fromObject(s);if(t!==void 0)return t;let n=s[e.nestedKey];if(n&&typeof n=="object"&&!Array.isArray(n)){let i=e.fromObject(n);if(i!==void 0)return i}let r=s._meta;if(r&&typeof r=="object"&&!Array.isArray(r)){for(let[i,a]of Object.entries(r))if(i!=="hydra-acp"&&a&&typeof a=="object"&&!Array.isArray(a)){let d=e.fromObject(a);if(d!==void 0)return d}}let o=bp(s,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function Ar(s){return Dn(s,{nestedKey:"models",configId:"model",fromObject:e=>$e(e.currentModelId)??$e(e.currentModel)??$e(e.modelId)??$e(e.model),fromConfig:e=>$e(e.currentValue)})}function Ve(s,e){if(!s||typeof s!="object")return s;let t=s;if(t.code!==x.AuthRequired)return s;let n=c=>!!c&&typeof c=="object"&&!Array.isArray(c),r=n(t.data)?t.data:{},o=n(r._meta)?r._meta:{},i=n(o["hydra-acp"])?o["hydra-acp"]:{},a=typeof t.message=="string"?t.message:"authentication required",d=new Error(a);return d.code=x.AuthRequired,d.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function fa(s){return/^[A-Za-z0-9_\-./=:@]+$/.test(s)?s:`'${s.replace(/'/g,"'\\''")}'`}function ga(s,e,t,n){if(s&&typeof s=="object"&&s.code===x.AuthRequired)return s;let r=s instanceof Error?s.message:String(s),o=r.includes("stderr:"),i=o?"":e.stderrTailText(),a=n?`to reproduce: (cd ${fa(n.cwd)} && ${[n.command,...n.args].map(fa).join(" ")})`:"";if(!i&&!a)return s;let d=[o?r:`agent ${t} failed to start: ${r}`];i&&d.push(`stderr: ${i}`),a&&d.push(a);let c=new Error(d.join(`
|
|
168
|
+
`)}async copyCarriedWork(e,t,n){let r=await this.patchFromSnapshot(n,t,e.provider);if(r===void 0)return!1;if(r.length===0)return!0;let o=Y(e.provider);return o===void 0?!1:(await o.applyDelta(e.path,r)).ok}async patchFromSnapshot(e,t,n){let r=Y(n);if(r===void 0)return;let o=await r.currentState(e);if(o!==void 0)return await r.captureDelta(e,o,t).catch(()=>{})}async unwindStartWorkspace(e){let{provider:t,ws:n,startRef:r,carried:o}=e;await t.unlock(n).catch(()=>{}),o!==void 0&&await t.dropSnapshotRef(n,r).catch(()=>{}),await t.removeWorkspace(n,{force:!0}).catch(()=>{})}async materializeNestedTrees(e,t){let n=Y(e.provider);if(n?.capabilities().supports.nestedTrees!==!0)return;let r=await n.materializeNested({path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:n.kind},t).catch(o=>({ok:!1,count:0,reason:o instanceof Error?o.message:String(o)}));return r.ok?r.count>0?`populated ${r.count} nested tree(s)`:void 0:`nested trees FAILED: ${r.reason??"unknown"}`}async applyWorkspaceSetup(e,t){let n=await Mn(e.sourceCwd).catch(()=>({})),r=[];if(n.carry!==void 0&&n.carry.length>0){let o=await mr(e.sourceCwd,e.path,n.carry).catch(()=>{});o!==void 0&&o.copied.length>0&&r.push(`carried ${o.copied.length} config file(s)`)}if(n.postCreate!==void 0){let o=await Tn(n.postCreate,{workspacePath:e.path,sourceCwd:e.sourceCwd,label:e.label,sessionId:t,...n.hookTimeoutSeconds!==void 0?{timeoutSeconds:n.hookTimeoutSeconds}:{}});r.push(o.ok?"ran postCreate":`postCreate FAILED: ${o.reason??"unknown"}`)}return r.length>0?r.join("; "):void 0}async deriveForkWorkspace(e,t){let n=Y(e.provider);if(n===void 0)return;let r=n.capabilities(),o=r.sharedHistory?await n.currentState(e.path)??"":"",i=await n.createWorkspace({sourceCwd:e.sourceCwd,label:t,...o.length>0?{from:o}:{contentFrom:e.path}}).catch(d=>({ok:!1,reason:String(d)}));if(!i.ok){this.logger?.warn?.(`fork workspace: could not derive from ${e.path}: ${i.reason}`);return}let a=i.workspace;if(o.length>0&&r.supports.captureWorkingState){let d=await n.captureWorkingState(e.path,`hydra: fork carry from ${e.label}`).catch(()=>{});d!==void 0&&d!==o&&await this.copyUncommittedInto(e.path,a.path,o,d,a.provider).catch(()=>{})}return{path:a.path,sourceCwd:a.sourceCwd,label:a.label,provider:a.provider,...a.snapshot!==void 0?{snapshot:a.snapshot}:{},...a.line!==void 0?{line:a.line}:{},...a.vcs!==void 0?{vcs:{...a.vcs}}:{}}}async copyUncommittedInto(e,t,n,r,o){let i=Y(o);if(i===void 0)return!1;let a=await i.captureDelta(e,n,r).catch(()=>{});return a===void 0||a.trim().length===0?!1:(await i.applyDelta(t,a,{stage:!0})).ok}async recoverWorkspace(e){let t=Y(e.provider);if(t===void 0)return;let n={path:e.path,sourceCwd:e.sourceCwd,label:e.label,provider:e.provider,...e.snapshot!==void 0?{snapshot:e.snapshot}:{},...e.vcs!==void 0?{vcs:e.vcs}:{}};if(t.capabilities().supports.rematerialize){let o=await t.rematerialize(n).catch(i=>({ok:!1,reason:String(i)}));if(o.ok)return this.logger?.info?.(`session workspace: restored ${o.workspace.path} from retained state`),{...e,path:o.workspace.path};this.logger?.warn?.(`session workspace: could not restore: ${o.reason}`)}if(!await this.dirExists(e.sourceCwd))return;let r=await t.createWorkspace({sourceCwd:e.sourceCwd,label:`${e.label}-r`}).catch(o=>({ok:!1,reason:String(o)}));if(r.ok)return this.logger?.warn?.(`session workspace: ${e.path} is gone and could not be restored; resurrecting in a fresh workspace ${r.workspace.path} from ${e.sourceCwd}. Uncommitted work from the old workspace is not recoverable.`),{path:r.workspace.path,sourceCwd:r.workspace.sourceCwd,label:r.workspace.label,provider:r.workspace.provider,...r.workspace.snapshot!==void 0?{snapshot:r.workspace.snapshot}:{},...r.workspace.vcs!==void 0?{vcs:{...r.workspace.vcs}}:{}}}async syncFromAgent(e){let t=await this.registry.getAgent(e);if(!t){let p=new Error(`agent ${e} not found in registry`);throw p.code=x.AgentNotInstalled,p}let n=await we(t,[],{npmRegistry:this.npmRegistry}),r=this.spawner({agentId:e,cwd:ha.homedir(),plan:n}),o;try{o=await r.connection.request("initialize",{protocolVersion:1,clientCapabilities:at,clientInfo:{name:"hydra",version:ie}})}catch(p){throw await r.kill().catch(()=>{}),Ve(p,r)}if(r.authMethods=Jt(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(p){throw await r.kill().catch(()=>{}),p}await r.kill().catch(()=>{});let d=new Set;for(let p of this.sessions.values())d.add(`${p.agentId}::${p.upstreamSessionId}`);let c=await this.store.list().catch(()=>[]);for(let p of c){d.add(`${p.agentId}::${p.upstreamSessionId}`);for(let g of p.upstreamGenerations??[])d.add(`${g.agentId}::${g.upstreamSessionId}`)}let u=C.sessionsDir(),l=[],f=0;for(let p of a){let g=`${e}::${p.sessionId}`;if(d.has(g)){f+=1;continue}if(yp(p.cwd,u)){f+=1;continue}let m=await this.tombstones.read(e,p.sessionId).catch(()=>{});if(m){if(!Li(m,p.updatedAt)){f+=1;continue}await this.tombstones.remove(e,p.sessionId).catch(()=>{}),this.logger?.info(`syncFromAgent: resurrecting tombstoned ${e}/${p.sessionId} (upstream updatedAt advanced past ${m.upstreamUpdatedAt??"<unset>"})`)}d.add(g);let h=`${Me}${It()}`,y=new Date().toISOString(),k=p.updatedAt??y,w={sessionId:h,lineageId:Ut(),upstreamSessionId:p.sessionId,agentId:e,cwd:p.cwd,pendingHistorySync:!0,interactive:!0,createdAt:k,updatedAt:k};p.title!==void 0&&(w.title=p.title);let S=ir(w);await this.store.write(S),l.push({version:1,...S})}return{synced:l,skipped:f}}async collectAgentSessions(e){let t=[],n,r=new Set;for(let o=0;o<100;o+=1){let i={};n!==void 0&&(i.cursor=n);let a=await e.connection.request("session/list",i),d=Array.isArray(a.sessions)?a.sessions:[];for(let c of d){if(typeof c.sessionId!="string"||typeof c.cwd!="string")continue;let u={sessionId:c.sessionId,cwd:c.cwd};typeof c.title=="string"&&(u.title=c.title),typeof c.updatedAt=="string"&&(u.updatedAt=c.updatedAt),t.push(u)}if(typeof a.nextCursor!="string"||a.nextCursor.length===0||r.has(a.nextCursor))break;r.add(a.nextCursor),n=a.nextCursor}return t}async applySeedModel(e,t,n,r,o){try{let{verb:i}=await Je({request:(a,d)=>e.connection.request(a,d),sessionId:t,modelId:n,...o?{verb:o}:{},logger:this.logger});return this.logger?.info(`${r}: ${i} accepted`),!0}catch(i){return this.logger?.warn(`${r} rejected by agent (${i.message}); session will use the agent's own default`),!1}}async bootstrapAgent(e){let t=await this.registry.getAgent(e.agentId);if(!t){let i=new Error(`agent ${e.agentId} not found in registry`);throw i.code=x.AgentNotInstalled,i}let n=await we(t,e.agentArgs??[],{npmRegistry:this.npmRegistry,onInstallProgress:e.onInstallProgress}),r=an(e.selfSessionId,e.forwardedEnv),o=this.spawner({agentId:e.agentId,cwd:e.cwd,plan:n,...r?{extraEnv:r}:{}});try{let i=await o.connection.request("initialize",{protocolVersion:1,clientCapabilities:at,clientInfo:{name:"hydra",version:ie}}),a=i.agentCapabilities;o.authMethods=Jt(i.authMethods);let d=Ir(e.agentId),c=await o.connection.request("session/new",{cwd:e.cwd,mcpServers:e.mcpServers??[],...d&&{_meta:d}}),u=c.sessionId;if(typeof u!="string")throw new Error(`agent ${e.agentId} returned a non-string sessionId from session/new`);let l=Ar(c),f=xr(c),p=ct(c),g=e.model??this.defaultModels[e.agentId];if(g&&g!==l){let y=gt(g,f),k=e.model!==void 0?`model=${JSON.stringify(g)}`:`defaultModels[${e.agentId}]=${JSON.stringify(g)}`;if(y.kind==="exact"||y.kind==="none")await this.applySeedModel(o,u,g,k,p)&&(l=g);else if(y.kind==="resolved")(y.modelId===l||await this.applySeedModel(o,u,y.modelId,`${k} resolved to ${JSON.stringify(y.modelId)}`,p))&&(l=y.modelId);else if(y.kind==="ambiguous")this.logger?.warn(`${k} is ambiguous (trailing-segment matches [${y.candidates.join(", ")}]); skipping session/set_model, session will use ${JSON.stringify(l)}`);else{let w=f.map(S=>S.modelId).join(", ");this.logger?.warn(`${k} not in agent's availableModels ([${w}]); skipping session/set_model, session will use ${JSON.stringify(l)}`)}}let m=Rr(c),h=Er(c);return{agent:o,upstreamSessionId:u,agentMeta:c._meta,agentCapabilities:a,initialModel:l,initialModels:f.length>0?f:void 0,initialModes:m.length>0?m:void 0,initialMode:h,modelVerb:p}}catch(i){throw await o.kill().catch(()=>{}),Ve(ga(i,o,e.agentId,{command:n.command,args:n.args,cwd:e.cwd}),o)}}async bootstrapAgentLoad(e,t){let n=await this.registry.getAgent(t.agentId);if(!n){let a=new Error(`agent ${t.agentId} not found in registry`);throw a.code=x.AgentNotInstalled,a}let r=await we(n,t.agentArgs??[],{npmRegistry:this.npmRegistry}),o=an(t.selfSessionId,t.forwardedEnv),i=this.spawner({agentId:t.agentId,cwd:t.cwd,plan:r,...o?{extraEnv:o}:{}});try{let a=await i.connection.request("initialize",{protocolVersion:1,clientCapabilities:at,clientInfo:{name:"hydra",version:ie}}),d=a.agentCapabilities;i.authMethods=Jt(a.authMethods);let c=Ir(t.agentId),u=await i.connection.request("session/load",{sessionId:e,cwd:t.cwd,mcpServers:t.mcpServers??[],...c&&{_meta:c}}),l=Ar(u),f=Cr(xr(u)),p=Rr(u),g=Er(u);return{agent:i,upstreamSessionId:e,agentMeta:u._meta,agentCapabilities:d,initialModel:l,initialModels:f,initialModes:p.length>0?p:void 0,initialMode:g,modelVerb:ct(u)}}catch(a){throw await i.kill().catch(()=>{}),Ve(ga(a,i,t.agentId,{command:r.command,args:r.args,cwd:t.cwd}),i)}}async performUncompact(e){if(this.rollbackLocks.has(e))throw new Error("a rollback is already in progress for this session");let t=this.get(e);if(!t)throw new Error("session is not live \u2014 cannot roll back a cold session");let n=await this.store.read(e);if(!n)throw new Error("session record not found");let r=n.rollbackBreadcrumb;if(!r)throw new Error("no rollback breadcrumb found \u2014 either the session has not been compacted, the rollback window has closed (a new turn was dispatched), or a previous rollback already consumed the breadcrumb");let o=n.compactionState;if(o!=null)throw new Error(`compaction is in progress (status: ${o.status}) \u2014 wait for it to complete before rolling back`);if(!await t.isQuiescedForSwap())throw new Error("session is not quiesced for rollback \u2014 wait for in-flight work to complete");this.rollbackLocks.add(e);try{await t.rollbackToUpstream({previousUpstreamSessionId:r.previousUpstreamSessionId,previousSummarizedThroughEntry:r.previousSummarizedThroughEntry}),await this.mutateRecord(e,{summarizedThroughEntry:r.previousSummarizedThroughEntry},["synopsis","rollbackBreadcrumb"])}finally{this.rollbackLocks.delete(e)}}async bootstrapAgentForAuth(e,t){let n=this.pendingAuthAgents.get(e);if(n&&n.isAlive())return n;let r=await this.registry.getAgent(e);if(!r){let d=new Error(`agent ${e} not found in registry`);throw d.code=x.AgentNotInstalled,d}let o=await we(r,[],{npmRegistry:this.npmRegistry}),i=t??de(this.defaultCwd),a=this.spawner({agentId:e,cwd:i,plan:o});try{let d=await a.connection.request("initialize",{protocolVersion:1,clientCapabilities:at,clientInfo:{name:"hydra",version:ie}});a.authMethods=Jt(d.authMethods)}catch(d){throw await a.kill().catch(()=>{}),Ve(d,a)}return this.pendingAuthAgents.set(e,a),a.onExit(()=>{this.pendingAuthAgents.get(e)===a&&this.pendingAuthAgents.delete(e)}),a}async planSpawnForAgent(e){let t=await this.registry.getAgent(e);if(!t){let n=new Error(`agent ${e} not found in registry`);throw n.code=x.AgentNotInstalled,n}return we(t,[],{npmRegistry:this.npmRegistry})}consumePendingAuthAgent(e){let t=this.pendingAuthAgents.get(e);if(t&&(this.pendingAuthAgents.delete(e),!!t.isAlive()))return t}getAgentForSession(e){return this.sessions.get(e)?.agent}async attachManagerHooks(e){e.onClose(({deleteRecord:t})=>{if(this.sessions.delete(e.sessionId),this.driftNoticed.delete(e.sessionId),this.invalidateListCache(),t&&e.workspace!==void 0&&this.releaseWorkspace(e.workspace,e.sessionId).catch(()=>{}),t){if(e.upstreamSessionId){let r=At({interactive:e.interactive,...e.originatingClient?{originatingClient:e.originatingClient}:{}},!0),o=this.tombstoneAllGenerations(e.sessionId,{agentId:e.agentId,upstreamSessionId:e.upstreamSessionId,upstreamUpdatedAt:new Date(e.updatedAt).toISOString(),cwd:e.cwd,...e.title!==void 0?{title:e.title}:{},...r!==void 0?{interactive:r}:{}},"user").catch(()=>{}).then(()=>this.store.delete(e.sessionId).catch(()=>{})).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===o&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,o);return}let n=this.store.delete(e.sessionId).catch(()=>{}).then(()=>this.histories.delete(e.sessionId).catch(()=>{})).finally(()=>{this.pendingDeletions.get(e.sessionId)===n&&this.pendingDeletions.delete(e.sessionId)});this.pendingDeletions.set(e.sessionId,n);return}}),e.onTitleChange(t=>{this.persistTitle(e.sessionId,t).catch(()=>{})}),e.onPriorityChange(t=>{this.persistPriority(e.sessionId,t).catch(()=>{})}),e.onAgentChange(({agentId:t,upstreamSessionId:n,retiredCost:r,reason:o,runId:i})=>{this.persistAgentChange(e.sessionId,t,n,r,o,i).catch(()=>{})}),e.onModelChange(t=>{this.persistSnapshot(e.sessionId,{currentModel:t}).catch(()=>{})}),e.onModeChange(t=>{this.persistSnapshot(e.sessionId,{currentMode:t}).catch(()=>{})}),e.onInteractiveChange(t=>{this.persistSnapshot(e.sessionId,{interactive:t}).catch(()=>{})}),e.onUsageChange(t=>{this.persistSnapshot(e.sessionId,{currentUsage:ya(t)}).catch(()=>{})}),e.onAgentCommandsChange(t=>{this.persistSnapshot(e.sessionId,{agentCommands:t.map(n=>({name:n.name,...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModesChange(t=>{this.persistSnapshot(e.sessionId,{agentModes:t.map(n=>({id:n.id,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAgentModelsChange(t=>{this.persistSnapshot(e.sessionId,{agentModels:t.map(n=>({modelId:n.modelId,...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{}}))}).catch(()=>{})}),e.onAttentionFlagsChange(t=>{this.mutateRecord(e.sessionId,{attentionFlags:t}).catch(()=>{})}),this.sessions.set(e.sessionId,e),this.invalidateListCache(),await this.enqueueMetaWrite(e.sessionId,async()=>{let t=await this.store.read(e.sessionId),n=wp(e,t);await this.store.write(n)}).catch(()=>{})}async getHistory(e){if(this.sessions.has(e))return this.histories.load(e).catch(()=>[]);if(await this.store.read(e))return this.histories.load(e).catch(()=>[])}async loadHistory(e,t={}){return this.histories.load(e,t)}async loadToolBlob(e,t){return Tt(e,t)}async loadFromDisk(e){let t=await this.store.read(e);if(!t)return;let n=t.title;return n||(n=await this.deriveTitleFromHistory(e)),{hydraSessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,agentId:t.agentId,cwd:t.cwd,title:n,synopsis:t.synopsis,summarizedThroughEntry:t.summarizedThroughEntry,agentArgs:t.agentArgs,currentModel:t.currentModel,currentMode:t.currentMode,currentUsage:kp(t.currentUsage),agentCommands:t.agentCommands,agentModes:t.agentModes,agentModels:t.agentModels,createdAt:t.createdAt,pendingHistorySync:t.pendingHistorySync,originatingClient:t.originatingClient,interactive:t.interactive,priority:t.priority,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,forwardedEnv:t.forwardedEnv,workspace:t.workspace,compactionState:t.compactionState,attentionFlags:t.attentionFlags?.filter(r=>!(r.source==="daemon"&&r.reason.startsWith("permission:")))}}async setForwardedEnv(e,t){if(t===void 0)return;let n=this.sessions.get(e);n&&(n.forwardedEnv=t),await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r)return;let o={...r,forwardedEnv:t};await this.store.write(o)})}async clearPendingHistorySync(e){await this.enqueueMetaWrite(e,async()=>{let t=await this.store.read(e);if(!t||t.pendingHistorySync!==!0)return;let n={...t};delete n.pendingHistorySync,await this.store.write(n)})}async deriveTitleFromHistory(e){let t=await this.histories.load(e).catch(()=>[]);for(let n of t){let r=n.params;if(r?.update?.sessionUpdate!=="prompt_received")continue;let o=r.update.sentBy;if(typeof o?.fromSession=="string"||typeof o?.clientId=="string"&&o.clientId.startsWith("transformer:"))continue;let i=ht(r.update.prompt),a=Xs(i,200);if(a&&!a.startsWith("/"))return a}}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 n=t.agent.agentId,r=t.agent.version,o=e.get(n);o||(o=new Set,e.set(n,o)),o.add(r)}return e}async resolveCanonicalId(e){if(this.sessions.has(e)||await this.store.read(e))return e;if(e.startsWith(Me))return;let t=Me+e;if(this.sessions.has(t)||await this.store.read(t))return t}require(e){let t=this.sessions.get(e);if(!t){let n=new Error(`session ${e} not found`);throw n.code=x.SessionNotFound,n}return t}liveListEntry(e){return{sessionId:e.sessionId,upstreamSessionId:e.upstreamSessionId,cwd:e.cwd,workspace:e.workspace,workspaceError:e.workspaceError,title:e.title,agentId:e.agentId,currentModel:e.currentModel,currentUsage:e.currentUsage,parentSessionId:e.parentSessionId,forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId,forkSynthesisState:e.forkSynthesisState,originatingClient:e.originatingClient,interactive:e.interactive,updatedAt:new Date(e.updatedAt).toISOString(),attachedClients:e.attachedCount,status:"warm",busy:e.turnStartedAt!==void 0,armedTasks:e.armedBackgroundTasks.length,...e.armedSince!==void 0?{armedSince:e.armedSince}:{},awaitingInput:e.awaitingInput,agentPid:e.agentPid}}async getOne(e){let t=this.sessions.get(e);if(t){let a=await Vt(t.sessionId),d=At({interactive:t.interactive,...t.originatingClient?{originatingClient:t.originatingClient}:{}},a.hasContent),c=a.mtime??new Date(t.updatedAt).toISOString();return{sessionId:t.sessionId,upstreamSessionId:t.upstreamSessionId,cwd:t.cwd,title:t.title,agentId:t.agentId,currentModel:t.currentModel,currentUsage:t.currentUsage,parentSessionId:t.parentSessionId,forkedFromSessionId:t.forkedFromSessionId,forkedFromMessageId:t.forkedFromMessageId,forkSynthesisState:t.forkSynthesisState,originatingClient:t.originatingClient,interactive:d,priority:t.priority,updatedAt:c,attachedClients:t.attachedCount,status:"warm",agentPid:t.agentPid,busy:t.turnStartedAt!==void 0,armedTasks:t.armedBackgroundTasks.length,...t.armedSince!==void 0?{armedSince:t.armedSince}:{},awaitingInput:t.awaitingInput}}let n=await this.store.read(e).catch(()=>{});if(!n)return;let r=await Vt(n.sessionId),o=At(n,r.hasContent),i=r.mtime??n.updatedAt;return{sessionId:n.sessionId,upstreamSessionId:n.upstreamSessionId,cwd:n.cwd,title:n.title,agentId:n.agentId,currentModel:n.currentModel,currentUsage:zt(n.currentUsage),importedFromMachine:n.importedFromMachine,importedFromUpstreamSessionId:n.importedFromUpstreamSessionId,parentSessionId:n.parentSessionId,forkedFromSessionId:n.forkedFromSessionId,forkedFromMessageId:n.forkedFromMessageId,forkSynthesisState:n.forkSynthesisState,originatingClient:n.originatingClient,interactive:o,priority:n.priority,updatedAt:i,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1}}async list(e={}){let t=`${e.cwd??""}|${e.includeNonInteractive?"1":"0"}|${e.status??""}`,n=Date.now(),r=this.listCache.get(t);if(r&&r.expiresAt>n)return r.promise;let o=this.listUncached(e);return this.listCache.set(t,{expiresAt:n+s.LIST_CACHE_TTL_MS,promise:o}),o.catch(()=>{let i=this.listCache.get(t);i&&i.promise===o&&this.listCache.delete(t)}),o}invalidateListCache(){this.listCache.clear()}async listUncached(e={}){let t=[],n=new Set,r=u=>e.includeNonInteractive?!0:u===!0,o=[...this.sessions.values()].filter(u=>pa(e.cwd,u));if(e.status==="cold")for(let u of o)n.add(u.sessionId);let i=e.status==="cold"?[]:await Promise.all(o.map(u=>Vt(u.sessionId)));for(let u=0;u<i.length;u+=1){let l=o[u],f=i[u];n.add(l.sessionId);let p=At({interactive:l.interactive,...l.originatingClient?{originatingClient:l.originatingClient}:{}},f.hasContent);if(!r(p))continue;let g=f.mtime??new Date(l.updatedAt).toISOString();t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,workspace:l.workspace,workspaceError:l.workspaceError,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:p,priority:l.priority,updatedAt:g,attachedClients:l.attachedCount,status:"warm",agentPid:l.agentPid,busy:l.turnStartedAt!==void 0,armedTasks:l.armedBackgroundTasks.length,...l.armedSince!==void 0?{armedSince:l.armedSince}:{},awaitingInput:l.awaitingInput,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}if(e.status==="warm")return t;let d=(await this.store.list().catch(u=>{throw this.logger?.warn(`session list: store.list() failed: ${u?.message??String(u)}`),u})).filter(u=>!n.has(u.sessionId)&&pa(e.cwd,u)),c=await Promise.all(d.map(u=>Vt(u.sessionId)));for(let u=0;u<d.length;u+=1){let l=d[u],f=c[u],p=At(l,f.hasContent);if(!r(p))continue;let g=f.mtime??l.updatedAt;t.push({sessionId:l.sessionId,upstreamSessionId:l.upstreamSessionId,cwd:l.cwd,workspace:l.workspace,title:l.title,agentId:l.agentId,currentModel:l.currentModel,currentUsage:zt(l.currentUsage),importedFromMachine:l.importedFromMachine,importedFromUpstreamSessionId:l.importedFromUpstreamSessionId,parentSessionId:l.parentSessionId,forkedFromSessionId:l.forkedFromSessionId,forkedFromMessageId:l.forkedFromMessageId,originatingClient:l.originatingClient,interactive:p,priority:l.priority,updatedAt:g,attachedClients:0,status:"cold",busy:!1,armedTasks:0,awaitingInput:!1,compactionState:l.compactionState,forkSynthesisState:l.forkSynthesisState})}return t.sort((u,l)=>u.updatedAt<l.updatedAt?1:-1),t}async exportBundle(e,t={}){let n=await this.store.read(e);if(!n)return;let r;if(n.lineageId)r=n;else{let c=Ut(),u={...n,lineageId:c};await this.enqueueMetaWrite(e,async()=>{let l=await this.store.read(e);l&&(l.lineageId||await this.store.write({...l,lineageId:c}))}).catch(()=>{}),r=u}let o=t.tools??"inline",i=await this.histories.load(e,o==="references"?{tools:"references"}:{}).catch(()=>[]),a=await ma(e);if(o!=="references")return{record:r,history:i,promptHistory:a};let d={};for(let c of ra(i)){let u=await mo(e,c);u&&(d[c]=u.toString("base64"))}return{record:r,history:i,promptHistory:a,toolBlobs:d}}async importBundle(e,t={}){let n=await this.store.findByLineageId(e.session.lineageId);if(n){if(!t.replace){let i=new Error(`bundle already imported as ${n.sessionId}`);throw i.code=x.BundleAlreadyImported,i.existingSessionId=n.sessionId,i}let o=this.sessions.get(n.sessionId);return o&&await o.close({deleteRecord:!1,by:"bundle-import-overwrite"}).catch(()=>{}),await this.writeImportedRecord({sessionId:n.sessionId,bundle:e,preservedCreatedAt:n.createdAt,cwd:t.cwd}),{sessionId:n.sessionId,importedFromSessionId:e.session.sessionId,replaced:!0}}let r=`${Me}${It()}`;return await this.writeImportedRecord({sessionId:r,bundle:e,cwd:t.cwd}),{sessionId:r,importedFromSessionId:e.session.sessionId,replaced:!1}}async forkSession(e,t={}){let n=await this.store.read(e);if(!n){let I=new Error(`source session not found: ${e}`);throw I.code=x.SessionNotFound,I}let r=t.agentId??n.agentId,o=r!==n.agentId;if(o&&!await this.registry.getAgent(r)){let b=new Error(`agent ${r} not found in registry`);throw b.code=x.AgentNotInstalled,b}let i=await this.histories.load(e).catch(()=>[]),a=i,d,c=t.mode??"synthesis",u,l,f,p=12e4;if(c==="verbatim")if(t.forkAt!==void 0){let I=bn(i,t.forkAt);if(I<0){let b=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw b.code=x.InvalidParams,b}d=t.forkAt,a=i.slice(0,I+1)}else{let I=vp(i);I?(d=I.messageId,a=i.slice(0,I.index+1)):(d="",a=i.slice(0,0))}else{if(t.forkAt!==void 0&&t.forkAt!==""){let b=bn(i,t.forkAt);if(b<0){let A=new Error(`forkAt messageId not found in source history: ${t.forkAt}`);throw A.code=x.InvalidParams,A}d=t.forkAt,a=i.slice(0,b+1)}else d="",a=i;let I=await this.registry.getAgent(r);if(!I){let b=new Error(`agent ${r} not found in registry`);throw b.code=x.AgentNotInstalled,b}f=I,l=n.currentModel,u="running"}let g=await ma(e),m=c==="synthesis",h={...n,lineageId:Ut(),agentId:r,interactive:!1,...u!==void 0?{forkSynthesisState:u}:{},summarizedThroughEntry:a.length,...t.title!==void 0?{title:t.title}:{},currentUsage:void 0,...o?{currentModel:void 0,currentMode:void 0,agentCommands:void 0,agentModes:void 0,agentModels:void 0}:{},...t.model!==void 0?{currentModel:t.model}:{}},y=qt({record:h,history:a,promptHistory:g.length>0?g:void 0,hydraVersion:ie,machine:$t()}),k=`${Me}${It()}`,w=t.cwd,S;if(t.cwd===void 0&&n.workspace!==void 0){let I=await this.deriveForkWorkspace(n.workspace,`${n.workspace.label}-fork-${k.slice(-6)}`);I!==void 0?(S=I,w=I.path):(w=n.workspace.sourceCwd,this.logger?.warn?.(`fork ${k}: could not derive an isolated workspace from ${n.workspace.path}; running unisolated in ${w}`))}return await this.writeImportedRecord({sessionId:k,bundle:y,cwd:w,...S!==void 0?{workspace:S}:{},forkedFromSessionId:e,forkedFromMessageId:d,...u!==void 0?{forkSynthesisState:u}:{}}),m&&(async()=>{try{let I=await we(f,[],{npmRegistry:this.npmRegistry}),b=await Nn({agentId:r,cwd:t.cwd??C.sessionDir(e),plan:I,history:a,modelId:l,sessionId:e,logger:this.logger,timeoutMs:p});b&&b.synopsis?await this.mutateRecord(k,{synopsis:b.synopsis},["forkSynthesisState"]):(this.logger?.warn(`forkSession(${e}): generateSynopsis returned no synopsis \u2014 fork usable via recall`),await this.mutateRecord(k,{},["forkSynthesisState"]))}catch(I){this.logger?.warn(`forkSession(${e}): generateSynopsis failed \u2014 fork usable via recall: ${I.message}`);try{await this.mutateRecord(k,{},["forkSynthesisState"])}catch(b){this.logger?.warn(`forkSession(${e}): mutateRecord to clear forkSynthesisState failed: ${b.message}`)}}})(),{sessionId:k,forkedFromSessionId:e,forkedAt:d}}async writeImportedRecord(e){if(await this.histories.rewrite(e.sessionId,e.bundle.history),e.bundle.toolBlobs)for(let[o,i]of Object.entries(e.bundle.toolBlobs))await ho(e.sessionId,o,Buffer.from(i,"base64")).catch(()=>{});let t=new Date(e.bundle.session.updatedAt);Number.isNaN(t.getTime())||await Xe.utimes(C.historyFile(e.sessionId),t,t).catch(()=>{}),e.bundle.promptHistory&&e.bundle.promptHistory.length>0&&await ca(C.tuiHistoryFile(e.sessionId),e.bundle.promptHistory).catch(()=>{});let n=new Date().toISOString(),r=e.forkedFromSessionId!==void 0;await this.enqueueMetaWrite(e.sessionId,async()=>{await this.store.write({sessionId:e.sessionId,lineageId:e.bundle.session.lineageId,upstreamSessionId:"",...r?{forkedFromSessionId:e.forkedFromSessionId,forkedFromMessageId:e.forkedFromMessageId}:{importedFromSessionId:e.bundle.session.sessionId,importedFromUpstreamSessionId:e.bundle.session.upstreamSessionId,importedFromMachine:e.bundle.exportedFrom.machine},agentId:e.bundle.session.agentId,cwd:e.cwd??e.bundle.session.cwd,workspace:e.workspace,title:e.bundle.session.title,synopsis:e.bundle.session.synopsis,summarizedThroughEntry:e.bundle.session.summarizedThroughEntry,...e.forkSynthesisState!==void 0?{forkSynthesisState:e.forkSynthesisState}:{},currentModel:e.bundle.session.currentModel,currentMode:e.bundle.session.currentMode,currentUsage:e.bundle.session.currentUsage,agentCommands:e.bundle.session.agentCommands,agentModes:e.bundle.session.agentModes,interactive:e.bundle.session.interactive,originatingClient:e.bundle.session.originatingClient,priority:e.bundle.session.priority,attentionFlags:[],createdAt:e.preservedCreatedAt??n,updatedAt:e.bundle.session.updatedAt})})}async tombstoneAllGenerations(e,t,n){let r=await this.store.read(e).catch(()=>{}),o=new Map;for(let a of r?.upstreamGenerations??[])a.upstreamSessionId&&o.set(`${a.agentId}::${a.upstreamSessionId}`,{agentId:a.agentId,upstreamSessionId:a.upstreamSessionId});o.set(`${t.agentId}::${t.upstreamSessionId}`,{agentId:t.agentId,upstreamSessionId:t.upstreamSessionId});let i=new Date().toISOString();for(let a of o.values())await this.tombstones.add({agentId:a.agentId,upstreamSessionId:a.upstreamSessionId,deletedAt:i,upstreamUpdatedAt:t.upstreamUpdatedAt,cwd:t.cwd,...t.title!==void 0?{title:t.title}:{},reason:n,...t.interactive!==void 0?{interactive:t.interactive}:{}}).catch(()=>{})}async deleteRecord(e,t="user"){let n=await this.store.read(e);if(!n)return!1;if(n.upstreamSessionId){let r=await Vt(e),o=At(n,r.hasContent);await this.tombstoneAllGenerations(e,{agentId:n.agentId,upstreamSessionId:n.upstreamSessionId,upstreamUpdatedAt:n.updatedAt,cwd:n.cwd,...n.title!==void 0?{title:n.title}:{},...o!==void 0?{interactive:o}:{}},t)}return n.workspace!==void 0&&await this.releaseWorkspace(n.workspace,e).catch(()=>{}),await this.store.delete(e).catch(()=>{}),await this.histories.delete(e).catch(()=>{}),this.invalidateListCache(),!0}async waitForDeletion(e){let t=this.pendingDeletions.get(e);t&&await t}async isTombstoned(e,t){return(await this.tombstones.read(e,t).catch(()=>{}))?.reason==="user"}async hasRecord(e){return await this.store.read(e).catch(()=>{})!==void 0}async clearWorkspaceBinding(e){if(this.get(e)!==void 0)return"live";let t=await this.store.read(e).catch(()=>{});if(!t)return"missing";let n=t.workspace?.sourceCwd;return await this.mutateRecord(e,n!==void 0?{cwd:n}:{},["workspace"]),"cleared"}async setCwd(e,t){if(this.get(e)!==void 0)return"live";let n=await this.store.read(e).catch(()=>{});return n?n.workspace!==void 0?"bound":await this.dirExists(t)?(await this.mutateRecord(e,{cwd:t}),this.invalidateListCache(),"set"):"not-a-directory":"missing"}async setPriority(e,t){let n=this.get(e);if(n)return n.setPriority(t),!0;if(!await this.hasRecord(e))return!1;let r=t===void 0||t<=0?void 0:Math.floor(t);return await this.persistPriority(e,r),!0}async persistPriority(e,t){t===void 0?await this.mutateRecord(e,{},["priority"]):await this.mutateRecord(e,{priority:t}),this.invalidateListCache()}async setTitle(e,t){let n=this.get(e);return n?(await n.retitle(t),!0):await this.hasRecord(e)?(await this.persistTitle(e,t),!0):!1}async persistTitle(e,t){await this.mutateRecord(e,{title:t})}async persistSynopsis(e,t,n){await this.mutateRecord(e,{synopsis:t,summarizedThroughEntry:n})}async persistAgentChange(e,t,n,r,o,i){await this.mutateRecord(e,{agentId:t,upstreamSessionId:n},void 0,a=>({upstreamGenerations:wa(a,t,n,void 0,r,o,i)}))}async persistSnapshot(e,t){let n={};t.currentModel!==void 0&&(n.currentModel=t.currentModel),t.currentMode!==void 0&&(n.currentMode=t.currentMode),t.currentUsage!==void 0&&(n.currentUsage=t.currentUsage),t.agentCommands!==void 0&&(n.agentCommands=t.agentCommands),t.agentModes!==void 0&&(n.agentModes=t.agentModes),t.agentModels!==void 0&&(n.agentModels=t.agentModels),t.interactive!==void 0&&(n.interactive=t.interactive),t.cwd!==void 0&&(n.cwd=t.cwd),await this.mutateRecord(e,n)}async mutateRecord(e,t,n=[],r){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o,...t,...r?r(o):{},updatedAt:new Date().toISOString()};for(let a of n)delete i[a];await this.store.write(i)})}static EXTENSION_STATE_CAP_BYTES=64*1024;async getExtensionState(e,t){return(await this.store.read(e))?.extensionState?.[t]??{}}async getExtensionStateKey(e,t,n){return(await this.getExtensionState(e,t))[n]}async setExtensionStateKey(e,t,n,r){await this.enqueueMetaWrite(e,async()=>{let o=await this.store.read(e);if(!o)return;let i={...o.extensionState??{}},a={...i[t]??{},[n]:r},d=Buffer.byteLength(JSON.stringify(a),"utf8");if(d>s.EXTENSION_STATE_CAP_BYTES)throw new Error(`extension_state: bucket for ${t} would be ${d} bytes; cap is ${s.EXTENSION_STATE_CAP_BYTES}`);i[t]=a;let c={...o,extensionState:i,updatedAt:new Date().toISOString()};await this.store.write(c)})}async deleteExtensionStateKey(e,t,n){await this.enqueueMetaWrite(e,async()=>{let r=await this.store.read(e);if(!r?.extensionState?.[t])return;let o={...r.extensionState},i={...o[t]};if(!(n in i))return;delete i[n],Object.keys(i).length===0?delete o[t]:o[t]=i;let a={...r,extensionState:o,updatedAt:new Date().toISOString()};await this.store.write(a)})}enqueueMetaWrite(e,t){return this.enqueueKeyed(this.metaWriteQueues,e,t)}enqueueKeyed(e,t,n){let o=(e.get(t)??Promise.resolve()).catch(()=>{}).then(n),i=o.catch(()=>{});return e.set(t,i),i.finally(()=>{e.get(t)===i&&e.delete(t)}),o}liveSessionsIn(e,t){let n=[];for(let r of this.sessions.values())r.sessionId!==t&&r.workspace?.path===e&&n.push(r);return n}async closeAll(){let e=[...this.sessions.values()];await Promise.allSettled(e.map(t=>t.close({deleteRecord:!1,by:"daemon-shutdown"}))),this.sessions.clear()}async flushSynopsis(e){await this.synopsisCoordinator.flush(e)}async shutdownSynopsis(){await this.synopsisCoordinator.shutdown()}scheduleSynopsis(e){this.synopsisCoordinator.schedule(e)}scheduleCompaction(e,t){if(t?.targetAgentId){this.mutateRecord(e,{pendingAgentSwap:t.targetAgentId}).catch(r=>{this.logger?.warn(`scheduleCompaction: failed to stamp pendingAgentSwap for ${e}: ${r instanceof Error?r.message:String(r)}`)});let n=t.targetAgentId;(async()=>{try{let r=await this.store.read(e);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=${n} (reusing artifact @${r.summarizedThroughEntry})`),await this.dispatchSynthesisSwap(e,r.synopsis,r.summarizedThroughEntry,n)}catch(r){this.logger?.warn(`scheduleCompaction: fast-path check failed for ${e}: ${r instanceof Error?r.message:String(r)} \u2014 falling back to synthesis`),this.synopsisCoordinator.scheduleCompaction(e,t)}})();return}this.synopsisCoordinator.scheduleCompaction(e,t)}getCompactionInFlight(){let e=this.synopsisCoordinator.size();return e.inflight>0||e.queued>0}async getPendingAgentSwap(e){return(await this.store.read(e).catch(()=>{}))?.pendingAgentSwap}async getCompactionState(e){return(await this.store.read(e).catch(()=>{}))?.compactionState}async persistRollbackBreadcrumb(e,t){await this.mutateRecord(e,{},void 0,n=>{let r=n.rollbackBreadcrumb;return r!==void 0&&t.runId!==void 0&&r.runId===t.runId?(this.logger?.info(`compaction: keeping rollback breadcrumb pinned at ${r.previousUpstreamSessionId} for runId=${t.runId} sessionId=${e} (later swap of the same run)`),{}):{rollbackBreadcrumb:t}})}async getUpstreamGenerations(e){return(await this.store.read(e).catch(()=>{}))?.upstreamGenerations??[]}async getRollbackBreadcrumb(e){return(await this.store.read(e).catch(()=>{}))?.rollbackBreadcrumb}emitSwapPhase(e,t,n){let r=this.get(e);if(r){if(t){let o=n.phase==="failed";r.broadcastPendingAgentSwap(o?null:t);return}r.broadcastCompactionPhase(n)}}async getSummarizedThroughEntry(e){let t=this.sessions.get(e);return t?t.summarizedThroughEntry:(await this.store.read(e).catch(()=>{}))?.summarizedThroughEntry}async flushMetaWrites(){let e=[...this.metaWriteQueues.values()];e.length!==0&&await Promise.allSettled(e)}async flushHistoryWrites(){await this.histories.flushAll()}async reconcilePermissionFlags(){let e=await this.store.list().catch(()=>[]),t=0;for(let n of e){let r=n.attentionFlags??[],o=r.filter(i=>!(i.source==="daemon"&&i.reason.startsWith("permission:")));if(o.length!==r.length){let i=r.length-o.length;t+=i,await this.mutateRecord(n.sessionId,{attentionFlags:o}).catch(()=>{})}}t>0&&this.logger?.info(`cleared ${t} stale permission attention flags on startup`)}async resumePendingCompactions(){let e=new Set(["requested","running","swap_pending","swap_deferred"]),t=await this.store.list().catch(()=>[]);for(let n of t){let r=n.compactionState;if(r!=null){if(!e.has(r.status)){this.logger?.info(`compaction: not resuming sessionId=${n.sessionId} status=${r.status} (terminal \u2014 user must re-trigger explicitly)`);continue}this.logger?.info(`compaction: resuming sessionId=${n.sessionId} status=${r.status} from prior daemon`);try{this.scheduleCompaction(n.sessionId)}catch(o){this.logger?.warn(`compaction: resume failed for sessionId=${n.sessionId}: ${o instanceof Error?o.message:String(o)}`)}}}}async resumePendingAgentSwaps(){let e=await this.store.list().catch(()=>[]);for(let t of e){let n=t.pendingAgentSwap;if(n)try{let r=await this.histories.load(t.sessionId).catch(()=>[]);t.synopsis!==void 0&&t.summarizedThroughEntry!==void 0&&t.summarizedThroughEntry>=r.length&&t.synopsis?(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${n} with persisted synopsis (history=${r.length})`),await this.dispatchSynthesisSwap(t.sessionId,t.synopsis,t.summarizedThroughEntry??r.length,n)):(this.logger?.info(`agent-swap: resuming sessionId=${t.sessionId} target=${n} via fresh synthesis (history=${r.length} watermark=${t.summarizedThroughEntry??"(none)"})`),this.scheduleCompaction(t.sessionId,{targetAgentId:n}))}catch(r){this.logger?.warn(`agent-swap: resume failed for sessionId=${t.sessionId}: ${r instanceof Error?r.message:String(r)}`)}}}async resurrectPendingQueues(){let e=await this.store.list().catch(()=>[]);for(let t of e){let n=await gi(t.sessionId).catch(()=>[]);if(n.length===0)continue;let r=Date.now(),o=n.filter(d=>r-d.enqueuedAt<la),i=n.length-o.length;if(i>0&&(this.logger?.info(`queue replay: dropping ${i} stale prompt(s) for ${t.sessionId} (TTL ${la/1e3}s)`),await Ot(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 Ot(t.sessionId,[]).catch(()=>{});continue}try{let d=await this.resurrect(a);this.logger?.info(`queue replay: resurrected ${t.sessionId} and replaying ${o.length} prompt(s)`),d.replayPersistedQueue(o)}catch(d){this.logger?.warn(`queue replay: failed to resurrect ${t.sessionId}: ${d.message}`)}}}};function yp(s,e){if(typeof s!="string"||s.length===0)return!1;let t=Gt.resolve(s),n=Gt.resolve(e);return t===n||t.startsWith(n+Gt.sep)}function pa(s,e){if(s===void 0||s.length===0)return!0;let t=Sr(s);if(Sr(e.cwd)===t)return!0;let n=e.workspace?.sourceCwd;return n!==void 0&&Sr(n)===t}function Sr(s){return s.length>1&&s.endsWith("/")?s.replace(/\/+$/,""):s}function wp(s,e){let n=(s.mergedAvailableCommands().length>0?s.agentOnlyAdvertisedCommands().map(u=>u.description!==void 0?{name:u.name,description:u.description}:{name:u.name}):void 0)??e?.agentCommands,r=s.availableModes(),i=(r.length>0?r.map(u=>{let l={id:u.id};return u.name!==void 0&&(l.name=u.name),u.description!==void 0&&(l.description=u.description),l}):void 0)??e?.agentModes,a=s.availableModels(),c=(a.length>0?a.map(u=>{let l={modelId:u.modelId};return u.name!==void 0&&(l.name=u.name),u.description!==void 0&&(l.description=u.description),l}):void 0)??e?.agentModels;return ir({sessionId:s.sessionId,lineageId:e?.lineageId??Ut(),upstreamSessionId:s.upstreamSessionId,importedFromSessionId:e?.importedFromSessionId,importedFromUpstreamSessionId:e?.importedFromUpstreamSessionId,importedFromMachine:e?.importedFromMachine,agentId:s.agentId,cwd:s.cwd,title:s.title,synopsis:e?.synopsis,summarizedThroughEntry:e?.summarizedThroughEntry,agentArgs:s.agentArgs,currentModel:s.currentModel??e?.currentModel,currentMode:s.currentMode??e?.currentMode,currentUsage:ya(s.persistableUsage)??e?.currentUsage,agentCommands:n,agentModes:i,agentModels:c,parentSessionId:s.parentSessionId??e?.parentSessionId,forkedFromSessionId:s.forkedFromSessionId??e?.forkedFromSessionId,forkedFromMessageId:s.forkedFromMessageId??e?.forkedFromMessageId,originatingClient:s.originatingClient??e?.originatingClient,interactive:s.interactive??e?.interactive,priority:s.priority??e?.priority,forwardedEnv:s.forwardedEnv??e?.forwardedEnv,workspace:s.workspace,attentionFlags:s.listAttentionFlags(),extensionState:e?.extensionState,upstreamGenerations:e?wa(e,s.agentId,s.upstreamSessionId):void 0,createdAt:e?.createdAt??new Date(s.createdAt).toISOString()})}function ya(s){if(!s)return;let e={};return s.used!==void 0&&(e.used=s.used),s.size!==void 0&&(e.size=s.size),s.costAmount!==void 0&&(e.costAmount=s.costAmount),s.costCurrency!==void 0&&(e.costCurrency=s.costCurrency),s.cumulativeCost!==void 0&&(e.cumulativeCost=s.cumulativeCost),Object.keys(e).length>0?e:void 0}function kp(s){return s?{...s}:void 0}function Ir(s,e={}){if(s!=="claude-acp")return;let t={extraArgs:{"thinking-display":"summarized"}};return e.model&&(t.model=e.model),{claudeCode:{options:t}}}function Dn(s,e){let t=e.fromObject(s);if(t!==void 0)return t;let n=s[e.nestedKey];if(n&&typeof n=="object"&&!Array.isArray(n)){let i=e.fromObject(n);if(i!==void 0)return i}let r=s._meta;if(r&&typeof r=="object"&&!Array.isArray(r)){for(let[i,a]of Object.entries(r))if(i!=="hydra-acp"&&a&&typeof a=="object"&&!Array.isArray(a)){let d=e.fromObject(a);if(d!==void 0)return d}}let o=bp(s,e.configId);if(o){let i=e.fromConfig(o);if(i!==void 0)return i}}function Ar(s){return Dn(s,{nestedKey:"models",configId:"model",fromObject:e=>$e(e.currentModelId)??$e(e.currentModel)??$e(e.modelId)??$e(e.model),fromConfig:e=>$e(e.currentValue)})}function Ve(s,e){if(!s||typeof s!="object")return s;let t=s;if(t.code!==x.AuthRequired)return s;let n=c=>!!c&&typeof c=="object"&&!Array.isArray(c),r=n(t.data)?t.data:{},o=n(r._meta)?r._meta:{},i=n(o["hydra-acp"])?o["hydra-acp"]:{},a=typeof t.message=="string"?t.message:"authentication required",d=new Error(a);return d.code=x.AuthRequired,d.data={...r,_meta:{...o,"hydra-acp":{...i,authMethods:e.authMethods??[],agentId:e.agentId}}},d}function fa(s){return/^[A-Za-z0-9_\-./=:@]+$/.test(s)?s:`'${s.replace(/'/g,"'\\''")}'`}function ga(s,e,t,n){if(s&&typeof s=="object"&&s.code===x.AuthRequired)return s;let r=s instanceof Error?s.message:String(s),o=r.includes("stderr:"),i=o?"":e.stderrTailText(),a=n?`to reproduce: (cd ${fa(n.cwd)} && ${[n.command,...n.args].map(fa).join(" ")})`:"";if(!i&&!a)return s;let d=[o?r:`agent ${t} failed to start: ${r}`];i&&d.push(`stderr: ${i}`),a&&d.push(a);let c=new Error(d.join(`
|
|
169
169
|
`));if(s&&typeof s=="object"){let u=s;typeof u.code=="number"&&(c.code=u.code),u.data!==void 0&&(c.data=u.data)}return c}function Jt(s){if(!Array.isArray(s))return;let e=[];for(let t of s){if(!t||typeof t!="object")continue;let n=t;if(typeof n.id!="string")continue;let r=typeof n.description=="string"?n.description:"",o=n.type==="agent"||n.type==="terminal"?n.type:void 0,i=typeof n.name=="string"?n.name:void 0,a=n._meta,d=a!==null&&typeof a=="object"&&!Array.isArray(a)?a:void 0;e.push({id:n.id,description:r,...o&&{type:o},...i!==void 0&&{name:i},...d&&{_meta:d}})}return e.length>0?e:void 0}function $e(s){if(typeof s!="string")return;let e=s.trim();return e.length>0?e:void 0}function bp(s,e){let t=s.configOptions;if(Array.isArray(t))for(let n of t){if(!n||typeof n!="object"||Array.isArray(n))continue;let r=n;if(r.id===e)return r}}function Cr(s){return s.length>0?s:void 0}function xr(s){return Dn(s,{nestedKey:"models",configId:"model",fromObject:e=>{let t=yt(e.availableModels);return t.length>0?t:void 0},fromConfig:e=>{let t=yt(e.options);return t.length>0?t:void 0}})??[]}function Rr(s){return Dn(s,{nestedKey:"modes",configId:"mode",fromObject:e=>{let t=Ht(e.availableModes);return t.length>0?t:void 0},fromConfig:e=>{let t=Ht(e.options);return t.length>0?t:void 0}})??[]}function Er(s){return Dn(s,{nestedKey:"modes",configId:"mode",fromObject:e=>$e(e.currentModeId)??$e(e.currentMode)??$e(e.modeId)??$e(e.mode),fromConfig:e=>$e(e.currentValue)})}function vp(s){for(let e=s.length-1;e>=0;e--){let t=s[e];if(!t||t.method!=="session/update")continue;let n=t.params?.update;if(n?.sessionUpdate==="turn_complete"&&!(typeof n.messageId!="string"||n.messageId.length===0))return{index:e,messageId:n.messageId}}}async function ma(s){try{let e=await Xe.readFile(C.tuiHistoryFile(s),"utf8"),t=[];for(let n of e.split(`
|
|
170
170
|
`))if(n.length!==0)try{let r=JSON.parse(n);typeof r=="string"&&t.push(r)}catch{}return t}catch{return[]}}function wa(s,e,t,n=new Date().toISOString(),r,o,i){let a=s.upstreamGenerations&&s.upstreamGenerations.length>0?[...s.upstreamGenerations]:s.upstreamSessionId?[{upstreamSessionId:s.upstreamSessionId,agentId:s.agentId}]:[],d=a[a.length-1];if(d&&d.upstreamSessionId===t){if(r!==void 0&&a.length>=2){let c=a[a.length-2];c&&c.cost===void 0&&(a[a.length-2]={...c,cost:r})}return o!==void 0&&d.reason===void 0&&(a[a.length-1]={...d,reason:o,...i!==void 0?{runId:i}:{}}),a}return d&&d.endedAt===void 0&&(a[a.length-1]={...d,endedAt:n,...r!==void 0?{cost:r}:{}}),a.push({upstreamSessionId:t,agentId:e,startedAt:n,...o!==void 0?{reason:o}:{},...i!==void 0?{runId:i}:{}}),a}async function Vt(s){try{let e=await Xe.stat(C.historyFile(s));return{mtime:new Date(e.mtimeMs).toISOString(),hasContent:e.size>0}}catch{return{hasContent:!1}}}function At(s,e){return s.interactive!==void 0?s.interactive:s.originatingClient?.name===Fn?!1:e?!0:void 0}import{spawn as Sp}from"child_process";import*as Ln from"fs";import*as De from"fs/promises";import*as Wn from"path";import Ip from"pino-roll";var Bn=class{windowMs;maxFailures;now;recentExits=[];tripped_;constructor(e={}){this.windowMs=e.windowMs??3e5,this.maxFailures=e.maxFailuresInWindow??10,this.now=e.now??Date.now}recordExit(e,t,n){if(e===78){let i=`exited with code 78 (unrecoverable); fix and run \`${n}s start ${t}\``;return this.tripped_=i,{tripped:i}}let r=this.now();this.recentExits.push(r);let o=r-this.windowMs;for(;this.recentExits.length>0&&this.recentExits[0]<o;)this.recentExits.shift();if(this.recentExits.length>this.maxFailures){let i=Math.round(this.windowMs/6e4),a=`${this.recentExits.length} exits in ${i}m (crash loop); fix and run \`${n}s start ${t}\``;return this.tripped_=a,{tripped:a}}return"restart"}reset(){this.recentExits=[],this.tripped_=void 0}get tripped(){return this.tripped_}};var Ap=1e3,Cp=6e4,Pr=3e3,Ct=class{entries=new Map;stopping=!1;context;tokenRegistry;breakerOptions;restartBaseMs;restartCapMs;adapter;constructor(e,t,n,r={}){this.adapter=t,this.context=n,this.tokenRegistry=r.tokenRegistry,this.breakerOptions=r.breakerOptions,this.restartBaseMs=r.restartBaseMs??Ap,this.restartCapMs=r.restartCapMs??Cp;for(let o of e)this.entries.set(o.name,this.makeEntry(o))}setContext(e){this.context=e}reportVersion(e,t){let n=this.entries.get(e);n&&(n.version=t)}async start(){if(!this.context)throw new Error(`${this.managerName()}: setContext must be called before start`);await De.mkdir(this.adapter.paths.dir(),{recursive:!0}),await this.reapOrphans();let e=[];for(let t of this.entries.values())t.config.enabled&&e.push(this.spawn(t,0));await Promise.all(e)}async stop(){this.stopping=!0;let e=[];for(let t of this.entries.values()){t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let n=t.child;if(n){try{n.kill("SIGTERM")}catch{}e.push(new Promise(r=>{if(n.exitCode!==null||n.signalCode!==null){r();return}let o=setTimeout(()=>{try{n.kill("SIGKILL")}catch{}r()},Pr);n.on("exit",()=>{clearTimeout(o),r()})}))}}await Promise.allSettled(e);for(let t of this.entries.values()){try{t.logStream?.end()}catch{}t.child=void 0,t.logStream=void 0,t.pid=void 0}}list(){return[...this.entries.values()].map(e=>this.infoFor(e))}get(e){let t=this.entries.get(e);return t?this.infoFor(t):void 0}has(e){return this.entries.has(e)}async startByName(e){let t=this.entries.get(e);if(!t)throw Qt(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");if(t.child)throw Qt(new Error(`${this.adapter.kind} ${e} already running`),"CONFLICT");return t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0),t.manuallyStopped=!1,t.restartCount=0,t.breaker.reset(),t.failureReason=void 0,await this.spawn(t,0),this.infoFor(t)}async stopByName(e){let t=this.entries.get(e);if(!t)throw Qt(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");t.manuallyStopped=!0,t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let n=t.child;return n?(await this.terminate(t,n),this.infoFor(t)):this.infoFor(t)}async restartByName(e){return await this.stopByName(e),this.startByName(e)}register(e){if(this.entries.has(e.name))throw Qt(new Error(`${this.adapter.kind} ${e.name} already exists`),"CONFLICT");if(!this.context)throw new Error(`${this.managerName()}: setContext must be called before register`);let t=this.makeEntry(e);return this.entries.set(e.name,t),e.enabled&&this.spawn(t,0).catch(n=>{t.failureReason=`spawn: ${n.message}`}),this.infoFor(t)}async unregister(e){let t=this.entries.get(e);if(!t)throw Qt(new Error(`unknown ${this.adapter.kind}: ${e}`),"NOT_FOUND");t.manuallyStopped=!0,t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);let n=t.child;n&&await this.terminate(t,n);try{t.logStream?.end()}catch{}this.entries.delete(e)}async terminate(e,t){if(t.exitCode!==null||t.signalCode!==null)return;let n=new Promise(o=>{e.exitWaiters.push(o)});try{t.kill("SIGTERM")}catch{}let r=setTimeout(()=>{try{t.kill("SIGKILL")}catch{}},Pr);typeof r.unref=="function"&&r.unref();try{await n}finally{clearTimeout(r)}}infoFor(e){let t;return e.failureReason!==void 0?t="failed":e.child?t="running":e.restartTimer?t="restarting":e.config.enabled?t="stopped":t="disabled",{name:e.config.name,status:t,pid:e.pid,enabled:e.config.enabled,restartCount:e.restartCount,startedAt:e.startedAt,lastExitCode:e.lastExitCode,logPath:this.adapter.paths.logFile(e.config.name),version:e.version,failureReason:e.failureReason}}makeEntry(e){return{config:e,child:void 0,logStream:void 0,restartTimer:void 0,pid:void 0,startedAt:void 0,restartCount:0,lastExitCode:void 0,manuallyStopped:!1,exitWaiters:[],version:void 0,processToken:void 0,breaker:new Bn(this.breakerOptions),failureReason:void 0}}async reapOrphans(){let e;try{e=await De.readdir(this.adapter.paths.dir(),{withFileTypes:!0})}catch(t){if(t.code==="ENOENT")return;throw t}for(let t of e){if(!t.isDirectory())continue;let n=this.adapter.paths.pidFile(t.name),r;try{let o=await De.readFile(n,"utf8"),i=Number.parseInt(o.trim(),10);Number.isInteger(i)&&i>0&&(r=i)}catch{}if(typeof r=="number"&&Mr(r)){try{process.kill(r,"SIGTERM")}catch{}let o=Date.now()+Pr;for(;Date.now()<o&&Mr(r);)await new Promise(i=>setTimeout(i,50));if(Mr(r))try{process.kill(r,"SIGKILL")}catch{}}await De.unlink(n).catch(()=>{})}}async spawn(e,t){if(this.stopping||e.manuallyStopped)return;let n=this.context;if(!n)throw new Error(`${this.managerName()}.spawn called before setContext`);let r=e.config,o=r.command.length>0?r.command:[r.name],i=Wn.dirname(this.adapter.paths.logFile(r.name)),a;try{await De.mkdir(i,{recursive:!0}),a=await Ip({file:Wn.join(i,`${r.name}.log`),size:"5m",mkdir:!0,symlink:!0,limit:{count:5}}),a.on("error",h=>{e.failureReason=`log stream: ${h.message}`})}catch(h){if(this.stopping||e.manuallyStopped)return;e.failureReason=`log setup: ${h.message}`,this.scheduleRestart(e,t+1);return}if(this.stopping||e.manuallyStopped){try{a.end()}catch{}return}a.write(`[hydra-acp] ${new Date().toISOString()} starting ${this.adapter.kind} ${r.name} (attempt ${t+1})
|
|
171
171
|
`);let d=this.tokenRegistry?.mint(r.name,this.adapter.tokenRole)??n.serviceToken;e.processToken=d,e.version=void 0;let c={...dn(),HYDRA_ACP_DAEMON_URL:n.daemonUrl,HYDRA_ACP_DAEMON_HOST:n.daemonHost,HYDRA_ACP_DAEMON_PORT:String(n.daemonPort),HYDRA_ACP_TOKEN:d,HYDRA_ACP_WS_URL:n.daemonWsUrl,HYDRA_ACP_HOME:n.hydraHome,[this.adapter.nameEnvVar]:r.name,...r.env},[u,...l]=o;if(u===void 0){a.write(`[hydra-acp] ${this.adapter.kind} ${r.name} has empty command
|