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

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 (105) hide show
  1. package/dist/{Admin-BbTZHSLu.d.mts → Admin-DWDYlvvZ.d.mts} +15 -19
  2. package/dist/{Agent-BCyrGaWg.d.mts → Agent-ZfnNCQXs.d.mts} +2 -2
  3. package/dist/{AgentPolicy-CnXWWwdg.d.mts → AgentPolicy-B4oH8TbG.d.mts} +13 -1
  4. package/dist/{AgentRuntime-D4eoBpIW.mjs → AgentRuntime-CVMHysXm.mjs} +41 -7
  5. package/dist/AgentRuntime-CVMHysXm.mjs.map +1 -0
  6. package/dist/{AgentRuntime-BPlAn5nA.d.mts → AgentRuntime-D1MmB_0z.d.mts} +10 -10
  7. package/dist/{ContextCompactor-CPlStZRc.d.mts → ContextCompactor-BoKQOjr5.d.mts} +2 -2
  8. package/dist/{Digest-CNHImGy0.d.mts → Digest-COAt3Orl.d.mts} +2 -2
  9. package/dist/{DurableAgentRuntime-eImXoGqD.mjs → DurableAgentRuntime-C7A5guvq.mjs} +12 -21
  10. package/dist/{DurableAgentRuntime-eImXoGqD.mjs.map → DurableAgentRuntime-C7A5guvq.mjs.map} +1 -1
  11. package/dist/{EventSource-CETtQTiH.d.mts → EventSource-BfNZBG4A.d.mts} +3 -3
  12. package/dist/{Messaging-Dkg87ebg.d.mts → Messaging-7VXQnWI3.d.mts} +2 -2
  13. package/dist/{Messaging-B1zumorg.d.mts → Messaging-CICd_CSi.d.mts} +4 -4
  14. package/dist/{MessagingHost-B4jqlJmx.d.mts → MessagingHost-DXwWnrMh.d.mts} +4 -4
  15. package/dist/{Output-WL7JexCm.d.mts → Output-CY7NZByV.d.mts} +2 -2
  16. package/dist/{PreparedInputAdmission-Swp9t800.d.mts → PreparedInputAdmission-VStpn8u2.d.mts} +4 -4
  17. package/dist/{Records-BxGWRs-t.d.mts → Records-Bm4Qt70a.d.mts} +3 -3
  18. package/dist/{RunEventSink-DsbcGXog.d.mts → RunEventSink-9CUdI9Ar.d.mts} +2 -2
  19. package/dist/{RunOptions-GjDlAuKh.d.mts → RunOptions-BHmBa05n.d.mts} +6 -6
  20. package/dist/{Schedule-B94iS2X3.d.mts → Schedule-Bi_XVKLF.d.mts} +2 -2
  21. package/dist/{Subagent-CLaMeZKu.d.mts → Subagent-D59om8SR.d.mts} +11 -13
  22. package/dist/{Subagent-211Oz2IN.mjs → Subagent-DH6G120f.mjs} +3 -6
  23. package/dist/Subagent-DH6G120f.mjs.map +1 -0
  24. package/dist/{SubagentContract-DdT7Cqe6.d.mts → SubagentContract-tyN9v-Jv.d.mts} +3 -7
  25. package/dist/{SubagentHost--HBuY8fF.d.mts → SubagentHost-VTyf_wEF.d.mts} +6 -6
  26. package/dist/{Subscription-DaMCppa_.d.mts → Subscription-Bx1ZRRVS.d.mts} +6 -6
  27. package/dist/{SubscriptionInput-B0ZtrQoY.d.mts → SubscriptionInput-B5k5vb1S.d.mts} +3 -3
  28. package/dist/{Worker-2r2zGDkh.d.mts → Worker-XEBYxRQv.d.mts} +3 -3
  29. package/dist/capabilities/Commands.d.mts +1 -1
  30. package/dist/capabilities/ContextTools.d.mts +1 -135
  31. package/dist/capabilities/ContextTools.mjs +1 -40
  32. package/dist/capabilities/ContextTools.mjs.map +1 -1
  33. package/dist/capabilities/Messaging.d.mts +2 -2
  34. package/dist/capabilities/RunHooks.d.mts +1 -1
  35. package/dist/capabilities/Subagent.d.mts +4 -4
  36. package/dist/capabilities/Subagent.mjs +2 -2
  37. package/dist/capabilities/SubagentReservations.d.mts +1 -1
  38. package/dist/core/Agent.d.mts +1 -1
  39. package/dist/core/AgentPolicy.d.mts +1 -1
  40. package/dist/core/AgentPolicy.mjs +6 -0
  41. package/dist/core/AgentPolicy.mjs.map +1 -1
  42. package/dist/core/SubagentContract.d.mts +2 -2
  43. package/dist/core/SubagentContract.mjs +1 -7
  44. package/dist/core/SubagentContract.mjs.map +1 -1
  45. package/dist/core/Worker.d.mts +2 -2
  46. package/dist/durable/ActivityStore.d.mts +1 -1
  47. package/dist/durable/Admin.d.mts +1 -1
  48. package/dist/durable/AgentRegistration.d.mts +1 -1
  49. package/dist/durable/Certification.d.mts +1 -1
  50. package/dist/durable/CommittedActivity.d.mts +3 -3
  51. package/dist/durable/Digest.d.mts +1 -1
  52. package/dist/durable/DurableAgentRuntime.d.mts +1 -1
  53. package/dist/durable/DurableAgentRuntime.mjs +1 -1
  54. package/dist/durable/EventSource.d.mts +1 -1
  55. package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
  56. package/dist/durable/LifecyclePublication.d.mts +1 -1
  57. package/dist/durable/MessageDelivery.d.mts +6 -6
  58. package/dist/durable/MessageDeliveryStoreConformance.d.mts +43 -43
  59. package/dist/durable/PersistentHistory.d.mts +1 -1
  60. package/dist/durable/PreparedInputAdmission.d.mts +1 -1
  61. package/dist/durable/Records.d.mts +1 -1
  62. package/dist/durable/Recovery.d.mts +1 -1
  63. package/dist/durable/RunJournal.d.mts +1 -1
  64. package/dist/durable/Schedule.d.mts +1 -1
  65. package/dist/durable/ScheduleStoreConformance.d.mts +1 -1
  66. package/dist/durable/ScheduleTransition.d.mts +1 -1
  67. package/dist/durable/Scheduling.d.mts +3 -3
  68. package/dist/durable/SubmissionLedger.d.mts +1 -1
  69. package/dist/durable/SubmissionLedgerConformance.d.mts +2 -2
  70. package/dist/durable/SubmissionStatus.d.mts +1 -1
  71. package/dist/durable/Subscription.d.mts +1 -1
  72. package/dist/durable/SubscriptionInput.d.mts +1 -1
  73. package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
  74. package/dist/durable/SubscriptionTools.d.mts +4 -4
  75. package/dist/durable/SubscriptionTransition.d.mts +1 -1
  76. package/dist/durable/Subscriptions.d.mts +6 -6
  77. package/dist/durable/ThreadContextHistory.d.mts +1 -1
  78. package/dist/durable/ThreadContextHistoryProjection.d.mts +1 -1
  79. package/dist/durable/ThreadInvariants.d.mts +2 -2
  80. package/dist/durable/ThreadProjection.d.mts +1 -1
  81. package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
  82. package/dist/durable/ThreadStore.d.mts +1 -1
  83. package/dist/durable/ThreadStoreConformance.d.mts +1 -1
  84. package/dist/durable/WorkerAdmission.d.mts +4 -4
  85. package/dist/durable/WorkerHost.d.mts +6 -6
  86. package/dist/engine/AgentRuntime.d.mts +1 -1
  87. package/dist/engine/AgentRuntime.mjs +1 -1
  88. package/dist/engine/Compaction.d.mts +1 -1
  89. package/dist/engine/ContextCompactor.d.mts +1 -1
  90. package/dist/engine/MessagingHost.d.mts +1 -1
  91. package/dist/engine/Output.d.mts +1 -1
  92. package/dist/engine/RunEventSink.d.mts +1 -1
  93. package/dist/engine/RunOptions.d.mts +1 -1
  94. package/dist/engine/SubagentHost.d.mts +1 -1
  95. package/dist/index.d.mts +21 -21
  96. package/dist/index.mjs +3 -3
  97. package/package.json +1 -1
  98. package/src/capabilities/ContextTools.ts +0 -55
  99. package/src/capabilities/Subagent.ts +0 -3
  100. package/src/core/AgentPolicy.ts +6 -0
  101. package/src/core/SubagentContract.ts +0 -7
  102. package/src/durable/DurableAgentRuntime.ts +21 -112
  103. package/src/engine/internal/agent-runtime.ts +86 -15
  104. package/dist/AgentRuntime-D4eoBpIW.mjs.map +0 -1
  105. package/dist/Subagent-211Oz2IN.mjs.map +0 -1
@@ -16,6 +16,7 @@ import {
16
16
  PubSub,
17
17
  Queue,
18
18
  Result,
19
+ Schedule,
19
20
  Schema,
20
21
  SchemaAST,
21
22
  SchemaGetter,
@@ -3965,6 +3966,31 @@ const snapshotCompactionMessages = Effect.fnUntraced(function* (
3965
3966
  });
3966
3967
  });
3967
3968
 
3969
+ const HttpStatus = AiError.HttpResponseDetails.fields.status.check(
3970
+ Schema.isBetween({ minimum: 100, maximum: 599 }),
3971
+ );
3972
+
3973
+ const decodeHttpErrorPayload = Schema.decodeUnknownOption(
3974
+ Schema.Union([Schema.Struct({ code: HttpStatus }), Schema.Struct({ status: HttpStatus })]),
3975
+ );
3976
+
3977
+ /** Native error parts carry unknown payloads; classify only validated HTTP statuses. */
3978
+ const isTransientErrorPayload = (error: Response.ErrorPart["error"]): boolean =>
3979
+ Option.exists(
3980
+ decodeHttpErrorPayload(error),
3981
+ (payload) =>
3982
+ AiError.reasonFromHttpStatus({ status: "code" in payload ? payload.code : payload.status })
3983
+ .isRetryable,
3984
+ );
3985
+
3986
+ /** Content streamed before a failure makes the call unsafe to repeat. */
3987
+ const hasStreamedContent = (trace: TurnTrace): boolean =>
3988
+ trace.toolCalls.size > 0 ||
3989
+ trace.parts.some((part) => part.type !== "response-metadata" && part.type !== "error");
3990
+
3991
+ const MODEL_RETRY_BASE = Duration.seconds(1);
3992
+ const MODEL_RETRY_MAX_DELAY = Duration.seconds(30);
3993
+
3968
3994
  /** Text a provider overflow classification matches against (message + reason). */
