eve 0.24.3 → 0.24.5

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 (214) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/src/channel/adapter.d.ts +4 -2
  3. package/dist/src/channel/adapter.js +1 -1
  4. package/dist/src/channel/session.d.ts +5 -1
  5. package/dist/src/channel/types.d.ts +20 -6
  6. package/dist/src/chunks/{use-eve-agent-dEGV09g_.js → use-eve-agent-8rerxDHY.js} +74 -10
  7. package/dist/src/chunks/{use-eve-agent-CFBTHlPx.js → use-eve-agent-DhgdHzDG.js} +74 -10
  8. package/dist/src/cli/commands/build.d.ts +14 -0
  9. package/dist/src/cli/commands/build.js +1 -0
  10. package/dist/src/cli/commands/channels.js +1 -1
  11. package/dist/src/cli/commands/link.d.ts +6 -5
  12. package/dist/src/cli/commands/link.js +1 -1
  13. package/dist/src/cli/dev/tui/runner.d.ts +2 -2
  14. package/dist/src/cli/dev/tui/runner.js +1 -1
  15. package/dist/src/cli/run.d.ts +3 -2
  16. package/dist/src/cli/run.js +1 -1
  17. package/dist/src/client/index.d.ts +2 -2
  18. package/dist/src/client/message-reducer.js +1 -1
  19. package/dist/src/client/ndjson.js +1 -1
  20. package/dist/src/client/open-stream.d.ts +3 -2
  21. package/dist/src/client/open-stream.js +1 -1
  22. package/dist/src/client/session-utils.js +1 -1
  23. package/dist/src/client/session.d.ts +19 -5
  24. package/dist/src/client/session.js +1 -1
  25. package/dist/src/client/types.d.ts +11 -2
  26. package/dist/src/compiled/.vendor-stamp.json +5 -5
  27. package/dist/src/compiled/@workflow/core/index.js +2 -2
  28. package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +55 -0
  29. package/dist/src/compiled/@workflow/core/runtime/run-id-time.d.ts +9 -0
  30. package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +2 -0
  31. package/dist/src/compiled/@workflow/core/runtime/step-latency.d.ts +70 -4
  32. package/dist/src/compiled/@workflow/core/runtime/suspension-handler.d.ts +10 -1
  33. package/dist/src/compiled/@workflow/core/runtime.js +3 -3
  34. package/dist/src/compiled/@workflow/core/step/context-storage.d.ts +6 -0
  35. package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +25 -0
  36. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  37. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  38. package/dist/src/compiled/@workflow/errors/index.d.ts +16 -0
  39. package/dist/src/compiled/@workflow/errors/index.js +1 -1
  40. package/dist/src/compiled/@workflow/world/attributes.d.ts +7 -0
  41. package/dist/src/compiled/@workflow/world/events.d.ts +16 -0
  42. package/dist/src/compiled/@workflow/world/index.d.ts +1 -1
  43. package/dist/src/compiled/@workflow/world-local/index.js +3 -3
  44. package/dist/src/compiled/@workflow/world-vercel/index.js +16 -16
  45. package/dist/src/compiled/_chunks/workflow/attribute-changes-DXbmITuI.js +20 -0
  46. package/dist/src/compiled/_chunks/workflow/{dist-DpDDcpTl.js → dist-BYo8Gno2.js} +1 -1
  47. package/dist/src/compiled/_chunks/workflow/{dist-Blxnyb7-.js → dist-CSfKNxQW.js} +1 -1
  48. package/dist/src/compiled/_chunks/workflow/resume-hook-DvvgYsRt.js +1 -0
  49. package/dist/src/compiled/_chunks/workflow/run-BdvQmV5a.js +1 -0
  50. package/dist/src/compiled/_chunks/workflow/run-id-BdE0MZz9.js +1 -0
  51. package/dist/src/compiled/_chunks/workflow/sleep-DzxrwWTs.js +1 -0
  52. package/dist/src/discover/filesystem.js +1 -1
  53. package/dist/src/evals/assertions/run.d.ts +3 -3
  54. package/dist/src/evals/context.js +1 -1
  55. package/dist/src/evals/index.d.ts +2 -1
  56. package/dist/src/evals/match.d.ts +4 -0
  57. package/dist/src/evals/match.js +1 -1
  58. package/dist/src/evals/runner/derive-run-facts.js +1 -1
  59. package/dist/src/evals/session.d.ts +10 -2
  60. package/dist/src/evals/session.js +1 -1
  61. package/dist/src/evals/target.js +1 -1
  62. package/dist/src/evals/types.d.ts +52 -2
  63. package/dist/src/execution/cancel-descendant-turns-step.d.ts +6 -0
  64. package/dist/src/execution/cancel-descendant-turns-step.js +1 -0
  65. package/dist/src/execution/create-session-step.js +1 -1
  66. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  67. package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -1
  68. package/dist/src/execution/durable-session-migrations/turn-workflow.d.ts +1 -0
  69. package/dist/src/execution/durable-session-migrations/turn-workflow.js +1 -1
  70. package/dist/src/execution/next-driver-action.d.ts +7 -0
  71. package/dist/src/execution/node-step.js +1 -1
  72. package/dist/src/execution/remote-agent-dispatch.d.ts +6 -0
  73. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  74. package/dist/src/execution/settle-cancelled-turn-step.d.ts +16 -0
  75. package/dist/src/execution/settle-cancelled-turn-step.js +1 -0
  76. package/dist/src/execution/subagent-event-proxy-step.js +1 -1
  77. package/dist/src/execution/subagent-hitl-proxy.js +1 -1
  78. package/dist/src/execution/terminal-session-failure-step.d.ts +6 -0
  79. package/dist/src/execution/terminal-session-failure-step.js +1 -0
  80. package/dist/src/execution/turn-cancellation-control.d.ts +27 -0
  81. package/dist/src/execution/turn-cancellation-control.js +1 -0
  82. package/dist/src/execution/turn-cancellation-token.d.ts +9 -0
  83. package/dist/src/execution/turn-cancellation-token.js +1 -0
  84. package/dist/src/execution/turn-dispatch.d.ts +14 -1
  85. package/dist/src/execution/turn-dispatch.js +1 -1
  86. package/dist/src/execution/turn-execution-cursor.d.ts +2 -1
  87. package/dist/src/execution/turn-execution-cursor.js +1 -1
  88. package/dist/src/execution/turn-workflow.d.ts +9 -1
  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.d.ts +3 -1
  92. package/dist/src/execution/workflow-runtime.js +1 -1
  93. package/dist/src/execution/workflow-steps.d.ts +8 -6
  94. package/dist/src/execution/workflow-steps.js +1 -1
  95. package/dist/src/harness/active-turn-id.d.ts +11 -0
  96. package/dist/src/harness/active-turn-id.js +1 -0
  97. package/dist/src/harness/advertised-tools.js +1 -1
  98. package/dist/src/harness/cancelled-turn-emission.d.ts +11 -0
  99. package/dist/src/harness/cancelled-turn-emission.js +1 -0
  100. package/dist/src/harness/emission.d.ts +4 -2
  101. package/dist/src/harness/emission.js +1 -1
  102. package/dist/src/harness/execute-tool.d.ts +0 -1
  103. package/dist/src/harness/proxy-input-requests.d.ts +5 -0
  104. package/dist/src/harness/proxy-input-requests.js +1 -1
  105. package/dist/src/harness/runtime-actions.d.ts +16 -12
  106. package/dist/src/harness/runtime-actions.js +1 -1
  107. package/dist/src/harness/session-limit-enforcement.js +1 -1
  108. package/dist/src/harness/tool-loop.js +2 -2
  109. package/dist/src/internal/application/build-profile.d.ts +64 -0
  110. package/dist/src/internal/application/build-profile.js +1 -0
  111. package/dist/src/internal/application/compiled-artifacts.js +3 -2
  112. package/dist/src/internal/application/package.js +1 -1
  113. package/dist/src/internal/authored-module-loader.d.ts +10 -0
  114. package/dist/src/internal/authored-module-loader.js +3 -3
  115. package/dist/src/internal/authored-module-map-loader.js +1 -1
  116. package/dist/src/internal/bundler/nitro-rolldown.d.ts +18 -2
  117. package/dist/src/internal/bundler/nitro-rolldown.js +1 -1
  118. package/dist/src/internal/materialized-authored-modules.d.ts +2 -4
  119. package/dist/src/internal/materialized-authored-modules.js +1 -1
  120. package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
  121. package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
  122. package/dist/src/internal/nitro/host/build-application.js +1 -1
  123. package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
  124. package/dist/src/internal/nitro/host/types.d.ts +2 -0
  125. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
  126. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +7 -1
  127. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
  128. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  129. package/dist/src/internal/nitro/routes/channel-route-context.d.ts +3 -0
  130. package/dist/src/internal/nitro/routes/channel-route-context.js +1 -1
  131. package/dist/src/internal/nitro/routes/runtime-stack.js +1 -1
  132. package/dist/src/internal/nitro/routes/schedule-task.js +1 -1
  133. package/dist/src/internal/workflow/development-world-client.js +1 -1
  134. package/dist/src/internal/workflow/development-world-server.js +1 -1
  135. package/dist/src/internal/workflow/local-world-data-directory.d.ts +2 -0
  136. package/dist/src/internal/workflow/local-world-data-directory.js +1 -0
  137. package/dist/src/internal/workflow-bundle/builder-support.js +3 -3
  138. package/dist/src/internal/workflow-bundle/builder.js +2 -2
  139. package/dist/src/internal/workflow-bundle/vercel-workflow-output.js +1 -1
  140. package/dist/src/protocol/cancel-turn.d.ts +11 -0
  141. package/dist/src/protocol/cancel-turn.js +1 -0
  142. package/dist/src/protocol/message.d.ts +23 -3
  143. package/dist/src/protocol/message.js +2 -2
  144. package/dist/src/protocol/routes.d.ts +10 -0
  145. package/dist/src/protocol/routes.js +1 -1
  146. package/dist/src/public/channels/discord/discordChannel.d.ts +1 -0
  147. package/dist/src/public/channels/eve.d.ts +2 -1
  148. package/dist/src/public/channels/eve.js +2 -2
  149. package/dist/src/public/channels/github/githubChannel.d.ts +1 -0
  150. package/dist/src/public/channels/linear/api.d.ts +0 -1
  151. package/dist/src/public/channels/linear/api.js +17 -22
  152. package/dist/src/public/channels/linear/linearChannel.d.ts +1 -0
  153. package/dist/src/public/channels/linear/linearChannel.js +1 -1
  154. package/dist/src/public/channels/slack/slackChannel.d.ts +1 -0
  155. package/dist/src/public/channels/teams/teamsChannel.d.ts +1 -0
  156. package/dist/src/public/channels/telegram/telegramChannel.d.ts +1 -0
  157. package/dist/src/public/channels/twilio/twilioChannel.d.ts +1 -0
  158. package/dist/src/public/definitions/channel.d.ts +25 -14
  159. package/dist/src/public/definitions/channel.js +1 -1
  160. package/dist/src/public/next/index.js +1 -1
  161. package/dist/src/public/next/resolve-eve-binary.d.ts +12 -0
  162. package/dist/src/public/next/resolve-eve-binary.js +1 -0
  163. package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
  164. package/dist/src/runtime/framework-tools/agent.d.ts +13 -0
  165. package/dist/src/runtime/framework-tools/agent.js +1 -0
  166. package/dist/src/runtime/framework-tools/index.d.ts +7 -2
  167. package/dist/src/runtime/framework-tools/index.js +1 -1
  168. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  169. package/dist/src/runtime/types.d.ts +2 -1
  170. package/dist/src/services/dev-client/runtime-artifacts.d.ts +2 -2
  171. package/dist/src/services/dev-client.d.ts +10 -18
  172. package/dist/src/services/dev-client.js +1 -1
  173. package/dist/src/setup/boxes/reconcile-host-framework-preset.d.ts +26 -0
  174. package/dist/src/setup/boxes/reconcile-host-framework-preset.js +1 -0
  175. package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
  176. package/dist/src/setup/index.js +1 -1
  177. package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
  178. package/dist/src/setup/scaffold/create/extension.js +0 -1
  179. package/dist/src/setup/scaffold/create/project.js +2 -4
  180. package/dist/src/setup/scaffold/index.d.ts +1 -1
  181. package/dist/src/setup/scaffold/index.js +1 -1
  182. package/dist/src/setup/scaffold/update/channels.d.ts +7 -1
  183. package/dist/src/setup/scaffold/update/channels.js +2 -2
  184. package/dist/src/setup/scaffold/update/connections.js +3 -3
  185. package/dist/src/setup/vercel-project-framework.d.ts +12 -0
  186. package/dist/src/setup/vercel-project-framework.js +1 -1
  187. package/dist/src/shared/continuation-token.d.ts +2 -0
  188. package/dist/src/shared/continuation-token.js +1 -0
  189. package/dist/src/svelte/index.js +1 -1
  190. package/dist/src/svelte/use-eve-agent.js +1 -1
  191. package/dist/src/vue/index.js +1 -1
  192. package/dist/src/vue/use-eve-agent.js +1 -1
  193. package/docs/channels/eve.mdx +11 -1
  194. package/docs/concepts/default-harness.md +2 -0
  195. package/docs/concepts/execution-model-and-durability.md +1 -1
  196. package/docs/concepts/sessions-runs-and-streaming.md +24 -4
  197. package/docs/evals/assertions.mdx +2 -2
  198. package/docs/evals/cases.mdx +31 -0
  199. package/docs/evals/overview.mdx +1 -1
  200. package/docs/evals/targets.mdx +2 -1
  201. package/docs/guides/client/continuations.mdx +16 -1
  202. package/docs/guides/client/streaming.mdx +31 -2
  203. package/docs/guides/deployment.md +1 -1
  204. package/docs/guides/frontend/overview.mdx +4 -2
  205. package/docs/guides/frontend/use-eve-agent-svelte.mdx +2 -2
  206. package/docs/guides/frontend/use-eve-agent-vue.mdx +2 -2
  207. package/docs/guides/remote-agents.md +2 -0
  208. package/docs/reference/cli.md +16 -3
  209. package/docs/subagents.mdx +10 -0
  210. package/package.json +6 -6
  211. package/dist/src/compiled/_chunks/workflow/attribute-changes-MGTOG_uX.js +0 -20
  212. package/dist/src/compiled/_chunks/workflow/resume-hook-DHP5ql3-.js +0 -1
  213. package/dist/src/compiled/_chunks/workflow/run-D8hv1ptT.js +0 -1
  214. package/dist/src/compiled/_chunks/workflow/sleep-uA9pS-PT.js +0 -1
