experimental-ash 0.62.0 → 0.64.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 +24 -0
- package/dist/docs/public/advanced/auth-and-route-protection.mdx +26 -20
- package/dist/docs/public/advanced/hooks.mdx +8 -2
- package/dist/docs/public/advanced/runs-and-streaming.md +6 -3
- package/dist/docs/public/advanced/typescript-api.md +32 -0
- package/dist/docs/public/channels/ash.mdx +5 -1
- package/dist/docs/public/channels/custom.mdx +23 -0
- package/dist/docs/public/frontend/README.md +8 -4
- package/dist/docs/public/frontend/meta.json +9 -1
- package/dist/docs/public/frontend/nextjs.md +4 -4
- package/dist/docs/public/frontend/nuxt.md +168 -0
- package/dist/docs/public/frontend/sveltekit.md +177 -0
- package/dist/docs/public/frontend/use-ash-agent-svelte.md +185 -0
- package/dist/docs/public/frontend/use-ash-agent-vue.md +236 -0
- package/dist/docs/public/frontend/use-ash-agent.md +14 -14
- package/dist/docs/public/getting-started.mdx +2 -0
- package/dist/src/channel/websocket-upgrade-server.d.ts +26 -0
- package/dist/src/channel/websocket-upgrade-server.js +1 -0
- package/dist/src/chunks/use-ash-agent-DzoSHUCb.js +1197 -0
- package/dist/src/chunks/use-ash-agent-KtjpWd5l.js +1229 -0
- package/dist/src/client/ash-agent-store.d.ts +61 -0
- package/dist/src/client/ash-agent-store.js +2 -0
- package/dist/src/client/client-error.js +1 -1
- package/dist/src/client/index.d.ts +2 -0
- package/dist/src/client/index.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +3 -3
- package/dist/src/compiled/@chat-adapter/slack/index.js +25 -25
- package/dist/src/compiled/@workflow/core/events-consumer.d.ts +8 -0
- package/dist/src/compiled/@workflow/core/index.js +2 -2
- package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +1 -0
- package/dist/src/compiled/@workflow/core/runtime.js +29 -29
- package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/@workflow/errors/error-codes.d.ts +2 -0
- package/dist/src/compiled/@workflow/errors/index.d.ts +14 -0
- package/dist/src/compiled/@workflow/errors/index.js +1 -1
- package/dist/src/compiled/@workflow/world/queue.d.ts +8 -0
- package/dist/src/compiled/_chunks/workflow/dist-zpK2YVVA.js +3 -0
- package/dist/src/compiled/_chunks/workflow/resume-hook-BFK9mgsb.js +12 -0
- package/dist/src/compiled/_chunks/workflow/{sleep-Bg0t23kF.js → sleep-CeJckNg2.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{symbols-u476uwyR.js → symbols-BWCAoPHE.js} +1 -1
- package/dist/src/internal/application/package.d.ts +1 -0
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/host/build-application.js +1 -1
- package/dist/src/internal/nitro/host/channel-routes.js +2 -2
- package/dist/src/internal/workflow-bundle/ash-service-route-output.js +11 -1
- package/dist/src/packages/ash-scaffold/src/channels.js +1 -1
- package/dist/src/packages/ash-scaffold/src/web-template.js +5 -16
- package/dist/src/public/channels/auth.d.ts +45 -3
- package/dist/src/public/channels/auth.js +1 -1
- package/dist/src/public/channels/index.d.ts +1 -0
- package/dist/src/public/channels/index.js +1 -1
- package/dist/src/public/channels/slack/inbound.d.ts +3 -1
- package/dist/src/public/channels/slack/inbound.js +1 -1
- package/dist/src/public/nuxt/dev-server.d.ts +24 -0
- package/dist/src/public/nuxt/dev-server.js +1 -0
- package/dist/src/public/nuxt/index.d.ts +1 -0
- package/dist/src/public/nuxt/index.js +1 -0
- package/dist/src/public/nuxt/module.d.ts +31 -0
- package/dist/src/public/nuxt/module.js +1 -0
- package/dist/src/public/nuxt/routing.d.ts +55 -0
- package/dist/src/public/nuxt/routing.js +1 -0
- package/dist/src/public/nuxt/vercel-json.d.ts +17 -0
- package/dist/src/public/nuxt/vercel-json.js +1 -0
- package/dist/src/public/sveltekit/dev-server.d.ts +24 -0
- package/dist/src/public/sveltekit/dev-server.js +1 -0
- package/dist/src/public/sveltekit/index.d.ts +39 -0
- package/dist/src/public/sveltekit/index.js +1 -0
- package/dist/src/public/sveltekit/routing.d.ts +32 -0
- package/dist/src/public/sveltekit/routing.js +1 -0
- package/dist/src/public/sveltekit/vercel-json.d.ts +17 -0
- package/dist/src/public/sveltekit/vercel-json.js +1 -0
- package/dist/src/react/use-ash-agent.d.ts +5 -27
- package/dist/src/react/use-ash-agent.js +1 -2
- package/dist/src/svelte/index.d.ts +3 -0
- package/dist/src/svelte/index.js +3 -0
- package/dist/src/svelte/use-ash-agent.d.ts +80 -0
- package/dist/src/svelte/use-ash-agent.js +3 -0
- package/dist/src/vue/index.d.ts +3 -0
- package/dist/src/vue/index.js +3 -0
- package/dist/src/vue/use-ash-agent.d.ts +78 -0
- package/dist/src/vue/use-ash-agent.js +3 -0
- package/package.json +51 -6
- package/dist/src/compiled/_chunks/workflow/dist-C4EHshZE.js +0 -3
- package/dist/src/compiled/_chunks/workflow/resume-hook-BlALLgSA.js +0 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# experimental-ash
|
|
2
2
|
|
|
3
|
+
## 0.64.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 76d7a1f: Add `placeholderAuth()` for scaffolded Web Chat channels so production requests return a structured 401 when app auth has not been configured. Generated apps now show setup guidance instead of an internal channel failure, and `ClientError` surfaces structured Ash error messages directly.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 030c0d1: Fix Slack direct messages dropping file uploads. `onDirectMessage` now receives `file_share` messages with their attachments intact, matching the existing `onAppMention` behavior; system subtypes (edits, deletes, joins) and bot-authored echoes are still filtered.
|
|
12
|
+
|
|
13
|
+
## 0.63.0
|
|
14
|
+
|
|
15
|
+
### Minor Changes
|
|
16
|
+
|
|
17
|
+
- 524cae7: Add `createWebSocketUpgradeServer()` as an escape hatch for `WS()` routes that need to adapt SDKs or frameworks which bind directly to Node `http.Server` upgrade events.
|
|
18
|
+
- a491826: Add Svelte 5 and SvelteKit integrations, including a `useAshAgent` binding, a SvelteKit Vite plugin for Ash route proxying, Vercel services configuration, docs, tests, and an example app.
|
|
19
|
+
- a491826: Add Vue composable (`useAshAgent`) and Nuxt module (`experimental-ash/nuxt`) for building agent UIs with Vue and Nuxt. The shared `AshAgentStore` class is now exported from `experimental-ash/client` for framework-agnostic consumption.
|
|
20
|
+
|
|
21
|
+
## 0.62.1
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- d141e9e: Update `@workflow/*` dependencies to the latest beta: `@workflow/core` 5.0.0-beta.12, `@workflow/errors` 5.0.0-beta.7, `@workflow/world` 5.0.0-beta.7, and `@workflow/world-local` 5.0.0-beta.13.
|
|
26
|
+
|
|
3
27
|
## 0.62.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
|
@@ -18,13 +18,13 @@ These settings apply to:
|
|
|
18
18
|
- `POST /ash/v1/session/:sessionId`
|
|
19
19
|
- `GET /ash/v1/session/:sessionId/stream`
|
|
20
20
|
|
|
21
|
-
<CopyPrompt text="Protect the user's Ash HTTP routes through the channel layer. In Ash, route auth and IP policy live on channel factories, usually agent/channels/ash.ts with ashChannel auth config, not in agent.ts. Inspect the existing channel file and app auth code, replace any generated
|
|
21
|
+
<CopyPrompt text="Protect the user's Ash HTTP routes through the channel layer. In Ash, route auth and IP policy live on channel factories, usually agent/channels/ash.ts with ashChannel auth config, not in agent.ts. Inspect the existing channel file and app auth code, replace any generated placeholderAuth guardrail with the smallest AuthFn or helper composition, use helpers such as localDev, vercelOidc, none, httpBasic, jwtHmac, jwtEcdsa, or oidc as appropriate, keep secrets in environment variables, preserve localDev and vercelOidc behavior where useful, verify unauthenticated production browser requests are rejected with 401, and do not commit unless the user asks.">
|
|
22
22
|
Protect the user's Ash HTTP routes through the channel layer. In Ash, route auth and IP policy
|
|
23
23
|
live on channel factories, usually agent/channels/ash.ts with ashChannel auth config, not in
|
|
24
24
|
agent.ts. Inspect the existing channel file and app auth code, replace any generated
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
placeholderAuth guardrail with the smallest AuthFn or helper composition, use helpers such as
|
|
26
|
+
localDev, vercelOidc, none, httpBasic, jwtHmac, jwtEcdsa, or oidc as appropriate, keep secrets in
|
|
27
|
+
environment variables, preserve localDev and vercelOidc behavior where useful, verify
|
|
28
28
|
unauthenticated production browser requests are rejected with 401, and do not commit unless the
|
|
29
29
|
user asks.
|
|
30
30
|
</CopyPrompt>
|
|
@@ -32,31 +32,24 @@ These settings apply to:
|
|
|
32
32
|
## Generated Web Chat Auth
|
|
33
33
|
|
|
34
34
|
`pnpm create experimental-ash-agent` scaffolds `agent/channels/ash.ts` from the Web Chat example.
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
It permits Vercel OIDC and localhost requests, but it will not allow browser requests in
|
|
36
|
+
production until you replace the placeholder with your app's auth:
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
39
|
// agent/channels/ash.ts
|
|
40
40
|
import { ashChannel } from "experimental-ash/channels/ash";
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
function exampleProductionAuth(): AuthFn<Request> {
|
|
44
|
-
return () => {
|
|
45
|
-
if (process.env.VERCEL_ENV === "production") {
|
|
46
|
-
throw new Error("Configure production auth in agent/channels/ash.ts.");
|
|
47
|
-
}
|
|
48
|
-
return null;
|
|
49
|
-
};
|
|
50
|
-
}
|
|
41
|
+
import { localDev, placeholderAuth, vercelOidc } from "experimental-ash/channels/auth";
|
|
51
42
|
|
|
52
43
|
export default ashChannel({
|
|
53
|
-
auth: [
|
|
44
|
+
auth: [localDev(), vercelOidc(), placeholderAuth()],
|
|
54
45
|
});
|
|
55
46
|
```
|
|
56
47
|
|
|
57
|
-
Replace `
|
|
58
|
-
|
|
59
|
-
|
|
48
|
+
Replace `placeholderAuth()` before a browser user submits a production request. It returns a
|
|
49
|
+
structured 401 in production so generated Web Chat apps can explain that auth is not configured
|
|
50
|
+
instead of showing an internal channel error. If you delete the authored file, Ash falls back to
|
|
51
|
+
its framework default `[localDev(), vercelOidc()]`; that default also does not accept browser
|
|
52
|
+
traffic in production.
|
|
60
53
|
|
|
61
54
|
## Walking The Auth Array
|
|
62
55
|
|
|
@@ -68,6 +61,19 @@ that default also does not accept browser-user traffic in production.
|
|
|
68
61
|
If every entry skips, the request is rejected with `401`. An empty array `auth: []` therefore
|
|
69
62
|
rejects every request.
|
|
70
63
|
|
|
64
|
+
To reject with a specific `401`, throw an `UnauthenticatedError`. To reject with a specific `403`,
|
|
65
|
+
throw a `ForbiddenError`. `routeAuth` turns those errors into HTTP responses; other thrown errors
|
|
66
|
+
still use the normal channel failure path.
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { UnauthenticatedError } from "experimental-ash/channels/auth";
|
|
70
|
+
|
|
71
|
+
throw new UnauthenticatedError({
|
|
72
|
+
code: "authentication_required",
|
|
73
|
+
message: "Sign in to continue.",
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
71
77
|
To accept anonymous traffic, include `none()` as the final entry:
|
|
72
78
|
|
|
73
79
|
```ts
|
|
@@ -6,8 +6,10 @@ url: /hooks
|
|
|
6
6
|
|
|
7
7
|
Hooks are Ash's authored extension points for the runtime event stream.
|
|
8
8
|
|
|
9
|
-
This page is about `agent/hooks/*.ts` runtime hooks. For the
|
|
10
|
-
see [`useAshAgent`](../frontend/use-ash-agent.md)
|
|
9
|
+
This page is about `agent/hooks/*.ts` runtime hooks. For the client-side hook,
|
|
10
|
+
see [`useAshAgent`](../frontend/use-ash-agent.md) (React) or
|
|
11
|
+
[`useAshAgent` (Vue)](../frontend/use-ash-agent-vue.md) or
|
|
12
|
+
[`useAshAgent` (Svelte)](../frontend/use-ash-agent-svelte.md).
|
|
11
13
|
|
|
12
14
|
Use a hook when you want to observe stream events (audit, metrics,
|
|
13
15
|
alerting) without writing a tool, a context provider, or a channel
|
|
@@ -188,7 +190,11 @@ when both are registered.
|
|
|
188
190
|
## What to read next
|
|
189
191
|
|
|
190
192
|
- [`useAshAgent`](../frontend/use-ash-agent.md)
|
|
193
|
+
- [`useAshAgent` (Vue)](../frontend/use-ash-agent-vue.md)
|
|
194
|
+
- [`useAshAgent` (Svelte)](../frontend/use-ash-agent-svelte.md)
|
|
191
195
|
- [Next.js](../frontend/nextjs.md)
|
|
196
|
+
- [Nuxt](../frontend/nuxt.md)
|
|
197
|
+
- [SvelteKit](../frontend/sveltekit.md)
|
|
192
198
|
- [Tools](./tools.mdx)
|
|
193
199
|
- [Context Control](./context-control.md)
|
|
194
200
|
- [Sessions And Streaming](./runs-and-streaming.md)
|
|
@@ -13,9 +13,10 @@ The key client model is:
|
|
|
13
13
|
- `POST /ash/v1/session/:sessionId` sends a follow-up message
|
|
14
14
|
- `GET /ash/v1/session/:sessionId/stream` lets you watch the session in real time
|
|
15
15
|
|
|
16
|
-
React apps can use [`useAshAgent()`](../frontend/use-ash-agent.md)
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
React apps can use [`useAshAgent()`](../frontend/use-ash-agent.md) and Vue apps can use
|
|
17
|
+
[`useAshAgent()` (Vue)](../frontend/use-ash-agent-vue.md) instead of calling these routes
|
|
18
|
+
directly. [Next.js](../frontend/nextjs.md) and [Nuxt](../frontend/nuxt.md) apps can proxy
|
|
19
|
+
these routes to the Ash runtime from the same origin.
|
|
19
20
|
|
|
20
21
|
Ash keeps those separate on purpose:
|
|
21
22
|
|
|
@@ -127,7 +128,9 @@ channel has already updated its state and the projection is current.
|
|
|
127
128
|
## What To Read Next
|
|
128
129
|
|
|
129
130
|
- [`useAshAgent`](../frontend/use-ash-agent.md)
|
|
131
|
+
- [`useAshAgent` (Vue)](../frontend/use-ash-agent-vue.md)
|
|
130
132
|
- [Next.js](../frontend/nextjs.md)
|
|
133
|
+
- [Nuxt](../frontend/nuxt.md)
|
|
131
134
|
- [Session Context](./session-context.md)
|
|
132
135
|
- [Subagents](./subagents.mdx)
|
|
133
136
|
- [Schedules](./schedules.mdx)
|
|
@@ -18,6 +18,10 @@ Source of truth:
|
|
|
18
18
|
- React subpath: [`../../packages/ash/src/react/index.ts`](../../packages/ash/src/react/index.ts)
|
|
19
19
|
- client subpath: [`../../packages/ash/src/client/index.ts`](../../packages/ash/src/client/index.ts)
|
|
20
20
|
- evals subpath: [`../../packages/ash/src/evals/index.ts`](../../packages/ash/src/evals/index.ts)
|
|
21
|
+
- vue subpath: [`../../packages/ash/src/vue/index.ts`](../../packages/ash/src/vue/index.ts)
|
|
22
|
+
- nuxt subpath: [`../../packages/ash/src/public/nuxt/index.ts`](../../packages/ash/src/public/nuxt/index.ts)
|
|
23
|
+
- svelte subpath: [`../../packages/ash/src/svelte/index.ts`](../../packages/ash/src/svelte/index.ts)
|
|
24
|
+
- SvelteKit subpath: [`../../packages/ash/src/public/sveltekit/index.ts`](../../packages/ash/src/public/sveltekit/index.ts)
|
|
21
25
|
|
|
22
26
|
## Definition Helpers
|
|
23
27
|
|
|
@@ -85,6 +89,32 @@ React helpers exported from `experimental-ash/react`:
|
|
|
85
89
|
- `UseAshAgentOptions`, `UseAshAgentHelpers`, `UseAshAgentSnapshot`, `UseAshAgentStatus` - hook configuration and state types
|
|
86
90
|
- `AshMessageData`, `AshMessage`, `AshMessagePart`, `AshDynamicToolPart` - default message projection types
|
|
87
91
|
|
|
92
|
+
Nuxt helpers exported from `experimental-ash/nuxt`:
|
|
93
|
+
|
|
94
|
+
- `default` - the Nuxt module that runs the Ash agent alongside your Nuxt app
|
|
95
|
+
- `ASH_NUXT_SERVICE_PREFIX` - default private Vercel service prefix for the Ash service
|
|
96
|
+
- `AshNuxtModuleOptions` - options for `ashRoot`, `ashBuildCommand`, `configureVercelJson`, and `servicePrefix`
|
|
97
|
+
|
|
98
|
+
Vue helpers exported from `experimental-ash/vue`:
|
|
99
|
+
|
|
100
|
+
- `useAshAgent(options?)` - Vue composable for sending turns, streaming events, projecting reactive UI state, and tracking a session cursor
|
|
101
|
+
- `defaultMessageReducer()` - default chat-style event projection used by `useAshAgent()`
|
|
102
|
+
- `UseAshAgentOptions`, `UseAshAgentReturn`, `UseAshAgentSnapshot`, `UseAshAgentStatus`, `PrepareSend` - composable configuration and state types
|
|
103
|
+
- `AshAgentReducer`, `AshMessageData`, `AshMessage`, `AshMessagePart`, `AshDynamicToolPart` - reducer and default message projection types
|
|
104
|
+
|
|
105
|
+
SvelteKit helpers exported from `experimental-ash/sveltekit`:
|
|
106
|
+
|
|
107
|
+
- `ashSvelteKit(options?)` - Vite plugin that runs the Ash agent alongside your SvelteKit app
|
|
108
|
+
- `ASH_SVELTEKIT_SERVICE_PREFIX` - default private Vercel service prefix for the Ash service
|
|
109
|
+
- `AshSvelteKitPluginOptions` - options for `ashRoot`, `ashBuildCommand`, `configureVercelJson`, and `servicePrefix`
|
|
110
|
+
|
|
111
|
+
Svelte helpers exported from `experimental-ash/svelte`:
|
|
112
|
+
|
|
113
|
+
- `useAshAgent(options?)` - Svelte 5 binding for sending turns, streaming events, projecting rune-friendly UI state, and tracking a session cursor
|
|
114
|
+
- `defaultMessageReducer()` - default chat-style event projection used by `useAshAgent()`
|
|
115
|
+
- `UseAshAgentOptions`, `UseAshAgentReturn`, `UseAshAgentSnapshot`, `UseAshAgentStatus`, `PrepareSend` - binding configuration and state types
|
|
116
|
+
- `AshAgentReducer`, `AshMessageData`, `AshMessage`, `AshMessagePart`, `AshDynamicToolPart` - reducer and default message projection types
|
|
117
|
+
|
|
88
118
|
Client helpers exported from `experimental-ash/client`:
|
|
89
119
|
|
|
90
120
|
- `Client` - HTTP client for an Ash server
|
|
@@ -321,6 +351,8 @@ import { Braintrust } from "experimental-ash/evals/reporters";
|
|
|
321
351
|
- `ctx.session` -> [Session Context](./session-context.md)
|
|
322
352
|
- `withAsh` -> [Next.js](../frontend/nextjs.md)
|
|
323
353
|
- `useAshAgent` -> [`useAshAgent`](../frontend/use-ash-agent.md)
|
|
354
|
+
- `useAshAgent` (Vue) and `defaultMessageReducer` -> [`useAshAgent` (Vue)](../frontend/use-ash-agent-vue.md)
|
|
355
|
+
- Nuxt module (`experimental-ash/nuxt`) -> [Nuxt](../frontend/nuxt.md)
|
|
324
356
|
- subagents (authored with `defineAgent` under `subagents/<id>/agent.ts`) -> [Subagents](./subagents.mdx)
|
|
325
357
|
- `defineSchedule` -> [Schedules](./schedules.mdx)
|
|
326
358
|
- `defineEvalSuite`, loaders, reporters, and scorers -> [Evals](./evals.mdx)
|
|
@@ -58,7 +58,11 @@ wire the Ash channel to your app's auth system, such as Clerk, Auth.js, or your
|
|
|
58
58
|
verification.
|
|
59
59
|
|
|
60
60
|
`pnpm create experimental-ash-agent` scaffolds an example `agent/channels/ash.ts` with a production
|
|
61
|
-
auth placeholder so you can replace it before exposing the API to real users.
|
|
61
|
+
auth placeholder so you can replace it before exposing the API to real users. The generated channel
|
|
62
|
+
permits Vercel OIDC and localhost requests and includes `placeholderAuth()`, which returns a
|
|
63
|
+
setup-focused 401 in production until you replace it with your app's auth. If you delete the
|
|
64
|
+
authored file, Ash falls back to `[localDev(), vercelOidc()]`; that default does not admit browser
|
|
65
|
+
users in production.
|
|
62
66
|
|
|
63
67
|
For the full auth model and helper list, see
|
|
64
68
|
[Auth and Route Protection](/docs/auth-and-route-protection).
|
|
@@ -89,6 +89,29 @@ export default defineChannel({
|
|
|
89
89
|
`params`, `waitUntil`, and `requestIp`. The returned hooks are Ash-owned structural types compatible
|
|
90
90
|
with Nitro/H3 websocket routing, including `upgrade`, `open`, `message`, `close`, and `error`.
|
|
91
91
|
|
|
92
|
+
### Node upgrade server escape hatch
|
|
93
|
+
|
|
94
|
+
Prefer the `WS()` lifecycle hooks above when you own the websocket behavior. Ash also exposes
|
|
95
|
+
`createWebSocketUpgradeServer()` for the narrower case where a third-party SDK or framework expects
|
|
96
|
+
to bind directly to a Node `http.Server` with `server.on("upgrade", ...)`.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import { defineChannel, WS, createWebSocketUpgradeServer } from "experimental-ash/channels";
|
|
100
|
+
|
|
101
|
+
const bridge = createWebSocketUpgradeServer();
|
|
102
|
+
|
|
103
|
+
thirdPartySdk.attach(bridge.server);
|
|
104
|
+
|
|
105
|
+
export default defineChannel({
|
|
106
|
+
routes: [WS("/vendor/ws", bridge.route)],
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The bridge server does not listen on its own port. It receives only upgrade events that matched the
|
|
111
|
+
Ash route, and only on hosts where Nitro exposes the raw Node upgrade request, socket, and head. Treat
|
|
112
|
+
it as a compatibility adapter for libraries with server-binding APIs, not as the primary way to build
|
|
113
|
+
websocket channels in Ash.
|
|
114
|
+
|
|
92
115
|
## Cross-channel hand-off
|
|
93
116
|
|
|
94
117
|
Route handlers can start a session on a different channel via `args.receive(channel, ...)`. Use this
|
|
@@ -4,13 +4,17 @@ description: "Wire your web app to an Ash agent."
|
|
|
4
4
|
url: /frontend
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Ash ships first-class helpers for the
|
|
7
|
+
Ash ships first-class helpers for the most common ways to put an agent
|
|
8
8
|
behind a web UI:
|
|
9
9
|
|
|
10
10
|
- [Next.js](./nextjs.md) — `withAsh()` runs the Ash agent alongside your
|
|
11
11
|
Next.js app.
|
|
12
|
-
- [
|
|
13
|
-
|
|
12
|
+
- [Nuxt](./nuxt.md) — `experimental-ash/nuxt` module runs the Ash agent
|
|
13
|
+
alongside your Nuxt app.
|
|
14
|
+
- [`useAshAgent` (React)](./use-ash-agent.md) — React hook for chat and agent
|
|
15
|
+
UIs in any React app.
|
|
16
|
+
- [`useAshAgent` (Vue)](./use-ash-agent-vue.md) — Vue composable for chat and
|
|
17
|
+
agent UIs in any Vue app.
|
|
14
18
|
|
|
15
19
|
For other stacks, call Ash directly over its HTTP routes —
|
|
16
|
-
see [Sessions And Streaming](../runs-and-streaming.md).
|
|
20
|
+
see [Sessions And Streaming](../advanced/runs-and-streaming.md).
|
|
@@ -198,11 +198,11 @@ next call only). See [`useAshAgent`](./use-ash-agent.md#add-per-turn-client-cont
|
|
|
198
198
|
for the full pattern.
|
|
199
199
|
|
|
200
200
|
For server-side enrichment (policy, durable context, dynamic skills), use
|
|
201
|
-
runtime lifecycle hooks instead. See [Hooks](../hooks.
|
|
201
|
+
runtime lifecycle hooks instead. See [Hooks](../advanced/hooks.mdx).
|
|
202
202
|
|
|
203
203
|
## What To Read Next
|
|
204
204
|
|
|
205
205
|
- [`useAshAgent`](./use-ash-agent.md)
|
|
206
|
-
- [Auth And Route Protection](../auth-and-route-protection.
|
|
207
|
-
- [Hooks](../hooks.
|
|
208
|
-
- [Sessions And Streaming](../runs-and-streaming.md)
|
|
206
|
+
- [Auth And Route Protection](../advanced/auth-and-route-protection.mdx)
|
|
207
|
+
- [Hooks](../advanced/hooks.mdx)
|
|
208
|
+
- [Sessions And Streaming](../advanced/runs-and-streaming.md)
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Nuxt"
|
|
3
|
+
description: "Add an Ash agent to a Nuxt app and call it from the browser."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`experimental-ash/nuxt` lets you ship a Nuxt frontend and an Ash agent as
|
|
7
|
+
one project. Come in from either side: drop it into an existing Nuxt app
|
|
8
|
+
to add an agent, or start with an agent and point a Nuxt project at it.
|
|
9
|
+
|
|
10
|
+
- **One dev server.** `nuxt dev` runs the app and the agent together.
|
|
11
|
+
- **One deploy.** Vercel ships them as a single project; no extra service to operate.
|
|
12
|
+
- **Zero URL plumbing.** `useAshAgent()` finds the mounted routes automatically; no CORS, no env vars.
|
|
13
|
+
|
|
14
|
+
## Add Ash To Nuxt
|
|
15
|
+
|
|
16
|
+
Register the module in your Nuxt config:
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
// nuxt.config.ts
|
|
20
|
+
export default defineNuxtConfig({
|
|
21
|
+
modules: ["experimental-ash/nuxt"],
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
By default, the module looks for an `agent/` folder inside your Nuxt
|
|
26
|
+
project root. Pass `ashRoot` when the agent lives somewhere else:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
export default defineNuxtConfig({
|
|
30
|
+
modules: ["experimental-ash/nuxt"],
|
|
31
|
+
ash: {
|
|
32
|
+
ashRoot: "../my-agent",
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Add The Ash Channel
|
|
38
|
+
|
|
39
|
+
Skip this section if the framework default channel works for you. The module
|
|
40
|
+
already wires Ash up without it.
|
|
41
|
+
|
|
42
|
+
Create `agent/channels/ash.ts` when you want to choose the route auth policy
|
|
43
|
+
explicitly:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// agent/channels/ash.ts
|
|
47
|
+
import { ashChannel } from "experimental-ash/channels/ash";
|
|
48
|
+
import { none } from "experimental-ash/channels/auth";
|
|
49
|
+
|
|
50
|
+
export default ashChannel({
|
|
51
|
+
auth: none(),
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
For protected apps, replace `none()` with a channel auth helper such as
|
|
56
|
+
`vercelOidc()`, `oidc(...)`, or `httpBasic(...)`.
|
|
57
|
+
|
|
58
|
+
## Use The Vue Composable
|
|
59
|
+
|
|
60
|
+
Once the module is in `nuxt.config.ts`, browser code can use
|
|
61
|
+
[`useAshAgent()`](./use-ash-agent-vue.md) without a custom host. The module
|
|
62
|
+
auto-imports the composable, so no explicit import is needed:
|
|
63
|
+
|
|
64
|
+
```vue
|
|
65
|
+
<script setup lang="ts">
|
|
66
|
+
const { status, sendMessage } = useAshAgent();
|
|
67
|
+
|
|
68
|
+
const isBusy = computed(() => status.value === "submitted" || status.value === "streaming");
|
|
69
|
+
|
|
70
|
+
const message = ref("");
|
|
71
|
+
|
|
72
|
+
async function handleSubmit() {
|
|
73
|
+
const text = message.value.trim();
|
|
74
|
+
if (!text || isBusy.value) return;
|
|
75
|
+
message.value = "";
|
|
76
|
+
await sendMessage(text);
|
|
77
|
+
}
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<template>
|
|
81
|
+
<form @submit.prevent="handleSubmit">
|
|
82
|
+
<input v-model="message" :disabled="isBusy" />
|
|
83
|
+
<button type="submit" :disabled="isBusy">Send</button>
|
|
84
|
+
</form>
|
|
85
|
+
</template>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The composable handles conversation state, streaming updates, errors, and
|
|
89
|
+
messages for you. See [`useAshAgent` (Vue)](./use-ash-agent-vue.md) for the
|
|
90
|
+
full API.
|
|
91
|
+
|
|
92
|
+
## Local Development
|
|
93
|
+
|
|
94
|
+
`pnpm dev` is enough. The module boots the Ash dev server alongside Nuxt
|
|
95
|
+
and proxies the Ash routes to it, so your browser keeps talking to the
|
|
96
|
+
Nuxt origin.
|
|
97
|
+
|
|
98
|
+
## Vercel Deployments
|
|
99
|
+
|
|
100
|
+
On Vercel, the module keeps the web app public and the Ash runtime tucked
|
|
101
|
+
behind it. Users visit the Nuxt app, and the browser talks to the agent
|
|
102
|
+
through the same site origin.
|
|
103
|
+
|
|
104
|
+
Use `ashBuildCommand` when the agent needs a project-specific build command:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
export default defineNuxtConfig({
|
|
108
|
+
modules: ["experimental-ash/nuxt"],
|
|
109
|
+
ash: {
|
|
110
|
+
ashBuildCommand: "pnpm build:ash",
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Non-Vercel Production Hosts
|
|
116
|
+
|
|
117
|
+
If you deploy somewhere other than Vercel and the Ash service runs on a
|
|
118
|
+
separate origin, point Nuxt at it with `ASH_NUXT_PRODUCTION_ORIGIN`:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
ASH_NUXT_PRODUCTION_ORIGIN=https://agent.example.com pnpm build
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Set `ASH_NUXT_PRODUCTION_PORT` to use a different local port (default `4274`):
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
ASH_NUXT_PRODUCTION_PORT=5000 pnpm build && pnpm preview
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Authenticated Requests
|
|
131
|
+
|
|
132
|
+
Because the agent runs on the same origin as your Nuxt app, the auth you
|
|
133
|
+
already use for the rest of the app applies to it for free. Cookie-based
|
|
134
|
+
sessions work without extra wiring: the browser already sends those cookies
|
|
135
|
+
on every Ash request.
|
|
136
|
+
|
|
137
|
+
For non-cookie schemes (bearer tokens, custom headers), attach them from the
|
|
138
|
+
client instead:
|
|
139
|
+
|
|
140
|
+
```vue
|
|
141
|
+
<script setup lang="ts">
|
|
142
|
+
const agent = useAshAgent({
|
|
143
|
+
headers: async () => ({
|
|
144
|
+
authorization: `Bearer ${await getAccessToken()}`,
|
|
145
|
+
}),
|
|
146
|
+
});
|
|
147
|
+
</script>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Prefer function values for short-lived credentials. Ash re-resolves them
|
|
151
|
+
before each HTTP request, including reconnects.
|
|
152
|
+
|
|
153
|
+
## Add Per-Turn Page Context
|
|
154
|
+
|
|
155
|
+
`useAshAgent()` accepts a `prepareSend` callback for attaching one-turn page
|
|
156
|
+
state (pathname, selected ids, anything else the model should see for the
|
|
157
|
+
next call only). See [`useAshAgent` (Vue)](./use-ash-agent-vue.md#add-per-turn-client-context)
|
|
158
|
+
for the full pattern.
|
|
159
|
+
|
|
160
|
+
For server-side enrichment (policy, durable context, dynamic skills), use
|
|
161
|
+
runtime lifecycle hooks instead. See [Hooks](../advanced/hooks.mdx).
|
|
162
|
+
|
|
163
|
+
## What To Read Next
|
|
164
|
+
|
|
165
|
+
- [`useAshAgent` (Vue)](./use-ash-agent-vue.md)
|
|
166
|
+
- [Auth And Route Protection](../advanced/auth-and-route-protection.mdx)
|
|
167
|
+
- [Hooks](../advanced/hooks.mdx)
|
|
168
|
+
- [Sessions And Streaming](../advanced/runs-and-streaming.md)
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "SvelteKit"
|
|
3
|
+
description: "Add an Ash agent to a SvelteKit app and call it from the browser."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`experimental-ash/sveltekit` lets you ship a SvelteKit frontend and an Ash
|
|
7
|
+
agent as one project. Add the Vite plugin to an existing SvelteKit app, or
|
|
8
|
+
start with an agent and point a SvelteKit project at it.
|
|
9
|
+
|
|
10
|
+
- **One dev server.** `vite dev` runs the app and the agent together.
|
|
11
|
+
- **One deploy.** Vercel ships them as a single project; no extra service to operate.
|
|
12
|
+
- **Zero URL plumbing.** `useAshAgent()` finds the mounted routes automatically; no CORS, no env vars.
|
|
13
|
+
|
|
14
|
+
## Add Ash To SvelteKit
|
|
15
|
+
|
|
16
|
+
Register the plugin in your Vite config:
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
// vite.config.ts
|
|
20
|
+
import { sveltekit } from "@sveltejs/kit/vite";
|
|
21
|
+
import { ashSvelteKit } from "experimental-ash/sveltekit";
|
|
22
|
+
import { defineConfig } from "vite";
|
|
23
|
+
|
|
24
|
+
export default defineConfig({
|
|
25
|
+
plugins: [ashSvelteKit(), sveltekit()],
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
By default, the plugin looks for an `agent/` folder inside your SvelteKit
|
|
30
|
+
project root. Pass `ashRoot` when the agent lives somewhere else:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
export default defineConfig({
|
|
34
|
+
plugins: [
|
|
35
|
+
ashSvelteKit({
|
|
36
|
+
ashRoot: "../my-agent",
|
|
37
|
+
}),
|
|
38
|
+
sveltekit(),
|
|
39
|
+
],
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Add The Ash Channel
|
|
44
|
+
|
|
45
|
+
Skip this section if the framework default channel works for you. The plugin
|
|
46
|
+
already wires Ash up without it.
|
|
47
|
+
|
|
48
|
+
Create `agent/channels/ash.ts` when you want to choose the route auth policy
|
|
49
|
+
explicitly:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
// agent/channels/ash.ts
|
|
53
|
+
import { ashChannel } from "experimental-ash/channels/ash";
|
|
54
|
+
import { none } from "experimental-ash/channels/auth";
|
|
55
|
+
|
|
56
|
+
export default ashChannel({
|
|
57
|
+
auth: none(),
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
For protected apps, replace `none()` with a channel auth helper such as
|
|
62
|
+
`vercelOidc()`, `oidc(...)`, or `httpBasic(...)`.
|
|
63
|
+
|
|
64
|
+
## Use The Svelte Binding
|
|
65
|
+
|
|
66
|
+
Once the plugin is in `vite.config.ts`, browser code can use
|
|
67
|
+
[`useAshAgent()`](./use-ash-agent-svelte.md) without a custom host:
|
|
68
|
+
|
|
69
|
+
```svelte
|
|
70
|
+
<script lang="ts">
|
|
71
|
+
import { useAshAgent } from "experimental-ash/svelte";
|
|
72
|
+
|
|
73
|
+
const agent = useAshAgent();
|
|
74
|
+
let message = $state("");
|
|
75
|
+
let isBusy = $derived(agent.status === "submitted" || agent.status === "streaming");
|
|
76
|
+
|
|
77
|
+
async function handleSubmit() {
|
|
78
|
+
const text = message.trim();
|
|
79
|
+
if (!text || isBusy) return;
|
|
80
|
+
message = "";
|
|
81
|
+
await agent.sendMessage(text);
|
|
82
|
+
}
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
<form onsubmit={(event) => {
|
|
86
|
+
event.preventDefault();
|
|
87
|
+
void handleSubmit();
|
|
88
|
+
}}>
|
|
89
|
+
<input bind:value={message} disabled={isBusy} />
|
|
90
|
+
<button type="submit" disabled={isBusy}>Send</button>
|
|
91
|
+
</form>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The binding handles conversation state, streaming updates, errors, and messages
|
|
95
|
+
for you. See [`useAshAgent` (Svelte)](./use-ash-agent-svelte.md) for the full
|
|
96
|
+
API.
|
|
97
|
+
|
|
98
|
+
## Local Development
|
|
99
|
+
|
|
100
|
+
`pnpm dev` is enough. The plugin boots the Ash dev server alongside SvelteKit
|
|
101
|
+
and proxies the Ash routes to it, so your browser keeps talking to the
|
|
102
|
+
SvelteKit origin.
|
|
103
|
+
|
|
104
|
+
`pnpm build && pnpm preview` works the same way for local production preview:
|
|
105
|
+
the preview server gets its own Ash route proxy and reuses or starts the shared
|
|
106
|
+
Ash server automatically.
|
|
107
|
+
|
|
108
|
+
## Vercel Deployments
|
|
109
|
+
|
|
110
|
+
On Vercel, the plugin keeps the web app public and the Ash runtime tucked
|
|
111
|
+
behind it. Users visit the SvelteKit app, and the browser talks to the agent
|
|
112
|
+
through the same site origin.
|
|
113
|
+
|
|
114
|
+
Use `ashBuildCommand` when the agent needs a project-specific build command:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
export default defineConfig({
|
|
118
|
+
plugins: [
|
|
119
|
+
ashSvelteKit({
|
|
120
|
+
ashBuildCommand: "pnpm build:ash",
|
|
121
|
+
}),
|
|
122
|
+
sveltekit(),
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Non-Vercel Production Hosts
|
|
128
|
+
|
|
129
|
+
If you deploy somewhere other than Vercel and the Ash service runs on a
|
|
130
|
+
separate origin, pass `host` directly to `useAshAgent`:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
const agent = useAshAgent({
|
|
134
|
+
host: "https://agent.example.com",
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Authenticated Requests
|
|
139
|
+
|
|
140
|
+
Because the agent runs on the same origin as your SvelteKit app, the auth you
|
|
141
|
+
already use for the rest of the app applies to it for free. Cookie-based
|
|
142
|
+
sessions work without extra wiring: the browser already sends those cookies on
|
|
143
|
+
every Ash request.
|
|
144
|
+
|
|
145
|
+
For non-cookie schemes (bearer tokens, custom headers), attach them from the
|
|
146
|
+
client instead:
|
|
147
|
+
|
|
148
|
+
```svelte
|
|
149
|
+
<script lang="ts">
|
|
150
|
+
const agent = useAshAgent({
|
|
151
|
+
headers: async () => ({
|
|
152
|
+
authorization: `Bearer ${await getAccessToken()}`,
|
|
153
|
+
}),
|
|
154
|
+
});
|
|
155
|
+
</script>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Prefer function values for short-lived credentials. Ash re-resolves them before
|
|
159
|
+
each HTTP request, including reconnects.
|
|
160
|
+
|
|
161
|
+
## Add Per-Turn Page Context
|
|
162
|
+
|
|
163
|
+
`useAshAgent()` accepts a `prepareSend` callback for attaching one-turn page
|
|
164
|
+
state (pathname, selected ids, anything else the model should see for the next
|
|
165
|
+
call only). See
|
|
166
|
+
[`useAshAgent` (Svelte)](./use-ash-agent-svelte.md#add-per-turn-client-context)
|
|
167
|
+
for the full pattern.
|
|
168
|
+
|
|
169
|
+
For server-side enrichment (policy, durable context, dynamic skills), use
|
|
170
|
+
runtime lifecycle hooks instead. See [Hooks](../advanced/hooks.mdx).
|
|
171
|
+
|
|
172
|
+
## What To Read Next
|
|
173
|
+
|
|
174
|
+
- [`useAshAgent` (Svelte)](./use-ash-agent-svelte.md)
|
|
175
|
+
- [Auth And Route Protection](../advanced/auth-and-route-protection.mdx)
|
|
176
|
+
- [Hooks](../advanced/hooks.mdx)
|
|
177
|
+
- [Sessions And Streaming](../advanced/runs-and-streaming.md)
|