@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
@@ -38,12 +38,11 @@ export function subagentUsageForRun(subagents: any, parentRunId: string | undefi
38
38
  * Build the `Agent` tool, or null when subagents are unavailable for this run.
39
39
  *
40
40
  * @param {RuntimeSubagentsOptions|null|undefined} subagents
41
- * @param {{model?: *, executionMode?: string, cwd?: string, parentRunId?: string, sandboxPolicy?: *, sandboxEngine?: *, skills?: {name: string, description?: string}[], skillsRoot?: string, toolEnvironment?: *, onEvent?: (event: *) => void}} [context]
41
+ * @param {{model?: *, cwd?: string, parentRunId?: string, sandboxPolicy?: *, sandboxEngine?: *, skills?: {name: string, description?: string}[], skillsRoot?: string, toolEnvironment?: *, webSearchConfig?: *, webRequestCoordinator?: *, webFetchConfig?: *, onEvent?: (event: *) => void}} [context]
42
42
  * @returns {*|null}
43
43
  */
44
44
  export function createAgentTool(subagents: RuntimeSubagentsOptions | null | undefined, context?: {
45
45
  model?: any;
46
- executionMode?: string;
47
46
  cwd?: string;
48
47
  parentRunId?: string;
49
48
  sandboxPolicy?: any;
@@ -54,6 +53,9 @@ export function createAgentTool(subagents: RuntimeSubagentsOptions | null | unde
54
53
  }[];
55
54
  skillsRoot?: string;
56
55
  toolEnvironment?: any;
56
+ webSearchConfig?: any;
57
+ webRequestCoordinator?: any;
58
+ webFetchConfig?: any;
57
59
  onEvent?: (event: any) => void;
58
60
  }): any | null;
59
61
  /**
@@ -24,7 +24,7 @@ export function normalizeBackgroundBashTimeoutMs(value: any): number;
24
24
  /**
25
25
  * Compatibility wrapper retained for direct callers and tests.
26
26
  *
27
- * @param {{command: string, description?: string, timeout?: number, timeout_ms?: number, max_output_chars?: number, workdir?: string, background?: boolean}} params
27
+ * @param {{command: string, description?: string, timeout?: number, timeout_ms?: number, max_output_chars?: number, workdir?: string, background?: boolean, wake_on_completion?: boolean}} params
28
28
  * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, processJobsController?: import("./shared/process-jobs.js").ProcessJobsController}} [options]
29
29
  */
30
30
  export function bashToolImpl(params: {
@@ -35,6 +35,7 @@ export function bashToolImpl(params: {
35
35
  max_output_chars?: number;
36
36
  workdir?: string;
37
37
  background?: boolean;
38
+ wake_on_completion?: boolean;
38
39
  }, options?: {
39
40
  signal?: AbortSignal;
40
41
  sandboxPolicy?: any;
@@ -45,10 +46,10 @@ export function bashToolImpl(params: {
45
46
  /**
46
47
  * Structured Bash execution used by the Pi bridge.
47
48
  *
48
- * @param {{command: string, description?: string, timeout?: number, timeout_ms?: number, max_output_chars?: number, workdir?: string, background?: boolean}} params
49
+ * @param {{command: string, description?: string, timeout?: number, timeout_ms?: number, max_output_chars?: number, workdir?: string, background?: boolean, wake_on_completion?: boolean}} params
49
50
  * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, processJobsController?: import("./shared/process-jobs.js").ProcessJobsController}} [options]
50
51
  */
51
- export function bashToolRun({ command, description, timeout, timeout_ms, max_output_chars, workdir, background, }: {
52
+ export function bashToolRun({ command, description, timeout, timeout_ms, max_output_chars, workdir, background, wake_on_completion, }: {
52
53
  command: string;
53
54
  description?: string;
54
55
  timeout?: number;
@@ -56,6 +57,7 @@ export function bashToolRun({ command, description, timeout, timeout_ms, max_out
56
57
  max_output_chars?: number;
57
58
  workdir?: string;
58
59
  background?: boolean;
60
+ wake_on_completion?: boolean;
59
61
  }, { signal, sandboxPolicy, sandboxEngine, ctx, processJobsController, }?: {
60
62
  signal?: AbortSignal;
61
63
  sandboxPolicy?: any;
@@ -18,14 +18,18 @@ export function inspectCodexSubscriptionSearch(options?: {
18
18
  * turns or cross-wire app-server notifications between requests.
19
19
  *
20
20
  * @param {string} query
21
- * @param {{model?: string, signal?: AbortSignal, clientFactory?: typeof createCodexAppServerClient}} [options]
21
+ * @param {{model?: string, signal?: AbortSignal, clientFactory?: typeof createCodexAppServerClient, coordinator?: any, language?: string, timeRange?: string, claimRequest?: () => void}} [options]
22
22
  */
23
23
  export function searchCodexSubscription(query: string, options?: {
24
24
  model?: string;
25
25
  signal?: AbortSignal;
26
26
  clientFactory?: typeof createCodexAppServerClient;
27
- }): Promise<void>;
27
+ coordinator?: any;
28
+ language?: string;
29
+ timeRange?: string;
30
+ claimRequest?: () => void;
31
+ }): any;
28
32
  /** Test hook for process-shared broker state. */
29
33
  export function __resetCodexSubscriptionSearchForTests(): Promise<void>;
30
34
  export const DEFAULT_CODEX_SEARCH_MODEL: "gpt-5.6-luna";
31
- import { createCodexAppServerClient } from "../../ai/providers/codex-app.js";
35
+ import { createCodexAppServerClient } from "../../ai/providers/codex/app-server-client.js";
@@ -1,6 +1,6 @@
1
1
  /** @typedef {import("./shared/process-jobs.js").ProcessJobsController} ProcessJobsController */
2
2
  /**
3
- * @param {{executable: string, args?: string[], workdir?: string, description?: string, timeout_ms?: number, max_output_chars?: number, background?: boolean}} params
3
+ * @param {{executable: string, args?: string[], workdir?: string, description?: string, timeout_ms?: number, max_output_chars?: number, background?: boolean, wake_on_completion?: boolean}} params
4
4
  * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, processJobsController?: ProcessJobsController}} [options]
5
5
  */
6
6
  export function execToolImpl(params: {
@@ -11,6 +11,7 @@ export function execToolImpl(params: {
11
11
  timeout_ms?: number;
12
12
  max_output_chars?: number;
13
13
  background?: boolean;
14
+ wake_on_completion?: boolean;
14
15
  }, options?: {
15
16
  signal?: AbortSignal;
16
17
  sandboxPolicy?: any;
@@ -21,10 +22,10 @@ export function execToolImpl(params: {
21
22
  /**
22
23
  * Execute an argv vector directly, without shell parsing.
23
24
  *
24
- * @param {{executable: string, args?: string[], workdir?: string, description?: string, timeout_ms?: number, max_output_chars?: number, background?: boolean}} params
25
+ * @param {{executable: string, args?: string[], workdir?: string, description?: string, timeout_ms?: number, max_output_chars?: number, background?: boolean, wake_on_completion?: boolean}} params
25
26
  * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, processJobsController?: ProcessJobsController}} [options]
26
27
  */
27
- export function execToolRun({ executable, args, workdir, description, timeout_ms, max_output_chars, background, }: {
28
+ export function execToolRun({ executable, args, workdir, description, timeout_ms, max_output_chars, background, wake_on_completion, }: {
28
29
  executable: string;
29
30
  args?: string[];
30
31
  workdir?: string;
@@ -32,6 +33,7 @@ export function execToolRun({ executable, args, workdir, description, timeout_ms
32
33
  timeout_ms?: number;
33
34
  max_output_chars?: number;
34
35
  background?: boolean;
36
+ wake_on_completion?: boolean;
35
37
  }, { signal, sandboxPolicy, sandboxEngine, ctx, processJobsController, }?: {
36
38
  signal?: AbortSignal;
37
39
  sandboxPolicy?: any;
@@ -7,6 +7,7 @@ export { createWebToolController } from "./web-controller.js";
7
7
  export { resolveRgPath } from "./shared/ripgrep.js";
8
8
  export { bashToolImpl, bashToolRun, normalizeBackgroundBashTimeoutMs, normalizeBackgroundTimeoutMs, normalizeBashTimeoutMs, normalizeProcessTimeoutMs } from "./bash.js";
9
9
  export { execToolImpl, execToolRun } from "./exec.js";
10
+ export { DEFAULT_MONITOR_TIMEOUT_MS, MIN_MONITOR_TIMEOUT_MS, monitorStopToolRun, monitorToolRun, normalizeMonitorTimeoutMs } from "./monitor.js";
10
11
  export { webFetchToolImpl, performWebFetch } from "./web-fetch.js";
11
12
  export { webSearchToolImpl, performWebSearch } from "./web-search.js";
12
13
  export { DEFAULT_CODEX_SEARCH_MODEL, inspectCodexSubscriptionSearch, searchCodexSubscription } from "./codex-subscription-search.js";
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Normalize `timeout_ms` for a monitor. Unlike Bash there is no
3
+ * seconds-vs-milliseconds heuristic — this field is new, so it is exact
4
+ * milliseconds only. `undefined`/invalid falls back to the documented default;
5
+ * the host's own ceiling clamps the result on its side and reports what it
6
+ * actually granted.
7
+ */
8
+ export function normalizeMonitorTimeoutMs(value: any, fallback?: number): number;
9
+ /**
10
+ * Structured Monitor execution used by the Pi bridge.
11
+ *
12
+ * Command preparation is deliberately byte-identical to Bash: the same
13
+ * `/bin/bash --noprofile --norc -c` shape, the same workdir rules, the same
14
+ * cleaned startup environment, and the same sandbox `prepareCommand` seam. A
15
+ * monitor must never be a way to run a command Bash could not.
16
+ *
17
+ * @param {{command?: string, description?: string, timeout_ms?: number, persistent?: boolean, workdir?: string, wake_on?: "batch"|"exit", dedupe?: "none"|"batch", min_wake_interval_ms?: number}} params
18
+ * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, monitorsController?: import("./shared/monitors.js").MonitorsController}} [options]
19
+ */
20
+ export function monitorToolRun({ command, description, timeout_ms, persistent, workdir, wake_on, dedupe, min_wake_interval_ms }: {
21
+ command?: string;
22
+ description?: string;
23
+ timeout_ms?: number;
24
+ persistent?: boolean;
25
+ workdir?: string;
26
+ wake_on?: "batch" | "exit";
27
+ dedupe?: "none" | "batch";
28
+ min_wake_interval_ms?: number;
29
+ }, { sandboxPolicy, sandboxEngine, ctx, monitorsController }?: {
30
+ signal?: AbortSignal;
31
+ sandboxPolicy?: any;
32
+ sandboxEngine?: any;
33
+ ctx?: any;
34
+ monitorsController?: import("./shared/monitors.js").MonitorsController;
35
+ }): Promise<any>;
36
+ /**
37
+ * @param {{monitor_id?: string}} params
38
+ * @param {{monitorsController?: import("./shared/monitors.js").MonitorsController}} [options]
39
+ */
40
+ export function monitorStopToolRun({ monitor_id }: {
41
+ monitor_id?: string;
42
+ }, { monitorsController }?: {
43
+ monitorsController?: import("./shared/monitors.js").MonitorsController;
44
+ }): Promise<any>;
45
+ /** Claude-Code-compatible defaults: 5 minutes, never below one second. */
46
+ export const DEFAULT_MONITOR_TIMEOUT_MS: 300000;
47
+ export const MIN_MONITOR_TIMEOUT_MS: 1000;
@@ -35,9 +35,9 @@ export function createStructuredOutputTool(outputSchema: any, onStructuredOutput
35
35
  };
36
36
  /**
37
37
  * @param {any} allowedTools
38
- * @param {{disallowedTools?: any[], skillNames?: any[], skills?: any[], skillsRoot?: any, dataDir?: any, cwd?: any, onEvent?: (event: any) => void, toolLimits?: any, persistArtifact?: any, onTruncate?: any, toolPayloadMaxBytes?: number, imageInlineMaxBytes?: any, toolPolicy?: any, sandboxPolicy?: any, sandboxEngine?: any, approvalManager?: any, approvalModel?: any, nodeReplController?: any, webController?: any, processJobsController?: any, toolExecutionMode?: "sequential"|"safe-parallel", subagents?: any, subagentContext?: any, ctx?: any}} [options]
38
+ * @param {{disallowedTools?: any[], skillNames?: any[], skills?: any[], skillsRoot?: any, dataDir?: any, cwd?: any, onEvent?: (event: any) => void, toolLimits?: any, persistArtifact?: any, onTruncate?: any, toolPayloadMaxBytes?: number, imageInlineMaxBytes?: any, toolPolicy?: any, sandboxPolicy?: any, sandboxEngine?: any, approvalManager?: any, approvalModel?: any, nodeReplController?: any, webController?: any, processJobsController?: any, processJobsAvailability?: any, monitorsController?: any, toolExecutionMode?: "sequential"|"safe-parallel", subagents?: any, subagentContext?: any, ctx?: any}} [options]
39
39
  */
40
- export function getPiBuiltinTools(allowedTools: any, { disallowedTools, skillNames, skills, skillsRoot, dataDir, cwd, onEvent, toolLimits, persistArtifact, onTruncate, toolPayloadMaxBytes, imageInlineMaxBytes, toolPolicy, sandboxPolicy, sandboxEngine, approvalManager, approvalModel, nodeReplController, webController, processJobsController, subagents, subagentContext, toolExecutionMode, ctx, }?: {
40
+ export function getPiBuiltinTools(allowedTools: any, { disallowedTools, skillNames, skills, skillsRoot, dataDir, cwd, onEvent, toolLimits, persistArtifact, onTruncate, toolPayloadMaxBytes, imageInlineMaxBytes, toolPolicy, sandboxPolicy, sandboxEngine, approvalManager, approvalModel, nodeReplController, webController, processJobsController, processJobsAvailability, monitorsController, subagents, subagentContext, toolExecutionMode, ctx, }?: {
41
41
  disallowedTools?: any[];
42
42
  skillNames?: any[];
43
43
  skills?: any[];
@@ -58,6 +58,8 @@ export function getPiBuiltinTools(allowedTools: any, { disallowedTools, skillNam
58
58
  nodeReplController?: any;
59
59
  webController?: any;
60
60
  processJobsController?: any;
61
+ processJobsAvailability?: any;
62
+ monitorsController?: any;
61
63
  toolExecutionMode?: "sequential" | "safe-parallel";
62
64
  subagents?: any;
63
65
  subagentContext?: any;
@@ -81,10 +83,11 @@ export function coerceMcpContent(out: any, { textLimit, imageInlineMaxBytes, per
81
83
  /**
82
84
  * @param {any} mcpConfig
83
85
  * @param {Set<any>} [reservedNames]
84
- * @param {{limits?: any, cwd?: any, persistArtifact?: any, qaOutputDir?: any, onTruncate?: any, toolPayloadMaxBytes?: number, sandboxPolicy?: any, sandboxEngine?: any, onToolProgress?: any, ctx?: any, mcpApps?: any, runId?: string}} [options]
86
+ * @param {{limits?: any, mcpCallNoTotalTimeoutTools?: readonly string[], cwd?: any, persistArtifact?: any, qaOutputDir?: any, onTruncate?: any, toolPayloadMaxBytes?: number, sandboxPolicy?: any, sandboxEngine?: any, onToolProgress?: any, ctx?: any, mcpApps?: any, runId?: string}} [options]
85
87
  */
86
- export function initPiMcpTools(mcpConfig: any, reservedNames?: Set<any>, { limits, cwd, persistArtifact, qaOutputDir, onTruncate, toolPayloadMaxBytes, sandboxPolicy, sandboxEngine, onToolProgress, ctx, mcpApps, runId, }?: {
88
+ export function initPiMcpTools(mcpConfig: any, reservedNames?: Set<any>, { limits, mcpCallNoTotalTimeoutTools, cwd, persistArtifact, qaOutputDir, onTruncate, toolPayloadMaxBytes, sandboxPolicy, sandboxEngine, onToolProgress, ctx, mcpApps, runId, }?: {
87
89
  limits?: any;
90
+ mcpCallNoTotalTimeoutTools?: readonly string[];
88
91
  cwd?: any;
89
92
  persistArtifact?: any;
90
93
  qaOutputDir?: any;
@@ -0,0 +1,4 @@
1
+ export function cleanBashEnvironment(sourceEnv?: NodeJS.ProcessEnv): {
2
+ BASH_ENV: string;
3
+ ENV: string;
4
+ };
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Kernel-local structural controller seam. The typed public interface lives in
3
+ * runtime-adapter; this package deliberately has no workspace dependencies.
4
+ *
5
+ * @typedef {Object} MonitorsController
6
+ * @property {(request: {
7
+ * prepared: import("../../sandbox-seam.js").PreparedSandboxCommand,
8
+ * summary: string,
9
+ * description: string,
10
+ * timeoutMs?: number,
11
+ * persistent?: boolean,
12
+ * wakeOn?: "batch"|"exit",
13
+ * dedupe?: "none"|"batch",
14
+ * minWakeIntervalMs?: number,
15
+ * launch: (options?: {timeoutMs?: number, onStdout?: (chunk: Buffer) => void, onStderr?: (chunk: Buffer) => void}) => ReturnType<typeof startPreparedProcess>,
16
+ * }) => Promise<{monitorId: string, state: "starting"|"running", startedAt: string, maxRuntimeMs: number, persistent: boolean, wakeOn: "batch"|"exit", dedupe: "none"|"batch", minWakeIntervalMs: number}>} start
17
+ * @property {(monitorId: string) => Promise<{monitorId: string, state: string, stopped: boolean}>} stop
18
+ */
19
+ /**
20
+ * Transfer one prepared watch command to the injected host controller. From the
21
+ * instant `start()` is invoked, the controller owns cleanup on every path.
22
+ *
23
+ * @param {{
24
+ * controller: MonitorsController,
25
+ * prepared: import("../../sandbox-seam.js").PreparedSandboxCommand,
26
+ * summary: string,
27
+ * description: string,
28
+ * timeoutMs?: number,
29
+ * persistent?: boolean,
30
+ * wakeOn?: "batch"|"exit",
31
+ * dedupe?: "none"|"batch",
32
+ * minWakeIntervalMs?: number,
33
+ * startedAt: number,
34
+ * failed: (text: string, code: string, startedAt: number) => any,
35
+ * }} input
36
+ */
37
+ export function handOffMonitor({ controller, prepared, summary, description, timeoutMs, persistent, wakeOn, dedupe, minWakeIntervalMs, startedAt, failed, }: {
38
+ controller: MonitorsController;
39
+ prepared: import("../../sandbox-seam.js").PreparedSandboxCommand;
40
+ summary: string;
41
+ description: string;
42
+ timeoutMs?: number;
43
+ persistent?: boolean;
44
+ wakeOn?: "batch" | "exit";
45
+ dedupe?: "none" | "batch";
46
+ minWakeIntervalMs?: number;
47
+ startedAt: number;
48
+ failed: (text: string, code: string, startedAt: number) => any;
49
+ }): Promise<any>;
50
+ /**
51
+ * Stop one monitor by id. Idempotent: stopping an already-terminal monitor is a
52
+ * success that reports the state it settled in, never an error, so a model that
53
+ * re-issues a stop after a terminal wake is not pushed into a retry loop.
54
+ *
55
+ * @param {{controller: MonitorsController, monitorId: unknown, startedAt: number, failed: (text: string, code: string, startedAt: number) => any}} input
56
+ */
57
+ export function handOffMonitorStop({ controller, monitorId, startedAt, failed }: {
58
+ controller: MonitorsController;
59
+ monitorId: unknown;
60
+ startedAt: number;
61
+ failed: (text: string, code: string, startedAt: number) => any;
62
+ }): Promise<any>;
63
+ /**
64
+ * Kernel-local structural controller seam. The typed public interface lives in
65
+ * runtime-adapter; this package deliberately has no workspace dependencies.
66
+ */
67
+ export type MonitorsController = {
68
+ start: (request: {
69
+ prepared: import("../../sandbox-seam.js").PreparedSandboxCommand;
70
+ summary: string;
71
+ description: string;
72
+ timeoutMs?: number;
73
+ persistent?: boolean;
74
+ wakeOn?: "batch" | "exit";
75
+ dedupe?: "none" | "batch";
76
+ minWakeIntervalMs?: number;
77
+ launch: (options?: {
78
+ timeoutMs?: number;
79
+ onStdout?: (chunk: Buffer) => void;
80
+ onStderr?: (chunk: Buffer) => void;
81
+ }) => ReturnType<typeof startPreparedProcess>;
82
+ }) => Promise<{
83
+ monitorId: string;
84
+ state: "starting" | "running";
85
+ startedAt: string;
86
+ maxRuntimeMs: number;
87
+ persistent: boolean;
88
+ wakeOn: "batch" | "exit";
89
+ dedupe: "none" | "batch";
90
+ minWakeIntervalMs: number;
91
+ }>;
92
+ stop: (monitorId: string) => Promise<{
93
+ monitorId: string;
94
+ state: string;
95
+ stopped: boolean;
96
+ }>;
97
+ };
98
+ import { startPreparedProcess } from "./process-runner.js";
@@ -8,6 +8,7 @@
8
8
  * prepared: import("../../sandbox-seam.js").PreparedSandboxCommand,
9
9
  * summary: string,
10
10
  * description?: string,
11
+ * wakeOnCompletion?: boolean,
11
12
  * timeoutMs?: number,
12
13
  * maxOutputChars?: number,
13
14
  * launch: (options?: {timeoutMs?: number, signal?: AbortSignal, maxBufferBytes?: number, onStdout?: (chunk: Buffer) => void, onStderr?: (chunk: Buffer) => void}) => ReturnType<typeof startPreparedProcess>,
@@ -23,18 +24,20 @@
23
24
  * prepared: import("../../sandbox-seam.js").PreparedSandboxCommand,
24
25
  * summary: string,
25
26
  * description?: string,
27
+ * wakeOnCompletion?: boolean,
26
28
  * timeoutMs?: number,
27
29
  * maxOutputChars?: number,
28
30
  * startedAt: number,
29
31
  * failed: (text: string, code: string, startedAt: number) => any,
30
32
  * }} input
31
33
  */
32
- export function handOffProcessJob({ controller, tool, prepared, summary, description, timeoutMs, maxOutputChars, startedAt, failed, }: {
34
+ export function handOffProcessJob({ controller, tool, prepared, summary, description, wakeOnCompletion, timeoutMs, maxOutputChars, startedAt, failed, }: {
33
35
  controller: ProcessJobsController;
34
36
  tool: "Exec" | "Bash";
35
37
  prepared: import("../../sandbox-seam.js").PreparedSandboxCommand;
36
38
  summary: string;
37
39
  description?: string;
40
+ wakeOnCompletion?: boolean;
38
41
  timeoutMs?: number;
39
42
  maxOutputChars?: number;
40
43
  startedAt: number;
@@ -50,6 +53,7 @@ export type ProcessJobsController = {
50
53
  prepared: import("../../sandbox-seam.js").PreparedSandboxCommand;
51
54
  summary: string;
52
55
  description?: string;
56
+ wakeOnCompletion?: boolean;
53
57
  timeoutMs?: number;
54
58
  maxOutputChars?: number;
55
59
  launch: (options?: {
@@ -6,18 +6,19 @@
6
6
  * or exceeds that cap.
7
7
  *
8
8
  * @param {{command: string, args?: string[], cwd?: string, env?: Record<string, string|undefined>}} commandSpec
9
- * @param {{timeoutMs?: number, signal?: AbortSignal, maxBufferBytes?: number, input?: string|Buffer}} [options]
9
+ * @param {{timeoutMs?: number, signal?: AbortSignal, maxBufferBytes?: number, input?: string|Buffer, exactEnvironment?: boolean}} [options]
10
10
  */
11
11
  export function runPreparedProcess(commandSpec: {
12
12
  command: string;
13
13
  args?: string[];
14
14
  cwd?: string;
15
15
  env?: Record<string, string | undefined>;
16
- }, { timeoutMs, signal, maxBufferBytes, input, }?: {
16
+ }, { timeoutMs, signal, maxBufferBytes, input, exactEnvironment, }?: {
17
17
  timeoutMs?: number;
18
18
  signal?: AbortSignal;
19
19
  maxBufferBytes?: number;
20
20
  input?: string | Buffer;
21
+ exactEnvironment?: boolean;
21
22
  }): Promise<any>;
22
23
  /**
23
24
  * Start one already-prepared executable and expose its process-group handle.
@@ -28,7 +29,15 @@ export function runPreparedProcess(commandSpec: {
28
29
  * descendant in the owned group is still alive.
29
30
  *
30
31
  * @param {{command: string, args?: string[], cwd?: string, env?: Record<string, string|undefined>}} commandSpec
31
- * @param {{timeoutMs?: number, signal?: AbortSignal, maxBufferBytes?: number, input?: string|Buffer, waitForProcessGroup?: boolean, exactEnvironment?: boolean, onStdout?: (chunk: Buffer) => void, onStderr?: (chunk: Buffer) => void}} [options]
32
+ * `outputMode` selects how output is handled. "buffer" (default) accumulates it
33
+ * under `maxBufferBytes` and terminates the process when that bound is crossed —
34
+ * the right contract for a job whose whole output is the result. "stream" hands
35
+ * every chunk to `onStdout`/`onStderr` and stores NEITHER, so an indefinitely
36
+ * long watch is never killed for producing output and the caller owns the only
37
+ * copy. Buffering stderr as well would hand a streaming caller two overlapping
38
+ * views of it: the runner's bounded PREFIX plus the caller's own tail.
39
+ *
40
+ * @param {{timeoutMs?: number, signal?: AbortSignal, maxBufferBytes?: number, input?: string|Buffer, waitForProcessGroup?: boolean, exactEnvironment?: boolean, outputMode?: "buffer"|"stream", onStdout?: (chunk: Buffer) => void, onStderr?: (chunk: Buffer) => void}} [options]
32
41
  * For process jobs, `release()` is the persistence fence: the target cannot
33
42
  * spawn until the host has durably recorded the returned ownership metadata.
34
43
  * Foreground handles expose a harmless no-op release for one structural shape.
@@ -40,13 +49,14 @@ export function startPreparedProcess(commandSpec: {
40
49
  args?: string[];
41
50
  cwd?: string;
42
51
  env?: Record<string, string | undefined>;
43
- }, { timeoutMs, signal, maxBufferBytes, input, waitForProcessGroup, exactEnvironment, onStdout, onStderr, }?: {
52
+ }, { timeoutMs, signal, maxBufferBytes, input, waitForProcessGroup, exactEnvironment, outputMode, onStdout, onStderr, }?: {
44
53
  timeoutMs?: number;
45
54
  signal?: AbortSignal;
46
55
  maxBufferBytes?: number;
47
56
  input?: string | Buffer;
48
57
  waitForProcessGroup?: boolean;
49
58
  exactEnvironment?: boolean;
59
+ outputMode?: "buffer" | "stream";
50
60
  onStdout?: (chunk: Buffer) => void;
51
61
  onStderr?: (chunk: Buffer) => void;
52
62
  }): {
@@ -47,6 +47,8 @@ export type RuntimeSandbox = import("../../sandbox-seam.js").RuntimeSandbox;
47
47
  export type ToolContext = {
48
48
  workspace?: string;
49
49
  repoRoot?: string;
50
+ additionalReadRoots?: ReadonlyArray<string>;
51
+ additionalWriteRoots?: ReadonlyArray<string>;
50
52
  runId?: string;
51
53
  toolArtifactDir?: string;
52
54
  ripgrepPath?: string;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Classify access and authentication interstitials without treating incidental
3
+ * words such as "captcha" or "access denied" as conclusive evidence.
4
+ *
5
+ * @param {{url?: string, text?: string, statusCode?: number}} input
6
+ * @returns {{code: "access_challenge"|"authentication_required", message: string}|undefined}
7
+ */
8
+ export function classifyWebAccessInterstitial({ url, text, statusCode }?: {
9
+ url?: string;
10
+ text?: string;
11
+ statusCode?: number;
12
+ }): {
13
+ code: "access_challenge" | "authentication_required";
14
+ message: string;
15
+ } | undefined;
16
+ /**
17
+ * @param {{url?: string, text?: string, statusCode?: number}} input
18
+ */
19
+ export function assertNoWebAccessInterstitial(input: {
20
+ url?: string;
21
+ text?: string;
22
+ statusCode?: number;
23
+ }): void;
@@ -12,5 +12,8 @@ export function renderWithAgentBrowser(url: string, { browserCommand, namespace,
12
12
  ctx?: any;
13
13
  signal?: AbortSignal;
14
14
  registerCleanup?: (cleanup: () => Promise<void>) => () => void;
15
- }): Promise<any>;
15
+ }): Promise<{
16
+ text: any;
17
+ finalUrl: string;
18
+ }>;
16
19
  export function extractBrowserText(output: any): any;
@@ -4,10 +4,12 @@
4
4
  * cleanup. Search results are the exception: they live in the process-wide
5
5
  * cache above so sibling subagents and later turns can reuse them.
6
6
  *
7
- * @param {{searchConfig?: any, fetchConfig?: any, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, fetchImpl?: typeof fetch, browserRenderer?: any, codexSearch?: any}} [options]
7
+ * @param {{coordinator?: any, searchConfig?: any, searchState?: any, fetchConfig?: any, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, fetchImpl?: typeof fetch, browserRenderer?: any, codexSearch?: any}} [options]
8
8
  */
9
- export function createWebToolController({ searchConfig, fetchConfig, sandboxPolicy, sandboxEngine, ctx, fetchImpl, browserRenderer, codexSearch, }?: {
9
+ export function createWebToolController({ coordinator, searchConfig, searchState: suppliedSearchState, fetchConfig, sandboxPolicy, sandboxEngine, ctx, fetchImpl, browserRenderer, codexSearch, }?: {
10
+ coordinator?: any;
10
11
  searchConfig?: any;
12
+ searchState?: any;
11
13
  fetchConfig?: any;
12
14
  sandboxPolicy?: any;
13
15
  sandboxEngine?: any;
@@ -0,0 +1,27 @@
1
+ export function contentKind(contentType: any, bytes: any): "binary" | "text" | "markdown" | "pdf" | "json" | "xml" | "html";
2
+ export function decodeWebBytes(bytes: any, contentType: any, kind?: string): {
3
+ text: string;
4
+ charset: string;
5
+ charsetSource: string;
6
+ hadDecodingReplacement: boolean;
7
+ };
8
+ export function extractWebDocument(bytes: any, { contentType, format, url }: {
9
+ contentType: any;
10
+ format: any;
11
+ url: any;
12
+ }): Promise<{
13
+ text: string;
14
+ charset: string;
15
+ charsetSource: string;
16
+ hadDecodingReplacement: boolean;
17
+ kind: string;
18
+ body: any;
19
+ readableText: string;
20
+ title: any;
21
+ extractionStage: any;
22
+ parserFailureCount: any;
23
+ parserFailures: any;
24
+ }>;
25
+ export function shouldAutoRender(readableText: any, html: any): boolean;
26
+ export function markdownToText(value: any): string;
27
+ export const MAX_STRUCTURED_DOCUMENT_BYTES: number;
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Compatibility wrapper for direct callers.
3
3
  *
4
- * @param {{url: string, headers?: Record<string, string>, max_output_chars?: number, format?: string, render?: string}} params
5
- * @param {{sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, signal?: AbortSignal, retryDelaysMs?: number[], fetchConfig?: any, fetchImpl?: typeof fetch, browserRenderer?: typeof renderWithAgentBrowser, namespace?: string, registerCleanup?: (cleanup: () => Promise<void>) => () => void}} [options]
4
+ * @param {{url: string, headers?: Record<string, string>, max_output_chars?: number, format?: string, render?: string, start_line?: number, max_lines?: number}} params
5
+ * @param {{documentOnly?: boolean, coordinator?: any, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, signal?: AbortSignal, retryDelaysMs?: number[], fetchConfig?: any, fetchImpl?: typeof fetch, browserRenderer?: typeof renderWithAgentBrowser, namespace?: string, registerCleanup?: (cleanup: () => Promise<void>) => () => void}} [options]
6
6
  */
7
7
  export function webFetchToolImpl(params: {
8
8
  url: string;
@@ -10,7 +10,11 @@ export function webFetchToolImpl(params: {
10
10
  max_output_chars?: number;
11
11
  format?: string;
12
12
  render?: string;
13
+ start_line?: number;
14
+ max_lines?: number;
13
15
  }, options?: {
16
+ documentOnly?: boolean;
17
+ coordinator?: any;
14
18
  sandboxPolicy?: any;
15
19
  sandboxEngine?: any;
16
20
  ctx?: any;
@@ -25,16 +29,20 @@ export function webFetchToolImpl(params: {
25
29
  /**
26
30
  * Fetch and locally extract one public URL.
27
31
  *
28
- * @param {{url: string, headers?: Record<string, string>, max_output_chars?: number, format?: string, render?: string}} params
29
- * @param {{sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, signal?: AbortSignal, retryDelaysMs?: number[], fetchConfig?: any, fetchImpl?: typeof fetch, browserRenderer?: typeof renderWithAgentBrowser, namespace?: string, registerCleanup?: (cleanup: () => Promise<void>) => () => void}} [options]
32
+ * @param {{url: string, headers?: Record<string, string>, max_output_chars?: number, format?: string, render?: string, start_line?: number, max_lines?: number}} params
33
+ * @param {{documentOnly?: boolean, coordinator?: any, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, signal?: AbortSignal, retryDelaysMs?: number[], fetchConfig?: any, fetchImpl?: typeof fetch, browserRenderer?: typeof renderWithAgentBrowser, namespace?: string, registerCleanup?: (cleanup: () => Promise<void>) => () => void}} [options]
30
34
  */
31
- export function performWebFetch({ url, headers, max_output_chars, format, render, }: {
35
+ export function performWebFetch(params: {
32
36
  url: string;
33
37
  headers?: Record<string, string>;
34
38
  max_output_chars?: number;
35
39
  format?: string;
36
40
  render?: string;
37
- }, { sandboxPolicy, sandboxEngine, ctx, signal, retryDelaysMs, fetchConfig, fetchImpl, browserRenderer, namespace, registerCleanup, }?: {
41
+ start_line?: number;
42
+ max_lines?: number;
43
+ }, options?: {
44
+ documentOnly?: boolean;
45
+ coordinator?: any;
38
46
  sandboxPolicy?: any;
39
47
  sandboxEngine?: any;
40
48
  ctx?: any;
@@ -45,7 +53,8 @@ export function performWebFetch({ url, headers, max_output_chars, format, render
45
53
  browserRenderer?: typeof renderWithAgentBrowser;
46
54
  namespace?: string;
47
55
  registerCleanup?: (cleanup: () => Promise<void>) => () => void;
48
- }): Promise<{
56
+ }): Promise<any>;
57
+ export function formatWebFetchDocument(document: any, params: any, ctx: any): {
49
58
  text: any;
50
59
  outcome: {
51
60
  status: string;
@@ -61,22 +70,8 @@ export function performWebFetch({ url, headers, max_output_chars, format, render
61
70
  error: boolean;
62
71
  } | {
63
72
  text: string;
64
- outcome: {
65
- status: string;
66
- code: string;
67
- retryable: boolean;
68
- attempts: number;
69
- backend: string;
70
- cacheHit: boolean;
71
- durationMs: number;
72
- bytes: number;
73
- truncated: boolean;
74
- statusCode: any;
75
- redirectCount: number;
76
- rendered: boolean;
77
- renderFailed: boolean;
78
- contentKind: string;
79
- };
73
+ outcome: any;
80
74
  error: boolean;
81
- }>;
75
+ document: any;
76
+ };
82
77
  import { renderWithAgentBrowser } from "./web-browser-render.js";
@@ -0,0 +1,20 @@
1
+ /** One deadline covers admission, backend startup, I/O, and retries. */
2
+ export function withWebDeadline(signal: any, milliseconds: any, execute: any): Promise<any>;
3
+ export function coordinatedWebRequest(coordinator: any, kind: any, key: any, signal: any, execute: any, classify?: typeof classifySearch): Promise<any>;
4
+ export function webRequestFailure(error: any, backend: any, signal: any): {
5
+ ok: boolean;
6
+ backend: any;
7
+ code: any;
8
+ message: string;
9
+ retryable: boolean;
10
+ cooldown: boolean;
11
+ rateLimited: boolean;
12
+ retryAfterMs: any;
13
+ retryAtMs: any;
14
+ };
15
+ declare function classifySearch(result: any): {
16
+ retryAtMs?: any;
17
+ retryAfterMs?: any;
18
+ status: string;
19
+ };
20
+ export {};
@@ -0,0 +1,31 @@
1
+ /** Replace isolated UTF-16 surrogates while preserving valid astral pairs. @param {unknown} value */
2
+ export function toWellFormedText(value: unknown): string;
3
+ /** @param {unknown} value @param {number} maxChars */
4
+ export function sliceWellFormedCodePoints(value: unknown, maxChars: number): string;
5
+ /** @param {string} value @param {number} maxBytes */
6
+ export function sliceUtf8(value: string, maxBytes: number): string;
7
+ /** @param {unknown} value @param {number} [maxChars] */
8
+ export function boundWebSearchSnippet(value: unknown, maxChars?: number): {
9
+ text: string;
10
+ truncated: boolean;
11
+ };
12
+ /**
13
+ * @param {Array<{title?: unknown, url?: unknown, snippet?: unknown, snippetTruncated?: boolean}>} results
14
+ * @param {{maxBytes?: number}} [options]
15
+ */
16
+ export function renderBoundedWebSearchBody(results: Array<{
17
+ title?: unknown;
18
+ url?: unknown;
19
+ snippet?: unknown;
20
+ snippetTruncated?: boolean;
21
+ }>, { maxBytes }?: {
22
+ maxBytes?: number;
23
+ }): {
24
+ body: string;
25
+ renderedResultCount: number;
26
+ truncated: boolean;
27
+ };
28
+ export const WEB_SEARCH_TITLE_MAX_CHARS: 500;
29
+ export const WEB_SEARCH_SNIPPET_MAX_CHARS: 4000;
30
+ export const WEB_SEARCH_BODY_MAX_BYTES: number;
31
+ export const WEB_SEARCH_SNIPPET_TRUNCATION_MARKER: "[snippet truncated; use WebFetch for full source]";