@x-otto/runtime 0.0.1-alpha.1 → 0.0.1-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{CostTracker as e,computeCacheHitRatio as t,createEventStream as n,createProviderRegistry as r,createStreamFunction as i}from"@x-otto/ai";import{createHookRegistry as a,defineHook as o,provisionBaselineSecurity as s}from"@x-otto/hooks";import{EventBus as c,TypedEventEmitter as l,buildAllowedEnv as u,createLogger as d}from"@x-otto/shared";import{dirname as f,join as p,resolve as m,sep as h}from"node:path";import{DiskPanelStatePersistence as g,DiskPasteStatePersistence as _,FileAppendLog as v,HttpAppendLog as y,MemoryAppendLog as b,createInMemoryPanelStatePersistence as x,createInMemoryPasteStatePersistence as S,normalizePasteSnapshot as ee}from"@x-otto/persistence";import{collectEnvironment as te,formatEnvironmentBlock as ne}from"@x-otto/prompt";import{FileSessionPersistence as re,InMemorySession as C,InMemorySessionPersistence as ie,RemoteSessionPersistence as ae,RemoteSnapshotConflictError as oe,SESSION_IDLE_TIMEOUT_MS as se,SESSION_MAX as ce,SESSION_SNAPSHOT_VERSION as w,hasStrippedReplacements as le,supportsReplacementHydration as ue}from"@x-otto/session";import{SDK_VERSION as de,isShadowModeEnabled as fe,listOttoProcesses as pe}from"@x-otto/env";import{ENGINE_DEFAULTS as me,applyMemoryTransform as he,createAgent as ge,createRecordingPorts as _e,createReplayPorts as ve,createTraceRecorder as ye,extractNondetDraws as be,extractToolResultText as xe,forceMemoryTransform as Se,prompt as Ce,stripAnsi as we,systemClock as Te,systemId as Ee,systemRandom as De}from"@x-otto/agent";import{mkdir as T,readFile as Oe,readdir as E,rm as D,stat as ke,unlink as Ae,writeFile as O}from"node:fs/promises";import{SESSION_COMPACTION_TIMEOUT_MS as je,SESSION_MAX_HISTORY_MESSAGES as Me,SESSION_MAX_PER_SESSION_BYTES as Ne,SESSION_MIN_PER_SESSION_BYTES as Pe,SESSION_TOTAL_RESIDENCY_BUDGET as Fe,resolveResidencyBudget as k}from"@x-otto/session-contract";import{randomUUID as A}from"node:crypto";import{getHeapStatistics as Ie}from"node:v8";import{execFileSync as j,spawn as Le,spawnSync as Re}from"node:child_process";import{EventEmitter as ze}from"node:events";import{mkdtempSync as Be,realpathSync as Ve}from"node:fs";import{tmpdir as He}from"node:os";function Ue(e,t){let n=t=>e.ephemeral?new b:e.sessionDir?new v({baseDir:p(e.sessionDir,t)}):e.remoteLog?new y(e.remoteLog):new b;return{traceStore:t?.traceStore??n(`trace`),checkpointStore:t?.checkpointStore??n(`checkpoint`)}}function We(e){let t=new Map;return[o({name:e.name,timing:`system.prompt.transform`,priority:e.priority,handle:async(n,r)=>{let i=t.get(n.sessionId);i===void 0&&(i=await e.compute(n)??``,t.set(n.sessionId,i)),i&&(r.systemPrompt=`${r.systemPrompt}\n\n${i}`)}}),o({name:`${e.name}-cleanup`,timing:`session.deleted`,priority:90,handle:e=>{t.delete(e.sessionId)}})]}var Ge=class{sources=new Map;sealed=!1;register(e){if(this.sealed)throw Error(`ContextSourceRegistry: cannot register "${e.id}" — registry is sealed (hooks already built).`);this.sources.set(e.id,e)}list(){return[...this.sources.values()].sort((e,t)=>(e.priority??50)-(t.priority??50))}sealAndBuildHooks(e,t){this.sealed=!0;let n=[];for(let r of this.list())n.push(...We({name:`ctxsrc:${r.id}`,priority:r.priority??50,compute:async n=>r.contribute({sessionId:n.sessionId,workspaceDir:e,memory:t})}));return n}};const M={toolGuidance:{name:`tool-guidance-injection`,priority:20,lane:`stable`},skillLoopGuidance:{name:`skill-loop-guidance-injection`,priority:21,lane:`stable`},environment:{name:`runtime:environment`,priority:25,lane:`stable`},memoryIndex:{name:`runtime:memory-index`,priority:35,lane:`stable`},skillCatalog:{name:`skill-catalog-injection`,priority:38,lane:`stable`},lesson:{name:`lesson-injection`,priority:40,lane:`stable`},memoryDelta:{name:`memory-delta-injection`,priority:60,lane:`volatile`},todoReminder:{name:`todo-reminder-injection`,priority:62,lane:`volatile`},docSyncReminder:{name:`doc-sync-reminder-injection`,priority:64,lane:`volatile`}};Object.values(M);function Ke(e){return{id:`runtime:environment`,priority:M.environment.priority,async contribute(t){let n=async(e,t)=>{let{execSync:n}=await import(`node:child_process`);return n(e,{cwd:t,encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]})};try{return ne(await te(e,n))}catch{return}}}}function qe(e,t){let n=!1;return{id:`runtime:memory-index`,priority:M.memoryIndex.priority,async contribute(e){if(!t)return;n||=(await t.loadMemory(),!0);let r=t.getMemoryPrompt();return r.trim()?r:void 0}}}const Je=d(`@x-otto/runtime/hooks`);function Ye(e){let{hookRegistry:t,agentName:n,sessionId:r}=e;return{async executeBeforeHooks(e){let i={args:{...e.args},cancelled:!1};return await t.execute(`tool.execute.before`,{...e,agentName:n,sessionId:r},i),i.cancelled||i.decision===`deny`?{kind:`deny`,reason:i.cancelReason??i.decisionReason??`Tool ${e.toolName} was blocked by pre-execution hook`}:i.decision===`ask`?{kind:`ask`,args:i.args,reason:i.decisionReason??`Requires confirmation`,risk:i.risk}:i.decision===`allow`||i.decision===void 0?{kind:`proceed`,args:i.args}:(Je.warn({toolName:e.toolName,decision:i.decision},`tool.execute.before hook returned unrecognized decision — denying as safety fallback`),{kind:`deny`,reason:`Tool ${e.toolName} was blocked: hook returned unrecognized decision "${String(i.decision)}"`})},async executeAfterHooks(e){let i={result:e.result,metadata:{}};return await t.execute(`tool.execute.after`,{...e,agentName:n,sessionId:r},i),i}}}function N(e){for(let t of e){if(t.role!==`user`)continue;let{content:e}=t,n;if(typeof e==`string`?n=e:Array.isArray(e)&&(n=e.filter(e=>e.type===`text`&&typeof e.text==`string`).map(e=>e.text).join(` `)),!n)continue;let r=n.replace(/\s+/g,` `).trim();if(r)return r.length>80?r.slice(0,80):r}}function Xe(e,t,n){return e?.trim()||(N(t)??n.slice(0,8))}function Ze(e){return typeof e==`string`?e:Array.isArray(e)?e.filter(e=>{let t=e;return t.type===`text`&&typeof t.text==`string`}).map(e=>e.text).join(``):``}function Qe(e){let t=e.trim();if(!t)return null;let n=t.match(/\{[^{}]*"title"\s*:\s*"([^"]+)"[^{}]*\}/);if(!n&&/"title/.test(t))return null;let r=(n?.[1]??t).replace(/\s+/g,` `).trim();return r?r.length>80?r.slice(0,80):r:null}async function $e(e,t,n){let r=t.trim().slice(-2e3);if(!r)return null;let i=new AbortController,a=()=>i.abort();if(n.aborted)return null;n.addEventListener(`abort`,a,{once:!0});let o=setTimeout(()=>i.abort(),e.timeoutMs??15e3);try{let t=[{role:`user`,timestamp:Date.now(),content:[{type:`text`,text:r}]}];return Qe(Ze((await e.stream({model:e.model,systemPrompt:`Generate a concise, sentence-case title (3-7 words) that captures the main topic or goal of this coding session. The title should be clear enough that the user recognizes the session in a list. Use sentence case: capitalize only the first word and proper nouns.
1
+ import{CostTracker as e,computeCacheHitRatio as t,createEventStream as n,createProviderRegistry as r,createStreamFunction as i}from"@x-otto/ai";import{createHookRegistry as a,defineHook as o,provisionBaselineSecurity as s}from"@x-otto/hooks";import{EventBus as c,TypedEventEmitter as l,buildAllowedEnv as u,createLogger as d}from"@x-otto/shared";import{dirname as f,join as p,resolve as m,sep as h}from"node:path";import{DiskPanelStatePersistence as g,DiskPasteStatePersistence as _,FileAppendLog as v,HttpAppendLog as y,MemoryAppendLog as b,createInMemoryPanelStatePersistence as x,createInMemoryPasteStatePersistence as S,normalizePasteSnapshot as ee}from"@x-otto/persistence";import{boundFragment as te}from"@x-otto/interchange";import{collectEnvironment as ne,formatEnvironmentBlock as re}from"@x-otto/prompt";import{FileSessionPersistence as ie,InMemorySession as C,InMemorySessionPersistence as ae,RemoteSessionPersistence as oe,RemoteSnapshotConflictError as se,SESSION_IDLE_TIMEOUT_MS as ce,SESSION_MAX as le,SESSION_SNAPSHOT_VERSION as w,hasStrippedReplacements as ue,supportsReplacementHydration as de}from"@x-otto/session";import{SDK_VERSION as fe,isShadowModeEnabled as pe,listOttoProcesses as me}from"@x-otto/env";import{ENGINE_DEFAULTS as he,applyMemoryTransform as ge,createAgent as _e,createRecordingPorts as ve,createReplayPorts as ye,createTraceRecorder as be,extractNondetDraws as xe,extractToolResultText as Se,forceMemoryTransform as Ce,prompt as we,stripAnsi as Te,systemClock as T,systemId as E,systemRandom as Ee}from"@x-otto/agent";import{mkdir as De,readFile as Oe,readdir as ke,rm as Ae,stat as je,unlink as Me,writeFile as Ne}from"node:fs/promises";import{randomUUID as D}from"node:crypto";import{SESSION_COMPACTION_TIMEOUT_MS as Pe,SESSION_MAX_HISTORY_MESSAGES as Fe,SESSION_MAX_PER_SESSION_BYTES as Ie,SESSION_MIN_PER_SESSION_BYTES as Le,SESSION_TOTAL_RESIDENCY_BUDGET as Re,resolveResidencyBudget as O}from"@x-otto/session-contract";import{getHeapStatistics as ze}from"node:v8";import{execFileSync as k,spawn as Be,spawnSync as Ve}from"node:child_process";import{EventEmitter as He}from"node:events";import{mkdtempSync as Ue,realpathSync as We}from"node:fs";import{tmpdir as Ge}from"node:os";function Ke(e,t){let n=t=>e.ephemeral?new b:e.sessionDir?new v({baseDir:p(e.sessionDir,t)}):e.remoteLog?new y(e.remoteLog):new b;return{traceStore:t?.traceStore??n(`trace`),checkpointStore:t?.checkpointStore??n(`checkpoint`)}}function qe(e){let t=new Map;return[o({name:e.name,timing:`system.prompt.transform`,priority:e.priority,handle:async(n,r)=>{let i=t.get(n.sessionId);i===void 0&&(i=await e.compute(n)??``,t.set(n.sessionId,i)),i&&(r.systemPrompt=`${r.systemPrompt}\n\n${i}`)}}),o({name:`${e.name}-cleanup`,timing:`session.deleted`,priority:90,handle:e=>{t.delete(e.sessionId)}})]}const A={toolGuidance:{name:`tool-guidance-injection`,priority:20,lane:`stable`,budgetBytes:2e4},skillLoopGuidance:{name:`skill-loop-guidance-injection`,priority:21,lane:`stable`,budgetBytes:2e3},environment:{name:`runtime:environment`,priority:25,lane:`stable`,budgetBytes:8e3},memoryIndex:{name:`runtime:memory-index`,priority:35,lane:`stable`,budgetBytes:3e4},skillCatalog:{name:`skill-catalog-injection`,priority:38,lane:`stable`,budgetBytes:12e3},lesson:{name:`lesson-injection`,priority:40,lane:`stable`,budgetBytes:8e3},memoryDelta:{name:`memory-delta-injection`,priority:60,lane:`volatile`,budgetBytes:8e3},todoReminder:{name:`todo-reminder-injection`,priority:62,lane:`volatile`,budgetBytes:4e3},docSyncReminder:{name:`doc-sync-reminder-injection`,priority:64,lane:`volatile`,budgetBytes:4e3}},Je=Object.values(A);function j(e,t){let n=Je.find(t=>t.name===e);return n?te({id:Ye(e),content:t},n.budgetBytes).content:t}function Ye(e){let t={"tool-guidance-injection":`toolGuidance`,"skill-loop-guidance-injection":`skillLoopGuidance`,"runtime:environment":`environment`,"runtime:memory-index":`memoryIndex`,"skill-catalog-injection":`skillCatalog`,"lesson-injection":`lesson`,"memory-delta-injection":`memoryDelta`,"todo-reminder-injection":`todoReminder`,"doc-sync-reminder-injection":`docSyncReminder`}[e];if(t===void 0)throw Error(`applySectionBudget: unknown section name "${e}"`);return t}var Xe=class{sources=new Map;sealed=!1;register(e){if(this.sealed)throw Error(`ContextSourceRegistry: cannot register "${e.id}" — registry is sealed (hooks already built).`);this.sources.set(e.id,e)}list(){return[...this.sources.values()].sort((e,t)=>(e.priority??50)-(t.priority??50))}sealAndBuildHooks(e,t){this.sealed=!0;let n=[];for(let r of this.list())n.push(...qe({name:`ctxsrc:${r.id}`,priority:r.priority??50,compute:async n=>{let i=await r.contribute({sessionId:n.sessionId,workspaceDir:e,memory:t});return i&&j(r.id,i)}}));return n}};function Ze(e){return{id:`runtime:environment`,priority:A.environment.priority,async contribute(t){let n=async(e,t)=>{let{execSync:n}=await import(`node:child_process`);return n(e,{cwd:t,encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]})};try{return re(await ne(e,n))}catch{return}}}}function Qe(e,t){let n=!1;return{id:`runtime:memory-index`,priority:A.memoryIndex.priority,async contribute(e){if(!t)return;n||=(await t.loadMemory(),!0);let r=t.getMemoryPrompt();return r.trim()?r:void 0}}}const $e=d(`@x-otto/runtime/hooks`);function et(e){let{hookRegistry:t,agentName:n,sessionId:r}=e;return{async executeBeforeHooks(e){let i={args:{...e.args},cancelled:!1};return await t.execute(`tool.execute.before`,{...e,agentName:n,sessionId:r},i),i.cancelled||i.decision===`deny`?{kind:`deny`,reason:i.cancelReason??i.decisionReason??`Tool ${e.toolName} was blocked by pre-execution hook`}:i.decision===`ask`?{kind:`ask`,args:i.args,reason:i.decisionReason??`Requires confirmation`,risk:i.risk}:i.decision===`allow`||i.decision===void 0?{kind:`proceed`,args:i.args}:($e.warn({toolName:e.toolName,decision:i.decision},`tool.execute.before hook returned unrecognized decision — denying as safety fallback`),{kind:`deny`,reason:`Tool ${e.toolName} was blocked: hook returned unrecognized decision "${String(i.decision)}"`})},async executeAfterHooks(e){let i={result:e.result,metadata:{}};return await t.execute(`tool.execute.after`,{...e,agentName:n,sessionId:r},i),i}}}function M(e){for(let t of e){if(t.role!==`user`)continue;let{content:e}=t,n;if(typeof e==`string`?n=e:Array.isArray(e)&&(n=e.filter(e=>e.type===`text`&&typeof e.text==`string`).map(e=>e.text).join(` `)),!n)continue;let r=n.replace(/\s+/g,` `).trim();if(r)return r.length>80?r.slice(0,80):r}}function tt(e,t,n){return e?.trim()||(M(t)??n.slice(0,8))}function nt(e){return typeof e==`string`?e:Array.isArray(e)?e.filter(e=>{let t=e;return t.type===`text`&&typeof t.text==`string`}).map(e=>e.text).join(``):``}function rt(e){let t=e.trim();if(!t)return null;let n=t.match(/\{[^{}]*"title"\s*:\s*"([^"]+)"[^{}]*\}/);if(!n&&/"title/.test(t))return null;let r=(n?.[1]??t).replace(/\s+/g,` `).trim();return r?r.length>80?r.slice(0,80):r:null}async function it(e,t,n){let r=t.trim().slice(-2e3);if(!r)return null;let i=new AbortController,a=()=>i.abort();if(n.aborted)return null;n.addEventListener(`abort`,a,{once:!0});let o=setTimeout(()=>i.abort(),e.timeoutMs??15e3);try{let t=[{role:`user`,timestamp:Date.now(),content:[{type:`text`,text:r}]}];return rt(nt((await e.stream({model:e.model,systemPrompt:`Generate a concise, sentence-case title (3-7 words) that captures the main topic or goal of this coding session. The title should be clear enough that the user recognizes the session in a list. Use sentence case: capitalize only the first word and proper nouns.
2
2
 
3
3
  Return JSON with a single "title" field.
4
4
 
@@ -9,16 +9,16 @@ Good examples:
9
9
 
10
10
  Bad (too vague): {"title": "Code changes"}
11
11
  Bad (too long): {"title": "Investigate and fix the issue where the login button does not respond on mobile devices"}
12
- Bad (wrong case): {"title": "Fix Login Button On Mobile"}`,messages:t,cacheRetention:`none`,maxTokens:64,temperature:0},i.signal).result()).content))}catch{return null}finally{clearTimeout(o),n.removeEventListener(`abort`,a)}}var et=class{session;stream;titleModel;genSeq=0;abortController=new AbortController;disposed=!1;constructor(e){this.session=e.session,this.stream=e.stream,this.titleModel=e.titleModel}maybeGenerate(e=!1){if(!this.titleModel||this.disposed||this.session.metadata().titleSource===`custom`)return;let t=this.session.messages().filter(e=>e.role===`user`).length;if(t===0||!e&&t>3)return;let n=++this.genSeq,r=this.session.messages().map(e=>{let t=e.content;return typeof t==`string`?t:Array.isArray(t)?t.filter(e=>{let t=e;return t.type===`text`&&typeof t.text==`string`}).map(e=>e.text).join(` `):``}).filter(Boolean).join(`
13
- `);$e({stream:this.stream,model:this.titleModel},r,this.abortController.signal).then(e=>{!e||this.disposed||n===this.genSeq&&this.session.metadata().titleSource!==`custom`&&this.session.setTitle(e,`ai`)}).catch(()=>{})}backfill(){this.maybeGenerate(!0)}dispose(){this.disposed||(this.disposed=!0,this.abortController.abort())}},tt=class{constructor(e){this.deps=e}messages(){return this.deps.session.messages()}append(e){this.deps.session.append(e)}removeLast(){this.deps.session.removeLast()}persistInputBoundary(){this.deps.requestInputBoundaryFlush?.()}buildContext(){return this.deps.session.buildContext()}persistNew(e,t){let n=e.slice(t);for(let e of n)this.deps.session.append(e)}recordCompaction(e,t){let{session:n,sessionId:r,publish:i}=this.deps,a=n.buildContext().messages.length;n.recordCompaction(e,t);let o=n.buildContext().messages.length;o<a&&(i({"compaction.start":[{type:`compaction.start`,sessionId:r,messageCount:a}]}),i({"compaction.end":[{type:`compaction.end`,sessionId:r,retainedCount:o,summary:e}]}))}notifyPrune(e,t){this.deps.publish({"memory.pruned":[{type:`memory.pruned`,sessionId:this.deps.sessionId,tokensSaved:e,prunedCount:t?.prunedCount,messagesBefore:t?.messagesBefore,messagesAfter:t?.messagesAfter}]})}};const nt=`Continue with the remaining todo items.`,rt=new Set([`done`,`skipped`,`failed`]);function it(e,t){if(e.size!==t.size)return!1;for(let[n,r]of e)if(!t.has(n)||t.get(n)!==r)return!1;return!0}var at=class e{session;sessionId;logger;todoContinuation;depth;publish;isAbortRequested;runPromptRound;constructor(e){this.session=e.session,this.sessionId=e.sessionId,this.logger=e.logger,this.todoContinuation=e.todoContinuation,this.depth=e.depth,this.publish=e.publish,this.isAbortRequested=e.isAbortRequested,this.runPromptRound=e.runPromptRound}snapshot(){return new Map((this.session.getTodoList()??[]).map(e=>[e.id,e.status]))}countIncomplete(){return(this.session.getTodoList()??[]).filter(e=>!rt.has(e.status??`pending`)).length}static hasStateProgress(e,t){return!it(e,t)}async run(){if(!this.todoContinuation.enabled||this.depth>0)return;let t=this.todoContinuation.max*4,n=0,r=0,i=0,a=!1,o=nt,s=this.snapshot();for(;n<this.todoContinuation.max&&r<t&&!this.isAbortRequested()&&this.countIncomplete()>0;){n++,r++,this.publish({"prompt.continued":[{type:`prompt.continued`,sessionId:this.sessionId,round:r,maxRounds:t,incompleteCount:this.countIncomplete()}]}),this.logger.info({sessionId:this.sessionId,round:n,totalRounds:r,max:this.todoContinuation.max,hardCap:t},`Todo gate: auto-continuing unfinished todos`);let c=await this.runPromptRound(o,!0);if(c.cancelled)return;o=nt;let l=this.snapshot();if(e.hasStateProgress(s,l)){n--,i=0,s=l;continue}if(c.hadToolActivity&&!a){n--,a=!0,i=1,o=`You made progress but did not update the todo list. Reconcile it now: mark each genuinely finished item done (or skipped/failed with a reason) via write_todos, then continue any remaining work.`,this.logger.info({sessionId:this.sessionId,round:n},`Todo gate: tool activity without todo updates — nudging state reconciliation`);continue}if(c.hadToolActivity){i++,this.logger.info({sessionId:this.sessionId,staleActivityRounds:i},`Todo gate: diminishing returns (repeated activity without todo progress), stopping`);return}this.logger.info({sessionId:this.sessionId,round:n},`Todo gate: no progress between rounds, stopping early`);return}}};async function ot(e,t,n){let{session:r,sessionId:i,hookRegistry:a,logger:o,publish:s}=e,c=r.messages().length;await a.emit(`compaction.before`,{sessionId:i,messageCount:c}),s({"compaction.start":[{type:`compaction.start`,sessionId:i,messageCount:c}]}),o.info({sessionId:i,count:n},`Session compacting`),r.compact(t,n);let l=r.messages().length;await a.emit(`compaction.after`,{sessionId:i,retainedCount:l}),s({"compaction.end":[{type:`compaction.end`,sessionId:i,retainedCount:l,summary:t}]}),o.info({sessionId:i,retained:l,summaryChars:t.length},`Session compaction finished`)}async function st(e,t){let{session:n,sessionId:r,hookRegistry:i,logger:a,memory:o,persistence:s}=e,c=n.buildContext(),l=c.messages.length;if(!o||t?.aborted)return{compacted:!1,before:l,after:l};await i.emit(`compaction.before`,{sessionId:r,messageCount:l}),a.info({sessionId:r,messageCount:l},`Session manual compaction (forced)`);let u={compacted:!1};await Se(o,c.messages,r,t,{persistence:s,sink:u});let d=n.buildContext().messages.length;return await i.emit(`compaction.after`,{sessionId:r,retainedCount:d}),a.info({sessionId:r,retainedCount:d},`Session manual compaction finished`),{compacted:u.compacted,before:l,after:d}}function ct(e,t,n,r){return[e.on(`max.turns`,e=>{e.steered&&r(),n({"budget.notice":[{type:`budget.notice`,sessionId:t,turnIndex:e.turnIndex,maxTurns:e.maxTurns,extended:e.extended,...e.steered===void 0?{}:{steered:e.steered},...e.progressDenied===void 0?{}:{progressDenied:e.progressDenied}}]})}),e.on(`prompt.budget`,e=>{e.steered&&r(),n({"prompt.budget.notice":[{type:`prompt.budget.notice`,sessionId:t,turnIndex:e.turnIndex,dimension:e.dimension,used:e.used,budget:e.budget,steered:e.steered}]})}),e.on(`progress.stall`,e=>{n({"progress.stall.notice":[{type:`progress.stall.notice`,sessionId:t,turnIndex:e.turnIndex,windowTurns:e.windowTurns,maxRepeat:e.maxRepeat}]})}),e.on(`tool.call.mismatch`,e=>{n({"tool.call.mismatch.notice":[{type:`tool.call.mismatch.notice`,sessionId:t,turnIndex:e.turnIndex,outcome:e.outcome,retryCount:e.retryCount}]})}),e.on(`image.vision-delegate`,e=>{n({"image.vision-delegate":[{type:`image.vision-delegate`,sessionId:t,attemptedCount:e.attemptedCount,describedCount:e.describedCount,failedCount:e.failedCount}]})}),e.on(`compaction.reactive`,e=>{n({"compaction.reactive.notice":[{type:`compaction.reactive.notice`,sessionId:t,messagesBefore:e.messagesBefore,messagesAfter:e.messagesAfter}]})}),e.on(`image.degradation`,e=>{n({"image.degradation.notice":[{type:`image.degradation.notice`,sessionId:t,degradedCount:e.degradedCount,trigger:e.trigger}]})})]}function lt(e,t){if(e)return e.length>t?`${e.slice(0,t)}…`:e}function ut(e,t){if(t.toolCall.name!==`write_todos`||t.result.isError)return;let n=t.result.details?.todos;if(!Array.isArray(n))return;let r=new Map((e.getTodoList()??[]).map(e=>[e.id,e.turn]));e.setTodoList(n.map(e=>({id:e.id,title:e.title,status:e.status,turn:e.id===void 0?void 0:r.get(e.id)})))}function dt(e){let{agent:t,session:n,sessionId:r,modelId:i,hookRegistry:a,publish:o}=e;return[t.on(`stream.event`,async({event:e})=>{o({"stream.event":[{type:`stream.event`,sessionId:r,event:e}]}),e.type===`start`?(o({"streaming.start":[{type:`streaming.start`,sessionId:r,model:i()}]}),a.emit(`stream.start`,{sessionId:r,model:i()})):e.type===`done`&&(o({"streaming.end":[{type:`streaming.end`,sessionId:r,model:i(),stopReason:e.reason??`end_turn`}]}),await a.emit(`stream.end`,{sessionId:r,model:i(),stopReason:e.reason??`end_turn`,tokenUsage:{input:e.message.usage.inputTokens,output:e.message.usage.outputTokens}}))}),t.on(`turn.start`,e=>{o({"turn.start":[{type:`turn.start`,sessionId:r,turnIndex:e.turnIndex,toolTurnCount:e.toolTurnCount,maxToolTurns:e.maxToolTurns,promptOutputTokens:e.promptOutputTokens,promptOutputTokenBudget:e.promptOutputTokenBudget}]})}),t.on(`turn.end`,e=>{o({"turn.end":[{type:`turn.end`,sessionId:r,turnIndex:e.turnIndex}]})}),t.on(`tool.call.start`,e=>{o({"tool.call.start":[{type:`tool.call.start`,sessionId:r,toolCall:{id:e.toolCall.id,name:e.toolCall.name,arguments:e.toolCall.arguments}}]})}),t.on(`tool.call.end`,e=>{ut(n,e);let t=we(xe(e.result)),i=e.contextChars??t.length;o({"tool.call.end":[{type:`tool.call.end`,sessionId:r,toolCall:{id:e.toolCall.id,name:e.toolCall.name,arguments:e.toolCall.arguments},isError:e.result.isError===!0,resultText:lt(t,me.traceResultMaxChars),resultTokensEstimate:Math.ceil(i/4),details:e.result.details??void 0}]})})]}const ft=100*1024*1024;function pt(e){return e.replace(/[^a-zA-Z0-9_-]/g,`_`).slice(0,128)||`unnamed`}var mt=class{rootDir;constructor(e){this.rootDir=p(e,`tool-results`)}sessionDir(e){return p(this.rootDir,pt(e))}async spill(e,t,n){if(!fe())try{let r=this.sessionDir(e);await T(r,{recursive:!0});let i=p(r,`${pt(t)}.txt`);return await O(i,n,`utf-8`),this.evictIfOverBudget().catch(()=>{}),i}catch{return}}async cleanupSession(e){try{await D(this.sessionDir(e),{recursive:!0,force:!0})}catch{}}async evictIfOverBudget(){let e=[],t=0,n;try{n=await E(this.rootDir)}catch{return}for(let r of n){let n=p(this.rootDir,r),i;try{i=await E(n)}catch{continue}for(let r of i){let i=p(n,r);try{let n=await ke(i);n.isFile()&&(e.push({path:i,mtimeMs:n.mtimeMs,size:n.size}),t+=n.size)}catch{}}}if(!(t<=ft)){e.sort((e,t)=>e.mtimeMs-t.mtimeMs);for(let n of e){if(t<=ft)break;try{await Ae(n.path),t-=n.size}catch{}}}}};let ht;function gt(){return ht??=new mt(p(process.cwd(),`.otto`)),ht}const _t={spill(e,t,n){return gt().spill(e,t,n)},cleanupSession(e){return gt().cleanupSession(e)}},vt={maxToolTurns:me.maxToolTurns};function yt(){let e,t,n=new Promise((n,r)=>{e=n,t=r});return{resolve:e,reject:t,promise:n}}var P=class{pending=new Map;open(e){let t=yt();return this.pending.set(e,t),t.promise.finally(()=>{this.pending.delete(e)})}resolve(e,t){let n=this.pending.get(e);return n?(n.resolve(t),!0):!1}rejectAll(e){for(let t of this.pending.values())t.reject(e);this.pending.clear()}},bt=class{approvalGate=new P;grillGate=new P;planGate=new P;constructor(e){this.deps=e}async requestApproval(e,t,n,r){let{sessionId:i,interactive:a,logger:o,publish:s}=this.deps;if(!a)return o.warn({sessionId:i(),toolName:e},`Approval requested in a non-interactive session; denying (fail-closed, no human to respond)`),!1;let c=A(),l=this.approvalGate.open(c);return s({"approval.required":[{type:`approval.required`,sessionId:i(),id:c,toolName:e,arguments:t,description:n,risk:r}]}),o.info({sessionId:i(),toolName:e,approvalId:c},`Approval requested`),l}resolveApproval(e,t){let{sessionId:n,logger:r,publish:i}=this.deps;this.approvalGate.resolve(e,t)&&(i({"approval.resolved":[{type:`approval.resolved`,sessionId:n(),id:e,approved:t}]}),r.info({sessionId:n(),approvalId:e,approved:t},`Approval resolved`))}async requestGrill(e){let{sessionId:t,interactive:n,logger:r,publish:i}=this.deps;if(!n)return{answer:e.recommendation,acceptedRecommendation:!0,resolvedBy:`auto_recommendation`};let a=A(),o={...e,id:a},s=this.grillGate.open(a);return i({"ask.user.required":[{type:`ask.user.required`,sessionId:t(),requestId:a,question:o}]}),r.info({sessionId:t(),requestId:a,askedBy:e.askedBy},`Grill requested`),s}resolveAskUser(e,t){let{sessionId:n,logger:r,publish:i}=this.deps;t&&this.grillGate.resolve(e,t)&&(i({"ask.user.resolved":[{type:`ask.user.resolved`,sessionId:n(),requestId:e}]}),r.info({sessionId:n(),requestId:e},`Grill resolved`))}async requestPlanApproval(e){let{sessionId:t,logger:n,publish:r}=this.deps,i=A(),a=this.planGate.open(i);return r({"plan.approval.required":[{type:`plan.approval.required`,sessionId:t(),requestId:i,planContent:e}]}),n.info({sessionId:t(),requestId:i},`Plan approval requested`),a}resolvePlanApproval(e,t,n){let{sessionId:r,logger:i,publish:a}=this.deps;this.planGate.resolve(e,{action:t,feedback:n})&&(a({"plan.approval.resolved":[{type:`plan.approval.resolved`,sessionId:r(),requestId:e,action:t}]}),i.info({sessionId:r(),action:t,requestId:e},`Plan approval resolved`))}rejectAll(e){this.approvalGate.rejectAll(e),this.grillGate.rejectAll(e),this.planGate.rejectAll(e)}},xt=class{costTracker=new e;sessionCrossedCostBudget=!1;lastTokenUsage;lastCacheHitRatio=null;constructor(e){this.deps=e}record(e,n){let r=e.usage;if(e.count===0||e.lastAssistantApi===void 0)return;this.lastTokenUsage={input:r.inputTokens,output:r.outputTokens},this.lastCacheHitRatio=t(r,e.lastAssistantApi);let i=this.costTracker.record(n,r),a=this.costTracker.summary().totalCostUSD,{sessionId:o,logger:s,publish:c,sessionCostBudgetUSD:l}=this.deps;s.info({sessionId:o(),input:r.inputTokens,output:r.outputTokens,cacheRead:r.cacheReadTokens,cacheWrite:r.cacheWriteTokens,cacheHitRatio:this.lastCacheHitRatio,turnCost:i.toFixed(6),sessionCost:a.toFixed(6)},`Session usage`),!this.sessionCrossedCostBudget&&l!==void 0&&l>0&&a>=l&&(this.sessionCrossedCostBudget=!0,c({"session.cost-budget-exceeded":[{type:`session.cost-budget-exceeded`,sessionId:o(),totalCostUSD:a,budgetUSD:l}]}))}getLastTokenUsage(){return this.lastTokenUsage}getCostSummary(){return this.costTracker.summary()}getLastCacheHitRatio(){return this.lastCacheHitRatio}};function St(e,t){return e>0||t?0:3}function Ct(e){let t=(e.OTTO_TODO_CONTINUE??``).toLowerCase(),n=!(t===`0`||t===`off`||t===`false`||t===`no`),r=Math.trunc(Number(e.OTTO_TODO_CONTINUE_MAX??3));return{enabled:n,max:Number.isFinite(r)&&r>=0?r:3}}var wt=class extends c{session;workspaceDir;workspaceId;agent;disposed=!1;promptGate=!1;titleManager;runStartedThisPrompt=!1;currentPrompt;compactionPending;getCompactionTimeoutMs;model;modelResolution;tools;systemPrompt;systemTail;agentName;depth;transient;listable;maxToolTurns;maxToolTurnExtensions;promptOutputTokenBudget;promptWallClockBudgetMs;thinkingLevel;promptRefresh;logger;hookRegistry;devtools;memory;recorder;describeImages;nondetFlush;clock;steerSeq=0;persistence;inputBoundaryFlusher;setInputBoundaryFlusher(e){this.inputBoundaryFlusher=e}gates;interactive;agentUnsubs=[];sessionCostBudgetUSD;usageTracker;todoGateRunner;abortRequested=!1;pauseRequested=!1;get id(){return this.session.id}get title(){return this.session.metadata().title}get status(){return this.agent.status}get pinned(){return this.session.metadata().pinned??!1}get pinGroup(){return this.session.metadata().pinGroup}get coreAgent(){return this.agent}get isExecuting(){return this.agent.status===`streaming`||this.agent.status===`tool_executing`}get isBusy(){return this.promptGate||this.isExecuting}getSessionInfo(){return{sessionId:this.id,modelId:this.model.id,modelName:this.model.name,systemPromptLength:this.systemPrompt?.length??0,tools:this.tools.map(e=>e.name)}}constructor(e,t){super(),this.session=e;let n=t.hookRegistry??a({preset:`default`});t.hookRegistry||s(n);let r=t.logger??d(`agent-session:${e.id}`,{level:`info`,destination:`stdout`});this.getCompactionTimeoutMs=t.getCompactionTimeoutMs;let i=t.promptRefresh,o=t.systemPrompt??``,c=t.tools??[],l=t.thinkingLevel??`medium`,u=t.maxToolTurns??vt.maxToolTurns,f=t.depth??0,p=t.maxToolTurnExtensions??St(f,t.transient),m=f===0?t.promptOutputTokenBudget:void 0,h=f===0?t.promptWallClockBudgetMs:void 0,g=t.stallDetection,_=process.env.OTTO_BUDGET_STEER_WRAPUP,v=t.budgetSteerWrapUp??(_===`1`||_===`on`?!0:_===`0`||_===`off`?!1:f===0),y=t.workspaceDir??process.cwd(),{model:b,devtools:x,agentName:S}=t;this.model=b,this.modelResolution=t.modelResolution,this.tools=c,this.systemPrompt=o,this.systemTail=t.systemTail,this.thinkingLevel=l,this.maxToolTurns=u,this.maxToolTurnExtensions=p,this.promptOutputTokenBudget=m,this.promptWallClockBudgetMs=h,this.hookRegistry=n,this.agentName=S??`agent`,this.depth=f,this.transient=t.transient??!1,this.listable=t.listable??!0,this.interactive=t.interactive??!1,this.devtools=x,this.memory=t.memory,this.recorder=t.recorder,this.describeImages=t.describeImages,this.nondetFlush=t.nondetFlush,this.clock=t.clock,this.logger=r,this.workspaceDir=y,this.sessionCostBudgetUSD=f===0?t.sessionCostBudgetUSD:void 0,this.workspaceId=t.workspaceId,this.promptRefresh=i,this.gates=new bt({sessionId:()=>this.id,interactive:this.interactive,logger:r,publish:e=>this.publish(e)}),this.usageTracker=new xt({sessionId:()=>this.id,sessionCostBudgetUSD:this.sessionCostBudgetUSD,logger:r,publish:e=>this.publish(e)}),this.titleManager=new et({session:e,stream:t.stream,titleModel:t.titleModel}),this.todoGateRunner=new at({session:e,sessionId:e.id,logger:r,todoContinuation:t.todoContinuation??Ct(process.env),depth:f,publish:e=>this.publish(e),isAbortRequested:()=>this.abortRequested,runPromptRound:(e,t)=>this.runPromptRound(e,t)}),this.agent=ge({stream:t.stream,logger:r,maxToolTurns:u,maxToolTurnExtensions:p,budgetSteerWrapUp:v,promptOutputTokenBudget:m,promptWallClockBudgetMs:h,stallDetection:g,agentName:this.agentName,sessionId:e.id,depth:this.depth,toolHookExecutor:Ye({hookRegistry:n,agentName:this.agentName,sessionId:e.id}),debug:x?.debugger,recorder:this.recorder,nondetFlush:this.nondetFlush,clock:this.clock,approval:(e,t,n,r)=>this.requestApproval(e,t,n,r),spill:(t,n)=>_t.spill(e.id,t,n),retryAccelerate:t.retryAccelerate,streamRetry:t.streamRetry,networkDisconnectRetry:t.networkDisconnectRetry,lifecycleAsyncTimeoutMs:t.lifecycleAsyncTimeoutMs}),this.agentUnsubs.push(this.agent.on(`status.change`,({to:e})=>{e===`streaming`&&(this.runStartedThisPrompt=!0)})),this.agentUnsubs.push(...ct(this.agent,this.id,e=>this.publish(e),()=>{this.budgetSteeredThisPrompt=!0})),this.agentUnsubs.push(...dt({agent:this.agent,session:this.session,sessionId:this.id,modelId:()=>this.model.id,hookRegistry:n,publish:e=>this.publish(e)})),this.agentUnsubs.push(this.agent.on(`steering.injected`,({messages:e})=>{for(let t of e){let e=t.uuid;e&&this.publish({"steer.consumed":[{type:`steer.consumed`,sessionId:this.id,id:e}]})}})),this.persistence=new tt({session:this.session,sessionId:this.id,publish:e=>this.publish(e),requestInputBoundaryFlush:()=>this.inputBoundaryFlusher?.()}),this.logger.info({sessionId:this.id,model:this.model.id},`Session initialized`)}notifyCreated(){this.publish({"session.start":[{type:`session.start`,sessionId:this.id}]})}budgetSteeredThisPrompt=!1;archive(){this.ensureNotDisposed(),this.agent.archive(),this.session.setArchived(!0)}unarchive(){this.ensureNotDisposed(),this.agent.unarchive(),this.session.setArchived(!1)}pin(e){this.ensureNotDisposed(),this.session.setPinned(!0,e?.trim()||void 0)}unpin(){this.ensureNotDisposed(),this.session.setPinned(!1)}async prompt(e,t){if(this.ensureNotDisposed(),this.status===`archived`)throw Error(`Session is archived. Unarchive it first before sending messages.`);if(this.isBusy){let{streamingBehavior:n}=t??{};if(n===`followUp`)this.followUp(e);else if(n===`steer`)this.steer(e);else throw Error(`Agent is processing. Specify streamingBehavior ("steer" or "followUp") to queue the message.`);return}let n=this.executePrompt(e,t);this.currentPrompt=n;try{await n}finally{this.currentPrompt===n&&(this.currentPrompt=void 0)}}async retryLastRound(){if(this.ensureNotDisposed(),this.status===`archived`)throw Error(`Session is archived. Unarchive it first before sending messages.`);if(this.isBusy)throw Error(`Agent is processing. Cannot retry while a round is in flight.`);if(![...this.session.messages()].reverse().find(e=>e.role===`user`)){let e=Error(`No resumable user message in history`);throw e.code=`RETRY_NO_RESUMABLE_ROUND`,e}let e=this.executePrompt(``,{resumeLastRound:!0});this.currentPrompt=e;try{await e}finally{this.currentPrompt===e&&(this.currentPrompt=void 0)}}async executePrompt(e,t){this.promptGate=!0,this.budgetSteeredThisPrompt=!1,this.runStartedThisPrompt=!1,this.abortRequested=!1,this.pauseRequested=!1;let n=this.model.id,r=this.thinkingLevel;try{if(this.publish({"prompt.start":[{type:`prompt.start`,sessionId:this.id,text:e}]}),!this.session.metadata().title?.trim()){let t=N([{role:`user`,content:e}]);t&&this.session.setTitle(t,`derived`)}if(this.logger.info({sessionId:this.id},`Session prompt started`),(await this.runPromptRound(e,void 0,t?.images,t?.resumeLastRound)).cancelled){this.publish({"prompt.end":[{type:`prompt.end`,sessionId:this.id,tokenUsage:this.usageTracker.getLastTokenUsage(),model:n,thinkingLevel:r,stopReason:`interrupted`}]});return}await this.todoGateRunner.run(),this.titleManager.maybeGenerate(),this.publish({"prompt.end":[{type:`prompt.end`,sessionId:this.id,tokenUsage:this.usageTracker.getLastTokenUsage(),model:n,thinkingLevel:r,stopReason:`completed`}]}),this.logger.info({sessionId:this.id},`Session prompt finished`)}catch(e){let t=e instanceof Error?e:Error(String(e));throw this.publish({"prompt.end":[{type:`prompt.end`,sessionId:this.id,tokenUsage:this.usageTracker.getLastTokenUsage(),model:n,thinkingLevel:r,stopReason:`error`}]}),this.publish({error:[{type:`error`,sessionId:this.id,error:t}]}),this.logger.error({sessionId:this.id,err:t.message},`Session prompt failed`),e}finally{this.promptGate=!1}}async runPromptRound(e,t,n,r){if(this.compactionPending){let e=this.compactionPending;this.compactionPending=void 0;try{let t=this.getCompactionTimeoutMs?.()??je;await Promise.race([e,new Promise((e,n)=>setTimeout(()=>n(Error(`compaction timeout`)),t))])}catch{}}if(this.promptRefresh){let e=await this.promptRefresh();e!==void 0&&(this.systemPrompt=e)}let i=await Ce({text:e,internal:t,images:n,...r?{resumeLastRound:!0}:{},sessionId:this.id,agentName:this.agentName,model:this.model,tools:this.model.supportsTools===!1?[]:this.tools,params:{systemPrompt:this.systemPrompt,systemTail:this.systemTail,thinkingLevel:this.thinkingLevel,cacheRetention:this.interactive?`long`:`short`},runner:this.agent,hooks:this.hookRegistry,persistence:this.persistence,memory:this.memory,debug:this.devtools?.debugger,recorder:this.recorder,clock:this.clock,isPauseRequested:()=>this.pauseRequested,describeImages:this.describeImages});return i.cancelled?{cancelled:!0,hadToolActivity:!1}:(this.pauseRequested&&this.publish({"run.paused":[{type:`run.paused`,sessionId:this.id}]}),this.systemPrompt=i.params.systemPrompt,this.thinkingLevel=i.params.thinkingLevel,this.usageTracker.record(i.newMessagesUsageSummary,this.model),{cancelled:!1,hadToolActivity:i.newMessagesUsageSummary.hadToolActivity})}steer(e){this.ensureNotDisposed();let t=`steer-${++this.steerSeq}`,n={role:`user`,timestamp:this.clock?.now()??Date.now(),content:[{type:`text`,text:e}],uuid:t};return this.agent.steer(n),{id:t}}removeSteer(e){return this.ensureNotDisposed(),this.agent.removeSteer(e)}followUp(e){this.ensureNotDisposed(),this.agent.followUp({role:`user`,timestamp:this.clock?.now()??Date.now(),content:[{type:`text`,text:e}]})}abort(){this.promptGate&&(this.abortRequested=!0),this.pauseRequested=!1;let e=this.isExecuting,t=this.promptGate&&!this.runStartedThisPrompt;!e&&!t||(this.rejectPendingGates(),this.agent.abort())}pauseRun(){return this.ensureNotDisposed(),this.isBusy?(this.pauseRequested=!0,this.publish({"run.pause_requested":[{type:`run.pause_requested`,sessionId:this.id}]}),!0):!1}cancelPauseRun(){return this.ensureNotDisposed(),!this.isBusy||!this.pauseRequested?!1:(this.pauseRequested=!1,this.publish({"run.pause_cancelled":[{type:`run.pause_cancelled`,sessionId:this.id}]}),!0)}resumeRun(){this.ensureNotDisposed(),this.pauseRequested&&(this.pauseRequested=!1,this.publish({"run.resumed":[{type:`run.resumed`,sessionId:this.id}]}))}get isPaused(){return this.pauseRequested}async compact(e,t){this.ensureNotDisposed(),await ot(this.compactionDeps(),e,t)}async compactNow(e){return this.ensureNotDisposed(),st({...this.compactionDeps(),memory:this.memory,persistence:this.persistence},e)}compactionDeps(){return{session:this.session,sessionId:this.id,hookRegistry:this.hookRegistry,logger:this.logger,publish:e=>this.publish(e)}}async clearContext(){this.ensureNotDisposed(),this.isBusy&&(this.abort(),await this.currentPrompt?.catch(()=>{}));let e=this.session.messages().length;this.session.clearContext(),this.memory?.clearSession?.(this.id),this.logger.info({sessionId:this.id,clearedCount:e},`Session context cleared (/clear)`),this.publish({"session.cleared":[{type:`session.cleared`,sessionId:this.id,clearedCount:e}]})}clearTurnPanels(){this.session.setTodoList([]),this.session.setEditedFiles([]),this.session.setSubagents([]),this.session.setTurnSummaries([])}renameSession(e){this.session.setTitle(e,`custom`)}getCostSummary(){return this.usageTracker.getCostSummary()}getLastCacheHitRatio(){return this.usageTracker.getLastCacheHitRatio()}subscribe(e,t,n){if(typeof e==`function`)return this.subscribeAll((t,n)=>{e(n)});if(!t)throw Error(`callback is required when subscribing by type`);return super.subscribe(e,t,n)}async requestApproval(e,t,n,r){return this.gates.requestApproval(e,t,n,r)}resolveApproval(e,t){this.gates.resolveApproval(e,t)}async requestGrill(e){return this.gates.requestGrill(e)}resolveAskUser(e,t){this.gates.resolveAskUser(e,t)}async requestPlanApproval(e){return this.gates.requestPlanApproval(e)}resolvePlanApproval(e,t,n){this.gates.resolvePlanApproval(e,t,n)}rejectPendingGates(){this.gates.rejectAll(Error(`Session aborted`))}ensureNotDisposed(){if(this.disposed)throw Error(`AgentSession ${this.id} has been disposed`)}backfillTitle(){this.titleManager.backfill()}dispose(){if(!this.disposed){this.disposed=!0,this.titleManager.dispose(),this.rejectPendingGates();for(let e of this.agentUnsubs)e();this.agentUnsubs.length=0,this.pauseRequested&&this.agent.status===`completed`||this.agent.abort(),this.memory?.forgetSession?.(this.id),this.publish({"session.end":[{type:`session.end`,sessionId:this.id}]}),this.removeAllListeners(),this.logger.info({sessionId:this.id},`Session disposed`)}}};function Tt(e,t,n,r,i,a){let o=a?.now()??Date.now(),s=new C(e,t,n.length);return s.restoreEntries([...n],{...r,createdAt:o,lastActiveAt:o,parentSessionId:t,forkPoint:n.length,tags:[...r.tags,`fork`]},i),s}function Et(e,t){let n=m(e),r=m(n,t);if(!r.startsWith(n+h)&&r!==n)throw Error(`路径穿越拒绝:路径 "${t}" 不在工作目录 "${e}" 内`);return r}function Dt(e){return typeof e==`object`&&!!e&&`code`in e&&e.code===`ENOENT`}async function Ot(e,t){let n=[];for(let r of t){let t=Et(e,r);try{n.push({path:r,content:await Oe(t,`utf-8`)})}catch(e){if(Dt(e))n.push({path:r,content:null});else throw e}}return{files:n}}async function kt(e,t){for(let n of t.files){let t=Et(e,n.path);n.content===null?await D(t,{force:!0}):(await T(f(t),{recursive:!0}),await O(t,n.content,`utf-8`))}}function At(e){return typeof e==`object`&&!!e&&`type`in e}function F(e){return typeof e==`object`&&!!e&&`id`in e&&`name`in e&&(`result`in e||`resultSummary`in e)}function jt(e){return e.contentPreview?.map(e=>({type:`text`,text:e.text??e.preview??``}))??[]}function Mt(e){let t=new Map;for(let n of e.entries)t.set(n.id,n);let n=[],r=e.leafId?t.get(e.leafId):void 0;for(;r;)n.push(r),r=r.parentId?t.get(r.parentId):void 0;return n.reverse(),n.filter(e=>e.type===`message`).map(e=>e.message)}function Nt(e){return e.result?e.result.content:e.resultSummary?jt(e.resultSummary):[]}function Pt(e){if(typeof e==`object`&&e&&`text`in e){let t=e.text;return typeof t==`string`?t:void 0}}function Ft(e,t){let n=[...e];for(let e of t)if(e.kind===`lifecycle`&&e.node===`prompt.before`){let t=Pt(e.payload);t!==void 0&&n.push({role:`user`,content:[{type:`text`,text:t}],timestamp:e.ts})}else if(e.kind===`stream`&&e.node===`stream.event`)At(e.payload)&&e.payload.type===`done`&&n.push(e.payload.message);else if(e.kind===`tool`&&e.node===`tool.call.end`&&F(e.payload)){let{id:t,name:r,result:i,resultSummary:a}=e.payload,o=i?.isError??a?.isError??!1,s=i?.details??a?.details??{};n.push({role:`tool_result`,toolCallId:t,toolName:r,content:Nt(e.payload),isError:o,details:s,timestamp:e.ts})}return n}function It(e){return e.result?e.result:e.resultSummary?{content:jt(e.resultSummary),isError:e.resultSummary.isError,details:e.resultSummary.details}:{content:[],isError:!0,details:{error:`unable to extract result from trace payload`}}}function Lt(e){let t=[],n=[];for(let r of e)r.kind===`stream`&&r.node===`stream.event`&&At(r.payload)&&(n.push(r.payload),r.payload.type===`done`&&(t.push(n),n=[]));return n.length>0&&t.push(n),t}function Rt(e){let t=Lt(e),r=0;return()=>{let e=t[r]??[];r++;let i=n(),a;for(let t of e)i.push(t),t.type===`done`?a=t.message:`partial`in t&&(a=t.partial);return a?i.complete(a):i.fail(Error(`replay stream: no recorded LLM events for this turn`)),i}}function zt(e){let t=new Map;for(let n of e)n.kind===`tool`&&n.node===`tool.call.end`&&F(n.payload)&&t.set(n.payload.id,It(n.payload));return t}function Bt(e,t){return e.map(e=>({...e,execute:async e=>t.get(e.id)||{content:[{type:`text`,text:`replay: no recorded result for tool call ${e.id}`}],isError:!0}}))}var Vt=class extends Error{constructor(){super(`L2 deterministic re-execution requires a SandboxRunner (x-web-container runtime), which is not yet available. Use replay level "L1" (record/replay of tool results) for now.`),this.name=`SandboxUnavailableError`}},Ht=class{constructor(e){this.deps=e}replayPorts(e,t){let n=[...e];return{clock:ve(be(n)).clock,stream:Rt(n),tools:Bt(t,zt(n)),disableMemory:!0}}async replaySession(e,t,n={}){if(!this.deps.traceStore)throw Error(`replaySession requires a traceStore (record mode must be enabled)`);if((n.level??`L1`)===`L2`&&!n.sandbox)throw new Vt;let r=this.deps.getConfig(e);if(!r)throw Error(`Cannot replay unknown session "${e}" (no resolved config)`);let i=[];for await(let t of this.deps.traceStore.read(e))i.push(t.entry);return this.deps.createSession({...r,id:t},this.replayPorts(i,r.tools))}async createCheckpoint(e,t={}){if(!this.deps.checkpointStore)throw Error(`createCheckpoint requires a checkpointStore`);let n=this.deps.getSession(e);if(!n)throw Error(`Cannot checkpoint unknown session "${e}"`);let r=n.session;if(!(r instanceof C))throw Error(`Session "${e}" does not support snapshots`);if(n.isBusy)throw Error(`Cannot checkpoint session "${e}" while a prompt is in flight (session busy); checkpoint requires a quiescent session for a consistent {conversation, traceSeq}`);let i=r.toSnapshot(),a=await this.ensureHydrated(e,i.entries,`checkpoint capture`),o=await this.countTraceEvents(e),s={sessionId:e,label:t.label,createdAt:Date.now(),traceSeq:o,conversation:{version:w,id:e,entries:a,metadata:i.metadata,leafId:i.leafId},files:t.files?await Ot(n.workspaceDir,t.files):void 0},c=await this.deps.checkpointStore.append(e,s);return{...c.entry,seq:c.seq}}async listCheckpoints(e){if(!this.deps.checkpointStore)return[];let t=[];for await(let n of this.deps.checkpointStore.read(e))t.push({...n.entry,seq:n.seq});return t}async restoreCheckpoint(e,t,n=`both`){if(!this.deps.checkpointStore)throw Error(`restoreCheckpoint requires a checkpointStore`);let r=this.deps.getSession(e);if(!r)throw Error(`Cannot restore unknown session "${e}"`);if(r.isBusy)throw Error(`Cannot restore/rollback session "${e}" while a prompt is in flight (session busy); abort the active prompt before rewinding`);let i=await this.readCheckpoint(e,t);if(n===`conversation`||n===`both`){let t=r.session;if(t instanceof C){let n=await this.ensureHydrated(e,i.conversation.entries,`checkpoint restore`);t.restoreEntries(n,i.conversation.metadata,i.conversation.leafId)}}(n===`code`||n===`both`)&&i.files&&await kt(r.workspaceDir,i.files)}async ensureHydrated(e,t,n){if(!le(t))return[...t];if(!this.deps.hydrateEntries)throw Error(`${n}: entries contain stripped compaction replacements but no hydrateEntries capability is wired (RFC-160 D4); refusing to proceed with stripped state`);return this.deps.hydrateEntries(e,t)}async readCheckpoint(e,t){if(!this.deps.checkpointStore)throw Error(`checkpoint operations require a checkpointStore`);let n;for await(let r of this.deps.checkpointStore.read(e,{from:t,to:t+1}))n=r.entry;if(!n)throw Error(`Checkpoint seq=${t} not found for session "${e}"`);if(n.conversation.version!==w)throw Error(`Checkpoint seq=${t} for session "${e}" has incompatible snapshot version ${n.conversation.version} (expected ${w})`);return n}async rollbackToCheckpoint(e,t,n=`both`){let r=await this.readCheckpoint(e,t);await this.restoreCheckpoint(e,t,n),this.deps.traceStore&&await this.deps.traceStore.truncate(e,r.traceSeq),this.deps.logger.info({sessionId:e,seq:t,traceSeq:r.traceSeq,mode:n},`Session rolled back`)}async forkFromCheckpoint(e,t,n){let r=this.deps.getSession(e),i=this.deps.getConfig(e);if(!r||!i)throw Error(`Cannot fork unknown session "${e}"`);let a=await this.readCheckpoint(e,t),o=n??crypto.randomUUID();if(this.deps.ensureCapacity(o),this.deps.traceStore)for await(let t of this.deps.traceStore.read(e,{to:a.traceSeq}))await this.deps.traceStore.append(o,t.entry);if(this.deps.checkpointStore)for await(let t of this.deps.checkpointStore.read(e))t.entry.traceSeq<=a.traceSeq&&await this.deps.checkpointStore.append(o,{...t.entry,sessionId:o});let s=Tt(o,e,await this.ensureHydrated(e,a.conversation.entries,`forkFromCheckpoint`),a.conversation.metadata,a.conversation.leafId),c=await this.deps.adoptForkedSession(s,{...i});return this.deps.logger.info({sessionId:o,sourceId:e,fromSeq:t},`Session forked from checkpoint`),c}async countTraceEvents(e){if(!this.deps.traceStore)return 0;let t=await this.deps.traceStore.count?.(e);if(t!==void 0)return t;let n=0;for await(let t of this.deps.traceStore.read(e))n++;return n}async replayTrace(e,t,n=0){if(!this.deps.traceStore)return[];let r={from:n,to:t===void 0?void 0:t+1},i=[];for await(let t of this.deps.traceStore.read(e,r))i.push(t.entry);return i}async traceback(e,t){let n=(await this.listCheckpoints(e)).filter(e=>e.traceSeq<=t).reduce((e,t)=>e===void 0||t.traceSeq>e.traceSeq?t:e,void 0),r=n?.traceSeq??0,i=n?Mt(n.conversation):[],a=await this.replayTrace(e,t,r);return{toSeq:t,baselineCheckpointSeq:n?.seq??null,fromTraceSeq:r,events:a,messages:Ft(i,a)}}};const I={healthy:1,warning:2,critical:4};var Ut=class{level=`healthy`;setLevel(e){this.level=e}get currentLevel(){return this.level}effectiveMaxMessages(e){return Math.max(1,Math.floor(e/I[this.level]))}effectiveMaxBytes(e){return Math.max(1,Math.floor(e/I[this.level]))}};const Wt=2e3;var Gt=class{gaps=new Map;constructor(e){this.deps=e}async detect(e,t){let n=this.deps.traceStore;if(!n)return;let r=t.entries[t.entries.length-1]?.timestamp??0;if(r!==0)try{let t=await n.count?.(e.id)??void 0,i=t!==void 0&&t>Wt?{from:t-Wt}:void 0,a=0,o=0;for await(let t of n.read(e.id,i)){let e=t.entry;e.kind!==`lifecycle`||e.node!==`turn.end`||e.ts>r+1e4&&(o++,e.ts>a&&(a=e.ts))}if(o===0)return;this.deps.logger.warn({sessionId:e.id,lostTurns:o,lastPersistedAt:r,lastTraceAt:a},`RFC-305 D3: crash gap detected — turns recorded in trace but never persisted to DB (lost in previous abnormal termination)`);let s={lostTurns:o,lastPersistedAt:r,lastTraceAt:a};this.gaps.set(e.id,s),this.deps.onDetected?.(e,s)}catch(t){this.deps.logger.debug?.({sessionId:e.id,err:t instanceof Error?t.message:String(t)},`RFC-305 D3: crash-gap reconciliation skipped (trace read failed)`)}}consume(e){let t=this.gaps.get(e);return this.gaps.delete(e),t}forget(e){this.gaps.delete(e)}};function Kt(e,t){return t<=0?1:Math.min(1,e/t)}function L(e){let t=e.config?.totalBytes??Fe,n=e.config?.minPerSessionBytes??Pe,r=e.config?.maxPerSessionBytes??Ne,i=Kt(e.currentTotalResidentBytes,t),a=Math.max(1,e.activeSessionCount),o=Math.floor(t*(1-i)/a),s=Math.max(n,Math.min(o,r)),c=Math.max(Math.floor(n/e.pressureDivisor),Math.floor(s/e.pressureDivisor));return{maxBytesPerSession:Math.max(1,c),globalPressure:Number(i.toFixed(4)),isGlobalPressure:i>=.85}}function qt(e,t,n){return n?e.wouldByteTrimTouchActiveContext(Math.max(1,t)):e.wouldTrimTouchActiveContext(Math.max(1,t))}const Jt=.9;function Yt(e){let t=e.agentSession.session,n=L({activeSessionCount:e.activeSessionCount,currentTotalResidentBytes:e.currentTotalResidentBytes,pressureDivisor:e.pressureDivisor,config:e.residencyConfig}),r=t instanceof C?t.messageCount:0,i=Math.max(1,Math.floor(e.maxMessages*Jt)),a=Math.max(1,Math.floor(n.maxBytesPerSession*Jt));if(!(t instanceof C))return{action:`none`,maxBytes:n.maxBytesPerSession,isLossy:!1,boundaryLimited:!1,activeOversized:!1};let o=r>e.maxMessages&&qt(t,i,!1),s=t.estimatedContentBytes>n.maxBytesPerSession&&qt(t,a,!0),c=o||s,l=(e.lossyFailureCount??0)>=3;if(c&&!l)return{action:`request-compaction`,maxBytes:n.maxBytesPerSession,isLossy:!1,boundaryLimited:!1,activeOversized:!1};if(!c){let i=t.estimatedContentBytes>n.maxBytesPerSession,a=r>e.maxMessages;if(!i&&!a)return{action:`none`,maxBytes:n.maxBytesPerSession,isLossy:!1,boundaryLimited:!1,activeOversized:!1}}return{action:`trim`,maxBytes:n.maxBytesPerSession,isLossy:l&&c,boundaryLimited:!1,activeOversized:!1}}const R=.9;var Xt=class{evalBaseline=new Map;publishBaseline=new Map;compactionFailures=new Map;compactionRequestBaseline=new Map;constructor(e){this.deps=e}evaluate(e){let t={action:`none`,removedCount:0,lossy:!1,shouldPublish:!1,trigger:`count`,capValue:0},n=e.session;if(!(n instanceof C))return t;let r=e.id,i=this.deps.residencyGovernor,a=i?i.effectiveMaxMessages(this.deps.maxHistoryMessages):this.deps.maxHistoryMessages,o=Yt({agentSession:e,activeSessionCount:this.deps.countActiveSessions(),currentTotalResidentBytes:this.deps.sumEstimatedContentBytes(),pressureDivisor:i?this.deps.levelDivisor[i.currentLevel]:1,residencyConfig:this.deps.getResidencyConfig?.(),maxMessages:a,lossyFailureCount:this.compactionFailures.get(r)}),s=o.maxBytes,c=e=>e.role!==`tool_result`,l=n.messageCount;if(o.action===`request-compaction`)return this.deps.requestCompaction(e,l),this.deps.logger.debug({sessionId:r,msgCount:l},`[cap] trim would touch active context; requested compaction first, skipping trim this round (RFC-321 R12)`),this.evalBaseline.set(r,l),{...t,action:`request-compaction`};if(o.action===`none`)return this.evalBaseline.set(r,l),t;let u=o.isLossy,d=(this.compactionFailures.get(r)??0)>=3,f=Math.max(1,Math.floor(a*R)),p=Math.max(1,Math.floor(s*R)),m=l>a?n.capStoredHistory(f,c):{capped:!1,removedCount:0,boundaryLimited:!1,activeOversized:!1},h=n.estimatedContentBytes>s?n.capStoredHistoryByBytes(p,c):{capped:!1,removedCount:0,boundaryLimited:!1,activeOversized:!1},g=m.removedCount+h.removedCount,_=u&&g>0;u&&this.compactionFailures.delete(r),(m.boundaryLimited||h.boundaryLimited)&&this.deps.logger.debug({sessionId:r,removedCount:g,msgCount:l,activeOversized:m.activeOversized||h.activeOversized},`[cap] trimming stopped at active compaction boundary (RFC-321 R4); may remain above cap`),(m.activeOversized||h.activeOversized)&&!d&&(this.deps.requestCompaction(e,l),this.deps.logger.debug({sessionId:r,msgCount:l,bytes:n.estimatedContentBytes},`[cap] active region itself exceeds cap (RFC-321 activeOversized); compaction needed`));let v=this.publishBaseline.get(r),y=Math.max(1,Math.floor(a*(1-R))),b=!_&&v!==void 0&&l<v+y,x=g>0&&!b,S=i&&i.currentLevel!==`healthy`?`memory-pressure`:h.removedCount>m.removedCount?`bytes`:`count`;return x&&this.publishBaseline.set(r,l),this.evalBaseline.set(r,l-g),{action:`trim`,removedCount:g,lossy:_,shouldPublish:x,trigger:S,capValue:S===`bytes`?s:a}}shouldEvaluateInline(e){let t=e.session;if(!(t instanceof C))return!1;let n=t.messageCount,r=this.evalBaseline.get(e.id);return r===void 0?(this.evalBaseline.set(e.id,n),!1):n-r>=this.deps.inlineCheckInterval}shouldRequestCompaction(e,t){let n=this.compactionRequestBaseline.get(e);return n!==void 0&&t<n+this.deps.inlineCheckInterval?!1:(this.compactionRequestBaseline.set(e,t),!0)}onCompactionSucceeded(e){this.compactionFailures.delete(e)}onCompactionFailed(e){let t=(this.compactionFailures.get(e)??0)+1;return this.compactionFailures.set(e,t),t}forget(e){this.evalBaseline.delete(e),this.publishBaseline.delete(e),this.compactionFailures.delete(e),this.compactionRequestBaseline.delete(e)}};function z(e,t){if(e===t)return!0;if(typeof e!=typeof t||e===null||t===null||typeof e!=`object`||typeof t!=`object`||Array.isArray(e)!==Array.isArray(t))return!1;if(Array.isArray(e)&&Array.isArray(t))return e.length===t.length?e.every((e,n)=>z(e,t[n])):!1;let n=e,r=t,i=Object.keys(n),a=Object.keys(r);return i.length===a.length?i.every(e=>Object.hasOwn(r,e)&&z(n[e],r[e])):!1}function B(e,t){return e===void 0&&t===void 0?!0:e===void 0||t===void 0||e.length!==t.length?!1:z(e,t)}var Zt=class{constructor(e){this.deps=e}async restore(e,t,n){let r=this.deps.panelStateStore;if(!r)return;let i=await r.loadAll(n);if(i){i.todoList!==void 0&&e.setTodoList(i.todoList),i.editedFiles!==void 0&&e.setEditedFiles(i.editedFiles),i.subagents!==void 0&&e.setSubagents(i.subagents),i.drafts!==void 0&&e.setDrafts(i.drafts),i.turnSummaries!==void 0&&e.setTurnSummaries(i.turnSummaries);return}let a=t.metadata.config,o=a?.todoList,s=a?.editedFiles,c=a?.subagents,l=a?.drafts;!o&&!s&&!c&&!l||(o&&e.setTodoList(o),s&&e.setEditedFiles(s),c&&e.setSubagents(c),l&&e.setDrafts(l),B(o,e.getTodoList())&&B(s,e.getEditedFiles())&&B(c,e.getSubagents())&&B(l,e.getDrafts())?await r.saveAll(n,{sessionId:n,todoList:o??[],editedFiles:s??[],subagents:c??[],drafts:l??[]}):this.deps.logger.warn({sessionId:n},`PanelState migration verification failed, using legacy in-memory data without persisting`))}},V=class{constructor(e,t){this.persistence=e,this.pasteStatePersistence=t}async getTodoList(e){return(await this.persistence.load(e))?.todoList}async setTodoList(e,t){let n=await this.loadOrInit(e);n.todoList=t,await this.persistence.save(n)}async getEditedFiles(e){return(await this.persistence.load(e))?.editedFiles}async setEditedFiles(e,t){let n=await this.loadOrInit(e);n.editedFiles=t,await this.persistence.save(n)}async getSubagents(e){return(await this.persistence.load(e))?.subagents}async setSubagents(e,t){let n=await this.loadOrInit(e);n.subagents=t,await this.persistence.save(n)}async getDrafts(e){return(await this.persistence.load(e))?.drafts}async setDrafts(e,t){let n=await this.loadOrInit(e);n.drafts=t,await this.persistence.save(n)}async getTurnSummaries(e){return(await this.persistence.load(e))?.turnSummaries}async setTurnSummaries(e,t){let n=await this.loadOrInit(e);n.turnSummaries=t,await this.persistence.save(n)}async getPaste(e){if(!this.pasteStatePersistence)return{sessionId:e,entries:[],nextId:1};try{return ee(e,await this.pasteStatePersistence.load(e))}catch{return{sessionId:e,entries:[],nextId:1}}}async setPaste(e,t){if(!this.pasteStatePersistence)return!1;if(t.sessionId!==e)throw Error(`PanelStateStore.setPaste: snapshot.sessionId (${t.sessionId}) !== sessionId (${e})`);try{return await this.pasteStatePersistence.save(t),!0}catch{return!1}}async deletePaste(e){if(!this.pasteStatePersistence)return!1;try{return await this.pasteStatePersistence.delete(e)}catch{return!1}}async loadAll(e){return this.persistence.load(e)}async saveAll(e,t){if(t.sessionId!==e)throw Error(`PanelStateStore.saveAll: snapshot.sessionId (${t.sessionId}) !== sessionId (${e})`);await this.persistence.save(t)}async loadOrInit(e){return await this.persistence.load(e)??{sessionId:e}}};function Qt(e){let t={};return e.interactive!==void 0&&(t.interactive=e.interactive),e.listable!==void 0&&(t.listable=e.listable),e.depth!==void 0&&(t.depth=e.depth),e.agentName!==void 0&&(t.agentName=e.agentName),e.thinkingLevel!==void 0&&(t.thinkingLevel=e.thinkingLevel),e.maxToolTurnExtensions!==void 0&&(t.maxToolTurnExtensions=e.maxToolTurnExtensions),e.transient!==void 0&&(t.transient=e.transient),e.model?.id&&(t.modelId=e.model.id),e.systemTail!==void 0&&(t.systemTail=e.systemTail),e.workspaceDir!==void 0&&(t.workspaceDir=e.workspaceDir),e.maxToolTurns!==void 0&&(t.maxToolTurns=e.maxToolTurns),e.permissionAlwaysAllow&&e.permissionAlwaysAllow.length>0&&(t.permissionAlwaysAllow=[...e.permissionAlwaysAllow]),e.availableModels&&e.availableModels.length>0&&(t.availableModels=[...e.availableModels]),t}function $t(e,t){if(!t)return e;let n={...e};return t.interactive!==void 0&&(n.interactive=t.interactive),t.listable!==void 0&&(n.listable=t.listable),t.depth!==void 0&&(n.depth=t.depth),t.agentName!==void 0&&(n.agentName=t.agentName),t.thinkingLevel!==void 0&&(n.thinkingLevel=t.thinkingLevel),t.maxToolTurnExtensions!==void 0&&(n.maxToolTurnExtensions=t.maxToolTurnExtensions),t.transient!==void 0&&(n.transient=t.transient),t.systemTail!==void 0&&(n.systemTail=t.systemTail),t.workspaceDir!==void 0&&(n.workspaceDir=t.workspaceDir),t.maxToolTurns!==void 0&&(n.maxToolTurns=t.maxToolTurns),t.permissionAlwaysAllow!==void 0&&(n.permissionAlwaysAllow=[...t.permissionAlwaysAllow]),t.availableModels!==void 0&&(n.availableModels=[...t.availableModels]),n}var en=class{saveChains=new Map;crashGapDetector;panelStateRestorer;turnSaveState=new Map;leaseDeniedState=new Map;remoteRevisions=new Map;residencyCoordinator;constructor(e){this.deps=e,this.residencyCoordinator=new Xt({logger:e.logger,...e.residencyGovernor?{residencyGovernor:e.residencyGovernor}:{},...e.getResidencyConfig?{getResidencyConfig:e.getResidencyConfig}:{},countActiveSessions:()=>this.countActiveSessionsForAllocation(),sumEstimatedContentBytes:()=>this.sumEstimatedContentBytes(),requestCompaction:(e,t)=>this.requestEscapeValveCompaction(e,t),maxHistoryMessages:Me,inlineCheckInterval:200,levelDivisor:I}),this.panelStateRestorer=new Zt({...e.panelStateStore?{panelStateStore:e.panelStateStore}:{},logger:e.logger}),this.crashGapDetector=new Gt({traceStore:e.traceStore,logger:e.logger,onDetected:(e,t)=>{e.publish({"session.crash-gap-detected":[{type:`session.crash-gap-detected`,sessionId:e.id,lostTurns:t.lostTurns,lastPersistedAt:t.lastPersistedAt,lastTraceAt:t.lastTraceAt}]})}})}applyResidencyCaps(e){let t=this.residencyCoordinator.evaluate(e);t.shouldPublish&&e.publish({"session.history-capped":[{type:`session.history-capped`,sessionId:e.id,removedCount:t.removedCount,trigger:t.trigger,capValue:t.capValue,...t.lossy?{lossy:!0}:{}}]})}requestEscapeValveCompaction(e,t){this.residencyCoordinator.shouldRequestCompaction(e.id,t)&&(e.compactionPending=e.compactNow().then(t=>(t.compacted?this.residencyCoordinator.onCompactionSucceeded(e.id):this.residencyCoordinator.onCompactionFailed(e.id),this.deps.logger.info({sessionId:e.id,compacted:t.compacted,before:t.before,after:t.after},`[cap] escape-valve compaction requested (RFC-321 R12 compaction-first)`),t)).catch(t=>{let n=this.residencyCoordinator.onCompactionFailed(e.id);return this.deps.logger.warn({sessionId:e.id,error:t,failures:n},`[cap] escape-valve compaction failed; lossy trim allowed after threshold`),{compacted:!1,before:0,after:0}}))}maybeInlineCapEval(e){this.residencyCoordinator.shouldEvaluateInline(e)&&this.applyResidencyCaps(e)}track(e,t){if(!this.deps.autoPersist||t)return;let n=this.deps.persistence,r=e.session;r instanceof C&&typeof n.getPersistedCursor==`function`&&r.setReplacementStripEligibility(t=>{let i=n.getPersistedCursor(e.id);if(!i)return this.deps.logger.debug?.({sessionId:e.id,entryId:t},`RFC-160 D2a: skip runtime replacement strip (no persisted cursor yet)`),!1;let a=!1;for(let n of r.entries())if(n.id===t&&(a=!0),n.id===i)return a||this.deps.logger.debug?.({sessionId:e.id,entryId:t,cursor:i},`RFC-160 D2a: skip runtime replacement strip (entry beyond persisted cursor)`),a;return!1});let i=t=>{if(t instanceof Error&&t.name===`SessionWriteLeaseDeniedError`){let t=this.leaseDeniedState.get(e.id)===!0;return this.leaseDeniedState.set(e.id,!0),t||e.publish({"session.write-lease-denied":[{type:`session.write-lease-denied`,sessionId:e.id}]}),!0}return!1},a=()=>{this.leaseDeniedState.get(e.id)===!0&&(this.leaseDeniedState.set(e.id,!1),e.publish({"session.write-lease-restored":[{type:`session.write-lease-restored`,sessionId:e.id}]}))},o=()=>{this.enqueue(e.id,async()=>{try{await this.doSave(e.id),a()}catch(t){i(t)||this.deps.logger.warn({sessionId:e.id,err:t instanceof Error?t.message:String(t)},`Session auto-persist failed`)}})},s=()=>{let t=e.id;this.enqueue(t,async()=>{try{await this.doSaveEntries(t),a()}catch(e){i(e)||this.deps.logger.warn({sessionId:t,err:e instanceof Error?e.message:String(e)},`Session turn-level auto-persist failed`)}})};e.subscribe(`prompt.end`,o),e.subscribe(`error`,o),e.subscribe(`session.cleared`,()=>{this.enqueue(e.id,async()=>{try{await this.doSave(e.id),a();let t=e.session;if(t instanceof C){let n=t.purgeClearedHistory();(n.removedCount>0||n.strippedReplacements>0)&&this.deps.logger.debug?.({sessionId:e.id,...n},`RFC-194: purged cleared history after successful save`)}}catch(t){i(t)||this.deps.logger.warn({sessionId:e.id,err:t instanceof Error?t.message:String(t)},`Session clear-persist failed (purge skipped, residency left to RFC-178 caps)`)}})}),e.subscribe(`turn.end`,()=>{let t=e.id;if(this.maybeInlineCapEval(e),(this.deps.turnFlush??`incremental`)===`snapshot`){let e=Date.now(),n=this.turnSaveState.get(t);if(!n){this.turnSaveState.set(t,{lastSaveAt:e,turnsSinceSave:1});return}n.turnsSinceSave++;let r=e-n.lastSaveAt;if(n.turnsSinceSave<5&&r<3e4)return;n.lastSaveAt=e,n.turnsSinceSave=0}s()}),e.setInputBoundaryFlusher?e.setInputBoundaryFlusher(()=>this.requestInputBoundaryFlush(e,t)):this.deps.logger.debug?.({sessionId:e.id},`RFC-336 D2: input-boundary flush disabled (session lacks setInputBoundaryFlusher)`)}async flushPending(e){let t=this.saveChains.get(e);t&&await t.catch(t=>{this.deps.logger.warn({sessionId:e,err:t instanceof Error?t.message:String(t)},`flushPending: pending save chain settled with failure (already logged by the job itself; surfaced here for removeSession/restore callers)`)}),this.leaseDeniedState.delete(e),this.turnSaveState.delete(e),this.remoteRevisions.delete(e)}countActiveSessionsForAllocation(){let e=this.deps.listSessionIds(),t=0;for(let n of e)this.deps.getConfig?.(n)?.transient!==!0&&t++;return Math.max(1,t)}sumEstimatedContentBytes(){let e=0;for(let t of this.deps.listSessionIds()){if(this.deps.getConfig?.(t)?.transient===!0)continue;let n=this.deps.getSession(t);n?.session instanceof C&&(e+=n.session.estimatedContentBytes)}return e}forgetSession(e){this.leaseDeniedState.delete(e),this.residencyCoordinator.forget(e),this.crashGapDetector.forget(e),this.turnSaveState.delete(e),this.remoteRevisions.delete(e)}forgetEvictedSession(e){this.deps.getSession(e)||this.forgetSession(e)}isTransient(e){return this.deps.getConfig?.(e)?.transient===!0}async save(e){return this.enqueue(e,()=>this.doSave(e))}requestInputBoundaryFlush(e,t){if(!this.deps.autoPersist||t||(this.deps.turnFlush??`incremental`)===`snapshot`)return;let n=e.id;this.enqueue(n,async()=>{try{await this.doSaveEntries(n)}catch(e){if(e instanceof Error&&e.name===`SessionWriteLeaseDeniedError`)return;this.deps.logger.warn({sessionId:n,err:e instanceof Error?e.message:String(e)},`Input-boundary flush failed (RFC-336 D2; falls back to turn/prompt-end persistence)`)}})}precreateSessionRow(e,t){if(!this.deps.autoPersist||t)return;let n=e.id;this.enqueue(n,async()=>{try{await this.doSaveEntries(n)}catch(e){if(e instanceof Error&&e.name===`SessionWriteLeaseDeniedError`)return;this.deps.logger.warn({sessionId:n,err:e instanceof Error?e.message:String(e)},`Session row pre-creation failed (RFC-336 D1; falls back to first-turn persistence)`)}})}saveSnapshot(e,t,n){if(this.isTransient(e))return n?.(),Promise.resolve();let r=this.mergeSnapshotConfig(e,t.metadata),i=this.enqueue(e,async()=>{let n={version:w,id:e,...t,metadata:r};if(this.isRemoteCasPersistence()?await this.saveRemoteWithCas(e,n):await this.deps.persistence.save(n),this.deps.panelStateStore){let t=this.deps.getSession(e)?.session;t&&await this.deps.panelStateStore.saveAll(e,{sessionId:e,todoList:t.getTodoList(),editedFiles:t.getEditedFiles(),subagents:t.getSubagents(),drafts:t.getDrafts(),turnSummaries:t.getTurnSummaries()})}});return n&&i.then(n,n),i}mergeSnapshotConfig(e,t){let n=this.deps.getConfig?.(e),r=n?Qt(n):void 0,i=t.config?.inputHistory,a=r||i?{...r,...i?{inputHistory:i}:{}}:void 0;return a?{...t,config:a}:t}enqueue(e,t){let n=(this.saveChains.get(e)??Promise.resolve()).catch(()=>{}).then(t);this.saveChains.set(e,n);let r=()=>{this.saveChains.get(e)===n&&this.saveChains.delete(e)};return n.then(r,r),n}async doSaveEntries(e){if(this.isTransient(e))return;let t=this.deps.getSession(e);if(!t)return;let n=t.session;if(n instanceof C){this.applyResidencyCaps(t);let r=n.toSnapshot(),i=this.mergeSnapshotConfig(n.id,r.metadata),a={version:w,id:n.id,...r,metadata:i};this.isRemoteCasPersistence()?await this.saveRemoteWithCas(e,a):await this.deps.persistence.save(a)}}isRemoteCasPersistence(){return typeof this.deps.persistence.saveWithRevision==`function`}async saveRemoteWithCas(e,t){let n=this.deps.persistence,r=this.remoteRevisions.get(e);try{let i=await n.saveWithRevision(t,r);this.remoteRevisions.set(e,i)}catch(i){if(!(i instanceof oe))throw i;this.deps.logger.warn({sessionId:e,expectedRevision:r,serverRevision:i.info.revision},`Remote session CAS conflict; reloading + rebasing for one retry`);let a=await n.loadWithRevision(e);if(!a){let r=await n.saveWithRevision(t,0);this.remoteRevisions.set(e,r);return}let o=this.rebaseSnapshotAgainstRemote(t,a.snapshot),s=await n.saveWithRevision(o,a.revision);this.remoteRevisions.set(e,s)}}rebaseSnapshotAgainstRemote(e,t){let n=new Set(t.entries.map(e=>e.id)),r=e.entries.filter(e=>!n.has(e.id));return{version:w,id:e.id,entries:[...t.entries,...r],metadata:e.metadata,leafId:e.leafId??t.leafId}}async doSave(e){if(await this.doSaveEntries(e),this.isTransient(e))return;let t=this.deps.getSession(e);if(!t)return;let n=t.session;this.deps.panelStateStore&&await this.deps.panelStateStore.saveAll(e,{sessionId:e,todoList:n.getTodoList(),editedFiles:n.getEditedFiles(),subagents:n.getSubagents(),drafts:n.getDrafts(),turnSummaries:n.getTurnSummaries()})}async saveAll(){let e=[...this.deps.listSessionIds()].filter(e=>{let t=this.deps.getSession(e)?.session;return!(t instanceof C)||t.entries().length>0});(await Promise.allSettled(e.map(e=>this.save(e)))).forEach((t,n)=>{t.status===`rejected`&&this.deps.logger.warn({sessionId:e[n],err:t.reason instanceof Error?t.reason.message:String(t.reason)},`saveAll: a session failed to persist (others unaffected)`)}),await Promise.allSettled([...this.saveChains.values()])}async restore(e){if(!this.deps.configProvider)return null;let t=this.deps.getSession(e);if(t)return t;await this.flushPending(e);let n=this.isRemoteCasPersistence()?await this.deps.persistence.loadWithRevision(e):null,r=n?.snapshot??(n===null&&this.isRemoteCasPersistence()?null:await this.deps.persistence.load(e));if(!r)return null;if(r.version!==w)return this.deps.logger.warn({sessionId:e,version:r.version,expected:w},`Session snapshot version mismatch, skipped`),null;if(!this.deps.canAccommodate(e))throw Error(`Max sessions reached, cannot restore ${e}.`);let i=new C(r.id);i.restoreEntries(r.entries,{...r.metadata,lastActiveAt:Date.now()},r.leafId);let a=$t(this.deps.configProvider(r.metadata.config?.agentName,r.metadata.config?.modelId),r.metadata.config),o=await this.deps.adoptRestoredSession(i,a);return r.metadata.archived&&o.archive(),await this.panelStateRestorer.restore(i,r,e),n&&this.remoteRevisions.set(e,n.revision),this.track(o,!1),await this.crashGapDetector.detect(o,r),this.deps.logger.info({sessionId:e},`Session restored`),o}consumeCrashGap(e){let t=this.crashGapDetector.consume(e);return t?{lostTurns:t.lostTurns}:void 0}async restoreAll(){if(!this.deps.configProvider)return 0;let e=this.deps.capacityLeft();if(e===0){let e=(await this.deps.persistence.list()).filter(e=>!this.deps.hasSession(e)).length;return e>0&&this.deps.logger.info({candidates:e},`Session pool full, restoreAll skipped (restore on demand)`),0}let t=await this.deps.persistence.listRecentMeta(e),n=[],r=0;for(let e of t){if(this.deps.hasSession(e))continue;let t;try{if(this.isRemoteCasPersistence()){let n=await this.deps.persistence.loadWithRevision(e);t=n?{snapshot:n.snapshot,revision:n.revision}:null}else{let n=await this.deps.persistence.load(e);t=n?{snapshot:n}:null}}catch(t){this.deps.logger.warn({sessionId:e,err:t instanceof Error?t.message:String(t)},`restoreAll: a session snapshot failed to load (skipped, others unaffected)`);continue}if(!t)continue;let r=t.snapshot;if(r.version!==w){this.deps.logger.warn({sessionId:e,version:r.version,expected:w},`Session snapshot version mismatch, skipped`);continue}n.push(t)}let i=this.deps.capacityLeft();for(;n.length>i;)n.pop(),r++;r>0&&this.deps.logger.info({skipped:r,capacity:i},`Sessions exceeding pool capacity left on storage (restore on demand)`);let a=0,o=null;for(let e of n){let{snapshot:t}=e;if(!this.deps.hasSession(t.id))try{let n=new C(t.id);n.restoreEntries(t.entries,{...t.metadata,lastActiveAt:Date.now()},t.leafId);let r=$t(this.deps.configProvider(t.metadata.config?.agentName,t.metadata.config?.modelId),t.metadata.config),i=await this.deps.adoptRestoredSession(n,r);t.metadata.archived&&i.archive(),await this.panelStateRestorer.restore(n,t,t.id),e.revision!==void 0&&this.remoteRevisions.set(t.id,e.revision),this.track(i,!1),await this.crashGapDetector.detect(i,t),a++,o===null&&(o=t.id)}catch(e){this.deps.logger.warn({sessionId:t.id,err:e instanceof Error?e.message:String(e)},`restoreAll: 单条会话重建失败(跳过,余者不受影响)`)}}return o&&this.deps.setActiveIfNone(o),this.deps.logger.info({count:a},`Sessions restored`),a}},H=class{panelStateStoreRef;sessions=new Map;configs=new Map;persistence;maxSessions;idleTimeoutMs;threshold;activeSessionId;stream;hookRegistry;logger;devtools;memory;traceStore;checkpointStore;clock;residencyGovernor;getResidencyConfig;configProvider;listColdSessionsOverride;isSessionWriteLocked;inspectSessionWriteLeaseFn;forceReleaseSessionWriteLeaseFn;autoPersist;timeTravel;persistenceSync;constructor(e,t,n=!1){this.autoPersist=n,this.stream=i(e.providerRegistry),this.hookRegistry=e.hookRegistry,this.logger=e.logger,this.devtools=e.devtools,this.memory=e.memory,this.traceStore=e.traceStore,this.checkpointStore=e.checkpointStore,this.clock=e.clock,this.residencyGovernor=e.residencyGovernor,this.getResidencyConfig=e.getResidencyConfig,this.configProvider=e.configProvider,this.listColdSessionsOverride=e.listColdSessionsOverride,this.isSessionWriteLocked=e.isSessionWriteLocked,this.inspectSessionWriteLeaseFn=e.inspectSessionWriteLease,this.forceReleaseSessionWriteLeaseFn=e.forceReleaseSessionWriteLease,this.persistence=t;let r=e.maxSessions??ce;this.maxSessions=r,this.idleTimeoutMs=e.idleTimeoutMs??se,this.threshold=Math.max(0,Math.min(e.threshold??r,r)),this.timeTravel=new Ht({logger:this.logger,traceStore:this.traceStore,checkpointStore:this.checkpointStore,getSession:e=>this.sessions.get(e),getConfig:e=>this.configs.get(e),createSession:(e,t)=>this.createSession(e,t),ensureCapacity:e=>{if(this.sessions.has(e))throw Error(`Session with ID ${e} already exists.`);this.prepareCapacity(e)},adoptForkedSession:(e,t)=>this.adoptForkedSession(e,t),...ue(this.persistence)?{hydrateEntries:(e,t)=>this.persistence.hydrateReplacements(e,t)}:{}}),this.persistenceSync=new en({persistence:this.persistence,logger:this.logger,autoPersist:this.autoPersist,traceStore:this.traceStore,turnFlush:this.persistence.turnFlush,getSession:e=>this.sessions.get(e),getConfig:e=>this.configs.get(e),hasSession:e=>this.sessions.has(e),listSessionIds:()=>this.sessions.keys(),canAccommodate:e=>this.canAccommodate(e),capacityLeft:()=>Math.max(0,this.maxSessions-this.sessions.size),adoptRestoredSession:async(e,t)=>{let n=this.buildAgentSession(e,t);return this.sessions.set(e.id,n),this.configs.set(e.id,t),await this.hookRegistry.emit(`session.restored`,{sessionId:e.id,metadata:{}}),n.notifyCreated(),n},setActiveIfNone:e=>{this.activeSessionId||=e},configProvider:this.configProvider,panelStateStore:e.panelStateStore,residencyGovernor:e.residencyGovernor,getResidencyConfig:e.getResidencyConfig}),this.panelStateStoreRef=e.panelStateStore}get panelState(){return this.panelStateStoreRef}get active(){return this.activeSessionId?this.sessions.get(this.activeSessionId):void 0}getSessionPermissionAllow(e){return[...this.configs.get(e)?.permissionAlwaysAllow??[]]}setSessionPermissionAllow(e,t){let n=this.configs.get(e);if(n){if(t.length===0){delete n.permissionAlwaysAllow;return}n.permissionAlwaysAllow=[...t]}}getSessionAvailableModels(e){return[...this.configs.get(e)?.availableModels??[]]}setSessionAvailableModels(e,t){let n=this.configs.get(e);if(n){if(t.length===0){delete n.availableModels;return}n.availableModels=[...t]}}trackPersistence(e,t){this.persistenceSync.track(e,t)}precreateSessionRow(e,t){this.persistenceSync.precreateSessionRow(e,t)}async adoptForkedSession(e,t){let n=this.buildAgentSession(e,t);return this.sessions.set(e.id,n),this.configs.set(e.id,t),this.trackPersistence(n,!1),this.precreateSessionRow(n,!1),await this.hookRegistry.emit(`session.created`,{sessionId:e.id,metadata:{}}),n.notifyCreated(),n}buildAgentSession(e,t,n){let r=n??this.recordPorts(e.id);return new wt(e,{getCompactionTimeoutMs:()=>k(this.getResidencyConfig?.()).compactionTimeoutMs,model:t.model,titleModel:t.titleModel,modelResolution:t.modelResolution,agentName:t.agentName,depth:t.depth,interactive:t.interactive,listable:t.listable,transient:t.transient,retryAccelerate:t.retryAccelerate,streamRetry:t.streamRetry,networkDisconnectRetry:t.networkDisconnectRetry,lifecycleAsyncTimeoutMs:t.lifecycleAsyncTimeoutMs,systemPrompt:t.systemPrompt,systemTail:t.systemTail,tools:r.tools??t.tools,thinkingLevel:t.thinkingLevel,maxToolTurns:t.maxToolTurns,maxToolTurnExtensions:t.maxToolTurnExtensions,promptOutputTokenBudget:t.promptOutputTokenBudget,promptWallClockBudgetMs:t.promptWallClockBudgetMs,stallDetection:t.stallDetection,sessionCostBudgetUSD:t.sessionCostBudgetUSD,todoContinuation:t.todoContinuation,promptRefresh:t.promptRefresh,workspaceDir:t.workspaceDir,workspaceId:t.workspaceId,hookRegistry:this.hookRegistry,stream:r.stream??this.stream,logger:this.logger.child({sessionId:e.id}),devtools:this.devtools,memory:r.disableMemory?void 0:this.memory,recorder:r.recorder,nondetFlush:r.nondetFlush,clock:r.clock,describeImages:t.describeImages})}recordPorts(e){let t=this.traceStore;if(!t)return{clock:this.clock};let n=this.clock??Te,r=ye({sink:{append:n=>t.append(e,n).then(()=>void 0)},sessionId:e,clock:n}),i=_e({clock:n,random:De,id:Ee},r);return{clock:i.clock,recorder:r,nondetFlush:i.flushNondetBatch}}async createSession(e,t){let n=e.id??crypto.randomUUID();if(this.sessions.has(n))throw Error(`Session with ID ${n} already exists.`);this.prepareCapacity(n);let r=new C(n);r.setSdkVersion(de);let i=this.buildAgentSession(r,e,t);return this.sessions.set(n,i),this.configs.set(n,e),(e.transient??!1)||(this.activeSessionId=n),this.trackPersistence(i,e.transient??!1),this.precreateSessionRow(i,e.transient??!1),await this.hookRegistry.emit(`session.created`,{sessionId:n,metadata:{}}),i.notifyCreated(),this.logger.info({sessionId:n},`Session created`),i}replaySession(e,t,n={}){return this.timeTravel.replaySession(e,t,n)}createCheckpoint(e,t={}){return this.timeTravel.createCheckpoint(e,t)}listCheckpoints(e){return this.timeTravel.listCheckpoints(e)}restoreCheckpoint(e,t,n=`both`){return this.timeTravel.restoreCheckpoint(e,t,n)}rollbackToCheckpoint(e,t,n=`both`){return this.timeTravel.rollbackToCheckpoint(e,t,n)}forkFromCheckpoint(e,t,n){return this.timeTravel.forkFromCheckpoint(e,t,n)}replayTrace(e,t,n=0){return this.timeTravel.replayTrace(e,t,n)}traceback(e,t){return this.timeTravel.traceback(e,t)}getSession(e){return this.sessions.get(e)}getResidencyDiagnostics(){let e=0,t=0;for(let[n,r]of this.sessions){if(this.configs.get(n)?.transient)continue;let i=r.session;i instanceof C&&(e++,t+=i.estimatedContentBytes)}let n=this.residencyGovernor?.currentLevel??`healthy`,r=L({activeSessionCount:e,currentTotalResidentBytes:t,pressureDivisor:I[n],config:this.getResidencyConfig?.()});return{activeSessionCount:e,totalResidentBytes:t,globalPressure:r.globalPressure,isGlobalPressure:r.isGlobalPressure,maxBytesPerSession:r.maxBytesPerSession,pressureLevel:n}}listSessions(e){let t=Array.from(this.sessions.values());e?.workspaceId&&(t=t.filter(t=>t.workspaceId===e.workspaceId));let n=t.map(e=>{let t=e.session.metadata();return{id:e.id,title:Xe(t.title,e.session.messages(),e.id),messageCount:e.session.messages().length,createdAt:t.createdAt?new Date(t.createdAt):new Date,updatedAt:t.lastActiveAt?new Date(t.lastActiveAt):void 0,model:e.model.id,status:e.status,sdkVersion:t.sdkVersion,workspaceId:e.workspaceId,pinned:e.pinned,pinGroup:t.pinGroup,writeLocked:this.isSessionWriteLocked?.(e.id)??!1}});return n.sort((e,t)=>{let n=e.updatedAt?.getTime()??e.createdAt.getTime();return(t.updatedAt?.getTime()??t.createdAt.getTime())-n}),n}async listAllPersistedSessions(e){let t=e?.workspaceKey??`default`;if(this.listColdSessionsOverride)return this.listColdSessionsOverride(t);let n;try{n=await this.persistence.listPaginated({page:0,pageSize:100,sortBy:`lastActiveAt`,order:`desc`})}catch(e){return this.logger.warn({workspaceKey:t,err:e instanceof Error?e.message:String(e)},`listAllPersistedSessions: listPaginated failed (batch unavailable, not a per-session issue)`),[]}let r=[];for(let e of n.items)try{let t=await this.persistence.load(e);if(!t)continue;let n=t.metadata;r.push({id:e,title:n.title?.trim()||e.slice(0,8),messageCount:n.messageCount??0,createdAt:n.createdAt?new Date(n.createdAt):new Date,updatedAt:n.lastActiveAt?new Date(n.lastActiveAt):void 0,status:n.archived?`archived`:`idle`,pinned:n.pinned,pinGroup:n.pinGroup,writeLocked:this.isSessionWriteLocked?.(e)??!1})}catch(t){this.logger.warn({sessionId:e,err:t instanceof Error?t.message:String(t)},`listAllPersistedSessions: a session snapshot failed to load (skipped, others unaffected)`)}return r}backfillTitles(){let e=0,t=0;for(let n of this.sessions.values()){let r=n.session.metadata().titleSource;if(r===`custom`||r===`ai`){t++;continue}n.backfillTitle(),e++}return{triggered:e,skipped:t}}async archiveSession(e){let t=this.sessions.get(e);return t?(await this.persistenceSync.save(e),typeof this.persistence.archiveSession==`function`&&await this.persistence.archiveSession(e),t.archive(),!0):!1}async removeSession(e){let t=this.sessions.get(e);if(!t){await this.persistenceSync.flushPending(e);let t=await this.persistence.delete(e);return await this.clearSessionStores(e),t}return t.dispose(),this.sessions.delete(e),this.configs.delete(e),this.activeSessionId===e&&(this.activeSessionId=void 0),await this.persistenceSync.flushPending(e),await this.persistence.delete(e),await this.clearSessionStores(e),this.hookRegistry.emit(`session.deleted`,{sessionId:e,metadata:{reason:`removed`}}),this.logger.info({sessionId:e},`Session removed`),!0}async clearSessionStores(e){let t=async(t,n)=>{if(n)try{await n.clear(e)}catch(n){this.logger.warn({sessionId:e,err:n instanceof Error?n.message:String(n)},`Failed to clear ${t} on session removal`)}};await t(`trace store`,this.traceStore),await t(`checkpoint store`,this.checkpointStore)}async ensureEntriesHydrated(e,t,n){if(!le(t))return t;if(!ue(this.persistence))throw Error(`${n}: entries contain stripped compaction replacements but persistence lacks hydration capability (RFC-160 D4); refusing to fork stripped state`);return this.persistence.hydrateReplacements(e,t)}async forkSession(e,t){let n=this.sessions.get(e),r=this.configs.get(e);if(!n||!r)return;let i=n.session;if(!(i instanceof C))return;let a=t??crypto.randomUUID();this.prepareCapacity(a);let o=i.toSnapshot(),s=Tt(a,e,await this.ensureEntriesHydrated(e,o.entries,`forkSession`),o.metadata,o.leafId,this.clock),c={model:n.model,modelResolution:r.modelResolution,agentName:n.agentName===`agent`?void 0:n.agentName,systemPrompt:n.systemPrompt,systemTail:n.systemTail,tools:n.tools,thinkingLevel:n.thinkingLevel,maxToolTurns:n.maxToolTurns,maxToolTurnExtensions:n.maxToolTurnExtensions,promptOutputTokenBudget:n.promptOutputTokenBudget,promptWallClockBudgetMs:n.promptWallClockBudgetMs,todoContinuation:r.todoContinuation,promptRefresh:n.promptRefresh,workspaceDir:n.workspaceDir,workspaceId:n.workspaceId,depth:r.depth,transient:r.transient,interactive:r.interactive,retryAccelerate:r.retryAccelerate,streamRetry:r.streamRetry,networkDisconnectRetry:r.networkDisconnectRetry,lifecycleAsyncTimeoutMs:r.lifecycleAsyncTimeoutMs,permissionAlwaysAllow:r.permissionAlwaysAllow,availableModels:r.availableModels},l=await this.adoptForkedSession(s,c);return this.logger.info({sessionId:a,sourceId:e},`Session forked`),l}save(e){return this.persistenceSync.save(e)}saveAll(){return this.persistenceSync.saveAll()}inspectSessionWriteLease(e){return this.inspectSessionWriteLeaseFn?.(e)??{locked:!1}}forceReleaseSessionWriteLease(e){this.forceReleaseSessionWriteLeaseFn?.(e)}restore(e){return this.persistenceSync.restore(e)}consumeCrashGap(e){return this.persistenceSync.consumeCrashGap(e)}restoreAll(){return this.persistenceSync.restoreAll()}collectIdle(){let e=Date.now(),t=[];for(let[n,r]of this.sessions)if(!(r.isBusy||r.isPaused)&&e-r.session.metadata().lastActiveAt>this.idleTimeoutMs){let e=r.session,i=!1;if(this.autoPersist&&e instanceof C){let t=e.toSnapshot();t.entries.length>0&&(i=!0,this.persistenceSync.saveSnapshot(n,t,()=>{this.persistenceSync.forgetEvictedSession(n)}).catch(e=>{this.logger.warn({sessionId:n,err:e instanceof Error?e.message:String(e)},`Session snapshot flush on idle eviction failed`)}))}r.dispose(),this.sessions.delete(n),this.configs.delete(n),i||this.persistenceSync.forgetSession(n),this.activeSessionId===n&&(this.activeSessionId=void 0),this.hookRegistry.emit(`session.deleted`,{sessionId:n,metadata:{reason:`idle`}}),t.push(n)}return t}entryCount(e){let t=e.session;return t instanceof C?t.entries().length:t.messages().length}evictLeastRecent(e){let t=Array.from(this.sessions.entries()).filter(([t,n])=>t!==e&&t!==this.activeSessionId&&!n.isBusy&&!n.isPaused&&!(this.configs.get(t)?.transient??!1)).filter(([,e])=>this.autoPersist||this.entryCount(e)===0).sort(([,e],[,t])=>e.session.metadata().lastActiveAt-t.session.metadata().lastActiveAt);for(let[e,n]of t){if(this.sessions.size<this.maxSessions)break;let t=n.session,r=!1;if(this.autoPersist&&t instanceof C){let n=t.toSnapshot();n.entries.length>0&&(r=!0,this.persistenceSync.saveSnapshot(e,n,()=>{this.persistenceSync.forgetEvictedSession(e)}).catch(t=>{this.logger.warn({sessionId:e,err:t instanceof Error?t.message:String(t)},`Session snapshot flush on eviction failed`)}))}n.dispose(),this.sessions.delete(e),this.configs.delete(e),r||this.persistenceSync.forgetSession(e),this.hookRegistry.emit(`session.deleted`,{sessionId:e,metadata:{reason:`evicted`}}),this.logger.info({sessionId:e},`Session evicted (LRU)`)}}prepareCapacity(e){if(!this.sessions.has(e)&&(this.sessions.size+1>this.threshold&&this.collectIdle(),this.sessions.size>=this.maxSessions&&this.evictLeastRecent(e),this.sessions.size>=this.maxSessions))throw Error(`Max sessions (${this.maxSessions}) reached.`)}canAccommodate(e){return this.sessions.has(e)?!0:(this.sessions.size+1>this.threshold&&this.collectIdle(),this.sessions.size>=this.maxSessions&&this.evictLeastRecent(e),this.sessions.size<this.maxSessions)}dispose(){for(let e of this.sessions.values())e.dispose();this.sessions.clear(),this.configs.clear(),this.activeSessionId=void 0}};function tn(e){let{sessionDir:t}=e;if(!t)throw Error(`sessionDir is required for DiskSessionPool`);return new H(e,new re({baseDir:t}),!0)}function nn(e){let{sessionUrl:t}=e;if(!t)throw Error(`sessionUrl is required for RemoteSessionPool`);return new H(e,new ae({baseUrl:t,fetch:e.fetch,getAuth:e.getAuth,timeoutMs:e.timeoutMs??3e4,userId:e.userId,wsKey:e.wsKey}),!0)}function rn(e){return new H(e,new ie)}function an(e,t,n=!0){return new H(e,t,n)}function on(e,t){let n=new Ge;return n.register(Ke(e)),t&&n.register(qe(e,t)),n}function sn(e={}){let t=e.logger??d(`otto-runtime`,{level:`info`,destination:`stdout`}),n=e.providerRegistry??r(),i=e.hookRegistry??a({preset:`default`});e.hookRegistry||s(i);let o=e.storage??{kind:`in-memory`},c=e.traceStore===void 0,l=e.checkpointStore===void 0,{traceStore:u,checkpointStore:f}=Ue(o.kind===`disk`?{sessionDir:o.sessionDir}:o.kind===`remote`?{remoteLog:{baseUrl:o.sessionUrl,getAuth:o.getAuth,fetch:o.fetch,timeoutMs:o.timeoutMs}}:{},{traceStore:e.traceStore,checkpointStore:e.checkpointStore}),p=on(e.workspaceDir??process.cwd(),e.memory),m=(()=>{if(o.kind===`custom`&&(o.panelStatePersistence||o.pasteStatePersistence))return new V(o.panelStatePersistence??x(),o.pasteStatePersistence??S());let e=o.kind===`disk`?`${o.sessionDir}/panel-state`:o.kind===`custom`&&o.panelStateDir?o.panelStateDir:void 0;if(e!==void 0)return new V(new g({baseDir:e}),new _({baseDir:`${e}/paste`}))})(),h={hookRegistry:i,providerRegistry:n,logger:t,memory:e.memory,traceStore:u,checkpointStore:f,clock:e.clock,maxSessions:e.maxSessions,idleTimeoutMs:e.idleTimeoutMs,devtools:e.devtools,configProvider:e.configProvider,panelStateStore:m,residencyGovernor:e.residencyGovernor,getResidencyConfig:e.getResidencyConfig},v=o.kind===`disk`?tn({...h,sessionDir:o.sessionDir}):o.kind===`remote`?nn({...h,sessionUrl:o.sessionUrl,fetch:o.fetch,getAuth:o.getAuth,timeoutMs:o.timeoutMs,userId:o.userId,wsKey:o.wsKey}):o.kind===`custom`?an({...h,listColdSessionsOverride:o.listColdSessionsOverride,isSessionWriteLocked:o.isSessionWriteLocked,inspectSessionWriteLease:o.inspectSessionWriteLease,forceReleaseSessionWriteLease:o.forceReleaseSessionWriteLease},o.persistence,o.autoPersist??!0):rn(h);return{createSession:(e,t)=>v.createSession(e,t),sessions:v,hookRegistry:i,stream:v.stream,contextSources:p,traceStore:u,checkpointStore:f,clock:e.clock,dispose:async()=>{v.dispose(),c&&await u.close?.(),l&&await f.close?.(),o.kind===`custom`&&await o.onDispose?.()}}}function cn(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0&&r<=100?r:t}function U(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0?r:t}var ln=class{warnThresholdPct;hardThresholdPct;sampleIntervalMs;warningIntervalMs;criticalIntervalMs;warnCooldownMs;onWarning;onCritical;logger;now;postRestartGraceMs;ticker=null;lastLevel=`healthy`;lastWarningFiredAt;graceStartedAt;onCriticalDuringGrace;onLevelChange;onSample;disposed=!1;criticalTimeoutMs;onCriticalTimeout;criticalEnteredAt;criticalTimeoutFired=!1;constructor(e={}){this.warnThresholdPct=e.warnThresholdPct??cn(`OTTO_MEMORY_WARN_PCT`,70),this.hardThresholdPct=e.hardThresholdPct??cn(`OTTO_MEMORY_HARD_PCT`,85),this.sampleIntervalMs=e.sampleIntervalMs??U(`OTTO_MEMORY_SAMPLE_INTERVAL_MS`,3e4),this.warningIntervalMs=e.warningIntervalMs??U(`OTTO_MEMORY_WARNING_INTERVAL_MS`,1e4),this.criticalIntervalMs=e.criticalIntervalMs??U(`OTTO_MEMORY_CRITICAL_INTERVAL_MS`,5e3),this.warnCooldownMs=e.warnCooldownMs??3e5,this.postRestartGraceMs=e.postRestartGraceMs??6e5,this.criticalTimeoutMs=e.criticalTimeoutMs??U(`OTTO_MEMORY_CRITICAL_TIMEOUT_MS`,9e5),this.onWarning=e.onWarning,this.onCritical=e.onCritical,this.onCriticalDuringGrace=e.onCriticalDuringGrace,this.onLevelChange=e.onLevelChange,this.onSample=e.onSample,this.onCriticalTimeout=e.onCriticalTimeout,this.logger=e.logger,this.now=e.now??(()=>Date.now())}get currentLevel(){return this.lastLevel}setCallbacks(e){`onWarning`in e&&(this.onWarning=e.onWarning),`onCritical`in e&&(this.onCritical=e.onCritical),`onCriticalDuringGrace`in e&&(this.onCriticalDuringGrace=e.onCriticalDuringGrace),`onLevelChange`in e&&(this.onLevelChange=e.onLevelChange),`onSample`in e&&(this.onSample=e.onSample),`onCriticalTimeout`in e&&(this.onCriticalTimeout=e.onCriticalTimeout)}markRestarted(){this.graceStartedAt=this.now()}updateThresholds(e){e.warnThresholdPct!=null&&process.env.OTTO_MEMORY_WARN_PCT===void 0&&(this.warnThresholdPct=e.warnThresholdPct),e.hardThresholdPct!=null&&process.env.OTTO_MEMORY_HARD_PCT===void 0&&(this.hardThresholdPct=e.hardThresholdPct)}get inPostRestartGrace(){return this.graceStartedAt===void 0?!1:this.now()-this.graceStartedAt<this.postRestartGraceMs}sample(){let{heapUsed:e,rss:t,external:n}=process.memoryUsage(),{heap_size_limit:r}=Ie(),i=r>0?e/r*100:0;return{level:this.grade(i),heapUsed:e,heapSizeLimit:r,usedPct:i,rss:t,external:n,ts:this.now()}}grade(e){return e>=this.hardThresholdPct?`critical`:e>=this.warnThresholdPct?`warning`:`healthy`}start(){this.ticker||(this.ticker=setTimeout(()=>this.tick(),this.sampleIntervalMs),this.ticker.unref?.())}tick(){let e=this.sample();if(this.disposed)return;if(this.onSample?.(e),e.level!==this.lastLevel){if(this.logger?.info({from:this.lastLevel,to:e.level,usedPct:e.usedPct.toFixed(1),heapUsed:e.heapUsed,heapSizeLimit:e.heapSizeLimit},`[memory-governor] pressure level changed`),this.onLevelChange?.(e.level),e.level===`warning`){let e=this.now();this.lastWarningFiredAt!==void 0&&e-this.lastWarningFiredAt<this.warnCooldownMs?this.logger?.info({cooldownRemainingMs:this.warnCooldownMs-(e-this.lastWarningFiredAt)},`[memory-governor] onWarning skipped (within cooldown)`):(this.lastWarningFiredAt=e,this.onWarning?.())}e.level===`critical`&&(this.inPostRestartGrace?this.onCriticalDuringGrace?.(e):this.onCritical?.(e))}if(e.level===`critical`?this.criticalEnteredAt===void 0?(this.criticalEnteredAt=this.now(),this.criticalTimeoutFired=!1):!this.criticalTimeoutFired&&this.now()-this.criticalEnteredAt>=this.criticalTimeoutMs&&(this.criticalTimeoutFired=!0,this.onCriticalTimeout?.(e)):(this.criticalEnteredAt=void 0,this.criticalTimeoutFired=!1),this.lastLevel=e.level,this.disposed)return;let t=this.lastLevel===`critical`?this.criticalIntervalMs:this.lastLevel===`warning`?this.warningIntervalMs:this.sampleIntervalMs;this.ticker=setTimeout(()=>this.tick(),t),this.ticker.unref?.()}dispose(){this.disposed=!0,this.ticker&&=(clearTimeout(this.ticker),null)}};function W(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0?r:t}var un=class{sampleIntervalMs;maxProcesses;maxTotalRssMb;listProcesses;logger;now;onSample;onBudgetExceeded;ticker=null;disposed=!1;budgetExceededNotified=!1;constructor(e={}){this.sampleIntervalMs=e.sampleIntervalMs??W(`OTTO_FLEET_SAMPLE_INTERVAL_MS`,6e5),this.maxProcesses=e.maxProcesses??W(`OTTO_FLEET_MAX_PROCESSES`,8),this.maxTotalRssMb=e.maxTotalRssMb??W(`OTTO_FLEET_MAX_TOTAL_RSS_MB`,8192),this.listProcesses=e.listProcesses??pe,this.onSample=e.onSample,this.onBudgetExceeded=e.onBudgetExceeded,this.logger=e.logger,this.now=e.now??(()=>Date.now())}setCallbacks(e){`onSample`in e&&(this.onSample=e.onSample),`onBudgetExceeded`in e&&(this.onBudgetExceeded=e.onBudgetExceeded)}sample(){let e;try{e=this.listProcesses()}catch(e){this.logger?.warn({err:e instanceof Error?e.message:String(e)},`[fleet-monitor] process enumeration failed (skipping sample)`);return}if(e.length===0)return;let t=0,n=0,r=0;for(let i of e)t+=i.rssKb,i.ppid===1&&i.tty===`??`&&n++,i.generation!==void 0&&i.generation>r&&(r=i.generation);return{processCount:e.length,totalRssMb:Math.round(t/1024),suspectedOrphanCount:n,maxGeneration:r,ts:this.now()}}tick(){if(this.disposed)return;let e=this.sample();if(e){this.onSample?.(e);let t=e.processCount>this.maxProcesses,n=e.totalRssMb>this.maxTotalRssMb;if(t||n){if(!this.budgetExceededNotified){this.budgetExceededNotified=!0;let n=t?`process-count`:`total-rss`;this.logger?.warn({processCount:e.processCount,totalRssMb:e.totalRssMb,maxProcesses:this.maxProcesses,maxTotalRssMb:this.maxTotalRssMb},`[fleet-monitor] fleet budget exceeded`),this.onBudgetExceeded?.(e,n)}}else this.budgetExceededNotified=!1}this.disposed||(this.ticker=setTimeout(()=>this.tick(),this.sampleIntervalMs),this.ticker.unref?.())}start(){this.ticker||this.disposed||(this.ticker=setTimeout(()=>this.tick(),this.sampleIntervalMs),this.ticker.unref?.())}dispose(){this.disposed=!0,this.ticker&&=(clearTimeout(this.ticker),null)}};const G=e=>{try{return process.kill(e,0),!0}catch{return!1}},K=(e,t)=>{try{process.kill(-e,t)}catch{try{process.kill(e,t)}catch{}}},q=e=>{try{Re(`taskkill`,[`/F`,`/T`,`/PID`,`${e}`],{stdio:`ignore`,timeout:5e3})}catch{}};var dn=class{entries=new Map;maxProcesses;graceMs;clock;spawnListeners=new Set;exitListeners=new Set;constructor(e={}){this.maxProcesses=e.maxProcesses??64,this.graceMs=e.graceMs??2e3,this.clock=e.clock??(()=>Date.now())}onSpawn(e){return this.spawnListeners.add(e),()=>this.spawnListeners.delete(e)}onExit(e){return this.exitListeners.add(e),()=>this.exitListeners.delete(e)}notify(e,t){for(let n of[...e])try{n(t)}catch{}}register(e){if(this.entries.size>=this.maxProcesses&&this.evictLeastRecent(),this.entries.size>=this.maxProcesses)throw Error(`Background process limit (${this.maxProcesses}) reached; stop one with kill_shell first.`);let t=e.child.pid;if(t===void 0)throw Error(`Cannot register a child process without a pid`);let n=e.now??this.clock(),r={id:e.id,sessionId:e.sessionId,owner:e.owner,pid:t,pgid:t,command:e.command,cwd:e.cwd,port:e.port,url:e.url,logPath:e.logPath,startedAt:n,lastUsed:n,status:`running`,keepAlive:e.keepAlive},i={info:r,child:e.child};return this.entries.set(e.id,i),e.child.once(`exit`,e=>{r.status===`running`?(r.status=`exited`,r.exitCode=e??void 0):r.status===`killing`&&(r.status=`killed`),i.silenced||this.notify(this.exitListeners,r)}),this.notify(this.spawnListeners,r),r}get(e){return this.entries.get(e)?.info}getForSession(e,t){let n=this.entries.get(t);return n&&n.info.sessionId===e?n.info:void 0}list(){return[...this.entries.values()].map(e=>e.info)}listForSession(e){return this.list().filter(t=>t.sessionId===e)}touch(e){let t=this.entries.get(e);t&&(t.info.lastUsed=this.clock())}updateDetectedService(e,t){let n=this.entries.get(e);n&&(n.info.detectedService?.url&&!t.url||(n.info.detectedService=t))}remove(e){let t=this.entries.get(e);t&&(t.silenced=!0,this.entries.delete(e))}size(){return this.entries.size}async kill(e){let t=this.entries.get(e);t&&await this.killEntry(t)}async killAll(){await Promise.all([...this.entries.values()].map(e=>this.killEntry(e)))}async killAllForOwner(e){await Promise.all([...this.entries.values()].filter(t=>t.info.owner===e).map(e=>this.killEntry(e)))}async killAllForSession(e){await Promise.all([...this.entries.values()].filter(t=>t.info.sessionId===e).map(e=>this.killEntry(e)))}killAllSync(){for(let e of this.entries.values())this.killEntrySync(e)}killEntrySync(e){let{info:t}=e;t.status===`exited`||t.status===`killed`||(process.platform===`win32`?q(t.pid):K(t.pgid,`SIGKILL`),t.status=`killed`)}evictLeastRecent(){let e;for(let t of this.entries.values()){if(t.info.status===`exited`||t.info.status===`killed`){e=t;break}t.info.keepAlive||(!e||t.info.lastUsed<e.info.lastUsed)&&(e=t)}e&&(e.silenced=!0,this.killEntrySync(e),this.entries.delete(e.info.id))}async killEntry(e){let{info:t}=e;if(t.status===`running`){if(t.status=`killing`,process.platform===`win32`){q(t.pid),t.status=`killed`;return}K(t.pgid,`SIGTERM`),await this.waitForExit(e,this.graceMs)||K(t.pgid,`SIGKILL`),t.status=`killed`}}waitForExit(e,t){return new Promise(n=>{let r=!1,i,a=t=>{r||(r=!0,clearTimeout(i),e.child.removeListener(`exit`,o),n(t))},o=()=>a(!0);if(e.child.once(`exit`,o),!G(e.info.pid)){a(!0);return}i=setTimeout(()=>a(!1),t)})}};const fn=new dn;let pn=!1;function mn(e=fn){pn||(pn=!0,process.on(`exit`,()=>{e.killAllSync()}))}let hn=0;var gn=class extends ze{id;child;config;status=`starting`;_pid;_pgid;_exitResult=null;_exitResolve=null;_stdoutBuf=``;_stderrBuf=``;lastUsed;constructor(e,t){if(super(),this.id=`proc_${++hn}_${Date.now()}`,this.child=e,this.config=t,this._pid=e.pid,this._pgid=e.pid,this.lastUsed=Date.now(),this.child.on(`spawn`,()=>{this._pid=this.child.pid,this._pgid=this.child.pid,this.status===`starting`&&(this.status=`running`)}),this.child.on(`error`,e=>{this.lastUsed=Date.now(),(this.status===`starting`||this.status===`running`)&&(this.status=`errored`),this.emit(`error`,e)}),this.child.on(`exit`,(e,t)=>{this.lastUsed=Date.now();let n={code:e,signal:t,timedOut:!1};this._exitResult=n,this.status===`running`?this.status=`exited`:this.status===`killing`&&(this.status=`killed`),this.emit(`exit`,n),this._exitResolve&&=(this._exitResolve(n),null)}),this.child.stdout&&this.child.stdout.on(`data`,e=>{this.lastUsed=Date.now();let t=e.toString(`utf-8`);for(this._stdoutBuf+=t;;){let e=this._stdoutBuf.indexOf(`
14
- `);if(e===-1)break;let t=this._stdoutBuf.slice(0,e).replace(/\r$/,``);this._stdoutBuf=this._stdoutBuf.slice(e+1),this.emit(`stdoutLine`,t)}}),this.child.stderr&&this.child.stderr.on(`data`,e=>{this.lastUsed=Date.now();let t=e.toString(`utf-8`);for(this._stderrBuf+=t;;){let e=this._stderrBuf.indexOf(`
15
- `);if(e===-1)break;let t=this._stderrBuf.slice(0,e).replace(/\r$/,``);this._stderrBuf=this._stderrBuf.slice(e+1),this.emit(`stderrLine`,t)}}),t.signal){let e=()=>{this.kill({reason:`aborted`})};t.signal.aborted?e():t.signal.addEventListener(`abort`,e,{once:!0})}}get pid(){return this._pid}get pgid(){return this._pgid}get stdin(){return this.child.stdin&&!this.child.stdin.destroyed?this.child.stdin:null}get stdout(){return this.child.stdout&&!this.child.stdout.destroyed?this.child.stdout:null}get stderr(){return this.child.stderr&&!this.child.stderr.destroyed?this.child.stderr:null}onStdoutLine(e){return this.on(`stdoutLine`,e),()=>this.off(`stdoutLine`,e)}onStderrLine(e){return this.on(`stderrLine`,e),()=>this.off(`stderrLine`,e)}onExit(e){return this.on(`exit`,e),()=>this.off(`exit`,e)}onError(e){return this.on(`error`,e),()=>this.off(`error`,e)}async kill(e){if(this.status===`killed`||this.status===`exited`)return;this.status=`killing`,this.lastUsed=Date.now();let t=e?.graceMs??this.config.killGraceMs??2e3,n=this._pid,r=this._pgid;if(!n||!G(n)){this.status=`killed`;return}if(process.platform===`win32`){q(n),this.status=`killed`;return}K(r??n,`SIGTERM`),await new Promise(e=>{let r=!1,i=t=>{r||(r=!0,clearTimeout(o),e(t))},a=()=>i(!0);if(this.child.once(`exit`,a),!G(n)){i(!0);return}let o=setTimeout(()=>{this.child.removeListener(`exit`,a),i(!1)},t)})||K(r??n,`SIGKILL`),this.status=`killed`}async waitForExit(e=3e4){return this._exitResult?this._exitResult:new Promise(t=>{if(this._exitResult){t(this._exitResult);return}let n=!1,r=e=>{n||(n=!0,clearTimeout(a),this.off(`exit`,i),t(e))},i=e=>r(e);this.on(`exit`,i);let a=setTimeout(()=>{r({code:null,signal:null,timedOut:!0})},e)})}},_n=class{_entries=new Map;_maxProcesses;killGraceMs;killTimeoutMs;_clock;_spawnListeners=new Set;_exitListeners=new Set;constructor(e={}){this._maxProcesses=e.maxProcesses??128,this.killGraceMs=e.killGraceMs??2e3,this.killTimeoutMs=e.killTimeoutMs??3e4,this._clock=e.clock??(()=>Date.now())}onSpawn(e){return this._spawnListeners.add(e),()=>this._spawnListeners.delete(e)}onExit(e){return this._exitListeners.add(e),()=>this._exitListeners.delete(e)}onAllExited(e){let t=()=>{this._entries.size===0&&e()},n=()=>t();return this._exitListeners.add(n),t(),()=>this._exitListeners.delete(n)}spawn(e){if(this._entries.size>=this._maxProcesses&&this._evictLeastRecent(),this._entries.size>=this._maxProcesses)throw Error(`Process limit (${this._maxProcesses}) reached. Stop unused processes first.`);let t={...e.options??{},stdio:e.options?.stdio??[`pipe`,`pipe`,`pipe`],cwd:e.cwd??e.options?.cwd,env:u(e.env??e.options?.env),...e.keepAlive===!0?{}:{detached:!0}},n=Le(e.command,e.args??[],t),r=new gn(n,e);this._entries.set(r.id,{proc:r,child:n}),r.onExit(()=>{if(!this._entries.get(r.id))return;let t=e.lifecycle??`evictable`;e.keepAlive!==!0&&t!==`pinned`&&this._entries.delete(r.id);for(let e of[...this._exitListeners])try{e(r)}catch{}});for(let e of[...this._spawnListeners])try{e(r)}catch{}return r}get(e){return this._entries.get(e)?.proc}list(e){let t=[...this._entries.values()];return e?.owner&&(t=t.filter(t=>t.proc.config.owner.type===e.owner.type&&t.proc.config.owner.id===e.owner.id)),e?.sessionId&&(t=t.filter(t=>t.proc.config.sessionId===e.sessionId)),e?.category&&(t=t.filter(t=>t.proc.config.category===e.category)),t.map(e=>e.proc)}listForSession(e){return this.list({sessionId:e})}listForOwner(e){return this.list({owner:e})}touch(e){let t=this._entries.get(e);t&&(t.proc.lastUsed=this._clock())}remove(e){this._entries.delete(e)}size(){return this._entries.size}async killAll(e,t){let n=this.list(e).filter(e=>!e.config.keepAlive);await Promise.all(n.map(e=>e.kill(t)))}killAllSync(){let e=process.platform===`win32`,t=[];for(let[n,r]of this._entries){let i=r.proc;if(i.config.keepAlive||i.status!==`running`&&i.status!==`starting`)continue;let a=i.pid;a&&(e?t.push(a):K(i.pgid??a,`SIGKILL`),this._entries.delete(n))}if(e&&t.length>0)try{Re(`taskkill`,[`/F`,`/T`,...t.map(String).flatMap(e=>[`/PID`,e])],{stdio:`ignore`,timeout:5e3})}catch{}}async killAllForOwner(e,t){return this.killAll({owner:{type:e,id:t}})}async killAllForSession(e){return this.killAll({sessionId:e})}registerChild(e,t){if(this._entries.size>=this._maxProcesses&&this._evictLeastRecent(),this._entries.size>=this._maxProcesses)throw Error(`Process limit (${this._maxProcesses}) reached. Stop unused processes first.`);let n=new gn(t,e);this._entries.set(n.id,{proc:n,child:t}),n.onExit(()=>{if(!this._entries.get(n.id))return;let t=e.lifecycle??`evictable`;e.keepAlive!==!0&&t!==`pinned`&&this._entries.delete(n.id);for(let e of[...this._exitListeners])try{e(n)}catch{}});for(let e of[...this._spawnListeners])try{e(n)}catch{}return n}_evictLeastRecent(){let e;for(let t of this._entries.values()){let n=t.proc.config,r=n.lifecycle??`evictable`;if(t.proc.status===`exited`||t.proc.status===`killed`||t.proc.status===`errored`){e=t;break}n.keepAlive||r!==`pinned`&&(!e||t.proc.lastUsed<e.proc.lastUsed)&&(e=t)}if(!e)return;let t=e.proc.pid;t&&G(t)&&(process.platform===`win32`?q(t):K(e.proc.pgid??t,`SIGKILL`)),this._entries.delete(e.proc.id)}};const vn=new _n;let yn=!1;function bn(e=vn){yn||(yn=!0,process.on(`exit`,()=>{e.killAllSync()}))}function J(e,t){return j(`git`,[`-C`,e,...t],{encoding:`utf-8`,stdio:[`ignore`,`pipe`,`pipe`]}).trimEnd()}function xn(e,t){let n=J(e,[`rev-parse`,`HEAD`]),r=`otto/job-${t}`,i=p(Be(p(He(),`otto-wt-`)),`job-${t}`);return J(e,[`worktree`,`add`,`-b`,r,i,n]),{path:i,branch:r,base:n,repoRoot:e}}function Sn(e){return J(e.path,[`add`,`-A`]),j(`git`,[`-C`,e.path,`diff`,`--cached`,`--binary`],{encoding:`utf-8`,maxBuffer:256*1024*1024})}function Y(e){return[...new Set(e.split(`
16
- `).map(e=>/(?:patch failed: |error: )([^\s:]+?)(?::| ?:?\s*(?:patch does not apply|does not exist))/.exec(e)?.[1]).filter(e=>!!e&&e!==`error`))]}function Cn(e,t){try{return J(e,[`rev-parse`,`HEAD`])!==t}catch{return!1}}function wn(e,t){if(!t.trim())return{applied:!0,conflictPaths:[]};try{j(`git`,[`-C`,e,`apply`,`--check`,`--whitespace=nowarn`],{input:t,stdio:[`pipe`,`pipe`,`pipe`]})}catch(e){return{applied:!1,conflictPaths:Y(String(e.stderr??``))}}try{return j(`git`,[`-C`,e,`apply`,`--whitespace=nowarn`],{input:t,stdio:[`pipe`,`pipe`,`pipe`]}),{applied:!0,conflictPaths:[]}}catch(e){return{applied:!1,conflictPaths:Y(String(e.stderr??``))}}}function Tn(e,t){if(!t.trim())return{applied:!0,conflictPaths:[]};try{j(`git`,[`-C`,e,`apply`,`--reverse`,`--check`,`--whitespace=nowarn`],{input:t,stdio:[`pipe`,`pipe`,`pipe`]})}catch(e){return{applied:!1,conflictPaths:Y(String(e.stderr??``))}}try{return j(`git`,[`-C`,e,`apply`,`--reverse`,`--whitespace=nowarn`],{input:t,stdio:[`pipe`,`pipe`,`pipe`]}),{applied:!0,conflictPaths:[]}}catch(e){return{applied:!1,conflictPaths:Y(String(e.stderr??``))}}}function X(e,t){try{J(e.repoRoot,[`worktree`,`remove`,`--force`,e.path])}catch(e){t?.(`worktree remove`,e)}try{J(e.repoRoot,[`branch`,`-D`,e.branch])}catch(e){t?.(`branch delete`,e)}try{J(e.repoRoot,[`worktree`,`prune`])}catch(e){t?.(`worktree prune`,e)}}function En(e,t){let n=new Set(t),r=[],i;try{i=p(Ve(He()),`otto-wt-`)}catch{return r}let a;try{a=J(e,[`worktree`,`list`,`--porcelain`])}catch{return r}let o=a.split(`
12
+ Bad (wrong case): {"title": "Fix Login Button On Mobile"}`,messages:t,cacheRetention:`none`,maxTokens:64,temperature:0},i.signal).result()).content))}catch{return null}finally{clearTimeout(o),n.removeEventListener(`abort`,a)}}var at=class{session;stream;titleModel;genSeq=0;abortController=new AbortController;disposed=!1;constructor(e){this.session=e.session,this.stream=e.stream,this.titleModel=e.titleModel}maybeGenerate(e=!1){if(!this.titleModel||this.disposed||this.session.metadata().titleSource===`custom`)return;let t=this.session.messages().filter(e=>e.role===`user`).length;if(t===0||!e&&t>3)return;let n=++this.genSeq,r=this.session.messages().map(e=>{let t=e.content;return typeof t==`string`?t:Array.isArray(t)?t.filter(e=>{let t=e;return t.type===`text`&&typeof t.text==`string`}).map(e=>e.text).join(` `):``}).filter(Boolean).join(`
13
+ `);it({stream:this.stream,model:this.titleModel},r,this.abortController.signal).then(e=>{!e||this.disposed||n===this.genSeq&&this.session.metadata().titleSource!==`custom`&&this.session.setTitle(e,`ai`)}).catch(()=>{})}backfill(){this.maybeGenerate(!0)}dispose(){this.disposed||(this.disposed=!0,this.abortController.abort())}},ot=class{constructor(e){this.deps=e}messages(){return this.deps.session.messages()}append(e){this.deps.session.append(e)}removeLast(){this.deps.session.removeLast()}persistInputBoundary(){this.deps.requestInputBoundaryFlush?.()}buildContext(){return this.deps.session.buildContext()}persistNew(e,t){let n=e.slice(t);for(let e of n)this.deps.session.append(e)}recordCompaction(e,t){let{session:n,sessionId:r,publish:i}=this.deps,a=n.buildContext().messages.length;n.recordCompaction(e,t);let o=n.buildContext().messages.length;o<a&&(i({"compaction.start":[{type:`compaction.start`,sessionId:r,messageCount:a}]}),i({"compaction.end":[{type:`compaction.end`,sessionId:r,retainedCount:o,summary:e}]}))}notifyPrune(e,t){this.deps.publish({"memory.pruned":[{type:`memory.pruned`,sessionId:this.deps.sessionId,tokensSaved:e,prunedCount:t?.prunedCount,messagesBefore:t?.messagesBefore,messagesAfter:t?.messagesAfter}]})}};const st=`Continue with the remaining todo items.`,ct=new Set([`done`,`skipped`,`failed`]);function lt(e,t){if(e.size!==t.size)return!1;for(let[n,r]of e)if(!t.has(n)||t.get(n)!==r)return!1;return!0}var ut=class e{session;sessionId;logger;todoContinuation;depth;publish;isAbortRequested;runPromptRound;constructor(e){this.session=e.session,this.sessionId=e.sessionId,this.logger=e.logger,this.todoContinuation=e.todoContinuation,this.depth=e.depth,this.publish=e.publish,this.isAbortRequested=e.isAbortRequested,this.runPromptRound=e.runPromptRound}snapshot(){return new Map((this.session.getTodoList()??[]).map(e=>[e.id,e.status]))}countIncomplete(){return(this.session.getTodoList()??[]).filter(e=>!ct.has(e.status??`pending`)).length}static hasStateProgress(e,t){return!lt(e,t)}async run(){if(!this.todoContinuation.enabled||this.depth>0)return;let t=this.todoContinuation.max*4,n=0,r=0,i=0,a=!1,o=st,s=this.snapshot();for(;n<this.todoContinuation.max&&r<t&&!this.isAbortRequested()&&this.countIncomplete()>0;){n++,r++,this.publish({"prompt.continued":[{type:`prompt.continued`,sessionId:this.sessionId,round:r,maxRounds:t,incompleteCount:this.countIncomplete()}]}),this.logger.info({sessionId:this.sessionId,round:n,totalRounds:r,max:this.todoContinuation.max,hardCap:t},`Todo gate: auto-continuing unfinished todos`);let c=await this.runPromptRound(o,!0);if(c.cancelled)return;o=st;let l=this.snapshot();if(e.hasStateProgress(s,l)){n--,i=0,s=l;continue}if(c.hadToolActivity&&!a){n--,a=!0,i=1,o=`You made progress but did not update the todo list. Reconcile it now: mark each genuinely finished item done (or skipped/failed with a reason) via write_todos, then continue any remaining work.`,this.logger.info({sessionId:this.sessionId,round:n},`Todo gate: tool activity without todo updates — nudging state reconciliation`);continue}if(c.hadToolActivity){i++,this.logger.info({sessionId:this.sessionId,staleActivityRounds:i},`Todo gate: diminishing returns (repeated activity without todo progress), stopping`);return}this.logger.info({sessionId:this.sessionId,round:n},`Todo gate: no progress between rounds, stopping early`);return}}};async function dt(e,t,n){let{session:r,sessionId:i,hookRegistry:a,logger:o,publish:s}=e,c=r.messages().length;await a.emit(`compaction.before`,{sessionId:i,messageCount:c}),s({"compaction.start":[{type:`compaction.start`,sessionId:i,messageCount:c}]}),o.info({sessionId:i,count:n},`Session compacting`),r.compact(t,n);let l=r.messages().length;await a.emit(`compaction.after`,{sessionId:i,retainedCount:l}),s({"compaction.end":[{type:`compaction.end`,sessionId:i,retainedCount:l,summary:t}]}),o.info({sessionId:i,retained:l,summaryChars:t.length},`Session compaction finished`)}async function ft(e,t){let{session:n,sessionId:r,hookRegistry:i,logger:a,memory:o,persistence:s}=e,c=n.buildContext(),l=c.messages.length;if(!o||t?.aborted)return{compacted:!1,before:l,after:l};await i.emit(`compaction.before`,{sessionId:r,messageCount:l}),a.info({sessionId:r,messageCount:l},`Session manual compaction (forced)`);let u={compacted:!1};await Ce(o,c.messages,r,t,{persistence:s,sink:u});let d=n.buildContext().messages.length;return await i.emit(`compaction.after`,{sessionId:r,retainedCount:d}),a.info({sessionId:r,retainedCount:d},`Session manual compaction finished`),{compacted:u.compacted,before:l,after:d}}function pt(e,t,n,r){return[e.on(`max.turns`,e=>{e.steered&&r(),n({"budget.notice":[{type:`budget.notice`,sessionId:t,turnIndex:e.turnIndex,maxTurns:e.maxTurns,extended:e.extended,...e.steered===void 0?{}:{steered:e.steered},...e.progressDenied===void 0?{}:{progressDenied:e.progressDenied}}]})}),e.on(`prompt.budget`,e=>{e.steered&&r(),n({"prompt.budget.notice":[{type:`prompt.budget.notice`,sessionId:t,turnIndex:e.turnIndex,dimension:e.dimension,used:e.used,budget:e.budget,steered:e.steered}]})}),e.on(`progress.stall`,e=>{n({"progress.stall.notice":[{type:`progress.stall.notice`,sessionId:t,turnIndex:e.turnIndex,windowTurns:e.windowTurns,maxRepeat:e.maxRepeat}]})}),e.on(`tool.call.mismatch`,e=>{n({"tool.call.mismatch.notice":[{type:`tool.call.mismatch.notice`,sessionId:t,turnIndex:e.turnIndex,outcome:e.outcome,retryCount:e.retryCount}]})}),e.on(`image.vision-delegate`,e=>{n({"image.vision-delegate":[{type:`image.vision-delegate`,sessionId:t,attemptedCount:e.attemptedCount,describedCount:e.describedCount,failedCount:e.failedCount}]})}),e.on(`compaction.reactive`,e=>{n({"compaction.reactive.notice":[{type:`compaction.reactive.notice`,sessionId:t,messagesBefore:e.messagesBefore,messagesAfter:e.messagesAfter}]})}),e.on(`image.degradation`,e=>{n({"image.degradation.notice":[{type:`image.degradation.notice`,sessionId:t,degradedCount:e.degradedCount,trigger:e.trigger}]})})]}function mt(e,t){if(e)return e.length>t?`${e.slice(0,t)}…`:e}function ht(e,t){if(t.toolCall.name!==`write_todos`||t.result.isError)return;let n=t.result.details?.todos;if(!Array.isArray(n))return;let r=new Map((e.getTodoList()??[]).map(e=>[e.id,e.turn]));e.setTodoList(n.map(e=>({id:e.id,title:e.title,status:e.status,turn:e.id===void 0?void 0:r.get(e.id)})))}function gt(e){let{agent:t,session:n,sessionId:r,modelId:i,hookRegistry:a,publish:o}=e;return[t.on(`stream.event`,async({event:e})=>{o({"stream.event":[{type:`stream.event`,sessionId:r,event:e}]}),e.type===`start`?(o({"streaming.start":[{type:`streaming.start`,sessionId:r,model:i()}]}),a.emit(`stream.start`,{sessionId:r,model:i()})):e.type===`done`&&(o({"streaming.end":[{type:`streaming.end`,sessionId:r,model:i(),stopReason:e.reason??`end_turn`}]}),await a.emit(`stream.end`,{sessionId:r,model:i(),stopReason:e.reason??`end_turn`,tokenUsage:{input:e.message.usage.inputTokens,output:e.message.usage.outputTokens}}))}),t.on(`turn.start`,e=>{o({"turn.start":[{type:`turn.start`,sessionId:r,turnIndex:e.turnIndex,toolTurnCount:e.toolTurnCount,maxToolTurns:e.maxToolTurns,promptOutputTokens:e.promptOutputTokens,promptOutputTokenBudget:e.promptOutputTokenBudget}]})}),t.on(`turn.end`,e=>{o({"turn.end":[{type:`turn.end`,sessionId:r,turnIndex:e.turnIndex}]})}),t.on(`tool.call.start`,e=>{o({"tool.call.start":[{type:`tool.call.start`,sessionId:r,toolCall:{id:e.toolCall.id,name:e.toolCall.name,arguments:e.toolCall.arguments}}]})}),t.on(`tool.call.end`,e=>{ht(n,e);let t=Te(Se(e.result)),i=e.contextChars??t.length;o({"tool.call.end":[{type:`tool.call.end`,sessionId:r,toolCall:{id:e.toolCall.id,name:e.toolCall.name,arguments:e.toolCall.arguments},isError:e.result.isError===!0,resultText:mt(t,he.traceResultMaxChars),resultTokensEstimate:Math.ceil(i/4),details:e.result.details??void 0}]})})]}const _t=100*1024*1024;function vt(e){return e.replace(/[^a-zA-Z0-9_-]/g,`_`).slice(0,128)||`unnamed`}var yt=class{rootDir;constructor(e){this.rootDir=p(e,`tool-results`)}sessionDir(e){return p(this.rootDir,vt(e))}async spill(e,t,n){if(!pe())try{let r=this.sessionDir(e);await De(r,{recursive:!0});let i=p(r,`${vt(t)}.txt`);return await Ne(i,n,`utf-8`),this.evictIfOverBudget().catch(()=>{}),i}catch{return}}async cleanupSession(e){try{await Ae(this.sessionDir(e),{recursive:!0,force:!0})}catch{}}async evictIfOverBudget(){let e=[],t=0,n;try{n=await ke(this.rootDir)}catch{return}for(let r of n){let n=p(this.rootDir,r),i;try{i=await ke(n)}catch{continue}for(let r of i){let i=p(n,r);try{let n=await je(i);n.isFile()&&(e.push({path:i,mtimeMs:n.mtimeMs,size:n.size}),t+=n.size)}catch{}}}if(!(t<=_t)){e.sort((e,t)=>e.mtimeMs-t.mtimeMs);for(let n of e){if(t<=_t)break;try{await Me(n.path),t-=n.size}catch{}}}}};let bt;function xt(){return bt??=new yt(p(process.cwd(),`.otto`)),bt}const St={spill(e,t,n){return xt().spill(e,t,n)},cleanupSession(e){return xt().cleanupSession(e)}},Ct={maxToolTurns:he.maxToolTurns};function wt(){let e,t,n=new Promise((n,r)=>{e=n,t=r});return{resolve:e,reject:t,promise:n}}var N=class{pending=new Map;open(e){let t=wt();return this.pending.set(e,t),t.promise.finally(()=>{this.pending.delete(e)})}resolve(e,t){let n=this.pending.get(e);return n?(n.resolve(t),!0):!1}rejectAll(e){for(let t of this.pending.values())t.reject(e);this.pending.clear()}},Tt=class{approvalGate=new N;grillGate=new N;planGate=new N;constructor(e){this.deps=e}async requestApproval(e,t,n,r){let{sessionId:i,interactive:a,logger:o,publish:s}=this.deps;if(!a)return o.warn({sessionId:i(),toolName:e},`Approval requested in a non-interactive session; denying (fail-closed, no human to respond)`),!1;let c=D(),l=this.approvalGate.open(c);return s({"approval.required":[{type:`approval.required`,sessionId:i(),id:c,toolName:e,arguments:t,description:n,risk:r}]}),o.info({sessionId:i(),toolName:e,approvalId:c},`Approval requested`),l}resolveApproval(e,t){let{sessionId:n,logger:r,publish:i}=this.deps;this.approvalGate.resolve(e,t)&&(i({"approval.resolved":[{type:`approval.resolved`,sessionId:n(),id:e,approved:t}]}),r.info({sessionId:n(),approvalId:e,approved:t},`Approval resolved`))}async requestGrill(e){let{sessionId:t,interactive:n,logger:r,publish:i}=this.deps;if(!n)return{answer:e.recommendation,acceptedRecommendation:!0,resolvedBy:`auto_recommendation`};let a=D(),o={...e,id:a},s=this.grillGate.open(a);return i({"ask.user.required":[{type:`ask.user.required`,sessionId:t(),requestId:a,question:o}]}),r.info({sessionId:t(),requestId:a,askedBy:e.askedBy},`Grill requested`),s}resolveAskUser(e,t){let{sessionId:n,logger:r,publish:i}=this.deps;t&&this.grillGate.resolve(e,t)&&(i({"ask.user.resolved":[{type:`ask.user.resolved`,sessionId:n(),requestId:e}]}),r.info({sessionId:n(),requestId:e},`Grill resolved`))}async requestPlanApproval(e){let{sessionId:t,logger:n,publish:r}=this.deps,i=D(),a=this.planGate.open(i);return r({"plan.approval.required":[{type:`plan.approval.required`,sessionId:t(),requestId:i,planContent:e}]}),n.info({sessionId:t(),requestId:i},`Plan approval requested`),a}resolvePlanApproval(e,t,n){let{sessionId:r,logger:i,publish:a}=this.deps;this.planGate.resolve(e,{action:t,feedback:n})&&(a({"plan.approval.resolved":[{type:`plan.approval.resolved`,sessionId:r(),requestId:e,action:t}]}),i.info({sessionId:r(),action:t,requestId:e},`Plan approval resolved`))}rejectAll(e){this.approvalGate.rejectAll(e),this.grillGate.rejectAll(e),this.planGate.rejectAll(e)}},Et=class{costTracker=new e;sessionCrossedCostBudget=!1;lastTokenUsage;lastCacheHitRatio=null;constructor(e){this.deps=e}record(e,n){let r=e.usage;if(e.count===0||e.lastAssistantApi===void 0)return;this.lastTokenUsage={input:r.inputTokens,output:r.outputTokens},this.lastCacheHitRatio=t(r,e.lastAssistantApi);let i=this.costTracker.record(n,r),a=this.costTracker.summary().totalCostUSD,{sessionId:o,logger:s,publish:c,sessionCostBudgetUSD:l}=this.deps;s.info({sessionId:o(),input:r.inputTokens,output:r.outputTokens,cacheRead:r.cacheReadTokens,cacheWrite:r.cacheWriteTokens,cacheHitRatio:this.lastCacheHitRatio,turnCost:i.toFixed(6),sessionCost:a.toFixed(6)},`Session usage`),!this.sessionCrossedCostBudget&&l!==void 0&&l>0&&a>=l&&(this.sessionCrossedCostBudget=!0,c({"session.cost-budget-exceeded":[{type:`session.cost-budget-exceeded`,sessionId:o(),totalCostUSD:a,budgetUSD:l}]}))}getLastTokenUsage(){return this.lastTokenUsage}getCostSummary(){return this.costTracker.summary()}getLastCacheHitRatio(){return this.lastCacheHitRatio}};function Dt(e,t){e.ensureNotDisposed();let n=`steer-${++e.steerSeq.value}`,r={role:`user`,timestamp:e.clock?.now()??Date.now(),content:[{type:`text`,text:t}],uuid:n};return e.agent.steer(r),{id:n}}function Ot(e,t){return e.ensureNotDisposed(),e.agent.removeSteer(t)}function kt(e,t){e.ensureNotDisposed(),e.agent.followUp({role:`user`,timestamp:e.clock?.now()??Date.now(),content:[{type:`text`,text:t}]})}async function At(e,t){let{text:n,internal:r,images:i,resumeLastRound:a}=t;if(e.compactionPending){let t=e.compactionPending;e.setCompactionPending(void 0);try{let n=e.getCompactionTimeoutMs?.()??Pe;await Promise.race([t,new Promise((e,t)=>setTimeout(()=>t(Error(`compaction timeout`)),n))])}catch{}}if(e.promptRefresh){let t=await e.promptRefresh();t!==void 0&&e.setSystemPrompt(t)}let o=await we({text:n,internal:r,images:i,...a?{resumeLastRound:!0}:{},sessionId:e.id,agentName:e.agentName,model:e.model,tools:e.model.supportsTools===!1?[]:e.tools,params:{systemPrompt:e.systemPrompt,systemTail:e.systemTail,thinkingLevel:e.thinkingLevel,cacheRetention:e.interactive?`long`:`short`},runner:e.agent,hooks:e.hookRegistry,persistence:e.persistence,memory:e.memory,debug:e.devtools?.debugger,recorder:e.recorder,clock:e.clock,isPauseRequested:e.pauseRequested,describeImages:e.describeImages});return o.cancelled?{cancelled:!0,hadToolActivity:!1}:(e.pauseRequested()&&e.publish({"run.paused":[{type:`run.paused`,sessionId:e.id}]}),e.setSystemPrompt(o.params.systemPrompt),e.setThinkingLevel(o.params.thinkingLevel),e.usageTracker.record(o.newMessagesUsageSummary,e.model),{cancelled:!1,hadToolActivity:o.newMessagesUsageSummary.hadToolActivity})}function jt(e,t){return e>0||t?0:3}function Mt(e){let t=(e.OTTO_TODO_CONTINUE??``).toLowerCase(),n=!(t===`0`||t===`off`||t===`false`||t===`no`),r=Math.trunc(Number(e.OTTO_TODO_CONTINUE_MAX??3));return{enabled:n,max:Number.isFinite(r)&&r>=0?r:3}}var Nt=class extends c{session;workspaceDir;workspaceId;agent;disposed=!1;promptGate=!1;titleManager;runStartedThisPrompt=!1;currentPrompt;compactionPending;getCompactionTimeoutMs;model;modelResolution;tools;systemPrompt;systemTail;agentName;depth;parentTaskId;transient;listable;maxToolTurns;maxToolTurnExtensions;promptOutputTokenBudget;promptWallClockBudgetMs;thinkingLevel;promptRefresh;logger;hookRegistry;devtools;memory;recorder;describeImages;nondetFlush;clock;steerSeq={value:0};persistence;inputBoundaryFlusher;setInputBoundaryFlusher(e){this.inputBoundaryFlusher=e}gates;interactive;agentUnsubs=[];sessionCostBudgetUSD;usageTracker;todoGateRunner;abortRequested=!1;pauseRequested=!1;get id(){return this.session.id}get title(){return this.session.metadata().title}get status(){return this.agent.status}get pinned(){return this.session.metadata().pinned??!1}get pinGroup(){return this.session.metadata().pinGroup}get coreAgent(){return this.agent}get steerDeps(){return{agent:this.agent,clock:this.clock,steerSeq:this.steerSeq,ensureNotDisposed:()=>this.ensureNotDisposed()}}get isExecuting(){return this.agent.status===`streaming`||this.agent.status===`tool_executing`}get isBusy(){return this.promptGate||this.isExecuting}getSessionInfo(){return{sessionId:this.id,modelId:this.model.id,modelName:this.model.name,systemPromptLength:this.systemPrompt?.length??0,tools:this.tools.map(e=>e.name)}}constructor(e,t){super(),this.session=e;let n=t.hookRegistry??a({preset:`default`});t.hookRegistry||s(n);let r=t.logger??d(`agent-session:${e.id}`,{level:`info`,destination:`stdout`});this.getCompactionTimeoutMs=t.getCompactionTimeoutMs;let i=t.promptRefresh,o=t.systemPrompt??``,c=t.tools??[],l=t.thinkingLevel??`medium`,u=t.maxToolTurns??Ct.maxToolTurns,f=t.depth??0,p=t.parentTaskId,m=t.maxToolTurnExtensions??jt(f,t.transient),h=f===0?t.promptOutputTokenBudget:void 0,g=f===0?t.promptWallClockBudgetMs:void 0,_=t.stallDetection,v=process.env.OTTO_BUDGET_STEER_WRAPUP,y=t.budgetSteerWrapUp??(v===`1`||v===`on`?!0:v===`0`||v===`off`?!1:f===0),b=t.workspaceDir??process.cwd(),{model:x,devtools:S,agentName:ee}=t;this.model=x,this.modelResolution=t.modelResolution,this.tools=c,this.systemPrompt=o,this.systemTail=t.systemTail,this.thinkingLevel=l,this.maxToolTurns=u,this.maxToolTurnExtensions=m,this.promptOutputTokenBudget=h,this.promptWallClockBudgetMs=g,this.hookRegistry=n,this.agentName=ee??`agent`,this.depth=f,this.parentTaskId=p,this.transient=t.transient??!1,this.listable=t.listable??!0,this.interactive=t.interactive??!1,this.devtools=S,this.memory=t.memory,this.recorder=t.recorder,this.describeImages=t.describeImages,this.nondetFlush=t.nondetFlush,this.clock=t.clock,this.logger=r,this.workspaceDir=b,this.sessionCostBudgetUSD=f===0?t.sessionCostBudgetUSD:void 0,this.workspaceId=t.workspaceId,this.promptRefresh=i,this.gates=new Tt({sessionId:()=>this.id,interactive:this.interactive,logger:r,publish:e=>this.publish(e)}),this.usageTracker=new Et({sessionId:()=>this.id,sessionCostBudgetUSD:this.sessionCostBudgetUSD,logger:r,publish:e=>this.publish(e)}),this.titleManager=new at({session:e,stream:t.stream,titleModel:t.titleModel}),this.todoGateRunner=new ut({session:e,sessionId:e.id,logger:r,todoContinuation:t.todoContinuation??Mt(process.env),depth:f,publish:e=>this.publish(e),isAbortRequested:()=>this.abortRequested,runPromptRound:(e,t)=>this.runPromptRound(e,t)}),this.agent=_e({stream:t.stream,logger:r,maxToolTurns:u,maxToolTurnExtensions:m,budgetSteerWrapUp:y,promptOutputTokenBudget:h,promptWallClockBudgetMs:g,stallDetection:_,agentName:this.agentName,sessionId:e.id,depth:this.depth,parentTaskId:this.parentTaskId,toolHookExecutor:et({hookRegistry:n,agentName:this.agentName,sessionId:e.id}),debug:S?.debugger,recorder:this.recorder,nondetFlush:this.nondetFlush,clock:this.clock,approval:(e,t,n,r)=>this.requestApproval(e,t,n,r),spill:(t,n)=>St.spill(e.id,t,n),retryAccelerate:t.retryAccelerate,streamRetry:t.streamRetry,networkDisconnectRetry:t.networkDisconnectRetry,lifecycleAsyncTimeoutMs:t.lifecycleAsyncTimeoutMs}),this.agentUnsubs.push(this.agent.on(`status.change`,({to:e})=>{e===`streaming`&&(this.runStartedThisPrompt=!0)})),this.agentUnsubs.push(...pt(this.agent,this.id,e=>this.publish(e),()=>{this.budgetSteeredThisPrompt=!0})),this.agentUnsubs.push(...gt({agent:this.agent,session:this.session,sessionId:this.id,modelId:()=>this.model.id,hookRegistry:n,publish:e=>this.publish(e)})),this.agentUnsubs.push(this.agent.on(`steering.injected`,({messages:e})=>{for(let t of e){let e=t.uuid;e&&this.publish({"steer.consumed":[{type:`steer.consumed`,sessionId:this.id,id:e}]})}})),this.persistence=new ot({session:this.session,sessionId:this.id,publish:e=>this.publish(e),requestInputBoundaryFlush:()=>this.inputBoundaryFlusher?.()}),this.logger.info({sessionId:this.id,model:this.model.id},`Session initialized`)}notifyCreated(){this.publish({"session.start":[{type:`session.start`,sessionId:this.id}]})}budgetSteeredThisPrompt=!1;archive(){this.ensureNotDisposed(),this.agent.archive(),this.session.setArchived(!0)}unarchive(){this.ensureNotDisposed(),this.agent.unarchive(),this.session.setArchived(!1)}pin(e){this.ensureNotDisposed(),this.session.setPinned(!0,e?.trim()||void 0)}unpin(){this.ensureNotDisposed(),this.session.setPinned(!1)}async prompt(e,t){if(this.ensureNotDisposed(),this.status===`archived`)throw Error(`Session is archived. Unarchive it first before sending messages.`);if(this.isBusy){let{streamingBehavior:n}=t??{};if(n===`followUp`)this.followUp(e);else if(n===`steer`)this.steer(e);else throw Error(`Agent is processing. Specify streamingBehavior ("steer" or "followUp") to queue the message.`);return}let n=this.executePrompt(e,t);this.currentPrompt=n;try{await n}finally{this.currentPrompt===n&&(this.currentPrompt=void 0)}}async retryLastRound(){if(this.ensureNotDisposed(),this.status===`archived`)throw Error(`Session is archived. Unarchive it first before sending messages.`);if(this.isBusy)throw Error(`Agent is processing. Cannot retry while a round is in flight.`);if(![...this.session.messages()].reverse().find(e=>e.role===`user`)){let e=Error(`No resumable user message in history`);throw e.code=`RETRY_NO_RESUMABLE_ROUND`,e}let e=this.executePrompt(``,{resumeLastRound:!0});this.currentPrompt=e;try{await e}finally{this.currentPrompt===e&&(this.currentPrompt=void 0)}}async executePrompt(e,t){this.promptGate=!0,this.budgetSteeredThisPrompt=!1,this.runStartedThisPrompt=!1,this.abortRequested=!1,this.pauseRequested=!1;let n=this.model.id,r=this.thinkingLevel;try{if(this.publish({"prompt.start":[{type:`prompt.start`,sessionId:this.id,text:e}]}),!this.session.metadata().title?.trim()){let t=M([{role:`user`,content:e}]);t&&this.session.setTitle(t,`derived`)}if(this.logger.info({sessionId:this.id},`Session prompt started`),(await this.runPromptRound(e,void 0,t?.images,t?.resumeLastRound)).cancelled){this.publish({"prompt.end":[{type:`prompt.end`,sessionId:this.id,tokenUsage:this.usageTracker.getLastTokenUsage(),model:n,thinkingLevel:r,stopReason:`interrupted`}]});return}await this.todoGateRunner.run(),this.titleManager.maybeGenerate(),this.publish({"prompt.end":[{type:`prompt.end`,sessionId:this.id,tokenUsage:this.usageTracker.getLastTokenUsage(),model:n,thinkingLevel:r,stopReason:`completed`}]}),this.logger.info({sessionId:this.id},`Session prompt finished`)}catch(e){let t=e instanceof Error?e:Error(String(e));throw this.publish({"prompt.end":[{type:`prompt.end`,sessionId:this.id,tokenUsage:this.usageTracker.getLastTokenUsage(),model:n,thinkingLevel:r,stopReason:`error`}]}),this.publish({error:[{type:`error`,sessionId:this.id,error:t}]}),this.logger.error({sessionId:this.id,err:t.message},`Session prompt failed`),e}finally{this.promptGate=!1}}async runPromptRound(e,t,n,r){return At(this.promptRoundHost,{text:e,internal:t,images:n,resumeLastRound:r})}get promptRoundHost(){return{id:this.id,agentName:this.agentName,agent:this.agent,model:this.model,tools:this.tools,systemPrompt:this.systemPrompt,systemTail:this.systemTail,thinkingLevel:this.thinkingLevel,interactive:this.interactive,hookRegistry:this.hookRegistry,persistence:this.persistence,memory:this.memory,devtools:this.devtools,recorder:this.recorder,clock:this.clock,describeImages:this.describeImages,pauseRequested:()=>this.pauseRequested,compactionPending:this.compactionPending,promptRefresh:this.promptRefresh,getCompactionTimeoutMs:this.getCompactionTimeoutMs,usageTracker:this.usageTracker,publish:e=>this.publish(e),setSystemPrompt:e=>{this.systemPrompt=e},setThinkingLevel:e=>{this.thinkingLevel=e},setCompactionPending:e=>{this.compactionPending=e}}}steer(e){return Dt(this.steerDeps,e)}removeSteer(e){return Ot(this.steerDeps,e)}followUp(e){kt(this.steerDeps,e)}abort(){this.promptGate&&(this.abortRequested=!0),this.pauseRequested=!1;let e=this.isExecuting,t=this.promptGate&&!this.runStartedThisPrompt;!e&&!t||(this.rejectPendingGates(),this.agent.abort())}pauseRun(){return this.ensureNotDisposed(),this.isBusy?(this.pauseRequested=!0,this.publish({"run.pause_requested":[{type:`run.pause_requested`,sessionId:this.id}]}),!0):!1}cancelPauseRun(){return this.ensureNotDisposed(),!this.isBusy||!this.pauseRequested?!1:(this.pauseRequested=!1,this.publish({"run.pause_cancelled":[{type:`run.pause_cancelled`,sessionId:this.id}]}),!0)}resumeRun(){this.ensureNotDisposed(),this.pauseRequested&&(this.pauseRequested=!1,this.publish({"run.resumed":[{type:`run.resumed`,sessionId:this.id}]}))}get isPaused(){return this.pauseRequested}async compact(e,t){this.ensureNotDisposed(),await dt(this.compactionDeps(),e,t)}async compactNow(e){return this.ensureNotDisposed(),ft({...this.compactionDeps(),memory:this.memory,persistence:this.persistence},e)}compactionDeps(){return{session:this.session,sessionId:this.id,hookRegistry:this.hookRegistry,logger:this.logger,publish:e=>this.publish(e)}}async clearContext(){this.ensureNotDisposed(),this.isBusy&&(this.abort(),await this.currentPrompt?.catch(()=>{}));let e=this.session.messages().length;this.session.clearContext(),this.memory?.clearSession?.(this.id),this.logger.info({sessionId:this.id,clearedCount:e},`Session context cleared (/clear)`),this.publish({"session.cleared":[{type:`session.cleared`,sessionId:this.id,clearedCount:e}]})}clearTurnPanels(){this.session.setTodoList([]),this.session.setEditedFiles([]),this.session.setSubagents([]),this.session.setTurnSummaries([])}renameSession(e){this.session.setTitle(e,`custom`)}getCostSummary(){return this.usageTracker.getCostSummary()}getLastCacheHitRatio(){return this.usageTracker.getLastCacheHitRatio()}subscribe(e,t,n){if(typeof e==`function`)return this.subscribeAll((t,n)=>{e(n)});if(!t)throw Error(`callback is required when subscribing by type`);return super.subscribe(e,t,n)}async requestApproval(e,t,n,r){return this.gates.requestApproval(e,t,n,r)}resolveApproval(e,t){this.gates.resolveApproval(e,t)}async requestGrill(e){return this.gates.requestGrill(e)}resolveAskUser(e,t){this.gates.resolveAskUser(e,t)}async requestPlanApproval(e){return this.gates.requestPlanApproval(e)}resolvePlanApproval(e,t,n){this.gates.resolvePlanApproval(e,t,n)}rejectPendingGates(){this.gates.rejectAll(Error(`Session aborted`))}ensureNotDisposed(){if(this.disposed)throw Error(`AgentSession ${this.id} has been disposed`)}backfillTitle(){this.titleManager.backfill()}dispose(){if(!this.disposed){this.disposed=!0,this.titleManager.dispose(),this.rejectPendingGates();for(let e of this.agentUnsubs)e();this.agentUnsubs.length=0,this.pauseRequested&&this.agent.status===`completed`||this.agent.abort(),this.memory?.forgetSession?.(this.id),this.publish({"session.end":[{type:`session.end`,sessionId:this.id}]}),this.removeAllListeners(),this.logger.info({sessionId:this.id},`Session disposed`)}}};function Pt(e,t,n,r,i,a){let o=a?.now()??Date.now(),s=new C(e,t,n.length);return s.restoreEntries([...n],{...r,createdAt:o,lastActiveAt:o,parentSessionId:t,forkPoint:n.length,tags:[...r.tags,`fork`]},i),s}function Ft(e,t){let n=m(e),r=m(n,t);if(!r.startsWith(n+h)&&r!==n)throw Error(`路径穿越拒绝:路径 "${t}" 不在工作目录 "${e}" 内`);return r}function It(e){return typeof e==`object`&&!!e&&`code`in e&&e.code===`ENOENT`}async function Lt(e,t){let n=[];for(let r of t){let t=Ft(e,r);try{n.push({path:r,content:await Oe(t,`utf-8`)})}catch(e){if(It(e))n.push({path:r,content:null});else throw e}}return{files:n}}async function Rt(e,t){for(let n of t.files){let t=Ft(e,n.path);n.content===null?await Ae(t,{force:!0}):(await De(f(t),{recursive:!0}),await Ne(t,n.content,`utf-8`))}}function zt(e){return typeof e==`object`&&!!e&&`type`in e}function Bt(e){return typeof e==`object`&&!!e&&`id`in e&&`name`in e&&(`result`in e||`resultSummary`in e)}function Vt(e){return e.contentPreview?.map(e=>({type:`text`,text:e.text??e.preview??``}))??[]}function Ht(e){let t=new Map;for(let n of e.entries)t.set(n.id,n);let n=[],r=e.leafId?t.get(e.leafId):void 0;for(;r;)n.push(r),r=r.parentId?t.get(r.parentId):void 0;return n.reverse(),n.filter(e=>e.type===`message`).map(e=>e.message)}function Ut(e){return e.result?e.result.content:e.resultSummary?Vt(e.resultSummary):[]}function Wt(e){if(typeof e==`object`&&e&&`text`in e){let t=e.text;return typeof t==`string`?t:void 0}}function P(e,t){let n=[...e];for(let e of t)if(e.kind===`lifecycle`&&e.node===`prompt.before`){let t=Wt(e.payload);t!==void 0&&n.push({role:`user`,content:[{type:`text`,text:t}],timestamp:e.ts})}else if(e.kind===`stream`&&e.node===`stream.event`)zt(e.payload)&&e.payload.type===`done`&&n.push(e.payload.message);else if(e.kind===`tool`&&e.node===`tool.call.end`&&Bt(e.payload)){let{id:t,name:r,result:i,resultSummary:a}=e.payload,o=i?.isError??a?.isError??!1,s=i?.details??a?.details??{};n.push({role:`tool_result`,toolCallId:t,toolName:r,content:Ut(e.payload),isError:o,details:s,timestamp:e.ts})}return n}function Gt(e){return e.result?e.result:e.resultSummary?{content:Vt(e.resultSummary),isError:e.resultSummary.isError,details:e.resultSummary.details}:{content:[],isError:!0,details:{error:`unable to extract result from trace payload`}}}function Kt(e){let t=[],n=[];for(let r of e)r.kind===`stream`&&r.node===`stream.event`&&zt(r.payload)&&(n.push(r.payload),r.payload.type===`done`&&(t.push(n),n=[]));return n.length>0&&t.push(n),t}function qt(e){let t=Kt(e),r=0;return()=>{let e=t[r]??[];r++;let i=n(),a;for(let t of e)i.push(t),t.type===`done`?a=t.message:`partial`in t&&(a=t.partial);return a?i.complete(a):i.fail(Error(`replay stream: no recorded LLM events for this turn`)),i}}function Jt(e){let t=new Map;for(let n of e)n.kind===`tool`&&n.node===`tool.call.end`&&Bt(n.payload)&&t.set(n.payload.id,Gt(n.payload));return t}function Yt(e,t){return e.map(e=>({...e,execute:async e=>t.get(e.id)||{content:[{type:`text`,text:`replay: no recorded result for tool call ${e.id}`}],isError:!0}}))}var Xt=class extends Error{constructor(){super(`L2 deterministic re-execution requires a SandboxRunner (x-web-container runtime), which is not yet available. Use replay level "L1" (record/replay of tool results) for now.`),this.name=`SandboxUnavailableError`}},Zt=class{constructor(e){this.deps=e}replayPorts(e,t){let n=[...e];return{clock:ye(xe(n)).clock,stream:qt(n),tools:Yt(t,Jt(n)),disableMemory:!0}}async replaySession(e,t,n={}){if(!this.deps.traceStore)throw Error(`replaySession requires a traceStore (record mode must be enabled)`);if((n.level??`L1`)===`L2`&&!n.sandbox)throw new Xt;let r=this.deps.getConfig(e);if(!r)throw Error(`Cannot replay unknown session "${e}" (no resolved config)`);let i=[];for await(let t of this.deps.traceStore.read(e))i.push(t.entry);return this.deps.createSession({...r,id:t},this.replayPorts(i,r.tools))}async createCheckpoint(e,t={}){if(!this.deps.checkpointStore)throw Error(`createCheckpoint requires a checkpointStore`);let n=this.deps.getSession(e);if(!n)throw Error(`Cannot checkpoint unknown session "${e}"`);let r=n.session;if(!(r instanceof C))throw Error(`Session "${e}" does not support snapshots`);if(n.isBusy)throw Error(`Cannot checkpoint session "${e}" while a prompt is in flight (session busy); checkpoint requires a quiescent session for a consistent {conversation, traceSeq}`);let i=r.toSnapshot(),a=await this.ensureHydrated(e,i.entries,`checkpoint capture`),o=await this.countTraceEvents(e),s={sessionId:e,label:t.label,createdAt:Date.now(),traceSeq:o,conversation:{version:w,id:e,entries:a,metadata:i.metadata,leafId:i.leafId},files:t.files?await Lt(n.workspaceDir,t.files):void 0},c=await this.deps.checkpointStore.append(e,s);return{...c.entry,seq:c.seq}}async listCheckpoints(e){if(!this.deps.checkpointStore)return[];let t=[];for await(let n of this.deps.checkpointStore.read(e))t.push({...n.entry,seq:n.seq});return t}async restoreCheckpoint(e,t,n=`both`){if(!this.deps.checkpointStore)throw Error(`restoreCheckpoint requires a checkpointStore`);let r=this.deps.getSession(e);if(!r)throw Error(`Cannot restore unknown session "${e}"`);if(r.isBusy)throw Error(`Cannot restore/rollback session "${e}" while a prompt is in flight (session busy); abort the active prompt before rewinding`);let i=await this.readCheckpoint(e,t);if(n===`conversation`||n===`both`){let t=r.session;if(t instanceof C){let n=await this.ensureHydrated(e,i.conversation.entries,`checkpoint restore`);t.restoreEntries(n,i.conversation.metadata,i.conversation.leafId)}}(n===`code`||n===`both`)&&i.files&&await Rt(r.workspaceDir,i.files)}async ensureHydrated(e,t,n){if(!ue(t))return[...t];if(!this.deps.hydrateEntries)throw Error(`${n}: entries contain stripped compaction replacements but no hydrateEntries capability is wired (RFC-160 D4); refusing to proceed with stripped state`);return this.deps.hydrateEntries(e,t)}async readCheckpoint(e,t){if(!this.deps.checkpointStore)throw Error(`checkpoint operations require a checkpointStore`);let n;for await(let r of this.deps.checkpointStore.read(e,{from:t,to:t+1}))n=r.entry;if(!n)throw Error(`Checkpoint seq=${t} not found for session "${e}"`);if(n.conversation.version!==w)throw Error(`Checkpoint seq=${t} for session "${e}" has incompatible snapshot version ${n.conversation.version} (expected ${w})`);return n}async rollbackToCheckpoint(e,t,n=`both`){let r=await this.readCheckpoint(e,t);await this.restoreCheckpoint(e,t,n),this.deps.traceStore&&await this.deps.traceStore.truncate(e,r.traceSeq),this.deps.logger.info({sessionId:e,seq:t,traceSeq:r.traceSeq,mode:n},`Session rolled back`)}async forkFromCheckpoint(e,t,n){let r=this.deps.getSession(e),i=this.deps.getConfig(e);if(!r||!i)throw Error(`Cannot fork unknown session "${e}"`);let a=await this.readCheckpoint(e,t),o=n??crypto.randomUUID();if(this.deps.ensureCapacity(o),this.deps.traceStore)for await(let t of this.deps.traceStore.read(e,{to:a.traceSeq}))await this.deps.traceStore.append(o,t.entry);if(this.deps.checkpointStore)for await(let t of this.deps.checkpointStore.read(e))t.entry.traceSeq<=a.traceSeq&&await this.deps.checkpointStore.append(o,{...t.entry,sessionId:o});let s=Pt(o,e,await this.ensureHydrated(e,a.conversation.entries,`forkFromCheckpoint`),a.conversation.metadata,a.conversation.leafId),c=await this.deps.adoptForkedSession(s,{...i});return this.deps.logger.info({sessionId:o,sourceId:e,fromSeq:t},`Session forked from checkpoint`),c}async countTraceEvents(e){if(!this.deps.traceStore)return 0;let t=await this.deps.traceStore.count?.(e);if(t!==void 0)return t;let n=0;for await(let t of this.deps.traceStore.read(e))n++;return n}async replayTrace(e,t,n=0){if(!this.deps.traceStore)return[];let r={from:n,to:t===void 0?void 0:t+1},i=[];for await(let t of this.deps.traceStore.read(e,r))i.push(t.entry);return i}async traceback(e,t){let n=(await this.listCheckpoints(e)).filter(e=>e.traceSeq<=t).reduce((e,t)=>e===void 0||t.traceSeq>e.traceSeq?t:e,void 0),r=n?.traceSeq??0,i=n?Ht(n.conversation):[],a=await this.replayTrace(e,t,r);return{toSeq:t,baselineCheckpointSeq:n?.seq??null,fromTraceSeq:r,events:a,messages:P(i,a)}}};const F={healthy:1,warning:2,critical:4};var Qt=class{level=`healthy`;setLevel(e){this.level=e}get currentLevel(){return this.level}effectiveMaxMessages(e){return Math.max(1,Math.floor(e/F[this.level]))}effectiveMaxBytes(e){return Math.max(1,Math.floor(e/F[this.level]))}};const $t=2e3;var en=class{gaps=new Map;constructor(e){this.deps=e}async detect(e,t){let n=this.deps.traceStore;if(!n)return;let r=t.entries[t.entries.length-1]?.timestamp??0;if(r!==0)try{let t=await n.count?.(e.id)??void 0,i=t!==void 0&&t>$t?{from:t-$t}:void 0,a=0,o=0;for await(let t of n.read(e.id,i)){let e=t.entry;e.kind!==`lifecycle`||e.node!==`turn.end`||e.ts>r+1e4&&(o++,e.ts>a&&(a=e.ts))}if(o===0)return;this.deps.logger.warn({sessionId:e.id,lostTurns:o,lastPersistedAt:r,lastTraceAt:a},`RFC-305 D3: crash gap detected — turns recorded in trace but never persisted to DB (lost in previous abnormal termination)`);let s={lostTurns:o,lastPersistedAt:r,lastTraceAt:a};this.gaps.set(e.id,s),this.deps.onDetected?.(e,s)}catch(t){this.deps.logger.debug?.({sessionId:e.id,err:t instanceof Error?t.message:String(t)},`RFC-305 D3: crash-gap reconciliation skipped (trace read failed)`)}}consume(e){let t=this.gaps.get(e);return this.gaps.delete(e),t}forget(e){this.gaps.delete(e)}};function tn(e,t){return t<=0?1:Math.min(1,e/t)}function I(e){let t=e.config?.totalBytes??Re,n=e.config?.minPerSessionBytes??Le,r=e.config?.maxPerSessionBytes??Ie,i=tn(e.currentTotalResidentBytes,t),a=Math.max(1,e.activeSessionCount),o=Math.floor(t*(1-i)/a),s=Math.max(n,Math.min(o,r)),c=Math.max(Math.floor(n/e.pressureDivisor),Math.floor(s/e.pressureDivisor));return{maxBytesPerSession:Math.max(1,c),globalPressure:Number(i.toFixed(4)),isGlobalPressure:i>=.85}}function nn(e,t,n){return n?e.wouldByteTrimTouchActiveContext(Math.max(1,t)):e.wouldTrimTouchActiveContext(Math.max(1,t))}const rn=.9;function an(e){let t=e.agentSession.session,n=I({activeSessionCount:e.activeSessionCount,currentTotalResidentBytes:e.currentTotalResidentBytes,pressureDivisor:e.pressureDivisor,config:e.residencyConfig}),r=t instanceof C?t.messageCount:0,i=Math.max(1,Math.floor(e.maxMessages*rn)),a=Math.max(1,Math.floor(n.maxBytesPerSession*rn));if(!(t instanceof C))return{action:`none`,maxBytes:n.maxBytesPerSession,isLossy:!1,boundaryLimited:!1,activeOversized:!1};let o=r>e.maxMessages&&nn(t,i,!1),s=t.estimatedContentBytes>n.maxBytesPerSession&&nn(t,a,!0),c=o||s,l=(e.lossyFailureCount??0)>=3;if(c&&!l)return{action:`request-compaction`,maxBytes:n.maxBytesPerSession,isLossy:!1,boundaryLimited:!1,activeOversized:!1};if(!c){let i=t.estimatedContentBytes>n.maxBytesPerSession,a=r>e.maxMessages;if(!i&&!a)return{action:`none`,maxBytes:n.maxBytesPerSession,isLossy:!1,boundaryLimited:!1,activeOversized:!1}}return{action:`trim`,maxBytes:n.maxBytesPerSession,isLossy:l&&c,boundaryLimited:!1,activeOversized:!1}}const L=.9;var on=class{evalBaseline=new Map;publishBaseline=new Map;compactionFailures=new Map;compactionRequestBaseline=new Map;constructor(e){this.deps=e}evaluate(e){let t={action:`none`,removedCount:0,lossy:!1,shouldPublish:!1,trigger:`count`,capValue:0},n=e.session;if(!(n instanceof C))return t;let r=e.id,i=this.deps.residencyGovernor,a=i?i.effectiveMaxMessages(this.deps.maxHistoryMessages):this.deps.maxHistoryMessages,o=an({agentSession:e,activeSessionCount:this.deps.countActiveSessions(),currentTotalResidentBytes:this.deps.sumEstimatedContentBytes(),pressureDivisor:i?this.deps.levelDivisor[i.currentLevel]:1,residencyConfig:this.deps.getResidencyConfig?.(),maxMessages:a,lossyFailureCount:this.compactionFailures.get(r)}),s=o.maxBytes,c=e=>e.role!==`tool_result`,l=n.messageCount;if(o.action===`request-compaction`)return this.deps.requestCompaction(e,l),this.deps.logger.debug({sessionId:r,msgCount:l},`[cap] trim would touch active context; requested compaction first, skipping trim this round (RFC-321 R12)`),this.evalBaseline.set(r,l),{...t,action:`request-compaction`};if(o.action===`none`)return this.evalBaseline.set(r,l),t;let u=o.isLossy,d=(this.compactionFailures.get(r)??0)>=3,f=Math.max(1,Math.floor(a*L)),p=Math.max(1,Math.floor(s*L)),m=l>a?n.capStoredHistory(f,c):{capped:!1,removedCount:0,boundaryLimited:!1,activeOversized:!1},h=n.estimatedContentBytes>s?n.capStoredHistoryByBytes(p,c):{capped:!1,removedCount:0,boundaryLimited:!1,activeOversized:!1},g=m.removedCount+h.removedCount,_=u&&g>0;u&&this.compactionFailures.delete(r),(m.boundaryLimited||h.boundaryLimited)&&this.deps.logger.debug({sessionId:r,removedCount:g,msgCount:l,activeOversized:m.activeOversized||h.activeOversized},`[cap] trimming stopped at active compaction boundary (RFC-321 R4); may remain above cap`),(m.activeOversized||h.activeOversized)&&!d&&(this.deps.requestCompaction(e,l),this.deps.logger.debug({sessionId:r,msgCount:l,bytes:n.estimatedContentBytes},`[cap] active region itself exceeds cap (RFC-321 activeOversized); compaction needed`));let v=this.publishBaseline.get(r),y=Math.max(1,Math.floor(a*(1-L))),b=!_&&v!==void 0&&l<v+y,x=g>0&&!b,S=i&&i.currentLevel!==`healthy`?`memory-pressure`:h.removedCount>m.removedCount?`bytes`:`count`;return x&&this.publishBaseline.set(r,l),this.evalBaseline.set(r,l-g),{action:`trim`,removedCount:g,lossy:_,shouldPublish:x,trigger:S,capValue:S===`bytes`?s:a}}shouldEvaluateInline(e){let t=e.session;if(!(t instanceof C))return!1;let n=t.messageCount,r=this.evalBaseline.get(e.id);return r===void 0?(this.evalBaseline.set(e.id,n),!1):n-r>=this.deps.inlineCheckInterval}shouldRequestCompaction(e,t){let n=this.compactionRequestBaseline.get(e);return n!==void 0&&t<n+this.deps.inlineCheckInterval?!1:(this.compactionRequestBaseline.set(e,t),!0)}onCompactionSucceeded(e){this.compactionFailures.delete(e)}onCompactionFailed(e){let t=(this.compactionFailures.get(e)??0)+1;return this.compactionFailures.set(e,t),t}forget(e){this.evalBaseline.delete(e),this.publishBaseline.delete(e),this.compactionFailures.delete(e),this.compactionRequestBaseline.delete(e)}};const R={touch:!1};function z(e,t){if(e===t)return!0;if(typeof e!=typeof t||e===null||t===null||typeof e!=`object`||typeof t!=`object`||Array.isArray(e)!==Array.isArray(t))return!1;if(Array.isArray(e)&&Array.isArray(t))return e.length===t.length?e.every((e,n)=>z(e,t[n])):!1;let n=e,r=t,i=Object.keys(n),a=Object.keys(r);return i.length===a.length?i.every(e=>Object.hasOwn(r,e)&&z(n[e],r[e])):!1}function B(e,t){return e===void 0&&t===void 0?!0:e===void 0||t===void 0||e.length!==t.length?!1:z(e,t)}var sn=class{constructor(e){this.deps=e}async restore(e,t,n){let r=this.deps.panelStateStore;if(!r)return;let i=await r.loadAll(n);if(i){i.todoList!==void 0&&e.setTodoList(i.todoList,R),i.editedFiles!==void 0&&e.setEditedFiles(i.editedFiles,R),i.subagents!==void 0&&e.setSubagents(i.subagents,R),i.drafts!==void 0&&e.setDrafts(i.drafts,R),i.turnSummaries!==void 0&&e.setTurnSummaries(i.turnSummaries,R);return}let a=t.metadata.config,o=a?.todoList,s=a?.editedFiles,c=a?.subagents,l=a?.drafts;!o&&!s&&!c&&!l||(o&&e.setTodoList(o,R),s&&e.setEditedFiles(s,R),c&&e.setSubagents(c,R),l&&e.setDrafts(l,R),B(o,e.getTodoList())&&B(s,e.getEditedFiles())&&B(c,e.getSubagents())&&B(l,e.getDrafts())?await r.saveAll(n,{sessionId:n,todoList:o??[],editedFiles:s??[],subagents:c??[],drafts:l??[]}):this.deps.logger.warn({sessionId:n},`PanelState migration verification failed, using legacy in-memory data without persisting`))}},V=class{constructor(e,t){this.persistence=e,this.pasteStatePersistence=t}async getTodoList(e){return(await this.persistence.load(e))?.todoList}async setTodoList(e,t){let n=await this.loadOrInit(e);n.todoList=t,await this.persistence.save(n)}async getEditedFiles(e){return(await this.persistence.load(e))?.editedFiles}async setEditedFiles(e,t){let n=await this.loadOrInit(e);n.editedFiles=t,await this.persistence.save(n)}async getSubagents(e){return(await this.persistence.load(e))?.subagents}async setSubagents(e,t){let n=await this.loadOrInit(e);n.subagents=t,await this.persistence.save(n)}async getDrafts(e){return(await this.persistence.load(e))?.drafts}async setDrafts(e,t){let n=await this.loadOrInit(e);n.drafts=t,await this.persistence.save(n)}async getTurnSummaries(e){return(await this.persistence.load(e))?.turnSummaries}async setTurnSummaries(e,t){let n=await this.loadOrInit(e);n.turnSummaries=t,await this.persistence.save(n)}async getPaste(e){if(!this.pasteStatePersistence)return{sessionId:e,entries:[],nextId:1};try{return ee(e,await this.pasteStatePersistence.load(e))}catch{return{sessionId:e,entries:[],nextId:1}}}async setPaste(e,t){if(!this.pasteStatePersistence)return!1;if(t.sessionId!==e)throw Error(`PanelStateStore.setPaste: snapshot.sessionId (${t.sessionId}) !== sessionId (${e})`);try{return await this.pasteStatePersistence.save(t),!0}catch{return!1}}async deletePaste(e){if(!this.pasteStatePersistence)return!1;try{return await this.pasteStatePersistence.delete(e)}catch{return!1}}async loadAll(e){return this.persistence.load(e)}async saveAll(e,t){if(t.sessionId!==e)throw Error(`PanelStateStore.saveAll: snapshot.sessionId (${t.sessionId}) !== sessionId (${e})`);await this.persistence.save(t)}async loadOrInit(e){return await this.persistence.load(e)??{sessionId:e}}};function cn(e){let t={};return e.interactive!==void 0&&(t.interactive=e.interactive),e.listable!==void 0&&(t.listable=e.listable),e.depth!==void 0&&(t.depth=e.depth),e.agentName!==void 0&&(t.agentName=e.agentName),e.thinkingLevel!==void 0&&(t.thinkingLevel=e.thinkingLevel),e.maxToolTurnExtensions!==void 0&&(t.maxToolTurnExtensions=e.maxToolTurnExtensions),e.transient!==void 0&&(t.transient=e.transient),e.model?.id&&(t.modelId=e.model.id),e.systemTail!==void 0&&(t.systemTail=e.systemTail),e.workspaceDir!==void 0&&(t.workspaceDir=e.workspaceDir),e.maxToolTurns!==void 0&&(t.maxToolTurns=e.maxToolTurns),e.permissionAlwaysAllow&&e.permissionAlwaysAllow.length>0&&(t.permissionAlwaysAllow=[...e.permissionAlwaysAllow]),e.availableModels&&e.availableModels.length>0&&(t.availableModels=[...e.availableModels]),t}function ln(e,t){if(!t)return e;let n={...e};return t.interactive!==void 0&&(n.interactive=t.interactive),t.listable!==void 0&&(n.listable=t.listable),t.depth!==void 0&&(n.depth=t.depth),t.agentName!==void 0&&(n.agentName=t.agentName),t.thinkingLevel!==void 0&&(n.thinkingLevel=t.thinkingLevel),t.maxToolTurnExtensions!==void 0&&(n.maxToolTurnExtensions=t.maxToolTurnExtensions),t.transient!==void 0&&(n.transient=t.transient),t.systemTail!==void 0&&(n.systemTail=t.systemTail),t.workspaceDir!==void 0&&(n.workspaceDir=t.workspaceDir),t.maxToolTurns!==void 0&&(n.maxToolTurns=t.maxToolTurns),t.permissionAlwaysAllow!==void 0&&(n.permissionAlwaysAllow=[...t.permissionAlwaysAllow]),t.availableModels!==void 0&&(n.availableModels=[...t.availableModels]),n}var un=class{saveChains=new Map;crashGapDetector;panelStateRestorer;turnSaveState=new Map;leaseDeniedState=new Map;remoteRevisions=new Map;residencyCoordinator;constructor(e){this.deps=e,this.residencyCoordinator=new on({logger:e.logger,...e.residencyGovernor?{residencyGovernor:e.residencyGovernor}:{},...e.getResidencyConfig?{getResidencyConfig:e.getResidencyConfig}:{},countActiveSessions:()=>this.countActiveSessionsForAllocation(),sumEstimatedContentBytes:()=>this.sumEstimatedContentBytes(),requestCompaction:(e,t)=>this.requestEscapeValveCompaction(e,t),maxHistoryMessages:Fe,inlineCheckInterval:200,levelDivisor:F}),this.panelStateRestorer=new sn({...e.panelStateStore?{panelStateStore:e.panelStateStore}:{},logger:e.logger}),this.crashGapDetector=new en({traceStore:e.traceStore,logger:e.logger,onDetected:(e,t)=>{e.publish({"session.crash-gap-detected":[{type:`session.crash-gap-detected`,sessionId:e.id,lostTurns:t.lostTurns,lastPersistedAt:t.lastPersistedAt,lastTraceAt:t.lastTraceAt}]})}})}applyResidencyCaps(e){let t=this.residencyCoordinator.evaluate(e);t.shouldPublish&&e.publish({"session.history-capped":[{type:`session.history-capped`,sessionId:e.id,removedCount:t.removedCount,trigger:t.trigger,capValue:t.capValue,...t.lossy?{lossy:!0}:{}}]})}requestEscapeValveCompaction(e,t){this.residencyCoordinator.shouldRequestCompaction(e.id,t)&&(e.compactionPending=e.compactNow().then(t=>(t.compacted?this.residencyCoordinator.onCompactionSucceeded(e.id):this.residencyCoordinator.onCompactionFailed(e.id),this.deps.logger.info({sessionId:e.id,compacted:t.compacted,before:t.before,after:t.after},`[cap] escape-valve compaction requested (RFC-321 R12 compaction-first)`),t)).catch(t=>{let n=this.residencyCoordinator.onCompactionFailed(e.id);return this.deps.logger.warn({sessionId:e.id,error:t,failures:n},`[cap] escape-valve compaction failed; lossy trim allowed after threshold`),{compacted:!1,before:0,after:0}}))}maybeInlineCapEval(e){this.residencyCoordinator.shouldEvaluateInline(e)&&this.applyResidencyCaps(e)}track(e,t){if(!this.deps.autoPersist||t)return;let n=this.deps.persistence,r=e.session;r instanceof C&&typeof n.getPersistedCursor==`function`&&r.setReplacementStripEligibility(t=>{let i=n.getPersistedCursor(e.id);if(!i)return this.deps.logger.debug?.({sessionId:e.id,entryId:t},`RFC-160 D2a: skip runtime replacement strip (no persisted cursor yet)`),!1;let a=!1;for(let n of r.entries())if(n.id===t&&(a=!0),n.id===i)return a||this.deps.logger.debug?.({sessionId:e.id,entryId:t,cursor:i},`RFC-160 D2a: skip runtime replacement strip (entry beyond persisted cursor)`),a;return!1});let i=t=>{if(t instanceof Error&&t.name===`SessionWriteLeaseDeniedError`){let t=this.leaseDeniedState.get(e.id)===!0;return this.leaseDeniedState.set(e.id,!0),t||e.publish({"session.write-lease-denied":[{type:`session.write-lease-denied`,sessionId:e.id}]}),!0}return!1},a=()=>{this.leaseDeniedState.get(e.id)===!0&&(this.leaseDeniedState.set(e.id,!1),e.publish({"session.write-lease-restored":[{type:`session.write-lease-restored`,sessionId:e.id}]}))},o=()=>{this.enqueue(e.id,async()=>{try{await this.doSave(e.id),a()}catch(t){i(t)||this.deps.logger.warn({sessionId:e.id,err:t instanceof Error?t.message:String(t)},`Session auto-persist failed`)}})},s=()=>{let t=e.id;this.enqueue(t,async()=>{try{await this.doSaveEntries(t),a()}catch(e){i(e)||this.deps.logger.warn({sessionId:t,err:e instanceof Error?e.message:String(e)},`Session turn-level auto-persist failed`)}})};e.subscribe(`prompt.end`,o),e.subscribe(`error`,o),e.subscribe(`session.cleared`,()=>{this.enqueue(e.id,async()=>{try{await this.doSave(e.id),a();let t=e.session;if(t instanceof C){let n=t.purgeClearedHistory();(n.removedCount>0||n.strippedReplacements>0)&&this.deps.logger.debug?.({sessionId:e.id,...n},`RFC-194: purged cleared history after successful save`)}}catch(t){i(t)||this.deps.logger.warn({sessionId:e.id,err:t instanceof Error?t.message:String(t)},`Session clear-persist failed (purge skipped, residency left to RFC-178 caps)`)}})}),e.subscribe(`turn.end`,()=>{let t=e.id;if(this.maybeInlineCapEval(e),(this.deps.turnFlush??`incremental`)===`snapshot`){let e=Date.now(),n=this.turnSaveState.get(t);if(!n){this.turnSaveState.set(t,{lastSaveAt:e,turnsSinceSave:1});return}n.turnsSinceSave++;let r=e-n.lastSaveAt;if(n.turnsSinceSave<5&&r<3e4)return;n.lastSaveAt=e,n.turnsSinceSave=0}s()}),e.setInputBoundaryFlusher?e.setInputBoundaryFlusher(()=>this.requestInputBoundaryFlush(e,t)):this.deps.logger.debug?.({sessionId:e.id},`RFC-336 D2: input-boundary flush disabled (session lacks setInputBoundaryFlusher)`)}async flushPending(e){let t=this.saveChains.get(e);t&&await t.catch(t=>{this.deps.logger.warn({sessionId:e,err:t instanceof Error?t.message:String(t)},`flushPending: pending save chain settled with failure (already logged by the job itself; surfaced here for removeSession/restore callers)`)}),this.leaseDeniedState.delete(e),this.turnSaveState.delete(e),this.remoteRevisions.delete(e)}countActiveSessionsForAllocation(){let e=this.deps.listSessionIds(),t=0;for(let n of e)this.deps.getConfig?.(n)?.transient!==!0&&t++;return Math.max(1,t)}sumEstimatedContentBytes(){let e=0;for(let t of this.deps.listSessionIds()){if(this.deps.getConfig?.(t)?.transient===!0)continue;let n=this.deps.getSession(t);n?.session instanceof C&&(e+=n.session.estimatedContentBytes)}return e}forgetSession(e){this.leaseDeniedState.delete(e),this.residencyCoordinator.forget(e),this.crashGapDetector.forget(e),this.turnSaveState.delete(e),this.remoteRevisions.delete(e)}forgetEvictedSession(e){this.deps.getSession(e)||this.forgetSession(e)}isTransient(e){return this.deps.getConfig?.(e)?.transient===!0}async save(e){return this.enqueue(e,()=>this.doSave(e))}requestInputBoundaryFlush(e,t){if(!this.deps.autoPersist||t||(this.deps.turnFlush??`incremental`)===`snapshot`)return;let n=e.id;this.enqueue(n,async()=>{try{await this.doSaveEntries(n)}catch(e){if(e instanceof Error&&e.name===`SessionWriteLeaseDeniedError`)return;this.deps.logger.warn({sessionId:n,err:e instanceof Error?e.message:String(e)},`Input-boundary flush failed (RFC-336 D2; falls back to turn/prompt-end persistence)`)}})}precreateSessionRow(e,t){if(!this.deps.autoPersist||t)return;let n=e.id;this.enqueue(n,async()=>{try{await this.doSaveEntries(n)}catch(e){if(e instanceof Error&&e.name===`SessionWriteLeaseDeniedError`)return;this.deps.logger.warn({sessionId:n,err:e instanceof Error?e.message:String(e)},`Session row pre-creation failed (RFC-336 D1; falls back to first-turn persistence)`)}})}saveSnapshot(e,t,n){if(this.isTransient(e))return n?.(),Promise.resolve();let r=this.mergeSnapshotConfig(e,t.metadata),i=this.enqueue(e,async()=>{let n={version:w,id:e,...t,metadata:r};if(this.isRemoteCasPersistence()?await this.saveRemoteWithCas(e,n):await this.deps.persistence.save(n),this.deps.panelStateStore){let t=this.deps.getSession(e)?.session;t&&await this.deps.panelStateStore.saveAll(e,{sessionId:e,todoList:t.getTodoList(),editedFiles:t.getEditedFiles(),subagents:t.getSubagents(),drafts:t.getDrafts(),turnSummaries:t.getTurnSummaries()})}});return n&&i.then(n,n),i}mergeSnapshotConfig(e,t){let n=this.deps.getConfig?.(e),r=n?cn(n):void 0,i=t.config?.inputHistory,a=r||i?{...r,...i?{inputHistory:i}:{}}:void 0;return a?{...t,config:a}:t}enqueue(e,t){let n=(this.saveChains.get(e)??Promise.resolve()).catch(()=>{}).then(t);this.saveChains.set(e,n);let r=()=>{this.saveChains.get(e)===n&&this.saveChains.delete(e)};return n.then(r,r),n}async doSaveEntries(e){if(this.isTransient(e))return;let t=this.deps.getSession(e);if(!t)return;let n=t.session;if(n instanceof C){this.applyResidencyCaps(t);let r=n.toSnapshot(),i=this.mergeSnapshotConfig(n.id,r.metadata),a={version:w,id:n.id,...r,metadata:i};this.isRemoteCasPersistence()?await this.saveRemoteWithCas(e,a):await this.deps.persistence.save(a)}}isRemoteCasPersistence(){return typeof this.deps.persistence.saveWithRevision==`function`}async saveRemoteWithCas(e,t){let n=this.deps.persistence,r=this.remoteRevisions.get(e);try{let i=await n.saveWithRevision(t,r);this.remoteRevisions.set(e,i)}catch(i){if(!(i instanceof se))throw i;this.deps.logger.warn({sessionId:e,expectedRevision:r,serverRevision:i.info.revision},`Remote session CAS conflict; reloading + rebasing for one retry`);let a=await n.loadWithRevision(e);if(!a){let r=await n.saveWithRevision(t,0);this.remoteRevisions.set(e,r);return}let o=this.rebaseSnapshotAgainstRemote(t,a.snapshot),s=await n.saveWithRevision(o,a.revision);this.remoteRevisions.set(e,s)}}rebaseSnapshotAgainstRemote(e,t){let n=new Set(t.entries.map(e=>e.id)),r=e.entries.filter(e=>!n.has(e.id));return{version:w,id:e.id,entries:[...t.entries,...r],metadata:e.metadata,leafId:e.leafId??t.leafId}}async doSave(e){if(await this.doSaveEntries(e),this.isTransient(e))return;let t=this.deps.getSession(e);if(!t)return;let n=t.session;this.deps.panelStateStore&&await this.deps.panelStateStore.saveAll(e,{sessionId:e,todoList:n.getTodoList(),editedFiles:n.getEditedFiles(),subagents:n.getSubagents(),drafts:n.getDrafts(),turnSummaries:n.getTurnSummaries()})}async saveAll(){let e=[...this.deps.listSessionIds()].filter(e=>{let t=this.deps.getSession(e)?.session;return!(t instanceof C)||t.entries().length>0});(await Promise.allSettled(e.map(e=>this.save(e)))).forEach((t,n)=>{t.status===`rejected`&&this.deps.logger.warn({sessionId:e[n],err:t.reason instanceof Error?t.reason.message:String(t.reason)},`saveAll: a session failed to persist (others unaffected)`)}),await Promise.allSettled([...this.saveChains.values()])}async restore(e){if(!this.deps.configProvider)return null;let t=this.deps.getSession(e);if(t)return t;await this.flushPending(e);let n=this.isRemoteCasPersistence()?await this.deps.persistence.loadWithRevision(e):null,r=n?.snapshot??(n===null&&this.isRemoteCasPersistence()?null:await this.deps.persistence.load(e));if(!r)return null;if(r.version!==w)return this.deps.logger.warn({sessionId:e,version:r.version,expected:w},`Session snapshot version mismatch, skipped`),null;if(!this.deps.canAccommodate(e))throw Error(`Max sessions reached, cannot restore ${e}.`);let i=new C(r.id);i.restoreEntries(r.entries,r.metadata,r.leafId);let a=ln(this.deps.configProvider(r.metadata.config?.agentName,r.metadata.config?.modelId),r.metadata.config),o=await this.deps.adoptRestoredSession(i,a);return r.metadata.archived&&o.archive(),await this.panelStateRestorer.restore(i,r,e),n&&this.remoteRevisions.set(e,n.revision),this.track(o,!1),await this.crashGapDetector.detect(o,r),this.deps.logger.info({sessionId:e},`Session restored`),o}consumeCrashGap(e){let t=this.crashGapDetector.consume(e);return t?{lostTurns:t.lostTurns}:void 0}async restoreAll(){if(!this.deps.configProvider)return 0;let e=this.deps.capacityLeft();if(e===0){let e=(await this.deps.persistence.list()).filter(e=>!this.deps.hasSession(e)).length;return e>0&&this.deps.logger.info({candidates:e},`Session pool full, restoreAll skipped (restore on demand)`),0}let t=await this.deps.persistence.listRecentMeta(e),n=[],r=0;for(let e of t){if(this.deps.hasSession(e))continue;let t;try{if(this.isRemoteCasPersistence()){let n=await this.deps.persistence.loadWithRevision(e);t=n?{snapshot:n.snapshot,revision:n.revision}:null}else{let n=await this.deps.persistence.load(e);t=n?{snapshot:n}:null}}catch(t){this.deps.logger.warn({sessionId:e,err:t instanceof Error?t.message:String(t)},`restoreAll: a session snapshot failed to load (skipped, others unaffected)`);continue}if(!t)continue;let r=t.snapshot;if(r.version!==w){this.deps.logger.warn({sessionId:e,version:r.version,expected:w},`Session snapshot version mismatch, skipped`);continue}n.push(t)}let i=this.deps.capacityLeft();for(;n.length>i;)n.pop(),r++;r>0&&this.deps.logger.info({skipped:r,capacity:i},`Sessions exceeding pool capacity left on storage (restore on demand)`);let a=0,o=null;for(let e of n){let{snapshot:t}=e;if(!this.deps.hasSession(t.id))try{let n=new C(t.id);n.restoreEntries(t.entries,t.metadata,t.leafId);let r=ln(this.deps.configProvider(t.metadata.config?.agentName,t.metadata.config?.modelId),t.metadata.config),i=await this.deps.adoptRestoredSession(n,r);t.metadata.archived&&i.archive(),await this.panelStateRestorer.restore(n,t,t.id),e.revision!==void 0&&this.remoteRevisions.set(t.id,e.revision),this.track(i,!1),await this.crashGapDetector.detect(i,t),a++,o===null&&(o=t.id)}catch(e){this.deps.logger.warn({sessionId:t.id,err:e instanceof Error?e.message:String(e)},`restoreAll: 单条会话重建失败(跳过,余者不受影响)`)}}return o&&this.deps.setActiveIfNone(o),this.deps.logger.info({count:a},`Sessions restored`),a}},H=class{panelStateStoreRef;sessions=new Map;configs=new Map;residencyClock=new Map;persistence;maxSessions;idleTimeoutMs;threshold;activeSessionId;stream;hookRegistry;logger;devtools;memory;traceStore;checkpointStore;clock;residencyGovernor;getResidencyConfig;configProvider;listColdSessionsOverride;isSessionWriteLocked;inspectSessionWriteLeaseFn;forceReleaseSessionWriteLeaseFn;autoPersist;timeTravel;persistenceSync;constructor(e,t,n=!1){this.autoPersist=n,this.stream=i(e.providerRegistry),this.hookRegistry=e.hookRegistry,this.logger=e.logger,this.devtools=e.devtools,this.memory=e.memory,this.traceStore=e.traceStore,this.checkpointStore=e.checkpointStore,this.clock=e.clock,this.residencyGovernor=e.residencyGovernor,this.getResidencyConfig=e.getResidencyConfig,this.configProvider=e.configProvider,this.listColdSessionsOverride=e.listColdSessionsOverride,this.isSessionWriteLocked=e.isSessionWriteLocked,this.inspectSessionWriteLeaseFn=e.inspectSessionWriteLease,this.forceReleaseSessionWriteLeaseFn=e.forceReleaseSessionWriteLease,this.persistence=t;let r=e.maxSessions??le;this.maxSessions=r,this.idleTimeoutMs=e.idleTimeoutMs??ce,this.threshold=Math.max(0,Math.min(e.threshold??r,r)),this.timeTravel=new Zt({logger:this.logger,traceStore:this.traceStore,checkpointStore:this.checkpointStore,getSession:e=>this.sessions.get(e),getConfig:e=>this.configs.get(e),createSession:(e,t)=>this.createSession(e,t),ensureCapacity:e=>{if(this.sessions.has(e))throw Error(`Session with ID ${e} already exists.`);this.prepareCapacity(e)},adoptForkedSession:(e,t)=>this.adoptForkedSession(e,t),...de(this.persistence)?{hydrateEntries:(e,t)=>this.persistence.hydrateReplacements(e,t)}:{}}),this.persistenceSync=new un({persistence:this.persistence,logger:this.logger,autoPersist:this.autoPersist,traceStore:this.traceStore,turnFlush:this.persistence.turnFlush,getSession:e=>this.sessions.get(e),getConfig:e=>this.configs.get(e),hasSession:e=>this.sessions.has(e),listSessionIds:()=>this.sessions.keys(),canAccommodate:e=>this.canAccommodate(e),capacityLeft:()=>Math.max(0,this.maxSessions-this.sessions.size),adoptRestoredSession:async(e,t)=>{let n=this.buildAgentSession(e,t);return this.sessions.set(e.id,n),this.configs.set(e.id,t),this.admitToResidency(e.id),await this.hookRegistry.emit(`session.restored`,{sessionId:e.id,metadata:{}}),n.notifyCreated(),n},setActiveIfNone:e=>{this.activeSessionId||=e},configProvider:this.configProvider,panelStateStore:e.panelStateStore,residencyGovernor:e.residencyGovernor,getResidencyConfig:e.getResidencyConfig}),this.panelStateStoreRef=e.panelStateStore}get panelState(){return this.panelStateStoreRef}get active(){return this.activeSessionId?this.sessions.get(this.activeSessionId):void 0}getSessionPermissionAllow(e){return[...this.configs.get(e)?.permissionAlwaysAllow??[]]}setSessionPermissionAllow(e,t){let n=this.configs.get(e);if(n){if(t.length===0){delete n.permissionAlwaysAllow;return}n.permissionAlwaysAllow=[...t]}}getSessionAvailableModels(e){return[...this.configs.get(e)?.availableModels??[]]}setSessionAvailableModels(e,t){let n=this.configs.get(e);if(n){if(t.length===0){delete n.availableModels;return}n.availableModels=[...t]}}admitToResidency(e){this.residencyClock.set(e,(this.clock??T).now())}residencySince(e,t){let n=this.residencyClock.get(e)??-1/0;return Math.max(n,t.session.metadata().lastActiveAt)}trackPersistence(e,t){this.persistenceSync.track(e,t)}precreateSessionRow(e,t){this.persistenceSync.precreateSessionRow(e,t)}async adoptForkedSession(e,t){let n=this.buildAgentSession(e,t);return this.sessions.set(e.id,n),this.configs.set(e.id,t),this.admitToResidency(e.id),this.trackPersistence(n,!1),this.precreateSessionRow(n,!1),await this.hookRegistry.emit(`session.created`,{sessionId:e.id,metadata:{}}),n.notifyCreated(),n}buildAgentSession(e,t,n){let r=n??this.recordPorts(e.id);return new Nt(e,{getCompactionTimeoutMs:()=>O(this.getResidencyConfig?.()).compactionTimeoutMs,model:t.model,titleModel:t.titleModel,modelResolution:t.modelResolution,agentName:t.agentName,depth:t.depth,interactive:t.interactive,listable:t.listable,transient:t.transient,retryAccelerate:t.retryAccelerate,streamRetry:t.streamRetry,networkDisconnectRetry:t.networkDisconnectRetry,lifecycleAsyncTimeoutMs:t.lifecycleAsyncTimeoutMs,systemPrompt:t.systemPrompt,systemTail:t.systemTail,tools:r.tools??t.tools,thinkingLevel:t.thinkingLevel,maxToolTurns:t.maxToolTurns,maxToolTurnExtensions:t.maxToolTurnExtensions,promptOutputTokenBudget:t.promptOutputTokenBudget,promptWallClockBudgetMs:t.promptWallClockBudgetMs,stallDetection:t.stallDetection,sessionCostBudgetUSD:t.sessionCostBudgetUSD,todoContinuation:t.todoContinuation,promptRefresh:t.promptRefresh,workspaceDir:t.workspaceDir,workspaceId:t.workspaceId,hookRegistry:this.hookRegistry,stream:r.stream??this.stream,logger:this.logger.child({sessionId:e.id}),devtools:this.devtools,memory:r.disableMemory?void 0:this.memory,recorder:r.recorder,nondetFlush:r.nondetFlush,clock:r.clock,describeImages:t.describeImages})}recordPorts(e){let t=this.traceStore;if(!t)return{clock:this.clock};let n=this.clock??T,r=be({sink:{append:n=>t.append(e,n).then(()=>void 0)},sessionId:e,clock:n}),i=ve({clock:n,random:Ee,id:E},r);return{clock:i.clock,recorder:r,nondetFlush:i.flushNondetBatch}}async createSession(e,t){let n=e.id??E.uuid();if(this.sessions.has(n))throw Error(`Session with ID ${n} already exists.`);this.prepareCapacity(n);let r=new C(n);r.setSdkVersion(fe);let i=this.buildAgentSession(r,e,t);return this.sessions.set(n,i),this.configs.set(n,e),this.admitToResidency(n),(e.transient??!1)||(this.activeSessionId=n),this.trackPersistence(i,e.transient??!1),this.precreateSessionRow(i,e.transient??!1),await this.hookRegistry.emit(`session.created`,{sessionId:n,metadata:{}}),i.notifyCreated(),this.logger.info({sessionId:n},`Session created`),i}replaySession(e,t,n={}){return this.timeTravel.replaySession(e,t,n)}createCheckpoint(e,t={}){return this.timeTravel.createCheckpoint(e,t)}listCheckpoints(e){return this.timeTravel.listCheckpoints(e)}restoreCheckpoint(e,t,n=`both`){return this.timeTravel.restoreCheckpoint(e,t,n)}rollbackToCheckpoint(e,t,n=`both`){return this.timeTravel.rollbackToCheckpoint(e,t,n)}forkFromCheckpoint(e,t,n){return this.timeTravel.forkFromCheckpoint(e,t,n)}replayTrace(e,t,n=0){return this.timeTravel.replayTrace(e,t,n)}traceback(e,t){return this.timeTravel.traceback(e,t)}getSession(e){return this.sessions.get(e)}getResidencyDiagnostics(){let e=0,t=0;for(let[n,r]of this.sessions){if(this.configs.get(n)?.transient)continue;let i=r.session;i instanceof C&&(e++,t+=i.estimatedContentBytes)}let n=this.residencyGovernor?.currentLevel??`healthy`,r=I({activeSessionCount:e,currentTotalResidentBytes:t,pressureDivisor:F[n],config:this.getResidencyConfig?.()});return{activeSessionCount:e,totalResidentBytes:t,globalPressure:r.globalPressure,isGlobalPressure:r.isGlobalPressure,maxBytesPerSession:r.maxBytesPerSession,pressureLevel:n}}listSessions(e){let t=Array.from(this.sessions.values());e?.workspaceId&&(t=t.filter(t=>t.workspaceId===e.workspaceId));let n=t.map(e=>{let t=e.session.metadata();return{id:e.id,title:tt(t.title,e.session.messages(),e.id),messageCount:e.session.messages().length,createdAt:t.createdAt?new Date(t.createdAt):new Date,updatedAt:t.lastActiveAt?new Date(t.lastActiveAt):void 0,model:e.model.id,status:e.status,sdkVersion:t.sdkVersion,workspaceId:e.workspaceId,pinned:e.pinned,pinGroup:t.pinGroup,writeLocked:this.isSessionWriteLocked?.(e.id)??!1}});return n.sort((e,t)=>{let n=e.updatedAt?.getTime()??e.createdAt.getTime();return(t.updatedAt?.getTime()??t.createdAt.getTime())-n}),n}async listAllPersistedSessions(e){let t=e?.workspaceKey??`default`;if(this.listColdSessionsOverride)return this.listColdSessionsOverride(t);let n;try{n=await this.persistence.listPaginated({page:0,pageSize:100,sortBy:`lastActiveAt`,order:`desc`})}catch(e){return this.logger.warn({workspaceKey:t,err:e instanceof Error?e.message:String(e)},`listAllPersistedSessions: listPaginated failed (batch unavailable, not a per-session issue)`),[]}let r=[];for(let e of n.items)try{let t=await this.persistence.load(e);if(!t)continue;let n=t.metadata;r.push({id:e,title:n.title?.trim()||e.slice(0,8),messageCount:n.messageCount??0,createdAt:n.createdAt?new Date(n.createdAt):new Date,updatedAt:n.lastActiveAt?new Date(n.lastActiveAt):void 0,status:n.archived?`archived`:`idle`,pinned:n.pinned,pinGroup:n.pinGroup,writeLocked:this.isSessionWriteLocked?.(e)??!1})}catch(t){this.logger.warn({sessionId:e,err:t instanceof Error?t.message:String(t)},`listAllPersistedSessions: a session snapshot failed to load (skipped, others unaffected)`)}return r}backfillTitles(){let e=0,t=0;for(let n of this.sessions.values()){let r=n.session.metadata().titleSource;if(r===`custom`||r===`ai`){t++;continue}n.backfillTitle(),e++}return{triggered:e,skipped:t}}async archiveSession(e){let t=this.sessions.get(e);return t?(await this.persistenceSync.save(e),typeof this.persistence.archiveSession==`function`&&await this.persistence.archiveSession(e),t.archive(),!0):!1}async removeSession(e){let t=this.sessions.get(e);if(!t){await this.persistenceSync.flushPending(e);let t=await this.persistence.delete(e);return await this.clearSessionStores(e),t}return t.dispose(),this.sessions.delete(e),this.configs.delete(e),this.residencyClock.delete(e),this.activeSessionId===e&&(this.activeSessionId=void 0),await this.persistenceSync.flushPending(e),await this.persistence.delete(e),await this.clearSessionStores(e),this.hookRegistry.emit(`session.deleted`,{sessionId:e,metadata:{reason:`removed`}}),this.logger.info({sessionId:e},`Session removed`),!0}async clearSessionStores(e){let t=async(t,n)=>{if(n)try{await n.clear(e)}catch(n){this.logger.warn({sessionId:e,err:n instanceof Error?n.message:String(n)},`Failed to clear ${t} on session removal`)}};await t(`trace store`,this.traceStore),await t(`checkpoint store`,this.checkpointStore)}async ensureEntriesHydrated(e,t,n){if(!ue(t))return t;if(!de(this.persistence))throw Error(`${n}: entries contain stripped compaction replacements but persistence lacks hydration capability (RFC-160 D4); refusing to fork stripped state`);return this.persistence.hydrateReplacements(e,t)}async forkSession(e,t){let n=this.sessions.get(e),r=this.configs.get(e);if(!n||!r)return;let i=n.session;if(!(i instanceof C))return;let a=t??E.uuid();this.prepareCapacity(a);let o=i.toSnapshot(),s=Pt(a,e,await this.ensureEntriesHydrated(e,o.entries,`forkSession`),o.metadata,o.leafId,this.clock),c={model:n.model,modelResolution:r.modelResolution,agentName:n.agentName===`agent`?void 0:n.agentName,systemPrompt:n.systemPrompt,systemTail:n.systemTail,tools:n.tools,thinkingLevel:n.thinkingLevel,maxToolTurns:n.maxToolTurns,maxToolTurnExtensions:n.maxToolTurnExtensions,promptOutputTokenBudget:n.promptOutputTokenBudget,promptWallClockBudgetMs:n.promptWallClockBudgetMs,todoContinuation:r.todoContinuation,promptRefresh:n.promptRefresh,workspaceDir:n.workspaceDir,workspaceId:n.workspaceId,depth:r.depth,transient:r.transient,interactive:r.interactive,retryAccelerate:r.retryAccelerate,streamRetry:r.streamRetry,networkDisconnectRetry:r.networkDisconnectRetry,lifecycleAsyncTimeoutMs:r.lifecycleAsyncTimeoutMs,permissionAlwaysAllow:r.permissionAlwaysAllow,availableModels:r.availableModels},l=await this.adoptForkedSession(s,c);return this.logger.info({sessionId:a,sourceId:e},`Session forked`),l}save(e){return this.persistenceSync.save(e)}saveAll(){return this.persistenceSync.saveAll()}inspectSessionWriteLease(e){return this.inspectSessionWriteLeaseFn?.(e)??{locked:!1}}forceReleaseSessionWriteLease(e){this.forceReleaseSessionWriteLeaseFn?.(e)}restore(e){return this.persistenceSync.restore(e)}consumeCrashGap(e){return this.persistenceSync.consumeCrashGap(e)}restoreAll(){return this.persistenceSync.restoreAll()}collectIdle(){let e=(this.clock??T).now(),t=[];for(let[n,r]of this.sessions)if(!(r.isBusy||r.isPaused)&&e-this.residencySince(n,r)>this.idleTimeoutMs){let e=r.session,i=!1;if(this.autoPersist&&e instanceof C){let t=e.toSnapshot();t.entries.length>0&&(i=!0,this.persistenceSync.saveSnapshot(n,t,()=>{this.persistenceSync.forgetEvictedSession(n)}).catch(e=>{this.logger.warn({sessionId:n,err:e instanceof Error?e.message:String(e)},`Session snapshot flush on idle eviction failed`)}))}r.dispose(),this.sessions.delete(n),this.configs.delete(n),this.residencyClock.delete(n),i||this.persistenceSync.forgetSession(n),this.activeSessionId===n&&(this.activeSessionId=void 0),this.hookRegistry.emit(`session.deleted`,{sessionId:n,metadata:{reason:`idle`}}),t.push(n)}return t}entryCount(e){let t=e.session;return t instanceof C?t.entries().length:t.messages().length}evictLeastRecent(e){let t=Array.from(this.sessions.entries()).filter(([t,n])=>t!==e&&t!==this.activeSessionId&&!n.isBusy&&!n.isPaused&&!(this.configs.get(t)?.transient??!1)).filter(([,e])=>this.autoPersist||this.entryCount(e)===0).sort(([e,t],[n,r])=>this.residencySince(e,t)-this.residencySince(n,r));for(let[e,n]of t){if(this.sessions.size<this.maxSessions)break;let t=n.session,r=!1;if(this.autoPersist&&t instanceof C){let n=t.toSnapshot();n.entries.length>0&&(r=!0,this.persistenceSync.saveSnapshot(e,n,()=>{this.persistenceSync.forgetEvictedSession(e)}).catch(t=>{this.logger.warn({sessionId:e,err:t instanceof Error?t.message:String(t)},`Session snapshot flush on eviction failed`)}))}n.dispose(),this.sessions.delete(e),this.configs.delete(e),this.residencyClock.delete(e),r||this.persistenceSync.forgetSession(e),this.hookRegistry.emit(`session.deleted`,{sessionId:e,metadata:{reason:`evicted`}}),this.logger.info({sessionId:e},`Session evicted (LRU)`)}}prepareCapacity(e){if(!this.sessions.has(e)&&(this.sessions.size+1>this.threshold&&this.collectIdle(),this.sessions.size>=this.maxSessions&&this.evictLeastRecent(e),this.sessions.size>=this.maxSessions))throw Error(`Max sessions (${this.maxSessions}) reached.`)}canAccommodate(e){return this.sessions.has(e)?!0:(this.sessions.size+1>this.threshold&&this.collectIdle(),this.sessions.size>=this.maxSessions&&this.evictLeastRecent(e),this.sessions.size<this.maxSessions)}dispose(){for(let e of this.sessions.values())e.dispose();this.sessions.clear(),this.configs.clear(),this.residencyClock.clear(),this.activeSessionId=void 0}};function dn(e){let{sessionDir:t}=e;if(!t)throw Error(`sessionDir is required for DiskSessionPool`);return new H(e,new ie({baseDir:t}),!0)}function fn(e){let{sessionUrl:t}=e;if(!t)throw Error(`sessionUrl is required for RemoteSessionPool`);return new H(e,new oe({baseUrl:t,fetch:e.fetch,getAuth:e.getAuth,timeoutMs:e.timeoutMs??3e4,userId:e.userId,wsKey:e.wsKey}),!0)}function pn(e){return new H(e,new ae)}function mn(e,t,n=!0){return new H(e,t,n)}function hn(e,t){let n=new Xe;return n.register(Ze(e)),t&&n.register(Qe(e,t)),n}function gn(e={}){let t=e.logger??d(`otto-runtime`,{level:`info`,destination:`stdout`}),n=e.providerRegistry??r(),i=e.hookRegistry??a({preset:`default`});e.hookRegistry||s(i);let o=e.storage??{kind:`in-memory`},c=e.traceStore===void 0,l=e.checkpointStore===void 0,{traceStore:u,checkpointStore:f}=Ke(o.kind===`disk`?{sessionDir:o.sessionDir}:o.kind===`remote`?{remoteLog:{baseUrl:o.sessionUrl,getAuth:o.getAuth,fetch:o.fetch,timeoutMs:o.timeoutMs}}:{},{traceStore:e.traceStore,checkpointStore:e.checkpointStore}),p=hn(e.workspaceDir??process.cwd(),e.memory),m=(()=>{if(o.kind===`custom`&&(o.panelStatePersistence||o.pasteStatePersistence))return new V(o.panelStatePersistence??x(),o.pasteStatePersistence??S());let e=o.kind===`disk`?`${o.sessionDir}/panel-state`:o.kind===`custom`&&o.panelStateDir?o.panelStateDir:void 0;if(e!==void 0)return new V(new g({baseDir:e}),new _({baseDir:`${e}/paste`}))})(),h={hookRegistry:i,providerRegistry:n,logger:t,memory:e.memory,traceStore:u,checkpointStore:f,clock:e.clock,maxSessions:e.maxSessions,idleTimeoutMs:e.idleTimeoutMs,devtools:e.devtools,configProvider:e.configProvider,panelStateStore:m,residencyGovernor:e.residencyGovernor,getResidencyConfig:e.getResidencyConfig},v=o.kind===`disk`?dn({...h,sessionDir:o.sessionDir}):o.kind===`remote`?fn({...h,sessionUrl:o.sessionUrl,fetch:o.fetch,getAuth:o.getAuth,timeoutMs:o.timeoutMs,userId:o.userId,wsKey:o.wsKey}):o.kind===`custom`?mn({...h,listColdSessionsOverride:o.listColdSessionsOverride,isSessionWriteLocked:o.isSessionWriteLocked,inspectSessionWriteLease:o.inspectSessionWriteLease,forceReleaseSessionWriteLease:o.forceReleaseSessionWriteLease},o.persistence,o.autoPersist??!0):pn(h);return{createSession:(e,t)=>v.createSession(e,t),sessions:v,hookRegistry:i,stream:v.stream,contextSources:p,traceStore:u,checkpointStore:f,clock:e.clock,dispose:async()=>{v.dispose(),c&&await u.close?.(),l&&await f.close?.(),o.kind===`custom`&&await o.onDispose?.()}}}function _n(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0&&r<=100?r:t}function U(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0?r:t}var vn=class{warnThresholdPct;hardThresholdPct;sampleIntervalMs;warningIntervalMs;criticalIntervalMs;warnCooldownMs;onWarning;onCritical;logger;now;postRestartGraceMs;ticker=null;lastLevel=`healthy`;lastWarningFiredAt;graceStartedAt;onCriticalDuringGrace;onLevelChange;onSample;disposed=!1;criticalTimeoutMs;onCriticalTimeout;criticalEnteredAt;criticalTimeoutFired=!1;constructor(e={}){this.warnThresholdPct=e.warnThresholdPct??_n(`OTTO_MEMORY_WARN_PCT`,70),this.hardThresholdPct=e.hardThresholdPct??_n(`OTTO_MEMORY_HARD_PCT`,85),this.sampleIntervalMs=e.sampleIntervalMs??U(`OTTO_MEMORY_SAMPLE_INTERVAL_MS`,3e4),this.warningIntervalMs=e.warningIntervalMs??U(`OTTO_MEMORY_WARNING_INTERVAL_MS`,1e4),this.criticalIntervalMs=e.criticalIntervalMs??U(`OTTO_MEMORY_CRITICAL_INTERVAL_MS`,5e3),this.warnCooldownMs=e.warnCooldownMs??3e5,this.postRestartGraceMs=e.postRestartGraceMs??6e5,this.criticalTimeoutMs=e.criticalTimeoutMs??U(`OTTO_MEMORY_CRITICAL_TIMEOUT_MS`,9e5),this.onWarning=e.onWarning,this.onCritical=e.onCritical,this.onCriticalDuringGrace=e.onCriticalDuringGrace,this.onLevelChange=e.onLevelChange,this.onSample=e.onSample,this.onCriticalTimeout=e.onCriticalTimeout,this.logger=e.logger,this.now=e.now??(()=>Date.now())}get currentLevel(){return this.lastLevel}setCallbacks(e){`onWarning`in e&&(this.onWarning=e.onWarning),`onCritical`in e&&(this.onCritical=e.onCritical),`onCriticalDuringGrace`in e&&(this.onCriticalDuringGrace=e.onCriticalDuringGrace),`onLevelChange`in e&&(this.onLevelChange=e.onLevelChange),`onSample`in e&&(this.onSample=e.onSample),`onCriticalTimeout`in e&&(this.onCriticalTimeout=e.onCriticalTimeout)}markRestarted(){this.graceStartedAt=this.now()}updateThresholds(e){e.warnThresholdPct!=null&&process.env.OTTO_MEMORY_WARN_PCT===void 0&&(this.warnThresholdPct=e.warnThresholdPct),e.hardThresholdPct!=null&&process.env.OTTO_MEMORY_HARD_PCT===void 0&&(this.hardThresholdPct=e.hardThresholdPct)}get inPostRestartGrace(){return this.graceStartedAt===void 0?!1:this.now()-this.graceStartedAt<this.postRestartGraceMs}sample(){let{heapUsed:e,rss:t,external:n}=process.memoryUsage(),{heap_size_limit:r}=ze(),i=r>0?e/r*100:0;return{level:this.grade(i),heapUsed:e,heapSizeLimit:r,usedPct:i,rss:t,external:n,ts:this.now()}}grade(e){return e>=this.hardThresholdPct?`critical`:e>=this.warnThresholdPct?`warning`:`healthy`}start(){this.ticker||(this.ticker=setTimeout(()=>this.tick(),this.sampleIntervalMs),this.ticker.unref?.())}tick(){let e=this.sample();if(this.disposed)return;if(this.onSample?.(e),e.level!==this.lastLevel){if(this.logger?.info({from:this.lastLevel,to:e.level,usedPct:e.usedPct.toFixed(1),heapUsed:e.heapUsed,heapSizeLimit:e.heapSizeLimit},`[memory-governor] pressure level changed`),this.onLevelChange?.(e.level),e.level===`warning`){let e=this.now();this.lastWarningFiredAt!==void 0&&e-this.lastWarningFiredAt<this.warnCooldownMs?this.logger?.info({cooldownRemainingMs:this.warnCooldownMs-(e-this.lastWarningFiredAt)},`[memory-governor] onWarning skipped (within cooldown)`):(this.lastWarningFiredAt=e,this.onWarning?.())}e.level===`critical`&&(this.inPostRestartGrace?this.onCriticalDuringGrace?.(e):this.onCritical?.(e))}if(e.level===`critical`?this.criticalEnteredAt===void 0?(this.criticalEnteredAt=this.now(),this.criticalTimeoutFired=!1):!this.criticalTimeoutFired&&this.now()-this.criticalEnteredAt>=this.criticalTimeoutMs&&(this.criticalTimeoutFired=!0,this.onCriticalTimeout?.(e)):(this.criticalEnteredAt=void 0,this.criticalTimeoutFired=!1),this.lastLevel=e.level,this.disposed)return;let t=this.lastLevel===`critical`?this.criticalIntervalMs:this.lastLevel===`warning`?this.warningIntervalMs:this.sampleIntervalMs;this.ticker=setTimeout(()=>this.tick(),t),this.ticker.unref?.()}dispose(){this.disposed=!0,this.ticker&&=(clearTimeout(this.ticker),null)}};function W(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0?r:t}var yn=class{sampleIntervalMs;maxProcesses;maxTotalRssMb;listProcesses;logger;now;onSample;onBudgetExceeded;ticker=null;disposed=!1;budgetExceededNotified=!1;constructor(e={}){this.sampleIntervalMs=e.sampleIntervalMs??W(`OTTO_FLEET_SAMPLE_INTERVAL_MS`,6e5),this.maxProcesses=e.maxProcesses??W(`OTTO_FLEET_MAX_PROCESSES`,8),this.maxTotalRssMb=e.maxTotalRssMb??W(`OTTO_FLEET_MAX_TOTAL_RSS_MB`,8192),this.listProcesses=e.listProcesses??me,this.onSample=e.onSample,this.onBudgetExceeded=e.onBudgetExceeded,this.logger=e.logger,this.now=e.now??(()=>Date.now())}setCallbacks(e){`onSample`in e&&(this.onSample=e.onSample),`onBudgetExceeded`in e&&(this.onBudgetExceeded=e.onBudgetExceeded)}sample(){let e;try{e=this.listProcesses()}catch(e){this.logger?.warn({err:e instanceof Error?e.message:String(e)},`[fleet-monitor] process enumeration failed (skipping sample)`);return}if(e.length===0)return;let t=0,n=0,r=0;for(let i of e)t+=i.rssKb,i.ppid===1&&i.tty===`??`&&n++,i.generation!==void 0&&i.generation>r&&(r=i.generation);return{processCount:e.length,totalRssMb:Math.round(t/1024),suspectedOrphanCount:n,maxGeneration:r,ts:this.now()}}tick(){if(this.disposed)return;let e=this.sample();if(e){this.onSample?.(e);let t=e.processCount>this.maxProcesses,n=e.totalRssMb>this.maxTotalRssMb;if(t||n){if(!this.budgetExceededNotified){this.budgetExceededNotified=!0;let n=t?`process-count`:`total-rss`;this.logger?.warn({processCount:e.processCount,totalRssMb:e.totalRssMb,maxProcesses:this.maxProcesses,maxTotalRssMb:this.maxTotalRssMb},`[fleet-monitor] fleet budget exceeded`),this.onBudgetExceeded?.(e,n)}}else this.budgetExceededNotified=!1}this.disposed||(this.ticker=setTimeout(()=>this.tick(),this.sampleIntervalMs),this.ticker.unref?.())}start(){this.ticker||this.disposed||(this.ticker=setTimeout(()=>this.tick(),this.sampleIntervalMs),this.ticker.unref?.())}dispose(){this.disposed=!0,this.ticker&&=(clearTimeout(this.ticker),null)}};const G=e=>{try{return process.kill(e,0),!0}catch{return!1}},K=(e,t)=>{try{process.kill(-e,t)}catch{try{process.kill(e,t)}catch{}}},q=e=>{try{Ve(`taskkill`,[`/F`,`/T`,`/PID`,`${e}`],{stdio:`ignore`,timeout:5e3})}catch{}};var bn=class{entries=new Map;maxProcesses;graceMs;clock;spawnListeners=new Set;exitListeners=new Set;constructor(e={}){this.maxProcesses=e.maxProcesses??64,this.graceMs=e.graceMs??2e3,this.clock=e.clock??(()=>Date.now())}onSpawn(e){return this.spawnListeners.add(e),()=>this.spawnListeners.delete(e)}onExit(e){return this.exitListeners.add(e),()=>this.exitListeners.delete(e)}notify(e,t){for(let n of[...e])try{n(t)}catch{}}register(e){if(this.entries.size>=this.maxProcesses&&this.evictLeastRecent(),this.entries.size>=this.maxProcesses)throw Error(`Background process limit (${this.maxProcesses}) reached; stop one with kill_shell first.`);let t=e.child.pid;if(t===void 0)throw Error(`Cannot register a child process without a pid`);let n=e.now??this.clock(),r={id:e.id,sessionId:e.sessionId,owner:e.owner,pid:t,pgid:t,command:e.command,cwd:e.cwd,port:e.port,url:e.url,logPath:e.logPath,startedAt:n,lastUsed:n,status:`running`,keepAlive:e.keepAlive},i={info:r,child:e.child};return this.entries.set(e.id,i),e.child.once(`exit`,e=>{r.status===`running`?(r.status=`exited`,r.exitCode=e??void 0):r.status===`killing`&&(r.status=`killed`),i.silenced||this.notify(this.exitListeners,r)}),this.notify(this.spawnListeners,r),r}get(e){return this.entries.get(e)?.info}getForSession(e,t){let n=this.entries.get(t);return n&&n.info.sessionId===e?n.info:void 0}list(){return[...this.entries.values()].map(e=>e.info)}listForSession(e){return this.list().filter(t=>t.sessionId===e)}touch(e){let t=this.entries.get(e);t&&(t.info.lastUsed=this.clock())}updateDetectedService(e,t){let n=this.entries.get(e);n&&(n.info.detectedService?.url&&!t.url||(n.info.detectedService=t))}remove(e){let t=this.entries.get(e);t&&(t.silenced=!0,this.entries.delete(e))}size(){return this.entries.size}async kill(e){let t=this.entries.get(e);t&&await this.killEntry(t)}async killAll(){await Promise.all([...this.entries.values()].map(e=>this.killEntry(e)))}async killAllForOwner(e){await Promise.all([...this.entries.values()].filter(t=>t.info.owner===e).map(e=>this.killEntry(e)))}async killAllForSession(e){await Promise.all([...this.entries.values()].filter(t=>t.info.sessionId===e).map(e=>this.killEntry(e)))}killAllSync(){for(let e of this.entries.values())this.killEntrySync(e)}killEntrySync(e){let{info:t}=e;t.status===`exited`||t.status===`killed`||(process.platform===`win32`?q(t.pid):K(t.pgid,`SIGKILL`),t.status=`killed`)}evictLeastRecent(){let e;for(let t of this.entries.values()){if(t.info.status===`exited`||t.info.status===`killed`){e=t;break}t.info.keepAlive||(!e||t.info.lastUsed<e.info.lastUsed)&&(e=t)}e&&(e.silenced=!0,this.killEntrySync(e),this.entries.delete(e.info.id))}async killEntry(e){let{info:t}=e;if(t.status===`running`){if(t.status=`killing`,process.platform===`win32`){q(t.pid),t.status=`killed`;return}K(t.pgid,`SIGTERM`),await this.waitForExit(e,this.graceMs)||K(t.pgid,`SIGKILL`),t.status=`killed`}}waitForExit(e,t){return new Promise(n=>{let r=!1,i,a=t=>{r||(r=!0,clearTimeout(i),e.child.removeListener(`exit`,o),n(t))},o=()=>a(!0);if(e.child.once(`exit`,o),!G(e.info.pid)){a(!0);return}i=setTimeout(()=>a(!1),t)})}};const xn=new bn;let Sn=!1;function Cn(e=xn){Sn||(Sn=!0,process.on(`exit`,()=>{e.killAllSync()}))}let wn=0;var Tn=class extends He{id;child;config;status=`starting`;_clock;_pid;_pgid;_exitResult=null;_exitResolve=null;_stdoutBuf=``;_stderrBuf=``;lastUsed;constructor(e,t,n){if(super(),this._clock=n,this.id=`proc_${++wn}_${this._clock()}`,this.child=e,this.config=t,this._pid=e.pid,this._pgid=e.pid,this.lastUsed=this._clock(),this.child.on(`spawn`,()=>{this._pid=this.child.pid,this._pgid=this.child.pid,this.status===`starting`&&(this.status=`running`)}),this.child.on(`error`,e=>{this.lastUsed=this._clock(),(this.status===`starting`||this.status===`running`)&&(this.status=`errored`),this.emit(`error`,e)}),this.child.on(`exit`,(e,t)=>{this.lastUsed=this._clock();let n={code:e,signal:t,timedOut:!1};this._exitResult=n,this.status===`running`?this.status=`exited`:this.status===`killing`&&(this.status=`killed`),this.emit(`exit`,n),this._exitResolve&&=(this._exitResolve(n),null)}),this.child.stdout&&this.child.stdout.on(`data`,e=>{this.lastUsed=this._clock();let t=e.toString(`utf-8`);for(this._stdoutBuf+=t;;){let e=this._stdoutBuf.indexOf(`
14
+ `);if(e===-1)break;let t=this._stdoutBuf.slice(0,e).replace(/\r$/,``);this._stdoutBuf=this._stdoutBuf.slice(e+1),this.emit(`stdoutLine`,t)}}),this.child.stderr&&this.child.stderr.on(`data`,e=>{this.lastUsed=this._clock();let t=e.toString(`utf-8`);for(this._stderrBuf+=t;;){let e=this._stderrBuf.indexOf(`
15
+ `);if(e===-1)break;let t=this._stderrBuf.slice(0,e).replace(/\r$/,``);this._stderrBuf=this._stderrBuf.slice(e+1),this.emit(`stderrLine`,t)}}),t.signal){let e=()=>{this.kill({reason:`aborted`})};t.signal.aborted?e():t.signal.addEventListener(`abort`,e,{once:!0})}}get pid(){return this._pid}get pgid(){return this._pgid}get stdin(){return this.child.stdin&&!this.child.stdin.destroyed?this.child.stdin:null}get stdout(){return this.child.stdout&&!this.child.stdout.destroyed?this.child.stdout:null}get stderr(){return this.child.stderr&&!this.child.stderr.destroyed?this.child.stderr:null}onStdoutLine(e){return this.on(`stdoutLine`,e),()=>this.off(`stdoutLine`,e)}onStderrLine(e){return this.on(`stderrLine`,e),()=>this.off(`stderrLine`,e)}onExit(e){return this.on(`exit`,e),()=>this.off(`exit`,e)}onError(e){return this.on(`error`,e),()=>this.off(`error`,e)}async kill(e){if(this.status===`killed`||this.status===`exited`)return;this.status=`killing`,this.lastUsed=this._clock();let t=e?.graceMs??this.config.killGraceMs??2e3,n=this._pid,r=this._pgid;if(!n||!G(n)){this.status=`killed`;return}if(process.platform===`win32`){q(n),this.status=`killed`;return}K(r??n,`SIGTERM`),await new Promise(e=>{let r=!1,i=t=>{r||(r=!0,clearTimeout(o),e(t))},a=()=>i(!0);if(this.child.once(`exit`,a),!G(n)){i(!0);return}let o=setTimeout(()=>{this.child.removeListener(`exit`,a),i(!1)},t)})||K(r??n,`SIGKILL`),this.status=`killed`}async waitForExit(e=3e4){return this._exitResult?this._exitResult:new Promise(t=>{if(this._exitResult){t(this._exitResult);return}let n=!1,r=e=>{n||(n=!0,clearTimeout(a),this.off(`exit`,i),t(e))},i=e=>r(e);this.on(`exit`,i);let a=setTimeout(()=>{r({code:null,signal:null,timedOut:!0})},e)})}},En=class{_entries=new Map;_maxProcesses;killGraceMs;killTimeoutMs;_clock;_spawnListeners=new Set;_exitListeners=new Set;constructor(e={}){this._maxProcesses=e.maxProcesses??128,this.killGraceMs=e.killGraceMs??2e3,this.killTimeoutMs=e.killTimeoutMs??3e4,this._clock=e.clock??(()=>Date.now())}onSpawn(e){return this._spawnListeners.add(e),()=>this._spawnListeners.delete(e)}onExit(e){return this._exitListeners.add(e),()=>this._exitListeners.delete(e)}onAllExited(e){let t=()=>{this._entries.size===0&&e()},n=()=>t();return this._exitListeners.add(n),t(),()=>this._exitListeners.delete(n)}spawn(e){if(this._entries.size>=this._maxProcesses&&this._evictLeastRecent(),this._entries.size>=this._maxProcesses)throw Error(`Process limit (${this._maxProcesses}) reached. Stop unused processes first.`);let t={...e.options??{},stdio:e.options?.stdio??[`pipe`,`pipe`,`pipe`],cwd:e.cwd??e.options?.cwd,env:u(e.env??e.options?.env),...e.keepAlive===!0?{}:{detached:!0}},n=Be(e.command,e.args??[],t),r=new Tn(n,e,this._clock);this._entries.set(r.id,{proc:r,child:n}),r.onExit(()=>{if(!this._entries.get(r.id))return;let t=e.lifecycle??`evictable`;e.keepAlive!==!0&&t!==`pinned`&&this._entries.delete(r.id);for(let e of[...this._exitListeners])try{e(r)}catch{}});for(let e of[...this._spawnListeners])try{e(r)}catch{}return r}get(e){return this._entries.get(e)?.proc}list(e){let t=[...this._entries.values()];return e?.owner&&(t=t.filter(t=>t.proc.config.owner.type===e.owner.type&&t.proc.config.owner.id===e.owner.id)),e?.sessionId&&(t=t.filter(t=>t.proc.config.sessionId===e.sessionId)),e?.category&&(t=t.filter(t=>t.proc.config.category===e.category)),t.map(e=>e.proc)}listForSession(e){return this.list({sessionId:e})}listForOwner(e){return this.list({owner:e})}touch(e){let t=this._entries.get(e);t&&(t.proc.lastUsed=this._clock())}remove(e){this._entries.delete(e)}size(){return this._entries.size}async killAll(e,t){let n=this.list(e).filter(e=>!e.config.keepAlive);await Promise.all(n.map(e=>e.kill(t)))}killAllSync(){let e=process.platform===`win32`,t=[];for(let[n,r]of this._entries){let i=r.proc;if(i.config.keepAlive||i.status!==`running`&&i.status!==`starting`)continue;let a=i.pid;a&&(e?t.push(a):K(i.pgid??a,`SIGKILL`),this._entries.delete(n))}if(e&&t.length>0)try{Ve(`taskkill`,[`/F`,`/T`,...t.map(String).flatMap(e=>[`/PID`,e])],{stdio:`ignore`,timeout:5e3})}catch{}}async killAllForOwner(e,t){return this.killAll({owner:{type:e,id:t}})}async killAllForSession(e){return this.killAll({sessionId:e})}registerChild(e,t){if(this._entries.size>=this._maxProcesses&&this._evictLeastRecent(),this._entries.size>=this._maxProcesses)throw Error(`Process limit (${this._maxProcesses}) reached. Stop unused processes first.`);let n=new Tn(t,e,this._clock);this._entries.set(n.id,{proc:n,child:t}),n.onExit(()=>{if(!this._entries.get(n.id))return;let t=e.lifecycle??`evictable`;e.keepAlive!==!0&&t!==`pinned`&&this._entries.delete(n.id);for(let e of[...this._exitListeners])try{e(n)}catch{}});for(let e of[...this._spawnListeners])try{e(n)}catch{}return n}_evictLeastRecent(){let e;for(let t of this._entries.values()){let n=t.proc.config,r=n.lifecycle??`evictable`;if(t.proc.status===`exited`||t.proc.status===`killed`||t.proc.status===`errored`){e=t;break}n.keepAlive||r!==`pinned`&&(!e||t.proc.lastUsed<e.proc.lastUsed)&&(e=t)}if(!e)return;let t=e.proc.pid;t&&G(t)&&(process.platform===`win32`?q(t):K(e.proc.pgid??t,`SIGKILL`)),this._entries.delete(e.proc.id)}};const Dn=new En;let On=!1;function kn(e=Dn){On||(On=!0,process.on(`exit`,()=>{e.killAllSync()}))}function J(e,t){return k(`git`,[`-C`,e,...t],{encoding:`utf-8`,stdio:[`ignore`,`pipe`,`pipe`]}).trimEnd()}function An(e,t){let n=J(e,[`rev-parse`,`HEAD`]),r=`otto/job-${t}`,i=p(Ue(p(Ge(),`otto-wt-`)),`job-${t}`);return J(e,[`worktree`,`add`,`-b`,r,i,n]),{path:i,branch:r,base:n,repoRoot:e}}function jn(e){return J(e.path,[`add`,`-A`]),k(`git`,[`-C`,e.path,`diff`,`--cached`,`--binary`],{encoding:`utf-8`,maxBuffer:256*1024*1024})}function Y(e){return[...new Set(e.split(`
16
+ `).map(e=>/(?:patch failed: |error: )([^\s:]+?)(?::| ?:?\s*(?:patch does not apply|does not exist))/.exec(e)?.[1]).filter(e=>!!e&&e!==`error`))]}function Mn(e,t){try{return J(e,[`rev-parse`,`HEAD`])!==t}catch{return!1}}function Nn(e,t){if(!t.trim())return{applied:!0,conflictPaths:[]};try{k(`git`,[`-C`,e,`apply`,`--check`,`--whitespace=nowarn`],{input:t,stdio:[`pipe`,`pipe`,`pipe`]})}catch(e){return{applied:!1,conflictPaths:Y(String(e.stderr??``))}}try{return k(`git`,[`-C`,e,`apply`,`--whitespace=nowarn`],{input:t,stdio:[`pipe`,`pipe`,`pipe`]}),{applied:!0,conflictPaths:[]}}catch(e){return{applied:!1,conflictPaths:Y(String(e.stderr??``))}}}function Pn(e,t){if(!t.trim())return{applied:!0,conflictPaths:[]};try{k(`git`,[`-C`,e,`apply`,`--reverse`,`--check`,`--whitespace=nowarn`],{input:t,stdio:[`pipe`,`pipe`,`pipe`]})}catch(e){return{applied:!1,conflictPaths:Y(String(e.stderr??``))}}try{return k(`git`,[`-C`,e,`apply`,`--reverse`,`--whitespace=nowarn`],{input:t,stdio:[`pipe`,`pipe`,`pipe`]}),{applied:!0,conflictPaths:[]}}catch(e){return{applied:!1,conflictPaths:Y(String(e.stderr??``))}}}function X(e,t){try{J(e.repoRoot,[`worktree`,`remove`,`--force`,e.path])}catch(e){t?.(`worktree remove`,e)}try{J(e.repoRoot,[`branch`,`-D`,e.branch])}catch(e){t?.(`branch delete`,e)}try{J(e.repoRoot,[`worktree`,`prune`])}catch(e){t?.(`worktree prune`,e)}}function Fn(e,t){let n=new Set(t),r=[],i;try{i=p(We(Ge()),`otto-wt-`)}catch{return r}let a;try{a=J(e,[`worktree`,`list`,`--porcelain`])}catch{return r}let o=a.split(`
17
17
 
18
18
  `);for(let t of o){let a=t.split(`
19
- `),o=``,s=``;for(let e of a)e.startsWith(`worktree `)?o=e.slice(9):e.startsWith(`branch `)&&(s=e.slice(7));if(!o||!s)continue;let c=/^refs\/heads\/otto\/job-(.+)$/.exec(s);if(!c)continue;let l=c[1],u;try{u=Ve(o)}catch{continue}if(u.startsWith(i)&&!n.has(l)){try{J(e,[`worktree`,`remove`,`--force`,o])}catch{}try{J(e,[`branch`,`-D`,s.slice(11)])}catch{}r.push(o)}}try{J(e,[`worktree`,`prune`])}catch{}return r}const Dn=[/(^|\/)governance\/forbidden-zone\./,/(^|\/)packages\/setting\//,/(^|\/)permission/i,/(^|\/)sandbox/i,/(^|\/)git-worktree\./,/(^|\/)agent-job-service\./,/(^|\/)mcp-controller\./,/(^|\/)packages\/mcp\/src\/oauth\//,/(allowlist|allow-list|egress|networkpolicy)/i];function On(e){if(e.length<2||!e.startsWith(`"`)||!e.endsWith(`"`))return e;let t=e.slice(1,-1),n=[];for(let e=0;e<t.length;e++){if(t[e]!==`\\`){n.push(t.charCodeAt(e));continue}let r=t[e+1];r&&r>=`0`&&r<=`7`?(n.push(parseInt(t.slice(e+1,e+4),8)),e+=3):(n.push({t:9,n:10,r:13,'"':34,"\\":92}[r]??(r?r.charCodeAt(0):92)),e+=1)}return Buffer.from(n).toString(`utf-8`)}function kn(e){let t=On(e.trim());return t===`/dev/null`?null:t.replace(/^[ab]\//,``)}function An(e){let t=/^("(?:[^"\\]|\\.)*") ("(?:[^"\\]|\\.)*")$/.exec(e);if(t)return[t[1],t[2]];let n=/^(a\/.+?) (b\/.+)$/.exec(e);return n?[n[1],n[2]]:[]}function Z(e){let t=new Set;for(let n of e.split(`
20
- `)){if(n.startsWith(`diff --git `)){for(let e of An(n.slice(11))){let n=kn(e);n&&t.add(n)}continue}if(/^\+\+\+ "?[ab]\//.test(n)||/^--- "?[ab]\//.test(n)){let e=kn(n.slice(4));e&&t.add(e)}}return[...t]}function jn(e){return e.trim()?Z(e).filter(e=>Dn.some(t=>t.test(e))):[]}const Mn=[/(^|\/)\.otto\/(agents|skills|teams)\//i,/(^|\/)\.otto\/[^/]*config/i,/(^|\/)otto\.config\./i];function Nn(e){return e.trim()?Z(e).filter(e=>Mn.some(t=>t.test(e))):[]}const Pn=200;function Fn(e,t){let{forbiddenZone:n,capabilityTouched:r,diffStat:i,conflict:a,origin:o}=e,s=t.maxAutoApplyLines??200,c=i.added+i.removed;if(o!==`user`&&n.length>0)return{action:`forbid`,reasons:[`触及治理禁区(高危自我修改):${n.join(`, `)}`]};if(o===`plugin`){let e=[`插件发起的作业需人手 apply(RFC-287 R2)`];return r.length&&e.push(`触及能力面:${r.join(`, `)}`),a&&e.push(`存在冲突`),c>s&&e.push(`改动较大(${c} 行 > ${s})`),{action:`gate`,reasons:e}}if(o===`user`){let e=[];return n.length&&e.push(`触及治理禁区:${n.join(`, `)}`),r.length&&e.push(`触及能力面:${r.join(`, `)}`),a&&e.push(`存在冲突,无法干净落地`),{action:`advise`,recommend:e.length?`review`:`apply`,reasons:e}}if(t.level<=1){let e=[];return r.length&&e.push(`触及能力面:${r.join(`, `)}`),a&&e.push(`存在冲突`),c>s&&e.push(`改动较大(${c} 行 > ${s})`),t.level===0?{action:`gate`,reasons:[`autonomy L0:需人手 apply`,...e]}:{action:`advise`,recommend:e.length?`review`:`apply`,reasons:e}}let l=[];return a&&l.push(`apply 有冲突`),c>s&&l.push(`改动超规模(${c} 行 > ${s})`),r.length&&t.level<3&&l.push(`触及能力面(需 L3+):${r.join(`, `)}`),l.length?{action:`gate`,reasons:l}:{action:`auto`}}const Q=new Set([`applied`,`failed`,`canceled`]);var In=class{entries=new Map;maxJobs;clock;onWorktreeCleanupError;spawnListeners=new Set;updateListeners=new Set;exitListeners=new Set;removeListeners=new Set;retained=new Set;constructor(e={}){this.maxJobs=e.maxJobs??16,this.clock=e.clock??(()=>Date.now()),this.onWorktreeCleanupError=e.onWorktreeCleanupError}setWorktreeCleanupErrorHandler(e){this.onWorktreeCleanupError=e}onSpawn(e){return this.spawnListeners.add(e),()=>this.spawnListeners.delete(e)}onUpdate(e){return this.updateListeners.add(e),()=>this.updateListeners.delete(e)}onExit(e){return this.exitListeners.add(e),()=>this.exitListeners.delete(e)}onRemove(e){return this.removeListeners.add(e),()=>this.removeListeners.delete(e)}retain(e,t){t?this.retained.add(e):this.retained.delete(e)}notify(e,t){for(let n of[...e])try{n(t)}catch{}}register(e){if(this.entries.size>=this.maxJobs&&this.evictTerminal(),this.entries.size>=this.maxJobs)throw Error(`Agent job limit (${this.maxJobs}) reached; cancel one with stop first.`);let t=e.now??this.clock(),n={id:e.id,sessionId:e.sessionId,type:`agent-session`,title:e.title,origin:e.origin??`user`,status:`running`,worktree:e.worktree,outputPath:e.outputPath,startedAt:t};return this.entries.set(e.id,{info:n,abort:e.abort}),this.notify(this.spawnListeners,n),n}get(e){return this.entries.get(e)?.info}getForSession(e,t){let n=this.entries.get(t);return n&&n.info.sessionId===e?n.info:void 0}list(){return[...this.entries.values()].map(e=>e.info)}listForSession(e){return this.list().filter(t=>t.sessionId===e)}size(){return this.entries.size}update(e,t){let n=this.entries.get(e);n&&(Q.has(n.info.status)||(Object.assign(n.info,t),this.notify(this.updateListeners,n.info),Q.has(n.info.status)&&(n.info.status!==`canceled`&&X(n.info.worktree,(t,n)=>this.onWorktreeCleanupError?.(e,t,n)),this.notify(this.exitListeners,n.info))))}cancel(e){let t=this.entries.get(e);if(!(!t||Q.has(t.info.status))){try{t.abort()}catch{}X(t.info.worktree,(t,n)=>this.onWorktreeCleanupError?.(e,t,n)),this.update(e,{status:`canceled`})}}remove(e){let t=this.entries.get(e);t&&X(t.info.worktree,(t,n)=>this.onWorktreeCleanupError?.(e,t,n)),this.retained.delete(e),this.entries.delete(e),t&&this.notify(this.removeListeners,t.info)}evictTerminal(){for(let[e,t]of this.entries)if(Q.has(t.info.status)&&!this.retained.has(e)){this.remove(e);return}}cleanupAll(){for(let[e,t]of this.entries)if(!Q.has(t.info.status)){try{t.abort()}catch{}X(t.info.worktree,(t,n)=>this.onWorktreeCleanupError?.(e,t,n)),t.info.status=`canceled`}}};const Ln=new In;let Rn=!1;function zn(e=Ln,t){Rn||(Rn=!0,t&&En(t,e.list().map(e=>e.id)),process.on(`exit`,()=>{e.cleanupAll()}))}const $=new Set([`done`,`error`,`aborted`]),Bn=new Set([`edit`,`write`,`delete`,`edit_file`,`write_file`]);function Vn(e){return Bn.has(e)}var Hn=class extends l{observations=new Map;abortFns=new Map;messagesRefs=new Map;streamingTexts=new Map;turns=new Map;evictTimers=new Map;pinned=new Set;now;warnMs;stalledMs;evictMs;constructor(e={}){super(),this.now=e.now??Date.now,this.warnMs=e.warnMs??3e3,this.stalledMs=e.stalledMs??3e4,this.evictMs=e.evictMs??15e3}register(e){let t=this.now(),n=this.evictTimers.get(e.id);n&&(clearTimeout(n),this.evictTimers.delete(e.id)),e.abort&&this.abortFns.set(e.id,e.abort),e.messages&&this.messagesRefs.set(e.id,e.messages),this.streamingTexts.set(e.id,``),this.turns.set(e.id,[]),this.observations.set(e.id,{id:e.id,agentName:e.agentName,title:e.title,prompt:e.prompt,model:e.model,modelDecidedBy:e.modelDecidedBy,origin:e.origin??`main`,depth:e.depth??0,status:`streaming`,turnIndex:0,toolUseCount:0,filesEdited:0,tokenCount:0,inputTokens:0,lastActivity:`starting`,lastEventAt:t,abortable:e.abortable??e.abort!==void 0,startedAt:t}),this.emit(`change`)}abort(e){let t=this.observations.get(e),n=this.abortFns.get(e);return!t||!n||$.has(t.status)?!1:(n(),!0)}record(e,t){let n=this.observations.get(e);if(!n)return;n.lastEventAt=this.now();let r=!0;switch(t.type){case`turn.start`:n.turnIndex=t.turnIndex,n.status=`streaming`,n.lastActivity=`thinking`,n.blockedOn=`model_io`,n.blockDetail=void 0,this.streamingTexts.set(e,``),this.turns.get(e)?.push({index:t.turnIndex,startedAt:this.now(),toolCount:0,tools:[],outputTokens:0});break;case`stream.event`:{let i=t.event;i.type===`text_delta`?(n.lastActivity=`responding`,n.blockedOn=void 0,this.streamingTexts.set(e,(this.streamingTexts.get(e)??``)+i.delta)):i.type.startsWith(`thinking`)&&(n.lastActivity=`thinking`,n.blockedOn=void 0),r=!1;break}case`tool.call.start`:{n.toolUseCount+=1,n.status=`tool_executing`,n.lastActivity=`using ${t.toolCall.name}`,n.blockedOn=`process`,n.blockDetail=t.toolCall.name;let r=this.turns.get(e);r?.length&&(r[r.length-1].toolCount+=1,r[r.length-1].tools.push(t.toolCall.name));break}case`tool.call.end`:n.status=`streaming`,n.lastActivity=`thinking`,n.blockedOn=`model_io`,n.blockDetail=void 0,Vn(t.toolCall.name)&&(n.filesEdited+=1);break;case`turn.end`:{let r=t.message.usage.outputTokens??0;n.tokenCount+=r,n.inputTokens=t.message.usage.inputTokens??n.inputTokens,this.streamingTexts.set(e,``);let i=this.turns.get(e),a=i?.[i.length-1];a&&a.endedAt===void 0&&(a.endedAt=this.now(),a.outputTokens=r);break}case`stream.retry`:n.lastActivity=`reconnecting ${t.attempt}/${t.maxRetries}`,n.blockedOn=`model_io`;break;case`status.change`:this.applyTerminal(n,t.to);break;case`error`:this.markTerminal(n,`error`);break;case`abort`:this.markTerminal(n,`aborted`);break;case`lifecycle.tool.completed`:n.lastActivity=`${t.toolName} ${t.isError?`failed`:`completed`} (background)`,n.lastEventAt=this.now(),r=!0;break;case`lifecycle.tool.completed.crossBoundary`:n.lastActivity=`${t.toolName} completed in background (result not shown — belongs to a previous prompt)`,n.lastEventAt=this.now(),r=!0;break;default:r=!1;break}r&&this.emit(`change`)}setAwaitingApproval(e,t){let n=this.observations.get(e);n&&(n.status=`awaiting_gate`,n.lastActivity=`awaiting approval`,n.blockedOn=`approval`,n.blockDetail=t,n.lastEventAt=this.now(),this.emit(`change`))}clearAwaitingApproval(e){let t=this.observations.get(e);!t||t.status!==`awaiting_gate`||(t.status=`streaming`,t.lastActivity=`thinking`,t.blockedOn=`model_io`,t.blockDetail=void 0,t.lastEventAt=this.now(),this.emit(`change`))}setToolWaiting(e,t){let n=this.observations.get(e);n&&(n.status=`tool_waiting`,n.lastActivity=t,n.blockedOn=`process`,n.blockDetail=t,n.lastEventAt=this.now(),this.emit(`change`))}clearToolWaiting(e){let t=this.observations.get(e);!t||t.status!==`tool_waiting`||(t.status=`streaming`,t.lastActivity=`thinking`,t.blockedOn=`model_io`,t.blockDetail=void 0,t.lastEventAt=this.now(),this.emit(`change`))}markEnded(e,t=`done`){let n=this.observations.get(e);!n||$.has(n.status)||(this.markTerminal(n,t),this.emit(`change`))}pin(e){let t=this.evictTimers.get(e);t&&(clearTimeout(t),this.evictTimers.delete(e)),this.pinned.add(e)}unpin(e){this.pinned.delete(e);let t=this.observations.get(e);t&&t.endedAt!==void 0&&this.scheduleEvict(e)}remove(e){let t=this.evictTimers.get(e);t&&(clearTimeout(t),this.evictTimers.delete(e)),this.observations.delete(e),this.abortFns.delete(e),this.messagesRefs.delete(e),this.streamingTexts.delete(e),this.turns.delete(e),this.pinned.delete(e),this.emit(`change`)}get(e){let t=this.observations.get(e);return t?this.toSnapshot(t):void 0}getMessages(e){let t=this.messagesRefs.get(e);if(t)return[...typeof t==`function`?t():t]}setMessages(e,t){this.messagesRefs.has(e)&&this.messagesRefs.set(e,[...t])}getStreamingText(e){return this.streamingTexts.get(e)??``}getTurns(e){let t=this.turns.get(e);return t?t.map(e=>({...e,tools:[...e.tools]})):[]}list(){return[...this.observations.values()].map(e=>this.toSnapshot(e))}listActive(){return this.list().filter(e=>!$.has(e.status))}subscribe(e){return this.on(`change`,e)}clear(){for(let e of this.evictTimers.values())clearTimeout(e);this.evictTimers.clear(),this.observations.clear(),this.abortFns.clear(),this.messagesRefs.clear(),this.streamingTexts.clear(),this.turns.clear(),this.pinned.clear()}applyTerminal(e,t){t===`completed`?this.markTerminal(e,`done`):t===`error`?this.markTerminal(e,`error`):t===`aborted`&&this.markTerminal(e,`aborted`)}markTerminal(e,t){e.status=t,e.lastActivity=t,e.blockedOn=void 0,e.blockDetail=void 0,e.endedAt=this.now(),this.scheduleEvict(e.id)}scheduleEvict(e){if(this.pinned.has(e))return;let t=this.evictTimers.get(e);t&&clearTimeout(t);let n=setTimeout(()=>{this.observations.delete(e),this.evictTimers.delete(e),this.abortFns.delete(e),this.messagesRefs.delete(e),this.streamingTexts.delete(e),this.turns.delete(e),this.emit(`change`)},this.evictMs);n.unref?.(),this.evictTimers.set(e,n)}toSnapshot(e){let t=e.endedAt!==void 0,n=t?0:Math.max(0,this.now()-e.lastEventAt),r=t?`none`:n>this.stalledMs?`stalled`:n>this.warnMs?`warn`:`none`;return{...e,idleMs:n,stall:r}}};const Un=new Hn;function Wn(e,t,n=Un){n.register(t);let r=t.id,i=[e.on(`turn.start`,e=>n.record(r,{type:`turn.start`,...e})),e.on(`turn.end`,e=>n.record(r,{type:`turn.end`,...e})),e.on(`stream.event`,e=>n.record(r,{type:`stream.event`,...e})),e.on(`tool.call.start`,e=>n.record(r,{type:`tool.call.start`,...e})),e.on(`tool.call.end`,e=>n.record(r,{type:`tool.call.end`,...e})),e.on(`status.change`,e=>n.record(r,{type:`status.change`,...e})),e.on(`stream.retry`,e=>n.record(r,{type:`stream.retry`,...e})),e.on(`error`,e=>n.record(r,{type:`error`,...e})),e.on(`abort`,()=>n.record(r,{type:`abort`})),e.on(`lifecycle.tool.completed`,e=>n.record(r,{type:`lifecycle.tool.completed`,...e})),e.on(`lifecycle.tool.completed.crossBoundary`,e=>n.record(r,{type:`lifecycle.tool.completed.crossBoundary`,...e}))];return()=>{for(let e of i)e()}}function Gn(e){let t=0;for(let n of e)/[\u3000-\u9fff\uff00-\uffef]/.test(n)&&t++;return Math.ceil(t+(e.length-t)/4)}function Kn(e,t){if(t<=0)return``;let n=t*4,r=Array.from(e);return r.length<=n?e:r.slice(0,n).join(``)}function qn(e,t=4e3){let n=[`<agent_memory_updates note="本会话中途更新——取代上方缓存中的对应文件">`],r=0,i=0;for(let a of e){let e=Array.isArray(a)?{kind:`upsert`,path:a[0],content:a[1]}:a,o=t-r;if(o<=0){i++;continue}if(e.kind===`remove`){let t=`[removed during this session — disregard the cached version of ${e.path} above]`,a=Gn(t);if(a>o){i++;continue}n.push(`# ${e.path}`),n.push(t),n.push(``),r+=a;continue}let{path:s,content:c}=e,l=c.trim();if(!l)continue;if(o<=0){i++;continue}let u=Gn(l);if(u<=o)n.push(`# ${s}`),n.push(l),n.push(``),r+=u;else{let e=Kn(l,o);n.push(`# ${s}`),n.push(e),n.push(`\n> ⚠ [truncated — content exceeded the memory delta budget (${t} tokens); remainder omitted]`),n.push(``),r=t}}return i>0&&(n.push(`> ⚠ [${i} additional changed memory source(s) omitted — delta budget (${t} tokens) reached]`),n.push(``)),n.push(`</agent_memory_updates>`),n.join(`
21
- `)}function Jn(e,t=M.memoryDelta.priority){let n=new Map,r=new Map;return[o({name:`memory-delta-injection`,timing:`system.prompt.transform`,priority:t,handle:(t,i)=>{let a=e.getMemories(),o=n.get(t.sessionId);if(!o){n.set(t.sessionId,new Map(a));return}let s=r.get(t.sessionId)??new Set;for(let e of o.keys())a.has(e)||s.add(e);for(let e of a.keys())s.delete(e);r.set(t.sessionId,s);let c=[];for(let e of s)c.push({kind:`remove`,path:e});for(let[e,t]of a)o.get(e)!==t&&c.push({kind:`upsert`,path:e,content:t});c.length!==0&&(i.systemTail??=[],i.systemTail.push(qn(c)))}}),o({name:`memory-delta-cleanup`,timing:`session.deleted`,priority:90,handle:e=>{let t=e.sessionId;n.delete(t),r.delete(t)}})]}const Yn=new Set([`done`,`skipped`,`failed`]);function Xn(e){return!Yn.has(e??`pending`)}function Zn(e){let t=[`<system-reminder>`,`Your todo list still has ${e.filter(e=>Xn(e.status)).length} unfinished item(s). Do not treat the task as complete — and do not end your turn — while any item is pending or in_progress. Either finish the remaining work and mark each item done, or explicitly mark items skipped/failed with a reason. Latest todo state:`];for(let n of e)t.push(`- [${n.status??`pending`}] ${n.title??``}`);return t.push(`Continue with the unfinished items now. (This reminder is system-generated from your todo list; do not repeat it back to the user.)`),t.push(`</system-reminder>`),t.join(`
22
- `)}function Qn(e,t=M.todoReminder.priority){return[o({name:`todo-reminder-injection`,timing:`system.prompt.transform`,priority:t,handle:(t,n)=>{let r=e.getTodoList(t.sessionId);!r||r.length===0||r.some(e=>Xn(e.status))&&(n.systemTail??=[],n.systemTail.push(Zn(r)))}})]}function $n(){return{touchedDoc:!1,toolTouchedDoc:void 0,calledWriteTodos:!1}}function er(e){return[`<system-reminder>`,`You just modified a tracked progress document (via ${e}) but have not called write_todos in this turn. write_todos (the UI-pinned todo list) and progress documents are two independent tracking systems that do not auto-sync. If this document edit reflects real progress (e.g. a milestone Status flip to Done), call write_todos now to keep the pinned list consistent with the document. (This reminder is system-generated; do not repeat it back to the user.)`,`</system-reminder>`].join(`
23
- `)}function tr(e,t=M.docSyncReminder.priority){let n=new Map;return[o({name:`doc-sync-tool-tracker`,timing:`tool.execute.after`,priority:90,handle:t=>{let r=n.get(t.sessionId)??$n();t.toolName===`write_todos`?r.calledWriteTodos=!0:!r.touchedDoc&&e.isDocSyncTrigger(t)&&(r.touchedDoc=!0,r.toolTouchedDoc=t.toolName),n.set(t.sessionId,r)}}),o({name:`doc-sync-turn-reset`,timing:`chat.message.before`,priority:10,handle:e=>{e.message.internal!==!0&&n.set(e.sessionId,$n())}}),o({name:`doc-sync-reminder-injection`,timing:`system.prompt.transform`,priority:t,handle:(e,t)=>{let r=n.get(e.sessionId);!r?.touchedDoc||r.calledWriteTodos||(t.systemTail??=[],t.systemTail.push(er(r.toolTouchedDoc??`edit/write`)))}}),o({name:`doc-sync-cleanup`,timing:`session.deleted`,priority:90,handle:e=>{n.delete(e.sessionId)}})]}function nr(e,t){let{totalBytes:n,minPerSessionBytes:r,maxPerSessionBytes:i}=k(t);if(e<=0)return i;let a=Math.floor(n/e);return Math.max(r,Math.min(a,i))}function rr(e,t,n){let{minPerSessionBytes:r}=k(n),i=nr(e,n),a=Math.max(1,Math.floor(r/t));return Math.max(a,Math.floor(i/t))}export{In as AgentJobRegistry,Hn as AgentObservabilityRegistry,wt as AgentSession,Mn as CAPABILITY_SURFACE_PATTERNS,Ge as ContextSourceRegistry,Pn as DEFAULT_MAX_AUTO_APPLY_LINES,Dn as FORBIDDEN_ZONE_PATTERNS,un as FleetMonitor,I as LEVEL_DIVISOR,ln as MemoryGovernor,V as PanelStateStore,en as PersistenceSync,dn as ProcessRegistry,_n as ProcessRuntime,vt as RUNTIME_DEFAULTS,Ut as ResidencyGovernor,M as SYSTEM_PROMPT_SECTIONS,Vt as SandboxUnavailableError,H as SessionPool,Ht as TimeTravelController,wn as applyDiff,he as applyMemoryTransform,Wn as attachAgentObserver,Ue as buildEngineStores,Ot as captureFiles,sn as createAgentRuntime,on as createDefaultContextSourceRegistry,tn as createDiskSessionPool,tr as createDocSyncReminderHooks,Ke as createEnvironmentContextSource,rn as createInMemorySessionPool,Jn as createMemoryDeltaHooks,qe as createMemoryIndexContextSource,nn as createRemoteSessionPool,We as createSessionStableInjectionHooks,Qn as createTodoReminderHooks,Ye as createToolHookExecutor,xn as createWorktree,Fn as decideApply,L as decideResidency,St as defaultMaxToolTurnExtensions,N as deriveSessionTitle,Z as diffTouchedPaths,rr as effectiveResidencyBudget,er as formatDocSyncReminder,Ln as globalAgentJobRegistry,Un as globalAgentObservability,fn as globalProcessRegistry,vn as globalProcessRuntime,Cn as hasRepoDrifted,zn as installAgentJobReaper,bn as installExitReaper,mn as installProcessReaper,Mt as messagesFromSnapshot,En as pruneOrphanWorktrees,Ft as reconstructMessages,X as removeWorktree,Xe as resolveSessionTitle,Ct as resolveTodoContinuationConfig,kt as restoreFiles,Tn as revertDiff,Nn as touchesCapabilitySurface,jn as touchesForbiddenZone,Sn as worktreeDiff};
19
+ `),o=``,s=``;for(let e of a)e.startsWith(`worktree `)?o=e.slice(9):e.startsWith(`branch `)&&(s=e.slice(7));if(!o||!s)continue;let c=/^refs\/heads\/otto\/job-(.+)$/.exec(s);if(!c)continue;let l=c[1],u;try{u=We(o)}catch{continue}if(u.startsWith(i)&&!n.has(l)){try{J(e,[`worktree`,`remove`,`--force`,o])}catch{}try{J(e,[`branch`,`-D`,s.slice(11)])}catch{}r.push(o)}}try{J(e,[`worktree`,`prune`])}catch{}return r}const In=[/(^|\/)governance\/forbidden-zone\./,/(^|\/)packages\/setting\//,/(^|\/)permission/i,/(^|\/)sandbox/i,/(^|\/)git-worktree\./,/(^|\/)agent-job-service\./,/(^|\/)mcp-controller\./,/(^|\/)packages\/mcp\/src\/oauth\//,/(allowlist|allow-list|egress|networkpolicy)/i];function Ln(e){if(e.length<2||!e.startsWith(`"`)||!e.endsWith(`"`))return e;let t=e.slice(1,-1),n=[];for(let e=0;e<t.length;e++){if(t[e]!==`\\`){n.push(t.charCodeAt(e));continue}let r=t[e+1];r&&r>=`0`&&r<=`7`?(n.push(parseInt(t.slice(e+1,e+4),8)),e+=3):(n.push({t:9,n:10,r:13,'"':34,"\\":92}[r]??(r?r.charCodeAt(0):92)),e+=1)}return Buffer.from(n).toString(`utf-8`)}function Rn(e){let t=Ln(e.trim());return t===`/dev/null`?null:t.replace(/^[ab]\//,``)}function zn(e){let t=/^("(?:[^"\\]|\\.)*") ("(?:[^"\\]|\\.)*")$/.exec(e);if(t)return[t[1],t[2]];let n=/^(a\/.+?) (b\/.+)$/.exec(e);return n?[n[1],n[2]]:[]}function Z(e){let t=new Set;for(let n of e.split(`
20
+ `)){if(n.startsWith(`diff --git `)){for(let e of zn(n.slice(11))){let n=Rn(e);n&&t.add(n)}continue}if(/^\+\+\+ "?[ab]\//.test(n)||/^--- "?[ab]\//.test(n)){let e=Rn(n.slice(4));e&&t.add(e)}}return[...t]}function Bn(e){return e.trim()?Z(e).filter(e=>In.some(t=>t.test(e))):[]}const Vn=[/(^|\/)\.otto\/(agents|skills|teams)\//i,/(^|\/)\.otto\/[^/]*config/i,/(^|\/)otto\.config\./i];function Hn(e){return e.trim()?Z(e).filter(e=>Vn.some(t=>t.test(e))):[]}const Un=200;function Wn(e,t){let{forbiddenZone:n,capabilityTouched:r,diffStat:i,conflict:a,origin:o}=e,s=t.maxAutoApplyLines??200,c=i.added+i.removed;if(o!==`user`&&n.length>0)return{action:`forbid`,reasons:[`触及治理禁区(高危自我修改):${n.join(`, `)}`]};if(o===`plugin`){let e=[`插件发起的作业需人手 apply(RFC-287 R2)`];return r.length&&e.push(`触及能力面:${r.join(`, `)}`),a&&e.push(`存在冲突`),c>s&&e.push(`改动较大(${c} 行 > ${s})`),{action:`gate`,reasons:e}}if(o===`user`){let e=[];return n.length&&e.push(`触及治理禁区:${n.join(`, `)}`),r.length&&e.push(`触及能力面:${r.join(`, `)}`),a&&e.push(`存在冲突,无法干净落地`),{action:`advise`,recommend:e.length?`review`:`apply`,reasons:e}}if(t.level<=1){let e=[];return r.length&&e.push(`触及能力面:${r.join(`, `)}`),a&&e.push(`存在冲突`),c>s&&e.push(`改动较大(${c} 行 > ${s})`),t.level===0?{action:`gate`,reasons:[`autonomy L0:需人手 apply`,...e]}:{action:`advise`,recommend:e.length?`review`:`apply`,reasons:e}}let l=[];return a&&l.push(`apply 有冲突`),c>s&&l.push(`改动超规模(${c} 行 > ${s})`),r.length&&t.level<3&&l.push(`触及能力面(需 L3+):${r.join(`, `)}`),l.length?{action:`gate`,reasons:l}:{action:`auto`}}const Q=new Set([`applied`,`failed`,`canceled`]);var Gn=class{entries=new Map;maxJobs;clock;onWorktreeCleanupError;spawnListeners=new Set;updateListeners=new Set;exitListeners=new Set;removeListeners=new Set;retained=new Set;constructor(e={}){this.maxJobs=e.maxJobs??16,this.clock=e.clock??(()=>Date.now()),this.onWorktreeCleanupError=e.onWorktreeCleanupError}setWorktreeCleanupErrorHandler(e){this.onWorktreeCleanupError=e}onSpawn(e){return this.spawnListeners.add(e),()=>this.spawnListeners.delete(e)}onUpdate(e){return this.updateListeners.add(e),()=>this.updateListeners.delete(e)}onExit(e){return this.exitListeners.add(e),()=>this.exitListeners.delete(e)}onRemove(e){return this.removeListeners.add(e),()=>this.removeListeners.delete(e)}retain(e,t){t?this.retained.add(e):this.retained.delete(e)}notify(e,t){for(let n of[...e])try{n(t)}catch{}}register(e){if(this.entries.size>=this.maxJobs&&this.evictTerminal(),this.entries.size>=this.maxJobs)throw Error(`Agent job limit (${this.maxJobs}) reached; cancel one with stop first.`);let t=e.now??this.clock(),n={id:e.id,sessionId:e.sessionId,type:`agent-session`,title:e.title,origin:e.origin??`user`,status:`running`,worktree:e.worktree,outputPath:e.outputPath,startedAt:t};return this.entries.set(e.id,{info:n,abort:e.abort}),this.notify(this.spawnListeners,n),n}get(e){return this.entries.get(e)?.info}getForSession(e,t){let n=this.entries.get(t);return n&&n.info.sessionId===e?n.info:void 0}list(){return[...this.entries.values()].map(e=>e.info)}listForSession(e){return this.list().filter(t=>t.sessionId===e)}size(){return this.entries.size}update(e,t){let n=this.entries.get(e);n&&(Q.has(n.info.status)||(Object.assign(n.info,t),this.notify(this.updateListeners,n.info),Q.has(n.info.status)&&(n.info.status!==`canceled`&&X(n.info.worktree,(t,n)=>this.onWorktreeCleanupError?.(e,t,n)),this.notify(this.exitListeners,n.info))))}cancel(e){let t=this.entries.get(e);if(!(!t||Q.has(t.info.status))){try{t.abort()}catch{}X(t.info.worktree,(t,n)=>this.onWorktreeCleanupError?.(e,t,n)),this.update(e,{status:`canceled`})}}remove(e){let t=this.entries.get(e);t&&X(t.info.worktree,(t,n)=>this.onWorktreeCleanupError?.(e,t,n)),this.retained.delete(e),this.entries.delete(e),t&&this.notify(this.removeListeners,t.info)}evictTerminal(){for(let[e,t]of this.entries)if(Q.has(t.info.status)&&!this.retained.has(e)){this.remove(e);return}}cleanupAll(){for(let[e,t]of this.entries)if(!Q.has(t.info.status)){try{t.abort()}catch{}X(t.info.worktree,(t,n)=>this.onWorktreeCleanupError?.(e,t,n)),t.info.status=`canceled`}}};const Kn=new Gn;let qn=!1;function Jn(e=Kn,t){qn||(qn=!0,t&&Fn(t,e.list().map(e=>e.id)),process.on(`exit`,()=>{e.cleanupAll()}))}const $=new Set([`done`,`error`,`aborted`]),Yn=new Set([`edit`,`write`,`delete`,`edit_file`,`write_file`]);function Xn(e){return Yn.has(e)}var Zn=class extends l{observations=new Map;abortFns=new Map;messagesRefs=new Map;streamingTexts=new Map;turns=new Map;evictTimers=new Map;pinned=new Set;now;warnMs;stalledMs;evictMs;constructor(e={}){super(),this.now=e.now??Date.now,this.warnMs=e.warnMs??3e3,this.stalledMs=e.stalledMs??3e4,this.evictMs=e.evictMs??15e3}register(e){let t=this.now(),n=this.evictTimers.get(e.id);n&&(clearTimeout(n),this.evictTimers.delete(e.id)),e.abort&&this.abortFns.set(e.id,e.abort),e.messages&&this.messagesRefs.set(e.id,e.messages),this.streamingTexts.set(e.id,``),this.turns.set(e.id,[]),this.observations.set(e.id,{id:e.id,agentName:e.agentName,title:e.title,prompt:e.prompt,model:e.model,modelDecidedBy:e.modelDecidedBy,origin:e.origin??`main`,depth:e.depth??0,status:`streaming`,turnIndex:0,toolUseCount:0,filesEdited:0,tokenCount:0,inputTokens:0,lastActivity:`starting`,lastEventAt:t,abortable:e.abortable??e.abort!==void 0,startedAt:t}),this.emit(`change`)}abort(e){let t=this.observations.get(e),n=this.abortFns.get(e);return!t||!n||$.has(t.status)?!1:(n(),!0)}record(e,t){let n=this.observations.get(e);if(!n)return;n.lastEventAt=this.now();let r=!0;switch(t.type){case`turn.start`:n.turnIndex=t.turnIndex,n.status=`streaming`,n.lastActivity=`thinking`,n.blockedOn=`model_io`,n.blockDetail=void 0,this.streamingTexts.set(e,``),this.turns.get(e)?.push({index:t.turnIndex,startedAt:this.now(),toolCount:0,tools:[],outputTokens:0});break;case`stream.event`:{let i=t.event;i.type===`text_delta`?(n.lastActivity=`responding`,n.blockedOn=void 0,this.streamingTexts.set(e,(this.streamingTexts.get(e)??``)+i.delta)):i.type.startsWith(`thinking`)&&(n.lastActivity=`thinking`,n.blockedOn=void 0),r=!1;break}case`tool.call.start`:{n.toolUseCount+=1,n.status=`tool_executing`,n.lastActivity=`using ${t.toolCall.name}`,n.blockedOn=`process`,n.blockDetail=t.toolCall.name;let r=this.turns.get(e);r?.length&&(r[r.length-1].toolCount+=1,r[r.length-1].tools.push(t.toolCall.name));break}case`tool.call.end`:n.status=`streaming`,n.lastActivity=`thinking`,n.blockedOn=`model_io`,n.blockDetail=void 0,Xn(t.toolCall.name)&&(n.filesEdited+=1);break;case`turn.end`:{let r=t.message.usage.outputTokens??0;n.tokenCount+=r,n.inputTokens=t.message.usage.inputTokens??n.inputTokens,this.streamingTexts.set(e,``);let i=this.turns.get(e),a=i?.[i.length-1];a&&a.endedAt===void 0&&(a.endedAt=this.now(),a.outputTokens=r);break}case`stream.retry`:n.lastActivity=`reconnecting ${t.attempt}/${t.maxRetries}`,n.blockedOn=`model_io`;break;case`status.change`:this.applyTerminal(n,t.to);break;case`error`:this.markTerminal(n,`error`);break;case`abort`:this.markTerminal(n,`aborted`);break;case`lifecycle.tool.completed`:n.lastActivity=`${t.toolName} ${t.isError?`failed`:`completed`} (background)`,n.lastEventAt=this.now(),r=!0;break;case`lifecycle.tool.completed.crossBoundary`:n.lastActivity=`${t.toolName} completed in background (result not shown — belongs to a previous prompt)`,n.lastEventAt=this.now(),r=!0;break;default:r=!1;break}r&&this.emit(`change`)}setAwaitingApproval(e,t){let n=this.observations.get(e);n&&(n.status=`awaiting_gate`,n.lastActivity=`awaiting approval`,n.blockedOn=`approval`,n.blockDetail=t,n.lastEventAt=this.now(),this.emit(`change`))}clearAwaitingApproval(e){let t=this.observations.get(e);!t||t.status!==`awaiting_gate`||(t.status=`streaming`,t.lastActivity=`thinking`,t.blockedOn=`model_io`,t.blockDetail=void 0,t.lastEventAt=this.now(),this.emit(`change`))}setToolWaiting(e,t){let n=this.observations.get(e);n&&(n.status=`tool_waiting`,n.lastActivity=t,n.blockedOn=`process`,n.blockDetail=t,n.lastEventAt=this.now(),this.emit(`change`))}clearToolWaiting(e){let t=this.observations.get(e);!t||t.status!==`tool_waiting`||(t.status=`streaming`,t.lastActivity=`thinking`,t.blockedOn=`model_io`,t.blockDetail=void 0,t.lastEventAt=this.now(),this.emit(`change`))}markEnded(e,t=`done`){let n=this.observations.get(e);!n||$.has(n.status)||(this.markTerminal(n,t),this.emit(`change`))}pin(e){let t=this.evictTimers.get(e);t&&(clearTimeout(t),this.evictTimers.delete(e)),this.pinned.add(e)}unpin(e){this.pinned.delete(e);let t=this.observations.get(e);t&&t.endedAt!==void 0&&this.scheduleEvict(e)}remove(e){let t=this.evictTimers.get(e);t&&(clearTimeout(t),this.evictTimers.delete(e)),this.observations.delete(e),this.abortFns.delete(e),this.messagesRefs.delete(e),this.streamingTexts.delete(e),this.turns.delete(e),this.pinned.delete(e),this.emit(`change`)}get(e){let t=this.observations.get(e);return t?this.toSnapshot(t):void 0}getMessages(e){let t=this.messagesRefs.get(e);if(t)return[...typeof t==`function`?t():t]}setMessages(e,t){this.messagesRefs.has(e)&&this.messagesRefs.set(e,[...t])}getStreamingText(e){return this.streamingTexts.get(e)??``}getTurns(e){let t=this.turns.get(e);return t?t.map(e=>({...e,tools:[...e.tools]})):[]}list(){return[...this.observations.values()].map(e=>this.toSnapshot(e))}listActive(){return this.list().filter(e=>!$.has(e.status))}subscribe(e){return this.on(`change`,e)}clear(){for(let e of this.evictTimers.values())clearTimeout(e);this.evictTimers.clear(),this.observations.clear(),this.abortFns.clear(),this.messagesRefs.clear(),this.streamingTexts.clear(),this.turns.clear(),this.pinned.clear()}applyTerminal(e,t){t===`completed`?this.markTerminal(e,`done`):t===`error`?this.markTerminal(e,`error`):t===`aborted`&&this.markTerminal(e,`aborted`)}markTerminal(e,t){e.status=t,e.lastActivity=t,e.blockedOn=void 0,e.blockDetail=void 0,e.endedAt=this.now(),this.scheduleEvict(e.id)}scheduleEvict(e){if(this.pinned.has(e))return;let t=this.evictTimers.get(e);t&&clearTimeout(t);let n=setTimeout(()=>{this.observations.delete(e),this.evictTimers.delete(e),this.abortFns.delete(e),this.messagesRefs.delete(e),this.streamingTexts.delete(e),this.turns.delete(e),this.emit(`change`)},this.evictMs);n.unref?.(),this.evictTimers.set(e,n)}toSnapshot(e){let t=e.endedAt!==void 0,n=t?0:Math.max(0,this.now()-e.lastEventAt),r=t?`none`:n>this.stalledMs?`stalled`:n>this.warnMs?`warn`:`none`;return{...e,idleMs:n,stall:r}}};const Qn=new Zn;function $n(e,t,n=Qn){n.register(t);let r=t.id,i=[e.on(`turn.start`,e=>n.record(r,{type:`turn.start`,...e})),e.on(`turn.end`,e=>n.record(r,{type:`turn.end`,...e})),e.on(`stream.event`,e=>n.record(r,{type:`stream.event`,...e})),e.on(`tool.call.start`,e=>n.record(r,{type:`tool.call.start`,...e})),e.on(`tool.call.end`,e=>n.record(r,{type:`tool.call.end`,...e})),e.on(`status.change`,e=>n.record(r,{type:`status.change`,...e})),e.on(`stream.retry`,e=>n.record(r,{type:`stream.retry`,...e})),e.on(`error`,e=>n.record(r,{type:`error`,...e})),e.on(`abort`,()=>n.record(r,{type:`abort`})),e.on(`lifecycle.tool.completed`,e=>n.record(r,{type:`lifecycle.tool.completed`,...e})),e.on(`lifecycle.tool.completed.crossBoundary`,e=>n.record(r,{type:`lifecycle.tool.completed.crossBoundary`,...e}))];return()=>{for(let e of i)e()}}function er(e){let t=0;for(let n of e)/[\u3000-\u9fff\uff00-\uffef]/.test(n)&&t++;return Math.ceil(t+(e.length-t)/4)}function tr(e,t){if(t<=0)return``;let n=t*4,r=Array.from(e);return r.length<=n?e:r.slice(0,n).join(``)}function nr(e,t=4e3){let n=[`<agent_memory_updates note="本会话中途更新——取代上方缓存中的对应文件">`],r=0,i=0;for(let a of e){let e=Array.isArray(a)?{kind:`upsert`,path:a[0],content:a[1]}:a,o=t-r;if(o<=0){i++;continue}if(e.kind===`remove`){let t=`[removed during this session — disregard the cached version of ${e.path} above]`,a=er(t);if(a>o){i++;continue}n.push(`# ${e.path}`),n.push(t),n.push(``),r+=a;continue}let{path:s,content:c}=e,l=c.trim();if(!l)continue;if(o<=0){i++;continue}let u=er(l);if(u<=o)n.push(`# ${s}`),n.push(l),n.push(``),r+=u;else{let e=tr(l,o);n.push(`# ${s}`),n.push(e),n.push(`\n> ⚠ [truncated — content exceeded the memory delta budget (${t} tokens); remainder omitted]`),n.push(``),r=t}}return i>0&&(n.push(`> ⚠ [${i} additional changed memory source(s) omitted — delta budget (${t} tokens) reached]`),n.push(``)),n.push(`</agent_memory_updates>`),n.join(`
21
+ `)}function rr(e,t=A.memoryDelta.priority){let n=new Map,r=new Map;return[o({name:`memory-delta-injection`,timing:`system.prompt.transform`,priority:t,handle:(t,i)=>{let a=e.getMemories(),o=n.get(t.sessionId);if(!o){n.set(t.sessionId,new Map(a));return}let s=r.get(t.sessionId)??new Set;for(let e of o.keys())a.has(e)||s.add(e);for(let e of a.keys())s.delete(e);r.set(t.sessionId,s);let c=[];for(let e of s)c.push({kind:`remove`,path:e});for(let[e,t]of a)o.get(e)!==t&&c.push({kind:`upsert`,path:e,content:t});c.length!==0&&(i.systemTail??=[],i.systemTail.push(j(`memory-delta-injection`,nr(c))))}}),o({name:`memory-delta-cleanup`,timing:`session.deleted`,priority:90,handle:e=>{let t=e.sessionId;n.delete(t),r.delete(t)}})]}const ir=new Set([`done`,`skipped`,`failed`]);function ar(e){return!ir.has(e??`pending`)}function or(e){let t=[`<system-reminder>`,`Your todo list still has ${e.filter(e=>ar(e.status)).length} unfinished item(s). Do not treat the task as complete — and do not end your turn — while any item is pending or in_progress. Either finish the remaining work and mark each item done, or explicitly mark items skipped/failed with a reason. Latest todo state:`];for(let n of e)t.push(`- [${n.status??`pending`}] ${n.title??``}`);return t.push(`Continue with the unfinished items now. (This reminder is system-generated from your todo list; do not repeat it back to the user.)`),t.push(`</system-reminder>`),t.join(`
22
+ `)}function sr(e,t=A.todoReminder.priority){return[o({name:`todo-reminder-injection`,timing:`system.prompt.transform`,priority:t,handle:(t,n)=>{let r=e.getTodoList(t.sessionId);!r||r.length===0||r.some(e=>ar(e.status))&&(n.systemTail??=[],n.systemTail.push(j(`todo-reminder-injection`,or(r))))}})]}function cr(){return{touchedDoc:!1,toolTouchedDoc:void 0,calledWriteTodos:!1}}function lr(e){return[`<system-reminder>`,`You just modified a tracked progress document (via ${e}) but have not called write_todos in this turn. write_todos (the UI-pinned todo list) and progress documents are two independent tracking systems that do not auto-sync. If this document edit reflects real progress (e.g. a milestone Status flip to Done), call write_todos now to keep the pinned list consistent with the document. (This reminder is system-generated; do not repeat it back to the user.)`,`</system-reminder>`].join(`
23
+ `)}function ur(e,t=A.docSyncReminder.priority){let n=new Map;return[o({name:`doc-sync-tool-tracker`,timing:`tool.execute.after`,priority:90,handle:t=>{let r=n.get(t.sessionId)??cr();t.toolName===`write_todos`?r.calledWriteTodos=!0:!r.touchedDoc&&e.isDocSyncTrigger(t)&&(r.touchedDoc=!0,r.toolTouchedDoc=t.toolName),n.set(t.sessionId,r)}}),o({name:`doc-sync-turn-reset`,timing:`chat.message.before`,priority:10,handle:e=>{e.message.internal!==!0&&n.set(e.sessionId,cr())}}),o({name:`doc-sync-reminder-injection`,timing:`system.prompt.transform`,priority:t,handle:(e,t)=>{let r=n.get(e.sessionId);!r?.touchedDoc||r.calledWriteTodos||(t.systemTail??=[],t.systemTail.push(j(`doc-sync-reminder-injection`,lr(r.toolTouchedDoc??`edit/write`))))}}),o({name:`doc-sync-cleanup`,timing:`session.deleted`,priority:90,handle:e=>{n.delete(e.sessionId)}})]}function dr(e,t){let{totalBytes:n,minPerSessionBytes:r,maxPerSessionBytes:i}=O(t);if(e<=0)return i;let a=Math.floor(n/e);return Math.max(r,Math.min(a,i))}function fr(e,t,n){let{minPerSessionBytes:r}=O(n),i=dr(e,n),a=Math.max(1,Math.floor(r/t));return Math.max(a,Math.floor(i/t))}export{Gn as AgentJobRegistry,Zn as AgentObservabilityRegistry,Nt as AgentSession,Vn as CAPABILITY_SURFACE_PATTERNS,Xe as ContextSourceRegistry,Un as DEFAULT_MAX_AUTO_APPLY_LINES,In as FORBIDDEN_ZONE_PATTERNS,yn as FleetMonitor,F as LEVEL_DIVISOR,vn as MemoryGovernor,V as PanelStateStore,un as PersistenceSync,bn as ProcessRegistry,En as ProcessRuntime,Ct as RUNTIME_DEFAULTS,Qt as ResidencyGovernor,A as SYSTEM_PROMPT_SECTIONS,Xt as SandboxUnavailableError,H as SessionPool,Zt as TimeTravelController,Nn as applyDiff,ge as applyMemoryTransform,j as applySectionBudget,$n as attachAgentObserver,Ke as buildEngineStores,Lt as captureFiles,gn as createAgentRuntime,hn as createDefaultContextSourceRegistry,dn as createDiskSessionPool,ur as createDocSyncReminderHooks,Ze as createEnvironmentContextSource,pn as createInMemorySessionPool,rr as createMemoryDeltaHooks,Qe as createMemoryIndexContextSource,fn as createRemoteSessionPool,qe as createSessionStableInjectionHooks,sr as createTodoReminderHooks,et as createToolHookExecutor,An as createWorktree,Wn as decideApply,I as decideResidency,jt as defaultMaxToolTurnExtensions,M as deriveSessionTitle,Z as diffTouchedPaths,fr as effectiveResidencyBudget,lr as formatDocSyncReminder,Kn as globalAgentJobRegistry,Qn as globalAgentObservability,xn as globalProcessRegistry,Dn as globalProcessRuntime,Mn as hasRepoDrifted,Jn as installAgentJobReaper,kn as installExitReaper,Cn as installProcessReaper,Ht as messagesFromSnapshot,Fn as pruneOrphanWorktrees,P as reconstructMessages,X as removeWorktree,tt as resolveSessionTitle,Mt as resolveTodoContinuationConfig,Rt as restoreFiles,Pn as revertDiff,Hn as touchesCapabilitySurface,Bn as touchesForbiddenZone,jn as worktreeDiff};
24
24
  //# sourceMappingURL=index.js.map