eve 0.11.3 → 0.11.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +1 -1
  3. package/dist/src/cli/banner.d.ts +0 -1
  4. package/dist/src/cli/banner.js +1 -1
  5. package/dist/src/cli/commands/init.js +1 -1
  6. package/dist/src/cli/dev/tui/agent-header.js +1 -1
  7. package/dist/src/cli/dev/tui/setup-issues.js +1 -1
  8. package/dist/src/compiled/.vendor-stamp.json +1 -1
  9. package/dist/src/compiled/@ai-sdk/anthropic/index.js +1 -1
  10. package/dist/src/compiled/@ai-sdk/google/index.js +1 -1
  11. package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
  12. package/dist/src/compiled/@ai-sdk/openai/index.js +1 -1
  13. package/dist/src/compiled/@ai-sdk/otel/index.js +1 -1
  14. package/dist/src/compiled/@workflow/core/capabilities.d.ts +3 -0
  15. package/dist/src/compiled/@workflow/core/index.js +2 -2
  16. package/dist/src/compiled/@workflow/core/private.js +1 -1
  17. package/dist/src/compiled/@workflow/core/runtime/start.d.ts +11 -1
  18. package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +6 -0
  19. package/dist/src/compiled/@workflow/core/runtime.js +19 -19
  20. package/dist/src/compiled/@workflow/core/serialization/codec.d.ts +16 -0
  21. package/dist/src/compiled/@workflow/core/serialization/compression.d.ts +104 -0
  22. package/dist/src/compiled/@workflow/core/serialization/index.d.ts +7 -6
  23. package/dist/src/compiled/@workflow/core/serialization/types.d.ts +4 -0
  24. package/dist/src/compiled/@workflow/core/serialization-format.d.ts +15 -0
  25. package/dist/src/compiled/@workflow/core/serialization.d.ts +8 -7
  26. package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +24 -0
  27. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  28. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  29. package/dist/src/compiled/@workflow/errors/index.js +1 -1
  30. package/dist/src/compiled/_chunks/workflow/{attribute-changes-Db-CKuLh.js → attribute-changes-Bi5DLT8S.js} +11 -11
  31. package/dist/src/compiled/_chunks/workflow/chunk-BHKSVoKr.js +1 -0
  32. package/dist/src/compiled/_chunks/workflow/coerce-B-Ro4Nfe.js +1 -0
  33. package/dist/src/compiled/_chunks/workflow/{compat-CG1hDp-3.js → compat-DLpWymPP.js} +1 -1
  34. package/dist/src/compiled/_chunks/workflow/{core-5Woff_dW.js → core-CXJbIkCL.js} +1 -1
  35. package/dist/src/compiled/_chunks/workflow/{dist-DhA2lbtB.js → dist-DTchiX0N.js} +1 -1
  36. package/dist/src/compiled/_chunks/workflow/{dist-DvHFhSJM.js → dist-Dxrjttr2.js} +1 -1
  37. package/dist/src/compiled/_chunks/workflow/{dist-aOKD_2KN.js → dist-FLIfyJ4Y.js} +1 -1
  38. package/dist/src/compiled/_chunks/workflow/{functions-DuPjIvMH.js → functions-CnVBREsg.js} +1 -1
  39. package/dist/src/compiled/_chunks/workflow/resume-hook-CKTw-lb5.js +1 -0
  40. package/dist/src/compiled/_chunks/workflow/run-XM8dTRAo.js +1 -0
  41. package/dist/src/compiled/_chunks/workflow/{schemas-DWOIBELG.js → schemas-iG9Z4s4o.js} +1 -1
  42. package/dist/src/compiled/_chunks/workflow/{sleep-BG6X2Bli.js → sleep-DPjVkRY-.js} +1 -1
  43. package/dist/src/compiled/_chunks/workflow/{src-B54rYDvB.js → src-CQuMexnO.js} +1 -1
  44. package/dist/src/compiled/_chunks/workflow/{token-CcaAeZHd.js → token-Bm-WLAUB.js} +1 -1
  45. package/dist/src/compiled/_chunks/workflow/{token-nK4u-N7w.js → token-J7YP0s9a.js} +1 -1
  46. package/dist/src/compiled/_chunks/workflow/wrapper-CQmdlFyy.js +6 -0
  47. package/dist/src/compiled/jose/index.js +1 -1
  48. package/dist/src/compiled/zod/index.js +1 -1
  49. package/dist/src/compiled/zod-validation-error/index.js +1 -1
  50. package/dist/src/execution/workflow-entry.js +1 -1
  51. package/dist/src/internal/application/package.js +1 -1
  52. package/dist/src/internal/nitro/host/start-development-server.js +2 -2
  53. package/dist/src/internal/nitro/host/vercel-build-prewarm.js +1 -1
  54. package/dist/src/internal/nitro/routes/info.js +1 -1
  55. package/dist/src/setup/package-manager.d.ts +1 -1
  56. package/dist/src/setup/package-manager.js +1 -1
  57. package/dist/src/setup/scaffold/create/project.js +1 -1
  58. package/docs/agent-config.md +7 -1
  59. package/docs/channels/eve.mdx +1 -1
  60. package/docs/concepts/execution-model-and-durability.md +6 -0
  61. package/docs/getting-started.mdx +2 -2
  62. package/docs/guides/auth-and-route-protection.md +5 -1
  63. package/docs/guides/deployment.md +84 -14
  64. package/docs/guides/instrumentation.md +7 -7
  65. package/docs/reference/cli.md +1 -1
  66. package/docs/sandbox.mdx +1 -1
  67. package/docs/schedules.mdx +7 -1
  68. package/docs/tutorial/first-agent.mdx +1 -1
  69. package/package.json +3 -3
  70. package/dist/src/compiled/_chunks/workflow/chunk-DSjMdhoD.js +0 -1
  71. package/dist/src/compiled/_chunks/workflow/coerce-BTuSKQr5.js +0 -1
  72. package/dist/src/compiled/_chunks/workflow/resume-hook-Uk1RAmYo.js +0 -1
  73. package/dist/src/compiled/_chunks/workflow/run-AA-FTD_U.js +0 -1
