eve 0.6.0-beta.17 → 0.6.0-beta.19
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 +26 -0
- package/README.md +4 -2
- package/dist/docs/public/advanced/auth-and-route-protection.md +2 -0
- package/dist/docs/public/advanced/dev-tui.md +2 -2
- package/dist/docs/public/agent-config.md +1 -1
- package/dist/docs/public/connections.mdx +3 -1
- package/dist/docs/public/getting-started.mdx +19 -8
- package/dist/docs/public/reference/cli.md +0 -1
- package/dist/src/chunks/{use-eve-agent-tFYnZx_b.js → use-eve-agent-DErQj5hs.js} +2 -1
- package/dist/src/chunks/{use-eve-agent-q1isCIFv.js → use-eve-agent-DoR8C4i6.js} +2 -1
- package/dist/src/cli/commands/init.d.ts +14 -6
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/commands/link.d.ts +1 -1
- package/dist/src/cli/dev/tui/agent-header.d.ts +1 -1
- package/dist/src/cli/dev/tui/agent-header.js +1 -1
- package/dist/src/cli/dev/tui/blocks.d.ts +1 -1
- package/dist/src/cli/dev/tui/blocks.js +2 -1
- package/dist/src/cli/dev/tui/errors.d.ts +1 -1
- package/dist/src/cli/dev/tui/errors.js +1 -1
- package/dist/src/cli/dev/tui/prompt-command-handler.d.ts +2 -1
- package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
- package/dist/src/cli/dev/tui/prompt-commands.d.ts +1 -1
- package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/setup-commands.d.ts +2 -4
- package/dist/src/cli/dev/tui/setup-commands.js +2 -1
- package/dist/src/cli/dev/tui/setup-flow.d.ts +3 -0
- package/dist/src/cli/dev/tui/setup-issues.d.ts +1 -1
- package/dist/src/cli/dev/tui/setup-issues.js +1 -1
- package/dist/src/cli/dev/tui/setup-panel.d.ts +6 -1
- package/dist/src/cli/dev/tui/setup-panel.js +1 -1
- package/dist/src/cli/dev/tui/stream-format.js +1 -1
- package/dist/src/cli/dev/tui/terminal-renderer.d.ts +6 -6
- package/dist/src/cli/dev/tui/terminal-renderer.js +3 -2
- package/dist/src/cli/dev/tui/tui-prompter.js +1 -1
- package/dist/src/cli/dev/tui/tui.d.ts +0 -8
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/cli/run.d.ts +3 -16
- package/dist/src/cli/run.js +2 -2
- package/dist/src/client/index.js +1 -1
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/client/session.js +1 -1
- package/dist/src/compiler/normalize-channel.d.ts +2 -1
- package/dist/src/compiler/normalize-channel.js +1 -1
- package/dist/src/compiler/normalize-connection.d.ts +2 -1
- package/dist/src/compiler/normalize-connection.js +1 -1
- package/dist/src/compiler/normalize-helpers.d.ts +5 -0
- package/dist/src/compiler/normalize-helpers.js +1 -1
- package/dist/src/compiler/normalize-instructions.d.ts +3 -2
- package/dist/src/compiler/normalize-instructions.js +1 -1
- package/dist/src/compiler/normalize-manifest.js +2 -2
- package/dist/src/compiler/normalize-sandbox.d.ts +2 -1
- package/dist/src/compiler/normalize-sandbox.js +1 -1
- package/dist/src/compiler/normalize-schedule.d.ts +2 -1
- package/dist/src/compiler/normalize-schedule.js +1 -1
- package/dist/src/compiler/normalize-skill.d.ts +2 -1
- package/dist/src/compiler/normalize-skill.js +1 -1
- package/dist/src/compiler/normalize-subagent.d.ts +4 -1
- package/dist/src/compiler/normalize-subagent.js +1 -1
- package/dist/src/compiler/normalize-tool.d.ts +2 -1
- package/dist/src/compiler/normalize-tool.js +1 -1
- package/dist/src/evals/cli/eval.js +1 -1
- package/dist/src/evals/session.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/code-mode-lifecycle.js +1 -1
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/model-call-error.d.ts +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/turn-tag-state.d.ts +4 -0
- package/dist/src/harness/turn-tag-state.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-module-loader.d.ts +4 -1
- package/dist/src/internal/authored-module-loader.js +2 -2
- package/dist/src/internal/authored-module-map-loader.js +1 -1
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/server-external-packages.d.ts +1 -1
- package/dist/src/internal/nitro/host/server-external-packages.js +1 -1
- package/dist/src/node_modules/.pnpm/@clack_core@1.3.1/node_modules/@clack/core/dist/index.js +4 -4
- package/dist/src/protocol/message.d.ts +7 -0
- package/dist/src/protocol/message.js +1 -1
- package/dist/src/public/channels/slack/defaults.js +1 -1
- package/dist/src/public/channels/teams/defaults.js +1 -1
- package/dist/src/public/connections/errors.d.ts +8 -0
- package/dist/src/public/next/index.d.ts +1 -1
- package/dist/src/public/next/server.js +1 -1
- package/dist/src/public/nuxt/dev-server.js +1 -1
- package/dist/src/public/sveltekit/dev-server.js +1 -1
- package/dist/src/public/sveltekit/index.d.ts +1 -1
- package/dist/src/runtime/connections/scoped-authorization.d.ts +12 -0
- package/dist/src/runtime/connections/scoped-authorization.js +1 -1
- package/dist/src/runtime/connections/types.d.ts +9 -0
- package/dist/src/runtime/connections/validate-authorization.js +1 -1
- package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
- package/dist/src/services/dev-client/client-options.d.ts +4 -4
- package/dist/src/services/dev-client.d.ts +0 -46
- package/dist/src/services/dev-client.js +1 -1
- package/dist/src/setup/boxes/add-channels.d.ts +5 -3
- package/dist/src/setup/boxes/add-channels.js +1 -1
- package/dist/src/setup/boxes/deploy-project.d.ts +4 -2
- package/dist/src/setup/boxes/deploy-project.js +1 -1
- package/dist/src/setup/boxes/one-shot-next-steps.d.ts +3 -0
- package/dist/src/setup/boxes/one-shot-next-steps.js +1 -1
- package/dist/src/setup/boxes/select-channels.d.ts +1 -1
- 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-chat.js +1 -1
- package/dist/src/setup/flows/channels.d.ts +1 -1
- package/dist/src/setup/flows/channels.js +1 -1
- package/dist/src/setup/flows/link.d.ts +2 -2
- package/dist/src/setup/flows/model.d.ts +81 -12
- package/dist/src/setup/flows/model.js +1 -1
- package/dist/src/setup/flows/vercel.d.ts +7 -6
- package/dist/src/setup/flows/vercel.js +1 -1
- package/dist/src/setup/index.d.ts +1 -1
- package/dist/src/setup/index.js +1 -1
- package/dist/src/setup/package-manager.d.ts +27 -0
- package/dist/src/setup/package-manager.js +1 -0
- package/dist/src/setup/primitives/index.d.ts +2 -1
- package/dist/src/setup/primitives/index.js +1 -1
- package/dist/src/setup/primitives/pm/bun.d.ts +10 -0
- package/dist/src/setup/primitives/pm/bun.js +1 -0
- package/dist/src/setup/primitives/pm/index.d.ts +11 -0
- package/dist/src/setup/primitives/pm/index.js +1 -0
- package/dist/src/setup/primitives/pm/npm.d.ts +10 -0
- package/dist/src/setup/primitives/pm/npm.js +1 -0
- package/dist/src/setup/primitives/pm/pnpm.d.ts +27 -0
- package/dist/src/setup/primitives/pm/pnpm.js +8 -0
- package/dist/src/setup/primitives/pm/run.d.ts +23 -0
- package/dist/src/setup/primitives/pm/run.js +1 -0
- package/dist/src/setup/primitives/pm/shared.d.ts +8 -0
- package/dist/src/setup/primitives/pm/shared.js +1 -0
- package/dist/src/setup/primitives/pm/types.d.ts +37 -0
- package/dist/src/setup/primitives/pm/types.js +1 -0
- package/dist/src/setup/primitives/pm/yarn.d.ts +10 -0
- package/dist/src/setup/primitives/pm/yarn.js +1 -0
- package/dist/src/setup/primitives/run-pnpm.d.ts +1 -17
- package/dist/src/setup/primitives/run-pnpm.js +1 -1
- package/dist/src/setup/project-resolution.js +1 -1
- package/dist/src/setup/prompter.d.ts +18 -0
- package/dist/src/setup/prompter.js +1 -1
- package/dist/src/setup/scaffold/create/add-to-project.d.ts +26 -0
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -0
- package/dist/src/setup/scaffold/create/project.d.ts +17 -0
- package/dist/src/setup/scaffold/create/project.js +11 -11
- package/dist/src/setup/scaffold/update/channels.d.ts +3 -0
- package/dist/src/setup/scaffold/update/channels.js +2 -2
- package/dist/src/setup/scaffold/update/connections.js +3 -3
- package/dist/src/shared/agent-definition.d.ts +5 -3
- 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 +1 -1
- package/dist/src/cli/dev/repl/input-requests.d.ts +0 -38
- package/dist/src/cli/dev/repl/input-requests.js +0 -1
- package/dist/src/cli/dev/repl/input.d.ts +0 -19
- package/dist/src/cli/dev/repl/input.js +0 -1
- package/dist/src/cli/dev/repl/repl.d.ts +0 -62
- package/dist/src/cli/dev/repl/repl.js +0 -2
- package/dist/src/cli/dev/repl/terminal.d.ts +0 -21
- package/dist/src/cli/dev/repl/terminal.js +0 -5
- package/dist/src/services/dev-client/stream.d.ts +0 -5
- package/dist/src/services/dev-client/stream.js +0 -1
- package/dist/src/services/dev-client/url.d.ts +0 -11
- package/dist/src/services/dev-client/url.js +0 -1
- package/dist/src/setup/primitives/pnpm-invocation.d.ts +0 -12
- package/dist/src/setup/primitives/pnpm-invocation.js +0 -1
- package/dist/src/setup/scaffold/update/pnpm-workspace.d.ts +0 -3
- package/dist/src/setup/scaffold/update/pnpm-workspace.js +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.6.0-beta.19
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9061941: The dev TUI's `/model` now opens a configure menu uniting the model and provider setup, and the separate `/vercel` command is removed: "Change model" runs the searchable AI Gateway catalog picker, and "Configure provider" (bold yellow with "Required to enable the agent" until a Vercel link or gateway credential is detected) runs the provider questions `/vercel` used to ask. Each action returns to the menu, which shows each row's current value on its own line — e.g. "AI Gateway (Linked to my-project)" — and keeps the latest outcome visible beneath the options ("✓ Model changed to …"); Esc leaves. Error messages and the startup attention line now point at `/model`, and `/model <provider/model-id>` still applies a model directly.
|
|
8
|
+
|
|
9
|
+
## 0.6.0-beta.18
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- aa5cfdc: Connection and tool `auth` definitions accept an optional `displayName`, and authorization challenges carry it to channels — sign-in buttons now show e.g. "Sign in with Salesforce" instead of a title-cased file name. The value is presentation-only (scope, token cache keys, and callback URLs stay keyed by the path-derived name), a definition-level `displayName` wins over one the strategy stamps on the challenge, and channels keep title-casing the name when neither is set.
|
|
14
|
+
- e55bb46: `eve init` now accepts an existing project directory as its target (e.g. `eve init .`): the project must have a `package.json` and use npm, pnpm, or yarn (bun is not supported yet), the `agent/` files must not already exist, and the missing `eve`/`ai`/`zod` dependencies are added without touching anything else the project owns. pnpm projects additionally receive the pnpm workspace policy. In both modes the final handoff now runs the `eve dev` binary through the project's package manager instead of the project's `dev` script, which in an existing app could start unrelated processes.
|
|
15
|
+
|
|
16
|
+
The bootstrap install disables npm's and pnpm's minimum-release-age cooldown for that single run — the scaffold pins versions younger than typical windows, so the gate would fail every fresh bootstrap. Later installs follow the project's own configuration.
|
|
17
|
+
|
|
18
|
+
- e55bb46: `eve init <name>` now scaffolds the new project with the package manager that launched it: `npx` produces an npm-managed project and `yarn dlx` a yarn one, while `pnpm dlx` and direct binary runs keep today's pnpm scaffold. Non-pnpm scaffolds no longer receive `pnpm-workspace.yaml`, `--channel-web-nextjs` requires a pnpm launch, and a bun launch is rejected until bun support lands.
|
|
19
|
+
- ca290a0: Remove the legacy `eve dev --repl` line-based REPL. The terminal UI is the only interactive dev UI; `--no-ui` starts the server headless. The deprecated `--no-repl` alias is no longer accepted — pass `--no-ui` instead.
|
|
20
|
+
- e55bb46: Run setup and generated-project configuration through package-manager strategies for npm, pnpm, Yarn, and Bun. `eve init --channel-web-nextjs` now works with every supported manager instead of requiring a pnpm launch.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- 1acc94e: Apply `build.externalDependencies` to authored module bundling and hosted output tracing, including imports from workspace packages and subagents.
|
|
25
|
+
- 8afd7bc: Emit `$eve.cache_write_tokens` as a per-turn observability tag, alongside the existing `$eve.input_tokens`, `$eve.output_tokens`, and `$eve.cache_read_tokens`. The value is read from the AI SDK's `usage.inputTokenDetails.cacheWriteTokens` and accumulated across tool-loop steps within a turn.
|
|
26
|
+
- ca290a0: Ctrl+C during a streaming `eve dev` response now aborts the underlying HTTP stream and releases its iterator instead of leaving the connection dangling.
|
|
27
|
+
- ca290a0: `eve dev` no longer clears the terminal (including native scrollback) when a source edit refreshes the agent header — the refreshed header is committed beneath the existing transcript instead.
|
|
28
|
+
|
|
3
29
|
## 0.6.0-beta.17
|
|
4
30
|
|
|
5
31
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -108,9 +108,11 @@ export default defineAgent({
|
|
|
108
108
|
pnpm dlx eve@beta init my-agent
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
-
`eve init` writes a new agent with Eve's default model. Pass `--web` to add the
|
|
111
|
+
`eve init` writes a new agent with Eve's default model. Pass `--channel-web-nextjs` to add the
|
|
112
112
|
Web Chat application. It installs dependencies, initializes Git, and starts the
|
|
113
|
-
development server.
|
|
113
|
+
development server. Targeting an existing npm, pnpm, or yarn project directory (`eve init .`)
|
|
114
|
+
adds the agent files and missing dependencies instead. It does not create a
|
|
115
|
+
Vercel project or deploy the agent.
|
|
114
116
|
|
|
115
117
|
CLI commands:
|
|
116
118
|
|
|
@@ -263,6 +263,8 @@ Declaring `auth` adds two accessors to the tool's `ctx`:
|
|
|
263
263
|
|
|
264
264
|
Throw `ConnectionAuthorizationRequiredError` anywhere in `execute` (directly, via `requireAuth()`, or implicitly from `getToken()`) and you trigger the consent flow, keyed by the tool's name. Calling either accessor on a tool that does not declare `auth` throws.
|
|
265
265
|
|
|
266
|
+
By default the sign-in affordance title-cases the tool's path-derived name — a tool file named `sfdc_lookup.ts` renders "Sign in with Sfdc_lookup". Set `displayName` on the `auth` definition to control what users see instead: `auth: { ...connect("sfdc"), displayName: "Salesforce" }`. It is presentation-only; the tool's name still keys the authorization scope, token cache, and callback URL, and a definition-level `displayName` wins over one the strategy stamps on the challenge.
|
|
267
|
+
|
|
266
268
|
## What to read next
|
|
267
269
|
|
|
268
270
|
- [Security model](./security-model): trust boundaries and the pre-production checklist
|
|
@@ -19,12 +19,12 @@ On startup the TUI prints a header for the connected agent — the model, instru
|
|
|
19
19
|
· Subagents researcher
|
|
20
20
|
· Server http://localhost:3000
|
|
21
21
|
|
|
22
|
-
Type to chat · ↑ history · /new reset session · /model /
|
|
22
|
+
Type to chat · ↑ history · /new reset session · /model /channels /deploy · /exit quit · Ctrl+C interrupt
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
From there the conversation streams straight into your terminal's normal scrollback — your prompts, the agent's replies, reasoning, tool calls, nested subagents, connection-authorization prompts, and any captured `stdout`/`stderr` — so you keep native scrolling, copy/paste, and a transcript that persists after you exit. Each turn is rendered without boxes: a colored gutter glyph marks who's speaking, tool calls collapse to a one-line summary (`✓ get_weather city="SF" → 73°F`), and a subagent's work is indented beneath its `◆` header. A sticky line at the bottom shows the input prompt or the live status (spinner, token usage). Press `Enter` to send; `Ctrl+C` interrupts a running turn or quits at the prompt. Slash commands: `/new` starts a fresh session and `/exit` quits.
|
|
26
26
|
|
|
27
|
-
When `eve dev` runs the server locally, three more slash commands manage the project without leaving the session. `/
|
|
27
|
+
When `eve dev` runs the server locally, three more slash commands manage the project without leaving the session. Bare `/model` opens a two-row configure menu that loops until Esc. "Change model" runs the same searchable model picker setup uses (the AI Gateway catalog, pre-selected on the model the runtime is serving); a model change is written into your agent's authored source, and the command reports success only after Eve confirms the new id (`/model <provider/model-id>` applies one directly, skipping the menu). The provider row opens the provider questions: which model provider to use (picking something other than AI Gateway shows wiring instructions for your own provider and stops there, leaving any existing setup untouched) and how to connect to AI Gateway — paste your own `AI_GATEWAY_API_KEY`, saved straight to `.env.local`, or connect via a project, which walks the same Vercel team/project pickers as setup (picking again re-links) and pulls the project's environment so an AI Gateway credential lands in `.env.local`; the dev server reloads env files automatically, no restart needed. The row demands attention (a bold yellow "Configure provider" with "Required to enable the agent") until a link or gateway credential is detected, then names the connection (e.g. "AI Gateway (Linked to my-project in my-team)") after, and each action's latest outcome stays visible beneath the menu (e.g. "✓ Model changed to openai/gpt-5.5"). `/channels` shows the agent's channel list — already-registered channels render as locked rows — and adds the one you pick, including the Slack Connect provisioning, then installs the dependencies the scaffold added so the dev server can load the new channels right away; after each addition the list repaints with the new channel locked, until Done (or Esc) leaves the flow. `/deploy` ships the agent to Vercel production, linking first when the directory is unlinked. Each command echoes as an invocation line, asks through a bordered panel that takes the input area's place — one question at a time, clearly separate from the chat transcript — and finishes with a one-line `⎿` result; loading states stay on the ephemeral status line instead of piling into the transcript. These commands are not available when connected to a remote server with `--url`, and when a turn fails because AI Gateway authentication is missing or stale, the error points you at `/model` directly. The TUI also checks at startup: a missing model-provider setup surfaces as an attention line — `⚠ 1 setup issue: model provider not linked · /model` — so the fix is visible before the first message fails, and each command's outcome hangs under it with the `⎿` connector.
|
|
28
28
|
|
|
29
29
|
The prompt input behaves like a shell line editor: `↑`/`↓` cycle through the messages you've sent this session, `←`/`→`, Home/End, and `Ctrl+A`/`Ctrl+E` move the caret, and `Ctrl+U`/`Ctrl+K`/`Ctrl+W` kill the line, the rest of the line, or the previous word. If a turn fails terminally — the server session dies or the connection drops — the TUI starts a fresh session and notes it inline so you can keep going (server-side context resets with the old session). Errors render compactly, with docs links highlighted, and a code bug escaping your agent's own code shows its stack trace dim beneath the error headline. Captured server `stdout`/`stderr` renders as dim, indented log runs behind a `│` rule — consecutive lines from the same source share one label, and nothing is ever hidden.
|
|
30
30
|
|
|
@@ -64,7 +64,7 @@ A structured return type for task-mode runs: a subagent, schedule, or remote job
|
|
|
64
64
|
|
|
65
65
|
### `build`
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
Build packaging controls. `externalDependencies` keeps listed packages external while Eve compiles authored modules such as tools and channels, and traces those packages into the hosted output.
|
|
68
68
|
|
|
69
69
|
## Where adjacent settings live
|
|
70
70
|
|
|
@@ -168,7 +168,9 @@ export default defineMcpClientConnection({
|
|
|
168
168
|
});
|
|
169
169
|
```
|
|
170
170
|
|
|
171
|
-
`getToken` runs before every tool call. `startAuthorization` and `completeAuthorization` are both-or-neither: provide one without the other and you get a definition error. The `challenge` rides along verbatim on the `authorization.required` event. Set `url` for redirect/device flows, `userCode` for a device code,
|
|
171
|
+
`getToken` runs before every tool call. `startAuthorization` and `completeAuthorization` are both-or-neither: provide one without the other and you get a definition error. The `challenge` rides along verbatim on the `authorization.required` event. Set `url` for redirect/device flows, `userCode` for a device code, `instructions` as the call to action when there's no URL, and `displayName` for the human-readable provider name channels show on the sign-in affordance (e.g. "Salesforce"). Drop `resume` when the provider keeps flow state server-side, so nothing has to cross the step boundary.
|
|
172
|
+
|
|
173
|
+
`displayName` is presentation-only — the connection's path-derived name still keys the authorization scope, token cache, and callback URL. You can also set `displayName` on the `auth` definition itself (e.g. `auth: { ...connect("sfdc"), displayName: "Salesforce" }`); that definition-level value wins over one the strategy stamps on the challenge, and channels fall back to title-casing the connection name when neither is set.
|
|
172
174
|
|
|
173
175
|
### Signaling authorization state
|
|
174
176
|
|
|
@@ -14,18 +14,29 @@ You also need a model credential. Set the provider or gateway key your model str
|
|
|
14
14
|
|
|
15
15
|
## Create Your Agent
|
|
16
16
|
|
|
17
|
-
Run `eve init` through
|
|
17
|
+
Run `eve init` through your package manager before Eve is installed locally:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
pnpm dlx eve@beta init my-agent
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
The command creates a child directory, uses Eve's default model, installs
|
|
24
|
-
dependencies, initializes Git, and starts the development server.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
dependencies, initializes Git, and starts the development server. Whichever
|
|
25
|
+
manager launches the command owns the new project: `pnpm dlx` scaffolds a
|
|
26
|
+
pnpm project, `npx` an npm one, and `yarn dlx` a yarn one (bun is not
|
|
27
|
+
supported yet). Pass `--channel-web-nextjs` to add the Web Chat
|
|
28
|
+
application; it currently requires a pnpm launch. Stop the server before
|
|
29
|
+
editing the generated agent. The command does not create a Vercel project or
|
|
30
|
+
deploy.
|
|
31
|
+
|
|
32
|
+
The target can also be an existing npm, pnpm, or yarn project directory
|
|
33
|
+
(`eve init .`): the project must have a `package.json`, the `agent/` files
|
|
34
|
+
must not exist yet, and the missing `eve`, `ai`, and `zod` dependencies are
|
|
35
|
+
added without touching anything else the project owns. Either way the final
|
|
36
|
+
handoff runs the `eve dev` binary through the project's package manager,
|
|
37
|
+
never the project's own `dev` script.
|
|
38
|
+
|
|
39
|
+
To add only the dependency to an existing app instead:
|
|
29
40
|
|
|
30
41
|
```bash
|
|
31
42
|
pnpm add eve@beta
|
|
@@ -156,7 +167,7 @@ See [Sessions, runs & streaming](./advanced/sessions-runs-and-streaming) for the
|
|
|
156
167
|
|
|
157
168
|
If a coding agent (Claude Code, Cursor, and the like) is doing the setup, hand it this prompt:
|
|
158
169
|
|
|
159
|
-
<CopyPrompt text="Set up an Eve agent for the user. Eve is a filesystem-first TypeScript framework for durable agents, published as the npm package eve. Read its docs: once eve is installed they are bundled in the package at node_modules/eve/dist/docs/public; before eve is installed, read the published Introduction and Getting Started pages. If the project has no Eve app, scaffold one with `pnpm dlx eve@beta init <name>`; add `--web` only when the user wants Web Chat. The init command installs dependencies, initializes Git, and starts the dev server, so run it in a controllable process and stop it before editing. To add Eve to an existing app, run `pnpm add eve@beta`. Make sure agent/agent.ts and agent/instructions.md exist, then add a first typed tool at agent/tools/get_weather.ts using defineTool from eve/tools with a Zod inputSchema and an inline execute. Start the dev server again, then exercise the HTTP API: create a session with POST /eve/v1/session, attach to GET /eve/v1/session/:id/stream, and send a follow-up with the returned continuationToken. Verify with the project's typecheck, adapt model and provider choices to the project, and do not commit unless the user asks.">
|
|
170
|
+
<CopyPrompt text="Set up an Eve agent for the user. Eve is a filesystem-first TypeScript framework for durable agents, published as the npm package eve. Read its docs: once eve is installed they are bundled in the package at node_modules/eve/dist/docs/public; before eve is installed, read the published Introduction and Getting Started pages. If the project has no Eve app, scaffold one with `pnpm dlx eve@beta init <name>`; add `--channel-web-nextjs` only when the user wants Web Chat. The init command installs dependencies, initializes Git, and starts the dev server, so run it in a controllable process and stop it before editing. To add Eve to an existing app, run `pnpm add eve@beta`. Make sure agent/agent.ts and agent/instructions.md exist, then add a first typed tool at agent/tools/get_weather.ts using defineTool from eve/tools with a Zod inputSchema and an inline execute. Start the dev server again, then exercise the HTTP API: create a session with POST /eve/v1/session, attach to GET /eve/v1/session/:id/stream, and send a follow-up with the returned continuationToken. Verify with the project's typecheck, adapt model and provider choices to the project, and do not commit unless the user asks.">
|
|
160
171
|
Set up an Eve agent: read the Eve docs (bundled at node_modules/eve/dist/docs/public once eve is
|
|
161
172
|
installed), scaffold with `pnpm dlx eve@beta init <name>` (or `pnpm add eve@beta` in an existing app), add
|
|
162
173
|
a typed tool at agent/tools/get_weather.ts, run it with `pnpm dev`, then create a session, stream
|
|
@@ -167,7 +178,7 @@ Once `eve` is a dependency, the full docs are bundled in the package, so the age
|
|
|
167
178
|
|
|
168
179
|
- Docs: `node_modules/eve/dist/docs/public/`
|
|
169
180
|
|
|
170
|
-
`eve init <name>` creates the base agent. Add `--web` for Web Chat, or run
|
|
181
|
+
`eve init <name>` creates the base agent; `eve init .` adds one to an existing npm, pnpm, or yarn project. Add `--channel-web-nextjs` for Web Chat, or run
|
|
171
182
|
`eve channels add slack` later from an interactive terminal.
|
|
172
183
|
|
|
173
184
|
## What to read next
|
|
@@ -79,7 +79,6 @@ Pass a bare URL as the only argument and the UI connects to that server instead
|
|
|
79
79
|
| `--host <host>` | Host interface to bind |
|
|
80
80
|
| `--port <port>` | Port to listen on (defaults to `$PORT`, then `3000`) |
|
|
81
81
|
| `-u, --url <url>` | Connect to an existing server URL instead of starting one |
|
|
82
|
-
| `--repl` | Use the classic line-based REPL instead of the terminal UI |
|
|
83
82
|
| `--no-ui` | Start the server without an interactive UI |
|
|
84
83
|
| `--name <name>` | Title shown in the terminal UI (defaults to the app folder name) |
|
|
85
84
|
| `--tools <mode>` | Tool-call rendering: `full` \| `collapsed` \| `auto-collapsed` \| `hidden` |
|
|
@@ -288,7 +288,7 @@ async function* openStreamIterable(input) {
|
|
|
288
288
|
if (!isStreamDisconnectError(error)) throw error;
|
|
289
289
|
disconnected = true;
|
|
290
290
|
}
|
|
291
|
-
if (!disconnected || remainingReconnectAttempts <= 0) return;
|
|
291
|
+
if (!disconnected || input.signal?.aborted || remainingReconnectAttempts <= 0) return;
|
|
292
292
|
remainingReconnectAttempts -= 1;
|
|
293
293
|
}
|
|
294
294
|
}
|
|
@@ -394,6 +394,7 @@ var ClientSession = class {
|
|
|
394
394
|
if (!isStreamDisconnectError(error)) throw error;
|
|
395
395
|
}
|
|
396
396
|
if (foundBoundary) break;
|
|
397
|
+
if (input.signal?.aborted) break;
|
|
397
398
|
if (remainingReconnectAttempts <= 0) break;
|
|
398
399
|
remainingReconnectAttempts -= 1;
|
|
399
400
|
}
|
|
@@ -288,7 +288,7 @@ async function* openStreamIterable(input) {
|
|
|
288
288
|
if (!isStreamDisconnectError(error)) throw error;
|
|
289
289
|
disconnected = true;
|
|
290
290
|
}
|
|
291
|
-
if (!disconnected || remainingReconnectAttempts <= 0) return;
|
|
291
|
+
if (!disconnected || input.signal?.aborted || remainingReconnectAttempts <= 0) return;
|
|
292
292
|
remainingReconnectAttempts -= 1;
|
|
293
293
|
}
|
|
294
294
|
}
|
|
@@ -394,6 +394,7 @@ var ClientSession = class {
|
|
|
394
394
|
if (!isStreamDisconnectError(error)) throw error;
|
|
395
395
|
}
|
|
396
396
|
if (foundBoundary) break;
|
|
397
|
+
if (input.signal?.aborted) break;
|
|
397
398
|
if (remainingReconnectAttempts <= 0) break;
|
|
398
399
|
remainingReconnectAttempts -= 1;
|
|
399
400
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { detectInvokingPackageManager, detectPackageManager } from "#setup/package-manager.js";
|
|
2
|
+
import { runPackageManagerInstall, spawnPackageManager } from "#setup/primitives/index.js";
|
|
3
|
+
import { addAgentToProject } from "#setup/scaffold/create/add-to-project.js";
|
|
2
4
|
import { ensureChannel, scaffoldBaseProject } from "#setup/scaffold/index.js";
|
|
3
5
|
import { tryInitializeGit } from "./init-git.js";
|
|
4
6
|
export interface InitCliLogger {
|
|
@@ -6,16 +8,22 @@ export interface InitCliLogger {
|
|
|
6
8
|
log(message: string): void;
|
|
7
9
|
}
|
|
8
10
|
export interface InitCommandOptions {
|
|
9
|
-
web
|
|
11
|
+
/** Add the Web Chat channel (a Next.js app). Set by `--channel-web-nextjs`. */
|
|
12
|
+
channelWebNextjs?: boolean;
|
|
10
13
|
}
|
|
11
14
|
export interface InitCommandDependencies {
|
|
15
|
+
addAgentToProject: typeof addAgentToProject;
|
|
16
|
+
detectInvokingPackageManager: typeof detectInvokingPackageManager;
|
|
17
|
+
detectPackageManager: typeof detectPackageManager;
|
|
12
18
|
ensureChannel: typeof ensureChannel;
|
|
13
|
-
|
|
19
|
+
runPackageManagerInstall: typeof runPackageManagerInstall;
|
|
14
20
|
scaffoldBaseProject: typeof scaffoldBaseProject;
|
|
15
|
-
|
|
21
|
+
spawnPackageManager: typeof spawnPackageManager;
|
|
16
22
|
tryInitializeGit: typeof tryInitializeGit;
|
|
17
23
|
}
|
|
18
24
|
/**
|
|
19
|
-
* Creates a new Eve agent
|
|
25
|
+
* Creates a new Eve agent (`target` is a project name), or adds one to an
|
|
26
|
+
* existing project (`target` is a directory), without prompts or external
|
|
27
|
+
* provisioning.
|
|
20
28
|
*/
|
|
21
|
-
export declare function runInitCommand(logger: InitCliLogger, parentDirectory: string,
|
|
29
|
+
export declare function runInitCommand(logger: InitCliLogger, parentDirectory: string, target: string, options: InitCommandOptions, dependencies?: InitCommandDependencies): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{tryInitializeGit}from"./init-git.js";import{join,resolve}from"node:path";import{ensureChannel,scaffoldBaseProject}from"#setup/scaffold/index.js";import{mkdtemp,rename,rm}from"node:fs/promises";import{EVE_WORDMARK}from"#cli/banner.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{SPINNER_FRAMES,SPINNER_FRAME_MS}from"#setup/cli/rail-log.js";import{pathExists}from"#setup/path-exists.js";import{parseProjectName}from"#setup/project-name.js";import{
|
|
1
|
+
import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{tryInitializeGit}from"./init-git.js";import{join,resolve}from"node:path";import{ensureChannel,scaffoldBaseProject}from"#setup/scaffold/index.js";import{mkdtemp,rename,rm,stat}from"node:fs/promises";import{EVE_WORDMARK}from"#cli/banner.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{SPINNER_FRAMES,SPINNER_FRAME_MS}from"#setup/cli/rail-log.js";import{detectInvokingPackageManager,detectPackageManager}from"#setup/package-manager.js";import{pathExists}from"#setup/path-exists.js";import{parseProjectName}from"#setup/project-name.js";import{eveDevArguments,runPackageManagerInstall,spawnPackageManager}from"#setup/primitives/index.js";import{addAgentToProject}from"#setup/scaffold/create/add-to-project.js";var import_picocolors=__toESM(require_picocolors(),1);const defaultDependencies={addAgentToProject,detectInvokingPackageManager,detectPackageManager,ensureChannel,runPackageManagerInstall,scaffoldBaseProject,spawnPackageManager,tryInitializeGit};async function resolveTargetDirectory(e,t){let n=resolve(e,t);return(await stat(n).catch(()=>void 0))?.isDirectory()?n:void 0}async function addToExistingProject(e,t,n){if(t.channelWebNextjs===!0)throw Error("`--channel-web-nextjs` is not supported when adding an agent to an existing project. Run `eve channels add web` from the project afterwards instead.");let r=await n.detectPackageManager(e);return await n.addAgentToProject({projectRoot:e,model:DEFAULT_AGENT_MODEL_ID,packageManager:r.kind}),r.kind}function resolveScaffoldPackageManager(e){return e.detectInvokingPackageManager()??`pnpm`}const EVE_INIT_PACKAGE_VERSION=`beta`;async function scaffoldProject(e,t,n,a,o){let u=resolve(e),d=join(u,t);if(await pathExists(d))throw Error(`Cannot create project because "${d}" already exists.`);let f=await mkdtemp(join(u,`.eve-init-`));try{let e=await o.scaffoldBaseProject({projectName:t,model:DEFAULT_AGENT_MODEL_ID,packageManager:n,targetDirectory:f,evePackageVersion:EVE_INIT_PACKAGE_VERSION});return a.channelWebNextjs===!0&&await o.ensureChannel({projectRoot:e,kind:`web`,packageManager:n,configureVercelServices:!1,webPackageVersions:{evePackageVersion:EVE_INIT_PACKAGE_VERSION}}),await rename(e,d),d}finally{await rm(f,{recursive:!0,force:!0})}}function startSpinner(e,t){if(process.stdout.isTTY!==!0)return e.log(t),{stop(){}};let row=e=>`${import_picocolors.default.green(e)} ${t}`;process.stdout.write(row(SPINNER_FRAMES[0]));let n=0,r=setInterval(()=>{n+=1;let e=SPINNER_FRAMES[n%SPINNER_FRAMES.length]??SPINNER_FRAMES[0];process.stdout.write(`\r\u001B[K${row(e)}`)},SPINNER_FRAME_MS);r.unref?.();let i=!1;return{stop(){i||(i=!0,clearInterval(r),process.stdout.write(`\r\x1B[K`))}}}async function runInitCommand(e,t,n,r,i=defaultDependencies){let a=await resolveTargetDirectory(t,n),o,s;a===void 0?(o=resolveScaffoldPackageManager(i),s=await scaffoldProject(t,parseProjectName(n),o,r,i),e.log(`${import_picocolors.default.green(`✓`)} Created an ${EVE_WORDMARK} agent in ${import_picocolors.default.bold(s)}`)):(o=await addToExistingProject(a,r,i),s=a,e.log(`${import_picocolors.default.green(`✓`)} Added an ${EVE_WORDMARK} agent to ${import_picocolors.default.bold(s)}`));let c=[],l=startSpinner(e,`Installing dependencies...`),u;try{u=await i.runPackageManagerInstall(o,s,{bypassMinimumReleaseAge:!0,onOutput:e=>c.push(e.text)})}finally{l.stop()}if(!u){for(let t of c)e.error(t);throw Error(`Failed to install dependencies in "${s}".`)}if(e.log(`${import_picocolors.default.green(`✓`)} Installed dependencies`),a===void 0){let t=i.tryInitializeGit(s);t.kind===`failed`&&e.error(import_picocolors.default.yellow(`Git initialization failed: ${t.reason}`))}if(e.log(import_picocolors.default.dim(`$ eve dev`)),!await i.spawnPackageManager(o,s,eveDevArguments(o)))throw Error(`Development server exited unsuccessfully in "${s}".`)}export{runInitCommand};
|
|
@@ -15,7 +15,7 @@ export interface LinkCommandDependencies {
|
|
|
15
15
|
* `eve link`: pick a Vercel team and project (re-linking when one is already
|
|
16
16
|
* linked), run `vercel link`, then pull env so the AI Gateway credential lands
|
|
17
17
|
* in `.env.local`. The flow itself is {@link runLinkFlow}, shared with the dev
|
|
18
|
-
* TUI's
|
|
18
|
+
* TUI `/model` menu's provider row. Interactive only: the pickers are the point of the command,
|
|
19
19
|
* so a non-TTY run refuses with guidance instead of guessing a project.
|
|
20
20
|
*/
|
|
21
21
|
export declare function runLinkCommand(logger: LinkCliLogger, appRoot: string, dependencies?: LinkCommandDependencies): Promise<void>;
|
|
@@ -18,7 +18,7 @@ export interface AgentHeaderInput {
|
|
|
18
18
|
theme: Theme;
|
|
19
19
|
/** Available terminal width. */
|
|
20
20
|
width: number;
|
|
21
|
-
/** Mention
|
|
21
|
+
/** Mention the setup slash commands in the key hints (local sessions only). */
|
|
22
22
|
setupCommands?: boolean;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{truncate}from"./tool-format.js";function buildAgentHeader(t){let{theme:n,info:r,name:i,serverUrl:a,width:o}=t,s=n.colors,c=[];if(r){c.push({label:`Model`,value:r.agent.model.id}),r.instructions.static&&c.push({label:`Instructions`,value:r.instructions.static.logicalPath});let e=[...r.tools.authored,...r.tools.dynamic.filter(e=>e.origin===`authored`).map(e=>({name:e.slug}))];e.length>0&&c.push({label:`Tools`,value:joinNames(e)});let t=[...r.skills.static,...r.skills.dynamic.filter(e=>e.origin===`authored`).map(e=>({name:e.slug}))];t.length>0&&c.push({label:`Skills`,value:joinNames(t)}),r.subagents.local.length>0&&c.push({label:`Subagents`,value:joinNames(r.subagents.local)}),r.schedules.length>0&&c.push({label:`Schedules`,value:joinNames(r.schedules)}),r.sandbox&&c.push({label:`Sandbox`,value:r.sandbox.logicalPath})}c.push({label:`Server`,value:a,link:!0});let l=c.reduce((e,t)=>Math.max(e,t.label.length),0),u=Math.max(8,o-l-6),d=[];if(d.push(` ${s.bold(`${n.glyph.brand} ${i}`)}`),r&&(r.diagnostics.discoveryErrors>0||r.diagnostics.discoveryWarnings>0)){let e=[];r.diagnostics.discoveryErrors>0&&e.push(s.red(`${r.diagnostics.discoveryErrors} error${plural(r.diagnostics.discoveryErrors)}`)),r.diagnostics.discoveryWarnings>0&&e.push(s.yellow(`${r.diagnostics.discoveryWarnings} warning${plural(r.diagnostics.discoveryWarnings)}`)),d.push(` ${s.dim(n.glyph.warning)} ${e.join(s.dim(` · `))}`)}for(let t of c){let r=s.dim(n.glyph.dot)+` `+s.gray(t.label.padEnd(l)),i=truncate(t.value,u);d.push(` ${r} ${t.link?s.cyan(i):i}`)}d.push(``);let f=t.setupCommands?` ${n.glyph.dot} /model /
|
|
1
|
+
import{truncate}from"./tool-format.js";function buildAgentHeader(t){let{theme:n,info:r,name:i,serverUrl:a,width:o}=t,s=n.colors,c=[];if(r){c.push({label:`Model`,value:r.agent.model.id}),r.instructions.static&&c.push({label:`Instructions`,value:r.instructions.static.logicalPath});let e=[...r.tools.authored,...r.tools.dynamic.filter(e=>e.origin===`authored`).map(e=>({name:e.slug}))];e.length>0&&c.push({label:`Tools`,value:joinNames(e)});let t=[...r.skills.static,...r.skills.dynamic.filter(e=>e.origin===`authored`).map(e=>({name:e.slug}))];t.length>0&&c.push({label:`Skills`,value:joinNames(t)}),r.subagents.local.length>0&&c.push({label:`Subagents`,value:joinNames(r.subagents.local)}),r.schedules.length>0&&c.push({label:`Schedules`,value:joinNames(r.schedules)}),r.sandbox&&c.push({label:`Sandbox`,value:r.sandbox.logicalPath})}c.push({label:`Server`,value:a,link:!0});let l=c.reduce((e,t)=>Math.max(e,t.label.length),0),u=Math.max(8,o-l-6),d=[];if(d.push(` ${s.bold(`${n.glyph.brand} ${i}`)}`),r&&(r.diagnostics.discoveryErrors>0||r.diagnostics.discoveryWarnings>0)){let e=[];r.diagnostics.discoveryErrors>0&&e.push(s.red(`${r.diagnostics.discoveryErrors} error${plural(r.diagnostics.discoveryErrors)}`)),r.diagnostics.discoveryWarnings>0&&e.push(s.yellow(`${r.diagnostics.discoveryWarnings} warning${plural(r.diagnostics.discoveryWarnings)}`)),d.push(` ${s.dim(n.glyph.warning)} ${e.join(s.dim(` · `))}`)}for(let t of c){let r=s.dim(n.glyph.dot)+` `+s.gray(t.label.padEnd(l)),i=truncate(t.value,u);d.push(` ${r} ${t.link?s.cyan(i):i}`)}d.push(``);let f=t.setupCommands?` ${n.glyph.dot} /model /channels /deploy`:``;return d.push(` ${s.dim(`Type to chat ${n.glyph.dot} ↑ history ${n.glyph.dot} /new reset session${f} ${n.glyph.dot} /exit quit ${n.glyph.dot} Ctrl+C interrupt`)}`),d}function joinNames(e){return e.map(e=>e.name).join(`, `)}function plural(e){return e===1?``:`s`}export{buildAgentHeader};
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import type { Theme } from "./theme.js";
|
|
13
13
|
export type ToolStatus = "running" | "done" | "error" | "denied" | "approval";
|
|
14
|
-
export type BlockKind = "user" | "assistant" | "reasoning" | "tool" | "error" | "notice" | "warning" | "result" | "flow" | "command" | "question" | "subagent" | "subagent-step" | "subagent-tool" | "connection-auth" | "log";
|
|
14
|
+
export type BlockKind = "user" | "assistant" | "reasoning" | "tool" | "error" | "notice" | "warning" | "result" | "flow" | "command" | "question" | "subagent" | "subagent-step" | "subagent-tool" | "connection-auth" | "log" | "agent-header";
|
|
15
15
|
/**
|
|
16
16
|
* One renderable transcript unit. Fields are interpreted per `kind`; unset
|
|
17
17
|
* fields are simply omitted from the rendered output.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import{formatValuePretty,truncate}from"./tool-format.js";import{sliceVisible,visibleLength,wrapVisibleLine}from"./terminal-text.js";import{renderMarkdown}from"./markdown.js";import{isPromptControlCommand}from"./prompt-commands.js";function renderBlockLines(e,t,n,i){let a=nestingPrefix(e.depth??0,n);return renderBody(e,Math.max(8,t-visibleLength(a)),n,i).map(e=>`${a}${e}`)}function nestingPrefix(e,t){return e<=0?``:`${t.colors.orange(t.glyph.rule)} `.repeat(e)}function renderBody(e,t,n,r){switch(e.kind){case`user`:return renderUser(e,t,n);case`assistant`:case`subagent-step`:return renderProse(e,t,n);case`reasoning`:return renderReasoning(e,t,n);case`tool`:case`subagent-tool`:return renderTool(e,t,n,r);case`error`:return renderError(e,t,n);case`notice`:return renderNotice(e,t,n);case`warning`:return renderWarning(e,t,n);case`result`:return renderResult(e,t,n);case`flow`:return renderFlow(e,t,n);case`command`:return renderCommand(e,n);case`question`:case`connection-auth`:return renderPreformatted(e,t,n);case`log`:return renderLog(e,t,n,r);case`subagent`:return renderSubagentHeader(e,t,n)
|
|
1
|
+
import{formatValuePretty,truncate}from"./tool-format.js";import{sliceVisible,visibleLength,wrapVisibleLine}from"./terminal-text.js";import{renderMarkdown}from"./markdown.js";import{isPromptControlCommand}from"./prompt-commands.js";function renderBlockLines(e,t,n,i){let a=nestingPrefix(e.depth??0,n);return renderBody(e,Math.max(8,t-visibleLength(a)),n,i).map(e=>`${a}${e}`)}function nestingPrefix(e,t){return e<=0?``:`${t.colors.orange(t.glyph.rule)} `.repeat(e)}function renderBody(e,t,n,r){switch(e.kind){case`user`:return renderUser(e,t,n);case`assistant`:case`subagent-step`:return renderProse(e,t,n);case`reasoning`:return renderReasoning(e,t,n);case`tool`:case`subagent-tool`:return renderTool(e,t,n,r);case`error`:return renderError(e,t,n);case`notice`:return renderNotice(e,t,n);case`warning`:return renderWarning(e,t,n);case`result`:return renderResult(e,t,n);case`flow`:return renderFlow(e,t,n);case`command`:return renderCommand(e,n);case`question`:case`connection-auth`:return renderPreformatted(e,t,n);case`log`:return renderLog(e,t,n,r);case`subagent`:return renderSubagentHeader(e,t,n);case`agent-header`:return(e.body??``).split(`
|
|
2
|
+
`)}}function renderUser(e,t,n){let r=n.colors.cyan(n.glyph.user);return wrap(e.body??``,t-2).map(e=>`${r} ${e}`)}function renderProse(e,t,n){let r=[],o=e.kind===`subagent-step`,s=o?``:`${n.colors.bold(n.colors.white(n.glyph.brand))} `,c=o?``:` `;e.reasoning&&e.reasoning.trim().length>0&&r.push(...renderReasoningLines(e.reasoning,t,n));let l=(e.body??``).trim();return l.length===0&&r.length===0?[`${s}${n.colors.dim(`thinking${n.glyph.ellipsis}`)}`]:(l.length>0&&renderMarkdown(l).split(`
|
|
2
3
|
`).flatMap(e=>wrapVisibleLine(e,t-c.length)).forEach((e,t)=>{t===0&&!o&&r.length===0?r.push(`${s}${e}`):r.push(`${c}${e}`)}),r.length>0?r:[`${s}`])}function renderReasoning(e,t,n){return e.collapsed?[`${n.colors.gray(n.glyph.reasoning)} ${n.colors.dim(`thinking`)}`]:renderReasoningLines(e.body??``,t,n,n.glyph.reasoning)}function renderReasoningLines(e,t,n,r){let i=r?2:0,a=wrap(e.trim(),t-i);return a.length===0?[]:a.map((e,t)=>`${r?t===0?`${n.colors.gray(r)} `:` `:``}${n.colors.dim(n.colors.italic(e))}`)}function renderTool(e,n,r,i){let{icon:a,accent:o}=toolGlyph(e.status??`running`,r,i),s=e.title??`tool`,c=n-2,l=truncatePlain(s,c),u=`${a} ${r.colors.bold(l)}`,d=c-l.length-2,f=e.subtitle??``;f.length>0&&d>=6&&(u+=` ${r.colors.gray(truncate(f,d))}`);let p=[u];return e.expanded?p.push(...renderToolExpanded(e,n,r)):e.status===`done`&&e.result&&e.result.length>0?p.push(resultLine(r.glyph.arrow,e.result,n,r,o)):e.status===`error`&&e.result?p.push(resultLine(r.glyph.arrow,e.result,n,r,r.colors.red)):e.status===`denied`&&p.push(resultLine(r.glyph.arrow,`denied`,n,r,r.colors.yellow)),p}function renderToolExpanded(t,n,r){let i=[],push=(t,a,o)=>{if(a!==void 0){i.push(` ${r.colors.dim(t)}`);for(let t of wrap(formatValuePretty(a),n-4))i.push(` ${o(t)}`)}};return push(`input`,t.toolInput,r.colors.gray),t.status===`error`&&t.result?push(`error`,t.result,r.colors.red):push(`output`,t.toolOutput,r.colors.gray),i}function resultLine(e,n,r,i,a){let o=r-4;return` ${i.colors.dim(e)} ${a(truncate(n,o))}`}function toolGlyph(e,t,n){switch(e){case`done`:return{icon:t.colors.green(t.glyph.success),accent:t.colors.gray};case`error`:return{icon:t.colors.red(t.glyph.error),accent:t.colors.red};case`denied`:return{icon:t.colors.yellow(t.glyph.warning),accent:t.colors.yellow};case`approval`:return{icon:t.colors.yellow(t.glyph.question),accent:t.colors.yellow};default:return{icon:t.colors.yellow(n.spinner),accent:t.colors.gray}}}function renderError(e,t,n){let r=n.colors.red(n.colors.bold(n.glyph.error)),i=e.title??`Error`,a=[`${r} ${n.colors.red(n.colors.bold(i))}`];for(let r of wrap(e.body??``,t-2))a.push(` ${colorizeError(r,n)}`);return a.push(...renderErrorDetail(e.detail,t,n)),a}function renderErrorDetail(e,t,n){if(e===void 0||e.trim().length===0)return[];let r=e.split(`
|
|
3
4
|
`),i=r.slice(0,12),a=i.map(e=>` ${n.colors.dim(truncatePlain(e,Math.max(1,t-2)))}`),o=r.length-i.length;return o>0&&a.push(` ${n.colors.dim(`${n.glyph.ellipsis} +${o} more line${o===1?``:`s`}`)}`),a}const URL_PATTERN=/(https?:\/\/\S+)/u;function colorizeError(e,t){return URL_PATTERN.test(e)?e.split(URL_PATTERN).map((e,n)=>n%2==1?t.colors.cyan(e):t.colors.red(e)).join(``):t.colors.red(e)}function renderNotice(e,t,n){let r=n.colors.dim(n.glyph.dot),i=wrap(e.body??``,t-2);return i.length===0?[r]:i.map(e=>`${r} ${n.colors.dim(e)}`)}function renderWarning(e,t,n){let r=n.colors.yellow(n.glyph.warning);return wrap(e.body??``,t-2).map((e,t)=>`${t===0?r:` `} ${paintCommands(e,n)}`)}function paintCommands(e,t){return e.replace(/\/[a-z-]+/g,e=>isPromptControlCommand(e)?t.colors.blue(e):e)}function renderCommand(e,t){let n=t.colors;return[`${n.cyan(t.glyph.user)} ${n.blue(e.body??``)}`]}function renderFlow(e,t,n){let r=n.colors,i=e.title??`info`,a=i===`success`?r.green(n.glyph.success):i===`warning`?r.yellow(n.glyph.warning):i===`error`?r.red(n.glyph.error):r.dim(n.glyph.dot),o=wrap(e.body??``,t-2),paint=e=>i===`info`?r.dim(e):e;return o.map((e,t)=>`${t===0?a:` `} ${paint(e)}`)}function renderResult(e,t,n){let r=n.colors.dim(n.glyph.elbow),i=wrap(e.body??``,t-7);return i.length===0?[` ${r}`]:i.map((e,t)=>t===0?` ${r} ${n.colors.dim(e)}`:` ${n.colors.dim(e)}`)}function renderPreformatted(e,t,n){let r=e.kind===`connection-auth`?n.colors.yellow(n.glyph.connection):n.colors.yellow(n.colors.bold(n.glyph.question)),a=e.title??``,o=[`${r} ${n.colors.bold(a)}`];for(let n of(e.body??``).split(`
|
|
4
5
|
`))for(let e of wrapVisibleLine(n,t-2))o.push(` ${e}`);return o}function renderLog(e,t,n,a){let o=e.title===`stderr`,s=o?n.colors.red:n.colors.gray,c=n.colors.dim(n.glyph.rule),l=o?`stderr`:`stdout`,u=n.colors.dim(`${l} ${n.glyph.dot} `),d=visibleLength(u),f=` `.repeat(d),p=a.previous?.kind===`log`&&a.previous.title===e.title,m=(e.body??``).split(`
|
|
@@ -51,7 +51,7 @@ export declare function formatFailureMessage(event: FailureStreamEvent): string;
|
|
|
51
51
|
*/
|
|
52
52
|
export declare function formatFailureDetail(event: FailureStreamEvent): string | undefined;
|
|
53
53
|
/**
|
|
54
|
-
* Minimal TUI rendering for a gateway-auth failure when `/
|
|
54
|
+
* Minimal TUI rendering for a gateway-auth failure when `/model` is available
|
|
55
55
|
* locally. Replaces the harness's full summary — whose remediation names CLI
|
|
56
56
|
* commands and dashboard URLs — with one actionable line; the caller drops
|
|
57
57
|
* the diagnostic detail along with it. The variant is picked off the summary
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{GATEWAY_AUTHENTICATION_ERROR_NAME,GATEWAY_AUTH_FAILURE_SUMMARY_NAME}from"#harness/model-call-error.js";var InterruptedError=class extends Error{constructor(){super(`Interrupted`),this.name=`InterruptedError`}};function interruptedError(){return new InterruptedError}function isInterruptedError(e){return e instanceof InterruptedError}function isAbortLikeError(e){return e instanceof Error?e.name===`AbortError`||/\babort(?:ed)?\b/iu.test(e.message):!1}function failureKey(e){return`${e.data.code}:${e.data.message}`}function formatFailureMessage(e){let{code:t,message:n}=e.data;return!t||n===t||n.startsWith(`${t}:`)||n.startsWith(`${t} `)?n:`${t}: ${n}`}function formatFailureDetail(e){let t=e.data.details;if(typeof t!=`object`||!t)return;let n=t.detail;if(typeof n!=`string`)return;let r=n.trim();if(!(r.length===0||r===e.data.message.trim()))return r}function formatGatewayAuthFailureNotice(e){let t=e.data.message;return/rejected the provided API key|Invalid API key/i.test(t)?`AI Gateway rejected your AI_GATEWAY_API_KEY. Run /
|
|
1
|
+
import{GATEWAY_AUTHENTICATION_ERROR_NAME,GATEWAY_AUTH_FAILURE_SUMMARY_NAME}from"#harness/model-call-error.js";var InterruptedError=class extends Error{constructor(){super(`Interrupted`),this.name=`InterruptedError`}};function interruptedError(){return new InterruptedError}function isInterruptedError(e){return e instanceof InterruptedError}function isAbortLikeError(e){return e instanceof Error?e.name===`AbortError`||/\babort(?:ed)?\b/iu.test(e.message):!1}function failureKey(e){return`${e.data.code}:${e.data.message}`}function formatFailureMessage(e){let{code:t,message:n}=e.data;return!t||n===t||n.startsWith(`${t}:`)||n.startsWith(`${t} `)?n:`${t}: ${n}`}function formatFailureDetail(e){let t=e.data.details;if(typeof t!=`object`||!t)return;let n=t.detail;if(typeof n!=`string`)return;let r=n.trim();if(!(r.length===0||r===e.data.message.trim()))return r}function formatGatewayAuthFailureNotice(e){let t=e.data.message;return/rejected the provided API key|Invalid API key/i.test(t)?`AI Gateway rejected your AI_GATEWAY_API_KEY. Run /model to refresh credentials, or update it in .env.local (a stale shell export can shadow it).`:/rejected the OIDC token|Invalid OIDC token/i.test(t)?`Your AI Gateway OIDC token is invalid or expired. Run /model to refresh it, or set AI_GATEWAY_API_KEY in .env.local.`:`There is no AI_GATEWAY_API_KEY set. Run /model to connect this to a project and refresh AI Gateway credentials, or set it manually in .env.local.`}function isGatewayAuthFailure(n){let r=n.data.details;if(typeof r!=`object`||!r)return!1;let i=r;return i.gatewayName===GATEWAY_AUTHENTICATION_ERROR_NAME||i.name===GATEWAY_AUTH_FAILURE_SUMMARY_NAME}export{InterruptedError,failureKey,formatFailureDetail,formatFailureMessage,formatGatewayAuthFailureNotice,interruptedError,isAbortLikeError,isGatewayAuthFailure,isInterruptedError};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ApplyModelOutcome } from "#setup/flows/model.js";
|
|
1
2
|
import type { PromptCommandHandler } from "./runner.js";
|
|
2
3
|
export interface PromptCommandHandlerOptions {
|
|
3
4
|
readonly appRoot?: string;
|
|
@@ -5,6 +6,6 @@ export interface PromptCommandHandlerOptions {
|
|
|
5
6
|
readonly applyModel?: (input: {
|
|
6
7
|
appRoot: string;
|
|
7
8
|
slug: string;
|
|
8
|
-
}) => Promise<
|
|
9
|
+
}) => Promise<ApplyModelOutcome>;
|
|
9
10
|
}
|
|
10
11
|
export declare function createPromptCommandHandler(options: PromptCommandHandlerOptions): PromptCommandHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function createPromptCommandHandler(e){return{async handle(t,n){let r=e.appRoot;if(r===void 0)return`/${t.name} needs eve dev running the local server (it is not available with --url).`;if(t.name===`model`&&t.argument.length>0){let
|
|
1
|
+
function createPromptCommandHandler(e){return{async handle(t,n){let r=e.appRoot;if(r===void 0)return`/${t.name} needs eve dev running the local server (it is not available with --url).`;if(t.name===`model`&&t.argument.length>0){let{changeAgentModel:n,formatApplyModelOutcome:i}=await import(`#setup/flows/model.js`),a=e.applyModel??n;try{return i(await a({appRoot:r,slug:t.argument}))}catch(e){return`Couldn't change the model: ${e instanceof Error?e.message:String(e)}`}}let i=n.renderer.setupFlow;if(i===void 0)return`/${t.name} is not supported by this renderer.`;let{runTuiSetupCommand:a,SETUP_FLOW_TITLES:o}=await import(`./setup-commands.js`);i.begin(o[t.name]);let s=!0;try{let e=await a({command:t.name,appRoot:r,renderer:i});return s=e.preserveFlowDiagnostics,e.message}finally{i.end({preserveDiagnostics:s})}}}}export{createPromptCommandHandler};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const PROMPT_COMMANDS=[{name:`help`,aliases:[],description:`Show available commands`,takesArgument:!1,build:()=>({type:`help`})},{name:`new`,aliases:[],description:`Start a fresh session`,takesArgument:!1,build:()=>({type:`new`})},{name:`model`,aliases:[],description:`
|
|
1
|
+
const PROMPT_COMMANDS=[{name:`help`,aliases:[],description:`Show available commands`,takesArgument:!1,build:()=>({type:`help`})},{name:`new`,aliases:[],description:`Start a fresh session`,takesArgument:!1,build:()=>({type:`new`})},{name:`model`,aliases:[],description:`Configure the agent's model and provider`,argumentHint:`[provider/model]`,takesArgument:!0,build:e=>({type:`extension`,name:`model`,argument:e})},{name:`channels`,aliases:[],description:`Add chat channels to the agent`,takesArgument:!1,build:()=>({type:`extension`,name:`channels`,argument:``})},{name:`deploy`,aliases:[],description:`Deploy the agent to Vercel`,takesArgument:!1,build:()=>({type:`extension`,name:`deploy`,argument:``})},{name:`exit`,aliases:[`quit`],description:`Quit the TUI`,takesArgument:!1,build:()=>({type:`exit`})}];function parsePromptCommand(t){let n=t.trim();if(!n.startsWith(`/`))return null;for(let t of PROMPT_COMMANDS)for(let e of[t.name,...t.aliases]){let r=`/${e}`;if(n===r)return t.build(``);if(t.takesArgument&&n.startsWith(`${r} `))return t.build(n.slice(r.length).trim())}return null}function isPromptControlCommand(e){return parsePromptCommand(e)!==null}function formatPromptCommandHelp(){let t=PROMPT_COMMANDS.map(e=>{let t=e.argumentHint===void 0?``:` ${e.argumentHint}`,n=e.aliases.map(e=>` (/${e})`).join(``);return{invocation:`/${e.name}${t}${n}`,description:e.description}}),n=Math.max(...t.map(e=>e.invocation.length))+2;return t.map(e=>e.invocation.padEnd(n)+e.description).join(`
|
|
2
2
|
`)}export{PROMPT_COMMANDS,formatPromptCommandHelp,isPromptControlCommand,parsePromptCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{formatPromptCommandHelp,parsePromptCommand}from"./prompt-commands.js";import{failureKey,formatFailureDetail,formatFailureMessage,formatGatewayAuthFailureNotice,isAbortLikeError,isGatewayAuthFailure,isInterruptedError}from"./errors.js";import{BOOT_DETECTIONS,detectSetupIssues,formatSetupIssuesLine}from"./setup-issues.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;#h;#g;#_=new Map;#v=new Map;#y=new Map;#b=new Map;#x=new Set;#S=!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.appRoot!==void 0&&(this.#p=e.appRoot),e.promptCommandHandler!==void 0&&(this.#m=e.promptCommandHandler),this.#h=e.bootDetections??BOOT_DETECTIONS,e.serverUrl!==void 0&&(this.#f=e.serverUrl,this.#d=createDevelopmentRuntimeArtifactSessionRefresher({serverUrl:e.serverUrl}))}async#C(){let e=this.#f;if(e===void 0){await this.#D(void 0);return}let t;try{t=await this.#t?.info()}catch{t=void 0}this.#g=t;let n={name:this.#r,serverUrl:e};t!==void 0&&(n.info=t),this.#p!==void 0&&(n.setupCommands=!0),this.#n.renderAgentHeader?.(n),await this.#D(t)}async run(){let n=this.#r,r,i,a=!1,o=!1;for(await this.#C();;){if(!o){if(r==null){if(!this.#n.readPrompt){if(a)return;throw Error(`No prompt was provided and the renderer does not support prompt input.`)}try{r=await this.#T({title:n})}catch(e){if(isInterruptedError(e))return;throw e}if(r==null)return}let s=parsePromptCommand(r);if(s?.type===`exit`){this.#n.shutdown?.();return}if(s?.type===`new`){this.#w(),i=void 0,o=!1,r=void 0,this.#n.reset?.();continue}if(s?.type===`help`){this.#O(formatPromptCommandHelp()),i=void 0,o=!1,r=void 0;continue}if(s?.type===`extension`){try{let e=this.#m===void 0?`/${s.name} is not available in this session.`:await this.#m.handle(s,{renderer:this.#n,title:n});e!==void 0&&this.#O(e)}catch(e){if(isInterruptedError(e))return;throw e}i=void 0,r=void 0,o=!1;continue}a=!0}let s=await this.#E({prompt:o?void 0:r,inputResponses:i});try{await this.#n.renderStream(s,{title:n,submittedPrompt:r,continueSession:!!this.#n.readPrompt,tools:this.#i,reasoning:this.#a,subagents:this.#o,connectionAuth:this.#s,assistantResponseStats:this.#c,contextSize:this.#l});let e=s.turnState?.pendingApprovals??[],t=s.turnState?.pendingQuestions??[];if(e.length>0||t.length>0){let a=[];if(e.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 e){let e=await this.#n.readToolApproval(t,{title:n});a.push({requestId:t.approvalId,optionId:e.approved?`approve`:`deny`}),this.#_.delete(t.approvalId)}}if(t.length>0){if(!this.#n.readInputQuestion)throw Error(`An interactive question was requested, but the renderer does not support input questions.`);for(let e of t){let t=toAgentTUIInputQuestion(e),r=await this.#n.readInputQuestion(t,{title:n});if(r===void 0)continue;let i={requestId:e.requestId};r.optionId!==void 0&&(i.optionId=r.optionId),r.text!==void 0&&(i.text=r.text),a.push(i),this.#_.delete(e.requestId)}}o=!0,i=a,r=void 0;continue}s.turnState&&s.turnState.boundaryEvent===void 0&&(this.#S=!0)}catch(e){if(isInterruptedError(e))return;throw e}o=!1,i=void 0,r=void 0,this.#S&&(this.#S=!1,this.#w(),this.#n.renderNotice?.(`Session ended — started a new session. Earlier context was cleared.`))}}#w(){for(let e of this.#y.values())e.abort();this.#y.clear(),this.#v.clear(),this.#_.clear(),this.#b.clear(),this.#x.clear(),this.#t&&(this.#e=this.#t.session()),this.#d?.clear()}async#T(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.#k(),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#E(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.#k(),session:this.#e})),n=await this.#e.send(t)}catch(e){if(isInterruptedError(e))throw e;return this.#S=!0,{events:errorOnlyTUIStream({errorText:this.#u(e)}),turnState:createTurnState()}}let r=createTurnState();return{events:eveEventsToTUIStream({events:n,pendingInputRequests:this.#_,subagentRuns:this.#v,turnState:r,onSubagentCalled:e=>this.#N(e),onSubagentCompleted:e=>this.#F(e),onConnectionAuthRequired:e=>this.#A(e),onConnectionAuthCompleted:e=>this.#j(e),onTerminalFailure:()=>{this.#S=!0},failureOverride:this.#p===void 0?void 0:e=>isGatewayAuthFailure(e)?formatGatewayAuthFailureNotice(e):void 0}),turnState:r}}async#D(e){if(this.#p===void 0||this.#n.renderSetupWarning===void 0)return;let t={appRoot:this.#p,env:process.env};e!==void 0&&(t.info=e);let n=await detectSetupIssues(t,this.#h);n.length!==0&&this.#n.renderSetupWarning(formatSetupIssuesLine(n))}#O(e){if(this.#n.renderCommandResult!==void 0){this.#n.renderCommandResult(e);return}this.#n.renderNotice?.(e)}async#k(){let e=this.#g,t;try{t=await this.#t?.info()}catch{t=void 0}t!==void 0&&(this.#g=t,this.#f!==void 0&&this.#n.renderAgentHeader?.({info:t,name:this.#r,serverUrl:this.#f,setupCommands:this.#p!==void 0})),(!this.#n.renderAgentHeader||t===void 0)&&this.#n.renderNotice?.(formatAgentUpdateNotice(e,t))}#A(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.#b.set(e.data.name,t),this.#M(t)}#j(e){let t=this.#b.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.#b.set(e.data.name,t),this.#x.delete(e.data.name),this.#M(t),this.#n.setConnectionAuthPendingCount?.(this.#x.size)}#M(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)}#N(e){let t=e.data.callId;if(this.#y.has(t))return;let n=this.#t;if(!n)return;let r=new AbortController;this.#y.set(t,r),(async()=>{try{let i=n.session({sessionId:e.data.childSessionId,streamIndex:0}).stream({signal:r.signal});for await(let e of i)if(r.signal.aborted||(this.#I(t,e),isCurrentTurnBoundaryEvent(e)))break}catch(e){if(!isAbortLikeError(e)){let n=toErrorMessage(e),r=this.#v.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.#y.delete(t)}})()}#P(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})}#F(e){let t=this.#v.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}}#I(e,t){let n=this.#v.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.#P(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.#P(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,failureOverride:u}=e,d=new Map,f=new Map,p=0,m=new Set,h=new Set,g=new Set,_=new Set,v=!1,y=!1,b;for await(let e of t)if(!(y&&isPostTurnVisibleEvent(e)))switch(e.type){case`session.started`:case`turn.started`:case`message.received`:break;case`step.started`:p+=1,yield{type:`step-start`};break;case`step.completed`:{let t=e;b=t.data.usage,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),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(d,n),i=t.data.messageSoFar;if(r.completed){if(r.text.startsWith(i)||p<=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(d,t),r=e.data.message;if(n.completed){if(r===null||r===n.text||p<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=p,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=p,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=p,yield{type:`assistant-complete`,id:i}}}else n.text.length>0&&(n.completed=!0,n.completedEpoch=p,yield{type:`assistant-complete`,id:i});break}case`reasoning.appended`:{let t=e,n=reasoningPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(f,n),i=t.data.reasoningSoFar;if(r.completed){if(r.text.startsWith(i)||p<=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(f,t),r=e.data.reasoning;if(n.completed){if(r.length===0||r===n.text||n.text.startsWith(r)||p<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=p;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=p,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(g.has(r)){for(let e of n)m.has(e.callId)||h.add(e.callId);break}g.add(r);for(let e of n)m.has(e.callId)||(m.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(g.has(a)){for(let e of r)m.has(e.action.callId)||h.add(e.action.callId);break}g.add(a);for(let e of r){let t=e.action.callId;if(m.has(t)||(m.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(h.has(n)||!m.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,_,u);t&&(yield t);break}case`session.failed`:{i.sawSessionFailure=!0,l?.(e);let t=toFailureEvent(e,_,u);t&&(yield t),i.boundaryEvent=e.type,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b},v=!0;return}case`session.waiting`:case`session.completed`:i.boundaryEvent=e.type,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b},v=!0;return;case`turn.completed`:y=!0,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p);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}v||(yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b})}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(e,t,a){let o=failureKey(e);if(t.has(o))return;t.add(o);let s=a?.(e),c={type:`error`,errorText:s??formatFailureMessage(e)};if(s!==void 0)return c;let l=formatFailureDetail(e);return l!==void 0&&(c.detail=l),c}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 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,parsePromptCommand};
|
|
1
|
+
import{formatPromptCommandHelp,parsePromptCommand}from"./prompt-commands.js";import{failureKey,formatFailureDetail,formatFailureMessage,formatGatewayAuthFailureNotice,isAbortLikeError,isGatewayAuthFailure,isInterruptedError}from"./errors.js";import{BOOT_DETECTIONS,detectSetupIssues,formatSetupIssuesLine}from"./setup-issues.js";import{TerminalRenderer}from"./terminal-renderer.js";import{isCurrentTurnBoundaryEvent}from"#client/index.js";import{createDevelopmentRuntimeArtifactSessionRefresher}from"#services/dev-client.js";import{toErrorMessage}from"#shared/errors.js";var EveTUIRunner=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u;#d;#f;#p;#m;#h;#g;#_=new Map;#v=new Map;#y=new Map;#b=new Map;#x=new Set;#S=!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.appRoot!==void 0&&(this.#p=e.appRoot),e.promptCommandHandler!==void 0&&(this.#m=e.promptCommandHandler),this.#h=e.bootDetections??BOOT_DETECTIONS,e.serverUrl!==void 0&&(this.#f=e.serverUrl,this.#d=createDevelopmentRuntimeArtifactSessionRefresher({serverUrl:e.serverUrl}))}async#C(){let e=this.#f;if(e===void 0){await this.#D(void 0);return}let t;try{t=await this.#t?.info()}catch{t=void 0}this.#g=t;let n={name:this.#r,serverUrl:e};t!==void 0&&(n.info=t),this.#p!==void 0&&(n.setupCommands=!0),this.#n.renderAgentHeader?.(n),await this.#D(t)}async run(){let n=this.#r,r,i,a=!1,o=!1;for(await this.#C();;){if(!o){if(r==null){if(!this.#n.readPrompt){if(a)return;throw Error(`No prompt was provided and the renderer does not support prompt input.`)}try{r=await this.#T({title:n})}catch(e){if(isInterruptedError(e))return;throw e}if(r==null)return}let s=parsePromptCommand(r);if(s?.type===`exit`){this.#n.shutdown?.();return}if(s?.type===`new`){this.#w(),i=void 0,o=!1,r=void 0,this.#n.reset?.();continue}if(s?.type===`help`){this.#O(formatPromptCommandHelp()),i=void 0,o=!1,r=void 0;continue}if(s?.type===`extension`){try{let e=this.#m===void 0?`/${s.name} is not available in this session.`:await this.#m.handle(s,{renderer:this.#n,title:n});e!==void 0&&this.#O(e)}catch(e){if(isInterruptedError(e))return;throw e}i=void 0,r=void 0,o=!1;continue}a=!0}let s=await this.#E({prompt:o?void 0:r,inputResponses:i});try{await this.#n.renderStream(s,{title:n,submittedPrompt:r,continueSession:!!this.#n.readPrompt,tools:this.#i,reasoning:this.#a,subagents:this.#o,connectionAuth:this.#s,assistantResponseStats:this.#c,contextSize:this.#l});let e=s.turnState?.pendingApprovals??[],t=s.turnState?.pendingQuestions??[];if(e.length>0||t.length>0){let a=[];if(e.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 e){let e=await this.#n.readToolApproval(t,{title:n});a.push({requestId:t.approvalId,optionId:e.approved?`approve`:`deny`}),this.#_.delete(t.approvalId)}}if(t.length>0){if(!this.#n.readInputQuestion)throw Error(`An interactive question was requested, but the renderer does not support input questions.`);for(let e of t){let t=toAgentTUIInputQuestion(e),r=await this.#n.readInputQuestion(t,{title:n});if(r===void 0)continue;let i={requestId:e.requestId};r.optionId!==void 0&&(i.optionId=r.optionId),r.text!==void 0&&(i.text=r.text),a.push(i),this.#_.delete(e.requestId)}}o=!0,i=a,r=void 0;continue}s.turnState&&s.turnState.boundaryEvent===void 0&&(this.#S=!0)}catch(e){if(isInterruptedError(e))return;throw e}o=!1,i=void 0,r=void 0,this.#S&&(this.#S=!1,this.#w(),this.#n.renderNotice?.(`Session ended — started a new session. Earlier context was cleared.`))}}#w(){for(let e of this.#y.values())e.abort();this.#y.clear(),this.#v.clear(),this.#_.clear(),this.#b.clear(),this.#x.clear(),this.#t&&(this.#e=this.#t.session()),this.#d?.clear()}async#T(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.#k(),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#E(e){let t=new AbortController,n={signal:t.signal};e.prompt!==void 0&&(n.message=e.prompt),e.inputResponses!==void 0&&e.inputResponses.length>0&&(n.inputResponses=e.inputResponses);let r;try{let e=this.#t;e!==void 0&&this.#d!==void 0&&(this.#e=await this.#d.refresh({createSession:()=>e.session(),inputResponses:n.inputResponses,message:n.message,onRuntimeArtifactsChanged:()=>this.#k(),session:this.#e})),r=await this.#e.send(n)}catch(e){if(isInterruptedError(e))throw e;return this.#S=!0,{events:errorOnlyTUIStream({errorText:this.#u(e)}),turnState:createTurnState()}}let i=createTurnState();return{abort:()=>t.abort(),events:eveEventsToTUIStream({events:r,pendingInputRequests:this.#_,subagentRuns:this.#v,turnState:i,onSubagentCalled:e=>this.#N(e),onSubagentCompleted:e=>this.#F(e),onConnectionAuthRequired:e=>this.#A(e),onConnectionAuthCompleted:e=>this.#j(e),onTerminalFailure:()=>{this.#S=!0},failureOverride:this.#p===void 0?void 0:e=>isGatewayAuthFailure(e)?formatGatewayAuthFailureNotice(e):void 0}),turnState:i}}async#D(e){if(this.#p===void 0||this.#n.renderSetupWarning===void 0)return;let t={appRoot:this.#p,env:process.env};e!==void 0&&(t.info=e);let n=await detectSetupIssues(t,this.#h);n.length!==0&&this.#n.renderSetupWarning(formatSetupIssuesLine(n))}#O(e){if(this.#n.renderCommandResult!==void 0){this.#n.renderCommandResult(e);return}this.#n.renderNotice?.(e)}async#k(){let e=this.#g,t;try{t=await this.#t?.info()}catch{t=void 0}t!==void 0&&(this.#g=t,this.#f!==void 0&&this.#n.renderAgentHeader?.({info:t,name:this.#r,serverUrl:this.#f,setupCommands:this.#p!==void 0})),(!this.#n.renderAgentHeader||t===void 0)&&this.#n.renderNotice?.(formatAgentUpdateNotice(e,t))}#A(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.#b.set(e.data.name,t),this.#M(t)}#j(e){let t=this.#b.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.#b.set(e.data.name,t),this.#x.delete(e.data.name),this.#M(t),this.#n.setConnectionAuthPendingCount?.(this.#x.size)}#M(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)}#N(e){let t=e.data.callId;if(this.#y.has(t))return;let n=this.#t;if(!n)return;let r=new AbortController;this.#y.set(t,r),(async()=>{try{let i=n.session({sessionId:e.data.childSessionId,streamIndex:0}).stream({signal:r.signal});for await(let e of i)if(r.signal.aborted||(this.#I(t,e),isCurrentTurnBoundaryEvent(e)))break}catch(e){if(!isAbortLikeError(e)){let n=toErrorMessage(e),r=this.#v.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.#y.delete(t)}})()}#P(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})}#F(e){let t=this.#v.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}}#I(e,t){let n=this.#v.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.#P(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.#P(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,failureOverride:u}=e,d=new Map,f=new Map,p=0,m=new Set,h=new Set,g=new Set,_=new Set,v=!1,y=!1,b;for await(let e of t)if(!(y&&isPostTurnVisibleEvent(e)))switch(e.type){case`session.started`:case`turn.started`:case`message.received`:break;case`step.started`:p+=1,yield{type:`step-start`};break;case`step.completed`:{let t=e;b=t.data.usage,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),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(d,n),i=t.data.messageSoFar;if(r.completed){if(r.text.startsWith(i)||p<=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(d,t),r=e.data.message;if(n.completed){if(r===null||r===n.text||p<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=p,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=p,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=p,yield{type:`assistant-complete`,id:i}}}else n.text.length>0&&(n.completed=!0,n.completedEpoch=p,yield{type:`assistant-complete`,id:i});break}case`reasoning.appended`:{let t=e,n=reasoningPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(f,n),i=t.data.reasoningSoFar;if(r.completed){if(r.text.startsWith(i)||p<=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(f,t),r=e.data.reasoning;if(n.completed){if(r.length===0||r===n.text||n.text.startsWith(r)||p<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=p;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=p,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(g.has(r)){for(let e of n)m.has(e.callId)||h.add(e.callId);break}g.add(r);for(let e of n)m.has(e.callId)||(m.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(g.has(a)){for(let e of r)m.has(e.action.callId)||h.add(e.action.callId);break}g.add(a);for(let e of r){let t=e.action.callId;if(m.has(t)||(m.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(h.has(n)||!m.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,_,u);t&&(yield t);break}case`session.failed`:{i.sawSessionFailure=!0,l?.(e);let t=toFailureEvent(e,_,u);t&&(yield t),i.boundaryEvent=e.type,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b},v=!0;return}case`session.waiting`:case`session.completed`:i.boundaryEvent=e.type,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b},v=!0;return;case`turn.completed`:y=!0,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p);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}v||(yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b})}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(e,t,a){let o=failureKey(e);if(t.has(o))return;t.add(o);let s=a?.(e),c={type:`error`,errorText:s??formatFailureMessage(e)};if(s!==void 0)return c;let l=formatFailureDetail(e);return l!==void 0&&(c.detail=l),c}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 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,parsePromptCommand};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { runChannelsFlow } from "#setup/flows/channels.js";
|
|
2
2
|
import { runDeployFlow } from "#setup/flows/deploy.js";
|
|
3
|
-
import { runVercelFlow } from "#setup/flows/vercel.js";
|
|
4
3
|
import { runModelFlow } from "#setup/flows/model.js";
|
|
5
4
|
import type { Prompter } from "#setup/prompter.js";
|
|
6
5
|
import { type TuiPrompterRenderer } from "./tui-prompter.js";
|
|
@@ -10,7 +9,7 @@ export type TuiSetupCommand = PromptCommandExtensionName;
|
|
|
10
9
|
* Human panel titles per command. The bordered panel never repeats the echoed
|
|
11
10
|
* command (the transcript already shows it); /channels and /model carry no
|
|
12
11
|
* title at all because their opening questions ("Where will you chat with
|
|
13
|
-
* your agent?", "
|
|
12
|
+
* your agent?", "Configure the agent's model") are the panel's header.
|
|
14
13
|
*/
|
|
15
14
|
export declare const SETUP_FLOW_TITLES: Record<TuiSetupCommand, string>;
|
|
16
15
|
export interface TuiSetupCommandInput {
|
|
@@ -27,7 +26,6 @@ export interface TuiSetupCommandInput {
|
|
|
27
26
|
/** The flow entry points the commands dispatch to, injectable for tests. */
|
|
28
27
|
export interface TuiSetupFlows {
|
|
29
28
|
runModelFlow: typeof runModelFlow;
|
|
30
|
-
runVercelFlow: typeof runVercelFlow;
|
|
31
29
|
runChannelsFlow: typeof runChannelsFlow;
|
|
32
30
|
runDeployFlow: typeof runDeployFlow;
|
|
33
31
|
}
|
|
@@ -37,7 +35,7 @@ export interface TuiSetupCommandResult {
|
|
|
37
35
|
preserveFlowDiagnostics: boolean;
|
|
38
36
|
}
|
|
39
37
|
/**
|
|
40
|
-
* Runs one TUI setup command (/model, /
|
|
38
|
+
* Runs one TUI setup command (/model, /channels, /deploy) over the
|
|
41
39
|
* shared setup flows, asking through the TUI's own bordered panel. Never throws:
|
|
42
40
|
* every outcome — done, cancelled, failed — folds into the returned command
|
|
43
41
|
* result. Known limitation: a flow cannot be cancelled mid-subprocess (keys
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{createTuiPrompter}from"./tui-prompter.js";import{runDeployFlow}from"#setup/flows/deploy.js";import{runChannelsFlow}from"#setup/flows/channels.js";import{
|
|
1
|
+
import{createTuiPrompter}from"./tui-prompter.js";import{runDeployFlow}from"#setup/flows/deploy.js";import{runChannelsFlow}from"#setup/flows/channels.js";import{runModelFlow}from"#setup/flows/model.js";import{WizardCancelledError}from"#setup/step.js";const SETUP_FLOW_TITLES={model:``,channels:``,deploy:`Deploy to Vercel`};async function runTuiSetupCommand(r){let{command:i,appRoot:a}=r,o={runModelFlow,runChannelsFlow,runDeployFlow,...r.flows},s=(r.createPrompter??createTuiPrompter)(r.renderer);try{switch(i){case`model`:{let e=await o.runModelFlow({appRoot:a,prompter:s});if(e.kind===`cancelled`)return{message:`/model cancelled.`,preserveFlowDiagnostics:!1};let t=[];return e.modelMessage!==void 0&&t.push(e.modelMessage),e.providerOutcome!==void 0&&t.push(providerOutcomeMessage(e.providerOutcome)),{message:t.join(`
|
|
2
|
+
`),preserveFlowDiagnostics:!1}}case`channels`:{let e=await o.runChannelsFlow({appRoot:a,prompter:s});return e.kind===`cancelled`?{message:`/channels cancelled.`,preserveFlowDiagnostics:!0}:{message:e.addedChannels.length===0?`No channels added.`:`Channels added: ${e.addedChannels.join(`, `)} — run /deploy to ship them.`,preserveFlowDiagnostics:!0}}case`deploy`:{let e=await o.runDeployFlow({appRoot:a,prompter:s,interactive:!0});return e.kind===`cancelled`?{message:`/deploy cancelled.`,preserveFlowDiagnostics:!0}:e.kind===`needs-link`?{message:`Not linked to a Vercel project — run /model to connect one first.`,preserveFlowDiagnostics:!0}:{message:e.productionUrl===void 0?`Deployed.`:`Deployed: ${e.productionUrl}`,preserveFlowDiagnostics:!0}}}}catch(e){return e instanceof WizardCancelledError?{message:`/${i} cancelled.`,preserveFlowDiagnostics:i!==`model`}:{message:`/${i} failed: ${e instanceof Error?e.message:String(e)}`,preserveFlowDiagnostics:!0}}finally{r.renderer.setStatus(void 0)}}function providerOutcomeMessage(e){let{credential:t,status:n}=e;return n.kind===`gateway-project`?t===void 0?`Project linked — no model credential found; set AI_GATEWAY_API_KEY in .env.local.`:`Project linked — connected to AI Gateway via ${t}.`:n.kind===`gateway-key`?`Connected to AI Gateway via ${n.envKey} in ${n.envFile}.`:`Provider updated — no gateway credential detected; set AI_GATEWAY_API_KEY in .env.local.`}export{SETUP_FLOW_TITLES,runTuiSetupCommand};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SelectNotice } from "#setup/prompter.js";
|
|
1
2
|
import type { SetupPanelOption } from "./setup-panel.js";
|
|
2
3
|
export interface SetupFlowRenderer {
|
|
3
4
|
begin(title: string): void;
|
|
@@ -13,6 +14,8 @@ export interface SetupFlowRenderer {
|
|
|
13
14
|
initialValue?: string;
|
|
14
15
|
initialValues?: readonly string[];
|
|
15
16
|
placeholder?: string;
|
|
17
|
+
layout?: "stacked";
|
|
18
|
+
notices?: readonly SelectNotice[];
|
|
16
19
|
}): Promise<readonly string[] | undefined>;
|
|
17
20
|
readText(options: {
|
|
18
21
|
message: string;
|
|
@@ -3,7 +3,7 @@ import type { AgentInfoResult } from "#client/index.js";
|
|
|
3
3
|
export interface SetupIssue {
|
|
4
4
|
/** Short category label, e.g. "AI Gateway credentials". */
|
|
5
5
|
label: string;
|
|
6
|
-
/** The slash command that fixes it, e.g. "/
|
|
6
|
+
/** The slash command that fixes it, e.g. "/model". */
|
|
7
7
|
command: string;
|
|
8
8
|
}
|
|
9
9
|
/** What a boot detection may inspect. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join}from"node:path";import{pathExists}from"#setup/path-exists.js";const BOOT_DETECTIONS=[{id:`model-provider`,async detect({appRoot:n,env:r}){return r.AI_GATEWAY_API_KEY||r.VERCEL_OIDC_TOKEN?[]:await pathExists(join(n,`.vercel`,`project.json`))?[{label:`AI Gateway credentials missing`,command:`/
|
|
1
|
+
import{join}from"node:path";import{pathExists}from"#setup/path-exists.js";const BOOT_DETECTIONS=[{id:`model-provider`,async detect({appRoot:n,env:r}){return r.AI_GATEWAY_API_KEY||r.VERCEL_OIDC_TOKEN?[]:await pathExists(join(n,`.vercel`,`project.json`))?[{label:`AI Gateway credentials missing`,command:`/model`}]:[{label:`model provider not linked`,command:`/model`}]}}];async function detectSetupIssues(e,t=BOOT_DETECTIONS){return(await Promise.all(t.map(async t=>{try{return await t.detect(e)}catch{return[]}}))).flat()}function formatSetupIssuesLine(e){let t=e.length===1?`setup issue`:`setup issues`,n=e.map(e=>`${e.label} · ${e.command}`).join(`, `);return`${e.length} ${t}: ${n}`}export{BOOT_DETECTIONS,detectSetupIssues,formatSetupIssuesLine};
|