mirror of
https://github.com/cline/cline.git
synced 2026-09-09 15:02:23 +08:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f6e583308 | ||
|
|
6df92bb05c | ||
|
|
5d4929e1be | ||
|
|
7f3c1c093d |
@@ -313,7 +313,7 @@ message ApiConfiguration {
|
||||
message UpdateApiConfigurationRequestNew {
|
||||
Metadata metadata = 1;
|
||||
ApiConfiguration updates = 2;
|
||||
|
||||
|
||||
// Required field mask specifying which fields to update.
|
||||
// Field paths use dot notation with camelCase field names:
|
||||
// - "options.ulid" (for options fields)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { anthropicModels, CLAUDE_SONNET_1M_SUFFIX } from "@shared/api"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { ApiKeyField } from "../common/ApiKeyField"
|
||||
import { BaseUrlField } from "../common/BaseUrlField"
|
||||
import { ContextWindowSwitcher } from "../common/ContextWindowSwitcher"
|
||||
@@ -8,7 +10,6 @@ import { ModelInfoView } from "../common/ModelInfoView"
|
||||
import { ModelSelector } from "../common/ModelSelector"
|
||||
import ThinkingBudgetSlider from "../ThinkingBudgetSlider"
|
||||
import { normalizeApiConfiguration } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
// Anthropic models that support thinking/reasoning mode
|
||||
export const SUPPORTED_ANTHROPIC_THINKING_MODELS = [
|
||||
@@ -36,21 +37,43 @@ interface AnthropicProviderProps {
|
||||
*/
|
||||
export const AnthropicProvider = ({ showModelOptions, isPopup, currentMode }: AnthropicProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange, handleModeFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
// Get the normalized configuration
|
||||
const { selectedModelId, selectedModelInfo } = normalizeApiConfiguration(apiConfiguration, currentMode)
|
||||
|
||||
// Helper function for model switching
|
||||
const handleModelChange = (modelId: string) => {
|
||||
handleModeFieldChange({ plan: "planModeApiModelId", act: "actModeApiModelId" }, modelId, currentMode)
|
||||
const handleModelChange = async (modelId: string) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: { options: { planModeApiModelId: modelId } },
|
||||
updateMask: ["options.planModeApiModelId"],
|
||||
}
|
||||
: {
|
||||
updates: { options: { actModeApiModelId: modelId } },
|
||||
updateMask: ["options.actModeApiModelId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ApiKeyField
|
||||
initialValue={apiConfiguration?.apiKey || ""}
|
||||
onChange={(value) => handleFieldChange("apiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
apiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.apiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
providerName="Anthropic"
|
||||
signupUrl="https://console.anthropic.com/settings/keys"
|
||||
/>
|
||||
@@ -58,7 +81,18 @@ export const AnthropicProvider = ({ showModelOptions, isPopup, currentMode }: An
|
||||
<BaseUrlField
|
||||
initialValue={apiConfiguration?.anthropicBaseUrl}
|
||||
label="Use custom base URL"
|
||||
onChange={(value) => handleFieldChange("anthropicBaseUrl", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
anthropicBaseUrl: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.anthropicBaseUrl"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Default: https://api.anthropic.com"
|
||||
/>
|
||||
|
||||
@@ -67,13 +101,23 @@ export const AnthropicProvider = ({ showModelOptions, isPopup, currentMode }: An
|
||||
<ModelSelector
|
||||
label="Model"
|
||||
models={anthropicModels}
|
||||
onChange={(e) =>
|
||||
handleModeFieldChange(
|
||||
{ plan: "planModeApiModelId", act: "actModeApiModelId" },
|
||||
e.target.value,
|
||||
currentMode,
|
||||
onChange={async (e: any) => {
|
||||
const value = e.target.value
|
||||
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: { options: { planModeApiModelId: value } },
|
||||
updateMask: ["options.planModeApiModelId"],
|
||||
}
|
||||
: {
|
||||
updates: { options: { actModeApiModelId: value } },
|
||||
updateMask: ["options.actModeApiModelId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}}
|
||||
selectedModelId={selectedModelId}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import BasetenModelPicker from "../BasetenModelPicker"
|
||||
import { ApiKeyField } from "../common/ApiKeyField"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Props for the BasetenProvider component
|
||||
@@ -18,13 +19,23 @@ interface BasetenProviderProps {
|
||||
*/
|
||||
export const BasetenProvider = ({ showModelOptions, isPopup, currentMode }: BasetenProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ApiKeyField
|
||||
initialValue={apiConfiguration?.basetenApiKey || ""}
|
||||
onChange={(value) => handleFieldChange("basetenApiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
basetenApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.basetenApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
providerName="Baseten"
|
||||
signupUrl="https://app.baseten.co/settings/api_keys"
|
||||
/>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { bedrockDefaultModelId, bedrockModels, CLAUDE_SONNET_1M_SUFFIX } from "@shared/api"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import BedrockData from "@shared/providers/bedrock.json"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { VSCodeCheckbox, VSCodeDropdown, VSCodeOption, VSCodeRadio, VSCodeRadioGroup } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useState } from "react"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { DebouncedTextField } from "../common/DebouncedTextField"
|
||||
import { ModelInfoView } from "../common/ModelInfoView"
|
||||
import { DropdownContainer } from "../common/ModelSelector"
|
||||
import ThinkingBudgetSlider from "../ThinkingBudgetSlider"
|
||||
import { getModeSpecificFields, normalizeApiConfiguration } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
const CLAUDE_MODELS = [
|
||||
"anthropic.claude-3-7-sonnet-20250219-v1:0",
|
||||
@@ -36,7 +37,6 @@ interface BedrockProviderProps {
|
||||
|
||||
export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: BedrockProviderProps) => {
|
||||
const { apiConfiguration, remoteConfigSettings } = useExtensionState()
|
||||
const { handleFieldChange, handleModeFieldChange, handleModeFieldsChange } = useApiConfigurationHandlers()
|
||||
|
||||
const { selectedModelId, selectedModelInfo } = normalizeApiConfiguration(apiConfiguration, currentMode)
|
||||
const modeFields = getModeSpecificFields(apiConfiguration, currentMode)
|
||||
@@ -45,9 +45,18 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
return (
|
||||
<div className="flex flex-col gap-1">
|
||||
<VSCodeRadioGroup
|
||||
onChange={(e) => {
|
||||
onChange={async (e) => {
|
||||
const value = (e.target as HTMLInputElement)?.value
|
||||
handleFieldChange("awsAuthentication", value)
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
awsAuthentication: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.awsAuthentication"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
value={apiConfiguration?.awsAuthentication ?? (apiConfiguration?.awsProfile ? "profile" : "credentials")}>
|
||||
<VSCodeRadio value="apikey">API Key</VSCodeRadio>
|
||||
@@ -61,7 +70,18 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
className="w-full"
|
||||
initialValue={apiConfiguration?.awsProfile ?? ""}
|
||||
key="profile"
|
||||
onChange={(value) => handleFieldChange("awsProfile", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
awsProfile: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.awsProfile"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Enter profile name (default if empty)">
|
||||
<span className="font-medium">AWS Profile Name</span>
|
||||
</DebouncedTextField>
|
||||
@@ -70,7 +90,18 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
className="w-full"
|
||||
initialValue={apiConfiguration?.awsBedrockApiKey ?? ""}
|
||||
key="apikey"
|
||||
onChange={(value) => handleFieldChange("awsBedrockApiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
awsBedrockApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.awsBedrockApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Enter Bedrock Api Key"
|
||||
type="password">
|
||||
<span className="font-medium">AWS Bedrock Api Key</span>
|
||||
@@ -81,7 +112,18 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
className="w-full"
|
||||
initialValue={apiConfiguration?.awsAccessKey || ""}
|
||||
key="accessKey"
|
||||
onChange={(value) => handleFieldChange("awsAccessKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
awsAccessKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.awsAccessKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Enter Access Key..."
|
||||
type="password">
|
||||
<span className="font-medium">AWS Access Key</span>
|
||||
@@ -89,7 +131,18 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
<DebouncedTextField
|
||||
className="w-full"
|
||||
initialValue={apiConfiguration?.awsSecretKey || ""}
|
||||
onChange={(value) => handleFieldChange("awsSecretKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
awsSecretKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.awsSecretKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Enter Secret Key..."
|
||||
type="password">
|
||||
<span className="font-medium">AWS Secret Key</span>
|
||||
@@ -97,7 +150,18 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
<DebouncedTextField
|
||||
className="w-full"
|
||||
initialValue={apiConfiguration?.awsSessionToken || ""}
|
||||
onChange={(value) => handleFieldChange("awsSessionToken", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
awsSessionToken: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.awsSessionToken"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Enter Session Token..."
|
||||
type="password">
|
||||
<span className="font-medium">AWS Session Token</span>
|
||||
@@ -123,7 +187,18 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
className="w-full"
|
||||
disabled={remoteConfigSettings?.awsRegion !== undefined}
|
||||
id="aws-region-dropdown"
|
||||
onChange={(e: any) => handleFieldChange("awsRegion", e.target.value)}
|
||||
onChange={async (e: any) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
awsRegion: e.target.value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.awsRegion"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
value={apiConfiguration?.awsRegion || ""}>
|
||||
<VSCodeOption value="">Select a region...</VSCodeOption>
|
||||
{/* 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. */}
|
||||
@@ -147,11 +222,20 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
<VSCodeCheckbox
|
||||
checked={awsEndpointSelected}
|
||||
disabled={remoteConfigSettings?.awsBedrockEndpoint !== undefined}
|
||||
onChange={(e: any) => {
|
||||
onChange={async (e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
setAwsEndpointSelected(isChecked)
|
||||
if (!isChecked) {
|
||||
handleFieldChange("awsBedrockEndpoint", "")
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
awsBedrockEndpoint: "",
|
||||
},
|
||||
},
|
||||
updateMask: ["options.awsBedrockEndpoint"],
|
||||
}),
|
||||
)
|
||||
}
|
||||
}}>
|
||||
Use custom VPC endpoint
|
||||
@@ -166,7 +250,18 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
className="mt-0.5 mb-1 text-sm text-description"
|
||||
disabled={remoteConfigSettings?.awsBedrockEndpoint !== undefined}
|
||||
initialValue={apiConfiguration?.awsBedrockEndpoint || ""}
|
||||
onChange={(value) => handleFieldChange("awsBedrockEndpoint", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
awsBedrockEndpoint: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.awsBedrockEndpoint"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Enter VPC Endpoint URL (optional)"
|
||||
type="text"
|
||||
/>
|
||||
@@ -183,10 +278,19 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsUseCrossRegionInference || false}
|
||||
disabled={remoteConfigSettings?.awsUseCrossRegionInference !== undefined}
|
||||
onChange={(e: any) => {
|
||||
onChange={async (e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
|
||||
handleFieldChange("awsUseCrossRegionInference", isChecked)
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
awsUseCrossRegionInference: isChecked,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.awsUseCrossRegionInference"],
|
||||
}),
|
||||
)
|
||||
}}>
|
||||
Use cross-region inference
|
||||
</VSCodeCheckbox>
|
||||
@@ -207,9 +311,18 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsUseGlobalInference || false}
|
||||
disabled={remoteConfigSettings?.awsUseGlobalInference !== undefined}
|
||||
onChange={(e: any) => {
|
||||
onChange={async (e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
handleFieldChange("awsUseGlobalInference", isChecked)
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
awsUseGlobalInference: isChecked,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.awsUseGlobalInference"],
|
||||
}),
|
||||
)
|
||||
}}>
|
||||
Use global inference profile
|
||||
</VSCodeCheckbox>
|
||||
@@ -231,9 +344,18 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsBedrockUsePromptCache || false}
|
||||
disabled={remoteConfigSettings?.awsBedrockUsePromptCache !== undefined}
|
||||
onChange={(e: any) => {
|
||||
onChange={async (e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
handleFieldChange("awsBedrockUsePromptCache", isChecked)
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
awsBedrockUsePromptCache: isChecked,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.awsBedrockUsePromptCache"],
|
||||
}),
|
||||
)
|
||||
}}>
|
||||
Use prompt caching
|
||||
</VSCodeCheckbox>
|
||||
@@ -261,27 +383,41 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
<VSCodeDropdown
|
||||
className="w-full"
|
||||
id="bedrock-model-dropdown"
|
||||
onChange={(e: any) => {
|
||||
onChange={async (e: any) => {
|
||||
const isCustom = e.target.value === "custom"
|
||||
|
||||
handleModeFieldsChange(
|
||||
{
|
||||
apiModelId: { plan: "planModeApiModelId", act: "actModeApiModelId" },
|
||||
awsBedrockCustomSelected: {
|
||||
plan: "planModeAwsBedrockCustomSelected",
|
||||
act: "actModeAwsBedrockCustomSelected",
|
||||
},
|
||||
awsBedrockCustomModelBaseId: {
|
||||
plan: "planModeAwsBedrockCustomModelBaseId",
|
||||
act: "actModeAwsBedrockCustomModelBaseId",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiModelId: isCustom ? "" : e.target.value,
|
||||
awsBedrockCustomSelected: isCustom,
|
||||
awsBedrockCustomModelBaseId: bedrockDefaultModelId,
|
||||
},
|
||||
currentMode,
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: {
|
||||
options: {
|
||||
planModeApiModelId: isCustom ? "" : e.target.value,
|
||||
planModeAwsBedrockCustomSelected: isCustom,
|
||||
planModeAwsBedrockCustomModelBaseId: bedrockDefaultModelId,
|
||||
},
|
||||
},
|
||||
updateMask: [
|
||||
"options.planModeApiModelId",
|
||||
"options.planModeAwsBedrockCustomSelected",
|
||||
"options.planModeAwsBedrockCustomModelBaseId",
|
||||
],
|
||||
}
|
||||
: {
|
||||
updates: {
|
||||
options: {
|
||||
actModeApiModelId: isCustom ? "" : e.target.value,
|
||||
actModeAwsBedrockCustomSelected: isCustom,
|
||||
actModeAwsBedrockCustomModelBaseId: bedrockDefaultModelId,
|
||||
},
|
||||
},
|
||||
updateMask: [
|
||||
"options.actModeApiModelId",
|
||||
"options.actModeAwsBedrockCustomSelected",
|
||||
"options.actModeAwsBedrockCustomModelBaseId",
|
||||
],
|
||||
},
|
||||
),
|
||||
)
|
||||
}}
|
||||
value={modeFields.awsBedrockCustomSelected ? "custom" : selectedModelId}>
|
||||
@@ -308,13 +444,21 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
className="w-full mt-0.5"
|
||||
id="bedrock-model-input"
|
||||
initialValue={modeFields.apiModelId || ""}
|
||||
onChange={(value) =>
|
||||
handleModeFieldChange(
|
||||
{ plan: "planModeApiModelId", act: "actModeApiModelId" },
|
||||
value,
|
||||
currentMode,
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: { options: { planModeApiModelId: value } },
|
||||
updateMask: ["options.planModeApiModelId"],
|
||||
}
|
||||
: {
|
||||
updates: { options: { actModeApiModelId: value } },
|
||||
updateMask: ["options.actModeApiModelId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}}
|
||||
placeholder="Enter custom model ID...">
|
||||
<span className="font-medium">Model ID</span>
|
||||
</DebouncedTextField>
|
||||
@@ -325,16 +469,25 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
<VSCodeDropdown
|
||||
className="w-full"
|
||||
id="bedrock-base-model-dropdown"
|
||||
onChange={(e: any) =>
|
||||
handleModeFieldChange(
|
||||
{
|
||||
plan: "planModeAwsBedrockCustomModelBaseId",
|
||||
act: "actModeAwsBedrockCustomModelBaseId",
|
||||
},
|
||||
e.target.value,
|
||||
currentMode,
|
||||
onChange={async (e: any) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: {
|
||||
options: { planModeAwsBedrockCustomModelBaseId: e.target.value },
|
||||
},
|
||||
updateMask: ["options.planModeAwsBedrockCustomModelBaseId"],
|
||||
}
|
||||
: {
|
||||
updates: {
|
||||
options: { actModeAwsBedrockCustomModelBaseId: e.target.value },
|
||||
},
|
||||
updateMask: ["options.actModeAwsBedrockCustomModelBaseId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}}
|
||||
value={modeFields.awsBedrockCustomModelBaseId || bedrockDefaultModelId}>
|
||||
<VSCodeOption value="">Select a model...</VSCodeOption>
|
||||
{Object.keys(bedrockModels).map((modelId) => (
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { claudeCodeModels } from "@shared/api"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { DebouncedTextField } from "../common/DebouncedTextField"
|
||||
import { ModelInfoView } from "../common/ModelInfoView"
|
||||
import { ModelSelector } from "../common/ModelSelector"
|
||||
import ThinkingBudgetSlider from "../ThinkingBudgetSlider"
|
||||
import { normalizeApiConfiguration } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
import { SUPPORTED_ANTHROPIC_THINKING_MODELS } from "./AnthropicProvider"
|
||||
|
||||
/**
|
||||
@@ -23,7 +24,6 @@ interface ClaudeCodeProviderProps {
|
||||
*/
|
||||
export const ClaudeCodeProvider = ({ showModelOptions, isPopup, currentMode }: ClaudeCodeProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange, handleModeFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
// Get the normalized configuration
|
||||
const { selectedModelId, selectedModelInfo } = normalizeApiConfiguration(apiConfiguration, currentMode)
|
||||
@@ -32,7 +32,18 @@ export const ClaudeCodeProvider = ({ showModelOptions, isPopup, currentMode }: C
|
||||
<div>
|
||||
<DebouncedTextField
|
||||
initialValue={apiConfiguration?.claudeCodePath || ""}
|
||||
onChange={(value) => handleFieldChange("claudeCodePath", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
claudeCodePath: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.claudeCodePath"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Default: claude"
|
||||
style={{ width: "100%", marginTop: 3 }}
|
||||
type="text">
|
||||
@@ -53,13 +64,23 @@ export const ClaudeCodeProvider = ({ showModelOptions, isPopup, currentMode }: C
|
||||
<ModelSelector
|
||||
label="Model"
|
||||
models={claudeCodeModels}
|
||||
onChange={(e: any) =>
|
||||
handleModeFieldChange(
|
||||
{ plan: "planModeApiModelId", act: "actModeApiModelId" },
|
||||
e.target.value,
|
||||
currentMode,
|
||||
onChange={async (e: any) => {
|
||||
const value = e.target.value
|
||||
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: { options: { planModeApiModelId: value } },
|
||||
updateMask: ["options.planModeApiModelId"],
|
||||
}
|
||||
: {
|
||||
updates: { options: { actModeApiModelId: value } },
|
||||
updateMask: ["options.actModeApiModelId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}}
|
||||
selectedModelId={selectedModelId}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { VSCodeCheckbox, VSCodeDropdown, VSCodeOption } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useState } from "react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { ClineAccountInfoCard } from "../ClineAccountInfoCard"
|
||||
import { DropdownContainer } from "../common/ModelSelector"
|
||||
import OpenRouterModelPicker, { OPENROUTER_MODEL_PICKER_Z_INDEX } from "../OpenRouterModelPicker"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Props for the ClineProvider component
|
||||
@@ -21,7 +22,6 @@ interface ClineProviderProps {
|
||||
*/
|
||||
export const ClineProvider = ({ showModelOptions, isPopup, currentMode }: ClineProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
const [providerSortingSelected, setProviderSortingSelected] = useState(!!apiConfiguration?.openRouterProviderSorting)
|
||||
|
||||
@@ -37,11 +37,20 @@ export const ClineProvider = ({ showModelOptions, isPopup, currentMode }: ClineP
|
||||
{/* Provider Sorting Options */}
|
||||
<VSCodeCheckbox
|
||||
checked={providerSortingSelected}
|
||||
onChange={(e: any) => {
|
||||
onChange={async (e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
setProviderSortingSelected(isChecked)
|
||||
if (!isChecked) {
|
||||
handleFieldChange("openRouterProviderSorting", "")
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
openRouterProviderSorting: "",
|
||||
},
|
||||
},
|
||||
updateMask: ["options.openRouterProviderSorting"],
|
||||
}),
|
||||
)
|
||||
}
|
||||
}}
|
||||
style={{ marginTop: -10 }}>
|
||||
@@ -52,8 +61,17 @@ export const ClineProvider = ({ showModelOptions, isPopup, currentMode }: ClineP
|
||||
<div style={{ marginBottom: -6 }}>
|
||||
<DropdownContainer className="dropdown-container" zIndex={OPENROUTER_MODEL_PICKER_Z_INDEX + 1}>
|
||||
<VSCodeDropdown
|
||||
onChange={(e: any) => {
|
||||
handleFieldChange("openRouterProviderSorting", e.target.value)
|
||||
onChange={async (e: any) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
openRouterProviderSorting: e.target.value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.openRouterProviderSorting"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
style={{ width: "100%", marginTop: 3 }}
|
||||
value={apiConfiguration?.openRouterProviderSorting}>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { deepSeekModels } from "@shared/api"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { ApiKeyField } from "../common/ApiKeyField"
|
||||
import { ModelInfoView } from "../common/ModelInfoView"
|
||||
import { ModelSelector } from "../common/ModelSelector"
|
||||
import { normalizeApiConfiguration } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Props for the DeepSeekProvider component
|
||||
@@ -21,7 +22,6 @@ interface DeepSeekProviderProps {
|
||||
*/
|
||||
export const DeepSeekProvider = ({ showModelOptions, isPopup, currentMode }: DeepSeekProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange, handleModeFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
// Get the normalized configuration
|
||||
const { selectedModelId, selectedModelInfo } = normalizeApiConfiguration(apiConfiguration, currentMode)
|
||||
@@ -30,7 +30,18 @@ export const DeepSeekProvider = ({ showModelOptions, isPopup, currentMode }: Dee
|
||||
<div>
|
||||
<ApiKeyField
|
||||
initialValue={apiConfiguration?.deepSeekApiKey || ""}
|
||||
onChange={(value) => handleFieldChange("deepSeekApiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
deepSeekApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.deepSeekApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
providerName="DeepSeek"
|
||||
signupUrl="https://www.deepseek.com/"
|
||||
/>
|
||||
@@ -40,13 +51,23 @@ export const DeepSeekProvider = ({ showModelOptions, isPopup, currentMode }: Dee
|
||||
<ModelSelector
|
||||
label="Model"
|
||||
models={deepSeekModels}
|
||||
onChange={(e: any) =>
|
||||
handleModeFieldChange(
|
||||
{ plan: "planModeApiModelId", act: "actModeApiModelId" },
|
||||
e.target.value,
|
||||
currentMode,
|
||||
onChange={async (e: any) => {
|
||||
const value = e.target.value
|
||||
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: { options: { planModeApiModelId: value } },
|
||||
updateMask: ["options.planModeApiModelId"],
|
||||
}
|
||||
: {
|
||||
updates: { options: { actModeApiModelId: value } },
|
||||
updateMask: ["options.actModeApiModelId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}}
|
||||
selectedModelId={selectedModelId}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { ApiKeyField } from "../common/ApiKeyField"
|
||||
import { DebouncedTextField } from "../common/DebouncedTextField"
|
||||
import { ModelInfoView } from "../common/ModelInfoView"
|
||||
import { normalizeApiConfiguration } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
import { useDebouncedInput } from "../utils/useDebouncedInput"
|
||||
|
||||
interface DifyProviderProps {
|
||||
showModelOptions: boolean
|
||||
@@ -15,16 +15,6 @@ interface DifyProviderProps {
|
||||
|
||||
export const DifyProvider = ({ showModelOptions, isPopup, currentMode }: DifyProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
// Use debounced input for proper state management
|
||||
const [baseUrlValue, setBaseUrlValue] = useDebouncedInput(apiConfiguration?.difyBaseUrl || "", (value) =>
|
||||
handleFieldChange("difyBaseUrl", value),
|
||||
)
|
||||
|
||||
const [apiKeyValue, setApiKeyValue] = useDebouncedInput(apiConfiguration?.difyApiKey || "", (value) =>
|
||||
handleFieldChange("difyApiKey", value),
|
||||
)
|
||||
|
||||
// Get the normalized configuration
|
||||
const { selectedModelId, selectedModelInfo } = normalizeApiConfiguration(apiConfiguration, currentMode)
|
||||
@@ -34,8 +24,17 @@ export const DifyProvider = ({ showModelOptions, isPopup, currentMode }: DifyPro
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
|
||||
<DebouncedTextField
|
||||
initialValue={apiConfiguration?.difyBaseUrl || ""}
|
||||
onChange={(value) => {
|
||||
handleFieldChange("difyBaseUrl", value)
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
difyBaseUrl: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.difyBaseUrl"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder={"Enter base URL..."}
|
||||
style={{ width: "100%", marginBottom: 10 }}
|
||||
@@ -45,8 +44,17 @@ export const DifyProvider = ({ showModelOptions, isPopup, currentMode }: DifyPro
|
||||
|
||||
<ApiKeyField
|
||||
initialValue={apiConfiguration?.difyApiKey || ""}
|
||||
onChange={(value) => {
|
||||
handleFieldChange("difyApiKey", value)
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
difyApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.difyApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
providerName="Dify"
|
||||
/>
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { geminiModels } from "@shared/api"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { ApiKeyField } from "../common/ApiKeyField"
|
||||
import { BaseUrlField } from "../common/BaseUrlField"
|
||||
import { ModelInfoView } from "../common/ModelInfoView"
|
||||
import { ModelSelector } from "../common/ModelSelector"
|
||||
import ThinkingBudgetSlider from "../ThinkingBudgetSlider"
|
||||
import { normalizeApiConfiguration } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
// Gemini models that support thinking/reasoning mode
|
||||
const SUPPORTED_THINKING_MODELS = ["gemini-2.5-pro", "gemini-2.5-flash", "gemini-2.5-flash-lite-preview-06-17"]
|
||||
@@ -26,7 +27,6 @@ interface GeminiProviderProps {
|
||||
*/
|
||||
export const GeminiProvider = ({ showModelOptions, isPopup, currentMode }: GeminiProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange, handleModeFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
// Get the normalized configuration
|
||||
const { selectedModelId, selectedModelInfo } = normalizeApiConfiguration(apiConfiguration, currentMode)
|
||||
@@ -35,7 +35,18 @@ export const GeminiProvider = ({ showModelOptions, isPopup, currentMode }: Gemin
|
||||
<div>
|
||||
<ApiKeyField
|
||||
initialValue={apiConfiguration?.geminiApiKey || ""}
|
||||
onChange={(value) => handleFieldChange("geminiApiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
geminiApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.geminiApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
providerName="Gemini"
|
||||
signupUrl="https://aistudio.google.com/apikey"
|
||||
/>
|
||||
@@ -43,7 +54,18 @@ export const GeminiProvider = ({ showModelOptions, isPopup, currentMode }: Gemin
|
||||
<BaseUrlField
|
||||
initialValue={apiConfiguration?.geminiBaseUrl}
|
||||
label="Use custom base URL"
|
||||
onChange={(value) => handleFieldChange("geminiBaseUrl", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
geminiBaseUrl: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.geminiBaseUrl"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Default: https://generativelanguage.googleapis.com"
|
||||
/>
|
||||
|
||||
@@ -52,13 +74,23 @@ export const GeminiProvider = ({ showModelOptions, isPopup, currentMode }: Gemin
|
||||
<ModelSelector
|
||||
label="Model"
|
||||
models={geminiModels}
|
||||
onChange={(e: any) =>
|
||||
handleModeFieldChange(
|
||||
{ plan: "planModeApiModelId", act: "actModeApiModelId" },
|
||||
e.target.value,
|
||||
currentMode,
|
||||
onChange={async (e: any) => {
|
||||
const value = e.target.value
|
||||
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: { options: { planModeApiModelId: value } },
|
||||
updateMask: ["options.planModeApiModelId"],
|
||||
}
|
||||
: {
|
||||
updates: { options: { actModeApiModelId: value } },
|
||||
updateMask: ["options.actModeApiModelId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}}
|
||||
selectedModelId={selectedModelId}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { ApiKeyField } from "../common/ApiKeyField"
|
||||
import GroqModelPicker from "../GroqModelPicker"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Props for the GroqProvider component
|
||||
@@ -18,13 +19,23 @@ interface GroqProviderProps {
|
||||
*/
|
||||
export const GroqProvider = ({ showModelOptions, isPopup, currentMode }: GroqProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ApiKeyField
|
||||
initialValue={apiConfiguration?.groqApiKey || ""}
|
||||
onChange={(value) => handleFieldChange("groqApiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
groqApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.groqApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
providerName="Groq"
|
||||
signupUrl="https://console.groq.com/keys"
|
||||
/>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { DebouncedTextField } from "../common/DebouncedTextField"
|
||||
import { HuggingFaceModelPicker } from "../HuggingFaceModelPicker"
|
||||
import { normalizeApiConfiguration } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Props for the HuggingFaceProvider component
|
||||
@@ -19,7 +20,6 @@ interface HuggingFaceProviderProps {
|
||||
*/
|
||||
export const HuggingFaceProvider = ({ showModelOptions, isPopup, currentMode }: HuggingFaceProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
// Get the normalized configuration
|
||||
const { selectedModelId, selectedModelInfo } = normalizeApiConfiguration(apiConfiguration, currentMode)
|
||||
@@ -28,7 +28,18 @@ export const HuggingFaceProvider = ({ showModelOptions, isPopup, currentMode }:
|
||||
<div>
|
||||
<DebouncedTextField
|
||||
initialValue={apiConfiguration?.huggingFaceApiKey || ""}
|
||||
onChange={(value) => handleFieldChange("huggingFaceApiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
huggingFaceApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.huggingFaceApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Enter API Key..."
|
||||
style={{ width: "100%" }}
|
||||
type="password">
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { mistralModels } from "@shared/api"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { ApiKeyField } from "../common/ApiKeyField"
|
||||
import { ModelInfoView } from "../common/ModelInfoView"
|
||||
import { ModelSelector } from "../common/ModelSelector"
|
||||
import { normalizeApiConfiguration } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Props for the MistralProvider component
|
||||
@@ -21,7 +22,6 @@ interface MistralProviderProps {
|
||||
*/
|
||||
export const MistralProvider = ({ showModelOptions, isPopup, currentMode }: MistralProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange, handleModeFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
// Get the normalized configuration
|
||||
const { selectedModelId, selectedModelInfo } = normalizeApiConfiguration(apiConfiguration, currentMode)
|
||||
@@ -30,7 +30,18 @@ export const MistralProvider = ({ showModelOptions, isPopup, currentMode }: Mist
|
||||
<div>
|
||||
<ApiKeyField
|
||||
initialValue={apiConfiguration?.mistralApiKey || ""}
|
||||
onChange={(value) => handleFieldChange("mistralApiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
mistralApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.mistralApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
providerName="Mistral"
|
||||
signupUrl="https://console.mistral.ai/codestral"
|
||||
/>
|
||||
@@ -40,13 +51,23 @@ export const MistralProvider = ({ showModelOptions, isPopup, currentMode }: Mist
|
||||
<ModelSelector
|
||||
label="Model"
|
||||
models={mistralModels}
|
||||
onChange={(e: any) =>
|
||||
handleModeFieldChange(
|
||||
{ plan: "planModeApiModelId", act: "actModeApiModelId" },
|
||||
e.target.value,
|
||||
currentMode,
|
||||
onChange={async (e: any) => {
|
||||
const value = e.target.value
|
||||
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: { options: { planModeApiModelId: value } },
|
||||
updateMask: ["options.planModeApiModelId"],
|
||||
}
|
||||
: {
|
||||
updates: { options: { actModeApiModelId: value } },
|
||||
updateMask: ["options.actModeApiModelId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}}
|
||||
selectedModelId={selectedModelId}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { StringRequest } from "@shared/proto/cline/common"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useCallback, useEffect, useState } from "react"
|
||||
@@ -11,7 +12,6 @@ import { BaseUrlField } from "../common/BaseUrlField"
|
||||
import { DebouncedTextField } from "../common/DebouncedTextField"
|
||||
import OllamaModelPicker from "../OllamaModelPicker"
|
||||
import { getModeSpecificFields } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Props for the OllamaProvider component
|
||||
@@ -27,7 +27,6 @@ interface OllamaProviderProps {
|
||||
*/
|
||||
export const OllamaProvider = ({ showModelOptions, isPopup, currentMode }: OllamaProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange, handleModeFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
const { ollamaModelId } = getModeSpecificFields(apiConfiguration, currentMode)
|
||||
|
||||
@@ -61,7 +60,18 @@ export const OllamaProvider = ({ showModelOptions, isPopup, currentMode }: Ollam
|
||||
<BaseUrlField
|
||||
initialValue={apiConfiguration?.ollamaBaseUrl}
|
||||
label="Use custom base URL"
|
||||
onChange={(value) => handleFieldChange("ollamaBaseUrl", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
ollamaBaseUrl: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.ollamaBaseUrl"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Default: http://localhost:11434"
|
||||
/>
|
||||
|
||||
@@ -69,7 +79,18 @@ export const OllamaProvider = ({ showModelOptions, isPopup, currentMode }: Ollam
|
||||
<ApiKeyField
|
||||
helpText="Optional API key for authenticated Ollama instances or cloud services. Leave empty for local installations."
|
||||
initialValue={apiConfiguration?.ollamaApiKey || ""}
|
||||
onChange={(value) => handleFieldChange("ollamaApiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
ollamaApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.ollamaApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Enter API Key (optional)..."
|
||||
providerName="Ollama"
|
||||
/>
|
||||
@@ -81,8 +102,20 @@ export const OllamaProvider = ({ showModelOptions, isPopup, currentMode }: Ollam
|
||||
</label>
|
||||
<OllamaModelPicker
|
||||
ollamaModels={ollamaModels}
|
||||
onModelChange={(modelId) => {
|
||||
handleModeFieldChange({ plan: "planModeOllamaModelId", act: "actModeOllamaModelId" }, modelId, currentMode)
|
||||
onModelChange={async (modelId) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: { options: { planModeOllamaModelId: modelId } },
|
||||
updateMask: ["options.planModeOllamaModelId"],
|
||||
}
|
||||
: {
|
||||
updates: { options: { actModeOllamaModelId: modelId } },
|
||||
updateMask: ["options.actModeOllamaModelId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}}
|
||||
placeholder={ollamaModels.length > 0 ? "Search and select a model..." : "e.g. llama3.1"}
|
||||
selectedModelId={ollamaModelId || ""}
|
||||
@@ -98,7 +131,18 @@ export const OllamaProvider = ({ showModelOptions, isPopup, currentMode }: Ollam
|
||||
|
||||
<DebouncedTextField
|
||||
initialValue={apiConfiguration?.ollamaApiOptionsCtxNum || "32768"}
|
||||
onChange={(v) => handleFieldChange("ollamaApiOptionsCtxNum", v || undefined)}
|
||||
onChange={async (v) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
ollamaApiOptionsCtxNum: v || undefined,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.ollamaApiOptionsCtxNum"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder={"e.g. 32768"}
|
||||
style={{ width: "100%" }}>
|
||||
<span className="font-semibold">Model Context Window</span>
|
||||
@@ -108,11 +152,20 @@ export const OllamaProvider = ({ showModelOptions, isPopup, currentMode }: Ollam
|
||||
<>
|
||||
<DebouncedTextField
|
||||
initialValue={apiConfiguration?.requestTimeoutMs ? apiConfiguration.requestTimeoutMs.toString() : "30000"}
|
||||
onChange={(value) => {
|
||||
onChange={async (value) => {
|
||||
// Convert to number, with validation
|
||||
const numValue = parseInt(value, 10)
|
||||
if (!Number.isNaN(numValue) && numValue > 0) {
|
||||
handleFieldChange("requestTimeoutMs", numValue)
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
requestTimeoutMs: numValue,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.requestTimeoutMs"],
|
||||
}),
|
||||
)
|
||||
}
|
||||
}}
|
||||
placeholder="Default: 30000 (30 seconds)"
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { openAiNativeModels } from "@shared/api"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { ApiKeyField } from "../common/ApiKeyField"
|
||||
import { ModelInfoView } from "../common/ModelInfoView"
|
||||
import { ModelSelector } from "../common/ModelSelector"
|
||||
import { normalizeApiConfiguration } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Props for the OpenAINativeProvider component
|
||||
@@ -21,7 +22,6 @@ interface OpenAINativeProviderProps {
|
||||
*/
|
||||
export const OpenAINativeProvider = ({ showModelOptions, isPopup, currentMode }: OpenAINativeProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange, handleModeFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
// Get the normalized configuration
|
||||
const { selectedModelId, selectedModelInfo } = normalizeApiConfiguration(apiConfiguration, currentMode)
|
||||
@@ -30,7 +30,18 @@ export const OpenAINativeProvider = ({ showModelOptions, isPopup, currentMode }:
|
||||
<div>
|
||||
<ApiKeyField
|
||||
initialValue={apiConfiguration?.openAiNativeApiKey || ""}
|
||||
onChange={(value) => handleFieldChange("openAiNativeApiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
openAiNativeApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.openAiNativeApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
providerName="OpenAI"
|
||||
signupUrl="https://platform.openai.com/api-keys"
|
||||
/>
|
||||
@@ -40,13 +51,23 @@ export const OpenAINativeProvider = ({ showModelOptions, isPopup, currentMode }:
|
||||
<ModelSelector
|
||||
label="Model"
|
||||
models={openAiNativeModels}
|
||||
onChange={(e: any) =>
|
||||
handleModeFieldChange(
|
||||
{ plan: "planModeApiModelId", act: "actModeApiModelId" },
|
||||
e.target.value,
|
||||
currentMode,
|
||||
onChange={async (e: any) => {
|
||||
const value = e.target.value
|
||||
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: { options: { planModeApiModelId: value } },
|
||||
updateMask: ["options.planModeApiModelId"],
|
||||
}
|
||||
: {
|
||||
updates: { options: { actModeApiModelId: value } },
|
||||
updateMask: ["options.actModeApiModelId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}}
|
||||
selectedModelId={selectedModelId}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { EmptyRequest } from "@shared/proto/cline/common"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { VSCodeButton, VSCodeCheckbox, VSCodeDropdown, VSCodeLink, VSCodeOption } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useState } from "react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { AccountServiceClient } from "@/services/grpc-client"
|
||||
import { AccountServiceClient, ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { useOpenRouterKeyInfo } from "../../ui/hooks/useOpenRouterKeyInfo"
|
||||
import { DebouncedTextField } from "../common/DebouncedTextField"
|
||||
import { DropdownContainer } from "../common/ModelSelector"
|
||||
import OpenRouterModelPicker, { OPENROUTER_MODEL_PICKER_Z_INDEX } from "../OpenRouterModelPicker"
|
||||
import { formatPrice } from "../utils/pricingUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Component to display OpenRouter balance information
|
||||
@@ -61,7 +61,6 @@ interface OpenRouterProviderProps {
|
||||
*/
|
||||
export const OpenRouterProvider = ({ showModelOptions, isPopup, currentMode }: OpenRouterProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
const [providerSortingSelected, setProviderSortingSelected] = useState(!!apiConfiguration?.openRouterProviderSorting)
|
||||
|
||||
@@ -70,7 +69,18 @@ export const OpenRouterProvider = ({ showModelOptions, isPopup, currentMode }: O
|
||||
<div>
|
||||
<DebouncedTextField
|
||||
initialValue={apiConfiguration?.openRouterApiKey || ""}
|
||||
onChange={(value) => handleFieldChange("openRouterApiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
openRouterApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.openRouterApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Enter API Key..."
|
||||
style={{ width: "100%" }}
|
||||
type="password">
|
||||
@@ -109,11 +119,20 @@ export const OpenRouterProvider = ({ showModelOptions, isPopup, currentMode }: O
|
||||
<>
|
||||
<VSCodeCheckbox
|
||||
checked={providerSortingSelected}
|
||||
onChange={(e: any) => {
|
||||
onChange={async (e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
setProviderSortingSelected(isChecked)
|
||||
if (!isChecked) {
|
||||
handleFieldChange("openRouterProviderSorting", "")
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
openRouterProviderSorting: "",
|
||||
},
|
||||
},
|
||||
updateMask: ["options.openRouterProviderSorting"],
|
||||
}),
|
||||
)
|
||||
}
|
||||
}}
|
||||
style={{ marginTop: -10 }}>
|
||||
@@ -124,8 +143,17 @@ export const OpenRouterProvider = ({ showModelOptions, isPopup, currentMode }: O
|
||||
<div style={{ marginBottom: -6 }}>
|
||||
<DropdownContainer className="dropdown-container" zIndex={OPENROUTER_MODEL_PICKER_Z_INDEX + 1}>
|
||||
<VSCodeDropdown
|
||||
onChange={(e: any) => {
|
||||
handleFieldChange("openRouterProviderSorting", e.target.value)
|
||||
onChange={async (e: any) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
openRouterProviderSorting: e.target.value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.openRouterProviderSorting"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
style={{ width: "100%", marginTop: 3 }}
|
||||
value={apiConfiguration?.openRouterProviderSorting}>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { qwenCodeModels } from "@shared/api"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { ModelInfoView } from "../common/ModelInfoView"
|
||||
import { ModelSelector } from "../common/ModelSelector"
|
||||
import { normalizeApiConfiguration } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Props for the QwenCodeProvider component
|
||||
@@ -21,7 +22,6 @@ interface QwenCodeProviderProps {
|
||||
*/
|
||||
export const QwenCodeProvider = ({ showModelOptions, isPopup, currentMode }: QwenCodeProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
// Get the normalized configuration
|
||||
const { selectedModelId, selectedModelInfo } = normalizeApiConfiguration(apiConfiguration, currentMode)
|
||||
@@ -30,7 +30,18 @@ export const QwenCodeProvider = ({ showModelOptions, isPopup, currentMode }: Qwe
|
||||
<div>
|
||||
<h3 style={{ color: "var(--vscode-foreground)", margin: "8px 0" }}>Qwen Code API Configuration</h3>
|
||||
<VSCodeTextField
|
||||
onInput={(e: any) => handleFieldChange("qwenCodeOauthPath", e.target.value)}
|
||||
onInput={async (e: any) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
qwenCodeOauthPath: e.target.value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.qwenCodeOauthPath"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="~/.qwen/oauth_creds.json"
|
||||
style={{ width: "100%" }}
|
||||
value={apiConfiguration?.qwenCodeOauthPath || ""}>
|
||||
@@ -71,9 +82,20 @@ export const QwenCodeProvider = ({ showModelOptions, isPopup, currentMode }: Qwe
|
||||
<ModelSelector
|
||||
label="Model"
|
||||
models={qwenCodeModels}
|
||||
onChange={(modelId) => {
|
||||
const fieldName = currentMode === "plan" ? "planModeApiModelId" : "actModeApiModelId"
|
||||
handleFieldChange(fieldName, modelId)
|
||||
onChange={async (modelId) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: { options: { planModeApiModelId: modelId } },
|
||||
updateMask: ["options.planModeApiModelId"],
|
||||
}
|
||||
: {
|
||||
updates: { options: { actModeApiModelId: modelId } },
|
||||
updateMask: ["options.actModeApiModelId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}}
|
||||
selectedModelId={selectedModelId}
|
||||
/>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { toRequestyServiceUrl } from "@shared/clients/requesty"
|
||||
import { StringRequest } from "@shared/proto/cline/common"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { VSCodeButton, VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useState } from "react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { AccountServiceClient } from "@/services/grpc-client"
|
||||
import { AccountServiceClient, ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { ApiKeyField } from "../common/ApiKeyField"
|
||||
import { DebouncedTextField } from "../common/DebouncedTextField"
|
||||
import RequestyModelPicker from "../RequestyModelPicker"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Props for the RequestyProvider component
|
||||
@@ -24,7 +24,6 @@ interface RequestyProviderProps {
|
||||
*/
|
||||
export const RequestyProvider = ({ showModelOptions, isPopup, currentMode }: RequestyProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
const [requestyEndpointSelected, setRequestyEndpointSelected] = useState(!!apiConfiguration?.requestyBaseUrl)
|
||||
|
||||
@@ -35,7 +34,18 @@ export const RequestyProvider = ({ showModelOptions, isPopup, currentMode }: Req
|
||||
<div style={{ display: "flex", flexDirection: "column" }}>
|
||||
<ApiKeyField
|
||||
initialValue={apiConfiguration?.requestyApiKey || ""}
|
||||
onChange={(value) => handleFieldChange("requestyApiKey", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
secrets: {
|
||||
requestyApiKey: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["secrets.requestyApiKey"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
providerName="Requesty"
|
||||
signupUrl={apiKeyUrl}
|
||||
/>
|
||||
@@ -59,12 +69,21 @@ export const RequestyProvider = ({ showModelOptions, isPopup, currentMode }: Req
|
||||
)}
|
||||
<VSCodeCheckbox
|
||||
checked={requestyEndpointSelected}
|
||||
onChange={(e: any) => {
|
||||
onChange={async (e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
setRequestyEndpointSelected(isChecked)
|
||||
|
||||
if (!isChecked) {
|
||||
handleFieldChange("requestyBaseUrl", undefined)
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
requestyBaseUrl: undefined,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.requestyBaseUrl"],
|
||||
}),
|
||||
)
|
||||
}
|
||||
}}>
|
||||
Use custom base URL
|
||||
@@ -72,12 +91,17 @@ export const RequestyProvider = ({ showModelOptions, isPopup, currentMode }: Req
|
||||
{requestyEndpointSelected && (
|
||||
<DebouncedTextField
|
||||
initialValue={apiConfiguration?.requestyBaseUrl ?? ""}
|
||||
onChange={(value) => {
|
||||
if (value.length === 0) {
|
||||
handleFieldChange("requestyBaseUrl", undefined)
|
||||
} else {
|
||||
handleFieldChange("requestyBaseUrl", value)
|
||||
}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
requestyBaseUrl: value.length === 0 ? undefined : value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.requestyBaseUrl"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Custom base URL"
|
||||
style={{ width: "100%", marginBottom: 5 }}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { vertexGlobalModels, vertexModels } from "@shared/api"
|
||||
import { UpdateApiConfigurationRequestNew } from "@shared/proto/index.cline"
|
||||
import VertexData from "@shared/providers/vertex.json"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { VSCodeDropdown, VSCodeLink, VSCodeOption } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { DROPDOWN_Z_INDEX, DropdownContainer } from "../ApiOptions"
|
||||
import { DebouncedTextField } from "../common/DebouncedTextField"
|
||||
import { ModelInfoView } from "../common/ModelInfoView"
|
||||
import { ModelSelector } from "../common/ModelSelector"
|
||||
import ThinkingBudgetSlider from "../ThinkingBudgetSlider"
|
||||
import { normalizeApiConfiguration } from "../utils/providerUtils"
|
||||
import { useApiConfigurationHandlers } from "../utils/useApiConfigurationHandlers"
|
||||
|
||||
/**
|
||||
* Props for the VertexProvider component
|
||||
@@ -40,7 +41,6 @@ const REGIONS = VertexData.regions
|
||||
*/
|
||||
export const VertexProvider = ({ showModelOptions, isPopup, currentMode }: VertexProviderProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const { handleFieldChange, handleModeFieldChange } = useApiConfigurationHandlers()
|
||||
|
||||
// Get the normalized configuration
|
||||
const { selectedModelId, selectedModelInfo } = normalizeApiConfiguration(apiConfiguration, currentMode)
|
||||
@@ -57,7 +57,18 @@ export const VertexProvider = ({ showModelOptions, isPopup, currentMode }: Verte
|
||||
}}>
|
||||
<DebouncedTextField
|
||||
initialValue={apiConfiguration?.vertexProjectId || ""}
|
||||
onChange={(value) => handleFieldChange("vertexProjectId", value)}
|
||||
onChange={async (value) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
vertexProjectId: value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.vertexProjectId"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
placeholder="Enter Project ID..."
|
||||
style={{ width: "100%" }}>
|
||||
<span style={{ fontWeight: 500 }}>Google Cloud Project ID</span>
|
||||
@@ -69,7 +80,18 @@ export const VertexProvider = ({ showModelOptions, isPopup, currentMode }: Verte
|
||||
</label>
|
||||
<VSCodeDropdown
|
||||
id="vertex-region-dropdown"
|
||||
onChange={(e: any) => handleFieldChange("vertexRegion", e.target.value)}
|
||||
onChange={async (e: any) => {
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create({
|
||||
updates: {
|
||||
options: {
|
||||
vertexRegion: e.target.value,
|
||||
},
|
||||
},
|
||||
updateMask: ["options.vertexRegion"],
|
||||
}),
|
||||
)
|
||||
}}
|
||||
style={{ width: "100%" }}
|
||||
value={apiConfiguration?.vertexRegion || ""}>
|
||||
<VSCodeOption value="">Select a region...</VSCodeOption>
|
||||
@@ -105,13 +127,23 @@ export const VertexProvider = ({ showModelOptions, isPopup, currentMode }: Verte
|
||||
<ModelSelector
|
||||
label="Model"
|
||||
models={modelsToUse}
|
||||
onChange={(e: any) =>
|
||||
handleModeFieldChange(
|
||||
{ plan: "planModeApiModelId", act: "actModeApiModelId" },
|
||||
e.target.value,
|
||||
currentMode,
|
||||
onChange={async (e: any) => {
|
||||
const value = e.target.value
|
||||
|
||||
await ModelsServiceClient.updateApiConfiguration(
|
||||
UpdateApiConfigurationRequestNew.create(
|
||||
currentMode === "plan"
|
||||
? {
|
||||
updates: { options: { planModeApiModelId: value } },
|
||||
updateMask: ["options.planModeApiModelId"],
|
||||
}
|
||||
: {
|
||||
updates: { options: { actModeApiModelId: value } },
|
||||
updateMask: ["options.actModeApiModelId"],
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}}
|
||||
selectedModelId={selectedModelId}
|
||||
zIndex={DROPDOWN_Z_INDEX - 2}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user