@springbrand/agent-runtime 0.2.0-alpha.34 → 0.2.0-alpha.38

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.
@@ -2,16 +2,11 @@ import type { SkillSource } from "agents/skills";
2
2
  import type { ExecutionLevel } from "./lib/execution-level";
3
3
  import type {
4
4
  RuntimeGatewayPort,
5
- RuntimeModelUsageEvent,
6
- RuntimeSubmissionAdmissionHook,
7
- RuntimeSubagentUsageEvent,
8
- RuntimeLifecycleFact,
9
- RuntimeEventConfirmation,
10
5
  RuntimePlatformPort,
11
6
  RuntimeProviderPort,
12
7
  RuntimeSkillScriptPolicy,
13
- RuntimeToolStartEvent,
14
- RuntimeTurnMessage,
8
+ RuntimeSubmissionAdmissionHook,
9
+ RuntimeTurnEventsPort,
15
10
  } from "./kernel/bindings";
16
11
  import type {
17
12
  RuntimeDenyPolicy,
@@ -20,15 +15,41 @@ import type {
20
15
  ThinkingEffort,
21
16
  } from "./kernel/profile";
22
17
  import type { RuntimeExtensionConfig } from "./kernel/extensions";
23
- import type { RuntimeActivityProjection } from "./kernel/state";
24
18
  import type { RuntimeDegradation } from "./kernel/degradation";
19
+ import type { PiToolCandidate } from "./pi/tool/compiler";
25
20
  import type {
26
21
  RuntimeAgentContext,
27
- RuntimeAssemblyContext,
28
22
  RuntimeAgentPlanningContext,
29
23
  } from "./runtime-agent-context";
30
24
  import type { AgentTelemetryBinding } from "./telemetry/contract";
31
- import type { ToolSurfaceSelectionPolicy } from "./tool-registry";
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
+ /** Kernel 绑定仍需要的执行后端;不出现在 Definition 公开类型里。 */
34
+ export interface RuntimeToolBindings {
35
+ readonly workspace?: import("./kernel/bindings").WorkspacePort;
36
+ readonly codeExecution?: import("./kernel/bindings").RuntimeCodeExecutionFactory;
37
+ readonly memory?: import("./kernel/bindings").RuntimeMemoryPort;
38
+ readonly subagents?: import("./kernel/bindings").RuntimeSubagentPort;
39
+ }
40
+
41
+ /** Host 一次装配原子提交的 Tool candidates 与 Runtime 绑定。 */
42
+ export interface ToolAssemblyResult {
43
+ readonly tools: readonly PiToolCandidate[];
44
+ readonly bindings?: RuntimeToolBindings;
45
+ readonly memoryProfile?: RuntimeMemoryProfile;
46
+ readonly enabledSubagents?: readonly string[];
47
+ readonly degradations?: readonly RuntimeDegradation[];
48
+ readonly surfacePolicy?: ToolSurfaceSelectionPolicy;
49
+ readonly commitGuard?: () => Promise<void>;
50
+ /** 释放本次装配创建的外部资源;临时 Agent 终止后由 Runtime 调用。 */
51
+ readonly dispose?: () => Promise<void>;
52
+ }
32
53
 
33
54
  export interface RuntimeProfileContribution {
34
55
  readonly model: string;
@@ -55,32 +76,6 @@ export interface RuntimeToolSurfacePolicy extends ToolSurfaceSelectionPolicy {
55
76
 
56
77
  export type { RuntimeAgentContext, RuntimeAssemblyContext } from "./runtime-agent-context";
57
78
 
58
- export interface GateToolRequest {
59
- readonly toolCallId: string;
60
- readonly toolName: string;
61
- readonly input: unknown;
62
- readonly requiredExecutionLevel: ExecutionLevel;
63
- readonly signal: AbortSignal;
64
- }
65
-
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
79
  export interface ResolvedConnectors {
85
80
  readonly servers: readonly RuntimeMcpServer[];
86
81
  readonly gateway?: RuntimeGatewayPort;
@@ -91,81 +86,14 @@ export interface ResolvedResources {
91
86
  readonly settings: RuntimeSettings;
92
87
  readonly provider: RuntimeProviderPort;
93
88
  readonly platform: RuntimePlatformPort;
89
+ readonly turnEvents?: RuntimeTurnEventsPort;
90
+ readonly admission?: RuntimeSubmissionAdmissionHook;
94
91
  readonly skills: readonly RuntimeSkillContribution[];
95
92
  readonly extensions: readonly RuntimeExtensionContribution[];
96
93
  readonly connectors: ResolvedConnectors;
97
94
  readonly degradations?: readonly RuntimeDegradation[];
98
95
  }
99
96
 
100
- export interface ProfileOverrides {
101
- readonly systemPrompt?: string;
102
- readonly executionLevel?: ExecutionLevel;
103
- }
104
-
105
- export interface ApprovalHookInput {
106
- readonly submissionId: string;
107
- readonly approvalExecutionId: string;
108
- }
109
-
110
- export interface SubmissionTerminalHookInput {
111
- readonly submissionId: string;
112
- readonly status: "completed" | "aborted" | "skipped" | "error";
113
- readonly error?: string;
114
- readonly resultMessageId?: string;
115
- }
116
-
117
- export interface RuntimeToolSettlementEvent {
118
- readonly eventId: string;
119
- readonly submissionId: string;
120
- readonly toolCallId: string;
121
- readonly toolName: string;
122
- readonly status: "success" | "error";
123
- }
124
-
125
- export interface RuntimeAgentHooks<
126
- Env extends Cloudflare.Env = Cloudflare.Env,
127
- Config = unknown,
128
- Command = never,
129
- Change = never,
130
- > {
131
- readonly beforeCommit?: ReadonlyArray<
132
- (
133
- ctx: RuntimeAssemblyContext<Env, Command, Change>,
134
- config: Config,
135
- ) => Promise<void>
136
- >;
137
-
138
- readonly onTurnEnd?: (
139
- ctx: RuntimeAssemblyContext<Env, Command, Change>,
140
- messages: readonly RuntimeTurnMessage[],
141
- ) => Promise<void>;
142
- readonly onModelUsage?: (event: RuntimeModelUsageEvent) => Promise<void>;
143
- readonly onSubagentUsage?: (
144
- event: RuntimeSubagentUsageEvent,
145
- ) => Promise<RuntimeEventConfirmation | void>;
146
- readonly onLifecycleFact?: (
147
- event: RuntimeLifecycleFact,
148
- ) => Promise<RuntimeEventConfirmation | void>;
149
- /** Single admission seam shared by chat, RPC, regenerate and scheduled submissions. */
150
- readonly onSubmissionAdmission?: RuntimeSubmissionAdmissionHook;
151
- readonly onToolStart?: (event: RuntimeToolStartEvent) => Promise<void>;
152
- readonly onToolSettled?: (event: RuntimeToolSettlementEvent) => Promise<void>;
153
- readonly onApproval?: (input: ApprovalHookInput) => Promise<void>;
154
- readonly onActivityChanged?: (
155
- projection: RuntimeActivityProjection,
156
- ) => Promise<void>;
157
- readonly onSubmissionTerminal?: (
158
- input: SubmissionTerminalHookInput,
159
- ) => Promise<void>;
160
-
161
- readonly gateTool?: (request: GateToolRequest) => Promise<void>;
162
-
163
- readonly profileOverrides?: (
164
- ctx: RuntimeAssemblyContext<Env, Command, Change>,
165
- config: Config,
166
- ) => ProfileOverrides | Promise<ProfileOverrides>;
167
- }
168
-
169
97
  export interface RuntimeSettings {
170
98
  readonly profile: RuntimeProfileContribution;
171
99
  readonly memoryProfile: RuntimeMemoryProfile;
@@ -175,14 +103,12 @@ export interface RuntimeSettings {
175
103
 
176
104
  export interface AssembleRuntimeSnapshotInput<
177
105
  Env extends Cloudflare.Env,
178
- Config,
179
106
  Command = never,
180
107
  Change = never,
181
108
  > {
182
109
  readonly ctx: RuntimeAgentPlanningContext<Env, Command, Change>;
183
- readonly config: Config;
184
- readonly tools: import("./tool-registry").ToolAssemblyResult;
110
+ readonly tools: ToolAssemblyResult;
185
111
  readonly resources: ResolvedResources;
186
- readonly hooks?: RuntimeAgentHooks<Env, Config, Command, Change>;
112
+ readonly commitGuard?: () => Promise<void>;
187
113
  readonly telemetry?: AgentTelemetryBinding;
188
114
  }
package/src/runtime.ts CHANGED
@@ -36,7 +36,11 @@ import {
36
36
  type SubmissionReceipt,
37
37
  } from "./kernel/receipts";
38
38
  import type { ExecutionLevel } from "./lib/execution-level";
39
- import type { RuntimeGatewaySession } from "./kernel/bindings";
39
+ import type {
40
+ RuntimeGatewaySession,
41
+ RuntimeSubmissionAdmissionHook,
42
+ RuntimeTurnEventsPort,
43
+ } from "./kernel/bindings";
40
44
  import type { RuntimeAssemblyView } from "./kernel/runtime-assembly-view";
41
45
  import { projectRuntimeAssembly } from "./kernel/runtime-assembly";
42
46
  import type {
@@ -57,8 +61,6 @@ import {
57
61
  type RuntimeCandidate,
58
62
  type RuntimeSnapshot,
59
63
  } from "./runtime-assembler";
60
- import type { RuntimeAgentHooks } from "./runtime-definition";
61
- import type { RuntimeTurnEventsPort } from "./kernel/bindings";
62
64
  import {
63
65
  RuntimeTelemetryCoordinator,
64
66
  } from "./telemetry";
@@ -199,6 +201,14 @@ interface ActiveTurn {
199
201
  agent: PreparedPiTurnAdapter;
200
202
  }
201
203
 
204
+ interface ActiveRuntime {
205
+ readonly snapshot: RuntimeSnapshot;
206
+ readonly revision: string;
207
+ readonly pi: PreparedPiRuntime;
208
+ readonly gatewaySession?: RuntimeGatewaySession;
209
+ readonly admission?: RuntimeSubmissionAdmissionHook;
210
+ }
211
+
202
212
  interface PlannedContinuationData {
203
213
  readonly submissionId: string;
204
214
  readonly requestId: string;
@@ -414,12 +424,7 @@ export abstract class AgentRuntimeKernel<
414
424
 
415
425
  protected abstract ensureRuntimeReady(): Promise<void>;
416
426
 
417
- private runtimeSnapshot?: RuntimeSnapshot;
418
- private runtimeRevision?: string;
419
- private runtimePi?: PreparedPiRuntime;
420
- private runtimeGatewaySession?: RuntimeGatewaySession;
421
- private runtimeTurnEvents?: RuntimeTurnEventsPort;
422
- private runtimeHooks?: RuntimeAgentHooks;
427
+ private activeRuntime?: ActiveRuntime;
423
428
  private telemetryCoordinator?: RuntimeTelemetryCoordinator;
424
429
  private piAdapter?: PiRuntimeAdapter;
425
430
  private readonly transcript: PiRuntimeTranscript;
@@ -464,7 +469,7 @@ export abstract class AgentRuntimeKernel<
464
469
  return this.runtimeLoadTracker ??= new RuntimeLoadTracker({
465
470
  read: () => this.state.runtimeLoad,
466
471
  publish: (runtimeLoad) => this.setState({ ...this.state, runtimeLoad }),
467
- isAvailable: () => Boolean(this.runtimeSnapshot),
472
+ isAvailable: () => Boolean(this.activeRuntime),
468
473
  });
469
474
  }
470
475
 
@@ -715,14 +720,11 @@ export abstract class AgentRuntimeKernel<
715
720
  }
716
721
 
717
722
  private turnEventsPort(): RuntimeTurnEventsPort | undefined {
718
- return this.runtimeTurnEvents ?? this.runtimeSnapshot?.bindings.turnEvents;
723
+ return this.activeRuntime?.snapshot.bindings.turnEvents;
719
724
  }
720
725
 
721
726
  protected async initCandidate(candidate: RuntimeCandidate): Promise<void> {
722
- this.runtimeTurnEvents =
723
- candidate.turnEvents ?? candidate.snapshot.bindings.turnEvents;
724
- this.runtimeHooks = candidate.hooks;
725
- const previous = this.runtimeSnapshot;
727
+ const previous = this.activeRuntime;
726
728
  const candidateSnapshot = candidate.snapshot;
727
729
  this.runtimeLoad.advance("assembly");
728
730
  this.runtimeLoad.advance("mcp");
@@ -776,7 +778,7 @@ export abstract class AgentRuntimeKernel<
776
778
  // 没有任何工具在执行 —— 换装配对它是安全的,而且这正是「决定时才装上
777
779
  // 新能力,同一轮接着跑」所依赖的那一步。真正在执行的 Turn 仍然被挡住。
778
780
  const contested = Boolean(previous) &&
779
- revision !== this.runtimeRevision &&
781
+ revision !== previous?.revision &&
780
782
  this.submissions.isBusy();
781
783
  const parked = contested && this.db.everyUnfinishedSubmissionParked();
782
784
  if (contested && !parked) {
@@ -791,8 +793,17 @@ export abstract class AgentRuntimeKernel<
791
793
  () => this.prepareParkedSubmissionRepin(prepared, revision),
792
794
  )
793
795
  : undefined;
796
+ const next = Object.freeze({
797
+ snapshot: candidateSnapshot,
798
+ revision,
799
+ pi: prepared,
800
+ ...(gatewaySession ? { gatewaySession } : {}),
801
+ ...(candidate.admission
802
+ ? { admission: candidate.admission }
803
+ : {}),
804
+ }) satisfies ActiveRuntime;
794
805
  let activated = false;
795
- const previousGatewaySession = this.runtimeGatewaySession;
806
+ const previousGatewaySession = previous?.gatewaySession;
796
807
  try {
797
808
  for (const [index, guard] of candidate.commitGuards.entries()) {
798
809
  await withRuntimeLoadTimeout(`commit-guard:${index}`, guard);
@@ -800,14 +811,11 @@ export abstract class AgentRuntimeKernel<
800
811
  this.pi.activate(candidateSnapshot);
801
812
  activated = true;
802
813
  repin?.commit();
803
- this.runtimeSnapshot = candidateSnapshot;
804
- this.runtimeRevision = revision;
805
- this.runtimePi = prepared;
806
- this.runtimeGatewaySession = gatewaySession;
807
814
  this.telemetry.configure(candidate.telemetry);
815
+ this.activeRuntime = next;
808
816
  } catch (error) {
809
817
  repin?.abort();
810
- if (activated && previous) this.pi.activate(previous);
818
+ if (activated && previous) this.pi.activate(previous.snapshot);
811
819
  await closeRuntimeGatewaySession(gatewaySession, "gateway.close.aborted");
812
820
  throw error;
813
821
  }
@@ -1101,22 +1109,22 @@ export abstract class AgentRuntimeKernel<
1101
1109
  try {
1102
1110
  const payload = JSON.parse(row.body) as RuntimeEventOutboxPayload;
1103
1111
  if (payload.type === "model-usage") {
1104
- if (!turnEvents.onModelUsage) continue;
1105
- await turnEvents.onModelUsage(payload.event);
1112
+ await turnEvents.onModelUsage?.(payload.event);
1106
1113
  } else if (payload.type === "tool-settlement") {
1107
- if (!turnEvents.onToolSettled) continue;
1108
- await turnEvents.onToolSettled(payload.event);
1114
+ await turnEvents.onToolSettled?.(payload.event);
1109
1115
  } else if (payload.type === "subagent-usage") {
1110
- if (!turnEvents.onSubagentUsage) continue;
1111
- const confirmation = await turnEvents.onSubagentUsage(payload.event);
1112
- if (confirmation?.confirmed !== true) {
1113
- throw new Error("Runtime event was not confirmed");
1116
+ if (turnEvents.onSubagentUsage) {
1117
+ const confirmation = await turnEvents.onSubagentUsage(payload.event);
1118
+ if (confirmation?.confirmed !== true) {
1119
+ throw new Error("Runtime event was not confirmed");
1120
+ }
1114
1121
  }
1115
1122
  } else {
1116
- if (!turnEvents.onLifecycleFact) continue;
1117
- const confirmation = await turnEvents.onLifecycleFact(payload.event);
1118
- if (confirmation?.confirmed !== true) {
1119
- throw new Error("Runtime event was not confirmed");
1123
+ if (turnEvents.onLifecycleFact) {
1124
+ const confirmation = await turnEvents.onLifecycleFact(payload.event);
1125
+ if (confirmation?.confirmed !== true) {
1126
+ throw new Error("Runtime event was not confirmed");
1127
+ }
1120
1128
  }
1121
1129
  }
1122
1130
  this.db.transaction(() =>
@@ -1320,12 +1328,12 @@ export abstract class AgentRuntimeKernel<
1320
1328
  // 调用:所有需要模型、工作区、扩展或投影绑定的运行时路径调用。
1321
1329
  // 原因:未初始化时立即失败,比在深层路径触发空值更容易定位。
1322
1330
  private assembly(): RuntimeSnapshot {
1323
- if (!this.runtimeSnapshot) {
1331
+ if (!this.activeRuntime) {
1324
1332
  throw new Error(
1325
1333
  "Runtime must be assembled before use",
1326
1334
  );
1327
1335
  }
1328
- return this.runtimeSnapshot;
1336
+ return this.activeRuntime.snapshot;
1329
1337
  }
1330
1338
 
1331
1339
  private async normalizeUIUserInput(
@@ -1377,10 +1385,14 @@ export abstract class AgentRuntimeKernel<
1377
1385
  // 调用:Session facet 的 `getRuntimeAssembly` RPC。
1378
1386
  // 原因:UI 需要读取真实装配结果,而不是上层配置声明。
1379
1387
  protected readRuntimeAssembly(): RuntimeAssemblyView {
1388
+ const runtime = this.activeRuntime;
1389
+ if (!runtime) {
1390
+ throw new Error("Runtime must be assembled before use");
1391
+ }
1380
1392
  return projectRuntimeAssembly(
1381
- this.assembly(),
1382
- this.runtimeRevision ?? null,
1383
- this.preparedPi(),
1393
+ runtime.snapshot,
1394
+ runtime.revision,
1395
+ runtime.pi,
1384
1396
  );
1385
1397
  }
1386
1398
 
@@ -1442,12 +1454,12 @@ export abstract class AgentRuntimeKernel<
1442
1454
  }
1443
1455
 
1444
1456
  private preparedPi(): PreparedPiRuntime {
1445
- if (!this.runtimePi) {
1457
+ if (!this.activeRuntime) {
1446
1458
  throw new Error(
1447
1459
  "SpringBrand Runtime must be prepared before starting a Turn",
1448
1460
  );
1449
1461
  }
1450
- return this.runtimePi;
1462
+ return this.activeRuntime.pi;
1451
1463
  }
1452
1464
 
1453
1465
  // #endregion
@@ -1474,10 +1486,11 @@ export abstract class AgentRuntimeKernel<
1474
1486
  descriptor: string;
1475
1487
  }> {
1476
1488
  await this.drainRuntimeEvents();
1477
- if (!this.runtimeRevision) {
1489
+ const runtime = this.activeRuntime;
1490
+ if (!runtime) {
1478
1491
  throw new Error("Runtime revision is not initialized");
1479
1492
  }
1480
- return this.pinAssembly(this.preparedPi(), this.runtimeRevision);
1493
+ return this.pinAssembly(runtime.pi, runtime.revision);
1481
1494
  }
1482
1495
 
1483
1496
  private async pinAssembly(
@@ -1731,7 +1744,7 @@ export abstract class AgentRuntimeKernel<
1731
1744
  "Regenerate request must match an existing user message",
1732
1745
  );
1733
1746
  }
1734
- const hook = this.runtimeHooks?.onSubmissionAdmission;
1747
+ const hook = this.activeRuntime?.admission;
1735
1748
  let existing: StoredSubmissionAdmission | null = null;
1736
1749
  if (hook) {
1737
1750
  const attemptedAt = Date.now();
@@ -2279,15 +2292,30 @@ export abstract class AgentRuntimeKernel<
2279
2292
  ): PiRecoveryDecision {
2280
2293
  let decision = this.decidePiRecovery(submission);
2281
2294
  for (const settlement of decision.recoveredToolSettlements) {
2295
+ const message = settlement.message;
2282
2296
  if (
2283
2297
  this.readToolSettlement(
2284
2298
  submission.submissionId,
2285
- settlement.toolCallId,
2299
+ message.toolCallId,
2286
2300
  )
2287
2301
  ) {
2288
2302
  continue;
2289
2303
  }
2290
- this.settleToolSync(submission.submissionId, settlement);
2304
+ this.settleToolSync(submission.submissionId, {
2305
+ toolCallId: message.toolCallId,
2306
+ toolName: message.toolName,
2307
+ args: settlement.args,
2308
+ result: {
2309
+ content: message.content,
2310
+ details: message.details,
2311
+ ...(message.usage ? { usage: message.usage } : {}),
2312
+ ...(message.addedToolNames?.length
2313
+ ? { addedToolNames: message.addedToolNames }
2314
+ : {}),
2315
+ },
2316
+ isError: message.isError,
2317
+ createdAt: message.timestamp,
2318
+ });
2291
2319
  decision = this.decidePiRecovery(submission);
2292
2320
  }
2293
2321
  const results = this.transcript.orderRecoveredToolSettlements(
@@ -4198,7 +4226,7 @@ export abstract class AgentRuntimeKernel<
4198
4226
  );
4199
4227
  }
4200
4228
  const result = decision.recoveredToolSettlements.find(
4201
- (item) => item.toolCallId === approval.toolCallId,
4229
+ (item) => item.message.toolCallId === approval.toolCallId,
4202
4230
  );
4203
4231
  if (!result) {
4204
4232
  throw new Error(
@@ -1,57 +0,0 @@
1
- import type {
2
- RuntimeSubmissionAdmissionHook,
3
- RuntimeTurnEventsPort,
4
- } from "../../../kernel/bindings";
5
- import type { RuntimeAgentHooks } from "../../../runtime-definition";
6
-
7
- export function createUniversalAgentHooks<
8
- Env extends Cloudflare.Env,
9
- Config,
10
- Command = never,
11
- Change = never,
12
- >(adapter: {
13
- guard(config: Config): Promise<void>;
14
- turnEvents(): RuntimeTurnEventsPort | Promise<RuntimeTurnEventsPort>;
15
- onSubmissionAdmission?: RuntimeSubmissionAdmissionHook;
16
- }): RuntimeAgentHooks<Env, Config, Command, Change> {
17
- const turnEvents = () => Promise.resolve(adapter.turnEvents());
18
- return {
19
- beforeCommit: [async (_context, config) => adapter.guard(config)],
20
- onTurnEnd: async (_context, messages) => {
21
- await (await turnEvents()).onResponse(messages);
22
- },
23
- onModelUsage: async (event) => {
24
- await (await turnEvents()).onModelUsage?.(event);
25
- },
26
- ...(adapter.onSubmissionAdmission
27
- ? { onSubmissionAdmission: adapter.onSubmissionAdmission }
28
- : {}),
29
- // 一个不订阅这两类事实的 Host 不能把 outbox 堵住:Runtime 只有拿到确认才
30
- // 会标记投递,而 `undefined` 表示"没投出去"。因此没有 Host 实现时这里就地确认,
31
- // 语义等同于旧版本"Host 不关心就丢弃",而不是让整条队列在队头无限重试。
32
- onSubagentUsage: async (event) => {
33
- const port = await turnEvents();
34
- return port.onSubagentUsage
35
- ? port.onSubagentUsage(event)
36
- : { confirmed: true };
37
- },
38
- onLifecycleFact: async (event) => {
39
- const port = await turnEvents();
40
- return port.onLifecycleFact
41
- ? port.onLifecycleFact(event)
42
- : { confirmed: true };
43
- },
44
- onToolSettled: async (event) => {
45
- await (await turnEvents()).onToolSettled?.(event);
46
- },
47
- onApproval: async (input) => {
48
- await (await turnEvents()).onApproval?.(input);
49
- },
50
- onActivityChanged: async (projection) => {
51
- await (await turnEvents()).onActivityChanged?.(projection);
52
- },
53
- onSubmissionTerminal: async (input) => {
54
- await (await turnEvents()).onSubmissionTerminal?.(input);
55
- },
56
- };
57
- }
@@ -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>;