@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,3 @@
1
+ import type { JsonlSessionStore } from '../session/jsonl-store.js';
2
+ import type { SubagentSessionControllerBackend } from '../subagent/session-controller.js';
3
+ export declare function createSubagentBackend(store: JsonlSessionStore, workspace: string): SubagentSessionControllerBackend;
@@ -0,0 +1,46 @@
1
+ import { MarAgentError } from '../error.js';
2
+ export function createSubagentBackend(store, workspace) {
3
+ return {
4
+ createSession: async (input) => {
5
+ const session = await store.createSession({
6
+ workspace,
7
+ title: input.title,
8
+ source: input.source
9
+ });
10
+ return { id: session.id };
11
+ },
12
+ deleteSession: async (sessionId) => {
13
+ await store.delete(sessionId);
14
+ },
15
+ listChildren: async (parentSessionId) => {
16
+ const sessions = await store.listSubagentChildren(parentSessionId);
17
+ return Promise.all(sessions.map(async (session) => ({
18
+ id: session.id,
19
+ createdAt: session.createdAt,
20
+ lastActivityAt: session.lastActivityAt,
21
+ source: session.source,
22
+ records: await store.read(session.id)
23
+ })));
24
+ },
25
+ loadChild: async (parentSessionId, childSessionId) => {
26
+ let session;
27
+ try {
28
+ session = await store.getSession(childSessionId);
29
+ }
30
+ catch (error) {
31
+ if (error instanceof MarAgentError && error.code === 'MAR_AGENT_SESSION_NOT_FOUND')
32
+ return undefined;
33
+ throw error;
34
+ }
35
+ if (session.source.type !== 'subagent' || session.source.parentSessionId !== parentSessionId)
36
+ return undefined;
37
+ return {
38
+ id: session.id,
39
+ createdAt: session.createdAt,
40
+ lastActivityAt: session.lastActivityAt,
41
+ source: session.source,
42
+ records: await store.read(session.id)
43
+ };
44
+ }
45
+ };
46
+ }
@@ -0,0 +1,56 @@
1
+ import type { MarAgentHost } from '../host/contracts.js';
2
+ import type { MarAgentModelConfiguration } from '../model/configuration.js';
3
+ import type { ExecutionResult, RolloutBudgetOptions, RunInput } from '../runtime/contracts.js';
4
+ import type { MarAgentEvent } from '../runtime/events.js';
5
+ import type { MarAgentSessionPage, MarAgentSessionSummary } from '../session/catalog.js';
6
+ import type { SessionListInput, SessionSource } from '../session/types.js';
7
+ export interface CreateSessionInput {
8
+ workspace: string;
9
+ title?: string;
10
+ }
11
+ export type { HostExecutionExtensions, HostSessionResourceSnapshot, HostSkill, MarAgentHost } from '../host/contracts.js';
12
+ export type { AccessMode, ExecutionMode, ExecutionResult, MarAgentImageMetadata, RolloutBudgetOptions, RunInput, RunInputImage } from '../runtime/contracts.js';
13
+ export type { MarAgentEvent, MarAgentEventBase } from '../runtime/events.js';
14
+ export type { CodeCellEventData, MarAgentToolArtifact, MarAgentToolImageArtifact, McpCatalogTool, McpToolCallContext, McpToolCatalog, McpToolCatalogContext, ToolCall, ToolExecutionContext, ToolExecutionResult } from '../tools/contracts.js';
15
+ /** A live execution exposes streamed events separately from its terminal result. */
16
+ export interface ExecutionHandle extends AsyncIterable<MarAgentEvent> {
17
+ readonly executionId: string;
18
+ result(): Promise<ExecutionResult>;
19
+ /** Signals abort; await result() to observe the terminal status and cleanup. */
20
+ cancel(): void;
21
+ }
22
+ /** A persisted Session permits one active main execution at a time. */
23
+ export interface MarAgentSession {
24
+ readonly id: string;
25
+ run(input: RunInput): ExecutionHandle;
26
+ plan(input: RunInput): ExecutionHandle;
27
+ compact(input?: Partial<RunInput>): ExecutionHandle;
28
+ cancel(executionId: string): Promise<void>;
29
+ }
30
+ export interface MarAgent {
31
+ createSession(input: CreateSessionInput): Promise<MarAgentSession>;
32
+ openSession(sessionId: string): Promise<MarAgentSession>;
33
+ listSessions(input?: SessionListInput): Promise<MarAgentSessionPage>;
34
+ clearSession(sessionId: string): Promise<void>;
35
+ /** Rebinds future main executions only; running subagents keep their captured model providers. */
36
+ reconfigureModels(input: {
37
+ readonly models: readonly MarAgentModelConfiguration[];
38
+ readonly defaultModelId?: string;
39
+ }): Promise<void>;
40
+ deleteSession(sessionId: string): Promise<void>;
41
+ /** Cancels active executions, then closes SDK-owned providers, the Host and the Session store. */
42
+ dispose(): Promise<void>;
43
+ }
44
+ export interface CreateMarAgentOptions {
45
+ mode: 'normal' | 'node';
46
+ host: MarAgentHost;
47
+ models: readonly MarAgentModelConfiguration[];
48
+ defaultModelId?: string;
49
+ systemInstruction?: string;
50
+ workspaceMapping?: {
51
+ readonly logicalPath: string;
52
+ readonly physicalPath: string;
53
+ };
54
+ rolloutBudget?: false | RolloutBudgetOptions;
55
+ }
56
+ export type { MarAgentSessionSummary, SessionListInput, SessionSource };
@@ -1,5 +1,6 @@
1
+ import type { MarAgentImageMetadata } from '../runtime/contracts.js';
2
+ import type { MarAgentEvent } from '../runtime/events.js';
1
3
  import type { SessionListInput, SessionSource } from './types.js';
