@springbrand/agent-runtime 0.1.3-alpha.0 → 0.1.3-alpha.10
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 +12 -3
- package/src/adapter/cloudflare/index.ts +56 -0
- package/src/adapter/cloudflare/resources/runtime-resources.ts +89 -0
- package/src/adapter/cloudflare/sandbox/adapter.ts +1513 -0
- package/src/adapter/cloudflare/sandbox/id.ts +23 -0
- package/src/adapter/cloudflare/sandbox/policy.ts +15 -0
- package/src/adapter/cloudflare/subagent/definition.ts +574 -0
- package/src/adapter/cloudflare/subagent/runner.ts +175 -0
- package/src/adapter/cloudflare/subagent/tools.ts +254 -0
- package/src/adapter/cloudflare/universal-agent/hooks.ts +35 -0
- package/src/adapter/cloudflare/universal-agent/preparation.ts +277 -0
- package/src/adapter/cloudflare/universal-agent/tools.ts +80 -0
- package/src/adapter/cloudflare/workspace/git-fs.ts +178 -0
- package/src/adapter/cloudflare/workspace/publisher.ts +31 -0
- package/src/adapter/cloudflare/workspace/scoped-workspace.ts +376 -0
- package/src/adapter/cloudflare/workspace/version-control.ts +374 -0
- package/src/agent-tool-runtime.ts +152 -0
- package/src/db/agent-tool.repo.ts +27 -0
- package/src/db/index.ts +33 -0
- package/src/db/interaction.repo.ts +185 -0
- package/src/db/schema.ts +25 -1
- package/src/db/submission.repo.ts +63 -1
- package/src/index.ts +61 -27
- package/src/kernel/approval-lifecycle.ts +41 -6
- package/src/kernel/bindings.ts +99 -12
- package/src/kernel/extensions.ts +1 -1
- package/src/kernel/interaction-lifecycle.ts +395 -0
- package/src/kernel/profile.ts +3 -4
- package/src/kernel/public-contracts.ts +2 -0
- package/src/kernel/recoverable-chat-agent.ts +104 -6
- package/src/kernel/runtime-assembly-view.ts +37 -0
- package/src/kernel/runtime-assembly.ts +41 -0
- package/src/kernel/runtime-config.ts +4 -0
- package/src/kernel/runtime-load.ts +191 -0
- package/src/kernel/state.ts +12 -1
- package/src/kernel/submission-lifecycle.ts +33 -2
- package/src/layers/orchestration/temporary-agent/core.ts +12 -1
- package/src/layers/orchestration/temporary-agent/runner.ts +1 -67
- package/src/lib/mcp.ts +7 -3
- package/src/lib/prompt.ts +1 -1
- package/src/lib/telemetry-dev.ts +7 -4
- package/src/pi/assembly/context.ts +4 -6
- package/src/pi/assembly/extensions.ts +11 -22
- package/src/pi/assembly/snapshot.ts +17 -9
- package/src/pi/message/contract.ts +7 -0
- package/src/pi/message/conversion.ts +9 -1
- package/src/pi/runtime-adapter/assembly.ts +42 -97
- package/src/pi/runtime-adapter/execution.ts +216 -21
- package/src/pi/runtime-adapter/index.ts +24 -8
- package/src/pi/runtime-adapter/models.ts +382 -35
- package/src/pi/runtime-adapter/recovery.ts +188 -1
- package/src/pi/runtime-adapter/transcript.ts +61 -3
- package/src/pi/tool/ai-adapter.ts +58 -1
- package/src/pi/tool/base.ts +190 -12
- package/src/pi/tool/compiler.ts +39 -33
- package/src/pi/tool/core-host.ts +28 -30
- package/src/pi/tool/core.ts +37 -124
- package/src/pi/tool/gateway.ts +54 -0
- package/src/pi/tool/index.ts +2 -0
- package/src/pi/tool/mcp.ts +98 -70
- package/src/pi/tool/schedule.ts +86 -20
- package/src/pi/tool/skill.ts +126 -420
- package/src/pi/tool/subagent.ts +14 -2
- package/src/pi/tool/web-fetch.ts +281 -0
- package/src/pi/tool/web-search/api.ts +34 -18
- package/src/pi/tool/web-search/web-search.ts +0 -1
- package/src/pi/tool/workspace-revision.ts +64 -0
- package/src/pi/tool/workspace-sandbox.ts +105 -263
- package/src/pi/turn/index.ts +20 -0
- package/src/pi/turn/interaction.ts +181 -0
- package/src/pi/turn/tool-recovery.ts +244 -1
- package/src/runtime-agent-context.ts +112 -0
- package/src/runtime-agent.ts +568 -321
- package/src/runtime-assembler.ts +797 -0
- package/src/runtime-definition.ts +175 -0
- package/src/runtime.ts +840 -208
- package/src/tool-registry.ts +143 -0
- package/src/workspace-versioning.ts +46 -0
- package/src/plugins.ts +0 -1033
package/src/pi/tool/mcp.ts
CHANGED
|
@@ -9,10 +9,26 @@ interface McpCallResult {
|
|
|
9
9
|
isError?: boolean;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
export interface PiDiscoveredMcpTool {
|
|
13
|
+
readonly serverId: string;
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly title?: string;
|
|
16
|
+
readonly description?: string;
|
|
17
|
+
readonly inputSchema?: unknown;
|
|
18
|
+
readonly annotations?: { readonly title?: string } & Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface PiMcpCandidatePolicy {
|
|
22
|
+
readonly owner: string;
|
|
23
|
+
readonly modelName: string;
|
|
24
|
+
readonly requiredExecutionLevel: PiToolCandidate["requiredExecutionLevel"];
|
|
25
|
+
readonly requiredExecutionLevelForInput?: PiToolCandidate["requiredExecutionLevelForInput"];
|
|
26
|
+
}
|
|
27
|
+
|
|
12
28
|
/**
|
|
13
29
|
* Pi 的 MCP 适配器所需的最小 Host 能力。
|
|
14
30
|
*
|
|
15
|
-
*
|
|
31
|
+
* Tool Surface 在收集本轮工具时传入真正的 Agent Host;其他调用方只应
|
|
16
32
|
* 提供同样的服务器状态快照、工具目录和调用能力,不要在这里复制连接状态。
|
|
17
33
|
*
|
|
18
34
|
* 这里沿用 MCP 的官方术语:Host 是承载 Agent 的应用,Client 是 Host 内连接
|
|
@@ -43,7 +59,8 @@ export interface PiMcpHost {
|
|
|
43
59
|
* 参数和中止信号必须原样交给 Agents SDK,避免另造一套传输生命周期。
|
|
44
60
|
*/
|
|
45
61
|
callTool(
|
|
46
|
-
|
|
62
|
+
params: Parameters<MCPClientManager["callTool"]>[0],
|
|
63
|
+
options?: { signal?: AbortSignal },
|
|
47
64
|
): Promise<unknown>;
|
|
48
65
|
};
|
|
49
66
|
}
|
|
@@ -200,16 +217,76 @@ function errorMessage(result: McpCallResult): string {
|
|
|
200
217
|
: "MCP tool call failed";
|
|
201
218
|
}
|
|
202
219
|
|
|
220
|
+
/** 共享 MCP 结果投影;Gateway 与用户配置的 Remote MCP 均经过此边界。 */
|
|
221
|
+
export function createPiMcpToolCandidate(
|
|
222
|
+
mcpTool: PiDiscoveredMcpTool,
|
|
223
|
+
callTool: (
|
|
224
|
+
input: Readonly<Record<string, unknown>>,
|
|
225
|
+
signal?: AbortSignal,
|
|
226
|
+
) => Promise<unknown>,
|
|
227
|
+
policy: PiMcpCandidatePolicy,
|
|
228
|
+
): PiToolCandidate {
|
|
229
|
+
const label =
|
|
230
|
+
mcpTool.title ??
|
|
231
|
+
mcpTool.annotations?.title ??
|
|
232
|
+
mcpTool.name;
|
|
233
|
+
const tool: AgentTool<any, {
|
|
234
|
+
kind: "mcp";
|
|
235
|
+
toolName: string;
|
|
236
|
+
}> = {
|
|
237
|
+
name: policy.modelName,
|
|
238
|
+
label,
|
|
239
|
+
description: mcpTool.description ?? label,
|
|
240
|
+
parameters: structuredClone(
|
|
241
|
+
mcpTool.inputSchema ?? {
|
|
242
|
+
type: "object",
|
|
243
|
+
additionalProperties: true,
|
|
244
|
+
},
|
|
245
|
+
) as AgentTool["parameters"],
|
|
246
|
+
execute: async (_toolCallId, args, signal) => {
|
|
247
|
+
const result = normalizeCallResult(
|
|
248
|
+
await callTool(args as Record<string, unknown>, signal),
|
|
249
|
+
);
|
|
250
|
+
if (result.isError) throw new Error(errorMessage(result));
|
|
251
|
+
const structuredContent = result.structuredContent === undefined
|
|
252
|
+
? undefined
|
|
253
|
+
: publicMcpValue(result.structuredContent);
|
|
254
|
+
const content = resultContent({ ...result, structuredContent });
|
|
255
|
+
return {
|
|
256
|
+
content,
|
|
257
|
+
details: {
|
|
258
|
+
kind: "mcp",
|
|
259
|
+
toolName: mcpTool.name,
|
|
260
|
+
output: structuredContent ?? content,
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
return {
|
|
266
|
+
owner: policy.owner,
|
|
267
|
+
tool,
|
|
268
|
+
summary: label,
|
|
269
|
+
requiredExecutionLevel: policy.requiredExecutionLevel,
|
|
270
|
+
...(policy.requiredExecutionLevelForInput
|
|
271
|
+
? {
|
|
272
|
+
requiredExecutionLevelForInput:
|
|
273
|
+
policy.requiredExecutionLevelForInput,
|
|
274
|
+
}
|
|
275
|
+
: {}),
|
|
276
|
+
source: "action",
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
203
280
|
/**
|
|
204
|
-
*
|
|
281
|
+
* 把当前已配置且 ready 的 MCP 工具转换成 Pi 候选工具。
|
|
205
282
|
*
|
|
206
|
-
*
|
|
283
|
+
* Tool Surface 在 Runtime 准备时调用它。调用方应传入
|
|
207
284
|
* Agent Host,以及同一 Runtime 快照中的 MCP 配置;未就绪、未配置或重复 URL
|
|
208
285
|
* 的连接不会进入模型工具目录。
|
|
209
286
|
*
|
|
210
287
|
* “候选工具”是进入 Pi 编译和统一治理前的内部描述。连接、凭据和恢复由 Host
|
|
211
|
-
* 与 Agents SDK
|
|
212
|
-
* 远端 Server 提供的 annotations
|
|
288
|
+
* 与 Agents SDK 管理;本函数只做动态连接状态过滤、Schema 转接和公开结果投影。
|
|
289
|
+
* 远端 Server 提供的 annotations 只是提示,不是本地审批边界,所以所有动态
|
|
213
290
|
* MCP 工具继续标为高风险,不能据此绕过审批。
|
|
214
291
|
*
|
|
215
292
|
* `Host`、`Pi`、`Runtime Snapshot` 与“候选工具”见 `../../index.ts`。
|
|
@@ -249,71 +326,22 @@ export function createPiMcpToolCandidates(
|
|
|
249
326
|
state: "ready",
|
|
250
327
|
})
|
|
251
328
|
.filter((tool) => selectedIds.has(tool.serverId))
|
|
252
|
-
.map((mcpTool)
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
toolName: string;
|
|
260
|
-
}> = {
|
|
261
|
-
name: modelVisibleName(mcpTool.serverId, mcpTool.name),
|
|
262
|
-
label,
|
|
263
|
-
description: mcpTool.description ?? label,
|
|
264
|
-
parameters: structuredClone(
|
|
265
|
-
mcpTool.inputSchema ?? {
|
|
266
|
-
type: "object",
|
|
267
|
-
additionalProperties: true,
|
|
268
|
-
},
|
|
269
|
-
) as AgentTool["parameters"],
|
|
270
|
-
// 作用:执行模型选中的远端 MCP 工具并返回公开结果。
|
|
271
|
-
// 调用:Pi 在参数校验和统一工具治理通过后调用。
|
|
272
|
-
// 原因:调用交给 Agents SDK,并在边界处统一处理错误、
|
|
273
|
-
// 私有元数据和非原生内容。
|
|
274
|
-
execute: async (_toolCallId, args, signal) => {
|
|
275
|
-
const result = normalizeCallResult(
|
|
276
|
-
await host.mcp.callTool(
|
|
277
|
-
{
|
|
278
|
-
serverId: mcpTool.serverId,
|
|
279
|
-
name: mcpTool.name,
|
|
280
|
-
arguments: args as Record<string, unknown>,
|
|
281
|
-
},
|
|
282
|
-
undefined,
|
|
283
|
-
{ signal },
|
|
284
|
-
),
|
|
285
|
-
);
|
|
286
|
-
if (result.isError) {
|
|
287
|
-
throw new Error(errorMessage(result));
|
|
288
|
-
}
|
|
289
|
-
const structuredContent =
|
|
290
|
-
result.structuredContent === undefined
|
|
291
|
-
? undefined
|
|
292
|
-
: publicMcpValue(result.structuredContent);
|
|
293
|
-
const content = resultContent({
|
|
294
|
-
...result,
|
|
295
|
-
structuredContent,
|
|
296
|
-
});
|
|
297
|
-
return {
|
|
298
|
-
content,
|
|
299
|
-
details: {
|
|
300
|
-
kind: "mcp",
|
|
301
|
-
toolName: mcpTool.name,
|
|
302
|
-
output: structuredContent ?? content,
|
|
303
|
-
},
|
|
304
|
-
};
|
|
329
|
+
.map((mcpTool) => createPiMcpToolCandidate(
|
|
330
|
+
mcpTool,
|
|
331
|
+
(args, signal) => host.mcp.callTool(
|
|
332
|
+
{
|
|
333
|
+
serverId: mcpTool.serverId,
|
|
334
|
+
name: mcpTool.name,
|
|
335
|
+
arguments: args,
|
|
305
336
|
},
|
|
306
|
-
|
|
307
|
-
|
|
337
|
+
{ signal },
|
|
338
|
+
),
|
|
339
|
+
{
|
|
308
340
|
owner: `mcp:${mcpTool.serverId}`,
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
// MCP annotations are supplied by the remote server and are not an
|
|
313
|
-
// authorization boundary. Until the Host supplies trusted per-method
|
|
314
|
-
// policy, every dynamic MCP method must take the approval path.
|
|
341
|
+
modelName: modelVisibleName(mcpTool.serverId, mcpTool.name),
|
|
342
|
+
// Remote MCP annotations are untrusted; all user-configured methods
|
|
343
|
+
// retain the existing high-risk approval policy.
|
|
315
344
|
requiredExecutionLevel: "high",
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
});
|
|
345
|
+
},
|
|
346
|
+
));
|
|
319
347
|
}
|
package/src/pi/tool/schedule.ts
CHANGED
|
@@ -10,6 +10,10 @@ import type {
|
|
|
10
10
|
import type { ScheduleSpec } from "../../kernel/receipts";
|
|
11
11
|
import { serializeOutput } from "../../lib/artifacts";
|
|
12
12
|
import type { PiToolCandidate } from "./compiler";
|
|
13
|
+
import {
|
|
14
|
+
toolRegistryFromPiCandidates,
|
|
15
|
+
type ToolRegistry,
|
|
16
|
+
} from "../../tool-registry";
|
|
13
17
|
|
|
14
18
|
const scheduleTriggerParameters = Type.Union([
|
|
15
19
|
Type.Object({
|
|
@@ -71,6 +75,14 @@ const updateScheduleParameters = Type.Object({
|
|
|
71
75
|
label: Type.Optional(Type.String()),
|
|
72
76
|
timezone: Type.Optional(Type.String()),
|
|
73
77
|
});
|
|
78
|
+
const changeScheduleAgentParameters = Type.Object({
|
|
79
|
+
id: Type.String({
|
|
80
|
+
description: "The exact schedule id returned by `list_schedules`.",
|
|
81
|
+
}),
|
|
82
|
+
userAgentId: Type.String({
|
|
83
|
+
description: "The exact User Agent id selected by the user.",
|
|
84
|
+
}),
|
|
85
|
+
});
|
|
74
86
|
|
|
75
87
|
function result<T>(details: T): AgentToolResult<T> {
|
|
76
88
|
return {
|
|
@@ -82,15 +94,20 @@ function result<T>(details: T): AgentToolResult<T> {
|
|
|
82
94
|
function candidate<T extends TSchema>(
|
|
83
95
|
tool: AgentTool<T>,
|
|
84
96
|
options: Partial<
|
|
85
|
-
Pick<
|
|
97
|
+
Pick<
|
|
98
|
+
PiToolCandidate,
|
|
99
|
+
"alwaysRequiresApproval" | "owner" | "requiredExecutionLevel" | "summary"
|
|
100
|
+
>
|
|
86
101
|
> = {},
|
|
87
102
|
): PiToolCandidate {
|
|
88
103
|
return {
|
|
89
|
-
owner: "runtime-base",
|
|
90
|
-
authorized: true,
|
|
104
|
+
owner: options.owner ?? "runtime-base",
|
|
91
105
|
requiredExecutionLevel: options.requiredExecutionLevel ?? "safe",
|
|
92
106
|
source: "action",
|
|
93
107
|
tool,
|
|
108
|
+
...(options.alwaysRequiresApproval
|
|
109
|
+
? { alwaysRequiresApproval: true }
|
|
110
|
+
: {}),
|
|
94
111
|
...(options.summary ? { summary: options.summary } : {}),
|
|
95
112
|
};
|
|
96
113
|
}
|
|
@@ -99,24 +116,30 @@ export function schedulePiToolCandidates(
|
|
|
99
116
|
schedule: RuntimeSchedulePort,
|
|
100
117
|
): PiToolCandidate[] {
|
|
101
118
|
return [
|
|
102
|
-
candidate(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
signal
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
candidate(
|
|
120
|
+
{
|
|
121
|
+
name: "schedule",
|
|
122
|
+
label: "Schedule prompt",
|
|
123
|
+
description:
|
|
124
|
+
"Schedule a prompt to run LATER, autonomously. Use when the user asks to be reminded, or to run something after a delay / at a time / on a recurring basis. The user always reviews the proposed schedule before it is created. The scheduled prompt runs in its own dedicated session at each trigger with NO memory of this conversation, so phrase `prompt` as a fully standalone instruction. After scheduling, tell the user what you set.",
|
|
125
|
+
parameters: scheduleParameters,
|
|
126
|
+
async execute(_toolCallId, input, signal) {
|
|
127
|
+
signal?.throwIfAborted();
|
|
128
|
+
const spec: ScheduleSpec = {
|
|
129
|
+
trigger: input.trigger,
|
|
130
|
+
job: { kind: "prompt", prompt: input.prompt },
|
|
131
|
+
label: input.label,
|
|
132
|
+
...(input.timezone ? { tz: input.timezone } : {}),
|
|
133
|
+
};
|
|
134
|
+
const { id } = await schedule.create(spec);
|
|
135
|
+
return result({ scheduled: true, id });
|
|
136
|
+
},
|
|
118
137
|
},
|
|
119
|
-
|
|
138
|
+
{
|
|
139
|
+
alwaysRequiresApproval: true,
|
|
140
|
+
summary: "Create a scheduled task",
|
|
141
|
+
},
|
|
142
|
+
),
|
|
120
143
|
candidate({
|
|
121
144
|
name: "list_schedules",
|
|
122
145
|
label: "List schedules",
|
|
@@ -194,5 +217,48 @@ export function schedulePiToolCandidates(
|
|
|
194
217
|
summary: "Cancel a scheduled task",
|
|
195
218
|
},
|
|
196
219
|
),
|
|
220
|
+
candidate(
|
|
221
|
+
{
|
|
222
|
+
name: "list_user_agents",
|
|
223
|
+
label: "List User Agents",
|
|
224
|
+
description:
|
|
225
|
+
"List the enabled User Agents available for scheduled tasks. " +
|
|
226
|
+
"Use this before changing a schedule Agent.",
|
|
227
|
+
parameters: noParameters,
|
|
228
|
+
async execute(_toolCallId, _input, signal) {
|
|
229
|
+
signal?.throwIfAborted();
|
|
230
|
+
return result({ agents: await schedule.listAgents() });
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
{ owner: "schedule-host" },
|
|
234
|
+
),
|
|
235
|
+
candidate(
|
|
236
|
+
{
|
|
237
|
+
name: "change_schedule_agent",
|
|
238
|
+
label: "Change schedule Agent",
|
|
239
|
+
description:
|
|
240
|
+
"Change which User Agent executes one scheduled task without " +
|
|
241
|
+
"changing its id or history. Call `list_schedules` and " +
|
|
242
|
+
"`list_user_agents` first and use exact ids; ask the user when " +
|
|
243
|
+
"the target is ambiguous.",
|
|
244
|
+
parameters: changeScheduleAgentParameters,
|
|
245
|
+
async execute(_toolCallId, input, signal) {
|
|
246
|
+
signal?.throwIfAborted();
|
|
247
|
+
const { ok } = await schedule.changeAgent(
|
|
248
|
+
input.id,
|
|
249
|
+
input.userAgentId,
|
|
250
|
+
);
|
|
251
|
+
return result({ updated: ok, id: input.id });
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
{ owner: "schedule-host" },
|
|
255
|
+
),
|
|
197
256
|
];
|
|
198
257
|
}
|
|
258
|
+
|
|
259
|
+
/** 从 {@link RuntimeSchedulePort} 生成定时任务 Tool 集。 */
|
|
260
|
+
export function createScheduleTools(
|
|
261
|
+
schedule: RuntimeSchedulePort,
|
|
262
|
+
): ToolRegistry {
|
|
263
|
+
return toolRegistryFromPiCandidates(schedulePiToolCandidates(schedule));
|
|
264
|
+
}
|