Skip to content

Commit 40fd397

Browse files
committed
fix api config profile
1 parent ef8d02d commit 40fd397

File tree

7 files changed

+193
-125
lines changed

7 files changed

+193
-125
lines changed

src/core/webview/ClineProvider.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -956,10 +956,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
956956
await this.configManager.SaveConfig(message.text, message.apiConfiguration);
957957
let listApiConfig = await this.configManager.ListConfig();
958958

959-
// Update listApiConfigMeta first to ensure UI has latest data
960-
await this.updateGlobalState("listApiConfigMeta", listApiConfig);
961-
962959
await Promise.all([
960+
this.updateGlobalState("listApiConfigMeta", listApiConfig),
963961
this.updateApiConfiguration(message.apiConfiguration),
964962
this.updateGlobalState("currentApiConfigName", message.text),
965963
])
@@ -999,14 +997,12 @@ export class ClineProvider implements vscode.WebviewViewProvider {
999997
case "loadApiConfiguration":
1000998
if (message.text) {
1001999
try {
1000+
console.log("loadApiConfiguration", message.text)
10021001
const apiConfig = await this.configManager.LoadConfig(message.text);
10031002
const listApiConfig = await this.configManager.ListConfig();
1004-
const config = listApiConfig?.find(c => c.name === message.text);
10051003

1006-
// Update listApiConfigMeta first to ensure UI has latest data
1007-
await this.updateGlobalState("listApiConfigMeta", listApiConfig);
1008-
10091004
await Promise.all([
1005+
this.updateGlobalState("listApiConfigMeta", listApiConfig),
10101006
this.updateGlobalState("currentApiConfigName", message.text),
10111007
this.updateApiConfiguration(apiConfig),
10121008
])

webview-ui/package-lock.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"shell-quote": "^1.8.2",
2727
"styled-components": "^6.1.13",
2828
"typescript": "^4.9.5",
29+
"vscrui": "^0.2.0",
2930
"web-vitals": "^2.1.4"
3031
},
3132
"scripts": {

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 110 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1+
import { Checkbox, Dropdown } from "vscrui"
2+
import type { DropdownOption } from "vscrui"
13
import {
2-
VSCodeCheckbox,
3-
VSCodeDropdown,
44
VSCodeLink,
5-
VSCodeOption,
65
VSCodeRadio,
76
VSCodeRadioGroup,
87
VSCodeTextField,
@@ -90,35 +89,26 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
9089
}, [])
9190
useEvent("message", handleMessage)
9291

93-
/*
94-
VSCodeDropdown has an open bug where dynamically rendered options don't auto select the provided value prop. You can see this for yourself by comparing it with normal select/option elements, which work as expected.
95-
https://github.com/microsoft/vscode-webview-ui-toolkit/issues/433
96-
97-
In our case, when the user switches between providers, we recalculate the selectedModelId depending on the provider, the default model for that provider, and a modelId that the user may have selected. Unfortunately, the VSCodeDropdown component wouldn't select this calculated value, and would default to the first "Select a model..." option instead, which makes it seem like the model was cleared out when it wasn't.
98-
99-
As a workaround, we create separate instances of the dropdown for each provider, and then conditionally render the one that matches the current provider.
100-
*/
10192
const createDropdown = (models: Record<string, ModelInfo>) => {
93+
const options: DropdownOption[] = [
94+
{ value: "", label: "Select a model..." },
95+
...Object.keys(models).map((modelId) => ({
96+
value: modelId,
97+
label: modelId,
98+
}))
99+
]
102100
return (
103-
<VSCodeDropdown
101+
<Dropdown
104102
id="model-id"
105103
value={selectedModelId}
106-
onChange={handleInputChange("apiModelId")}
107-
style={{ width: "100%" }}>
108-
<VSCodeOption value="">Select a model...</VSCodeOption>
109-
{Object.keys(models).map((modelId) => (
110-
<VSCodeOption
111-
key={modelId}
112-
value={modelId}
113-
style={{
114-
whiteSpace: "normal",
115-
wordWrap: "break-word",
116-
maxWidth: "100%",
117-
}}>
118-
{modelId}
119-
</VSCodeOption>
120-
))}
121-
</VSCodeDropdown>
104+
onChange={(value: unknown) => {handleInputChange("apiModelId")({
105+
target: {
106+
value: (value as DropdownOption).value
107+
}
108+
})}}
109+
style={{ width: "100%" }}
110+
options={options}
111+
/>
122112
)
123113
}
124114

@@ -128,23 +118,31 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
128118
<label htmlFor="api-provider">
129119
<span style={{ fontWeight: 500 }}>API Provider</span>
130120
</label>
131-
<VSCodeDropdown
121+
<Dropdown
132122
id="api-provider"
133123
value={selectedProvider}
134-
onChange={handleInputChange("apiProvider")}
135-
style={{ minWidth: 130, position: "relative", zIndex: OPENROUTER_MODEL_PICKER_Z_INDEX + 1 }}>
136-
<VSCodeOption value="openrouter">OpenRouter</VSCodeOption>
137-
<VSCodeOption value="anthropic">Anthropic</VSCodeOption>
138-
<VSCodeOption value="gemini">Google Gemini</VSCodeOption>
139-
<VSCodeOption value="deepseek">DeepSeek</VSCodeOption>
140-
<VSCodeOption value="openai-native">OpenAI</VSCodeOption>
141-
<VSCodeOption value="openai">OpenAI Compatible</VSCodeOption>
142-
<VSCodeOption value="vertex">GCP Vertex AI</VSCodeOption>
143-
<VSCodeOption value="bedrock">AWS Bedrock</VSCodeOption>
144-
<VSCodeOption value="glama">Glama</VSCodeOption>
145-
<VSCodeOption value="lmstudio">LM Studio</VSCodeOption>
146-
<VSCodeOption value="ollama">Ollama</VSCodeOption>
147-
</VSCodeDropdown>
124+
onChange={(value: unknown) => {
125+
handleInputChange("apiProvider")({
126+
target: {
127+
value: (value as DropdownOption).value
128+
}
129+
})
130+
}}
131+
style={{ minWidth: 130, position: "relative", zIndex: OPENROUTER_MODEL_PICKER_Z_INDEX + 1 }}
132+
options={[
133+
{ value: "openrouter", label: "OpenRouter" },
134+
{ value: "anthropic", label: "Anthropic" },
135+
{ value: "gemini", label: "Google Gemini" },
136+
{ value: "deepseek", label: "DeepSeek" },
137+
{ value: "openai-native", label: "OpenAI" },
138+
{ value: "openai", label: "OpenAI Compatible" },
139+
{ value: "vertex", label: "GCP Vertex AI" },
140+
{ value: "bedrock", label: "AWS Bedrock" },
141+
{ value: "glama", label: "Glama" },
142+
{ value: "lmstudio", label: "LM Studio" },
143+
{ value: "ollama", label: "Ollama" }
144+
]}
145+
/>
148146
</div>
149147

150148
{selectedProvider === "anthropic" && (
@@ -158,17 +156,16 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
158156
<span style={{ fontWeight: 500 }}>Anthropic API Key</span>
159157
</VSCodeTextField>
160158

161-
<VSCodeCheckbox
159+
<Checkbox
162160
checked={anthropicBaseUrlSelected}
163-
onChange={(e: any) => {
164-
const isChecked = e.target.checked === true
165-
setAnthropicBaseUrlSelected(isChecked)
166-
if (!isChecked) {
161+
onChange={(checked: boolean) => {
162+
setAnthropicBaseUrlSelected(checked)
163+
if (!checked) {
167164
setApiConfiguration({ ...apiConfiguration, anthropicBaseUrl: "" })
168165
}
169166
}}>
170167
Use custom base URL
171-
</VSCodeCheckbox>
168+
</Checkbox>
172169

173170
{anthropicBaseUrlSelected && (
174171
<VSCodeTextField
@@ -286,15 +283,16 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
286283
</span>
287284
)} */}
288285
</p>
289-
<VSCodeCheckbox
286+
<Checkbox
290287
checked={apiConfiguration?.openRouterUseMiddleOutTransform || false}
291-
onChange={(e: any) => {
292-
const isChecked = e.target.checked === true
293-
setApiConfiguration({ ...apiConfiguration, openRouterUseMiddleOutTransform: isChecked })
288+
onChange={(checked: boolean) => {
289+
handleInputChange("openRouterUseMiddleOutTransform")({
290+
target: { value: checked },
291+
})
294292
}}>
295293
Compress prompts and message chains to the context size (<a href="https://openrouter.ai/docs/transforms">OpenRouter Transforms</a>)
296-
</VSCodeCheckbox>
297-
<br/>
294+
</Checkbox>
295+
<br />
298296
</div>
299297
)}
300298

@@ -328,45 +326,44 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
328326
<label htmlFor="aws-region-dropdown">
329327
<span style={{ fontWeight: 500 }}>AWS Region</span>
330328
</label>
331-
<VSCodeDropdown
329+
<Dropdown
332330
id="aws-region-dropdown"
333331
value={apiConfiguration?.awsRegion || ""}
334332
style={{ width: "100%" }}
335-
onChange={handleInputChange("awsRegion")}>
336-
<VSCodeOption value="">Select a region...</VSCodeOption>
337-
{/* The user will have to choose a region that supports the model they use, but this shouldn't be a problem since they'd have to request access for it in that region in the first place. */}
338-
<VSCodeOption value="us-east-1">us-east-1</VSCodeOption>
339-
<VSCodeOption value="us-east-2">us-east-2</VSCodeOption>
340-
{/* <VSCodeOption value="us-west-1">us-west-1</VSCodeOption> */}
341-
<VSCodeOption value="us-west-2">us-west-2</VSCodeOption>
342-
{/* <VSCodeOption value="af-south-1">af-south-1</VSCodeOption> */}
343-
{/* <VSCodeOption value="ap-east-1">ap-east-1</VSCodeOption> */}
344-
<VSCodeOption value="ap-south-1">ap-south-1</VSCodeOption>
345-
<VSCodeOption value="ap-northeast-1">ap-northeast-1</VSCodeOption>
346-
<VSCodeOption value="ap-northeast-2">ap-northeast-2</VSCodeOption>
347-
{/* <VSCodeOption value="ap-northeast-3">ap-northeast-3</VSCodeOption> */}
348-
<VSCodeOption value="ap-southeast-1">ap-southeast-1</VSCodeOption>
349-
<VSCodeOption value="ap-southeast-2">ap-southeast-2</VSCodeOption>
350-
<VSCodeOption value="ca-central-1">ca-central-1</VSCodeOption>
351-
<VSCodeOption value="eu-central-1">eu-central-1</VSCodeOption>
352-
<VSCodeOption value="eu-west-1">eu-west-1</VSCodeOption>
353-
<VSCodeOption value="eu-west-2">eu-west-2</VSCodeOption>
354-
<VSCodeOption value="eu-west-3">eu-west-3</VSCodeOption>
355-
{/* <VSCodeOption value="eu-north-1">eu-north-1</VSCodeOption> */}
356-
{/* <VSCodeOption value="me-south-1">me-south-1</VSCodeOption> */}
357-
<VSCodeOption value="sa-east-1">sa-east-1</VSCodeOption>
358-
<VSCodeOption value="us-gov-west-1">us-gov-west-1</VSCodeOption>
359-
{/* <VSCodeOption value="us-gov-east-1">us-gov-east-1</VSCodeOption> */}
360-
</VSCodeDropdown>
333+
onChange={(value: unknown) => {handleInputChange("awsRegion")({
334+
target: {
335+
value: (value as DropdownOption).value
336+
}
337+
})}}
338+
options={[
339+
{ value: "", label: "Select a region..." },
340+
{ value: "us-east-1", label: "us-east-1" },
341+
{ value: "us-east-2", label: "us-east-2" },
342+
{ value: "us-west-2", label: "us-west-2" },
343+
{ value: "ap-south-1", label: "ap-south-1" },
344+
{ value: "ap-northeast-1", label: "ap-northeast-1" },
345+
{ value: "ap-northeast-2", label: "ap-northeast-2" },
346+
{ value: "ap-southeast-1", label: "ap-southeast-1" },
347+
{ value: "ap-southeast-2", label: "ap-southeast-2" },
348+
{ value: "ca-central-1", label: "ca-central-1" },
349+
{ value: "eu-central-1", label: "eu-central-1" },
350+
{ value: "eu-west-1", label: "eu-west-1" },
351+
{ value: "eu-west-2", label: "eu-west-2" },
352+
{ value: "eu-west-3", label: "eu-west-3" },
353+
{ value: "sa-east-1", label: "sa-east-1" },
354+
{ value: "us-gov-west-1", label: "us-gov-west-1" }
355+
]}
356+
/>
361357
</div>
362-
<VSCodeCheckbox
358+
<Checkbox
363359
checked={apiConfiguration?.awsUseCrossRegionInference || false}
364-
onChange={(e: any) => {
365-
const isChecked = e.target.checked === true
366-
setApiConfiguration({ ...apiConfiguration, awsUseCrossRegionInference: isChecked })
360+
onChange={(checked: boolean) => {
361+
handleInputChange("awsUseCrossRegionInference")({
362+
target: { value: checked },
363+
})
367364
}}>
368365
Use cross-region inference
369-
</VSCodeCheckbox>
366+
</Checkbox>
370367
<p
371368
style={{
372369
fontSize: "12px",
@@ -393,18 +390,24 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
393390
<label htmlFor="vertex-region-dropdown">
394391
<span style={{ fontWeight: 500 }}>Google Cloud Region</span>
395392
</label>
396-
<VSCodeDropdown
393+
<Dropdown
397394
id="vertex-region-dropdown"
398395
value={apiConfiguration?.vertexRegion || ""}
399396
style={{ width: "100%" }}
400-
onChange={handleInputChange("vertexRegion")}>
401-
<VSCodeOption value="">Select a region...</VSCodeOption>
402-
<VSCodeOption value="us-east5">us-east5</VSCodeOption>
403-
<VSCodeOption value="us-central1">us-central1</VSCodeOption>
404-
<VSCodeOption value="europe-west1">europe-west1</VSCodeOption>
405-
<VSCodeOption value="europe-west4">europe-west4</VSCodeOption>
406-
<VSCodeOption value="asia-southeast1">asia-southeast1</VSCodeOption>
407-
</VSCodeDropdown>
397+
onChange={(value: unknown) => {handleInputChange("vertexRegion")({
398+
target: {
399+
value: (value as DropdownOption).value
400+
}
401+
})}}
402+
options={[
403+
{ value: "", label: "Select a region..." },
404+
{ value: "us-east5", label: "us-east5" },
405+
{ value: "us-central1", label: "us-central1" },
406+
{ value: "europe-west1", label: "europe-west1" },
407+
{ value: "europe-west4", label: "europe-west4" },
408+
{ value: "asia-southeast1", label: "asia-southeast1" }
409+
]}
410+
/>
408411
</div>
409412
<p
410413
style={{
@@ -477,29 +480,27 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
477480
</VSCodeTextField>
478481
<OpenAiModelPicker />
479482
<div style={{ display: 'flex', alignItems: 'center' }}>
480-
<VSCodeCheckbox
483+
<Checkbox
481484
checked={apiConfiguration?.openAiStreamingEnabled ?? true}
482-
onChange={(e: any) => {
483-
const isChecked = e.target.checked
484-
setApiConfiguration({
485-
...apiConfiguration,
486-
openAiStreamingEnabled: isChecked
485+
onChange={(checked: boolean) => {
486+
console.log("isChecked", checked)
487+
handleInputChange("openAiStreamingEnabled")({
488+
target: { value: checked },
487489
})
488490
}}>
489491
Enable streaming
490-
</VSCodeCheckbox>
492+
</Checkbox>
491493
</div>
492-
<VSCodeCheckbox
494+
<Checkbox
493495
checked={azureApiVersionSelected}
494-
onChange={(e: any) => {
495-
const isChecked = e.target.checked === true
496-
setAzureApiVersionSelected(isChecked)
497-
if (!isChecked) {
496+
onChange={(checked: boolean) => {
497+
setAzureApiVersionSelected(checked)
498+
if (!checked) {
498499
setApiConfiguration({ ...apiConfiguration, azureApiVersion: "" })
499500
}
500501
}}>
501502
Set Azure API version
502-
</VSCodeCheckbox>
503+
</Checkbox>
503504
{azureApiVersionSelected && (
504505
<VSCodeTextField
505506
value={apiConfiguration?.azureApiVersion || ""}

0 commit comments

Comments
 (0)