@mono-agent/agent-runtime 0.19.1 → 0.20.1

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 (51) hide show
  1. package/MIGRATION.md +1 -1
  2. package/README.md +101 -4
  3. package/package.json +1 -1
  4. package/src/agent/sandbox-seam.js +16 -2
  5. package/src/agent/tools/bash.js +26 -4
  6. package/src/agent/tools/edit.js +72 -5
  7. package/src/agent/tools/exec.js +22 -4
  8. package/src/agent/tools/glob.js +65 -9
  9. package/src/agent/tools/grep.js +66 -11
  10. package/src/agent/tools/node-repl.js +5 -2
  11. package/src/agent/tools/pi-bridge.js +263 -48
  12. package/src/agent/tools/read.js +50 -10
  13. package/src/agent/tools/shared/path-resolver.js +67 -2
  14. package/src/agent/tools/shared/process-jobs.js +188 -0
  15. package/src/agent/tools/shared/process-runner.js +541 -30
  16. package/src/agent/tools/shared/protected-filesystem.js +150 -0
  17. package/src/agent/tools/web-search.js +63 -8
  18. package/src/agent/tools/write.js +52 -6
  19. package/src/ai/providers/acp.js +4 -0
  20. package/src/ai/providers/claude-cli.js +35 -2
  21. package/src/ai/providers/claude-sdk.js +12 -0
  22. package/src/ai/providers/codex-app.js +15 -2
  23. package/src/ai/providers/pi-native/stream-subscriber.js +29 -2
  24. package/src/ai/providers/pi-native/turn-runner.js +3 -0
  25. package/src/ai/providers/pi-native.js +7 -1
  26. package/src/ai/runtime/capabilities.js +2 -0
  27. package/src/ai/runtime/router.js +78 -6
  28. package/src/ai/streaming/codex-events.js +15 -0
  29. package/src/ai/streaming/opencode-events.js +5 -0
  30. package/src/ai/tool-lifecycle.js +347 -0
  31. package/src/ai/types.js +58 -0
  32. package/src/runtime.js +35 -21
  33. package/types/agent/sandbox-seam.d.ts +19 -6
  34. package/types/agent/tools/bash.d.ts +11 -26
  35. package/types/agent/tools/edit.d.ts +3 -2
  36. package/types/agent/tools/exec.d.ts +13 -26
  37. package/types/agent/tools/glob.d.ts +3 -2
  38. package/types/agent/tools/grep.d.ts +3 -2
  39. package/types/agent/tools/pi-bridge.d.ts +11 -4
  40. package/types/agent/tools/read.d.ts +3 -2
  41. package/types/agent/tools/shared/path-resolver.d.ts +8 -0
  42. package/types/agent/tools/shared/process-jobs.d.ts +64 -0
  43. package/types/agent/tools/shared/process-runner.d.ts +45 -3
  44. package/types/agent/tools/shared/protected-filesystem.d.ts +51 -0
  45. package/types/agent/tools/write.d.ts +3 -2
  46. package/types/ai/providers/pi-native/stream-subscriber.d.ts +2 -0
  47. package/types/ai/runtime/capabilities.d.ts +3 -0
  48. package/types/ai/streaming/codex-events.d.ts +1 -0
  49. package/types/ai/streaming/opencode-events.d.ts +1 -0
  50. package/types/ai/tool-lifecycle.d.ts +43 -0
  51. package/types/ai/types.d.ts +118 -0
package/src/runtime.js CHANGED
@@ -41,6 +41,7 @@ import { createToolContext, updateToolContext } from "./agent/tools/shared/tool-
41
41
  import { resolveRuntimeBrand } from "./runtime-brand.js";
42
42
  import { retireDurableNativeSession } from "./ai/providers/pi-native/session-lifecycle.js";
43
43
  import { instrumentLiveInputAppliedEvents } from "./ai/runtime/live-input-events.js";
44
+ import { createToolLifecycleEventGate } from "./ai/tool-lifecycle.js";
44
45
 
