@yielded/agent 0.1.0-beta.174 → 0.1.0-beta.175
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-BHmp2V9p.d.mts → Admin-Qa3I1oA5.d.mts} +38 -7
- package/dist/{AgentRuntime-BD3ZHAMq.d.mts → AgentRuntime-CHDyRbSf.d.mts} +3 -3
- package/dist/{AgentRuntime-B6qZlD3f.mjs → AgentRuntime-DaDKMasp.mjs} +123 -114
- package/dist/AgentRuntime-DaDKMasp.mjs.map +1 -0
- package/dist/{Digest-EpeqWEdv.mjs → Digest-C3EODOee.mjs} +2 -2
- package/dist/{Digest-EpeqWEdv.mjs.map → Digest-C3EODOee.mjs.map} +1 -1
- package/dist/{DurableAgentRuntime-CBBjRNJN.mjs → DurableAgentRuntime-CPlw5_7e.mjs} +161 -85
- package/dist/DurableAgentRuntime-CPlw5_7e.mjs.map +1 -0
- package/dist/{EventSource-C9aaJaXT.d.mts → EventSource-BTu68yDW.d.mts} +2 -2
- package/dist/InMemory.d.mts +2 -2
- package/dist/{MessageDelivery-BGDm-c46.d.mts → MessageDelivery-DjAZJ4Fd.d.mts} +4 -4
- package/dist/{MessagingHost-CRUK4JBi.mjs → MessagingHost-CZCyrnvJ.mjs} +27 -26
- package/dist/MessagingHost-CZCyrnvJ.mjs.map +1 -0
- package/dist/{PreparedInputAdmission-BvDqlgiP.d.mts → PreparedInputAdmission-wgY4JMZY.d.mts} +3 -3
- package/dist/{Records-BiuJDWNe.mjs → Records-DzL4Kbtw.mjs} +2 -2
- package/dist/{Records-BiuJDWNe.mjs.map → Records-DzL4Kbtw.mjs.map} +1 -1
- package/dist/{RunContinuation-CTJ1jGrO.d.mts → RunContinuation-3jB5pULC.d.mts} +10 -4
- package/dist/{RunContinuation-4ZATcVLB.mjs → RunContinuation-BiyKJK32.mjs} +74 -40
- package/dist/RunContinuation-BiyKJK32.mjs.map +1 -0
- package/dist/{RunJournal-CNZqA3Ge.mjs → RunJournal-CPMKcfd0.mjs} +84 -79
- package/dist/RunJournal-CPMKcfd0.mjs.map +1 -0
- package/dist/{RunStorage-BHjuuERI.mjs → RunStorage-CzutHJBE.mjs} +3 -2
- package/dist/RunStorage-CzutHJBE.mjs.map +1 -0
- package/dist/{Scheduling-NG8slKdI.mjs → Scheduling-07_dsGED.mjs} +3 -3
- package/dist/{Scheduling-NG8slKdI.mjs.map → Scheduling-07_dsGED.mjs.map} +1 -1
- package/dist/{Subagent-CTIpnzlB.mjs → Subagent-CexndZSp.mjs} +2 -2
- package/dist/{Subagent-CTIpnzlB.mjs.map → Subagent-CexndZSp.mjs.map} +1 -1
- package/dist/{Subagent-DKhZA72u.d.mts → Subagent-xhN_aD1r.d.mts} +3 -3
- package/dist/{Subscription-BNg9VCRl.d.mts → Subscription-DmIHlOJK.d.mts} +2 -2
- package/dist/{SubscriptionInput-BUoXv-_K.d.mts → SubscriptionInput-DgcQhvbe.d.mts} +2 -2
- package/dist/{Thread-dk-QiNml.d.mts → Thread-DzdJAY4J.d.mts} +4 -3
- package/dist/{ThreadHistory-ByxS8HU1.d.mts → ThreadHistory-KPPBJLJb.d.mts} +12 -2
- package/dist/{ThreadImport-CodYoJoa.mjs → ThreadImport-CjlG57vH.mjs} +8 -8
- package/dist/{ThreadImport-CodYoJoa.mjs.map → ThreadImport-CjlG57vH.mjs.map} +1 -1
- package/dist/{ThreadImport-CMgzttvr.d.mts → ThreadImport-DP-vOk2F.d.mts} +4 -4
- package/dist/{ThreadStore-59uDGXul.mjs → ThreadStore-EuUilthA.mjs} +5 -7
- package/dist/ThreadStore-EuUilthA.mjs.map +1 -0
- package/dist/{ThreadTransfer-3jigUl3g.mjs → ThreadTransfer-DB_zsrtJ.mjs} +4 -4
- package/dist/{ThreadTransfer-3jigUl3g.mjs.map → ThreadTransfer-DB_zsrtJ.mjs.map} +1 -1
- package/dist/{WorkerAdmission-DDYJdOsU.mjs → WorkerAdmission-eBeXt_mu.mjs} +5 -5
- package/dist/{WorkerAdmission-DDYJdOsU.mjs.map → WorkerAdmission-eBeXt_mu.mjs.map} +1 -1
- package/dist/{agent-registration-DRbyhAu-.mjs → agent-registration-a6QYaG3h.mjs} +4 -4
- package/dist/{agent-registration-DRbyhAu-.mjs.map → agent-registration-a6QYaG3h.mjs.map} +1 -1
- package/dist/capabilities/Messaging.mjs +1 -1
- package/dist/capabilities/ModelContext.d.mts +1 -1
- package/dist/capabilities/RunHooks.d.mts +1 -1
- package/dist/capabilities/Subagent.d.mts +1 -1
- package/dist/capabilities/Subagent.mjs +1 -1
- package/dist/core/Thread.d.mts +2 -2
- package/dist/core/Thread.mjs +5 -3
- package/dist/core/Thread.mjs.map +1 -1
- package/dist/durable/ActivityStore.mjs +1 -1
- package/dist/durable/Admin.d.mts +1 -1
- package/dist/durable/Admin.mjs +1 -1
- package/dist/durable/AgentRegistration.d.mts +1 -1
- package/dist/durable/AgentRegistration.mjs +1 -1
- package/dist/durable/Certification.d.mts +1 -1
- package/dist/durable/CommittedActivity.d.mts +1 -1
- package/dist/durable/CommittedActivity.mjs +3 -3
- package/dist/durable/Digest.mjs +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/EventSource.mjs +1 -1
- package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/LifecyclePublication.d.mts +1 -1
- package/dist/durable/LifecyclePublication.mjs +2 -2
- package/dist/durable/MessageDelivery.d.mts +1 -1
- package/dist/durable/MessageDelivery.mjs +2 -2
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +40 -40
- package/dist/durable/MessageDeliveryStoreConformance.mjs +2 -2
- package/dist/durable/PersistentHistory.d.mts +2 -2
- package/dist/durable/PersistentHistory.mjs +4 -4
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/RecordFormat.mjs +1 -1
- package/dist/durable/Records.mjs +1 -1
- package/dist/durable/Recovery.d.mts +1 -1
- package/dist/durable/Recovery.mjs +1 -1
- package/dist/durable/RunContinuation.d.mts +2 -2
- package/dist/durable/RunContinuation.mjs +3 -3
- package/dist/durable/RunJournal.d.mts +2 -2
- package/dist/durable/RunJournal.mjs +2 -2
- package/dist/durable/RunStorage.d.mts +1 -1
- package/dist/durable/RunStorage.mjs +1 -1
- package/dist/durable/Schedule.mjs +1 -1
- package/dist/durable/ScheduleStoreConformance.mjs +1 -1
- package/dist/durable/ScheduleTransition.mjs +1 -1
- package/dist/durable/Scheduling.d.mts +1 -1
- package/dist/durable/Scheduling.mjs +1 -1
- package/dist/durable/SettlementPublisher.d.mts +1 -1
- package/dist/durable/SettlementPublisher.mjs +3 -3
- package/dist/durable/SqlMemoryStore.mjs +5 -3
- package/dist/durable/SqlMemoryStore.mjs.map +1 -1
- package/dist/durable/SubmissionLedger.d.mts +1 -1
- package/dist/durable/SubmissionLedger.mjs +7 -3
- package/dist/durable/SubmissionLedger.mjs.map +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.mjs +6 -6
- package/dist/durable/SubmissionStatus.d.mts +1 -1
- package/dist/durable/Subscription.d.mts +1 -1
- package/dist/durable/Subscription.mjs +2 -2
- package/dist/durable/SubscriptionInput.d.mts +1 -1
- package/dist/durable/SubscriptionInput.mjs +2 -2
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionStoreConformance.mjs +1 -1
- package/dist/durable/SubscriptionTools.d.mts +2 -2
- package/dist/durable/SubscriptionTransition.d.mts +1 -1
- package/dist/durable/SubscriptionTransition.mjs +1 -1
- package/dist/durable/Subscriptions.d.mts +5 -5
- package/dist/durable/Subscriptions.mjs +2 -2
- package/dist/durable/ThreadArchiveRange.d.mts +1 -1
- package/dist/durable/ThreadArchiveRange.mjs +1 -1
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadContextHistory.mjs +2 -2
- package/dist/durable/ThreadContextHistoryProjection.mjs +1 -1
- package/dist/durable/ThreadImport.d.mts +1 -1
- package/dist/durable/ThreadImport.mjs +1 -1
- package/dist/durable/ThreadInvariants.d.mts +3 -3
- package/dist/durable/ThreadInvariants.mjs +4 -4
- package/dist/durable/ThreadProjection.mjs +1 -1
- package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
- package/dist/durable/ThreadReader.d.mts +1 -1
- package/dist/durable/ThreadReader.mjs +1 -1
- package/dist/durable/ThreadStore.d.mts +1 -1
- package/dist/durable/ThreadStore.mjs +2 -2
- package/dist/durable/ThreadStoreConformance.d.mts +1 -1
- package/dist/durable/ThreadStoreConformance.mjs +4 -4
- package/dist/durable/ThreadTransfer.d.mts +1 -1
- package/dist/durable/ThreadTransfer.mjs +1 -1
- package/dist/durable/ThreadWork.d.mts +2 -2
- package/dist/durable/ThreadWork.mjs +12 -6
- package/dist/durable/ThreadWork.mjs.map +1 -1
- package/dist/durable/ToolReconciler.mjs +1 -1
- package/dist/durable/WakeScheduler.mjs +23 -39
- package/dist/durable/WakeScheduler.mjs.map +1 -1
- package/dist/durable/WorkerAdmission.d.mts +1 -1
- package/dist/durable/WorkerAdmission.mjs +1 -1
- package/dist/durable/WorkerHost.d.mts +1 -1
- package/dist/engine/AgentRuntime.d.mts +1 -1
- package/dist/engine/AgentRuntime.mjs +1 -1
- package/dist/engine/MessagingHost.mjs +1 -1
- package/dist/engine/Output.mjs +1 -1
- package/dist/engine/ThreadHistory.d.mts +1 -1
- package/dist/engine/ThreadHistory.mjs +3 -2
- package/dist/engine/ThreadHistory.mjs.map +1 -1
- package/dist/index.d.mts +12 -12
- package/dist/index.mjs +13 -13
- package/dist/{output-contract-CMIhu4Cw.mjs → output-contract-DCnLYCdp.mjs} +12 -15
- package/dist/{output-contract-CMIhu4Cw.mjs.map → output-contract-DCnLYCdp.mjs.map} +1 -1
- package/dist/{run-context-reader-CC7ZD95F.d.mts → run-context-reader-DVhJZ1Qe.d.mts} +2 -2
- package/package.json +1 -1
- package/src/core/Thread.ts +143 -146
- package/src/durable/DurableAgentRuntime.ts +381 -206
- package/src/durable/RunContinuation.ts +113 -62
- package/src/durable/RunJournal.ts +99 -108
- package/src/durable/RunStorage.ts +7 -0
- package/src/durable/SqlMemoryStore.ts +8 -6
- package/src/durable/SubmissionLedger.ts +7 -0
- package/src/durable/ThreadStore.ts +9 -7
- package/src/durable/ThreadWork.ts +10 -0
- package/src/durable/WakeScheduler.ts +34 -66
- package/src/durable/internal/usage-totals.ts +28 -31
- package/src/engine/MessagingHost.ts +4 -2
- package/src/engine/ThreadHistory.ts +47 -48
- package/src/engine/internal/agent-runtime.ts +234 -202
- package/src/engine/internal/output-contract.ts +15 -15
- package/src/engine/internal/primitive-delta.ts +2 -3
- package/src/engine/internal/tool-telemetry.ts +3 -5
- package/dist/AgentRuntime-B6qZlD3f.mjs.map +0 -1
- package/dist/DurableAgentRuntime-CBBjRNJN.mjs.map +0 -1
- package/dist/MessagingHost-CRUK4JBi.mjs.map +0 -1
- package/dist/RunContinuation-4ZATcVLB.mjs.map +0 -1
- package/dist/RunJournal-CNZqA3Ge.mjs.map +0 -1
- package/dist/RunStorage-BHjuuERI.mjs.map +0 -1
- package/dist/ThreadStore-59uDGXul.mjs.map +0 -1
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
getToolExecutionKind,
|
|
64
64
|
SubagentParentLink,
|
|
65
65
|
} from "../core/SubagentContract.ts";
|
|
66
|
+
import { Store as ConversationStore, makeMemoryStore } from "../core/Thread.ts";
|
|
66
67
|
import { Selection, Snapshot } from "../core/ToolExposure.ts";
|
|
67
68
|
import type { ToolParameterRejection } from "../core/ToolResult.ts";
|
|
68
69
|
import {
|
|
@@ -280,6 +281,7 @@ import {
|
|
|
280
281
|
modelResponseInterruptedRecordId,
|
|
281
282
|
modelResponseRecordId,
|
|
282
283
|
projectRunJournalStream,
|
|
284
|
+
initialRunJournal,
|
|
283
285
|
type JournalBoundary,
|
|
284
286
|
type RunJournalProjection,
|
|
285
287
|
type RunJournalContext,
|
|
@@ -846,6 +848,11 @@ export class RecoverySweepResult extends Schema.Class<RecoverySweepResult>("Reco
|
|
|
846
848
|
/** Recover one bounded page of native work, optionally confined to one Thread. */
|
|
847
849
|
export interface RecoverySweepOptions {
|
|
848
850
|
readonly threadId?: ThreadId;
|
|
851
|
+
/** Leave this incarnation's untouched root admissions to their first actual claim.
|
|
852
|
+
* A verified sole admission needs no recovery inventory; other owners retain bounded
|
|
853
|
+
* discovery and deferred reports. Neither case supplies ownership or a recovery decision:
|
|
854
|
+
* the Attempt still verifies current controls, journal, fencing and historyDigest. */
|
|
855
|
+
readonly deferUnclaimedAdmissions?: boolean;
|
|
849
856
|
/** Continue the previous pass with the same Thread selection until its result has no cursor. */
|
|
850
857
|
readonly cursor?: string;
|
|
851
858
|
}
|
|
@@ -1374,6 +1381,11 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
1374
1381
|
const reader = ThreadReader.fromStore(store);
|
|
1375
1382
|
const promptHistory = yield* makePromptHistoryCache();
|
|
1376
1383
|
|
|
1384
|
+
// One incarnation remembers only newly accepted root input, never a recovery decision.
|
|
1385
|
+
// A claim consumes the hint before binding/application code can run. Cold owners,
|
|
1386
|
+
// replays, linked inputs, and any changed ledger state retain the recovery path.
|
|
1387
|
+
const unclaimedAdmissions = new Map<SubmissionId, ThreadId>();
|
|
1388
|
+
|
|
1377
1389
|
const workDiscovery = yield* ThreadWorkDiscovery.pipe(
|
|
1378
1390
|
Effect.provide(ThreadWorkDiscovery.layer),
|
|
1379
1391
|
Effect.provideService(ThreadStore, store),
|
|
@@ -1444,6 +1456,17 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
1444
1456
|
// observer must never replace this host choice on a fresh or replacement Attempt.
|
|
1445
1457
|
const toolFailureObserver = yield* CurrentToolFailureObserver;
|
|
1446
1458
|
|
|
1459
|
+
const runServices = Context.make(CurrentToolFailureObserver, toolFailureObserver).pipe(
|
|
1460
|
+
Context.add(RunToolVisibility, runToolVisibility),
|
|
1461
|
+
Context.add(RunToolScheduling, runToolScheduling),
|
|
1462
|
+
Context.add(ContextCompactor, compactor),
|
|
1463
|
+
Context.add(RunContextPreparation, runContextPreparation),
|
|
1464
|
+
);
|
|
1465
|
+
|
|
1466
|
+
const journalServices = Context.make(ThreadReader, reader).pipe(
|
|
1467
|
+
Context.add(Crypto.Crypto, crypto),
|
|
1468
|
+
);
|
|
1469
|
+
|
|
1447
1470
|
const withCrypto = <A, E>(effect: Effect.Effect<A, E, Crypto.Crypto>): Effect.Effect<A, E> =>
|
|
1448
1471
|
Effect.provideService(effect, Crypto.Crypto, crypto);
|
|
1449
1472
|
|
|
@@ -1453,8 +1476,7 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
1453
1476
|
suffix: ReadonlyArray<CanonicalRecordEnvelope>,
|
|
1454
1477
|
) =>
|
|
1455
1478
|
initialContext(original).pipe(
|
|
1456
|
-
Effect.
|
|
1457
|
-
Effect.provideService(Crypto.Crypto, crypto),
|
|
1479
|
+
Effect.provideContext(journalServices),
|
|
1458
1480
|
Effect.map((history) => history.concat(suffix)),
|
|
1459
1481
|
);
|
|
1460
1482
|
|
|
@@ -1708,10 +1730,7 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
1708
1730
|
|
|
1709
1731
|
if (found === undefined) {
|
|
1710
1732
|
// An exact lookup distinguishes missing evidence from an incomplete native index.
|
|
1711
|
-
yield* resolveEvidence(threadId, ref).pipe(
|
|
1712
|
-
Effect.provideService(ThreadReader, reader),
|
|
1713
|
-
Effect.provideService(Crypto.Crypto, crypto),
|
|
1714
|
-
);
|
|
1733
|
+
yield* resolveEvidence(threadId, ref).pipe(Effect.provideContext(journalServices));
|
|
1715
1734
|
|
|
1716
1735
|
return yield* invalid(
|
|
1717
1736
|
"Required Run evidence is absent from its locator; rebuild the index explicitly",
|
|
@@ -1778,8 +1797,7 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
1778
1797
|
} else {
|
|
1779
1798
|
saved = yield* readRunContext(initial, input, cursor.savedContext.recordId).pipe(
|
|
1780
1799
|
Effect.provide(RunContextReader.layer(threadId)),
|
|
1781
|
-
Effect.
|
|
1782
|
-
Effect.provideService(Crypto.Crypto, crypto),
|
|
1800
|
+
Effect.provideContext(journalServices),
|
|
1783
1801
|
Effect.mapError(() =>
|
|
1784
1802
|
invalid("Saved original context cannot be resolved from its evidence"),
|
|
1785
1803
|
),
|
|
@@ -2573,8 +2591,7 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
2573
2591
|
const progress =
|
|
2574
2592
|
active?.writer ??
|
|
2575
2593
|
(yield* makeProgressWriter(writer.threadId, config.deploymentId).pipe(
|
|
2576
|
-
Effect.
|
|
2577
|
-
Effect.provideService(Crypto.Crypto, crypto),
|
|
2594
|
+
Effect.provideContext(journalServices),
|
|
2578
2595
|
));
|
|
2579
2596
|
|
|
2580
2597
|
const owned: RunWriter = {
|
|
@@ -2633,8 +2650,7 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
2633
2650
|
const progress =
|
|
2634
2651
|
active?.writer ??
|
|
2635
2652
|
(yield* makeProgressWriter(request.threadId, config.deploymentId).pipe(
|
|
2636
|
-
Effect.
|
|
2637
|
-
Effect.provideService(Crypto.Crypto, crypto),
|
|
2653
|
+
Effect.provideContext(journalServices),
|
|
2638
2654
|
));
|
|
2639
2655
|
|
|
2640
2656
|
let tail = {
|
|
@@ -4856,23 +4872,35 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
4856
4872
|
historyEvidence.set(entry.record.recordId, entry);
|
|
4857
4873
|
};
|
|
4858
4874
|
|
|
4875
|
+
// An exact cache prefix followed only by this fresh input has no response,
|
|
4876
|
+
// policy reservation or context to replay. Keep recovery on the full projector.
|
|
4877
|
+
const freshPrefix =
|
|
4878
|
+
priorContext === undefined &&
|
|
4879
|
+
initialJournal?.prefix !== undefined &&
|
|
4880
|
+
initialJournal.records?.length === 1 &&
|
|
4881
|
+
initialJournal.records[0] === originalInput
|
|
4882
|
+
? initialJournal.prefix.prompt
|
|
4883
|
+
: undefined;
|
|
4884
|
+
|
|
4859
4885
|
let journal =
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
cached.
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4886
|
+
freshPrefix !== undefined
|
|
4887
|
+
? initialRunJournal(freshPrefix)
|
|
4888
|
+
: cached !== undefined &&
|
|
4889
|
+
cached.threadId === ctx.threadId &&
|
|
4890
|
+
cached.through === projectionThrough &&
|
|
4891
|
+
cached.runId === runId &&
|
|
4892
|
+
cached.contextRecordId === priorContext?.recordId
|
|
4893
|
+
? (boundaries.push(...cached.boundaries),
|
|
4894
|
+
cached.contextEvidence.forEach(retainHistory),
|
|
4895
|
+
cached.journal)
|
|
4896
|
+
: yield* projectRunJournalStream(
|
|
4897
|
+
canonical,
|
|
4898
|
+
runId,
|
|
4899
|
+
(boundary) => boundaries.push(boundary),
|
|
4900
|
+
priorContext,
|
|
4901
|
+
journalMetadata,
|
|
4902
|
+
priorContext === undefined ? retainHistory : undefined,
|
|
4903
|
+
);
|
|
4876
4904
|
|
|
4877
4905
|
if (initialJournal?.prefix !== undefined) {
|
|
4878
4906
|
const prompt = initialJournal.prefix.prompt;
|
|
@@ -5192,9 +5220,6 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
5192
5220
|
),
|
|
5193
5221
|
);
|
|
5194
5222
|
|
|
5195
|
-
const addUsageTotal = (field: string, left: number, right: number) =>
|
|
5196
|
-
checkedUsageTotal(field, left + right);
|
|
5197
|
-
|
|
5198
5223
|
const subtractUsageTotal = (field: string, left: number, right: number) =>
|
|
5199
5224
|
checkedUsageTotal(field, left - right);
|
|
5200
5225
|
|
|
@@ -5204,11 +5229,7 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
5204
5229
|
let unobservedModelCalls = journal.usage.unobservedModelCalls ?? 0;
|
|
5205
5230
|
|
|
5206
5231
|
for (const count of stagedUnobservedCalls.values()) {
|
|
5207
|
-
unobservedModelCalls
|
|
5208
|
-
"unobservedModelCalls",
|
|
5209
|
-
unobservedModelCalls,
|
|
5210
|
-
count,
|
|
5211
|
-
);
|
|
5232
|
+
unobservedModelCalls += count;
|
|
5212
5233
|
}
|
|
5213
5234
|
const detailedCalls = [...journal.usage.modelUsage, ...stagedCalls];
|
|
5214
5235
|
|
|
@@ -5229,17 +5250,15 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
5229
5250
|
let costMicrousd = journal.usage.costMicrousd;
|
|
5230
5251
|
|
|
5231
5252
|
for (const usage of stagedUsage.values()) {
|
|
5232
|
-
inputTokens
|
|
5233
|
-
outputTokens
|
|
5234
|
-
costMicrousd
|
|
5253
|
+
inputTokens += usage.inputTokens;
|
|
5254
|
+
outputTokens += usage.outputTokens;
|
|
5255
|
+
costMicrousd += usage.costMicrousd;
|
|
5235
5256
|
}
|
|
5236
5257
|
|
|
5237
|
-
const modelCalls =
|
|
5238
|
-
"modelCalls",
|
|
5239
|
-
journal.usage.modelCalls,
|
|
5240
|
-
stagedCalls.length,
|
|
5241
|
-
);
|
|
5258
|
+
const modelCalls = journal.usage.modelCalls + stagedCalls.length;
|
|
5242
5259
|
|
|
5260
|
+
// Reconciliation must reject negative legacy deltas independently of
|
|
5261
|
+
// the final summary's complete safe-integer and additive checks.
|
|
5243
5262
|
const legacyCalls = yield* subtractUsageTotal(
|
|
5244
5263
|
"legacy.modelCalls",
|
|
5245
5264
|
modelCalls,
|
|
@@ -5283,81 +5302,52 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
5283
5302
|
|
|
5284
5303
|
const existing = existingIndex < 0 ? undefined : byModel[existingIndex];
|
|
5285
5304
|
|
|
5286
|
-
const legacyGroup = ModelUsageGroup.
|
|
5305
|
+
const legacyGroup = yield* ModelUsageGroup.makeEffect({
|
|
5287
5306
|
provider: "unknown",
|
|
5288
5307
|
model: "legacy-record",
|
|
5289
|
-
modelCalls:
|
|
5290
|
-
|
|
5291
|
-
existing?.
|
|
5292
|
-
|
|
5293
|
-
),
|
|
5294
|
-
inputTokens: InputTokenUsage.make({
|
|
5295
|
-
total: yield* addUsageTotal(
|
|
5296
|
-
"byModel.inputTokens.total",
|
|
5297
|
-
existing?.inputTokens.total ?? 0,
|
|
5298
|
-
legacyInput,
|
|
5299
|
-
),
|
|
5300
|
-
uncached: yield* addUsageTotal(
|
|
5301
|
-
"byModel.inputTokens.uncached",
|
|
5302
|
-
existing?.inputTokens.uncached ?? 0,
|
|
5303
|
-
legacyInput,
|
|
5304
|
-
),
|
|
5308
|
+
modelCalls: (existing?.modelCalls ?? 0) + legacyCalls,
|
|
5309
|
+
inputTokens: {
|
|
5310
|
+
total: (existing?.inputTokens.total ?? 0) + legacyInput,
|
|
5311
|
+
uncached: (existing?.inputTokens.uncached ?? 0) + legacyInput,
|
|
5305
5312
|
cacheRead: existing?.inputTokens.cacheRead ?? 0,
|
|
5306
5313
|
cacheWrite: existing?.inputTokens.cacheWrite ?? 0,
|
|
5307
|
-
}
|
|
5308
|
-
outputTokens:
|
|
5309
|
-
total:
|
|
5310
|
-
|
|
5311
|
-
existing?.outputTokens.total ?? 0,
|
|
5312
|
-
legacyOutput,
|
|
5313
|
-
),
|
|
5314
|
-
text: yield* addUsageTotal(
|
|
5315
|
-
"byModel.outputTokens.text",
|
|
5316
|
-
existing?.outputTokens.text ?? 0,
|
|
5317
|
-
legacyOutput,
|
|
5318
|
-
),
|
|
5314
|
+
},
|
|
5315
|
+
outputTokens: {
|
|
5316
|
+
total: (existing?.outputTokens.total ?? 0) + legacyOutput,
|
|
5317
|
+
text: (existing?.outputTokens.text ?? 0) + legacyOutput,
|
|
5319
5318
|
reasoning: existing?.outputTokens.reasoning ?? 0,
|
|
5320
|
-
}
|
|
5321
|
-
costMicrousd:
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5319
|
+
},
|
|
5320
|
+
costMicrousd: (existing?.costMicrousd ?? 0) + legacyCost,
|
|
5321
|
+
}).pipe(
|
|
5322
|
+
Effect.mapError((cause) =>
|
|
5323
|
+
RunJournalError.make({
|
|
5324
|
+
message: "Run legacy usage exceeds safe-integer accounting bounds",
|
|
5325
|
+
cause,
|
|
5326
|
+
}),
|
|
5325
5327
|
),
|
|
5326
|
-
|
|
5328
|
+
);
|
|
5327
5329
|
|
|
5328
5330
|
if (existingIndex < 0) byModel.push(legacyGroup);
|
|
5329
5331
|
else byModel[existingIndex] = legacyGroup;
|
|
5330
5332
|
}
|
|
5331
5333
|
|
|
5332
|
-
|
|
5333
|
-
"inputTokens.uncached",
|
|
5334
|
-
detailed.inputTokens.uncached,
|
|
5335
|
-
legacyInput,
|
|
5336
|
-
);
|
|
5337
|
-
|
|
5338
|
-
const text = yield* addUsageTotal(
|
|
5339
|
-
"outputTokens.text",
|
|
5340
|
-
detailed.outputTokens.text,
|
|
5341
|
-
legacyOutput,
|
|
5342
|
-
);
|
|
5343
|
-
|
|
5344
|
-
return RunUsageSummary.make({
|
|
5334
|
+
return yield* RunUsageSummary.makeEffect({
|
|
5345
5335
|
...(legacyCalls === 0 && detailed.webSearchCalls !== undefined
|
|
5346
5336
|
? { webSearchCalls: detailed.webSearchCalls }
|
|
5347
5337
|
: {}),
|
|
5348
5338
|
modelCalls,
|
|
5349
|
-
inputTokens:
|
|
5339
|
+
inputTokens: {
|
|
5350
5340
|
total: inputTokens,
|
|
5351
5341
|
// Legacy aggregate inputs are conservatively classified as uncached.
|
|
5352
|
-
uncached,
|
|
5342
|
+
uncached: detailed.inputTokens.uncached + legacyInput,
|
|
5353
5343
|
cacheRead: detailed.inputTokens.cacheRead,
|
|
5354
5344
|
cacheWrite: detailed.inputTokens.cacheWrite,
|
|
5355
|
-
}
|
|
5356
|
-
outputTokens:
|
|
5345
|
+
},
|
|
5346
|
+
outputTokens: {
|
|
5357
5347
|
total: outputTokens,
|
|
5358
|
-
text,
|
|
5348
|
+
text: detailed.outputTokens.text + legacyOutput,
|
|
5359
5349
|
reasoning: detailed.outputTokens.reasoning,
|
|
5360
|
-
}
|
|
5350
|
+
},
|
|
5361
5351
|
costMicrousd,
|
|
5362
5352
|
byModel,
|
|
5363
5353
|
unobservedModelCalls,
|
|
@@ -5373,7 +5363,14 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
5373
5363
|
? "unknown"
|
|
5374
5364
|
: "partial"
|
|
5375
5365
|
: detailed.pricingStatus,
|
|
5376
|
-
})
|
|
5366
|
+
}).pipe(
|
|
5367
|
+
Effect.mapError((cause) =>
|
|
5368
|
+
RunJournalError.make({
|
|
5369
|
+
message: "Run usage summary exceeds safe-integer accounting bounds",
|
|
5370
|
+
cause,
|
|
5371
|
+
}),
|
|
5372
|
+
),
|
|
5373
|
+
);
|
|
5377
5374
|
});
|
|
5378
5375
|
|
|
5379
5376
|
const activeExecution = yield* reader.readExecution({ threadId: ctx.threadId, runId });
|
|
@@ -5549,37 +5546,38 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
5549
5546
|
const recordHalt = <A, R>(
|
|
5550
5547
|
effect: Effect.Effect<A, DurableWorkerFailure, R>,
|
|
5551
5548
|
): Effect.Effect<A, CoordinatorHalt | AgentPersistenceCapacityError, R> =>
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
Cause.map(cause, (failure) =>
|
|
5562
|
-
failure instanceof ThreadStoreError &&
|
|
5563
|
-
failure.cause instanceof AgentPersistenceCapacityError
|
|
5564
|
-
? failure.cause
|
|
5565
|
-
: new CoordinatorHalt(failure),
|
|
5566
|
-
),
|
|
5549
|
+
Effect.catchCause(effect, (cause) => {
|
|
5550
|
+
const first = Cause.findErrorOption(cause);
|
|
5551
|
+
|
|
5552
|
+
const failure = Effect.failCause(
|
|
5553
|
+
Cause.map(cause, (error) =>
|
|
5554
|
+
error instanceof ThreadStoreError &&
|
|
5555
|
+
error.cause instanceof AgentPersistenceCapacityError
|
|
5556
|
+
? error.cause
|
|
5557
|
+
: new CoordinatorHalt(error),
|
|
5567
5558
|
),
|
|
5568
|
-
)
|
|
5569
|
-
|
|
5559
|
+
);
|
|
5560
|
+
|
|
5561
|
+
return Option.isNone(first) ||
|
|
5562
|
+
(first.value instanceof ThreadStoreError &&
|
|
5563
|
+
first.value.cause instanceof AgentPersistenceCapacityError)
|
|
5564
|
+
? failure
|
|
5565
|
+
: Effect.andThen(Ref.set(haltRef, first.value), failure);
|
|
5566
|
+
});
|
|
5570
5567
|
|
|
5571
5568
|
// Infrastructure errors can be wrapped by broker/Tool APIs. The interpreter checks this
|
|
5572
5569
|
// authority before semantic work; progress delivery is not a coordinator checkpoint.
|
|
5573
|
-
const
|
|
5574
|
-
Effect.gen(function* () {
|
|
5575
|
-
const failure = yield* Ref.get(haltRef);
|
|
5570
|
+
const progress = progressWriters.get(ctx);
|
|
5576
5571
|
|
|
5577
|
-
|
|
5578
|
-
|
|
5572
|
+
const checkProgress =
|
|
5573
|
+
progress === undefined
|
|
5574
|
+
? Effect.void
|
|
5575
|
+
: progress.check(runId).pipe(Effect.provideService(CurrentRunWriter, ctx));
|
|
5579
5576
|
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5577
|
+
const checkpoint = recordHalt(
|
|
5578
|
+
Effect.flatMap(Ref.get(haltRef), (failure) =>
|
|
5579
|
+
failure === undefined ? checkProgress : Effect.fail(failure),
|
|
5580
|
+
),
|
|
5583
5581
|
);
|
|
5584
5582
|
|
|
5585
5583
|
// One readonly Turn may own its response without publishing it. Promotion and settlement
|
|
@@ -7834,35 +7832,39 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
7834
7832
|
stagedUnobservedCalls.set(turn, (stagedUnobservedCalls.get(turn) ?? 0) + 1);
|
|
7835
7833
|
}),
|
|
7836
7834
|
}),
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7835
|
+
(body) =>
|
|
7836
|
+
body.pipe(
|
|
7837
|
+
Effect.provideServiceEffect(ThreadHistory, ThreadHistory.makeFromStore),
|
|
7838
|
+
Effect.provideServiceEffect(ConversationStore, makeMemoryStore),
|
|
7839
|
+
Effect.scoped,
|
|
7840
|
+
),
|
|
7841
|
+
Effect.provideContext(
|
|
7842
|
+
runServices.pipe(
|
|
7843
|
+
Context.add(SubagentHost.forTool, (source) =>
|
|
7844
|
+
source.threadId !== submission.threadId ||
|
|
7845
|
+
source.agentId !== submission.agentId ||
|
|
7846
|
+
source.runId !== runId
|
|
7847
|
+
? SubagentHost.unavailable
|
|
7848
|
+
: workerRuntime.facet(
|
|
7849
|
+
{
|
|
7850
|
+
source,
|
|
7851
|
+
policy: agent.definition.policy,
|
|
7852
|
+
depth: delegationDepth,
|
|
7853
|
+
...(inheritedGrant === undefined ? {} : { grant: inheritedGrant }),
|
|
7854
|
+
},
|
|
7855
|
+
submission.principal,
|
|
7856
|
+
submission.submissionId,
|
|
7857
|
+
),
|
|
7858
|
+
),
|
|
7859
|
+
Context.add(MessagingHost.forTool, (source) =>
|
|
7860
|
+
source.threadId !== submission.threadId ||
|
|
7861
|
+
source.agentId !== submission.agentId ||
|
|
7862
|
+
source.runId !== runId
|
|
7863
|
+
? MessagingHost.unavailable
|
|
7864
|
+
: messagingRuntime.forTool(source, submission.principal),
|
|
7865
|
+
),
|
|
7866
|
+
),
|
|
7860
7867
|
),
|
|
7861
|
-
Effect.provideService(CurrentToolFailureObserver, toolFailureObserver),
|
|
7862
|
-
Effect.provideService(RunToolVisibility, runToolVisibility),
|
|
7863
|
-
Effect.provideService(RunToolScheduling, runToolScheduling),
|
|
7864
|
-
Effect.provideService(ContextCompactor, compactor),
|
|
7865
|
-
Effect.provideService(RunContextPreparation, runContextPreparation),
|
|
7866
7868
|
Effect.andThen(checkpoint),
|
|
7867
7869
|
// A wrapped Tool/approval failure cannot outrank retained infrastructure authority.
|
|
7868
7870
|
// Preserve independent defects, interruptions and already-marked coordinator failures.
|
|
@@ -7909,21 +7911,20 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
7909
7911
|
}),
|
|
7910
7912
|
);
|
|
7911
7913
|
|
|
7912
|
-
const
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
yieldAfter === undefined && submissionScheduling.yieldTo === undefined
|
|
7916
|
-
?
|
|
7917
|
-
:
|
|
7918
|
-
execution,
|
|
7914
|
+
const raced = Effect.raceAllFirst([
|
|
7915
|
+
consume,
|
|
7916
|
+
abortWatcher,
|
|
7917
|
+
...(yieldAfter === undefined && submissionScheduling.yieldTo === undefined
|
|
7918
|
+
? []
|
|
7919
|
+
: [
|
|
7919
7920
|
Deferred.await(yieldSignal).pipe(
|
|
7920
7921
|
Effect.map((nextSubmissionId) => ({
|
|
7921
7922
|
_tag: "yielded" as const,
|
|
7922
7923
|
...(nextSubmissionId === undefined ? {} : { nextSubmissionId }),
|
|
7923
7924
|
})),
|
|
7924
7925
|
),
|
|
7925
|
-
)
|
|
7926
|
-
).pipe(Effect.provideService(IdGenerator, idGenerator));
|
|
7926
|
+
]),
|
|
7927
|
+
]).pipe(Effect.provideService(IdGenerator, idGenerator));
|
|
7927
7928
|
|
|
7928
7929
|
const result = yield* raced.pipe(
|
|
7929
7930
|
Effect.catchCauseFilter(
|
|
@@ -8149,17 +8150,14 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
8149
8150
|
resumeAfterRetention: () => void,
|
|
8150
8151
|
onHandoff: (nextSubmissionId: SubmissionId) => void,
|
|
8151
8152
|
yieldAfter?: DateTime.Utc,
|
|
8153
|
+
freshlyAdmitted = false,
|
|
8152
8154
|
) {
|
|
8153
8155
|
// Recheck ownership outside the disposable cache's failure recovery.
|
|
8154
8156
|
yield* session.checkActive;
|
|
8155
8157
|
|
|
8156
8158
|
const checkpointPrompt = yield* promptHistory
|
|
8157
8159
|
.take({ threadId: session.threadId })
|
|
8158
|
-
.pipe(
|
|
8159
|
-
Effect.provideService(ThreadStore, store),
|
|
8160
|
-
Effect.provideService(ThreadReader, reader),
|
|
8161
|
-
Effect.provideService(Crypto.Crypto, crypto),
|
|
8162
|
-
);
|
|
8160
|
+
.pipe(Effect.provideService(ThreadStore, store), Effect.provideContext(journalServices));
|
|
8163
8161
|
|
|
8164
8162
|
// withProgressSession exposes only progress.commit/publish. Their prepare step owns and
|
|
8165
8163
|
// freezes each canonical fact before reaching this raw writer. Snapshot the private array
|
|
@@ -8173,7 +8171,8 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
8173
8171
|
committedPromptSuffix = undefined;
|
|
8174
8172
|
}),
|
|
8175
8173
|
);
|
|
8176
|
-
|
|
8174
|
+
|
|
8175
|
+
const promptSession: RunStorageSession = {
|
|
8177
8176
|
...storageSession,
|
|
8178
8177
|
append: (batch, executions) => {
|
|
8179
8178
|
const suffix = committedPromptSuffix;
|
|
@@ -8208,17 +8207,117 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
8208
8207
|
Effect.tapCause(() => Effect.sync(() => suffix.discard())),
|
|
8209
8208
|
);
|
|
8210
8209
|
},
|
|
8211
|
-
}
|
|
8210
|
+
};
|
|
8211
|
+
|
|
8212
|
+
session = yield* withProgressSession(promptSession);
|
|
8212
8213
|
const { claim, threadId } = session;
|
|
8213
8214
|
const submissionId = claim.submissionId;
|
|
8214
8215
|
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8216
|
+
// The hint only selects this preparation. A real claim, current controls, exact
|
|
8217
|
+
// evidence and checkpoint absence are verified under its owner before any reuse.
|
|
8218
|
+
// No binding, instructions, model, Tool or cross-Thread operation runs in the window.
|
|
8219
|
+
let prepared =
|
|
8220
|
+
freshlyAdmitted && session.withInitialization !== undefined
|
|
8221
|
+
? yield* session.withInitialization(
|
|
8222
|
+
Effect.gen(function* () {
|
|
8223
|
+
const snapshot = yield* ledger.loadRecoverySnapshot(
|
|
8224
|
+
RecoverySnapshotRequest.make({ submissionId }),
|
|
8225
|
+
);
|
|
8226
|
+
|
|
8227
|
+
const submission = snapshot.submission;
|
|
8228
|
+
|
|
8229
|
+
if (
|
|
8230
|
+
submission.state !== "ready" ||
|
|
8231
|
+
submission.workerAdmission !== undefined ||
|
|
8232
|
+
submission.messageAdmission !== undefined ||
|
|
8233
|
+
submission.parentLinkage !== undefined ||
|
|
8234
|
+
snapshot.inputApplied !== undefined ||
|
|
8235
|
+
snapshot.abortIntent !== undefined ||
|
|
8236
|
+
snapshot.approvalDecisions.length !== 0
|
|
8237
|
+
)
|
|
8238
|
+
return undefined;
|
|
8239
|
+
yield* ensureThreadCreated(threadId, submission.agentId, submission.agentDigests);
|
|
8240
|
+
yield* session.refresh;
|
|
8241
|
+
const before = (yield* session.tail).sequence;
|
|
8242
|
+
|
|
8243
|
+
const view = yield* recoveryView(
|
|
8244
|
+
threadId,
|
|
8245
|
+
before,
|
|
8246
|
+
[submissionId],
|
|
8247
|
+
runIdForSubmission(submissionId),
|
|
8248
|
+
);
|
|
8249
|
+
|
|
8250
|
+
if (
|
|
8251
|
+
view.progress !== undefined ||
|
|
8252
|
+
view.context !== undefined ||
|
|
8253
|
+
view.operational.length !== 0 ||
|
|
8254
|
+
view.records.some(({ record }) => record.payload._tag !== "ThreadCreated")
|
|
8255
|
+
)
|
|
8256
|
+
return undefined;
|
|
8257
|
+
const progress = progressWriters.get(session);
|
|
8258
|
+
|
|
8259
|
+
const applyInput = applyCanonicalInput(
|
|
8260
|
+
session,
|
|
8261
|
+
submission,
|
|
8262
|
+
session,
|
|
8263
|
+
view.records,
|
|
8264
|
+
undefined,
|
|
8265
|
+
);
|
|
8266
|
+
|
|
8267
|
+
yield* progress === undefined
|
|
8268
|
+
? applyInput
|
|
8269
|
+
: progress
|
|
8270
|
+
.withVerifiedEmptyRun(runIdForSubmission(submissionId), before, applyInput)
|
|
8271
|
+
.pipe(Effect.provideService(CurrentRunWriter, promptSession));
|
|
8272
|
+
const through = (yield* session.tail).sequence;
|
|
8273
|
+
const added = yield* selectedRange(threadId, [submissionId], through, before);
|
|
8274
|
+
const records = [...view.records, ...added];
|
|
8275
|
+
|
|
8276
|
+
const accepted = progressWriters
|
|
8277
|
+
.get(session)
|
|
8278
|
+
?.acceptedCheckpoint(runIdForSubmission(submissionId));
|
|
8279
|
+
|
|
8280
|
+
if (
|
|
8281
|
+
accepted === undefined ||
|
|
8282
|
+
accepted.throughSequence !== through ||
|
|
8283
|
+
accepted.progress.runId !== runIdForSubmission(submissionId) ||
|
|
8284
|
+
accepted.progress.submissionId !== submissionId
|
|
8285
|
+
)
|
|
8286
|
+
return undefined;
|
|
8287
|
+
|
|
8288
|
+
const start = yield* makeRunStart(
|
|
8289
|
+
submission,
|
|
8290
|
+
Duration.toMillis(registeredAgent.definition.policy.maxDuration),
|
|
8291
|
+
records,
|
|
8292
|
+
view.operational,
|
|
8293
|
+
).pipe(Effect.provideService(CurrentRunWriter, session));
|
|
8294
|
+
|
|
8295
|
+
return {
|
|
8296
|
+
snapshot,
|
|
8297
|
+
through,
|
|
8298
|
+
view: {
|
|
8299
|
+
...view,
|
|
8300
|
+
records,
|
|
8301
|
+
progress: accepted.progress,
|
|
8302
|
+
progressThrough: accepted.throughSequence,
|
|
8303
|
+
operational: accepted.operational,
|
|
8304
|
+
},
|
|
8305
|
+
start,
|
|
8306
|
+
};
|
|
8307
|
+
}),
|
|
8308
|
+
)
|
|
8309
|
+
: undefined;
|
|
8310
|
+
|
|
8311
|
+
const preparedInput = prepared !== undefined;
|
|
8312
|
+
|
|
8313
|
+
const snapshot =
|
|
8314
|
+
prepared?.snapshot ??
|
|
8315
|
+
(yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId })));
|
|
8218
8316
|
|
|
8219
8317
|
const submission = snapshot.submission;
|
|
8220
8318
|
|
|
8221
|
-
|
|
8319
|
+
if (prepared === undefined)
|
|
8320
|
+
yield* ensureThreadCreated(threadId, submission.agentId, submission.agentDigests);
|
|
8222
8321
|
if (submission.workerAdmission?.origin.reporting?.mode === "standard")
|
|
8223
8322
|
yield* updateRuntime.repairRun(threadId, submissionId);
|
|
8224
8323
|
if (submission.workerAdmission !== undefined) {
|
|
@@ -8233,18 +8332,20 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
8233
8332
|
if (submission.state === "admitted") {
|
|
8234
8333
|
yield* ledger.markReady(MarkReadyRequest.make({ submissionId }));
|
|
8235
8334
|
}
|
|
8236
|
-
yield* session.refresh;
|
|
8335
|
+
if (prepared === undefined) yield* session.refresh;
|
|
8237
8336
|
const ctx: AttemptAppendContext = session;
|
|
8238
|
-
let controlThrough = (yield* session.tail).sequence;
|
|
8337
|
+
let controlThrough = prepared?.through ?? (yield* session.tail).sequence;
|
|
8239
8338
|
|
|
8240
8339
|
const initialThrough = controlThrough;
|
|
8241
8340
|
|
|
8242
|
-
const initialView =
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8341
|
+
const initialView =
|
|
8342
|
+
prepared?.view ??
|
|
8343
|
+
(yield* recoveryView(
|
|
8344
|
+
threadId,
|
|
8345
|
+
initialThrough,
|
|
8346
|
+
[submissionId],
|
|
8347
|
+
runIdForSubmission(submissionId),
|
|
8348
|
+
));
|
|
8248
8349
|
|
|
8249
8350
|
let journalMetadata: ReturnType<typeof makeJournalMetadata> | undefined;
|
|
8250
8351
|
|
|
@@ -8367,15 +8468,17 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
8367
8468
|
),
|
|
8368
8469
|
);
|
|
8369
8470
|
}
|
|
8370
|
-
|
|
8471
|
+
if (prepared === undefined)
|
|
8472
|
+
yield* applyCanonicalInput(ctx, submission, session, records, snapshot.inputApplied);
|
|
8371
8473
|
|
|
8372
|
-
const start =
|
|
8373
|
-
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8474
|
+
const start =
|
|
8475
|
+
prepared?.start ??
|
|
8476
|
+
(yield* makeRunStart(
|
|
8477
|
+
submission,
|
|
8478
|
+
Duration.toMillis(agent.definition.policy.maxDuration),
|
|
8479
|
+
yield* refreshControl(),
|
|
8480
|
+
initialView.operational,
|
|
8481
|
+
).pipe(Effect.provideService(CurrentRunWriter, ctx)));
|
|
8379
8482
|
|
|
8380
8483
|
const savedRunTiming = start.timing;
|
|
8381
8484
|
|
|
@@ -8397,8 +8500,11 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
8397
8500
|
};
|
|
8398
8501
|
|
|
8399
8502
|
let expiredChildObligation = false;
|
|
8503
|
+
let preparedControl = prepared !== undefined;
|
|
8400
8504
|
|
|
8401
8505
|
if ((yield* Clock.currentTimeMillis) >= DateTime.toEpochMillis(runTiming.deadline)) {
|
|
8506
|
+
prepared = undefined;
|
|
8507
|
+
preparedControl = false;
|
|
8402
8508
|
yield* commitStart;
|
|
8403
8509
|
yield* reconcileRetainedChildren(ctx, submission, session);
|
|
8404
8510
|
expiredChildObligation = yield* completeJoinedReleases(submission);
|
|
@@ -8406,7 +8512,9 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
8406
8512
|
|
|
8407
8513
|
// Recheck after duration interruption too: that Attempt may have declared new ordinary calls.
|
|
8408
8514
|
const ordinaryCallsResolved = Effect.gen(function* () {
|
|
8409
|
-
const reconciliationRecords = yield* refreshControl();
|
|
8515
|
+
const reconciliationRecords = preparedControl ? records : yield* refreshControl();
|
|
8516
|
+
|
|
8517
|
+
preparedControl = false;
|
|
8410
8518
|
|
|
8411
8519
|
const reconciliationEvidence = yield* evidenceFor(
|
|
8412
8520
|
reconciliationRecords,
|
|
@@ -8456,7 +8564,7 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
8456
8564
|
if (!expiredChildObligation && !(yield* ordinaryCallsResolved))
|
|
8457
8565
|
return Option.none<Settlement>();
|
|
8458
8566
|
|
|
8459
|
-
const continuationRecords = yield* refreshControl();
|
|
8567
|
+
const continuationRecords = prepared === undefined ? yield* refreshControl() : records;
|
|
8460
8568
|
|
|
8461
8569
|
const continuation = yield* pendingToolBatchFor(
|
|
8462
8570
|
continuationRecords,
|
|
@@ -8596,24 +8704,30 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
8596
8704
|
|
|
8597
8705
|
const lineage: AttemptLineage = {
|
|
8598
8706
|
attemptId: claim.attemptId,
|
|
8599
|
-
inputWasRecorded: evidence.inputRecorded,
|
|
8707
|
+
inputWasRecorded: !preparedInput && evidence.inputRecorded,
|
|
8600
8708
|
};
|
|
8601
8709
|
|
|
8602
8710
|
let approvalDecisionIntents = snapshot.approvalDecisions;
|
|
8603
8711
|
|
|
8604
8712
|
while (true) {
|
|
8605
|
-
|
|
8713
|
+
const initialization = prepared;
|
|
8714
|
+
|
|
8715
|
+
prepared = undefined;
|
|
8716
|
+
if (initialization === undefined) yield* session.refresh;
|
|
8606
8717
|
const tail = yield* session.tail;
|
|
8607
8718
|
|
|
8608
|
-
const currentRecords =
|
|
8719
|
+
const currentRecords =
|
|
8720
|
+
initialization === undefined ? yield* refreshControl(tail.sequence) : records;
|
|
8609
8721
|
|
|
8610
|
-
const view =
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8722
|
+
const view =
|
|
8723
|
+
initialization?.view ??
|
|
8724
|
+
(yield* recoveryView(
|
|
8725
|
+
threadId,
|
|
8726
|
+
tail.sequence,
|
|
8727
|
+
[submissionId],
|
|
8728
|
+
runIdForSubmission(submissionId),
|
|
8729
|
+
currentRecords,
|
|
8730
|
+
));
|
|
8617
8731
|
|
|
8618
8732
|
let canonical: Stream.Stream<
|
|
8619
8733
|
JournalRecordEnvelope,
|
|
@@ -8933,6 +9047,9 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
8933
9047
|
const session = claimed.value;
|
|
8934
9048
|
const { claim } = session;
|
|
8935
9049
|
|
|
9050
|
+
const freshlyAdmitted = unclaimedAdmissions.get(claim.submissionId) === threadId;
|
|
9051
|
+
|
|
9052
|
+
unclaimedAdmissions.delete(claim.submissionId);
|
|
8936
9053
|
firstClaimedSubmissionId ??= claim.submissionId;
|
|
8937
9054
|
|
|
8938
9055
|
const attributes = {
|
|
@@ -9017,6 +9134,7 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
9017
9134
|
});
|
|
9018
9135
|
},
|
|
9019
9136
|
options?.yieldAfter,
|
|
9137
|
+
freshlyAdmitted,
|
|
9020
9138
|
),
|
|
9021
9139
|
threadId,
|
|
9022
9140
|
claim,
|
|
@@ -10395,6 +10513,7 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
10395
10513
|
const recoverOwnedWork = Effect.fnUntraced(function* (
|
|
10396
10514
|
request: WorkRecoveryRequest,
|
|
10397
10515
|
recoveredAdmissions = new Map<SubmissionId, RecoveryReport>(),
|
|
10516
|
+
deferUnclaimedAdmissions = false,
|
|
10398
10517
|
): Effect.fn.Return<WorkRecoveryReport, DurableWorkerFailure> {
|
|
10399
10518
|
const { threadId, work: entry } = yield* Schema.decodeEffect(WorkRecoveryRequest)(request).pipe(
|
|
10400
10519
|
Effect.mapError((cause) =>
|
|
@@ -10448,6 +10567,21 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
10448
10567
|
const original = yield* lookupKnownSubmission("recover work", owner.submissionId);
|
|
10449
10568
|
|
|
10450
10569
|
if (original.threadId !== threadId) return yield* invalid();
|
|
10570
|
+
if (
|
|
10571
|
+
deferUnclaimedAdmissions &&
|
|
10572
|
+
unclaimedAdmissions.get(owner.submissionId) === threadId &&
|
|
10573
|
+
original.state === "ready" &&
|
|
10574
|
+
!storageOwner.hasOwner(threadId) &&
|
|
10575
|
+
(yield* ledger.readAbortIntent(
|
|
10576
|
+
AbortIntentRequest.make({ submissionId: owner.submissionId }),
|
|
10577
|
+
)) === undefined
|
|
10578
|
+
) {
|
|
10579
|
+
// The worker's first scoped claim performs the authoritative control/journal
|
|
10580
|
+
// read. This hint skips only a redundant pre-claim recovery traversal; it grants
|
|
10581
|
+
// no claim, synthesizes no decision, and supplies no model-visible facts.
|
|
10582
|
+
return report("deferred");
|
|
10583
|
+
}
|
|
10584
|
+
unclaimedAdmissions.delete(owner.submissionId);
|
|
10451
10585
|
const submission = yield* recoverAdmission(owner.submissionId);
|
|
10452
10586
|
|
|
10453
10587
|
return report(submission.disposition, submission);
|
|
@@ -10926,6 +11060,29 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
10926
11060
|
|
|
10927
11061
|
const outcome = yield* isolateRecovery(
|
|
10928
11062
|
Effect.gen(function* () {
|
|
11063
|
+
// This incarnation admitted the sole untouched root. The native snapshot proves
|
|
11064
|
+
// there is no old owner to repair; claim and live controls still run normally.
|
|
11065
|
+
// New source mutations retain their dirty generation for the next maintenance scan.
|
|
11066
|
+
if (
|
|
11067
|
+
workCursor === undefined &&
|
|
11068
|
+
options?.deferUnclaimedAdmissions === true &&
|
|
11069
|
+
workDiscovery.isOnlyFreshAdmission !== undefined &&
|
|
11070
|
+
!storageOwner.hasOwner(threadId)
|
|
11071
|
+
) {
|
|
11072
|
+
const fresh = [...unclaimedAdmissions].find(([, owner]) => owner === threadId);
|
|
11073
|
+
|
|
11074
|
+
if (
|
|
11075
|
+
fresh !== undefined &&
|
|
11076
|
+
(yield* workDiscovery.isOnlyFreshAdmission({
|
|
11077
|
+
threadId,
|
|
11078
|
+
submissionId: fresh[0],
|
|
11079
|
+
}))
|
|
11080
|
+
) {
|
|
11081
|
+
complete = true;
|
|
11082
|
+
|
|
11083
|
+
return;
|
|
11084
|
+
}
|
|
11085
|
+
}
|
|
10929
11086
|
for (
|
|
10930
11087
|
let pages = 0;
|
|
10931
11088
|
pages < MAX_RECOVERY_PAGES && workReports.length < MAX_RECOVERY_WORK_ITEMS;
|
|
@@ -10941,7 +11098,11 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
10941
11098
|
|
|
10942
11099
|
phase = "recovery";
|
|
10943
11100
|
for (const work of workPage.entries) {
|
|
10944
|
-
const repaired = yield* recoverOwnedWork(
|
|
11101
|
+
const repaired = yield* recoverOwnedWork(
|
|
11102
|
+
{ threadId, work },
|
|
11103
|
+
recoveredAdmissions,
|
|
11104
|
+
options?.deferUnclaimedAdmissions === true,
|
|
11105
|
+
);
|
|
10945
11106
|
|
|
10946
11107
|
workReports.push(repaired);
|
|
10947
11108
|
if (
|
|
@@ -11165,7 +11326,7 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
11165
11326
|
queueSequence: admitted.queueSequence,
|
|
11166
11327
|
});
|
|
11167
11328
|
}
|
|
11168
|
-
const admitted = yield* ledger.admit(request);
|
|
11329
|
+
const admitted = yield* ledger.admit(request, { readyIfInitialized: true });
|
|
11169
11330
|
|
|
11170
11331
|
yield* hit("submit:after-admit");
|
|
11171
11332
|
|
|
@@ -11181,10 +11342,24 @@ const make = Effect.fnUntraced(function* (bindings: ReadonlyArray<ResolvedBindin
|
|
|
11181
11342
|
if (admitted.replayed && admitted.state !== "admitted") {
|
|
11182
11343
|
return receipt;
|
|
11183
11344
|
}
|
|
11184
|
-
|
|
11185
|
-
|
|
11186
|
-
|
|
11187
|
-
|
|
11345
|
+
if (admitted.state === "admitted") {
|
|
11346
|
+
yield* materializeThread(options.threadId);
|
|
11347
|
+
yield* ensureThreadCreated(options.threadId, agent.definition.id, options.definitions);
|
|
11348
|
+
yield* hit("submit:after-materialize");
|
|
11349
|
+
yield* ledger.markReady(MarkReadyRequest.make({ submissionId: admitted.submissionId }));
|
|
11350
|
+
}
|
|
11351
|
+
if (
|
|
11352
|
+
!admitted.replayed &&
|
|
11353
|
+
messageAdmission === undefined &&
|
|
11354
|
+
options.workerAdmission === undefined
|
|
11355
|
+
) {
|
|
11356
|
+
unclaimedAdmissions.set(admitted.submissionId, options.threadId);
|
|
11357
|
+
if (unclaimedAdmissions.size > 128) {
|
|
11358
|
+
const oldest = unclaimedAdmissions.keys().next().value;
|
|
11359
|
+
|
|
11360
|
+
if (oldest !== undefined) unclaimedAdmissions.delete(oldest);
|
|
11361
|
+
}
|
|
11362
|
+
}
|
|
11188
11363
|
yield* wake.notify(options.threadId);
|
|
11189
11364
|
|
|
11190
11365
|
return receipt;
|