eve 0.6.0-beta.12 → 0.6.0-beta.13

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 (167) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/docs/evals-v2-plan.md +45 -8
  3. package/dist/docs/public/advanced/default-harness.md +2 -2
  4. package/dist/docs/public/advanced/evals.md +43 -4
  5. package/dist/docs/public/frontend/nextjs.mdx +9 -0
  6. package/dist/docs/public/getting-started.mdx +1 -1
  7. package/dist/docs/public/tools.mdx +0 -4
  8. package/dist/src/chunks/{use-eve-agent-DT2A6VJb.js → use-eve-agent-q1isCIFv.js} +42 -8
  9. package/dist/src/chunks/{use-eve-agent-BD79SFqg.js → use-eve-agent-tFYnZx_b.js} +42 -8
  10. package/dist/src/cli/commands/setup.js +1 -1
  11. package/dist/src/cli/dev/tui/runner.d.ts +2 -1
  12. package/dist/src/cli/dev/tui/runner.js +1 -1
  13. package/dist/src/cli/dev/tui/terminal-renderer.d.ts +3 -1
  14. package/dist/src/cli/dev/tui/terminal-renderer.js +2 -2
  15. package/dist/src/cli/run.d.ts +4 -0
  16. package/dist/src/cli/run.js +1 -1
  17. package/dist/src/client/client.d.ts +8 -0
  18. package/dist/src/client/client.js +1 -1
  19. package/dist/src/client/session.js +1 -1
  20. package/dist/src/client/types.d.ts +4 -1
  21. package/dist/src/compiled/.vendor-stamp.json +7 -7
  22. package/dist/src/compiled/@ai-sdk/anthropic/index.d.ts +56 -31
  23. package/dist/src/compiled/@ai-sdk/anthropic/index.js +2 -2
  24. package/dist/src/compiled/@ai-sdk/google/index.js +1 -1
  25. package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
  26. package/dist/src/compiled/@ai-sdk/openai/index.d.ts +16 -9
  27. package/dist/src/compiled/@ai-sdk/openai/index.js +2 -2
  28. package/dist/src/compiled/@ai-sdk/otel/index.js +2 -2
  29. package/dist/src/compiled/@vercel/sandbox/index.js +1 -1
  30. package/dist/src/compiled/@workflow/core/index.js +2 -2
  31. package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +4 -2
  32. package/dist/src/compiled/@workflow/core/runtime/wait-until.d.ts +18 -0
  33. package/dist/src/compiled/@workflow/core/runtime.d.ts +3 -1
  34. package/dist/src/compiled/@workflow/core/runtime.js +28 -28
  35. package/dist/src/compiled/@workflow/core/serialization.d.ts +41 -0
  36. package/dist/src/compiled/@workflow/core/util.d.ts +0 -5
  37. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  38. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  39. package/dist/src/compiled/@workflow/world/index.d.ts +2 -2
  40. package/dist/src/compiled/@workflow/world/queue.d.ts +28 -2
  41. package/dist/src/compiled/_chunks/workflow/{dist-gEXVSMPU.js → dist-CkMRLaRV.js} +1 -1
  42. package/dist/src/compiled/_chunks/workflow/functions-DuPjIvMH.js +1 -0
  43. package/dist/src/compiled/_chunks/workflow/resume-hook-CEAS3opc.js +12 -0
  44. package/dist/src/compiled/_chunks/workflow/sleep-Cup6vPoA.js +1 -0
  45. package/dist/src/compiled/_chunks/workflow/{symbols-BWCAoPHE.js → symbols-BUTtwS7j.js} +1 -1
  46. package/dist/src/evals/cli/eval.d.ts +4 -0
  47. package/dist/src/evals/cli/eval.js +1 -1
  48. package/dist/src/evals/define-eval.js +1 -1
  49. package/dist/src/evals/index.d.ts +2 -1
  50. package/dist/src/evals/index.js +1 -1
  51. package/dist/src/evals/reporters/index.d.ts +1 -0
  52. package/dist/src/evals/reporters/index.js +1 -1
  53. package/dist/src/evals/requirements.d.ts +4 -0
  54. package/dist/src/evals/requirements.js +1 -0
  55. package/dist/src/evals/runner/artifacts.js +1 -1
  56. package/dist/src/evals/runner/execute-case.d.ts +5 -2
  57. package/dist/src/evals/runner/execute-case.js +1 -1
  58. package/dist/src/evals/runner/execute-eval.d.ts +5 -2
  59. package/dist/src/evals/runner/execute-eval.js +1 -1
  60. package/dist/src/evals/runner/reporters/junit.d.ts +9 -0
  61. package/dist/src/evals/runner/reporters/junit.js +8 -0
  62. package/dist/src/evals/session.d.ts +6 -0
  63. package/dist/src/evals/session.js +1 -1
  64. package/dist/src/evals/target.d.ts +23 -0
  65. package/dist/src/evals/target.js +1 -0
  66. package/dist/src/evals/types.d.ts +39 -2
  67. package/dist/src/execution/compaction.d.ts +14 -0
  68. package/dist/src/execution/compaction.js +1 -0
  69. package/dist/src/execution/delegated-parent-notification.js +1 -1
  70. package/dist/src/execution/node-step.js +1 -1
  71. package/dist/src/execution/sandbox/glob-tool.js +3 -3
  72. package/dist/src/execution/sandbox/grep-tool.js +3 -3
  73. package/dist/src/execution/sandbox/read-file-tool.js +1 -1
  74. package/dist/src/execution/subagent-adapter.js +1 -1
  75. package/dist/src/execution/turn-workflow.js +1 -1
  76. package/dist/src/execution/workflow-runtime.js +1 -1
  77. package/dist/src/execution/workflow-steps.js +1 -1
  78. package/dist/src/harness/model-call-error.d.ts +23 -6
  79. package/dist/src/harness/model-call-error.js +1 -1
  80. package/dist/src/harness/step-hooks.d.ts +6 -0
  81. package/dist/src/harness/tool-loop.js +1 -1
  82. package/dist/src/harness/types.d.ts +4 -15
  83. package/dist/src/internal/application/package.js +1 -1
  84. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  85. package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
  86. package/dist/src/internal/nitro/host/configure-nitro-routes.js +2 -2
  87. package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
  88. package/dist/src/internal/nitro/host/start-production-server.js +1 -1
  89. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.d.ts +5 -0
  90. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -0
  91. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +31 -2
  92. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
  93. package/dist/src/internal/nitro/routes/agent-info/load-agent-info-data.d.ts +13 -0
  94. package/dist/src/internal/nitro/routes/agent-info/load-agent-info-data.js +1 -1
  95. package/dist/src/internal/nitro/routes/info.d.ts +2 -2
  96. package/dist/src/internal/nitro/routes/info.js +1 -1
  97. package/dist/src/internal/workflow/queue-namespace.d.ts +5 -0
  98. package/dist/src/internal/workflow/queue-namespace.js +1 -0
  99. package/dist/src/internal/workflow-bundle/builder-support.js +2 -2
  100. package/dist/src/internal/workflow-bundle/builder.js +3 -5
  101. package/dist/src/internal/workflow-bundle/vercel-workflow-output.js +1 -1
  102. package/dist/src/internal/workflow-bundle/workflow-builders.d.ts +1 -1
  103. package/dist/src/internal/workflow-bundle/workflow-builders.js +1 -1
  104. package/dist/src/public/definitions/tool.d.ts +0 -33
  105. package/dist/src/public/next/index.d.ts +6 -0
  106. package/dist/src/public/next/index.js +1 -1
  107. package/dist/src/public/next/server.d.ts +1 -0
  108. package/dist/src/public/next/server.js +1 -1
  109. package/dist/src/public/tools/defaults.d.ts +2 -4
  110. package/dist/src/public/tools/defaults.js +1 -1
  111. package/dist/src/public/tools/define-read-file-tool.d.ts +0 -6
  112. package/dist/src/public/tools/define-read-file-tool.js +1 -1
  113. package/dist/src/public/tools/index.d.ts +1 -1
  114. package/dist/src/public/tools/internal.js +1 -1
  115. package/dist/src/runtime/connections/callback-route.js +1 -1
  116. package/dist/src/runtime/framework-tools/connection-search-dynamic.d.ts +1 -1
  117. package/dist/src/runtime/framework-tools/file-state.d.ts +3 -3
  118. package/dist/src/runtime/framework-tools/index.js +1 -1
  119. package/dist/src/runtime/framework-tools/read-file.js +2 -2
  120. package/dist/src/runtime/framework-tools/todo.d.ts +7 -0
  121. package/dist/src/runtime/framework-tools/todo.js +2 -2
  122. package/dist/src/runtime/resolve-tool.d.ts +2 -2
  123. package/dist/src/runtime/resolve-tool.js +1 -1
  124. package/dist/src/runtime/session-callback-route.js +1 -1
  125. package/dist/src/runtime/types.d.ts +1 -7
  126. package/dist/src/services/dev-client.d.ts +13 -0
  127. package/dist/src/services/dev-client.js +1 -1
  128. package/dist/src/setup/boxes/one-shot-next-steps.d.ts +4 -3
  129. package/dist/src/setup/boxes/one-shot-next-steps.js +1 -1
  130. package/dist/src/setup/boxes/preflight.d.ts +6 -5
  131. package/dist/src/setup/boxes/preflight.js +1 -1
  132. package/dist/src/setup/boxes/resolve-provisioning.d.ts +20 -7
  133. package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
  134. package/dist/src/setup/boxes/select-channels.d.ts +16 -9
  135. package/dist/src/setup/boxes/select-channels.js +1 -1
  136. package/dist/src/setup/boxes/select-chat.d.ts +1 -1
  137. package/dist/src/setup/boxes/select-connections.d.ts +5 -7
  138. package/dist/src/setup/boxes/select-connections.js +1 -1
  139. package/dist/src/setup/boxes/select-model.d.ts +6 -6
  140. package/dist/src/setup/boxes/select-model.js +1 -1
  141. package/dist/src/setup/boxes/select-setup-mode.js +1 -1
  142. package/dist/src/setup/cli/select-component.js +1 -1
  143. package/dist/src/setup/onboarding.d.ts +2 -1
  144. package/dist/src/setup/onboarding.js +1 -1
  145. package/dist/src/setup/prompter.js +1 -1
  146. package/dist/src/setup/scaffold/channels-catalog.d.ts +1 -1
  147. package/dist/src/setup/scaffold/create/project.d.ts +16 -0
  148. package/dist/src/setup/scaffold/create/project.js +3 -3
  149. package/dist/src/setup/scaffold/index.d.ts +1 -1
  150. package/dist/src/setup/scaffold/index.js +1 -1
  151. package/dist/src/setup/scaffold/update/channels.js +1 -1
  152. package/dist/src/setup/state.d.ts +9 -8
  153. package/dist/src/setup/vercel-project.d.ts +12 -0
  154. package/dist/src/setup/vercel-project.js +1 -1
  155. package/dist/src/source-change/apply-model-name.d.ts +25 -0
  156. package/dist/src/source-change/apply-model-name.js +2 -0
  157. package/dist/src/source-change/static-source-change.d.ts +36 -0
  158. package/dist/src/source-change/static-source-change.js +1 -0
  159. package/dist/src/svelte/index.js +1 -1
  160. package/dist/src/svelte/use-eve-agent.js +1 -1
  161. package/dist/src/vue/index.js +1 -1
  162. package/dist/src/vue/use-eve-agent.js +1 -1
  163. package/package.json +13 -12
  164. package/dist/src/compiled/_chunks/workflow/resume-hook-0Zk0zSvq.js +0 -12
  165. package/dist/src/compiled/_chunks/workflow/sleep-DXZr2BgM.js +0 -1
  166. package/dist/src/execution/tool-compaction.d.ts +0 -9
  167. package/dist/src/execution/tool-compaction.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # eve
