eve 0.79.2 → 0.80.1

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 (184) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/src/compiled/.vendor-stamp.json +8 -8
  3. package/dist/src/compiled/@chat-adapter/slack/api.d.ts +6 -0
  4. package/dist/src/compiled/@chat-adapter/slack/api.js +1 -1
  5. package/dist/src/compiled/@chat-adapter/slack/blocks.js +1 -1
  6. package/dist/src/compiled/@chat-adapter/slack/format.js +1 -1
  7. package/dist/src/compiled/@chat-adapter/slack/index.d.ts +14 -8
  8. package/dist/src/compiled/@chat-adapter/slack/index.js +33 -32
  9. package/dist/src/compiled/@chat-adapter/twilio/index.d.ts +37 -1
  10. package/dist/src/compiled/@chat-adapter/twilio/index.js +2 -2
  11. package/dist/src/compiled/@linqapp/chat-sdk-adapter/index.js +1 -1
  12. package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.js +1 -1
  13. package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/ai-sdk-telemetry.d.ts +2 -2
  14. package/dist/src/compiled/{@eve/tracing/agent-tracing.d.ts → @vercel/agent-runs/agent-run.d.ts} +3 -3
  15. package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/index.d.ts +1 -1
  16. package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/index.js +1 -1
  17. package/dist/src/compiled/@vercel/connect/index.js +5 -5
  18. package/dist/src/compiled/@vercel/connect/token.d.ts +11 -1
  19. package/dist/src/compiled/@workflow/world-vercel/index.js +3 -3
  20. package/dist/src/compiled/_chunks/node/chunk-NBSLXVG3-Bt7pDfyn.js +12 -0
  21. package/dist/src/compiled/_chunks/node/dist-BKsV21Vu.js +6 -0
  22. package/dist/src/compiled/_chunks/node/dist-CO_n_hUa.js +98 -0
  23. package/dist/src/compiled/chat/index.js +1 -1
  24. package/dist/src/compiler/extension-compatibility.d.ts +6 -6
  25. package/dist/src/compiler/extension-compatibility.js +1 -1
  26. package/dist/src/compiler/manifest.d.ts +8 -4
  27. package/dist/src/compiler/manifest.js +1 -1
  28. package/dist/src/compiler/normalize-connection.js +1 -1
  29. package/dist/src/compiler/normalize-manifest.js +1 -1
  30. package/dist/src/context/schedule-collection-tools.js +1 -1
  31. package/dist/src/execution/catalog/connection-auth.d.ts +4 -2
  32. package/dist/src/execution/catalog/connection-auth.js +1 -1
  33. package/dist/src/execution/catalog/connection-entry.js +1 -1
  34. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  35. package/dist/src/execution/session/entry.js +1 -1
  36. package/dist/src/execution/session-event-stream.js +1 -1
  37. package/dist/src/execution/stable-workflow-names.d.ts +2 -0
  38. package/dist/src/execution/stable-workflow-names.js +1 -1
  39. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  40. package/dist/src/execution/web-fetch/execute.js +1 -1
  41. package/dist/src/execution/workflow-runtime.d.ts +6 -0
  42. package/dist/src/execution/workflow-runtime.js +1 -1
  43. package/dist/src/extensions/git/extension/extension.d.ts +3 -1
  44. package/dist/src/extensions/git/extension/extension.js +1 -1
  45. package/dist/src/extensions/git/extension/lib/gh-tool.js +1 -1
  46. package/dist/src/extensions/git/extension/lib/github-shell.d.ts +14 -0
  47. package/dist/src/extensions/git/extension/lib/github-shell.js +1 -1
  48. package/dist/src/harness/compaction/engine.js +2 -2
  49. package/dist/src/harness/compaction/prompt.d.ts +6 -0
  50. package/dist/src/harness/compaction/prompt.js +1 -1
  51. package/dist/src/harness/model-call/call.js +1 -1
  52. package/dist/src/harness/model-call/errors.d.ts +2 -2
  53. package/dist/src/harness/model-call/recovery.d.ts +2 -3
  54. package/dist/src/instrumentation/ai-sdk-hook-bridge.js +1 -1
  55. package/dist/src/instrumentation/principal-summary.js +1 -1
  56. package/dist/src/instrumentation/runtime.d.ts +1 -1
  57. package/dist/src/instrumentation/runtime.js +1 -1
  58. package/dist/src/instrumentation/session-init.d.ts +2 -1
  59. package/dist/src/instrumentation/session-init.js +1 -1
  60. package/dist/src/internal/application/stamped-package-version.js +1 -1
  61. package/dist/src/internal/authored-definition/connection.js +1 -1
  62. package/dist/src/internal/authored-definition/schedule-collection.js +1 -1
  63. package/dist/src/internal/authored-package-boundary.d.ts +4 -0
  64. package/dist/src/internal/authored-package-boundary.js +1 -1
  65. package/dist/src/internal/bundler/nitro-rolldown.d.ts +2 -2
  66. package/dist/src/internal/logging.js +1 -1
  67. package/dist/src/internal/nitro/host/application-route-registry.d.ts +7 -2
  68. package/dist/src/internal/nitro/host/application-route-registry.js +1 -1
  69. package/dist/src/internal/nitro/host/configure-nitro-routes.js +1 -1
  70. package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
  71. package/dist/src/internal/nitro/host/external-dependency-output-check-plugin.d.ts +23 -0
  72. package/dist/src/internal/nitro/host/external-dependency-output-check-plugin.js +3 -0
  73. package/dist/src/internal/nitro/routes/channel-request-instrumentation.d.ts +3 -1
  74. package/dist/src/internal/nitro/routes/channel-request-instrumentation.js +1 -1
  75. package/dist/src/internal/nitro/routes/connection-events.d.ts +5 -0
  76. package/dist/src/internal/nitro/routes/connection-events.js +1 -0
  77. package/dist/src/internal/workflow-bundle/builder.js +1 -1
  78. package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.js +1 -1
  79. package/dist/src/public/channels/slack/blocks.js +2 -2
  80. package/dist/src/public/connections/index.d.ts +1 -0
  81. package/dist/src/public/definitions/connections/events.d.ts +43 -0
  82. package/dist/src/public/definitions/connections/events.js +1 -0
  83. package/dist/src/public/definitions/connections/mcp.d.ts +3 -0
  84. package/dist/src/public/schedules/subscription.d.ts +4 -3
  85. package/dist/src/runtime/connections/events/actions.d.ts +17 -0
  86. package/dist/src/runtime/connections/events/actions.js +1 -0
  87. package/dist/src/runtime/connections/events/delivery.d.ts +10 -0
  88. package/dist/src/runtime/connections/events/delivery.js +1 -0
  89. package/dist/src/runtime/connections/events/dispatch-step.d.ts +20 -0
  90. package/dist/src/runtime/connections/events/dispatch-step.js +1 -0
  91. package/dist/src/runtime/connections/events/lifecycle-step.d.ts +42 -0
  92. package/dist/src/runtime/connections/events/lifecycle-step.js +1 -0
  93. package/dist/src/runtime/connections/events/owner.d.ts +38 -0
  94. package/dist/src/runtime/connections/events/owner.js +1 -0
  95. package/dist/src/runtime/connections/events/path.d.ts +4 -0
  96. package/dist/src/runtime/connections/events/path.js +1 -0
  97. package/dist/src/runtime/connections/events/state.d.ts +37 -0
  98. package/dist/src/runtime/connections/events/state.js +1 -0
  99. package/dist/src/runtime/connections/events/workflow.d.ts +28 -0
  100. package/dist/src/runtime/connections/events/workflow.js +1 -0
  101. package/dist/src/runtime/connections/mcp-client.d.ts +4 -2
  102. package/dist/src/runtime/connections/mcp-client.js +1 -1
  103. package/dist/src/runtime/connections/openapi-client.js +1 -1
  104. package/dist/src/runtime/connections/scoped-authorization.js +1 -1
  105. package/dist/src/runtime/resolve-connection.js +1 -1
  106. package/dist/src/runtime/schedules/collection-client.d.ts +0 -2
  107. package/dist/src/runtime/schedules/collection-client.js +1 -1
  108. package/dist/src/runtime/types.d.ts +11 -0
  109. package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
  110. package/dist/src/setup/scaffold/create/project.js +2 -2
  111. package/dist/src/setup/scaffold/update/channels.js +1 -1
  112. package/dist/src/setup/scaffold/update/connections.js +2 -2
  113. package/dist/src/setup/scaffold/version-tokens.d.ts +1 -1
  114. package/dist/src/setup/scaffold/version-tokens.js +1 -1
  115. package/dist/src/shared/agent-definition.d.ts +12 -4
  116. package/dist/src/shared/connection-events.d.ts +84 -0
  117. package/dist/src/shared/connection-events.js +1 -0
  118. package/dist/src/shared/connection-types.d.ts +10 -0
  119. package/dist/src/shared/validate-authorization.js +1 -1
  120. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  121. package/dist/src/tools/provided/no-reply.d.ts +5 -0
  122. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  123. package/dist/src/tracing/eve/agent-approval-instrumentation.d.ts +2 -2
  124. package/dist/src/tracing/eve/agent-channel-delivery-instrumentation.js +1 -1
  125. package/dist/src/tracing/eve/agent-memory-instrumentation.d.ts +2 -2
  126. package/dist/src/tracing/eve/agent-memory-instrumentation.js +1 -1
  127. package/dist/src/tracing/eve/agent-otel-provider.d.ts +1 -1
  128. package/dist/src/tracing/eve/agent-tool-instrumentation.d.ts +3 -3
  129. package/dist/src/tracing/eve/agent-trace-context.js +1 -1
  130. package/dist/src/tracing/eve/agent-trace-state.d.ts +1 -1
  131. package/dist/src/tracing/eve/connection-events.d.ts +25 -0
  132. package/dist/src/tracing/eve/connection-events.js +1 -0
  133. package/dist/src/tracing/eve/content-span-processor.js +1 -1
  134. package/dist/src/tracing/eve/delegation.js +1 -1
  135. package/dist/src/tracing/eve/gateway.d.ts +1 -1
  136. package/dist/src/tracing/eve/install-instrumentation-runtime.js +1 -1
  137. package/dist/src/tracing/eve/invoke-tool-span.js +1 -1
  138. package/dist/src/tracing/eve/mcp.d.ts +2 -1
  139. package/dist/src/tracing/eve/mcp.js +1 -1
  140. package/dist/src/tracing/eve/metadata.d.ts +1 -1
  141. package/dist/src/tracing/eve/operation-input.d.ts +2 -2
  142. package/dist/src/tracing/eve/operation-input.js +1 -1
  143. package/dist/src/tracing/eve/otel-declaration.d.ts +5 -0
  144. package/dist/src/tracing/eve/otel-registration.d.ts +2 -2
  145. package/dist/src/tracing/eve/otel-registration.js +1 -1
  146. package/dist/src/tracing/eve/profile.d.ts +1 -1
  147. package/dist/src/tracing/eve/session.d.ts +2 -2
  148. package/dist/src/tracing/local/trace-summary.js +1 -1
  149. package/docs/agent-config.md +38 -13
  150. package/docs/code-extension.mdx +28 -0
  151. package/docs/concepts/built-in-tools.md +2 -0
  152. package/docs/connections/mcp.mdx +105 -0
  153. package/docs/connections/openapi.mdx +2 -0
  154. package/docs/guides/instrumentation/otel.mdx +10 -0
  155. package/docs/sandbox/vercel.mdx +46 -0
  156. package/package.json +8 -8
  157. package/dist/src/compiled/_chunks/node/chunk-6QHBXN7B-gl4n6nmi.js +0 -12
  158. package/dist/src/compiled/_chunks/node/dist-DYDVZ-FS.js +0 -98
  159. package/dist/src/compiled/_chunks/node/dist-iEFkK9qw.js +0 -6
  160. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/agent-transport.d.ts +0 -0
  161. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/ai-sdk-payload.d.ts +0 -0
  162. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/otel-error.d.ts +0 -0
  163. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/otel-ids.d.ts +0 -0
  164. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/otel.d.ts +0 -0
  165. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/serialization.d.ts +0 -0
  166. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/ai-sdk.d.ts +0 -0
  167. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/ai-sdk.js +0 -0
  168. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/capture.d.ts +0 -0
  169. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/activation.d.ts +0 -0
  170. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/attributes.d.ts +0 -0
  171. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/content-policy.d.ts +0 -0
  172. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/context.d.ts +0 -0
  173. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/delegation.d.ts +0 -0
  174. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/mcp.d.ts +0 -0
  175. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/scopes.d.ts +0 -0
  176. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/snapshot.d.ts +0 -0
  177. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/span-kinds.d.ts +0 -0
  178. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/types.d.ts +0 -0
  179. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/writer.d.ts +0 -0
  180. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/delegation.d.ts +0 -0
  181. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/delegation.js +0 -0
  182. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/operations.d.ts +0 -0
  183. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/otel.d.ts +0 -0
  184. /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/otel.js +0 -0
