# AI Configuration Domain

## WS1 Configuration Infrastructure

### WS1-F1: Instance-level env vars and key fallback
- `settings.py`: `VOYAGE_AI_PROVIDER`, `VOYAGE_AI_MODEL`, `VOYAGE_AI_API_KEY`
- `get_llm_api_key(user, provider)` falls back to instance key only when provider matches `VOYAGE_AI_PROVIDER`
- Fallback chain: user key -> matching-provider instance key -> error
- See [tech-stack.md](../tech-stack.md#server-side-env-vars-from-settingspy), [decisions.md](../../decisions.md#ws1-configuration-infrastructure-backend-review)

### WS1-F2: UserAISettings model
- `integrations/models.py`: `UserAISettings` (OneToOneField to user) with `preferred_provider` and `preferred_model`
- Endpoint: `/api/integrations/ai-settings/` (upsert pattern)
- Migration: `0008_useraisettings.py`

### WS1-F3: Provider catalog enhancement
- `get_provider_catalog(user=None)` adds `instance_configured` and `user_configured` booleans
- User API keys prefetched once per request (no N+1)
- `ChatProviderCatalogEntry` TypeScript type updated with both fields

### Frontend Provider Selection (Fixed)
- No longer hardcodes `selectedProvider = 'openai'`; auto-selects first usable provider
- Filtered to configured+usable entries only (`available_for_chat && (user_configured || instance_configured)`)
- Warning alert + Settings link when no providers configured
- Model selection uses dropdown from `GET /api/chat/providers/{provider}/models/`

## Known Frontend Gaps

### Root Cause of User-Facing LLM Errors
Three compounding issues (all resolved):
1. ~~Hardcoded `'openai'` default~~ (fixed: auto-selects first usable)
2. ~~No provider status feedback~~ (fixed: catalog fields consumed)
3. ~~`UserAISettings.preferred_provider` never loaded~~ (fixed: Settings UI saves/loads DB defaults; chat initializes from saved prefs)
4. `FIELD_ENCRYPTION_KEY` not set disables key storage (env-dependent)
5. ~~TypeScript type missing fields~~ (fixed)

## Key Edit Reference Points
| Feature | File | Location |
|---|---|---|
| AI env vars | `backend/server/main/settings.py` | after `FIELD_ENCRYPTION_KEY` |
| Fallback key | `backend/server/chat/llm_client.py` | `get_llm_api_key()` |
| UserAISettings model | `backend/server/integrations/models.py` | after UserAPIKey |
| Catalog user flags | `backend/server/chat/llm_client.py` | `get_provider_catalog()` |
| Provider view | `backend/server/chat/views/__init__.py` | `ChatProviderCatalogViewSet` |
