@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.
- package/package.json +3 -1
- package/src/adapter/cloudflare/dynamic-worker-observability.ts +84 -0
- package/src/adapter/cloudflare/index.ts +11 -2
- package/src/adapter/cloudflare/scheduling/zoned-cron.ts +114 -0
- package/src/adapter/cloudflare/universal-agent/tools.ts +17 -30
- package/src/index.ts +7 -35
- 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/index.ts +1 -0
- 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/time.ts +31 -0
- package/src/pi/tool/workspace-revision.ts +0 -12
- package/src/pi/tool/workspace-sandbox.ts +0 -10
- package/src/runtime-agent.ts +35 -45
- package/src/runtime-assembler.ts +68 -192
- package/src/runtime-definition.ts +35 -109
- package/src/runtime.ts +75 -47
- package/src/adapter/cloudflare/universal-agent/hooks.ts +0 -57
- package/src/kernel/tool-surface.ts +0 -42
- package/src/tool-registry.ts +0 -142
|
@@ -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
|
-
|
|
14
|
-
|
|
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
|
-
|
|
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
|
|
184
|
-
readonly tools: import("./tool-registry").ToolAssemblyResult;
|
|
110
|
+
readonly tools: ToolAssemblyResult;
|
|
185
111
|
readonly resources: ResolvedResources;
|
|
186
|
-
readonly
|
|
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 {
|
|
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
|
|
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.
|
|
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.
|
|
723
|
+
return this.activeRuntime?.snapshot.bindings.turnEvents;
|
|
719
724
|
}
|
|
720
725
|
|
|
721
726
|
protected async initCandidate(candidate: RuntimeCandidate): Promise<void> {
|
|
722
|
-
this.
|
|
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 !==
|
|
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 =
|
|
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
|
-
|
|
1105
|
-
await turnEvents.onModelUsage(payload.event);
|
|
1112
|
+
await turnEvents.onModelUsage?.(payload.event);
|
|
1106
1113
|
} else if (payload.type === "tool-settlement") {
|
|
1107
|
-
|
|
1108
|
-
await turnEvents.onToolSettled(payload.event);
|
|
1114
|
+
await turnEvents.onToolSettled?.(payload.event);
|
|
1109
1115
|
} else if (payload.type === "subagent-usage") {
|
|
1110
|
-
if (
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
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 (
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
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.
|
|
1331
|
+
if (!this.activeRuntime) {
|
|
1324
1332
|
throw new Error(
|
|
1325
1333
|
"Runtime must be assembled before use",
|
|
1326
1334
|
);
|
|
1327
1335
|
}
|
|
1328
|
-
return this.
|
|
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
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
1489
|
+
const runtime = this.activeRuntime;
|
|
1490
|
+
if (!runtime) {
|
|
1478
1491
|
throw new Error("Runtime revision is not initialized");
|
|
1479
1492
|
}
|
|
1480
|
-
return this.pinAssembly(
|
|
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.
|
|
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
|
-
|
|
2299
|
+
message.toolCallId,
|
|
2286
2300
|
)
|
|
2287
2301
|
) {
|
|
2288
2302
|
continue;
|
|
2289
2303
|
}
|
|
2290
|
-
this.settleToolSync(submission.submissionId,
|
|
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>;
|