mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com>
This commit is contained in:
parent
6416118f74
commit
8cb5c4e9e3
62 changed files with 1502 additions and 1003 deletions
5
.changeset/thin-penguins-search.md
Normal file
5
.changeset/thin-penguins-search.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"roo-cline": patch
|
||||
---
|
||||
|
||||
Restore profile management work + fix #3434
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,6 +4,7 @@ out
|
|||
out-*
|
||||
node_modules
|
||||
coverage/
|
||||
mock/
|
||||
|
||||
.DS_Store
|
||||
|
||||
|
|
|
|||
2
e2e/package-lock.json
generated
2
e2e/package-lock.json
generated
|
|
@ -12,7 +12,7 @@
|
|||
"@vscode/test-cli": "^0.0.10",
|
||||
"@vscode/test-electron": "^2.4.0",
|
||||
"mocha": "^11.1.0",
|
||||
"typescript": "^5.4.5"
|
||||
"typescript": "5.8.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@bcoe/v8-coverage": {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@
|
|||
"@vscode/test-cli": "^0.0.10",
|
||||
"@vscode/test-electron": "^2.4.0",
|
||||
"mocha": "^11.1.0",
|
||||
"typescript": "^5.4.5"
|
||||
"typescript": "5.8.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"eslint-plugin-turbo": "^2.4.4",
|
||||
"globals": "^16.0.0",
|
||||
"typescript": "^5",
|
||||
"typescript-eslint": "^8.26.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
"prettier": "^3.5.3",
|
||||
"tsx": "^4.19.4",
|
||||
"turbo": "^2.5.2",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript": "5.8.3",
|
||||
"typescript-eslint": "^8.31.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,18 +128,6 @@ export const modelInfoSchema = z.object({
|
|||
|
||||
export type ModelInfo = z.infer<typeof modelInfoSchema>
|
||||
|
||||
/**
|
||||
* ApiConfigMeta
|
||||
*/
|
||||
|
||||
export const apiConfigMetaSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
apiProvider: providerNamesSchema.optional(),
|
||||
})
|
||||
|
||||
export type ApiConfigMeta = z.infer<typeof apiConfigMetaSchema>
|
||||
|
||||
/**
|
||||
* HistoryItem
|
||||
*/
|
||||
|
|
@ -329,27 +317,56 @@ export type Experiments = z.infer<typeof experimentsSchema>
|
|||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type _AssertExperiments = AssertEqual<Equals<ExperimentId, Keys<Experiments>>>
|
||||
|
||||
/**
|
||||
* ProviderSettingsEntry
|
||||
*/
|
||||
|
||||
export const providerSettingsEntrySchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
apiProvider: providerNamesSchema.optional(),
|
||||
})
|
||||
|
||||
export type ProviderSettingsEntry = z.infer<typeof providerSettingsEntrySchema>
|
||||
|
||||
/**
|
||||
* ProviderSettings
|
||||
*/
|
||||
|
||||
export const providerSettingsSchema = z.object({
|
||||
apiProvider: providerNamesSchema.optional(),
|
||||
// Anthropic
|
||||
const genericProviderSettingsSchema = z.object({
|
||||
includeMaxTokens: z.boolean().optional(),
|
||||
reasoningEffort: reasoningEffortsSchema.optional(),
|
||||
promptCachingDisabled: z.boolean().optional(),
|
||||
diffEnabled: z.boolean().optional(),
|
||||
fuzzyMatchThreshold: z.number().optional(),
|
||||
modelTemperature: z.number().nullish(),
|
||||
rateLimitSeconds: z.number().optional(),
|
||||
// Claude 3.7 Sonnet Thinking
|
||||
modelMaxTokens: z.number().optional(),
|
||||
modelMaxThinkingTokens: z.number().optional(),
|
||||
})
|
||||
|
||||
const anthropicSchema = z.object({
|
||||
apiModelId: z.string().optional(),
|
||||
apiKey: z.string().optional(),
|
||||
anthropicBaseUrl: z.string().optional(),
|
||||
anthropicUseAuthToken: z.boolean().optional(),
|
||||
// Glama
|
||||
})
|
||||
|
||||
const glamaSchema = z.object({
|
||||
glamaModelId: z.string().optional(),
|
||||
glamaApiKey: z.string().optional(),
|
||||
// OpenRouter
|
||||
})
|
||||
|
||||
const openRouterSchema = z.object({
|
||||
openRouterApiKey: z.string().optional(),
|
||||
openRouterModelId: z.string().optional(),
|
||||
openRouterBaseUrl: z.string().optional(),
|
||||
openRouterSpecificProvider: z.string().optional(),
|
||||
openRouterUseMiddleOutTransform: z.boolean().optional(),
|
||||
// Amazon Bedrock
|
||||
})
|
||||
|
||||
const bedrockSchema = z.object({
|
||||
awsAccessKey: z.string().optional(),
|
||||
awsSecretKey: z.string().optional(),
|
||||
awsSessionToken: z.string().optional(),
|
||||
|
|
@ -359,15 +376,18 @@ export const providerSettingsSchema = z.object({
|
|||
awsProfile: z.string().optional(),
|
||||
awsUseProfile: z.boolean().optional(),
|
||||
awsCustomArn: z.string().optional(),
|
||||
// Google Vertex
|
||||
})
|
||||
|
||||
const vertexSchema = z.object({
|
||||
vertexKeyFile: z.string().optional(),
|
||||
vertexJsonCredentials: z.string().optional(),
|
||||
vertexProjectId: z.string().optional(),
|
||||
vertexRegion: z.string().optional(),
|
||||
// OpenAI
|
||||
})
|
||||
|
||||
const openAiSchema = z.object({
|
||||
openAiBaseUrl: z.string().optional(),
|
||||
openAiApiKey: z.string().optional(),
|
||||
openAiHostHeader: z.string().optional(),
|
||||
openAiLegacyFormat: z.boolean().optional(),
|
||||
openAiR1FormatEnabled: z.boolean().optional(),
|
||||
openAiModelId: z.string().optional(),
|
||||
|
|
@ -376,10 +396,16 @@ export const providerSettingsSchema = z.object({
|
|||
azureApiVersion: z.string().optional(),
|
||||
openAiStreamingEnabled: z.boolean().optional(),
|
||||
enableReasoningEffort: z.boolean().optional(),
|
||||
// Ollama
|
||||
openAiHostHeader: z.string().optional(), // Keep temporarily for backward compatibility during migration.
|
||||
openAiHeaders: z.record(z.string(), z.string()).optional(),
|
||||
})
|
||||
|
||||
const ollamaSchema = z.object({
|
||||
ollamaModelId: z.string().optional(),
|
||||
ollamaBaseUrl: z.string().optional(),
|
||||
// VS Code LM
|
||||
})
|
||||
|
||||
const vsCodeLmSchema = z.object({
|
||||
vsCodeLmModelSelector: z
|
||||
.object({
|
||||
vendor: z.string().optional(),
|
||||
|
|
@ -388,46 +414,210 @@ export const providerSettingsSchema = z.object({
|
|||
id: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
// LM Studio
|
||||
})
|
||||
|
||||
const lmStudioSchema = z.object({
|
||||
lmStudioModelId: z.string().optional(),
|
||||
lmStudioBaseUrl: z.string().optional(),
|
||||
lmStudioDraftModelId: z.string().optional(),
|
||||
lmStudioSpeculativeDecodingEnabled: z.boolean().optional(),
|
||||
// Gemini
|
||||
})
|
||||
|
||||
const geminiSchema = z.object({
|
||||
geminiApiKey: z.string().optional(),
|
||||
googleGeminiBaseUrl: z.string().optional(),
|
||||
// OpenAI Native
|
||||
})
|
||||
|
||||
const openAiNativeSchema = z.object({
|
||||
openAiNativeApiKey: z.string().optional(),
|
||||
openAiNativeBaseUrl: z.string().optional(),
|
||||
// Mistral
|
||||
})
|
||||
|
||||
const mistralSchema = z.object({
|
||||
mistralApiKey: z.string().optional(),
|
||||
mistralCodestralUrl: z.string().optional(),
|
||||
// DeepSeek
|
||||
})
|
||||
|
||||
const deepSeekSchema = z.object({
|
||||
deepSeekBaseUrl: z.string().optional(),
|
||||
deepSeekApiKey: z.string().optional(),
|
||||
// Unbound
|
||||
})
|
||||
|
||||
const unboundSchema = z.object({
|
||||
unboundApiKey: z.string().optional(),
|
||||
unboundModelId: z.string().optional(),
|
||||
// Requesty
|
||||
})
|
||||
|
||||
const requestySchema = z.object({
|
||||
requestyApiKey: z.string().optional(),
|
||||
requestyModelId: z.string().optional(),
|
||||
// X.AI (Grok)
|
||||
xaiApiKey: z.string().optional(),
|
||||
// Claude 3.7 Sonnet Thinking
|
||||
modelMaxTokens: z.number().optional(),
|
||||
modelMaxThinkingTokens: z.number().optional(),
|
||||
// Generic
|
||||
includeMaxTokens: z.boolean().optional(),
|
||||
reasoningEffort: reasoningEffortsSchema.optional(),
|
||||
promptCachingDisabled: z.boolean().optional(),
|
||||
diffEnabled: z.boolean().optional(),
|
||||
fuzzyMatchThreshold: z.number().optional(),
|
||||
modelTemperature: z.number().nullish(),
|
||||
rateLimitSeconds: z.number().optional(),
|
||||
// Fake AI
|
||||
})
|
||||
|
||||
const humanRelaySchema = z.object({})
|
||||
|
||||
const fakeAiSchema = z.object({
|
||||
fakeAi: z.unknown().optional(),
|
||||
})
|
||||
|
||||
const xaiSchema = z.object({
|
||||
xaiApiKey: z.string().optional(),
|
||||
})
|
||||
|
||||
const groqSchema = z.object({
|
||||
groqApiKey: z.string().optional(),
|
||||
})
|
||||
|
||||
const chutesSchema = z.object({
|
||||
chutesApiKey: z.string().optional(),
|
||||
})
|
||||
|
||||
const litellmSchema = z.object({
|
||||
litellmBaseUrl: z.string().optional(),
|
||||
litellmApiKey: z.string().optional(),
|
||||
litellmModelId: z.string().optional(),
|
||||
})
|
||||
|
||||
const defaultSchema = z.object({
|
||||
apiProvider: z.undefined(),
|
||||
})
|
||||
|
||||
export const providerSettingsSchemaDiscriminated = z
|
||||
.discriminatedUnion("apiProvider", [
|
||||
anthropicSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("anthropic"),
|
||||
}),
|
||||
),
|
||||
glamaSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("glama"),
|
||||
}),
|
||||
),
|
||||
openRouterSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("openrouter"),
|
||||
}),
|
||||
),
|
||||
bedrockSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("bedrock"),
|
||||
}),
|
||||
),
|
||||
vertexSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("vertex"),
|
||||
}),
|
||||
),
|
||||
openAiSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("openai"),
|
||||
}),
|
||||
),
|
||||
ollamaSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("ollama"),
|
||||
}),
|
||||
),
|
||||
vsCodeLmSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("vscode-lm"),
|
||||
}),
|
||||
),
|
||||
lmStudioSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("lmstudio"),
|
||||
}),
|
||||
),
|
||||
geminiSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("gemini"),
|
||||
}),
|
||||
),
|
||||
openAiNativeSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("openai-native"),
|
||||
}),
|
||||
),
|
||||
mistralSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("mistral"),
|
||||
}),
|
||||
),
|
||||
deepSeekSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("deepseek"),
|
||||
}),
|
||||
),
|
||||
unboundSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("unbound"),
|
||||
}),
|
||||
),
|
||||
requestySchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("requesty"),
|
||||
}),
|
||||
),
|
||||
humanRelaySchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("human-relay"),
|
||||
}),
|
||||
),
|
||||
fakeAiSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("fake-ai"),
|
||||
}),
|
||||
),
|
||||
xaiSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("xai"),
|
||||
}),
|
||||
),
|
||||
groqSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("groq"),
|
||||
}),
|
||||
),
|
||||
chutesSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("chutes"),
|
||||
}),
|
||||
),
|
||||
litellmSchema.merge(
|
||||
z.object({
|
||||
apiProvider: z.literal("litellm"),
|
||||
}),
|
||||
),
|
||||
defaultSchema,
|
||||
])
|
||||
.and(genericProviderSettingsSchema)
|
||||
|
||||
export const providerSettingsSchema = z.object({
|
||||
apiProvider: providerNamesSchema.optional(),
|
||||
...anthropicSchema.shape,
|
||||
...glamaSchema.shape,
|
||||
...openRouterSchema.shape,
|
||||
...bedrockSchema.shape,
|
||||
...vertexSchema.shape,
|
||||
...openAiSchema.shape,
|
||||
...ollamaSchema.shape,
|
||||
...vsCodeLmSchema.shape,
|
||||
...lmStudioSchema.shape,
|
||||
...geminiSchema.shape,
|
||||
...openAiNativeSchema.shape,
|
||||
...mistralSchema.shape,
|
||||
...deepSeekSchema.shape,
|
||||
...unboundSchema.shape,
|
||||
...requestySchema.shape,
|
||||
...humanRelaySchema.shape,
|
||||
...fakeAiSchema.shape,
|
||||
...xaiSchema.shape,
|
||||
...groqSchema.shape,
|
||||
...chutesSchema.shape,
|
||||
...litellmSchema.shape,
|
||||
...genericProviderSettingsSchema.shape,
|
||||
})
|
||||
|
||||
export type ProviderSettings = z.infer<typeof providerSettingsSchema>
|
||||
|
||||
type ProviderSettingsRecord = Record<Keys<ProviderSettings>, undefined>
|
||||
|
|
@ -466,7 +656,6 @@ const providerSettingsRecord: ProviderSettingsRecord = {
|
|||
// OpenAI
|
||||
openAiBaseUrl: undefined,
|
||||
openAiApiKey: undefined,
|
||||
openAiHostHeader: undefined,
|
||||
openAiLegacyFormat: undefined,
|
||||
openAiR1FormatEnabled: undefined,
|
||||
openAiModelId: undefined,
|
||||
|
|
@ -475,6 +664,8 @@ const providerSettingsRecord: ProviderSettingsRecord = {
|
|||
azureApiVersion: undefined,
|
||||
openAiStreamingEnabled: undefined,
|
||||
enableReasoningEffort: undefined,
|
||||
openAiHostHeader: undefined, // Keep temporarily for backward compatibility during migration
|
||||
openAiHeaders: undefined,
|
||||
// Ollama
|
||||
ollamaModelId: undefined,
|
||||
ollamaBaseUrl: undefined,
|
||||
|
|
@ -517,6 +708,14 @@ const providerSettingsRecord: ProviderSettingsRecord = {
|
|||
fakeAi: undefined,
|
||||
// X.AI (Grok)
|
||||
xaiApiKey: undefined,
|
||||
// Groq
|
||||
groqApiKey: undefined,
|
||||
// Chutes AI
|
||||
chutesApiKey: undefined,
|
||||
// LiteLLM
|
||||
litellmBaseUrl: undefined,
|
||||
litellmApiKey: undefined,
|
||||
litellmModelId: undefined,
|
||||
}
|
||||
|
||||
export const PROVIDER_SETTINGS_KEYS = Object.keys(providerSettingsRecord) as Keys<ProviderSettings>[]
|
||||
|
|
@ -527,7 +726,7 @@ export const PROVIDER_SETTINGS_KEYS = Object.keys(providerSettingsRecord) as Key
|
|||
|
||||
export const globalSettingsSchema = z.object({
|
||||
currentApiConfigName: z.string().optional(),
|
||||
listApiConfigMeta: z.array(apiConfigMetaSchema).optional(),
|
||||
listApiConfigMeta: z.array(providerSettingsEntrySchema).optional(),
|
||||
pinnedApiConfigs: z.record(z.string(), z.boolean()).optional(),
|
||||
|
||||
lastShownAnnouncementId: z.string().optional(),
|
||||
|
|
|
|||
72
evals/pnpm-lock.yaml
generated
72
evals/pnpm-lock.yaml
generated
|
|
@ -30,7 +30,7 @@ importers:
|
|||
specifier: ^2.5.2
|
||||
version: 2.5.3
|
||||
typescript:
|
||||
specifier: ^5.8.3
|
||||
specifier: 5.8.3
|
||||
version: 5.8.3
|
||||
typescript-eslint:
|
||||
specifier: ^8.31.1
|
||||
|
|
@ -235,12 +235,9 @@ importers:
|
|||
globals:
|
||||
specifier: ^16.0.0
|
||||
version: 16.0.0
|
||||
typescript:
|
||||
specifier: ^5
|
||||
version: 5.8.2
|
||||
typescript-eslint:
|
||||
specifier: ^8.26.0
|
||||
version: 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
version: 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
|
||||
config/typescript: {}
|
||||
|
||||
|
|
@ -4377,11 +4374,6 @@ packages:
|
|||
eslint: ^8.57.0 || ^9.0.0
|
||||
typescript: '>=4.8.4 <5.9.0'
|
||||
|
||||
typescript@5.8.2:
|
||||
resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==}
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
typescript@5.8.3:
|
||||
resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
|
||||
engines: {node: '>=14.17'}
|
||||
|
|
@ -6037,20 +6029,20 @@ snapshots:
|
|||
dependencies:
|
||||
'@types/node': 20.17.24
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||
'@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.1
|
||||
'@typescript-eslint/parser': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
'@typescript-eslint/parser': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/scope-manager': 8.26.1
|
||||
'@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
'@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
'@typescript-eslint/type-utils': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/visitor-keys': 8.26.1
|
||||
eslint: 9.22.0(jiti@2.4.2)
|
||||
graphemer: 1.4.0
|
||||
ignore: 5.3.2
|
||||
natural-compare: 1.4.0
|
||||
ts-api-utils: 2.0.1(typescript@5.8.2)
|
||||
typescript: 5.8.2
|
||||
ts-api-utils: 2.0.1(typescript@5.8.3)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -6071,15 +6063,15 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||
'@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.26.1
|
||||
'@typescript-eslint/types': 8.26.1
|
||||
'@typescript-eslint/typescript-estree': 8.26.1(typescript@5.8.2)
|
||||
'@typescript-eslint/typescript-estree': 8.26.1(typescript@5.8.3)
|
||||
'@typescript-eslint/visitor-keys': 8.26.1
|
||||
debug: 4.4.0
|
||||
eslint: 9.22.0(jiti@2.4.2)
|
||||
typescript: 5.8.2
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -6105,14 +6097,14 @@ snapshots:
|
|||
'@typescript-eslint/types': 8.32.0
|
||||
'@typescript-eslint/visitor-keys': 8.32.0
|
||||
|
||||
'@typescript-eslint/type-utils@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||
'@typescript-eslint/type-utils@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/typescript-estree': 8.26.1(typescript@5.8.2)
|
||||
'@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
'@typescript-eslint/typescript-estree': 8.26.1(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
debug: 4.4.0
|
||||
eslint: 9.22.0(jiti@2.4.2)
|
||||
ts-api-utils: 2.0.1(typescript@5.8.2)
|
||||
typescript: 5.8.2
|
||||
ts-api-utils: 2.0.1(typescript@5.8.3)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -6131,7 +6123,7 @@ snapshots:
|
|||
|
||||
'@typescript-eslint/types@8.32.0': {}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.26.1(typescript@5.8.2)':
|
||||
'@typescript-eslint/typescript-estree@8.26.1(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.26.1
|
||||
'@typescript-eslint/visitor-keys': 8.26.1
|
||||
|
|
@ -6140,8 +6132,8 @@ snapshots:
|
|||
is-glob: 4.0.3
|
||||
minimatch: 9.0.5
|
||||
semver: 7.7.1
|
||||
ts-api-utils: 2.1.0(typescript@5.8.2)
|
||||
typescript: 5.8.2
|
||||
ts-api-utils: 2.1.0(typescript@5.8.3)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -6159,14 +6151,14 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||
'@typescript-eslint/utils@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.6.1(eslint@9.22.0(jiti@2.4.2))
|
||||
'@typescript-eslint/scope-manager': 8.26.1
|
||||
'@typescript-eslint/types': 8.26.1
|
||||
'@typescript-eslint/typescript-estree': 8.26.1(typescript@5.8.2)
|
||||
'@typescript-eslint/typescript-estree': 8.26.1(typescript@5.8.3)
|
||||
eslint: 9.22.0(jiti@2.4.2)
|
||||
typescript: 5.8.2
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -8577,13 +8569,9 @@ snapshots:
|
|||
|
||||
toidentifier@1.0.1: {}
|
||||
|
||||
ts-api-utils@2.0.1(typescript@5.8.2):
|
||||
ts-api-utils@2.0.1(typescript@5.8.3):
|
||||
dependencies:
|
||||
typescript: 5.8.2
|
||||
|
||||
ts-api-utils@2.1.0(typescript@5.8.2):
|
||||
dependencies:
|
||||
typescript: 5.8.2
|
||||
typescript: 5.8.3
|
||||
|
||||
ts-api-utils@2.1.0(typescript@5.8.3):
|
||||
dependencies:
|
||||
|
|
@ -8670,13 +8658,13 @@ snapshots:
|
|||
possible-typed-array-names: 1.1.0
|
||||
reflect.getprototypeof: 1.0.10
|
||||
|
||||
typescript-eslint@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2):
|
||||
typescript-eslint@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
'@typescript-eslint/parser': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
'@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
'@typescript-eslint/eslint-plugin': 8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/parser': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
eslint: 9.22.0(jiti@2.4.2)
|
||||
typescript: 5.8.2
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -8690,8 +8678,6 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
typescript@5.8.2: {}
|
||||
|
||||
typescript@5.8.3: {}
|
||||
|
||||
unbox-primitive@1.1.0:
|
||||
|
|
|
|||
0
git
0
git
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -65,7 +65,7 @@
|
|||
"vscode-material-icons": "^0.1.1",
|
||||
"web-tree-sitter": "^0.22.6",
|
||||
"workerpool": "^9.2.0",
|
||||
"zod": "^3.23.8"
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.27.10",
|
||||
|
|
@ -103,7 +103,7 @@
|
|||
"ts-jest": "^29.2.5",
|
||||
"tsup": "^8.4.0",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript": "5.8.3",
|
||||
"vitest": "^3.1.3",
|
||||
"zod-to-ts": "^1.2.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -421,7 +421,7 @@
|
|||
"vscode-material-icons": "^0.1.1",
|
||||
"web-tree-sitter": "^0.22.6",
|
||||
"workerpool": "^9.2.0",
|
||||
"zod": "^3.23.8"
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.27.10",
|
||||
|
|
@ -459,7 +459,7 @@
|
|||
"ts-jest": "^29.2.5",
|
||||
"tsup": "^8.4.0",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript": "5.8.3",
|
||||
"vitest": "^3.1.3",
|
||||
"zod-to-ts": "^1.2.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import { BetaThinkingConfigParam } from "@anthropic-ai/sdk/resources/beta/messages/index.mjs"
|
||||
|
||||
import { ApiConfiguration, ModelInfo, ApiHandlerOptions } from "../shared/api"
|
||||
import { ProviderSettings, ModelInfo, ApiHandlerOptions } from "../shared/api"
|
||||
import { ANTHROPIC_DEFAULT_MAX_TOKENS } from "./providers/constants"
|
||||
import { GlamaHandler } from "./providers/glama"
|
||||
import { AnthropicHandler } from "./providers/anthropic"
|
||||
|
|
@ -47,7 +47,7 @@ export interface ApiHandler {
|
|||
countTokens(content: Array<Anthropic.Messages.ContentBlockParam>): Promise<number>
|
||||
}
|
||||
|
||||
export function buildApiHandler(configuration: ApiConfiguration): ApiHandler {
|
||||
export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
|
||||
const { apiProvider, ...options } = configuration
|
||||
|
||||
switch (apiProvider) {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import { ExtensionContext } from "vscode"
|
||||
import { z, ZodError } from "zod"
|
||||
|
||||
import { providerSettingsSchema, ApiConfigMeta } from "../../schemas"
|
||||
import { providerSettingsSchema, ProviderSettingsEntry, providerSettingsSchemaDiscriminated } from "../../schemas"
|
||||
import { Mode, modes } from "../../shared/modes"
|
||||
import { telemetryService } from "../../services/telemetry/TelemetryService"
|
||||
|
||||
const providerSettingsWithIdSchema = providerSettingsSchema.extend({ id: z.string().optional() })
|
||||
const discriminatedProviderSettingsWithIdSchema = providerSettingsSchemaDiscriminated.and(
|
||||
z.object({ id: z.string().optional() }),
|
||||
)
|
||||
|
||||
type ProviderSettingsWithId = z.infer<typeof providerSettingsWithIdSchema>
|
||||
|
||||
|
|
@ -223,7 +226,7 @@ export class ProviderSettingsManager {
|
|||
/**
|
||||
* List all available configs with metadata.
|
||||
*/
|
||||
public async listConfig(): Promise<ApiConfigMeta[]> {
|
||||
public async listConfig(): Promise<ProviderSettingsEntry[]> {
|
||||
try {
|
||||
return await this.lock(async () => {
|
||||
const providerProfiles = await this.load()
|
||||
|
|
@ -244,66 +247,81 @@ 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()
|
||||
// Preserve the existing ID if this is an update to an existing config.
|
||||
const existingId = providerProfiles.apiConfigs[name]?.id
|
||||
providerProfiles.apiConfigs[name] = { ...config, id: config.id || existingId || this.generateId() }
|
||||
const id = config.id || existingId || this.generateId()
|
||||
|
||||
// Filter out settings from other providers.
|
||||
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}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a config by name and set it as the current config.
|
||||
*/
|
||||
public async loadConfig(name: string) {
|
||||
public async getProfile(
|
||||
params: { name: string } | { id: string },
|
||||
): Promise<ProviderSettingsWithId & { name: string }> {
|
||||
try {
|
||||
return await this.lock(async () => {
|
||||
const providerProfiles = await this.load()
|
||||
const providerSettings = providerProfiles.apiConfigs[name]
|
||||
let name: string
|
||||
let providerSettings: ProviderSettingsWithId
|
||||
|
||||
if (!providerSettings) {
|
||||
throw new Error(`Config '${name}' not found`)
|
||||
if ("name" in params) {
|
||||
name = params.name
|
||||
|
||||
if (!providerProfiles.apiConfigs[name]) {
|
||||
throw new Error(`Config with name '${name}' not found`)
|
||||
}
|
||||
|
||||
providerSettings = providerProfiles.apiConfigs[name]
|
||||
} else {
|
||||
const id = params.id
|
||||
|
||||
const entry = Object.entries(providerProfiles.apiConfigs).find(
|
||||
([_, apiConfig]) => apiConfig.id === id,
|
||||
)
|
||||
|
||||
if (!entry) {
|
||||
throw new Error(`Config with ID '${id}' not found`)
|
||||
}
|
||||
|
||||
name = entry[0]
|
||||
providerSettings = entry[1]
|
||||
}
|
||||
|
||||
providerProfiles.currentApiConfigName = name
|
||||
await this.store(providerProfiles)
|
||||
|
||||
return providerSettings
|
||||
return { name, ...providerSettings }
|
||||
})
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to load config: ${error}`)
|
||||
throw new Error(`Failed to get profile: ${error instanceof Error ? error.message : error}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a config by ID and set it as the current config.
|
||||
* Activate a profile by name or ID.
|
||||
*/
|
||||
public async loadConfigById(id: string) {
|
||||
public async activateProfile(
|
||||
params: { name: string } | { id: string },
|
||||
): Promise<ProviderSettingsWithId & { name: string }> {
|
||||
const { name, ...providerSettings } = await this.getProfile(params)
|
||||
|
||||
try {
|
||||
return await this.lock(async () => {
|
||||
const providerProfiles = await this.load()
|
||||
const providerSettings = Object.entries(providerProfiles.apiConfigs).find(
|
||||
([_, apiConfig]) => apiConfig.id === id,
|
||||
)
|
||||
|
||||
if (!providerSettings) {
|
||||
throw new Error(`Config with ID '${id}' not found`)
|
||||
}
|
||||
|
||||
const [name, apiConfig] = providerSettings
|
||||
providerProfiles.currentApiConfigName = name
|
||||
await this.store(providerProfiles)
|
||||
|
||||
return { config: apiConfig, name }
|
||||
return { name, ...providerSettings }
|
||||
})
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to load config by ID: ${error}`)
|
||||
throw new Error(`Failed to activate profile: ${error instanceof Error ? error.message : error}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -381,7 +399,15 @@ export class ProviderSettingsManager {
|
|||
|
||||
public async export() {
|
||||
try {
|
||||
return await this.lock(async () => providerProfilesSchema.parse(await this.load()))
|
||||
return await this.lock(async () => {
|
||||
const profiles = providerProfilesSchema.parse(await this.load())
|
||||
const configs = profiles.apiConfigs
|
||||
for (const name in configs) {
|
||||
// Avoid leaking properties from other providers.
|
||||
configs[name] = discriminatedProviderSettingsWithIdSchema.parse(configs[name])
|
||||
}
|
||||
return profiles
|
||||
})
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to export provider profiles: ${error}`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,8 +221,9 @@ describe("ProviderSettingsManager", () => {
|
|||
)
|
||||
|
||||
const newConfig: ProviderSettings = {
|
||||
apiProvider: "anthropic",
|
||||
apiKey: "test-key",
|
||||
apiProvider: "vertex",
|
||||
apiModelId: "gemini-2.5-flash-preview-04-17",
|
||||
vertexKeyFile: "test-key-file",
|
||||
}
|
||||
|
||||
await providerSettingsManager.saveConfig("test", newConfig)
|
||||
|
|
@ -247,10 +248,58 @@ describe("ProviderSettingsManager", () => {
|
|||
},
|
||||
}
|
||||
|
||||
expect(mockSecrets.store).toHaveBeenCalledWith(
|
||||
"roo_cline_config_api_config",
|
||||
JSON.stringify(expectedConfig, null, 2),
|
||||
expect(mockSecrets.store.mock.calls[0][0]).toEqual("roo_cline_config_api_config")
|
||||
expect(storedConfig).toEqual(expectedConfig)
|
||||
})
|
||||
|
||||
it("should only save provider relevant settings", async () => {
|
||||
mockSecrets.get.mockResolvedValue(
|
||||
JSON.stringify({
|
||||
currentApiConfigName: "default",
|
||||
apiConfigs: {
|
||||
default: {},
|
||||
},
|
||||
modeApiConfigs: {
|
||||
code: "default",
|
||||
architect: "default",
|
||||
ask: "default",
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
const newConfig: ProviderSettings = {
|
||||
apiProvider: "anthropic",
|
||||
apiKey: "test-key",
|
||||
}
|
||||
const newConfigWithExtra: ProviderSettings = {
|
||||
...newConfig,
|
||||
openRouterApiKey: "another-key",
|
||||
}
|
||||
|
||||
await providerSettingsManager.saveConfig("test", newConfigWithExtra)
|
||||
|
||||
// Get the actual stored config to check the generated ID
|
||||
const storedConfig = JSON.parse(mockSecrets.store.mock.lastCall[1])
|
||||
const testConfigId = storedConfig.apiConfigs.test.id
|
||||
|
||||
const expectedConfig = {
|
||||
currentApiConfigName: "default",
|
||||
apiConfigs: {
|
||||
default: {},
|
||||
test: {
|
||||
...newConfig,
|
||||
id: testConfigId,
|
||||
},
|
||||
},
|
||||
modeApiConfigs: {
|
||||
code: "default",
|
||||
architect: "default",
|
||||
ask: "default",
|
||||
},
|
||||
}
|
||||
|
||||
expect(mockSecrets.store.mock.calls[0][0]).toEqual("roo_cline_config_api_config")
|
||||
expect(storedConfig).toEqual(expectedConfig)
|
||||
})
|
||||
|
||||
it("should update existing config", async () => {
|
||||
|
|
@ -291,10 +340,9 @@ describe("ProviderSettingsManager", () => {
|
|||
},
|
||||
}
|
||||
|
||||
expect(mockSecrets.store).toHaveBeenCalledWith(
|
||||
"roo_cline_config_api_config",
|
||||
JSON.stringify(expectedConfig, null, 2),
|
||||
)
|
||||
const storedConfig = JSON.parse(mockSecrets.store.mock.lastCall[1])
|
||||
expect(mockSecrets.store.mock.lastCall[0]).toEqual("roo_cline_config_api_config")
|
||||
expect(storedConfig).toEqual(expectedConfig)
|
||||
})
|
||||
|
||||
it("should throw error if secrets storage fails", async () => {
|
||||
|
|
@ -391,17 +439,15 @@ describe("ProviderSettingsManager", () => {
|
|||
mockGlobalState.get.mockResolvedValue(42)
|
||||
mockSecrets.get.mockResolvedValue(JSON.stringify(existingConfig))
|
||||
|
||||
const config = await providerSettingsManager.loadConfig("test")
|
||||
const { name, ...providerSettings } = await providerSettingsManager.activateProfile({ name: "test" })
|
||||
|
||||
expect(config).toEqual({
|
||||
apiProvider: "anthropic",
|
||||
apiKey: "test-key",
|
||||
id: "test-id",
|
||||
})
|
||||
expect(name).toBe("test")
|
||||
expect(providerSettings).toEqual({ apiProvider: "anthropic", apiKey: "test-key", id: "test-id" })
|
||||
|
||||
// Get the stored config to check the structure
|
||||
// Get the stored config to check the structure.
|
||||
const storedConfig = JSON.parse(mockSecrets.store.mock.calls[1][1])
|
||||
expect(storedConfig.currentApiConfigName).toBe("test")
|
||||
|
||||
expect(storedConfig.apiConfigs.test).toEqual({
|
||||
apiProvider: "anthropic",
|
||||
apiKey: "test-key",
|
||||
|
|
@ -413,17 +459,12 @@ describe("ProviderSettingsManager", () => {
|
|||
mockSecrets.get.mockResolvedValue(
|
||||
JSON.stringify({
|
||||
currentApiConfigName: "default",
|
||||
apiConfigs: {
|
||||
default: {
|
||||
config: {},
|
||||
id: "default",
|
||||
},
|
||||
},
|
||||
apiConfigs: { default: { config: {}, id: "default" } },
|
||||
}),
|
||||
)
|
||||
|
||||
await expect(providerSettingsManager.loadConfig("nonexistent")).rejects.toThrow(
|
||||
"Config 'nonexistent' not found",
|
||||
await expect(providerSettingsManager.activateProfile({ name: "nonexistent" })).rejects.toThrow(
|
||||
"Config with name 'nonexistent' not found",
|
||||
)
|
||||
})
|
||||
|
||||
|
|
@ -431,20 +472,13 @@ describe("ProviderSettingsManager", () => {
|
|||
mockSecrets.get.mockResolvedValue(
|
||||
JSON.stringify({
|
||||
currentApiConfigName: "default",
|
||||
apiConfigs: {
|
||||
test: {
|
||||
config: {
|
||||
apiProvider: "anthropic",
|
||||
},
|
||||
id: "test-id",
|
||||
},
|
||||
},
|
||||
apiConfigs: { test: { config: { apiProvider: "anthropic" }, id: "test-id" } },
|
||||
}),
|
||||
)
|
||||
mockSecrets.store.mockRejectedValueOnce(new Error("Storage failed"))
|
||||
|
||||
await expect(providerSettingsManager.loadConfig("test")).rejects.toThrow(
|
||||
"Failed to load config: Error: Failed to write provider profiles to secrets: Error: Storage failed",
|
||||
await expect(providerSettingsManager.activateProfile({ name: "test" })).rejects.toThrow(
|
||||
"Failed to activate profile: Failed to write provider profiles to secrets: Error: Storage failed",
|
||||
)
|
||||
})
|
||||
|
||||
|
|
@ -494,12 +528,7 @@ describe("ProviderSettingsManager", () => {
|
|||
mockSecrets.get.mockResolvedValue(
|
||||
JSON.stringify({
|
||||
currentApiConfigName: "test",
|
||||
apiConfigs: {
|
||||
test: {
|
||||
apiProvider: "anthropic",
|
||||
id: "test-id",
|
||||
},
|
||||
},
|
||||
apiConfigs: { test: { apiProvider: "anthropic", id: "test-id" } },
|
||||
}),
|
||||
)
|
||||
|
||||
|
|
@ -514,18 +543,8 @@ describe("ProviderSettingsManager", () => {
|
|||
it("should return true for existing config", async () => {
|
||||
const existingConfig: ProviderProfiles = {
|
||||
currentApiConfigName: "default",
|
||||
apiConfigs: {
|
||||
default: {
|
||||
id: "default",
|
||||
},
|
||||
test: {
|
||||
apiProvider: "anthropic",
|
||||
id: "test-id",
|
||||
},
|
||||
},
|
||||
migrations: {
|
||||
rateLimitSecondsMigrated: false,
|
||||
},
|
||||
apiConfigs: { default: { id: "default" }, test: { apiProvider: "anthropic", id: "test-id" } },
|
||||
migrations: { rateLimitSecondsMigrated: false },
|
||||
}
|
||||
|
||||
mockSecrets.get.mockResolvedValue(JSON.stringify(existingConfig))
|
||||
|
|
@ -536,10 +555,7 @@ describe("ProviderSettingsManager", () => {
|
|||
|
||||
it("should return false for non-existent config", async () => {
|
||||
mockSecrets.get.mockResolvedValue(
|
||||
JSON.stringify({
|
||||
currentApiConfigName: "default",
|
||||
apiConfigs: { default: {} },
|
||||
}),
|
||||
JSON.stringify({ currentApiConfigName: "default", apiConfigs: { default: {} } }),
|
||||
)
|
||||
|
||||
const hasConfig = await providerSettingsManager.hasConfig("nonexistent")
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import { ApiHandler, buildApiHandler } from "../../api"
|
|||
import { ApiStream } from "../../api/transform/stream"
|
||||
|
||||
// shared
|
||||
import { ApiConfiguration } from "../../shared/api"
|
||||
import { ProviderSettings } from "../../shared/api"
|
||||
import { findLastIndex } from "../../shared/array"
|
||||
import { combineApiRequests } from "../../shared/combineApiRequests"
|
||||
import { combineCommandSequences } from "../../shared/combineCommandSequences"
|
||||
|
|
@ -92,7 +92,7 @@ export type ClineEvents = {
|
|||
|
||||
export type TaskOptions = {
|
||||
provider: ClineProvider
|
||||
apiConfiguration: ApiConfiguration
|
||||
apiConfiguration: ProviderSettings
|
||||
customInstructions?: string
|
||||
enableDiff?: boolean
|
||||
enableCheckpoints?: boolean
|
||||
|
|
@ -130,7 +130,7 @@ export class Task extends EventEmitter<ClineEvents> {
|
|||
customInstructions?: string
|
||||
|
||||
// API
|
||||
readonly apiConfiguration: ApiConfiguration
|
||||
readonly apiConfiguration: ProviderSettings
|
||||
api: ApiHandler
|
||||
private promptCacheKey: string
|
||||
private lastApiRequestTime?: number
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { Anthropic } from "@anthropic-ai/sdk"
|
|||
import { GlobalState } from "../../../schemas"
|
||||
import { Task } from "../Task"
|
||||
import { ClineProvider } from "../../webview/ClineProvider"
|
||||
import { ApiConfiguration, ModelInfo } from "../../../shared/api"
|
||||
import { ProviderSettings, ModelInfo } from "../../../shared/api"
|
||||
import { ApiStreamChunk } from "../../../api/transform/stream"
|
||||
import { ContextProxy } from "../../config/ContextProxy"
|
||||
import { processUserContentMentions } from "../../mentions/processUserContentMentions"
|
||||
|
|
@ -156,7 +156,7 @@ const mockMessages = [
|
|||
|
||||
describe("Cline", () => {
|
||||
let mockProvider: jest.Mocked<ClineProvider>
|
||||
let mockApiConfig: ApiConfiguration
|
||||
let mockApiConfig: ProviderSettings
|
||||
let mockOutputChannel: any
|
||||
let mockExtensionContext: vscode.ExtensionContext
|
||||
|
||||
|
|
|
|||
|
|
@ -9,16 +9,10 @@ import axios from "axios"
|
|||
import pWaitFor from "p-wait-for"
|
||||
import * as vscode from "vscode"
|
||||
|
||||
import { GlobalState, ProviderSettings, RooCodeSettings } from "../../schemas"
|
||||
import type { GlobalState, ProviderName, ProviderSettings, RooCodeSettings, ProviderSettingsEntry } from "../../schemas"
|
||||
import { t } from "../../i18n"
|
||||
import { setPanel } from "../../activate/registerCommands"
|
||||
import {
|
||||
ProviderName,
|
||||
ApiConfiguration,
|
||||
requestyDefaultModelId,
|
||||
openRouterDefaultModelId,
|
||||
glamaDefaultModelId,
|
||||
} from "../../shared/api"
|
||||
import { requestyDefaultModelId, openRouterDefaultModelId, glamaDefaultModelId } from "../../shared/api"
|
||||
import { findLast } from "../../shared/array"
|
||||
import { supportPrompt } from "../../shared/support-prompt"
|
||||
import { GlobalFileNames } from "../../shared/globalFileNames"
|
||||
|
|
@ -252,7 +246,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
return false
|
||||
}
|
||||
|
||||
// check if there is a cline instance in the stack (if this provider has an active task)
|
||||
// Check if there is a cline instance in the stack (if this provider has an active task)
|
||||
if (visibleProvider.getCurrentCline()) {
|
||||
return true
|
||||
}
|
||||
|
|
@ -762,7 +756,6 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
* @param newMode The mode to switch to
|
||||
*/
|
||||
public async handleModeSwitch(newMode: Mode) {
|
||||
// Capture mode switch telemetry event
|
||||
const cline = this.getCurrentCline()
|
||||
|
||||
if (cline) {
|
||||
|
|
@ -779,24 +772,19 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
// Update listApiConfigMeta first to ensure UI has latest data
|
||||
await this.updateGlobalState("listApiConfigMeta", listApiConfig)
|
||||
|
||||
// If this mode has a saved config, use it
|
||||
// If this mode has a saved config, use it.
|
||||
if (savedConfigId) {
|
||||
const config = listApiConfig?.find((c) => c.id === savedConfigId)
|
||||
const profile = listApiConfig.find(({ id }) => id === savedConfigId)
|
||||
|
||||
if (config?.name) {
|
||||
const apiConfig = await this.providerSettingsManager.loadConfig(config.name)
|
||||
|
||||
await Promise.all([
|
||||
this.updateGlobalState("currentApiConfigName", config.name),
|
||||
this.updateApiConfiguration(apiConfig),
|
||||
])
|
||||
if (profile?.name) {
|
||||
await this.activateProviderProfile({ name: profile.name })
|
||||
}
|
||||
} else {
|
||||
// If no saved config for this mode, save current config as default
|
||||
// If no saved config for this mode, save current config as default.
|
||||
const currentApiConfigName = this.getGlobalState("currentApiConfigName")
|
||||
|
||||
if (currentApiConfigName) {
|
||||
const config = listApiConfig?.find((c) => c.name === currentApiConfigName)
|
||||
const config = listApiConfig.find((c) => c.name === currentApiConfigName)
|
||||
|
||||
if (config?.id) {
|
||||
await this.providerSettingsManager.setModeConfig(newMode, config.id)
|
||||
|
|
@ -807,27 +795,127 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
await this.postStateToWebview()
|
||||
}
|
||||
|
||||
async updateApiConfiguration(providerSettings: ProviderSettings) {
|
||||
// Update mode's default config.
|
||||
const { mode } = await this.getState()
|
||||
// Provider Profile Management
|
||||
|
||||
if (mode) {
|
||||
const currentApiConfigName = this.getGlobalState("currentApiConfigName")
|
||||
const listApiConfig = await this.providerSettingsManager.listConfig()
|
||||
const config = listApiConfig?.find((c) => c.name === currentApiConfigName)
|
||||
getProviderProfileEntries(): ProviderSettingsEntry[] {
|
||||
return this.contextProxy.getValues().listApiConfigMeta || []
|
||||
}
|
||||
|
||||
if (config?.id) {
|
||||
await this.providerSettingsManager.setModeConfig(mode, config.id)
|
||||
getProviderProfileEntry(name: string): ProviderSettingsEntry | undefined {
|
||||
return this.getProviderProfileEntries().find((profile) => profile.name === name)
|
||||
}
|
||||
|
||||
public hasProviderProfileEntry(name: string): boolean {
|
||||
return !!this.getProviderProfileEntry(name)
|
||||
}
|
||||
|
||||
async upsertProviderProfile(
|
||||
name: string,
|
||||
providerSettings: ProviderSettings,
|
||||
activate: boolean = true,
|
||||
): Promise<string | undefined> {
|
||||
try {
|
||||
// TODO: Do we need to be calling `activateProfile`? It's not
|
||||
// clear to me what the source of truth should be; in some cases
|
||||
// we rely on the `ContextProxy`'s data store and in other cases
|
||||
// we rely on the `ProviderSettingsManager`'s data store. It might
|
||||
// be simpler to unify these two.
|
||||
const id = await this.providerSettingsManager.saveConfig(name, providerSettings)
|
||||
|
||||
if (activate) {
|
||||
const { mode } = await this.getState()
|
||||
|
||||
// These promises do the following:
|
||||
// 1. Adds or updates the list of provider profiles.
|
||||
// 2. Sets the current provider profile.
|
||||
// 3. Sets the current mode's provider profile.
|
||||
// 4. Copies the provider settings to the context.
|
||||
//
|
||||
// Note: 1, 2, and 4 can be done in one `ContextProxy` call:
|
||||
// this.contextProxy.setValues({ ...providerSettings, listApiConfigMeta: ..., currentApiConfigName: ... })
|
||||
// We should probably switch to that and verify that it works.
|
||||
// I left the original implementation in just to be safe.
|
||||
await Promise.all([
|
||||
this.updateGlobalState("listApiConfigMeta", await this.providerSettingsManager.listConfig()),
|
||||
this.updateGlobalState("currentApiConfigName", name),
|
||||
this.providerSettingsManager.setModeConfig(mode, id),
|
||||
this.contextProxy.setProviderSettings(providerSettings),
|
||||
])
|
||||
|
||||
// Change the provider for the current task.
|
||||
// TODO: We should rename `buildApiHandler` for clarity (e.g. `getProviderClient`).
|
||||
const task = this.getCurrentCline()
|
||||
|
||||
if (task) {
|
||||
task.api = buildApiHandler(providerSettings)
|
||||
}
|
||||
} else {
|
||||
await this.updateGlobalState("listApiConfigMeta", await this.providerSettingsManager.listConfig())
|
||||
}
|
||||
}
|
||||
|
||||
await this.contextProxy.setProviderSettings(providerSettings)
|
||||
await this.postStateToWebview()
|
||||
return id
|
||||
} catch (error) {
|
||||
this.log(
|
||||
`Error create new api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
|
||||
)
|
||||
|
||||
if (this.getCurrentCline()) {
|
||||
this.getCurrentCline()!.api = buildApiHandler(providerSettings)
|
||||
vscode.window.showErrorMessage(t("common:errors.create_api_config"))
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
async deleteProviderProfile(profileToDelete: ProviderSettingsEntry) {
|
||||
const globalSettings = this.contextProxy.getValues()
|
||||
let profileToActivate: string | undefined = globalSettings.currentApiConfigName
|
||||
|
||||
if (profileToDelete.name === profileToActivate) {
|
||||
profileToActivate = this.getProviderProfileEntries().find(({ name }) => name !== profileToDelete.name)?.name
|
||||
}
|
||||
|
||||
if (!profileToActivate) {
|
||||
throw new Error("You cannot delete the last profile")
|
||||
}
|
||||
|
||||
const entries = this.getProviderProfileEntries().filter(({ name }) => name !== profileToDelete.name)
|
||||
|
||||
await this.contextProxy.setValues({
|
||||
...globalSettings,
|
||||
currentApiConfigName: profileToActivate,
|
||||
listApiConfigMeta: entries,
|
||||
})
|
||||
|
||||
await this.postStateToWebview()
|
||||
}
|
||||
|
||||
async activateProviderProfile(args: { name: string } | { id: string }) {
|
||||
const { name, id, ...providerSettings } = await this.providerSettingsManager.activateProfile(args)
|
||||
|
||||
// See `upsertProviderProfile` for a description of what this is doing.
|
||||
await Promise.all([
|
||||
this.contextProxy.setValue("listApiConfigMeta", await this.providerSettingsManager.listConfig()),
|
||||
this.contextProxy.setValue("currentApiConfigName", name),
|
||||
this.contextProxy.setProviderSettings(providerSettings),
|
||||
])
|
||||
|
||||
const { mode } = await this.getState()
|
||||
|
||||
if (id) {
|
||||
await this.providerSettingsManager.setModeConfig(mode, id)
|
||||
}
|
||||
|
||||
// Change the provider for the current task.
|
||||
const task = this.getCurrentCline()
|
||||
|
||||
if (task) {
|
||||
task.api = buildApiHandler(providerSettings)
|
||||
}
|
||||
|
||||
await this.postStateToWebview()
|
||||
}
|
||||
|
||||
// Task Management
|
||||
|
||||
async cancelTask() {
|
||||
const cline = this.getCurrentCline()
|
||||
|
||||
|
|
@ -936,14 +1024,14 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
throw error
|
||||
}
|
||||
|
||||
const newConfiguration: ApiConfiguration = {
|
||||
const newConfiguration: ProviderSettings = {
|
||||
...apiConfiguration,
|
||||
apiProvider: "openrouter",
|
||||
openRouterApiKey: apiKey,
|
||||
openRouterModelId: apiConfiguration?.openRouterModelId || openRouterDefaultModelId,
|
||||
}
|
||||
|
||||
await this.upsertApiConfiguration(currentApiConfigName, newConfiguration)
|
||||
await this.upsertProviderProfile(currentApiConfigName, newConfiguration)
|
||||
}
|
||||
|
||||
// Glama
|
||||
|
|
@ -966,14 +1054,14 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
|
||||
const { apiConfiguration, currentApiConfigName } = await this.getState()
|
||||
|
||||
const newConfiguration: ApiConfiguration = {
|
||||
const newConfiguration: ProviderSettings = {
|
||||
...apiConfiguration,
|
||||
apiProvider: "glama",
|
||||
glamaApiKey: apiKey,
|
||||
glamaModelId: apiConfiguration?.glamaModelId || glamaDefaultModelId,
|
||||
}
|
||||
|
||||
await this.upsertApiConfiguration(currentApiConfigName, newConfiguration)
|
||||
await this.upsertProviderProfile(currentApiConfigName, newConfiguration)
|
||||
}
|
||||
|
||||
// Requesty
|
||||
|
|
@ -981,36 +1069,14 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
async handleRequestyCallback(code: string) {
|
||||
let { apiConfiguration, currentApiConfigName } = await this.getState()
|
||||
|
||||
const newConfiguration: ApiConfiguration = {
|
||||
const newConfiguration: ProviderSettings = {
|
||||
...apiConfiguration,
|
||||
apiProvider: "requesty",
|
||||
requestyApiKey: code,
|
||||
requestyModelId: apiConfiguration?.requestyModelId || requestyDefaultModelId,
|
||||
}
|
||||
|
||||
await this.upsertApiConfiguration(currentApiConfigName, newConfiguration)
|
||||
}
|
||||
|
||||
// Save configuration
|
||||
|
||||
async upsertApiConfiguration(configName: string, apiConfiguration: ApiConfiguration) {
|
||||
try {
|
||||
await this.providerSettingsManager.saveConfig(configName, apiConfiguration)
|
||||
const listApiConfig = await this.providerSettingsManager.listConfig()
|
||||
|
||||
await Promise.all([
|
||||
this.updateGlobalState("listApiConfigMeta", listApiConfig),
|
||||
this.updateApiConfiguration(apiConfiguration),
|
||||
this.updateGlobalState("currentApiConfigName", configName),
|
||||
])
|
||||
|
||||
await this.postStateToWebview()
|
||||
} catch (error) {
|
||||
this.log(
|
||||
`Error create new api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
|
||||
)
|
||||
vscode.window.showErrorMessage(t("common:errors.create_api_config"))
|
||||
}
|
||||
await this.upsertProviderProfile(currentApiConfigName, newConfiguration)
|
||||
}
|
||||
|
||||
// Task history
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import * as vscode from "vscode"
|
|||
import axios from "axios"
|
||||
|
||||
import { ClineProvider } from "../ClineProvider"
|
||||
import { ClineMessage, ExtensionMessage, ExtensionState } from "../../../shared/ExtensionMessage"
|
||||
import { ProviderSettingsEntry, ClineMessage, ExtensionMessage, ExtensionState } from "../../../shared/ExtensionMessage"
|
||||
import { setSoundEnabled } from "../../../utils/sound"
|
||||
import { setTtsEnabled } from "../../../utils/tts"
|
||||
import { defaultModeSlug } from "../../../shared/modes"
|
||||
|
|
@ -227,12 +227,6 @@ jest.mock("../../../integrations/misc/extract-text", () => ({
|
|||
}),
|
||||
}))
|
||||
|
||||
// Spy on console.error and console.log to suppress expected messages
|
||||
beforeAll(() => {
|
||||
jest.spyOn(console, "error").mockImplementation(() => {})
|
||||
jest.spyOn(console, "log").mockImplementation(() => {})
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
|
@ -596,14 +590,16 @@ describe("ClineProvider", () => {
|
|||
expect(state.alwaysApproveResubmit).toBe(false)
|
||||
})
|
||||
|
||||
test("loads saved API config when switching modes", async () => {
|
||||
it("loads saved API config when switching modes", async () => {
|
||||
await provider.resolveWebviewView(mockWebviewView)
|
||||
const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as jest.Mock).mock.calls[0][0]
|
||||
|
||||
const profile: ProviderSettingsEntry = { name: "test-config", id: "test-id", apiProvider: "anthropic" }
|
||||
|
||||
;(provider as any).providerSettingsManager = {
|
||||
getModeConfigId: jest.fn().mockResolvedValue("test-id"),
|
||||
listConfig: jest.fn().mockResolvedValue([{ name: "test-config", id: "test-id", apiProvider: "anthropic" }]),
|
||||
loadConfig: jest.fn().mockResolvedValue({ apiProvider: "anthropic" }),
|
||||
listConfig: jest.fn().mockResolvedValue([profile]),
|
||||
activateProfile: jest.fn().mockResolvedValue(profile),
|
||||
setModeConfig: jest.fn(),
|
||||
} as any
|
||||
|
||||
|
|
@ -612,11 +608,11 @@ describe("ClineProvider", () => {
|
|||
|
||||
// Should load the saved config for architect mode
|
||||
expect(provider.providerSettingsManager.getModeConfigId).toHaveBeenCalledWith("architect")
|
||||
expect(provider.providerSettingsManager.loadConfig).toHaveBeenCalledWith("test-config")
|
||||
expect(provider.providerSettingsManager.activateProfile).toHaveBeenCalledWith({ name: "test-config" })
|
||||
expect(mockContext.globalState.update).toHaveBeenCalledWith("currentApiConfigName", "test-config")
|
||||
})
|
||||
|
||||
test("saves current config when switching to mode without config", async () => {
|
||||
it("saves current config when switching to mode without config", async () => {
|
||||
await provider.resolveWebviewView(mockWebviewView)
|
||||
const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as jest.Mock).mock.calls[0][0]
|
||||
|
||||
|
|
@ -637,16 +633,15 @@ describe("ClineProvider", () => {
|
|||
expect(provider.providerSettingsManager.setModeConfig).toHaveBeenCalledWith("architect", "current-id")
|
||||
})
|
||||
|
||||
test("saves config as default for current mode when loading config", async () => {
|
||||
it("saves config as default for current mode when loading config", async () => {
|
||||
await provider.resolveWebviewView(mockWebviewView)
|
||||
const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as jest.Mock).mock.calls[0][0]
|
||||
|
||||
const profile: ProviderSettingsEntry = { apiProvider: "anthropic", id: "new-id", name: "new-config" }
|
||||
|
||||
;(provider as any).providerSettingsManager = {
|
||||
loadConfig: jest.fn().mockResolvedValue({ apiProvider: "anthropic", id: "new-id" }),
|
||||
loadConfigById: jest
|
||||
.fn()
|
||||
.mockResolvedValue({ config: { apiProvider: "anthropic", id: "new-id" }, name: "new-config" }),
|
||||
listConfig: jest.fn().mockResolvedValue([{ name: "new-config", id: "new-id", apiProvider: "anthropic" }]),
|
||||
activateProfile: jest.fn().mockResolvedValue(profile),
|
||||
listConfig: jest.fn().mockResolvedValue([profile]),
|
||||
setModeConfig: jest.fn(),
|
||||
getModeConfigId: jest.fn().mockResolvedValue(undefined),
|
||||
} as any
|
||||
|
|
@ -661,18 +656,19 @@ describe("ClineProvider", () => {
|
|||
expect(provider.providerSettingsManager.setModeConfig).toHaveBeenCalledWith("architect", "new-id")
|
||||
})
|
||||
|
||||
test("load API configuration by ID works and updates mode config", async () => {
|
||||
it("load API configuration by ID works and updates mode config", async () => {
|
||||
await provider.resolveWebviewView(mockWebviewView)
|
||||
const messageHandler = (mockWebviewView.webview.onDidReceiveMessage as jest.Mock).mock.calls[0][0]
|
||||
|
||||
const profile: ProviderSettingsEntry = {
|
||||
name: "config-by-id",
|
||||
id: "config-id-123",
|
||||
apiProvider: "anthropic",
|
||||
}
|
||||
|
||||
;(provider as any).providerSettingsManager = {
|
||||
loadConfigById: jest.fn().mockResolvedValue({
|
||||
config: { apiProvider: "anthropic", id: "config-id-123" },
|
||||
name: "config-by-id",
|
||||
}),
|
||||
listConfig: jest
|
||||
.fn()
|
||||
.mockResolvedValue([{ name: "config-by-id", id: "config-id-123", apiProvider: "anthropic" }]),
|
||||
activateProfile: jest.fn().mockResolvedValue(profile),
|
||||
listConfig: jest.fn().mockResolvedValue([profile]),
|
||||
setModeConfig: jest.fn(),
|
||||
getModeConfigId: jest.fn().mockResolvedValue(undefined),
|
||||
} as any
|
||||
|
|
@ -686,8 +682,8 @@ describe("ClineProvider", () => {
|
|||
// Should save new config as default for architect mode
|
||||
expect(provider.providerSettingsManager.setModeConfig).toHaveBeenCalledWith("architect", "config-id-123")
|
||||
|
||||
// Ensure the loadConfigById method was called with the correct ID
|
||||
expect(provider.providerSettingsManager.loadConfigById).toHaveBeenCalledWith("config-id-123")
|
||||
// Ensure the `activateProfile` method was called with the correct ID
|
||||
expect(provider.providerSettingsManager.activateProfile).toHaveBeenCalledWith({ id: "config-id-123" })
|
||||
})
|
||||
|
||||
test("handles browserToolEnabled setting", async () => {
|
||||
|
|
@ -886,7 +882,7 @@ describe("ClineProvider", () => {
|
|||
})
|
||||
})
|
||||
|
||||
test("saves mode config when updating API configuration", async () => {
|
||||
it("saves mode config when updating API configuration", async () => {
|
||||
// Setup mock context with mode and config name
|
||||
mockContext = {
|
||||
...mockContext,
|
||||
|
|
@ -912,12 +908,14 @@ describe("ClineProvider", () => {
|
|||
|
||||
;(provider as any).providerSettingsManager = {
|
||||
listConfig: jest.fn().mockResolvedValue([{ name: "test-config", id: "test-id", apiProvider: "anthropic" }]),
|
||||
saveConfig: jest.fn().mockResolvedValue("test-id"),
|
||||
setModeConfig: jest.fn(),
|
||||
} as any
|
||||
|
||||
// Update API configuration
|
||||
await messageHandler({
|
||||
type: "apiConfiguration",
|
||||
type: "upsertApiConfiguration",
|
||||
text: "test-config",
|
||||
apiConfiguration: { apiProvider: "anthropic" },
|
||||
})
|
||||
|
||||
|
|
@ -1542,13 +1540,17 @@ describe("ClineProvider", () => {
|
|||
await provider.resolveWebviewView(mockWebviewView)
|
||||
})
|
||||
|
||||
test("loads saved API config when switching modes", async () => {
|
||||
it("loads saved API config when switching modes", async () => {
|
||||
const profile: ProviderSettingsEntry = {
|
||||
name: "saved-config",
|
||||
id: "saved-config-id",
|
||||
apiProvider: "anthropic",
|
||||
}
|
||||
|
||||
;(provider as any).providerSettingsManager = {
|
||||
getModeConfigId: jest.fn().mockResolvedValue("saved-config-id"),
|
||||
listConfig: jest
|
||||
.fn()
|
||||
.mockResolvedValue([{ name: "saved-config", id: "saved-config-id", apiProvider: "anthropic" }]),
|
||||
loadConfig: jest.fn().mockResolvedValue({ apiProvider: "anthropic" }),
|
||||
listConfig: jest.fn().mockResolvedValue([profile]),
|
||||
activateProfile: jest.fn().mockResolvedValue(profile),
|
||||
setModeConfig: jest.fn(),
|
||||
} as any
|
||||
|
||||
|
|
@ -1560,7 +1562,7 @@ describe("ClineProvider", () => {
|
|||
|
||||
// Verify saved config was loaded
|
||||
expect(provider.providerSettingsManager.getModeConfigId).toHaveBeenCalledWith("architect")
|
||||
expect(provider.providerSettingsManager.loadConfig).toHaveBeenCalledWith("saved-config")
|
||||
expect(provider.providerSettingsManager.activateProfile).toHaveBeenCalledWith({ name: "saved-config" })
|
||||
expect(mockContext.globalState.update).toHaveBeenCalledWith("currentApiConfigName", "saved-config")
|
||||
|
||||
// Verify state was posted to webview
|
||||
|
|
@ -1676,14 +1678,11 @@ describe("ClineProvider", () => {
|
|||
currentApiConfigName: "test-config",
|
||||
} as any)
|
||||
|
||||
// Trigger updateApiConfiguration
|
||||
// Trigger upsertApiConfiguration
|
||||
await messageHandler({
|
||||
type: "upsertApiConfiguration",
|
||||
text: "test-config",
|
||||
apiConfiguration: {
|
||||
apiProvider: "anthropic",
|
||||
apiKey: "test-key",
|
||||
},
|
||||
apiConfiguration: { apiProvider: "anthropic", apiKey: "test-key" },
|
||||
})
|
||||
|
||||
// Verify error was logged and user was notified
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import pWaitFor from "p-wait-for"
|
|||
import * as vscode from "vscode"
|
||||
|
||||
import { ClineProvider } from "./ClineProvider"
|
||||
import { Language, ApiConfigMeta } from "../../schemas"
|
||||
import { Language, ProviderSettings } from "../../schemas"
|
||||
import { changeLanguage, t } from "../../i18n"
|
||||
import { ApiConfiguration, RouterName, toRouterName } from "../../shared/api"
|
||||
import { RouterName, toRouterName } from "../../shared/api"
|
||||
import { supportPrompt } from "../../shared/support-prompt"
|
||||
|
||||
import { checkoutDiffPayloadSchema, checkoutRestorePayloadSchema, WebviewMessage } from "../../shared/WebviewMessage"
|
||||
|
|
@ -89,19 +89,12 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|||
|
||||
if (currentConfigName) {
|
||||
if (!(await provider.providerSettingsManager.hasConfig(currentConfigName))) {
|
||||
// current config name not valid, get first config in list
|
||||
await updateGlobalState("currentApiConfigName", listApiConfig?.[0]?.name)
|
||||
if (listApiConfig?.[0]?.name) {
|
||||
const apiConfig = await provider.providerSettingsManager.loadConfig(
|
||||
listApiConfig?.[0]?.name,
|
||||
)
|
||||
// Current config name not valid, get first config in list.
|
||||
const name = listApiConfig[0]?.name
|
||||
await updateGlobalState("currentApiConfigName", name)
|
||||
|
||||
await Promise.all([
|
||||
updateGlobalState("listApiConfigMeta", listApiConfig),
|
||||
provider.postMessageToWebview({ type: "listApiConfig", listApiConfig }),
|
||||
provider.updateApiConfiguration(apiConfig),
|
||||
])
|
||||
await provider.postStateToWebview()
|
||||
if (name) {
|
||||
await provider.activateProviderProfile({ name })
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -133,12 +126,6 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|||
// task. This essentially creates a fresh slate for the new task.
|
||||
await provider.initClineWithTask(message.text, message.images)
|
||||
break
|
||||
case "apiConfiguration":
|
||||
if (message.apiConfiguration) {
|
||||
await provider.updateApiConfiguration(message.apiConfiguration)
|
||||
}
|
||||
await provider.postStateToWebview()
|
||||
break
|
||||
case "customInstructions":
|
||||
await provider.updateCustomInstructions(message.text)
|
||||
break
|
||||
|
|
@ -939,45 +926,36 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|||
const { apiConfiguration, customSupportPrompts, listApiConfigMeta, enhancementApiConfigId } =
|
||||
await provider.getState()
|
||||
|
||||
// Try to get enhancement config first, fall back to current config
|
||||
let configToUse: ApiConfiguration = apiConfiguration
|
||||
if (enhancementApiConfigId) {
|
||||
const config = listApiConfigMeta?.find((c: ApiConfigMeta) => c.id === enhancementApiConfigId)
|
||||
if (config?.name) {
|
||||
const loadedConfig = await provider.providerSettingsManager.loadConfig(config.name)
|
||||
if (loadedConfig.apiProvider) {
|
||||
configToUse = loadedConfig
|
||||
}
|
||||
// Try to get enhancement config first, fall back to current config.
|
||||
let configToUse: ProviderSettings = apiConfiguration
|
||||
|
||||
if (enhancementApiConfigId && !!listApiConfigMeta.find(({ id }) => id === enhancementApiConfigId)) {
|
||||
const { name: _, ...providerSettings } = await provider.providerSettingsManager.getProfile({
|
||||
id: enhancementApiConfigId,
|
||||
})
|
||||
|
||||
if (providerSettings.apiProvider) {
|
||||
configToUse = providerSettings
|
||||
}
|
||||
}
|
||||
|
||||
const enhancedPrompt = await singleCompletionHandler(
|
||||
configToUse,
|
||||
supportPrompt.create(
|
||||
"ENHANCE",
|
||||
{
|
||||
userInput: message.text,
|
||||
},
|
||||
customSupportPrompts,
|
||||
),
|
||||
supportPrompt.create("ENHANCE", { userInput: message.text }, customSupportPrompts),
|
||||
)
|
||||
|
||||
// Capture telemetry for prompt enhancement
|
||||
// Capture telemetry for prompt enhancement.
|
||||
const currentCline = provider.getCurrentCline()
|
||||
telemetryService.capturePromptEnhanced(currentCline?.taskId)
|
||||
|
||||
await provider.postMessageToWebview({
|
||||
type: "enhancedPrompt",
|
||||
text: enhancedPrompt,
|
||||
})
|
||||
await provider.postMessageToWebview({ type: "enhancedPrompt", text: enhancedPrompt })
|
||||
} catch (error) {
|
||||
provider.log(
|
||||
`Error enhancing prompt: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
|
||||
)
|
||||
|
||||
vscode.window.showErrorMessage(t("common:errors.enhance_prompt"))
|
||||
await provider.postMessageToWebview({
|
||||
type: "enhancedPrompt",
|
||||
})
|
||||
await provider.postMessageToWebview({ type: "enhancedPrompt" })
|
||||
}
|
||||
}
|
||||
break
|
||||
|
|
@ -1084,7 +1062,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|||
break
|
||||
case "upsertApiConfiguration":
|
||||
if (message.text && message.apiConfiguration) {
|
||||
await provider.upsertApiConfiguration(message.text, message.apiConfiguration)
|
||||
await provider.upsertProviderProfile(message.text, message.apiConfiguration)
|
||||
}
|
||||
break
|
||||
case "renameApiConfiguration":
|
||||
|
|
@ -1096,30 +1074,23 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|||
break
|
||||
}
|
||||
|
||||
// Load the old configuration to get its ID
|
||||
const oldConfig = await provider.providerSettingsManager.loadConfig(oldName)
|
||||
// Load the old configuration to get its ID.
|
||||
const { id } = await provider.providerSettingsManager.getProfile({ name: oldName })
|
||||
|
||||
// Create a new configuration with the same ID
|
||||
const newConfig = {
|
||||
...message.apiConfiguration,
|
||||
id: oldConfig.id, // Preserve the ID
|
||||
}
|
||||
// Create a new configuration with the new name and old ID.
|
||||
await provider.providerSettingsManager.saveConfig(newName, { ...message.apiConfiguration, id })
|
||||
|
||||
// Save with the new name but same ID
|
||||
await provider.providerSettingsManager.saveConfig(newName, newConfig)
|
||||
// Delete the old configuration.
|
||||
await provider.providerSettingsManager.deleteConfig(oldName)
|
||||
|
||||
const listApiConfig = await provider.providerSettingsManager.listConfig()
|
||||
|
||||
// Update listApiConfigMeta first to ensure UI has latest data
|
||||
await updateGlobalState("listApiConfigMeta", listApiConfig)
|
||||
await updateGlobalState("currentApiConfigName", newName)
|
||||
|
||||
await provider.postStateToWebview()
|
||||
// Re-activate to update the global settings related to the
|
||||
// currently activated provider profile.
|
||||
await provider.activateProviderProfile({ name: newName })
|
||||
} catch (error) {
|
||||
provider.log(
|
||||
`Error rename api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
|
||||
)
|
||||
|
||||
vscode.window.showErrorMessage(t("common:errors.rename_api_config"))
|
||||
}
|
||||
}
|
||||
|
|
@ -1127,16 +1098,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|||
case "loadApiConfiguration":
|
||||
if (message.text) {
|
||||
try {
|
||||
const apiConfig = await provider.providerSettingsManager.loadConfig(message.text)
|
||||
const listApiConfig = await provider.providerSettingsManager.listConfig()
|
||||
|
||||
await Promise.all([
|
||||
updateGlobalState("listApiConfigMeta", listApiConfig),
|
||||
updateGlobalState("currentApiConfigName", message.text),
|
||||
provider.updateApiConfiguration(apiConfig),
|
||||
])
|
||||
|
||||
await provider.postStateToWebview()
|
||||
await provider.activateProviderProfile({ name: message.text })
|
||||
} catch (error) {
|
||||
provider.log(
|
||||
`Error load api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
|
||||
|
|
@ -1148,18 +1110,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|||
case "loadApiConfigurationById":
|
||||
if (message.text) {
|
||||
try {
|
||||
const { config: apiConfig, name } = await provider.providerSettingsManager.loadConfigById(
|
||||
message.text,
|
||||
)
|
||||
const listApiConfig = await provider.providerSettingsManager.listConfig()
|
||||
|
||||
await Promise.all([
|
||||
updateGlobalState("listApiConfigMeta", listApiConfig),
|
||||
updateGlobalState("currentApiConfigName", name),
|
||||
provider.updateApiConfiguration(apiConfig),
|
||||
])
|
||||
|
||||
await provider.postStateToWebview()
|
||||
await provider.activateProviderProfile({ id: message.text })
|
||||
} catch (error) {
|
||||
provider.log(
|
||||
`Error load api configuration by ID: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
|
||||
|
|
@ -1180,29 +1131,25 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|||
break
|
||||
}
|
||||
|
||||
const oldName = message.text
|
||||
|
||||
const newName = (await provider.providerSettingsManager.listConfig()).filter(
|
||||
(c) => c.name !== oldName,
|
||||
)[0]?.name
|
||||
|
||||
if (!newName) {
|
||||
vscode.window.showErrorMessage(t("common:errors.delete_api_config"))
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await provider.providerSettingsManager.deleteConfig(message.text)
|
||||
const listApiConfig = await provider.providerSettingsManager.listConfig()
|
||||
|
||||
// Update listApiConfigMeta first to ensure UI has latest data
|
||||
await updateGlobalState("listApiConfigMeta", listApiConfig)
|
||||
|
||||
// If this was the current config, switch to first available
|
||||
const currentApiConfigName = getGlobalState("currentApiConfigName")
|
||||
|
||||
if (message.text === currentApiConfigName && listApiConfig?.[0]?.name) {
|
||||
const apiConfig = await provider.providerSettingsManager.loadConfig(listApiConfig[0].name)
|
||||
await Promise.all([
|
||||
updateGlobalState("currentApiConfigName", listApiConfig[0].name),
|
||||
provider.updateApiConfiguration(apiConfig),
|
||||
])
|
||||
}
|
||||
|
||||
await provider.postStateToWebview()
|
||||
await provider.providerSettingsManager.deleteConfig(oldName)
|
||||
await provider.activateProviderProfile({ name: newName })
|
||||
} catch (error) {
|
||||
provider.log(
|
||||
`Error delete api configuration: ${JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}`,
|
||||
)
|
||||
|
||||
vscode.window.showErrorMessage(t("common:errors.delete_api_config"))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,14 @@ import * as path from "path"
|
|||
import { getWorkspacePath } from "../utils/path"
|
||||
import { ClineProvider } from "../core/webview/ClineProvider"
|
||||
import { openClineInNewTab } from "../activate/registerCommands"
|
||||
import { RooCodeSettings, RooCodeEvents, RooCodeEventName } from "../schemas"
|
||||
import {
|
||||
RooCodeSettings,
|
||||
RooCodeEvents,
|
||||
RooCodeEventName,
|
||||
ProviderSettings,
|
||||
ProviderSettingsEntry,
|
||||
isSecretStateKey,
|
||||
} from "../schemas"
|
||||
import { IpcOrigin, IpcMessageType, TaskCommandName, TaskEvent } from "../schemas/ipc"
|
||||
|
||||
import { RooCodeAPI } from "./interface"
|
||||
|
|
@ -178,91 +185,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
|
||||
}
|
||||
|
||||
public getProfiles() {
|
||||
return (this.getConfiguration().listApiConfigMeta || []).map((profile) => profile.name)
|
||||
}
|
||||
|
||||
public async setActiveProfile(name: string) {
|
||||
const currentSettings = this.getConfiguration()
|
||||
const profiles = currentSettings.listApiConfigMeta || []
|
||||
|
||||
const profile = profiles.find((p) => p.name === name)
|
||||
|
||||
if (!profile) {
|
||||
throw new Error(`Profile with name "${name}" does not exist`)
|
||||
}
|
||||
|
||||
await this.setConfiguration({ ...currentSettings, currentApiConfigName: profile.name })
|
||||
}
|
||||
|
||||
public getActiveProfile() {
|
||||
return this.getConfiguration().currentApiConfigName
|
||||
}
|
||||
|
||||
public async deleteProfile(name: string) {
|
||||
const currentSettings = this.getConfiguration()
|
||||
const profiles = currentSettings.listApiConfigMeta || []
|
||||
const targetIndex = profiles.findIndex((p) => p.name === name)
|
||||
|
||||
if (targetIndex === -1) {
|
||||
throw new Error(`Profile with name "${name}" does not exist`)
|
||||
}
|
||||
|
||||
const profileToDelete = profiles[targetIndex]
|
||||
profiles.splice(targetIndex, 1)
|
||||
|
||||
// If we're deleting the active profile, clear the currentApiConfigName.
|
||||
const newSettings: RooCodeSettings = {
|
||||
...currentSettings,
|
||||
listApiConfigMeta: profiles,
|
||||
currentApiConfigName:
|
||||
currentSettings.currentApiConfigName === profileToDelete.name
|
||||
? undefined
|
||||
: currentSettings.currentApiConfigName,
|
||||
}
|
||||
|
||||
await this.setConfiguration(newSettings)
|
||||
}
|
||||
|
||||
public isReady() {
|
||||
return this.sidebarProvider.viewLaunched
|
||||
}
|
||||
|
|
@ -328,4 +250,103 @@ export class API extends EventEmitter<RooCodeEvents> implements RooCodeAPI {
|
|||
this.logfile = undefined
|
||||
}
|
||||
}
|
||||
|
||||
// Global Settings Management
|
||||
|
||||
public getConfiguration(): RooCodeSettings {
|
||||
return Object.fromEntries(
|
||||
Object.entries(this.sidebarProvider.getValues()).filter(([key]) => !isSecretStateKey(key)),
|
||||
)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
public getProfiles(): string[] {
|
||||
return this.sidebarProvider.getProviderProfileEntries().map(({ name }) => name)
|
||||
}
|
||||
|
||||
public getProfileEntry(name: string): ProviderSettingsEntry | undefined {
|
||||
return this.sidebarProvider.getProviderProfileEntry(name)
|
||||
}
|
||||
|
||||
public async createProfile(name: string, profile?: ProviderSettings, activate: boolean = true) {
|
||||
const entry = this.getProfileEntry(name)
|
||||
|
||||
if (entry) {
|
||||
throw new Error(`Profile with name "${name}" already exists`)
|
||||
}
|
||||
|
||||
const id = await this.sidebarProvider.upsertProviderProfile(name, profile ?? {}, activate)
|
||||
|
||||
if (!id) {
|
||||
throw new Error(`Failed to create profile with name "${name}"`)
|
||||
}
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
public async updateProfile(
|
||||
name: string,
|
||||
profile: ProviderSettings,
|
||||
activate: boolean = true,
|
||||
): Promise<string | undefined> {
|
||||
const entry = this.getProfileEntry(name)
|
||||
|
||||
if (!entry) {
|
||||
throw new Error(`Profile with name "${name}" does not exist`)
|
||||
}
|
||||
|
||||
const id = await this.sidebarProvider.upsertProviderProfile(name, profile, activate)
|
||||
|
||||
if (!id) {
|
||||
throw new Error(`Failed to update profile with name "${name}"`)
|
||||
}
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
public async upsertProfile(
|
||||
name: string,
|
||||
profile: ProviderSettings,
|
||||
activate: boolean = true,
|
||||
): Promise<string | undefined> {
|
||||
const id = await this.sidebarProvider.upsertProviderProfile(name, profile, activate)
|
||||
|
||||
if (!id) {
|
||||
throw new Error(`Failed to upsert profile with name "${name}"`)
|
||||
}
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
public async deleteProfile(name: string): Promise<void> {
|
||||
const entry = this.getProfileEntry(name)
|
||||
|
||||
if (!entry) {
|
||||
throw new Error(`Profile with name "${name}" does not exist`)
|
||||
}
|
||||
|
||||
await this.sidebarProvider.deleteProviderProfile(entry)
|
||||
}
|
||||
|
||||
public getActiveProfile(): string | undefined {
|
||||
return this.getConfiguration().currentApiConfigName
|
||||
}
|
||||
|
||||
public async setActiveProfile(name: string): Promise<string | undefined> {
|
||||
const entry = this.getProfileEntry(name)
|
||||
|
||||
if (!entry) {
|
||||
throw new Error(`Profile with name "${name}" does not exist`)
|
||||
}
|
||||
|
||||
await this.sidebarProvider.activateProviderProfile({ name })
|
||||
return this.getActiveProfile()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,17 +114,40 @@ export interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
|
|||
getProfiles(): string[]
|
||||
|
||||
/**
|
||||
* Changes the active API configuration profile
|
||||
* @param name The name of the profile to activate
|
||||
* @throws Error if the profile does not exist
|
||||
* Returns the profile entry for a given name
|
||||
* @param name The name of the profile
|
||||
* @returns The profile entry, or undefined if the profile does not exist
|
||||
*/
|
||||
setActiveProfile(name: string): Promise<void>
|
||||
getProfileEntry(name: string): ProviderSettingsEntry | undefined
|
||||
|
||||
/**
|
||||
* Returns the name of the currently active profile
|
||||
* @returns The profile name, or undefined if no profile is active
|
||||
* Creates a new API configuration profile
|
||||
* @param name The name of the profile
|
||||
* @param profile The profile to create; defaults to an empty object
|
||||
* @param activate Whether to activate the profile after creation; defaults to true
|
||||
* @returns The ID of the created profile
|
||||
* @throws Error if the profile already exists
|
||||
*/
|
||||
getActiveProfile(): string | undefined
|
||||
createProfile(name: string, profile?: ProviderSettings, activate?: boolean): Promise<string>
|
||||
|
||||
/**
|
||||
* Updates an existing API configuration profile
|
||||
* @param name The name of the profile
|
||||
* @param profile The profile to update
|
||||
* @param activate Whether to activate the profile after update; defaults to true
|
||||
* @returns The ID of the updated profile
|
||||
* @throws Error if the profile does not exist
|
||||
*/
|
||||
updateProfile(name: string, profile: ProviderSettings, activate?: boolean): Promise<string | undefined>
|
||||
|
||||
/**
|
||||
* Creates a new API configuration profile or updates an existing one
|
||||
* @param name The name of the profile
|
||||
* @param profile The profile to create or update; defaults to an empty object
|
||||
* @param activate Whether to activate the profile after upsert; defaults to true
|
||||
* @returns The ID of the upserted profile
|
||||
*/
|
||||
upsertProfile(name: string, profile: ProviderSettings, activate?: boolean): Promise<string | undefined>
|
||||
|
||||
/**
|
||||
* Deletes a profile by name
|
||||
|
|
@ -120,7 +157,15 @@ export interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
|
|||
deleteProfile(name: string): Promise<void>
|
||||
|
||||
/**
|
||||
* Returns true if the API is ready to use.
|
||||
* Returns the name of the currently active profile
|
||||
* @returns The profile name, or undefined if no profile is active
|
||||
*/
|
||||
isReady(): boolean
|
||||
getActiveProfile(): string | undefined
|
||||
|
||||
/**
|
||||
* Changes the active API configuration profile
|
||||
* @param name The name of the profile to activate
|
||||
* @throws Error if the profile does not exist
|
||||
*/
|
||||
setActiveProfile(name: string): Promise<string | undefined>
|
||||
}
|
||||
|
|
|
|||
363
src/exports/roo-code.d.ts
vendored
363
src/exports/roo-code.d.ts
vendored
|
|
@ -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
|
||||
xaiApiKey?: string | undefined
|
||||
groqApiKey?: string | undefined
|
||||
chutesApiKey?: string | undefined
|
||||
litellmBaseUrl?: string | undefined
|
||||
litellmApiKey?: string | undefined
|
||||
litellmModelId?: string | undefined
|
||||
modelMaxTokens?: number | undefined
|
||||
modelMaxThinkingTokens?: number | 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
|
||||
fakeAi?: unknown | 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
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
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,28 +627,43 @@ 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
|
||||
* Returns the profile entry for a given name
|
||||
* @param name The name of the profile
|
||||
* @returns The profile entry, or undefined if the profile does not exist
|
||||
*/
|
||||
getProfileEntry(name: string): ProviderSettingsEntry | undefined
|
||||
/**
|
||||
* Creates a new API configuration profile
|
||||
* @param name The name of the profile
|
||||
* @param profile The profile to create; defaults to an empty object
|
||||
* @param activate Whether to activate the profile after creation; defaults to true
|
||||
* @returns The ID of the created profile
|
||||
* @throws Error if the profile already exists
|
||||
*/
|
||||
createProfile(name: string, profile?: ProviderSettings, activate?: boolean): Promise<string>
|
||||
/**
|
||||
* Updates an existing API configuration profile
|
||||
* @param name The name of the profile
|
||||
* @param profile The profile to update
|
||||
* @param activate Whether to activate the profile after update; defaults to true
|
||||
* @returns The ID of the updated profile
|
||||
* @throws Error if the profile does not exist
|
||||
*/
|
||||
setActiveProfile(name: string): Promise<void>
|
||||
updateProfile(name: string, profile: ProviderSettings, activate?: boolean): Promise<string | undefined>
|
||||
/**
|
||||
* Returns the name of the currently active profile
|
||||
* @returns The profile name, or undefined if no profile is active
|
||||
* Creates a new API configuration profile or updates an existing one
|
||||
* @param name The name of the profile
|
||||
* @param profile The profile to create or update; defaults to an empty object
|
||||
* @param activate Whether to activate the profile after upsert; defaults to true
|
||||
* @returns The ID of the upserted profile
|
||||
*/
|
||||
getActiveProfile(): string | undefined
|
||||
upsertProfile(name: string, profile: ProviderSettings, activate?: boolean): Promise<string | undefined>
|
||||
/**
|
||||
* Deletes a profile by name
|
||||
* @param name The name of the profile to delete
|
||||
|
|
@ -622,15 +671,23 @@ interface RooCodeAPI extends EventEmitter<RooCodeEvents> {
|
|||
*/
|
||||
deleteProfile(name: string): Promise<void>
|
||||
/**
|
||||
* Returns true if the API is ready to use.
|
||||
* Returns the name of the currently active profile
|
||||
* @returns The profile name, or undefined if no profile is active
|
||||
*/
|
||||
isReady(): boolean
|
||||
getActiveProfile(): string | undefined
|
||||
/**
|
||||
* Changes the active API configuration profile
|
||||
* @param name The name of the profile to activate
|
||||
* @throws Error if the profile does not exist
|
||||
*/
|
||||
setActiveProfile(name: string): Promise<string | undefined>
|
||||
}
|
||||
|
||||
export {
|
||||
type ClineMessage,
|
||||
type GlobalSettings,
|
||||
type ProviderSettings,
|
||||
type ProviderSettingsEntry,
|
||||
type RooCodeAPI,
|
||||
RooCodeEventName,
|
||||
type RooCodeEvents,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
xaiApiKey?: string | undefined
|
||||
groqApiKey?: string | undefined
|
||||
chutesApiKey?: string | undefined
|
||||
litellmBaseUrl?: string | undefined
|
||||
litellmApiKey?: string | undefined
|
||||
litellmModelId?: string | undefined
|
||||
modelMaxTokens?: number | undefined
|
||||
modelMaxThinkingTokens?: number | 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
|
||||
fakeAi?: unknown | 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
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -135,18 +135,6 @@ export const modelInfoSchema = z.object({
|
|||
|
||||
export type ModelInfo = z.infer<typeof modelInfoSchema>
|
||||
|
||||
/**
|
||||
* ApiConfigMeta
|
||||
*/
|
||||
|
||||
export const apiConfigMetaSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
apiProvider: providerNamesSchema.optional(),
|
||||
})
|
||||
|
||||
export type ApiConfigMeta = z.infer<typeof apiConfigMetaSchema>
|
||||
|
||||
/**
|
||||
* HistoryItem
|
||||
*/
|
||||
|
|
@ -341,27 +329,60 @@ export type Experiments = z.infer<typeof experimentsSchema>
|
|||
|
||||
type _AssertExperiments = AssertEqual<Equals<ExperimentId, Keys<Experiments>>>
|
||||
|
||||
/**
|
||||
* ProviderSettingsEntry
|
||||
*/
|
||||
|
||||
export const providerSettingsEntrySchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
apiProvider: providerNamesSchema.optional(),
|
||||
})
|
||||
|
||||
export type ProviderSettingsEntry = z.infer<typeof providerSettingsEntrySchema>
|
||||
|
||||
/**
|
||||
* ProviderSettings
|
||||
*/
|
||||
|
||||
export const providerSettingsSchema = z.object({
|
||||
apiProvider: providerNamesSchema.optional(),
|
||||
// Anthropic
|
||||
const baseProviderSettingsSchema = z.object({
|
||||
includeMaxTokens: z.boolean().optional(),
|
||||
reasoningEffort: reasoningEffortsSchema.optional(),
|
||||
promptCachingDisabled: z.boolean().optional(),
|
||||
diffEnabled: z.boolean().optional(),
|
||||
fuzzyMatchThreshold: z.number().optional(),
|
||||
modelTemperature: z.number().nullish(),
|
||||
rateLimitSeconds: z.number().optional(),
|
||||
// Claude 3.7 Sonnet Thinking
|
||||
modelMaxTokens: z.number().optional(),
|
||||
modelMaxThinkingTokens: z.number().optional(),
|
||||
})
|
||||
|
||||
// Several of the providers share common model config properties.
|
||||
const apiModelIdProviderModelSchema = baseProviderSettingsSchema.extend({
|
||||
apiModelId: z.string().optional(),
|
||||
})
|
||||
|
||||
const anthropicSchema = apiModelIdProviderModelSchema.extend({
|
||||
apiKey: z.string().optional(),
|
||||
anthropicBaseUrl: z.string().optional(),
|
||||
anthropicUseAuthToken: z.boolean().optional(),
|
||||
// Glama
|
||||
})
|
||||
|
||||
const glamaSchema = baseProviderSettingsSchema.extend({
|
||||
glamaModelId: z.string().optional(),
|
||||
glamaApiKey: z.string().optional(),
|
||||
// OpenRouter
|
||||
})
|
||||
|
||||
const openRouterSchema = baseProviderSettingsSchema.extend({
|
||||
openRouterApiKey: z.string().optional(),
|
||||
openRouterModelId: z.string().optional(),
|
||||
openRouterBaseUrl: z.string().optional(),
|
||||
openRouterSpecificProvider: z.string().optional(),
|
||||
openRouterUseMiddleOutTransform: z.boolean().optional(),
|
||||
// Amazon Bedrock
|
||||
})
|
||||
|
||||
const bedrockSchema = apiModelIdProviderModelSchema.extend({
|
||||
awsAccessKey: z.string().optional(),
|
||||
awsSecretKey: z.string().optional(),
|
||||
awsSessionToken: z.string().optional(),
|
||||
|
|
@ -371,12 +392,16 @@ export const providerSettingsSchema = z.object({
|
|||
awsProfile: z.string().optional(),
|
||||
awsUseProfile: z.boolean().optional(),
|
||||
awsCustomArn: z.string().optional(),
|
||||
// Google Vertex
|
||||
})
|
||||
|
||||
const vertexSchema = apiModelIdProviderModelSchema.extend({
|
||||
vertexKeyFile: z.string().optional(),
|
||||
vertexJsonCredentials: z.string().optional(),
|
||||
vertexProjectId: z.string().optional(),
|
||||
vertexRegion: z.string().optional(),
|
||||
// OpenAI
|
||||
})
|
||||
|
||||
const openAiSchema = baseProviderSettingsSchema.extend({
|
||||
openAiBaseUrl: z.string().optional(),
|
||||
openAiApiKey: z.string().optional(),
|
||||
openAiLegacyFormat: z.boolean().optional(),
|
||||
|
|
@ -387,12 +412,16 @@ export const providerSettingsSchema = z.object({
|
|||
azureApiVersion: z.string().optional(),
|
||||
openAiStreamingEnabled: z.boolean().optional(),
|
||||
enableReasoningEffort: z.boolean().optional(),
|
||||
openAiHostHeader: z.string().optional(), // Keep temporarily for backward compatibility during migration
|
||||
openAiHostHeader: z.string().optional(), // Keep temporarily for backward compatibility during migration.
|
||||
openAiHeaders: z.record(z.string(), z.string()).optional(),
|
||||
// Ollama
|
||||
})
|
||||
|
||||
const ollamaSchema = baseProviderSettingsSchema.extend({
|
||||
ollamaModelId: z.string().optional(),
|
||||
ollamaBaseUrl: z.string().optional(),
|
||||
// VS Code LM
|
||||
})
|
||||
|
||||
const vsCodeLmSchema = baseProviderSettingsSchema.extend({
|
||||
vsCodeLmModelSelector: z
|
||||
.object({
|
||||
vendor: z.string().optional(),
|
||||
|
|
@ -401,54 +430,124 @@ export const providerSettingsSchema = z.object({
|
|||
id: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
// LM Studio
|
||||
})
|
||||
|
||||
const lmStudioSchema = baseProviderSettingsSchema.extend({
|
||||
lmStudioModelId: z.string().optional(),
|
||||
lmStudioBaseUrl: z.string().optional(),
|
||||
lmStudioDraftModelId: z.string().optional(),
|
||||
lmStudioSpeculativeDecodingEnabled: z.boolean().optional(),
|
||||
// Gemini
|
||||
})
|
||||
|
||||
const geminiSchema = apiModelIdProviderModelSchema.extend({
|
||||
geminiApiKey: z.string().optional(),
|
||||
googleGeminiBaseUrl: z.string().optional(),
|
||||
// OpenAI Native
|
||||
})
|
||||
|
||||
const openAiNativeSchema = apiModelIdProviderModelSchema.extend({
|
||||
openAiNativeApiKey: z.string().optional(),
|
||||
openAiNativeBaseUrl: z.string().optional(),
|
||||
// Mistral
|
||||
})
|
||||
|
||||
const mistralSchema = apiModelIdProviderModelSchema.extend({
|
||||
mistralApiKey: z.string().optional(),
|
||||
mistralCodestralUrl: z.string().optional(),
|
||||
// DeepSeek
|
||||
})
|
||||
|
||||
const deepSeekSchema = apiModelIdProviderModelSchema.extend({
|
||||
deepSeekBaseUrl: z.string().optional(),
|
||||
deepSeekApiKey: z.string().optional(),
|
||||
// Unbound
|
||||
})
|
||||
|
||||
const unboundSchema = baseProviderSettingsSchema.extend({
|
||||
unboundApiKey: z.string().optional(),
|
||||
unboundModelId: z.string().optional(),
|
||||
// Requesty
|
||||
})
|
||||
|
||||
const requestySchema = baseProviderSettingsSchema.extend({
|
||||
requestyApiKey: z.string().optional(),
|
||||
requestyModelId: z.string().optional(),
|
||||
// X.AI (Grok)
|
||||
})
|
||||
|
||||
const humanRelaySchema = baseProviderSettingsSchema
|
||||
|
||||
const fakeAiSchema = baseProviderSettingsSchema.extend({
|
||||
fakeAi: z.unknown().optional(),
|
||||
})
|
||||
|
||||
const xaiSchema = apiModelIdProviderModelSchema.extend({
|
||||
xaiApiKey: z.string().optional(),
|
||||
// Groq
|
||||
})
|
||||
|
||||
const groqSchema = apiModelIdProviderModelSchema.extend({
|
||||
groqApiKey: z.string().optional(),
|
||||
// Chutes AI
|
||||
})
|
||||
|
||||
const chutesSchema = apiModelIdProviderModelSchema.extend({
|
||||
chutesApiKey: z.string().optional(),
|
||||
// LiteLLM
|
||||
})
|
||||
|
||||
const litellmSchema = baseProviderSettingsSchema.extend({
|
||||
litellmBaseUrl: z.string().optional(),
|
||||
litellmApiKey: z.string().optional(),
|
||||
litellmModelId: z.string().optional(),
|
||||
// Claude 3.7 Sonnet Thinking
|
||||
modelMaxTokens: z.number().optional(),
|
||||
modelMaxThinkingTokens: z.number().optional(),
|
||||
// Generic
|
||||
includeMaxTokens: z.boolean().optional(),
|
||||
reasoningEffort: reasoningEffortsSchema.optional(),
|
||||
promptCachingDisabled: z.boolean().optional(),
|
||||
diffEnabled: z.boolean().optional(),
|
||||
fuzzyMatchThreshold: z.number().optional(),
|
||||
modelTemperature: z.number().nullish(),
|
||||
rateLimitSeconds: z.number().optional(),
|
||||
// Fake AI
|
||||
fakeAi: z.unknown().optional(),
|
||||
})
|
||||
|
||||
const defaultSchema = z.object({
|
||||
apiProvider: z.undefined(),
|
||||
})
|
||||
|
||||
export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProvider", [
|
||||
anthropicSchema.merge(z.object({ apiProvider: z.literal("anthropic") })),
|
||||
glamaSchema.merge(z.object({ apiProvider: z.literal("glama") })),
|
||||
openRouterSchema.merge(z.object({ apiProvider: z.literal("openrouter") })),
|
||||
bedrockSchema.merge(z.object({ apiProvider: z.literal("bedrock") })),
|
||||
vertexSchema.merge(z.object({ apiProvider: z.literal("vertex") })),
|
||||
openAiSchema.merge(z.object({ apiProvider: z.literal("openai") })),
|
||||
ollamaSchema.merge(z.object({ apiProvider: z.literal("ollama") })),
|
||||
vsCodeLmSchema.merge(z.object({ apiProvider: z.literal("vscode-lm") })),
|
||||
lmStudioSchema.merge(z.object({ apiProvider: z.literal("lmstudio") })),
|
||||
geminiSchema.merge(z.object({ apiProvider: z.literal("gemini") })),
|
||||
openAiNativeSchema.merge(z.object({ apiProvider: z.literal("openai-native") })),
|
||||
mistralSchema.merge(z.object({ apiProvider: z.literal("mistral") })),
|
||||
deepSeekSchema.merge(z.object({ apiProvider: z.literal("deepseek") })),
|
||||
unboundSchema.merge(z.object({ apiProvider: z.literal("unbound") })),
|
||||
requestySchema.merge(z.object({ apiProvider: z.literal("requesty") })),
|
||||
humanRelaySchema.merge(z.object({ apiProvider: z.literal("human-relay") })),
|
||||
fakeAiSchema.merge(z.object({ apiProvider: z.literal("fake-ai") })),
|
||||
xaiSchema.merge(z.object({ apiProvider: z.literal("xai") })),
|
||||
groqSchema.merge(z.object({ apiProvider: z.literal("groq") })),
|
||||
chutesSchema.merge(z.object({ apiProvider: z.literal("chutes") })),
|
||||
litellmSchema.merge(z.object({ apiProvider: z.literal("litellm") })),
|
||||
defaultSchema,
|
||||
])
|
||||
|
||||
export const providerSettingsSchema = z
|
||||
.object({
|
||||
apiProvider: providerNamesSchema.optional(),
|
||||
})
|
||||
.merge(anthropicSchema)
|
||||
.merge(glamaSchema)
|
||||
.merge(openRouterSchema)
|
||||
.merge(bedrockSchema)
|
||||
.merge(vertexSchema)
|
||||
.merge(openAiSchema)
|
||||
.merge(ollamaSchema)
|
||||
.merge(vsCodeLmSchema)
|
||||
.merge(lmStudioSchema)
|
||||
.merge(geminiSchema)
|
||||
.merge(openAiNativeSchema)
|
||||
.merge(mistralSchema)
|
||||
.merge(deepSeekSchema)
|
||||
.merge(unboundSchema)
|
||||
.merge(requestySchema)
|
||||
.merge(humanRelaySchema)
|
||||
.merge(fakeAiSchema)
|
||||
.merge(xaiSchema)
|
||||
.merge(groqSchema)
|
||||
.merge(chutesSchema)
|
||||
.merge(litellmSchema)
|
||||
|
||||
export type ProviderSettings = z.infer<typeof providerSettingsSchema>
|
||||
|
||||
type ProviderSettingsRecord = Record<Keys<ProviderSettings>, undefined>
|
||||
|
|
@ -557,7 +656,7 @@ export const PROVIDER_SETTINGS_KEYS = Object.keys(providerSettingsRecord) as Key
|
|||
|
||||
export const globalSettingsSchema = z.object({
|
||||
currentApiConfigName: z.string().optional(),
|
||||
listApiConfigMeta: z.array(apiConfigMetaSchema).optional(),
|
||||
listApiConfigMeta: z.array(providerSettingsEntrySchema).optional(),
|
||||
pinnedApiConfigs: z.record(z.string(), z.boolean()).optional(),
|
||||
|
||||
lastShownAnnouncementId: z.string().optional(),
|
||||
|
|
@ -976,8 +1075,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" },
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { GitCommit } from "../utils/git"
|
|||
|
||||
import {
|
||||
GlobalSettings,
|
||||
ApiConfigMeta,
|
||||
ProviderSettings as ApiConfiguration,
|
||||
ProviderSettingsEntry,
|
||||
ProviderSettings,
|
||||
HistoryItem,
|
||||
ModeConfig,
|
||||
TelemetrySetting,
|
||||
|
|
@ -17,7 +17,7 @@ import { McpServer } from "./mcp"
|
|||
import { Mode } from "./modes"
|
||||
import { RouterModels } from "./api"
|
||||
|
||||
export type { ApiConfigMeta, ToolProgressStatus }
|
||||
export type { ProviderSettingsEntry, ToolProgressStatus }
|
||||
|
||||
export interface LanguageModelChatSelector {
|
||||
vendor?: string
|
||||
|
|
@ -95,7 +95,7 @@ export interface ExtensionMessage {
|
|||
vsCodeLmModels?: { vendor?: string; family?: string; version?: string; id?: string }[]
|
||||
mcpServers?: McpServer[]
|
||||
commits?: GitCommit[]
|
||||
listApiConfig?: ApiConfigMeta[]
|
||||
listApiConfig?: ProviderSettingsEntry[]
|
||||
mode?: Mode
|
||||
customMode?: ModeConfig
|
||||
slug?: string
|
||||
|
|
@ -172,7 +172,7 @@ export type ExtensionState = Pick<
|
|||
version: string
|
||||
clineMessages: ClineMessage[]
|
||||
currentTaskItem?: HistoryItem
|
||||
apiConfiguration?: ApiConfiguration
|
||||
apiConfiguration?: ProviderSettings
|
||||
uriScheme?: string
|
||||
shouldShowAnnouncement: boolean
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { z } from "zod"
|
||||
|
||||
import { ApiConfiguration } from "./api"
|
||||
import { ProviderSettings } from "./api"
|
||||
import { Mode, PromptComponent, ModeConfig } from "./modes"
|
||||
|
||||
export type ClineAskResponse = "yesButtonClicked" | "noButtonClicked" | "messageResponse"
|
||||
|
|
@ -11,7 +11,6 @@ export type AudioType = "notification" | "celebration" | "progress_loop"
|
|||
|
||||
export interface WebviewMessage {
|
||||
type:
|
||||
| "apiConfiguration"
|
||||
| "deleteMultipleTasksWithIds"
|
||||
| "currentApiConfigName"
|
||||
| "saveApiConfiguration"
|
||||
|
|
@ -134,7 +133,7 @@ export interface WebviewMessage {
|
|||
text?: string
|
||||
disabled?: boolean
|
||||
askResponse?: ClineAskResponse
|
||||
apiConfiguration?: ApiConfiguration
|
||||
apiConfiguration?: ProviderSettings
|
||||
images?: string[]
|
||||
bool?: boolean
|
||||
value?: number
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { checkExistKey } from "../checkExistApiConfig"
|
||||
import { ApiConfiguration } from "../api"
|
||||
import { ProviderSettings } from "../api"
|
||||
|
||||
describe("checkExistKey", () => {
|
||||
it("should return false for undefined config", () => {
|
||||
|
|
@ -7,19 +7,19 @@ describe("checkExistKey", () => {
|
|||
})
|
||||
|
||||
it("should return false for empty config", () => {
|
||||
const config: ApiConfiguration = {}
|
||||
const config: ProviderSettings = {}
|
||||
expect(checkExistKey(config)).toBe(false)
|
||||
})
|
||||
|
||||
it("should return true when one key is defined", () => {
|
||||
const config: ApiConfiguration = {
|
||||
const config: ProviderSettings = {
|
||||
apiKey: "test-key",
|
||||
}
|
||||
expect(checkExistKey(config)).toBe(true)
|
||||
})
|
||||
|
||||
it("should return true when multiple keys are defined", () => {
|
||||
const config: ApiConfiguration = {
|
||||
const config: ProviderSettings = {
|
||||
apiKey: "test-key",
|
||||
glamaApiKey: "glama-key",
|
||||
openRouterApiKey: "openrouter-key",
|
||||
|
|
@ -28,7 +28,7 @@ describe("checkExistKey", () => {
|
|||
})
|
||||
|
||||
it("should return true when only non-key fields are undefined", () => {
|
||||
const config: ApiConfiguration = {
|
||||
const config: ProviderSettings = {
|
||||
apiKey: "test-key",
|
||||
apiProvider: undefined,
|
||||
anthropicBaseUrl: undefined,
|
||||
|
|
@ -38,7 +38,7 @@ describe("checkExistKey", () => {
|
|||
})
|
||||
|
||||
it("should return false when all key fields are undefined", () => {
|
||||
const config: ApiConfiguration = {
|
||||
const config: ProviderSettings = {
|
||||
apiKey: undefined,
|
||||
glamaApiKey: undefined,
|
||||
openRouterApiKey: undefined,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import { ModelInfo, ProviderName, ProviderSettings } from "../schemas"
|
||||
|
||||
export type { ModelInfo, ProviderName }
|
||||
export type { ModelInfo, ProviderName, ProviderSettings }
|
||||
|
||||
export type ApiHandlerOptions = Omit<ProviderSettings, "apiProvider" | "id">
|
||||
|
||||
export type ApiConfiguration = ProviderSettings
|
||||
|
||||
// Anthropic
|
||||
// https://docs.anthropic.com/en/docs/about-claude/models
|
||||
export type AnthropicModelId = keyof typeof anthropicModels
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { singleCompletionHandler } from "../single-completion-handler"
|
||||
import { ApiConfiguration } from "../../shared/api"
|
||||
import { ProviderSettings } from "../../shared/api"
|
||||
import { buildApiHandler, SingleCompletionHandler } from "../../api"
|
||||
import { supportPrompt } from "../../shared/support-prompt"
|
||||
|
||||
|
|
@ -9,7 +9,7 @@ jest.mock("../../api", () => ({
|
|||
}))
|
||||
|
||||
describe("enhancePrompt", () => {
|
||||
const mockApiConfig: ApiConfiguration = {
|
||||
const mockApiConfig: ProviderSettings = {
|
||||
apiProvider: "openai",
|
||||
openAiApiKey: "test-key",
|
||||
openAiBaseUrl: "https://api.openai.com/v1",
|
||||
|
|
@ -69,7 +69,7 @@ describe("enhancePrompt", () => {
|
|||
})
|
||||
|
||||
it("throws error for missing API configuration", async () => {
|
||||
await expect(singleCompletionHandler({} as ApiConfiguration, "Test prompt")).rejects.toThrow(
|
||||
await expect(singleCompletionHandler({} as ProviderSettings, "Test prompt")).rejects.toThrow(
|
||||
"No valid API configuration provided",
|
||||
)
|
||||
})
|
||||
|
|
@ -94,7 +94,7 @@ describe("enhancePrompt", () => {
|
|||
})
|
||||
|
||||
it("uses appropriate model based on provider", async () => {
|
||||
const openRouterConfig: ApiConfiguration = {
|
||||
const openRouterConfig: ProviderSettings = {
|
||||
apiProvider: "openrouter",
|
||||
openRouterApiKey: "test-key",
|
||||
openRouterModelId: "test-model",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { ApiConfiguration } from "../shared/api"
|
||||
import { ProviderSettings } from "../shared/api"
|
||||
import { buildApiHandler, SingleCompletionHandler } from "../api"
|
||||
|
||||
/**
|
||||
* Enhances a prompt using the configured API without creating a full Cline instance or task history.
|
||||
* This is a lightweight alternative that only uses the API's completion functionality.
|
||||
*/
|
||||
export async function singleCompletionHandler(apiConfiguration: ApiConfiguration, promptText: string): Promise<string> {
|
||||
export async function singleCompletionHandler(apiConfiguration: ProviderSettings, promptText: string): Promise<string> {
|
||||
if (!promptText) {
|
||||
throw new Error("No prompt text provided")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import React from "react"
|
|||
import { render, screen } from "@testing-library/react"
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import TaskHeader, { TaskHeaderProps } from "../TaskHeader"
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ jest.mock("@src/context/ExtensionStateContext", () => ({
|
|||
apiProvider: "anthropic",
|
||||
apiKey: "test-api-key", // Add relevant fields
|
||||
apiModelId: "claude-3-opus-20240229", // Add relevant fields
|
||||
} as ApiConfiguration, // Optional: Add type assertion if ApiConfiguration is imported
|
||||
} as ProviderSettings, // Optional: Add type assertion if ProviderSettings is imported
|
||||
currentTaskItem: null,
|
||||
}),
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { memo, useEffect, useRef, useState } from "react"
|
|||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
import { ChevronsUpDown, Check, X } from "lucide-react"
|
||||
|
||||
import { ApiConfigMeta } from "@roo/shared/ExtensionMessage"
|
||||
import { ProviderSettingsEntry } from "@roo/shared/ExtensionMessage"
|
||||
|
||||
import { useAppTranslation } from "@/i18n/TranslationContext"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
|
@ -25,7 +25,7 @@ import {
|
|||
|
||||
interface ApiConfigManagerProps {
|
||||
currentApiConfigName?: string
|
||||
listApiConfigMeta?: ApiConfigMeta[]
|
||||
listApiConfigMeta?: ProviderSettingsEntry[]
|
||||
onSelectConfig: (configName: string) => void
|
||||
onDeleteConfig: (configName: string) => void
|
||||
onRenameConfig: (oldName: string, newName: string) => void
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
|
|||
|
||||
import {
|
||||
type ProviderName,
|
||||
type ApiConfiguration,
|
||||
type ProviderSettings,
|
||||
openRouterDefaultModelId,
|
||||
requestyDefaultModelId,
|
||||
glamaDefaultModelId,
|
||||
|
|
@ -56,8 +56,8 @@ import { BedrockCustomArn } from "./providers/BedrockCustomArn"
|
|||
|
||||
export interface ApiOptionsProps {
|
||||
uriScheme: string | undefined
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: <K extends keyof ApiConfiguration>(field: K, value: ApiConfiguration[K]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: <K extends keyof ProviderSettings>(field: K, value: ProviderSettings[K]) => void
|
||||
fromWelcomeView?: boolean
|
||||
errorMessage: string | undefined
|
||||
setErrorMessage: React.Dispatch<React.SetStateAction<string | undefined>>
|
||||
|
|
@ -107,9 +107,9 @@ const ApiOptions = ({
|
|||
const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false)
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
|
||||
interface PromptCachingControlProps {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: <K extends keyof ApiConfiguration>(field: K, value: ApiConfiguration[K]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: <K extends keyof ProviderSettings>(field: K, value: ProviderSettings[K]) => void
|
||||
}
|
||||
|
||||
export const PromptCachingControl = ({ apiConfiguration, setApiConfigurationField }: PromptCachingControlProps) => {
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ import { useAppTranslation } from "@/i18n/TranslationContext"
|
|||
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
import { reasoningEfforts, ReasoningEffort as ReasoningEffortType } from "@roo/schemas"
|
||||
|
||||
interface ReasoningEffortProps {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: <K extends keyof ApiConfiguration>(field: K, value: ApiConfiguration[K]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: <K extends keyof ProviderSettings>(field: K, value: ProviderSettings[K]) => void
|
||||
}
|
||||
|
||||
export const ReasoningEffort = ({ apiConfiguration, setApiConfigurationField }: ReasoningEffortProps) => {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import {
|
|||
|
||||
import { ExperimentId } from "@roo/shared/experiments"
|
||||
import { TelemetrySetting } from "@roo/shared/TelemetrySetting"
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { vscode } from "@/utils/vscode"
|
||||
import { ExtensionStateContextType, useExtensionState } from "@/context/ExtensionStateContext"
|
||||
|
|
@ -195,7 +195,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
}, [])
|
||||
|
||||
const setApiConfigurationField = useCallback(
|
||||
<K extends keyof ApiConfiguration>(field: K, value: ApiConfiguration[K]) => {
|
||||
<K extends keyof ProviderSettings>(field: K, value: ProviderSettings[K]) => {
|
||||
setCachedState((prevState) => {
|
||||
if (prevState.apiConfiguration?.[field] === value) {
|
||||
return prevState
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@ import { useAppTranslation } from "@/i18n/TranslationContext"
|
|||
|
||||
import { Slider } from "@/components/ui"
|
||||
|
||||
import { ApiConfiguration, ModelInfo } from "@roo/shared/api"
|
||||
import { ProviderSettings, ModelInfo } from "@roo/shared/api"
|
||||
|
||||
const DEFAULT_MAX_OUTPUT_TOKENS = 16_384
|
||||
const DEFAULT_MAX_THINKING_TOKENS = 8_192
|
||||
|
||||
interface ThinkingBudgetProps {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: <K extends keyof ApiConfiguration>(field: K, value: ApiConfiguration[K]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: <K extends keyof ProviderSettings>(field: K, value: ProviderSettings[K]) => void
|
||||
modelInfo?: ModelInfo
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import { render, screen, fireEvent } from "@testing-library/react"
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { ExtensionStateContextProvider } from "@/context/ExtensionStateContext"
|
||||
import { openAiModelInfoSaneDefaults } from "@roo/shared/api"
|
||||
|
|
@ -148,7 +148,7 @@ jest.mock("../DiffSettingsControl", () => ({
|
|||
}))
|
||||
|
||||
jest.mock("@src/components/ui/hooks/useSelectedModel", () => ({
|
||||
useSelectedModel: jest.fn((apiConfiguration: ApiConfiguration) => {
|
||||
useSelectedModel: jest.fn((apiConfiguration: ProviderSettings) => {
|
||||
if (apiConfiguration.apiModelId?.includes("thinking")) {
|
||||
return {
|
||||
provider: apiConfiguration.apiProvider,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useCallback, useState } from "react"
|
|||
import { Checkbox } from "vscrui"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
||||
|
|
@ -10,8 +10,8 @@ import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
|||
import { inputEventTransform, noTransform } from "../transforms"
|
||||
|
||||
type AnthropicProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const Anthropic = ({ apiConfiguration, setApiConfigurationField }: AnthropicProps) => {
|
||||
|
|
@ -20,9 +20,9 @@ export const Anthropic = ({ apiConfiguration, setApiConfigurationField }: Anthro
|
|||
const [anthropicBaseUrlSelected, setAnthropicBaseUrlSelected] = useState(!!apiConfiguration?.anthropicBaseUrl)
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useCallback } from "react"
|
|||
import { Checkbox } from "vscrui"
|
||||
import { VSCodeTextField, VSCodeRadio, VSCodeRadioGroup } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration, ModelInfo } from "@roo/shared/api"
|
||||
import { ProviderSettings, ModelInfo } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@src/components/ui"
|
||||
|
|
@ -11,8 +11,8 @@ import { AWS_REGIONS } from "../constants"
|
|||
import { inputEventTransform, noTransform } from "../transforms"
|
||||
|
||||
type BedrockProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
selectedModelInfo?: ModelInfo
|
||||
}
|
||||
|
||||
|
|
@ -20,9 +20,9 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo
|
|||
const { t } = useAppTranslation()
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { useMemo } from "react"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { validateBedrockArn } from "@src/utils/validate"
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
|
||||
type BedrockCustomArnProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const BedrockCustomArn = ({ apiConfiguration, setApiConfigurationField }: BedrockCustomArnProps) => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useCallback } from "react"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
||||
|
|
@ -9,17 +9,17 @@ import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
|||
import { inputEventTransform } from "../transforms"
|
||||
|
||||
type ChutesProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const Chutes = ({ apiConfiguration, setApiConfigurationField }: ChutesProps) => {
|
||||
const { t } = useAppTranslation()
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useCallback } from "react"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
||||
|
|
@ -9,17 +9,17 @@ import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
|||
import { inputEventTransform } from "../transforms"
|
||||
|
||||
type DeepSeekProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const DeepSeek = ({ apiConfiguration, setApiConfigurationField }: DeepSeekProps) => {
|
||||
const { t } = useAppTranslation()
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useCallback, useState } from "react"
|
|||
import { Checkbox } from "vscrui"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
||||
|
|
@ -10,8 +10,8 @@ import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
|||
import { inputEventTransform } from "../transforms"
|
||||
|
||||
type GeminiProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const Gemini = ({ apiConfiguration, setApiConfigurationField }: GeminiProps) => {
|
||||
|
|
@ -22,9 +22,9 @@ export const Gemini = ({ apiConfiguration, setApiConfigurationField }: GeminiPro
|
|||
)
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useCallback } from "react"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration, RouterModels, glamaDefaultModelId } from "@roo/shared/api"
|
||||
import { ProviderSettings, RouterModels, glamaDefaultModelId } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { getGlamaAuthUrl } from "@src/oauth/urls"
|
||||
|
|
@ -11,8 +11,8 @@ import { inputEventTransform } from "../transforms"
|
|||
import { ModelPicker } from "../ModelPicker"
|
||||
|
||||
type GlamaProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
routerModels?: RouterModels
|
||||
uriScheme?: string
|
||||
}
|
||||
|
|
@ -21,9 +21,9 @@ export const Glama = ({ apiConfiguration, setApiConfigurationField, routerModels
|
|||
const { t } = useAppTranslation()
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useCallback } from "react"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
||||
|
|
@ -9,17 +9,17 @@ import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
|||
import { inputEventTransform } from "../transforms"
|
||||
|
||||
type GroqProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const Groq = ({ apiConfiguration, setApiConfigurationField }: GroqProps) => {
|
||||
const { t } = useAppTranslation()
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Trans } from "react-i18next"
|
|||
import { Checkbox } from "vscrui"
|
||||
import { VSCodeLink, VSCodeRadio, VSCodeRadioGroup, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { ExtensionMessage } from "@roo/shared/ExtensionMessage"
|
||||
|
|
@ -12,8 +12,8 @@ import { ExtensionMessage } from "@roo/shared/ExtensionMessage"
|
|||
import { inputEventTransform } from "../transforms"
|
||||
|
||||
type LMStudioProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const LMStudio = ({ apiConfiguration, setApiConfigurationField }: LMStudioProps) => {
|
||||
|
|
@ -22,9 +22,9 @@ export const LMStudio = ({ apiConfiguration, setApiConfigurationField }: LMStudi
|
|||
const [lmStudioModels, setLmStudioModels] = useState<string[]>([])
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useCallback } from "react"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration, RouterModels, litellmDefaultModelId } from "@roo/shared/api"
|
||||
import { ProviderSettings, RouterModels, litellmDefaultModelId } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
|
||||
|
|
@ -9,8 +9,8 @@ import { inputEventTransform } from "../transforms"
|
|||
import { ModelPicker } from "../ModelPicker"
|
||||
|
||||
type LiteLLMProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
routerModels?: RouterModels
|
||||
}
|
||||
|
||||
|
|
@ -18,9 +18,9 @@ export const LiteLLM = ({ apiConfiguration, setApiConfigurationField, routerMode
|
|||
const { t } = useAppTranslation()
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
@ -46,6 +46,7 @@ export const LiteLLM = ({ apiConfiguration, setApiConfigurationField, routerMode
|
|||
className="w-full">
|
||||
<label className="block font-medium mb-1">{t("settings:providers.litellmApiKey")}</label>
|
||||
</VSCodeTextField>
|
||||
|
||||
<div className="text-sm text-vscode-descriptionForeground -mt-2">
|
||||
{t("settings:providers.apiKeyStorageNotice")}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useCallback } from "react"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration, RouterModels, mistralDefaultModelId } from "@roo/shared/api"
|
||||
import { ProviderSettings, RouterModels, mistralDefaultModelId } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
||||
|
|
@ -9,8 +9,8 @@ import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
|||
import { inputEventTransform } from "../transforms"
|
||||
|
||||
type MistralProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
routerModels?: RouterModels
|
||||
}
|
||||
|
||||
|
|
@ -18,9 +18,9 @@ export const Mistral = ({ apiConfiguration, setApiConfigurationField }: MistralP
|
|||
const { t } = useAppTranslation()
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useState, useCallback } from "react"
|
|||
import { useEvent } from "react-use"
|
||||
import { VSCodeTextField, VSCodeRadioGroup, VSCodeRadio } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
import { ExtensionMessage } from "@roo/shared/ExtensionMessage"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
|
|
@ -10,8 +10,8 @@ import { useAppTranslation } from "@src/i18n/TranslationContext"
|
|||
import { inputEventTransform } from "../transforms"
|
||||
|
||||
type OllamaProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const Ollama = ({ apiConfiguration, setApiConfigurationField }: OllamaProps) => {
|
||||
|
|
@ -20,9 +20,9 @@ export const Ollama = ({ apiConfiguration, setApiConfigurationField }: OllamaPro
|
|||
const [ollamaModels, setOllamaModels] = useState<string[]>([])
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useCallback, useState } from "react"
|
|||
import { Checkbox } from "vscrui"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
||||
|
|
@ -10,8 +10,8 @@ import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
|||
import { inputEventTransform } from "../transforms"
|
||||
|
||||
type OpenAIProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const OpenAI = ({ apiConfiguration, setApiConfigurationField }: OpenAIProps) => {
|
||||
|
|
@ -22,9 +22,9 @@ export const OpenAI = ({ apiConfiguration, setApiConfigurationField }: OpenAIPro
|
|||
)
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { VSCodeButton, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
|||
import { convertHeadersToObject } from "../utils/headers"
|
||||
|
||||
import { ModelInfo, ReasoningEffort as ReasoningEffortType } from "@roo/schemas"
|
||||
import { ApiConfiguration, azureOpenAiDefaultApiVersion, openAiModelInfoSaneDefaults } from "@roo/shared/api"
|
||||
import { ProviderSettings, azureOpenAiDefaultApiVersion, openAiModelInfoSaneDefaults } from "@roo/shared/api"
|
||||
import { ExtensionMessage } from "@roo/shared/ExtensionMessage"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
|
|
@ -17,8 +17,8 @@ import { R1FormatSetting } from "../R1FormatSetting"
|
|||
import { ReasoningEffort } from "../ReasoningEffort"
|
||||
|
||||
type OpenAICompatibleProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const OpenAICompatible = ({ apiConfiguration, setApiConfigurationField }: OpenAICompatibleProps) => {
|
||||
|
|
@ -81,9 +81,9 @@ export const OpenAICompatible = ({ apiConfiguration, setApiConfigurationField }:
|
|||
}, [customHeaders, setApiConfigurationField])
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Checkbox } from "vscrui"
|
|||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
import { ExternalLinkIcon } from "@radix-ui/react-icons"
|
||||
|
||||
import { ApiConfiguration, RouterModels, openRouterDefaultModelId } from "@roo/shared/api"
|
||||
import { ProviderSettings, RouterModels, openRouterDefaultModelId } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { getOpenRouterAuthUrl } from "@src/oauth/urls"
|
||||
|
|
@ -21,8 +21,8 @@ import { ModelPicker } from "../ModelPicker"
|
|||
import { OpenRouterBalanceDisplay } from "./OpenRouterBalanceDisplay"
|
||||
|
||||
type OpenRouterProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
routerModels?: RouterModels
|
||||
selectedModelId: string
|
||||
uriScheme: string | undefined
|
||||
|
|
@ -42,9 +42,9 @@ export const OpenRouter = ({
|
|||
const [openRouterBaseUrlSelected, setOpenRouterBaseUrlSelected] = useState(!!apiConfiguration?.openRouterBaseUrl)
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useCallback, useState } from "react"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration, RouterModels, requestyDefaultModelId } from "@roo/shared/api"
|
||||
import { ProviderSettings, RouterModels, requestyDefaultModelId } from "@roo/shared/api"
|
||||
|
||||
import { vscode } from "@src/utils/vscode"
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
|
|
@ -13,8 +13,8 @@ import { ModelPicker } from "../ModelPicker"
|
|||
import { RequestyBalanceDisplay } from "./RequestyBalanceDisplay"
|
||||
|
||||
type RequestyProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
routerModels?: RouterModels
|
||||
refetchRouterModels: () => void
|
||||
}
|
||||
|
|
@ -30,9 +30,9 @@ export const Requesty = ({
|
|||
const [didRefetch, setDidRefetch] = useState<boolean>()
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useCallback } from "react"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration, RouterModels, unboundDefaultModelId } from "@roo/shared/api"
|
||||
import { ProviderSettings, RouterModels, unboundDefaultModelId } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
||||
|
|
@ -10,8 +10,8 @@ import { inputEventTransform } from "../transforms"
|
|||
import { ModelPicker } from "../ModelPicker"
|
||||
|
||||
type UnboundProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
routerModels?: RouterModels
|
||||
}
|
||||
|
||||
|
|
@ -19,9 +19,9 @@ export const Unbound = ({ apiConfiguration, setApiConfigurationField, routerMode
|
|||
const { t } = useAppTranslation()
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useState, useCallback } from "react"
|
|||
import { useEvent } from "react-use"
|
||||
import { LanguageModelChatSelector } from "vscode"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
import { ExtensionMessage } from "@roo/shared/ExtensionMessage"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
|
|
@ -11,8 +11,8 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
|
|||
import { inputEventTransform } from "../transforms"
|
||||
|
||||
type VSCodeLMProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const VSCodeLM = ({ apiConfiguration, setApiConfigurationField }: VSCodeLMProps) => {
|
||||
|
|
@ -21,9 +21,9 @@ export const VSCodeLM = ({ apiConfiguration, setApiConfigurationField }: VSCodeL
|
|||
const [vsCodeLmModels, setVsCodeLmModels] = useState<LanguageModelChatSelector[]>([])
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useCallback } from "react"
|
||||
import { VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@src/components/ui"
|
||||
|
|
@ -10,17 +10,17 @@ import { inputEventTransform } from "../transforms"
|
|||
import { VERTEX_REGIONS } from "../constants"
|
||||
|
||||
type VertexProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const Vertex = ({ apiConfiguration, setApiConfigurationField }: VertexProps) => {
|
||||
const { t } = useAppTranslation()
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useCallback } from "react"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
import { useAppTranslation } from "@src/i18n/TranslationContext"
|
||||
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
||||
|
|
@ -9,17 +9,17 @@ import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
|
|||
import { inputEventTransform } from "../transforms"
|
||||
|
||||
type XAIProps = {
|
||||
apiConfiguration: ApiConfiguration
|
||||
setApiConfigurationField: (field: keyof ApiConfiguration, value: ApiConfiguration[keyof ApiConfiguration]) => void
|
||||
apiConfiguration: ProviderSettings
|
||||
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
|
||||
}
|
||||
|
||||
export const XAI = ({ apiConfiguration, setApiConfigurationField }: XAIProps) => {
|
||||
const { t } = useAppTranslation()
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ApiConfiguration, E>(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
transform: (event: E) => ApiConfiguration[K] = inputEventTransform,
|
||||
transform: (event: E) => ProviderSettings[K] = inputEventTransform,
|
||||
) =>
|
||||
(event: E | Event) => {
|
||||
setApiConfigurationField(field, transform(event as E))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import {
|
||||
type ProviderName,
|
||||
type ApiConfiguration,
|
||||
type ProviderSettings,
|
||||
type RouterModels,
|
||||
type ModelInfo,
|
||||
anthropicDefaultModelId,
|
||||
|
|
@ -35,7 +35,7 @@ import {
|
|||
|
||||
import { useRouterModels } from "./useRouterModels"
|
||||
|
||||
export const useSelectedModel = (apiConfiguration?: ApiConfiguration) => {
|
||||
export const useSelectedModel = (apiConfiguration?: ProviderSettings) => {
|
||||
const { data: routerModels, isLoading, isError } = useRouterModels()
|
||||
const provider = apiConfiguration?.apiProvider || "anthropic"
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ function getSelectedModel({
|
|||
routerModels,
|
||||
}: {
|
||||
provider: ProviderName
|
||||
apiConfiguration: ApiConfiguration
|
||||
apiConfiguration: ProviderSettings
|
||||
routerModels: RouterModels
|
||||
}): { id: string; info: ModelInfo } {
|
||||
switch (provider) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import React, { createContext, useCallback, useContext, useEffect, useState } from "react"
|
||||
import { useEvent } from "react-use"
|
||||
import { ApiConfigMeta, ExtensionMessage, ExtensionState } from "@roo/shared/ExtensionMessage"
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { vscode } from "@src/utils/vscode"
|
||||
import { convertTextMateToHljs } from "@src/utils/textMateToHljs"
|
||||
|
||||
import { ProviderSettingsEntry, ExtensionMessage, ExtensionState } from "@roo/shared/ExtensionMessage"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
import { findLastIndex } from "@roo/shared/array"
|
||||
import { McpServer } from "@roo/shared/mcp"
|
||||
import { checkExistKey } from "@roo/shared/checkExistApiConfig"
|
||||
|
|
@ -12,6 +11,9 @@ import { CustomSupportPrompts } from "@roo/shared/support-prompt"
|
|||
import { experimentDefault, ExperimentId } from "@roo/shared/experiments"
|
||||
import { TelemetrySetting } from "@roo/shared/TelemetrySetting"
|
||||
|
||||
import { vscode } from "@src/utils/vscode"
|
||||
import { convertTextMateToHljs } from "@src/utils/textMateToHljs"
|
||||
|
||||
export interface ExtensionStateContextType extends ExtensionState {
|
||||
historyPreviewCollapsed?: boolean // Add the new state property
|
||||
didHydrateState: boolean
|
||||
|
|
@ -22,7 +24,7 @@ export interface ExtensionStateContextType extends ExtensionState {
|
|||
currentCheckpoint?: string
|
||||
filePaths: string[]
|
||||
openedTabs: Array<{ label: string; isActive: boolean; path?: string }>
|
||||
setApiConfiguration: (config: ApiConfiguration) => void
|
||||
setApiConfiguration: (config: ProviderSettings) => void
|
||||
setCustomInstructions: (value?: string) => void
|
||||
setAlwaysAllowReadOnly: (value: boolean) => void
|
||||
setAlwaysAllowReadOnlyOutsideWorkspace: (value: boolean) => void
|
||||
|
|
@ -65,7 +67,7 @@ export interface ExtensionStateContextType extends ExtensionState {
|
|||
requestDelaySeconds: number
|
||||
setRequestDelaySeconds: (value: number) => void
|
||||
setCurrentApiConfigName: (value: string) => void
|
||||
setListApiConfigMeta: (value: ApiConfigMeta[]) => void
|
||||
setListApiConfigMeta: (value: ProviderSettingsEntry[]) => void
|
||||
mode: Mode
|
||||
setMode: (value: Mode) => void
|
||||
setCustomModePrompts: (value: CustomModePrompts) => void
|
||||
|
|
@ -182,7 +184,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
const [currentCheckpoint, setCurrentCheckpoint] = useState<string>()
|
||||
|
||||
const setListApiConfigMeta = useCallback(
|
||||
(value: ApiConfigMeta[]) => setState((prevState) => ({ ...prevState, listApiConfigMeta: value })),
|
||||
(value: ProviderSettingsEntry[]) => setState((prevState) => ({ ...prevState, listApiConfigMeta: value })),
|
||||
[],
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
// cd webview-ui && npx jest src/context/__tests__/ExtensionStateContext.test.tsx
|
||||
// npx jest src/context/__tests__/ExtensionStateContext.test.tsx
|
||||
|
||||
import { render, screen, act } from "@testing-library/react"
|
||||
|
||||
import { ExtensionState } from "@roo/shared/ExtensionMessage"
|
||||
import { ExtensionStateContextProvider, useExtensionState, mergeExtensionState } from "../ExtensionStateContext"
|
||||
import { ExperimentId } from "@roo/shared/experiments"
|
||||
import { ApiConfiguration } from "@roo/shared/api"
|
||||
import { ProviderSettings } from "@roo/shared/api"
|
||||
|
||||
// Test component that consumes the context
|
||||
const TestComponent = () => {
|
||||
const { allowedCommands, setAllowedCommands, soundEnabled, showRooIgnoredFiles, setShowRooIgnoredFiles } =
|
||||
useExtensionState()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div data-testid="allowed-commands">{JSON.stringify(allowedCommands)}</div>
|
||||
|
|
@ -26,9 +26,9 @@ const TestComponent = () => {
|
|||
)
|
||||
}
|
||||
|
||||
// Test component for API configuration
|
||||
const ApiConfigTestComponent = () => {
|
||||
const { apiConfiguration, setApiConfiguration } = useExtensionState()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div data-testid="api-configuration">{JSON.stringify(apiConfiguration)}</div>
|
||||
|
|
@ -197,7 +197,7 @@ describe("mergeExtensionState", () => {
|
|||
customModes: [],
|
||||
maxOpenTabsContext: 20,
|
||||
maxWorkspaceFiles: 100,
|
||||
apiConfiguration: { providerId: "openrouter" } as ApiConfiguration,
|
||||
apiConfiguration: { providerId: "openrouter" } as ProviderSettings,
|
||||
telemetrySetting: "unset",
|
||||
showRooIgnoredFiles: true,
|
||||
renderContext: "sidebar",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import i18next from "i18next"
|
||||
|
||||
import { ApiConfiguration, isRouterName, RouterModels } from "@roo/shared/api"
|
||||
import { ProviderSettings, isRouterName, RouterModels } from "@roo/shared/api"
|
||||
|
||||
export function validateApiConfiguration(apiConfiguration: ApiConfiguration): string | undefined {
|
||||
export function validateApiConfiguration(apiConfiguration: ProviderSettings): string | undefined {
|
||||
switch (apiConfiguration.apiProvider) {
|
||||
case "openrouter":
|
||||
if (!apiConfiguration.openRouterApiKey) {
|
||||
|
|
@ -118,7 +118,7 @@ export function validateBedrockArn(arn: string, region?: string) {
|
|||
return { isValid: true, arnRegion, errorMessage: undefined }
|
||||
}
|
||||
|
||||
export function validateModelId(apiConfiguration: ApiConfiguration, routerModels?: RouterModels): string | undefined {
|
||||
export function validateModelId(apiConfiguration: ProviderSettings, routerModels?: RouterModels): string | undefined {
|
||||
const provider = apiConfiguration.apiProvider ?? ""
|
||||
|
||||
if (!isRouterName(provider)) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue