eve 0.70.1 → 0.70.3

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 (189) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/src/channel/adapter.js +1 -1
  3. package/dist/src/channel/channel-operations.js +1 -1
  4. package/dist/src/channel/resolve-text.d.ts +8 -0
  5. package/dist/src/channel/resolve-text.js +2 -1
  6. package/dist/src/chunks/{use-eve-agent-CJQeE7-t.js → use-eve-agent-CFCaYnrI.js} +1 -1
  7. package/dist/src/chunks/{use-eve-agent-DdemtY6C.js → use-eve-agent-DcDhXNv1.js} +1 -1
  8. package/dist/src/cli/banner.d.ts +2 -2
  9. package/dist/src/cli/banner.js +1 -1
  10. package/dist/src/cli/commands/init-agent-workspace.js +1 -1
  11. package/dist/src/cli/commands/init.js +1 -1
  12. package/dist/src/cli/dev/tui/runner.d.ts +2 -1
  13. package/dist/src/cli/dev/tui/runner.js +1 -1
  14. package/dist/src/cli/dev/tui/terminal-renderer.js +2 -2
  15. package/dist/src/cli/dev/tui/test/mock-terminal.d.ts +7 -1
  16. package/dist/src/cli/dev/tui/test/mock-terminal.js +4 -3
  17. package/dist/src/cli/dev/tui/theme.d.ts +1 -1
  18. package/dist/src/cli/dev/tui/theme.js +1 -1
  19. package/dist/src/cli/dev/tui/tool-presentation.d.ts +15 -2
  20. package/dist/src/cli/dev/tui/tool-presentation.js +1 -1
  21. package/dist/src/cli/dev/tui/transcript-parts.js +1 -1
  22. package/dist/src/client/ndjson.js +1 -1
  23. package/dist/src/compiled/.vendor-stamp.json +7 -7
  24. package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.js +1 -1
  25. package/dist/src/compiled/@vercel/sandbox/index.js +1 -1
  26. package/dist/src/compiled/@workflow/core/index.js +2 -2
  27. package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +15 -0
  28. package/dist/src/compiled/@workflow/core/runtime/dynamic-workflow.d.ts +182 -0
  29. package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +7 -0
  30. package/dist/src/compiled/@workflow/core/runtime/helpers.js +1 -1
  31. package/dist/src/compiled/@workflow/core/runtime/quickjs-assets.generated.d.ts +7 -0
  32. package/dist/src/compiled/@workflow/core/runtime/quickjs-entrypoint.d.ts +2 -30
  33. package/dist/src/compiled/@workflow/core/runtime/quickjs-log-view.d.ts +27 -4
  34. package/dist/src/compiled/@workflow/core/runtime/quickjs-runtime.d.ts +55 -3
  35. package/dist/src/compiled/@workflow/core/runtime/quickjs-snapshot-codec.d.ts +74 -0
  36. package/dist/src/compiled/@workflow/core/runtime/start.d.ts +4 -0
  37. package/dist/src/compiled/@workflow/core/runtime/vm-mode.d.ts +44 -0
  38. package/dist/src/compiled/@workflow/core/runtime.d.ts +1 -1
  39. package/dist/src/compiled/@workflow/core/runtime.js +4 -4
  40. package/dist/src/compiled/@workflow/core/schemas.d.ts +1 -1
  41. package/dist/src/compiled/@workflow/core/serialization/compression.d.ts +27 -2
  42. package/dist/src/compiled/@workflow/core/serialization/hardened.d.ts +8 -0
  43. package/dist/src/compiled/@workflow/core/serialization/types.d.ts +1 -0
  44. package/dist/src/compiled/@workflow/core/serialization.d.ts +48 -0
  45. package/dist/src/compiled/@workflow/core/serialization.js +1 -1
  46. package/dist/src/compiled/@workflow/core/set-error-stack.d.ts +12 -0
  47. package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +47 -0
  48. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  49. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  50. package/dist/src/compiled/@workflow/world/events.d.ts +10 -0
  51. package/dist/src/compiled/@workflow/world/index.d.ts +2 -0
  52. package/dist/src/compiled/@workflow/world/interfaces.d.ts +127 -0
  53. package/dist/src/compiled/@workflow/world/queue.d.ts +6 -0
  54. package/dist/src/compiled/@workflow/world/runs.d.ts +9 -2
  55. package/dist/src/compiled/@workflow/world/snapshots.d.ts +60 -0
  56. package/dist/src/compiled/@workflow/world-local/index.js +5 -5
  57. package/dist/src/compiled/@workflow/world-vercel/index.js +19 -17
  58. package/dist/src/compiled/_chunks/node/undici-B61sz6UT.js +95 -0
  59. package/dist/src/compiled/_chunks/workflow/{attribute-changes-D721NpZv.js → attribute-changes-VaTKT4K8.js} +3 -3
  60. package/dist/src/compiled/_chunks/workflow/dist-B7NC1c9-.js +1 -0
  61. package/dist/src/compiled/_chunks/workflow/{functions-DpZiBxgQ.js → functions-CKkqf9V6.js} +1 -1
  62. package/dist/src/compiled/_chunks/workflow/helpers-CP9TjeO8.js +1 -0
  63. package/dist/src/compiled/_chunks/workflow/{logger-D4GJNTk4.js → logger-oqfblE3p.js} +2 -2
  64. package/dist/src/compiled/_chunks/workflow/resume-hook-yq-NAdBu.js +1 -0
  65. package/dist/src/compiled/_chunks/workflow/run-DYKeqbob.js +32 -0
  66. package/dist/src/compiled/_chunks/workflow/serialization-APSKphN5.js +3 -0
  67. package/dist/src/compiled/_chunks/workflow/signal-exit-iIdjQcCK.js +95 -0
  68. package/dist/src/compiled/_chunks/workflow/sleep-Ba8SExMt.js +1 -0
  69. package/dist/src/compiled/_chunks/workflow/{token-BhlnqoHM.js → token-BKeK6DmC.js} +1 -1
  70. package/dist/src/compiled/_chunks/workflow/token-Cv2GYj9A.js +1 -0
  71. package/dist/src/compiled/_chunks/workflow/{token-util-DaeRTzDa.js → token-util-CddTZ_ef.js} +1 -1
  72. package/dist/src/compiled/_chunks/workflow/{wait-until-3_1djUuL.js → wait-until-Dc9s3yyP.js} +1 -1
  73. package/dist/src/compiled/_chunks/workflow/{wrapper-CzrF_dmI.js → wrapper-Dq4OeGmJ.js} +4 -4
  74. package/dist/src/compiled/shadcn-registry/index.js +4 -4
  75. package/dist/src/context/serialize.js +1 -1
  76. package/dist/src/discover/discover-agent.js +1 -1
  77. package/dist/src/discover/extension-specifier.d.ts +1 -0
  78. package/dist/src/discover/extension-specifier.js +1 -1
  79. package/dist/src/discover/extensions.d.ts +1 -1
  80. package/dist/src/discover/extensions.js +1 -1
  81. package/dist/src/discover/project-source.d.ts +5 -0
  82. package/dist/src/discover/project-source.js +1 -1
  83. package/dist/src/evals/session.d.ts +1 -0
  84. package/dist/src/evals/session.js +1 -1
  85. package/dist/src/evals/types.d.ts +6 -0
  86. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  87. package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
  88. package/dist/src/execution/proxied-deliver-step.d.ts +11 -0
  89. package/dist/src/execution/proxied-deliver-step.js +1 -1
  90. package/dist/src/execution/sandbox/read-file.d.ts +8 -1
  91. package/dist/src/execution/sandbox/read-file.js +3 -3
  92. package/dist/src/execution/session/active-turn.d.ts +4 -1
  93. package/dist/src/execution/session/active-turn.js +1 -1
  94. package/dist/src/execution/session/entry-input.d.ts +23 -5
  95. package/dist/src/execution/session/entry.js +1 -1
  96. package/dist/src/execution/session/handoff.d.ts +35 -13
  97. package/dist/src/execution/session/handoff.js +1 -1
  98. package/dist/src/execution/session/program.d.ts +16 -3
  99. package/dist/src/execution/session/program.js +1 -1
  100. package/dist/src/execution/session/turn-step-types.d.ts +6 -1
  101. package/dist/src/execution/session/turn-step.js +1 -1
  102. package/dist/src/execution/session/turn.js +1 -1
  103. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  104. package/dist/src/execution/workflow-runtime.d.ts +4 -4
  105. package/dist/src/execution/workflow-runtime.js +1 -1
  106. package/dist/src/harness/attachment-staging.d.ts +27 -7
  107. package/dist/src/harness/attachment-staging.js +1 -1
  108. package/dist/src/harness/compaction-prompt.js +3 -3
  109. package/dist/src/harness/input-requests.js +1 -1
  110. package/dist/src/harness/messages.js +1 -1
  111. package/dist/src/harness/token-estimate.d.ts +7 -3
  112. package/dist/src/harness/token-estimate.js +1 -1
  113. package/dist/src/harness/tool-loop.js +2 -2
  114. package/dist/src/instrumentation/ai-sdk-hook-bridge.js +1 -1
  115. package/dist/src/instrumentation/lifecycle.d.ts +2 -0
  116. package/dist/src/internal/application/package.js +1 -1
  117. package/dist/src/internal/attachments/media-metadata.d.ts +25 -0
  118. package/dist/src/internal/attachments/media-metadata.js +1 -0
  119. package/dist/src/internal/attachments/sandbox-refs.d.ts +12 -7
  120. package/dist/src/internal/attachments/sandbox-refs.js +1 -1
  121. package/dist/src/internal/authored-module-loader.js +1 -1
  122. package/dist/src/internal/bundler/extension-mount-plugin.d.ts +4 -0
  123. package/dist/src/internal/bundler/extension-mount-plugin.js +1 -1
  124. package/dist/src/internal/bundler/extension-scope-plugin.js +2 -2
  125. package/dist/src/internal/input-text.d.ts +12 -0
  126. package/dist/src/internal/input-text.js +1 -0
  127. package/dist/src/internal/workflow/vercel-world-defaults.d.ts +1 -1
  128. package/dist/src/internal/workflow/vercel-world-defaults.js +1 -1
  129. package/dist/src/protocol/message.d.ts +2 -1
  130. package/dist/src/public/channels/chat-sdk/input-actions.d.ts +8 -2
  131. package/dist/src/public/channels/chat-sdk/input-actions.js +4 -1
  132. package/dist/src/public/channels/github/defaults.js +2 -3
  133. package/dist/src/public/channels/linear/hitl.js +2 -3
  134. package/dist/src/public/channels/slack/action-status.d.ts +10 -5
  135. package/dist/src/public/channels/slack/action-status.js +1 -1
  136. package/dist/src/public/channels/slack/defaults.js +3 -3
  137. package/dist/src/public/channels/slack/limits.d.ts +1 -1
  138. package/dist/src/public/channels/slack/limits.js +1 -1
  139. package/dist/src/public/channels/slack/slackChannel.d.ts +11 -9
  140. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  141. package/dist/src/public/channels/slack/task-card.js +1 -1
  142. package/dist/src/public/channels/slack/thread-status.d.ts +33 -0
  143. package/dist/src/public/channels/slack/thread-status.js +1 -0
  144. package/dist/src/public/channels/twilio/defaults.js +4 -2
  145. package/dist/src/react/use-eve-agent.js +1 -1
  146. package/dist/src/setup/scaffold/create/project.js +1 -1
  147. package/dist/src/subagents/hitl-proxy.d.ts +4 -2
  148. package/dist/src/subagents/hitl-proxy.js +1 -1
  149. package/dist/src/svelte/index.js +1 -1
  150. package/dist/src/svelte/use-eve-agent.js +1 -1
  151. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  152. package/dist/src/tools/provided/read-file.d.ts +7 -0
  153. package/dist/src/tools/provided/read-file.js +2 -2
  154. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  155. package/dist/src/tracing/agent-tool-instrumentation.js +1 -1
  156. package/dist/src/vue/index.js +1 -1
  157. package/dist/src/vue/use-eve-agent.js +1 -1
  158. package/docs/README.md +1 -0
  159. package/docs/agent-config.md +2 -2
  160. package/docs/channels/chat-sdk.mdx +1 -1
  161. package/docs/channels/slack.mdx +21 -15
  162. package/docs/channels/twilio.mdx +1 -1
  163. package/docs/code-extension.mdx +119 -0
  164. package/docs/concepts/built-in-tools.md +1 -1
  165. package/docs/concepts/default-harness.md +4 -0
  166. package/docs/concepts/execution-model-and-durability.mdx +7 -1
  167. package/docs/concepts/sessions-runs-and-streaming.md +6 -4
  168. package/docs/evals/cases.mdx +1 -0
  169. package/docs/extensions.md +6 -3
  170. package/docs/guides/client/streaming.mdx +1 -1
  171. package/docs/guides/dev-tui.md +3 -1
  172. package/docs/guides/dynamic-capabilities.md +1 -1
  173. package/docs/meta.json +1 -0
  174. package/docs/sandbox/index.mdx +13 -0
  175. package/docs/tools/overview.mdx +4 -2
  176. package/package.json +7 -7
  177. package/dist/src/compiled/_chunks/node/undici-h5GH4RBM.js +0 -95
  178. package/dist/src/compiled/_chunks/workflow/debug-log-CVPstO1D.js +0 -1
  179. package/dist/src/compiled/_chunks/workflow/dist-BUFGAKRb.js +0 -1
  180. package/dist/src/compiled/_chunks/workflow/frames-Dr9fHWdo.js +0 -3
  181. package/dist/src/compiled/_chunks/workflow/helpers-DkKxg_yn.js +0 -1
  182. package/dist/src/compiled/_chunks/workflow/resume-hook-uTW-jBYz.js +0 -1
  183. package/dist/src/compiled/_chunks/workflow/run-5DmiMN9b.js +0 -1
  184. package/dist/src/compiled/_chunks/workflow/serialization-CNIYl1D3.js +0 -3
  185. package/dist/src/compiled/_chunks/workflow/signal-exit-DZKTacNU.js +0 -95
  186. package/dist/src/compiled/_chunks/workflow/sleep-DFKgN7UG.js +0 -1
  187. package/dist/src/compiled/_chunks/workflow/token-1wSBbi5N.js +0 -1
  188. package/dist/src/compiled/_chunks/workflow/token-util-Cm4Ec1Bg.js +0 -1
  189. package/dist/src/compiled/_chunks/workflow/ws-transport--rYOVIaf.js +0 -1
