mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 20:31:37 -05:00
Merge pull request #369 from samhvw8/fix/roo-cline-select-api-config
fix api config profile
This commit is contained in:
@@ -961,10 +961,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
await this.configManager.SaveConfig(message.text, message.apiConfiguration);
|
await this.configManager.SaveConfig(message.text, message.apiConfiguration);
|
||||||
let listApiConfig = await this.configManager.ListConfig();
|
let listApiConfig = await this.configManager.ListConfig();
|
||||||
|
|
||||||
// Update listApiConfigMeta first to ensure UI has latest data
|
|
||||||
await this.updateGlobalState("listApiConfigMeta", listApiConfig);
|
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
this.updateGlobalState("listApiConfigMeta", listApiConfig),
|
||||||
this.updateApiConfiguration(message.apiConfiguration),
|
this.updateApiConfiguration(message.apiConfiguration),
|
||||||
this.updateGlobalState("currentApiConfigName", message.text),
|
this.updateGlobalState("currentApiConfigName", message.text),
|
||||||
])
|
])
|
||||||
@@ -1006,12 +1004,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||||||
try {
|
try {
|
||||||
const apiConfig = await this.configManager.LoadConfig(message.text);
|
const apiConfig = await this.configManager.LoadConfig(message.text);
|
||||||
const listApiConfig = await this.configManager.ListConfig();
|
const listApiConfig = await this.configManager.ListConfig();
|
||||||
const config = listApiConfig?.find(c => c.name === message.text);
|
|
||||||
|
|
||||||
// Update listApiConfigMeta first to ensure UI has latest data
|
|
||||||
await this.updateGlobalState("listApiConfigMeta", listApiConfig);
|
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
this.updateGlobalState("listApiConfigMeta", listApiConfig),
|
||||||
this.updateGlobalState("currentApiConfigName", message.text),
|
this.updateGlobalState("currentApiConfigName", message.text),
|
||||||
this.updateApiConfiguration(apiConfig),
|
this.updateApiConfiguration(apiConfig),
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module.exports.jest = function(config) {
|
|||||||
|
|
||||||
// Configure transform ignore patterns for ES modules
|
// Configure transform ignore patterns for ES modules
|
||||||
config.transformIgnorePatterns = [
|
config.transformIgnorePatterns = [
|
||||||
'/node_modules/(?!(rehype-highlight|react-remark|unist-util-visit|unist-util-find-after|vfile|unified|bail|is-plain-obj|trough|vfile-message|unist-util-stringify-position|mdast-util-from-markdown|mdast-util-to-string|micromark|decode-named-character-reference|character-entities|markdown-table|zwitch|longest-streak|escape-string-regexp|unist-util-is|hast-util-to-text|@vscode/webview-ui-toolkit|@microsoft/fast-react-wrapper|@microsoft/fast-element|@microsoft/fast-foundation|@microsoft/fast-web-utilities|exenv-es6)/)'
|
'/node_modules/(?!(rehype-highlight|react-remark|unist-util-visit|unist-util-find-after|vfile|unified|bail|is-plain-obj|trough|vfile-message|unist-util-stringify-position|mdast-util-from-markdown|mdast-util-to-string|micromark|decode-named-character-reference|character-entities|markdown-table|zwitch|longest-streak|escape-string-regexp|unist-util-is|hast-util-to-text|@vscode/webview-ui-toolkit|@microsoft/fast-react-wrapper|@microsoft/fast-element|@microsoft/fast-foundation|@microsoft/fast-web-utilities|exenv-es6|vscrui)/)'
|
||||||
];
|
];
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
|
|||||||
15
webview-ui/package-lock.json
generated
15
webview-ui/package-lock.json
generated
@@ -31,6 +31,7 @@
|
|||||||
"shell-quote": "^1.8.2",
|
"shell-quote": "^1.8.2",
|
||||||
"styled-components": "^6.1.13",
|
"styled-components": "^6.1.13",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
|
"vscrui": "^0.2.0",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -15155,6 +15156,20 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vscrui": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/vscrui/-/vscrui-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-fvxZM/uIYOMN3fUbE2In+R1VrNj8PKcfAdh+Us2bJaPGuG9ySkR6xkV2aJVqXxWDX77U3v/UQGc5e7URrB52Gw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/estruyf"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"react": "^17 || ^18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/w3c-hr-time": {
|
"node_modules/w3c-hr-time": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
"shell-quote": "^1.8.2",
|
"shell-quote": "^1.8.2",
|
||||||
"styled-components": "^6.1.13",
|
"styled-components": "^6.1.13",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
|
"vscrui": "^0.2.0",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
|
import { Checkbox, Dropdown } from "vscrui"
|
||||||
|
import type { DropdownOption } from "vscrui"
|
||||||
import {
|
import {
|
||||||
VSCodeCheckbox,
|
|
||||||
VSCodeDropdown,
|
|
||||||
VSCodeLink,
|
VSCodeLink,
|
||||||
VSCodeOption,
|
|
||||||
VSCodeRadio,
|
VSCodeRadio,
|
||||||
VSCodeRadioGroup,
|
VSCodeRadioGroup,
|
||||||
VSCodeTextField,
|
VSCodeTextField
|
||||||
} from "@vscode/webview-ui-toolkit/react"
|
} from "@vscode/webview-ui-toolkit/react"
|
||||||
import { Fragment, memo, useCallback, useEffect, useMemo, useState } from "react"
|
import { Fragment, memo, useCallback, useEffect, useMemo, useState } from "react"
|
||||||
import { useEvent, useInterval } from "react-use"
|
import { useEvent, useInterval } from "react-use"
|
||||||
@@ -95,35 +94,26 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
|
|||||||
}, [])
|
}, [])
|
||||||
useEvent("message", handleMessage)
|
useEvent("message", handleMessage)
|
||||||
|
|
||||||
/*
|
|
||||||
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.
|
|
||||||
https://github.com/microsoft/vscode-webview-ui-toolkit/issues/433
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
As a workaround, we create separate instances of the dropdown for each provider, and then conditionally render the one that matches the current provider.
|
|
||||||
*/
|
|
||||||
const createDropdown = (models: Record<string, ModelInfo>) => {
|
const createDropdown = (models: Record<string, ModelInfo>) => {
|
||||||
|
const options: DropdownOption[] = [
|
||||||
|
{ value: "", label: "Select a model..." },
|
||||||
|
...Object.keys(models).map((modelId) => ({
|
||||||
|
value: modelId,
|
||||||
|
label: modelId,
|
||||||
|
}))
|
||||||
|
]
|
||||||
return (
|
return (
|
||||||
<VSCodeDropdown
|
<Dropdown
|
||||||
id="model-id"
|
id="model-id"
|
||||||
value={selectedModelId}
|
value={selectedModelId}
|
||||||
onChange={handleInputChange("apiModelId")}
|
onChange={(value: unknown) => {handleInputChange("apiModelId")({
|
||||||
style={{ width: "100%" }}>
|
target: {
|
||||||
<VSCodeOption value="">Select a model...</VSCodeOption>
|
value: (value as DropdownOption).value
|
||||||
{Object.keys(models).map((modelId) => (
|
}
|
||||||
<VSCodeOption
|
})}}
|
||||||
key={modelId}
|
style={{ width: "100%" }}
|
||||||
value={modelId}
|
options={options}
|
||||||
style={{
|
/>
|
||||||
whiteSpace: "normal",
|
|
||||||
wordWrap: "break-word",
|
|
||||||
maxWidth: "100%",
|
|
||||||
}}>
|
|
||||||
{modelId}
|
|
||||||
</VSCodeOption>
|
|
||||||
))}
|
|
||||||
</VSCodeDropdown>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,24 +123,32 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
|
|||||||
<label htmlFor="api-provider">
|
<label htmlFor="api-provider">
|
||||||
<span style={{ fontWeight: 500 }}>API Provider</span>
|
<span style={{ fontWeight: 500 }}>API Provider</span>
|
||||||
</label>
|
</label>
|
||||||
<VSCodeDropdown
|
<Dropdown
|
||||||
id="api-provider"
|
id="api-provider"
|
||||||
value={selectedProvider}
|
value={selectedProvider}
|
||||||
onChange={handleInputChange("apiProvider")}
|
onChange={(value: unknown) => {
|
||||||
style={{ minWidth: 130, position: "relative", zIndex: OPENROUTER_MODEL_PICKER_Z_INDEX + 1 }}>
|
handleInputChange("apiProvider")({
|
||||||
<VSCodeOption value="openrouter">OpenRouter</VSCodeOption>
|
target: {
|
||||||
<VSCodeOption value="anthropic">Anthropic</VSCodeOption>
|
value: (value as DropdownOption).value
|
||||||
<VSCodeOption value="gemini">Google Gemini</VSCodeOption>
|
}
|
||||||
<VSCodeOption value="deepseek">DeepSeek</VSCodeOption>
|
})
|
||||||
<VSCodeOption value="openai-native">OpenAI</VSCodeOption>
|
}}
|
||||||
<VSCodeOption value="openai">OpenAI Compatible</VSCodeOption>
|
style={{ minWidth: 130, position: "relative", zIndex: OPENROUTER_MODEL_PICKER_Z_INDEX + 1 }}
|
||||||
<VSCodeOption value="vertex">GCP Vertex AI</VSCodeOption>
|
options={[
|
||||||
<VSCodeOption value="bedrock">AWS Bedrock</VSCodeOption>
|
{ value: "openrouter", label: "OpenRouter" },
|
||||||
<VSCodeOption value="glama">Glama</VSCodeOption>
|
{ value: "anthropic", label: "Anthropic" },
|
||||||
<VSCodeOption value="vscode-lm">VS Code LM API</VSCodeOption>
|
{ value: "gemini", label: "Google Gemini" },
|
||||||
<VSCodeOption value="lmstudio">LM Studio</VSCodeOption>
|
{ value: "deepseek", label: "DeepSeek" },
|
||||||
<VSCodeOption value="ollama">Ollama</VSCodeOption>
|
{ value: "openai-native", label: "OpenAI" },
|
||||||
</VSCodeDropdown>
|
{ value: "openai", label: "OpenAI Compatible" },
|
||||||
|
{ value: "vertex", label: "GCP Vertex AI" },
|
||||||
|
{ value: "bedrock", label: "AWS Bedrock" },
|
||||||
|
{ value: "glama", label: "Glama" },
|
||||||
|
{ value: "vscode-lm", label: "VS Code LM API" },
|
||||||
|
{ value: "lmstudio", label: "LM Studio" },
|
||||||
|
{ value: "ollama", label: "Ollama" }
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{selectedProvider === "anthropic" && (
|
{selectedProvider === "anthropic" && (
|
||||||
@@ -164,17 +162,16 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
|
|||||||
<span style={{ fontWeight: 500 }}>Anthropic API Key</span>
|
<span style={{ fontWeight: 500 }}>Anthropic API Key</span>
|
||||||
</VSCodeTextField>
|
</VSCodeTextField>
|
||||||
|
|
||||||
<VSCodeCheckbox
|
<Checkbox
|
||||||
checked={anthropicBaseUrlSelected}
|
checked={anthropicBaseUrlSelected}
|
||||||
onChange={(e: any) => {
|
onChange={(checked: boolean) => {
|
||||||
const isChecked = e.target.checked === true
|
setAnthropicBaseUrlSelected(checked)
|
||||||
setAnthropicBaseUrlSelected(isChecked)
|
if (!checked) {
|
||||||
if (!isChecked) {
|
|
||||||
setApiConfiguration({ ...apiConfiguration, anthropicBaseUrl: "" })
|
setApiConfiguration({ ...apiConfiguration, anthropicBaseUrl: "" })
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
Use custom base URL
|
Use custom base URL
|
||||||
</VSCodeCheckbox>
|
</Checkbox>
|
||||||
|
|
||||||
{anthropicBaseUrlSelected && (
|
{anthropicBaseUrlSelected && (
|
||||||
<VSCodeTextField
|
<VSCodeTextField
|
||||||
@@ -293,14 +290,15 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
|
|||||||
</span>
|
</span>
|
||||||
)} */}
|
)} */}
|
||||||
</p>
|
</p>
|
||||||
<VSCodeCheckbox
|
<Checkbox
|
||||||
checked={apiConfiguration?.openRouterUseMiddleOutTransform || false}
|
checked={apiConfiguration?.openRouterUseMiddleOutTransform || false}
|
||||||
onChange={(e: any) => {
|
onChange={(checked: boolean) => {
|
||||||
const isChecked = e.target.checked === true
|
handleInputChange("openRouterUseMiddleOutTransform")({
|
||||||
setApiConfiguration({ ...apiConfiguration, openRouterUseMiddleOutTransform: isChecked })
|
target: { value: checked },
|
||||||
|
})
|
||||||
}}>
|
}}>
|
||||||
Compress prompts and message chains to the context size (<a href="https://openrouter.ai/docs/transforms">OpenRouter Transforms</a>)
|
Compress prompts and message chains to the context size (<a href="https://openrouter.ai/docs/transforms">OpenRouter Transforms</a>)
|
||||||
</VSCodeCheckbox>
|
</Checkbox>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -335,45 +333,44 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
|
|||||||
<label htmlFor="aws-region-dropdown">
|
<label htmlFor="aws-region-dropdown">
|
||||||
<span style={{ fontWeight: 500 }}>AWS Region</span>
|
<span style={{ fontWeight: 500 }}>AWS Region</span>
|
||||||
</label>
|
</label>
|
||||||
<VSCodeDropdown
|
<Dropdown
|
||||||
id="aws-region-dropdown"
|
id="aws-region-dropdown"
|
||||||
value={apiConfiguration?.awsRegion || ""}
|
value={apiConfiguration?.awsRegion || ""}
|
||||||
style={{ width: "100%" }}
|
style={{ width: "100%" }}
|
||||||
onChange={handleInputChange("awsRegion")}>
|
onChange={(value: unknown) => {handleInputChange("awsRegion")({
|
||||||
<VSCodeOption value="">Select a region...</VSCodeOption>
|
target: {
|
||||||
{/* 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. */}
|
value: (value as DropdownOption).value
|
||||||
<VSCodeOption value="us-east-1">us-east-1</VSCodeOption>
|
}
|
||||||
<VSCodeOption value="us-east-2">us-east-2</VSCodeOption>
|
})}}
|
||||||
{/* <VSCodeOption value="us-west-1">us-west-1</VSCodeOption> */}
|
options={[
|
||||||
<VSCodeOption value="us-west-2">us-west-2</VSCodeOption>
|
{ value: "", label: "Select a region..." },
|
||||||
{/* <VSCodeOption value="af-south-1">af-south-1</VSCodeOption> */}
|
{ value: "us-east-1", label: "us-east-1" },
|
||||||
{/* <VSCodeOption value="ap-east-1">ap-east-1</VSCodeOption> */}
|
{ value: "us-east-2", label: "us-east-2" },
|
||||||
<VSCodeOption value="ap-south-1">ap-south-1</VSCodeOption>
|
{ value: "us-west-2", label: "us-west-2" },
|
||||||
<VSCodeOption value="ap-northeast-1">ap-northeast-1</VSCodeOption>
|
{ value: "ap-south-1", label: "ap-south-1" },
|
||||||
<VSCodeOption value="ap-northeast-2">ap-northeast-2</VSCodeOption>
|
{ value: "ap-northeast-1", label: "ap-northeast-1" },
|
||||||
{/* <VSCodeOption value="ap-northeast-3">ap-northeast-3</VSCodeOption> */}
|
{ value: "ap-northeast-2", label: "ap-northeast-2" },
|
||||||
<VSCodeOption value="ap-southeast-1">ap-southeast-1</VSCodeOption>
|
{ value: "ap-southeast-1", label: "ap-southeast-1" },
|
||||||
<VSCodeOption value="ap-southeast-2">ap-southeast-2</VSCodeOption>
|
{ value: "ap-southeast-2", label: "ap-southeast-2" },
|
||||||
<VSCodeOption value="ca-central-1">ca-central-1</VSCodeOption>
|
{ value: "ca-central-1", label: "ca-central-1" },
|
||||||
<VSCodeOption value="eu-central-1">eu-central-1</VSCodeOption>
|
{ value: "eu-central-1", label: "eu-central-1" },
|
||||||
<VSCodeOption value="eu-west-1">eu-west-1</VSCodeOption>
|
{ value: "eu-west-1", label: "eu-west-1" },
|
||||||
<VSCodeOption value="eu-west-2">eu-west-2</VSCodeOption>
|
{ value: "eu-west-2", label: "eu-west-2" },
|
||||||
<VSCodeOption value="eu-west-3">eu-west-3</VSCodeOption>
|
{ value: "eu-west-3", label: "eu-west-3" },
|
||||||
{/* <VSCodeOption value="eu-north-1">eu-north-1</VSCodeOption> */}
|
{ value: "sa-east-1", label: "sa-east-1" },
|
||||||
{/* <VSCodeOption value="me-south-1">me-south-1</VSCodeOption> */}
|
{ value: "us-gov-west-1", label: "us-gov-west-1" }
|
||||||
<VSCodeOption value="sa-east-1">sa-east-1</VSCodeOption>
|
]}
|
||||||
<VSCodeOption value="us-gov-west-1">us-gov-west-1</VSCodeOption>
|
/>
|
||||||
{/* <VSCodeOption value="us-gov-east-1">us-gov-east-1</VSCodeOption> */}
|
|
||||||
</VSCodeDropdown>
|
|
||||||
</div>
|
</div>
|
||||||
<VSCodeCheckbox
|
<Checkbox
|
||||||
checked={apiConfiguration?.awsUseCrossRegionInference || false}
|
checked={apiConfiguration?.awsUseCrossRegionInference || false}
|
||||||
onChange={(e: any) => {
|
onChange={(checked: boolean) => {
|
||||||
const isChecked = e.target.checked === true
|
handleInputChange("awsUseCrossRegionInference")({
|
||||||
setApiConfiguration({ ...apiConfiguration, awsUseCrossRegionInference: isChecked })
|
target: { value: checked },
|
||||||
|
})
|
||||||
}}>
|
}}>
|
||||||
Use cross-region inference
|
Use cross-region inference
|
||||||
</VSCodeCheckbox>
|
</Checkbox>
|
||||||
<p
|
<p
|
||||||
style={{
|
style={{
|
||||||
fontSize: "12px",
|
fontSize: "12px",
|
||||||
@@ -400,18 +397,24 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
|
|||||||
<label htmlFor="vertex-region-dropdown">
|
<label htmlFor="vertex-region-dropdown">
|
||||||
<span style={{ fontWeight: 500 }}>Google Cloud Region</span>
|
<span style={{ fontWeight: 500 }}>Google Cloud Region</span>
|
||||||
</label>
|
</label>
|
||||||
<VSCodeDropdown
|
<Dropdown
|
||||||
id="vertex-region-dropdown"
|
id="vertex-region-dropdown"
|
||||||
value={apiConfiguration?.vertexRegion || ""}
|
value={apiConfiguration?.vertexRegion || ""}
|
||||||
style={{ width: "100%" }}
|
style={{ width: "100%" }}
|
||||||
onChange={handleInputChange("vertexRegion")}>
|
onChange={(value: unknown) => {handleInputChange("vertexRegion")({
|
||||||
<VSCodeOption value="">Select a region...</VSCodeOption>
|
target: {
|
||||||
<VSCodeOption value="us-east5">us-east5</VSCodeOption>
|
value: (value as DropdownOption).value
|
||||||
<VSCodeOption value="us-central1">us-central1</VSCodeOption>
|
}
|
||||||
<VSCodeOption value="europe-west1">europe-west1</VSCodeOption>
|
})}}
|
||||||
<VSCodeOption value="europe-west4">europe-west4</VSCodeOption>
|
options={[
|
||||||
<VSCodeOption value="asia-southeast1">asia-southeast1</VSCodeOption>
|
{ value: "", label: "Select a region..." },
|
||||||
</VSCodeDropdown>
|
{ value: "us-east5", label: "us-east5" },
|
||||||
|
{ value: "us-central1", label: "us-central1" },
|
||||||
|
{ value: "europe-west1", label: "europe-west1" },
|
||||||
|
{ value: "europe-west4", label: "europe-west4" },
|
||||||
|
{ value: "asia-southeast1", label: "asia-southeast1" }
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
style={{
|
style={{
|
||||||
@@ -484,29 +487,26 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
|
|||||||
</VSCodeTextField>
|
</VSCodeTextField>
|
||||||
<OpenAiModelPicker />
|
<OpenAiModelPicker />
|
||||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
<VSCodeCheckbox
|
<Checkbox
|
||||||
checked={apiConfiguration?.openAiStreamingEnabled ?? true}
|
checked={apiConfiguration?.openAiStreamingEnabled ?? true}
|
||||||
onChange={(e: any) => {
|
onChange={(checked: boolean) => {
|
||||||
const isChecked = e.target.checked
|
handleInputChange("openAiStreamingEnabled")({
|
||||||
setApiConfiguration({
|
target: { value: checked },
|
||||||
...apiConfiguration,
|
|
||||||
openAiStreamingEnabled: isChecked
|
|
||||||
})
|
})
|
||||||
}}>
|
}}>
|
||||||
Enable streaming
|
Enable streaming
|
||||||
</VSCodeCheckbox>
|
</Checkbox>
|
||||||
</div>
|
</div>
|
||||||
<VSCodeCheckbox
|
<Checkbox
|
||||||
checked={azureApiVersionSelected}
|
checked={azureApiVersionSelected}
|
||||||
onChange={(e: any) => {
|
onChange={(checked: boolean) => {
|
||||||
const isChecked = e.target.checked === true
|
setAzureApiVersionSelected(checked)
|
||||||
setAzureApiVersionSelected(isChecked)
|
if (!checked) {
|
||||||
if (!isChecked) {
|
|
||||||
setApiConfiguration({ ...apiConfiguration, azureApiVersion: "" })
|
setApiConfiguration({ ...apiConfiguration, azureApiVersion: "" })
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
Set Azure API version
|
Set Azure API version
|
||||||
</VSCodeCheckbox>
|
</Checkbox>
|
||||||
{azureApiVersionSelected && (
|
{azureApiVersionSelected && (
|
||||||
<VSCodeTextField
|
<VSCodeTextField
|
||||||
value={apiConfiguration?.azureApiVersion || ""}
|
value={apiConfiguration?.azureApiVersion || ""}
|
||||||
@@ -633,29 +633,28 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) =
|
|||||||
<span style={{ fontWeight: 500 }}>Language Model</span>
|
<span style={{ fontWeight: 500 }}>Language Model</span>
|
||||||
</label>
|
</label>
|
||||||
{vsCodeLmModels.length > 0 ? (
|
{vsCodeLmModels.length > 0 ? (
|
||||||
<VSCodeDropdown
|
<Dropdown
|
||||||
id="vscode-lm-model"
|
id="vscode-lm-model"
|
||||||
value={apiConfiguration?.vsCodeLmModelSelector ?
|
value={apiConfiguration?.vsCodeLmModelSelector ?
|
||||||
`${apiConfiguration.vsCodeLmModelSelector.vendor ?? ""}/${apiConfiguration.vsCodeLmModelSelector.family ?? ""}` :
|
`${apiConfiguration.vsCodeLmModelSelector.vendor ?? ""}/${apiConfiguration.vsCodeLmModelSelector.family ?? ""}` :
|
||||||
""}
|
""}
|
||||||
onChange={(e) => {
|
onChange={(value: unknown) => {
|
||||||
const value = (e.target as HTMLInputElement).value;
|
const valueStr = (value as DropdownOption).value;
|
||||||
const [vendor, family] = value.split('/');
|
const [vendor, family] = valueStr.split('/');
|
||||||
setApiConfiguration({
|
setApiConfiguration({
|
||||||
...apiConfiguration,
|
...apiConfiguration,
|
||||||
vsCodeLmModelSelector: value ? { vendor, family } : undefined
|
vsCodeLmModelSelector: valueStr ? { vendor, family } : undefined
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
style={{ width: "100%" }}>
|
style={{ width: "100%" }}
|
||||||
<VSCodeOption value="">Select a model...</VSCodeOption>
|
options={[
|
||||||
{vsCodeLmModels.map((model) => (
|
{ value: "", label: "Select a model..." },
|
||||||
<VSCodeOption
|
...vsCodeLmModels.map((model) => ({
|
||||||
key={`${model.vendor}/${model.family}`}
|
value: `${model.vendor}/${model.family}`,
|
||||||
value={`${model.vendor}/${model.family}`}>
|
label: `${model.vendor} - ${model.family}`
|
||||||
{model.vendor} - {model.family}
|
}))
|
||||||
</VSCodeOption>
|
]}
|
||||||
))}
|
/>
|
||||||
</VSCodeDropdown>
|
|
||||||
) : (
|
) : (
|
||||||
<p style={{
|
<p style={{
|
||||||
fontSize: "12px",
|
fontSize: "12px",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
import { VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||||
|
import debounce from "debounce"
|
||||||
import { Fzf } from "fzf"
|
import { Fzf } from "fzf"
|
||||||
import React, { KeyboardEvent, memo, useEffect, useMemo, useRef, useState } from "react"
|
import React, { KeyboardEvent, memo, useEffect, useMemo, useRef, useState } from "react"
|
||||||
import { useRemark } from "react-remark"
|
import { useRemark } from "react-remark"
|
||||||
@@ -44,8 +45,24 @@ const GlamaModelPicker: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [apiConfiguration, searchTerm])
|
}, [apiConfiguration, searchTerm])
|
||||||
|
|
||||||
useMount(() => {
|
const debouncedRefreshModels = useMemo(
|
||||||
|
() =>
|
||||||
|
debounce(
|
||||||
|
() => {
|
||||||
vscode.postMessage({ type: "refreshGlamaModels" })
|
vscode.postMessage({ type: "refreshGlamaModels" })
|
||||||
|
},
|
||||||
|
50
|
||||||
|
),
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
useMount(() => {
|
||||||
|
debouncedRefreshModels()
|
||||||
|
|
||||||
|
// Cleanup debounced function
|
||||||
|
return () => {
|
||||||
|
debouncedRefreshModels.clear()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
import { VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||||
import { Fzf } from "fzf"
|
import { Fzf } from "fzf"
|
||||||
import React, { KeyboardEvent, memo, useEffect, useMemo, useRef, useState } from "react"
|
import React, { KeyboardEvent, memo, useEffect, useMemo, useRef, useState } from "react"
|
||||||
|
import debounce from "debounce"
|
||||||
import { useRemark } from "react-remark"
|
import { useRemark } from "react-remark"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import { useExtensionState } from "../../context/ExtensionStateContext"
|
import { useExtensionState } from "../../context/ExtensionStateContext"
|
||||||
@@ -34,18 +35,38 @@ const OpenAiModelPicker: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [apiConfiguration, searchTerm])
|
}, [apiConfiguration, searchTerm])
|
||||||
|
|
||||||
|
const debouncedRefreshModels = useMemo(
|
||||||
|
() =>
|
||||||
|
debounce(
|
||||||
|
(baseUrl: string, apiKey: string) => {
|
||||||
|
vscode.postMessage({
|
||||||
|
type: "refreshOpenAiModels",
|
||||||
|
values: {
|
||||||
|
baseUrl,
|
||||||
|
apiKey
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
50
|
||||||
|
),
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!apiConfiguration?.openAiBaseUrl || !apiConfiguration?.openAiApiKey) {
|
if (!apiConfiguration?.openAiBaseUrl || !apiConfiguration?.openAiApiKey) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
vscode.postMessage({
|
debouncedRefreshModels(
|
||||||
type: "refreshOpenAiModels", values: {
|
apiConfiguration.openAiBaseUrl,
|
||||||
baseUrl: apiConfiguration?.openAiBaseUrl,
|
apiConfiguration.openAiApiKey
|
||||||
apiKey: apiConfiguration?.openAiApiKey
|
)
|
||||||
|
|
||||||
|
// Cleanup debounced function
|
||||||
|
return () => {
|
||||||
|
debouncedRefreshModels.clear()
|
||||||
}
|
}
|
||||||
})
|
}, [apiConfiguration?.openAiBaseUrl, apiConfiguration?.openAiApiKey, debouncedRefreshModels])
|
||||||
}, [apiConfiguration?.openAiBaseUrl, apiConfiguration?.openAiApiKey])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
import { VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||||
|
import debounce from "debounce"
|
||||||
import { Fzf } from "fzf"
|
import { Fzf } from "fzf"
|
||||||
import React, { KeyboardEvent, memo, useEffect, useMemo, useRef, useState } from "react"
|
import React, { KeyboardEvent, memo, useEffect, useMemo, useRef, useState } from "react"
|
||||||
import { useRemark } from "react-remark"
|
import { useRemark } from "react-remark"
|
||||||
@@ -43,8 +44,24 @@ const OpenRouterModelPicker: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [apiConfiguration, searchTerm])
|
}, [apiConfiguration, searchTerm])
|
||||||
|
|
||||||
useMount(() => {
|
const debouncedRefreshModels = useMemo(
|
||||||
|
() =>
|
||||||
|
debounce(
|
||||||
|
() => {
|
||||||
vscode.postMessage({ type: "refreshOpenRouterModels" })
|
vscode.postMessage({ type: "refreshOpenRouterModels" })
|
||||||
|
},
|
||||||
|
50
|
||||||
|
),
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
useMount(() => {
|
||||||
|
debouncedRefreshModels()
|
||||||
|
|
||||||
|
// Cleanup debounced function
|
||||||
|
return () => {
|
||||||
|
debouncedRefreshModels.clear()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,14 +1,26 @@
|
|||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
|
|
||||||
// Mock window.matchMedia
|
// Mock crypto.getRandomValues
|
||||||
|
Object.defineProperty(window, 'crypto', {
|
||||||
|
value: {
|
||||||
|
getRandomValues: function(buffer: Uint8Array) {
|
||||||
|
for (let i = 0; i < buffer.length; i++) {
|
||||||
|
buffer[i] = Math.floor(Math.random() * 256);
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mock matchMedia
|
||||||
Object.defineProperty(window, 'matchMedia', {
|
Object.defineProperty(window, 'matchMedia', {
|
||||||
writable: true,
|
writable: true,
|
||||||
value: jest.fn().mockImplementation(query => ({
|
value: jest.fn().mockImplementation(query => ({
|
||||||
matches: false,
|
matches: false,
|
||||||
media: query,
|
media: query,
|
||||||
onchange: null,
|
onchange: null,
|
||||||
addListener: jest.fn(), // Deprecated
|
addListener: jest.fn(), // deprecated
|
||||||
removeListener: jest.fn(), // Deprecated
|
removeListener: jest.fn(), // deprecated
|
||||||
addEventListener: jest.fn(),
|
addEventListener: jest.fn(),
|
||||||
removeEventListener: jest.fn(),
|
removeEventListener: jest.fn(),
|
||||||
dispatchEvent: jest.fn(),
|
dispatchEvent: jest.fn(),
|
||||||
|
|||||||
Reference in New Issue
Block a user