6.1 KiB
Plan: Add Mistral AI as Alternative Chat Provider
Context
bDS currently routes all AI chat through the OpenCode Zen gateway (opencode.ai/zen/v1/...) with two code paths: Anthropic Messages API and OpenAI-compatible. The user wants Mistral AI added as a direct alternative provider with frontier models that support chat completion, tool use, and vision. Mistral's API is OpenAI-compatible (api.mistral.ai/v1/chat/completions), making integration straightforward.
Target Models
- Mistral Large 3 (
mistral-large-2512) - frontier, vision, tools, 40k ctx - Mistral Medium 3.1 (
mistral-medium-2508) - frontier, vision, tools, 40k ctx - Mistral Small 3.2 (
mistral-small-2506) - vision, tools, 128k ctx
Files to Modify
1. src/main/engine/OpenCodeManager.ts - Core provider logic
A. Add Mistral constants (near lines 23-25)
MISTRAL_API_URL = 'https://api.mistral.ai/v1/chat/completions'MISTRAL_MODELS_URL = 'https://api.mistral.ai/v1/models'
B. Add Mistral models to MODEL_DISPLAY_NAMES (lines 28-69)
'mistral-large-2512': 'Mistral Large 3'
'mistral-medium-2508': 'Mistral Medium 3.1'
'mistral-small-2506': 'Mistral Small 3.2'
C. Update detectProvider() (lines 1839-1845)
- Add:
if (id.startsWith('mistral') || id.startsWith('ministral')) return 'mistral';
D. Add Mistral API key storage
- New field:
private mistralApiKey: string = '' - New methods:
setMistralApiKey(),getMistralApiKey(),validateMistralApiKey() - Load on init from settings key
'mistral_api_key'
E. Add Mistral request path in sendMessage()
- Route
provider === 'mistral'to newsendMistralRequest()method - Similar to OpenAI path but:
- URL:
MISTRAL_API_URL(direct, not through OpenCode gateway) - Auth:
Authorization: Bearer ${this.mistralApiKey} - No
tool_choice: "required"— use"any"for Mistral's equivalent - Context budget: 35,000 tokens (vs 150k for OpenCode) for 40k-ctx models, 120k for Small 3.2
- URL:
F. Vision format for Mistral
- In
view_imagetool result handling: useimage_urlformat with base64 data URI - Format:
{ type: 'image_url', image_url: { url: 'data:image/webp;base64,...' } } - Same as OpenAI path (Mistral is compatible here)
G. Update getAvailableModels()
- When Mistral key is set, include Mistral models in returned list
- Add
providerfield to model entries so UI can group them
H. Update analyzeMediaImage() (lines 2066-2192)
- Support Mistral models for image metadata analysis (title/alt/caption generation)
- When a Mistral model is selected, use Mistral vision format (
image_urlwith base64 data URI) - Route to
api.mistral.aiwith Mistral API key
2. src/main/engine/ChatEngine.ts - Settings persistence
A. Add Mistral key helpers
getMistralApiKey()- read from settings tablesetMistralApiKey(key)- persist to settings table- Settings key:
'mistral_api_key'
3. src/main/ipc/chatHandlers.ts - IPC bridge
A. Add Mistral-specific handlers
chat:setMistralApiKey- validate + persist Mistral keychat:getMistralApiKey- return masked keychat:validateMistralApiKey- test key against Mistral API
B. Update chat:getAvailableModels
- Include Mistral models when Mistral key is configured
- Return provider info per model
C. Update chat:checkReady
- Report readiness for both providers independently
4. src/main/shared/electronApi.ts - Type definitions
A. Extend ChatModel interface
- Add
provider: 'opencode' | 'mistral'field (already optional, ensure populated)
B. Add Mistral IPC methods to ElectronAPI.chat
setMistralApiKey(key: string)getMistralApiKey()validateMistralApiKey(key: string)
5. src/renderer/components/SettingsView.tsx - UI settings
A. Add Mistral API key section
- Separate input field for Mistral API key (below OpenCode key)
- Same pattern: masked display, change button, validation on save
B. Update model selector
- Group models by provider in dropdown (optgroup: "OpenCode Zen", "Mistral AI")
- Show provider badge next to selected model
6. src/renderer/components/ChatPanel/ChatPanel.tsx - Chat UI
A. Update model selector in chat
- Group by provider in dropdown
- Only show models for configured providers
7. Preload/IPC registration
A. src/main/ipc/handlers.ts or preload
- Register new Mistral IPC channels
- Expose in preload bridge
8. MCP Server - src/main/engine/MCPServer.ts
- No changes needed — MCP server exposes tools for external AI agents to call; no bDS-side AI runs during MCP requests
Implementation Order
- Tests first (per AGENTS.md)
- Types (
electronApi.ts) - Engine (
OpenCodeManager.ts— constants, detection, key storage, request path) - Persistence (
ChatEngine.ts— settings helpers) - IPC (
chatHandlers.ts— new handlers) - UI (
SettingsView.tsx,ChatPanel.tsx— key input, model grouping) - Build verification
Key Differences to Handle
| Aspect | OpenCode/OpenAI | Mistral |
|---|---|---|
| Base URL | opencode.ai/zen/v1/... |
api.mistral.ai/v1/... |
| Auth header | Bearer ${openCodeKey} |
Bearer ${mistralKey} |
| Tool choice forced | "required" |
"any" |
| Parallel tools | not set | parallel_tool_calls: true |
| Context budget | 150k tokens | 35k (Large/Medium), 120k (Small) |
| Vision format | image_url block |
image_url block (same) |
| Streaming | SSE deltas | SSE deltas (same) |
Verification
- Run
npm test— all existing + new tests pass - Run
npm run build— clean build - Manual: set Mistral API key in Settings, verify validation
- Manual: select Mistral Large 3, send chat message, verify response streams
- Manual: use
view_imagetool in chat with Mistral model, verify vision works - Manual: verify tool calling works (search_posts, list_posts, etc.)
- Manual: verify OpenCode models still work unchanged
Resolved Decisions
analyzeMediaImage()— Mistral models will be usable for image metadata analysis- MCP server — N/A; MCP server only exposes tools, no bDS-side AI runs during MCP requests
- Model dropdown grouping — Use
<optgroup>labels ("OpenCode Zen", "Mistral AI")