/** * Pure presentation logic for tool cards (CHAT-004/005, V2-054/055). * * Collapsed cards must stay cheap even when the spool holds multi‑MB output * (no full-string split on every render). Full bodies open in the pager. */ import type { BoundedTextState } from "../../app/events/event-buffer.js"; import type { ToolItem } from "../state/transcript-types.js"; export interface ToolPresentation { readonly glyph: string; readonly statusLabel: string; /** Bold title — tool name or "Edited App.css". */ readonly name: string; readonly argsLabel: string | undefined; readonly argsDisplay: string | undefined; readonly detail: string | undefined; /** Full absolute path line under file-mutation titles. */ readonly pathLine: string | undefined; /** True when the card should render a structured file-diff body. */ readonly isFileDiff: boolean; } /** * Bound the args/command preview. * * A heredoc (`cat > main.py << 'EOF' … EOF`) puts an entire file into * `argsDisplay`. Rendering it verbatim made one card hundreds of rows tall, * which overflowed the card border and corrupted the surrounding transcript * layout. The full command is still available in the pager and the artifact. * Rows keep their full text — callers soft-wrap to the visible width, they * never get a `…` slapped mid-line. */ export declare function clampArgsDisplay(raw: string | undefined): string | undefined; export declare function presentTool(item: ToolItem): ToolPresentation; /** Basename + create/overwrite marker for writeMany list rows. */ export declare function writeManyFileLabel(change: { readonly path: string; readonly kind: string; }): string; export interface OutputPresentation { readonly lines: readonly string[]; readonly hiddenAboveCount: number; readonly truncatedNotice: string | undefined; } /** * Sample start+end of a huge string so we never `.split("\n")` a multi‑MB body * just to draw a collapsed card. */ export declare function sampleEnds(raw: string, eachEnd?: number): string; /** * Clean raw spool body for card rendering. Lines keep their full text — * every caller soft-wraps to its own visible width instead of relying on a * fixed character cap here. */ export declare function cleanToolOutputLines(raw: string): string[]; /** * Prefer keeping high-signal evidence lines at the top of a collapsed card * for research tools (R5): top search hits, fetch title/status + lede. */ export declare function evidencePreviewLines(toolName: string | undefined, cleaned: readonly string[]): string[] | undefined; /** * Card body presentation. * * Collapsed: head + tail with a mid-body “··· N lines more ···” gap so the end * of streaming output stays visible. Expanded (Ctrl+O): full cleaned body in * place (classic parity). The unbounded raw body always lives in the spool / * artifact and the click-to-open pager modal. */ export declare function presentOutput(tail: string, state: BoundedTextState | undefined, expanded: boolean, toolName?: string): OutputPresentation;