feat: add runtime provider/model switching via /model <tier> <provider/model>

- ModelRouter: add setClient(), labels map, getLabel(), getAllLabels()
- TUI commands: parse /model <tier> <provider/model> syntax with autocompletion
- TUI minimal: handle provider switching via createClientFromConfig factory
- Daemon: wire initial labels into router config
- Fix /model alias mappings (opus=complex, sonnet=default, haiku=fast)
- Add design doc and update state.json with feature status
This commit is contained in:
William Valentin
2026-02-06 23:42:14 -08:00
parent e92ce69067
commit d4530a7034
8 changed files with 527 additions and 37 deletions
+135 -2
View File
@@ -336,6 +336,136 @@
}
}
},
"p4-media-pipeline": {
"status": "completed",
"date": "2026-02-06",
"summary": "Multimodal media pipeline: receive images from channel adapters and pass through to vision-capable models (Anthropic, OpenAI, Gemini, Bedrock)",
"phases": {
"type_widening": {
"priority": "P4",
"status": "completed",
"description": "Widen Message.content from string to string | MessageContentPart[], add Attachment type to channel layer, add ImageSource/MessageContentPart types",
"files_created": [
"src/models/media.ts",
"src/models/media.test.ts"
],
"files_modified": [
"src/models/types.ts",
"src/models/index.ts",
"src/channels/types.ts",
"src/channels/index.ts"
],
"test_status": "25/25 passing"
},
"model_client_multimodal": {
"priority": "P4",
"status": "completed",
"description": "Update all model clients to convert MessageContentPart[] to provider-specific image formats (Anthropic base64, OpenAI data URI, Gemini inlineData, Bedrock image bytes)",
"files_modified": [
"src/models/anthropic.ts",
"src/models/openai.ts",
"src/models/gemini.ts",
"src/models/bedrock.ts",
"src/models/local/llamacpp.ts",
"src/models/local/ollama.ts"
]
},
"agent_attachment_passthrough": {
"priority": "P4",
"status": "completed",
"description": "Wire attachments through NativeAgent.process() and AgentOrchestrator.process() to daemon message handler",
"files_modified": [
"src/backends/native/agent.ts",
"src/backends/native/orchestrator.ts",
"src/daemon/index.ts"
]
},
"downstream_type_fixes": {
"priority": "P4",
"status": "completed",
"description": "Fix all consumers of Message.content to use getMessageText() helper: token estimation, compaction, TUI rendering",
"files_modified": [
"src/context/tokens.ts",
"src/context/compaction.ts",
"src/frontends/tui/components/MessageList.tsx"
]
},
"channel_adapter_extraction": {
"priority": "P4",
"status": "completed",
"description": "Extract images from platform messages in all channel adapters",
"sub_phases": {
"telegram": {
"status": "completed",
"description": "Handle message:photo (largest size, download via getFile API, base64) and image message:document events with caption text",
"files_modified": ["src/channels/telegram/adapter.ts"]
},
"discord": {
"status": "completed",
"description": "Extract image attachments from message.attachments Collection, pass Discord CDN URLs directly",
"files_modified": ["src/channels/discord/adapter.ts"]
},
"slack": {
"status": "completed",
"description": "Download image files via url_private_download with bot token auth, base64 encode",
"files_modified": ["src/channels/slack/adapter.ts"]
},
"whatsapp": {
"status": "completed",
"description": "Use downloadMedia() from whatsapp-web.js (returns base64 natively)",
"files_modified": ["src/channels/whatsapp/adapter.ts"]
},
"webchat": {
"status": "deferred",
"description": "Requires gateway protocol update for WebSocket attachment messages"
}
}
}
}
},
"p5-github-copilot-provider": {
"status": "completed",
"date": "2026-02-06",
"summary": "GitHub Copilot as a model provider with OAuth device flow and auto-login on first use",
"phases": {
"copilot_client": {
"priority": "P5",
"status": "completed",
"description": "GitHubModelsClient using OpenAI SDK against api.githubcopilot.com with Copilot-specific headers, multimodal support, streaming, tool calls",
"files_created": [
"src/models/github.ts",
"src/auth/github.ts",
"src/auth/index.ts"
],
"files_modified": [
"src/config/schema.ts",
"src/models/index.ts",
"src/models/costs.ts",
"src/daemon/index.ts",
"src/cli/tui.ts"
]
},
"oauth_device_flow": {
"priority": "P5",
"status": "completed",
"description": "Interactive OAuth device flow via /login github command, token stored at ~/.config/flynn/auth.json with chmod 0600",
"files_modified": [
"src/frontends/tui/minimal.ts",
"src/frontends/tui/commands.ts"
]
},
"auto_login": {
"priority": "P5",
"status": "completed",
"description": "Lazy token resolution with onLoginRequired callback — triggers OAuth device flow automatically on first API call when no token is available",
"files_modified": [
"src/models/github.ts",
"src/daemon/index.ts",
"src/cli/tui.ts"
]
}
}
},
"earlier_plans": {
"status": "completed",
"summary": "Original design and implementation phases from 2026-02-02 to 2026-02-05",
@@ -361,11 +491,14 @@
},
"overall_progress": {
"total_test_count": 655,
"total_test_count": 742,
"all_tests_passing": true,
"p0_completion": "3/3 (100%)",
"p1_completion": "4/4 (100%)",
"p2_completion": "7/7 (100%)",
"next_up": "p3_remaining (group chat support, gateway auth, gemini provider, browser control, additional model providers)"
"p3_completion": "completed (group chat, gateway auth, Gemini, OpenRouter, Bedrock, browser control)",
"p4_completion": "1/1 (100%) — multimodal media pipeline",
"p5_completion": "1/1 (100%) — GitHub Copilot provider with auto-login",
"next_up": "p6 (image.analyze tool, audio transcription, outbound attachments, gateway protocol attachments)"
}
}