2
- import type { MarAgentEvent, MarAgentImageMetadata } from '../sdk/types.js';
3
4
  export interface MarAgentSessionSummary {
4
5
  id: string;
5
6
  title: string;
@@ -29,6 +29,7 @@ export type ContextGcBase = {
29
29
  readonly recordId: string;
30
30
  };
31
31
  export interface ContextGcTarget {
32
+ readonly observationId?: string;
32
33
  readonly sequence: number;
33
34
  readonly recordId: string;
34
35
  readonly role: 'tool_call' | 'tool' | 'provider';
@@ -37,6 +38,7 @@ export interface ContextGcTarget {
37
38
  readonly sourceHash: string;
38
39
  }
39
40
  export interface ContextGcReadItemReplacement {
41
+ readonly supersededByCallId?: string;
40
42
  readonly index: number;
41
43
  readonly path: string;
42
44
  readonly replacement: string;
@@ -58,6 +60,7 @@ export type ContextGcReplacement = {
58
60
  readonly evidenceSequence: number;
59
61
  } | {
60
62
  readonly kind: 'EXEC_OUTPUT';
63
+ readonly terminalCallId?: string;
61
64
  readonly callId: string;
62
65
  readonly target: ContextGcTarget;
63
66
  readonly replacementContent: string;
@@ -1,7 +1,8 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { posix, win32 } from 'node:path';
3
3
  import { isDeepStrictEqual } from 'node:util';
4
- import { parseReadContextOutput } from '../tools/read-context.js';
4
+ import { codeCallEvidence, callsFromRecord, codeObservationEvidence, observationsFromRecord, retainedCodeInputs } from './context-gc-observations.js';
5
+ import { parseReadContextOutput } from '../tools/local/read-context.js';
5
6
  import { codeCellCompletionSequence, contextGcApplyPatchInputReplacement, contextGcCodeModeInputReplacement, contextGcCodeModeOutputReplacement, contextGcExecInputReplacement, contextGcExecOutputReplacement, contextGcPatchResultFromCompletedPayload, contextGcStaleReadReplacement, contextGcWebOutputReplacement, normalizeContextGcCodeModeInput, normalizeContextGcExecResult } from './context-gc-replacements.js';
6
7
  import { contextGcSubagentNeedsRetainedPriorFinal, contextGcSubagentOutputReplacement, contextGcSubagentSnapshotIsPreciselyCovered, contextGcSubagentSnapshotIsSuperseded, normalizeContextGcSubagentSnapshot } from './context-gc-subagent.js';
7
8
  export const CONTEXT_GC_CHECKPOINT_VERSION = 1;
@@ -57,7 +58,7 @@ export function contextGcLogicalPathKey(path, workspace, platform) {
57
58
  return resolved;
58
59
  }
59
60
  export function contextGcTargetKey(target) {
60
- return `${target.sequence}:${target.recordId}:${target.role}:${target.callId ?? ''}:${target.toolName ?? ''}`;
61
+ return `${target.sequence}:${target.recordId}:${target.role}:${target.callId ?? ''}:${target.toolName ?? ''}${target.observationId ? `:${target.observationId}` : ''}`;
61
62
  }
62
63
  export function contextGcReplacementKey(replacement) {
63
64
  return contextGcTargetKey(replacement.target);
@@ -154,6 +155,8 @@ export function validateContextGcCheckpoint(records, record, workspace = session
154
155
  if (contextGcSourceProjectionHash(records, payload.boundarySequence, payload.base) !==
155
156
  payload.sourceProjectionHash)
156
157
  return undefined;
158
+ // Later cell completion cannot retroactively authorize an earlier checkpoint.
159
+ records = records.filter((item) => item.sequence <= payload.boundarySequence);
157
160
  const recordsBySequence = new Map(records.map((item) => [item.sequence, item]));
158
161
  if (!triggerMatchesRecords(records, recordsBySequence, payload))
159
162
  return undefined;
@@ -225,13 +228,39 @@ function targetMatchesRecord(target, record) {
225
228
  const messageCallId = modelContextCallId(record.payload);
226
229
  const messageToolName = modelContextToolName(record.payload);
227
230
  return ((target.callId === undefined || target.callId === messageCallId) &&
231
+ (target.observationId === undefined ||
232
+ observationsFromRecord(record)?.some((value) => value.id === target.observationId) ===
233
+ true) &&
228
234
  (target.toolName === undefined || target.toolName === messageToolName));
229
235
  }
230
236
  /** A checkpoint draft is valid only when its replacements match the source records and evidence. */
231
237
  function replacementMatchesRecords(replacement, records, recordsBySequence, workspace, platform) {
232
- const source = recordsBySequence.get(replacement.target.sequence);
238
+ let source = recordsBySequence.get(replacement.target.sequence);
233
239
  if (!source || !isRecord(source.payload))
234
240
  return false;
241
+ if (replacement.target.observationId) {
242
+ const selected = observationsFromRecord(source)?.find((value) => value.id === replacement.target.observationId);
243
+ if (!selected)
244
+ return false;
245
+ if (selected.type === 'tool_result') {
246
+ const evidence = codeObservationEvidence(records, source, selected);
247
+ if (!evidence)
248
+ return false;
249
+ source = {
250
+ ...source,
251
+ payload: {
252
+ ...source.payload,
253
+ callId: selected.source.callId,
254
+ content: selected.result.content
255
+ }
256
+ };
257
+ }
258
+ else
259
+ source = { ...source, payload: { ...source.payload, content: selected.value } };
260
+ recordsBySequence = new Map(recordsBySequence).set(source.sequence, source);
261
+ }
262
+ if (!isRecord(source.payload))
263
+ return false;
235
264
  if (replacement.kind === 'READ_OUTPUT_ITEMS') {
236
265
  if (!workspace || toolNameForCallId(records, replacement.callId, source.sequence) !== 'read')
237
266
  return false;
@@ -243,7 +272,7 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
243
272
  const originalItems = new Map(parsed.items.map((item) => [item.index, item]));
244
273
  return replacement.items.every((item) => {
245
274
  const original = originalItems.get(item.index);
246
- const evidence = successfulPatchEvidenceForPath(records, recordsBySequence, item.evidenceSequence, item.path, workspace, platform);
275
+ const evidence = successfulPatchEvidenceForPath(records, recordsBySequence, item.evidenceSequence, item.path, workspace, platform, item.supersededByCallId);
247
276
  return (original?.pathTruncated === false &&
248
277
  original?.path === item.path &&
249
278
  evidence !== undefined &&
@@ -274,7 +303,9 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
274
303
  codeCellCompletionSequence(records, evidence.completed) !== undefined &&
275
304
  evidence.call.sequence === replacement.target.sequence &&
276
305
  input !== undefined &&
277
- isDeepStrictEqual(replacement.replacementArguments, contextGcCodeModeInputReplacement(input)));
306
+ isDeepStrictEqual(replacement.replacementArguments, contextGcCodeModeInputReplacement(input, observationsFromRecord(evidence.result)
307
+ ? retainedCodeInputs(records, replacement.callId)
308
+ : [])));
278
309
  }
279
310
  if (replacement.kind === 'CODE_MODE_OUTPUT') {
280
311
  const evidence = ['code_mode', 'code_exec', 'code_exec_wait']
@@ -288,12 +319,16 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
288
319
  isRecord(evidence.completed.payload) &&
289
320
  typeof evidence.completed.payload.truncated === 'boolean' &&
290
321
  replacement.replacementContent ===
291
- contextGcCodeModeOutputReplacement(evidence.result.payload.content, evidence.completed.payload.truncated));
322
+ contextGcCodeModeOutputReplacement(source.payload.content, replacement.target.observationId
323
+ ? observationsFromRecord(source)?.some((value) => value.id === replacement.target.observationId &&
324
+ value.type === 'value' &&
325
+ value.truncated === true) === true
326
+ : evidence.completed.payload.truncated));
292
327
  }
293
328
  if (replacement.kind === 'SUBAGENT_OUTPUT') {
294
329
  const retainedPriorFinal = replacement.retainedPriorFinal;
295
330
  const sourceEvidence = successfulToolEvidence(records, recordsBySequence, source.sequence, replacement.toolName);
296
- const terminalEvidence = successfulToolEvidence(records, recordsBySequence, replacement.evidenceSequence, replacement.terminalToolName);
331
+ const terminalEvidence = successfulToolEvidence(records, recordsBySequence, replacement.evidenceSequence, replacement.terminalToolName, replacement.terminalCallId);
297
332
  if (!sourceEvidence ||
298
333
  sourceEvidence.callId !== replacement.callId ||
299
334
  !terminalEvidence ||
@@ -304,7 +339,7 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
304
339
  let retainedPriorFinalEvidence;
305
340
  let retainedPriorFinalSnapshot;
306
341
  if (retainedPriorFinal !== undefined) {
307
- retainedPriorFinalEvidence = successfulToolEvidence(records, recordsBySequence, retainedPriorFinal.evidenceSequence, retainedPriorFinal.toolName);
342
+ retainedPriorFinalEvidence = successfulToolEvidence(records, recordsBySequence, retainedPriorFinal.evidenceSequence, retainedPriorFinal.toolName, retainedPriorFinal.callId);
308
343
  if (!retainedPriorFinalEvidence ||
309
344
  retainedPriorFinalEvidence.callId !== retainedPriorFinal.callId ||
310
345
  !isRecord(retainedPriorFinalEvidence.result.payload))
@@ -319,7 +354,7 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
319
354
  (retainedPriorFinal !== undefined) &&
320
355
  (retainedPriorFinalEvidence === undefined ||
321
356
  retainedPriorFinalEvidence.result.sequence < sourceEvidence.result.sequence) &&
322
- sourceEvidence.result.sequence < terminalEvidence.result.sequence &&
357
+ sourceEvidence.completed.sequence < terminalEvidence.completed.sequence &&
323
358
  (contextGcSubagentSnapshotIsSuperseded(sourceSnapshot, terminalSnapshot, retainedPriorFinalSnapshot) ||
324
359
  contextGcSubagentSnapshotIsPreciselyCovered(sourceSnapshot, terminalSnapshot)) &&
325
360
  replacement.replacementContent ===
@@ -351,8 +386,8 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
351
386
  return false;
352
387
  if (replacement.kind === 'TOOL_CALL_INPUT')
353
388
  return isDeepStrictEqual(replacement.replacementArguments, contextGcExecInputReplacement(source.payload.arguments, execInputReplacementFormatVersion(replacement.replacementArguments), replacement.toolName));
354
- const targetEvidence = successfulToolEvidence(records, recordsBySequence, source.sequence, 'exec') ??
355
- successfulToolEvidence(records, recordsBySequence, source.sequence, 'exec_wait');
389
+ const targetEvidence = successfulToolEvidence(records, recordsBySequence, source.sequence, 'exec', replacement.callId) ??
390
+ successfulToolEvidence(records, recordsBySequence, source.sequence, 'exec_wait', replacement.callId);
356
391
  const result = normalizeContextGcExecResult(source.payload.content, targetEvidence?.completed.payload);
357
392
  return (result !== undefined &&
358
393
  replacement.replacementContent ===
@@ -401,7 +436,7 @@ function toolNameForCallId(records, callId, beforeSequence) {
401
436
  ? call.payload.name
402
437
  : undefined;
403
438
  }
404
- function successfulToolEvidence(records, recordsBySequence, evidenceSequence, toolName) {
439
+ function successfulToolEvidence(records, recordsBySequence, evidenceSequence, toolName, expectedCallId) {
405
440
  const result = recordsBySequence.get(evidenceSequence);
406
441
  if (result?.type !== 'model.context' ||
407
442
  !isRecord(result.payload) ||
@@ -410,8 +445,28 @@ function successfulToolEvidence(records, recordsBySequence, evidenceSequence, to
410
445
  return undefined;
411
446
  const callId = result.payload.callId;
412
447
  const call = modelToolCallForCallId(records, callId, result.sequence);
413
- if (!call || !isRecord(call.payload) || call.payload.name !== toolName)
448
+ if (!call ||
449
+ !isRecord(call.payload) ||
450
+ call.payload.name !== toolName ||
451
+ (expectedCallId && expectedCallId !== callId)) {
452
+ for (const observation of observationsFromRecord(result) ?? []) {
453
+ if (observation.type !== 'tool_result' ||
454
+ observation.source.toolName !== toolName ||
455
+ (expectedCallId && observation.source.callId !== expectedCallId))
456
+ continue;
457
+ const evidence = codeObservationEvidence(records, result, observation);
458
+ if (evidence)
459
+ return evidence;
460
+ }
461
+ for (const entry of callsFromRecord(result) ?? []) {
462
+ if (entry.toolName !== toolName || (expectedCallId && entry.callId !== expectedCallId))
463
+ continue;
464
+ const evidence = codeCallEvidence(records, result, entry);
465
+ if (evidence)
466
+ return evidence;
467
+ }
414
468
  return undefined;
469
+ }
415
470
  const completed = records.findLast((record) => record.sequence > call.sequence &&
416
471
  record.sequence < result.sequence &&
417
472
  record.type === 'tool.completed' &&
@@ -441,11 +496,29 @@ function hasFailedToolEvidence(records, call, result, toolName) {
441
496
  record.payload.toolName === toolName);
442
497
  }
443
498
  function modelToolCallForCallId(records, callId, beforeSequence) {
444
- return records.findLast((record) => record.sequence < beforeSequence &&
499
+ const direct = records.findLast((record) => record.sequence < beforeSequence &&
445
500
  record.type === 'model.context' &&
446
501
  isRecord(record.payload) &&
447
502
  record.payload.role === 'tool_call' &&
448
503
  record.payload.callId === callId);
504
+ if (direct)
505
+ return direct;
506
+ const started = records.findLast((record) => record.sequence < beforeSequence &&
507
+ record.type === 'tool.started' &&
508
+ isRecord(record.payload) &&
509
+ record.payload.callId === callId &&
510
+ typeof record.payload.parentCallId === 'string');
511
+ return started && isRecord(started.payload)
512
+ ? {
513
+ ...started,
514
+ payload: {
515
+ role: 'tool_call',
516
+ name: started.payload.toolName,
517
+ callId,
518
+ arguments: started.payload.input
519
+ }
520
+ }
521
+ : undefined;
449
522
  }
450
523
  function modelToolResultForCall(records, call, beforeSequence) {
451
524
  if (!isRecord(call.payload) || typeof call.payload.callId !== 'string')
@@ -458,8 +531,8 @@ function modelToolResultForCall(records, call, beforeSequence) {
458
531
  record.payload.role === 'tool' &&
459
532
  record.payload.callId === callId);
460
533
  }
461
- function successfulPatchEvidenceForPath(records, recordsBySequence, evidenceSequence, path, workspace, platform) {
462
- const evidence = successfulToolEvidence(records, recordsBySequence, evidenceSequence, 'apply_patch');
534
+ function successfulPatchEvidenceForPath(records, recordsBySequence, evidenceSequence, path, workspace, platform, expectedCallId) {
535
+ const evidence = successfulToolEvidence(records, recordsBySequence, evidenceSequence, 'apply_patch', expectedCallId);
463
536
  if (!evidence || !isRecord(evidence.completed.payload))
464
537
  return undefined;
465
538
  const result = contextGcPatchResultFromCompletedPayload(evidence.completed.payload);
@@ -475,8 +548,9 @@ function successfulPatchEvidenceForPath(records, recordsBySequence, evidenceSequ
475
548
  : undefined;
476
549
  }
477
550
  function isSuccessfulExecLifecycleEvidence(replacement, source, records, recordsBySequence) {
478
- const evidence = successfulToolEvidence(records, recordsBySequence, replacement.evidenceSequence, 'exec') ??
479
- successfulToolEvidence(records, recordsBySequence, replacement.evidenceSequence, 'exec_wait');
551
+ const expectedTerminal = replacement.kind === 'EXEC_OUTPUT' ? replacement.terminalCallId : undefined;
552
+ const evidence = successfulToolEvidence(records, recordsBySequence, replacement.evidenceSequence, 'exec', expectedTerminal) ??
553
+ successfulToolEvidence(records, recordsBySequence, replacement.evidenceSequence, 'exec_wait', expectedTerminal);
480
554
  if (!evidence || !isRecord(evidence.call.payload) || !isRecord(evidence.result.payload))
481
555
  return false;
482
556
  const finalResult = normalizeContextGcExecResult(evidence.result.payload.content, evidence.completed.payload);
@@ -497,7 +571,7 @@ function isSuccessfulExecLifecycleEvidence(replacement, source, records, records
497
571
  : modelToolResultForCall(records, targetCall, evidence.result.sequence);
498
572
  if (!targetResult)
499
573
  return false;
500
- const targetEvidence = successfulToolEvidence(records, recordsBySequence, targetResult.sequence, targetCall.payload.name);
574
+ const targetEvidence = successfulToolEvidence(records, recordsBySequence, targetResult.sequence, targetCall.payload.name, replacement.callId);
501
575
  if (!targetEvidence || targetEvidence.call.sequence !== targetCall.sequence)
502
576
  return false;
503
577
  if (targetEvidence.callId === evidence.callId)
@@ -597,7 +671,7 @@ function isContextGcReplacement(value) {
597
671
  if (!isRecord(value) ||
598
672
  !isContextGcTarget(value.target) ||
599
673
  !isNonemptyString(value.callId) ||
600
- value.target.callId !== value.callId)
674
+ (value.target.callId !== value.callId && value.target.observationId === undefined))
601
675
  return false;
602
676
  if (value.kind === 'READ_OUTPUT_ITEMS') {
603
677
  const items = value.items;
@@ -607,7 +681,14 @@ function isContextGcReplacement(value) {
607
681
  Array.isArray(items) &&
608
682
  items.length > 0 &&
609
683
  items.every((item) => isRecord(item) &&
610
- hasOnlyKeys(item, ['index', 'path', 'replacement', 'evidenceSequence']) &&
684
+ hasOnlyKeys(item, [
685
+ 'index',
686
+ 'path',
687
+ 'replacement',
688
+ 'evidenceSequence',
689
+ 'supersededByCallId'
690
+ ]) &&
691
+ (item.supersededByCallId === undefined || isNonemptyString(item.supersededByCallId)) &&
611
692
  isNonnegativeInteger(item.index) &&
612
693
  isNonemptyString(item.path) &&
613
694
  isNonemptyString(item.replacement) &&
@@ -697,14 +778,32 @@ function isContextGcReplacement(value) {
697
778
  isNonemptyString(value.replacementContent) &&
698
779
  isPositiveInteger(value.evidenceSequence));
699
780
  return (value.kind === 'EXEC_OUTPUT' &&
700
- hasOnlyKeys(value, ['kind', 'callId', 'target', 'replacementContent', 'evidenceSequence']) &&
781
+ hasOnlyKeys(value, [
782
+ 'kind',
783
+ 'callId',
784
+ 'target',
785
+ 'replacementContent',
786
+ 'evidenceSequence',
787
+ 'terminalCallId'
788
+ ]) &&
789
+ (value.terminalCallId === undefined || isNonemptyString(value.terminalCallId)) &&
701
790
  value.target.role === 'tool' &&
702
791
  isNonemptyString(value.replacementContent) &&
703
792
  isPositiveInteger(value.evidenceSequence));
704
793
  }
705
794
  function isContextGcTarget(value) {
706
795
  return (isRecord(value) &&
707
- hasOnlyKeys(value, ['sequence', 'recordId', 'role', 'callId', 'toolName', 'sourceHash']) &&
796
+ hasOnlyKeys(value, [
797
+ 'sequence',
798
+ 'recordId',
799
+ 'role',
800
+ 'callId',
801
+ 'toolName',
802
+ 'sourceHash',
803
+ 'observationId'
804
+ ]) &&
805
+ (value.observationId === undefined ||
806
+ (value.role === 'tool' && isNonemptyString(value.observationId))) &&
708
807
  isPositiveInteger(value.sequence) &&
709
808
  isNonemptyString(value.recordId) &&
710
809
  (value.role === 'tool_call' || value.role === 'tool' || value.role === 'provider') &&
@@ -0,0 +1,38 @@
1
+ import type { SessionRecord } from './jsonl-store.js';
2
+ import { type CodeObservation, type CodeToolCallRecord } from '../tools/code-mode/observations.js';
3
+ /** Resolve private observation identity to real dispatch facts, not Provider tool calls. */
4
+ export declare function codeObservationEvidence(records: readonly SessionRecord[], result: SessionRecord, observation: Extract<CodeObservation, {
5
+ type: 'tool_result';
6
+ }>): {
7
+ callId: string;
8
+ call: SessionRecord;
9
+ completed: SessionRecord;
10
+ result: SessionRecord;
11
+ } | undefined;
12
+ export declare function observationsFromRecord(record: SessionRecord): CodeObservation[] | undefined;
13
+ export declare function codeCallEvidence(records: readonly SessionRecord[], result: SessionRecord, entry: CodeToolCallRecord): {
14
+ result: {
15
+ payload: {
16
+ role: string;
17
+ callId: string;
18
+ content: string;
19
+ };
20
+ schemaVersion: 1;
21
+ recordId: string;
22
+ sequence: number;
23
+ timestamp: string;
24
+ sessionId: string;
25
+ executionId?: string;
26
+ turnId?: string;
27
+ type: string;
28
+ };
29
+ callId: string;
30
+ call: SessionRecord;
31
+ completed: SessionRecord;
32
+ } | undefined;
33
+ export declare function callsFromRecord(record: SessionRecord): CodeToolCallRecord[] | undefined;
34
+ export declare function retainedCodeInputs(records: readonly SessionRecord[], parentCallId: string): {
35
+ callId: unknown;
36
+ toolName: unknown;
37
+ input: unknown;
38
+ }[];
@@ -0,0 +1,150 @@
1
+ import { isDeepStrictEqual } from 'node:util';
2
+ import { codeCellCompletionSequence, contextGcPatchResultFromCompletedPayload } from './context-gc-replacements.js';
3
+ import { parseCodeCalls, parseObservations } from '../tools/code-mode/observations.js';
4
+ /** Resolve private observation identity to real dispatch facts, not Provider tool calls. */
5
+ export function codeObservationEvidence(records, result, observation) {
6
+ if (observation.outcome !== 'completed')
7
+ return undefined;
8
+ const started = records.findLast((record) => record.sequence < result.sequence &&
9
+ record.type === 'tool.started' &&
10
+ isRecord(record.payload) &&
11
+ record.payload.callId === observation.source.callId &&
12
+ record.payload.toolName === observation.source.toolName &&
13
+ typeof record.payload.parentCallId === 'string' &&
14
+ isDeepStrictEqual(record.payload.input, observation.source.input));
15
+ if (!started || !isRecord(started.payload))
16
+ return undefined;
17
+ const parentId = started.payload.parentCallId;
18
+ const parent = records.find((record) => record.type === 'model.context' &&
19
+ record.sequence < started.sequence &&
20
+ isRecord(record.payload) &&
21
+ record.payload.role === 'tool_call' &&
22
+ record.payload.callId === parentId &&
23
+ (record.payload.name === 'code_exec' || record.payload.name === 'code_mode'));
24
+ if (!parent)
25
+ return undefined;
26
+ const original = records.find((record) => record.recordId === result.recordId) ?? result;
27
+ if (!isRecord(original.payload))
28
+ return undefined;
29
+ const outerId = original.payload.callId;
30
+ const outer = records.findLast((record) => record.sequence < result.sequence &&
31
+ record.type === 'tool.completed' &&
32
+ isRecord(record.payload) &&
33
+ record.payload.callId === outerId &&
34
+ (record.payload.toolName === 'code_exec' ||
35
+ record.payload.toolName === 'code_mode' ||
36
+ record.payload.toolName === 'code_exec_wait'));
37
+ if (!outer ||
38
+ codeCellCompletionSequence(records, outer) === undefined ||
39
+ records.some((record) => record.sequence < result.sequence &&
40
+ record.type === 'tool.failed' &&
41
+ isRecord(record.payload) &&
42
+ record.payload.callId === outerId))
43
+ return undefined;
44
+ if (original.payload.callId !== parentId) {
45
+ const initial = records.find((record) => record.sequence < outer.sequence &&
46
+ record.type === 'tool.completed' &&
47
+ isRecord(record.payload) &&
48
+ record.payload.callId === parentId);
49
+ if (!initial ||
50
+ !isRecord(outer.payload) ||
51
+ outer.payload.toolName !== 'code_exec_wait' ||
52
+ !isRecord(initial.payload) ||
53
+ !isRecord(outer.payload.data) ||
54
+ !isRecord(initial.payload.data) ||
55
+ typeof outer.payload.data.cellId !== 'string' ||
56
+ outer.payload.data.cellId !== initial.payload.data.cellId)
57
+ return undefined;
58
+ }
59
+ const completed = records.findLast((record) => record.sequence > started.sequence &&
60
+ record.sequence < result.sequence &&
61
+ record.type === 'tool.completed' &&
62
+ isRecord(record.payload) &&
63
+ record.payload.callId === observation.source.callId &&
64
+ record.payload.toolName === observation.source.toolName &&
65
+ record.payload.parentCallId === parentId);
66
+ if (!completed ||
67
+ records.some((record) => record.sequence > started.sequence &&
68
+ record.sequence < result.sequence &&
69
+ record.type === 'tool.failed' &&
70
+ isRecord(record.payload) &&
71
+ record.payload.callId === observation.source.callId))
72
+ return undefined;
73
+ const call = {
74
+ ...started,
75
+ payload: {
76
+ role: 'tool_call',
77
+ name: observation.source.toolName,
78
+ callId: observation.source.callId,
79
+ arguments: observation.source.input
80
+ }
81
+ };
82
+ const selected = {
83
+ ...result,
84
+ payload: {
85
+ role: 'tool',
86
+ callId: observation.source.callId,
87
+ content: observation.result.content,
88
+ observationId: observation.id
89
+ }
90
+ };
91
+ return { callId: observation.source.callId, call, completed, result: selected };
92
+ }
93
+ export function observationsFromRecord(record) {
94
+ return isRecord(record.payload) ? parseObservations(record.payload.observations) : undefined;
95
+ }
96
+ export function codeCallEvidence(records, result, entry) {
97
+ if (entry.status !== 'completed')
98
+ return undefined;
99
+ const evidence = codeObservationEvidence(records, result, {
100
+ type: 'tool_result',
101
+ id: `call:${entry.callId}`,
102
+ source: { callId: entry.callId, toolName: entry.toolName, input: entry.input },
103
+ outcome: 'completed',
104
+ result: { content: '' }
105
+ });
106
+ if (!evidence || !isRecord(evidence.completed.payload))
107
+ return undefined;
108
+ return {
109
+ ...evidence,
110
+ result: {
111
+ ...evidence.result,
112
+ payload: {
113
+ role: 'tool',
114
+ callId: entry.callId,
115
+ content: JSON.stringify(evidence.completed.payload.data ?? {})
116
+ }
117
+ }
118
+ };
119
+ }
120
+ export function callsFromRecord(record) {
121
+ return isRecord(record.payload) ? parseCodeCalls(record.payload.calls) : undefined;
122
+ }
123
+ export function retainedCodeInputs(records, parentCallId) {
124
+ return records.flatMap((record) => {
125
+ if (!isRecord(record.payload) ||
126
+ record.type !== 'tool.started' ||
127
+ record.payload.parentCallId !== parentCallId)
128
+ return [];
129
+ const call = record.payload;
130
+ const completedPatch = call.toolName === 'apply_patch' &&
131
+ records.some((next) => next.sequence > record.sequence &&
132
+ next.type === 'tool.completed' &&
133
+ isRecord(next.payload) &&
134
+ next.payload.callId === call.callId &&
135
+ next.payload.toolName === 'apply_patch' &&
136
+ next.payload.parentCallId === parentCallId &&
137
+ contextGcPatchResultFromCompletedPayload(next.payload) !== undefined) &&
138
+ !records.some((next) => next.sequence > record.sequence &&
139
+ next.type === 'tool.failed' &&
140
+ isRecord(next.payload) &&
141
+ next.payload.callId === call.callId);
142
+ // Successful patches have durable file evidence; other inputs retain their direct-mode semantics.
143
+ return completedPatch
144
+ ? []
145
+ : [{ callId: call.callId, toolName: call.toolName, input: call.input }];
146
+ });
147
+ }
148
+ function isRecord(value) {
149
+ return !!value && typeof value === 'object' && !Array.isArray(value);
150
+ }
@@ -4,7 +4,7 @@ export interface ContextGcCodeModeInput {
4
4
  readonly inputMode: 'freeform' | 'json';
5
5
  }
6
6
  export declare function normalizeContextGcCodeModeInput(arguments_: unknown): ContextGcCodeModeInput | undefined;
7
- export declare function contextGcCodeModeInputReplacement(input: ContextGcCodeModeInput): unknown;
7
+ export declare function contextGcCodeModeInputReplacement(input: ContextGcCodeModeInput, retainedInputs?: readonly unknown[]): unknown;
8
8
  export declare function contextGcCodeModeOutputReplacement(originalContent: string, truncated: boolean): string;
9
9
  export interface ContextGcPatchFile {
10
10
  readonly path: string;
@@ -14,9 +14,13 @@ export function normalizeContextGcCodeModeInput(arguments_) {
14
14
  return { code: arguments_.code, inputMode: 'json' };
15
15
  return undefined;
16
16
  }
17
- export function contextGcCodeModeInputReplacement(input) {
17
+ export function contextGcCodeModeInputReplacement(input, retainedInputs = []) {
18
18
  const replacement = `<context_gc kind="completed_code_mode_input" originalBytes="${Buffer.byteLength(input.code)}" lines="${lineCount(input.code)}" inputMode="${input.inputMode}">Completed Code Mode source was reclaimed after six successful rollouts. The paired output, images, completion evidence, and nested tool side effects remain in history.</context_gc>`;
19
- return input.inputMode === 'freeform' ? replacement : { code: replacement };
19
+ const content = replacement +
20
+ (retainedInputs.length
21
+ ? `\nRetained tool instructions: ${JSON.stringify(retainedInputs)}`
22
+ : '');
23
+ return input.inputMode === 'freeform' ? content : { code: content };
20
24
  }
21
25
  export function contextGcCodeModeOutputReplacement(originalContent, truncated) {
22
26
  const preview = unicodeHeadTail(originalContent, CODE_MODE_OUTPUT_PREVIEW_CHARACTERS);