experimental-ash 0.25.1 → 0.26.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 (88) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/bin/ash.d.ts +4 -4
  3. package/bin/ash.js +12 -8
  4. package/dist/docs/public/channels/README.md +26 -2
  5. package/dist/docs/public/channels/discord.md +159 -0
  6. package/dist/docs/public/channels/slack.md +14 -2
  7. package/dist/src/channel/routes.d.ts +6 -1
  8. package/dist/src/channel/send.js +5 -2
  9. package/dist/src/channel/session-callback.d.ts +10 -0
  10. package/dist/src/channel/session-callback.js +65 -0
  11. package/dist/src/channel/types.d.ts +19 -0
  12. package/dist/src/chunks/{client-BShLWzR6.js → client-ZqNLLMZB.js} +3 -3
  13. package/dist/src/chunks/{compile-agent-CyP6FrL8.js → compile-agent-DrIyb818.js} +1 -1
  14. package/dist/src/chunks/{dev-authored-source-watcher-DIWfVUsu.js → dev-authored-source-watcher-C1WUVv9F.js} +1 -1
  15. package/dist/src/chunks/host-CwAcCrg7.js +70 -0
  16. package/dist/src/chunks/paths-CWZN-XRX.js +85 -0
  17. package/dist/src/chunks/{token-BOkIxJeV.js → token-YW4VSeBB.js} +1 -1
  18. package/dist/src/chunks/types-BJSR0JNV.js +1 -0
  19. package/dist/src/cli/commands/channels.d.ts +15 -0
  20. package/dist/src/cli/commands/channels.js +9 -0
  21. package/dist/src/cli/commands/info.js +1 -1
  22. package/dist/src/cli/dev/repl.js +3 -3
  23. package/dist/src/cli/run.js +1 -1
  24. package/dist/src/client/message-reducer.js +6 -0
  25. package/dist/src/context/keys.d.ts +1 -1
  26. package/dist/src/context/keys.js +1 -1
  27. package/dist/src/context/seed-keys.d.ts +5 -1
  28. package/dist/src/context/seed-keys.js +4 -0
  29. package/dist/src/evals/cli/eval.js +1 -1
  30. package/dist/src/execution/await-authorization-orchestrator.js +1 -1
  31. package/dist/src/execution/node-step.js +13 -0
  32. package/dist/src/execution/remote-agent-dispatch.d.ts +15 -0
  33. package/dist/src/execution/remote-agent-dispatch.js +79 -0
  34. package/dist/src/execution/runtime-context.js +4 -1
  35. package/dist/src/execution/session-callback-step.d.ts +16 -0
  36. package/dist/src/execution/session-callback-step.js +72 -0
  37. package/dist/src/execution/subagent-invocation.d.ts +16 -0
  38. package/dist/src/execution/subagent-invocation.js +16 -0
  39. package/dist/src/execution/subagent-tool.js +5 -8
  40. package/dist/src/execution/workflow-entry.js +21 -1
  41. package/dist/src/execution/workflow-steps.d.ts +6 -1
  42. package/dist/src/execution/workflow-steps.js +76 -25
  43. package/dist/src/harness/execute-tool.d.ts +3 -3
  44. package/dist/src/harness/runtime-actions.d.ts +1 -0
  45. package/dist/src/harness/runtime-actions.js +18 -1
  46. package/dist/src/internal/application/package.js +1 -1
  47. package/dist/src/internal/process/pnpm.d.ts +28 -0
  48. package/dist/src/internal/process/pnpm.js +50 -0
  49. package/dist/src/protocol/message.d.ts +6 -0
  50. package/dist/src/protocol/message.js +1 -0
  51. package/dist/src/protocol/routes.d.ts +11 -0
  52. package/dist/src/protocol/routes.js +13 -0
  53. package/dist/src/public/channels/ash.js +25 -1
  54. package/dist/src/public/channels/discord/api.d.ts +99 -0
  55. package/dist/src/public/channels/discord/api.js +167 -0
  56. package/dist/src/public/channels/discord/defaults.d.ts +9 -0
  57. package/dist/src/public/channels/discord/defaults.js +74 -0
  58. package/dist/src/public/channels/discord/discordChannel.d.ts +132 -0
  59. package/dist/src/public/channels/discord/discordChannel.js +402 -0
  60. package/dist/src/public/channels/discord/hitl.d.ts +34 -0
  61. package/dist/src/public/channels/discord/hitl.js +194 -0
  62. package/dist/src/public/channels/discord/inbound.d.ts +97 -0
  63. package/dist/src/public/channels/discord/inbound.js +238 -0
  64. package/dist/src/public/channels/discord/index.d.ts +7 -0
  65. package/dist/src/public/channels/discord/index.js +6 -0
  66. package/dist/src/public/channels/discord/responses.d.ts +11 -0
  67. package/dist/src/public/channels/discord/responses.js +40 -0
  68. package/dist/src/public/channels/discord/verify.d.ts +38 -0
  69. package/dist/src/public/channels/discord/verify.js +72 -0
  70. package/dist/src/public/channels/discord/verifyInbound.d.ts +6 -0
  71. package/dist/src/public/channels/discord/verifyInbound.js +19 -0
  72. package/dist/src/public/channels/slack/constants.d.ts +7 -0
  73. package/dist/src/public/channels/slack/constants.js +7 -0
  74. package/dist/src/public/channels/slack/slackChannel.js +2 -1
  75. package/dist/src/runtime/actions/keys.js +2 -0
  76. package/dist/src/runtime/actions/types.d.ts +47 -1
  77. package/dist/src/runtime/actions/types.js +23 -0
  78. package/dist/src/runtime/connections/callback-route.d.ts +1 -1
  79. package/dist/src/runtime/connections/callback-route.js +1 -1
  80. package/dist/src/runtime/connections/mcp-client.d.ts +1 -2
  81. package/dist/src/runtime/connections/mcp-client.js +69 -3
  82. package/dist/src/runtime/framework-channels/index.js +7 -2
  83. package/dist/src/runtime/session-callback-route.d.ts +6 -0
  84. package/dist/src/runtime/session-callback-route.js +87 -0
  85. package/package.json +9 -3
  86. package/dist/src/chunks/host-BxT35q6K.js +0 -70
  87. package/dist/src/chunks/paths-B2hLA0Fn.js +0 -85
  88. package/dist/src/chunks/types-CjIyrcYo.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # experimental-ash
2
2
 
3
+ ## 0.26.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 3553354: Add a native Discord channel for HTTP Interactions. The channel verifies Discord Ed25519 signatures, dispatches application commands, supports HITL buttons/selects/modals, sends deferred replies and followups, falls back to bot-token channel messages, supports proactive `receive(...)` sessions, and exposes a best-effort `ctx.discord.startTyping()` helper.
8
+
9
+ ## 0.25.2
10
+
11
+ ### Patch Changes
12
+
13
+ - 2ba4206: Limit MCP SSE fallback to retryable transport errors. The HTTP-streaming → SSE fallback now retries on HTTP 400, 404, and 405 per the MCP transport spec, and surfaces other failures (auth, 5xx) directly instead of masking them behind a confusing fallback error.
14
+
3
15
  ## 0.25.1
4
16
 
5
17
  ### Patch Changes
