@springbrand/agent-runtime 0.2.0-alpha.34 → 0.2.0-alpha.36
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/adapter/cloudflare/index.ts +0 -1
- package/src/adapter/cloudflare/universal-agent/tools.ts +17 -30
- package/src/index.ts +5 -32
- package/src/kernel/bindings.ts +6 -6
- package/src/pi/assembly/extensions.ts +23 -38
- package/src/pi/assembly/snapshot.ts +7 -1
- package/src/pi/runtime-adapter/assembly.ts +19 -14
- package/src/pi/runtime-adapter/execution.ts +7 -10
- package/src/pi/runtime-adapter/recovery.ts +15 -34
- package/src/pi/runtime-adapter/transcript.ts +5 -12
- package/src/pi/tool/base.ts +0 -15
- package/src/pi/tool/compiler.ts +0 -2
- package/src/pi/tool/core-host.ts +125 -49
- package/src/pi/tool/core.ts +8 -3
- package/src/pi/tool/nested-tools.ts +42 -0
- package/src/pi/tool/schedule.ts +0 -9
- package/src/pi/tool/skill.ts +10 -21
- package/src/pi/tool/subagent.ts +0 -13
- package/src/pi/tool/workspace-revision.ts +0 -12
- package/src/pi/tool/workspace-sandbox.ts +0 -10
- package/src/runtime-agent.ts +5 -9
- package/src/runtime-assembler.ts +57 -89
- package/src/runtime-definition.ts +30 -20
- package/src/runtime.ts +18 -3
- package/src/kernel/tool-surface.ts +0 -42
- package/src/tool-registry.ts +0 -142
package/src/runtime-assembler.ts
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
} from "./lib/execution-level";
|
|
30
30
|
import {
|
|
31
31
|
createPiRuntimeAssembly,
|
|
32
|
+
type FinalizedPiToolSurface,
|
|
32
33
|
type PiToolSurface,
|
|
33
34
|
type PiRuntimeAssembly,
|
|
34
35
|
} from "./pi/assembly/snapshot";
|
|
@@ -43,11 +44,7 @@ import type {
|
|
|
43
44
|
RuntimeSkillContribution,
|
|
44
45
|
RuntimeToolSurfacePolicy,
|
|
45
46
|
} from "./runtime-definition";
|
|
46
|
-
import {
|
|
47
|
-
toolRegistryFromPiCandidates,
|
|
48
|
-
type RuntimeCodeExecutionFactory,
|
|
49
|
-
type ToolRegistry,
|
|
50
|
-
} from "./tool-registry";
|
|
47
|
+
import type { RuntimeCodeExecutionFactory } from "./kernel/bindings";
|
|
51
48
|
import { withRuntimeLoadTimeout } from "./kernel/runtime-load";
|
|
52
49
|
import {
|
|
53
50
|
basePiToolCandidates,
|
|
@@ -198,9 +195,13 @@ async function createToolSurface(
|
|
|
198
195
|
const classify = (candidate: PiToolCandidate): PiToolCandidate =>
|
|
199
196
|
Object.freeze({
|
|
200
197
|
...candidate,
|
|
201
|
-
...(defersTool
|
|
202
|
-
? {
|
|
203
|
-
|
|
198
|
+
...(defersTool
|
|
199
|
+
? {
|
|
200
|
+
deferLoading: defersTool(candidate.tool.name) === true
|
|
201
|
+
? true as const
|
|
202
|
+
: undefined,
|
|
203
|
+
}
|
|
204
|
+
: {}),
|
|
204
205
|
});
|
|
205
206
|
// 平台没有浏览器能力时注册空集:宁可没有这个 Tool,也不注册一个必然失败的 Tool 误导模型。
|
|
206
207
|
// `create()` 推迟到确认这个名字真的可见之后,被 deny 的装配不白建一个浏览器连接器。
|
|
@@ -267,7 +268,10 @@ async function createToolSurface(
|
|
|
267
268
|
deny.has("execute") ||
|
|
268
269
|
allowsTool?.("execute") === false
|
|
269
270
|
) {
|
|
270
|
-
return Object.freeze(
|
|
271
|
+
return Object.freeze({
|
|
272
|
+
candidates: Object.freeze(directVisible.map(classify)),
|
|
273
|
+
codeExecutionCandidates: Object.freeze([]),
|
|
274
|
+
}) satisfies FinalizedPiToolSurface;
|
|
271
275
|
}
|
|
272
276
|
const mergeable = finalized.filter(
|
|
273
277
|
(candidate) =>
|
|
@@ -275,11 +279,40 @@ async function createToolSurface(
|
|
|
275
279
|
!candidate.interaction &&
|
|
276
280
|
typeof candidate.tool.execute === "function",
|
|
277
281
|
);
|
|
278
|
-
const
|
|
282
|
+
const codeExecutionCandidates = Object.freeze([...mergeable]);
|
|
283
|
+
const codeExecutionToolNames = new Set(
|
|
284
|
+
codeExecutionCandidates.map(({ tool }) => tool.name),
|
|
285
|
+
);
|
|
279
286
|
const codeExecution = input.codeExecution.create(
|
|
280
|
-
|
|
287
|
+
codeExecutionCandidates,
|
|
288
|
+
);
|
|
289
|
+
const topLevelOnly = directVisible.filter(
|
|
290
|
+
({ tool }) => !codeExecutionToolNames.has(tool.name),
|
|
281
291
|
);
|
|
282
|
-
const
|
|
292
|
+
const routeList = (deferred: boolean) => {
|
|
293
|
+
const matches = topLevelOnly.filter((candidate) =>
|
|
294
|
+
(defersTool?.(candidate.tool.name) === true) === deferred
|
|
295
|
+
);
|
|
296
|
+
return matches.length > 0
|
|
297
|
+
? matches.map(({ tool }) =>
|
|
298
|
+
`- \`${tool.name}\` — ${(tool.label ?? tool.name)
|
|
299
|
+
.replaceAll(/\s+/g, " ").trim().replaceAll("`", "'")}`
|
|
300
|
+
).join("\n")
|
|
301
|
+
: "- None.";
|
|
302
|
+
};
|
|
303
|
+
const routeGuidance = [
|
|
304
|
+
"## Tool routing",
|
|
305
|
+
"Top-level deferred Tools are not callable through `tools.*`. Use Provider Tool Search with their exact name, then call them directly.",
|
|
306
|
+
"Top-level immediate Tools are already available outside execute; call them directly.",
|
|
307
|
+
"",
|
|
308
|
+
"## Top-level deferred Tools",
|
|
309
|
+
routeList(true),
|
|
310
|
+
"",
|
|
311
|
+
"## Top-level immediate Tools",
|
|
312
|
+
routeList(false),
|
|
313
|
+
"",
|
|
314
|
+
].join("\n");
|
|
315
|
+
const materializeGuidance = codeExecutionCandidates.some(
|
|
283
316
|
({ tool }) => tool.name === "materialize_skill_resource",
|
|
284
317
|
)
|
|
285
318
|
? "Skill resource copying is available only inside execute through " +
|
|
@@ -287,18 +320,17 @@ async function createToolSurface(
|
|
|
287
320
|
"no Direct Tool is registered for it. " +
|
|
288
321
|
"Use a loop or Promise.all when copying multiple resources.\n\n"
|
|
289
322
|
: "";
|
|
290
|
-
return Object.freeze(
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
),
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
]);
|
|
323
|
+
return Object.freeze({
|
|
324
|
+
candidates: Object.freeze([
|
|
325
|
+
classify(codeExecutionPiToolCandidate({
|
|
326
|
+
...codeExecution,
|
|
327
|
+
description:
|
|
328
|
+
routeGuidance + "\n" + materializeGuidance + codeExecution.description,
|
|
329
|
+
})),
|
|
330
|
+
...directVisible.map(classify),
|
|
331
|
+
]),
|
|
332
|
+
codeExecutionCandidates,
|
|
333
|
+
}) satisfies FinalizedPiToolSurface;
|
|
302
334
|
},
|
|
303
335
|
}),
|
|
304
336
|
extensions: input.extensions.filter(
|
|
@@ -658,67 +690,6 @@ export async function assembleRuntime(
|
|
|
658
690
|
commit(candidate.snapshot);
|
|
659
691
|
}
|
|
660
692
|
|
|
661
|
-
export function toolRegistryPiToolCandidates(
|
|
662
|
-
registry: ToolRegistry,
|
|
663
|
-
settings?: Pick<RuntimeSettings, "toolPolicy">,
|
|
664
|
-
): PiToolCandidate[] {
|
|
665
|
-
const deny = new Set(settings?.toolPolicy?.denyPolicy?.deny ?? []);
|
|
666
|
-
const allowsTool = settings?.toolPolicy?.allowsTool;
|
|
667
|
-
const candidates: PiToolCandidate[] = [];
|
|
668
|
-
for (const [name, spec] of Object.entries(registry)) {
|
|
669
|
-
if (deny.has(name)) continue;
|
|
670
|
-
if (allowsTool?.(name) === false) continue;
|
|
671
|
-
const normalized = requiredName(name, "Platform Tool");
|
|
672
|
-
const {
|
|
673
|
-
label,
|
|
674
|
-
description,
|
|
675
|
-
parameters,
|
|
676
|
-
execute,
|
|
677
|
-
owner = "platform",
|
|
678
|
-
...metadata
|
|
679
|
-
} = spec;
|
|
680
|
-
candidates.push(Object.freeze({
|
|
681
|
-
...metadata,
|
|
682
|
-
owner,
|
|
683
|
-
tool: Object.freeze({
|
|
684
|
-
name: normalized,
|
|
685
|
-
label,
|
|
686
|
-
description,
|
|
687
|
-
parameters,
|
|
688
|
-
async execute(
|
|
689
|
-
toolCallId: string,
|
|
690
|
-
input: unknown,
|
|
691
|
-
signal?: AbortSignal,
|
|
692
|
-
) {
|
|
693
|
-
const result = await execute(input, {
|
|
694
|
-
toolCallId,
|
|
695
|
-
signal: signal ?? new AbortController().signal,
|
|
696
|
-
});
|
|
697
|
-
if (
|
|
698
|
-
result != null &&
|
|
699
|
-
typeof result === "object" &&
|
|
700
|
-
"content" in result &&
|
|
701
|
-
Array.isArray((result as { content?: unknown }).content)
|
|
702
|
-
) {
|
|
703
|
-
return result as import("@earendil-works/pi-agent-core").AgentToolResult<unknown>;
|
|
704
|
-
}
|
|
705
|
-
let text: string;
|
|
706
|
-
try {
|
|
707
|
-
text = JSON.stringify(result) ?? String(result);
|
|
708
|
-
} catch {
|
|
709
|
-
text = String(result);
|
|
710
|
-
}
|
|
711
|
-
return {
|
|
712
|
-
content: [{ type: "text" as const, text }],
|
|
713
|
-
details: result,
|
|
714
|
-
};
|
|
715
|
-
},
|
|
716
|
-
} as AgentTool<any, any>),
|
|
717
|
-
}));
|
|
718
|
-
}
|
|
719
|
-
return candidates;
|
|
720
|
-
}
|
|
721
|
-
|
|
722
693
|
function hooksToTurnEventsPort<
|
|
723
694
|
Env extends Cloudflare.Env,
|
|
724
695
|
Config,
|
|
@@ -795,10 +766,7 @@ export async function assembleRuntimeSnapshot<
|
|
|
795
766
|
}
|
|
796
767
|
}
|
|
797
768
|
|
|
798
|
-
const hostTools =
|
|
799
|
-
toolAssembly.tools,
|
|
800
|
-
settings,
|
|
801
|
-
);
|
|
769
|
+
const hostTools = toolAssembly.tools;
|
|
802
770
|
|
|
803
771
|
const commitGuards: Array<() => Promise<void>> = [];
|
|
804
772
|
if (toolAssembly.commitGuard) commitGuards.push(toolAssembly.commitGuard);
|
|
@@ -22,13 +22,41 @@ import type {
|
|
|
22
22
|
import type { RuntimeExtensionConfig } from "./kernel/extensions";
|
|
23
23
|
import type { RuntimeActivityProjection } from "./kernel/state";
|
|
24
24
|
import type { RuntimeDegradation } from "./kernel/degradation";
|
|
25
|
+
import type { PiToolCandidate } from "./pi/tool/compiler";
|
|
25
26
|
import type {
|
|
26
27
|
RuntimeAgentContext,
|
|
27
28
|
RuntimeAssemblyContext,
|
|
28
29
|
RuntimeAgentPlanningContext,
|
|
29
30
|
} from "./runtime-agent-context";
|
|
30
31
|
import type { AgentTelemetryBinding } from "./telemetry/contract";
|
|
31
|
-
|
|
32
|
+
|
|
33
|
+
/** Tool Surface 筛选策略(不含 Manifest deny 列表)。 */
|
|
34
|
+
export interface ToolSurfaceSelectionPolicy {
|
|
35
|
+
readonly allowsTool?: (name: string) => boolean;
|
|
36
|
+
readonly allowsExtension?: (extension: RuntimeExtensionConfig) => boolean;
|
|
37
|
+
readonly defersTool?: (name: string) => boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Kernel 绑定仍需要的执行后端;不出现在 Definition 公开类型里。 */
|
|
41
|
+
export interface RuntimeToolBindings {
|
|
42
|
+
readonly workspace?: import("./kernel/bindings").WorkspacePort;
|
|
43
|
+
readonly codeExecution?: import("./kernel/bindings").RuntimeCodeExecutionFactory;
|
|
44
|
+
readonly memory?: import("./kernel/bindings").RuntimeMemoryPort;
|
|
45
|
+
readonly subagents?: import("./kernel/bindings").RuntimeSubagentPort;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Host 一次装配原子提交的 Tool candidates 与 Runtime 绑定。 */
|
|
49
|
+
export interface ToolAssemblyResult {
|
|
50
|
+
readonly tools: readonly PiToolCandidate[];
|
|
51
|
+
readonly bindings?: RuntimeToolBindings;
|
|
52
|
+
readonly memoryProfile?: RuntimeMemoryProfile;
|
|
53
|
+
readonly enabledSubagents?: readonly string[];
|
|
54
|
+
readonly degradations?: readonly RuntimeDegradation[];
|
|
55
|
+
readonly surfacePolicy?: ToolSurfaceSelectionPolicy;
|
|
56
|
+
readonly commitGuard?: () => Promise<void>;
|
|
57
|
+
/** 释放本次装配创建的外部资源;临时 Agent 终止后由 Runtime 调用。 */
|
|
58
|
+
readonly dispose?: () => Promise<void>;
|
|
59
|
+
}
|
|
32
60
|
|
|
33
61
|
export interface RuntimeProfileContribution {
|
|
34
62
|
readonly model: string;
|
|
@@ -63,24 +91,6 @@ export interface GateToolRequest {
|
|
|
63
91
|
readonly signal: AbortSignal;
|
|
64
92
|
}
|
|
65
93
|
|
|
66
|
-
export type {
|
|
67
|
-
PlatformToolContext,
|
|
68
|
-
PlatformToolRegistry,
|
|
69
|
-
PlatformToolSpec,
|
|
70
|
-
RuntimeToolBindings,
|
|
71
|
-
ToolAssemblyResult,
|
|
72
|
-
ToolContext,
|
|
73
|
-
ToolRegistry,
|
|
74
|
-
ToolSpec,
|
|
75
|
-
} from "./tool-registry";
|
|
76
|
-
export {
|
|
77
|
-
emptyPlatformToolRegistry,
|
|
78
|
-
emptyToolRegistry,
|
|
79
|
-
mergeToolRegistries,
|
|
80
|
-
normalizeToolAssembly,
|
|
81
|
-
toolRegistryFromPiCandidates,
|
|
82
|
-
} from "./tool-registry";
|
|
83
|
-
|
|
84
94
|
export interface ResolvedConnectors {
|
|
85
95
|
readonly servers: readonly RuntimeMcpServer[];
|
|
86
96
|
readonly gateway?: RuntimeGatewayPort;
|
|
@@ -181,7 +191,7 @@ export interface AssembleRuntimeSnapshotInput<
|
|
|
181
191
|
> {
|
|
182
192
|
readonly ctx: RuntimeAgentPlanningContext<Env, Command, Change>;
|
|
183
193
|
readonly config: Config;
|
|
184
|
-
readonly tools:
|
|
194
|
+
readonly tools: ToolAssemblyResult;
|
|
185
195
|
readonly resources: ResolvedResources;
|
|
186
196
|
readonly hooks?: RuntimeAgentHooks<Env, Config, Command, Change>;
|
|
187
197
|
readonly telemetry?: AgentTelemetryBinding;
|
package/src/runtime.ts
CHANGED
|
@@ -2279,15 +2279,30 @@ export abstract class AgentRuntimeKernel<
|
|
|
2279
2279
|
): PiRecoveryDecision {
|
|
2280
2280
|
let decision = this.decidePiRecovery(submission);
|
|
2281
2281
|
for (const settlement of decision.recoveredToolSettlements) {
|
|
2282
|
+
const message = settlement.message;
|
|
2282
2283
|
if (
|
|
2283
2284
|
this.readToolSettlement(
|
|
2284
2285
|
submission.submissionId,
|
|
2285
|
-
|
|
2286
|
+
message.toolCallId,
|
|
2286
2287
|
)
|
|
2287
2288
|
) {
|
|
2288
2289
|
continue;
|
|
2289
2290
|
}
|
|
2290
|
-
this.settleToolSync(submission.submissionId,
|
|
2291
|
+
this.settleToolSync(submission.submissionId, {
|
|
2292
|
+
toolCallId: message.toolCallId,
|
|
2293
|
+
toolName: message.toolName,
|
|
2294
|
+
args: settlement.args,
|
|
2295
|
+
result: {
|
|
2296
|
+
content: message.content,
|
|
2297
|
+
details: message.details,
|
|
2298
|
+
...(message.usage ? { usage: message.usage } : {}),
|
|
2299
|
+
...(message.addedToolNames?.length
|
|
2300
|
+
? { addedToolNames: message.addedToolNames }
|
|
2301
|
+
: {}),
|
|
2302
|
+
},
|
|
2303
|
+
isError: message.isError,
|
|
2304
|
+
createdAt: message.timestamp,
|
|
2305
|
+
});
|
|
2291
2306
|
decision = this.decidePiRecovery(submission);
|
|
2292
2307
|
}
|
|
2293
2308
|
const results = this.transcript.orderRecoveredToolSettlements(
|
|
@@ -4198,7 +4213,7 @@ export abstract class AgentRuntimeKernel<
|
|
|
4198
4213
|
);
|
|
4199
4214
|
}
|
|
4200
4215
|
const result = decision.recoveredToolSettlements.find(
|
|
4201
|
-
(item) => item.toolCallId === approval.toolCallId,
|
|
4216
|
+
(item) => item.message.toolCallId === approval.toolCallId,
|
|
4202
4217
|
);
|
|
4203
4218
|
if (!result) {
|
|
4204
4219
|
throw new Error(
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { ExecutionLevel } from "../lib/execution-level";
|
|
2
|
-
import type { PiToolCandidate } from "../pi/tool/compiler";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Tool Surface 的形状类型。
|
|
6
|
-
*
|
|
7
|
-
* @remarks
|
|
8
|
-
* `kernel/bindings.ts` 和 `tool-registry.ts` 都要用它们,所以它们不能住在其中任何
|
|
9
|
-
* 一边:`RuntimeBindings.codeExecution` 的工厂签名需要 `ToolRegistry`,而
|
|
10
|
-
* `tool-registry.ts` 又需要 bindings 里的各个 Port —— 两边互相 import 就形成了
|
|
11
|
-
* depcruise 的 no-circular 违规(`bindings → tool-registry → bindings`)。
|
|
12
|
-
*
|
|
13
|
-
* 这里只放形状,不放行为:注册表的合并、筛选和构造仍然留在 `tool-registry.ts`。
|
|
14
|
-
*
|
|
15
|
-
* 术语见 `../index.ts`。
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/** 模型调用 Tool 时传给 `execute` 的上下文。 */
|
|
19
|
-
export interface ToolContext {
|
|
20
|
-
readonly toolCallId: string;
|
|
21
|
-
readonly signal: AbortSignal;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** Definition 作者声明的一个 Tool。 */
|
|
25
|
-
export interface ToolSpec extends Partial<
|
|
26
|
-
Omit<PiToolCandidate, "tool" | "requiredExecutionLevel">
|
|
27
|
-
> {
|
|
28
|
-
readonly label: string;
|
|
29
|
-
readonly description: string;
|
|
30
|
-
readonly parameters: unknown;
|
|
31
|
-
readonly requiredExecutionLevel: ExecutionLevel;
|
|
32
|
-
/** Require a fresh human decision for every call, regardless of execution level. */
|
|
33
|
-
readonly alwaysRequiresApproval?: boolean;
|
|
34
|
-
/** Preserve adapted Pi result envelopes; only details-only adapters may unwrap them. */
|
|
35
|
-
readonly execute: (
|
|
36
|
-
input: unknown,
|
|
37
|
-
ctx: ToolContext,
|
|
38
|
-
) => Promise<unknown>;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** 一次装配声明的全部 Tool,键即模型可见的工具名。 */
|
|
42
|
-
export type ToolRegistry = Record<string, ToolSpec>;
|
package/src/tool-registry.ts
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
RuntimeCodeExecutionFactory,
|
|
3
|
-
RuntimeMemoryPort,
|
|
4
|
-
RuntimeSubagentPort,
|
|
5
|
-
WorkspacePort,
|
|
6
|
-
} from "./kernel/bindings";
|
|
7
|
-
import type { RuntimeExtensionConfig } from "./kernel/extensions";
|
|
8
|
-
import type { RuntimeDegradation } from "./kernel/degradation";
|
|
9
|
-
import type {
|
|
10
|
-
ToolContext,
|
|
11
|
-
ToolRegistry,
|
|
12
|
-
ToolSpec,
|
|
13
|
-
} from "./kernel/tool-surface";
|
|
14
|
-
import type { PiToolCandidate } from "./pi/tool/compiler";
|
|
15
|
-
import { validateToolArguments } from "@earendil-works/pi-ai";
|
|
16
|
-
|
|
17
|
-
// Tool Surface 的形状类型住在 `kernel/tool-surface.ts`:bindings 也要用它们,放在这里
|
|
18
|
-
// 会让 `bindings → tool-registry → bindings` 成环。这里继续导出是为了保持调用方不变。
|
|
19
|
-
export type {
|
|
20
|
-
RuntimeCodeExecutionFactory,
|
|
21
|
-
ToolContext,
|
|
22
|
-
ToolRegistry,
|
|
23
|
-
ToolSpec,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/** Tool Surface 筛选策略(不含 Manifest deny 列表)。 */
|
|
27
|
-
export interface ToolSurfaceSelectionPolicy {
|
|
28
|
-
readonly allowsTool?: (name: string) => boolean;
|
|
29
|
-
readonly allowsExtension?: (extension: RuntimeExtensionConfig) => boolean;
|
|
30
|
-
readonly defersTool?: (name: string) => boolean;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function emptyToolRegistry(): ToolRegistry {
|
|
34
|
-
return {};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function mergeToolRegistries(...registries: ToolRegistry[]): ToolRegistry {
|
|
38
|
-
const merged: ToolRegistry = {};
|
|
39
|
-
for (const registry of registries) {
|
|
40
|
-
for (const [name, spec] of Object.entries(registry)) {
|
|
41
|
-
if (name in merged) {
|
|
42
|
-
throw new Error(`Duplicate Runtime Tool: ${name}`);
|
|
43
|
-
}
|
|
44
|
-
merged[name] = spec;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return merged;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function toolRegistryFromPiCandidates(
|
|
51
|
-
candidates:
|
|
52
|
-
| readonly PiToolCandidate[]
|
|
53
|
-
| Record<string, PiToolCandidate>,
|
|
54
|
-
): ToolRegistry {
|
|
55
|
-
const list = Array.isArray(candidates)
|
|
56
|
-
? candidates
|
|
57
|
-
: Object.values(candidates);
|
|
58
|
-
const registry: ToolRegistry = {};
|
|
59
|
-
for (const candidate of list) {
|
|
60
|
-
const name = candidate.tool.name;
|
|
61
|
-
if (!name.trim()) {
|
|
62
|
-
throw new Error("SpringBrand Tool name must not be empty");
|
|
63
|
-
}
|
|
64
|
-
registry[name] = piCandidateToToolSpec(candidate);
|
|
65
|
-
}
|
|
66
|
-
return registry;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function piCandidateToToolSpec(candidate: PiToolCandidate): ToolSpec {
|
|
70
|
-
const { tool, ...metadata } = candidate;
|
|
71
|
-
const name = tool.name;
|
|
72
|
-
return {
|
|
73
|
-
...metadata,
|
|
74
|
-
label: tool.label ?? name,
|
|
75
|
-
description: tool.description,
|
|
76
|
-
parameters: tool.parameters,
|
|
77
|
-
execute: async (input, ctx) => {
|
|
78
|
-
const execute = tool.execute;
|
|
79
|
-
if (typeof execute !== "function") {
|
|
80
|
-
throw new Error(`Tool "${name}" is not executable`);
|
|
81
|
-
}
|
|
82
|
-
const validated = validateToolArguments(tool, {
|
|
83
|
-
type: "toolCall",
|
|
84
|
-
id: ctx.toolCallId,
|
|
85
|
-
name,
|
|
86
|
-
arguments: input as Record<string, unknown>,
|
|
87
|
-
});
|
|
88
|
-
return execute(
|
|
89
|
-
ctx.toolCallId,
|
|
90
|
-
validated,
|
|
91
|
-
ctx.signal,
|
|
92
|
-
undefined,
|
|
93
|
-
);
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/** Kernel 绑定仍需要的执行后端;不出现在 Definition 公开类型里。 */
|
|
99
|
-
export interface RuntimeToolBindings {
|
|
100
|
-
readonly workspace?: WorkspacePort;
|
|
101
|
-
readonly codeExecution?: RuntimeCodeExecutionFactory;
|
|
102
|
-
readonly memory?: RuntimeMemoryPort;
|
|
103
|
-
readonly subagents?: RuntimeSubagentPort;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Worker `tools()` 可返回纯注册表,或附带 Kernel 绑定与降级信息。
|
|
108
|
-
*/
|
|
109
|
-
export interface ToolAssemblyResult {
|
|
110
|
-
readonly tools: ToolRegistry;
|
|
111
|
-
readonly bindings?: RuntimeToolBindings;
|
|
112
|
-
readonly memoryProfile?: import("./kernel/profile").RuntimeMemoryProfile;
|
|
113
|
-
readonly enabledSubagents?: readonly string[];
|
|
114
|
-
readonly degradations?: readonly RuntimeDegradation[];
|
|
115
|
-
readonly surfacePolicy?: ToolSurfaceSelectionPolicy;
|
|
116
|
-
readonly commitGuard?: () => Promise<void>;
|
|
117
|
-
/** 释放本次装配创建的外部资源;临时 Agent 终止后由 Runtime 调用。 */
|
|
118
|
-
readonly dispose?: () => Promise<void>;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function normalizeToolAssembly(
|
|
122
|
-
input: ToolRegistry | ToolAssemblyResult,
|
|
123
|
-
): ToolAssemblyResult {
|
|
124
|
-
if ("tools" in input && typeof input.tools === "object" && input.tools !== null) {
|
|
125
|
-
return input as ToolAssemblyResult;
|
|
126
|
-
}
|
|
127
|
-
return { tools: input as ToolRegistry };
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/** @deprecated 使用 `ToolSpec`。 */
|
|
131
|
-
export type PlatformToolSpec = ToolSpec;
|
|
132
|
-
|
|
133
|
-
/** @deprecated 使用 `ToolContext`。 */
|
|
134
|
-
export type PlatformToolContext = ToolContext;
|
|
135
|
-
|
|
136
|
-
/** @deprecated 使用 `ToolRegistry`。 */
|
|
137
|
-
export type PlatformToolRegistry = ToolRegistry;
|
|
138
|
-
|
|
139
|
-
/** @deprecated 使用 `emptyToolRegistry`。 */
|
|
140
|
-
export function emptyPlatformToolRegistry(): ToolRegistry {
|
|
141
|
-
return emptyToolRegistry();
|
|
142
|
-
}
|