@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,397 @@
1
+ import { MarAgentError } from '../error.js';
2
+ import { isProviderContextOverflow, recoverModelStream } from '../model/recovery.js';
3
+ import { modelStreamEventObservedAt } from '../model/sse.js';
4
+ import { modelOutputContinuationMessage } from '../prompts/output.js';
5
+ import { executeRoundTools } from '../tools/execution.js';
6
+ import { publicModelUsage } from './event-projection.js';
7
+ import { PlanOutputPrefix, splitPlanOutput } from './plan-output.js';
8
+ /** Own the single model/tool loop; the SDK owns its handle, terminal events and cleanup. */
9
+ export class ExecutionLoop {
10
+ input;
11
+ #finalAnswer = '';
12
+ planOutputPrefixes = new Map();
13
+ get finalAnswer() {
14
+ return this.#finalAnswer;
15
+ }
16
+ set finalAnswer(value) {
17
+ this.#finalAnswer = value;
18
+ }
19
+ constructor(input) {
20
+ this.input = input;
21
+ }
22
+ async run() {
23
+ const input = this.input;
24
+ const { mode, messages } = input;
25
+ let recoveringFromContextOverflow = false;
26
+ let maxOutputContinuationUsed = false;
27
+ let pendingOutputContinuation;
28
+ const modelRetryState = { attempts: 0 };
29
+ while (true) {
30
+ let stop;
31
+ let sawTool = false;
32
+ let latestUsage;
33
+ let roundServerUsage;
34
+ const pendingTools = [];
35
+ let incompleteToolCall = false;
36
+ const round = await input.prepareRound(pendingOutputContinuation);
37
+ let sawModelSemanticEvent = false;
38
+ let requestStartedAt;
39
+ let firstModelResponseAt;
40
+ let firstOutputDeltaAt;
41
+ let lastOutputDeltaAt;
42
+ let requestCompletedAt;
43
+ let requestOutputTokens;
44
+ const roundMessageCount = messages.length;
45
+ const emitLatency = async () => {
46
+ if (mode === 'compact' || firstModelResponseAt === undefined)
47
+ return;
48
+ await input.publish({
49
+ type: 'model.performance',
50
+ latencyMs: Math.max(0, Math.round(firstModelResponseAt - requestStartedAt))
51
+ });
52
+ };
53
+ const emitFinalPerformance = async (completedAt) => {
54
+ if (mode === 'compact' ||
55
+ firstModelResponseAt === undefined ||
56
+ firstOutputDeltaAt === undefined ||
57
+ lastOutputDeltaAt === undefined ||
58
+ lastOutputDeltaAt - firstOutputDeltaAt < 1)
59
+ return;
60
+ const outputDuration = completedAt - firstOutputDeltaAt;
61
+ const outputTokens = requestOutputTokens;
62
+ if (outputTokens === undefined || outputDuration < 1 || completedAt < lastOutputDeltaAt)
63
+ return;
64
+ await input.publish({
65
+ type: 'model.performance',
66
+ latencyMs: Math.max(0, Math.round(firstModelResponseAt - requestStartedAt)),
67
+ outputTokens,
68
+ outputDurationMs: Math.round(outputDuration),
69
+ tokensPerSecond: Number(((outputTokens * 1000) / outputDuration).toFixed(2))
70
+ });
71
+ };
72
+ const persistToolCalls = async (calls) => {
73
+ for (const call of calls) {
74
+ const message = {
75
+ role: 'tool_call',
76
+ callId: call.callId,
77
+ name: call.name,
78
+ arguments: call.arguments,
79
+ ...(call.inputMode ? { inputMode: call.inputMode } : {}),
80
+ content: ''
81
+ };
82
+ messages.push(message);
83
+ await input.appendContext(message);
84
+ }
85
+ };
86
+ try {
87
+ requestStartedAt = performance.now();
88
+ for await (const event of input.startModel({
89
+ ...round.request,
90
+ retryState: modelRetryState
91
+ })) {
92
+ if (event.type === 'output.reset') {
93
+ firstOutputDeltaAt = undefined;
94
+ lastOutputDeltaAt = undefined;
95
+ requestOutputTokens = undefined;
96
+ continue;
97
+ }
98
+ const modelResponseAt = mode !== 'compact' && isModelResponseEvent(event)
99
+ ? Math.max(requestStartedAt, modelStreamEventObservedAt(event) ?? performance.now())
100
+ : undefined;
101
+ const isFirstModelResponse = modelResponseAt !== undefined && firstModelResponseAt === undefined;
102
+ if (modelResponseAt !== undefined) {
103
+ if (event.type !== 'output.delta')
104
+ sawModelSemanticEvent = true;
105
+ firstModelResponseAt ??= modelResponseAt;
106
+ if (event.type === 'output.delta' ||
107
+ (event.type === 'text.delta' && event.delta.length > 0)) {
108
+ firstOutputDeltaAt ??= modelResponseAt;
109
+ lastOutputDeltaAt = modelResponseAt;
110
+ }
111
+ }
112
+ if (event.type === 'response.item') {
113
+ // Compaction keeps only its successful checkpoint, never intermediate native output.
114
+ if (mode === 'compact')
115
+ continue;
116
+ const message = {
117
+ role: 'provider',
118
+ content: '',
119
+ provider: event.provider,
120
+ providerModelId: input.model.id,
121
+ ...(event.provider === 'ANTHROPIC_MESSAGES'
122
+ ? { contextKind: 'private' }
123
+ : {}),
124
+ item: event.item
125
+ };
126
+ messages.push(message);
127
+ await input.appendContext(message);
128
+ }
129
+ else if (event.type === 'text.delta') {
130
+ let delta = event.delta;
131
+ if (mode === 'plan' && input.sourceType !== 'subagent') {
132
+ let prefix = this.planOutputPrefixes.get(event.itemId);
133
+ if (!prefix) {
134
+ prefix = new PlanOutputPrefix();
135
+ this.planOutputPrefixes.set(event.itemId, prefix);
136
+ }
137
+ delta = prefix.push(delta);
138
+ }
139
+ if (mode !== 'compact' && delta) {
140
+ await input.publish({
141
+ type: 'message.delta',
142
+ itemId: event.itemId,
143
+ phase: event.phase,
144
+ delta
145
+ });
146
+ }
147
+ }
148
+ else if (event.type === 'text.completed') {
149
+ const phase = event.phase ?? 'final_answer';
150
+ if (phase === 'final_answer')
151
+ this.finalAnswer = event.text;
152
+ this.planOutputPrefixes.delete(event.itemId);
153
+ if (mode !== 'compact') {
154
+ if (mode === 'plan' && input.sourceType !== 'subagent') {
155
+ const parts = splitPlanOutput(event.text);
156
+ for (const [index, part] of parts.entries()) {
157
+ const itemId = index === 0 ? event.itemId : `${event.itemId}:plan-part:${index}`;
158
+ if (part.kind === 'plan')
159
+ await input.publish({ type: 'plan.completed', itemId, text: part.text });
160
+ else {
161
+ await input.publish({
162
+ type: 'message.completed',
163
+ itemId,
164
+ phase,
165
+ text: part.text,
166
+ modelId: input.model.id,
167
+ modelName: input.model.name
168
+ });
169
+ }
170
+ }
171
+ }
172
+ else {
173
+ await input.publish({
174
+ type: 'message.completed',
175
+ itemId: event.itemId,
176
+ phase,
177
+ text: event.text,
178
+ modelId: input.model.id,
179
+ modelName: input.model.name
180
+ });
181
+ }
182
+ }
183
+ messages.push({ role: 'assistant', content: event.text });
184
+ }
185
+ else if (event.type === 'usage') {
186
+ latestUsage = event.usage;
187
+ const outputTokens = typeof event.usage.outputTokens === 'number' &&
188
+ Number.isSafeInteger(event.usage.outputTokens) &&
189
+ event.usage.outputTokens >= 0
190
+ ? event.usage.outputTokens
191
+ : undefined;
192
+ if (outputTokens !== undefined) {
193
+ requestOutputTokens = outputTokens;
194
+ }
195
+ const reportedContext = event.usage.contextInputTokens ?? event.usage.inputTokens;
196
+ if (reportedContext !== undefined &&
197
+ Number.isSafeInteger(reportedContext) &&
198
+ reportedContext >= 0) {
199
+ input.observeContextTokens(reportedContext);
200
+ roundServerUsage = {
201
+ contextInputTokens: reportedContext,
202
+ outputTokens: typeof event.usage.outputTokens === 'number' &&
203
+ Number.isSafeInteger(event.usage.outputTokens) &&
204
+ event.usage.outputTokens >= 0
205
+ ? event.usage.outputTokens
206
+ : undefined
207
+ };
208
+ }
209
+ await input.publish({ type: 'usage.updated', ...publicModelUsage(event.usage) });
210
+ }
211
+ else if (event.type === 'reasoning.summary') {
212
+ if (mode !== 'compact')
213
+ await input.publish({ type: 'reasoning.summary', text: event.text });
214
+ }
215
+ else if (event.type === 'hosted_tool') {
216
+ if (mode !== 'compact')
217
+ await input.publish({
218
+ type: 'hosted_tool.updated',
219
+ itemId: event.itemId,
220
+ kind: event.kind,
221
+ status: event.status,
222
+ summary: event.summary
223
+ });
224
+ }
225
+ else if (event.type === 'citation') {
226
+ if (mode !== 'compact')
227
+ await input.publish({
228
+ type: 'citation.added',
229
+ id: event.citation.id,
230
+ url: event.citation.url,
231
+ ...(event.citation.title ? { title: event.citation.title } : {})
232
+ });
233
+ }
234
+ else if (event.type === 'client_tool.call') {
235
+ if (mode === 'compact')
236
+ throw new MarAgentError('MAR_AGENT_MODEL_PROTOCOL_ERROR', 'Compaction returned a tool call while tools were disabled.');
237
+ sawTool = true;
238
+ pendingTools.push(event);
239
+ }
240
+ else if (event.type === 'completed') {
241
+ stop = event.reason;
242
+ requestCompletedAt = modelStreamEventObservedAt(event) ?? performance.now();
243
+ }
244
+ if (isFirstModelResponse)
245
+ await emitLatency();
246
+ }
247
+ if (mode !== 'compact' && firstModelResponseAt !== undefined) {
248
+ const completedAt = requestCompletedAt ?? performance.now();
249
+ await emitFinalPerformance(completedAt);
250
+ }
251
+ pendingOutputContinuation = undefined;
252
+ incompleteToolCall = pendingTools.some((call) => call.argumentError !== undefined);
253
+ if (!(stop === 'max_output' && incompleteToolCall)) {
254
+ await persistToolCalls(pendingTools);
255
+ }
256
+ else
257
+ pendingTools.splice(0, pendingTools.length);
258
+ modelRetryState.attempts = 0;
259
+ }
260
+ catch (error) {
261
+ this.planOutputPrefixes.clear();
262
+ if (await recoverModelStream(error, modelRetryState, input.recoverySignal())) {
263
+ this.finalAnswer = '';
264
+ if (mode === 'compact')
265
+ messages.splice(roundMessageCount);
266
+ if (pendingTools.some((call) => call.argumentError !== undefined))
267
+ pendingTools.splice(0, pendingTools.length);
268
+ else if (pendingTools.length > 0)
269
+ await persistToolCalls(pendingTools);
270
+ if (pendingTools.length === 0)
271
+ continue;
272
+ }
273
+ else if (mode === 'compact' &&
274
+ !sawModelSemanticEvent &&
275
+ isProviderContextOverflow(error) &&
276
+ input.compactionFallback?.()) {
277
+ modelRetryState.attempts = 0;
278
+ this.finalAnswer = '';
279
+ continue;
280
+ }
281
+ else if (mode !== 'compact' &&
282
+ !sawModelSemanticEvent &&
283
+ isProviderContextOverflow(error)) {
284
+ if (!recoveringFromContextOverflow && (await input.compactContext())) {
285
+ modelRetryState.attempts = 0;
286
+ recoveringFromContextOverflow = true;
287
+ continue;
288
+ }
289
+ throw new MarAgentError('MAR_AGENT_CONTEXT_LIMIT', 'The model rejected the compacted context as too large.', { cause: error });
290
+ }
291
+ else
292
+ throw error;
293
+ }
294
+ recoveringFromContextOverflow = false;
295
+ input.observeUsage(roundServerUsage);
296
+ if (pendingTools.length === 0 && input.mailbox.hasPending()) {
297
+ await input.mailbox.append();
298
+ this.finalAnswer = '';
299
+ continue;
300
+ }
301
+ const toolResults = await executeRoundTools(pendingTools, round.toolScope);
302
+ for (const result of toolResults) {
303
+ if ('images' in result && result.images?.length)
304
+ input.toolImages.push(...result.images.map((image) => ({
305
+ mimeType: image.mimeType,
306
+ data: Buffer.from(image.dataBase64, 'base64')
307
+ })));
308
+ const toolSearchTools = result.call.name === 'tool_search' && !result.failed
309
+ ? result.output.toolSearchTools
310
+ : undefined;
311
+ const message = {
312
+ role: 'tool',
313
+ callId: result.call.callId,
314
+ content: result.content,
315
+ ...(result.calls ? { calls: result.calls } : {}),
316
+ ...(result.observations ? { observations: result.observations } : {}),
317
+ ...(toolSearchTools === undefined ? {} : { toolSearchTools }),
318
+ ...('images' in result && result.images?.length ? { images: result.images } : {})
319
+ };
320
+ messages.push(message);
321
+ await input.appendContext({
322
+ role: message.role,
323
+ callId: result.call.callId,
324
+ content: message.content,
325
+ ...(message.calls ? { calls: message.calls } : {}),
326
+ ...(message.observations ? { observations: message.observations } : {}),
327
+ ...(message.toolSearchTools === undefined
328
+ ? {}
329
+ : { toolSearchTools: message.toolSearchTools })
330
+ });
331
+ }
332
+ if (sawTool) {
333
+ modelRetryState.attempts = 0;
334
+ if (input.sourceType === 'subagent')
335
+ this.finalAnswer = '';
336
+ }
337
+ input.rolloutBudget?.recordUsage(latestUsage);
338
+ if (mode !== 'compact' && stop === 'max_output') {
339
+ const needsContinuation = !sawTool || incompleteToolCall;
340
+ if (needsContinuation) {
341
+ if (maxOutputContinuationUsed ||
342
+ (input.rolloutBudget?.active && input.rolloutBudget.stage === 'exhausted'))
343
+ throw new MarAgentError('MAR_AGENT_MODEL_OUTPUT_INCOMPLETE', 'Model output reached its limit before completing.');
344
+ maxOutputContinuationUsed = true;
345
+ pendingOutputContinuation = {
346
+ role: 'user',
347
+ content: modelOutputContinuationMessage
348
+ };
349
+ this.finalAnswer = '';
350
+ continue;
351
+ }
352
+ maxOutputContinuationUsed = false;
353
+ }
354
+ else
355
+ maxOutputContinuationUsed = false;
356
+ await input.checkpoint(round, latestUsage);
357
+ if (input.signal.aborted) {
358
+ const aborted = toolResults.find((result) => result.failed)?.error;
359
+ throw aborted ?? new MarAgentError('MAR_AGENT_EXECUTION_CANCELLED', 'Execution cancelled.');
360
+ }
361
+ if (input.mailbox.hasPending()) {
362
+ await input.mailbox.append();
363
+ this.finalAnswer = '';
364
+ continue;
365
+ }
366
+ if (stop === 'completed' && !sawTool) {
367
+ input.mailbox.close();
368
+ const compactSummary = mode === 'compact' ? this.finalAnswer.trim() : '';
369
+ if (mode === 'compact' && !compactSummary)
370
+ throw new MarAgentError('MAR_AGENT_COMPACT_FAILED', 'Compaction returned an empty handoff.');
371
+ if (mode !== 'compact' && !this.finalAnswer.trim())
372
+ throw new MarAgentError(input.sourceType === 'subagent'
373
+ ? 'MAR_AGENT_SUBAGENT_FAILED'
374
+ : 'MAR_AGENT_MODEL_OUTPUT_INCOMPLETE', input.sourceType === 'subagent'
375
+ ? 'Subagent completed without a final summary.'
376
+ : 'Model completed without an answer or tool request.');
377
+ return {
378
+ finalAnswer: this.finalAnswer,
379
+ ...(latestUsage === undefined ? {} : { usage: latestUsage })
380
+ };
381
+ }
382
+ if (!sawTool && stop !== 'pause')
383
+ throw new MarAgentError('MAR_AGENT_MODEL_OUTPUT_INCOMPLETE', 'Model did not complete or request a tool.');
384
+ }
385
+ }
386
+ }
387
+ function isModelResponseEvent(event) {
388
+ if (event.type === 'text.delta')
389
+ return event.delta.length > 0;
390
+ if (event.type === 'text.completed' || event.type === 'reasoning.summary')
391
+ return event.text.length > 0;
392
+ return (event.type === 'response.item' ||
393
+ event.type === 'output.delta' ||
394
+ event.type === 'client_tool.call' ||
395
+ event.type === 'hosted_tool' ||
396
+ event.type === 'citation');
397
+ }
@@ -1,5 +1,5 @@
1
1
  import type { ModelUsage } from '../model/contracts.js';
