Fix reply to single model silently skipping AI response#69
Fix reply to single model silently skipping AI response#69sidharthmirch wants to merge 97 commits into
Conversation
- New Visible Models settings tab: fetch models from OpenRouter/Ollama/LM Studio, then toggle per-model visibility with sub-provider filter chips - New Model Profiles settings tab: create/edit/delete named model sets grouped by provider; profiles draw only from visible models - Centralized filtering (ModelFiltering.ts) so visibility and active profile apply consistently in the chat model picker and quick chat - Profile selector dropdown in the chat model picker uses the themed Radix Select component Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Model Profiles and Visible Models management
Adds persona/role presets that inject a system prompt into chats. Includes 5 built-in profiles (Data Scientist, Academic Researcher, Study Guide, Code Reviewer, Creative Writer), a per-chat selector pill in the chat input toolbar, and a Prompt Profiles tab in Settings. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Model Profiles, Visible Models, and Prompt Profiles
- Created BUILD.md with instructions - Updated README.md - Added .github/workflows/build.yml - Removed unused import in ModelFiltering.ts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add LFS support to checkout step - Add Rust toolchain setup with caching via actions-rust-lang/setup-rust-toolchain@v1 - Use pnpm install --frozen-lockfile for deterministic builds - Remove push-to-main trigger to avoid duplicating cloud-qa.yaml - Upgrade pnpm/action-setup from v3 to v4 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The updater bundle requires TAURI_SIGNING_PRIVATE_KEY which isn't available in CI. Build only app and dmg bundles for verification. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
--bundles flag doesn't suppress createUpdaterArtifacts; use --config inline override instead to prevent the signing key error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds workflow_dispatch trigger with optional release_tag input. Builds for both aarch64 and x86_64 targets. When a release tag is provided, creates a GitHub Release with downloadable .app.zip and .dmg files for both architectures. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add GitHub Release support to build workflow
- Migration v142: create Ambient Gemini Flash config (gemini-2.5-flash-preview-04-17, vision-capable, free tier on Google AI Studio), migrate users off the deprecated ambient-gemini-2.5-pro config, mark old config as deprecated - Remove ALLOWED_MODEL_IDS_FOR_QUICK_CHAT allowlist so all non-deprecated, enabled models with valid API keys appear in the ambient model selector Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Migration v143: add gemini-2.5-flash-lite (stable, vision-capable, free tier), deprecate gemini-2.0-flash-lite-preview-02-05, update ambient config to point to the new flash-lite model - Allow gemini-2.5-flash-lite in ProviderGoogle model name allowlist Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bump @tauri-apps/plugin-store to ~2.2.0 to match the Rust crate which had already resolved to 2.2.0 via Cargo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ambient (quick chat) mode should not pass MCP tools like web_search to the model — there's no UI to invoke them and they cause confusing responses when the model tries to call an unconfigured tool. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update ambient default to Gemini 2.5 Flash and open model selector
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bump version to 0.14.6
Adds a "Select All" button in the profile selector row of the manage models dialog, plus a cmd+shift+A keyboard shortcut to select all currently visible models (respecting active profile and search filter). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Select All button and shortcut to model picker
… shortcut scope - Extract selectableVisibleModels memo shared by button and shortcut, filtering out models without API keys and OpenRouter when collapsed - Add `enabled` option to useShortcut so cmd+shift+A is not swallowed in non-default dialog modes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lowup Fix Select All: filter ungated models, dedup logic, scope shortcut
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bump version to 0.14.7
Users can now select which model is used to auto-generate chat titles. Defaults to the ambient chat model, with the option to pick from any cheap enabled OpenRouter model the user has marked available. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Made-with: Cursor
…r-1-8gq Persist model selection per chat and default new-chat models
…model prefs Made-with: Cursor
- Settings.tsx: use hasOwnProperty to guard against prototype key exploits in tab validation
- DefaultsTab.tsx: filter fallback profile dropdown to only profiles containing the fallback model; add incompatibility warning; add comment that visibleModels are not filtered by active profile
- ChorusDefaultPreferences.ts: simplify buildFreshInstallModelAndPromptDefaults to remove unused apiKeys param (always called with {} at fresh install)
- Settings.ts: update call sites to match simplified signature
- MessageAPI.ts: tighten applyChatCreationModelDefaults JSDoc to reflect quick-chat-only behavior
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Settings.tsx: remove unnecessary 'as string' type assertion (fixes ESLint no-unnecessary-type-assertion) - migrations.rs: add migration 144 to add default_prompt_profile_id column to projects - ProjectAPI.ts: add defaultPromptProfileId to Project type/DB row/read/fetch, add useSetProjectDefaultPromptProfile mutation - chatCreationDefaults.ts: pass project-level default profile to applyDefaultPromptProfileForChat, which takes priority over the global setting - ProjectView.tsx: add prompt profile selector in the CHATS panel (hidden when no profiles exist) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Uses a proper isSettingsTabId type guard function to narrow rawTab to SettingsTabId without a type assertion, fixing the ESLint no-unnecessary-type-assertion error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comparing rawTab (which includes SettingsTabId) against "quick-chat" caused TS2367 since "quick-chat" is not a member of SettingsTabId. Fix: resolve the searchParams tab param independently (as string | null), then merge with the typed tab prop via ??. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Default settings and new-chat model preferences
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… guard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Deselect model block when clicking outside or re-clicking selected block
…blur Fix sidepane blur state being forced on the reply panel
- Add currentVisualOrder store to track resolved visual order of model columns - Extend cmd+1-8 keybindings to work with tools block (was compare-only) - Use visual order for tools keybindings so cmd+1 always selects leftmost column - Add cmd/ctrl+shift+space keybinding to scroll selected column into view - Add data-tools-message-id attribute for DOM queries
…nearest - Wrap activeMessages in useMemo so toolsItemOrder is stable and the setCurrentVisualOrder effect only fires when the order actually changes - Update clearChat to also delete from currentVisualOrderByChatId (was leaking per-chat visual state on navigation) - Add block: nearest to scrollIntoView to prevent unintended vertical scrolling
…r-keybindings Fix cmd+number keybindings for tools and compare blocks - added cmd+shift+space to focus selected block
- CMD+1-8 now smooth-scrolls the selected model column into view - CMD+Shift+Space now moves the selected model to the first column position - Added data-compare-message-id attribute to compare block columns for scroll targeting Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
bug fixes for cmd+KEY and multi-model selection states
… single model replyToModelConfig?.modelId is a human-readable model string (e.g. "anthropic::claude-sonnet-4-5"), but fetchModelConfigById expects a UUID primary key. Passing the wrong field caused it to return null, silently skipping AI generation on reply. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
There was a problem hiding this comment.
Pull request overview
This PR fixes the “reply to a single model silently skips AI response” bug by ensuring reply flows pass a model config primary key (config id) into block population. In addition, it introduces a broader set of model-management and UX features (visibility, profiles, defaults, minimize/reorder columns), plus supporting persistence/migrations and build/docs updates.
Changes:
- Fix reply-to-single-model by passing/storing model config IDs (not provider model IDs) through the reply + populate pipeline.
- Add model visibility filtering, model/prompt profiles, defaults management, and per-project default prompt profiles; update settings + pickers accordingly.
- Add multi-model UX improvements (minimize/reorder columns, retry handling/tool-disable heuristics), title-generation model selection, and supporting migrations/build docs/workflow updates.
Reviewed changes
Copilot reviewed 47 out of 48 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/ui/lib/models.ts | Removes quick-chat allowed-model allowlist constant. |
| src/ui/hooks/useShortcut.ts | Adds enabled option gate to disable shortcuts without unmounting. |
| src/ui/components/VisibleModelsTab.tsx | New Settings tab UI for toggling model visibility + fetching provider catalogs. |
| src/ui/components/ui/command.tsx | Adds trailing adornment support in command input (e.g., shortcut hint). |
| src/ui/components/SortableColumnItem.tsx | New DnD helper combining draggable + droppable for column reorder. |
| src/ui/components/Settings.tsx | Restructures settings tabs; adds Defaults/Profiles/Visible Models tabs and title model selector. |
| src/ui/components/QuickChatModelSelector.tsx | Uses centralized filtering + provider visibility map for ambient model selection. |
| src/ui/components/PromptProfilesTab.tsx | New CRUD UI for prompt/persona profiles. |
| src/ui/components/PromptProfilePill.tsx | New chat toolbar pill to pick/manage prompt profile per chat. |
| src/ui/components/ProjectView.tsx | Adds per-project default prompt profile selection. |
| src/ui/components/MultiChatDeprecationPath.tsx | Adds minimize/reorder behaviors to deprecated compare UI path. |
| src/ui/components/MultiChat.tsx | Adds minimize/reorder UX for tools/compare blocks; integrates defaults/prompt-profile application on new chats. |
| src/ui/components/ModelProfilesTab.tsx | New CRUD UI for model profiles (named model sets). |
| src/ui/components/ManageModelsBox.tsx | Adds profile selector/apply + select-all shortcut; integrates visibility/profile filtering; supports per-chat selection/reorder hooks. |
| src/ui/components/DefaultsTab.tsx | New consolidated Defaults settings (prompt profile, chat models, fallback, ambient, shortcut/accessibility). |
| src/ui/components/ChatInput.tsx | Fixes reply-to-single-model by passing config id; persists per-chat compare selection; passes excluded minimized models and new-chat defaults flags. |
| src/ui/components/AppSidebar.tsx | Adds “Minimized” panel to manage minimized models and retry failures from sidebar. |
| src/ui/App.tsx | Redirects legacy quick-chat settings tab open requests to defaults. |
| src/core/utilities/Settings.ts | Extends settings schema with defaults/title model; uses fresh-install default builder. |
| src/core/utilities/ModelFiltering.ts | New centralized filtering utility combining visibility + active model profile constraints. |
| src/core/utilities/ChorusDefaultPreferences.ts | New fresh-install default model/prompt settings seed values. |
| src/core/infra/ToolsDisabledStore.ts | New per-chat/per-model tools-disabled store for retry behavior. |
| src/core/infra/ModelOrderStore.ts | New per-chat model order + resolved visual order store for keybindings/UX. |
| src/core/infra/MinimizedModelsStore.ts | New per-chat minimized-models store shared with sidebar/UI. |
| src/core/chorus/simpleLLM.ts | Adds ability to run simple LLM calls via a specific model config ID. |
| src/core/chorus/prompts/prompts.ts | Injects optional prompt-profile system prompt into model config prompts. |
| src/core/chorus/Models.ts | Adds types for ProviderVisibility, ModelProfile, PromptProfile. |
| src/core/chorus/ModelProviders/simple/SimpleCompletionProviderFactory.ts | Adds createProviderByPrefix for explicit-provider selection. |
| src/core/chorus/ModelProviders/ProviderGoogle.ts | Adds support for gemini-2.5-flash-lite name mapping. |
| src/core/chorus/chatCreationDefaults.ts | Applies defaults for new chats (prompt profile / ambient model metadata) and visibility/vision checks. |
| src/core/chorus/ChatCompareSelection.ts | Implements initial compare-model selection priority and syncing global compare metadata to per-chat selection. |
| src/core/chorus/api/ProviderVisibilityAPI.ts | New DB-backed provider-visible-models API + hooks and visibility map helper. |
| src/core/chorus/api/PromptProfilesAPI.ts | New DB-backed prompt profiles + per-chat association APIs. |
| src/core/chorus/api/ProjectAPI.ts | Adds defaultPromptProfileId to projects + mutation to set it. |
| src/core/chorus/api/ModelProfilesAPI.ts | New DB-backed model profiles + active profile tracking via app_metadata. |
| src/core/chorus/api/ModelConfigChatAPI.ts | Exposes saved per-chat model-config selection; resolves effective compare selection with visibility filtering. |
| src/core/chorus/api/MessageAPI.ts | Major updates: prompt-profile injection, retry improvements, tools-disable heuristics, populate behavior changes, title generation model selection, per-chat selection handling. |
| src/core/chorus/api/ChatAPI.ts | Initializes per-chat compare selection on chat creation; applies creation defaults post-insert. |
| src-tauri/tauri.qa.conf.json | Version bump. |
| src-tauri/tauri.dev.conf.json | Version bump. |
| src-tauri/tauri.conf.json | Version bump. |
| src-tauri/src/migrations.rs | Adds tables and model updates for visibility/profiles/defaults; adds gemini model changes; adds project default prompt profile column. |
| README.md | Documents fork-specific features and unsigned app note; adds build doc link. |
| package.json | Version bump; updates @tauri-apps/plugin-store version. |
| BUILD.md | New build instructions. |
| .github/workflows/build.yml | New GitHub Actions workflow for building (and optionally releasing) macOS bundles. |
| .cursor/worktrees.json | Adds worktree setup command configuration for Cursor. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Migration { | ||
| version: 144, | ||
| description: "add default_prompt_profile_id to projects", | ||
| kind: MigrationKind::Up, | ||
| sql: r#" | ||
| ALTER TABLE projects ADD COLUMN default_prompt_profile_id TEXT DEFAULT NULL; | ||
| "#, | ||
| }, | ||
| Migration { | ||
| version: 143, | ||
| description: "add gemini 2.5 flash lite and update ambient to use it", | ||
| kind: MigrationKind::Up, | ||
| sql: r#" |
There was a problem hiding this comment.
The new migrations are not listed in ascending version order (version 144 appears before 143). If the migration runner applies migrations in vector order (rather than sorting by version), this can lead to incorrect application/recording order. Please reorder these entries so migrations are appended in monotonically increasing version order (…142, 143, 144).
| export function useProviderVisibilityMap(): Map<string, boolean> | undefined { | ||
| const { data } = useProviderVisibleModels(); | ||
| if (!data) return undefined; | ||
|
|
||
| return new Map(data.map((v) => [v.modelId, v.isVisible])); | ||
| } |
There was a problem hiding this comment.
useProviderVisibilityMap() creates and returns a new Map instance on every render. Because many callers use this value in useMemo/dependency arrays, this forces unnecessary recomputation even when the underlying data hasn't changed. Consider memoizing the map with useMemo keyed on data (or return the raw array and let callers memoize) so the reference stays stable across renders.
|
|
||
| const visibleConfigs = useMemo( | ||
| () => | ||
| getFilteredModelConfigs( | ||
| modelConfigsQuery.data ?? [], | ||
| providerVisibilityMap, | ||
| null, | ||
| ), | ||
| [modelConfigsQuery.data, providerVisibilityMap], |
There was a problem hiding this comment.
useChatCompareModelConfigs builds visibleConfigs using getFilteredModelConfigs(..., null) (no active model profile). Elsewhere (e.g. ChatCompareSelection.fetchVisibleModelConfigsForSelection and ManageModelsBox) the active model profile is applied, so this can produce an inconsistent state where the current chat selection includes models outside the active profile and the picker UI can't represent them. Consider including the active model profile here as well (or explicitly document that chat compare selection ignores the active profile).
| const visibleConfigs = useMemo( | |
| () => | |
| getFilteredModelConfigs( | |
| modelConfigsQuery.data ?? [], | |
| providerVisibilityMap, | |
| null, | |
| ), | |
| [modelConfigsQuery.data, providerVisibilityMap], | |
| const activeModelProfileQuery = ModelsAPI.useActiveModelProfile(); | |
| const visibleConfigs = useMemo( | |
| () => | |
| getFilteredModelConfigs( | |
| modelConfigsQuery.data ?? [], | |
| providerVisibilityMap, | |
| activeModelProfileQuery.data ?? null, | |
| ), | |
| [ | |
| modelConfigsQuery.data, | |
| providerVisibilityMap, | |
| activeModelProfileQuery.data, | |
| ], |
| void populateBlock.mutateAsync({ | ||
| messageSetId: aiMessageSetId, | ||
| blockType: BLOCK_TYPE, | ||
| replyToModelId: replyToModelConfig?.modelId, | ||
| replyToModelId: replyToModelConfig?.id, | ||
| excludedModelIds: minimizedModels, | ||
| applyChatCreationModelDefaults, |
There was a problem hiding this comment.
PR title/description states this is a one-line fix for single-model reply (replyToModelConfig?.modelId → replyToModelConfig?.id), but this PR also introduces substantial new functionality (model visibility, model/prompt profiles, minimize/reorder UI, defaults, new migrations, etc.). Please either update the PR description to reflect the full scope or split these unrelated changes into separate PRs to reduce review/rollback risk.
Fixes the bug where replying to a single model in the reply window saves the user message but never generates an AI response.
Root cause
ChatInput.tsx:363was passingreplyToModelConfig?.modelId(e.g."anthropic::claude-sonnet-4-5") topopulateBlock. This flows intofetchModelConfigByIdwhich queriesWHERE model_configs.id = ?— expecting a UUID primary key. The mismatch caused it to returnnull, andusePopulateToolsBlockreturned{ skipped: true }silently.Fix
One-line change:
replyToModelConfig?.modelId→replyToModelConfig?.idTest plan
🤖 Generated with Claude Code