@springbrand/agent-runtime 0.1.3-alpha.0 → 0.1.3-alpha.2
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/db/schema.ts +10 -1
- package/src/db/submission.repo.ts +34 -1
- package/src/index.ts +9 -11
- package/src/kernel/bindings.ts +27 -6
- package/src/kernel/extensions.ts +1 -1
- package/src/kernel/profile.ts +3 -4
- package/src/kernel/recoverable-chat-agent.ts +82 -4
- package/src/kernel/state.ts +4 -0
- package/src/kernel/submission-lifecycle.ts +3 -2
- package/src/layers/orchestration/temporary-agent/runner.ts +0 -65
- package/src/lib/prompt.ts +1 -1
- package/src/pi/assembly/context.ts +1 -3
- package/src/pi/assembly/snapshot.ts +17 -9
- package/src/pi/runtime-adapter/assembly.ts +25 -86
- package/src/pi/runtime-adapter/execution.ts +107 -12
- package/src/pi/runtime-adapter/index.ts +8 -3
- package/src/pi/runtime-adapter/models.ts +221 -29
- package/src/pi/runtime-adapter/transcript.ts +61 -3
- package/src/pi/tool/ai-adapter.ts +58 -1
- package/src/pi/tool/base.ts +112 -2
- package/src/pi/tool/compiler.ts +5 -32
- package/src/pi/tool/core-host.ts +28 -30
- package/src/pi/tool/core.ts +25 -122
- package/src/pi/tool/mcp.ts +2 -2
- package/src/pi/tool/schedule.ts +46 -2
- package/src/pi/tool/skill.ts +112 -420
- package/src/pi/tool/web-fetch.ts +282 -0
- package/src/pi/tool/web-search/api.ts +34 -18
- package/src/pi/tool/workspace-sandbox.ts +92 -258
- package/src/plugins.ts +358 -531
- package/src/runtime.ts +195 -44
package/src/pi/tool/compiler.ts
CHANGED
|
@@ -6,7 +6,6 @@ import type {
|
|
|
6
6
|
import type { ApprovalReceipt } from "../../kernel/receipts";
|
|
7
7
|
import { boundDurableToolOutput } from "../../layers/context/budget/gate";
|
|
8
8
|
import {
|
|
9
|
-
EXECUTION_LEVELS,
|
|
10
9
|
type ExecutionLevel,
|
|
11
10
|
} from "../../lib/execution-level";
|
|
12
11
|
|
|
@@ -14,7 +13,7 @@ import {
|
|
|
14
13
|
|
|
15
14
|
// #region Public contracts
|
|
16
15
|
|
|
17
|
-
/**
|
|
16
|
+
/** 描述一个尚未进入最终 Tool Surface 和结算包装的 Pi 工具。 */
|
|
18
17
|
export interface PiToolCandidate {
|
|
19
18
|
readonly owner: string;
|
|
20
19
|
readonly authorized: boolean;
|
|
@@ -26,7 +25,6 @@ export interface PiToolCandidate {
|
|
|
26
25
|
|
|
27
26
|
/** 控制候选 Pi 工具如何被编译为可执行工具集。 */
|
|
28
27
|
export interface CompilePiToolsOptions {
|
|
29
|
-
readonly deny?: readonly string[];
|
|
30
28
|
readonly governance?: PiToolGovernance;
|
|
31
29
|
readonly settle: (
|
|
32
30
|
call: SettledPiToolCall,
|
|
@@ -248,7 +246,7 @@ export function createPiToolGovernance(
|
|
|
248
246
|
}
|
|
249
247
|
|
|
250
248
|
// 为一个候选工具包上输出限额、持久化结算、重试治理和遥测。
|
|
251
|
-
// `compilePiTools()`
|
|
249
|
+
// `compilePiTools()` 对最终 Tool Surface 中的每个候选项调用。
|
|
252
250
|
// 一个共享包装边界可确保所有工具无论成功还是失败都经过 settle,不能由各工具自行选择是否持久化。
|
|
253
251
|
function governedTool(
|
|
254
252
|
candidate: PiToolCandidate,
|
|
@@ -402,11 +400,9 @@ function governedTool(
|
|
|
402
400
|
}
|
|
403
401
|
|
|
404
402
|
/**
|
|
405
|
-
*
|
|
403
|
+
* 把已经 Tool Surface 最终化的候选项包成可执行工具集。
|
|
406
404
|
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
* 工具名是模型调用和结算的唯一键,所以冲突必须在组装时失败,不能用后来者静默覆盖。
|
|
405
|
+
* `PiTurnAdapter` 在每个 Turn 及手动重试时用它创建执行治理包装。
|
|
410
406
|
*/
|
|
411
407
|
export function compilePiTools(
|
|
412
408
|
candidates: readonly PiToolCandidate[],
|
|
@@ -415,30 +411,7 @@ export function compilePiTools(
|
|
|
415
411
|
if (!options?.settle) {
|
|
416
412
|
throw new Error("Pi Tool settlement port is required");
|
|
417
413
|
}
|
|
418
|
-
|
|
419
|
-
const tools: AgentTool<any, any>[] = [];
|
|
420
|
-
const owners = new Map<string, string>();
|
|
421
|
-
|
|
422
|
-
for (const candidate of candidates) {
|
|
423
|
-
if (!EXECUTION_LEVELS.includes(candidate.requiredExecutionLevel)) {
|
|
424
|
-
throw new Error(
|
|
425
|
-
`Pi Tool "${candidate.tool.name}" has invalid requiredExecutionLevel`,
|
|
426
|
-
);
|
|
427
|
-
}
|
|
428
|
-
if (!candidate.authorized || deny.has(candidate.tool.name)) continue;
|
|
429
|
-
|
|
430
|
-
const existingOwner = owners.get(candidate.tool.name);
|
|
431
|
-
if (existingOwner !== undefined) {
|
|
432
|
-
throw new Error(
|
|
433
|
-
`duplicate tool key "${candidate.tool.name}" (${candidate.owner} collides with ${existingOwner})`,
|
|
434
|
-
);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
owners.set(candidate.tool.name, candidate.owner);
|
|
438
|
-
tools.push(governedTool(candidate, options));
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
return tools;
|
|
414
|
+
return candidates.map((candidate) => governedTool(candidate, options));
|
|
442
415
|
}
|
|
443
416
|
|
|
444
417
|
// #endregion
|
package/src/pi/tool/core-host.ts
CHANGED
|
@@ -1,52 +1,50 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createCodemodeRuntime,
|
|
3
|
-
DynamicWorkerExecutor,
|
|
4
|
-
truncateResult,
|
|
5
|
-
} from "@cloudflare/codemode";
|
|
6
1
|
import {
|
|
7
2
|
createWorkspaceStateBackend,
|
|
8
3
|
type WorkspaceFsLike,
|
|
9
4
|
} from "@cloudflare/shell";
|
|
10
|
-
import {
|
|
11
|
-
import type {
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
import { createExecuteRuntime } from "@cloudflare/think/tools/execute";
|
|
6
|
+
import type {
|
|
7
|
+
RuntimeCodeExecutionPort,
|
|
8
|
+
WorkspacePort,
|
|
9
|
+
} from "../../kernel/bindings";
|
|
14
10
|
|
|
15
11
|
// 本文件沿用 `../../index.ts` 入口定义的 Workspace、Port 和 Tool Candidate 术语。
|
|
16
12
|
|
|
17
13
|
const CODEMODE_SANDBOX_TIMEOUT_MS = 55_000;
|
|
18
14
|
|
|
19
15
|
/**
|
|
20
|
-
* 把宿主的 Worker Loader、出站网络和 Workspace
|
|
16
|
+
* 把宿主的 Worker Loader、出站网络和 Workspace 组装成代码执行 Port。
|
|
21
17
|
*
|
|
22
18
|
* Worker 宿主在具备 Durable Object state 和完整平台绑定时调用,然后把返回值交给 Runtime 工具组装。
|
|
23
19
|
*
|
|
24
|
-
*
|
|
20
|
+
* Think 的独立 execute factory 接受显式宿主参数,不要求 Agent 继承 Think;这里只借它组装 Codemode Runtime、Dynamic Worker executor 和已限定范围的 Workspace state connector。
|
|
25
21
|
*/
|
|
26
|
-
export function
|
|
22
|
+
export function createWorkspaceCodeExecutionPort(options: {
|
|
27
23
|
readonly ctx: DurableObjectState;
|
|
28
24
|
readonly loader: WorkerLoader;
|
|
29
25
|
readonly outbound: Fetcher;
|
|
30
26
|
readonly workspace: WorkspacePort;
|
|
31
|
-
}):
|
|
32
|
-
const
|
|
27
|
+
}): RuntimeCodeExecutionPort {
|
|
28
|
+
const { tool } = createExecuteRuntime({
|
|
33
29
|
ctx: options.ctx,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
new StateConnector(
|
|
42
|
-
options.ctx,
|
|
43
|
-
createWorkspaceStateBackend(
|
|
44
|
-
options.workspace as unknown as WorkspaceFsLike,
|
|
45
|
-
),
|
|
46
|
-
),
|
|
47
|
-
],
|
|
30
|
+
loader: options.loader,
|
|
31
|
+
globalOutbound: options.outbound,
|
|
32
|
+
// 先于外层 60s 截止结束,给 Runtime RPC 结算和 Worker 释放留出时间。
|
|
33
|
+
timeout: CODEMODE_SANDBOX_TIMEOUT_MS,
|
|
34
|
+
state: createWorkspaceStateBackend(
|
|
35
|
+
options.workspace as unknown as WorkspaceFsLike,
|
|
36
|
+
),
|
|
48
37
|
name: "execute",
|
|
49
|
-
transformResult: truncateResult,
|
|
50
38
|
});
|
|
51
|
-
|
|
39
|
+
const execute = tool.execute;
|
|
40
|
+
if (typeof execute !== "function") {
|
|
41
|
+
throw new Error("Think createExecuteRuntime returned a non-executable tool");
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
execute: (input) => Promise.resolve(execute(input, {
|
|
45
|
+
toolCallId: "execute",
|
|
46
|
+
messages: [],
|
|
47
|
+
context: undefined,
|
|
48
|
+
})),
|
|
49
|
+
};
|
|
52
50
|
}
|
package/src/pi/tool/core.ts
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
|
+
import { createQuickActionTools } from "@cloudflare/think/tools/browser";
|
|
1
2
|
import type {
|
|
2
3
|
AgentTool,
|
|
3
4
|
AgentToolResult,
|
|
4
5
|
} from "@earendil-works/pi-agent-core";
|
|
5
6
|
import { Type } from "@earendil-works/pi-ai";
|
|
6
|
-
import type {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
browserMarkdown,
|
|
11
|
-
browserScrape,
|
|
12
|
-
type QuickActionPage,
|
|
13
|
-
} from "agents/browser";
|
|
14
|
-
import type { RuntimeBrowserPort } from "../../kernel/bindings";
|
|
7
|
+
import type {
|
|
8
|
+
RuntimeBrowserPort,
|
|
9
|
+
RuntimeCodeExecutionPort,
|
|
10
|
+
} from "../../kernel/bindings";
|
|
15
11
|
import { serializeOutput } from "../../lib/artifacts";
|
|
16
12
|
import type { PiLoadedExtension } from "../assembly/extensions";
|
|
13
|
+
import { aiToolToPi } from "./ai-adapter";
|
|
17
14
|
import type { PiToolCandidate } from "./compiler";
|
|
18
15
|
|
|
19
16
|
// 本文件沿用 `../../index.ts` 入口定义的 Extension、Port 和 Tool Candidate 术语。
|
|
@@ -30,128 +27,33 @@ function result(details: unknown): AgentToolResult<unknown> {
|
|
|
30
27
|
|
|
31
28
|
// #region Browser Quick Actions
|
|
32
29
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
const BROWSER_TOOL_LABELS: Readonly<Record<string, string>> = {
|
|
31
|
+
browser_markdown: "Read web page",
|
|
32
|
+
browser_extract: "Extract web data",
|
|
33
|
+
browser_links: "List web links",
|
|
34
|
+
browser_scrape: "Scrape web elements",
|
|
36
35
|
};
|
|
37
|
-
const browserPageParameters = Type.Object(pageParameters);
|
|
38
|
-
const browserExtractParameters = Type.Object({
|
|
39
|
-
...pageParameters,
|
|
40
|
-
prompt: Type.Optional(Type.String({ minLength: 1 })),
|
|
41
|
-
schema: Type.Optional(Type.Unknown()),
|
|
42
|
-
});
|
|
43
|
-
const browserScrapeParameters = Type.Object({
|
|
44
|
-
...pageParameters,
|
|
45
|
-
selectors: Type.Array(Type.String({ minLength: 1 }), {
|
|
46
|
-
minItems: 1,
|
|
47
|
-
}),
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// 把工具输入收窄为 Browser Quick Action 接受的页面来源。
|
|
51
|
-
// 四个 Browser Quick Action execute 方法在调用 Agents SDK 前共用它。
|
|
52
|
-
// 实际运行时再拒绝空输入,而同时给出 url 和 html 时优先 url,不能把不完整来源传给宿主绑定。
|
|
53
|
-
function page(input: {
|
|
54
|
-
url?: string;
|
|
55
|
-
html?: string;
|
|
56
|
-
}): QuickActionPage {
|
|
57
|
-
if (input.url) return { url: input.url };
|
|
58
|
-
if (input.html) return { html: input.html };
|
|
59
|
-
throw new Error("Provide either 'url' or 'html'");
|
|
60
|
-
}
|
|
61
36
|
|
|
62
37
|
/**
|
|
63
38
|
* 为 Cloudflare Browser Run 的四个一次性 Quick Action 创建 Pi 工具候选项。
|
|
64
39
|
*
|
|
65
40
|
* Runtime 在宿主提供 Browser port 时调用,模型分别用它读取 Markdown、抽取数据、列出链接或按选择器抓取。
|
|
66
41
|
*
|
|
67
|
-
* Cloudflare 官方将 Quick Actions 定位为只需 browser binding
|
|
42
|
+
* Cloudflare 官方将 Quick Actions 定位为只需 browser binding 的无状态单次操作,这里直接复用官方工厂。
|
|
68
43
|
*/
|
|
69
44
|
export function browserQuickActionPiToolCandidates(
|
|
70
45
|
browser: RuntimeBrowserPort,
|
|
71
46
|
): PiToolCandidate[] {
|
|
72
|
-
|
|
73
|
-
name
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
signal?.throwIfAborted();
|
|
83
|
-
return result(await browserMarkdown(browser, page(input)));
|
|
84
|
-
},
|
|
85
|
-
};
|
|
86
|
-
const extract: AgentTool<typeof browserExtractParameters> = {
|
|
87
|
-
name: "browser_extract",
|
|
88
|
-
label: "Extract web data",
|
|
89
|
-
description:
|
|
90
|
-
"Extract structured data from a web page using AI. Describe what you want in 'prompt'. Passing a JSON Schema in 'schema' is strongly recommended — without one the extractor often fails to produce JSON.",
|
|
91
|
-
parameters: browserExtractParameters,
|
|
92
|
-
// 按自然语言提示或 JSON Schema 从页面抽取数据。
|
|
93
|
-
// Pi 工具循环在模型选择 `browser_extract` 时调用,至少需要 prompt 或 schema 之一。
|
|
94
|
-
// schema 必须转成 Browser Run 期望的 `json_schema` response_format,而空抽取要求必须在发起请求前失败。
|
|
95
|
-
async execute(
|
|
96
|
-
_toolCallId,
|
|
97
|
-
{ prompt, schema, ...input },
|
|
98
|
-
signal,
|
|
99
|
-
) {
|
|
100
|
-
signal?.throwIfAborted();
|
|
101
|
-
if (!prompt && schema === undefined) {
|
|
102
|
-
throw new Error("Provide either 'prompt' or 'schema'");
|
|
103
|
-
}
|
|
104
|
-
return result(await browserExtract(browser, {
|
|
105
|
-
...page(input),
|
|
106
|
-
prompt,
|
|
107
|
-
response_format: schema === undefined
|
|
108
|
-
? undefined
|
|
109
|
-
: { type: "json_schema", schema },
|
|
110
|
-
}));
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
const links: AgentTool<typeof browserPageParameters> = {
|
|
114
|
-
name: "browser_links",
|
|
115
|
-
label: "List web links",
|
|
116
|
-
description:
|
|
117
|
-
"Return every link found on a web page (including ones not visible). Useful for discovering pages to follow.",
|
|
118
|
-
parameters: browserPageParameters,
|
|
119
|
-
// 列出 URL 或 HTML 页面中的链接。
|
|
120
|
-
// Pi 工具循环在模型选择 `browser_links` 时调用,调用前允许 Turn 取消。
|
|
121
|
-
// 保留 Agents SDK 的原始结果形状,让统一 result 边界负责文本投影而不在此处二次整形。
|
|
122
|
-
async execute(_toolCallId, input, signal) {
|
|
123
|
-
signal?.throwIfAborted();
|
|
124
|
-
return result(await browserLinks(browser, page(input)));
|
|
125
|
-
},
|
|
126
|
-
};
|
|
127
|
-
const scrape: AgentTool<typeof browserScrapeParameters> = {
|
|
128
|
-
name: "browser_scrape",
|
|
129
|
-
label: "Scrape web elements",
|
|
130
|
-
description:
|
|
131
|
-
"Scrape specific elements from a web page by CSS selector. Returns the matched elements' text, HTML, and attributes.",
|
|
132
|
-
parameters: browserScrapeParameters,
|
|
133
|
-
// 按 CSS 选择器抓取 URL 或 HTML 页面的指定元素。
|
|
134
|
-
// Pi 工具循环在模型选择 `browser_scrape` 时调用,并把简化的字符串列表传入。
|
|
135
|
-
// Browser Run 需要 `{ selector }` 对象列表,因此这个适配只在边界做一次形状转换。
|
|
136
|
-
async execute(
|
|
137
|
-
_toolCallId,
|
|
138
|
-
{ selectors, ...input },
|
|
139
|
-
signal,
|
|
140
|
-
) {
|
|
141
|
-
signal?.throwIfAborted();
|
|
142
|
-
return result(await browserScrape(browser, {
|
|
143
|
-
...page(input),
|
|
144
|
-
elements: selectors.map((selector) => ({ selector })),
|
|
145
|
-
}));
|
|
146
|
-
},
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
return [markdown, extract, links, scrape].map((tool) => ({
|
|
150
|
-
owner: "core:browser",
|
|
151
|
-
authorized: true,
|
|
152
|
-
requiredExecutionLevel: "low",
|
|
153
|
-
tool,
|
|
154
|
-
}));
|
|
47
|
+
return Object.entries(createQuickActionTools({ browser })).map(
|
|
48
|
+
([name, tool]) => ({
|
|
49
|
+
owner: "core:browser",
|
|
50
|
+
authorized: true,
|
|
51
|
+
requiredExecutionLevel: "low",
|
|
52
|
+
tool: aiToolToPi(name, tool, {
|
|
53
|
+
label: BROWSER_TOOL_LABELS[name] ?? name,
|
|
54
|
+
}),
|
|
55
|
+
}),
|
|
56
|
+
);
|
|
155
57
|
}
|
|
156
58
|
|
|
157
59
|
// #endregion
|
|
@@ -210,12 +112,13 @@ const CODEMODE_EXECUTE_TIMEOUT_MS = 60_000;
|
|
|
210
112
|
/**
|
|
211
113
|
* 把 Cloudflare Codemode Runtime handle 包装为高风险 Pi 代码执行工具候选项。
|
|
212
114
|
*
|
|
213
|
-
*
|
|
115
|
+
* Tool Surface 收到 Host 已组装的 Code Execution Port 后调用,
|
|
116
|
+
* 模型再通过 `execute` 运行代码。
|
|
214
117
|
*
|
|
215
118
|
* Codemode 代码可访问出站网络和已配置 connector,因此必须保留 high 档和 codemode source 标记,不能降级成普通本地计算工具。
|
|
216
119
|
*/
|
|
217
120
|
export function codeExecutionPiToolCandidate(
|
|
218
|
-
runtime:
|
|
121
|
+
runtime: RuntimeCodeExecutionPort,
|
|
219
122
|
): PiToolCandidate {
|
|
220
123
|
const tool: AgentTool<typeof executeParameters> = {
|
|
221
124
|
name: "execute",
|
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
|
}
|