2
- import type { RolloutBudgetOptions } from '../sdk/types.js';
2
+ import type { RolloutBudgetOptions } from './contracts.js';
3
3
  export type RolloutBudgetStage = 'normal' | 'conserve' | 'finalize' | 'exhausted';
4
4
  export interface ResolvedRolloutBudgetOptions {
5
5
  limitTokens: number;
@@ -0,0 +1,209 @@
1
+ import { addModelCredentialProviders, closeModelAdapters, resolveAgentModels } from './model-runtime.js';
2
+ import { createSessionOpener } from './session.js';
3
+ import { MarAgentError } from '../error.js';
4
+ import { negotiateHost } from '../host/contracts.js';
5
+ import { AnthropicMessagesAdapter } from '../model/anthropic-messages.js';
6
+ import { OpenAiResponsesAdapter } from '../model/openai-responses.js';
7
+ import { resolveRolloutBudgetOptions } from '../runtime/rollout-budget.js';
8
+ import { JsonlSessionStore } from '../session/jsonl-store.js';
9
+ /** Validate models before Host negotiation and expose only built-in protocol adapters. */
10
+ export async function createMarAgent(options) {
11
+ if (Object.hasOwn(options, 'adapterFactory'))
12
+ throw new MarAgentError('MAR_AGENT_MODEL_CONFIG_INVALID', 'Custom model adapters are not supported.');
13
+ return createMarAgentWithAdapter(options);
14
+ }
15
+ /** Package-internal seam for deterministic adapter tests; not a package export. */
16
+ export async function createMarAgentWithAdapter(options) {
17
+ const rolloutBudgetOptions = resolveRolloutBudgetOptions(options.rolloutBudget);
18
+ const resolvedModels = resolveAgentModels(options.models);
19
+ let { models, defaultModelId } = resolvedModels;
20
+ let modelGeneration = 0;
21
+ const { credentialProviders } = resolvedModels;
22
+ const description = negotiateHost(await options.host.describe());
23
+ if (description.mode !== options.mode)
24
+ throw new MarAgentError('MAR_AGENT_HOST_INCOMPATIBLE', 'Host mode does not match Agent mode.');
25
+ const store = await JsonlSessionStore.open(description.homeDirectory);
26
+ const active = new Map();
27
+ const activeExecutionAdapters = new Set();
28
+ const executionResults = new Map();
29
+ const sessionRuntimes = new Map();
30
+ const sessionWriterOwner = {};
31
+ let disposed = false;
32
+ let reconfiguring = false;
33
+ const createAdapter = (modelId, configuredModels = models) => {
34
+ const configuration = configuredModels.get(modelId);
35
+ if (!configuration)
36
+ throw new MarAgentError('MAR_AGENT_MODEL_DISABLED', 'Selected model is unavailable.');
37
+ return (options.adapterFactory?.(configuration) ??
38
+ (configuration.protocol === 'OPENAI_RESPONSES'
39
+ ? new OpenAiResponsesAdapter(configuration)
40
+ : new AnthropicMessagesAdapter(configuration)));
41
+ };
42
+ const activeSessionIds = () => new Set([...active.keys()].map((key) => key.slice(0, key.indexOf(':'))));
43
+ const activeAdaptersExcept = (sessionId) => {
44
+ const activeAdapters = new Set();
45
+ for (const [candidateSessionId, runtime] of sessionRuntimes)
46
+ if (candidateSessionId !== sessionId && activeSessionIds().has(candidateSessionId))
47
+ for (const adapter of runtime.adapters.values())
48
+ activeAdapters.add(adapter);
49
+ return activeAdapters;
50
+ };
51
+ const openSession = createSessionOpener({
52
+ host: options.host,
53
+ description,
54
+ settings: {
55
+ ...(options.workspaceMapping === undefined
56
+ ? {}
57
+ : { workspaceMapping: options.workspaceMapping }),
58
+ ...(options.systemInstruction === undefined
59
+ ? {}
60
+ : { systemInstruction: options.systemInstruction })
61
+ },
62
+ store,
63
+ registry: {
64
+ active,
65
+ activeExecutionAdapters,
66
+ executionResults,
67
+ sessionRuntimes,
68
+ sessionWriterOwner
69
+ },
70
+ rolloutBudgetOptions,
71
+ hasCustomAdapters: options.adapterFactory !== undefined,
72
+ modelState: () => ({ models, defaultModelId, generation: modelGeneration }),
73
+ createAdapter,
74
+ activeAdaptersExcept,
75
+ assertCanStart: () => {
76
+ if (disposed)
77
+ throw new MarAgentError('MAR_AGENT_DISPOSED', 'Agent is disposed.');
78
+ if (reconfiguring)
79
+ throw new MarAgentError('MAR_AGENT_EXECUTION_ACTIVE', 'Models are being reconfigured for the next execution.');
80
+ }
81
+ });
82
+ return {
83
+ createSession: async (input) => openSession((await store.createSession(input)).id, input.workspace),
84
+ openSession: (id) => openSession(id),
85
+ listSessions: (input) => store.list(input),
86
+ clearSession: async (id) => {
87
+ const runtime = sessionRuntimes.get(id);
88
+ if ([...active.keys()].some((key) => key.startsWith(`${id}:`)))
89
+ throw new MarAgentError('MAR_AGENT_EXECUTION_ACTIVE', 'A session cannot be cleared while an execution is active.');
90
+ await runtime?.subagents?.dispose();
91
+ await closeModelAdapters(runtime === undefined ? [] : [...runtime.adapters.values()]);
92
+ sessionRuntimes.delete(id);
93
+ await options.host.disposeSessionResources?.(id);
94
+ await store.clearSession(id);
95
+ },
96
+ reconfigureModels: async (input) => {
97
+ if (disposed)
98
+ throw new MarAgentError('MAR_AGENT_DISPOSED', 'Agent is disposed.');
99
+ if (reconfiguring)
100
+ throw new MarAgentError('MAR_AGENT_EXECUTION_ACTIVE', 'Models are already being reconfigured for the next execution.');
101
+ const next = resolveAgentModels(input.models, input.defaultModelId);
102
+ const activeSessions = activeSessionIds();
103
+ if ([...activeSessions].some((sessionId) => sessionRuntimes.get(sessionId)?.sourceType !== 'subagent'))
104
+ throw new MarAgentError('MAR_AGENT_EXECUTION_ACTIVE', 'Models cannot be reconfigured while a main execution is active.');
105
+ const activeAdapters = new Set(activeExecutionAdapters);
106
+ for (const [sessionId, runtime] of sessionRuntimes)
107
+ if (activeSessions.has(sessionId))
108
+ for (const adapter of runtime.adapters.values())
109
+ activeAdapters.add(adapter);
110
+ const inactiveRuntimes = [...sessionRuntimes].flatMap(([sessionId, runtime]) => activeSessions.has(sessionId) ? [] : [runtime]);
111
+ reconfiguring = true;
112
+ try {
113
+ const reconfigurationCommits = new Map();
114
+ for (const runtime of inactiveRuntimes)
115
+ for (const [modelId, adapter] of runtime.adapters) {
116
+ if (activeAdapters.has(adapter))
117
+ continue;
118
+ const configuration = next.models.get(modelId);
119
+ const commit = configuration === undefined ? undefined : adapter.prepareReconfigure?.(configuration);
120
+ if (commit !== undefined)
121
+ reconfigurationCommits.set(adapter, commit);
122
+ }
123
+ const retainedAdapters = new Set(reconfigurationCommits.keys());
124
+ const adapters = [
125
+ ...new Set(inactiveRuntimes.flatMap((runtime) => [...runtime.adapters.values()]))
126
+ ].filter((adapter) => !activeAdapters.has(adapter) && !retainedAdapters.has(adapter));
127
+ for (const runtime of inactiveRuntimes) {
128
+ for (const [modelId, adapter] of runtime.adapters)
129
+ if (!retainedAdapters.has(adapter))
130
+ runtime.adapters.delete(modelId);
131
+ }
132
+ await closeModelAdapters(adapters);
133
+ if (disposed)
134
+ throw new MarAgentError('MAR_AGENT_DISPOSED', 'Agent is disposed.');
135
+ for (const commit of reconfigurationCommits.values())
136
+ commit();
137
+ models = next.models;
138
+ defaultModelId = next.defaultModelId;
139
+ modelGeneration++;
140
+ for (const provider of next.credentialProviders)
141
+ credentialProviders.add(provider);
142
+ for (const runtime of inactiveRuntimes) {
143
+ runtime.adapterGeneration = modelGeneration;
144
+ }
145
+ const liveProviders = new Set(next.credentialProviders);
146
+ for (const adapter of activeExecutionAdapters)
147
+ addModelCredentialProviders(liveProviders, adapter.configuration);
148
+ for (const runtime of sessionRuntimes.values())
149
+ for (const adapter of runtime.adapters.values())
150
+ addModelCredentialProviders(liveProviders, adapter.configuration);
151
+ const obsoleteProviders = [...credentialProviders].filter((provider) => !liveProviders.has(provider));
152
+ const providerCloseResults = await Promise.allSettled(obsoleteProviders.map((provider) => provider.close()));
153
+ for (const [index, result] of providerCloseResults.entries())
154
+ if (result.status === 'fulfilled')
155
+ credentialProviders.delete(obsoleteProviders[index]);
156
+ }
157
+ finally {
158
+ reconfiguring = false;
159
+ }
160
+ },
161
+ deleteSession: async (id) => {
162
+ const sessionIds = await store.sessionTree(id);
163
+ const sessionIdSet = new Set(sessionIds);
164
+ const executionKeys = [...active.keys()].filter((key) => sessionIdSet.has(key.slice(0, key.indexOf(':'))));
165
+ for (const key of executionKeys)
166
+ active.get(key)?.abort();
167
+ const runtimes = sessionIds.flatMap((sessionId) => {
168
+ const runtime = sessionRuntimes.get(sessionId);
169
+ sessionRuntimes.delete(sessionId);
170
+ return runtime === undefined ? [] : [runtime];
171
+ });
172
+ await Promise.all(runtimes.map((runtime) => runtime.subagents?.dispose()));
173
+ await Promise.allSettled(executionKeys.flatMap((key) => {
174
+ const result = executionResults.get(key);
175
+ return result === undefined ? [] : [result];
176
+ }));
177
+ await closeModelAdapters(runtimes.flatMap((runtime) => [...runtime.adapters.values()]));
178
+ await Promise.all(sessionIds.map((sessionId) => options.host.disposeSessionResources?.(sessionId)));
179
+ await store.delete(id);
180
+ },
181
+ dispose: async () => {
182
+ if (disposed)
183
+ return;
184
+ disposed = true;
185
+ for (const controller of active.values())
186
+ controller.abort();
187
+ await Promise.all([...sessionRuntimes.values()].map((runtime) => runtime.subagents?.dispose().catch(() => undefined)));
188
+ await Promise.allSettled([...executionResults.values()]);
189
+ await closeModelAdapters([...sessionRuntimes.values()].flatMap((runtime) => [...runtime.adapters.values()]));
190
+ let disposalError;
191
+ const providerResults = await Promise.allSettled([...credentialProviders].map((provider) => provider.close()));
192
+ disposalError = providerResults.find((result) => result.status === 'rejected')?.reason;
193
+ try {
194
+ await options.host.dispose();
195
+ }
196
+ catch (error) {
197
+ disposalError ??= error;
198
+ }
199
+ try {
200
+ await store.close();
201
+ }
202
+ catch (error) {
203
+ disposalError ??= error;
204
+ }
205
+ if (disposalError !== undefined)
206
+ throw disposalError;
207
+ }
208
+ };
209
+ }
@@ -0,0 +1,13 @@
1
+ import { type MarAgentModelConfiguration, type MarAgentReasoningEffort, type ModelCredentialProvider } from '../model/configuration.js';
2
+ import type { ModelAdapter, ModelTurnSession } from '../model/contracts.js';
3
+ export type ResolvedModelConfiguration = MarAgentModelConfiguration & {
4
+ readonly defaultReasoningEffort: MarAgentReasoningEffort;
5
+ };
6
+ export declare function resolveAgentModels(configurations: readonly MarAgentModelConfiguration[], requestedDefaultModelId?: string): {
7
+ readonly models: Map<string, ResolvedModelConfiguration>;
8
+ readonly defaultModelId: string;
9
+ readonly credentialProviders: Set<ModelCredentialProvider>;
10
+ };
11
+ export declare function createModelTurnSession(adapter: ModelAdapter): ModelTurnSession;
12
+ export declare function closeModelAdapters(adapters: Iterable<ModelAdapter>): Promise<void>;
13
+ export declare function addModelCredentialProviders(target: Set<ModelCredentialProvider>, configuration: MarAgentModelConfiguration): void;