2
2
 
3
+ ## 0.6.0-beta.13
4
+
5
+ ### Minor Changes
6
+
7
+ - fe98d0b: Compaction is now owned by the framework instead of individual tools. The per-tool `onCompact` hook (and the `CompactionInput` / `CompactionHookResult` types) is removed: the framework automatically preserves its own tool state across compaction — it resets read-before-write tracking and re-injects the active todo list. `defineReadFileTool` no longer accepts an `onCompact` option, and the agent-info response drops the now-meaningless `hasCompactionHook` field.
8
+ - 6fbf1e8: Evals can now verify target requirements and drive non-session surfaces. `eve eval` discovers live target capabilities from `/eve/v1/info`, supports `--mock-models`, `--no-skips`, and `--junit`, exposes `ctx.target.fetch/dispatchSchedule/attachSession`, and adds `requires` to eval and case definitions with a visible `skipped` verdict for unmet requirements.
9
+ - 6fbf1e8: Eval runner polish ahead of the e2e migration: `eve eval --verbose` streams `ctx.log` lines to stdout (and they now land in case artifacts), checks receive the same requirement-scoped target handle as the case run, JUnit failure bodies are trimmed to verdict/checks/scores, and reporter callbacks run off the case-execution hot path.
10
+ - 4408988: Onboarding now asks where the agent runs last, after the agent itself is described: name, model, channels, connections, then deployment (Vercel, or locally for now). Picking Slack or a Connect-backed connection resolves the deployment question to Vercel automatically with a note instead of disabling those rows up front, and scaffolding into a directory that is already linked to a Vercel project (with a logged-in CLI) skips the deployment, team, and project questions entirely — the AI Gateway authenticates through your Vercel login. The "own provider key" path now derives the scaffolded `byok` block from the model you picked (e.g. `openai/…` → `OPENAI_API_KEY`) instead of pinning the Anthropic default, and on headless `--skip-vercel` runs `--model` is now honored and validated against the AI Gateway catalog instead of being silently replaced by that default.
11
+ - 7319957: Add `createStaticSourceChange`, a central registry that lets upstream consumers (CLI, web setup UI) apply targeted edits to authored agent source. Its first operation, `updateModelName`, rewrites the `model` literal in `agent.ts` in place using oxc, preserving surrounding formatting and quote style. It bails with a source location when the value isn't a string literal, like an env reference or an inlined SDK model.
12
+
13
+ ### Patch Changes
14
+
15
+ - 431e5f6: Upgrade Eve's Nitro runtime dependency to `3.0.260610-beta`, picking up the latest Nitro 3 beta fixes and bundler updates.
16
+ - adc6118: Bump the AI SDK to the latest canary releases (`ai@7.0.0-canary.171`, `@ai-sdk/anthropic@4.0.0-canary.65`, `@ai-sdk/google@4.0.0-canary.80`, `@ai-sdk/mcp@2.0.0-canary.62`, `@ai-sdk/openai@4.0.0-canary.72`, `@ai-sdk/otel@1.0.0-canary.117`, `@ai-sdk/provider-utils@5.0.0-canary.47`, `@ai-sdk/react@4.0.0-canary.174`) and the Workflow packages to the latest betas (`@workflow/core@5.0.0-beta.14`, `@workflow/world@5.0.0-beta.8`, `@workflow/world-local@5.0.0-beta.15`).
17
+ - 790865c: Bump the AI SDK to the latest canary releases: `ai@7.0.0-canary.169`, `@ai-sdk/anthropic@4.0.0-canary.64`, `@ai-sdk/mcp@2.0.0-canary.60`, `@ai-sdk/openai@4.0.0-canary.71`, `@ai-sdk/otel@1.0.0-canary.115`, and `@ai-sdk/react@4.0.0-canary.172`.
18
+ - 790865c: Empty-response recovery now also catches the AI SDK's `NoOutputGeneratedError` rejection (new in `ai@7.0.0-canary.169`): a model stream that closes without producing output is reissued once with the recovery nudge, as before, instead of failing the turn.
19
+ - 8507473: Update Workflow SDK beta packages and isolate Eve's workflow queue traffic behind the SDK's `eve` queue namespace so co-deployed apps can use their own Workflow output without topic collisions.
20
+ - 4408988: The one-shot "Next steps" note now lists the exact commands in execution order — `cd`, `pnpm install`, `vercel link` (or set `AI_GATEWAY_API_KEY` in `.env.local` manually), `eve dev` — with the commands in bold.
21
+ - f010437: Allow Next.js development integrations up to three minutes to start Eve by default, and support overriding the wait with the `withEve` `devServerTimeoutMs` option.
22
+
3
23
  ## 0.6.0-beta.12
4
24
 
5
25
  ### Minor Changes
@@ -824,8 +824,10 @@ pnpm --filter <fixture-app> exec eve eval --strict --json --url "$TARGET_URL"
824
824
  twice (direct / `EVE_EXPERIMENTAL_CODE_MODE=1` set by the provisioner),
825
825
  `fail-fast: false`, JUnit reporter for annotations. Per-eval artifacts under
826
826
  `.eve/evals/` upload on failure — strictly better debuggability than today's
827
- stdout scraping. A post-deploy leg is the same invocation pointed at a preview
828
- deployment; requirement-incompatible cases skip visibly.
827
+ stdout scraping. This phase-4 CI runs entirely on the runner (loopback
828
+ targets only); the remote leg — the same invocation pointed at a preview
829
+ deployment, with requirement-incompatible cases skipping visibly — is
830
+ Phase 5.
829
831
 
830
832
  ### What gets deleted (end state)
831
833
 
@@ -881,18 +883,53 @@ Each phase ships independently, keeps `pnpm test` green, and includes docs
881
883
  `e2e/provision/` scripts.
882
884
  11. `trials` + JUnit reporter.
883
885
 
884
- ### Phase 4 Migration and deletion
886
+ > **Descoped after implementation review (June 2026):** `trials` (and
887
+ > `--trials`), the public `eve/evals/environment` helpers, `target.info()`,
888
+ > and the `baseUrl` alias on targets were cut from v1 to shrink the public
889
+ > API. Phase 4 ports are mock-model deterministic and provisioners keep
890
+ > using the existing `e2e/lib` stub/probe helpers; revisit each only with
891
+ > concrete post-migration demand.
892
+
893
+ ### Phase 4 — Migration and deletion (local CI only)
894
+
895
+ Everything in this phase runs on the CI runner: provisioners build and start
896
+ fixture servers locally and point `eve eval --strict --url` at loopback
897
+ addresses. Nothing in phase 4 deploys anywhere.
885
898
 
886
899
  12. Port evals group by group in the order: `basic-runtime` → `tools` →
887
900
  `tools-hitl` → `subagents` → `schedules` → `channels` → `codemode` →
888
- `tools-sandbox`. Each ported group flips its CI matrix entry from
889
- `node e2e/tests/...` to provision + `eve eval --strict --url` in the same
890
- PR; both runners coexist until the last group lands.
901
+ `tools-sandbox` (plus `skills`, added after this table was written). Each
902
+ ported group flips its CI matrix entry from `node e2e/tests/...` to
903
+ provision + `eve eval --strict --url` in the same PR; both runners
904
+ coexist until the last group lands.
891
905
  13. Delete `e2e/tests/**` (minus `tui-client/`) and `ExampleClient`; retire
892
906
  area policy; shrink `e2e/lib`/`e2e/target` into `e2e/provision/`; update
893
907
  `e2e/README.md` and AGENTS.md smoke-test guidance to point at `eve eval`.
894
- 14. Optional follow-on: add a post-deploy `--url` leg against preview
895
- deployments for the requirement-compatible subset of fixture evals.
908
+
909
+ ### Phase 5 Remote leg: deploy fixtures and eval the deployment
910
+
911
+ After phase 4, CI gains a second e2e variant that runs the **same eval
912
+ files** against a real Vercel deployment. End state: two e2e legs — local
913
+ (provisioned on the runner) and remote (deployed preview) — sharing one
914
+ eval suite, differing only in target URL and which `requires`-gated cases
915
+ skip.
916
+
917
+ 15. Link the first fixture app (`agent-basic-runtime`) as a Vercel project;
918
+ preview env sets `EVE_MOCK_AUTHORED_MODELS=1` (determinism, zero model
919
+ spend) and the workflow backend credentials.
920
+ 16. CI job: deploy the preview, capture the URL, then
921
+ `eve eval --strict --json --junit ... --url "$DEPLOY_URL"` with
922
+ `VERCEL_AUTOMATION_BYPASS_SECRET` in the job env (the eval client's
923
+ existing remote-auth cascade handles protection bypass / OIDC). No
924
+ `--no-skips` on this leg: schedule evals (`devRoutes`) and local-sidecar
925
+ evals (`env:`-gated MCP stubs, fake channel providers) skip visibly.
926
+ 17. Expand fixture-by-fixture for the remote-eligible subset (basic-runtime,
927
+ tools, tools-hitl, codemode, skills). `defineState` persistence cases
928
+ need per-run unique keys before joining the remote leg — the deployed
929
+ store is shared across CI runs.
930
+ 18. Out of scope for phase 5: multi-agent remote topologies (two deployed
931
+ fixtures with hosts wired at deploy time) and remote channel evals;
932
+ revisit with demand.
896
933
 
897
934
  ## Breaking changes
898
935
 
@@ -18,7 +18,7 @@ export default defineAgent({
18
18
  });
