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.
- package/CHANGELOG.md +30 -0
- package/dist/src/compiled/.vendor-stamp.json +8 -8
- package/dist/src/compiled/@chat-adapter/slack/api.d.ts +6 -0
- package/dist/src/compiled/@chat-adapter/slack/api.js +1 -1
- package/dist/src/compiled/@chat-adapter/slack/blocks.js +1 -1
- package/dist/src/compiled/@chat-adapter/slack/format.js +1 -1
- package/dist/src/compiled/@chat-adapter/slack/index.d.ts +14 -8
- package/dist/src/compiled/@chat-adapter/slack/index.js +33 -32
- package/dist/src/compiled/@chat-adapter/twilio/index.d.ts +37 -1
- package/dist/src/compiled/@chat-adapter/twilio/index.js +2 -2
- package/dist/src/compiled/@linqapp/chat-sdk-adapter/index.js +1 -1
- package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.js +1 -1
- package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/ai-sdk-telemetry.d.ts +2 -2
- package/dist/src/compiled/{@eve/tracing/agent-tracing.d.ts → @vercel/agent-runs/agent-run.d.ts} +3 -3
- package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/index.d.ts +1 -1
- package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/index.js +1 -1
- package/dist/src/compiled/@vercel/connect/index.js +5 -5
- package/dist/src/compiled/@vercel/connect/token.d.ts +11 -1
- package/dist/src/compiled/@workflow/world-vercel/index.js +3 -3
- package/dist/src/compiled/_chunks/node/chunk-NBSLXVG3-Bt7pDfyn.js +12 -0
- package/dist/src/compiled/_chunks/node/dist-BKsV21Vu.js +6 -0
- package/dist/src/compiled/_chunks/node/dist-CO_n_hUa.js +98 -0
- package/dist/src/compiled/chat/index.js +1 -1
- package/dist/src/compiler/extension-compatibility.d.ts +6 -6
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/manifest.d.ts +8 -4
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/normalize-connection.js +1 -1
- package/dist/src/compiler/normalize-manifest.js +1 -1
- package/dist/src/context/schedule-collection-tools.js +1 -1
- package/dist/src/execution/catalog/connection-auth.d.ts +4 -2
- package/dist/src/execution/catalog/connection-auth.js +1 -1
- package/dist/src/execution/catalog/connection-entry.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/session/entry.js +1 -1
- package/dist/src/execution/session-event-stream.js +1 -1
- package/dist/src/execution/stable-workflow-names.d.ts +2 -0
- package/dist/src/execution/stable-workflow-names.js +1 -1
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/web-fetch/execute.js +1 -1
- package/dist/src/execution/workflow-runtime.d.ts +6 -0
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/extensions/git/extension/extension.d.ts +3 -1
- package/dist/src/extensions/git/extension/extension.js +1 -1
- package/dist/src/extensions/git/extension/lib/gh-tool.js +1 -1
- package/dist/src/extensions/git/extension/lib/github-shell.d.ts +14 -0
- package/dist/src/extensions/git/extension/lib/github-shell.js +1 -1
- package/dist/src/harness/compaction/engine.js +2 -2
- package/dist/src/harness/compaction/prompt.d.ts +6 -0
- package/dist/src/harness/compaction/prompt.js +1 -1
- package/dist/src/harness/model-call/call.js +1 -1
- package/dist/src/harness/model-call/errors.d.ts +2 -2
- package/dist/src/harness/model-call/recovery.d.ts +2 -3
- package/dist/src/instrumentation/ai-sdk-hook-bridge.js +1 -1
- package/dist/src/instrumentation/principal-summary.js +1 -1
- package/dist/src/instrumentation/runtime.d.ts +1 -1
- package/dist/src/instrumentation/runtime.js +1 -1
- package/dist/src/instrumentation/session-init.d.ts +2 -1
- package/dist/src/instrumentation/session-init.js +1 -1
- package/dist/src/internal/application/stamped-package-version.js +1 -1
- package/dist/src/internal/authored-definition/connection.js +1 -1
- package/dist/src/internal/authored-definition/schedule-collection.js +1 -1
- package/dist/src/internal/authored-package-boundary.d.ts +4 -0
- package/dist/src/internal/authored-package-boundary.js +1 -1
- package/dist/src/internal/bundler/nitro-rolldown.d.ts +2 -2
- package/dist/src/internal/logging.js +1 -1
- package/dist/src/internal/nitro/host/application-route-registry.d.ts +7 -2
- package/dist/src/internal/nitro/host/application-route-registry.js +1 -1
- package/dist/src/internal/nitro/host/configure-nitro-routes.js +1 -1
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/external-dependency-output-check-plugin.d.ts +23 -0
- package/dist/src/internal/nitro/host/external-dependency-output-check-plugin.js +3 -0
- package/dist/src/internal/nitro/routes/channel-request-instrumentation.d.ts +3 -1
- package/dist/src/internal/nitro/routes/channel-request-instrumentation.js +1 -1
- package/dist/src/internal/nitro/routes/connection-events.d.ts +5 -0
- package/dist/src/internal/nitro/routes/connection-events.js +1 -0
- package/dist/src/internal/workflow-bundle/builder.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.js +1 -1
- package/dist/src/public/channels/slack/blocks.js +2 -2
- package/dist/src/public/connections/index.d.ts +1 -0
- package/dist/src/public/definitions/connections/events.d.ts +43 -0
- package/dist/src/public/definitions/connections/events.js +1 -0
- package/dist/src/public/definitions/connections/mcp.d.ts +3 -0
- package/dist/src/public/schedules/subscription.d.ts +4 -3
- package/dist/src/runtime/connections/events/actions.d.ts +17 -0
- package/dist/src/runtime/connections/events/actions.js +1 -0
- package/dist/src/runtime/connections/events/delivery.d.ts +10 -0
- package/dist/src/runtime/connections/events/delivery.js +1 -0
- package/dist/src/runtime/connections/events/dispatch-step.d.ts +20 -0
- package/dist/src/runtime/connections/events/dispatch-step.js +1 -0
- package/dist/src/runtime/connections/events/lifecycle-step.d.ts +42 -0
- package/dist/src/runtime/connections/events/lifecycle-step.js +1 -0
- package/dist/src/runtime/connections/events/owner.d.ts +38 -0
- package/dist/src/runtime/connections/events/owner.js +1 -0
- package/dist/src/runtime/connections/events/path.d.ts +4 -0
- package/dist/src/runtime/connections/events/path.js +1 -0
- package/dist/src/runtime/connections/events/state.d.ts +37 -0
- package/dist/src/runtime/connections/events/state.js +1 -0
- package/dist/src/runtime/connections/events/workflow.d.ts +28 -0
- package/dist/src/runtime/connections/events/workflow.js +1 -0
- package/dist/src/runtime/connections/mcp-client.d.ts +4 -2
- package/dist/src/runtime/connections/mcp-client.js +1 -1
- package/dist/src/runtime/connections/openapi-client.js +1 -1
- package/dist/src/runtime/connections/scoped-authorization.js +1 -1
- package/dist/src/runtime/resolve-connection.js +1 -1
- package/dist/src/runtime/schedules/collection-client.d.ts +0 -2
- package/dist/src/runtime/schedules/collection-client.js +1 -1
- package/dist/src/runtime/types.d.ts +11 -0
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +2 -2
- package/dist/src/setup/scaffold/update/channels.js +1 -1
- package/dist/src/setup/scaffold/update/connections.js +2 -2
- package/dist/src/setup/scaffold/version-tokens.d.ts +1 -1
- package/dist/src/setup/scaffold/version-tokens.js +1 -1
- package/dist/src/shared/agent-definition.d.ts +12 -4
- package/dist/src/shared/connection-events.d.ts +84 -0
- package/dist/src/shared/connection-events.js +1 -0
- package/dist/src/shared/connection-types.d.ts +10 -0
- package/dist/src/shared/validate-authorization.js +1 -1
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/no-reply.d.ts +5 -0
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/dist/src/tracing/eve/agent-approval-instrumentation.d.ts +2 -2
- package/dist/src/tracing/eve/agent-channel-delivery-instrumentation.js +1 -1
- package/dist/src/tracing/eve/agent-memory-instrumentation.d.ts +2 -2
- package/dist/src/tracing/eve/agent-memory-instrumentation.js +1 -1
- package/dist/src/tracing/eve/agent-otel-provider.d.ts +1 -1
- package/dist/src/tracing/eve/agent-tool-instrumentation.d.ts +3 -3
- package/dist/src/tracing/eve/agent-trace-context.js +1 -1
- package/dist/src/tracing/eve/agent-trace-state.d.ts +1 -1
- package/dist/src/tracing/eve/connection-events.d.ts +25 -0
- package/dist/src/tracing/eve/connection-events.js +1 -0
- package/dist/src/tracing/eve/content-span-processor.js +1 -1
- package/dist/src/tracing/eve/delegation.js +1 -1
- package/dist/src/tracing/eve/gateway.d.ts +1 -1
- package/dist/src/tracing/eve/install-instrumentation-runtime.js +1 -1
- package/dist/src/tracing/eve/invoke-tool-span.js +1 -1
- package/dist/src/tracing/eve/mcp.d.ts +2 -1
- package/dist/src/tracing/eve/mcp.js +1 -1
- package/dist/src/tracing/eve/metadata.d.ts +1 -1
- package/dist/src/tracing/eve/operation-input.d.ts +2 -2
- package/dist/src/tracing/eve/operation-input.js +1 -1
- package/dist/src/tracing/eve/otel-declaration.d.ts +5 -0
- package/dist/src/tracing/eve/otel-registration.d.ts +2 -2
- package/dist/src/tracing/eve/otel-registration.js +1 -1
- package/dist/src/tracing/eve/profile.d.ts +1 -1
- package/dist/src/tracing/eve/session.d.ts +2 -2
- package/dist/src/tracing/local/trace-summary.js +1 -1
- package/docs/agent-config.md +38 -13
- package/docs/code-extension.mdx +28 -0
- package/docs/concepts/built-in-tools.md +2 -0
- package/docs/connections/mcp.mdx +105 -0
- package/docs/connections/openapi.mdx +2 -0
- package/docs/guides/instrumentation/otel.mdx +10 -0
- package/docs/sandbox/vercel.mdx +46 -0
- package/package.json +8 -8
- package/dist/src/compiled/_chunks/node/chunk-6QHBXN7B-gl4n6nmi.js +0 -12
- package/dist/src/compiled/_chunks/node/dist-DYDVZ-FS.js +0 -98
- package/dist/src/compiled/_chunks/node/dist-iEFkK9qw.js +0 -6
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/agent-transport.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/ai-sdk-payload.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/otel-error.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/otel-ids.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/otel.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/adapters/serialization.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/ai-sdk.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/ai-sdk.js +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/capture.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/activation.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/attributes.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/content-policy.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/context.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/delegation.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/mcp.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/scopes.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/snapshot.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/span-kinds.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/types.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/core/writer.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/delegation.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/delegation.js +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/operations.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/otel.d.ts +0 -0
- /package/dist/src/compiled/{@eve/tracing → @vercel/agent-runs}/otel.js +0 -0
package/docs/agent-config.md
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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
|
-
|
|
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
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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
|
|
package/docs/code-extension.mdx
CHANGED
|
@@ -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:
|
package/docs/connections/mcp.mdx
CHANGED
|
@@ -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 })`.
|
package/docs/sandbox/vercel.mdx
CHANGED
|
@@ -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.
|
|
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.
|
|
573
|
-
"@chat-adapter/state-memory": "4.
|
|
574
|
-
"@chat-adapter/twilio": "4.
|
|
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.
|
|
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.
|
|
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.
|
|
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=/^(?:>|<|#{1,6}(?=[ \t\n]|$)|[-+*](?=[ \t\n]|$)|`{3,}|~{3,}|(?:[-*_][ \t]*){3,}(?=\n|$))/,s=/^(\d{1,9})([.)])(?=[ \t\n]|$)/;function c(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)}function l(e){return e.replace(/</g,`<`).replace(/>/g,`>`).replace(/&/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(`>`)}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};
|