Adding New AI Providers
Relevant source files
The following files were used as context for generating this wiki page:
mausVoice is built with a "TypeScript is the Brain" architecture, where all business logic—including the resolution of AI providers for transcription and LLM text cleanup—lives within the TypeScript layer. The application supports a hybrid model of local providers (like Whisper) and external API-backed services (like Groq, Deepgram, and OpenAI).
Adding a new provider involves updates across the voice-ai package for communication logic, the desktop application for state management and UI, and the Tauri configuration for security allowlisting. The system utilizes encrypted local storage (XChaCha20-Poly1305) for API keys, ensuring that provider credentials are never baked into the binary.
Sources: llms.txt:19-27, CLAUDE.md:15-18, PRODUCT.md
Architecture and Data Flow
The data flow for AI processing moves from the user interface through Zustand state actions to specific repository implementations that interface with the voice-ai package.
This diagram illustrates how the TypeScript layer decides between local processing and external API calls based on the user's configuration.
Sources: llms.txt:24-31, CLAUDE.md:21-25
Core Implementation Steps
1. Update the Voice-AI Package
New providers typically require shared utility functions for text generation or transcription. If the provider is OpenAI-compatible, it can leverage existing streaming chat utilities.
- File Path:
packages/voice-ai/src/ - Key Utilities:
openaiCompatibleStreamChatandopenaiGenerateTextResponsehandle standard chat completions and text generation. - Integration Testing: Every provider should implement a test integration function (e.g.,
openaiCompatibleTestIntegration) to verify connectivity.
// Example from packages/voice-ai/src/openai.utils.ts:167-176
export const openaiCompatibleTestIntegration = async ({
baseUrl,
apiKey,
}: OpenAICompatibleTestIntegrationArgs): Promise<boolean> => {
const client = createClient(apiKey || "dummy", baseUrl);
// Test connectivity by listing models
await client.models.list();
return true;
};
Sources: openai.utils.ts:167-176, openai.utils.ts:241-260
2. Configure Tauri Security (CSP)
Tauri's security model requires external domains to be explicitly allowlisted in the Content Security Policy (CSP) and the application capabilities.
- File:
apps/desktop/src-tauri/tauri.conf.json - Security Update: Add the provider's API endpoint to
connect-src. - Distinction: External API domains must be in the
http:defaultpermission set, not inremote.urls, to ensure they can be reached viafetch()but cannot access IPC commands.
Sources: CLAUDE.md:46-52, tauri.conf.json:28-30
3. Repository and Command Registration
To expose the new provider to the frontend, the corresponding Rust commands and TypeScript repositories must be updated.
| Step | Component | Action |
|---|---|---|
| Rust | commands.rs | Define new #[tauri::command] if native bridge is needed. |
| Rust | app.rs | Register the command in the invoke_handler. |
| Bindings | gen:bindings | Run pnpm gen:bindings to update TypeScript definitions. |
| TypeScript | src/repos/ | Implement the logic in the relevant Repository (e.g., LocalLLMRepo). |
Sources: CLAUDE.md:31-35, packages/desktop-native-apis/README.md:44-53
AI Provider Configuration Parameters
When implementing a new provider, the following standard configuration types from @maus-inc/types are typically utilized:
| Parameter | Type | Description |
|---|---|---|
apiKey | string | User-provided key, stored encrypted on disk. |
baseUrl | string (Optional) | Custom endpoint for self-hosted or proxy services. |
model | string | The specific model identifier (e.g., gpt-4o-mini). |
temperature | number | Controls randomness (standard LLM parameter). |
jsonResponse | object | Schema for structured output (used in transcription cleaning). |
Sources: openai.utils.ts:87-95, openai.utils.ts:121-136
Security Requirements
Adding a new provider MUST strictly follow the existing security patterns:
- Encryption: API keys must be encrypted with XChaCha20-Poly1305 before storage.
- CSP Sync: The
connect-srcintauri.conf.jsonmust always be in sync with the external API allowlist. - No Wildcards: Never add a wildcard (
*) to any CSP directive for a new provider.
Sources: llms.txt:60-64, CLAUDE.md:52-54
Conclusion
Adding a new AI provider requires careful synchronization between the voice-ai communication layer, the Tauri security configuration, and the TypeScript application logic. By following the project's "TypeScript as the Brain" pattern, developers ensure that provider integration remains maintainable and secure.