effect-agent 0.1.0-beta.100 → 0.1.0-beta.101

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.
Files changed (116) hide show
  1. package/dist/{DurableAgentRuntime-BE_OjQjz.mjs → DurableAgentRuntime-HOZ3AeSi.mjs} +166 -101
  2. package/dist/DurableAgentRuntime-HOZ3AeSi.mjs.map +1 -0
  3. package/dist/{EventSource-EKNxvkLe.d.mts → EventSource-K7XUzurY.d.mts} +3 -3
  4. package/dist/{PreparedInputAdmission-D0yepgfa.d.mts → PreparedInputAdmission-KLk5rGFI.d.mts} +4 -4
  5. package/dist/{Records-Uh_ktvNK.d.mts → Records-Bidb7ByL.d.mts} +173 -8
  6. package/dist/{Records-DR1xtbXY.mjs → Records-D8167fHn.mjs} +4 -2
  7. package/dist/{Records-DR1xtbXY.mjs.map → Records-D8167fHn.mjs.map} +1 -1
  8. package/dist/{RunJournal-DNs3PM4K.mjs → RunJournal-srpbEBEy.mjs} +25 -4
  9. package/dist/RunJournal-srpbEBEy.mjs.map +1 -0
  10. package/dist/{Schedule-CVNtnIpG.d.mts → Schedule-Cy9up8Uf.d.mts} +2 -2
  11. package/dist/{Scheduling-HFH0pST1.mjs → Scheduling-CHCsSCGo.mjs} +2 -2
  12. package/dist/{Scheduling-HFH0pST1.mjs.map → Scheduling-CHCsSCGo.mjs.map} +1 -1
  13. package/dist/{Subscription-D94jLq3n.d.mts → Subscription-CHyoQelH.d.mts} +3 -3
  14. package/dist/{SubscriptionInput-CfefvQng.d.mts → SubscriptionInput-DqrHW-Ja.d.mts} +3 -3
  15. package/dist/{agent-registration-cXpB8cBU.mjs → agent-registration-ByeHejH3.mjs} +2 -2
  16. package/dist/{agent-registration-cXpB8cBU.mjs.map → agent-registration-ByeHejH3.mjs.map} +1 -1
  17. package/dist/durable/ActivityStore.d.mts +1 -1
  18. package/dist/durable/ActivityStore.mjs +1 -1
  19. package/dist/durable/Admin.d.mts +1 -1
  20. package/dist/durable/Admin.mjs +1 -1
  21. package/dist/durable/AgentRegistration.d.mts +1 -1
  22. package/dist/durable/AgentRegistration.mjs +1 -1
  23. package/dist/durable/Certification.d.mts +1 -1
  24. package/dist/durable/CommittedActivity.d.mts +1 -1
  25. package/dist/durable/CommittedActivity.mjs +1 -1
  26. package/dist/durable/Digest.d.mts +1 -1
  27. package/dist/durable/Digest.mjs +1 -1
  28. package/dist/durable/DurableAgentRuntime.d.mts +1 -1
  29. package/dist/durable/DurableAgentRuntime.mjs +1 -1
  30. package/dist/durable/EventSource.d.mts +1 -1
  31. package/dist/durable/EventSource.mjs +1 -1
  32. package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
  33. package/dist/durable/GitHubWorkflowSource.mjs +1 -1
  34. package/dist/durable/MessageDelivery.d.mts +348 -8
  35. package/dist/durable/MessageDelivery.mjs +38 -4
  36. package/dist/durable/MessageDelivery.mjs.map +1 -1
  37. package/dist/durable/MessageDeliveryStoreConformance.d.mts +1 -1
  38. package/dist/durable/MessageDeliveryStoreConformance.mjs +31 -4
  39. package/dist/durable/MessageDeliveryStoreConformance.mjs.map +1 -1
  40. package/dist/durable/PersistentHistory.d.mts +1 -1
  41. package/dist/durable/PersistentHistory.mjs +2 -2
  42. package/dist/durable/PreparedInputAdmission.d.mts +1 -1
  43. package/dist/durable/Records.d.mts +1 -1
  44. package/dist/durable/Records.mjs +1 -1
  45. package/dist/durable/Recovery.d.mts +1 -1
  46. package/dist/durable/Recovery.mjs +1 -1
  47. package/dist/durable/RunJournal.d.mts +2 -2
  48. package/dist/durable/RunJournal.mjs +2 -2
  49. package/dist/durable/Schedule.d.mts +1 -1
  50. package/dist/durable/Schedule.mjs +1 -1
  51. package/dist/durable/ScheduleStoreConformance.d.mts +1 -1
  52. package/dist/durable/ScheduleStoreConformance.mjs +1 -1
  53. package/dist/durable/ScheduleTransition.d.mts +1 -1
  54. package/dist/durable/ScheduleTransition.mjs +1 -1
  55. package/dist/durable/Scheduling.d.mts +2 -2
  56. package/dist/durable/Scheduling.mjs +1 -1
  57. package/dist/durable/SqlMessageDeliveryStore.d.mts +3 -0
  58. package/dist/durable/SqlMessageDeliveryStore.mjs +6 -2
  59. package/dist/durable/SqlMessageDeliveryStore.mjs.map +1 -1
  60. package/dist/durable/SqlStorageV2Upgrade.d.mts +2 -2
  61. package/dist/durable/SqlStorageV2Upgrade.mjs +1 -1
  62. package/dist/durable/SqlSubscriptionStore.d.mts +2 -2
  63. package/dist/durable/SqlSubscriptionStore.mjs +1 -1
  64. package/dist/durable/SqlThreadNativeReads.d.mts +49 -0
  65. package/dist/durable/SqlThreadNativeReads.mjs +153 -0
  66. package/dist/durable/SqlThreadNativeReads.mjs.map +1 -0
  67. package/dist/durable/SubmissionLedger.d.mts +1 -1
  68. package/dist/durable/SubmissionLedger.mjs +1 -1
  69. package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
  70. package/dist/durable/SubmissionLedgerConformance.mjs +1 -1
  71. package/dist/durable/SubmissionStatus.d.mts +1 -1
  72. package/dist/durable/Subscription.d.mts +1 -1
  73. package/dist/durable/Subscription.mjs +1 -1
  74. package/dist/durable/SubscriptionInput.d.mts +1 -1
  75. package/dist/durable/SubscriptionInput.mjs +2 -2
  76. package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
  77. package/dist/durable/SubscriptionStoreConformance.mjs +1 -1
  78. package/dist/durable/SubscriptionTools.d.mts +3 -3
  79. package/dist/durable/SubscriptionTransition.d.mts +1 -1
  80. package/dist/durable/SubscriptionTransition.mjs +1 -1
  81. package/dist/durable/Subscriptions.d.mts +5 -5
  82. package/dist/durable/Subscriptions.mjs +1 -1
  83. package/dist/durable/ThreadContextHistory.d.mts +1 -1
  84. package/dist/durable/ThreadContextHistory.mjs +1 -1
  85. package/dist/durable/ThreadContextHistoryProjection.d.mts +1 -1
  86. package/dist/durable/ThreadContextHistoryProjection.mjs +1 -1
  87. package/dist/durable/ThreadInvariants.d.mts +1 -1
  88. package/dist/durable/ThreadInvariants.mjs +2 -2
  89. package/dist/durable/ThreadProjection.d.mts +1 -1
  90. package/dist/durable/ThreadProjection.mjs +1 -1
  91. package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
  92. package/dist/durable/ThreadStore.d.mts +2 -2
  93. package/dist/durable/ThreadStore.mjs +195 -6
  94. package/dist/durable/ThreadStore.mjs.map +1 -1
  95. package/dist/durable/ThreadStoreConformance.d.mts +1 -1
  96. package/dist/durable/ThreadStoreConformance.mjs +290 -35
  97. package/dist/durable/ThreadStoreConformance.mjs.map +1 -1
  98. package/dist/durable/ToolReconciler.mjs +1 -1
  99. package/dist/durable/WorkerHost.d.mts +1 -1
  100. package/dist/index.d.mts +8 -7
  101. package/dist/index.mjs +6 -5
  102. package/package.json +1 -1
  103. package/src/durable/DurableAgentRuntime.ts +10 -0
  104. package/src/durable/MessageDelivery.ts +56 -5
  105. package/src/durable/MessageDeliveryStoreConformance.ts +48 -1
  106. package/src/durable/Records.ts +2 -0
  107. package/src/durable/RunJournal.ts +27 -0
  108. package/src/durable/SqlMessageDeliveryStore.ts +8 -1
  109. package/src/durable/SqlThreadNativeReads.ts +256 -0
  110. package/src/durable/ThreadStore.ts +315 -5
  111. package/src/durable/ThreadStoreConformance.ts +447 -1
  112. package/src/durable/internal/messaging-host.ts +67 -29
  113. package/src/durable/internal/worker-host.ts +180 -58
  114. package/src/index.ts +2 -0
  115. package/dist/DurableAgentRuntime-BE_OjQjz.mjs.map +0 -1
  116. package/dist/RunJournal-DNs3PM4K.mjs.map +0 -1
@@ -20,20 +20,20 @@ import { getToolExecutionClass } from "./engine/DurableStep.mjs";
20
20
  import { CompactionError, ContextCompactor } from "./engine/ContextCompactor.mjs";
21
21
  import { RunPolicyUsage } from "./core/RunPolicyUsage.mjs";
22
22
  import { AgentUpdateAcceptance, CurrentToolFailureObserver, ModelUsageAccounting, RunContextPreparation, RunContextPreparationPassthrough, RunToolAuthorization, RunToolScheduling } from "./engine/RunOptions.mjs";
23
- import { $ as ToolCallSettled, B as SubagentJoined, E as ProducerEpoch, G as SubmissionSettledRecord, H as SubagentRequested, I as RunPolicyUsageReserved, J as ToolApprovalDecided, K as SubtreeBudgetReserved, L as RunStartedRecord, O as RecordEnvelope, P as RunDurationExhausted, Q as ToolCallResolved, R as SettlementFailureDiagnostic, T as PersistedJson, U as SubagentStarted, V as SubagentLineageRecorded, W as SubmissionSettled, X as ToolCallPrepared, Y as ToolApprovalRequested, at as WorkerAdmission, c as CanonicalRecordEnvelope, ct as WorkerOrigin, d as CompactionCreated, dt as WorkerReportRefused, et as ToolCallUnknown, ft as WorkerReportingIntent, h as Digest, i as BatchId, it as UserInputRecorded, j as RepairAnnotated, k as RecordId, lt as WorkerOriginRecorded, n as AgentUpdateEmitted, nt as ToolStepSettled, o as CanonicalBatch, ot as WorkerInputCompleted, p as DefinitionDigests, q as ThreadCreated, rt as ToolUnavailable, st as WorkerInputRequested, t as AbortRequested, tt as ToolOperation, u as CanonicalSequence, ut as WorkerReportPrepared, w as PeerMessagePrepared, x as ModelResponseInterrupted } from "./Records-DR1xtbXY.mjs";
23
+ import { $ as ToolCallSettled, B as SubagentJoined, E as ProducerEpoch, G as SubmissionSettledRecord, H as SubagentRequested, I as RunPolicyUsageReserved, J as ToolApprovalDecided, K as SubtreeBudgetReserved, L as RunStartedRecord, O as RecordEnvelope, P as RunDurationExhausted, Q as ToolCallResolved, R as SettlementFailureDiagnostic, T as PersistedJson, U as SubagentStarted, V as SubagentLineageRecorded, W as SubmissionSettled, X as ToolCallPrepared, Y as ToolApprovalRequested, at as WorkerAdmission, c as CanonicalRecordEnvelope, ct as WorkerOrigin, d as CompactionCreated, dt as WorkerReportRefused, et as ToolCallUnknown, ft as WorkerReportingIntent, h as Digest, i as BatchId, it as UserInputRecorded, j as RepairAnnotated, k as RecordId, lt as WorkerOriginRecorded, n as AgentUpdateEmitted, nt as ToolStepSettled, o as CanonicalBatch, ot as WorkerInputCompleted, p as DefinitionDigests, q as ThreadCreated, rt as ToolUnavailable, st as WorkerInputRequested, t as AbortRequested, tt as ToolOperation, u as CanonicalSequence, ut as WorkerReportPrepared, w as PeerMessagePrepared, x as ModelResponseInterrupted } from "./Records-D8167fHn.mjs";
24
24
  import { AbortCommand, AbortIntentRequest, AdmissionPolicyError, AdmissionRequest, ApprovalDecisionCommand, ApprovalPendingSuspension, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, ChildBudgetReservationRequest, ChildReservationId, ChildSettledNotification, ClaimJoiningRequest, ClaimRequest, LedgerError, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, OwnershipToken, ParentLinkage, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, RevertJoiningRequest, Settlement, SettlementFinalization, SettlementReservation, SubmissionLedger, SubmissionLookupById, SubmissionLookupByKey, SuspendRequest, UnknownResolutionCommand, WaitingChild, WaitingForChildSuspension, submissionAbortBatchId, submissionAbortRecordId, submissionInputBatchId, submissionInputRecordId, submissionSettlementBatchId, submissionSettlementId, submissionSettlementRecordId } from "./durable/SubmissionLedger.mjs";
25
25
  import { DeclaredPendingBatchEvidence, OpenDelegationCallEvidence, OpenToolCallEvidence, PendingApprovalEvidence, RecoveryDecision, RecoveryEvidence, classifyRecovery } from "./durable/Recovery.mjs";
26
26
  import { ExplainedEvidence, ExplainedSubmission, ExplainedUnknownCall, IntegrityCheck, IntegrityReport, ObligationEntry, ObligationReport, RecoveryExplanation, RetryRefused, obligationSeverityOf, predictRecoveryDisposition, recoveryDecisionMeaning } from "./durable/Admin.mjs";
27
27
  import { digestJson } from "./durable/Digest.mjs";