19
19
  ```
20
20
 
21
- Compaction is also a hook point for tools. When the harness compacts history, it calls each tool's `onCompact(input, ctx)` in registration order, so a tool can re-inject the facts it needs to survive the summary: appending a short message, or patching session state. See [`onCompact`](./dynamic-capabilities) for the hook contract.
21
+ Compaction also preserves the framework's own tool state automatically. When the harness compacts history, it resets read-before-write tracking (so a write afterward re-reads the file whose read evidence was summarized away) and re-injects the active todo list, so the model keeps its task list across the summary. There is no per-tool hook to configure.
22
22
 
23
23
  ## Built-in tools
24
24
 
@@ -89,6 +89,6 @@ With it on, the model can orchestrate the agent's own subagents from model-autho
89
89
 
90
90
  ## What to read next
91
91
 
92
- - [Tools](../tools): define your own tools, gate them on approval, and shape their output (`toModelOutput` / `onCompact`)
92
+ - [Tools](../tools): define your own tools, gate them on approval, and shape their output with `toModelOutput`
93
93
  - [Dynamic capabilities](./dynamic-capabilities): generate the tool set per session with `defineDynamic`
94
94
  - [Sandbox](../sandbox): the sandbox the shell and file tools run in
@@ -33,7 +33,7 @@ export default defineEval({
33
33
  });
34
34
  ```
35
35
 
36
- Every eval needs `scores` (an empty array is fine) and either `cases` or `load`. The rest are optional: `description`, `task`, `checks`, `model`, `thresholds`, `modelOptions`, `tags`, `metadata`, `maxConcurrency`, `timeoutMs`, `reporters`. The init template adds `evals/**/*.ts` to `tsconfig.json`, so your eval code type-checks alongside the app.
36
+ Every eval needs `scores` (an empty array is fine) and either `cases` or `load`. The rest are optional: `description`, `task`, `checks`, `requires`, `model`, `thresholds`, `modelOptions`, `tags`, `metadata`, `maxConcurrency`, `timeoutMs`, `reporters`. The init template adds `evals/**/*.ts` to `tsconfig.json`, so your eval code type-checks alongside the app.
37
37
 
38
38
  `model` is only required when a model-backed scorer (one of the `Autoevals` wrappers) is present without its own per-scorer model override — and it's the scorer model, not the agent's. Eve only uses it for model-backed scoring, never to swap out the agent under test. Pass a string id (e.g. `"anthropic/claude-opus-4.8"`) to route through the Vercel AI Gateway, or hand it an AI SDK model instance to use that directly.
39
39
 
@@ -72,11 +72,13 @@ Checks.subagentCalled("weather", {
72
72
 
73
73
  A custom check is a plain function receiving `{ case, result, target }` and returning `{ name, passed, message? }`.
74
74
 
75
+ Note that `result.status` is `"waiting"` whenever the session is left open for a next message — the normal end state of a successful turn. Parking on unanswered HITL input is tracked separately as `result.derived.parked`, which is what `Checks.completed()` and `Checks.waiting()` key off.
76
+
75
77
  ## Cases and tasks
76
78
 
77
79
  A case is either a data case or a scripted case.
78
80
 
79
- Data cases pair an `input` with an `expected`, plus optional `checks`, `scores`, tags, and metadata. `input` can be a string or an object. `expected` is optional, which is handy when you only care about behavior. List cases inline, or load them dynamically:
81
+ Data cases pair an `input` with an `expected`, plus optional `checks`, `scores`, `requires`, tags, and metadata. `input` can be a string or an object. `expected` is optional, which is handy when you only care about behavior. List cases inline, or load them dynamically:
80
82
 
81
83
  ```ts
82
84
  import { defineEval } from "eve/evals";
@@ -122,7 +124,40 @@ export default defineEval({
122
124
  });
123
125
  ```
124
126
 
125
- `ctx.session` is the primary `EveEvalSession`; `ctx.newSession()` creates another independent session against the same target. `session.send()` accepts the same input as `ClientSession.send()`, `session.sendFile(text, path, mediaType?)` attaches a local file as a data URL, and `turn.expectOk()` throws only when the turn ended failed. Events from every eval session are captured in the case result and artifacts.
127
+ `ctx.session` is the primary `EveEvalSession`; `ctx.newSession()` creates another independent session against the same target. `session.send()` accepts the same input as `ClientSession.send()`, `session.sendFile(text, path, mediaType?)` attaches a local file as a data URL, and `turn.expectOk()` throws only when the turn ended failed. Events from every eval session are captured in the case result and artifacts. `ctx.log(message)` records debug lines into the case artifact; `--verbose` also streams them to stdout as cases run.
128
+
129
+ ## Targets and requirements
130
+
131
+ An eval target is always an HTTP URL. `eve eval` starts a local dev server, while `eve eval --url <url>` runs against an existing server or deployment. The runner polls `/eve/v1/health`, verifies `/eve/v1/info`, and exposes the live target as `ctx.target`:
132
+
133
+ ```ts
134
+ export default defineEval({
135
+ requires: ["mockModels", "devRoutes"],
136
+ scores: [],
137
+ cases: [
138
+ {
139
+ id: "heartbeat",
140
+ async run({ target }) {
141
+ const { sessionIds } = await target.dispatchSchedule("heartbeat");
142
+ const session = await target.attachSession(sessionIds[0]!);
143
+ return session.events;
144
+ },
145
+ },
146
+ ],
147
+ });
148
+ ```
149
+
150
+ `target.fetch(path, init)` performs an authenticated fetch against the target for channel/webhook ingress. `target.dispatchSchedule(id)` uses the dev-only schedule route, and `target.attachSession(sessionId, { startIndex? })` consumes one turn from a session created by a channel or schedule so its events participate in checks and scores.
151
+
152
+ Use `requires` to declare assumptions the runner verifies before executing a case:
153
+
154
+ | Requirement | Means |
155
+ | -------------- | --------------------------------------------------------------------- |
156
+ | `"mockModels"` | `/eve/v1/info` reports the deterministic mock model adapter is active |
157
+ | `"devRoutes"` | `/eve/v1/info` reports dev-only routes are mounted |
158
+ | `"env:NAME"` | The eval process has environment variable `NAME` set |
159
+
160
+ Eval-level requirements apply to every case; case-level requirements append. Unmet requirements produce a visible `skipped` verdict and do not affect the exit code. Pass `--no-skips` when a CI leg must prove full coverage. For local targets, `--mock-models` starts the dev server with deterministic authored models; it is invalid with `--url` because remote target capabilities are discovered, not set by the runner.
126
161
 
127
162
  ## Scorers and rubrics
128
163
 
@@ -158,7 +193,7 @@ defineEval({
158
193
 
159
194
  ## Reporters
160
195
 
161
- Eval-level reporters live on `eve/evals/reporters`. Right now the public surface is `Braintrust(...)`, which uploads eval results to Braintrust experiments. Eve still runs and scores everything itself; the reporter just ships the results out. Checks log as binary scores under a `check:` prefix so experiments diff check regressions the same way they diff score regressions. Eval and case `metadata` ride along to the reporter, and the CLI prints a console summary by default.
196
+ Eval-level reporters live on `eve/evals/reporters`. `Braintrust(...)` uploads eval results to Braintrust experiments, and `JUnit({ filePath })` writes JUnit XML for CI annotations. Eve still runs and scores everything itself; reporters just ship the results out. Checks log as binary scores under a `check:` prefix so experiments diff check regressions the same way they diff score regressions. Eval and case `metadata` ride along to reporters, and the CLI prints a console summary by default.
162
197
 
163
198
  ## Running evals
164
199
 
@@ -166,10 +201,14 @@ Eval-level reporters live on `eve/evals/reporters`. Right now the public surface
166
201
  eve eval # run all discovered evals locally
167
202
  eve eval weather smoke # run selected evals
168
203
  eve eval --url https://<app> # target a remote app instead of a local host
204
+ eve eval --mock-models # local dev target uses deterministic mock models
169
205
  eve eval --tag fast # only cases (or evals) carrying a tag
170
206
  eve eval --case brooklyn-forecast # only specific case ids
171
207
  eve eval --strict # below-threshold scores also fail the exit code
208
+ eve eval --no-skips # unmet requirements fail instead of skipping
209
+ eve eval --junit .eve/junit.xml # write JUnit XML
172
210
  eve eval --list # print discovered evals and cases without running
211
+ eve eval --verbose # stream per-case ctx.log lines to stdout
173
212
  eve eval --json # machine-readable output
174
213
  eve eval --skip-report # skip eval-defined reporters (e.g. Braintrust)
175
214
  ```
@@ -34,6 +34,15 @@ All fields are optional.
34
34
  | `eveBuildCommand` | `string` | `"eve build"` | Build command for the generated Eve Vercel service. Use it when the Eve service needs project-specific prework, without changing the Next.js build. |
35
35
  | `configureVercelOutput` | `boolean` | `true` | Set to `false` to skip creating or updating `.vercel/output/config.json`. By default `withEve` writes the `experimentalServices` entries for both apps. |
36
36
  | `servicePrefix` | `string` | `"/_eve_internal/eve"` | Private Vercel route namespace for the Eve service. Must match the Eve service's mount in your Vercel Build Output config when you set it manually. |
37
+ | `devServerTimeoutMs` | `number` | `180000` | Maximum time to wait for the Eve development server to become available. |
38
+
39
+ For unusually slow cold starts, increase the development timeout:
40
+
41
+ ```ts
42
+ export default withEve(nextConfig, {
43
+ devServerTimeoutMs: 300_000,
44
+ });
45
+ ```
37
46
 
38
47
  ## Call the hook
39
48
 
@@ -20,7 +20,7 @@ The fastest path is the `create` CLI. It scaffolds the project, prompts for a mo
20
20
  pnpm create eve@beta
21
21
  ```
22
22
 
23
- The wizard first asks how much to set up: a complete setup, or a one-shot scaffold (also available as `--one-shot`) that just writes the project files with the default model. The complete path asks for a model and which channel you want (Web Chat or Slack). You can skip both: every app ships the built-in HTTP channel (`agent/channels/eve.ts`) regardless. For a local chat it installs dependencies and starts the dev server for you.
23
+ The wizard first asks how much to set up: a complete setup, or a one-shot scaffold (also available as `--one-shot`) that just writes the project files with the default model. The complete path describes the agent first — a model, the channels you'll chat through (Web Chat or Slack; the CLI REPL is always available), and the connections it can reach — and only then asks where it should run: on Vercel, or locally for now. Picking Slack or a Connect-backed connection settles that question automatically, since both need a Vercel project, and scaffolding into a directory that is already linked to one (with a logged-in Vercel CLI) skips it too: the AI Gateway authenticates through your Vercel login. Every app ships the built-in HTTP channel (`agent/channels/eve.ts`) regardless of what you pick. For a local chat it installs dependencies and starts the dev server for you.
24
24
 
25
25
  To add Eve to an existing app instead:
26
26
 
@@ -99,10 +99,6 @@ toModelOutput(output) {
99
99
 
100
100
  It receives the full, typed `execute` return and only affects the model. Channel event handlers and hooks still get the full output on `action.result`, so a channel can render rich platform output (Slack Block Kit, say) the model never sees. Return `{ type: "text", value }` for a summary, or `{ type: "json", value }` for a smaller object.
101
101
 
102
- ## Survive compaction with `onCompact`
103
-
104
- When the harness [compacts history](./advanced/default-harness#compaction), it calls each tool's `onCompact(input, ctx)` in registration order and applies the merged result to the compacted session. Return nothing to leave things alone, `messages` to append to the compacted history, or a `sessionPatch` to shallow-merge into session state. It works on the projected output (what the model sees), and a throw fails the compaction step, so don't swallow errors.
105
-
106
102
  ## What to read next
107
103
 
108
104
  - [Skills](./skills): on-demand procedures the model loads when relevant
@@ -344,14 +344,7 @@ var ClientSession = class {
344
344
  stream(options) {
345
345
  const sessionId = this.#state.sessionId;
346
346
  if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
347
- return openStreamIterable({
348
- host: this.#context.host,
349
- maxReconnectAttempts: this.#context.maxReconnectAttempts,
350
- resolveHeaders: () => this.#context.resolveHeaders(),
351
- sessionId,
352
- signal: options?.signal,
353
- startIndex: options?.startIndex ?? this.#state.streamIndex
354
- });
347
+ return this.#streamAndAdvance(sessionId, options);
355
348
  }
356
349
  async #postTurn(input, session) {
357
350
  const routePath = session.sessionId ? createEveContinueSessionRoutePath(session.sessionId) : EVE_CREATE_SESSION_ROUTE_PATH;
@@ -422,6 +415,35 @@ var ClientSession = class {
422
415
  startIndex
423
416
  });
424
417
  }
418
+ async *#streamAndAdvance(sessionId, options) {
419
+ const initialState = this.#state;
420
+ const streamIndex = options?.startIndex ?? initialState.streamIndex;
421
+ const events = [];
422
+ try {
423
+ for await (const event of openStreamIterable({
424
+ host: this.#context.host,
425
+ maxReconnectAttempts: this.#context.maxReconnectAttempts,
426
+ resolveHeaders: () => this.#context.resolveHeaders(),
427
+ sessionId,
428
+ signal: options?.signal,
429
+ startIndex: streamIndex
430
+ })) {
431
+ events.push(event);
432
+ yield event;
433
+ }
434
+ } finally {
435
+ this.#state = advanceSession({
436
+ continuationToken: initialState.continuationToken,
437
+ events,
438
+ session: {
439
+ ...initialState,
440
+ sessionId,
441
+ streamIndex
442
+ },
443
+ sessionId
444
+ });
445
+ }
446
+ }
425
447
  };
426
448
  async function postTurnWithRetry(input) {
427
449
  const attempts = input.mustDeliver ? DELIVER_RETRY_ATTEMPTS : 1;
@@ -497,6 +519,14 @@ var Client = class {
497
519
  }
498
520
  return await response.json();
499
521
  }
522
+ async fetch(path, init = {}) {
523
+ const url = createClientUrl(this.#host, path);
524
+ const headers = await this.#resolveHeaders(headersInitToRecord(init.headers));
525
+ return await fetch(url, {
526
+ ...init,
527
+ headers
528
+ });
529
+ }
500
530
  session(state) {
501
531
  let resolved;
502
532
  if (typeof state === "string") resolved = {
@@ -541,6 +571,10 @@ async function resolveHeadersValue(value) {
541
571
  if (value === void 0) return {};
542
572
  return typeof value === "function" ? await value() : value;
543
573
  }
574
+ function headersInitToRecord(headers) {
575
+ if (headers === void 0) return {};
576
+ return Object.fromEntries(new Headers(headers).entries());
577
+ }
544
578
  function encodeBasicCredentials(username, password) {
545
579
  const bytes = new TextEncoder().encode(`${username}:${password}`);
546
580
  const binaryString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
@@ -344,14 +344,7 @@ var ClientSession = class {
344
344
  stream(options) {
345
345
  const sessionId = this.#state.sessionId;
346
346
  if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
347
- return openStreamIterable({
348
- host: this.#context.host,
349
- maxReconnectAttempts: this.#context.maxReconnectAttempts,
350
- resolveHeaders: () => this.#context.resolveHeaders(),
351
- sessionId,
352
- signal: options?.signal,
353
- startIndex: options?.startIndex ?? this.#state.streamIndex
354
- });
347
+ return this.#streamAndAdvance(sessionId, options);
355
348
  }
356
349
  async #postTurn(input, session) {
357
350
  const routePath = session.sessionId ? createEveContinueSessionRoutePath(session.sessionId) : EVE_CREATE_SESSION_ROUTE_PATH;
@@ -422,6 +415,35 @@ var ClientSession = class {
422
415
  startIndex
423
416
  });
424
417
  }
418
+ async *#streamAndAdvance(sessionId, options) {
419
+ const initialState = this.#state;
420
+ const streamIndex = options?.startIndex ?? initialState.streamIndex;
421
+ const events = [];
422
+ try {
423
+ for await (const event of openStreamIterable({
424
+ host: this.#context.host,
425
+ maxReconnectAttempts: this.#context.maxReconnectAttempts,
426
+ resolveHeaders: () => this.#context.resolveHeaders(),
427
+ sessionId,
428
+ signal: options?.signal,
429
+ startIndex: streamIndex
430
+ })) {
431
+ events.push(event);
432
+ yield event;
433
+ }
434
+ } finally {
435
+ this.#state = advanceSession({
436
+ continuationToken: initialState.continuationToken,
437
+ events,
438
+ session: {
439
+ ...initialState,
440
+ sessionId,
441
+ streamIndex
442
+ },
443
+ sessionId
444
+ });
445
+ }
446
+ }
425
447
  };
