@springbrand/agent-runtime 0.2.0-alpha.67 → 0.2.0-alpha.69
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 -3
- package/src/adapter/cloudflare/subagent/runner.ts +23 -22
- package/src/adapter/cloudflare/subagent/tools.ts +1 -1
- package/src/adapter/cloudflare/universal-agent/preparation.ts +0 -7
- package/src/db/schema.ts +0 -12
- package/src/db/submission-admission.repo.ts +5 -20
- package/src/db/submission.repo.ts +5 -21
- package/src/kernel/bindings.ts +8 -7
- package/src/kernel/durable-lifecycle.ts +0 -9
- package/src/kernel/profile.ts +3 -0
- package/src/kernel/public-contracts.ts +0 -1
- package/src/kernel/subagent-runtime.ts +2 -12
- package/src/kernel/submission-authority.ts +4 -24
- package/src/model-usage.ts +52 -0
- package/src/pi/assembly/context.ts +26 -60
- package/src/pi/runtime-adapter/assembly.ts +6 -2
- package/src/pi/runtime-adapter/execution.ts +78 -114
- package/src/pi/runtime-adapter/index.ts +3 -4
- package/src/pi/runtime-adapter/transcript.ts +31 -46
- package/src/pi/session/index.ts +22 -22
- package/src/pi/session/migration.ts +646 -0
- package/src/pi/session/storage.ts +523 -311
- package/src/pi/tool/compiler.ts +2 -2
- package/src/pi/tool/core-host.ts +29 -7
- package/src/pi/tool/mcp.ts +23 -15
- package/src/pi/tool/subagent.ts +0 -9
- package/src/pi/tool/workspace-state-connector.ts +23 -20
- package/src/runtime-agent.ts +11 -0
- package/src/runtime-assembler.ts +13 -2
- package/src/runtime-definition.ts +2 -0
- package/src/runtime.ts +24 -83
package/src/runtime.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { summarizeModelUsage } from "./model-usage";
|
|
1
2
|
import type {
|
|
2
3
|
AgentToolLifecycleResult,
|
|
3
4
|
AgentToolRunInfo,
|
|
@@ -181,9 +182,6 @@ interface StoredSubmission extends SubmissionReceipt {
|
|
|
181
182
|
recoveryErrorCount: number;
|
|
182
183
|
recoveryReason?: SubmissionRecoveryReason;
|
|
183
184
|
runId: string | null;
|
|
184
|
-
accountId: string | null;
|
|
185
|
-
rateVersion: number | null;
|
|
186
|
-
slotIdentity: string | null;
|
|
187
185
|
/** 跨执行片累计的模型回合数,全局回合预算据此判断。 */
|
|
188
186
|
modelTurns: number;
|
|
189
187
|
/** 当前让步执行片的标识;没有未完成让步时为 null。 */
|
|
@@ -281,14 +279,6 @@ function validateAdmissionResult(
|
|
|
281
279
|
}
|
|
282
280
|
return result;
|
|
283
281
|
}
|
|
284
|
-
if (
|
|
285
|
-
typeof result.accountId !== "string" || !result.accountId.trim() ||
|
|
286
|
-
typeof result.slotIdentity !== "string" || !result.slotIdentity.trim() ||
|
|
287
|
-
!Number.isSafeInteger(result.rateVersion) ||
|
|
288
|
-
result.rateVersion <= 0
|
|
289
|
-
) {
|
|
290
|
-
throw new Error("Runtime admission context is invalid");
|
|
291
|
-
}
|
|
292
282
|
return result;
|
|
293
283
|
}
|
|
294
284
|
|
|
@@ -306,24 +296,14 @@ function assistantUsageEvent(
|
|
|
306
296
|
eventId: string,
|
|
307
297
|
submissionId: string,
|
|
308
298
|
message: AssistantMessage,
|
|
309
|
-
|
|
299
|
+
requestedModel: RuntimeSnapshot["pi"]["model"],
|
|
310
300
|
): RuntimeModelUsageEvent {
|
|
311
301
|
return {
|
|
312
302
|
eventId,
|
|
313
303
|
submissionId,
|
|
314
304
|
runId: submissionId,
|
|
315
|
-
...(pinned?.accountId ? { accountId: pinned.accountId } : {}),
|
|
316
|
-
...(pinned?.rateVersion !== null && pinned?.rateVersion !== undefined
|
|
317
|
-
? { rateVersion: pinned.rateVersion }
|
|
318
|
-
: {}),
|
|
319
|
-
...(pinned?.slotIdentity ? { slotIdentity: pinned.slotIdentity } : {}),
|
|
320
305
|
kind: "assistant",
|
|
321
|
-
|
|
322
|
-
provider: message.provider,
|
|
323
|
-
model: message.model,
|
|
324
|
-
...(message.responseModel ? { responseModel: message.responseModel } : {}),
|
|
325
|
-
stopReason: message.stopReason,
|
|
326
|
-
usage: message.usage,
|
|
306
|
+
...summarizeModelUsage(requestedModel, [message]),
|
|
327
307
|
};
|
|
328
308
|
}
|
|
329
309
|
|
|
@@ -437,6 +417,10 @@ export abstract class AgentRuntimeKernel<
|
|
|
437
417
|
};
|
|
438
418
|
|
|
439
419
|
protected abstract ensureRuntimeReady(): Promise<void>;
|
|
420
|
+
/** Runs only before the first pin of a newly activated Submission. */
|
|
421
|
+
protected prepareRuntimeForSubmission(): Promise<void> {
|
|
422
|
+
return this.ensureRuntimeReady();
|
|
423
|
+
}
|
|
440
424
|
|
|
441
425
|
/** Let the Host prepare a validated client response before Tool settlement. */
|
|
442
426
|
protected prepareToolInteractionResponse(
|
|
@@ -579,7 +563,7 @@ export abstract class AgentRuntimeKernel<
|
|
|
579
563
|
interruptActive: (turn) => turn.agent.interrupt(),
|
|
580
564
|
});
|
|
581
565
|
this.transcript = this.pi.createTranscript({
|
|
582
|
-
|
|
566
|
+
storage: this.ctx.storage,
|
|
583
567
|
durability: {
|
|
584
568
|
transaction: (run) => this.db.transaction(run),
|
|
585
569
|
upsertUserSidecar: (id, body) =>
|
|
@@ -763,7 +747,7 @@ export abstract class AgentRuntimeKernel<
|
|
|
763
747
|
this.runtimeLoad.advance("mcp");
|
|
764
748
|
await connectConfiguredMcpServers(
|
|
765
749
|
this,
|
|
766
|
-
candidateSnapshot.profile.mcpServers,
|
|
750
|
+
candidateSnapshot.profile.mcpServers.filter(server => !server.hostManaged),
|
|
767
751
|
);
|
|
768
752
|
const gatewayDegradations = [];
|
|
769
753
|
let gatewaySession: RuntimeGatewaySession | undefined;
|
|
@@ -812,7 +796,8 @@ export abstract class AgentRuntimeKernel<
|
|
|
812
796
|
// 新能力,同一轮接着跑」所依赖的那一步。真正在执行的 Turn 仍然被挡住。
|
|
813
797
|
const contested = Boolean(previous) &&
|
|
814
798
|
revision !== previous?.revision &&
|
|
815
|
-
this.submissions.isBusy()
|
|
799
|
+
this.submissions.isBusy() &&
|
|
800
|
+
this.db.submissions.listUnfinishedIds().some(id => Boolean(this.readSubmission(id)?.assemblyRevision));
|
|
816
801
|
const parked = contested && this.db.everyUnfinishedSubmissionParked();
|
|
817
802
|
if (contested && !parked) {
|
|
818
803
|
await closeRuntimeGatewaySession(gatewaySession, "gateway.close.contested");
|
|
@@ -902,13 +887,6 @@ export abstract class AgentRuntimeKernel<
|
|
|
902
887
|
const runMetadata: RuntimeSubagentRunMetadata = {
|
|
903
888
|
submissionId: submission.submissionId,
|
|
904
889
|
parentRunId: submission.runId ?? submission.submissionId,
|
|
905
|
-
...(submission.accountId ? { accountId: submission.accountId } : {}),
|
|
906
|
-
...(submission.rateVersion !== null
|
|
907
|
-
? { rateVersion: submission.rateVersion }
|
|
908
|
-
: {}),
|
|
909
|
-
...(submission.slotIdentity
|
|
910
|
-
? { slotIdentity: submission.slotIdentity }
|
|
911
|
-
: {}),
|
|
912
890
|
};
|
|
913
891
|
const lifecycle = this.subagentLifecycle(runMetadata);
|
|
914
892
|
const toolExecutors = snapshot.bindings.subagents
|
|
@@ -1077,7 +1055,7 @@ export abstract class AgentRuntimeKernel<
|
|
|
1077
1055
|
persisted.id,
|
|
1078
1056
|
submission.submissionId,
|
|
1079
1057
|
commit.message,
|
|
1080
|
-
|
|
1058
|
+
snapshot.pi.model,
|
|
1081
1059
|
);
|
|
1082
1060
|
this.db.runtimeEvents.insert({
|
|
1083
1061
|
eventId: event.eventId,
|
|
@@ -1107,7 +1085,6 @@ export abstract class AgentRuntimeKernel<
|
|
|
1107
1085
|
: undefined;
|
|
1108
1086
|
this.transcript.append(commit.id, commit.message, {
|
|
1109
1087
|
submissionId: submission.submissionId,
|
|
1110
|
-
createdAt: commit.message.timestamp,
|
|
1111
1088
|
...(uiMessage ? { userMessage: uiMessage } : {}),
|
|
1112
1089
|
});
|
|
1113
1090
|
this.db.steers.deleteByMessageId(commit.id);
|
|
@@ -1558,11 +1535,12 @@ export abstract class AgentRuntimeKernel<
|
|
|
1558
1535
|
// 作用:为新 Submission 生成包含当前 Context 的不可变装配描述。
|
|
1559
1536
|
// 调用:Submission 通过去重和忙碌检查后,在真正写入前调用。
|
|
1560
1537
|
// 原因:把动态 Context 和执行档位固定在准入时,恢复时才能按原配置继续。
|
|
1561
|
-
private async admissionPin(): Promise<{
|
|
1538
|
+
private async admissionPin(fresh: boolean): Promise<{
|
|
1562
1539
|
revision: string;
|
|
1563
1540
|
descriptor: string;
|
|
1564
1541
|
}> {
|
|
1565
|
-
await this.
|
|
1542
|
+
if (fresh) await this.prepareRuntimeForSubmission();
|
|
1543
|
+
else await this.ensureRuntimeReady();
|
|
1566
1544
|
return this.currentAssemblyPin();
|
|
1567
1545
|
}
|
|
1568
1546
|
|
|
@@ -1606,6 +1584,7 @@ export abstract class AgentRuntimeKernel<
|
|
|
1606
1584
|
|
|
1607
1585
|
private async pinSubmissionAssembly(
|
|
1608
1586
|
submission: StoredSubmission,
|
|
1587
|
+
mode: SubmissionExecutionMode,
|
|
1609
1588
|
): Promise<StoredSubmission> {
|
|
1610
1589
|
if (submission.assemblyRevision && submission.assemblyDescriptor) {
|
|
1611
1590
|
return submission;
|
|
@@ -1613,7 +1592,7 @@ export abstract class AgentRuntimeKernel<
|
|
|
1613
1592
|
if (submission.assemblyRevision || submission.assemblyDescriptor) {
|
|
1614
1593
|
throw new Error("Submission assembly pin is incomplete");
|
|
1615
1594
|
}
|
|
1616
|
-
const { revision, descriptor } = await this.admissionPin();
|
|
1595
|
+
const { revision, descriptor } = await this.admissionPin(mode === 'fresh');
|
|
1617
1596
|
this.db.submissions.pinAssembly(
|
|
1618
1597
|
submission.submissionId,
|
|
1619
1598
|
revision,
|
|
@@ -1744,7 +1723,7 @@ export abstract class AgentRuntimeKernel<
|
|
|
1744
1723
|
model: snapshot.pi.model,
|
|
1745
1724
|
signal,
|
|
1746
1725
|
submissionId,
|
|
1747
|
-
|
|
1726
|
+
onCompactionUsage: (event, didCompact) => {
|
|
1748
1727
|
this.db.runtimeEvents.insert({
|
|
1749
1728
|
eventId: event.eventId,
|
|
1750
1729
|
body: json({
|
|
@@ -1752,21 +1731,11 @@ export abstract class AgentRuntimeKernel<
|
|
|
1752
1731
|
event: {
|
|
1753
1732
|
...event,
|
|
1754
1733
|
runId: submissionId,
|
|
1755
|
-
...(this.readSubmission(submissionId)?.accountId
|
|
1756
|
-
? { accountId: this.readSubmission(submissionId)!.accountId! }
|
|
1757
|
-
: {}),
|
|
1758
|
-
...(this.readSubmission(submissionId)?.rateVersion !== null &&
|
|
1759
|
-
this.readSubmission(submissionId)?.rateVersion !== undefined
|
|
1760
|
-
? { rateVersion: this.readSubmission(submissionId)!.rateVersion! }
|
|
1761
|
-
: {}),
|
|
1762
|
-
...(this.readSubmission(submissionId)?.slotIdentity
|
|
1763
|
-
? { slotIdentity: this.readSubmission(submissionId)!.slotIdentity! }
|
|
1764
|
-
: {}),
|
|
1765
1734
|
},
|
|
1766
1735
|
}),
|
|
1767
1736
|
createdAt: Date.now(),
|
|
1768
1737
|
});
|
|
1769
|
-
this.telemetry.capture("contextCompacted", {
|
|
1738
|
+
if (didCompact) this.telemetry.capture("contextCompacted", {
|
|
1770
1739
|
submissionId,
|
|
1771
1740
|
compactionId: event.eventId,
|
|
1772
1741
|
inputTokens: event.usage.input,
|
|
@@ -1907,9 +1876,6 @@ export abstract class AgentRuntimeKernel<
|
|
|
1907
1876
|
let admission = existing?.status === "accepted"
|
|
1908
1877
|
? {
|
|
1909
1878
|
accepted: true as const,
|
|
1910
|
-
accountId: existing.accountId!,
|
|
1911
|
-
rateVersion: existing.rateVersion!,
|
|
1912
|
-
slotIdentity: existing.slotIdentity!,
|
|
1913
1879
|
}
|
|
1914
1880
|
: existing?.status === "rejected"
|
|
1915
1881
|
? {
|
|
@@ -1951,9 +1917,6 @@ export abstract class AgentRuntimeKernel<
|
|
|
1951
1917
|
this.db.submissionAdmissions.saveAccepted(
|
|
1952
1918
|
admissionRequestId,
|
|
1953
1919
|
runId,
|
|
1954
|
-
admission.accountId,
|
|
1955
|
-
admission.rateVersion,
|
|
1956
|
-
admission.slotIdentity,
|
|
1957
1920
|
);
|
|
1958
1921
|
}
|
|
1959
1922
|
this.db.submissions.insert({
|
|
@@ -1973,9 +1936,6 @@ export abstract class AgentRuntimeKernel<
|
|
|
1973
1936
|
? options.userMessageId ?? null
|
|
1974
1937
|
: null,
|
|
1975
1938
|
runId,
|
|
1976
|
-
accountId: admission?.accepted ? admission.accountId : null,
|
|
1977
|
-
rateVersion: admission?.accepted ? admission.rateVersion : null,
|
|
1978
|
-
slotIdentity: admission?.accepted ? admission.slotIdentity : null,
|
|
1979
1939
|
});
|
|
1980
1940
|
if (admission?.accepted) {
|
|
1981
1941
|
const fact: RuntimeLifecycleFact = {
|
|
@@ -1983,9 +1943,6 @@ export abstract class AgentRuntimeKernel<
|
|
|
1983
1943
|
eventId: `${submissionId}:admitted`,
|
|
1984
1944
|
submissionId,
|
|
1985
1945
|
runId: submissionId,
|
|
1986
|
-
accountId: admission.accountId,
|
|
1987
|
-
rateVersion: admission.rateVersion,
|
|
1988
|
-
slotIdentity: admission.slotIdentity,
|
|
1989
1946
|
};
|
|
1990
1947
|
this.db.runtimeEvents.insert({
|
|
1991
1948
|
eventId: fact.eventId,
|
|
@@ -2086,13 +2043,6 @@ export abstract class AgentRuntimeKernel<
|
|
|
2086
2043
|
zeroUsage: !this.db.runtimeEvents.hasNonZeroModelUsage(
|
|
2087
2044
|
submission.submissionId,
|
|
2088
2045
|
),
|
|
2089
|
-
...(submission.accountId ? { accountId: submission.accountId } : {}),
|
|
2090
|
-
...(submission.rateVersion !== null
|
|
2091
|
-
? { rateVersion: submission.rateVersion }
|
|
2092
|
-
: {}),
|
|
2093
|
-
...(submission.slotIdentity
|
|
2094
|
-
? { slotIdentity: submission.slotIdentity }
|
|
2095
|
-
: {}),
|
|
2096
2046
|
};
|
|
2097
2047
|
this.db.runtimeEvents.insert({
|
|
2098
2048
|
eventId: terminalFact.eventId,
|
|
@@ -2859,7 +2809,6 @@ export abstract class AgentRuntimeKernel<
|
|
|
2859
2809
|
userMessage,
|
|
2860
2810
|
{
|
|
2861
2811
|
submissionId: submission.submissionId,
|
|
2862
|
-
createdAt: userMessage.timestamp,
|
|
2863
2812
|
...(uiMessage ? { userMessage: uiMessage } : {}),
|
|
2864
2813
|
},
|
|
2865
2814
|
);
|
|
@@ -2991,7 +2940,7 @@ export abstract class AgentRuntimeKernel<
|
|
|
2991
2940
|
submission.abortReason,
|
|
2992
2941
|
);
|
|
2993
2942
|
}
|
|
2994
|
-
submission = await this.pinSubmissionAssembly(submission);
|
|
2943
|
+
submission = await this.pinSubmissionAssembly(submission, mode);
|
|
2995
2944
|
await this.assertPinnedSubmission(submission);
|
|
2996
2945
|
if (submission.status === "pending" && mode === "fresh") {
|
|
2997
2946
|
submission = await this.activateQueuedSubmission(submission);
|
|
@@ -3667,7 +3616,9 @@ export abstract class AgentRuntimeKernel<
|
|
|
3667
3616
|
private async hydrationMessages(): Promise<UIMessage[]> {
|
|
3668
3617
|
const messages = await this.getMessages();
|
|
3669
3618
|
const running = this.db.submissions.findRunning();
|
|
3670
|
-
|
|
3619
|
+
// After a restart there is no in-memory replay stream. In particular, a
|
|
3620
|
+
// parked approval cannot recreate one until the user can see and decide it.
|
|
3621
|
+
return running?.assistantMessageId && this.streamBySubmission.has(running.submissionId)
|
|
3671
3622
|
? messages.filter((message) =>
|
|
3672
3623
|
message.role !== "assistant" ||
|
|
3673
3624
|
(message.id !== running.assistantMessageId &&
|
|
@@ -3804,9 +3755,7 @@ export abstract class AgentRuntimeKernel<
|
|
|
3804
3755
|
await this.broadcastApprovals();
|
|
3805
3756
|
return;
|
|
3806
3757
|
}
|
|
3807
|
-
this.transcript.append(crypto.randomUUID(), message
|
|
3808
|
-
createdAt: message.timestamp,
|
|
3809
|
-
});
|
|
3758
|
+
this.transcript.append(crypto.randomUUID(), message);
|
|
3810
3759
|
}
|
|
3811
3760
|
|
|
3812
3761
|
// 作用:返回扩展可见的当前 Session 摘要。
|
|
@@ -4260,7 +4209,6 @@ export abstract class AgentRuntimeKernel<
|
|
|
4260
4209
|
: undefined;
|
|
4261
4210
|
this.transcript.append(steer.messageId, message, {
|
|
4262
4211
|
submissionId: current.submissionId,
|
|
4263
|
-
createdAt: steer.createdAt,
|
|
4264
4212
|
...(userMessage ? { userMessage } : {}),
|
|
4265
4213
|
});
|
|
4266
4214
|
this.db.steers.deleteByMessageId(steer.messageId);
|
|
@@ -4613,13 +4561,6 @@ export abstract class AgentRuntimeKernel<
|
|
|
4613
4561
|
runId: run.runId,
|
|
4614
4562
|
subagentRunId: run.runId,
|
|
4615
4563
|
parentRunId: metadata.parentRunId,
|
|
4616
|
-
...(metadata.accountId ? { accountId: metadata.accountId } : {}),
|
|
4617
|
-
...(metadata.rateVersion !== undefined
|
|
4618
|
-
? { rateVersion: metadata.rateVersion }
|
|
4619
|
-
: {}),
|
|
4620
|
-
...(metadata.slotIdentity
|
|
4621
|
-
? { slotIdentity: metadata.slotIdentity }
|
|
4622
|
-
: {}),
|
|
4623
4564
|
kind: "subagent",
|
|
4624
4565
|
status,
|
|
4625
4566
|
usage: completion.usage,
|