eve 0.27.0 → 0.27.2

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 (177) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/src/channel/resolve-active-session.d.ts +4 -0
  3. package/dist/src/channel/resolve-active-session.js +1 -0
  4. package/dist/src/channel/routes.d.ts +11 -0
  5. package/dist/src/chunks/{use-eve-agent-PMY2WkAt.js → use-eve-agent-CbF0l_Fp.js} +66 -27
  6. package/dist/src/chunks/{use-eve-agent-AeQLLhu9.js → use-eve-agent-CgxB9WQv.js} +66 -27
  7. package/dist/src/cli/dev/tui/vercel-trusted-sources-policy.d.ts +1 -1
  8. package/dist/src/cli/dev/tui/vercel-trusted-sources.js +1 -1
  9. package/dist/src/client/index.d.ts +1 -1
  10. package/dist/src/client/open-stream.d.ts +15 -2
  11. package/dist/src/client/open-stream.js +1 -1
  12. package/dist/src/client/session.d.ts +3 -2
  13. package/dist/src/client/session.js +1 -1
  14. package/dist/src/client/types.d.ts +32 -0
  15. package/dist/src/compiled/.vendor-stamp.json +16 -16
  16. package/dist/src/compiled/@ai-sdk/anthropic/index.js +2 -2
  17. package/dist/src/compiled/@ai-sdk/google/index.d.ts +9 -2
  18. package/dist/src/compiled/@ai-sdk/google/index.js +6 -6
  19. package/dist/src/compiled/@ai-sdk/mcp/index.d.ts +18 -3
  20. package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
  21. package/dist/src/compiled/@ai-sdk/openai/index.d.ts +285 -24
  22. package/dist/src/compiled/@ai-sdk/openai/index.js +2 -2
  23. package/dist/src/compiled/@ai-sdk/otel/index.js +1 -1
  24. package/dist/src/compiled/@ai-sdk/provider-utils/index.d.ts +7 -3
  25. package/dist/src/compiled/@vercel/oidc/index.js +28 -2
  26. package/dist/src/compiled/@vercel/sandbox/api-client/api-client.d.ts +11 -0
  27. package/dist/src/compiled/@vercel/sandbox/api-client/validators.d.ts +7 -0
  28. package/dist/src/compiled/@vercel/sandbox/command.d.ts +8 -0
  29. package/dist/src/compiled/@vercel/sandbox/execution-context.d.ts +116 -0
  30. package/dist/src/compiled/@vercel/sandbox/index.d.ts +3 -1
  31. package/dist/src/compiled/@vercel/sandbox/index.js +20 -19
  32. package/dist/src/compiled/@vercel/sandbox/network-policy.d.ts +13 -5
  33. package/dist/src/compiled/@vercel/sandbox/sandbox-user.d.ts +212 -0
  34. package/dist/src/compiled/@vercel/sandbox/sandbox.d.ts +133 -2
  35. package/dist/src/compiled/@vercel/sandbox/session.d.ts +2 -1
  36. package/dist/src/compiled/@vercel/sandbox/snapshot.d.ts +1 -1
  37. package/dist/src/compiled/@workflow/core/create-hook.d.ts +41 -22
  38. package/dist/src/compiled/@workflow/core/flushable-stream.d.ts +29 -0
  39. package/dist/src/compiled/@workflow/core/global.d.ts +2 -0
  40. package/dist/src/compiled/@workflow/core/index.js +2 -2
  41. package/dist/src/compiled/@workflow/core/private.d.ts +6 -17
  42. package/dist/src/compiled/@workflow/core/private.js +1 -1
  43. package/dist/src/compiled/@workflow/core/replay-payload-cache.d.ts +56 -0
  44. package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +11 -0
  45. package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +6 -4
  46. package/dist/src/compiled/@workflow/core/runtime/resume-hook.d.ts +4 -1
  47. package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +39 -0
  48. package/dist/src/compiled/@workflow/core/runtime.js +3 -3
  49. package/dist/src/compiled/@workflow/core/serialization.d.ts +44 -4
  50. package/dist/src/compiled/@workflow/core/symbols.d.ts +13 -0
  51. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  52. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  53. package/dist/src/compiled/@workflow/errors/error-codes.d.ts +2 -0
  54. package/dist/src/compiled/@workflow/errors/index.d.ts +14 -0
  55. package/dist/src/compiled/@workflow/errors/index.js +1 -1
  56. package/dist/src/compiled/@workflow/world/events.d.ts +15 -0
  57. package/dist/src/compiled/@workflow/world/hooks.d.ts +2 -1
  58. package/dist/src/compiled/@workflow/world/interfaces.d.ts +77 -4
  59. package/dist/src/compiled/@workflow/world-local/index.js +4 -4
  60. package/dist/src/compiled/@workflow/world-vercel/index.js +16 -16
  61. package/dist/src/compiled/_chunks/node/{auth-BuQkq4Gr.js → auth-l7F2PF2b.js} +2 -2
  62. package/dist/src/compiled/_chunks/node/{version-DD-FX9rK.js → version-CjHTLx2a.js} +1 -1
  63. package/dist/src/compiled/_chunks/node/virtual-loader-Cwgujv7l.js +1 -0
  64. package/dist/src/compiled/_chunks/workflow/attribute-changes-Dk1fP6vt.js +20 -0
  65. package/dist/src/compiled/_chunks/workflow/{chunk-BHKSVoKr.js → chunk-BTyA9uPd.js} +1 -1
  66. package/dist/src/compiled/_chunks/workflow/dist-B3qkUnLJ.js +3 -0
  67. package/dist/src/compiled/_chunks/workflow/{dist-CSfKNxQW.js → dist-BX517Nmz.js} +2 -2
  68. package/dist/src/compiled/_chunks/workflow/{dist-zLevmMyU.js → dist-C_VDTghO.js} +10 -10
  69. package/dist/src/compiled/_chunks/workflow/{dist-CttsoN4D.js → dist-CrxV2rsR.js} +1 -1
  70. package/dist/src/compiled/_chunks/workflow/{functions-PT9ri9Hu.js → functions-Dv8dc_-I.js} +1 -1
  71. package/dist/src/compiled/_chunks/workflow/resume-hook-czpG5xnP.js +1 -0
  72. package/dist/src/compiled/_chunks/workflow/run-6zaMjFY6.js +1 -0
  73. package/dist/src/compiled/_chunks/workflow/sleep-B2u06FWc.js +1 -0
  74. package/dist/src/compiled/_chunks/workflow/{src-CQuMexnO.js → src-D1EltLDA.js} +1 -1
  75. package/dist/src/compiled/_chunks/workflow/{token-CaY0nA5J.js → token-Cz223z3C.js} +1 -1
  76. package/dist/src/compiled/_chunks/workflow/token-DWqA5-DA.js +1 -0
  77. package/dist/src/compiled/_chunks/workflow/token-util-B6qBs3-0.js +27 -0
  78. package/dist/src/compiled/_chunks/workflow/{undici-fb54XL8i.js → undici-C2ZhYnV9.js} +1 -1
  79. package/dist/src/compiled/_chunks/workflow/wrapper-Cc2otuUR.js +6 -0
  80. package/dist/src/compiled/env-runner/index.js +1 -1
  81. package/dist/src/compiled/env-runner/node-worker.js +1 -1
  82. package/dist/src/compiled/eventsource-parser/stream/index.d.ts +16 -3
  83. package/dist/src/compiled/jose/index.js +1 -1
  84. package/dist/src/compiler/compile-from-memory.d.ts +5 -0
  85. package/dist/src/compiler/compile-from-memory.js +1 -1
  86. package/dist/src/compiler/extension-compatibility.d.ts +10 -10
  87. package/dist/src/compiler/extension-compatibility.js +1 -1
  88. package/dist/src/execution/deliver-payloads.d.ts +1 -1
  89. package/dist/src/execution/deliver-payloads.js +1 -1
  90. package/dist/src/execution/workflow-entry.js +1 -1
  91. package/dist/src/execution/workflow-steps.js +1 -1
  92. package/dist/src/harness/session-limit-continuation.d.ts +8 -0
  93. package/dist/src/harness/session-limit-continuation.js +1 -1
  94. package/dist/src/harness/session-limit-enforcement.d.ts +9 -6
  95. package/dist/src/harness/session-limit-enforcement.js +1 -1
  96. package/dist/src/harness/stale-input-responses.d.ts +21 -3
  97. package/dist/src/harness/stale-input-responses.js +2 -2
  98. package/dist/src/harness/tool-loop.js +2 -2
  99. package/dist/src/harness/turn-cancellation.d.ts +13 -0
  100. package/dist/src/harness/turn-cancellation.js +1 -1
  101. package/dist/src/internal/application/package.js +1 -1
  102. package/dist/src/internal/authored-module-evaluation-error.d.ts +2 -0
  103. package/dist/src/internal/authored-module-evaluation-error.js +4 -0
  104. package/dist/src/internal/authored-module-loader.js +2 -2
  105. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  106. package/dist/src/internal/workflow-bundle/vercel-workflow-output.js +1 -1
  107. package/dist/src/node_modules/.pnpm/@vercel_sdk@1.28.8/node_modules/@vercel/sdk/esm/models/updateprojectblock.js +1 -0
  108. package/dist/src/node_modules/.pnpm/@vercel_sdk@1.28.8/node_modules/@vercel/sdk/esm/models/updateprojectprojectsbranchmatcher.js +1 -0
  109. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  110. package/dist/src/public/channels/discord/defaults.js +1 -1
  111. package/dist/src/public/channels/eve.js +2 -1
  112. package/dist/src/public/channels/linear/api.d.ts +2 -0
  113. package/dist/src/public/channels/linear/api.js +3 -1
  114. package/dist/src/public/channels/linear/defaults.js +2 -2
  115. package/dist/src/public/channels/linear/hitl.d.ts +8 -13
  116. package/dist/src/public/channels/linear/hitl.js +3 -3
  117. package/dist/src/public/channels/linear/index.d.ts +1 -1
  118. package/dist/src/public/channels/linear/index.js +1 -1
  119. package/dist/src/public/channels/linear/linearChannel.js +1 -1
  120. package/dist/src/public/channels/slack/api.d.ts +46 -2
  121. package/dist/src/public/channels/slack/api.js +1 -1
  122. package/dist/src/public/channels/slack/attachments.d.ts +6 -5
  123. package/dist/src/public/channels/slack/defaults.js +1 -1
  124. package/dist/src/public/channels/slack/inbound.d.ts +31 -0
  125. package/dist/src/public/channels/slack/inbound.js +1 -1
  126. package/dist/src/public/channels/slack/index.d.ts +2 -2
  127. package/dist/src/public/channels/slack/interactions.d.ts +2 -1
  128. package/dist/src/public/channels/slack/interactions.js +1 -1
  129. package/dist/src/public/channels/slack/slackChannel.d.ts +118 -13
  130. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  131. package/dist/src/public/channels/slack/thread.d.ts +4 -3
  132. package/dist/src/public/channels/slack/thread.js +1 -1
  133. package/dist/src/public/channels/teams/defaults.js +2 -2
  134. package/dist/src/public/channels/teams/index.d.ts +1 -1
  135. package/dist/src/public/channels/teams/teamsChannel.d.ts +7 -2
  136. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  137. package/dist/src/public/channels/telegram/defaults.js +1 -1
  138. package/dist/src/public/definitions/channel.d.ts +1 -1
  139. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +2 -1
  140. package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
  141. package/dist/src/setup/scaffold/create/project.js +2 -2
  142. package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
  143. package/dist/src/setup/scaffold/create/web-template.js +90 -5
  144. package/dist/src/setup/scaffold/update/channels.js +2 -2
  145. package/dist/src/setup/scaffold/update/connections.js +1 -1
  146. package/dist/src/svelte/index.js +1 -1
  147. package/dist/src/svelte/use-eve-agent.js +1 -1
  148. package/dist/src/vue/index.js +1 -1
  149. package/dist/src/vue/use-eve-agent.js +1 -1
  150. package/docs/agent-config.md +10 -5
  151. package/docs/channels/slack.mdx +115 -12
  152. package/docs/channels/teams.mdx +10 -3
  153. package/docs/guides/client/streaming.mdx +15 -0
  154. package/docs/guides/deployment/vercel.mdx +1 -1
  155. package/docs/guides/frontend/overview.mdx +2 -0
  156. package/package.json +22 -22
  157. package/dist/src/compiled/@workflow/core/step-hydration-cache.d.ts +0 -148
  158. package/dist/src/compiled/_chunks/node/virtual-loader-B8K8w9cr.js +0 -1
  159. package/dist/src/compiled/_chunks/workflow/attribute-changes-CXiYB8h9.js +0 -20
  160. package/dist/src/compiled/_chunks/workflow/dist-BYo8Gno2.js +0 -3
  161. package/dist/src/compiled/_chunks/workflow/resume-hook-CHXbXuRZ.js +0 -1
  162. package/dist/src/compiled/_chunks/workflow/run-BjtAGa3_.js +0 -1
  163. package/dist/src/compiled/_chunks/workflow/sleep-BJAv0MFP.js +0 -1
  164. package/dist/src/compiled/_chunks/workflow/token-D4VIwGlD.js +0 -1
  165. package/dist/src/compiled/_chunks/workflow/wrapper-ulTvoTdW.js +0 -6
  166. package/dist/src/node_modules/.pnpm/@vercel_sdk@1.28.1/node_modules/@vercel/sdk/esm/models/updateprojectprojectsaction.js +0 -1
  167. package/dist/src/node_modules/.pnpm/@vercel_sdk@1.28.1/node_modules/@vercel/sdk/esm/models/updateprojectprojectsoptionsallowlist.js +0 -1
  168. /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/lib/primitives.js +0 -0
  169. /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/lib/schemas.js +0 -0
  170. /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/models/aclaction.js +0 -0
  171. /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/models/sdkvalidationerror.js +0 -0
  172. /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/defaultToZeroValue.js +0 -0
  173. /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/fp.js +0 -0
  174. /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/primitives.js +0 -0
  175. /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/rfcdate.js +0 -0
  176. /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/smartUnion.js +0 -0
  177. /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/unrecognized.js +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # eve