45
46
  /**
46
47
  * @typedef {import('./ai/types.js').AgentRuntimeHostOptions} AgentRuntimeHostOptions
@@ -210,9 +211,16 @@ export function createRuntime(host = {}) {
210
211
  const callObservers = Array.isArray(options.observers) ? options.observers : [];
211
212
  const hub = createObserverHub({
212
213
  observers: [...hostObservers, ...callObservers],
214
+ });
215
+ const lifecycleGate = createToolLifecycleEventGate({
216
+ sink: options.toolLifecycleSink,
217
+ // Observer delivery keeps the runtime's synchronous contract. Only the
218
+ // client-facing lifecycle event waits for its serialized persistence.
219
+ onObserve: (event) => hub.emit(event),
213
220
  onEvent: options.onEvent,
221
+ abortSignal: options.abortSignal,
214
222
  });
215
- const liveInput = instrumentLiveInputAppliedEvents(options.liveInput, hub.emit);
223
+ const liveInput = instrumentLiveInputAppliedEvents(options.liveInput, lifecycleGate.emit);
216
224
  const prompts = resolvePrompts(host.prompts, options.prompts);
217
225
  // A request-scoped environment must never mutate the long-lived runtime's
218
226
  // shared ToolContext. Clone only for this call, preserving configureTools
@@ -226,26 +234,32 @@ export function createRuntime(host = {}) {
226
234
  const subagents = options.subagents === undefined
227
235
  ? undefined
228
236
  : { ...options.subagents, run: options.subagents.run ?? defaultSubagentRun };
229
- const result = await bridge.execute(systemPrompt, {
230
- ...hostDefaults,
231
- ...options,
232
- ...(subagents === undefined ? {} : { subagents }),
233
- // `...options` alone doesn't carry the `options.model` narrowing above
234
- // (spread reads the parameter's declared Partial type); re-assert
235
- // the already-validated model so the request satisfies RuntimeRequest.
236
- model: options.model,
237
- executionMode,
238
- runtimeBrand,
239
- toolContext: runToolContext,
240
- observerHub: hub,
241
- onEvent: hub.emit,
242
- ...(liveInput === undefined ? {} : { liveInput }),
243
- // Merged AFTER the spreads so the per-field run>host>default precedence
244
- // wins over either bag's whole-object `prompts`.
245
- ...(prompts === undefined ? {} : { prompts }),
246
- });
247
- await hub.flush();
248
- return result;
237
+ try {
238
+ return await bridge.execute(systemPrompt, {
239
+ ...hostDefaults,
240
+ ...options,
241
+ ...(subagents === undefined ? {} : { subagents }),
242
+ // `...options` alone doesn't carry the `options.model` narrowing above
243
+ // (spread reads the parameter's declared Partial type); re-assert
244
+ // the already-validated model so the request satisfies RuntimeRequest.
245
+ model: options.model,
246
+ executionMode,
247
+ runtimeBrand,
248
+ toolContext: runToolContext,
249
+ observerHub: hub,
250
+ onEvent: lifecycleGate.emit,
251
+ // The host gate is the sole persistence owner. Provider subscribe
252
+ // callbacks are synchronous and must never await the storage sink.
253
+ toolLifecycleSink: undefined,
254
+ ...(liveInput === undefined ? {} : { liveInput }),
255
+ // Merged AFTER the spreads so the per-field run>host>default precedence
256
+ // wins over either bag's whole-object `prompts`.
257
+ ...(prompts === undefined ? {} : { prompts }),
258
+ });
259
+ } finally {
260
+ await lifecycleGate.flush();
261
+ await hub.flush();
262
+ }
249
263
  },
250
264
  configureTools(next = {}) {
251
265
  updateToolContext(toolContext, pickPresent(next, TOOL_RUNTIME_KEYS));
@@ -4,16 +4,20 @@ export type SandboxCommandSpec = {
4
4
  command: string;
5
5
  args?: ReadonlyArray<string>;
6
6
  cwd?: string;
7
- env?: {
8
- [x: string]: string;
9
- };
7
+ env?: Record<string, string | undefined>;
10
8
  /**
11
9
  * Trusted per-command capability.
12
10
  */
13
11
  allowLocalBinding?: boolean;
14
12
  };
