/** * Multi-line voice-input status panel. * * Renders the live state of a `voicetools serve` capture across its phases so * the user always sees what's happening: * * ```text * ● Listening · 0:03 esc cancel * ▁▂▃▅▇▆▄▂▁▂▄▆▇▅▃▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ← level history, left-anchored on a track * › and so my fellow ameri▏ ← live partial transcript (PARTIAL) * ``` * * Phases: * - `warming` spinner while the binary resolves / model loads; shows a * real progress bar when a download reports byte counts * - `listening` recording dot + elapsed timer + waveform + partial text * - `silence` trailing-silence countdown; waveform dims * - `transcribing` spinner while the final decode runs * * The component self-animates (spinner, timer, countdown) on an internal timer * and calls `ui.requestRender()`; the owner feeds it protocol events via * `pushLevel` / `setPartial` / `beginSilence` / `setDownloadProgress` etc. and * disposes it on collapse. */ import type { Component, TUI } from "@kolisachint/hoocode-tui"; export type VoicePanelPhase = "warming" | "listening" | "silence" | "transcribing"; export declare class VoicePanel implements Component { private readonly ui; private readonly cancelHint; private phase; private frame; private levels; private partial; private listeningStartMs; private silenceRemainingMs; private warmingMessage; private warmingDetail; private downloadReceived; private downloadTotal; private downloading; private timer; constructor(ui: TUI | undefined, cancelHint: string); private ensureAnimating; /** Stop timers. The owner removes the panel from its container to collapse it. */ dispose(): void; /** No cached render state to clear; every `render()` recomputes from live state. */ invalidate(): void; setWarming(message: string, detail?: string): void; /** * Live byte counts while the voicetools binary downloads (first run only). * Turns the warming spinner into a determinate progress bar. */ setDownloadProgress(receivedBytes: number, totalBytes: number | null): void; startListening(): void; beginSilence(totalMs: number): void; /** Speech resumed before cutoff: return to the listening phase. */ endSilence(): void; setTranscribing(): void; pushLevel(rms: number): void; setPartial(text: string): void; /** * Level history, LEFT-anchored: the meter grows from the left edge and the * unfilled remainder renders as a dim baseline track, so the first seconds of * a capture read as a meter filling — not a cluster of glyphs floating at the * far right edge over a void (the old right-anchored layout). Once the * history exceeds the width it scrolls, keeping the newest samples visible. */ private renderWaveform; private renderPartial; private elapsedLabel; /** * The model download's progress, rendered by the shared progress-bar * component so this panel and the footer always agree. The panel is wider * than a footer line, so it asks for a finer track — width is the only thing * a surface gets to choose. */ private renderDownloadBar; render(width: number): string[]; } //# sourceMappingURL=voice-panel.d.ts.map