eve 0.26.2 → 0.27.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 +33 -0
- package/dist/src/channel/resolve-active-session.d.ts +4 -0
- package/dist/src/channel/resolve-active-session.js +1 -0
- package/dist/src/channel/routes.d.ts +11 -0
- package/dist/src/cli/dev/tui/vercel-trusted-sources-policy.d.ts +1 -1
- package/dist/src/cli/dev/tui/vercel-trusted-sources.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +16 -16
- package/dist/src/compiled/@ai-sdk/anthropic/index.js +2 -2
- package/dist/src/compiled/@ai-sdk/google/index.d.ts +9 -2
- package/dist/src/compiled/@ai-sdk/google/index.js +6 -6
- package/dist/src/compiled/@ai-sdk/mcp/index.d.ts +18 -3
- package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
- package/dist/src/compiled/@ai-sdk/openai/index.d.ts +285 -24
- package/dist/src/compiled/@ai-sdk/openai/index.js +2 -2
- package/dist/src/compiled/@ai-sdk/otel/index.js +1 -1
- package/dist/src/compiled/@ai-sdk/provider-utils/index.d.ts +7 -3
- package/dist/src/compiled/@vercel/oidc/index.js +28 -2
- package/dist/src/compiled/@vercel/sandbox/api-client/api-client.d.ts +11 -0
- package/dist/src/compiled/@vercel/sandbox/api-client/validators.d.ts +7 -0
- package/dist/src/compiled/@vercel/sandbox/command.d.ts +8 -0
- package/dist/src/compiled/@vercel/sandbox/execution-context.d.ts +116 -0
- package/dist/src/compiled/@vercel/sandbox/index.d.ts +3 -1
- package/dist/src/compiled/@vercel/sandbox/index.js +20 -19
- package/dist/src/compiled/@vercel/sandbox/network-policy.d.ts +13 -5
- package/dist/src/compiled/@vercel/sandbox/sandbox-user.d.ts +212 -0
- package/dist/src/compiled/@vercel/sandbox/sandbox.d.ts +133 -2
- package/dist/src/compiled/@vercel/sandbox/session.d.ts +2 -1
- package/dist/src/compiled/@vercel/sandbox/snapshot.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/create-hook.d.ts +41 -22
- package/dist/src/compiled/@workflow/core/flushable-stream.d.ts +29 -0
- package/dist/src/compiled/@workflow/core/global.d.ts +2 -0
- package/dist/src/compiled/@workflow/core/index.js +2 -2
- package/dist/src/compiled/@workflow/core/private.d.ts +6 -17
- package/dist/src/compiled/@workflow/core/private.js +1 -1
- package/dist/src/compiled/@workflow/core/replay-payload-cache.d.ts +56 -0
- package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +11 -0
- package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +6 -4
- package/dist/src/compiled/@workflow/core/runtime/resume-hook.d.ts +4 -1
- package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +39 -0
- package/dist/src/compiled/@workflow/core/runtime.js +3 -3
- package/dist/src/compiled/@workflow/core/serialization.d.ts +44 -4
- package/dist/src/compiled/@workflow/core/symbols.d.ts +13 -0
- package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/@workflow/errors/error-codes.d.ts +2 -0
- package/dist/src/compiled/@workflow/errors/index.d.ts +14 -0
- package/dist/src/compiled/@workflow/errors/index.js +1 -1
- package/dist/src/compiled/@workflow/world/events.d.ts +15 -0
- package/dist/src/compiled/@workflow/world/hooks.d.ts +2 -1
- package/dist/src/compiled/@workflow/world/interfaces.d.ts +77 -4
- package/dist/src/compiled/@workflow/world-local/index.js +4 -4
- package/dist/src/compiled/@workflow/world-vercel/index.js +16 -16
- package/dist/src/compiled/_chunks/node/{auth-BuQkq4Gr.js → auth-l7F2PF2b.js} +2 -2
- package/dist/src/compiled/_chunks/node/{version-DD-FX9rK.js → version-CjHTLx2a.js} +1 -1
- package/dist/src/compiled/_chunks/node/virtual-loader-Cwgujv7l.js +1 -0
- package/dist/src/compiled/_chunks/workflow/attribute-changes-Dk1fP6vt.js +20 -0
- package/dist/src/compiled/_chunks/workflow/{chunk-BHKSVoKr.js → chunk-BTyA9uPd.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/dist-B3qkUnLJ.js +3 -0
- package/dist/src/compiled/_chunks/workflow/{dist-CSfKNxQW.js → dist-BX517Nmz.js} +2 -2
- package/dist/src/compiled/_chunks/workflow/{dist-zLevmMyU.js → dist-C_VDTghO.js} +10 -10
- package/dist/src/compiled/_chunks/workflow/{dist-CttsoN4D.js → dist-CrxV2rsR.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{functions-PT9ri9Hu.js → functions-Dv8dc_-I.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/resume-hook-czpG5xnP.js +1 -0
- package/dist/src/compiled/_chunks/workflow/run-6zaMjFY6.js +1 -0
- package/dist/src/compiled/_chunks/workflow/sleep-B2u06FWc.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{src-CQuMexnO.js → src-D1EltLDA.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{token-CaY0nA5J.js → token-Cz223z3C.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/token-DWqA5-DA.js +1 -0
- package/dist/src/compiled/_chunks/workflow/token-util-B6qBs3-0.js +27 -0
- package/dist/src/compiled/_chunks/workflow/{undici-fb54XL8i.js → undici-C2ZhYnV9.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/wrapper-Cc2otuUR.js +6 -0
- package/dist/src/compiled/env-runner/index.js +1 -1
- package/dist/src/compiled/env-runner/node-worker.js +1 -1
- package/dist/src/compiled/eventsource-parser/stream/index.d.ts +16 -3
- package/dist/src/compiled/jose/index.js +1 -1
- package/dist/src/compiler/compile-from-memory.d.ts +5 -0
- package/dist/src/compiler/compile-from-memory.js +1 -1
- package/dist/src/compiler/extension-compatibility.d.ts +10 -10
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/execution/deliver-payloads.d.ts +1 -1
- package/dist/src/execution/deliver-payloads.js +1 -1
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/compaction-prompt.d.ts +19 -1
- package/dist/src/harness/compaction-prompt.js +7 -5
- package/dist/src/harness/compaction.d.ts +4 -11
- package/dist/src/harness/compaction.js +1 -1
- package/dist/src/harness/prompt-cache.d.ts +16 -5
- package/dist/src/harness/prompt-cache.js +1 -1
- package/dist/src/harness/session-limit-continuation.d.ts +8 -0
- package/dist/src/harness/session-limit-continuation.js +1 -1
- package/dist/src/harness/session-limit-enforcement.d.ts +9 -6
- package/dist/src/harness/session-limit-enforcement.js +1 -1
- package/dist/src/harness/stale-input-responses.d.ts +21 -3
- package/dist/src/harness/stale-input-responses.js +2 -2
- package/dist/src/harness/token-estimate.d.ts +9 -0
- package/dist/src/harness/token-estimate.js +1 -0
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/harness/turn-cancellation.d.ts +13 -0
- package/dist/src/harness/turn-cancellation.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/host/copy-host-middleware.js +1 -1
- package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
- package/dist/src/internal/workflow-bundle/vercel-workflow-output.js +1 -1
- package/dist/src/node_modules/.pnpm/@vercel_sdk@1.28.8/node_modules/@vercel/sdk/esm/models/updateprojectblock.js +1 -0
- package/dist/src/node_modules/.pnpm/@vercel_sdk@1.28.8/node_modules/@vercel/sdk/esm/models/updateprojectprojectsbranchmatcher.js +1 -0
- package/dist/src/packages/eve-catalog/src/index.js +1 -1
- package/dist/src/public/channels/auth.d.ts +59 -9
- package/dist/src/public/channels/auth.js +1 -1
- package/dist/src/public/channels/discord/defaults.js +1 -1
- package/dist/src/public/channels/linear/api.d.ts +2 -0
- package/dist/src/public/channels/linear/api.js +3 -1
- package/dist/src/public/channels/linear/defaults.js +2 -2
- package/dist/src/public/channels/linear/hitl.d.ts +8 -13
- package/dist/src/public/channels/linear/hitl.js +3 -3
- package/dist/src/public/channels/linear/index.d.ts +1 -1
- package/dist/src/public/channels/linear/index.js +1 -1
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/channels/slack/api.d.ts +20 -0
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/channels/slack/defaults.js +1 -1
- package/dist/src/public/channels/slack/inbound.d.ts +31 -0
- package/dist/src/public/channels/slack/inbound.js +1 -1
- package/dist/src/public/channels/slack/index.d.ts +2 -2
- package/dist/src/public/channels/slack/slackChannel.d.ts +72 -4
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/teams/defaults.js +2 -2
- package/dist/src/public/channels/teams/index.d.ts +1 -1
- package/dist/src/public/channels/teams/teamsChannel.d.ts +7 -2
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/telegram/defaults.js +1 -1
- package/dist/src/public/definitions/channel.d.ts +1 -1
- package/dist/src/public/next/index.js +1 -1
- package/dist/src/public/nuxt/index.d.ts +1 -1
- package/dist/src/public/nuxt/index.js +1 -1
- package/dist/src/public/nuxt/module.d.ts +10 -24
- package/dist/src/public/nuxt/module.js +1 -1
- package/dist/src/public/nuxt/routing.d.ts +5 -39
- package/dist/src/public/nuxt/routing.js +1 -1
- package/dist/src/public/nuxt/vercel-services.d.ts +117 -0
- package/dist/src/public/nuxt/vercel-services.js +1 -0
- package/dist/src/runtime/framework-tools/connection-search-dynamic.js +2 -1
- package/dist/src/runtime/framework-tools/todo.js +1 -1
- package/dist/src/runtime/governance/auth/http-basic.js +1 -1
- 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/create/web-template.d.ts +1 -1
- package/dist/src/setup/scaffold/create/web-template.js +90 -5
- package/dist/src/setup/scaffold/update/channels.js +2 -2
- package/dist/src/setup/scaffold/update/connections.js +1 -1
- package/dist/src/{public/next → shared}/resolve-eve-binary.d.ts +1 -1
- package/docs/agent-config.md +10 -5
- package/docs/channels/slack.mdx +76 -10
- package/docs/channels/teams.mdx +10 -3
- package/docs/extensions.md +115 -77
- package/docs/guides/auth-and-route-protection.md +14 -1
- package/docs/guides/deployment/vercel.mdx +1 -1
- package/docs/guides/frontend/nuxt.mdx +22 -1
- package/docs/guides/frontend/overview.mdx +2 -0
- package/docs/meta.json +1 -0
- package/package.json +22 -22
- package/dist/src/compiled/@workflow/core/step-hydration-cache.d.ts +0 -148
- package/dist/src/compiled/_chunks/node/virtual-loader-B8K8w9cr.js +0 -1
- package/dist/src/compiled/_chunks/workflow/attribute-changes-CXiYB8h9.js +0 -20
- package/dist/src/compiled/_chunks/workflow/dist-BYo8Gno2.js +0 -3
- package/dist/src/compiled/_chunks/workflow/resume-hook-CHXbXuRZ.js +0 -1
- package/dist/src/compiled/_chunks/workflow/run-BjtAGa3_.js +0 -1
- package/dist/src/compiled/_chunks/workflow/sleep-BJAv0MFP.js +0 -1
- package/dist/src/compiled/_chunks/workflow/token-D4VIwGlD.js +0 -1
- package/dist/src/compiled/_chunks/workflow/wrapper-ulTvoTdW.js +0 -6
- package/dist/src/node_modules/.pnpm/@vercel_sdk@1.28.1/node_modules/@vercel/sdk/esm/models/updateprojectprojectsaction.js +0 -1
- package/dist/src/node_modules/.pnpm/@vercel_sdk@1.28.1/node_modules/@vercel/sdk/esm/models/updateprojectprojectsoptionsallowlist.js +0 -1
- package/dist/src/public/nuxt/vercel-json.d.ts +0 -17
- package/dist/src/public/nuxt/vercel-json.js +0 -1
- /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/lib/primitives.js +0 -0
- /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/lib/schemas.js +0 -0
- /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/models/aclaction.js +0 -0
- /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/models/sdkvalidationerror.js +0 -0
- /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/defaultToZeroValue.js +0 -0
- /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/fp.js +0 -0
- /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/primitives.js +0 -0
- /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/rfcdate.js +0 -0
- /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/smartUnion.js +0 -0
- /package/dist/src/node_modules/.pnpm/{@vercel_sdk@1.28.1 → @vercel_sdk@1.28.8}/node_modules/@vercel/sdk/esm/types/unrecognized.js +0 -0
- /package/dist/src/{public/next → shared}/resolve-eve-binary.js +0 -0
package/docs/channels/slack.mdx
CHANGED
|
@@ -36,7 +36,11 @@ export default slackChannel({
|
|
|
36
36
|
});
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
`connectSlackCredentials` returns `{ botToken, webhookVerifier }`, keeping token rotation, multi-workspace tenancy, and request verification inside Connect rather than your code.
|
|
39
|
+
`connectSlackCredentials` returns `{ botToken, webhookVerifier }`, keeping token rotation, multi-workspace tenancy, and request verification inside Connect rather than your code.
|
|
40
|
+
|
|
41
|
+
### Deploy
|
|
42
|
+
|
|
43
|
+
Deploy once the trigger destination and channel file are ready:
|
|
40
44
|
|
|
41
45
|
```bash
|
|
42
46
|
VERCEL_USE_EXPERIMENTAL_FRAMEWORKS=1 vercel deploy --prod
|
|
@@ -44,17 +48,79 @@ VERCEL_USE_EXPERIMENTAL_FRAMEWORKS=1 vercel deploy --prod
|
|
|
44
48
|
|
|
45
49
|
`VERCEL_USE_EXPERIMENTAL_FRAMEWORKS=1` lets the Vercel CLI recognize eve as a framework during the build. eve's own setup commands set the same flag.
|
|
46
50
|
|
|
47
|
-
## How the channel handles
|
|
51
|
+
## How the channel handles inbound events
|
|
52
|
+
|
|
53
|
+
### Message hooks
|
|
54
|
+
|
|
55
|
+
Message hooks return `{ auth }` to dispatch, `null` to drop, or `{ auth, context }` to inject background into history.
|
|
56
|
+
|
|
57
|
+
- `onMessage(ctx, message)` handles Slack `message` events. `ctx.isBotMentioned()` and `ctx.isSubscribed()` support mention and active-thread policies; check `message.author?.isBot` when bot messages should be ignored.
|
|
58
|
+
- `onAppMention(ctx, message)` handles only `app_mention` and takes precedence over `onMessage`. Its default derives workspace-scoped auth and posts `Thinking…`.
|
|
59
|
+
- `onDirectMessage(ctx, message)` handles only DMs and takes precedence over `onMessage`. Bot-authored messages and edits are filtered first; Slack requires `message.im` and `im:history`.
|
|
60
|
+
|
|
61
|
+
| Incoming event | Handler order |
|
|
62
|
+
| ---------------------- | ------------------------------------------------------------------- |
|
|
63
|
+
| App mention | `onAppMention` → `onMessage` → `onEvent` → built-in mention default |
|
|
64
|
+
| Direct message | `onDirectMessage` → `onMessage` → `onEvent` → built-in DM default |
|
|
65
|
+
| Other Slack message | `onMessage` → `onEvent` → ignore |
|
|
66
|
+
| Other Events API event | `onEvent` → ignore |
|
|
67
|
+
|
|
68
|
+
Only the first available handler runs. A message hook returning `null` drops the message; it does not continue down the table.
|
|
69
|
+
|
|
70
|
+
`onInteraction(action, ctx)` separately handles `block_actions` callbacks not consumed by HITL. eve attaches the triggering Slack user id to the same model message as its text, preserving speaker attribution without profile lookups.
|
|
71
|
+
|
|
72
|
+
#### Continue conversations without repeated mentions
|
|
73
|
+
|
|
74
|
+
Use `onMessage` to handle explicit mentions and continue replies in threads with an active eve session:
|
|
75
|
+
|
|
76
|
+
```ts title="agent/channels/slack.ts"
|
|
77
|
+
export default slackChannel({
|
|
78
|
+
credentials: connectSlackCredentials("slack/my-agent"),
|
|
79
|
+
async onMessage(ctx, message) {
|
|
80
|
+
if (message.author?.isBot) return null;
|
|
81
|
+
const isDirectMessage = message.raw.channel_type === "im";
|
|
82
|
+
return isDirectMessage || ctx.isBotMentioned() || (await ctx.isSubscribed())
|
|
83
|
+
? { auth: null }
|
|
84
|
+
: null;
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`isBotMentioned()` identifies an explicit mention. `isSubscribed()` checks whether the message belongs to a thread with an active eve session. For Vercel Connect, open **Advanced** when creating the connector and add `message.channels` under **Trigger Event Types** and `channels:history` under **Bot Scopes**. Private channels additionally need `message.groups` and `groups:history`.
|
|
90
|
+
|
|
91
|
+
### Other Events API callbacks
|
|
48
92
|
|
|
49
|
-
|
|
93
|
+
Use `onEvent` for subscribed events such as `reaction_added`, `team_join`, or `channel_created`. It receives the raw, open-ended Slack event and owns control flow. `ctx.receive(options)` is the current Slack channel's pre-bound form of the schedule API's `receive(slack, options)`: call it zero, one, or many times to start turns. Each call accepts `message`, `target`, and `auth`, and returns the resulting session.
|
|
94
|
+
|
|
95
|
+
```ts title="agent/channels/slack.ts"
|
|
96
|
+
import { connectSlackCredentials } from "@vercel/connect/eve";
|
|
97
|
+
import { slackChannel } from "eve/channels/slack";
|
|
98
|
+
|
|
99
|
+
const onboardingChannels = ["C0123ABC", "C0456DEF"];
|
|
100
|
+
|
|
101
|
+
export default slackChannel({
|
|
102
|
+
credentials: connectSlackCredentials("slack/my-agent"),
|
|
103
|
+
async onEvent({ receive }, event) {
|
|
104
|
+
if (event.type !== "team_join") return;
|
|
105
|
+
|
|
106
|
+
await Promise.all(
|
|
107
|
+
onboardingChannels.map((channelId) =>
|
|
108
|
+
receive({
|
|
109
|
+
message: `A user joined the Slack workspace. Onboard them from this event:\n${JSON.stringify(event)}`,
|
|
110
|
+
target: { channelId },
|
|
111
|
+
auth: null,
|
|
112
|
+
}),
|
|
113
|
+
),
|
|
114
|
+
);
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
```
|
|
50
118
|
|
|
51
|
-
|
|
119
|
+
The webhook invocation already keeps an awaited `onEvent` handler alive. Use `ctx.waitUntil(promise)` for deliberately detached work, matching a handler-form schedule. `ctx.slack.request(operation, body)` provides workspace-scoped Slack Web API access, while `ctx.envelope` carries delivery metadata such as `team_id`, `event_id`, and `event_time`. Calls to `ctx.receive` automatically seed the callback's team id into Slack session state.
|
|
52
120
|
|
|
53
|
-
|
|
54
|
-
- `onDirectMessage(ctx, message)` handles `message.im` events (needs `im:history` scope). Bot-authored messages and edits are filtered out first.
|
|
55
|
-
- `onInteraction(action, ctx)` handles `block_actions` callbacks not consumed by HITL.
|
|
121
|
+
`onEvent` is the raw fallback after the message hooks. If an event is not claimed by `onAppMention`, `onDirectMessage`, or `onMessage`, an authored `onEvent` receives it; otherwise eve applies the built-in mention/DM default or ignores it.
|
|
56
122
|
|
|
57
|
-
|
|
123
|
+
`onEvent` covers JSON `event_callback` deliveries only. URL verification, slash commands, and interactive payloads do not reach it. Add every desired event and required OAuth scope to the Slack app's Event Subscriptions configuration; eve can only handle events Slack sends.
|
|
58
124
|
|
|
59
125
|
You get the triggering mention by default, but not the earlier replies in the thread. Enable `threadContext` to fetch and inject them with every message attributed by stable Slack user id. Use `since: "last-agent-reply"` so repeated mentions inject only what is new:
|
|
60
126
|
|
|
@@ -78,7 +144,7 @@ export default slackChannel({
|
|
|
78
144
|
|
|
79
145
|
### Slack API calls outside a handler
|
|
80
146
|
|
|
81
|
-
Inside webhook-side handlers (`onAppMention`, `onInteraction`, `events`),
|
|
147
|
+
Inside webhook-side handlers (`onAppMention`, `onEvent`, `onInteraction`, `events`),
|
|
82
148
|
`ctx.slack.request(operation, body)` is the raw-API escape hatch. Outside
|
|
83
149
|
those contexts there is no handle — a schedule resolving reactions on old
|
|
84
150
|
messages, for example, has no inbound Slack request. For that, call the
|
|
@@ -105,7 +171,7 @@ when you need the bearer token itself.
|
|
|
105
171
|
|
|
106
172
|
### Delivery
|
|
107
173
|
|
|
108
|
-
The default handlers reply in-thread and show progress. Typing indicators post automatically: `Thinking…` on inbound, `Working…` on `turn.started`, a truncated reasoning snippet on `reasoning.appended`, and an action label on `actions.requested` — the tool name plus its most telling argument (`grep useEveAgent`, `read_file agent/agent.ts`), the subagent or remote-agent name for dispatched calls, and `+N more` when the model requests several actions at once. The model's own pre-tool narration, when present, takes precedence over the derived label. Reasoning snippets build progressively: extensions of at least four characters appear immediately, while smaller streamed deltas use the five-second refresh interval to avoid one Slack request per token. Override `events["reasoning.appended"]` if you prefer generic wording. Override
|
|
174
|
+
The default handlers reply in-thread and show progress. Typing indicators post automatically: `Thinking…` on inbound, `Working…` on `turn.started`, a truncated reasoning snippet on `reasoning.appended`, and an action label on `actions.requested` — the tool name plus its most telling argument (`grep useEveAgent`, `read_file agent/agent.ts`), the subagent or remote-agent name for dispatched calls, and `+N more` when the model requests several actions at once. The model's own pre-tool narration, when present, takes precedence over the derived label. Reasoning snippets build progressively: extensions of at least four characters appear immediately, while smaller streamed deltas use the five-second refresh interval to avoid one Slack request per token. Override `events["reasoning.appended"]` if you prefer generic wording. Override an inbound handler or the `events` handlers to customize.
|
|
109
175
|
|
|
110
176
|
Outbound text preserves bare `@` tokens as literal text. To mention a user, embed Slack's `<@USER_ID>` syntax directly or use `channel.thread.mentionUser(userId)`.
|
|
111
177
|
|
package/docs/channels/teams.mdx
CHANGED
|
@@ -28,17 +28,24 @@ By default the channel mounts at `POST /eve/v1/teams`. Point your Azure Bot or T
|
|
|
28
28
|
|
|
29
29
|
The default `onMessage` handles two cases: personal-chat messages, and channel or group-chat messages that mention the bot directly. Ambient resource-specific-consent messages are dropped unless you override it. Before dispatch, eve strips the mention, adds a `<teams_context>` block, and scopes channel and group threads by root activity id (`replyToId ?? id`).
|
|
30
30
|
|
|
31
|
+
For example, use the contextual `isSubscribed()` helper to continue active threads without requiring another mention:
|
|
32
|
+
|
|
31
33
|
```ts
|
|
32
34
|
import { defaultTeamsAuth, teamsChannel } from "eve/channels/teams";
|
|
33
35
|
|
|
34
36
|
export default teamsChannel({
|
|
35
|
-
onMessage(ctx, message) {
|
|
36
|
-
if (message.
|
|
37
|
-
|
|
37
|
+
async onMessage(ctx, message) {
|
|
38
|
+
if (message.from.role === "bot" || message.from.id === message.recipient.id) return null;
|
|
39
|
+
const isDirectMessage = message.scope === "personal";
|
|
40
|
+
return isDirectMessage || message.isBotMentioned || (await ctx.isSubscribed())
|
|
41
|
+
? { auth: defaultTeamsAuth(message) }
|
|
42
|
+
: null;
|
|
38
43
|
},
|
|
39
44
|
});
|
|
40
45
|
```
|
|
41
46
|
|
|
47
|
+
`isSubscribed()` checks whether the conversation has previously involved the agent.
|
|
48
|
+
|
|
42
49
|
### Delivery
|
|
43
50
|
|
|
44
51
|
Replies post as Markdown (`textFormat: "markdown"`), with oversized text split across messages and a typing indicator sent on turn start and action requests.
|
package/docs/extensions.md
CHANGED
|
@@ -1,39 +1,48 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Extensions"
|
|
3
|
-
description: "
|
|
3
|
+
description: "Publish reusable eve capabilities as an npm package, then install and mount them in an agent."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Extensions package eve tools, connections, skills, instruction fragments, and hooks. A publisher builds and distributes a package; a consumer installs it and mounts it in an agent.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
This enables sharing many different capability sets. A browser extension might include several tools for navigating a site. A memory extension could use hooks to capture context and tools to recall it. A self-improving extension could pair hooks with dynamic instructions.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Publisher: create and publish an extension
|
|
11
|
+
|
|
12
|
+
### Create the package
|
|
13
|
+
|
|
14
|
+
Start with the extension scaffold:
|
|
11
15
|
|
|
12
16
|
```bash
|
|
13
17
|
npx eve@latest extension init my-crm
|
|
14
18
|
```
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
The command creates the package, installs dependencies, and initializes Git. It includes `extension/extension.ts`, TypeScript configuration, and the package metadata required to build and publish.
|
|
17
21
|
|
|
18
|
-
An extension
|
|
22
|
+
An extension uses the same file conventions as an agent for its contributions:
|
|
19
23
|
|
|
20
24
|
```
|
|
21
25
|
@acme/crm/
|
|
22
26
|
package.json
|
|
23
27
|
extension/
|
|
24
|
-
extension.ts
|
|
28
|
+
extension.ts
|
|
25
29
|
tools/search.ts
|
|
26
30
|
connections/api.ts
|
|
27
31
|
skills/triage/SKILL.md
|
|
32
|
+
instructions.md
|
|
28
33
|
hooks/audit.ts
|
|
29
|
-
lib/http.ts
|
|
34
|
+
lib/http.ts
|
|
30
35
|
```
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
Each listed slot accepts the same authored forms as its agent counterpart. Static and dynamic tools, skills, and instructions all work in an extension: `extension/instructions.ts` is as valid as `extension/instructions.md`, and `extension/tools/` can contain `defineDynamic(...)`.
|
|
38
|
+
|
|
39
|
+
Names come from paths, so call the tool `search`, not `crm_search`; the consumer's mount adds the `crm__` prefix. Keep shared code in `extension/lib/`.
|
|
33
40
|
|
|
34
|
-
|
|
41
|
+
Keep agent configuration, sandboxes, schedules, and nested extensions in the consumer's agent.
|
|
35
42
|
|
|
36
|
-
|
|
43
|
+
### Add configuration and contributions
|
|
44
|
+
|
|
45
|
+
The publisher's `extension/extension.ts` default-exports a `defineExtension` handle. Give it a [Standard Schema](https://standardschema.dev) when consumers need to provide settings:
|
|
37
46
|
|
|
38
47
|
```ts title="extension/extension.ts"
|
|
39
48
|
import { defineExtension } from "eve/extension";
|
|
@@ -42,40 +51,41 @@ import { z } from "zod";
|
|
|
42
51
|
export default defineExtension({
|
|
43
52
|
config: z.object({
|
|
44
53
|
apiKey: z.string(),
|
|
45
|
-
baseUrl: z.string().default("https://api.acme.example"),
|
|
54
|
+
baseUrl: z.string().url().default("https://api.acme.example"),
|
|
46
55
|
}),
|
|
47
56
|
});
|
|
48
57
|
```
|
|
49
58
|
|
|
50
|
-
|
|
59
|
+
Contributions import that handle to read the validated configuration. Defaults have already been applied:
|
|
51
60
|
|
|
52
61
|
```ts title="extension/tools/search.ts"
|
|
53
62
|
import { defineTool } from "eve/tools";
|
|
63
|
+
import { z } from "zod";
|
|
54
64
|
|
|
55
65
|
import extension from "../extension";
|
|
56
66
|
|
|
57
67
|
export default defineTool({
|
|
58
68
|
description: "Search the CRM.",
|
|
59
|
-
inputSchema: {
|
|
69
|
+
inputSchema: z.object({ query: z.string() }),
|
|
60
70
|
async execute({ query }) {
|
|
61
|
-
const { apiKey, baseUrl } = extension.config;
|
|
71
|
+
const { apiKey, baseUrl } = extension.config;
|
|
72
|
+
return { query, baseUrl, authenticated: apiKey.length > 0 };
|
|
62
73
|
},
|
|
63
74
|
});
|
|
64
75
|
```
|
|
65
76
|
|
|
66
|
-
|
|
77
|
+
If no configuration is needed, export `defineExtension()` and let consumers re-export it directly. Config schemas must validate synchronously.
|
|
67
78
|
|
|
68
|
-
|
|
79
|
+
`defineState` is automatically scoped to the publisher's package, so the same state name does not collide with the consumer or another extension.
|
|
69
80
|
|
|
70
|
-
|
|
81
|
+
### Build and publish
|
|
71
82
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
Declare separate authoring and distribution roots and run `eve extension build` (wired to `build`/`prepare`):
|
|
83
|
+
The scaffold's `package.json` declares separate source and distribution roots:
|
|
75
84
|
|
|
76
85
|
```jsonc title="package.json"
|
|
77
86
|
{
|
|
78
|
-
"name": "
|
|
87
|
+
"name": "my-crm",
|
|
88
|
+
"version": "0.0.0",
|
|
79
89
|
"type": "module",
|
|
80
90
|
"eve": {
|
|
81
91
|
"extension": {
|
|
@@ -84,86 +94,105 @@ Declare separate authoring and distribution roots and run `eve extension build`
|
|
|
84
94
|
},
|
|
85
95
|
},
|
|
86
96
|
"files": ["dist"],
|
|
87
|
-
"
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
{
|
|
98
|
-
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
"
|
|
97
|
+
"exports": {
|
|
98
|
+
".": {
|
|
99
|
+
"types": "./dist/index.d.ts",
|
|
100
|
+
"default": "./dist/index.mjs",
|
|
101
|
+
},
|
|
102
|
+
"./tools": {
|
|
103
|
+
"types": "./dist/tools/index.d.ts",
|
|
104
|
+
"default": "./dist/tools/index.mjs",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
"scripts": {
|
|
108
|
+
"build": "eve extension build",
|
|
109
|
+
"prepare": "eve extension build",
|
|
110
|
+
"typecheck": "tsc",
|
|
111
|
+
},
|
|
112
|
+
"dependencies": {
|
|
113
|
+
"zod": "^x",
|
|
114
|
+
},
|
|
115
|
+
"devDependencies": {
|
|
116
|
+
"@types/node": "^x",
|
|
117
|
+
"eve": "x.y.z",
|
|
118
|
+
"typescript": "^x",
|
|
119
|
+
},
|
|
120
|
+
"peerDependencies": {
|
|
121
|
+
"eve": "*",
|
|
122
|
+
},
|
|
123
|
+
"engines": {
|
|
124
|
+
"node": ">=24",
|
|
104
125
|
},
|
|
105
|
-
"include": ["extension/**/*.ts"],
|
|
106
126
|
}
|
|
107
127
|
```
|
|
108
128
|
|
|
109
|
-
|
|
129
|
+
The scaffold omits `engines` when it creates a workspace package.
|
|
110
130
|
|
|
111
|
-
|
|
131
|
+
Build the package with `eve extension build`:
|
|
112
132
|
|
|
113
|
-
|
|
133
|
+
```bash
|
|
134
|
+
eve extension build
|
|
135
|
+
```
|
|
114
136
|
|
|
115
|
-
|
|
137
|
+
`eve extension build` writes an agent-shaped `dist/extension` tree, copies skill assets, emits declarations, and records compatibility metadata. It also manages the package exports for the mount factory (`@acme/crm`) and tool definitions (`@acme/crm/tools`). Publish `dist/`; consumers do not need the publisher's TypeScript source.
|
|
116
138
|
|
|
117
|
-
|
|
139
|
+
The exact `eve` development pin controls the publisher's authoring API and build tooling. The wildcard peer lets the consumer provide the runtime copy of eve. At consumption time, eve checks generated metadata, not the npm peer range. Do not add eve to regular `dependencies`.
|
|
118
140
|
|
|
119
|
-
|
|
141
|
+
Put runtime packages such as `zod` or an SDK in `dependencies`. If a dependency cannot be bundled, such as a native addon, tell consumers to add it to `build.externalDependencies` in `agent.ts`.
|
|
120
142
|
|
|
121
|
-
|
|
143
|
+
Consumers can now add the built package to an agent.
|
|
122
144
|
|
|
123
|
-
|
|
145
|
+
## Consumer: install and mount an extension
|
|
124
146
|
|
|
125
|
-
|
|
126
|
-
{
|
|
127
|
-
"peerDependencies": { "eve": "*" },
|
|
128
|
-
"devDependencies": { "eve": "0.25.0" },
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
The exact pin makes builds reproducible. Keep it until the extension intentionally upgrades its eve authoring API. `eve extension build` records the capability contracts required by the build, and each consuming eve validates those requirements before it runs the extension.
|
|
147
|
+
A mount gives the publisher's contributions a namespace. Updating the package updates the mounted extension; nothing is copied into the consumer's agent.
|
|
133
148
|
|
|
134
|
-
|
|
149
|
+
### Install the package
|
|
135
150
|
|
|
136
|
-
|
|
151
|
+
Install the extension in the consumer's agent project:
|
|
137
152
|
|
|
138
|
-
|
|
153
|
+
```bash
|
|
154
|
+
npm install @acme/crm
|
|
155
|
+
```
|
|
139
156
|
|
|
140
|
-
|
|
157
|
+
### Mount it
|
|
141
158
|
|
|
142
|
-
|
|
159
|
+
Create a file under `agent/extensions/`. Its filename becomes the mount namespace. Call the publisher's default export when the extension needs configuration:
|
|
143
160
|
|
|
144
161
|
```ts title="agent/extensions/crm.ts"
|
|
145
162
|
import crm from "@acme/crm";
|
|
146
163
|
|
|
147
|
-
export default crm({ apiKey: process.env.CRM_API_KEY });
|
|
164
|
+
export default crm({ apiKey: process.env.CRM_API_KEY! });
|
|
148
165
|
```
|
|
149
166
|
|
|
150
|
-
|
|
167
|
+
Set `CRM_API_KEY` in the consumer's environment, such as `.env.local` for local development.
|
|
168
|
+
|
|
169
|
+
The mount adds `crm__` to named contributions: `tools/search.ts` becomes `crm__search`, and `connections/api.ts` becomes `crm__api`.
|
|
170
|
+
|
|
171
|
+
For a publisher with no configuration, mount its default export directly:
|
|
151
172
|
|
|
152
173
|
```ts title="agent/extensions/gizmo.ts"
|
|
153
174
|
export { default } from "@acme/gizmo";
|
|
154
175
|
```
|
|
155
176
|
|
|
156
|
-
|
|
177
|
+
The same mount shape works with an npm package, a workspace dependency, or a linked local package.
|
|
178
|
+
|
|
179
|
+
### Override a contribution
|
|
157
180
|
|
|
158
|
-
|
|
181
|
+
Use a directory mount to replace or remove a publisher contribution. Put the mount declaration in `extension.ts` and add overrides beside it:
|
|
159
182
|
|
|
160
183
|
```
|
|
161
184
|
agent/extensions/crm/
|
|
162
|
-
extension.ts
|
|
163
|
-
tools/search.ts
|
|
185
|
+
extension.ts
|
|
186
|
+
tools/search.ts
|
|
164
187
|
```
|
|
165
188
|
|
|
166
|
-
|
|
189
|
+
```ts title="agent/extensions/crm/extension.ts"
|
|
190
|
+
import crm from "@acme/crm";
|
|
191
|
+
|
|
192
|
+
export default crm({ apiKey: process.env.CRM_API_KEY! });
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
A same-named consumer tool, connection, or skill wins. To adjust a publisher tool, import it from the package's `./tools` export and define it again:
|
|
167
196
|
|
|
168
197
|
```ts title="agent/extensions/crm/tools/search.ts"
|
|
169
198
|
import { search } from "@acme/crm/tools";
|
|
@@ -173,7 +202,7 @@ import { always } from "eve/tools/approval";
|
|
|
173
202
|
export default defineTool({ ...search, approval: always() });
|
|
174
203
|
```
|
|
175
204
|
|
|
176
|
-
|
|
205
|
+
To remove a publisher tool, use `disableTool()` in its matching slot:
|
|
177
206
|
|
|
178
207
|
```ts title="agent/extensions/crm/tools/search.ts"
|
|
179
208
|
import { disableTool } from "eve/tools";
|
|
@@ -181,13 +210,13 @@ import { disableTool } from "eve/tools";
|
|
|
181
210
|
export default disableTool();
|
|
182
211
|
```
|
|
183
212
|
|
|
184
|
-
|
|
213
|
+
Hooks and instruction fragments are additive, so they cannot be replaced. To replace a dynamic tool, use a dynamic definition in the same slot; dynamic tools win over same-named static tools at runtime. `disableTool()` removes either kind.
|
|
185
214
|
|
|
186
|
-
|
|
215
|
+
The `crm__` prefix is reserved for this directory mount. A consumer cannot override the extension from `agent/tools/`, `agent/connections/`, or another agent-root slot.
|
|
187
216
|
|
|
188
|
-
###
|
|
217
|
+
### Use a publisher tool result in a hook
|
|
189
218
|
|
|
190
|
-
|
|
219
|
+
To retain a publisher tool's result type in a consumer hook, import its definition from `./tools` and pass it to [`toolResultFrom`](/guides/hooks#narrowing-tool-results):
|
|
191
220
|
|
|
192
221
|
```ts title="agent/hooks/narrow-crm.ts"
|
|
193
222
|
import { defineHook } from "eve/hooks";
|
|
@@ -198,14 +227,23 @@ export default defineHook({
|
|
|
198
227
|
events: {
|
|
199
228
|
"action.result"(event) {
|
|
200
229
|
const match = toolResultFrom(event.data.result, search);
|
|
201
|
-
if (match) console.log(match.output);
|
|
230
|
+
if (match) console.log(match.output);
|
|
202
231
|
},
|
|
203
232
|
},
|
|
204
233
|
});
|
|
205
234
|
```
|
|
206
235
|
|
|
207
|
-
|
|
236
|
+
`toolResultFrom` recognizes the mounted `crm__search` result from the original definition, not the namespaced string. Publishers should keep tool descriptions distinct so eve can assign each definition an unambiguous identity.
|
|
237
|
+
|
|
238
|
+
### Compatibility
|
|
239
|
+
|
|
240
|
+
At build time, eve checks the publisher's generated capability metadata. If the extension needs an unsupported capability contract, upgrade eve or install a compatible extension release.
|
|
208
241
|
|
|
209
|
-
##
|
|
242
|
+
## What to read next
|
|
210
243
|
|
|
211
|
-
|
|
244
|
+
- [Tools](/docs/tools): static tools, approval, and tool output
|
|
245
|
+
- [Dynamic capabilities](/docs/guides/dynamic-capabilities): dynamic tools, skills, and instructions
|
|
246
|
+
- [Instructions](/docs/instructions): static and TypeScript instructions
|
|
247
|
+
- [Skills](/docs/skills): package procedures and supporting files
|
|
248
|
+
- [Connections](/docs/connections): integrate external services
|
|
249
|
+
- [Hooks](/docs/guides/hooks): observe agent events
|
|
@@ -41,7 +41,7 @@ export default eveChannel({
|
|
|
41
41
|
- returns `null` / `undefined`: skip to the next entry
|
|
42
42
|
- **throws**: reject with a specific status
|
|
43
43
|
|
|
44
|
-
If every entry skips, the request gets a `401
|
|
44
|
+
If every entry skips, the request gets a `401` whose `WWW-Authenticate` header advertises the challenge scheme(s) the configured entries declare — `Basic` for `httpBasic()`, `Bearer` for the token-based helpers (`jwtHmac`, `jwtEcdsa`, `oidc`, `vercelOidc`), both when you mix them, and `Bearer` as a fallback for entries that don't declare a scheme (custom `AuthFn`s, or an empty array). See [`withAuthChallenges`](#custom-verifiers) to declare a scheme on a custom `AuthFn`.
|
|
45
45
|
|
|
46
46
|
```ts
|
|
47
47
|
import { type AuthFn, localDev, vercelOidc } from "eve/channels/auth";
|
|
@@ -96,6 +96,8 @@ Any other thrown error follows the normal channel failure path. When building a
|
|
|
96
96
|
| `jwtEcdsa(...)` | You verify asymmetric JWTs minted by another system. |
|
|
97
97
|
| `oidc(...)` | You want eve to verify OIDC-issued tokens from an arbitrary issuer. |
|
|
98
98
|
|
|
99
|
+
`httpBasic(credentials, { realm })` accepts an optional `realm`, rendered on the `WWW-Authenticate: Basic` challenge (e.g. `Basic realm="agent", charset="UTF-8"`) so browsers label their native login prompt. It defaults to `"eve"`, ensuring every Basic challenge includes the required realm. Usernames and passwords are normalized to Unicode NFC before comparison, matching the advertised UTF-8 credential encoding.
|
|
100
|
+
|
|
99
101
|
Exercise caution for agents that process non-public, sensitive, regulated, or production data unless you have implemented other access controls.
|
|
100
102
|
|
|
101
103
|
### `localDev()`
|
|
@@ -131,6 +133,17 @@ vercelOidc({
|
|
|
131
133
|
|
|
132
134
|
When none of the shipped helpers fit, write your own `AuthFn` (the array example above) or call the low-level verifiers directly. Each verifier is the pure function sitting behind the matching strategy helper, and returns `{ ok: true, sessionAuth }` or `{ ok: false }`:
|
|
133
135
|
|
|
136
|
+
A custom `AuthFn` doesn't declare a `WWW-Authenticate` scheme by default, so `routeAuth` falls back to `Bearer` for it. Wrap it with `withAuthChallenges(fn, challenges)` to declare the scheme(s) it actually satisfies, so a mixed `auth` array produces an accurate 401:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
import { withAuthChallenges, type AuthFn } from "eve/channels/auth";
|
|
140
|
+
|
|
141
|
+
const apiKeyAuth: AuthFn<Request> = withAuthChallenges(
|
|
142
|
+
(request) => (isValidApiKey(request) ? apiKeySessionAuth : null),
|
|
143
|
+
[{ scheme: "Bearer" }],
|
|
144
|
+
);
|
|
145
|
+
```
|
|
146
|
+
|
|
134
147
|
| Verifier | Behind | Input |
|
|
135
148
|
| -------------------------------------- | -------------- | -------------------------------- |
|
|
136
149
|
| `verifyHttpBasic(header, credentials)` | `httpBasic()` | raw `Authorization` header value |
|
|
@@ -60,7 +60,7 @@ eve deploy
|
|
|
60
60
|
Vercel uses the generated output to configure these services:
|
|
61
61
|
|
|
62
62
|
- **Web runtime**: serves health, session, stream, channel, callback, and schedule routes
|
|
63
|
-
- **Vercel Workflow**: persists and resumes durable runs
|
|
63
|
+
- **Vercel Workflow**: persists and resumes durable runs, with optimistic replay preconditions enabled so stale event-log snapshots reload before they can commit
|
|
64
64
|
- **Vercel Cron**: invokes authored schedules
|
|
65
65
|
- **Vercel Sandbox**: runs sandbox sessions selected by `defaultBackend()`
|
|
66
66
|
|
|
@@ -74,7 +74,7 @@ For a public demo, use `none()` (also from `eve/channels/auth`) to skip authenti
|
|
|
74
74
|
## Dev vs deploy topology
|
|
75
75
|
|
|
76
76
|
- **Local dev.** `npm run dev` starts the eve dev server next to `nuxt dev` and proxies the eve routes through it. As far as the browser knows, everything is the Nuxt origin.
|
|
77
|
-
- **Vercel.**
|
|
77
|
+
- **Vercel.** The web app and the eve runtime deploy as a single project. On Vercel builds the module adds Build Output [`services`](https://vercel.com/docs/services) for eve and `routes` that send `/eve/v1/**` to that service before filesystem routing; the Nuxt app itself remains the default app. No `vercel.json` is required. By default the generated service runs the installed eve binary from the agent root, so the agent directory does not need its own `package.json`. When the agent needs its own build step, set `eveBuildCommand`:
|
|
78
78
|
|
|
79
79
|
```ts
|
|
80
80
|
export default defineNuxtConfig({
|
|
@@ -92,6 +92,27 @@ For a public demo, use `none()` (also from `eve/channels/auth`) to skip authenti
|
|
|
92
92
|
EVE_NUXT_PRODUCTION_PORT=5000 npm run build && npm run preview
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
## Managing vercel.json yourself
|
|
96
|
+
|
|
97
|
+
When `vercel.json` declares [`services`](https://vercel.com/docs/services), the module generates nothing and your configuration owns routing. It must include the eve service (`framework: "eve"`) and a rewrite that exposes the eve transport, or the module fails the build:
|
|
98
|
+
|
|
99
|
+
```json title="vercel.json"
|
|
100
|
+
{
|
|
101
|
+
"services": {
|
|
102
|
+
"web": { "root": ".", "framework": "nuxtjs" },
|
|
103
|
+
"eve": { "root": "agent", "framework": "eve", "buildCommand": "eve build" }
|
|
104
|
+
},
|
|
105
|
+
"rewrites": [{ "source": "/eve/v1/(.*)", "destination": { "service": "eve" } }]
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Migrating from experimentalServices
|
|
110
|
+
|
|
111
|
+
Earlier versions of the module wrote the legacy `experimentalServices` field into `vercel.json`. Vercel no longer routes that model — deployments build both services but every `/eve/v1/*` request returns a platform NOT_FOUND — so the module now ignores the field and warns when it sees one. Migrate either way:
|
|
112
|
+
|
|
113
|
+
- **Generated (default).** Delete `vercel.json` (or just its `experimentalServices` block) and set the project's Framework Preset back to Nuxt.js. The module generates the eve service and its routing on every Vercel build.
|
|
114
|
+
- **Hand-maintained.** Replace `experimentalServices` with the stable `services` and `rewrites` shown above, and keep the "Services" Framework Preset.
|
|
115
|
+
|
|
95
116
|
## What to read next
|
|
96
117
|
|
|
97
118
|
- [`useEveAgent` (Vue)](./use-eve-agent-vue): the composable API
|
|
@@ -100,6 +100,8 @@ Assistant text, reasoning, tool calls, and tool results stream into `data` as th
|
|
|
100
100
|
|
|
101
101
|
`stop()` is local: turns are resumable across disconnects, so detaching the stream never cancels the work — the turn keeps running and billing on the server. To stop the turn itself, POST the session's [cancel route](../../channels/eve#routes); the turn then settles on the stream as `turn.cancelled` followed by `session.waiting`.
|
|
102
102
|
|
|
103
|
+
A chat UI with a Stop button should own the `ClientSession` passed to `useEveAgent`, create it with `preserveCompletedSessions: true`, and call `session.cancel({ turnId })` after observing that turn's `turn.started` event. The `turnId` guard makes a late click a harmless no-op instead of cancelling a newer turn. Keep the stream open until the cancellation boundary arrives; do not use `stop()` for this interaction.
|
|
104
|
+
|
|
103
105
|
After eve confirms an attachment turn with `message.received`, the default reducer projects each
|
|
104
106
|
received attachment as a `file` part on the user message. The part includes `mediaType`, optional
|
|
105
107
|
`filename` and `size`, and a `url` only when the original attachment was browser-resolvable.
|