import type { Subprocess } from "bun";
import type { TtsProgressEvent, TtsWorkerInbound, TtsWorkerOutbound } from "./tts-protocol";
/** Decoded PCM returned by a local synthesis request. */
export interface TtsAudio {
    pcm: Float32Array;
    sampleRate: number;
}
/**
 * Abstraction over the TTS subprocess. The runtime implementation is a Bun child
 * process so `onnxruntime-node`'s NAPI finalizer never runs inside the main agent
 * address space — that destructor segfaults Bun during shutdown (issue #1606).
 */
interface WorkerHandle {
    send(message: TtsWorkerInbound): void;
    onMessage(handler: (message: TtsWorkerOutbound) => void): () => void;
    onError(handler: (error: Error) => void): () => void;
    /** Re-reference the subprocess so a pending request keeps the parent event loop alive. */
    ref(): void;
    /** Drop the reference once the worker is idle so it never blocks process exit. */
    unref(): void;
    terminate(): Promise<void>;
}
export interface TtsSynthesizeOptions {
    voice?: string;
    signal?: AbortSignal;
}
export interface TtsDownloadOptions {
    signal?: AbortSignal;
    onProgress?: (event: TtsProgressEvent) => void;
}
export interface TtsStreamOptions {
    voice?: string;
    signal?: AbortSignal;
}
/** One synthesized sentence of a streaming session, in emission order. */
export interface TtsAudioChunk {
    index: number;
    text: string;
    pcm: Float32Array;
    sampleRate: number;
}
/**
 * A live streaming-synthesis session. Feed text incrementally with {@link push}
 * and close the input with {@link end}; `chunks` yields each synthesized
 * sentence's audio as soon as it is ready, then completes once the worker
 * finishes draining the closed input.
 */
export interface TtsStreamHandle {
    push(text: string): void;
    end(): void;
    chunks: AsyncIterableIterator<TtsAudioChunk>;
}
/**
 * Hidden subcommand on the main CLI that boots the TTS worker in the spawned
 * subprocess. Kept in sync with the dispatch in `cli.ts` (Main-owned).
 */
export declare const TTS_WORKER_ARG = "__omp_worker_tts";
interface SpawnedSubprocess {
    proc: Subprocess<"ignore", "ignore", "ignore">;
    inbound: Set<(message: TtsWorkerOutbound) => void>;
    errors: Set<(error: Error) => void>;
    /** Flipped to `true` right before the deliberate SIGKILL so `onExit` can tell it apart from a crash. */
    intentionalExit: {
        value: boolean;
    };
}
/**
 * Spawn the TTS worker as a subprocess. Exported for tests and the smoke probe;
 * production callers go through {@link spawnTtsWorker}.
 */
export declare function createTtsSubprocess(): SpawnedSubprocess;
export declare class TtsClient {
    #private;
    constructor(spawnWorker?: () => WorkerHandle);
    onProgress(listener: (event: TtsProgressEvent) => void): () => void;
    synthesize(modelKey: string, text: string, options?: TtsSynthesizeOptions): Promise<TtsAudio | null>;
    /**
     * Open a streaming-synthesis session. Text is fed incrementally through the
     * returned handle's `push`/`end`; audio is emitted one synthesized sentence at
     * a time via `chunks`, so playback can begin before the full text is known.
     * Returns an inert handle (immediately-ended `chunks`) for unknown models or
     * an already-aborted signal, and fails the iterator if the worker cannot spawn.
     */
    synthesizeStream(modelKey: string, options?: TtsStreamOptions): TtsStreamHandle;
    downloadModel(modelKey: string, options?: TtsDownloadOptions): Promise<boolean>;
    terminate(): Promise<void>;
}
export declare const ttsClient: TtsClient;
export declare function shutdownTtsClient(): Promise<void>;
export declare function smokeTestTtsWorker({ timeoutMs, }?: {
    timeoutMs?: number;
}): Promise<void>;
export {};