28
- import { a as definitionDigestsEqual, c as resolveWorkerBinding, i as compileRegistrations, l as toolReplayContracts, o as makeLegacyWorkerBinding, s as resolveDefinitionBinding, t as BindingUnavailable } from "./agent-registration-cXpB8cBU.mjs";
29
- import { FencedAppendRequest, LoadCheckpointRequest, SaveRecoveryCheckpointRequest, ThreadCheckpoint, ThreadExportRequest, ThreadMaterialization, ThreadObservation, ThreadRead, ThreadStore, ThreadStoreError, ThreadTailRequest } from "./durable/ThreadStore.mjs";
28
+ import { a as definitionDigestsEqual, c as resolveWorkerBinding, i as compileRegistrations, l as toolReplayContracts, o as makeLegacyWorkerBinding, s as resolveDefinitionBinding, t as BindingUnavailable } from "./agent-registration-ByeHejH3.mjs";
29
+ import { $ as workerOriginRecordId, A as subagentRequestedRecordId, B as toolCallUnknownRecordId, C as runStartedBatchId, D as subagentLineageBatchId, E as subagentJoinedRecordId, F as toolCallPreparedRecordId, G as turnCanonicalBatch, H as toolStepSettledRecordId, I as toolCallResolutionBatchId, J as turnResponseBatch, K as turnIdForRun, L as toolCallResolvedRecordId, M as subagentStartedRecordId, N as toolApprovalDecisionRecordId, O as subagentLineageRecordId, P as toolApprovalRequestRecordId, Q as workerInputRecordId, R as toolCallResultBatchId, S as runIdForSubmission, T as subagentJoinBatchId, U as turnApprovalsBatchId, V as toolStepSettledBatchId, X as turnResultsBatch, a as childIdempotencyKeyFor, b as runDurationBatchId, c as compactionRecordId, d as modelResponseInterruptedBatchId, et as workerReportRecordId, f as modelResponseInterruptedRecordId, g as projectRunJournalStream, i as approvalDecisionBatchId, j as subagentStartedBatchId, k as subagentRequestedBatchId, l as firstWorkerInputRecordId, m as peerMessageRecordId, o as childThreadIdFor, p as modelResponseRecordId, q as turnPreparedBatchId, r as agentUpdateRecordId, s as compactionBatchId, t as RunJournalError, tt as makeJournalMetadata, u as markUnknownBatchId, v as runCompletedRecordId, w as runStartedRecordId, x as runDurationRecordId, y as runCompletionDigest, z as toolCallSettledRecordId } from "./RunJournal-srpbEBEy.mjs";
30
+ import { FencedAppendRequest, LoadCheckpointRequest, MAX_THREAD_EXPORT_RECORDS, SaveRecoveryCheckpointRequest, ThreadCheckpoint, ThreadExportRequest, ThreadMaterialization, ThreadObservation, ThreadRead, ThreadStore, ThreadStoreError, ThreadTailRequest, getRecord, readWorkerState } from "./durable/ThreadStore.mjs";
30
31
  import { DurableRuntimeFailpoint } from "./durable/DurableFailpoint.mjs";
31
32
  import { ScheduledInputRefused, ScheduledInputRetryable } from "./durable/Schedule.mjs";
32
33
  import { PreparedInputAdmission } from "./durable/PreparedInputAdmission.mjs";
33
34
  import { PreparedInput } from "./durable/Subscription.mjs";
34
35
  import { MessageDeliveryDriver, MessageDeliveryFailpoint, MessageDeliveryRecord, MessageDeliveryStore, messageDeliveryCapacity, messageDeliveryUsesCapacity, prepareMessageDelivery } from "./durable/MessageDelivery.mjs";
35
36
  import { n as safeUnknownString, t as inspectForeignDiagnostic } from "./foreign-diagnostic-DBQ1XHKh.mjs";
36
- import { A as toolApprovalDecisionRecordId, B as turnApprovalsBatchId, C as subagentJoinedRecordId, D as subagentRequestedRecordId, E as subagentRequestedBatchId, F as toolCallResultBatchId, G as turnResponseBatch, H as turnCanonicalBatch, I as toolCallSettledRecordId, L as toolCallUnknownRecordId, M as toolCallPreparedRecordId, N as toolCallResolutionBatchId, O as subagentStartedBatchId, P as toolCallResolvedRecordId, R as toolStepSettledBatchId, S as subagentJoinBatchId, T as subagentLineageRecordId, U as turnIdForRun, W as turnPreparedBatchId, Y as makeJournalMetadata, _ as runDurationBatchId, a as childThreadIdFor, b as runStartedBatchId, c as markUnknownBatchId, d as modelResponseRecordId, g as runCompletionDigest, h as runCompletedRecordId, i as childIdempotencyKeyFor, j as toolApprovalRequestRecordId, k as subagentStartedRecordId, l as modelResponseInterruptedBatchId, o as compactionBatchId, p as projectRunJournalStream, q as turnResultsBatch, r as approvalDecisionBatchId, s as compactionRecordId, t as RunJournalError, u as modelResponseInterruptedRecordId, v as runDurationRecordId, w as subagentLineageBatchId, x as runStartedRecordId, y as runIdForSubmission, z as toolStepSettledRecordId } from "./RunJournal-DNs3PM4K.mjs";
37
37
  import { WorkerBudgetAuthorizer, WorkerConcurrencyLimit, WorkerConcurrencyResolver, WorkerHostAuthorizer, WorkerHostConfig, WorkerPolicyResolver } from "./durable/WorkerHost.mjs";
38
38
  import { OperationAuthorizationRequest, OperationAuthorizer, OperationDenied } from "./durable/OperationAuthorizer.mjs";
39
39
  import { PendingSubmission, SettledSubmission } from "./durable/SubmissionStatus.mjs";
@@ -42,6 +42,61 @@ import { PreparedToolCallEvidence, ToolReconciler } from "./durable/ToolReconcil
42
42
  import { WakeScheduler } from "./durable/WakeScheduler.mjs";
43
43
  import { Prompt } from "effect/unstable/ai";
44
44
  import { Cause, Clock, Context, Crypto, DateTime, Deferred, Duration, Effect, Equal, Layer, Option, Ref, Schedule, Schema, Semaphore, Stream } from "effect";
