diff --git a/CHANGELOG.md b/CHANGELOG.md index d9510884..65dc0aab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. - Desktop/Remote instances: a managed remote server can now also be published to the remote machine's own network, so other devices there reach it without the SSH tunnel. It requires a UI password, and stays private to the tunnel otherwise. - Desktop/Remote instances: disconnecting from a connection set to not keep the server running now actually stops that remote server. - Chat: in a chat without a project, the work status card again steps aside when the context panel is open, instead of sitting next to it. +- Settings/General: changing the default model, variant or agent no longer repoints an open chat that already carries a model you picked for it. Chats following the default still switch immediately. - **Settings:** the project selector on Providers, Agents, MCP, Commands and Skills now only changes what those pages show. It used to switch the whole app, so opening another project's configuration moved your chat, session list and file tree with it. - Settings/Providers: the provider you select no longer jumps to a different one on its own. Changing the chat's model or agent, and background provider refreshes, used to move the settings selection with them. - **Chat sessions:** start chats without choosing a project. They live in their own Chats section, rather than inheriting a project's repository and worktree context. diff --git a/packages/ui/src/components/sections/openchamber/DefaultsSettings.tsx b/packages/ui/src/components/sections/openchamber/DefaultsSettings.tsx index 9aba89c4..627964e7 100644 --- a/packages/ui/src/components/sections/openchamber/DefaultsSettings.tsx +++ b/packages/ui/src/components/sections/openchamber/DefaultsSettings.tsx @@ -17,6 +17,8 @@ import { SettingsInfoHint } from '@/components/sections/shared/SettingsInfoHint' import { updateDesktopSettings } from '@/lib/persistence'; import { useConfigStore } from '@/stores/useConfigStore'; import { useUIStore } from '@/stores/useUIStore'; +import { useSelectionStore } from '@/sync/selection-store'; +import { useSessionUIStore } from '@/sync/session-ui-store'; import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry'; import { useI18n } from '@/lib/i18n'; import { parseModelIdentifier } from '@/lib/modelIdentifier'; @@ -43,6 +45,20 @@ export const DefaultsSettings: React.FC = () => { const setSettingsDefaultModel = useConfigStore((state) => state.setSettingsDefaultModel); const setSettingsDefaultVariant = useConfigStore((state) => state.setSettingsDefaultVariant); const setSettingsDefaultAgent = useConfigStore((state) => state.setSettingsDefaultAgent); + // A default describes new sessions. Applying it to the open chat is a + // convenience, not the point, so it stops where the chat carries a choice the + // user made for it — the same pair of signals ModelControls restores from + // (`shouldPreserveManualModelOverride`). + const selectionIsManual = useConfigStore((state) => state.selectionSource === 'manual'); + const currentSessionId = useSessionUIStore((state) => state.currentSessionId); + const getSessionModelSelection = useSelectionStore((state) => state.getSessionModelSelection); + const getSessionAgentSelection = useSelectionStore((state) => state.getSessionAgentSelection); + const chatHasOwnModel = Boolean( + selectionIsManual && currentSessionId && getSessionModelSelection(currentSessionId), + ); + const chatHasOwnAgent = Boolean( + selectionIsManual && currentSessionId && getSessionAgentSelection(currentSessionId), + ); const showDeletionDialog = useUIStore((state) => state.showDeletionDialog); const setShowDeletionDialog = useUIStore((state) => state.setShowDeletionDialog); const providers = useConfigStore((state) => state.providers); @@ -148,14 +164,17 @@ export const DefaultsSettings: React.FC = () => { setDefaultModel(newValue); setDefaultVariant(undefined); setSettingsDefaultVariant(undefined); - setCurrentVariant(undefined); setSettingsDefaultModel(newValue); - if (providerId && modelId) { - const provider = providers.find((p) => p.id === providerId); - if (provider) { - setProvider(providerId); - setModel(modelId); + if (!chatHasOwnModel) { + setCurrentVariant(undefined); + + if (providerId && modelId) { + const provider = providers.find((p) => p.id === providerId); + if (provider) { + setProvider(providerId); + setModel(modelId); + } } } @@ -173,7 +192,7 @@ export const DefaultsSettings: React.FC = () => { console.warn('Failed to save default model:', error); } }, - [providers, setCurrentVariant, setModel, setProvider, setSettingsDefaultModel, setSettingsDefaultVariant] + [chatHasOwnModel, providers, setCurrentVariant, setModel, setProvider, setSettingsDefaultModel, setSettingsDefaultVariant] ); const DEFAULT_VARIANT_VALUE = '__default__'; @@ -190,7 +209,9 @@ export const DefaultsSettings: React.FC = () => { const newValue = variant === DEFAULT_VARIANT_VALUE ? undefined : variant || undefined; setDefaultVariant(newValue); setSettingsDefaultVariant(newValue); - setCurrentVariant(newValue); + if (!chatHasOwnModel) { + setCurrentVariant(newValue); + } try { await updateDesktopSettings({ defaultVariant: newValue ?? '' }); @@ -198,7 +219,7 @@ export const DefaultsSettings: React.FC = () => { console.warn('Failed to save default variant:', error); } }, - [setCurrentVariant, setSettingsDefaultVariant] + [chatHasOwnModel, setCurrentVariant, setSettingsDefaultVariant] ); const handleAgentChange = React.useCallback( @@ -207,7 +228,7 @@ export const DefaultsSettings: React.FC = () => { setDefaultAgent(newValue); setSettingsDefaultAgent(newValue); - if (agentName) { + if (agentName && !chatHasOwnAgent) { setAgent(agentName); } @@ -217,7 +238,7 @@ export const DefaultsSettings: React.FC = () => { console.warn('Failed to save default agent:', error); } }, - [setAgent, setSettingsDefaultAgent] + [chatHasOwnAgent, setAgent, setSettingsDefaultAgent] ); const handleSmallModelUseDefaultChange = React.useCallback( @@ -316,12 +337,14 @@ export const DefaultsSettings: React.FC = () => { if (!supportsVariants && defaultVariant) { setDefaultVariant(undefined); setSettingsDefaultVariant(undefined); - setCurrentVariant(undefined); + if (!chatHasOwnModel) { + setCurrentVariant(undefined); + } updateDesktopSettings({ defaultVariant: '' }).catch(() => { // best effort }); } - }, [defaultVariant, setCurrentVariant, setSettingsDefaultVariant, supportsVariants]); + }, [chatHasOwnModel, defaultVariant, setCurrentVariant, setSettingsDefaultVariant, supportsVariants]); if (isLoading) { return null;