@springbrand/agent-runtime 0.1.3-alpha.1 → 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/kernel/bindings.ts +1 -3
- 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/lib/prompt.ts +1 -1
- package/src/pi/assembly/snapshot.ts +5 -2
- package/src/pi/runtime-adapter/assembly.ts +9 -20
- package/src/pi/runtime-adapter/execution.ts +89 -6
- 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/core-host.ts +19 -24
- package/src/pi/tool/core.ts +18 -118
- 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 +79 -42
- package/src/runtime.ts +190 -40
package/src/pi/tool/core-host.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
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 {
|
|
5
|
+
import { createExecuteRuntime } from "@cloudflare/think/tools/execute";
|
|
11
6
|
import type {
|
|
12
7
|
RuntimeCodeExecutionPort,
|
|
13
8
|
WorkspacePort,
|
|
@@ -22,7 +17,7 @@ const CODEMODE_SANDBOX_TIMEOUT_MS = 55_000;
|
|
|
22
17
|
*
|
|
23
18
|
* Worker 宿主在具备 Durable Object state 和完整平台绑定时调用,然后把返回值交给 Runtime 工具组装。
|
|
24
19
|
*
|
|
25
|
-
*
|
|
20
|
+
* Think 的独立 execute factory 接受显式宿主参数,不要求 Agent 继承 Think;这里只借它组装 Codemode Runtime、Dynamic Worker executor 和已限定范围的 Workspace state connector。
|
|
26
21
|
*/
|
|
27
22
|
export function createWorkspaceCodeExecutionPort(options: {
|
|
28
23
|
readonly ctx: DurableObjectState;
|
|
@@ -30,26 +25,26 @@ export function createWorkspaceCodeExecutionPort(options: {
|
|
|
30
25
|
readonly outbound: Fetcher;
|
|
31
26
|
readonly workspace: WorkspacePort;
|
|
32
27
|
}): RuntimeCodeExecutionPort {
|
|
33
|
-
const
|
|
28
|
+
const { tool } = createExecuteRuntime({
|
|
34
29
|
ctx: options.ctx,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
new StateConnector(
|
|
43
|
-
options.ctx,
|
|
44
|
-
createWorkspaceStateBackend(
|
|
45
|
-
options.workspace as unknown as WorkspaceFsLike,
|
|
46
|
-
),
|
|
47
|
-
),
|
|
48
|
-
],
|
|
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
|
+
),
|
|
49
37
|
name: "execute",
|
|
50
|
-
transformResult: truncateResult,
|
|
51
38
|
});
|
|
39
|
+
const execute = tool.execute;
|
|
40
|
+
if (typeof execute !== "function") {
|
|
41
|
+
throw new Error("Think createExecuteRuntime returned a non-executable tool");
|
|
42
|
+
}
|
|
52
43
|
return {
|
|
53
|
-
execute: (input) =>
|
|
44
|
+
execute: (input) => Promise.resolve(execute(input, {
|
|
45
|
+
toolCallId: "execute",
|
|
46
|
+
messages: [],
|
|
47
|
+
context: undefined,
|
|
48
|
+
})),
|
|
54
49
|
};
|
|
55
50
|
}
|
package/src/pi/tool/core.ts
CHANGED
|
@@ -1,21 +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 {
|
|
7
|
-
browserExtract,
|
|
8
|
-
browserLinks,
|
|
9
|
-
browserMarkdown,
|
|
10
|
-
browserScrape,
|
|
11
|
-
type QuickActionPage,
|
|
12
|
-
} from "agents/browser";
|
|
13
7
|
import type {
|
|
14
8
|
RuntimeBrowserPort,
|
|
15
9
|
RuntimeCodeExecutionPort,
|
|
16
10
|
} from "../../kernel/bindings";
|
|
17
11
|
import { serializeOutput } from "../../lib/artifacts";
|
|
18
12
|
import type { PiLoadedExtension } from "../assembly/extensions";
|
|
13
|
+
import { aiToolToPi } from "./ai-adapter";
|
|
19
14
|
import type { PiToolCandidate } from "./compiler";
|
|
20
15
|
|
|
21
16
|
// 本文件沿用 `../../index.ts` 入口定义的 Extension、Port 和 Tool Candidate 术语。
|
|
@@ -32,128 +27,33 @@ function result(details: unknown): AgentToolResult<unknown> {
|
|
|
32
27
|
|
|
33
28
|
// #region Browser Quick Actions
|
|
34
29
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
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",
|
|
38
35
|
};
|
|
39
|
-
const browserPageParameters = Type.Object(pageParameters);
|
|
40
|
-
const browserExtractParameters = Type.Object({
|
|
41
|
-
...pageParameters,
|
|
42
|
-
prompt: Type.Optional(Type.String({ minLength: 1 })),
|
|
43
|
-
schema: Type.Optional(Type.Unknown()),
|
|
44
|
-
});
|
|
45
|
-
const browserScrapeParameters = Type.Object({
|
|
46
|
-
...pageParameters,
|
|
47
|
-
selectors: Type.Array(Type.String({ minLength: 1 }), {
|
|
48
|
-
minItems: 1,
|
|
49
|
-
}),
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// 把工具输入收窄为 Browser Quick Action 接受的页面来源。
|
|
53
|
-
// 四个 Browser Quick Action execute 方法在调用 Agents SDK 前共用它。
|
|
54
|
-
// 实际运行时再拒绝空输入,而同时给出 url 和 html 时优先 url,不能把不完整来源传给宿主绑定。
|
|
55
|
-
function page(input: {
|
|
56
|
-
url?: string;
|
|
57
|
-
html?: string;
|
|
58
|
-
}): QuickActionPage {
|
|
59
|
-
if (input.url) return { url: input.url };
|
|
60
|
-
if (input.html) return { html: input.html };
|
|
61
|
-
throw new Error("Provide either 'url' or 'html'");
|
|
62
|
-
}
|
|
63
36
|
|
|
64
37
|
/**
|
|
65
38
|
* 为 Cloudflare Browser Run 的四个一次性 Quick Action 创建 Pi 工具候选项。
|
|
66
39
|
*
|
|
67
40
|
* Runtime 在宿主提供 Browser port 时调用,模型分别用它读取 Markdown、抽取数据、列出链接或按选择器抓取。
|
|
68
41
|
*
|
|
69
|
-
* Cloudflare 官方将 Quick Actions 定位为只需 browser binding
|
|
42
|
+
* Cloudflare 官方将 Quick Actions 定位为只需 browser binding 的无状态单次操作,这里直接复用官方工厂。
|
|
70
43
|
*/
|
|
71
44
|
export function browserQuickActionPiToolCandidates(
|
|
72
45
|
browser: RuntimeBrowserPort,
|
|
73
46
|
): PiToolCandidate[] {
|
|
74
|
-
|
|
75
|
-
name
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
signal?.throwIfAborted();
|
|
85
|
-
return result(await browserMarkdown(browser, page(input)));
|
|
86
|
-
},
|
|
87
|
-
};
|
|
88
|
-
const extract: AgentTool<typeof browserExtractParameters> = {
|
|
89
|
-
name: "browser_extract",
|
|
90
|
-
label: "Extract web data",
|
|
91
|
-
description:
|
|
92
|
-
"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.",
|
|
93
|
-
parameters: browserExtractParameters,
|
|
94
|
-
// 按自然语言提示或 JSON Schema 从页面抽取数据。
|
|
95
|
-
// Pi 工具循环在模型选择 `browser_extract` 时调用,至少需要 prompt 或 schema 之一。
|
|
96
|
-
// schema 必须转成 Browser Run 期望的 `json_schema` response_format,而空抽取要求必须在发起请求前失败。
|
|
97
|
-
async execute(
|
|
98
|
-
_toolCallId,
|
|
99
|
-
{ prompt, schema, ...input },
|
|
100
|
-
signal,
|
|
101
|
-
) {
|
|
102
|
-
signal?.throwIfAborted();
|
|
103
|
-
if (!prompt && schema === undefined) {
|
|
104
|
-
throw new Error("Provide either 'prompt' or 'schema'");
|
|
105
|
-
}
|
|
106
|
-
return result(await browserExtract(browser, {
|
|
107
|
-
...page(input),
|
|
108
|
-
prompt,
|
|
109
|
-
response_format: schema === undefined
|
|
110
|
-
? undefined
|
|
111
|
-
: { type: "json_schema", schema },
|
|
112
|
-
}));
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
const links: AgentTool<typeof browserPageParameters> = {
|
|
116
|
-
name: "browser_links",
|
|
117
|
-
label: "List web links",
|
|
118
|
-
description:
|
|
119
|
-
"Return every link found on a web page (including ones not visible). Useful for discovering pages to follow.",
|
|
120
|
-
parameters: browserPageParameters,
|
|
121
|
-
// 列出 URL 或 HTML 页面中的链接。
|
|
122
|
-
// Pi 工具循环在模型选择 `browser_links` 时调用,调用前允许 Turn 取消。
|
|
123
|
-
// 保留 Agents SDK 的原始结果形状,让统一 result 边界负责文本投影而不在此处二次整形。
|
|
124
|
-
async execute(_toolCallId, input, signal) {
|
|
125
|
-
signal?.throwIfAborted();
|
|
126
|
-
return result(await browserLinks(browser, page(input)));
|
|
127
|
-
},
|
|
128
|
-
};
|
|
129
|
-
const scrape: AgentTool<typeof browserScrapeParameters> = {
|
|
130
|
-
name: "browser_scrape",
|
|
131
|
-
label: "Scrape web elements",
|
|
132
|
-
description:
|
|
133
|
-
"Scrape specific elements from a web page by CSS selector. Returns the matched elements' text, HTML, and attributes.",
|
|
134
|
-
parameters: browserScrapeParameters,
|
|
135
|
-
// 按 CSS 选择器抓取 URL 或 HTML 页面的指定元素。
|
|
136
|
-
// Pi 工具循环在模型选择 `browser_scrape` 时调用,并把简化的字符串列表传入。
|
|
137
|
-
// Browser Run 需要 `{ selector }` 对象列表,因此这个适配只在边界做一次形状转换。
|
|
138
|
-
async execute(
|
|
139
|
-
_toolCallId,
|
|
140
|
-
{ selectors, ...input },
|
|
141
|
-
signal,
|
|
142
|
-
) {
|
|
143
|
-
signal?.throwIfAborted();
|
|
144
|
-
return result(await browserScrape(browser, {
|
|
145
|
-
...page(input),
|
|
146
|
-
elements: selectors.map((selector) => ({ selector })),
|
|
147
|
-
}));
|
|
148
|
-
},
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
return [markdown, extract, links, scrape].map((tool) => ({
|
|
152
|
-
owner: "core:browser",
|
|
153
|
-
authorized: true,
|
|
154
|
-
requiredExecutionLevel: "low",
|
|
155
|
-
tool,
|
|
156
|
-
}));
|
|
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
|
+
);
|
|
157
57
|
}
|
|
158
58
|
|
|
159
59
|
// #endregion
|