eve 0.6.0-beta.11 → 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.
- package/CHANGELOG.md +35 -0
- package/dist/docs/evals-v2-plan.md +45 -8
- package/dist/docs/public/advanced/default-harness.md +2 -2
- package/dist/docs/public/advanced/evals.md +43 -4
- package/dist/docs/public/frontend/nextjs.mdx +9 -0
- package/dist/docs/public/getting-started.mdx +2 -2
- package/dist/docs/public/tools.mdx +0 -4
- package/dist/src/chunks/{use-eve-agent-DT2A6VJb.js → use-eve-agent-q1isCIFv.js} +42 -8
- package/dist/src/chunks/{use-eve-agent-BD79SFqg.js → use-eve-agent-tFYnZx_b.js} +42 -8
- package/dist/src/cli/commands/setup.d.ts +6 -3
- package/dist/src/cli/commands/setup.js +1 -1
- package/dist/src/cli/dev/tui/runner.d.ts +2 -1
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/terminal-renderer.d.ts +3 -1
- package/dist/src/cli/dev/tui/terminal-renderer.js +2 -2
- package/dist/src/cli/run.d.ts +4 -0
- package/dist/src/cli/run.js +1 -1
- package/dist/src/client/client.d.ts +8 -0
- package/dist/src/client/client.js +1 -1
- package/dist/src/client/session.js +1 -1
- package/dist/src/client/types.d.ts +4 -1
- package/dist/src/compiled/.vendor-stamp.json +7 -7
- package/dist/src/compiled/@ai-sdk/anthropic/index.d.ts +56 -31
- package/dist/src/compiled/@ai-sdk/anthropic/index.js +2 -2
- package/dist/src/compiled/@ai-sdk/google/index.js +1 -1
- package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
- package/dist/src/compiled/@ai-sdk/openai/index.d.ts +16 -9
- package/dist/src/compiled/@ai-sdk/openai/index.js +2 -2
- package/dist/src/compiled/@ai-sdk/otel/index.js +2 -2
- package/dist/src/compiled/@vercel/sandbox/index.js +1 -1
- package/dist/src/compiled/@workflow/core/index.js +2 -2
- package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +4 -2
- package/dist/src/compiled/@workflow/core/runtime/wait-until.d.ts +18 -0
- package/dist/src/compiled/@workflow/core/runtime.d.ts +3 -1
- package/dist/src/compiled/@workflow/core/runtime.js +28 -28
- package/dist/src/compiled/@workflow/core/serialization.d.ts +41 -0
- package/dist/src/compiled/@workflow/core/util.d.ts +0 -5
- package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/@workflow/world/index.d.ts +2 -2
- package/dist/src/compiled/@workflow/world/queue.d.ts +28 -2
- package/dist/src/compiled/_chunks/workflow/{dist-gEXVSMPU.js → dist-CkMRLaRV.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/functions-DuPjIvMH.js +1 -0
- package/dist/src/compiled/_chunks/workflow/resume-hook-CEAS3opc.js +12 -0
- package/dist/src/compiled/_chunks/workflow/sleep-Cup6vPoA.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{symbols-BWCAoPHE.js → symbols-BUTtwS7j.js} +1 -1
- package/dist/src/evals/cli/eval.d.ts +4 -0
- package/dist/src/evals/cli/eval.js +1 -1
- package/dist/src/evals/define-eval.js +1 -1
- package/dist/src/evals/index.d.ts +2 -1
- package/dist/src/evals/index.js +1 -1
- package/dist/src/evals/reporters/index.d.ts +1 -0
- package/dist/src/evals/reporters/index.js +1 -1
- package/dist/src/evals/requirements.d.ts +4 -0
- package/dist/src/evals/requirements.js +1 -0
- package/dist/src/evals/runner/artifacts.js +1 -1
- package/dist/src/evals/runner/execute-case.d.ts +5 -2
- package/dist/src/evals/runner/execute-case.js +1 -1
- package/dist/src/evals/runner/execute-eval.d.ts +5 -2
- package/dist/src/evals/runner/execute-eval.js +1 -1
- package/dist/src/evals/runner/reporters/junit.d.ts +9 -0
- package/dist/src/evals/runner/reporters/junit.js +8 -0
- package/dist/src/evals/session.d.ts +6 -0
- package/dist/src/evals/session.js +1 -1
- package/dist/src/evals/target.d.ts +23 -0
- package/dist/src/evals/target.js +1 -0
- package/dist/src/evals/types.d.ts +39 -2
- package/dist/src/execution/compaction.d.ts +14 -0
- package/dist/src/execution/compaction.js +1 -0
- package/dist/src/execution/delegated-parent-notification.js +1 -1
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/sandbox/glob-tool.js +3 -3
- package/dist/src/execution/sandbox/grep-tool.js +3 -3
- package/dist/src/execution/sandbox/read-file-tool.js +1 -1
- package/dist/src/execution/subagent-adapter.js +1 -1
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/model-call-error.d.ts +23 -6
- package/dist/src/harness/model-call-error.js +1 -1
- package/dist/src/harness/step-hooks.d.ts +6 -0
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/types.d.ts +4 -15
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/schema-backed.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
- package/dist/src/internal/nitro/host/configure-nitro-routes.js +2 -2
- package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
- package/dist/src/internal/nitro/host/start-production-server.js +1 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.d.ts +5 -0
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -0
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +31 -2
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
- package/dist/src/internal/nitro/routes/agent-info/load-agent-info-data.d.ts +13 -0
- package/dist/src/internal/nitro/routes/agent-info/load-agent-info-data.js +1 -1
- package/dist/src/internal/nitro/routes/info.d.ts +2 -2
- package/dist/src/internal/nitro/routes/info.js +1 -1
- package/dist/src/internal/workflow/queue-namespace.d.ts +5 -0
- package/dist/src/internal/workflow/queue-namespace.js +1 -0
- package/dist/src/internal/workflow-bundle/builder-support.js +2 -2
- package/dist/src/internal/workflow-bundle/builder.js +3 -5
- package/dist/src/internal/workflow-bundle/vercel-workflow-output.js +1 -1
- package/dist/src/internal/workflow-bundle/workflow-builders.d.ts +1 -1
- package/dist/src/internal/workflow-bundle/workflow-builders.js +1 -1
- package/dist/src/public/definitions/tool.d.ts +0 -33
- package/dist/src/public/next/index.d.ts +6 -0
- package/dist/src/public/next/index.js +1 -1
- package/dist/src/public/next/server.d.ts +1 -0
- package/dist/src/public/next/server.js +1 -1
- package/dist/src/public/tools/defaults.d.ts +2 -4
- package/dist/src/public/tools/defaults.js +1 -1
- package/dist/src/public/tools/define-read-file-tool.d.ts +0 -6
- package/dist/src/public/tools/define-read-file-tool.js +1 -1
- package/dist/src/public/tools/index.d.ts +1 -1
- package/dist/src/public/tools/internal.js +1 -1
- package/dist/src/runtime/connections/callback-route.js +1 -1
- package/dist/src/runtime/framework-tools/connection-search-dynamic.d.ts +1 -1
- package/dist/src/runtime/framework-tools/file-state.d.ts +3 -3
- package/dist/src/runtime/framework-tools/index.js +1 -1
- package/dist/src/runtime/framework-tools/read-file.js +2 -2
- package/dist/src/runtime/framework-tools/todo.d.ts +7 -0
- package/dist/src/runtime/framework-tools/todo.js +2 -2
- package/dist/src/runtime/resolve-tool.d.ts +2 -2
- package/dist/src/runtime/resolve-tool.js +1 -1
- package/dist/src/runtime/session-callback-route.js +1 -1
- package/dist/src/runtime/types.d.ts +1 -7
- package/dist/src/services/dev-client.d.ts +13 -0
- package/dist/src/services/dev-client.js +1 -1
- package/dist/src/setup/ask.d.ts +7 -0
- package/dist/src/setup/ask.js +1 -1
- package/dist/src/setup/boxes/add-channels.d.ts +11 -2
- package/dist/src/setup/boxes/add-channels.js +1 -1
- package/dist/src/setup/boxes/add-connections.d.ts +8 -58
- package/dist/src/setup/boxes/add-connections.js +1 -1
- package/dist/src/setup/boxes/deploy-project.js +1 -1
- package/dist/src/setup/boxes/one-shot-next-steps.d.ts +15 -0
- package/dist/src/setup/boxes/one-shot-next-steps.js +2 -0
- package/dist/src/setup/boxes/preflight.d.ts +6 -5
- package/dist/src/setup/boxes/preflight.js +1 -1
- package/dist/src/setup/boxes/resolve-provisioning.d.ts +20 -7
- package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
- package/dist/src/setup/boxes/select-channels.d.ts +16 -9
- package/dist/src/setup/boxes/select-channels.js +1 -1
- package/dist/src/setup/boxes/select-chat.d.ts +1 -1
- package/dist/src/setup/boxes/select-connections.d.ts +30 -0
- package/dist/src/setup/boxes/select-connections.js +1 -0
- package/dist/src/setup/boxes/select-model.d.ts +7 -7
- package/dist/src/setup/boxes/select-model.js +1 -1
- package/dist/src/setup/boxes/select-setup-mode.d.ts +32 -0
- package/dist/src/setup/boxes/select-setup-mode.js +1 -0
- package/dist/src/setup/cli/index.d.ts +1 -0
- package/dist/src/setup/cli/index.js +1 -1
- package/dist/src/setup/cli/prompt-ui.d.ts +39 -15
- package/dist/src/setup/cli/prompt-ui.js +1 -1
- package/dist/src/setup/cli/select-component.d.ts +16 -1
- package/dist/src/setup/cli/select-component.js +1 -1
- package/dist/src/setup/cli/select-state.d.ts +13 -1
- package/dist/src/setup/cli/select-state.js +1 -1
- package/dist/src/setup/cli/whimsy.d.ts +16 -0
- package/dist/src/setup/cli/whimsy.js +1 -0
- package/dist/src/setup/connection-connector.js +1 -1
- package/dist/src/setup/index.d.ts +2 -2
- package/dist/src/setup/onboarding.d.ts +6 -3
- package/dist/src/setup/onboarding.js +1 -1
- package/dist/src/setup/primitives/run-vercel.d.ts +7 -0
- package/dist/src/setup/primitives/run-vercel.js +1 -1
- package/dist/src/setup/prompter.d.ts +20 -3
- package/dist/src/setup/prompter.js +1 -1
- package/dist/src/setup/scaffold/channels-catalog.d.ts +1 -1
- package/dist/src/setup/scaffold/create/project.d.ts +16 -0
- package/dist/src/setup/scaffold/create/project.js +3 -3
- package/dist/src/setup/scaffold/index.d.ts +1 -1
- package/dist/src/setup/scaffold/index.js +1 -1
- package/dist/src/setup/scaffold/update/channels.js +1 -1
- package/dist/src/setup/slackbot.js +1 -1
- package/dist/src/setup/state.d.ts +44 -9
- package/dist/src/setup/state.js +1 -1
- package/dist/src/setup/vercel-project.d.ts +12 -0
- package/dist/src/setup/vercel-project.js +1 -1
- package/dist/src/source-change/apply-model-name.d.ts +25 -0
- package/dist/src/source-change/apply-model-name.js +2 -0
- package/dist/src/source-change/static-source-change.d.ts +36 -0
- package/dist/src/source-change/static-source-change.js +1 -0
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/package.json +13 -12
- package/dist/src/compiled/_chunks/workflow/resume-hook-0Zk0zSvq.js +0 -12
- package/dist/src/compiled/_chunks/workflow/sleep-DXZr2BgM.js +0 -1
- package/dist/src/execution/tool-compaction.d.ts +0 -9
- package/dist/src/execution/tool-compaction.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
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
|
+
|
|
23
|
+
## 0.6.0-beta.12
|
|
24
|
+
|
|
25
|
+
### Minor Changes
|
|
26
|
+
|
|
27
|
+
- 4c1dd92: The connections picker moved into the onboarding interview: it now asks right after channel selection, before any files are written. The selected connections are still scaffolded and provisioned after the project link, exactly as before.
|
|
28
|
+
- 432deaa: The setup model picker now opens on a curated shortlist (Claude Sonnet 4.6 as the default, Claude Opus 4.8, GPT-5.5, and Gemini 3.5) and surfaces the rest of the AI Gateway catalog through scrolling or search. The search filter now accepts spaces. Vercel Connect steps in Slack channel setup run under hard deadlines, so an abandoned browser OAuth can no longer stall `connect create slack` forever.
|
|
29
|
+
- 4c1dd92: Onboarding deploys to Vercel only when the Slack channel was added — its connector needs a public production URL. A web-only onboarding run links the project but skips the deploy; Web Chat runs locally through `eve dev`. Adding channels to an existing project (`eve setup` in-project, `eve channels add`) still deploys for any channel.
|
|
30
|
+
- 4c1dd92: The onboarding flow now asks how much to set up after the agent name: "Complete setup" (the existing full flow, recommended) or "One-shot", which scaffolds the base template with the default model and skips provisioning, channels, deploy, and chat, ending with a next-steps note. `eve setup` in a directory that is not an Eve project now asks for the agent name and where the agent should live instead of force-scaffolding in place over the existing repo.
|
|
31
|
+
- 432deaa: A failed Slackbot provision no longer aborts onboarding or `eve setup`. The run warns, skips Slack, and keeps scaffolding and deploying, and you can add Slack later with `eve channels add slack`. The `eve channels add slack` command itself still fails hard, since Slack is its whole purpose.
|
|
32
|
+
- 432deaa: Setup multi-select prompts now render checkboxes and end with a bold Submit row. Enter toggles the highlighted option, and only enter on Submit confirms, so a stray enter can no longer skip the checklist. Single-select prompts mark the highlighted row with a `›` arrow instead of a check.
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- 432deaa: Refreshed onboarding copy: the deploy question now asks where to deploy (Vercel vs. elsewhere), the team and project pickers use shorter titles, and the intro banners spell the product as 𝐞𝐯𝐞.
|
|
37
|
+
|
|
3
38
|
## 0.6.0-beta.11
|
|
4
39
|
|
|
5
40
|
### 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.
|
|
828
|
-
|
|
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
|
-
|
|
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
|
|
889
|
-
|
|
890
|
-
|
|
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
|
-
|
|
895
|
-
|
|
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
|
|
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
|
|
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`.
|
|
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 asks
|
|
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
|
|
|
@@ -164,7 +164,7 @@ Once `eve` is a dependency, the full docs are bundled in the package, so the age
|
|
|
164
164
|
|
|
165
165
|
- Docs: `node_modules/eve/dist/docs/public/`
|
|
166
166
|
|
|
167
|
-
To scaffold a project end to end, `pnpm create eve@beta` collects the decisions (name, model, channels), runs setup, adds Slack interactively with `eve channels add slack`, and verifies the result with `eve info --json`.
|
|
167
|
+
To scaffold a project end to end, `pnpm create eve@beta` collects the decisions (name, setup mode, model, channels), runs setup, adds Slack interactively with `eve channels add slack`, and verifies the result with `eve info --json`.
|
|
168
168
|
|
|
169
169
|
## What to read next
|
|
170
170
|
|
|
@@ -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
|
|
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
|
|
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,6 +1,6 @@
|
|
|
1
1
|
import { type DeploymentInfo } from "#setup/project-resolution.js";
|
|
2
2
|
import { type Prompter } from "#setup/prompter.js";
|
|
3
|
-
import { type ArgsHeadlessAiGateway, type ArgsHeadlessProject, type ChannelKind, type ChatPreference } from "#setup/state.js";
|
|
3
|
+
import { type ArgsHeadlessAiGateway, type ArgsHeadlessProject, type ChannelKind, type ChatPreference, type SetupMode } from "#setup/state.js";
|
|
4
4
|
export interface SetupCliLogger {
|
|
5
5
|
error(message: string): void;
|
|
6
6
|
log(message: string): void;
|
|
@@ -12,6 +12,7 @@ export interface SetupCliLogger {
|
|
|
12
12
|
*/
|
|
13
13
|
export interface SetupCommandPresets {
|
|
14
14
|
presetName?: string;
|
|
15
|
+
presetMode?: SetupMode;
|
|
15
16
|
presetModel?: string;
|
|
16
17
|
presetChannels?: ChannelKind[];
|
|
17
18
|
presetCreateSlackbot?: boolean;
|
|
@@ -46,8 +47,10 @@ export interface SetupCommandDependencies {
|
|
|
46
47
|
}
|
|
47
48
|
/**
|
|
48
49
|
* The unified `eve setup` entry. In a directory that is not yet an Eve project
|
|
49
|
-
* it runs the SAME onboarding composition as `pnpm create eve
|
|
50
|
-
*
|
|
50
|
+
* it runs the SAME onboarding composition as `pnpm create eve`: an interactive
|
|
51
|
+
* run asks the name and where the agent should live (a `./<name>` child or the
|
|
52
|
+
* current directory), while a headless run scaffolds in place. Inside an
|
|
53
|
+
* existing project it runs in-project setup: the channel
|
|
51
54
|
* interview, then channel scaffolding, then deploy, against the detected
|
|
52
55
|
* on-disk project link. Both compose the shared boxes through the shared
|
|
53
56
|
* runner.
|
|
@@ -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{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
|
|
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
|
|
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.
|
|
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>;
|