@springbrand/agent-runtime 0.1.3-alpha.1 → 0.1.3-alpha.11
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 +57 -21
- package/src/kernel/approval-lifecycle.ts +41 -6
- package/src/kernel/bindings.ts +73 -9
- package/src/kernel/interaction-lifecycle.ts +395 -0
- 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 -2
- package/src/lib/mcp.ts +7 -3
- package/src/lib/prompt.ts +4 -1
- package/src/lib/telemetry-dev.ts +7 -4
- package/src/pi/assembly/context.ts +3 -3
- package/src/pi/assembly/extensions.ts +11 -22
- package/src/pi/assembly/snapshot.ts +6 -3
- package/src/pi/message/contract.ts +7 -0
- package/src/pi/message/conversion.ts +9 -1
- package/src/pi/runtime-adapter/assembly.ts +26 -31
- package/src/pi/runtime-adapter/execution.ts +198 -15
- 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 +34 -1
- package/src/pi/tool/core-host.ts +19 -24
- package/src/pi/tool/core.ts +30 -120
- package/src/pi/tool/gateway.ts +54 -0
- package/src/pi/tool/index.ts +2 -0
- package/src/pi/tool/mcp.ts +96 -68
- package/src/pi/tool/schedule.ts +41 -19
- 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/{plugins.ts → runtime-assembler.ts} +372 -398
- package/src/runtime-definition.ts +175 -0
- package/src/runtime.ts +835 -204
- package/src/tool-registry.ts +143 -0
- package/src/workspace-versioning.ts +46 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SkillSource } from "agents/skills";
|
|
2
2
|
import type {
|
|
3
3
|
RuntimeCodeExecutionPort,
|
|
4
|
+
RuntimeGatewayPort,
|
|
4
5
|
RuntimeMemoryPort,
|
|
5
6
|
RuntimePlatformPort,
|
|
6
7
|
RuntimeProviderPort,
|
|
@@ -32,209 +33,65 @@ import {
|
|
|
32
33
|
type PiToolSurface,
|
|
33
34
|
type PiRuntimeAssembly,
|
|
34
35
|
} from "./pi/assembly/snapshot";
|
|
36
|
+
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
35
37
|
import type { PiToolCandidate } from "./pi/tool/compiler";
|
|
36
|
-
import {
|
|
38
|
+
import type {
|
|
39
|
+
AssembleRuntimeSnapshotInput,
|
|
40
|
+
RuntimeAgentHooks,
|
|
41
|
+
RuntimeSettings,
|
|
42
|
+
RuntimeExtensionContribution,
|
|
43
|
+
RuntimeProfileContribution,
|
|
44
|
+
RuntimeSkillContribution,
|
|
45
|
+
RuntimeToolSurfacePolicy,
|
|
46
|
+
} from "./runtime-definition";
|
|
47
|
+
import type { ToolRegistry } from "./tool-registry";
|
|
48
|
+
import { withRuntimeLoadTimeout } from "./kernel/runtime-load";
|
|
49
|
+
import {
|
|
50
|
+
basePiToolCandidates,
|
|
51
|
+
memoryPiToolCandidate,
|
|
52
|
+
} from "./pi/tool/base";
|
|
37
53
|
import {
|
|
38
54
|
browserQuickActionPiToolCandidates,
|
|
39
|
-
codeExecutionPiToolCandidate,
|
|
40
55
|
} from "./pi/tool/core";
|
|
41
|
-
import {
|
|
42
|
-
sandboxPiToolCandidates,
|
|
43
|
-
workspacePiToolCandidates,
|
|
44
|
-
} from "./pi/tool/workspace-sandbox";
|
|
45
|
-
import { schedulePiToolCandidates } from "./pi/tool/schedule";
|
|
46
56
|
import { skillPiToolCandidates } from "./pi/tool/skill";
|
|
47
|
-
import { subagentPiToolCandidates } from "./pi/tool/subagent";
|
|
48
57
|
import { createWebSearch } from "./pi/tool/web-search";
|
|
49
58
|
import { resolvePiModel } from "./pi/runtime-adapter/models";
|
|
50
59
|
|
|
51
|
-
/**
|
|
52
|
-
* 本文件实现 Plugin 的准备、声明合并、校验和原子候选装配。
|
|
53
|
-
*
|
|
54
|
-
* @remarks
|
|
55
|
-
* 核心术语见包入口 `index.ts`,这里不重复定义。
|
|
56
|
-
*/
|
|
57
|
-
|
|
58
|
-
// #region Plugin 公开契约
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* 标明一个 Plugin 负责哪一类能力。
|
|
62
|
-
*
|
|
63
|
-
* @remarks
|
|
64
|
-
* 应用创建 Plugin 时必须选择其中一个值。
|
|
65
|
-
*
|
|
66
|
-
* Runtime 用它拒绝重复能力并确定贡献顺序,所以不要把它当作自由文本。
|
|
67
|
-
*/
|
|
68
|
-
export type PluginKind =
|
|
69
|
-
| "scope"
|
|
70
|
-
| "profile"
|
|
71
|
-
| "provider"
|
|
72
|
-
| "platform"
|
|
73
|
-
| "workspace"
|
|
74
|
-
| "sandbox"
|
|
75
|
-
| "memory"
|
|
76
|
-
| "tool"
|
|
77
|
-
| "skill"
|
|
78
|
-
| "connector"
|
|
79
|
-
| "extension"
|
|
80
|
-
| "schedule"
|
|
81
|
-
| "subagent"
|
|
82
|
-
| "turn-events";
|
|
60
|
+
/** Runtime Assembler:校验一份扁平输入并生成可原子提交的 Snapshot。 */
|
|
83
61
|
|
|
84
62
|
export type { RuntimeDegradation } from "./kernel/degradation";
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
readonly
|
|
96
|
-
readonly
|
|
97
|
-
readonly
|
|
98
|
-
readonly
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
readonly
|
|
106
|
-
readonly
|
|
107
|
-
readonly
|
|
108
|
-
readonly
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
export interface RuntimeExtensionContribution {
|
|
115
|
-
readonly name: string;
|
|
116
|
-
readonly extension: RuntimeExtensionConfig;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* 描述 Agent 对最终 Tool Surface 的可见性约束。
|
|
121
|
-
*
|
|
122
|
-
* Host 只提供策略;Runtime 在唯一 Tool Surface seam 中对所有
|
|
123
|
-
* Port 和 Resource 生成的候选项统一应用。
|
|
124
|
-
*/
|
|
125
|
-
export interface RuntimeToolSurfacePolicy {
|
|
126
|
-
readonly denyPolicy?: RuntimeDenyPolicy;
|
|
127
|
-
readonly allowsTool?: (name: string) => boolean;
|
|
128
|
-
readonly allowsExtension?: (extension: RuntimeExtensionConfig) => boolean;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
interface PluginResultByKind {
|
|
132
|
-
readonly scope: {
|
|
133
|
-
readonly commitGuards: readonly (() => Promise<void>)[];
|
|
134
|
-
};
|
|
135
|
-
readonly profile: { readonly profile: RuntimeProfileContribution };
|
|
136
|
-
readonly provider: { readonly provider: RuntimeProviderPort };
|
|
137
|
-
readonly platform: {
|
|
138
|
-
readonly platform: RuntimePlatformPort;
|
|
139
|
-
};
|
|
140
|
-
readonly workspace: {
|
|
141
|
-
readonly workspace?: WorkspacePort;
|
|
142
|
-
readonly codeExecution?: RuntimeCodeExecutionPort;
|
|
143
|
-
};
|
|
144
|
-
readonly sandbox: {
|
|
145
|
-
readonly sandbox?: RuntimeSandboxPort;
|
|
146
|
-
};
|
|
147
|
-
readonly memory: {
|
|
148
|
-
readonly memoryProfile: RuntimeMemoryProfile;
|
|
149
|
-
readonly memoryPort?: RuntimeMemoryPort;
|
|
150
|
-
};
|
|
151
|
-
readonly tool: {
|
|
152
|
-
readonly hostTools: readonly PiToolCandidate[];
|
|
153
|
-
readonly policy?: RuntimeToolSurfacePolicy;
|
|
154
|
-
};
|
|
155
|
-
readonly skill: {
|
|
156
|
-
readonly skills: readonly RuntimeSkillContribution[];
|
|
157
|
-
};
|
|
158
|
-
readonly connector: {
|
|
159
|
-
readonly connectors: readonly RuntimeMcpServer[];
|
|
160
|
-
};
|
|
161
|
-
readonly extension: {
|
|
162
|
-
readonly extensions: readonly RuntimeExtensionContribution[];
|
|
163
|
-
};
|
|
164
|
-
readonly schedule: {
|
|
165
|
-
readonly schedule: RuntimeSchedulePort;
|
|
166
|
-
};
|
|
167
|
-
readonly subagent: {
|
|
168
|
-
readonly enabledSubagents: readonly string[];
|
|
169
|
-
readonly subagents?: RuntimeSubagentPort;
|
|
170
|
-
};
|
|
171
|
-
readonly "turn-events": {
|
|
172
|
-
readonly turnEvents: RuntimeTurnEventsPort;
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
export type PluginPreparation<K extends PluginKind> = Readonly<
|
|
177
|
-
PluginResultByKind[K] & {
|
|
178
|
-
readonly degradations: readonly RuntimeDegradation[];
|
|
179
|
-
}
|
|
180
|
-
>;
|
|
181
|
-
|
|
182
|
-
export type PreparedPlugin<K extends PluginKind = PluginKind> =
|
|
183
|
-
K extends PluginKind
|
|
184
|
-
? Readonly<PluginPreparation<K> & { readonly kind: K }>
|
|
185
|
-
: never;
|
|
186
|
-
|
|
187
|
-
interface AgentPluginContract<K extends PluginKind> {
|
|
188
|
-
readonly kind: K;
|
|
189
|
-
prepare(): Promise<PreparedPlugin<K>>;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export type AgentPlugin<K extends PluginKind = PluginKind> =
|
|
193
|
-
K extends PluginKind ? AgentPluginContract<K> : never;
|
|
194
|
-
|
|
195
|
-
export interface AgentPluginSpec<K extends PluginKind> {
|
|
196
|
-
readonly kind: K;
|
|
197
|
-
prepare(): Promise<PluginPreparation<K>>;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* 汇总一次 Runtime 装配要使用的全部 Plugin。
|
|
202
|
-
*/
|
|
203
|
-
export interface AgentConfig {
|
|
204
|
-
readonly plugins: readonly AgentPlugin[];
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* 定义一个只准备声明式结果的 Runtime Plugin。
|
|
209
|
-
*
|
|
210
|
-
* Runtime 内部负责排序、合并、冲突检查和提交。
|
|
211
|
-
*/
|
|
212
|
-
export function definePlugin<K extends PluginKind>(
|
|
213
|
-
spec: AgentPluginSpec<K>,
|
|
214
|
-
): AgentPlugin<K> {
|
|
215
|
-
return Object.freeze({
|
|
216
|
-
kind: spec.kind,
|
|
217
|
-
|
|
218
|
-
async prepare(): Promise<PreparedPlugin<K>> {
|
|
219
|
-
const prepared = await spec.prepare();
|
|
220
|
-
const degradations = Object.freeze(
|
|
221
|
-
prepared.degradations.map((degradation) =>
|
|
222
|
-
Object.freeze({ ...degradation }),
|
|
223
|
-
),
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
return Object.freeze({
|
|
227
|
-
...prepared,
|
|
228
|
-
kind: spec.kind,
|
|
229
|
-
degradations,
|
|
230
|
-
}) as PreparedPlugin<K>;
|
|
231
|
-
},
|
|
232
|
-
}) as AgentPlugin<K>;
|
|
63
|
+
export type {
|
|
64
|
+
RuntimeExtensionContribution,
|
|
65
|
+
RuntimeProfileContribution,
|
|
66
|
+
RuntimeSkillContribution,
|
|
67
|
+
RuntimeToolSurfacePolicy,
|
|
68
|
+
} from "./runtime-definition";
|
|
69
|
+
|
|
70
|
+
/** Host Planner 与 Runtime Assembler 之间的一次性内部 seam。 */
|
|
71
|
+
export interface RuntimeAssemblyInput {
|
|
72
|
+
readonly profile: RuntimeProfileContribution;
|
|
73
|
+
readonly memoryProfile: RuntimeMemoryProfile;
|
|
74
|
+
readonly toolPolicy?: RuntimeToolSurfacePolicy;
|
|
75
|
+
readonly enabledSubagents: readonly string[];
|
|
76
|
+
readonly provider: RuntimeProviderPort;
|
|
77
|
+
readonly platform: RuntimePlatformPort;
|
|
78
|
+
readonly workspace?: WorkspacePort;
|
|
79
|
+
readonly codeExecution?: RuntimeCodeExecutionPort;
|
|
80
|
+
readonly sandbox?: RuntimeSandboxPort;
|
|
81
|
+
readonly memory?: RuntimeMemoryPort;
|
|
82
|
+
readonly hostTools: readonly PiToolCandidate[];
|
|
83
|
+
readonly skills: readonly RuntimeSkillContribution[];
|
|
84
|
+
readonly connectors: readonly RuntimeMcpServer[];
|
|
85
|
+
readonly gateway?: RuntimeGatewayPort;
|
|
86
|
+
readonly extensions: readonly RuntimeExtensionContribution[];
|
|
87
|
+
readonly subagents?: RuntimeSubagentPort;
|
|
88
|
+
readonly schedule?: RuntimeSchedulePort;
|
|
89
|
+
readonly turnEvents?: RuntimeTurnEventsPort;
|
|
90
|
+
readonly commitGuards: readonly (() => Promise<void>)[];
|
|
91
|
+
readonly degradations: readonly RuntimeDegradation[];
|
|
233
92
|
}
|
|
234
93
|
|
|
235
|
-
// #
|
|
236
|
-
|
|
237
|
-
// #region 内部候选契约与装配顺序
|
|
94
|
+
// #region 内部候选契约
|
|
238
95
|
|
|
239
96
|
/**
|
|
240
97
|
* 保存一次已经完成校验、可供 Kernel 使用的 Runtime 结果。
|
|
@@ -256,31 +113,10 @@ export interface RuntimeSnapshot {
|
|
|
256
113
|
export interface RuntimeCandidate {
|
|
257
114
|
readonly snapshot: RuntimeSnapshot;
|
|
258
115
|
readonly commitGuards: readonly (() => Promise<void>)[];
|
|
116
|
+
readonly hooks?: RuntimeAgentHooks<Cloudflare.Env, unknown, never, never>;
|
|
117
|
+
readonly turnEvents?: RuntimeTurnEventsPort;
|
|
259
118
|
}
|
|
260
119
|
|
|
261
|
-
const PLUGIN_ORDER: readonly PluginKind[] = Object.freeze([
|
|
262
|
-
"scope",
|
|
263
|
-
"profile",
|
|
264
|
-
"provider",
|
|
265
|
-
"platform",
|
|
266
|
-
"workspace",
|
|
267
|
-
"sandbox",
|
|
268
|
-
"memory",
|
|
269
|
-
"tool",
|
|
270
|
-
"skill",
|
|
271
|
-
"connector",
|
|
272
|
-
"extension",
|
|
273
|
-
"schedule",
|
|
274
|
-
"subagent",
|
|
275
|
-
"turn-events",
|
|
276
|
-
]);
|
|
277
|
-
|
|
278
|
-
const REQUIRED_PLUGIN_KINDS: readonly PluginKind[] = Object.freeze([
|
|
279
|
-
"profile",
|
|
280
|
-
"provider",
|
|
281
|
-
"platform",
|
|
282
|
-
]);
|
|
283
|
-
|
|
284
120
|
const DISABLED_MEMORY: RuntimeMemoryProfile = Object.freeze({
|
|
285
121
|
enabled: false,
|
|
286
122
|
memoryTokens: 2_000,
|
|
@@ -315,14 +151,14 @@ function assertMemoryProfile(profile: RuntimeMemoryProfile): void {
|
|
|
315
151
|
interface ToolSurfaceInput {
|
|
316
152
|
readonly platform: RuntimePlatformPort;
|
|
317
153
|
readonly workspace?: WorkspacePort;
|
|
318
|
-
readonly
|
|
319
|
-
|
|
154
|
+
readonly memory?: {
|
|
155
|
+
readonly port: RuntimeMemoryPort;
|
|
156
|
+
readonly profile: RuntimeMemoryProfile;
|
|
157
|
+
};
|
|
320
158
|
readonly hostTools: readonly PiToolCandidate[];
|
|
321
159
|
readonly skills: readonly RuntimeSkillSourceBinding[];
|
|
322
|
-
readonly schedule?: RuntimeSchedulePort;
|
|
323
|
-
readonly subagents?: RuntimeSubagentPort;
|
|
324
160
|
readonly enabledSubagents: readonly string[];
|
|
325
|
-
readonly webSearch
|
|
161
|
+
readonly webSearch: Parameters<typeof basePiToolCandidates>[0];
|
|
326
162
|
readonly extensions: readonly RuntimeExtensionConfig[];
|
|
327
163
|
readonly policy?: RuntimeToolSurfacePolicy;
|
|
328
164
|
}
|
|
@@ -333,45 +169,53 @@ interface ToolSurface {
|
|
|
333
169
|
readonly degradations: readonly RuntimeDegradation[];
|
|
334
170
|
}
|
|
335
171
|
|
|
336
|
-
// 唯一 Tool Surface seam
|
|
172
|
+
// 唯一 Tool Surface seam:只读取已配置 Port、Resource 和 Agent policy,
|
|
337
173
|
// 统一生成可见 Tool,并在一处做名称、执行档位与冲突校验。
|
|
338
|
-
function createToolSurface(
|
|
174
|
+
async function createToolSurface(
|
|
175
|
+
input: ToolSurfaceInput,
|
|
176
|
+
): Promise<ToolSurface> {
|
|
177
|
+
const deny = new Set(input.policy?.denyPolicy?.deny ?? []);
|
|
178
|
+
const allowsTool = input.policy?.allowsTool;
|
|
179
|
+
const allowsExtension = input.policy?.allowsExtension;
|
|
180
|
+
const visible = (candidate: PiToolCandidate) =>
|
|
181
|
+
!deny.has(candidate.tool.name) &&
|
|
182
|
+
allowsTool?.(candidate.tool.name) !== false;
|
|
183
|
+
const browserCandidates = input.platform.browser
|
|
184
|
+
? browserQuickActionPiToolCandidates(input.platform.browser)
|
|
185
|
+
: [];
|
|
186
|
+
const baseCandidates = basePiToolCandidates(input.webSearch);
|
|
187
|
+
const memoryCandidates = input.memory
|
|
188
|
+
? [memoryPiToolCandidate(input.memory.port, input.memory.profile)]
|
|
189
|
+
: [];
|
|
190
|
+
const scriptCandidates = [
|
|
191
|
+
...browserCandidates,
|
|
192
|
+
...input.hostTools,
|
|
193
|
+
...baseCandidates,
|
|
194
|
+
...memoryCandidates,
|
|
195
|
+
].filter(visible);
|
|
339
196
|
const staticCandidates = [
|
|
340
|
-
...
|
|
341
|
-
? browserQuickActionPiToolCandidates(input.platform.browser)
|
|
342
|
-
: []),
|
|
343
|
-
...(input.workspace ? workspacePiToolCandidates(input.workspace) : []),
|
|
344
|
-
...(input.workspace && input.codeExecution
|
|
345
|
-
? [codeExecutionPiToolCandidate(input.codeExecution)]
|
|
346
|
-
: []),
|
|
347
|
-
...(input.sandbox ? sandboxPiToolCandidates(input.sandbox) : []),
|
|
197
|
+
...browserCandidates,
|
|
348
198
|
...input.hostTools,
|
|
349
|
-
...skillPiToolCandidates(input.skills, {
|
|
199
|
+
...(await skillPiToolCandidates(input.skills, {
|
|
350
200
|
loader: input.platform.loader,
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
...
|
|
201
|
+
...(input.workspace ? { workspace: input.workspace } : {}),
|
|
202
|
+
tools: scriptCandidates,
|
|
203
|
+
})),
|
|
204
|
+
...baseCandidates,
|
|
205
|
+
...memoryCandidates,
|
|
355
206
|
];
|
|
356
|
-
const deny = new Set(input.policy?.denyPolicy?.deny ?? []);
|
|
357
|
-
const allowsTool = input.policy?.allowsTool;
|
|
358
|
-
const allowsExtension = input.policy?.allowsExtension;
|
|
359
207
|
|
|
360
208
|
return {
|
|
361
209
|
surface: Object.freeze({
|
|
362
|
-
finalize(
|
|
210
|
+
finalize(candidates: readonly PiToolCandidate[]) {
|
|
363
211
|
const tools = new Map<string, PiToolCandidate>();
|
|
364
212
|
|
|
365
213
|
for (const candidate of [
|
|
366
214
|
...staticCandidates,
|
|
367
|
-
...
|
|
215
|
+
...candidates,
|
|
368
216
|
]) {
|
|
369
217
|
const name = requiredName(candidate.tool.name, "Pi Tool");
|
|
370
|
-
if (
|
|
371
|
-
!candidate.authorized ||
|
|
372
|
-
deny.has(name) ||
|
|
373
|
-
allowsTool?.(name) === false
|
|
374
|
-
) continue;
|
|
218
|
+
if (!visible(candidate)) continue;
|
|
375
219
|
if (!EXECUTION_LEVELS.includes(candidate.requiredExecutionLevel)) {
|
|
376
220
|
throw new Error(`Pi Tool ${name} execution level is invalid`);
|
|
377
221
|
}
|
|
@@ -387,13 +231,7 @@ function createToolSurface(input: ToolSurfaceInput): ToolSurface {
|
|
|
387
231
|
extensions: input.extensions.filter(
|
|
388
232
|
(extension) => allowsExtension?.(extension) !== false,
|
|
389
233
|
),
|
|
390
|
-
degradations:
|
|
391
|
-
? []
|
|
392
|
-
: [{
|
|
393
|
-
capability: "web_search",
|
|
394
|
-
reason: "unavailable",
|
|
395
|
-
detail: "Native web search is unavailable for openrouter-chat",
|
|
396
|
-
}],
|
|
234
|
+
degradations: [],
|
|
397
235
|
};
|
|
398
236
|
}
|
|
399
237
|
|
|
@@ -405,6 +243,7 @@ class RuntimeBuilder {
|
|
|
405
243
|
private profile?: RuntimeProfileContribution;
|
|
406
244
|
private provider?: RuntimeProviderPort;
|
|
407
245
|
private platform?: RuntimePlatformPort;
|
|
246
|
+
private gateway?: RuntimeGatewayPort;
|
|
408
247
|
private workspace?: WorkspacePort;
|
|
409
248
|
private codeExecution?: RuntimeCodeExecutionPort;
|
|
410
249
|
private sandbox?: RuntimeSandboxPort;
|
|
@@ -430,68 +269,36 @@ class RuntimeBuilder {
|
|
|
430
269
|
private readonly commitGuards: Array<() => Promise<void>> = [];
|
|
431
270
|
private readonly degradations: RuntimeDegradation[] = [];
|
|
432
271
|
|
|
433
|
-
merge(
|
|
434
|
-
for (const degradation of
|
|
272
|
+
merge(input: RuntimeAssemblyInput): void {
|
|
273
|
+
for (const degradation of input.degradations) {
|
|
435
274
|
this.reportDegradation(degradation);
|
|
436
275
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
this.sandbox = prepared.sandbox;
|
|
460
|
-
break;
|
|
461
|
-
case "memory":
|
|
462
|
-
this.memoryProfile = prepared.memoryProfile;
|
|
463
|
-
this.memory = prepared.memoryPort;
|
|
464
|
-
break;
|
|
465
|
-
case "tool":
|
|
466
|
-
this.hostTools.push(...prepared.hostTools);
|
|
467
|
-
this.toolPolicy = prepared.policy;
|
|
468
|
-
break;
|
|
469
|
-
case "skill":
|
|
470
|
-
for (const skill of prepared.skills) this.addSkill(skill);
|
|
471
|
-
break;
|
|
472
|
-
case "connector":
|
|
473
|
-
for (const connector of prepared.connectors) {
|
|
474
|
-
this.addConnector(connector);
|
|
475
|
-
}
|
|
476
|
-
break;
|
|
477
|
-
case "extension":
|
|
478
|
-
for (const { name, extension } of prepared.extensions) {
|
|
479
|
-
this.addExtension(name, extension);
|
|
480
|
-
}
|
|
481
|
-
break;
|
|
482
|
-
case "schedule":
|
|
483
|
-
this.schedule = prepared.schedule;
|
|
484
|
-
break;
|
|
485
|
-
case "subagent":
|
|
486
|
-
for (const name of prepared.enabledSubagents) {
|
|
487
|
-
this.enabledSubagents.add(requiredName(name, "Subagent"));
|
|
488
|
-
}
|
|
489
|
-
this.subagents = prepared.subagents;
|
|
490
|
-
break;
|
|
491
|
-
case "turn-events":
|
|
492
|
-
this.turnEvents = prepared.turnEvents;
|
|
493
|
-
break;
|
|
276
|
+
if (!EXECUTION_LEVELS.includes(input.profile.executionLevel)) {
|
|
277
|
+
throw new Error("Runtime execution level is invalid");
|
|
278
|
+
}
|
|
279
|
+
this.profile = input.profile;
|
|
280
|
+
this.provider = input.provider;
|
|
281
|
+
this.platform = input.platform;
|
|
282
|
+
this.workspace = input.workspace;
|
|
283
|
+
this.codeExecution = input.codeExecution;
|
|
284
|
+
this.sandbox = input.sandbox;
|
|
285
|
+
this.memoryProfile = input.memoryProfile;
|
|
286
|
+
this.memory = input.memory;
|
|
287
|
+
this.hostTools.push(...input.hostTools);
|
|
288
|
+
this.toolPolicy = input.toolPolicy;
|
|
289
|
+
for (const skill of input.skills) this.addSkill(skill);
|
|
290
|
+
for (const connector of input.connectors) this.addConnector(connector);
|
|
291
|
+
this.gateway = input.gateway;
|
|
292
|
+
for (const { name, extension } of input.extensions) {
|
|
293
|
+
this.addExtension(name, extension);
|
|
294
|
+
}
|
|
295
|
+
this.schedule = input.schedule;
|
|
296
|
+
for (const name of input.enabledSubagents) {
|
|
297
|
+
this.enabledSubagents.add(requiredName(name, "Subagent"));
|
|
494
298
|
}
|
|
299
|
+
this.subagents = input.subagents;
|
|
300
|
+
this.turnEvents = input.turnEvents;
|
|
301
|
+
this.commitGuards.push(...input.commitGuards);
|
|
495
302
|
}
|
|
496
303
|
|
|
497
304
|
private addSkill(skill: RuntimeSkillContribution): void {
|
|
@@ -578,17 +385,17 @@ class RuntimeBuilder {
|
|
|
578
385
|
// #region RuntimeBuilder 校验与候选生成
|
|
579
386
|
|
|
580
387
|
// 作用:校验全部声明,并生成一个不可变候选 Runtime。
|
|
581
|
-
//
|
|
388
|
+
// 调用:扁平 Assembly Input 合并完成后调用一次。
|
|
582
389
|
// 原因:所有交叉约束都在这里通过后才返回候选,旧 Snapshot 不会半更新。
|
|
583
|
-
build(): RuntimeCandidate {
|
|
390
|
+
async build(): Promise<RuntimeCandidate> {
|
|
584
391
|
if (!this.profile) {
|
|
585
|
-
throw new Error("Runtime
|
|
392
|
+
throw new Error("Runtime assembly did not configure a profile");
|
|
586
393
|
}
|
|
587
394
|
if (!this.platform) {
|
|
588
|
-
throw new Error("Runtime
|
|
395
|
+
throw new Error("Runtime assembly did not bind a platform");
|
|
589
396
|
}
|
|
590
397
|
if (!this.provider) {
|
|
591
|
-
throw new Error("Runtime
|
|
398
|
+
throw new Error("Runtime assembly did not bind a provider");
|
|
592
399
|
}
|
|
593
400
|
if (!this.profile.model.trim()) {
|
|
594
401
|
throw new Error("Runtime model must not be empty");
|
|
@@ -617,17 +424,7 @@ class RuntimeBuilder {
|
|
|
617
424
|
assertMemoryProfile(this.memoryProfile);
|
|
618
425
|
if (this.memoryProfile.enabled && (!this.workspace || !this.memory)) {
|
|
619
426
|
throw new Error(
|
|
620
|
-
"Enabled Runtime memory requires Workspace and Memory
|
|
621
|
-
);
|
|
622
|
-
}
|
|
623
|
-
if (this.sandbox && !this.workspace) {
|
|
624
|
-
throw new Error(
|
|
625
|
-
"Runtime Sandbox requires a persistent Workspace port",
|
|
626
|
-
);
|
|
627
|
-
}
|
|
628
|
-
if (this.enabledSubagents.size > 0 && !this.subagents) {
|
|
629
|
-
throw new Error(
|
|
630
|
-
"Enabled Runtime Subagents require a Subagent port",
|
|
427
|
+
"Enabled Runtime memory requires Workspace and Memory bindings",
|
|
631
428
|
);
|
|
632
429
|
}
|
|
633
430
|
const profile = freezeRuntimeProfile({
|
|
@@ -664,26 +461,23 @@ class RuntimeBuilder {
|
|
|
664
461
|
}
|
|
665
462
|
const resolvedModel = resolvePiModel(provider, profile.model);
|
|
666
463
|
const endpoint = endpoints[0]!;
|
|
667
|
-
const webSearch =
|
|
668
|
-
|
|
669
|
-
:
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
reasoning: resolvedModel.reasoning,
|
|
674
|
-
});
|
|
464
|
+
const webSearch = createWebSearch({
|
|
465
|
+
endpoint,
|
|
466
|
+
model: profile.model,
|
|
467
|
+
maxTokens: resolvedModel.maxTokens,
|
|
468
|
+
reasoning: resolvedModel.reasoning,
|
|
469
|
+
});
|
|
675
470
|
const skillSources = [...this.skillSources.values()];
|
|
676
|
-
const toolSurface = createToolSurface({
|
|
471
|
+
const toolSurface = await createToolSurface({
|
|
677
472
|
platform: this.platform,
|
|
678
473
|
...(this.workspace ? { workspace: this.workspace } : {}),
|
|
679
|
-
...(this.
|
|
680
|
-
|
|
474
|
+
...(this.memoryProfile.enabled && this.memory
|
|
475
|
+
? { memory: { port: this.memory, profile: this.memoryProfile } }
|
|
476
|
+
: {}),
|
|
681
477
|
hostTools: this.hostTools,
|
|
682
478
|
skills: skillSources,
|
|
683
|
-
...(this.schedule ? { schedule: this.schedule } : {}),
|
|
684
|
-
...(this.subagents ? { subagents: this.subagents } : {}),
|
|
685
479
|
enabledSubagents: [...this.enabledSubagents],
|
|
686
|
-
|
|
480
|
+
webSearch,
|
|
687
481
|
extensions: [...this.extensions.values()],
|
|
688
482
|
...(this.toolPolicy ? { policy: this.toolPolicy } : {}),
|
|
689
483
|
});
|
|
@@ -693,6 +487,7 @@ class RuntimeBuilder {
|
|
|
693
487
|
const bindings: RuntimeBindings = Object.freeze({
|
|
694
488
|
provider,
|
|
695
489
|
platform: Object.freeze({ ...this.platform }),
|
|
490
|
+
...(this.gateway ? { gateway: this.gateway } : {}),
|
|
696
491
|
...(this.workspace ? { workspace: this.workspace } : {}),
|
|
697
492
|
...(this.memoryProfile.enabled && this.memory
|
|
698
493
|
? { memory: this.memory }
|
|
@@ -727,75 +522,23 @@ class RuntimeBuilder {
|
|
|
727
522
|
|
|
728
523
|
}
|
|
729
524
|
|
|
730
|
-
// 作用:检查 Plugin kind 合法、唯一,并包含所有必需能力。
|
|
731
|
-
// 调用:任何 prepare 启动前由 `prepareRuntimeCandidate` 调用。
|
|
732
|
-
// 原因:先校验结构可避免为注定失败的配置执行外部读取。
|
|
733
|
-
function validatePluginKinds(
|
|
734
|
-
plugins: readonly AgentPlugin[],
|
|
735
|
-
): void {
|
|
736
|
-
const kinds = new Set<PluginKind>();
|
|
737
|
-
const knownKinds = new Set(PLUGIN_ORDER);
|
|
738
|
-
|
|
739
|
-
for (const plugin of plugins) {
|
|
740
|
-
if (!knownKinds.has(plugin.kind)) {
|
|
741
|
-
throw new Error(`Unknown Agent Plugin kind: ${plugin.kind}`);
|
|
742
|
-
}
|
|
743
|
-
if (kinds.has(plugin.kind)) {
|
|
744
|
-
throw new Error(
|
|
745
|
-
`Duplicate Agent Plugin kind: ${plugin.kind}`,
|
|
746
|
-
);
|
|
747
|
-
}
|
|
748
|
-
kinds.add(plugin.kind);
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
for (const required of REQUIRED_PLUGIN_KINDS) {
|
|
752
|
-
if (!kinds.has(required)) {
|
|
753
|
-
throw new Error(
|
|
754
|
-
`Missing required Agent Plugin: ${required}`,
|
|
755
|
-
);
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
|
|
760
525
|
/**
|
|
761
526
|
* 在不改动当前 Runtime 的前提下生成一个隔离候选。
|
|
762
527
|
*
|
|
763
528
|
* @remarks
|
|
764
529
|
* `AgentRuntimeKernel` 在初始化或重载时调用它。
|
|
765
530
|
*
|
|
766
|
-
*
|
|
531
|
+
* 任何合并、校验或 Tool Surface 构建失败都不会产生 commit。
|
|
767
532
|
*
|
|
768
533
|
* 该函数有意不从包入口导出,提交生命周期只能由 Kernel 控制。
|
|
769
534
|
*
|
|
770
535
|
* @internal
|
|
771
536
|
*/
|
|
772
537
|
export async function prepareRuntimeCandidate(
|
|
773
|
-
|
|
538
|
+
input: RuntimeAssemblyInput,
|
|
774
539
|
): Promise<RuntimeCandidate> {
|
|
775
|
-
validatePluginKinds(config.plugins);
|
|
776
|
-
|
|
777
|
-
const prepared = await Promise.all(
|
|
778
|
-
config.plugins.map(async (plugin) => {
|
|
779
|
-
const result = await plugin.prepare();
|
|
780
|
-
if (result.kind !== plugin.kind) {
|
|
781
|
-
throw new Error(
|
|
782
|
-
`Prepared Agent Plugin kind mismatch: expected ${plugin.kind}, got ${result.kind}`,
|
|
783
|
-
);
|
|
784
|
-
}
|
|
785
|
-
return result;
|
|
786
|
-
}),
|
|
787
|
-
);
|
|
788
|
-
const byKind = new Map(
|
|
789
|
-
prepared.map((plugin) => [plugin.kind, plugin]),
|
|
790
|
-
);
|
|
791
540
|
const builder = new RuntimeBuilder();
|
|
792
|
-
|
|
793
|
-
for (const kind of PLUGIN_ORDER) {
|
|
794
|
-
const plugin = byKind.get(kind);
|
|
795
|
-
if (!plugin) continue;
|
|
796
|
-
builder.merge(plugin);
|
|
797
|
-
}
|
|
798
|
-
|
|
541
|
+
builder.merge(input);
|
|
799
542
|
return builder.build();
|
|
800
543
|
}
|
|
801
544
|
|
|
@@ -809,15 +552,246 @@ export async function prepareRuntimeCandidate(
|
|
|
809
552
|
*
|
|
810
553
|
* @internal
|
|
811
554
|
*/
|
|
812
|
-
export async function
|
|
813
|
-
|
|
555
|
+
export async function assembleRuntime(
|
|
556
|
+
input: RuntimeAssemblyInput,
|
|
814
557
|
commit: (snapshot: RuntimeSnapshot) => void,
|
|
815
558
|
): Promise<void> {
|
|
816
|
-
const candidate = await prepareRuntimeCandidate(
|
|
559
|
+
const candidate = await prepareRuntimeCandidate(input);
|
|
817
560
|
for (const guard of candidate.commitGuards) {
|
|
818
561
|
await guard();
|
|
819
562
|
}
|
|
820
563
|
commit(candidate.snapshot);
|
|
821
564
|
}
|
|
822
565
|
|
|
566
|
+
export function toolRegistryPiToolCandidates(
|
|
567
|
+
registry: ToolRegistry,
|
|
568
|
+
settings?: Pick<RuntimeSettings, "toolPolicy">,
|
|
569
|
+
): PiToolCandidate[] {
|
|
570
|
+
const deny = new Set(settings?.toolPolicy?.denyPolicy?.deny ?? []);
|
|
571
|
+
const allowsTool = settings?.toolPolicy?.allowsTool;
|
|
572
|
+
const candidates: PiToolCandidate[] = [];
|
|
573
|
+
for (const [name, spec] of Object.entries(registry)) {
|
|
574
|
+
if (deny.has(name)) continue;
|
|
575
|
+
if (allowsTool?.(name) === false) continue;
|
|
576
|
+
const normalized = requiredName(name, "Platform Tool");
|
|
577
|
+
candidates.push(Object.freeze({
|
|
578
|
+
owner: "platform",
|
|
579
|
+
requiredExecutionLevel: spec.requiredExecutionLevel,
|
|
580
|
+
...(spec.alwaysRequiresApproval
|
|
581
|
+
? { alwaysRequiresApproval: true }
|
|
582
|
+
: {}),
|
|
583
|
+
tool: Object.freeze({
|
|
584
|
+
name: normalized,
|
|
585
|
+
label: spec.label,
|
|
586
|
+
description: spec.description,
|
|
587
|
+
parameters: spec.parameters,
|
|
588
|
+
async execute(
|
|
589
|
+
toolCallId: string,
|
|
590
|
+
input: unknown,
|
|
591
|
+
signal?: AbortSignal,
|
|
592
|
+
) {
|
|
593
|
+
const result = await spec.execute(input, {
|
|
594
|
+
toolCallId,
|
|
595
|
+
signal: signal ?? new AbortController().signal,
|
|
596
|
+
});
|
|
597
|
+
if (
|
|
598
|
+
result != null &&
|
|
599
|
+
typeof result === "object" &&
|
|
600
|
+
"content" in result &&
|
|
601
|
+
Array.isArray((result as { content?: unknown }).content)
|
|
602
|
+
) {
|
|
603
|
+
return result as import("@earendil-works/pi-agent-core").AgentToolResult<unknown>;
|
|
604
|
+
}
|
|
605
|
+
let text: string;
|
|
606
|
+
try {
|
|
607
|
+
text = JSON.stringify(result) ?? String(result);
|
|
608
|
+
} catch {
|
|
609
|
+
text = String(result);
|
|
610
|
+
}
|
|
611
|
+
return {
|
|
612
|
+
content: [{ type: "text" as const, text }],
|
|
613
|
+
details: result,
|
|
614
|
+
};
|
|
615
|
+
},
|
|
616
|
+
} as AgentTool<any, any>),
|
|
617
|
+
}));
|
|
618
|
+
}
|
|
619
|
+
return candidates;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
function hooksToTurnEventsPort<
|
|
623
|
+
Env extends Cloudflare.Env,
|
|
624
|
+
Config,
|
|
625
|
+
Command,
|
|
626
|
+
Change,
|
|
627
|
+
>(
|
|
628
|
+
ctx: AssembleRuntimeSnapshotInput<Env, Config, Command, Change>["ctx"],
|
|
629
|
+
hooks?: RuntimeAgentHooks<Env, Config, Command, Change>,
|
|
630
|
+
): RuntimeTurnEventsPort | undefined {
|
|
631
|
+
if (!hooks) return undefined;
|
|
632
|
+
if (
|
|
633
|
+
!hooks.onTurnEnd &&
|
|
634
|
+
!hooks.onModelUsage &&
|
|
635
|
+
!hooks.onToolStart &&
|
|
636
|
+
!hooks.onToolSettled &&
|
|
637
|
+
!hooks.onApproval &&
|
|
638
|
+
!hooks.onActivityChanged &&
|
|
639
|
+
!hooks.onSubmissionTerminal
|
|
640
|
+
) {
|
|
641
|
+
return undefined;
|
|
642
|
+
}
|
|
643
|
+
return {
|
|
644
|
+
onResponse: hooks.onTurnEnd
|
|
645
|
+
? (messages) => hooks.onTurnEnd!(ctx, messages)
|
|
646
|
+
: async () => undefined,
|
|
647
|
+
...(hooks.onModelUsage ? { onModelUsage: hooks.onModelUsage } : {}),
|
|
648
|
+
...(hooks.onToolStart ? { onToolStart: hooks.onToolStart } : {}),
|
|
649
|
+
...(hooks.onToolSettled ? { onToolSettled: hooks.onToolSettled } : {}),
|
|
650
|
+
...(hooks.onApproval ? { onApproval: hooks.onApproval } : {}),
|
|
651
|
+
...(hooks.onActivityChanged
|
|
652
|
+
? { onActivityChanged: hooks.onActivityChanged }
|
|
653
|
+
: {}),
|
|
654
|
+
...(hooks.onSubmissionTerminal
|
|
655
|
+
? { onSubmissionTerminal: hooks.onSubmissionTerminal }
|
|
656
|
+
: {}),
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* 从 Config、Tool 和已加载 Resource 装配 Runtime 候选 Snapshot。
|
|
662
|
+
*
|
|
663
|
+
* @internal
|
|
664
|
+
*/
|
|
665
|
+
export async function assembleRuntimeSnapshot<
|
|
666
|
+
Env extends Cloudflare.Env,
|
|
667
|
+
Config,
|
|
668
|
+
Command = never,
|
|
669
|
+
Change = never,
|
|
670
|
+
>(
|
|
671
|
+
input: AssembleRuntimeSnapshotInput<Env, Config, Command, Change>,
|
|
672
|
+
): Promise<RuntimeCandidate> {
|
|
673
|
+
const resources = input.resources;
|
|
674
|
+
const toolAssembly = input.tools;
|
|
675
|
+
const settings = resources.settings;
|
|
676
|
+
const provider = resources.provider;
|
|
677
|
+
let profile = settings.profile;
|
|
678
|
+
if (input.hooks?.profileOverrides) {
|
|
679
|
+
const overrides = await withRuntimeLoadTimeout(
|
|
680
|
+
"profile-overrides",
|
|
681
|
+
() => input.hooks!.profileOverrides!(
|
|
682
|
+
input.ctx,
|
|
683
|
+
input.config,
|
|
684
|
+
),
|
|
685
|
+
);
|
|
686
|
+
if (overrides.systemPrompt !== undefined) {
|
|
687
|
+
profile = { ...profile, systemPrompt: overrides.systemPrompt };
|
|
688
|
+
}
|
|
689
|
+
if (overrides.executionLevel !== undefined) {
|
|
690
|
+
profile = { ...profile, executionLevel: overrides.executionLevel };
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
const hostTools = toolRegistryPiToolCandidates(
|
|
695
|
+
toolAssembly.tools,
|
|
696
|
+
settings,
|
|
697
|
+
);
|
|
698
|
+
|
|
699
|
+
const commitGuards: Array<() => Promise<void>> = [];
|
|
700
|
+
if (toolAssembly.commitGuard) commitGuards.push(toolAssembly.commitGuard);
|
|
701
|
+
if (input.hooks?.beforeCommit) {
|
|
702
|
+
for (const guard of input.hooks.beforeCommit) {
|
|
703
|
+
commitGuards.push(() => guard(input.ctx, input.config));
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
const platform: RuntimePlatformPort = input.hooks?.gateTool
|
|
708
|
+
? Object.freeze({
|
|
709
|
+
...resources.platform,
|
|
710
|
+
gateTool: (request: {
|
|
711
|
+
toolCallId: string;
|
|
712
|
+
toolName: string;
|
|
713
|
+
input: unknown;
|
|
714
|
+
requiredExecutionLevel: import("./lib/execution-level").ExecutionLevel;
|
|
715
|
+
signal: AbortSignal;
|
|
716
|
+
}) => input.hooks!.gateTool!(request),
|
|
717
|
+
})
|
|
718
|
+
: resources.platform;
|
|
719
|
+
|
|
720
|
+
const memoryProfile =
|
|
721
|
+
toolAssembly.memoryProfile ?? settings.memoryProfile;
|
|
722
|
+
const enabledSubagents =
|
|
723
|
+
toolAssembly.enabledSubagents ?? settings.enabledSubagents;
|
|
724
|
+
const turnEvents = hooksToTurnEventsPort(input.ctx, input.hooks);
|
|
725
|
+
|
|
726
|
+
const toolPolicy: RuntimeToolSurfacePolicy | undefined =
|
|
727
|
+
settings.toolPolicy || toolAssembly.surfacePolicy
|
|
728
|
+
? {
|
|
729
|
+
...(settings.toolPolicy?.denyPolicy
|
|
730
|
+
? { denyPolicy: settings.toolPolicy.denyPolicy }
|
|
731
|
+
: {}),
|
|
732
|
+
...(settings.toolPolicy?.allowsTool
|
|
733
|
+
? { allowsTool: settings.toolPolicy.allowsTool }
|
|
734
|
+
: {}),
|
|
735
|
+
...(settings.toolPolicy?.allowsExtension
|
|
736
|
+
? { allowsExtension: settings.toolPolicy.allowsExtension }
|
|
737
|
+
: {}),
|
|
738
|
+
...(toolAssembly.surfacePolicy?.allowsTool
|
|
739
|
+
? { allowsTool: toolAssembly.surfacePolicy.allowsTool }
|
|
740
|
+
: {}),
|
|
741
|
+
...(toolAssembly.surfacePolicy?.allowsExtension
|
|
742
|
+
? { allowsExtension: toolAssembly.surfacePolicy.allowsExtension }
|
|
743
|
+
: {}),
|
|
744
|
+
}
|
|
745
|
+
: undefined;
|
|
746
|
+
|
|
747
|
+
const assemblyInput: RuntimeAssemblyInput = {
|
|
748
|
+
profile,
|
|
749
|
+
memoryProfile,
|
|
750
|
+
...(toolPolicy ? { toolPolicy } : {}),
|
|
751
|
+
enabledSubagents: [...enabledSubagents],
|
|
752
|
+
provider,
|
|
753
|
+
platform,
|
|
754
|
+
...(toolAssembly.bindings?.workspace
|
|
755
|
+
? { workspace: toolAssembly.bindings.workspace }
|
|
756
|
+
: {}),
|
|
757
|
+
...(memoryProfile.enabled && toolAssembly.bindings?.memory
|
|
758
|
+
? { memory: toolAssembly.bindings.memory }
|
|
759
|
+
: {}),
|
|
760
|
+
hostTools,
|
|
761
|
+
skills: resources.skills,
|
|
762
|
+
connectors: resources.connectors.servers,
|
|
763
|
+
...(resources.connectors.gateway
|
|
764
|
+
? { gateway: resources.connectors.gateway }
|
|
765
|
+
: {}),
|
|
766
|
+
extensions: resources.extensions,
|
|
767
|
+
...(turnEvents ? { turnEvents } : {}),
|
|
768
|
+
commitGuards: [],
|
|
769
|
+
degradations: [
|
|
770
|
+
...(toolAssembly.degradations ?? []),
|
|
771
|
+
...(resources.degradations ?? []),
|
|
772
|
+
...resources.connectors.degradations,
|
|
773
|
+
],
|
|
774
|
+
};
|
|
775
|
+
|
|
776
|
+
const candidate = await prepareRuntimeCandidate(assemblyInput);
|
|
777
|
+
return Object.freeze({
|
|
778
|
+
snapshot: candidate.snapshot,
|
|
779
|
+
commitGuards: Object.freeze([
|
|
780
|
+
...candidate.commitGuards,
|
|
781
|
+
...commitGuards,
|
|
782
|
+
]),
|
|
783
|
+
...(input.hooks
|
|
784
|
+
? {
|
|
785
|
+
hooks: input.hooks as unknown as RuntimeAgentHooks<
|
|
786
|
+
Cloudflare.Env,
|
|
787
|
+
unknown,
|
|
788
|
+
never,
|
|
789
|
+
never
|
|
790
|
+
>,
|
|
791
|
+
}
|
|
792
|
+
: {}),
|
|
793
|
+
...(turnEvents ? { turnEvents } : {}),
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
|
|
823
797
|
// #endregion
|