import{type TemplateResult,type PropertyValues}from'lit';import{LyraElement}from'../../../internal/lyra-element.js';import type{LyraAnchor,LyraHighlight,HighlightActivateDetail,TextSelectDetail}from'../../viewers/document-viewer/anchors.js';export type{LyraAnchor,LyraHighlight,LyraHighlightTone,HighlightActivateDetail,TextSelectDetail,}from'../../viewers/document-viewer/anchors.js';import type{LyraFrame}from'../../../internal/variants.js';import type{LyraSearchChangeDetail}from'../../../internal/text-viewer-target.js';import{type LyraClipboardWriteFailure,type LyraClipboardWriteSuccess}from'../../../internal/clipboard.js';export interface LyraTerminalEventMap{'lr-copy':CustomEvent;'lr-error':CustomEvent;'lr-copy-error':CustomEvent;'lr-download':CustomEvent<{filename:string;}>;'lr-follow-change':CustomEvent<{following:boolean;}>;'lr-search-change':CustomEvent;'lr-highlight-activate':CustomEvent;'lr-text-select':CustomEvent;} /** * `` — read-only ANSI console for streamed agent/tool output. Not a PTY: no * stdin/keystroke handling, no cursor-addressed full-screen apps. Split ANSI sequences retain at * most 4,096 characters; an overlong unterminated control sequence is dropped so later chunks * resume without an unbounded hidden carry. * * `compact` tightens the toolbar and line padding for dense transcript rows, and `frame="plain"` * removes the outer card chrome when a surrounding container already supplies it — the same pair * `lr-result-card`, `lr-stack-trace`, `lr-task-list`, and `lr-thinking-panel` expose. * * Deliberately no `maxHeight`/`--lr-terminal-max-height` pair (unlike `lr-json-viewer`, * `lr-diff-view`, `lr-code-block`, `lr-stack-trace`, and `lr-markdown`): those default to `none` * and grow with their content until a caller opts into a cap. This component's `[part="viewport"]` * is *always* a fixed-height virtualized scrollback region — `--lr-terminal-height` (default * `20rem`) already is that cap, retunable the same way. A second, differently-shaped "grows until * capped" property would fight that always-scrolling model rather than complement it. * * @customElement lr-terminal * @event lr-copy - `detail: { ok: true, text }` — the plain-text clipboard write completed. * @event lr-error - The clipboard write failed; generic no-detail notification. * @event lr-copy-error - `detail: { ok: false, text, reason, error }` — typed clipboard failure. * @event lr-download - `detail: { filename }` — the download button was activated. Cancelable: by * default this component itself builds an in-memory Blob of the current plain-text log and * triggers a browser download via a synthetic `` click; a host that calls * `preventDefault()` on this event suppresses that built-in download entirely and can substitute * its own handling (e.g. routing a large log through a server-side export instead), mirroring * ``'s `lr-open` convention. * @event lr-follow-change - `detail: { following }` — a user viewport/jump action changed * stick-to-bottom. Direct `follow` assignments and imperative navigation do not echo an event. * @event lr-search-change - `detail: { query, matchCount, matchCountExact, activeIndex }`. * `matchCountExact` is `false` once a search hits the 10,000-match retention ceiling, marking * `matchCount` as a lower bound rather than an exact total. * @event lr-highlight-activate - `detail: { highlightId }` — a highlighted line was * clicked/activated. * @event lr-text-select - `detail: { text, anchor, rects }` — fires on pointerup after a text * selection ending inside the viewport. `anchor` is `null` when either selection endpoint isn't * inside a currently-mounted (non-virtualized-out) line. * @csspart base - The outer container. * @csspart toolbar - The header row, only rendered when copy/download are enabled. * @csspart copy-button - The copy-to-clipboard button. * @csspart download-button - The download button. * @csspart viewport - The `role="log"` scrollable region wrapping the virtualized line list. * @csspart line - One rendered line; carries `data-line-number`, `data-match`, `data-highlight-tone`. * Rendered through ``'s `renderItem`, so it lives inside that element's own * shadow root rather than this component's -- this component's own stylesheet reaches it via * `lr-virtual-list::part(line)`, one hop of the standard CSS Shadow Parts selector. * @csspart line-interactive - Alias on a line that owns an activatable highlight. * @csspart line-highlight-accent - Alias on an accent-highlighted line. * @csspart line-highlight-success - Alias on a success-highlighted line. * @csspart line-highlight-warning - Alias on a warning-highlighted line. * @csspart line-highlight-danger - Alias on a danger-highlighted line. * @csspart line-highlight-neutral - Alias on a neutral-highlighted line. * @csspart line-match - Alias on a line containing a search match. * @csspart line-active-match - Alias on the active search-match line. * @csspart jump-to-latest - The pill shown while `follow` is disengaged and new output has arrived. * @csspart announcer - The visually-hidden, `aria-hidden` mirror of the text last announced while * `announce-output` is set. The announcement itself lands in the shared light-DOM region * (`acquireAnnouncementSink()` in `internal/announcer.ts`), because a live region inside a shadow * root is not reliably announced; this part is a styling/inspection surface only. * @cssprop [--lr-terminal-height=var(--lr-size-20rem)] - Block size of `[part="viewport"]`, the * scrollable log region. Not declared on `:host`, so it is inherited — set it on the host or any * ancestor. * @cssprop [--lr-terminal-surface-color=var(--lr-color-surface-raised)] - Card-frame background * and the fallback foreground for inverse ANSI segments without an explicit background. The * `frame="plain"` escape remains transparent. * @cssprop [--lr-terminal-toolbar-button-hover-bg=var(--lr-color-brand-quiet)] - Hover background * of `[part="copy-button"]` and `[part="download-button"]`. * @cssprop [--lr-terminal-toolbar-button-active-bg=color-mix(in oklab, var(--lr-terminal-toolbar-button-hover-bg, var(--lr-color-brand-quiet)), var(--lr-color-mix-partner) var(--lr-color-mix-active))] - Pressed background of the toolbar buttons. * @cssprop [--lr-terminal-line-hover-bg=var(--lr-color-brand-quiet)] - Hover background of an * ordinary rendered `[part="line"]`. * @cssprop [--lr-terminal-line-active-bg=color-mix(in oklab, var(--lr-terminal-line-hover-bg, var(--lr-color-brand-quiet)), var(--lr-color-mix-partner) var(--lr-color-mix-active))] - Pressed background of an ordinary rendered line. * @cssprop [--lr-terminal-highlight-accent-bg=var(--lr-color-brand-quiet)] - Background of an * `accent`-tone highlighted line. Decoupled from the shared `--lr-color-brand-quiet` token also * used by `[part="copy-button"]`/`[part="download-button"]`'s hover state, and from any * `::part('line')` override (the background is applied inline, so a stylesheet rule can't beat it * without `!important`). * @cssprop [--lr-terminal-highlight-success-bg=var(--lr-color-success-quiet)] - Background of a * `success`-tone highlighted line. * @cssprop [--lr-terminal-highlight-warning-bg=var(--lr-color-warning-quiet)] - Background of a * `warning`-tone highlighted line. * @cssprop [--lr-terminal-highlight-danger-bg=var(--lr-color-danger-quiet)] - Background of a * `danger`-tone highlighted line. * @cssprop [--lr-terminal-highlight-neutral-bg=var(--lr-color-surface)] - Background of a * `neutral`-tone highlighted line. * @cssprop [--lr-terminal-search-outline-color=var(--lr-color-warning)] - Outline color for a * line containing a non-active search match. * @cssprop [--lr-terminal-search-active-outline-color=var(--lr-color-brand)] - Outline color for * the active search match's line. * @cssprop [--lr-terminal-compact-toolbar-padding=var(--lr-space-2xs) var(--lr-space-xs)] - * `[part="toolbar"]` padding while `compact`. * @cssprop [--lr-terminal-compact-toolbar-gap=var(--lr-space-2xs)] - Gap between * `[part="toolbar"]`'s buttons while `compact`. * @cssprop [--lr-terminal-compact-line-padding-inline=var(--lr-space-xs)] - Inline padding of each * rendered `[part="line"]` while `compact`. * @cssprop [--lr-terminal-border-color=var(--lr-color-border)] - Colour of the outer card's * border and of the toolbar/log divider, which `frame="plain"` keeps. * @cssprop [--lr-terminal-radius=var(--lr-radius)] - Corner radius of the outer card. * `frame="plain"` still squares the corners. * @status stable * @since 4.0.0 */ export declare class LyraTerminal extends LyraElement{protected static readonly immutableEventDetails:readonly string[];static styles:import("lit").CSSResultGroup[];content:string; /** Line-count scrollback buffer limit. NaN/negative/oversized (e.g. `Infinity`) normalize to a * 1..10,000 range; total retained cells and cells per line have independent hard ceilings. */ maxScrollback:number;follow:boolean;wrap:boolean;copyable:boolean;downloadable:boolean;filename:string;announceOutput:boolean; /** Accessible name for the nested `role="log"`; a non-empty host `aria-label` is forwarded, * while an empty value falls back to the localized terminal-purpose label. */ accessibleLabel:string; /** Line-range highlights keyed by stable id. Empty/blank ids and highlights with a missing, * malformed, or non-discriminated anchor are omitted (`snapshotLyraHighlights`) before * duplicates normalize first-wins for range ownership, activation, and anchor lookup. * @default [] */ private _highlights;get highlights():readonly LyraHighlight[];set highlights(value:readonly LyraHighlight[]);activeHighlightId:string|null;private get normalizedHighlights(); /** Tightens the toolbar's padding/gap and each rendered line's inline padding for a terminal * embedded in an already-padded transcript row -- same convention as `lr-task-list`'s and * `lr-thinking-panel`'s `compact`. Defaults to `false`, i.e. the full padding. Purely a density * knob: the card border and background stay, so use `frame="plain"` to drop the chrome. */ compact:boolean; /** Visual chrome, in the library's shared container-frame vocabulary. `'card'` (the default) * keeps `[part="base"]`'s border, corner radius, and raised surface; `'plain'` removes all * three so a terminal nested inside a container that already draws a border (an agent-run * panel, a message bubble) doesn't double it. Plain keeps the toolbar/log divider and whichever * regular or compact padding applies -- it controls outer chrome only. */ frame:LyraFrame; /** Feature-detectable capability mirror -- the same pattern `DocumentAnchorTarget`-adopting * viewers use for their own `anchorKinds` field. This component isn't document-viewer-registry- * routed, so it has no registry `capabilities.anchors` entry to declare this on instead. */ readonly anchorKinds:readonly LyraAnchor['kind'][];private lines;private scrollTargetLineNumber;private copyStatus;private buffer;private retainedCellCount;private lineSeq;private column;private appliedContent;private readonly terminalLineKey;private readonly ansiParser;private copyTimeoutId?;private copyTimeoutWindow?;private copyTimeoutGeneration?;private copyGeneration; /** Plain text appended since the last announcer flush -- coalesced so a burst of small * `write()` chunks (a common line-by-line stdout pattern) becomes one throttled announcement * instead of one per chunk. Reset in the announcer's own `onFlush` callback below, so it always * reflects exactly "what's new since the last thing actually spoken". */ private pendingAnnounceText;private announceRegionEl?; /** Handle on the shared light-DOM live region every flush actually announces through -- a region * rendered inside this shadow root is not reliably announced (JAWS with Firefox ignores one * outright), so `[part="announcer"]` below is only an `aria-hidden` mirror. */ private sink?;private readonly announcer;private searchQuery;private searchMatches; /** `false` once `recomputeSearchMatches()` hits `MAX_SEARCH_MATCHES` -- marks `searchMatches` * as a truthful lower bound rather than the true total. */ private searchMatchCountExact;private searchActiveIndex;connectedCallback():void;disconnectedCallback():void;adoptedCallback():void;firstUpdated(changed:PropertyValues):void;protected willUpdate(changed:PropertyValues):void;private resetBuffer;private appendLine;private effectiveMaxScrollback;private trimScrollback;private putChar;private applyChunk;private writeInternal; /** Append streamed output. Escape sequences may split across chunks -- the shared parser buffers * partial sequences internally up to its 4,096-character ceiling, then drops an unterminated * sequence and resumes from a clean boundary on the next write. */ write(chunk:string):void; /** Synchronously replaces the buffer and the reactive `content` source. This is the explicit * commit-order primitive for code that mixes replacement with same-turn `write()`/`clear()`. */ replace(content:string):void;private commitPendingContent;clear():void;getPlainText():string;scrollToBottom():void;private jumpToLatest;private recomputeSearchMatches;private emitSearchChange;private searchState;private emitSearchChangeIfChanged;private jumpToActiveMatch; /** Resolves the retained match count. The emitted `lr-search-change.matchCountExact` is `false` * when that return value is only a lower bound because the 10,000-match retention ceiling was * reached. A query with no matches also clears the previous rendered search markers. */ search(query:string):Promise; /** Advances to the next match, wrapping to the first after the last. Resolves `true` once the * active match moved, `false` when there are no matches -- the shape the shared * `LyraTextViewerTarget` search contract declares, so a find-in-page host can drive every * searchable component through one typed surface. */ searchNext():Promise; /** Moves to the previous match, wrapping to the last before the first. Resolves `true` once the * active match moved, `false` when there are no matches. */ searchPrevious():Promise;clearSearch():void; /** Resolves, in one O(highlights + covered-lines) pass, both (a) `perLine` -- the same winning * highlight a per-line `this.highlights.find(...)` scan would have returned for every line * currently in the buffer, first match in `this.highlights` array order winning any overlap -- * and (b) `owners`, the first (lowest-numbered) line each highlight actually wins, i.e. the one * `renderLine()` renders as the highlight's single interactive (`role="button"`) owner. Replaces * what used to be a per-line `.find()` scan of the whole `highlights` array (O(lines × * highlights) every render). `this.lines`' numbers are always contiguous (see `appendLine()`), * so a highlight's `[start, end]` range is * clamped to the buffer's actual `[minLine, maxLine]` and then walked directly -- an end far * outside the buffer (or omitted) never costs more than a pass over the lines actually present. * Highlights are processed in array order and a line already claimed by an earlier (higher * priority) highlight is skipped, which reproduces `.find()`'s first-match-wins tie-break * exactly, including when a later-array, wider/earlier-starting highlight would otherwise have * looked like the "obvious" winner by start position alone. */ private resolvedHighlightLines;private activateHighlight;private onLineKeyDown;scrollToAnchor(target:LyraAnchor|string):Promise;private onCopy;private copyOutput;private isCurrentCopy;private showCopyStatus;private resetCopyFeedback;private clearCopyTimeout;private cancelPendingAnnouncement;private onDownload;private onVisibleRangeChanged;private onViewportKeyDown; /** Best-effort: resolves a user text selection ending inside the viewport into `lr-text-select`. * Walks each selection endpoint up to its nearest `[data-line-number]` ancestor to build a * `line-range` anchor; `anchor` is `null` when either endpoint isn't inside a currently-mounted * line (virtualized out, or the selection reaches outside the viewport entirely) -- matching * `TextSelectDetail`'s own documented "`anchor` is `null` when the selection couldn't be * anchored" case, shared by every anchor-capable viewer. Cross-shadow-boundary text selection * has known browser-support variance; this degrades to no event firing rather than a broken one * when the platform doesn't expose a usable Selection here. */ private onViewportPointerUp; /** Per-line state styling (cursor, search-match outline, highlight-tone background). Applied * inline rather than through `data-match`/`data-highlight-tone` stylesheet selectors, since those * attributes live on the same element `part="line"` names -- and a `::part()` selector (needed to * reach across ``'s shadow boundary, see `terminal.styles.ts`) cannot be * combined with a trailing attribute selector the way a same-shadow-root rule could. */ private lineStateStyle;private renderLine;private segmentStyle;render():TemplateResult;}declare global{interface HTMLElementTagNameMap{'lr-terminal':LyraTerminal;}}