eve 0.84.1 → 0.85.0

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 (147) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/src/channel/channel-operations.d.ts +2 -18
  3. package/dist/src/channel/compiled-channel.d.ts +3 -7
  4. package/dist/src/channel/cross-channel-receive.d.ts +9 -10
  5. package/dist/src/channel/cross-channel-receive.js +1 -1
  6. package/dist/src/channel/schedule.js +1 -1
  7. package/dist/src/channel/session.d.ts +26 -4
  8. package/dist/src/channel/session.js +1 -1
  9. package/dist/src/chunks/{use-eve-agent-DMeP0JOF.js → use-eve-agent-B2jCfcnG.js} +3 -2
  10. package/dist/src/chunks/{use-eve-agent-DP5Rso9C.js → use-eve-agent-DCLFi26P.js} +3 -2
  11. package/dist/src/client/client.js +1 -1
  12. package/dist/src/client/open-stream.js +1 -1
  13. package/dist/src/client/types.d.ts +5 -4
  14. package/dist/src/compiled/.vendor-stamp.json +1 -1
  15. package/dist/src/context/keys.d.ts +7 -0
  16. package/dist/src/context/keys.js +1 -1
  17. package/dist/src/execution/agent-sessions/context.d.ts +5 -1
  18. package/dist/src/execution/agent-sessions/context.js +1 -1
  19. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  20. package/dist/src/execution/legacy-session/snapshot.d.ts +1 -2
  21. package/dist/src/execution/legacy-session/snapshot.js +1 -1
  22. package/dist/src/execution/proxied-deliver-step.js +1 -1
  23. package/dist/src/execution/public-destination.d.ts +3 -0
  24. package/dist/src/execution/public-destination.js +1 -1
  25. package/dist/src/execution/publish-session-events.js +1 -1
  26. package/dist/src/execution/session/checkpoint-migrations.d.ts +16 -5
  27. package/dist/src/execution/session/checkpoint-migrations.js +1 -1
  28. package/dist/src/execution/session/checkpoint-refusal.d.ts +4 -0
  29. package/dist/src/execution/session/checkpoint-refusal.js +1 -0
  30. package/dist/src/execution/session/entry.js +1 -1
  31. package/dist/src/execution/session/handoff-steps.d.ts +7 -1
  32. package/dist/src/execution/session/handoff-steps.js +1 -1
  33. package/dist/src/execution/session/imported-conversation.d.ts +2 -0
  34. package/dist/src/execution/session/imported-conversation.js +1 -0
  35. package/dist/src/execution/session/interrupted-step.js +1 -1
  36. package/dist/src/execution/session/pre-v27-checkpoint.d.ts +36 -0
  37. package/dist/src/execution/session/pre-v27-checkpoint.js +1 -0
  38. package/dist/src/execution/session/program.d.ts +2 -0
  39. package/dist/src/execution/session/program.js +1 -1
  40. package/dist/src/execution/session/turn-step.js +1 -1
  41. package/dist/src/execution/session-callback-request.js +1 -1
  42. package/dist/src/execution/tool-auth.js +1 -1
  43. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  44. package/dist/src/execution/tools/channel-to.d.ts +12 -0
  45. package/dist/src/execution/tools/channel-to.js +1 -0
  46. package/dist/src/execution/tools/workflow/body.d.ts +3 -0
  47. package/dist/src/execution/tools/workflow/body.js +1 -1
  48. package/dist/src/execution/tools/workflow/step-context.d.ts +5 -0
  49. package/dist/src/execution/tools/workflow/step-execution.js +1 -1
  50. package/dist/src/execution/tools/workflow/step.js +1 -1
  51. package/dist/src/execution/workflow-callback-url.d.ts +2 -3
  52. package/dist/src/execution/workflow-callback-url.js +1 -1
  53. package/dist/src/execution/workflow-runtime.js +1 -1
  54. package/dist/src/harness/compaction/step.js +1 -1
  55. package/dist/src/harness/model-call/call.js +1 -1
  56. package/dist/src/harness/model-call/run.js +1 -1
  57. package/dist/src/harness/session-machine/transitions.js +1 -1
  58. package/dist/src/internal/application/stamped-package-version.js +1 -1
  59. package/dist/src/internal/attachments/limited-read.d.ts +2 -0
  60. package/dist/src/internal/attachments/limited-read.js +1 -1
  61. package/dist/src/internal/attachments/url-refs.js +1 -1
  62. package/dist/src/internal/capability-error.d.ts +3 -0
  63. package/dist/src/internal/capability-error.js +1 -0
  64. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +1 -1
  65. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  66. package/dist/src/public/channels/github/githubChannel.js +1 -1
  67. package/dist/src/public/channels/linear/linearChannel.js +1 -1
  68. package/dist/src/public/channels/linq/inboundContent.js +1 -1
  69. package/dist/src/public/channels/slack/answers.d.ts +2 -3
  70. package/dist/src/public/channels/slack/answers.js +1 -1
  71. package/dist/src/public/channels/slack/api.d.ts +23 -3
  72. package/dist/src/public/channels/slack/api.js +1 -1
  73. package/dist/src/public/channels/slack/app-manifest.d.ts +2 -0
  74. package/dist/src/public/channels/slack/app-manifest.js +1 -1
  75. package/dist/src/public/channels/slack/auth.d.ts +2 -1
  76. package/dist/src/public/channels/slack/auth.js +1 -1
  77. package/dist/src/public/channels/slack/code-channel.d.ts +42 -0
  78. package/dist/src/public/channels/slack/code-channel.js +1 -0
  79. package/dist/src/public/channels/slack/defaults.d.ts +7 -3
  80. package/dist/src/public/channels/slack/defaults.js +3 -3
  81. package/dist/src/public/channels/slack/hitl.d.ts +7 -17
  82. package/dist/src/public/channels/slack/hitl.js +1 -1
  83. package/dist/src/public/channels/slack/index.d.ts +4 -3
  84. package/dist/src/public/channels/slack/index.js +1 -1
  85. package/dist/src/public/channels/slack/interaction-cards.d.ts +0 -2
  86. package/dist/src/public/channels/slack/interaction-cards.js +1 -1
  87. package/dist/src/public/channels/slack/interactions.js +1 -1
  88. package/dist/src/public/channels/slack/open-code-channel.d.ts +30 -0
  89. package/dist/src/public/channels/slack/open-code-channel.js +1 -0
  90. package/dist/src/public/channels/slack/private-approval-delivery.d.ts +16 -4
  91. package/dist/src/public/channels/slack/private-approval-delivery.js +1 -1
  92. package/dist/src/public/channels/slack/renderers.d.ts +58 -6
  93. package/dist/src/public/channels/slack/renderers.js +1 -1
  94. package/dist/src/public/channels/slack/reply-delivery.d.ts +4 -0
  95. package/dist/src/public/channels/slack/reply-delivery.js +1 -1
  96. package/dist/src/public/channels/slack/request-card-render.d.ts +45 -0
  97. package/dist/src/public/channels/slack/request-card-render.js +1 -0
  98. package/dist/src/public/channels/slack/request-cards.d.ts +35 -0
  99. package/dist/src/public/channels/slack/request-cards.js +3 -0
  100. package/dist/src/public/channels/slack/sign-in-cancel.d.ts +3 -5
  101. package/dist/src/public/channels/slack/sign-in-cancel.js +1 -1
  102. package/dist/src/public/channels/slack/slackChannel.d.ts +109 -22
  103. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  104. package/dist/src/public/channels/slack/task-card.d.ts +3 -3
  105. package/dist/src/public/channels/slack/task-card.js +1 -1
  106. package/dist/src/public/channels/slack/thread-status.js +1 -1
  107. package/dist/src/public/channels/teams/api.js +1 -1
  108. package/dist/src/public/channels/teams/defaults.js +1 -1
  109. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  110. package/dist/src/public/channels/teams/verify.d.ts +9 -5
  111. package/dist/src/public/channels/teams/verify.js +1 -1
  112. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  113. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  114. package/dist/src/public/schedules/subscription.d.ts +10 -1
  115. package/dist/src/runtime/subagents/workflow.js +1 -1
  116. package/dist/src/setup/index.d.ts +1 -1
  117. package/dist/src/setup/primitives/index.d.ts +1 -1
  118. package/dist/src/setup/primitives/pm/run.d.ts +0 -2
  119. package/dist/src/setup/scaffold/create/project.js +1 -1
  120. package/dist/src/shared/channel-definition.d.ts +4 -4
  121. package/dist/src/subagents/adapter.js +1 -1
  122. package/dist/src/subagents/parent-notification.js +1 -1
  123. package/dist/src/svelte/index.js +1 -1
  124. package/dist/src/svelte/use-eve-agent.js +1 -1
  125. package/dist/src/tools/definition.d.ts +21 -0
  126. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  127. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  128. package/dist/src/tools/workflow-definition.d.ts +4 -4
  129. package/dist/src/vue/index.js +1 -1
  130. package/dist/src/vue/use-eve-agent.js +1 -1
  131. package/docs/channels/custom.mdx +16 -3
  132. package/docs/channels/eve.mdx +2 -0
  133. package/docs/channels/linq.mdx +1 -1
  134. package/docs/channels/slack.mdx +185 -18
  135. package/docs/channels/teams.mdx +6 -2
  136. package/docs/concepts/upgrade-to-v27-events.md +2 -2
  137. package/docs/experimental/dynamic-schedules.mdx +2 -2
  138. package/docs/guides/client/overview.mdx +1 -1
  139. package/docs/guides/remote-agents.md +8 -0
  140. package/docs/patterns/fork-conversations-into-new-threads.md +159 -0
  141. package/docs/patterns/meta.json +1 -0
  142. package/docs/schedules.mdx +1 -1
  143. package/docs/tools/overview.mdx +34 -0
  144. package/docs/tools/workflows.mdx +47 -5
  145. package/package.json +1 -1
  146. package/dist/src/public/channels/slack/approval-cards.d.ts +0 -25
  147. package/dist/src/public/channels/slack/approval-cards.js +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # eve
2
2
 
3
+ ## 0.85.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 24c6b9f: Client requests now reject redirects by default, including session writes and event streams. Update redirecting base URLs to their final destination, use `redirect: "manual"` to stop at redirects, or explicitly opt into `"follow"` only when every redirect destination is trusted.
8
+ - c8328f8: Protected cross-project callbacks now require reciprocal Vercel Trusted Sources and an explicit `EVE_CALLBACK_TRUSTED_ORIGINS` allowlist on the remote deployment. Callback URLs no longer include the parent's deployment-wide bypass secret; listed origins instead receive the remote's short-lived OIDC credential.
9
+ - 5cfec0e: Slack renderers can restyle approval, question, and budget prompt cards with a new `interactionCard(card, next)` hook, while eve keeps routing, batching, action IDs, and card updates. Cards now update from the session for every request kind, so a question answered by a typed reply or withdrawn, or a settled budget prompt, no longer keeps live buttons.
10
+
11
+ Breaking changes:
12
+
13
+ - `SlackChannelState.pendingApprovalCards` is replaced by `interactionCards`. Cards posted before the upgrade keep their buttons.
14
+ - `SlackTaskCard` is renamed to `SlackCardMessage`, which both `taskCard` and `interactionCard` return.
15
+ - Clicking a question no longer rewrites its card from the webhook. The buttons stay until the session admits the answer, and apps that post eve's controls themselves no longer get that rewrite.
16
+ - An approval's buttons disappear once its answer is admitted, so a later click can't change it. A denied approval reads **Deny** instead of **Cancel**, and a direct-message request's thread note reports the same outcome as its card.
17
+
18
+ ### Patch Changes
19
+
20
+ - f20a7a1: Bind native Teams activities to the verified Bot Connector token's service URL before dispatch. Connector requests require HTTPS and reject redirects, keeping bearer credentials on the validated destination.
21
+ - 4f290a7: Sessions whose deployment runs eve 0.69 through 0.83 now move to a v27 deployment the next time they receive a message while idle, or earlier when a channel prepares them for the next message, instead of staying on their original deployment until they time out. eve compacts the earlier conversation as the session moves, so the model continues from a summary; the stored transcript stays intact, and new turns continue after it. Remembered tool approvals and usage limits start over.
22
+ - 0553a67: Keep continuation capabilities out of session lookup and child-interaction failure logs, including capability values embedded in error messages and causes. Failure diagnostics retain correlation fields and non-secret error details.
23
+ - e54f078: Render Teams mention display names and fallback IDs as literal text, preserving names that contain ampersands or angle brackets without changing mention identity.
24
+ - ba52da4: Remove the deprecated internal setup type alias `RunPnpmOptions`. Setup tooling should use `RunPackageManagerOptions`; package-manager command behavior is unchanged.
25
+ - 5b8a34b: `to(channel, target).send()`, Slack's `onEvent` `ctx.send()`, dynamic schedules' `to().send()`, and channel `receive` hooks now accept the same options as `from(address).send()`, including `history`, `idempotencyKey`, and `title`. Slack derives a threadless target's session from `idempotencyKey`, and a dynamic schedule's keyed send reaches the session its earlier attempt started, so a retried send no longer starts a second thread or session.
26
+ - 6ea94da: Set `codeChannels: true` on `slackChannel()` to serve Slack code channels as one session per channel. The agent answers un-mentioned messages, replies top-level or in the thread a person wrote in, and follows Slack's session status and stop. The option also adds the code channel scopes and events to the app manifest. A code channel session has no thread: `threadTs` is empty or `null`, and `ctx.slack.codeChannel` marks it. Address its session with `{ channelId, codeChannel: true }` in `onEvent` targets, or with `slackCodeChannelContinuationToken(channelId)`.
27
+
28
+ Two changes also reach agents that don't enable code channels: a cancelled turn now clears the Slack thread status by default, and `SlackSessionTarget` is now a union, so code that reads `target.threadTs` must handle the `{ channelId, codeChannel: true }` variant. `SlackHandle` also gains a required `codeChannel` field, which affects code that builds a handle by hand.
29
+ - 2764e1e: Add `openCodeChannel(ctx, slack, message, { name })` to `eve/channels/slack`, which a tool calls to move the Slack conversation it was called from into a new Slack code channel and continue the work there with the conversation so far. Wrap it in your own tool with your own description and inputs, and pass your Slack channel. It finds the conversation from `ctx.channel`, so it works when message hooks return their own auth. To write your own variant, Slack receive targets accept `codeChannel`. Message hooks can open a code channel without the model through `ctx.openCodeChannel()`.
30
+ - cb14c32: Reject framework-owned adapter attachment references in HTTP messages and restrict Linq attachment downloads to bounded public HTTPS destinations. Thanks to HackerOne researcher ryota for reporting the attachment-reference boundary issue.
31
+ - 412b077: Tools can start or reach sessions on the agent's channels with `ctx.to(channel, target).send(message, options)`, the same call route handlers and schedules use, such as forking a conversation into a new Slack thread. Ordinary tools call it directly, and workflow tools call it in a `"use step"` helper. Pass `` idempotencyKey: `${ctx.session.id}:${ctx.callId}` `` so a retried call reaches the same session once. `ctx.to()` throws in a subagent, a root copy, or a remote agent call. Tools also get `ctx.channel`, the calling session's channel `kind`, `continuationToken`, and `metadata`, as hooks and dynamic resolvers read it.
32
+
3
33
  ## 0.84.1
4
34
 
5
35
  ### Patch Changes
@@ -4,29 +4,13 @@ import type { ChannelAdapter } from "#channel/adapter.js";
4
4
  import type { ChannelDeliverySource } from "#channel/delivery-metadata.js";
5
5
  import { type ChannelCreateResult } from "#channel/channel-address.js";