3969
3995
  const overflowText = (error: AiError.AiError): string => `${error.message} ${error.reason.message}`;
3970
3996
 
@@ -5588,6 +5614,12 @@ const makeTurn = <
5588
5614
  .map((entry) => entry.tool)),
5589
5615
  ) as unknown as Toolkit.Toolkit<Tools>;
5590
5616
 
5617
+ // Hosted tools may execute before emitting a response part. Only readonly
5618
+ // hosted tools are safe to repeat after a failure or joined-input restart.
5619
+ const canRepeatModelCall = !Object.values(modelToolkit.tools).some(
5620
+ (tool) => Tool.isProviderDefined(tool) && !Context.get(tool.annotations, Tool.Readonly),
5621
+ );
5622
+
5591
5623
  if (options.durability !== undefined && snapshot !== undefined) {
5592
5624
  if (
5593
5625
  options.durability.noteToolExposure === undefined &&
@@ -6462,11 +6494,59 @@ const makeTurn = <
6462
6494
  ),
6463
6495
  );
6464
6496
 
6497
+ // Retry after part processing: metadata emits no events, so it cannot reset
6498
+ // Stream.retry's schedule. Content makes the response ineligible for retry.
6499
+ const attemptWithRetries = Stream.suspend(() => attempt(compactedOutgoing())).pipe(
6500
+ Stream.retry(($) =>
6501
+ $(Schedule.exponential(MODEL_RETRY_BASE)).pipe(
6502
+ Schedule.upTo({ times: policy.modelRetries ?? 0 }),
6503
+ Schedule.while(({ input: error }) => {
6504
+ const lastPart = trace.parts.at(-1);
6505
+
6506
+ return (
6507
+ canRepeatModelCall &&
6508
+ !hasStreamedContent(trace) &&
6509
+ ((lastPart?.type === "error" && isTransientErrorPayload(lastPart.error)) ||
6510
+ (AiError.isAiError(error) && error.isRetryable))
6511
+ );
6512
+ }),
6513
+ Schedule.modifyDelay(({ input: error, duration }) => {
6514
+ const backoff = Duration.min(duration, MODEL_RETRY_MAX_DELAY);
6515
+ const retryAfter = AiError.isAiError(error) ? error.retryAfter : undefined;
6516
+
6517
+ return Effect.succeed(
6518
+ retryAfter === undefined ? backoff : Duration.max(backoff, retryAfter),
6519
+ );
6520
+ }),
6521
+ Schedule.tap(({ input: error, attempt: retry, duration }) =>
6522
+ Effect.gen(function* () {
6523
+ trace.parts.length = 0;
6524
+ trace.responsePartCount = 0;
6525
+ trace.responsePartBytes = 0;
6526
+ // The failed attempt's usage was already retained on exit.
6527
+ trace.usage = undefined;
6528
+ delete trace.response;
6529
+ delete trace.finishMetadata;
6530
+ yield* Effect.logWarning("agent model call retrying").pipe(
6531
+ Effect.annotateLogs({
6532
+ runId: context.runId,
6533
+ turnId,
6534
+ retry,
6535
+ delayMillis: Duration.toMillis(duration),
6536
+ error: errorMessage(error),
6537
+ }),
6538
+ );
6539
+ }),
6540
+ ),
6541
+ ),
6542
+ ),
6543
+ );
6544
+
6465
6545
  // RUN-027: one summarize-and-retry for a classified provider context