2
2
 
3
+ ## 0.27.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 6c433f4: Expose thread-scoped cancellation in Slack message and interaction contexts, plus target-addressed cancellation in `onEvent`, so authored Slack handlers can stop or replace in-flight turns.
8
+ - 835f076: Emit an initial NDJSON whitespace byte when opening a session event stream so clients and proxies receive the response body before the first durable event.
9
+ - f36f143: Added `thread.listParticipants()` for Slack thread routing based on the unique human participants in first-appearance order.
10
+ - eb92ee3: Allow `session.send()` and `session.stream()` callers to disable automatic stream reconnection with `streamReconnectPolicy: { reconnect: false }`, so relays and proxies can own cursor recovery and retry policy.
11
+ - 4133ffc: Slack thread helpers now reuse messages loaded within the same inbound handler, while overlapping `thread.refresh()` calls share one request and failed refreshes preserve the last successful snapshot.
12
+ - ee72db8: Messages posted by the installed Slack app are now ignored before reaching message hooks to prevent self-reply loops.
13
+ - bd4397b: Fixed Slack `threadContext` with `since: "last-agent-reply"` so only replies from the installed app move the context boundary. Replies from other bots remain part of the incremental thread context, are labeled `bot` instead of `agent` in the injected transcript, and their file uploads are now eligible for mention attachment lookback.
14
+ - 64dbe2b: Add actionable authored-module evaluation errors that identify installed packages and distinguish extensionless ESM from missing package output while preserving the original failure as the cause.
15
+
16
+ ## 0.27.1
17
+
18
+ ### Patch Changes
19
+
20
+ - eaaf6d6: Enable Workflow's optimistic concurrency precondition guard in every generated Vercel workflow function so stale replays reload concurrent events before committing.
21
+ - 6ded22e: Preserve every queued delivery's message, context, and input responses when eve batches payloads before routing.
22
+ - 3ffaf12: Added a Slack `onMessage` hook with `isBotMentioned()` and `isSubscribed()` helpers for custom message routing.
23
+ - 49f2f13: Report `connection_search` as failed when every targeted connection fails to load, including authorization startup failures, so tool-call observability preserves the underlying error. Requests for unregistered connections now fail instead of returning an empty result.
24
+ - 9679abc: Added an `isSubscribed()` helper to the Microsoft Teams `onMessage` hook for custom routing that can continue conversations without repeated mentions.
25
+ - 1a618ba: Add a generic Slack `onEvent` fallback for subscribed Events API callbacks. Handlers can use a Slack-bound `receive` function to start zero, one, or many agent turns while authored mention and direct-message handlers retain precedence.
26
+ - 0df8ab9: Update the bundled AI SDK and provider integrations to their latest compatible releases.
27
+ - 394b467: Update the bundled Vercel integrations and core execution utilities to their latest compatible releases.
28
+ - f2724fb: Update the Vite integration and Vitest test tooling to their latest compatible releases.
29
+ - 01552fc: Update the bundled Workflow runtime dependencies to their latest 5.0 beta releases.
30
+ - dd1ba23: Declining a session token-budget prompt now cancels the in-flight turn cleanly (`turn.cancelled` → `session.waiting`) instead of completing the session or surfacing an error to the delegating parent. Declining a delegated child's prompt cancels the whole turn tree from the root, so the parent can no longer retry the child against a fresh quota share, and stale answers to budget prompts are dropped instead of being shown to the model. The prompt copy is reworded ("This session has hit the input-token limit (2M) per session…") with Approve/Stop buttons.
31
+ - a70d4ce: Restart native progress feedback across built-in chat channels when a completed connection authorization resumes the agent session. Slack also shows an explicit connected and resuming status.
32
+ - d3cd770: Generated Web Chat apps now retain completed sessions for follow-up messages and cancel the active durable turn when Stop is clicked instead of only disconnecting the browser stream.
33
+
3
34
  ## 0.27.0
4
35
 
5
36
  ### Minor Changes
@@ -0,0 +1,4 @@
1
+ import type { ResolveActiveSessionFn } from "#channel/routes.js";
2
+ import type { Runtime } from "#channel/types.js";
3
+ /** Builds a channel-scoped lookup for the active owner of a continuation token. */
4
+ export declare function createResolveActiveSessionFn(runtime: Runtime, channelName: string): ResolveActiveSessionFn;
@@ -0,0 +1 @@
1
+ function createResolveActiveSessionFn(e,t){return({continuationToken:n})=>e.resolveSession(`${t}:${n}`)}export{createResolveActiveSessionFn};
@@ -17,6 +17,11 @@ type WebSocketHeaders = Headers | readonly (readonly [string, string])[] | Recor
17
17
  */