6
6
  export type { ChannelCreateResult } from "#channel/channel-address.js";
7
- import type { Session } from "#channel/session.js";
7
+ import type { SessionSendOptions, Session } from "#channel/session.js";
8
8
  import type { Runtime, SessionAuthContext, TurnPolicy, SessionControlOptions } from "#channel/types.js";
9
9
  import { type Answer, type StrictAnswers } from "#shared/input.js";
10
10
  import type { JsonObject } from "#shared/json.js";
11
11
  import type { SessionHistoryMessage } from "#shared/session-history.js";
12
- interface BaseChannelSendOptions {
13
- /** Stable delivery identity, deduplicated within this session's recent-key window. */
14
- readonly idempotencyKey?: string;
15
- /**
16
- * Prior conversation added as user and assistant turns before this
17
- * message and its `context`. Seeds a session this send creates, or
18
- * extends the history of the session that owns the address.
19
- */
20
- readonly history?: readonly SessionHistoryMessage[];
21
- readonly auth: SessionAuthContext | null;
22
- readonly context?: readonly string[];
23
- /** JSON Schema for a structured final answer, as on `Session.send()`. */
24
- readonly outputSchema?: JsonObject;
25
- readonly title?: string;
26
- readonly turnPolicy?: TurnPolicy;
27
- }
28
12
  /** Options for sending a message from a channel-local continuation address. */
