effect-agent 0.1.0-beta.159 → 0.1.0-beta.160

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 (62) hide show
  1. package/dist/{Admin-DWDYlvvZ.d.mts → Admin-Dirux8PR.d.mts} +9 -2
  2. package/dist/{DurableAgentRuntime-C7A5guvq.mjs → DurableAgentRuntime-pr7cCaZw.mjs} +216 -55
  3. package/dist/DurableAgentRuntime-pr7cCaZw.mjs.map +1 -0
  4. package/dist/{EventSource-BfNZBG4A.d.mts → EventSource-DOXB0RJR.d.mts} +2 -2
  5. package/dist/{PreparedInputAdmission-VStpn8u2.d.mts → PreparedInputAdmission-B7r401xJ.d.mts} +3 -3
  6. package/dist/{RunJournal-ixFRCyW3.mjs → RunJournal-CA2bsvHn.mjs} +8 -5
  7. package/dist/RunJournal-CA2bsvHn.mjs.map +1 -0
  8. package/dist/{Subscription-Bx1ZRRVS.d.mts → Subscription-B3ScCBaN.d.mts} +2 -2
  9. package/dist/{SubscriptionInput-B5k5vb1S.d.mts → SubscriptionInput-BP5WVsX_.d.mts} +2 -2
  10. package/dist/{WorkerAdmission-N9hZV85Q.mjs → WorkerAdmission-Cmcxd6nS.mjs} +2 -2
  11. package/dist/{WorkerAdmission-N9hZV85Q.mjs.map → WorkerAdmission-Cmcxd6nS.mjs.map} +1 -1
  12. package/dist/durable/Admin.d.mts +1 -1
  13. package/dist/durable/AgentRegistration.d.mts +1 -1
  14. package/dist/durable/Certification.d.mts +1 -1
  15. package/dist/durable/CommittedActivity.d.mts +1 -1
  16. package/dist/durable/DurableAgentRuntime.d.mts +1 -1
  17. package/dist/durable/DurableAgentRuntime.mjs +2 -2
  18. package/dist/durable/EventSource.d.mts +1 -1
  19. package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
  20. package/dist/durable/LifecyclePublication.d.mts +1 -1
  21. package/dist/durable/MessageDelivery.d.mts +3 -3
  22. package/dist/durable/MessageDeliveryStoreConformance.d.mts +1 -1
  23. package/dist/durable/PersistentHistory.d.mts +1 -1
  24. package/dist/durable/PersistentHistory.mjs +1 -1
  25. package/dist/durable/PreparedInputAdmission.d.mts +1 -1
  26. package/dist/durable/Recovery.d.mts +1 -1
  27. package/dist/durable/RunJournal.d.mts +1 -1
  28. package/dist/durable/RunJournal.mjs +1 -1
  29. package/dist/durable/Scheduling.d.mts +1 -1
  30. package/dist/durable/SqlMemoryStore.d.mts +3 -0
  31. package/dist/durable/SqlMemoryStore.mjs +3 -2
  32. package/dist/durable/SqlMemoryStore.mjs.map +1 -1
  33. package/dist/durable/SubmissionLedger.d.mts +1 -1
  34. package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
  35. package/dist/durable/SubmissionLedgerConformance.mjs +1 -1
  36. package/dist/durable/SubmissionStatus.d.mts +1 -1
  37. package/dist/durable/Subscription.d.mts +1 -1
  38. package/dist/durable/SubscriptionInput.d.mts +1 -1
  39. package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
  40. package/dist/durable/SubscriptionTools.d.mts +2 -2
  41. package/dist/durable/SubscriptionTransition.d.mts +1 -1
  42. package/dist/durable/Subscriptions.d.mts +5 -5
  43. package/dist/durable/ThreadContextHistory.d.mts +1 -1
  44. package/dist/durable/ThreadInvariants.d.mts +1 -1
  45. package/dist/durable/ThreadInvariants.mjs +1 -1
  46. package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
  47. package/dist/durable/ThreadStore.d.mts +1 -1
  48. package/dist/durable/ThreadStore.mjs +1 -1
  49. package/dist/durable/ThreadStoreConformance.d.mts +1 -1
  50. package/dist/durable/ThreadStoreConformance.mjs +1 -1
  51. package/dist/durable/WorkerAdmission.d.mts +1 -1
  52. package/dist/durable/WorkerAdmission.mjs +1 -1
  53. package/dist/durable/WorkerHost.d.mts +1 -1
  54. package/dist/index.d.mts +5 -5
  55. package/dist/index.mjs +3 -3
  56. package/package.json +1 -1
  57. package/src/durable/DurableAgentRuntime.ts +371 -84
  58. package/src/durable/RunJournal.ts +16 -4
  59. package/src/durable/SqlMemoryStore.ts +7 -3
  60. package/src/durable/internal/journal-checkpoint.ts +57 -3
  61. package/dist/DurableAgentRuntime-C7A5guvq.mjs.map +0 -1
  62. package/dist/RunJournal-ixFRCyW3.mjs.map +0 -1
@@ -182,6 +182,13 @@ declare const JournalCheckpointSeed_base: Schema.Class<JournalCheckpointSeed, Sc
182
182
  }>, {}>;
183
183
  /** Retired accounting is additive; the latest Tool batch always remains replayable verbatim. */
184
184
  declare class JournalCheckpointSeed extends JournalCheckpointSeed_base {}
185
+ declare const ThreadContextCheckpoint_base: Schema.Class<ThreadContextCheckpoint, Schema.Struct<{
186
+ readonly throughSequence: Schema.brand<Schema.Natural, "@effect-agent/thread/CanonicalSequence">;
187
+ readonly prompt: Schema.declare<Schema.Json, Schema.Json>;
188
+ readonly contextWindowId: Schema.optionalKey<Schema.String>;
189
+ }>, {}>;
190
+ /** Canonical historical context for a later Run, without the previous Run's authority or usage. */
191
+ declare class ThreadContextCheckpoint extends ThreadContextCheckpoint_base {}
185
192
  //#endregion
186
193
  //#region src/durable/internal/journal-metadata.d.ts
187
194
  /** Metadata for one exact canonical prefix, including the same optional checkpoint seed. */
