import { type VoiceCommand } from "./convo.js"; import { VoiceStt, type SttOptions } from "./stt.js"; import { VoiceTts } from "./tts.js"; export interface VoiceConfig { sttProvider: string; /** Transcription model for the OpenAI provider (real-time gpt-4o-transcribe by default). */ sttModel: string; ttsProvider: string; apiKey: string; voice: string; speed: number; language: string; /** Conversation mode: how long (ms) to wait after you stop talking before * sending — higher = more tolerant of mid-sentence pauses. */ silenceMs: number; /** Hands-free max recording duration (ms): stop listening + submit after this long * regardless, so a runaway/open mic can't record forever. Default 60000 (60s). */ maxDictationMs: number; /** How much of a reply is read aloud, in characters (#179). A long answer is fine to * read but exhausting to listen to, and OpenAI TTS hard-rejects over 4096 — so this is * bounded 200–4096 rather than offered as "unlimited". Default 1500. */ ttsMaxChars: number; /** Mic sensitivity for silence detection (0.4–2): higher = more sensitive * (needs a smaller gap above the noise floor to count as speech). Default 1. */ sensitivity: number; /** Whether hands-free voice commands (e.g. "repeat") are honored. Default true. */ commandsEnabled: boolean; /** Hold a screen wake lock during hands-free so the display doesn't sleep and * suspend the mic. Default true; users on iOS can disable it in Settings → Voice. */ keepAwake: boolean; /** Custom hands-free command keywords (Settings → Voice). Empty ⇒ built-in defaults * for repeat/mute; stopWords is off unless set. */ repeatWords: string[]; muteWords: string[]; /** Phrases that re-open the mic while muted (#152) — matched ONLY while muted. */ unmuteWords: string[]; /** Phrases that leave voice mode entirely and return to typing (#165). */ exitWords: string[]; /** Phrases that move you to the agent asking for you (#277). Inert on a surface that * cannot switch conversations — see `useVoice`'s `onNext`. */ nextWords: string[]; /** Phrases that scrap the last turn (#342). Whole-utterance only, and inert on a surface * that cannot delete — see `useVoice`'s `onScrap`. */ scrapWords: string[]; /** * Commands the user switched OFF (#443). Default empty: everything on. * * The answer to "exit cannot be turned off at all". A SWITCH rather than a blank field, so the * built-ins stay language-derived — see {@link VoiceCommandWords.disabled} for why the * blank-means-off spelling was measured to be unrepairable. */ disabledCommands: VoiceCommand[]; stopWords: string[]; /** * Words the user says that a recogniser gets wrong (#373) — the account list UNIONed with this * agent's, resolved server-side, plus (from `derivedVocabulary`) the proper nouns the platform * already knows about this agent (#372). * * Used TWICE, because the two recognisers have different capabilities: appended to the * transcription bias prompt (Whisper takes a vocabulary hint), and applied as a post-hoc * spelling correction over the finished transcript from EITHER engine — which is the only * lever that exists on the browser path, where there is no steerable grammar at all. */ vocabulary: string[]; /** Say this word/phrase while the agent is speaking to immediately halt playback * (e.g. "stop stop"). Empty ⇒ off. Per-instance. Case-insensitive substring match. */ stopSpeechKeyword: string; /** Lock STT to the configured language (#126): a transcript detected as a DIFFERENT * language is treated as a mis-detection and NOT sent — the user is asked to repeat, * instead of the agent responding in the wrong language. Default on. */ confirmLanguage: boolean; } /** True if the saved settings want an OpenAI-backed provider (Whisper STT or OpenAI * TTS) — the only case where we need to check whether the key is present. */ export declare function voiceWantsOpenAi(vs: Record): boolean; /** * Resolve raw voice settings + key presence into a concrete {@link VoiceConfig}. * Pure (no I/O) so the provider fallback + numeric clamping is unit-tested. An * OpenAI-backed provider is only chosen when the key is actually present — otherwise * we fall back to the browser voice rather than fail. */ export declare function resolveVoiceConfig(vs: Record, hasOpenAiKey: boolean): VoiceConfig; /** * The instance's voice config, cached across calls. * * `refresh: "background"` serves the cached value IMMEDIATELY and revalidates behind it. The * hands-free start path used to invalidate the cache and `await` this before touching * `getUserMedia`, so every entry paid a network round trip (two, when an OpenAI provider forces * the `/v1/keys/status` check) with nothing on screen — measurably the dominant await in #284, * and the one worth removing rather than papering over with a spinner. * * The trade is explicit: a settings change now lands on the NEXT mic start rather than this one. * That is the right way round — the user is not on the settings screen at the moment they tap * the mic, and the revalidate fired here has normally landed long before they tap it again. */ export declare function getVoiceConfig(instanceId?: string, opts?: { refresh?: "background"; }): Promise; export declare function invalidateVoiceConfig(): void; export declare function createTts(instanceId?: string, opts?: { technical?: boolean; }): Promise; export declare function createStt(instanceId?: string, opts?: Partial): Promise; //# sourceMappingURL=config.d.ts.map