mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Simplify the process of setting the "active" provider profile (#3366)
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
parent
791f4e2742
commit
a12fb2a736
8 changed files with 155 additions and 222 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,6 +4,7 @@ out
|
|||
out-*
|
||||
node_modules
|
||||
coverage/
|
||||
mock/
|
||||
|
||||
.DS_Store
|
||||
|
||||
|
|
|
|||
0
git
0
git
|
|
@ -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<ProviderSettingsWithId & { name: string }> {
|
||||
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}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -762,7 +762,6 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> 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<ClineProviderEvents> 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<ClineProviderEvents> 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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,21 +217,24 @@ export class API extends EventEmitter<RooCodeEvents> 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<RooCodeEvents> 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() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue