AI model selector
ai-ui specs/ai-ui/model-selector.kmd
Dropdown/menu for choosing AI model mid-conversation. Capability chips (vision/tools/reasoning/long-context/voice), cost tier, recent-used, "auto" mode delegating to Kode Relay. Source-of-truth: registries/ai-model-recommendations.md. Required for Kortex/Talk power-user surfaces.
When this spec applies
Primary triggers
- Render model selector dropdown/menu
All triggers
- Allow user to switch AI model in a conversation
- Display per-model capabilities
- Implement Kortex / Talk / Kruze with multi-model support
Specification body
Spec — AI model selector
Backend:
services/ai/modelreg/+services/ai/gateway/+services/ai/kode/(Relay). Registry source-of-truth:registries/ai-model-recommendations.md. Companion:cost-display.kmd(#112).
Princípios
- Capability-first display — user vê o que o model SUPORTA (vision/tools/reasoning/long-context/voice), não só o nome.
- Cost transparency — tier visible (1x/10x/100x); cross-link cost display per-message.
- Auto mode is the default — Kode Relay routing escolhe modelo apropriado per task.
- Mid-conversation switch — supported com warning de cache re-priming cost.
R1 — Anatomia
Compact button (chat header chip): current model name + capability icons.
Tap → opens menu:
┌──────────────────────────────────────────┐
│ Auto · let Kode Relay decide ✓ │
│ 1x cost · all capabilities │
├──────────────────────────────────────────┤
│ Anthropic │
│ Claude Opus 4.7 · 100x ✨🔧🧠📏 │
│ Claude Sonnet 4.6 · 10x ✨🔧🧠📏 │
│ Claude Haiku 4.5 · 1x ✨🔧🧠📏 │
├──────────────────────────────────────────┤
│ OpenAI │
│ GPT-5 · 100x ✨🔧🧠📏 │
│ GPT-5 Mini · 10x ✨🔧🧠📏 │
├──────────────────────────────────────────┤
│ Google │
│ Gemini 3 Pro · 50x ✨🔧🧠📏🔊 │
├──────────────────────────────────────────┤
│ Self-hosted Koder │
│ Koder LLM · 1x 🔧🧠 │
├──────────────────────────────────────────┤
│ Recent: Claude Opus 4.7, GPT-5 │
└──────────────────────────────────────────┘
Slots:
| Slot | Content |
|---|---|
| Current chip | name + cost tier + 3 prominent capability icons |
| Menu | grouped by provider; capability chips per model; cost tier; recent |
R2 — Capability chips
| Icon | Capability | Description |
|---|---|---|
| ✨ | vision | Accepts image input |
| 🔧 | tools | Native tool/function calling |
| 🧠 | reasoning | Has thinking/reasoning mode |
| 📏 | long-context | Context window > 200k tokens |
| 🔊 | voice | Native voice input/output |
| 🎨 | multimodal | Image generation, video, etc. |
Source: model declared capabilities in modelreg. Refresh on session
start.
R3 — Cost tier
Relative to baseline (base_cost-equivalent of cheapest available model in registry):
| Tier | Range |
|---|---|
| 1× | baseline |
| 5× | 4-9× baseline |
| 10× | 9-30× baseline |
| 50× | 30-80× baseline |
| 100× | 80×+ baseline |
Source: registries/ai-model-recommendations.md (per-model pricing).
Tier displayed; absolute cost via cost-display.kmd (#112).
R4 — "Auto" mode
Default selection: "Auto · let Kode Relay decide".
Behavior:
- Gateway request has
model: "auto". services/ai/kode/Relay receives + analyzes task (prompt classification, attached content types, agent vs chat) + routes to best model.- Resulting model shown in response metadata; chip updates retroactively to show which model handled THIS message (not the next).
User can override (pick specific model); subsequent requests honor override.
R5 — Mid-conversation switch warning
Switching model mid-conversation has cost:
- Previous context cached em old model (Anthropic prompt caching, OpenAI cached input, etc.) is lost.
- New model needs full context re-priming.
When user switches mid-conversation:
┌─────────────────────────────────────────────┐
│ Switching model: warning │
│ │
│ The new model will need to re-read your │
│ {N} message history. Estimated extra cost: │
│ {tokens} tokens (~{currency}). │
│ │
│ [Cancel] [Switch] │
└─────────────────────────────────────────────┘
Skip warning if context is empty (new conversation).
R6 — Recent-used
Maintain MRU list per (koder_user_id, workspace_id). Top 3 surfaced
as quick-pick group.
R7 — Per-tenant default
Workspace settings allow default_model: "<model_id>" override of
Auto. Per-user override possible. Cascade: user > workspace > stack default (Auto).
R8 — Surface bindings
| Surface | API |
|---|---|
| Flutter | KoderModelPicker({onModelChange, currentModel}) em koder_kit/lib/src/ai/model_picker.dart |
| Web | <koder-model-picker> |
| Compose Android | KoderModelPicker (futuro) |
| SwiftUI iOS | idem (futuro) |
| CLI / TUI | koder model list + koder model use <id> + setting in TOML |
R9 — Acessibilidade
- Button:
aria-haspopup="menu" aria-expanded="...". - Menu:
role="menu"+ itemsrole="menuitem". - Provider groups:
role="group" aria-label="<provider>". - Selected:
aria-checked="true". - Keyboard nav: arrows + Enter + Esc.
- Screen reader announces model name + cost tier + 3 capabilities.
R10 — i18n
| Key | en-US | pt-BR |
|---|---|---|
ai.model.auto.label | "Auto" | "Automático" |
ai.model.auto.subtitle | "Let Kode Relay decide" | "Deixar a Kode Relay decidir" |
ai.model.recent | "Recent" | "Recentes" |
ai.model.capability.vision | "Vision" | "Visão" |
ai.model.capability.tools | "Tools" | "Ferramentas" |
ai.model.capability.reasoning | "Reasoning" | "Raciocínio" |
ai.model.capability.long_context | "Long context" | "Contexto longo" |
ai.model.capability.voice | "Voice" | "Voz" |
ai.model.switch.warning_title | "Switching model" | "Trocando modelo" |
ai.model.switch.warning_body | "Re-reading history may add cost." | "Reler o histórico pode adicionar custo." |
R11 — Per-preset variation
Cosmetic: button shape per preset; menu fill; chip styles. Content fixed.
T-suite
- T1 Mount: button shows current model + 3 capability icons; "Auto" by default.
- T2 Open menu: tap button → menu populates from modelreg.
- T3 Capability chips: model with vision+tools+reasoning shows correct icons.
- T4 Cost tier display: model priced 50x baseline → "50×" badge.
- T5 Switch: select different model → onModelChange callback fires.
- T6 Switch warning: existing conversation + switch → confirmation dialog.
- T7 Auto mode: select Auto → gateway request includes model="auto".
- T8 Recent: switch twice → recent group has 2 entries.
- T9 Per-tenant default: workspace sets default_model → loaded on new conversation.
- T10 A11y: arrow keys nav menu; Enter selects.
- N1 Modelreg unavailable: graceful fallback to Auto only.
Cross-link
- Companion:
cost-display.kmd(#112) - Backend:
services/ai/modelreg/,services/ai/gateway/,services/ai/kode/ - Registry:
registries/ai-model-recommendations.md - Policies:
multi-tenant-by-default.kmd(per-workspace default)
References
meta/docs/stack/specs/ai-ui/cost-display.kmdmeta/docs/stack/registries/ai-model-recommendations.mdmeta/docs/stack/policies/multi-tenant-by-default.kmd