effect-agent 0.1.0-beta.119 → 0.1.0-beta.120

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 (56) hide show
  1. package/dist/{DurableAgentRuntime-DQqxmn2h.mjs → DurableAgentRuntime-B-9w7jDt.mjs} +86 -51
  2. package/dist/DurableAgentRuntime-B-9w7jDt.mjs.map +1 -0
  3. package/dist/{EventSource-hk1sVGsO.d.mts → EventSource-CnlZ3Kma.d.mts} +3 -3
  4. package/dist/{PreparedInputAdmission-DXvFh8zZ.d.mts → PreparedInputAdmission-BQLGldl-.d.mts} +4 -4
  5. package/dist/{Records-3uLornLz.d.mts → Records-D88mgvyS.d.mts} +22 -5
  6. package/dist/{Schedule-yVT2CmKT.d.mts → Schedule-BIOHA6RR.d.mts} +2 -2
  7. package/dist/{Subscription-CCvcJGlB.d.mts → Subscription-CRteOKRf.d.mts} +3 -3
  8. package/dist/{SubscriptionInput-BlE85a8M.d.mts → SubscriptionInput-oNcwTPti.d.mts} +3 -3
  9. package/dist/agent-registration-CKNsrpwo.mjs.map +1 -1
  10. package/dist/durable/ActivityStore.d.mts +1 -1
  11. package/dist/durable/Admin.d.mts +1 -1
  12. package/dist/durable/AgentRegistration.d.mts +1 -1
  13. package/dist/durable/Certification.d.mts +1 -1
  14. package/dist/durable/CommittedActivity.d.mts +1 -1
  15. package/dist/durable/Digest.d.mts +1 -1
  16. package/dist/durable/DurableAgentRuntime.d.mts +2 -2
  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/MessageDelivery.d.mts +41 -41
  21. package/dist/durable/MessageDeliveryStoreConformance.d.mts +1 -1
  22. package/dist/durable/PersistentHistory.d.mts +1 -1
  23. package/dist/durable/PreparedInputAdmission.d.mts +1 -1
  24. package/dist/durable/Records.d.mts +1 -1
  25. package/dist/durable/Recovery.d.mts +1 -1
  26. package/dist/durable/RunJournal.d.mts +1 -1
  27. package/dist/durable/Schedule.d.mts +1 -1
  28. package/dist/durable/ScheduleStoreConformance.d.mts +1 -1
  29. package/dist/durable/ScheduleTransition.d.mts +1 -1
  30. package/dist/durable/Scheduling.d.mts +2 -2
  31. package/dist/durable/SqlStorageV2Upgrade.d.mts +2 -2
  32. package/dist/durable/SqlSubscriptionStore.d.mts +2 -2
  33. package/dist/durable/SqlThreadNativeReads.d.mts +1 -1
  34. package/dist/durable/SubmissionLedger.d.mts +1 -1
  35. package/dist/durable/SubmissionLedgerConformance.d.mts +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 +3 -3
  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/ThreadContextHistoryProjection.d.mts +1 -1
  45. package/dist/durable/ThreadInvariants.d.mts +1 -1
  46. package/dist/durable/ThreadProjection.d.mts +1 -1
  47. package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
  48. package/dist/durable/ThreadStore.d.mts +1 -1
  49. package/dist/durable/ThreadStoreConformance.d.mts +1 -1
  50. package/dist/durable/WorkerHost.d.mts +1 -1
  51. package/dist/index.d.mts +6 -6
  52. package/dist/index.mjs +1 -1
  53. package/package.json +1 -1
  54. package/src/durable/DurableAgentRuntime.ts +174 -80
  55. package/src/durable/internal/agent-registration.ts +1 -0
  56. package/dist/DurableAgentRuntime-DQqxmn2h.mjs.map +0 -1
@@ -1862,8 +1862,10 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
1862
1862
  //#endregion
1863
1863
  //#region src/durable/DurableAgentRuntime.ts
