diff --git a/.gitignore b/.gitignore index 1277732969..3a541f1b09 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ out out-* node_modules coverage/ +mock/ .DS_Store diff --git a/git b/git deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/core/config/ProviderSettingsManager.ts b/src/core/config/ProviderSettingsManager.ts index d0cc1a90da..77687a0d36 100644 --- a/src/core/config/ProviderSettingsManager.ts +++ b/src/core/config/ProviderSettingsManager.ts @@ -265,52 +265,60 @@ export class ProviderSettingsManager { } } - /** - * Load a config by name and set it as the current config. - */ - public async loadConfig(name: string) { + public async getProfile(params: { name: string } | { id: string }) { try { return await this.lock(async () => { const providerProfiles = await this.load() - const providerSettings = providerProfiles.apiConfigs[name] + let name: string + let providerSettings: ProviderSettingsWithId - if (!providerSettings) { - throw new Error(`Config '${name}' not found`) + if ("name" in params) { + name = params.name + + if (!providerProfiles.apiConfigs[name]) { + throw new Error(`Config with name '${name}' not found`) + } + + providerSettings = providerProfiles.apiConfigs[name] + } else { + const id = params.id + + const entry = Object.entries(providerProfiles.apiConfigs).find( + ([_, apiConfig]) => apiConfig.id === id, + ) + + if (!entry) { + throw new Error(`Config with ID '${id}' not found`) + } + + name = entry[0] + providerSettings = entry[1] } - providerProfiles.currentApiConfigName = name - await this.store(providerProfiles) - - return providerSettings + return { name, ...providerSettings } }) } catch (error) { - throw new Error(`Failed to load config: ${error}`) + throw new Error(`Failed to get profile: ${error instanceof Error ? error.message : error}`) } } /** - * Load a config by ID and set it as the current config. + * Activate a profile by name or ID. */ - public async loadConfigById(id: string) { + public async activateProfile( + params: { name: string } | { id: string }, + ): Promise { + const { name, ...providerSettings } = await this.getProfile(params) + try { return await this.lock(async () => { const providerProfiles = await this.load() - const providerSettings = Object.entries(providerProfiles.apiConfigs).find( - ([_, apiConfig]) => apiConfig.id === id, - ) - - if (!providerSettings) { - throw new Error(`Config with ID '${id}' not found`) - } - - const [name, apiConfig] = providerSettings providerProfiles.currentApiConfigName = name await this.store(providerProfiles) - - return { config: apiConfig, name } + return { name, ...providerSettings } }) } catch (error) { - throw new Error(`Failed to load config by ID: ${error}`) + throw new Error(`Failed to activate profile: ${error instanceof Error ? error.message : error}`) } } diff --git a/src/core/config/__tests__/ProviderSettingsManager.test.ts b/src/core/config/__tests__/ProviderSettingsManager.test.ts index 9399fc45c7..573c5453a4 100644 --- a/src/core/config/__tests__/ProviderSettingsManager.test.ts +++ b/src/core/config/__tests__/ProviderSettingsManager.test.ts @@ -438,17 +438,15 @@ describe("ProviderSettingsManager", () => { mockGlobalState.get.mockResolvedValue(42) mockSecrets.get.mockResolvedValue(JSON.stringify(existingConfig)) - const config = await providerSettingsManager.loadConfig("test") + const { name, ...providerSettings } = await providerSettingsManager.activateProfile({ name: "test" }) - expect(config).toEqual({ - apiProvider: "anthropic", - apiKey: "test-key", - id: "test-id", - }) + expect(name).toBe("test") + expect(providerSettings).toEqual({ apiProvider: "anthropic", apiKey: "test-key", id: "test-id" }) - // Get the stored config to check the structure + // Get the stored config to check the structure. const storedConfig = JSON.parse(mockSecrets.store.mock.calls[1][1]) expect(storedConfig.currentApiConfigName).toBe("test") + expect(storedConfig.apiConfigs.test).toEqual({ apiProvider: "anthropic", apiKey: "test-key", @@ -460,17 +458,12 @@ describe("ProviderSettingsManager", () => { mockSecrets.get.mockResolvedValue( JSON.stringify({ currentApiConfigName: "default", - apiConfigs: { - default: { - config: {}, - id: "default", - }, - }, + apiConfigs: { default: { config: {}, id: "default" } }, }), ) - await expect(providerSettingsManager.loadConfig("nonexistent")).rejects.toThrow( - "Config 'nonexistent' not found", + await expect(providerSettingsManager.activateProfile({ name: "nonexistent" })).rejects.toThrow( + "Config with name 'nonexistent' not found", ) }) @@ -478,20 +471,13 @@ describe("ProviderSettingsManager", () => { mockSecrets.get.mockResolvedValue( JSON.stringify({ currentApiConfigName: "default", - apiConfigs: { - test: { - config: { - apiProvider: "anthropic", - }, - id: "test-id", - }, - }, + apiConfigs: { test: { config: { apiProvider: "anthropic" }, id: "test-id" } }, }), ) mockSecrets.store.mockRejectedValueOnce(new Error("Storage failed")) - await expect(providerSettingsManager.loadConfig("test")).rejects.toThrow( - "Failed to load config: Error: Failed to write provider profiles to secrets: Error: Storage failed", + await expect(providerSettingsManager.activateProfile({ name: "test" })).rejects.toThrow( + "Failed to activate profile: Failed to write provider profiles to secrets: Error: Storage failed", ) }) @@ -541,12 +527,7 @@ describe("ProviderSettingsManager", () => { mockSecrets.get.mockResolvedValue( JSON.stringify({ currentApiConfigName: "test", - apiConfigs: { - test: { - apiProvider: "anthropic", - id: "test-id", - }, - }, + apiConfigs: { test: { apiProvider: "anthropic", id: "test-id" } }, }), ) @@ -561,18 +542,8 @@ describe("ProviderSettingsManager", () => { it("should return true for existing config", async () => { const existingConfig: ProviderProfiles = { currentApiConfigName: "default", - apiConfigs: { - default: { - id: "default", - }, - test: { - apiProvider: "anthropic", - id: "test-id", - }, - }, - migrations: { - rateLimitSecondsMigrated: false, - }, + apiConfigs: { default: { id: "default" }, test: { apiProvider: "anthropic", id: "test-id" } }, + migrations: { rateLimitSecondsMigrated: false }, } mockSecrets.get.mockResolvedValue(JSON.stringify(existingConfig)) @@ -583,10 +554,7 @@ describe("ProviderSettingsManager", () => { it("should return false for non-existent config", async () => { mockSecrets.get.mockResolvedValue( - JSON.stringify({ - currentApiConfigName: "default", - apiConfigs: { default: {} }, - }), + JSON.stringify({ currentApiConfigName: "default", apiConfigs: { default: {} } }), ) const hasConfig = await providerSettingsManager.hasConfig("nonexistent") diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 87598bd45d..f43f85877d 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -762,7 +762,6 @@ export class ClineProvider extends EventEmitter implements * @param newMode The mode to switch to */ public async handleModeSwitch(newMode: Mode) { - // Capture mode switch telemetry event const cline = this.getCurrentCline() if (cline) { @@ -779,24 +778,19 @@ export class ClineProvider extends EventEmitter implements // Update listApiConfigMeta first to ensure UI has latest data await this.updateGlobalState("listApiConfigMeta", listApiConfig) - // If this mode has a saved config, use it + // If this mode has a saved config, use it. if (savedConfigId) { - const config = listApiConfig?.find((c) => c.id === savedConfigId) + const profile = listApiConfig.find(({ id }) => id === savedConfigId) - if (config?.name) { - const apiConfig = await this.providerSettingsManager.loadConfig(config.name) - - await Promise.all([ - this.updateGlobalState("currentApiConfigName", config.name), - this.updateApiConfiguration(apiConfig), - ]) + if (profile?.name) { + await this.activateProviderProfile({ name: profile.name }) } } else { - // If no saved config for this mode, save current config as default + // If no saved config for this mode, save current config as default. const currentApiConfigName = this.getGlobalState("currentApiConfigName") if (currentApiConfigName) { - const config = listApiConfig?.find((c) => c.name === currentApiConfigName) + const config = listApiConfig.find((c) => c.name === currentApiConfigName) if (config?.id) { await this.providerSettingsManager.setModeConfig(newMode, config.id) @@ -807,6 +801,18 @@ export class ClineProvider extends EventEmitter implements await this.postStateToWebview() } + async activateProviderProfile(args: { name: string } | { id: string }) { + const { name, ...providerSettings } = await this.providerSettingsManager.activateProfile(args) + + await Promise.all([ + this.contextProxy.setValue("listApiConfigMeta", await this.providerSettingsManager.listConfig()), + this.contextProxy.setValue("currentApiConfigName", name), + ]) + + await this.updateApiConfiguration(providerSettings) + await this.postStateToWebview() + } + async updateApiConfiguration(providerSettings: ProviderSettings) { // Update mode's default config. const { mode } = await this.getState() diff --git a/src/core/webview/__tests__/ClineProvider.test.ts b/src/core/webview/__tests__/ClineProvider.test.ts index 1897a7e7e8..67cb181b94 100644 --- a/src/core/webview/__tests__/ClineProvider.test.ts +++ b/src/core/webview/__tests__/ClineProvider.test.ts @@ -5,7 +5,7 @@ import * as vscode from "vscode" import axios from "axios" import { ClineProvider } from "../ClineProvider" -import { ClineMessage, ExtensionMessage, ExtensionState } from "../../../shared/ExtensionMessage" +import { ApiConfigMeta, ClineMessage, ExtensionMessage, ExtensionState } from "../../../shared/ExtensionMessage" import { setSoundEnabled } from "../../../utils/sound" import { setTtsEnabled } from "../../../utils/tts" import { defaultModeSlug } from "../../../shared/modes" @@ -227,12 +227,6 @@ jest.mock("../../../integrations/misc/extract-text", () => ({ }), })) -// Spy on console.error and console.log to suppress expected messages -beforeAll(() => { - jest.spyOn(console, "error").mockImplementation(() => {}) - jest.spyOn(console, "log").mockImplementation(() => {}) -}) - afterAll(() => { jest.restoreAllMocks() }) @@ -596,14 +590,16 @@ describe("ClineProvider", () => { expect(state.alwaysApproveResubmit).toBe(false) }) - test("loads saved API config when switching modes", async () => { + it("loads saved API config when switching modes", async () => { await provider.resolveWebviewView(mockWebviewView) const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as jest.Mock).mock.calls[0][0] + const profile: ApiConfigMeta = { name: "test-config", id: "test-id", apiProvider: "anthropic" } + ;(provider as any).providerSettingsManager = { getModeConfigId: jest.fn().mockResolvedValue("test-id"), - listConfig: jest.fn().mockResolvedValue([{ name: "test-config", id: "test-id", apiProvider: "anthropic" }]), - loadConfig: jest.fn().mockResolvedValue({ apiProvider: "anthropic" }), + listConfig: jest.fn().mockResolvedValue([profile]), + activateProfile: jest.fn().mockResolvedValue(profile), setModeConfig: jest.fn(), } as any @@ -612,7 +608,7 @@ describe("ClineProvider", () => { // Should load the saved config for architect mode expect(provider.providerSettingsManager.getModeConfigId).toHaveBeenCalledWith("architect") - expect(provider.providerSettingsManager.loadConfig).toHaveBeenCalledWith("test-config") + expect(provider.providerSettingsManager.activateProfile).toHaveBeenCalledWith({ name: "test-config" }) expect(mockContext.globalState.update).toHaveBeenCalledWith("currentApiConfigName", "test-config") }) @@ -642,8 +638,7 @@ describe("ClineProvider", () => { const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as jest.Mock).mock.calls[0][0] ;(provider as any).providerSettingsManager = { - loadConfig: jest.fn().mockResolvedValue({ apiProvider: "anthropic", id: "new-id" }), - loadConfigById: jest + activateProfile: jest .fn() .mockResolvedValue({ config: { apiProvider: "anthropic", id: "new-id" }, name: "new-config" }), listConfig: jest.fn().mockResolvedValue([{ name: "new-config", id: "new-id", apiProvider: "anthropic" }]), @@ -666,7 +661,7 @@ describe("ClineProvider", () => { const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as jest.Mock).mock.calls[0][0] ;(provider as any).providerSettingsManager = { - loadConfigById: jest.fn().mockResolvedValue({ + activateProfile: jest.fn().mockResolvedValue({ config: { apiProvider: "anthropic", id: "config-id-123" }, name: "config-by-id", }), @@ -686,8 +681,8 @@ describe("ClineProvider", () => { // Should save new config as default for architect mode expect(provider.providerSettingsManager.setModeConfig).toHaveBeenCalledWith("architect", "config-id-123") - // Ensure the loadConfigById method was called with the correct ID - expect(provider.providerSettingsManager.loadConfigById).toHaveBeenCalledWith("config-id-123") + // Ensure the `activateProfile` method was called with the correct ID + expect(provider.providerSettingsManager.activateProfile).toHaveBeenCalledWith({ id: "config-id-123" }) }) test("handles browserToolEnabled setting", async () => { @@ -1542,13 +1537,13 @@ describe("ClineProvider", () => { await provider.resolveWebviewView(mockWebviewView) }) - test("loads saved API config when switching modes", async () => { + it("loads saved API config when switching modes", async () => { + const profile: ApiConfigMeta = { name: "saved-config", id: "saved-config-id", apiProvider: "anthropic" } + ;(provider as any).providerSettingsManager = { getModeConfigId: jest.fn().mockResolvedValue("saved-config-id"), - listConfig: jest - .fn() - .mockResolvedValue([{ name: "saved-config", id: "saved-config-id", apiProvider: "anthropic" }]), - loadConfig: jest.fn().mockResolvedValue({ apiProvider: "anthropic" }), + listConfig: jest.fn().mockResolvedValue([profile]), + activateProfile: jest.fn().mockResolvedValue(profile), setModeConfig: jest.fn(), } as any @@ -1560,7 +1555,7 @@ describe("ClineProvider", () => { // Verify saved config was loaded expect(provider.providerSettingsManager.getModeConfigId).toHaveBeenCalledWith("architect") - expect(provider.providerSettingsManager.loadConfig).toHaveBeenCalledWith("saved-config") + expect(provider.providerSettingsManager.activateProfile).toHaveBeenCalledWith({ name: "saved-config" }) expect(mockContext.globalState.update).toHaveBeenCalledWith("currentApiConfigName", "saved-config") // Verify state was posted to webview diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 6560a5cac6..2f1c888a57 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -4,9 +4,9 @@ import pWaitFor from "p-wait-for" import * as vscode from "vscode" import { ClineProvider } from "./ClineProvider" -import { Language, ApiConfigMeta } from "../../schemas" +import { Language, ApiConfigMeta, ProviderSettings } from "../../schemas" import { changeLanguage, t } from "../../i18n" -import { ApiConfiguration, RouterName, toRouterName } from "../../shared/api" +import { RouterName, toRouterName } from "../../shared/api" import { supportPrompt } from "../../shared/support-prompt" import { checkoutDiffPayloadSchema, checkoutRestorePayloadSchema, WebviewMessage } from "../../shared/WebviewMessage" @@ -89,19 +89,12 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We if (currentConfigName) { if (!(await provider.providerSettingsManager.hasConfig(currentConfigName))) { - // current config name not valid, get first config in list - await updateGlobalState("currentApiConfigName", listApiConfig?.[0]?.name) - if (listApiConfig?.[0]?.name) { - const apiConfig = await provider.providerSettingsManager.loadConfig( - listApiConfig?.[0]?.name, - ) + // Current config name not valid, get first config in list. + const name = listApiConfig[0]?.name + await updateGlobalState("currentApiConfigName", name) - await Promise.all([ - updateGlobalState("listApiConfigMeta", listApiConfig), - provider.postMessageToWebview({ type: "listApiConfig", listApiConfig }), - provider.updateApiConfiguration(apiConfig), - ]) - await provider.postStateToWebview() + if (name) { + await provider.activateProviderProfile({ name }) return } } @@ -939,45 +932,39 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We const { apiConfiguration, customSupportPrompts, listApiConfigMeta, enhancementApiConfigId } = await provider.getState() - // Try to get enhancement config first, fall back to current config - let configToUse: ApiConfiguration = apiConfiguration - if (enhancementApiConfigId) { - const config = listApiConfigMeta?.find((c: ApiConfigMeta) => c.id === enhancementApiConfigId) - if (config?.name) { - const loadedConfig = await provider.providerSettingsManager.loadConfig(config.name) - if (loadedConfig.apiProvider) { - configToUse = loadedConfig - } + // Try to get enhancement config first, fall back to current config. + let configToUse: ProviderSettings = apiConfiguration + + if ( + enhancementApiConfigId && + !!listApiConfigMeta.find((c: ApiConfigMeta) => c.id === enhancementApiConfigId) + ) { + const { name: _, ...providerSettings } = await provider.providerSettingsManager.getProfile({ + id: enhancementApiConfigId, + }) + + if (providerSettings.apiProvider) { + configToUse = providerSettings } } const enhancedPrompt = await singleCompletionHandler( configToUse, - supportPrompt.create( - "ENHANCE", - { - userInput: message.text, - }, - customSupportPrompts, - ), + supportPrompt.create("ENHANCE", { userInput: message.text }, customSupportPrompts), ) - // Capture telemetry for prompt enhancement + // Capture telemetry for prompt enhancement. const currentCline = provider.getCurrentCline() telemetryService.capturePromptEnhanced(currentCline?.taskId) - await provider.postMessageToWebview({ - type: "enhancedPrompt", - text: enhancedPrompt, - }) + await provider.postMessageToWebview({ type: "enhancedPrompt", text: enhancedPrompt }) } catch (error) { provider.log( `Error enhancing prompt: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`, ) + vscode.window.showErrorMessage(t("common:errors.enhance_prompt")) - await provider.postMessageToWebview({ - type: "enhancedPrompt", - }) + await provider.postMessageToWebview({ type: "enhancedPrompt" }) } } break @@ -1096,30 +1083,23 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We break } - // Load the old configuration to get its ID - const oldConfig = await provider.providerSettingsManager.loadConfig(oldName) + // Load the old configuration to get its ID. + const { id } = await provider.providerSettingsManager.getProfile({ name: oldName }) - // Create a new configuration with the same ID - const newConfig = { - ...message.apiConfiguration, - id: oldConfig.id, // Preserve the ID - } + // Create a new configuration with the new name and old ID. + await provider.providerSettingsManager.saveConfig(newName, { ...message.apiConfiguration, id }) - // Save with the new name but same ID - await provider.providerSettingsManager.saveConfig(newName, newConfig) + // Delete the old configuration. await provider.providerSettingsManager.deleteConfig(oldName) - const listApiConfig = await provider.providerSettingsManager.listConfig() - - // Update listApiConfigMeta first to ensure UI has latest data - await updateGlobalState("listApiConfigMeta", listApiConfig) - await updateGlobalState("currentApiConfigName", newName) - - await provider.postStateToWebview() + // Re-activate to update the global settings related to the + // currently activated provider profile. + await provider.activateProviderProfile({ name: newName }) } catch (error) { provider.log( `Error rename api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`, ) + vscode.window.showErrorMessage(t("common:errors.rename_api_config")) } } @@ -1127,16 +1107,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We case "loadApiConfiguration": if (message.text) { try { - const apiConfig = await provider.providerSettingsManager.loadConfig(message.text) - const listApiConfig = await provider.providerSettingsManager.listConfig() - - await Promise.all([ - updateGlobalState("listApiConfigMeta", listApiConfig), - updateGlobalState("currentApiConfigName", message.text), - provider.updateApiConfiguration(apiConfig), - ]) - - await provider.postStateToWebview() + await provider.activateProviderProfile({ name: message.text }) } catch (error) { provider.log( `Error load api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`, @@ -1148,18 +1119,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We case "loadApiConfigurationById": if (message.text) { try { - const { config: apiConfig, name } = await provider.providerSettingsManager.loadConfigById( - message.text, - ) - const listApiConfig = await provider.providerSettingsManager.listConfig() - - await Promise.all([ - updateGlobalState("listApiConfigMeta", listApiConfig), - updateGlobalState("currentApiConfigName", name), - provider.updateApiConfiguration(apiConfig), - ]) - - await provider.postStateToWebview() + await provider.activateProviderProfile({ id: message.text }) } catch (error) { provider.log( `Error load api configuration by ID: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`, @@ -1180,29 +1140,25 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We break } + const oldName = message.text + + const newName = (await provider.providerSettingsManager.listConfig()).filter( + (c) => c.name !== oldName, + )[0]?.name + + if (!newName) { + vscode.window.showErrorMessage(t("common:errors.delete_api_config")) + return + } + try { - await provider.providerSettingsManager.deleteConfig(message.text) - const listApiConfig = await provider.providerSettingsManager.listConfig() - - // Update listApiConfigMeta first to ensure UI has latest data - await updateGlobalState("listApiConfigMeta", listApiConfig) - - // If this was the current config, switch to first available - const currentApiConfigName = getGlobalState("currentApiConfigName") - - if (message.text === currentApiConfigName && listApiConfig?.[0]?.name) { - const apiConfig = await provider.providerSettingsManager.loadConfig(listApiConfig[0].name) - await Promise.all([ - updateGlobalState("currentApiConfigName", listApiConfig[0].name), - provider.updateApiConfiguration(apiConfig), - ]) - } - - await provider.postStateToWebview() + await provider.providerSettingsManager.deleteConfig(oldName) + await provider.activateProviderProfile({ name: newName }) } catch (error) { provider.log( `Error delete api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`, ) + vscode.window.showErrorMessage(t("common:errors.delete_api_config")) } } diff --git a/src/exports/api.ts b/src/exports/api.ts index 0d70d7dc04..1a9842ef98 100644 --- a/src/exports/api.ts +++ b/src/exports/api.ts @@ -217,21 +217,24 @@ export class API extends EventEmitter implements RooCodeAPI { return id } + private getProfilesMeta() { + return this.getConfiguration().listApiConfigMeta || [] + } + public getProfiles() { - return (this.getConfiguration().listApiConfigMeta || []).map((profile) => profile.name) + return this.getProfilesMeta().map((profile) => profile.name) + } + + public hasProfile(name: string): boolean { + return !!(this.getConfiguration().listApiConfigMeta || []).find((profile) => profile.name === name) } public async setActiveProfile(name: string) { - const currentSettings = this.getConfiguration() - const profiles = currentSettings.listApiConfigMeta || [] - - const profile = profiles.find((p) => p.name === name) - - if (!profile) { + if (!this.hasProfile(name)) { throw new Error(`Profile with name "${name}" does not exist`) } - await this.setConfiguration({ ...currentSettings, currentApiConfigName: profile.name }) + await this.sidebarProvider.activateProviderProfile({ name }) } public getActiveProfile() { @@ -240,27 +243,23 @@ export class API extends EventEmitter implements RooCodeAPI { public async deleteProfile(name: string) { const currentSettings = this.getConfiguration() - const profiles = currentSettings.listApiConfigMeta || [] - const targetIndex = profiles.findIndex((p) => p.name === name) + const listApiConfigMeta = this.getProfilesMeta() + const targetIndex = listApiConfigMeta.findIndex((p) => p.name === name) if (targetIndex === -1) { throw new Error(`Profile with name "${name}" does not exist`) } - const profileToDelete = profiles[targetIndex] - profiles.splice(targetIndex, 1) + const profileToDelete = listApiConfigMeta[targetIndex] + listApiConfigMeta.splice(targetIndex, 1) // If we're deleting the active profile, clear the currentApiConfigName. - const newSettings: RooCodeSettings = { - ...currentSettings, - listApiConfigMeta: profiles, - currentApiConfigName: - currentSettings.currentApiConfigName === profileToDelete.name - ? undefined - : currentSettings.currentApiConfigName, - } + const currentApiConfigName = + currentSettings.currentApiConfigName === profileToDelete.name + ? undefined + : currentSettings.currentApiConfigName - await this.setConfiguration(newSettings) + await this.setConfiguration({ ...currentSettings, listApiConfigMeta, currentApiConfigName }) } public isReady() {