@myagentroam/agent 0.9.141 → 0.9.143

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/dist/agent-core/host/contracts.d.ts +64 -0
  2. package/dist/{host → agent-core/host}/local-agent-host.d.ts +6 -5
  3. package/dist/{host → agent-core/host}/local-agent-host.js +4 -4
  4. package/dist/{model → agent-core/model}/anthropic-messages.js +24 -13
  5. package/dist/{model → agent-core/model}/contracts.d.ts +6 -16
  6. package/dist/{model → agent-core/model}/openai-responses.js +16 -9
  7. package/dist/agent-core/model/recovery.d.ts +4 -0
  8. package/dist/agent-core/model/recovery.js +71 -0
  9. package/dist/{prompts → agent-core/prompts}/core.d.ts +3 -13
  10. package/dist/{prompts → agent-core/prompts}/index.d.ts +1 -1
  11. package/dist/{prompts → agent-core/prompts}/modes.d.ts +1 -1
  12. package/dist/{prompts → agent-core/prompts}/resources.d.ts +1 -1
  13. package/dist/{runtime/compact.d.ts → agent-core/runtime/compaction/history.d.ts} +2 -23
  14. package/dist/{runtime/compact.js → agent-core/runtime/compaction/history.js} +2 -92
  15. package/dist/agent-core/runtime/compaction/operation.d.ts +22 -0
  16. package/dist/agent-core/runtime/compaction/operation.js +91 -0
  17. package/dist/agent-core/runtime/context/contracts.d.ts +12 -0
  18. package/dist/{runtime/environment-context.d.ts → agent-core/runtime/context/environment.d.ts} +2 -2
  19. package/dist/{runtime/environment-context.js → agent-core/runtime/context/environment.js} +1 -1
  20. package/dist/{runtime/context-gc-runtime.d.ts → agent-core/runtime/context/gc-runtime.d.ts} +4 -4
  21. package/dist/{runtime/context-gc-runtime.js → agent-core/runtime/context/gc-runtime.js} +3 -3
  22. package/dist/{runtime/context-gc-tokens.d.ts → agent-core/runtime/context/gc-tokens.d.ts} +2 -2
  23. package/dist/{runtime/context-gc-tokens.js → agent-core/runtime/context/gc-tokens.js} +7 -5
  24. package/dist/{runtime/context-gc.d.ts → agent-core/runtime/context/gc.d.ts} +3 -3
  25. package/dist/{runtime/context-gc.js → agent-core/runtime/context/gc.js} +152 -19
  26. package/dist/{runtime → agent-core/runtime/context}/instructions.d.ts +1 -1
  27. package/dist/{runtime → agent-core/runtime/context}/instructions.js +1 -1
  28. package/dist/{runtime → agent-core/runtime/context}/normalize.d.ts +1 -1
  29. package/dist/{runtime/context-projection.d.ts → agent-core/runtime/context/projection.d.ts} +3 -3
  30. package/dist/{runtime/context-projection.js → agent-core/runtime/context/projection.js} +35 -4
  31. package/dist/agent-core/runtime/context/request-budget.d.ts +6 -0
  32. package/dist/agent-core/runtime/context/request-budget.js +22 -0
  33. package/dist/agent-core/runtime/context/restore.d.ts +15 -0
  34. package/dist/agent-core/runtime/context/restore.js +85 -0
  35. package/dist/agent-core/runtime/context/usage.d.ts +18 -0
  36. package/dist/agent-core/runtime/context/usage.js +138 -0
  37. package/dist/agent-core/runtime/context/world-state.d.ts +35 -0
  38. package/dist/agent-core/runtime/context/world-state.js +133 -0
  39. package/dist/agent-core/runtime/contracts.d.ts +37 -0
  40. package/dist/agent-core/runtime/event-projection.d.ts +5 -0
  41. package/dist/agent-core/runtime/event-projection.js +17 -0
  42. package/dist/agent-core/runtime/events.d.ts +143 -0
  43. package/dist/agent-core/runtime/execution.d.ts +50 -0
  44. package/dist/agent-core/runtime/execution.js +397 -0
  45. package/dist/{runtime → agent-core/runtime}/rollout-budget.d.ts +1 -1
  46. package/dist/agent-core/sdk/agent.js +209 -0
  47. package/dist/agent-core/sdk/model-runtime.d.ts +13 -0
  48. package/dist/agent-core/sdk/model-runtime.js +63 -0
  49. package/dist/agent-core/sdk/session-title.d.ts +3 -0
  50. package/dist/agent-core/sdk/session-title.js +42 -0
  51. package/dist/agent-core/sdk/session.d.ts +62 -0
  52. package/dist/agent-core/sdk/session.js +1147 -0
  53. package/dist/agent-core/sdk/subagent-backend.d.ts +3 -0
  54. package/dist/agent-core/sdk/subagent-backend.js +46 -0
  55. package/dist/agent-core/sdk/types.d.ts +56 -0
  56. package/dist/{session → agent-core/session}/catalog.d.ts +2 -1
  57. package/dist/{session → agent-core/session}/context-gc-checkpoint.d.ts +3 -0
  58. package/dist/{session → agent-core/session}/context-gc-checkpoint.js +122 -23
  59. package/dist/agent-core/session/context-gc-observations.d.ts +38 -0
  60. package/dist/agent-core/session/context-gc-observations.js +150 -0
  61. package/dist/{session → agent-core/session}/context-gc-replacements.d.ts +1 -1
  62. package/dist/{session → agent-core/session}/context-gc-replacements.js +6 -2
  63. package/dist/{session → agent-core/session}/jsonl-store.d.ts +2 -2
  64. package/dist/{session → agent-core/session}/jsonl-store.js +1 -1
  65. package/dist/agent-core/subagent/contracts.d.ts +91 -0
  66. package/dist/agent-core/subagent/contracts.js +1 -0
  67. package/dist/agent-core/subagent/scheduler.d.ts +117 -0
  68. package/dist/{subagent → agent-core/subagent}/session-controller.d.ts +3 -2
  69. package/dist/agent-core/tools/agent/agent-cancel.d.ts +7 -0
  70. package/dist/{tools → agent-core/tools/agent}/agent-cancel.js +1 -1
  71. package/dist/agent-core/tools/agent/agent-message.d.ts +7 -0
  72. package/dist/{tools → agent-core/tools/agent}/agent-message.js +2 -2
  73. package/dist/{tools → agent-core/tools/agent}/agent-start.d.ts +3 -3
  74. package/dist/{tools → agent-core/tools/agent}/agent-start.js +3 -3
  75. package/dist/agent-core/tools/agent/agent-wait.d.ts +7 -0
  76. package/dist/{tools → agent-core/tools/agent}/agent-wait.js +2 -2
  77. package/dist/{tools → agent-core/tools/agent}/question.d.ts +2 -2
  78. package/dist/{tools → agent-core/tools/agent}/question.js +2 -2
  79. package/dist/{tools → agent-core/tools/agent}/skill.d.ts +2 -2
  80. package/dist/{tools → agent-core/tools/agent}/skill.js +2 -2
  81. package/dist/{tools → agent-core/tools/agent}/todo-read.d.ts +2 -2
  82. package/dist/{tools → agent-core/tools/agent}/todo-write.d.ts +2 -2
  83. package/dist/{tools → agent-core/tools/agent}/todo-write.js +2 -2
  84. package/dist/{tools → agent-core/tools/agent}/todo.d.ts +2 -9
  85. package/dist/{tools → agent-core/tools/agent}/todo.js +1 -1
  86. package/dist/{tools → agent-core/tools}/code-mode/cells.d.ts +4 -1
  87. package/dist/{tools → agent-core/tools}/code-mode/cells.js +60 -6
  88. package/dist/{tools → agent-core/tools}/code-mode/dispatch.d.ts +2 -4
  89. package/dist/{tools → agent-core/tools}/code-mode/dispatch.js +10 -6
  90. package/dist/{tools → agent-core/tools}/code-mode/engine.d.ts +13 -1
  91. package/dist/agent-core/tools/code-mode/engine.js +1 -0
  92. package/dist/{tools/code-mode.d.ts → agent-core/tools/code-mode/index.d.ts} +7 -7
  93. package/dist/{tools/code-mode.js → agent-core/tools/code-mode/index.js} +190 -28
  94. package/dist/agent-core/tools/code-mode/observations.d.ts +103 -0
  95. package/dist/agent-core/tools/code-mode/observations.js +195 -0
  96. package/dist/{tools → agent-core/tools}/code-mode/quickjs-engine.js +91 -17
  97. package/dist/{tools → agent-core/tools}/code-mode/state.d.ts +2 -13
  98. package/dist/agent-core/tools/code-mode/worker.d.ts +1 -0
  99. package/dist/{tools → agent-core/tools}/code-mode/worker.js +8 -1
  100. package/dist/agent-core/tools/contracts.d.ts +172 -0
  101. package/dist/agent-core/tools/contracts.js +1 -0
  102. package/dist/agent-core/tools/execution.d.ts +36 -0
  103. package/dist/agent-core/tools/execution.js +111 -0
  104. package/dist/agent-core/tools/local/apply-patch.d.ts +19 -0
  105. package/dist/{tools → agent-core/tools/local}/apply-patch.js +8 -2
  106. package/dist/{tools → agent-core/tools/local}/exec.d.ts +5 -17
  107. package/dist/{tools → agent-core/tools/local}/exec.js +4 -4
  108. package/dist/{tools → agent-core/tools/local}/read.d.ts +7 -15
  109. package/dist/{tools → agent-core/tools/local}/read.js +185 -2
  110. package/dist/{tools/local-registry.d.ts → agent-core/tools/local/registry.d.ts} +5 -5
  111. package/dist/agent-core/tools/local/registry.js +101 -0
  112. package/dist/{tools → agent-core/tools/local}/view-image.d.ts +4 -9
  113. package/dist/{tools → agent-core/tools/local}/view-image.js +2 -2
  114. package/dist/agent-core/tools/local/web-fetch.d.ts +4 -0
  115. package/dist/agent-core/tools/local/web-fetch.js +85 -0
  116. package/dist/agent-core/tools/local/web-search.d.ts +7 -0
  117. package/dist/agent-core/tools/local/web-search.js +34 -0
  118. package/dist/{tools/local-workspace-tools.js → agent-core/tools/local/workspace-tools.js} +1 -1
  119. package/dist/{sdk/mcp-catalog.d.ts → agent-core/tools/mcp/catalog.d.ts} +1 -2
  120. package/dist/{sdk/mcp-catalog.js → agent-core/tools/mcp/catalog.js} +1 -1
  121. package/dist/agent-core/tools/mcp/history.d.ts +4 -0
  122. package/dist/agent-core/tools/mcp/history.js +33 -0
  123. package/dist/{tools → agent-core/tools/mcp}/tool-search.d.ts +3 -3
  124. package/dist/{tools → agent-core/tools/mcp}/tool-search.js +4 -4
  125. package/dist/agent-core/tools/output-projection.d.ts +14 -0
  126. package/dist/agent-core/tools/output-projection.js +223 -0
  127. package/dist/{tools → agent-core/tools}/registry.d.ts +1 -1
  128. package/dist/agent-core/tools/registry.js +47 -0
  129. package/dist/{tools → agent-core/tools}/runtime-context.d.ts +8 -7
  130. package/dist/agent-core/tools/runtime-context.js +1 -0
  131. package/dist/{tools → agent-core/tools}/runtime.d.ts +1 -1
  132. package/dist/cli/codex-auth-file.d.ts +1 -1
  133. package/dist/cli/codex-auth-file.js +2 -2
  134. package/dist/cli/main.js +9 -9
  135. package/dist/index.d.ts +17 -15
  136. package/dist/index.js +8 -8
  137. package/dist/sandbox/linux/bubblewrap-sandbox-executor.d.ts +1 -1
  138. package/dist/sandbox/linux/bubblewrap-sandbox-executor.js +1 -1
  139. package/package.json +3 -3
  140. package/dist/host/contracts.d.ts +0 -21
  141. package/dist/sdk/agent.js +0 -2548
  142. package/dist/sdk/types.d.ts +0 -349
  143. package/dist/subagent/scheduler.d.ts +0 -206
  144. package/dist/tools/agent-cancel.d.ts +0 -7
  145. package/dist/tools/agent-message.d.ts +0 -7
  146. package/dist/tools/agent-wait.d.ts +0 -7
  147. package/dist/tools/apply-patch.d.ts +0 -32
  148. package/dist/tools/local-registry.js +0 -373
  149. package/dist/tools/registry.js +0 -47
  150. package/dist/tools/web-fetch.d.ts +0 -2
  151. package/dist/tools/web-fetch.js +0 -12
  152. package/dist/tools/web-search.d.ts +0 -2
  153. package/dist/tools/web-search.js +0 -15
  154. /package/dist/{error.d.ts → agent-core/error.d.ts} +0 -0
  155. /package/dist/{error.js → agent-core/error.js} +0 -0
  156. /package/dist/{host → agent-core/host}/contracts.js +0 -0
  157. /package/dist/{host → agent-core/host}/local-process-executor.d.ts +0 -0
  158. /package/dist/{host → agent-core/host}/local-process-executor.js +0 -0
  159. /package/dist/{host → agent-core/host}/network.d.ts +0 -0
  160. /package/dist/{host → agent-core/host}/network.js +0 -0
  161. /package/dist/{model → agent-core/model}/anthropic-messages.d.ts +0 -0
  162. /package/dist/{model → agent-core/model}/anthropic-thinking.d.ts +0 -0
  163. /package/dist/{model → agent-core/model}/anthropic-thinking.js +0 -0
  164. /package/dist/{model → agent-core/model}/catalog-file.d.ts +0 -0
  165. /package/dist/{model → agent-core/model}/catalog-file.js +0 -0
  166. /package/dist/{model → agent-core/model}/configuration.d.ts +0 -0
  167. /package/dist/{model → agent-core/model}/configuration.js +0 -0
  168. /package/dist/{model → agent-core/model}/contracts.js +0 -0
  169. /package/dist/{model → agent-core/model}/http.d.ts +0 -0
  170. /package/dist/{model → agent-core/model}/http.js +0 -0
  171. /package/dist/{model → agent-core/model}/openai-responses.d.ts +0 -0
  172. /package/dist/{model → agent-core/model}/runtime-credential.d.ts +0 -0
  173. /package/dist/{model → agent-core/model}/runtime-credential.js +0 -0
  174. /package/dist/{model → agent-core/model}/sse.d.ts +0 -0
  175. /package/dist/{model → agent-core/model}/sse.js +0 -0
  176. /package/dist/{model → agent-core/model}/transport-test.d.ts +0 -0
  177. /package/dist/{model → agent-core/model}/transport-test.js +0 -0
  178. /package/dist/{prompts → agent-core/prompts}/compact.d.ts +0 -0
  179. /package/dist/{prompts → agent-core/prompts}/compact.js +0 -0
  180. /package/dist/{prompts → agent-core/prompts}/core.js +0 -0
  181. /package/dist/{prompts → agent-core/prompts}/execution-budget.d.ts +0 -0
  182. /package/dist/{prompts → agent-core/prompts}/execution-budget.js +0 -0
  183. /package/dist/{prompts → agent-core/prompts}/index.js +0 -0
  184. /package/dist/{prompts → agent-core/prompts}/modes.js +0 -0
  185. /package/dist/{prompts → agent-core/prompts}/output.d.ts +0 -0
  186. /package/dist/{prompts → agent-core/prompts}/output.js +0 -0
  187. /package/dist/{prompts → agent-core/prompts}/resources.js +0 -0
  188. /package/dist/{prompts → agent-core/prompts}/subagent.d.ts +0 -0
  189. /package/dist/{prompts → agent-core/prompts}/subagent.js +0 -0
  190. /package/dist/{prompts → agent-core/prompts}/title.d.ts +0 -0
  191. /package/dist/{prompts → agent-core/prompts}/title.js +0 -0
  192. /package/dist/{prompts → agent-core/prompts}/workflow.d.ts +0 -0
  193. /package/dist/{prompts → agent-core/prompts}/workflow.js +0 -0
  194. /package/dist/{runtime → agent-core/runtime}/async-queue.d.ts +0 -0
  195. /package/dist/{runtime → agent-core/runtime}/async-queue.js +0 -0
  196. /package/dist/{sdk/types.js → agent-core/runtime/context/contracts.js} +0 -0
  197. /package/dist/{runtime → agent-core/runtime/context}/normalize.js +0 -0
  198. /package/dist/{session/types.js → agent-core/runtime/contracts.js} +0 -0
  199. /package/dist/{tools/code-mode/engine.js → agent-core/runtime/events.js} +0 -0
  200. /package/dist/{runtime → agent-core/runtime}/execution-policy.d.ts +0 -0
  201. /package/dist/{runtime → agent-core/runtime}/execution-policy.js +0 -0
  202. /package/dist/{runtime → agent-core/runtime}/plan-output.d.ts +0 -0
  203. /package/dist/{runtime → agent-core/runtime}/plan-output.js +0 -0
  204. /package/dist/{runtime → agent-core/runtime}/rollout-budget.js +0 -0
  205. /package/dist/{runtime → agent-core/runtime}/token-budget.d.ts +0 -0
  206. /package/dist/{runtime → agent-core/runtime}/token-budget.js +0 -0
  207. /package/dist/{sdk → agent-core/sdk}/agent.d.ts +0 -0
  208. /package/dist/{tools/code-mode/worker.d.ts → agent-core/sdk/types.js} +0 -0
  209. /package/dist/{session → agent-core/session}/catalog.js +0 -0
  210. /package/dist/{session → agent-core/session}/context-gc-subagent.d.ts +0 -0
  211. /package/dist/{session → agent-core/session}/context-gc-subagent.js +0 -0
  212. /package/dist/{session → agent-core/session}/transaction-recovery.d.ts +0 -0
  213. /package/dist/{session → agent-core/session}/transaction-recovery.js +0 -0
  214. /package/dist/{session → agent-core/session}/types.d.ts +0 -0
  215. /package/dist/{tools/runtime-context.js → agent-core/session/types.js} +0 -0
  216. /package/dist/{subagent → agent-core/subagent}/scheduler.js +0 -0
  217. /package/dist/{subagent → agent-core/subagent}/session-controller.js +0 -0
  218. /package/dist/{tools → agent-core/tools/agent}/todo-read.js +0 -0
  219. /package/dist/{tools → agent-core/tools}/callers.d.ts +0 -0
  220. /package/dist/{tools → agent-core/tools}/callers.js +0 -0
  221. /package/dist/{tools → agent-core/tools}/code-mode/quickjs-engine.d.ts +0 -0
  222. /package/dist/{tools → agent-core/tools}/code-mode/state.js +0 -0
  223. /package/dist/{tools → agent-core/tools}/code-mode/text-output.d.ts +0 -0
  224. /package/dist/{tools → agent-core/tools}/code-mode/text-output.js +0 -0
  225. /package/dist/{tools → agent-core/tools}/execution-limits.d.ts +0 -0
  226. /package/dist/{tools → agent-core/tools}/execution-limits.js +0 -0
  227. /package/dist/{tools → agent-core/tools/local}/read-context.d.ts +0 -0
  228. /package/dist/{tools → agent-core/tools/local}/read-context.js +0 -0
  229. /package/dist/{tools/local-workspace-tools.d.ts → agent-core/tools/local/workspace-tools.d.ts} +0 -0
  230. /package/dist/{tools → agent-core/tools}/runtime.js +0 -0
  231. /package/dist/{tools → agent-core/tools}/scheduler.d.ts +0 -0
  232. /package/dist/{tools → agent-core/tools}/scheduler.js +0 -0
  233. /package/dist/{tools → agent-core/tools}/shared/path-resolver.d.ts +0 -0
  234. /package/dist/{tools → agent-core/tools}/shared/path-resolver.js +0 -0
