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.
Files changed (240) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +5 -6
  3. package/dist/src/acp/adapter.d.ts +10 -4
  4. package/dist/src/acp/adapter.js +1 -1
  5. package/dist/src/channel/adapter-context.d.ts +1 -1
  6. package/dist/src/channel/adapter.d.ts +2 -4
  7. package/dist/src/channel/adapter.js +1 -1
  8. package/dist/src/channel/channel-address.d.ts +58 -0
  9. package/dist/src/channel/channel-address.js +1 -0
  10. package/dist/src/channel/channel-operations.d.ts +72 -0
  11. package/dist/src/channel/channel-operations.js +1 -0
  12. package/dist/src/channel/compiled-channel.d.ts +10 -6
  13. package/dist/src/channel/cross-channel-receive.d.ts +13 -25
  14. package/dist/src/channel/cross-channel-receive.js +2 -2
  15. package/dist/src/channel/receive-target.d.ts +1 -2
  16. package/dist/src/channel/routes.d.ts +21 -149
  17. package/dist/src/channel/schedule.d.ts +1 -1
  18. package/dist/src/channel/schedule.js +1 -1
  19. package/dist/src/channel/send-input.d.ts +6 -0
  20. package/dist/src/channel/send-input.js +1 -0
  21. package/dist/src/channel/session.d.ts +44 -30
  22. package/dist/src/channel/session.js +1 -1
  23. package/dist/src/channel/types.d.ts +8 -35
  24. package/dist/src/chunks/{use-eve-agent-k-XHfrJT.js → use-eve-agent-CF5D6jSV.js} +361 -367
  25. package/dist/src/chunks/{use-eve-agent-BXMIf5fR.js → use-eve-agent-DbYZLG0h.js} +364 -368
  26. package/dist/src/cli/commands/agent-prompt/build-and-verify.md +1 -2
  27. package/dist/src/cli/commands/channel-add-conflicts.js +1 -1
  28. package/dist/src/cli/commands/info.d.ts +1 -1
  29. package/dist/src/cli/commands/info.js +1 -1
  30. package/dist/src/cli/commands/registry-metadata.d.ts +15 -0
  31. package/dist/src/cli/commands/registry-metadata.js +1 -0
  32. package/dist/src/cli/commands/registry-package.d.ts +46 -0
  33. package/dist/src/cli/commands/registry-package.js +1 -0
  34. package/dist/src/cli/commands/registry.d.ts +1 -1
  35. package/dist/src/cli/commands/registry.js +4 -4
  36. package/dist/src/cli/dev/tui/runner.d.ts +1 -1
  37. package/dist/src/cli/dev/tui/runner.js +1 -1
  38. package/dist/src/cli/dev/tui/subagent-pump.js +1 -1
  39. package/dist/src/cli/dev/tui/terminal-renderer.js +2 -2
  40. package/dist/src/cli/dev/tui/tui.js +1 -1
  41. package/dist/src/cli/invoke/invoke.d.ts +1 -1
  42. package/dist/src/cli/invoke/invoke.js +1 -1
  43. package/dist/src/cli/invoke/result.d.ts +0 -11
  44. package/dist/src/cli/invoke/result.js +1 -1
  45. package/dist/src/client/client-error.d.ts +2 -0
  46. package/dist/src/client/client-error.js +1 -1
  47. package/dist/src/client/client.d.ts +7 -14
  48. package/dist/src/client/client.js +1 -1
  49. package/dist/src/client/eve-agent-store.d.ts +4 -4
  50. package/dist/src/client/eve-agent-store.js +1 -1
  51. package/dist/src/client/index.d.ts +3 -2
  52. package/dist/src/client/index.js +1 -1
  53. package/dist/src/client/message-reducer-types.d.ts +3 -0
  54. package/dist/src/client/message-reducer.js +1 -1
  55. package/dist/src/client/message-response.d.ts +2 -7
  56. package/dist/src/client/message-response.js +1 -1
  57. package/dist/src/client/open-stream.js +1 -1
  58. package/dist/src/client/session-controls.d.ts +29 -0
  59. package/dist/src/client/session-controls.js +1 -0
  60. package/dist/src/client/session-utils.d.ts +0 -20
  61. package/dist/src/client/session-utils.js +1 -1
  62. package/dist/src/client/session.d.ts +26 -90
  63. package/dist/src/client/session.js +1 -1
  64. package/dist/src/client/sessions.d.ts +20 -0
  65. package/dist/src/client/sessions.js +1 -0
  66. package/dist/src/client/types.d.ts +26 -47
  67. package/dist/src/compiler/extension-compatibility.d.ts +10 -10
  68. package/dist/src/compiler/extension-compatibility.js +1 -1
  69. package/dist/src/compiler/normalize-subagent.js +1 -1
  70. package/dist/src/evals/cli/eval-client.js +1 -1
  71. package/dist/src/evals/context.js +1 -1
  72. package/dist/src/evals/session.d.ts +7 -6
  73. package/dist/src/evals/session.js +1 -1
  74. package/dist/src/evals/types.d.ts +9 -9
  75. package/dist/src/execution/agent-handle-dispatch.js +1 -1
  76. package/dist/src/execution/cancel-descendant-turns-step.js +1 -1
  77. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  78. package/dist/src/execution/remote-agent-dispatch.d.ts +1 -3
  79. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  80. package/dist/src/execution/runtime-context.js +1 -1
  81. package/dist/src/execution/runtime-errors.d.ts +1 -1
  82. package/dist/src/execution/session-command-token.d.ts +2 -0
  83. package/dist/src/execution/session-command-token.js +1 -1
  84. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  85. package/dist/src/execution/subagent-hitl-proxy.js +1 -1
  86. package/dist/src/execution/tool-auth.d.ts +1 -1
  87. package/dist/src/execution/tool-auth.js +1 -1
  88. package/dist/src/execution/turn-control-receiver.d.ts +2 -2
  89. package/dist/src/execution/turn-workflow.js +1 -1
  90. package/dist/src/execution/workflow-entry.js +1 -1
  91. package/dist/src/execution/workflow-runtime.js +1 -1
  92. package/dist/src/harness/cancelled-turn-emission.d.ts +1 -1
  93. package/dist/src/harness/cancelled-turn-emission.js +1 -1
  94. package/dist/src/harness/emission-state.d.ts +25 -0
  95. package/dist/src/harness/emission-state.js +1 -0
  96. package/dist/src/harness/emission.d.ts +5 -37
  97. package/dist/src/harness/emission.js +1 -1
  98. package/dist/src/harness/handles/prompt.d.ts +22 -3
  99. package/dist/src/harness/handles/prompt.js +1 -1
  100. package/dist/src/harness/handles/store.d.ts +0 -5
  101. package/dist/src/harness/handles/store.js +1 -1
  102. package/dist/src/harness/ordered-stream-emitter.d.ts +3 -2
  103. package/dist/src/harness/ordered-stream-emitter.js +1 -1
  104. package/dist/src/harness/runtime-actions.js +1 -1
  105. package/dist/src/harness/session-limit-enforcement.js +1 -1
  106. package/dist/src/harness/tool-loop.js +1 -1
  107. package/dist/src/harness/tools.d.ts +1 -1
  108. package/dist/src/harness/tools.js +1 -1
  109. package/dist/src/internal/application/package.js +1 -1
  110. package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
  111. package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
  112. package/dist/src/internal/nitro/dev-runtime-source-snapshot-local-roots.d.ts +15 -0
  113. package/dist/src/internal/nitro/dev-runtime-source-snapshot-local-roots.js +1 -0
  114. package/dist/src/internal/nitro/dev-runtime-source-snapshot.d.ts +14 -2
  115. package/dist/src/internal/nitro/dev-runtime-source-snapshot.js +1 -1
  116. package/dist/src/internal/nitro/host/dev-server-http.js +1 -1
  117. package/dist/src/internal/nitro/routes/channel-dispatch.d.ts +2 -5
  118. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  119. package/dist/src/internal/nitro/routes/channel-route-context.d.ts +4 -3
  120. package/dist/src/internal/nitro/routes/channel-route-context.js +1 -1
  121. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  122. package/dist/src/protocol/cancel-turn.d.ts +9 -4
  123. package/dist/src/protocol/cancel-turn.js +1 -1
  124. package/dist/src/protocol/message.d.ts +27 -17
  125. package/dist/src/protocol/message.js +2 -2
  126. package/dist/src/protocol/reset-session.d.ts +1 -1
  127. package/dist/src/protocol/routes.d.ts +27 -47
  128. package/dist/src/protocol/routes.js +1 -1
  129. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +19 -21
  130. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
  131. package/dist/src/public/channels/discord/discordChannel.d.ts +5 -4
  132. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  133. package/dist/src/public/channels/eve.d.ts +11 -10
  134. package/dist/src/public/channels/eve.js +1 -1
  135. package/dist/src/public/channels/github/dispatch.d.ts +8 -8
  136. package/dist/src/public/channels/github/dispatch.js +1 -1
  137. package/dist/src/public/channels/github/githubChannel.d.ts +4 -3
  138. package/dist/src/public/channels/github/githubChannel.js +1 -1
  139. package/dist/src/public/channels/github/pr-context.d.ts +1 -1
  140. package/dist/src/public/channels/index.d.ts +1 -1
  141. package/dist/src/public/channels/linear/linearChannel.d.ts +4 -3
  142. package/dist/src/public/channels/linear/linearChannel.js +1 -1
  143. package/dist/src/public/channels/slack/index.d.ts +1 -1
  144. package/dist/src/public/channels/slack/interactions.d.ts +3 -4
  145. package/dist/src/public/channels/slack/interactions.js +1 -1
  146. package/dist/src/public/channels/slack/session-operations.d.ts +37 -0
  147. package/dist/src/public/channels/slack/session-operations.js +1 -0
  148. package/dist/src/public/channels/slack/slackChannel.d.ts +56 -74
  149. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  150. package/dist/src/public/channels/teams/teamsChannel.d.ts +4 -3
  151. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  152. package/dist/src/public/channels/telegram/telegramChannel.d.ts +5 -4
  153. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  154. package/dist/src/public/channels/twilio/twilioChannel.d.ts +4 -3
  155. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  156. package/dist/src/public/definitions/callback-context.d.ts +1 -2
  157. package/dist/src/public/definitions/channel.d.ts +22 -86
  158. package/dist/src/public/definitions/channel.js +1 -1
  159. package/dist/src/public/definitions/hook.d.ts +1 -0
  160. package/dist/src/public/definitions/remote-agent.js +1 -1
  161. package/dist/src/public/definitions/schedule.d.ts +16 -16
  162. package/dist/src/public/definitions/tool.d.ts +5 -5
  163. package/dist/src/public/schedules/index.d.ts +1 -1
  164. package/dist/src/react/use-eve-agent.d.ts +7 -4
  165. package/dist/src/react/use-eve-agent.js +1 -1
  166. package/dist/src/runtime/agent/bootstrap-model-utils.d.ts +11 -0
  167. package/dist/src/runtime/agent/bootstrap-model-utils.js +1 -1
  168. package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
  169. package/dist/src/runtime/agent/mock-model-fixtures.js +2 -2
  170. package/dist/src/runtime/prompt/compose.js +1 -1
  171. package/dist/src/runtime/subagents/dynamic-remote-agent-config.js +1 -1
  172. package/dist/src/runtime/types.d.ts +2 -2
  173. package/dist/src/services/inspect-application.d.ts +1 -1
  174. package/dist/src/services/inspect-application.js +1 -1
  175. package/dist/src/setup/channel-add-conflicts.js +1 -1
  176. package/dist/src/setup/integrations/linear/setup.js +1 -1
  177. package/dist/src/setup/scaffold/create/project.js +1 -1
  178. package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
  179. package/dist/src/setup/scaffold/create/web-template.js +29 -17
  180. package/dist/src/shared/async-iterable.d.ts +2 -0
  181. package/dist/src/shared/async-iterable.js +1 -0
  182. package/dist/src/shared/channel-definition.d.ts +7 -7
  183. package/dist/src/shared/schedule-definition.d.ts +2 -2
  184. package/dist/src/shared/tool-definition.d.ts +1 -1
  185. package/dist/src/svelte/index.js +1 -1
  186. package/dist/src/svelte/use-eve-agent.d.ts +8 -5
  187. package/dist/src/svelte/use-eve-agent.js +1 -1
  188. package/dist/src/vue/index.js +1 -1
  189. package/dist/src/vue/use-eve-agent.d.ts +8 -5
  190. package/dist/src/vue/use-eve-agent.js +1 -1
  191. package/docs/README.md +6 -6
  192. package/docs/channels/chat-sdk.mdx +5 -6
  193. package/docs/channels/custom.mdx +116 -144
  194. package/docs/channels/discord.mdx +1 -1
  195. package/docs/channels/eve.mdx +76 -30
  196. package/docs/channels/github.mdx +1 -1
  197. package/docs/channels/linear.mdx +10 -10
  198. package/docs/channels/overview.mdx +2 -2
  199. package/docs/channels/slack.mdx +46 -15
  200. package/docs/channels/telegram.mdx +1 -1
  201. package/docs/channels/twilio.mdx +1 -1
  202. package/docs/concepts/default-harness.md +11 -3
  203. package/docs/concepts/execution-model-and-durability.mdx +17 -5
  204. package/docs/concepts/sessions-runs-and-streaming.md +45 -16
  205. package/docs/evals/cases.mdx +3 -3
  206. package/docs/evals/targets.mdx +1 -1
  207. package/docs/guides/auth-and-route-protection.md +2 -1
  208. package/docs/guides/client/continuations.mdx +50 -77
  209. package/docs/guides/client/messages.mdx +29 -33
  210. package/docs/guides/client/output-schema.mdx +7 -14
  211. package/docs/guides/client/overview.mdx +40 -11
  212. package/docs/guides/client/streaming.mdx +18 -23
  213. package/docs/guides/frontend/nuxt.mdx +1 -1
  214. package/docs/guides/frontend/overview.mdx +40 -36
  215. package/docs/guides/frontend/sveltekit.mdx +1 -1
  216. package/docs/guides/frontend/use-eve-agent-svelte.mdx +19 -23
  217. package/docs/guides/frontend/use-eve-agent-vue.mdx +21 -25
  218. package/docs/guides/hooks.md +1 -1
  219. package/docs/guides/instrumentation.md +1 -1
  220. package/docs/install-integrations.mdx +4 -2
  221. package/docs/patterns/dynamic-scheduling.md +16 -15
  222. package/docs/reference/cli.md +4 -1
  223. package/docs/schedules.mdx +10 -11
  224. package/docs/subagents.mdx +1 -1
  225. package/docs/tools/human-in-the-loop.md +1 -1
  226. package/docs/tools/overview.mdx +26 -2
  227. package/docs/tutorial/ship-it.mdx +1 -1
  228. package/package.json +1 -1
  229. package/dist/src/channel/cancel.d.ts +0 -6
  230. package/dist/src/channel/cancel.js +0 -1
  231. package/dist/src/channel/clear-session.d.ts +0 -4
  232. package/dist/src/channel/clear-session.js +0 -1
  233. package/dist/src/channel/compact-session.d.ts +0 -4
  234. package/dist/src/channel/compact-session.js +0 -1
  235. package/dist/src/channel/reset-session.d.ts +0 -6
  236. package/dist/src/channel/reset-session.js +0 -1
  237. package/dist/src/channel/resolve-active-session.d.ts +0 -4
  238. package/dist/src/channel/resolve-active-session.js +0 -1
  239. package/dist/src/channel/send.d.ts +0 -6
  240. package/dist/src/channel/send.js +0 -1
