@mono-agent/agent-runtime 0.15.3 → 0.15.4
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/README.md +43 -6
- package/package.json +5 -1
- package/src/agent/tools/agent-tool.js +859 -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/providers/pi-native/stream-subscriber.js +37 -0
- package/src/ai/providers/pi-native/turn-runner.js +60 -5
- package/src/ai/providers/pi-native.js +49 -5
- package/src/ai/runtime/router.js +302 -166
- package/src/ai/types.js +52 -1
- package/src/runtime.js +51 -1
- package/types/agent/tools/agent-tool.d.ts +60 -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/providers/pi-native/turn-runner.d.ts +34 -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 +163 -1
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
initPiMcpTools,
|
|
16
16
|
} from "../../../agent/tools/pi-bridge.js";
|
|
17
17
|
import { createNodeReplController } from "../../../agent/tools/node-repl.js";
|
|
18
|
+
import { createWebToolController } from "../../../agent/tools/web-controller.js";
|
|
18
19
|
import { readToolRuntime } from "../../../agent/tools/shared/runtime-context.js";
|
|
19
20
|
import { formatLiveInputGuidance } from "../../live-input-prompt.js";
|
|
20
21
|
import { appendStructuredOutputInstruction } from "./structured-output.js";
|
|
@@ -40,6 +41,7 @@ export async function buildTurnTools(runState, {
|
|
|
40
41
|
resolved,
|
|
41
42
|
onEvent,
|
|
42
43
|
runtimeWarnings,
|
|
44
|
+
toolExecutionMode = "safe-parallel",
|
|
43
45
|
}) {
|
|
44
46
|
const onTruncate = (info) => {
|
|
45
47
|
try {
|
|
@@ -73,6 +75,15 @@ export async function buildTurnTools(runState, {
|
|
|
73
75
|
sandboxEngine,
|
|
74
76
|
ctx: runCtx,
|
|
75
77
|
});
|
|
78
|
+
const webController = capabilities.tool_use === false
|
|
79
|
+
? null
|
|
80
|
+
: createWebToolController({
|
|
81
|
+
searchConfig: options.webSearchConfig,
|
|
82
|
+
fetchConfig: options.webFetchConfig,
|
|
83
|
+
sandboxPolicy: options.sandboxPolicy,
|
|
84
|
+
sandboxEngine,
|
|
85
|
+
ctx: runCtx,
|
|
86
|
+
});
|
|
76
87
|
|
|
77
88
|
// REUSED custom pieces: built-in tool sandboxing + allowlist/bloat filter +
|
|
78
89
|
// approval gates. These are identical to the legacy bridge.
|
|
@@ -109,6 +120,21 @@ export async function buildTurnTools(runState, {
|
|
|
109
120
|
approvalManager,
|
|
110
121
|
approvalModel: runtime.model?.id || runtime.model?.name || resolved.model,
|
|
111
122
|
nodeReplController,
|
|
123
|
+
webController,
|
|
124
|
+
toolExecutionMode,
|
|
125
|
+
subagents: options.subagents,
|
|
126
|
+
// The child inherits the parent's route and workspace unless its profile
|
|
127
|
+
// pins a model; the tool closure reads these to build each child request.
|
|
128
|
+
subagentContext: {
|
|
129
|
+
model: options.model,
|
|
130
|
+
executionMode: options.executionMode,
|
|
131
|
+
cwd: options.cwd,
|
|
132
|
+
parentRunId: runCtx?.runId,
|
|
133
|
+
// Same policy + engine this turn's own tools are confined by, so a
|
|
134
|
+
// child is never less sandboxed than the parent that spawned it.
|
|
135
|
+
sandboxPolicy: options.sandboxPolicy,
|
|
136
|
+
sandboxEngine,
|
|
137
|
+
},
|
|
112
138
|
ctx: runCtx,
|
|
113
139
|
}));
|
|
114
140
|
|
|
@@ -143,14 +169,19 @@ export async function buildTurnTools(runState, {
|
|
|
143
169
|
|
|
144
170
|
const tools = [
|
|
145
171
|
...builtIns,
|
|
146
|
-
...mcpInit.tools,
|
|
172
|
+
...mcpInit.tools.map((tool) => ({ ...tool, executionMode: "sequential" })),
|
|
147
173
|
...(structuredTool ? [structuredTool] : []),
|
|
148
174
|
];
|
|
149
175
|
return {
|
|
150
176
|
tools,
|
|
151
177
|
structuredTool,
|
|
152
178
|
mcpClients: mcpInit.clients,
|
|
153
|
-
closeRunTools: async () => {
|
|
179
|
+
closeRunTools: async () => {
|
|
180
|
+
await Promise.allSettled([
|
|
181
|
+
nodeReplController?.close(),
|
|
182
|
+
webController?.close(),
|
|
183
|
+
].filter(Boolean));
|
|
184
|
+
},
|
|
154
185
|
};
|
|
155
186
|
}
|
|
156
187
|
|
|
@@ -189,6 +220,26 @@ export function thinkingLevelForEffort(effort, capabilities) {
|
|
|
189
220
|
* @param {any} params
|
|
190
221
|
* @returns {any}
|
|
191
222
|
*/
|
|
223
|
+
/**
|
|
224
|
+
* Restore the error flag on a tool result pi resolved successfully.
|
|
225
|
+
*
|
|
226
|
+
* pi hardcodes `isError: false` for every `execute()` that returns rather than
|
|
227
|
+
* throws, so any tool that reports failure in its payload needs this hook or
|
|
228
|
+
* the model is told the call succeeded.
|
|
229
|
+
*
|
|
230
|
+
* @param {*} details Tool-result details recorded by the bridge.
|
|
231
|
+
* @returns {{isError: true}|undefined}
|
|
232
|
+
*/
|
|
233
|
+
export function toolResultErrorOverride(details) {
|
|
234
|
+
const subagentStatus = details?.subagent?.status;
|
|
235
|
+
const failed = details?.mcp_result_is_error === true
|
|
236
|
+
|| details?.outcome?.status === "error"
|
|
237
|
+
// A failed subagent returns its answer-plus-log instead of throwing,
|
|
238
|
+
// precisely so a failed delegation keeps its activity log.
|
|
239
|
+
|| (typeof subagentStatus === "string" && subagentStatus !== "ok");
|
|
240
|
+
return failed ? { isError: true } : undefined;
|
|
241
|
+
}
|
|
242
|
+
|
|
192
243
|
export function buildTurnHarness(runState, {
|
|
193
244
|
cwd,
|
|
194
245
|
session,
|
|
@@ -225,9 +276,13 @@ export function buildTurnHarness(runState, {
|
|
|
225
276
|
// this after-tool hook restores the error flag while preserving the already
|
|
226
277
|
// bounded content/details verbatim. Downstream tool_execution_end and timing
|
|
227
278
|
// events therefore report the failure accurately.
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
279
|
+
//
|
|
280
|
+
// A failed subagent is the same shape of problem: the `Agent` tool returns
|
|
281
|
+
// its formatted answer-plus-activity-log rather than throwing, precisely so a
|
|
282
|
+
// failed delegation keeps its log — but pi hardcodes `isError: false` for
|
|
283
|
+
// every resolved execute(), so without this the model would be told a failed,
|
|
284
|
+
// timed-out, or empty delegation succeeded.
|
|
285
|
+
harness.on("tool_result", (event) => toolResultErrorOverride(event?.details));
|
|
231
286
|
runState.harness = harness;
|
|
232
287
|
|
|
233
288
|
harness.subscribe(createStreamSubscriber(runState, {
|
|
@@ -78,6 +78,37 @@ import {
|
|
|
78
78
|
} from "./pi-native/turn-runner.js";
|
|
79
79
|
import { resolvePiTransport } from "./pi-native/transport.js";
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Pi 0.80.6 exposes per-tool execution markers but not AgentHarness's global
|
|
83
|
+
* toolExecution option. Resolve mono-agent's programmatic mode once per run;
|
|
84
|
+
* individual tool builders then mark stateful/mutating tools sequential.
|
|
85
|
+
*/
|
|
86
|
+
export function resolvePiToolExecutionMode(options = {}) {
|
|
87
|
+
const warnings = [];
|
|
88
|
+
const requested = options.piToolExecutionMode;
|
|
89
|
+
let mode = requested === "sequential" || requested === "safe-parallel"
|
|
90
|
+
? requested
|
|
91
|
+
: null;
|
|
92
|
+
if (requested !== undefined && mode === null) {
|
|
93
|
+
warnings.push({
|
|
94
|
+
warning_kind: "invalid_pi_tool_execution_mode",
|
|
95
|
+
message: `Unknown piToolExecutionMode ${JSON.stringify(requested)}; using safe-parallel.`,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (options.piToolParallelismMode !== undefined) {
|
|
99
|
+
warnings.push({
|
|
100
|
+
warning_kind: "deprecated_pi_tool_parallelism_mode",
|
|
101
|
+
message: "piToolParallelismMode is deprecated; use piToolExecutionMode (sequential or safe-parallel).",
|
|
102
|
+
});
|
|
103
|
+
if (mode === null) {
|
|
104
|
+
mode = options.piToolParallelismMode === "one-at-a-time"
|
|
105
|
+
? "sequential"
|
|
106
|
+
: "safe-parallel";
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return { mode: mode || "safe-parallel", warnings };
|
|
110
|
+
}
|
|
111
|
+
|
|
81
112
|
async function resolveApiKey(provider, { apiKeys, resolvePiApiKey, runtimeWarnings }) {
|
|
82
113
|
if (apiKeys?.has(provider)) return apiKeys.get(provider);
|
|
83
114
|
if (typeof resolvePiApiKey !== "function") return undefined;
|
|
@@ -307,13 +338,21 @@ export async function generatePiNativeResponse(systemPrompt, options = {}) {
|
|
|
307
338
|
const piTransport = resolvePiTransport(options.piTransport);
|
|
308
339
|
|
|
309
340
|
const onEvent = (event) => emitCaptured(events, options.onEvent, event);
|
|
341
|
+
const approvalRiskTiers = {
|
|
342
|
+
...(options.toolRiskTiers || {}),
|
|
343
|
+
...(
|
|
344
|
+
options.toolRiskTiers?.Exec === undefined && options.toolRiskTiers?.Bash !== undefined
|
|
345
|
+
? { Exec: options.toolRiskTiers.Bash }
|
|
346
|
+
: {}
|
|
347
|
+
),
|
|
348
|
+
};
|
|
310
349
|
const approvalManager = options.onToolApprovalRequest
|
|
311
350
|
? createApprovalManager({
|
|
312
351
|
onToolApprovalRequest: options.onToolApprovalRequest,
|
|
313
352
|
defaultRiskTier: options.approvalDefaultRiskTier,
|
|
314
353
|
timeoutMs: options.approvalTimeoutMs,
|
|
315
354
|
onEvent,
|
|
316
|
-
riskTiersByTool:
|
|
355
|
+
riskTiersByTool: approvalRiskTiers,
|
|
317
356
|
alwaysAllowTools: options.approvalAlwaysAllowTools,
|
|
318
357
|
})
|
|
319
358
|
: null;
|
|
@@ -396,6 +435,11 @@ export async function generatePiNativeResponse(systemPrompt, options = {}) {
|
|
|
396
435
|
// normalization. Restores configurable clamping (toolTextLimitChars,
|
|
397
436
|
// searchResultLimit, ...) on top of the 256KB hard ceiling.
|
|
398
437
|
const toolLimits = resolveAgentCompactionPolicy(settingsLike, runtime.model);
|
|
438
|
+
const toolExecution = resolvePiToolExecutionMode(options);
|
|
439
|
+
for (const warning of toolExecution.warnings) {
|
|
440
|
+
runtimeWarnings.push(warning);
|
|
441
|
+
onEvent({ type: "runtime_warning", ...warning });
|
|
442
|
+
}
|
|
399
443
|
|
|
400
444
|
// Build the turn's tools (builtins + MCP bridge + StructuredOutput). The
|
|
401
445
|
// StructuredOutput callback writes runState.structuredResult; the MCP clients
|
|
@@ -414,6 +458,7 @@ export async function generatePiNativeResponse(systemPrompt, options = {}) {
|
|
|
414
458
|
resolved,
|
|
415
459
|
onEvent,
|
|
416
460
|
runtimeWarnings,
|
|
461
|
+
toolExecutionMode: toolExecution.mode,
|
|
417
462
|
});
|
|
418
463
|
mcpClients = builtMcpClients;
|
|
419
464
|
closeRunTools = builtCloseRunTools;
|
|
@@ -426,10 +471,9 @@ export async function generatePiNativeResponse(systemPrompt, options = {}) {
|
|
|
426
471
|
const maxRetryDelayMs = Number.isFinite(Number(options.maxRetryDelayMs))
|
|
427
472
|
? Number(options.maxRetryDelayMs)
|
|
428
473
|
: 60_000;
|
|
429
|
-
//
|
|
430
|
-
//
|
|
431
|
-
|
|
432
|
-
const toolSteeringMode = options.piToolParallelismMode === "all" ? "all" : "one-at-a-time";
|
|
474
|
+
// Steering controls user follow-up delivery, not tool scheduling. Keep it
|
|
475
|
+
// independent from piToolExecutionMode; tools carry their own executionMode.
|
|
476
|
+
const toolSteeringMode = "one-at-a-time";
|
|
433
477
|
|
|
434
478
|
const piModels = buildRunModels(runtime, options, runtimeWarnings);
|
|
435
479
|
|