import type { ThemeColor } from "./theme.js"; import type { ToolEntryConfig } from "./display-config.js"; export type { ToolEntryConfig, ToolResultMode } from "./display-config.js"; export type Color = ThemeColor; export interface StyleHint { color?: Color; bold?: boolean; dim?: boolean; italic?: boolean; } export type Segment = string | { text: string; style?: StyleHint; highlight?: string; }; export type Body = { kind: "text"; segments: Segment[]; } | { kind: "code"; lang?: string; text: string; } /** Width-aware renderer supplied via setDiffRenderer; view() opts in and gates on hasDiff. */ | { kind: "diff"; } | { kind: "stream"; text: string; } | { kind: "lines"; lines: Segment[][]; } | { kind: "compound"; parts: Body[]; }; export interface DisplayStatus { exitCode: number | null; elapsedMs: number; summary?: string; } /** Renderers pick a category; ashi picks the glyph. */ export type TitleIcon = "read" | "search" | "edit" | "shell" | "generic" | "scheme"; export interface ToolDisplay { titleIcon?: TitleIcon; title: Segment[]; /** Right-aligned on the title line; framework handles padding and status-suffix spacing. */ titleRight?: Segment[]; status?: DisplayStatus; /** Drop the status suffix from the title line — for renderers that surface it on the result line instead. */ hideTitleStatus?: boolean; body?: Body; expandable?: boolean; defaultExpanded?: boolean; } /** `mode`, `previewLines`, `expandedLines` come from ashi.display.{name}. */ export interface Env { width: number; expanded: boolean; finalized: boolean; mode: "preview" | "summary" | "hidden"; previewLines: number; expandedLines?: number; } export type Reducer = (state: S, payload: P) => S; /** Framework tracks `output`/`status`/`hasDiff`; renderers don't wire those reducers. */ export type ViewState = S & { output: string; status?: DisplayStatus; hasDiff: boolean; }; export interface RenderInitArgs { rawInput?: unknown; name: string; title: string; kind?: string; displayDetail?: string; } export interface RenderModel> { initial: (args: RenderInitArgs) => S; /** Only for tool-specific state transitions; `status`/`chunk` are framework-tracked. */ reducers?: Record, never>>; view: (state: ViewState, env: Env) => ToolDisplay; display?: Partial; } export declare function isRenderModel(v: unknown): v is RenderModel; export interface MountArgs { toolCallId: string; name: string; title: string; kind?: string; displayDetail?: string; rawInput?: unknown; } export interface MountEnv { width: number; mode: Env["mode"]; previewLines: number; expandedLines?: number; } /** Width-aware diff cache shared between this projection and the renderer's mount cell. */ export interface DiffSlot { fn?: (width: number) => string[]; lastWidth: number; cached: string[]; } export declare function segmentsToString(segs: Segment[]): string; export declare function iconString(icon?: TitleIcon): string; export declare function statusSuffix(s?: DisplayStatus): string; export declare function renderBody(body: Body, env: Env, diff: DiffSlot): string;