@springbrand/agent-runtime 0.2.0-alpha.42 → 0.2.0-alpha.43
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/package.json +1 -1
- package/src/adapter/cloudflare/subagent/tools.ts +2 -5
- package/src/adapter/cloudflare/universal-agent/preparation.ts +1 -8
- package/src/adapter/cloudflare/universal-agent/tools.ts +0 -2
- package/src/adapter/cloudflare/workspace/scoped-workspace.ts +15 -0
- package/src/index.ts +1 -0
- package/src/kernel/bindings.ts +10 -0
- package/src/layers/context/budget/gate.ts +3 -3
- package/src/layers/orchestration/temporary-agent/workspace.ts +2 -0
- package/src/lib/prompt.ts +3 -8
- package/src/pi/runtime-adapter/execution.ts +4 -3
- package/src/pi/runtime-adapter/models.ts +9 -6
- package/src/pi/runtime-adapter/openrouter-messages.ts +10 -3
- package/src/pi/tool/base.ts +16 -12
- package/src/pi/tool/compiler.ts +15 -6
- package/src/pi/tool/core-host.ts +141 -56
- package/src/pi/tool/core.ts +3 -2
- package/src/pi/tool/declared.ts +3 -2
- package/src/pi/tool/nested-tools.ts +5 -1
- package/src/pi/tool/schedule.ts +12 -12
- package/src/pi/tool/skill.ts +179 -14
- package/src/pi/tool/subagent.ts +2 -0
- package/src/pi/tool/time.ts +1 -1
- package/src/pi/tool/web-fetch.ts +1 -1
- package/src/pi/tool/web-search/web-search.ts +2 -1
- package/src/pi/tool/workspace-revision.ts +2 -1
- package/src/pi/tool/workspace-sandbox.ts +10 -21
- package/src/runtime-assembler.ts +13 -6
- package/src/runtime.ts +28 -0
package/src/pi/tool/web-fetch.ts
CHANGED
|
@@ -18,7 +18,7 @@ export const webSearchParameters = Type.Object({
|
|
|
18
18
|
description: "Additional URLs to analyze along with search (up to 20)",
|
|
19
19
|
maxItems: 20,
|
|
20
20
|
})),
|
|
21
|
-
});
|
|
21
|
+
}, { additionalProperties: false });
|
|
22
22
|
|
|
23
23
|
export interface WebSearchDetails extends Omit<WebSearchResult, "text"> {
|
|
24
24
|
resultCount: number;
|
|
@@ -119,6 +119,7 @@ export function webSearchPiToolCandidate(
|
|
|
119
119
|
};
|
|
120
120
|
return {
|
|
121
121
|
owner: "runtime-base",
|
|
122
|
+
exposureMode: "direct",
|
|
122
123
|
requiredExecutionLevel: "safe",
|
|
123
124
|
source: "action",
|
|
124
125
|
tool,
|
|
@@ -14,7 +14,7 @@ const parameters = Type.Object({
|
|
|
14
14
|
], {
|
|
15
15
|
description: "Use previous for the revision immediately before the current one.",
|
|
16
16
|
}),
|
|
17
|
-
});
|
|
17
|
+
}, { additionalProperties: false });
|
|
18
18
|
|
|
19
19
|
function result<T>(details: T): AgentToolResult<T> {
|
|
20
20
|
return {
|
|
@@ -43,6 +43,7 @@ export function workspaceRevisionPiToolCandidate(
|
|
|
43
43
|
};
|
|
44
44
|
return {
|
|
45
45
|
owner: "workspace",
|
|
46
|
+
exposureMode: "direct",
|
|
46
47
|
tool,
|
|
47
48
|
requiredExecutionLevel: "safe",
|
|
48
49
|
alwaysRequiresApproval: true,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
createBashTool,
|
|
3
2
|
createDeleteTool,
|
|
4
3
|
createEditTool,
|
|
5
4
|
createFindTool,
|
|
@@ -68,7 +67,7 @@ const workspaceReadParameters = Type.Object({
|
|
|
68
67
|
minimum: 1,
|
|
69
68
|
description: "Maximum lines to return; a page is capped by size regardless",
|
|
70
69
|
})),
|
|
71
|
-
});
|
|
70
|
+
}, { additionalProperties: false });
|
|
72
71
|
const workspaceEditParameters = Type.Object({
|
|
73
72
|
path: Type.String({
|
|
74
73
|
minLength: 1,
|
|
@@ -80,7 +79,7 @@ const workspaceEditParameters = Type.Object({
|
|
|
80
79
|
"Exact existing text to replace. Include enough surrounding context to match one location.",
|
|
81
80
|
}),
|
|
82
81
|
new_string: Type.String({ description: "Replacement text." }),
|
|
83
|
-
});
|
|
82
|
+
}, { additionalProperties: false });
|
|
84
83
|
|
|
85
84
|
/**
|
|
86
85
|
* 单页 read 返回的字符上限。
|
|
@@ -176,7 +175,7 @@ function pageReadResult(
|
|
|
176
175
|
const span = `lines ${fromLine}-${toLine} of ${totalLines ?? toLine}`;
|
|
177
176
|
const lossyNote = lossy
|
|
178
177
|
? " Some lines were longer than 2000 chars and are cut short; " +
|
|
179
|
-
"paging cannot recover them — use grep
|
|
178
|
+
"paging cannot recover them — use grep on this path instead."
|
|
180
179
|
: "";
|
|
181
180
|
const marker = fromLine === 1 && eof && !lossy
|
|
182
181
|
? ""
|
|
@@ -399,12 +398,6 @@ export function workspacePiToolCandidates(
|
|
|
399
398
|
},
|
|
400
399
|
};
|
|
401
400
|
|
|
402
|
-
const bash = aiToolToPi(
|
|
403
|
-
"bash",
|
|
404
|
-
createBashTool({ ops: workspace }),
|
|
405
|
-
{ label: "Workspace Bash" },
|
|
406
|
-
);
|
|
407
|
-
|
|
408
401
|
return [
|
|
409
402
|
{
|
|
410
403
|
owner: "workspace",
|
|
@@ -420,13 +413,6 @@ export function workspacePiToolCandidates(
|
|
|
420
413
|
requiredExecutionLevel: "safe" as const,
|
|
421
414
|
tool,
|
|
422
415
|
})),
|
|
423
|
-
{
|
|
424
|
-
owner: "workspace",
|
|
425
|
-
requiredExecutionLevel: "high" as const,
|
|
426
|
-
summary: "Run a Bash script over Workspace files",
|
|
427
|
-
source: "action" as const,
|
|
428
|
-
tool: bash,
|
|
429
|
-
},
|
|
430
416
|
];
|
|
431
417
|
}
|
|
432
418
|
|
|
@@ -460,15 +446,18 @@ const sandboxExecParameters = Type.Object({
|
|
|
460
446
|
description: "Maximum command runtime in milliseconds, from 1 to 60000.",
|
|
461
447
|
}),
|
|
462
448
|
),
|
|
463
|
-
});
|
|
464
|
-
const sandboxStartParameters = Type.Object(
|
|
449
|
+
}, { additionalProperties: false });
|
|
450
|
+
const sandboxStartParameters = Type.Object(
|
|
451
|
+
sandboxCommandParameters,
|
|
452
|
+
{ additionalProperties: false },
|
|
453
|
+
);
|
|
465
454
|
const sandboxProcessParameters = Type.Object({
|
|
466
455
|
id: Type.String({
|
|
467
456
|
minLength: 1,
|
|
468
457
|
maxLength: 128,
|
|
469
458
|
description: "Process ID returned by sandbox_start_process.",
|
|
470
459
|
}),
|
|
471
|
-
});
|
|
460
|
+
}, { additionalProperties: false });
|
|
472
461
|
const sandboxPublishParameters = Type.Object({
|
|
473
462
|
paths: Type.Array(Type.String({
|
|
474
463
|
minLength: 1,
|
|
@@ -479,7 +468,7 @@ const sandboxPublishParameters = Type.Object({
|
|
|
479
468
|
maxItems: 100,
|
|
480
469
|
description: "Files to copy from the temporary Sandbox into the persistent Workspace.",
|
|
481
470
|
}),
|
|
482
|
-
});
|
|
471
|
+
}, { additionalProperties: false });
|
|
483
472
|
|
|
484
473
|
/**
|
|
485
474
|
* 为现有 RuntimeSandboxPort 创建 Pi 命令、进程和文件发布工具。
|
package/src/runtime-assembler.ts
CHANGED
|
@@ -35,7 +35,10 @@ import {
|
|
|
35
35
|
type PiRuntimeAssembly,
|
|
36
36
|
} from "./pi/assembly/snapshot";
|
|
37
37
|
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
38
|
-
import type {
|
|
38
|
+
import type {
|
|
39
|
+
PiToolCandidate,
|
|
40
|
+
ToolExposureMode,
|
|
41
|
+
} from "./pi/tool/compiler";
|
|
39
42
|
import type {
|
|
40
43
|
AssembleRuntimeSnapshotInput,
|
|
41
44
|
RuntimeSettings,
|
|
@@ -178,6 +181,10 @@ interface ToolSurface {
|
|
|
178
181
|
readonly degradations: readonly RuntimeDegradation[];
|
|
179
182
|
}
|
|
180
183
|
|
|
184
|
+
function exposureOf(candidate: PiToolCandidate): ToolExposureMode {
|
|
185
|
+
return candidate.exposureMode ?? "both";
|
|
186
|
+
}
|
|
187
|
+
|
|
181
188
|
// 唯一 Tool Surface seam:只读取已配置 Port、Resource 和 Agent policy,
|
|
182
189
|
// 统一生成可见 Tool,并在一处做名称、执行档位与冲突校验。
|
|
183
190
|
async function createToolSurface(
|
|
@@ -203,14 +210,14 @@ async function createToolSurface(
|
|
|
203
210
|
});
|
|
204
211
|
// 平台没有浏览器能力时注册空集:宁可没有这个 Tool,也不注册一个必然失败的 Tool 误导模型。
|
|
205
212
|
// `create()` 推迟到确认这个名字真的可见之后,被 deny 的装配不白建一个浏览器连接器。
|
|
206
|
-
// `direct` 使它只走 Direct 调用,不再被并进 `execute` 的工具集——两个 Code Mode 类工具互相嵌套
|
|
213
|
+
// `direct` exposure 使它只走 Direct 调用,不再被并进 `execute` 的工具集——两个 Code Mode 类工具互相嵌套
|
|
207
214
|
// 会让「哪次执行被记录、被重放」变得无法解释,而它们的分工本就由 System Prompt 划清。
|
|
208
215
|
const browserVisible = !deny.has(BROWSER_EXECUTE_TOOL_NAME) &&
|
|
209
216
|
allowsTool?.(BROWSER_EXECUTE_TOOL_NAME) !== false;
|
|
210
217
|
const browserCandidates = input.platform.browser && browserVisible
|
|
211
218
|
? [{
|
|
212
219
|
...browserExecutionPiToolCandidate(input.platform.browser.create()),
|
|
213
|
-
|
|
220
|
+
exposureMode: "direct" as const,
|
|
214
221
|
}]
|
|
215
222
|
: [];
|
|
216
223
|
const baseCandidates = basePiToolCandidates(input.webSearch);
|
|
@@ -256,7 +263,7 @@ async function createToolSurface(
|
|
|
256
263
|
|
|
257
264
|
const finalized = [...tools.values()];
|
|
258
265
|
const directVisible = finalized.filter(
|
|
259
|
-
(candidate) =>
|
|
266
|
+
(candidate) => exposureOf(candidate) !== "codemode",
|
|
260
267
|
);
|
|
261
268
|
if (tools.has("execute")) {
|
|
262
269
|
throw new Error("SpringBrand reserved Runtime Tool name: execute");
|
|
@@ -273,7 +280,7 @@ async function createToolSurface(
|
|
|
273
280
|
}
|
|
274
281
|
const mergeable = finalized.filter(
|
|
275
282
|
(candidate) =>
|
|
276
|
-
|
|
283
|
+
exposureOf(candidate) !== "direct" &&
|
|
277
284
|
!candidate.interaction &&
|
|
278
285
|
typeof candidate.tool.execute === "function",
|
|
279
286
|
);
|
|
@@ -316,7 +323,7 @@ async function createToolSurface(
|
|
|
316
323
|
? "Skill resource copying is available only inside execute through " +
|
|
317
324
|
"`tools.materialize_skill_resource({ name, path, destination })`; " +
|
|
318
325
|
"no Direct Tool is registered for it. " +
|
|
319
|
-
"
|
|
326
|
+
"Copy multiple resources sequentially in one execute so durable replay preserves call order.\n\n"
|
|
320
327
|
: "";
|
|
321
328
|
return Object.freeze({
|
|
322
329
|
candidates: Object.freeze([
|
package/src/runtime.ts
CHANGED
|
@@ -899,6 +899,7 @@ export abstract class AgentRuntimeKernel<
|
|
|
899
899
|
return this.pi.createTurn({
|
|
900
900
|
prepared: this.preparedPi(),
|
|
901
901
|
pinnedDescriptor: submission.assemblyDescriptor,
|
|
902
|
+
modelSessionId: this.name,
|
|
902
903
|
submission: {
|
|
903
904
|
id: submission.submissionId,
|
|
904
905
|
requestId: submission.requestId,
|
|
@@ -996,6 +997,7 @@ export abstract class AgentRuntimeKernel<
|
|
|
996
997
|
...(event.error ? { error: errorText(event.error) } : {}),
|
|
997
998
|
occurredAt: event.occurredAt,
|
|
998
999
|
});
|
|
1000
|
+
this.projectNestedToolSettlement(submission.submissionId, event);
|
|
999
1001
|
},
|
|
1000
1002
|
...(toolExecutors && Object.keys(toolExecutors).length > 0
|
|
1001
1003
|
? { toolExecutors }
|
|
@@ -2200,6 +2202,32 @@ export abstract class AgentRuntimeKernel<
|
|
|
2200
2202
|
return this.drainRuntimeEvents();
|
|
2201
2203
|
}
|
|
2202
2204
|
|
|
2205
|
+
private projectNestedToolSettlement(
|
|
2206
|
+
submissionId: string,
|
|
2207
|
+
event: Readonly<{
|
|
2208
|
+
toolCallId: string;
|
|
2209
|
+
toolName: string;
|
|
2210
|
+
outcome: "completed" | "failed" | "cancelled";
|
|
2211
|
+
occurredAt: number;
|
|
2212
|
+
}>,
|
|
2213
|
+
): void {
|
|
2214
|
+
const settlement: RuntimeToolSettlementEvent = {
|
|
2215
|
+
eventId: `${submissionId}:tool:${event.toolCallId}`,
|
|
2216
|
+
submissionId,
|
|
2217
|
+
toolCallId: event.toolCallId,
|
|
2218
|
+
toolName: event.toolName,
|
|
2219
|
+
status: event.outcome === "completed" ? "success" : "error",
|
|
2220
|
+
};
|
|
2221
|
+
this.db.transaction(() => {
|
|
2222
|
+
this.db.runtimeEvents.insert({
|
|
2223
|
+
eventId: settlement.eventId,
|
|
2224
|
+
body: json({ type: "tool-settlement", event: settlement }),
|
|
2225
|
+
createdAt: event.occurredAt,
|
|
2226
|
+
});
|
|
2227
|
+
});
|
|
2228
|
+
this.ctx.waitUntil(this.drainRuntimeEvents());
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2203
2231
|
// 终态事务用这个同步内核先补齐 ToolResult,再在同一事务末尾写 marker。
|
|
2204
2232
|
private settleToolSync(
|
|
2205
2233
|
submissionId: string,
|