@@ -102,6 +102,8 @@ export default defineEval({
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
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.
106
+ - `t.cancel()` requests cooperative cancellation of the primary session's active turn. Both `accepted` and `no_active_turn` are successful outcomes.
105
107
  - `t.sendFile(text, path, mediaType?)` attaches a local file as a data URL.
106
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.
107
109
  - `t.respond(...responses)` answers specific pending input requests and sends them as the next turn.
@@ -110,6 +112,35 @@ export default defineEval({
110
112
 
111
113
  Each `send` (and `respond`/`respondAll`) resolves to an immutable turn with `.message`, `.data`, `.events`, `.inputRequests`, `.toolCalls`, `.sessionId`, `.status`, and `.expectOk()`. Use `.sessionId` to relate turns or attach follow-up work to the session that produced a specific turn. `expectOk()` throws only when the turn ended failed; a session left open for a next message is the normal end state of a successful turn.
112
114
 
115
+ ## In-flight turns
116
+
117
+ Use `start()` when the eval must observe or affect a turn before it settles. A live turn owns one stream consumer: `waitForEvent()` reads typed events from its buffer, and `result()` waits for the boundary and records the same buffered stream as an immutable turn. Event data matchers use the same partial-deep matcher language as `t.event(...)`.
118
+
119
+ ```ts title="evals/cancel-running-tool.eval.ts"
120
+ import { defineEval } from "eve/evals";
121
+
122
+ export default defineEval({
123
+ async test(t) {
124
+ const live = await t.start("Run the long operation.");
125
+
126
+ await live.waitForEvent("actions.requested", {
127
+ data: {
128
+ actions: (actions) =>
129
+ actions.some(
130
+ (action) => action.kind === "tool-call" && action.toolName === "long_operation",
131
+ ),
132
+ },
133
+ });
134
+
135
+ await live.cancel();
136
+ const turn = await live.result();
137
+ turn.eventOrder([{ type: "turn.cancelled" }, { type: "session.waiting" }]);
138
+ },
139
+ });
140
+ ```
141
+
142
+ `waitForEvent()` rejects if the stream fails or reaches its turn boundary before the requested event. Call `result()` after any coordination to settle the stream and make its events available to run-level assertions.
143
+
113
144
  Use `expectOk()` only when the next operation depends on that intermediate turn succeeding. A final `t.succeeded()` already records a complete-run gate.
114
145
 
115
146
  To intentionally omit an eval for the current target, call `t.skip(reason)` before sending messages or recording assertions. Skipped evals are reported separately and do not affect the exit code.
@@ -100,7 +100,7 @@ model: mockModel({
100
100
 
101
101
  `t` is both the driver and the assertion surface. There are no separate `input`, `run`, `checks`, or `scores` fields. You write ordinary control flow, sending turns and asserting inline.
102
102
 
103
- - **Drive** the agent: `t.send(...)`, `t.respond(...)`, `t.respondAll(...)`, `t.sendFile(...)`, `t.requireInputRequest(...)`, `t.newSession()`. Read what came back with `t.reply` (the last assistant message), `t.sessionId`, and `t.events`. See [Cases](./cases).
103
+ - **Drive** the agent: `t.send(...)`, `t.start(...)`, `t.cancel()`, `t.respond(...)`, `t.respondAll(...)`, `t.sendFile(...)`, `t.requireInputRequest(...)`, `t.newSession()`. Live turns returned by `start()` can wait for typed mid-turn events before cancellation or settlement. Read what came back with `t.reply` (the last assistant message), `t.sessionId`, and `t.events`. See [Cases](./cases).
104
104
  - **Assert** with three surfaces, covered next.
105
105
 
106
106
  ## Three assertion surfaces
@@ -24,7 +24,8 @@ 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.
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.
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.
28
29
 
29
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.
30
31
 
@@ -23,6 +23,8 @@ await response.result();
23
23
  await saveSessionState(session.state);
24
24
  ```
25
25
 
26
+ As soon as `send()` returns, `session.state.sessionId` identifies the accepted in-flight turn for cancellation or stream reconnection. Consume the response before saving a fully advanced cursor: the continuation token and `streamIndex` update as events reach the turn boundary.
27
+
26
28
  Store the full state object:
27
29
 
28
30
  ```ts
@@ -64,7 +66,7 @@ The shorthand can send a follow-up, but it doesn't know the previous stream curs
64
66
 
65
67
  ## Waiting, completed, and failed sessions
66
68
 
67
- When a turn ends with `session.waiting`, the client preserves the state so the next send continues the conversation.
69
+ When a turn ends with `session.waiting`, the event carries the current channel-owned `data.continuationToken` and the client preserves the state so the next send continues the conversation.
68
70
 
69
71
  When a turn ends with `session.completed` or `session.failed`, the client resets its local state. The next send starts a fresh durable session:
70
72
 
@@ -115,6 +117,19 @@ for await (const event of session.stream()) {
115
117
 
116
118
  `stream()` attaches to an existing run; to send new user input, use `send()`. For overriding the cursor with `startIndex` and the full reconnection model, see [Streaming](./streaming#open-a-stream-manually).
117
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
+ ```
132
+
118
133
  ## What to read next
119
134
 
120
135
  - [Streaming](./streaming): stream events and reconnect by index
@@ -5,6 +5,20 @@ 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 active turn accepted the signal or `no_active_turn` when it already settled:
9
+
10
+ ```ts
11
+ const session = client.session();
12
+ const response = await session.send("Run the long operation.");
13
+
14
+ const cancellation = await session.cancel();
15
+ console.log(cancellation.status);
16
+
17
+ const result = await response.result();
18
+ ```
19
+
20
+ 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
+
8
22
  ## Aggregate a turn
9
23
 
10
24
  Use `result()` when you only need the final turn summary:
@@ -70,7 +84,7 @@ The most common UI events are:
70
84
  | `action.result` | Show tool call results. |
71
85
  | `input.requested` | Pause the UI for approval or a question answer. |
72
86
  | `result.completed` | Read structured output from an [output schema](./output-schema). |
73
- | `session.waiting` | Enable the composer for the next turn. |
87
+ | `session.waiting` | Enable the composer and read the current `data.continuationToken`. |
74
88
  | `session.completed` | Mark the conversation terminal. |
75
89
  | `session.failed` | Mark the conversation failed. |
76
90
 
@@ -124,11 +138,26 @@ for await (const event of session.stream({ startIndex: 0 })) {
124
138
  }
125
139
  ```
126
140
 
141
+ Nonnegative values are absolute event indexes. Negative values read relative to the stream's current tail, so `-1` reads the latest event:
142
+
143
+ ```ts
144
+ for await (const event of session.stream({ startIndex: -1 })) {
145
+ if (event.type === "session.waiting") {
146
+ console.log(event.data.continuationToken);
147
+ }
148
+ break;
149
+ }
150
+ ```
151
+
152
+ Tail-relative attachments do not automatically reconnect or advance the session's stored absolute `streamIndex`. Break after the event you need when using one as a tail lookup.
153
+
127
154
  `stream()` throws if the session has no `sessionId`, because there's no stream to attach to before the first send.
128
155
 
129
156
  ## Abort a request
130
157
 
131
- Pass an `AbortSignal` to cancel the POST or stream. Arm the timeout before awaiting `send()` so it covers the POST as well as the stream:
158
+ Pass an `AbortSignal` to cancel the POST or stream. Aborting is local transport cancellation: turns are resumable across disconnects, so detaching never stops the server-side turn — it keeps running and remains attachable by index. To stop the turn itself, POST the session's [cancel route](../../channels/eve#routes) and watch the stream settle with `turn.cancelled` followed by `session.waiting`.
159
+
160
+ Arm the timeout before awaiting `send()` so it covers the POST as well as the stream:
132
161
 
133
162
  ```ts
134
163
  const controller = new AbortController();
@@ -140,7 +140,7 @@ Eve writes the standard Nitro output under `.output/` instead of Vercel Build Ou
140
140
 
141
141
  Self-deployed agents should make the Vercel-specific choices explicit:
142
142
 
143
- - Let the Workflow SDK use its default local world, which stores workflow state under `.workflow-data`, configure your host so that directory is on persistent storage, or select another world with `experimental.workflow.world` in the root `agent.ts`. When you select a custom world, install a world package built against the same `@workflow/*` line as your eve release (currently the `5.0.0-beta` line). The npm `latest` tag may lag, so pin the version explicitly, for example `pnpm add @workflow/world-postgres@5.0.0-beta.x`. The Workflow SDK rejects worlds with an incompatible runtime protocol during initialization.
143
+ - Let the Workflow SDK use its default local world, which stores workflow state under `.eve/.workflow-data`; configure your host so that directory is on persistent storage, or select another world with `experimental.workflow.world` in the root `agent.ts`. When you select a custom world, install a world package built against the same `@workflow/*` line as your eve release (currently the `5.0.0-beta` line). The npm `latest` tag may lag, so pin the version explicitly, for example `pnpm add @workflow/world-postgres@5.0.0-beta.x`. The Workflow SDK rejects worlds with an incompatible runtime protocol during initialization.
144
144
  - If you put a reverse proxy or ingress in front of eve, forward **both** `/eve/` and `/.well-known/workflow/`. The workflow world delivers run callbacks to `/.well-known/workflow/v1/flow`; a proxy restricted to `/eve/` lets sessions start but silently stalls runs forever, because the callbacks never reach eve.
145
145
  - Install the AI SDK package for your provider, then use a direct provider model object and `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` when you want no Gateway dependency.
146
146
  - Use `AI_GATEWAY_API_KEY` if you still want Gateway routing from a non-Vercel host.
@@ -69,7 +69,7 @@ export function Chat() {
69
69
  | `events` | Raw eve stream events for this session. |
70
70
  | `session` | Serializable session cursor (`sessionId`, `continuationToken`, `streamIndex`). |
71
71
  | `send` | Send text or the full turn payload (multi-part messages, HITL responses). |
72
- | `stop` | Abort the active request. |
72
+ | `stop` | Abort the client's in-flight stream. The server-side turn keeps running. |
73
73
  | `reset` | Clear local events, data, errors, and the local session cursor. |
74
74
 
75
75
  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.
@@ -96,7 +96,9 @@ await agent.send({
96
96
  });
97
97
  ```
98
98
 
99
- 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 active request, and `reset()` to clear local state so the next send starts a fresh durable session.
99
+ 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
+
101
+ `stop()` is local: turns are resumable across disconnects, so detaching the stream never cancels the work — the turn keeps running and billing on the server. To stop the turn itself, POST the session's [cancel route](../../channels/eve#routes); the turn then settles on the stream as `turn.cancelled` followed by `session.waiting`.
100
102
 
101
103
  After eve confirms an attachment turn with `message.received`, the default reducer projects each
102
104
  received attachment as a `file` part on the user message. The part includes `mediaType`, optional
@@ -31,7 +31,7 @@ Import from `eve/svelte` and read the reactive getters directly. No `$` prefix:
31
31
  | `events` | `readonly HandleMessageStreamEvent[]` | Raw server events for this session. |
32
32
  | `session` | `SessionState` | Snapshot of session state. |
33
33
  | `send` | `(input: SendTurnPayload) => Promise<void>` | Send text or a full turn (multi-part, attachments, HITL responses). |
34
- | `stop` | `() => void` | Abort the in-flight request. |
34
+ | `stop` | `() => void` | Abort the client's in-flight stream. |
35
35
  | `reset` | `() => void` | Clear state and start a new session. |
36
36
 
37
37
  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 `$`.
@@ -103,7 +103,7 @@ The find-and-answer flow is identical across frameworks. The [React hook referen
103
103
 
104
104
  ## Stop, reset, and resume
105
105
 
106
- `stop()` aborts the in-flight stream. `reset()` wipes state and starts a fresh session. To resume across reloads, hand `initialSession` the state you saved earlier and use `onSessionChange` to persist the cursor as it advances:
106
+ `stop()` aborts the in-flight stream; the server-side turn keeps running and remains attachable — to stop the turn itself, POST the session's [cancel route](../../channels/eve#routes). `reset()` wipes state and starts a fresh session. To resume across reloads, hand `initialSession` the state you saved earlier and use `onSessionChange` to persist the cursor as it advances:
107
107
 
108
108
  ```ts
109
109
  const agent = useEveAgent({
@@ -33,7 +33,7 @@ const { data } = useEveAgent();
33
33
  | `events` | `ComputedRef<readonly HandleMessageStreamEvent[]>` | Raw server events for this session. |
34
34
  | `session` | `ComputedRef<SessionState>` | Snapshot of session state. |
35
35
  | `send` | `(input: SendTurnPayload) => Promise<void>` | Send text or a full turn (multi-part, attachments, HITL responses). |
36
- | `stop` | `() => void` | Abort the in-flight request. |
36
+ | `stop` | `() => void` | Abort the client's in-flight stream. |
37
37
  | `reset` | `() => void` | Clear state and start a new session. |
38
38
 
39
39
  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>`.
@@ -116,7 +116,7 @@ The find-and-answer flow is the same across every framework. The [React hook ref
116
116
 
117
117
  ## Stop, reset, and resume
118
118
 
119
- `stop()` aborts the in-flight stream. `reset()` wipes state and starts a fresh session. To survive a reload, pass `initialSession` to restore a saved session and `onSessionChange` to persist the cursor as it moves:
119
+ `stop()` aborts the in-flight stream; the server-side turn keeps running and remains attachable — to stop the turn itself, POST the session's [cancel route](../../channels/eve#routes). `reset()` wipes state and starts a fresh session. To survive a reload, pass `initialSession` to restore a saved session and `onSessionChange` to persist the cursor as it moves:
120
120
 
121
121
  ```ts
122
122
  const agent = useEveAgent({
@@ -70,6 +70,8 @@ A local subagent runs inline. A remote one runs in its own deployment, so dispat
70
70
 
71
71
  The parent stream carries the same `subagent.called`, `action.result`, and `subagent.completed` events as local delegation. For a remote call, `subagent.called.data.remote.url` records the target.
72
72
 
73
+ Cancelling the parent while a remote call is active sends an authenticated `POST /eve/v1/session/:childSessionId/cancel` to the remote and waits for that request to be accepted before the parent settles. eve resolves the remote's `headers` and `auth` again for every cancellation attempt, so rotating credentials work the same way as they do for session creation. Cancellation always uses the standard eve cancel path on `url`, even when `path` customizes only the create-session endpoint. The remote child reports `turn.cancelled` → `session.waiting` on its own stream; an older or unreachable remote is logged but cannot turn the parent's cancellation into a failure.
74
+
73
75
  Both failure paths surface to the parent as a failed tool result, so the caller can explain or recover within the same session. A failed _start_ returns the error inline. A remote that starts and then fails posts a terminal failure callback, which the parent receives as an errored subagent result carrying the remote's error (or `REMOTE_AGENT_FAILED` when none is supplied). Terminal callback delivery runs as a durable step on the underlying workflow engine (see [Execution model & durability](../concepts/execution-model-and-durability)). A failed callback POST is rethrown rather than marking the task complete, so the engine retries it.
74
76
 
75
77
  ## What to read next
@@ -90,11 +90,24 @@ Run this first when something behaves unexpectedly. It confirms a file was disco
90
90
  ## `eve build`
91
91
 
92
92
  ```bash
93
- eve build
93
+ eve build [--profile <path>] [--skip-sandbox-prewarm]
94
94
  ```
95
95
 
96
96
  Compiles and bundles in an invocation-owned directory under `.eve/builds/`, then publishes the completed host output and prints its path. Scratch workspaces are removed after success or failure.
97
97
 
98
+ | Flag | Type | Default | Description |
99
+ | ------------------------ | ------ | ------- | --------------------------------------------------------------------------------------------- |
100
+ | `--profile <path>` | string | off | Best-effort versioned JSON report with build-phase timings and final output-size measurements |
101
+ | `--skip-sandbox-prewarm` | flag | off | Skip sandbox template prewarm for a Vercel build; the output might not be deployable |
102
+
103
+ Use a profile file to establish a repeatable baseline before changing the build pipeline:
104
+
105
+ ```bash
106
+ eve build --profile .eve/build-profiles/baseline.json
107
+ ```
108
+
109
+ The report is attempted only after a successful build. It records total elapsed time, completed phase timings, and final regular-file totals for file count, raw bytes, and the sum of each file compressed with gzip. For Vercel output it also includes a subtotal for every real `.func` directory, so app and flow bundles can be compared separately. The profile path resolves from the app root and should be outside the published output directory; profile collection does not add a file to the deployment. If collection or writing fails, eve emits a warning but keeps the completed build successful.
110
+
98
111
  Production builds do not write through the stable compiler, host, Nitro, or Workflow files owned by `eve dev`, so builds can run while a local dev server is active. A failed build leaves the last successful `.output/` and agent summary untouched. Concurrent completed builds serialize only the final publication window.
99
112
 
100
113
  Useful stable artifacts written by inspection and development flows under `.eve/` include:
@@ -158,7 +171,7 @@ For bearer tokens or custom schemes, pass explicit headers with `-H`.
158
171
 
159
172
  Local dev records the last ready URL per resolved app root in `.eve/dev-server-state.v1.json`. A second interactive `eve dev` reconnects only when that URL is loopback and healthy; each terminal UI creates a fresh client session while sharing the server process. A stale or malformed record is replaced when eve starts a new server. Passing `--host`, `--port`, or a `PORT` environment value skips reconnection and reports a healthy recorded server instead.
160
173
 
161
- Local dev keeps immutable runtime source snapshots under `.eve/dev-runtime/snapshots/` so in-flight turns hold a consistent code revision while new turns pick up rebuilds. After a generation is superseded, `eve dev` retains it for at least 30 minutes and also retains the five most recently superseded generations, regardless of the configured Workflow World. The active generation is never pruned. Old runtime snapshots and local sandbox templates are pruned in the background. For manual cleanup, stop `eve dev` before deleting `.eve/dev-runtime/snapshots/` or `.eve/sandbox-cache/local/templates/`. A turn that remains unfinished beyond the automatic retention window can no longer resume after its generation is pruned.
174
+ Local dev keeps immutable runtime source snapshots under `.eve/dev-runtime/snapshots/` so in-flight turns hold a consistent code revision while new turns pick up rebuilds. The terminal REPL keeps its logical session across successful rebuilds, so the next turn continues the conversation on the latest generation; use `/new` to start a fresh session. After a generation is superseded, `eve dev` retains it for at least 30 minutes and also retains the five most recently superseded generations, regardless of the configured Workflow World. The active generation is never pruned. Old runtime snapshots and local sandbox templates are pruned in the background. For manual cleanup, stop `eve dev` before deleting `.eve/dev-runtime/snapshots/` or `.eve/sandbox-cache/local/templates/`. A turn that remains unfinished beyond the automatic retention window can no longer resume after its generation is pruned.
162
175
 
163
176
  ## `eve link`
164
177
 
@@ -166,7 +179,7 @@ Local dev keeps immutable runtime source snapshots under `.eve/dev-runtime/snaps
166
179
  eve link
167
180
  ```
168
181
 
169
- Links the current directory to an existing Vercel project. You select a team and then one of its recent projects; type a project name and choose **Search for '<name>'** to search the rest of that team's projects. Vercel links the selected project, eve verifies its project ID, and then pulls the project's environment so an AI Gateway credential (`VERCEL_OIDC_TOKEN` or `AI_GATEWAY_API_KEY`) lands in `.env.local`. Running it again re-links: the pickers always run, and the new choice wins. The command is interactive only; in CI, use `vercel link --project <name> --yes --non-interactive` instead. A running `eve dev` reloads env files automatically, so you don't need to restart after the pull.
182
+ Links the current directory to a Vercel project. After selecting a team, you can create a project named for the agent or link an existing project. The existing-project picker shows recent projects; type a project name and choose **Search for '<name>'** to search the rest of that team's projects. Vercel links the resolved project, eve verifies its project ID, and then pulls the project's environment so an AI Gateway credential (`VERCEL_OIDC_TOKEN` or `AI_GATEWAY_API_KEY`) lands in `.env.local`. Running it again re-links: the pickers always run, and the new choice wins. The command is interactive only; in CI, use `vercel link --project <name> --yes --non-interactive` instead. A running `eve dev` reloads env files automatically, so you don't need to restart after the pull.
170
183
 
171
184
  ## `eve deploy`
172
185
 
@@ -22,6 +22,14 @@ The copy uses the root's instructions, connections, auth, and sandbox. It receiv
22
22
 
23
23
  The parent transfers data to the child through the `message` input it gives the subagent. Do not include sensitive data in a subagent request unless that child and its inherited tools, connections, sandbox, and telemetry path are appropriate for that data.
24
24
 
25
+ To prevent the root session from delegating to a fresh copy of itself, disable `agent` the same way as any other built-in tool:
26
+
27
+ ```ts title="agent/tools/agent.ts"
28
+ import { disableTool } from "eve/tools";
29
+
30
+ export default disableTool();
31
+ ```
32
+
25
33
  An authored root tool at `agent/tools/agent.ts` takes priority over the built-in.
26
34
 
27
35
  ## Declared subagents
@@ -98,6 +106,8 @@ Do not rely on subagent delegation by itself as an approval boundary. Put sensit
98
106
 
99
107
  Each delegated subagent spins up its own child session and stream. The parent stream carries the control-plane events `subagent.called` and `subagent.completed`, plus interactive `input.requested`, `authorization.required`, and `authorization.completed` events proxied from descendants so the root channel can prompt the user. To follow the child's other progress, read `subagent.called.data.childSessionId` and subscribe at `GET /eve/v1/session/:childSessionId/stream`.
100
108
 
109
+ Cancelling a parent turn also requests cancellation of every active child it started, recursively through nested and remote subagents. Each affected session emits its own `turn.cancelled` → `session.waiting` boundary; the cancelled parent does not synthesize tool results or emit `subagent.completed`. A child that already completed or parked has no active turn and is a benign no-op.
110
+
101
111
  Subagent model calls automatically retry classified transient provider failures, including overload errors delivered after a stream starts. eve makes at most three fresh model-call attempts, repeating only the current uncommitted call so completed earlier steps, tool results, and sandbox work remain available to the child. Other recoverable task errors fall back to Workflow's durable step retry from the last committed session snapshot. Exhausting the transient model-call attempts or the dedicated empty-response reissue returns one failed task result instead of stacking both retry budgets; terminal errors fail immediately.
102
112
 
103
113
  ## When to split
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.24.3",
3
+ "version": "0.24.5",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [
@@ -303,13 +303,13 @@
303
303
  "@vercel/oidc": "3.5.0",
304
304
  "@vercel/sandbox": "2.3.0",
305
305
  "@vercel/sdk": "1.28.1",
306
- "@workflow/core": "5.0.0-beta.34",
307
- "@workflow/errors": "5.0.0-beta.10",
306
+ "@workflow/core": "5.0.0-beta.35",
307
+ "@workflow/errors": "5.0.0-beta.11",
308
308
  "@workflow/serde": "5.0.0-beta.2",
309
309
  "@workflow/utils": "5.0.0-beta.6",
310
- "@workflow/world": "5.0.0-beta.20",
311
- "@workflow/world-local": "5.0.0-beta.28",
312
- "@workflow/world-vercel": "5.0.0-beta.30",
310
+ "@workflow/world": "5.0.0-beta.21",
311
+ "@workflow/world-local": "5.0.0-beta.29",
312
+ "@workflow/world-vercel": "5.0.0-beta.31",
313
313
  "ai": "^7.0.26",
314
314
  "autoevals": "0.0.132",
315
315
  "chat": "4.31.0",