eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
81 lines (80 loc) • 3.77 kB
TypeScript
/**
* The transcript block model and its renderer.
*
* A {@link Block} is one logical unit of the conversation — a user message, a
* streamed assistant reply, a reasoning trace, a tool call, a nested subagent
* step, a log line, and so on. {@link renderBlockLines} turns a block into the
* exact terminal rows it occupies: a colored gutter glyph, brand-aligned
* indentation, nesting rules for subagents, and word-wrapped content — with no
* boxes anywhere. Every returned row is already styled and fits within the
* given width, so the live region can place rows verbatim.
*/
import type { Theme } from "./theme.js";
export type ToolStatus = "running" | "done" | "error" | "denied" | "approval";
export type BlockKind = "user" | "assistant" | "reasoning" | "tool" | "error" | "notice" | "warning" | "result" | "flow" | "command" | "question" | "subagent" | "subagent-step" | "subagent-tool" | "connection-auth" | "sandbox" | "log" | "agent-header";
/**
* One renderable transcript unit. Fields are interpreted per `kind`; unset
* fields are simply omitted from the rendered output.
*/
export interface Block {
kind: BlockKind;
/** Stable id for in-place updates while the block is live. */
id?: string;
/** Nesting depth: 0 = top level, 1 = inside a subagent, etc. */
depth?: number;
/** Whether the block is still streaming / mutating (drives the spinner). */
live?: boolean;
/** Primary label — tool name, subagent name, log source, error title. */
title?: string;
/** Compact secondary text — summarized tool args. */
subtitle?: string;
/** Main multi-line content (markdown for prose, plain for logs). */
body?: string;
/** Reasoning trace shown above `body` (subagent steps). */
reasoning?: string;
/** One-line summarized result shown after a tool resolves. */
result?: string;
/**
* Errors only: multi-line diagnostic dump (stack trace, cause chain)
* rendered dim beneath the headline, capped to a handful of lines.
*/
detail?: string;
/** Tool / connection lifecycle status. */
status?: ToolStatus;
/** When true, treat `body` as pre-styled and only wrap + indent it. */
preformatted?: boolean;
/** Reasoning only: collapse the trace to a single "thinking" line. */
collapsed?: boolean;
/** When true, expand tool input/output instead of summarizing. */
expanded?: boolean;
/** Raw tool input / output for the expanded view. */
toolInput?: unknown;
toolOutput?: unknown;
}
export interface RenderBlockContext {
/** Current spinner frame for live blocks. */
spinner: string;
/**
* Kind and title of the block rendered immediately above this one. Lets a
* log block detect that it continues a same-source run (label suppressed,
* lines hang under the previous block's label) without any mutable run
* state — each captured write stays its own immediately-committed block.
*/
previous?: {
kind: BlockKind;
title?: string;
};
}
/**
* Renders a block to its terminal rows. Each row is fully styled and clipped
* to `width` visible columns.
*/
export declare function renderBlockLines(block: Block, width: number, theme: Theme, context: RenderBlockContext): string[];
/**
* The setup attention line (`⚠ 1 setup issue: … · /model`): yellow glyph, body
* at full intensity, slash commands painted blue so the fix reads as actionable
* — clearly a system surface, not chat content. Exported so the live footer can
* render the same line as a clearable element (it disappears once the issue is
* resolved), not just committed scrollback.
*/
export declare function renderAttentionRows(body: string, width: number, theme: Theme): string[];