effect-agent 0.1.0-beta.151 → 0.1.0-beta.153
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/dist/{Admin-CKIdJoP8.d.mts → Admin-BjmupLN3.d.mts} +36 -17
- package/dist/{Agent-Cjd_ZveM.d.mts → Agent-BCyrGaWg.d.mts} +2 -2
- package/dist/{AgentPolicy-BqDoSXO6.d.mts → AgentPolicy-CnXWWwdg.d.mts} +5 -1
- package/dist/{AgentRuntime-sXpKcyxu.d.mts → AgentRuntime-BAjT5gXl.d.mts} +10 -10
- package/dist/{AgentRuntime-D8U9gl9Q.mjs → AgentRuntime-IF_1GoUf.mjs} +54 -11
- package/dist/AgentRuntime-IF_1GoUf.mjs.map +1 -0
- package/dist/{ContextCompactor-WwSIG_Z2.d.mts → ContextCompactor-CPlStZRc.d.mts} +2 -2
- package/dist/{Digest-U69rDHuO.d.mts → Digest-CaJ2RIsF.d.mts} +2 -2
- package/dist/{DurableAgentRuntime-R2LUYnRl.mjs → DurableAgentRuntime-BQzYkFVy.mjs} +186 -89
- package/dist/DurableAgentRuntime-BQzYkFVy.mjs.map +1 -0
- package/dist/{EventSource-CMbXXmwe.d.mts → EventSource-C8CKwQy5.d.mts} +3 -3
- package/dist/InMemory.d.mts +1 -1
- package/dist/{Messaging-ccQURKCf.d.mts → Messaging-B1zumorg.d.mts} +3 -3
- package/dist/{MessagingHost-D04wE-7W.d.mts → MessagingHost-B4jqlJmx.d.mts} +3 -3
- package/dist/{Output-CFD1CPfU.d.mts → Output-WL7JexCm.d.mts} +2 -2
- package/dist/{PreparedInputAdmission-Bt6rgtVu.d.mts → PreparedInputAdmission-CU1PzUVD.d.mts} +4 -4
- package/dist/{Records-B5GFWCpn.d.mts → Records-BrEpibum.d.mts} +17 -6
- package/dist/{RunEvent-DIrzkjLr.d.mts → RunEvent-DV_llBcq.d.mts} +18 -4
- package/dist/{RunJournal-Gd83HYqG.mjs → RunJournal-ixFRCyW3.mjs} +29 -7
- package/dist/RunJournal-ixFRCyW3.mjs.map +1 -0
- package/dist/{RunOptions-Bv9NpkPZ.d.mts → RunOptions-CkRYnlJa.d.mts} +22 -8
- package/dist/{RunPolicyUsage-ClZxyR46.d.mts → RunPolicyUsage-CUudVtg_.d.mts} +3 -1
- package/dist/{Schedule-CtYREFnz.d.mts → Schedule-B_z7PMg-.d.mts} +2 -2
- package/dist/{Subagent-hG9lJ7tJ.mjs → Subagent-CmFtZaeI.mjs} +2 -2
- package/dist/{Subagent-hG9lJ7tJ.mjs.map → Subagent-CmFtZaeI.mjs.map} +1 -1
- package/dist/{Subagent-VHrANXFy.d.mts → Subagent-Dld4W1BY.d.mts} +7 -7
- package/dist/{SubagentHost-C-4A7tA2.d.mts → SubagentHost--HBuY8fF.d.mts} +4 -4
- package/dist/{Subscription-BJAzYNw1.d.mts → Subscription-BomcQ9_W.d.mts} +5 -5
- package/dist/{SubscriptionInput-CkBJt0AS.d.mts → SubscriptionInput-gpZSR9vB.d.mts} +3 -3
- package/dist/{ThreadHistory-tS1KwxHR.d.mts → ThreadHistory-ZEu_ja6L.d.mts} +2 -2
- package/dist/{Worker-fwWkBg12.d.mts → Worker-2r2zGDkh.d.mts} +2 -2
- package/dist/{WorkerAdmission-CJ_oWRuS.mjs → WorkerAdmission-CNbm4o_x.mjs} +3 -3
- package/dist/{WorkerAdmission-CJ_oWRuS.mjs.map → WorkerAdmission-CNbm4o_x.mjs.map} +1 -1
- package/dist/{agent-registration-CKNsrpwo.mjs → agent-registration-U3kmV7nW.mjs} +18 -18
- package/dist/agent-registration-U3kmV7nW.mjs.map +1 -0
- package/dist/capabilities/Commands.d.mts +1 -1
- package/dist/capabilities/Messaging.d.mts +1 -1
- package/dist/capabilities/Redaction.d.mts +1 -1
- package/dist/capabilities/RunHooks.d.mts +1 -1
- package/dist/capabilities/Subagent.d.mts +2 -2
- package/dist/capabilities/Subagent.mjs +1 -1
- package/dist/core/Agent.d.mts +1 -1
- package/dist/core/AgentPolicy.d.mts +1 -1
- package/dist/core/AgentPolicy.mjs +2 -0
- package/dist/core/AgentPolicy.mjs.map +1 -1
- package/dist/core/RunEvent.d.mts +2 -2
- package/dist/core/RunEvent.mjs +10 -1
- package/dist/core/RunEvent.mjs.map +1 -1
- package/dist/core/RunPolicyUsage.d.mts +1 -1
- package/dist/core/RunPolicyUsage.mjs +6 -1
- package/dist/core/RunPolicyUsage.mjs.map +1 -1
- package/dist/core/Worker.d.mts +1 -1
- package/dist/durable/ActivityStore.d.mts +1 -1
- package/dist/durable/Admin.d.mts +1 -1
- package/dist/durable/AgentRegistration.d.mts +2 -2
- package/dist/durable/AgentRegistration.mjs +3 -2
- package/dist/durable/AgentRegistration.mjs.map +1 -1
- package/dist/durable/Certification.d.mts +1 -1
- package/dist/durable/CommittedActivity.d.mts +3 -3
- package/dist/durable/Digest.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.mjs +2 -2
- package/dist/durable/EventSource.d.mts +1 -1
- package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/LifecyclePublication.d.mts +1 -1
- package/dist/durable/MessageDelivery.d.mts +5 -5
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +42 -42
- package/dist/durable/PersistentHistory.d.mts +2 -2
- package/dist/durable/PersistentHistory.mjs +1 -1
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/Records.d.mts +2 -2
- package/dist/durable/Records.mjs +16 -1
- package/dist/durable/Records.mjs.map +1 -1
- package/dist/durable/Recovery.d.mts +1 -1
- package/dist/durable/RunJournal.d.mts +1 -1
- package/dist/durable/RunJournal.mjs +1 -1
- package/dist/durable/Schedule.d.mts +1 -1
- package/dist/durable/ScheduleStoreConformance.d.mts +1 -1
- package/dist/durable/ScheduleTransition.d.mts +1 -1
- package/dist/durable/Scheduling.d.mts +3 -3
- package/dist/durable/SubmissionLedger.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +2 -2
- package/dist/durable/SubmissionLedgerConformance.mjs +1 -1
- package/dist/durable/SubmissionStatus.d.mts +1 -1
- package/dist/durable/Subscription.d.mts +1 -1
- package/dist/durable/SubscriptionInput.d.mts +1 -1
- package/dist/durable/SubscriptionInput.mjs +1 -1
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionTools.d.mts +4 -4
- package/dist/durable/SubscriptionTransition.d.mts +1 -1
- package/dist/durable/Subscriptions.d.mts +6 -6
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadContextHistoryProjection.d.mts +1 -1
- package/dist/durable/ThreadInvariants.d.mts +2 -2
- package/dist/durable/ThreadInvariants.mjs +1 -1
- package/dist/durable/ThreadProjection.d.mts +1 -1
- package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
- package/dist/durable/ThreadStore.d.mts +1 -1
- package/dist/durable/ThreadStore.mjs +1 -1
- package/dist/durable/ThreadStoreConformance.d.mts +1 -1
- package/dist/durable/ThreadStoreConformance.mjs +1 -1
- package/dist/durable/WorkerAdmission.d.mts +3 -3
- package/dist/durable/WorkerAdmission.mjs +1 -1
- package/dist/durable/WorkerHost.d.mts +5 -5
- package/dist/engine/AgentRuntime.d.mts +1 -1
- package/dist/engine/AgentRuntime.mjs +1 -1
- package/dist/engine/Compaction.d.mts +1 -1
- package/dist/engine/ContextCompactor.d.mts +1 -1
- package/dist/engine/MessagingHost.d.mts +1 -1
- package/dist/engine/Output.d.mts +1 -1
- package/dist/engine/RunOptions.d.mts +1 -1
- package/dist/engine/RunOptions.mjs.map +1 -1
- package/dist/engine/SubagentHost.d.mts +1 -1
- package/dist/engine/ThreadHistory.d.mts +1 -1
- package/dist/index.d.mts +22 -22
- package/dist/index.mjs +5 -5
- package/package.json +1 -1
- package/src/core/AgentPolicy.ts +2 -0
- package/src/core/RunEvent.ts +9 -0
- package/src/core/RunPolicyUsage.ts +2 -0
- package/src/durable/AgentRegistration.ts +2 -0
- package/src/durable/DurableAgentRuntime.ts +331 -138
- package/src/durable/Records.ts +12 -0
- package/src/durable/RunJournal.ts +88 -27
- package/src/durable/internal/agent-registration.ts +58 -35
- package/src/engine/RunOptions.ts +17 -2
- package/src/engine/internal/agent-runtime.ts +115 -8
- package/dist/AgentRuntime-D8U9gl9Q.mjs.map +0 -1
- package/dist/DurableAgentRuntime-R2LUYnRl.mjs.map +0 -1
- package/dist/RunJournal-Gd83HYqG.mjs.map +0 -1
- package/dist/agent-registration-CKNsrpwo.mjs.map +0 -1
|
@@ -151,6 +151,7 @@ import {
|
|
|
151
151
|
type ResolvedBinding,
|
|
152
152
|
resolveDefinitionBinding,
|
|
153
153
|
resolveWorkerBinding,
|
|
154
|
+
CurrentBindingSelection,
|
|
154
155
|
} from "./internal/agent-registration.ts";
|
|
155
156
|
import { makeAgentUpdateRuntime } from "./internal/agent-updates.ts";
|
|
156
157
|
import { inspectForeignDiagnostic, safeUnknownString } from "./internal/foreign-diagnostic.ts";
|
|
@@ -184,6 +185,7 @@ import {
|
|
|
184
185
|
CompactionCreated,
|
|
185
186
|
DefinitionDigests,
|
|
186
187
|
ModelResponseInterrupted,
|
|
188
|
+
ModelCallAborted,
|
|
187
189
|
PersistedJson,
|
|
188
190
|
ProducerEpoch,
|
|
189
191
|
RecordEnvelope,
|
|
@@ -240,6 +242,7 @@ import {
|
|
|
240
242
|
modelResponseRecordId,
|
|
241
243
|
projectRunJournalStream,
|
|
242
244
|
type JournalBoundary,
|
|
245
|
+
type RunJournalProjection,
|
|
243
246
|
runCompletedRecordId,
|
|
244
247
|
runCompletionDigest,
|
|
245
248
|
runIdForSubmission,
|
|
@@ -296,6 +299,7 @@ import {
|
|
|
296
299
|
ClaimHandoff,
|
|
297
300
|
SubmissionScheduling,
|
|
298
301
|
ClaimJoiningRequest,
|
|
302
|
+
type JoiningClaim,
|
|
299
303
|
ClaimRequest,
|
|
300
304
|
IdempotencyKey,
|
|
301
305
|
LedgerError,
|
|
@@ -1257,11 +1261,25 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
1257
1261
|
bindings: ReadonlyArray<ResolvedBinding>,
|
|
1258
1262
|
) {
|
|
1259
1263
|
const registeredBindings = [...bindings];
|
|
1264
|
+
const bindingSelection = yield* CurrentBindingSelection;
|
|
1260
1265
|
const workerAdmissionPort = yield* WorkerAdmissionPort;
|
|
1261
1266
|
const ledger = yield* SubmissionLedger;
|
|
1262
1267
|
const submissionScheduling = yield* SubmissionScheduling;
|
|
1263
1268
|
const store = yield* ThreadStore;
|
|
1264
1269
|
|
|
1270
|
+
// Disposable: canonical tail and owner identify the exact projection, never ownership.
|
|
1271
|
+
// Retain only the most recent view; persisted checkpoints still govern cold recovery.
|
|
1272
|
+
let projectedJournal:
|
|
1273
|
+
| {
|
|
1274
|
+
readonly threadId: ThreadId;
|
|
1275
|
+
readonly through: CanonicalSequence;
|
|
1276
|
+
readonly runId: RunId;
|
|
1277
|
+
readonly seedThrough: CanonicalSequence | undefined;
|
|
1278
|
+
readonly journal: RunJournalProjection;
|
|
1279
|
+
readonly boundaries: ReadonlyArray<JournalBoundary>;
|
|
1280
|
+
}
|
|
1281
|
+
| undefined;
|
|
1282
|
+
|
|
1265
1283
|
const wake = yield* WakeScheduler;
|
|
1266
1284
|
const failpoint = yield* DurableRuntimeFailpoint;
|
|
1267
1285
|
const config = yield* DurableRuntimeConfig;
|
|
@@ -1301,20 +1319,11 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
1301
1319
|
Effect.provideService(effect, Crypto.Crypto, crypto);
|
|
1302
1320
|
|
|
1303
1321
|
const contractsFor = (definition: Agent.AnyDefinition) => {
|
|
1304
|
-
const registered = registeredBindings.filter(
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
// Attempts may restore the accepted Run policy on a Definition copy. Replay contracts
|
|
1308
|
-
// describe Tools, so retain the registration's semantic versions while all declarations
|
|
1309
|
-
// that affect those contracts are unchanged. Replaced Tools or completion declarations
|
|
1310
|
-
// must not inherit another executable's replay authority.
|
|
1311
|
-
const current =
|
|
1312
|
-
binding?.definition.toolkit === definition.toolkit &&
|
|
1313
|
-
binding.definition.completion === definition.completion &&
|
|
1314
|
-
binding.definition.completionFromTools === definition.completionFromTools
|
|
1315
|
-
? binding
|
|
1316
|
-
: undefined;
|
|
1322
|
+
const registered = registeredBindings.filter(
|
|
1323
|
+
(binding) => binding.agentId === definition.id && Object.is(binding.definition, definition),
|
|
1324
|
+
);
|
|
1317
1325
|
|
|
1326
|
+
const current = registered.length === 1 ? registered[0] : undefined;
|
|
1318
1327
|
const contracts = current?.digests.replay?.tools;
|
|
1319
1328
|
|
|
1320
1329
|
return contracts === undefined
|
|
@@ -1324,9 +1333,15 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
1324
1333
|
: Effect.succeed(contracts);
|
|
1325
1334
|
};
|
|
1326
1335
|
|
|
1327
|
-
const
|
|
1328
|
-
|
|
1329
|
-
|
|
1336
|
+
const resolveCurrentBinding = (submission: SubmissionSnapshot) =>
|
|
1337
|
+
resolveWorkerBinding(registeredBindings, submission).pipe(
|
|
1338
|
+
Effect.provideService(CurrentBindingSelection, bindingSelection),
|
|
1339
|
+
);
|
|
1340
|
+
|
|
1341
|
+
const currentOperationsFor = Effect.fnUntraced(function* (submission: SubmissionSnapshot) {
|
|
1342
|
+
const binding = yield* resolveCurrentBinding(submission).pipe(
|
|
1343
|
+
Effect.catchTag("BindingUnavailable", () => Effect.succeed(undefined)),
|
|
1344
|
+
);
|
|
1330
1345
|
|
|
1331
1346
|
return binding === undefined
|
|
1332
1347
|
? undefined
|
|
@@ -4551,6 +4566,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
4551
4566
|
journalMetadata: JournalMetadata | undefined,
|
|
4552
4567
|
lineage: AttemptLineage,
|
|
4553
4568
|
approvalDecisions: ReadonlyArray<ApprovalDecisionIntent>,
|
|
4569
|
+
currentContracts: Readonly<Record<string, Digest>>,
|
|
4554
4570
|
runTiming: { readonly startedAt: DateTime.Utc; readonly deadline: DateTime.Utc },
|
|
4555
4571
|
yieldAfter?: DateTime.Utc,
|
|
4556
4572
|
) =>
|
|
@@ -4560,13 +4576,31 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
4560
4576
|
const runId = runIdForSubmission(submissionId);
|
|
4561
4577
|
const boundaries: Array<JournalBoundary> = [];
|
|
4562
4578
|
|
|
4563
|
-
const
|
|
4564
|
-
|
|
4579
|
+
const cached = projectedJournal;
|
|
4580
|
+
|
|
4581
|
+
const journal =
|
|
4582
|
+
cached !== undefined &&
|
|
4583
|
+
cached.threadId === ctx.threadId &&
|
|
4584
|
+
cached.through === canonicalThrough &&
|
|
4585
|
+
cached.runId === runId &&
|
|
4586
|
+
cached.seedThrough === journalSeed?.throughSequence
|
|
4587
|
+
? (boundaries.push(...cached.boundaries), cached.journal)
|
|
4588
|
+
: yield* projectRunJournalStream(
|
|
4589
|
+
canonical,
|
|
4590
|
+
runId,
|
|
4591
|
+
(boundary) => boundaries.push(boundary),
|
|
4592
|
+
journalSeed,
|
|
4593
|
+
journalMetadata,
|
|
4594
|
+
);
|
|
4595
|
+
|
|
4596
|
+
projectedJournal = {
|
|
4597
|
+
threadId: ctx.threadId,
|
|
4598
|
+
through: canonicalThrough,
|
|
4565
4599
|
runId,
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4600
|
+
seedThrough: journalSeed?.throughSequence,
|
|
4601
|
+
journal,
|
|
4602
|
+
boundaries,
|
|
4603
|
+
};
|
|
4570
4604
|
|
|
4571
4605
|
const saveRecoveryCheckpoint = Effect.fn("DurableAgentRuntime.saveRecoveryCheckpoint")(
|
|
4572
4606
|
function* (compactionId: RecordId): Effect.fn.Return<void, DurableWorkerFailure> {
|
|
@@ -4873,8 +4907,6 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
4873
4907
|
journalSeed,
|
|
4874
4908
|
);
|
|
4875
4909
|
|
|
4876
|
-
const currentContracts = yield* contractsFor(agent.definition);
|
|
4877
|
-
|
|
4878
4910
|
const rolloverOperation =
|
|
4879
4911
|
journal.pendingContextToolCallId === undefined
|
|
4880
4912
|
? undefined
|
|
@@ -5009,15 +5041,43 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
5009
5041
|
|
|
5010
5042
|
// Staging also backs the cumulative summary; keep it intact and track canonical prefixes.
|
|
5011
5043
|
const committedUsageLengths = new Map<number, number>();
|
|
5044
|
+
const committedUnobservedCalls = new Map<number, number>();
|
|
5045
|
+
|
|
5046
|
+
const usageForCommit = (turn: number) => {
|
|
5047
|
+
const staged = stagedUsage.get(turn);
|
|
5048
|
+
|
|
5049
|
+
if (staged === undefined) return undefined;
|
|
5050
|
+
const modelUsage = staged.modelUsage.slice(committedUsageLengths.get(turn) ?? 0);
|
|
5051
|
+
|
|
5052
|
+
if (modelUsage.length === 0) return undefined;
|
|
5053
|
+
|
|
5054
|
+
return {
|
|
5055
|
+
modelUsage,
|
|
5056
|
+
inputTokens: modelUsage.reduce((sum, call) => sum + call.inputTokens.total, 0),
|
|
5057
|
+
outputTokens: modelUsage.reduce((sum, call) => sum + call.outputTokens.total, 0),
|
|
5058
|
+
costMicrousd: modelUsage.reduce((sum, call) => sum + call.costMicrousd, 0),
|
|
5059
|
+
};
|
|
5060
|
+
};
|
|
5061
|
+
|
|
5062
|
+
const unobservedForCommit = (turn: number) =>
|
|
5063
|
+
(stagedUnobservedCalls.get(turn) ?? 0) - (committedUnobservedCalls.get(turn) ?? 0);
|
|
5012
5064
|
|
|
5013
5065
|
const recordCommittedUsage = (batch: CanonicalBatch) => {
|
|
5014
5066
|
for (const record of batch.records) {
|
|
5015
|
-
if (
|
|
5067
|
+
if (
|
|
5068
|
+
record.payload._tag !== "ModelResponseRecorded" &&
|
|
5069
|
+
record.payload._tag !== "ModelCallAborted"
|
|
5070
|
+
)
|
|
5071
|
+
continue;
|
|
5016
5072
|
const payload = record.payload;
|
|
5017
5073
|
|
|
5018
5074
|
committedUsageLengths.set(
|
|
5019
5075
|
payload.turn,
|
|
5020
|
-
|
|
5076
|
+
(committedUsageLengths.get(payload.turn) ?? 0) + (payload.modelUsage?.length ?? 0),
|
|
5077
|
+
);
|
|
5078
|
+
committedUnobservedCalls.set(
|
|
5079
|
+
payload.turn,
|
|
5080
|
+
(committedUnobservedCalls.get(payload.turn) ?? 0) + (payload.unobservedModelCalls ?? 0),
|
|
5021
5081
|
);
|
|
5022
5082
|
}
|
|
5023
5083
|
};
|
|
@@ -5430,7 +5490,9 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
5430
5490
|
completedExhausted: undefined,
|
|
5431
5491
|
});
|
|
5432
5492
|
|
|
5433
|
-
const turnCounter = yield* Ref.make(
|
|
5493
|
+
const turnCounter = yield* Ref.make(
|
|
5494
|
+
journal.committedTurns + (journal.policyUsage.modelRestarts ?? 0),
|
|
5495
|
+
);
|
|
5434
5496
|
|
|
5435
5497
|
const idGenerator: (typeof IdGenerator)["Service"] = {
|
|
5436
5498
|
nextThreadId: Effect.succeed(submission.threadId),
|
|
@@ -5543,6 +5605,37 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
5543
5605
|
};
|
|
5544
5606
|
|
|
5545
5607
|
const durability: RunDurabilityHook<CoordinatorHalt | CompactionError, never> = {
|
|
5608
|
+
commitModelRestart: (restart) =>
|
|
5609
|
+
recordHalt(
|
|
5610
|
+
Effect.gen(function* () {
|
|
5611
|
+
if (knownIds.has(modelResponseRecordId(runId, restart.turn)))
|
|
5612
|
+
return yield* RunJournalError.make({
|
|
5613
|
+
message: "Cannot restart a canonical model response",
|
|
5614
|
+
});
|
|
5615
|
+
const recordId = decodeRecordIdSync(`model-aborted:${runId}:${restart.restart}`);
|
|
5616
|
+
|
|
5617
|
+
const record = yield* makeEnvelope(
|
|
5618
|
+
recordId,
|
|
5619
|
+
ModelCallAborted.make({
|
|
5620
|
+
runId,
|
|
5621
|
+
...restart,
|
|
5622
|
+
reason: "joined-input",
|
|
5623
|
+
modelUsage: usageForCommit(restart.turn)?.modelUsage ?? [],
|
|
5624
|
+
unobservedModelCalls: unobservedForCommit(restart.turn),
|
|
5625
|
+
}),
|
|
5626
|
+
);
|
|
5627
|
+
|
|
5628
|
+
const batch = CanonicalBatch.make({
|
|
5629
|
+
batchId: decodeBatchIdSync(recordId),
|
|
5630
|
+
producerId: config.producerId,
|
|
5631
|
+
records: [record],
|
|
5632
|
+
});
|
|
5633
|
+
|
|
5634
|
+
yield* appendBatch(ctx, batch);
|
|
5635
|
+
recordCommittedUsage(batch);
|
|
5636
|
+
knownIds.add(recordId);
|
|
5637
|
+
}),
|
|
5638
|
+
),
|
|
5546
5639
|
noteToolExposure: (turn, snapshot) =>
|
|
5547
5640
|
Effect.sync(() => {
|
|
5548
5641
|
stagedToolExposure.set(turn, snapshot);
|
|
@@ -5624,8 +5717,8 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
5624
5717
|
...(canonicalTurn === 1 && pendingSlice.length > 0
|
|
5625
5718
|
? { runScopedPrefixLength: pendingSlice.length }
|
|
5626
5719
|
: {}),
|
|
5627
|
-
usage:
|
|
5628
|
-
unobservedModelCalls:
|
|
5720
|
+
usage: usageForCommit(canonicalTurn),
|
|
5721
|
+
unobservedModelCalls: unobservedForCommit(canonicalTurn),
|
|
5629
5722
|
}),
|
|
5630
5723
|
);
|
|
5631
5724
|
|
|
@@ -6210,10 +6303,114 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
6210
6303
|
yield* commitPendingTurn;
|
|
6211
6304
|
});
|
|
6212
6305
|
|
|
6306
|
+
// Claims are authority, wakes are hints. A cancelled waiter retains every claim
|
|
6307
|
+
// for the seam drain; it never appends input while an old response can still commit.
|
|
6308
|
+
type PreparedJoin = {
|
|
6309
|
+
readonly claim: JoiningClaim;
|
|
6310
|
+
readonly input: Pick<UserInputRecorded, "input" | "messageAdmission">;
|
|
6311
|
+
readonly rendered: Prompt.RawInput;
|
|
6312
|
+
};
|
|
6313
|
+
|
|
6314
|
+
const pendingJoinClaims: Array<{ readonly claim: JoiningClaim; prepared?: PreparedJoin }> =
|
|
6315
|
+
[];
|
|
6316
|
+
|
|
6317
|
+
const claimInputs = Effect.fnUntraced(function* (maxCount: number) {
|
|
6318
|
+
const ownershipToken = yield* Ref.get(tokenRef);
|
|
6319
|
+
|
|
6320
|
+
const claims = yield* ledger.claimJoining(
|
|
6321
|
+
ClaimJoiningRequest.make({
|
|
6322
|
+
threadId: submission.threadId,
|
|
6323
|
+
hostSubmissionId: submissionId,
|
|
6324
|
+
ownershipToken,
|
|
6325
|
+
maxCount,
|
|
6326
|
+
}),
|
|
6327
|
+
);
|
|
6328
|
+
|
|
6329
|
+
pendingJoinClaims.push(...claims.map((claim) => ({ claim })));
|
|
6330
|
+
|
|
6331
|
+
return claims.length;
|
|
6332
|
+
}, Effect.uninterruptible);
|
|
6333
|
+
|
|
6334
|
+
const revertClaims = Effect.fnUntraced(function* (
|
|
6335
|
+
claims: ReadonlyArray<(typeof pendingJoinClaims)[number]>,
|
|
6336
|
+
) {
|
|
6337
|
+
for (const pending of claims) {
|
|
6338
|
+
yield* ledger.revertJoining(
|
|
6339
|
+
RevertJoiningRequest.make({ submissionId: pending.claim.submissionId }),
|
|
6340
|
+
);
|
|
6341
|
+
pendingJoinClaims.splice(pendingJoinClaims.indexOf(pending), 1);
|
|
6342
|
+
}
|
|
6343
|
+
}, Effect.uninterruptible);
|
|
6344
|
+
|
|
6345
|
+
// Preparation remains interruptible; a completed render stays with its claim so
|
|
6346
|
+
// cancellation of the waiter cannot lose it or invoke the callback again at the seam.
|
|
6347
|
+
const prepareInputs = Effect.fnUntraced(function* (limit: number, firstReady = false) {
|
|
6348
|
+
if (
|
|
6349
|
+
pendingJoinClaims.length < limit &&
|
|
6350
|
+
(yield* claimInputs(limit - pendingJoinClaims.length)) > 0
|
|
6351
|
+
)
|
|
6352
|
+
yield* hit("join:after-claim");
|
|
6353
|
+
const prepared: Array<PreparedJoin> = [];
|
|
6354
|
+
|
|
6355
|
+
for (const pending of pendingJoinClaims.slice(0, limit)) {
|
|
6356
|
+
const claim = pending.claim;
|
|
6357
|
+
|
|
6358
|
+
const snapshot = yield* ledger.loadRecoverySnapshot(
|
|
6359
|
+
RecoverySnapshotRequest.make({ submissionId: claim.submissionId }),
|
|
6360
|
+
);
|
|
6361
|
+
|
|
6362
|
+
if (snapshot.abortIntent !== undefined) {
|
|
6363
|
+
yield* revertClaims([pending]);
|
|
6364
|
+
continue;
|
|
6365
|
+
}
|
|
6366
|
+
if (pending.prepared === undefined) {
|
|
6367
|
+
const input = {
|
|
6368
|
+
input: claim.inputPayload,
|
|
6369
|
+
...(snapshot.submission.messageAdmission === undefined
|
|
6370
|
+
? {}
|
|
6371
|
+
: { messageAdmission: snapshot.submission.messageAdmission }),
|
|
6372
|
+
};
|
|
6373
|
+
|
|
6374
|
+
const rendered = yield* Effect.result(renderJoinedInput(input));
|
|
6375
|
+
|
|
6376
|
+
if (Result.isFailure(rendered)) {
|
|
6377
|
+
// A rejected prompt and its suffix retain their own Runs in queue order.
|
|
6378
|
+
yield* revertClaims(pendingJoinClaims.slice(pendingJoinClaims.indexOf(pending)));
|
|
6379
|
+
break;
|
|
6380
|
+
}
|
|
6381
|
+
pending.prepared = { claim, input, rendered: rendered.success };
|
|
6382
|
+
}
|
|
6383
|
+
prepared.push(pending.prepared);
|
|
6384
|
+
if (firstReady) break;
|
|
6385
|
+
}
|
|
6386
|
+
|
|
6387
|
+
return prepared;
|
|
6388
|
+
});
|
|
6389
|
+
|
|
6390
|
+
const awaitJoin = recordHalt(
|
|
6391
|
+
Effect.gen(function* () {
|
|
6392
|
+
while (true) {
|
|
6393
|
+
const ready = yield* Effect.scoped(
|
|
6394
|
+
Effect.gen(function* () {
|
|
6395
|
+
const notified = yield* wake.subscribe(submission.threadId);
|
|
6396
|
+
|
|
6397
|
+
if ((yield* prepareInputs(MAX_JOIN_DRAIN, true)).length > 0) return true;
|
|
6398
|
+
yield* notified;
|
|
6399
|
+
|
|
6400
|
+
return false;
|
|
6401
|
+
}),
|
|
6402
|
+
);
|
|
6403
|
+
|
|
6404
|
+
if (ready) return;
|
|
6405
|
+
}
|
|
6406
|
+
}),
|
|
6407
|
+
);
|
|
6408
|
+
|
|
6213
6409
|
const input: RunInputHook<
|
|
6214
6410
|
CoordinatorHalt | Agent.Failure<typeof agent>,
|
|
6215
6411
|
Agent.DefinitionRequirements<(typeof agent)["definition"]>
|
|
6216
6412
|
> = {
|
|
6413
|
+
awaitJoin,
|
|
6217
6414
|
drain: (policy) =>
|
|
6218
6415
|
Effect.gen(function* () {
|
|
6219
6416
|
const joinedInputs = yield* recordHalt(
|
|
@@ -6233,8 +6430,9 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
6233
6430
|
|
|
6234
6431
|
joinBacklog = hostSnapshot.joins;
|
|
6235
6432
|
}
|
|
6433
|
+
// These inputs were already consumed by an earlier attempt. Restore the
|
|
6434
|
+
// entire uncovered prompt; only fresh claims are subject to the drain bound.
|
|
6236
6435
|
for (const join of joinBacklog) {
|
|
6237
|
-
if (joinedInputs.length >= limit) break;
|
|
6238
6436
|
const joinId = join.submissionId;
|
|
6239
6437
|
|
|
6240
6438
|
if (deliveredJoinInputs.has(joinId)) continue;
|
|
@@ -6269,109 +6467,62 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
6269
6467
|
yield* preserveToolResults;
|
|
6270
6468
|
joinedInputs.push(payload);
|
|
6271
6469
|
}
|
|
6272
|
-
|
|
6273
|
-
const ownershipToken = yield* Ref.get(tokenRef);
|
|
6274
|
-
|
|
6275
|
-
const claims = yield* ledger.claimJoining(
|
|
6276
|
-
ClaimJoiningRequest.make({
|
|
6277
|
-
threadId: submission.threadId,
|
|
6278
|
-
hostSubmissionId: submissionId,
|
|
6279
|
-
ownershipToken,
|
|
6280
|
-
maxCount: limit - joinedInputs.length,
|
|
6281
|
-
}),
|
|
6282
|
-
);
|
|
6470
|
+
const claims = yield* prepareInputs(limit);
|
|
6283
6471
|
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6472
|
+
pendingJoinClaims.splice(0, claims.length);
|
|
6473
|
+
for (const { claim, input: payload, rendered } of claims) {
|
|
6474
|
+
yield* preserveToolResults;
|
|
6475
|
+
const recordId = submissionInputRecordId(claim.submissionId);
|
|
6476
|
+
let sequence: CanonicalSequence;
|
|
6477
|
+
const existing = joinedInputEnvelopes.get(claim.submissionId);
|
|
6478
|
+
|
|
6479
|
+
if (existing !== undefined) {
|
|
6480
|
+
// Defensive reattach: the exact record is already canonical, so only the
|
|
6481
|
+
// marker and the delivery remain (DUR-016 — never a duplicate append).
|
|
6482
|
+
sequence = existing.sequence;
|
|
6483
|
+
} else {
|
|
6484
|
+
const envelope = yield* makeEnvelope(
|
|
6485
|
+
recordId,
|
|
6486
|
+
UserInputRecorded.make({
|
|
6487
|
+
submissionId: claim.submissionId,
|
|
6488
|
+
kind: "steering",
|
|
6489
|
+
runId,
|
|
6490
|
+
input: claim.inputPayload,
|
|
6491
|
+
...(payload.messageAdmission === undefined
|
|
6492
|
+
? {}
|
|
6493
|
+
: { messageAdmission: payload.messageAdmission }),
|
|
6494
|
+
}),
|
|
6290
6495
|
);
|
|
6291
6496
|
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
);
|
|
6299
|
-
continue;
|
|
6300
|
-
}
|
|
6301
|
-
|
|
6302
|
-
const payload = {
|
|
6303
|
-
input: claim.inputPayload,
|
|
6304
|
-
...(claimSnapshot.submission.messageAdmission === undefined
|
|
6305
|
-
? {}
|
|
6306
|
-
: { messageAdmission: claimSnapshot.submission.messageAdmission }),
|
|
6307
|
-
};
|
|
6308
|
-
|
|
6309
|
-
const rendered = yield* Effect.result(renderJoinedInput(payload));
|
|
6310
|
-
|
|
6311
|
-
if (Result.isFailure(rendered)) {
|
|
6312
|
-
// The rejecting input gets its own Run and normal typed failure.
|
|
6313
|
-
// Leave it and the unconsumed suffix ready, preserving queue order
|
|
6314
|
-
// and preventing one invalid prompt from failing unrelated receipts.
|
|
6315
|
-
for (const remaining of claims.slice(claims.indexOf(claim))) {
|
|
6316
|
-
yield* ledger.revertJoining(
|
|
6317
|
-
RevertJoiningRequest.make({ submissionId: remaining.submissionId }),
|
|
6318
|
-
);
|
|
6319
|
-
}
|
|
6320
|
-
break;
|
|
6321
|
-
}
|
|
6322
|
-
yield* preserveToolResults;
|
|
6323
|
-
const recordId = submissionInputRecordId(claim.submissionId);
|
|
6324
|
-
let sequence: CanonicalSequence;
|
|
6325
|
-
const existing = joinedInputEnvelopes.get(claim.submissionId);
|
|
6326
|
-
|
|
6327
|
-
if (existing !== undefined) {
|
|
6328
|
-
// Defensive reattach: the exact record is already canonical, so only the
|
|
6329
|
-
// marker and the delivery remain (DUR-016 — never a duplicate append).
|
|
6330
|
-
sequence = existing.sequence;
|
|
6331
|
-
} else {
|
|
6332
|
-
const envelope = yield* makeEnvelope(
|
|
6333
|
-
recordId,
|
|
6334
|
-
UserInputRecorded.make({
|
|
6335
|
-
submissionId: claim.submissionId,
|
|
6336
|
-
kind: "steering",
|
|
6337
|
-
runId,
|
|
6338
|
-
input: claim.inputPayload,
|
|
6339
|
-
...(claimSnapshot.submission.messageAdmission === undefined
|
|
6340
|
-
? {}
|
|
6341
|
-
: { messageAdmission: claimSnapshot.submission.messageAdmission }),
|
|
6342
|
-
}),
|
|
6343
|
-
);
|
|
6344
|
-
|
|
6345
|
-
const result = yield* appendBatch(
|
|
6346
|
-
ctx,
|
|
6347
|
-
CanonicalBatch.make({
|
|
6348
|
-
batchId: submissionInputBatchId(claim.submissionId),
|
|
6349
|
-
producerId: config.producerId,
|
|
6350
|
-
records: [envelope],
|
|
6351
|
-
}),
|
|
6352
|
-
);
|
|
6353
|
-
|
|
6354
|
-
sequence = result.firstSequence;
|
|
6355
|
-
knownIds.add(recordId);
|
|
6356
|
-
yield* hit("join:after-canonical-append");
|
|
6357
|
-
}
|
|
6358
|
-
// Re-read the token: the concurrent lease renewal may rotate it mid-batch.
|
|
6359
|
-
const markToken = yield* Ref.get(tokenRef);
|
|
6360
|
-
|
|
6361
|
-
yield* ledger.markJoined(
|
|
6362
|
-
MarkJoinedRequest.make({
|
|
6363
|
-
submissionId: claim.submissionId,
|
|
6364
|
-
ownershipToken: markToken,
|
|
6365
|
-
recordId,
|
|
6366
|
-
sequence,
|
|
6497
|
+
const result = yield* appendBatch(
|
|
6498
|
+
ctx,
|
|
6499
|
+
CanonicalBatch.make({
|
|
6500
|
+
batchId: submissionInputBatchId(claim.submissionId),
|
|
6501
|
+
producerId: config.producerId,
|
|
6502
|
+
records: [envelope],
|
|
6367
6503
|
}),
|
|
6368
6504
|
);
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
});
|
|
6505
|
+
|
|
6506
|
+
sequence = result.firstSequence;
|
|
6507
|
+
knownIds.add(recordId);
|
|
6508
|
+
yield* hit("join:after-canonical-append");
|
|
6374
6509
|
}
|
|
6510
|
+
// Re-read the token: the concurrent lease renewal may rotate it mid-batch.
|
|
6511
|
+
const markToken = yield* Ref.get(tokenRef);
|
|
6512
|
+
|
|
6513
|
+
yield* ledger.markJoined(
|
|
6514
|
+
MarkJoinedRequest.make({
|
|
6515
|
+
submissionId: claim.submissionId,
|
|
6516
|
+
ownershipToken: markToken,
|
|
6517
|
+
recordId,
|
|
6518
|
+
sequence,
|
|
6519
|
+
}),
|
|
6520
|
+
);
|
|
6521
|
+
deliveredJoinInputs.add(claim.submissionId);
|
|
6522
|
+
joinedInputs.push({
|
|
6523
|
+
...payload,
|
|
6524
|
+
rendered,
|
|
6525
|
+
});
|
|
6375
6526
|
}
|
|
6376
6527
|
|
|
6377
6528
|
return joinedInputs;
|
|
@@ -7014,7 +7165,17 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
7014
7165
|
: {}),
|
|
7015
7166
|
approval,
|
|
7016
7167
|
toolAuthorization,
|
|
7017
|
-
...(journal.toolSelection === undefined
|
|
7168
|
+
...(journal.toolSelection === undefined
|
|
7169
|
+
? {}
|
|
7170
|
+
: {
|
|
7171
|
+
toolSelection: {
|
|
7172
|
+
// A settled discovery receipt survives deployment; its selection only
|
|
7173
|
+
// names current tools. Keep validation of fresh selections fail-closed.
|
|
7174
|
+
toolNames: journal.toolSelection.toolNames.filter((name) =>
|
|
7175
|
+
Object.hasOwn(agent.definition.toolkit.tools, name),
|
|
7176
|
+
),
|
|
7177
|
+
},
|
|
7178
|
+
}),
|
|
7018
7179
|
durability,
|
|
7019
7180
|
subagent,
|
|
7020
7181
|
delegationDepth,
|
|
@@ -7296,8 +7457,8 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
7296
7457
|
createdAt,
|
|
7297
7458
|
...(runScopedPrefixLength > 0 ? { runScopedPrefixLength } : {}),
|
|
7298
7459
|
...(completedRun === undefined ? {} : { runCompletion: completedRun }),
|
|
7299
|
-
usage:
|
|
7300
|
-
unobservedModelCalls:
|
|
7460
|
+
usage: usageForCommit(canonicalTurn),
|
|
7461
|
+
unobservedModelCalls: unobservedForCommit(canonicalTurn),
|
|
7301
7462
|
}),
|
|
7302
7463
|
);
|
|
7303
7464
|
|
|
@@ -7363,6 +7524,11 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
7363
7524
|
|
|
7364
7525
|
const handleEvent = (event: RunEvent): Effect.Effect<void, DurableWorkerFailure> => {
|
|
7365
7526
|
switch (event._tag) {
|
|
7527
|
+
case "ModelRestarted": {
|
|
7528
|
+
// A finish part can arrive before the provider stream closes. Its TurnCompleted
|
|
7529
|
+
// only staged this disposable Turn; never let the next seam commit its prefix.
|
|
7530
|
+
return Ref.update(stateRef, (state) => ({ ...state, pendingTurn: undefined }));
|
|
7531
|
+
}
|
|
7366
7532
|
case "TurnStarted": {
|
|
7367
7533
|
// Suspension owns only this Turn's siblings. Earlier results are already canonical
|
|
7368
7534
|
// under their original Turn and must never be re-recorded with a later Turn id.
|
|
@@ -7994,6 +8160,10 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
7994
8160
|
definition: { ...registeredAgent.definition, policy: childPolicy },
|
|
7995
8161
|
};
|
|
7996
8162
|
|
|
8163
|
+
// Restoring the accepted child policy changes no Tool declarations. Retain the
|
|
8164
|
+
// selected registration's contracts instead of resolving the copied Definition.
|
|
8165
|
+
const currentContracts = yield* contractsFor(registeredAgent.definition);
|
|
8166
|
+
|
|
7997
8167
|
const evidence = yield* evidenceFor(records, submissionId, true, snapshot.hostSubmissionId);
|
|
7998
8168
|
const knownIds = knownRecordIdsOf(records);
|
|
7999
8169
|
|
|
@@ -8089,7 +8259,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8089
8259
|
reconciliationRecords,
|
|
8090
8260
|
reconciliationEvidence.openToolCalls,
|
|
8091
8261
|
knownIds,
|
|
8092
|
-
{ definition: agent.definition, contracts:
|
|
8262
|
+
{ definition: agent.definition, contracts: currentContracts },
|
|
8093
8263
|
);
|
|
8094
8264
|
|
|
8095
8265
|
if (review.uncertain.length > 0 || review.unproven.length > 0) {
|
|
@@ -8129,7 +8299,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8129
8299
|
if (continuation !== undefined) {
|
|
8130
8300
|
const current = {
|
|
8131
8301
|
definition: agent.definition,
|
|
8132
|
-
contracts:
|
|
8302
|
+
contracts: currentContracts,
|
|
8133
8303
|
};
|
|
8134
8304
|
|
|
8135
8305
|
const operations = operationsFor(continuationRecords, runIdForSubmission(submissionId));
|
|
@@ -8304,6 +8474,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8304
8474
|
journalMetadata?.snapshot(),
|
|
8305
8475
|
lineage,
|
|
8306
8476
|
approvalDecisionIntents,
|
|
8477
|
+
currentContracts,
|
|
8307
8478
|
runTiming,
|
|
8308
8479
|
yieldAfter,
|
|
8309
8480
|
);
|
|
@@ -8749,9 +8920,6 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8749
8920
|
);
|
|
8750
8921
|
});
|
|
8751
8922
|
|
|
8752
|
-
const resolveCurrentBinding = (submission: SubmissionSnapshot) =>
|
|
8753
|
-
resolveWorkerBinding(registeredBindings, submission.agentId);
|
|
8754
|
-
|
|
8755
8923
|
const processThreadResolvedImpl = (
|
|
8756
8924
|
threadId: ThreadId,
|
|
8757
8925
|
): Effect.Effect<ReadonlyArray<Settlement>, DurableWorkerFailure | DurableBindingFailure> =>
|
|
@@ -9001,7 +9169,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
9001
9169
|
records,
|
|
9002
9170
|
evidence.openToolCalls.filter((call) => markableIds.has(call.toolCallId)),
|
|
9003
9171
|
knownIds,
|
|
9004
|
-
yield* currentOperationsFor(submission
|
|
9172
|
+
yield* currentOperationsFor(submission),
|
|
9005
9173
|
);
|
|
9006
9174
|
|
|
9007
9175
|
let disposition: "repaired" | "deferred" | "unknown";
|
|
@@ -9040,7 +9208,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
9040
9208
|
if (!snapshot.unknownResolutions.some((intent) => intent.resolution._tag === "SafeToRetry"))
|
|
9041
9209
|
return false;
|
|
9042
9210
|
const submission = snapshot.submission;
|
|
9043
|
-
const current = yield* currentOperationsFor(submission
|
|
9211
|
+
const current = yield* currentOperationsFor(submission);
|
|
9044
9212
|
const operations = operationsFor(records, runIdForSubmission(submission.submissionId));
|
|
9045
9213
|
|
|
9046
9214
|
for (const intent of snapshot.unknownResolutions) {
|
|
@@ -10978,6 +11146,29 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
10978
11146
|
}).pipe(Effect.provideService(WorkerRuntime, workerRuntime));
|
|
10979
11147
|
|
|
10980
11148
|
return DurableAgentRuntime.of({
|
|
11149
|
+
bindingRegistryKey: yield* withCrypto(
|
|
11150
|
+
digestJson({
|
|
11151
|
+
selection: bindingSelection?.key ?? null,
|
|
11152
|
+
bindings: (yield* Effect.forEach(registeredBindings, (binding) =>
|
|
11153
|
+
withCrypto(
|
|
11154
|
+
digestJson({
|
|
11155
|
+
agentId: binding.agentId,
|
|
11156
|
+
agent: binding.digests.agent,
|
|
11157
|
+
model: binding.digests.model,
|
|
11158
|
+
tools: binding.digests.tools,
|
|
11159
|
+
replay:
|
|
11160
|
+
binding.digests.replay === undefined
|
|
11161
|
+
? null
|
|
11162
|
+
: {
|
|
11163
|
+
agent: binding.digests.replay.agent,
|
|
11164
|
+
agentBehavior: binding.digests.replay.agentBehavior ?? null,
|
|
11165
|
+
tools: binding.digests.replay.tools,
|
|
11166
|
+
},
|
|
11167
|
+
}),
|
|
11168
|
+
),
|
|
11169
|
+
).pipe(Effect.orDie)).sort(),
|
|
11170
|
+
}),
|
|
11171
|
+
).pipe(Effect.orDie),
|
|
10981
11172
|
workerHost: workerRuntime.acquire,
|
|
10982
11173
|
messagingHost: messagingRuntime.acquire,
|
|
10983
11174
|
submitRegistered,
|
|
@@ -11069,6 +11260,8 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
11069
11260
|
export class DurableAgentRuntime extends Context.Service<
|
|
11070
11261
|
DurableAgentRuntime,
|
|
11071
11262
|
{
|
|
11263
|
+
/** Stable registration identity for hosts parking unavailable bindings; never an admission authority. */
|
|
11264
|
+
readonly bindingRegistryKey: string;
|
|
11072
11265
|
/** Acquire an authenticated source Thread facet; its References confer no authority. */
|
|
11073
11266
|
readonly workerHost: (request: {
|
|
11074
11267
|
readonly sourceThreadId: ThreadId;
|
|
@@ -11320,7 +11513,7 @@ export class DurableAgentRuntime extends Context.Service<
|
|
|
11320
11513
|
>()("@effect-agent/thread/DurableAgentRuntime") {
|
|
11321
11514
|
/**
|
|
11322
11515
|
* Resolve typed registrations and capture their services once in the runtime's Layer Scope.
|
|
11323
|
-
* Every claimed head must
|
|
11516
|
+
* Every claimed head must select exactly one current registered Definition. Worker calls
|
|
11324
11517
|
* cannot replace these registrations or their captured services. Tool authorization is required.
|
|
11325
11518
|
*/
|
|
11326
11519
|
static layerRegistered<const Entries extends ReadonlyArray<AgentRegistration>>(
|