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
|
@@ -1,137 +1,110 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
3
|
-
description: "Persist and resume eve client sessions with
|
|
2
|
+
title: "Session State"
|
|
3
|
+
description: "Persist and resume eve client sessions with durable session IDs and stream cursors."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- `sessionId`: the stream-and-inspect handle. Use it to attach to event history.
|
|
10
|
-
|
|
11
|
-
`ClientSession` also tracks `streamIndex`, the count of events already consumed. Together these three fields make a `SessionState`.
|
|
6
|
+
The TypeScript client uses one durable session ID for messages, controls, and
|
|
7
|
+
streams. A `ClientSession` adds a local `streamIndex` cursor so reconnects do not
|
|
8
|
+
replay events already consumed by that handle.
|
|
12
9
|
|
|
13
10
|
## Read and persist state
|
|
14
11
|
|
|
15
|
-
|
|
12
|
+
Create the session with its first turn, then persist `session.state` after
|
|
13
|
+
consuming the response:
|
|
16
14
|
|
|
17
15
|
```ts
|
|
18
|
-
const session = client.
|
|
16
|
+
const { session, response } = await client.sessions.create({
|
|
17
|
+
message: "Create a launch checklist.",
|
|
18
|
+
});
|
|
19
19
|
|
|
20
|
-
const response = await session.send("Create a launch checklist.");
|
|
21
20
|
await response.result();
|
|
22
|
-
|
|
23
21
|
await saveSessionState(session.state);
|
|
24
22
|
```
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Store the full state object:
|
|
24
|
+
The state is deliberately small:
|
|
29
25
|
|
|
30
26
|
```ts
|
|
31
|
-
interface
|
|
32
|
-
|
|
33
|
-
sessionId?: string;
|
|
27
|
+
interface ClientSessionState {
|
|
28
|
+
sessionId: string;
|
|
34
29
|
streamIndex: number;
|
|
35
30
|
}
|
|
36
31
|
```
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
`SessionState` is a cursor, not a chat transcript. If your app shows historical messages, persist the stream events separately and store them under your own chat or thread ID. On reload, pass the saved `SessionState` back to `client.session(savedState)` or `useEveAgent({ initialSession })`, and pass the saved events to your renderer or `useEveAgent({ initialEvents })`.
|
|
33
|
+
It is a remote stream cursor, not a transcript. Persist events separately when
|
|
34
|
+
your application renders chat history.
|
|
41
35
|
|
|
42
36
|
## Resume a saved session
|
|
43
37
|
|
|
44
|
-
|
|
38
|
+
Attach a fixed handle to the saved ID and restore its cursor:
|
|
45
39
|
|
|
46
40
|
```ts
|
|
47
|
-
import type {
|
|
41
|
+
import type { ClientSessionState } from "eve/client";
|
|
48
42
|
|
|
49
|
-
const saved = (await loadSessionState()) as
|
|
50
|
-
const session = client.
|
|
43
|
+
const saved = (await loadSessionState()) as ClientSessionState;
|
|
44
|
+
const session = client.sessions.attach(saved.sessionId, {
|
|
45
|
+
streamIndex: saved.streamIndex,
|
|
46
|
+
});
|
|
51
47
|
|
|
52
48
|
const response = await session.send("Now shorten it.");
|
|
53
|
-
|
|
54
|
-
console.log(result.message);
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
If all you have is a continuation token, pass it as shorthand:
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
const session = client.session(continuationToken);
|
|
61
|
-
const response = await session.send("Continue where we left off.");
|
|
62
|
-
await response.result();
|
|
49
|
+
console.log((await response.result()).message);
|
|
63
50
|
```
|
|
64
51
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
## Waiting, completed, and failed sessions
|
|
52
|
+
`attach()` performs no request. Every later operation targets exactly
|
|
53
|
+
`saved.sessionId`; it never follows or creates a replacement.
|
|
68
54
|
|
|
69
|
-
|
|
55
|
+
## Waiting, completed, and reset sessions
|
|
70
56
|
|
|
71
|
-
|
|
57
|
+
A session that emits `session.waiting` accepts another message through the same
|
|
58
|
+
handle. A terminal or reset session does not. Start a fresh conversation
|
|
59
|
+
explicitly with another `client.sessions.create(firstTurn)` call.
|
|
72
60
|
|
|
73
61
|
```ts
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
if (result.status === "completed") {
|
|
78
|
-
// session.state is now a fresh cursor: { streamIndex: 0 }
|
|
79
|
-
}
|
|
62
|
+
const reset = await session.reset({ reason: "Start over" });
|
|
63
|
+
const { session: fresh, response } = await client.sessions.create({ message: "Begin again." });
|
|
80
64
|
```
|
|
81
65
|
|
|
82
|
-
|
|
66
|
+
The old `session` remains pinned to its retired ID; `fresh` owns a different ID.
|
|
83
67
|
|
|
84
68
|
## Multiple sessions
|
|
85
69
|
|
|
86
|
-
Create
|
|
70
|
+
Create one handle per conversation:
|
|
87
71
|
|
|
88
72
|
```ts
|
|
89
|
-
const research = client.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
await supportResponse.result();
|
|
97
|
-
|
|
73
|
+
const { session: research, response: researchResponse } = await client.sessions.create({
|
|
74
|
+
message: "Research competitors.",
|
|
75
|
+
});
|
|
76
|
+
const { session: support, response: supportResponse } = await client.sessions.create({
|
|
77
|
+
message: "Draft a support reply.",
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await Promise.all([researchResponse.result(), supportResponse.result()]);
|
|
98
81
|
await save("research", research.state);
|
|
99
82
|
await save("support", support.state);
|
|
100
83
|
```
|
|
101
84
|
|
|
102
|
-
The shared `Client`
|
|
103
|
-
|
|
104
|
-
For a multi-chat UI, this usually means one application row per chat with two eve fields: the latest `SessionState` and the ordered event log for rendering. Do not reuse one `ClientSession` across sidebar conversations, and do not treat `streamIndex` as your database row index; it is only the remote stream cursor for that eve session.
|
|
85
|
+
The shared `Client` owns host, auth, headers, and redirect policy. Each
|
|
86
|
+
`ClientSession` owns its fixed ID and stream cursor.
|
|
105
87
|
|
|
106
88
|
## Reconnect an existing stream
|
|
107
89
|
|
|
108
|
-
|
|
90
|
+
`stream()` starts from the handle's saved cursor and advances it as events are
|
|
91
|
+
read:
|
|
109
92
|
|
|
110
93
|
```ts
|
|
111
|
-
const session = client.
|
|
94
|
+
const session = client.sessions.attach(saved.sessionId, {
|
|
95
|
+
streamIndex: saved.streamIndex,
|
|
96
|
+
});
|
|
112
97
|
|
|
113
98
|
for await (const event of session.stream()) {
|
|
114
99
|
console.log(event.type);
|
|
115
100
|
}
|
|
116
101
|
```
|
|
117
102
|
|
|
118
|
-
`
|
|
119
|
-
|
|
120
|
-
If you only persisted `sessionId`, read the latest durable event to recover the current token from a waiting session:
|
|
121
|
-
|
|
122
|
-
```ts
|
|
123
|
-
const session = client.session({ sessionId, streamIndex: 0 });
|
|
124
|
-
|
|
125
|
-
for await (const event of session.stream({ startIndex: -1 })) {
|
|
126
|
-
if (event.type === "session.waiting") {
|
|
127
|
-
await saveContinuationToken(event.data.continuationToken);
|
|
128
|
-
}
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
```
|
|
103
|
+
Use `send()` for new input. For explicit cursors, tail-relative reads, and
|
|
104
|
+
bounded catch-up, see [Streaming](./streaming#open-a-stream-manually).
|
|
132
105
|
|
|
133
106
|
## What to read next
|
|
134
107
|
|
|
135
108
|
- [Streaming](./streaming): stream events and reconnect by index
|
|
136
109
|
- [Sessions, runs & streaming](../../concepts/sessions-runs-and-streaming): the raw HTTP contract
|
|
137
|
-
- [eve channel](../../channels/eve):
|
|
110
|
+
- [eve channel](../../channels/eve): the ID-addressed routes
|
|
@@ -3,7 +3,7 @@ title: "Messages"
|
|
|
3
3
|
description: "Send text, full turn payloads, client context, attachments, and HITL responses with eve/client."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Create a session with its first turn, then use the returned `ClientSession` for follow-ups. Each handle targets one durable session ID.
|
|
7
7
|
|
|
8
8
|
## Send text
|
|
9
9
|
|
|
@@ -13,12 +13,12 @@ Pass a string to `send()` for plain text:
|
|
|
13
13
|
import { Client } from "eve/client";
|
|
14
14
|
|
|
15
15
|
const client = new Client({ host: "http://127.0.0.1:2000" });
|
|
16
|
-
const session = client.
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const { session, response } = await client.sessions.create({
|
|
17
|
+
message: "What is the weather in Brooklyn?",
|
|
18
|
+
});
|
|
19
19
|
|
|
20
20
|
// Metadata is available as soon as the POST succeeds.
|
|
21
|
-
console.log(response.sessionId
|
|
21
|
+
console.log(response.sessionId);
|
|
22
22
|
|
|
23
23
|
const result = await response.result();
|
|
24
24
|
console.log(result.status, result.message);
|
|
@@ -38,10 +38,10 @@ When the stream includes `session.failed`, the turn returns `status: "failed"` r
|
|
|
38
38
|
|
|
39
39
|
## Send a full turn payload
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
Pass the full payload to `create()` for the first turn or `send()` for a follow-up:
|
|
42
42
|
|
|
43
43
|
```ts
|
|
44
|
-
const response = await
|
|
44
|
+
const { session, response } = await client.sessions.create({
|
|
45
45
|
message: "What should I do on this screen?",
|
|
46
46
|
clientContext: {
|
|
47
47
|
route: "/billing",
|
|
@@ -60,17 +60,15 @@ await response.result();
|
|
|
60
60
|
`send()` accepts AI SDK `UserContent`, so a message can mix text and file parts:
|
|
61
61
|
|
|
62
62
|
```ts
|
|
63
|
-
const response = await session.send(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
],
|
|
73
|
-
});
|
|
63
|
+
const response = await session.send([
|
|
64
|
+
{ type: "text", text: "Summarize this report." },
|
|
65
|
+
{
|
|
66
|
+
type: "file",
|
|
67
|
+
data: reportDataUrl,
|
|
68
|
+
mediaType: "application/pdf",
|
|
69
|
+
filename: "report.pdf",
|
|
70
|
+
},
|
|
71
|
+
]);
|
|
74
72
|
|
|
75
73
|
await response.result();
|
|
76
74
|
```
|
|
@@ -83,17 +81,15 @@ import { readFile } from "node:fs/promises";
|
|
|
83
81
|
const bytes = await readFile("report.pdf");
|
|
84
82
|
const reportDataUrl = `data:application/pdf;base64,${bytes.toString("base64")}`;
|
|
85
83
|
|
|
86
|
-
const response = await session.send(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
],
|
|
96
|
-
});
|
|
84
|
+
const response = await session.send([
|
|
85
|
+
{ type: "text", text: "Summarize this report." },
|
|
86
|
+
{
|
|
87
|
+
type: "file",
|
|
88
|
+
data: reportDataUrl,
|
|
89
|
+
mediaType: "application/pdf",
|
|
90
|
+
filename: "report.pdf",
|
|
91
|
+
},
|
|
92
|
+
]);
|
|
97
93
|
|
|
98
94
|
await response.result();
|
|
99
95
|
```
|
|
@@ -119,17 +115,17 @@ for await (const event of response) {
|
|
|
119
115
|
}
|
|
120
116
|
}
|
|
121
117
|
|
|
122
|
-
const resumed = await session.
|
|
123
|
-
|
|
118
|
+
const resumed = await session.respond(
|
|
119
|
+
pendingRequests.map((request) => ({
|
|
124
120
|
requestId: request.requestId,
|
|
125
121
|
optionId: "approve",
|
|
126
122
|
})),
|
|
127
|
-
|
|
123
|
+
);
|
|
128
124
|
|
|
129
125
|
await resumed.result();
|
|
130
126
|
```
|
|
131
127
|
|
|
132
|
-
|
|
128
|
+
`send(message, options)` and `respond(inputResponses, options)` are separate operations. Put `clientContext`, `outputSchema`, headers, or stream options in the second argument to either method.
|
|
133
129
|
|
|
134
130
|
## Single-use responses
|
|
135
131
|
|
|
@@ -27,9 +27,7 @@ const outputSchema = {
|
|
|
27
27
|
} as const;
|
|
28
28
|
|
|
29
29
|
const client = new Client({ host: "http://127.0.0.1:2000" });
|
|
30
|
-
const session = client.
|
|
31
|
-
|
|
32
|
-
const response = await session.send<Summary>({
|
|
30
|
+
const { session, response } = await client.sessions.create<Summary>({
|
|
33
31
|
message: "Summarize this turn.",
|
|
34
32
|
outputSchema,
|
|
35
33
|
});
|
|
@@ -56,8 +54,7 @@ const summarySchema = z.object({
|
|
|
56
54
|
|
|
57
55
|
type Summary = z.infer<typeof summarySchema>;
|
|
58
56
|
|
|
59
|
-
const response = await session.send<Summary>({
|
|
60
|
-
message: "Summarize this turn.",
|
|
57
|
+
const response = await session.send<Summary>("Summarize this turn.", {
|
|
61
58
|
outputSchema: summarySchema,
|
|
62
59
|
});
|
|
63
60
|
|
|
@@ -71,8 +68,7 @@ The server is authoritative for validation. The client types `MessageResult.data
|
|
|
71
68
|
If you consume events manually, read `result.completed`:
|
|
72
69
|
|
|
73
70
|
```ts
|
|
74
|
-
const response = await session.send<Summary>({
|
|
75
|
-
message: "Summarize this turn.",
|
|
71
|
+
const response = await session.send<Summary>("Summarize this turn.", {
|
|
76
72
|
outputSchema,
|
|
77
73
|
});
|
|
78
74
|
|
|
@@ -88,11 +84,10 @@ If more than one `result.completed` appears in the consumed event list, `result(
|
|
|
88
84
|
|
|
89
85
|
## Send payloads with output schema
|
|
90
86
|
|
|
91
|
-
`outputSchema`
|
|
87
|
+
Pass `outputSchema` in the second argument to `send()` or `respond()` alongside headers, signal, or client context:
|
|
92
88
|
|
|
93
89
|
```ts
|
|
94
|
-
const response = await session.send<Summary>({
|
|
95
|
-
message: "Summarize this PDF.",
|
|
90
|
+
const response = await session.send<Summary>("Summarize this PDF.", {
|
|
96
91
|
clientContext: { reportId: "rpt_123" },
|
|
97
92
|
outputSchema,
|
|
98
93
|
});
|
|
@@ -103,9 +98,7 @@ const result = await response.result();
|
|
|
103
98
|
It also works on follow-up turns and HITL response turns:
|
|
104
99
|
|
|
105
100
|
```ts
|
|
106
|
-
const response = await session.
|
|
107
|
-
inputResponses: [{ requestId, optionId: "approve" }],
|
|
108
|
-
message: "Return the approved action as structured output.",
|
|
101
|
+
const response = await session.respond([{ requestId, optionId: "approve" }], {
|
|
109
102
|
outputSchema,
|
|
110
103
|
});
|
|
111
104
|
|
|
@@ -117,7 +110,7 @@ const result = await response.result();
|
|
|
117
110
|
Client `outputSchema` is scoped to the turn that sends it. It doesn't become a permanent setting for the conversation:
|
|
118
111
|
|
|
119
112
|
```ts
|
|
120
|
-
const response = await session.send(
|
|
113
|
+
const response = await session.send("Return a structured summary.", { outputSchema });
|
|
121
114
|
await response.result();
|
|
122
115
|
|
|
123
116
|
const followUpResponse = await session.send("Now answer normally.");
|
|
@@ -100,8 +100,7 @@ Set `redirect` to `"manual"` or `"error"` on credential-bearing clients so fetch
|
|
|
100
100
|
Per-request headers can be attached to an individual turn:
|
|
101
101
|
|
|
102
102
|
```ts
|
|
103
|
-
const response = await session.send({
|
|
104
|
-
message: "Run the check.",
|
|
103
|
+
const response = await session.send("Run the check.", {
|
|
105
104
|
headers: { "x-request-id": requestId },
|
|
106
105
|
});
|
|
107
106
|
|
|
@@ -112,23 +111,53 @@ Per-request headers override client-level values with the same name. For example
|
|
|
112
111
|
|
|
113
112
|
## Sessions
|
|
114
113
|
|
|
115
|
-
|
|
114
|
+
For an ID-addressed session, create it explicitly with the first message:
|
|
116
115
|
|
|
117
116
|
```ts
|
|
118
|
-
const session = client.
|
|
117
|
+
const { session, response } = await client.sessions.create({ message: "Summarize account A." });
|
|
118
|
+
await response.result();
|
|
119
|
+
|
|
120
|
+
await (await session.send("Now list the risks.")).result();
|
|
121
|
+
await session.compact();
|
|
122
|
+
await session.clear();
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
If you already know the durable ID, attach a fixed handle without performing I/O:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
const session = client.sessions.attach("wrun_A");
|
|
119
129
|
```
|
|
120
130
|
|
|
121
|
-
|
|
131
|
+
The fixed client handle exposes the full lifecycle around that ID. The calls below show the available shapes independently:
|
|
122
132
|
|
|
123
133
|
```ts
|
|
124
|
-
const
|
|
125
|
-
|
|
134
|
+
const response = await session.send("Continue the analysis.");
|
|
135
|
+
await response.result();
|
|
136
|
+
|
|
137
|
+
await session.cancel({ turnId: "turn_123" });
|
|
138
|
+
await session.compact();
|
|
139
|
+
await session.clear();
|
|
126
140
|
|
|
127
|
-
const
|
|
128
|
-
|
|
141
|
+
for await (const event of session.stream({ follow: false })) {
|
|
142
|
+
console.log(event.type);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
await session.reset({ reason: "User requested a fresh session" });
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`client.sessions` stores only the session ID and stream cursor. Every method calls an ID-addressed `/eve/v1/session/:sessionId/...` route. Sending through a handle for an unknown or terminal ID fails instead of creating a replacement, and reset leaves the handle pinned to the retired ID.
|
|
149
|
+
|
|
150
|
+
A client can own many independent fixed sessions at once:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
const { session: alice, response: aliceResponse } = await client.sessions.create({
|
|
154
|
+
message: "Summarize account A.",
|
|
155
|
+
});
|
|
156
|
+
const { session: bob, response: bobResponse } = await client.sessions.create({
|
|
157
|
+
message: "Summarize account B.",
|
|
158
|
+
});
|
|
129
159
|
|
|
130
|
-
|
|
131
|
-
await bobResponse.result();
|
|
160
|
+
await Promise.all([aliceResponse.result(), bobResponse.result()]);
|
|
132
161
|
```
|
|
133
162
|
|
|
134
163
|
The next pages cover the session lifecycle:
|
|
@@ -5,18 +5,22 @@ description: "Consume eve client stream events live, reconnect by event index, a
|
|
|
5
5
|
|
|
6
6
|
Every `ClientSession.send()` call posts the turn, then reads the session's NDJSON (newline-delimited JSON) event stream. `MessageResponse` gives you two ways to consume that stream, aggregating it with `result()` or iterating it live.
|
|
7
7
|
|
|
8
|
-
Once `send()` is accepted, the session exposes its assigned `sessionId` and can request cooperative cancellation with `session.cancel()`, even while the response stream is still running. The result status is `accepted` when the
|
|
8
|
+
Once `send()` is accepted, the session exposes its assigned `sessionId` and can request cooperative cancellation with `session.cancel()`, even while the response stream is still running. The result status is `accepted` when the live session durably queued the command, including when a parked session consumes it as a no-op. An unknown or terminal session returns `no_active_turn`:
|
|
9
9
|
|
|
10
10
|
```ts
|
|
11
|
-
const session = client.
|
|
12
|
-
const response = await session.send("Run the long operation.");
|
|
11
|
+
const { session, response } = await client.sessions.create({ message: "Run the long operation." });
|
|
13
12
|
|
|
14
13
|
const cancellation = await session.cancel();
|
|
15
|
-
|
|
14
|
+
if (cancellation.status === "accepted") {
|
|
15
|
+
console.log(cancellation.sessionId);
|
|
16
|
+
}
|
|
16
17
|
|
|
17
18
|
const result = await response.result();
|
|
18
19
|
```
|
|
19
20
|
|
|
21
|
+
The cancellation result is discriminated by `status`: only `accepted` includes
|
|
22
|
+
`sessionId`; `no_active_turn` has no session identity field.
|
|
23
|
+
|
|
20
24
|
Cancellation does not replace stream consumption. Continue reading the response to observe its terminal `turn.cancelled` and `session.waiting` boundary and to advance the client session cursor normally.
|
|
21
25
|
|
|
22
26
|
Between turns, `session.compact()` queues context compaction without sending model input. An accepted request reports the session id; consume the durable stream through the following `session.waiting` boundary before sending the next turn. `compaction.completed` confirms that summarization succeeded; without it, eve preserves the previous history. A never-started session returns `no_active_session` as a successful no-op.
|
|
@@ -99,10 +103,11 @@ The most common UI events are:
|
|
|
99
103
|
| `reasoning.appended` | Render reasoning deltas when the model provides them. |
|
|
100
104
|
| `message.appended` | Render assistant text deltas. |
|
|
101
105
|
| `actions.requested` | Show tool calls as the model requests them, before execution. |
|
|
106
|
+
| `action.partial` | Update a generator tool's provisional output snapshot. |
|
|
102
107
|
| `action.result` | Show tool call results. |
|
|
103
108
|
| `input.requested` | Pause the UI for approval or a question answer. |
|
|
104
109
|
| `result.completed` | Read structured output from an [output schema](./output-schema). |
|
|
105
|
-
| `session.waiting` | Enable the composer
|
|
110
|
+
| `session.waiting` | Enable the composer; the same fixed session handle accepts the next message. |
|
|
106
111
|
| `session.completed` | Mark the conversation terminal. |
|
|
107
112
|
| `session.failed` | Mark the conversation failed. |
|
|
108
113
|
|
|
@@ -128,8 +133,7 @@ If your consumer persists events, key on `event.meta.id`. It is stable across re
|
|
|
128
133
|
Set `streamReconnectPolicy: { reconnect: false }` when a relay or proxy owns the cursor and reconnection policy. This makes a single stream GET attempt and returns when that connection ends; it does not stop the server-side turn:
|
|
129
134
|
|
|
130
135
|
```ts
|
|
131
|
-
const response = await session.send({
|
|
132
|
-
message: "Run the long operation.",
|
|
136
|
+
const response = await session.send("Run the long operation.", {
|
|
133
137
|
streamReconnectPolicy: { reconnect: false },
|
|
134
138
|
});
|
|
135
139
|
|
|
@@ -145,9 +149,7 @@ The same option is available on manual attachments as `session.stream({ streamRe
|
|
|
145
149
|
Use `session.stream()` when you already have a session cursor and only need to attach to the existing stream:
|
|
146
150
|
|
|
147
151
|
```ts
|
|
148
|
-
const session = client.
|
|
149
|
-
continuationToken: "eve:6c8b1f2e-3d4a-4b9c-8e21-9f0a1b2c3d4e",
|
|
150
|
-
sessionId: "wrun_01ARYZ6S41TSV4RRFFQ69G5FAV",
|
|
152
|
+
const session = client.sessions.attach("wrun_01ARYZ6S41TSV4RRFFQ69G5FAV", {
|
|
151
153
|
streamIndex: 10,
|
|
152
154
|
});
|
|
153
155
|
|
|
@@ -168,9 +170,7 @@ Nonnegative values are absolute event indexes. Negative values read relative to
|
|
|
168
170
|
|
|
169
171
|
```ts
|
|
170
172
|
for await (const event of session.stream({ startIndex: -1 })) {
|
|
171
|
-
|
|
172
|
-
console.log(event.data.continuationToken);
|
|
173
|
-
}
|
|
173
|
+
console.log(event.type);
|
|
174
174
|
break;
|
|
175
175
|
}
|
|
176
176
|
```
|
|
@@ -192,15 +192,13 @@ The first connection pins the bound to the tail the server reports at open time;
|
|
|
192
192
|
|
|
193
193
|
Because a tail-relative cursor cannot be bounded, `follow: false` throws when combined with a negative `startIndex`. It also fails if the server does not report the durable tail (an agent running an older eve version).
|
|
194
194
|
|
|
195
|
-
`stream()` throws if the session has no `sessionId`, because there's no stream to attach to before the first send.
|
|
196
|
-
|
|
197
195
|
## Snapshot a session
|
|
198
196
|
|
|
199
197
|
Use `snapshot()` when you need the complete event prefix and its matching cursor
|
|
200
198
|
as one value, such as when hydrating a server-rendered chat:
|
|
201
199
|
|
|
202
200
|
```ts
|
|
203
|
-
const session = client.
|
|
201
|
+
const session = client.sessions.attach(sessionId);
|
|
204
202
|
const snapshot = await session.snapshot();
|
|
205
203
|
|
|
206
204
|
// snapshot.events contains event indexes 0 through snapshot.session.streamIndex - 1.
|
|
@@ -212,11 +210,9 @@ The read pins the durable tail when it opens, just like
|
|
|
212
210
|
continue. `snapshot()` always reads from index `0`; use a bounded stream directly
|
|
213
211
|
when you only need the unread suffix from an existing cursor.
|
|
214
212
|
|
|
215
|
-
Unlike `stream()`, `snapshot()` does not advance
|
|
216
|
-
`ClientSession`. Its returned
|
|
217
|
-
the captured prefix
|
|
218
|
-
explicitly preserved by the client. Active and terminal snapshots remain
|
|
219
|
-
inspectable at their returned stream cursor but cannot accept another turn.
|
|
213
|
+
Unlike `stream()`, `snapshot()` does not advance the originating
|
|
214
|
+
`ClientSession`. Its returned cursor contains the fixed session ID and the exact
|
|
215
|
+
stream index after the captured prefix.
|
|
220
216
|
|
|
221
217
|
## Abort a request
|
|
222
218
|
|
|
@@ -228,8 +224,7 @@ Arm the timeout before awaiting `send()` so it covers the POST as well as the st
|
|
|
228
224
|
const controller = new AbortController();
|
|
229
225
|
const timeout = setTimeout(() => controller.abort(), 10_000);
|
|
230
226
|
|
|
231
|
-
const response = await session.send({
|
|
232
|
-
message: "Run a long analysis.",
|
|
227
|
+
const response = await session.send("Run a long analysis.", {
|
|
233
228
|
signal: controller.signal,
|
|
234
229
|
});
|
|
235
230
|
|