45
+ //#region src/durable/internal/journal-checkpoint.ts
46
+ /** Retired accounting is additive; the latest Tool batch always remains replayable verbatim. */
47
+ var JournalCheckpointSeed = class extends Schema.Class("@effect-agent/thread/internal/JournalCheckpointSeed")({
48
+ runId: RunId,
49
+ throughSequence: CanonicalSequence,
50
+ firstSequence: Schema.optionalKey(CanonicalSequence),
51
+ toolSelection: Schema.optionalKey(Selection),
52
+ committedTurns: Schema.Natural,
53
+ policyUsage: RunPolicyUsage,
54
+ modelCalls: Schema.Natural,
55
+ unobservedModelCalls: Schema.Natural,
56
+ inputTokens: Schema.Natural,
57
+ outputTokens: Schema.Natural,
58
+ lastInputTokens: Schema.Natural,
59
+ lastOutputTokens: Schema.Natural,
60
+ costMicrousd: Schema.Natural,
61
+ summarizedModelUsage: RunUsageSummary,
62
+ protectedContext: Schema.optionalKey(PersistedJson),
63
+ contextWindowId: Schema.optionalKey(Schema.String),
64
+ frontier: Schema.optionalKey(Schema.Struct({
65
+ sequence: CanonicalSequence,
66
+ tag: Schema.Literals(["ModelResponseRecorded", "ToolCallSettled"])
67
+ })),
68
+ /** Canonical replacement whose covered batches were validated before retirement. */
69
+ compaction: CanonicalRecordEnvelope
70
+ }) {};
71
+ /** A bounded sparse projection, never a canonical log or a submission-ownership record. */
72
+ var RecoveryCheckpointState = class extends Schema.Class("@effect-agent/thread/internal/RecoveryCheckpointState")({
73
+ schemaVersion: Schema.Literal(1),
74
+ policyAccountingVersion: Schema.Literal(1),
75
+ submissionId: SubmissionId,
76
+ submissionIds: Schema.Array(SubmissionId).check(Schema.isMaxLength(4096)),
77
+ seed: JournalCheckpointSeed,
78
+ records: Schema.Array(CanonicalRecordEnvelope).check(Schema.isMaxLength(4096))
79
+ }) {};
80
+ var RecoveryCheckpointContents = class extends Schema.Class("@effect-agent/thread/internal/RecoveryCheckpointContents")({
81
+ state: RecoveryCheckpointState,
82
+ digest: Digest
83
+ }) {};
84
+ const RECOVERY_ENGINE_VERSION = "effect-agent/recovery@1";
85
+ /**
86
+ * Late evidence can invalidate an old compaction. Such histories use full canonical replay;
87
+ * an omitted run/turn must never be treated as proven absent by a sparse projection.
88
+ */
89
+ const checkpointSuffixCompatible = (seed, records, retained) => records.every(({ sequence, record: { payload } }) => {
90
+ if ("runId" in payload && payload.runId !== void 0 && payload.runId !== seed.runId) return false;
91
+ if ("turn" in payload && payload.turn <= seed.committedTurns) return false;
92
+ if (payload._tag === "ToolCallSettled" || payload._tag === "ToolCallResolved") return [...retained, ...records].some(({ sequence: declarationSequence, record: { payload: candidate } }) => {
93
+ if (candidate._tag !== "ModelResponseRecorded" || candidate.runId !== payload.runId || candidate.turn <= seed.committedTurns || seed.compaction.record.payload._tag !== "CompactionCreated" || declarationSequence <= seed.compaction.record.payload.coversThrough || declarationSequence >= sequence) return false;
94
+ const decoded = Schema.decodeUnknownOption(Prompt.Prompt)(candidate.messages);
95
+ return Option.isSome(decoded) && decoded.value.content.some((message) => message.role === "assistant" && message.content.some((part) => part.type === "tool-call" && part.id === payload.toolCallId));
96
+ });
97
+ return payload._tag !== "CompactionCreated" || payload.coversThrough >= seed.throughSequence;
98
+ });
99
+ //#endregion
45
100
  //#region src/durable/internal/worker-runtime.ts
46
101
  /** Canonical worker operations constructed once by the durable coordinator. */
47
102
  var WorkerRuntime = class extends Context.Service()("@effect-agent/thread/internal/WorkerRuntime") {};
@@ -191,61 +246,6 @@ const makeAgentUpdateRuntime = Effect.fn("AgentUpdates.makeDurable")(function* (
191
246
  };
192
247
  });
193
248
  //#endregion
194
- //#region src/durable/internal/journal-checkpoint.ts
195
- /** Retired accounting is additive; the latest Tool batch always remains replayable verbatim. */
196
- var JournalCheckpointSeed = class extends Schema.Class("@effect-agent/thread/internal/JournalCheckpointSeed")({
197
- runId: RunId,
198
- throughSequence: CanonicalSequence,
199
- firstSequence: Schema.optionalKey(CanonicalSequence),
200
- toolSelection: Schema.optionalKey(Selection),
201
- committedTurns: Schema.Natural,
202
- policyUsage: RunPolicyUsage,
203
- modelCalls: Schema.Natural,
204
- unobservedModelCalls: Schema.Natural,
205
- inputTokens: Schema.Natural,
206
- outputTokens: Schema.Natural,
207
- lastInputTokens: Schema.Natural,
208
- lastOutputTokens: Schema.Natural,
209
- costMicrousd: Schema.Natural,
210
- summarizedModelUsage: RunUsageSummary,
211
- protectedContext: Schema.optionalKey(PersistedJson),
212
- contextWindowId: Schema.optionalKey(Schema.String),
213
- frontier: Schema.optionalKey(Schema.Struct({
214
- sequence: CanonicalSequence,
215
- tag: Schema.Literals(["ModelResponseRecorded", "ToolCallSettled"])
216
- })),
217
- /** Canonical replacement whose covered batches were validated before retirement. */
218
- compaction: CanonicalRecordEnvelope
219
- }) {};
220
- /** A bounded sparse projection, never a canonical log or a submission-ownership record. */
221
- var RecoveryCheckpointState = class extends Schema.Class("@effect-agent/thread/internal/RecoveryCheckpointState")({
222
- schemaVersion: Schema.Literal(1),
223
- policyAccountingVersion: Schema.Literal(1),
224
- submissionId: SubmissionId,
225
- submissionIds: Schema.Array(SubmissionId).check(Schema.isMaxLength(4096)),
226
- seed: JournalCheckpointSeed,
227
- records: Schema.Array(CanonicalRecordEnvelope).check(Schema.isMaxLength(4096))
228
- }) {};
229
- var RecoveryCheckpointContents = class extends Schema.Class("@effect-agent/thread/internal/RecoveryCheckpointContents")({
230
- state: RecoveryCheckpointState,
231
- digest: Digest
232
- }) {};
233
- const RECOVERY_ENGINE_VERSION = "effect-agent/recovery@1";
234
- /**
235
- * Late evidence can invalidate an old compaction. Such histories use full canonical replay;
236
- * an omitted run/turn must never be treated as proven absent by a sparse projection.
237
- */
238
- const checkpointSuffixCompatible = (seed, records, retained) => records.every(({ sequence, record: { payload } }) => {
239
- if ("runId" in payload && payload.runId !== void 0 && payload.runId !== seed.runId) return false;
240
- if ("turn" in payload && payload.turn <= seed.committedTurns) return false;
241
- if (payload._tag === "ToolCallSettled" || payload._tag === "ToolCallResolved") return [...retained, ...records].some(({ sequence: declarationSequence, record: { payload: candidate } }) => {
242
- if (candidate._tag !== "ModelResponseRecorded" || candidate.runId !== payload.runId || candidate.turn <= seed.committedTurns || seed.compaction.record.payload._tag !== "CompactionCreated" || declarationSequence <= seed.compaction.record.payload.coversThrough || declarationSequence >= sequence) return false;
243
- const decoded = Schema.decodeUnknownOption(Prompt.Prompt)(candidate.messages);
244
- return Option.isSome(decoded) && decoded.value.content.some((message) => message.role === "assistant" && message.content.some((part) => part.type === "tool-call" && part.id === payload.toolCallId));
245
- });
246
- return payload._tag !== "CompactionCreated" || payload.coversThrough >= seed.throughSequence;
247
- });
248
- //#endregion
249
249
  //#region src/durable/internal/messaging-host.ts
