@mono-agent/agent-runtime 0.20.11 → 0.21.0

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 (148) hide show
  1. package/ARCHITECTURE.md +50 -11
  2. package/MIGRATION.md +288 -26
  3. package/README.md +352 -477
  4. package/package.json +13 -44
  5. package/src/agent/tool-bloat.js +145 -9
  6. package/src/agent/tools/agent-tool.js +108 -9
  7. package/src/agent/tools/bash.js +11 -26
  8. package/src/agent/tools/codex-subscription-search.js +123 -29
  9. package/src/agent/tools/exec.js +10 -2
  10. package/src/agent/tools/index.js +7 -0
  11. package/src/agent/tools/monitor.js +149 -0
  12. package/src/agent/tools/pi-bridge.js +123 -19
  13. package/src/agent/tools/shared/bash-environment.js +31 -0
  14. package/src/agent/tools/shared/monitors.js +293 -0
  15. package/src/agent/tools/shared/path-resolver.js +25 -6
  16. package/src/agent/tools/shared/process-jobs.js +6 -1
  17. package/src/agent/tools/shared/process-runner.js +26 -6
  18. package/src/agent/tools/shared/tool-context.js +8 -0
  19. package/src/agent/tools/web-access-interstitial.js +70 -0
  20. package/src/agent/tools/web-browser-render.js +83 -58
  21. package/src/agent/tools/web-controller.js +112 -21
  22. package/src/agent/tools/web-document-extractor.js +379 -0
  23. package/src/agent/tools/web-fetch.js +271 -243
  24. package/src/agent/tools/web-request.js +65 -0
  25. package/src/agent/tools/web-search-output.js +165 -0
  26. package/src/agent/tools/web-search-state.js +75 -0
  27. package/src/agent/tools/web-search.js +532 -71
  28. package/src/ai/cost.js +13 -68
  29. package/src/ai/failure.js +3 -3
  30. package/src/ai/index.js +5 -17
  31. package/src/ai/observer.js +8 -0
  32. package/src/ai/pi-interop.js +221 -1
  33. package/src/ai/pi-oauth-compat.js +1 -1
  34. package/src/ai/provider-check.js +131 -0
  35. package/src/ai/providers/codex/app-server-client.js +592 -0
  36. package/src/ai/providers/pi-models.js +18 -10
  37. package/src/ai/providers/pi-native/compaction-driver.js +94 -42
  38. package/src/ai/providers/pi-native/compaction-summary.js +140 -0
  39. package/src/ai/providers/pi-native/harness-adapter.js +376 -0
  40. package/src/ai/providers/pi-native/prompt-cache-diagnostics.js +103 -0
  41. package/src/ai/providers/pi-native/provider-attribution.js +102 -0
  42. package/src/ai/providers/pi-native/result-builder.js +38 -14
  43. package/src/ai/providers/pi-native/session-lifecycle.js +253 -55
  44. package/src/ai/providers/pi-native/stream-subscriber.js +52 -6
  45. package/src/ai/providers/pi-native/terminal-recovery.js +40 -0
  46. package/src/ai/providers/pi-native/turn-runner.js +279 -28
  47. package/src/ai/providers/pi-native.js +206 -61
  48. package/src/ai/runtime/capabilities.js +11 -56
  49. package/src/ai/runtime/live-input-events.js +250 -54
  50. package/src/ai/runtime/model-refs.js +118 -153
  51. package/src/ai/runtime/registry.js +22 -56
  52. package/src/ai/runtime/router.js +76 -417
  53. package/src/ai/runtime/session-liveness.js +3 -4
  54. package/src/ai/runtime/sessions.js +4 -5
  55. package/src/ai/runtime/tool-policy.js +0 -2
  56. package/src/ai/tool-lifecycle.js +32 -18
  57. package/src/ai/types.js +37 -112
  58. package/src/index.js +0 -6
  59. package/src/runtime.js +29 -16
  60. package/types/agent/tool-bloat.d.ts +1 -1
  61. package/types/agent/tools/agent-tool.d.ts +4 -2
  62. package/types/agent/tools/bash.d.ts +5 -3
  63. package/types/agent/tools/codex-subscription-search.d.ts +7 -3
  64. package/types/agent/tools/exec.d.ts +5 -3
  65. package/types/agent/tools/index.d.ts +1 -0
  66. package/types/agent/tools/monitor.d.ts +47 -0
  67. package/types/agent/tools/pi-bridge.d.ts +7 -4
  68. package/types/agent/tools/shared/bash-environment.d.ts +4 -0
  69. package/types/agent/tools/shared/monitors.d.ts +98 -0
  70. package/types/agent/tools/shared/process-jobs.d.ts +5 -1
  71. package/types/agent/tools/shared/process-runner.d.ts +14 -4
  72. package/types/agent/tools/shared/tool-context.d.ts +2 -0
  73. package/types/agent/tools/web-access-interstitial.d.ts +23 -0
  74. package/types/agent/tools/web-browser-render.d.ts +4 -1
  75. package/types/agent/tools/web-controller.d.ts +4 -2
  76. package/types/agent/tools/web-document-extractor.d.ts +27 -0
  77. package/types/agent/tools/web-fetch.d.ts +19 -24
  78. package/types/agent/tools/web-request.d.ts +20 -0
  79. package/types/agent/tools/web-search-output.d.ts +31 -0
  80. package/types/agent/tools/web-search-state.d.ts +21 -0
  81. package/types/agent/tools/web-search.d.ts +10 -45
  82. package/types/ai/cost.d.ts +1 -2
  83. package/types/ai/index.d.ts +2 -4
  84. package/types/ai/observer.d.ts +6 -0
  85. package/types/ai/pi-interop.d.ts +81 -0
  86. package/types/ai/provider-check.d.ts +53 -0
  87. package/types/ai/providers/codex/app-server-client.d.ts +37 -0
  88. package/types/ai/providers/pi-native/compaction-driver.d.ts +2 -1
  89. package/types/ai/providers/pi-native/compaction-summary.d.ts +19 -0
  90. package/types/ai/providers/pi-native/harness-adapter.d.ts +58 -0
  91. package/types/ai/providers/pi-native/prompt-cache-diagnostics.d.ts +3 -0
  92. package/types/ai/providers/pi-native/provider-attribution.d.ts +26 -0
  93. package/types/ai/providers/pi-native/result-builder.d.ts +14 -4
  94. package/types/ai/providers/pi-native/session-lifecycle.d.ts +25 -6
  95. package/types/ai/providers/pi-native/stream-subscriber.d.ts +2 -2
  96. package/types/ai/providers/pi-native/terminal-recovery.d.ts +2 -0
  97. package/types/ai/providers/pi-native/turn-runner.d.ts +68 -10
  98. package/types/ai/providers/pi-native.d.ts +21 -4
  99. package/types/ai/runtime/capabilities.d.ts +21 -70
  100. package/types/ai/runtime/live-input-events.d.ts +32 -8
  101. package/types/ai/runtime/model-refs.d.ts +0 -24
  102. package/types/ai/runtime/router.d.ts +3 -10
  103. package/types/ai/runtime/tool-policy.d.ts +0 -2
  104. package/types/ai/tool-lifecycle.d.ts +4 -3
  105. package/types/ai/types.d.ts +162 -256
  106. package/types/index.d.ts +0 -1
  107. package/src/ai/providers/acp-client.js +0 -1149
  108. package/src/ai/providers/acp-privacy.js +0 -124
  109. package/src/ai/providers/acp-public.js +0 -21
  110. package/src/ai/providers/acp-session-tokens.js +0 -282
  111. package/src/ai/providers/acp-transport.js +0 -356
  112. package/src/ai/providers/acp.js +0 -543
  113. package/src/ai/providers/claude-cli.js +0 -883
  114. package/src/ai/providers/claude-sandbox.js +0 -71
  115. package/src/ai/providers/claude-sdk-discovery-worker.js +0 -53
  116. package/src/ai/providers/claude-sdk-discovery.js +0 -352
  117. package/src/ai/providers/claude-sdk.js +0 -1127
  118. package/src/ai/providers/claude-subagent-activity.js +0 -719
  119. package/src/ai/providers/claude-subagents.js +0 -88
  120. package/src/ai/providers/codex-app.js +0 -2946
  121. package/src/ai/providers/opencode-app.js +0 -1109
  122. package/src/ai/providers/opencode-discovery.js +0 -39
  123. package/src/ai/providers/opencode-server.js +0 -508
  124. package/src/ai/runtime/context-windows.js +0 -46
  125. package/src/ai/runtime/fast-mode.js +0 -8
  126. package/src/ai/streaming/codex-events.js +0 -146
  127. package/src/ai/streaming/opencode-events.js +0 -59
  128. package/types/ai/providers/acp-client.d.ts +0 -227
  129. package/types/ai/providers/acp-privacy.d.ts +0 -25
  130. package/types/ai/providers/acp-public.d.ts +0 -7
  131. package/types/ai/providers/acp-session-tokens.d.ts +0 -41
  132. package/types/ai/providers/acp-transport.d.ts +0 -45
  133. package/types/ai/providers/acp.d.ts +0 -93
  134. package/types/ai/providers/claude-cli.d.ts +0 -305
  135. package/types/ai/providers/claude-sandbox.d.ts +0 -79
  136. package/types/ai/providers/claude-sdk-discovery-worker.d.ts +0 -1
  137. package/types/ai/providers/claude-sdk-discovery.d.ts +0 -97
  138. package/types/ai/providers/claude-sdk.d.ts +0 -138
  139. package/types/ai/providers/claude-subagent-activity.d.ts +0 -53
  140. package/types/ai/providers/claude-subagents.d.ts +0 -18
  141. package/types/ai/providers/codex-app.d.ts +0 -151
  142. package/types/ai/providers/opencode-app.d.ts +0 -96
  143. package/types/ai/providers/opencode-discovery.d.ts +0 -4
  144. package/types/ai/providers/opencode-server.d.ts +0 -20
  145. package/types/ai/runtime/context-windows.d.ts +0 -9
  146. package/types/ai/runtime/fast-mode.d.ts +0 -2
  147. package/types/ai/streaming/codex-events.d.ts +0 -40
  148. package/types/ai/streaming/opencode-events.d.ts +0 -42