@@ -31,6 +31,8 @@ export default eveChannel({
31
31
  });
32
32
  ```
33
33
 
34
+ `vercelOidc()` is a convenience for Vercel-hosted agents and Vercel-to-Vercel callers, not a requirement. If your app already has users, sessions, API keys, or an identity provider, put that authenticator in the `auth` walk instead. Custom `AuthFn` entries are first-class and can fully replace Vercel OIDC.
35
+
34
36
  ## The ordered auth walk
35
37
 
36
38
  `auth` takes a single `AuthFn` or an array that eve walks in order. Each entry has three possible outcomes:
@@ -64,7 +66,7 @@ export default eveChannel({
64
66
  });
65
67
  ```
66
68
 
67
- Put your own providers ahead of the catch-all helpers. Any entry that doesn't recognize the caller returns `null`, and the walk moves on.
69
+ Put your own providers ahead of the catch-all helpers. Any entry that doesn't recognize the caller returns `null`, and the walk moves on. On non-Vercel hosts, omit `vercelOidc()` unless you specifically want to accept Vercel-issued tokens.
68
70
 
69
71
  To reject with a precise status instead of skipping, throw:
70
72
 
@@ -201,6 +203,8 @@ export default eveChannel({
201
203
 
202
204
  In production, `placeholderAuth()` returns a structured `401` so a generated web chat app can say "auth isn't configured yet" instead of throwing an internal error. Replace it before a browser caller submits a production request: swap in your app's `AuthFn` or one of the shipped helpers. Delete the authored channel file entirely and eve falls back to the framework default `[localDev(), vercelOidc()]`, which also rejects production browser traffic.
203
205
 
206
+ You do not have to keep `vercelOidc()` in the final policy. For a self-hosted app, an app-embedded frontend, or any deployment that uses a non-Vercel identity system, use `httpBasic()`, `jwtHmac()`, `jwtEcdsa()`, generic `oidc()`, or a custom `AuthFn` that maps your verified user/session/API key into a `SessionAuthContext`.
207
+
204
208
  Keep secret values (`ROUTE_AUTH_BASIC_PASSWORD`, signing keys) in environment variables. Route-auth secrets never land in compiled artifacts. The runtime re-materializes them from the authored channel definition at boot.
205
209
 
206
210
  ## What reaches `ctx.session.auth`
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  title: "Deployment"
3
- description: "A production checklist for shipping an eve agent on Vercel, covering build output, env and secrets, sandbox backend, prewarm, auth, deploy, and verify."
3
+ description: "A production checklist for shipping an eve agent on Vercel or your own host, covering build output, env and secrets, sandbox backend, auth, deploy, and verify."
4
4
  ---
5
5
 
6
- eve runs the same way locally and on Vercel, so taking an agent from `eve dev` to production is mostly mechanical. Work through this checklist in order.
6
+ eve runs the same way locally, on Vercel, and on a long-running Node host, so taking an agent from `eve dev` to production is mostly mechanical. Work through this checklist in order.
7
7
 
8
8
  ## 1. Build
9
9
 
@@ -13,18 +13,59 @@ eve runs the same way locally and on Vercel, so taking an agent from `eve dev` t
13
13
  eve build
14
14
  ```
15
15
 
16
- When `VERCEL` is set (every hosted Vercel build sets it), `eve build` writes the Vercel output bundle under `.vercel/output`. A plain local `eve build` skips that bundle. Either way you get eve's compiled framework artifacts under `.eve/`, including the discovery manifest, compiled manifest, diagnostics, and module map. Open those to see which authored surface a deployment will load. For the artifact guide and what to do when `eve build` fails, see [Observability](./instrumentation).
16
+ When `VERCEL` is set (every hosted Vercel build sets it), `eve build` writes the [Vercel Build Output](https://vercel.com/docs/build-output-api) bundle under `.vercel/output`. A plain local `eve build` skips that bundle. Either way you get eve's compiled framework artifacts under `.eve/`, including the discovery manifest, compiled manifest, diagnostics, and module map. Open those to see which authored surface a deployment will load. For the artifact guide and what to do when `eve build` fails, see [Observability](./instrumentation).
17
+
18
+ ### How portability works
19
+
20
+ Nitro is the HTTP host layer. It gives eve a build artifact that can serve the health, session, stream, channel, callback, and schedule routes outside the dev server. Workflow execution and sandbox execution are separate runtime adapters; they are not hidden Vercel dependencies inside Nitro.
21
+
22
+ On Vercel, eve emits Vercel Build Output, the Workflow SDK runs on Vercel Workflow, and `defaultBackend()` selects Vercel Sandbox. Outside Vercel, `eve start` serves the standard Nitro Node output, the Workflow SDK uses its local world by default, and `defaultBackend()` selects a local sandbox backend in availability order. That local workflow world persists run state on disk and has no direct coupling to Vercel; Vercel-only behavior such as latest-deployment routing and dashboard run attributes is additive.
23
+
24
+ Eve does not expose Workflow world selection as a public app API today. Future releases will let advanced deployments provide a different Workflow world, the SDK abstraction for workflow state, queues, auth, and streaming; see [Workflow Worlds](https://workflow-sdk.dev/worlds) for the underlying concept.
17
25
 
18
26
  ## 2. Environment variables and secrets
19
27
 
20
- Set these in your Vercel project's environment variables, never in source or compiled artifacts:
28
+ Set these in your deployment environment or secret manager, never in source or compiled artifacts:
21
29
 
22
- - **A model credential.** The lowest-setup option is the Vercel AI Gateway. Link a Vercel project, and gateway model ids like `anthropic/claude-opus-4.8` authenticate through Vercel OIDC, with no provider keys to manage. To call a provider directly instead, set its key (for example `OPENAI_API_KEY`).
30
+ - **A model credential.** The lowest-setup Vercel option is the Vercel AI Gateway. Link a Vercel project, and gateway model ids like `anthropic/claude-opus-4.8` authenticate through Vercel OIDC, with no provider keys to manage. Outside Vercel, either set `AI_GATEWAY_API_KEY` for gateway-routed models or configure a direct provider model with an [AI SDK provider package](https://ai-sdk.dev/docs/foundations/providers-and-models) and set that provider's key, for example `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`.
23
31
  - **Route-auth secrets**, for example `ROUTE_AUTH_BASIC_PASSWORD` and any JWT/OIDC signing keys referenced by your channel's `auth` (see [Auth and route protection](./auth-and-route-protection)).
24
32
 
25
33
  Route-auth secrets are never serialized into the compiled discovery or module-map artifacts. The runtime re-materializes them from the authored channel definition instead. If your deployment sits behind Vercel preview protection and you want to drive it with `eve dev`, set `VERCEL_AUTOMATION_BYPASS_SECRET` locally before launching.
26
34
 
27
- ## 3. Sandbox backend
35
+ ## 3. Model routing
36
+
37
+ The shape of `model` in `agent/agent.ts` decides whether eve calls the Vercel AI Gateway or a provider endpoint directly.
38
+
39
+ A string model id is gateway-routed:
40
+
41
+ ```ts title="agent/agent.ts"
42
+ import { defineAgent } from "eve";
43
+
44
+ export default defineAgent({
45
+ model: "anthropic/claude-opus-4.8",
46
+ });
47
+ ```
48
+
49
+ That works on Vercel with project OIDC or anywhere else with `AI_GATEWAY_API_KEY`. Passing a provider key through `modelOptions.providerOptions.gateway.byok` also still sends the request through the Gateway; it only changes which upstream key the Gateway uses.
50
+
51
+ To avoid the Gateway entirely, install the [AI SDK package](https://ai-sdk.dev/docs/foundations/providers-and-models) for the provider you want to call, pass that provider's model object, and set that provider's normal environment variable:
52
+
53
+ ```bash
54
+ npm install @ai-sdk/anthropic
55
+ ```
56
+
57
+ ```ts title="agent/agent.ts"
58
+ import { anthropic } from "@ai-sdk/anthropic";
59
+ import { defineAgent } from "eve";
60
+
61
+ export default defineAgent({
62
+ model: anthropic("claude-opus-4.8"),
63
+ });
64
+ ```
65
+
66
+ With that shape, the model call goes directly to Anthropic and the runtime reads `ANTHROPIC_API_KEY`. The same pattern works for OpenAI after installing `@ai-sdk/openai`, using `openai("...")`, and setting `OPENAI_API_KEY`. This is the usual choice when self-deploying without any Vercel-managed services.
67
+
68
+ ## 4. Sandbox backend
28
69
 
29
70
  On Vercel, the [sandbox](../sandbox) runs on hosted [Vercel Sandbox](https://vercel.com/docs/sandbox) infrastructure. Attach the backend on the sandbox definition:
30
71
 
@@ -39,7 +80,9 @@ export default defineSandbox({
39
80
 
40
81
  Leave `backend` off and eve falls back to `defaultBackend()`, which picks the Vercel backend on hosted builds and the local backend everywhere else. One definition, both environments.
41
82
 
42
- ## 4. Build-time sandbox prewarm
83
+ For a self-deployed process, leave `defaultBackend()` in place or choose an explicit non-Vercel backend such as Docker or microsandbox. If those do not match your infrastructure, write a custom `SandboxBackend` adapter that creates sessions in your own container, VM, or isolation service. Do not pin `vercel()` unless that process should create hosted Vercel sandboxes.
84
+
85
+ ## 5. Build-time sandbox prewarm
43
86
 
44
87
  During hosted builds, eve prewarms reusable Vercel sandbox templates so the first session doesn't pay the cold-start cost:
45
88
 
@@ -51,11 +94,15 @@ During hosted builds, eve prewarms reusable Vercel sandbox templates so the firs
51
94
  - Prewarming only covers template construction. `onSession()` still runs at runtime, once per session.
52
95
  - **If build-time prewarm fails, the build fails.**
53
96
 
54
- ## 5. Auth
97
+ If `VERCEL` is set but `VERCEL_DEPLOYMENT_ID` is missing, eve warns that it skipped prewarming. Do not deploy that build with `vercel deploy --prebuilt`; its output may reference sandbox templates that were never provisioned. Run `vercel deploy` instead so Vercel builds the source in its hosted build environment.
55
98
 
56
- Swap any scaffolded `placeholderAuth()` for your real policy before the first production browser request hits the app. Both the framework default and the placeholder reject production browser traffic, so an unconfigured app fails closed rather than serving open routes. See [Auth and route protection](./auth-and-route-protection) for the ordered auth walk and the fail-closed guarantee.
99
+ ## 6. Auth
57
100
 
58
- ## 6. Deploy on Vercel
101
+ Swap any scaffolded `placeholderAuth()` for your real policy before the first production browser request hits the app. Both the framework default and the placeholder reject production browser traffic, so an unconfigured app fails closed rather than serving open routes. The production policy can be a shipped helper (`httpBasic()`, `jwtHmac()`, `jwtEcdsa()`, `oidc()`, `vercelOidc()`) or a custom `AuthFn` that validates your own sessions, API keys, or identity provider. See [Auth and route protection](./auth-and-route-protection) for the ordered auth walk and the fail-closed guarantee.
102
+
103
+ If you self-deploy outside Vercel, do not rely on `vercelOidc()` as the only production authenticator. Use your own route policy, such as Basic auth, JWT/OIDC verification for your identity provider, or a custom verifier.
104
+
105
+ ## 7. Deploy on Vercel
59
106
 
60
107
  Deploy with the [Vercel CLI](https://vercel.com/docs/cli) or by pushing to a Git-connected project:
61
108
 
@@ -65,7 +112,30 @@ vercel deploy
65
112
 
66
113
  The deployed app serves the same stable health, session, and stream routes you've been hitting locally.
67
114
 
68
- ## 7. Verify the deployment
115
+ ## 8. Deploy without Vercel
116
+
117
+ eve can also run as a normal Node service behind your own process manager, container platform, or reverse proxy:
118
+
119
+ ```bash
120
+ eve build
121
+ PORT=3000 eve start --host 0.0.0.0
122
+ ```
123
+
124
+ Eve writes the standard Nitro output under `.output/` instead of Vercel Build Output. `eve start` serves that built app and respects `PORT`, or the `--port` flag. Put TLS, routing, autoscaling, and log collection around that process the same way you would for any other Node HTTP service.
125
+
126
+ Self-deployed agents should make the Vercel-specific choices explicit:
127
+
128
+ - Let the Workflow SDK use its default local world, which stores workflow state under `.workflow-data`, or configure your host so that directory is on persistent storage.
129
+ - Install the AI SDK package for your provider, then use a direct provider model object and `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` when you want no Gateway dependency.
130
+ - Use `AI_GATEWAY_API_KEY` if you still want Gateway routing from a non-Vercel host.
131
+ - Replace `vercelOidc()` with auth that your host can verify.
132
+ - Use `defaultBackend()`, a pinned non-Vercel sandbox backend such as Docker or microsandbox, or your own `SandboxBackend` adapter.
133
+ - If the agent defines schedules, the default `eve build && eve start` path starts Nitro's schedule runner, and Vercel wires schedules to Vercel Cron automatically. If you adapt the output to a custom HTTP-only host or preset, make sure it also runs Nitro scheduled tasks, or trigger the same work from your own scheduler.
134
+ - Treat Vercel Cron, Vercel Sandbox prewarm, Vercel Deployment Protection bypass, and the Agent Runs dashboard as Vercel-only conveniences.
135
+
136
+ The HTTP contract is unchanged: health, session creation, streaming, channels, tools, and subagents use the same routes. Any client that can reach and authenticate to those routes can talk to the agent.
137
+
138
+ ## 9. Verify the deployment
69
139
 
70
140
  Smoke-test the live routes. Health first:
71
141
 
@@ -110,11 +180,11 @@ You can deploy an eve app on its own, or mount it inside a host web framework th
110
180
  ## Checklist
111
181
 
112
182
  - [ ] `eve build` succeeds, and writes `.vercel/output` when `VERCEL` is set.
113
- - [ ] Provider keys and route-auth secrets are set in Vercel env vars.
183
+ - [ ] Provider keys and route-auth secrets are set in the deployment environment.
114
184
  - [ ] The sandbox backend matches the environment (`vercel()` or `defaultBackend()`).
115
- - [ ] Build-time prewarm reused or built templates without failing.
185
+ - [ ] On Vercel, build-time prewarm reused or built templates without failing.
116
186
  - [ ] `placeholderAuth()` is replaced with your real policy.
117
- - [ ] `vercel deploy` succeeds.
187
+ - [ ] `vercel deploy` succeeds, or your self-hosted process starts with `eve start`.
118
188
  - [ ] The health, session, and stream routes respond on the deployment URL.
119
189
 
120
190
  ## What to read next
@@ -157,13 +157,13 @@ When `eve build` fails on discovery errors, the CLI prints the full diagnostics
157
157
 
158
158
  ### Common failures
159
159
 
160
- | Symptom | Likely cause and fix |
161
- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
162
- | Tool not discovered (the model never sees it) | Run `eve info`. Confirm the file is in the right slot (`agent/tools/<name>.ts`) and default-exports `defineTool(...)`, and check `.eve/diagnostics.json` for shape errors. `schedules/` are root-only. |
163
- | Model won't call a tool it should | Tighten the tool `description` and `inputSchema`; put procedural guidance in a [skill](../skills), not the description. Confirm it's in the active set with `eve info`. |
164
- | Stuck on `session.waiting` | The turn is parked on an approval, a question, or a connection sign-in. Answer it, or POST a follow-up with the `continuationToken` (a stale token is rejected). |
165
- | 401 on production routes | Expected: auth fails closed. Replace `placeholderAuth()`, and set `VERCEL_PROJECT_ID` and environment so `vercelOidc()` accepts user tokens. See [Auth and route protection](./auth-and-route-protection). |
166
- | Build fails with discovery errors | Read the printed diagnostics and `.eve/diagnostics.json`; confirm the root-vs-subagent boundary is valid and secrets come from env vars. |
160
+ | Symptom | Likely cause and fix |
161
+ | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
162
+ | Tool not discovered (the model never sees it) | Run `eve info`. Confirm the file is in the right slot (`agent/tools/<name>.ts`) and default-exports `defineTool(...)`, and check `.eve/diagnostics.json` for shape errors. `schedules/` are root-only. |
163
+ | Model won't call a tool it should | Tighten the tool `description` and `inputSchema`; put procedural guidance in a [skill](../skills), not the description. Confirm it's in the active set with `eve info`. |
164
+ | Stuck on `session.waiting` | The turn is parked on an approval, a question, or a connection sign-in. Answer it, or POST a follow-up with the `continuationToken` (a stale token is rejected). |
165
+ | 401 on production routes | Expected: auth fails closed. Replace `placeholderAuth()` with your route policy. Use `vercelOidc()` only for Vercel-issued tokens; otherwise configure `httpBasic()`, JWT/OIDC helpers, or a custom `AuthFn`. See [Auth and route protection](./auth-and-route-protection). |
166
+ | Build fails with discovery errors | Read the printed diagnostics and `.eve/diagnostics.json`; confirm the root-vs-subagent boundary is valid and secrets come from env vars. |
167
167
 
168
168
  ## What to read next
169
169
 
@@ -35,7 +35,7 @@ The optional `target` decides the mode:
35
35
  - An existing directory, including `.` for the current one (`eve init .`), adds an agent to that project. The project needs a `package.json`, the `agent/` files must not exist yet, and the missing `eve`, `ai`, and `zod` dependencies are added without touching anything else.
36
36
  - Omitting the target scaffolds or updates the current directory, the same as `eve init .`.
37
37
 
38
- Either mode installs dependencies, initializes Git, and runs `eve dev` through the project's package manager.
38
+ Either mode installs dependencies, initializes Git, and runs `eve dev` through the detected project package manager. Fresh projects inherit a parent workspace manager when one is present; otherwise they use the manager that launched `eve init`.
39
39
 
40
40
  | Flag | Type | Default | Description |
41
41
  | ---------------------- | ---- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
package/docs/sandbox.mdx CHANGED
@@ -157,7 +157,7 @@ export default defineSandbox({
157
157
 
158
158
  `justbash()` needs no daemon or VM, but commands run in a simulated bash with a virtual filesystem under `.eve/sandbox-cache/`, with no real binaries (`git`, `node`, package managers) and no network isolation. The `just-bash` package is an optional peer dependency, so `eve dev` installs it into your application automatically when missing (disable with `autoInstall: false`); production processes fail with an actionable install error instead.
159
159
 
160
- You can also write your own backend. A `SandboxBackend` is an object with a `name`, a `create`, and an optional `prewarm`. See the `SandboxBackend*` types on `eve/sandbox`.
160
+ You can also write your own backend. A `SandboxBackend` is an adapter object with a `name`, a `create`, and an optional `prewarm`. It can point at your own container runner, VM pool, internal sandbox service, or another isolation layer, as long as it returns the `SandboxSession` operations eve needs. See the `SandboxBackend*` types on `eve/sandbox`.
161
161
 
162
162
  ## Lifecycle
163
163
 
@@ -27,7 +27,7 @@ interface ScheduleHandlerArgs {
27
27
 
28
28
  `defineSchedule` is a type-level pass-through. The compiler is what enforces the one-of rule.
29
29
 
30
- `cron` is a standard 5-field string (`minute hour day-of-month month day-of-week`) with minute granularity. On Vercel, each schedule becomes a Vercel Cron Job, and Vercel evaluates the expression in UTC, so `"0 9 * * 1-5"` fires at 09:00 UTC on weekdays. `eve dev` never fires schedules on their cron cadence. To trigger one while iterating, use the dispatch route below.
30
+ `cron` is a standard 5-field string (`minute hour day-of-month month day-of-week`) with minute granularity. On Vercel, each schedule becomes a Vercel Cron Job, and Vercel evaluates the expression in UTC, so `"0 9 * * 1-5"` fires at 09:00 UTC on weekdays. `eve dev` never fires schedules on their cron cadence. A built app served with `eve start` does run production scheduled tasks. To trigger one while iterating in dev, use the dispatch route below.
31
31
 
32
32
  ## Markdown form (fire-and-forget)
33
33
 
@@ -100,6 +100,12 @@ The route is dev-only. Production builds never mount it, and it needs no auth si
100
100
 
101
101
  Hosted Vercel builds turn every `defineSchedule(...)` into a Vercel Cron Job, with each `cron` written as an entry in `.vercel/output/config.json`. Vercel evaluates these expressions in UTC. Confirm discovery under **Settings → Cron Jobs** and watch execution history under **Observability → Cron Jobs**. Per-run logs land under **Observability → Logs**.
102
102
 
103
+ ## Self-deployed hosts
104
+
105
+ Production builds register schedules as Nitro scheduled tasks. On Vercel, Nitro's Vercel preset wires those task registrations into Vercel Cron for you. Outside Vercel, the standard `eve build && eve start` path serves Nitro's Node output and starts Nitro's schedule runner, so the tasks fire on their cron cadence while that process is running.
106
+
107
+ The gotcha is custom hosting. If you adapt the generated output to a process manager, container platform, or Nitro preset that only serves HTTP and does not start Nitro's scheduled task runner, the schedule definitions still compile, but they will not fire automatically. In that case, run eve through `eve start`, use a host that supports Nitro scheduled tasks, or trigger the same work from your own scheduler through an authenticated route, channel handoff, or application-specific job runner. The dev dispatch route above is only for `eve dev`; production builds do not mount it.
108
+
103
109
  ## What to read next
104
110
 
105
111
  - [Channels](./channels/overview): deliver schedule output to users.
@@ -10,7 +10,7 @@ Step 1 gets it talking. The scaffold bundles a small sample dataset, so your fir
10
10
  ## Prerequisites
11
11
 
12
12
  - Node 24 or newer and npm.
13
- - A model credential. The scaffold's default model goes through the [Vercel AI Gateway](../getting-started), so you need `AI_GATEWAY_API_KEY` (or `VERCEL_OIDC_TOKEN` pulled via `vercel link`). A direct provider id like `anthropic/claude-opus-4.8` instead needs that provider's key, here `ANTHROPIC_API_KEY`.
13
+ - A model credential. The scaffold's default model goes through the [Vercel AI Gateway](../getting-started), so you need `AI_GATEWAY_API_KEY` (or `VERCEL_OIDC_TOKEN` pulled via `vercel link`). A direct provider model like `anthropic("claude-opus-4.8")` instead needs that provider's AI SDK package and key, here `@ai-sdk/anthropic` and `ANTHROPIC_API_KEY`.
14
14
 
15
15
  If you have not run eve before, complete [Getting Started](../getting-started) first. Without a credential, "Run the agent" below fails when the runtime tries to reach the model; the dev TUI's `/model` flow walks you through pasting a key or linking a project.
16
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.11.3",
3
+ "version": "0.11.5",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [
@@ -285,10 +285,10 @@
285
285
  "@vercel/detect-agent": "1.2.3",
286
286
  "@vercel/oidc": "3.5.0",
287
287
  "@vercel/sandbox": "2.2.1",
288
- "@workflow/core": "5.0.0-beta.17",
288
+ "@workflow/core": "5.0.0-beta.19",
289
289
  "@workflow/errors": "5.0.0-beta.8",
290
290
  "@workflow/world": "5.0.0-beta.10",
291
- "@workflow/world-local": "5.0.0-beta.18",
291
+ "@workflow/world-local": "5.0.0-beta.19",
292
292
  "ai": "7.0.0-beta.178",
293
293
  "autoevals": "0.0.132",
294
294
  "chat": "4.29.0",
@@ -1 +0,0 @@
1
- import{createRequire as e}from"node:module";var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),c=(e,t)=>{let r={};for(var i in e)n(r,i,{get:e[i],enumerable:!0});return t||n(r,Symbol.toStringTag,{value:`Module`}),r},l=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;l<u;l++)d=c[l],!o.call(e,d)&&d!==a&&n(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},u=(e,r,i)=>(i=e==null?{}:t(a(e)),l(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),d=e(import.meta.url);export{u as i,c as n,d as r,s as t};
@@ -1 +0,0 @@
1
- import{n as e}from"./chunk-DSjMdhoD.js";import{$ as t,et as n,nt as r,rt as i,tt as a}from"./core-5Woff_dW.js";import{$ as o,H as s,a as c,g as l,s as u}from"./schemas-DWOIBELG.js";var d=e({bigint:()=>h,boolean:()=>m,date:()=>g,number:()=>p,string:()=>f});function f(e){return i(o,e)}function p(e){return r(s,e)}function m(e){return n(u,e)}function h(e){return t(c,e)}function g(e){return a(l,e)}export{p as n,d as t};
@@ -1 +0,0 @@
1
- import{n as e}from"./chunk-DSjMdhoD.js";import{n as t,o as n,w as r}from"./dist-DvHFhSJM.js";import{E as i,Gt as a,It as o,Nt as s,Y as c,a as l,cn as u,en as d,fn as f,it as p,m,n as h,nt as g,q as _,r as v,rt as y,y as b,yn as x,z as S}from"./attribute-changes-Db-CKuLh.js";var C=e({getHookByToken:()=>T,resumeHook:()=>E,resumeWebhook:()=>D});async function w(e){let t=await u(),n=await t.hooks.getByToken(e),r=await t.runs.get(n.runId),a=await t.getEncryptionKeyForRun?.(r),o=a?await f(a):void 0;return n.metadata!==void 0&&(n.metadata=await i(n.metadata,n.runId,o)),{hook:n,run:r,encryptionKey:o}}async function T(e){let{hook:t}=await w(e);return t}async function E(e,t,n){return await v(()=>c(`hook.resume`,async r=>{let i=await u();try{let c,u,d;if(typeof e==`string`){let t=await w(e);c=t.hook,u=t.run,d=n??t.encryptionKey}else if(c=e,u=await i.runs.get(c.runId),n)d=n;else{let e=await i.getEncryptionKeyForRun?.(u);d=e?await f(e):void 0}r?.setAttributes({...p(c.token),...y(c.hookId),...o(c.runId)});let g=u.executionContext?.workflowCoreVersion,v=m(typeof g==`string`?g:void 0);v.supportedFormats.has(a.ENCRYPTED)||(d=void 0);let C=[],T=x(c.specVersion),E=await b(t,c.runId,d,C,globalThis,T,v.framedByteStreams);h(Promise.all(C),e=>{e!==void 0&&S.warn(`Background flush of hook payload ops failed`,{workflowRunId:c.runId,hookId:c.hookId,error:e instanceof Error?e.message:String(e)})}),await i.events.create(c.runId,{eventType:`hook_received`,specVersion:4,correlationId:c.hookId,eventData:{...T?{}:{token:c.token},payload:E}},{v1Compat:T}),r?.setAttributes({...s(u.workflowName)});let D=await _(u.executionContext?.traceCarrier);return D&&r?.addLink?.(D),await i.queue(l(u.workflowName),{runId:c.runId,traceCarrier:u.executionContext?.traceCarrier??void 0},{deploymentId:u.deploymentId,specVersion:u.specVersion??1}),c}catch(t){throw r?.setAttributes({...p(typeof e==`string`?e:e.token),...g(!1)}),t}}))}async function D(e,i){let{hook:a,encryptionKey:o}=await w(e);if(a.isWebhook===!1)throw new n(e);let s,c;if(a.metadata&&typeof a.metadata==`object`&&`respondWith`in a.metadata)if(a.metadata.respondWith===`manual`){let{readable:e,writable:t}=new TransformStream;c=e,i[d]=t}else if(a.metadata.respondWith instanceof Response)s=a.metadata.respondWith;else throw new r(`Invalid \`respondWith\` value: ${a.metadata.respondWith}`,{slug:t.WEBHOOK_INVALID_RESPOND_WITH_VALUE});else s=new Response(null,{status:202});if(await E(a,i,o),c){let e=c.getReader(),t=await e.read();t.value&&(s=t.value),e.cancel()}if(!s)throw new r(`Workflow run did not send a response`,{slug:t.WEBHOOK_RESPONSE_NOT_SENT});return s}export{C as i,E as n,D as r,T as t};
@@ -1 +0,0 @@
1
- import{d as e}from"./dist-aOKD_2KN.js";import{C as t,S as n,T as r,b as i,m as a,r as o,w as s,x as c}from"./dist-DvHFhSJM.js";import{A as l,C as u,Dt as d,It as f,J as p,L as m,Lt as h,Nt as g,Pt as _,Q as v,T as y,Y as b,_n as x,a as S,b as C,cn as w,fn as T,k as E,m as D,n as O,on as k,p as A,r as j,s as M,sn as N,t as P,yn as F,z as I}from"./attribute-changes-Db-CKuLh.js";const L=x();async function R(t,n,r){"use step";return await j(()=>{let i=t?.workflowId;if(!i)throw new s(`'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.`,{slug:`start-invalid-workflow-function`});return b(`workflow.start ${e(i)}`,async e=>{e?.setAttributes({...g(i),..._(`start`)});let t=[],a=r??{};Array.isArray(n)?t=n:typeof n==`object`&&(a=n),e?.setAttributes({...d(t.length)});let c=a?.world??await w(),l=await c.getDeploymentId(),u=a.deploymentId??l;if(u===`latest`){if(!c.resolveLatestDeploymentId)throw new s(`deploymentId 'latest' requires a World that implements resolveLatestDeploymentId()`);u=await c.resolveLatestDeploymentId()}let m;m=u===l?!0:typeof c.streams?.get==`function`?D((await M(c,`workflow`,{deploymentId:u,timeout:2e3}).catch(()=>void 0))?.workflowCoreVersion).framedByteStreams:!1;let y=[],b=`wrun_${L()}`,x=await p(),E=a.specVersion??c.specVersion??2,k=F(E),j=a.allowReservedAttributes===!0,N;if(a.attributes&&Object.keys(a.attributes).length>0){if(E<4)throw new s(`Initial workflow attributes require a World that supports spec version 4 or later.`);for(let[e,t]of Object.entries(a.attributes))if(typeof t!=`string`)throw new s(`Initial workflow attribute ${JSON.stringify(e)} must be a string value.`);let e=P(a.attributes,{allowReservedAttributes:j});N=Object.fromEntries(e.map(({key:e,value:t})=>[e,t]))}let R=N?{attributes:N,...j?{allowReservedAttributes:!0}:{}}:{},B=await c.getEncryptionKeyForRun?.(b,{...a,deploymentId:u}),V=B?await T(B):void 0,H=await C(t,b,V,y,globalThis,k,m),U={traceCarrier:x,workflowCoreVersion:A,features:{encryption:!!V}},[W,G]=await Promise.allSettled([c.events.create(b,{eventType:`run_created`,specVersion:E,eventData:{deploymentId:u,workflowName:i,input:H,executionContext:U,...R}},{v1Compat:k}),c.queue(S(i),{runId:b,traceCarrier:x,...E>=3?{runInput:{input:H,deploymentId:u,workflowName:i,specVersion:E,executionContext:U,...R}}:{}},{deploymentId:u,specVersion:E})]);if(G.status===`rejected`)throw G.reason;let K=!1;if(W.status===`rejected`){let e=W.reason;if(!o.is(e))if(z(e))K=!0,I.warn(`Run creation event failed, but the run was accepted via the queue. The run_created event will be re-tried async by the runtime.`,{workflowRunId:b,error:e.message});else throw e}else{let e=W.value;if(!e.run)throw new s(`Missing 'run' in server response for 'run_created' event`);if(!k&&e.run.runId!==b)throw new s(`Server returned different runId than requested: expected ${b}, got ${e.run.runId}`)}return O(Promise.all(y),e=>{I.warn(`Background flush of workflow argument streams failed`,{workflowRunId:b,error:e instanceof Error?e.message:String(e)})}),e?.setAttributes({...f(b),...v(u),...W.status===`fulfilled`&&W.value.run?h(W.value.run.status):{}}),new q(b,{resilientStart:K})})})}function z(e){return!!(a.is(e)||r.is(e)&&e.status&&e.status>=500)}const B=e=>Array.isArray(e)?e:[e];async function V(e,t,n={}){try{let r=await e.runs.get(t,{resolveData:`all`}),i=await e.getEncryptionKeyForRun?.(r),a=i?await T(i):void 0,o=B(await E(r.input,t,a,globalThis)),s=n.specVersion??r.specVersion??1,c=n.deploymentId??r.deploymentId;return(await R({workflowId:r.workflowName},o,{deploymentId:c,world:e,specVersion:s})).runId}catch(e){throw Error(`Failed to recreate run from ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async function H(e,t){try{let n=(await e.runs.get(t,{resolveData:`none`})).specVersion??1,r=F(n),i={eventType:`run_cancelled`,specVersion:n};await e.events.create(t,i,{v1Compat:r})}catch(e){throw Error(`Failed to cancel run ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async function U(e,t){try{let n=await e.runs.get(t,{resolveData:`none`});await e.queue(S(n.workflowName),{runId:t},{deploymentId:n.deploymentId,specVersion:n.specVersion??1})}catch(e){throw Error(`Failed to re-enqueue run ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async function W(e,t,n){try{let r=await e.runs.get(t,{resolveData:`none`}),i=F(r.specVersion),a=[],s=null;do{let n=await e.events.list({runId:t,pagination:{limit:1e3,...s?{cursor:s}:{}},resolveData:`none`});a.push(...n.data),s=n.hasMore?n.cursor:null}while(s);let c=a.filter(e=>e.eventType===`wait_created`),l=new Set(a.filter(e=>e.eventType===`wait_completed`).map(e=>e.correlationId)),u=c.filter(e=>!l.has(e.correlationId));if(n?.correlationIds&&n.correlationIds.length>0){let e=new Set(n.correlationIds);u=u.filter(t=>t.correlationId&&e.has(t.correlationId))}let d=[],f=0;for(let n of u){if(!n.correlationId)continue;let a=i?{eventType:`wait_completed`,correlationId:n.correlationId}:{eventType:`wait_completed`,correlationId:n.correlationId,specVersion:r.specVersion,eventData:{resumeAt:n.eventData.resumeAt}};try{await e.events.create(t,a,{v1Compat:i}),f++}catch(e){o.is(e)?f++:d.push(e instanceof Error?e:Error(String(e)))}}if(f>0&&await e.queue(S(r.workflowName),{runId:t},{deploymentId:r.deploymentId,specVersion:r.specVersion??1}),d.length>0)throw AggregateError(d,`Failed to complete ${d.length}/${u.length} pending wait(s) for run ${t}`);return{stoppedCount:f}}catch(e){throw e instanceof AggregateError?e:Error(`Failed to wake up run ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async function G(e,t,n,r){try{return await e.streams.get(t,n,r?.startIndex)}catch(e){throw Error(`Failed to read stream ${n}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}async function K(e,t){try{return await e.streams.list(t)}catch(e){throw Error(`Failed to list streams for run ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}var q=class e{static[N](e){return{runId:e.runId,resilientStart:e.#r}}static[k](t){return new e(t.runId,{resilientStart:t.resilientStart})}runId;#e;get#t(){return this.#e||=w(),this.#e}#n=null;#r=!1;constructor(e,t){this.runId=e,this.#r=t?.resilientStart??!1}#i(){return this.#n||=(async()=>{let e=await this.#t,t=await e.runs.get(this.runId),n=await e.getEncryptionKeyForRun?.(t);return n?await T(n):void 0})(),this.#n}#a(){return()=>this.#i()}async wakeUp(e){"use step";return W(await this.#t,this.runId,e)}async cancel(){"use step";await(await this.#t).events.create(this.runId,{eventType:`run_cancelled`,specVersion:4})}get exists(){"use step";return this.#t.then(e=>e.runs.get(this.runId,{resolveData:`none`}).then(()=>!0).catch(e=>{if(t.is(e))return!1;throw e}))}get status(){"use step";return this.#t.then(e=>e.runs.get(this.runId).then(e=>e.status))}get returnValue(){"use step";return this.#o()}get workflowName(){"use step";return this.#t.then(e=>e.runs.get(this.runId).then(e=>e.workflowName))}get createdAt(){"use step";return this.#t.then(e=>e.runs.get(this.runId).then(e=>e.createdAt))}get startedAt(){"use step";return this.#t.then(e=>e.runs.get(this.runId).then(e=>e.startedAt))}get completedAt(){"use step";return this.#t.then(e=>e.runs.get(this.runId).then(e=>e.completedAt))}get readable(){return this.getReadable()}getReadable(e={}){"use step";let{ops:t=[],global:n=globalThis,startIndex:r,namespace:i}=e,a=m(this.runId,i),o=this.#a(),s=u(n,t,this.runId,o).ReadableStream({name:a,startIndex:r}),c=this.#t,l=this.runId;return Object.assign(s,{getTailIndex:async()=>(await(await c).streams.getInfo(l,a)).tailIndex})}async#o(){let e=await this.#t,r=0,a=this.#r?3:0,o=[1e3,3e3,6e3];for(;;)try{let t=await e.runs.get(this.runId);if(t.status===`completed`){let e=await this.#i();return await l(t.output,this.runId,e)}if(t.status===`cancelled`)throw new i(this.runId);if(t.status===`failed`){let e=await this.#i(),n;try{n=await y(t.error,this.runId,e)}catch{n=Error(`Failed to hydrate workflow run error`)}throw new c(this.runId,n,{errorCode:t.errorCode})}throw new n(this.runId,t.status)}catch(e){if(n.is(e)){await new Promise(e=>setTimeout(e,1e3));continue}if(t.is(e)&&r<a){let e=o[r];r++,await new Promise(t=>setTimeout(t,e));continue}throw e}}};function J(e){return new q(e)}export{G as a,W as c,K as i,R as l,J as n,V as o,H as r,U as s,q as t};