@@ -263,7 +263,8 @@ duration. Process restarts, ordinary messages, compaction handoffs, and failed
263
263
  or skipped handoffs keep the existing deadline. At the deadline, eve lets an active turn settle,
264
264
  then emits `session.completed` and releases every continuation address; the next
265
265
  qualifying channel message starts fresh. Set it to `false` to disable the
266
- timeout. Expiration does not delete stored session data.
266
+ timeout. Session expiration follows [run-data retention](#run-data-retention);
267
+ a zero-retention session loses its stored payloads when it ends.
267
268
 
268
269
  Input tokens, output tokens, and model token cost are checked independently.
269
270
  The model call that crosses a limit is allowed to finish because exact usage
@@ -409,11 +410,24 @@ for the retry behavior.
409
410
 
410
411
  ## Run data retention
411
412
 
412
- The runtime keeps each run's data after the run finishes: model and tool
413
- payloads, streamed output, and the event log eve replays from. How long it keeps
414
- them is the World's decision, and on Vercel that follows your team's plan. Set
415
- `experimental.workflow.retention` to `0` to have it deleted as soon as the run
416
- finishes instead:
413
+ By default, eve derives run-data retention from the session's resolved
414
+ [OpenTelemetry trace policy](./observability/otel#configure-opentelemetry):
415
+
416
+ - When the policy allows both inputs and outputs, eve uses the World's default
417
+ retention period.
418
+ - When the policy drops the trace or excludes either content direction, eve
419
+ requests deletion as soon as the run ends with Workflow's
420
+ `experimental_retention: 0`. Workflow cannot delete inputs and outputs separately.
421
+
422
+ Without a custom policy, public conversations and development sessions use the
423
+ World's default. Private and unknown-audience sessions outside development request
424
+ `0`, even when no OpenTelemetry destination is installed. This decision is made
425
+ when the session starts; destination export filters and lifecycle-provider
426
+ policies do not change it.
427
+
428
+ Set `experimental.workflow.retention` explicitly to override this behavior.
429
+ Use `0` to request deletion regardless of the tracing policy, or `"default"` to
430
+ keep run data for the World's default period regardless of the tracing policy:
417
431
 
418
432
  ```ts title="agent/agent.ts"
419
433
  import { defineAgent } from "eve";
@@ -428,18 +442,29 @@ export default defineAgent({
428
442
  });
429
443
  ```
430
444
 
431
- This applies to every run that owns the session, including successor owners
445
+ The resolved value applies to every run that owns the session, including successor owners
432
446
  started after a deployment handoff, and to the run that collects session
433
447
  activity. Runs eve starts for other purposes keep the world's default: session
434
448
  timeouts and [workflow tools](./tools/workflows).
435
449
 
436
450
  The value applies per agent. A [subagent](./subagents) that runs its own session
437
- uses its own value, unlike `experimental.workflow.world`, which is root-only.
438
-
439
- Custom Worlds used with eve might not support this feature, in which case
440
- it falls back to the World's default retention period.
441
-
442
- > ⚠️ **At `0`, a finished session's output is usually gone before you can read it.** Since data is deleted immediately before it can be read back, results and transcripts become unreadable and a client polling for a finished session's output can see it disappear.
451
+ uses its own explicit value or derives retention from its resolved trace decision,
452
+ including any inherited content ceiling. `experimental.workflow.world` is root-only.
453
+
454
+ At `0`, supporting Worlds delete run and step inputs, outputs, and errors;
455
+ event payloads; and stream contents when the run reaches a terminal state. The
456
+ data remains available while the session is active. Run, step, and event records
457
+ remain for the World's default period, including IDs, timestamps, statuses,
458
+ step names, and attributes. Attributes can contain content, including eve's
459
+ session title. This option does not delete local traces, exported telemetry, or
460
+ data stored by tools, channels, or model providers.
461
+
462
+ The Workflow World enforces deletion, not eve or the SDK. A World older than
463
+ spec version 4 rejects `0`; a spec version 4 World without retention support
464
+ keeps the data. Confirm support with your World provider. See
465
+ [Workflow data retention](https://workflow-sdk.dev/docs/observability/retention).
466
+
467
+ > ⚠️ **At `0`, completed session transcripts become unreadable.** Deletion races reads of finished runs. Depending on the World, reading deleted session history returns either an empty stream or `410` with `code: "session_expired"`. Persist anything you need to keep from inside a tool, or set `retention: "default"` to preserve completed-session reads independently of tracing.
443
468
 
444
469
  ## Other defineAgent fields
445
470
 
@@ -103,9 +103,37 @@ Configure `github` to broker GitHub access through Connect instead. The extensio
103
103
  | `github.connector` | With `github` | Connector that mints a GitHub token |
104
104
  | `github.org` | With `github` | Organization whose repositories the `gh` tool can access |
105
105
  | `github.broker` | With `github` | `broker(sandbox, rules)` callback that installs, then removes, the GitHub credential rules |
106
+ | `github.authorize` | No | `authorize({ auth, repository, token })` callback that allows or denies each `gh` tool invocation |
106
107
 
107
108
  The `gh` tool requests a token scoped to exactly one repository in `github.org` for each invocation. The sandbox process receives a placeholder `GH_TOKEN`, and the firewall exchanges it on matching GitHub requests. Your `github.broker` callback receives the header-transform rules for the command, then `null` to remove the lease. The callback must preserve your other network rules. GitHub authentication has no command-delivery option.
108
109
 
110
+ `github.authorize` runs during each `gh` tool execution, not when the session starts. The order is: validate the command and repository, mint the repository-scoped app token, await `authorize({ auth, repository, token })`, install the credential lease, then run the command. `auth` is the session's current caller at tool invocation, or `null`. Returning `false` stops execution before the lease is installed or the command runs. The decision applies to that invocation only; it is neither cached for the session nor repeated for each GitHub API request.
111
+
112
+ For example, use the token to check collaborator status (allowed commands still use the app token's permissions, not the collaborator's):
113
+
114
+ ```ts title="agent/extensions/git.ts"
115
+ import git from "eve/extensions/git";
116
+
117
+ import { brokerGitHubLease } from "../lib/github";
118
+
119
+ export default git({
120
+ github: {
121
+ connector: "github/my-agent",
122
+ org: "acme",
123
+ broker: brokerGitHubLease,
124
+ // GitHub channel sessions carry the commenter's login as `auth.subject`.
125
+ async authorize({ auth, repository, token }) {
126
+ if (auth?.authenticator !== "github-webhook" || !auth.subject) return false;
127
+ const response = await fetch(
128
+ `https://api.github.com/repos/${repository}/collaborators/${auth.subject}`,
129
+ { headers: { authorization: `Bearer ${token}` } },
130
+ );
131
+ return response.status === 204;
132
+ },
133
+ },
134
+ });
135
+ ```
136
+
109
137
  ### Migrate from `code({ github })`
110
138
 
111
139
  `code({ github })` is deprecated. While it is set, the code extension still contributes `code__gh`, its GitHub instructions, and the signed-commit `code__pr` skill. Without it, the code extension contributes no GitHub tool, instructions, or pull request skill. Move the `github` option to `git({ github })`, and import `gh` and the GitHub sandbox helpers from `eve/extensions/git/tools` and `eve/extensions/git/sandbox`.
@@ -422,6 +422,8 @@ export default noReply();
422
422
 
423
423
  `no_reply` is a `defineTool` tool with [`endsTurn: true`](/docs/tools#end-the-turn-after-a-tool-call), so the turn ends only when no other tool runs in the same step. Only root sessions receive it. Slack clears the thread status when the turn completes. Remove the file to remove the tool.
424
424
 
425
+ A root session also accepts a successful model call that returns no text with `finishReason: "stop"`, without retrying or reporting a model-call failure. A turn that settles with no text completes without a final message. Use `no_reply` when the agent should record an explicit choice to stay quiet, including an optional reason. Delegated sessions still retry an empty reply once and report a failure if it remains empty, so the caller can act on the failure.
426
+
425
427
  ### `sleep`
426
428
 
427
429
  `sleep` pauses and durably resumes the current turn. The model calls it with `{ seconds }`; the wait does not hold an application runtime open. Concurrent calls run in parallel, and the turn resumes after the longest wait. A steering message, the default for a new message, ends the wait early: `sleep` returns `{ interrupted: true }`, which the model reads as `Stopped early because a new message arrived.`, followed by the message. Add it:
@@ -205,6 +205,111 @@ An MCP tool call returns the tool's `structuredContent` when the server sends it
205
205
 
206
206
  When a remote tool returns more data than the model needs, narrow the result at the MCP server. Prefer a purpose-built search or summary tool, or return a stable handle that another call can use to fetch a smaller slice. If you do not control the server and an equivalent upstream API is available, replace only that operation with an authored tool that stores the full payload outside model context and projects the needed fields through `toModelOutput`. Block the original MCP operation through [`tools.block`](#tool-filters) so the model does not see duplicate tools.
207
207
 
208
+ ## Events (experimental)
209
+
210
+ An MCP connection can watch the server's events and run your code when one arrives. Vercel Connect holds the upstream subscription and forwards each event to your agent; eve runs your callback.
211
+
212
+ Requirements:
213
+
214
+ - A statically authored MCP connection with a static `connect()` auth provider. Dynamic connections and auth resolvers are not supported.
215
+ - `@vercel/connect@2.5.2` or later.
216
+ - An MCP server that supports events over Streamable HTTP.
217
+
218
+ ### Handle events
219
+
220
+ Add `experimental_events` to the connection. In this example, a user asks the agent to "watch the support inbox and draft replies to new bug reports". The model subscribes to Bird's `email_mailbox.message_received` event for that mailbox. Each new email then starts a turn in the same conversation, with instructions to triage it:
221
+
222
+ ```ts title="agent/connections/bird.ts"
223
+ import { connect } from "@vercel/connect/eve";
224
+ import { defineMcpClientConnection } from "eve/connections";
225
+
226
+ export default defineMcpClientConnection({
227
+ url: "https://mcp.bird.com/",
228
+ description: "Bird: email, SMS, and contacts. Can watch a mailbox for new mail.",
229
+ auth: connect("bird/bird"),
230
+ experimental_events: {
231
+ async onEvent({ event, origin, auth, attachSession }) {
232
+ if (event.name !== "email_mailbox.message_received") return;
233
+ await attachSession(origin.sessionId).send(
234
+ [
235
+ "A new email arrived in the mailbox you are watching:",
236
+ JSON.stringify(event.data),
237
+ "If it is a bug report, look up the sender's earlier threads, draft a reply " +
238
+ "that says what we know and what happens next, and ask me before sending it. " +
239
+ "Otherwise, summarize it in one line.",
240
+ ].join("\n\n"),
241
+ { auth, turnPolicy: "queue" },
242
+ );
243
+ },
244
+ },
245
+ });
246
+ ```
247
+
248
+ The model does the work with the connection's own tools: it reads the thread, drafts the reply, and waits for the user's approval in the conversation. `turnPolicy: "queue"` lets a burst of emails run one turn after another instead of interrupting the user.
249
+
250
+ `onEvent` is required. Defining it does not subscribe to anything: the model subscribes at runtime.
251
+
252
+ Callbacks run outside any conversation, as the user who subscribed (`auth`). Nothing enters a session unless you call `attachSession(sessionId).send(...)`, and `attachSession` never creates a session.
253
+
254
+ Each delivery runs in its own durable workflow, so callbacks can run concurrently, out of order, and more than once. Use `deliveryId` to deduplicate side effects:
255
+
256
+ ```ts
257
+ async onEvent({ event, deliveryId }) {
258
+ await fetch("https://crm.example/notes", {
259
+ method: "POST",
260
+ headers: { "Idempotency-Key": deliveryId },
261
+ body: JSON.stringify(event.data),
262
+ });
263
+ },
264
+ ```
265
+
266
+ ### Handle missed events and ended subscriptions
267
+
268
+ ```ts
269
+ experimental_events: {
270
+ async onEvent({ event }) {
271
+ // ...
272
+ },
273
+ async onGap({ origin, auth, attachSession }) {
274
+ // The server could not deliver every event. Re-read the source.
275
+ await attachSession(origin.sessionId).send(
276
+ "Some Bird events were missed. Re-check the mailbox.",
277
+ { auth },
278
+ );
279
+ },
280
+ async onTerminated({ origin, auth, error, attachSession }) {
281
+ // The upstream subscription ended. The watch ends when this returns.
282
+ await attachSession(origin.sessionId).send(
283
+ `The Bird watch ended: ${error.message}`,
284
+ { auth },
285
+ );
286
+ },
287
+ },
288
+ ```
289
+
290
+ ### What the model can call
291
+
292
+ `eve__search` lists three kinds of actions for the connection:
293
+
294
+ | Action | Input | Result |
295
+ | ------------------------- | ---------------------- | --------------------------------------- |
296
+ | `events_subscribe_<hash>` | `{ arguments, ttlMs }` | `{ id, status, expiresAt, ... }` |
297
+ | `events_get_subscription` | `{ id }` | The subscription, or unknown once ended |
298
+ | `events_unsubscribe` | `{ id }` | `{ id, status: "stopping" }` |
299
+
300
+ There is one subscribe action per event the server offers; its description names the event. `ttlMs` is required: an integer from `120000` (2 minutes) to `31536000000` (365 days), or `null` to watch until stopped. `expiresAt` is the resulting deadline, or `null`.
301
+
302
+ - **Pending.** If Connect has not confirmed in time, subscribe returns the `id` with `status: "pending"`. Call get with that `id` later.
303
+ - **Repeats.** Subscribing again to the same event with the same arguments from the same session returns the existing watch. Another session gets its own watch.
304
+ - **Stopping.** Get and stop accept the `id` from any of the creator's sessions. After stop, eve keeps retrying Connect's unsubscribe until cleanup completes; until then get still reports the watch and stop can be called again.
305
+ - **Lifetime.** A watch outlives the session that created it. It ends on stop, at `expiresAt`, or when the upstream subscription terminates.
306
+
307
+ `tools.allow` and `tools.block` apply to these actions. An allow list hides any event action it does not name, so copy the exact `events_subscribe_<hash>` names from `eve__search`. `toolCall.providedArguments` does not apply to event actions.
308
+
309
+ ### Receiver
310
+
311
+ eve mounts `POST /eve/v1/hooks/:connectionName`, under any configured agent or public prefix. It accepts only Connect's delivery token and only deliveries for a live watch's subscription; it answers `410` once the watch has ended. The callback's identity always comes from the saved watch, never from the event payload.
312
+
208
313
  ## Troubleshooting
209
314
 
210
315
  | Symptom | Check |
@@ -119,6 +119,8 @@ Filters match `operationId`. If an operation does not declare one, use the deter
119
119
 
120
120
  When an operation path contains dynamic segments, the spec must declare matching OpenAPI path parameters. eve exposes path, query, header, and cookie parameters as top-level tool inputs, then substitutes `in: "path"` values into the matching `{name}` placeholder before making the request.
121
121
 
122
+ Path parameter values must not be exactly `.` or `..`. eve rejects these values before URL parsing can normalize them and change the route, including values resolved through `toolCall.providedArguments`. Other values remain URL-encoded during substitution, including embedded slashes.
123
+
122
124
  ```ts title="agent/connections/cart.ts"