1864
1864
  var DurableAgentRuntime_exports = /* @__PURE__ */ __exportAll({
1865
+ ApprovalSuspensionError: () => ApprovalSuspensionError,
1865
1866
  DurableAgentRuntime: () => DurableAgentRuntime,
1866
1867
  DurableApprovalResolver: () => DurableApprovalResolver,
1868
+ DurableApprovalSuspension: () => DurableApprovalSuspension,
1867
1869
  DurableRuntimeConfig: () => DurableRuntimeConfig,
1868
1870
  Receipt: () => Receipt,
1869
1871
  RecoveryBlocked: () => RecoveryBlocked,
@@ -2123,6 +2125,8 @@ var RecoverySweepResult = class extends Schema.Class("RecoverySweepResult")({
2123
2125
  /** Exactly one fault per failed Thread, regardless of its queued Submission count. */
2124
2126
  blocked: Schema.Array(RecoveryBlocked)
2125
2127
  }) {};
2128
+ /** Attempt resources could not be retained before deliberate approval suspension. */
2129
+ var ApprovalSuspensionError = class extends Schema.TaggedError()("ApprovalSuspensionError", { cause: Schema.Defect() }) {};
2126
2130
  /**
2127
2131
  * Optional policy-auto approval delegate consulted by the durable approval hook (plan §2.6 step
2128
2132
  * 2) AFTER the recorded-decision lookup misses. An immediate `approved`/`denied` answer becomes
@@ -2133,6 +2137,17 @@ var RecoverySweepResult = class extends Schema.Class("RecoverySweepResult")({
2133
2137
  * `@effect-agent/capabilities`' `toDurableRunApprovalHook`.
2134
2138
  */
2135
2139
  const DurableApprovalResolver = Context.Reference("@effect-agent/thread/DurableApprovalResolver", { defaultValue: () => void 0 });
2140
+ /**
2141
+ * Optional attempt-local retention before an unresolved approval releases ownership. Supply
2142
+ * this from the Attempt's Layer, capturing its live resources. The canonical approval request
2143
+ * already exists; claim renewal and abort observation remain active while this operation runs.
2144
+ * Return only after retention is confirmed. Failure leaves the accepted work owed and preserves
2145
+ * its cause; interruption keeps normal resource cleanup. No approval-gated Tool runs here.
2146
+ *
2147
+ * A decision racing with successful retention resumes the pending batch in a fresh Attempt,
2148
+ * after the old services and claim finalize. The default leaves existing suspension unchanged.
2149
+ */
2150
+ const DurableApprovalSuspension = Context.Reference("@effect-agent/thread/DurableApprovalSuspension", { defaultValue: () => void 0 });
2136
2151
  /** Deployment-scoped identity and liveness cadences for the durable coordinator. */
2137
2152
  var DurableRuntimeConfig = class DurableRuntimeConfig extends Context.Service()("@effect-agent/thread/DurableRuntimeConfig") {
2138
2153
  static make(options) {
@@ -2175,6 +2190,7 @@ var CoordinatorHalt = class {
2175
2190
  this.failure = failure;
2176
2191
  }
2177
2192
  };
2193
+ const isCoordinatorHaltCause = (cause) => cause.reasons.every((reason) => reason._tag !== "Fail" || reason.error instanceof CoordinatorHalt);
2178
2194
  const PolicyFailure = Schema.TaggedStruct("AgentPolicyError", { limit: PolicyLimit });
2179
2195
  const decodePolicyFailure = Schema.decodeUnknownOption(PolicyFailure);
2180
2196
  const decodePolicyFailureSafely = (error) => {
@@ -2184,9 +2200,10 @@ const decodePolicyFailureSafely = (error) => {
2184
2200
  return Option.none();
2185
2201
  }
2186
2202
  };
2187
- const agentApprovalPendingOption = (error) => {
2203
+ const agentApprovalPendingOption = (cause) => {
2188
2204
  try {
2189
- return error instanceof AgentApprovalPending ? Option.some(error) : Option.none();
2205
+ const first = cause.reasons.find(Cause.isFailReason);
2206
+ return first !== void 0 && first.error instanceof AgentApprovalPending && cause.reasons.every((reason) => reason._tag !== "Fail" || reason.error instanceof AgentApprovalPending) ? Option.some(first.error) : Option.none();
2190
2207
  } catch {
2191
2208
  return Option.none();
2192
2209
  }
@@ -3972,7 +3989,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
3972
3989
  onSome: ({ limit }) => ({ policyLimit: limit })
3973
3990
  })
3974
3991
  })));
