eve 0.30.7 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/README.md +5 -6
- package/dist/src/acp/adapter.d.ts +10 -4
- package/dist/src/acp/adapter.js +1 -1
- package/dist/src/channel/adapter-context.d.ts +1 -1
- package/dist/src/channel/adapter.d.ts +2 -4
- package/dist/src/channel/adapter.js +1 -1
- package/dist/src/channel/channel-address.d.ts +58 -0
- package/dist/src/channel/channel-address.js +1 -0
- package/dist/src/channel/channel-operations.d.ts +72 -0
- package/dist/src/channel/channel-operations.js +1 -0
- package/dist/src/channel/compiled-channel.d.ts +10 -6
- package/dist/src/channel/cross-channel-receive.d.ts +13 -25
- package/dist/src/channel/cross-channel-receive.js +2 -2
- package/dist/src/channel/receive-target.d.ts +1 -2
- package/dist/src/channel/routes.d.ts +21 -149
- package/dist/src/channel/schedule.d.ts +1 -1
- package/dist/src/channel/schedule.js +1 -1
- package/dist/src/channel/send-input.d.ts +6 -0
- package/dist/src/channel/send-input.js +1 -0
- package/dist/src/channel/session.d.ts +44 -30
- package/dist/src/channel/session.js +1 -1
- package/dist/src/channel/types.d.ts +8 -35
- package/dist/src/chunks/{use-eve-agent-k-XHfrJT.js → use-eve-agent-CF5D6jSV.js} +361 -367
- package/dist/src/chunks/{use-eve-agent-BXMIf5fR.js → use-eve-agent-DbYZLG0h.js} +364 -368
- package/dist/src/cli/commands/agent-prompt/build-and-verify.md +1 -2
- package/dist/src/cli/commands/channel-add-conflicts.js +1 -1
- package/dist/src/cli/commands/info.d.ts +1 -1
- package/dist/src/cli/commands/info.js +1 -1
- package/dist/src/cli/commands/registry-metadata.d.ts +15 -0
- package/dist/src/cli/commands/registry-metadata.js +1 -0
- package/dist/src/cli/commands/registry-package.d.ts +46 -0
- package/dist/src/cli/commands/registry-package.js +1 -0
- package/dist/src/cli/commands/registry.d.ts +1 -1
- package/dist/src/cli/commands/registry.js +4 -4
- package/dist/src/cli/dev/tui/runner.d.ts +1 -1
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/subagent-pump.js +1 -1
- package/dist/src/cli/dev/tui/terminal-renderer.js +2 -2
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/cli/invoke/invoke.d.ts +1 -1
- package/dist/src/cli/invoke/invoke.js +1 -1
- package/dist/src/cli/invoke/result.d.ts +0 -11
- package/dist/src/cli/invoke/result.js +1 -1
- package/dist/src/client/client-error.d.ts +2 -0
- package/dist/src/client/client-error.js +1 -1
- package/dist/src/client/client.d.ts +7 -14
- package/dist/src/client/client.js +1 -1
- package/dist/src/client/eve-agent-store.d.ts +4 -4
- package/dist/src/client/eve-agent-store.js +1 -1
- package/dist/src/client/index.d.ts +3 -2
- package/dist/src/client/index.js +1 -1
- package/dist/src/client/message-reducer-types.d.ts +3 -0
- package/dist/src/client/message-reducer.js +1 -1
- package/dist/src/client/message-response.d.ts +2 -7
- package/dist/src/client/message-response.js +1 -1
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/client/session-controls.d.ts +29 -0
- package/dist/src/client/session-controls.js +1 -0
- package/dist/src/client/session-utils.d.ts +0 -20
- package/dist/src/client/session-utils.js +1 -1
- package/dist/src/client/session.d.ts +26 -90
- package/dist/src/client/session.js +1 -1
- package/dist/src/client/sessions.d.ts +20 -0
- package/dist/src/client/sessions.js +1 -0
- package/dist/src/client/types.d.ts +26 -47
- package/dist/src/compiler/extension-compatibility.d.ts +10 -10
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/normalize-subagent.js +1 -1
- package/dist/src/evals/cli/eval-client.js +1 -1
- package/dist/src/evals/context.js +1 -1
- package/dist/src/evals/session.d.ts +7 -6
- package/dist/src/evals/session.js +1 -1
- package/dist/src/evals/types.d.ts +9 -9
- package/dist/src/execution/agent-handle-dispatch.js +1 -1
- package/dist/src/execution/cancel-descendant-turns-step.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/remote-agent-dispatch.d.ts +1 -3
- package/dist/src/execution/remote-agent-dispatch.js +1 -1
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/runtime-errors.d.ts +1 -1
- package/dist/src/execution/session-command-token.d.ts +2 -0
- package/dist/src/execution/session-command-token.js +1 -1
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/subagent-hitl-proxy.js +1 -1
- package/dist/src/execution/tool-auth.d.ts +1 -1
- package/dist/src/execution/tool-auth.js +1 -1
- package/dist/src/execution/turn-control-receiver.d.ts +2 -2
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/harness/cancelled-turn-emission.d.ts +1 -1
- package/dist/src/harness/cancelled-turn-emission.js +1 -1
- package/dist/src/harness/emission-state.d.ts +25 -0
- package/dist/src/harness/emission-state.js +1 -0
- package/dist/src/harness/emission.d.ts +5 -37
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/handles/prompt.d.ts +22 -3
- package/dist/src/harness/handles/prompt.js +1 -1
- package/dist/src/harness/handles/store.d.ts +0 -5
- package/dist/src/harness/handles/store.js +1 -1
- package/dist/src/harness/ordered-stream-emitter.d.ts +3 -2
- package/dist/src/harness/ordered-stream-emitter.js +1 -1
- package/dist/src/harness/runtime-actions.js +1 -1
- package/dist/src/harness/session-limit-enforcement.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/tools.d.ts +1 -1
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-source-snapshot-local-roots.d.ts +15 -0
- package/dist/src/internal/nitro/dev-runtime-source-snapshot-local-roots.js +1 -0
- package/dist/src/internal/nitro/dev-runtime-source-snapshot.d.ts +14 -2
- package/dist/src/internal/nitro/dev-runtime-source-snapshot.js +1 -1
- package/dist/src/internal/nitro/host/dev-server-http.js +1 -1
- package/dist/src/internal/nitro/routes/channel-dispatch.d.ts +2 -5
- package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
- package/dist/src/internal/nitro/routes/channel-route-context.d.ts +4 -3
- package/dist/src/internal/nitro/routes/channel-route-context.js +1 -1
- package/dist/src/packages/eve-catalog/src/index.js +1 -1
- package/dist/src/protocol/cancel-turn.d.ts +9 -4
- package/dist/src/protocol/cancel-turn.js +1 -1
- package/dist/src/protocol/message.d.ts +27 -17
- package/dist/src/protocol/message.js +2 -2
- package/dist/src/protocol/reset-session.d.ts +1 -1
- package/dist/src/protocol/routes.d.ts +27 -47
- package/dist/src/protocol/routes.js +1 -1
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +19 -21
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
- package/dist/src/public/channels/discord/discordChannel.d.ts +5 -4
- package/dist/src/public/channels/discord/discordChannel.js +1 -1
- package/dist/src/public/channels/eve.d.ts +11 -10
- package/dist/src/public/channels/eve.js +1 -1
- package/dist/src/public/channels/github/dispatch.d.ts +8 -8
- package/dist/src/public/channels/github/dispatch.js +1 -1
- package/dist/src/public/channels/github/githubChannel.d.ts +4 -3
- package/dist/src/public/channels/github/githubChannel.js +1 -1
- package/dist/src/public/channels/github/pr-context.d.ts +1 -1
- package/dist/src/public/channels/index.d.ts +1 -1
- package/dist/src/public/channels/linear/linearChannel.d.ts +4 -3
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/channels/slack/index.d.ts +1 -1
- package/dist/src/public/channels/slack/interactions.d.ts +3 -4
- package/dist/src/public/channels/slack/interactions.js +1 -1
- package/dist/src/public/channels/slack/session-operations.d.ts +37 -0
- package/dist/src/public/channels/slack/session-operations.js +1 -0
- package/dist/src/public/channels/slack/slackChannel.d.ts +56 -74
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/teams/teamsChannel.d.ts +4 -3
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/telegram/telegramChannel.d.ts +5 -4
- package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
- package/dist/src/public/channels/twilio/twilioChannel.d.ts +4 -3
- package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
- package/dist/src/public/definitions/callback-context.d.ts +1 -2
- package/dist/src/public/definitions/channel.d.ts +22 -86
- package/dist/src/public/definitions/channel.js +1 -1
- package/dist/src/public/definitions/hook.d.ts +1 -0
- package/dist/src/public/definitions/remote-agent.js +1 -1
- package/dist/src/public/definitions/schedule.d.ts +16 -16
- package/dist/src/public/definitions/tool.d.ts +5 -5
- package/dist/src/public/schedules/index.d.ts +1 -1
- package/dist/src/react/use-eve-agent.d.ts +7 -4
- package/dist/src/react/use-eve-agent.js +1 -1
- package/dist/src/runtime/agent/bootstrap-model-utils.d.ts +11 -0
- package/dist/src/runtime/agent/bootstrap-model-utils.js +1 -1
- package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
- package/dist/src/runtime/agent/mock-model-fixtures.js +2 -2
- package/dist/src/runtime/prompt/compose.js +1 -1
- package/dist/src/runtime/subagents/dynamic-remote-agent-config.js +1 -1
- package/dist/src/runtime/types.d.ts +2 -2
- package/dist/src/services/inspect-application.d.ts +1 -1
- package/dist/src/services/inspect-application.js +1 -1
- package/dist/src/setup/channel-add-conflicts.js +1 -1
- package/dist/src/setup/integrations/linear/setup.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
- package/dist/src/setup/scaffold/create/web-template.js +29 -17
- package/dist/src/shared/async-iterable.d.ts +2 -0
- package/dist/src/shared/async-iterable.js +1 -0
- package/dist/src/shared/channel-definition.d.ts +7 -7
- package/dist/src/shared/schedule-definition.d.ts +2 -2
- package/dist/src/shared/tool-definition.d.ts +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.d.ts +8 -5
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.d.ts +8 -5
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/README.md +6 -6
- package/docs/channels/chat-sdk.mdx +5 -6
- package/docs/channels/custom.mdx +116 -144
- package/docs/channels/discord.mdx +1 -1
- package/docs/channels/eve.mdx +76 -30
- package/docs/channels/github.mdx +1 -1
- package/docs/channels/linear.mdx +10 -10
- package/docs/channels/overview.mdx +2 -2
- package/docs/channels/slack.mdx +46 -15
- package/docs/channels/telegram.mdx +1 -1
- package/docs/channels/twilio.mdx +1 -1
- package/docs/concepts/default-harness.md +11 -3
- package/docs/concepts/execution-model-and-durability.mdx +17 -5
- package/docs/concepts/sessions-runs-and-streaming.md +45 -16
- package/docs/evals/cases.mdx +3 -3
- package/docs/evals/targets.mdx +1 -1
- package/docs/guides/auth-and-route-protection.md +2 -1
- package/docs/guides/client/continuations.mdx +50 -77
- package/docs/guides/client/messages.mdx +29 -33
- package/docs/guides/client/output-schema.mdx +7 -14
- package/docs/guides/client/overview.mdx +40 -11
- package/docs/guides/client/streaming.mdx +18 -23
- package/docs/guides/frontend/nuxt.mdx +1 -1
- package/docs/guides/frontend/overview.mdx +40 -36
- package/docs/guides/frontend/sveltekit.mdx +1 -1
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +19 -23
- package/docs/guides/frontend/use-eve-agent-vue.mdx +21 -25
- package/docs/guides/hooks.md +1 -1
- package/docs/guides/instrumentation.md +1 -1
- package/docs/install-integrations.mdx +4 -2
- package/docs/patterns/dynamic-scheduling.md +16 -15
- package/docs/reference/cli.md +4 -1
- package/docs/schedules.mdx +10 -11
- package/docs/subagents.mdx +1 -1
- package/docs/tools/human-in-the-loop.md +1 -1
- package/docs/tools/overview.mdx +26 -2
- package/docs/tutorial/ship-it.mdx +1 -1
- package/package.json +1 -1
- package/dist/src/channel/cancel.d.ts +0 -6
- package/dist/src/channel/cancel.js +0 -1
- package/dist/src/channel/clear-session.d.ts +0 -4
- package/dist/src/channel/clear-session.js +0 -1
- package/dist/src/channel/compact-session.d.ts +0 -4
- package/dist/src/channel/compact-session.js +0 -1
- package/dist/src/channel/reset-session.d.ts +0 -6
- package/dist/src/channel/reset-session.js +0 -1
- package/dist/src/channel/resolve-active-session.d.ts +0 -4
- package/dist/src/channel/resolve-active-session.js +0 -1
- package/dist/src/channel/send.d.ts +0 -6
- package/dist/src/channel/send.js +0 -1
|
@@ -36,7 +36,7 @@ export function Chat() {
|
|
|
36
36
|
const form = new FormData(event.currentTarget);
|
|
37
37
|
const message = String(form.get("message") ?? "").trim();
|
|
38
38
|
if (message.length > 0) {
|
|
39
|
-
void agent.send(
|
|
39
|
+
void agent.send(message);
|
|
40
40
|
}
|
|
41
41
|
}}
|
|
42
42
|
>
|
|
@@ -61,16 +61,17 @@ export function Chat() {
|
|
|
61
61
|
|
|
62
62
|
`useEveAgent()` returns the current UI state plus commands:
|
|
63
63
|
|
|
64
|
-
| Field | What it is
|
|
65
|
-
| --------- |
|
|
66
|
-
| `data` | Projected UI state from the reducer. Defaults to `{ messages }`.
|
|
67
|
-
| `status` | `"ready"`, `"submitted"`, `"streaming"`, or `"error"`. Drives the composer.
|
|
68
|
-
| `error` | The last `Error` thrown, if any.
|
|
69
|
-
| `events` | Raw eve stream events for this session.
|
|
70
|
-
| `session` | Serializable session cursor (`sessionId`, `
|
|
71
|
-
| `send` | Send text or
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
64
|
+
| Field | What it is |
|
|
65
|
+
| --------- | --------------------------------------------------------------------------- |
|
|
66
|
+
| `data` | Projected UI state from the reducer. Defaults to `{ messages }`. |
|
|
67
|
+
| `status` | `"ready"`, `"submitted"`, `"streaming"`, or `"error"`. Drives the composer. |
|
|
68
|
+
| `error` | The last `Error` thrown, if any. |
|
|
69
|
+
| `events` | Raw eve stream events for this session. |
|
|
70
|
+
| `session` | Serializable fixed session cursor (`sessionId`, `streamIndex`). |
|
|
71
|
+
| `send` | Send text or a multi-part message, with per-turn options. |
|
|
72
|
+
| `respond` | Answer pending HITL input requests, with per-turn options. |
|
|
73
|
+
| `stop` | Abort the client's in-flight stream. The server-side turn keeps running. |
|
|
74
|
+
| `reset` | Clear local events, data, errors, and the local session cursor. |
|
|
74
75
|
|
|
75
76
|
Most chat UIs only need `data.messages` and `status`. Drop down to `events` when you need the authoritative wire events directly, for example to persist an audit log or build a custom projection.
|
|
76
77
|
|
|
@@ -78,29 +79,31 @@ Most chat UIs only need `data.messages` and `status`. Drop down to `events` when
|
|
|
78
79
|
|
|
79
80
|
## Sending and streaming
|
|
80
81
|
|
|
81
|
-
Pass
|
|
82
|
+
Pass the message first and optional per-turn settings second. Use `respond()` for HITL answers:
|
|
82
83
|
|
|
83
84
|
```tsx
|
|
84
|
-
await agent.send(
|
|
85
|
-
|
|
86
|
-
await agent.send(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
],
|
|
96
|
-
});
|
|
85
|
+
await agent.send("Summarize this session.");
|
|
86
|
+
|
|
87
|
+
await agent.send([
|
|
88
|
+
{ type: "text", text: "What is in this file?" },
|
|
89
|
+
{
|
|
90
|
+
type: "file",
|
|
91
|
+
data: fileDataUrl, // base64 data URL
|
|
92
|
+
mediaType: "application/pdf",
|
|
93
|
+
filename: "report.pdf",
|
|
94
|
+
},
|
|
95
|
+
]);
|
|
97
96
|
```
|
|
98
97
|
|
|
99
98
|
Assistant text, reasoning, tool calls, and tool results stream into `data` as they arrive, and `status` moves from `ready` to `submitted` to `streaming` and back. Call `stop()` to abort the client's in-flight stream, and `reset()` to clear local state so the next send starts a fresh durable session.
|
|
100
99
|
|
|
101
100
|
`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
101
|
|
|
103
|
-
A chat UI with a
|
|
102
|
+
A chat UI with a server-side Cancel button can use the `sessionId` exposed by the
|
|
103
|
+
hook, attach a fixed `ClientSession`, and call `session.cancel({ turnId })` after
|
|
104
|
+
observing that turn's `turn.started` event. The `turnId` guard makes a late click
|
|
105
|
+
a harmless no-op instead of cancelling a newer turn. Keep the stream open until
|
|
106
|
+
the cancellation boundary arrives; do not use `stop()` for this interaction.
|
|
104
107
|
|
|
105
108
|
After eve confirms an attachment turn with `message.received`, the default reducer projects each
|
|
106
109
|
received attachment as a `file` part on the user message. The part includes `mediaType`, optional
|
|
@@ -108,7 +111,7 @@ received attachment as a `file` part on the user message. The part includes `med
|
|
|
108
111
|
|
|
109
112
|
## Human-in-the-loop prompts
|
|
110
113
|
|
|
111
|
-
Tools opt into approval with `approval`, and the model can also ask a question with `ask_question` — see [Human-in-the-loop](/docs/human-in-the-loop) for the server-side model. Either way the stream emits an `input.requested` event, and the pending request rides on a `dynamic-tool` part of the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `
|
|
114
|
+
Tools opt into approval with `approval`, and the model can also ask a question with `ask_question` — see [Human-in-the-loop](/docs/human-in-the-loop) for the server-side model. Either way the stream emits an `input.requested` event, and the pending request rides on a `dynamic-tool` part of the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `respond()`:
|
|
112
115
|
|
|
113
116
|
```tsx
|
|
114
117
|
const request = agent.data.messages
|
|
@@ -117,9 +120,7 @@ const request = agent.data.messages
|
|
|
117
120
|
?.toolMetadata?.eve?.inputRequest;
|
|
118
121
|
|
|
119
122
|
if (request) {
|
|
120
|
-
await agent.
|
|
121
|
-
inputResponses: [{ requestId: request.requestId, optionId: "approve" }],
|
|
122
|
-
});
|
|
123
|
+
await agent.respond([{ requestId: request.requestId, optionId: "approve" }]);
|
|
123
124
|
}
|
|
124
125
|
```
|
|
125
126
|
|
|
@@ -159,11 +160,10 @@ For fully custom state machines, `authorization.required` and `authorization.com
|
|
|
159
160
|
|
|
160
161
|
## Attach page context per turn
|
|
161
162
|
|
|
162
|
-
`clientContext` adds ephemeral context for the next model call only. Strings (or an array of strings) become user-role context messages; an object is JSON-serialized into one. It rides along with a message or HITL response, so it never dispatches a turn on its own and never lands in durable session history. Pass it
|
|
163
|
+
`clientContext` adds ephemeral context for the next model call only. Strings (or an array of strings) become user-role context messages; an object is JSON-serialized into one. It rides along with a message or HITL response, so it never dispatches a turn on its own and never lands in durable session history. Pass it in the second argument to `send()` or `respond()`:
|
|
163
164
|
|
|
164
165
|
```tsx
|
|
165
|
-
await agent.send({
|
|
166
|
-
message: "What should I do on this screen?",
|
|
166
|
+
await agent.send("What should I do on this screen?", {
|
|
167
167
|
clientContext: { route: "/billing", plan: "pro", seatsUsed: 4 },
|
|
168
168
|
});
|
|
169
169
|
```
|
|
@@ -226,11 +226,11 @@ const agent = useEveAgent({ reducer: toolCounter });
|
|
|
226
226
|
The browser conversation lives durably on the server. Persist both the rendered event log and the `session` cursor to pick it back up after a reload:
|
|
227
227
|
|
|
228
228
|
```tsx
|
|
229
|
-
import type {
|
|
229
|
+
import type { ClientSessionState, MessageStreamEvent } from "eve/client";
|
|
230
230
|
|
|
231
231
|
type SavedEveChat = {
|
|
232
232
|
events?: readonly MessageStreamEvent[];
|
|
233
|
-
session?:
|
|
233
|
+
session?: ClientSessionState;
|
|
234
234
|
};
|
|
235
235
|
|
|
236
236
|
const [saved] = useState<SavedEveChat>(() => {
|
|
@@ -253,7 +253,11 @@ const agent = useEveAgent({
|
|
|
253
253
|
});
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
-
Store the full `session` object (`sessionId`, `
|
|
256
|
+
Store the full `session` object (`sessionId`, `streamIndex`). The session cursor
|
|
257
|
+
lets eve continue the exact durable conversation; the event log lets your UI
|
|
258
|
+
render historical messages without replaying the whole stream. A database-backed
|
|
259
|
+
chat app should usually persist stream events as they arrive with `onEvent` and
|
|
260
|
+
then save a final snapshot in `onFinish`.
|
|
257
261
|
|
|
258
262
|
`initialEvents` must be an ordered prefix of the same session's stream, but its endpoint does not have to line up exactly with where the stream resumes. Every event carries a stable [`meta.id`](/docs/concepts/sessions-runs-and-streaming#the-event-envelope), and the store drops any event whose id it has already applied — so a saved log that overlaps the replayed prefix renders once, and `onEvent` only fires for events your UI has not seen.
|
|
259
263
|
|
|
@@ -23,16 +23,17 @@ Import from `eve/svelte` and read the reactive getters directly. No `$` prefix:
|
|
|
23
23
|
|
|
24
24
|
## What it returns
|
|
25
25
|
|
|
26
|
-
| Property | Type
|
|
27
|
-
| --------- |
|
|
28
|
-
| `data` | `TData`
|
|
29
|
-
| `status` | `UseEveAgentStatus`
|
|
30
|
-
| `error` | `Error \| undefined`
|
|
31
|
-
| `events` | `readonly MessageStreamEvent[]`
|
|
32
|
-
| `session` | `
|
|
33
|
-
| `send` | `(
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
26
|
+
| Property | Type | Description |
|
|
27
|
+
| --------- | --------------------------------------------- | ------------------------------------------------------------------------- |
|
|
28
|
+
| `data` | `TData` | Projected state. With the default reducer, `EveMessageData` (`messages`). |
|
|
29
|
+
| `status` | `UseEveAgentStatus` | `"ready"`, `"submitted"`, `"streaming"`, or `"error"`. |
|
|
30
|
+
| `error` | `Error \| undefined` | Last transport-level error. |
|
|
31
|
+
| `events` | `readonly MessageStreamEvent[]` | Raw server events for this session. |
|
|
32
|
+
| `session` | `ClientSessionState \| undefined` | Fixed session ID and stream cursor. |
|
|
33
|
+
| `send` | `(message, options?) => Promise<void>` | Send text or a multi-part message. |
|
|
34
|
+
| `respond` | `(inputResponses, options?) => Promise<void>` | Answer pending HITL input requests. |
|
|
35
|
+
| `stop` | `() => void` | Abort the client's in-flight stream. |
|
|
36
|
+
| `reset` | `() => void` | Clear state and start a new session. |
|
|
36
37
|
|
|
37
38
|
These state fields are reactive getters, so read them straight from templates, `$derived`, or `$effect`. They are not stores, so don't prefix them with `$`.
|
|
38
39
|
|
|
@@ -49,7 +50,7 @@ These state fields are reactive getters, so read them straight from templates, `
|
|
|
49
50
|
const text = message.trim();
|
|
50
51
|
if (!text) return;
|
|
51
52
|
message = "";
|
|
52
|
-
await agent.send(
|
|
53
|
+
await agent.send(text);
|
|
53
54
|
}
|
|
54
55
|
</script>
|
|
55
56
|
|
|
@@ -68,17 +69,15 @@ When a turn is more than plain text, reach for `send()`. Attachments follow the
|
|
|
68
69
|
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
69
70
|
const base64 = btoa(String.fromCodePoint(...bytes));
|
|
70
71
|
|
|
71
|
-
await agent.send(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
],
|
|
76
|
-
});
|
|
72
|
+
await agent.send([
|
|
73
|
+
{ type: "text", text: "Describe this image." },
|
|
74
|
+
{ type: "file", data: `data:${file.type};base64,${base64}`, mediaType: file.type },
|
|
75
|
+
]);
|
|
77
76
|
```
|
|
78
77
|
|
|
79
78
|
## Human-in-the-loop prompts
|
|
80
79
|
|
|
81
|
-
A tool opts into approval with `approval` ([Tools](../../tools)). When one fires, the pending request rides along on a `dynamic-tool` part of the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `agent.
|
|
80
|
+
A tool opts into approval with `approval` ([Tools](../../tools)). When one fires, the pending request rides along on a `dynamic-tool` part of the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `agent.respond(inputResponses)`:
|
|
82
81
|
|
|
83
82
|
```ts
|
|
84
83
|
import type { EveDynamicToolPart, EveMessagePart } from "eve/svelte";
|
|
@@ -93,9 +92,7 @@ const request = agent.data.messages
|
|
|
93
92
|
.find((value) => value !== undefined);
|
|
94
93
|
|
|
95
94
|
if (request) {
|
|
96
|
-
await agent.
|
|
97
|
-
inputResponses: [{ requestId: request.requestId, optionId: "approve" }],
|
|
98
|
-
});
|
|
95
|
+
await agent.respond([{ requestId: request.requestId, optionId: "approve" }]);
|
|
99
96
|
}
|
|
100
97
|
```
|
|
101
98
|
|
|
@@ -133,8 +130,7 @@ const agent = useEveAgent({
|
|
|
133
130
|
`clientContext` adds ephemeral context for the next model call and nothing more. Strings (or an array of strings) become user-role context messages; an object is JSON-serialized into one. It rides along with a message or HITL response, never dispatches a turn on its own, and never lands in durable session history. Pass it to `send()`:
|
|
134
131
|
|
|
135
132
|
```ts
|
|
136
|
-
await agent.send({
|
|
137
|
-
message: "What should I do on this screen?",
|
|
133
|
+
await agent.send("What should I do on this screen?", {
|
|
138
134
|
clientContext: { route: "/billing", plan: "pro", seatsUsed: 4 },
|
|
139
135
|
});
|
|
140
136
|
```
|
|
@@ -25,16 +25,17 @@ const { data } = useEveAgent();
|
|
|
25
25
|
|
|
26
26
|
## What it returns
|
|
27
27
|
|
|
28
|
-
| Property | Type
|
|
29
|
-
| --------- |
|
|
30
|
-
| `data` | `ComputedRef<TData>`
|
|
31
|
-
| `status` | `ComputedRef<UseEveAgentStatus>`
|
|
32
|
-
| `error` | `ComputedRef<Error \| undefined>`
|
|
33
|
-
| `events` | `ComputedRef<readonly MessageStreamEvent[]>`
|
|
34
|
-
| `session` | `ComputedRef<
|
|
35
|
-
| `send` | `(
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
28
|
+
| Property | Type | Description |
|
|
29
|
+
| --------- | ---------------------------------------------- | ------------------------------------------------------------------------- |
|
|
30
|
+
| `data` | `ComputedRef<TData>` | Projected state. With the default reducer, `EveMessageData` (`messages`). |
|
|
31
|
+
| `status` | `ComputedRef<UseEveAgentStatus>` | `"ready"`, `"submitted"`, `"streaming"`, or `"error"`. |
|
|
32
|
+
| `error` | `ComputedRef<Error \| undefined>` | Last transport-level error. |
|
|
33
|
+
| `events` | `ComputedRef<readonly MessageStreamEvent[]>` | Raw server events for this session. |
|
|
34
|
+
| `session` | `ComputedRef<ClientSessionState \| undefined>` | Fixed session ID and stream cursor. |
|
|
35
|
+
| `send` | `(message, options?) => Promise<void>` | Send text or a multi-part message. |
|
|
36
|
+
| `respond` | `(inputResponses, options?) => Promise<void>` | Answer pending HITL input requests. |
|
|
37
|
+
| `stop` | `() => void` | Abort the client's in-flight stream. |
|
|
38
|
+
| `reset` | `() => void` | Clear state and start a new session. |
|
|
38
39
|
|
|
39
40
|
The first five are `ComputedRef`s; the rest are methods. Destructure whatever you need, since refs keep their reactivity through destructuring. Read them with `.value` in `<script>`, and unwrapped in `<template>`.
|
|
40
41
|
|
|
@@ -52,7 +53,7 @@ async function handleSubmit() {
|
|
|
52
53
|
const text = message.value.trim();
|
|
53
54
|
if (!text) return;
|
|
54
55
|
message.value = "";
|
|
55
|
-
await send(
|
|
56
|
+
await send(text);
|
|
56
57
|
}
|
|
57
58
|
</script>
|
|
58
59
|
|
|
@@ -77,24 +78,22 @@ async function onFileChange(event: Event) {
|
|
|
77
78
|
if (!file) return;
|
|
78
79
|
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
79
80
|
const base64 = btoa(String.fromCodePoint(...bytes));
|
|
80
|
-
await send(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
],
|
|
85
|
-
});
|
|
81
|
+
await send([
|
|
82
|
+
{ type: "text", text: "Describe this image." },
|
|
83
|
+
{ type: "file", data: `data:${file.type};base64,${base64}`, mediaType: file.type },
|
|
84
|
+
]);
|
|
86
85
|
}
|
|
87
86
|
</script>
|
|
88
87
|
```
|
|
89
88
|
|
|
90
89
|
## Human-in-the-loop prompts
|
|
91
90
|
|
|
92
|
-
A tool opts into approval with `approval` ([Tools](../../tools)). When it triggers, the pending request shows up as a `dynamic-tool` part on the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `
|
|
91
|
+
A tool opts into approval with `approval` ([Tools](../../tools)). When it triggers, the pending request shows up as a `dynamic-tool` part on the latest message at `part.toolMetadata?.eve?.inputRequest`. Read it, then answer through the same session with `respond(inputResponses)`:
|
|
93
92
|
|
|
94
93
|
```ts
|
|
95
94
|
import type { EveDynamicToolPart, EveMessagePart } from "eve/vue";
|
|
96
95
|
|
|
97
|
-
const { data,
|
|
96
|
+
const { data, respond } = useEveAgent();
|
|
98
97
|
|
|
99
98
|
const isDynamicToolPart = (part: EveMessagePart): part is EveDynamicToolPart =>
|
|
100
99
|
part.type === "dynamic-tool";
|
|
@@ -106,9 +105,7 @@ const request = data.value.messages
|
|
|
106
105
|
.find((value) => value !== undefined);
|
|
107
106
|
|
|
108
107
|
if (request) {
|
|
109
|
-
await
|
|
110
|
-
inputResponses: [{ requestId: request.requestId, optionId: "approve" }],
|
|
111
|
-
});
|
|
108
|
+
await respond([{ requestId: request.requestId, optionId: "approve" }]);
|
|
112
109
|
}
|
|
113
110
|
```
|
|
114
111
|
|
|
@@ -143,11 +140,10 @@ const agent = useEveAgent({
|
|
|
143
140
|
|
|
144
141
|
## Attach page context per turn
|
|
145
142
|
|
|
146
|
-
`clientContext` adds ephemeral context for the next model call and nothing more. Strings (or an array of strings) become user-role context messages; an object is JSON-serialized into one. It rides along with a message or HITL response, never dispatches a turn on its own, and never lands in durable session history. Pass it to `send()`:
|
|
143
|
+
`clientContext` adds ephemeral context for the next model call and nothing more. Strings (or an array of strings) become user-role context messages; an object is JSON-serialized into one. It rides along with a message or HITL response, never dispatches a turn on its own, and never lands in durable session history. Pass it in the second argument to `send()` or `respond()`:
|
|
147
144
|
|
|
148
145
|
```ts
|
|
149
|
-
await send({
|
|
150
|
-
message: "What should I do on this screen?",
|
|
146
|
+
await send("What should I do on this screen?", {
|
|
151
147
|
clientContext: { route: "/billing", plan: "pro", seatsUsed: 4 },
|
|
152
148
|
});
|
|
153
149
|
```
|
package/docs/guides/hooks.md
CHANGED
|
@@ -26,7 +26,7 @@ The slug is the path-relative basename. `agent/hooks/audit.ts` becomes `"audit"`
|
|
|
26
26
|
|
|
27
27
|
`defineHook`, `HookDefinition`, and `HookContext` live on `eve/hooks`.
|
|
28
28
|
|
|
29
|
-
A hook file declares stream-event subscribers under the `events` map, keyed by event type, with `*` matching every event. Subscribe to any event in the runtime stream vocabulary documented in [Sessions, runs and streaming](../concepts/sessions-runs-and-streaming), including the lifecycle events `session.started`, `turn.completed`, `message.completed`, and `action.result`. Handlers are observe-only. They cannot inject model context. To contribute runtime model messages, use `defineDynamic` and `defineInstructions` in `agent/instructions/`.
|
|
29
|
+
A hook file declares stream-event subscribers under the `events` map, keyed by event type, with `*` matching every event. Subscribe to any event in the runtime stream vocabulary documented in [Sessions, runs and streaming](../concepts/sessions-runs-and-streaming), including the lifecycle events `session.started`, `turn.completed`, `message.completed`, `action.partial`, and `action.result`. Handlers are observe-only. They cannot inject model context. To contribute runtime model messages, use `defineDynamic` and `defineInstructions` in `agent/instructions/`.
|
|
30
30
|
|
|
31
31
|
## Hook structure and context
|
|
32
32
|
|
|
@@ -181,7 +181,7 @@ When `eve build` fails on discovery errors, the CLI prints the full diagnostics
|
|
|
181
181
|
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
182
182
|
| Tool not discovered (the model never sees it) | Run `eve info`. Confirm the file is in the right slot (`agent/tools/<name>.ts`) and default-exports `defineTool(...)`, and check `.eve/diagnostics.json` for shape errors. `schedules/` are root-only. |
|
|
183
183
|
| Model won't call a tool it should | Tighten the tool `description` and `inputSchema`; put procedural guidance in a [skill](../skills), not the description. Confirm it's in the active set with `eve info`. |
|
|
184
|
-
| Stuck on `session.waiting` | The turn is parked
|
|
184
|
+
| Stuck on `session.waiting` | The turn is parked for input. Answer the pending approval or question, or POST a follow-up to `/eve/v1/session/:sessionId`. |
|
|
185
185
|
| 401 on production routes | Expected: auth fails closed. Replace `placeholderAuth()` with your route policy. Use `vercelOidc()` only for Vercel-issued tokens; otherwise configure `httpBasic()`, JWT/OIDC helpers, or a custom `AuthFn`. See [Auth and route protection](./auth-and-route-protection). |
|
|
186
186
|
| Build fails with discovery errors | Read the printed diagnostics and `.eve/diagnostics.json`; confirm the root-vs-subagent boundary is valid and secrets come from env vars. |
|
|
187
187
|
|
|
@@ -12,13 +12,15 @@ Run `eve add` from an eve agent project. This installs the integration's depende
|
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
eve add extension/agent-browser
|
|
15
|
-
eve add
|
|
15
|
+
eve add linear
|
|
16
16
|
eve add instrumentation/braintrust
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Extensions may create a mount under `agent/extensions/`. Connections write their initial definition under `agent/connections/` and install `@vercel/connect` when required. Instrumentation providers write `agent/instrumentation.ts`; because an agent has one instrumentation file, compose multiple exporters there by hand. Configure generated files and required environment variables before running your agent.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Some integrations package several independently installable components. For example, `eve add linear` lets you choose the Linear Channel, Linear MCP, or both; both are selected by default. The specific `eve add channel/linear-agent` and `eve add connection/linear` commands remain available.
|
|
22
|
+
|
|
23
|
+
When an official item declares an interactive setup flow or flows, eve asks whether to run them after installation and runs multiple flows in declaration order. Run the printed `eve add <item> --skip-install` command to resume a skipped or cancelled setup later; it reruns the selected components' declared flows from the beginning.
|
|
22
24
|
|
|
23
25
|
## Find an integration
|
|
24
26
|
|
|
@@ -35,7 +35,7 @@ import { scheduleStore } from "../lib/schedule-store";
|
|
|
35
35
|
|
|
36
36
|
export default defineSchedule({
|
|
37
37
|
cron: "* * * * *",
|
|
38
|
-
run({
|
|
38
|
+
run({ to, waitUntil }) {
|
|
39
39
|
waitUntil(
|
|
40
40
|
(async () => {
|
|
41
41
|
const jobs = await scheduleStore.claimDue({
|
|
@@ -47,25 +47,26 @@ export default defineSchedule({
|
|
|
47
47
|
await Promise.all(
|
|
48
48
|
jobs.map(async (job) => {
|
|
49
49
|
try {
|
|
50
|
-
await
|
|
51
|
-
|
|
50
|
+
await to(slack, { channelId: job.channelId }).send(
|
|
51
|
+
[
|
|
52
52
|
`Run dynamic schedule ${job.id}.`,
|
|
53
53
|
"Complete this tenant-owned task:",
|
|
54
54
|
job.prompt,
|
|
55
55
|
].join("\n\n"),
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
{
|
|
57
|
+
auth: {
|
|
58
|
+
attributes: {
|
|
59
|
+
tenantId: job.tenantId,
|
|
60
|
+
role: job.ownerRole,
|
|
61
|
+
scheduleId: job.id,
|
|
62
|
+
},
|
|
63
|
+
authenticator: job.authenticator,
|
|
64
|
+
...(job.issuer ? { issuer: job.issuer } : {}),
|
|
65
|
+
principalId: job.ownerId,
|
|
66
|
+
principalType: "user",
|
|
62
67
|
},
|
|
63
|
-
authenticator: job.authenticator,
|
|
64
|
-
...(job.issuer ? { issuer: job.issuer } : {}),
|
|
65
|
-
principalId: job.ownerId,
|
|
66
|
-
principalType: "user",
|
|
67
68
|
},
|
|
68
|
-
|
|
69
|
+
);
|
|
69
70
|
await scheduleStore.complete(job);
|
|
70
71
|
} catch (error) {
|
|
71
72
|
await scheduleStore.release(job, { error, retryAt: new Date(Date.now() + 300_000) });
|
|
@@ -78,7 +79,7 @@ export default defineSchedule({
|
|
|
78
79
|
});
|
|
79
80
|
```
|
|
80
81
|
|
|
81
|
-
`waitUntil` keeps the cron invocation alive until claiming and handoff settle. `
|
|
82
|
+
`waitUntil` keeps the cron invocation alive until claiming and handoff settle. `to(...).send(...)` starts the same durable runtime used by inbound channel messages.
|
|
82
83
|
|
|
83
84
|
This example uses Slack because it has a proactive target of `{ channelId }`. Any channel that implements `receive` can replace it.
|
|
84
85
|
|
package/docs/reference/cli.md
CHANGED
|
@@ -87,6 +87,7 @@ Commands for installing and discovering [shadcn registry](https://ui.shadcn.com/
|
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
89
|
eve add extension/agent-browser
|
|
90
|
+
eve add linear
|
|
90
91
|
eve add channel/slack --skip-install
|
|
91
92
|
eve add https://example.com/r/my-extension.json --overwrite
|
|
92
93
|
eve registry add @acme=https://example.com/r/{name}.json
|
|
@@ -97,7 +98,9 @@ eve registry view @acme/my-extension
|
|
|
97
98
|
eve add @acme/my-extension
|
|
98
99
|
```
|
|
99
100
|
|
|
100
|
-
`eve add` asks before running setup declared by an official item and
|
|
101
|
+
`eve add` asks before running setup declared by an official item and runs multiple declared flows in declaration order. Product-level packages can offer independently installable components: `eve add linear` lets you select the Linear Channel, Linear MCP, or both, with both selected by default. `--yes` installs a package's default components.
|
|
102
|
+
|
|
103
|
+
When setup is skipped or cancelled, eve prints the matching `eve add <item> --skip-install` command. `--skip-install` reruns the selected components' declared flows from the beginning without reinstalling them.
|
|
101
104
|
|
|
102
105
|
`eve registry add` records configured sources in `package.json#registries`. `eve registry list` aggregates the official catalog and all configured sources by default. `eve registry search` also includes [skills.sh](https://skills.sh), available without configuration at `@skills`, and groups results by source with each source's available result count. Search returns up to 10 matches per source by default; pass `--limit <count>` to request between 1 and 100. Either command can browse one supplied URL or namespace. Official and other universal items with explicit file targets do not require shadcn project configuration.
|
|
103
106
|
|
package/docs/schedules.mdx
CHANGED
|
@@ -19,7 +19,7 @@ interface ScheduleDefinition {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
interface ScheduleHandlerArgs {
|
|
22
|
-
|
|
22
|
+
to: ScheduleToFn; // select a channel target, then send
|
|
23
23
|
waitUntil: (task: Promise<unknown>) => void; // keep the cron task alive past return
|
|
24
24
|
appAuth: SessionAuthContext; // pre-built app principal
|
|
25
25
|
}
|
|
@@ -56,7 +56,7 @@ Sweep stale workflow state.
|
|
|
56
56
|
|
|
57
57
|
## Handler form (`run`)
|
|
58
58
|
|
|
59
|
-
Use a handler when the schedule needs to deliver to a channel, branch on conditions, or compute its arguments at fire time. The handler is in full control. It has no channel of its own, so it
|
|
59
|
+
Use a handler when the schedule needs to deliver to a channel, branch on conditions, or compute its arguments at fire time. The handler is in full control. It has no channel of its own, so it selects a channel target with `to(...)` and sends through the returned handle.
|
|
60
60
|
|
|
61
61
|
```ts title="agent/schedules/critical-alerts.ts"
|
|
62
62
|
import { defineSchedule } from "eve/schedules";
|
|
@@ -65,13 +65,12 @@ import slack from "../channels/slack";
|
|
|
65
65
|
|
|
66
66
|
export default defineSchedule({
|
|
67
67
|
cron: "* * * * *",
|
|
68
|
-
async run({
|
|
68
|
+
async run({ to, waitUntil, appAuth }) {
|
|
69
69
|
waitUntil(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}),
|
|
70
|
+
to(slack, { channelId: "C0123ABC" }).send(
|
|
71
|
+
"Check for new critical alerts. Report only when there are any.",
|
|
72
|
+
{ auth: appAuth },
|
|
73
|
+
),
|
|
75
74
|
);
|
|
76
75
|
},
|
|
77
76
|
});
|
|
@@ -79,9 +78,9 @@ export default defineSchedule({
|
|
|
79
78
|
|
|
80
79
|
The agent does not have to deliver a message on every run. When a prompt makes delivery conditional, as in the alert check above, eve tells the agent how to finish successfully without sending anything to the channel. Frequent polling schedules do not need a separate filter or delivery setting.
|
|
81
80
|
|
|
82
|
-
- `
|
|
83
|
-
- `waitUntil(promise)`: extends the cron task's lifetime so the parked session and any in-flight fetches settle before the task ends. Wrap the `
|
|
84
|
-
- `appAuth`: the app principal (`{ authenticator: "app", principalId: "eve:app", principalType: "runtime" }`). Pass it as `
|
|
81
|
+
- `to(channel, target).send(message, { auth })`: starts a session on another channel. It has the same contract as a route handler's `ctx.to(...)` handle.
|
|
82
|
+
- `waitUntil(promise)`: extends the cron task's lifetime so the parked session and any in-flight fetches settle before the task ends. Wrap the `send` call in it.
|
|
83
|
+
- `appAuth`: the app principal (`{ authenticator: "app", principalId: "eve:app", principalType: "runtime" }`). Pass it as `to(...).send(..., { auth: appAuth })` for work the agent does on its own behalf.
|
|
85
84
|
|
|
86
85
|
A handler-form session runs on the same durable runtime engine as any other session, so it can park (durably suspend), for instance when the channel handoff is waiting for a Slack reply. Only markdown task mode is barred from waiting.
|
|
87
86
|
|
package/docs/subagents.mdx
CHANGED
|
@@ -192,7 +192,7 @@ Without the opt-in, delegated children run as one-shot tasks: they answer once a
|
|
|
192
192
|
|
|
193
193
|
With it enabled, a child parks after answering instead of terminating, keeping its session and conversation history alive. A failed child turn can also leave the child parked — its latest status shows the error and the parent may message it again. Pass a parked child's `agentId` to the same subagent tool with a new `message` to continue that session. Omitting `agentId` (or passing an empty string or `null`) always starts a new child, and an `agentId` that matches no known agent falls back to starting a new child rather than failing. Passing a known `agentId` through a different subagent tool fails with `AGENT_MISMATCH`, and messaging a child that is still starting or working on its previous request fails with `AGENT_BUSY` — wait for its result before continuing it.
|
|
194
194
|
|
|
195
|
-
|
|
195
|
+
Whenever the set of parked (resumable) children changes, eve appends a framework-injected note to the conversation — labeled `[Agents]` and carrying an `<agents>` block — listing each child's `agentId`, name, and latest status. The static system prompt tells the model the note is injected by eve, not written by the user. The note is appended only when the listing changes (an append-only design that preserves the provider prompt cache), the most recent note is authoritative, and children that are starting or running do not appear until they park again.
|
|
196
196
|
|
|
197
197
|
The parent holds agent handles only for its session lifetime. When the parent session ends, eve terminates its local children. Remote children are not terminated on parent shutdown — that is a known gap: a parked remote child stays alive on its own deployment until that deployment's own lifecycle ends it. For [remote agents](./guides/remote-agents), both deployments must run the same eve version to use agent messaging.
|
|
198
198
|
|
|
@@ -58,7 +58,7 @@ Gating a side effect on approval is also how you make non-idempotent work safe a
|
|
|
58
58
|
|
|
59
59
|
### Skipping approval for schedule-dispatched turns
|
|
60
60
|
|
|
61
|
-
`session.auth.current` identifies the caller of this turn. Markdown schedules use the app principal (`authenticator: "app"`, `principalId: "eve:app"`, `principalType: "runtime"`) automatically. A `run` schedule must pass its `appAuth` to `
|
|
61
|
+
`session.auth.current` identifies the caller of this turn. Markdown schedules use the app principal (`authenticator: "app"`, `principalId: "eve:app"`, `principalType: "runtime"`) automatically. A `run` schedule must pass its `appAuth` to `send(...)` for the child session to use that principal. Match all three fields to skip approval for automated turns while still prompting when a person calls the same tool:
|
|
62
62
|
|
|
63
63
|
```ts title="agent/tools/refund_charge.ts"
|
|
64
64
|
import { defineTool } from "eve/tools";
|
package/docs/tools/overview.mdx
CHANGED
|
@@ -28,10 +28,34 @@ A tool definition needs:
|
|
|
28
28
|
- a filename slug under `agent/tools/`, the model-facing name.
|
|
29
29
|
- a `description`: what the tool does, written for the model.
|
|
30
30
|
- an `inputSchema`: a Zod schema (or any Standard Schema, or a plain JSON Schema object). Required. For no input, pass `z.object({})`. Zod and Standard Schema infer the `input` type in `execute`. Plain JSON Schema types it as `Record<string, unknown>`.
|
|
31
|
-
- an `execute(input, ctx)`: the implementation. May be sync or async.
|
|
31
|
+
- an `execute(input, ctx)`: the implementation. May be sync, async, or an async generator.
|
|
32
32
|
|
|
33
33
|
When a tool returns structured data, add an optional `outputSchema`. With Zod or Standard Schema it also types the `execute` return.
|
|
34
34
|
|
|
35
|
+
### Stream preliminary tool results
|
|
36
|
+
|
|
37
|
+
An async generator lets a long-running tool stream complete output snapshots
|
|
38
|
+
before it finishes. Each `yield` replaces the previous snapshot; the final
|
|
39
|
+
yield is the normal tool result the model receives:
|
|
40
|
+
|
|
41
|
+
```ts title="agent/tools/build_report.ts"
|
|
42
|
+
export default defineTool({
|
|
43
|
+
description: "Build a project report.",
|
|
44
|
+
inputSchema: z.object({ project: z.string() }),
|
|
45
|
+
async *execute({ project }) {
|
|
46
|
+
yield { phase: "collecting", report: null };
|
|
47
|
+
const report = await buildReport(project);
|
|
48
|
+
yield { phase: "complete", report };
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
eve publishes every earlier yield as an `action.partial` stream event. The
|
|
54
|
+
snapshot is visible to channels, hooks, and clients but never enters model
|
|
55
|
+
history or `toModelOutput`; only the final yield does. Treat snapshots as
|
|
56
|
+
last-write-wins by tool call id, not append-only progress. The durable runtime
|
|
57
|
+
can retry a step and replay overlapping snapshots.
|
|
58
|
+
|
|
35
59
|
### The `ctx` parameter
|
|
36
60
|
|
|
37
61
|
`execute` gets a `ctx` carrying the runtime accessors:
|
|
@@ -78,7 +102,7 @@ toModelOutput(output) {
|
|
|
78
102
|
},
|
|
79
103
|
```
|
|
80
104
|
|
|
81
|
-
`toModelOutput` receives the
|
|
105
|
+
`toModelOutput` receives the final, typed `execute` return and only affects the model. Channel event handlers and hooks still get the full output on `action.result`, so a channel can render rich platform output (Slack Block Kit, say) the model never sees. Return `{ type: "text", value }` for a summary, or `{ type: "json", value }` for a smaller object.
|
|
82
106
|
|
|
83
107
|
Tool outputs must be JSON-serializable. Return plain objects, arrays, strings, numbers, booleans, or `null`; convert values like `Date`, `Map`, `Set`, `NaN`, and cyclic objects before returning them from `execute` or from a `{ type: "json" }` `toModelOutput`.
|
|
84
108
|
|
|
@@ -43,7 +43,7 @@ export function AgentChat() {
|
|
|
43
43
|
event.preventDefault();
|
|
44
44
|
const data = new FormData(event.currentTarget);
|
|
45
45
|
const message = String(data.get("q") ?? "").trim();
|
|
46
|
-
if (message) void agent.send(
|
|
46
|
+
if (message) void agent.send(message);
|
|
47
47
|
}}
|
|
48
48
|
>
|
|
49
49
|
{agent.data.messages.map((message) => (
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function createCancelFn(e,t){return async n=>await e.dispatchContinuation({command:{kind:`cancel`,turnId:n.turnId},continuationToken:`${t}:${n.continuationToken}`})}export{createCancelFn};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function createClearFn(e,t){return async n=>await e.dispatchContinuation({command:{kind:`clear`},continuationToken:`${t}:${n.continuationToken}`})}export{createClearFn};
|