426
448
  async function postTurnWithRetry(input) {
427
449
  const attempts = input.mustDeliver ? DELIVER_RETRY_ATTEMPTS : 1;
@@ -497,6 +519,14 @@ var Client = class {
497
519
  }
498
520
  return await response.json();
499
521
  }
522
+ async fetch(path, init = {}) {
523
+ const url = createClientUrl(this.#host, path);
524
+ const headers = await this.#resolveHeaders(headersInitToRecord(init.headers));
525
+ return await fetch(url, {
526
+ ...init,
527
+ headers
528
+ });
529
+ }
500
530
  session(state) {
501
531
  let resolved;
502
532
  if (typeof state === "string") resolved = {
@@ -541,6 +571,10 @@ async function resolveHeadersValue(value) {
541
571
  if (value === void 0) return {};
542
572
  return typeof value === "function" ? await value() : value;
543
573
  }
574
+ function headersInitToRecord(headers) {
575
+ if (headers === void 0) return {};
576
+ return Object.fromEntries(new Headers(headers).entries());
577
+ }
544
578
  function encodeBasicCredentials(username, password) {
545
579
  const bytes = new TextEncoder().encode(`${username}:${password}`);
546
580
  const binaryString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
@@ -1 +1 @@
1
- import{basename}from"node:path";import{isEveProject}from"#setup/scaffold/index.js";import{headlessAsker,interactiveAsker}from"#setup/ask.js";import{addChannels}from"#setup/boxes/add-channels.js";import{deployProject}from"#setup/boxes/deploy-project.js";import{selectChannels}from"#setup/boxes/select-channels.js";import{detectDeployment,projectResolutionFromDeployment}from"#setup/project-resolution.js";import{createPrompter}from"#setup/prompter.js";import{runHeadless,runInteractive}from"#setup/runner.js";import{createDefaultSetupState,snapshotSetupState}from"#setup/state.js";import{whimsyFor}from"#setup/cli/index.js";import{composeOnboardingBoxes}from"#setup/onboarding.js";const defaultDependencies={createPrompter,detectDeployment,isEveProject,hasInteractiveTerminal:()=>!!(process.stdin.isTTY&&process.stdout.isTTY)};async function runSetupCommand(t,n,r,i=defaultDependencies){let a=!await i.isEveProject(n),o=r.evePackageVersion??`beta`,s=r.presets??{},c=r.headless!==!0;if(c&&!i.hasInteractiveTerminal()){t.error("eve setup is interactive and needs a terminal. For automation, use `create-eve --headless` to scaffold a new agent or `eve channels add` inside an existing project."),process.exitCode=1;return}let l=i.createPrompter(),u={write:e=>l.log.message(e)};l.intro(a?`Create an 𝐞𝐯𝐞 agent`:`Set-up your 𝐞𝐯𝐞 agent`);let d=a?`Agent created.`:`Setup complete.`,f,p;a?(f=createDefaultSetupState(),p=composeOnboardingBoxes({prompter:l,presetName:s.presetName,presetMode:s.presetMode,presetModel:s.presetModel,presetChannels:s.presetChannels,presetConnections:s.presetConnections,presetCreateSlackbot:s.presetCreateSlackbot,provisioning:r.provisioning,presetChatPreference:s.presetChatPreference??`skip`,targetDirectory:n,inPlace:!c,overwriteExisting:s.overwriteExisting,presetNoDeploy:s.presetNoDeploy,headless:!c,evePackageVersion:o})):(l.log.message(whimsyFor(`project-detect`)),f={...createDefaultSetupState(),project:projectResolutionFromDeployment(await i.detectDeployment(n)),agentName:basename(n),projectPath:{kind:`resolved`,inPlace:!0,path:n}},p=[selectChannels({asker:c?interactiveAsker(l):headlessAsker(),presetChannels:s.presetChannels}),addChannels({asker:c?interactiveAsker(l):headlessAsker(),prompter:l,evePackageVersion:o,presetCreateSlackbot:s.presetCreateSlackbot,headless:!c,slackbotFailure:`warn-and-continue`}),deployProject({prompter:l,skip:s.presetNoDeploy,headless:!c})]);try{if(c){let e=await runInteractive(p,f,u,{snapshot:snapshotSetupState});l.outro(e.kind===`cancelled`?`Cancelled.`:d);return}await runHeadless(p,f,u,{snapshot:snapshotSetupState}),l.outro(d)}catch(e){t.error(e instanceof Error?e.message:String(e)),process.exitCode=1}}export{runSetupCommand};
1
+ import{basename}from"node:path";import{isEveProject}from"#setup/scaffold/index.js";import{headlessAsker,interactiveAsker}from"#setup/ask.js";import{addChannels}from"#setup/boxes/add-channels.js";import{deployProject}from"#setup/boxes/deploy-project.js";import{selectChannels}from"#setup/boxes/select-channels.js";import{detectDeployment,projectResolutionFromDeployment}from"#setup/project-resolution.js";import{createPrompter}from"#setup/prompter.js";import{runHeadless,runInteractive}from"#setup/runner.js";import{createDefaultSetupState,snapshotSetupState}from"#setup/state.js";import{whimsyFor}from"#setup/cli/index.js";import{composeOnboardingBoxes}from"#setup/onboarding.js";const defaultDependencies={createPrompter,detectDeployment,isEveProject,hasInteractiveTerminal:()=>!!(process.stdin.isTTY&&process.stdout.isTTY)};async function runSetupCommand(t,n,r,i=defaultDependencies){let a=!await i.isEveProject(n),o=r.evePackageVersion??`beta`,s=r.presets??{},c=r.headless!==!0;if(c&&!i.hasInteractiveTerminal()){t.error("eve setup is interactive and needs a terminal. For automation, use `create-eve --headless` to scaffold a new agent or `eve channels add` inside an existing project."),process.exitCode=1;return}let l=i.createPrompter(),u={write:e=>l.log.message(e)};l.intro(a?`Create an 𝐞𝐯𝐞 agent`:`Set-up your 𝐞𝐯𝐞 agent`);let d=a?`Agent created.`:`Setup complete.`,f,p;a?(f=createDefaultSetupState(),p=composeOnboardingBoxes({prompter:l,presetName:s.presetName,presetMode:s.presetMode,presetModel:s.presetModel,presetChannels:s.presetChannels,presetConnections:s.presetConnections,presetCreateSlackbot:s.presetCreateSlackbot,provisioning:r.provisioning,presetChatPreference:s.presetChatPreference??`skip`,targetDirectory:n,inPlace:!c,overwriteExisting:s.overwriteExisting,presetNoDeploy:s.presetNoDeploy,headless:!c,evePackageVersion:o})):(l.log.message(whimsyFor(`project-detect`)),f={...createDefaultSetupState(),project:projectResolutionFromDeployment(await i.detectDeployment(n)),agentName:basename(n),projectPath:{kind:`resolved`,inPlace:!0,path:n}},p=[selectChannels({asker:c?interactiveAsker(l):headlessAsker(),presetChannels:s.presetChannels,variant:`in-project`}),addChannels({asker:c?interactiveAsker(l):headlessAsker(),prompter:l,evePackageVersion:o,presetCreateSlackbot:s.presetCreateSlackbot,headless:!c,slackbotFailure:`warn-and-continue`}),deployProject({prompter:l,skip:s.presetNoDeploy,headless:!c})]);try{if(c){let e=await runInteractive(p,f,u,{snapshot:snapshotSetupState});l.outro(e.kind===`cancelled`?`Cancelled.`:d);return}await runHeadless(p,f,u,{snapshot:snapshotSetupState}),l.outro(d)}catch(e){t.error(e instanceof Error?e.message:String(e)),process.exitCode=1}}export{runSetupCommand};
@@ -109,7 +109,8 @@ export type AgentTUIRenderer = {
109
109
  /**
110
110
  * Commits a startup header describing the connected agent (brand mark,
111
111
  * model, instructions, tools, skills, subagents) to the transcript before
112
- * the first prompt. Optional renderers without a header simply skip it.
112
+ * the first prompt, and refreshes it after local dev artifact changes.
113
+ * Optional — renderers without a header simply skip it.
113
114
  */
114
115
  renderAgentHeader?(header: AgentTUIAgentHeader): void;
115
116
  /**
@@ -1 +1 @@
1
- import{failureKey,formatFailureDetail,formatFailureMessage,isAbortLikeError,isInterruptedError}from"./errors.js";import{TerminalRenderer}from"./terminal-renderer.js";import{toErrorMessage}from"#shared/errors.js";import{createDevelopmentRuntimeArtifactSessionRefresher}from"#services/dev-client.js";import{isCurrentTurnBoundaryEvent}from"#client/index.js";var EveTUIRunner=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u;#d;#f;#p=new Map;#m=new Map;#h=new Map;#g=new Map;#_=new Set;#v=!1;constructor(e){this.#e=e.session,e.client!==void 0&&(this.#t=e.client),this.#n=createRenderer(e),this.#r=e.name??`Eve`,this.#i=e.tools??`full`,this.#a=e.reasoning??`full`,this.#o=e.subagents??`full`,this.#s=e.connectionAuth??`full`,this.#c=e.assistantResponseStats??`tokensPerSecond`,this.#l=e.contextSize,this.#u=e.formatTransportError??toErrorMessage,e.serverUrl!==void 0&&(this.#f=e.serverUrl,this.#d=createDevelopmentRuntimeArtifactSessionRefresher({serverUrl:e.serverUrl}))}async#y(){if(!this.#n.renderAgentHeader)return;let e=this.#f;if(e===void 0)return;let t;try{t=await this.#t?.info()}catch{t=void 0}let n={name:this.#r,serverUrl:e};t!==void 0&&(n.info=t),this.#n.renderAgentHeader(n)}async run(){let e=this.#r,t,n,r=!1,a=!1;for(await this.#y();;){if(!a){if(t==null){if(!this.#n.readPrompt){if(r)return;throw Error(`No prompt was provided and the renderer does not support prompt input.`)}try{t=await this.#n.readPrompt({title:e})}catch(e){if(isInterruptedError(e))return;throw e}if(t==null)return}let o=parsePromptCommand(t);if(o===`exit`){this.#n.shutdown?.();return}if(o===`new`){this.#b(),n=void 0,a=!1,t=void 0,this.#n.reset?.();continue}r=!0}let o=await this.#x({prompt:a?void 0:t,inputResponses:n});try{await this.#n.renderStream(o,{title:e,submittedPrompt:t,continueSession:!!this.#n.readPrompt,tools:this.#i,reasoning:this.#a,subagents:this.#o,connectionAuth:this.#s,assistantResponseStats:this.#c,contextSize:this.#l});let r=o.turnState?.pendingApprovals??[],i=o.turnState?.pendingQuestions??[];if(r.length>0||i.length>0){let o=[];if(r.length>0){if(!this.#n.readToolApproval)throw Error(`Tool approval was requested, but the renderer does not support tool approval input.`);for(let t of r){let n=await this.#n.readToolApproval(t,{title:e});o.push({requestId:t.approvalId,optionId:n.approved?`approve`:`deny`}),this.#p.delete(t.approvalId)}}if(i.length>0){if(!this.#n.readInputQuestion)throw Error(`An interactive question was requested, but the renderer does not support input questions.`);for(let t of i){let n=toAgentTUIInputQuestion(t),r=await this.#n.readInputQuestion(n,{title:e});if(r===void 0)continue;let i={requestId:t.requestId};r.optionId!==void 0&&(i.optionId=r.optionId),r.text!==void 0&&(i.text=r.text),o.push(i),this.#p.delete(t.requestId)}}a=!0,n=o,t=void 0;continue}o.turnState&&o.turnState.boundaryEvent===void 0&&(this.#v=!0)}catch(e){if(isInterruptedError(e))return;throw e}a=!1,n=void 0,t=void 0,this.#v&&(this.#v=!1,this.#b(),this.#n.renderNotice?.(`Session ended — started a new session. Earlier context was cleared.`))}}#b(){for(let e of this.#h.values())e.abort();this.#h.clear(),this.#m.clear(),this.#p.clear(),this.#g.clear(),this.#_.clear(),this.#t&&(this.#e=this.#t.session()),this.#d?.clear()}async#x(e){let t={};e.prompt!==void 0&&(t.message=e.prompt),e.inputResponses!==void 0&&e.inputResponses.length>0&&(t.inputResponses=e.inputResponses);let n;try{let e=this.#t;e!==void 0&&this.#d!==void 0&&(this.#e=await this.#d.refresh({createSession:()=>e.session(),inputResponses:t.inputResponses,message:t.message,session:this.#e})),n=await this.#e.send(t)}catch(e){if(isInterruptedError(e))throw e;return this.#v=!0,{events:errorOnlyTUIStream({errorText:this.#u(e)}),turnState:createTurnState()}}let r=createTurnState();return{events:eveEventsToTUIStream({events:n,pendingInputRequests:this.#p,subagentRuns:this.#m,turnState:r,onSubagentCalled:e=>this.#T(e),onSubagentCompleted:e=>this.#D(e),onConnectionAuthRequired:e=>this.#S(e),onConnectionAuthCompleted:e=>this.#C(e),onTerminalFailure:()=>{this.#v=!0}}),turnState:r}}#S(e){let t={name:e.data.name,description:e.data.description,state:`required`};e.data.authorization!==void 0&&(t.challenge=e.data.authorization),e.data.webhookUrl!==void 0&&(t.webhookUrl=e.data.webhookUrl),this.#g.set(e.data.name,t),this.#w(t)}#C(e){let t=this.#g.get(e.data.name)??{name:e.data.name,description:``,state:e.data.outcome};t.state=e.data.outcome,e.data.reason!==void 0&&(t.reason=e.data.reason),this.#g.set(e.data.name,t),this.#_.delete(e.data.name),this.#w(t),this.#n.setConnectionAuthPendingCount?.(this.#_.size)}#w(e){let t={name:e.name,description:e.description,state:e.state};e.challenge!==void 0&&(t.challenge=e.challenge),e.reason!==void 0&&(t.reason=e.reason),this.#n.upsertConnectionAuth?.(t)}#T(e){let t=e.data.callId;if(this.#h.has(t))return;let n=this.#t;if(!n)return;let i=new AbortController;this.#h.set(t,i),(async()=>{try{let r=n.session({sessionId:e.data.childSessionId,streamIndex:0}).stream({signal:i.signal});for await(let e of r)if(i.signal.aborted||(this.#O(t,e),isCurrentTurnBoundaryEvent(e)))break}catch(e){if(!isAbortLikeError(e)){let n=toErrorMessage(e),r=this.#m.get(t);if(r){let{key:e,step:i}=openCurrentSubagentSection(r);i.message=i.message?`${i.message}\n\nstream error: ${n}`:`stream error: ${n}`,i.finalized=!0,r.currentSectionKey=null,this.#n.upsertSubagentStep?.({callId:t,subagentName:r.name,sectionKey:e,reasoning:i.reasoning,message:i.message,finalized:!0})}}}finally{this.#h.delete(t)}})()}#E(e,t,n){let r=t.tools.get(n.childCallId),i=r??{toolName:n.toolName,input:n.input,status:n.status};if(r){let e={"approval-requested":0,executing:1,done:2,failed:2};e[n.status]>e[r.status]&&(r.status=n.status),r.input=n.input}else t.tools.set(n.childCallId,i);this.#n.markChildToolCallId?.(n.childCallId),this.#n.upsertSubagentTool?.({callId:e,subagentName:t.name,childCallId:n.childCallId,toolName:i.toolName,input:i.input,status:i.status})}#D(e){let t=this.#m.get(e);if(t){for(let[n,r]of t.steps)r.finalized||(r.finalized=!0,this.#n.upsertSubagentStep?.({callId:e,subagentName:t.name,sectionKey:n,reasoning:r.reasoning,message:r.message,finalized:!0}));t.currentSectionKey=null}}#O(e,t){let n=this.#m.get(e);if(!n)return;let r=this.#n,emit=(t,i)=>{r.upsertSubagentStep?.({callId:e,subagentName:n.name,sectionKey:t,reasoning:i.reasoning,message:i.message,finalized:i.finalized})},finalizeCurrent=()=>{if(n.currentSectionKey===null)return;let e=n.steps.get(n.currentSectionKey);e&&(e.finalized=!0,emit(n.currentSectionKey,e)),n.currentSectionKey=null};switch(t.type){case`reasoning.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.reasoning+=t.data.reasoningDelta,emit(e,r);break}case`reasoning.completed`:break;case`message.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.message+=t.data.messageDelta,emit(e,r);break}case`message.completed`:{let{key:e,step:r}=openCurrentSubagentSection(n);t.data.message!==null&&r.message.length===0&&(r.message=t.data.message),r.finalized=!0,emit(e,r),n.currentSectionKey=null;break}case`step.completed`:finalizeCurrent();break;case`actions.requested`:finalizeCurrent();for(let r of t.data.actions)r.kind===`tool-call`&&this.#E(e,n,{childCallId:r.callId,toolName:r.toolName,input:r.input,status:`executing`});break;case`input.requested`:finalizeCurrent();for(let r of t.data.requests)r.action.kind===`tool-call`&&this.#E(e,n,{childCallId:r.action.callId,toolName:r.action.toolName,input:r.action.input,status:`approval-requested`});break;case`action.result`:{let i=t.data.result;if(i.kind!==`tool-result`)break;let a=n.tools.get(i.callId);if(!a)break;t.data.status===`failed`?(a.status=`failed`,a.errorText=formatActionResultError(t)):(a.status=`done`,a.output=i.output);let o={callId:e,subagentName:n.name,childCallId:i.callId,toolName:a.toolName,input:a.input,status:a.status};a.output!==void 0&&(o.output=a.output),a.errorText!==void 0&&(o.errorText=a.errorText),r.upsertSubagentTool?.(o);break}default:break}}};function createRenderer(e){return e.renderer?e.renderer:new TerminalRenderer({tools:e.tools,reasoning:e.reasoning,subagents:e.subagents,connectionAuth:e.connectionAuth,assistantResponseStats:e.assistantResponseStats,contextSize:e.contextSize,logs:e.logs,input:e.userInput,output:e.screen})}async function*eveEventsToTUIStream(e){let{events:t,pendingInputRequests:n,subagentRuns:r,turnState:i,onSubagentCalled:a,onSubagentCompleted:o,onConnectionAuthRequired:s,onConnectionAuthCompleted:c,onTerminalFailure:l}=e,u=new Map,d=new Map,f=0,p=new Set,m=new Set,h=new Set,g=new Set,_=!1,v=!1,y;for await(let e of t)if(!(v&&isPostTurnVisibleEvent(e)))switch(e.type){case`session.started`:case`turn.started`:case`message.received`:break;case`step.started`:f+=1,yield{type:`step-start`};break;case`step.completed`:{let t=e;y=t.data.usage,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`step-finish`,usage:t.data.usage};break}case`message.appended`:{let t=e,n=textPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(u,n),i=t.data.messageSoFar;if(r.completed){if(r.text.startsWith(i)||f<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`assistant-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`message.completed`:{let t=textPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(u,t),r=e.data.message;if(n.completed){if(r===null||r===n.text||f<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=f,yield{type:`assistant-complete`,id:partGenerationId(t,n.generation),text:r};break}let i=partGenerationId(t,n.generation);if(r!==null){if(n.text.length===0)n.text=r,n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i,text:r};else if(r.startsWith(n.text)){let e=r.slice(n.text.length);e.length>0&&(yield{type:`assistant-delta`,id:i,delta:e}),n.text=r,n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i}}}else n.text.length>0&&(n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i});break}case`reasoning.appended`:{let t=e,n=reasoningPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(d,n),i=t.data.reasoningSoFar;if(r.completed){if(r.text.startsWith(i)||f<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`reasoning-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`reasoning.completed`:{let t=reasoningPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(d,t),r=e.data.reasoning;if(n.completed){if(r.length===0||r===n.text||n.text.startsWith(r)||f<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=f;let e=partGenerationId(t,n.generation);yield{type:`reasoning-delta`,id:e,delta:r},yield{type:`reasoning-complete`,id:e};break}let i=partGenerationId(t,n.generation);if(n.text.length===0&&r.length>0)n.text=r,yield{type:`reasoning-delta`,id:i,delta:r};else if(r.length>0&&!r.startsWith(n.text))break;n.completed=!0,n.completedEpoch=f,yield{type:`reasoning-complete`,id:i};break}case`actions.requested`:{let t=e.data,n=t.actions.filter(e=>e.kind===`tool-call`);if(n.length===0)break;let r=toolBatchKey(`actions.requested`,t.turnId,t.stepIndex,n);if(h.has(r)){for(let e of n)p.has(e.callId)||m.add(e.callId);break}h.add(r);for(let e of n)p.has(e.callId)||(p.add(e.callId),yield{type:`tool-call`,toolCallId:e.callId,toolName:e.toolName,input:e.input});break}case`input.requested`:{let t=e.data,r=t.requests.filter(e=>e.action.kind===`tool-call`);if(r.length===0)break;let a=inputRequestBatchKey(t.turnId,t.stepIndex,r);if(h.has(a)){for(let e of r)p.has(e.action.callId)||m.add(e.action.callId);break}h.add(a);for(let e of r){let t=e.action.callId;if(p.has(t)||(p.add(t),yield{type:`tool-call`,toolCallId:t,toolName:e.action.toolName,input:e.action.input}),n.set(e.requestId,e),isQuestionRequest(e)){upsertPendingQuestion(i,e);continue}upsertPendingApproval(i,e),yield{type:`tool-approval-request`,approvalId:e.requestId,toolCallId:t}}break}case`action.result`:{let t=e;if(t.data.result.kind!==`tool-result`)break;let n=t.data.result.callId;if(m.has(n)||!p.has(n))break;t.data.status===`failed`?yield{type:`tool-error`,toolCallId:n,errorText:formatActionResultError(t)}:yield{type:`tool-result`,toolCallId:n,output:t.data.result.output};break}case`step.failed`:case`turn.failed`:{let t=toFailureEvent(e,g);t&&(yield t);break}case`session.failed`:{i.sawSessionFailure=!0,l?.(e);let t=toFailureEvent(e,g);t&&(yield t),i.boundaryEvent=e.type,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y},_=!0;return}case`session.waiting`:case`session.completed`:i.boundaryEvent=e.type,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y},_=!0;return;case`turn.completed`:v=!0,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f);break;case`subagent.called`:{let t=e;if(!r.has(t.data.callId))r.set(t.data.callId,{name:t.data.name,steps:new Map,currentSectionKey:null,nextSectionKey:0,tools:new Map});else{let e=r.get(t.data.callId);e&&(e.name=t.data.name)}a?.(t);break}case`subagent.started`:case`subagent.event`:break;case`subagent.completed`:o?.(e.data.callId);break;case`authorization.required`:s?.(e);break;case`authorization.completed`:c?.(e);break;default:break}_||(yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y})}async function*errorOnlyTUIStream(e){yield{type:`error`,errorText:e.errorText},yield{type:`finish`}}function createTurnState(){return{pendingApprovals:[],pendingQuestions:[],sawSessionFailure:!1}}function upsertPendingApproval(e,t){let n=toAgentTUIToolApprovalRequest(t),r=e.pendingApprovals.findIndex(e=>e.approvalId===n.approvalId);r===-1?e.pendingApprovals.push(n):e.pendingApprovals[r]=n}function toAgentTUIToolApprovalRequest(e){return{approvalId:e.requestId,toolCallId:e.action.callId,toolName:e.action.toolName,input:e.action.input}}function upsertPendingQuestion(e,t){let n=e.pendingQuestions.findIndex(e=>e.requestId===t.requestId);n===-1?e.pendingQuestions.push(t):e.pendingQuestions[n]=t}function textPartId(e,t){return`text:${e}:${t}`}function reasoningPartId(e,t){return`reasoning:${e}:${t}`}function partStateFor(e,t){let n=e.get(t);return n===void 0&&(n={generation:0,text:``,completed:!1,completedEpoch:0},e.set(t,n)),n}function partGenerationId(e,t){return t===0?e:`${e}#${t}`}function*closeOpenParts(e,t,n){for(let[r,i]of e)i.completed||i.text.length===0||(i.completed=!0,i.completedEpoch=n,yield{type:t,id:partGenerationId(r,i.generation)})}function isPostTurnVisibleEvent(e){switch(e.type){case`action.result`:case`actions.requested`:case`authorization.completed`:case`authorization.required`:case`input.requested`:case`message.appended`:case`message.completed`:case`reasoning.appended`:case`reasoning.completed`:case`result.completed`:case`step.completed`:case`step.failed`:case`step.started`:case`subagent.called`:case`subagent.completed`:case`subagent.event`:case`subagent.started`:case`turn.completed`:case`turn.failed`:return!0;default:return!1}}function toolBatchKey(e,t,n,r){return`${e}:${t}:${String(n)}:${stableStringify(r.map(e=>({input:e.input,toolName:e.toolName})))}`}function inputRequestBatchKey(e,t,n){return toolBatchKey(`input.requested`,e,t,n.map(e=>({input:e.action.input,toolName:e.action.toolName})))}function stableStringify(e){return JSON.stringify(toStableJson(e))??`undefined`}function toStableJson(e,t=new WeakSet){if(typeof e!=`object`||!e)return e;if(t.has(e))return`[Circular]`;if(t.add(e),Array.isArray(e))return e.map(e=>toStableJson(e,t));let n=e,r={};for(let e of Object.keys(n).sort())r[e]=toStableJson(n[e],t);return r}function formatActionResultError(e){if(e.data.error?.message)return e.data.error.message;let t=e.data.result.output;if(typeof t==`string`)return t;try{return JSON.stringify(t)}catch{return`Tool execution failed.`}}function toFailureEvent(r,i){let a=failureKey(r);if(i.has(a))return;i.add(a);let o={type:`error`,errorText:formatFailureMessage(r)},s=formatFailureDetail(r);return s!==void 0&&(o.detail=s),o}function isQuestionRequest(e){return e.display===`select`||e.display===`text`?!0:e.display===`confirmation`?!1:e.options!==void 0&&e.options.length>0}function toAgentTUIInputQuestion(e){let t=e.display===`text`?`text`:e.display===`select`||e.options!==void 0&&e.options.length>0?`select`:`text`,n={requestId:e.requestId,prompt:e.prompt,display:t};return e.options!==void 0&&(n.options=e.options.map(e=>{let t={id:e.id,label:e.label};return e.description!==void 0&&(t.description=e.description),e.style!==void 0&&(t.style=e.style),t})),e.allowFreeform!==void 0&&(n.allowFreeform=e.allowFreeform),n}function parsePromptCommand(e){let t=e.trim();return t===`/new`?`new`:t===`/exit`||t===`/quit`?`exit`:null}function openCurrentSubagentSection(e){e.currentSectionKey===null&&(e.currentSectionKey=e.nextSectionKey++,e.steps.set(e.currentSectionKey,{reasoning:``,message:``,finalized:!1}));let t=e.steps.get(e.currentSectionKey);if(!t)throw Error(`invariant: subagent section state missing for current key`);return{key:e.currentSectionKey,step:t}}export{EveTUIRunner};
1
+ import{failureKey,formatFailureDetail,formatFailureMessage,isAbortLikeError,isInterruptedError}from"./errors.js";import{TerminalRenderer}from"./terminal-renderer.js";import{toErrorMessage}from"#shared/errors.js";import{createDevelopmentRuntimeArtifactSessionRefresher}from"#services/dev-client.js";import{isCurrentTurnBoundaryEvent}from"#client/index.js";var EveTUIRunner=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u;#d;#f;#p;#m=new Map;#h=new Map;#g=new Map;#_=new Map;#v=new Set;#y=!1;constructor(e){this.#e=e.session,e.client!==void 0&&(this.#t=e.client),this.#n=createRenderer(e),this.#r=e.name??`Eve`,this.#i=e.tools??`full`,this.#a=e.reasoning??`full`,this.#o=e.subagents??`full`,this.#s=e.connectionAuth??`full`,this.#c=e.assistantResponseStats??`tokensPerSecond`,this.#l=e.contextSize,this.#u=e.formatTransportError??toErrorMessage,e.serverUrl!==void 0&&(this.#f=e.serverUrl,this.#d=createDevelopmentRuntimeArtifactSessionRefresher({serverUrl:e.serverUrl}))}async#b(){if(!this.#n.renderAgentHeader)return;let e=this.#f;if(e===void 0)return;let t;try{t=await this.#t?.info()}catch{t=void 0}this.#p=t;let n={name:this.#r,serverUrl:e};t!==void 0&&(n.info=t),this.#n.renderAgentHeader(n)}async run(){let e=this.#r,t,n,r=!1,a=!1;for(await this.#b();;){if(!a){if(t==null){if(!this.#n.readPrompt){if(r)return;throw Error(`No prompt was provided and the renderer does not support prompt input.`)}try{t=await this.#S({title:e})}catch(e){if(isInterruptedError(e))return;throw e}if(t==null)return}let o=parsePromptCommand(t);if(o===`exit`){this.#n.shutdown?.();return}if(o===`new`){this.#x(),n=void 0,a=!1,t=void 0,this.#n.reset?.();continue}r=!0}let o=await this.#C({prompt:a?void 0:t,inputResponses:n});try{await this.#n.renderStream(o,{title:e,submittedPrompt:t,continueSession:!!this.#n.readPrompt,tools:this.#i,reasoning:this.#a,subagents:this.#o,connectionAuth:this.#s,assistantResponseStats:this.#c,contextSize:this.#l});let r=o.turnState?.pendingApprovals??[],i=o.turnState?.pendingQuestions??[];if(r.length>0||i.length>0){let o=[];if(r.length>0){if(!this.#n.readToolApproval)throw Error(`Tool approval was requested, but the renderer does not support tool approval input.`);for(let t of r){let n=await this.#n.readToolApproval(t,{title:e});o.push({requestId:t.approvalId,optionId:n.approved?`approve`:`deny`}),this.#m.delete(t.approvalId)}}if(i.length>0){if(!this.#n.readInputQuestion)throw Error(`An interactive question was requested, but the renderer does not support input questions.`);for(let t of i){let n=toAgentTUIInputQuestion(t),r=await this.#n.readInputQuestion(n,{title:e});if(r===void 0)continue;let i={requestId:t.requestId};r.optionId!==void 0&&(i.optionId=r.optionId),r.text!==void 0&&(i.text=r.text),o.push(i),this.#m.delete(t.requestId)}}a=!0,n=o,t=void 0;continue}o.turnState&&o.turnState.boundaryEvent===void 0&&(this.#y=!0)}catch(e){if(isInterruptedError(e))return;throw e}a=!1,n=void 0,t=void 0,this.#y&&(this.#y=!1,this.#x(),this.#n.renderNotice?.(`Session ended — started a new session. Earlier context was cleared.`))}}#x(){for(let e of this.#g.values())e.abort();this.#g.clear(),this.#h.clear(),this.#m.clear(),this.#_.clear(),this.#v.clear(),this.#t&&(this.#e=this.#t.session()),this.#d?.clear()}async#S(e){if(!this.#n.readPrompt)return;let t=this.#n.readPrompt(e),n=this.#t,r=this.#d;if(n===void 0||r===void 0)return await t;let i=!1,a=!1,o,refresh=async()=>{if(!(i||a)){a=!0;try{this.#e=await r.refreshIdle({createSession:()=>n.session(),onRuntimeArtifactsChanged:()=>this.#w(),session:this.#e})}finally{a=!1}}},startRefresh=()=>{if(i||a)return;let e=refresh().finally(()=>{o===e&&(o=void 0)});o=e};startRefresh();let s=setInterval(()=>{startRefresh()},500);s.unref?.();try{return await t}finally{i=!0,clearInterval(s),await o}}async#C(e){let t={};e.prompt!==void 0&&(t.message=e.prompt),e.inputResponses!==void 0&&e.inputResponses.length>0&&(t.inputResponses=e.inputResponses);let n;try{let e=this.#t;e!==void 0&&this.#d!==void 0&&(this.#e=await this.#d.refresh({createSession:()=>e.session(),inputResponses:t.inputResponses,message:t.message,onRuntimeArtifactsChanged:()=>this.#w(),session:this.#e})),n=await this.#e.send(t)}catch(e){if(isInterruptedError(e))throw e;return this.#y=!0,{events:errorOnlyTUIStream({errorText:this.#u(e)}),turnState:createTurnState()}}let r=createTurnState();return{events:eveEventsToTUIStream({events:n,pendingInputRequests:this.#m,subagentRuns:this.#h,turnState:r,onSubagentCalled:e=>this.#O(e),onSubagentCompleted:e=>this.#A(e),onConnectionAuthRequired:e=>this.#T(e),onConnectionAuthCompleted:e=>this.#E(e),onTerminalFailure:()=>{this.#y=!0}}),turnState:r}}async#w(){let e=this.#p,t;try{t=await this.#t?.info()}catch{t=void 0}t!==void 0&&(this.#p=t,this.#f!==void 0&&this.#n.renderAgentHeader?.({info:t,name:this.#r,serverUrl:this.#f})),(!this.#n.renderAgentHeader||t===void 0)&&this.#n.renderNotice?.(formatAgentUpdateNotice(e,t))}#T(e){let t={name:e.data.name,description:e.data.description,state:`required`};e.data.authorization!==void 0&&(t.challenge=e.data.authorization),e.data.webhookUrl!==void 0&&(t.webhookUrl=e.data.webhookUrl),this.#_.set(e.data.name,t),this.#D(t)}#E(e){let t=this.#_.get(e.data.name)??{name:e.data.name,description:``,state:e.data.outcome};t.state=e.data.outcome,e.data.reason!==void 0&&(t.reason=e.data.reason),this.#_.set(e.data.name,t),this.#v.delete(e.data.name),this.#D(t),this.#n.setConnectionAuthPendingCount?.(this.#v.size)}#D(e){let t={name:e.name,description:e.description,state:e.state};e.challenge!==void 0&&(t.challenge=e.challenge),e.reason!==void 0&&(t.reason=e.reason),this.#n.upsertConnectionAuth?.(t)}#O(e){let t=e.data.callId;if(this.#g.has(t))return;let n=this.#t;if(!n)return;let i=new AbortController;this.#g.set(t,i),(async()=>{try{let r=n.session({sessionId:e.data.childSessionId,streamIndex:0}).stream({signal:i.signal});for await(let e of r)if(i.signal.aborted||(this.#j(t,e),isCurrentTurnBoundaryEvent(e)))break}catch(e){if(!isAbortLikeError(e)){let n=toErrorMessage(e),r=this.#h.get(t);if(r){let{key:e,step:i}=openCurrentSubagentSection(r);i.message=i.message?`${i.message}\n\nstream error: ${n}`:`stream error: ${n}`,i.finalized=!0,r.currentSectionKey=null,this.#n.upsertSubagentStep?.({callId:t,subagentName:r.name,sectionKey:e,reasoning:i.reasoning,message:i.message,finalized:!0})}}}finally{this.#g.delete(t)}})()}#k(e,t,n){let r=t.tools.get(n.childCallId),i=r??{toolName:n.toolName,input:n.input,status:n.status};if(r){let e={"approval-requested":0,executing:1,done:2,failed:2};e[n.status]>e[r.status]&&(r.status=n.status),r.input=n.input}else t.tools.set(n.childCallId,i);this.#n.markChildToolCallId?.(n.childCallId),this.#n.upsertSubagentTool?.({callId:e,subagentName:t.name,childCallId:n.childCallId,toolName:i.toolName,input:i.input,status:i.status})}#A(e){let t=this.#h.get(e);if(t){for(let[n,r]of t.steps)r.finalized||(r.finalized=!0,this.#n.upsertSubagentStep?.({callId:e,subagentName:t.name,sectionKey:n,reasoning:r.reasoning,message:r.message,finalized:!0}));t.currentSectionKey=null}}#j(e,t){let n=this.#h.get(e);if(!n)return;let r=this.#n,emit=(t,i)=>{r.upsertSubagentStep?.({callId:e,subagentName:n.name,sectionKey:t,reasoning:i.reasoning,message:i.message,finalized:i.finalized})},finalizeCurrent=()=>{if(n.currentSectionKey===null)return;let e=n.steps.get(n.currentSectionKey);e&&(e.finalized=!0,emit(n.currentSectionKey,e)),n.currentSectionKey=null};switch(t.type){case`reasoning.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.reasoning+=t.data.reasoningDelta,emit(e,r);break}case`reasoning.completed`:break;case`message.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.message+=t.data.messageDelta,emit(e,r);break}case`message.completed`:{let{key:e,step:r}=openCurrentSubagentSection(n);t.data.message!==null&&r.message.length===0&&(r.message=t.data.message),r.finalized=!0,emit(e,r),n.currentSectionKey=null;break}case`step.completed`:finalizeCurrent();break;case`actions.requested`:finalizeCurrent();for(let r of t.data.actions)r.kind===`tool-call`&&this.#k(e,n,{childCallId:r.callId,toolName:r.toolName,input:r.input,status:`executing`});break;case`input.requested`:finalizeCurrent();for(let r of t.data.requests)r.action.kind===`tool-call`&&this.#k(e,n,{childCallId:r.action.callId,toolName:r.action.toolName,input:r.action.input,status:`approval-requested`});break;case`action.result`:{let i=t.data.result;if(i.kind!==`tool-result`)break;let a=n.tools.get(i.callId);if(!a)break;t.data.status===`failed`?(a.status=`failed`,a.errorText=formatActionResultError(t)):(a.status=`done`,a.output=i.output);let o={callId:e,subagentName:n.name,childCallId:i.callId,toolName:a.toolName,input:a.input,status:a.status};a.output!==void 0&&(o.output=a.output),a.errorText!==void 0&&(o.errorText=a.errorText),r.upsertSubagentTool?.(o);break}default:break}}};function createRenderer(e){return e.renderer?e.renderer:new TerminalRenderer({tools:e.tools,reasoning:e.reasoning,subagents:e.subagents,connectionAuth:e.connectionAuth,assistantResponseStats:e.assistantResponseStats,contextSize:e.contextSize,logs:e.logs,input:e.userInput,output:e.screen})}function formatAgentUpdateNotice(e,t){let n=e?.agent.model.id,r=t?.agent.model.id;return n!==void 0&&r!==void 0&&n!==r?`Agent updated: Model ${n} -> ${r}`:`Agent updated.`}async function*eveEventsToTUIStream(e){let{events:t,pendingInputRequests:n,subagentRuns:r,turnState:i,onSubagentCalled:a,onSubagentCompleted:o,onConnectionAuthRequired:s,onConnectionAuthCompleted:c,onTerminalFailure:l}=e,u=new Map,d=new Map,f=0,p=new Set,m=new Set,h=new Set,g=new Set,_=!1,v=!1,y;for await(let e of t)if(!(v&&isPostTurnVisibleEvent(e)))switch(e.type){case`session.started`:case`turn.started`:case`message.received`:break;case`step.started`:f+=1,yield{type:`step-start`};break;case`step.completed`:{let t=e;y=t.data.usage,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`step-finish`,usage:t.data.usage};break}case`message.appended`:{let t=e,n=textPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(u,n),i=t.data.messageSoFar;if(r.completed){if(r.text.startsWith(i)||f<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`assistant-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`message.completed`:{let t=textPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(u,t),r=e.data.message;if(n.completed){if(r===null||r===n.text||f<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=f,yield{type:`assistant-complete`,id:partGenerationId(t,n.generation),text:r};break}let i=partGenerationId(t,n.generation);if(r!==null){if(n.text.length===0)n.text=r,n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i,text:r};else if(r.startsWith(n.text)){let e=r.slice(n.text.length);e.length>0&&(yield{type:`assistant-delta`,id:i,delta:e}),n.text=r,n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i}}}else n.text.length>0&&(n.completed=!0,n.completedEpoch=f,yield{type:`assistant-complete`,id:i});break}case`reasoning.appended`:{let t=e,n=reasoningPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(d,n),i=t.data.reasoningSoFar;if(r.completed){if(r.text.startsWith(i)||f<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`reasoning-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`reasoning.completed`:{let t=reasoningPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(d,t),r=e.data.reasoning;if(n.completed){if(r.length===0||r===n.text||n.text.startsWith(r)||f<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=f;let e=partGenerationId(t,n.generation);yield{type:`reasoning-delta`,id:e,delta:r},yield{type:`reasoning-complete`,id:e};break}let i=partGenerationId(t,n.generation);if(n.text.length===0&&r.length>0)n.text=r,yield{type:`reasoning-delta`,id:i,delta:r};else if(r.length>0&&!r.startsWith(n.text))break;n.completed=!0,n.completedEpoch=f,yield{type:`reasoning-complete`,id:i};break}case`actions.requested`:{let t=e.data,n=t.actions.filter(e=>e.kind===`tool-call`);if(n.length===0)break;let r=toolBatchKey(`actions.requested`,t.turnId,t.stepIndex,n);if(h.has(r)){for(let e of n)p.has(e.callId)||m.add(e.callId);break}h.add(r);for(let e of n)p.has(e.callId)||(p.add(e.callId),yield{type:`tool-call`,toolCallId:e.callId,toolName:e.toolName,input:e.input});break}case`input.requested`:{let t=e.data,r=t.requests.filter(e=>e.action.kind===`tool-call`);if(r.length===0)break;let a=inputRequestBatchKey(t.turnId,t.stepIndex,r);if(h.has(a)){for(let e of r)p.has(e.action.callId)||m.add(e.action.callId);break}h.add(a);for(let e of r){let t=e.action.callId;if(p.has(t)||(p.add(t),yield{type:`tool-call`,toolCallId:t,toolName:e.action.toolName,input:e.action.input}),n.set(e.requestId,e),isQuestionRequest(e)){upsertPendingQuestion(i,e);continue}upsertPendingApproval(i,e),yield{type:`tool-approval-request`,approvalId:e.requestId,toolCallId:t}}break}case`action.result`:{let t=e;if(t.data.result.kind!==`tool-result`)break;let n=t.data.result.callId;if(m.has(n)||!p.has(n))break;t.data.status===`failed`?yield{type:`tool-error`,toolCallId:n,errorText:formatActionResultError(t)}:yield{type:`tool-result`,toolCallId:n,output:t.data.result.output};break}case`step.failed`:case`turn.failed`:{let t=toFailureEvent(e,g);t&&(yield t);break}case`session.failed`:{i.sawSessionFailure=!0,l?.(e);let t=toFailureEvent(e,g);t&&(yield t),i.boundaryEvent=e.type,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y},_=!0;return}case`session.waiting`:case`session.completed`:i.boundaryEvent=e.type,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y},_=!0;return;case`turn.completed`:v=!0,yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f);break;case`subagent.called`:{let t=e;if(!r.has(t.data.callId))r.set(t.data.callId,{name:t.data.name,steps:new Map,currentSectionKey:null,nextSectionKey:0,tools:new Map});else{let e=r.get(t.data.callId);e&&(e.name=t.data.name)}a?.(t);break}case`subagent.started`:case`subagent.event`:break;case`subagent.completed`:o?.(e.data.callId);break;case`authorization.required`:s?.(e);break;case`authorization.completed`:c?.(e);break;default:break}_||(yield*closeOpenParts(u,`assistant-complete`,f),yield*closeOpenParts(d,`reasoning-complete`,f),yield{type:`finish`,usage:y})}async function*errorOnlyTUIStream(e){yield{type:`error`,errorText:e.errorText},yield{type:`finish`}}function createTurnState(){return{pendingApprovals:[],pendingQuestions:[],sawSessionFailure:!1}}function upsertPendingApproval(e,t){let n=toAgentTUIToolApprovalRequest(t),r=e.pendingApprovals.findIndex(e=>e.approvalId===n.approvalId);r===-1?e.pendingApprovals.push(n):e.pendingApprovals[r]=n}function toAgentTUIToolApprovalRequest(e){return{approvalId:e.requestId,toolCallId:e.action.callId,toolName:e.action.toolName,input:e.action.input}}function upsertPendingQuestion(e,t){let n=e.pendingQuestions.findIndex(e=>e.requestId===t.requestId);n===-1?e.pendingQuestions.push(t):e.pendingQuestions[n]=t}function textPartId(e,t){return`text:${e}:${t}`}function reasoningPartId(e,t){return`reasoning:${e}:${t}`}function partStateFor(e,t){let n=e.get(t);return n===void 0&&(n={generation:0,text:``,completed:!1,completedEpoch:0},e.set(t,n)),n}function partGenerationId(e,t){return t===0?e:`${e}#${t}`}function*closeOpenParts(e,t,n){for(let[r,i]of e)i.completed||i.text.length===0||(i.completed=!0,i.completedEpoch=n,yield{type:t,id:partGenerationId(r,i.generation)})}function isPostTurnVisibleEvent(e){switch(e.type){case`action.result`:case`actions.requested`:case`authorization.completed`:case`authorization.required`:case`input.requested`:case`message.appended`:case`message.completed`:case`reasoning.appended`:case`reasoning.completed`:case`result.completed`:case`step.completed`:case`step.failed`:case`step.started`:case`subagent.called`:case`subagent.completed`:case`subagent.event`:case`subagent.started`:case`turn.completed`:case`turn.failed`:return!0;default:return!1}}function toolBatchKey(e,t,n,r){return`${e}:${t}:${String(n)}:${stableStringify(r.map(e=>({input:e.input,toolName:e.toolName})))}`}function inputRequestBatchKey(e,t,n){return toolBatchKey(`input.requested`,e,t,n.map(e=>({input:e.action.input,toolName:e.action.toolName})))}function stableStringify(e){return JSON.stringify(toStableJson(e))??`undefined`}function toStableJson(e,t=new WeakSet){if(typeof e!=`object`||!e)return e;if(t.has(e))return`[Circular]`;if(t.add(e),Array.isArray(e))return e.map(e=>toStableJson(e,t));let n=e,r={};for(let e of Object.keys(n).sort())r[e]=toStableJson(n[e],t);return r}function formatActionResultError(e){if(e.data.error?.message)return e.data.error.message;let t=e.data.result.output;if(typeof t==`string`)return t;try{return JSON.stringify(t)}catch{return`Tool execution failed.`}}function toFailureEvent(r,i){let a=failureKey(r);if(i.has(a))return;i.add(a);let o={type:`error`,errorText:formatFailureMessage(r)},s=formatFailureDetail(r);return s!==void 0&&(o.detail=s),o}function isQuestionRequest(e){return e.display===`select`||e.display===`text`?!0:e.display===`confirmation`?!1:e.options!==void 0&&e.options.length>0}function toAgentTUIInputQuestion(e){let t=e.display===`text`?`text`:e.display===`select`||e.options!==void 0&&e.options.length>0?`select`:`text`,n={requestId:e.requestId,prompt:e.prompt,display:t};return e.options!==void 0&&(n.options=e.options.map(e=>{let t={id:e.id,label:e.label};return e.description!==void 0&&(t.description=e.description),e.style!==void 0&&(t.style=e.style),t})),e.allowFreeform!==void 0&&(n.allowFreeform=e.allowFreeform),n}function parsePromptCommand(e){let t=e.trim();return t===`/new`?`new`:t===`/exit`||t===`/quit`?`exit`:null}function openCurrentSubagentSection(e){e.currentSectionKey===null&&(e.currentSectionKey=e.nextSectionKey++,e.steps.set(e.currentSectionKey,{reasoning:``,message:``,finalized:!1}));let t=e.steps.get(e.currentSectionKey);if(!t)throw Error(`invariant: subagent section state missing for current key`);return{key:e.currentSectionKey,step:t}}export{EveTUIRunner};
@@ -40,7 +40,9 @@ export declare class TerminalRenderer {
40
40
  constructor(options?: TerminalRendererOptions);
41
41
  /**
42
42
  * Commits the startup agent header (brand mark + resolved configuration) to
43
- * scrollback before the first prompt. Safe to call once at startup.
43
+ * scrollback before the first prompt. Later calls replace the committed
44
+ * header and replay the transcript beneath it so dev HMR can refresh fields
45
+ * such as the resolved model.
44
46
  */
45
47
  renderAgentHeader(options: AgentHeaderOptions): void;
46
48
  readPrompt(options?: AgentTUISessionOptions): Promise<string>;