15
- export type PreparedSandboxCommand = SandboxCommandSpec & {
13
+ export type PreparedSandboxCommand = {
14
+ command: string;
15
+ args: ReadonlyArray<string>;
16
+ cwd: string;
17
+ env?: Record<string, string | undefined>;
18
+ allowLocalBinding?: boolean;
16
19
  sandboxed: boolean;
20
+ sandboxSettingsPath?: string;
17
21
  cleanup?: () => Promise<void>;
18
22
  };
19
23
  export type SandboxNetworkPolicyLike = {
@@ -88,11 +92,19 @@ export class SandboxUnavailableError extends Error {
88
92
  * @property {string} command
89
93
  * @property {ReadonlyArray<string>} [args]
90
94
  * @property {string} [cwd]
91
- * @property {Object<string, string|undefined>} [env]
95
+ * @property {Record<string, string|undefined>} [env]
92
96
  * @property {boolean} [allowLocalBinding] Trusted per-command capability.
93
97
  */
94
98
  /**
95
- * @typedef {SandboxCommandSpec & {sandboxed: boolean, cleanup?: () => Promise<void>}} PreparedSandboxCommand
99
+ * @typedef {Object} PreparedSandboxCommand
100
+ * @property {string} command
101
+ * @property {ReadonlyArray<string>} args
102
+ * @property {string} cwd
103
+ * @property {Record<string, string|undefined>} [env]
104
+ * @property {boolean} [allowLocalBinding]
105
+ * @property {boolean} sandboxed
106
+ * @property {string} [sandboxSettingsPath]
107
+ * @property {() => Promise<void>} [cleanup]
96
108
  */
97
109
  /**
98
110
  * @typedef {Object} SandboxNetworkPolicyLike
@@ -114,6 +126,7 @@ export class SandboxUnavailableError extends Error {
114
126
  * @property {SandboxNetworkPolicyLike} [network]
115
127
  * @property {ReadonlyArray<string>} [readableRoots]
116
128
  * @property {ReadonlyArray<string>} [writableRoots]
129
+ * @property {ReadonlyArray<string>} [protectedRoots] Host-internal roots denied for both reads and writes.
117
130
  * @property {ReadonlyArray<string>} [denyWrite]
118
131
  * @property {string} [root]
119
132
  */
@@ -10,8 +10,8 @@ export function normalizeProcessTimeoutMs(value: any, fallback?: number): any;
10
10
  /**
11
11
  * Compatibility wrapper retained for direct callers and tests.
12
12
  *
13
- * @param {{command: string, timeout?: number, timeout_ms?: number, max_output_chars?: number, workdir?: string}} params
14
- * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any}} [options]
13
+ * @param {{command: string, timeout?: number, timeout_ms?: number, max_output_chars?: number, workdir?: string, background?: boolean}} params
14
+ * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, processJobsController?: import("./shared/process-jobs.js").ProcessJobsController}} [options]
15
15
  */
16
16
  export function bashToolImpl(params: {
17
17
  command: string;
@@ -19,46 +19,31 @@ export function bashToolImpl(params: {
19
19
  timeout_ms?: number;
20
20
  max_output_chars?: number;
21
21
  workdir?: string;
22
+ background?: boolean;
22
23
  }, options?: {
23
24
  signal?: AbortSignal;
24
25
  sandboxPolicy?: any;
25
26
  sandboxEngine?: any;
26
27
  ctx?: any;
28
+ processJobsController?: import("./shared/process-jobs.js").ProcessJobsController;
27
29
  }): Promise<any>;
28
30
  /**
29
31
  * Structured Bash execution used by the Pi bridge.
30
32
  *
31
- * @param {{command: string, timeout?: number, timeout_ms?: number, max_output_chars?: number, workdir?: string}} params
32
- * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any}} [options]
33
+ * @param {{command: string, timeout?: number, timeout_ms?: number, max_output_chars?: number, workdir?: string, background?: boolean}} params
34
+ * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, processJobsController?: import("./shared/process-jobs.js").ProcessJobsController}} [options]
33
35
  */
34
- export function bashToolRun({ command, timeout, timeout_ms, max_output_chars, workdir, }: {
36
+ export function bashToolRun({ command, timeout, timeout_ms, max_output_chars, workdir, background, }: {
35
37
  command: string;
36
38
  timeout?: number;
37
39
  timeout_ms?: number;
38
40
  max_output_chars?: number;
39
41
  workdir?: string;
40
- }, { signal, sandboxPolicy, sandboxEngine, ctx, }?: {
42
+ background?: boolean;
43
+ }, { signal, sandboxPolicy, sandboxEngine, ctx, processJobsController, }?: {
41
44
  signal?: AbortSignal;
42
45
  sandboxPolicy?: any;
43
46
  sandboxEngine?: any;
44
47
  ctx?: any;
45
- }): Promise<{
46
- text: any;
47
- outcome: {
48
- status: string;
49
- code: any;
50
- retryable: boolean;
51
- attempts: number;
52
- durationMs: number;
53
- bytes: number;
54
- truncated: boolean;
55
- exitCode: any;
56
- signal: any;
57
- timedOut: boolean;
58
- };
59
- error: boolean;
60
- } | {
61
- text: string;
62
- outcome: any;
63
- error: boolean;
64
- }>;
48
+ processJobsController?: import("./shared/process-jobs.js").ProcessJobsController;
49
+ }): Promise<any>;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @param {{file_path: string, old_string: string, new_string: string, replace_all?: boolean, workdir?: string}} params
3
- * @param {{sandboxPolicy?: any, ctx?: any}} [options]
3
+ * @param {{sandboxPolicy?: any, sandboxEngine?: any, ctx?: any}} [options]
4
4
  */
5
5
  export function editToolImpl({ file_path, old_string, new_string, replace_all, workdir }: {
6
6
  file_path: string;
@@ -8,7 +8,8 @@ export function editToolImpl({ file_path, old_string, new_string, replace_all, w
8
8
  new_string: string;
9
9
  replace_all?: boolean;
10
10
  workdir?: string;
11
- }, { sandboxPolicy, ctx }?: {
11
+ }, { sandboxPolicy, sandboxEngine, ctx }?: {
12
12
  sandboxPolicy?: any;
13
+ sandboxEngine?: any;
13
14
  ctx?: any;
14
15
  }): Promise<string>;
@@ -1,6 +1,7 @@
1
+ /** @typedef {import("./shared/process-jobs.js").ProcessJobsController} ProcessJobsController */
1
2
  /**
2
- * @param {{executable: string, args?: string[], workdir?: string, timeout_ms?: number, max_output_chars?: number}} params
3
- * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any}} [options]
3
+ * @param {{executable: string, args?: string[], workdir?: string, timeout_ms?: number, max_output_chars?: number, background?: boolean}} params
4
+ * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, processJobsController?: ProcessJobsController}} [options]
4
5
  */
5
6
  export function execToolImpl(params: {
6
7
  executable: string;
@@ -8,46 +9,32 @@ export function execToolImpl(params: {
8
9
  workdir?: string;
9
10
  timeout_ms?: number;
10
11
  max_output_chars?: number;
12
+ background?: boolean;
11
13
  }, options?: {
12
14
  signal?: AbortSignal;
13
15
  sandboxPolicy?: any;
14
16
  sandboxEngine?: any;
15
17
  ctx?: any;
18
+ processJobsController?: ProcessJobsController;
16
19
  }): Promise<any>;
17
20
  /**
18
21
  * Execute an argv vector directly, without shell parsing.
19
22
  *
20
- * @param {{executable: string, args?: string[], workdir?: string, timeout_ms?: number, max_output_chars?: number}} params
21
- * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any}} [options]
23
+ * @param {{executable: string, args?: string[], workdir?: string, timeout_ms?: number, max_output_chars?: number, background?: boolean}} params
24
+ * @param {{signal?: AbortSignal, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, processJobsController?: ProcessJobsController}} [options]
22
25
  */
23
- export function execToolRun({ executable, args, workdir, timeout_ms, max_output_chars, }: {
26
+ export function execToolRun({ executable, args, workdir, timeout_ms, max_output_chars, background, }: {
24
27
  executable: string;
25
28
  args?: string[];
26
29
  workdir?: string;
27
30
  timeout_ms?: number;
28
31
  max_output_chars?: number;
29
- }, { signal, sandboxPolicy, sandboxEngine, ctx, }?: {
32
+ background?: boolean;
33
+ }, { signal, sandboxPolicy, sandboxEngine, ctx, processJobsController, }?: {
30
34
  signal?: AbortSignal;
31
35
  sandboxPolicy?: any;
32
36
  sandboxEngine?: any;
33
37
  ctx?: any;
34
- }): Promise<{
35
- text: any;
36
- outcome: {
37
- status: string;
38
- code: any;
39
- retryable: boolean;
40
- attempts: number;
41
- durationMs: number;
42
- bytes: number;
43
- truncated: boolean;
44
- exitCode: any;
45
- signal: any;
46
- timedOut: boolean;
47
- };
48
- error: boolean;
49
- } | {
50
- text: string;
51
- outcome: any;
52
- error: any;
53
- }>;
38
+ processJobsController?: ProcessJobsController;
39
+ }): Promise<any>;
40
+ export type ProcessJobsController = import("./shared/process-jobs.js").ProcessJobsController;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @param {{pattern: string, path?: string, limit?: number, offset?: number, max_matches?: number, max_output_chars?: number, workdir?: string}} params
3
- * @param {{sandboxPolicy?: any, ctx?: any}} [options]
3
+ * @param {{sandboxPolicy?: any, sandboxEngine?: any, ctx?: any}} [options]
4
4
  */
5
5
  export function globToolImpl({ pattern, path, limit, offset, max_matches, max_output_chars, workdir }: {
6
6
  pattern: string;
@@ -10,7 +10,8 @@ export function globToolImpl({ pattern, path, limit, offset, max_matches, max_ou
10
10
  max_matches?: number;
11
11
  max_output_chars?: number;
12
12
  workdir?: string;
13
- }, { sandboxPolicy, ctx }?: {
13
+ }, { sandboxPolicy, sandboxEngine, ctx }?: {
14
14
  sandboxPolicy?: any;
15
+ sandboxEngine?: any;
15
16
  ctx?: any;
16
17
  }): Promise<string>;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @param {{pattern: string, path?: string, glob?: string, type?: string, output_mode?: string, context?: number, case_insensitive?: boolean, multiline?: boolean, head_limit?: number, offset?: number, max_matches?: number, max_output_chars?: number, workdir?: string}} params
3
- * @param {{sandboxPolicy?: any, ctx?: any}} [options]
3
+ * @param {{sandboxPolicy?: any, sandboxEngine?: any, ctx?: any}} [options]
4
4
  */
5
5
  export function grepToolImpl({ pattern, path, glob, type, output_mode, context, case_insensitive, multiline, head_limit, offset, max_matches, max_output_chars, workdir, }: {
6
6
  pattern: string;
@@ -16,7 +16,8 @@ export function grepToolImpl({ pattern, path, glob, type, output_mode, context,
16
16
  max_matches?: number;
17
17
  max_output_chars?: number;
18
18
  workdir?: string;
19
- }, { sandboxPolicy, ctx }?: {
19
+ }, { sandboxPolicy, sandboxEngine, ctx }?: {
20
20
  sandboxPolicy?: any;
21
+ sandboxEngine?: any;
21
22
  ctx?: any;
22
23
  }): Promise<string>;
@@ -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, 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, 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, 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, subagents, subagentContext, toolExecutionMode, ctx, }?: {
41
41
  disallowedTools?: any[];
42
42
  skillNames?: any[];
43
43
  skills?: any[];
@@ -57,6 +57,7 @@ export function getPiBuiltinTools(allowedTools: any, { disallowedTools, skillNam
57
57
  approvalModel?: any;
58
58
  nodeReplController?: any;
59
59
  webController?: any;
60
+ processJobsController?: any;
60
61
  toolExecutionMode?: "sequential" | "safe-parallel";
61
62
  subagents?: any;
62
63
  subagentContext?: any;
@@ -80,9 +81,9 @@ export function coerceMcpContent(out: any, { textLimit, imageInlineMaxBytes, per
80
81
  /**
81
82
  * @param {any} mcpConfig
82
83
  * @param {Set<any>} [reservedNames]
83
- * @param {{limits?: any, cwd?: any, persistArtifact?: any, qaOutputDir?: any, onTruncate?: any, toolPayloadMaxBytes?: number, sandboxPolicy?: any, sandboxEngine?: any, onToolProgress?: any, ctx?: any}} [options]
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]
84
85
  */
85
- export function initPiMcpTools(mcpConfig: any, reservedNames?: Set<any>, { limits, cwd, persistArtifact, qaOutputDir, onTruncate, toolPayloadMaxBytes, sandboxPolicy, sandboxEngine, onToolProgress, ctx, }?: {
86
+ export function initPiMcpTools(mcpConfig: any, reservedNames?: Set<any>, { limits, cwd, persistArtifact, qaOutputDir, onTruncate, toolPayloadMaxBytes, sandboxPolicy, sandboxEngine, onToolProgress, ctx, mcpApps, runId, }?: {
86
87
  limits?: any;
87
88
  cwd?: any;
88
89
  persistArtifact?: any;
@@ -93,6 +94,8 @@ export function initPiMcpTools(mcpConfig: any, reservedNames?: Set<any>, { limit
93
94
  sandboxEngine?: any;
94
95
  onToolProgress?: any;
95
96
  ctx?: any;
97
+ mcpApps?: any;
98
+ runId?: string;
96
99
  }): Promise<{
97
100
  clients: {
98
101
  name: any;
@@ -131,6 +134,10 @@ export function initPiMcpTools(mcpConfig: any, reservedNames?: Set<any>, { limit
131
134
  };
132
135
  }>;
133
136
  transport: StreamableHTTPClientTransport | SSEClientTransport | StdioClientTransport;
137
+ connectionId: `${string}-${string}-${string}-${string}-${string}`;
138
+ retainedByMcpApps: boolean;
139
+ privateCapabilityUrl: boolean;
140
+ closed: boolean;
134
141
  }[];
135
142
  tools: any[];
136
143
  warnings: {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @param {{file_path: string, offset?: number, start_line?: number, limit?: number, max_output_chars?: number, workdir?: string}} params
3
- * @param {{sandboxPolicy?: any, ctx?: any}} [options]
3
+ * @param {{sandboxPolicy?: any, sandboxEngine?: any, ctx?: any}} [options]
4
4
  */
5
5
  export function readToolImpl({ file_path, offset, start_line, limit, max_output_chars, workdir }: {
6
6
  file_path: string;
@@ -9,8 +9,9 @@ export function readToolImpl({ file_path, offset, start_line, limit, max_output_
9
9
  limit?: number;
10
10
  max_output_chars?: number;
11
11
  workdir?: string;
12
- }, { sandboxPolicy, ctx }?: {
12
+ }, { sandboxPolicy, sandboxEngine, ctx }?: {
13
13
  sandboxPolicy?: any;
14
+ sandboxEngine?: any;
14
15
  ctx?: any;
15
16
  }): Promise<string | {
16
17
  kind: string;
@@ -2,5 +2,13 @@ export function workspaceRoot(workdir: any, ctx: any): string;
2
2
  export function resolveToolPath(path: any, workdir: any, ctx: any): any;
3
3
  export function isPathAllowed(path: any, workdir: any, options?: {}): boolean;
4
4
  export function isWritablePathAllowed(path: any, workdir: any, options?: {}): boolean;
5
+ export function isPathLexicallyAllowed(path: any, workdir: any, options?: {}): boolean;
6
+ export function isWritablePathLexicallyAllowed(path: any, workdir: any, options?: {}): boolean;
5
7
  export function isWorkdirAllowed(workdir: any, options?: {}): boolean;
8
+ /**
9
+ * Protected descendants of one search root, as normalized relative paths.
10
+ * Search tools use these both as ripgrep exclusions and as a defensive output
11
+ * filter; actual reads still cross the native sandbox boundary.
12
+ */
13
+ export function protectedRelativePaths(directory: any, options?: {}): any[];
6
14
  export function isInsidePath(root: any, target: any): boolean;
@@ -0,0 +1,64 @@
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} ProcessJobsController
6
+ * @property {(request: {
7
+ * tool: "Exec"|"Bash",
8
+ * prepared: import("../../sandbox-seam.js").PreparedSandboxCommand,
9
+ * summary: string,
10
+ * timeoutMs?: number,
11
+ * maxOutputChars?: number,
12
+ * launch: (options?: {timeoutMs?: number, signal?: AbortSignal, maxBufferBytes?: number, onStdout?: (chunk: Buffer) => void, onStderr?: (chunk: Buffer) => void}) => ReturnType<typeof startPreparedProcess>,
13
+ * }) => Promise<{jobId: string, state: "queued"|"starting"|"running", startedAt: string|null}>} start
14
+ */
15
+ /**
16
+ * Transfer one prepared command to the injected host controller. From the
17
+ * instant `start()` is invoked, the controller owns cleanup on every path.
18
+ *
19
+ * @param {{
20
+ * controller: ProcessJobsController,
21
+ * tool: "Exec"|"Bash",
22
+ * prepared: import("../../sandbox-seam.js").PreparedSandboxCommand,
23
+ * summary: string,
24
+ * timeoutMs?: number,
25
+ * maxOutputChars?: number,
26
+ * startedAt: number,
27
+ * failed: (text: string, code: string, startedAt: number) => any,
28
+ * }} input
29
+ */
30
+ export function handOffProcessJob({ controller, tool, prepared, summary, timeoutMs, maxOutputChars, startedAt, failed, }: {
31
+ controller: ProcessJobsController;
32
+ tool: "Exec" | "Bash";
33
+ prepared: import("../../sandbox-seam.js").PreparedSandboxCommand;
34
+ summary: string;
35
+ timeoutMs?: number;
36
+ maxOutputChars?: number;
37
+ startedAt: number;
38
+ failed: (text: string, code: string, startedAt: number) => any;
39
+ }): Promise<any>;
40
+ /**
41
+ * Kernel-local structural controller seam. The typed public interface lives in
42
+ * runtime-adapter; this package deliberately has no workspace dependencies.
43
+ */
44
+ export type ProcessJobsController = {
45
+ start: (request: {
46
+ tool: "Exec" | "Bash";
47
+ prepared: import("../../sandbox-seam.js").PreparedSandboxCommand;
48
+ summary: string;
49
+ timeoutMs?: number;
50
+ maxOutputChars?: number;
51
+ launch: (options?: {
52
+ timeoutMs?: number;
53
+ signal?: AbortSignal;
54
+ maxBufferBytes?: number;
55
+ onStdout?: (chunk: Buffer) => void;
56
+ onStderr?: (chunk: Buffer) => void;
57
+ }) => ReturnType<typeof startPreparedProcess>;
58
+ }) => Promise<{
59
+ jobId: string;
60
+ state: "queued" | "starting" | "running";
61
+ startedAt: string | null;
62
+ }>;
63
+ };
64
+ import { startPreparedProcess } from "./process-runner.js";
@@ -6,23 +6,65 @@
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}} [options]
9
+ * @param {{timeoutMs?: number, signal?: AbortSignal, maxBufferBytes?: number, input?: string|Buffer}} [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, }?: {
16
+ }, { timeoutMs, signal, maxBufferBytes, input, }?: {
17
17
  timeoutMs?: number;
18
18
  signal?: AbortSignal;
19
19
  maxBufferBytes?: number;
20
+ input?: string | Buffer;
20
21
  }): Promise<any>;
22
+ /**
23
+ * Start one already-prepared executable and expose its process-group handle.
24
+ *
25
+ * `waitForProcessGroup` is deliberately opt-in so existing foreground tools
26
+ * retain their exact leader/stdio completion semantics. Process jobs enable it
27
+ * through their bound launcher: sandbox cleanup must not run while a detached
28
+ * descendant in the owned group is still alive.
29
+ *
30
+ * @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
+ * For process jobs, `release()` is the persistence fence: the target cannot
33
+ * spawn until the host has durably recorded the returned ownership metadata.
34
+ * Foreground handles expose a harmless no-op release for one structural shape.
35
+ *
36
+ * @returns {{pid: number|null, pgid: number|null, startedAt: string, completion: Promise<any>, release: () => Promise<void>, cancel: () => void}}
37
+ */
38
+ export function startPreparedProcess(commandSpec: {
39
+ command: string;
40
+ args?: string[];
41
+ cwd?: string;
42
+ env?: Record<string, string | undefined>;
43
+ }, { timeoutMs, signal, maxBufferBytes, input, waitForProcessGroup, exactEnvironment, onStdout, onStderr, }?: {
44
+ timeoutMs?: number;
45
+ signal?: AbortSignal;
46
+ maxBufferBytes?: number;
47
+ input?: string | Buffer;
48
+ waitForProcessGroup?: boolean;
49
+ exactEnvironment?: boolean;
50
+ onStdout?: (chunk: Buffer) => void;
51
+ onStderr?: (chunk: Buffer) => void;
52
+ }): {
53
+ pid: number | null;
54
+ pgid: number | null;
55
+ startedAt: string;
56
+ completion: Promise<any>;
57
+ release: () => Promise<void>;
58
+ cancel: () => void;
59
+ };
21
60
  /**
22
61
  * @param {import("node:child_process").ChildProcess} child
23
62
  * @param {NodeJS.Signals} signal
63
+ * @param {{fallbackToChildPid?: boolean}} [options]
24
64
  */
25
- export function killProcessGroup(child: import("node:child_process").ChildProcess, signal: NodeJS.Signals): void;
65
+ export function killProcessGroup(child: import("node:child_process").ChildProcess, signal: NodeJS.Signals, { fallbackToChildPid }?: {
66
+ fallbackToChildPid?: boolean;
67
+ }): void;
26
68
  /**
27
69
  * @param {{stdout?: string, stderr?: string}} result
28
70
  */
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @param {{command: string, args?: string[], cwd?: string, env?: Record<string, string|undefined>}} command
3
+ * @param {{sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, input?: string|Buffer, maxBufferBytes?: number}} [options]
4
+ * @returns {Promise<any|null>}
5
+ */
6
+ export function runProtectedFilesystemCommand(command: {
7
+ command: string;
8
+ args?: string[];
9
+ cwd?: string;
10
+ env?: Record<string, string | undefined>;
11
+ }, { sandboxPolicy, sandboxEngine, ctx, input, maxBufferBytes, }?: {
12
+ sandboxPolicy?: any;
13
+ sandboxEngine?: any;
14
+ ctx?: any;
15
+ input?: string | Buffer;
16
+ maxBufferBytes?: number;
17
+ }): Promise<any | null>;
18
+ /**
19
+ * Build a metadata-free operation plan rooted at a configured policy path.
20
+ * Search tools keep the model-controlled target as an argument; file helpers
21
+ * use the stable cwd with their absolute target. In both cases the host avoids
22
+ * target metadata and target-derived cwd resolution before SRT enforces policy.
23
+ *
24
+ * @param {string} target
25
+ * @param {{sandboxPolicy?: any, ctx?: any}} [options]
26
+ * @returns {{cwd: string, searchTarget: string}|null}
27
+ */
28
+ export function protectedFilesystemTargetPlan(target: string, { sandboxPolicy, ctx }?: {
29
+ sandboxPolicy?: any;
30
+ ctx?: any;
31
+ }): {
32
+ cwd: string;
33
+ searchTarget: string;
34
+ } | null;
35
+ /** @param {string} searchTarget */
36
+ export function protectedDirectorySearchTarget(searchTarget: string): string;
37
+ /**
38
+ * Scope a target-relative user glob to ripgrep's stable host cwd.
39
+ * @param {string} pattern
40
+ * @param {string} searchTarget
41
+ */
42
+ export function scopeProtectedSearchGlob(pattern: string, searchTarget: string): string;
43
+ /**
44
+ * Restore the historical target-relative search output after ripgrep runs from
45
+ * the stable policy root.
46
+ * @param {string} line
47
+ * @param {string} searchTarget
48
+ */
49
+ export function normalizeProtectedSearchLine(line: string, searchTarget: string): string;
50
+ /** @param {any} result */
51
+ export function protectedCommandSucceeded(result: any): boolean;
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * @param {{file_path: string, content?: string, workdir?: string}} params
3
- * @param {{sandboxPolicy?: any, ctx?: any}} [options]
3
+ * @param {{sandboxPolicy?: any, sandboxEngine?: any, ctx?: any}} [options]
4
4
  */
5
5
  export function writeToolImpl({ file_path, content, workdir }: {
6
6
  file_path: string;
7
7
  content?: string;
8
8
  workdir?: string;
9
- }, { sandboxPolicy, ctx }?: {
9
+ }, { sandboxPolicy, sandboxEngine, ctx }?: {
10
10
  sandboxPolicy?: any;
11
+ sandboxEngine?: any;
11
12
  ctx?: any;
12
13
  }): Promise<string>;
@@ -7,6 +7,7 @@
7
7
  * @property {Set<unknown>} textDeltaIndexes
8
8
  * @property {Set<unknown>} thinkingDeltaIndexes
9
9
  * @property {Map<string, number>} toolStartTimes
10
+ * @property {Map<string, any>} toolApprovals
10
11
  * @property {number} turnCount
11
12
  * @property {number} toolResultsSeen
12
13
  * @property {string|null} lastToolName
@@ -38,6 +39,7 @@ export type StreamSubscriberState = {
38
39
  textDeltaIndexes: Set<unknown>;
39
40
  thinkingDeltaIndexes: Set<unknown>;
40
41
  toolStartTimes: Map<string, number>;
42
+ toolApprovals: Map<string, any>;
41
43
  turnCount: number;
42
44
  toolResultsSeen: number;
43
45
  lastToolName: string | null;
@@ -5,6 +5,7 @@ export namespace COMMON_CAPABILITIES {
5
5
  export let supports_session_resume: boolean;
6
6
  export let native_runtime_config: any;
7
7
  export let supports_mcp: boolean;
8
+ export let supports_mcp_apps: boolean;
8
9
  export let supports_skills: boolean;
9
10
  export let supports_builtin_tools: boolean;
10
11
  export let supports_live_input: boolean;
@@ -26,6 +27,8 @@ export namespace RUNTIME_CAPABILITIES {
26
27
  export { supports_native_subagents_1 as supports_native_subagents };
27
28
  let supports_request_tool_environment_1: boolean;
28
29
  export { supports_request_tool_environment_1 as supports_request_tool_environment };
30
+ let supports_mcp_apps_1: boolean;
31
+ export { supports_mcp_apps_1 as supports_mcp_apps };
29
32
  let runtime_1: string;
30
33
  export { runtime_1 as runtime };
31
34
  }
@@ -26,6 +26,7 @@ export function normalizeCodexItemEvent(raw: any, context?: {}): {
26
26
  tool_use_id: any;
27
27
  content: any;
28
28
  is_error: boolean;
29
+ tool_lifecycle: any;
29
30
  }[];
30
31
  };
31
32
  } | {