18
18
  export interface RouteHandlerArgs<TState = undefined> {
19
19
  send: SendFn<TState>;
20
+ /**
21
+ * Resolves the session currently owning a channel-local continuation token.
22
+ * This point-in-time lookup does not reserve the continuation.
23
+ */
24
+ resolveActiveSession: ResolveActiveSessionFn;
20
25
  cancel: CancelFn;
21
26
  getSession: GetSessionFn;
22
27
  /**
@@ -54,6 +59,12 @@ export interface SendPayload {
54
59
  * channels). Resolves to the resulting {@link Session}.
55
60
  */
56
61
  export type SendFn<TState = undefined> = (input: string | UserContent | SendPayload, options: SendOptions<TState>) => Promise<Session>;
62
+ /** Resolves the active owner of a channel-local continuation token. */
63
+ export type ResolveActiveSessionFn = (options: {
64
+ readonly continuationToken: string;
65
+ }) => Promise<{
66
+ readonly sessionId: string;
67
+ } | undefined>;
57
68
  type BaseSendOptions = {
58
69
  auth: SessionAuthContext | null;
59
70
  callback?: SessionCallback;
@@ -471,24 +471,58 @@ function formatSearch(searchParams) {
471
471
 
472
472
  //#endregion
473
473
  //#region src/client/open-stream.ts
474
- const STREAM_OPEN_RETRY_ATTEMPTS = 12;
475
- const STREAM_OPEN_RETRY_BASE_DELAY_MS = 250;
476
- const STREAM_OPEN_RETRY_MAX_DELAY_MS = 5e3;
477
- const STREAM_OPEN_RETRYABLE_STATUS = new Set([
478
- 404,
479
- 409,
480
- 425,
481
- 500,
482
- 502,
483
- 503,
484
- 504
485
- ]);
486
- const STREAM_RECONNECT_BASE_DELAY_MS = 250;
487
- const STREAM_RECONNECT_MAX_DELAY_MS = 4e3;
488
- const STREAM_MAX_IDLE_RECONNECTS = 5;
474
+ const DEFAULT_STREAM_RECONNECT_POLICY = {
475
+ retryableErrorStatuses: new Set([
476
+ 404,
477
+ 409,
478
+ 425,
479
+ 500,
480
+ 502,
481
+ 503,
482
+ 504
483
+ ]),
484
+ streamIdleReconnectPolicy: {
485
+ baseDelayMs: 250,
486
+ maxAttempts: 5,
487
+ maxDelayMs: 4e3
488
+ },
489
+ streamOpenReconnectPolicy: {
490
+ baseDelayMs: 250,
491
+ maxAttempts: 12,
492
+ maxDelayMs: 5e3
493
+ }
494
+ };
495
+ const NO_STREAM_RECONNECT_POLICY = {
496
+ ...DEFAULT_STREAM_RECONNECT_POLICY,
497
+ streamIdleReconnectPolicy: {
498
+ ...DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy,
499
+ maxAttempts: 0
500
+ },
501
+ streamOpenReconnectPolicy: {
502
+ ...DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy,
503
+ maxAttempts: 1
504
+ }
505
+ };
506
+ function resolveRetryPolicy(policy, defaults) {
507
+ return {
508
+ ...defaults,
509
+ ...policy
510
+ };
511
+ }
512
+ function resolveStreamReconnectPolicy(policy) {
513
+ if (policy && "reconnect" in policy && policy.reconnect === false) return NO_STREAM_RECONNECT_POLICY;
514
+ const configured = policy;
515
+ return {
516
+ retryableErrorStatuses: configured?.retryableErrorStatuses ? new Set(configured.retryableErrorStatuses) : DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses,
517
+ streamIdleReconnectPolicy: resolveRetryPolicy(configured?.streamIdleReconnectPolicy, DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy),
518
+ streamOpenReconnectPolicy: resolveRetryPolicy(configured?.streamOpenReconnectPolicy, DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy)
519
+ };
520
+ }
489
521
  async function* followStreamIterable(input) {
522
+ const retryPolicy = resolveStreamReconnectPolicy(input.streamReconnectPolicy);
523
+ const idleRetryPolicy = retryPolicy.streamIdleReconnectPolicy;
490
524
  let startIndex = input.startIndex;
491
- let reconnectDelayMs = STREAM_RECONNECT_BASE_DELAY_MS;
525
+ let reconnectDelayMs = idleRetryPolicy.baseDelayMs;
492
526
  let idleReconnects = 0;
493
527
  let initialConnection = true;
494
528
  while (true) {
@@ -496,6 +530,7 @@ async function* followStreamIterable(input) {
496
530
  try {
497
531
  body = await openStreamBody({
498
532
  ...input,
533
+ retryPolicy,
499
534
  startIndex
500
535
  });
501
536
  } catch (error) {
@@ -507,27 +542,29 @@ async function* followStreamIterable(input) {
507
542
  for await (const event of readNdjsonStream(body)) {
508
543
  startIndex += 1;
509
544
  deliveredEvent = true;
510
- reconnectDelayMs = STREAM_RECONNECT_BASE_DELAY_MS;
545
+ reconnectDelayMs = idleRetryPolicy.baseDelayMs;
511
546
  idleReconnects = 0;
512
547
  yield event;
513
548
  }
514
549
  } catch (error) {
515
550
  if (!isStreamDisconnectError(error)) throw error;
516
551
  }
517
- if (input.signal?.aborted || input.startIndex < 0) return;
518
- if (!deliveredEvent && !initialConnection && (idleReconnects += 1) >= STREAM_MAX_IDLE_RECONNECTS) return;
552
+ if (input.signal?.aborted || input.startIndex < 0 || idleRetryPolicy.maxAttempts === 0) return;
553
+ if (!deliveredEvent && !initialConnection && (idleReconnects += 1) >= idleRetryPolicy.maxAttempts) return;
519
554
  initialConnection = false;
520
555
  await sleep$1(reconnectDelayMs, input.signal);
521
556
  if (input.signal?.aborted) return;
522
- reconnectDelayMs = Math.min(reconnectDelayMs * 2, STREAM_RECONNECT_MAX_DELAY_MS);
557
+ reconnectDelayMs = Math.min(reconnectDelayMs * 2, idleRetryPolicy.maxDelayMs);
523
558
  }
524
559
  }
525
560
  async function openStreamBody(input) {
561
+ const retryPolicy = input.retryPolicy ?? DEFAULT_STREAM_RECONNECT_POLICY;
562
+ const openRetryPolicy = retryPolicy.streamOpenReconnectPolicy;
526
563
  let lastStatus;
527
564
  let lastBody;
528
565
  let lastHeaders;
529
- let retryDelayMs = STREAM_OPEN_RETRY_BASE_DELAY_MS;
530
- for (let attempt = 0; attempt < STREAM_OPEN_RETRY_ATTEMPTS; attempt += 1) {
566
+ let retryDelayMs = openRetryPolicy.baseDelayMs;
567
+ for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
531
568
  const url = createClientUrl(input.host, createEveMessageStreamRoutePath(input.sessionId), input.startIndex !== 0 ? { startIndex: String(input.startIndex) } : void 0);
532
569
  const headers = await input.resolveHeaders();
533
570
  let response;
@@ -538,9 +575,9 @@ async function openStreamBody(input) {
538
575
  signal: input.signal ?? null
539
576
  });
540
577
  } catch (error) {
541
- if (input.signal?.aborted || !isStreamDisconnectError(error) || attempt === STREAM_OPEN_RETRY_ATTEMPTS - 1) throw error;
578
+ if (input.signal?.aborted || !isStreamDisconnectError(error) || attempt === openRetryPolicy.maxAttempts - 1) throw error;
542
579
  await sleep$1(retryDelayMs, input.signal);
543
- retryDelayMs = Math.min(retryDelayMs * 2, STREAM_OPEN_RETRY_MAX_DELAY_MS);
580
+ retryDelayMs = Math.min(retryDelayMs * 2, openRetryPolicy.maxDelayMs);
544
581
  continue;
545
582
  }
546
583
  if (response.ok) {
@@ -550,10 +587,10 @@ async function openStreamBody(input) {
550
587
  lastStatus = response.status;
551
588
  lastBody = await response.text();
552
589
  lastHeaders = response.headers;
553
- if (!STREAM_OPEN_RETRYABLE_STATUS.has(response.status)) throw new ClientError(response.status, lastBody, response.headers);
554
- if (attempt < STREAM_OPEN_RETRY_ATTEMPTS - 1) {
590
+ if (!retryPolicy.retryableErrorStatuses.has(response.status)) throw new ClientError(response.status, lastBody, response.headers);
591
+ if (attempt < openRetryPolicy.maxAttempts - 1) {
555
592
  await sleep$1(retryDelayMs, input.signal);
556
- retryDelayMs = Math.min(retryDelayMs * 2, STREAM_OPEN_RETRY_MAX_DELAY_MS);
593
+ retryDelayMs = Math.min(retryDelayMs * 2, openRetryPolicy.maxDelayMs);
557
594
  }
558
595
  }
559
596
  throw new ClientError(lastStatus ?? 0, lastBody ?? "Failed to open message stream.", lastHeaders);
@@ -734,6 +771,7 @@ var ClientSession = class {
734
771
  host: this.#context.host,
735
772
  resolveHeaders: () => this.#context.resolveHeaders(input.headers),
736
773
  redirect: this.#context.redirect,
774
+ streamReconnectPolicy: input.streamReconnectPolicy,
737
775
  sessionId,
738
776
  signal: input.signal,
739
777
  startIndex: initialState.sessionId === sessionId ? initialState.streamIndex : 0
@@ -761,6 +799,7 @@ var ClientSession = class {
761
799
  host: this.#context.host,
762
800
  resolveHeaders: () => this.#context.resolveHeaders(),
763
801
  redirect: this.#context.redirect,
802
+ streamReconnectPolicy: options?.streamReconnectPolicy,
764
803
  sessionId,
765
804
  signal: options?.signal,
766
805
  startIndex: streamIndex
@@ -471,24 +471,58 @@ function formatSearch(searchParams) {
471
471
 
472
472
  //#endregion
473
473
  //#region src/client/open-stream.ts
474
- const STREAM_OPEN_RETRY_ATTEMPTS = 12;
475
- const STREAM_OPEN_RETRY_BASE_DELAY_MS = 250;
476
- const STREAM_OPEN_RETRY_MAX_DELAY_MS = 5e3;
477
- const STREAM_OPEN_RETRYABLE_STATUS = new Set([
478
- 404,
479
- 409,
480
- 425,
481
- 500,
482
- 502,
483
- 503,
484
- 504
485
- ]);
486
- const STREAM_RECONNECT_BASE_DELAY_MS = 250;
487
- const STREAM_RECONNECT_MAX_DELAY_MS = 4e3;
488
- const STREAM_MAX_IDLE_RECONNECTS = 5;
474
+ const DEFAULT_STREAM_RECONNECT_POLICY = {
475
+ retryableErrorStatuses: new Set([
476
+ 404,
477
+ 409,
478
+ 425,
479
+ 500,
480
+ 502,
481
+ 503,
482
+ 504
483
+ ]),
484
+ streamIdleReconnectPolicy: {
485
+ baseDelayMs: 250,
486
+ maxAttempts: 5,
487
+ maxDelayMs: 4e3
488
+ },
489
+ streamOpenReconnectPolicy: {
490
+ baseDelayMs: 250,
491
+ maxAttempts: 12,
492
+ maxDelayMs: 5e3
493
+ }
494
+ };
495
+ const NO_STREAM_RECONNECT_POLICY = {
496
+ ...DEFAULT_STREAM_RECONNECT_POLICY,
497
+ streamIdleReconnectPolicy: {
498
+ ...DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy,
499
+ maxAttempts: 0
500
+ },
501
+ streamOpenReconnectPolicy: {
502
+ ...DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy,
503
+ maxAttempts: 1
504
+ }
505
+ };
506
+ function resolveRetryPolicy(policy, defaults) {
507
+ return {
508
+ ...defaults,
509
+ ...policy
510
+ };
511
+ }
512
+ function resolveStreamReconnectPolicy(policy) {
513
+ if (policy && "reconnect" in policy && policy.reconnect === false) return NO_STREAM_RECONNECT_POLICY;
514
+ const configured = policy;
515
+ return {
516
+ retryableErrorStatuses: configured?.retryableErrorStatuses ? new Set(configured.retryableErrorStatuses) : DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses,
517
+ streamIdleReconnectPolicy: resolveRetryPolicy(configured?.streamIdleReconnectPolicy, DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy),
518
+ streamOpenReconnectPolicy: resolveRetryPolicy(configured?.streamOpenReconnectPolicy, DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy)
519
+ };
520
+ }
489
521
  async function* followStreamIterable(input) {
522
+ const retryPolicy = resolveStreamReconnectPolicy(input.streamReconnectPolicy);
523
+ const idleRetryPolicy = retryPolicy.streamIdleReconnectPolicy;
490
524
  let startIndex = input.startIndex;
491
- let reconnectDelayMs = STREAM_RECONNECT_BASE_DELAY_MS;
525
+ let reconnectDelayMs = idleRetryPolicy.baseDelayMs;
492
526
  let idleReconnects = 0;
493
527
  let initialConnection = true;
494
528
  while (true) {
@@ -496,6 +530,7 @@ async function* followStreamIterable(input) {
496
530
  try {
497
531
  body = await openStreamBody({
498
532
  ...input,
533
+ retryPolicy,
499
534
  startIndex
500
535
  });
501
536
  } catch (error) {
@@ -507,27 +542,29 @@ async function* followStreamIterable(input) {
507
542
  for await (const event of readNdjsonStream(body)) {
508
543
  startIndex += 1;
509
544
  deliveredEvent = true;
510
- reconnectDelayMs = STREAM_RECONNECT_BASE_DELAY_MS;
545
+ reconnectDelayMs = idleRetryPolicy.baseDelayMs;
511
546
  idleReconnects = 0;
512
547
  yield event;
513
548
  }
514
549
  } catch (error) {
515
550
  if (!isStreamDisconnectError(error)) throw error;
516
551
  }
517
- if (input.signal?.aborted || input.startIndex < 0) return;
518
- if (!deliveredEvent && !initialConnection && (idleReconnects += 1) >= STREAM_MAX_IDLE_RECONNECTS) return;
552
+ if (input.signal?.aborted || input.startIndex < 0 || idleRetryPolicy.maxAttempts === 0) return;
553
+ if (!deliveredEvent && !initialConnection && (idleReconnects += 1) >= idleRetryPolicy.maxAttempts) return;
519
554
  initialConnection = false;
520
555
  await sleep$1(reconnectDelayMs, input.signal);
521
556
  if (input.signal?.aborted) return;
522
- reconnectDelayMs = Math.min(reconnectDelayMs * 2, STREAM_RECONNECT_MAX_DELAY_MS);
557
+ reconnectDelayMs = Math.min(reconnectDelayMs * 2, idleRetryPolicy.maxDelayMs);
523
558
  }
524
559
  }
525
560
  async function openStreamBody(input) {
561
+ const retryPolicy = input.retryPolicy ?? DEFAULT_STREAM_RECONNECT_POLICY;
562
+ const openRetryPolicy = retryPolicy.streamOpenReconnectPolicy;
526
563
  let lastStatus;
527
564
  let lastBody;
528
565
  let lastHeaders;
529
- let retryDelayMs = STREAM_OPEN_RETRY_BASE_DELAY_MS;
530
- for (let attempt = 0; attempt < STREAM_OPEN_RETRY_ATTEMPTS; attempt += 1) {
566
+ let retryDelayMs = openRetryPolicy.baseDelayMs;
567
+ for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
531
568
  const url = createClientUrl(input.host, createEveMessageStreamRoutePath(input.sessionId), input.startIndex !== 0 ? { startIndex: String(input.startIndex) } : void 0);
532
569
  const headers = await input.resolveHeaders();
533
570
  let response;
@@ -538,9 +575,9 @@ async function openStreamBody(input) {
538
575
  signal: input.signal ?? null
539
576
  });
540
577
  } catch (error) {
541
- if (input.signal?.aborted || !isStreamDisconnectError(error) || attempt === STREAM_OPEN_RETRY_ATTEMPTS - 1) throw error;
578
+ if (input.signal?.aborted || !isStreamDisconnectError(error) || attempt === openRetryPolicy.maxAttempts - 1) throw error;
542
579
  await sleep$1(retryDelayMs, input.signal);
543
- retryDelayMs = Math.min(retryDelayMs * 2, STREAM_OPEN_RETRY_MAX_DELAY_MS);
580
+ retryDelayMs = Math.min(retryDelayMs * 2, openRetryPolicy.maxDelayMs);
544
581
  continue;
545
582
  }
546
583
  if (response.ok) {
@@ -550,10 +587,10 @@ async function openStreamBody(input) {
550
587
  lastStatus = response.status;
551
588
  lastBody = await response.text();
552
589
  lastHeaders = response.headers;
553
- if (!STREAM_OPEN_RETRYABLE_STATUS.has(response.status)) throw new ClientError(response.status, lastBody, response.headers);
554
- if (attempt < STREAM_OPEN_RETRY_ATTEMPTS - 1) {
590
+ if (!retryPolicy.retryableErrorStatuses.has(response.status)) throw new ClientError(response.status, lastBody, response.headers);
591
+ if (attempt < openRetryPolicy.maxAttempts - 1) {
555
592
  await sleep$1(retryDelayMs, input.signal);
556
- retryDelayMs = Math.min(retryDelayMs * 2, STREAM_OPEN_RETRY_MAX_DELAY_MS);
593
+ retryDelayMs = Math.min(retryDelayMs * 2, openRetryPolicy.maxDelayMs);
557
594
  }
558
595
  }
559
596
  throw new ClientError(lastStatus ?? 0, lastBody ?? "Failed to open message stream.", lastHeaders);
@@ -734,6 +771,7 @@ var ClientSession = class {
734
771
  host: this.#context.host,
735
772
  resolveHeaders: () => this.#context.resolveHeaders(input.headers),
736
773
  redirect: this.#context.redirect,
774
+ streamReconnectPolicy: input.streamReconnectPolicy,
737
775
  sessionId,
738
776
  signal: input.signal,
739
777
  startIndex: initialState.sessionId === sessionId ? initialState.streamIndex : 0
@@ -761,6 +799,7 @@ var ClientSession = class {
761
799
  host: this.#context.host,
762
800
  resolveHeaders: () => this.#context.resolveHeaders(),
763
801
  redirect: this.#context.redirect,
802
+ streamReconnectPolicy: options?.streamReconnectPolicy,
764
803
  sessionId,
765
804
  signal: options?.signal,
766
805
  startIndex: streamIndex
@@ -1,4 +1,4 @@
1
- import type { UpdateProjectCustomAllow, UpdateProjectTrustedSources } from "@vercel/sdk/models/updateprojectprojectsaction.js";
1
+ import type { UpdateProjectCustomAllow, UpdateProjectTrustedSources } from "@vercel/sdk/models/updateprojectblock.js";
2
2
  export type TrustedSourceEnvironmentRule = UpdateProjectCustomAllow;
3
3
  export interface TrustedSourceProject {
4
4
  readonly projectId: string;
@@ -1 +1 @@
1
- import{updateProjectTrustedSourcesFromJSON}from"../../../node_modules/.pnpm/@vercel_sdk@1.28.1/node_modules/@vercel/sdk/esm/models/updateprojectprojectsaction.js";import{trustedSourcesToJSON}from"../../../node_modules/.pnpm/@vercel_sdk@1.28.1/node_modules/@vercel/sdk/esm/models/updateprojectprojectsoptionsallowlist.js";import{array,object,string,unknown}from"../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js";import"../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js";import{planTrustedSourceAccess}from"./vercel-trusted-sources-policy.js";import{captureVercel}from"#setup/primitives/index.js";import{normalizeVercelApiResult}from"#setup/vercel-api-failure.js";const ProjectSchema=object({id:string().min(1),name:string().min(1),customEnvironments:array(object({slug:string().min(1)})).optional(),trustedSources:unknown().nullable().optional()});function parseJson(e){try{return JSON.parse(e)}catch{return}}function parseTrustedSources(t){let n=JSON.stringify(t);if(n===void 0)return;let r=updateProjectTrustedSourcesFromJSON(n);return r.ok?r.value:void 0}function parseProject(e){let t=ProjectSchema.safeParse(parseJson(e));if(!t.success)return;let{trustedSources:n,...r}=t.data;if(n==null)return r;let i=parseTrustedSources(n);return i===void 0?void 0:{...r,trustedSources:i}}const ProjectUpdateSchema=object({id:string().min(1)}),defaultDeps={captureVercel};function environmentLabel(e){switch(e){case`development`:return`Development`;case`preview`:return`Preview`;case`production`:return`Production`;default:return e}}function projectPolicyContext(e){return{projectId:e.id,customEnvironmentSlugs:e.customEnvironments?.map(({slug:e})=>e)??[]}}async function readProject(e){let t=await e.deps.captureVercel([`api`,`/v9/projects/${encodeURIComponent(e.projectId)}`,`--scope`,e.ownerId,`--raw`],{cwd:e.workspaceRoot,nonInteractive:!0,signal:e.signal});if(!t.ok)return{kind:`failed`,message:t.failure.message};let n=parseProject(t.stdout);return n===void 0||n.id!==e.projectId?{kind:`failed`,message:`Vercel returned an invalid project response.`}:{kind:`project`,project:n}}async function prepareVercelTrustedSourceAccess(e){let t={...defaultDeps,...e.deps},n=e.target.deployment,r=await readProject({deps:t,workspaceRoot:e.workspaceRoot,ownerId:n.ownerId,projectId:n.projectId,signal:e.signal});if(r.kind===`failed`)return{kind:`failed`,message:`Could not read Deployment Protection for ${n.projectName}: ${r.message}`};let{project:i}=r;if(planTrustedSourceAccess({project:projectPolicyContext(i),targetEnvironment:n.environment,trustedSources:i.trustedSources??void 0}).kind===`unchanged`)return{kind:`unchanged`};let a=environmentLabel(`development`),o=environmentLabel(n.environment);return await e.prompter.select({message:`Allow ${a} from ${i.name} to access ${o} deployments of ${i.name}?`,hintLayout:`stacked`,notices:[{tone:`warning`,text:`This changes Deployment Protection for ${i.name} until the Trusted Sources rule is removed.`}],options:[{value:`continue`,label:`Allow access`,hint:`Add ${a} → ${o} to Trusted Sources`},{value:`cancel`,label:`Cancel`,hint:`Leave Deployment Protection unchanged`}]})===`cancel`?{kind:`cancelled`}:{kind:`approved`,grant:{ownerId:n.ownerId,projectId:i.id,projectName:i.name,targetEnvironment:n.environment}}}async function applyVercelTrustedSourceAccess(e){let n={...defaultDeps,...e.deps},r=await readProject({deps:n,workspaceRoot:e.workspaceRoot,ownerId:e.grant.ownerId,projectId:e.grant.projectId,signal:e.signal});if(r.kind===`failed`)return{kind:`failed`,message:`Could not refresh Deployment Protection for ${e.grant.projectName}: ${r.message}`};let{project:i}=r,a=planTrustedSourceAccess({project:projectPolicyContext(i),targetEnvironment:e.grant.targetEnvironment,trustedSources:i.trustedSources??void 0});if(a.kind===`unchanged`)return{kind:`unchanged`};let o=normalizeVercelApiResult(await n.captureVercel([`api`,`/v9/projects/${encodeURIComponent(i.id)}`,`--scope`,e.grant.ownerId,`--method`,`PATCH`,`--field`,`trustedSources=${trustedSourcesToJSON(a.trustedSources)}`,`--raw`],{cwd:e.workspaceRoot,nonInteractive:!0,signal:e.signal}));if(!o.ok)return{kind:`failed`,message:`Could not update Trusted Sources for ${i.name}: ${o.failure.message}`};let s=ProjectUpdateSchema.safeParse(parseJson(o.stdout));return(s.success?s.data:void 0)?.id===i.id?{kind:`updated`,targetProjectName:i.name}:{kind:`failed`,message:`Vercel returned an invalid project response.`}}export{applyVercelTrustedSourceAccess,prepareVercelTrustedSourceAccess};
1
+ import{trustedSourcesToJSON}from"../../../node_modules/.pnpm/@vercel_sdk@1.28.8/node_modules/@vercel/sdk/esm/models/updateprojectprojectsbranchmatcher.js";import{updateProjectTrustedSourcesFromJSON}from"../../../node_modules/.pnpm/@vercel_sdk@1.28.8/node_modules/@vercel/sdk/esm/models/updateprojectblock.js";import{array,object,string,unknown}from"../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js";import"../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js";import{planTrustedSourceAccess}from"./vercel-trusted-sources-policy.js";import{captureVercel}from"#setup/primitives/index.js";import{normalizeVercelApiResult}from"#setup/vercel-api-failure.js";const ProjectSchema=object({id:string().min(1),name:string().min(1),customEnvironments:array(object({slug:string().min(1)})).optional(),trustedSources:unknown().nullable().optional()});function parseJson(e){try{return JSON.parse(e)}catch{return}}function parseTrustedSources(e){let n=JSON.stringify(e);if(n===void 0)return;let r=updateProjectTrustedSourcesFromJSON(n);return r.ok?r.value:void 0}function parseProject(e){let t=ProjectSchema.safeParse(parseJson(e));if(!t.success)return;let{trustedSources:n,...r}=t.data;if(n==null)return r;let i=parseTrustedSources(n);return i===void 0?void 0:{...r,trustedSources:i}}const ProjectUpdateSchema=object({id:string().min(1)}),defaultDeps={captureVercel};function environmentLabel(e){switch(e){case`development`:return`Development`;case`preview`:return`Preview`;case`production`:return`Production`;default:return e}}function projectPolicyContext(e){return{projectId:e.id,customEnvironmentSlugs:e.customEnvironments?.map(({slug:e})=>e)??[]}}async function readProject(e){let t=await e.deps.captureVercel([`api`,`/v9/projects/${encodeURIComponent(e.projectId)}`,`--scope`,e.ownerId,`--raw`],{cwd:e.workspaceRoot,nonInteractive:!0,signal:e.signal});if(!t.ok)return{kind:`failed`,message:t.failure.message};let n=parseProject(t.stdout);return n===void 0||n.id!==e.projectId?{kind:`failed`,message:`Vercel returned an invalid project response.`}:{kind:`project`,project:n}}async function prepareVercelTrustedSourceAccess(e){let t={...defaultDeps,...e.deps},n=e.target.deployment,r=await readProject({deps:t,workspaceRoot:e.workspaceRoot,ownerId:n.ownerId,projectId:n.projectId,signal:e.signal});if(r.kind===`failed`)return{kind:`failed`,message:`Could not read Deployment Protection for ${n.projectName}: ${r.message}`};let{project:i}=r;if(planTrustedSourceAccess({project:projectPolicyContext(i),targetEnvironment:n.environment,trustedSources:i.trustedSources??void 0}).kind===`unchanged`)return{kind:`unchanged`};let a=environmentLabel(`development`),o=environmentLabel(n.environment);return await e.prompter.select({message:`Allow ${a} from ${i.name} to access ${o} deployments of ${i.name}?`,hintLayout:`stacked`,notices:[{tone:`warning`,text:`This changes Deployment Protection for ${i.name} until the Trusted Sources rule is removed.`}],options:[{value:`continue`,label:`Allow access`,hint:`Add ${a} → ${o} to Trusted Sources`},{value:`cancel`,label:`Cancel`,hint:`Leave Deployment Protection unchanged`}]})===`cancel`?{kind:`cancelled`}:{kind:`approved`,grant:{ownerId:n.ownerId,projectId:i.id,projectName:i.name,targetEnvironment:n.environment}}}async function applyVercelTrustedSourceAccess(t){let n={...defaultDeps,...t.deps},r=await readProject({deps:n,workspaceRoot:t.workspaceRoot,ownerId:t.grant.ownerId,projectId:t.grant.projectId,signal:t.signal});if(r.kind===`failed`)return{kind:`failed`,message:`Could not refresh Deployment Protection for ${t.grant.projectName}: ${r.message}`};let{project:i}=r,a=planTrustedSourceAccess({project:projectPolicyContext(i),targetEnvironment:t.grant.targetEnvironment,trustedSources:i.trustedSources??void 0});if(a.kind===`unchanged`)return{kind:`unchanged`};let o=normalizeVercelApiResult(await n.captureVercel([`api`,`/v9/projects/${encodeURIComponent(i.id)}`,`--scope`,t.grant.ownerId,`--method`,`PATCH`,`--field`,`trustedSources=${trustedSourcesToJSON(a.trustedSources)}`,`--raw`],{cwd:t.workspaceRoot,nonInteractive:!0,signal:t.signal}));if(!o.ok)return{kind:`failed`,message:`Could not update Trusted Sources for ${i.name}: ${o.failure.message}`};let s=ProjectUpdateSchema.safeParse(parseJson(o.stdout));return(s.success?s.data:void 0)?.id===i.id?{kind:`updated`,targetProjectName:i.name}:{kind:`failed`,message:`Vercel returned an invalid project response.`}}export{applyVercelTrustedSourceAccess,prepareVercelTrustedSourceAccess};
@@ -7,7 +7,7 @@ export { createDataUrlFilePart, createTextWithFileContent } from "#client/file-p
7
7
  export { MessageResponse } from "#client/message-response.js";
8
8
  export { ClientSession } from "#client/session.js";
9
9
  export type { EveAgentStoreCallbacks, EveAgentStoreInit, EveAgentStoreSnapshot, EveAgentStoreStatus, PrepareSend, } from "#client/eve-agent-store.js";
10
- export type { AgentInfoEntry, AgentInfoChannelEntry, AgentInfoChannels, AgentInfoConnectionEntry, AgentInfoDynamicResolverEntry, AgentInfoFrameworkChannelEntry, AgentInfoFrameworkToolEntry, AgentInfoHookEntry, AgentInfoInstructions, AgentInfoInstructionsEntry, AgentInfoResult, AgentInfoSandboxEntry, AgentInfoScheduleEntry, AgentInfoSkillEntry, AgentInfoSource, AgentInfoSubagentEntry, AgentInfoToolEntry, AgentInfoTools, CancelSessionResult, ClientAuth, ClientOptions, ClientRedirectPolicy, HeadersValue, HealthResult, MessageResult, SendTurnInput, SendTurnPayload, SessionState, StreamOptions, TokenValue, } from "#client/types.js";
10
+ export type { AgentInfoEntry, AgentInfoChannelEntry, AgentInfoChannels, AgentInfoConnectionEntry, AgentInfoDynamicResolverEntry, AgentInfoFrameworkChannelEntry, AgentInfoFrameworkToolEntry, AgentInfoHookEntry, AgentInfoInstructions, AgentInfoInstructionsEntry, AgentInfoResult, AgentInfoSandboxEntry, AgentInfoScheduleEntry, AgentInfoSkillEntry, AgentInfoSource, AgentInfoSubagentEntry, AgentInfoToolEntry, AgentInfoTools, CancelSessionResult, ClientAuth, ClientOptions, ClientRedirectPolicy, HeadersValue, HealthResult, MessageResult, ResolvedStreamReconnectPolicy, SendTurnInput, SendTurnPayload, SessionState, StreamOptions, StreamReconnectPolicy, StreamReconnectRetryPolicy, TokenValue, } from "#client/types.js";
11
11
  export type { EveAgentReducer, EveAgentReducerEvent, ClientInputRespondedEvent, ClientMessageFailedEvent, ClientMessageSubmittedEvent, } from "#client/reducer.js";
12
12
  export type { EveAuthorizationChallenge, EveAuthorizationOutcome, EveAuthorizationPart, EveMessageData, EveDynamicToolPart, EveMessageInputRequest, EveMessage, EveMessageMetadata, EveMessagePart, EveMessageToolMetadata, } from "#client/message-reducer.js";
13
13
  export type { ActionResultStreamEvent, ActionsRequestedStreamEvent, AssistantStepFinishReason, AuthorizationOutcome, CompactionCompletedStreamEvent, CompactionRequestedStreamEvent, AuthorizationCompletedStreamEvent, ConnectionAuthorizationOutcome, AuthorizationRequiredStreamEvent, HandleMessageStreamEvent, InputRequestedStreamEvent, MessageAppendedStreamEvent, MessageCompletedStreamEvent, MessageReceivedPart, MessageReceivedStreamEvent, ReasoningAppendedStreamEvent, ReasoningCompletedStreamEvent, ResultCompletedStreamEvent, SessionCompletedStreamEvent, SessionFailedStreamEvent, SessionStartedStreamEvent, SessionWaitingStreamEvent, StepCompletedStreamEvent, StepFailedStreamEvent, StepStartedStreamEvent, SubagentCalledStreamEvent, SubagentChildEventStreamEvent, SubagentCompletedStreamEvent, SubagentStartedStreamEvent, TurnCancelledStreamEvent, TurnCompletedStreamEvent, TurnFailedStreamEvent, TurnStartedStreamEvent, TurnFailureStreamEvent, } from "#protocol/message.js";
@@ -1,10 +1,21 @@
1
1
  import type { HandleMessageStreamEvent } from "#protocol/message.js";
2
- import type { ClientRedirectPolicy } from "#client/types.js";
2
+ import type { ClientRedirectPolicy, StreamReconnectPolicy } from "#client/types.js";
3
+ interface RetryPolicy {
4
+ readonly baseDelayMs: number;
5
+ readonly maxAttempts: number;
6
+ readonly maxDelayMs: number;
7
+ }
8
+ interface ResolvedStreamReconnectPolicy {
9
+ readonly retryableErrorStatuses: ReadonlySet<number>;
10
+ readonly streamIdleReconnectPolicy: RetryPolicy;
11
+ readonly streamOpenReconnectPolicy: RetryPolicy;
12
+ }
3
13
  /**
4
14
  * Internal configuration for following a durable event stream.
5
15
  */
6
16
  interface FollowStreamInput {
7
17
  readonly host: string;
18
+ readonly streamReconnectPolicy?: StreamReconnectPolicy;
8
19
  readonly resolveHeaders: () => Promise<Headers>;
9
20
  readonly redirect?: ClientRedirectPolicy;
10
21
  readonly sessionId: string;
@@ -27,5 +38,7 @@ export declare function followStreamIterable(input: FollowStreamInput): AsyncGen
27
38
  * propagation window where a just-acknowledged session may not yet be
28
39
  * readable from the stream route.
29
40
  */
30
- export declare function openStreamBody(input: FollowStreamInput): Promise<ReadableStream<Uint8Array>>;
41
+ export declare function openStreamBody(input: FollowStreamInput & {
42
+ readonly retryPolicy?: ResolvedStreamReconnectPolicy;
43
+ }): Promise<ReadableStream<Uint8Array>>;
31
44
  export {};
@@ -1 +1 @@
1
- import{createEveMessageStreamRoutePath}from"#protocol/routes.js";import{ClientError}from"#client/client-error.js";import{createClientUrl}from"#client/url.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";const STREAM_OPEN_RETRY_MAX_DELAY_MS=5e3,STREAM_OPEN_RETRYABLE_STATUS=new Set([404,409,425,500,502,503,504]);async function*followStreamIterable(e){let t=e.startIndex,n=250,a=0,o=!0;for(;;){let s;try{s=await openStreamBody({...e,startIndex:t})}catch(t){if(e.signal?.aborted)return;throw t}let c=!1;try{for await(let e of readNdjsonStream(s))t+=1,c=!0,n=250,a=0,yield e}catch(e){if(!isStreamDisconnectError(e))throw e}if(e.signal?.aborted||e.startIndex<0||!c&&!o&&(a+=1)>=5||(o=!1,await sleep(n,e.signal),e.signal?.aborted))return;n=Math.min(n*2,4e3)}}async function openStreamBody(i){let s,c,l,u=250;for(let d=0;d<12;d+=1){let f=createClientUrl(i.host,createEveMessageStreamRoutePath(i.sessionId),i.startIndex===0?void 0:{startIndex:String(i.startIndex)}),p=await i.resolveHeaders(),m;try{m=await fetch(f,{headers:p,redirect:i.redirect,signal:i.signal??null})}catch(e){if(i.signal?.aborted||!isStreamDisconnectError(e)||d===11)throw e;await sleep(u,i.signal),u=Math.min(u*2,STREAM_OPEN_RETRY_MAX_DELAY_MS);continue}if(m.ok){if(!m.body)throw new ClientError(m.status,`Response body is null.`,m.headers);return m.body}if(s=m.status,c=await m.text(),l=m.headers,!STREAM_OPEN_RETRYABLE_STATUS.has(m.status))throw new ClientError(m.status,c,m.headers);d<11&&(await sleep(u,i.signal),u=Math.min(u*2,STREAM_OPEN_RETRY_MAX_DELAY_MS))}throw new ClientError(s??0,c??`Failed to open message stream.`,l)}async function sleep(e,t){t?.aborted||await new Promise(n=>{let onAbort=()=>{clearTimeout(r),n()},r=setTimeout(()=>{t?.removeEventListener(`abort`,onAbort),n()},e);t?.addEventListener(`abort`,onAbort,{once:!0})})}export{followStreamIterable,openStreamBody};
1
+ import{createEveMessageStreamRoutePath}from"#protocol/routes.js";import{ClientError}from"#client/client-error.js";import{createClientUrl}from"#client/url.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";const DEFAULT_STREAM_RECONNECT_POLICY={retryableErrorStatuses:new Set([404,409,425,500,502,503,504]),streamIdleReconnectPolicy:{baseDelayMs:250,maxAttempts:5,maxDelayMs:4e3},streamOpenReconnectPolicy:{baseDelayMs:250,maxAttempts:12,maxDelayMs:5e3}},NO_STREAM_RECONNECT_POLICY={...DEFAULT_STREAM_RECONNECT_POLICY,streamIdleReconnectPolicy:{...DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy,maxAttempts:0},streamOpenReconnectPolicy:{...DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy,maxAttempts:1}};function resolveRetryPolicy(e,t){return{...t,...e}}function resolveStreamReconnectPolicy(e){if(e&&`reconnect`in e&&e.reconnect===!1)return NO_STREAM_RECONNECT_POLICY;let t=e;return{retryableErrorStatuses:t?.retryableErrorStatuses?new Set(t.retryableErrorStatuses):DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses,streamIdleReconnectPolicy:resolveRetryPolicy(t?.streamIdleReconnectPolicy,DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy),streamOpenReconnectPolicy:resolveRetryPolicy(t?.streamOpenReconnectPolicy,DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy)}}async function*followStreamIterable(e){let t=resolveStreamReconnectPolicy(e.streamReconnectPolicy),n=t.streamIdleReconnectPolicy,a=e.startIndex,o=n.baseDelayMs,s=0,c=!0;for(;;){let l;try{l=await openStreamBody({...e,retryPolicy:t,startIndex:a})}catch(t){if(e.signal?.aborted)return;throw t}let u=!1;try{for await(let e of readNdjsonStream(l))a+=1,u=!0,o=n.baseDelayMs,s=0,yield e}catch(e){if(!isStreamDisconnectError(e))throw e}if(e.signal?.aborted||e.startIndex<0||n.maxAttempts===0||!u&&!c&&(s+=1)>=n.maxAttempts||(c=!1,await sleep(o,e.signal),e.signal?.aborted))return;o=Math.min(o*2,n.maxDelayMs)}}async function openStreamBody(i){let o=i.retryPolicy??DEFAULT_STREAM_RECONNECT_POLICY,s=o.streamOpenReconnectPolicy,c,l,u,d=s.baseDelayMs;for(let a=0;a<s.maxAttempts;a+=1){let f=createClientUrl(i.host,createEveMessageStreamRoutePath(i.sessionId),i.startIndex===0?void 0:{startIndex:String(i.startIndex)}),p=await i.resolveHeaders(),m;try{m=await fetch(f,{headers:p,redirect:i.redirect,signal:i.signal??null})}catch(e){if(i.signal?.aborted||!isStreamDisconnectError(e)||a===s.maxAttempts-1)throw e;await sleep(d,i.signal),d=Math.min(d*2,s.maxDelayMs);continue}if(m.ok){if(!m.body)throw new ClientError(m.status,`Response body is null.`,m.headers);return m.body}if(c=m.status,l=await m.text(),u=m.headers,!o.retryableErrorStatuses.has(m.status))throw new ClientError(m.status,l,m.headers);a<s.maxAttempts-1&&(await sleep(d,i.signal),d=Math.min(d*2,s.maxDelayMs))}throw new ClientError(c??0,l??`Failed to open message stream.`,u)}async function sleep(e,t){t?.aborted||await new Promise(n=>{let onAbort=()=>{clearTimeout(r),n()},r=setTimeout(()=>{t?.removeEventListener(`abort`,onAbort),n()},e);t?.addEventListener(`abort`,onAbort,{once:!0})})}export{followStreamIterable,openStreamBody};
@@ -55,8 +55,9 @@ export declare class ClientSession {
55
55
  * Opens this session's event stream for the current session ID.
56
56
  *
57
57
  * Resumes from the session's stored stream cursor unless `options.startIndex`
58
- * overrides it. The stream reconnects from its cursor when the connection
59
- * ends. Negative indices read relative to the current tail on one connection
58
+ * overrides it. By default, the stream reconnects from its cursor when the
59
+ * connection ends; pass `streamReconnectPolicy: { reconnect: false }` to use
60
+ * one connection. Negative indices read relative to the current tail on one connection
60
61
  * and do not advance the stored absolute cursor.
61
62
  *
62
63
  * @throws {Error} If the session has no session ID (no message has been sent
@@ -1 +1 @@
1
- import{EVE_CREATE_SESSION_ROUTE_PATH,createEveCancelTurnRoutePath,createEveContinueSessionRoutePath}from"#protocol/routes.js";import{EVE_SESSION_ID_HEADER,isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{ClientError}from"#client/client-error.js";import{advanceSession}from"#client/session-utils.js";import{createClientUrl}from"#client/url.js";import{MessageResponse}from"#client/message-response.js";import{CancelTurnResponseSchema}from"#protocol/cancel-turn.js";import{followStreamIterable}from"#client/open-stream.js";import{serializeOutputSchema}from"#shared/tool-schema.js";var ClientSession=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}get state(){return this.#t}async send(e){let t=normalizeSendTurnInput(e),n=this.#t,{continuationToken:r,sessionId:i}=await this.#n(t,n);return this.#t===n&&(this.#t={...n,sessionId:i}),new MessageResponse({continuationToken:r,createStream:()=>this.#r(i,r,n,t),sessionId:i})}async cancel(e){let n=this.#t.sessionId;if(!n)throw Error(`Session has no session ID. Send a message first.`);let r=createClientUrl(this.#e.host,createEveCancelTurnRoutePath(n)),i=await this.#e.resolveHeaders();i.set(`content-type`,`application/json`);let o=await fetch(r,withRedirectPolicy({headers:i,method:`POST`,body:e?JSON.stringify(e):void 0},this.#e.redirect)),c=await o.text();if(!o.ok)throw new ClientError(o.status,c,o.headers);let u;try{u=JSON.parse(c)}catch{throw Error(`Cancel route returned invalid JSON (${o.status}).`)}let d=CancelTurnResponseSchema.safeParse(u);if(!d.success||d.data.sessionId!==n)throw Error(`Cancel route returned an invalid response (${o.status}).`);return{sessionId:d.data.sessionId,status:d.data.status}}stream(e){let t=this.#t.sessionId;if(!t)throw Error(`Session has no session ID. Send a message first.`);return this.#i(t,e)}async#n(t,i){let a=i.sessionId?createEveContinueSessionRoutePath(i.sessionId):EVE_CREATE_SESSION_ROUTE_PATH,o=createClientUrl(this.#e.host,a),c=await this.#e.resolveHeaders(t.headers);c.set(`content-type`,`application/json`);let l=createHandleMessageBody({input:t,outputSchema:serializeOutputSchema(t.outputSchema),session:i});if(l===null)throw Error(`Session.send requires a non-empty message, inputResponses, or both.`);let u=await postTurnWithRetry({body:JSON.stringify(l),headers:c,mustDeliver:(t.inputResponses?.length??0)>0,redirect:this.#e.redirect,signal:t.signal,url:o}),f=await u.json(),p=(typeof f.sessionId==`string`?f.sessionId:void 0)??u.headers.get(EVE_SESSION_ID_HEADER)?.trim()??i.sessionId;if(!p)throw Error(`Message route did not return a session id.`);return{continuationToken:typeof f.continuationToken==`string`?f.continuationToken:void 0,sessionId:p}}async*#r(e,t,n,r){let a=[];try{for await(let t of followStreamIterable({host:this.#e.host,resolveHeaders:()=>this.#e.resolveHeaders(r.headers),redirect:this.#e.redirect,sessionId:e,signal:r.signal,startIndex:n.sessionId===e?n.streamIndex:0}))if(a.push(t),yield t,isCurrentTurnBoundaryEvent(t))break}finally{this.#t=advanceSession({continuationToken:t,events:a,preserveCompletedSessions:this.#e.preserveCompletedSessions,sessionId:e,session:n})}}async*#i(e,t){let n=this.#t,r=t?.startIndex??n.streamIndex,i=[];try{for await(let n of followStreamIterable({host:this.#e.host,resolveHeaders:()=>this.#e.resolveHeaders(),redirect:this.#e.redirect,sessionId:e,signal:t?.signal,startIndex:r}))i.push(n),yield n}finally{r>=0&&(this.#t=advanceSession({continuationToken:n.continuationToken,events:i,preserveCompletedSessions:this.#e.preserveCompletedSessions,session:{...n,sessionId:e,streamIndex:r},sessionId:e}))}}};async function postTurnWithRetry(e){let t=e.mustDeliver?10:1,n,r,i;for(let o=0;o<t;o+=1){let s=await fetch(e.url,{body:e.body,headers:e.headers,method:`POST`,redirect:e.redirect,signal:e.signal??null});if(s.ok)return s;if(n=s.status,r=await s.text(),i=s.headers,!isRetryableDeliveryFailure(s.status,r))throw new ClientError(s.status,r,s.headers);o<t-1&&await sleep(200)}throw new ClientError(n??0,r??`Failed to deliver session turn.`,i)}function isRetryableDeliveryFailure(e,t){return e===500&&/target session was not found/i.test(t)}async function sleep(e){await new Promise(t=>setTimeout(t,e))}function normalizeSendTurnInput(e){return typeof e==`string`?{message:e}:e}function createHandleMessageBody(e){let t={};return e.input.message!==void 0&&(t.message=e.input.message),e.input.inputResponses!==void 0&&e.input.inputResponses.length>0&&(t.inputResponses=e.input.inputResponses),e.input.clientContext!==void 0&&(t.clientContext=e.input.clientContext),e.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),e.session.continuationToken!==void 0&&(t.continuationToken=e.session.continuationToken),Object.keys(t).length===0||e.session.continuationToken===void 0&&t.message===void 0||e.session.continuationToken!==void 0&&t.message===void 0&&t.inputResponses===void 0?null:t}function withRedirectPolicy(e,t){return t===void 0?e:{...e,redirect:t}}export{ClientSession};
1
+ import{EVE_CREATE_SESSION_ROUTE_PATH,createEveCancelTurnRoutePath,createEveContinueSessionRoutePath}from"#protocol/routes.js";import{EVE_SESSION_ID_HEADER,isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{ClientError}from"#client/client-error.js";import{advanceSession}from"#client/session-utils.js";import{createClientUrl}from"#client/url.js";import{MessageResponse}from"#client/message-response.js";import{CancelTurnResponseSchema}from"#protocol/cancel-turn.js";import{followStreamIterable}from"#client/open-stream.js";import{serializeOutputSchema}from"#shared/tool-schema.js";var ClientSession=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}get state(){return this.#t}async send(e){let t=normalizeSendTurnInput(e),n=this.#t,{continuationToken:r,sessionId:i}=await this.#n(t,n);return this.#t===n&&(this.#t={...n,sessionId:i}),new MessageResponse({continuationToken:r,createStream:()=>this.#r(i,r,n,t),sessionId:i})}async cancel(e){let n=this.#t.sessionId;if(!n)throw Error(`Session has no session ID. Send a message first.`);let r=createClientUrl(this.#e.host,createEveCancelTurnRoutePath(n)),i=await this.#e.resolveHeaders();i.set(`content-type`,`application/json`);let o=await fetch(r,withRedirectPolicy({headers:i,method:`POST`,body:e?JSON.stringify(e):void 0},this.#e.redirect)),c=await o.text();if(!o.ok)throw new ClientError(o.status,c,o.headers);let u;try{u=JSON.parse(c)}catch{throw Error(`Cancel route returned invalid JSON (${o.status}).`)}let d=CancelTurnResponseSchema.safeParse(u);if(!d.success||d.data.sessionId!==n)throw Error(`Cancel route returned an invalid response (${o.status}).`);return{sessionId:d.data.sessionId,status:d.data.status}}stream(e){let t=this.#t.sessionId;if(!t)throw Error(`Session has no session ID. Send a message first.`);return this.#i(t,e)}async#n(t,i){let a=i.sessionId?createEveContinueSessionRoutePath(i.sessionId):EVE_CREATE_SESSION_ROUTE_PATH,o=createClientUrl(this.#e.host,a),c=await this.#e.resolveHeaders(t.headers);c.set(`content-type`,`application/json`);let l=createHandleMessageBody({input:t,outputSchema:serializeOutputSchema(t.outputSchema),session:i});if(l===null)throw Error(`Session.send requires a non-empty message, inputResponses, or both.`);let u=await postTurnWithRetry({body:JSON.stringify(l),headers:c,mustDeliver:(t.inputResponses?.length??0)>0,redirect:this.#e.redirect,signal:t.signal,url:o}),f=await u.json(),p=(typeof f.sessionId==`string`?f.sessionId:void 0)??u.headers.get(EVE_SESSION_ID_HEADER)?.trim()??i.sessionId;if(!p)throw Error(`Message route did not return a session id.`);return{continuationToken:typeof f.continuationToken==`string`?f.continuationToken:void 0,sessionId:p}}async*#r(e,t,n,r){let a=[];try{for await(let t of followStreamIterable({host:this.#e.host,resolveHeaders:()=>this.#e.resolveHeaders(r.headers),redirect:this.#e.redirect,streamReconnectPolicy:r.streamReconnectPolicy,sessionId:e,signal:r.signal,startIndex:n.sessionId===e?n.streamIndex:0}))if(a.push(t),yield t,isCurrentTurnBoundaryEvent(t))break}finally{this.#t=advanceSession({continuationToken:t,events:a,preserveCompletedSessions:this.#e.preserveCompletedSessions,sessionId:e,session:n})}}async*#i(e,t){let n=this.#t,r=t?.startIndex??n.streamIndex,i=[];try{for await(let n of followStreamIterable({host:this.#e.host,resolveHeaders:()=>this.#e.resolveHeaders(),redirect:this.#e.redirect,streamReconnectPolicy:t?.streamReconnectPolicy,sessionId:e,signal:t?.signal,startIndex:r}))i.push(n),yield n}finally{r>=0&&(this.#t=advanceSession({continuationToken:n.continuationToken,events:i,preserveCompletedSessions:this.#e.preserveCompletedSessions,session:{...n,sessionId:e,streamIndex:r},sessionId:e}))}}};async function postTurnWithRetry(e){let t=e.mustDeliver?10:1,n,r,i;for(let o=0;o<t;o+=1){let s=await fetch(e.url,{body:e.body,headers:e.headers,method:`POST`,redirect:e.redirect,signal:e.signal??null});if(s.ok)return s;if(n=s.status,r=await s.text(),i=s.headers,!isRetryableDeliveryFailure(s.status,r))throw new ClientError(s.status,r,s.headers);o<t-1&&await sleep(200)}throw new ClientError(n??0,r??`Failed to deliver session turn.`,i)}function isRetryableDeliveryFailure(e,t){return e===500&&/target session was not found/i.test(t)}async function sleep(e){await new Promise(t=>setTimeout(t,e))}function normalizeSendTurnInput(e){return typeof e==`string`?{message:e}:e}function createHandleMessageBody(e){let t={};return e.input.message!==void 0&&(t.message=e.input.message),e.input.inputResponses!==void 0&&e.input.inputResponses.length>0&&(t.inputResponses=e.input.inputResponses),e.input.clientContext!==void 0&&(t.clientContext=e.input.clientContext),e.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),e.session.continuationToken!==void 0&&(t.continuationToken=e.session.continuationToken),Object.keys(t).length===0||e.session.continuationToken===void 0&&t.message===void 0||e.session.continuationToken!==void 0&&t.message===void 0&&t.inputResponses===void 0?null:t}function withRedirectPolicy(e,t){return t===void 0?e:{...e,redirect:t}}export{ClientSession};
@@ -118,6 +118,11 @@ export interface SendTurnPayload<TOutput = unknown> {
118
118
  * schema's output type and is not revalidated client-side.
119
119
  */
120
120
  readonly outputSchema?: StandardJSONSchemaV1<unknown, TOutput> | JsonObject;
121
+ /**
122
+ * Reconnection policy for the response event stream. Omit to use the default
123
+ * policy, or pass `{ reconnect: false }` when the caller owns cursor recovery.
124
+ */
125
+ readonly streamReconnectPolicy?: StreamReconnectPolicy;
121
126
  /**
122
127
  * Abort signal for cancelling the request.
123
128
  */
@@ -127,10 +132,37 @@ export interface SendTurnPayload<TOutput = unknown> {
127
132
  */
128
133
  readonly headers?: Readonly<Record<string, string>>;
129
134
  }
135
+ /** Retry and backoff settings for one kind of stream reconnection. */
136
+ export interface StreamReconnectRetryPolicy {
137
+ /** Initial delay before retrying, in milliseconds. */
138
+ readonly baseDelayMs?: number;
139
+ /** Maximum number of attempts governed by this retry policy. */
140
+ readonly maxAttempts?: number;
141
+ /** Maximum delay between retries, in milliseconds. */
142
+ readonly maxDelayMs?: number;
143
+ }
144
+ /** Configurable policy used when automatic stream reconnection is enabled. */
145
+ export interface ResolvedStreamReconnectPolicy {
146
+ /** Retry policy for opening an HTTP stream connection. */
147
+ readonly streamOpenReconnectPolicy?: StreamReconnectRetryPolicy;
148
+ /** Retry policy for reconnecting streams that make no progress. */
149
+ readonly streamIdleReconnectPolicy?: StreamReconnectRetryPolicy;
150
+ /** HTTP response statuses that may be retried while opening a stream. */
151
+ readonly retryableErrorStatuses?: readonly number[];
152
+ }
153
+ /** Automatic stream reconnection configuration. */
154
+ export type StreamReconnectPolicy = ResolvedStreamReconnectPolicy | {
155
+ readonly reconnect: false;
156
+ };
130
157
  /**
131
158
  * Options for {@link ClientSession.stream}.
132
159
  */
133
160
  export interface StreamOptions {
161
+ /**
162
+ * Reconnection policy for the event stream. Omit to use the default policy,
163
+ * or pass `{ reconnect: false }` when the caller owns cursor recovery.
164
+ */
165
+ readonly streamReconnectPolicy?: StreamReconnectPolicy;
134
166
  /**
135
167
  * Absolute event index to start from. Negative values read relative to the
136
168
  * current tail (`-1` starts at the latest event). Relative-tail streams do
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "moduleVersions": {
3
- "@ai-sdk/anthropic": "4.0.14",
3
+ "@ai-sdk/anthropic": "4.0.18",
4
4
  "chat": "4.34.0",
5
5
  "@chat-adapter/slack": "4.34.0",
6
6
  "@chat-adapter/state-memory": "4.34.0",
@@ -8,35 +8,35 @@
8
8
  "chokidar": "5.0.0",
9
9
  "commander": "14.0.3",
10
10
  "experimental-ai-sdk-code-mode": "1.0.16",
11
- "eventsource-parser": "3.0.8",
12
- "env-runner": "0.1.12",
13
- "@ai-sdk/google": "4.0.14",
11
+ "eventsource-parser": "3.1.0",
12
+ "env-runner": "0.1.16",
13
+ "@ai-sdk/google": "4.0.21",
14
14
  "gray-matter": "4.0.3",
15
15
  "jose": "6.2.3",
16
16
  "jsonc-parser": "3.3.1",
17
17
  "@types/json-schema": "7.0.15",
18
18
  "marked": "17.0.6",
19
- "@ai-sdk/mcp": "2.0.12",
20
- "@ai-sdk/openai": "4.0.13",
19
+ "@ai-sdk/mcp": "2.0.16",
20
+ "@ai-sdk/openai": "4.0.17",
21
21
  "@opentelemetry/api": "1.9.1",
22
- "@ai-sdk/otel": "1.0.26",
22
+ "@ai-sdk/otel": "1.0.34",
23
23
  "picocolors": "1.1.1",
24
24
  "@ai-sdk/provider": "4.0.3",
25
- "@ai-sdk/provider-utils": "5.0.9",
25
+ "@ai-sdk/provider-utils": "5.0.12",
26
26
  "semver": "7.8.4",
27
27
  "@standard-schema/spec": "1.1.0",
28
28
  "turndown": "7.2.4",
29
29
  "@vercel/detect-agent": "1.2.3",
30
- "@vercel/oidc": "3.5.0",
31
- "@vercel/sandbox": "2.3.0",
32
- "@workflow/core": "5.0.0-beta.35",
33
- "@workflow/errors": "5.0.0-beta.11",
30
+ "@vercel/oidc": "3.8.0",
31
+ "@vercel/sandbox": "2.8.0",
32
+ "@workflow/core": "5.0.0-beta.36",
33
+ "@workflow/errors": "5.0.0-beta.12",
34
34
  "@workflow/serde": "5.0.0-beta.2",
35
- "@workflow/world": "5.0.0-beta.21",
36
- "@workflow/world-local": "5.0.0-beta.29",
37
- "@workflow/world-vercel": "5.0.0-beta.31",
35
+ "@workflow/world": "5.0.0-beta.22",
36
+ "@workflow/world-local": "5.0.0-beta.30",
37
+ "@workflow/world-vercel": "5.0.0-beta.32",
38
38
  "zod": "4.4.3",
39
39
  "zod-validation-error": "5.0.0"
40
40
  },
41
- "scriptHash": "8da9abfc5a69e5b398d150c3d0988f4facdeec175e869134e17cea976897d5c4"
41
+ "scriptHash": "1afbe648332a28fef0cb1b24097c6d9066854ba9acaf3b734045c41cbd36e1c0"
42
42
  }