experimental-ash 0.22.2 → 0.24.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 +36 -0
- package/dist/docs/internals/hooks.md +13 -16
- package/dist/docs/internals/message-runtime.md +1 -1
- package/dist/docs/public/auth-and-route-protection.md +3 -3
- package/dist/docs/public/faqs.md +67 -0
- package/dist/docs/public/meta.json +1 -0
- package/dist/docs/public/schedules.md +11 -0
- package/dist/docs/public/session-context.md +46 -89
- package/dist/docs/public/skills.md +13 -0
- package/dist/docs/public/subagents.md +12 -6
- package/dist/docs/public/tools.md +9 -13
- package/dist/docs/public/typescript-api.md +4 -4
- package/dist/src/channel/types.d.ts +10 -12
- package/dist/src/chunks/{client-CKsU8Li3.js → client-nshDsWNF.js} +1 -1
- package/dist/src/chunks/{dev-authored-source-watcher-BLzYWh05.js → dev-authored-source-watcher-B4PaZGUr.js} +1 -1
- package/dist/src/chunks/host-DsW72Q-w.js +65 -0
- package/dist/src/chunks/paths-OknjaYR8.js +89 -0
- package/dist/src/chunks/prewarm-B4YblQ5m.js +6 -0
- package/dist/src/cli/commands/info.js +1 -1
- package/dist/src/cli/dev/repl.js +2 -2
- package/dist/src/cli/run.js +1 -1
- package/dist/src/client/session.js +8 -0
- package/dist/src/client/types.d.ts +12 -1
- package/dist/src/compiled/.vendor-stamp.json +3 -3
- package/dist/src/compiled/@workflow/core/_ms.d.ts +4 -0
- package/dist/src/compiled/@workflow/core/_workflow-serde.d.ts +5 -0
- package/dist/src/compiled/@workflow/core/_workflow-utils.d.ts +8 -0
- package/dist/src/compiled/@workflow/core/_workflow-world.d.ts +59 -0
- package/dist/src/compiled/@workflow/core/capabilities.d.ts +45 -0
- package/dist/src/compiled/@workflow/core/capture-stack.d.ts +16 -0
- package/dist/src/compiled/@workflow/core/class-serialization.d.ts +31 -0
- package/dist/src/compiled/@workflow/core/classify-error.d.ts +20 -0
- package/dist/src/compiled/@workflow/core/context-errors.d.ts +27 -0
- package/dist/src/compiled/@workflow/core/context-violation-error.d.ts +97 -0
- package/dist/src/compiled/@workflow/core/create-hook.d.ts +179 -0
- package/dist/src/compiled/@workflow/core/define-hook.d.ts +68 -0
- package/dist/src/compiled/@workflow/core/describe-error.d.ts +70 -0
- package/dist/src/compiled/@workflow/core/encryption.d.ts +51 -0
- package/dist/src/compiled/@workflow/core/events-consumer.d.ts +64 -0
- package/dist/src/compiled/@workflow/core/flushable-stream.d.ts +82 -0
- package/dist/src/compiled/@workflow/core/global.d.ts +48 -0
- package/dist/src/compiled/@workflow/core/index.d.ts +19 -38
- package/dist/src/compiled/@workflow/core/index.js +2 -2
- package/dist/src/compiled/@workflow/core/log-format.d.ts +25 -0
- package/dist/src/compiled/@workflow/core/logger.d.ts +29 -0
- package/dist/src/compiled/@workflow/core/package.json +1 -1
- package/dist/src/compiled/@workflow/core/private.d.ts +59 -10
- package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +51 -0
- package/dist/src/compiled/@workflow/core/runtime/get-port-lazy.d.ts +10 -0
- package/dist/src/compiled/@workflow/core/runtime/get-world-lazy.d.ts +32 -0
- package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +97 -0
- package/dist/src/compiled/@workflow/core/runtime/replay-budget.d.ts +98 -0
- package/dist/src/compiled/@workflow/core/runtime/resume-hook.d.ts +77 -0
- package/dist/src/compiled/@workflow/core/runtime/run.d.ts +134 -0
- package/dist/src/compiled/@workflow/core/runtime/runs.d.ts +50 -0
- package/dist/src/compiled/@workflow/core/runtime/start.d.ts +59 -0
- package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +40 -0
- package/dist/src/compiled/@workflow/core/runtime/step-handler.d.ts +2 -0
- package/dist/src/compiled/@workflow/core/runtime/suspension-handler.d.ts +42 -0
- package/dist/src/compiled/@workflow/core/runtime/world-init.d.ts +75 -0
- package/dist/src/compiled/@workflow/core/runtime/world.d.ts +32 -0
- package/dist/src/compiled/@workflow/core/runtime.d.ts +22 -67
- package/dist/src/compiled/@workflow/core/runtime.js +27 -27
- package/dist/src/compiled/@workflow/core/schemas.d.ts +15 -0
- package/dist/src/compiled/@workflow/core/serialization/client.d.ts +17 -0
- package/dist/src/compiled/@workflow/core/serialization/codec-devalue.d.ts +14 -0
- package/dist/src/compiled/@workflow/core/serialization/codec.d.ts +90 -0
- package/dist/src/compiled/@workflow/core/serialization/encryption.d.ts +32 -0
- package/dist/src/compiled/@workflow/core/serialization/errors.d.ts +21 -0
- package/dist/src/compiled/@workflow/core/serialization/format.d.ts +60 -0
- package/dist/src/compiled/@workflow/core/serialization/index.d.ts +18 -0
- package/dist/src/compiled/@workflow/core/serialization/reducers/class.d.ts +11 -0
- package/dist/src/compiled/@workflow/core/serialization/reducers/common.d.ts +16 -0
- package/dist/src/compiled/@workflow/core/serialization/reducers/step-function.d.ts +35 -0
- package/dist/src/compiled/@workflow/core/serialization/step.d.ts +17 -0
- package/dist/src/compiled/@workflow/core/serialization/types.d.ts +215 -0
- package/dist/src/compiled/@workflow/core/serialization/workflow.d.ts +29 -0
- package/dist/src/compiled/@workflow/core/serialization-format.d.ts +171 -0
- package/dist/src/compiled/@workflow/core/serialization.d.ts +337 -0
- package/dist/src/compiled/@workflow/core/sleep.d.ts +33 -0
- package/dist/src/compiled/@workflow/core/source-map.d.ts +10 -0
- package/dist/src/compiled/@workflow/core/step/context-storage.d.ts +13 -0
- package/dist/src/compiled/@workflow/core/step/get-closure-vars.d.ts +9 -0
- package/dist/src/compiled/@workflow/core/step/get-step-metadata.d.ts +42 -0
- package/dist/src/compiled/@workflow/core/step/get-workflow-metadata.d.ts +7 -0
- package/dist/src/compiled/@workflow/core/step/writable-stream.d.ts +22 -0
- package/dist/src/compiled/@workflow/core/step.d.ts +4 -0
- package/dist/src/compiled/@workflow/core/symbols.d.ts +36 -0
- package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +283 -0
- package/dist/src/compiled/@workflow/core/telemetry.d.ts +53 -0
- package/dist/src/compiled/@workflow/core/types.d.ts +14 -0
- package/dist/src/compiled/@workflow/core/util.d.ts +40 -0
- package/dist/src/compiled/@workflow/core/version.d.ts +2 -0
- package/dist/src/compiled/@workflow/core/vm/index.d.ts +17 -0
- package/dist/src/compiled/@workflow/core/vm/uint8array-base64.d.ts +21 -0
- package/dist/src/compiled/@workflow/core/vm/uuid.d.ts +10 -0
- package/dist/src/compiled/@workflow/core/workflow/abort-controller.d.ts +65 -0
- package/dist/src/compiled/@workflow/core/workflow/create-hook.d.ts +7 -0
- package/dist/src/compiled/@workflow/core/workflow/define-hook.d.ts +10 -0
- package/dist/src/compiled/@workflow/core/workflow/get-workflow-metadata.d.ts +32 -0
- package/dist/src/compiled/@workflow/core/workflow/hook.d.ts +4 -0
- package/dist/src/compiled/@workflow/core/workflow/index.d.ts +11 -0
- package/dist/src/compiled/@workflow/core/workflow/sleep.d.ts +4 -0
- package/dist/src/compiled/@workflow/core/workflow/world-init-stub.d.ts +15 -0
- package/dist/src/compiled/@workflow/core/workflow/writable-stream.d.ts +3 -0
- package/dist/src/compiled/@workflow/core/workflow.d.ts +1 -38
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/@workflow/errors/error-codes.d.ts +5 -1
- package/dist/src/compiled/@workflow/errors/index.d.ts +15 -1
- package/dist/src/compiled/@workflow/errors/index.js +1 -1
- package/dist/src/compiled/@workflow/errors/package.json +1 -1
- package/dist/src/compiled/_chunks/workflow/{context-errors-zbKocOyk.js → context-errors-Bbvvp-li.js} +2 -2
- package/dist/src/compiled/_chunks/workflow/{dist-0iNBqPYp.js → dist-C7wPwOI9.js} +2 -2
- package/dist/src/compiled/_chunks/workflow/{dist-D774SUM4.js → dist-C_oiE-l7.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/resume-hook-C3VWUPii.js +12 -0
- package/dist/src/compiled/_chunks/workflow/sleep-QTkC1VFe.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{symbols-D-4tVV8x.js → symbols-QezhMuLg.js} +1 -1
- package/dist/src/evals/cli/eval.js +1 -1
- package/dist/src/execution/await-authorization-orchestrator.d.ts +2 -1
- package/dist/src/execution/await-authorization-orchestrator.js +4 -0
- package/dist/src/execution/connection-auth-steps.d.ts +4 -0
- package/dist/src/execution/connection-auth-steps.js +9 -11
- package/dist/src/execution/node-step.d.ts +4 -5
- package/dist/src/execution/subagent-adapter.d.ts +0 -27
- package/dist/src/execution/subagent-adapter.js +2 -66
- package/dist/src/execution/subagent-hitl-proxy.d.ts +2 -2
- package/dist/src/execution/subagent-hitl-proxy.js +2 -2
- package/dist/src/execution/task-mode.d.ts +3 -3
- package/dist/src/execution/task-mode.js +3 -3
- package/dist/src/execution/turn-workflow.d.ts +41 -0
- package/dist/src/execution/turn-workflow.js +96 -0
- package/dist/src/execution/workflow-entry.js +77 -87
- package/dist/src/execution/workflow-errors.d.ts +14 -0
- package/dist/src/execution/workflow-errors.js +54 -0
- package/dist/src/execution/workflow-runtime.d.ts +34 -3
- package/dist/src/execution/workflow-runtime.js +52 -10
- package/dist/src/execution/workflow-steps.d.ts +27 -2
- package/dist/src/execution/workflow-steps.js +31 -26
- package/dist/src/harness/instrumentation-config.js +14 -7
- package/dist/src/harness/messages.d.ts +7 -7
- package/dist/src/harness/messages.js +4 -4
- package/dist/src/harness/runtime-actions.d.ts +4 -4
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/workflow-bundle/workflow-builders.d.ts +1 -1
- package/dist/src/internal/workflow-bundle/workflow-builders.js +20 -8
- package/dist/src/internal/workflow-bundle/workflow-transformer.d.ts +13 -0
- package/dist/src/internal/workflow-bundle/workflow-transformer.js +10 -4
- package/dist/src/protocol/message.d.ts +6 -1
- package/dist/src/public/channels/ash.js +50 -3
- package/dist/src/public/context/index.d.ts +4 -7
- package/dist/src/public/context/index.js +4 -5
- package/dist/src/public/definitions/state.d.ts +33 -0
- package/dist/src/public/definitions/state.js +34 -0
- package/dist/src/public/next/index.d.ts +7 -0
- package/dist/src/public/next/index.js +2 -0
- package/dist/src/public/next/vercel-json.d.ts +1 -0
- package/dist/src/public/next/vercel-json.js +1 -0
- package/dist/src/react/index.d.ts +1 -1
- package/dist/src/react/use-ash-agent.d.ts +8 -0
- package/dist/src/react/use-ash-agent.js +26 -4
- package/dist/src/services/dev-client.d.ts +4 -1
- package/dist/src/services/dev-client.js +1 -0
- package/package.json +4 -4
- package/dist/src/chunks/host-DREC8e8Z.js +0 -65
- package/dist/src/chunks/paths-C6sp4T2U.js +0 -88
- package/dist/src/chunks/prewarm-hz8p2jlZ.js +0 -6
- package/dist/src/compiled/_chunks/workflow/resume-hook-CL8Ed91K.js +0 -12
- package/dist/src/compiled/_chunks/workflow/sleep-Dn3i9nxI.js +0 -1
- package/dist/src/execution/continuous-entry.d.ts +0 -59
- package/dist/src/execution/continuous-entry.js +0 -487
- package/dist/src/execution/continuous-runtime.d.ts +0 -17
- package/dist/src/execution/continuous-runtime.js +0 -123
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# experimental-ash
|
|
2
2
|
|
|
3
|
+
## 0.24.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 1a43bef: Remove `result` from `RunHandle`. The workflow runtime's terminal state is observed through the durable event stream's `session.completed` / `session.failed` events. The continuous runtime keeps `result` via a new `ContinuousRunHandle` subtype (in-process resolution; no polling).
|
|
8
|
+
- 5a9f798: Split the durable workflow runtime into a long-lived session driver plus per-turn child workflows. The driver acquires the session's writable once in its workflow body and forwards it to each turn workflow as the second positional `start()` argument; the per-turn child writes directly to the driver's stream, preserving the stable client session stream while preparing turn execution for deployment updates. Requires `@workflow/core` ≥ 5.0.0-beta.6 ([vercel/workflow#2059](https://github.com/vercel/workflow/pull/2059)), which routes child writes to the parent run's stream with a parent-key encrypt-only handshake.
|
|
9
|
+
- 8b2957a: Remove the continuous (in-memory, non-durable) runtime and its supporting
|
|
10
|
+
machinery. The workflow runtime is now the only runtime. Deleted public
|
|
11
|
+
exports: `createContinuousLoopRuntime`, `createContinuousLoopRuntimeFactory`,
|
|
12
|
+
`ContinuousRuntime`, `ContinuousCreateRuntime`, `ContinuousRunHandle`. The
|
|
13
|
+
process-local subagent HITL dispatcher registry
|
|
14
|
+
(`registerContinuousSubagentInputRequestDispatcher` /
|
|
15
|
+
`unregisterContinuousSubagentInputRequestDispatcher`) is also removed —
|
|
16
|
+
subagent `input.requested` events now always forward to the parent via the
|
|
17
|
+
workflow `resumeHook` path.
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- 8ca8600: fix(ash): honor `defineInstrumentation` exports when running under Nitro
|
|
22
|
+
|
|
23
|
+
Nitro evaluates the harness's instrumentation-config module twice (once via the generated plugin's `file://` URL, once via the inlined `#harness/*` alias), so a module-local store left the harness reading `undefined` even after the plugin registered a config. The config now lives on `globalThis` under a stable `Symbol.for(...)`, so telemetry actually flows when an `agent/instrumentation.ts` default export is present.
|
|
24
|
+
|
|
25
|
+
## 0.23.0
|
|
26
|
+
|
|
27
|
+
### Minor Changes
|
|
28
|
+
|
|
29
|
+
- 316f6c5: feat(ash): add `defineState` for typed durable state, remove raw `ContextKey` from public API
|
|
30
|
+
|
|
31
|
+
`defineState(name, initial)` creates a typed state handle with `get()` and `update()`. All operations throw outside the Ash context scope. Replaces the `ContextKey` + `ensureContext` / `setContext` / `requireContext` pattern with a single primitive.
|
|
32
|
+
|
|
33
|
+
Breaking: `ContextKey`, `ensureContext`, `getContext`, `setContext`, `requireContext`, `hasContext`, `ContextAccessor`, `AshContext`, `ContextProvider`, and `ContextReader` are no longer exported from `experimental-ash/context`.
|
|
34
|
+
|
|
35
|
+
### Patch Changes
|
|
36
|
+
|
|
37
|
+
- 5aedab4: Add browser client support for one-turn `clientContext`, React `prepareSend`, and AI SDK `UserContent` messages.
|
|
38
|
+
|
|
3
39
|
## 0.22.2
|
|
4
40
|
|
|
5
41
|
### Patch Changes
|
|
@@ -84,22 +84,19 @@ the workflow path.
|
|
|
84
84
|
|
|
85
85
|
## Dispatch
|
|
86
86
|
|
|
87
|
-
Lifecycle dispatch lives in `src/context/hook-lifecycle.ts`.
|
|
88
|
-
runtime entry
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
`getHarnessEmissionState(session).turnId === ""` so tool-loop
|
|
101
|
-
continuations and runtime-action resumes (which are continuations of
|
|
102
|
-
an existing turn) skip the lifecycle stack.
|
|
87
|
+
Lifecycle dispatch lives in `src/context/hook-lifecycle.ts`. The
|
|
88
|
+
workflow runtime entry point (`execution/workflow-steps.ts`) calls
|
|
89
|
+
`runHookLifecycleStep` once per turn, **inside** the active ALS scope
|
|
90
|
+
so hook code can read and write `ctx.ash` like every other authored
|
|
91
|
+
function. `runHookLifecycleStep` wraps `dispatchHookLifecycle`, lowers
|
|
92
|
+
a `turn-failed` outcome into a parking `StepResult` (`{ next: null }`
|
|
93
|
+
for conversation mode, `{ next: { done: true, output } }` for task
|
|
94
|
+
mode), and otherwise hands off to the supplied harness step callback
|
|
95
|
+
with the (possibly augmented) input.
|
|
96
|
+
|
|
97
|
+
Dispatch is gated on `getHarnessEmissionState(session).turnId === ""`
|
|
98
|
+
so tool-loop continuations and runtime-action resumes (which are
|
|
99
|
+
continuations of an existing turn) skip the lifecycle stack.
|
|
103
100
|
|
|
104
101
|
Stages, in order:
|
|
105
102
|
|
|
@@ -64,4 +64,4 @@ The runtime stores both `auth.current` and `auth.initiator`. Follow-up messages
|
|
|
64
64
|
|
|
65
65
|
The runtime owns stream plumbing; the channel owns delivery policy. The runtime calls `channel.onEvent(event)` for each lifecycle event — the channel may transform it or perform platform side effects. The harness emits events without knowing the transport.
|
|
66
66
|
|
|
67
|
-
Authored stream-event hooks fan out alongside `callAdapterEventHandler` from the same `HarnessEmitFn` composer (`workflow-steps.ts`
|
|
67
|
+
Authored stream-event hooks fan out alongside `callAdapterEventHandler` from the same `HarnessEmitFn` composer (`workflow-steps.ts`). Hook errors propagate through the emit composer and are caught by the existing harness error path, which emits the recoverable `turn.failed` cascade. See [Hooks](./hooks.md).
|
|
@@ -110,9 +110,9 @@ Important behavior:
|
|
|
110
110
|
- follow-up messages update `auth.current` without changing `auth.initiator`
|
|
111
111
|
- unprotected agents expose both as `null`
|
|
112
112
|
|
|
113
|
-
Auth on follow-up messages (`deliver()`) is honored by
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
Auth on follow-up messages (`deliver()`) is honored by the workflow runtime. When a different
|
|
114
|
+
user sends a follow-up to the same session, `session.auth.current` reflects the new caller on
|
|
115
|
+
that turn while `session.auth.initiator` stays the same.
|
|
116
116
|
|
|
117
117
|
## What Ash Does Not Do
|
|
118
118
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "FAQs"
|
|
3
|
+
description: "Frequently asked questions about Ash."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# FAQs
|
|
7
|
+
|
|
8
|
+
## How do I view my agent's observability and drill into conversation traces?
|
|
9
|
+
|
|
10
|
+
When you deploy an Ash agent to Vercel, the platform auto-detects `ash` as the
|
|
11
|
+
framework, which surfaces an **Agent Runs** tab under your project's
|
|
12
|
+
**Observability** view in the Vercel dashboard. From there you can browse
|
|
13
|
+
sessions and drill into each conversation's trace.
|
|
14
|
+
|
|
15
|
+
> The Agent Runs tab is currently gated — your Vercel team needs the feature
|
|
16
|
+
> enabled before it appears. If you don't see it, reach out to your Vercel
|
|
17
|
+
> contact to get your team enabled.
|
|
18
|
+
|
|
19
|
+
Agent Runs is separate from the OpenTelemetry exporters configured in
|
|
20
|
+
[`instrumentation.ts`](./instrumentation.md) — those still work and are the
|
|
21
|
+
recommended path if you want spans in Braintrust, Datadog, or another
|
|
22
|
+
third-party backend.
|
|
23
|
+
|
|
24
|
+
## Does Ash use the Chat SDK?
|
|
25
|
+
|
|
26
|
+
Ash uses Chat SDK's **card-builder components** (Cards, Buttons,
|
|
27
|
+
Actions, etc.) for composing rich Slack messages — when you build a card with
|
|
28
|
+
Ash's Slack channel, the underlying primitives come from Chat SDK and get
|
|
29
|
+
converted to Slack Block Kit at post time.
|
|
30
|
+
|
|
31
|
+
Ash does **not** use Chat SDK's runtime. The `Chat`, `Adapter`, and `Thread`
|
|
32
|
+
primitives are never imported or reachable through Ash's public API. Ash's
|
|
33
|
+
channel layer — webhook handling, signature verification, event parsing, and
|
|
34
|
+
thread management — is implemented inside Ash itself (see [Channels](./channels/)).
|
|
35
|
+
|
|
36
|
+
In short:
|
|
37
|
+
|
|
38
|
+
- **Building Slack messages** → the components feel just like Chat SDK cards.
|
|
39
|
+
- **Wiring a channel** → you author against Ash's `defineChannel(...)` API, not
|
|
40
|
+
a Chat SDK adapter.
|
|
41
|
+
|
|
42
|
+
## How is session data persisted?
|
|
43
|
+
|
|
44
|
+
Ash persists session state automatically using the
|
|
45
|
+
[Workflow SDK](https://workflow-sdk.dev) — an open-source TypeScript
|
|
46
|
+
library that makes ordinary functions durable, resumable, and crash-safe.
|
|
47
|
+
Each Ash session corresponds to one workflow run: when a new message comes in,
|
|
48
|
+
the runtime either starts a new workflow or resumes an existing one, and the
|
|
49
|
+
durable context is serialized and threaded forward across each model-call
|
|
50
|
+
boundary so the session can be reloaded on the next turn.
|
|
51
|
+
|
|
52
|
+
You don't write workflow code directly. Workflow primitives (`start()`,
|
|
53
|
+
`resumeHook()`, etc.) are an implementation detail of Ash's runtime layer —
|
|
54
|
+
channels, tools, and hooks never touch them. This separation is enforced by
|
|
55
|
+
the framework's mechanical invariants.
|
|
56
|
+
|
|
57
|
+
If you want session data from your own code, there are two supported surfaces:
|
|
58
|
+
|
|
59
|
+
- **Tools** can read the current session's metadata (sessionId, turn, auth,
|
|
60
|
+
parent lineage) via `getSession()` from `experimental-ash/context`. This is
|
|
61
|
+
read-only.
|
|
62
|
+
- **Durable context keys + `ContextProvider`** are the supported pattern for
|
|
63
|
+
reading or writing session-scoped durable state from authored code — see
|
|
64
|
+
[Session Context](./session-context.md).
|
|
65
|
+
|
|
66
|
+
For the wire-level session lifecycle (creating sessions, streaming events,
|
|
67
|
+
reconnecting by event index) see [Sessions And Streaming](./runs-and-streaming.md).
|
|
@@ -166,6 +166,17 @@ In both cases, the schedule session uses the **app principal**: `getSession().au
|
|
|
166
166
|
|
|
167
167
|
The session goes through the same durable runtime engine as any other Ash session.
|
|
168
168
|
|
|
169
|
+
## On Vercel
|
|
170
|
+
|
|
171
|
+
On hosted Vercel builds, Ash compiles every `defineSchedule(...)` into a Vercel Cron Job. Each schedule's `cron` expression becomes an entry in `.vercel/output/config.json` `crons[]`, which the platform reads at deploy time.
|
|
172
|
+
|
|
173
|
+
You can view and monitor your schedules in two places in the Vercel dashboard:
|
|
174
|
+
|
|
175
|
+
- **Settings → Cron Jobs** — lists every schedule the deployment registered, with its cron expression and target path. Use this to confirm a schedule was discovered and shipped.
|
|
176
|
+
- **Observability → Cron Jobs** — shows execution history (when each schedule fired, success/failure, latency). Use this to confirm a schedule is actually firing on cadence.
|
|
177
|
+
|
|
178
|
+
The execution itself runs through the same durable runtime engine as any other Ash session, so per-run logs also appear under **Observability → Logs**.
|
|
179
|
+
|
|
169
180
|
## When to use a schedule
|
|
170
181
|
|
|
171
182
|
Use a schedule when the agent should initiate work on its own cadence:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Session Context"
|
|
3
|
-
description: "Runtime helpers: getSession, getSandbox, getSkill, and
|
|
3
|
+
description: "Runtime helpers: getSession, getSandbox, getSkill, and defineState."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Ash exposes runtime helpers for authored code:
|
|
@@ -8,16 +8,10 @@ Ash exposes runtime helpers for authored code:
|
|
|
8
8
|
- `getSession()`
|
|
9
9
|
- `getSandbox()`
|
|
10
10
|
- `getSkill(identifier)`
|
|
11
|
-
- `
|
|
12
|
-
- `requireContext(key)` -- returns `T`, throws if unset
|
|
13
|
-
- `hasContext(key)` -- returns `boolean`
|
|
14
|
-
- `setContext(key, valueOrUpdater)` -- returns `T`
|
|
15
|
-
- `ensureContext(key, factory)` -- returns `T`
|
|
11
|
+
- `defineState(name, initial)` -- typed durable state with `get()` and `update()`
|
|
16
12
|
|
|
17
13
|
These APIs work only inside active authored runtime execution such as tools, channel event
|
|
18
|
-
handlers, and authored hooks.
|
|
19
|
-
the framework binds to the current async call chain via `AsyncLocalStorage`. Authored hooks
|
|
20
|
-
receive the same `ContextAccessor` on `HookContext.ash` -- see [Hooks](./hooks.md).
|
|
14
|
+
handlers, and authored hooks. They throw when called outside a managed context.
|
|
21
15
|
|
|
22
16
|
## `getSession()`
|
|
23
17
|
|
|
@@ -107,112 +101,75 @@ Important behavior:
|
|
|
107
101
|
|
|
108
102
|
See [Skills](./skills.md) for the full authoring model.
|
|
109
103
|
|
|
110
|
-
##
|
|
104
|
+
## Custom State With `defineState`
|
|
111
105
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
or `onDirectMessage` on `slackChannel()`. This is useful when a channel needs to pass
|
|
115
|
-
platform-specific metadata (tenant ID, feature flags, etc.) that authored tools can read on the
|
|
116
|
-
same turn and on later turns.
|
|
106
|
+
Use `defineState` when your agent needs durable typed state that tools, hooks, and channel
|
|
107
|
+
handlers can share. State survives across workflow step boundaries.
|
|
117
108
|
|
|
118
|
-
### Defining
|
|
109
|
+
### Defining state
|
|
119
110
|
|
|
120
|
-
Declare
|
|
121
|
-
read it.
|
|
111
|
+
Declare the state handle at module scope. The handle is shared between all code that imports it.
|
|
122
112
|
|
|
123
|
-
`agent/
|
|
113
|
+
`agent/lib/budget.ts`
|
|
124
114
|
|
|
125
115
|
```ts
|
|
126
|
-
import {
|
|
116
|
+
import { defineState } from "experimental-ash/context";
|
|
127
117
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
Use `slackChannel()` and seed context via the `onAppMention` return value's auth attributes:
|
|
134
|
-
|
|
135
|
-
`agent/channels/slack.ts`
|
|
118
|
+
interface BudgetState {
|
|
119
|
+
readonly count: number;
|
|
120
|
+
readonly cap: number;
|
|
121
|
+
}
|
|
136
122
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
export default slackChannel({
|
|
142
|
-
onAppMention(ctx, message) {
|
|
143
|
-
if (!message.author) return null;
|
|
144
|
-
const tenantId = lookupTenant(message);
|
|
145
|
-
return {
|
|
146
|
-
auth: {
|
|
147
|
-
principalId: message.author.userId,
|
|
148
|
-
principalType: "user",
|
|
149
|
-
authenticator: "slack",
|
|
150
|
-
attributes: { tenantId },
|
|
151
|
-
},
|
|
152
|
-
};
|
|
153
|
-
},
|
|
154
|
-
events: {
|
|
155
|
-
"message.completed"(event, ctx) {
|
|
156
|
-
if (event.finishReason === "tool-calls") return;
|
|
157
|
-
if (event.message) ctx.thread.post(event.message);
|
|
158
|
-
},
|
|
159
|
-
"session.failed"(event, ctx) {
|
|
160
|
-
ctx.thread.post("Something went wrong.");
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
});
|
|
123
|
+
export const budget = defineState<BudgetState>("myapp.budget", () => ({
|
|
124
|
+
count: 0,
|
|
125
|
+
cap: 25,
|
|
126
|
+
}));
|
|
164
127
|
```
|
|
165
128
|
|
|
166
|
-
|
|
167
|
-
separate channel object.
|
|
168
|
-
|
|
169
|
-
### Reading context from a tool
|
|
129
|
+
### Reading and writing from tools
|
|
170
130
|
|
|
171
131
|
```ts
|
|
172
|
-
import { requireContext } from "experimental-ash/context";
|
|
173
132
|
import { defineTool } from "experimental-ash/tools";
|
|
174
133
|
import { z } from "zod";
|
|
175
|
-
import {
|
|
134
|
+
import { budget } from "../lib/budget.js";
|
|
176
135
|
|
|
177
136
|
export default defineTool({
|
|
178
|
-
description: "
|
|
137
|
+
description: "Check the remaining tool budget.",
|
|
179
138
|
inputSchema: z.object({}),
|
|
180
139
|
async execute() {
|
|
181
|
-
const
|
|
182
|
-
return {
|
|
140
|
+
const current = budget.get();
|
|
141
|
+
return { remaining: current.cap - current.count };
|
|
183
142
|
},
|
|
184
143
|
});
|
|
185
144
|
```
|
|
186
145
|
|
|
187
|
-
###
|
|
188
|
-
|
|
189
|
-
If a channel needs to vend a live non-serializable object each step, declare a `ContextProvider`.
|
|
190
|
-
Providers derive live step-local values from durable context keys.
|
|
191
|
-
|
|
192
|
-
The intended pattern is:
|
|
193
|
-
|
|
194
|
-
- The channel's event handler or `run()` setup writes durable serializable facts such as
|
|
195
|
-
tenant IDs, channel IDs, or installation IDs.
|
|
196
|
-
- A `ContextProvider` derives live step-local values such as SDK clients from those durable keys.
|
|
197
|
-
- Tools and other authored step code read the derived value with `requireContext(...)` or
|
|
198
|
-
`getContext(...)`.
|
|
146
|
+
### Updating from hooks
|
|
199
147
|
|
|
200
148
|
```ts
|
|
201
|
-
import {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
149
|
+
import { defineHook } from "experimental-ash/hooks";
|
|
150
|
+
import { budget } from "../lib/budget.js";
|
|
151
|
+
|
|
152
|
+
export default defineHook({
|
|
153
|
+
lifecycle: {
|
|
154
|
+
turn() {
|
|
155
|
+
// Reset budget each turn
|
|
156
|
+
budget.update(() => ({ count: 0, cap: 25 }));
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
events: {
|
|
160
|
+
"actions.requested"() {
|
|
161
|
+
budget.update((s) => ({ ...s, count: s.count + 1 }));
|
|
162
|
+
},
|
|
210
163
|
},
|
|
211
|
-
};
|
|
164
|
+
});
|
|
212
165
|
```
|
|
213
166
|
|
|
214
|
-
|
|
215
|
-
|
|
167
|
+
### API
|
|
168
|
+
|
|
169
|
+
| Method | Description |
|
|
170
|
+
| ------------ | -------------------------------------------------------------------------------- |
|
|
171
|
+
| `get()` | Read the current value. Returns `initial()` on first access. Throws outside ALS. |
|
|
172
|
+
| `update(fn)` | Apply a function to the current value. Throws outside ALS. |
|
|
216
173
|
|
|
217
174
|
## Where These APIs Work
|
|
218
175
|
|
|
@@ -233,7 +190,7 @@ explaining the required scope.
|
|
|
233
190
|
|
|
234
191
|
## How It Works
|
|
235
192
|
|
|
236
|
-
All
|
|
193
|
+
All runtime accessors read from the same `AshContext` container bound by a single `AsyncLocalStorage`.
|
|
237
194
|
The framework sets up this context before invoking authored code:
|
|
238
195
|
|
|
239
196
|
1. The runtime entry point creates an `AshContext` and populates durable seed keys (auth, session
|
|
@@ -137,6 +137,19 @@ Do not use a skill for:
|
|
|
137
137
|
- shell or filesystem setup for the agent -> use `sandbox/`
|
|
138
138
|
- a truly separate specialist surface -> use a subagent
|
|
139
139
|
|
|
140
|
+
## Skill Scoping Across Agents
|
|
141
|
+
|
|
142
|
+
Skills are scoped to the agent that declares them. The root agent's `skills/` are available only
|
|
143
|
+
to the root agent; a subagent's `skills/` (under `agent/subagents/<id>/skills/`) are available
|
|
144
|
+
only to that subagent.
|
|
145
|
+
|
|
146
|
+
There is no shared-skill mechanism. If two agents need the same procedure, either duplicate the
|
|
147
|
+
markdown under each agent's `skills/`, or — if both agents really need the _same_ identity around
|
|
148
|
+
it — reconsider whether the subagent boundary makes sense.
|
|
149
|
+
|
|
150
|
+
For sharing executable helpers (not skill instructions), use `lib/` — modules under `lib/` are not
|
|
151
|
+
indexed as skills, but can be imported from any tool or hook in the same agent tree.
|
|
152
|
+
|
|
140
153
|
## TypeScript-Authored Skills
|
|
141
154
|
|
|
142
155
|
If markdown is not enough, you can author a skill in TypeScript with `defineSkill(...)`.
|
|
@@ -69,14 +69,20 @@ Subagent execution gets:
|
|
|
69
69
|
- its own instructions prompt
|
|
70
70
|
- its own tools
|
|
71
71
|
- its own sandbox (independent of the parent's sandbox)
|
|
72
|
-
- its own
|
|
72
|
+
- its own `skills/` set (independent of the parent's skills)
|
|
73
73
|
- immediate parent lineage in `getSession().parent`
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
Skills and sandboxes do not cross the parent/child boundary. The subagent only sees skills
|
|
76
|
+
authored under `agent/subagents/<id>/skills/`; skills under the root `agent/skills/` are not
|
|
77
|
+
available inside the subagent's turns. If two subagents need the same procedure, duplicate the
|
|
78
|
+
markdown under each subagent's `skills/` (or, for typed code reuse, share helpers via `lib/`).
|
|
79
|
+
|
|
80
|
+
The subagent's sandbox follows the same rule: it does not inherit from the parent, since different
|
|
81
|
+
agents generally have different skills and sharing a filesystem would be confusing. Each subagent
|
|
82
|
+
gets the framework default sandbox unless it authors its own override at
|
|
83
|
+
`subagents/<name>/sandbox.ts` (or `subagents/<name>/sandbox/sandbox.ts` when paired with a
|
|
84
|
+
`workspace/` folder). A subagent can also author only `subagents/<name>/sandbox/workspace/` to seed
|
|
85
|
+
files without overriding the definition.
|
|
80
86
|
|
|
81
87
|
## Stream Behavior
|
|
82
88
|
|
|
@@ -40,7 +40,7 @@ There is no `name` override and no compile-time normalization — if you want a
|
|
|
40
40
|
identifier, name the file in snake_case.
|
|
41
41
|
|
|
42
42
|
`defineTool`, `disableTool`, `defineBashTool`, `defineReadFileTool`, and `defineWriteFileTool` live on the `experimental-ash/tools` subpath.
|
|
43
|
-
Runtime context helpers (`getSession`, `
|
|
43
|
+
Runtime context helpers (`getSession`, `defineState`) live on `experimental-ash/context`.
|
|
44
44
|
`getSandbox` lives on `experimental-ash/sandbox` and `getSkill` lives on `experimental-ash/skills`.
|
|
45
45
|
|
|
46
46
|
## What A Tool Definition Needs
|
|
@@ -205,14 +205,13 @@ The runtime tool name comes from the filename (here, `repo_shell`, `read_file`,
|
|
|
205
205
|
When replacing the framework `read_file`, the authored version inherits the same compaction
|
|
206
206
|
state-reset behavior by default. Provide an explicit `onCompact` to override that.
|
|
207
207
|
|
|
208
|
-
### Replace A Default With Custom
|
|
208
|
+
### Replace A Default With Custom State
|
|
209
209
|
|
|
210
|
-
`agent/tools/todo.ts` - replace the framework `todo` tool with a custom durable
|
|
211
|
-
version
|
|
212
|
-
`requireContext` / `setContext`:
|
|
210
|
+
`agent/tools/todo.ts` - replace the framework `todo` tool with a custom durable state-backed
|
|
211
|
+
version using `defineState`:
|
|
213
212
|
|
|
214
213
|
```ts
|
|
215
|
-
import {
|
|
214
|
+
import { defineState } from "experimental-ash/context";
|
|
216
215
|
import { defineTool } from "experimental-ash/tools";
|
|
217
216
|
import { z } from "zod";
|
|
218
217
|
|
|
@@ -220,7 +219,7 @@ interface NoteListState {
|
|
|
220
219
|
readonly notes: readonly string[];
|
|
221
220
|
}
|
|
222
221
|
|
|
223
|
-
const
|
|
222
|
+
const noteList = defineState<NoteListState>("myapp.notes", () => ({ notes: [] }));
|
|
224
223
|
|
|
225
224
|
export default defineTool({
|
|
226
225
|
description: "Append a note or read the running list of notes.",
|
|
@@ -228,15 +227,12 @@ export default defineTool({
|
|
|
228
227
|
note: z.string().optional(),
|
|
229
228
|
}),
|
|
230
229
|
async execute(input) {
|
|
231
|
-
ensureContext(NoteListStateKey, () => ({ notes: [] }));
|
|
232
|
-
|
|
233
230
|
if (typeof input.note === "string" && input.note.length > 0) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
notes: [...(current?.notes ?? []), next],
|
|
231
|
+
noteList.update((current) => ({
|
|
232
|
+
notes: [...current.notes, input.note!],
|
|
237
233
|
}));
|
|
238
234
|
}
|
|
239
|
-
return
|
|
235
|
+
return noteList.get();
|
|
240
236
|
},
|
|
241
237
|
});
|
|
242
238
|
```
|
|
@@ -53,17 +53,17 @@ Each runtime accessor lives on the subpath that owns its concern:
|
|
|
53
53
|
- `getSession()` - current session, turn, auth, and optional parent lineage (`experimental-ash/context`)
|
|
54
54
|
- `getSandbox()` - live sandbox handle for the current agent (`experimental-ash/sandbox`)
|
|
55
55
|
- `getSkill(identifier)` - handle for a named skill visible to the current agent (`experimental-ash/skills`)
|
|
56
|
-
- `
|
|
56
|
+
- `defineState(name, initial)` - typed durable state with `get()` and `update()` (`experimental-ash/context`)
|
|
57
57
|
|
|
58
58
|
Related exported types by subpath:
|
|
59
59
|
|
|
60
|
-
- `experimental-ash/context`: `Session`, `SessionAuth`, `SessionAuthContext`, `SessionParent`, `SessionTurn`, `
|
|
60
|
+
- `experimental-ash/context`: `Session`, `SessionAuth`, `SessionAuthContext`, `SessionParent`, `SessionTurn`, `StateHandle`
|
|
61
61
|
- `experimental-ash/skills`: `SkillHandle`, `SkillFile`, `SkillDefinition`
|
|
62
62
|
- `experimental-ash`: `RunMode`
|
|
63
63
|
- `experimental-ash/evals`: eval types
|
|
64
64
|
|
|
65
|
-
Ash also exports lower-level runtime primitives such as `createToolLoopHarness(...)
|
|
66
|
-
|
|
65
|
+
Ash also exports lower-level runtime primitives such as `createToolLoopHarness(...)`
|
|
66
|
+
and `createWorkflowRuntime(...)`.
|
|
67
67
|
|
|
68
68
|
Channel and Slack types exported from `experimental-ash/channels/slack`:
|
|
69
69
|
|
|
@@ -38,9 +38,9 @@ export interface SessionAuthContext {
|
|
|
38
38
|
/**
|
|
39
39
|
* Function provided by the runtime that writes one event to the event stream.
|
|
40
40
|
*
|
|
41
|
-
* Backed by `getWritable()` in the workflow runtime
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* Backed by `getWritable()` in the workflow runtime. Not part of the
|
|
42
|
+
* adapter interface — the runtime always writes events to the stream
|
|
43
|
+
* itself.
|
|
44
44
|
*/
|
|
45
45
|
export type EventEmitFn = (event: HandleMessageStreamEvent) => Promise<void>;
|
|
46
46
|
/**
|
|
@@ -195,7 +195,10 @@ export interface DeliverInput {
|
|
|
195
195
|
readonly payload: DeliverPayload;
|
|
196
196
|
}
|
|
197
197
|
/**
|
|
198
|
-
* Terminal outcome of a runtime
|
|
198
|
+
* Terminal outcome of a runtime run.
|
|
199
|
+
*
|
|
200
|
+
* Terminal state on the workflow runtime is observed through the durable
|
|
201
|
+
* event stream's `session.completed` / `session.failed` events.
|
|
199
202
|
*/
|
|
200
203
|
export type RunResult = {
|
|
201
204
|
readonly status: "completed";
|
|
@@ -207,19 +210,14 @@ export type RunResult = {
|
|
|
207
210
|
* Handle returned immediately by `runtime.run()` before the step loop
|
|
208
211
|
* completes.
|
|
209
212
|
*
|
|
210
|
-
* Carries the identifiers needed for stream endpoints
|
|
211
|
-
* result as a promise.
|
|
213
|
+
* Carries the identifiers needed for stream endpoints.
|
|
212
214
|
*/
|
|
213
215
|
export interface RunHandle {
|
|
214
216
|
readonly continuationToken: string;
|
|
215
217
|
readonly events: ReadableStream<HandleMessageStreamEvent>;
|
|
216
|
-
readonly result: Promise<RunResult>;
|
|
217
218
|
/**
|
|
218
|
-
* Runtime-owned identifier for this session.
|
|
219
|
-
*
|
|
220
|
-
* Used for stream and inspection APIs. Workflow-backed runs expose
|
|
221
|
-
* the workflow run id; continuous runs mint an in-memory session id
|
|
222
|
-
* when the run starts.
|
|
219
|
+
* Runtime-owned identifier for this session. Used for stream and
|
|
220
|
+
* inspection APIs — workflow-backed runs expose the workflow run id.
|
|
223
221
|
*/
|
|
224
222
|
readonly sessionId: string;
|
|
225
223
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import{i as e,t}from"./chunk-8L7ocgPr.js";import{_ as n,f as r,g as i,l as a,p as o,v as s}from"./types-MZUhN0Zy.js";import{n as c,r as l,t as u}from"./token-util-CHjOk3A7.js";var d=class extends Error{status;body;constructor(e,t){super(t||`Server returned ${e}.`),this.name=`ClientError`,this.status=e,this.body=t}};function f(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*p(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
3
|
`)}}let e=r.trim();e.length>0&&(yield JSON.parse(e))}finally{t.releaseLock()}}function m(e,t,n){let r=t.startsWith(`/`)?t:`/${t}`,i=_(n);if(h(e)){let t=new URL(e);return t.pathname=`${g(t.pathname)}${r}`,t.search=i,t.hash=``,t.toString()}return`${g(e)}${r}${i}`}function h(e){return/^[a-z][a-z\d+\-.]*:/i.test(e)}function g(e){return e===`/`?``:e.endsWith(`/`)?e.slice(0,-1):e}function _(e){return!e||Object.keys(e).length===0?``:`?${new URLSearchParams(e).toString()}`}async function*v(e){let t=e.startIndex,n=e.maxReconnectAttempts;for(;;){let r=m(e.host,s(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 d(a.status,e)}if(!a.body)throw new d(a.status,`Response body is null.`);let o=!1;try{for await(let e of p(a.body))t+=1,yield e}catch(e){if(!f(e))throw e;o=!0}if(!o||n<=0)return;--n}}var y=t(((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?.()??{}}})),b=t(((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},u=e=>c(r({},`__esModule`,{value:!0}),e),d={};s(d,{getVercelOidcToken:()=>m,getVercelOidcTokenSync:()=>h}),n.exports=u(d);var f=y(),p=l();async function m(t){let n=``,r;try{n=h()}catch(e){r=e}try{let[{getTokenPayload:r,isExpired:i},{refreshToken:a}]=await Promise.all([await import(`./token-util-CHjOk3A7.js`).then(t=>e(t.t())),await import(`./token-DtoyQZy2.js`).then(t=>e(t.default))]);(!n||i(r(n),t?.expirationBufferMs))&&(await a(t),n=h())}catch(e){let t=r instanceof Error?r.message:``;throw e instanceof Error&&(t=`${t}
|
|
4
|
-
${e.message}`),t?new p.VercelOidcTokenError(t):e}return n}function h(){let e=(0,f.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}})),x=t(((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},l=e=>s(n({},`__esModule`,{value:!0}),e),d={};o(d,{AccessTokenMissingError:()=>m.AccessTokenMissingError,RefreshAccessTokenFailedError:()=>m.RefreshAccessTokenFailedError,getContext:()=>p.getContext,getVercelOidcToken:()=>f.getVercelOidcToken,getVercelOidcTokenSync:()=>f.getVercelOidcTokenSync,getVercelToken:()=>h.getVercelToken}),t.exports=l(d);var f=b(),p=y(),m=c(),h=u()})),S=x();const C=`${i}/`,w=new Set([`localhost`,`127.0.0.1`,`0.0.0.0`,`::1`,`[::1]`]);function T(e){return w.has(e.hostname)}const E=`x-vercel-protection-bypass`,D=`x-vercel-trusted-oidc-idp-token`;function O(e){return e.pathname.endsWith(`/ash/v1`)||e.pathname.includes(C)}async function k(e){let t=A(e),n=await M(t,e.resourceUrl);return n!==null&&j(t,n),t}function A(e){let t=new Headers(F(e.headers)),n=process.env.VERCEL_AUTOMATION_BYPASS_SECRET?.trim();return n&&O(e.resourceUrl)&&t.set(E,n),t}function j(e,t){e.has(`authorization`)||e.set(`authorization`,`Bearer ${t}`),e.set(D,t)}async function M(e,t){return N(t)?e.get(`x-vercel-oidc-token`)?.trim()||await P():null}function N(e){return!(!O(e)||T(e))}async function P(){let e=process.env.VERCEL_OIDC_TOKEN?.trim();try{let e=(await(0,S.getVercelOidcToken)()).trim();if(e.length>0)return e}catch{return e??null}return e??null}function F(e){if(e!==void 0)return e instanceof Headers?e:Array.isArray(e)?e.map(([e,t])=>[e,t]):e}function I(){return{streamIndex:0}}function L(e){let t=B(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}:I()}function R(e){let t;for(let n of e)V(n)&&(t=n.data.message??void 0);return t}function z(e){let t=B(e);return t?.type===`session.waiting`?`waiting`:t?.type===`session.failed`?`failed`:`completed`}function B(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(n!==void 0&&a(n))return n}}function V(e){return e.type===`message.completed`&&e.data.finishReason!==`tool-calls`}var H=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:R(e),sessionId:this.sessionId,status:z(e)}}[Symbol.asyncIterator](){if(this.#e)throw Error(`MessageResponse has already been consumed.`);return this.#e=!0,this.#t()}},U=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 H({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 v({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,i){let a=t.sessionId?n(t.sessionId):r,o=m(this.#e.host,a),s=await this.#e.resolveHeaders(i?.headers);s.set(`content-type`,`application/json`);let c=W({input:e,session:t});if(c===null)throw Error(`Session.send requires a non-empty message, inputResponses, or both.`);let l=await fetch(o,{body:JSON.stringify(c),headers:s,method:`POST`,signal:i?.signal??null});if(!l.ok){let e=await l.text();throw new d(l.status,e)}let u=await l.json(),f=(typeof u.sessionId==`string`?u.sessionId:void 0)??l.headers.get(`x-ash-session-id`)?.trim()??t.sessionId;if(!f)throw Error(`Message route did not return a session id.`);return{continuationToken:typeof u.continuationToken==`string`?u.continuationToken:void 0,sessionId:f}}async*#r(e,t,n,r){let i=[];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 p(n))if(i.push(e),t+=1,yield e,a(e)){s=!0;break}}catch(e){if(!f(e))throw e}if(s||o<=0)break;--o}}finally{this.#t=L({continuationToken:t,events:i,sessionId:e,session:n})}}async#i(e,t,n){let r=m(this.#e.host,s(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 d(a.status,e)}if(!a.body)throw new d(a.status,`Response body is null.`);return a.body}};function W(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.session.continuationToken!==void 0&&(t.continuationToken=e.session.continuationToken),Object.keys(t).length===0||e.session.continuationToken===void 0&&t.message===void 0||`continuationToken`in t&&Object.keys(t).length===1?null:t}var G=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=m(this.#n,o),t=await this.#i(),n=await fetch(e,{headers:t});if(!n.ok){let e=await n.text();throw new d(n.status,e)}return await n.json()}session(e){let t;return t=typeof e==`string`?{continuationToken:e,streamIndex:0}:e||I(),new U({host:this.#n,maxReconnectAttempts:this.#r,resolveHeaders:e=>this.#i(e)},t)}async#i(e){let t=new Headers,n=await q(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 K(e.bearer)).trim();return t.length===0?void 0:`Bearer ${t}`}if(`basic`in e){let t=await K(e.basic.password);return`Basic ${J(e.basic.username,t)}`}}}};async function K(e){return typeof e==`function`?e():e}async function q(e){return e===void 0?{}:typeof e==`function`?await e():e}function J(e,t){let n=new TextEncoder().encode(`${e}:${t}`),r=Array.from(n,e=>String.fromCodePoint(e)).join(``);return btoa(r)}export{x as a,k as i,E as n,v as o,D as r,d as s,G as t};
|
|
4
|
+
${e.message}`),t?new p.VercelOidcTokenError(t):e}return n}function h(){let e=(0,f.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}})),x=t(((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},l=e=>s(n({},`__esModule`,{value:!0}),e),d={};o(d,{AccessTokenMissingError:()=>m.AccessTokenMissingError,RefreshAccessTokenFailedError:()=>m.RefreshAccessTokenFailedError,getContext:()=>p.getContext,getVercelOidcToken:()=>f.getVercelOidcToken,getVercelOidcTokenSync:()=>f.getVercelOidcTokenSync,getVercelToken:()=>h.getVercelToken}),t.exports=l(d);var f=b(),p=y(),m=c(),h=u()})),S=x();const C=`${i}/`,w=new Set([`localhost`,`127.0.0.1`,`0.0.0.0`,`::1`,`[::1]`]);function T(e){return w.has(e.hostname)}const E=`x-vercel-protection-bypass`,D=`x-vercel-trusted-oidc-idp-token`;function O(e){return e.pathname.endsWith(`/ash/v1`)||e.pathname.includes(C)}async function k(e){let t=A(e),n=await M(t,e.resourceUrl);return n!==null&&j(t,n),t}function A(e){let t=new Headers(F(e.headers)),n=process.env.VERCEL_AUTOMATION_BYPASS_SECRET?.trim();return n&&O(e.resourceUrl)&&t.set(E,n),t}function j(e,t){e.has(`authorization`)||e.set(`authorization`,`Bearer ${t}`),e.set(D,t)}async function M(e,t){return N(t)?e.get(`x-vercel-oidc-token`)?.trim()||await P():null}function N(e){return!(!O(e)||T(e))}async function P(){let e=process.env.VERCEL_OIDC_TOKEN?.trim();try{let e=(await(0,S.getVercelOidcToken)()).trim();if(e.length>0)return e}catch{return e??null}return e??null}function F(e){if(e!==void 0)return e instanceof Headers?e:Array.isArray(e)?e.map(([e,t])=>[e,t]):e}function I(){return{streamIndex:0}}function L(e){let t=B(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}:I()}function R(e){let t;for(let n of e)V(n)&&(t=n.data.message??void 0);return t}function z(e){let t=B(e);return t?.type===`session.waiting`?`waiting`:t?.type===`session.failed`?`failed`:`completed`}function B(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(n!==void 0&&a(n))return n}}function V(e){return e.type===`message.completed`&&e.data.finishReason!==`tool-calls`}var H=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:R(e),sessionId:this.sessionId,status:z(e)}}[Symbol.asyncIterator](){if(this.#e)throw Error(`MessageResponse has already been consumed.`);return this.#e=!0,this.#t()}},U=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 H({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 v({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,i){let a=t.sessionId?n(t.sessionId):r,o=m(this.#e.host,a),s=await this.#e.resolveHeaders(i?.headers);s.set(`content-type`,`application/json`);let c=W({input:e,session:t});if(c===null)throw Error(`Session.send requires a non-empty message, inputResponses, or both.`);let l=await fetch(o,{body:JSON.stringify(c),headers:s,method:`POST`,signal:i?.signal??null});if(!l.ok){let e=await l.text();throw new d(l.status,e)}let u=await l.json(),f=(typeof u.sessionId==`string`?u.sessionId:void 0)??l.headers.get(`x-ash-session-id`)?.trim()??t.sessionId;if(!f)throw Error(`Message route did not return a session id.`);return{continuationToken:typeof u.continuationToken==`string`?u.continuationToken:void 0,sessionId:f}}async*#r(e,t,n,r){let i=[];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 p(n))if(i.push(e),t+=1,yield e,a(e)){s=!0;break}}catch(e){if(!f(e))throw e}if(s||o<=0)break;--o}}finally{this.#t=L({continuationToken:t,events:i,sessionId:e,session:n})}}async#i(e,t,n){let r=m(this.#e.host,s(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 d(a.status,e)}if(!a.body)throw new d(a.status,`Response body is null.`);return a.body}};function W(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||`continuationToken`in t&&Object.keys(t).length===1?null:t}var G=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=m(this.#n,o),t=await this.#i(),n=await fetch(e,{headers:t});if(!n.ok){let e=await n.text();throw new d(n.status,e)}return await n.json()}session(e){let t;return t=typeof e==`string`?{continuationToken:e,streamIndex:0}:e||I(),new U({host:this.#n,maxReconnectAttempts:this.#r,resolveHeaders:e=>this.#i(e)},t)}async#i(e){let t=new Headers,n=await q(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 K(e.bearer)).trim();return t.length===0?void 0:`Bearer ${t}`}if(`basic`in e){let t=await K(e.basic.password);return`Basic ${J(e.basic.username,t)}`}}}};async function K(e){return typeof e==`function`?e():e}async function q(e){return e===void 0?{}:typeof e==`function`?await e():e}function J(e,t){let n=new TextEncoder().encode(`${e}:${t}`),r=Array.from(n,e=>String.fromCodePoint(e)).join(``);return btoa(r)}export{x as a,k as i,E as n,v as o,D as r,d as s,G as t};
|