package/bin/ash.d.ts CHANGED
@@ -5,14 +5,14 @@ export interface BootstrapOptions {
5
5
  cliEntrypointPath?: string;
6
6
 
7
7
  /**
8
- * Absolute path to the script that copies static assets after compilation.
8
+ * Absolute path to the ash package root.
9
9
  */
10
- copyAssetsScriptPath?: string;
10
+ packageRoot?: string;
11
11
 
12
12
  /**
13
- * Absolute path to the ash package root.
13
+ * Absolute paths to scripts that run after workspace bootstrap compilation.
14
14
  */
15
- packageRoot?: string;
15
+ postBuildScriptPaths?: readonly string[];
16
16
 
17
17
  /**
18
18
  * Absolute path to the tsgo CLI entrypoint used for bootstrap builds.
package/bin/ash.js CHANGED
@@ -16,9 +16,11 @@ function createBootstrapOptions(overrides = {}) {
16
16
  return {
17
17
  cliEntrypointPath:
18
18
  overrides.cliEntrypointPath ?? resolve(packageRoot, "dist", "src", "cli", "run.js"),
19
- copyAssetsScriptPath:
20
- overrides.copyAssetsScriptPath ?? resolve(packageRoot, "scripts", "copy-static-assets.mjs"),
21
19
  packageRoot,
20
+ postBuildScriptPaths: overrides.postBuildScriptPaths ?? [
21
+ resolve(packageRoot, "scripts", "copy-docs.mjs"),
22
+ resolve(packageRoot, "scripts", "stamp-version-tokens.mjs"),
23
+ ],
22
24
  tsgoCliPath: overrides.tsgoCliPath,
23
25
  };
24
26
  }
@@ -85,14 +87,14 @@ async function getLatestBuildInputMtimeMs({ packageRoot }) {
85
87
  return latestMtimeMs;
86
88
  }
87
89
 
88
- async function canBuildWorkspaceCli({ copyAssetsScriptPath, exists, packageRoot }) {
90
+ async function canBuildWorkspaceCli({ exists, packageRoot, postBuildScriptPaths }) {
89
91
  for (const requiredPath of [
90
92
  resolve(packageRoot, "bin"),
91
93
  inputTsconfigPath({
92
94
  packageRoot,
93
95
  }),
94
96
  resolve(packageRoot, "src"),
95
- copyAssetsScriptPath,
97
+ ...postBuildScriptPaths,
96
98
  ]) {
97
99
  if (!(await exists(requiredPath))) {
98
100
  return false;
@@ -175,9 +177,9 @@ export async function ensureBuiltCli(overrides = {}, dependencies = {}) {
175
177
  const getEntrypointMtimeMs = dependencies.getPathMtimeMs ?? getPathMtimeMs;
176
178
  const executeCommand = dependencies.runCommand ?? runCommand;
177
179
  const packageCanBuildCli = await canBuildWorkspaceCli({
178
- copyAssetsScriptPath: options.copyAssetsScriptPath,
179
180
  exists,
180
181
  packageRoot: options.packageRoot,
182
+ postBuildScriptPaths: options.postBuildScriptPaths,
181
183
  });
182
184
 
183
185
  if (await exists(options.cliEntrypointPath)) {
@@ -210,9 +212,11 @@ export async function ensureBuiltCli(overrides = {}, dependencies = {}) {
210
212
  cwd: options.packageRoot,
211
213
  },
212
214
  );
213
- await executeCommand(process.execPath, [options.copyAssetsScriptPath], {
214
- cwd: options.packageRoot,
215
- });
215
+ for (const scriptPath of options.postBuildScriptPaths) {
216
+ await executeCommand(process.execPath, [scriptPath], {
217
+ cwd: options.packageRoot,
218
+ });
219
+ }
216
220
 
217
221
  if (await exists(options.cliEntrypointPath)) {
218
222
  return options.cliEntrypointPath;
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: "Channels"
3
- description: "Deliver your agent over HTTP, Slack, and custom transports."
3
+ description: "Deliver your agent over HTTP, Slack, Discord, Twilio, and custom transports."
4
4
  url: /channels
5
5
  ---
6
6
 
@@ -23,7 +23,7 @@ Ash ships the public HTTP protocol as channels:
23
23
  - `ashChannel({ auth })` for the built-in Ash protocol channel
24
24
 
25
25
  Ash also supports authored channels under `agent/channels/` for platform-specific integrations such
26
- as Slack or custom webhooks.
26
+ as Slack, Discord, Twilio, or custom webhooks.
27
27
 
28
28
  ## Filesystem Shape
29
29
 
@@ -232,6 +232,30 @@ dispatch for app mentions, direct messages, and interactions.
232
232
  For a Slack app backed by Vercel Connect, see [Slack channel setup](./slack.md) to create the Connect client
233
233
  and channel file.
234
234
 
235
+ ## Discord Channels
236
+
237
+ Discord channels are authored with `discordChannel()`:
238
+
239
+ ```ts
240
+ import { discordChannel } from "experimental-ash/channels/discord";
241
+
242
+ export default discordChannel();
243
+ ```
244
+
245
+ The channel verifies Discord's Ed25519 interaction signature headers, accepts HTTP Interactions at
246
+ `/ash/v1/discord`, responds to `PING`, dispatches application commands, and resolves HITL button,
247
+ select, and modal submissions back into Ash input responses. The default command parser uses a
248
+ string option named `message` as the agent prompt and derives auth from the invoking Discord user.
249
+
250
+ Default delivery edits the original deferred interaction response for the first agent reply, sends
251
+ followups after that, and falls back to bot-token channel messages when the interaction token can no
252
+ longer be used. Proactive `receive(discord, { channelId })` sessions also use bot-token channel
253
+ messages. Default progress handlers trigger Discord's short-lived typing indicator when bot auth is
254
+ available.
255
+
256
+ See [Discord channel setup](./discord.md) for endpoint setup, environment variables, command
257
+ registration, and overrides.
258
+
235
259
  ## Twilio Channels
236
260
 
237
261
  Twilio channels are authored with `twilioChannel()`:
@@ -0,0 +1,159 @@
1
+ ---
2
+ title: "Discord channel setup"
3
+ description: "Create a Discord-backed Ash channel for HTTP Interactions."
4
+ ---
5
+
6
+ # Discord Channel Setup
7
+
8
+ The Discord channel accepts HTTP Interactions: slash/application commands, message components, and
9
+ modal submissions. It verifies Discord's Ed25519 signature headers before parsing the request,
10
+ acknowledges commands immediately, and continues Ash work in the background.
11
+
12
+ ## Add The Channel
13
+
14
+ Create `agent/channels/discord.ts`:
15
+
16
+ ```ts
17
+ import { discordChannel } from "experimental-ash/channels/discord";
18
+
19
+ export default discordChannel();
20
+ ```
21
+
22
+ Set the credentials Ash needs for inbound verification and outbound replies:
23
+
24
+ ```bash
25
+ DISCORD_PUBLIC_KEY=...
26
+ DISCORD_APPLICATION_ID=...
27
+ DISCORD_BOT_TOKEN=...
28
+ ```
29
+
30
+ - `DISCORD_PUBLIC_KEY` verifies `X-Signature-Ed25519` and `X-Signature-Timestamp`.
31
+ - `DISCORD_APPLICATION_ID` lets Ash edit the original deferred interaction response and send
32
+ followups.
33
+ - `DISCORD_BOT_TOKEN` lets Ash send proactive channel messages and fall back after an interaction
34
+ token expires. It also powers best-effort channel typing indicators.
35
+
36
+ You can also pass the same values in config:
37
+
38
+ ```ts
39
+ export default discordChannel({
40
+ credentials: {
41
+ applicationId: "123456789012345678",
42
+ botToken: process.env.DISCORD_BOT_TOKEN,
43
+ publicKey: process.env.DISCORD_PUBLIC_KEY,
44
+ },
45
+ });
46
+ ```
47
+
48
+ By default, the channel mounts `POST /ash/v1/discord`. Paste that public URL into your Discord
49
+ application's **Interactions Endpoint URL**.
50
+
51
+ ## Register A Command
52
+
53
+ The channel does not register commands for you. Create a command with Discord's application command
54
+ API or the Developer Portal. A simple command with a string option named `message` maps cleanly to
55
+ the default Ash prompt extraction:
56
+
57
+ ```bash
58
+ curl -X PUT \
59
+ "https://discord.com/api/v10/applications/$DISCORD_APPLICATION_ID/commands" \
60
+ -H "Authorization: Bot $DISCORD_BOT_TOKEN" \
61
+ -H "Content-Type: application/json" \
62
+ -d '[
63
+ {
64
+ "name": "ask",
65
+ "description": "Ask the Ash agent",
66
+ "type": 1,
67
+ "options": [
68
+ {
69
+ "name": "message",
70
+ "description": "What should the agent do?",
71
+ "type": 3,
72
+ "required": true
73
+ }
74
+ ]
75
+ }
76
+ ]'
77
+ ```
78
+
79
+ Discord may take time to propagate global command changes. Use guild commands during development if
80
+ you need faster iteration.
81
+
82
+ ## Hooks And Delivery
83
+
84
+ `onCommand(ctx, interaction)` decides whether to dispatch a command and what auth to use. Return
85
+ `{ auth }` to dispatch or `null` to acknowledge without running the agent. The default derives auth
86
+ from the invoking Discord user.
87
+
88
+ ```ts
89
+ import { discordChannel } from "experimental-ash/channels/discord";
90
+
91
+ export default discordChannel({
92
+ onCommand(ctx, interaction) {
93
+ return {
94
+ auth: {
95
+ principalId: interaction.user.id,
96
+ principalType: "user",
97
+ authenticator: "discord",
98
+ attributes: {
99
+ channel_id: interaction.channelId,
100
+ guild_id: interaction.guildId ?? "",
101
+ },
102
+ },
103
+ };
104
+ },
105
+ events: {
106
+ "message.completed"(event, ctx) {
107
+ if (event.finishReason === "tool-calls") return;
108
+ if (event.message) ctx.discord.post(event.message);
109
+ },
110
+ },
111
+ });
112
+ ```
113
+
114
+ The default `"message.completed"` handler edits the original deferred response for the first reply,
115
+ then sends followups. If Discord rejects the interaction-token write, Ash falls back to a
116
+ bot-authenticated channel message. Outbound text is split to Discord's 2000-character content limit,
117
+ and generated messages default to `allowed_mentions: { parse: [] }`.
118
+
119
+ The default `"turn.started"` and `"actions.requested"` handlers trigger Discord's short-lived
120
+ channel typing indicator when a bot token is available. You can call `ctx.discord.startTyping()` in
121
+ custom hooks or event handlers; failures are logged and swallowed because typing is only a UX hint.
122
+
123
+ ## Human Input
124
+
125
+ Pending Ash input requests render as Discord components:
126
+
127
+ - confirmation/options render as buttons;
128
+ - `display: "select"` renders as a string select;
129
+ - freeform questions render a button that opens a Discord modal.
130
+
131
+ Component and modal submissions resume the parked Ash session automatically.
132
+
133
+ ## Proactive Sessions
134
+
135
+ Use `receive(discord, args)` from schedules or another channel to start a Discord session:
136
+
137
+ ```ts
138
+ import { defineSchedule, receive } from "experimental-ash/schedules";
139
+ import discord from "../channels/discord.js";
140
+
141
+ export default defineSchedule({
142
+ cron: "0 9 * * 1-5",
143
+ markdown: "Post the daily summary.",
144
+ channel: receive(discord, {
145
+ channelId: "123456789012345678",
146
+ initialMessage: "Daily summary",
147
+ }),
148
+ });
149
+ ```
150
+
151
+ Proactive delivery requires `DISCORD_BOT_TOKEN` or `credentials.botToken`.
152
+
153
+ ## Discord References
154
+
155
+ - [Interactions overview](https://docs.discord.com/developers/interactions/overview)
156
+ - [Receiving and responding to interactions](https://docs.discord.com/developers/interactions/receiving-and-responding)
157
+ - [Application commands](https://docs.discord.com/developers/interactions/application-commands)
158
+ - [Create message](https://docs.discord.com/developers/resources/message#create-message)
159
+ - [Trigger typing indicator](https://docs.discord.com/developers/resources/channel#trigger-typing-indicator)
@@ -71,12 +71,24 @@ If you are using an AI coding agent, install the Connect skill first:
71
71
  npx skills add https://github.com/vercel/connect --skill vercel-connect
72
72
  ```
73
73
 
74
- Then create the Slack client from the project or agent folder that will use it:
74
+ Then create the Slack client from the project or agent folder that will use it, and attach this
75
+ project as the trigger destination so Slack events are forwarded to your deployment:
75
76
 
76
77
  ```bash
77
- vercel connect create slack
78
+ vercel connect create slack --triggers
79
+ vercel connect detach <uid> --yes
80
+ vercel connect attach <uid> --triggers --trigger-path /ash/v1/slack --yes
78
81
  ```
79
82
 
83
+ `--triggers` on `create` is what turns on Slack Event Subscriptions — without it the bot installs
84
+ but Slack never delivers `app_mention` or `message.im` events to the Connect webhook. The create
85
+ step also auto-attaches the linked project at Connect's default trigger path, so detach it before
86
+ attaching the Ash path. `attach --triggers` then registers the currently-linked Vercel project as
87
+ the destination Connect forwards verified webhooks to. The `--trigger-path /ash/v1/slack` value
88
+ must match Ash's Slack channel route; the default Connect trigger path is not served by Ash. These
89
+ commands target your project's production deployment, so make sure you have run
90
+ `vercel deploy --prod` before attaching.
91
+
80
92
  Run Connect commands from the directory containing the agent's `package.json` or `vercel.json`.
81
93
  Connect uses that project context to configure project access, webhooks, and triggers. The command
82
94
  may open a browser for Slack installation or OAuth consent; finish that flow before continuing.
@@ -1,8 +1,9 @@
1
1
  import type { ModelMessage, UserContent } from "ai";
2
2
  import type { CrossChannelReceiveFn } from "#channel/cross-channel-receive.js";
3
- import type { SessionAuthContext } from "#channel/types.js";
3
+ import type { SessionAuthContext, SessionCallback } from "#channel/types.js";
4
4
  import type { InputResponse } from "#runtime/input/types.js";
5
5
  import type { Session } from "#channel/session.js";
6
+ import type { RunMode } from "#shared/run-mode.js";
6
7
  export interface RouteHandlerArgs<TState = undefined> {
7
8
  send: SendFn<TState>;
8
9
  getSession: GetSessionFn;
@@ -40,10 +41,14 @@ export type SendFn<TState = undefined> = (input: string | UserContent | SendPayl
40
41
  */
41
42
  export type SendOptions<TState = undefined> = TState extends undefined ? {
42
43
  auth: SessionAuthContext | null;
44
+ callback?: SessionCallback;
43
45
  continuationToken: string;
46
+ mode?: RunMode;
44
47
  } : {
45
48
  auth: SessionAuthContext | null;
49
+ callback?: SessionCallback;
46
50
  continuationToken: string;
51
+ mode?: RunMode;
47
52
  state: TState;
48
53
  };
49
54
  export type GetSessionFn = (sessionId: string) => Session;
@@ -7,6 +7,8 @@ const log = createLogger("channel.send");
7
7
  export function createSendFn(runtime, adapter, channelName) {
8
8
  return async (input, options) => {
9
9
  const auth = options.auth;
10
+ const callback = options.callback;
11
+ const mode = options.mode ?? "conversation";
10
12
  const state = options.state;
11
13
  const rawToken = options.continuationToken;
12
14
  const continuationToken = `${channelName}:${rawToken}`;
@@ -40,10 +42,11 @@ export function createSendFn(runtime, adapter, channelName) {
40
42
  const handle = await runtime.run({
41
43
  adapter: sessionAdapter,
42
44
  auth,
43
- capabilities: { requestInput: true },
45
+ capabilities: mode === "conversation" ? { requestInput: true } : undefined,
46
+ callback,
44
47
  continuationToken,
45
48
  input: { message: message ?? "", modelContext },
46
- mode: "conversation",
49
+ mode,
47
50
  });
48
51
  return createSession(handle.sessionId, rawToken, runtime);
49
52
  };
@@ -0,0 +1,10 @@
1
+ import type { SessionCallback } from "#channel/types.js";
2
+ export type SessionCallbackParseResult = {
3
+ readonly callback: SessionCallback;
4
+ readonly ok: true;
5
+ } | {
6
+ readonly cause: unknown;
7
+ readonly message: string;
8
+ readonly ok: false;
9
+ };
10
+ export declare function parseSessionCallback(value: unknown): SessionCallbackParseResult;
@@ -0,0 +1,65 @@
1
+ import { z } from "#compiled/zod/index.js";
2
+ import { createAshCallbackRoutePath } from "#protocol/routes.js";
3
+ const sessionCallbackSchema = z
4
+ .object({
5
+ callId: z.string().min(1),
6
+ subagentName: z.string().min(1),
7
+ token: z.string().min(1),
8
+ url: z.string().min(1),
9
+ })
10
+ .strict()
11
+ .superRefine((callback, ctx) => {
12
+ let url;
13
+ try {
14
+ url = new URL(callback.url);
15
+ }
16
+ catch {
17
+ ctx.addIssue({
18
+ code: "custom",
19
+ message: "Callback url must be absolute.",
20
+ path: ["url"],
21
+ });
22
+ return;
23
+ }
24
+ if (readCallbackUrlToken(url) !== callback.token) {
25
+ ctx.addIssue({
26
+ code: "custom",
27
+ message: "Callback url token must match callback token.",
28
+ path: ["url"],
29
+ });
30
+ }
31
+ });
32
+ export function parseSessionCallback(value) {
33
+ const parsed = sessionCallbackSchema.safeParse(value);
34
+ if (parsed.success) {
35
+ return { callback: parsed.data, ok: true };
36
+ }
37
+ return {
38
+ cause: parsed.error,
39
+ message: formatSessionCallbackParseError(parsed.error),
40
+ ok: false,
41
+ };
42
+ }
43
+ function readCallbackUrlToken(url) {
44
+ const tokenPrefix = createAshCallbackRoutePath("");
45
+ if (!url.pathname.startsWith(tokenPrefix)) {
46
+ return null;
47
+ }
48
+ const encodedToken = url.pathname.slice(tokenPrefix.length);
49
+ if (encodedToken.length === 0 || encodedToken.includes("/")) {
50
+ return null;
51
+ }
52
+ try {
53
+ return decodeURIComponent(encodedToken);
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ function formatSessionCallbackParseError(error) {
60
+ const messages = error.issues.map((issue) => {
61
+ const path = issue.path.length === 0 ? "callback" : `callback.${issue.path.join(".")}`;
62
+ return `${path}: ${issue.message}`;
63
+ });
64
+ return `Invalid callback metadata: ${messages.join("; ")}`;
65
+ }
@@ -114,6 +114,20 @@ export interface SubagentInputRequestHookPayload {
114
114
  * Serializable payload sent through the workflow `resumeHook`.
115
115
  */
116
116
  export type HookPayload = DeliverHookPayload | RuntimeActionResultHookPayload | SubagentInputRequestHookPayload;
117
+ /**
118
+ * Terminal callback metadata attached to a session at creation.
119
+ *
120
+ * `url` is the absolute callback endpoint. `token` is the capability token
121
+ * embedded in the framework-owned callback route. `callId` and
122
+ * `subagentName` correlate the callee's terminal callback back to the
123
+ * pending parent tool call.
124
+ */
125
+ export interface SessionCallback {
126
+ readonly callId: string;
127
+ readonly subagentName: string;
128
+ readonly token: string;
129
+ readonly url: string;
130
+ }
117
131
  /**
118
132
  * Declares runtime capabilities granted to one Ash session.
119
133
  *
@@ -160,6 +174,11 @@ export interface RunInput {
160
174
  * leave this undefined.
161
175
  */
162
176
  readonly capabilities?: SessionCapabilities;
177
+ /**
178
+ * Optional terminal callback. When present, the runtime posts a single
179
+ * callback when the session completes or fails.
180
+ */
181
+ readonly callback?: SessionCallback;
163
182
  /**
164
183
  * Session continuation token for delivery and hook creation. Channels
165
184
  * can re-key the session during the first turn by calling
@@ -1,4 +1,4 @@
1
- import{i as e,r as t,t as n}from"./chunk-DSjMdhoD.js";import{_ as r,c as i,d as a,f as o,g as s,h as c}from"./types-CjIyrcYo.js";var l=class extends Error{status;body;constructor(e,t){super(t||`Server returned ${e}.`),this.name=`ClientError`,this.status=e,this.body=t}};function u(e){if(e instanceof DOMException)return e.name===`AbortError`;if(!(e instanceof Error))return!1;let t=`code`in e&&typeof e.code==`string`?e.code:void 0;return e.name===`AbortError`||e.message===`terminated`||t===`UND_ERR_SOCKET`||/abort|cancel|disconnect|premature close|socket|terminated/i.test(e.message)}async function*d(e){let t=e.getReader(),n=new TextDecoder,r=``;try{for(;;){let e=await t.read();if(e.done){r+=n.decode();break}e.value&&(r+=n.decode(e.value,{stream:!0}));let i=r.indexOf(`
1
+ import{i as e,r as t,t as n}from"./chunk-DSjMdhoD.js";import{c as r,f as i,g as a,p as o,v as s,y as c}from"./types-BJSR0JNV.js";var l=class extends Error{status;body;constructor(e,t){super(t||`Server returned ${e}.`),this.name=`ClientError`,this.status=e,this.body=t}};function u(e){if(e instanceof DOMException)return e.name===`AbortError`;if(!(e instanceof Error))return!1;let t=`code`in e&&typeof e.code==`string`?e.code:void 0;return e.name===`AbortError`||e.message===`terminated`||t===`UND_ERR_SOCKET`||/abort|cancel|disconnect|premature close|socket|terminated/i.test(e.message)}async function*d(e){let t=e.getReader(),n=new TextDecoder,r=``;try{for(;;){let e=await t.read();if(e.done){r+=n.decode();break}e.value&&(r+=n.decode(e.value,{stream:!0}));let i=r.indexOf(`
2
2
  `);for(;i!==-1;){let e=r.slice(0,i).trim();r=r.slice(i+1),e.length>0&&(yield JSON.parse(e)),i=r.indexOf(`
3
- `)}}let e=r.trim();e.length>0&&(yield JSON.parse(e))}finally{t.releaseLock()}}function f(e,t,n){let r=t.startsWith(`/`)?t:`/${t}`,i=h(n);if(p(e)){let t=new URL(e);return t.pathname=`${m(t.pathname)}${r}`,t.search=i,t.hash=``,t.toString()}return`${m(e)}${r}${i}`}function p(e){return/^[a-z][a-z\d+\-.]*:/i.test(e)}function m(e){return e===`/`?``:e.endsWith(`/`)?e.slice(0,-1):e}function h(e){return!e||Object.keys(e).length===0?``:`?${new URLSearchParams(e).toString()}`}async function*g(e){let t=e.startIndex,n=e.maxReconnectAttempts;for(;;){let i=f(e.host,r(e.sessionId),t>0?{startIndex:String(t)}:void 0),a=await e.resolveHeaders(),o=await fetch(i,{headers:a,signal:e.signal??null});if(!o.ok){let e=await o.text();throw new l(o.status,e)}if(!o.body)throw new l(o.status,`Response body is null.`);let s=!1;try{for await(let e of d(o.body))t+=1,yield e}catch(e){if(!u(e))throw e;s=!0}if(!s||n<=0)return;--n}}var _=n(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},s=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},c=e=>s(n({},`__esModule`,{value:!0}),e),l={};o(l,{SYMBOL_FOR_REQ_CONTEXT:()=>u,getContext:()=>d}),t.exports=c(l);let u=Symbol.for(`@vercel/request-context`);function d(){return globalThis[u]?.get?.()??{}}})),v=n(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},s=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},c=e=>s(n({},`__esModule`,{value:!0}),e),l={};o(l,{VercelOidcTokenError:()=>u}),t.exports=c(l);var u=class extends Error{constructor(e,t){super(e),this.name=`VercelOidcTokenError`,this.cause=t}toString(){return this.cause?`${this.name}: ${this.message}: ${this.cause}`:`${this.name}: ${this.message}`}}})),y=n(((t,n)=>{var r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,s=(e,t)=>{for(var n in t)r(e,n,{get:t[n],enumerable:!0})},c=(e,t,n,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of a(t))!o.call(e,c)&&c!==n&&r(e,c,{get:()=>t[c],enumerable:!(s=i(t,c))||s.enumerable});return e},l=e=>c(r({},`__esModule`,{value:!0}),e),u={};s(u,{getVercelOidcToken:()=>p,getVercelOidcTokenSync:()=>m}),n.exports=l(u);var d=_(),f=v();async function p(t){let n=``,r;try{n=m()}catch(e){r=e}try{let[{getTokenPayload:r,isExpired:i},{refreshToken:a}]=await Promise.all([await Promise.resolve().then(()=>e(w())),await import(`./token-BOkIxJeV.js`).then(t=>e(t.default))]);(!n||i(r(n),t?.expirationBufferMs))&&(await a(t),n=m())}catch(e){let t=r instanceof Error?r.message:``;throw e instanceof Error&&(t=`${t}
4
- ${e.message}`),t?new f.VercelOidcTokenError(t):e}return n}function m(){let e=(0,d.getContext)().headers?.[`x-vercel-oidc-token`]??process.env.VERCEL_OIDC_TOKEN;if(!e)throw Error(`The 'x-vercel-oidc-token' header is missing from the request. Do you have the OIDC option enabled in the Vercel project settings?`);return e}})),b=n(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},s=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},c=e=>s(n({},`__esModule`,{value:!0}),e),l={};o(l,{AccessTokenMissingError:()=>u,RefreshAccessTokenFailedError:()=>d}),t.exports=c(l);var u=class extends Error{constructor(){super(`No authentication found. Please log in with the Vercel CLI (vercel login).`),this.name=`AccessTokenMissingError`}},d=class extends Error{constructor(e){super(`Failed to refresh authentication token.`,{cause:e}),this.name=`RefreshAccessTokenFailedError`}}})),x=n(((e,n)=>{var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t)=>{for(var n in t)i(e,n,{get:t[n],enumerable:!0})},u=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let s of o(t))!c.call(e,s)&&s!==n&&i(e,s,{get:()=>t[s],enumerable:!(r=a(t,s))||r.enumerable});return e},d=(e,t,n)=>(n=e==null?{}:r(s(e)),u(t||!e||!e.__esModule?i(n,`default`,{value:e,enumerable:!0}):n,e)),f=e=>u(i({},`__esModule`,{value:!0}),e),p={};l(p,{findRootDir:()=>y,getUserDataDir:()=>b}),n.exports=f(p);var m=d(t(`path`)),h=d(t(`fs`)),g=d(t(`os`)),_=v();function y(){try{let e=process.cwd();for(;e!==m.default.dirname(e);){let t=m.default.join(e,`.vercel`);if(h.default.existsSync(t))return e;e=m.default.dirname(e)}}catch{throw new _.VercelOidcTokenError(`Token refresh only supported in node server environments`)}return null}function b(){if(process.env.XDG_DATA_HOME)return process.env.XDG_DATA_HOME;switch(g.default.platform()){case`darwin`:return m.default.join(g.default.homedir(),`Library/Application Support`);case`linux`:return m.default.join(g.default.homedir(),`.local/share`);case`win32`:return process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:null;default:return null}}})),S=n(((e,n)=>{var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t)=>{for(var n in t)i(e,n,{get:t[n],enumerable:!0})},u=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let s of o(t))!c.call(e,s)&&s!==n&&i(e,s,{get:()=>t[s],enumerable:!(r=a(t,s))||r.enumerable});return e},d=(e,t,n)=>(n=e==null?{}:r(s(e)),u(t||!e||!e.__esModule?i(n,`default`,{value:e,enumerable:!0}):n,e)),f=e=>u(i({},`__esModule`,{value:!0}),e),p={};l(p,{isValidAccessToken:()=>b,readAuthConfig:()=>v,writeAuthConfig:()=>y}),n.exports=f(p);var m=d(t(`fs`)),h=d(t(`path`)),g=w();function _(){let e=(0,g.getVercelDataDir)();if(!e)throw Error(`Unable to find Vercel CLI data directory. Your platform: ${process.platform}. Supported: darwin, linux, win32.`);return h.join(e,`auth.json`)}function v(){try{let e=_();if(!m.existsSync(e))return null;let t=m.readFileSync(e,`utf8`);return t?JSON.parse(t):null}catch{return null}}function y(e){let t=_(),n=h.dirname(t);m.existsSync(n)||m.mkdirSync(n,{mode:504,recursive:!0}),m.writeFileSync(t,JSON.stringify(e,null,2),{mode:384})}function b(e,t=0){if(!e.token)return!1;if(typeof e.expiresAt!=`number`)return!0;let n=Math.floor(Date.now()/1e3),r=t/1e3;return e.expiresAt>=n+r}})),C=n(((e,n)=>{var r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,s=(e,t)=>{for(var n in t)r(e,n,{get:t[n],enumerable:!0})},c=(e,t,n,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of a(t))!o.call(e,c)&&c!==n&&r(e,c,{get:()=>t[c],enumerable:!(s=i(t,c))||s.enumerable});return e},l=e=>c(r({},`__esModule`,{value:!0}),e),u={};s(u,{processTokenResponse:()=>g,refreshTokenRequest:()=>h}),n.exports=l(u);var d=t(`os`);let f=`@vercel/oidc node-${process.version} ${(0,d.platform)()} (${(0,d.arch)()}) ${(0,d.hostname)()}`,p=null;async function m(){if(p)return p;let e=await fetch(`https://vercel.com/.well-known/openid-configuration`,{headers:{"user-agent":f}});if(!e.ok)throw Error(`Failed to discover OAuth endpoints`);let t=await e.json();if(!t||typeof t.token_endpoint!=`string`)throw Error(`Invalid OAuth discovery response`);let n=t.token_endpoint;return p=n,n}async function h(e){let t=await m();return await fetch(t,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`,"user-agent":f},body:new URLSearchParams({client_id:`cl_HYyOPBNtFMfHhaUn9L4QPfTZz6TP47bp`,grant_type:`refresh_token`,...e})})}async function g(e){let t=await e.json();if(!e.ok){let e=typeof t==`object`&&t&&`error`in t?String(t.error):`Token refresh failed`;return[Error(e)]}return typeof t!=`object`||!t?[Error(`Invalid token response`)]:typeof t.access_token==`string`?t.token_type===`Bearer`?typeof t.expires_in==`number`?[null,t]:[Error(`Missing expires_in in response`)]:[Error(`Invalid token_type in response`)]:[Error(`Missing access_token in response`)]}})),w=n(((e,n)=>{var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t)=>{for(var n in t)i(e,n,{get:t[n],enumerable:!0})},u=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let s of o(t))!c.call(e,s)&&s!==n&&i(e,s,{get:()=>t[s],enumerable:!(r=a(t,s))||r.enumerable});return e},d=(e,t,n)=>(n=e==null?{}:r(s(e)),u(t||!e||!e.__esModule?i(n,`default`,{value:e,enumerable:!0}):n,e)),f=e=>u(i({},`__esModule`,{value:!0}),e),p={};l(p,{assertVercelOidcTokenResponse:()=>k,findProjectInfo:()=>A,getTokenPayload:()=>N,getVercelDataDir:()=>E,getVercelOidcToken:()=>O,getVercelToken:()=>D,isExpired:()=>P,loadToken:()=>M,saveToken:()=>j}),n.exports=f(p);var m=d(t(`path`)),h=d(t(`fs`)),g=v(),_=x(),y=S(),w=C(),T=b();function E(){let e=(0,_.getUserDataDir)();return e?m.join(e,`com.vercel.cli`):null}async function D(e){let t=(0,y.readAuthConfig)();if(!t?.token)throw new T.AccessTokenMissingError;if((0,y.isValidAccessToken)(t,e?.expirationBufferMs))return t.token;if(!t.refreshToken)throw(0,y.writeAuthConfig)({}),new T.RefreshAccessTokenFailedError(`No refresh token available`);try{let e=await(0,w.refreshTokenRequest)({refresh_token:t.refreshToken}),[n,r]=await(0,w.processTokenResponse)(e);if(n||!r)throw(0,y.writeAuthConfig)({}),new T.RefreshAccessTokenFailedError(n);let i={token:r.access_token,expiresAt:Math.floor(Date.now()/1e3)+r.expires_in};return r.refresh_token&&(i.refreshToken=r.refresh_token),(0,y.writeAuthConfig)(i),i.token}catch(e){throw(0,y.writeAuthConfig)({}),e instanceof T.AccessTokenMissingError||e instanceof T.RefreshAccessTokenFailedError?e:new T.RefreshAccessTokenFailedError(e)}}async function O(e,t,n){let r=`https://api.vercel.com/v1/projects/${t}/token?source=vercel-oidc-refresh${n?`&teamId=${n}`:``}`,i=await fetch(r,{method:`POST`,headers:{Authorization:`Bearer ${e}`}});if(!i.ok)throw new g.VercelOidcTokenError(`Failed to refresh OIDC token: ${i.statusText}`);let a=await i.json();return k(a),a}function k(e){if(!e||typeof e!=`object`)throw TypeError("Vercel OIDC token is malformed. Expected an object. Please run `vc env pull` and try again");if(!(`token`in e)||typeof e.token!=`string`)throw TypeError("Vercel OIDC token is malformed. Expected a string-valued token property. Please run `vc env pull` and try again")}function A(){let e=(0,_.findRootDir)();if(!e)throw new g.VercelOidcTokenError("Unable to find project root directory. Have you linked your project with `vc link?`");let t=m.join(e,`.vercel`,`project.json`);if(!h.existsSync(t))throw new g.VercelOidcTokenError("project.json not found, have you linked your project with `vc link?`");let n=JSON.parse(h.readFileSync(t,`utf8`));if(typeof n.projectId!=`string`&&typeof n.orgId!=`string`)throw TypeError("Expected a string-valued projectId property. Try running `vc link` to re-link your project.");return{projectId:n.projectId,teamId:n.orgId}}function j(e,t){let n=(0,_.getUserDataDir)();if(!n)throw new g.VercelOidcTokenError(`Unable to find user data directory. Please reach out to Vercel support.`);let r=m.join(n,`com.vercel.token`,`${t}.json`),i=JSON.stringify(e);h.mkdirSync(m.dirname(r),{mode:504,recursive:!0}),h.writeFileSync(r,i),h.chmodSync(r,432)}function M(e){let t=(0,_.getUserDataDir)();if(!t)throw new g.VercelOidcTokenError(`Unable to find user data directory. Please reach out to Vercel support.`);let n=m.join(t,`com.vercel.token`,`${e}.json`);if(!h.existsSync(n))return null;let r=JSON.parse(h.readFileSync(n,`utf8`));return k(r),r}function N(e){let t=e.split(`.`);if(t.length!==3)throw new g.VercelOidcTokenError("Invalid token. Please run `vc env pull` and try again");let n=t[1].replace(/-/g,`+`).replace(/_/g,`/`),r=n.padEnd(n.length+(4-n.length%4)%4,`=`);return JSON.parse(Buffer.from(r,`base64`).toString(`utf8`))}function P(e,t=0){return e.exp*1e3<Date.now()+t}})),T=n(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},s=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},c=e=>s(n({},`__esModule`,{value:!0}),e),l={};o(l,{AccessTokenMissingError:()=>f.AccessTokenMissingError,RefreshAccessTokenFailedError:()=>f.RefreshAccessTokenFailedError,getContext:()=>d.getContext,getVercelOidcToken:()=>u.getVercelOidcToken,getVercelOidcTokenSync:()=>u.getVercelOidcTokenSync,getVercelToken:()=>p.getVercelToken}),t.exports=c(l);var u=y(),d=_(),f=b(),p=w()})),E=T();const D=`${c}/`,O=new Set([`localhost`,`127.0.0.1`,`0.0.0.0`,`::1`,`[::1]`]);function k(e){return O.has(e.hostname)}function A(e){try{return k(new URL(e))}catch{return!1}}async function j(){try{let e=(await(0,E.getVercelOidcToken)()).trim();if(e.length>0)return e}catch{}return process.env.VERCEL_OIDC_TOKEN?.trim()??``}const M=`x-vercel-protection-bypass`,N=`x-vercel-trusted-oidc-idp-token`;function P(e){return e.pathname.endsWith(`/ash/v1`)||e.pathname.includes(D)}async function F(e){let t=I(e),n=await R(t,e.resourceUrl);return n!==null&&L(t,n),t}function I(e){let t=new Headers(V(e.headers)),n=process.env.VERCEL_AUTOMATION_BYPASS_SECRET?.trim();return n&&P(e.resourceUrl)&&t.set(M,n),t}function L(e,t){e.has(`authorization`)||e.set(`authorization`,`Bearer ${t}`),e.set(N,t)}async function R(e,t){return z(t)?e.get(`x-vercel-oidc-token`)?.trim()||await B():null}function z(e){return!(!P(e)||k(e))}async function B(){let e=await j();return e.length>0?e:null}function V(e){if(e!==void 0)return e instanceof Headers?e:Array.isArray(e)?e.map(([e,t])=>[e,t]):e}async function H(e){let t={},n=process.env.VERCEL_AUTOMATION_BYPASS_SECRET?.trim();if(n&&(t[M]=n),!A(e.serverUrl)){let e=await j();e.length>0&&(t[N]=e)}return t}function U(){return{streamIndex:0}}function W(e){let t=q(e.events),n=e.session.streamIndex+e.events.length;return t?.type===`session.waiting`?{continuationToken:e.continuationToken??e.session.continuationToken,sessionId:e.sessionId,streamIndex:n}:U()}function G(e){let t;for(let n of e)J(n)&&(t=n.data.message??void 0);return t}function K(e){let t=q(e);return t?.type===`session.waiting`?`waiting`:t?.type===`session.failed`?`failed`:`completed`}function q(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(n!==void 0&&i(n))return n}}function J(e){return e.type===`message.completed`&&e.data.finishReason!==`tool-calls`}var Y=class{continuationToken;sessionId;#e=!1;#t;constructor(e){this.continuationToken=e.continuationToken,this.sessionId=e.sessionId,this.#t=e.createStream}async result(){let e=[];for await(let t of this)e.push(t);return{events:e,message:G(e),sessionId:this.sessionId,status:K(e)}}[Symbol.asyncIterator](){if(this.#e)throw Error(`MessageResponse has already been consumed.`);return this.#e=!0,this.#t()}},X=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}get state(){return this.#t}async sendMessage(e,t){return this.send({message:e},t)}async send(e,t){let n=this.#t,{continuationToken:r,sessionId:i}=await this.#n(e,n,t);return new Y({continuationToken:r,createStream:()=>this.#r(i,r,n,t),sessionId:i})}openStream(e){let t=this.#t.sessionId;if(!t)throw Error(`Session has no session ID. Send a message first.`);return g({host:this.#e.host,maxReconnectAttempts:this.#e.maxReconnectAttempts,resolveHeaders:()=>this.#e.resolveHeaders(),sessionId:t,signal:e?.signal,startIndex:e?.startIndex??this.#t.streamIndex})}async#n(e,t,n){let r=t.sessionId?s(t.sessionId):a,i=f(this.#e.host,r),o=await this.#e.resolveHeaders(n?.headers);o.set(`content-type`,`application/json`);let c=Z({input:e,session:t});if(c===null)throw Error(`Session.send requires a non-empty message, inputResponses, or both.`);let u=await fetch(i,{body:JSON.stringify(c),headers:o,method:`POST`,signal:n?.signal??null});if(!u.ok){let e=await u.text();throw new l(u.status,e)}let d=await u.json(),p=(typeof d.sessionId==`string`?d.sessionId:void 0)??u.headers.get(`x-ash-session-id`)?.trim()??t.sessionId;if(!p)throw Error(`Message route did not return a session id.`);return{continuationToken:typeof d.continuationToken==`string`?d.continuationToken:void 0,sessionId:p}}async*#r(e,t,n,r){let a=[];try{let t=n.sessionId===e?n.streamIndex:0,o=this.#e.maxReconnectAttempts;for(;;){let n=await this.#i(e,t,r?.signal),s=!1;try{for await(let e of d(n))if(a.push(e),t+=1,yield e,i(e)){s=!0;break}}catch(e){if(!u(e))throw e}if(s||o<=0)break;--o}}finally{this.#t=W({continuationToken:t,events:a,sessionId:e,session:n})}}async#i(e,t,n){let i=f(this.#e.host,r(e),t>0?{startIndex:String(t)}:void 0),a=await this.#e.resolveHeaders(),o=await fetch(i,{headers:a,signal:n??null});if(!o.ok){let e=await o.text();throw new l(o.status,e)}if(!o.body)throw new l(o.status,`Response body is null.`);return o.body}};function Z(e){let t={};return e.input.message!==void 0&&(t.message=e.input.message),e.input.inputResponses!==void 0&&e.input.inputResponses.length>0&&(t.inputResponses=e.input.inputResponses),e.input.clientContext!==void 0&&(t.clientContext=e.input.clientContext),e.session.continuationToken!==void 0&&(t.continuationToken=e.session.continuationToken),Object.keys(t).length===0||e.session.continuationToken===void 0&&t.message===void 0||e.session.continuationToken!==void 0&&t.message===void 0&&t.inputResponses===void 0?null:t}var Q=class{#e;#t;#n;#r;constructor(e){this.#n=e.host,this.#e=e.auth,this.#t=e.headers,this.#r=e.maxReconnectAttempts??3}async health(){let e=f(this.#n,o),t=await this.#i(),n=await fetch(e,{headers:t});if(!n.ok){let e=await n.text();throw new l(n.status,e)}return await n.json()}session(e){let t;return t=typeof e==`string`?{continuationToken:e,streamIndex:0}:e||U(),new X({host:this.#n,maxReconnectAttempts:this.#r,resolveHeaders:e=>this.#i(e)},t)}async#i(e){let t=new Headers,n=await ee(this.#t);for(let[e,r]of Object.entries(n))t.set(e,r);if(e)for(let[n,r]of Object.entries(e))t.set(n,r);let r=await this.#a();return r&&t.set(`authorization`,r),t}async#a(){let e=this.#e;if(e){if(`bearer`in e){let t=(await $(e.bearer)).trim();return t.length===0?void 0:`Bearer ${t}`}if(`basic`in e){let t=await $(e.basic.password);return`Basic ${te(e.basic.username,t)}`}}}};async function $(e){return typeof e==`function`?e():e}async function ee(e){return e===void 0?{}:typeof e==`function`?await e():e}function te(e,t){let n=new TextEncoder().encode(`${e}:${t}`),r=Array.from(n,e=>String.fromCodePoint(e)).join(``);return btoa(r)}export{H as a,w as c,l as d,A as i,v as l,M as n,j as o,F as r,T as s,Q as t,g as u};
3
+ `)}}let e=r.trim();e.length>0&&(yield JSON.parse(e))}finally{t.releaseLock()}}function f(e,t,n){let r=t.startsWith(`/`)?t:`/${t}`,i=h(n);if(p(e)){let t=new URL(e);return t.pathname=`${m(t.pathname)}${r}`,t.search=i,t.hash=``,t.toString()}return`${m(e)}${r}${i}`}function p(e){return/^[a-z][a-z\d+\-.]*:/i.test(e)}function m(e){return e===`/`?``:e.endsWith(`/`)?e.slice(0,-1):e}function h(e){return!e||Object.keys(e).length===0?``:`?${new URLSearchParams(e).toString()}`}async function*g(e){let t=e.startIndex,n=e.maxReconnectAttempts;for(;;){let r=f(e.host,c(e.sessionId),t>0?{startIndex:String(t)}:void 0),i=await e.resolveHeaders(),a=await fetch(r,{headers:i,signal:e.signal??null});if(!a.ok){let e=await a.text();throw new l(a.status,e)}if(!a.body)throw new l(a.status,`Response body is null.`);let o=!1;try{for await(let e of d(a.body))t+=1,yield e}catch(e){if(!u(e))throw e;o=!0}if(!o||n<=0)return;--n}}var _=n(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},s=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},c=e=>s(n({},`__esModule`,{value:!0}),e),l={};o(l,{SYMBOL_FOR_REQ_CONTEXT:()=>u,getContext:()=>d}),t.exports=c(l);let u=Symbol.for(`@vercel/request-context`);function d(){return globalThis[u]?.get?.()??{}}})),v=n(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},s=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},c=e=>s(n({},`__esModule`,{value:!0}),e),l={};o(l,{VercelOidcTokenError:()=>u}),t.exports=c(l);var u=class extends Error{constructor(e,t){super(e),this.name=`VercelOidcTokenError`,this.cause=t}toString(){return this.cause?`${this.name}: ${this.message}: ${this.cause}`:`${this.name}: ${this.message}`}}})),y=n(((t,n)=>{var r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,s=(e,t)=>{for(var n in t)r(e,n,{get:t[n],enumerable:!0})},c=(e,t,n,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of a(t))!o.call(e,c)&&c!==n&&r(e,c,{get:()=>t[c],enumerable:!(s=i(t,c))||s.enumerable});return e},l=e=>c(r({},`__esModule`,{value:!0}),e),u={};s(u,{getVercelOidcToken:()=>p,getVercelOidcTokenSync:()=>m}),n.exports=l(u);var d=_(),f=v();async function p(t){let n=``,r;try{n=m()}catch(e){r=e}try{let[{getTokenPayload:r,isExpired:i},{refreshToken:a}]=await Promise.all([await Promise.resolve().then(()=>e(w())),await import(`./token-YW4VSeBB.js`).then(t=>e(t.default))]);(!n||i(r(n),t?.expirationBufferMs))&&(await a(t),n=m())}catch(e){let t=r instanceof Error?r.message:``;throw e instanceof Error&&(t=`${t}
4
+ ${e.message}`),t?new f.VercelOidcTokenError(t):e}return n}function m(){let e=(0,d.getContext)().headers?.[`x-vercel-oidc-token`]??process.env.VERCEL_OIDC_TOKEN;if(!e)throw Error(`The 'x-vercel-oidc-token' header is missing from the request. Do you have the OIDC option enabled in the Vercel project settings?`);return e}})),b=n(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},s=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},c=e=>s(n({},`__esModule`,{value:!0}),e),l={};o(l,{AccessTokenMissingError:()=>u,RefreshAccessTokenFailedError:()=>d}),t.exports=c(l);var u=class extends Error{constructor(){super(`No authentication found. Please log in with the Vercel CLI (vercel login).`),this.name=`AccessTokenMissingError`}},d=class extends Error{constructor(e){super(`Failed to refresh authentication token.`,{cause:e}),this.name=`RefreshAccessTokenFailedError`}}})),x=n(((e,n)=>{var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t)=>{for(var n in t)i(e,n,{get:t[n],enumerable:!0})},u=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let s of o(t))!c.call(e,s)&&s!==n&&i(e,s,{get:()=>t[s],enumerable:!(r=a(t,s))||r.enumerable});return e},d=(e,t,n)=>(n=e==null?{}:r(s(e)),u(t||!e||!e.__esModule?i(n,`default`,{value:e,enumerable:!0}):n,e)),f=e=>u(i({},`__esModule`,{value:!0}),e),p={};l(p,{findRootDir:()=>y,getUserDataDir:()=>b}),n.exports=f(p);var m=d(t(`path`)),h=d(t(`fs`)),g=d(t(`os`)),_=v();function y(){try{let e=process.cwd();for(;e!==m.default.dirname(e);){let t=m.default.join(e,`.vercel`);if(h.default.existsSync(t))return e;e=m.default.dirname(e)}}catch{throw new _.VercelOidcTokenError(`Token refresh only supported in node server environments`)}return null}function b(){if(process.env.XDG_DATA_HOME)return process.env.XDG_DATA_HOME;switch(g.default.platform()){case`darwin`:return m.default.join(g.default.homedir(),`Library/Application Support`);case`linux`:return m.default.join(g.default.homedir(),`.local/share`);case`win32`:return process.env.LOCALAPPDATA?process.env.LOCALAPPDATA:null;default:return null}}})),S=n(((e,n)=>{var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t)=>{for(var n in t)i(e,n,{get:t[n],enumerable:!0})},u=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let s of o(t))!c.call(e,s)&&s!==n&&i(e,s,{get:()=>t[s],enumerable:!(r=a(t,s))||r.enumerable});return e},d=(e,t,n)=>(n=e==null?{}:r(s(e)),u(t||!e||!e.__esModule?i(n,`default`,{value:e,enumerable:!0}):n,e)),f=e=>u(i({},`__esModule`,{value:!0}),e),p={};l(p,{isValidAccessToken:()=>b,readAuthConfig:()=>v,writeAuthConfig:()=>y}),n.exports=f(p);var m=d(t(`fs`)),h=d(t(`path`)),g=w();function _(){let e=(0,g.getVercelDataDir)();if(!e)throw Error(`Unable to find Vercel CLI data directory. Your platform: ${process.platform}. Supported: darwin, linux, win32.`);return h.join(e,`auth.json`)}function v(){try{let e=_();if(!m.existsSync(e))return null;let t=m.readFileSync(e,`utf8`);return t?JSON.parse(t):null}catch{return null}}function y(e){let t=_(),n=h.dirname(t);m.existsSync(n)||m.mkdirSync(n,{mode:504,recursive:!0}),m.writeFileSync(t,JSON.stringify(e,null,2),{mode:384})}function b(e,t=0){if(!e.token)return!1;if(typeof e.expiresAt!=`number`)return!0;let n=Math.floor(Date.now()/1e3),r=t/1e3;return e.expiresAt>=n+r}})),C=n(((e,n)=>{var r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,s=(e,t)=>{for(var n in t)r(e,n,{get:t[n],enumerable:!0})},c=(e,t,n,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of a(t))!o.call(e,c)&&c!==n&&r(e,c,{get:()=>t[c],enumerable:!(s=i(t,c))||s.enumerable});return e},l=e=>c(r({},`__esModule`,{value:!0}),e),u={};s(u,{processTokenResponse:()=>g,refreshTokenRequest:()=>h}),n.exports=l(u);var d=t(`os`);let f=`@vercel/oidc node-${process.version} ${(0,d.platform)()} (${(0,d.arch)()}) ${(0,d.hostname)()}`,p=null;async function m(){if(p)return p;let e=await fetch(`https://vercel.com/.well-known/openid-configuration`,{headers:{"user-agent":f}});if(!e.ok)throw Error(`Failed to discover OAuth endpoints`);let t=await e.json();if(!t||typeof t.token_endpoint!=`string`)throw Error(`Invalid OAuth discovery response`);let n=t.token_endpoint;return p=n,n}async function h(e){let t=await m();return await fetch(t,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`,"user-agent":f},body:new URLSearchParams({client_id:`cl_HYyOPBNtFMfHhaUn9L4QPfTZz6TP47bp`,grant_type:`refresh_token`,...e})})}async function g(e){let t=await e.json();if(!e.ok){let e=typeof t==`object`&&t&&`error`in t?String(t.error):`Token refresh failed`;return[Error(e)]}return typeof t!=`object`||!t?[Error(`Invalid token response`)]:typeof t.access_token==`string`?t.token_type===`Bearer`?typeof t.expires_in==`number`?[null,t]:[Error(`Missing expires_in in response`)]:[Error(`Invalid token_type in response`)]:[Error(`Missing access_token in response`)]}})),w=n(((e,n)=>{var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t)=>{for(var n in t)i(e,n,{get:t[n],enumerable:!0})},u=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let s of o(t))!c.call(e,s)&&s!==n&&i(e,s,{get:()=>t[s],enumerable:!(r=a(t,s))||r.enumerable});return e},d=(e,t,n)=>(n=e==null?{}:r(s(e)),u(t||!e||!e.__esModule?i(n,`default`,{value:e,enumerable:!0}):n,e)),f=e=>u(i({},`__esModule`,{value:!0}),e),p={};l(p,{assertVercelOidcTokenResponse:()=>k,findProjectInfo:()=>A,getTokenPayload:()=>N,getVercelDataDir:()=>E,getVercelOidcToken:()=>O,getVercelToken:()=>D,isExpired:()=>P,loadToken:()=>M,saveToken:()=>j}),n.exports=f(p);var m=d(t(`path`)),h=d(t(`fs`)),g=v(),_=x(),y=S(),w=C(),T=b();function E(){let e=(0,_.getUserDataDir)();return e?m.join(e,`com.vercel.cli`):null}async function D(e){let t=(0,y.readAuthConfig)();if(!t?.token)throw new T.AccessTokenMissingError;if((0,y.isValidAccessToken)(t,e?.expirationBufferMs))return t.token;if(!t.refreshToken)throw(0,y.writeAuthConfig)({}),new T.RefreshAccessTokenFailedError(`No refresh token available`);try{let e=await(0,w.refreshTokenRequest)({refresh_token:t.refreshToken}),[n,r]=await(0,w.processTokenResponse)(e);if(n||!r)throw(0,y.writeAuthConfig)({}),new T.RefreshAccessTokenFailedError(n);let i={token:r.access_token,expiresAt:Math.floor(Date.now()/1e3)+r.expires_in};return r.refresh_token&&(i.refreshToken=r.refresh_token),(0,y.writeAuthConfig)(i),i.token}catch(e){throw(0,y.writeAuthConfig)({}),e instanceof T.AccessTokenMissingError||e instanceof T.RefreshAccessTokenFailedError?e:new T.RefreshAccessTokenFailedError(e)}}async function O(e,t,n){let r=`https://api.vercel.com/v1/projects/${t}/token?source=vercel-oidc-refresh${n?`&teamId=${n}`:``}`,i=await fetch(r,{method:`POST`,headers:{Authorization:`Bearer ${e}`}});if(!i.ok)throw new g.VercelOidcTokenError(`Failed to refresh OIDC token: ${i.statusText}`);let a=await i.json();return k(a),a}function k(e){if(!e||typeof e!=`object`)throw TypeError("Vercel OIDC token is malformed. Expected an object. Please run `vc env pull` and try again");if(!(`token`in e)||typeof e.token!=`string`)throw TypeError("Vercel OIDC token is malformed. Expected a string-valued token property. Please run `vc env pull` and try again")}function A(){let e=(0,_.findRootDir)();if(!e)throw new g.VercelOidcTokenError("Unable to find project root directory. Have you linked your project with `vc link?`");let t=m.join(e,`.vercel`,`project.json`);if(!h.existsSync(t))throw new g.VercelOidcTokenError("project.json not found, have you linked your project with `vc link?`");let n=JSON.parse(h.readFileSync(t,`utf8`));if(typeof n.projectId!=`string`&&typeof n.orgId!=`string`)throw TypeError("Expected a string-valued projectId property. Try running `vc link` to re-link your project.");return{projectId:n.projectId,teamId:n.orgId}}function j(e,t){let n=(0,_.getUserDataDir)();if(!n)throw new g.VercelOidcTokenError(`Unable to find user data directory. Please reach out to Vercel support.`);let r=m.join(n,`com.vercel.token`,`${t}.json`),i=JSON.stringify(e);h.mkdirSync(m.dirname(r),{mode:504,recursive:!0}),h.writeFileSync(r,i),h.chmodSync(r,432)}function M(e){let t=(0,_.getUserDataDir)();if(!t)throw new g.VercelOidcTokenError(`Unable to find user data directory. Please reach out to Vercel support.`);let n=m.join(t,`com.vercel.token`,`${e}.json`);if(!h.existsSync(n))return null;let r=JSON.parse(h.readFileSync(n,`utf8`));return k(r),r}function N(e){let t=e.split(`.`);if(t.length!==3)throw new g.VercelOidcTokenError("Invalid token. Please run `vc env pull` and try again");let n=t[1].replace(/-/g,`+`).replace(/_/g,`/`),r=n.padEnd(n.length+(4-n.length%4)%4,`=`);return JSON.parse(Buffer.from(r,`base64`).toString(`utf8`))}function P(e,t=0){return e.exp*1e3<Date.now()+t}})),T=n(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},s=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},c=e=>s(n({},`__esModule`,{value:!0}),e),l={};o(l,{AccessTokenMissingError:()=>f.AccessTokenMissingError,RefreshAccessTokenFailedError:()=>f.RefreshAccessTokenFailedError,getContext:()=>d.getContext,getVercelOidcToken:()=>u.getVercelOidcToken,getVercelOidcTokenSync:()=>u.getVercelOidcTokenSync,getVercelToken:()=>p.getVercelToken}),t.exports=c(l);var u=y(),d=_(),f=b(),p=w()})),E=T();const D=`${a}/`,O=new Set([`localhost`,`127.0.0.1`,`0.0.0.0`,`::1`,`[::1]`]);function k(e){return O.has(e.hostname)}function A(e){try{return k(new URL(e))}catch{return!1}}async function j(){try{let e=(await(0,E.getVercelOidcToken)()).trim();if(e.length>0)return e}catch{}return process.env.VERCEL_OIDC_TOKEN?.trim()??``}const M=`x-vercel-protection-bypass`,N=`x-vercel-trusted-oidc-idp-token`;function P(e){return e.pathname.endsWith(`/ash/v1`)||e.pathname.includes(D)}async function F(e){let t=I(e),n=await R(t,e.resourceUrl);return n!==null&&L(t,n),t}function I(e){let t=new Headers(V(e.headers)),n=process.env.VERCEL_AUTOMATION_BYPASS_SECRET?.trim();return n&&P(e.resourceUrl)&&t.set(M,n),t}function L(e,t){e.has(`authorization`)||e.set(`authorization`,`Bearer ${t}`),e.set(N,t)}async function R(e,t){return z(t)?e.get(`x-vercel-oidc-token`)?.trim()||await B():null}function z(e){return!(!P(e)||k(e))}async function B(){let e=await j();return e.length>0?e:null}function V(e){if(e!==void 0)return e instanceof Headers?e:Array.isArray(e)?e.map(([e,t])=>[e,t]):e}async function H(e){let t={},n=process.env.VERCEL_AUTOMATION_BYPASS_SECRET?.trim();if(n&&(t[M]=n),!A(e.serverUrl)){let e=await j();e.length>0&&(t[N]=e)}return t}function U(){return{streamIndex:0}}function W(e){let t=q(e.events),n=e.session.streamIndex+e.events.length;return t?.type===`session.waiting`?{continuationToken:e.continuationToken??e.session.continuationToken,sessionId:e.sessionId,streamIndex:n}:U()}function G(e){let t;for(let n of e)J(n)&&(t=n.data.message??void 0);return t}function K(e){let t=q(e);return t?.type===`session.waiting`?`waiting`:t?.type===`session.failed`?`failed`:`completed`}function q(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(n!==void 0&&r(n))return n}}function J(e){return e.type===`message.completed`&&e.data.finishReason!==`tool-calls`}var Y=class{continuationToken;sessionId;#e=!1;#t;constructor(e){this.continuationToken=e.continuationToken,this.sessionId=e.sessionId,this.#t=e.createStream}async result(){let e=[];for await(let t of this)e.push(t);return{events:e,message:G(e),sessionId:this.sessionId,status:K(e)}}[Symbol.asyncIterator](){if(this.#e)throw Error(`MessageResponse has already been consumed.`);return this.#e=!0,this.#t()}},X=class{#e;#t;constructor(e,t){this.#e=e,this.#t=t}get state(){return this.#t}async sendMessage(e,t){return this.send({message:e},t)}async send(e,t){let n=this.#t,{continuationToken:r,sessionId:i}=await this.#n(e,n,t);return new Y({continuationToken:r,createStream:()=>this.#r(i,r,n,t),sessionId:i})}openStream(e){let t=this.#t.sessionId;if(!t)throw Error(`Session has no session ID. Send a message first.`);return g({host:this.#e.host,maxReconnectAttempts:this.#e.maxReconnectAttempts,resolveHeaders:()=>this.#e.resolveHeaders(),sessionId:t,signal:e?.signal,startIndex:e?.startIndex??this.#t.streamIndex})}async#n(e,t,n){let r=t.sessionId?s(t.sessionId):i,a=f(this.#e.host,r),o=await this.#e.resolveHeaders(n?.headers);o.set(`content-type`,`application/json`);let c=Z({input:e,session:t});if(c===null)throw Error(`Session.send requires a non-empty message, inputResponses, or both.`);let u=await fetch(a,{body:JSON.stringify(c),headers:o,method:`POST`,signal:n?.signal??null});if(!u.ok){let e=await u.text();throw new l(u.status,e)}let d=await u.json(),p=(typeof d.sessionId==`string`?d.sessionId:void 0)??u.headers.get(`x-ash-session-id`)?.trim()??t.sessionId;if(!p)throw Error(`Message route did not return a session id.`);return{continuationToken:typeof d.continuationToken==`string`?d.continuationToken:void 0,sessionId:p}}async*#r(e,t,n,i){let a=[];try{let t=n.sessionId===e?n.streamIndex:0,o=this.#e.maxReconnectAttempts;for(;;){let n=await this.#i(e,t,i?.signal),s=!1;try{for await(let e of d(n))if(a.push(e),t+=1,yield e,r(e)){s=!0;break}}catch(e){if(!u(e))throw e}if(s||o<=0)break;--o}}finally{this.#t=W({continuationToken:t,events:a,sessionId:e,session:n})}}async#i(e,t,n){let r=f(this.#e.host,c(e),t>0?{startIndex:String(t)}:void 0),i=await this.#e.resolveHeaders(),a=await fetch(r,{headers:i,signal:n??null});if(!a.ok){let e=await a.text();throw new l(a.status,e)}if(!a.body)throw new l(a.status,`Response body is null.`);return a.body}};function Z(e){let t={};return e.input.message!==void 0&&(t.message=e.input.message),e.input.inputResponses!==void 0&&e.input.inputResponses.length>0&&(t.inputResponses=e.input.inputResponses),e.input.clientContext!==void 0&&(t.clientContext=e.input.clientContext),e.session.continuationToken!==void 0&&(t.continuationToken=e.session.continuationToken),Object.keys(t).length===0||e.session.continuationToken===void 0&&t.message===void 0||e.session.continuationToken!==void 0&&t.message===void 0&&t.inputResponses===void 0?null:t}var Q=class{#e;#t;#n;#r;constructor(e){this.#n=e.host,this.#e=e.auth,this.#t=e.headers,this.#r=e.maxReconnectAttempts??3}async health(){let e=f(this.#n,o),t=await this.#i(),n=await fetch(e,{headers:t});if(!n.ok){let e=await n.text();throw new l(n.status,e)}return await n.json()}session(e){let t;return t=typeof e==`string`?{continuationToken:e,streamIndex:0}:e||U(),new X({host:this.#n,maxReconnectAttempts:this.#r,resolveHeaders:e=>this.#i(e)},t)}async#i(e){let t=new Headers,n=await ee(this.#t);for(let[e,r]of Object.entries(n))t.set(e,r);if(e)for(let[n,r]of Object.entries(e))t.set(n,r);let r=await this.#a();return r&&t.set(`authorization`,r),t}async#a(){let e=this.#e;if(e){if(`bearer`in e){let t=(await $(e.bearer)).trim();return t.length===0?void 0:`Bearer ${t}`}if(`basic`in e){let t=await $(e.basic.password);return`Basic ${te(e.basic.username,t)}`}}}};async function $(e){return typeof e==`function`?e():e}async function ee(e){return e===void 0?{}:typeof e==`function`?await e():e}function te(e,t){let n=new TextEncoder().encode(`${e}:${t}`),r=Array.from(n,e=>String.fromCodePoint(e)).join(``);return btoa(r)}export{H as a,w as c,l as d,A as i,v as l,M as n,j as o,F as r,T as s,Q as t,g as u};