@springbrand/agent-runtime 0.1.2 → 0.1.3-alpha.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.
- package/package.json +1 -1
- package/src/index.ts +9 -11
- package/src/kernel/bindings.ts +26 -3
- package/src/kernel/extensions.ts +1 -1
- package/src/kernel/profile.ts +3 -4
- package/src/layers/orchestration/temporary-agent/runner.ts +0 -65
- package/src/pi/assembly/context.ts +1 -3
- package/src/pi/assembly/snapshot.ts +12 -7
- package/src/pi/runtime-adapter/assembly.ts +16 -66
- package/src/pi/runtime-adapter/execution.ts +18 -6
- package/src/pi/tool/compiler.ts +5 -32
- package/src/pi/tool/core-host.ts +14 -7
- package/src/pi/tool/core.ts +35 -5
- package/src/pi/tool/mcp.ts +2 -2
- package/src/pi/tool/schedule.ts +46 -2
- package/src/pi/tool/skill.ts +1 -1
- package/src/plugins.ts +311 -521
- package/src/runtime.ts +5 -4
package/src/pi/tool/core-host.ts
CHANGED
|
@@ -8,30 +8,35 @@ import {
|
|
|
8
8
|
type WorkspaceFsLike,
|
|
9
9
|
} from "@cloudflare/shell";
|
|
10
10
|
import { StateConnector } from "@cloudflare/shell/workers";
|
|
11
|
-
import type {
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
import type {
|
|
12
|
+
RuntimeCodeExecutionPort,
|
|
13
|
+
WorkspacePort,
|
|
14
|
+
} from "../../kernel/bindings";
|
|
14
15
|
|
|
15
16
|
// 本文件沿用 `../../index.ts` 入口定义的 Workspace、Port 和 Tool Candidate 术语。
|
|
16
17
|
|
|
18
|
+
const CODEMODE_SANDBOX_TIMEOUT_MS = 55_000;
|
|
19
|
+
|
|
17
20
|
/**
|
|
18
|
-
* 把宿主的 Worker Loader、出站网络和 Workspace
|
|
21
|
+
* 把宿主的 Worker Loader、出站网络和 Workspace 组装成代码执行 Port。
|
|
19
22
|
*
|
|
20
23
|
* Worker 宿主在具备 Durable Object state 和完整平台绑定时调用,然后把返回值交给 Runtime 工具组装。
|
|
21
24
|
*
|
|
22
25
|
* Cloudflare Codemode 把持久化 Runtime 和无状态 Dynamic Worker executor 分开;这里必须用 StateConnector 显式注入已限定范围的 Workspace,并在返回模型前用官方 `truncateResult` 限制结果。
|
|
23
26
|
*/
|
|
24
|
-
export function
|
|
27
|
+
export function createWorkspaceCodeExecutionPort(options: {
|
|
25
28
|
readonly ctx: DurableObjectState;
|
|
26
29
|
readonly loader: WorkerLoader;
|
|
27
30
|
readonly outbound: Fetcher;
|
|
28
31
|
readonly workspace: WorkspacePort;
|
|
29
|
-
}):
|
|
32
|
+
}): RuntimeCodeExecutionPort {
|
|
30
33
|
const runtime = createCodemodeRuntime({
|
|
31
34
|
ctx: options.ctx,
|
|
32
35
|
executor: new DynamicWorkerExecutor({
|
|
33
36
|
loader: options.loader,
|
|
34
37
|
globalOutbound: options.outbound,
|
|
38
|
+
// 先于外层 60s 截止结束,给 Runtime RPC 结算和 Worker 释放留出时间。
|
|
39
|
+
timeout: CODEMODE_SANDBOX_TIMEOUT_MS,
|
|
35
40
|
}),
|
|
36
41
|
connectors: [
|
|
37
42
|
new StateConnector(
|
|
@@ -44,5 +49,7 @@ export function workspaceCodeExecutionPiToolCandidate(options: {
|
|
|
44
49
|
name: "execute",
|
|
45
50
|
transformResult: truncateResult,
|
|
46
51
|
});
|
|
47
|
-
return
|
|
52
|
+
return {
|
|
53
|
+
execute: (input) => runtime.execute(input),
|
|
54
|
+
};
|
|
48
55
|
}
|
package/src/pi/tool/core.ts
CHANGED
|
@@ -3,7 +3,6 @@ import type {
|
|
|
3
3
|
AgentToolResult,
|
|
4
4
|
} from "@earendil-works/pi-agent-core";
|
|
5
5
|
import { Type } from "@earendil-works/pi-ai";
|
|
6
|
-
import type { CodemodeRuntimeHandle } from "@cloudflare/codemode";
|
|
7
6
|
import {
|
|
8
7
|
browserExtract,
|
|
9
8
|
browserLinks,
|
|
@@ -11,7 +10,10 @@ import {
|
|
|
11
10
|
browserScrape,
|
|
12
11
|
type QuickActionPage,
|
|
13
12
|
} from "agents/browser";
|
|
14
|
-
import type {
|
|
13
|
+
import type {
|
|
14
|
+
RuntimeBrowserPort,
|
|
15
|
+
RuntimeCodeExecutionPort,
|
|
16
|
+
} from "../../kernel/bindings";
|
|
15
17
|
import { serializeOutput } from "../../lib/artifacts";
|
|
16
18
|
import type { PiLoadedExtension } from "../assembly/extensions";
|
|
17
19
|
import type { PiToolCandidate } from "./compiler";
|
|
@@ -205,16 +207,18 @@ const executeParameters = Type.Object({
|
|
|
205
207
|
"Plain JavaScript async function. TypeScript annotations are not supported.",
|
|
206
208
|
}),
|
|
207
209
|
});
|
|
210
|
+
const CODEMODE_EXECUTE_TIMEOUT_MS = 60_000;
|
|
208
211
|
|
|
209
212
|
/**
|
|
210
213
|
* 把 Cloudflare Codemode Runtime handle 包装为高风险 Pi 代码执行工具候选项。
|
|
211
214
|
*
|
|
212
|
-
*
|
|
215
|
+
* Tool Surface 收到 Host 已组装的 Code Execution Port 后调用,
|
|
216
|
+
* 模型再通过 `execute` 运行代码。
|
|
213
217
|
*
|
|
214
218
|
* Codemode 代码可访问出站网络和已配置 connector,因此必须保留 high 档和 codemode source 标记,不能降级成普通本地计算工具。
|
|
215
219
|
*/
|
|
216
220
|
export function codeExecutionPiToolCandidate(
|
|
217
|
-
runtime:
|
|
221
|
+
runtime: RuntimeCodeExecutionPort,
|
|
218
222
|
): PiToolCandidate {
|
|
219
223
|
const tool: AgentTool<typeof executeParameters> = {
|
|
220
224
|
name: "execute",
|
|
@@ -235,7 +239,33 @@ export function codeExecutionPiToolCandidate(
|
|
|
235
239
|
// 必须通过 Runtime handle 而不是直接调用 executor,因为 Cloudflare Codemode 把重放、审批和执行日志放在持久化 Runtime 层。
|
|
236
240
|
async execute(_toolCallId, input, signal) {
|
|
237
241
|
signal?.throwIfAborted();
|
|
238
|
-
|
|
242
|
+
// ponytail: 外层截止只保证 Agent 继续;Codemode 支持 AbortSignal 或宿主 dispose 后再终止底层执行。
|
|
243
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
244
|
+
const deadline = new Promise<{
|
|
245
|
+
status: "error";
|
|
246
|
+
code: "timeout";
|
|
247
|
+
error: string;
|
|
248
|
+
retryable: false;
|
|
249
|
+
outcome: "unknown";
|
|
250
|
+
}>((resolve) => {
|
|
251
|
+
timeout = setTimeout(() => resolve({
|
|
252
|
+
status: "error",
|
|
253
|
+
code: "timeout",
|
|
254
|
+
error:
|
|
255
|
+
`Code Mode execute exceeded ${CODEMODE_EXECUTE_TIMEOUT_MS} ms; ` +
|
|
256
|
+
"use existing results and state the missing evidence.",
|
|
257
|
+
retryable: false,
|
|
258
|
+
outcome: "unknown",
|
|
259
|
+
}), CODEMODE_EXECUTE_TIMEOUT_MS);
|
|
260
|
+
});
|
|
261
|
+
try {
|
|
262
|
+
return result(await Promise.race([
|
|
263
|
+
runtime.execute(input),
|
|
264
|
+
deadline,
|
|
265
|
+
]));
|
|
266
|
+
} finally {
|
|
267
|
+
if (timeout !== undefined) clearTimeout(timeout);
|
|
268
|
+
}
|
|
239
269
|
},
|
|
240
270
|
};
|
|
241
271
|
return {
|
package/src/pi/tool/mcp.ts
CHANGED
|
@@ -12,7 +12,7 @@ interface McpCallResult {
|
|
|
12
12
|
/**
|
|
13
13
|
* Pi 的 MCP 适配器所需的最小 Host 能力。
|
|
14
14
|
*
|
|
15
|
-
*
|
|
15
|
+
* Tool Surface 在收集本轮工具时传入真正的 Agent Host;其他调用方只应
|
|
16
16
|
* 提供同样的服务器状态快照、工具目录和调用能力,不要在这里复制连接状态。
|
|
17
17
|
*
|
|
18
18
|
* 这里沿用 MCP 的官方术语:Host 是承载 Agent 的应用,Client 是 Host 内连接
|
|
@@ -203,7 +203,7 @@ function errorMessage(result: McpCallResult): string {
|
|
|
203
203
|
/**
|
|
204
204
|
* 把当前已连接且获授权的 MCP 工具转换成 Pi 候选工具。
|
|
205
205
|
*
|
|
206
|
-
*
|
|
206
|
+
* Tool Surface 在 Runtime 准备时调用它。调用方应传入
|
|
207
207
|
* Agent Host,以及同一 Runtime 快照中的 MCP 配置;未就绪、未配置或重复 URL
|
|
208
208
|
* 的连接不会进入模型工具目录。
|
|
209
209
|
*
|
package/src/pi/tool/schedule.ts
CHANGED
|
@@ -71,6 +71,14 @@ const updateScheduleParameters = Type.Object({
|
|
|
71
71
|
label: Type.Optional(Type.String()),
|
|
72
72
|
timezone: Type.Optional(Type.String()),
|
|
73
73
|
});
|
|
74
|
+
const changeScheduleAgentParameters = Type.Object({
|
|
75
|
+
id: Type.String({
|
|
76
|
+
description: "The exact schedule id returned by `list_schedules`.",
|
|
77
|
+
}),
|
|
78
|
+
userAgentId: Type.String({
|
|
79
|
+
description: "The exact User Agent id selected by the user.",
|
|
80
|
+
}),
|
|
81
|
+
});
|
|
74
82
|
|
|
75
83
|
function result<T>(details: T): AgentToolResult<T> {
|
|
76
84
|
return {
|
|
@@ -82,11 +90,11 @@ function result<T>(details: T): AgentToolResult<T> {
|
|
|
82
90
|
function candidate<T extends TSchema>(
|
|
83
91
|
tool: AgentTool<T>,
|
|
84
92
|
options: Partial<
|
|
85
|
-
Pick<PiToolCandidate, "requiredExecutionLevel" | "summary">
|
|
93
|
+
Pick<PiToolCandidate, "owner" | "requiredExecutionLevel" | "summary">
|
|
86
94
|
> = {},
|
|
87
95
|
): PiToolCandidate {
|
|
88
96
|
return {
|
|
89
|
-
owner: "runtime-base",
|
|
97
|
+
owner: options.owner ?? "runtime-base",
|
|
90
98
|
authorized: true,
|
|
91
99
|
requiredExecutionLevel: options.requiredExecutionLevel ?? "safe",
|
|
92
100
|
source: "action",
|
|
@@ -194,5 +202,41 @@ export function schedulePiToolCandidates(
|
|
|
194
202
|
summary: "Cancel a scheduled task",
|
|
195
203
|
},
|
|
196
204
|
),
|
|
205
|
+
candidate(
|
|
206
|
+
{
|
|
207
|
+
name: "list_user_agents",
|
|
208
|
+
label: "List User Agents",
|
|
209
|
+
description:
|
|
210
|
+
"List the enabled User Agents available for scheduled tasks. " +
|
|
211
|
+
"Use this before changing a schedule Agent.",
|
|
212
|
+
parameters: noParameters,
|
|
213
|
+
async execute(_toolCallId, _input, signal) {
|
|
214
|
+
signal?.throwIfAborted();
|
|
215
|
+
return result({ agents: await schedule.listAgents() });
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
{ owner: "schedule-host" },
|
|
219
|
+
),
|
|
220
|
+
candidate(
|
|
221
|
+
{
|
|
222
|
+
name: "change_schedule_agent",
|
|
223
|
+
label: "Change schedule Agent",
|
|
224
|
+
description:
|
|
225
|
+
"Change which User Agent executes one scheduled task without " +
|
|
226
|
+
"changing its id or history. Call `list_schedules` and " +
|
|
227
|
+
"`list_user_agents` first and use exact ids; ask the user when " +
|
|
228
|
+
"the target is ambiguous.",
|
|
229
|
+
parameters: changeScheduleAgentParameters,
|
|
230
|
+
async execute(_toolCallId, input, signal) {
|
|
231
|
+
signal?.throwIfAborted();
|
|
232
|
+
const { ok } = await schedule.changeAgent(
|
|
233
|
+
input.id,
|
|
234
|
+
input.userAgentId,
|
|
235
|
+
);
|
|
236
|
+
return result({ updated: ok, id: input.id });
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
{ owner: "schedule-host" },
|
|
240
|
+
),
|
|
197
241
|
];
|
|
198
242
|
}
|
package/src/pi/tool/skill.ts
CHANGED
|
@@ -242,7 +242,7 @@ function resourceResult(
|
|
|
242
242
|
/**
|
|
243
243
|
* 为已启用的 Skill 创建按需加载说明、资源和可选脚本的 Pi 候选工具。
|
|
244
244
|
*
|
|
245
|
-
* Worker 的 Skill Plugin
|
|
245
|
+
* Worker 的 Skill Plugin 在准备 Runtime 能力时调用它。调用方只传入已授权绑定;
|
|
246
246
|
* 没有绑定时不公开工具,没有 Worker Loader 或脚本策略时不公开脚本执行工具。
|
|
247
247
|
*
|
|
248
248
|
* 这里的 “Skill” 是按需加载的任务说明包,“Source” 负责列出和读取包,“资源”
|