Skip to content

feat: inline model picker in AI chat composer with per-turn provider attribution#1058

Merged
datlechin merged 8 commits into
mainfrom
feat/chat-model-picker
May 7, 2026
Merged

feat: inline model picker in AI chat composer with per-turn provider attribution#1058
datlechin merged 8 commits into
mainfrom
feat/chat-model-picker

Conversation

@datlechin

Copy link
Copy Markdown
Member

Phase 2 of #1047. Inline model picker in the chat composer + per-turn provider attribution stamped on every assistant message. Builds on the ChatTurn.modelId / ChatTurn.providerId slots that landed in #1057.

What you see

  • Picker in the composer (under the text field, leading edge of the send-button row). Shows Provider · model with the standard cpu icon and a chevron. Click → menu of all configured providers; checkmark on the current selection.
  • Attribution badge in the assistant-message footer next to the regenerate button. Shows the model name that produced that turn. Past turns retain their original modelId when you switch mid-conversation.

This matches Cursor / Zed / Copilot Chat conventions: per-message attribution, picker at the bottom of the composer next to actions.

What's wired

  • AIChatViewModel.selectedProviderId: UUID? and .selectedModel: String? track the user's choice. Both default to nil, in which case AIProviderFactory.resolve falls back to the active provider in settings.
  • AIProviderFactory.resolve(settings:overrideProviderId:overrideModel:) accepts optional overrides. Existing resolve(settings:) callers keep working via default arguments.
  • startStreaming() resolves with the overrides and stamps the assistant ChatTurn with modelId: resolved.model and providerId: resolved.config.id.uuidString.
  • AIChatMessageView reads message.modelId and renders it as a small .tertiary badge in the assistant footer.

Persistence

Picker state lives on the view model. Persists for the lifetime of the chat panel session, not across app launches. On restart, the picker resets to the active provider in settings (which is the user's intentional default). Per-conversation persistence is a follow-up if anyone asks.

Out of scope

  • Per-conversation picker memory.
  • Available-models list per provider (AIProviderConfig stores one model per entry; switching requires the user to configure additional providers in Settings, same as today).
  • Model picker in toolbar / outside the composer.

CHANGELOG

Adding under [Unreleased] -> Added.

Test plan

  • With one configured provider, the picker shows it; clicking does nothing harmful.
  • With two configured providers (e.g. Claude + Ollama), open the picker, switch from one to the other.
  • Send a message after switching — the new assistant turn shows the new model name in its footer.
  • Switch back; new turns are attributed to the old model. Past turns retain their original attribution.
  • Open a conversation from before this PR (no modelId set) — assistant turns render without the attribution badge, no crash.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@datlechin datlechin merged commit 6acbfc6 into main May 7, 2026
2 checks passed
@datlechin datlechin deleted the feat/chat-model-picker branch May 7, 2026 03:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant