Compare commits

...
Author SHA1 Message Date
abeatrix e42359ebcc update type 2025-09-23 16:43:40 -07:00
abeatrix f627a8ea25 refactor(storage): improve state management
Current issue:

1. State definitions are duplicated across multiple places
2. Adding new state requires updates in multiple location, and changes are verbose and error-prone

Changes:

Create a single source of truth for state definitions and reduce boilerplate while maintaining type safety.  Reuse the same set of keys across functions to make sure all keys are updated accordingly.

This change makes it easier to add new state properties in one place.

- Add utility functions to categorize API configuration keys into secrets and settings
- Replace manual key categorization with helper functions in setApiConfiguration method
- Add type assertions with comments for internal state cache modifications
- Reduce code duplication and improve maintainability of API configuration handling
2025-09-23 13:40:16 -07:00
9 changed files with 544 additions and 1329 deletions
+2 -6
View File
@@ -65,11 +65,7 @@ export interface SingleCompletionHandler {
completePrompt(prompt: string): Promise<string>
}
function createHandlerForProvider(
apiProvider: string | undefined,
options: Omit<ApiConfiguration, "apiProvider">,
mode: Mode,
): ApiHandler {
function createHandlerForProvider(apiProvider: string | undefined, options: Partial<ApiConfiguration>, mode: Mode): ApiHandler {
switch (apiProvider) {
case "anthropic":
return new AnthropicHandler({
@@ -399,7 +395,7 @@ function createHandlerForProvider(
}
}
export function buildApiHandler(configuration: ApiConfiguration, mode: Mode): ApiHandler {
export function buildApiHandler(configuration: Partial<ApiConfiguration>, mode: Mode): ApiHandler {
const { planModeApiProvider, actModeApiProvider, ...options } = configuration
const apiProvider = mode === "plan" ? planModeApiProvider : actModeApiProvider
+54 -498
View File
@@ -23,6 +23,11 @@ import {
Settings,
SettingsKey,
} from "./state-keys"
import {
categorizeApiConfigurationKeys,
getApiConfigurationSecretKeys,
getApiConfigurationSettingsKeys,
} from "./utils/api-configuration-helpers"
import { readGlobalStateFromDisk, readSecretsFromDisk, readWorkspaceStateFromDisk } from "./utils/state-helpers"
export interface PersistenceErrorEvent {
error: Error
@@ -298,7 +303,8 @@ export class StateManager {
const onDisk = await readTaskHistoryFromState(this.context)
const cached = this.globalStateCache["taskHistory"]
if (JSON.stringify(onDisk) !== JSON.stringify(cached)) {
this.globalStateCache["taskHistory"] = onDisk
// Use type assertion to bypass readonly constraint for internal state management
;(this.globalStateCache as any)["taskHistory"] = onDisk
await this.onSyncExternalChange?.()
}
} catch (err) {
@@ -310,7 +316,8 @@ export class StateManager {
.on("add", () => syncTaskHistoryFromDisk())
.on("change", () => syncTaskHistoryFromDisk())
.on("unlink", async () => {
this.globalStateCache["taskHistory"] = []
// Use type assertion to bypass readonly constraint for internal state management
;(this.globalStateCache as any)["taskHistory"] = []
await this.onSyncExternalChange?.()
})
.on("error", (error) => console.error("[StateManager] TaskHistory watcher error:", error))
@@ -334,303 +341,25 @@ export class StateManager {
/**
* Convenience method for setting API configuration
* Automatically categorizes keys based on STATE_DEFINITION and SecretKeys
*/
setApiConfiguration(apiConfiguration: ApiConfiguration): void {
setApiConfiguration(apiConfiguration: Partial<ApiConfiguration>): void {
if (!this.isInitialized) {
throw new Error(STATE_MANAGER_NOT_INITIALIZED)
}
const {
apiKey,
openRouterApiKey,
awsAccessKey,
awsSecretKey,
awsSessionToken,
awsRegion,
awsUseCrossRegionInference,
awsBedrockUsePromptCache,
awsBedrockEndpoint,
awsBedrockApiKey,
awsProfile,
awsUseProfile,
awsAuthentication,
vertexProjectId,
vertexRegion,
openAiBaseUrl,
openAiApiKey,
openAiHeaders,
ollamaBaseUrl,
ollamaApiKey,
ollamaApiOptionsCtxNum,
lmStudioBaseUrl,
lmStudioMaxTokens,
anthropicBaseUrl,
geminiApiKey,
geminiBaseUrl,
openAiNativeApiKey,
deepSeekApiKey,
requestyApiKey,
requestyBaseUrl,
togetherApiKey,
qwenApiKey,
doubaoApiKey,
mistralApiKey,
azureApiVersion,
openRouterProviderSorting,
liteLlmBaseUrl,
liteLlmApiKey,
liteLlmUsePromptCache,
qwenApiLine,
moonshotApiLine,
zaiApiLine,
asksageApiKey,
asksageApiUrl,
xaiApiKey,
clineAccountId,
sambanovaApiKey,
cerebrasApiKey,
groqApiKey,
moonshotApiKey,
nebiusApiKey,
fireworksApiKey,
fireworksModelMaxCompletionTokens,
fireworksModelMaxTokens,
sapAiCoreClientId,
sapAiCoreClientSecret,
sapAiCoreBaseUrl,
sapAiCoreTokenUrl,
sapAiResourceGroup,
sapAiCoreUseOrchestrationMode,
claudeCodePath,
qwenCodeOauthPath,
basetenApiKey,
huggingFaceApiKey,
huaweiCloudMaasApiKey,
difyApiKey,
difyBaseUrl,
vercelAiGatewayApiKey,
zaiApiKey,
requestTimeoutMs,
ocaBaseUrl,
// Plan mode configurations
planModeApiProvider,
planModeApiModelId,
planModeThinkingBudgetTokens,
planModeReasoningEffort,
planModeVsCodeLmModelSelector,
planModeAwsBedrockCustomSelected,
planModeAwsBedrockCustomModelBaseId,
planModeOpenRouterModelId,
planModeOpenRouterModelInfo,
planModeOpenAiModelId,
planModeOpenAiModelInfo,
planModeOllamaModelId,
planModeLmStudioModelId,
planModeLiteLlmModelId,
planModeLiteLlmModelInfo,
planModeRequestyModelId,
planModeRequestyModelInfo,
planModeTogetherModelId,
planModeFireworksModelId,
planModeSapAiCoreModelId,
planModeSapAiCoreDeploymentId,
planModeGroqModelId,
planModeGroqModelInfo,
planModeBasetenModelId,
planModeBasetenModelInfo,
planModeHuggingFaceModelId,
planModeHuggingFaceModelInfo,
planModeHuaweiCloudMaasModelId,
planModeHuaweiCloudMaasModelInfo,
planModeVercelAiGatewayModelId,
planModeVercelAiGatewayModelInfo,
planModeOcaModelId,
planModeOcaModelInfo,
// Act mode configurations
actModeApiProvider,
actModeApiModelId,
actModeThinkingBudgetTokens,
actModeReasoningEffort,
actModeVsCodeLmModelSelector,
actModeAwsBedrockCustomSelected,
actModeAwsBedrockCustomModelBaseId,
actModeOpenRouterModelId,
actModeOpenRouterModelInfo,
actModeOpenAiModelId,
actModeOpenAiModelInfo,
actModeOllamaModelId,
actModeLmStudioModelId,
actModeLiteLlmModelId,
actModeLiteLlmModelInfo,
actModeRequestyModelId,
actModeRequestyModelInfo,
actModeTogetherModelId,
actModeFireworksModelId,
actModeSapAiCoreModelId,
actModeSapAiCoreDeploymentId,
actModeGroqModelId,
actModeGroqModelInfo,
actModeBasetenModelId,
actModeBasetenModelInfo,
actModeHuggingFaceModelId,
actModeHuggingFaceModelInfo,
actModeHuaweiCloudMaasModelId,
actModeHuaweiCloudMaasModelInfo,
actModeVercelAiGatewayModelId,
actModeVercelAiGatewayModelInfo,
actModeOcaModelId,
actModeOcaModelInfo,
} = apiConfiguration
// Automatically categorize the API configuration keys
const { settingsUpdates, secretsUpdates } = categorizeApiConfigurationKeys(apiConfiguration)
// Batch update global state keys
this.setGlobalStateBatch({
// Plan mode configuration updates
planModeApiProvider,
planModeApiModelId,
planModeThinkingBudgetTokens,
planModeReasoningEffort,
planModeVsCodeLmModelSelector,
planModeAwsBedrockCustomSelected,
planModeAwsBedrockCustomModelBaseId,
planModeOpenRouterModelId,
planModeOpenRouterModelInfo,
planModeOpenAiModelId,
planModeOpenAiModelInfo,
planModeOllamaModelId,
planModeLmStudioModelId,
planModeLiteLlmModelId,
planModeLiteLlmModelInfo,
planModeRequestyModelId,
planModeRequestyModelInfo,
planModeTogetherModelId,
planModeFireworksModelId,
planModeSapAiCoreModelId,
planModeSapAiCoreDeploymentId,
planModeGroqModelId,
planModeGroqModelInfo,
planModeBasetenModelId,
planModeBasetenModelInfo,
planModeHuggingFaceModelId,
planModeHuggingFaceModelInfo,
planModeHuaweiCloudMaasModelId,
planModeHuaweiCloudMaasModelInfo,
planModeVercelAiGatewayModelId,
planModeVercelAiGatewayModelInfo,
planModeOcaModelId,
planModeOcaModelInfo,
// Act mode configuration updates
actModeApiProvider,
actModeApiModelId,
actModeThinkingBudgetTokens,
actModeReasoningEffort,
actModeVsCodeLmModelSelector,
actModeAwsBedrockCustomSelected,
actModeAwsBedrockCustomModelBaseId,
actModeOpenRouterModelId,
actModeOpenRouterModelInfo,
actModeOpenAiModelId,
actModeOpenAiModelInfo,
actModeOllamaModelId,
actModeLmStudioModelId,
actModeLiteLlmModelId,
actModeLiteLlmModelInfo,
actModeRequestyModelId,
actModeRequestyModelInfo,
actModeTogetherModelId,
actModeFireworksModelId,
actModeSapAiCoreModelId,
actModeSapAiCoreDeploymentId,
actModeGroqModelId,
actModeGroqModelInfo,
actModeBasetenModelId,
actModeBasetenModelInfo,
actModeHuggingFaceModelId,
actModeHuggingFaceModelInfo,
actModeHuaweiCloudMaasModelId,
actModeHuaweiCloudMaasModelInfo,
actModeVercelAiGatewayModelId,
actModeVercelAiGatewayModelInfo,
actModeOcaModelId,
actModeOcaModelInfo,
// Global state updates
awsRegion,
awsUseCrossRegionInference,
awsBedrockUsePromptCache,
awsBedrockEndpoint,
awsProfile,
awsUseProfile,
awsAuthentication,
vertexProjectId,
vertexRegion,
requestyBaseUrl,
openAiBaseUrl,
openAiHeaders,
ollamaBaseUrl,
ollamaApiOptionsCtxNum,
lmStudioBaseUrl,
lmStudioMaxTokens,
anthropicBaseUrl,
geminiBaseUrl,
azureApiVersion,
openRouterProviderSorting,
liteLlmBaseUrl,
liteLlmUsePromptCache,
qwenApiLine,
moonshotApiLine,
zaiApiLine,
asksageApiUrl,
requestTimeoutMs,
fireworksModelMaxCompletionTokens,
fireworksModelMaxTokens,
sapAiCoreBaseUrl,
sapAiCoreTokenUrl,
sapAiResourceGroup,
sapAiCoreUseOrchestrationMode,
claudeCodePath,
difyBaseUrl,
qwenCodeOauthPath,
ocaBaseUrl,
})
// Batch update settings (stored in global state)
if (Object.keys(settingsUpdates).length > 0) {
this.setGlobalStateBatch(settingsUpdates)
}
// Batch update secrets
this.setSecretsBatch({
apiKey,
openRouterApiKey,
clineAccountId,
awsAccessKey,
awsSecretKey,
awsSessionToken,
awsBedrockApiKey,
openAiApiKey,
ollamaApiKey,
geminiApiKey,
openAiNativeApiKey,
deepSeekApiKey,
requestyApiKey,
togetherApiKey,
qwenApiKey,
doubaoApiKey,
mistralApiKey,
liteLlmApiKey,
fireworksApiKey,
asksageApiKey,
xaiApiKey,
sambanovaApiKey,
cerebrasApiKey,
groqApiKey,
moonshotApiKey,
nebiusApiKey,
sapAiCoreClientId,
sapAiCoreClientSecret,
basetenApiKey,
huggingFaceApiKey,
huaweiCloudMaasApiKey,
difyApiKey,
vercelAiGatewayApiKey,
zaiApiKey,
})
if (Object.keys(secretsUpdates).length > 0) {
this.setSecretsBatch(secretsUpdates)
}
}
/**
@@ -842,219 +571,46 @@ export class StateManager {
Object.assign(this.workspaceStateCache, workspaceState)
}
/**
* Helper to get a setting value with task-specific override support
* Returns task cache value if available, otherwise falls back to global cache
*/
private getSettingWithOverride<K extends keyof Settings>(key: K): Settings[K] {
return this.taskStateCache[key] !== undefined ? this.taskStateCache[key] : this.globalStateCache[key]
}
/**
* Helper to get a secret value
*/
private getSecret<K extends keyof Secrets>(key: K): Secrets[K] {
return this.secretsCache[key]
}
/**
* Construct API configuration from cached component keys
* Uses helper functions to automatically get keys from STATE_DEFINITION
*/
private constructApiConfigurationFromCache(): ApiConfiguration {
return {
// Secrets
apiKey: this.secretsCache["apiKey"],
openRouterApiKey: this.secretsCache["openRouterApiKey"],
clineAccountId: this.secretsCache["clineAccountId"],
awsAccessKey: this.secretsCache["awsAccessKey"],
awsSecretKey: this.secretsCache["awsSecretKey"],
awsSessionToken: this.secretsCache["awsSessionToken"],
awsBedrockApiKey: this.secretsCache["awsBedrockApiKey"],
openAiApiKey: this.secretsCache["openAiApiKey"],
ollamaApiKey: this.secretsCache["ollamaApiKey"],
geminiApiKey: this.secretsCache["geminiApiKey"],
openAiNativeApiKey: this.secretsCache["openAiNativeApiKey"],
deepSeekApiKey: this.secretsCache["deepSeekApiKey"],
requestyApiKey: this.secretsCache["requestyApiKey"],
togetherApiKey: this.secretsCache["togetherApiKey"],
qwenApiKey: this.secretsCache["qwenApiKey"],
doubaoApiKey: this.secretsCache["doubaoApiKey"],
mistralApiKey: this.secretsCache["mistralApiKey"],
liteLlmApiKey: this.secretsCache["liteLlmApiKey"],
fireworksApiKey: this.secretsCache["fireworksApiKey"],
asksageApiKey: this.secretsCache["asksageApiKey"],
xaiApiKey: this.secretsCache["xaiApiKey"],
sambanovaApiKey: this.secretsCache["sambanovaApiKey"],
cerebrasApiKey: this.secretsCache["cerebrasApiKey"],
groqApiKey: this.secretsCache["groqApiKey"],
basetenApiKey: this.secretsCache["basetenApiKey"],
moonshotApiKey: this.secretsCache["moonshotApiKey"],
nebiusApiKey: this.secretsCache["nebiusApiKey"],
sapAiCoreClientId: this.secretsCache["sapAiCoreClientId"],
sapAiCoreClientSecret: this.secretsCache["sapAiCoreClientSecret"],
huggingFaceApiKey: this.secretsCache["huggingFaceApiKey"],
huaweiCloudMaasApiKey: this.secretsCache["huaweiCloudMaasApiKey"],
difyApiKey: this.secretsCache["difyApiKey"],
vercelAiGatewayApiKey: this.secretsCache["vercelAiGatewayApiKey"],
zaiApiKey: this.secretsCache["zaiApiKey"],
// Get keys dynamically from STATE_DEFINITION and SecretKeys
const settingsKeys = getApiConfigurationSettingsKeys()
const secretKeys = getApiConfigurationSecretKeys()
// Global state
awsRegion: this.taskStateCache["awsRegion"] || this.globalStateCache["awsRegion"],
awsUseCrossRegionInference:
this.taskStateCache["awsUseCrossRegionInference"] || this.globalStateCache["awsUseCrossRegionInference"],
awsBedrockUsePromptCache:
this.taskStateCache["awsBedrockUsePromptCache"] || this.globalStateCache["awsBedrockUsePromptCache"],
awsBedrockEndpoint: this.taskStateCache["awsBedrockEndpoint"] || this.globalStateCache["awsBedrockEndpoint"],
awsProfile: this.taskStateCache["awsProfile"] || this.globalStateCache["awsProfile"],
awsUseProfile: this.taskStateCache["awsUseProfile"] || this.globalStateCache["awsUseProfile"],
awsAuthentication: this.taskStateCache["awsAuthentication"] || this.globalStateCache["awsAuthentication"],
vertexProjectId: this.taskStateCache["vertexProjectId"] || this.globalStateCache["vertexProjectId"],
vertexRegion: this.taskStateCache["vertexRegion"] || this.globalStateCache["vertexRegion"],
requestyBaseUrl: this.taskStateCache["requestyBaseUrl"] || this.globalStateCache["requestyBaseUrl"],
openAiBaseUrl: this.taskStateCache["openAiBaseUrl"] || this.globalStateCache["openAiBaseUrl"],
openAiHeaders: this.taskStateCache["openAiHeaders"] || this.globalStateCache["openAiHeaders"] || {},
ollamaBaseUrl: this.taskStateCache["ollamaBaseUrl"] || this.globalStateCache["ollamaBaseUrl"],
ollamaApiOptionsCtxNum:
this.taskStateCache["ollamaApiOptionsCtxNum"] || this.globalStateCache["ollamaApiOptionsCtxNum"],
lmStudioBaseUrl: this.taskStateCache["lmStudioBaseUrl"] || this.globalStateCache["lmStudioBaseUrl"],
lmStudioMaxTokens: this.taskStateCache["lmStudioMaxTokens"] || this.globalStateCache["lmStudioMaxTokens"],
anthropicBaseUrl: this.taskStateCache["anthropicBaseUrl"] || this.globalStateCache["anthropicBaseUrl"],
geminiBaseUrl: this.taskStateCache["geminiBaseUrl"] || this.globalStateCache["geminiBaseUrl"],
azureApiVersion: this.taskStateCache["azureApiVersion"] || this.globalStateCache["azureApiVersion"],
openRouterProviderSorting:
this.taskStateCache["openRouterProviderSorting"] || this.globalStateCache["openRouterProviderSorting"],
liteLlmBaseUrl: this.taskStateCache["liteLlmBaseUrl"] || this.globalStateCache["liteLlmBaseUrl"],
liteLlmUsePromptCache: this.taskStateCache["liteLlmUsePromptCache"] || this.globalStateCache["liteLlmUsePromptCache"],
qwenApiLine: this.taskStateCache["qwenApiLine"] || this.globalStateCache["qwenApiLine"],
moonshotApiLine: this.taskStateCache["moonshotApiLine"] || this.globalStateCache["moonshotApiLine"],
zaiApiLine: this.taskStateCache["zaiApiLine"] || this.globalStateCache["zaiApiLine"],
asksageApiUrl: this.taskStateCache["asksageApiUrl"] || this.globalStateCache["asksageApiUrl"],
requestTimeoutMs: this.taskStateCache["requestTimeoutMs"] || this.globalStateCache["requestTimeoutMs"],
fireworksModelMaxCompletionTokens:
this.taskStateCache["fireworksModelMaxCompletionTokens"] ||
this.globalStateCache["fireworksModelMaxCompletionTokens"],
fireworksModelMaxTokens:
this.taskStateCache["fireworksModelMaxTokens"] || this.globalStateCache["fireworksModelMaxTokens"],
sapAiCoreBaseUrl: this.taskStateCache["sapAiCoreBaseUrl"] || this.globalStateCache["sapAiCoreBaseUrl"],
sapAiCoreTokenUrl: this.taskStateCache["sapAiCoreTokenUrl"] || this.globalStateCache["sapAiCoreTokenUrl"],
sapAiResourceGroup: this.taskStateCache["sapAiResourceGroup"] || this.globalStateCache["sapAiResourceGroup"],
sapAiCoreUseOrchestrationMode:
this.taskStateCache["sapAiCoreUseOrchestrationMode"] || this.globalStateCache["sapAiCoreUseOrchestrationMode"],
claudeCodePath: this.taskStateCache["claudeCodePath"] || this.globalStateCache["claudeCodePath"],
qwenCodeOauthPath: this.taskStateCache["qwenCodeOauthPath"] || this.globalStateCache["qwenCodeOauthPath"],
difyBaseUrl: this.taskStateCache["difyBaseUrl"] || this.globalStateCache["difyBaseUrl"],
ocaBaseUrl: this.globalStateCache["ocaBaseUrl"],
// Build configuration object
const config: any = {}
// Plan mode configurations
planModeApiProvider: this.taskStateCache["planModeApiProvider"] || this.globalStateCache["planModeApiProvider"],
planModeApiModelId: this.taskStateCache["planModeApiModelId"] || this.globalStateCache["planModeApiModelId"],
planModeThinkingBudgetTokens:
this.taskStateCache["planModeThinkingBudgetTokens"] || this.globalStateCache["planModeThinkingBudgetTokens"],
planModeReasoningEffort:
this.taskStateCache["planModeReasoningEffort"] || this.globalStateCache["planModeReasoningEffort"],
planModeVsCodeLmModelSelector:
this.taskStateCache["planModeVsCodeLmModelSelector"] || this.globalStateCache["planModeVsCodeLmModelSelector"],
planModeAwsBedrockCustomSelected:
this.taskStateCache["planModeAwsBedrockCustomSelected"] ||
this.globalStateCache["planModeAwsBedrockCustomSelected"],
planModeAwsBedrockCustomModelBaseId:
this.taskStateCache["planModeAwsBedrockCustomModelBaseId"] ||
this.globalStateCache["planModeAwsBedrockCustomModelBaseId"],
planModeOpenRouterModelId:
this.taskStateCache["planModeOpenRouterModelId"] || this.globalStateCache["planModeOpenRouterModelId"],
planModeOpenRouterModelInfo:
this.taskStateCache["planModeOpenRouterModelInfo"] || this.globalStateCache["planModeOpenRouterModelInfo"],
planModeOpenAiModelId: this.taskStateCache["planModeOpenAiModelId"] || this.globalStateCache["planModeOpenAiModelId"],
planModeOpenAiModelInfo:
this.taskStateCache["planModeOpenAiModelInfo"] || this.globalStateCache["planModeOpenAiModelInfo"],
planModeOllamaModelId: this.taskStateCache["planModeOllamaModelId"] || this.globalStateCache["planModeOllamaModelId"],
planModeLmStudioModelId:
this.taskStateCache["planModeLmStudioModelId"] || this.globalStateCache["planModeLmStudioModelId"],
planModeLiteLlmModelId:
this.taskStateCache["planModeLiteLlmModelId"] || this.globalStateCache["planModeLiteLlmModelId"],
planModeLiteLlmModelInfo:
this.taskStateCache["planModeLiteLlmModelInfo"] || this.globalStateCache["planModeLiteLlmModelInfo"],
planModeRequestyModelId:
this.taskStateCache["planModeRequestyModelId"] || this.globalStateCache["planModeRequestyModelId"],
planModeRequestyModelInfo:
this.taskStateCache["planModeRequestyModelInfo"] || this.globalStateCache["planModeRequestyModelInfo"],
planModeTogetherModelId:
this.taskStateCache["planModeTogetherModelId"] || this.globalStateCache["planModeTogetherModelId"],
planModeFireworksModelId:
this.taskStateCache["planModeFireworksModelId"] || this.globalStateCache["planModeFireworksModelId"],
planModeSapAiCoreModelId:
this.taskStateCache["planModeSapAiCoreModelId"] || this.globalStateCache["planModeSapAiCoreModelId"],
planModeSapAiCoreDeploymentId:
this.taskStateCache["planModeSapAiCoreDeploymentId"] || this.globalStateCache["planModeSapAiCoreDeploymentId"],
planModeGroqModelId: this.taskStateCache["planModeGroqModelId"] || this.globalStateCache["planModeGroqModelId"],
planModeGroqModelInfo: this.taskStateCache["planModeGroqModelInfo"] || this.globalStateCache["planModeGroqModelInfo"],
planModeBasetenModelId:
this.taskStateCache["planModeBasetenModelId"] || this.globalStateCache["planModeBasetenModelId"],
planModeBasetenModelInfo:
this.taskStateCache["planModeBasetenModelInfo"] || this.globalStateCache["planModeBasetenModelInfo"],
planModeHuggingFaceModelId:
this.taskStateCache["planModeHuggingFaceModelId"] || this.globalStateCache["planModeHuggingFaceModelId"],
planModeHuggingFaceModelInfo:
this.taskStateCache["planModeHuggingFaceModelInfo"] || this.globalStateCache["planModeHuggingFaceModelInfo"],
planModeHuaweiCloudMaasModelId:
this.taskStateCache["planModeHuaweiCloudMaasModelId"] || this.globalStateCache["planModeHuaweiCloudMaasModelId"],
planModeHuaweiCloudMaasModelInfo:
this.taskStateCache["planModeHuaweiCloudMaasModelInfo"] ||
this.globalStateCache["planModeHuaweiCloudMaasModelInfo"],
planModeVercelAiGatewayModelId:
this.taskStateCache["planModeVercelAiGatewayModelId"] || this.globalStateCache["planModeVercelAiGatewayModelId"],
planModeVercelAiGatewayModelInfo:
this.taskStateCache["planModeVercelAiGatewayModelInfo"] ||
this.globalStateCache["planModeVercelAiGatewayModelInfo"],
planModeOcaModelId: this.globalStateCache["planModeOcaModelId"],
planModeOcaModelInfo: this.globalStateCache["planModeOcaModelInfo"],
// Act mode configurations
actModeApiProvider: this.taskStateCache["actModeApiProvider"] || this.globalStateCache["actModeApiProvider"],
actModeApiModelId: this.taskStateCache["actModeApiModelId"] || this.globalStateCache["actModeApiModelId"],
actModeThinkingBudgetTokens:
this.taskStateCache["actModeThinkingBudgetTokens"] || this.globalStateCache["actModeThinkingBudgetTokens"],
actModeReasoningEffort:
this.taskStateCache["actModeReasoningEffort"] || this.globalStateCache["actModeReasoningEffort"],
actModeVsCodeLmModelSelector:
this.taskStateCache["actModeVsCodeLmModelSelector"] || this.globalStateCache["actModeVsCodeLmModelSelector"],
actModeAwsBedrockCustomSelected:
this.taskStateCache["actModeAwsBedrockCustomSelected"] ||
this.globalStateCache["actModeAwsBedrockCustomSelected"],
actModeAwsBedrockCustomModelBaseId:
this.taskStateCache["actModeAwsBedrockCustomModelBaseId"] ||
this.globalStateCache["actModeAwsBedrockCustomModelBaseId"],
actModeOpenRouterModelId:
this.taskStateCache["actModeOpenRouterModelId"] || this.globalStateCache["actModeOpenRouterModelId"],
actModeOpenRouterModelInfo:
this.taskStateCache["actModeOpenRouterModelInfo"] || this.globalStateCache["actModeOpenRouterModelInfo"],
actModeOpenAiModelId: this.taskStateCache["actModeOpenAiModelId"] || this.globalStateCache["actModeOpenAiModelId"],
actModeOpenAiModelInfo:
this.taskStateCache["actModeOpenAiModelInfo"] || this.globalStateCache["actModeOpenAiModelInfo"],
actModeOllamaModelId: this.taskStateCache["actModeOllamaModelId"] || this.globalStateCache["actModeOllamaModelId"],
actModeLmStudioModelId:
this.taskStateCache["actModeLmStudioModelId"] || this.globalStateCache["actModeLmStudioModelId"],
actModeLiteLlmModelId: this.taskStateCache["actModeLiteLlmModelId"] || this.globalStateCache["actModeLiteLlmModelId"],
actModeLiteLlmModelInfo:
this.taskStateCache["actModeLiteLlmModelInfo"] || this.globalStateCache["actModeLiteLlmModelInfo"],
actModeRequestyModelId:
this.taskStateCache["actModeRequestyModelId"] || this.globalStateCache["actModeRequestyModelId"],
actModeRequestyModelInfo:
this.taskStateCache["actModeRequestyModelInfo"] || this.globalStateCache["actModeRequestyModelInfo"],
actModeTogetherModelId:
this.taskStateCache["actModeTogetherModelId"] || this.globalStateCache["actModeTogetherModelId"],
actModeFireworksModelId:
this.taskStateCache["actModeFireworksModelId"] || this.globalStateCache["actModeFireworksModelId"],
actModeSapAiCoreModelId:
this.taskStateCache["actModeSapAiCoreModelId"] || this.globalStateCache["actModeSapAiCoreModelId"],
actModeSapAiCoreDeploymentId:
this.taskStateCache["actModeSapAiCoreDeploymentId"] || this.globalStateCache["actModeSapAiCoreDeploymentId"],
actModeGroqModelId: this.taskStateCache["actModeGroqModelId"] || this.globalStateCache["actModeGroqModelId"],
actModeGroqModelInfo: this.taskStateCache["actModeGroqModelInfo"] || this.globalStateCache["actModeGroqModelInfo"],
actModeBasetenModelId: this.taskStateCache["actModeBasetenModelId"] || this.globalStateCache["actModeBasetenModelId"],
actModeBasetenModelInfo:
this.taskStateCache["actModeBasetenModelInfo"] || this.globalStateCache["actModeBasetenModelInfo"],
actModeHuggingFaceModelId:
this.taskStateCache["actModeHuggingFaceModelId"] || this.globalStateCache["actModeHuggingFaceModelId"],
actModeHuggingFaceModelInfo:
this.taskStateCache["actModeHuggingFaceModelInfo"] || this.globalStateCache["actModeHuggingFaceModelInfo"],
actModeHuaweiCloudMaasModelId:
this.taskStateCache["actModeHuaweiCloudMaasModelId"] || this.globalStateCache["actModeHuaweiCloudMaasModelId"],
actModeHuaweiCloudMaasModelInfo:
this.taskStateCache["actModeHuaweiCloudMaasModelInfo"] ||
this.globalStateCache["actModeHuaweiCloudMaasModelInfo"],
actModeVercelAiGatewayModelId:
this.taskStateCache["actModeVercelAiGatewayModelId"] || this.globalStateCache["actModeVercelAiGatewayModelId"],
actModeVercelAiGatewayModelInfo:
this.taskStateCache["actModeVercelAiGatewayModelInfo"] ||
this.globalStateCache["actModeVercelAiGatewayModelInfo"],
actModeOcaModelId: this.globalStateCache["actModeOcaModelId"],
actModeOcaModelInfo: this.globalStateCache["actModeOcaModelInfo"],
// Add all secrets
for (const key of secretKeys) {
config[key] = this.getSecret(key)
}
// Add all settings with task override support
for (const key of settingsKeys) {
config[key] = this.getSettingWithOverride(key)
}
// Add special case for openAiHeaders with default empty object
config.openAiHeaders = this.getSettingWithOverride("openAiHeaders") || {}
return config satisfies ApiConfiguration
}
}
+325 -203
View File
@@ -1,219 +1,341 @@
import { ApiProvider, ModelInfo, type OcaModelInfo } from "@shared/api"
import { FocusChainSettings } from "@shared/FocusChainSettings"
import { AutoApprovalSettings, DEFAULT_AUTO_APPROVAL_SETTINGS } from "@shared/AutoApprovalSettings"
import { ApiProvider, fireworksDefaultModelId, ModelInfo, type OcaModelInfo } from "@shared/api"
import { BrowserSettings, DEFAULT_BROWSER_SETTINGS } from "@shared/BrowserSettings"
import { ClineRulesToggles } from "@shared/cline-rules"
import { DEFAULT_DICTATION_SETTINGS, DictationSettings } from "@shared/DictationSettings"
import { DEFAULT_FOCUS_CHAIN_SETTINGS, FocusChainSettings } from "@shared/FocusChainSettings"
import { HistoryItem } from "@shared/HistoryItem"
import { DEFAULT_MCP_DISPLAY_MODE, McpDisplayMode } from "@shared/McpDisplayMode"
import { McpMarketplaceCatalog } from "@shared/mcp"
import { Mode, OpenaiReasoningEffort } from "@shared/storage/types"
import { TelemetrySetting } from "@shared/TelemetrySetting"
import { UserInfo } from "@shared/UserInfo"
import { LanguageModelChatSelector } from "vscode"
import { WorkspaceRoot } from "@/core/workspace/WorkspaceRoot"
import { AutoApprovalSettings } from "@/shared/AutoApprovalSettings"
import { BrowserSettings } from "@/shared/BrowserSettings"
import { ClineRulesToggles } from "@/shared/cline-rules"
import { DictationSettings } from "@/shared/DictationSettings"
import { HistoryItem } from "@/shared/HistoryItem"
import { McpDisplayMode } from "@/shared/McpDisplayMode"
import { McpMarketplaceCatalog } from "@/shared/mcp"
import { Mode, OpenaiReasoningEffort } from "@/shared/storage/types"
import { TelemetrySetting } from "@/shared/TelemetrySetting"
import { UserInfo } from "@/shared/UserInfo"
export type SecretKey = keyof Secrets
import { WorkspaceRoot } from "../workspace/WorkspaceRoot"
export type GlobalStateKey = keyof GlobalState
// ============================================================================
// SINGLE SOURCE OF TRUTH - Property definitions
// ============================================================================
export type LocalStateKey = keyof LocalState
const GLOBAL_STATE_PROPS = {
lastShownAnnouncementId: { type: undefined as string | undefined },
taskHistory: { type: [] as HistoryItem[], isAsync: true },
userInfo: { type: undefined as UserInfo | undefined },
mcpMarketplaceCatalog: { type: undefined as McpMarketplaceCatalog | undefined },
favoritedModelIds: { type: [] as string[], defaultValue: [] as string[] },
mcpMarketplaceEnabled: { type: true as boolean, defaultValue: true },
mcpResponsesCollapsed: { type: false as boolean, defaultValue: false },
terminalReuseEnabled: { type: true as boolean, defaultValue: true },
isNewUser: { type: true as boolean, defaultValue: true },
welcomeViewCompleted: { type: undefined as boolean | undefined },
mcpDisplayMode: { type: DEFAULT_MCP_DISPLAY_MODE as McpDisplayMode, defaultValue: DEFAULT_MCP_DISPLAY_MODE },
workspaceRoots: { type: undefined as WorkspaceRoot[] | undefined },
primaryRootIndex: { type: 0 as number, defaultValue: 0 },
multiRootEnabled: { type: false as boolean, defaultValue: false },
} as const
export type SettingsKey = keyof Settings
const SETTINGS_PROPS = {
// AWS Settings
awsRegion: { type: undefined as string | undefined },
awsUseCrossRegionInference: { type: undefined as boolean | undefined },
awsBedrockUsePromptCache: { type: undefined as boolean | undefined },
awsBedrockEndpoint: { type: undefined as string | undefined },
awsProfile: { type: undefined as string | undefined },
awsAuthentication: { type: undefined as string | undefined },
awsUseProfile: { type: undefined as boolean | undefined },
export type GlobalStateAndSettingsKey = keyof (GlobalState & Settings)
// Vertex Settings
vertexProjectId: { type: undefined as string | undefined },
vertexRegion: { type: undefined as string | undefined },
// API Base URLs
requestyBaseUrl: { type: undefined as string | undefined },
openAiBaseUrl: { type: undefined as string | undefined },
ollamaBaseUrl: { type: undefined as string | undefined },
lmStudioBaseUrl: { type: undefined as string | undefined },
anthropicBaseUrl: { type: undefined as string | undefined },
geminiBaseUrl: { type: undefined as string | undefined },
liteLlmBaseUrl: { type: undefined as string | undefined },
asksageApiUrl: { type: undefined as string | undefined },
difyBaseUrl: { type: undefined as string | undefined },
ocaBaseUrl: { type: undefined as string | undefined },
// API Configuration
openAiHeaders: { type: {} as Record<string, string>, defaultValue: {} as Record<string, string> },
ollamaApiOptionsCtxNum: { type: undefined as string | undefined },
lmStudioMaxTokens: { type: undefined as string | undefined },
azureApiVersion: { type: undefined as string | undefined },
openRouterProviderSorting: { type: undefined as string | undefined },
liteLlmUsePromptCache: { type: undefined as boolean | undefined },
fireworksModelMaxCompletionTokens: { type: undefined as number | undefined },
fireworksModelMaxTokens: { type: undefined as number | undefined },
// API Lines
qwenApiLine: { type: undefined as string | undefined },
moonshotApiLine: { type: undefined as string | undefined },
zaiApiLine: { type: undefined as string | undefined },
// Complex Settings
autoApprovalSettings: {
type: DEFAULT_AUTO_APPROVAL_SETTINGS as AutoApprovalSettings,
defaultValue: DEFAULT_AUTO_APPROVAL_SETTINGS,
},
browserSettings: {
type: DEFAULT_BROWSER_SETTINGS as BrowserSettings,
defaultValue: DEFAULT_BROWSER_SETTINGS,
transform: (v: any) => ({ ...DEFAULT_BROWSER_SETTINGS, ...v }),
},
dictationSettings: {
type: DEFAULT_DICTATION_SETTINGS as DictationSettings,
defaultValue: DEFAULT_DICTATION_SETTINGS,
transform: (v: any) => ({ ...DEFAULT_DICTATION_SETTINGS, ...v }),
},
focusChainSettings: { type: DEFAULT_FOCUS_CHAIN_SETTINGS as FocusChainSettings, defaultValue: DEFAULT_FOCUS_CHAIN_SETTINGS },
// Toggles and Rules
globalClineRulesToggles: { type: {} as ClineRulesToggles, defaultValue: {} as ClineRulesToggles },
globalWorkflowToggles: { type: {} as ClineRulesToggles, defaultValue: {} as ClineRulesToggles },
// General Settings
telemetrySetting: { type: "unset" as TelemetrySetting, defaultValue: "unset" as TelemetrySetting },
planActSeparateModelsSetting: { type: false as boolean, defaultValue: false, isComputed: true },
enableCheckpointsSetting: { type: true as boolean, defaultValue: true },
requestTimeoutMs: { type: undefined as number | undefined },
shellIntegrationTimeout: { type: 4000 as number, defaultValue: 4000 },
defaultTerminalProfile: { type: "default" as string, defaultValue: "default" },
terminalOutputLineLimit: { type: 500 as number, defaultValue: 500 },
// SAP AI Core
sapAiCoreTokenUrl: { type: undefined as string | undefined },
sapAiCoreBaseUrl: { type: undefined as string | undefined },
sapAiResourceGroup: { type: undefined as string | undefined },
sapAiCoreUseOrchestrationMode: { type: true as boolean | undefined, defaultValue: true },
// Paths
claudeCodePath: { type: undefined as string | undefined },
qwenCodeOauthPath: { type: undefined as string | undefined },
// Mode Settings
strictPlanModeEnabled: { type: true as boolean, defaultValue: true },
yoloModeToggled: { type: false as boolean, defaultValue: false },
useAutoCondense: { type: false as boolean, defaultValue: false },
preferredLanguage: { type: "English" as string, defaultValue: "English" },
openaiReasoningEffort: { type: "medium" as OpenaiReasoningEffort, defaultValue: "medium" as OpenaiReasoningEffort },
mode: { type: "act" as Mode, defaultValue: "act" as Mode },
customPrompt: { type: undefined as "compact" | undefined },
autoCondenseThreshold: { type: 0.75 as number | undefined, defaultValue: 0.75 },
// Plan Mode Configurations
planModeApiProvider: { type: "openrouter" as ApiProvider, defaultValue: "openrouter" as ApiProvider },
planModeApiModelId: { type: undefined as string | undefined },
planModeThinkingBudgetTokens: { type: undefined as number | undefined },
planModeReasoningEffort: { type: undefined as string | undefined },
planModeVsCodeLmModelSelector: { type: undefined as LanguageModelChatSelector | undefined },
planModeAwsBedrockCustomSelected: { type: undefined as boolean | undefined },
planModeAwsBedrockCustomModelBaseId: { type: undefined as string | undefined },
planModeOpenRouterModelId: { type: undefined as string | undefined },
planModeOpenRouterModelInfo: { type: undefined as ModelInfo | undefined },
planModeOpenAiModelId: { type: undefined as string | undefined },
planModeOpenAiModelInfo: { type: undefined as ModelInfo | undefined },
planModeOllamaModelId: { type: undefined as string | undefined },
planModeLmStudioModelId: { type: undefined as string | undefined },
planModeLiteLlmModelId: { type: undefined as string | undefined },
planModeLiteLlmModelInfo: { type: undefined as ModelInfo | undefined },
planModeRequestyModelId: { type: undefined as string | undefined },
planModeRequestyModelInfo: { type: undefined as ModelInfo | undefined },
planModeTogetherModelId: { type: undefined as string | undefined },
planModeFireworksModelId: { type: fireworksDefaultModelId as string | undefined, defaultValue: fireworksDefaultModelId },
planModeSapAiCoreModelId: { type: undefined as string | undefined },
planModeSapAiCoreDeploymentId: { type: undefined as string | undefined },
planModeGroqModelId: { type: undefined as string | undefined },
planModeGroqModelInfo: { type: undefined as ModelInfo | undefined },
planModeBasetenModelId: { type: undefined as string | undefined },
planModeBasetenModelInfo: { type: undefined as ModelInfo | undefined },
planModeHuggingFaceModelId: { type: undefined as string | undefined },
planModeHuggingFaceModelInfo: { type: undefined as ModelInfo | undefined },
planModeHuaweiCloudMaasModelId: { type: undefined as string | undefined },
planModeHuaweiCloudMaasModelInfo: { type: undefined as ModelInfo | undefined },
planModeVercelAiGatewayModelId: { type: undefined as string | undefined },
planModeVercelAiGatewayModelInfo: { type: undefined as ModelInfo | undefined },
planModeOcaModelId: { type: undefined as string | undefined },
planModeOcaModelInfo: { type: undefined as OcaModelInfo | undefined },
// Act Mode Configurations
actModeApiProvider: { type: "openrouter" as ApiProvider, defaultValue: "openrouter" as ApiProvider },
actModeApiModelId: { type: undefined as string | undefined },
actModeThinkingBudgetTokens: { type: undefined as number | undefined },
actModeReasoningEffort: { type: undefined as string | undefined },
actModeVsCodeLmModelSelector: { type: undefined as LanguageModelChatSelector | undefined },
actModeAwsBedrockCustomSelected: { type: undefined as boolean | undefined },
actModeAwsBedrockCustomModelBaseId: { type: undefined as string | undefined },
actModeOpenRouterModelId: { type: undefined as string | undefined },
actModeOpenRouterModelInfo: { type: undefined as ModelInfo | undefined },
actModeOpenAiModelId: { type: undefined as string | undefined },
actModeOpenAiModelInfo: { type: undefined as ModelInfo | undefined },
actModeOllamaModelId: { type: undefined as string | undefined },
actModeLmStudioModelId: { type: undefined as string | undefined },
actModeLiteLlmModelId: { type: undefined as string | undefined },
actModeLiteLlmModelInfo: { type: undefined as ModelInfo | undefined },
actModeRequestyModelId: { type: undefined as string | undefined },
actModeRequestyModelInfo: { type: undefined as ModelInfo | undefined },
actModeTogetherModelId: { type: undefined as string | undefined },
actModeFireworksModelId: { type: fireworksDefaultModelId as string | undefined, defaultValue: fireworksDefaultModelId },
actModeSapAiCoreModelId: { type: undefined as string | undefined },
actModeSapAiCoreDeploymentId: { type: undefined as string | undefined },
actModeGroqModelId: { type: undefined as string | undefined },
actModeGroqModelInfo: { type: undefined as ModelInfo | undefined },
actModeBasetenModelId: { type: undefined as string | undefined },
actModeBasetenModelInfo: { type: undefined as ModelInfo | undefined },
actModeHuggingFaceModelId: { type: undefined as string | undefined },
actModeHuggingFaceModelInfo: { type: undefined as ModelInfo | undefined },
actModeHuaweiCloudMaasModelId: { type: undefined as string | undefined },
actModeHuaweiCloudMaasModelInfo: { type: undefined as ModelInfo | undefined },
actModeVercelAiGatewayModelId: { type: undefined as string | undefined },
actModeVercelAiGatewayModelInfo: { type: undefined as ModelInfo | undefined },
actModeOcaModelId: { type: undefined as string | undefined },
actModeOcaModelInfo: { type: undefined as OcaModelInfo | undefined },
} as const
// ============================================================================
// GENERATED TYPES - Auto-generated from property definitions
// ============================================================================
type ExtractType<T> = T extends { type: infer U } ? U : never
type BuildInterface<T extends Record<string, { type: any }>> = { [K in keyof T]: ExtractType<T[K]> }
export type GlobalState = BuildInterface<typeof GLOBAL_STATE_PROPS>
export type Settings = BuildInterface<typeof SETTINGS_PROPS>
export type GlobalStateAndSettings = GlobalState & Settings
export interface GlobalState {
lastShownAnnouncementId: string | undefined
taskHistory: HistoryItem[]
userInfo: UserInfo | undefined
mcpMarketplaceCatalog: McpMarketplaceCatalog | undefined
favoritedModelIds: string[]
mcpMarketplaceEnabled: boolean
mcpResponsesCollapsed: boolean
terminalReuseEnabled: boolean
isNewUser: boolean
welcomeViewCompleted: boolean | undefined
mcpDisplayMode: McpDisplayMode
// Multi-root workspace support
workspaceRoots: WorkspaceRoot[] | undefined
primaryRootIndex: number
multiRootEnabled: boolean
// ============================================================================
// GENERATED DEFAULTS - Auto-generated from property definitions
// ============================================================================
function extractDefaults<T extends Record<string, any>>(props: T): Partial<BuildInterface<T>> {
return Object.fromEntries(
Object.entries(props)
.filter(([_, prop]) => "defaultValue" in prop && prop.defaultValue !== undefined)
.map(([key, prop]) => [key, prop.defaultValue]),
) as Partial<BuildInterface<T>>
}
export interface Settings {
awsRegion: string | undefined
awsUseCrossRegionInference: boolean | undefined
awsBedrockUsePromptCache: boolean | undefined
awsBedrockEndpoint: string | undefined
awsProfile: string | undefined
awsAuthentication: string | undefined
awsUseProfile: boolean | undefined
vertexProjectId: string | undefined
vertexRegion: string | undefined
requestyBaseUrl: string | undefined
openAiBaseUrl: string | undefined
openAiHeaders: Record<string, string>
ollamaBaseUrl: string | undefined
ollamaApiOptionsCtxNum: string | undefined
lmStudioBaseUrl: string | undefined
lmStudioMaxTokens: string | undefined
anthropicBaseUrl: string | undefined
geminiBaseUrl: string | undefined
azureApiVersion: string | undefined
openRouterProviderSorting: string | undefined
autoApprovalSettings: AutoApprovalSettings
globalClineRulesToggles: ClineRulesToggles
globalWorkflowToggles: ClineRulesToggles
browserSettings: BrowserSettings
liteLlmBaseUrl: string | undefined
liteLlmUsePromptCache: boolean | undefined
fireworksModelMaxCompletionTokens: number | undefined
fireworksModelMaxTokens: number | undefined
qwenApiLine: string | undefined
moonshotApiLine: string | undefined
zaiApiLine: string | undefined
telemetrySetting: TelemetrySetting
asksageApiUrl: string | undefined
planActSeparateModelsSetting: boolean
enableCheckpointsSetting: boolean
requestTimeoutMs: number | undefined
shellIntegrationTimeout: number
defaultTerminalProfile: string
terminalOutputLineLimit: number
sapAiCoreTokenUrl: string | undefined
sapAiCoreBaseUrl: string | undefined
sapAiResourceGroup: string | undefined
sapAiCoreUseOrchestrationMode: boolean | undefined
claudeCodePath: string | undefined
qwenCodeOauthPath: string | undefined
strictPlanModeEnabled: boolean
yoloModeToggled: boolean
useAutoCondense: boolean
preferredLanguage: string
openaiReasoningEffort: OpenaiReasoningEffort
mode: Mode
dictationSettings: DictationSettings
focusChainSettings: FocusChainSettings
customPrompt: "compact" | undefined
difyBaseUrl: string | undefined
autoCondenseThreshold: number | undefined // number from 0 to 1
ocaBaseUrl: string | undefined
export const GLOBAL_STATE_DEFAULTS = extractDefaults(GLOBAL_STATE_PROPS)
export const SETTINGS_DEFAULTS = extractDefaults(SETTINGS_PROPS)
// Plan mode configurations
planModeApiProvider: ApiProvider
planModeApiModelId: string | undefined
planModeThinkingBudgetTokens: number | undefined
planModeReasoningEffort: string | undefined
planModeVsCodeLmModelSelector: LanguageModelChatSelector | undefined
planModeAwsBedrockCustomSelected: boolean | undefined
planModeAwsBedrockCustomModelBaseId: string | undefined
planModeOpenRouterModelId: string | undefined
planModeOpenRouterModelInfo: ModelInfo | undefined
planModeOpenAiModelId: string | undefined
planModeOpenAiModelInfo: ModelInfo | undefined
planModeOllamaModelId: string | undefined
planModeLmStudioModelId: string | undefined
planModeLiteLlmModelId: string | undefined
planModeLiteLlmModelInfo: ModelInfo | undefined
planModeRequestyModelId: string | undefined
planModeRequestyModelInfo: ModelInfo | undefined
planModeTogetherModelId: string | undefined
planModeFireworksModelId: string | undefined
planModeSapAiCoreModelId: string | undefined
planModeSapAiCoreDeploymentId: string | undefined
planModeGroqModelId: string | undefined
planModeGroqModelInfo: ModelInfo | undefined
planModeBasetenModelId: string | undefined
planModeBasetenModelInfo: ModelInfo | undefined
planModeHuggingFaceModelId: string | undefined
planModeHuggingFaceModelInfo: ModelInfo | undefined
planModeHuaweiCloudMaasModelId: string | undefined
planModeHuaweiCloudMaasModelInfo: ModelInfo | undefined
planModeOcaModelId: string | undefined
planModeOcaModelInfo: OcaModelInfo | undefined
// Act mode configurations
actModeApiProvider: ApiProvider
actModeApiModelId: string | undefined
actModeThinkingBudgetTokens: number | undefined
actModeReasoningEffort: string | undefined
actModeVsCodeLmModelSelector: LanguageModelChatSelector | undefined
actModeAwsBedrockCustomSelected: boolean | undefined
actModeAwsBedrockCustomModelBaseId: string | undefined
actModeOpenRouterModelId: string | undefined
actModeOpenRouterModelInfo: ModelInfo | undefined
actModeOpenAiModelId: string | undefined
actModeOpenAiModelInfo: ModelInfo | undefined
actModeOllamaModelId: string | undefined
actModeLmStudioModelId: string | undefined
actModeLiteLlmModelId: string | undefined
actModeLiteLlmModelInfo: ModelInfo | undefined
actModeRequestyModelId: string | undefined
actModeRequestyModelInfo: ModelInfo | undefined
actModeTogetherModelId: string | undefined
actModeFireworksModelId: string | undefined
actModeSapAiCoreModelId: string | undefined
actModeSapAiCoreDeploymentId: string | undefined
actModeGroqModelId: string | undefined
actModeGroqModelInfo: ModelInfo | undefined
actModeBasetenModelId: string | undefined
actModeBasetenModelInfo: ModelInfo | undefined
actModeHuggingFaceModelId: string | undefined
actModeHuggingFaceModelInfo: ModelInfo | undefined
actModeHuaweiCloudMaasModelId: string | undefined
actModeHuaweiCloudMaasModelInfo: ModelInfo | undefined
planModeVercelAiGatewayModelId: string | undefined
planModeVercelAiGatewayModelInfo: ModelInfo | undefined
actModeVercelAiGatewayModelId: string | undefined
actModeVercelAiGatewayModelInfo: ModelInfo | undefined
actModeOcaModelId: string | undefined
actModeOcaModelInfo: OcaModelInfo | undefined
// ============================================================================
// GENERATED METADATA - Auto-generated from property definitions
// ============================================================================
function extractTransforms<T extends Record<string, any>>(props: T): Record<string, (value: any) => any> {
return Object.fromEntries(
Object.entries(props)
.filter(([_, prop]) => "transform" in prop && prop.transform !== undefined)
.map(([key, prop]) => [key, prop.transform]),
)
}
export interface Secrets {
apiKey: string | undefined
clineAccountId: string | undefined
openRouterApiKey: string | undefined
awsAccessKey: string | undefined
awsSecretKey: string | undefined
awsSessionToken: string | undefined
awsBedrockApiKey: string | undefined
openAiApiKey: string | undefined
geminiApiKey: string | undefined
openAiNativeApiKey: string | undefined
ollamaApiKey: string | undefined
deepSeekApiKey: string | undefined
requestyApiKey: string | undefined
togetherApiKey: string | undefined
fireworksApiKey: string | undefined
qwenApiKey: string | undefined
doubaoApiKey: string | undefined
mistralApiKey: string | undefined
liteLlmApiKey: string | undefined
authNonce: string | undefined
asksageApiKey: string | undefined
xaiApiKey: string | undefined
moonshotApiKey: string | undefined
zaiApiKey: string | undefined
huggingFaceApiKey: string | undefined
nebiusApiKey: string | undefined
sambanovaApiKey: string | undefined
cerebrasApiKey: string | undefined
sapAiCoreClientId: string | undefined
sapAiCoreClientSecret: string | undefined
groqApiKey: string | undefined
huaweiCloudMaasApiKey: string | undefined
basetenApiKey: string | undefined
vercelAiGatewayApiKey: string | undefined
difyApiKey: string | undefined
ocaApiKey: string | undefined
ocaRefreshToken: string | undefined
function extractMetadata<T extends Record<string, any>>(props: T, field: string): Set<string> {
return new Set(
Object.entries(props)
.filter(([_, prop]) => field in prop && prop[field] === true)
.map(([key]) => key),
)
}
export interface LocalState {
localClineRulesToggles: ClineRulesToggles
localCursorRulesToggles: ClineRulesToggles
localWindsurfRulesToggles: ClineRulesToggles
workflowToggles: ClineRulesToggles
export const SETTINGS_TRANSFORMS = extractTransforms(SETTINGS_PROPS)
export const ASYNC_PROPERTIES = extractMetadata({ ...GLOBAL_STATE_PROPS, ...SETTINGS_PROPS }, "isAsync")
export const COMPUTED_PROPERTIES = extractMetadata({ ...GLOBAL_STATE_PROPS, ...SETTINGS_PROPS }, "isComputed")
// ============================================================================
// GENERATED KEYS AND LOOKUP SETS - Auto-generated from property definitions
// ============================================================================
export const GlobalStateKeys = new Set(Object.keys(GLOBAL_STATE_PROPS))
export const SettingsKeys = new Set(Object.keys(SETTINGS_PROPS))
// ============================================================================
// SECRET KEYS AND LOCAL STATE - Static definitions
// ============================================================================
export const ApiHandlerSecretsKeys = [
"apiKey",
"clineAccountId",
"openRouterApiKey",
"awsAccessKey",
"awsSecretKey",
"awsSessionToken",
"awsBedrockApiKey",
"openAiApiKey",
"geminiApiKey",
"openAiNativeApiKey",
"ollamaApiKey",
"deepSeekApiKey",
"requestyApiKey",
"togetherApiKey",
"fireworksApiKey",
"qwenApiKey",
"doubaoApiKey",
"mistralApiKey",
"liteLlmApiKey",
"asksageApiKey",
"xaiApiKey",
"moonshotApiKey",
"zaiApiKey",
"huggingFaceApiKey",
"nebiusApiKey",
"sambanovaApiKey",
"cerebrasApiKey",
"sapAiCoreClientId",
"sapAiCoreClientSecret",
"groqApiKey",
"huaweiCloudMaasApiKey",
"basetenApiKey",
"vercelAiGatewayApiKey",
"difyApiKey",
] as const
const AuthSecretsKeys = ["authNonce", "ocaApiKey", "ocaRefreshToken"] as const
export const SecretKeys = [...ApiHandlerSecretsKeys, ...AuthSecretsKeys] as const
export const LocalStateKeys = [
"localClineRulesToggles",
"localCursorRulesToggles",
"localWindsurfRulesToggles",
"workflowToggles",
] as const
// ============================================================================
// TYPE ALIASES
// ============================================================================
export type Secrets = { [K in (typeof SecretKeys)[number]]: string | undefined }
export type ApiHandlerSecrets = { [K in (typeof ApiHandlerSecretsKeys)[number]]: string | undefined }
export type LocalState = { [K in (typeof LocalStateKeys)[number]]: ClineRulesToggles }
export type SecretKey = (typeof SecretKeys)[number]
export type ApiHandlerSecretKey = (typeof ApiHandlerSecretsKeys)[number]
export type GlobalStateKey = keyof GlobalState
export type LocalStateKey = keyof LocalState
export type SettingsKey = keyof Settings
export type GlobalStateAndSettingsKey = keyof GlobalStateAndSettings
// ============================================================================
// UTILITY FUNCTIONS
// ============================================================================
export const isGlobalStateKey = (key: string): key is GlobalStateKey => GlobalStateKeys.has(key)
export const isSettingsKey = (key: string): key is SettingsKey => SettingsKeys.has(key)
export const isSecretKey = (key: string): key is SecretKey => SecretKeys.includes(key as SecretKey)
export const isLocalStateKey = (key: string): key is LocalStateKey => LocalStateKeys.includes(key as LocalStateKey)
export const getDefaultValue = <K extends GlobalStateAndSettingsKey>(key: K): GlobalStateAndSettings[K] | undefined => {
return (GLOBAL_STATE_DEFAULTS as any)[key] ?? (SETTINGS_DEFAULTS as any)[key]
}
export const hasTransform = (key: string): boolean => key in SETTINGS_TRANSFORMS
export const applyTransform = <T>(key: string, value: T): T => {
const transform = SETTINGS_TRANSFORMS[key]
return transform ? transform(value) : value
}
export const isAsyncProperty = (key: string): boolean => ASYNC_PROPERTIES.has(key)
export const isComputedProperty = (key: string): boolean => COMPUTED_PROPERTIES.has(key)
@@ -0,0 +1,58 @@
import { ApiConfiguration } from "@shared/api"
import { ApiHandlerSecrets, ApiHandlerSecretsKeys, SecretKeys, Settings, SettingsKeys } from "../state-keys"
/**
* Helper functions to automatically categorize ApiConfiguration keys based on optimized state definitions
* This ensures we only need to maintain keys in one place (state-keys.ts)
*/
// Convert SecretKeys array to Set for faster lookup
const SECRET_KEYS = new Set(SecretKeys)
/**
* Categorizes ApiConfiguration keys into settings and secrets based on optimized state definitions
*/
export function categorizeApiConfigurationKeys(apiConfiguration: Partial<ApiConfiguration>): {
settingsUpdates: Partial<Settings>
secretsUpdates: Partial<ApiHandlerSecrets>
} {
const settingsUpdates: Partial<Settings> = {}
const secretsUpdates: Partial<ApiHandlerSecrets> = {}
// Iterate through all keys in the ApiConfiguration
for (const [key, value] of Object.entries(apiConfiguration)) {
if (value === undefined) {
continue // Skip undefined values
}
if (SECRET_KEYS.has(key as any)) {
// This is a secret key
;(secretsUpdates as any)[key] = value
} else if (SettingsKeys.has(key)) {
// This is a settings key
;(settingsUpdates as any)[key] = value
}
// If key is neither in secrets nor settings, it's ignored (shouldn't happen with proper typing)
}
return { settingsUpdates, secretsUpdates }
}
/**
* Type-safe helper to get all API configuration keys that should be stored as settings
*/
export function getApiConfigurationSettingsKeys(): (keyof Settings)[] {
return Array.from(SettingsKeys).filter(
(_key) =>
// Only include keys that could be part of ApiConfiguration
// This is a type-safe way to ensure we only get relevant keys
true,
) as (keyof Settings)[]
}
/**
* Type-safe helper to get all API configuration keys that should be stored as secrets
*/
export function getApiConfigurationSecretKeys(): (keyof ApiHandlerSecrets)[] {
return [...ApiHandlerSecretsKeys]
}
+101 -581
View File
@@ -1,575 +1,131 @@
import { ApiProvider, fireworksDefaultModelId, type OcaModelInfo } from "@shared/api"
import { ApiProvider } from "@shared/api"
import { ExtensionContext } from "vscode"
import { Controller } from "@/core/controller"
import { DEFAULT_AUTO_APPROVAL_SETTINGS } from "@/shared/AutoApprovalSettings"
import { DEFAULT_BROWSER_SETTINGS } from "@/shared/BrowserSettings"
import { ClineRulesToggles } from "@/shared/cline-rules"
import { DEFAULT_DICTATION_SETTINGS, DictationSettings } from "@/shared/DictationSettings"
import { DEFAULT_FOCUS_CHAIN_SETTINGS } from "@/shared/FocusChainSettings"
import { DEFAULT_MCP_DISPLAY_MODE } from "@/shared/McpDisplayMode"
import { OpenaiReasoningEffort } from "@/shared/storage/types"
import { readTaskHistoryFromState } from "../disk"
import { GlobalStateAndSettings, LocalState, SecretKey, Secrets } from "../state-keys"
export async function readSecretsFromDisk(context: ExtensionContext): Promise<Secrets> {
const [
apiKey,
openRouterApiKey,
clineAccountId,
awsAccessKey,
awsSecretKey,
awsSessionToken,
awsBedrockApiKey,
openAiApiKey,
geminiApiKey,
openAiNativeApiKey,
deepSeekApiKey,
requestyApiKey,
togetherApiKey,
qwenApiKey,
doubaoApiKey,
mistralApiKey,
fireworksApiKey,
liteLlmApiKey,
asksageApiKey,
xaiApiKey,
sambanovaApiKey,
cerebrasApiKey,
groqApiKey,
moonshotApiKey,
nebiusApiKey,
huggingFaceApiKey,
sapAiCoreClientId,
sapAiCoreClientSecret,
huaweiCloudMaasApiKey,
basetenApiKey,
zaiApiKey,
ollamaApiKey,
vercelAiGatewayApiKey,
difyApiKey,
authNonce,
ocaApiKey,
ocaRefreshToken,
] = await Promise.all([
context.secrets.get("apiKey") as Promise<Secrets["apiKey"]>,
context.secrets.get("openRouterApiKey") as Promise<Secrets["openRouterApiKey"]>,
context.secrets.get("clineAccountId") as Promise<Secrets["clineAccountId"]>,
context.secrets.get("awsAccessKey") as Promise<Secrets["awsAccessKey"]>,
context.secrets.get("awsSecretKey") as Promise<Secrets["awsSecretKey"]>,
context.secrets.get("awsSessionToken") as Promise<Secrets["awsSessionToken"]>,
context.secrets.get("awsBedrockApiKey") as Promise<Secrets["awsBedrockApiKey"]>,
context.secrets.get("openAiApiKey") as Promise<Secrets["openAiApiKey"]>,
context.secrets.get("geminiApiKey") as Promise<Secrets["geminiApiKey"]>,
context.secrets.get("openAiNativeApiKey") as Promise<Secrets["openAiNativeApiKey"]>,
context.secrets.get("deepSeekApiKey") as Promise<Secrets["deepSeekApiKey"]>,
context.secrets.get("requestyApiKey") as Promise<Secrets["requestyApiKey"]>,
context.secrets.get("togetherApiKey") as Promise<Secrets["togetherApiKey"]>,
context.secrets.get("qwenApiKey") as Promise<Secrets["qwenApiKey"]>,
context.secrets.get("doubaoApiKey") as Promise<Secrets["doubaoApiKey"]>,
context.secrets.get("mistralApiKey") as Promise<Secrets["mistralApiKey"]>,
context.secrets.get("fireworksApiKey") as Promise<Secrets["fireworksApiKey"]>,
context.secrets.get("liteLlmApiKey") as Promise<Secrets["liteLlmApiKey"]>,
context.secrets.get("asksageApiKey") as Promise<Secrets["asksageApiKey"]>,
context.secrets.get("xaiApiKey") as Promise<Secrets["xaiApiKey"]>,
context.secrets.get("sambanovaApiKey") as Promise<Secrets["sambanovaApiKey"]>,
context.secrets.get("cerebrasApiKey") as Promise<Secrets["cerebrasApiKey"]>,
context.secrets.get("groqApiKey") as Promise<Secrets["groqApiKey"]>,
context.secrets.get("moonshotApiKey") as Promise<Secrets["moonshotApiKey"]>,
context.secrets.get("nebiusApiKey") as Promise<Secrets["nebiusApiKey"]>,
context.secrets.get("huggingFaceApiKey") as Promise<Secrets["huggingFaceApiKey"]>,
context.secrets.get("sapAiCoreClientId") as Promise<Secrets["sapAiCoreClientId"]>,
context.secrets.get("sapAiCoreClientSecret") as Promise<Secrets["sapAiCoreClientSecret"]>,
context.secrets.get("huaweiCloudMaasApiKey") as Promise<Secrets["huaweiCloudMaasApiKey"]>,
context.secrets.get("basetenApiKey") as Promise<Secrets["basetenApiKey"]>,
context.secrets.get("zaiApiKey") as Promise<Secrets["zaiApiKey"]>,
context.secrets.get("ollamaApiKey") as Promise<Secrets["ollamaApiKey"]>,
context.secrets.get("vercelAiGatewayApiKey") as Promise<Secrets["vercelAiGatewayApiKey"]>,
context.secrets.get("difyApiKey") as Promise<Secrets["difyApiKey"]>,
context.secrets.get("authNonce") as Promise<Secrets["authNonce"]>,
context.secrets.get("ocaApiKey") as Promise<string | undefined>,
context.secrets.get("ocaRefreshToken") as Promise<string | undefined>,
])
import {
applyTransform,
GlobalStateAndSettings,
GlobalStateKeys,
getDefaultValue,
isAsyncProperty,
isComputedProperty,
LocalState,
LocalStateKeys,
SecretKeys,
Secrets,
SettingsKeys,
} from "../state-keys"
return {
authNonce,
apiKey,
openRouterApiKey,
clineAccountId,
huggingFaceApiKey,
huaweiCloudMaasApiKey,
basetenApiKey,
zaiApiKey,
ollamaApiKey,
vercelAiGatewayApiKey,
difyApiKey,
sapAiCoreClientId,
sapAiCoreClientSecret,
xaiApiKey,
sambanovaApiKey,
cerebrasApiKey,
groqApiKey,
moonshotApiKey,
nebiusApiKey,
asksageApiKey,
fireworksApiKey,
liteLlmApiKey,
doubaoApiKey,
mistralApiKey,
openAiNativeApiKey,
deepSeekApiKey,
requestyApiKey,
togetherApiKey,
qwenApiKey,
geminiApiKey,
openAiApiKey,
awsBedrockApiKey,
awsAccessKey,
awsSecretKey,
awsSessionToken,
ocaApiKey,
ocaRefreshToken,
}
/**
* Get all state keys for batch processing
*/
const GlobalStateAndSettingKeys = [...GlobalStateKeys, ...SettingsKeys] as Array<keyof GlobalStateAndSettings>
export async function readSecretsFromDisk(context: ExtensionContext): Promise<Secrets> {
const secrets = await Promise.all(SecretKeys.map((key) => context.secrets.get(key)))
return SecretKeys.reduce((acc, key, index) => {
acc[key] = secrets[index]
return acc
}, {} as Secrets)
}
export async function readWorkspaceStateFromDisk(context: ExtensionContext): Promise<LocalState> {
const localClineRulesToggles = context.workspaceState.get("localClineRulesToggles") as ClineRulesToggles | undefined
const localWindsurfRulesToggles = context.workspaceState.get("localWindsurfRulesToggles") as ClineRulesToggles | undefined
const localCursorRulesToggles = context.workspaceState.get("localCursorRulesToggles") as ClineRulesToggles | undefined
const localWorkflowToggles = context.workspaceState.get("workflowToggles") as ClineRulesToggles | undefined
const states = LocalStateKeys.map((key) => context.workspaceState.get<ClineRulesToggles | undefined>(key))
return {
localClineRulesToggles: localClineRulesToggles || {},
localWindsurfRulesToggles: localWindsurfRulesToggles || {},
localCursorRulesToggles: localCursorRulesToggles || {},
workflowToggles: localWorkflowToggles || {},
}
return LocalStateKeys.reduce((acc, key, index) => {
acc[key] = states[index] || {}
return acc
}, {} as LocalState)
}
export async function readGlobalStateFromDisk(context: ExtensionContext): Promise<GlobalStateAndSettings> {
try {
// Get all global state values
const strictPlanModeEnabled =
context.globalState.get<GlobalStateAndSettings["strictPlanModeEnabled"]>("strictPlanModeEnabled")
const yoloModeToggled = context.globalState.get<GlobalStateAndSettings["yoloModeToggled"]>("yoloModeToggled")
const useAutoCondense = context.globalState.get<GlobalStateAndSettings["useAutoCondense"]>("useAutoCondense")
const isNewUser = context.globalState.get<GlobalStateAndSettings["isNewUser"]>("isNewUser")
const welcomeViewCompleted =
context.globalState.get<GlobalStateAndSettings["welcomeViewCompleted"]>("welcomeViewCompleted")
const awsRegion = context.globalState.get<GlobalStateAndSettings["awsRegion"]>("awsRegion")
const awsUseCrossRegionInference =
context.globalState.get<GlobalStateAndSettings["awsUseCrossRegionInference"]>("awsUseCrossRegionInference")
const awsBedrockUsePromptCache =
context.globalState.get<GlobalStateAndSettings["awsBedrockUsePromptCache"]>("awsBedrockUsePromptCache")
const awsBedrockEndpoint = context.globalState.get<GlobalStateAndSettings["awsBedrockEndpoint"]>("awsBedrockEndpoint")
const awsProfile = context.globalState.get<GlobalStateAndSettings["awsProfile"]>("awsProfile")
const awsUseProfile = context.globalState.get<GlobalStateAndSettings["awsUseProfile"]>("awsUseProfile")
const awsAuthentication = context.globalState.get<GlobalStateAndSettings["awsAuthentication"]>("awsAuthentication")
const vertexProjectId = context.globalState.get<GlobalStateAndSettings["vertexProjectId"]>("vertexProjectId")
const vertexRegion = context.globalState.get<GlobalStateAndSettings["vertexRegion"]>("vertexRegion")
const openAiBaseUrl = context.globalState.get<GlobalStateAndSettings["openAiBaseUrl"]>("openAiBaseUrl")
const requestyBaseUrl = context.globalState.get<GlobalStateAndSettings["requestyBaseUrl"]>("requestyBaseUrl")
const openAiHeaders = context.globalState.get<GlobalStateAndSettings["openAiHeaders"]>("openAiHeaders")
const ollamaBaseUrl = context.globalState.get<GlobalStateAndSettings["ollamaBaseUrl"]>("ollamaBaseUrl")
const ollamaApiOptionsCtxNum =
context.globalState.get<GlobalStateAndSettings["ollamaApiOptionsCtxNum"]>("ollamaApiOptionsCtxNum")
const lmStudioBaseUrl = context.globalState.get<GlobalStateAndSettings["lmStudioBaseUrl"]>("lmStudioBaseUrl")
const lmStudioMaxTokens = context.globalState.get<GlobalStateAndSettings["lmStudioMaxTokens"]>("lmStudioMaxTokens")
const anthropicBaseUrl = context.globalState.get<GlobalStateAndSettings["anthropicBaseUrl"]>("anthropicBaseUrl")
const geminiBaseUrl = context.globalState.get<GlobalStateAndSettings["geminiBaseUrl"]>("geminiBaseUrl")
const azureApiVersion = context.globalState.get<GlobalStateAndSettings["azureApiVersion"]>("azureApiVersion")
const openRouterProviderSorting =
context.globalState.get<GlobalStateAndSettings["openRouterProviderSorting"]>("openRouterProviderSorting")
const lastShownAnnouncementId =
context.globalState.get<GlobalStateAndSettings["lastShownAnnouncementId"]>("lastShownAnnouncementId")
const autoApprovalSettings =
context.globalState.get<GlobalStateAndSettings["autoApprovalSettings"]>("autoApprovalSettings")
const browserSettings = context.globalState.get<GlobalStateAndSettings["browserSettings"]>("browserSettings")
const liteLlmBaseUrl = context.globalState.get<GlobalStateAndSettings["liteLlmBaseUrl"]>("liteLlmBaseUrl")
const liteLlmUsePromptCache =
context.globalState.get<GlobalStateAndSettings["liteLlmUsePromptCache"]>("liteLlmUsePromptCache")
const fireworksModelMaxCompletionTokens = context.globalState.get<
GlobalStateAndSettings["fireworksModelMaxCompletionTokens"]
>("fireworksModelMaxCompletionTokens")
const fireworksModelMaxTokens =
context.globalState.get<GlobalStateAndSettings["fireworksModelMaxTokens"]>("fireworksModelMaxTokens")
const userInfo = context.globalState.get<GlobalStateAndSettings["userInfo"]>("userInfo")
const qwenApiLine = context.globalState.get<GlobalStateAndSettings["qwenApiLine"]>("qwenApiLine")
const moonshotApiLine = context.globalState.get<GlobalStateAndSettings["moonshotApiLine"]>("moonshotApiLine")
const zaiApiLine = context.globalState.get<GlobalStateAndSettings["zaiApiLine"]>("zaiApiLine")
const telemetrySetting = context.globalState.get<GlobalStateAndSettings["telemetrySetting"]>("telemetrySetting")
const asksageApiUrl = context.globalState.get<GlobalStateAndSettings["asksageApiUrl"]>("asksageApiUrl")
const planActSeparateModelsSettingRaw =
context.globalState.get<GlobalStateAndSettings["planActSeparateModelsSetting"]>("planActSeparateModelsSetting")
const favoritedModelIds = context.globalState.get<GlobalStateAndSettings["favoritedModelIds"]>("favoritedModelIds")
const globalClineRulesToggles =
context.globalState.get<GlobalStateAndSettings["globalClineRulesToggles"]>("globalClineRulesToggles")
const requestTimeoutMs = context.globalState.get<GlobalStateAndSettings["requestTimeoutMs"]>("requestTimeoutMs")
const shellIntegrationTimeout =
context.globalState.get<GlobalStateAndSettings["shellIntegrationTimeout"]>("shellIntegrationTimeout")
const enableCheckpointsSettingRaw =
context.globalState.get<GlobalStateAndSettings["enableCheckpointsSetting"]>("enableCheckpointsSetting")
const mcpMarketplaceEnabledRaw =
context.globalState.get<GlobalStateAndSettings["mcpMarketplaceEnabled"]>("mcpMarketplaceEnabled")
const mcpDisplayMode = context.globalState.get<GlobalStateAndSettings["mcpDisplayMode"]>("mcpDisplayMode")
const mcpResponsesCollapsedRaw =
context.globalState.get<GlobalStateAndSettings["mcpResponsesCollapsed"]>("mcpResponsesCollapsed")
const globalWorkflowToggles =
context.globalState.get<GlobalStateAndSettings["globalWorkflowToggles"]>("globalWorkflowToggles")
const terminalReuseEnabled =
context.globalState.get<GlobalStateAndSettings["terminalReuseEnabled"]>("terminalReuseEnabled")
const terminalOutputLineLimit =
context.globalState.get<GlobalStateAndSettings["terminalOutputLineLimit"]>("terminalOutputLineLimit")
const defaultTerminalProfile =
context.globalState.get<GlobalStateAndSettings["defaultTerminalProfile"]>("defaultTerminalProfile")
const sapAiCoreBaseUrl = context.globalState.get<GlobalStateAndSettings["sapAiCoreBaseUrl"]>("sapAiCoreBaseUrl")
const sapAiCoreTokenUrl = context.globalState.get<GlobalStateAndSettings["sapAiCoreTokenUrl"]>("sapAiCoreTokenUrl")
const sapAiResourceGroup = context.globalState.get<GlobalStateAndSettings["sapAiResourceGroup"]>("sapAiResourceGroup")
const claudeCodePath = context.globalState.get<GlobalStateAndSettings["claudeCodePath"]>("claudeCodePath")
const difyBaseUrl = context.globalState.get<GlobalStateAndSettings["difyBaseUrl"]>("difyBaseUrl")
const ocaBaseUrl = context.globalState.get("ocaBaseUrl") as string | undefined
const openaiReasoningEffort =
context.globalState.get<GlobalStateAndSettings["openaiReasoningEffort"]>("openaiReasoningEffort")
const preferredLanguage = context.globalState.get<GlobalStateAndSettings["preferredLanguage"]>("preferredLanguage")
const focusChainSettings = context.globalState.get<GlobalStateAndSettings["focusChainSettings"]>("focusChainSettings")
const dictationSettings = context.globalState.get<GlobalStateAndSettings["dictationSettings"]>("dictationSettings") as
| DictationSettings
| undefined
// Batch read all state values in a single optimized pass
const stateValues = new Map<string, any>()
const mcpMarketplaceCatalog =
context.globalState.get<GlobalStateAndSettings["mcpMarketplaceCatalog"]>("mcpMarketplaceCatalog")
const qwenCodeOauthPath = context.globalState.get<GlobalStateAndSettings["qwenCodeOauthPath"]>("qwenCodeOauthPath")
const customPrompt = context.globalState.get<GlobalStateAndSettings["customPrompt"]>("customPrompt")
const autoCondenseThreshold =
context.globalState.get<GlobalStateAndSettings["autoCondenseThreshold"]>("autoCondenseThreshold") // number from 0 to 1
// Get mode-related configurations
const mode = context.globalState.get<GlobalStateAndSettings["mode"]>("mode")
// Plan mode configurations
const planModeApiProvider = context.globalState.get<GlobalStateAndSettings["planModeApiProvider"]>("planModeApiProvider")
const planModeApiModelId = context.globalState.get<GlobalStateAndSettings["planModeApiModelId"]>("planModeApiModelId")
const planModeThinkingBudgetTokens =
context.globalState.get<GlobalStateAndSettings["planModeThinkingBudgetTokens"]>("planModeThinkingBudgetTokens")
const planModeReasoningEffort =
context.globalState.get<GlobalStateAndSettings["planModeReasoningEffort"]>("planModeReasoningEffort")
const planModeVsCodeLmModelSelector =
context.globalState.get<GlobalStateAndSettings["planModeVsCodeLmModelSelector"]>("planModeVsCodeLmModelSelector")
const planModeAwsBedrockCustomSelected = context.globalState.get<
GlobalStateAndSettings["planModeAwsBedrockCustomSelected"]
>("planModeAwsBedrockCustomSelected")
const planModeAwsBedrockCustomModelBaseId = context.globalState.get<
GlobalStateAndSettings["planModeAwsBedrockCustomModelBaseId"]
>("planModeAwsBedrockCustomModelBaseId")
const planModeOpenRouterModelId =
context.globalState.get<GlobalStateAndSettings["planModeOpenRouterModelId"]>("planModeOpenRouterModelId")
const planModeOpenRouterModelInfo =
context.globalState.get<GlobalStateAndSettings["planModeOpenRouterModelInfo"]>("planModeOpenRouterModelInfo")
const planModeOpenAiModelId =
context.globalState.get<GlobalStateAndSettings["planModeOpenAiModelId"]>("planModeOpenAiModelId")
const planModeOpenAiModelInfo =
context.globalState.get<GlobalStateAndSettings["planModeOpenAiModelInfo"]>("planModeOpenAiModelInfo")
const planModeOllamaModelId =
context.globalState.get<GlobalStateAndSettings["planModeOllamaModelId"]>("planModeOllamaModelId")
const planModeLmStudioModelId =
context.globalState.get<GlobalStateAndSettings["planModeLmStudioModelId"]>("planModeLmStudioModelId")
const planModeLiteLlmModelId =
context.globalState.get<GlobalStateAndSettings["planModeLiteLlmModelId"]>("planModeLiteLlmModelId")
const planModeLiteLlmModelInfo =
context.globalState.get<GlobalStateAndSettings["planModeLiteLlmModelInfo"]>("planModeLiteLlmModelInfo")
const planModeRequestyModelId =
context.globalState.get<GlobalStateAndSettings["planModeRequestyModelId"]>("planModeRequestyModelId")
const planModeRequestyModelInfo =
context.globalState.get<GlobalStateAndSettings["planModeRequestyModelInfo"]>("planModeRequestyModelInfo")
const planModeTogetherModelId =
context.globalState.get<GlobalStateAndSettings["planModeTogetherModelId"]>("planModeTogetherModelId")
const planModeFireworksModelId =
context.globalState.get<GlobalStateAndSettings["planModeFireworksModelId"]>("planModeFireworksModelId")
const planModeSapAiCoreModelId =
context.globalState.get<GlobalStateAndSettings["planModeSapAiCoreModelId"]>("planModeSapAiCoreModelId")
const planModeSapAiCoreDeploymentId =
context.globalState.get<GlobalStateAndSettings["planModeSapAiCoreDeploymentId"]>("planModeSapAiCoreDeploymentId")
const planModeGroqModelId = context.globalState.get<GlobalStateAndSettings["planModeGroqModelId"]>("planModeGroqModelId")
const planModeGroqModelInfo =
context.globalState.get<GlobalStateAndSettings["planModeGroqModelInfo"]>("planModeGroqModelInfo")
const planModeHuggingFaceModelId =
context.globalState.get<GlobalStateAndSettings["planModeHuggingFaceModelId"]>("planModeHuggingFaceModelId")
const planModeHuggingFaceModelInfo =
context.globalState.get<GlobalStateAndSettings["planModeHuggingFaceModelInfo"]>("planModeHuggingFaceModelInfo")
const planModeHuaweiCloudMaasModelId =
context.globalState.get<GlobalStateAndSettings["planModeHuaweiCloudMaasModelId"]>("planModeHuaweiCloudMaasModelId")
const planModeHuaweiCloudMaasModelInfo = context.globalState.get<
GlobalStateAndSettings["planModeHuaweiCloudMaasModelInfo"]
>("planModeHuaweiCloudMaasModelInfo")
const planModeBasetenModelId =
context.globalState.get<GlobalStateAndSettings["planModeBasetenModelId"]>("planModeBasetenModelId")
const planModeBasetenModelInfo =
context.globalState.get<GlobalStateAndSettings["planModeBasetenModelInfo"]>("planModeBasetenModelInfo")
const planModeVercelAiGatewayModelId =
context.globalState.get<GlobalStateAndSettings["planModeVercelAiGatewayModelId"]>("planModeVercelAiGatewayModelId")
const planModeVercelAiGatewayModelInfo = context.globalState.get<
GlobalStateAndSettings["planModeVercelAiGatewayModelInfo"]
>("planModeVercelAiGatewayModelInfo")
const planModeOcaModelId = context.globalState.get("planModeOcaModelId") as string | undefined
const planModeOcaModelInfo = context.globalState.get("planModeOcaModelInfo") as OcaModelInfo | undefined
// Act mode configurations
const actModeApiProvider = context.globalState.get<GlobalStateAndSettings["actModeApiProvider"]>("actModeApiProvider")
const actModeApiModelId = context.globalState.get<GlobalStateAndSettings["actModeApiModelId"]>("actModeApiModelId")
const actModeThinkingBudgetTokens =
context.globalState.get<GlobalStateAndSettings["actModeThinkingBudgetTokens"]>("actModeThinkingBudgetTokens")
const actModeReasoningEffort =
context.globalState.get<GlobalStateAndSettings["actModeReasoningEffort"]>("actModeReasoningEffort")
const actModeVsCodeLmModelSelector =
context.globalState.get<GlobalStateAndSettings["actModeVsCodeLmModelSelector"]>("actModeVsCodeLmModelSelector")
const actModeAwsBedrockCustomSelected = context.globalState.get<
GlobalStateAndSettings["actModeAwsBedrockCustomSelected"]
>("actModeAwsBedrockCustomSelected")
const actModeAwsBedrockCustomModelBaseId = context.globalState.get<
GlobalStateAndSettings["actModeAwsBedrockCustomModelBaseId"]
>("actModeAwsBedrockCustomModelBaseId")
const actModeOpenRouterModelId =
context.globalState.get<GlobalStateAndSettings["actModeOpenRouterModelId"]>("actModeOpenRouterModelId")
const actModeOpenRouterModelInfo =
context.globalState.get<GlobalStateAndSettings["actModeOpenRouterModelInfo"]>("actModeOpenRouterModelInfo")
const actModeOpenAiModelId =
context.globalState.get<GlobalStateAndSettings["actModeOpenAiModelId"]>("actModeOpenAiModelId")
const actModeOpenAiModelInfo =
context.globalState.get<GlobalStateAndSettings["actModeOpenAiModelInfo"]>("actModeOpenAiModelInfo")
const actModeOllamaModelId =
context.globalState.get<GlobalStateAndSettings["actModeOllamaModelId"]>("actModeOllamaModelId")
const actModeLmStudioModelId =
context.globalState.get<GlobalStateAndSettings["actModeLmStudioModelId"]>("actModeLmStudioModelId")
const actModeLiteLlmModelId =
context.globalState.get<GlobalStateAndSettings["actModeLiteLlmModelId"]>("actModeLiteLlmModelId")
const actModeLiteLlmModelInfo =
context.globalState.get<GlobalStateAndSettings["actModeLiteLlmModelInfo"]>("actModeLiteLlmModelInfo")
const actModeRequestyModelId =
context.globalState.get<GlobalStateAndSettings["actModeRequestyModelId"]>("actModeRequestyModelId")
const actModeRequestyModelInfo =
context.globalState.get<GlobalStateAndSettings["actModeRequestyModelInfo"]>("actModeRequestyModelInfo")
const actModeTogetherModelId =
context.globalState.get<GlobalStateAndSettings["actModeTogetherModelId"]>("actModeTogetherModelId")
const actModeFireworksModelId =
context.globalState.get<GlobalStateAndSettings["actModeFireworksModelId"]>("actModeFireworksModelId")
const actModeSapAiCoreModelId =
context.globalState.get<GlobalStateAndSettings["actModeSapAiCoreModelId"]>("actModeSapAiCoreModelId")
const actModeSapAiCoreDeploymentId =
context.globalState.get<GlobalStateAndSettings["actModeSapAiCoreDeploymentId"]>("actModeSapAiCoreDeploymentId")
const actModeGroqModelId = context.globalState.get<GlobalStateAndSettings["actModeGroqModelId"]>("actModeGroqModelId")
const actModeGroqModelInfo =
context.globalState.get<GlobalStateAndSettings["actModeGroqModelInfo"]>("actModeGroqModelInfo")
const actModeHuggingFaceModelId =
context.globalState.get<GlobalStateAndSettings["actModeHuggingFaceModelId"]>("actModeHuggingFaceModelId")
const actModeHuggingFaceModelInfo =
context.globalState.get<GlobalStateAndSettings["actModeHuggingFaceModelInfo"]>("actModeHuggingFaceModelInfo")
const actModeHuaweiCloudMaasModelId =
context.globalState.get<GlobalStateAndSettings["actModeHuaweiCloudMaasModelId"]>("actModeHuaweiCloudMaasModelId")
const actModeHuaweiCloudMaasModelInfo = context.globalState.get<
GlobalStateAndSettings["actModeHuaweiCloudMaasModelInfo"]
>("actModeHuaweiCloudMaasModelInfo")
const actModeBasetenModelId =
context.globalState.get<GlobalStateAndSettings["actModeBasetenModelId"]>("actModeBasetenModelId")
const actModeBasetenModelInfo =
context.globalState.get<GlobalStateAndSettings["actModeBasetenModelInfo"]>("actModeBasetenModelInfo")
const actModeVercelAiGatewayModelId =
context.globalState.get<GlobalStateAndSettings["actModeVercelAiGatewayModelId"]>("actModeVercelAiGatewayModelId")
const actModeVercelAiGatewayModelInfo = context.globalState.get<
GlobalStateAndSettings["actModeVercelAiGatewayModelInfo"]
>("actModeVercelAiGatewayModelInfo")
const actModeOcaModelId = context.globalState.get("actModeOcaModelId") as string | undefined
const actModeOcaModelInfo = context.globalState.get("actModeOcaModelInfo") as OcaModelInfo | undefined
const sapAiCoreUseOrchestrationMode =
context.globalState.get<GlobalStateAndSettings["sapAiCoreUseOrchestrationMode"]>("sapAiCoreUseOrchestrationMode")
let apiProvider: ApiProvider
if (planModeApiProvider) {
apiProvider = planModeApiProvider
} else {
// New users should default to openrouter, since they've opted to use an API key instead of signing in
apiProvider = "openrouter"
// Read all values at once for better performance
for (const key of GlobalStateAndSettingKeys) {
const value = context.globalState.get(key as string)
stateValues.set(key, value)
}
const mcpResponsesCollapsed = mcpResponsesCollapsedRaw ?? false
// Build result object with proper typing
const result = {} as any // Use any for assignment, but return proper type
// Plan/Act separate models setting is a boolean indicating whether the user wants to use different models for plan and act. Existing users expect this to be enabled, while we want new users to opt in to this being disabled by default.
// On win11 state sometimes initializes as empty string instead of undefined
let planActSeparateModelsSetting: boolean | undefined
if (planActSeparateModelsSettingRaw === true || planActSeparateModelsSettingRaw === false) {
planActSeparateModelsSetting = planActSeparateModelsSettingRaw
} else {
// default to true for existing users
if (planModeApiProvider) {
planActSeparateModelsSetting = true
} else {
// default to false for new users
planActSeparateModelsSetting = false
// Process each state property using optimized approach
for (const key of GlobalStateAndSettingKeys) {
const stateKey = key as keyof GlobalStateAndSettings
let value = stateValues.get(stateKey)
// Skip async properties - they need special handling
if (isAsyncProperty(stateKey)) {
continue
}
// Skip computed properties - they need special handling
if (isComputedProperty(stateKey)) {
continue
}
// Apply default value if needed
if (value === undefined) {
const defaultValue = getDefaultValue(stateKey)
if (defaultValue !== undefined) {
value = defaultValue
}
}
// Apply transformation if provided
if (value !== undefined) {
value = applyTransform(stateKey, value)
}
// Set the processed value
result[stateKey] = value
}
const taskHistory = await readTaskHistoryFromState(context)
// Handle computed properties with special logic
await handleComputedProperties(result, stateValues)
// Multi-root workspace support
const workspaceRoots = context.globalState.get<GlobalStateAndSettings["workspaceRoots"]>("workspaceRoots")
/**
* Get primary root index from global state.
* The primary root is the main workspace folder that Cline focuses on when dealing with
* multi-root workspaces. In VS Code, you can have multiple folders open in one workspace,
* and the primary root index indicates which folder (by its position in the array, 0-based)
* should be treated as the main/default working directory for operations.
*/
const primaryRootIndex = context.globalState.get<GlobalStateAndSettings["primaryRootIndex"]>("primaryRootIndex")
const multiRootEnabled = context.globalState.get<GlobalStateAndSettings["multiRootEnabled"]>("multiRootEnabled")
// Handle async properties
await handleAsyncProperties(result, context)
return {
// api configuration fields
claudeCodePath,
awsRegion,
awsUseCrossRegionInference,
awsBedrockUsePromptCache,
awsBedrockEndpoint,
awsProfile,
awsUseProfile,
awsAuthentication,
vertexProjectId,
vertexRegion,
openAiBaseUrl,
requestyBaseUrl,
openAiHeaders: openAiHeaders || {},
ollamaBaseUrl,
ollamaApiOptionsCtxNum,
lmStudioBaseUrl,
lmStudioMaxTokens,
anthropicBaseUrl,
geminiBaseUrl,
qwenApiLine,
moonshotApiLine,
zaiApiLine,
azureApiVersion,
openRouterProviderSorting,
liteLlmBaseUrl,
liteLlmUsePromptCache,
fireworksModelMaxCompletionTokens,
fireworksModelMaxTokens,
asksageApiUrl,
favoritedModelIds: favoritedModelIds || [],
requestTimeoutMs,
sapAiCoreBaseUrl,
sapAiCoreTokenUrl,
sapAiResourceGroup,
difyBaseUrl,
sapAiCoreUseOrchestrationMode: sapAiCoreUseOrchestrationMode ?? true,
ocaBaseUrl,
// Plan mode configurations
planModeApiProvider: planModeApiProvider || apiProvider,
planModeApiModelId,
planModeThinkingBudgetTokens,
planModeReasoningEffort,
planModeVsCodeLmModelSelector,
planModeAwsBedrockCustomSelected,
planModeAwsBedrockCustomModelBaseId,
planModeOpenRouterModelId,
planModeOpenRouterModelInfo,
planModeOpenAiModelId,
planModeOpenAiModelInfo,
planModeOllamaModelId,
planModeLmStudioModelId,
planModeLiteLlmModelId,
planModeLiteLlmModelInfo,
planModeRequestyModelId,
planModeRequestyModelInfo,
planModeTogetherModelId,
planModeFireworksModelId: planModeFireworksModelId || fireworksDefaultModelId,
planModeSapAiCoreModelId,
planModeSapAiCoreDeploymentId,
planModeGroqModelId,
planModeGroqModelInfo,
planModeHuggingFaceModelId,
planModeHuggingFaceModelInfo,
planModeHuaweiCloudMaasModelId,
planModeHuaweiCloudMaasModelInfo,
planModeBasetenModelId,
planModeBasetenModelInfo,
planModeVercelAiGatewayModelId,
planModeVercelAiGatewayModelInfo,
planModeOcaModelId,
planModeOcaModelInfo,
// Act mode configurations
actModeApiProvider: actModeApiProvider || apiProvider,
actModeApiModelId,
actModeThinkingBudgetTokens,
actModeReasoningEffort,
actModeVsCodeLmModelSelector,
actModeAwsBedrockCustomSelected,
actModeAwsBedrockCustomModelBaseId,
actModeOpenRouterModelId,
actModeOpenRouterModelInfo,
actModeOpenAiModelId,
actModeOpenAiModelInfo,
actModeOllamaModelId,
actModeLmStudioModelId,
actModeLiteLlmModelId,
actModeLiteLlmModelInfo,
actModeRequestyModelId,
actModeRequestyModelInfo,
actModeTogetherModelId,
actModeFireworksModelId: actModeFireworksModelId || fireworksDefaultModelId,
actModeSapAiCoreModelId,
actModeSapAiCoreDeploymentId,
actModeGroqModelId,
actModeGroqModelInfo,
actModeHuggingFaceModelId,
actModeHuggingFaceModelInfo,
actModeHuaweiCloudMaasModelId,
actModeHuaweiCloudMaasModelInfo,
actModeBasetenModelId,
actModeBasetenModelInfo,
actModeVercelAiGatewayModelId,
actModeVercelAiGatewayModelInfo,
actModeOcaModelId,
actModeOcaModelInfo,
// Other global fields
focusChainSettings: focusChainSettings || DEFAULT_FOCUS_CHAIN_SETTINGS,
dictationSettings: { ...DEFAULT_DICTATION_SETTINGS, ...dictationSettings },
strictPlanModeEnabled: strictPlanModeEnabled ?? true,
yoloModeToggled: yoloModeToggled ?? false,
useAutoCondense: useAutoCondense ?? false,
isNewUser: isNewUser ?? true,
welcomeViewCompleted,
lastShownAnnouncementId,
taskHistory: taskHistory || [],
autoApprovalSettings: autoApprovalSettings || DEFAULT_AUTO_APPROVAL_SETTINGS, // default value can be 0 or empty string
globalClineRulesToggles: globalClineRulesToggles || {},
browserSettings: { ...DEFAULT_BROWSER_SETTINGS, ...browserSettings }, // this will ensure that older versions of browserSettings (e.g. before remoteBrowserEnabled was added) are merged with the default values (false for remoteBrowserEnabled)
preferredLanguage: preferredLanguage || "English",
openaiReasoningEffort: (openaiReasoningEffort as OpenaiReasoningEffort) || "medium",
mode: mode || "act",
userInfo,
mcpMarketplaceEnabled: mcpMarketplaceEnabledRaw ?? true,
mcpDisplayMode: mcpDisplayMode ?? DEFAULT_MCP_DISPLAY_MODE,
mcpResponsesCollapsed: mcpResponsesCollapsed,
telemetrySetting: telemetrySetting || "unset",
planActSeparateModelsSetting: planActSeparateModelsSetting ?? false,
enableCheckpointsSetting: enableCheckpointsSettingRaw ?? true,
shellIntegrationTimeout: shellIntegrationTimeout || 4000,
terminalReuseEnabled: terminalReuseEnabled ?? true,
terminalOutputLineLimit: terminalOutputLineLimit ?? 500,
defaultTerminalProfile: defaultTerminalProfile ?? "default",
globalWorkflowToggles: globalWorkflowToggles || {},
mcpMarketplaceCatalog,
qwenCodeOauthPath,
customPrompt,
autoCondenseThreshold: autoCondenseThreshold || 0.75, // default to 0.75 if not set
// Multi-root workspace support
workspaceRoots,
primaryRootIndex: primaryRootIndex ?? 0,
// Feature flag - defaults to false
// For now, always return false to disable multi-root support by default
multiRootEnabled: multiRootEnabled ?? false,
}
return result as GlobalStateAndSettings
} catch (error) {
console.error("[StateHelpers] Failed to read global state:", error)
throw error
}
}
/**
* Handle properties that require computed logic
*/
async function handleComputedProperties(result: any, stateValues: Map<string, any>): Promise<void> {
// 1. API Provider logic - set defaults based on existing values
const defaultApiProvider: ApiProvider = "openrouter"
result.planModeApiProvider = result.planModeApiProvider || defaultApiProvider
result.actModeApiProvider = result.actModeApiProvider || defaultApiProvider
// 2. Plan/Act separate models setting with special logic
const planActSeparateModelsSettingRaw = stateValues.get("planActSeparateModelsSetting")
if (planActSeparateModelsSettingRaw === true || planActSeparateModelsSettingRaw === false) {
result.planActSeparateModelsSetting = planActSeparateModelsSettingRaw
} else {
// Default to true for existing users (who have planModeApiProvider set), false for new users
result.planActSeparateModelsSetting = !!stateValues.get("planModeApiProvider")
}
}
/**
* Handle properties that require async operations
*/
async function handleAsyncProperties(result: any, context: ExtensionContext): Promise<void> {
// Task history requires async disk read
result.taskHistory = await readTaskHistoryFromState(context)
}
export async function resetWorkspaceState(controller: Controller) {
const context = controller.context
await Promise.all(context.workspaceState.keys().map((key) => controller.context.workspaceState.update(key, undefined)))
@@ -582,42 +138,6 @@ export async function resetGlobalState(controller: Controller) {
const context = controller.context
await Promise.all(context.globalState.keys().map((key) => context.globalState.update(key, undefined)))
const secretKeys: SecretKey[] = [
"apiKey",
"openRouterApiKey",
"awsAccessKey",
"awsSecretKey",
"awsSessionToken",
"awsBedrockApiKey",
"openAiApiKey",
"ollamaApiKey",
"geminiApiKey",
"openAiNativeApiKey",
"deepSeekApiKey",
"requestyApiKey",
"togetherApiKey",
"qwenApiKey",
"doubaoApiKey",
"mistralApiKey",
"clineAccountId",
"liteLlmApiKey",
"fireworksApiKey",
"asksageApiKey",
"xaiApiKey",
"sambanovaApiKey",
"cerebrasApiKey",
"groqApiKey",
"basetenApiKey",
"moonshotApiKey",
"nebiusApiKey",
"huggingFaceApiKey",
"huaweiCloudMaasApiKey",
"vercelAiGatewayApiKey",
"zaiApiKey",
"difyApiKey",
"ocaApiKey",
"ocaRefreshToken",
]
await Promise.all(secretKeys.map((key) => context.secrets.delete(key)))
await Promise.all(SecretKeys.map((key) => context.secrets.delete(key)))
await controller.stateManager.reInitialize()
}
+1 -39
View File
@@ -1,4 +1,5 @@
import type { LanguageModelChatSelector } from "../core/api/providers/types"
import type { ApiHandlerSecrets } from "../core/storage/state-keys"
export type ApiProvider =
| "anthropic"
@@ -38,45 +39,6 @@ export type ApiProvider =
| "zai"
| "oca"
export interface ApiHandlerSecrets {
apiKey?: string // anthropic
liteLlmApiKey?: string
awsAccessKey?: string
awsSecretKey?: string
openRouterApiKey?: string
clineAccountId?: string
awsSessionToken?: string
awsBedrockApiKey?: string
openAiApiKey?: string
geminiApiKey?: string
openAiNativeApiKey?: string
ollamaApiKey?: string
deepSeekApiKey?: string
requestyApiKey?: string
togetherApiKey?: string
fireworksApiKey?: string
qwenApiKey?: string
doubaoApiKey?: string
mistralApiKey?: string
authNonce?: string
asksageApiKey?: string
xaiApiKey?: string
moonshotApiKey?: string
zaiApiKey?: string
huggingFaceApiKey?: string
nebiusApiKey?: string
sambanovaApiKey?: string
cerebrasApiKey?: string
sapAiCoreClientId?: string
sapAiCoreClientSecret?: string
groqApiKey?: string
huaweiCloudMaasApiKey?: string
basetenApiKey?: string
vercelAiGatewayApiKey?: string
difyApiKey?: string
}
export interface ApiHandlerOptions {
// Global configuration (not mode-specific)
ulid?: string // Used to identify the task in API requests
@@ -393,7 +393,7 @@ export function convertProtoToApiProvider(provider: ProtoApiProvider): ApiProvid
}
// Converts application ApiConfiguration to proto ApiConfiguration
export function convertApiConfigurationToProto(config: ApiConfiguration): ProtoApiConfiguration {
export function convertApiConfigurationToProto(config: Partial<ApiConfiguration>): ProtoApiConfiguration {
return {
// Global configuration fields
apiKey: config.apiKey,
+1 -1
View File
@@ -80,7 +80,7 @@ export default meta
type Story = StoryObj<typeof MockApp>
// Mock data factories
const createApiConfig = (overrides: Partial<ApiConfiguration> = {}): ApiConfiguration => ({
const createApiConfig = (overrides: Partial<ApiConfiguration> = {}): Partial<ApiConfiguration> => ({
actModeApiProvider: "anthropic",
actModeApiModelId: "claude-3-5-sonnet-20241022",
actModeOpenRouterModelInfo: {
@@ -120,6 +120,7 @@ export const OpenAICompatibleProvider = ({ showModelOptions, isPopup, currentMod
</div>
<div>
{headerEntries.map(([key, value], index) => (
// biome-ignore lint/suspicious/noArrayIndexKey:handle simple static list for user-defined headers
<div key={index} style={{ display: "flex", gap: 5, marginTop: 5 }}>
<DebouncedTextField
initialValue={key}