@@ -11,10 +11,12 @@ The Linear channel uses Linear's Agent Session surface rather than ordinary comm
11
11
  Run the registry setup from the agent directory:
12
12
 
13
13
  ```bash
14
- eve add channel/linear-agent
14
+ eve add linear
15
15
  ```
16
16
 
17
- The flow checks that the Vercel CLI is authenticated, creates or links a Vercel project when needed, provisions an app-scoped Linear Connect client, and replaces its default trigger with `/eve/v1/linear`. It then installs `@vercel/connect` and writes `agent/channels/linear.ts` with the connector UID.
17
+ Select **Linear Channel** in the component checklist. **Linear MCP** is also selected by default if you want the agent to search and update Linear through MCP. Run `eve add channel/linear-agent` instead to install only the channel directly.
18
+
19
+ The flow checks that the Vercel CLI is authenticated, creates or links a Vercel project when needed, reuses a compatible existing connector when available or provisions an app-scoped Linear Connect client, and replaces its default trigger with `/eve/v1/linear`. It then installs `@vercel/connect` and writes `agent/channels/linear.ts` with the connector UID.
18
20
 
19
21
  Vercel Connect creates the Linear app with the `app:assignable` and `app:mentionable` scopes required for Agent Sessions, receives and verifies `AgentSessionEvent` webhooks, and forwards them to the deployed agent. After deploying, open the Linear app in the Connect dashboard and install it in the workspace where you want to delegate work. Then delegate an issue or mention the agent in a Linear Agent Session.