@@ -0,0 +1,1147 @@
1
+ import { isProviderContextOverflow, recoverModelStream } from '../model/recovery.js';
2
+ import { estimatedRequestTokens } from '../runtime/context/request-budget.js';
3
+ import { restoreMessages } from '../runtime/context/restore.js';
4
+ import { lastConfigurationEffort, latestModelUsage, reasoningEffortBaseline, shouldUseNativeCompaction } from '../runtime/context/usage.js';
5
+ import { compactHistoryMayContainRetainedResources, contextualInstructionInsertIndex, insertContextualWorldState, latestContextualWorldStateGeneration, parsePersistedContextualWorldState, persistContextualWorldState, resetContextualWorldState, updateContextualWorldState } from '../runtime/context/world-state.js';
6
+ import { eventForPersistence, publicModelUsage } from '../runtime/event-projection.js';
7
+ import { ExecutionLoop } from '../runtime/execution.js';
8
+ import { closeModelAdapters, createModelTurnSession } from './model-runtime.js';
9
+ import { generateSessionTitle } from './session-title.js';
10
+ import { createSubagentBackend } from './subagent-backend.js';
11
+ import { discoveredMcpToolNames, rebindMcpToolSearchOutputs } from '../tools/mcp/history.js';
12
+ import { currentExecutionImages } from '../tools/output-projection.js';
13
+ import { createHash, randomUUID } from 'node:crypto';
14
+ import { isDeepStrictEqual } from 'node:util';
15
+ import { MarAgentError, describeMarAgentError } from '../error.js';
16
+ import { usesResponsesConfigurationUpdates } from '../model/configuration.js';
17
+ import { buildEnvironmentContext } from '../prompts/core.js';
18
+ import { executionBudgetEnvironmentEntry } from '../prompts/execution-budget.js';
19
+ import { MAR_AGENT_PROMPT_VERSION, buildSystemPrompt } from '../prompts/index.js';
20
+ import { retainedSessionResourcesSnapshot } from '../prompts/resources.js';
21
+ import { childSubagentInstruction } from '../prompts/subagent.js';
22
+ import { AsyncQueue } from '../runtime/async-queue.js';
23
+ import { CompactionOperation } from '../runtime/compaction/operation.js';
24
+ import { DEFAULT_COMPACTION_FOCUS, buildCompactedHistory, buildCompactionInput, buildCompactionMessages, buildNativeCompactionMessages, compactedHistoryMessages } from '../runtime/compaction/history.js';
25
+ import { currentLocalTimeContext, environmentContextUpdate, restoreEnvironmentState } from '../runtime/context/environment.js';
26
+ import { ContextGcRuntime } from '../runtime/context/gc-runtime.js';
27
+ import { AGENT_EXECUTION_POLICY } from '../runtime/execution-policy.js';
28
+ import { loadAgentInstructions, renderAgentInstructions } from '../runtime/context/instructions.js';
29
+ import { normalizeMessagesForModel } from '../runtime/context/normalize.js';
30
+ import { RolloutBudget } from '../runtime/rollout-budget.js';
31
+ import { compactSummaryFromCheckpoint } from '../session/jsonl-store.js';
32
+ import { SubagentSessionController } from '../subagent/session-controller.js';
33
+ import { agentStartToolDefinitionWithModels } from '../tools/agent/agent-start.js';
34
+ import { allowsDirectTool, allowsToolCaller, toolCallers } from '../tools/callers.js';
35
+ import { projectCodeModeSearchResult, projectCodeModeTools } from '../tools/code-mode/index.js';
36
+ import { assertMcpToolCatalog } from '../tools/mcp/catalog.js';
37
+ import { BUILTIN_TOOL_DEFINITIONS } from '../tools/registry.js';
38
+ import { createSessionToolScheduler } from '../tools/scheduler.js';
39
+ import { TodoStore } from '../tools/agent/todo.js';
40
+ import { DeferredMcpRegistry } from '../tools/mcp/tool-search.js';
41
+ /** SDK Session orchestration owns warm resources; Runtime owns only the model/tool loop. */
42
+ export function createSessionOpener(services) {
43
+ const { host, description, settings, store, rolloutBudgetOptions, createAdapter, activeAdaptersExcept } = services;
44
+ const { active, activeExecutionAdapters, executionResults, sessionRuntimes, sessionWriterOwner } = services.registry;
45
+ const openSession = async (sessionId, workspace) => {
46
+ const storedSession = await store.getSession(sessionId);
47
+ const storedWorkspace = storedSession.workspace;
48
+ const sessionSource = storedSession.source;
49
+ const logicalWorkspace = settings.workspaceMapping?.logicalPath ?? workspace ?? storedWorkspace ?? '';
50
+ const instructionWorkspace = settings.workspaceMapping?.physicalPath ?? workspace ?? storedWorkspace ?? '';
51
+ const currentEnvironment = {
52
+ platform: description.platform,
53
+ ...(description.architecture ? { architecture: description.architecture } : {}),
54
+ ...(description.shell ? { shell: description.shell } : {}),
55
+ ...(description.guaranteedCommands
56
+ ? { guaranteedCommands: description.guaranteedCommands }
57
+ : {}),
58
+ workspace: logicalWorkspace
59
+ };
60
+ if (!restoreEnvironmentState({ version: 1, state: currentEnvironment }))
61
+ throw new MarAgentError('MAR_AGENT_HOST_INCOMPATIBLE', 'Host environment facts are invalid or exceed the context limit.');
62
+ const environmentContext = buildEnvironmentContext(currentEnvironment);
63
+ let sessionRuntime = sessionRuntimes.get(sessionId);
64
+ if (sessionRuntime === undefined) {
65
+ sessionRuntime = {
66
+ sourceType: sessionSource.type,
67
+ scheduleTool: createSessionToolScheduler(),
68
+ adapterGeneration: services.modelState().generation,
69
+ adapters: new Map()
70
+ };
71
+ sessionRuntimes.set(sessionId, sessionRuntime);
72
+ }
73
+ if (sessionSource.type === 'user' && sessionRuntime.subagents === undefined) {
74
+ sessionRuntime.subagentsOpening ??= SubagentSessionController.open({
75
+ parentSessionId: sessionId,
76
+ rootSessionId: sessionId,
77
+ backend: createSubagentBackend(store, storedWorkspace)
78
+ });
79
+ try {
80
+ sessionRuntime.subagents = await sessionRuntime.subagentsOpening;
81
+ }
82
+ finally {
83
+ delete sessionRuntime.subagentsOpening;
84
+ }
85
+ }
86
+ const sessionAdapter = (modelId, configuredModels) => {
87
+ let selected = sessionRuntime.adapters.get(modelId);
88
+ if (selected === undefined) {
89
+ selected = createAdapter(modelId, configuredModels);
90
+ if (!services.hasCustomAdapters || selected.createTurnSession !== undefined)
91
+ sessionRuntime.adapters.set(modelId, selected);
92
+ }
93
+ return selected;
94
+ };
95
+ const refreshSessionAdapters = async (generation) => {
96
+ if (sessionRuntime.adapterGeneration === generation)
97
+ return;
98
+ const retainedByActiveSessions = activeAdaptersExcept(sessionId);
99
+ await closeModelAdapters([...sessionRuntime.adapters.values()].filter((adapter) => !retainedByActiveSessions.has(adapter)));
100
+ sessionRuntime.adapters.clear();
101
+ sessionRuntime.adapterGeneration = generation;
102
+ };
103
+ const execution = (mode, input, internal = {}) => {
104
+ services.assertCanStart();
105
+ if ([...active.keys()].some((key) => key.startsWith(`${sessionId}:`)))
106
+ throw new MarAgentError('MAR_AGENT_EXECUTION_ACTIVE', 'Session already has an active execution.');
107
+ const executionId = randomUUID(), turnId = internal.turnId ?? randomUUID(), queue = new AsyncQueue(), controller = new AbortController();
108
+ let executionEnvironment = {
109
+ ...currentEnvironment,
110
+ ...currentLocalTimeContext()
111
+ };
112
+ const { models: executionModels, defaultModelId: executionDefaultModelId, generation: executionModelGeneration } = services.modelState();
113
+ const manualCompactionId = mode === 'compact' ? randomUUID() : undefined;
114
+ active.set(`${sessionId}:${executionId}`, controller);
115
+ const mailbox = [...(internal.initialMailbox ?? [])];
116
+ let acceptsMailbox = sessionSource.type === 'subagent' && mode !== 'compact';
117
+ let sequence = 0;
118
+ let manualCompactionStarted = false;
119
+ let emitTail = Promise.resolve();
120
+ let exhaustedModelAttempt;
121
+ // Serialize durable events before either the local stream or Host observes them.
122
+ const emit = (event) => {
123
+ const full = {
124
+ ...event,
125
+ eventId: randomUUID(),
126
+ sequence: ++sequence,
127
+ timestamp: new Date().toISOString(),
128
+ sessionId,
129
+ executionId,
130
+ turnId
131
+ };
132
+ const operation = emitTail.then(async () => {
133
+ // Transport-only progress events never become recoverable history.
134
+ const persistent = eventForPersistence(full);
135
+ if (persistent !== undefined)
136
+ await store.append(sessionId, {
137
+ type: full.type,
138
+ payload: persistent,
139
+ executionId,
140
+ turnId
141
+ });
142
+ queue.push(full);
143
+ if (internal.publishHostEvents !== false)
144
+ await host.emit(full);
145
+ });
146
+ emitTail = operation.catch(() => undefined);
147
+ return operation;
148
+ };
149
+ const recordModelAttempt = (purpose) => (diagnostic) => {
150
+ if (purpose === 'EXECUTION' || purpose === 'COMPACTION') {
151
+ if ((diagnostic.state === 'STARTED' && diagnostic.attempt === 1) ||
152
+ diagnostic.state === 'SUCCEEDED')
153
+ exhaustedModelAttempt = undefined;
154
+ else if (diagnostic.state === 'FAILED' &&
155
+ diagnostic.willRetry === false &&
156
+ diagnostic.attempt > 1)
157
+ exhaustedModelAttempt = {
158
+ attempts: diagnostic.attempt,
159
+ retries: diagnostic.attempt - 1
160
+ };
161
+ }
162
+ const operation = emitTail.then(async () => {
163
+ await store.append(sessionId, {
164
+ type: 'model.attempt',
165
+ payload: { purpose, ...diagnostic },
166
+ executionId,
167
+ turnId
168
+ });
169
+ });
170
+ emitTail = operation.catch(() => undefined);
171
+ return operation;
172
+ };
173
+ const createCompactionOperation = (compactionId) => new CompactionOperation(controller.signal, (progress) => {
174
+ const operation = emitTail.then(async () => {
175
+ await store.append(sessionId, {
176
+ type: 'compact.progress',
177
+ payload: { compactionId, ...progress },
178
+ executionId,
179
+ turnId
180
+ });
181
+ });
182
+ emitTail = operation.catch(() => undefined);
183
+ return operation;
184
+ });
185
+ const result = (async () => {
186
+ let finalAnswer = '';
187
+ let executionLoop;
188
+ let manualCompaction;
189
+ const rolloutBudget = internal.sharedRolloutBudget ??
190
+ (rolloutBudgetOptions ? new RolloutBudget(rolloutBudgetOptions) : undefined);
191
+ const ownsRolloutBudget = rolloutBudget !== undefined && internal.sharedRolloutBudget === undefined;
192
+ let releaseSession;
193
+ let selectedTurn;
194
+ const contextGc = new ContextGcRuntime();
195
+ let selectedAdapter;
196
+ let titleAdapter;
197
+ const executionScopedAdapters = new Set();
198
+ let titleTask;
199
+ let titleSettled = false;
200
+ const settleTitle = async () => {
201
+ if (titleSettled)
202
+ return;
203
+ titleSettled = true;
204
+ const generatedTitle = await titleTask;
205
+ if (generatedTitle)
206
+ await store
207
+ .updateTitle(sessionId, generatedTitle, { executionId, turnId })
208
+ .catch(() => undefined);
209
+ };
210
+ const subagents = sessionSource.type === 'user' ? sessionRuntime.subagents : undefined;
211
+ try {
212
+ releaseSession = await store.acquireSessionLease(sessionId, sessionWriterOwner);
213
+ await refreshSessionAdapters(executionModelGeneration);
214
+ const sessionState = await store.readExecutionState(sessionId);
215
+ if (!store.hasRetainedSessionLease(sessionId, sessionWriterOwner))
216
+ sessionRuntime.todo = TodoStore.restore(sessionState.todo);
217
+ const todo = (sessionRuntime.todo ??= TodoStore.restore(sessionState.todo));
218
+ const contextRecords = sessionState.contextRecords;
219
+ const contextualWorldStateGeneration = latestContextualWorldStateGeneration(contextRecords);
220
+ const restoredContextualWorldState = sessionRuntime.contextualWorldState;
221
+ const persistedContextualWorldState = parsePersistedContextualWorldState(await store.readContextualWorldState(sessionId));
222
+ let contextualWorldState;
223
+ if (restoredContextualWorldState !== undefined &&
224
+ restoredContextualWorldState.generation === contextualWorldStateGeneration)
225
+ contextualWorldState = restoredContextualWorldState;
226
+ else if (persistedContextualWorldState !== undefined &&
227
+ persistedContextualWorldState.generation === contextualWorldStateGeneration) {
228
+ contextualWorldState = persistedContextualWorldState;
229
+ sessionRuntime.contextualWorldState = contextualWorldState;
230
+ }
231
+ else {
232
+ contextualWorldState = {
233
+ generation: contextualWorldStateGeneration,
234
+ initialized: false,
235
+ instructionSnapshot: undefined,
236
+ resourceSnapshot: undefined,
237
+ entries: []
238
+ };
239
+ sessionRuntime.contextualWorldState = contextualWorldState;
240
+ }
241
+ const compactMayContainAgentInstructions = contextRecords.some((record) => compactSummaryFromCheckpoint(record) !== undefined);
242
+ const compactMayContainRetainedResources = compactHistoryMayContainRetainedResources(contextRecords);
243
+ const restored = await restoreMessages(store, sessionId, contextRecords, {
244
+ includeImages: mode !== 'compact'
245
+ });
246
+ const messages = restored.messages;
247
+ let recordedEnvironment = restored.environmentState;
248
+ let projectedExecutionBudgetStage;
249
+ const appendExecutionBudgetEnvironment = () => {
250
+ const currentStage = rolloutBudget?.active ? rolloutBudget.stage : 'inactive';
251
+ if (currentStage === projectedExecutionBudgetStage)
252
+ return;
253
+ const previousStage = projectedExecutionBudgetStage;
254
+ projectedExecutionBudgetStage = currentStage;
255
+ if ((previousStage === undefined &&
256
+ (currentStage === 'normal' || currentStage === 'inactive')) ||
257
+ (currentStage === 'inactive' && previousStage === 'normal'))
258
+ return;
259
+ const entry = executionBudgetEnvironmentEntry(currentStage === 'normal' ? 'inactive' : currentStage);
260
+ messages.push(environmentContextUpdate(executionEnvironment, executionEnvironment, [entry]));
261
+ };
262
+ const appendMailboxMessages = async () => {
263
+ let appended = false;
264
+ while (mailbox.length > 0) {
265
+ const pending = mailbox.splice(0);
266
+ for (const { text: prompt, delivery } of pending) {
267
+ await store.append(sessionId, {
268
+ type: 'turn.user',
269
+ payload: {
270
+ prompt,
271
+ inputSource: 'parent_agent',
272
+ ...(delivery ? { messageId: delivery.messageId } : {})
273
+ },
274
+ executionId,
275
+ turnId
276
+ });
277
+ messages.push({ role: 'user', content: prompt });
278
+ delivery?.applied();
279
+ appended = true;
280
+ }
281
+ }
282
+ return appended;
283
+ };
284
+ const recordEnvironment = async () => {
285
+ const message = environmentContextUpdate(executionEnvironment, recordedEnvironment);
286
+ if (!message)
287
+ return;
288
+ await store.append(sessionId, {
289
+ type: 'context.environment',
290
+ payload: { version: 1, state: executionEnvironment },
291
+ executionId,
292
+ turnId
293
+ });
294
+ messages.push(message);
295
+ recordedEnvironment = executionEnvironment;
296
+ };
297
+ let compactionUserMessages = [
298
+ ...restored.userMessages,
299
+ ...(mode === 'compact' ? [] : [input.prompt])
300
+ ];
301
+ const hasRestoredUserImages = messages.some((message) => message.role === 'user' && Boolean(message.images?.length));
302
+ const modelInputImages = mode === 'compact'
303
+ ? undefined
304
+ : input.images?.map(({ mimeType, dataBase64 }) => ({
305
+ mimeType,
306
+ dataBase64
307
+ }));
308
+ const currentExecutionToolImages = [];
309
+ let currentExecutionUserIndex;
310
+ if (mode !== 'compact') {
311
+ await recordEnvironment();
312
+ const inputImageMetadata = input.images?.length
313
+ ? await store.persistInputImages(sessionId, input.images)
314
+ : [];
315
+ // A failed sync can still leave a complete record; lease recovery decides image ownership.
316
+ await store.append(sessionId, {
317
+ type: 'turn.user',
318
+ payload: {
319
+ prompt: input.prompt,
320
+ ...(internal.delivery ? { messageId: internal.delivery.messageId } : {}),
321
+ ...(internal.inputSource === undefined
322
+ ? {}
323
+ : { inputSource: internal.inputSource }),
324
+ ...(input.clientMessageId ? { clientMessageId: input.clientMessageId } : {}),
325
+ ...(inputImageMetadata.length ? { images: inputImageMetadata } : {})
326
+ },
327
+ executionId,
328
+ turnId
329
+ });
330
+ messages.push({ role: 'user', content: input.prompt });
331
+ currentExecutionUserIndex = messages.length - 1;
332
+ internal.delivery?.applied();
333
+ await appendMailboxMessages();
334
+ if (sessionState.automaticTitlePending) {
335
+ const titleModel = [...executionModels.values()].find((model) => model.titleGeneration) ??
336
+ executionModels.get(input.modelId ?? executionDefaultModelId);
337
+ titleAdapter = createAdapter(titleModel.id, executionModels);
338
+ activeExecutionAdapters.add(titleAdapter);
339
+ titleTask = generateSessionTitle(titleAdapter, input.prompt, titleModel.defaultReasoningEffort, controller.signal, recordModelAttempt('TITLE')).catch(() => undefined);
340
+ }
341
+ }
342
+ await emit({ type: 'execution.started', mode });
343
+ if (restored.ignoredImages > 0)
344
+ await store.append(sessionId, {
345
+ type: 'context.warning',
346
+ payload: {
347
+ code: 'MAR_AGENT_INPUT_IMAGE_IGNORED',
348
+ message: 'One or more corrupt historical input images were ignored.',
349
+ ignoredImages: restored.ignoredImages
350
+ },
351
+ executionId,
352
+ turnId
353
+ });
354
+ selectedAdapter = sessionAdapter(input.modelId ?? executionDefaultModelId, executionModels);
355
+ const selectedModel = executionModels.get(input.modelId ?? executionDefaultModelId);
356
+ if (services.hasCustomAdapters && selectedAdapter.createTurnSession === undefined) {
357
+ executionScopedAdapters.add(selectedAdapter);
358
+ activeExecutionAdapters.add(selectedAdapter);
359
+ }
360
+ const selected = createModelTurnSession(selectedAdapter);
361
+ selectedTurn = selected;
362
+ let lastServerUsage = latestModelUsage(contextRecords, selectedModel.id);
363
+ const compactUserTokenLimit = Math.min(20_000, Math.floor(selectedModel.contextWindowTokens / 8));
364
+ const reasoningEffort = input.reasoningEffort ?? selectedModel.defaultReasoningEffort;
365
+ const useEffortUpdates = usesResponsesConfigurationUpdates(selectedModel);
366
+ const previousReasoningEffort = useEffortUpdates
367
+ ? reasoningEffortBaseline(contextRecords, selectedModel.id)
368
+ : undefined;
369
+ let requestReasoningEffort = useEffortUpdates
370
+ ? (previousReasoningEffort ?? reasoningEffort)
371
+ : undefined;
372
+ let effectiveReasoningEffort = useEffortUpdates
373
+ ? previousReasoningEffort === undefined
374
+ ? requestReasoningEffort
375
+ : (lastConfigurationEffort(messages, selectedModel.id) ?? requestReasoningEffort)
376
+ : undefined;
377
+ if (mode !== 'compact' &&
378
+ useEffortUpdates &&
379
+ effectiveReasoningEffort !== reasoningEffort) {
380
+ const update = {
381
+ role: 'provider',
382
+ content: '',
383
+ provider: 'OPENAI_RESPONSES',
384
+ providerModelId: selectedModel.id,
385
+ item: { type: 'configuration_update', reasoning: { effort: reasoningEffort } }
386
+ };
387
+ messages.push(update);
388
+ await store.append(sessionId, {
389
+ type: 'model.context',
390
+ payload: update,
391
+ executionId,
392
+ turnId
393
+ });
394
+ effectiveReasoningEffort = reasoningEffort;
395
+ }
396
+ if (mode !== 'compact' && subagents)
397
+ await subagents.beginParentExecution({
398
+ executionId,
399
+ modelId: selectedModel.id,
400
+ reasoningEffort,
401
+ models: executionModels,
402
+ emitTerminal: async (task) => emit({
403
+ type: 'subagent.completed',
404
+ agentId: task.agentId,
405
+ description: task.description,
406
+ status: task.status,
407
+ ...(task.modelId === undefined ? {} : { modelId: task.modelId }),
408
+ ...(task.modelName === undefined ? {} : { modelName: task.modelName }),
409
+ ...(task.reasoningEffort === undefined
410
+ ? {}
411
+ : { reasoningEffort: task.reasoningEffort }),
412
+ ...(task.latestMessage === undefined
413
+ ? {}
414
+ : { latestMessage: task.latestMessage }),
415
+ ...(task.latestActivity === undefined
416
+ ? {}
417
+ : { latestActivity: task.latestActivity }),
418
+ ...(task.errorCode === undefined ? {} : { errorCode: task.errorCode }),
419
+ ...(task.errorMessage === undefined ? {} : { errorMessage: task.errorMessage })
420
+ }),
421
+ startTurn: async (turn) => {
422
+ const child = await openSession(turn.sessionId);
423
+ return child.startSubagentTurn({
424
+ prompt: turn.prompt,
425
+ modelId: turn.modelId,
426
+ reasoningEffort: turn.reasoningEffort,
427
+ role: turn.role,
428
+ initialMailbox: turn.initialMailbox,
429
+ turnId: turn.turnId,
430
+ mcpExecutionScopeId: executionId,
431
+ ...(turn.delivery ? { delivery: turn.delivery } : {}),
432
+ ...(rolloutBudget === undefined ? {} : { sharedRolloutBudget: rolloutBudget })
433
+ });
434
+ }
435
+ });
436
+ if (mode !== 'compact' &&
437
+ (input.images?.length || hasRestoredUserImages) &&
438
+ !selectedModel.inputCapabilities.includes('IMAGE'))
439
+ throw new MarAgentError('MAR_AGENT_INPUT_CAPABILITY_UNSUPPORTED', 'Selected model does not support image input.');
440
+ const catalogContext = {
441
+ sessionId,
442
+ executionId,
443
+ ...(sessionSource.type === 'subagent'
444
+ ? internal.mcpExecutionScopeId === undefined
445
+ ? {}
446
+ : { executionScopeId: internal.mcpExecutionScopeId }
447
+ : { claimExecutionScope: true })
448
+ };
449
+ const readMcpCatalog = async () => {
450
+ if (host.listMcpToolCatalog) {
451
+ const catalog = await host.listMcpToolCatalog(catalogContext);
452
+ assertMcpToolCatalog(catalog);
453
+ return catalog;
454
+ }
455
+ const definitions = (await host.listMcpTools?.(catalogContext)) ?? [];
456
+ return {
457
+ revision: createHash('sha256').update(JSON.stringify(definitions)).digest('hex'),
458
+ servers: [{ id: 'legacy', name: 'External MCP' }],
459
+ tools: definitions.map((definition) => ({
460
+ definition,
461
+ serverId: 'legacy',
462
+ rawName: definition.name,
463
+ sourceIdentity: `legacy:${executionId}`,
464
+ definitionRevision: createHash('sha256')
465
+ .update(JSON.stringify(definition))
466
+ .digest('hex'),
467
+ lifetime: 'execution',
468
+ exposure: 'deferred'
469
+ }))
470
+ };
471
+ };
472
+ const mcpCatalog = await readMcpCatalog();
473
+ const mcpRegistry = new DeferredMcpRegistry(discoveredMcpToolNames(messages));
474
+ const mcpTools = mcpCatalog.tools.map((tool) => tool.definition);
475
+ const extensions = (await host.listExecutionExtensions?.(catalogContext)) ?? {};
476
+ if (extensions.tools?.some((tool) => tool.name.startsWith('mcp__')))
477
+ throw new MarAgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Host tools cannot use the MCP namespace.');
478
+ const selectedModelForTools = executionModels.get(input.modelId ?? executionDefaultModelId);
479
+ const builtinTools = BUILTIN_TOOL_DEFINITIONS.map((tool) => tool.name === 'agent_start'
480
+ ? agentStartToolDefinitionWithModels([...executionModels.values()].map((configuration) => ({
481
+ id: configuration.id,
482
+ name: configuration.name,
483
+ reasoningEfforts: configuration.reasoningEfforts
484
+ })))
485
+ : tool);
486
+ const combinedTools = [...builtinTools, ...(extensions.tools ?? []), ...mcpTools];
487
+ if (new Set(combinedTools.map((tool) => tool.name)).size !== combinedTools.length)
488
+ throw new MarAgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Tool names conflict.');
489
+ const toolEligible = (tool) => {
490
+ toolCallers(tool);
491
+ if (sessionSource.type === 'subagent' && tool.agentScope === 'ROOT_ONLY')
492
+ return false;
493
+ if (sessionSource.type === 'subagent' &&
494
+ (tool.name.startsWith('agent_') || tool.name === 'question'))
495
+ return false;
496
+ if (tool.name === 'tool_search')
497
+ return mcpRegistry.hasDeferred;
498
+ return tool.name === 'code_exec' || tool.name === 'code_exec_wait'
499
+ ? selectedModelForTools.codeMode && description.capabilities.includes('code.execute')
500
+ : tool.name === 'question'
501
+ ? mode === 'plan'
502
+ : tool.name === 'web_search'
503
+ ? !selectedModelForTools.hostedWebSearch &&
504
+ description.capabilities.includes('web.search')
505
+ : tool.name === 'view_image'
506
+ ? selectedModelForTools.inputCapabilities.includes('IMAGE')
507
+ : tool.name !== 'web_fetch' || description.capabilities.includes('web.fetch');
508
+ };
509
+ mcpRegistry.update(mcpCatalog, (tool) => toolEligible(tool.definition));
510
+ rebindMcpToolSearchOutputs(messages, mcpRegistry);
511
+ const availableTools = combinedTools.filter(toolEligible);
512
+ const instructionContext = await loadAgentInstructions({
513
+ home: description.homeDirectory,
514
+ workspace: instructionWorkspace,
515
+ availableTools: new Set(availableTools.map((tool) => tool.name)),
516
+ hostSkills: extensions.skills ?? [],
517
+ ...(settings.workspaceMapping === undefined
518
+ ? {}
519
+ : { workspaceDisplayPath: logicalWorkspace })
520
+ });
521
+ const instructionEntries = instructionContext?.entries ?? [];
522
+ const currentInstructionSnapshot = renderAgentInstructions(instructionEntries, false);
523
+ let agentInstructionInsertIndex = mode === 'compact'
524
+ ? contextualInstructionInsertIndex(messages)
525
+ : (currentExecutionUserIndex ?? Math.max(0, messages.length - 1));
526
+ if (mode !== 'compact' &&
527
+ agentInstructionInsertIndex &&
528
+ messages[agentInstructionInsertIndex - 1]?.contextKind === 'environment')
529
+ agentInstructionInsertIndex--;
530
+ const baseTools = () => [...builtinTools, ...(extensions.tools ?? [])].filter((tool) => toolEligible(tool) &&
531
+ (tool.name !== 'skill' || (instructionContext?.skills.size ?? 0) > 0));
532
+ let executionTools = mcpRegistry.project(baseTools());
533
+ const restoreMcpDiscovery = () => {
534
+ mcpRegistry.restore(discoveredMcpToolNames(messages));
535
+ rebindMcpToolSearchOutputs(messages, mcpRegistry);
536
+ executionTools = mcpRegistry.project(baseTools());
537
+ };
538
+ const loadRetainedSessionResources = async () => {
539
+ const hostResources = (await host.listSessionResources?.(sessionId)) ?? {
540
+ processes: []
541
+ };
542
+ return {
543
+ ...(hostResources.idleTtlMs === undefined
544
+ ? {}
545
+ : { idleTtlMs: hostResources.idleTtlMs }),
546
+ processes: hostResources.processes,
547
+ ...(hostResources.codeCells ? { codeCells: hostResources.codeCells } : {}),
548
+ subagents: subagents?.listSessionResources() ?? []
549
+ };
550
+ };
551
+ let currentResourceSnapshot = retainedSessionResourcesSnapshot(await loadRetainedSessionResources());
552
+ const previousContextualWorldState = contextualWorldState;
553
+ contextualWorldState = updateContextualWorldState(contextualWorldState, agentInstructionInsertIndex, {
554
+ instructionSnapshot: currentInstructionSnapshot,
555
+ instructionContent: renderAgentInstructions(instructionEntries, compactMayContainAgentInstructions ||
556
+ contextualWorldState.instructionSnapshot !== undefined),
557
+ resourceSnapshot: currentResourceSnapshot,
558
+ previousMayContainResources: (!contextualWorldState.initialized && compactMayContainRetainedResources) ||
559
+ (host.listSessionResources !== undefined &&
560
+ currentResourceSnapshot === undefined &&
561
+ messages
562
+ .slice(contextualWorldState.entries.findLast((entry) => entry.kind === 'resources')
563
+ ?.index ?? 0)
564
+ .some((message) => message.role === 'tool_call' &&
565
+ ['exec', 'code_exec', 'code_mode', 'agent_start'].includes(message.name ?? '')))
566
+ });
567
+ sessionRuntime.contextualWorldState = contextualWorldState;
568
+ if (!isDeepStrictEqual(previousContextualWorldState, contextualWorldState))
569
+ await persistContextualWorldState(store, sessionId, contextualWorldState);
570
+ const buildExecutionSystemPrompt = (availableTools = executionTools, promptMode = mode) => buildSystemPrompt({
571
+ mode: promptMode,
572
+ platform: description.platform,
573
+ ...(description.architecture ? { architecture: description.architecture } : {}),
574
+ ...(description.shell ? { shell: description.shell } : {}),
575
+ ...(description.guaranteedCommands
576
+ ? { guaranteedCommands: description.guaranteedCommands }
577
+ : {}),
578
+ workspace: logicalWorkspace,
579
+ tools: availableTools
580
+ .filter((tool) => !tool.name.startsWith('mcp__'))
581
+ .map((tool) => tool.name),
582
+ directTools: availableTools
583
+ .filter((tool) => !tool.name.startsWith('mcp__') &&
584
+ allowsDirectTool(tool, availableTools.some((candidate) => candidate.name === 'code_exec')))
585
+ .map((tool) => tool.name),
586
+ highDensityCompaction: selectedModel.highDensityCompaction,
587
+ extension: [
588
+ settings.systemInstruction,
589
+ instructionContext?.skillCatalog,
590
+ sessionSource.type === 'subagent' ? childSubagentInstruction : undefined
591
+ ]
592
+ .filter(Boolean)
593
+ .join('\n\n')
594
+ });
595
+ const syncMcpWorldState = async (index) => {
596
+ const snapshot = mcpRegistry.navigation();
597
+ if (contextualWorldState.mcpSnapshot === snapshot)
598
+ return;
599
+ contextualWorldState = {
600
+ ...contextualWorldState,
601
+ mcpSnapshot: snapshot,
602
+ entries: [
603
+ ...contextualWorldState.entries,
604
+ {
605
+ index,
606
+ kind: 'mcp',
607
+ content: snapshot ?? '<mcp_catalog>No deferred MCP tools remain.</mcp_catalog>'
608
+ }
609
+ ]
610
+ };
611
+ sessionRuntime.contextualWorldState = contextualWorldState;
612
+ await persistContextualWorldState(store, sessionId, contextualWorldState);
613
+ };
614
+ if (mode !== 'compact')
615
+ await syncMcpWorldState(agentInstructionInsertIndex);
616
+ const initialSystemPrompt = mode === 'compact'
617
+ ? buildExecutionSystemPrompt(executionTools, 'run')
618
+ : buildExecutionSystemPrompt();
619
+ let useManualCompactionFallback;
620
+ if (mode === 'compact') {
621
+ const compactSystemPrompt = initialSystemPrompt;
622
+ const compactHistory = [...messages];
623
+ const projectedHistory = normalizeMessagesForModel(insertContextualWorldState(compactHistory, contextualWorldState.entries), { supportsImages: false });
624
+ const nativeMessages = buildNativeCompactionMessages(projectedHistory, {
625
+ focus: input.prompt,
626
+ highDensityCompaction: selectedModel.highDensityCompaction
627
+ });
628
+ const compactOverheadTokens = estimatedRequestTokens(compactSystemPrompt, buildCompactionMessages('', selectedModel.highDensityCompaction), executionTools);
629
+ const compactInputTokens = selectedModel.contextWindowTokens - compactOverheadTokens;
630
+ if (compactInputTokens <= 0)
631
+ throw new MarAgentError('MAR_AGENT_CONTEXT_LIMIT', 'Compaction prompt exceeds the selected model context window.');
632
+ const fallbackMessages = () => buildCompactionMessages(buildCompactionInput(compactHistory, {
633
+ focus: input.prompt,
634
+ maxTokens: compactInputTokens
635
+ }), selectedModel.highDensityCompaction);
636
+ const useNative = shouldUseNativeCompaction({
637
+ estimatedRequestTokens: estimatedRequestTokens(compactSystemPrompt, nativeMessages, executionTools),
638
+ contextWindowTokens: selectedModel.contextWindowTokens,
639
+ latestUsage: lastServerUsage,
640
+ historyMessages: compactHistory,
641
+ appendedMessages: nativeMessages.slice(projectedHistory.length)
642
+ });
643
+ messages.splice(0, messages.length, ...(useNative ? nativeMessages : fallbackMessages()));
644
+ if (useNative) {
645
+ let available = true;
646
+ useManualCompactionFallback = () => {
647
+ if (!available)
648
+ return false;
649
+ available = false;
650
+ messages.splice(0, messages.length, ...fallbackMessages());
651
+ return true;
652
+ };
653
+ }
654
+ }
655
+ await store.append(sessionId, {
656
+ type: 'execution.header',
657
+ payload: {
658
+ promptVersion: MAR_AGENT_PROMPT_VERSION,
659
+ promptHash: createHash('sha256').update(initialSystemPrompt).digest('hex'),
660
+ modelId: selectedModel.id,
661
+ modelName: selectedModel.name,
662
+ reasoningEffort,
663
+ contextWindowTokens: selectedModel.contextWindowTokens,
664
+ mode
665
+ },
666
+ executionId,
667
+ turnId
668
+ });
669
+ let lastServerContextTokens = lastServerUsage?.contextInputTokens;
670
+ const compactContext = async () => {
671
+ const current = messages.at(-1);
672
+ if (!current || messages.length < 2)
673
+ return false;
674
+ const retainCurrent = current.role === 'user' && current.contextKind !== 'environment';
675
+ let compactSummary = '';
676
+ const compactSystemPrompt = buildExecutionSystemPrompt(executionTools, 'run');
677
+ const compactHistory = retainCurrent ? messages.slice(0, -1) : messages;
678
+ const projectedHistory = normalizeMessagesForModel(insertContextualWorldState(compactHistory, contextualWorldState.entries), { supportsImages: false });
679
+ const nativeCompactMessages = buildNativeCompactionMessages(projectedHistory, {
680
+ highDensityCompaction: selectedModel.highDensityCompaction
681
+ });
682
+ const compactOverheadTokens = estimatedRequestTokens(compactSystemPrompt, buildCompactionMessages('', selectedModel.highDensityCompaction), executionTools);
683
+ const compactInputTokens = Math.max(0, selectedModel.contextWindowTokens - compactOverheadTokens);
684
+ if (compactInputTokens === 0)
685
+ throw new MarAgentError('MAR_AGENT_CONTEXT_LIMIT', 'Compaction prompt exceeds the selected model context window.');
686
+ let usingNativeMessages = shouldUseNativeCompaction({
687
+ estimatedRequestTokens: estimatedRequestTokens(compactSystemPrompt, nativeCompactMessages, executionTools),
688
+ contextWindowTokens: selectedModel.contextWindowTokens,
689
+ latestUsage: lastServerUsage,
690
+ historyMessages: compactHistory,
691
+ appendedMessages: nativeCompactMessages.slice(projectedHistory.length)
692
+ });
693
+ const fallbackMessages = () => buildCompactionMessages(buildCompactionInput(compactHistory, {
694
+ maxTokens: Math.max(1, compactInputTokens)
695
+ }), selectedModel.highDensityCompaction);
696
+ let compactMessages = usingNativeMessages ? nativeCompactMessages : fallbackMessages();
697
+ const compactionId = randomUUID();
698
+ await emit({ type: 'context.compacting', compactionId });
699
+ let latestUsage;
700
+ const compactionRetryState = { attempts: 0 };
701
+ const operation = createCompactionOperation(compactionId);
702
+ try {
703
+ while (true) {
704
+ compactSummary = '';
705
+ latestUsage = undefined;
706
+ try {
707
+ for await (const event of operation.start(selected, {
708
+ retryState: compactionRetryState,
709
+ system: compactSystemPrompt,
710
+ messages: compactMessages,
711
+ tools: executionTools,
712
+ toolChoice: 'none',
713
+ promptCacheKey: sessionId,
714
+ reasoningEffort: requestReasoningEffort ?? reasoningEffort,
715
+ onAttemptDiagnostic: recordModelAttempt('COMPACTION')
716
+ })) {
717
+ if (event.type === 'text.completed' &&
718
+ (event.phase ?? 'final_answer') === 'final_answer')
719
+ compactSummary = event.text.trim();
720
+ else if (event.type === 'usage') {
721
+ latestUsage = event.usage;
722
+ await emit({ type: 'usage.updated', ...publicModelUsage(event.usage) });
723
+ }
724
+ else if (event.type === 'client_tool.call')
725
+ throw new MarAgentError('MAR_AGENT_MODEL_PROTOCOL_ERROR', 'Compaction returned a tool call while tools were disabled.');
726
+ }
727
+ break;
728
+ }
729
+ catch (error) {
730
+ if (await recoverModelStream(error, compactionRetryState, operation.signal)) {
731
+ continue;
732
+ }
733
+ if (isProviderContextOverflow(error) && usingNativeMessages) {
734
+ usingNativeMessages = false;
735
+ compactMessages = fallbackMessages();
736
+ compactionRetryState.attempts = 0;
737
+ continue;
738
+ }
739
+ if (isProviderContextOverflow(error))
740
+ throw new MarAgentError('MAR_AGENT_CONTEXT_LIMIT', 'The compaction request exceeds the model context window.', { cause: error });
741
+ throw error;
742
+ }
743
+ }
744
+ }
745
+ finally {
746
+ await operation.dispose();
747
+ }
748
+ if (!compactSummary)
749
+ throw new MarAgentError('MAR_AGENT_COMPACT_FAILED', 'Automatic compact failed.');
750
+ rolloutBudget?.recordUsage(latestUsage);
751
+ const replacementHistory = buildCompactedHistory(compactSummary, retainCurrent ? compactionUserMessages.slice(0, -1) : compactionUserMessages, compactUserTokenLimit, retainCurrent ? current.content : undefined);
752
+ const compactRecord = await store.compact(sessionId, {
753
+ summary: compactSummary,
754
+ replacementHistory,
755
+ automatic: true,
756
+ environment: executionEnvironment,
757
+ modelId: selectedModel.id,
758
+ contextWindowTokens: selectedModel.contextWindowTokens,
759
+ ...(latestUsage === undefined ? {} : { usage: latestUsage }),
760
+ executionId,
761
+ turnId
762
+ });
763
+ contextGc.reset();
764
+ messages.splice(0, messages.length, environmentContextUpdate(executionEnvironment), ...compactedHistoryMessages(replacementHistory));
765
+ restoreMcpDiscovery();
766
+ projectedExecutionBudgetStage = undefined;
767
+ recordedEnvironment = executionEnvironment;
768
+ compactionUserMessages = replacementHistory
769
+ .filter((message) => message.kind === 'user_input')
770
+ .map((message) => message.content);
771
+ agentInstructionInsertIndex = Math.max(0, messages.length - 1);
772
+ currentResourceSnapshot = retainedSessionResourcesSnapshot(await loadRetainedSessionResources());
773
+ contextualWorldState = resetContextualWorldState(compactRecord.recordId, agentInstructionInsertIndex, {
774
+ instructionSnapshot: currentInstructionSnapshot,
775
+ instructionContent: renderAgentInstructions(instructionEntries, true),
776
+ resourceSnapshot: currentResourceSnapshot,
777
+ previousMayContainResources: compactSummary.includes('# Retained Session resources')
778
+ });
779
+ sessionRuntime.contextualWorldState = contextualWorldState;
780
+ await persistContextualWorldState(store, sessionId, contextualWorldState);
781
+ lastServerContextTokens = undefined;
782
+ lastServerUsage = undefined;
783
+ requestReasoningEffort = reasoningEffort;
784
+ effectiveReasoningEffort = reasoningEffort;
785
+ await emit({ type: 'context.compacted', compactionId });
786
+ return true;
787
+ };
788
+ const ensureContextBudget = async () => {
789
+ if (mode === 'compact' || lastServerContextTokens === undefined)
790
+ return;
791
+ const hardLimit = selectedModel.contextWindowTokens;
792
+ const compactLimit = Math.floor((hardLimit * AGENT_EXECUTION_POLICY.automaticCompactionPercent) / 100);
793
+ if (lastServerContextTokens < compactLimit)
794
+ return;
795
+ if (!(await compactContext()))
796
+ throw new MarAgentError('MAR_AGENT_CONTEXT_LIMIT', 'Provider usage reached the compaction threshold but no history can be compacted.');
797
+ };
798
+ executionLoop = new ExecutionLoop({
799
+ mode,
800
+ sourceType: sessionSource.type,
801
+ signal: controller.signal,
802
+ model: selectedModel,
803
+ messages,
804
+ toolImages: currentExecutionToolImages,
805
+ rolloutBudget,
806
+ publish: emit,
807
+ appendContext: async (message) => {
808
+ await store.append(sessionId, {
809
+ type: 'model.context',
810
+ payload: message,
811
+ executionId,
812
+ turnId
813
+ });
814
+ },
815
+ prepareRound: async (pendingOutputContinuation) => {
816
+ await appendMailboxMessages();
817
+ appendExecutionBudgetEnvironment();
818
+ executionTools = mcpRegistry.project(baseTools());
819
+ if (mode !== 'compact')
820
+ await syncMcpWorldState(messages.length);
821
+ await ensureContextBudget();
822
+ if (mode !== 'compact')
823
+ await syncMcpWorldState(messages.length);
824
+ appendExecutionBudgetEnvironment();
825
+ if (mode !== 'compact') {
826
+ executionEnvironment = { ...currentEnvironment, ...currentLocalTimeContext() };
827
+ await recordEnvironment();
828
+ }
829
+ const toolsAllowed = mode !== 'compact' &&
830
+ (!rolloutBudget?.active || rolloutBudget.stage !== 'exhausted');
831
+ const roundTools = mode === 'compact' ? executionTools : toolsAllowed ? executionTools : [];
832
+ const codeModeEnabled = roundTools.some((tool) => tool.name === 'code_exec');
833
+ const residentTools = mcpRegistry.projectDirect(baseTools());
834
+ const requestTools = (() => {
835
+ if (selectedModel.protocol !== 'OPENAI_RESPONSES' ||
836
+ selectedModel.responsesEncoding === 'LITE')
837
+ return projectCodeModeTools(roundTools, residentTools);
838
+ const directNames = new Set(residentTools.map((tool) => tool.name));
839
+ // Discovery and caller policy are independent: keep nested declarations for active tools.
840
+ return projectCodeModeTools(roundTools, residentTools).filter((tool) => directNames.has(tool.name));
841
+ })();
842
+ const systemPrompt = mode === 'compact'
843
+ ? buildExecutionSystemPrompt(roundTools, 'run')
844
+ : buildExecutionSystemPrompt(roundTools);
845
+ const requestContextMessages = pendingOutputContinuation === undefined
846
+ ? messages
847
+ : [...messages, pendingOutputContinuation];
848
+ const modelMessages = mode === 'compact'
849
+ ? normalizeMessagesForModel(requestContextMessages, { supportsImages: false })
850
+ : normalizeMessagesForModel(insertContextualWorldState(requestContextMessages, contextualWorldState.entries), {
851
+ supportsImages: selectedModel.inputCapabilities.includes('IMAGE')
852
+ });
853
+ const roundMcpExpectations = new Map(roundTools
854
+ .filter((tool) => tool.name.startsWith('mcp__'))
855
+ .map((tool) => [tool.name, mcpRegistry.expectedTool(tool.name)]));
856
+ const toolContext = {
857
+ host: host,
858
+ todo,
859
+ ...(subagents === undefined ? {} : { subagents }),
860
+ mode,
861
+ sessionId,
862
+ executionId,
863
+ signal: controller.signal,
864
+ emit,
865
+ skills: instructionContext?.skills ?? new Map()
866
+ };
867
+ const recentImages = () => currentExecutionImages(modelInputImages, currentExecutionToolImages);
868
+ const toolScope = {
869
+ context: toolContext,
870
+ tools: roundTools,
871
+ expectations: roundMcpExpectations,
872
+ extensionToolNames: new Set((extensions.tools ?? []).map((tool) => tool.name)),
873
+ schedule: sessionRuntime.scheduleTool,
874
+ emit,
875
+ searchMcpTools: (arguments_, searchSignal) => mcpRegistry.expose(arguments_, {
876
+ signal: searchSignal,
877
+ base: baseTools(),
878
+ window: selectedModel.contextWindowTokens,
879
+ system: systemPrompt
880
+ }),
881
+ recentImages,
882
+ captureCodeContext: () => ({
883
+ ...toolContext,
884
+ ...(subagents ? { subagents: subagents.captureExecution() } : {}),
885
+ recentImages: recentImages()
886
+ }),
887
+ codeModeContext: async (call) => {
888
+ const stateSnapshot = call.name === 'code_exec' ? await store.readCodeModeState(sessionId) : [];
889
+ return {
890
+ retainSession: () => store.retainSessionLease(sessionId, sessionWriterOwner),
891
+ onSettled: async (result) => {
892
+ await store.append(sessionId, {
893
+ type: 'code.cell.completed',
894
+ payload: { ...result, callId: call.callId },
895
+ executionId,
896
+ turnId
897
+ });
898
+ },
899
+ supportsImages: selectedModel.inputCapabilities.includes('IMAGE'),
900
+ tools: roundTools.filter((tool) => allowsToolCaller(tool, 'programmatic')),
901
+ state: stateSnapshot,
902
+ commitState: (mutations) => store.commitCodeModeState(sessionId, mutations, {
903
+ executionId,
904
+ turnId,
905
+ expectedState: stateSnapshot
906
+ })
907
+ };
908
+ }
909
+ };
910
+ return {
911
+ request: {
912
+ system: systemPrompt,
913
+ messages: modelMessages.map((message) => projectCodeModeSearchResult(message, codeModeEnabled)),
914
+ tools: requestTools,
915
+ ...(mode === 'compact'
916
+ ? { toolChoice: 'none' }
917
+ : toolsAllowed
918
+ ? {}
919
+ : { allowTools: false }),
920
+ promptCacheKey: sessionId,
921
+ reasoningEffort,
922
+ ...(requestReasoningEffort === undefined ? {} : { requestReasoningEffort }),
923
+ ...(modelInputImages?.length ? { images: modelInputImages } : {}),
924
+ onAttemptDiagnostic: recordModelAttempt(mode === 'compact' ? 'COMPACTION' : 'EXECUTION')
925
+ },
926
+ toolScope
927
+ };
928
+ },
929
+ startModel: async function* (request) {
930
+ if (manualCompactionId !== undefined && !manualCompactionStarted) {
931
+ manualCompactionStarted = true;
932
+ manualCompaction = createCompactionOperation(manualCompactionId);
933
+ await emit({ type: 'context.compacting', compactionId: manualCompactionId });
934
+ }
935
+ yield* manualCompaction
936
+ ? manualCompaction.start(selected, request)
937
+ : selected.start(request, controller.signal);
938
+ },
939
+ recoverySignal: () => manualCompaction?.signal ?? controller.signal,
940
+ compactContext,
941
+ compactionFallback: useManualCompactionFallback,
942
+ observeContextTokens: (tokens) => {
943
+ lastServerContextTokens = tokens;
944
+ },
945
+ observeUsage: (usage) => {
946
+ if (usage !== undefined) {
947
+ lastServerContextTokens = usage.contextInputTokens;
948
+ lastServerUsage = { ...usage, historyMessages: [...messages] };
949
+ }
950
+ },
951
+ checkpoint: async (round, latestUsage) => {
952
+ if (mode !== 'compact' &&
953
+ sessionSource.type !== 'subagent' &&
954
+ latestUsage !== undefined) {
955
+ // Only a committed GC checkpoint may replace active context and invalidate continuation.
956
+ const committed = await contextGc.run({
957
+ store,
958
+ sessionId,
959
+ system: round.request.system,
960
+ tools: round.toolScope.tools,
961
+ modelId: selectedModel.id,
962
+ contextWindowTokens: selectedModel.contextWindowTokens,
963
+ usage: latestUsage,
964
+ modelProtocol: selectedModel.protocol,
965
+ responsesConfigurationUpdates: usesResponsesConfigurationUpdates(selectedModel),
966
+ workspace: logicalWorkspace,
967
+ platform: description.platform,
968
+ getActiveProcessIds: async () => {
969
+ const resources = await host
970
+ .listSessionResources?.(sessionId)
971
+ .catch(() => undefined);
972
+ return new Set((resources?.processes ?? [])
973
+ .filter((process) => process.status === 'running')
974
+ .map((process) => process.processId));
975
+ }
976
+ });
977
+ if (committed) {
978
+ selected.resetContinuation?.();
979
+ const refreshed = await restoreMessages(store, sessionId, committed.records, {
980
+ includeImages: true,
981
+ currentTurnId: turnId,
982
+ projection: committed.projection
983
+ });
984
+ messages.splice(0, messages.length, ...refreshed.messages);
985
+ restoreMcpDiscovery();
986
+ projectedExecutionBudgetStage = undefined;
987
+ recordedEnvironment = refreshed.environmentState;
988
+ compactionUserMessages = [...refreshed.userMessages];
989
+ agentInstructionInsertIndex =
990
+ refreshed.currentTurnUserIndex ?? Math.max(0, messages.length - 1);
991
+ if (agentInstructionInsertIndex &&
992
+ messages[agentInstructionInsertIndex - 1]?.contextKind === 'environment')
993
+ agentInstructionInsertIndex--;
994
+ currentResourceSnapshot = retainedSessionResourcesSnapshot(await loadRetainedSessionResources());
995
+ contextualWorldState = resetContextualWorldState(latestContextualWorldStateGeneration(committed.records), agentInstructionInsertIndex, {
996
+ instructionSnapshot: currentInstructionSnapshot,
997
+ instructionContent: renderAgentInstructions(instructionEntries, committed.records.some((record) => compactSummaryFromCheckpoint(record) !== undefined)),
998
+ resourceSnapshot: currentResourceSnapshot,
999
+ previousMayContainResources: compactHistoryMayContainRetainedResources(committed.records)
1000
+ });
1001
+ sessionRuntime.contextualWorldState = contextualWorldState;
1002
+ await persistContextualWorldState(store, sessionId, contextualWorldState);
1003
+ }
1004
+ }
1005
+ },
1006
+ mailbox: {
1007
+ hasPending: () => mailbox.length > 0,
1008
+ append: appendMailboxMessages,
1009
+ close: () => {
1010
+ acceptsMailbox = false;
1011
+ }
1012
+ }
1013
+ });
1014
+ const completed = await executionLoop.run();
1015
+ finalAnswer = completed.finalAnswer;
1016
+ const compactSummary = mode === 'compact' ? finalAnswer.trim() : '';
1017
+ if (manualCompaction) {
1018
+ manualCompaction.signal.throwIfAborted();
1019
+ await manualCompaction.dispose();
1020
+ }
1021
+ if (mode === 'compact')
1022
+ await store.compact(sessionId, {
1023
+ summary: compactSummary,
1024
+ replacementHistory: buildCompactedHistory(compactSummary, compactionUserMessages, compactUserTokenLimit),
1025
+ modelId: selectedModel.id,
1026
+ contextWindowTokens: selectedModel.contextWindowTokens,
1027
+ ...(completed.usage === undefined ? {} : { usage: completed.usage }),
1028
+ executionId,
1029
+ turnId
1030
+ });
1031
+ if (mode === 'compact' && manualCompactionId !== undefined)
1032
+ await emit({ type: 'context.compacted', compactionId: manualCompactionId });
1033
+ await settleTitle();
1034
+ subagents?.endParentExecution(executionId);
1035
+ await emit({ type: 'execution.completed' });
1036
+ return {
1037
+ executionId,
1038
+ status: 'completed',
1039
+ finalAnswer: mode === 'compact' ? '' : finalAnswer
1040
+ };
1041
+ }
1042
+ catch (error) {
1043
+ finalAnswer = executionLoop?.finalAnswer ?? finalAnswer;
1044
+ acceptsMailbox = false;
1045
+ await settleTitle();
1046
+ if (controller.signal.aborted) {
1047
+ subagents?.endParentExecution(executionId);
1048
+ await emit({ type: 'execution.cancelled' });
1049
+ return {
1050
+ executionId,
1051
+ status: 'cancelled',
1052
+ finalAnswer: mode === 'compact' ? '' : finalAnswer
1053
+ };
1054
+ }
1055
+ const diagnostic = modelAttemptFailureDiagnostic(describeMarAgentError(error, 'MAR_AGENT_EXECUTION_FAILED'), exhaustedModelAttempt);
1056
+ subagents?.endParentExecution(executionId);
1057
+ await emit({ type: 'execution.failed', ...diagnostic });
1058
+ return {
1059
+ executionId,
1060
+ status: 'failed',
1061
+ finalAnswer: mode === 'compact' ? '' : finalAnswer,
1062
+ errorCode: diagnostic.code,
1063
+ errorMessage: diagnostic.message
1064
+ };
1065
+ }
1066
+ finally {
1067
+ acceptsMailbox = false;
1068
+ if (ownsRolloutBudget)
1069
+ rolloutBudget.discard();
1070
+ await manualCompaction?.dispose();
1071
+ await selectedTurn?.close().catch(() => undefined);
1072
+ if (titleAdapter !== undefined && titleAdapter !== selectedAdapter)
1073
+ executionScopedAdapters.add(titleAdapter);
1074
+ try {
1075
+ await closeModelAdapters(executionScopedAdapters);
1076
+ }
1077
+ catch {
1078
+ // Execution cleanup is best effort.
1079
+ }
1080
+ finally {
1081
+ for (const adapter of executionScopedAdapters)
1082
+ activeExecutionAdapters.delete(adapter);
1083
+ }
1084
+ subagents?.endParentExecution(executionId);
1085
+ await releaseSession?.();
1086
+ active.delete(`${sessionId}:${executionId}`);
1087
+ queue.close();
1088
+ }
1089
+ })();
1090
+ const executionKey = `${sessionId}:${executionId}`;
1091
+ executionResults.set(executionKey, result);
1092
+ void result.then(() => executionResults.delete(executionKey), () => executionResults.delete(executionKey));
1093
+ return {
1094
+ executionId,
1095
+ turnId,
1096
+ [Symbol.asyncIterator]: () => queue[Symbol.asyncIterator](),
1097
+ result: () => {
1098
+ queue.discardIfUnobserved();
1099
+ return result;
1100
+ },
1101
+ cancel: () => controller.abort(new MarAgentError('MAR_AGENT_CANCELLED', 'Execution was cancelled.')),
1102
+ enqueueMessage: (message, delivery) => {
1103
+ if (!acceptsMailbox || controller.signal.aborted)
1104
+ return false;
1105
+ mailbox.push({ text: message, ...(delivery ? { delivery } : {}) });
1106
+ return true;
1107
+ }
1108
+ };
1109
+ };
1110
+ return {
1111
+ id: sessionId,
1112
+ run: (input) => execution('run', input),
1113
+ plan: (input) => execution('plan', input),
1114
+ compact: (input = {}) => execution('compact', {
1115
+ prompt: input.prompt ?? DEFAULT_COMPACTION_FOCUS,
1116
+ ...input
1117
+ }),
1118
+ cancel: async (executionId) => active.get(`${sessionId}:${executionId}`)?.abort(),
1119
+ startSubagentTurn: (turn) => execution(turn.role === 'explore' ? 'plan' : 'run', {
1120
+ prompt: turn.prompt,
1121
+ modelId: turn.modelId,
1122
+ reasoningEffort: turn.reasoningEffort
1123
+ }, {
1124
+ publishHostEvents: false,
1125
+ inputSource: 'parent_agent',
1126
+ initialMailbox: turn.initialMailbox,
1127
+ turnId: turn.turnId,
1128
+ mcpExecutionScopeId: turn.mcpExecutionScopeId,
1129
+ ...(turn.delivery ? { delivery: turn.delivery } : {}),
1130
+ ...(turn.sharedRolloutBudget === undefined
1131
+ ? {}
1132
+ : { sharedRolloutBudget: turn.sharedRolloutBudget })
1133
+ })
1134
+ };
1135
+ };
1136
+ return openSession;
1137
+ }
1138
+ function modelAttemptFailureDiagnostic(diagnostic, summary) {
1139
+ if (summary === undefined)
1140
+ return diagnostic;
1141
+ const prefix = `Model request failed after ${summary.attempts} attempts (${summary.retries} retries). `;
1142
+ const availableCharacters = Math.max(0, 1_000 - [...prefix].length);
1143
+ return {
1144
+ code: diagnostic.code,
1145
+ message: `${prefix}${[...diagnostic.message].slice(0, availableCharacters).join('')}`
1146
+ };
1147
+ }