Browse Source

Export more types to the external API (#3383)

Chris Estreich 8 months ago
parent
commit
302dc2dcba
6 changed files with 492 additions and 403 deletions
  1. 5 2
      src/core/config/ProviderSettingsManager.ts
  2. 88 84
      src/exports/api.ts
  3. 37 20
      src/exports/interface.ts
  4. 187 155
      src/exports/roo-code.d.ts
  5. 173 141
      src/exports/types.ts
  6. 2 1
      src/schemas/index.ts

+ 5 - 2
src/core/config/ProviderSettingsManager.ts

@@ -247,7 +247,7 @@ export class ProviderSettingsManager {
 	 * Preserves the ID from the input 'config' object if it exists,
 	 * otherwise generates a new one (for creation scenarios).
 	 */
-	public async saveConfig(name: string, config: ProviderSettingsWithId) {
+	public async saveConfig(name: string, config: ProviderSettingsWithId): Promise<string> {
 		try {
 			return await this.lock(async () => {
 				const providerProfiles = await this.load()
@@ -259,13 +259,16 @@ export class ProviderSettingsManager {
 				const filteredConfig = providerSettingsSchemaDiscriminated.parse(config)
 				providerProfiles.apiConfigs[name] = { ...filteredConfig, id }
 				await this.store(providerProfiles)
+				return id
 			})
 		} catch (error) {
 			throw new Error(`Failed to save config: ${error}`)
 		}
 	}
 
-	public async getProfile(params: { name: string } | { id: string }) {
+	public async getProfile(
+		params: { name: string } | { id: string },
+	): Promise<ProviderSettingsWithId & { name: string }> {
 		try {
 			return await this.lock(async () => {
 				const providerProfiles = await this.load()

+ 88 - 84
src/exports/api.ts

@@ -178,90 +178,6 @@ export class API extends EventEmitter<RooCodeEvents> implements RooCodeAPI {
 		await this.sidebarProvider.postMessageToWebview({ type: "invoke", invoke: "secondaryButtonClick" })
 	}
 
-	public getConfiguration() {
-		return this.sidebarProvider.getValues()
-	}
-
-	public async setConfiguration(values: RooCodeSettings) {
-		await this.sidebarProvider.setValues(values)
-		await this.sidebarProvider.providerSettingsManager.saveConfig(values.currentApiConfigName || "default", values)
-		await this.sidebarProvider.postStateToWebview()
-	}
-
-	public async createProfile(name: string) {
-		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`)
-		}
-
-		const id = this.sidebarProvider.providerSettingsManager.generateId()
-
-		await this.setConfiguration({
-			...currentSettings,
-			listApiConfigMeta: [
-				...profiles,
-				{
-					id,
-					name: name.trim(),
-					apiProvider: "openai" as const,
-				},
-			],
-		})
-
-		return id
-	}
-
-	private getProfilesMeta() {
-		return this.getConfiguration().listApiConfigMeta || []
-	}
-
-	public getProfiles() {
-		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) {
-		if (!this.hasProfile(name)) {
-			throw new Error(`Profile with name "${name}" does not exist`)
-		}
-
-		await this.sidebarProvider.activateProviderProfile({ name })
-	}
-
-	public getActiveProfile() {
-		return this.getConfiguration().currentApiConfigName
-	}
-
-	public async deleteProfile(name: string) {
-		const currentSettings = this.getConfiguration()
-		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 = listApiConfigMeta[targetIndex]
-		listApiConfigMeta.splice(targetIndex, 1)
-
-		// If we're deleting the active profile, clear the currentApiConfigName.
-		const currentApiConfigName =
-			currentSettings.currentApiConfigName === profileToDelete.name
-				? undefined
-				: currentSettings.currentApiConfigName
-
-		await this.setConfiguration({ ...currentSettings, listApiConfigMeta, currentApiConfigName })
-	}
-
 	public isReady() {
 		return this.sidebarProvider.viewLaunched
 	}
@@ -327,4 +243,92 @@ export class API extends EventEmitter<RooCodeEvents> implements RooCodeAPI {
 			this.logfile = undefined
 		}
 	}
+
+	// Global Settings Management
+
+	public getConfiguration() {
+		return this.sidebarProvider.getValues()
+	}
+
+	public async setConfiguration(values: RooCodeSettings) {
+		await this.sidebarProvider.contextProxy.setValues(values)
+		await this.sidebarProvider.providerSettingsManager.saveConfig(values.currentApiConfigName || "default", values)
+		await this.sidebarProvider.postStateToWebview()
+	}
+
+	// Provider Profile Management
+
+	private getProfilesMeta() {
+		return this.getConfiguration().listApiConfigMeta || []
+	}
+
+	public getProfiles() {
+		return this.getProfilesMeta().map((profile) => profile.name)
+	}
+
+	public hasProfile(name: string): boolean {
+		return !!(this.getConfiguration().listApiConfigMeta || []).find((profile) => profile.name === name)
+	}
+
+	public async createProfile(name: string) {
+		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`)
+		}
+
+		const id = this.sidebarProvider.providerSettingsManager.generateId()
+
+		await this.setConfiguration({
+			...currentSettings,
+			listApiConfigMeta: [
+				...profiles,
+				{
+					id,
+					name: name.trim(),
+					apiProvider: "openai" as const,
+				},
+			],
+		})
+
+		return id
+	}
+
+	public async deleteProfile(name: string) {
+		const currentSettings = this.getConfiguration()
+		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 = listApiConfigMeta[targetIndex]
+		listApiConfigMeta.splice(targetIndex, 1)
+
+		// If we're deleting the active profile, clear the currentApiConfigName.
+		const currentApiConfigName =
+			currentSettings.currentApiConfigName === profileToDelete.name
+				? undefined
+				: currentSettings.currentApiConfigName
+
+		await this.setConfiguration({ ...currentSettings, listApiConfigMeta, currentApiConfigName })
+	}
+
+	public getActiveProfile(): string | undefined {
+		return this.getConfiguration().currentApiConfigName
+	}
+
+	public async setActiveProfile(name: string) {
+		if (!this.hasProfile(name)) {
+			throw new Error(`Profile with name "${name}" does not exist`)
+		}
+
+		await this.sidebarProvider.activateProviderProfile({ name })
+	}
 }

+ 37 - 20
src/exports/interface.ts

@@ -1,7 +1,23 @@
 import { EventEmitter } from "events"
 
-import type { ProviderSettings, GlobalSettings, ClineMessage, TokenUsage, RooCodeEvents } from "./types"
-export type { RooCodeSettings, ProviderSettings, GlobalSettings, ClineMessage, TokenUsage, RooCodeEvents }
+import type {
+	GlobalSettings,
+	ProviderSettings,
+	ProviderSettingsEntry,
+	ClineMessage,
+	TokenUsage,
+	RooCodeEvents,
+} from "./types"
+
+export type {
+	RooCodeSettings,
+	GlobalSettings,
+	ProviderSettings,
+	ProviderSettingsEntry,
+	ClineMessage,
+	TokenUsage,
+	RooCodeEvents,
+}
 
 import { RooCodeEventName } from "../schemas"
 export type { RooCodeEventName }
@@ -74,6 +90,11 @@ export interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
 	 */
 	pressSecondaryButton(): Promise<void>
 
+	/**
+	 * Returns true if the API is ready to use.
+	 */
+	isReady(): boolean
+
 	/**
 	 * Returns the current configuration.
 	 * @returns The current configuration.
@@ -86,13 +107,6 @@ export interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
 	 */
 	setConfiguration(values: RooCodeSettings): Promise<void>
 
-	/**
-	 * Creates a new API configuration profile
-	 * @param name The name of the profile
-	 * @returns The ID of the created profile
-	 */
-	createProfile(name: string): Promise<string>
-
 	/**
 	 * Returns a list of all configured profile names
 	 * @returns Array of profile names
@@ -100,11 +114,19 @@ export interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
 	getProfiles(): string[]
 
 	/**
-	 * Changes the active API configuration profile
-	 * @param name The name of the profile to activate
+	 * Creates a new API configuration profile
+	 * @param name The name of the profile
+	 * @returns The ID of the created profile
+	 * @throws Error if the profile already exists
+	 */
+	createProfile(name: string, profile?: ProviderSettings): Promise<string>
+
+	/**
+	 * Deletes a profile by name
+	 * @param name The name of the profile to delete
 	 * @throws Error if the profile does not exist
 	 */
-	setActiveProfile(name: string): Promise<void>
+	deleteProfile(name: string): Promise<void>
 
 	/**
 	 * Returns the name of the currently active profile
@@ -113,14 +135,9 @@ export interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
 	getActiveProfile(): string | undefined
 
 	/**
-	 * Deletes a profile by name
-	 * @param name The name of the profile to delete
+	 * Changes the active API configuration profile
+	 * @param name The name of the profile to activate
 	 * @throws Error if the profile does not exist
 	 */
-	deleteProfile(name: string): Promise<void>
-
-	/**
-	 * Returns true if the API is ready to use.
-	 */
-	isReady(): boolean
+	setActiveProfile(name: string): Promise<void>
 }

+ 187 - 155
src/exports/roo-code.d.ts

@@ -1,144 +1,5 @@
 import { EventEmitter } from "events"
 
-type ProviderSettings = {
-	apiProvider?:
-		| (
-				| "anthropic"
-				| "glama"
-				| "openrouter"
-				| "bedrock"
-				| "vertex"
-				| "openai"
-				| "ollama"
-				| "vscode-lm"
-				| "lmstudio"
-				| "gemini"
-				| "openai-native"
-				| "mistral"
-				| "deepseek"
-				| "unbound"
-				| "requesty"
-				| "human-relay"
-				| "fake-ai"
-				| "xai"
-				| "groq"
-				| "chutes"
-				| "litellm"
-		  )
-		| undefined
-	apiModelId?: string | undefined
-	apiKey?: string | undefined
-	anthropicBaseUrl?: string | undefined
-	anthropicUseAuthToken?: boolean | undefined
-	glamaModelId?: string | undefined
-	glamaApiKey?: string | undefined
-	openRouterApiKey?: string | undefined
-	openRouterModelId?: string | undefined
-	openRouterBaseUrl?: string | undefined
-	openRouterSpecificProvider?: string | undefined
-	openRouterUseMiddleOutTransform?: boolean | undefined
-	awsAccessKey?: string | undefined
-	awsSecretKey?: string | undefined
-	awsSessionToken?: string | undefined
-	awsRegion?: string | undefined
-	awsUseCrossRegionInference?: boolean | undefined
-	awsUsePromptCache?: boolean | undefined
-	awsProfile?: string | undefined
-	awsUseProfile?: boolean | undefined
-	awsCustomArn?: string | undefined
-	vertexKeyFile?: string | undefined
-	vertexJsonCredentials?: string | undefined
-	vertexProjectId?: string | undefined
-	vertexRegion?: string | undefined
-	openAiBaseUrl?: string | undefined
-	openAiApiKey?: string | undefined
-	openAiLegacyFormat?: boolean | undefined
-	openAiR1FormatEnabled?: boolean | undefined
-	openAiModelId?: string | undefined
-	openAiCustomModelInfo?:
-		| ({
-				maxTokens?: (number | null) | undefined
-				maxThinkingTokens?: (number | null) | undefined
-				contextWindow: number
-				supportsImages?: boolean | undefined
-				supportsComputerUse?: boolean | undefined
-				supportsPromptCache: boolean
-				isPromptCacheOptional?: boolean | undefined
-				inputPrice?: number | undefined
-				outputPrice?: number | undefined
-				cacheWritesPrice?: number | undefined
-				cacheReadsPrice?: number | undefined
-				description?: string | undefined
-				reasoningEffort?: ("low" | "medium" | "high") | undefined
-				thinking?: boolean | undefined
-				minTokensPerCachePoint?: number | undefined
-				maxCachePoints?: number | undefined
-				cachableFields?: string[] | undefined
-				tiers?:
-					| {
-							contextWindow: number
-							inputPrice?: number | undefined
-							outputPrice?: number | undefined
-							cacheWritesPrice?: number | undefined
-							cacheReadsPrice?: number | undefined
-					  }[]
-					| undefined
-		  } | null)
-		| undefined
-	openAiUseAzure?: boolean | undefined
-	azureApiVersion?: string | undefined
-	openAiStreamingEnabled?: boolean | undefined
-	enableReasoningEffort?: boolean | undefined
-	openAiHostHeader?: string | undefined
-	openAiHeaders?:
-		| {
-				[x: string]: string
-		  }
-		| undefined
-	ollamaModelId?: string | undefined
-	ollamaBaseUrl?: string | undefined
-	vsCodeLmModelSelector?:
-		| {
-				vendor?: string | undefined
-				family?: string | undefined
-				version?: string | undefined
-				id?: string | undefined
-		  }
-		| undefined
-	lmStudioModelId?: string | undefined
-	lmStudioBaseUrl?: string | undefined
-	lmStudioDraftModelId?: string | undefined
-	lmStudioSpeculativeDecodingEnabled?: boolean | undefined
-	geminiApiKey?: string | undefined
-	googleGeminiBaseUrl?: string | undefined
-	openAiNativeApiKey?: string | undefined
-	openAiNativeBaseUrl?: string | undefined
-	mistralApiKey?: string | undefined
-	mistralCodestralUrl?: string | undefined
-	deepSeekBaseUrl?: string | undefined
-	deepSeekApiKey?: string | undefined
-	unboundApiKey?: string | undefined
-	unboundModelId?: string | undefined
-	requestyApiKey?: string | undefined
-	requestyModelId?: string | undefined
-	fakeAi?: unknown | undefined
-	xaiApiKey?: string | undefined
-	groqApiKey?: string | undefined
-	chutesApiKey?: string | undefined
-	litellmBaseUrl?: string | undefined
-	litellmApiKey?: string | undefined
-	litellmModelId?: string | undefined
-	includeMaxTokens?: boolean | undefined
-	reasoningEffort?: ("low" | "medium" | "high") | undefined
-	promptCachingDisabled?: boolean | undefined
-	diffEnabled?: boolean | undefined
-	fuzzyMatchThreshold?: number | undefined
-	modelTemperature?: (number | null) | undefined
-	rateLimitSeconds?: number | undefined
-	modelMaxTokens?: number | undefined
-	modelMaxThinkingTokens?: number | undefined
-}
-
 type GlobalSettings = {
 	currentApiConfigName?: string | undefined
 	listApiConfigMeta?:
@@ -309,6 +170,175 @@ type GlobalSettings = {
 	historyPreviewCollapsed?: boolean | undefined
 }
 
+type ProviderSettings = {
+	apiProvider?:
+		| (
+				| "anthropic"
+				| "glama"
+				| "openrouter"
+				| "bedrock"
+				| "vertex"
+				| "openai"
+				| "ollama"
+				| "vscode-lm"
+				| "lmstudio"
+				| "gemini"
+				| "openai-native"
+				| "mistral"
+				| "deepseek"
+				| "unbound"
+				| "requesty"
+				| "human-relay"
+				| "fake-ai"
+				| "xai"
+				| "groq"
+				| "chutes"
+				| "litellm"
+		  )
+		| undefined
+	apiModelId?: string | undefined
+	apiKey?: string | undefined
+	anthropicBaseUrl?: string | undefined
+	anthropicUseAuthToken?: boolean | undefined
+	glamaModelId?: string | undefined
+	glamaApiKey?: string | undefined
+	openRouterApiKey?: string | undefined
+	openRouterModelId?: string | undefined
+	openRouterBaseUrl?: string | undefined
+	openRouterSpecificProvider?: string | undefined
+	openRouterUseMiddleOutTransform?: boolean | undefined
+	awsAccessKey?: string | undefined
+	awsSecretKey?: string | undefined
+	awsSessionToken?: string | undefined
+	awsRegion?: string | undefined
+	awsUseCrossRegionInference?: boolean | undefined
+	awsUsePromptCache?: boolean | undefined
+	awsProfile?: string | undefined
+	awsUseProfile?: boolean | undefined
+	awsCustomArn?: string | undefined
+	vertexKeyFile?: string | undefined
+	vertexJsonCredentials?: string | undefined
+	vertexProjectId?: string | undefined
+	vertexRegion?: string | undefined
+	openAiBaseUrl?: string | undefined
+	openAiApiKey?: string | undefined
+	openAiLegacyFormat?: boolean | undefined
+	openAiR1FormatEnabled?: boolean | undefined
+	openAiModelId?: string | undefined
+	openAiCustomModelInfo?:
+		| ({
+				maxTokens?: (number | null) | undefined
+				maxThinkingTokens?: (number | null) | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				isPromptCacheOptional?: boolean | undefined
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+				minTokensPerCachePoint?: number | undefined
+				maxCachePoints?: number | undefined
+				cachableFields?: string[] | undefined
+				tiers?:
+					| {
+							contextWindow: number
+							inputPrice?: number | undefined
+							outputPrice?: number | undefined
+							cacheWritesPrice?: number | undefined
+							cacheReadsPrice?: number | undefined
+					  }[]
+					| undefined
+		  } | null)
+		| undefined
+	openAiUseAzure?: boolean | undefined
+	azureApiVersion?: string | undefined
+	openAiStreamingEnabled?: boolean | undefined
+	enableReasoningEffort?: boolean | undefined
+	openAiHostHeader?: string | undefined
+	openAiHeaders?:
+		| {
+				[x: string]: string
+		  }
+		| undefined
+	ollamaModelId?: string | undefined
+	ollamaBaseUrl?: string | undefined
+	vsCodeLmModelSelector?:
+		| {
+				vendor?: string | undefined
+				family?: string | undefined
+				version?: string | undefined
+				id?: string | undefined
+		  }
+		| undefined
+	lmStudioModelId?: string | undefined
+	lmStudioBaseUrl?: string | undefined
+	lmStudioDraftModelId?: string | undefined
+	lmStudioSpeculativeDecodingEnabled?: boolean | undefined
+	geminiApiKey?: string | undefined
+	googleGeminiBaseUrl?: string | undefined
+	openAiNativeApiKey?: string | undefined
+	openAiNativeBaseUrl?: string | undefined
+	mistralApiKey?: string | undefined
+	mistralCodestralUrl?: string | undefined
+	deepSeekBaseUrl?: string | undefined
+	deepSeekApiKey?: string | undefined
+	unboundApiKey?: string | undefined
+	unboundModelId?: string | undefined
+	requestyApiKey?: string | undefined
+	requestyModelId?: string | undefined
+	fakeAi?: unknown | undefined
+	xaiApiKey?: string | undefined
+	groqApiKey?: string | undefined
+	chutesApiKey?: string | undefined
+	litellmBaseUrl?: string | undefined
+	litellmApiKey?: string | undefined
+	litellmModelId?: string | undefined
+	includeMaxTokens?: boolean | undefined
+	reasoningEffort?: ("low" | "medium" | "high") | undefined
+	promptCachingDisabled?: boolean | undefined
+	diffEnabled?: boolean | undefined
+	fuzzyMatchThreshold?: number | undefined
+	modelTemperature?: (number | null) | undefined
+	rateLimitSeconds?: number | undefined
+	modelMaxTokens?: number | undefined
+	modelMaxThinkingTokens?: number | undefined
+}
+
+type ProviderSettingsEntry = {
+	id: string
+	name: string
+	apiProvider?:
+		| (
+				| "anthropic"
+				| "glama"
+				| "openrouter"
+				| "bedrock"
+				| "vertex"
+				| "openai"
+				| "ollama"
+				| "vscode-lm"
+				| "lmstudio"
+				| "gemini"
+				| "openai-native"
+				| "mistral"
+				| "deepseek"
+				| "unbound"
+				| "requesty"
+				| "human-relay"
+				| "fake-ai"
+				| "xai"
+				| "groq"
+				| "chutes"
+				| "litellm"
+		  )
+		| undefined
+}
+
 type ClineMessage = {
 	ts: number
 	type: "ask" | "say"
@@ -583,6 +613,10 @@ interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
 	 * Simulates pressing the secondary button in the chat interface.
 	 */
 	pressSecondaryButton(): Promise<void>
+	/**
+	 * Returns true if the API is ready to use.
+	 */
+	isReady(): boolean
 	/**
 	 * Returns the current configuration.
 	 * @returns The current configuration.
@@ -593,44 +627,42 @@ interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
 	 * @param values An object containing key-value pairs to set.
 	 */
 	setConfiguration(values: RooCodeSettings): Promise<void>
-	/**
-	 * Creates a new API configuration profile
-	 * @param name The name of the profile
-	 * @returns The ID of the created profile
-	 */
-	createProfile(name: string): Promise<string>
 	/**
 	 * 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
+	 * Creates a new API configuration profile
+	 * @param name The name of the profile
+	 * @returns The ID of the created profile
+	 * @throws Error if the profile already exists
+	 */
+	createProfile(name: string, profile?: ProviderSettings): Promise<string>
+	/**
+	 * Deletes a profile by name
+	 * @param name The name of the profile to delete
 	 * @throws Error if the profile does not exist
 	 */
-	setActiveProfile(name: string): Promise<void>
+	deleteProfile(name: string): Promise<void>
 	/**
 	 * 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
+	 * Changes the active API configuration profile
+	 * @param name The name of the profile to activate
 	 * @throws Error if the profile does not exist
 	 */
-	deleteProfile(name: string): Promise<void>
-	/**
-	 * Returns true if the API is ready to use.
-	 */
-	isReady(): boolean
+	setActiveProfile(name: string): Promise<void>
 }
 
 export {
 	type ClineMessage,
 	type GlobalSettings,
 	type ProviderSettings,
+	type ProviderSettingsEntry,
 	type RooCodeAPI,
 	RooCodeEventName,
 	type RooCodeEvents,

+ 173 - 141
src/exports/types.ts

@@ -1,147 +1,6 @@
 // This file is automatically generated by running `npm run generate-types`
 // Do not edit it directly.
 
-type ProviderSettings = {
-	apiProvider?:
-		| (
-				| "anthropic"
-				| "glama"
-				| "openrouter"
-				| "bedrock"
-				| "vertex"
-				| "openai"
-				| "ollama"
-				| "vscode-lm"
-				| "lmstudio"
-				| "gemini"
-				| "openai-native"
-				| "mistral"
-				| "deepseek"
-				| "unbound"
-				| "requesty"
-				| "human-relay"
-				| "fake-ai"
-				| "xai"
-				| "groq"
-				| "chutes"
-				| "litellm"
-		  )
-		| undefined
-	apiModelId?: string | undefined
-	apiKey?: string | undefined
-	anthropicBaseUrl?: string | undefined
-	anthropicUseAuthToken?: boolean | undefined
-	glamaModelId?: string | undefined
-	glamaApiKey?: string | undefined
-	openRouterApiKey?: string | undefined
-	openRouterModelId?: string | undefined
-	openRouterBaseUrl?: string | undefined
-	openRouterSpecificProvider?: string | undefined
-	openRouterUseMiddleOutTransform?: boolean | undefined
-	awsAccessKey?: string | undefined
-	awsSecretKey?: string | undefined
-	awsSessionToken?: string | undefined
-	awsRegion?: string | undefined
-	awsUseCrossRegionInference?: boolean | undefined
-	awsUsePromptCache?: boolean | undefined
-	awsProfile?: string | undefined
-	awsUseProfile?: boolean | undefined
-	awsCustomArn?: string | undefined
-	vertexKeyFile?: string | undefined
-	vertexJsonCredentials?: string | undefined
-	vertexProjectId?: string | undefined
-	vertexRegion?: string | undefined
-	openAiBaseUrl?: string | undefined
-	openAiApiKey?: string | undefined
-	openAiLegacyFormat?: boolean | undefined
-	openAiR1FormatEnabled?: boolean | undefined
-	openAiModelId?: string | undefined
-	openAiCustomModelInfo?:
-		| ({
-				maxTokens?: (number | null) | undefined
-				maxThinkingTokens?: (number | null) | undefined
-				contextWindow: number
-				supportsImages?: boolean | undefined
-				supportsComputerUse?: boolean | undefined
-				supportsPromptCache: boolean
-				isPromptCacheOptional?: boolean | undefined
-				inputPrice?: number | undefined
-				outputPrice?: number | undefined
-				cacheWritesPrice?: number | undefined
-				cacheReadsPrice?: number | undefined
-				description?: string | undefined
-				reasoningEffort?: ("low" | "medium" | "high") | undefined
-				thinking?: boolean | undefined
-				minTokensPerCachePoint?: number | undefined
-				maxCachePoints?: number | undefined
-				cachableFields?: string[] | undefined
-				tiers?:
-					| {
-							contextWindow: number
-							inputPrice?: number | undefined
-							outputPrice?: number | undefined
-							cacheWritesPrice?: number | undefined
-							cacheReadsPrice?: number | undefined
-					  }[]
-					| undefined
-		  } | null)
-		| undefined
-	openAiUseAzure?: boolean | undefined
-	azureApiVersion?: string | undefined
-	openAiStreamingEnabled?: boolean | undefined
-	enableReasoningEffort?: boolean | undefined
-	openAiHostHeader?: string | undefined
-	openAiHeaders?:
-		| {
-				[x: string]: string
-		  }
-		| undefined
-	ollamaModelId?: string | undefined
-	ollamaBaseUrl?: string | undefined
-	vsCodeLmModelSelector?:
-		| {
-				vendor?: string | undefined
-				family?: string | undefined
-				version?: string | undefined
-				id?: string | undefined
-		  }
-		| undefined
-	lmStudioModelId?: string | undefined
-	lmStudioBaseUrl?: string | undefined
-	lmStudioDraftModelId?: string | undefined
-	lmStudioSpeculativeDecodingEnabled?: boolean | undefined
-	geminiApiKey?: string | undefined
-	googleGeminiBaseUrl?: string | undefined
-	openAiNativeApiKey?: string | undefined
-	openAiNativeBaseUrl?: string | undefined
-	mistralApiKey?: string | undefined
-	mistralCodestralUrl?: string | undefined
-	deepSeekBaseUrl?: string | undefined
-	deepSeekApiKey?: string | undefined
-	unboundApiKey?: string | undefined
-	unboundModelId?: string | undefined
-	requestyApiKey?: string | undefined
-	requestyModelId?: string | undefined
-	fakeAi?: unknown | undefined
-	xaiApiKey?: string | undefined
-	groqApiKey?: string | undefined
-	chutesApiKey?: string | undefined
-	litellmBaseUrl?: string | undefined
-	litellmApiKey?: string | undefined
-	litellmModelId?: string | undefined
-	includeMaxTokens?: boolean | undefined
-	reasoningEffort?: ("low" | "medium" | "high") | undefined
-	promptCachingDisabled?: boolean | undefined
-	diffEnabled?: boolean | undefined
-	fuzzyMatchThreshold?: number | undefined
-	modelTemperature?: (number | null) | undefined
-	rateLimitSeconds?: number | undefined
-	modelMaxTokens?: number | undefined
-	modelMaxThinkingTokens?: number | undefined
-}
-
-export type { ProviderSettings }
-
 type GlobalSettings = {
 	currentApiConfigName?: string | undefined
 	listApiConfigMeta?:
@@ -314,6 +173,179 @@ type GlobalSettings = {
 
 export type { GlobalSettings }
 
+type ProviderSettings = {
+	apiProvider?:
+		| (
+				| "anthropic"
+				| "glama"
+				| "openrouter"
+				| "bedrock"
+				| "vertex"
+				| "openai"
+				| "ollama"
+				| "vscode-lm"
+				| "lmstudio"
+				| "gemini"
+				| "openai-native"
+				| "mistral"
+				| "deepseek"
+				| "unbound"
+				| "requesty"
+				| "human-relay"
+				| "fake-ai"
+				| "xai"
+				| "groq"
+				| "chutes"
+				| "litellm"
+		  )
+		| undefined
+	apiModelId?: string | undefined
+	apiKey?: string | undefined
+	anthropicBaseUrl?: string | undefined
+	anthropicUseAuthToken?: boolean | undefined
+	glamaModelId?: string | undefined
+	glamaApiKey?: string | undefined
+	openRouterApiKey?: string | undefined
+	openRouterModelId?: string | undefined
+	openRouterBaseUrl?: string | undefined
+	openRouterSpecificProvider?: string | undefined
+	openRouterUseMiddleOutTransform?: boolean | undefined
+	awsAccessKey?: string | undefined
+	awsSecretKey?: string | undefined
+	awsSessionToken?: string | undefined
+	awsRegion?: string | undefined
+	awsUseCrossRegionInference?: boolean | undefined
+	awsUsePromptCache?: boolean | undefined
+	awsProfile?: string | undefined
+	awsUseProfile?: boolean | undefined
+	awsCustomArn?: string | undefined
+	vertexKeyFile?: string | undefined
+	vertexJsonCredentials?: string | undefined
+	vertexProjectId?: string | undefined
+	vertexRegion?: string | undefined
+	openAiBaseUrl?: string | undefined
+	openAiApiKey?: string | undefined
+	openAiLegacyFormat?: boolean | undefined
+	openAiR1FormatEnabled?: boolean | undefined
+	openAiModelId?: string | undefined
+	openAiCustomModelInfo?:
+		| ({
+				maxTokens?: (number | null) | undefined
+				maxThinkingTokens?: (number | null) | undefined
+				contextWindow: number
+				supportsImages?: boolean | undefined
+				supportsComputerUse?: boolean | undefined
+				supportsPromptCache: boolean
+				isPromptCacheOptional?: boolean | undefined
+				inputPrice?: number | undefined
+				outputPrice?: number | undefined
+				cacheWritesPrice?: number | undefined
+				cacheReadsPrice?: number | undefined
+				description?: string | undefined
+				reasoningEffort?: ("low" | "medium" | "high") | undefined
+				thinking?: boolean | undefined
+				minTokensPerCachePoint?: number | undefined
+				maxCachePoints?: number | undefined
+				cachableFields?: string[] | undefined
+				tiers?:
+					| {
+							contextWindow: number
+							inputPrice?: number | undefined
+							outputPrice?: number | undefined
+							cacheWritesPrice?: number | undefined
+							cacheReadsPrice?: number | undefined
+					  }[]
+					| undefined
+		  } | null)
+		| undefined
+	openAiUseAzure?: boolean | undefined
+	azureApiVersion?: string | undefined
+	openAiStreamingEnabled?: boolean | undefined
+	enableReasoningEffort?: boolean | undefined
+	openAiHostHeader?: string | undefined
+	openAiHeaders?:
+		| {
+				[x: string]: string
+		  }
+		| undefined
+	ollamaModelId?: string | undefined
+	ollamaBaseUrl?: string | undefined
+	vsCodeLmModelSelector?:
+		| {
+				vendor?: string | undefined
+				family?: string | undefined
+				version?: string | undefined
+				id?: string | undefined
+		  }
+		| undefined
+	lmStudioModelId?: string | undefined
+	lmStudioBaseUrl?: string | undefined
+	lmStudioDraftModelId?: string | undefined
+	lmStudioSpeculativeDecodingEnabled?: boolean | undefined
+	geminiApiKey?: string | undefined
+	googleGeminiBaseUrl?: string | undefined
+	openAiNativeApiKey?: string | undefined
+	openAiNativeBaseUrl?: string | undefined
+	mistralApiKey?: string | undefined
+	mistralCodestralUrl?: string | undefined
+	deepSeekBaseUrl?: string | undefined
+	deepSeekApiKey?: string | undefined
+	unboundApiKey?: string | undefined
+	unboundModelId?: string | undefined
+	requestyApiKey?: string | undefined
+	requestyModelId?: string | undefined
+	fakeAi?: unknown | undefined
+	xaiApiKey?: string | undefined
+	groqApiKey?: string | undefined
+	chutesApiKey?: string | undefined
+	litellmBaseUrl?: string | undefined
+	litellmApiKey?: string | undefined
+	litellmModelId?: string | undefined
+	includeMaxTokens?: boolean | undefined
+	reasoningEffort?: ("low" | "medium" | "high") | undefined
+	promptCachingDisabled?: boolean | undefined
+	diffEnabled?: boolean | undefined
+	fuzzyMatchThreshold?: number | undefined
+	modelTemperature?: (number | null) | undefined
+	rateLimitSeconds?: number | undefined
+	modelMaxTokens?: number | undefined
+	modelMaxThinkingTokens?: number | undefined
+}
+
+export type { ProviderSettings }
+
+type ProviderSettingsEntry = {
+	id: string
+	name: string
+	apiProvider?:
+		| (
+				| "anthropic"
+				| "glama"
+				| "openrouter"
+				| "bedrock"
+				| "vertex"
+				| "openai"
+				| "ollama"
+				| "vscode-lm"
+				| "lmstudio"
+				| "gemini"
+				| "openai-native"
+				| "mistral"
+				| "deepseek"
+				| "unbound"
+				| "requesty"
+				| "human-relay"
+				| "fake-ai"
+				| "xai"
+				| "groq"
+				| "chutes"
+				| "litellm"
+		  )
+		| undefined
+}
+
+export type { ProviderSettingsEntry }
+
 type ClineMessage = {
 	ts: number
 	type: "ask" | "say"

+ 2 - 1
src/schemas/index.ts

@@ -1074,8 +1074,9 @@ export type TypeDefinition = {
 }
 
 export const typeDefinitions: TypeDefinition[] = [
-	{ schema: providerSettingsSchema, identifier: "ProviderSettings" },
 	{ schema: globalSettingsSchema, identifier: "GlobalSettings" },
+	{ schema: providerSettingsSchema, identifier: "ProviderSettings" },
+	{ schema: providerSettingsEntrySchema, identifier: "ProviderSettingsEntry" },
 	{ schema: clineMessageSchema, identifier: "ClineMessage" },
 	{ schema: tokenUsageSchema, identifier: "TokenUsage" },
 	{ schema: rooCodeEventsSchema, identifier: "RooCodeEvents" },