3975
- const halt = (effect) => Effect.mapError(effect, (failure) => new CoordinatorHalt(failure));
3992
+ const halt = (effect) => Effect.catchCause(effect, (cause) => Effect.failCause(Cause.map(cause, (failure) => new CoordinatorHalt(failure))));
3976
3993
  /**
3977
3994
  * Superseding-Attempt interruption audit (durability §9): appended at most once per superseded
3978
3995
  * fence epoch before this Attempt re-invokes the model. It deliberately over-approximates — a
@@ -4345,7 +4362,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
4345
4362
  const budgetRejectedCalls = /* @__PURE__ */ new Set();
4346
4363
  const haltRef = yield* Ref.make(void 0);
4347
4364
  const yieldSignal = yield* Deferred.make();
4348
- const recordHalt = (effect) => effect.pipe(Effect.tapError((failure) => Ref.set(haltRef, failure)), Effect.mapError((failure) => new CoordinatorHalt(failure)));
4365
+ const recordHalt = (effect) => effect.pipe(Effect.tapError((failure) => Ref.set(haltRef, failure)), halt);
4349
4366
  const stateRef = yield* Ref.make({
4350
4367
  baseLen: void 0,
4351
4368
  lastCommitLen: 0,
@@ -5389,7 +5406,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5389
5406
  const failure = yield* Ref.get(haltRef);
5390
5407
  if (failure !== void 0) return yield* Effect.fail(failure);
5391
5408
  yield* handleEvent(event);
5392
- }))).pipe(Effect.as({ _tag: "run" }));
5409
+ }))).pipe(Effect.tapCause((cause) => Option.isSome(agentApprovalPendingOption(cause)) && cause.reasons.every(Cause.isFailReason) ? Effect.flatMap(DurableApprovalSuspension, (retain) => retain === void 0 ? Effect.void : halt(retain)) : Effect.void), Effect.as({ _tag: "run" }));
5393
5410
  const abortWatcher = halt(Effect.gen(function* () {
5394
5411
  while (true) {
5395
5412
  yield* Effect.sleep(config.abortPollInterval);
@@ -5409,12 +5426,16 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5409
5426
  }).pipe(Effect.uninterruptible), { schedule: Schedule.spaced(config.leaseRenewalInterval) }).pipe(Effect.andThen(Effect.never)));
5410
5427
  const execution = Effect.raceFirst(consume, Effect.raceFirst(abortWatcher, renewal));