20
22
 
@@ -158,7 +160,7 @@ await channel.linear.updateSession({
158
160
 
159
161
  ## Proactive sessions
160
162
 
161
- Use the channel's `receive` target to continue an existing Agent Session or create one from a Linear issue or root comment. The target accepts an existing `agentSessionId`, or an `issueId` or root `commentId` to create a new session before sending the message. The example below runs from a schedule; a route handler uses the same target shape through its own `receive` helper.
163
+ Use the channel's proactive target to continue an existing Agent Session or create one from a Linear issue or root comment. The target accepts an existing `agentSessionId`, or an `issueId` or root `commentId` to create a new session before sending the message. The example below runs from a schedule; a route handler uses the same target shape through `ctx.to(...)`.
162
164
 
163
165
  ```ts
164
166
  import { defineSchedule } from "eve/schedules";
@@ -167,15 +169,13 @@ import linear from "../channels/linear";
167
169
 
168
170
  export default defineSchedule({
169
171
  cron: "0 14 * * 1",
170
- async run({ receive, waitUntil, appAuth }) {
172
+ async run({ to, waitUntil, appAuth }) {
171
173
  waitUntil(
172
- receive(linear, {
174
+ to(linear, {
175
+ issueId: "EVE-123",
176
+ initialActivity: "Preparing the status update.",
177
+ }).send("Post a concise status update with blockers and next actions.", {
173
178
  auth: appAuth,
174
- message: "Post a concise status update with blockers and next actions.",
175
- target: {
176
- issueId: "EVE-123",
177
- initialActivity: "Preparing the status update.",
178
- },
179
179
  }),
180
180
  );
181
181
  },
@@ -6,7 +6,7 @@ description: "How users reach your agent: the channel contract, the base eve HTT
6
6
  A channel is the edge adapter between a platform and your agent. It does three things:
7
7
 
8
8
  - Normalizes platform input into a user message.
9
- - Owns the `continuationToken`, the resume handle for a conversation on that surface.
9
+ - Owns the channel-local address that maps a platform conversation to its current durable session.
10
10
  - Decides delivery, meaning how, where, and whether a response goes back.
11
11
 
12
12
  eve ships a base HTTP channel plus first-class platform channels, and you can author your own. Browse the full set in the [Integrations](/integrations) gallery and choose the Channels filter.
@@ -36,7 +36,7 @@ The eve channel is the framework's default HTTP session API, the routes the term
36
36
 
37
37
  ## Custom channels
38
38
 
39
- When eve doesn't ship a channel for your surface, build one with `defineChannel` from `eve/channels`. A custom channel declares route handlers (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `WS`), an `events` map, and a `send` call inside a handler to start or resume a session. See [Custom channels](./custom) for the full walkthrough, including WebSocket routes, cross-channel hand-off, channel metadata, continuation tokens, and file uploads.
39
+ When eve doesn't ship a channel for your surface, build one with `defineChannel` from `eve/channels`. A custom channel declares route handlers (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `WS`), an `events` map, and uses `send(address, input)` to start or resume a session. See [Custom channels](./custom) for the full walkthrough, including WebSocket routes, cross-channel hand-off, channel metadata, address tokens, and file uploads.
40
40
 
41
41
  ## Relationship to the Chat SDK
42
42
 
@@ -108,7 +108,7 @@ Like `threadContext`, this helper calls `conversations.replies` and requires the
108
108
 
109
109
  #### Cancel an active turn
110
110
 
111
- Message hooks (`onMessage`, `onAppMention`, and `onDirectMessage`) receive a thread-bound `ctx.cancel({ turnId? })` helper. Call it before returning `{ auth }` to stop the current turn and queue the new Slack message as replacement input, producing a debounce-like experience:
111
+ Message hooks (`onMessage`, `onAppMention`, and `onDirectMessage`) receive thread-bound session operations directly on `ctx`. Call `ctx.cancel({ turnId? })` before returning `{ auth }` to stop the current turn and queue the new Slack message as replacement input, producing a debounce-like experience:
112
112
 
113
113
  ```ts title="agent/channels/slack.ts"
114
114
  export default slackChannel({
@@ -123,11 +123,28 @@ export default slackChannel({
123
123
  });
124
124
  ```
125
125
 
126
- `"accepted"` means the cancellation request was consumed; `"no_active_turn"` means the thread had no cancellable turn. Both are successful outcomes, so the hook can still return `{ auth }` to deliver the replacement message. Cancellation never sends input itself. A custom `onInteraction` handler receives the same bound helper, which is useful for a Stop button that should cancel without replacement input.
126
+ `"accepted"` means the live thread session durably queued the cancellation request. A parked session consumes it as a no-op; `"no_active_turn"` means the thread has no active session owner. Both are successful outcomes, so the hook can still return `{ auth }` to deliver the replacement message. Cancellation never sends input itself. A custom `onInteraction` handler receives the same flat operations, which is useful for a Stop button that should cancel without replacement input.
127
+
128
+ Message and interaction hooks expose every current-owner operation directly on `ctx`:
129
+
130
+ ```ts
131
+ async onAppMention(ctx) {
132
+ await ctx.send("Run a separate turn.");
133
+ await ctx.respond(inputResponses);
134
+ await ctx.cancel();
135
+ await ctx.compact();
136
+ await ctx.clear();
137
+ await ctx.reset({ reason: "Start over" });
138
+ const session = await ctx.resolveSession();
139
+ return { auth: null };
140
+ }
141
+ ```
142
+
143
+ These calls are independent examples; a handler normally chooses one. `ctx.send()` is the only method that can create a session when the thread is unowned. It derives Slack auth from the inbound user unless `auth` is supplied explicitly. Use `await ctx.resolveSession()` only when later work must stay pinned to the currently owning durable session ID.
127
144
 
128
145
  #### Reset a conversation
129
146
 
130
- Use the thread-bound `ctx.reset({ reason? })` helper when the conversation should start over instead. Reset terminally retires the session that currently owns the thread, including any in-flight turn. The next delivered message starts a new session with fresh history, state, and a new session-scoped sandbox:
147
+ Use the thread-bound `ctx.reset({ reason? })` method when the conversation should start over instead. Reset terminally retires the session that currently owns the thread, including any in-flight turn. The next delivered message starts a new session with fresh history, state, and a new session-scoped sandbox:
131
148
 
132
149
  ```ts title="agent/channels/slack.ts"
133
150
  export default slackChannel({
@@ -142,11 +159,11 @@ export default slackChannel({
142
159
  });
143
160
  ```
144
161
 
145
- Reset returns `{ status: "reset", previousSessionId }` when the thread had a session, or `{ status: "no_active_session" }` when it was already free. Both outcomes are successful. Returning `null` after reset consumes the triggering message as a command; return `{ auth }` instead to deliver that message as the first turn of the fresh session. Custom `onInteraction` handlers receive the same bound reset helper, which is useful for a New conversation button.
162
+ Reset returns `{ status: "reset", previousSessionId }` when the thread had a session, or `{ status: "no_active_session" }` when it was already free. Both outcomes are successful. Returning `null` after reset consumes the triggering message as a command; return `{ auth }` instead to deliver that message as the first turn of the fresh session. Custom `onInteraction` handlers receive the same flat operations, which is useful for a New conversation button.
146
163
 
147
164
  ### Other Events API callbacks
148
165
 
149
- 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.
166
+ 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. Call `ctx.send(message, { target, auth })` zero, one, or many times to start turns. Each call returns the resulting session.
150
167
 
151
168
  ```ts title="agent/channels/slack.ts"
152
169
  import { connectSlackCredentials } from "@vercel/connect/eve";
@@ -156,25 +173,39 @@ const onboardingChannels = ["C0123ABC", "C0456DEF"];
156
173
 
157
174
  export default slackChannel({
158
175
  credentials: connectSlackCredentials("slack/my-agent"),
159
- async onEvent({ receive }, event) {
176
+ async onEvent(ctx, event) {
160
177
  if (event.type !== "team_join") return;
161
178
 
162
179
  await Promise.all(
163
180
  onboardingChannels.map((channelId) =>
164
- receive({
165
- message: `A user joined the Slack workspace. Onboard them from this event:\n${JSON.stringify(event)}`,
166
- target: { channelId },
167
- auth: null,
168
- }),
181
+ ctx.send(
182
+ `A user joined the Slack workspace. Onboard them from this event:\n${JSON.stringify(event)}`,
183
+ {
184
+ target: { channelId },
185
+ auth: null,
186
+ },
187
+ ),
169
188
  ),
170
189
  );
171
190
  },
172
191
  });
173
192
  ```
174
193
 
175
- 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.
194
+ 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.send` automatically seed the callback's team id into Slack session state.
195
+
196
+ Because a generic event is not necessarily tied to one thread, put the target in each operation's input:
176
197
 
177
- Because a generic event is not necessarily tied to one thread, its session helpers take the target explicitly: `ctx.cancel({ channelId, threadTs, turnId? })` stops in-flight work while retaining the session, and `ctx.reset({ channelId, threadTs, reason? })` retires the session. Pair either one with `ctx.receive(...)` when an event should deliver replacement input, or call it alone to stop or reset the thread.
198
+ ```ts
199
+ const target = { channelId, threadTs };
200
+
201
+ await ctx.send("Follow up", { auth: null, target });
202
+ await ctx.respond(inputResponses, { auth: null, target });
203
+ await ctx.cancel({ target, turnId });
204
+ await ctx.compact({ target });
205
+ await ctx.clear({ target });
206
+ await ctx.reset({ reason: "Start over", target });
207
+ const session = await ctx.resolveSession({ target });
208
+ ```
178
209
 
179
210
  `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.
180
211
 
@@ -233,7 +264,7 @@ The default handlers reply in-thread and show progress. Typing indicators post a
233
264
 
234
265
  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)`.
235
266
 
236
- When a session starts without a `threadTs` (say, from a schedule or `receive(slack, ...)`), eve gives it a unique temporary continuation token. The first agent post anchors the session to the Slack message timestamp, and later posts and mentions resume that same session. Pass `initialMessage` with a `Card` to land a structured anchor first instead. `threadTs` and `initialMessage` are mutually exclusive.
267
+ When a session starts without a `threadTs` (say, from a schedule's `to(slack, target).send(...)`), eve gives it a unique temporary continuation token. The first agent post anchors the session to the Slack message timestamp, and later posts and mentions resume that same session. Pass `initialMessage` with a `Card` to land a structured anchor first instead. `threadTs` and `initialMessage` are mutually exclusive.
237
268
 
238
269
  The example below overrides `onAppMention` to gate on an authored message and posts the completed reply to the thread. Event handlers receive `(eventData, channel, ctx)`, with Slack platform handles on `channel.thread` and `channel.slack`:
239
270
 
@@ -272,7 +303,7 @@ events: {
272
303
 
273
304
  ### Proactive sessions
274
305
 
275
- Start a session without an inbound message through `receive(slack, { message, target, auth })` from a schedule `run` handler, or `args.receive(slack, ...)` from another channel. The proactive target shape is `{ channelId }`.
306
+ Start a session without an inbound message through `ctx.to(slack, target).send(message, { auth })` from another channel, or `to(slack, target).send(message, { auth })` from a schedule `run` handler. The proactive target shape is `{ channelId, threadTs?, initialMessage? }`.
276
307
 
277
308
  ### Attachments
278
309
 
@@ -51,7 +51,7 @@ Human-in-the-loop (HITL) turns option requests into inline-keyboard buttons and
51
51
 
52
52
  ### Proactive sessions
53
53
 
54
- Start a session without an inbound message through `receive(telegram, { message, target, auth })` from a schedule `run` handler, or `args.receive(telegram, ...)` from another channel. `target.chatId` is required. Add `messageThreadId` to land in a specific forum topic.
54
+ Start a session without an inbound message through `to(telegram, target).send(message, { auth })` from a schedule `run` handler, or `ctx.to(telegram, target).send(message, { auth })` from another channel. `target.chatId` is required. Add `messageThreadId` to land in a specific forum topic.
55
55
 
56
56
  Private proactive chats stay keyed to the chat, or to the chat plus `messageThreadId` when you target a topic. Group and supergroup proactive sends anchor to the bot message id returned by Telegram, so replies to different bot messages can resume different sessions in the same chat. If Telegram does not return a recognized chat type for an outbound send, eve keeps the session unanchored instead of guessing.
57
57
 
@@ -66,7 +66,7 @@ SMS and voice have no native button or card affordance, so HITL prompts do not r
66
66
 
67
67
  ### Proactive sessions
68
68
 
69
- Start a session without an inbound message through `receive(twilio, { message, target, auth })` from a schedule `run` handler, or `args.receive(twilio, ...)` from another channel. `target.phoneNumber` is required, and the channel needs `messaging.from` or `messaging.messagingServiceSid` for the outbound sender.
69
+ Start a session without an inbound message through `to(twilio, target).send(message, { auth })` from a schedule `run` handler, or `ctx.to(twilio, target).send(message, { auth })` from another channel. `target.phoneNumber` is required, and the channel needs `messaging.from` or `messaging.messagingServiceSid` for the outbound sender.
70
70
 
71
71
  ### Attachments
72
72
 
@@ -20,9 +20,17 @@ export default defineAgent({
20
20
 
21
21
  Compaction also preserves the framework's own tool state automatically. It resets read-before-write tracking (so a write afterward re-reads the file whose read evidence was summarized away) and re-injects the active todo list, so the model keeps its task list across the summary. There is no per-tool hook to configure.
22
22
 
23
- Clients and channels can also request compaction between turns. Call `ClientSession.compact()` or a custom route's `compact({ continuationToken })` helper. The request does not append a user message; if a turn is running, eve queues it until that turn settles. A successful manual compaction emits the same `compaction.requested` and `compaction.completed` events as automatic compaction, followed by `session.waiting`.
24
-
25
- To discard model-message history instead of summarizing it, call `ClientSession.clear()` or a custom route's `clear({ continuationToken })` helper. Clearing preserves the session identity, system prompt, configured tools and skills, durable state, limits, and sandbox. Its stream boundary is `context.cleared` followed by `session.waiting`.
23
+ Clients and channels can also request compaction between turns. Call
24
+ `ClientSession.compact()`, a channel route's `compact(address)`, or
25
+ `attachSession(sessionId).compact()`. The request does not append a user message;
26
+ if a turn is running, eve queues it until that turn settles. A successful manual
27
+ compaction emits the same `compaction.requested` and `compaction.completed`
28
+ events as automatic compaction, followed by `session.waiting`.
29
+
30
+ To discard model-message history instead of summarizing it, call the corresponding
31
+ `clear()` method on any of those handles. Clearing preserves the session identity,
32
+ system prompt, configured tools and skills, durable state, limits, and sandbox.
33
+ Its stream boundary is `context.cleared` followed by `session.waiting`.
26
34
 
27
35
  ## Built-in tools
28
36
 
@@ -68,11 +68,23 @@ Some work has to wait, including a human approving a [tool](../tools), an intera
68
68
 
69
69
  ## Message delivery and queueing
70
70
 
71
- eve does not maintain a durable FIFO queue of user messages for a session. The `continuationToken` is a resume handle for the session's current workflow hook, not a general message-queue address.
72
-
73
- Only one active session can own a continuation token. When a session starts with a token, eve commits the park hook before processing its first turn and fails a competing session if another run already owns that token. A tokenless session claims its token after the first turn establishes one. Competing input is not forwarded to the owner.
74
-
75
- When a session is waiting, a delivery to the current continuation token wakes the session and starts the next turn. When a turn is already active, the hook may accept additional deliveries, but the runtime only drains them at specific workflow boundaries. If more than one delivery is ready when the driver checks, eve may fold them into the next turn; that drain is best-effort and depends on workflow and transport timing.
71
+ eve does not maintain a durable FIFO queue of user messages for a session. An
72
+ ID-addressed HTTP delivery and a channel-address delivery both target the
73
+ session's current command inbox; neither is a general message queue.
74
+
75
+ Only one active session can own a channel continuation token. A channel-created
76
+ session commits both its stable session-ID alias and its channel alias before
77
+ processing the first turn, and fails creation if another run already owns the
78
+ channel alias. Rekeying replaces only that channel alias. An HTTP-created
79
+ session has the stable ID alias and no channel continuation token. Competing
80
+ channel input is not forwarded to the owner.
81
+
82
+ When a session is waiting, a delivery through its ID or current channel address
83
+ wakes the session and starts the next turn. When a turn is already active, the
84
+ inbox may accept additional deliveries, but the runtime only drains them at
85
+ specific workflow boundaries. If more than one delivery is ready when the driver
86
+ checks, eve may fold them into the next turn; that drain is best-effort and
87
+ depends on workflow and transport timing.
76
88
 
77
89
  So don't rely on concurrent sends to the same session behaving like a typical ordered chat queue. For deterministic behavior, send one user turn at a time and wait for `session.waiting` before sending the next message to the same session. If your channel can receive bursts while the agent is working, keep your own per-session queue in the channel or app layer, then deliver the next message after the session parks again. Separate sessions still run independently.
78
90
 
@@ -1,18 +1,20 @@
1
1
  ---
2
2
  title: "Sessions, Runs & Streaming"
3
- description: "The session and run contract you touch: continuation tokens, stream handles, the NDJSON event stream, and reconnecting."
3
+ description: "The ID-addressed session contract: messages, controls, the NDJSON event stream, and reconnecting."
4
4
  ---
5
5
 
6
6
  Every eve app speaks the same stable HTTP API to a [durable session](./execution-model-and-durability). This page is the contract you hold: the handles you get back, the events you stream, and how to reconnect.
7
7
 
8
- ## The two handles
8
+ ## Identity by surface
9
9
 
10
- Two handles do two jobs, and mixing them up is the most common mistake. One handle creates and resumes a session; a different one streams and inspects it.
10
+ The HTTP API and TypeScript client use one durable `sessionId` for messages,
11
+ controls, and streams. Every operation targets that exact session; none follows
12
+ or creates a replacement implicitly.
11
13
 
12
- - **`continuationToken`**: the resume handle. Use it to send a follow-up message to the same conversation. Owned by the channel.
13
- - **`sessionId` / `runId`**: the stream-and-inspect handle. Use it to attach to the event stream and watch a run. Owned by the runtime.
14
-
15
- A session has one active continuation at a time: each follow-up uses the current `continuationToken`, and a stale one is rejected.
14
+ Authored channels also have channel-local continuation tokens. A token addresses
15
+ whichever session currently owns a platform conversation, such as a Slack thread.
16
+ That identity stays behind the channel boundary and is never accepted or returned
17
+ by the eve HTTP session API. See [Custom channels](../channels/custom#address-and-session-handles).
16
18
 
17
19
  Sessions last 30 days by default; configure `limits.sessionTimeoutMs` in
18
20
  `agent.ts`, or set it to `false` to disable the deadline. At expiration, eve
@@ -30,7 +32,8 @@ curl -X POST http://127.0.0.1:2000/eve/v1/session \
30
32
  -d '{"message":"Summarize the latest forecast."}'
31
33
  ```
32
34
 
33
- eve responds right away. The JSON body carries a `sessionId` and a `continuationToken`, and the `x-eve-session-id` header names the durable session to stream.
35
+ eve responds right away with the durable `sessionId` in the JSON body and
36
+ `x-eve-session-id` header.
34
37
 
35
38
  ## Stream a session
36
39
 
@@ -47,6 +50,7 @@ The stream is newline-delimited JSON (NDJSON), one event per line:
47
50
  | `message.received` | An inbound user message was accepted; carries flattened text plus structured text/file parts. |
48
51
  | `step.started` | A model step began. |
49
52
  | `actions.requested` | The model requested one or more actions, including tool calls; calls stream before execution. |
53
+ | `action.partial` | A locally executed tool generator yielded a preliminary output snapshot. |
50
54
  | `action.result` | A tool call returned. |
51
55
  | `input.requested` | The run paused for human input ([HITL](/docs/human-in-the-loop) approval or `ask_question`); carries `requests`. |
52
56
  | `subagent.called` | A subagent was delegated; carries `childSessionId` to attach to. |
@@ -65,12 +69,14 @@ The stream is newline-delimited JSON (NDJSON), one event per line:
65
69
  | `turn.completed` | The turn finished. |
66
70
  | `turn.failed` | The turn failed; carries `{ code, message, details? }`. |
67
71
  | `turn.cancelled` | The turn was cancelled before finishing; always followed by `session.waiting`. |
68
- | `session.waiting` | The session parked for the next input; carries the current channel-owned `continuationToken`. |
72
+ | `session.waiting` | The session parked and is ready for the next message. |
69
73
  | `session.failed` | The session failed. |
70
74
  | `session.completed` | The session reached a terminal end. |
71
75
 
72
76
  `reasoning.appended` and `message.appended` stream incremental output as it arrives. When the durable stream writer is busy, eve may coalesce adjacent deltas of the same type; the text remains in source order, and any other event forms an ordering barrier. Each append carries both the new delta and the cumulative text for the current block. The finalized block shows up on `message.completed` and `reasoning.completed`, which is the compatibility path for clients that don't render incremental streaming.
73
77
 
78
+ `action.partial` carries one complete preliminary output snapshot from an authored async-generator tool. A later partial for the same `callId` replaces it, and `action.result` is the final snapshot. When the durable writer is busy, eve may keep only the newest adjacent partial for a call. Treat partials as last-write-wins: a durable step can retry and replay overlapping event runs. Provider-executed tool progress and MCP progress notifications are not projected as `action.partial` events.
79
+
74
80
  Note: consider the privacy, confidentiality, and user-experience implications for displaying, storing, or transmitting reasoning events in your application.
75
81
 
76
82
  `message.completed` can fire more than once in a turn: the agent often emits interim assistant text before a tool call. To tell tool-call narration from a terminal reply, check `message.completed.data.finishReason`. `step.completed.data.finishReason` mirrors the step outcome, and usage lives on `step.completed`.
@@ -134,12 +140,12 @@ Authored [hooks](../guides/hooks) receive the same envelope, but observe each ev
134
140
 
135
141
  ## Send a follow-up message
136
142
 
137
- Once the session is waiting (you'll see `session.waiting`), POST your follow-up to the session endpoint with `event.data.continuationToken`:
143
+ Once the session is waiting (you'll see `session.waiting`), POST your follow-up to its ID-addressed messages endpoint:
138
144
 
139
145
  ```bash
140
146
  curl -X POST http://127.0.0.1:2000/eve/v1/session/<sessionId> \
141
147
  -H 'content-type: application/json' \
142
- -d '{"continuationToken":"<token>","message":"Now send the short version."}'
148
+ -d '{"message":"Now send the short version."}'
143
149
  ```
144
150
 
145
151
  The follow-up reuses the same durable session: same history, same state.
@@ -163,9 +169,30 @@ curl -X POST http://127.0.0.1:2000/eve/v1/session/<sessionId>/cancel
163
169
  # {"ok":true,"sessionId":"<sessionId>","status":"accepted"}
164
170
  ```
165
171
 
166
- `"accepted"` means a cancellation hook accepted the request. Confirm cancellation on the stream as `turn.cancelled` followed by `session.waiting`; the session then accepts the next message normally. If the turn is waiting on active local or remote subagents, eve also requests cancellation of every adopted child, recursively, before settling the parent. Each child reports its own cancellation boundary on its child-session stream; the parent does not emit `subagent.completed` for cancelled work. `"no_active_turn"` means no resumable cancellation target exists, including an unknown session or an already-settled turn. Both statuses are success, so clients can fire and forget. See the [eve channel](../channels/eve) for the full route contract.
172
+ `"accepted"` means the live session durably queued the request. Confirm an actual cancellation on the stream as `turn.cancelled` followed by `session.waiting`; the session then accepts the next message normally. If the turn is waiting on active local or remote subagents, eve also requests cancellation of every adopted child, recursively, before settling the parent. Each child reports its own cancellation boundary on its child-session stream; the parent does not emit `subagent.completed` for cancelled work. A live but already-parked session also returns `"accepted"` and consumes the command as a no-op. `"no_active_turn"` means the session or channel address is unknown or terminal. Both statuses are success, so clients can fire and forget. See the [eve channel](../channels/eve) for the full route contract.
173
+
174
+ The HTTP route returns `202` for `"accepted"` and `200` for
175
+ `"no_active_turn"`. Only the accepted result includes `sessionId`.
176
+
177
+ Custom channel routes request the same cancellation through
178
+ `from(address).cancel()` or `attachSession(sessionId).cancel()`. See
179
+ [custom channels](../channels/custom#channel-operations-and-session-handles).
180
+
181
+ ## Compact, clear, and reset
182
+
183
+ All session controls are ID-addressed and accept no continuation token:
184
+
185
+ ```bash
186
+ curl -X POST http://127.0.0.1:2000/eve/v1/session/<sessionId>/compact
187
+ curl -X POST http://127.0.0.1:2000/eve/v1/session/<sessionId>/clear
188
+ curl -X POST http://127.0.0.1:2000/eve/v1/session/<sessionId>/reset \
189
+ -H 'content-type: application/json' \
190
+ -d '{"reason":"Start over"}'
191
+ ```
167
192
 
168
- Custom channel routes request the same cancellation without knowing the session id: the `cancel` route helper is addressed by the channel-local continuation token, and `Session.cancel()` by session id. See [custom channels](../channels/custom#cancel-a-turn).
193
+ Compaction summarizes context, clear removes model-message history in place,
194
+ and reset terminally retires the session. A reset ID never becomes a new session;
195
+ create another session explicitly for a fresh conversation.
169
196
 
170
197
  ## Reconnect and rewind
171
198
 
@@ -183,7 +210,9 @@ A negative `startIndex` reads relative to the stream's current tail. For example
183
210
  curl "http://127.0.0.1:2000/eve/v1/session/<sessionId>/stream?startIndex=-1"
184
211
  ```
185
212
 
186
- This gives a consumer that only persisted `sessionId` a lightweight way to recover the current `continuationToken`. Because a tail-relative position does not resolve to an absolute consumed-event count, client tail reads do not automatically reconnect or advance the stored cursor.
213
+ Because a tail-relative position does not resolve to an absolute consumed-event
214
+ count, client tail reads do not automatically reconnect or advance the stored
215
+ cursor.
187
216
 
188
217
  For a catch-up read that stops instead of following the live stream, pass `includeTailIndex=1`. The response then carries the `x-eve-stream-tail-index` header: the zero-based index of the last durably recorded event, or `-1` before the first. Read from your cursor until it passes that tail, then disconnect — reconnecting from the updated cursor if the connection drops first:
189
218
 
@@ -198,7 +227,7 @@ The lookup is opt-in; requests without the parameter get no header. The TypeScri
198
227
 
199
228
  For scripts, server-to-server calls, tests, evals, and custom UIs, `eve/client` wraps these routes in a typed client so you don't hand-roll the POST and NDJSON stream loop.
200
229
 
201
- Start with the [TypeScript SDK](../guides/client/overview) guide. It covers basic usage, sending messages, continuations, streaming, and per-turn `outputSchema` results.
230
+ Start with the [TypeScript SDK](../guides/client/overview) guide. It covers basic usage, sending messages, session state, streaming, and per-turn `outputSchema` results.
202
231
 
203
232
  ## Inspect the agent over HTTP
204
233
 
@@ -224,6 +253,6 @@ The order is structural, not incidental. By the time a resolver or hook reads ch
224
253
  ## What to read next
225
254
 
226
255
  - [Execution model & durability](./execution-model-and-durability): what makes a session durable and how parked work resumes.
227
- - [Channels](../channels/overview): what owns the continuation token and delivery.
256
+ - [Channels](../channels/overview): how platform addresses map to durable sessions.
228
257
  - [TypeScript SDK](../guides/client/overview): call these routes from scripts and server-side code.
229
258
  - [Frontend](../guides/frontend/overview): `useEveAgent` instead of raw routes.
@@ -101,12 +101,12 @@ export default defineEval({
101
101
 
102
102
  `t` drives the primary session; `t.newSession()` returns an independent `EveEvalSession` against the same target, whose events feed the same run-level assertions.
103
103
 
104
- - `t.send(input)` sends a turn and waits for it to settle. It accepts the same input as `ClientSession.send()` (a string or a structured message) and resolves to a turn carrying `.message` and `.expectOk()`.
105
- - `t.start(input)` starts a turn but returns as soon as the server accepts it. The returned live turn exposes `.sessionId`, `.waitForEvent(...)`, `.cancel()`, and `.result()` for coordinating with work that is still running.
104
+ - `t.send(message, options?)` sends a turn and waits for it to settle. It matches `ClientSession.send()` and resolves to a turn carrying `.message` and `.expectOk()`.
105
+ - `t.start(message)` starts a text turn but returns as soon as the server accepts it. The returned live turn exposes `.sessionId`, `.waitForEvent(...)`, `.cancel()`, and `.result()` for coordinating with work that is still running.
106
106
  - `t.cancel()` requests cooperative cancellation of the primary session's active turn. Both `accepted` and `no_active_turn` are successful outcomes.
107
107
  - `t.sendFile(text, path, mediaType?)` attaches a local file as a data URL.
108
108
  - `t.requireInputRequest(filter?)` records a gate, requires exactly one pending request, and returns it. Filters match tool name, action input, prompt, display, and option ids.
109
- - `t.respond(...responses)` answers specific pending input requests and sends them as the next turn.
109
+ - `t.respond(responses, options?)` answers specific pending input requests and sends them as the next turn.
110
110
  - `t.respondAll(optionId)` answers every pending input request with the same option and sends the responses as the next turn.
111
111
  - `t.reply` is the last assistant message (or `null`); `t.sessionId` is the current session id; `t.events` is the full typed event stream captured so far.
112
112
 
@@ -24,7 +24,7 @@ export default defineEval({
24
24
 
25
25
  - `t.target.fetch(path, init)` performs an authenticated fetch against the target, useful for channel and webhook ingress. See [Authentication](#authentication) for how the runner authenticates.
26
26
  - `t.target.dispatchSchedule(id)` triggers a [schedule](../schedules) through the dev-only schedule route and returns the session ids it created. It works only against a target with dev routes enabled (the local `eve eval` dev server, or a deployment running in development mode), and throws otherwise.
27
- - `t.target.attachSession(sessionId, { startIndex? })` consumes one turn from a session created outside the eval, by a channel or a schedule, so its events feed the run-level assertions. `startIndex` skips events before that position, so a session already partway through its stream resumes from where you left off rather than replaying from the start. When the consumed turn parks (`session.waiting`), the attached session recovers the current continuation token from the stream, so `session.send(...)` and `session.respond(...)` continue the same durable session.
27
+ - `t.target.attachSession(sessionId, { startIndex? })` consumes one turn from a session created outside the eval, by a channel or a schedule, so its events feed the run-level assertions. `startIndex` skips events before that position, so a session already partway through its stream resumes from where you left off rather than replaying from the start. The attached session stays bound to that exact ID, so `session.send(...)` and `session.respond(...)` continue it after the turn parks (`session.waiting`).
28
28
  - `t.target.watchTurn(sessionId, { startIndex? })` starts consuming an externally-created turn immediately and returns a live-turn handle. Use `waitForEvent(...)` to coordinate with mid-turn work, `cancel()` to request cancellation, and `result()` to consume through the boundary. The live turn's `.session` is the attached `EveEvalSession` for follow-up sends after settlement.
29
29
 
30
30
  Sessions attached this way are full `EveEvalSession`s: you can keep driving them and assert directly on that session (`session.succeeded()`, `session.calledTool(...)`). Aggregate assertions on `t` continue to read the whole run, including every attached session.
@@ -16,6 +16,7 @@ The route-auth policy lives on the HTTP channel factory (`agent/channels/eve.ts`
16
16
 
17
17
  - `POST /eve/v1/session`
18
18
  - `POST /eve/v1/session/:sessionId`
19
+ - `POST /eve/v1/session/:sessionId/{cancel,compact,clear,reset}`
19
20
  - `GET /eve/v1/session/:sessionId/stream`
20
21
 
21
22
  These routes are protected by the channel's auth policy. eve fails closed by default: production traffic is rejected unless you configure an authenticator that accepts it, and anonymous access requires an explicit `none()`.
@@ -181,7 +182,7 @@ import { createUnauthorizedResponse } from "eve/channels/auth";
181
182
 
182
183
  export default defineChannel({
183
184
  routes: [
184
- POST("/message", async (req, { send }) => {
185
+ POST("/message", async (req) => {
185
186
  if (!isAllowed(req)) {
186
187
  return createUnauthorizedResponse({
187
188
  status: 403, // defaults to 401; code defaults to "forbidden" / "unauthorized"