@mono-agent/agent-runtime 0.15.3 → 0.16.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.
- package/MIGRATION.md +41 -13
- package/README.md +43 -6
- package/package.json +7 -3
- package/src/agent/tools/agent-tool.js +894 -0
- package/src/agent/tools/bash.js +241 -123
- package/src/agent/tools/exec.js +238 -0
- package/src/agent/tools/index.js +10 -3
- package/src/agent/tools/node-repl.js +231 -95
- package/src/agent/tools/pi-bridge.js +115 -24
- package/src/agent/tools/shared/process-runner.js +162 -0
- package/src/agent/tools/shared/semaphore.js +73 -0
- package/src/agent/tools/web-browser-render.js +221 -0
- package/src/agent/tools/web-controller.js +160 -0
- package/src/agent/tools/web-fetch.js +653 -68
- package/src/agent/tools/web-search.js +568 -16
- package/src/ai/pi-interop.js +7 -5
- package/src/ai/pi-oauth-compat.js +193 -0
- package/src/ai/providers/pi-native/stream-subscriber.js +37 -0
- package/src/ai/providers/pi-native/turn-runner.js +73 -8
- package/src/ai/providers/pi-native.js +67 -7
- package/src/ai/runtime/router.js +310 -166
- package/src/ai/types.js +54 -2
- package/src/pi-auth.js +2 -2
- package/src/runtime.js +58 -1
- package/types/agent/tools/agent-tool.d.ts +80 -0
- package/types/agent/tools/bash.d.ts +55 -7
- package/types/agent/tools/exec.d.ts +53 -0
- package/types/agent/tools/index.d.ts +5 -3
- package/types/agent/tools/node-repl.d.ts +28 -3
- package/types/agent/tools/pi-bridge.d.ts +6 -2
- package/types/agent/tools/shared/process-runner.d.ts +33 -0
- package/types/agent/tools/shared/semaphore.d.ts +29 -0
- package/types/agent/tools/web-browser-render.d.ts +16 -0
- package/types/agent/tools/web-controller.d.ts +20 -0
- package/types/agent/tools/web-fetch.d.ts +74 -5
- package/types/agent/tools/web-search.d.ts +81 -5
- package/types/ai/pi-oauth-compat.d.ts +57 -0
- package/types/ai/providers/pi-native/turn-runner.d.ts +33 -2
- package/types/ai/providers/pi-native.d.ts +12 -0
- package/types/ai/runtime/router.d.ts +23 -3
- package/types/ai/types.d.ts +174 -4
- package/types/ai/backend.d.ts +0 -57
- package/types/ai/registry.d.ts +0 -1
package/src/ai/types.js
CHANGED
|
@@ -147,7 +147,8 @@
|
|
|
147
147
|
* @property {boolean} [fastMode]
|
|
148
148
|
* @property {string} [cwd]
|
|
149
149
|
* @property {Object<string, Object>} [mcpServers]
|
|
150
|
-
* @property {ReadonlyArray<
|
|
150
|
+
* @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.
|
|
151
|
+
* @property {string} [skillsRoot] Directory holding `<name>/SKILL.md`. Required alongside `skills` for `ReadSkill` to be built.
|
|
151
152
|
* @property {ReadonlyArray<string>} [allowedTools]
|
|
152
153
|
* @property {ReadonlyArray<string>} [disallowedTools]
|
|
153
154
|
* @property {string} [permissionMode]
|
|
@@ -161,8 +162,13 @@
|
|
|
161
162
|
* @property {RuntimeToolLimits} [toolLimits] Typed per-run tool-output limits (supported replacement for the deprecated `settings` tool keys).
|
|
162
163
|
* @property {RuntimeCompactionPolicy} [compaction] Typed per-run compaction policy (supported replacement for the deprecated `settings` compaction keys).
|
|
163
164
|
* @property {RuntimePromptOverrides} [prompts] Per-run prompt-fragment overrides (run wins over the host default).
|
|
165
|
+
* @property {{backend?: "auto"|"searxng"|"keyless", endpoint?: string}} [webSearchConfig] Run-scoped WebSearch backend configuration.
|
|
166
|
+
* @property {{render?: "never"|"auto", browserCommand?: string}} [webFetchConfig] Run-scoped WebFetch extraction/render configuration.
|
|
167
|
+
* @property {"sequential"|"safe-parallel"} [piToolExecutionMode] Pi built-in tool scheduling mode. Safe parallelism is the default.
|
|
168
|
+
* @property {"one-at-a-time"|"all"} [piToolParallelismMode] DEPRECATED. Compatibility alias mapped to piToolExecutionMode.
|
|
164
169
|
* @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).
|
|
165
170
|
* @property {Object} [nativeSubagents] Same-runtime teammate helpers exposed through native provider subagent surfaces.
|
|
171
|
+
* @property {RuntimeSubagentsOptions} [subagents] In-process `Agent` built-in: profiles, caps, and the nested-run callback.
|
|
166
172
|
* @property {Object} [diagnosticsSeed] Set by createRouterRuntime (ai/runtime/router.js) with a `resume_snapshot` when
|
|
167
173
|
* failing over mid-chain; a host-level coordinator may relay it forward (see agent/transcript.js), not read by any
|
|
168
174
|
* bridge in this package today.
|
|
@@ -185,6 +191,52 @@
|
|
|
185
191
|
* hub's emit). `systemPrompt` is passed positionally, not folded into this object.
|
|
186
192
|
*/
|
|
187
193
|
|
|
194
|
+
/**
|
|
195
|
+
* @typedef {Object} RuntimeSubagentDefinition
|
|
196
|
+
* One named subagent profile the `Agent` built-in can deploy.
|
|
197
|
+
* @property {string} name Model-visible identifier and the tool's `name` enum value.
|
|
198
|
+
* @property {string} description Model-visible: when to pick this profile.
|
|
199
|
+
* @property {string} systemPrompt Full system prompt for the child run.
|
|
200
|
+
* @property {RuntimeModelRef} [model] Absent inherits the parent's configured route.
|
|
201
|
+
* @property {string} [effort]
|
|
202
|
+
* @property {ReadonlyArray<string>} [allowedTools] Absent uses the safe read-only default set.
|
|
203
|
+
* @property {ReadonlyArray<string>} [disallowedTools]
|
|
204
|
+
* @property {Object<string, Object>} [mcpServers]
|
|
205
|
+
* @property {number} [maxTurns]
|
|
206
|
+
* @property {number} [timeoutMs]
|
|
207
|
+
*/
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @callback RuntimeSubagentRun
|
|
211
|
+
* Owning-layer callback that actually executes one child turn. The kernel
|
|
212
|
+
* supplies a self-run fallback so `createRuntime` works without host wiring;
|
|
213
|
+
* agent-app replaces it so subagent runs get the configured fallback chain,
|
|
214
|
+
* same-model retries, and run recording.
|
|
215
|
+
* @param {Object} request
|
|
216
|
+
* @returns {Promise<RuntimeResult>}
|
|
217
|
+
*/
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* @typedef {Object} RuntimeInlineSubagentsOptions
|
|
221
|
+
* Policy for subagents the model authors at call time rather than picking from
|
|
222
|
+
* `definitions`. Absent suppresses authoring entirely.
|
|
223
|
+
* @property {boolean} [enabled] Only `false` turns authoring off.
|
|
224
|
+
* @property {ReadonlyArray<string>} [allowedTools] Ceiling on what an authored subagent may
|
|
225
|
+
* request. Absent means the safe read-only default set, never every built-in.
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* @typedef {Object} RuntimeSubagentsOptions
|
|
230
|
+
* @property {ReadonlyArray<RuntimeSubagentDefinition>} [definitions] Named profiles.
|
|
231
|
+
* @property {RuntimeInlineSubagentsOptions} [inline] Call-time authoring policy.
|
|
232
|
+
* @property {number} [maxConcurrent] In-flight subagents per parent turn. Default 5.
|
|
233
|
+
* @property {number} [maxPerTurn] Total Agent calls per parent turn. Default 20.
|
|
234
|
+
* @property {number} [maxTurns] Default per-subagent turn cap. Default 100.
|
|
235
|
+
* @property {number} [timeoutMs] Default per-subagent wall clock.
|
|
236
|
+
* @property {RuntimeSubagentRun} [run] Nested-run callback; absent uses the kernel self-run.
|
|
237
|
+
* @property {number} [depth] Kernel-owned. Absent/0 is the parent; >=1 suppresses the `Agent` tool.
|
|
238
|
+
*/
|
|
239
|
+
|
|
188
240
|
/**
|
|
189
241
|
* @typedef {Object} RuntimeResult
|
|
190
242
|
* @property {string|null} [text]
|
|
@@ -206,7 +258,7 @@
|
|
|
206
258
|
* @property {Array<Object>} [runtimeWarnings]
|
|
207
259
|
* @property {Object} [diagnostics]
|
|
208
260
|
* @property {Object} [capabilitiesUsed]
|
|
209
|
-
* @property {Array<{model: RuntimeModelRef, failureKind: (string|null), requestId?: (string|null), retryableSubkind?: (string|null), requirements?: Object, routeSafety?: RuntimeRouteSafetyMode, safetyContract?: RuntimeRouteSafetyContract}>} [failoverHistory] Set by createRouterRuntime (ai/runtime/router.js) on every failed/skipped attempt.
|
|
261
|
+
* @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.
|
|
210
262
|
* @property {Array<{attemptIndex: number, model: RuntimeModelRef, routeSafety: RuntimeRouteSafetyMode, safetyContract: RuntimeRouteSafetyContract, status: string}>} [routeSafetyHistory] Bounded route-safety audit emitted by createRouterRuntime.
|
|
211
263
|
*/
|
|
212
264
|
|
package/src/pi-auth.js
CHANGED
|
@@ -4,7 +4,7 @@ import { realpathSync } from "node:fs";
|
|
|
4
4
|
import { chmod, mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
5
5
|
import { basename, dirname, join, resolve } from "node:path";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { resolveOAuthApiKey } from "./ai/pi-oauth-compat.js";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @typedef {{type: "api_key", key?: string, env?: Object<string, *>}} PiApiKeyCredential
|
|
@@ -41,7 +41,7 @@ export function createPiOAuthApiKeyResolver(options = {}) {
|
|
|
41
41
|
return undefined;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const result = await
|
|
44
|
+
const result = await resolveOAuthApiKey(provider, cloneAuth(auth));
|
|
45
45
|
if (result === null || result === undefined || typeof result.apiKey !== "string" || result.apiKey.length === 0) {
|
|
46
46
|
return undefined;
|
|
47
47
|
}
|
package/src/runtime.js
CHANGED
|
@@ -140,7 +140,55 @@ export function createRuntime(host = {}) {
|
|
|
140
140
|
// THIS object so later runs of this instance observe the update.
|
|
141
141
|
const toolContext = createToolContext({ ...toolRuntime, runtimeBrand });
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
/** @type {*} */
|
|
144
|
+
let self;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Kernel fallback for `subagents.run`, so the `Agent` built-in works from a
|
|
148
|
+
* bare `createRuntime` with no host wiring. Hosts replace it to route child
|
|
149
|
+
* turns through their own runtime (fallback chain, retries, recording).
|
|
150
|
+
*
|
|
151
|
+
* Scope of the guarantee, precisely: this fallback rebuilds the child bag with
|
|
152
|
+
* stripped session/steering state, but a HOST-SUPPLIED `run` is installed
|
|
153
|
+
* verbatim and is a privileged seam — it is responsible for its own session
|
|
154
|
+
* isolation. Recursion is blocked independently of the callback: the `Agent`
|
|
155
|
+
* tool stamps `depth + 1` into every descriptor it hands out, and
|
|
156
|
+
* `getPiBuiltinTools` refuses to register the tool at depth >= 1, so a custom
|
|
157
|
+
* callback cannot produce a grandchild even if it ignores the rest.
|
|
158
|
+
* @param {*} request
|
|
159
|
+
*/
|
|
160
|
+
const defaultSubagentRun = async (request) => self.run(request.systemPrompt, {
|
|
161
|
+
model: request.model,
|
|
162
|
+
// A child must never be less confined than its parent. The policy is a
|
|
163
|
+
// per-run option, not a host key, so without forwarding it the child would
|
|
164
|
+
// run with no sandbox at all — and its default tools include WebFetch and
|
|
165
|
+
// WebSearch, so even a read-only profile could bypass network policy.
|
|
166
|
+
...(request.sandboxPolicy === undefined ? {} : { sandboxPolicy: request.sandboxPolicy }),
|
|
167
|
+
...(request.sandboxEngine === undefined ? {} : { sandboxEngine: request.sandboxEngine }),
|
|
168
|
+
// The parent's disclosed skills, for the same reason: they are a per-run
|
|
169
|
+
// option, so a child that does not receive them has no ReadSkill tool and no
|
|
170
|
+
// index, and must rediscover by trial and error what its parent could look
|
|
171
|
+
// up. A host-supplied `run` may gate this; the default has no route or deny
|
|
172
|
+
// list of its own to consult, so it forwards what it was given.
|
|
173
|
+
...(request.skills === undefined ? {} : { skills: request.skills }),
|
|
174
|
+
...(request.skillsRoot === undefined ? {} : { skillsRoot: request.skillsRoot }),
|
|
175
|
+
...(request.executionMode === undefined ? {} : { executionMode: request.executionMode }),
|
|
176
|
+
...(request.cwd === undefined ? {} : { cwd: request.cwd }),
|
|
177
|
+
// A profile that pins effort — declared or authored at call time — means it
|
|
178
|
+
// on this path too; dropping it would silently run the child at the
|
|
179
|
+
// parent's level while reporting the profile's.
|
|
180
|
+
...(request.definition?.effort === undefined ? {} : { effort: request.definition.effort }),
|
|
181
|
+
messages: [{ role: "user", content: request.prompt }],
|
|
182
|
+
maxTurns: request.maxTurns,
|
|
183
|
+
allowedTools: request.definition?.allowedTools,
|
|
184
|
+
disallowedTools: request.definition?.disallowedTools,
|
|
185
|
+
mcpServers: request.definition?.mcpServers ?? {},
|
|
186
|
+
abortSignal: request.abortSignal,
|
|
187
|
+
onEvent: request.onEvent,
|
|
188
|
+
subagents: { depth: (request.depth ?? 1) },
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
self = {
|
|
144
192
|
/**
|
|
145
193
|
* @param {string} systemPrompt
|
|
146
194
|
* @param {Partial<RuntimeRunOptions>} [options] Optional only so the
|
|
@@ -162,9 +210,16 @@ export function createRuntime(host = {}) {
|
|
|
162
210
|
});
|
|
163
211
|
const liveInput = instrumentLiveInputAppliedEvents(options.liveInput, hub.emit);
|
|
164
212
|
const prompts = resolvePrompts(host.prompts, options.prompts);
|
|
213
|
+
// Default the nested-run callback so the Agent built-in is usable without
|
|
214
|
+
// host wiring; the depth field is left exactly as the caller set it, since
|
|
215
|
+
// defaultSubagentRun is what increments it for the child.
|
|
216
|
+
const subagents = options.subagents === undefined
|
|
217
|
+
? undefined
|
|
218
|
+
: { ...options.subagents, run: options.subagents.run ?? defaultSubagentRun };
|
|
165
219
|
const result = await bridge.execute(systemPrompt, {
|
|
166
220
|
...hostDefaults,
|
|
167
221
|
...options,
|
|
222
|
+
...(subagents === undefined ? {} : { subagents }),
|
|
168
223
|
// `...options` alone doesn't carry the `options.model` narrowing above
|
|
169
224
|
// (spread reads the parameter's declared — Partial — type); re-assert
|
|
170
225
|
// the already-validated model so the request satisfies RuntimeRequest.
|
|
@@ -204,4 +259,6 @@ export function createRuntime(host = {}) {
|
|
|
204
259
|
return disposeAllProviderSessions();
|
|
205
260
|
},
|
|
206
261
|
};
|
|
262
|
+
|
|
263
|
+
return self;
|
|
207
264
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How many subagents this logical run actually spawned.
|
|
3
|
+
*
|
|
4
|
+
* A read-only accessor so a provider can report `subagent_invoked` truthfully
|
|
5
|
+
* without reaching into `__budgets`, which is a deliberately private,
|
|
6
|
+
* non-enumerable implementation detail. Returns 0 when nothing was ever
|
|
7
|
+
* registered — a run with no `Agent` tool never creates a budget entry, and that
|
|
8
|
+
* is indistinguishable from one that had the tool and never used it, which is
|
|
9
|
+
* exactly what "no subagent was invoked" means for this signal.
|
|
10
|
+
*
|
|
11
|
+
* @param {*} subagents The run-scoped options object, or undefined.
|
|
12
|
+
* @param {string|undefined} parentRunId
|
|
13
|
+
* @returns {number}
|
|
14
|
+
*/
|
|
15
|
+
export function subagentInvocationCount(subagents: any, parentRunId: string | undefined): number;
|
|
16
|
+
/**
|
|
17
|
+
* Build the `Agent` tool, or null when subagents are unavailable for this run.
|
|
18
|
+
*
|
|
19
|
+
* @param {RuntimeSubagentsOptions|null|undefined} subagents
|
|
20
|
+
* @param {{model?: *, executionMode?: string, cwd?: string, parentRunId?: string, sandboxPolicy?: *, sandboxEngine?: *, skills?: {name: string, description?: string}[], skillsRoot?: string, onEvent?: (event: *) => void}} [context]
|
|
21
|
+
* @returns {*|null}
|
|
22
|
+
*/
|
|
23
|
+
export function createAgentTool(subagents: RuntimeSubagentsOptions | null | undefined, context?: {
|
|
24
|
+
model?: any;
|
|
25
|
+
executionMode?: string;
|
|
26
|
+
cwd?: string;
|
|
27
|
+
parentRunId?: string;
|
|
28
|
+
sandboxPolicy?: any;
|
|
29
|
+
sandboxEngine?: any;
|
|
30
|
+
skills?: {
|
|
31
|
+
name: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
}[];
|
|
34
|
+
skillsRoot?: string;
|
|
35
|
+
onEvent?: (event: any) => void;
|
|
36
|
+
}): any | null;
|
|
37
|
+
/**
|
|
38
|
+
* A subagent that fails, times out, or says nothing still returns its activity
|
|
39
|
+
* log: that log is the most useful artifact of a failed delegation, and a
|
|
40
|
+
* thrown tool error would discard it.
|
|
41
|
+
*
|
|
42
|
+
* @param {{profileName: string, label?: string, outcome: {status: string, answer: string, reason?: string}, durationMs: number, activity: ReadonlyArray<{name: string, args: unknown, ms?: number, isError: boolean}>, maxBytes?: number, cwd?: string, notice?: string}} input
|
|
43
|
+
* @returns {string}
|
|
44
|
+
*/
|
|
45
|
+
export function formatSubagentResult({ profileName, label, outcome, durationMs, activity, maxBytes, cwd, notice }: {
|
|
46
|
+
profileName: string;
|
|
47
|
+
label?: string;
|
|
48
|
+
outcome: {
|
|
49
|
+
status: string;
|
|
50
|
+
answer: string;
|
|
51
|
+
reason?: string;
|
|
52
|
+
};
|
|
53
|
+
durationMs: number;
|
|
54
|
+
activity: ReadonlyArray<{
|
|
55
|
+
name: string;
|
|
56
|
+
args: unknown;
|
|
57
|
+
ms?: number;
|
|
58
|
+
isError: boolean;
|
|
59
|
+
}>;
|
|
60
|
+
maxBytes?: number;
|
|
61
|
+
cwd?: string;
|
|
62
|
+
notice?: string;
|
|
63
|
+
}): string;
|
|
64
|
+
/** @typedef {import('../../ai/types.js').RuntimeSubagentDefinition} RuntimeSubagentDefinition */
|
|
65
|
+
/** @typedef {import('../../ai/types.js').RuntimeSubagentsOptions} RuntimeSubagentsOptions */
|
|
66
|
+
export const GENERAL_PURPOSE_SUBAGENT: "general-purpose";
|
|
67
|
+
/**
|
|
68
|
+
* Read-only by default. A profile that needs a shell or writes must say so in
|
|
69
|
+
* config: widening a subagent's reach is an operator decision, not one the
|
|
70
|
+
* model makes at call time.
|
|
71
|
+
*/
|
|
72
|
+
export const DEFAULT_SUBAGENT_TOOLS: readonly string[];
|
|
73
|
+
/**
|
|
74
|
+
* Never available to a subagent, whatever a profile asks for. `Agent` is the
|
|
75
|
+
* third independent recursion lock; the rest would let a helper hijack the
|
|
76
|
+
* user's conversation or post to a channel on the main agent's behalf.
|
|
77
|
+
*/
|
|
78
|
+
export const SUBAGENT_HARD_DENY: readonly string[];
|
|
79
|
+
export type RuntimeSubagentDefinition = import("../../ai/types.js").RuntimeSubagentDefinition;
|
|
80
|
+
export type RuntimeSubagentsOptions = import("../../ai/types.js").RuntimeSubagentsOptions;
|
|
@@ -1,16 +1,64 @@
|
|
|
1
|
-
export function normalizeBashTimeoutMs(value: any, fallback?: number): number;
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Legacy Bash timeout normalization. Values up to 600 are seconds; larger
|
|
3
|
+
* values are milliseconds. New callers should use `timeout_ms`.
|
|
5
4
|
*/
|
|
6
|
-
export function
|
|
5
|
+
export function normalizeBashTimeoutMs(value: any, fallback?: number): any;
|
|
6
|
+
/**
|
|
7
|
+
* Exact millisecond timeout used by Bash.timeout_ms and Exec.timeout_ms.
|
|
8
|
+
*/
|
|
9
|
+
export function normalizeProcessTimeoutMs(value: any, fallback?: number): any;
|
|
10
|
+
/**
|
|
11
|
+
* Compatibility wrapper retained for direct callers and tests.
|
|
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]
|
|
15
|
+
*/
|
|
16
|
+
export function bashToolImpl(params: {
|
|
17
|
+
command: string;
|
|
18
|
+
timeout?: number;
|
|
19
|
+
timeout_ms?: number;
|
|
20
|
+
max_output_chars?: number;
|
|
21
|
+
workdir?: string;
|
|
22
|
+
}, options?: {
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
sandboxPolicy?: any;
|
|
25
|
+
sandboxEngine?: any;
|
|
26
|
+
ctx?: any;
|
|
27
|
+
}): Promise<any>;
|
|
28
|
+
/**
|
|
29
|
+
* Structured Bash execution used by the Pi bridge.
|
|
30
|
+
*
|
|
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
|
+
*/
|
|
34
|
+
export function bashToolRun({ command, timeout, timeout_ms, max_output_chars, workdir, }: {
|
|
7
35
|
command: string;
|
|
8
36
|
timeout?: number;
|
|
37
|
+
timeout_ms?: number;
|
|
9
38
|
max_output_chars?: number;
|
|
10
39
|
workdir?: string;
|
|
11
|
-
}, { signal, sandboxPolicy, sandboxEngine, ctx }?: {
|
|
12
|
-
signal?:
|
|
40
|
+
}, { signal, sandboxPolicy, sandboxEngine, ctx, }?: {
|
|
41
|
+
signal?: AbortSignal;
|
|
13
42
|
sandboxPolicy?: any;
|
|
14
43
|
sandboxEngine?: any;
|
|
15
44
|
ctx?: any;
|
|
16
|
-
}): Promise<
|
|
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
|
+
}>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
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]
|
|
4
|
+
*/
|
|
5
|
+
export function execToolImpl(params: {
|
|
6
|
+
executable: string;
|
|
7
|
+
args?: string[];
|
|
8
|
+
workdir?: string;
|
|
9
|
+
timeout_ms?: number;
|
|
10
|
+
max_output_chars?: number;
|
|
11
|
+
}, options?: {
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
sandboxPolicy?: any;
|
|
14
|
+
sandboxEngine?: any;
|
|
15
|
+
ctx?: any;
|
|
16
|
+
}): Promise<any>;
|
|
17
|
+
/**
|
|
18
|
+
* Execute an argv vector directly, without shell parsing.
|
|
19
|
+
*
|
|
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]
|
|
22
|
+
*/
|
|
23
|
+
export function execToolRun({ executable, args, workdir, timeout_ms, max_output_chars, }: {
|
|
24
|
+
executable: string;
|
|
25
|
+
args?: string[];
|
|
26
|
+
workdir?: string;
|
|
27
|
+
timeout_ms?: number;
|
|
28
|
+
max_output_chars?: number;
|
|
29
|
+
}, { signal, sandboxPolicy, sandboxEngine, ctx, }?: {
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
sandboxPolicy?: any;
|
|
32
|
+
sandboxEngine?: any;
|
|
33
|
+
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
|
+
}>;
|
|
@@ -3,8 +3,10 @@ export { writeToolImpl } from "./write.js";
|
|
|
3
3
|
export { editToolImpl } from "./edit.js";
|
|
4
4
|
export { globToolImpl } from "./glob.js";
|
|
5
5
|
export { grepToolImpl } from "./grep.js";
|
|
6
|
-
export {
|
|
7
|
-
export { webSearchToolImpl } from "./web-search.js";
|
|
6
|
+
export { createWebToolController } from "./web-controller.js";
|
|
8
7
|
export { resolveRgPath } from "./shared/ripgrep.js";
|
|
9
|
-
export { bashToolImpl, normalizeBashTimeoutMs } from "./bash.js";
|
|
8
|
+
export { bashToolImpl, bashToolRun, normalizeBashTimeoutMs, normalizeProcessTimeoutMs } from "./bash.js";
|
|
9
|
+
export { execToolImpl, execToolRun } from "./exec.js";
|
|
10
|
+
export { webFetchToolImpl, performWebFetch } from "./web-fetch.js";
|
|
11
|
+
export { webSearchToolImpl, performWebSearch } from "./web-search.js";
|
|
10
12
|
export { isPathAllowed, isWorkdirAllowed } from "./shared/path-resolver.js";
|
|
@@ -9,11 +9,36 @@ export function createNodeReplController({ cwd, maxOutputChars, sandboxPolicy, s
|
|
|
9
9
|
sandboxEngine?: any;
|
|
10
10
|
ctx?: any;
|
|
11
11
|
}): {
|
|
12
|
-
|
|
13
|
-
execute({ code }: {
|
|
12
|
+
execute: ({ code }: {
|
|
14
13
|
code: string;
|
|
15
14
|
}, { signal }?: {
|
|
16
15
|
signal?: AbortSignal;
|
|
17
|
-
})
|
|
16
|
+
}) => Promise<any>;
|
|
17
|
+
/** Structured result used by the Pi bridge so telemetry does not depend on text prefixes. */
|
|
18
|
+
executeDetailed(params: any, execution?: {}): Promise<{
|
|
19
|
+
text: any;
|
|
20
|
+
outcome: {
|
|
21
|
+
status: string;
|
|
22
|
+
code: string;
|
|
23
|
+
retryable: boolean;
|
|
24
|
+
attempts: number;
|
|
25
|
+
durationMs: number;
|
|
26
|
+
bytes: number;
|
|
27
|
+
truncated: boolean;
|
|
28
|
+
};
|
|
29
|
+
error: boolean;
|
|
30
|
+
} | {
|
|
31
|
+
text: string;
|
|
32
|
+
outcome: {
|
|
33
|
+
status: string;
|
|
34
|
+
code: any;
|
|
35
|
+
retryable: boolean;
|
|
36
|
+
attempts: number;
|
|
37
|
+
durationMs: number;
|
|
38
|
+
bytes: number;
|
|
39
|
+
truncated: boolean;
|
|
40
|
+
};
|
|
41
|
+
error: boolean;
|
|
42
|
+
}>;
|
|
18
43
|
close(): Promise<void>;
|
|
19
44
|
};
|
|
@@ -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, 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, 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, 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, subagents, subagentContext, toolExecutionMode, ctx, }?: {
|
|
41
41
|
disallowedTools?: any[];
|
|
42
42
|
skillNames?: any[];
|
|
43
43
|
skills?: any[];
|
|
@@ -56,6 +56,10 @@ export function getPiBuiltinTools(allowedTools: any, { disallowedTools, skillNam
|
|
|
56
56
|
approvalManager?: any;
|
|
57
57
|
approvalModel?: any;
|
|
58
58
|
nodeReplController?: any;
|
|
59
|
+
webController?: any;
|
|
60
|
+
toolExecutionMode?: "sequential" | "safe-parallel";
|
|
61
|
+
subagents?: any;
|
|
62
|
+
subagentContext?: any;
|
|
59
63
|
ctx?: any;
|
|
60
64
|
}): any[];
|
|
61
65
|
export function resolveMcpStdioCwd(cfg?: {}, cwd?: any): any;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run one already-prepared executable without adding a shell.
|
|
3
|
+
*
|
|
4
|
+
* The result is deliberately loss-aware: stdout/stderr are retained up to the
|
|
5
|
+
* shared byte cap even when the child times out, is aborted, exits by signal,
|
|
6
|
+
* or exceeds that cap.
|
|
7
|
+
*
|
|
8
|
+
* @param {{command: string, args?: string[], cwd?: string, env?: Record<string, string|undefined>}} commandSpec
|
|
9
|
+
* @param {{timeoutMs?: number, signal?: AbortSignal, maxBufferBytes?: number}} [options]
|
|
10
|
+
*/
|
|
11
|
+
export function runPreparedProcess(commandSpec: {
|
|
12
|
+
command: string;
|
|
13
|
+
args?: string[];
|
|
14
|
+
cwd?: string;
|
|
15
|
+
env?: Record<string, string | undefined>;
|
|
16
|
+
}, { timeoutMs, signal, maxBufferBytes, }?: {
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
maxBufferBytes?: number;
|
|
20
|
+
}): Promise<any>;
|
|
21
|
+
/**
|
|
22
|
+
* @param {import("node:child_process").ChildProcess} child
|
|
23
|
+
* @param {NodeJS.Signals} signal
|
|
24
|
+
*/
|
|
25
|
+
export function killProcessGroup(child: import("node:child_process").ChildProcess, signal: NodeJS.Signals): void;
|
|
26
|
+
/**
|
|
27
|
+
* @param {{stdout?: string, stderr?: string}} result
|
|
28
|
+
*/
|
|
29
|
+
export function combinedProcessOutput(result: {
|
|
30
|
+
stdout?: string;
|
|
31
|
+
stderr?: string;
|
|
32
|
+
}): string;
|
|
33
|
+
export const DEFAULT_PROCESS_BUFFER_BYTES: number;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} CountingSemaphore
|
|
3
|
+
* @property {(signal?: AbortSignal) => Promise<() => void>} acquire Resolves with
|
|
4
|
+
* a single-use release function once a slot is free. Rejects if `signal`
|
|
5
|
+
* aborts while queued; an already-acquired slot is never leaked.
|
|
6
|
+
* @property {() => number} inFlight Slots currently held.
|
|
7
|
+
* @property {() => number} queued Waiters not yet admitted.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* @param {number} limit Maximum simultaneous holders. Values below 1 are clamped.
|
|
11
|
+
* @returns {CountingSemaphore}
|
|
12
|
+
*/
|
|
13
|
+
export function createCountingSemaphore(limit: number): CountingSemaphore;
|
|
14
|
+
export type CountingSemaphore = {
|
|
15
|
+
/**
|
|
16
|
+
* Resolves with
|
|
17
|
+
* a single-use release function once a slot is free. Rejects if `signal`
|
|
18
|
+
* aborts while queued; an already-acquired slot is never leaked.
|
|
19
|
+
*/
|
|
20
|
+
acquire: (signal?: AbortSignal) => Promise<() => void>;
|
|
21
|
+
/**
|
|
22
|
+
* Slots currently held.
|
|
23
|
+
*/
|
|
24
|
+
inFlight: () => number;
|
|
25
|
+
/**
|
|
26
|
+
* Waiters not yet admitted.
|
|
27
|
+
*/
|
|
28
|
+
queued: () => number;
|
|
29
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render one public page in a fresh anonymous agent-browser session.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} url
|
|
5
|
+
* @param {{browserCommand?: string, namespace?: string, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, signal?: AbortSignal, registerCleanup?: (cleanup: () => Promise<void>) => () => void}} [options]
|
|
6
|
+
*/
|
|
7
|
+
export function renderWithAgentBrowser(url: string, { browserCommand, namespace, sandboxPolicy, sandboxEngine, ctx, signal, registerCleanup, }?: {
|
|
8
|
+
browserCommand?: string;
|
|
9
|
+
namespace?: string;
|
|
10
|
+
sandboxPolicy?: any;
|
|
11
|
+
sandboxEngine?: any;
|
|
12
|
+
ctx?: any;
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
registerCleanup?: (cleanup: () => Promise<void>) => () => void;
|
|
15
|
+
}): Promise<any>;
|
|
16
|
+
export function extractBrowserText(output: any): any;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One ephemeral web-tool controller for one model run. It owns in-memory
|
|
3
|
+
* deduplication, result caches, anonymous browser namespaces, and cleanup.
|
|
4
|
+
*
|
|
5
|
+
* @param {{searchConfig?: any, fetchConfig?: any, sandboxPolicy?: any, sandboxEngine?: any, ctx?: any, fetchImpl?: typeof fetch, browserRenderer?: any}} [options]
|
|
6
|
+
*/
|
|
7
|
+
export function createWebToolController({ searchConfig, fetchConfig, sandboxPolicy, sandboxEngine, ctx, fetchImpl, browserRenderer, }?: {
|
|
8
|
+
searchConfig?: any;
|
|
9
|
+
fetchConfig?: any;
|
|
10
|
+
sandboxPolicy?: any;
|
|
11
|
+
sandboxEngine?: any;
|
|
12
|
+
ctx?: any;
|
|
13
|
+
fetchImpl?: typeof fetch;
|
|
14
|
+
browserRenderer?: any;
|
|
15
|
+
}): {
|
|
16
|
+
namespace: string;
|
|
17
|
+
search(params: any, execution?: {}): Promise<any>;
|
|
18
|
+
fetch(params: any, execution?: {}): Promise<any>;
|
|
19
|
+
close(): Promise<void>;
|
|
20
|
+
};
|
|
@@ -1,13 +1,82 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Compatibility wrapper for direct callers.
|
|
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
6
|
*/
|
|
5
|
-
export function webFetchToolImpl(
|
|
7
|
+
export function webFetchToolImpl(params: {
|
|
6
8
|
url: string;
|
|
7
9
|
headers?: Record<string, string>;
|
|
8
10
|
max_output_chars?: number;
|
|
9
|
-
|
|
11
|
+
format?: string;
|
|
12
|
+
render?: string;
|
|
13
|
+
}, options?: {
|
|
10
14
|
sandboxPolicy?: any;
|
|
15
|
+
sandboxEngine?: any;
|
|
11
16
|
ctx?: any;
|
|
17
|
+
signal?: AbortSignal;
|
|
12
18
|
retryDelaysMs?: number[];
|
|
13
|
-
|
|
19
|
+
fetchConfig?: any;
|
|
20
|
+
fetchImpl?: typeof fetch;
|
|
21
|
+
browserRenderer?: typeof renderWithAgentBrowser;
|
|
22
|
+
namespace?: string;
|
|
23
|
+
registerCleanup?: (cleanup: () => Promise<void>) => () => void;
|
|
24
|
+
}): Promise<any>;
|
|
25
|
+
/**
|
|
26
|
+
* Fetch and locally extract one public URL.
|
|
27
|
+
*
|
|
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]
|
|
30
|
+
*/
|
|
31
|
+
export function performWebFetch({ url, headers, max_output_chars, format, render, }: {
|
|
32
|
+
url: string;
|
|
33
|
+
headers?: Record<string, string>;
|
|
34
|
+
max_output_chars?: number;
|
|
35
|
+
format?: string;
|
|
36
|
+
render?: string;
|
|
37
|
+
}, { sandboxPolicy, sandboxEngine, ctx, signal, retryDelaysMs, fetchConfig, fetchImpl, browserRenderer, namespace, registerCleanup, }?: {
|
|
38
|
+
sandboxPolicy?: any;
|
|
39
|
+
sandboxEngine?: any;
|
|
40
|
+
ctx?: any;
|
|
41
|
+
signal?: AbortSignal;
|
|
42
|
+
retryDelaysMs?: number[];
|
|
43
|
+
fetchConfig?: any;
|
|
44
|
+
fetchImpl?: typeof fetch;
|
|
45
|
+
browserRenderer?: typeof renderWithAgentBrowser;
|
|
46
|
+
namespace?: string;
|
|
47
|
+
registerCleanup?: (cleanup: () => Promise<void>) => () => void;
|
|
48
|
+
}): Promise<{
|
|
49
|
+
text: any;
|
|
50
|
+
outcome: {
|
|
51
|
+
status: string;
|
|
52
|
+
code: any;
|
|
53
|
+
retryable: boolean;
|
|
54
|
+
attempts: number;
|
|
55
|
+
backend: string;
|
|
56
|
+
cacheHit: boolean;
|
|
57
|
+
durationMs: number;
|
|
58
|
+
bytes: number;
|
|
59
|
+
truncated: boolean;
|
|
60
|
+
};
|
|
61
|
+
error: boolean;
|
|
62
|
+
} | {
|
|
63
|
+
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
|
+
};
|
|
80
|
+
error: boolean;
|
|
81
|
+
}>;
|
|
82
|
+
import { renderWithAgentBrowser } from "./web-browser-render.js";
|