123
125
  import { defineOpenAPIConnection } from "eve/connections";
124
126
 
@@ -38,6 +38,16 @@ does not affect lifecycle instrumentation created with `defineInstrumentation()`
38
38
  See [Audience](../channels/overview#audience) for how channels classify the
39
39
  conversation passed to this policy.
40
40
 
41
+ The session's resolved capture decision also selects its default
42
+ [Workflow run-data retention](/docs/agent-config#run-data-retention). Allowing
43
+ both inputs and outputs uses the World's default; dropping the trace or excluding
44
+ either direction requests deletion of durable payloads and streams when the run
45
+ ends. This makes completed private and unknown-audience transcripts unreadable
46
+ under the default policy outside development. Set
47
+ `experimental.workflow.retention: "default"` on the agent to retain completed
48
+ sessions independently of tracing. Destination `exportPolicy` filters do not
49
+ change Workflow retention, and Workflow deletion does not delete exported traces.
50
+
41
51
  ## Instrument Node.js dependencies
42
52
 
43
53
  Pass OpenTelemetry instrumentation instances to `otel({ instrumentations })`.
@@ -104,6 +104,52 @@ const sandbox = await ctx.getSandbox(environment);
104
104
  const sandboxName = sandbox.name;
105
105
  ```
106
106
 
107
+ ## Mount a Drive
108
+
109
+ A [Vercel Sandbox Drive](https://vercel.com/docs/sandbox/concepts/drives) stores files independently of a sandbox. Create or retrieve the Drive before calling `open()`, then pass it in `mounts` under an absolute path:
110
+
111
+ ```ts
112
+ import { defineSandbox } from "eve/sandbox";
113
+ import { Drive, VercelSandbox } from "eve/sandbox/vercel";
114
+
115
+ const REGION = "iad1";
116
+
117
+ export const environment = VercelSandbox.environment({ region: REGION });
118
+
119
+ export default defineSandbox(async () => {
120
+ const drive = await Drive.getOrCreate({
121
+ name: "agent-workspace",
122
+ region: REGION,
123
+ });
124
+
125
+ return environment.open({
126
+ mounts: {
127
+ "/data": drive,
128
+ },
129
+ });
130
+ });
131
+ ```
132
+
133
+ This example mounts the Drive read-write at `/data`. Files written there remain on the Drive after the sandbox stops. Keep Drive mounts separate from eve's managed `/workspace` directory.
134
+
135
+ Set the same region on the environment and the Drive. The environment region places the prepared snapshot and each session sandbox together with the Drive.
136
+
137
+ A Drive supports one active read-write mount. Because each eve session gets its own sandbox, the fixed `agent-workspace` name works only when one eve session uses the Drive at a time. If sessions can overlap, derive an opaque, stable Drive name per owner or tenant. The [Vercel guide to using Drives with eve](https://vercel.com/kb/guide/vercel-drives-eve-agent) shows how to derive a Drive name from the session initiator.
138
+
139
+ To share a point-in-time view across concurrent sandboxes, mount a read-only snapshot instead:
140
+
141
+ ```ts
142
+ return environment.open({
143
+ mounts: {
144
+ "/data": drive.snapshot(),
145
+ },
146
+ });
147
+ ```
148
+
149
+ Before mounting `drive.snapshot()`, seed a new Drive by mounting it read-write and writing at least one file. An uninitialized Drive cannot be mounted as a snapshot.
150
+
151
+ Vercel allows up to four non-overlapping, absolute Drive mount paths per sandbox. See the Vercel documentation for [Drive lifecycle, limits, and pricing](https://vercel.com/docs/sandbox/concepts/drives).
152
+
107
153
  ## Live sandbox options
108
154
 
109
155
  `open()` also accepts Vercel compute resources, timeout, and Drive mounts. Configure project credentials and custom fetch behavior on the environment, not in `open()`, because resume does not reconstruct start-only options.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.79.2",
3
+ "version": "0.80.1",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [
@@ -569,12 +569,11 @@
569
569
  "@ai-sdk/provider": "^4.0.26",
570
570
  "@ai-sdk/provider-utils": "^5.0.58",
571
571
  "@cfworker/json-schema": "4.1.1",
572
- "@chat-adapter/slack": "4.41.0",
573
- "@chat-adapter/state-memory": "4.41.0",
574
- "@chat-adapter/twilio": "4.41.0",
572
+ "@chat-adapter/slack": "4.42.0",
573
+ "@chat-adapter/state-memory": "4.42.0",
574
+ "@chat-adapter/twilio": "4.42.0",
575
575
  "@clack/core": "1.3.1",
576
576
  "@eve/catalog": "0.0.1",
577
- "@eve/tracing": "0.0.0",
578
577
  "@linqapp/chat-sdk-adapter": "^0.5.1",
579
578
  "@modelcontextprotocol/server": "2.0.0",
580
579
  "@nuxt/kit": "^4.0.0",
@@ -591,8 +590,9 @@
591
590
  "@types/json-schema": "7.0.15",
592
591
  "@types/react": "19.2.15",
593
592
  "@types/react-test-renderer": "19.1.0",
593
+ "@vercel/agent-runs": "0.0.1",
594
594
  "@vercel/blob": "2.8.0",
595
- "@vercel/connect": "2.3.3",
595
+ "@vercel/connect": "2.5.2",
596
596
  "@vercel/detect-agent": "1.2.3",
597
597
  "@vercel/oidc": "3.8.0",
598
598
  "@vercel/otel": "2.1.3",
@@ -607,7 +607,7 @@
607
607
  "@workflow/world-local": "5.1.0",
608
608
  "@workflow/world-vercel": "5.2.0",
609
609
  "ai": "^7.0.137",
610
- "chat": "4.41.0",
610
+ "chat": "4.42.0",
611
611
  "chokidar": "5.0.0",
612
612
  "commander": "14.0.3",
613
613
  "dd-trace": "6.13.0",
@@ -640,7 +640,7 @@
640
640
  "@opentelemetry/api": "^1.0.0",
641
641
  "ai": "^7.0.137",
642
642
  "braintrust": "^3.0.0",
643
- "chat": "^4.41.0",
643
+ "chat": "^4.42.0",
644
644
  "dd-trace": "^6.13.0",
645
645
  "just-bash": "^3.1.0",
646
646
  "microsandbox": "^0.5.0"
@@ -1,12 +0,0 @@
1
- var e=/[<>|]/,t=/[\^|>]/,n=/^[A-Z0-9_]+$/,r=/(?<![<\w])@([A-Z][A-Z0-9_]+)/g,i=3e3,a=/^[ \t]+/,o=/^(?:&gt;|&lt;|#{1,6}(?=[ \t\n]|$)|[-+*](?=[ \t\n]|$)|`{3,}|~{3,}|(?:[-*_][ \t]*){3,}(?=\n|$))/,s=/^(\d{1,9})([.)])(?=[ \t\n]|$)/;function c(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`)}function l(e){return e.replace(/&lt;/g,`<`).replace(/&gt;/g,`>`).replace(/&amp;/g,`&`)}function u(e,t={}){return O(e),{...t.emoji===void 0?{}:{emoji:t.emoji},text:e,type:`plain_text`}}function d(e,t={}){return O(e),{text:e,type:`mrkdwn`,...t.verbatim===void 0?{}:{verbatim:t.verbatim}}}function f(e){return k(e,`userId`),`<@${e}>`}function p(e){return k(e,`channelId`),`<#${e}>`}function m(e){return k(e,`userGroupId`),`<!subteam^${e}>`}function h(e){return`<!${e}>`}function g(e,t){return A(e,`url`),t?`<${e}|${c(t)}>`:`<${e}>`}function _(e,t,n,r={}){j(t,`token`);let i=e instanceof Date?Math.floor(e.getTime()/1e3):e;if(!Number.isInteger(i))throw TypeError(`timestamp must be an integer unix timestamp or Date`);return`<!date^${i}^${t}${r.link?`^${M(r.link)}`:``}|${c(n)}>`}function v(e){return l(e.includes("```")?x(e):b(e))}function y(e){let t=e.replace(/<@([A-Z0-9_]+)\|([^<>]+)>/g,`@$2`);return t=t.replace(/<@([A-Z0-9_]+)>/g,`@$1`),t=t.replace(/<#([A-Z0-9_]+)\|([^<>]+)>/g,`#$2 ($1)`),t=t.replace(/<#([A-Z0-9_]+)>/g,`#$1`),t=t.replace(/<(?!https?:\/\/)([^<>|]+)\|(https?:\/\/[^|<>]+)>/g,`<$2|$1>`),t=t.replace(/<(https?:\/\/[^|<>]+)\|([^<>]+)>/g,`[$2]($1)`),t=t.replace(/<(https?:\/\/[^<>]+)>/g,`$1`),t}function b(e){let t=y(e);return t=t.replace(/(?<![_*\\])\*([^*\n]+)\*(?![_*])/g,`**$1**`),t=t.replace(/(?<!~)~([^~\n]+)~(?!~)/g,`~~$1~~`),t}function x(e){let t=``,n=0,r=0,i=!1,a=r=>{let a=e.slice(n,r);i&&=(a=T(a),!1),t+=b(a)};for(;r<e.length;){let o=e[r];if(o===`<`){let t=S(e,r);r=t===-1?r+1:t;continue}if(o!=="`"){r+=1;continue}if(!e.startsWith("```",r)){let t=C(e,r);r=t===-1?r+1:t;continue}let s=r+3,c=e.indexOf("```",s);if(c===-1||w(e,r)){r=s;continue}a(r),t.length>0&&!t.endsWith(`
2
- `)&&(t+=`
3
- `);let l=e.slice(s,c);t+="```",l.startsWith(`
4
- `)||(t+=`
5
- `),t+=y(l),l.endsWith(`
6
- `)||(t+=`
7
- `),t+="```",r=c+3,n=r,r<e.length&&e[r]!==`
8
- `&&(t+=`
9
- `,i=!0)}return a(e.length),t}function S(e,t){let n=t+1;for(;n<e.length&&e[n]!==`>`&&e[n]!==`
10
- `&&e[n]!==`\r`;)n+=1;return e[n]===`>`?n+1:-1}function C(e,t){let n=e.indexOf("`",t+1);if(n===-1)return-1;let r=e.indexOf(`
11
- `,t+1);return r!==-1&&r<n?-1:n+1}function w(e,t){let n=e.lastIndexOf(`
12
- `,t-1)+1;return e.slice(n,t).trimStart().startsWith(`&gt;`)}function T(e){let t=a.exec(e)?.[0]??``,n=t.length>0?` `:``,r=e.slice(t.length);return o.test(r)?`${n}\\${r}`:n+r.replace(s,`$1\\$2`)}function E(e){return e.replace(/\*\*(.+?)\*\*/g,`*$1*`)}function D(e){return e.replace(r,`<@$1>`)}function O(e){if(e.length<1||e.length>i)throw TypeError(`text must be between 1 and ${i} characters`)}function k(e,t){if(!n.test(e))throw TypeError(`${t} must be a Slack ID`)}function A(t,n){if(e.test(t))throw TypeError(`${n} cannot contain Slack control characters`)}function j(e,n){if(t.test(e))throw TypeError(`${n} cannot contain Slack date control characters`)}function M(e){return j(e,`link`),e}export{_ as a,f as c,E as d,v as f,p as i,m as l,u as n,g as o,l as p,c as r,h as s,d as t,D as u};