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.
- package/CHANGELOG.md +12 -0
- package/bin/ash.d.ts +4 -4
- package/bin/ash.js +12 -8
- package/dist/docs/public/channels/README.md +26 -2
- package/dist/docs/public/channels/discord.md +159 -0
- package/dist/docs/public/channels/slack.md +14 -2
- package/dist/src/channel/routes.d.ts +6 -1
- package/dist/src/channel/send.js +5 -2
- package/dist/src/channel/session-callback.d.ts +10 -0
- package/dist/src/channel/session-callback.js +65 -0
- package/dist/src/channel/types.d.ts +19 -0
- package/dist/src/chunks/{client-BShLWzR6.js → client-ZqNLLMZB.js} +3 -3
- package/dist/src/chunks/{compile-agent-CyP6FrL8.js → compile-agent-DrIyb818.js} +1 -1
- package/dist/src/chunks/{dev-authored-source-watcher-DIWfVUsu.js → dev-authored-source-watcher-C1WUVv9F.js} +1 -1
- package/dist/src/chunks/host-CwAcCrg7.js +70 -0
- package/dist/src/chunks/paths-CWZN-XRX.js +85 -0
- package/dist/src/chunks/{token-BOkIxJeV.js → token-YW4VSeBB.js} +1 -1
- package/dist/src/chunks/types-BJSR0JNV.js +1 -0
- package/dist/src/cli/commands/channels.d.ts +15 -0
- package/dist/src/cli/commands/channels.js +9 -0
- package/dist/src/cli/commands/info.js +1 -1
- package/dist/src/cli/dev/repl.js +3 -3
- package/dist/src/cli/run.js +1 -1
- package/dist/src/client/message-reducer.js +6 -0
- package/dist/src/context/keys.d.ts +1 -1
- package/dist/src/context/keys.js +1 -1
- package/dist/src/context/seed-keys.d.ts +5 -1
- package/dist/src/context/seed-keys.js +4 -0
- package/dist/src/evals/cli/eval.js +1 -1
- package/dist/src/execution/await-authorization-orchestrator.js +1 -1
- package/dist/src/execution/node-step.js +13 -0
- package/dist/src/execution/remote-agent-dispatch.d.ts +15 -0
- package/dist/src/execution/remote-agent-dispatch.js +79 -0
- package/dist/src/execution/runtime-context.js +4 -1
- package/dist/src/execution/session-callback-step.d.ts +16 -0
- package/dist/src/execution/session-callback-step.js +72 -0
- package/dist/src/execution/subagent-invocation.d.ts +16 -0
- package/dist/src/execution/subagent-invocation.js +16 -0
- package/dist/src/execution/subagent-tool.js +5 -8
- package/dist/src/execution/workflow-entry.js +21 -1
- package/dist/src/execution/workflow-steps.d.ts +6 -1
- package/dist/src/execution/workflow-steps.js +76 -25
- package/dist/src/harness/execute-tool.d.ts +3 -3
- package/dist/src/harness/runtime-actions.d.ts +1 -0
- package/dist/src/harness/runtime-actions.js +18 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/process/pnpm.d.ts +28 -0
- package/dist/src/internal/process/pnpm.js +50 -0
- package/dist/src/protocol/message.d.ts +6 -0
- package/dist/src/protocol/message.js +1 -0
- package/dist/src/protocol/routes.d.ts +11 -0
- package/dist/src/protocol/routes.js +13 -0
- package/dist/src/public/channels/ash.js +25 -1
- package/dist/src/public/channels/discord/api.d.ts +99 -0
- package/dist/src/public/channels/discord/api.js +167 -0
- package/dist/src/public/channels/discord/defaults.d.ts +9 -0
- package/dist/src/public/channels/discord/defaults.js +74 -0
- package/dist/src/public/channels/discord/discordChannel.d.ts +132 -0
- package/dist/src/public/channels/discord/discordChannel.js +402 -0
- package/dist/src/public/channels/discord/hitl.d.ts +34 -0
- package/dist/src/public/channels/discord/hitl.js +194 -0
- package/dist/src/public/channels/discord/inbound.d.ts +97 -0
- package/dist/src/public/channels/discord/inbound.js +238 -0
- package/dist/src/public/channels/discord/index.d.ts +7 -0
- package/dist/src/public/channels/discord/index.js +6 -0
- package/dist/src/public/channels/discord/responses.d.ts +11 -0
- package/dist/src/public/channels/discord/responses.js +40 -0
- package/dist/src/public/channels/discord/verify.d.ts +38 -0
- package/dist/src/public/channels/discord/verify.js +72 -0
- package/dist/src/public/channels/discord/verifyInbound.d.ts +6 -0
- package/dist/src/public/channels/discord/verifyInbound.js +19 -0
- package/dist/src/public/channels/slack/constants.d.ts +7 -0
- package/dist/src/public/channels/slack/constants.js +7 -0
- package/dist/src/public/channels/slack/slackChannel.js +2 -1
- package/dist/src/runtime/actions/keys.js +2 -0
- package/dist/src/runtime/actions/types.d.ts +47 -1
- package/dist/src/runtime/actions/types.js +23 -0
- package/dist/src/runtime/connections/callback-route.d.ts +1 -1
- package/dist/src/runtime/connections/callback-route.js +1 -1
- package/dist/src/runtime/connections/mcp-client.d.ts +1 -2
- package/dist/src/runtime/connections/mcp-client.js +69 -3
- package/dist/src/runtime/framework-channels/index.js +7 -2
- package/dist/src/runtime/session-callback-route.d.ts +6 -0
- package/dist/src/runtime/session-callback-route.js +87 -0
- package/package.json +9 -3
- package/dist/src/chunks/host-BxT35q6K.js +0 -70
- package/dist/src/chunks/paths-B2hLA0Fn.js +0 -85
- 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
|
|
8
|
+
* Absolute path to the ash package root.
|
|
9
9
|
*/
|
|
10
|
-
|
|
10
|
+
packageRoot?: string;
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Absolute
|
|
13
|
+
* Absolute paths to scripts that run after workspace bootstrap compilation.
|
|
14
14
|
*/
|
|
15
|
-
|
|
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({
|
|
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
|
-
|
|
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
|
-
|
|
214
|
-
|
|
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;
|
package/dist/src/channel/send.js
CHANGED
|
@@ -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
|
|
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{
|
|
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
|
|
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};
|