Просмотр исходного кода

Preserve existing provider profiles when importing (#2052)

Chris Estreich 9 месяцев назад
Родитель
Сommit
23d1bbfd1a

+ 5 - 0
.changeset/honest-walls-search.md

@@ -0,0 +1,5 @@
+---
+"roo-cline": patch
+---
+
+Preserve existing provider profiles when importing

+ 43 - 4
src/core/config/__tests__/importExport.test.ts

@@ -2,7 +2,6 @@
 
 import fs from "fs/promises"
 import * as path from "path"
-import os from "os"
 
 import * as vscode from "vscode"
 
@@ -37,6 +36,7 @@ jest.mock("os", () => ({
 describe("importExport", () => {
 	let mockProviderSettingsManager: jest.Mocked<ProviderSettingsManager>
 	let mockContextProxy: jest.Mocked<ContextProxy>
+	let mockExtensionContext: jest.Mocked<vscode.ExtensionContext>
 
 	beforeEach(() => {
 		// Reset all mocks
@@ -55,6 +55,15 @@ describe("importExport", () => {
 			setValue: jest.fn(),
 			export: jest.fn().mockImplementation(() => Promise.resolve({})),
 		} as unknown as jest.Mocked<ContextProxy>
+
+		const map = new Map<string, string>()
+
+		mockExtensionContext = {
+			secrets: {
+				get: jest.fn().mockImplementation((key: string) => map.get(key)),
+				store: jest.fn().mockImplementation((key: string, value: string) => map.set(key, value)),
+			},
+		} as unknown as jest.Mocked<vscode.ExtensionContext>
 	})
 
 	describe("importSettings", () => {
@@ -161,9 +170,7 @@ describe("importExport", () => {
 
 			// Invalid content (missing required fields)
 			const mockInvalidContent = JSON.stringify({
-				providerProfiles: {
-					apiConfigs: {},
-				},
+				providerProfiles: { apiConfigs: {} },
 				globalSettings: {},
 			})
 
@@ -219,6 +226,38 @@ describe("importExport", () => {
 			expect(mockProviderSettingsManager.import).not.toHaveBeenCalled()
 			expect(mockContextProxy.setValues).not.toHaveBeenCalled()
 		})
+
+		it("should not clobber existing api configs", async () => {
+			const providerSettingsManager = new ProviderSettingsManager(mockExtensionContext)
+			await providerSettingsManager.saveConfig("openai", { apiProvider: "openai", id: "openai" })
+
+			const configs = await providerSettingsManager.listConfig()
+			expect(configs[0].name).toBe("default")
+			expect(configs[1].name).toBe("openai")
+			;(vscode.window.showOpenDialog as jest.Mock).mockResolvedValue([{ fsPath: "/mock/path/settings.json" }])
+
+			const mockFileContent = JSON.stringify({
+				globalSettings: { mode: "code" },
+				providerProfiles: {
+					currentApiConfigName: "anthropic",
+					apiConfigs: { default: { apiProvider: "anthropic" as const, id: "anthropic" } },
+				},
+			})
+
+			;(fs.readFile as jest.Mock).mockResolvedValue(mockFileContent)
+
+			mockContextProxy.export.mockResolvedValue({ mode: "code" })
+
+			const result = await importSettings({
+				providerSettingsManager,
+				contextProxy: mockContextProxy,
+			})
+
+			expect(result.success).toBe(true)
+			expect(result.providerProfiles?.apiConfigs["openai"]).toBeDefined()
+			expect(result.providerProfiles?.apiConfigs["default"]).toBeDefined()
+			expect(result.providerProfiles?.apiConfigs["default"].apiProvider).toBe("anthropic")
+		})
 	})
 
 	describe("exportSettings", () => {

+ 16 - 4
src/core/config/importExport.ts

@@ -30,15 +30,27 @@ export const importSettings = async ({ providerSettingsManager, contextProxy }:
 	})
 
 	try {
-		const { providerProfiles, globalSettings } = schema.parse(
+		const previousProviderProfiles = await providerSettingsManager.export()
+
+		const { providerProfiles: newProviderProfiles, globalSettings } = schema.parse(
 			JSON.parse(await fs.readFile(uris[0].fsPath, "utf-8")),
 		)
 
-		const previousProviderProfiles = await providerSettingsManager.export()
+		const providerProfiles = {
+			currentApiConfigName: newProviderProfiles.currentApiConfigName,
+			apiConfigs: {
+				...previousProviderProfiles.apiConfigs,
+				...newProviderProfiles.apiConfigs,
+			},
+			modeApiConfigs: {
+				...previousProviderProfiles.modeApiConfigs,
+				...newProviderProfiles.modeApiConfigs,
+			},
+		}
 
-		await contextProxy.setValues(globalSettings)
-		await providerSettingsManager.import({ ...previousProviderProfiles, ...providerProfiles })
+		await providerSettingsManager.import(newProviderProfiles)
 
+		await contextProxy.setValues(globalSettings)
 		contextProxy.setValue("currentApiConfigName", providerProfiles.currentApiConfigName)
 		contextProxy.setValue("listApiConfigMeta", await providerSettingsManager.listConfig())