@@ -444,7 +451,7 @@ interface JournalBoundary {
444
451
  * it skips only the metadata scan, never covered-Tool validation or the canonical fold.
445
452
  * @internal
446
453
  */
447
- declare const projectRunJournalStream: <E, R>(records: Stream.Stream<CanonicalRecordEnvelope, E, R>, ownerRunId: (string & import("effect/Brand").Brand<"@effect-agent/core/RunId">) | undefined, onBoundary?: ((boundary: JournalBoundary) => void) | undefined, seed?: JournalCheckpointSeed | undefined, preparedMetadata?: JournalMetadata | undefined) => Effect.Effect<RunJournalProjection, E | RunJournalError, R>;
454
+ declare const projectRunJournalStream: <E, R>(records: Stream.Stream<CanonicalRecordEnvelope, E, R>, ownerRunId: (string & import("effect/Brand").Brand<"@effect-agent/core/RunId">) | undefined, onBoundary?: ((boundary: JournalBoundary) => void) | undefined, seed?: JournalCheckpointSeed | undefined, preparedMetadata?: JournalMetadata | undefined, priorContext?: ThreadContextCheckpoint | undefined) => Effect.Effect<RunJournalProjection, E | RunJournalError, R>;
448
455
  /** Pure projection of one Run's durable recovery state from canonical records. */
449
456
  declare const projectRunJournal: (records: readonly CanonicalRecordEnvelope[], runId: string & import("effect/Brand").Brand<"@effect-agent/core/RunId">) => Effect.Effect<RunJournalProjection, RunJournalError, never>;
450
457
  /**
@@ -4260,4 +4267,4 @@ declare const RetryRefused_base: Schema.Class<RetryRefused, Schema.TaggedStruct<
4260
4267
  declare class RetryRefused extends RetryRefused_base {}
4261
4268
  //#endregion
4262
4269
  export { RepairSubagentStartLink as $, runDurationBatchId as $i, DurableApprovalFailure as $n, ThreadRecoveryCheckpoints as $r, ParentLinkage as $t, AwaitChildSettlement as A, turnResultsBatchId as Aa, JournalBoundary as Ai, SuspensionReason as An, CheckpointRejected as Ar, ChildReservationConflict as At, MarkUnknown as B, DurableBindingFailure as Ba, compactionBatchId as Bi, settlementFailureFromRecord as Bn, ThreadExport as Br, InputAppliedMarker as Bt, renderRecoveryExplanation as C, turnBatchId as Ca, drainLifecyclePublications as Ci, SubmissionLookupByKey as Cn, isolateRecovery as Cr, ApprovalDecisionIntent as Ct, ApplyUnknownResolutions as D, turnResponseBatch as Da, SettledSubmission as Di, SubmissionWorkItem as Dn, threadCreatedRecordId as Dr, ChildAttachmentSnapshot as Dt, ApplyJoinAccounting as E, turnPreparedBatchId as Ea, PendingSubmission as Ei, SubmissionState as En, threadCreatedBatchId as Er, BeginChildBudgetReleaseRequest as Et, CompleteMaterialization as F, AgentAttemptContext as Fa, TurnCommitInput as Fi, UnknownResolutionIntent as Fn, SaveCheckpointRequest as Fr, Claim as Ft, PropagateChildAbort as G, compileBindingContracts as Ga, modelResponseInterruptedRecordId as Gi, submissionSettlementBatchId as Gn, ThreadNotMaterialized as Gr, MarkInputAppliedRequest as Gt, OpenDelegationCallEvidence as H, ExecutableAgentBinding as Ha, firstWorkerInputRecordId as Hi, submissionAbortRecordId as Hn, ThreadIdentity as Hr, JoiningClaim as Ht, DeclaredPendingBatchEvidence as I, AgentRegistration as Ia, agentUpdateRecordId as Ii, WaitingChild as In, SaveRecoveryCheckpointRequest as Ir, ClaimHandoff as It, Recovery_d_exports as J, projectRunJournal as Ji, workerTerminalFromRecord as Jn, ThreadOutstandingRequest as Jr, MarkUnknownRequest as Jt, RecoveryDecision as K, compileRegistrations as Ka, modelResponseRecordId as Ki, submissionSettlementId as Kn, ThreadObservation as Kr, MarkJoinedRequest as Kt, DelegationAdmissionEvidence as L, BindingSelection as La, approvalDecisionBatchId as Li, WaitingForChildSuspension as Ln, SelectedThreadRead as Lr, ClaimJoiningRequest as Lt, AwaitParentEstablishment as M, workerOriginRecordId as Ma, RunJournalProjection as Mi, UnknownResolution as Mn, FencedAppendRequest as Mr, ChildReservationStatus as Mt, AwaitUnknownResolution as N, workerReportRecordId as Na, RunJournalUsage as Ni, UnknownResolutionCommand as Nn, LoadCheckpointRequest as Nr, ChildSettledNotification as Nt, AwaitApprovalDecision as O, turnResponseBatchId as Oa, SubmissionStatus as Oi, SuspendRequest as On, AppendConflict as Or, ChildBudgetReservationRequest as Ot, CompleteChildAdmission as P, AgentRegistration_d_exports as Pa, RunJournal_d_exports as Pi, UnknownResolutionConflict as Pn, MAX_THREAD_EXPORT_RECORDS as Pr, ChildSettledOutcome as Pt, RepairReadiness as Q, runCompletionDigest as Qi, DurableAgentRuntime_d_exports as Qn, ThreadRecordRequest as Qr, OwnershipToken as Qt, EnsureWaitingForChild as R, BindingUnavailable as Ra, childIdempotencyKeyFor as Ri, WorkerLedgerState as Rn, ThreadCheckpoint as Rr, ClaimRequest as Rt, recoveryDecisionMeaning as S, turnApprovalsBatchId as Sa, LifecyclePublication_d_exports as Si, SubmissionLookupById as Sn, childReservationIdFor as Sr, ApprovalDecisionCommand as St, ApplyInput as T, turnIdForRun as Ta, lifecyclePublicationLayer as Ti, SubmissionSnapshot as Tn, recoveryRepairRecordId as Tr, AttachChildToReservationRequest as Tt, OpenToolCallEvidence as U, ReplayVersions as Ua, markUnknownBatchId as Ui, submissionInputBatchId as Un, ThreadIdentityRequest as Ur, LedgerCapabilities as Ut, NoAction as V, DurableWorkerBinding as Va, compactionRecordId as Vi, submissionAbortBatchId as Vn, ThreadExportRequest as Vr, JoinSnapshot as Vt, PendingApprovalEvidence as W, ResolvedBinding as Wa, modelResponseInterruptedBatchId as Wi, submissionInputRecordId as Wn, ThreadMaterialization as Wr, LedgerError as Wt, RepairInputMarker as X, promptFromCanonicalRecords as Xi, DurableAbortFailure as Xn, ThreadRead as Xr, OwnershipRenewal as Xt, ReleaseOrphanChildReservation as Y, projectRunJournalStream as Yi, ApprovalSuspensionError as Yn, ThreadPeerCountRequest as Yr, OwnershipLost as Yt, RepairJoinMarker as Z, runCompletedRecordId as Zi, DurableAgentRuntime as Zn, ThreadReadRequest as Zr, OwnershipSnapshot as Zt, RetryCommand as _, toolCallResultBatchId as _a, LifecyclePublicationError as _i, SubmissionAdmissionFence as _n, RecoveryBlocked as _r, AdmissionPolicyError as _t, IntegrityCheck as a, subagentJoinedRecordId as aa, ThreadStoreFailure as ai, ReservedChildBudget as an, DurableObserveOptions as ar, SettleAborted as at, obligationSeverityOf as b, toolStepSettledBatchId as ba, LifecyclePublicationSource as bi, SubmissionLedger_d_exports as bn, RecoverySweepOptions as br, AdmissionResult as bt, IntegrityReport as c, subagentRequestedBatchId as ca, ThreadTailRequest as ci, ResolutionCompletedWithResult as cn, DurableRetryFailure as cr, AbortCommand as ct, ObligationReport as d, subagentStartedRecordId as da, getRunInput as di, RevertJoiningRequest as dn, DurableSubmitAgent as dr, AdmissionAdmitted as dt, runDurationRecordId as ea, ThreadRunInputRequest as ei, RecoverySnapshot as en, DurableApprovalResolver as er, ResumeFromTurnBoundary as et, ObligationSeverity as f, toolApprovalDecisionRecordId as fa, readOutstanding as fi, Settlement as fn, DurableSubmitFailure as fr, AdmissionConflict as ft, RecoveryExplanation as g, toolCallResolvedRecordId as ga, LifecyclePublicationConfig as gi, SettlementReservationSnapshot as gn, DurableWorkerRequirements as gr, AdmissionNotAdmitted as gt, RecoveryDisposition as h, toolCallResolutionBatchId as ha, LifecyclePublicationBatch as hi, SettlementReservation as hn, DurableWorkerFailure as hr, AdmissionIndeterminate as ht, ExplainedUnknownCall as i, subagentJoinBatchId as ia, ThreadStoreError as ii, RenewOwnershipRequest as in, DurableObligationFailure as ir, RevertJoining as it, AwaitHostSettlement as j, workerInputRecordId as ja, RunJournalError as ji, SuspensionSnapshot as jn, FenceRejected as jr, ChildReservationId as jt, AwaitChildAdmissionResolution as k, turnResultsBatch as ka, SubmissionStatus_d_exports as ki, SuspensionOutcome as kn, AppendResult as kr, ChildBudgetReservationSnapshot as kt, ObligationBlockedOn as l, subagentRequestedRecordId as la, ThreadWorkerStateRequest as li, ResolutionNeverHappened as ln, DurableRuntimeConfig as lr, AbortIntent as lt, RECOVERY_DECISION_MEANINGS as m, toolCallPreparedRecordId as ma, LifecyclePublication as mi, SettlementFinalization as mn, DurableVerifyFailure as mr, AdmissionGroup as mt, ExplainedEvidence as n, runStartedBatchId as na, ThreadStore as ni, ReleaseChildBudgetRequest as nn, DurableAwaitFailure as nr, ResumeSuspended as nt, IntegrityCheckName as o, subagentLineageBatchId as oa, ThreadStore_d_exports as oi, ReservedSettlement as on, DurableProgressFailure as or, SettleJoinedWithHost as ot, ObligationThresholds as p, toolApprovalRequestRecordId as pa, readWorkerState as pi, SettlementConflict as pn, DurableSubmitOptions as pr, AdmissionFence as pt, RecoveryEvidence as q, definitionDigestsEqual as qa, peerMessageRecordId as qi, submissionSettlementRecordId as qn, ThreadOutstanding as qr, MarkReadyRequest as qt, ExplainedSubmission as r, runStartedRecordId as ra, ThreadStoreDiagnostic as ri, ReleaseOwnershipRequest as rn, DurableExplainFailure as rr, ResumeWaitingParent as rt, IntegrityCheckStatus as s, subagentLineageRecordId as sa, ThreadTail as si, ResolutionAbortSubmission as sn, DurableResolveFailure as sr, classifyRecovery as st, Admin_d_exports as t, runIdForSubmission as ta, ThreadSelection as ti, RecoverySnapshotRequest as tn, DurableApprovalSuspension as tr, ResumePendingToolBatch as tt, ObligationEntry as u, subagentStartedBatchId as ua, getRecord as ui, ResolutionSafeToRetry as un, DurableRuntimeConfigOptions as ur, AbortIntentRequest as ut, RetryRefusalReason as v, toolCallSettledRecordId as va, LifecyclePublicationFact as vi, SubmissionLedger as vn, RecoveryFailure as vr, AdmissionRequest as vt, AppendReservedSettlement as w, turnCanonicalBatch as wa, lifecyclePublicationBatchMaxFacts as wi, SubmissionScheduling as wn, recoveryRepairBatchId as wr, ApprovalPendingSuspension as wt, predictRecoveryDisposition as x, toolStepSettledRecordId as xa, LifecyclePublicationStorage as xi, SubmissionLookup as xn, RecoverySweepResult as xr, ApprovalConflict as xt, RetryRefused as y, toolCallUnknownRecordId as ya, LifecyclePublicationHandler as yi, SubmissionLedgerFailure as yn, RecoveryReport as yr, AdmissionResolution as yt, FinalizeLedgerFromHistory as z, CurrentBindingSelection as za, childThreadIdFor as zi, WorkerStopCommand as zn, ThreadCheckpoints as zr, DEFAULT_OWNERSHIP_LEASE_DURATION as zt };
4263
- //# sourceMappingURL=Admin-DWDYlvvZ.d.mts.map
4270
+ //# sourceMappingURL=Admin-Dirux8PR.d.mts.map
@@ -27,7 +27,7 @@ import { DeclaredPendingBatchEvidence, OpenDelegationCallEvidence, OpenToolCallE
27
27
  import { ExplainedEvidence, ExplainedSubmission, ExplainedUnknownCall, IntegrityCheck, IntegrityReport, ObligationEntry, ObligationReport, RecoveryExplanation, RetryRefused, obligationSeverityOf, predictRecoveryDisposition, recoveryDecisionMeaning } from "./durable/Admin.mjs";
28
28
  import { digestJson } from "./durable/Digest.mjs";
29
29
  import { a as compileRegistrations, c as resolveDefinitionBinding, l as resolveWorkerBinding, n as CurrentBindingSelection, o as definitionDigestsEqual, s as makeLegacyWorkerBinding, t as BindingUnavailable, u as toolReplayContracts } from "./agent-registration-BIOzAej4.mjs";
30
- 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-ixFRCyW3.mjs";
30
+ 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-CA2bsvHn.mjs";
31
31
  import { FencedAppendRequest, LoadCheckpointRequest, MAX_THREAD_EXPORT_RECORDS, SaveRecoveryCheckpointRequest, ThreadCheckpoint, ThreadExportRequest, ThreadIdentityRequest, ThreadMaterialization, ThreadObservation, ThreadRead, ThreadStore, ThreadStoreDiagnostic, ThreadStoreError, ThreadTailRequest, getRecord, getRunInput, readWorkerState } from "./durable/ThreadStore.mjs";
32
32
  import { DurableRuntimeFailpoint } from "./durable/DurableFailpoint.mjs";
33
33
  import { ScheduledInputRefused, ScheduledInputRetryable } from "./durable/Schedule.mjs";
@@ -36,7 +36,7 @@ import { PreparedInput } from "./durable/Subscription.mjs";
36
36
  import { MessageDeliveryDriver, MessageDeliveryFailpoint, MessageDeliveryRecord, MessageDeliveryStore, messageDeliveryCapacity, messageDeliveryUsesCapacity, prepareMessageDelivery } from "./durable/MessageDelivery.mjs";
37
37
  import { WakeScheduler } from "./durable/WakeScheduler.mjs";
38
38
  import { n as safeUnknownString, t as inspectForeignDiagnostic } from "./foreign-diagnostic-DBQ1XHKh.mjs";
39
- import { c as threadCreatedBatchId, l as threadCreatedRecordId, n as WorkerAdmissionPort, o as ensureThreadCreated, r as WorkerAdmissionRequest, s as ensureWorkerOrigin } from "./WorkerAdmission-N9hZV85Q.mjs";
39
+ import { c as threadCreatedBatchId, l as threadCreatedRecordId, n as WorkerAdmissionPort, o as ensureThreadCreated, r as WorkerAdmissionRequest, s as ensureWorkerOrigin } from "./WorkerAdmission-Cmcxd6nS.mjs";
40
40
  import { WorkerBudgetAuthorizer, WorkerConcurrencyLimit, WorkerConcurrencyResolver, WorkerHostAuthorizer, WorkerHostConfig, WorkerPolicyResolver } from "./durable/WorkerHost.mjs";
41
41
  import { OperationAuthorizationRequest, OperationAuthorizer, OperationDenied } from "./durable/OperationAuthorizer.mjs";
42
42
  import { PendingSubmission, SettledSubmission } from "./durable/SubmissionStatus.mjs";
@@ -70,20 +70,60 @@ var JournalCheckpointSeed = class extends Schema.Class("@effect-agent/thread/int
70
70
  /** Canonical replacement whose covered batches were validated before retirement. */
71
71
  compaction: CanonicalRecordEnvelope
72
72
  }) {};
73
+ /** Canonical historical context for a later Run, without the previous Run's authority or usage. */
74
+ var ThreadContextCheckpoint = class extends Schema.Class("@effect-agent/thread/internal/ThreadContextCheckpoint")({
75
+ throughSequence: CanonicalSequence,
76
+ prompt: PersistedJson,
77
+ contextWindowId: Schema.optionalKey(Schema.String)
78
+ }) {};
73
79
  /** A bounded sparse projection, never a canonical log or a submission-ownership record. */
74
80
  var RecoveryCheckpointState = class extends Schema.Class("@effect-agent/thread/internal/RecoveryCheckpointState")({
75
- schemaVersion: Schema.Literal(1),
81
+ schemaVersion: Schema.Literal(2),
76
82
  policyAccountingVersion: Schema.Literal(1),
77
83
  submissionId: SubmissionId,
78
84
  submissionIds: Schema.Array(SubmissionId).check(Schema.isMaxLength(4096)),
79
- seed: JournalCheckpointSeed,
85
+ seed: Schema.optionalKey(JournalCheckpointSeed),
86
+ context: Schema.optionalKey(ThreadContextCheckpoint),
80
87
  records: Schema.Array(CanonicalRecordEnvelope).check(Schema.isMaxLength(4096))
81
88
  }) {};
82
89
  var RecoveryCheckpointContents = class extends Schema.Class("@effect-agent/thread/internal/RecoveryCheckpointContents")({
83
90
  state: RecoveryCheckpointState,
84
91
  digest: Digest
85
92
  }) {};
86
- const RECOVERY_ENGINE_VERSION = "effect-agent/recovery@2";
93
+ const RECOVERY_ENGINE_VERSION = "effect-agent/recovery@3";
94
+ /**
95
+ * Prove that indexed original-input absence also means absent prefix Run/control evidence.
96
+ * Only cache consumers with colon-free Submission IDs use this certificate. For those IDs,
97
+ * every possible control marker is exactly :run:<submission-id>:. Parsing here can only decline
98
+ * caching; it never supplies an execution identity. Separator-bearing identities use full replay.
99
+ * The temporary anchor set is discarded after certification, not persisted with the context.
100
+ */
101
+ const makeThreadContextCertificate = () => {
102
+ const anchored = /* @__PURE__ */ new Set();
103
+ let valid = true;
104
+ return {
105
+ add: ({ record }) => {
106
+ if (!valid) return;
107
+ const payload = record.payload;
108
+ if ("runId" in payload && payload.runId !== void 0) {
109
+ const originalInput = payload._tag === "UserInputRecorded" && payload.kind === "user";
110
+ if (originalInput ? anchored.has(payload.runId) : !anchored.has(payload.runId)) {
111
+ valid = false;
112
+ return;
113
+ }
114
+ if (originalInput) anchored.add(payload.runId);
115
+ }
116
+ for (let start = record.recordId.indexOf(":run:"); start !== -1; start = record.recordId.indexOf(":run:", start + 1)) {
117
+ const end = record.recordId.indexOf(":", start + 5);
118
+ if (end !== -1 && !anchored.has(record.recordId.slice(start + 1, end))) {
119
+ valid = false;
120
+ return;
121
+ }
122
+ }
123
+ },
124
+ isValid: () => valid
125
+ };
126
+ };
87
127
  /**
88
128
  * Late evidence can invalidate an old compaction. Such histories use full canonical replay;
89
129
  * an omitted run/turn must never be treated as proven absent by a sparse projection.
@@ -2499,21 +2539,19 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
2499
2539
  const view = yield* recoveryView(threadId, tail.tailSequence, submissionIds);
2500
2540
  return yield* Stream.runCollect(view.canonical.pipe(Stream.filter(controlRecords(submissionIds))));
2501
2541
  });
2502
- /** A checkpoint is useful only for its explicitly retained submissions and exact definitions. */
2503
- const recoveryView = Effect.fn("DurableAgentRuntime.recoveryView")(function* (threadId, throughSequence, submissionIds, journalOwner) {
2504
- const full = { canonical: canonicalRange(threadId, throughSequence) };
2505
- if (store.recoveryCheckpoints === void 0) return full;
2542
+ const loadRecoveryCheckpoint = Effect.fn("DurableAgentRuntime.loadRecoveryCheckpoint")(function* (threadId, throughSequence) {
2543
+ if (store.recoveryCheckpoints === void 0) return Option.none();
2506
2544
  const loaded = yield* store.recoveryCheckpoints.load(LoadCheckpointRequest.make({
2507
2545
  threadId,
2508
2546
  atOrBeforeSequence: throughSequence
2509
2547
  })).pipe(Effect.catchTag("CheckpointRejected", () => Effect.succeed(Option.none())));
2510
- if (Option.isNone(loaded)) return full;
2548
+ if (Option.isNone(loaded)) return Option.none();
2511
2549
  const checkpoint = loaded.value;
2512
- if (checkpoint.engineVersion !== "effect-agent/recovery@2" || checkpoint.threadId !== threadId || checkpoint.throughSequence > throughSequence || throughSequence - checkpoint.throughSequence > 4096) return full;
2550
+ if (checkpoint.engineVersion !== "effect-agent/recovery@3" || checkpoint.threadId !== threadId || checkpoint.throughSequence > throughSequence) return Option.none();
2513
2551
  const decoded = yield* Schema.decodeUnknownEffect(RecoveryCheckpointContents)(checkpoint.state).pipe(Effect.option);
2514
- if (Option.isNone(decoded)) return full;
2552
+ if (Option.isNone(decoded)) return Option.none();
2515
2553
  const { state, digest } = decoded.value;
2516
- if (!submissionIds.every((id) => state.submissionIds.includes(id)) || state.seed.runId !== runIdForSubmission(state.submissionId) || journalOwner !== void 0 && state.seed.runId !== journalOwner) return full;
2554
+ if (state.seed === void 0 && state.context === void 0 || state.records.some((record) => record.threadId !== threadId || record.sequence > checkpoint.throughSequence) || state.context !== void 0 && state.context.throughSequence !== checkpoint.throughSequence) return Option.none();
2517
2555
  const encoded = yield* Schema.encodeEffect(RecoveryCheckpointState)(state).pipe(Effect.mapError((cause) => ThreadStoreError.make({
2518
2556
  operation: "decode recovery checkpoint",
2519
2557
  message: "Invalid recovery state",
@@ -2523,15 +2561,74 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
2523
2561
  operation: "decode recovery checkpoint",
2524
2562
  message: cause.message,
2525
2563
  cause
2526
- }))))) return full;
2564
+ }))))) return Option.none();
2565
+ if (state.context !== void 0) {
2566
+ const prompt = yield* Schema.decodeUnknownEffect(Prompt.Prompt)(state.context.prompt).pipe(Effect.option);
2567
+ if (Option.isNone(prompt)) return Option.none();
2568
+ }
2527
2569
  const owner = yield* ledger.lookup(SubmissionLookupById.make({ submissionId: state.submissionId })).pipe(Effect.mapError((cause) => ThreadStoreError.make({
2528
2570
  operation: "recovery checkpoint compatibility",
2529
2571
  message: cause.message,
2530
2572
  cause
2531
2573
  })));
2532
- if (Option.isNone(owner) || owner.value.threadId !== threadId || owner.value.agentDigests.agent !== checkpoint.agentDefinitionDigest || owner.value.agentDigests.model !== checkpoint.modelDigest || owner.value.agentDigests.tools !== checkpoint.toolDigest) return full;
2574
+ if (Option.isNone(owner) || owner.value.threadId !== threadId || owner.value.agentDigests.agent !== checkpoint.agentDefinitionDigest || owner.value.agentDigests.model !== checkpoint.modelDigest || owner.value.agentDigests.tools !== checkpoint.toolDigest) return Option.none();
2575
+ return Option.some({
2576
+ checkpoint,
2577
+ state
2578
+ });
2579
+ });
2580
+ const retainThreadIdentity = ({ record }) => record.payload._tag === "ThreadCreated" || record.payload._tag === "SubagentLineageRecorded" || record.payload._tag === "WorkerOriginRecorded" || record.recordId.startsWith("subagent-lineage:");
2581
+ /** Late/foreign evidence and new compactions require the original canonical proof. */
2582
+ const contextSuffixCompatible = (records, submissionId) => {
2583
+ const runId = runIdForSubmission(submissionId);
2584
+ const certificate = makeThreadContextCertificate();
2585
+ for (const entry of records) {
2586
+ const { payload, recordId } = entry.record;
2587
+ if (payload._tag === "CompactionCreated" || retainThreadIdentity(entry)) return false;
2588
+ if ("runId" in payload && payload.runId !== void 0) {
2589
+ if (payload.runId !== runId) return false;
2590
+ } else if (payload._tag === "AbortRequested") {
2591
+ if (payload.submissionId !== submissionId || recordId !== submissionAbortRecordId(submissionId)) return false;
2592
+ } else if (payload._tag === "SubmissionSettled") {
2593
+ if (payload.submissionId !== submissionId || recordId !== submissionSettlementRecordId(submissionId)) return false;
2594
+ } else return false;
2595
+ certificate.add(entry);
2596
+ }
2597
+ return certificate.isValid();
2598
+ };
2599
+ /** Run seeds retain their owner; certified Thread context serves only provably later Runs. */
2600
+ const recoveryView = Effect.fn("DurableAgentRuntime.recoveryView")(function* (threadId, throughSequence, submissionIds, journalOwner) {
2601
+ const full = { canonical: canonicalRange(threadId, throughSequence) };
2602
+ const loaded = yield* loadRecoveryCheckpoint(threadId, throughSequence);
2603
+ if (Option.isNone(loaded)) return full;
2604
+ const { checkpoint, state } = loaded.value;
2605
+ if (throughSequence - checkpoint.throughSequence > 4096) return full;
2606
+ const submissionId = submissionIds.length === 1 ? submissionIds[0] : void 0;
2607
+ if (state.context !== void 0 && submissionId !== void 0 && !submissionId.includes(":") && (journalOwner === void 0 || journalOwner === runIdForSubmission(submissionId))) {
2608
+ const runId = runIdForSubmission(submissionId);
2609
+ if ([yield* getRunInput({
2610
+ threadId,
2611
+ runId
2612
+ }).pipe(Effect.provideService(ThreadStore, store)), ...yield* Effect.forEach([
2613
+ submissionInputRecordId(submissionId),
2614
+ submissionAbortRecordId(submissionId),
2615
+ submissionSettlementRecordId(submissionId),
2616
+ runStartedRecordId(runId),
2617
+ runCompletedRecordId(runId)
2618
+ ], (recordId) => getRecord({
2619
+ threadId,
2620
+ recordId
2621
+ }).pipe(Effect.provideService(ThreadStore, store)))].every((record) => Option.isNone(record) || record.value.sequence > checkpoint.throughSequence && record.value.sequence <= throughSequence)) {
2622
+ const suffix = yield* Stream.runCollect(canonicalRange(threadId, throughSequence, checkpoint.throughSequence));
2623
+ if (contextSuffixCompatible(suffix, submissionId)) return {
2624
+ canonical: Stream.fromIterable([...state.records.filter(retainThreadIdentity), ...suffix]),
2625
+ context: state.context
2626
+ };
2627
+ }
2628
+ }
2629
+ if (state.seed === void 0 || !submissionIds.every((id) => state.submissionIds.includes(id)) || state.seed.runId !== runIdForSubmission(state.submissionId) || journalOwner !== void 0 && state.seed.runId !== journalOwner) return full;
2533
2630
  const replacement = state.seed.compaction;
2534
- if (replacement.threadId !== threadId || replacement.sequence > checkpoint.throughSequence || replacement.record.payload._tag !== "CompactionCreated" || replacement.record.payload.kind === "clear-tool-results" || replacement.record.payload.coversThrough < state.seed.throughSequence || replacement.record.payload.coversThrough >= replacement.sequence || state.records.some((record) => record.threadId !== threadId || record.sequence > checkpoint.throughSequence) || !state.records.some((record) => record.sequence === replacement.sequence && record.record.recordId === replacement.record.recordId)) return full;
2631
+ if (replacement.threadId !== threadId || replacement.sequence > checkpoint.throughSequence || replacement.record.payload._tag !== "CompactionCreated" || replacement.record.payload.kind === "clear-tool-results" || replacement.record.payload.coversThrough < state.seed.throughSequence || replacement.record.payload.coversThrough >= replacement.sequence || !state.records.some((record) => record.sequence === replacement.sequence && record.record.recordId === replacement.record.recordId)) return full;
2535
2632
  const suffix = yield* Stream.runCollect(canonicalRange(threadId, throughSequence, checkpoint.throughSequence));
2536
2633
  if (!checkpointSuffixCompatible(state.seed, suffix, state.records)) return full;
2537
2634
  return {
@@ -2539,6 +2636,90 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
2539
2636
  seed: state.seed
2540
2637
  };
2541
2638
  });
2639
+ const persistRecoveryCheckpoint = Effect.fn("DurableAgentRuntime.persistRecoveryCheckpoint")(function* (ctx, submission, state, tail, createdAt) {
2640
+ if (store.recoveryCheckpoints === void 0) return;
2641
+ const encoded = yield* Schema.encodeEffect(RecoveryCheckpointState)(state).pipe(Effect.option);
2642
+ if (Option.isNone(encoded)) return;
2643
+ const digest = yield* withCrypto(digestJson(encoded.value));
2644
+ const contents = yield* Schema.encodeEffect(Schema.fromJsonString(RecoveryCheckpointContents))(RecoveryCheckpointContents.make({
2645
+ state,
2646
+ digest
2647
+ })).pipe(Effect.flatMap(Schema.decodeUnknownEffect(Schema.fromJsonString(PersistedJson))), Effect.option);
2648
+ if (Option.isNone(contents)) return;
2649
+ const checkpoint = ThreadCheckpoint.make({
2650
+ schemaVersion: 1,
2651
+ threadId: ctx.threadId,
2652
+ throughSequence: tail.sequence,
2653
+ tailDigest: tail.digest,
2654
+ engineVersion: RECOVERY_ENGINE_VERSION,
2655
+ agentDefinitionDigest: submission.agentDigests.agent,
2656
+ modelDigest: submission.agentDigests.model,
2657
+ toolDigest: submission.agentDigests.tools,
2658
+ state: contents.value,
2659
+ createdAt
2660
+ });
2661
+ yield* hit("checkpoint:before-save");
2662
+ yield* store.recoveryCheckpoints.save(SaveRecoveryCheckpointRequest.make({
2663
+ checkpoint,
2664
+ producerEpoch: ctx.producerEpoch
2665
+ })).pipe(Effect.catchTag("CheckpointRejected", () => Effect.void));
2666
+ yield* hit("checkpoint:after-save");
2667
+ });
2668
+ /** Refresh before settlement finalization, so completed processing includes the cache's cost. */
2669
+ const saveThreadContext = Effect.fn("DurableAgentRuntime.saveThreadContext")(function* (ctx, submission, priorContext) {
2670
+ if (store.recoveryCheckpoints === void 0) return;
2671
+ const tail = yield* Ref.get(ctx.tailRef);
2672
+ const loaded = yield* loadRecoveryCheckpoint(ctx.threadId, tail.sequence);
2673
+ if (Option.isNone(loaded)) return;
2674
+ const previous = loaded.value;
2675
+ let identities = previous.state.records.filter(retainThreadIdentity);
2676
+ let projection;
2677
+ if (priorContext !== void 0 && tail.sequence - priorContext.throughSequence <= 4096) {
2678
+ const suffix = yield* Stream.runCollect(canonicalRange(ctx.threadId, tail.sequence, priorContext.throughSequence));
2679
+ if (contextSuffixCompatible(suffix, submission.submissionId)) projection = yield* projectRunJournalStream(Stream.fromIterable(suffix), void 0, void 0, void 0, void 0, priorContext).pipe(Effect.catchTag("RunJournalError", () => Effect.succeed(void 0)));
2680
+ }
2681
+ if (projection === void 0) {
2682
+ const source = canonicalRange(ctx.threadId, tail.sequence);
2683
+ const certificate = makeThreadContextCertificate();
2684
+ const metadata = makeJournalMetadata(void 0);
2685
+ const retained = [];
2686
+ yield* Stream.runForEach(source, (entry) => Effect.sync(() => {
2687
+ certificate.add(entry);
2688
+ metadata.add(entry);
2689
+ if (retainThreadIdentity(entry) && retained.length <= 4096) retained.push(entry);
2690
+ }));
2691
+ if (!certificate.isValid() || retained.length > 4096) return;
2692
+ identities = retained;
2693
+ projection = yield* projectRunJournalStream(source, void 0, void 0, void 0, metadata.snapshot()).pipe(Effect.catchTag("RunJournalError", () => Effect.succeed(void 0)));
2694
+ }
2695
+ if (projection === void 0) return;
2696
+ const prompt = yield* Schema.encodeEffect(Prompt.Prompt)(projection.prompt).pipe(Effect.flatMap(decodePersisted), Effect.option);
2697
+ if (Option.isNone(prompt)) return;
2698
+ let seed;
2699
+ let records = identities;
2700
+ let submissionIds = [submission.submissionId];
2701
+ if (previous.state.submissionId === submission.submissionId && previous.state.seed !== void 0 && tail.sequence - previous.checkpoint.throughSequence + previous.state.records.length <= 4096) {
2702
+ const suffix = yield* Stream.runCollect(canonicalRange(ctx.threadId, tail.sequence, previous.checkpoint.throughSequence));
2703
+ if (checkpointSuffixCompatible(previous.state.seed, suffix, previous.state.records)) {
2704
+ seed = previous.state.seed;
2705
+ records = [...previous.state.records, ...suffix];
2706
+ submissionIds = previous.state.submissionIds;
2707
+ }
2708
+ }
2709
+ yield* persistRecoveryCheckpoint(ctx, submission, RecoveryCheckpointState.make({
2710
+ schemaVersion: 2,
2711
+ policyAccountingVersion: 1,
2712
+ submissionId: submission.submissionId,
2713
+ submissionIds,
2714
+ ...seed === void 0 ? {} : { seed },
2715
+ context: ThreadContextCheckpoint.make({
2716
+ throughSequence: tail.sequence,
2717
+ prompt: prompt.value,
2718
+ ...projection.contextWindowId === void 0 ? {} : { contextWindowId: projection.contextWindowId }
2719
+ }),
2720
+ records
2721
+ }), tail, yield* DateTime.now);
2722
+ });
2542
2723
  const readAllTolerant = Effect.fn("DurableAgentRuntime.readAllTolerant")((threadId, submissionIds) => readControl(threadId, submissionIds).pipe(Effect.map((records) => ({
2543
2724
  records,
2544
2725
  materialized: true
@@ -3468,7 +3649,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
3468
3649
  * Submissions joined to this host Run settle with the host outcome immediately after
3469
3650
  * (plan §2.5); recovery completes any prefix of that loop.
3470
3651
  */
3471
- const terminalize = Effect.fn("DurableAgentRuntime.terminalize")(function* (ctx, submission, tokenRef, outcome, includeRunId) {
3652
+ const terminalize = Effect.fn("DurableAgentRuntime.terminalize")(function* (ctx, submission, tokenRef, outcome, includeRunId, afterCanonical) {
3472
3653
  const submissionId = submission.submissionId;
3473
3654
  const settlementId = submissionSettlementId(submissionId);
3474
3655
  const payload = yield* Schema.decodeEffect(SubmissionSettledRecord)(SubmissionSettled.make({
@@ -3505,6 +3686,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
3505
3686
  })).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
3506
3687
  yield* hit("terminalize:after-canonical-append");
3507
3688
  yield* notifyParentOfChildSettlement(submission, reserved.record);
3689
+ if (afterCanonical !== void 0) yield* afterCanonical;
3508
3690
  const settlement = yield* ledger.finalizeSettlement(SettlementFinalization.make({
3509
3691
  submissionId,
3510
3692
  settlementId
@@ -4146,25 +4328,26 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4146
4328
  * journal ends mid-batch,
4147
4329
  * `RunOptions.resume` replays the declared batch without re-invoking the model (§2.4).
4148
4330
  */
4149
- const runModel = (agent, ctx, submission, tokenRef, renewAtRef, records, canonical, canonicalThrough, journalSeed, journalMetadata, lineage, approvalDecisions, currentContracts, runTiming, yieldAfter) => Effect.gen(function* () {
4331
+ const runModel = (agent, ctx, submission, tokenRef, renewAtRef, records, canonical, canonicalThrough, journalSeed, priorContext, journalMetadata, lineage, approvalDecisions, currentContracts, runTiming, yieldAfter) => Effect.gen(function* () {
4150
4332
  const submissionId = submission.submissionId;
4151
4333
  const runId = runIdForSubmission(submissionId);
4152
4334
  const boundaries = [];
4153
4335
  const cached = projectedJournal;
4154
- const journal = cached !== void 0 && cached.threadId === ctx.threadId && cached.through === canonicalThrough && cached.runId === runId && cached.seedThrough === journalSeed?.throughSequence ? (boundaries.push(...cached.boundaries), cached.journal) : yield* projectRunJournalStream(canonical, runId, (boundary) => boundaries.push(boundary), journalSeed, journalMetadata);
4336
+ const journal = cached !== void 0 && cached.threadId === ctx.threadId && cached.through === canonicalThrough && cached.runId === runId && cached.seedThrough === journalSeed?.throughSequence && cached.contextThrough === priorContext?.throughSequence ? (boundaries.push(...cached.boundaries), cached.journal) : yield* projectRunJournalStream(canonical, runId, (boundary) => boundaries.push(boundary), journalSeed, journalMetadata, priorContext);
4155
4337
  journalMetadata = void 0;
4156
4338
  projectedJournal = {
4157
4339
  threadId: ctx.threadId,
4158
4340
  through: canonicalThrough,
4159
4341
  runId,
4160
4342
  seedThrough: journalSeed?.throughSequence,
4343
+ contextThrough: priorContext?.throughSequence,
4161
4344
  journal,
4162
4345
  boundaries
4163
4346
  };
4164
4347
  const saveRecoveryCheckpoint = Effect.fn("DurableAgentRuntime.saveRecoveryCheckpoint")(function* (compactionId) {
4165
4348
  if (store.recoveryCheckpoints === void 0) return;
4166
4349
  const tail = yield* Ref.get(ctx.tailRef);
4167
- const source = Stream.concat(canonical, canonicalRange(ctx.threadId, tail.sequence, canonicalThrough));
4350
+ const source = priorContext === void 0 ? Stream.concat(canonical, canonicalRange(ctx.threadId, tail.sequence, canonicalThrough)) : canonicalRange(ctx.threadId, tail.sequence);
4168
4351
  let compaction;
4169
4352
  let latestResponse;
4170
4353
  let firstSequence = journalSeed?.firstSequence;
@@ -4222,7 +4405,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4222
4405
  for (const { record: { payload } } of retained) if (payload._tag === "UserInputRecorded" && payload.submissionId !== void 0) ids.add(payload.submissionId);
4223
4406
  const validated = yield* Effect.try({
4224
4407
  try: () => RecoveryCheckpointState.make({
4225
- schemaVersion: 1,
4408
+ schemaVersion: 2,
4226
4409
  policyAccountingVersion: 1,
4227
4410
  submissionId,
4228
4411
  submissionIds: [...ids],
@@ -4268,32 +4451,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4268
4451
  ].some((field) => current.usage[field] !== candidate.usage[field]) || (current.usage.unobservedModelCalls ?? 0) !== (candidate.usage.unobservedModelCalls ?? 0)) return;
4269
4452
  const summaries = yield* Effect.forEach([current, candidate], (projection) => summarizeModelUsage(projection.usage.modelUsage, projection.usage.summarizedModelUsage)).pipe(Effect.option);
4270
4453
  if (Option.isNone(summaries) || summaries.value[0] === void 0 || summaries.value[1] === void 0 || !Schema.toEquivalence(RunUsageSummary)(summaries.value[0], summaries.value[1])) return;
4271
- const encoded = yield* Schema.encodeEffect(RecoveryCheckpointState)(validated.value).pipe(Effect.option);
4272
- if (Option.isNone(encoded)) return;
4273
- const digest = yield* withCrypto(digestJson(encoded.value));
4274
- const contents = yield* Schema.encodeEffect(Schema.fromJsonString(RecoveryCheckpointContents))(RecoveryCheckpointContents.make({
4275
- state: validated.value,
4276
- digest
4277
- })).pipe(Effect.flatMap(Schema.decodeUnknownEffect(Schema.fromJsonString(PersistedJson))), Effect.option);
4278
- if (Option.isNone(contents)) return;
4279
- const checkpoint = ThreadCheckpoint.make({
4280
- schemaVersion: 1,
4281
- threadId: ctx.threadId,
4282
- throughSequence: tail.sequence,
4283
- tailDigest: tail.digest,
4284
- engineVersion: RECOVERY_ENGINE_VERSION,
4285
- agentDefinitionDigest: submission.agentDigests.agent,
4286
- modelDigest: submission.agentDigests.model,
4287
- toolDigest: submission.agentDigests.tools,
4288
- state: contents.value,
4289
- createdAt: replacement.record.createdAt
4290
- });
4291
- yield* hit("checkpoint:before-save");
4292
- yield* store.recoveryCheckpoints.save(SaveRecoveryCheckpointRequest.make({
4293
- checkpoint,
4294
- producerEpoch: ctx.producerEpoch
4295
- })).pipe(Effect.catchTag("CheckpointRejected", () => Effect.void));
4296
- yield* hit("checkpoint:after-save");
4454
+ yield* persistRecoveryCheckpoint(ctx, submission, validated.value, tail, replacement.record.createdAt);
4297
4455
  });
4298
4456
  const childLineage = records.find(({ record }) => record.recordId === subagentLineageRecordId(submission.threadId))?.record.payload;
4299
4457
  const inheritedGrant = submission.workerAdmission?.origin.grant ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.grant : void 0);
@@ -4301,7 +4459,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4301
4459
  const inheritedBudget = submission.workerAdmission?.origin.budget ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.budget : void 0);
4302
4460
  if (submission.parentLinkage !== void 0 && (childLineage?._tag !== "SubagentLineageRecorded" || childLineage.parentSubmissionId !== submission.parentLinkage.parentSubmissionId || childLineage.parentLink.parentToolCallId !== submission.parentLinkage.parentToolCallId || !definitionDigestsEqual(childLineage.childDefinitionDigests, submission.agentDigests) || childLineage.childInputDigest !== submission.inputDigest)) return yield* RunJournalError.make({ message: "The child Run has no matching canonical lineage and execution bounds" });
4303
4461
  const pending = yield* pendingToolBatchFor(records, runId, agent.definition.completionFromTools?.map((declaration) => declaration.tool));
4304
- const resumeProjection = pending === void 0 ? journal : yield* projectRunJournalStream(withoutPendingBatch(canonical, pending, runId), runId, void 0, journalSeed);
4462
+ const resumeProjection = pending === void 0 ? journal : yield* projectRunJournalStream(withoutPendingBatch(canonical, pending, runId), runId, void 0, journalSeed, void 0, priorContext);
4305
4463
  const rolloverOperation = journal.pendingContextToolCallId === void 0 ? void 0 : operationsFor(records, runId).get(journal.pendingContextToolCallId);
4306
4464
  const rolloverTool = rolloverOperation === void 0 ? void 0 : agent.definition.toolkit.tools[rolloverOperation.toolName];
4307
4465
  const pendingContextToolCallId = rolloverOperation !== void 0 && rolloverTool !== void 0 && Context.get(rolloverTool.annotations, ContextRolloverTool) && currentContracts[rolloverOperation.toolName] === rolloverOperation.replay ? journal.pendingContextToolCallId : void 0;
@@ -4728,11 +4886,11 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4728
4886
  if (knownIds.has(recordId)) return yield* CompactionError.make({ message: "Compaction is already committed for this Turn and kind" });
4729
4887
  let sourceJournal = journal;
4730
4888
  let sourceBoundaries = boundaries;
4731
- if (commit.kind !== "summarize") {
4732
- yield* recordHalt(commitPendingTurn);
4889
+ if (commit.kind !== "summarize" || priorContext !== void 0) {
4890
+ if (commit.kind !== "summarize") yield* recordHalt(commitPendingTurn);
4733
4891
  const tail = yield* Ref.get(ctx.tailRef);
4734
4892
  sourceBoundaries = [];
4735
- sourceJournal = yield* recordHalt(projectRunJournalStream(Stream.concat(canonical, canonicalRange(ctx.threadId, tail.sequence, canonicalThrough)).pipe(Stream.filter((envelope) => envelope.record.payload._tag !== "CompactionCreated" || envelope.sequence <= canonicalThrough)), runId, (boundary) => sourceBoundaries.push(boundary), journalSeed));
4893
+ sourceJournal = yield* recordHalt(projectRunJournalStream((priorContext === void 0 ? Stream.concat(canonical, canonicalRange(ctx.threadId, tail.sequence, canonicalThrough)) : canonicalRange(ctx.threadId, commit.kind === "summarize" ? canonicalThrough : tail.sequence)).pipe(Stream.filter((envelope) => envelope.record.payload._tag !== "CompactionCreated" || envelope.sequence <= canonicalThrough)), runId, (boundary) => sourceBoundaries.push(boundary), journalSeed));
4736
4894
  }
4737
4895
  const coverable = sourceBoundaries.filter((boundary) => commit.kind !== "summarize" || ownerFirstSequence === void 0 || boundary.sequence < ownerFirstSequence);
4738
4896
  if (coverable.length === 0) return yield* CompactionError.make({ message: commit.kind === "rollover" ? "Durable rollover requires complete canonical records" : "Durable compaction requires eligible canonical records" });
@@ -5935,11 +6093,14 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5935
6093
  inputWasRecorded: evidence.inputRecorded
5936
6094
  };
5937
6095
  let approvalDecisionIntents = snapshot.approvalDecisions;
6096
+ let priorContext = initialView.context;
5938
6097
  while (true) {
5939
6098
  const tail = yield* store.inspectTail(ThreadTailRequest.make({ threadId }));
5940
- const canonical = Stream.concat(initialView.canonical, canonicalRange(threadId, tail.tailSequence, initialThrough));
6099
+ const fullContextReplay = initialView.context !== void 0 && priorContext === void 0;
6100
+ const canonical = fullContextReplay ? canonicalRange(threadId, tail.tailSequence) : Stream.concat(initialView.canonical, canonicalRange(threadId, tail.tailSequence, initialThrough));
5941
6101
  const currentRecords = yield* refreshControl(tail.tailSequence);
5942
- const outcome = yield* runModel(agent, ctx, submission, tokenRef, renewAtRef, currentRecords, canonical, tail.tailSequence, initialView.seed, takeJournalMetadata(), lineage, approvalDecisionIntents, currentContracts, runTiming, yieldAfter);
6102
+ const outcome = yield* runModel(agent, ctx, submission, tokenRef, renewAtRef, currentRecords, canonical, tail.tailSequence, initialView.seed, priorContext, fullContextReplay ? void 0 : takeJournalMetadata(), lineage, approvalDecisionIntents, currentContracts, runTiming, yieldAfter);
6103
+ priorContext = void 0;
5943
6104
  if (outcome._tag === "yielded") {
5944
6105
  if (outcome.nextSubmissionId !== void 0) onHandoff(outcome.nextSubmissionId);
5945
6106
  return Option.none();
@@ -6021,7 +6182,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
6021
6182
  });
6022
6183
  }
6023
6184
  if (outcome._tag === "failed" && outcome.policyLimit === "duration" && !(yield* ordinaryCallsResolved)) return Option.none();
6024
- return Option.some(yield* terminalize(ctx, submission, tokenRef, outcome, true));
6185
+ return Option.some(yield* terminalize(ctx, submission, tokenRef, outcome, true, outcome._tag === "completed" ? saveThreadContext(ctx, submission, initialView.context) : void 0));
6025
6186
  }
6026
6187
  }).pipe(Effect.scoped);
6027
6188
  const acquireClaim = Effect.fn("DurableAgentRuntime.acquireClaim")(function* (threadId, handoff) {
@@ -7343,4 +7504,4 @@ var DurableAgentRuntime = class DurableAgentRuntime extends Context.Service()("@
7343
7504
  //#endregion
7344
7505
  export { DurableApprovalSuspension as a, RecoveryFailure as c, childReservationIdFor as d, isolateRecovery as f, DurableApprovalResolver as i, RecoveryReport as l, recoveryRepairRecordId as m, DurableAgentRuntime as n, DurableRuntimeConfig as o, recoveryRepairBatchId as p, DurableAgentRuntime_exports as r, RecoveryBlocked as s, ApprovalSuspensionError as t, RecoverySweepResult as u };
7345
7506
 
7346
- //# sourceMappingURL=DurableAgentRuntime-C7A5guvq.mjs.map
7507
+ //# sourceMappingURL=DurableAgentRuntime-pr7cCaZw.mjs.map