)}
- {selectedProvider === "openrouter" && showModelOptions && }
-
{selectedProvider !== "openrouter" &&
selectedProvider !== "openai" &&
selectedProvider !== "ollama" &&
selectedProvider !== "lmstudio" &&
+ selectedProvider !== "vscode-lm" &&
showModelOptions && (
<>
-
+
@@ -732,17 +829,20 @@ const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage }:
{selectedProvider === "openai-native" && createDropdown(openAiNativeModels)}
{selectedProvider === "deepseek" && createDropdown(deepSeekModels)}
{selectedProvider === "mistral" && createDropdown(mistralModels)}
-
+
>
)}
+ {selectedProvider === "openrouter" && showModelOptions && }
+
{modelIdErrorMessage && (
void
+ isPopup?: boolean
}) => {
const isGemini = Object.keys(geminiModels).includes(selectedModelId)
@@ -790,6 +892,7 @@ export const ModelInfoView = ({
markdown={modelInfo.description}
isExpanded={isDescriptionExpanded}
setIsExpanded={setIsDescriptionExpanded}
+ isPopup={isPopup}
/>
),
)
-export function normalizeApiConfiguration(apiConfiguration?: ApiConfiguration) {
+export function normalizeApiConfiguration(apiConfiguration?: ApiConfiguration): {
+ selectedProvider: ApiProvider
+ selectedModelId: string
+ selectedModelInfo: ModelInfo
+} {
const provider = apiConfiguration?.apiProvider || "anthropic"
const modelId = apiConfiguration?.apiModelId
@@ -954,6 +1061,17 @@ export function normalizeApiConfiguration(apiConfiguration?: ApiConfiguration) {
selectedModelId: apiConfiguration?.lmStudioModelId || "",
selectedModelInfo: openAiModelInfoSaneDefaults,
}
+ case "vscode-lm":
+ return {
+ selectedProvider: provider,
+ selectedModelId: apiConfiguration?.vsCodeLmModelSelector
+ ? `${apiConfiguration.vsCodeLmModelSelector.vendor}/${apiConfiguration.vsCodeLmModelSelector.family}`
+ : "",
+ selectedModelInfo: {
+ ...openAiModelInfoSaneDefaults,
+ supportsImages: false, // VSCode LM API currently doesn't support images
+ },
+ }
default:
return getProviderData(anthropicModels, anthropicDefaultModelId)
}
diff --git a/webview-ui/src/components/settings/OpenRouterModelPicker.tsx b/webview-ui/src/components/settings/OpenRouterModelPicker.tsx
index cdace4472b..37b0bbfad3 100644
--- a/webview-ui/src/components/settings/OpenRouterModelPicker.tsx
+++ b/webview-ui/src/components/settings/OpenRouterModelPicker.tsx
@@ -9,8 +9,13 @@ import { useExtensionState } from "../../context/ExtensionStateContext"
import { vscode } from "../../utils/vscode"
import { highlight } from "../history/HistoryView"
import { ModelInfoView, normalizeApiConfiguration } from "./ApiOptions"
+import { CODE_BLOCK_BG_COLOR } from "../common/CodeBlock"
-const OpenRouterModelPicker: React.FC = () => {
+export interface OpenRouterModelPickerProps {
+ isPopup?: boolean
+}
+
+const OpenRouterModelPicker: React.FC = ({ isPopup }) => {
const { apiConfiguration, setApiConfiguration, openRouterModels } = useExtensionState()
const [searchTerm, setSearchTerm] = useState(apiConfiguration?.openRouterModelId || openRouterDefaultModelId)
const [isDropdownVisible, setIsDropdownVisible] = useState(false)
@@ -24,8 +29,10 @@ const OpenRouterModelPicker: React.FC = () => {
// could be setting invalid model id/undefined info but validation will catch it
setApiConfiguration({
...apiConfiguration,
- openRouterModelId: newModelId,
- openRouterModelInfo: openRouterModels[newModelId],
+ ...{
+ openRouterModelId: newModelId,
+ openRouterModelInfo: openRouterModels[newModelId],
+ },
})
setSearchTerm(newModelId)
}
@@ -129,7 +136,7 @@ const OpenRouterModelPicker: React.FC = () => {
}, [selectedIndex])
return (
- <>
+
-
+
@@ -204,6 +211,7 @@ const OpenRouterModelPicker: React.FC = () => {
modelInfo={selectedModelInfo}
isDescriptionExpanded={isDescriptionExpanded}
setIsDescriptionExpanded={setIsDescriptionExpanded}
+ isPopup={isPopup}
/>
) : (
{
marginTop: 0,
color: "var(--vscode-descriptionForeground)",
}}>
- The extension automatically fetches the latest list of models available on{" "}
-
- OpenRouter.
-
- If you're unsure which model to choose, Cline works best with{" "}
- handleModelChange("anthropic/claude-3.5-sonnet:beta")}>
- anthropic/claude-3.5-sonnet:beta.
-
- You can also try searching "free" for no-cost options currently available.
+ <>
+ The extension automatically fetches the latest list of models available on{" "}
+
+ OpenRouter.
+
+ If you're unsure which model to choose, Cline works best with{" "}
+ handleModelChange("anthropic/claude-3.5-sonnet:beta")}>
+ anthropic/claude-3.5-sonnet:beta.
+
+ You can also try searching "free" for no-cost options currently available.
+ >
)}
- >
+
)
}
@@ -320,11 +330,13 @@ export const ModelDescriptionMarkdown = memo(
key,
isExpanded,
setIsExpanded,
+ isPopup,
}: {
markdown?: string
key: string
isExpanded: boolean
setIsExpanded: (isExpanded: boolean) => void
+ isPopup?: boolean
}) => {
const [reactContent, setMarkdown] = useRemark()
// const [isExpanded, setIsExpanded] = useState(false)
@@ -394,7 +406,7 @@ export const ModelDescriptionMarkdown = memo(
fontSize: "inherit",
paddingRight: 0,
paddingLeft: 3,
- backgroundColor: "var(--vscode-sideBar-background)",
+ backgroundColor: isPopup ? CODE_BLOCK_BG_COLOR : "var(--vscode-sideBar-background)",
}}
onClick={() => setIsExpanded(true)}>
See more
diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx
index c5526fb32c..6c1daf60e0 100644
--- a/webview-ui/src/components/settings/SettingsView.tsx
+++ b/webview-ui/src/components/settings/SettingsView.tsx
@@ -4,6 +4,7 @@ import { useExtensionState } from "../../context/ExtensionStateContext"
import { validateApiConfiguration, validateModelId } from "../../utils/validate"
import { vscode } from "../../utils/vscode"
import ApiOptions from "./ApiOptions"
+import SettingsButton from "../common/SettingsButton"
const IS_DEV = false // FIXME: use flags when packaging
@@ -15,12 +16,14 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
const { apiConfiguration, version, customInstructions, setCustomInstructions, openRouterModels } = useExtensionState()
const [apiErrorMessage, setApiErrorMessage] = useState
(undefined)
const [modelIdErrorMessage, setModelIdErrorMessage] = useState(undefined)
+
const handleSubmit = () => {
const apiValidationResult = validateApiConfiguration(apiConfiguration)
const modelIdValidationResult = validateModelId(apiConfiguration, openRouterModels)
setApiErrorMessage(apiValidationResult)
setModelIdErrorMessage(modelIdValidationResult)
+
if (!apiValidationResult && !modelIdValidationResult) {
vscode.postMessage({ type: "apiConfiguration", apiConfiguration })
vscode.postMessage({
@@ -135,16 +138,14 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
display: "flex",
justifyContent: "center",
}}>
- vscode.postMessage({ type: "openExtensionSettings" })}
style={{
margin: "0 0 16px 0",
- minWidth: "fit-content",
- whiteSpace: "nowrap",
}}>
+
Advanced Settings
-
+
key !== undefined)
: false
setShowWelcome(!hasKey)
diff --git a/webview-ui/src/utils/validate.ts b/webview-ui/src/utils/validate.ts
index 7dce99bebd..beafc65572 100644
--- a/webview-ui/src/utils/validate.ts
+++ b/webview-ui/src/utils/validate.ts
@@ -58,6 +58,11 @@ export function validateApiConfiguration(apiConfiguration?: ApiConfiguration): s
return "You must provide a valid model ID."
}
break
+ case "vscode-lm":
+ if (!apiConfiguration.vsCodeLmModelSelector) {
+ return "You must provide a valid model selector."
+ }
+ break
}
}
return undefined