@@ -457,20 +457,26 @@ The bases say where a call may go. `apiBaseUrl` is the base Slack Web API method
457
457
 
458
458
  eve shows an agent's progress in two places. Short work, such as thinking or a tool call, appears in the thread status and never posts a message. [Tasks](/docs/tools/tasks), which keep working while the conversation continues, appear in a task card: one message per turn that eve updates in place. Replies post as ordinary messages, so the thread holds the conversation, the task card, and nothing else.
459
459
 
460
- | Moment | Thread status |
461
- | ---------------------------------- | ------------------------------------------------------------------------------- |
462
- | A mention or DM arrives | `Thinking...`, right away, while the message hook is still deciding |
463
- | The message hook drops the message | Cleared |
464
- | The turn starts | `Working...` |
465
- | The model reasons | The first line of its reasoning |
466
- | The model calls tools | Its narration before the calls, or an action label such as `Search useEveAgent` |
467
- | The turn waits on its tasks | `Waiting on researcher...`, or `Waiting on 3 tasks...` |
468
- | The model starts its next step | `Reviewing results...` after a task finishes, otherwise `Thinking...` |
469
- | A reply posts | Cleared by Slack |
470
-
471
- Slack clears a thread status after two minutes without a message, so during a long wait the task card is what shows the work is still going.
472
-
473
- Action labels follow the same rule as the task card titles described below, plus `+N more` when the model requests several actions at once. They leave out the model's own `task_wait` and `task_cancel` calls. Reasoning snippets build progressively: extensions of at least four characters appear immediately, while smaller streamed deltas use a five-second refresh interval to avoid one Slack request per token.
460
+ | Moment | Thread status |
461
+ | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
462
+ | A mention or DM arrives | `Thinking...`, right away, while the message hook is still deciding |
463
+ | The message hook drops the message | Cleared |
464
+ | The turn starts | `Thinking...` |
465
+ | The model reasons | Its latest reasoning heading, or its latest finished sentence |
466
+ | The model calls tools | Its narration before the calls, or the first action label, such as `Search useEveAgent`, plus `+N more` for the step's other calls |
467
+ | A tool reports progress | The tool's `label.delta` text |
468
+ | A tool finishes | The tool's `label.complete` text, when it defines one; otherwise the status stays |
469
+ | The model starts its next step | `Reviewing researcher's results...` after a task finishes, otherwise the same status again |
470
+ | The model streams a long reply | `Writing a reply...`, once the text runs past 280 characters |
471
+ | The turn waits on its tasks | `Waiting on researcher...`, or `Waiting on 3 tasks...` |
472
+ | The turn waits on an approval, answer, or sign-in | Cleared until the turn resumes, then the status it had |
473
+ | A reply posts | Cleared by Slack |
474
+
475
+ A model step never resets the status to a generic line. The status keeps naming the latest work until something newer replaces it, so a user watching the thread sees `Checking recent deploys`, then `Found 4 failed deploys`, then `Reading build logs`, without `Thinking...` in between.
476
+
477
+ Slack removes a thread status after two minutes without a message from the app, and clears it whenever the app posts in the thread. eve sets the current status again at each model step, after it posts a new task card, and as a tool reports progress. A tool that runs longer than two minutes without reporting progress loses its status. Report progress with [`label.delta`](/docs/tools#label-tool-activity), or run the work as a [task](/docs/tools/tasks), whose card shows it is still going.
478
+
479
+ Action labels follow the same rule as the task card titles described below. They leave out the model's own `task_wait` and `task_cancel` calls. Reasoning shows one piece at a time: a heading when the model titles its reasoning, as reasoning summaries do, otherwise the latest finished sentence. Each piece of reasoning, and each progress label, stays up for at least three seconds, so the status changes at a readable pace instead of sending a Slack request per token. Every status is cut to 50 characters at a word boundary.
474
480
 
475
481
  Replies up to 12,000 characters render inline. Longer replies are uploaded unchanged as a Markdown snippet named `eve-response.md` with a short in-thread note, which requires the `files:write` bot scope.
476
482
 
@@ -792,7 +798,7 @@ Private file downloads resolve credentials from the session's app installation w
792
798
 
793
799
  Downloads cover Slack's own file hosts plus URLs under a configured [`api.fileBaseUrl`](#point-the-channel-at-a-different-slack-api-host), and travel on `api.fetch` when one is configured.
794
800
 
795
- Staged files live in the session sandbox under `/workspace/attachments`. Session history keeps a reference to that path, not a second copy of the Slack file. If the backend can no longer reattach the original sandbox, eve cannot restore the attachment bytes from history; later turns receive a missing-file result. Store files outside the sandbox when the agent must retain them independently of sandbox availability.
801
+ Staged files live in the session sandbox under `/workspace/.eve/attachments`. Session history keeps a reference to that path, not a second copy of the Slack file. If the backend can no longer reattach the original sandbox, eve cannot restore the attachment bytes from history; later turns receive a missing-file result. Store files outside the sandbox when the agent must retain them independently of sandbox availability.
796
802
 
797
803
  ## What to read next
798
804
 
@@ -62,7 +62,7 @@ The default `message.completed` handler sends the reply as SMS through Twilio's
62
62
 
63
63
  ### Human-in-the-loop (HITL)
64
64
 
65
- SMS and voice have no native button or card affordance, so HITL prompts do not render as interactive controls. The agent's `input.requested` event reaches your `events["input.requested"]` handler if you declare one. Handle it by sending the prompt as text and mapping the caller's reply back to the input request yourself.
65
+ SMS has no buttons or cards, so the default `input.requested` handler sends each question and tool approval as an SMS with its options numbered. A reply with an option's number or label answers the pending request, so `1` or `approve` runs an approval-gated tool and `2` or `cancel` stops it. If the question allows a custom answer, any other text is taken as that answer. Callers on a voice call get the question by SMS too. To render questions differently, declare your own `events["input.requested"]` handler.
66
66
 
67
67
  ### Proactive sessions
68
68
 
@@ -0,0 +1,119 @@
1
+ ---
2
+ title: "Code Extension"
3
+ description: "Mount eve's coding extension, eve-code, and see its latest benchmark results against other coding agent harnesses."
4
+ ---
5
+
6
+ `eve/extensions/code` (eve-code) turns an eve agent into a coding agent. It ships inside the `eve` package, so you mount it without installing anything else. The extension contributes file-editing and search tools, an authenticated GitHub CLI tool, coding skills, a read-only worker subagent, and sandbox bootstrap helpers.
7
+
8
+ ## Benchmark results
9
+
10
+ 12 tasks × 3 attempts on `anthropic/claude-sonnet-5.5`. Snapshot updated 2026-10-03.
11
+
12
+ | Harness | Resolved | 95% interval | Median latency | p90 latency | Measured |
13
+ | --- | --- | --- | --- | --- | --- |
14
+ | `pi` | 72% (26/36) | 50%–92% | 266.7s | 340.5s | 2026-09-30 |
15
+ | `eve-code` | 67% (24/36) | 53%–81% | 235.4s | 389.7s | 2026-09-30 |
16
+ | `opencode` | 50% (18/36) | 28%–72% | 611.7s | 1170.3s | 2026-09-30 |
17
+
18
+ These results show baseline performance. Each harness uses its standard setup with high reasoning. The results do not show how a harness performs with other models, settings, or tasks.
19
+
20
+ <details>
21
+ <summary>How the benchmark works</summary>
22
+
23
+ The benchmark uses eve-bench and the DeepSWE-lean dataset. DeepSWE-lean has 12 feature and bug-fix tasks from DeepSWE v1.1.
24
+
25
+ - All harnesses use the same model and the same tasks.
26
+ - Each harness does each task 3 times.
27
+ - Each attempt runs in a new Vercel Sandbox.
28
+ - Each attempt has a limit of 20 minutes.
29
+ - The DeepSWE verifier examines the files that the agent leaves.
30
+ - An attempt passes only when the verifier passes.
31
+ - A crash or a timeout is a failure.
32
+
33
+ The line on each correctness row shows the 95% interval. When the lines of two harnesses overlap, the benchmark does not show a difference between them.
34
+
35
+ </details>
36
+
37
+ <details>
38
+ <summary>How the results update</summary>
39
+
40
+ 1. A maintainer runs the `eve-code` workflow on `main` with the `deepswe-lean` dataset.
41
+ 2. The workflow runs eve-code, opencode, and pi. It saves each complete result in the eve-bench result store.
42
+ 3. The workflow writes a summary of the result to `apps/docs/lib/evals/eve-code-benchmark.json`. Then it commits the file to `main`.
43
+ 4. The next docs deployment shows the new results.
44
+
45
+ The workflow does not publish incomplete runs, single-task runs, or pull request runs. Results can be older than `main`, because a maintainer starts each run. Select a harness name to open the GitHub Actions run for that result.
46
+
47
+ </details>
48
+
49
+ ## Mount the extension
50
+
51
+ Create an extension file in your agent. The file name sets the mount name, which prefixes every contributed tool and subagent ID (for example, `code__grep`):
52
+
53
+ ```ts title="agent/extensions/code.ts"
54
+ import code from "eve/extensions/code";
55
+
56
+ export default code({});
57
+ ```
58
+
59
+ `code({})` mounts the extension without GitHub or Vercel authentication. Add the options below when the agent needs them.
60
+
61
+ ## Configure the extension
62
+
63
+ | Option | Required | Effect |
64
+ | ------------------------------ | ------------- | ---------------------------------------------------------------------------------------------- |
65
+ | `github.connector` | With `github` | Connector that mints a GitHub token |
66
+ | `github.org` | With `github` | Organization whose repositories the `gh` tool can access |
67
+ | `github.broker` | With `github` | `broker(sandbox, rules)` callback that installs, then removes, the GitHub credential rules |
68
+ | `vercel.connector` | With `vercel` | Connector that requests an app-subject Vercel token |
69
+ | `vercel.delivery` | No | `"firewall"` (default) or `"command"` |
70
+ | `broker` | No | `broker(sandbox, rules)` callback that merges Vercel credential rules into your network policy |
71
+ | `worker.model` | With `worker` | Model for the `worker` subagent. Defaults to `openai/gpt-5.6-terra-fast` |
72
+ | `worker.reasoning` | With `worker` | Reasoning level for the `worker` subagent. Defaults to `xhigh` |
73
+ | `worker.openaiReasoningEffort` | No | Passed to OpenAI models as `reasoningEffort` |
74
+
75
+ ```ts title="agent/extensions/code.ts"
76
+ import code from "eve/extensions/code";
77
+
78
+ export default code({
79
+ vercel: { connector: "vercel/acme-bot" },
80
+ worker: { model: "openai/gpt-5.6-terra-fast", reasoning: "high" },
81
+ });
82
+ ```
83
+
84
+ ### Credentials stay outside the sandbox
85
+
86
+ With firewall delivery, Vercel tokens never enter sandbox processes. Firewall delivery without a top-level `broker` requires a sandbox provider that exposes `setNetworkPolicy()`, and fails otherwise. Set `vercel.delivery: "command"` for providers without a mutable network policy.
87
+
88
+ The `gh` tool requests a token scoped to exactly one repository in `github.org` for each invocation. The sandbox process receives a placeholder `GH_TOKEN`, and the firewall exchanges it on matching GitHub requests. Your `github.broker` callback receives the header-transform rules for the command, then `null` to remove the lease. The callback must preserve your other network rules. GitHub authentication has no command-delivery option.
89
+
90
+ To use a personal access token or another credential provider, omit the connector and call `authenticateGitHub` or `authenticateVercel` from `eve/extensions/code/sandbox` in your own sandbox lifecycle. These helpers authenticate commands you run yourself; they do not configure the `gh` tool.
91
+
92
+ ## Prepare the sandbox
93
+
94
+ Install the CLI tooling in your sandbox environment's `prepare` callback:
95
+
96
+ ```ts title="agent/sandbox.ts"
97
+ import { defineSandbox } from "eve/sandbox";
98
+ import { VercelSandbox } from "eve/sandbox/vercel";
99
+ import { installCodeTooling } from "eve/extensions/code/sandbox";
100
+
101
+ export const environment = VercelSandbox.environment({
102
+ prepare: async (sandbox) => {
103
+ await installCodeTooling(sandbox, { vercel: true });
104
+ },
105
+ });
106
+
107
+ export default defineSandbox(() => environment.open());
108
+ ```
109
+
110
+ Preparation installs `gh`, wrappers for `gh`, `vc`, and `gh-signed-commit`, and TypeScript diagnostics. For repositories that require verified signatures, stage your changes and commit with `gh-signed-commit`.
111
+
112
+ eve derives the prepared environment generation from the sandbox file and environment options, not from imported helpers. Upgrading eve alone does not rebuild an existing prepared environment.
113
+
114
+ ## What to read next
115
+
116
+ - [Extensions](/docs/extensions): mount, configure, and override extension packages
117
+ - [Sandbox](/docs/sandbox): environments, preparation, and network policy
118
+ - [Subagents](/docs/subagents): how declared subagents run and inherit configuration
119
+ - [Skills](/docs/skills): how the model loads skills on demand
@@ -64,7 +64,7 @@ export default disableTool();
64
64
 
65
65
  ### `read_file`
66
66
 
67
- `read_file` reads text files from the sandbox with line-numbered output. It accepts absolute paths and paths beginning with `$HOME/`.
67
+ `read_file` reads text files from the sandbox with line-numbered output, and shows PNG, JPEG, GIF, and WebP images up to 3 MiB to the model as images. It accepts absolute paths and paths beginning with `$HOME/`.
68
68
 
69
69
  ```sh
70
70
  eve add tool/read_file
@@ -36,6 +36,10 @@ if a turn is running, eve queues it until that turn settles. A successful manual
36
36
  compaction emits the same `compaction.requested` and `compaction.completed`
37
37
  events as automatic compaction, followed by `session.waiting`.
38
38
 
39
+ After either kind of compaction, eve moves the idle session to a fresh workflow
40
+ run on the same deployment, so a long session's run history does not keep
41
+ growing. See [Execution model and durability](./execution-model-and-durability#compaction-handoff).
42
+
39
43
  To discard model-message history instead of summarizing it, call the corresponding
40
44
  `clear()` method on any of those handles. Clearing preserves the session identity,
41
45
  system prompt, configured tools and skills, durable state, limits, and sandbox.
@@ -25,12 +25,18 @@ The Workflow SDK is not inherently tied to Vercel. In local development and in a
25
25
 
26
26
  When a Vercel production deployment changes, a new delivery to an idle session hands the session's settled state to the exact deployment that accepted the request. This applies whether the delivery arrives through the session ID or through any channel continuation address the session has claimed. The session keeps its original ID and event stream, while the next model turn uses that deployment's current system-role instructions, model, and tools. Static user-role instructions stay pinned in the durable conversation history and are not seeded again. A successful handoff restarts the session's original configured [`sessionTimeoutMs`](../agent-config#runtime-limits) duration; disabled timeouts stay disabled. Failed or skipped handoffs keep the existing deadline.
27
27
 
28
- Before taking ownership, the target deployment upgrades the checkpoint when an older eve release wrote it, then checks that no pending work remains. A deployment accepts checkpoints from eve 0.66.0 and later, so upgrading eve does not leave long-lived sessions, such as a Slack thread, on their old deployment. An older release cannot read a newer checkpoint: after a rollback, a session that already moved to the newer deployment stays there. Extension state saved before eve 0.69 moves to its mount when exactly one mount uses that extension package and the extension still defines that state. Otherwise eve cannot choose an owner, and the session stays on its current deployment. Idle subagent sessions that eve 0.66–0.68 kept for later reuse are stopped after the handoff. Authored session state remains opaque to this validation.
28
+ Before taking ownership, the target deployment upgrades the checkpoint when an older eve release wrote it, then checks that no pending work remains. A deployment accepts checkpoints from eve 0.66.0 and later, so upgrading eve does not leave long-lived sessions, such as a Slack thread, on their old deployment. An older release cannot read a newer checkpoint: after a rollback, a session that already moved to the newer deployment stays there. Extension state saved before eve 0.69 moves to its mount when exactly one mount of that extension package defines that state. State that the target deployment no longer defines, such as a removed `defineState` key, is dropped, and the target deployment's runtime logs show a `dropping unknown context key during deserialization` warning. When two or more mounts of one extension package define that state, eve cannot choose an owner, and the session stays on its current deployment. Idle subagent sessions that eve 0.66–0.68 kept for later reuse are stopped after the handoff. Authored session state remains opaque to this validation.
29
29
 
30
30
  If the target deployment rejects the session, the previous owner keeps it and processes the triggering delivery. When the target deployment cannot read the checkpoint, its Vercel runtime logs show a `session handoff refused` warning with the checkpoint version and the reason. Owners on this release or later also write a `session handoff failed` warning to their own runtime logs, with the target deployment and the reason.
31
31
 
32
32
  eve does not move live work between deployments. A session with a running turn, pending human input or authorization, queued messages, or active tasks and subagents stays on its current deployment. After that work settles, a later delivery can move the idle session; the earlier deployment signal is not remembered.
33
33
 
34
+ ### Compaction handoff
35
+
36
+ Every workflow run records each step it executes, so a session that ran on one run for weeks would carry its whole history in that run. To bound this, eve moves a session to a fresh run on its current deployment after [compaction](./default-harness#compaction) rewrites the conversation history. This applies to automatic compaction during a turn and to a client or channel compaction request.
37
+
38
+ The move happens once the turn settles and nothing else is waiting: no queued messages, running tasks or subagents, or pending human input. The new run receives the compacted history and settled state, then waits for the next message. If a single message reaches an otherwise idle session before the move completes, eve moves the session with that message, and the message's turn runs on the new run. If work is still pending, eve tries again after a later turn settles. The session keeps its ID, event stream, continuation addresses, and deadline; compaction never extends [`sessionTimeoutMs`](../agent-config#runtime-limits). If the new run cannot take ownership, the current run keeps the session, writes a `session handoff failed` warning to its runtime logs, and tries again later.
39
+
34
40
  ### Upgrading sessions from the former execution model
35
41
 
36
42
  You can upgrade directly from a release that used a session driver and separate
@@ -12,8 +12,8 @@ controls, and streams. Every operation targets that exact session; none follows
12
12
  or creates a replacement implicitly.
13
13
 
14
14
  The session ID currently identifies the original Workflow run that owns the
15
- event stream. A deployment handoff changes the executing run, not the session
16
- ID or stream. Stream namespaces belong to a run; eve does not support
15
+ event stream. A deployment or compaction handoff changes the executing run, not
16
+ the session ID or stream. Stream namespaces belong to a run; eve does not support
17
17
  caller-assigned session IDs or globally addressed streams.
18
18
 
19
19
  Authored channels also have channel-local continuation tokens. A token addresses
@@ -24,7 +24,7 @@ by the eve HTTP session API. See [Custom channels](../channels/custom#channel-op
24
24
  Sessions last 30 days by default; configure `limits.sessionTimeoutMs` in
25
25
  `agent.ts`, or set it to `false` to disable the deadline. A successful deployment
26
26
  handoff or legacy-session import restarts the original configured duration.
27
- Ordinary messages and process restarts keep the existing deadline. At expiration, eve
27
+ Ordinary messages, compaction handoffs, and process restarts keep the existing deadline. At expiration, eve
28
28
  lets an active turn settle, emits `session.completed`, and releases the
29
29
  session's continuation addresses so the next qualifying channel message starts fresh. Stored
30
30
  session data is not deleted. See [Agent config](../agent-config#runtime-limits).
@@ -123,7 +123,7 @@ Note: consider the privacy, confidentiality, and user-experience implications fo
123
123
 
124
124
  A delegated subagent publishes progress on its own child-session stream. When a subagent tool call or a workflow tool's `ctx.agent` opens a session, the parent emits `agent.started` with the call's `callId` and `turnId`, its `taskId` when the call runs as a task, the child's `sessionId`, and a `streamPath` that a client follows with `session.agent(started).stream()`. A subagent tool call is a [task](#task-events) whose `task.started` has `kind: "agent"`: its `task.started` and `task.settled` carry the call, and `task.settled.data.output` is the child's reply. A call that fails before the child session opens has no `agent.started`. A settled call does not end the child session; later calls with the same `taskId` reach it.
125
125
 
126
- A question or sign-in from inside a running call does not end the turn. This covers a workflow tool's `ctx.ask()`, including the built-in `ask_question` tool, and a delegated subagent's question or sign-in. The stream emits `input.requested` or `authorization.required`, then `turn.waiting` with `on: "input"` and the open turn's `turnId`. After the answer or sign-in, the turn resumes with the next `step.started` for the same `turnId`, and only `turn.completed`, `turn.failed`, or `turn.cancelled` ends it. When you answer a question that belongs to a workflow tool or a subagent, the session you answer on emits `input.resolved` for it as it routes the answer down. If the workflow tool run that relayed a question or approval ends before anyone answers, that session emits `input.resolved` with `outcome: "cancelled"` for it. This covers the run's own `ctx.ask()` questions and requests from sessions it opened with `ctx.agent`. A cancelled turn does the same for every question or approval the session relays. A sign-in or tool approval the turn raises itself holds it the same way, also with `on: "input"`. A message from the same person steers the turn and cancels the request: a sign-in reports `authorization.completed` with `outcome: "declined"`, and an approval reports `input.resolved` with `outcome: "ignored"`. Messages from other people wait until the turn ends. Cancelling the turn ends both: a held sign-in reports `authorization.completed` with `outcome: "declined"`, and a held approval reports `input.resolved` with `outcome: "cancelled"`.
126
+ A question or sign-in from inside a running call does not end the turn. This covers a workflow tool's `ctx.ask()`, including the built-in `ask_question` tool, and a delegated subagent's question or sign-in. The stream emits `input.requested` or `authorization.required`, then `turn.waiting` with `on: "input"` and the open turn's `turnId`. After the answer or sign-in, the turn resumes with the next `step.started` for the same `turnId`, and only `turn.completed`, `turn.failed`, or `turn.cancelled` ends it. When you answer a question that belongs to a workflow tool or a subagent, the session you answer on emits `input.resolved` for it as it routes the answer down. While other relayed questions are still pending, it then emits `turn.waiting` with `on: "input"` again. If the workflow tool run that relayed a question or approval ends before anyone answers, that session emits `input.resolved` with `outcome: "cancelled"` for it. This covers the run's own `ctx.ask()` questions and requests from sessions it opened with `ctx.agent`. A cancelled turn does the same for every question or approval the session relays. A sign-in or tool approval the turn raises itself holds it the same way, also with `on: "input"`. A message from the same person steers the turn and cancels the request: a sign-in reports `authorization.completed` with `outcome: "declined"`, and an approval reports `input.resolved` with `outcome: "ignored"`. Messages from other people wait until the turn ends. Cancelling the turn ends both: a held sign-in reports `authorization.completed` with `outcome: "declined"`, and a held approval reports `input.resolved` with `outcome: "cancelled"`.
127
127
 
128
128
  ### Task events
129
129
 
@@ -225,6 +225,8 @@ A structured response matches any currently pending request by ID, not only the
225
225
 
226
226
  One delivery can answer requests from several batches. eve resumes approval-bearing batches in durable order and carries later answers forward until each batch can resume. If you answer only some approvals in a batch, eve saves those responses until the remaining approvals are answered. Meanwhile, unrelated messages can run tools and receive a completed reply. The saved partial responses neither block that reply nor trigger another model call after it.
227
227
 
228
+ When steering interrupts pending model generation, the interrupted step still ends with `step.completed`, carrying `finishReason: "other"` and any usage the provider reported. The correction's `message.received` and the next `step.started` for the same `turnId` follow.
229
+
228
230
  Multiple steering messages retain their durable arrival order and may be folded into one input at the next boundary. A message accepted after turn settlement starts the next turn. See [message delivery and steering](./execution-model-and-durability#message-delivery-and-steering).
229
231
 
230
232
  ## Cancel the in-flight turn
@@ -110,6 +110,7 @@ Every `t.session()` or `t.send()` creates a new independent conversation. Contin
110
110
  - `session.send(message, options?)` sends a follow-up on that session and waits for it to settle.
111
111
  - `session.start(message, options?)` starts a text turn and returns as soon as the server accepts it. The live turn exposes `.session`, `.sessionId`, `.waitForEvent(...)`, `.cancel()`, and `.result()`.
112
112
  - `session.cancel()` requests cooperative cancellation of that session's active turn. Both `accepted` and `no_active_turn` are successful outcomes.
113
+ - `session.compact()` compacts that session's history between turns and waits for it to finish. It resolves to the captured events from `compaction.requested` through `session.waiting`, so assertions such as `.event("compaction.completed")` work on the result. It throws when the session is no longer active.
113
114
  - `session.sendFile(text, path, mediaType?)` attaches a local file as a data URL.
114
115
  - `session.agent(started).stream(options?)` follows a delegated child's stream through the parent with the eval client's credentials. Pass an `agent.started` event from that session. It also reaches children on another deployment, which `t.target.watchTurn(...)` cannot address.
115
116
  - `session.requireInputRequest(filter?)` records a gate, requires exactly one pending request, and returns it. Filters match tool name, action input, prompt, display, and option ids.
@@ -210,11 +210,13 @@ Extension state belongs to the logical mount path (for example, `extensions/crm`
210
210
 
211
211
  ### Upgrade from package-scoped extension state
212
212
 
213
- Deployments before eve 0.69 stored extension state under package-prefixed keys, such as `acme-crm.requests`. When a session from one of those deployments hands off to a newer deployment, eve moves each package-prefixed value to the mount that uses that package. eve never resets that state during restore.
213
+ Deployments before eve 0.69 stored extension state under package-prefixed keys, such as `acme-crm.requests`. When a session from one of those deployments hands off to a newer deployment, eve moves each package-prefixed value to the mount that uses that package.
214
214
 
215
- - The value moves only when exactly one mount uses the package and the extension still defines that state name. Otherwise eve cannot tell which mount owns the value, so the handoff is rejected and the session stays on its current deployment. Keep that deployment available until the session finishes, or start a new session on the deployment you want to use.
215
+ - The value moves when exactly one mount of that package defines that state name.
216
+ - When no mount of that package defines that state name, for example because the extension removed it or the package was renamed, eve drops the value. The target deployment's runtime logs show a `dropping unknown context key during deserialization` warning with the key.
217
+ - When two or more mounts use the package and define that state name, eve cannot tell which mount owns the value, so the handoff is rejected and the session stays on its current deployment. Keep that deployment available until the session finishes, or start a new session on the deployment you want to use.
216
218
  - Older deployments cannot read sessions saved by a newer release, so a session that already moved does not hand back after a rollback.
217
- - Local context snapshots follow the same rule: an older snapshot restores when every saved state key still has an owner.
219
+ - Local context snapshots follow the same rules.
218
220
 
219
221
  ### Use an extension in a workspace
220
222
 
@@ -368,6 +370,7 @@ At build time, eve checks the extension's generated capability metadata. If the
368
370
  ## What to read next
369
371
 
370
372
  - [Integrations](/integrations): browse ready-to-install extensions using the Extensions filter
373
+ - [Code extension](/docs/code-extension): mount eve-code, the coding extension that ships in `eve`, and see its benchmark results
371
374
  - [Tools](/docs/tools): static tools, approval, and tool output
372
375
  - [Dynamic capabilities](/docs/guides/dynamic-capabilities): dynamic connections, tools, skills, and instructions
373
376
  - [Instructions](/docs/instructions): static and TypeScript instructions
@@ -173,7 +173,7 @@ The sign-in holds the turn open, and the stream emits `turn.waiting` with `on: "
173
173
 
174
174
  HTTP connections can end before a run does. The client reconnects from the number of events already consumed, so long turns continue without replaying events. By default, a turn response keeps reconnecting until it reaches a turn boundary or is aborted, including while the turn is paused for authorization. A manually opened `session.stream()` eventually stops after repeated empty streams when it can no longer make progress.
175
175
 
176
- Browser failures while reading a response body, including `TypeError: Load failed` and `TypeError: network error`, use the same reconnect policy. Invalid stream events still fail the read.
176
+ Browser network failures use the same reconnect policy, both when opening a stream (`TypeError: Failed to fetch`, `TypeError: Load failed`, or `TypeError: NetworkError when attempting to fetch resource.`) and while reading a response body (any `TypeError`, such as `TypeError: network error`). Invalid stream events still fail the read.
177
177
 
178
178
  If your consumer persists events, key on `event.meta.id`. It is stable across reconnects and rewinds, so an overlapping replay is safe to ingest twice. See [the event envelope](../../concepts/sessions-runs-and-streaming#the-event-envelope).
179
179
 
@@ -98,7 +98,9 @@ Type a message and press `Enter` to send it. When the agent asks a question or r
98
98
 
99
99
  The activity line shows **Thinking** while the model reasons or waits to respond, **Generating** while it writes a response or tool input, and **Running** while tools execute. A blinking dot and elapsed time indicate progress, with token counts shown when available. While [tasks](../tools/tasks) work, the drawer header replaces this line: it shows the parent's current activity, task count, and turn elapsed time without token counts. **Waiting** means the parent is waiting on work; **Working** appears without a turn timer when tasks remain active between turns.
100
100
 
101
- A task, such as a call to a subagent, writes one line to the transcript when it starts and one when it finishes, fails, or is stopped. The finished line names how long the task took and, for a subagent, what it did, such as `Read 3 files, Ran 2 commands`. Task starts use the same tool-call styling as synchronous calls. While tasks work, an activity drawer above the prompt shows each task's name, current activity, and elapsed time without repeating its launch prompt. Subagents use labels such as `subagent(self-modification)`, with elapsed time beside the name and the latest observed tool grouped beneath an elbow. The tool remains visible between calls rather than switching to a starting placeholder. During questions and approvals, activity stays visible above the request with a shared divider when screen space permits; the request takes priority on small terminals. Background work started by a followed subagent appears beneath that subagent; deeper work uses an ownership path instead of further indentation. The panel caps its height and prioritizes tasks needing approval when work overflows. The UI does not show the model's own `task_wait` and `task_cancel` calls; their effect appears as the **Waiting** header and a stopped task's line.
101
+ A tool call shows the tool's own `label`, or eve's copy for built-in tools such as `Read README.md`. Any other call shows a readable tool name without its extension or connection prefix, such as `List issues` for `linear__list_issues`. Approval prompts show the exact tool name unless the tool provides a title.
102
+
103
+ A task, such as a call to a subagent, writes one line to the transcript when it starts and one when it finishes, fails, or is stopped. The finished line names how long the task took and, for a subagent, what it did, such as `Read 3 files, Ran 2 commands`. Task starts use the same tool-call styling as synchronous calls. While tasks work, an activity drawer above the prompt shows each task's name, current activity, and elapsed time without repeating its launch prompt. Subagents use readable labels, such as `subagent(stock price)` for a `stock-price` subagent or `subagent(worker)` for the `code__worker` subagent of the code extension, with elapsed time beside the name and the latest observed tool grouped beneath an elbow. The tool remains visible between calls rather than switching to a starting placeholder. During questions and approvals, activity stays visible above the request with a shared divider when screen space permits; the request takes priority on small terminals. Background work started by a followed subagent appears beneath that subagent; deeper work uses an ownership path instead of further indentation. The panel caps its height and prioritizes tasks needing approval when work overflows. The UI does not show the model's own `task_wait` and `task_cancel` calls; their effect appears as the **Waiting** header and a stopped task's line.
102
104
 
103
105
  The prompt stays open while the agent works, including turns started elsewhere, such as a scheduled run. While a turn is running, `Enter` sends your message immediately as steering. Before assistant output begins, the runtime interrupts pending model generation and continues the same turn with your correction. Executing tools finish safely. After output begins, steering applies at the next workflow boundary and preserves streamed text.
104
106
 
@@ -55,7 +55,7 @@ export default defineAgent({
55
55
  });
56
56
  ```
57
57
 
58
- eve stages byte-backed `file` parts under `/workspace/attachments` before
58
+ eve stages byte-backed `file` parts under `/workspace/.eve/attachments` before
59
59
  `step.started`, but keeps their media type in `ctx.messages`. When an image
60
60
  reaches the provider, vision models can process it and non-vision models reject
61
61
  it. eve does not reroute automatically. See [Inbound
package/docs/meta.json CHANGED
@@ -20,6 +20,7 @@
20
20
  "---Integrate---",
21
21
  "install-integrations",
22
22
  "extensions",
23
+ "code-extension",
23
24
  "protocols/acp",
24
25
  "guides/client",
25
26
  "guides/frontend",
@@ -149,6 +149,19 @@ interface SandboxProviderResourceTree {
149
149
 
150
150
  Docker and microsandbox mount the compiled trees read-only under `/eve/resources`, copy workspace seeds into writable `/workspace`, and expose skills read-only where possible. Vercel's snapshot environment writes workspace and skill contents before capturing its snapshot. Custom providers decide whether to upload, mount, or write each tree, but must expose the final target paths before authored preparation runs.
151
151
 
152
+ ## Inbound attachments
153
+
154
+ eve writes byte-backed files that reach the agent into the sandbox under `/workspace/.eve/attachments/` and keeps only a reference in session history. This covers files attached to user messages and files that tools return to the model with `toolOutputPart.file` or as MCP image, audio, and blob content.
155
+
156
+ Before every model call, eve reads the referenced files back from the sandbox:
157
+
158
+ - An image up to 3 MiB or a PDF up to 20 MiB attached to a message reaches the model as a file. Larger files and other types reach the model as a text reference, such as `Attached file /workspace/.eve/attachments/<hash>/report.csv (text/csv)`, that the agent can open with `read_file` or `bash`.
159
+ - A file returned by a tool always reaches the model as a file.
160
+
161
+ If a referenced file is missing, or its bytes no longer match what eve staged because something in the sandbox overwrote it, the model receives a `FileNotFound` note in its place.
162
+
163
+ Each call sends the same bytes for the same file, so the model still sees attachments from earlier turns and the provider's prompt cache stays valid. Compaction replaces files in older tool results with their text reference. The `read_file` tool shows PNG, JPEG, GIF, and WebP files up to 3 MiB to the model as images, so the agent can look at an image again after compaction.
164
+
152
165
  ## Custom providers
153
166
 
154
167
  Define a provider with `defineSandboxProvider()` from `eve/sandbox/provider`. The five generic parameters describe environment options, live options, the prepared artifact, minimal serialized session state, and the provider-specific sandbox session type:
@@ -307,9 +307,11 @@ export default defineTool({
307
307
 
308
308
  The `toolOutput.text` and `toolOutput.json` builders construct the other two output shapes; hand-written literals remain valid everywhere.
309
309
 
310
- File payloads must be base64 strings — raw bytes (`Uint8Array`, `Buffer`) are rejected because they do not survive eve's durable JSON boundary. Keep payloads small: a content-part image is persisted in session history and re-sent on every subsequent model call, and eve warns above 3 MiB. Sending image parts to a model without vision support fails with that provider's error, the same as image parts in user messages.
310
+ File payloads must be base64 strings — raw bytes (`Uint8Array`, `Buffer`) are rejected because they do not survive eve's durable JSON boundary. eve warns above 3 MiB. Sending image parts to a model without vision support fails with that provider's error, the same as image parts in user messages.
311
311
 
312
- When older turns are compacted, file payloads are dropped from the summary and replaced with a text stub naming the file and media type — the model cannot re-see a compacted image. Content parts are for "look at this now"; if the agent may need an artifact again later, write it to the [sandbox](/docs/sandbox) and return its path.
312
+ eve writes each returned file to the session sandbox and keeps only a reference in session history, so the file's bytes are not stored again on every workflow step. Every later model call sends the same file, which keeps it visible on later turns and keeps the provider's prompt cache valid. See [Inbound attachments](/docs/sandbox#inbound-attachments). Compaction counts an image at roughly what providers bill for it rather than its base64 length.
313
+
314
+ When compaction drops older tool results, each file becomes a text reference such as `Attached file /workspace/.eve/attachments/<hash>/chart.png (image/png)`. The built-in `read_file` tool shows PNG, JPEG, GIF, and WebP files up to 3 MiB to the model as images, so the agent can open a compacted image again.
313
315
 
314
316
  Do not return secrets, credentials, unnecessary personal data, or unbounded sensitive content from tools. Filter, minimize, and redact tool outputs before returning them.
315
317
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.70.1",
3
+ "version": "0.70.3",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [
@@ -547,12 +547,12 @@
547
547
  "@vercel/otel": "2.1.3",
548
548
  "@vercel/sandbox": "3.3.0",
549
549
  "@vercel/sdk": "1.28.8",
550
- "@workflow/core": "5.0.0-beta.57",
551
- "@workflow/errors": "5.0.0-beta.24",
552
- "@workflow/serde": "5.0.0-beta.2",
553
- "@workflow/world": "5.0.0-beta.39",
554
- "@workflow/world-local": "5.0.0-beta.48",
555
- "@workflow/world-vercel": "5.0.0-beta.52",
550
+ "@workflow/core": "5.0.1",
551
+ "@workflow/errors": "5.0.1",
552
+ "@workflow/serde": "5.0.0",
553
+ "@workflow/world": "5.0.1",
554
+ "@workflow/world-local": "5.0.1",
555
+ "@workflow/world-vercel": "5.0.1",
556
556
  "ai": "^7.0.105",
557
557
  "chat": "4.41.0",
558
558
  "chokidar": "5.0.0",