/** * Drives the external `voicetools` binary and streams its stdout line protocol * into callbacks. One line per event on stdout (stderr is free for debug logs): * * ```text * STATUS recording # state transition (recording | transcribing | ...) * SEGMENT hello world # a chunk of decoded text * DONE # finished successfully * ERROR no model found # fatal error; process exits non-zero * ``` * * `voicetools serve` (see `VoiceDaemon` below) reuses this same line protocol * plus a few daemon-only events (READY, LEVEL, PHASE). * * The caller wires `onSegment` to inject text into the editor (via bracketed * paste) and `onStatus` / `onError` to surface feedback. */ export type VoiceStatus = "recording" | "transcribing" | "done" | "listening" | string; export interface VoiceTranscribeHandlers { /** A decoded chunk of text. Injected into the editor by the caller. */ onSegment: (text: string) => void; /** A state transition reported by the binary, or `"done"` on completion. */ onStatus: (status: VoiceStatus) => void; /** A fatal error: spawn failure, protocol ERROR line, or non-zero exit. */ onError: (message: string) => void; } /** * A running voice-transcribe session. Call `stop()` to cancel early (e.g. the * user pressing the shortcut again). `stop()` is idempotent. */ export interface VoiceSession { stop(): void; readonly running: boolean; } /** * Spawn `voicetools transcribe` for a single capture. This is the fallback * path for binaries that don't support `serve` (see `VoiceDaemon`): every * push-to-talk press pays the model load cold start. */ export declare function startVoiceTranscribe(bin: string, handlers: VoiceTranscribeHandlers): VoiceSession; /** * Handlers for a persistent `voicetools serve` daemon. Extends the base * transcribe handlers with the daemon-only events: * - `onReady` fires once after models finish loading. * - `onLevel` per-audio-chunk RMS, for a live meter/waveform. * - `onPhase` phase markers (e.g. `"silence"` when trailing silence begins). * - `onPartial` interim transcript while the user speaks — the FULL growing * hypothesis each time (supersedes the previous), never committed. * - `onFinal` the complete committed transcript for the utterance, emitted * once before DONE — this is the text to inject into the editor. * - `onCrash` the process died after having been ready (caller should drop * the reference and respawn lazily on the next push-to-talk). */ export interface VoiceDaemonHandlers extends VoiceTranscribeHandlers { onReady?: () => void; onLevel?: (rms: number) => void; onPhase?: (phase: string) => void; onPartial?: (text: string) => void; onFinal?: (text: string) => void; onCrash?: (message: string) => void; /** Fired when the daemon has been idle (no capture) for `idleTimeoutMs`. */ onIdle?: () => void; } /** * Outcome of {@link VoiceDaemon.spawn}. `reason: "unsupported"` means the * process exited before READY with no ERROR line at all — the signature of * an old binary rejecting the unrecognized `serve` subcommand — and the * caller should silently fall back to `startVoiceTranscribe`. `reason: * "error"` means a genuine ERROR line (or OS-level spawn failure) was seen; * `handlers.onError` has already been called with it, and the caller should * surface that (not retry with the legacy path, which would just hit the * same failure) while leaving daemon mode available to retry next press. */ export type VoiceDaemonSpawnResult = { ok: true; daemon: VoiceDaemon; } | { ok: false; reason: "unsupported" | "error"; }; /** Tunables passed to `voicetools serve` on spawn. Omitted fields use the binary's defaults. */ export interface VoiceDaemonOptions { /** Trailing-silence timeout, in ms, before the binary auto-stops a capture (`--silence-ms`). */ silenceMs?: number; /** Idle timeout, in ms. After a capture completes, the daemon auto-shuts down * if no new capture starts within this window, releasing the warm model from * memory. `0` disables idle shutdown (daemon stays warm forever). */ idleTimeoutMs?: number; } /** * A persistent `voicetools serve` process: models are loaded once and stay * warm across captures. Only one capture runs at a time; call `startCapture` * to open the mic and `cancel` to stop early. `spawn` doubles as the support * probe for old binaries (see {@link VoiceDaemonSpawnResult}). */ export declare class VoiceDaemon { private readonly proc; private readonly handlers; private closed; private idleTimer; private readonly idleTimeoutMs; private constructor(); get isReady(): boolean; static spawn(bin: string, handlers: VoiceDaemonHandlers, options?: VoiceDaemonOptions): Promise; private startIdleTimer; private stopIdleTimer; private handleLine; /** Begin a capture: opens the mic, streams PARTIAL/FINAL (or SEGMENT), ends with DONE. */ startCapture(): void; /** Cancel the in-flight capture, if any. Idempotent. */ cancel(): void; /** Ask the daemon to exit gracefully, force-killing if it doesn't within 1s. */ shutdown(): void; } //# sourceMappingURL=voice-transcribe.d.ts.map