@ai-agent-forge/agent-forge 0.85.5 → 0.85.7
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/CHANGELOG.md +7 -1
- package/dist/bundle/.build-manifest.json +6 -6
- package/dist/bundle/chunks/{chunk-7YVQMWO5.js → chunk-WD7FTOHY.js} +2 -2
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-compaction.js +6 -0
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session.d.ts +4 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +5 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/compaction.md +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
-
## [
|
|
5
|
+
## [0.85.7] - 2026-09-29
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Auto-compaction that decides to compact but finds no summarizable prefix (the entire session history sits inside the `keepRecentTokens` budget) now emits a `compaction_skipped` session event (`{ reason, cause: "nothing_to_compact" }`) instead of silently doing nothing, and the interactive TUI shows it as a transient status line ("Auto-compaction skipped: nothing to compact"). This surfaces the previously invisible "context is full but nothing compacts" state; manual `/compact` already reports it as "Nothing to compact (session too small)". Contract documented in `docs/compaction.md`; covered by `test/agent-session-auto-compaction-queue.test.ts`.
|
|
10
|
+
|
|
11
|
+
## [0.85.6] - 2026-09-29
|
|
6
12
|
|
|
7
13
|
## [0.85.5] - 2026-09-29
|
|
8
14
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-09-
|
|
2
|
+
"generatedAt": "2026-09-29T13:25:11.946Z",
|
|
3
3
|
"inputCount": 3560,
|
|
4
4
|
"inputs": {
|
|
5
5
|
"node_modules/@anthropic-ai/sdk/_vendor/partial-json-parser/parser.mjs": "717f9403f2d3ee0f2077aeb7f0ca7eaff7cc9bcdbb054ac23c6c0361fa03cd1f",
|
|
@@ -2103,7 +2103,7 @@
|
|
|
2103
2103
|
"packages/agent-forge/dist/config.js": "d5385bbd45014dd43ec334ca75d5061d32bf5e8313be63c271701d4adfc47f73",
|
|
2104
2104
|
"packages/agent-forge/dist/core/agent-capability-contract.js": "40ca2bb245646233e9299f16281ff8ce4cc318639e63d77181a1d81996b1b0e8",
|
|
2105
2105
|
"packages/agent-forge/dist/core/agent-session-bash.js": "be1e6ba94a28ee0bb34e5156b8a00312ce2c1dda8c703c7180b940a7e5f00f5d",
|
|
2106
|
-
"packages/agent-forge/dist/core/agent-session-compaction.js": "
|
|
2106
|
+
"packages/agent-forge/dist/core/agent-session-compaction.js": "380884770bebdc40669666995fba012a8e1aa2dcaf0d58cc270bba1547e9bd65",
|
|
2107
2107
|
"packages/agent-forge/dist/core/agent-session-context.js": "ce15ea36a1730153b82e15210cf384e70fecdd16d49108ba055101958e51e984",
|
|
2108
2108
|
"packages/agent-forge/dist/core/agent-session-extensions.js": "341572c1ca3be22e968b3772c39db2f2fbfba9d67eba589618a3dbbefdeb9655",
|
|
2109
2109
|
"packages/agent-forge/dist/core/agent-session-internal.js": "e1d42c9083684aa87f5f4f0c2e8d2057449c81ff93e45d9c7c9fa42fd3a6b956",
|
|
@@ -2288,7 +2288,7 @@
|
|
|
2288
2288
|
"packages/agent-forge/dist/modes/interactive/interactive-dialog-ui.js": "90898eb229aec95c087171b21c3c7ad64c65d9ba553d46a0610f405023bb666b",
|
|
2289
2289
|
"packages/agent-forge/dist/modes/interactive/interactive-format.js": "0baa01993d9fccd9afdb19937bd2cbe8eb91b820f9873f0f2b8dbfd84d646d18",
|
|
2290
2290
|
"packages/agent-forge/dist/modes/interactive/interactive-helpers.js": "b0094b0dd196d4667eb61d5d4498ac8429b4f8f8d9c7bf46313f3a36060cabf6",
|
|
2291
|
-
"packages/agent-forge/dist/modes/interactive/interactive-mode.js": "
|
|
2291
|
+
"packages/agent-forge/dist/modes/interactive/interactive-mode.js": "1981c4a2eefcf723da6f0c8cab355db2936cc01cfe5e85088df465671b8e89d1",
|
|
2292
2292
|
"packages/agent-forge/dist/modes/interactive/interactive-selectors.js": "5f0997adf81a0456969a27e3e29b25d4dd8576eeeb044c91bce4c5df07eff426",
|
|
2293
2293
|
"packages/agent-forge/dist/modes/interactive/model-catalog-refresh.js": "482cf2c064fcb33822a5d25c66ae782bc81cb2e1381f2140e90733d2c8abfc61",
|
|
2294
2294
|
"packages/agent-forge/dist/modes/interactive/model-search.js": "5fbe3c08cc30c21fe38bfb3a86bb790b020b8c4a2fec8e14e57419560f790a92",
|
|
@@ -2442,7 +2442,7 @@
|
|
|
2442
2442
|
"packages/agent-forge/src/config.ts": "449583f59742dea75d03642f9d1b9defec2945b19d822854df984edd0f5872f0",
|
|
2443
2443
|
"packages/agent-forge/src/core/agent-capability-contract.ts": "c74c49b7233cbc64aaaf80f1302e344225d8c53e840b117a3fbfaf038ec88bfd",
|
|
2444
2444
|
"packages/agent-forge/src/core/agent-session-bash.ts": "4e094f86a7ed9d1afebbbf946858a3196d8c4e3ede8e1cd841e621a8a0ff1d4b",
|
|
2445
|
-
"packages/agent-forge/src/core/agent-session-compaction.ts": "
|
|
2445
|
+
"packages/agent-forge/src/core/agent-session-compaction.ts": "4e9f0b1d68d25a5fa6ab96eb16b2e708672ffa64e57d7e63c4e718b247b96683",
|
|
2446
2446
|
"packages/agent-forge/src/core/agent-session-context.ts": "1270a7dba505079f890c2c2e286679812b388500ce6c8972753e6fccfe706201",
|
|
2447
2447
|
"packages/agent-forge/src/core/agent-session-extensions.ts": "d4f96cd48bd3210ea6315f013fa3ea24a3fb8902fe9727f88b8dea511cf6c9d9",
|
|
2448
2448
|
"packages/agent-forge/src/core/agent-session-internal.ts": "acd8e48aa4a2f281abe30c02335d5fce02772d3332b501bdaa6cf4fa510dd4e8",
|
|
@@ -2457,7 +2457,7 @@
|
|
|
2457
2457
|
"packages/agent-forge/src/core/agent-session-services.ts": "d7ff11e50353509ff4ce55039baf3733279400fa06272fcaf028bfec9665deb4",
|
|
2458
2458
|
"packages/agent-forge/src/core/agent-session-store.ts": "9bc26c7328004b0742347572ad54479bda113b54516d8de7fc1ad73963d2c651",
|
|
2459
2459
|
"packages/agent-forge/src/core/agent-session-tools.ts": "b09a156b085a12ca59f43df6ba05b7375442304614ced9fa9e1214d8579b50de",
|
|
2460
|
-
"packages/agent-forge/src/core/agent-session.ts": "
|
|
2460
|
+
"packages/agent-forge/src/core/agent-session.ts": "9cec22139bef04bee999f96314a7dcb0331674385d57e15714e524e45ba34860",
|
|
2461
2461
|
"packages/agent-forge/src/core/auth-guidance.ts": "8fbee7c272953bf881f22e9ce4b163bb0df9c091f63ee823dbfe32186991efe0",
|
|
2462
2462
|
"packages/agent-forge/src/core/auth-storage.ts": "c3b53cd49af9e98bbec1c3ab15fedd065cabda94f0cd35673742f5a2b8bb057c",
|
|
2463
2463
|
"packages/agent-forge/src/core/bash-executor.ts": "c905c5014c83b4429b3e722ba8d940fef70e15eef8f1747ce90985c6a9085e0c",
|
|
@@ -2646,7 +2646,7 @@
|
|
|
2646
2646
|
"packages/agent-forge/src/modes/interactive/interactive-dialog-ui.ts": "01cebe30b41b73a3dc88c3cd60c2e91f509a20d3f1f7f1648e9697372040621a",
|
|
2647
2647
|
"packages/agent-forge/src/modes/interactive/interactive-format.ts": "318c755690bd079a1c03b6f0f3b38fdec1906d93885ee74724201dee6f483c40",
|
|
2648
2648
|
"packages/agent-forge/src/modes/interactive/interactive-helpers.ts": "f19ae5bb8a6fb7ae07a4d4421bdeb48a5afa3828344a36ca3539ce2a96ec933e",
|
|
2649
|
-
"packages/agent-forge/src/modes/interactive/interactive-mode.ts": "
|
|
2649
|
+
"packages/agent-forge/src/modes/interactive/interactive-mode.ts": "569b3818161c84331cb3994462e0fa3fabeaddc7cb70dfa2d610e61ac2545d00",
|
|
2650
2650
|
"packages/agent-forge/src/modes/interactive/interactive-selectors.ts": "e415cde76abfe2e3016ace232b7ba533bc6e52fbe07d8612c74feb4e31757f36",
|
|
2651
2651
|
"packages/agent-forge/src/modes/interactive/model-catalog-refresh.ts": "774196269ba7b140115c803c0aebde814099b5e6fe2dea82ec3eaabd7cf1d5cb",
|
|
2652
2652
|
"packages/agent-forge/src/modes/interactive/model-search.ts": "9be620174c0f25516b0c537dcd4ef9be7c9c9a145e6489e186cc6c4787b25412",
|
|
@@ -980,7 +980,7 @@ ${getProviderLoginHelp()}
|
|
|
980
980
|
|
|
981
981
|
Then use /model to select a model.`}function formatNoApiKeyFoundMessage(provider){return`No API key found for ${provider===UNKNOWN_PROVIDER?"the selected model":provider}.
|
|
982
982
|
|
|
983
|
-
${getProviderLoginHelp()}`}function withoutDeletedHeaders(headers){return headers?Object.fromEntries(Object.entries(headers).filter(entry=>entry[1]!==null)):void 0}function estimateMessagesTokens(messages){let tokens=0;for(let message of messages)tokens+=estimateTokens2(message);return tokens}async function getRequiredRequestAuth(session,model){let result;try{result=await session._modelRuntime.getAuth(model)}catch(error2){let cause=error2 instanceof Error?error2.cause:void 0;throw cause instanceof Error&&cause.message==="authHeader requires a resolved API key"?new Error(formatNoApiKeyFoundMessage(model.provider)):error2}if(result&&(result.auth.apiKey||result.auth.headers))return{model:result.auth.baseUrl?{...model,baseUrl:result.auth.baseUrl}:model,apiKey:result.auth.apiKey,headers:withoutDeletedHeaders(result.auth.headers),env:result.env};throw session._modelRuntime.isUsingOAuth(model.provider)?new Error(`Authentication failed for "${model.provider}". Credentials may have expired or network is unavailable. Run '/login ${model.provider}' to re-authenticate.`):new Error(formatNoApiKeyFoundMessage(model.provider))}async function getSummarizationRequestAuth(session,model){if(session.agent.streamFunction===streamSimple)return getRequiredRequestAuth(session,model);try{let result=await session._modelRuntime.getAuth(model);return result?{model:result.auth.baseUrl?{...model,baseUrl:result.auth.baseUrl}:model,apiKey:result.auth.apiKey,headers:withoutDeletedHeaders(result.auth.headers),env:result.env}:{model}}catch{return{model}}}function summaryModelFacts(model){return{id:model.id,contextWindow:model.contextWindow,maxTokens:model.maxTokens,reasoning:model.reasoning}}function createSummaryModelInvocationV1(session,auth,retry,callbacks,options={}){return{invoke:async(input,signal)=>{let maxTokens=input.maxTokens===void 0||auth.model.maxTokens<=0?input.maxTokens:Math.min(input.maxTokens,auth.model.maxTokens),requestOptions={...maxTokens===void 0?{}:{maxTokens},signal,apiKey:auth.apiKey,headers:auth.headers,env:auth.env,cacheRetention:"none",sessionId:options.routingSessionId??uuidv7()};auth.model.reasoning&&input.thinkingLevel&&input.thinkingLevel!=="off"&&(requestOptions.reasoning=input.thinkingLevel);let context={systemPrompt:input.systemPrompt,messages:[{role:"user",content:[{type:"text",text:input.prompt}],timestamp:Date.now()}]},produce=async()=>{let streamFn=session.agent.streamFunction;return streamFn?(await streamFn(auth.model,context,requestOptions)).result():completeSimple(auth.model,context,requestOptions)},response2;try{response2=await retryAssistantCall(produce,retry,requestOptions.signal,callbacks)}catch(error2){return error2 instanceof Error&&error2.name==="AbortError"?{version:1,status:"aborted"}:{version:1,status:"failed",error:{code:SUMMARY_MODEL_INVOCATION_ERROR_CODES.transportError,message:error2 instanceof Error?error2.message:String(error2)}}}return response2.stopReason==="aborted"?{version:1,status:"aborted"}:response2.stopReason==="error"?{version:1,status:"failed",error:{code:SUMMARY_MODEL_INVOCATION_ERROR_CODES.providerError,message:response2.errorMessage||"Unknown error"}}:response2.stopReason==="length"?{version:1,status:"failed",error:{code:SUMMARY_MODEL_INVOCATION_ERROR_CODES.lengthCap,message:"generation hit the token cap and the summary is incomplete"}}:response2.content.some(block=>block.type==="toolCall")?{version:1,status:"failed",error:{code:SUMMARY_MODEL_INVOCATION_ERROR_CODES.toolCall,message:"attempted to call a tool"}}:{version:1,status:"completed",text:contentText(response2.content),usage:response2.usage}}}}async function compactBeforeNextAssistantResponse(session,context,signal){let model=session.model,settings2=session.settingsManager.getCompactionSettings();if(!model||model.contextWindow<=0)return context;let contextTokens=estimateContextTokens2(context.messages).tokens,decision=await decideCompaction(session,{reason:"threshold",contextOverflow:!1,recoverableLength:!1,contextUsage:{contextTokens,contextWindow:model.contextWindow,reserveTokens:settings2.reserveTokens},canContinue:!1,signal:signal??session._policyDecisionAbortController?.signal});return await dispatchCompactionDecisionLifecycle(session,{reason:"threshold",compact:decision.compact,willRetry:!1,contextTokens,contextWindow:model.contextWindow,reserveTokens:settings2.reserveTokens,...decision.failureMessage===void 0?{}:{failureMessage:decision.failureMessage}}),decision.compact?(await session._runAutoCompaction("threshold",!1),{...context,messages:session.agent.state.messages.slice()}):context}function executionFacts(session,phase,operationId,revision){let inputRevision=detachedSessionSnapshot(revision??session.sessionManager.getRevision());return Object.freeze({version:1,operationId:operationId??`${phase}:${inputRevision.sessionId}:${inputRevision.sequence}:${inputRevision.leafId??"root"}`,sessionId:session.sessionId,inputRevision,phase})}async function runCompactionSummary(session,preparation,auth,customInstructions,signal,reason,execution){let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");let result=await runtime.summarizeCompaction(session._compactionPolicyName,{preparation,model:summaryModelFacts(auth.model),invocation:createSummaryModelInvocationV1(session,auth,summarizationRetryPolicy(session,execution.operationId,execution.inputRevision,signal),summarizationRetryCallbacks(session,{source:"compaction",reason}),{routingSessionId:session.sessionId}),customInstructions,signal,reason,thinkingLevel:session.thinkingLevel,sessionId:session.sessionId,context:{version:1,sessionId:session.sessionId,phase:"compaction"},execution});return{...result,usage:result.usage}}async function decideCompaction(session,input){let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");return session._compactionPolicyName===DEFAULT_COMPACTION_POLICY_NAME&&!runtime.hasCompactionPolicy(session._compactionPolicyName)?(session._hostLogger?.warn("compaction","no compaction policy registered; skipping automatic compaction",{fields:{policyName:session._compactionPolicyName,reason:input.reason}}),{compact:!1,retry:!1}):runtime.decideCompaction(session._compactionPolicyName,{enabled:session.settingsManager.getCompactionSettings().enabled,recoveryAttempted:session._overflowRecoveryAttempted,...input,context:{version:1,sessionId:session.sessionId,phase:"compaction"},execution:input.execution??executionFacts(session,"compaction"),signal:input.signal})}async function prepareCompaction3(session,pathEntries,settings2,execution,signal){let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");let preparation=await runtime.prepareCompaction(session._compactionPolicyName,{entries:pathEntries,settings:settings2,context:{version:1,sessionId:session.sessionId,phase:"compaction"},execution:execution??executionFacts(session,"compaction"),signal});if(preparation===void 0)return;let value=preparation;if(!preparation||typeof preparation!="object"||typeof value.firstKeptEntryId!="string"||!Array.isArray(value.messagesToSummarize)||!Array.isArray(value.turnPrefixMessages)||typeof value.isSplitTurn!="boolean"||!Number.isFinite(value.tokensBefore)||typeof value.fileOps!="object"||typeof value.settings!="object")throw new Error(`Compaction policy returned an invalid preparation: ${session._compactionPolicyName}`);return preparation}function captureCompactionCommitBoundary(session,reason){let pathEntries=session.sessionManager.getBranch(),expectedRevision=session.sessionManager.getRevision();return{pathEntries,expectedRevision,operationId:`compaction:${reason}:${expectedRevision.sessionId}:${expectedRevision.sequence}:${expectedRevision.leafId??"root"}`}}function enqueueCompaction(session,operation){let previous=session._compactionQueue,release;session._compactionQueue=new Promise(resolve25=>{release=resolve25});let queued=previous.then(()=>{if(session._reloadInProgress)throw new Error("Session reload in progress; compaction was not started");return operation()}).finally(release);return session._activeCompactionPromise=queued,queued.then(()=>{session._activeCompactionPromise===queued&&(session._activeCompactionPromise=void 0)},()=>{session._activeCompactionPromise===queued&&(session._activeCompactionPromise=void 0)}),queued}function commitCompaction(session,input){let commit=session.sessionManager.commitCompaction({version:1,operationId:input.operationId,expectedRevision:input.expectedRevision,summary:input.summary,firstKeptEntryId:input.firstKeptEntryId,tokensBefore:input.tokensBefore,details:input.details,fromHook:!1,usage:input.usage});if(commit.status==="revision_conflict")throw new Error(`Compaction commit revision conflict: expected ${input.expectedRevision.sequence}/${input.expectedRevision.leafId??"root"}, current ${commit.currentRevision.sequence}/${commit.currentRevision.leafId??"root"}`);let entry=session.sessionManager.getEntry(commit.entryId);if(entry?.type!=="compaction"||entry.operationId!==input.operationId)throw new Error(`Compaction commit entry is unavailable: ${commit.entryId}`);return{entry,status:commit.status,revision:commit.revision}}async function dispatchCompactionCommitLifecycle(session,reason,commit){try{let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");let entry=commit.entry,data={version:1,status:commit.status,entryId:entry.id,operationId:entry.operationId??"",revision:commit.revision,reason,summary:entry.summary,firstKeptEntryId:entry.firstKeptEntryId,tokensBefore:entry.tokensBefore,fromHook:entry.fromHook===!0,...entry.usage===void 0?{}:{usage:entry.usage},...entry.details===void 0?{}:{details:entry.details}},delivery=await runtime.dispatchLifecycle({type:SESSION_COMPACTION_COMMIT_EVENT_ID,version:SESSION_COMPACTION_COMMIT_EVENT_VERSION,phase:"committed",data,operationId:entry.operationId,source:"agent-session"});for(let failure2 of delivery.report.failures)session._observeLifecycleDeliveryError(failure2.error,failure2.pluginId,`${SESSION_COMPACTION_COMMIT_EVENT_ID}@${SESSION_COMPACTION_COMMIT_EVENT_VERSION}/${failure2.kind}`)}catch(error2){let report=error2.report;if(report?.failures)for(let failure2 of report.failures)session._observeLifecycleDeliveryError(failure2.error,failure2.pluginId,`${SESSION_COMPACTION_COMMIT_EVENT_ID}@${SESSION_COMPACTION_COMMIT_EVENT_VERSION}/${failure2.kind}`);else session._observeLifecycleDeliveryError(error2,"<capability-lifecycle>",`${SESSION_COMPACTION_COMMIT_EVENT_ID}@${SESSION_COMPACTION_COMMIT_EVENT_VERSION}`)}}async function decideOverflow(session,message,execution,signal){let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");return runtime.decideOverflow(session._overflowPolicyName,{message,contextWindow:session.model?.contextWindow,desiredMaxOutput:session.model?.maxTokens??0,context:{version:1,sessionId:session.sessionId,phase:"overflow"},execution:execution??executionFacts(session,"overflow"),signal})}function clearManualCompactionState(session){session._compactionAbortController=void 0,session._resolveIdleWaitIfIdle()}async function compactInternal(session,customInstructions){if(await session._abortInternal(),session._reloadInProgress)return{cancelled:!0,aborted:!0};session._compactionAbortController=new AbortController,session._emit({type:"compaction_start",reason:"manual"});try{if(!session.model)throw new Error(formatNoModelSelectedMessage());let auth=await getSummarizationRequestAuth(session,session.model),{pathEntries,expectedRevision,operationId}=captureCompactionCommitBoundary(session,"manual"),settings2=session.settingsManager.getCompactionSettings(),execution=executionFacts(session,"compaction",operationId),preparation=await prepareCompaction3(session,pathEntries,settings2,execution,session._compactionAbortController.signal);if(!preparation)throw pathEntries[pathEntries.length-1]?.type==="compaction"?new Error("Already compacted"):new Error("Nothing to compact (session too small)");let{summary,firstKeptEntryId,tokensBefore,usage,details}=await runCompactionSummary(session,preparation,auth,customInstructions,session._compactionAbortController.signal,"manual",execution);if(session._compactionAbortController.signal.aborted||session._reloadInProgress)throw new SessionCancelledError("signal");let compactionCommit=commitCompaction(session,{expectedRevision,operationId,summary,firstKeptEntryId,tokensBefore,details,usage});await dispatchCompactionCommitLifecycle(session,"manual",compactionCommit);let sessionContext=session.sessionManager.buildSessionContext();await session._applyContextTransition(sessionContext.messages,"compaction");let estimatedTokensAfter=estimateMessagesTokens(session.agent.state.messages),compactionResult={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return clearManualCompactionState(session),session._emit({type:"compaction_end",reason:"manual",result:compactionResult,aborted:!1,willRetry:!1}),compactionResult}catch(error2){if(error2 instanceof SessionCancelledError||error2 instanceof Error&&error2.name==="AbortError")return clearManualCompactionState(session),session._emit({type:"compaction_end",reason:"manual",result:void 0,aborted:!0,willRetry:!1}),{cancelled:!0,aborted:!0};let errorMessage2=`Compaction failed: ${error2 instanceof Error?error2.message:String(error2)}`;throw clearManualCompactionState(session),session._emit({type:"compaction_end",reason:"manual",result:void 0,aborted:!1,willRetry:!1,errorMessage:errorMessage2}),session._hostLogger?.error("compaction","compaction failed",{fields:{reason:"manual"},cause:error2}),await dispatchCompactionFailedLifecycle(session,{reason:"manual",errorMessage:errorMessage2}),error2}finally{clearManualCompactionState(session)}}async function checkCompaction(session,assistantMessage,skipAbortedCheck=!0,signal){if(signal?.aborted)return!1;let settings2=session.settingsManager.getCompactionSettings();if(skipAbortedCheck&&assistantMessage.stopReason==="aborted")return!1;let contextWindow=session.model?.contextWindow??0,sameModel=session.model!==void 0&&assistantMessage.provider===session.model.provider&&assistantMessage.model===session.model.id,compactionEntry=getLatestCompactionEntry(session.sessionManager.getBranch());if(compactionEntry!==null&&assistantMessage.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1;let overflow=sameModel?await decideOverflow(session,assistantMessage,void 0,signal):{contextOverflow:!1,recoverableLength:!1},{contextOverflow,recoverableLength}=overflow;if(contextOverflow||recoverableLength){let decision2=await decideCompaction(session,{reason:"overflow",contextOverflow,recoverableLength,canContinue:assistantMessage.stopReason!=="stop",signal});if(await dispatchCompactionDecisionLifecycle(session,{reason:"overflow",compact:decision2.compact,willRetry:decision2.retry===!0,...decision2.failureMessage===void 0?{}:{failureMessage:decision2.failureMessage}}),!decision2.compact){if(decision2.failureMessage){let errorMessage2=decision2.failureMessage;session._emit({type:"compaction_end",reason:"overflow",result:void 0,aborted:!1,willRetry:!1,errorMessage:errorMessage2}),session._hostLogger?.error("compaction","compaction failed",{fields:{reason:"overflow"},cause:errorMessage2}),await dispatchCompactionFailedLifecycle(session,{reason:"overflow",errorMessage:errorMessage2})}return!1}let willRetry=decision2.retry===!0;return willRetry&&(session._overflowRecoveryAttempted=!0),await session._runAutoCompaction("overflow",willRetry)}let contextTokens,directContextTokens=assistantMessage.usage?calculateContextTokens2(assistantMessage.usage):0;if(assistantMessage.stopReason==="error"||directContextTokens===0){let messages=session.agent.state.messages,estimate=estimateContextTokens2(messages);if(estimate.lastUsageIndex!==null){let usageMsg=messages[estimate.lastUsageIndex];if(compactionEntry&&usageMsg.role==="assistant"&&usageMsg.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1}contextTokens=estimate.tokens}else contextTokens=directContextTokens;let decision=await decideCompaction(session,{reason:"threshold",contextOverflow:!1,recoverableLength:!1,contextUsage:{contextTokens,contextWindow,reserveTokens:settings2.reserveTokens},canContinue:!1,branchEntries:session.sessionManager.getBranch(),keepRecentTokens:settings2.keepRecentTokens,signal});if(await dispatchCompactionDecisionLifecycle(session,{reason:"threshold",compact:decision.compact,willRetry:decision.retry===!0,contextTokens,contextWindow,reserveTokens:settings2.reserveTokens,...decision.failureMessage===void 0?{}:{failureMessage:decision.failureMessage}}),decision.relief!==void 0&&!decision.compact){session.sessionManager.appendCustomEntry(decision.relief.customType,decision.relief.data);let sessionContext=session.sessionManager.buildSessionContext();return await session._applyContextTransition(sessionContext.messages,"compaction"),session._hostLogger?.info("compaction","policy relief applied",{fields:{customType:decision.relief.customType}}),session.agent.hasQueuedMessages()}return decision.compact?session._runAutoCompaction("threshold",decision.retry===!0):!1}async function runAutoCompaction(session,reason,willRetry){return session._reloadInProgress?!1:enqueueCompaction(session,()=>runAutoCompactionInternal(session,reason,willRetry))}async function runAutoCompactionInternal(session,reason,willRetry){session._autoCompactionAbortController=new AbortController;let autoCompactionSignal=session._autoCompactionAbortController.signal;try{try{if(willRetry){let messages=session.agent.state.messages;messages.length>0&&messages[messages.length-1].role==="assistant"&&await session._applyContextTransition(messages.slice(0,-1),"overflow_recovery")}if(autoCompactionSignal.aborted||session._reloadInProgress)return!1}catch(error2){throw session._autoCompactionAbortController=void 0,error2}let settings2=session.settingsManager.getCompactionSettings(),started=!1;try{if(!session.model)return!1;let auth=await getSummarizationRequestAuth(session,session.model),{pathEntries,expectedRevision,operationId}=captureCompactionCommitBoundary(session,reason),execution=executionFacts(session,"compaction",operationId),preparation=await prepareCompaction3(session,pathEntries,settings2,execution,autoCompactionSignal);if(!preparation)return!1;session._emit({type:"compaction_start",reason}),started=!0;let{summary,firstKeptEntryId,tokensBefore,usage,details}=await runCompactionSummary(session,preparation,auth,void 0,autoCompactionSignal,reason,execution);if(autoCompactionSignal.aborted||session._reloadInProgress)return session._emit({type:"compaction_end",reason,result:void 0,aborted:!0,willRetry:!1}),!1;let compactionCommit=commitCompaction(session,{expectedRevision,operationId,summary,firstKeptEntryId,tokensBefore,details,usage});await dispatchCompactionCommitLifecycle(session,reason,compactionCommit);let sessionContext=session.sessionManager.buildSessionContext();await session._applyContextTransition(sessionContext.messages,"compaction");let estimatedTokensAfter=estimateMessagesTokens(session.agent.state.messages),result={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};if(session._emit({type:"compaction_end",reason,result,aborted:!1,willRetry}),willRetry){let messages=session.agent.state.messages,lastMsg=messages[messages.length-1];return lastMsg?.role==="assistant"&&(lastMsg.stopReason==="error"||lastMsg.stopReason==="length")&&await session._applyContextTransition(messages.slice(0,-1),"overflow_recovery"),!0}return session.agent.hasQueuedMessages()}catch(error2){let errorMessage2=error2 instanceof Error?error2.message:"compaction failed";if(started){let formattedErrorMessage=reason==="overflow"?`Context overflow recovery failed: ${errorMessage2}`:`Auto-compaction failed: ${errorMessage2}`;session._emit({type:"compaction_end",reason,result:void 0,aborted:!1,willRetry:!1,errorMessage:formattedErrorMessage}),session._hostLogger?.error("compaction","compaction failed",{fields:{reason},cause:error2}),await dispatchCompactionFailedLifecycle(session,{reason,errorMessage:formattedErrorMessage})}return!1}}finally{session._autoCompactionAbortController=void 0,session._resolveIdleWaitIfIdle()}}function summarizationRetryCallbacks(session,source){let attempts=[];return{onRetryScheduled:(attempt2,_maxAttempts,delayMs,errorMessage2)=>{attempts.push({attempt:attempt2,at:Date.now(),ok:!1,failure:errorMessage2,waitedMs:delayMs}),session._emit({type:"summarization_retry_scheduled",attempt:attempt2,maxAttempts:_maxAttempts,delayMs,errorMessage:errorMessage2})},onRetryAttemptStart:()=>{session._emit({type:"summarization_retry_attempt_start",...source})},onRetryFinished:(success,attempt2,finalError)=>{attempts.push(success?{attempt:attempt2+1,at:Date.now(),ok:!0,waitedMs:0}:{attempt:attempt2+1,at:Date.now(),ok:!1,waitedMs:0,...finalError===void 0?{}:{failure:finalError}}),session._emit({type:"summarization_retry_finished",source,attempts})}}}function summarizationRetryPolicy(session,operationId,inputRevision,signal){let settings2=session.settingsManager.getRetrySettings(),runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");let execution=executionFacts(session,"retry",operationId?`${operationId}:retry`:void 0,inputRevision);return{...settings2,classify:message=>runtime.classifyRetry(session._retryPolicyName,{message,signal,context:{version:1,sessionId:session.sessionId,phase:"retry"},execution}),decide:({message,retryable,attempt:attempt2,maxAttempts,baseDelayMs})=>runtime.decideRetry(session._retryPolicyName,{retryable,enabled:settings2.enabled,attempt:attempt2,maxAttempts,baseDelayMs,errorMessage:message.errorMessage,signal,context:{version:1,sessionId:session.sessionId,phase:"retry"},execution})}}async function navigateTree(session,targetId,options={}){if(session.isStreaming)throw new Error("Wait for the current response to finish before navigating the session tree.");if(session._compactionAbortController!==void 0||session._autoCompactionAbortController!==void 0)throw new Error("Wait for the current compaction or tree navigation to finish before navigating the session tree.");let oldLeafId=session.sessionManager.getLeafId();if(targetId===oldLeafId)return{cancelled:!1};if(options.summarize&&!session.model)throw new Error("No model available for summarization");let targetEntry=session.sessionManager.getEntry(targetId);if(!targetEntry)throw new Error(`Entry ${targetId} not found`);let{entries:entriesToSummarize}=collectEntriesForBranchSummary2(session.sessionManager,oldLeafId,targetId),customInstructions=options.customInstructions,replaceInstructions=options.replaceInstructions,label=options.label;if(session._reloadInProgress)throw new Error("Session reload in progress; tree navigation is unavailable");if(session._branchSummaryAbortController)throw new Error("Branch navigation is already in progress");session._branchSummaryAbortController=new AbortController;let branchSummaryPromise=new Promise(resolve25=>{session._resolveBranchSummaryPromise=resolve25});session._branchSummaryPromise=branchSummaryPromise;try{let summaryText,summaryDetails,summaryUsage;if(options.summarize&&entriesToSummarize.length>0){let model=session.model,auth=await getSummarizationRequestAuth(session,model),branchSummarySettings=session.settingsManager.getBranchSummarySettings(),runtime=session._capabilityRuntime;if(!runtime||!runtime.hasBranchSummaryPolicy(session._branchSummaryPolicyName))throw new Error(`Branch summary policy is not registered: ${session._branchSummaryPolicyName}`);let execution=executionFacts(session,"branch_summary",`branch_summary:${session.sessionId}:${oldLeafId??"root"}:${targetId}`),result=await runtime.summarizeBranch(session._branchSummaryPolicyName,{entries:entriesToSummarize,model:summaryModelFacts(auth.model),invocation:createSummaryModelInvocationV1(session,auth,summarizationRetryPolicy(session,execution.operationId,execution.inputRevision,session._branchSummaryAbortController.signal),summarizationRetryCallbacks(session,{source:"branchSummary"})),signal:session._branchSummaryAbortController.signal,customInstructions,replaceInstructions,reserveTokens:branchSummarySettings.reserveTokens,context:{version:1,sessionId:session.sessionId,phase:"branch_summary"},execution});if(result.aborted)return{cancelled:!0,aborted:!0};if(result.error)throw new Error(result.error);summaryText=result.summary,summaryUsage=result.usage,summaryDetails={readFiles:result.readFiles||[],modifiedFiles:result.modifiedFiles||[]}}if(session._branchSummaryAbortController.signal.aborted||session._reloadInProgress)return{cancelled:!0,aborted:!0};let newLeafId,editorText;targetEntry.type==="message"&&targetEntry.message.role==="user"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.message.content,"")):targetEntry.type==="custom_message"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.content,"")):newLeafId=targetId;let summaryEntry;if(summaryText){let summaryId=session.sessionManager.branchWithSummary(newLeafId,summaryText,summaryDetails,!1,summaryUsage);summaryEntry=session.sessionManager.getEntry(summaryId),label&&session.sessionManager.appendLabelChange(summaryId,label)}else newLeafId===null?session.sessionManager.resetLeaf():session.sessionManager.branch(newLeafId);label&&!summaryText&&session.sessionManager.appendLabelChange(targetId,label);let sessionContext=session.sessionManager.buildSessionContext();return await session._applyContextTransition(sessionContext.messages,"tree"),{editorText,cancelled:!1,summaryEntry}}finally{session._branchSummaryAbortController=void 0,session._resolveIdleWaitIfIdle(),session._resolveBranchSummaryPromise?.(),session._resolveBranchSummaryPromise=void 0,session._branchSummaryPromise===branchSummaryPromise&&(session._branchSummaryPromise=void 0)}}function requireContextStrategy(session){let name=session._contextStrategyName;if(!name)throw new Error("Context strategy is not configured");let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");if(!runtime.hasContextStrategy(name))throw new Error(`Configured context strategy is not registered: ${name}`);return{runtime,name}}function requireIdleContextOperation(session,operation){if(!session.isIdle)throw new Error(`Cannot ${operation} while the session is running`)}function beginContextTransitionFence(session){session._contextEpoch+=1,session._contextTransitionAbortController.abort("context runtime replaced"),session._contextTransitionAbortController=new AbortController}function isContextTransitionCurrent(session,epoch,allowReload){return!session.isDisposed&&epoch===session._contextEpoch&&(allowReload||!session._reloadInProgress)}function assertContextTransitionCurrent(session,epoch,allowReload){if(!session._isContextTransitionCurrent(epoch,allowReload))throw new Error(session.isDisposed?"Session is disposed; context transition was cancelled":session._reloadInProgress?"Session reload in progress; context transition was cancelled":"Context transition was superseded")}function enqueueContextTransition(session,operation,options){let allowReload=options?.allowReload??!1;if(session.isDisposed)return Promise.reject(new Error("Session is disposed; context transition is unavailable"));if(session._reloadInProgress&&!allowReload)return Promise.reject(new Error("Session reload in progress; context transition is unavailable"));let epoch=session._contextEpoch,fenceSignal=session._contextTransitionAbortController.signal,signal=options?.signal?AbortSignal.any([fenceSignal,options.signal]):fenceSignal,queued=(session._activeContextTransition?.catch(()=>{})??Promise.resolve()).then(()=>(session._assertContextTransitionCurrent(epoch,allowReload),operation(epoch,signal)));return session._activeContextTransition=queued,queued.then(()=>{session._activeContextTransition===queued&&(session._activeContextTransition=void 0)},()=>{session._activeContextTransition===queued&&(session._activeContextTransition=void 0)}),queued}function copyContextMessages(value,strategyName,direction){if(!Array.isArray(value)||value.some(message=>typeof message!="object"||message===null||!("role"in message)||typeof message.role!="string"))throw new Error(direction==="result"?`Context strategy must return an AgentMessage array: ${strategyName}`:`Context transition requires an AgentMessage array: ${strategyName}`);try{return structuredClone(value)}catch(error2){throw new Error(direction==="result"?`Context strategy must return structured-cloneable AgentMessage values: ${strategyName}`:`Context transition requires structured-cloneable AgentMessage values: ${strategyName}`,{cause:error2})}}function applyContextTransition(session,messages,reason="session_replace",signal,options){return session._enqueueContextTransition(async(epoch,transitionSignal)=>{let name=session._contextStrategyName,runtime=session._capabilityRuntime;if(name){if(!runtime)throw new Error("Capability runtime is not available");if(!runtime.hasContextStrategy(name))throw new Error(`Configured context strategy is not registered: ${name}`);let replaced=await runtime.replaceContext(name,session._copyContextMessages(messages,name,"input"),{signal:transitionSignal,reason,sessionId:session.sessionId});session._assertContextTransitionCurrent(epoch,options?.allowReload??!1);let committed=session._copyContextMessages(replaced,name,"result");return session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),session.agent.state.messages=committed,session._contextRevision+=1,session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),await session._dispatchContextReplacedLifecycle(reason,name),committed}return session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),session.agent.state.messages=messages,session._contextRevision+=1,session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),await session._dispatchContextReplacedLifecycle(reason),messages},{signal,allowReload:options?.allowReload})}function restoreContextTransition(session,snapshot2,reason,options){return session._enqueueContextTransition(async(epoch,signal)=>{let{runtime,name}=session._requireContextStrategy(),restored=await runtime.restoreContext(name,snapshot2,{signal,reason,sessionId:session.sessionId});session._assertContextTransitionCurrent(epoch,options?.allowReload??!1);let committed=session._copyContextMessages(restored,name,"result");return session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),session.agent.state.messages=committed,session._contextRevision+=1,session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),await session._dispatchContextReplacedLifecycle(reason,name),committed},{allowReload:options?.allowReload})}async function snapshotContext(session){session._requireIdleContextOperation("snapshot context");let{runtime,name}=session._requireContextStrategy();return runtime.snapshotContext(name,session._copyContextMessages(session.agent.state.messages,name,"input"),{reason:"reload",sessionId:session.sessionId})}async function restoreContext(session,snapshot2){return session._requireIdleContextOperation("restore context"),session._restoreContextTransition(snapshot2,"session_replace")}async function replaceContext(session,context){session._requireIdleContextOperation("replace context");let{name}=session._requireContextStrategy();return session._applyContextTransition(session._copyContextMessages(context,name,"input"),"session_replace")}import{basename as basename7,dirname as dirname17}from"node:path";async function extendResourcesFromExtensions(session,reason){dispatchResourcesDiscoverV1Lifecycle(session,{cwd:session._cwd,reason});let contributed=await dispatchResourcesDiscoverV2Lifecycle(session,reason),{skillPaths,promptPaths,themePaths}=contributed;if(skillPaths.length===0&&promptPaths.length===0&&themePaths.length===0)return;let extensionPaths={skillPaths:session.buildExtensionResourcePaths(skillPaths),promptPaths:session.buildExtensionResourcePaths(promptPaths),themePaths:session.buildExtensionResourcePaths(themePaths)};session._resourceLoader.extendResources(extensionPaths),await session._refreshBootstrapSkills(),session._baseSystemPrompt=session._rebuildSystemPrompt(session.getActiveToolNames()),session.agent.state.systemPrompt=session._baseSystemPrompt}function buildExtensionResourcePaths(session,entries){return entries.map(entry=>{let source=session.getExtensionSourceLabel(entry.extensionPath),baseDir=entry.extensionPath.startsWith("<")?void 0:dirname17(entry.extensionPath);return{path:entry.path,metadata:{source,scope:"temporary",origin:"top-level",baseDir}}})}function getExtensionSourceLabel(extensionPath){return extensionPath.startsWith("<")?`extension:${extensionPath.replace(/[<>]/g,"")}`:`extension:${basename7(extensionPath).replace(/\.(ts|js)$/,"")}`}function collectCommandInfos(session){let templates=session.promptTemplates.map(template=>({name:template.name,description:template.description,source:"prompt",sourceInfo:template.sourceInfo})),skills=session._getAvailableSkills().map(skill=>({name:`skill:${skill.name}`,description:skill.description,source:"skill",sourceInfo:skill.sourceInfo}));return[...templates,...skills]}function wireDefaultLoop(session){let previousPrepareNextTurnWithContext=session.agent.prepareNextTurnWithContext??(session.agent.prepareNextTurn?async(_turn,signal)=>await session.agent.prepareNextTurn?.(signal):void 0);session._initialPrepareNextTurn=previousPrepareNextTurnWithContext;let previousTransform=session.agent.transformContext,transformHead=previousTransform?async(messages,signal)=>await previousTransform(messages,signal):void 0;session.agent.beforeToolCall=async({toolCall,args},signal)=>{let chain=session._capabilityRuntime?.getLoopHookChain("beforeToolCall")??[],currentArgs=args,replaced=!1;for(let link of chain){let result=await link({toolCallId:toolCall.id,toolName:toolCall.name,args:currentArgs,signal});if(result){if(result.block){let reason=typeof result.reason=="string"&&result.reason.trim()!==""?result.reason:void 0;return await dispatchToolGateBlockedLifecycle(session,toolCall.id,toolCall.name,reason),result}"args"in result&&(currentArgs=result.args,replaced=!0)}}return replaced?{args:currentArgs}:void 0},session.agent.afterToolCall=async({toolCall,args,result,isError},signal)=>{let chain=session._capabilityRuntime?.getLoopHookChain("afterToolCall")??[],current=result,override;for(let link of chain){let linkResult=await link({toolCallId:toolCall.id,toolName:toolCall.name,args,result:current,isError,signal});linkResult!==void 0&&(current=linkResult,override=linkResult)}return override},session.agent.transformContext=async(messages,signal)=>{let current=messages;if(transformHead){let transformed=await transformHead(current,signal);transformed!==void 0&&(current=transformed)}let chain=session._capabilityRuntime?.getLoopHookChain("transformContext")??[];for(let link of chain){let transformed=await link(current,signal);transformed!==void 0&&(current=transformed)}return current},session.agent.prepareNextTurnWithContext=async(turn,signal)=>{let chain=session._capabilityRuntime?.getLoopHookChain("prepareNextTurn")??[],current=turn;for(let link of chain){let revised=await link(current,signal);revised!==void 0&&(current=revised)}return current};let previousShouldStopAfterTurn=session.agent.shouldStopAfterTurn;session.agent.shouldStopAfterTurn=async(context,signal)=>{if(previousShouldStopAfterTurn&&await previousShouldStopAfterTurn(context,signal))return!0;let chain=session._capabilityRuntime?.getLoopHookChain("shouldStopAfterTurn")??[];for(let link of chain)if(await link(context,signal))return!0;return!1}}function createLoopWiring(session){return{getSessionId:()=>session.sessionId,getRevision:()=>detachedSessionSnapshot(session.sessionManager.getRevision()),getTurnCorrelationId:()=>session._turnCorrelationId,observeError:(error2,source,event)=>{session._observeLifecycleDeliveryError(error2,source,event)},getImageAutoResize:()=>session.settingsManager.getImageAutoResize(),compactBeforeNextAssistantResponse:(context,signal)=>session._compactBeforeNextAssistantResponse(context,signal),getTurnRefresh:()=>({systemPrompt:session._systemPromptOverride??session._baseSystemPrompt,tools:session.agent.state.tools.slice(),model:session.agent.state.model,thinkingLevel:session.agent.state.thinkingLevel}),getInitialPrepareNextTurn:()=>session._initialPrepareNextTurn,getContextStrategyName:()=>session._contextStrategyName}}async function runPromptLoop(session,messages){return session._loopExecutor?session._loopExecutor(session,messages):runDefaultLoop(session,messages)}async function runDefaultLoop(session,messages,drive=postAgentRun){let policyDecisionController=new AbortController,previousPolicyDecisionController=session._policyDecisionAbortController;session._policyDecisionAbortController=policyDecisionController,session._isAgentRunActive=!0,session._currentRunAborted=!1;let turnCorrelationId=`turn:${++session._turnCorrelationCounter}`;session._turnCorrelationId=turnCorrelationId;try{for(await session.agent.prompt(messages);await drive(session);)await session.agent.continue();return session._currentRunAborted?{status:"aborted",reason:session._lastAbortReason??"interrupted"}:{status:"done"}}finally{session._turnCorrelationId===turnCorrelationId&&(session._turnCorrelationId=void 0);try{session._systemPromptOverride=void 0,session._flushPendingBashMessages(),session._flushPendingCustomMessages(),await session._emitAgentSettled()}finally{session._policyDecisionAbortController===policyDecisionController&&(session._policyDecisionAbortController=previousPolicyDecisionController)}}}async function postAgentRun(session){let msg=session._lastAssistantMessage;if(session._lastAssistantMessage=void 0,!msg)return session._pendingRetryDecision=void 0,!1;let pendingDecision=session._pendingRetryDecision;session._pendingRetryDecision=void 0;let policySignal=session._policyDecisionAbortController?.signal;try{if(pendingDecision?!policySignal?.aborted&&await session._prepareRetry(msg,pendingDecision.decision):await session._isRetryableError(msg,void 0,policySignal)&&await session._prepareRetry(msg))return await decideRunLoop(session,{willRetry:!0,willCompact:!1,queuedFollowUp:session.agent.hasQueuedMessages(),hostWillContinue:!0},policySignal)}catch(error2){if(!policySignal?.aborted)throw error2}msg.stopReason==="error"&&session._retryAttempt>0&&(session._emit({type:"auto_retry_end",success:!1,attempt:session._retryAttempt,finalError:msg.errorMessage}),session._retryAttempt=0);try{if(await session._checkCompaction(msg,!0,policySignal))return await decideRunLoop(session,{willRetry:!1,willCompact:!0,queuedFollowUp:session.agent.hasQueuedMessages(),hostWillContinue:!0},policySignal)}catch(error2){if(!policySignal?.aborted)throw error2}let queuedFollowUp=session.agent.hasQueuedMessages();return decideRunLoop(session,{willRetry:!1,willCompact:!1,queuedFollowUp,hostWillContinue:queuedFollowUp},policySignal)}async function decideRunLoop(session,facts,signal){let runtime=session._capabilityRuntime;if(!runtime?.hasRunLoopStrategy(session._runLoopStrategyName))return facts.hostWillContinue;try{let decision=await runtime.decideRunLoop(session._runLoopStrategyName,{...facts,signal});return facts.hostWillContinue&&decision.continueLoop}catch(error2){if(!signal?.aborted)throw error2;return facts.hostWillContinue}}async function emitModelSelect(session,nextModel,previousModel,source){modelsAreEqual(previousModel,nextModel)||await dispatchModelSelectLifecycle(session,{provider:nextModel.provider,id:nextModel.id},source)}async function setModel(session,model,options={}){if(!await session._modelRuntime.checkAuth(model.provider))throw new Error(`No API key for ${model.provider}/${model.id}`);let previousModel=session.model,thinkingLevel=session._getThinkingLevelForModelSwitch(model);session.agent.state.model=model,session.sessionManager.appendModelChange(model.provider,model.id),options.persist&&(session.settingsManager.setDefaultModelAndProvider(model.provider,model.id),session._addPersistedDefaultToNonEmptyScope(model)),session.setThinkingLevel(thinkingLevel),await session._emitModelSelect(model,previousModel,"set")}function addPersistedDefaultToNonEmptyScope(session,model){if(session._scopedModels.length===0||session._scopedModels.some(scoped=>modelsAreEqual(scoped.model,model)))return;session._scopedModels=[...session._scopedModels,{model}];let enabledModels=session.settingsManager.getEnabledModels();if(!enabledModels?.length)return;let modelReference=`${model.provider}/${model.id}`;enabledModels.some(pattern=>pattern.toLowerCase()===modelReference.toLowerCase())||session.settingsManager.setEnabledModels([...enabledModels,modelReference])}async function cycleModel(session,direction="forward",options={}){return session._scopedModels.length>0?session._cycleScopedModel(direction,options):session._cycleAvailableModel(direction,options)}async function cycleScopedModel(session,direction,options){let availableIds=new Set(session._modelRuntime.getAvailableSnapshot().map(model=>`${model.provider}\0${model.id}`)),scopedModels=session._scopedModels.filter(scoped=>availableIds.has(`${scoped.model.provider}\0${scoped.model.id}`));if(scopedModels.length<=1)return;let currentModel=session.model,currentIndex=scopedModels.findIndex(sm=>modelsAreEqual(sm.model,currentModel));currentIndex===-1&&(currentIndex=0);let len=scopedModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,next=scopedModels[nextIndex],thinkingLevel=session._getThinkingLevelForModelSwitch(next.model,next.thinkingLevel);return session.agent.state.model=next.model,session.sessionManager.appendModelChange(next.model.provider,next.model.id),options.persist&&(session.settingsManager.setDefaultModelAndProvider(next.model.provider,next.model.id),session._addPersistedDefaultToNonEmptyScope(next.model)),session.setThinkingLevel(thinkingLevel),await session._emitModelSelect(next.model,currentModel,"cycle"),{model:next.model,thinkingLevel:session.thinkingLevel,isScoped:!0}}async function cycleAvailableModel(session,direction,options){let availableModels=session._modelRuntime.getAvailableSnapshot();if(availableModels.length<=1)return;let currentModel=session.model,currentIndex=availableModels.findIndex(m2=>modelsAreEqual(m2,currentModel));currentIndex===-1&&(currentIndex=0);let len=availableModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,nextModel=availableModels[nextIndex],thinkingLevel=session._getThinkingLevelForModelSwitch(nextModel);return session.agent.state.model=nextModel,session.sessionManager.appendModelChange(nextModel.provider,nextModel.id),options.persist&&(session.settingsManager.setDefaultModelAndProvider(nextModel.provider,nextModel.id),session._addPersistedDefaultToNonEmptyScope(nextModel)),session.setThinkingLevel(thinkingLevel),await session._emitModelSelect(nextModel,currentModel,"cycle"),{model:nextModel,thinkingLevel:session.thinkingLevel,isScoped:!1}}function getScopedModels(session){return session._scopedModels}function modelFactsView(model){return{provider:model.provider,id:model.id,contextWindow:model.contextWindow,maxTokens:model.maxTokens,reasoning:model.reasoning}}function setScopedModels(session,scopedModels){session._scopedModels=scopedModels}function getThinkingLevelForModelSwitch(session,targetModel,explicitLevel){if(explicitLevel!==void 0)return explicitLevel;if(targetModel){let perModel=session.settingsManager.getModelThinkingLevel(targetModel.provider,targetModel.id);if(perModel!==void 0)return perModel}return session.settingsManager.getDefaultThinkingLevel()??session.thinkingLevel??DEFAULT_THINKING_LEVEL}import{existsSync as existsSync10,readFileSync as readFileSync9,writeFileSync as writeFileSync7}from"fs";import{basename as basename8,join as join36}from"path";function parseColor(color){let hexMatch=color.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(hexMatch)return{r:Number.parseInt(hexMatch[1],16),g:Number.parseInt(hexMatch[2],16),b:Number.parseInt(hexMatch[3],16)};let rgbMatch=color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/);if(rgbMatch)return{r:Number.parseInt(rgbMatch[1],10),g:Number.parseInt(rgbMatch[2],10),b:Number.parseInt(rgbMatch[3],10)}}function getLuminance(r,g2,b2){let toLinear=c2=>{let s=c2/255;return s<=.03928?s/12.92:((s+.055)/1.055)**2.4};return .2126*toLinear(r)+.7152*toLinear(g2)+.0722*toLinear(b2)}function adjustBrightness(color,factor){let parsed=parseColor(color);if(!parsed)return color;let adjust=c2=>Math.min(255,Math.max(0,Math.round(c2*factor)));return`rgb(${adjust(parsed.r)}, ${adjust(parsed.g)}, ${adjust(parsed.b)})`}function deriveExportColors(baseColor){let parsed=parseColor(baseColor);return parsed?getLuminance(parsed.r,parsed.g,parsed.b)>.5?{pageBg:adjustBrightness(baseColor,.96),cardBg:baseColor,infoBg:`rgb(${Math.min(255,parsed.r+10)}, ${Math.min(255,parsed.g+5)}, ${Math.max(0,parsed.b-20)})`}:{pageBg:adjustBrightness(baseColor,.7),cardBg:adjustBrightness(baseColor,.85),infoBg:`rgb(${Math.min(255,parsed.r+20)}, ${Math.min(255,parsed.g+15)}, ${parsed.b})`}:{pageBg:"rgb(24, 24, 30)",cardBg:"rgb(30, 30, 36)",infoBg:"rgb(60, 55, 40)"}}function generateThemeVars(themeName){let colors=getResolvedThemeColors(themeName),lines=[];for(let[key,value]of Object.entries(colors))lines.push(`--${key}: ${value};`);let themeExport=getThemeExportColors(themeName),userMessageBg=colors.userMessageBg||"#343541",derivedColors=deriveExportColors(userMessageBg);return lines.push(`--exportPageBg: ${themeExport.pageBg??derivedColors.pageBg};`),lines.push(`--exportCardBg: ${themeExport.cardBg??derivedColors.cardBg};`),lines.push(`--exportInfoBg: ${themeExport.infoBg??derivedColors.infoBg};`),lines.join(`
|
|
983
|
+
${getProviderLoginHelp()}`}function withoutDeletedHeaders(headers){return headers?Object.fromEntries(Object.entries(headers).filter(entry=>entry[1]!==null)):void 0}function estimateMessagesTokens(messages){let tokens=0;for(let message of messages)tokens+=estimateTokens2(message);return tokens}async function getRequiredRequestAuth(session,model){let result;try{result=await session._modelRuntime.getAuth(model)}catch(error2){let cause=error2 instanceof Error?error2.cause:void 0;throw cause instanceof Error&&cause.message==="authHeader requires a resolved API key"?new Error(formatNoApiKeyFoundMessage(model.provider)):error2}if(result&&(result.auth.apiKey||result.auth.headers))return{model:result.auth.baseUrl?{...model,baseUrl:result.auth.baseUrl}:model,apiKey:result.auth.apiKey,headers:withoutDeletedHeaders(result.auth.headers),env:result.env};throw session._modelRuntime.isUsingOAuth(model.provider)?new Error(`Authentication failed for "${model.provider}". Credentials may have expired or network is unavailable. Run '/login ${model.provider}' to re-authenticate.`):new Error(formatNoApiKeyFoundMessage(model.provider))}async function getSummarizationRequestAuth(session,model){if(session.agent.streamFunction===streamSimple)return getRequiredRequestAuth(session,model);try{let result=await session._modelRuntime.getAuth(model);return result?{model:result.auth.baseUrl?{...model,baseUrl:result.auth.baseUrl}:model,apiKey:result.auth.apiKey,headers:withoutDeletedHeaders(result.auth.headers),env:result.env}:{model}}catch{return{model}}}function summaryModelFacts(model){return{id:model.id,contextWindow:model.contextWindow,maxTokens:model.maxTokens,reasoning:model.reasoning}}function createSummaryModelInvocationV1(session,auth,retry,callbacks,options={}){return{invoke:async(input,signal)=>{let maxTokens=input.maxTokens===void 0||auth.model.maxTokens<=0?input.maxTokens:Math.min(input.maxTokens,auth.model.maxTokens),requestOptions={...maxTokens===void 0?{}:{maxTokens},signal,apiKey:auth.apiKey,headers:auth.headers,env:auth.env,cacheRetention:"none",sessionId:options.routingSessionId??uuidv7()};auth.model.reasoning&&input.thinkingLevel&&input.thinkingLevel!=="off"&&(requestOptions.reasoning=input.thinkingLevel);let context={systemPrompt:input.systemPrompt,messages:[{role:"user",content:[{type:"text",text:input.prompt}],timestamp:Date.now()}]},produce=async()=>{let streamFn=session.agent.streamFunction;return streamFn?(await streamFn(auth.model,context,requestOptions)).result():completeSimple(auth.model,context,requestOptions)},response2;try{response2=await retryAssistantCall(produce,retry,requestOptions.signal,callbacks)}catch(error2){return error2 instanceof Error&&error2.name==="AbortError"?{version:1,status:"aborted"}:{version:1,status:"failed",error:{code:SUMMARY_MODEL_INVOCATION_ERROR_CODES.transportError,message:error2 instanceof Error?error2.message:String(error2)}}}return response2.stopReason==="aborted"?{version:1,status:"aborted"}:response2.stopReason==="error"?{version:1,status:"failed",error:{code:SUMMARY_MODEL_INVOCATION_ERROR_CODES.providerError,message:response2.errorMessage||"Unknown error"}}:response2.stopReason==="length"?{version:1,status:"failed",error:{code:SUMMARY_MODEL_INVOCATION_ERROR_CODES.lengthCap,message:"generation hit the token cap and the summary is incomplete"}}:response2.content.some(block=>block.type==="toolCall")?{version:1,status:"failed",error:{code:SUMMARY_MODEL_INVOCATION_ERROR_CODES.toolCall,message:"attempted to call a tool"}}:{version:1,status:"completed",text:contentText(response2.content),usage:response2.usage}}}}async function compactBeforeNextAssistantResponse(session,context,signal){let model=session.model,settings2=session.settingsManager.getCompactionSettings();if(!model||model.contextWindow<=0)return context;let contextTokens=estimateContextTokens2(context.messages).tokens,decision=await decideCompaction(session,{reason:"threshold",contextOverflow:!1,recoverableLength:!1,contextUsage:{contextTokens,contextWindow:model.contextWindow,reserveTokens:settings2.reserveTokens},canContinue:!1,signal:signal??session._policyDecisionAbortController?.signal});return await dispatchCompactionDecisionLifecycle(session,{reason:"threshold",compact:decision.compact,willRetry:!1,contextTokens,contextWindow:model.contextWindow,reserveTokens:settings2.reserveTokens,...decision.failureMessage===void 0?{}:{failureMessage:decision.failureMessage}}),decision.compact?(await session._runAutoCompaction("threshold",!1),{...context,messages:session.agent.state.messages.slice()}):context}function executionFacts(session,phase,operationId,revision){let inputRevision=detachedSessionSnapshot(revision??session.sessionManager.getRevision());return Object.freeze({version:1,operationId:operationId??`${phase}:${inputRevision.sessionId}:${inputRevision.sequence}:${inputRevision.leafId??"root"}`,sessionId:session.sessionId,inputRevision,phase})}async function runCompactionSummary(session,preparation,auth,customInstructions,signal,reason,execution){let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");let result=await runtime.summarizeCompaction(session._compactionPolicyName,{preparation,model:summaryModelFacts(auth.model),invocation:createSummaryModelInvocationV1(session,auth,summarizationRetryPolicy(session,execution.operationId,execution.inputRevision,signal),summarizationRetryCallbacks(session,{source:"compaction",reason}),{routingSessionId:session.sessionId}),customInstructions,signal,reason,thinkingLevel:session.thinkingLevel,sessionId:session.sessionId,context:{version:1,sessionId:session.sessionId,phase:"compaction"},execution});return{...result,usage:result.usage}}async function decideCompaction(session,input){let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");return session._compactionPolicyName===DEFAULT_COMPACTION_POLICY_NAME&&!runtime.hasCompactionPolicy(session._compactionPolicyName)?(session._hostLogger?.warn("compaction","no compaction policy registered; skipping automatic compaction",{fields:{policyName:session._compactionPolicyName,reason:input.reason}}),{compact:!1,retry:!1}):runtime.decideCompaction(session._compactionPolicyName,{enabled:session.settingsManager.getCompactionSettings().enabled,recoveryAttempted:session._overflowRecoveryAttempted,...input,context:{version:1,sessionId:session.sessionId,phase:"compaction"},execution:input.execution??executionFacts(session,"compaction"),signal:input.signal})}async function prepareCompaction3(session,pathEntries,settings2,execution,signal){let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");let preparation=await runtime.prepareCompaction(session._compactionPolicyName,{entries:pathEntries,settings:settings2,context:{version:1,sessionId:session.sessionId,phase:"compaction"},execution:execution??executionFacts(session,"compaction"),signal});if(preparation===void 0)return;let value=preparation;if(!preparation||typeof preparation!="object"||typeof value.firstKeptEntryId!="string"||!Array.isArray(value.messagesToSummarize)||!Array.isArray(value.turnPrefixMessages)||typeof value.isSplitTurn!="boolean"||!Number.isFinite(value.tokensBefore)||typeof value.fileOps!="object"||typeof value.settings!="object")throw new Error(`Compaction policy returned an invalid preparation: ${session._compactionPolicyName}`);return preparation}function captureCompactionCommitBoundary(session,reason){let pathEntries=session.sessionManager.getBranch(),expectedRevision=session.sessionManager.getRevision();return{pathEntries,expectedRevision,operationId:`compaction:${reason}:${expectedRevision.sessionId}:${expectedRevision.sequence}:${expectedRevision.leafId??"root"}`}}function enqueueCompaction(session,operation){let previous=session._compactionQueue,release;session._compactionQueue=new Promise(resolve25=>{release=resolve25});let queued=previous.then(()=>{if(session._reloadInProgress)throw new Error("Session reload in progress; compaction was not started");return operation()}).finally(release);return session._activeCompactionPromise=queued,queued.then(()=>{session._activeCompactionPromise===queued&&(session._activeCompactionPromise=void 0)},()=>{session._activeCompactionPromise===queued&&(session._activeCompactionPromise=void 0)}),queued}function commitCompaction(session,input){let commit=session.sessionManager.commitCompaction({version:1,operationId:input.operationId,expectedRevision:input.expectedRevision,summary:input.summary,firstKeptEntryId:input.firstKeptEntryId,tokensBefore:input.tokensBefore,details:input.details,fromHook:!1,usage:input.usage});if(commit.status==="revision_conflict")throw new Error(`Compaction commit revision conflict: expected ${input.expectedRevision.sequence}/${input.expectedRevision.leafId??"root"}, current ${commit.currentRevision.sequence}/${commit.currentRevision.leafId??"root"}`);let entry=session.sessionManager.getEntry(commit.entryId);if(entry?.type!=="compaction"||entry.operationId!==input.operationId)throw new Error(`Compaction commit entry is unavailable: ${commit.entryId}`);return{entry,status:commit.status,revision:commit.revision}}async function dispatchCompactionCommitLifecycle(session,reason,commit){try{let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");let entry=commit.entry,data={version:1,status:commit.status,entryId:entry.id,operationId:entry.operationId??"",revision:commit.revision,reason,summary:entry.summary,firstKeptEntryId:entry.firstKeptEntryId,tokensBefore:entry.tokensBefore,fromHook:entry.fromHook===!0,...entry.usage===void 0?{}:{usage:entry.usage},...entry.details===void 0?{}:{details:entry.details}},delivery=await runtime.dispatchLifecycle({type:SESSION_COMPACTION_COMMIT_EVENT_ID,version:SESSION_COMPACTION_COMMIT_EVENT_VERSION,phase:"committed",data,operationId:entry.operationId,source:"agent-session"});for(let failure2 of delivery.report.failures)session._observeLifecycleDeliveryError(failure2.error,failure2.pluginId,`${SESSION_COMPACTION_COMMIT_EVENT_ID}@${SESSION_COMPACTION_COMMIT_EVENT_VERSION}/${failure2.kind}`)}catch(error2){let report=error2.report;if(report?.failures)for(let failure2 of report.failures)session._observeLifecycleDeliveryError(failure2.error,failure2.pluginId,`${SESSION_COMPACTION_COMMIT_EVENT_ID}@${SESSION_COMPACTION_COMMIT_EVENT_VERSION}/${failure2.kind}`);else session._observeLifecycleDeliveryError(error2,"<capability-lifecycle>",`${SESSION_COMPACTION_COMMIT_EVENT_ID}@${SESSION_COMPACTION_COMMIT_EVENT_VERSION}`)}}async function decideOverflow(session,message,execution,signal){let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");return runtime.decideOverflow(session._overflowPolicyName,{message,contextWindow:session.model?.contextWindow,desiredMaxOutput:session.model?.maxTokens??0,context:{version:1,sessionId:session.sessionId,phase:"overflow"},execution:execution??executionFacts(session,"overflow"),signal})}function clearManualCompactionState(session){session._compactionAbortController=void 0,session._resolveIdleWaitIfIdle()}async function compactInternal(session,customInstructions){if(await session._abortInternal(),session._reloadInProgress)return{cancelled:!0,aborted:!0};session._compactionAbortController=new AbortController,session._emit({type:"compaction_start",reason:"manual"});try{if(!session.model)throw new Error(formatNoModelSelectedMessage());let auth=await getSummarizationRequestAuth(session,session.model),{pathEntries,expectedRevision,operationId}=captureCompactionCommitBoundary(session,"manual"),settings2=session.settingsManager.getCompactionSettings(),execution=executionFacts(session,"compaction",operationId),preparation=await prepareCompaction3(session,pathEntries,settings2,execution,session._compactionAbortController.signal);if(!preparation)throw pathEntries[pathEntries.length-1]?.type==="compaction"?new Error("Already compacted"):new Error("Nothing to compact (session too small)");let{summary,firstKeptEntryId,tokensBefore,usage,details}=await runCompactionSummary(session,preparation,auth,customInstructions,session._compactionAbortController.signal,"manual",execution);if(session._compactionAbortController.signal.aborted||session._reloadInProgress)throw new SessionCancelledError("signal");let compactionCommit=commitCompaction(session,{expectedRevision,operationId,summary,firstKeptEntryId,tokensBefore,details,usage});await dispatchCompactionCommitLifecycle(session,"manual",compactionCommit);let sessionContext=session.sessionManager.buildSessionContext();await session._applyContextTransition(sessionContext.messages,"compaction");let estimatedTokensAfter=estimateMessagesTokens(session.agent.state.messages),compactionResult={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return clearManualCompactionState(session),session._emit({type:"compaction_end",reason:"manual",result:compactionResult,aborted:!1,willRetry:!1}),compactionResult}catch(error2){if(error2 instanceof SessionCancelledError||error2 instanceof Error&&error2.name==="AbortError")return clearManualCompactionState(session),session._emit({type:"compaction_end",reason:"manual",result:void 0,aborted:!0,willRetry:!1}),{cancelled:!0,aborted:!0};let errorMessage2=`Compaction failed: ${error2 instanceof Error?error2.message:String(error2)}`;throw clearManualCompactionState(session),session._emit({type:"compaction_end",reason:"manual",result:void 0,aborted:!1,willRetry:!1,errorMessage:errorMessage2}),session._hostLogger?.error("compaction","compaction failed",{fields:{reason:"manual"},cause:error2}),await dispatchCompactionFailedLifecycle(session,{reason:"manual",errorMessage:errorMessage2}),error2}finally{clearManualCompactionState(session)}}async function checkCompaction(session,assistantMessage,skipAbortedCheck=!0,signal){if(signal?.aborted)return!1;let settings2=session.settingsManager.getCompactionSettings();if(skipAbortedCheck&&assistantMessage.stopReason==="aborted")return!1;let contextWindow=session.model?.contextWindow??0,sameModel=session.model!==void 0&&assistantMessage.provider===session.model.provider&&assistantMessage.model===session.model.id,compactionEntry=getLatestCompactionEntry(session.sessionManager.getBranch());if(compactionEntry!==null&&assistantMessage.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1;let overflow=sameModel?await decideOverflow(session,assistantMessage,void 0,signal):{contextOverflow:!1,recoverableLength:!1},{contextOverflow,recoverableLength}=overflow;if(contextOverflow||recoverableLength){let decision2=await decideCompaction(session,{reason:"overflow",contextOverflow,recoverableLength,canContinue:assistantMessage.stopReason!=="stop",signal});if(await dispatchCompactionDecisionLifecycle(session,{reason:"overflow",compact:decision2.compact,willRetry:decision2.retry===!0,...decision2.failureMessage===void 0?{}:{failureMessage:decision2.failureMessage}}),!decision2.compact){if(decision2.failureMessage){let errorMessage2=decision2.failureMessage;session._emit({type:"compaction_end",reason:"overflow",result:void 0,aborted:!1,willRetry:!1,errorMessage:errorMessage2}),session._hostLogger?.error("compaction","compaction failed",{fields:{reason:"overflow"},cause:errorMessage2}),await dispatchCompactionFailedLifecycle(session,{reason:"overflow",errorMessage:errorMessage2})}return!1}let willRetry=decision2.retry===!0;return willRetry&&(session._overflowRecoveryAttempted=!0),await session._runAutoCompaction("overflow",willRetry)}let contextTokens,directContextTokens=assistantMessage.usage?calculateContextTokens2(assistantMessage.usage):0;if(assistantMessage.stopReason==="error"||directContextTokens===0){let messages=session.agent.state.messages,estimate=estimateContextTokens2(messages);if(estimate.lastUsageIndex!==null){let usageMsg=messages[estimate.lastUsageIndex];if(compactionEntry&&usageMsg.role==="assistant"&&usageMsg.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1}contextTokens=estimate.tokens}else contextTokens=directContextTokens;let decision=await decideCompaction(session,{reason:"threshold",contextOverflow:!1,recoverableLength:!1,contextUsage:{contextTokens,contextWindow,reserveTokens:settings2.reserveTokens},canContinue:!1,branchEntries:session.sessionManager.getBranch(),keepRecentTokens:settings2.keepRecentTokens,signal});if(await dispatchCompactionDecisionLifecycle(session,{reason:"threshold",compact:decision.compact,willRetry:decision.retry===!0,contextTokens,contextWindow,reserveTokens:settings2.reserveTokens,...decision.failureMessage===void 0?{}:{failureMessage:decision.failureMessage}}),decision.relief!==void 0&&!decision.compact){session.sessionManager.appendCustomEntry(decision.relief.customType,decision.relief.data);let sessionContext=session.sessionManager.buildSessionContext();return await session._applyContextTransition(sessionContext.messages,"compaction"),session._hostLogger?.info("compaction","policy relief applied",{fields:{customType:decision.relief.customType}}),session.agent.hasQueuedMessages()}return decision.compact?session._runAutoCompaction("threshold",decision.retry===!0):!1}async function runAutoCompaction(session,reason,willRetry){return session._reloadInProgress?!1:enqueueCompaction(session,()=>runAutoCompactionInternal(session,reason,willRetry))}async function runAutoCompactionInternal(session,reason,willRetry){session._autoCompactionAbortController=new AbortController;let autoCompactionSignal=session._autoCompactionAbortController.signal;try{try{if(willRetry){let messages=session.agent.state.messages;messages.length>0&&messages[messages.length-1].role==="assistant"&&await session._applyContextTransition(messages.slice(0,-1),"overflow_recovery")}if(autoCompactionSignal.aborted||session._reloadInProgress)return!1}catch(error2){throw session._autoCompactionAbortController=void 0,error2}let settings2=session.settingsManager.getCompactionSettings(),started=!1;try{if(!session.model)return!1;let auth=await getSummarizationRequestAuth(session,session.model),{pathEntries,expectedRevision,operationId}=captureCompactionCommitBoundary(session,reason),execution=executionFacts(session,"compaction",operationId),preparation=await prepareCompaction3(session,pathEntries,settings2,execution,autoCompactionSignal);if(!preparation)return session._emit({type:"compaction_skipped",reason,cause:"nothing_to_compact"}),!1;session._emit({type:"compaction_start",reason}),started=!0;let{summary,firstKeptEntryId,tokensBefore,usage,details}=await runCompactionSummary(session,preparation,auth,void 0,autoCompactionSignal,reason,execution);if(autoCompactionSignal.aborted||session._reloadInProgress)return session._emit({type:"compaction_end",reason,result:void 0,aborted:!0,willRetry:!1}),!1;let compactionCommit=commitCompaction(session,{expectedRevision,operationId,summary,firstKeptEntryId,tokensBefore,details,usage});await dispatchCompactionCommitLifecycle(session,reason,compactionCommit);let sessionContext=session.sessionManager.buildSessionContext();await session._applyContextTransition(sessionContext.messages,"compaction");let estimatedTokensAfter=estimateMessagesTokens(session.agent.state.messages),result={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};if(session._emit({type:"compaction_end",reason,result,aborted:!1,willRetry}),willRetry){let messages=session.agent.state.messages,lastMsg=messages[messages.length-1];return lastMsg?.role==="assistant"&&(lastMsg.stopReason==="error"||lastMsg.stopReason==="length")&&await session._applyContextTransition(messages.slice(0,-1),"overflow_recovery"),!0}return session.agent.hasQueuedMessages()}catch(error2){let errorMessage2=error2 instanceof Error?error2.message:"compaction failed";if(started){let formattedErrorMessage=reason==="overflow"?`Context overflow recovery failed: ${errorMessage2}`:`Auto-compaction failed: ${errorMessage2}`;session._emit({type:"compaction_end",reason,result:void 0,aborted:!1,willRetry:!1,errorMessage:formattedErrorMessage}),session._hostLogger?.error("compaction","compaction failed",{fields:{reason},cause:error2}),await dispatchCompactionFailedLifecycle(session,{reason,errorMessage:formattedErrorMessage})}return!1}}finally{session._autoCompactionAbortController=void 0,session._resolveIdleWaitIfIdle()}}function summarizationRetryCallbacks(session,source){let attempts=[];return{onRetryScheduled:(attempt2,_maxAttempts,delayMs,errorMessage2)=>{attempts.push({attempt:attempt2,at:Date.now(),ok:!1,failure:errorMessage2,waitedMs:delayMs}),session._emit({type:"summarization_retry_scheduled",attempt:attempt2,maxAttempts:_maxAttempts,delayMs,errorMessage:errorMessage2})},onRetryAttemptStart:()=>{session._emit({type:"summarization_retry_attempt_start",...source})},onRetryFinished:(success,attempt2,finalError)=>{attempts.push(success?{attempt:attempt2+1,at:Date.now(),ok:!0,waitedMs:0}:{attempt:attempt2+1,at:Date.now(),ok:!1,waitedMs:0,...finalError===void 0?{}:{failure:finalError}}),session._emit({type:"summarization_retry_finished",source,attempts})}}}function summarizationRetryPolicy(session,operationId,inputRevision,signal){let settings2=session.settingsManager.getRetrySettings(),runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");let execution=executionFacts(session,"retry",operationId?`${operationId}:retry`:void 0,inputRevision);return{...settings2,classify:message=>runtime.classifyRetry(session._retryPolicyName,{message,signal,context:{version:1,sessionId:session.sessionId,phase:"retry"},execution}),decide:({message,retryable,attempt:attempt2,maxAttempts,baseDelayMs})=>runtime.decideRetry(session._retryPolicyName,{retryable,enabled:settings2.enabled,attempt:attempt2,maxAttempts,baseDelayMs,errorMessage:message.errorMessage,signal,context:{version:1,sessionId:session.sessionId,phase:"retry"},execution})}}async function navigateTree(session,targetId,options={}){if(session.isStreaming)throw new Error("Wait for the current response to finish before navigating the session tree.");if(session._compactionAbortController!==void 0||session._autoCompactionAbortController!==void 0)throw new Error("Wait for the current compaction or tree navigation to finish before navigating the session tree.");let oldLeafId=session.sessionManager.getLeafId();if(targetId===oldLeafId)return{cancelled:!1};if(options.summarize&&!session.model)throw new Error("No model available for summarization");let targetEntry=session.sessionManager.getEntry(targetId);if(!targetEntry)throw new Error(`Entry ${targetId} not found`);let{entries:entriesToSummarize}=collectEntriesForBranchSummary2(session.sessionManager,oldLeafId,targetId),customInstructions=options.customInstructions,replaceInstructions=options.replaceInstructions,label=options.label;if(session._reloadInProgress)throw new Error("Session reload in progress; tree navigation is unavailable");if(session._branchSummaryAbortController)throw new Error("Branch navigation is already in progress");session._branchSummaryAbortController=new AbortController;let branchSummaryPromise=new Promise(resolve25=>{session._resolveBranchSummaryPromise=resolve25});session._branchSummaryPromise=branchSummaryPromise;try{let summaryText,summaryDetails,summaryUsage;if(options.summarize&&entriesToSummarize.length>0){let model=session.model,auth=await getSummarizationRequestAuth(session,model),branchSummarySettings=session.settingsManager.getBranchSummarySettings(),runtime=session._capabilityRuntime;if(!runtime||!runtime.hasBranchSummaryPolicy(session._branchSummaryPolicyName))throw new Error(`Branch summary policy is not registered: ${session._branchSummaryPolicyName}`);let execution=executionFacts(session,"branch_summary",`branch_summary:${session.sessionId}:${oldLeafId??"root"}:${targetId}`),result=await runtime.summarizeBranch(session._branchSummaryPolicyName,{entries:entriesToSummarize,model:summaryModelFacts(auth.model),invocation:createSummaryModelInvocationV1(session,auth,summarizationRetryPolicy(session,execution.operationId,execution.inputRevision,session._branchSummaryAbortController.signal),summarizationRetryCallbacks(session,{source:"branchSummary"})),signal:session._branchSummaryAbortController.signal,customInstructions,replaceInstructions,reserveTokens:branchSummarySettings.reserveTokens,context:{version:1,sessionId:session.sessionId,phase:"branch_summary"},execution});if(result.aborted)return{cancelled:!0,aborted:!0};if(result.error)throw new Error(result.error);summaryText=result.summary,summaryUsage=result.usage,summaryDetails={readFiles:result.readFiles||[],modifiedFiles:result.modifiedFiles||[]}}if(session._branchSummaryAbortController.signal.aborted||session._reloadInProgress)return{cancelled:!0,aborted:!0};let newLeafId,editorText;targetEntry.type==="message"&&targetEntry.message.role==="user"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.message.content,"")):targetEntry.type==="custom_message"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.content,"")):newLeafId=targetId;let summaryEntry;if(summaryText){let summaryId=session.sessionManager.branchWithSummary(newLeafId,summaryText,summaryDetails,!1,summaryUsage);summaryEntry=session.sessionManager.getEntry(summaryId),label&&session.sessionManager.appendLabelChange(summaryId,label)}else newLeafId===null?session.sessionManager.resetLeaf():session.sessionManager.branch(newLeafId);label&&!summaryText&&session.sessionManager.appendLabelChange(targetId,label);let sessionContext=session.sessionManager.buildSessionContext();return await session._applyContextTransition(sessionContext.messages,"tree"),{editorText,cancelled:!1,summaryEntry}}finally{session._branchSummaryAbortController=void 0,session._resolveIdleWaitIfIdle(),session._resolveBranchSummaryPromise?.(),session._resolveBranchSummaryPromise=void 0,session._branchSummaryPromise===branchSummaryPromise&&(session._branchSummaryPromise=void 0)}}function requireContextStrategy(session){let name=session._contextStrategyName;if(!name)throw new Error("Context strategy is not configured");let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");if(!runtime.hasContextStrategy(name))throw new Error(`Configured context strategy is not registered: ${name}`);return{runtime,name}}function requireIdleContextOperation(session,operation){if(!session.isIdle)throw new Error(`Cannot ${operation} while the session is running`)}function beginContextTransitionFence(session){session._contextEpoch+=1,session._contextTransitionAbortController.abort("context runtime replaced"),session._contextTransitionAbortController=new AbortController}function isContextTransitionCurrent(session,epoch,allowReload){return!session.isDisposed&&epoch===session._contextEpoch&&(allowReload||!session._reloadInProgress)}function assertContextTransitionCurrent(session,epoch,allowReload){if(!session._isContextTransitionCurrent(epoch,allowReload))throw new Error(session.isDisposed?"Session is disposed; context transition was cancelled":session._reloadInProgress?"Session reload in progress; context transition was cancelled":"Context transition was superseded")}function enqueueContextTransition(session,operation,options){let allowReload=options?.allowReload??!1;if(session.isDisposed)return Promise.reject(new Error("Session is disposed; context transition is unavailable"));if(session._reloadInProgress&&!allowReload)return Promise.reject(new Error("Session reload in progress; context transition is unavailable"));let epoch=session._contextEpoch,fenceSignal=session._contextTransitionAbortController.signal,signal=options?.signal?AbortSignal.any([fenceSignal,options.signal]):fenceSignal,queued=(session._activeContextTransition?.catch(()=>{})??Promise.resolve()).then(()=>(session._assertContextTransitionCurrent(epoch,allowReload),operation(epoch,signal)));return session._activeContextTransition=queued,queued.then(()=>{session._activeContextTransition===queued&&(session._activeContextTransition=void 0)},()=>{session._activeContextTransition===queued&&(session._activeContextTransition=void 0)}),queued}function copyContextMessages(value,strategyName,direction){if(!Array.isArray(value)||value.some(message=>typeof message!="object"||message===null||!("role"in message)||typeof message.role!="string"))throw new Error(direction==="result"?`Context strategy must return an AgentMessage array: ${strategyName}`:`Context transition requires an AgentMessage array: ${strategyName}`);try{return structuredClone(value)}catch(error2){throw new Error(direction==="result"?`Context strategy must return structured-cloneable AgentMessage values: ${strategyName}`:`Context transition requires structured-cloneable AgentMessage values: ${strategyName}`,{cause:error2})}}function applyContextTransition(session,messages,reason="session_replace",signal,options){return session._enqueueContextTransition(async(epoch,transitionSignal)=>{let name=session._contextStrategyName,runtime=session._capabilityRuntime;if(name){if(!runtime)throw new Error("Capability runtime is not available");if(!runtime.hasContextStrategy(name))throw new Error(`Configured context strategy is not registered: ${name}`);let replaced=await runtime.replaceContext(name,session._copyContextMessages(messages,name,"input"),{signal:transitionSignal,reason,sessionId:session.sessionId});session._assertContextTransitionCurrent(epoch,options?.allowReload??!1);let committed=session._copyContextMessages(replaced,name,"result");return session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),session.agent.state.messages=committed,session._contextRevision+=1,session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),await session._dispatchContextReplacedLifecycle(reason,name),committed}return session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),session.agent.state.messages=messages,session._contextRevision+=1,session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),await session._dispatchContextReplacedLifecycle(reason),messages},{signal,allowReload:options?.allowReload})}function restoreContextTransition(session,snapshot2,reason,options){return session._enqueueContextTransition(async(epoch,signal)=>{let{runtime,name}=session._requireContextStrategy(),restored=await runtime.restoreContext(name,snapshot2,{signal,reason,sessionId:session.sessionId});session._assertContextTransitionCurrent(epoch,options?.allowReload??!1);let committed=session._copyContextMessages(restored,name,"result");return session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),session.agent.state.messages=committed,session._contextRevision+=1,session._assertContextTransitionCurrent(epoch,options?.allowReload??!1),await session._dispatchContextReplacedLifecycle(reason,name),committed},{allowReload:options?.allowReload})}async function snapshotContext(session){session._requireIdleContextOperation("snapshot context");let{runtime,name}=session._requireContextStrategy();return runtime.snapshotContext(name,session._copyContextMessages(session.agent.state.messages,name,"input"),{reason:"reload",sessionId:session.sessionId})}async function restoreContext(session,snapshot2){return session._requireIdleContextOperation("restore context"),session._restoreContextTransition(snapshot2,"session_replace")}async function replaceContext(session,context){session._requireIdleContextOperation("replace context");let{name}=session._requireContextStrategy();return session._applyContextTransition(session._copyContextMessages(context,name,"input"),"session_replace")}import{basename as basename7,dirname as dirname17}from"node:path";async function extendResourcesFromExtensions(session,reason){dispatchResourcesDiscoverV1Lifecycle(session,{cwd:session._cwd,reason});let contributed=await dispatchResourcesDiscoverV2Lifecycle(session,reason),{skillPaths,promptPaths,themePaths}=contributed;if(skillPaths.length===0&&promptPaths.length===0&&themePaths.length===0)return;let extensionPaths={skillPaths:session.buildExtensionResourcePaths(skillPaths),promptPaths:session.buildExtensionResourcePaths(promptPaths),themePaths:session.buildExtensionResourcePaths(themePaths)};session._resourceLoader.extendResources(extensionPaths),await session._refreshBootstrapSkills(),session._baseSystemPrompt=session._rebuildSystemPrompt(session.getActiveToolNames()),session.agent.state.systemPrompt=session._baseSystemPrompt}function buildExtensionResourcePaths(session,entries){return entries.map(entry=>{let source=session.getExtensionSourceLabel(entry.extensionPath),baseDir=entry.extensionPath.startsWith("<")?void 0:dirname17(entry.extensionPath);return{path:entry.path,metadata:{source,scope:"temporary",origin:"top-level",baseDir}}})}function getExtensionSourceLabel(extensionPath){return extensionPath.startsWith("<")?`extension:${extensionPath.replace(/[<>]/g,"")}`:`extension:${basename7(extensionPath).replace(/\.(ts|js)$/,"")}`}function collectCommandInfos(session){let templates=session.promptTemplates.map(template=>({name:template.name,description:template.description,source:"prompt",sourceInfo:template.sourceInfo})),skills=session._getAvailableSkills().map(skill=>({name:`skill:${skill.name}`,description:skill.description,source:"skill",sourceInfo:skill.sourceInfo}));return[...templates,...skills]}function wireDefaultLoop(session){let previousPrepareNextTurnWithContext=session.agent.prepareNextTurnWithContext??(session.agent.prepareNextTurn?async(_turn,signal)=>await session.agent.prepareNextTurn?.(signal):void 0);session._initialPrepareNextTurn=previousPrepareNextTurnWithContext;let previousTransform=session.agent.transformContext,transformHead=previousTransform?async(messages,signal)=>await previousTransform(messages,signal):void 0;session.agent.beforeToolCall=async({toolCall,args},signal)=>{let chain=session._capabilityRuntime?.getLoopHookChain("beforeToolCall")??[],currentArgs=args,replaced=!1;for(let link of chain){let result=await link({toolCallId:toolCall.id,toolName:toolCall.name,args:currentArgs,signal});if(result){if(result.block){let reason=typeof result.reason=="string"&&result.reason.trim()!==""?result.reason:void 0;return await dispatchToolGateBlockedLifecycle(session,toolCall.id,toolCall.name,reason),result}"args"in result&&(currentArgs=result.args,replaced=!0)}}return replaced?{args:currentArgs}:void 0},session.agent.afterToolCall=async({toolCall,args,result,isError},signal)=>{let chain=session._capabilityRuntime?.getLoopHookChain("afterToolCall")??[],current=result,override;for(let link of chain){let linkResult=await link({toolCallId:toolCall.id,toolName:toolCall.name,args,result:current,isError,signal});linkResult!==void 0&&(current=linkResult,override=linkResult)}return override},session.agent.transformContext=async(messages,signal)=>{let current=messages;if(transformHead){let transformed=await transformHead(current,signal);transformed!==void 0&&(current=transformed)}let chain=session._capabilityRuntime?.getLoopHookChain("transformContext")??[];for(let link of chain){let transformed=await link(current,signal);transformed!==void 0&&(current=transformed)}return current},session.agent.prepareNextTurnWithContext=async(turn,signal)=>{let chain=session._capabilityRuntime?.getLoopHookChain("prepareNextTurn")??[],current=turn;for(let link of chain){let revised=await link(current,signal);revised!==void 0&&(current=revised)}return current};let previousShouldStopAfterTurn=session.agent.shouldStopAfterTurn;session.agent.shouldStopAfterTurn=async(context,signal)=>{if(previousShouldStopAfterTurn&&await previousShouldStopAfterTurn(context,signal))return!0;let chain=session._capabilityRuntime?.getLoopHookChain("shouldStopAfterTurn")??[];for(let link of chain)if(await link(context,signal))return!0;return!1}}function createLoopWiring(session){return{getSessionId:()=>session.sessionId,getRevision:()=>detachedSessionSnapshot(session.sessionManager.getRevision()),getTurnCorrelationId:()=>session._turnCorrelationId,observeError:(error2,source,event)=>{session._observeLifecycleDeliveryError(error2,source,event)},getImageAutoResize:()=>session.settingsManager.getImageAutoResize(),compactBeforeNextAssistantResponse:(context,signal)=>session._compactBeforeNextAssistantResponse(context,signal),getTurnRefresh:()=>({systemPrompt:session._systemPromptOverride??session._baseSystemPrompt,tools:session.agent.state.tools.slice(),model:session.agent.state.model,thinkingLevel:session.agent.state.thinkingLevel}),getInitialPrepareNextTurn:()=>session._initialPrepareNextTurn,getContextStrategyName:()=>session._contextStrategyName}}async function runPromptLoop(session,messages){return session._loopExecutor?session._loopExecutor(session,messages):runDefaultLoop(session,messages)}async function runDefaultLoop(session,messages,drive=postAgentRun){let policyDecisionController=new AbortController,previousPolicyDecisionController=session._policyDecisionAbortController;session._policyDecisionAbortController=policyDecisionController,session._isAgentRunActive=!0,session._currentRunAborted=!1;let turnCorrelationId=`turn:${++session._turnCorrelationCounter}`;session._turnCorrelationId=turnCorrelationId;try{for(await session.agent.prompt(messages);await drive(session);)await session.agent.continue();return session._currentRunAborted?{status:"aborted",reason:session._lastAbortReason??"interrupted"}:{status:"done"}}finally{session._turnCorrelationId===turnCorrelationId&&(session._turnCorrelationId=void 0);try{session._systemPromptOverride=void 0,session._flushPendingBashMessages(),session._flushPendingCustomMessages(),await session._emitAgentSettled()}finally{session._policyDecisionAbortController===policyDecisionController&&(session._policyDecisionAbortController=previousPolicyDecisionController)}}}async function postAgentRun(session){let msg=session._lastAssistantMessage;if(session._lastAssistantMessage=void 0,!msg)return session._pendingRetryDecision=void 0,!1;let pendingDecision=session._pendingRetryDecision;session._pendingRetryDecision=void 0;let policySignal=session._policyDecisionAbortController?.signal;try{if(pendingDecision?!policySignal?.aborted&&await session._prepareRetry(msg,pendingDecision.decision):await session._isRetryableError(msg,void 0,policySignal)&&await session._prepareRetry(msg))return await decideRunLoop(session,{willRetry:!0,willCompact:!1,queuedFollowUp:session.agent.hasQueuedMessages(),hostWillContinue:!0},policySignal)}catch(error2){if(!policySignal?.aborted)throw error2}msg.stopReason==="error"&&session._retryAttempt>0&&(session._emit({type:"auto_retry_end",success:!1,attempt:session._retryAttempt,finalError:msg.errorMessage}),session._retryAttempt=0);try{if(await session._checkCompaction(msg,!0,policySignal))return await decideRunLoop(session,{willRetry:!1,willCompact:!0,queuedFollowUp:session.agent.hasQueuedMessages(),hostWillContinue:!0},policySignal)}catch(error2){if(!policySignal?.aborted)throw error2}let queuedFollowUp=session.agent.hasQueuedMessages();return decideRunLoop(session,{willRetry:!1,willCompact:!1,queuedFollowUp,hostWillContinue:queuedFollowUp},policySignal)}async function decideRunLoop(session,facts,signal){let runtime=session._capabilityRuntime;if(!runtime?.hasRunLoopStrategy(session._runLoopStrategyName))return facts.hostWillContinue;try{let decision=await runtime.decideRunLoop(session._runLoopStrategyName,{...facts,signal});return facts.hostWillContinue&&decision.continueLoop}catch(error2){if(!signal?.aborted)throw error2;return facts.hostWillContinue}}async function emitModelSelect(session,nextModel,previousModel,source){modelsAreEqual(previousModel,nextModel)||await dispatchModelSelectLifecycle(session,{provider:nextModel.provider,id:nextModel.id},source)}async function setModel(session,model,options={}){if(!await session._modelRuntime.checkAuth(model.provider))throw new Error(`No API key for ${model.provider}/${model.id}`);let previousModel=session.model,thinkingLevel=session._getThinkingLevelForModelSwitch(model);session.agent.state.model=model,session.sessionManager.appendModelChange(model.provider,model.id),options.persist&&(session.settingsManager.setDefaultModelAndProvider(model.provider,model.id),session._addPersistedDefaultToNonEmptyScope(model)),session.setThinkingLevel(thinkingLevel),await session._emitModelSelect(model,previousModel,"set")}function addPersistedDefaultToNonEmptyScope(session,model){if(session._scopedModels.length===0||session._scopedModels.some(scoped=>modelsAreEqual(scoped.model,model)))return;session._scopedModels=[...session._scopedModels,{model}];let enabledModels=session.settingsManager.getEnabledModels();if(!enabledModels?.length)return;let modelReference=`${model.provider}/${model.id}`;enabledModels.some(pattern=>pattern.toLowerCase()===modelReference.toLowerCase())||session.settingsManager.setEnabledModels([...enabledModels,modelReference])}async function cycleModel(session,direction="forward",options={}){return session._scopedModels.length>0?session._cycleScopedModel(direction,options):session._cycleAvailableModel(direction,options)}async function cycleScopedModel(session,direction,options){let availableIds=new Set(session._modelRuntime.getAvailableSnapshot().map(model=>`${model.provider}\0${model.id}`)),scopedModels=session._scopedModels.filter(scoped=>availableIds.has(`${scoped.model.provider}\0${scoped.model.id}`));if(scopedModels.length<=1)return;let currentModel=session.model,currentIndex=scopedModels.findIndex(sm=>modelsAreEqual(sm.model,currentModel));currentIndex===-1&&(currentIndex=0);let len=scopedModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,next=scopedModels[nextIndex],thinkingLevel=session._getThinkingLevelForModelSwitch(next.model,next.thinkingLevel);return session.agent.state.model=next.model,session.sessionManager.appendModelChange(next.model.provider,next.model.id),options.persist&&(session.settingsManager.setDefaultModelAndProvider(next.model.provider,next.model.id),session._addPersistedDefaultToNonEmptyScope(next.model)),session.setThinkingLevel(thinkingLevel),await session._emitModelSelect(next.model,currentModel,"cycle"),{model:next.model,thinkingLevel:session.thinkingLevel,isScoped:!0}}async function cycleAvailableModel(session,direction,options){let availableModels=session._modelRuntime.getAvailableSnapshot();if(availableModels.length<=1)return;let currentModel=session.model,currentIndex=availableModels.findIndex(m2=>modelsAreEqual(m2,currentModel));currentIndex===-1&&(currentIndex=0);let len=availableModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,nextModel=availableModels[nextIndex],thinkingLevel=session._getThinkingLevelForModelSwitch(nextModel);return session.agent.state.model=nextModel,session.sessionManager.appendModelChange(nextModel.provider,nextModel.id),options.persist&&(session.settingsManager.setDefaultModelAndProvider(nextModel.provider,nextModel.id),session._addPersistedDefaultToNonEmptyScope(nextModel)),session.setThinkingLevel(thinkingLevel),await session._emitModelSelect(nextModel,currentModel,"cycle"),{model:nextModel,thinkingLevel:session.thinkingLevel,isScoped:!1}}function getScopedModels(session){return session._scopedModels}function modelFactsView(model){return{provider:model.provider,id:model.id,contextWindow:model.contextWindow,maxTokens:model.maxTokens,reasoning:model.reasoning}}function setScopedModels(session,scopedModels){session._scopedModels=scopedModels}function getThinkingLevelForModelSwitch(session,targetModel,explicitLevel){if(explicitLevel!==void 0)return explicitLevel;if(targetModel){let perModel=session.settingsManager.getModelThinkingLevel(targetModel.provider,targetModel.id);if(perModel!==void 0)return perModel}return session.settingsManager.getDefaultThinkingLevel()??session.thinkingLevel??DEFAULT_THINKING_LEVEL}import{existsSync as existsSync10,readFileSync as readFileSync9,writeFileSync as writeFileSync7}from"fs";import{basename as basename8,join as join36}from"path";function parseColor(color){let hexMatch=color.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(hexMatch)return{r:Number.parseInt(hexMatch[1],16),g:Number.parseInt(hexMatch[2],16),b:Number.parseInt(hexMatch[3],16)};let rgbMatch=color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/);if(rgbMatch)return{r:Number.parseInt(rgbMatch[1],10),g:Number.parseInt(rgbMatch[2],10),b:Number.parseInt(rgbMatch[3],10)}}function getLuminance(r,g2,b2){let toLinear=c2=>{let s=c2/255;return s<=.03928?s/12.92:((s+.055)/1.055)**2.4};return .2126*toLinear(r)+.7152*toLinear(g2)+.0722*toLinear(b2)}function adjustBrightness(color,factor){let parsed=parseColor(color);if(!parsed)return color;let adjust=c2=>Math.min(255,Math.max(0,Math.round(c2*factor)));return`rgb(${adjust(parsed.r)}, ${adjust(parsed.g)}, ${adjust(parsed.b)})`}function deriveExportColors(baseColor){let parsed=parseColor(baseColor);return parsed?getLuminance(parsed.r,parsed.g,parsed.b)>.5?{pageBg:adjustBrightness(baseColor,.96),cardBg:baseColor,infoBg:`rgb(${Math.min(255,parsed.r+10)}, ${Math.min(255,parsed.g+5)}, ${Math.max(0,parsed.b-20)})`}:{pageBg:adjustBrightness(baseColor,.7),cardBg:adjustBrightness(baseColor,.85),infoBg:`rgb(${Math.min(255,parsed.r+20)}, ${Math.min(255,parsed.g+15)}, ${parsed.b})`}:{pageBg:"rgb(24, 24, 30)",cardBg:"rgb(30, 30, 36)",infoBg:"rgb(60, 55, 40)"}}function generateThemeVars(themeName){let colors=getResolvedThemeColors(themeName),lines=[];for(let[key,value]of Object.entries(colors))lines.push(`--${key}: ${value};`);let themeExport=getThemeExportColors(themeName),userMessageBg=colors.userMessageBg||"#343541",derivedColors=deriveExportColors(userMessageBg);return lines.push(`--exportPageBg: ${themeExport.pageBg??derivedColors.pageBg};`),lines.push(`--exportCardBg: ${themeExport.cardBg??derivedColors.cardBg};`),lines.push(`--exportInfoBg: ${themeExport.infoBg??derivedColors.infoBg};`),lines.join(`
|
|
984
984
|
`)}function generateHtml(sessionData,themeName){let templateDir=getExportTemplateDir(),template=readFileSync9(join36(templateDir,"template.html"),"utf-8"),templateCss=readFileSync9(join36(templateDir,"template.css"),"utf-8"),templateJs=readFileSync9(join36(templateDir,"template.js"),"utf-8"),markedJs=readFileSync9(join36(templateDir,"vendor","marked.min.js"),"utf-8"),hljsJs=readFileSync9(join36(templateDir,"vendor","highlight.min.js"),"utf-8"),themeVars=generateThemeVars(themeName),colors=getResolvedThemeColors(themeName),themeExport=getThemeExportColors(themeName),derivedExportColors=deriveExportColors(colors.userMessageBg||"#343541"),bodyBg=themeExport.pageBg??derivedExportColors.pageBg,containerBg=themeExport.cardBg??derivedExportColors.cardBg,infoBg=themeExport.infoBg??derivedExportColors.infoBg,sessionDataBase64=Buffer.from(JSON.stringify(sessionData)).toString("base64"),css=templateCss.replace("{{THEME_VARS}}",themeVars).replace("{{BODY_BG}}",bodyBg).replace("{{CONTAINER_BG}}",containerBg).replace("{{INFO_BG}}",infoBg);return template.replace("{{CSS}}",css).replace("{{JS}}",templateJs).replace("{{SESSION_DATA}}",sessionDataBase64).replace("{{MARKED_JS}}",markedJs).replace("{{HIGHLIGHT_JS}}",hljsJs)}var TEMPLATE_RENDERED_TOOLS=new Set(["bash","read","write","edit","ls"]);function preRenderCustomTools(entries,toolRenderer){let renderedTools={};for(let entry of entries){if(entry.type!=="message")continue;let msg=entry.message;if(msg.role==="assistant"&&Array.isArray(msg.content)){for(let block of msg.content)if(block.type==="toolCall"&&!TEMPLATE_RENDERED_TOOLS.has(block.name)){let callHtml=toolRenderer.renderCall(block.id,block.name,block.arguments);callHtml&&(renderedTools[block.id]={callHtml})}}if(msg.role==="toolResult"&&msg.toolCallId){let toolName=msg.toolName||"",existing=renderedTools[msg.toolCallId];if(existing||!TEMPLATE_RENDERED_TOOLS.has(toolName)){let rendered=toolRenderer.renderResult(msg.toolCallId,toolName,msg.content,msg.details,msg.isError||!1);rendered&&(renderedTools[msg.toolCallId]={...existing,resultHtmlCollapsed:rendered.collapsed,resultHtmlExpanded:rendered.expanded})}}}return renderedTools}async function exportSessionToHtml(sm,state2,options){let opts=typeof options=="string"?{outputPath:options}:options||{},sessionFile=sm.getSessionFile();if(!sessionFile)throw new Error("Cannot export in-memory session to HTML");if(!existsSync10(sessionFile))throw new Error("Nothing to export yet - start a conversation first");let entries=sm.getEntries(),renderedTools;opts.toolRenderer&&(renderedTools=preRenderCustomTools(entries,opts.toolRenderer),Object.keys(renderedTools).length===0&&(renderedTools=void 0));let sessionData={header:sm.getHeader(),entries,leafId:sm.getLeafId(),systemPrompt:state2?.systemPrompt,tools:state2?.tools?.map(t=>({name:t.name,description:t.description,parameters:t.parameters})),renderedTools},html=generateHtml(sessionData,opts.themeName),outputPath=opts.outputPath?normalizePath(opts.outputPath):void 0;if(!outputPath){let sessionBasename=basename8(sessionFile,".jsonl");outputPath=`${APP_NAME}-session-${sessionBasename}.html`}return writeFileSync7(outputPath,html,"utf8"),outputPath}async function exportFromFile(inputPath,options){let opts=typeof options=="string"?{outputPath:options}:options||{},resolvedInputPath=resolvePath(inputPath);if(!existsSync10(resolvedInputPath))throw new Error(`File not found: ${resolvedInputPath}`);let sm=SessionManager.open(resolvedInputPath),sessionData={header:sm.getHeader(),entries:sm.getEntries(),leafId:sm.getLeafId(),systemPrompt:void 0,tools:void 0},html=generateHtml(sessionData,opts.themeName),outputPath=opts.outputPath?normalizePath(opts.outputPath):void 0;if(!outputPath){let inputBasename=basename8(resolvedInputPath,".jsonl");outputPath=`${APP_NAME}-session-${inputBasename}.html`}return writeFileSync7(outputPath,html,"utf8"),outputPath}var ANSI_COLORS=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff"];function color256ToHex(index3){if(index3<16)return ANSI_COLORS[index3];if(index3<232){let cubeIndex=index3-16,r=Math.floor(cubeIndex/36),g2=Math.floor(cubeIndex%36/6),b2=cubeIndex%6,toComponent=n=>n===0?0:55+n*40,toHex=n=>toComponent(n).toString(16).padStart(2,"0");return`#${toHex(r)}${toHex(g2)}${toHex(b2)}`}let grayHex=(8+(index3-232)*10).toString(16).padStart(2,"0");return`#${grayHex}${grayHex}${grayHex}`}function escapeHtml(text){return text.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function createEmptyStyle(){return{fg:null,bg:null,bold:!1,dim:!1,italic:!1,underline:!1}}function styleToInlineCSS(style){let parts=[];return style.fg&&parts.push(`color:${style.fg}`),style.bg&&parts.push(`background-color:${style.bg}`),style.bold&&parts.push("font-weight:bold"),style.dim&&parts.push("opacity:0.6"),style.italic&&parts.push("font-style:italic"),style.underline&&parts.push("text-decoration:underline"),parts.join(";")}function hasStyle(style){return style.fg!==null||style.bg!==null||style.bold||style.dim||style.italic||style.underline}function applySgrCode(params,style){let i=0;for(;i<params.length;){let code=params[i];if(code===0)style.fg=null,style.bg=null,style.bold=!1,style.dim=!1,style.italic=!1,style.underline=!1;else if(code===1)style.bold=!0;else if(code===2)style.dim=!0;else if(code===3)style.italic=!0;else if(code===4)style.underline=!0;else if(code===22)style.bold=!1,style.dim=!1;else if(code===23)style.italic=!1;else if(code===24)style.underline=!1;else if(code>=30&&code<=37)style.fg=ANSI_COLORS[code-30];else if(code===38){if(params[i+1]===5&¶ms.length>i+2)style.fg=color256ToHex(params[i+2]),i+=2;else if(params[i+1]===2&¶ms.length>i+4){let r=params[i+2],g2=params[i+3],b2=params[i+4];style.fg=`rgb(${r},${g2},${b2})`,i+=4}}else if(code===39)style.fg=null;else if(code>=40&&code<=47)style.bg=ANSI_COLORS[code-40];else if(code===48){if(params[i+1]===5&¶ms.length>i+2)style.bg=color256ToHex(params[i+2]),i+=2;else if(params[i+1]===2&¶ms.length>i+4){let r=params[i+2],g2=params[i+3],b2=params[i+4];style.bg=`rgb(${r},${g2},${b2})`,i+=4}}else code===49?style.bg=null:code>=90&&code<=97?style.fg=ANSI_COLORS[code-90+8]:code>=100&&code<=107&&(style.bg=ANSI_COLORS[code-100+8]);i++}}var ANSI_REGEX=/\x1b\[([\d;]*)m/g;function ansiToHtml(text){let style=createEmptyStyle(),result="",lastIndex=0,inSpan=!1;ANSI_REGEX.lastIndex=0;let match2=ANSI_REGEX.exec(text);for(;match2!==null;){let beforeText=text.slice(lastIndex,match2.index);beforeText&&(result+=escapeHtml(beforeText));let paramStr=match2[1],params=paramStr?paramStr.split(";").map(p=>parseInt(p,10)||0):[0];inSpan&&(result+="</span>",inSpan=!1),applySgrCode(params,style),hasStyle(style)&&(result+=`<span style="${styleToInlineCSS(style)}">`,inSpan=!0),lastIndex=match2.index+match2[0].length,match2=ANSI_REGEX.exec(text)}let remainingText=text.slice(lastIndex);return remainingText&&(result+=escapeHtml(remainingText)),inSpan&&(result+="</span>"),result}function ansiLinesToHtml(lines){return lines.map(line=>`<div class="ansi-line">${ansiToHtml(line)||" "}</div>`).join("")}var ANSI_ESCAPE_REGEX=/\x1b\[[\d;]*m/g;function isBlankRenderedLine(line){return line.replace(ANSI_ESCAPE_REGEX,"").trim().length===0}function trimRenderedResultLines(lines){let start=0,end=lines.length;for(;start<end&&isBlankRenderedLine(lines[start]);)start++;for(;end>start&&isBlankRenderedLine(lines[end-1]);)end--;return lines.slice(start,end)}function createToolHtmlRenderer(deps){let{getToolDefinition:getToolDefinition2,theme:theme2,cwd,width=100}=deps,renderedCallComponents=new Map,renderedResultComponents=new Map,renderedStates=new Map,renderedArgs=new Map,getState=toolCallId=>{let state2=renderedStates.get(toolCallId);return state2||(state2={},renderedStates.set(toolCallId,state2)),state2},createRenderContext=(toolCallId,lastComponent,expanded,isPartial,isError)=>({args:renderedArgs.get(toolCallId),toolCallId,invalidate:()=>{},lastComponent,state:getState(toolCallId),cwd,executionStarted:!0,argsComplete:!0,isPartial,expanded,showImages:!1,isError});return{renderCall(toolCallId,toolName,args){try{renderedArgs.set(toolCallId,args);let toolDef=getToolDefinition2(toolName);if(!toolDef?.renderCall)return;let component=toolDef.renderCall(args,theme2,createRenderContext(toolCallId,renderedCallComponents.get(toolCallId),!1,!0,!1));renderedCallComponents.set(toolCallId,component);let lines=component.render(width);return ansiLinesToHtml(lines)}catch{return}},renderResult(toolCallId,toolName,result,details,isError){try{let toolDef=getToolDefinition2(toolName);if(!toolDef?.renderResult)return;let agentToolResult={content:result,details,isError},collapsedComponent=toolDef.renderResult(agentToolResult,{expanded:!1,isPartial:!1},theme2,createRenderContext(toolCallId,renderedResultComponents.get(toolCallId),!1,!1,isError));renderedResultComponents.set(toolCallId,collapsedComponent);let collapsed=ansiLinesToHtml(trimRenderedResultLines(collapsedComponent.render(width))),expandedComponent=toolDef.renderResult(agentToolResult,{expanded:!0,isPartial:!1},theme2,createRenderContext(toolCallId,renderedResultComponents.get(toolCallId),!0,!1,isError));renderedResultComponents.set(toolCallId,expandedComponent);let expanded=ansiLinesToHtml(trimRenderedResultLines(expandedComponent.render(width)));return{...collapsed&&collapsed!==expanded?{collapsed}:{},expanded}}catch{return}}}}import{existsSync as existsSync11,mkdirSync as mkdirSync9,writeFileSync as writeFileSync8}from"node:fs";import{dirname as dirname18}from"node:path";function serializeSessionBranch(sessionManager,header,createTrailingEntries){let lines=[JSON.stringify(header)],parentId=null;for(let entry of sessionManager.getBranch())lines.push(JSON.stringify({...entry,parentId})),parentId=entry.id;for(let entry of createTrailingEntries?.(parentId,header.timestamp)??[])lines.push(JSON.stringify(entry));return`${lines.join(`
|
|
985
985
|
`)}
|
|
986
986
|
`}function createSessionJsonlArtifact(sessionManager){let header=sessionManager.getHeader();if(!header)throw new Error("Cannot export a session without a session header");return{version:1,format:"jsonl",mediaType:"application/x-ndjson",fileName:`session-${header.id}.jsonl`,bytes:new TextEncoder().encode(serializeSessionBranch(sessionManager,{...header}))}}function exportSessionToJsonl(sessionManager,outputPath,createTrailingEntries){let filePath=resolvePath(outputPath??`session-${new Date().toISOString().replace(/[:.]/g,"-")}.jsonl`,process.cwd()),dir=dirname18(filePath);existsSync11(dir)||mkdirSync9(dir,{recursive:!0});let timestamp=new Date().toISOString(),header={type:"session",version:CURRENT_SESSION_VERSION,id:sessionManager.getSessionId(),timestamp,cwd:sessionManager.getCwd()};return writeFileSync8(filePath,serializeSessionBranch(sessionManager,header,createTrailingEntries)),filePath}function createUsageTotals(){return{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0}}function addUsageToTotals(totals,usage){totals.input+=usage.input,totals.output+=usage.output,totals.cacheRead+=usage.cacheRead,totals.cacheWrite+=usage.cacheWrite,totals.cost+=usage.cost.total}function getUsageCostBreakdown(entries){let totalsByKey=new Map;for(let entry of entries){let key,usage;if(entry.type==="message"&&entry.message.role==="assistant"?(key=`${entry.message.provider}/${entry.message.responseModel??entry.message.model}`,usage=entry.message.usage):entry.type==="message"&&entry.message.role==="toolResult"&&entry.message.usage?(key="Tools/summaries",usage=entry.message.usage):(entry.type==="branch_summary"||entry.type==="compaction")&&entry.usage&&(key="Tools/summaries",usage=entry.usage),!key||!usage)continue;let totals=totalsByKey.get(key);totals||(totals=createUsageTotals(),totalsByKey.set(key,totals)),addUsageToTotals(totals,usage)}return Array.from(totalsByKey,([key,totals])=>({key,cost:totals.cost,tokens:totals.input+totals.output+totals.cacheRead+totals.cacheWrite,totals})).filter(entry=>entry.cost>0||entry.tokens>0).sort((a,b2)=>b2.cost-a.cost)}function getUserMessagesForForking(session){let entries=session.sessionManager.getEntries(),result=[];for(let entry of entries){if(entry.type!=="message"||entry.message.role!=="user")continue;let text=contentText(entry.message.content,"");text&&result.push({entryId:entry.id,text})}return result}function getSessionStats(session){let userMessages=0,assistantMessages=0,toolResults=0,totalMessages=0,toolCalls=0,usageTotals=createUsageTotals();for(let entry of session.sessionManager.getEntries()){if((entry.type==="branch_summary"||entry.type==="compaction")&&entry.usage&&addUsageToTotals(usageTotals,entry.usage),entry.type!=="message")continue;totalMessages++;let message=entry.message;if(message.role==="user")userMessages++;else if(message.role==="toolResult")toolResults++,message.usage&&addUsageToTotals(usageTotals,message.usage);else if(message.role==="assistant"){assistantMessages++;let assistantMsg=message;Array.isArray(assistantMsg.content)&&(toolCalls+=assistantMsg.content.filter(c2=>c2.type==="toolCall").length),addUsageToTotals(usageTotals,assistantMsg.usage)}}return{sessionFile:session.sessionFile,sessionId:session.sessionId,userMessages,assistantMessages,toolCalls,toolResults,totalMessages,tokens:{input:usageTotals.input,output:usageTotals.output,cacheRead:usageTotals.cacheRead,cacheWrite:usageTotals.cacheWrite,total:usageTotals.input+usageTotals.output+usageTotals.cacheRead+usageTotals.cacheWrite},cost:usageTotals.cost,contextUsage:session.getContextUsage()}}function getContextUsage(session){let model=session.model;if(!model)return;let contextWindow=model.contextWindow??0;if(contextWindow<=0)return;let branchEntries=session.sessionManager.getBranch(),latestCompaction=getLatestCompactionEntry(branchEntries);if(latestCompaction){let compactionIndex=branchEntries.lastIndexOf(latestCompaction),hasPostCompactionUsage=!1;for(let i=branchEntries.length-1;i>compactionIndex;i--){let entry=branchEntries[i];if(entry.type==="message"&&entry.message.role==="assistant"){let assistant=entry.message;if(assistant.stopReason!=="aborted"&&assistant.stopReason!=="error"&&calculateContextTokens2(assistant.usage)>0){hasPostCompactionUsage=!0;break}}}if(!hasPostCompactionUsage)return{tokens:null,contextWindow,percent:null}}let estimate=estimateContextTokens2(session.messages),percent=estimate.tokens/contextWindow*100;return{tokens:estimate.tokens,contextWindow,percent}}async function exportToHtml(session,outputPath,options={}){let themeName=[options.themeName,session.settingsManager.getTheme()].find(candidate=>candidate!==void 0&&getThemeByName(candidate)!==void 0),toolRenderer=createToolHtmlRenderer({getToolDefinition:name=>session.getToolDefinition(name),theme,cwd:session.sessionManager.getCwd()});return await exportSessionToHtml(session.sessionManager,session.agent.state,{outputPath,themeName,toolRenderer})}function exportToJsonl(session,outputPath){return exportSessionToJsonl(session.sessionManager,outputPath)}function getLastAssistantText(session){let lastAssistant=session.messages.slice().reverse().find(m2=>{if(m2.role!=="assistant")return!1;let msg=m2;return!(msg.stopReason==="aborted"&&msg.content.length===0)});if(!lastAssistant)return;let text="";for(let content of lastAssistant.content)content.type==="text"&&(text+=content.text);return text.trim()||void 0}function sleep3(ms,signal){return new Promise((resolve25,reject2)=>{if(signal?.aborted){reject2(new Error("Aborted"));return}let timeout=setTimeout(resolve25,ms);signal?.addEventListener("abort",()=>{clearTimeout(timeout),reject2(new Error("Aborted"))})})}async function willRetryAfterAgentEnd(session,event,signal){if(signal?.aborted)return session._pendingRetryDecision=void 0,!1;let settings2=session.settingsManager.getRetrySettings();if(session._retryAttempt>=settings2.maxRetries)return session._pendingRetryDecision=void 0,!1;for(let i=event.messages.length-1;i>=0;i--){let message=event.messages[i];if(message.role==="assistant"){let assistantMessage=message;try{let decision=await decideRetry(session,assistantMessage,void 0,signal);return session._pendingRetryDecision={message:assistantMessage,decision},decision.retry}catch(error2){if(signal?.aborted)return session._pendingRetryDecision=void 0,!1;throw error2}}}return session._pendingRetryDecision=void 0,!1}async function isRetryableError(session,message,execution,signal){if((await decideOverflow(session,message,execution,signal)).contextOverflow)return!1;let runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");return runtime.classifyRetry(session._retryPolicyName,{message,signal,context:{version:1,sessionId:session.sessionId,phase:"retry"},execution:execution??executionFacts(session,"retry")})}async function decideRetry(session,message,execution,signal){let settings2=session.settingsManager.getRetrySettings(),runtime=session._capabilityRuntime;if(!runtime)throw new Error("Capability runtime is not available");return runtime.decideRetry(session._retryPolicyName,{retryable:await session._isRetryableError(message,execution,signal),enabled:settings2.enabled,attempt:session._retryAttempt+1,maxAttempts:settings2.maxRetries,baseDelayMs:settings2.baseDelayMs,errorMessage:message.errorMessage,signal,context:{version:1,sessionId:session.sessionId,phase:"retry"},execution:execution??executionFacts(session,"retry")})}async function prepareRetry(session,message,precomputedDecision){let settings2=session.settingsManager.getRetrySettings(),decision=precomputedDecision??await decideRetry(session,message);if(!decision.retry)return!1;session._retryAttempt++;let baseDelayMs=Math.min(decision.delayMs??retryDelayMs(settings2,session._retryAttempt),settings2.maxAgentDelayMs),delayMs=Math.round(baseDelayMs*(.9+Math.random()*.2));session._retryAbortController=new AbortController,session._emit({type:"auto_retry_start",attempt:session._retryAttempt,maxAttempts:settings2.maxRetries,delayMs,errorMessage:message.errorMessage||"Unknown error"}),await dispatchAutoRetryLifecycle(session,{attempt:session._retryAttempt,maxAttempts:settings2.maxRetries,delayMs,errorMessage:message.errorMessage||"Unknown error"});let messages=session.agent.state.messages;messages.length>0&&messages[messages.length-1].role==="assistant"&&await session._applyContextTransition(messages.slice(0,-1),"retry");try{await sleep3(delayMs,session._retryAbortController.signal)}catch{let attempt2=session._retryAttempt;return session._retryAttempt=0,session._emit({type:"auto_retry_end",success:!1,attempt:attempt2,finalError:"Retry cancelled"}),!1}finally{session._retryAbortController=void 0}return!0}function buildSystemPrompt(options){let{customPrompt,orientationPrompt,preferenceCard,selectedTools,toolSnippets,promptGuidelines,appendSystemPrompt,cwd,contextFiles:providedContextFiles,skills:providedSkills}=options,promptCwd=cwd.replace(/\\/g,"/"),appendSection=appendSystemPrompt?`
|
|
@@ -1374,7 +1374,7 @@ ${expandedBody}`,this.getStartupExpansionState(),0,0);this.loadedResourcesContai
|
|
|
1374
1374
|
${warningLines}`,0,0)),this.loadedResourcesContainer.addChild(new Spacer(1))}let promptDiagnostics=promptsResult.diagnostics;if(promptDiagnostics.length>0){let warningLines=this.formatDiagnostics(promptDiagnostics,sourceInfos);this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning","[Prompt conflicts]")}
|
|
1375
1375
|
${warningLines}`,0,0)),this.loadedResourcesContainer.addChild(new Spacer(1))}let themeDiagnostics=themesResult.diagnostics;if(themeDiagnostics.length>0){let warningLines=this.formatDiagnostics(themeDiagnostics,sourceInfos);this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning","[Theme conflicts]")}
|
|
1376
1376
|
${warningLines}`,0,0)),this.loadedResourcesContainer.addChild(new Spacer(1))}}}async bindCurrentSessionExtensions(){await this.session.startSession(),setRegisteredThemes(buildRegisteredThemes(this.facade.getThemes().themes)),this.setupAutocompleteProvider(),this.showLoadedResources({force:!1,showDiagnosticsWhenQuiet:!0}),this.showStartupNoticesIfNeeded()}applyFullscreenScrollbarSetting(){this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar())}applyRuntimeSettings(){setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides()),configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs()),this.applyFullscreenScrollbarSetting(),this.renderer instanceof TuiAltScreen&&this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect()),this.footer.setSession(this.session),this.footer.setAutoCompactEnabled(this.facade.isAutoCompactionEnabled()),this.footerDataProvider.setCwd(this.facade.getCwd()),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());let clearOnShrink=this.settingsManager.getClearOnShrink();this.ui.setClearOnShrink(clearOnShrink),!clearOnShrink&&!this.activeStatusIndicator&&this.statusContainer.clear();let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor.setPaddingX(editorPaddingX),this.defaultEditor.setAutocompleteMaxVisible(autocompleteMaxVisible),this.editor!==this.defaultEditor&&(this.editor.setPaddingX?.(editorPaddingX),this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible))}async rebindCurrentSession(options={}){let session=this.session;this.unsubscribe?.(),this.unsubscribe=void 0,this.applyRuntimeSettings(),options.renderBeforeBind&&(this.renderCurrentSessionState(),this.subscribeToAgent()),await this.bindCurrentSessionExtensions(),this.session===session&&(options.renderBeforeBind||this.subscribeToAgent(),await this.updateAvailableProviderCount(),this.updateEditorBorderColor(),this.updateTerminalTitle())}async handleFatalRuntimeError(prefix,error2){let message=error2 instanceof Error?error2.message:String(error2);this.showError(`${prefix}: ${message}`),stopThemeWatcher(),this.stop("transcript"),process.exit(1)}renderCurrentSessionState(){this.loadedResourcesContainer.clear(),this.chatContainer.clear(),this.pendingMessagesContainer.clear(),this.compactionQueuedMessages=[],this.streamingComponent=void 0,this.streamingMessage=void 0,this.pendingTools.clear(),this.renderInitialMessages()}getRegisteredToolDefinition(toolName){return this.facade.getToolDefinition(toolName)}getMarkdownTransformers(){return[this.mermaidMarkdownTransformer]}showStatusIndicator(indicator){this.activeStatusIndicator?.dispose(),this.activeStatusIndicator=indicator,this.statusContainer.clear(),this.statusContainer.addChild(indicator)}clearStatusIndicator(kind){if(kind&&this.activeStatusIndicator?.kind!==kind)return;let hadActiveStatusIndicator=this.activeStatusIndicator!==void 0;this.activeStatusIndicator?.dispose(),this.activeStatusIndicator=void 0,this.statusContainer.clear(),hadActiveStatusIndicator&&this.options.tuiMode==="regular"&&this.ui.getClearOnShrink()&&this.statusContainer.addChild(this.idleStatus)}showWorkingStatusIndicator(){this.showStatusIndicator(new WorkingStatusIndicator(this.ui,this.workingMessage??this.defaultWorkingMessage,this.workingIndicatorOptions))}setWorkingVisible(visible){if(this.workingVisible=visible,!visible){this.clearStatusIndicator("working"),this.ui.requestRender();return}this.facade.isStreaming()&&this.activeStatusIndicator?.kind!=="working"&&this.showWorkingStatusIndicator(),this.ui.requestRender()}setWorkingIndicator(options){this.workingIndicatorOptions=options,this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setIndicator(options),this.ui.requestRender()}setHiddenThinkingLabel(label){this.hiddenThinkingLabel=label??this.defaultHiddenThinkingLabel;for(let child of this.chatContainer.children)child instanceof AssistantMessageComponent&&child.setHiddenThinkingLabel(this.hiddenThinkingLabel);this.streamingComponent&&this.streamingComponent.setHiddenThinkingLabel(this.hiddenThinkingLabel),this.ui.requestRender()}setWorkingMessage(message){this.workingMessage=message,this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setMessage(message??this.defaultWorkingMessage)}resetDialogUI(){this.dialogSelector&&this.hideDialogSelector(),this.dialogInput&&this.hideDialogInput(),this.dialogEditor&&this.hideDialogEditor(),this.ui.hideOverlay(),this.footer.invalidate(),this.setupAutocompleteProvider(),this.updateTerminalTitle(),this.workingMessage=void 0,this.workingVisible=!0,this.setWorkingIndicator(),this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`),this.setHiddenThinkingLabel()}applyExtensionTheme(themeOrName){if(themeOrName instanceof Theme)return this.themeController.setThemeInstance(themeOrName);let result=this.themeController.setThemeName(themeOrName);return result.success&&this.settingsManager.getTheme()!==themeOrName&&this.settingsManager.setTheme(themeOrName),result}createInteractionHostV1(){return createInteractionHostV1(this)}showDialogSelector(title,options,opts){return showDialogSelector(this,title,options,opts)}hideDialogSelector(){hideDialogSelector(this)}async showDialogConfirm(title,message,opts){return showDialogConfirm(this,title,message,opts)}async promptForMissingSessionCwd(error2){return await this.showDialogConfirm("Session cwd not found",formatMissingSessionCwdPrompt(error2.issue))?error2.issue.fallbackCwd:void 0}showDialogInput(title,placeholder,opts){return showDialogInput(this,title,placeholder,opts)}hideDialogInput(){hideDialogInput(this)}showDialogEditor(title,prefill){return showDialogEditor(this,title,prefill)}getExternalEditorCommand(){return this.settingsManager.getExternalEditorCommand()}hideDialogEditor(){hideDialogEditor(this)}showDialogNotify(message,type){showDialogNotify(this,message,type)}setupKeyHandlers(){this.defaultEditor.onEscape=()=>{if(this.facade.isStreaming())this.restoreQueuedMessagesToEditor({abort:!0});else if(this.facade.isBashRunning())this.facade.abortBash();else if(this.isBashMode)this.editor.setText(""),this.isBashMode=!1,this.updateEditorBorderColor();else if(!this.editor.getText().trim()){let action=this.settingsManager.getDoubleEscapeAction();if(action!=="none"){let now=Date.now();now-this.lastEscapeTime<500?(action==="tree"?this.showTreeSelector():this.showUserMessageSelector(),this.lastEscapeTime=0):this.lastEscapeTime=now}}},this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onAction("app.suspend",()=>this.handleCtrlZ()),this.defaultEditor.onAction("app.thinking.cycle",()=>this.cycleThinkingLevel()),this.defaultEditor.onAction("app.model.cycleForward",()=>this.cycleModel("forward")),this.defaultEditor.onAction("app.model.cycleBackward",()=>this.cycleModel("backward")),this.ui.onDebug=()=>this.handleDebugCommand(),this.defaultEditor.onAction("app.model.select",()=>this.showModelSelector()),this.defaultEditor.onAction("app.tools.expand",()=>this.toggleToolOutputExpansion()),this.defaultEditor.onAction("app.thinking.toggle",()=>this.toggleThinkingBlockVisibility()),this.defaultEditor.onAction("app.editor.external",()=>{this.handleOpenExternalEditor()}),this.defaultEditor.onAction("app.message.copy",()=>{this.handleCopyCommand({flashConfirmation:!0,preferSelection:!0})}),this.defaultEditor.onAction("app.message.followUp",()=>this.handleFollowUp()),this.defaultEditor.onAction("app.message.dequeue",()=>this.handleDequeue()),this.defaultEditor.onAction("app.session.new",()=>this.handleClearCommand()),this.defaultEditor.onAction("app.session.tree",()=>this.showTreeSelector()),this.defaultEditor.onAction("app.session.fork",()=>this.showUserMessageSelector()),this.defaultEditor.onAction("app.session.resume",()=>this.showSessionSelector()),this.defaultEditor.onChange=text=>{let wasBashMode=this.isBashMode;this.isBashMode=text.trimStart().startsWith("!"),wasBashMode!==this.isBashMode&&this.updateEditorBorderColor()},this.defaultEditor.onPasteImage=()=>{this.handleClipboardPaste()}}async handleRightClickPaste(){let target=this.renderer.getFocusedComponent(),handleInput=target?.handleInput;if(!(!target||!handleInput))try{let text=await readClipboardText();if(!text||this.renderer.getFocusedComponent()!==target)return;handleInput.call(target,`\x1B[200~${text}\x1B[201~`),this.ui.requestRender()}catch{}}async handleClipboardPaste(){try{let image=await readClipboardImage();if(image){let tmpDir=os6.tmpdir(),ext2=extensionForImageMimeType(image.mimeType)??"png",fileName=`agent-forge-clipboard-${crypto.randomUUID()}.${ext2}`,filePath=path14.join(tmpDir,fileName);fs5.writeFileSync(filePath,Buffer.from(image.bytes)),this.editor.insertTextAtCursor?.(filePath),this.ui.requestRender();return}let text=await readClipboardText();text&&(this.editor.insertTextAtCursor?.(text),this.ui.requestRender())}catch{}}handleStartupSubmit(text){text.trim()&&(this.pendingUserInputs.push(text),this.showStatus("Startup in progress \u2014 input queued and will run when startup completes"))}setupEditorSubmitHandler(){this.defaultEditor.onSubmit=async rawText=>{let text=rawText.trim();if(text&&!await this.dispatchCommandOrBash(text)){if(this.facade.isCompacting()){this.queueCompactionMessage(text,"steer");return}if(this.facade.isStreaming()){this.editor.addToHistory?.(text),this.editor.setText(""),await this.facade.prompt(text,{streamingBehavior:"steer"}),this.updatePendingMessagesDisplay(),this.ui.requestRender();return}this.flushPendingBashComponents(),this.onInputCallback?this.onInputCallback(text):this.pendingUserInputs.push(text),this.editor.addToHistory?.(text)}}}async dispatchCommandOrBash(text){let dispatched=this.dispatchEditorCommand(text);if(dispatched)return dispatched.pending&&await dispatched.pending,!0;if(text.startsWith("!")){let isExcluded=text.startsWith("!!"),command=isExcluded?text.slice(2).trim():text.slice(1).trim();if(command)return this.facade.isBashRunning()?(this.showWarning("A bash command is already running. Press Esc to cancel it first."),this.editor.setText(text),!0):(this.editor.addToHistory?.(text),await this.handleBashCommand(command,isExcluded),this.isBashMode=!1,this.updateEditorBorderColor(),!0)}return!1}dispatchEditorCommand(text){let match2=matchCommandDispatchEntry(COMMAND_DISPATCH_ENTRIES,text);if(!match2)return;let{entry,arg}=match2;entry.clearEditorBeforeRun&&this.setEditorText("");let result=entry.run(this,text,arg);return result instanceof Promise?{pending:entry.clearEditorBeforeRun?result:result.then(()=>this.setEditorText(""))}:(entry.clearEditorBeforeRun||this.setEditorText(""),{pending:void 0})}setEditorText(text){this.editor.setText(text)}subscribeToAgent(){this.unsubscribe=this.facade.subscribe(async event=>{await this.handleEvent(event)})}async handleEvent(event){switch(this.isInitialized||await this.init(),this.footer.invalidate(),event.type){case"agent_start":this.pendingTools.clear(),this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0);break;case"turn_start":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.workingVisible?this.activeStatusIndicator?.kind!=="working"&&this.showWorkingStatusIndicator():this.clearStatusIndicator(),this.ui.requestRender();break;case"queue_update":this.updatePendingMessagesDisplay(),this.ui.requestRender();break;case"entry_appended":break;case"session_info_changed":this.updateTerminalTitle(),this.footer.invalidate(),this.ui.requestRender();break;case"thinking_level_changed":this.footer.invalidate(),this.updateEditorBorderColor();break;case"message_start":event.message.role==="custom"?(this.addMessageToChat(event.message),this.ui.requestRender()):event.message.role==="user"?(this.addMessageToChat(event.message),this.updatePendingMessagesDisplay(),this.ui.requestRender()):event.message.role==="assistant"&&(this.streamingComponent=new AssistantMessageComponent(void 0,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.hiddenThinkingLabel,this.outputPad,this.getMarkdownTransformers()),this.streamingMessage=event.message,this.chatContainer.addChild(this.streamingComponent),this.streamingComponent.updateContent(this.streamingMessage,!0),this.ui.requestRender());break;case"message_update":if(this.streamingComponent&&event.message.role==="assistant"){this.streamingMessage=event.message,this.streamingComponent.updateContent(this.streamingMessage,!0);for(let content of this.streamingMessage.content)if(content.type==="toolCall")if(this.pendingTools.has(content.id)){let component=this.pendingTools.get(content.id);component&&component.updateArgs(content.arguments)}else{let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells()},this.getRegisteredToolDefinition(content.name),this.ui,this.facade.getCwd());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),this.pendingTools.set(content.id,component)}this.ui.requestRender()}break;case"message_end":if(event.message.role==="user")break;if(this.streamingComponent&&event.message.role==="assistant"){this.streamingMessage=event.message;let errorMessage2;if(this.streamingMessage.stopReason==="aborted"){let retryAttempt=this.facade.getRetryAttempt();errorMessage2=retryAttempt>0?`Aborted after ${retryAttempt} retry attempt${retryAttempt>1?"s":""}`:"Operation aborted",this.streamingMessage.errorMessage=errorMessage2}if(this.streamingComponent.updateContent(this.streamingMessage,!1),this.streamingMessage.stopReason==="aborted"||this.streamingMessage.stopReason==="error"){errorMessage2||(errorMessage2=this.streamingMessage.errorMessage||"Error");for(let[,component]of this.pendingTools.entries())component.updateResult({content:[{type:"text",text:errorMessage2}],isError:!0});this.pendingTools.clear()}else{for(let[,component]of this.pendingTools.entries())component.setArgsComplete();this.maybeShowAssistantDiagnostics(this.streamingMessage),this.maybeShowCacheMissNotice(this.streamingMessage)}this.streamingComponent=void 0,this.streamingMessage=void 0,this.footer.invalidate()}this.ui.requestRender();break;case"bash_execution_update":break;case"tool_execution_start":{let component=this.pendingTools.get(event.toolCallId);component||(component=new ToolExecutionComponent(event.toolName,event.toolCallId,event.args,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells()},this.getRegisteredToolDefinition(event.toolName),this.ui,this.facade.getCwd()),component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),this.pendingTools.set(event.toolCallId,component)),component.markExecutionStarted(),this.ui.requestRender();break}case"tool_execution_update":{let component=this.pendingTools.get(event.toolCallId);component&&(component.updateResult({...event.partialResult,isError:!1},!0),this.ui.requestRender());break}case"tool_execution_end":{let component=this.pendingTools.get(event.toolCallId);component&&(component.updateResult({...event.result,isError:event.isError}),this.pendingTools.delete(event.toolCallId),this.ui.requestRender());break}case"capability_command_result":{let links=event.result.links?.map(link=>`${link.label}: ${link.url}`)??[],message=[event.result.message,...links].filter(Boolean).join(`
|
|
1377
|
-
`);event.result.status==="error"?this.showError(message):this.showStatus(message),this.ui.requestRender();break}case"agent_end":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.clearStatusIndicator("working"),this.streamingComponent&&(this.chatContainer.removeChild(this.streamingComponent),this.streamingComponent=void 0,this.streamingMessage=void 0),this.pendingTools.clear(),this.ui.requestRender();break;case"agent_settled":await this.checkShutdownRequested();break;case"compaction_start":{this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.autoCompactionEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.facade.abortCompaction()},this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason)),this.ui.requestRender();break}case"compaction_end":{if(this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.autoCompactionEscapeHandler&&(this.defaultEditor.onEscape=this.autoCompactionEscapeHandler,this.autoCompactionEscapeHandler=void 0),this.clearStatusIndicator("compaction"),event.aborted)event.reason==="manual"?this.showError("Compaction cancelled"):this.showStatus("Auto-compaction cancelled");else if(event.result){let entries=this.facade.getContextEntries();if(entries[0]?.type!=="compaction")throw new Error("Completed compaction is missing from the session context");this.chatContainer.clear(),this.renderSessionEntries(entries.slice(1)),this.addMessageToChat(createCompactionSummaryMessage2(event.result.summary,event.result.tokensBefore,new Date().toISOString())),event.result.usage&&this.addCompactionCostNotice({type:"compaction_cost",kind:"compaction",usage:event.result.usage}),this.footer.invalidate()}else event.errorMessage&&(event.reason==="manual"?this.showError(event.errorMessage):(this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("error",event.errorMessage),1,0))));this.flushCompactionQueue({willRetry:event.willRetry}),this.ui.requestRender();break}case"auto_retry_start":{this.retryEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.facade.abortRetry()},this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"auto_retry_end":{this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0),this.clearStatusIndicator("retry"),event.success||this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError||"Unknown error"}`),this.ui.requestRender();break}case"summarization_retry_scheduled":{this.showError(event.errorMessage),this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"summarization_retry_attempt_start":{this.clearStatusIndicator("retry"),event.source==="branchSummary"?this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui)):this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason)),this.ui.requestRender();break}case"summarization_retry_finished":{this.clearStatusIndicator("retry"),this.ui.requestRender();break}}}getUserMessageText(message){return message.role!=="user"?"":(typeof message.content=="string"?[{type:"text",text:message.content}]:message.content.filter(c2=>c2.type==="text")).map(c2=>c2.text).join("")}showManagedToolStatus(status2){this.managedToolStatusStarted||(this.chatContainer.addChild(new Spacer(1)),this.managedToolStatusStarted=!0);let message=status2.type==="warning"?`Warning: ${status2.message}`:status2.message,color=status2.type==="warning"?"warning":"dim";this.chatContainer.addChild(new Text(theme.fg(color,message),1,0)),this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.ui.requestRender()}showStatus(message){let children=this.chatContainer.children,last=children.length>0?children[children.length-1]:void 0,secondLast=children.length>1?children[children.length-2]:void 0;if(last&&secondLast&&last===this.lastStatusText&&secondLast===this.lastStatusSpacer){this.lastStatusText.setText(theme.fg("dim",message)),this.ui.requestRender();return}let spacer=new Spacer(1),text=new Text(theme.fg("dim",message),1,0);this.chatContainer.addChild(spacer),this.chatContainer.addChild(text),this.lastStatusSpacer=spacer,this.lastStatusText=text,this.ui.requestRender()}addMessageToChat(message,options){switch(message.role){case"bashExecution":{let component=new BashExecutionComponent(message.command,this.ui,message.excludeFromContext);message.output&&component.appendOutput(message.output),component.setComplete(message.exitCode,message.cancelled,message.truncated?{truncated:!0}:void 0,message.fullOutputPath),this.chatContainer.addChild(component);break}case"custom":{if(message.display){let component=new CustomMessageComponent(message,void 0,this.getMarkdownThemeWithSettings(),this.outputPad);component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component)}break}case"compactionSummary":{this.chatContainer.addChild(new Spacer(1));let component=new CompactionSummaryMessageComponent(message,this.getMarkdownThemeWithSettings());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"branchSummary":{this.chatContainer.addChild(new Spacer(1));let component=new BranchSummaryMessageComponent(message,this.getMarkdownThemeWithSettings());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"user":{let textContent=this.getUserMessageText(message);if(textContent){this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1));let skillBlock=parseSkillBlock(textContent);if(skillBlock){let component=new SkillInvocationMessageComponent(skillBlock,this.getMarkdownThemeWithSettings());if(component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),skillBlock.userMessage){this.chatContainer.addChild(new Spacer(1));let userComponent=new UserMessageComponent(skillBlock.userMessage,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}}else{let userComponent=new UserMessageComponent(textContent,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}options?.populateHistory&&this.editor.addToHistory?.(textContent)}break}case"assistant":{let assistantComponent=new AssistantMessageComponent(message,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.hiddenThinkingLabel,this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(assistantComponent);break}case"toolResult":break;default:{let _exhaustive=message}}}renderSessionItems(items,options={}){this.pendingTools.clear();let renderedPendingTools=new Map,cacheMisses=this.settingsManager.getShowCacheMissNotices()?collectCacheMisses(this.facade.getEntries(),this.facade.getModelPriceSource()):new Map;options.updateFooter&&(this.footer.invalidate(),this.updateEditorBorderColor());for(let item of items){if(isCustomSessionEntry(item))continue;if(isCompactionCostNotice(item)){this.addCompactionCostNotice(item);continue}let message=item;if(message.role==="assistant"){this.addMessageToChat(message);for(let content of message.content)if(content.type==="toolCall"){let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells()},this.getRegisteredToolDefinition(content.name),this.ui,this.facade.getCwd());if(component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),message.stopReason==="aborted"||message.stopReason==="error"){let errorMessage2;if(message.stopReason==="aborted"){let retryAttempt=this.facade.getRetryAttempt();errorMessage2=retryAttempt>0?`Aborted after ${retryAttempt} retry attempt${retryAttempt>1?"s":""}`:"Operation aborted"}else errorMessage2=message.errorMessage||"Error";component.updateResult({content:[{type:"text",text:errorMessage2}],isError:!0})}else renderedPendingTools.set(content.id,component)}if(message.stopReason!=="aborted"&&message.stopReason!=="error"){this.maybeShowAssistantDiagnostics(message);let miss=cacheMisses.get(message);miss&&this.addCacheMissNotice(miss)}}else if(message.role==="toolResult"){let component=renderedPendingTools.get(message.toolCallId);component&&(component.updateResult(message),renderedPendingTools.delete(message.toolCallId))}else this.addMessageToChat(message,options)}for(let[toolCallId,component]of renderedPendingTools)this.pendingTools.set(toolCallId,component);this.ui.requestRender()}renderSessionEntries(entries,options={}){let items=entries.flatMap(entry=>{if(entry.type==="custom")return[entry];let messages=sessionEntryToContextMessages(entry);return(entry.type==="compaction"||entry.type==="branch_summary")&&entry.usage&&messages.length>0?[...messages,{type:"compaction_cost",kind:entry.type,usage:entry.usage}]:messages});this.renderSessionItems(items,options)}addCompactionCostNotice(notice){if(!this.settingsManager.getShowCacheMissNotices())return;let{usage}=notice,tokens=usage.input+usage.output+usage.cacheRead+usage.cacheWrite,cost=usage.cost.total>=.01?` (~$${usage.cost.total.toFixed(2)})`:"",label=notice.kind==="compaction"?"Compaction":"Branch summary";this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`${label}: ${formatTokens(tokens)} tokens billed${cost}`),1,0))}maybeShowAssistantDiagnostics(message){if(this.settingsManager.getShowCacheMissNotices())for(let diagnostic5 of message.diagnostics??[]){if(diagnostic5.type!=="anthropic_input_transformations")continue;let transformations=diagnostic5.details?.transformations;if(!Array.isArray(transformations))continue;let dropped=transformations.flatMap(transformation=>{if(typeof transformation!="object"||transformation===null)return[];let details=transformation;if(details.type!=="thinking_dropped")return[];let reason=typeof details.reason=="string"?details.reason:"unknown reason",location=typeof details.path=="string"?` at ${details.path}`:"";return[`${reason}${location}`]});if(dropped.length===0)continue;let noun=dropped.length===1?"thinking block":`${dropped.length} thinking blocks`;this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`Anthropic dropped ${noun}: ${dropped.join("; ")}`),1,0))}}maybeShowCacheMissNotice(message){if(!this.settingsManager.getShowCacheMissNotices())return;let miss=detectCacheMiss(this.facade.getEntries(),message,this.facade.getModelPriceSource());miss&&this.addCacheMissNotice(miss)}addCacheMissNotice(miss){if(miss.missedTokens<2e4&&miss.missedCost<.1)return;let cost=miss.missedCost>=.01?` (~$${miss.missedCost.toFixed(2)})`:"",reBilled=`${formatTokens(miss.missedTokens)} tokens re-billed${cost}`,label="Cache miss";miss.modelChanged?label="Cache miss after model switch":miss.idleMs>=3e5&&(label=`Cache miss after ${Math.round(miss.idleMs/6e4)}m idle`);let text=theme.fg("warning",`${label}: ${reBilled}`);this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(text,1,0))}renderInitialMessages(){let entries=this.facade.getContextEntries();this.renderSessionEntries(entries,{updateFooter:!0,populateHistory:!0});let compactionCount=this.facade.getEntries().filter(e=>e.type==="compaction").length;if(compactionCount>0){let times=compactionCount===1?"1 time":`${compactionCount} times`;this.showStatus(`Session compacted ${times}`)}}async getUserInput(){let queuedInput=this.pendingUserInputs.shift();return queuedInput!==void 0?queuedInput:new Promise(resolve25=>{this.onInputCallback=text=>{this.onInputCallback=void 0,resolve25(text)}})}rebuildChatFromMessages(){this.chatContainer.clear(),this.renderSessionEntries(this.facade.getContextEntries())}handleCtrlC(){let now=Date.now();now-this.lastSigintTime<500?this.shutdown():(this.clearEditor(),this.lastSigintTime=now)}handleCtrlD(){this.shutdown()}isShuttingDown=!1;async shutdown(options){if(this.isShuttingDown)return;this.isShuttingDown=!0,options?.fromSignal&&(await this.runtimeFacade.dispose(),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),process.exit(0)),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),await this.runtimeFacade.dispose();let resumeCommand=formatResumeCommand(this.runtimeFacade);resumeCommand&&process.stdout.write(`${source_default.dim("To resume this session:")} ${resumeCommand}
|
|
1377
|
+
`);event.result.status==="error"?this.showError(message):this.showStatus(message),this.ui.requestRender();break}case"agent_end":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.clearStatusIndicator("working"),this.streamingComponent&&(this.chatContainer.removeChild(this.streamingComponent),this.streamingComponent=void 0,this.streamingMessage=void 0),this.pendingTools.clear(),this.ui.requestRender();break;case"agent_settled":await this.checkShutdownRequested();break;case"compaction_start":{this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.autoCompactionEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.facade.abortCompaction()},this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason)),this.ui.requestRender();break}case"compaction_end":{if(this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.autoCompactionEscapeHandler&&(this.defaultEditor.onEscape=this.autoCompactionEscapeHandler,this.autoCompactionEscapeHandler=void 0),this.clearStatusIndicator("compaction"),event.aborted)event.reason==="manual"?this.showError("Compaction cancelled"):this.showStatus("Auto-compaction cancelled");else if(event.result){let entries=this.facade.getContextEntries();if(entries[0]?.type!=="compaction")throw new Error("Completed compaction is missing from the session context");this.chatContainer.clear(),this.renderSessionEntries(entries.slice(1)),this.addMessageToChat(createCompactionSummaryMessage2(event.result.summary,event.result.tokensBefore,new Date().toISOString())),event.result.usage&&this.addCompactionCostNotice({type:"compaction_cost",kind:"compaction",usage:event.result.usage}),this.footer.invalidate()}else event.errorMessage&&(event.reason==="manual"?this.showError(event.errorMessage):(this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("error",event.errorMessage),1,0))));this.flushCompactionQueue({willRetry:event.willRetry}),this.ui.requestRender();break}case"compaction_skipped":{this.showStatus("Auto-compaction skipped: nothing to compact"),this.ui.requestRender();break}case"auto_retry_start":{this.retryEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.facade.abortRetry()},this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"auto_retry_end":{this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0),this.clearStatusIndicator("retry"),event.success||this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError||"Unknown error"}`),this.ui.requestRender();break}case"summarization_retry_scheduled":{this.showError(event.errorMessage),this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"summarization_retry_attempt_start":{this.clearStatusIndicator("retry"),event.source==="branchSummary"?this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui)):this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason)),this.ui.requestRender();break}case"summarization_retry_finished":{this.clearStatusIndicator("retry"),this.ui.requestRender();break}}}getUserMessageText(message){return message.role!=="user"?"":(typeof message.content=="string"?[{type:"text",text:message.content}]:message.content.filter(c2=>c2.type==="text")).map(c2=>c2.text).join("")}showManagedToolStatus(status2){this.managedToolStatusStarted||(this.chatContainer.addChild(new Spacer(1)),this.managedToolStatusStarted=!0);let message=status2.type==="warning"?`Warning: ${status2.message}`:status2.message,color=status2.type==="warning"?"warning":"dim";this.chatContainer.addChild(new Text(theme.fg(color,message),1,0)),this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.ui.requestRender()}showStatus(message){let children=this.chatContainer.children,last=children.length>0?children[children.length-1]:void 0,secondLast=children.length>1?children[children.length-2]:void 0;if(last&&secondLast&&last===this.lastStatusText&&secondLast===this.lastStatusSpacer){this.lastStatusText.setText(theme.fg("dim",message)),this.ui.requestRender();return}let spacer=new Spacer(1),text=new Text(theme.fg("dim",message),1,0);this.chatContainer.addChild(spacer),this.chatContainer.addChild(text),this.lastStatusSpacer=spacer,this.lastStatusText=text,this.ui.requestRender()}addMessageToChat(message,options){switch(message.role){case"bashExecution":{let component=new BashExecutionComponent(message.command,this.ui,message.excludeFromContext);message.output&&component.appendOutput(message.output),component.setComplete(message.exitCode,message.cancelled,message.truncated?{truncated:!0}:void 0,message.fullOutputPath),this.chatContainer.addChild(component);break}case"custom":{if(message.display){let component=new CustomMessageComponent(message,void 0,this.getMarkdownThemeWithSettings(),this.outputPad);component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component)}break}case"compactionSummary":{this.chatContainer.addChild(new Spacer(1));let component=new CompactionSummaryMessageComponent(message,this.getMarkdownThemeWithSettings());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"branchSummary":{this.chatContainer.addChild(new Spacer(1));let component=new BranchSummaryMessageComponent(message,this.getMarkdownThemeWithSettings());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"user":{let textContent=this.getUserMessageText(message);if(textContent){this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1));let skillBlock=parseSkillBlock(textContent);if(skillBlock){let component=new SkillInvocationMessageComponent(skillBlock,this.getMarkdownThemeWithSettings());if(component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),skillBlock.userMessage){this.chatContainer.addChild(new Spacer(1));let userComponent=new UserMessageComponent(skillBlock.userMessage,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}}else{let userComponent=new UserMessageComponent(textContent,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}options?.populateHistory&&this.editor.addToHistory?.(textContent)}break}case"assistant":{let assistantComponent=new AssistantMessageComponent(message,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.hiddenThinkingLabel,this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(assistantComponent);break}case"toolResult":break;default:{let _exhaustive=message}}}renderSessionItems(items,options={}){this.pendingTools.clear();let renderedPendingTools=new Map,cacheMisses=this.settingsManager.getShowCacheMissNotices()?collectCacheMisses(this.facade.getEntries(),this.facade.getModelPriceSource()):new Map;options.updateFooter&&(this.footer.invalidate(),this.updateEditorBorderColor());for(let item of items){if(isCustomSessionEntry(item))continue;if(isCompactionCostNotice(item)){this.addCompactionCostNotice(item);continue}let message=item;if(message.role==="assistant"){this.addMessageToChat(message);for(let content of message.content)if(content.type==="toolCall"){let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells()},this.getRegisteredToolDefinition(content.name),this.ui,this.facade.getCwd());if(component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),message.stopReason==="aborted"||message.stopReason==="error"){let errorMessage2;if(message.stopReason==="aborted"){let retryAttempt=this.facade.getRetryAttempt();errorMessage2=retryAttempt>0?`Aborted after ${retryAttempt} retry attempt${retryAttempt>1?"s":""}`:"Operation aborted"}else errorMessage2=message.errorMessage||"Error";component.updateResult({content:[{type:"text",text:errorMessage2}],isError:!0})}else renderedPendingTools.set(content.id,component)}if(message.stopReason!=="aborted"&&message.stopReason!=="error"){this.maybeShowAssistantDiagnostics(message);let miss=cacheMisses.get(message);miss&&this.addCacheMissNotice(miss)}}else if(message.role==="toolResult"){let component=renderedPendingTools.get(message.toolCallId);component&&(component.updateResult(message),renderedPendingTools.delete(message.toolCallId))}else this.addMessageToChat(message,options)}for(let[toolCallId,component]of renderedPendingTools)this.pendingTools.set(toolCallId,component);this.ui.requestRender()}renderSessionEntries(entries,options={}){let items=entries.flatMap(entry=>{if(entry.type==="custom")return[entry];let messages=sessionEntryToContextMessages(entry);return(entry.type==="compaction"||entry.type==="branch_summary")&&entry.usage&&messages.length>0?[...messages,{type:"compaction_cost",kind:entry.type,usage:entry.usage}]:messages});this.renderSessionItems(items,options)}addCompactionCostNotice(notice){if(!this.settingsManager.getShowCacheMissNotices())return;let{usage}=notice,tokens=usage.input+usage.output+usage.cacheRead+usage.cacheWrite,cost=usage.cost.total>=.01?` (~$${usage.cost.total.toFixed(2)})`:"",label=notice.kind==="compaction"?"Compaction":"Branch summary";this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`${label}: ${formatTokens(tokens)} tokens billed${cost}`),1,0))}maybeShowAssistantDiagnostics(message){if(this.settingsManager.getShowCacheMissNotices())for(let diagnostic5 of message.diagnostics??[]){if(diagnostic5.type!=="anthropic_input_transformations")continue;let transformations=diagnostic5.details?.transformations;if(!Array.isArray(transformations))continue;let dropped=transformations.flatMap(transformation=>{if(typeof transformation!="object"||transformation===null)return[];let details=transformation;if(details.type!=="thinking_dropped")return[];let reason=typeof details.reason=="string"?details.reason:"unknown reason",location=typeof details.path=="string"?` at ${details.path}`:"";return[`${reason}${location}`]});if(dropped.length===0)continue;let noun=dropped.length===1?"thinking block":`${dropped.length} thinking blocks`;this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`Anthropic dropped ${noun}: ${dropped.join("; ")}`),1,0))}}maybeShowCacheMissNotice(message){if(!this.settingsManager.getShowCacheMissNotices())return;let miss=detectCacheMiss(this.facade.getEntries(),message,this.facade.getModelPriceSource());miss&&this.addCacheMissNotice(miss)}addCacheMissNotice(miss){if(miss.missedTokens<2e4&&miss.missedCost<.1)return;let cost=miss.missedCost>=.01?` (~$${miss.missedCost.toFixed(2)})`:"",reBilled=`${formatTokens(miss.missedTokens)} tokens re-billed${cost}`,label="Cache miss";miss.modelChanged?label="Cache miss after model switch":miss.idleMs>=3e5&&(label=`Cache miss after ${Math.round(miss.idleMs/6e4)}m idle`);let text=theme.fg("warning",`${label}: ${reBilled}`);this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(text,1,0))}renderInitialMessages(){let entries=this.facade.getContextEntries();this.renderSessionEntries(entries,{updateFooter:!0,populateHistory:!0});let compactionCount=this.facade.getEntries().filter(e=>e.type==="compaction").length;if(compactionCount>0){let times=compactionCount===1?"1 time":`${compactionCount} times`;this.showStatus(`Session compacted ${times}`)}}async getUserInput(){let queuedInput=this.pendingUserInputs.shift();return queuedInput!==void 0?queuedInput:new Promise(resolve25=>{this.onInputCallback=text=>{this.onInputCallback=void 0,resolve25(text)}})}rebuildChatFromMessages(){this.chatContainer.clear(),this.renderSessionEntries(this.facade.getContextEntries())}handleCtrlC(){let now=Date.now();now-this.lastSigintTime<500?this.shutdown():(this.clearEditor(),this.lastSigintTime=now)}handleCtrlD(){this.shutdown()}isShuttingDown=!1;async shutdown(options){if(this.isShuttingDown)return;this.isShuttingDown=!0,options?.fromSignal&&(await this.runtimeFacade.dispose(),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),process.exit(0)),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),await this.runtimeFacade.dispose();let resumeCommand=formatResumeCommand(this.runtimeFacade);resumeCommand&&process.stdout.write(`${source_default.dim("To resume this session:")} ${resumeCommand}
|
|
1378
1378
|
`),process.exit(0)}emergencyTerminalExit(){this.isShuttingDown=!0,this.unregisterSignalHandlers(),killTrackedDetachedChildren(),process.exit(129)}uncaughtCrash(error2){this.isShuttingDown&&process.exit(1),this.isShuttingDown=!0;try{this.unregisterSignalHandlers()}catch{}try{killTrackedDetachedChildren()}catch{}try{this.ui.stop()}catch{}console.error(`${APP_NAME} exiting due to uncaughtException:`),console.error(error2),process.exit(1)}async checkShutdownRequested(){this.shutdownRequested&&await this.shutdown()}registerSignalHandlers(){this.unregisterSignalHandlers();let signals=["SIGTERM"];process.platform!=="win32"&&signals.push("SIGHUP");for(let signal of signals){let handler=()=>{killTrackedDetachedChildren(),this.shutdown({fromSignal:!0})};process.prependListener(signal,handler),this.signalCleanupHandlers.push(()=>process.off(signal,handler))}let terminalErrorHandler=error2=>{throw isDeadTerminalError(error2)&&this.emergencyTerminalExit(),error2};process.stdout.on("error",terminalErrorHandler),process.stderr.on("error",terminalErrorHandler),this.signalCleanupHandlers.push(()=>process.stdout.off("error",terminalErrorHandler)),this.signalCleanupHandlers.push(()=>process.stderr.off("error",terminalErrorHandler));let uncaughtExceptionHandler=error2=>this.uncaughtCrash(error2);process.prependListener("uncaughtException",uncaughtExceptionHandler),this.signalCleanupHandlers.push(()=>process.off("uncaughtException",uncaughtExceptionHandler))}unregisterSignalHandlers(){for(let cleanup of this.signalCleanupHandlers)cleanup();this.signalCleanupHandlers=[]}handleCtrlZ(){if(process.platform==="win32"){this.showStatus("Suspend to background is not supported on Windows");return}let suspendKeepAlive=setInterval(()=>{},2**30),ignoreSigint=()=>{};process.on("SIGINT",ignoreSigint),process.once("SIGCONT",()=>{clearInterval(suspendKeepAlive),process.removeListener("SIGINT",ignoreSigint),this.ui.start(),this.ui.requestRender(!0)});try{this.ui.stop(),process.kill(0,"SIGTSTP")}catch(error2){throw clearInterval(suspendKeepAlive),process.removeListener("SIGINT",ignoreSigint),error2}}async handleFollowUp(){let text=(this.editor.getExpandedText?.()??this.editor.getText()).trim();if(text){if(this.facade.isCompacting()){this.queueCompactionMessage(text,"followUp");return}this.facade.isStreaming()?(this.editor.addToHistory?.(text),this.editor.setText(""),await this.facade.prompt(text,{streamingBehavior:"followUp"}),this.updatePendingMessagesDisplay(),this.ui.requestRender()):this.editor.onSubmit&&(this.editor.setText(""),this.editor.onSubmit(text))}}handleDequeue(){let restored=this.restoreQueuedMessagesToEditor();restored===0?this.showStatus("No queued messages to restore"):this.showStatus(`Restored ${restored} queued message${restored>1?"s":""} to editor`)}updateEditorBorderColor(){if(this.isBashMode)this.editor.borderColor=theme.getBashModeBorderColor();else{let level=this.facade.getState().thinkingLevel||"off";this.editor.borderColor=theme.getThinkingBorderColor(level)}this.ui.requestRender()}cycleThinkingLevel(){let newLevel=this.facade.cycleThinkingLevel();newLevel===void 0?this.showStatus("Current model does not support thinking"):(this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Thinking level: ${newLevel}`))}async cycleModel(direction){try{let result=await this.facade.cycleModel(direction);if(result===void 0){let msg=this.facade.getScopedModels().length>0?"Only one model in scope":"Only one model available";this.showStatus(msg)}else{this.footer.invalidate(),this.updateEditorBorderColor();let thinkingStr=result.model.reasoning&&result.thinkingLevel!=="off"?` (thinking: ${result.thinkingLevel})`:"";this.showStatus(`Switched to ${result.model.name||result.model.id}${thinkingStr}`),this.maybeWarnAboutAnthropicSubscriptionAuth(result.model)}}catch(error2){this.showError(error2 instanceof Error?error2.message:String(error2))}}toggleToolOutputExpansion(){this.setToolsExpanded(!this.toolOutputExpanded)}setToolsExpanded(expanded){if(expanded===this.toolOutputExpanded)return;this.toolOutputExpanded=expanded;let activeHeader=this.builtInHeader;isExpandable(activeHeader)&&activeHeader.setExpanded(expanded);for(let container of[this.loadedResourcesContainer,this.chatContainer])for(let child of container.children)isExpandable(child)&&child.setExpanded(expanded);this.showStatus(`Tool output: ${expanded?"expanded":"collapsed"}`)}updateThinkingBlockVisibility(){for(let child of this.chatContainer.children)child instanceof AssistantMessageComponent&&child.setHideThinkingBlock(this.hideThinkingBlock);this.ui.requestRender()}toggleThinkingBlockVisibility(){this.hideThinkingBlock=!this.hideThinkingBlock,this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock),this.updateThinkingBlockVisibility(),this.showStatus(`Thinking blocks: ${this.hideThinkingBlock?"hidden":"visible"}`)}async handleOpenExternalEditor(){let editorCmd=this.settingsManager.getExternalEditorCommand(),content=this.editor.getExpandedText?.()??this.editor.getText();this.ui.stop();try{let result=await editInExternalEditor({command:editorCmd,content});result.status==="complete"&&this.editor.setText(result.content)}finally{this.ui.start(),this.ui.requestRender(!0)}}clearEditor(){this.editor.setText(""),this.ui.requestRender()}showError(errorMessage2){this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("error",`Error: ${errorMessage2}`),this.outputPad,0)),this.ui.requestRender()}showWarning(warningMessage){this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`Warning: ${warningMessage}`),1,0)),this.ui.requestRender()}showNewVersionNotification(release){let action=theme.fg("accent",`${APP_NAME} update`),updateInstruction=theme.fg("muted",`New version ${release.version} is available. Run `)+action,changelogUrl=process.env.AGENT_FORGE_CHANGELOG_URL,changelogLine=changelogUrl?theme.fg("muted","Changelog: ")+(getCapabilities().hyperlinks?hyperlink(theme.fg("accent",changelogUrl),changelogUrl):theme.fg("accent",changelogUrl)):theme.fg("muted","Changelog URL is not configured."),note=release.note?.trim();this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder(text=>theme.fg("warning",text))),this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning","Update Available"))}
|
|
1379
1379
|
${updateInstruction}`,1,0)),note&&(this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Markdown(note,1,0,this.getMarkdownThemeWithSettings(),{color:text=>theme.fg("muted",text)})),this.chatContainer.addChild(new Spacer(1))),this.chatContainer.addChild(new Text(changelogLine,1,0)),this.chatContainer.addChild(new DynamicBorder(text=>theme.fg("warning",text))),this.ui.requestRender()}showPackageUpdateNotification(packages){let action=theme.fg("accent",`${APP_NAME} update --extensions`),updateInstruction=theme.fg("muted","Package updates are available. Run ")+action,packageLines=packages.map(pkg2=>`- ${pkg2}`).join(`
|
|
1380
1380
|
`);this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder(text=>theme.fg("warning",text))),this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning","Package Updates Available"))}
|
package/dist/bundle/cli.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
|
|
3
|
-
import{APP_NAME,configureHttpDispatcher,main}from"./chunks/chunk-
|
|
3
|
+
import{APP_NAME,configureHttpDispatcher,main}from"./chunks/chunk-WD7FTOHY.js";import"./chunks/chunk-JUUC5AZY.js";import"./chunks/chunk-XDUWOHPL.js";import"./chunks/chunk-3QKHSPQL.js";import"./chunks/chunk-DRQDKNXA.js";import"./chunks/chunk-7ZY7IXZD.js";import"./chunks/chunk-V46XUTK3.js";import"./chunks/chunk-WGLBM2BP.js";import"./chunks/chunk-4L3WN2XY.js";process.title=APP_NAME;process.env.AGENT_FORGE="true";process.env.AI_AGENT="agent-forge";process.emitWarning=(()=>{});configureHttpDispatcher();main(process.argv.slice(2));
|