Skip to content

Commit 49c884b

Browse files
committed
fix: add Mistral provider support to webview UI
- Add Mistral option to provider dropdown - Add Mistral API key configuration UI - Add Mistral model selection dropdown - Add validation schema for Mistral provider - Handle Mistral API key in secret management
1 parent 8ba9581 commit 49c884b

File tree

1 file changed

+84
-1
lines changed

1 file changed

+84
-1
lines changed

webview-ui/src/components/chat/CodeIndexPopover.tsx

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ interface LocalCodeIndexSettings {
6868
codebaseIndexOpenAiCompatibleBaseUrl?: string
6969
codebaseIndexOpenAiCompatibleApiKey?: string
7070
codebaseIndexGeminiApiKey?: string
71+
codebaseIndexMistralApiKey?: string
7172
}
7273

7374
// Validation schema for codebase index settings
@@ -126,6 +127,14 @@ const createValidationSchema = (provider: EmbedderProvider, t: any) => {
126127
.min(1, t("settings:codeIndex.validation.modelSelectionRequired")),
127128
})
128129

130+
case "mistral":
131+
return baseSchema.extend({
132+
codebaseIndexMistralApiKey: z.string().min(1, t("settings:codeIndex.validation.mistralApiKeyRequired")),
133+
codebaseIndexEmbedderModelId: z
134+
.string()
135+
.min(1, t("settings:codeIndex.validation.modelSelectionRequired")),
136+
})
137+
129138
default:
130139
return baseSchema
131140
}
@@ -169,6 +178,7 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
169178
codebaseIndexOpenAiCompatibleBaseUrl: "",
170179
codebaseIndexOpenAiCompatibleApiKey: "",
171180
codebaseIndexGeminiApiKey: "",
181+
codebaseIndexMistralApiKey: "",
172182
})
173183

174184
// Initial settings state - stores the settings when popover opens
@@ -202,6 +212,7 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
202212
codebaseIndexOpenAiCompatibleBaseUrl: codebaseIndexConfig.codebaseIndexOpenAiCompatibleBaseUrl || "",
203213
codebaseIndexOpenAiCompatibleApiKey: "",
204214
codebaseIndexGeminiApiKey: "",
215+
codebaseIndexMistralApiKey: "",
205216
}
206217
setInitialSettings(settings)
207218
setCurrentSettings(settings)
@@ -293,6 +304,9 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
293304
if (!prev.codebaseIndexGeminiApiKey || prev.codebaseIndexGeminiApiKey === SECRET_PLACEHOLDER) {
294305
updated.codebaseIndexGeminiApiKey = secretStatus.hasGeminiApiKey ? SECRET_PLACEHOLDER : ""
295306
}
307+
if (!prev.codebaseIndexMistralApiKey || prev.codebaseIndexMistralApiKey === SECRET_PLACEHOLDER) {
308+
updated.codebaseIndexMistralApiKey = secretStatus.hasMistralApiKey ? SECRET_PLACEHOLDER : ""
309+
}
296310

297311
return updated
298312
}
@@ -364,7 +378,8 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
364378
if (
365379
key === "codeIndexOpenAiKey" ||
366380
key === "codebaseIndexOpenAiCompatibleApiKey" ||
367-
key === "codebaseIndexGeminiApiKey"
381+
key === "codebaseIndexGeminiApiKey" ||
382+
key === "codebaseIndexMistralApiKey"
368383
) {
369384
dataToValidate[key] = "placeholder-valid"
370385
}
@@ -606,6 +621,9 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
606621
<SelectItem value="gemini">
607622
{t("settings:codeIndex.geminiProvider")}
608623
</SelectItem>
624+
<SelectItem value="mistral">
625+
{t("settings:codeIndex.mistralProvider")}
626+
</SelectItem>
609627
</SelectContent>
610628
</Select>
611629
</div>
@@ -933,6 +951,71 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
933951
</>
934952
)}
935953

954+
{currentSettings.codebaseIndexEmbedderProvider === "mistral" && (
955+
<>
956+
<div className="space-y-2">
957+
<label className="text-sm font-medium">
958+
{t("settings:codeIndex.mistralApiKeyLabel")}
959+
</label>
960+
<VSCodeTextField
961+
type="password"
962+
value={currentSettings.codebaseIndexMistralApiKey || ""}
963+
onInput={(e: any) =>
964+
updateSetting("codebaseIndexMistralApiKey", e.target.value)
965+
}
966+
placeholder={t("settings:codeIndex.mistralApiKeyPlaceholder")}
967+
className={cn("w-full", {
968+
"border-red-500": formErrors.codebaseIndexMistralApiKey,
969+
})}
970+
/>
971+
{formErrors.codebaseIndexMistralApiKey && (
972+
<p className="text-xs text-vscode-errorForeground mt-1 mb-0">
973+
{formErrors.codebaseIndexMistralApiKey}
974+
</p>
975+
)}
976+
</div>
977+
978+
<div className="space-y-2">
979+
<label className="text-sm font-medium">
980+
{t("settings:codeIndex.modelLabel")}
981+
</label>
982+
<VSCodeDropdown
983+
value={currentSettings.codebaseIndexEmbedderModelId}
984+
onChange={(e: any) =>
985+
updateSetting("codebaseIndexEmbedderModelId", e.target.value)
986+
}
987+
className={cn("w-full", {
988+
"border-red-500": formErrors.codebaseIndexEmbedderModelId,
989+
})}>
990+
<VSCodeOption value="" className="p-2">
991+
{t("settings:codeIndex.selectModel")}
992+
</VSCodeOption>
993+
{getAvailableModels().map((modelId) => {
994+
const model =
995+
codebaseIndexModels?.[
996+
currentSettings.codebaseIndexEmbedderProvider
997+
]?.[modelId]
998+
return (
999+
<VSCodeOption key={modelId} value={modelId} className="p-2">
1000+
{modelId}{" "}
1001+
{model
1002+
? t("settings:codeIndex.modelDimensions", {
1003+
dimension: model.dimension,
1004+
})
1005+
: ""}
1006+
</VSCodeOption>
1007+
)
1008+
})}
1009+
</VSCodeDropdown>
1010+
{formErrors.codebaseIndexEmbedderModelId && (
1011+
<p className="text-xs text-vscode-errorForeground mt-1 mb-0">
1012+
{formErrors.codebaseIndexEmbedderModelId}
1013+
</p>
1014+
)}
1015+
</div>
1016+
</>
1017+
)}
1018+
9361019
{/* Qdrant Settings */}
9371020
<div className="space-y-2">
9381021
<label className="text-sm font-medium">

0 commit comments

Comments
 (0)