diff --git a/src/core/config/ProviderSettingsManager.ts b/src/core/config/ProviderSettingsManager.ts index 9729219a2de..a6153e636c0 100644 --- a/src/core/config/ProviderSettingsManager.ts +++ b/src/core/config/ProviderSettingsManager.ts @@ -40,7 +40,7 @@ export class ProviderSettingsManager { this.initialize().catch(console.error) } - private generateId() { + public generateId() { return Math.random().toString(36).substring(2, 15) } diff --git a/src/exports/api.ts b/src/exports/api.ts index 609eda3b6d4..b1061cb56ae 100644 --- a/src/exports/api.ts +++ b/src/exports/api.ts @@ -163,6 +163,82 @@ export class API extends EventEmitter implements RooCodeAPI { await this.sidebarProvider.postStateToWebview() } + public async createProfile(name: string): Promise { + // Input validation + if (!name || !name.trim()) { + throw new Error("Profile name cannot be empty") + } + + const currentSettings = this.getConfiguration() + const profiles = currentSettings.listApiConfigMeta || [] + + if (profiles.some((profile) => profile.name === name)) { + throw new Error(`A profile with the name "${name}" already exists`) + } + + // Generate unique ID and create profile + const id = this.sidebarProvider.providerSettingsManager.generateId() + const newProfile = { + id, + name: name.trim(), + apiProvider: "openai" as const, // Type assertion for better type safety + } + + // Update configuration with new profile + await this.setConfiguration({ + ...currentSettings, + listApiConfigMeta: [...profiles, newProfile], + }) + return id + } + + public getProfiles(): string[] { + const profiles = this.getConfiguration().listApiConfigMeta || [] + return profiles.map((profile) => profile.name) + } + + public async setActiveProfile(name: string): Promise { + const currentSettings = this.getConfiguration() + const profiles = currentSettings.listApiConfigMeta || [] + + const profile = profiles.find((p) => p.name === name) + if (!profile) { + throw new Error(`Profile with name "${name}" does not exist`) + } + + await this.setConfiguration({ + ...currentSettings, + currentApiConfigName: profile.name, + }) + } + + public getActiveProfile(): string | undefined { + return this.getConfiguration().currentApiConfigName + } + + public async deleteProfile(name: string): Promise { + const currentSettings = this.getConfiguration() + const profiles = currentSettings.listApiConfigMeta || [] + const targetIndex = profiles.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) + + // If we're deleting the active profile, clear the currentApiConfigName + const newSettings: RooCodeSettings = { + ...currentSettings, + listApiConfigMeta: profiles, + currentApiConfigName: + currentSettings.currentApiConfigName === profileToDelete.name + ? undefined + : currentSettings.currentApiConfigName, + } + await this.setConfiguration(newSettings) + } + public isReady() { return this.sidebarProvider.viewLaunched } diff --git a/src/exports/interface.ts b/src/exports/interface.ts index 6e0eb8adec4..f30cc3a09e9 100644 --- a/src/exports/interface.ts +++ b/src/exports/interface.ts @@ -72,6 +72,39 @@ export interface RooCodeAPI extends EventEmitter { */ setConfiguration(values: RooCodeSettings): Promise + /** + * Creates a new API configuration profile + * @param name The name of the profile + * @returns The ID of the created profile + */ + createProfile(name: string): Promise + + /** + * Returns a list of all configured profile names + * @returns Array of profile names + */ + getProfiles(): string[] + + /** + * Changes the active API configuration profile + * @param name The name of the profile to activate + * @throws Error if the profile does not exist + */ + setActiveProfile(name: string): Promise + + /** + * Returns the name of the currently active profile + * @returns The profile name, or undefined if no profile is active + */ + getActiveProfile(): string | undefined + + /** + * Deletes a profile by name + * @param name The name of the profile to delete + * @throws Error if the profile does not exist + */ + deleteProfile(name: string): Promise + /** * Returns true if the API is ready to use. */ diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts index c75db2ab2fc..238dff137c1 100644 --- a/src/exports/roo-code.d.ts +++ b/src/exports/roo-code.d.ts @@ -572,6 +572,34 @@ interface RooCodeAPI extends EventEmitter { * @param values An object containing key-value pairs to set. */ setConfiguration(values: RooCodeSettings): Promise + /** + * Creates a new API configuration profile + * @param name The name of the profile + * @returns The ID of the created profile + */ + createProfile(name: string): Promise + /** + * Returns a list of all configured profile names + * @returns Array of profile names + */ + getProfiles(): string[] + /** + * Changes the active API configuration profile + * @param name The name of the profile to activate + * @throws Error if the profile does not exist + */ + setActiveProfile(name: string): Promise + /** + * Returns the name of the currently active profile + * @returns The profile name, or undefined if no profile is active + */ + getActiveProfile(): string | undefined + /** + * Deletes a profile by name + * @param name The name of the profile to delete + * @throws Error if the profile does not exist + */ + deleteProfile(name: string): Promise /** * Returns true if the API is ready to use. */