diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 61a54f8ead..0213c2f2af 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1322,16 +1322,10 @@ export class ClineProvider // The task will continue with the current/default configuration. } } else { - // If no saved config for this mode, save current config as default. - const currentApiConfigNameAfter = this.getGlobalState("currentApiConfigName") - - if (currentApiConfigNameAfter) { - const config = listApiConfig.find((c) => c.name === currentApiConfigNameAfter) - - if (config?.id) { - await this.providerSettingsManager.setModeConfig(newMode, config.id) - } - } + // No saved config for this mode — leave the current config active + // without persisting it as the mode's default. This prevents config + // "bleed" where switching modes silently inherits and saves the + // previous mode's API configuration. } await this.postStateToWebview() diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index edb7278081..0429dcd8a2 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -866,7 +866,7 @@ describe("ClineProvider", () => { expect(mockContext.globalState.update).toHaveBeenCalledWith("currentApiConfigName", "test-config") }) - it("saves current config when switching to mode without config", async () => { + it("does not auto-save current config when switching to mode without config", async () => { await provider.resolveWebviewView(mockWebviewView) const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as any).mock.calls[0][0] @@ -883,8 +883,8 @@ describe("ClineProvider", () => { // Switch to architect mode await messageHandler({ type: "mode", text: "architect" }) - // Should save current config as default for architect mode - expect(provider.providerSettingsManager.setModeConfig).toHaveBeenCalledWith("architect", "current-id") + // Should NOT auto-save current config as default for the new mode + expect(provider.providerSettingsManager.setModeConfig).not.toHaveBeenCalled() }) it("saves config as default for current mode when loading config", async () => { @@ -1459,7 +1459,7 @@ describe("ClineProvider", () => { expect(mockPostMessage).toHaveBeenCalledWith(expect.objectContaining({ type: "state" })) }) - test("saves current config when switching to mode without config", async () => { + test("does not auto-save current config when switching to mode without config", async () => { ;(provider as any).providerSettingsManager = { getModeConfigId: vi.fn().mockResolvedValue(undefined), listConfig: vi @@ -1482,8 +1482,8 @@ describe("ClineProvider", () => { // Verify mode was updated expect(mockContext.globalState.update).toHaveBeenCalledWith("mode", "architect") - // Verify current config was saved as default for new mode - expect(provider.providerSettingsManager.setModeConfig).toHaveBeenCalledWith("architect", "current-id") + // Should NOT auto-save current config as default for the new mode + expect(provider.providerSettingsManager.setModeConfig).not.toHaveBeenCalled() // Verify state was posted to webview expect(mockPostMessage).toHaveBeenCalledWith(expect.objectContaining({ type: "state" })) diff --git a/webview-ui/src/components/modes/ModesView.tsx b/webview-ui/src/components/modes/ModesView.tsx index 48a20ab4b1..606c3688ff 100644 --- a/webview-ui/src/components/modes/ModesView.tsx +++ b/webview-ui/src/components/modes/ModesView.tsx @@ -63,7 +63,11 @@ function getGroupName(group: GroupEntry): ToolGroup { return Array.isArray(group) ? group[0] : group } -const ModesView = () => { +interface ModesViewProps { + checkUnsaveChanges?: (then: () => void) => void +} + +const ModesView = ({ checkUnsaveChanges }: ModesViewProps) => { const { t } = useAppTranslation() const { @@ -895,10 +899,16 @@ const ModesView = () => {