@@ -1,8 +1,8 @@
1
1
  // @ts-check
2
2
  // Synchronous session-liveness primitives over a createSessionRegistry.
3
3
  //
4
- // A provider bridge owns session DURABILITY (pi keeps a Session transcript,
5
- // codex keeps an app-server thread); this kernel layer owns session LIVENESS —
4
+ // The Pi bridge owns session DURABILITY by keeping a Session transcript; this
5
+ // kernel layer owns session LIVENESS —
6
6
  // the concurrency claim that keeps two turns from driving one session at once.
7
7
  // The primitives here are deliberately SYNCHRONOUS: each does its registry
8
8
  // get -> check -> set in a single await-free span, so the "busy claim must be
@@ -11,8 +11,7 @@
11
11
  //
12
12
  // The registry stays the storage + idle-TTL + dispose fan-out layer (its
13
13
  // exports are unchanged, worklab-compatible); liveness only adds the claim /
14
- // reserve / release / adoptIfPresent seam that pi-native's session-lifecycle and
15
- // codex-app both consume.
14
+ // reserve / release / adoptIfPresent seam that Pi's session lifecycle consumes.
16
15
 
17
16
  /**
18
17
  * @typedef {object} SessionRegistryLike
@@ -1,8 +1,7 @@
1
1
  // Provider session registries.
2
2
  //
3
- // Bridges that support continuous provider sessions (codex-app keeps the
4
- // app-server subprocess + thread alive, pi-native keeps a pi Session
5
- // transcript) register their live sessions here, keyed by provider session id.
3
+ // Pi keeps each continuous provider session as a live Session transcript and
4
+ // registers it here under the provider session id.
6
5
  // The host
7
6
  // owns session lifetime policy (which conversation maps to which session,
8
7
  // when to resume, when to retire); these registries only make sure nothing
@@ -13,8 +12,8 @@
13
12
  // `createSessionRegistry` instances self-register in a module-level set so
14
13
  // the runtime surface can expose `syncSession(id)` / `refreshSession(id)` /
15
14
  // `disposeSession(id)` / `disposeAllSessions()`
16
- // without knowing which bridge owns the id. Provider session ids are unique
17
- // across bridges (codex thread ids, pi uuids), so fan-out dispose is safe.
15
+ // without coupling the host-facing lifecycle surface to Pi's transcript
16
+ // implementation. Pi session UUIDs are unique, so fan-out dispose is safe.
18
17
 
19
18
  const DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
20
19
 
@@ -2,8 +2,6 @@
2
2
 
3
3
  /** @type {"projected"} */
4
4
  export const TOOL_POLICY_PROJECTED = "projected";
5
- /** @type {"allow_all_only"} */
6
- export const TOOL_POLICY_ALLOW_ALL_ONLY = "allow_all_only";
7
5
 
8
6
  /**
9
7
  * True when a tool policy is semantically unrestricted.
@@ -15,9 +15,9 @@ const HOST_HISTORY_METADATA = Symbol("mono-agent.host-tool-history");
15
15
  const HOST_TOOL_LIFECYCLE_METADATA = Symbol("mono-agent.host-tool-lifecycle");
16
16
 
17
17
  /**
18
- * @param {{sink?: (event: any) => Promise<any>, onObserve?: (event: any) => void, onEvent?: (event: any) => void, abortSignal?: AbortSignal}} options
18
+ * @param {{sink?: (event: any) => Promise<any>, onObserve?: (event: any) => void, onLifecycleAdmitted?: (event: any) => void, onEvent?: (event: any) => void, abortSignal?: AbortSignal}} options
19
19
  */
20
- export function createToolLifecycleEventGate({ sink, onObserve, onEvent, abortSignal }) {
20
+ export function createToolLifecycleEventGate({ sink, onObserve, onLifecycleAdmitted, onEvent, abortSignal }) {
21
21
  /** @type {Promise<void>} */
22
22
  let tail = Promise.resolve();
23
23
  let pendingDeliveries = 0;
@@ -25,22 +25,30 @@ export function createToolLifecycleEventGate({ sink, onObserve, onEvent, abortSi
25
25
  const timing = new Map();
26
26
  /** @type {Map<string, any>} */
27
27
  const approvals = new Map();
28
+ const preparedBlocks = new WeakSet();
28
29
 
29
30
  const emit = (event) => {
30
31
  stripProviderLifecycleMetadata(event);
31
32
  try { onObserve?.(event); } catch { /* observer callback semantics remain best-effort */ }
33
+ observeClassification(event, timing, approvals);
32
34
  const requiresPersistence = typeof sink === "function" && eventNeedsPersistence(event);
35
+ // Admission/classification follows native emission, not delayed storage.
36
+ const writes = requiresPersistence ? prepareEvent(event, { timing, approvals, abortSignal }, preparedBlocks) : [];
37
+ for (const write of writes) {
38
+ try { onLifecycleAdmitted?.(write.lifecycle); } catch { /* observers remain best-effort */ }
39
+ }
33
40
  if (!requiresPersistence && pendingDeliveries === 0) {
34
- observeClassification(event, timing, approvals);
35
41
  try { onEvent?.(event); } catch { /* host callback semantics remain best-effort */ }
36
42
  return;
37
43
  }
38
44
 
39
45
  pendingDeliveries += 1;
40
46
  const delivery = tail.then(async () => {
41
- observeClassification(event, timing, approvals);
42
47
  if (requiresPersistence) {
43
- await persistEvent(event, sink, { timing, approvals, abortSignal });
48
+ for (const write of writes) {
49
+ const persisted = await safePersist(sink, write.lifecycle);
50
+ try { write.block.history = historyMetadata(persisted, write.state); } catch { /* still settle every admitted write */ }
51
+ }
44
52
  }
45
53
  try { onEvent?.(event); } catch { /* host callback semantics remain best-effort */ }
46
54
  }).catch((error) => {
@@ -118,32 +126,34 @@ function observeClassification(event, timing, approvals) {
118
126
  }
119
127
  }
120
128
 
121
- /** @param {any} event @param {(event:any)=>Promise<any>} sink @param {{timing:Map<string,any>,approvals:Map<string,any>,abortSignal?:AbortSignal}} context */
122
- async function persistEvent(event, sink, context) {
123
- if (!record(event) || (event.type !== "assistant" && event.type !== "user")) return;
129
+ /** @param {any} event @param {{timing:Map<string,any>,approvals:Map<string,any>,abortSignal?:AbortSignal}} context @param {WeakSet<object>} preparedBlocks */
130
+ function prepareEvent(event, context, preparedBlocks) {
131
+ const writes = [];
132
+ if (!record(event) || (event.type !== "assistant" && event.type !== "user")) return writes;
124
133
  const message = event.message;
125
- if (!record(message) || !Array.isArray(message.content)) return;
134
+ if (!record(message) || !Array.isArray(message.content)) return writes;
126
135
  for (const block of message.content) {
127
136
  if (!record(block)) continue;
128
137
  if (event.type === "assistant" && block.type === "tool_use") {
129
- if (hostHistoryMetadata(block.history)) continue;
138
+ if (hostHistoryMetadata(block.history) || preparedBlocks.has(block)) continue;
130
139
  if (typeof block.id !== "string" || typeof block.name !== "string") continue;
131
- const persisted = await safePersist(sink, {
140
+ const lifecycle = {
132
141
  phase: "invocation",
133
142
  toolCallId: block.id,
134
143
  toolName: block.name,
135
144
  ...(Object.hasOwn(block, "input") ? { arguments: block.input } : {}),
136
- });
137
- block.history = historyMetadata(persisted, undefined);
145
+ };
146
+ preparedBlocks.add(block);
147
+ writes.push({ block, lifecycle, state: undefined });
138
148
  continue;
139
149
  }
140
150
  if (event.type === "user" && block.type === "tool_result") {
141
- if (hostHistoryMetadata(block.history)) continue;
151
+ if (hostHistoryMetadata(block.history) || preparedBlocks.has(block)) continue;
142
152
  const id = typeof block.tool_use_id === "string" ? block.tool_use_id
143
153
  : typeof block.tool_call_id === "string" ? block.tool_call_id : undefined;
144
154
  if (id === undefined) continue;
145
155
  const classified = classifyGenericResult(block, context.timing.get(id), context.approvals.get(id), context.abortSignal);
146
- const persisted = await safePersist(sink, {
156
+ const lifecycle = {
147
157
  phase: "result",
148
158
  toolCallId: id,
149
159
  ...(typeof block.name === "string" ? { toolName: block.name } : {}),
@@ -153,12 +163,14 @@ async function persistEvent(event, sink, context) {
153
163
  ? { executionMs: context.timing.get(id).execution_ms }
154
164
  : {}),
155
165
  artifacts: artifactPaths(block),
156
- });
157
- block.history = historyMetadata(persisted, classified.state);
166
+ };
167
+ preparedBlocks.add(block);
168
+ writes.push({ block, lifecycle, state: classified.state });
158
169
  context.timing.delete(id);
159
170
  context.approvals.delete(id);
160
171
  }
161
172
  }
173
+ return writes;
162
174
  }
163
175
 
164
176
  /** @param {any} block @param {any} timing @param {any} approval @param {AbortSignal|undefined} abortSignal */
@@ -219,7 +231,9 @@ export function historyMetadata(persisted, terminalStateValue) {
219
231
  const metadata = {
220
232
  ...(typeof persisted?.recordId === "string" ? { recordId: persisted.recordId } : {}),
221
233
  ...(Number.isFinite(Number(persisted?.sequence)) ? { sequence: Number(persisted.sequence) } : {}),
222
- persistence: persisted?.persistence === "persisted" ? "persisted" : "failed",
234
+ persistence: persisted?.persistence === "persisted" || persisted?.persistence === "deferred"
235
+ ? persisted.persistence
236
+ : "failed",
223
237
  ...(terminalStateValue === undefined ? {} : { terminalState: terminalStateValue }),
224
238
  ...(typeof persisted?.truncated === "boolean" ? { truncated: persisted.truncated } : {}),
225
239
  ...(Number.isFinite(Number(persisted?.originalBytes)) ? { originalBytes: Number(persisted.originalBytes) } : {}),
package/src/ai/types.js CHANGED
@@ -8,62 +8,22 @@
8
8
  // via `import('./types.js').X` JSDoc syntax from the other seam files, or
9
9
  // transitively through the package root's generated declarations.
10
10
  //
11
- // A few fields below use the `"literal" | (string & {})` shape (a "branded
12
- // string union"). This keeps the known literal values available for
13
- // IDE/editor autocomplete while still accepting any plain `string`, since
14
- // hosts validate the real vocabulary at runtime (parseRuntimeModelReference,
15
- // resolveRuntimeBridge) rather than at the type level — the type only
16
- // documents the values active runtimes currently produce.
17
-
18
11
  /**
19
- * @typedef {"claude" | "pi" | "codex" | "opencode" | "acp" | (string & {})} RuntimeSdkId
20
- * Canonical active runtime id. See ACTIVE_RUNTIME_KINDS (model-refs.js) for
21
- * the enforced-at-runtime vocabulary.
12
+ * @typedef {"pi"} RuntimeSdkId
13
+ * Runtime-result and telemetry label. Model references no longer carry this
14
+ * field because Pi is the sole runtime bridge.
22
15
  */
23
16
 
24
17
  /**
25
- * @typedef {"claude" | "claude-code" | "codex-app" | "opencode-app" | "pi" | "acp-stdio" | (string & {})} RuntimeBridgeId
26
- * Registry bridge id (distinct from RuntimeSdkId: a single sdk can be served
27
- * by more than one bridge, e.g. sdk "claude" is served by both the "claude"
28
- * SDK bridge and the "claude-code" CLI bridge). See
29
- * src/ai/runtime/registry.js's builtinBridgeSpecs.
18
+ * @typedef {"pi"} RuntimeBridgeId
19
+ * Registry bridge id. See src/ai/runtime/registry.js's builtinBridgeSpecs.
30
20
  */
31
21
 
32
22
  /**
33
23
  * @typedef {Object} RuntimeModelRef
34
- * @property {RuntimeSdkId} sdk Canonical active runtime id.
24
+ * @property {string} provider Pi provider id.
35
25
  * @property {string} model Provider model id.
36
- * @property {string} [reference] Original canonical model reference; always set by
37
- * parseRuntimeModelReference, but router.js's chain
38
- * shorthand accepts bare {sdk, model} refs without one.
39
- * @property {string} [provider] Pi/OpenCode provider id when sdk === "pi" | "opencode".
40
- */
41
-
42
- /**
43
- * @typedef {Object} RuntimeNativeSubagentDefinition
44
- * One caller-defined Claude native `Task` profile. Codex collaboration-agent
45
- * definitions are owned by Codex and are not represented by this type.
46
- * @property {string} name
47
- * @property {string} [displayName]
48
- * @property {string} [description]
49
- * @property {string} [helperSystemPrompt]
50
- * @property {string} [instructions]
51
- * @property {ReadonlyArray<string>} [allowedTools]
52
- * @property {ReadonlyArray<string>} [disallowedTools]
53
- * @property {string | RuntimeModelRef} [modelRef]
54
- * @property {RuntimeModelRef} [model]
55
- * @property {string} [effort]
56
- * @property {Object<string, Object>} [mcpServers]
57
- * @property {Object} [mcpApps] App-owned exact-connection MCP Apps registry (Pi-native only).
58
- */
59
-
60
- /**
61
- * @typedef {Object} RuntimeNativeSubagentsOptions
62
- * Caller-defined native profiles are supported only by the Claude bridges.
63
- * Codex owns its collaboration agents; use `codexLoadProjectDocs` when those
64
- * agents should receive repository instructions.
65
- * @property {"claude"} provider
66
- * @property {ReadonlyArray<RuntimeNativeSubagentDefinition>} teammates
26
+ * @property {string} reference Canonical `<provider>:<model>` reference.
67
27
  */
68
28
 
69
29
  /**
@@ -82,6 +42,8 @@
82
42
  * nested native agent. Informational only; `id` remains the attachment key.
83
43
  * @property {number} [costUsd] Priced delegation cost, when the runtime can
84
44
  * attribute it to this subagent.
45
+ * @property {*} [attribution] Bounded provider-route attribution for the
46
+ * completed child run. Consumers must treat it as operator telemetry.
85
47
  */
86
48
 
87
49
  /**
@@ -150,7 +112,7 @@
150
112
  * @typedef {Readonly<{
151
113
  * recordId?: string,
152
114
  * sequence?: number,
153
- * persistence: "persisted"|"failed",
115
+ * persistence: "persisted"|"deferred"|"failed",
154
116
  * truncated?: boolean,
155
117
  * originalBytes?: number,
156
118
  * retainedBytes?: number,
@@ -166,36 +128,11 @@
166
128
  * @returns {Promise<RuntimeToolLifecyclePersistence|undefined>}
167
129
  */
168
130
 
169
- /** @typedef {"uniform"|"per-route-native"} RuntimeRouteSafetyMode */
170
-
171
- /**
172
- * @typedef {"mono-agent-monotonic"|"disabled"|"mono-agent-srt"|"mono-agent-srt-unsafe-host-fallback"|"provider-native"|"codex-native"|"unsupported"} RuntimeRouteSandboxContract
173
- * Fixed telemetry vocabulary for a route's sandbox posture. The
174
- * `mono-agent-srt-unsafe-host-fallback` describes a policy that prefers SRT but
175
- * explicitly permits host execution if unavailable; it does not claim which
176
- * branch ran for a particular command.
177
- */
178
-
179
- /**
180
- * @typedef {"mono-agent-monotonic"|"mono-agent-policy"|"provider-representable"|"exact-allow-all"|"unsupported"} RuntimeRouteToolsContract
181
- * `exact-allow-all` is a stable telemetry token. It describes an effective
182
- * unrestricted contract, including mixed allowlists that contain `"*"`;
183
- * it does not require the literal one-element array `["*"]`.
184
- */
185
-
186
- /**
187
- * @typedef {Object} RuntimeRouteSafetyContract
188
- * Bounded, credential-free description of the sandbox/tool contract applied
189
- * to one fallback route.
190
- * @property {RuntimeRouteSafetyMode} mode
191
- * @property {RuntimeRouteSandboxContract} sandbox
192
- * @property {RuntimeRouteToolsContract} tools
193
- */
194
-
195
131
  /**
196
132
  * @typedef {Object} RuntimeObserver
197
133
  * Per-call or host-level observer merged by createObserverHub (ai/observer.js).
198
134
  * Loose on purpose: observer.js is not a kernel seam file.
135
+ * @property {(event: RuntimeToolLifecycleEvent) => void} [recordToolLifecycle] Synchronous admission before queued lifecycle persistence.
199
136
  * @property {(event: RuntimeEvent) => (void|Promise<void>)} [onEvent]
200
137
  * @property {() => (void|Promise<void>)} [flush]
201
138
  */
@@ -254,19 +191,19 @@
254
191
  * @typedef {Object} RuntimeRunOptions
255
192
  * The options object a host passes to `createRuntime(host).run(systemPrompt, options)`.
256
193
  * @property {RuntimeModelRef} model Resolved model reference; see parseRuntimeModelReference.
257
- * @property {"sdk"|"cli"|"acp"} [executionMode] "sdk" (default), "cli", or "acp"; selects which bridge variant handles the model.
258
194
  * @property {string} [sessionId] Host conversation/session key for resumable bridges.
259
195
  * @property {string} [providerSessionId] Provider-owned resume id for resumable bridges.
260
- * @property {typeof import("@anthropic-ai/claude-agent-sdk").query} [claudeAgentQuery] Advanced programmatic/test seam for the Claude SDK route; omitted runs use the runtime's pinned SDK query implementation.
196
+ * @property {string} [providerAttributionSessionId] Host-owned provider attribution continuity key; does not authorize transcript resume.
197
+ * @property {{runId: string, revision: number}} [sessionRecovery] Host-owned durable recovery opt-in.
261
198
  * @property {boolean} [sessionKeepAlive] Keep resumable provider state alive after the turn.
262
199
  * @property {number} [sessionIdleTimeoutMs] Idle TTL for resumable provider state.
263
- * @property {AsyncIterable<{body: string, id?: string, receivedAt?: string, acknowledge?: () => void, reject?: (error?: unknown) => void}>} [liveInput] Stream of in-flight user messages for steering an active run. Providers acknowledge only after accepting a message into the active turn.
200
+ * @property {AsyncIterable<{body: string, id?: string, receivedAt?: string, logicalOwner?: object, accepted?: (evidence?: {providerEntryId?: string, providerRunId?: string}) => unknown, acknowledge?: (evidence?: {providerEntryId?: string, providerRunId?: string}) => unknown, uncertain?: (details: {reason: "delivery_uncertain", providerEntryId?: string, providerRunId?: string}) => unknown, reject?: (error?: unknown) => unknown}>} [liveInput] Stream of in-flight user messages for steering an active run. Native acceptance, exact transcript consumption, and uncertain delivery are distinct synchronous callbacks; thenables are never awaited as settlement confirmation. An optional opaque logicalOwner object proves that a later same-id value is a fresh callback lease for the first logical owner, not an independent duplicate.
264
201
  * @property {ReadonlyArray<*>} [observers] Per-call observers (see RuntimeObserver) merged with host-level (createRuntime) observers.
265
202
  * @property {(event: RuntimeEvent) => void} [onEvent]
203
+ * @property {boolean} [promptCacheDiagnostics] Emit metadata-only prompt-cache request fingerprints.
266
204
  * @property {RuntimeToolLifecycleSink} [toolLifecycleSink] Awaited host-owned incremental lifecycle persistence boundary.
267
205
  * @property {ReadonlyArray<Object>} [messages]
268
206
  * @property {string} [effort]
269
- * @property {boolean} [fastMode]
270
207
  * @property {string} [cwd]
271
208
  * @property {Object<string, Object>} [mcpServers]
272
209
  * @property {ReadonlyArray<{name: string, description?: string}>} [skills] Skills disclosed to this run, as `{name, description}`. Non-empty makes `supports_skills` a routing requirement (see router.js), so a chain entry that lacks it is skipped.
@@ -275,46 +212,32 @@
275
212
  * @property {ReadonlyArray<string>} [disallowedTools]
276
213
  * @property {string} [permissionMode]
277
214
  * @property {number} [maxTurns]
215
+ * @property {number} [providerCheckMaxTokens] Internal provider-check output cap; ordinary callers must omit it.
216
+ * @property {{env(name: string): Promise<string|undefined>, fileExists(path: string): Promise<boolean>}} [providerCheckAuthContext] Internal provider-check effective auth context; ordinary callers must omit it.
278
217
  * @property {Object} [outputSchema]
279
218
  * @property {string} [runArtifactDir]
280
219
  * @property {AbortSignal} [abortSignal]
220
+ * @property {(artifact: {filename: string, buffer: Buffer, toolName: string, toolUseId: (string|null)}) => (string|null)} [persistArtifact] Host-owned synchronous artifact writer bound to this run.
281
221
  * @property {{schema: 1, values: Readonly<Record<string, string>>, pathPrepend?: readonly string[]}} [toolEnvironment] Host-only environment for Bash, Exec, and nested subagents in this run.
282
222
  * @property {import('../agent/sandbox-seam.js').SandboxPolicy} [sandboxPolicy] Per-run sandbox policy; merged monotonically with the host policy (see resolveSandboxPolicy, agent/tools/shared/tool-context.js).
283
223
  * @property {import('../agent/sandbox-seam.js').RuntimeSandboxEngine} [sandboxEngine] Per-run concrete sandbox engine handed to the active sandbox implementation.
284
224
  * @property {import('../agent/sandbox-seam.js').RuntimeSandbox} [sandbox] Per-run sandbox IMPLEMENTATION override; when set it enforces this run's tools instead of the host/ToolContext impl (precedence run > host > passthrough). Policy DATA still merges monotonically (I13); this overrides only the enforcing code.
285
225
  * @property {RuntimeToolLimits} [toolLimits] Typed per-run tool-output limits (supported replacement for the deprecated `settings` tool keys).
226
+ * @property {readonly string[]} [mcpCallNoTotalTimeoutTools] Exact `server:tool`
227
+ * names whose host-owned lifecycle has no total deadline. Inactivity and abort still apply.
286
228
  * @property {RuntimeCompactionPolicy} [compaction] Typed per-run compaction policy (supported replacement for the deprecated `settings` compaction keys).
287
229
  * @property {RuntimePromptOverrides} [prompts] Per-run prompt-fragment overrides (run wins over the host default).
288
- * @property {import('./providers/acp-client.js').AcpClientHostOptions["resolveAcpProfile"]} [resolveAcpProfile] Per-run ACP profile resolver; wins over the host default.
289
- * @property {import('./providers/acp-client.js').AcpClientHostOptions["onAcpInteractionRequest"]} [onAcpInteractionRequest] Per-run ACP permission/elicitation callback; wins over the host default.
290
- * @property {Uint8Array} [acpSessionTokenKey] Host-owned 32-byte key for confidential authenticated ACP session handles. Required for every ACP task run.
291
- * @property {{backend?: "auto"|"searxng"|"codex"|"keyless", endpoint?: string, codex?: {model?: string}}} [webSearchConfig] Run-scoped WebSearch backend configuration.
230
+ * @property {any} [webRequestCoordinator] Host-owned shared web admission and quota state.
231
+ * @property {{backend?: "auto"|"searxng"|"ollama"|"codex"|"keyless", maxRequestsPerRun?: number, endpoint?: string, searxng?: {endpoint?: string}, ollama?: {baseUrl?: string, apiKey?: string, apiKeyEnv?: string, trustPublicUrl?: boolean}, codex?: {model?: string}}} [webSearchConfig] Run-scoped WebSearch backend configuration.
232
+ * @property {any} [webSearchState] Private request budget and provider deferral state for one logical run.
292
233
  * @property {{render?: "never"|"auto", browserCommand?: string}} [webFetchConfig] Run-scoped WebFetch extraction/render configuration.
293
234
  * @property {"sequential"|"safe-parallel"} [piToolExecutionMode] Pi built-in tool scheduling mode. Safe parallelism is the default.
294
235
  * @property {"one-at-a-time"|"all"} [piToolParallelismMode] DEPRECATED. Compatibility alias mapped to piToolExecutionMode.
295
236
  * @property {Object} [settings] DEPRECATED. Legacy flat settings bag; consumed only as a per-group FALLBACK when the corresponding typed object (`toolLimits` / `compaction`) is absent. Consuming any key emits one `deprecated_settings_option` runtime_warning per run. Migrate via resolveRuntimePolicies (@mono-agent/runtime-adapter).
296
- * @property {ReadonlyArray<"user" | "project" | "local">} [settingSources] Claude Agent SDK only. Filesystem
297
- * settings the SDK may load for this run. Omitted/empty disables user, project, and local sources, including their
298
- * CLAUDE.md, hooks, plugins, and on-disk agent profiles. Anthropic managed settings remain in force and may still
299
- * configure hooks or plugins; this option is not a managed-policy bypass. Each opted-in source may execute configured
300
- * hooks and plugins, so enable only trusted settings and avoid these sources in an untrusted checkout. Include
301
- * `"project"`/`"user"` to let the native `Task` tool discover `.claude/agents` definitions. Unrecognized entries are
302
- * dropped. The Claude Code CLI bridge does not take this option: that binary performs its own settings discovery and
303
- * mono-agent passes no `--setting-sources`, so a CLI run already reads the host config regardless of this value.
304
- * @property {boolean} [codexLoadProjectDocs] Codex app-server only. Omitted/false starts the managed app-server with
305
- * `project_doc_max_bytes=0`, preventing automatic repository-instruction discovery. True restores Codex's native
306
- * project-doc loading defaults. An explicit `codexAppServerArgs` array wins over this convenience option.
307
- * @property {boolean} [codexSandboxNetworkAccess] Codex app-server only, code-only. Strict `true` enables native
308
- * network access for plan/read-only and default/acceptEdits/workspace-write turns; omitted or any other runtime
309
- * value denies it. No-tool probes always deny network access, and bypass/danger-full-access remains unchanged. This
310
- * is unrelated to `RuntimeRunOptions.sandboxPolicy`, which controls mono-agent's own sandbox and is not consumed by
311
- * Codex's provider-owned tool loop. Default/acceptEdits workspace-write plus network true grants repository read and
312
- * network egress in the same turn; prefer plan when only read-only browsing is needed.
313
- * @property {RuntimeNativeSubagentsOptions} [nativeSubagents] Caller-defined Claude native `Task` profiles. Direct
314
- * Codex owns its collaboration agents and rejects configured teammate definitions; `codexLoadProjectDocs` controls
315
- * whether Codex loads repository instructions for its own agents.
316
237
  * @property {RuntimeSubagentsOptions} [subagents] In-process `Agent` built-in: profiles, caps, and the nested-run callback.
317
238
  * @property {import('../agent/tools/shared/process-jobs.js').ProcessJobsController} [processJobs] Pi-native-only structural process-job controller. When absent, Exec/Bash schemas and foreground behavior are unchanged.
239
+ * @property {{chainDepth: number, maxChainDepth: number, remainingStarts: number, unavailableReason?: string}} [processJobsAvailability] Host-owned request lineage diagnostics, including when the controller is unavailable.
240
+ * @property {import('../agent/tools/shared/monitors.js').MonitorsController} [monitors] Pi-native-only structural monitor controller. When absent, the Monitor and MonitorStop tools are not registered at all.
318
241
  * @property {Object} [diagnosticsSeed] Set by createRouterRuntime (ai/runtime/router.js) with a `resume_snapshot` when
319
242
  * failing over mid-chain; a host-level coordinator may relay it forward (see agent/transcript.js), not read by any
320
243
  * bridge in this package today.
@@ -325,7 +248,7 @@
325
248
 
326
249
  /**
327
250
  * @typedef {RuntimeRunOptions
328
- * & Pick<AgentRuntimeHostOptions, "resolveCustomPricing" | "resolvePiApiKey" | "resolveAcpProfile" | "onAcpInteractionRequest" | "acpSessionTokenKey" | "persistArtifact" | "onCompactionRecorded" | "onToolApprovalRequest" | "toolRiskTiers" | "approvalDefaultRiskTier" | "approvalTimeoutMs" | "approvalAlwaysAllowTools">
251
+ * & Pick<AgentRuntimeHostOptions, "resolveCustomPricing" | "resolvePiApiKey" | "onCompactionRecorded" | "onToolApprovalRequest" | "toolRiskTiers" | "approvalDefaultRiskTier" | "approvalTimeoutMs" | "approvalAlwaysAllowTools">
329
252
  * & {runtimeBrand: import('../runtime-brand.js').RuntimeBrand, toolContext?: import('../agent/tools/shared/tool-context.js').ToolContext, observerHub: {emit: (event: RuntimeEvent) => void, flush: () => Promise<void>}}
330
253
  * } RuntimeRequest
331
254
  * The request shape a bridge's `execute(systemPrompt, req)` receives as its
@@ -397,18 +320,19 @@
397
320
  * @property {number} [numTurns]
398
321
  * @property {string} [model]
399
322
  * @property {string} [effort]
323
+ * @property {string} [effectiveEffort] Provider-effective reasoning/thinking level when reported.
400
324
  * @property {RuntimeSdkId} [sdk]
401
325
  * @property {boolean} [cancelled]
402
326
  * @property {string|null} [error]
403
327
  * @property {Object|null} [errorDetails]
404
328
  * @property {string|null} [failureKind]
329
+ * @property {{runId: string, revision: number, providerSessionId: string, modelKey: string, tipId: string}} [providerSessionRecovery]
405
330
  * @property {string|null} [providerSessionId]
406
331
  * @property {string|null} [stderrTail] Bounded stderr tail from a CLI-backed bridge; see createStderrTail (ai/failure.js).
407
332
  * @property {Array<Object>} [runtimeWarnings]
408
333
  * @property {Object} [diagnostics]
409
334
  * @property {Object} [capabilitiesUsed]
410
- * @property {Array<{model: RuntimeModelRef, failureKind: (string|null), requestId?: (string|null), retryableSubkind?: (string|null), retryIndex?: number, requirements?: Object, routeSafety?: RuntimeRouteSafetyMode, safetyContract?: RuntimeRouteSafetyContract}>} [failoverHistory] Set by createRouterRuntime (ai/runtime/router.js) on every failed/skipped attempt.
411
- * @property {Array<{attemptIndex: number, model: RuntimeModelRef, routeSafety: RuntimeRouteSafetyMode, safetyContract: RuntimeRouteSafetyContract, status: string}>} [routeSafetyHistory] Bounded route-safety audit emitted by createRouterRuntime.
335
+ * @property {Array<{model: RuntimeModelRef, failureKind: (string|null), requestId?: (string|null), retryableSubkind?: (string|null), retryIndex?: number, requirements?: Object}>} [failoverHistory] Set by createRouterRuntime (ai/runtime/router.js) on every failed/skipped attempt.
412
336
  */
413
337
 
414
338
  /**
@@ -428,8 +352,7 @@
428
352
  * @property {boolean} [supports_builtin_tools]
429
353
  * @property {boolean} [supports_live_input]
430
354
  * @property {boolean} [supports_native_subagents] Whether the bridge exposes provider-native subagent surfaces and
431
- * normalized activity. This does not imply it accepts caller-defined `nativeSubagents`: Codex owns its collaboration
432
- * agents, while only the Claude bridges project caller-defined profiles.
355
+ * normalized activity. In-process delegation is the `Agent` tool, configured by the host.
433
356
  * @property {boolean} [supports_request_tool_environment]
434
357
  * @property {boolean} [supports_fast_mode]
435
358
  * @property {"projected"|"allow_all_only"} [tool_policy] Whether the bridge can
@@ -500,6 +423,8 @@
500
423
  * host-integration callbacks (bound once, applied to every run via hostDefaults).
501
424
  * @property {string} [workspace]
502
425
  * @property {string} [repoRoot]
426
+ * @property {ReadonlyArray<string>} [additionalReadRoots]
427
+ * @property {ReadonlyArray<string>} [additionalWriteRoots]
503
428
  * @property {string} [ripgrepPath]
504
429
  * @property {string} [qaOutputDir]
505
430
  * @property {import('../agent/sandbox-seam.js').SandboxPolicy} [sandboxPolicy]
@@ -508,11 +433,8 @@
508
433
  * @property {RuntimePromptOverrides} [prompts] Host-level prompt-fragment override defaults; a per-run `options.prompts` field wins over these (see resolvePrompts, runtime.js).
509
434
  * @property {ReadonlyArray<*>} [observers] Observer instances (see RuntimeObserver); loose because observer.js is not a kernel seam file.
510
435
  * @property {*} [runtimeBrand] See resolveRuntimeBrand (runtime-brand.js); accepts a partial RuntimeBrand.
511
- * @property {(parsed: {sdk: (string|null), provider?: string, model: string}) => (import('./cost.js').NormalizedPricing|null)} [resolveCustomPricing] See resolvePricing (ai/cost.js).
436
+ * @property {(parsed: {provider: string, model: string}) => (import('./cost.js').NormalizedPricing|null)} [resolveCustomPricing] See resolvePricing (ai/cost.js).
512
437
  * @property {import('../pi-auth.js').PiApiKeyResolver} [resolvePiApiKey] See createPiOAuthApiKeyResolver (pi-auth.js) for a ready-made implementation.
513
- * @property {import('./providers/acp-client.js').AcpClientHostOptions["resolveAcpProfile"]} [resolveAcpProfile] Default ACP profile resolver; a per-run callback wins.
514
- * @property {import('./providers/acp-client.js').AcpClientHostOptions["onAcpInteractionRequest"]} [onAcpInteractionRequest] Default ACP interaction callback; a per-run callback wins.
515
- * @property {Uint8Array} [acpSessionTokenKey] Default host-owned 32-byte key for confidential authenticated ACP session handles.
516
438
  * @property {(artifact: {filename: string, buffer: Buffer, toolName: string, toolUseId: (string|null)}) => (string|null)} [persistArtifact]
517
439
  * @property {(record: CompactionRecordedPayload) => void} [onCompactionRecorded]
518
440
  * @property {(payload: ApprovalRequestPayload) => Promise<ApprovalDecision>} [onToolApprovalRequest]
@@ -528,6 +450,8 @@
528
450
  * (createRuntime's TOOL_RUNTIME_KEYS pick).
529
451
  * @property {string} [workspace]
530
452
  * @property {string} [repoRoot]
453
+ * @property {ReadonlyArray<string>} [additionalReadRoots]
454
+ * @property {ReadonlyArray<string>} [additionalWriteRoots]
531
455
  * @property {string} [ripgrepPath]
532
456
  * @property {string} [qaOutputDir]
533
457
  * @property {import('../agent/sandbox-seam.js').SandboxPolicy} [sandboxPolicy]
@@ -540,9 +464,10 @@
540
464
  * The object `createRuntime`/`createRouterRuntime` return.
541
465
  * @property {(systemPrompt: string, options: RuntimeRunOptions) => Promise<RuntimeResult>} run
542
466
  * @property {(next?: AgentRuntimeToolOptions) => void} configureTools
467
+ * @property {(receipt: NonNullable<RuntimeResult["providerSessionRecovery"]>, context: {appliedInputIds: readonly string[]}) => Promise<boolean>} recoverSession
543
468
  * @property {(providerSessionId: string) => Promise<boolean>} syncSession
544
469
  * @property {(providerSessionId: string) => Promise<void>} refreshSession Guarantees the id has no reusable process-local handle; rejects on failure.
545
- * @property {(providerSessionId: string, sessionsRoot: string) => Promise<void>} retireDurableSession Permanently deletes every durable transcript with the exact id; absence is success.
470
+ * @property {(providerSessionId: string, sessionsRoot: string) => Promise<void>} retireDurableSession Deletes every currently materialized durable transcript with the exact id; callers retry after an active retired run settles to reclaim any late same-name append. Absence is success.
546
471
  * @property {(providerSessionId: string) => Promise<boolean>} disposeSession
547
472
  * @property {(providerSessionId: string) => Promise<boolean>} invalidateSession
548
473
  * @property {() => Promise<void>} disposeAllSessions
package/src/index.js CHANGED
@@ -18,12 +18,6 @@ export {
18
18
  DEFAULT_RUNTIME_BRAND,
19
19
  resolveRuntimeBrand,
20
20
  } from "./runtime-brand.js";
21
- export {
22
- CLAUDE_SDK_CATALOG_VERSION,
23
- discoverClaudeSdkModels,
24
- normalizeClaudeSdkCatalog,
25
- normalizeClaudeSdkModelId,
26
- } from "./ai/providers/claude-sdk-discovery.js";
27
21
 
28
22
  export * from "./ai/index.js";
29
23
  export * from "./agent/index.js";
package/src/runtime.js CHANGED
@@ -5,14 +5,11 @@
5
5
  // per-instance `ToolContext` (agent/tools/shared/tool-context.js) that this
6
6
  // runtime instance threads to every bridge call via `options.toolContext`
7
7
  // instead of a process-global, and returns a `.run(systemPrompt, options)`
8
- // method that resolves the right provider bridge based on `options.model` +
9
- // `options.executionMode`.
8
+ // method that resolves the Pi provider bridge based on `options.model`.
10
9
  //
11
- // The runtime registry contains a static table for the six built-in bridges
12
- // (ACP, Claude SDK/CLI, Pi-native, Codex app-server, OpenCode app-server) and lazily imports
13
- // the matching implementation only when a run selects it. Hosts that need finer
14
- // control can keep using the named exports (resolveRuntimeBridge,
15
- // generateClaudeResponse, etc.) directly.
10
+ // The runtime registry lazily imports the Pi implementation only when a run
11
+ // selects it. Hosts that need finer control can keep using the named exports
12
+ // directly.
16
13
  //
17
14
  // Return shape from `.run()`:
18
15
  // { text, structuredResult, structuredResultSource, events, usage,
@@ -39,9 +36,10 @@ import {
39
36
  } from "./ai/runtime/sessions.js";
40
37
  import { createToolContext, updateToolContext } from "./agent/tools/shared/tool-context.js";
41
38
  import { resolveRuntimeBrand } from "./runtime-brand.js";
42
- import { retireDurableNativeSession } from "./ai/providers/pi-native/session-lifecycle.js";
39
+ import { recoverDurableNativeSession, retireDurableNativeSession } from "./ai/providers/pi-native/session-lifecycle.js";
43
40
  import { instrumentLiveInputAppliedEvents } from "./ai/runtime/live-input-events.js";
44
41
  import { createToolLifecycleEventGate } from "./ai/tool-lifecycle.js";
42
+ import { createWebSearchRunState } from "./agent/tools/web-search-state.js";
45
43
 
46
44
  /**
47
45
  * @typedef {import('./ai/types.js').AgentRuntimeHostOptions} AgentRuntimeHostOptions
@@ -51,12 +49,12 @@ import { createToolLifecycleEventGate } from "./ai/tool-lifecycle.js";
51
49
  * @typedef {import('./ai/types.js').RuntimeResult} RuntimeResult
52
50
  */
53
51
 
52
+ // Host-integration callbacks bound onto every request. This list is the runtime
53
+ // host-default half of `RuntimeRequest` in ai/types.js. Every entry must be
54
+ // admitted either by RuntimeRunOptions itself or by its host-option Pick.
54
55
  const HOST_KEYS = [
55
56
  "resolveCustomPricing",
56
57
  "resolvePiApiKey",
57
- "resolveAcpProfile",
58
- "onAcpInteractionRequest",
59
- "acpSessionTokenKey",
60
58
  "persistArtifact",
61
59
  "onCompactionRecorded",
62
60
  "onToolApprovalRequest",
@@ -69,6 +67,8 @@ const HOST_KEYS = [
69
67
  const TOOL_RUNTIME_KEYS = [
70
68
  "workspace",
71
69
  "repoRoot",
70
+ "additionalReadRoots",
71
+ "additionalWriteRoots",
72
72
  "ripgrepPath",
73
73
  "qaOutputDir",
74
74
  "sandboxPolicy",
@@ -177,7 +177,9 @@ export function createRuntime(host = {}) {
177
177
  ...(request.skills === undefined ? {} : { skills: request.skills }),
178
178
  ...(request.skillsRoot === undefined ? {} : { skillsRoot: request.skillsRoot }),
179
179
  ...(request.toolEnvironment === undefined ? {} : { toolEnvironment: request.toolEnvironment }),
180
- ...(request.executionMode === undefined ? {} : { executionMode: request.executionMode }),
180
+ ...(request.webSearchConfig === undefined ? {} : { webSearchConfig: request.webSearchConfig }),
181
+ ...(request.webRequestCoordinator === undefined ? {} : { webRequestCoordinator: request.webRequestCoordinator }),
182
+ ...(request.webFetchConfig === undefined ? {} : { webFetchConfig: request.webFetchConfig }),
181
183
  ...(request.cwd === undefined ? {} : { cwd: request.cwd }),
182
184
  // A profile that pins effort — declared or authored at call time — means it
183
185
  // on this path too; dropping it would silently run the child at the
@@ -203,10 +205,9 @@ export function createRuntime(host = {}) {
203
205
  */
204
206
  async run(systemPrompt, options = {}) {
205
207
  if (!options.model) throw new Error("createRuntime.run requires options.model");
206
- const executionMode = typeof options.executionMode === "string" ? options.executionMode : "sdk";
208
+ const webSearchState = createWebSearchRunState(options.webSearchConfig, options.webSearchState);
207
209
  const bridge = await resolveRuntimeBridge(options.model, {
208
210
  liveInput: !!options.liveInput,
209
- executionMode,
210
211
  });
211
212
  const callObservers = Array.isArray(options.observers) ? options.observers : [];
212
213
  const hub = createObserverHub({
@@ -217,6 +218,7 @@ export function createRuntime(host = {}) {
217
218
  // Observer delivery keeps the runtime's synchronous contract. Only the
218
219
  // client-facing lifecycle event waits for its serialized persistence.
219
220
  onObserve: (event) => hub.emit(event),
221
+ onLifecycleAdmitted: (event) => hub.recordToolLifecycle(event),
220
222
  onEvent: options.onEvent,
221
223
  abortSignal: options.abortSignal,
222
224
  });
@@ -233,17 +235,25 @@ export function createRuntime(host = {}) {
233
235
  // defaultSubagentRun is what increments it for the child.
234
236
  const subagents = options.subagents === undefined
235
237
  ? undefined
236
- : { ...options.subagents, run: options.subagents.run ?? defaultSubagentRun };
238
+ : {
239
+ ...options.subagents,
240
+ run: options.subagents.run ?? ((request) => defaultSubagentRun({
241
+ ...request,
242
+ ...(options.webSearchConfig === undefined ? {} : { webSearchConfig: options.webSearchConfig }),
243
+ ...(options.webRequestCoordinator === undefined ? {} : { webRequestCoordinator: options.webRequestCoordinator }),
244
+ ...(options.webFetchConfig === undefined ? {} : { webFetchConfig: options.webFetchConfig }),
245
+ })),
246
+ };
237
247
  try {
238
248
  return await bridge.execute(systemPrompt, {
239
249
  ...hostDefaults,
240
250
  ...options,
251
+ webSearchState,
241
252
  ...(subagents === undefined ? {} : { subagents }),
242
253
  // `...options` alone doesn't carry the `options.model` narrowing above
243
254
  // (spread reads the parameter's declared — Partial — type); re-assert
244
255
  // the already-validated model so the request satisfies RuntimeRequest.
245
256
  model: options.model,
246
- executionMode,
247
257
  runtimeBrand,
248
258
  toolContext: runToolContext,
249
259
  observerHub: hub,
@@ -264,6 +274,9 @@ export function createRuntime(host = {}) {
264
274
  configureTools(next = {}) {
265
275
  updateToolContext(toolContext, pickPresent(next, TOOL_RUNTIME_KEYS));
266
276
  },
277
+ async recoverSession(receipt, context) {
278
+ return recoverDurableNativeSession(receipt, context);
279
+ },
267
280
  async syncSession(providerSessionId) {
268
281
  return syncProviderSession(providerSessionId);
269
282
  },
@@ -6,7 +6,7 @@ export function summarisePayload(toolName: any, contentBlocks: any, persistArtif
6
6
  } | {
7
7
  rewrittenBlocks: {
8
8
  type: string;
9
- text: string;
9
+ text: any;
10
10
  }[];
11
11
  savedPaths: any[];
12
12
  originalBytes: any;