eve 0.6.0-beta.6 → 0.6.0-beta.7
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 +16 -0
- package/dist/docs/public/advanced/dev-tui.md +16 -1
- package/dist/docs/public/advanced/sessions-runs-and-streaming.md +1 -1
- package/dist/src/chunks/{use-eve-agent-9vL56Fjy.js → use-eve-agent-DCZbkLG7.js} +10 -0
- package/dist/src/chunks/{use-eve-agent-DTWI5Lji.js → use-eve-agent-DoheC4_o.js} +10 -0
- package/dist/src/cli/dev/tui/agent-header.d.ts +26 -0
- package/dist/src/cli/dev/tui/agent-header.js +1 -0
- package/dist/src/cli/dev/tui/blocks.d.ts +72 -0
- package/dist/src/cli/dev/tui/blocks.js +6 -0
- package/dist/src/cli/dev/tui/errors.d.ts +52 -0
- package/dist/src/cli/dev/tui/errors.js +1 -0
- package/dist/src/cli/dev/tui/line-editor.d.ts +68 -0
- package/dist/src/cli/dev/tui/line-editor.js +1 -0
- package/dist/src/cli/dev/tui/live-region.d.ts +60 -0
- package/dist/src/cli/dev/tui/live-region.js +3 -0
- package/dist/src/cli/dev/tui/markdown.d.ts +0 -13
- package/dist/src/cli/dev/tui/runner.d.ts +77 -22
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/stream-format.d.ts +76 -0
- package/dist/src/cli/dev/tui/stream-format.js +2 -0
- package/dist/src/cli/dev/tui/terminal-renderer.d.ts +21 -69
- package/dist/src/cli/dev/tui/terminal-renderer.js +4 -12
- package/dist/src/cli/dev/tui/terminal-text.d.ts +6 -0
- package/dist/src/cli/dev/tui/terminal-text.js +1 -1
- package/dist/src/cli/dev/tui/test/mock-terminal.d.ts +7 -0
- package/dist/src/cli/dev/tui/test/mock-terminal.js +2 -2
- package/dist/src/cli/dev/tui/theme.d.ts +95 -0
- package/dist/src/cli/dev/tui/theme.js +1 -0
- package/dist/src/cli/dev/tui/tool-format.d.ts +31 -0
- package/dist/src/cli/dev/tui/tool-format.js +2 -0
- package/dist/src/cli/dev/tui/tui.d.ts +9 -12
- package/dist/src/client/client.d.ts +11 -1
- package/dist/src/client/client.js +1 -1
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/types.d.ts +161 -0
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/evals/scorers/autoevals.js +1 -1
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/harness/code-mode.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-source-snapshot.js +1 -1
- package/dist/src/internal/nitro/host/configure-nitro-routes.js +1 -1
- package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +153 -73
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -6
- package/dist/src/internal/nitro/routes/info.d.ts +11 -13
- package/dist/src/internal/nitro/routes/info.js +1 -1
- package/dist/src/protocol/routes.d.ts +4 -8
- package/dist/src/public/channels/eve.js +1 -1
- package/dist/src/runtime/resolve-agent-graph.js +1 -1
- package/dist/src/setup/scaffold/channels.js +1 -1
- package/dist/src/setup/scaffold/project.js +1 -1
- 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/tui/layout.d.ts +0 -24
- package/dist/src/cli/dev/tui/layout.js +0 -3
- package/dist/src/cli/dev/tui/terminal-frame-buffer.d.ts +0 -21
- package/dist/src/cli/dev/tui/terminal-frame-buffer.js +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.6.0-beta.7
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- edf9f1a: Redesign the `eve dev` terminal UI and add `Client.info()`.
|
|
8
|
+
|
|
9
|
+
The TUI now streams its transcript into the terminal's native scrollback instead of a bordered alt-screen, so scrolling, copy/paste, and the transcript all survive after you exit. The visual language follows the Vercel / Next.js CLI: a monochrome base with the `▲` brand mark, colored gutter glyphs per speaker, the `dots` spinner, and status icons (`✓` done, `⨯` error). Tool calls collapse to a one-line summary (`✓ get_weather city="SF" → 73°F`) that expands under `--tools full`, subagent work is indented beneath a `◆` header, and a startup header prints the connected agent's model, instructions, tools, skills, and subagents. Subagents now default to `auto-collapsed`.
|
|
10
|
+
|
|
11
|
+
The prompt input gains shell-style editing: `↑`/`↓` cycle through your previously sent messages, `←`/`→`/Home/End/`Ctrl+A`/`Ctrl+E` move the caret, and `Ctrl+U`/`Ctrl+K`/`Ctrl+W` kill the line/word. Escape sequences that arrive split across reads (common with PTYs) are reassembled, and pasted text is sanitized of stray control bytes.
|
|
12
|
+
|
|
13
|
+
Failures read more cleanly: a terminal `session.failed` (or a dead-socket transport error) no longer leaves you stuck — the TUI starts a fresh session before the next prompt and notes it inline, so you can keep going. A failure cascade (`step.failed` → `turn.failed` → `session.failed`) renders one error block instead of three, and code bugs escaping user code show their stack trace dim beneath the headline (capped to a dozen lines; recognized provider/config failures keep their curated one-line summary). Error blocks no longer double-print a `Code: Code:` prefix and render docs links in cyan, and denied tool approvals settle to a `→ denied` line instead of a frozen `?`.
|
|
14
|
+
|
|
15
|
+
Captured server `stdout`/`stderr` renders as quiet, indented log runs: consecutive lines from the same source coalesce behind one `stdout ·` / `stderr ·` label with a hanging indent, runs get a blank line of breathing room on both sides, and nothing is ever truncated — a transcript can't be clicked open, so the full output is always shown.
|
|
16
|
+
|
|
17
|
+
`Client.info()` fetches the agent inspection payload (`GET /eve/v1/info`) — model id, instructions source, tools, skills, subagents, schedules, and sandbox — for both local and remote targets, returning the new `AgentInfoResult` type.
|
|
18
|
+
|
|
3
19
|
## 0.6.0-beta.6
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
|
@@ -9,7 +9,22 @@ description: "Drive an Eve agent locally in an interactive terminal UI: chat, st
|
|
|
9
9
|
eve dev
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
On startup the TUI prints a header for the connected agent — the model, instructions prompt, and the tools, skills, and subagents it has available:
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
▲ Weather Agent
|
|
16
|
+
· Model openai/gpt-5
|
|
17
|
+
· Instructions agent/instructions.md
|
|
18
|
+
· Tools get_weather, get_forecast, geocode
|
|
19
|
+
· Subagents researcher
|
|
20
|
+
· Server http://localhost:3000
|
|
21
|
+
|
|
22
|
+
Type to chat · ↑ history · /new reset session · /exit quit · Ctrl+C interrupt
|
|
23
|
+
```
|
|
24
|
+
|
|
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. Two slash commands: `/new` starts a fresh session and `/exit` quits.
|
|
26
|
+
|
|
27
|
+
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.
|
|
13
28
|
|
|
14
29
|
The agent will sometimes need something from you, and the TUI asks inline. Tool approvals are a `y`/`n`. Option questions let you pick with `↑`/`↓` and `Enter`, or you can type a freeform answer. If a tool needs an authorized [connection](../connections), the URL shows up right in the transcript, and the turn picks back up once you've finished the flow.
|
|
15
30
|
|
|
@@ -100,7 +100,7 @@ Start with the [TypeScript Client](../client/overview) guide. It covers basic us
|
|
|
100
100
|
|
|
101
101
|
## Inspect the agent over HTTP
|
|
102
102
|
|
|
103
|
-
`GET /eve/v1/info` returns a JSON inspection
|
|
103
|
+
`GET /eve/v1/info` returns a JSON inspection snapshot for the running agent: model, instructions, authored and framework tools, skills, channels, schedules, subagents, sandbox, connections, hooks, workflow, and workspace metadata. Local development accepts loopback requests; deployed Vercel targets require the route's OIDC auth.
|
|
104
104
|
|
|
105
105
|
```bash
|
|
106
106
|
curl http://127.0.0.1:3000/eve/v1/info
|
|
@@ -434,6 +434,16 @@ var Client = class {
|
|
|
434
434
|
}
|
|
435
435
|
return await response.json();
|
|
436
436
|
}
|
|
437
|
+
async info() {
|
|
438
|
+
const url = createClientUrl(this.#host, EVE_INFO_ROUTE_PATH);
|
|
439
|
+
const headers = await this.#resolveHeaders();
|
|
440
|
+
const response = await fetch(url, { headers });
|
|
441
|
+
if (!response.ok) {
|
|
442
|
+
const body = await response.text();
|
|
443
|
+
throw new ClientError(response.status, body);
|
|
444
|
+
}
|
|
445
|
+
return await response.json();
|
|
446
|
+
}
|
|
437
447
|
session(state) {
|
|
438
448
|
let resolved;
|
|
439
449
|
if (typeof state === "string") resolved = {
|
|
@@ -434,6 +434,16 @@ var Client = class {
|
|
|
434
434
|
}
|
|
435
435
|
return await response.json();
|
|
436
436
|
}
|
|
437
|
+
async info() {
|
|
438
|
+
const url = createClientUrl(this.#host, EVE_INFO_ROUTE_PATH);
|
|
439
|
+
const headers = await this.#resolveHeaders();
|
|
440
|
+
const response = await fetch(url, { headers });
|
|
441
|
+
if (!response.ok) {
|
|
442
|
+
const body = await response.text();
|
|
443
|
+
throw new ClientError(response.status, body);
|
|
444
|
+
}
|
|
445
|
+
return await response.json();
|
|
446
|
+
}
|
|
437
447
|
session(state) {
|
|
438
448
|
let resolved;
|
|
439
449
|
if (typeof state === "string") resolved = {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the startup header the dev TUI commits to scrollback before the first
|
|
3
|
+
* prompt. Styled after the Next.js dev banner: a leading `▲` brand mark, then
|
|
4
|
+
* an aligned `·` list of the agent's resolved configuration (model,
|
|
5
|
+
* instructions, authored tools, skills, subagents, server). When the
|
|
6
|
+
* `/eve/v1/info` payload is unavailable it degrades to a minimal name +
|
|
7
|
+
* server banner.
|
|
8
|
+
*/
|
|
9
|
+
import type { AgentInfoResult } from "#client/index.js";
|
|
10
|
+
import type { Theme } from "./theme.js";
|
|
11
|
+
export interface AgentHeaderInput {
|
|
12
|
+
/** Resolved display name (e.g. "Weather Agent"). */
|
|
13
|
+
name: string;
|
|
14
|
+
/** Server URL the TUI is connected to. */
|
|
15
|
+
serverUrl: string;
|
|
16
|
+
/** Agent inspection payload, or `undefined` when it could not be fetched. */
|
|
17
|
+
info?: AgentInfoResult;
|
|
18
|
+
theme: Theme;
|
|
19
|
+
/** Available terminal width. */
|
|
20
|
+
width: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Returns the styled rows of the startup header (no trailing blank line is
|
|
24
|
+
* added by callers other than the one separating it from the transcript).
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildAgentHeader(input: AgentHeaderInput): string[];
|
|
@@ -0,0 +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}`)}return d.push(``),d.push(` ${s.dim(`Type to chat ${n.glyph.dot} ↑ history ${n.glyph.dot} /new reset session ${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};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The transcript block model and its renderer.
|
|
3
|
+
*
|
|
4
|
+
* A {@link Block} is one logical unit of the conversation — a user message, a
|
|
5
|
+
* streamed assistant reply, a reasoning trace, a tool call, a nested subagent
|
|
6
|
+
* step, a log line, and so on. {@link renderBlockLines} turns a block into the
|
|
7
|
+
* exact terminal rows it occupies: a colored gutter glyph, brand-aligned
|
|
8
|
+
* indentation, nesting rules for subagents, and word-wrapped content — with no
|
|
9
|
+
* boxes anywhere. Every returned row is already styled and fits within the
|
|
10
|
+
* given width, so the live region can place rows verbatim.
|
|
11
|
+
*/
|
|
12
|
+
import type { Theme } from "./theme.js";
|
|
13
|
+
export type ToolStatus = "running" | "done" | "error" | "denied" | "approval";
|
|
14
|
+
export type BlockKind = "user" | "assistant" | "reasoning" | "tool" | "error" | "notice" | "question" | "subagent" | "subagent-step" | "subagent-tool" | "connection-auth" | "log";
|
|
15
|
+
/**
|
|
16
|
+
* One renderable transcript unit. Fields are interpreted per `kind`; unset
|
|
17
|
+
* fields are simply omitted from the rendered output.
|
|
18
|
+
*/
|
|
19
|
+
export interface Block {
|
|
20
|
+
kind: BlockKind;
|
|
21
|
+
/** Stable id for in-place updates while the block is live. */
|
|
22
|
+
id?: string;
|
|
23
|
+
/** Nesting depth: 0 = top level, 1 = inside a subagent, etc. */
|
|
24
|
+
depth?: number;
|
|
25
|
+
/** Whether the block is still streaming / mutating (drives the spinner). */
|
|
26
|
+
live?: boolean;
|
|
27
|
+
/** Primary label — tool name, subagent name, log source, error title. */
|
|
28
|
+
title?: string;
|
|
29
|
+
/** Compact secondary text — summarized tool args. */
|
|
30
|
+
subtitle?: string;
|
|
31
|
+
/** Main multi-line content (markdown for prose, plain for logs). */
|
|
32
|
+
body?: string;
|
|
33
|
+
/** Reasoning trace shown above `body` (subagent steps). */
|
|
34
|
+
reasoning?: string;
|
|
35
|
+
/** One-line summarized result shown after a tool resolves. */
|
|
36
|
+
result?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Errors only: multi-line diagnostic dump (stack trace, cause chain)
|
|
39
|
+
* rendered dim beneath the headline, capped to a handful of lines.
|
|
40
|
+
*/
|
|
41
|
+
detail?: string;
|
|
42
|
+
/** Tool / connection lifecycle status. */
|
|
43
|
+
status?: ToolStatus;
|
|
44
|
+
/** When true, treat `body` as pre-styled and only wrap + indent it. */
|
|
45
|
+
preformatted?: boolean;
|
|
46
|
+
/** Reasoning only: collapse the trace to a single "thinking" line. */
|
|
47
|
+
collapsed?: boolean;
|
|
48
|
+
/** When true, expand tool input/output instead of summarizing. */
|
|
49
|
+
expanded?: boolean;
|
|
50
|
+
/** Raw tool input / output for the expanded view. */
|
|
51
|
+
toolInput?: unknown;
|
|
52
|
+
toolOutput?: unknown;
|
|
53
|
+
}
|
|
54
|
+
export interface RenderBlockContext {
|
|
55
|
+
/** Current spinner frame for live blocks. */
|
|
56
|
+
spinner: string;
|
|
57
|
+
/**
|
|
58
|
+
* Kind and title of the block rendered immediately above this one. Lets a
|
|
59
|
+
* log block detect that it continues a same-source run (label suppressed,
|
|
60
|
+
* lines hang under the previous block's label) without any mutable run
|
|
61
|
+
* state — each captured write stays its own immediately-committed block.
|
|
62
|
+
*/
|
|
63
|
+
previous?: {
|
|
64
|
+
kind: BlockKind;
|
|
65
|
+
title?: string;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Renders a block to its terminal rows. Each row is fully styled and clipped
|
|
70
|
+
* to `width` visible columns.
|
|
71
|
+
*/
|
|
72
|
+
export declare function renderBlockLines(block: Block, width: number, theme: Theme, context: RenderBlockContext): string[];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{formatValuePretty,truncate}from"./tool-format.js";import{sliceVisible,visibleLength,wrapVisibleLine}from"./terminal-text.js";import{renderMarkdown}from"./markdown.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`question`:case`connection-auth`:return renderPreformatted(e,t,n);case`log`:return renderLog(e,t,n,r);case`subagent`:return renderSubagentHeader(e,t,n)}}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
|
+
`).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
|
+
`),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 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
|
+
`))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(`
|
|
5
|
+
`),h=[];for(let e of m){let r=wrapVisibleLine(e,Math.max(1,t-2-d));for(let e of r){let t=h.length===0&&!p?u:f;h.push(`${c} ${t}${n.colors.dim(s(e))}`)}}return h.length>0?h:[`${c}`]}function renderSubagentHeader(e,t,n){let r=truncatePlain(e.title??`subagent`,Math.max(8,t-14));return[`${n.colors.orange(n.glyph.subagent)} ${n.colors.bold(r)} ${n.colors.dim(`subagent`)}`]}function wrap(e,t){return e.trim().length===0?[]:e.split(`
|
|
6
|
+
`).flatMap(e=>wrapVisibleLine(e,Math.max(1,t)))}function truncatePlain(e,t){return visibleLength(e)<=t?e:sliceVisible(e,t)}export{renderBlockLines};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error classification and display formatting shared by the TUI runner and
|
|
3
|
+
* terminal renderer. One module owns the interrupt sentinel and the
|
|
4
|
+
* failure-event projections so the two sides cannot drift apart.
|
|
5
|
+
*/
|
|
6
|
+
import type { SessionFailedStreamEvent, StepFailedStreamEvent, TurnFailedStreamEvent } from "#client/index.js";
|
|
7
|
+
/**
|
|
8
|
+
* One of the failure events a session stream can carry. All three share the
|
|
9
|
+
* same `{ code, message, details? }` payload shape — the harness emits them
|
|
10
|
+
* as a cascade (`step.failed` → `turn.failed` → `session.failed` /
|
|
11
|
+
* `session.waiting`) describing a single underlying failure.
|
|
12
|
+
*/
|
|
13
|
+
export type FailureStreamEvent = StepFailedStreamEvent | TurnFailedStreamEvent | SessionFailedStreamEvent;
|
|
14
|
+
/**
|
|
15
|
+
* Thrown when the user interrupts the TUI (Ctrl+C, or Ctrl+D on an empty
|
|
16
|
+
* prompt). The runner treats it as a clean exit, never as a failure.
|
|
17
|
+
*/
|
|
18
|
+
export declare class InterruptedError extends Error {
|
|
19
|
+
constructor();
|
|
20
|
+
}
|
|
21
|
+
export declare function interruptedError(): InterruptedError;
|
|
22
|
+
export declare function isInterruptedError(error: unknown): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Recognizes errors raised by aborting an in-flight fetch/stream (e.g. the
|
|
25
|
+
* subagent child-session pump being cancelled). These are expected shutdown
|
|
26
|
+
* noise, not failures to surface.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isAbortLikeError(error: unknown): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Stable identity for one failure cascade entry. The harness emits the same
|
|
31
|
+
* `{ code, message }` payload on `step.failed`, `turn.failed`, and (for
|
|
32
|
+
* terminal failures) `session.failed`; keying on both lets the stream
|
|
33
|
+
* translator render the underlying failure exactly once.
|
|
34
|
+
*/
|
|
35
|
+
export declare function failureKey(event: FailureStreamEvent): string;
|
|
36
|
+
/**
|
|
37
|
+
* One-line headline for a failure event: `code: message`, except when the
|
|
38
|
+
* message already carries its own class-name prefix (e.g. a
|
|
39
|
+
* `HookConflictError` whose message starts with `HookConflictError:`), in
|
|
40
|
+
* which case the message stands alone instead of reading `Code: Code: …`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatFailureMessage(event: FailureStreamEvent): string;
|
|
43
|
+
/**
|
|
44
|
+
* Extracts the diagnostic dump attached to a failure event, if any.
|
|
45
|
+
*
|
|
46
|
+
* `details.detail` is the `util.inspect` rendering (stack trace and cause
|
|
47
|
+
* chain included) that `formatError` attaches to *unrecognized* failures —
|
|
48
|
+
* i.e. code bugs escaping user code. Recognized provider/config failures
|
|
49
|
+
* deliberately ship a curated summary without the dump, so this returns
|
|
50
|
+
* `undefined` for them and the headline stands alone.
|
|
51
|
+
*/
|
|
52
|
+
export declare function formatFailureDetail(event: FailureStreamEvent): string | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
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}export{InterruptedError,failureKey,formatFailureDetail,formatFailureMessage,interruptedError,isAbortLikeError,isInterruptedError};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tiny, dependency-free line-editing model for the prompt input.
|
|
3
|
+
*
|
|
4
|
+
* The renderer owns the terminal; this module owns the *text* — a single
|
|
5
|
+
* logical line plus a caret position — and exposes pure transforms for the
|
|
6
|
+
* common readline-style edits (insert, delete, word/line kill, cursor moves)
|
|
7
|
+
* and a {@link visibleLine} helper that windows a long line around the caret
|
|
8
|
+
* so it stays on screen. Keeping it pure makes the editing rules trivial to
|
|
9
|
+
* unit test without a TTY.
|
|
10
|
+
*/
|
|
11
|
+
/** One logical input line: its text and the caret's index within it. */
|
|
12
|
+
export interface LineState {
|
|
13
|
+
readonly text: string;
|
|
14
|
+
readonly cursor: number;
|
|
15
|
+
}
|
|
16
|
+
/** The empty line with the caret at column 0. */
|
|
17
|
+
export declare const EMPTY_LINE: LineState;
|
|
18
|
+
/** Builds a line from `text` with the caret placed at the end. */
|
|
19
|
+
export declare function lineOf(text: string): LineState;
|
|
20
|
+
/** Inserts `value` at the caret and advances the caret past it. */
|
|
21
|
+
export declare function insert(state: LineState, value: string): LineState;
|
|
22
|
+
/** Deletes the character before the caret (Backspace). */
|
|
23
|
+
export declare function backspace(state: LineState): LineState;
|
|
24
|
+
/** Deletes the character at the caret (Delete / Ctrl+D mid-line). */
|
|
25
|
+
export declare function deleteForward(state: LineState): LineState;
|
|
26
|
+
/** Moves the caret one column left. */
|
|
27
|
+
export declare function moveLeft(state: LineState): LineState;
|
|
28
|
+
/** Moves the caret one column right. */
|
|
29
|
+
export declare function moveRight(state: LineState): LineState;
|
|
30
|
+
/** Moves the caret to the start of the line (Home / Ctrl+A). */
|
|
31
|
+
export declare function moveHome(state: LineState): LineState;
|
|
32
|
+
/** Moves the caret to the end of the line (End / Ctrl+E). */
|
|
33
|
+
export declare function moveEnd(state: LineState): LineState;
|
|
34
|
+
/** Deletes from the caret to the end of the line (Ctrl+K). */
|
|
35
|
+
export declare function killToEnd(state: LineState): LineState;
|
|
36
|
+
/** Deletes from the start of the line to the caret (Ctrl+U). */
|
|
37
|
+
export declare function killToStart(state: LineState): LineState;
|
|
38
|
+
/** Deletes the whitespace-delimited word before the caret (Ctrl+W). */
|
|
39
|
+
export declare function deleteWord(state: LineState): LineState;
|
|
40
|
+
/**
|
|
41
|
+
* The portion of `state.text` to draw within `budget` columns, split at the
|
|
42
|
+
* caret so the renderer can place its caret glyph between `before` and
|
|
43
|
+
* `after`. When the line is wider than `budget` it is windowed around the
|
|
44
|
+
* caret, marking truncated ends with `…` so the caret is always visible.
|
|
45
|
+
*/
|
|
46
|
+
export interface VisibleLine {
|
|
47
|
+
readonly before: string;
|
|
48
|
+
readonly after: string;
|
|
49
|
+
}
|
|
50
|
+
export declare function visibleLine(state: LineState, budget: number, ellipsis?: string): VisibleLine;
|
|
51
|
+
/**
|
|
52
|
+
* In-memory, append-only prompt history with shell-style up/down navigation.
|
|
53
|
+
*
|
|
54
|
+
* Navigation is non-destructive: stepping back from the live line stashes the
|
|
55
|
+
* in-progress draft and restores it when the user steps forward past the
|
|
56
|
+
* newest entry. Consecutive duplicate submissions are collapsed.
|
|
57
|
+
*/
|
|
58
|
+
export declare class PromptHistory {
|
|
59
|
+
#private;
|
|
60
|
+
/** Records a submitted prompt (skips blanks and consecutive duplicates). */
|
|
61
|
+
add(entry: string): void;
|
|
62
|
+
/** Resets navigation to the live line, stashing `draft` as the in-progress text. */
|
|
63
|
+
begin(draft: string): void;
|
|
64
|
+
/** The previous (older) entry, or `undefined` at the oldest entry. */
|
|
65
|
+
previous(currentDraft: string): string | undefined;
|
|
66
|
+
/** The next (newer) entry, or the stashed draft once past the newest entry. */
|
|
67
|
+
next(): string | undefined;
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const EMPTY_LINE={text:``,cursor:0};function lineOf(e){return{text:e,cursor:e.length}}function insert(e,t){return t.length===0?e:{text:e.text.slice(0,e.cursor)+t+e.text.slice(e.cursor),cursor:e.cursor+t.length}}function backspace(e){return e.cursor===0?e:{text:e.text.slice(0,e.cursor-1)+e.text.slice(e.cursor),cursor:e.cursor-1}}function deleteForward(e){return e.cursor>=e.text.length?e:{text:e.text.slice(0,e.cursor)+e.text.slice(e.cursor+1),cursor:e.cursor}}function moveLeft(e){return e.cursor===0?e:{text:e.text,cursor:e.cursor-1}}function moveRight(e){return e.cursor>=e.text.length?e:{text:e.text,cursor:e.cursor+1}}function moveHome(e){return e.cursor===0?e:{text:e.text,cursor:0}}function moveEnd(e){return e.cursor===e.text.length?e:{text:e.text,cursor:e.text.length}}function killToEnd(e){return e.cursor>=e.text.length?e:{text:e.text.slice(0,e.cursor),cursor:e.cursor}}function killToStart(e){return e.cursor===0?e:{text:e.text.slice(e.cursor),cursor:0}}function deleteWord(e){if(e.cursor===0)return e;let t=e.cursor;for(;t>0&&isWhitespace(e.text[t-1]);)--t;for(;t>0&&!isWhitespace(e.text[t-1]);)--t;return{text:e.text.slice(0,t)+e.text.slice(e.cursor),cursor:t}}function isWhitespace(e){return e!==void 0&&/\s/u.test(e)}function visibleLine(e,t,n=`…`){let r=Math.max(1,t),{text:i,cursor:a}=e;if(i.length<=r)return{before:i.slice(0,a),after:i.slice(a)};let o=a<r?0:a-r+1;o=Math.min(o,i.length-r),o=Math.max(0,o);let s=o+r,c=i.slice(o,s),l=a-o;return o>0&&l>0&&(c=n+c.slice(n.length)),s<i.length&&l<c.length&&(c=c.slice(0,c.length-n.length)+n),{before:c.slice(0,l),after:c.slice(l)}}var PromptHistory=class{#e=[];#t=0;#n=``;add(e){if(e.trim().length!==0){if(this.#e.at(-1)===e){this.#r();return}this.#e.push(e),this.#r()}}begin(e){this.#t=this.#e.length,this.#n=e}previous(e){if(this.#e.length!==0&&(this.#t===this.#e.length&&(this.#n=e),this.#t!==0))return--this.#t,this.#e[this.#t]}next(){if(!(this.#t>=this.#e.length))return this.#t+=1,this.#t===this.#e.length?this.#n:this.#e[this.#t]}#r(){this.#t=this.#e.length,this.#n=``}};export{EMPTY_LINE,PromptHistory,backspace,deleteForward,deleteWord,insert,killToEnd,killToStart,lineOf,moveEnd,moveHome,moveLeft,moveRight,visibleLine};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inline scrollback engine.
|
|
3
|
+
*
|
|
4
|
+
* Unlike a full-screen alt-buffer UI, the dev TUI streams its transcript into
|
|
5
|
+
* the terminal's *native* scrollback so the user keeps real scrolling, copy /
|
|
6
|
+
* paste, and a persistent transcript after exit. Two regions are maintained:
|
|
7
|
+
*
|
|
8
|
+
* - **Committed scrollback** — finalized rows printed once and owned by the
|
|
9
|
+
* terminal thereafter (never repainted).
|
|
10
|
+
* - **Live region** — the still-streaming rows plus the sticky footer, redrawn
|
|
11
|
+
* in place on every update.
|
|
12
|
+
*
|
|
13
|
+
* Redrawing moves the cursor to the top of the previous live region, clears to
|
|
14
|
+
* the end of the screen, and reprints. {@link flush} additionally writes a run
|
|
15
|
+
* of newly-finalized rows above the live region so they scroll away for good.
|
|
16
|
+
*
|
|
17
|
+
* Writes go through the terminal's original `write` captured at construction,
|
|
18
|
+
* so the renderer's foreign-output capture (which monkeypatches
|
|
19
|
+
* `process.stdout.write`) never mistakes the engine's own paint for agent log
|
|
20
|
+
* output.
|
|
21
|
+
*/
|
|
22
|
+
export interface LiveRegionOutput {
|
|
23
|
+
write(chunk: string): boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface LiveRegionOptions {
|
|
26
|
+
/** Wrap each paint in synchronized-update markers to avoid flicker. */
|
|
27
|
+
synchronized?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare class LiveRegion {
|
|
30
|
+
#private;
|
|
31
|
+
constructor(output: LiveRegionOutput, options?: LiveRegionOptions);
|
|
32
|
+
/** Hides the hardware cursor; the renderer draws its own caret. */
|
|
33
|
+
hideCursor(): void;
|
|
34
|
+
showCursor(): void;
|
|
35
|
+
/** Writes a newline through the bound (original) write. */
|
|
36
|
+
newline(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Repaints the live region in place from `liveRows`. Each row must already
|
|
39
|
+
* be styled and fit within the terminal width (one row == one screen line).
|
|
40
|
+
*/
|
|
41
|
+
update(liveRows: readonly string[]): void;
|
|
42
|
+
/**
|
|
43
|
+
* Commits `committedRows` to scrollback above the live region, then repaints
|
|
44
|
+
* `liveRows`. Committed rows are permanent and scroll with the terminal.
|
|
45
|
+
*/
|
|
46
|
+
flush(committedRows: readonly string[], liveRows: readonly string[]): void;
|
|
47
|
+
/**
|
|
48
|
+
* Erases the live region, leaving the cursor at its former top. Committed
|
|
49
|
+
* scrollback is untouched. Used on teardown before restoring the cursor.
|
|
50
|
+
*/
|
|
51
|
+
clear(): void;
|
|
52
|
+
/** Clears the visible transcript and, where supported, terminal scrollback. */
|
|
53
|
+
clearAll(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Forgets the live-region row count without moving the cursor. Call after
|
|
56
|
+
* the cursor position is known to be a fresh column-0 line that the engine
|
|
57
|
+
* did not itself paint (e.g. immediately after teardown).
|
|
58
|
+
*/
|
|
59
|
+
reset(): void;
|
|
60
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const CLEAR_TO_END=`\x1B[0J`;var LiveRegion=class{#e;#t;#n=0;constructor(e,t){this.#e=e.write.bind(e),this.#t=t?.synchronized??!0}hideCursor(){this.#e(`\x1B[?25l`)}showCursor(){this.#e(`\x1B[?25h`)}newline(){this.#e(`
|
|
2
|
+
`)}update(e){this.#r([],e)}flush(e,t){this.#r(e,t)}clear(){if(this.#n===0){this.#e(`\r`),this.#e(CLEAR_TO_END);return}this.#e(`${this.#i()}${CLEAR_TO_END}`),this.#n=0}clearAll(){this.#e(`\x1B[3J\x1B[2J\x1B[H`),this.#n=0}reset(){this.#n=0}#r(t,n){let r=this.#i()+CLEAR_TO_END+t.map(e=>`${e}\n`).join(``)+n.join(`
|
|
3
|
+
`);this.#e(this.#t?`[?2026h${r}[?2026l`:r),this.#n=n.length}#i(){return this.#n<=1?`\r`:`[${this.#n-1}F`}};export{LiveRegion};
|
|
@@ -1,14 +1 @@
|
|
|
1
|
-
export type MarkdownToken = {
|
|
2
|
-
type: "text";
|
|
3
|
-
text: string;
|
|
4
|
-
} | {
|
|
5
|
-
type: "bold";
|
|
6
|
-
text: string;
|
|
7
|
-
} | {
|
|
8
|
-
type: "italic";
|
|
9
|
-
text: string;
|
|
10
|
-
} | {
|
|
11
|
-
type: "code";
|
|
12
|
-
text: string;
|
|
13
|
-
};
|
|
14
1
|
export declare function renderMarkdown(input: string): string;
|
|
@@ -1,20 +1,69 @@
|
|
|
1
|
-
import { type ConnectionAuthorizationOutcome, Client, ClientSession } from "#client/index.js";
|
|
2
|
-
import { type UIMessage, type UIMessageChunk } from "ai";
|
|
1
|
+
import { type AgentInfoResult, type ConnectionAuthorizationOutcome, type InputRequest, Client, ClientSession } from "#client/index.js";
|
|
3
2
|
import type { AssistantResponseStatsMode, TerminalPartDisplayMode, TuiDisplayOptions } from "./types.js";
|
|
4
3
|
import { type TerminalInput, type TerminalOutput } from "./terminal-renderer.js";
|
|
5
4
|
export type AgentTUIStreamResult = {
|
|
6
|
-
|
|
7
|
-
message?: UIMessage;
|
|
5
|
+
events: AsyncIterable<AgentTUIStreamEvent> | ReadableStream<AgentTUIStreamEvent>;
|
|
8
6
|
abort?: () => void;
|
|
7
|
+
turnState?: AgentTUITurnState;
|
|
9
8
|
};
|
|
10
|
-
export type
|
|
11
|
-
|
|
9
|
+
export type AgentTUIStreamUsage = {
|
|
10
|
+
inputTokens?: number;
|
|
11
|
+
outputTokens?: number;
|
|
12
|
+
};
|
|
13
|
+
export type AgentTUIStreamEvent = {
|
|
14
|
+
type: "step-start";
|
|
15
|
+
} | {
|
|
16
|
+
type: "step-finish";
|
|
17
|
+
usage?: AgentTUIStreamUsage;
|
|
18
|
+
} | {
|
|
19
|
+
type: "assistant-delta";
|
|
20
|
+
id: string;
|
|
21
|
+
delta: string;
|
|
22
|
+
} | {
|
|
23
|
+
type: "assistant-complete";
|
|
24
|
+
id: string;
|
|
25
|
+
text?: string | null;
|
|
26
|
+
} | {
|
|
27
|
+
type: "reasoning-delta";
|
|
28
|
+
id: string;
|
|
29
|
+
delta: string;
|
|
30
|
+
} | {
|
|
31
|
+
type: "reasoning-complete";
|
|
32
|
+
id: string;
|
|
33
|
+
} | {
|
|
34
|
+
type: "tool-call";
|
|
35
|
+
toolCallId: string;
|
|
36
|
+
toolName: string;
|
|
37
|
+
input: unknown;
|
|
38
|
+
} | {
|
|
39
|
+
type: "tool-approval-request";
|
|
40
|
+
approvalId: string;
|
|
41
|
+
toolCallId: string;
|
|
42
|
+
} | {
|
|
43
|
+
type: "tool-result";
|
|
44
|
+
toolCallId: string;
|
|
45
|
+
output: unknown;
|
|
46
|
+
} | {
|
|
47
|
+
type: "tool-error";
|
|
48
|
+
toolCallId: string;
|
|
49
|
+
errorText: string;
|
|
50
|
+
} | {
|
|
51
|
+
type: "error";
|
|
52
|
+
errorText: string;
|
|
53
|
+
detail?: string;
|
|
54
|
+
} | {
|
|
55
|
+
type: "finish";
|
|
56
|
+
usage?: AgentTUIStreamUsage;
|
|
57
|
+
};
|
|
58
|
+
export type AgentTUITurnState = {
|
|
59
|
+
boundaryEvent?: "session.completed" | "session.failed" | "session.waiting";
|
|
60
|
+
pendingApprovals: AgentTUIToolApprovalRequest[];
|
|
61
|
+
pendingQuestions: InputRequest[];
|
|
62
|
+
sawSessionFailure: boolean;
|
|
12
63
|
};
|
|
13
64
|
export type AgentTUISessionOptions = {
|
|
14
65
|
title?: string;
|
|
15
|
-
initialPrompt?: string;
|
|
16
66
|
submittedPrompt?: string;
|
|
17
|
-
waitForExit?: boolean;
|
|
18
67
|
continueSession?: boolean;
|
|
19
68
|
tools?: TerminalPartDisplayMode;
|
|
20
69
|
reasoning?: TerminalPartDisplayMode;
|
|
@@ -29,9 +78,6 @@ export type AgentTUIToolApprovalRequest = {
|
|
|
29
78
|
toolName: string;
|
|
30
79
|
title?: string;
|
|
31
80
|
input: unknown;
|
|
32
|
-
providerExecuted?: boolean;
|
|
33
|
-
messageId: string;
|
|
34
|
-
partIndex: number;
|
|
35
81
|
};
|
|
36
82
|
export type AgentTUIToolApprovalResponse = {
|
|
37
83
|
approved: boolean;
|
|
@@ -54,11 +100,27 @@ export type AgentTUIInputQuestionResponse = {
|
|
|
54
100
|
optionId?: string;
|
|
55
101
|
text?: string;
|
|
56
102
|
};
|
|
103
|
+
export type AgentTUIAgentHeader = {
|
|
104
|
+
name: string;
|
|
105
|
+
serverUrl: string;
|
|
106
|
+
info?: AgentInfoResult;
|
|
107
|
+
};
|
|
57
108
|
export type AgentTUIRenderer = {
|
|
109
|
+
/**
|
|
110
|
+
* Commits a startup header describing the connected agent (brand mark,
|
|
111
|
+
* model, instructions, tools, skills, subagents) to the transcript before
|
|
112
|
+
* the first prompt. Optional — renderers without a header simply skip it.
|
|
113
|
+
*/
|
|
114
|
+
renderAgentHeader?(header: AgentTUIAgentHeader): void;
|
|
115
|
+
/**
|
|
116
|
+
* Commits a single dim informational line to the transcript. Used to
|
|
117
|
+
* announce session recovery after a terminal server failure. Optional.
|
|
118
|
+
*/
|
|
119
|
+
renderNotice?(text: string): void;
|
|
58
120
|
readPrompt?(options?: AgentTUISessionOptions): Promise<string | undefined>;
|
|
59
121
|
readToolApproval?(request: AgentTUIToolApprovalRequest, options?: AgentTUISessionOptions): Promise<AgentTUIToolApprovalResponse>;
|
|
60
122
|
readInputQuestion?(question: AgentTUIInputQuestion, options?: AgentTUISessionOptions): Promise<AgentTUIInputQuestionResponse | undefined>;
|
|
61
|
-
renderStream(result: AgentTUIStreamResult, options?: AgentTUISessionOptions): Promise<
|
|
123
|
+
renderStream(result: AgentTUIStreamResult, options?: AgentTUISessionOptions): Promise<void>;
|
|
62
124
|
/**
|
|
63
125
|
* Out-of-band update for one child step (reasoning + message text) of a
|
|
64
126
|
* subagent dispatch. Called by the runner as child-session stream events
|
|
@@ -72,9 +134,8 @@ export type AgentTUIRenderer = {
|
|
|
72
134
|
upsertSubagentTool?(update: SubagentToolUpdate): void;
|
|
73
135
|
/**
|
|
74
136
|
* Registers a tool call id as originating from a subagent's child
|
|
75
|
-
* session. The renderer must skip
|
|
76
|
-
*
|
|
77
|
-
* instead.
|
|
137
|
+
* session. The renderer must skip or remove parent-level tool blocks for
|
|
138
|
+
* these ids — they are surfaced via {@link upsertSubagentTool} instead.
|
|
78
139
|
*/
|
|
79
140
|
markChildToolCallId?(callId: string): void;
|
|
80
141
|
/**
|
|
@@ -138,12 +199,6 @@ export declare class EveTUIRunner {
|
|
|
138
199
|
constructor(options: EveTUIRunnerOptions);
|
|
139
200
|
run(): Promise<void>;
|
|
140
201
|
}
|
|
141
|
-
type ResponseMetadata = {
|
|
142
|
-
usage?: {
|
|
143
|
-
totalTokens?: number;
|
|
144
|
-
outputTokens?: number;
|
|
145
|
-
};
|
|
146
|
-
};
|
|
147
202
|
type SubagentChildStep = {
|
|
148
203
|
reasoning: string;
|
|
149
204
|
message: string;
|
|
@@ -208,4 +263,4 @@ export type ConnectionAuthUpdate = {
|
|
|
208
263
|
challenge?: ConnectionAuthChallenge;
|
|
209
264
|
reason?: string;
|
|
210
265
|
};
|
|
211
|
-
export
|
|
266
|
+
export {};
|