Preserve existing provider profiles when importing (#2052)

This commit is contained in:
Chris Estreich 2025-03-30 20:38:26 -07:00 committed by GitHub
parent 48148e38d9
commit 23d1bbfd1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 64 additions and 8 deletions

View file

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

View file

@ -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", () => {

View file

@ -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 providerSettingsManager.import(newProviderProfiles)
await contextProxy.setValues(globalSettings)
await providerSettingsManager.import({ ...previousProviderProfiles, ...providerProfiles })
contextProxy.setValue("currentApiConfigName", providerProfiles.currentApiConfigName)
contextProxy.setValue("listApiConfigMeta", await providerSettingsManager.listConfig())