5411
5428
  const result = yield* (yieldAfter === void 0 ? execution : Effect.raceFirst(execution, Deferred.await(yieldSignal).pipe(Effect.as({ _tag: "yielded" })))).pipe(Effect.provideService(IdGenerator$1, idGenerator)).pipe(Effect.catchCauseFilter(Cause.findError, (error, cause) => {
5412
- if (error instanceof CoordinatorHalt) return Effect.fail(error.failure);
5413
- const approvalPending = agentApprovalPendingOption(error);
5414
- if (Option.isSome(approvalPending)) return decodeToolCallIdUnknown(approvalPending.value.toolCallId).pipe(Effect.orDie, Effect.map((toolCallId) => ({
5415
- _tag: "suspendedRun",
5416
- toolCallId
5417
- })));
5429
+ if (isCoordinatorHaltCause(cause)) return Effect.failCause(Cause.map(cause, (halt) => halt.failure));
5430
+ const approvalPending = agentApprovalPendingOption(cause);
5431
+ if (Option.isSome(approvalPending)) {
5432
+ const residual = Cause.fromReasons(cause.reasons.filter((reason) => reason._tag !== "Fail"));
5433
+ if (residual.reasons.length > 0) return Effect.failCause(residual);
5434
+ return decodeToolCallIdUnknown(approvalPending.value.toolCallId).pipe(Effect.orDie, Effect.map((toolCallId) => ({
5435
+ _tag: "suspendedRun",
5436
+ toolCallId
5437
+ })));
5438
+ }
5418
5439
  const childPending = agentChildPendingOption(error);
5419
5440
  if (Option.isSome(childPending)) return commitSiblingLateSettles(childPending.value.children).pipe(Effect.map(() => ({
5420
5441
  _tag: "suspendedChildRun",
@@ -5483,7 +5504,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5483
5504
  * (Unknown Outcomes, or a durable approval suspension) — no settlement occurs and the
5484
5505
  * obligation stays owed.
5485
5506
  */
5486
- const runAttempt = (registeredAgent, threadId, claim, tokenRef, yieldAfter) => Effect.gen(function* () {
5507
+ const runAttempt = (registeredAgent, threadId, claim, tokenRef, resumeAfterRetention, yieldAfter) => Effect.gen(function* () {
5487
5508
  const submissionId = claim.submissionId;
5488
5509
  const supersededEpoch = yield* store.inspectTail(ThreadTailRequest.make({ threadId })).pipe(Effect.map((tail) => tail.producerEpoch), Effect.catchTag("ThreadNotMaterialized", () => Effect.succeed(ZERO_EPOCH)));
5489
5510
  yield* store.materialize(ThreadMaterialization.make({
@@ -5696,6 +5717,10 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5696
5717
  }));
5697
5718
  yield* hit("approval:after-suspend");
5698
5719
  if (suspension === "suspended") return Option.none();
5720
+ if ((yield* DurableApprovalSuspension) !== void 0) {
5721
+ resumeAfterRetention();
5722
+ return Option.none();
5723
+ }
5699
5724
  approvalDecisionIntents = (yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId }))).approvalDecisions;
5700
5725
  continue;
5701
5726
  }
@@ -5760,45 +5785,55 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
5760
5785
  tokenRef
5761
5786
  });
5762
5787
  }, Effect.uninterruptible);
5763
- const processThreadHead = (resolve, threadId, options) => Effect.scoped(Effect.gen(function* () {
5764
- const claimed = yield* acquireClaim(threadId);
5765
- if (Option.isNone(claimed)) return Option.none();
5766
- const { claim, tokenRef } = claimed.value;
5767
- const attributes = {
5768
- threadId,
5769
- submissionId: claim.submissionId,
5770
- attemptId: claim.attemptId
5771
- };
5772
- yield* Effect.annotateCurrentSpan(attributes);
5773
- yield* Effect.annotateLogsScoped(attributes);
5774
- yield* hit("claim:after-claim");
5775
- const found = yield* ledger.lookup(SubmissionLookupById.make({ submissionId: claim.submissionId }));
5776
- if (Option.isNone(found)) return yield* LedgerError.make({
5777
- operation: "processThreadHead",
5778
- message: `Claimed unknown Submission ${claim.submissionId}`
5779
- });
5780
- const submission = found.value;
5781
- if (submission.parentLinkage !== void 0 && submission.state === "admitted") {
5782
- if (!(yield* readAllTolerant(threadId, [])).records.some((envelope) => envelope.record.payload._tag === "SubagentLineageRecorded")) {
5783
- yield* ledger.releaseOwnership(ReleaseOwnershipRequest.make({
5784
- submissionId: claim.submissionId,
5785
- ownershipToken: claim.ownershipToken
5786
- })).pipe(Effect.catchTag("OwnershipLost", () => Effect.void));
5787
- const parent = yield* ledger.lookup(SubmissionLookupById.make({ submissionId: submission.parentLinkage.parentSubmissionId }));
5788
- if (Option.isSome(parent)) yield* wake.notify(parent.value.threadId);
5789
- return Option.none();
5788
+ const processThreadHead = (resolve, threadId, options) => Effect.gen(function* () {
5789
+ let resumeAfterRetention = false;
5790
+ const attempt = Effect.scoped(Effect.gen(function* () {
5791
+ const claimed = yield* acquireClaim(threadId);
5792
+ if (Option.isNone(claimed)) return Option.none();
5793
+ const { claim, tokenRef } = claimed.value;
5794
+ const attributes = {
5795
+ threadId,
5796
+ submissionId: claim.submissionId,
5797
+ attemptId: claim.attemptId
5798
+ };
5799
+ yield* Effect.annotateCurrentSpan(attributes);
5800
+ yield* Effect.annotateLogsScoped(attributes);
5801
+ yield* hit("claim:after-claim");
5802
+ const found = yield* ledger.lookup(SubmissionLookupById.make({ submissionId: claim.submissionId }));
5803
+ if (Option.isNone(found)) return yield* LedgerError.make({
5804
+ operation: "processThreadHead",
5805
+ message: `Claimed unknown Submission ${claim.submissionId}`
5806
+ });
5807
+ const submission = found.value;
5808
+ if (submission.parentLinkage !== void 0 && submission.state === "admitted") {
5809
+ if (!(yield* readAllTolerant(threadId, [])).records.some((envelope) => envelope.record.payload._tag === "SubagentLineageRecorded")) {
5810
+ yield* ledger.releaseOwnership(ReleaseOwnershipRequest.make({
5811
+ submissionId: claim.submissionId,
5812
+ ownershipToken: claim.ownershipToken
5813
+ })).pipe(Effect.catchTag("OwnershipLost", () => Effect.void));
5814
+ const parent = yield* ledger.lookup(SubmissionLookupById.make({ submissionId: submission.parentLinkage.parentSubmissionId }));
5815
+ if (Option.isSome(parent)) yield* wake.notify(parent.value.threadId);
5816
+ return Option.none();
5817
+ }
5790
5818
  }
5819
+ const resolution = yield* resolve(submission).pipe(Effect.map((binding) => ({
5820
+ _tag: "resolved",
5821
+ binding
5822
+ })), Effect.catchTags({ BindingUnavailable: (failure) => Effect.succeed({
5823
+ _tag: "refused",
5824
+ failure
5825
+ }) }));
5826
+ if (resolution._tag === "refused") return yield* resolution.failure;
5827
+ return yield* resolution.binding.attempt((agent, attemptThreadId, attemptClaim) => runAttempt(agent, attemptThreadId, attemptClaim, tokenRef, () => {
5828
+ resumeAfterRetention = true;
5829
+ }, options?.yieldAfter), threadId, claim);
5830
+ }));
5831
+ while (true) {
5832
+ resumeAfterRetention = false;
5833
+ const settlement = yield* attempt;
5834
+ if (!resumeAfterRetention) return settlement;
5791
5835
  }
5792
- const resolution = yield* resolve(submission).pipe(Effect.map((binding) => ({
5793
- _tag: "resolved",
5794
- binding
5795
- })), Effect.catchTags({ BindingUnavailable: (failure) => Effect.succeed({
5796
- _tag: "refused",
5797
- failure
5798
- }) }));
5799
- if (resolution._tag === "refused") return yield* resolution.failure;
5800
- return yield* resolution.binding.attempt((agent, attemptThreadId, attemptClaim) => runAttempt(agent, attemptThreadId, attemptClaim, tokenRef, options?.yieldAfter), threadId, claim);
5801
- })).pipe(withThreadHeadSpan);
5836
+ }).pipe(withThreadHeadSpan);
5802
5837
  const eligibleThreadHead = (threadId) => Stream.runHead(ledger.scanNonterminal.pipe(Stream.filter((entry) => entry.threadId === threadId), Stream.filterEffect((entry) => entry.state !== "unknown" ? Effect.succeed(true) : ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId: entry.submissionId })).pipe(Effect.map((snapshot) => snapshot.abortIntent !== void 0)))));
5803
5838
  const drainThread = (resolve, threadId) => Effect.gen(function* () {
5804
5839
  const settlements = [];
@@ -7021,6 +7056,6 @@ var DurableAgentRuntime = class DurableAgentRuntime extends Context.Service()("@
7021
7056
  static layer = DurableAgentRuntime.layerWithServices.pipe(Layer.provide([RunContextPreparationPassthrough, RunToolAuthorization.allowAll]));
7022
7057
  };
7023
7058
  //#endregion
7024
- export { RecoveryBlocked as a, RecoverySweepResult as c, recoveryRepairBatchId as d, recoveryRepairRecordId as f, DurableRuntimeConfig as i, childReservationIdFor as l, threadCreatedRecordId as m, DurableAgentRuntime_exports as n, RecoveryFailure as o, threadCreatedBatchId as p, DurableApprovalResolver as r, RecoveryReport as s, DurableAgentRuntime as t, isolateRecovery as u };
7059
+ export { DurableApprovalSuspension as a, RecoveryFailure as c, childReservationIdFor as d, isolateRecovery as f, threadCreatedRecordId as g, threadCreatedBatchId as h, 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 };
7025
7060
 
7026
- //# sourceMappingURL=DurableAgentRuntime-DQqxmn2h.mjs.map
7061
+ //# sourceMappingURL=DurableAgentRuntime-B-9w7jDt.mjs.map