29
- export type ChannelSendOptions<TState = undefined> = BaseChannelSendOptions & {
13
+ export type ChannelSendOptions<TState = undefined> = SessionSendOptions & {
30
14
  readonly state?: Partial<TState>;
31
15
  };
32
16
  interface BaseChannelRespondOptions<TState = undefined> {
@@ -1,11 +1,11 @@
1
1
  import type { ChannelAdapter } from "#channel/adapter.js";
2
- import type { MessageContent } from "#shared/message-content.js";
3
2
  import type { ChannelReceiveContext } from "#channel/channel-operations.js";
4
3
  import type { NormalizedChannelCorsOptions } from "#channel/cors.js";
5
4
  import type { TypedReceiveTarget } from "#channel/receive-target.js";
6
5
  import type { RouteDefinition } from "#channel/routes.js";
7
6
  import type { Delivery } from "#shared/delivery.js";
8
- import type { SessionAuthContext, TurnPolicy } from "#channel/types.js";
7
+ import type { TurnPolicy } from "#channel/types.js";
8
+ import type { GenericReceiveInput } from "#shared/channel-definition.js";
9
9
  import type { JsonObject } from "#shared/json.js";
10
10
  export declare const CHANNEL_SENTINEL: "eve:channel";
11
11
  interface ChannelBuildMetadata {
@@ -22,11 +22,7 @@ export interface CompiledChannel<TState = undefined, TReceiveTarget = Record<str
22
22
  readonly adapter: ChannelAdapter<any>;
23
23
  readonly cors?: NormalizedChannelCorsOptions;
24
24
  readonly __metadata?: TMetadata;
25
- readonly receive?: (input: {
26
- readonly message: MessageContent;
27
- readonly target: Readonly<TReceiveTarget>;
28
- readonly auth: SessionAuthContext | null;
29
- }, ctx: ChannelReceiveContext<TState>) => Promise<Delivery>;
25
+ readonly receive?: (input: GenericReceiveInput<TReceiveTarget>, ctx: ChannelReceiveContext<TState>) => Promise<Delivery>;
30
26
  readonly turnPolicy?: TurnPolicy;
31
27
  }
32
28
  export declare function isCompiledChannel(value: unknown): value is CompiledChannel;
@@ -3,19 +3,17 @@ import type { ChannelAdapter } from "#channel/adapter.js";
3
3
  import { type ChannelReference, type CompiledChannel } from "#channel/compiled-channel.js";
4
4
  import type { ChannelDeliverySource } from "#channel/delivery-metadata.js";
5
5
  import type { InferReceiveTarget } from "#channel/receive-target.js";
6
+ import { type SessionSendOptions } from "#channel/session.js";
6
7
  import type { Delivery } from "#shared/delivery.js";
7
- import type { Runtime, SessionAuthContext, TurnPolicy } from "#channel/types.js";
8
+ import type { Runtime } from "#channel/types.js";
8
9
  import type { ResolvedChannelDefinition } from "#runtime/types.js";
9
- /**
10
- * Options for sending a message to a channel selected with `ctx.to(...)`.
11
- */
12
- interface CrossChannelSendOptions {
13
- readonly auth: SessionAuthContext | null;
14
- readonly turnPolicy?: TurnPolicy;
15
- }
16
10
  /** Message delivery bound to one channel-specific proactive target. */
17
11
  export interface CrossChannelTargetHandle {
18
- send(message: MessageContent, options: CrossChannelSendOptions): Promise<Delivery>;
12
+ /**
13
+ * Starts a session at the target, or continues the one that owns it. The
14
+ * channel's `receive()` hook gets `options` with the message and target.
15
+ */
16
+ send(message: MessageContent, options: SessionSendOptions): Promise<Delivery>;
19
17
  }
20
18
  /** Selects another authored channel and one of its proactive targets. */
21
19
  export type CrossChannelToFn = <TChannel extends ChannelReference<unknown>>(channel: TChannel, target: InferReceiveTarget<TChannel>) => CrossChannelTargetHandle;
@@ -42,7 +40,8 @@ type CrossChannelDeliverySource = Omit<ChannelDeliverySource, "channelKind" | "c
42
40
  */
43
41
  export declare function toCrossChannelTargets(channels: readonly ResolvedChannelDefinition[]): readonly CrossChannelTarget[];
44
42
  /**
45
- * Builds the `ctx.to(channel, target)` closure used by route and schedule handlers.
43
+ * Builds the `ctx.to(channel, target)` closure used by route and schedule
44
+ * handlers and tools.
46
45
  */
47
46
  export declare function createCrossChannelToFn(runtime: Runtime, channels: readonly CrossChannelTarget[], source?: CrossChannelDeliverySource): CrossChannelToFn;
48
47
  export {};
@@ -1,2 +1,2 @@
1
- import{createChannelOperations}from"#channel/channel-operations.js";import{isCompiledChannel}from"#channel/compiled-channel.js";function toCrossChannelTargets(e){return e.flatMap(e=>e.definition===void 0?[]:[{name:e.name,definition:e.definition,receive:e.receive,adapter:e.adapter,turnPolicy:e.turnPolicy}])}function createCrossChannelToFn(e,t,n={}){return(r,i)=>{let a=resolveTargetByReference(r,t);return{async send(t,r){return await invokeChannelReceive({runtime:e,source:n,target:a,input:{message:t,target:i,auth:r.auth},turnPolicy:r.turnPolicy,describeMissingReceive:()=>`ctx.to(): channel "${a.name}" does not implement receive(). Declare a receive hook on the channel to accept cross-channel sessions.`,describeMissingAdapter:()=>`ctx.to(): channel "${a.name}" has no adapter — cannot build ctx.from().`})}}}}async function invokeChannelReceive(e){if(!e.target.receive)throw Error(e.describeMissingReceive());if(!e.target.adapter)throw Error(e.describeMissingAdapter());let t=createChannelOperations({adapter:e.target.adapter,channelName:e.target.name,metadata:{...e.source,channelKind:`channel:${e.target.name}`,channelName:e.target.name},runtime:e.runtime,turnPolicy:e.turnPolicy??e.target.turnPolicy});return await e.target.receive(e.input,t)}function resolveTargetByReference(e,t){for(let n of t)if(n.definition===e)return n;let n=resolveTargetByRouteFingerprint(e,t);if(n!==null)return n;throw Error(`ctx.to(): the channel passed as the first argument is not registered in this agent's channels/. Import the channel module's default export from agent/channels/<name>.ts and pass that value.`)}function resolveTargetByRouteFingerprint(e,t){if(!isCompiledChannel(e))return null;let n=createRouteFingerprint(e);if(n===null)return null;let r=new Map;for(let e of t)createRouteFingerprint(e.definition)===n&&r.set(e.name,e);if(r.size===1)return[...r.values()][0];if(r.size>1)throw Error(`ctx.to(): the channel passed as the first argument matches multiple registered channels by route shape. Import a channel with a unique route set from agent/channels/<name>.ts before passing it to ctx.to().`);return null}function createRouteFingerprint(e){return e.routes.length===0?null:e.routes.map(e=>`${e.method.toUpperCase()} ${e.path}`).sort().join(`
1
+ import{toSessionSendOptions}from"#channel/session.js";import{createChannelOperations}from"#channel/channel-operations.js";import{isCompiledChannel}from"#channel/compiled-channel.js";function toCrossChannelTargets(e){return e.flatMap(e=>e.definition===void 0?[]:[{name:e.name,definition:e.definition,receive:e.receive,adapter:e.adapter,turnPolicy:e.turnPolicy}])}function createCrossChannelToFn(e,t,n={}){return(r,i)=>{let a=resolveTargetByReference(r,t);return{async send(t,r){return await invokeChannelReceive({runtime:e,source:n,target:a,input:{...toSessionSendOptions(r),message:t,target:i},turnPolicy:r.turnPolicy})}}}}async function invokeChannelReceive(e){let{name:t}=e.target;if(!e.target.receive)throw Error(`ctx.to(): channel "${t}" does not implement receive(). Declare a receive hook on the channel to accept cross-channel sessions.`);if(!e.target.adapter)throw Error(`ctx.to(): channel "${t}" has no adapter — cannot build ctx.from().`);let n=createChannelOperations({adapter:e.target.adapter,channelName:t,metadata:{...e.source,channelKind:`channel:${t}`,channelName:t},runtime:e.runtime,turnPolicy:e.turnPolicy??e.target.turnPolicy});return await e.target.receive(e.input,n)}function resolveTargetByReference(e,t){for(let n of t)if(n.definition===e)return n;let n=resolveTargetByRouteFingerprint(e,t);if(n!==null)return n;throw Error(`ctx.to(): the channel passed as the first argument is not registered in this agent's channels/. Import the channel module's default export from agent/channels/<name>.ts and pass that value.`)}function resolveTargetByRouteFingerprint(e,t){if(!isCompiledChannel(e))return null;let n=createRouteFingerprint(e);if(n===null)return null;let r=new Map;for(let e of t)createRouteFingerprint(e.definition)===n&&r.set(e.name,e);if(r.size===1)return[...r.values()][0];if(r.size>1)throw Error(`ctx.to(): the channel passed as the first argument matches multiple registered channels by route shape. Import a channel with a unique route set from agent/channels/<name>.ts before passing it to ctx.to().`);return null}function createRouteFingerprint(e){return e.routes.length===0?null:e.routes.map(e=>`${e.method.toUpperCase()} ${e.path}`).sort().join(`
2
2
  `)}export{createCrossChannelToFn,toCrossChannelTargets};
@@ -1 +1 @@
1
- import{randomUUID}from"node:crypto";import{commandDelivery}from"#channel/delivery.js";import{createChannelDeliveryMetadata}from"#channel/delivery-metadata.js";import{scheduleDisplayName}from"#runtime/schedules/record.js";import{SCHEDULE_APP_AUTH,SCHEDULE_APP_AUTH as SCHEDULE_APP_AUTH$1}from"#channel/schedule-auth.js";import{createCrossChannelToFn,toCrossChannelTargets}from"#channel/cross-channel-receive.js";import{ContextContainer,contextStorage}from"#context/container.js";import{AuthKey,OccurrenceIdKey,ScheduleIdKey,ScheduleInstanceKey}from"#context/keys.js";import{expectFunction}from"#internal/authored-module.js";import{parseSchedulePayload,validateSchedulePayload}from"#runtime/schedules/payload.js";const SCHEDULE_ADAPTER_KIND=`schedule`,SCHEDULE_ADAPTER={kind:SCHEDULE_ADAPTER_KIND};var ScheduleDispatcher=class{runtime;channels;constructor(e){this.runtime=e.runtime,this.channels=e.channels}async trigger(e){let t=new ContextContainer;return t.set(ScheduleIdKey,e.scheduleId),await contextStorage.run(t,()=>this.triggerInScope(e))}async triggerCollection(e){let{envelope:t}=parseSchedulePayload(e.payload,{application:e.payload.eve.application,collection:e.collectionId}),{definition:n}=e,r={...e.occurrence,displayName:scheduleDisplayName(e.occurrence.name)},i=n.preparePayload===void 0?await validateSchedulePayload(n.inputSchema,t.payload):t.payload;await e.verifyDelivery?.();let a=await n.auth({principal:t.principal,payload:i,occurrence:r});if(a===null)throw Error(`Scheduled execution is no longer authorized.`);if(a.principalId!==t.principal.principalId||a.principalType!==t.principal.type||a.authenticator!==t.principal.authenticator||a.issuer!==t.principal.issuer||a.subject!==t.principal.subject)throw Error(`Scheduled execution auth must resolve the schedule creator.`);let o=a,s=new ContextContainer;return s.set(ScheduleIdKey,e.collectionId),s.set(AuthKey,o),s.set(OccurrenceIdKey,r.executionId),s.set(ScheduleInstanceKey,r.name),await contextStorage.run(s,async()=>{let e={...this.runtime,resolveContinuation:async()=>void 0,dispatchContinuation:async e=>{if(e.command.kind!==`send`)throw Error(`Scheduled channel receive can only start a fresh session.`);return{status:`session_not_active`}},createSession:async e=>await this.runtime.createSession({...e,auth:o,initiatorAuth:o,capabilities:{requestInput:!1},continuationToken:`eve-scheduled-send:${randomUUID()}`,continuationConflictCommand:void 0})},{args:t,sessions:a,waitUntilTasks:s}=this.createHandlerContext(e);return await n.run({payload:i,occurrence:r,auth:o,to:(e,n)=>({send:r=>t.to(e,n).send(r,{auth:o})}),waitUntil:t.waitUntil}),await Promise.all(s),{sessions:a,waitUntilTasks:s}})}async triggerInScope(e){let{args:t,sessions:n,waitUntilTasks:r}=this.createHandlerContext();if(e.run)await e.run(t);else if(e.markdown!==void 0)n.push(await this.runMarkdown(e.markdown));else throw Error(`Schedule "${e.scheduleId}" has neither "run" nor "markdown" — at least one must be set.`);return{sessions:n,waitUntilTasks:r}}createHandlerContext(e=this.runtime){let t=[],n=[],r=createCrossChannelToFn(e,toCrossChannelTargets(this.channels));return{args:{appAuth:SCHEDULE_APP_AUTH$1,to(e,n){let i=r(e,n);return{async send(e,n){let r=await i.send(e,n);return t.push(r),r}}},waitUntil(e){n.push(e)}},sessions:t,waitUntilTasks:n}}async runMarkdown(e){let t=createChannelDeliveryMetadata({channelKind:`schedule`,channelName:`schedule`}),n=await this.runtime.createSession({delivery:t,adapter:SCHEDULE_ADAPTER,auth:SCHEDULE_APP_AUTH$1,input:{message:e}});return commandDelivery(this.runtime,{status:`accepted`,sessionId:n.sessionId},t.deliveryId)}};function expectScheduleRun(e,t,n){let r=e;if(typeof r!=`object`||!r)throw Error(`Schedule export "${n??`default`}" from "${t}" must be an object.`);return expectFunction(r.run,`Expected the schedule export "${n??`default`}" from "${t}" to export a \`run\` handler function.`)}export{SCHEDULE_ADAPTER,SCHEDULE_ADAPTER_KIND,SCHEDULE_APP_AUTH,ScheduleDispatcher,expectScheduleRun};
1
+ import{createHash,randomUUID}from"node:crypto";import{commandDelivery}from"#channel/delivery.js";import{createChannelDeliveryMetadata}from"#channel/delivery-metadata.js";import{scheduleDisplayName}from"#runtime/schedules/record.js";import{SCHEDULE_APP_AUTH,SCHEDULE_APP_AUTH as SCHEDULE_APP_AUTH$1}from"#channel/schedule-auth.js";import{createCrossChannelToFn,toCrossChannelTargets}from"#channel/cross-channel-receive.js";import{ContextContainer,contextStorage}from"#context/container.js";import{AuthKey,OccurrenceIdKey,ScheduleIdKey,ScheduleInstanceKey}from"#context/keys.js";import{expectFunction}from"#internal/authored-module.js";import{parseSchedulePayload,validateSchedulePayload}from"#runtime/schedules/payload.js";const SCHEDULE_ADAPTER_KIND=`schedule`,SCHEDULE_ADAPTER={kind:SCHEDULE_ADAPTER_KIND};var ScheduleDispatcher=class{runtime;channels;constructor(e){this.runtime=e.runtime,this.channels=e.channels}async trigger(e){let t=new ContextContainer;return t.set(ScheduleIdKey,e.scheduleId),await contextStorage.run(t,()=>this.triggerInScope(e))}async triggerCollection(e){let{envelope:t}=parseSchedulePayload(e.payload,{application:e.payload.eve.application,collection:e.collectionId}),{definition:n}=e,r={...e.occurrence,displayName:scheduleDisplayName(e.occurrence.name)},i=n.preparePayload===void 0?await validateSchedulePayload(n.inputSchema,t.payload):t.payload;await e.verifyDelivery?.();let a=await n.auth({principal:t.principal,payload:i,occurrence:r});if(a===null)throw Error(`Scheduled execution is no longer authorized.`);if(a.principalId!==t.principal.principalId||a.principalType!==t.principal.type||a.authenticator!==t.principal.authenticator||a.issuer!==t.principal.issuer||a.subject!==t.principal.subject)throw Error(`Scheduled execution auth must resolve the schedule creator.`);let o=a,s=new ContextContainer;s.set(ScheduleIdKey,e.collectionId),s.set(AuthKey,o),s.set(OccurrenceIdKey,r.executionId),s.set(ScheduleInstanceKey,r.name);let scheduledToken=(e,t)=>t===void 0?`eve-scheduled-send:${randomUUID()}`:`eve-scheduled-send:${createHash(`sha256`).update(JSON.stringify([r.scheduleId,e,t])).digest(`hex`)}`,freshRun=e=>({...e,auth:o,initiatorAuth:o,capabilities:{requestInput:!1},continuationToken:scheduledToken(e.continuationToken,e.idempotencyKey),continuationConflictCommand:e.idempotencyKey===void 0?void 0:e.continuationConflictCommand});return await contextStorage.run(s,async()=>{let e={...this.runtime,resolveContinuation:async()=>void 0,dispatchContinuation:async e=>{let{command:t}=e;if(t.kind!==`send`)throw Error(`Scheduled channel receive can only start a fresh session.`);return t.idempotencyKey===void 0?{status:`session_not_active`}:await this.runtime.dispatchContinuation({command:t,continuationToken:scheduledToken(e.continuationToken,t.idempotencyKey),successor:e.successor&&freshRun(e.successor)})},createSession:async e=>await this.runtime.createSession(freshRun(e))},{args:t,sessions:a,waitUntilTasks:s}=this.createHandlerContext(e);return await n.run({payload:i,occurrence:r,auth:o,to:(e,n)=>({send:(r,i)=>t.to(e,n).send(r,{...i,auth:o})}),waitUntil:t.waitUntil}),await Promise.all(s),{sessions:a,waitUntilTasks:s}})}async triggerInScope(e){let{args:t,sessions:n,waitUntilTasks:r}=this.createHandlerContext();if(e.run)await e.run(t);else if(e.markdown!==void 0)n.push(await this.runMarkdown(e.markdown));else throw Error(`Schedule "${e.scheduleId}" has neither "run" nor "markdown" — at least one must be set.`);return{sessions:n,waitUntilTasks:r}}createHandlerContext(e=this.runtime){let t=[],n=[],r=createCrossChannelToFn(e,toCrossChannelTargets(this.channels));return{args:{appAuth:SCHEDULE_APP_AUTH$1,to(e,n){let i=r(e,n);return{async send(e,n){let r=await i.send(e,n);return t.push(r),r}}},waitUntil(e){n.push(e)}},sessions:t,waitUntilTasks:n}}async runMarkdown(e){let t=createChannelDeliveryMetadata({channelKind:`schedule`,channelName:`schedule`}),n=await this.runtime.createSession({delivery:t,adapter:SCHEDULE_ADAPTER,auth:SCHEDULE_APP_AUTH$1,input:{message:e}});return commandDelivery(this.runtime,{status:`accepted`,sessionId:n.sessionId},t.deliveryId)}};function expectScheduleRun(e,t,n){let r=e;if(typeof r!=`object`||!r)throw Error(`Schedule export "${n??`default`}" from "${t}" must be an object.`);return expectFunction(r.run,`Expected the schedule export "${n??`default`}" from "${t}" to export a \`run\` handler function.`)}export{SCHEDULE_ADAPTER,SCHEDULE_ADAPTER_KIND,SCHEDULE_APP_AUTH,ScheduleDispatcher,expectScheduleRun};
@@ -48,14 +48,36 @@ interface SessionDeliveryOptions {
48
48
  readonly context?: readonly string[];
49
49
  readonly outputSchema?: JsonObject;
50
50
  }
51
- /** Options for sending a message through a fixed session handle. */
52
- export type SessionSendOptions = SessionDeliveryOptions & {
51
+ /**
52
+ * Options every server-side message send accepts: `Session.send()`,
53
+ * `from(address).send()`, `to(channel, target).send()`, and the input a
54
+ * channel's `receive()` hook gets.
55
+ */
56
+ export interface SessionSendOptions {
57
+ /** Who the session runs as. */
58
+ readonly auth: SessionAuthContext | null;
59
+ /** Strings added as user messages before the message, kept in session history. */
60
+ readonly context?: readonly string[];
53
61
  /** Prior conversation added as user and assistant turns before this message and its `context`. */
54
62
  readonly history?: readonly SessionHistoryMessage[];
55
- /** Initial workflow title for a prewarmed session. */
63
+ /**
64
+ * Stable delivery identity. Deduplicated within the receiving session's recent-key window, which
65
+ * every sender to that session shares, so make it unique across senders, for example by
66
+ * prefixing the source. A threadless Slack target also derives its session from it.
67
+ */
68
+ readonly idempotencyKey?: string;
69
+ /** JSON Schema for a structured final answer. */
70
+ readonly outputSchema?: JsonObject;
71
+ /** Workflow run title for a session this send starts. Defaults to one derived from the message. */
56
72
  readonly title?: string;
73
+ /** How the message treats a running turn. */
57
74
  readonly turnPolicy?: TurnPolicy;
58
- };
75
+ }
76
+ /**
77
+ * Copies only the {@link SessionSendOptions} fields and validates the key. Callers can pass wider
78
+ * objects, which must not carry internal send fields such as `callback` across a channel boundary.
79
+ */
80
+ export declare function toSessionSendOptions(options: SessionSendOptions): SessionSendOptions;
59
81
  /** Options for answering pending input requests through a fixed session handle. */
60
82
  export type SessionRespondOptions = SessionDeliveryOptions;
61
83
  export declare function createSession(id: string, runtime: Runtime, metadata?: Partial<ChannelDeliverySource> & {
@@ -1 +1 @@
1
- import{attachClientContext,readClientContext}from"#internal/client-context.js";import{commandDelivery}from"#channel/delivery.js";import{validateDeliveryIdempotencyKey}from"#channel/delivery-idempotency.js";import{createChannelDeliveryMetadata}from"#channel/delivery-metadata.js";import{serializeFilePartsInMessage}from"#channel/send-input.js";import{DEFAULT_TURN_POLICY,controlCommand}from"#channel/types.js";import{validateSessionHistory}from"#shared/session-history.js";import{parseAnswers}from"#shared/input.js";import{AuthKey,ContinuationHookTokensKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";import{toChannelLocalContinuationToken}from"#shared/continuation-token.js";function internalSession(e){return e}function createSession(e,t,n={}){return{id:e,async send(r,i){validateDeliveryIdempotencyKey(i.idempotencyKey);let a=createDelivery(n,i.deliveryId),o=sessionCallbackToTurnCaller(i.callback),s=validateSessionHistory(i.history),c=attachClientContext({message:serializeFilePartsInMessage(r)},readClientContext(i));i.context!==void 0&&(c.context=i.context),s!==void 0&&(c.history=s),i.outputSchema!==void 0&&(c.outputSchema=i.outputSchema);let l={idempotencyKey:i.idempotencyKey,auth:i.auth,delivery:a,kind:`send`,payload:c,requestId:n.requestId,turnPolicy:i.turnPolicy??n.turnPolicy??DEFAULT_TURN_POLICY,title:i.title},u=await t.dispatchSession({command:o===void 0?l:{...l,caller:o},sessionId:e,inbox:i.inbox});return commandDelivery(t,u,a.deliveryId)},async respond(r,i){if(validateDeliveryIdempotencyKey(i.idempotencyKey),r.length===0)throw Error(`respond() requires at least one answer.`);let a=parseAnswers(r),o=sessionCallbackToTurnCaller(i.callback),s=createDelivery(n,i.deliveryId),c=attachClientContext({answers:a},readClientContext(i));i.context!==void 0&&(c.context=i.context),i.outputSchema!==void 0&&(c.outputSchema=i.outputSchema);let l={idempotencyKey:i.idempotencyKey,auth:i.auth,delivery:s,kind:`send`,payload:c,requestId:n.requestId},u=await t.dispatchSession({command:o===void 0?l:{...l,caller:o},sessionId:e,inbox:i.inbox});return commandDelivery(t,u,s.deliveryId)},async cancel(n){let r=controlCommand({kind:`cancel`,turnId:n?.turnId},n),i=await t.dispatchSession({command:r,sessionId:e});return commandDelivery(t,i,r.deliveryId)},async prewarm(){return await t.dispatchSession({command:{kind:`prewarm`,targetDeploymentId:n.acceptedDeploymentId},sessionId:e})},async compact(n){let r=controlCommand({kind:`compact`},n),i=await t.dispatchSession({command:r,sessionId:e});return commandDelivery(t,i,r.deliveryId)},async clear(n){let r=controlCommand({kind:`clear`},n),i=await t.dispatchSession({command:r,sessionId:e});return commandDelivery(t,i,r.deliveryId)},async reset(n){let r=controlCommand({kind:`reset`,reason:n?.reason},n),i=await t.dispatchSession({command:r,sessionId:e});return commandDelivery(t,i,r.deliveryId,{follow:!1})},async*stream(n){yield*await t.getEventStream(e,n)},async getLineStream(n){return t.getLineStream(e,n)},async getStreamTailIndex(){return t.getStreamTailIndex(e)},async hasRunnableOwner(){return await t.hasRunnableOwner?.(e)??!0},async getChildBinding(n){return await t.readChildBinding?.(e,n)}}}function createAttachSessionFn(e,t={}){return n=>createSession(n,e,t)}function createDelivery(e,t){let n=createChannelDeliveryMetadata({channelKind:`http`,channelName:`http`,...e});return t===void 0?n:{...n,deliveryId:t}}function buildChannelContext(e){return{session:{get id(){return e.get(SessionIdKey)??``},get auth(){return{current:e.get(AuthKey)??null,initiator:e.get(InitiatorAuthKey)??null}}},get continuation(){let t=e.get(ContinuationTokenKey);if(t!==void 0&&t.length!==0)return{token:toChannelLocalContinuationToken(t),alias(n){if(n.length===0)throw Error(`A session alias requires a nonempty token.`);let r=namespaceContinuationToken(t,n);t!==r&&(e.set(ContinuationHookTokensKey,e=>{let n=e??[t];return n.includes(r)?n:[...n,r]}),e.set(ContinuationTokenKey,r))}}}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}function sessionCallbackToTurnCaller(e){return e===void 0?void 0:{callId:e.callId,replyTo:{kind:`callback`,token:e.token,url:e.url},subagentName:e.subagentName}}export{buildChannelContext,createAttachSessionFn,createSession,internalSession,sessionCallbackToTurnCaller};
1
+ import{attachClientContext,readClientContext}from"#internal/client-context.js";import{commandDelivery}from"#channel/delivery.js";import{validateDeliveryIdempotencyKey}from"#channel/delivery-idempotency.js";import{createChannelDeliveryMetadata}from"#channel/delivery-metadata.js";import{serializeFilePartsInMessage}from"#channel/send-input.js";import{DEFAULT_TURN_POLICY,controlCommand}from"#channel/types.js";import{validateSessionHistory}from"#shared/session-history.js";import{parseAnswers}from"#shared/input.js";import{AuthKey,ContinuationHookTokensKey,ContinuationTokenKey,InitiatorAuthKey,SessionIdKey}from"#context/keys.js";import{toChannelLocalContinuationToken}from"#shared/continuation-token.js";function internalSession(e){return e}const SESSION_SEND_OPTION_KEYS=Object.keys({auth:!0,context:!0,history:!0,idempotencyKey:!0,outputSchema:!0,title:!0,turnPolicy:!0});function toSessionSendOptions(e){validateDeliveryIdempotencyKey(e.idempotencyKey);let t={};for(let n of SESSION_SEND_OPTION_KEYS)e[n]!==void 0&&(t[n]=e[n]);return t}function createSession(e,t,n={}){return{id:e,async send(r,i){validateDeliveryIdempotencyKey(i.idempotencyKey);let a=createDelivery(n,i.deliveryId),o=sessionCallbackToTurnCaller(i.callback),s=validateSessionHistory(i.history),c=attachClientContext({message:serializeFilePartsInMessage(r)},readClientContext(i));i.context!==void 0&&(c.context=i.context),s!==void 0&&(c.history=s),i.outputSchema!==void 0&&(c.outputSchema=i.outputSchema);let l={idempotencyKey:i.idempotencyKey,auth:i.auth,delivery:a,kind:`send`,payload:c,requestId:n.requestId,turnPolicy:i.turnPolicy??n.turnPolicy??DEFAULT_TURN_POLICY,title:i.title},u=await t.dispatchSession({command:o===void 0?l:{...l,caller:o},sessionId:e,inbox:i.inbox});return commandDelivery(t,u,a.deliveryId)},async respond(r,i){if(validateDeliveryIdempotencyKey(i.idempotencyKey),r.length===0)throw Error(`respond() requires at least one answer.`);let a=parseAnswers(r),o=sessionCallbackToTurnCaller(i.callback),s=createDelivery(n,i.deliveryId),c=attachClientContext({answers:a},readClientContext(i));i.context!==void 0&&(c.context=i.context),i.outputSchema!==void 0&&(c.outputSchema=i.outputSchema);let l={idempotencyKey:i.idempotencyKey,auth:i.auth,delivery:s,kind:`send`,payload:c,requestId:n.requestId},u=await t.dispatchSession({command:o===void 0?l:{...l,caller:o},sessionId:e,inbox:i.inbox});return commandDelivery(t,u,s.deliveryId)},async cancel(n){let r=controlCommand({kind:`cancel`,turnId:n?.turnId},n),i=await t.dispatchSession({command:r,sessionId:e});return commandDelivery(t,i,r.deliveryId)},async prewarm(){return await t.dispatchSession({command:{kind:`prewarm`,targetDeploymentId:n.acceptedDeploymentId},sessionId:e})},async compact(n){let r=controlCommand({kind:`compact`},n),i=await t.dispatchSession({command:r,sessionId:e});return commandDelivery(t,i,r.deliveryId)},async clear(n){let r=controlCommand({kind:`clear`},n),i=await t.dispatchSession({command:r,sessionId:e});return commandDelivery(t,i,r.deliveryId)},async reset(n){let r=controlCommand({kind:`reset`,reason:n?.reason},n),i=await t.dispatchSession({command:r,sessionId:e});return commandDelivery(t,i,r.deliveryId,{follow:!1})},async*stream(n){yield*await t.getEventStream(e,n)},async getLineStream(n){return t.getLineStream(e,n)},async getStreamTailIndex(){return t.getStreamTailIndex(e)},async hasRunnableOwner(){return await t.hasRunnableOwner?.(e)??!0},async getChildBinding(n){return await t.readChildBinding?.(e,n)}}}function createAttachSessionFn(e,t={}){return n=>createSession(n,e,t)}function createDelivery(e,t){let n=createChannelDeliveryMetadata({channelKind:`http`,channelName:`http`,...e});return t===void 0?n:{...n,deliveryId:t}}function buildChannelContext(e){return{session:{get id(){return e.get(SessionIdKey)??``},get auth(){return{current:e.get(AuthKey)??null,initiator:e.get(InitiatorAuthKey)??null}}},get continuation(){let t=e.get(ContinuationTokenKey);if(t!==void 0&&t.length!==0)return{token:toChannelLocalContinuationToken(t),alias(n){if(n.length===0)throw Error(`A session alias requires a nonempty token.`);let r=namespaceContinuationToken(t,n);t!==r&&(e.set(ContinuationHookTokensKey,e=>{let n=e??[t];return n.includes(r)?n:[...n,r]}),e.set(ContinuationTokenKey,r))}}}}}function namespaceContinuationToken(e,t){let n=e.indexOf(`:`);if(n<=0)throw Error(`Cannot set session continuation token without an existing namespaced continuation token. Start the session with a placeholder continuationToken.`);return`${e.slice(0,n+1)}${t}`}function sessionCallbackToTurnCaller(e){return e===void 0?void 0:{callId:e.callId,replyTo:{kind:`callback`,token:e.token,url:e.url},subagentName:e.subagentName}}export{buildChannelContext,createAttachSessionFn,createSession,internalSession,sessionCallbackToTurnCaller,toSessionSendOptions};
@@ -2299,6 +2299,7 @@ async function openStreamBody(input) {
2299
2299
  signal
2300
2300
  });
2301
2301
  } catch (error) {
2302
+ if (input.redirect === "error" && error instanceof Error && error.cause instanceof Error && error.cause.message === "unexpected redirect") throw new Error("The session stream refused a redirect. Use the final agent URL instead.", { cause: error });
2302
2303
  if (input.signal?.aborted || !isStreamDisconnectError(error) || attempt === openRetryPolicy.maxAttempts - 1) throw error;
2303
2304
  await sleep(retryDelayMs, input.signal);
2304
2305
  retryDelayMs = Math.min(retryDelayMs * 2, openRetryPolicy.maxDelayMs);
@@ -3253,7 +3254,7 @@ var Client = class {
3253
3254
  this.#baseUrl = options.baseUrl;
3254
3255
  this.#auth = options.auth;
3255
3256
  this.#headers = options.headers;
3256
- this.#redirect = options.redirect;
3257
+ this.#redirect = options.redirect ?? "error";
3257
3258
  this.sessions = new ClientSessions({
3258
3259
  baseUrl: this.#baseUrl,
3259
3260
  redirect: this.#redirect,
@@ -3350,7 +3351,7 @@ function headersInitToRecord(headers) {
3350
3351
  return Object.fromEntries(new Headers(headers).entries());
3351
3352
  }
3352
3353
  function withRedirectPolicy(init, redirect) {
3353
- return redirect === void 0 ? init : {
3354
+ return {
3354
3355
  ...init,
3355
3356
  redirect
3356
3357
  };
@@ -2300,6 +2300,7 @@ async function openStreamBody(input) {
2300
2300
  signal
2301
2301
  });
2302
2302
  } catch (error) {
2303
+ if (input.redirect === "error" && error instanceof Error && error.cause instanceof Error && error.cause.message === "unexpected redirect") throw new Error("The session stream refused a redirect. Use the final agent URL instead.", { cause: error });
2303
2304
  if (input.signal?.aborted || !isStreamDisconnectError(error) || attempt === openRetryPolicy.maxAttempts - 1) throw error;
2304
2305
  await sleep(retryDelayMs, input.signal);
2305
2306
  retryDelayMs = Math.min(retryDelayMs * 2, openRetryPolicy.maxDelayMs);
@@ -3254,7 +3255,7 @@ var Client = class {
3254
3255
  this.#baseUrl = options.baseUrl;
3255
3256
  this.#auth = options.auth;
3256
3257
  this.#headers = options.headers;
3257
- this.#redirect = options.redirect;
3258
+ this.#redirect = options.redirect ?? "error";
3258
3259
  this.sessions = new ClientSessions({
3259
3260
  baseUrl: this.#baseUrl,
3260
3261
  redirect: this.#redirect,
@@ -3351,7 +3352,7 @@ function headersInitToRecord(headers) {
3351
3352
  return Object.fromEntries(new Headers(headers).entries());
3352
3353
  }
3353
3354
  function withRedirectPolicy(init, redirect) {
3354
- return redirect === void 0 ? init : {
3355
+ return {
3355
3356
  ...init,
3356
3357
  redirect
3357
3358
  };
@@ -1 +1 @@
1
- import{EVE_HEALTH_ROUTE_PATH,EVE_INFO_ROUTE_PATH}from"#protocol/routes.js";import{encodeBasicCredentials}from"#internal/http/basic-auth.js";import{ClientError}from"#client/client-error.js";import{AgentInfoResponseError}from"#client/agent-info-error.js";import{HealthResponseError}from"#client/health-response-error.js";import{HealthResultSchema}from"#client/health-schema.js";import{AgentInfoResultSchema}from"#client/agent-info-schema.js";import{ClientSessions}from"#client/sessions.js";import{createClientUrl}from"#client/url.js";import{VERCEL_TRUSTED_OIDC_IDP_TOKEN_HEADER}from"#client/types.js";var Client=class{#e;#t;#n;#r;sessions;constructor(e){this.#n=e.baseUrl,this.#e=e.auth,this.#t=e.headers,this.#r=e.redirect,this.sessions=new ClientSessions({baseUrl:this.#n,redirect:this.#r,resolveHeaders:e=>this.#i(e)})}async health(){let e=createClientUrl(this.#n,EVE_HEALTH_ROUTE_PATH),t=await this.#i(),n=await fetch(e,withRedirectPolicy({headers:t},this.#r));if(!n.ok){let e=await n.text();throw new ClientError(n.status,e,n.headers)}let r;try{r=await n.json()}catch{throw new HealthResponseError}let i=HealthResultSchema.safeParse(r);if(!i.success)throw new HealthResponseError(i.error.issues.slice(0,5).map(e=>{let t=e.path.join(`.`);return t.length===0?e.message:`${t}: ${e.message}`}));return i.data}async info(e={}){let t=await this.fetch(EVE_INFO_ROUTE_PATH,e);if(!t.ok){let e=await t.text();throw new ClientError(t.status,e,t.headers)}let n;try{n=await t.json()}catch{throw new AgentInfoResponseError}let r=AgentInfoResultSchema.safeParse(n);if(!r.success)throw new AgentInfoResponseError(r.error.issues.slice(0,5).map(e=>{let t=e.path.join(`.`);return t.length===0?e.message:`${t}: ${e.message}`}));return r.data}async fetch(e,t={}){let n=createClientUrl(this.#n,e),r=await this.#i(headersInitToRecord(t.headers));return await fetch(n,withRedirectPolicy({...t,headers:r},this.#r))}async#i(e){let t=new Headers,[n,r]=await Promise.all([resolveHeadersValue(this.#t),this.#a()]);for(let[e,r]of Object.entries(n))t.set(e,r);for(let[e,n]of Object.entries(r))t.set(e,n);if(e)for(let[n,r]of Object.entries(e))t.set(n,r);return t}async#a(){let e=this.#e;if(!e)return{};if(`vercelOidc`in e){let t=(await resolveTokenValue(e.vercelOidc.token)).trim();return t.length===0?{}:{authorization:`Bearer ${t}`,[VERCEL_TRUSTED_OIDC_IDP_TOKEN_HEADER]:t}}if(`bearer`in e){let t=(await resolveTokenValue(e.bearer)).trim();return t.length===0?{}:{authorization:`Bearer ${t}`}}if(`basic`in e){let t=await resolveTokenValue(e.basic.password);return{authorization:`Basic ${encodeBasicCredentials(e.basic.username,t)}`}}return{}}};async function resolveTokenValue(e){return typeof e==`function`?e():e}async function resolveHeadersValue(e){return e===void 0?{}:typeof e==`function`?await e():e}function headersInitToRecord(e){return e===void 0?{}:Object.fromEntries(new Headers(e).entries())}function withRedirectPolicy(e,t){return t===void 0?e:{...e,redirect:t}}export{Client};
1
+ import{EVE_HEALTH_ROUTE_PATH,EVE_INFO_ROUTE_PATH}from"#protocol/routes.js";import{encodeBasicCredentials}from"#internal/http/basic-auth.js";import{ClientError}from"#client/client-error.js";import{AgentInfoResponseError}from"#client/agent-info-error.js";import{HealthResponseError}from"#client/health-response-error.js";import{HealthResultSchema}from"#client/health-schema.js";import{AgentInfoResultSchema}from"#client/agent-info-schema.js";import{ClientSessions}from"#client/sessions.js";import{createClientUrl}from"#client/url.js";import{VERCEL_TRUSTED_OIDC_IDP_TOKEN_HEADER}from"#client/types.js";var Client=class{#e;#t;#n;#r;sessions;constructor(e){this.#n=e.baseUrl,this.#e=e.auth,this.#t=e.headers,this.#r=e.redirect??`error`,this.sessions=new ClientSessions({baseUrl:this.#n,redirect:this.#r,resolveHeaders:e=>this.#i(e)})}async health(){let e=createClientUrl(this.#n,EVE_HEALTH_ROUTE_PATH),t=await this.#i(),n=await fetch(e,withRedirectPolicy({headers:t},this.#r));if(!n.ok){let e=await n.text();throw new ClientError(n.status,e,n.headers)}let r;try{r=await n.json()}catch{throw new HealthResponseError}let i=HealthResultSchema.safeParse(r);if(!i.success)throw new HealthResponseError(i.error.issues.slice(0,5).map(e=>{let t=e.path.join(`.`);return t.length===0?e.message:`${t}: ${e.message}`}));return i.data}async info(e={}){let t=await this.fetch(EVE_INFO_ROUTE_PATH,e);if(!t.ok){let e=await t.text();throw new ClientError(t.status,e,t.headers)}let n;try{n=await t.json()}catch{throw new AgentInfoResponseError}let r=AgentInfoResultSchema.safeParse(n);if(!r.success)throw new AgentInfoResponseError(r.error.issues.slice(0,5).map(e=>{let t=e.path.join(`.`);return t.length===0?e.message:`${t}: ${e.message}`}));return r.data}async fetch(e,t={}){let n=createClientUrl(this.#n,e),r=await this.#i(headersInitToRecord(t.headers));return await fetch(n,withRedirectPolicy({...t,headers:r},this.#r))}async#i(e){let t=new Headers,[n,r]=await Promise.all([resolveHeadersValue(this.#t),this.#a()]);for(let[e,r]of Object.entries(n))t.set(e,r);for(let[e,n]of Object.entries(r))t.set(e,n);if(e)for(let[n,r]of Object.entries(e))t.set(n,r);return t}async#a(){let e=this.#e;if(!e)return{};if(`vercelOidc`in e){let t=(await resolveTokenValue(e.vercelOidc.token)).trim();return t.length===0?{}:{authorization:`Bearer ${t}`,[VERCEL_TRUSTED_OIDC_IDP_TOKEN_HEADER]:t}}if(`bearer`in e){let t=(await resolveTokenValue(e.bearer)).trim();return t.length===0?{}:{authorization:`Bearer ${t}`}}if(`basic`in e){let t=await resolveTokenValue(e.basic.password);return{authorization:`Basic ${encodeBasicCredentials(e.basic.username,t)}`}}return{}}};async function resolveTokenValue(e){return typeof e==`function`?e():e}async function resolveHeadersValue(e){return e===void 0?{}:typeof e==`function`?await e():e}function headersInitToRecord(e){return e===void 0?{}:Object.fromEntries(new Headers(e).entries())}function withRedirectPolicy(e,t){return{...e,redirect:t}}export{Client};
@@ -1 +1 @@
1
- import{SessionNotActiveError}from"#channel/session-not-active-error.js";import{ClientError,ClientSessionStrandedError,createClientError}from"#client/client-error.js";import{createEventReader}from"#protocol/session-lines.js";import{EVE_STREAM_TAIL_INDEX_HEADER}from"#protocol/session-http.js";import{createClientUrl}from"#client/url.js";import{throwIfAborted}from"#client/abort-signal.js";import{isV26Line}from"#protocol/v26-lines.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";import{readMessageStreamVersion}from"#client/stream-version.js";const RECONNECT_BACKOFF={baseDelayMs:250,maxDelayMs:5e3},DEFAULT_STREAM_RECONNECT_POLICY={reconnect:!0,retryableErrorStatuses:new Set([404,409,425,500,502,503,504]),streamOpenReconnectPolicy:{baseDelayMs:250,maxAttempts:12,maxDelayMs:5e3}},NO_STREAM_RECONNECT_POLICY={...DEFAULT_STREAM_RECONNECT_POLICY,reconnect:!1,streamOpenReconnectPolicy:{...DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy,maxAttempts:1}};function isRetryableStreamError(e,t=DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses){return e instanceof ClientSessionStrandedError?!1:SessionNotActiveError.is(e)?t.has(409):e instanceof ClientError?e.code!==`session_version_unsupported`&&t.has(e.status):isStreamDisconnectError(e)}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{reconnect:!0,retryableErrorStatuses:t?.retryableErrorStatuses?new Set(t.retryableErrorStatuses):DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses,streamOpenReconnectPolicy:resolveRetryPolicy(t?.streamOpenReconnectPolicy,DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy)}}async function*followStreamLines(e){let resolvePolicy=()=>resolveStreamReconnectPolicy(e.resolveReconnectPolicy===void 0?e.streamReconnectPolicy:e.resolveReconnectPolicy()),t=e.follow===!1||e.onCaughtUp!==void 0,n=e.startIndex,r=RECONNECT_BACKOFF.baseDelayMs,i=0,a,o=!1,passedTail=()=>a!==void 0&&n>a,noteProgress=()=>(!o&&passedTail()&&(o=!0,e.onCaughtUp?.()),e.follow===!1&&passedTail());for(;;){let o=resolvePolicy(),s;try{s=await openStreamBody({...e,retryPolicy:o,startIndex:n,requestTailIndex:(t||n<0)&&a===void 0})}catch(t){if(e.signal?.aborted)return;throw t}if((t||n<0)&&a===void 0){if(a=s.tailIndex,a===void 0)throw s.close(),Error(`This read requires the server to report the ${EVE_STREAM_TAIL_INDEX_HEADER} header. The agent may be running an older eve version.`);n<0&&(n=Math.max(0,a+1+n))}try{e.onOpen?.(s.headers)}catch(e){throw s.close(),e}if(noteProgress()){s.close();return}let c=!1,l=!1;try{for await(let t of readNdjsonStream(s.body,{signal:e.signal,idleTimeoutMs:e.streamReadIdleTimeoutMs??3e4}))switch(t.kind){case`transport`:switch(t.record.$eve){case`position`:if(t.record.next>n&&(n=t.record.next),e.onPosition?.(n),noteProgress())return;break;case`stream.lease-ended`:l=!0;break;case`stream.ended`:c=!0}continue;case`unknown-transport`:continue;case`commit`:case`progress`:case`invalid`:{if(t.kind===`invalid`&&isV26Line(t.value))throw new ClientError(409,JSON.stringify({code:`session_version_unsupported`,error:`This session was started by an earlier eve version. Start a new session.`}));let a=n;if(n+=1,i=0,r=RECONNECT_BACKOFF.baseDelayMs,yield{line:t.kind===`invalid`?void 0:t.line,position:a},e.onPosition?.(n),noteProgress())return}}}catch(e){if(!isStreamDisconnectError(e))throw e}finally{s.close()}if(c||e.signal?.aborted||!resolvePolicy().reconnect)return;if(!l){if(i+=1,e.follow===!1&&i>=o.streamOpenReconnectPolicy.maxAttempts)throw Error(`The session stream kept disconnecting before the read reached its tail.`);if(await sleep(r,e.signal),e.signal?.aborted)return;r=Math.min(r*2,RECONNECT_BACKOFF.maxDelayMs)}}}async function*followStreamIterable(e){let t=createEventReader();for await(let{line:n,position:r}of followStreamLines(e)){if(n===void 0)continue;let e=t.read(n,r);for(let[t,n]of e.entries())yield{cursor:t===e.length-1?r+1:r,event:n}}}async function openStreamBody(e){let t=e.retryPolicy??resolveStreamReconnectPolicy(e.streamReconnectPolicy),n=t.streamOpenReconnectPolicy,r,i,a,o=n.baseDelayMs,s={...e.searchParams};e.startIndex!==0&&(s.startIndex=String(e.startIndex)),e.requestTailIndex===!0&&(s.includeTailIndex=`1`),e.follow===!1&&(s.follow=`false`);for(let c=0;c<n.maxAttempts;c+=1){throwIfAborted(e.signal);let l=createClientUrl(e.baseUrl,e.path,Object.keys(s).length>0?s:void 0),u=await e.resolveHeaders();throwIfAborted(e.signal);let d=new AbortController,f=e.signal?AbortSignal.any([e.signal,d.signal]):d.signal,p;try{p=await fetch(l,{cache:`no-store`,headers:u,redirect:e.redirect,signal:f})}catch(t){if(e.signal?.aborted||!isStreamDisconnectError(t)||c===n.maxAttempts-1)throw t;await sleep(o,e.signal),o=Math.min(o*2,n.maxDelayMs);continue}if(p.ok){if(!p.body)throw new ClientError(p.status,`Response body is null.`,p.headers);try{readMessageStreamVersion(p.headers)}catch(e){throw p.body.cancel().catch(()=>{}),d.abort(),e}let e=!1;return{headers:p.headers,body:p.body,close:()=>{e||(e=!0,p.body?.cancel().catch(()=>{}),d.abort())},tailIndex:parseTailIndexHeader(p.headers)}}r=p.status,i=await p.text(),a=p.headers;let m=createClientError(p.status,i,p.headers);if(!isRetryableStreamError(m,t.retryableErrorStatuses))throw m;c<n.maxAttempts-1&&(await sleep(o,e.signal),o=Math.min(o*2,n.maxDelayMs))}throw new ClientError(r??0,i??`Failed to open message stream.`,a)}function parseTailIndexHeader(e){let t=e.get(EVE_STREAM_TAIL_INDEX_HEADER);if(t===null||!/^-?\d+$/.test(t))return;let n=Number(t);return Number.isSafeInteger(n)?n:void 0}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{DEFAULT_STREAM_RECONNECT_POLICY,RECONNECT_BACKOFF,followStreamIterable,followStreamLines,isRetryableStreamError,openStreamBody,sleep};
1
+ import{SessionNotActiveError}from"#channel/session-not-active-error.js";import{ClientError,ClientSessionStrandedError,createClientError}from"#client/client-error.js";import{createEventReader}from"#protocol/session-lines.js";import{EVE_STREAM_TAIL_INDEX_HEADER}from"#protocol/session-http.js";import{createClientUrl}from"#client/url.js";import{throwIfAborted}from"#client/abort-signal.js";import{isV26Line}from"#protocol/v26-lines.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";import{readMessageStreamVersion}from"#client/stream-version.js";const RECONNECT_BACKOFF={baseDelayMs:250,maxDelayMs:5e3},DEFAULT_STREAM_RECONNECT_POLICY={reconnect:!0,retryableErrorStatuses:new Set([404,409,425,500,502,503,504]),streamOpenReconnectPolicy:{baseDelayMs:250,maxAttempts:12,maxDelayMs:5e3}},NO_STREAM_RECONNECT_POLICY={...DEFAULT_STREAM_RECONNECT_POLICY,reconnect:!1,streamOpenReconnectPolicy:{...DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy,maxAttempts:1}};function isRetryableStreamError(e,t=DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses){return e instanceof ClientSessionStrandedError?!1:SessionNotActiveError.is(e)?t.has(409):e instanceof ClientError?e.code!==`session_version_unsupported`&&t.has(e.status):isStreamDisconnectError(e)}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{reconnect:!0,retryableErrorStatuses:t?.retryableErrorStatuses?new Set(t.retryableErrorStatuses):DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses,streamOpenReconnectPolicy:resolveRetryPolicy(t?.streamOpenReconnectPolicy,DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy)}}async function*followStreamLines(e){let resolvePolicy=()=>resolveStreamReconnectPolicy(e.resolveReconnectPolicy===void 0?e.streamReconnectPolicy:e.resolveReconnectPolicy()),t=e.follow===!1||e.onCaughtUp!==void 0,n=e.startIndex,r=RECONNECT_BACKOFF.baseDelayMs,i=0,a,o=!1,passedTail=()=>a!==void 0&&n>a,noteProgress=()=>(!o&&passedTail()&&(o=!0,e.onCaughtUp?.()),e.follow===!1&&passedTail());for(;;){let o=resolvePolicy(),s;try{s=await openStreamBody({...e,retryPolicy:o,startIndex:n,requestTailIndex:(t||n<0)&&a===void 0})}catch(t){if(e.signal?.aborted)return;throw t}if((t||n<0)&&a===void 0){if(a=s.tailIndex,a===void 0)throw s.close(),Error(`This read requires the server to report the ${EVE_STREAM_TAIL_INDEX_HEADER} header. The agent may be running an older eve version.`);n<0&&(n=Math.max(0,a+1+n))}try{e.onOpen?.(s.headers)}catch(e){throw s.close(),e}if(noteProgress()){s.close();return}let c=!1,l=!1;try{for await(let t of readNdjsonStream(s.body,{signal:e.signal,idleTimeoutMs:e.streamReadIdleTimeoutMs??3e4}))switch(t.kind){case`transport`:switch(t.record.$eve){case`position`:if(t.record.next>n&&(n=t.record.next),e.onPosition?.(n),noteProgress())return;break;case`stream.lease-ended`:l=!0;break;case`stream.ended`:c=!0}continue;case`unknown-transport`:continue;case`commit`:case`progress`:case`invalid`:{if(t.kind===`invalid`&&isV26Line(t.value))throw new ClientError(409,JSON.stringify({code:`session_version_unsupported`,error:`This session was started by an earlier eve version. Start a new session.`}));let a=n;if(n+=1,i=0,r=RECONNECT_BACKOFF.baseDelayMs,yield{line:t.kind===`invalid`?void 0:t.line,position:a},e.onPosition?.(n),noteProgress())return}}}catch(e){if(!isStreamDisconnectError(e))throw e}finally{s.close()}if(c||e.signal?.aborted||!resolvePolicy().reconnect)return;if(!l){if(i+=1,e.follow===!1&&i>=o.streamOpenReconnectPolicy.maxAttempts)throw Error(`The session stream kept disconnecting before the read reached its tail.`);if(await sleep(r,e.signal),e.signal?.aborted)return;r=Math.min(r*2,RECONNECT_BACKOFF.maxDelayMs)}}}async function*followStreamIterable(e){let t=createEventReader();for await(let{line:n,position:r}of followStreamLines(e)){if(n===void 0)continue;let e=t.read(n,r);for(let[t,n]of e.entries())yield{cursor:t===e.length-1?r+1:r,event:n}}}async function openStreamBody(e){let t=e.retryPolicy??resolveStreamReconnectPolicy(e.streamReconnectPolicy),n=t.streamOpenReconnectPolicy,r,i,a,o=n.baseDelayMs,s={...e.searchParams};e.startIndex!==0&&(s.startIndex=String(e.startIndex)),e.requestTailIndex===!0&&(s.includeTailIndex=`1`),e.follow===!1&&(s.follow=`false`);for(let c=0;c<n.maxAttempts;c+=1){throwIfAborted(e.signal);let l=createClientUrl(e.baseUrl,e.path,Object.keys(s).length>0?s:void 0),u=await e.resolveHeaders();throwIfAborted(e.signal);let d=new AbortController,f=e.signal?AbortSignal.any([e.signal,d.signal]):d.signal,p;try{p=await fetch(l,{cache:`no-store`,headers:u,redirect:e.redirect,signal:f})}catch(t){if(e.redirect===`error`&&t instanceof Error&&t.cause instanceof Error&&t.cause.message===`unexpected redirect`)throw Error(`The session stream refused a redirect. Use the final agent URL instead.`,{cause:t});if(e.signal?.aborted||!isStreamDisconnectError(t)||c===n.maxAttempts-1)throw t;await sleep(o,e.signal),o=Math.min(o*2,n.maxDelayMs);continue}if(p.ok){if(!p.body)throw new ClientError(p.status,`Response body is null.`,p.headers);try{readMessageStreamVersion(p.headers)}catch(e){throw p.body.cancel().catch(()=>{}),d.abort(),e}let e=!1;return{headers:p.headers,body:p.body,close:()=>{e||(e=!0,p.body?.cancel().catch(()=>{}),d.abort())},tailIndex:parseTailIndexHeader(p.headers)}}r=p.status,i=await p.text(),a=p.headers;let m=createClientError(p.status,i,p.headers);if(!isRetryableStreamError(m,t.retryableErrorStatuses))throw m;c<n.maxAttempts-1&&(await sleep(o,e.signal),o=Math.min(o*2,n.maxDelayMs))}throw new ClientError(r??0,i??`Failed to open message stream.`,a)}function parseTailIndexHeader(e){let t=e.get(EVE_STREAM_TAIL_INDEX_HEADER);if(t===null||!/^-?\d+$/.test(t))return;let n=Number(t);return Number.isSafeInteger(n)?n:void 0}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{DEFAULT_STREAM_RECONNECT_POLICY,RECONNECT_BACKOFF,followStreamIterable,followStreamLines,isRetryableStreamError,openStreamBody,sleep};
@@ -67,10 +67,11 @@ export interface ClientOptions {
67
67
  */
68
68
  readonly headers?: HeadersValue;
69
69
  /**
70
- * Redirect policy for every request, including streams. Overrides a
71
- * per-request `RequestInit.redirect`. Credential-bearing clients should use
72
- * `"manual"` or `"error"` so custom auth headers can't follow a cross-origin
73
- * redirect.
70
+ * Redirect policy for every request, including streams. Defaults to
71
+ * `"error"` and overrides a per-request `RequestInit.redirect`. Use
72
+ * `"manual"` to stop at redirects. Browsers expose an opaque response;
73
+ * Node.js exposes the redirect status and headers.
74
+ * `"follow"` explicitly permits forwarding custom headers on redirects.
74
75
  */
75
76
  readonly redirect?: ClientRedirectPolicy;
76
77
  }
@@ -61,7 +61,7 @@
61
61
  "zod": "4.5.4",
62
62
  "zod-validation-error": "5.0.0"
63
63
  },
64
- "scriptHash": "cb6b617bbc0dc933c6c8c99f99382c7b96a55e11f69edc3eb77cb07e0c2a5bbd",
64
+ "scriptHash": "e131224ddb21683920afcfceb11b26db2c7ea6ff4b1295b53fb273dbb14234ae",
65
65
  "toolVersions": {
66
66
  "rolldown": "1.2.9",
67
67
  "typescript": "7.0.2"
@@ -10,6 +10,8 @@ import { ContextKey } from "#context/key.js";
10
10
  import { type StubScope } from "#tool-stubs/types.js";
11
11
  import { type SessionInboxAddress } from "#execution/session-inbox/address.js";
12
12
  import type { HandleEventFn } from "#harness/types.js";
13
+ import type { CrossChannelToFn } from "#channel/cross-channel-receive.js";
14
+ import type { InstrumentationChannel } from "#shared/instrumentation-channel.js";
13
15
  import type { DynamicSubagentAgentConfig } from "#runtime/subagents/dynamic-agent-config.js";
14
16
  import type { DynamicRemoteAgentConfig } from "#runtime/subagents/dynamic-remote-agent-config.js";
15
17
  import type { DynamicRemoteBinding } from "#reactions/remote.js";
@@ -125,6 +127,11 @@ export declare const SessionKey: ContextKey<Session>;
125
127
  export declare const SandboxKey: ContextKey<SandboxAccess>;
126
128
  export declare const SandboxTerminalCleanupKey: ContextKey<(reason: SandboxSessionEndReason) => Promise<void>>;
127
129
  export declare const HandleEventKey: ContextKey<HandleEventFn>;
130
+ /** A tool's `ctx.channel` and `ctx.to()`, which the turn running the tool provides. */
131
+ export declare const ToolChannelKey: ContextKey<{
132
+ readonly channel: InstrumentationChannel;
133
+ readonly to: CrossChannelToFn;
134
+ }>;
128
135
  /** Static model configured for the effective turn agent, or `null` for a dynamic-only agent. */
129
136
  export declare const StaticModelReferenceKey: ContextKey<Readonly<import("../shared/agent-definition.ts").InternalAgentModelDefinition & {
130
137
  reasoning?: import("../index.ts").AgentReasoningDefinition;
@@ -1 +1 @@
1
- import{SESSION_INBOX_CONTEXT_KEY}from"#execution/session-inbox/address.js";import{ContextKey}from"#context/key.js";import{STUB_CONTEXT_KEY}from"#tool-stubs/types.js";import{EARLIER_REMOTE_CALLER_CONTEXT_KEY_NAME,SESSION_CALLBACK_CONTEXT_KEY_NAME}from"#context/key-names.js";const AuthKey=new ContextKey(`eve.auth`),ToolStubsKey=new ContextKey(STUB_CONTEXT_KEY),InitiatorAuthKey=new ContextKey(`eve.initiatorAuth`),SessionIdKey=new ContextKey(`eve.sessionId`),ConversationIdKey=new ContextKey(`eve.conversationId`),SessionInboxKey=new ContextKey(SESSION_INBOX_CONTEXT_KEY),ContinuationTokenKey=new ContextKey(`eve.continuationToken`),ContinuationHookTokensKey=new ContextKey(`eve.continuationHookTokens`),ChannelRequestIdKey=new ContextKey(`eve.channelRequestId`),LocalDevRequestKey=new ContextKey(`eve.internal.localDevRequest`),OccurrenceIdKey=new ContextKey(`eve.scheduleOccurrenceId`),ScheduleIdKey=new ContextKey(`eve.scheduleId`),ScheduleInstanceKey=new ContextKey(`eve.scheduleInstance`),SessionTitleKey=new ContextKey(`eve.sessionTitle`),ChannelDeliveryKey=new ContextKey(`eve.channelDelivery`),TurnDeliveryIdsKey=new ContextKey(`eve.turnDeliveryIds`),HistoryStateKey=new ContextKey(`eve.historyState`),OfferedCatalogToolsKey=new ContextKey(`eve.offeredCatalogTools`),ChannelInstrumentationKey=new ContextKey(`eve.channelInstrumentation`),ParentSessionKey=new ContextKey(`eve.parentSession`),SessionPredecessorKey=new ContextKey(`eve.sessionPredecessor`),TraceRootKey=new ContextKey(`eve.traceRoot`),ParentTraceContextKey=new ContextKey(`eve.parentTraceContext`),SessionTraceSeedKey=new ContextKey(`eve.sessionTraceSeed`),OtelTraceEnabledKey=new ContextKey(`eve.otelTraceEnabled`),CapabilitiesKey=new ContextKey(`eve.capabilities`),SessionCallbackKey=new ContextKey(SESSION_CALLBACK_CONTEXT_KEY_NAME),EarlierRemoteCallerKey=new ContextKey(EARLIER_REMOTE_CALLER_CONTEXT_KEY_NAME),SessionKey=new ContextKey(`eve.session`),SandboxKey=new ContextKey(`eve.sandbox`),SandboxTerminalCleanupKey=new ContextKey(`eve.internal.sandboxTerminalCleanup`),HandleEventKey=new ContextKey(`eve.internal.handleEvent`),StaticModelReferenceKey=new ContextKey(`eve.staticModelReference`),DynamicSubagentAgentConfigKey=new ContextKey(`eve.dynamicSubagentAgentConfig`),AgentSessionRuntimeOverridesKey=new ContextKey(`eve.agentSessionRuntimeOverrides`),DynamicSkillSandboxKey=new ContextKey(`eve.dynamicSkillSandbox`);export{AgentSessionRuntimeOverridesKey,AuthKey,CapabilitiesKey,ChannelDeliveryKey,ChannelInstrumentationKey,ChannelRequestIdKey,ContinuationHookTokensKey,ContinuationTokenKey,ConversationIdKey,DynamicSkillSandboxKey,DynamicSubagentAgentConfigKey,EarlierRemoteCallerKey,HandleEventKey,HistoryStateKey,InitiatorAuthKey,LocalDevRequestKey,OccurrenceIdKey,OfferedCatalogToolsKey,OtelTraceEnabledKey,ParentSessionKey,ParentTraceContextKey,SandboxKey,SandboxTerminalCleanupKey,ScheduleIdKey,ScheduleInstanceKey,SessionCallbackKey,SessionIdKey,SessionInboxKey,SessionKey,SessionPredecessorKey,SessionTitleKey,SessionTraceSeedKey,StaticModelReferenceKey,ToolStubsKey,TraceRootKey,TurnDeliveryIdsKey};
1
+ import{SESSION_INBOX_CONTEXT_KEY}from"#execution/session-inbox/address.js";import{ContextKey}from"#context/key.js";import{STUB_CONTEXT_KEY}from"#tool-stubs/types.js";import{EARLIER_REMOTE_CALLER_CONTEXT_KEY_NAME,SESSION_CALLBACK_CONTEXT_KEY_NAME}from"#context/key-names.js";const AuthKey=new ContextKey(`eve.auth`),ToolStubsKey=new ContextKey(STUB_CONTEXT_KEY),InitiatorAuthKey=new ContextKey(`eve.initiatorAuth`),SessionIdKey=new ContextKey(`eve.sessionId`),ConversationIdKey=new ContextKey(`eve.conversationId`),SessionInboxKey=new ContextKey(SESSION_INBOX_CONTEXT_KEY),ContinuationTokenKey=new ContextKey(`eve.continuationToken`),ContinuationHookTokensKey=new ContextKey(`eve.continuationHookTokens`),ChannelRequestIdKey=new ContextKey(`eve.channelRequestId`),LocalDevRequestKey=new ContextKey(`eve.internal.localDevRequest`),OccurrenceIdKey=new ContextKey(`eve.scheduleOccurrenceId`),ScheduleIdKey=new ContextKey(`eve.scheduleId`),ScheduleInstanceKey=new ContextKey(`eve.scheduleInstance`),SessionTitleKey=new ContextKey(`eve.sessionTitle`),ChannelDeliveryKey=new ContextKey(`eve.channelDelivery`),TurnDeliveryIdsKey=new ContextKey(`eve.turnDeliveryIds`),HistoryStateKey=new ContextKey(`eve.historyState`),OfferedCatalogToolsKey=new ContextKey(`eve.offeredCatalogTools`),ChannelInstrumentationKey=new ContextKey(`eve.channelInstrumentation`),ParentSessionKey=new ContextKey(`eve.parentSession`),SessionPredecessorKey=new ContextKey(`eve.sessionPredecessor`),TraceRootKey=new ContextKey(`eve.traceRoot`),ParentTraceContextKey=new ContextKey(`eve.parentTraceContext`),SessionTraceSeedKey=new ContextKey(`eve.sessionTraceSeed`),OtelTraceEnabledKey=new ContextKey(`eve.otelTraceEnabled`),CapabilitiesKey=new ContextKey(`eve.capabilities`),SessionCallbackKey=new ContextKey(SESSION_CALLBACK_CONTEXT_KEY_NAME),EarlierRemoteCallerKey=new ContextKey(EARLIER_REMOTE_CALLER_CONTEXT_KEY_NAME),SessionKey=new ContextKey(`eve.session`),SandboxKey=new ContextKey(`eve.sandbox`),SandboxTerminalCleanupKey=new ContextKey(`eve.internal.sandboxTerminalCleanup`),HandleEventKey=new ContextKey(`eve.internal.handleEvent`),ToolChannelKey=new ContextKey(`eve.internal.toolChannel`),StaticModelReferenceKey=new ContextKey(`eve.staticModelReference`),DynamicSubagentAgentConfigKey=new ContextKey(`eve.dynamicSubagentAgentConfig`),AgentSessionRuntimeOverridesKey=new ContextKey(`eve.agentSessionRuntimeOverrides`),DynamicSkillSandboxKey=new ContextKey(`eve.dynamicSkillSandbox`);export{AgentSessionRuntimeOverridesKey,AuthKey,CapabilitiesKey,ChannelDeliveryKey,ChannelInstrumentationKey,ChannelRequestIdKey,ContinuationHookTokensKey,ContinuationTokenKey,ConversationIdKey,DynamicSkillSandboxKey,DynamicSubagentAgentConfigKey,EarlierRemoteCallerKey,HandleEventKey,HistoryStateKey,InitiatorAuthKey,LocalDevRequestKey,OccurrenceIdKey,OfferedCatalogToolsKey,OtelTraceEnabledKey,ParentSessionKey,ParentTraceContextKey,SandboxKey,SandboxTerminalCleanupKey,ScheduleIdKey,ScheduleInstanceKey,SessionCallbackKey,SessionIdKey,SessionInboxKey,SessionKey,SessionPredecessorKey,SessionTitleKey,SessionTraceSeedKey,StaticModelReferenceKey,ToolChannelKey,ToolStubsKey,TraceRootKey,TurnDeliveryIdsKey};
@@ -1,5 +1,5 @@
1
1
  import type { ChannelInstrumentationProjection, SessionCapabilities, SessionParent, SessionTraceRoot } from "#channel/types.js";
2
- import type { LocalDevRequestProvenance } from "#context/keys.js";
2
+ import { type LocalDevRequestProvenance } from "#context/keys.js";
3
3
  import { type StubScope } from "#tool-stubs/types.js";
4
4
  import { type SessionSchedule } from "#context/session-schedule.js";
5
5
  import type { DynamicSubagentSelections } from "#execution/agent-sessions/target.js";
@@ -28,9 +28,13 @@ export interface AgentSessionContext {
28
28
  readonly capabilities?: SessionCapabilities;
29
29
  readonly schedule?: SessionSchedule;
30
30
  readonly channelMetadata?: ChannelInstrumentationProjection;
31
+ /** The calling session's address on its channel, which `ctx.channel.continuationToken` reads. */
32
+ readonly continuationToken?: string;
31
33
  readonly conversation?: ConversationContext;
32
34
  /** Dynamic agents the calling turn selected, by node id. */
33
35
  readonly dynamicSelections: DynamicSubagentSelections;
36
+ /** Whether a parent, local or remote, delegated the calling session. */
37
+ readonly delegated?: boolean;
34
38
  readonly localDevRequest?: LocalDevRequestProvenance;
35
39
  /** The calling session, turn, and tool call, recorded as each session's lineage. */
36
40
  readonly parent: SessionParent;
@@ -1 +1 @@
1
- import{readSerializedSessionSchedule}from"#context/session-schedule.js";import{STUB_CONTEXT_KEY}from"#tool-stubs/types.js";import{serializeDurableCompiledArtifactsSource}from"#runtime/durable-compiled-artifacts-source.js";import{resolveToolCallAgentTrace}from"#tracing/eve/agent-invocation-coordinator.js";function captureAgentSessionContext(e,t){let{batch:n,session:r}=e;return{agents:e.workflowAgents,toolStubs:e.serializedContext[STUB_CONTEXT_KEY],bundle:{nodeId:e.bundle.nodeId,source:serializeDurableCompiledArtifactsSource(e.bundle.compiledArtifactsSource)},capabilities:e.capabilities,schedule:readSerializedSessionSchedule(e.serializedContext),channelMetadata:e.channelMetadata,conversation:e.inheritedConversation,dynamicSelections:e.dynamicSubagentSelections,localDevRequest:e.localDevRequest,parent:{callId:t,rootSessionId:r.rootSessionId??r.sessionId,sessionId:r.sessionId,turn:{id:n.event.turnId,sequence:n.event.sequence}},sandbox:{sessionId:e.sandboxSessionId,state:e.sandboxState},traceRoot:e.traceRoot,trace:resolveToolCallAgentTrace({callId:t,conversation:e.inheritedConversation,serializedContext:e.serializedContext,sessionId:r.sessionId,turnId:n.event.turnId})}}export{captureAgentSessionContext};
1
+ import{ContinuationTokenKey}from"#context/keys.js";import{readSerializedSessionSchedule}from"#context/session-schedule.js";import{STUB_CONTEXT_KEY}from"#tool-stubs/types.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{serializeDurableCompiledArtifactsSource}from"#runtime/durable-compiled-artifacts-source.js";import{resolveToolCallAgentTrace}from"#tracing/eve/agent-invocation-coordinator.js";function captureAgentSessionContext(e,t){let{batch:n,session:r}=e;return{agents:e.workflowAgents,toolStubs:e.serializedContext[STUB_CONTEXT_KEY],bundle:{nodeId:e.bundle.nodeId,source:serializeDurableCompiledArtifactsSource(e.bundle.compiledArtifactsSource)},capabilities:e.capabilities,schedule:readSerializedSessionSchedule(e.serializedContext),channelMetadata:e.channelMetadata,continuationToken:e.serializedContext[ContinuationTokenKey.name],conversation:e.inheritedConversation,dynamicSelections:e.dynamicSubagentSelections,delegated:hasDelegatedSessionContext(e.serializedContext),localDevRequest:e.localDevRequest,parent:{callId:t,rootSessionId:r.rootSessionId??r.sessionId,sessionId:r.sessionId,turn:{id:n.event.turnId,sequence:n.event.sequence}},sandbox:{sessionId:e.sandboxSessionId,state:e.sandboxState},traceRoot:e.traceRoot,trace:resolveToolCallAgentTrace({callId:t,conversation:e.inheritedConversation,serializedContext:e.serializedContext,sessionId:r.sessionId,turnId:n.event.turnId})}}export{captureAgentSessionContext};
@@ -1 +1 @@
1
- import{runJsProgram}from"#execution/dynamic-workflow/workflow.js";async function runWorkflowProgramTask(e,t){"use workflow";return runJsProgram(e.js,t,{maxSubagents:e.maxSubagents??0})}runWorkflowProgramTask.workflowId=`workflow//eve@0.84.1//runWorkflowProgramTask`;export{runWorkflowProgramTask};
1
+ import{runJsProgram}from"#execution/dynamic-workflow/workflow.js";async function runWorkflowProgramTask(e,t){"use workflow";return runJsProgram(e.js,t,{maxSubagents:e.maxSubagents??0})}runWorkflowProgramTask.workflowId=`workflow//eve@0.85.0//runWorkflowProgramTask`;export{runWorkflowProgramTask};
@@ -1,6 +1,6 @@
1
1
  import type { ModelMessage } from "ai";
2
2
  import { type SessionProjection } from "#protocol/session-projection.js";
3
- import { type DurableSession, type DurableSessionState } from "#execution/durable-session-store.js";
3
+ import type { DurableSession, DurableSessionState } from "#execution/durable-session-store.js";
4
4
  import type { HarnessModelMessage } from "#harness/messages.js";
5
5
  export type LegacySession = DurableSession & {
6
6
  readonly history: ModelMessage[];
@@ -19,4 +19,3 @@ export declare function importConversation(session: LegacySession): {
19
19
  * counted the session spent as the view's usage, so the session's limits keep counting.
20
20
  */
21
21
  export declare function importProjection(session: LegacySession): SessionProjection;
22
- export declare function normalizeHistory(messages: readonly ModelMessage[]): HarnessModelMessage[];
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";import{SESSION_PROJECTION_STATE_KEY}from"#harness/session-machine/view.js";import{DURABLE_SESSION_VERSION}from"#execution/durable-session-store.js";import{isUserMessageKind,validateHarnessModelMessages}from"#harness/messages.js";import{usageOf}from"#harness/facts.js";import{withModelUsage}from"#harness/session-usage.js";import{initialSessionProjection}from"#protocol/session-projection.js";const PRESERVED_FRAMEWORK_STATE=new Set([`eve.harness.sessionRuntimeTokenLimit`]),LEGACY_USAGE_KEY=`eve.harness.turnUsage`,REPORTED_USAGE_KEY=`eve.harness.reportedSessionUsage`;function readLegacySnapshot(e){let t=e.snapshot;if(!isObject(t)||t.version!==1||!isObject(t.session)||t.session.sessionId!==e.sessionId||!Array.isArray(t.session.history))throw Error(`Unsupported legacy session snapshot.`);return t.session}function importConversation(e){let{history:t,...n}=e,r=Object.fromEntries(Object.entries(e.state??{}).filter(([e])=>!e.startsWith(`eve.`)||PRESERVED_FRAMEWORK_STATE.has(e))),i=legacyUsage(e.state?.[REPORTED_USAGE_KEY]);return i!==void 0&&(r[REPORTED_USAGE_KEY]=i),{history:normalizeHistory(t),sessionState:{version:DURABLE_SESSION_VERSION,sessionId:e.sessionId,continuationToken:e.continuationToken,hasProxyInputRequests:!1,snapshot:{session:{...n,state:{...r,[SESSION_PROJECTION_STATE_KEY]:importProjection(e)}}}}}}function importProjection(e){let t=e.state?.[`eve.harness.emission`],n=initialSessionProjection(),r=legacyUsage(isObject(e.state?.[LEGACY_USAGE_KEY])?e.state[LEGACY_USAGE_KEY].session:void 0),i=r===void 0?n:{...n,view:withModelUsage(n.view,r)};if(!isObject(t)||typeof t.sequence!=`number`)return i;let{view:a}=i,o=t.sessionStarted===!0?`open`:`new`,s=typeof t.turnId==`string`?t.turnId:``;if(s===``)return{...i,view:{...a,session:{status:o,turnCount:t.sequence}}};let c=typeof t.stepIndex==`number`?t.stepIndex:0,l={cause:{hook:`legacy`},follows:null,introducedAt:0,startedAt:new Date(0).toISOString(),status:`running`,turnId:s,...c>0&&{runs:c}};return{...i,view:{...a,session:{latestTurnId:s,status:o,turnCount:t.sequence+1},turns:{[s]:l}}}}function legacyUsage(e){if(!isObject(e))return;let count=t=>typeof e[t]==`number`?e[t]:0;return usageOf({cacheReadTokens:count(`cacheReadTokens`),cacheWriteTokens:count(`cacheWriteTokens`),costUsd:e.sawCost===!0&&typeof e.costUsd==`number`?e.costUsd:void 0,inputTokens:count(`inputTokens`),outputTokens:count(`outputTokens`)})}function normalizeHistory(e){let t=[],n=new Map,settle=()=>{n.size!==0&&(t.push({role:`tool`,content:[...n].map(([e,t])=>({type:`tool-result`,toolCallId:e,toolName:t,output:{type:`error-text`,value:`Interrupted by the session upgrade. Start this work again if it is still needed.`}}))}),n.clear())};for(let r of e){let e=r;if(e.role===`assistant`&&Array.isArray(e.content))e={...e,content:e.content.filter(e=>e.type!==`tool-approval-request`)};else if(e.role===`tool`&&(e={...e,content:e.content.filter(e=>e.type!==`tool-approval-response`)},e.content.length===0))continue;if(e.role!==`tool`&&settle(),e.role===`assistant`&&Array.isArray(e.content))for(let t of e.content)t.type===`tool-call`&&n.set(t.toolCallId,t.toolName);if(e.role===`tool`)for(let t of e.content)t.type===`tool-result`&&n.delete(t.toolCallId);let i=e.kind;t.push(e.role===`user`&&!isUserMessageKind(i)?{...e,kind:`user`}:e)}return settle(),validateHarnessModelMessages(t)}export{importConversation,importProjection,normalizeHistory,readLegacySnapshot};
1
+ import{isObject}from"#shared/guards.js";import{SESSION_PROJECTION_STATE_KEY}from"#harness/session-machine/view.js";import{DURABLE_SESSION_VERSION}from"#execution/durable-session-read.js";import{withModelUsage}from"#harness/session-usage.js";import{initialSessionProjection}from"#protocol/session-projection.js";import{normalizeHistory}from"#execution/session/imported-conversation.js";import{usageOf}from"#harness/facts.js";const PRESERVED_FRAMEWORK_STATE=new Set([`eve.harness.sessionRuntimeTokenLimit`]),LEGACY_USAGE_KEY=`eve.harness.turnUsage`,REPORTED_USAGE_KEY=`eve.harness.reportedSessionUsage`;function readLegacySnapshot(e){let t=e.snapshot;if(!isObject(t)||t.version!==1||!isObject(t.session)||t.session.sessionId!==e.sessionId||!Array.isArray(t.session.history))throw Error(`Unsupported legacy session snapshot.`);return t.session}function importConversation(e){let{history:t,...n}=e,r=Object.fromEntries(Object.entries(e.state??{}).filter(([e])=>!e.startsWith(`eve.`)||PRESERVED_FRAMEWORK_STATE.has(e))),i=legacyUsage(e.state?.[REPORTED_USAGE_KEY]);return i!==void 0&&(r[REPORTED_USAGE_KEY]=i),{history:normalizeHistory(t),sessionState:{version:DURABLE_SESSION_VERSION,sessionId:e.sessionId,continuationToken:e.continuationToken,hasProxyInputRequests:!1,snapshot:{session:{...n,state:{...r,[SESSION_PROJECTION_STATE_KEY]:importProjection(e)}}}}}}function importProjection(e){let t=e.state?.[`eve.harness.emission`],n=initialSessionProjection(),r=legacyUsage(isObject(e.state?.[LEGACY_USAGE_KEY])?e.state[LEGACY_USAGE_KEY].session:void 0),i=r===void 0?n:{...n,view:withModelUsage(n.view,r)};if(!isObject(t)||typeof t.sequence!=`number`)return i;let{view:a}=i,o=t.sessionStarted===!0?`open`:`new`,s=typeof t.turnId==`string`?t.turnId:``;if(s===``)return{...i,view:{...a,session:{status:o,turnCount:t.sequence}}};let c=typeof t.stepIndex==`number`?t.stepIndex:0,l={cause:{hook:`legacy`},follows:null,introducedAt:0,startedAt:new Date(0).toISOString(),status:`running`,turnId:s,...c>0&&{runs:c}};return{...i,view:{...a,session:{latestTurnId:s,status:o,turnCount:t.sequence+1},turns:{[s]:l}}}}function legacyUsage(e){if(!isObject(e))return;let count=t=>typeof e[t]==`number`?e[t]:0;return usageOf({cacheReadTokens:count(`cacheReadTokens`),cacheWriteTokens:count(`cacheWriteTokens`),costUsd:e.sawCost===!0&&typeof e.costUsd==`number`?e.costUsd:void 0,inputTokens:count(`inputTokens`),outputTokens:count(`outputTokens`)})}export{importConversation,importProjection,readLegacySnapshot};
@@ -1 +1 @@
1
- import{activeTurn,interactionOwner,waiting}from"#protocol/session-projection/selectors.js";import{AuthKey,TurnDeliveryIdsKey}from"#context/keys.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{storedProjection}from"#harness/session-machine/view.js";import{V26_INPUT_REMOTE_AGENT_PROTOCOL}from"#protocol/remote-agent-protocol.js";import{resolveRemoteAgentStreamHeaders,respondToRemoteAgentSession}from"#execution/agent-sessions/remote.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{readDurableSession}from"#execution/durable-session-store.js";import{readHitlState}from"#harness/hitl/index.js";import{selectDeliveryPayloads}from"#harness/messages.js";import{resumeSessionInbox}from"#execution/session-inbox/resume.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{commitSessionStep,publishSessionEvents}from"#execution/publish-session-events.js";import"#execution/session/state-delta.js";import{withSessionStateDelta}from"#execution/session/step-state-delta.js";import{routeAnswer}from"#harness/session-machine/transitions.js";import{coalesceDeliverPayloads}from"#execution/deliver-payloads.js";import{fact}from"#harness/facts.js";import{userPartsOf}from"#harness/user-parts.js";import{principalOf}from"#execution/session/delivery-facts.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{setChannelContext}from"#execution/channel-context.js";import{routeDeliverPayload}from"#subagents/hitl-proxy.js";import{protocolTwoAnswersSettledOnForward}from"#subagents/protocol-two-callback.js";import{sendWorkflowAskAnswers}from"#execution/tools/workflow/answer.js";async function routeProxiedDeliverStep(e){"use step";return await withSessionStateDelta(e,routeProxiedDeliver)}async function routeProxiedDeliver(e){let t=readHitlState(readDurableSession(e.sessionState).state).relays,{delivery:n,serializedContext:r}=await deliverChannelAnswers({...e,routable:e=>t.has(e.interactionId)}),i=readDurableSession(e.sessionState),a=new Map,o=new Map,s,c=!hasDelegatedSessionContext(r)&&n.caller===void 0,l=new Set,u=[],d=storedProjection(i.state).view,f=activeTurn(d),p=f===void 0?void 0:waiting(d,f.turnId),askedTurn=e=>{let t=interactionOwner(d,e).turnId;return t!==void 0&&d.turns[t]?.status===`running`?t:p?.on===`interaction`&&p.interactions.some(t=>t.interactionId===e.interactionId)?f?.turnId:void 0},m=[],h=[];for(let[e,t]of n.payloads.entries()){let r=routeDeliverPayload({allowRoute:e=>!l.has(e),payload:t,resolveMessage:c,state:i.state});s??=r.parentAction,r.forSelf!==void 0&&a.set(e,r.forSelf);let f=(n.deliveryMetadata??[]).filter(t=>t.payloadIndex===e),p=f[0]?.deliveryId;if(r.forChildren.length>0&&p!==void 0){let e=r.forChildren.find(e=>e.message!==void 0),i=r.forChildren.flatMap(e=>e.payload.answers).map(e=>d.interactions[e.interactionId]).find(e=>e!==void 0&&askedTurn(e)!==void 0),a=i===void 0?void 0:askedTurn(i);r.forSelf===void 0&&a!==void 0&&u.push(...f.map(e=>e.deliveryId));for(let t of f)m.push({consumed:r.forSelf===void 0&&a!==void 0?{parts:e?.message===void 0?[]:userPartsOf(e.message),turnId:a}:void 0,continues:r.forSelf!==void 0||void 0,deliveryId:t.deliveryId,principal:principalOf(n.auth),source:t.channelKind===void 0?void 0:{channel:t.channelKind}});for(let e of r.forChildren)for(let n of e.payload.answers){let e=(t.answers??[]).indexOf(n),r={};n.optionId!==void 0&&(r.optionId=n.optionId),n.text!==void 0&&(r.text=n.text),h.push({deliveryId:p,interactionId:n.interactionId,responseId:`response_${p}_forwarded_${e===-1?`typed_0`:String(e)}`,value:r})}}for(let[t,i]of r.forChildren.entries()){if(i.workflowAsk!==void 0||i.message!==void 0)for(let{interactionId:e}of i.payload.answers)l.add(e);let a=JSON.stringify([i.childContinuationToken,i.childSessionInbox?.sessionId??``,i.remote?.sessionId??``,i.inputSource??null,i.workflowAsk?.control??null]),s=o.get(a)??{workflowAsk:i.workflowAsk,remote:i.remote,childContinuationToken:i.childContinuationToken,childSessionInbox:i.childSessionInbox,metadata:[],payloads:[]},c=s.payloads.length;if(s.payloads.push(i.payload),r.forSelf===void 0&&t===0)for(let t of n.deliveryMetadata??[])t.payloadIndex===e&&s.metadata.push({...t,payloadIndex:c});o.set(a,s)}}let g={serializedContext:joinTurnDeliveryIds(r,u),sessionState:e.sessionState},_=!1,v=m.filter(e=>e.consumed!==void 0),y=v.length===0?g:await commitSessionStep({...g,sessionWritable:e.sessionWritable},e=>[routeAnswer(e,{deliveries:v,forwarded:[],decided:[]})],{origin:`own`,cancelTurn:()=>{_=!0}});if(_){let t=storedProjection(readDurableSession(y.sessionState).state).view,r=(n.deliveryMetadata??[]).filter(({deliveryId:e,payloadIndex:n})=>a.has(n)&&t.deliveries[e]?.status!==`settled`);if(r.length===0)return{...y,kind:`cancel-turn`};let i=await publishSessionEvents({...y,sessionWritable:e.sessionWritable},r.flatMap(({channelKind:e,deliveryId:r})=>[...t.deliveries[r]===void 0?[fact(`delivery.admitted`,{deliveryId:r,principal:principalOf(n.auth),source:e===void 0?void 0:{channel:e}})]:[],fact(`delivery.settled`,{deliveryId:r,outcome:`ignored`})]));return{kind:`cancel-turn`,serializedContext:i.serializedContext,sessionState:i.sessionState}}let b=[];for(let[e,t]of o)if(t.workflowAsk!==void 0){let e=coalesceDeliverPayloads(t.payloads).answers??[];b.push(...e.map(e=>({answer:e,outcome:`accepted`}))),await sendWorkflowAskAnswers(t.workflowAsk,e,principalOf(n.auth))}else{let i={...n,deliveryMetadata:t.metadata.length===0?void 0:t.metadata,payloads:t.payloads},a=t.remote;if(a!==void 0){let i=await deserializeContext(r),o=await resolveRemoteAgentStreamHeaders({bundle:i.require(BundleKey),name:a.name,dynamicBinding:a.dynamicBinding,resolverId:a.resolverId,url:a.url}),c=coalesceDeliverPayloads(t.payloads).answers??[];if(await respondToRemoteAgentSession({remote:a,headers:o,auth:n.auth,idempotencyKey:await answersIdempotencyKey(n,e),responses:c}),a.earlierProtocol===V26_INPUT_REMOTE_AGENT_PROTOCOL)for(let e of protocolTwoAnswersSettledOnForward({answers:c,decidedHere:s?.answer.interactionId,kindOf:e=>d.interactions[e]?.request.kind}))b.push({answer:e,outcome:`accepted`})}else await resumeSessionInbox(t.childSessionInbox??t.childContinuationToken,i)}let x=await commitSessionStep({...y,sessionWritable:e.sessionWritable},e=>[routeAnswer(e,{decided:s===void 0?b:[...b,{answer:s.answer,outcome:`declined`}],deliveries:m,forwarded:h})],{origin:`relayed`});if(s!==void 0)return{...x,kind:s.kind};let S=[...a].sort(([e],[t])=>e-t),C=S.length===0?void 0:selectDeliveryPayloads(n,S.map(([e,t])=>({index:e,payload:t})));return{...x,kind:`continue`,remainder:C}}async function answersIdempotencyKey(e,t){let n=(e.deliveryMetadata??[]).map(e=>e.deliveryId);if(n.length===0)return;let r=JSON.stringify([n,t]),i=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(r));return`eve-answers:${Array.from(new Uint8Array(i),e=>e.toString(16).padStart(2,`0`)).join(``)}`}function joinTurnDeliveryIds(e,t){if(t.length===0)return e;let n=e[TurnDeliveryIdsKey.name]??[];return{...e,[TurnDeliveryIdsKey.name]:[...new Set([...n,...t])]}}async function mapHeldAnswersStep(e){"use step";return await withSessionStateDelta(e,async()=>{let t=new Set(e.requestIds),n=await deliverChannelAnswers({...e,routable:e=>t.has(e.interactionId)});return n.delivery===e.delivery?{delivery:void 0}:{delivery:n.delivery,serializedContext:n.serializedContext}})}async function deliverChannelAnswers(e){let{routable:t}=e;if(!e.delivery.payloads.some(e=>e.answers?.some(e=>!t(e))===!0))return e;let n=await deserializeContext(e.serializedContext),r=n.require(ChannelKey);if(r.deliver===void 0)return e;e.delivery.auth!==void 0&&n.set(AuthKey,e.delivery.auth??null);let i=r.state??{},a=!1,o=[];for(let s of e.delivery.payloads){if(s.answers===void 0){o.push(s);continue}let e=[];for(let o of s.answers){if(t(o)){e.push(o);continue}let c=buildAdapterContext({...r,state:structuredClone(i)},n),l=(await r.deliver({...s,answers:[o],message:void 0},c))?.answers?.filter(t)??[];if(l.length===0){e.push(o);continue}a=!0,i=c.state,e.push(...l)}o.push({...s,answers:e})}if(!a)return e;let s=await deserializeContext(e.serializedContext);return setChannelContext(s,{...r,state:i}),{delivery:{...e.delivery,payloads:o},serializedContext:serializeContext(s)}}export{answersIdempotencyKey,mapHeldAnswersStep,routeProxiedDeliverStep};
1
+ import{activeTurn,interactionOwner,waiting}from"#protocol/session-projection/selectors.js";import{AuthKey,TurnDeliveryIdsKey}from"#context/keys.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{storedProjection}from"#harness/session-machine/view.js";import{V26_INPUT_REMOTE_AGENT_PROTOCOL}from"#protocol/remote-agent-protocol.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{resolveRemoteAgentStreamHeaders,respondToRemoteAgentSession}from"#execution/agent-sessions/remote.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{readDurableSession}from"#execution/durable-session-store.js";import{readHitlState}from"#harness/hitl/index.js";import{selectDeliveryPayloads}from"#harness/messages.js";import{resumeSessionInbox}from"#execution/session-inbox/resume.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{commitSessionStep,publishSessionEvents}from"#execution/publish-session-events.js";import"#execution/session/state-delta.js";import{withSessionStateDelta}from"#execution/session/step-state-delta.js";import{routeAnswer}from"#harness/session-machine/transitions.js";import{coalesceDeliverPayloads}from"#execution/deliver-payloads.js";import{fact}from"#harness/facts.js";import{userPartsOf}from"#harness/user-parts.js";import{principalOf}from"#execution/session/delivery-facts.js";import{setChannelContext}from"#execution/channel-context.js";import{routeDeliverPayload}from"#subagents/hitl-proxy.js";import{protocolTwoAnswersSettledOnForward}from"#subagents/protocol-two-callback.js";import{sendWorkflowAskAnswers}from"#execution/tools/workflow/answer.js";async function routeProxiedDeliverStep(e){"use step";return await withSessionStateDelta(e,routeProxiedDeliver)}async function routeProxiedDeliver(e){let t=readHitlState(readDurableSession(e.sessionState).state).relays,{delivery:n,serializedContext:r}=await deliverChannelAnswers({...e,routable:e=>t.has(e.interactionId)}),i=readDurableSession(e.sessionState),a=new Map,o=new Map,s,c=!hasDelegatedSessionContext(r)&&n.caller===void 0,l=new Set,u=[],d=storedProjection(i.state).view,f=activeTurn(d),p=f===void 0?void 0:waiting(d,f.turnId),askedTurn=e=>{let t=interactionOwner(d,e).turnId;return t!==void 0&&d.turns[t]?.status===`running`?t:p?.on===`interaction`&&p.interactions.some(t=>t.interactionId===e.interactionId)?f?.turnId:void 0},m=[],h=[];for(let[e,t]of n.payloads.entries()){let r=routeDeliverPayload({allowRoute:e=>!l.has(e),payload:t,resolveMessage:c,state:i.state});s??=r.parentAction,r.forSelf!==void 0&&a.set(e,r.forSelf);let f=(n.deliveryMetadata??[]).filter(t=>t.payloadIndex===e),p=f[0]?.deliveryId;if(r.forChildren.length>0&&p!==void 0){let e=r.forChildren.find(e=>e.message!==void 0),i=r.forChildren.flatMap(e=>e.payload.answers).map(e=>d.interactions[e.interactionId]).find(e=>e!==void 0&&askedTurn(e)!==void 0),a=i===void 0?void 0:askedTurn(i);r.forSelf===void 0&&a!==void 0&&u.push(...f.map(e=>e.deliveryId));for(let t of f)m.push({consumed:r.forSelf===void 0&&a!==void 0?{parts:e?.message===void 0?[]:userPartsOf(e.message),turnId:a}:void 0,continues:r.forSelf!==void 0||void 0,deliveryId:t.deliveryId,principal:principalOf(n.auth),source:t.channelKind===void 0?void 0:{channel:t.channelKind}});for(let e of r.forChildren)for(let n of e.payload.answers){let e=(t.answers??[]).indexOf(n),r={};n.optionId!==void 0&&(r.optionId=n.optionId),n.text!==void 0&&(r.text=n.text),h.push({deliveryId:p,interactionId:n.interactionId,responseId:`response_${p}_forwarded_${e===-1?`typed_0`:String(e)}`,value:r})}}for(let[t,i]of r.forChildren.entries()){if(i.workflowAsk!==void 0||i.message!==void 0)for(let{interactionId:e}of i.payload.answers)l.add(e);let a=JSON.stringify([i.childContinuationToken,i.childSessionInbox?.sessionId??``,i.remote?.sessionId??``,i.inputSource??null,i.workflowAsk?.control??null]),s=o.get(a)??{workflowAsk:i.workflowAsk,remote:i.remote,childContinuationToken:i.childContinuationToken,childSessionInbox:i.childSessionInbox,metadata:[],payloads:[]},c=s.payloads.length;if(s.payloads.push(i.payload),r.forSelf===void 0&&t===0)for(let t of n.deliveryMetadata??[])t.payloadIndex===e&&s.metadata.push({...t,payloadIndex:c});o.set(a,s)}}let g={serializedContext:joinTurnDeliveryIds(r,u),sessionState:e.sessionState},_=!1,v=m.filter(e=>e.consumed!==void 0),y=v.length===0?g:await commitSessionStep({...g,sessionWritable:e.sessionWritable},e=>[routeAnswer(e,{deliveries:v,forwarded:[],decided:[]})],{origin:`own`,cancelTurn:()=>{_=!0}});if(_){let t=storedProjection(readDurableSession(y.sessionState).state).view,r=(n.deliveryMetadata??[]).filter(({deliveryId:e,payloadIndex:n})=>a.has(n)&&t.deliveries[e]?.status!==`settled`);if(r.length===0)return{...y,kind:`cancel-turn`};let i=await publishSessionEvents({...y,sessionWritable:e.sessionWritable},r.flatMap(({channelKind:e,deliveryId:r})=>[...t.deliveries[r]===void 0?[fact(`delivery.admitted`,{deliveryId:r,principal:principalOf(n.auth),source:e===void 0?void 0:{channel:e}})]:[],fact(`delivery.settled`,{deliveryId:r,outcome:`ignored`})]));return{kind:`cancel-turn`,serializedContext:i.serializedContext,sessionState:i.sessionState}}let b=[];for(let[e,t]of o)if(t.workflowAsk!==void 0){let e=coalesceDeliverPayloads(t.payloads).answers??[];b.push(...e.map(e=>({answer:e,outcome:`accepted`}))),await sendWorkflowAskAnswers(t.workflowAsk,e,principalOf(n.auth))}else{let i={...n,deliveryMetadata:t.metadata.length===0?void 0:t.metadata,payloads:t.payloads},a=t.remote;if(a!==void 0){let i=await deserializeContext(r),o=await resolveRemoteAgentStreamHeaders({bundle:i.require(BundleKey),name:a.name,dynamicBinding:a.dynamicBinding,resolverId:a.resolverId,url:a.url}),c=coalesceDeliverPayloads(t.payloads).answers??[];if(await respondToRemoteAgentSession({remote:a,headers:o,auth:n.auth,idempotencyKey:await answersIdempotencyKey(n,e),responses:c}),a.earlierProtocol===V26_INPUT_REMOTE_AGENT_PROTOCOL)for(let e of protocolTwoAnswersSettledOnForward({answers:c,decidedHere:s?.answer.interactionId,kindOf:e=>d.interactions[e]?.request.kind}))b.push({answer:e,outcome:`accepted`})}else await resumeSessionInbox(t.childSessionInbox??t.childContinuationToken,i)}let x=await commitSessionStep({...y,sessionWritable:e.sessionWritable},e=>[routeAnswer(e,{decided:s===void 0?b:[...b,{answer:s.answer,outcome:`declined`}],deliveries:m,forwarded:h})],{origin:`relayed`});if(s!==void 0)return{...x,kind:s.kind};let S=[...a].sort(([e],[t])=>e-t),C=S.length===0?void 0:selectDeliveryPayloads(n,S.map(([e,t])=>({index:e,payload:t})));return{...x,kind:`continue`,remainder:C}}async function answersIdempotencyKey(e,t){let n=(e.deliveryMetadata??[]).map(e=>e.deliveryId);if(n.length===0)return;let r=JSON.stringify([n,t]),i=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(r));return`eve-answers:${Array.from(new Uint8Array(i),e=>e.toString(16).padStart(2,`0`)).join(``)}`}function joinTurnDeliveryIds(e,t){if(t.length===0)return e;let n=e[TurnDeliveryIdsKey.name]??[];return{...e,[TurnDeliveryIdsKey.name]:[...new Set([...n,...t])]}}async function mapHeldAnswersStep(e){"use step";return await withSessionStateDelta(e,async()=>{let t=new Set(e.requestIds),n=await deliverChannelAnswers({...e,routable:e=>t.has(e.interactionId)});return n.delivery===e.delivery?{delivery:void 0}:{delivery:n.delivery,serializedContext:n.serializedContext}})}async function deliverChannelAnswers(e){let{routable:t}=e;if(!e.delivery.payloads.some(e=>e.answers?.some(e=>!t(e))===!0))return e;let n=await deserializeContext(e.serializedContext),r=n.require(ChannelKey);if(r.deliver===void 0)return e;e.delivery.auth!==void 0&&n.set(AuthKey,e.delivery.auth??null);let i=r.state??{},a=!1,o=[];for(let s of e.delivery.payloads){if(s.answers===void 0){o.push(s);continue}let e=[];for(let o of s.answers){if(t(o)){e.push(o);continue}let c=buildAdapterContext({...r,state:structuredClone(i)},n),l=(await r.deliver({...s,answers:[o],message:void 0},c))?.answers?.filter(t)??[];if(l.length===0){e.push(o);continue}a=!0,i=c.state,e.push(...l)}o.push({...s,answers:e})}if(!a)return e;let s=await deserializeContext(e.serializedContext);return setChannelContext(s,{...r,state:i}),{delivery:{...e.delivery,payloads:o},serializedContext:serializeContext(s)}}export{answersIdempotencyKey,mapHeldAnswersStep,routeProxiedDeliverStep};
@@ -31,4 +31,7 @@ export declare function fetchWithDispatcher(url: string | URL, init: DispatcherR
31
31
  */
32
32
  export declare function readBoundedResponse(response: Response, maxResponseSize: number): Promise<Response>;
33
33
  export declare function cancelResponseBody(response: Response): Promise<void>;
34
+ export declare class ResponseTooLargeError extends Error {
35
+ constructor(maxResponseSize: number);
36
+ }
34
37
  export {};
@@ -1 +1 @@
1
- import{isBlockedDestinationHost}from"#shared/network-address.js";import{lookup}from"node:dns";var UnsafeDestinationError=class extends Error{constructor(e=`URL must not target localhost, private, link-local, or reserved IP addresses.`){super(e),this.name=`UnsafeDestinationError`}};function assertPublicHostname(e,t){if(isBlockedDestinationHost(e,t))throw new UnsafeDestinationError}async function createPublicDispatcher(e){let{Agent:t,Dispatcher1Wrapper:n}=await import(`undici`);return new n(new t({connect:{lookup:createPublicLookup(e)}}))}function findUnsafeDestinationError(e){return e instanceof UnsafeDestinationError?e:e instanceof Error&&e.cause instanceof UnsafeDestinationError?e.cause:void 0}function fetchWithDispatcher(e,t){return fetch(e,t)}function createPublicLookup(e){return(t,n,r)=>{lookup(t,{all:!0,verbatim:!0},(i,a)=>{if(i!==null){r(i,``,0);return}if(a.some(({address:t})=>isBlockedDestinationHost(t,e))){r(new UnsafeDestinationError,``,0);return}let o=n.family===void 0||n.family===0?a:a.filter(({family:e})=>e===n.family);if(o.length===0){let e=Error(`Unable to resolve URL hostname "${t}" in the requested IP family.`);Object.assign(e,{code:`ENOTFOUND`}),r(e,``,0);return}if(n.all===!0){r(null,o);return}let s=o[0];r(null,s.address,s.family)})}}async function readBoundedResponse(e,t){let n=parseContentLength(e.headers.get(`content-length`));if(n!==void 0&&n>t)throw await cancelResponseBody(e),createResponseTooLargeError(t);let r=await readBoundedBody(e,t),i=r.byteLength===0?null:Uint8Array.from(r).buffer;return new Response(i,{headers:e.headers,status:e.status,statusText:e.statusText})}function parseContentLength(e){if(e===null)return;let t=Number.parseInt(e,10);return Number.isFinite(t)&&t>=0?t:void 0}async function readBoundedBody(e,t){if(e.body===null)return new Uint8Array;let n=e.body.getReader(),r=[],i=0;try{for(;;){let{done:e,value:a}=await n.read();if(e)break;if(i+=a.byteLength,i>t)throw await n.cancel(),createResponseTooLargeError(t);r.push(a)}}finally{n.releaseLock()}let a=new Uint8Array(i),o=0;for(let e of r)a.set(e,o),o+=e.byteLength;return a}async function cancelResponseBody(e){try{await e.body?.cancel()}catch{}}function createResponseTooLargeError(e){return Error(`Response too large (exceeds ${e} bytes).`)}export{UnsafeDestinationError,assertPublicHostname,cancelResponseBody,createPublicDispatcher,fetchWithDispatcher,findUnsafeDestinationError,readBoundedResponse};
1
+ import{isBlockedDestinationHost}from"#shared/network-address.js";import{lookup}from"node:dns";var UnsafeDestinationError=class extends Error{constructor(e=`URL must not target localhost, private, link-local, or reserved IP addresses.`){super(e),this.name=`UnsafeDestinationError`}};function assertPublicHostname(e,t){if(isBlockedDestinationHost(e,t))throw new UnsafeDestinationError}async function createPublicDispatcher(e){let{Agent:t,Dispatcher1Wrapper:n}=await import(`undici`);return new n(new t({connect:{lookup:createPublicLookup(e)}}))}function findUnsafeDestinationError(e){return e instanceof UnsafeDestinationError?e:e instanceof Error&&e.cause instanceof UnsafeDestinationError?e.cause:void 0}function fetchWithDispatcher(e,t){return fetch(e,t)}function createPublicLookup(e){return(t,n,r)=>{lookup(t,{all:!0,verbatim:!0},(i,a)=>{if(i!==null){r(i,``,0);return}if(a.some(({address:t})=>isBlockedDestinationHost(t,e))){r(new UnsafeDestinationError,``,0);return}let o=n.family===void 0||n.family===0?a:a.filter(({family:e})=>e===n.family);if(o.length===0){let e=Error(`Unable to resolve URL hostname "${t}" in the requested IP family.`);Object.assign(e,{code:`ENOTFOUND`}),r(e,``,0);return}if(n.all===!0){r(null,o);return}let s=o[0];r(null,s.address,s.family)})}}async function readBoundedResponse(e,t){let n=parseContentLength(e.headers.get(`content-length`));if(n!==void 0&&n>t)throw await cancelResponseBody(e),new ResponseTooLargeError(t);let r=await readBoundedBody(e,t),i=r.byteLength===0?null:Uint8Array.from(r).buffer;return new Response(i,{headers:e.headers,status:e.status,statusText:e.statusText})}function parseContentLength(e){if(e===null)return;let t=Number.parseInt(e,10);return Number.isFinite(t)&&t>=0?t:void 0}async function readBoundedBody(e,t){if(e.body===null)return new Uint8Array;let n=e.body.getReader(),r=[],i=0;try{for(;;){let{done:e,value:a}=await n.read();if(e)break;if(i+=a.byteLength,i>t)throw await n.cancel(),new ResponseTooLargeError(t);r.push(a)}}finally{n.releaseLock()}let a=new Uint8Array(i),o=0;for(let e of r)a.set(e,o),o+=e.byteLength;return a}async function cancelResponseBody(e){try{await e.body?.cancel()}catch{}}var ResponseTooLargeError=class extends Error{constructor(e){super(`Response too large (exceeds ${e} bytes).`),this.name=`ResponseTooLargeError`}};export{ResponseTooLargeError,UnsafeDestinationError,assertPublicHostname,cancelResponseBody,createPublicDispatcher,fetchWithDispatcher,findUnsafeDestinationError,readBoundedResponse};