/** * Push-to-talk voice input controller for the TUI. * * Owns the enabled/recording state and ties microphone capture to * transcription. The editor drives this controller from its key dispatch: * it calls startRecording() when a held space begins push-to-talk, and * stopRecording() when the space key is released (detected as an idle gap * after the last repeated space). * * Transcribed text is delivered through the onTranscript callback so the * editor can insert it at the cursor. */ import type { AuthStorage } from '@mastra/code-sdk/auth/storage'; import type { VoiceSettings } from '@mastra/code-sdk/onboarding/settings'; import type { PermissionGuidance } from './engines/types.js'; export interface VoiceControllerOptions { authStorage?: AuthStorage; /** Voice configuration (engine/provider/model). */ settings: VoiceSettings; /** Called with transcribed text to insert at the cursor. */ onTranscript: (text: string) => void; /** * Called repeatedly during recording with the best transcript of the audio * captured so far. Each call supersedes the previous one (replace, not * append), so the input shows live dictation as the user keeps speaking. */ onPartialTranscript?: (text: string) => void; /** Show a transient informational message. */ showInfo: (message: string) => void; /** Show a transient error message. */ showError: (message: string) => void; /** * Called when push-to-talk recording starts (true) and ends (false) so the * editor can drive a "listening" cursor animation. */ onListeningChange?: (listening: boolean) => void; } export type VoiceState = 'idle' | 'recording' | 'transcribing'; export declare class VoiceController { private enabled; private state; private session; private engine; private settings; private liveTranscriptEmitted; private readonly options; constructor(options: VoiceControllerOptions); /** * Swap the active engine/provider/model from updated settings. If voice is * currently enabled it is re-validated against the new engine. */ reconfigure(settings: VoiceSettings): void; isEnabled(): boolean; /** * Deeper readiness check that may do async work (e.g. compiling the native * recognizer). Returns `null` when ready or a user-facing problem message. * Falls back to the synchronous check when the engine has no async verify. */ verifyReady(): Promise; /** * Structured, actionable permission guidance for the active engine (e.g. how * to grant macOS Microphone/Speech access). Returns `null` for engines that * don't expose it (cloud), so callers can skip the guided flow. */ permissionGuidance(): Promise; getState(): VoiceState; isRecording(): boolean; /** * Toggle voice input on/off. Returns the new enabled state. * Reports problems (missing recorder/credentials) via showError and stays * disabled when prerequisites are missing. */ toggle(): boolean; enable(): boolean; /** * Restore the persisted enabled state at startup without emitting the * interactive "voice input on" message or surfacing errors. Silently stays * disabled if the active engine is not ready. */ restoreEnabled(): void; disable(): void; /** * Begin a streaming recognition session. No-op if disabled or already active. * Partial results stream into the input via onPartialTranscript; the final * result replaces the live text (live mode) or streams in word-by-word. */ startRecording(): void; /** * Stop the session and let the engine emit its final transcript. */ stopRecording(): Promise; /** * Abort any in-progress session without transcribing. */ cancelRecording(): void; /** * Surface a session error. If the active engine can explain a permission * problem (e.g. macOS access is blocked), append the concrete fix steps so the * user knows exactly what to do instead of seeing a bare failure. */ private reportSessionError; /** * Feed the transcript into the editor incrementally so it visibly streams in * word-by-word rather than appearing all at once. Each chunk keeps its * trailing whitespace so word spacing is preserved. */ private streamTranscript; } //# sourceMappingURL=voice-controller.d.ts.map