6466
6546
  // overflow when compaction is configured; every other provider error
6467
6547
  // propagates unchanged. A response that already streamed parts mutated
6468
6548
  // the trace, so it is never retried.
6469
- const response = attempt(compactedOutgoing()).pipe(
6549
+ const response = attemptWithRetries.pipe(
6470
6550
  Stream.catch(
6471
6551
  (
6472
6552
  error,
@@ -6475,10 +6555,7 @@ const makeTurn = <
6475
6555
  AgentRuntimeFailure<typeof agent, HookError, InstructionError>,
6476
6556
  InterpreterRequirements<typeof agent, HookRequirements, InstructionRequirements>
6477
6557
  > => {
6478
- if (
6479
- !(error instanceof AiError.AiError) ||
6480
- !isContextOverflowMessage(overflowText(error))
6481
- ) {
6558
+ if (!AiError.isAiError(error) || !isContextOverflowMessage(overflowText(error))) {
6482
6559
  return Stream.fail(error);
6483
6560
  }
6484
6561
  const message = overflowText(error);
@@ -6514,8 +6591,7 @@ const makeTurn = <
6514
6591
  .pipe(
6515
6592
  Effect.mapError(
6516
6593
  (inner): AgentRuntimeFailure<typeof agent, HookError, InstructionError> =>
6517
- inner instanceof AiError.AiError &&
6518
- isContextOverflowMessage(overflowText(inner))
6594
+ AiError.isAiError(inner) && isContextOverflowMessage(overflowText(inner))
6519
6595
  ? ContextOverflowError.make({
6520
6596
  message: overflowText(inner),
6521
6597
  retried: true,
@@ -6540,10 +6616,9 @@ const makeTurn = <
6540
6616
 
6541
6617
  // The retried call is outside the outer catch: a second
6542
6618
  // classified overflow converts here, typed, no retry.
6543
- const retried: TurnStream = attempt(compactedOutgoing()).pipe(
6619
+ const retried: TurnStream = attemptWithRetries.pipe(
6544
6620
  Stream.catch((again): TurnStream =>
6545
- again instanceof AiError.AiError &&
6546
- isContextOverflowMessage(overflowText(again))
6621
+ AiError.isAiError(again) && isContextOverflowMessage(overflowText(again))
6547
6622
  ? Stream.fail(
6548
6623
  ContextOverflowError.make({
6549
6624
  message: overflowText(again),
@@ -7149,15 +7224,11 @@ const makeTurn = <
7149
7224
 
7150
7225
  // Only the model stream is cancellable. It resolves no application Tools and
7151
7226
  // closes its waiter before continuation can commit a response or start a Handler.
7152
- // Hosted effects may happen before reporting a part. Only Tools explicitly
7153
- // annotated Readonly are safe to discard and repeat.
7154
7227
  const restartSignal =
7155
7228
  policy.restartOnJoinedInput === true &&
7156
7229
  context.modelRestarts < 2 &&
7157
7230
  (options.durability === undefined || options.durability.commitModelRestart !== undefined) &&
7158
- !Object.values(modelToolkit.tools).some(
7159
- (tool) => Tool.isProviderDefined(tool) && !Context.get(tool.annotations, Tool.Readonly),
7160
- )
7231
+ canRepeatModelCall
7161
7232
  ? options.input?.awaitJoin
7162
7233
  : undefined;
7163
7234