250
250
  const failure$1 = (operation, reason) => MessagingError.make({
251
251
  operation,
@@ -259,6 +259,7 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
259
259
  const deps = {
260
260
  ...options,
261
261
  store: yield* ThreadStore,
262
+ ledger: yield* SubmissionLedger,
262
263
  deliveries: yield* Effect.serviceOption(MessageDeliveryStore),
263
264
  crypto: yield* Crypto.Crypto,
264
265
  authorizer: yield* PeerAuthorizer,
@@ -268,10 +269,18 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
268
269
  failpoint: yield* MessageDeliveryFailpoint
269
270
  };
270
271
  const digest = (value) => digestJson(value).pipe(Effect.provideService(Crypto.Crypto, deps.crypto), Effect.mapError(() => failure$1("send", "storage")));
271
- const read = (threadId) => deps.store.export(ThreadExportRequest.make({ threadId })).pipe(Effect.mapError(() => failure$1("context", "storage")));
272
+ const exactRecord = Effect.fn("MessagingHost.exactRecord")(function* (threadId, recordId) {
273
+ return Option.getOrUndefined(yield* getRecord({
274
+ threadId,
275
+ recordId
276
+ }).pipe(Effect.provideService(ThreadStore, deps.store)).pipe(Effect.mapError(() => failure$1("send", "storage"))))?.record;
277
+ });
272
278
  const sourceOf = Effect.fn("MessagingHost.source")(function* (threadId) {
273
- const log = yield* read(threadId);
274
- const created = log.records[0]?.record.payload;
279
+ const log = yield* deps.store.inspectTail(ThreadTailRequest.make({ threadId })).pipe(Effect.mapError(() => failure$1("context", "storage")));
280
+ const created = (yield* deps.store.read(ThreadRead.make({
281
+ threadId,
282
+ limit: 1
283
+ })).pipe(Stream.runCollect, Effect.mapError(() => failure$1("context", "storage"))))[0]?.record.payload;
275
284
  if (created?._tag !== "ThreadCreated") return yield* failure$1("context", "not-found");
276
285
  if (deps.bindings.filter((binding) => binding.agentId === created.agentId).length !== 1) return yield* failure$1("context", "binding-mismatch");
277
286
  return {
@@ -296,7 +305,7 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
296
305
  });
297
306
  const proof = Effect.fn("MessagingHost.proof")(function* (message) {
298
307
  const source = yield* sourceOf(message.ownerThreadId);
299
- const record = source.log.records.find(({ record }) => record.payload._tag === "PeerMessagePrepared" && record.payload.messageId === message.messageId)?.record;
308
+ const record = yield* exactRecord(message.ownerThreadId, peerMessageRecordId(message.messageId));
300
309
  if (record === void 0) return yield* failure$1("reply", "invalid-reference");
301
310
  const saved = yield* decodeProof(record);
302
311
  if (!Schema.is(MessageAdmission)(saved.envelope.messageAdmission) || saved.envelope.messageAdmission.sender.agentId !== source.address.agentId || !sameRef(saved.envelope.messageAdmission.message, message)) return yield* failure$1("reply", "invalid-reference");
@@ -371,7 +380,7 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
371
380
  const maxMessages = yield* capacity;
372
381
  for (let attempt = 0; attempt < 8; attempt++) {
373
382
  const current = attempt === 0 ? initial : yield* sourceOf(threadId);
374
- const prior = current.log.records.find(({ record }) => record.payload._tag === "PeerMessagePrepared" && record.payload.messageId === message.messageId)?.record;
383
+ const prior = yield* exactRecord(threadId, peerMessageRecordId(message.messageId));
375
384
  let saved;
376
385
  if (prior !== void 0) {
377
386
  saved = yield* decodeProof(prior);
@@ -383,12 +392,23 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
383
392
  });
384
393
  yield* authorizeEnvelope(saved, operation);
385
394
  } else {
386
- if (current.log.records.filter(({ record }) => record.payload._tag === "PeerMessagePrepared").length >= maxMessages) return yield* failure$1(operation, "capacity");
395
+ if (deps.store.countPeerMessages === void 0) return yield* failure$1(operation, "unavailable");
396
+ if ((yield* deps.store.countPeerMessages({
397
+ threadId,
398
+ limit: maxMessages
399
+ }).pipe(Effect.mapError(mapStore(operation)))) >= maxMessages) return yield* failure$1(operation, "capacity");
387
400
  let destinationThread;
388
401
  if (operation === "reply") {
389
402
  if (inReplyTo === void 0) return yield* failure$1(operation, "invalid-reference");
390
- const inbound = current.log.records.find(({ record }) => record.payload._tag === "UserInputRecorded" && Schema.is(MessageAdmission)(record.payload.messageAdmission) && sameRef(record.payload.messageAdmission.message, inReplyTo))?.record.payload;
391
- if (inbound?._tag !== "UserInputRecorded" || !Schema.is(MessageAdmission)(inbound.messageAdmission) || inbound.messageAdmission.sender.agentId !== target.agentId) return yield* failure$1(operation, "invalid-reference");
403
+ const original = yield* proof(inReplyTo);
404
+ if (original.envelope.threadId !== threadId || original.envelope.agentId !== current.address.agentId) return yield* failure$1(operation, "invalid-reference");
405
+ const accepted = yield* deps.ledger.lookup(SubmissionLookupByKey.make({
406
+ threadId,
407
+ principal: original.envelope.deliveryPrincipal,
408
+ idempotencyKey: inReplyTo.messageId
409
+ })).pipe(Effect.mapError(mapStore(operation)));
410
+ const inbound = Option.isNone(accepted) ? void 0 : (yield* exactRecord(threadId, submissionInputRecordId(accepted.value.submissionId)))?.payload;
411
+ if (inbound?._tag !== "UserInputRecorded" || !Schema.is(MessageAdmission)(inbound.messageAdmission) || inbound.messageAdmission.sender.agentId !== target.agentId || !sameRef(inbound.messageAdmission.message, inReplyTo) || !Schema.is(MessageAdmission)(original.envelope.messageAdmission) || !sameAdmission$1(inbound.messageAdmission, original.envelope.messageAdmission) || Option.isNone(accepted) || inbound.submissionId !== accepted.value.submissionId) return yield* failure$1(operation, "invalid-reference");
392
412
  destinationThread = inbound.messageAdmission.returnAddress.threadId;
393
413
  } else destinationThread = yield* deps.routes.resolve({
394
414
  source: current.address,
@@ -437,7 +457,7 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
437
457
  batchId: Schema.decodeSync(BatchId)(message.messageId),
438
458
  producerId: deps.producerId,
439
459
  records: [RecordEnvelope.make({
440
- recordId: Schema.decodeSync(RecordId)(message.messageId),
460
+ recordId: peerMessageRecordId(message.messageId),
441
461
  family: "thread",
442
462
  schemaVersion: 1,
443
463
  createdAt: DateTime.makeUnsafe(createdAtMillis),
@@ -638,6 +658,36 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
638
658
  });
639
659
  });
640
660
  const read = (threadId, operation) => deps.store.export(ThreadExportRequest.make({ threadId })).pipe(Effect.mapError(storageFailure(operation)));
661
+ const exactRecord = Effect.fn("WorkerHost.exactRecord")(function* (threadId, recordId, operation) {
662
+ return yield* getRecord({
663
+ threadId,
664
+ recordId
665
+ }).pipe(Effect.provideService(ThreadStore, deps.store), Effect.mapError(storageFailure(operation)));
666
+ });
667
+ const readIdentity = Effect.fn("WorkerHost.readIdentity")(function* (threadId, operation) {
668
+ const tail = yield* deps.store.inspectTail(ThreadTailRequest.make({ threadId })).pipe(Effect.mapError(storageFailure(operation)));
669
+ const first = yield* deps.store.read(ThreadRead.make({
670
+ threadId,
671
+ limit: 1
672
+ })).pipe(Stream.runCollect, Effect.mapError(storageFailure(operation)));
673
+ const worker = yield* exactRecord(threadId, workerOriginRecordId(threadId), operation);
674
+ const attached = yield* exactRecord(threadId, subagentLineageRecordId(threadId), operation);
675
+ return {
676
+ ...tail,
677
+ records: [
678
+ ...first,
679
+ ...Option.toArray(worker),
680
+ ...Option.toArray(attached)
681
+ ]
682
+ };
683
+ });
684
+ const readWorkerState$1 = Effect.fn("WorkerHost.readWorkerState")(function* (threadId, operation, sourceSubmissionId) {
685
+ return yield* readWorkerState({
686
+ threadId,
687
+ limit: MAX_THREAD_EXPORT_RECORDS,
688
+ ...sourceSubmissionId === void 0 ? {} : { sourceSubmissionId }
689
+ }).pipe(Effect.provideService(ThreadStore, deps.store), Effect.mapError(storageFailure(operation)));
690
+ });
641
691
  const hit = (location, operation) => deps.failpoint.hit(location).pipe(Effect.mapError(storageFailure(operation)));
642
692
  const append = Effect.fn("WorkerHost.append")(function* (threadId, id, payload, current, phase) {
643
693
  const operation = "start";
@@ -681,10 +731,10 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
681
731
  const matches = deps.bindings.filter((entry) => entry.agentId === agentId);
682
732
  return matches.length === 1 ? matches[0] : void 0;
683
733
  };
684
- const sourceAuthority = Effect.fn("WorkerHost.sourceAuthority")(function* (threadId, submissionId) {
685
- const current = yield* read(threadId, "start");
734
+ const sourceAuthority = Effect.fn("WorkerHost.sourceAuthority")(function* (threadId, submissionId, reservations = false) {
735
+ const current = yield* reservations ? readWorkerState$1(threadId, "start", submissionId) : readIdentity(threadId, "start");
686
736
  const created = current.records[0]?.record.payload;
687
- if (created?._tag !== "ThreadCreated") return yield* failure("start", "not-found");
737
+ if (created?._tag !== "ThreadCreated" || current.records[0]?.sequence !== 1) return yield* failure("start", "not-found");
688
738
  const binding = currentBinding(created.agentId);
689
739
  const worker = current.records.find(({ record }) => record.payload._tag === "WorkerOriginRecorded")?.record.payload;
690
740
  const attached = current.records.find(({ record }) => record.payload._tag === "SubagentLineageRecorded")?.record.payload;
@@ -760,7 +810,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
760
810
  const payload = yield* decode(SubtreeBudgetReserved, requested, "start");
761
811
  const recordId = `subtree:${payload.reservationId}`;
762
812
  for (let attempt = 0; attempt < 16; attempt++) {
763
- const source = yield* sourceAuthority(sourceThreadId, payload.sourceSubmissionId);
813
+ const source = yield* sourceAuthority(sourceThreadId, payload.sourceSubmissionId, true);
764
814
  const previous = source.current.records.find(({ record }) => record.recordId === recordId)?.record.payload;
765
815
  if (previous !== void 0) {
766
816
  if (previous._tag !== "SubtreeBudgetReserved" || !Schema.toEquivalence(SubtreeBudgetReserved)(previous, payload)) return yield* failure("start", "idempotency-conflict");
@@ -809,9 +859,9 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
809
859
  });
810
860
  const reservation = Effect.fn("WorkerHost.reserveInput")(function* (admission, inputDigest, input, principal, retainedFrameworkInput) {
811
861
  const origin = admission.origin;
812
- const id = `worker-input:${admission.messageId}`;
862
+ const id = workerInputRecordId(admission.messageId);
813
863
  for (let attempt = 0; attempt < 16; attempt++) {
814
- const source = yield* sourceAuthority(origin.source.threadId, admission.sourceSubmissionId);
864
+ const source = yield* sourceAuthority(origin.source.threadId, admission.sourceSubmissionId, true);
815
865
  const current = source.current;
816
866
  const rows = requests(current.records);
817
867
  const existing = current.records.find(({ record }) => record.recordId === id)?.record.payload;
@@ -899,7 +949,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
899
949
  });
900
950
  const ensureOrigin = Effect.fn("WorkerHost.ensureOrigin")(function* (origin) {
901
951
  for (let attempt = 0; attempt < 16; attempt++) {
902
- const current = yield* read(origin.worker.threadId, "start");
952
+ const current = yield* readIdentity(origin.worker.threadId, "start");
903
953
  const existing = current.records.find(({ record }) => record.payload._tag === "WorkerOriginRecorded")?.record.payload;
904
954
  if (existing?._tag === "WorkerOriginRecorded") {
905
955
  if (!sameOrigin(existing.origin, origin)) return yield* failure("start", "worker-mismatch");
@@ -907,7 +957,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
907
957
  }
908
958
  const first = current.records[0]?.record.payload;
909
959
  if (first?._tag !== "ThreadCreated" || first.agentId !== origin.worker.targetAgentId || !definitionDigestsEqual(first.definitions, origin.targetDigests) || current.records.some(({ record }) => record.payload._tag === "SubagentLineageRecorded")) return yield* failure("start", "worker-mismatch");
910
- if (yield* append(origin.worker.threadId, `worker-origin:${origin.worker.threadId}`, WorkerOriginRecorded.make({ origin }), current, "origin")) return;
960
+ if (yield* append(origin.worker.threadId, workerOriginRecordId(origin.worker.threadId), WorkerOriginRecorded.make({ origin }), current, "origin")) return;
911
961
  }
912
962
  return yield* failure("start", "storage");
913
963
  });
@@ -937,9 +987,8 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
937
987
  const intent = origin?.reporting;
938
988
  if (origin === void 0 || intent?.mode !== "standard") return void 0;
939
989
  if (update.threadId !== submission.threadId || update.agentId !== origin.worker.targetAgentId) return yield* failure("followUp", "worker-mismatch");
940
- const sourceHistory = yield* read(origin.source.threadId, "followUp");
941
- const first = requests(sourceHistory.records).find((row) => row.admission.messageId === origin.firstMessageId);
942
- if (first === void 0 || !sameOrigin(first.admission.origin, origin)) return yield* failure("followUp", "corrupt");
990
+ const first = Option.getOrUndefined(yield* exactRecord(origin.source.threadId, workerInputRecordId(origin.firstMessageId), "followUp"))?.record.payload;
991
+ if (first?._tag !== "WorkerInputRequested" || first.admission.messageId !== origin.firstMessageId || !sameOrigin(first.admission.origin, origin)) return yield* failure("followUp", "corrupt");
943
992
  const source = yield* sourceAuthority(origin.source.threadId, first.admission.sourceSubmissionId);
944
993
  if (source.binding === void 0 || source.submission === void 0) return yield* failure("followUp", "declaration-unavailable");
945
994
  const sourceBinding = currentBinding(origin.source.agentId);
@@ -1028,7 +1077,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1028
1077
  submission.threadId,
1029
1078
  runId
1030
1079
  ])).pipe(Effect.map((value) => Schema.decodeSync(IdempotencyKey)(`report:${value}`)), Effect.mapError(storageFailure("inspect")));
1031
- const recordId = `worker-report:${messageId}`;
1080
+ const recordId = workerReportRecordId(messageId);
1032
1081
  const prepare = Effect.fn("WorkerHost.prepareReport")(function* () {
1033
1082
  const refused = (reason) => WorkerReportRefused.make({
1034
1083
  runId,
@@ -1039,9 +1088,8 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1039
1088
  if (Option.isNone(selected) || selected.value.threadId !== submission.threadId || selected.value.receiptId !== host.receiptId || selected.value.workerAdmission === void 0 || !sameOrigin(selected.value.workerAdmission.origin, origin)) return yield* failure("inspect", "corrupt");
1040
1089
  const hostSubmission = selected.value;
1041
1090
  const hostAdmission = selected.value.workerAdmission;
1042
- const sourceHistory = yield* read(origin.source.threadId, "inspect");
1043
- const firstInput = requests(sourceHistory.records).find((row) => row.admission.messageId === origin.firstMessageId);
1044
- if (firstInput === void 0 || !sameOrigin(firstInput.admission.origin, origin)) return yield* failure("inspect", "corrupt");
1091
+ const firstInput = Option.getOrUndefined(yield* exactRecord(origin.source.threadId, workerInputRecordId(origin.firstMessageId), "inspect"))?.record.payload;
1092
+ if (firstInput?._tag !== "WorkerInputRequested" || firstInput.admission.messageId !== origin.firstMessageId || !sameOrigin(firstInput.admission.origin, origin)) return yield* failure("inspect", "corrupt");
1045
1093
  const source = yield* sourceAuthority(origin.source.threadId, firstInput.admission.sourceSubmissionId);
1046
1094
  if (source.binding === void 0) return refused("declaration-unavailable");
1047
1095
  const sourceBinding = currentBinding(origin.source.agentId);
@@ -1192,7 +1240,15 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1192
1240
  const settledEnvelope = child.records.find(({ record }) => record.payload._tag === "SubmissionSettled" && record.payload.submissionId === submission.submissionId)?.record;
1193
1241
  const settled = settledEnvelope?.payload;
1194
1242
  if (settled?._tag !== "SubmissionSettled" || settled.receiptId !== submission.receiptId || settledEnvelope === void 0) return yield* failure("inspect", "corrupt");
1243
+ const unresolved = /* @__PURE__ */ new Set();
1244
+ for (const { record } of child.records) {
1245
+ const value = record.payload;
1246
+ if ((value._tag === "ToolCallPrepared" || value._tag === "ToolCallUnknown") && value.runId === settled.runId) unresolved.add(value.toolCallId);
1247
+ if (value._tag === "ToolCallSettled" && value.runId === settled.runId) unresolved.delete(value.toolCallId);
1248
+ }
1249
+ if (unresolved.size > 0) return;
1195
1250
  const payload = WorkerInputCompleted.make({
1251
+ effectsResolved: true,
1196
1252
  messageId: admission.messageId,
1197
1253
  workerThreadId: submission.threadId,
1198
1254
  submissionId: submission.submissionId,
@@ -1202,12 +1258,15 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1202
1258
  });
1203
1259
  for (let attempt = 0; attempt < 16; attempt++) {
1204
1260
  const source = yield* read(admission.origin.source.threadId, "inspect");
1205
- const existing = source.records.find(({ record }) => record.payload._tag === "WorkerInputCompleted" && record.payload.messageId === admission.messageId)?.record.payload;
1261
+ const existing = source.records.findLast(({ record }) => record.payload._tag === "WorkerInputCompleted" && record.payload.messageId === admission.messageId)?.record.payload;
1206
1262
  if (existing !== void 0) {
1207
- if (existing._tag !== "WorkerInputCompleted" || !Schema.toEquivalence(WorkerInputCompleted)(existing, payload)) return yield* failure("inspect", "corrupt");
1208
- return;
1263
+ if (existing._tag !== "WorkerInputCompleted" || !Schema.toEquivalence(WorkerInputCompleted)({
1264
+ ...existing,
1265
+ effectsResolved: true
1266
+ }, payload)) return yield* failure("inspect", "corrupt");
1267
+ if (existing.effectsResolved) return;
1209
1268
  }
1210
- if (yield* append(admission.origin.source.threadId, `worker-completed:${admission.messageId}`, payload, source, "completion")) return;
1269
+ if (yield* append(admission.origin.source.threadId, `worker-effects-resolved:${admission.messageId}`, payload, source, "completion")) return;
1211
1270
  }
1212
1271
  return yield* failure("inspect", "storage");
1213
1272
  });
@@ -1244,10 +1303,10 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1244
1303
  const findOrigin = Effect.fn("WorkerHost.findOrigin")(function* (worker, target, operation) {
1245
1304
  yield* binding(target, operation);
1246
1305
  if (worker.targetAgentId !== target.id) return yield* failure(operation, "worker-mismatch");
1247
- const source = yield* read(context.source.threadId, operation);
1248
- const origin = requests(source.records).find((row) => row.admission.origin.worker.threadId === worker.threadId)?.admission.origin;
1306
+ const first = Option.getOrUndefined(yield* exactRecord(context.source.threadId, firstWorkerInputRecordId(worker), operation))?.record.payload;
1307
+ const origin = first?._tag === "WorkerInputRequested" ? first.admission.origin : void 0;
1249
1308
  if (origin === void 0) return yield* failure(operation, "not-found");
1250
- if (origin.worker.delegationId !== worker.delegationId) return yield* failure(operation, "worker-mismatch");
1309
+ if (!Schema.toEquivalence(WorkerRef)(origin.worker, worker) || first?._tag !== "WorkerInputRequested" || first.admission.messageId !== origin.firstMessageId || workerInputRecordId(origin.firstMessageId) !== firstWorkerInputRecordId(worker)) return yield* failure(operation, "worker-mismatch");
1251
1310
  return origin;
1252
1311
  });
1253
1312
  const receiptInput = Effect.fn("WorkerHost.receiptInput")(function* (request, operation) {
@@ -1476,7 +1535,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1476
1535
  summary: Effect.fn("WorkerHost.inspectWorker")(function* (request) {
1477
1536
  yield* authorize("inspect", "read", request.worker);
1478
1537
  const origin = yield* findOrigin(request.worker, request.target, "inspect");
1479
- const source = yield* read(context.source.threadId, "inspect");
1538
+ const source = yield* readWorkerState$1(context.source.threadId, "inspect");
1480
1539
  return yield* summarize(origin, requests(source.records), "inspect");
1481
1540
  }),
1482
1541
  observe: (request) => Stream.unwrap(Effect.gen(function* () {
@@ -1516,7 +1575,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1516
1575
  yield* authorize("list", "read");
1517
1576
  yield* binding(request.target, "list");
1518
1577
  if (!Number.isSafeInteger(request.limit) || request.limit < 1 || request.limit > 100) return yield* failure("list", "capacity");
1519
- const source = yield* read(context.source.threadId, "list");
1578
+ const source = yield* readWorkerState$1(context.source.threadId, "list");
1520
1579
  const all = requests(source.records);
1521
1580
  const origins = [...new Map(all.map((row) => [row.admission.origin.worker.threadId, row.admission.origin])).values()].filter((origin) => origin.worker.delegationId === request.delegationId && origin.worker.targetAgentId === request.target.id && (request.after === void 0 || origin.worker.threadId > request.after)).sort((left, right) => left.worker.threadId.localeCompare(right.worker.threadId));
1522
1581
  const selected = origins.slice(0, request.limit);
@@ -1538,17 +1597,18 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1538
1597
  };
1539
1598
  const validateCompletion = Effect.fn("WorkerHost.validateCompletion")(function* (unvalidated, options, agentId, inputDigest) {
1540
1599
  const message = yield* Schema.decodeEffect(FrameworkMessage)(unvalidated).pipe(Effect.mapError(() => failure("followUp", "corrupt")));
1541
- const child = yield* read(message._tag === "WorkerCompletion" ? message.report.worker.threadId : message.worker.threadId, "followUp");
1542
- const frozen = message._tag === "WorkerCompletion" ? child.records.flatMap(({ record }) => record.payload._tag === "WorkerReportPrepared" && record.payload.runId === message.report.runId ? [record.payload.envelope] : [])[0] : child.records.flatMap(({ record }) => record.payload._tag === "AgentUpdateEmitted" && Schema.toEquivalence(Update)(record.payload.update, message.update) && record.payload.delivery !== void 0 ? [record.payload.delivery.envelope] : [])[0];
1600
+ const childThreadId = message._tag === "WorkerCompletion" ? message.report.worker.threadId : message.worker.threadId;
1601
+ const proofId = message._tag === "WorkerCompletion" ? workerReportRecordId(options.idempotencyKey) : yield* withCrypto(agentUpdateRecordId(message.update.threadId, message.update.runId, message.update.updateId)).pipe(Effect.mapError(storageFailure("followUp")));
1602
+ const proof = Option.getOrUndefined(yield* exactRecord(childThreadId, proofId, "followUp"))?.record.payload;
1603
+ const frozen = message._tag === "WorkerCompletion" ? proof?._tag === "WorkerReportPrepared" && proof.runId === message.report.runId && proof.messageId === options.idempotencyKey ? proof.envelope : void 0 : proof?._tag === "AgentUpdateEmitted" && Schema.toEquivalence(Update)(proof.update, message.update) ? proof.delivery?.envelope : void 0;
1543
1604
  if (frozen === void 0) return yield* failure("followUp", "denied");
1544
1605
  const envelope = yield* Schema.decodeUnknownEffect(PreparedInput)(frozen).pipe(Effect.mapError(() => failure("followUp", "corrupt")));
1545
1606
  if (!Schema.is(FrameworkMessage)(envelope.messageAdmission) || !Schema.toEquivalence(FrameworkMessage)(envelope.messageAdmission, message) || envelope.threadId !== options.threadId || envelope.agentId !== agentId || envelope.inputDigest !== inputDigest || envelope.deliveryPrincipal !== options.principal || envelope.admissionKey !== options.idempotencyKey || !definitionDigestsEqual(envelope.definitions, options.definitions) || !Schema.toEquivalence(Schema.UndefinedOr(WorkerAdmission))(envelope.workerAdmission, options.workerAdmission)) return yield* failure("followUp", "denied");
1546
- const recorded = child.records.find(({ record }) => record.payload._tag === "WorkerOriginRecorded")?.record.payload;
1547
- if (recorded?._tag !== "WorkerOriginRecorded" || recorded.origin.reporting?.mode !== "standard") return yield* failure("followUp", "denied");
1607
+ const recorded = Option.getOrUndefined(yield* exactRecord(childThreadId, workerOriginRecordId(childThreadId), "followUp"))?.record.payload;
1608
+ if (recorded?._tag !== "WorkerOriginRecorded" || recorded.origin.worker.threadId !== childThreadId || recorded.origin.reporting?.mode !== "standard") return yield* failure("followUp", "denied");
1548
1609
  const origin = recorded.origin;
1549
- const source = yield* read(origin.source.threadId, "followUp");
1550
- const first = requests(source.records).find((row) => row.admission.messageId === origin.firstMessageId);
1551
- if (first === void 0 || !sameOrigin(first.admission.origin, origin)) return yield* failure("followUp", "denied");
1610
+ const first = Option.getOrUndefined(yield* exactRecord(origin.source.threadId, workerInputRecordId(origin.firstMessageId), "followUp"))?.record.payload;
1611
+ if (first?._tag !== "WorkerInputRequested" || first.admission.messageId !== origin.firstMessageId || !sameOrigin(first.admission.origin, origin)) return yield* failure("followUp", "denied");
1552
1612
  const receiving = envelope.workerAdmission;
1553
1613
  const sourceSubmissionId = receiving === void 0 ? first.admission.sourceSubmissionId : receiving.sourceSubmissionId;
1554
1614
  if ((yield* deps.authorizer.authorize({
@@ -1573,7 +1633,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1573
1633
  operation: "context",
1574
1634
  access: "context"
1575
1635
  });
1576
- const current = yield* read(sourceThreadId, "context");
1636
+ const current = yield* readIdentity(sourceThreadId, "context");
1577
1637
  const created = current.records[0]?.record.payload;
1578
1638
  if (created?._tag !== "ThreadCreated") return yield* failure("context", "not-found");
1579
1639
  const selected = request.sourceSubmissionId === void 0 ? void 0 : yield* sourceAuthority(sourceThreadId, request.sourceSubmissionId);
@@ -5937,6 +5997,11 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5937
5997
  operation: "recoverSubmission",
5938
5998
  message: `Unknown Submission ${submissionId}`
5939
5999
  });
6000
+ if (found.value.state === "settled") yield* workerRuntime.completeInput(found.value).pipe(Effect.mapError((cause) => LedgerError.make({
6001
+ operation: "recoverSubmission",
6002
+ message: "Worker completion repair failed",
6003
+ cause
6004
+ })));
5940
6005
  const history = yield* readRecoveryHistory(found.value.threadId, [submissionId]);
5941
6006
  if (history.materialized && found.value.workerAdmission?.origin.reporting?.mode === "standard") yield* updateRuntime.repair(found.value.threadId);
5942
6007
  return yield* recoverSnapshot(found.value, history);
@@ -6604,4 +6669,4 @@ var DurableAgentRuntime = class DurableAgentRuntime extends Context.Service()("@
6604
6669
  //#endregion
6605
6670
  export { RecoveryReport as a, recoveryRepairRecordId as c, DurableRuntimeConfig as i, threadCreatedBatchId as l, DurableAgentRuntime_exports as n, childReservationIdFor as o, DurableApprovalResolver as r, recoveryRepairBatchId as s, DurableAgentRuntime as t, threadCreatedRecordId as u };
6606
6671
 
6607
- //# sourceMappingURL=DurableAgentRuntime-BE_OjQjz.mjs.map
6672
+ //# sourceMappingURL=DurableAgentRuntime-HOZ3AeSi.mjs.map