Skip to content

Commit aad292a

Browse files
committed
refactor: consolidate validation logic into Zod schema
- Remove redundant manual validation checks (lines 375-425) - Simplify validateSettings() to rely solely on Zod schema - Handle SECRET_PLACEHOLDER values as valid (backend secrets exist) - Reduce code by ~80 lines while maintaining same functionality - Single source of truth for validation rules
1 parent 3fae369 commit aad292a

File tree

1 file changed

+13
-79
lines changed

1 file changed

+13
-79
lines changed

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

Lines changed: 13 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -334,93 +334,27 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
334334
const validateSettings = (): boolean => {
335335
const schema = createValidationSchema(currentSettings.codebaseIndexEmbedderProvider, t)
336336

337-
// Prepare data for validation, excluding placeholder values
337+
// Prepare data for validation
338338
const dataToValidate: any = {}
339339
for (const [key, value] of Object.entries(currentSettings)) {
340-
// Skip secret fields that still have placeholder value
340+
// For secret fields with placeholder values, treat them as valid (they exist in backend)
341341
if (value === SECRET_PLACEHOLDER) {
342-
continue
343-
}
344-
dataToValidate[key] = value
345-
}
346-
347-
try {
348-
// Create a partial schema that only validates fields that are present
349-
const partialSchema = schema.partial()
350-
351-
// For required fields that have placeholder values, we need to check if they exist in the backend
352-
const requiredFieldsWithPlaceholder: Record<string, boolean> = {}
353-
354-
// Check which secret fields have placeholder values but should be considered valid
355-
if (currentSettings.codeIndexOpenAiKey === SECRET_PLACEHOLDER) {
356-
requiredFieldsWithPlaceholder.codeIndexOpenAiKey = true
357-
}
358-
if (currentSettings.codebaseIndexOpenAiCompatibleApiKey === SECRET_PLACEHOLDER) {
359-
requiredFieldsWithPlaceholder.codebaseIndexOpenAiCompatibleApiKey = true
360-
}
361-
if (currentSettings.codebaseIndexGeminiApiKey === SECRET_PLACEHOLDER) {
362-
requiredFieldsWithPlaceholder.codebaseIndexGeminiApiKey = true
363-
}
364-
365-
// Validate the data we have
366-
partialSchema.parse(dataToValidate)
367-
368-
// Additional validation for required fields based on provider
369-
const provider = currentSettings.codebaseIndexEmbedderProvider
370-
const errors: Record<string, string> = {}
371-
372-
// Check provider-specific required fields
373-
if (provider === "openai") {
374-
if (!dataToValidate.codeIndexOpenAiKey && !requiredFieldsWithPlaceholder.codeIndexOpenAiKey) {
375-
errors.codeIndexOpenAiKey = t("settings:codeIndex.validation.openaiApiKeyRequired")
376-
}
377-
if (!dataToValidate.codebaseIndexEmbedderModelId) {
378-
errors.codebaseIndexEmbedderModelId = t("settings:codeIndex.validation.modelSelectionRequired")
379-
}
380-
} else if (provider === "ollama") {
381-
if (!dataToValidate.codebaseIndexEmbedderBaseUrl) {
382-
errors.codebaseIndexEmbedderBaseUrl = t("settings:codeIndex.validation.ollamaBaseUrlRequired")
383-
}
384-
if (!dataToValidate.codebaseIndexEmbedderModelId) {
385-
errors.codebaseIndexEmbedderModelId = t("settings:codeIndex.validation.modelIdRequired")
386-
}
387-
} else if (provider === "openai-compatible") {
388-
if (
389-
!dataToValidate.codebaseIndexOpenAiCompatibleApiKey &&
390-
!requiredFieldsWithPlaceholder.codebaseIndexOpenAiCompatibleApiKey
391-
) {
392-
errors.codebaseIndexOpenAiCompatibleApiKey = t("settings:codeIndex.validation.apiKeyRequired")
393-
}
394-
if (!dataToValidate.codebaseIndexEmbedderModelId) {
395-
errors.codebaseIndexEmbedderModelId = t("settings:codeIndex.validation.modelIdRequired")
396-
}
397-
if (!dataToValidate.codebaseIndexEmbedderModelDimension) {
398-
errors.codebaseIndexEmbedderModelDimension = t(
399-
"settings:codeIndex.validation.modelDimensionRequired",
400-
)
401-
}
402-
} else if (provider === "gemini") {
342+
// Add a dummy value that will pass validation for these fields
403343
if (
404-
!dataToValidate.codebaseIndexGeminiApiKey &&
405-
!requiredFieldsWithPlaceholder.codebaseIndexGeminiApiKey
344+
key === "codeIndexOpenAiKey" ||
345+
key === "codebaseIndexOpenAiCompatibleApiKey" ||
346+
key === "codebaseIndexGeminiApiKey"
406347
) {
407-
errors.codebaseIndexGeminiApiKey = t("settings:codeIndex.validation.geminiApiKeyRequired")
408-
}
409-
if (!dataToValidate.codebaseIndexEmbedderModelId) {
410-
errors.codebaseIndexEmbedderModelId = t("settings:codeIndex.validation.modelSelectionRequired")
348+
dataToValidate[key] = "placeholder-valid"
411349
}
350+
} else {
351+
dataToValidate[key] = value
412352
}
353+
}
413354

414-
// Always check base required fields
415-
if (!dataToValidate.codebaseIndexQdrantUrl) {
416-
errors.codebaseIndexQdrantUrl = t("settings:codeIndex.validation.qdrantUrlRequired")
417-
}
418-
419-
if (Object.keys(errors).length > 0) {
420-
setFormErrors(errors)
421-
return false
422-
}
423-
355+
try {
356+
// Validate using the schema
357+
schema.parse(dataToValidate)
424358
setFormErrors({})
425359
return true
426360
} catch (error) {

0 commit comments

Comments
 (0)