Implementation
List<({String id, String name})> get availableModels => switch (this) {
claude => const [
(id: 'claude-sonnet-4-6', name: 'Claude Sonnet 4'),
(id: 'claude-haiku-4-5-20251001', name: 'Claude Haiku 4.5'),
],
openai => const [
(id: 'gpt-4.1', name: 'GPT-4.1'),
(id: 'gpt-4.1-mini', name: 'GPT-4.1 Mini'),
(id: 'gpt-4.1-nano', name: 'GPT-4.1 Nano'),
(id: 'o3-mini', name: 'o3 Mini'),
],
gemini => const [
(id: 'gemini-2.5-pro', name: 'Gemini 2.5 Pro'),
(id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash'),
(id: 'gemini-2.0-flash', name: 'Gemini 2.0 Flash'),
],
// Curated GGUF Q4_K_M allowlist served by Hugging Face mirrors. IDs are
// clean slugs used in storage keys + UI; the canonical file names +
// download URLs + SHA-256 checksums are resolved in
// `LocalLlmDatasource._modelSpecs`. Inference runs on llama.cpp via
// `llama_cpp_dart`; the embedded GGUF chat template is applied
// automatically by `EngineChat.generate`. Llama 3.2 1B is first so
// the radio list lands on a model named "Llama" by default.
local => const [
(id: 'llama-3.2-1b', name: 'Llama 3.2 1B Instruct (~0.8 GB) — default'),
(id: 'gemma-2-2b', name: 'Gemma 2 2B (~1.7 GB)'),
(id: 'qwen2.5-1.5b', name: 'Qwen 2.5 1.5B (~1.0 GB) — low-RAM'),
(
id: 'deepseek-r1-distill-1.5b',
name: 'DeepSeek R1 Distill 1.5B (~1.1 GB) — reasoning',
),
],
};