Преглед изворни кода

Merge pull request #5526 from nubol23/feature/voyage-ai-embedder

feat: add Voyage AI embedder support
Kevin van Dijk пре 6 дана
родитељ
комит
f24ddaf5d6
61 измењених фајлова са 825 додато и 19 уклоњено
  1. 5 0
      .changeset/flat-eels-press.md
  2. 3 0
      packages/types/src/codebase-index.ts
  3. 2 1
      packages/types/src/embedding.ts
  4. 6 1
      packages/types/src/global-settings.ts
  5. 2 0
      packages/types/src/vscode-extension-host.ts
  6. 10 0
      src/core/webview/webviewMessageHandler.ts
  7. 7 0
      src/i18n/locales/ar/embeddings.json
  8. 7 0
      src/i18n/locales/ca/embeddings.json
  9. 7 0
      src/i18n/locales/cs/embeddings.json
  10. 7 0
      src/i18n/locales/de/embeddings.json
  11. 7 0
      src/i18n/locales/en/embeddings.json
  12. 7 0
      src/i18n/locales/es/embeddings.json
  13. 7 0
      src/i18n/locales/fr/embeddings.json
  14. 7 0
      src/i18n/locales/hi/embeddings.json
  15. 7 0
      src/i18n/locales/id/embeddings.json
  16. 7 0
      src/i18n/locales/it/embeddings.json
  17. 7 0
      src/i18n/locales/ja/embeddings.json
  18. 7 0
      src/i18n/locales/ko/embeddings.json
  19. 7 0
      src/i18n/locales/nl/embeddings.json
  20. 7 0
      src/i18n/locales/pl/embeddings.json
  21. 7 0
      src/i18n/locales/pt-BR/embeddings.json
  22. 7 0
      src/i18n/locales/ru/embeddings.json
  23. 7 0
      src/i18n/locales/sk/embeddings.json
  24. 7 0
      src/i18n/locales/th/embeddings.json
  25. 7 0
      src/i18n/locales/tr/embeddings.json
  26. 7 0
      src/i18n/locales/uk/embeddings.json
  27. 7 0
      src/i18n/locales/vi/embeddings.json
  28. 7 0
      src/i18n/locales/zh-CN/embeddings.json
  29. 7 0
      src/i18n/locales/zh-TW/embeddings.json
  30. 94 0
      src/services/code-index/__tests__/service-factory.spec.ts
  31. 25 0
      src/services/code-index/config-manager.ts
  32. 288 0
      src/services/code-index/embedders/voyage.ts
  33. 2 0
      src/services/code-index/interfaces/config.ts
  34. 1 0
      src/services/code-index/interfaces/embedder.ts
  35. 1 0
      src/services/code-index/interfaces/manager.ts
  36. 8 0
      src/services/code-index/service-factory.ts
  37. 16 0
      src/shared/embeddingModels.ts
  38. 93 1
      webview-ui/src/components/chat/CodeIndexPopover.tsx
  39. 4 0
      webview-ui/src/i18n/locales/ar/settings.json
  40. 5 1
      webview-ui/src/i18n/locales/ca/settings.json
  41. 4 0
      webview-ui/src/i18n/locales/cs/settings.json
  42. 5 1
      webview-ui/src/i18n/locales/de/settings.json
  43. 4 0
      webview-ui/src/i18n/locales/en/settings.json
  44. 5 1
      webview-ui/src/i18n/locales/es/settings.json
  45. 5 1
      webview-ui/src/i18n/locales/fr/settings.json
  46. 5 1
      webview-ui/src/i18n/locales/hi/settings.json
  47. 5 1
      webview-ui/src/i18n/locales/id/settings.json
  48. 5 1
      webview-ui/src/i18n/locales/it/settings.json
  49. 5 1
      webview-ui/src/i18n/locales/ja/settings.json
  50. 5 1
      webview-ui/src/i18n/locales/ko/settings.json
  51. 5 1
      webview-ui/src/i18n/locales/nl/settings.json
  52. 5 1
      webview-ui/src/i18n/locales/pl/settings.json
  53. 5 1
      webview-ui/src/i18n/locales/pt-BR/settings.json
  54. 5 1
      webview-ui/src/i18n/locales/ru/settings.json
  55. 4 0
      webview-ui/src/i18n/locales/sk/settings.json
  56. 4 0
      webview-ui/src/i18n/locales/th/settings.json
  57. 5 1
      webview-ui/src/i18n/locales/tr/settings.json
  58. 4 0
      webview-ui/src/i18n/locales/uk/settings.json
  59. 5 1
      webview-ui/src/i18n/locales/vi/settings.json
  60. 5 1
      webview-ui/src/i18n/locales/zh-CN/settings.json
  61. 4 0
      webview-ui/src/i18n/locales/zh-TW/settings.json

+ 5 - 0
.changeset/flat-eels-press.md

@@ -0,0 +1,5 @@
+---
+"kilo-code": minor
+---
+
+Added Voyage AI embedder support

+ 3 - 0
packages/types/src/codebase-index.ts

@@ -41,6 +41,7 @@ export const codebaseIndexConfigSchema = z.object({
 			"vercel-ai-gateway",
 			"bedrock",
 			"openrouter",
+			"voyage", // kilocode_change
 		])
 		.optional(),
 	// kilocode_change start
@@ -93,6 +94,7 @@ export const codebaseIndexModelsSchema = z.object({
 	"vercel-ai-gateway": z.record(z.string(), z.object({ dimension: z.number() })).optional(),
 	openrouter: z.record(z.string(), z.object({ dimension: z.number() })).optional(),
 	bedrock: z.record(z.string(), z.object({ dimension: z.number() })).optional(),
+	voyage: z.record(z.string(), z.object({ dimension: z.number() })).optional(), // kilocode_change
 })
 
 export type CodebaseIndexModels = z.infer<typeof codebaseIndexModelsSchema>
@@ -111,6 +113,7 @@ export const codebaseIndexProviderSchema = z.object({
 	codebaseIndexMistralApiKey: z.string().optional(),
 	codebaseIndexVercelAiGatewayApiKey: z.string().optional(),
 	codebaseIndexOpenRouterApiKey: z.string().optional(),
+	codebaseIndexVoyageApiKey: z.string().optional(), // kilocode_change
 })
 
 export type CodebaseIndexProvider = z.infer<typeof codebaseIndexProviderSchema>

+ 2 - 1
packages/types/src/embedding.ts

@@ -6,7 +6,8 @@ export type EmbedderProvider =
 	| "mistral"
 	| "vercel-ai-gateway"
 	| "bedrock"
-	| "openrouter" // Add other providers as needed.
+	| "openrouter"
+	| "voyage" // kilocode_change // Add other providers as needed.
 
 export interface EmbeddingModelProfile {
 	dimension: number

+ 6 - 1
packages/types/src/global-settings.ts

@@ -14,7 +14,11 @@ import { telemetrySettingsSchema } from "./telemetry.js"
 import { modeConfigSchema } from "./mode.js"
 import { customModePromptsSchema, customSupportPromptsSchema } from "./mode.js"
 import { languagesSchema } from "./vscode.js"
-import { fastApplyModelSchema, autocompleteServiceSettingsSchema, fastApplyApiProviderSchema } from "./kilocode/kilocode.js"
+import {
+	fastApplyModelSchema,
+	autocompleteServiceSettingsSchema,
+	fastApplyApiProviderSchema,
+} from "./kilocode/kilocode.js"
 
 /**
  * Default delay in milliseconds after writes to allow diagnostics to detect potential problems.
@@ -310,6 +314,7 @@ export const SECRET_STATE_KEYS = [
 	"vercelAiGatewayApiKey",
 	"sapAiCoreServiceKey", // kilocode_change
 	"basetenApiKey",
+	"codebaseIndexVoyageApiKey", // kilocode_change
 	"corethinkApiKey",
 ] as const
 

+ 2 - 0
packages/types/src/vscode-extension-host.ts

@@ -1059,6 +1059,7 @@ export interface WebviewMessage {
 			| "vercel-ai-gateway"
 			| "bedrock"
 			| "openrouter"
+			| "voyage" // kilocode_change
 		codebaseIndexVectorStoreProvider?: "lancedb" | "qdrant" // kilocode_change
 		codebaseIndexLancedbVectorStoreDirectory?: string // kilocode_change
 		codebaseIndexEmbedderBaseUrl?: string
@@ -1083,6 +1084,7 @@ export interface WebviewMessage {
 		codebaseIndexMistralApiKey?: string
 		codebaseIndexVercelAiGatewayApiKey?: string
 		codebaseIndexOpenRouterApiKey?: string
+		codebaseIndexVoyageApiKey?: string // kilocode_change
 	}
 	updatedSettings?: RooCodeSettings
 	// kilocode_change start: Review mode

+ 10 - 0
src/core/webview/webviewMessageHandler.ts

@@ -3410,6 +3410,14 @@ export const webviewMessageHandler = async (
 						settings.codebaseIndexOpenRouterApiKey,
 					)
 				}
+				// kilocode_change start
+				if (settings.codebaseIndexVoyageApiKey !== undefined) {
+					await provider.contextProxy.storeSecret(
+						"codebaseIndexVoyageApiKey",
+						settings.codebaseIndexVoyageApiKey,
+					)
+				}
+				// kilocode_change end
 
 				// Send success response first - settings are saved regardless of validation
 				await provider.postMessageToWebview({
@@ -3548,6 +3556,7 @@ export const webviewMessageHandler = async (
 				"codebaseIndexVercelAiGatewayApiKey",
 			))
 			const hasOpenRouterApiKey = !!(await provider.context.secrets.get("codebaseIndexOpenRouterApiKey"))
+			const hasVoyageApiKey = !!(await provider.context.secrets.get("codebaseIndexVoyageApiKey")) // kilocode_change
 
 			provider.postMessageToWebview({
 				type: "codeIndexSecretStatus",
@@ -3559,6 +3568,7 @@ export const webviewMessageHandler = async (
 					hasMistralApiKey,
 					hasVercelAiGatewayApiKey,
 					hasOpenRouterApiKey,
+					hasVoyageApiKey, // kilocode_change
 				},
 			})
 			break

+ 7 - 0
src/i18n/locales/ar/embeddings.json

@@ -24,6 +24,12 @@
 		"modelNotFound": "النموذج {{model}} غير موجود في Amazon Bedrock",
 		"missingConfiguration": "إعدادات Amazon Bedrock مفقودة لإنشاء التضمين"
 	},
+	"voyage": {
+		"invalidResponseFormat": "تنسيق استجابة غير صالح من Voyage AI",
+		"invalidCredentials": "مفتاح API الخاص بـ Voyage AI غير صالح. تحقق من إعدادات مفتاح الـ API.",
+		"accessDenied": "تم رفض الوصول. عنوان الـ IP الخاص بك قد يكون محظوراً من Voyage AI. جرّب شبكة مختلفة.",
+		"modelNotFound": "النموذج {{model}} غير موجود في Voyage AI. تحقق من اختيارك للنموذج."
+	},
 	"scanner": {
 		"unknownErrorProcessingFile": "خطأ غير معروف أثناء معالجة الملف {{filePath}}",
 		"unknownErrorDeletingPoints": "خطأ غير معروف أثناء حذف النقاط للملف {{filePath}}",
@@ -59,6 +65,7 @@
 		"openRouterConfigMissing": "إعدادات OpenRouter مفقودة لإنشاء التضمين",
 		"vercelAiGatewayConfigMissing": "إعدادات Vercel AI Gateway مفقودة لإنشاء التضمين",
 		"bedrockConfigMissing": "إعدادات Amazon Bedrock مفقودة لإنشاء التضمين",
+		"voyageConfigMissing": "إعدادات Voyage AI مفقودة لإنشاء التضمين",
 		"invalidEmbedderType": "نوع التضمين المُعدّ غير صالح: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "لا يمكن تحديد أبعاد المتجه للنموذج '{{modelId}}' مع المزوّد '{{provider}}'. يرجى التأكد من ضبط 'أبعاد التضمين' بشكل صحيح في إعدادات مزوّد OpenAI المتوافق.",
 		"vectorDimensionNotDetermined": "لا يمكن تحديد أبعاد المتجه للنموذج '{{modelId}}' مع المزوّد '{{provider}}'. تحقق من ملفات النموذج أو الإعدادات.",

+ 7 - 0
src/i18n/locales/ca/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Accés denegat al servei d'Amazon Bedrock. Si us plau, comprova els teus permisos d'IAM.",
 		"modelNotFound": "Model {{model}} no trobat a Amazon Bedrock"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Format de resposta no vàlid de Voyage AI",
+		"invalidCredentials": "Clau d'API de Voyage AI no vàlida. Si us plau, comprova la teva configuració de clau d'API.",
+		"accessDenied": "Accés denegat. La teva adreça IP pot estar bloquejada per Voyage AI. Prova amb una xarxa diferent.",
+		"modelNotFound": "Model {{model}} no trobat a Voyage AI. Si us plau, comprova la teva selecció de model."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "No s'ha pogut llegir el cos de l'error",
 		"requestFailed": "La sol·licitud de l'API d'Ollama ha fallat amb l'estat {{status}} {{statusText}}: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "Falta la configuració d'OpenRouter per crear l'embedder",
 		"vercelAiGatewayConfigMissing": "Falta la configuració de Vercel AI Gateway per crear l'embedder",
 		"bedrockConfigMissing": "Falta la configuració d'Amazon Bedrock per crear l'embedder",
+		"voyageConfigMissing": "Falta la configuració de Voyage AI per crear l'embedder",
 		"invalidEmbedderType": "Tipus d'embedder configurat no vàlid: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "No s'ha pogut determinar la dimensió del vector per al model '{{modelId}}' amb el proveïdor '{{provider}}'. Assegura't que la 'Dimensió d'incrustació' estigui configurada correctament als paràmetres del proveïdor compatible amb OpenAI.",
 		"vectorDimensionNotDetermined": "No s'ha pogut determinar la dimensió del vector per al model '{{modelId}}' amb el proveïdor '{{provider}}'. Comprova els perfils del model o la configuració.",

+ 7 - 0
src/i18n/locales/cs/embeddings.json

@@ -24,6 +24,12 @@
 		"modelNotFound": "Model {{model}} nebyl nalezen v Amazon Bedrock",
 		"missingConfiguration": "Chybí konfigurace Amazon Bedrock pro vytvoření embedderu"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Neplatný formát odpovědi z Voyage AI",
+		"invalidCredentials": "Neplatný API klíč Voyage AI. Zkontroluj prosím konfiguraci API klíče.",
+		"accessDenied": "Přístup odepřen. Tvá IP adresa může být blokována Voyage AI. Zkus jinou síť.",
+		"modelNotFound": "Model {{model}} nebyl nalezen ve Voyage AI. Zkontroluj prosím výběr modelu."
+	},
 	"scanner": {
 		"unknownErrorProcessingFile": "Neznámá chyba při zpracování souboru {{filePath}}",
 		"unknownErrorDeletingPoints": "Neznámá chyba při mazání bodů pro {{filePath}}",
@@ -59,6 +65,7 @@
 		"openRouterConfigMissing": "Chybí konfigurace OpenRouter pro vytvoření embedderu",
 		"vercelAiGatewayConfigMissing": "Chybí konfigurace Vercel AI Gateway pro vytvoření embedderu",
 		"bedrockConfigMissing": "Chybí konfigurace Amazon Bedrock pro vytvoření embedderu",
+		"voyageConfigMissing": "Chybí konfigurace Voyage AI pro vytvoření embedderu",
 		"invalidEmbedderType": "Nakonfigurován neplatný typ embedderu: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Nelze určit rozměr vektoru pro model '{{modelId}}' s poskytovatelem '{{provider}}'. Ujisti se prosím, že 'Rozměr Embeddingu' je správně nastaven v nastavení OpenAI-Compatible poskytovatele.",
 		"vectorDimensionNotDetermined": "Nelze určit rozměr vektoru pro model '{{modelId}}' s poskytovatelem '{{provider}}'. Zkontroluj profily modelů nebo konfiguraci.",

+ 7 - 0
src/i18n/locales/de/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Zugriff auf den Amazon Bedrock-Dienst verweigert. Bitte überprüfe deine IAM-Berechtigungen.",
 		"modelNotFound": "Modell {{model}} in Amazon Bedrock nicht gefunden"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Ungültiges Antwortformat von Voyage AI",
+		"invalidCredentials": "Ungültiger Voyage AI API-Schlüssel. Bitte überprüfe deine API-Schlüssel-Konfiguration.",
+		"accessDenied": "Zugriff verweigert. Deine IP-Adresse wird möglicherweise von Voyage AI blockiert. Versuche ein anderes Netzwerk.",
+		"modelNotFound": "Modell {{model}} in Voyage AI nicht gefunden. Bitte überprüfe deine Modellauswahl."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "Fehlerinhalt konnte nicht gelesen werden",
 		"requestFailed": "Ollama API-Anfrage fehlgeschlagen mit Status {{status}} {{statusText}}: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "OpenRouter-Konfiguration fehlt für die Erstellung des Embedders",
 		"vercelAiGatewayConfigMissing": "Vercel AI Gateway-Konfiguration fehlt für die Erstellung des Embedders",
 		"bedrockConfigMissing": "Amazon Bedrock-Konfiguration fehlt für die Erstellung des Embedders",
+		"voyageConfigMissing": "Voyage AI-Konfiguration fehlt für die Erstellung des Embedders",
 		"invalidEmbedderType": "Ungültiger Embedder-Typ konfiguriert: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Konnte die Vektordimension für Modell '{{modelId}}' mit Anbieter '{{provider}}' nicht bestimmen. Stelle sicher, dass die 'Embedding-Dimension' in den OpenAI-kompatiblen Anbietereinstellungen korrekt eingestellt ist.",
 		"vectorDimensionNotDetermined": "Konnte die Vektordimension für Modell '{{modelId}}' mit Anbieter '{{provider}}' nicht bestimmen. Überprüfe die Modellprofile oder Konfiguration.",

+ 7 - 0
src/i18n/locales/en/embeddings.json

@@ -23,6 +23,12 @@
 		"accessDenied": "Access denied to Amazon Bedrock service. Please check your IAM permissions.",
 		"modelNotFound": "Model {{model}} not found in Amazon Bedrock"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Invalid response format from Voyage AI",
+		"invalidCredentials": "Invalid Voyage AI API key. Please check your API key configuration.",
+		"accessDenied": "Access denied. Your IP address may be blocked by Voyage AI. Try a different network.",
+		"modelNotFound": "Model {{model}} not found in Voyage AI. Please check your model selection."
+	},
 	"scanner": {
 		"unknownErrorProcessingFile": "Unknown error processing file {{filePath}}",
 		"unknownErrorDeletingPoints": "Unknown error deleting points for {{filePath}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "OpenRouter configuration missing for embedder creation",
 		"vercelAiGatewayConfigMissing": "Vercel AI Gateway configuration missing for embedder creation",
 		"bedrockConfigMissing": "Amazon Bedrock configuration missing for embedder creation",
+		"voyageConfigMissing": "Voyage AI configuration missing for embedder creation",
 		"invalidEmbedderType": "Invalid embedder type configured: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Could not determine vector dimension for model '{{modelId}}' with provider '{{provider}}'. Please ensure the 'Embedding Dimension' is correctly set in the OpenAI-Compatible provider settings.",
 		"vectorDimensionNotDetermined": "Could not determine vector dimension for model '{{modelId}}' with provider '{{provider}}'. Check model profiles or configuration.",

+ 7 - 0
src/i18n/locales/es/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Acceso denegado al servicio de Amazon Bedrock. Por favor, verifica tus permisos de IAM.",
 		"modelNotFound": "Modelo {{model}} no encontrado en Amazon Bedrock"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Formato de respuesta no válido de Voyage AI",
+		"invalidCredentials": "Clave de API de Voyage AI no válida. Comprueba la configuración de tu clave de API.",
+		"accessDenied": "Acceso denegado. Tu dirección IP puede estar bloqueada por Voyage AI. Prueba con una red diferente.",
+		"modelNotFound": "Modelo {{model}} no encontrado en Voyage AI. Comprueba tu selección de modelo."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "No se pudo leer el cuerpo del error",
 		"requestFailed": "La solicitud de la API de Ollama falló con estado {{status}} {{statusText}}: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "Falta la configuración de OpenRouter para la creación del incrustador",
 		"vercelAiGatewayConfigMissing": "Falta la configuración de Vercel AI Gateway para la creación del incrustador",
 		"bedrockConfigMissing": "Falta la configuración de Amazon Bedrock para la creación del incrustador",
+		"voyageConfigMissing": "Falta la configuración de Voyage AI para la creación del incrustador",
 		"invalidEmbedderType": "Tipo de incrustador configurado inválido: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "No se pudo determinar la dimensión del vector para el modelo '{{modelId}}' con el proveedor '{{provider}}'. Asegúrate de que la 'Dimensión de incrustación' esté configurada correctamente en los ajustes del proveedor compatible con OpenAI.",
 		"vectorDimensionNotDetermined": "No se pudo determinar la dimensión del vector para el modelo '{{modelId}}' con el proveedor '{{provider}}'. Verifica los perfiles del modelo o la configuración.",

+ 7 - 0
src/i18n/locales/fr/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Accès refusé au service Amazon Bedrock. Veuillez vérifier vos permissions IAM.",
 		"modelNotFound": "Modèle {{model}} introuvable dans Amazon Bedrock"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Format de réponse invalide de Voyage AI",
+		"invalidCredentials": "Clé API Voyage AI invalide. Vérifie ta configuration de clé API.",
+		"accessDenied": "Accès refusé. Ton adresse IP est peut-être bloquée par Voyage AI. Essaie un autre réseau.",
+		"modelNotFound": "Modèle {{model}} introuvable dans Voyage AI. Vérifie ta sélection de modèle."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "Impossible de lire le corps de l'erreur",
 		"requestFailed": "Échec de la requête API Ollama avec le statut {{status}} {{statusText}} : {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "Configuration OpenRouter manquante pour la création de l'embedder",
 		"vercelAiGatewayConfigMissing": "Configuration Vercel AI Gateway manquante pour la création de l'embedder",
 		"bedrockConfigMissing": "Configuration Amazon Bedrock manquante pour la création de l'embedder",
+		"voyageConfigMissing": "Configuration Voyage AI manquante pour la création de l'embedder",
 		"invalidEmbedderType": "Type d'embedder configuré invalide : {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Impossible de déterminer la dimension du vecteur pour le modèle '{{modelId}}' avec le fournisseur '{{provider}}'. Assure-toi que la 'Dimension d'embedding' est correctement définie dans les paramètres du fournisseur compatible OpenAI.",
 		"vectorDimensionNotDetermined": "Impossible de déterminer la dimension du vecteur pour le modèle '{{modelId}}' avec le fournisseur '{{provider}}'. Vérifie les profils du modèle ou la configuration.",

+ 7 - 0
src/i18n/locales/hi/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Amazon Bedrock सेवा तक पहुंच अस्वीकृत। कृपया अपनी IAM अनुमतियां जांचें।",
 		"modelNotFound": "मॉडल {{model}} Amazon Bedrock में नहीं मिला"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Voyage AI से अमान्य प्रतिसाद प्रारूप",
+		"invalidCredentials": "अमान्य Voyage AI API कुंजी। कृपया अपनी API कुंजी कॉन्फ़िगरेशन जांचें।",
+		"accessDenied": "पहुंच अस्वीकृत। तुम्हारा IP पता Voyage AI द्वारा ब्लॉक किया जा सकता है। एक अलग नेटवर्क आज़माओ।",
+		"modelNotFound": "मॉडल {{model}} Voyage AI में नहीं मिला। कृपया अपना मॉडल चयन जांचें।"
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "त्रुटि सामग्री पढ़ नहीं सका",
 		"requestFailed": "Ollama API अनुरोध स्थिति {{status}} {{statusText}} के साथ विफल: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "एम्बेडर निर्माण के लिए OpenRouter कॉन्फ़िगरेशन गायब है",
 		"vercelAiGatewayConfigMissing": "एम्बेडर निर्माण के लिए Vercel AI Gateway कॉन्फ़िगरेशन गायब है",
 		"bedrockConfigMissing": "एम्बेडर निर्माण के लिए Amazon Bedrock कॉन्फ़िगरेशन गायब है",
+		"voyageConfigMissing": "एम्बेडर निर्माण के लिए Voyage AI कॉन्फ़िगरेशन गायब है",
 		"invalidEmbedderType": "अमान्य एम्बेडर प्रकार कॉन्फ़िगर किया गया: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "प्रदाता '{{provider}}' के साथ मॉडल '{{modelId}}' के लिए वेक्टर आयाम निर्धारित नहीं कर सका। कृपया सुनिश्चित करें कि OpenAI-संगत प्रदाता सेटिंग्स में 'एम्बेडिंग आयाम' सही तरीके से सेट है।",
 		"vectorDimensionNotDetermined": "प्रदाता '{{provider}}' के साथ मॉडल '{{modelId}}' के लिए वेक्टर आयाम निर्धारित नहीं कर सका। मॉडल प्रोफ़ाइल या कॉन्फ़िगरेशन की जांच करें।",

+ 7 - 0
src/i18n/locales/id/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Akses ditolak ke layanan Amazon Bedrock. Harap periksa izin IAM Anda.",
 		"modelNotFound": "Model {{model}} tidak ditemukan di Amazon Bedrock"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Format respons tidak valid dari Voyage AI",
+		"invalidCredentials": "API key Voyage AI tidak valid. Silakan periksa konfigurasi API key kamu.",
+		"accessDenied": "Akses ditolak. Alamat IP kamu mungkin diblokir oleh Voyage AI. Coba gunakan jaringan lain.",
+		"modelNotFound": "Model {{model}} tidak ditemukan di Voyage AI. Silakan periksa pilihan model kamu."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "Tidak dapat membaca body error",
 		"requestFailed": "Permintaan API Ollama gagal dengan status {{status}} {{statusText}}: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "Konfigurasi OpenRouter hilang untuk pembuatan embedder",
 		"vercelAiGatewayConfigMissing": "Konfigurasi Vercel AI Gateway hilang untuk pembuatan embedder",
 		"bedrockConfigMissing": "Konfigurasi Amazon Bedrock hilang untuk pembuatan embedder",
+		"voyageConfigMissing": "Konfigurasi Voyage AI hilang untuk pembuatan embedder",
 		"invalidEmbedderType": "Tipe embedder yang dikonfigurasi tidak valid: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Tidak dapat menentukan dimensi vektor untuk model '{{modelId}}' dengan penyedia '{{provider}}'. Pastikan 'Dimensi Embedding' diatur dengan benar di pengaturan penyedia yang kompatibel dengan OpenAI.",
 		"vectorDimensionNotDetermined": "Tidak dapat menentukan dimensi vektor untuk model '{{modelId}}' dengan penyedia '{{provider}}'. Periksa profil model atau konfigurasi.",

+ 7 - 0
src/i18n/locales/it/embeddings.json

@@ -23,6 +23,12 @@
 		"modelNotEmbeddingCapable": "Il modello Ollama non è in grado di eseguire l'embedding: {{modelId}}",
 		"hostNotFound": "Host Ollama non trovato: {{baseUrl}}"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Formato di risposta non valido da Voyage AI",
+		"invalidCredentials": "Chiave API Voyage AI non valida. Controlla la configurazione della tua chiave API.",
+		"accessDenied": "Accesso negato. Il tuo indirizzo IP potrebbe essere bloccato da Voyage AI. Prova con una rete diversa.",
+		"modelNotFound": "Modello {{model}} non trovato in Voyage AI. Controlla la selezione del modello."
+	},
 	"scanner": {
 		"unknownErrorProcessingFile": "Errore sconosciuto nell'elaborazione del file {{filePath}}",
 		"unknownErrorDeletingPoints": "Errore sconosciuto nell'eliminazione dei punti per {{filePath}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "Configurazione di OpenRouter mancante per la creazione dell'embedder",
 		"vercelAiGatewayConfigMissing": "Configurazione di Vercel AI Gateway mancante per la creazione dell'embedder",
 		"bedrockConfigMissing": "Configurazione di Amazon Bedrock mancante per la creazione dell'embedder",
+		"voyageConfigMissing": "Configurazione di Voyage AI mancante per la creazione dell'embedder",
 		"invalidEmbedderType": "Tipo di embedder configurato non valido: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Impossibile determinare la dimensione del vettore per il modello '{{modelId}}' con il provider '{{provider}}'. Assicurati che la 'Dimensione di embedding' sia impostata correttamente nelle impostazioni del provider compatibile con OpenAI.",
 		"vectorDimensionNotDetermined": "Impossibile determinare la dimensione del vettore per il modello '{{modelId}}' con il provider '{{provider}}'. Controlla i profili del modello o la configurazione.",

+ 7 - 0
src/i18n/locales/ja/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Amazon Bedrockサービスへのアクセスが拒否されました。IAMの権限を確認してください。",
 		"modelNotFound": "モデル{{model}}がAmazon Bedrockに見つかりません"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Voyage AIからの無効な応答形式",
+		"invalidCredentials": "無効なVoyage AI APIキーだ。APIキーの設定を確認してください。",
+		"accessDenied": "アクセスが拒否された。IPアドレスがVoyage AIによってブロックされている可能性がある。別のネットワークを試してください。",
+		"modelNotFound": "モデル{{model}}がVoyage AIに見つからない。モデルの選択を確認してください。"
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "エラー本文を読み取れませんでした",
 		"requestFailed": "Ollama APIリクエストが失敗しました。ステータス {{status}} {{statusText}}: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "エンベッダー作成のためのOpenRouter設定がありません",
 		"vercelAiGatewayConfigMissing": "エンベッダー作成のためのVercel AI Gateway設定がありません",
 		"bedrockConfigMissing": "エンベッダー作成のためのAmazon Bedrock設定がありません",
+		"voyageConfigMissing": "エンベッダー作成のためのVoyage AI設定がありません",
 		"invalidEmbedderType": "無効なエンベッダータイプが設定されています: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "プロバイダー '{{provider}}' のモデル '{{modelId}}' の埋め込み次元を決定できませんでした。OpenAI互換プロバイダー設定で「埋め込み次元」が正しく設定されていることを確認してください。",
 		"vectorDimensionNotDetermined": "プロバイダー '{{provider}}' のモデル '{{modelId}}' の埋め込み次元を決定できませんでした。モデルプロファイルまたは設定を確認してください。",

+ 7 - 0
src/i18n/locales/ko/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Amazon Bedrock 서비스에 대한 액세스가 거부되었습니다. IAM 권한을 확인하세요.",
 		"modelNotFound": "Amazon Bedrock에서 모델 {{model}}을(를) 찾을 수 없습니다"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Voyage AI에서 잘못된 응답 형식",
+		"invalidCredentials": "잘못된 Voyage AI API 키예요. API 키 구성을 확인하세요.",
+		"accessDenied": "액세스가 거부되었어요. IP 주소가 Voyage AI에 의해 차단되었을 수 있어요. 다른 네트워크를 시도하세요.",
+		"modelNotFound": "Voyage AI에서 모델 {{model}}을(를) 찾을 수 없어요. 모델 선택을 확인하세요."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "오류 본문을 읽을 수 없습니다",
 		"requestFailed": "Ollama API 요청이 실패했습니다. 상태 {{status}} {{statusText}}: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "임베더 생성을 위한 OpenRouter 구성이 없습니다",
 		"vercelAiGatewayConfigMissing": "임베더 생성을 위한 Vercel AI Gateway 구성이 없습니다",
 		"bedrockConfigMissing": "임베더 생성을 위한 Amazon Bedrock 구성이 없습니다",
+		"voyageConfigMissing": "임베더 생성을 위한 Voyage AI 구성이 없습니다",
 		"invalidEmbedderType": "잘못된 임베더 유형이 구성되었습니다: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "프로바이더 '{{provider}}'의 모델 '{{modelId}}'에 대한 벡터 차원을 결정할 수 없습니다. OpenAI 호환 프로바이더 설정에서 '임베딩 차원'이 올바르게 설정되어 있는지 확인하세요.",
 		"vectorDimensionNotDetermined": "프로바이더 '{{provider}}'의 모델 '{{modelId}}'에 대한 벡터 차원을 결정할 수 없습니다. 모델 프로필 또는 구성을 확인하세요.",

+ 7 - 0
src/i18n/locales/nl/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Toegang geweigerd tot Amazon Bedrock-service. Controleer uw IAM-machtigingen.",
 		"modelNotFound": "Model {{model}} niet gevonden in Amazon Bedrock"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Ongeldig antwoordformaat van Voyage AI",
+		"invalidCredentials": "Ongeldige Voyage AI API-sleutel. Controleer je API-sleutelconfiguratie.",
+		"accessDenied": "Toegang geweigerd. Je IP-adres is mogelijk geblokkeerd door Voyage AI. Probeer een ander netwerk.",
+		"modelNotFound": "Model {{model}} niet gevonden in Voyage AI. Controleer je modelselectie."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "Kon foutinhoud niet lezen",
 		"requestFailed": "Ollama API-verzoek mislukt met status {{status}} {{statusText}}: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "OpenRouter-configuratie ontbreekt voor het maken van de embedder",
 		"vercelAiGatewayConfigMissing": "Vercel AI Gateway-configuratie ontbreekt voor het maken van de embedder",
 		"bedrockConfigMissing": "Amazon Bedrock-configuratie ontbreekt voor het maken van de embedder",
+		"voyageConfigMissing": "Voyage AI-configuratie ontbreekt voor het maken van de embedder",
 		"invalidEmbedderType": "Ongeldig embedder-type geconfigureerd: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Kan de vectordimensie voor model '{{modelId}}' met provider '{{provider}}' niet bepalen. Zorg ervoor dat de 'Embedding Dimensie' correct is ingesteld in de OpenAI-compatibele provider-instellingen.",
 		"vectorDimensionNotDetermined": "Kan de vectordimensie voor model '{{modelId}}' met provider '{{provider}}' niet bepalen. Controleer modelprofielen of configuratie.",

+ 7 - 0
src/i18n/locales/pl/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Odmowa dostępu do usługi Amazon Bedrock. Sprawdź uprawnienia IAM.",
 		"modelNotFound": "Model {{model}} nie znaleziony w Amazon Bedrock"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Nieprawidłowy format odpowiedzi z Voyage AI",
+		"invalidCredentials": "Nieprawidłowy klucz API Voyage AI. Sprawdź konfigurację klucza API.",
+		"accessDenied": "Odmowa dostępu. Twój adres IP może być zablokowany przez Voyage AI. Spróbuj innej sieci.",
+		"modelNotFound": "Model {{model}} nie znaleziony w Voyage AI. Sprawdź wybór modelu."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "Nie można odczytać treści błędu",
 		"requestFailed": "Żądanie API Ollama nie powiodło się ze statusem {{status}} {{statusText}}: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "Brak konfiguracji OpenRouter do utworzenia embeddera",
 		"vercelAiGatewayConfigMissing": "Brak konfiguracji Vercel AI Gateway do utworzenia embeddera",
 		"bedrockConfigMissing": "Brak konfiguracji Amazon Bedrock do utworzenia embeddera",
+		"voyageConfigMissing": "Brak konfiguracji Voyage AI do utworzenia embeddera",
 		"invalidEmbedderType": "Skonfigurowano nieprawidłowy typ embeddera: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Nie można określić wymiaru wektora dla modelu '{{modelId}}' z dostawcą '{{provider}}'. Upewnij się, że 'Wymiar osadzania' jest poprawnie ustawiony w ustawieniach dostawcy kompatybilnego z OpenAI.",
 		"vectorDimensionNotDetermined": "Nie można określić wymiaru wektora dla modelu '{{modelId}}' z dostawcą '{{provider}}'. Sprawdź profile modelu lub konfigurację.",

+ 7 - 0
src/i18n/locales/pt-BR/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Acesso negado ao serviço Amazon Bedrock. Verifique suas permissões IAM.",
 		"modelNotFound": "Modelo {{model}} não encontrado no Amazon Bedrock"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Formato de resposta inválido do Voyage AI",
+		"invalidCredentials": "Chave de API do Voyage AI inválida. Verifique sua configuração de chave de API.",
+		"accessDenied": "Acesso negado. Seu endereço IP pode estar bloqueado pelo Voyage AI. Tente uma rede diferente.",
+		"modelNotFound": "Modelo {{model}} não encontrado no Voyage AI. Verifique sua seleção de modelo."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "Não foi possível ler o corpo do erro",
 		"requestFailed": "Solicitação da API Ollama falhou com status {{status}} {{statusText}}: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "Configuração do OpenRouter ausente para a criação do embedder",
 		"vercelAiGatewayConfigMissing": "Configuração do Vercel AI Gateway ausente para a criação do embedder",
 		"bedrockConfigMissing": "Configuração do Amazon Bedrock ausente para a criação do embedder",
+		"voyageConfigMissing": "Configuração do Voyage AI ausente para a criação do embedder",
 		"invalidEmbedderType": "Tipo de embedder configurado inválido: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Não foi possível determinar a dimensão do vetor para o modelo '{{modelId}}' com o provedor '{{provider}}'. Certifique-se de que a 'Dimensão de Embedding' esteja configurada corretamente nas configurações do provedor compatível com OpenAI.",
 		"vectorDimensionNotDetermined": "Não foi possível determinar a dimensão do vetor para o modelo '{{modelId}}' com o provedor '{{provider}}'. Verifique os perfis do modelo ou a configuração.",

+ 7 - 0
src/i18n/locales/ru/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Доступ запрещен к сервису Amazon Bedrock. Проверьте разрешения IAM.",
 		"modelNotFound": "Модель {{model}} не найдена в Amazon Bedrock"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Неверный формат ответа от Voyage AI",
+		"invalidCredentials": "Неверный ключ API Voyage AI. Проверь конфигурацию ключа API.",
+		"accessDenied": "Доступ запрещён. Твой IP-адрес может быть заблокирован Voyage AI. Попробуй другую сеть.",
+		"modelNotFound": "Модель {{model}} не найдена в Voyage AI. Проверь выбор модели."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "Не удалось прочитать тело ошибки",
 		"requestFailed": "Запрос к API Ollama не удался со статусом {{status}} {{statusText}}: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "Конфигурация OpenRouter отсутствует для создания эмбеддера",
 		"vercelAiGatewayConfigMissing": "Конфигурация Vercel AI Gateway отсутствует для создания эмбеддера",
 		"bedrockConfigMissing": "Конфигурация Amazon Bedrock отсутствует для создания эмбеддера",
+		"voyageConfigMissing": "Конфигурация Voyage AI отсутствует для создания эмбеддера",
 		"invalidEmbedderType": "Настроен недопустимый тип эмбеддера: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Не удалось определить размерность вектора для модели '{{modelId}}' с провайдером '{{provider}}'. Убедитесь, что 'Размерность эмбеддинга' правильно установлена в настройках провайдера, совместимого с OpenAI.",
 		"vectorDimensionNotDetermined": "Не удалось определить размерность вектора для модели '{{modelId}}' с провайдером '{{provider}}'. Проверьте профили модели или конфигурацию.",

+ 7 - 0
src/i18n/locales/sk/embeddings.json

@@ -27,6 +27,12 @@
 		"modelNotFound": "Model {{model}} nebol nájdený v Amazon Bedrock",
 		"missingConfiguration": "Chýba konfigurácia Amazon Bedrock pre vytvorenie embedderu"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Neplatný formát odpovede z Voyage AI",
+		"invalidCredentials": "Neplatný API kľúč Voyage AI. Skontroluj prosím konfiguráciu API kľúča.",
+		"accessDenied": "Prístup odopretý. Tvoja IP adresa môže byť blokovaná službou Voyage AI. Skús inú sieť.",
+		"modelNotFound": "Model {{model}} nebol nájdený vo Voyage AI. Skontroluj prosím výber modelu."
+	},
 	"scanner": {
 		"unknownErrorProcessingFile": "Neznáma chyba pri spracovaní súboru {{filePath}}",
 		"unknownErrorDeletingPoints": "Neznáma chyba pri mazaní bodov pre {{filePath}}",
@@ -62,6 +68,7 @@
 		"openRouterConfigMissing": "Chýba konfigurácia OpenRouter pre vytvorenie embedderu",
 		"vercelAiGatewayConfigMissing": "Chýba konfigurácia Vercel AI Gateway pre vytvorenie embedderu",
 		"bedrockConfigMissing": "Chýba konfigurácia Amazon Bedrock pre vytvorenie embedderu",
+		"voyageConfigMissing": "Chýba konfigurácia Voyage AI pre vytvorenie embedderu",
 		"invalidEmbedderType": "Nakonfigurovaný neplatný typ embedderu: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Nedá sa určiť rozmer vektora pre model '{{modelId}}' s poskytovateľom '{{provider}}'. Uisti sa prosím, že 'Rozmer Embeddingu' je správne nastavený v nastavení OpenAI-Compatible poskytovateľa.",
 		"vectorDimensionNotDetermined": "Nedá sa určiť rozmer vektora pre model '{{modelId}}' s poskytovateľom '{{provider}}'. Skontroluj profily modelov alebo konfiguráciu.",

+ 7 - 0
src/i18n/locales/th/embeddings.json

@@ -24,6 +24,12 @@
 		"modelNotFound": "ไม่พบโมเดล {{model}} ใน Amazon Bedrock",
 		"missingConfiguration": "การกำหนดค่า Amazon Bedrock หายไปสำหรับการสร้าง embedder"
 	},
+	"voyage": {
+		"invalidResponseFormat": "รูปแบบการตอบสนองไม่ถูกต้องจาก Voyage AI",
+		"invalidCredentials": "API key ของ Voyage AI ไม่ถูกต้อง กรุณาตรวจสอบการกำหนดค่า API key ของคุณ",
+		"accessDenied": "การเข้าถึงถูกปฏิเสธ ที่อยู่ IP ของคุณอาจถูกบล็อกโดย Voyage AI ลองใช้เครือข่ายอื่น",
+		"modelNotFound": "ไม่พบโมเดล {{model}} ใน Voyage AI กรุณาตรวจสอบการเลือกโมเดลของคุณ"
+	},
 	"scanner": {
 		"unknownErrorProcessingFile": "ข้อผิดพลาดที่ไม่รู้จักในการประมวลผลไฟล์ {{filePath}}",
 		"unknownErrorDeletingPoints": "ข้อผิดพลาดที่ไม่รู้จักในการลบจุดสำหรับ {{filePath}}",
@@ -59,6 +65,7 @@
 		"vercelAiGatewayConfigMissing": "การกำหนดค่า Vercel AI Gateway หายไปสำหรับการสร้าง embedder",
 		"bedrockConfigMissing": "การกำหนดค่า Amazon Bedrock หายไปสำหรับการสร้าง embedder",
 		"openRouterConfigMissing": "การกำหนดค่า OpenRouter หายไปสำหรับการสร้าง embedder",
+		"voyageConfigMissing": "การกำหนดค่า Voyage AI หายไปสำหรับการสร้าง embedder",
 		"invalidEmbedderType": "ประเภท embedder ที่กำหนดค่าไม่ถูกต้อง: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "ไม่สามารถกำหนดมิติเวกเตอร์สำหรับโมเดล '{{modelId}}' กับผู้ให้บริการ '{{provider}}' กรุณาตรวจสอบให้แน่ใจว่า 'Embedding Dimension' ถูกตั้งค่าอย่างถูกต้องในการตั้งค่าผู้ให้บริการ OpenAI-Compatible",
 		"vectorDimensionNotDetermined": "ไม่สามารถกำหนดมิติเวกเตอร์สำหรับโมเดล '{{modelId}}' กับผู้ให้บริการ '{{provider}}' ตรวจสอบโปรไฟล์โมเดลหรือการกำหนดค่า",

+ 7 - 0
src/i18n/locales/tr/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Amazon Bedrock hizmetine erişim reddedildi. Lütfen IAM izinlerinizi kontrol edin.",
 		"modelNotFound": "Model {{model}} Amazon Bedrock'ta bulunamadı"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Voyage AI'dan geçersiz yanıt formatı",
+		"invalidCredentials": "Geçersiz Voyage AI API anahtarı. Lütfen API anahtarı yapılandırmanı kontrol et.",
+		"accessDenied": "Erişim reddedildi. IP adresin Voyage AI tarafından engellenmiş olabilir. Farklı bir ağ dene.",
+		"modelNotFound": "Model {{model}} Voyage AI'da bulunamadı. Lütfen model seçimini kontrol et."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "Hata gövdesi okunamadı",
 		"requestFailed": "Ollama API isteği {{status}} {{statusText}} durumuyla başarısız oldu: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "Gömücü oluşturmak için OpenRouter yapılandırması eksik",
 		"vercelAiGatewayConfigMissing": "Gömücü oluşturmak için Vercel AI Gateway yapılandırması eksik",
 		"bedrockConfigMissing": "Gömücü oluşturmak için Amazon Bedrock yapılandırması eksik",
+		"voyageConfigMissing": "Gömücü oluşturmak için Voyage AI yapılandırması eksik",
 		"invalidEmbedderType": "Geçersiz gömücü türü yapılandırıldı: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "'{{provider}}' sağlayıcısı ile '{{modelId}}' modeli için vektör boyutu belirlenemedi. OpenAI uyumlu sağlayıcı ayarlarında 'Gömme Boyutu'nun doğru ayarlandığından emin ol.",
 		"vectorDimensionNotDetermined": "'{{provider}}' sağlayıcısı ile '{{modelId}}' modeli için vektör boyutu belirlenemedi. Model profillerini veya yapılandırmayı kontrol et.",

+ 7 - 0
src/i18n/locales/uk/embeddings.json

@@ -23,6 +23,12 @@
 		"accessDenied": "Відмовлено в доступі до сервісу Amazon Bedrock. Будь ласка, перевір свої дозволи IAM.",
 		"modelNotFound": "Модель {{model}} не знайдена в Amazon Bedrock"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Недійсний формат відповіді від Voyage AI",
+		"invalidCredentials": "Недійсний API ключ Voyage AI. Будь ласка, перевір конфігурацію свого API ключа.",
+		"accessDenied": "Доступ заборонено. Твоя IP-адреса може бути заблокована Voyage AI. Спробуй іншу мережу.",
+		"modelNotFound": "Модель {{model}} не знайдена у Voyage AI. Будь ласка, перевір вибір моделі."
+	},
 	"scanner": {
 		"unknownErrorProcessingFile": "Невідома помилка при обробці файлу {{filePath}}",
 		"unknownErrorDeletingPoints": "Невідома помилка при видаленні точок для {{filePath}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "Відсутня конфігурація OpenRouter для створення embedder",
 		"vercelAiGatewayConfigMissing": "Відсутня конфігурація Vercel AI Gateway для створення embedder",
 		"bedrockConfigMissing": "Відсутня конфігурація Amazon Bedrock для створення embedder",
+		"voyageConfigMissing": "Відсутня конфігурація Voyage AI для створення embedder",
 		"invalidEmbedderType": "Налаштовано недійсний тип embedder: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Не вдалося визначити розмірність вектора для моделі '{{modelId}}' з провайдером '{{provider}}'. Будь ласка, переконайся, що 'Розмірність Embedding' правильно встановлена в налаштуваннях провайдера OpenAI-Compatible.",
 		"vectorDimensionNotDetermined": "Не вдалося визначити розмірність вектора для моделі '{{modelId}}' з провайдером '{{provider}}'. Перевір профілі моделі або конфігурацію.",

+ 7 - 0
src/i18n/locales/vi/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "Bị từ chối truy cập dịch vụ Amazon Bedrock. Vui lòng kiểm tra quyền IAM của bạn.",
 		"modelNotFound": "Không tìm thấy mô hình {{model}} trong Amazon Bedrock"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Định dạng phản hồi không hợp lệ từ Voyage AI",
+		"invalidCredentials": "Khóa API Voyage AI không hợp lệ. Vui lòng kiểm tra cấu hình khóa API của bạn.",
+		"accessDenied": "Bị từ chối truy cập. Địa chỉ IP của bạn có thể bị Voyage AI chặn. Hãy thử mạng khác.",
+		"modelNotFound": "Không tìm thấy mô hình {{model}} trong Voyage AI. Vui lòng kiểm tra lựa chọn mô hình của bạn."
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "Không thể đọc nội dung lỗi",
 		"requestFailed": "Yêu cầu API Ollama thất bại với trạng thái {{status}} {{statusText}}: {{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "Thiếu cấu hình OpenRouter để tạo trình nhúng",
 		"vercelAiGatewayConfigMissing": "Thiếu cấu hình Vercel AI Gateway để tạo trình nhúng",
 		"bedrockConfigMissing": "Thiếu cấu hình Amazon Bedrock để tạo trình nhúng",
+		"voyageConfigMissing": "Thiếu cấu hình Voyage AI để tạo trình nhúng",
 		"invalidEmbedderType": "Loại embedder được cấu hình không hợp lệ: {{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "Không thể xác định kích thước vector cho mô hình '{{modelId}}' với nhà cung cấp '{{provider}}'. Hãy đảm bảo 'Kích thước Embedding' được cài đặt đúng trong cài đặt nhà cung cấp tương thích OpenAI.",
 		"vectorDimensionNotDetermined": "Không thể xác định kích thước vector cho mô hình '{{modelId}}' với nhà cung cấp '{{provider}}'. Kiểm tra hồ sơ mô hình hoặc cấu hình.",

+ 7 - 0
src/i18n/locales/zh-CN/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "访问 Amazon Bedrock 服务被拒绝。请检查您的 IAM 权限。",
 		"modelNotFound": "在 Amazon Bedrock 中找不到模型 {{model}}"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Voyage AI 返回无效的响应格式",
+		"invalidCredentials": "Voyage AI API 密钥无效。请检查你的 API 密钥配置。",
+		"accessDenied": "访问被拒绝。你的 IP 地址可能被 Voyage AI 屏蔽。请尝试更换网络。",
+		"modelNotFound": "在 Voyage AI 中找不到模型 {{model}}。请检查你的模型选择。"
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "无法读取错误内容",
 		"requestFailed": "Ollama API 请求失败,状态码 {{status}} {{statusText}}:{{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "创建嵌入器时缺少 OpenRouter 配置",
 		"vercelAiGatewayConfigMissing": "创建嵌入器时缺少 Vercel AI Gateway 配置",
 		"bedrockConfigMissing": "创建嵌入器时缺少 Amazon Bedrock 配置",
+		"voyageConfigMissing": "创建嵌入器时缺少 Voyage AI 配置",
 		"invalidEmbedderType": "配置的嵌入器类型无效:{{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "无法确定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量维度。请确保在 OpenAI 兼容提供商设置中正确设置了「嵌入维度」。",
 		"vectorDimensionNotDetermined": "无法确定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量维度。请检查模型配置文件或配置。",

+ 7 - 0
src/i18n/locales/zh-TW/embeddings.json

@@ -12,6 +12,12 @@
 		"accessDenied": "存取 Amazon Bedrock 服務遭拒。請檢查您的 IAM 權限。",
 		"modelNotFound": "在 Amazon Bedrock 中找不到模型 {{model}}"
 	},
+	"voyage": {
+		"invalidResponseFormat": "Voyage AI 傳回無效的回應格式",
+		"invalidCredentials": "Voyage AI API 金鑰無效。請檢查你的 API 金鑰設定。",
+		"accessDenied": "存取遭拒。你的 IP 位址可能被 Voyage AI 封鎖。請嘗試使用其他網路。",
+		"modelNotFound": "在 Voyage AI 中找不到模型 {{model}}。請檢查你的模型選擇。"
+	},
 	"ollama": {
 		"couldNotReadErrorBody": "無法讀取錯誤內容",
 		"requestFailed": "Ollama API 請求失敗,狀態碼 {{status}} {{statusText}}:{{errorBody}}",
@@ -58,6 +64,7 @@
 		"openRouterConfigMissing": "建立嵌入器時缺少 OpenRouter 設定",
 		"vercelAiGatewayConfigMissing": "建立嵌入器時缺少 Vercel AI Gateway 設定",
 		"bedrockConfigMissing": "建立嵌入器時缺少 Amazon Bedrock 設定",
+		"voyageConfigMissing": "建立嵌入器時缺少 Voyage AI 設定",
 		"invalidEmbedderType": "設定的嵌入器類型無效:{{embedderProvider}}",
 		"vectorDimensionNotDeterminedOpenAiCompatible": "無法確定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量維度。請確保在 OpenAI 相容提供商設定中正確設定了「嵌入維度」。",
 		"vectorDimensionNotDetermined": "無法確定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量維度。請檢查模型設定檔或設定。",

+ 94 - 0
src/services/code-index/__tests__/service-factory.spec.ts

@@ -4,6 +4,7 @@ import { OpenAiEmbedder } from "../embedders/openai"
 import { CodeIndexOllamaEmbedder } from "../embedders/ollama"
 import { OpenAICompatibleEmbedder } from "../embedders/openai-compatible"
 import { GeminiEmbedder } from "../embedders/gemini"
+import { VoyageEmbedder } from "../embedders/voyage" // kilocode_change
 import { QdrantVectorStore } from "../vector-store/qdrant-client"
 
 // Mock the embedders and vector store
@@ -11,6 +12,7 @@ vitest.mock("../embedders/openai")
 vitest.mock("../embedders/ollama")
 vitest.mock("../embedders/openai-compatible")
 vitest.mock("../embedders/gemini")
+vitest.mock("../embedders/voyage") // kilocode_change
 vitest.mock("../vector-store/qdrant-client")
 
 // Mock the embedding models module
@@ -32,6 +34,7 @@ const MockedOpenAiEmbedder = OpenAiEmbedder as MockedClass<typeof OpenAiEmbedder
 const MockedCodeIndexOllamaEmbedder = CodeIndexOllamaEmbedder as MockedClass<typeof CodeIndexOllamaEmbedder>
 const MockedOpenAICompatibleEmbedder = OpenAICompatibleEmbedder as MockedClass<typeof OpenAICompatibleEmbedder>
 const MockedGeminiEmbedder = GeminiEmbedder as MockedClass<typeof GeminiEmbedder>
+const MockedVoyageEmbedder = VoyageEmbedder as MockedClass<typeof VoyageEmbedder> // kilocode_change
 const MockedQdrantVectorStore = QdrantVectorStore as MockedClass<typeof QdrantVectorStore>
 
 // Import the mocked functions
@@ -337,6 +340,73 @@ describe("CodeIndexServiceFactory", () => {
 			// Act & Assert
 			expect(() => factory.createEmbedder()).toThrow("serviceFactory.invalidEmbedderType")
 		})
+
+		// kilocode_change start
+		it("should pass model ID to Voyage embedder when using Voyage provider", () => {
+			// Arrange
+			const testModelId = "voyage-code-3"
+			const testConfig = {
+				embedderProvider: "voyage",
+				modelId: testModelId,
+				voyageOptions: {
+					apiKey: "test-api-key",
+				},
+			}
+			mockConfigManager.getConfig.mockReturnValue(testConfig as any)
+
+			// Act
+			factory.createEmbedder()
+
+			// Assert
+			expect(MockedVoyageEmbedder).toHaveBeenCalledWith("test-api-key", testModelId)
+		})
+
+		it("should handle undefined model ID for Voyage embedder", () => {
+			// Arrange
+			const testConfig = {
+				embedderProvider: "voyage",
+				modelId: undefined,
+				voyageOptions: {
+					apiKey: "test-api-key",
+				},
+			}
+			mockConfigManager.getConfig.mockReturnValue(testConfig as any)
+
+			// Act
+			factory.createEmbedder()
+
+			// Assert
+			expect(MockedVoyageEmbedder).toHaveBeenCalledWith("test-api-key", undefined)
+		})
+
+		it("should throw error when Voyage API key is missing", () => {
+			// Arrange
+			const testConfig = {
+				embedderProvider: "voyage",
+				modelId: "voyage-code-3",
+				voyageOptions: {
+					apiKey: undefined,
+				},
+			}
+			mockConfigManager.getConfig.mockReturnValue(testConfig as any)
+
+			// Act & Assert
+			expect(() => factory.createEmbedder()).toThrow("serviceFactory.voyageConfigMissing")
+		})
+
+		it("should throw error when Voyage options are missing", () => {
+			// Arrange
+			const testConfig = {
+				embedderProvider: "voyage",
+				modelId: "voyage-code-3",
+				voyageOptions: undefined,
+			}
+			mockConfigManager.getConfig.mockReturnValue(testConfig as any)
+
+			// Act & Assert
+			expect(() => factory.createEmbedder()).toThrow("serviceFactory.voyageConfigMissing")
+		})
+		// kilocode_change end
 	})
 
 	describe("createVectorStore", () => {
@@ -785,6 +855,30 @@ describe("CodeIndexServiceFactory", () => {
 			expect(mockEmbedderInstance.validateConfiguration).toHaveBeenCalled()
 		})
 
+		// kilocode_change start
+		it("should validate Voyage embedder successfully", async () => {
+			// Arrange
+			const testConfig = {
+				embedderProvider: "voyage",
+				modelId: "voyage-code-3",
+				voyageOptions: {
+					apiKey: "test-voyage-api-key",
+				},
+			}
+			mockConfigManager.getConfig.mockReturnValue(testConfig as any)
+			MockedVoyageEmbedder.mockImplementation(() => mockEmbedderInstance)
+			mockEmbedderInstance.validateConfiguration.mockResolvedValue({ valid: true })
+
+			// Act
+			const embedder = factory.createEmbedder()
+			const result = await factory.validateEmbedder(embedder)
+
+			// Assert
+			expect(result).toEqual({ valid: true })
+			expect(mockEmbedderInstance.validateConfiguration).toHaveBeenCalled()
+		})
+		// kilocode_change end
+
 		it("should handle validation exceptions", async () => {
 			// Arrange
 			const testConfig = {

+ 25 - 0
src/services/code-index/config-manager.ts

@@ -26,6 +26,7 @@ export class CodeIndexConfigManager {
 	private vercelAiGatewayOptions?: { apiKey: string }
 	private bedrockOptions?: { region: string; profile?: string }
 	private openRouterOptions?: { apiKey: string; specificProvider?: string }
+	private voyageOptions?: { apiKey: string } // kilocode_change
 	private qdrantUrl?: string = "http://localhost:6333"
 	private qdrantApiKey?: string
 	private searchMinScore?: number
@@ -137,6 +138,7 @@ export class CodeIndexConfigManager {
 		const bedrockProfile = codebaseIndexConfig.codebaseIndexBedrockProfile ?? ""
 		const openRouterApiKey = this.contextProxy?.getSecret("codebaseIndexOpenRouterApiKey") ?? ""
 		const openRouterSpecificProvider = codebaseIndexConfig.codebaseIndexOpenRouterSpecificProvider ?? ""
+		const voyageApiKey = this.contextProxy?.getSecret("codebaseIndexVoyageApiKey") ?? "" // kilocode_change
 
 		// Update instance variables with configuration
 		this.codebaseIndexEnabled = codebaseIndexEnabled ?? false
@@ -186,6 +188,10 @@ export class CodeIndexConfigManager {
 			this.embedderProvider = "bedrock"
 		} else if (codebaseIndexEmbedderProvider === "openrouter") {
 			this.embedderProvider = "openrouter"
+			// kilocode_change start
+		} else if (codebaseIndexEmbedderProvider === "voyage") {
+			this.embedderProvider = "voyage"
+			// kilocode_change end
 		} else {
 			this.embedderProvider = "openai"
 		}
@@ -214,6 +220,7 @@ export class CodeIndexConfigManager {
 		this.bedrockOptions = bedrockRegion
 			? { region: bedrockRegion, profile: bedrockProfile || undefined }
 			: undefined
+		this.voyageOptions = voyageApiKey ? { apiKey: voyageApiKey } : undefined // kilocode_change
 	}
 
 	/**
@@ -262,6 +269,7 @@ export class CodeIndexConfigManager {
 			bedrockProfile: this.bedrockOptions?.profile ?? "",
 			openRouterApiKey: this.openRouterOptions?.apiKey ?? "",
 			openRouterSpecificProvider: this.openRouterOptions?.specificProvider ?? "",
+			voyageApiKey: this.voyageOptions?.apiKey ?? "", // kilocode_change
 			qdrantUrl: this.qdrantUrl ?? "",
 			qdrantApiKey: this.qdrantApiKey ?? "",
 		}
@@ -349,7 +357,14 @@ export class CodeIndexConfigManager {
 			const qdrantUrl = this.qdrantUrl
 			const isConfigured = !!(apiKey && qdrantUrl)
 			return isConfigured
+			// kilocode_change start
+		} else if (this.embedderProvider === "voyage") {
+			const apiKey = this.voyageOptions?.apiKey
+			const qdrantUrl = this.qdrantUrl
+			const isConfigured = !!(apiKey && qdrantUrl)
+			return isConfigured
 		}
+		// kilocode_change end
 		return false // Should not happen if embedderProvider is always set correctly
 	}
 
@@ -388,6 +403,7 @@ export class CodeIndexConfigManager {
 		const prevBedrockProfile = prev?.bedrockProfile ?? ""
 		const prevOpenRouterApiKey = prev?.openRouterApiKey ?? ""
 		const prevOpenRouterSpecificProvider = prev?.openRouterSpecificProvider ?? ""
+		const prevVoyageApiKey = prev?.voyageApiKey ?? "" // kilocode_change
 		const prevQdrantUrl = prev?.qdrantUrl ?? ""
 		const prevQdrantApiKey = prev?.qdrantApiKey ?? ""
 		// kilocode_change - start
@@ -446,6 +462,7 @@ export class CodeIndexConfigManager {
 		const currentBedrockProfile = this.bedrockOptions?.profile ?? ""
 		const currentOpenRouterApiKey = this.openRouterOptions?.apiKey ?? ""
 		const currentOpenRouterSpecificProvider = this.openRouterOptions?.specificProvider ?? ""
+		const currentVoyageApiKey = this.voyageOptions?.apiKey ?? "" // kilocode_change
 		const currentQdrantUrl = this.qdrantUrl ?? ""
 		const currentQdrantApiKey = this.qdrantApiKey ?? ""
 
@@ -489,6 +506,13 @@ export class CodeIndexConfigManager {
 			return true
 		}
 
+		// kilocode_change start
+		// Voyage API key change
+		if (prevVoyageApiKey !== currentVoyageApiKey) {
+			return true
+		}
+		// kilocode_change end
+
 		// Check for model dimension changes (generic for all providers)
 		if (prevModelDimension !== currentModelDimension) {
 			return true
@@ -553,6 +577,7 @@ export class CodeIndexConfigManager {
 			vercelAiGatewayOptions: this.vercelAiGatewayOptions,
 			bedrockOptions: this.bedrockOptions,
 			openRouterOptions: this.openRouterOptions,
+			voyageOptions: this.voyageOptions, // kilocode_change
 			qdrantUrl: this.qdrantUrl,
 			qdrantApiKey: this.qdrantApiKey,
 			searchMinScore: this.currentSearchMinScore,

+ 288 - 0
src/services/code-index/embedders/voyage.ts

@@ -0,0 +1,288 @@
+// kilocode_change - new file
+import { IEmbedder, EmbeddingResponse, EmbedderInfo } from "../interfaces/embedder"
+import {
+	MAX_BATCH_TOKENS,
+	MAX_ITEM_TOKENS,
+	MAX_BATCH_RETRIES as MAX_RETRIES,
+	INITIAL_RETRY_DELAY_MS as INITIAL_DELAY_MS,
+} from "../constants"
+import { getModelQueryPrefix } from "../../../shared/embeddingModels"
+import { t } from "../../../i18n"
+import { withValidationErrorHandling, formatEmbeddingError, HttpError } from "../shared/validation-helpers"
+import { TelemetryEventName } from "@roo-code/types"
+import { TelemetryService } from "@roo-code/telemetry"
+
+/**
+ * Response structure from Voyage AI embedding API
+ */
+interface VoyageEmbeddingItem {
+	embedding: number[]
+	index: number
+}
+
+interface VoyageEmbeddingResponse {
+	data: VoyageEmbeddingItem[]
+	model: string
+	usage?: {
+		total_tokens?: number
+	}
+}
+
+/**
+ * Voyage AI embedder implementation using the native Voyage API.
+ *
+ * Voyage AI provides high-quality embedding models including code-specific models.
+ * API endpoint: https://api.voyageai.com/v1/embeddings
+ *
+ * Supported models:
+ * - voyage-code-3 (dimension: 1024, code-optimized)
+ * - voyage-4-large (dimension: 1024)
+ * - voyage-4 (dimension: 1024)
+ * - voyage-4-lite (dimension: 1024)
+ * - voyage-finance-2 (dimension: 1024)
+ * - voyage-law-2 (dimension: 1024)
+ */
+export class VoyageEmbedder implements IEmbedder {
+	private static readonly VOYAGE_BASE_URL = "https://api.voyageai.com/v1/embeddings"
+	private static readonly DEFAULT_MODEL = "voyage-code-3"
+	private readonly apiKey: string
+	private readonly modelId: string
+
+	/**
+	 * Creates a new Voyage AI embedder
+	 * @param apiKey The Voyage AI API key for authentication
+	 * @param modelId The model ID to use (defaults to voyage-code-3)
+	 */
+	constructor(apiKey: string, modelId?: string) {
+		if (!apiKey) {
+			throw new Error(t("embeddings:validation.apiKeyRequired"))
+		}
+
+		this.apiKey = apiKey
+		this.modelId = modelId || VoyageEmbedder.DEFAULT_MODEL
+	}
+
+	/**
+	 * Creates embeddings for the given texts using Voyage AI's embedding API
+	 * @param texts Array of text strings to embed
+	 * @param model Optional model identifier (uses constructor model if not provided)
+	 * @returns Promise resolving to embedding response
+	 */
+	async createEmbeddings(texts: string[], model?: string): Promise<EmbeddingResponse> {
+		const modelToUse = model || this.modelId
+
+		// Apply model-specific query prefix if required
+		const queryPrefix = getModelQueryPrefix("voyage", modelToUse)
+		const processedTexts = queryPrefix
+			? texts.map((text, index) => {
+					// Prevent double-prefixing
+					if (text.startsWith(queryPrefix)) {
+						return text
+					}
+					const prefixedText = `${queryPrefix}${text}`
+					const estimatedTokens = Math.ceil(prefixedText.length / 4)
+					if (estimatedTokens > MAX_ITEM_TOKENS) {
+						console.warn(
+							t("embeddings:textWithPrefixExceedsTokenLimit", {
+								index,
+								estimatedTokens,
+								maxTokens: MAX_ITEM_TOKENS,
+							}),
+						)
+						// Return original text if adding prefix would exceed limit
+						return text
+					}
+					return prefixedText
+				})
+			: texts
+
+		const allEmbeddings: number[][] = []
+		const usage = { promptTokens: 0, totalTokens: 0 }
+		const remainingTexts = [...processedTexts]
+
+		while (remainingTexts.length > 0) {
+			const currentBatch: string[] = []
+			let currentBatchTokens = 0
+			const processedIndices: number[] = []
+
+			for (let i = 0; i < remainingTexts.length; i++) {
+				const text = remainingTexts[i]
+				const itemTokens = Math.ceil(text.length / 4)
+
+				if (itemTokens > MAX_ITEM_TOKENS) {
+					console.warn(
+						t("embeddings:textExceedsTokenLimit", {
+							index: i,
+							itemTokens,
+							maxTokens: MAX_ITEM_TOKENS,
+						}),
+					)
+					processedIndices.push(i)
+					continue
+				}
+
+				if (currentBatchTokens + itemTokens <= MAX_BATCH_TOKENS) {
+					currentBatch.push(text)
+					currentBatchTokens += itemTokens
+					processedIndices.push(i)
+				} else {
+					break
+				}
+			}
+
+			// Remove processed items from remainingTexts (in reverse order to maintain correct indices)
+			for (let i = processedIndices.length - 1; i >= 0; i--) {
+				remainingTexts.splice(processedIndices[i], 1)
+			}
+
+			if (currentBatch.length > 0) {
+				const batchResult = await this._embedBatchWithRetries(currentBatch, modelToUse)
+				allEmbeddings.push(...batchResult.embeddings)
+				usage.promptTokens += batchResult.usage.promptTokens
+				usage.totalTokens += batchResult.usage.totalTokens
+			}
+		}
+
+		return { embeddings: allEmbeddings, usage }
+	}
+
+	/**
+	 * Helper method to handle batch embedding with retries and exponential backoff
+	 * @param batchTexts Array of texts to embed in this batch
+	 * @param model Model identifier to use
+	 * @returns Promise resolving to embeddings and usage statistics
+	 */
+	private async _embedBatchWithRetries(
+		batchTexts: string[],
+		model: string,
+	): Promise<{ embeddings: number[][]; usage: { promptTokens: number; totalTokens: number } }> {
+		for (let attempts = 0; attempts < MAX_RETRIES; attempts++) {
+			try {
+				const response = await fetch(VoyageEmbedder.VOYAGE_BASE_URL, {
+					method: "POST",
+					headers: {
+						"Content-Type": "application/json",
+						Authorization: `Bearer ${this.apiKey}`,
+					},
+					body: JSON.stringify({
+						input: batchTexts,
+						model: model,
+						input_type: "document", // For indexing, we use "document" type
+					}),
+				})
+
+				if (!response.ok) {
+					const errorBody = await response.text().catch(() => "Unknown error")
+					const error = new Error(`HTTP ${response.status}: ${errorBody}`) as HttpError
+					error.status = response.status
+					throw error
+				}
+
+				const result: VoyageEmbeddingResponse = await response.json()
+
+				// Sort by index to ensure correct order
+				const sortedData = [...result.data].sort((a, b) => a.index - b.index)
+
+				return {
+					embeddings: sortedData.map((item) => item.embedding),
+					usage: {
+						promptTokens: result.usage?.total_tokens || 0,
+						totalTokens: result.usage?.total_tokens || 0,
+					},
+				}
+			} catch (error: any) {
+				const hasMoreAttempts = attempts < MAX_RETRIES - 1
+
+				// Check if it's a rate limit error
+				const httpError = error as HttpError
+				if (httpError?.status === 429 && hasMoreAttempts) {
+					const delayMs = INITIAL_DELAY_MS * Math.pow(2, attempts)
+					console.warn(
+						t("embeddings:rateLimitRetry", {
+							delayMs,
+							attempt: attempts + 1,
+							maxRetries: MAX_RETRIES,
+						}),
+					)
+					await new Promise((resolve) => setTimeout(resolve, delayMs))
+					continue
+				}
+
+				// Capture telemetry before reformatting the error
+				TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, {
+					error: error instanceof Error ? error.message : String(error),
+					stack: error instanceof Error ? error.stack : undefined,
+					location: "VoyageEmbedder:_embedBatchWithRetries",
+					attempt: attempts + 1,
+				})
+
+				// Log the error for debugging
+				console.error(`Voyage AI embedder error (attempt ${attempts + 1}/${MAX_RETRIES}):`, error)
+
+				// Format and throw the error
+				throw formatEmbeddingError(error, MAX_RETRIES)
+			}
+		}
+
+		throw new Error(t("embeddings:failedMaxAttempts", { attempts: MAX_RETRIES }))
+	}
+
+	/**
+	 * Validates the Voyage AI embedder configuration by attempting a minimal embedding request
+	 * @returns Promise resolving to validation result with success status and optional error message
+	 */
+	async validateConfiguration(): Promise<{ valid: boolean; error?: string }> {
+		return withValidationErrorHandling(async () => {
+			try {
+				const response = await fetch(VoyageEmbedder.VOYAGE_BASE_URL, {
+					method: "POST",
+					headers: {
+						"Content-Type": "application/json",
+						Authorization: `Bearer ${this.apiKey}`,
+					},
+					body: JSON.stringify({
+						input: ["test"],
+						model: this.modelId,
+					}),
+				})
+
+				if (!response.ok) {
+					const errorBody = await response.text().catch(() => "Unknown error")
+					const error = new Error(`HTTP ${response.status}: ${errorBody}`) as HttpError
+					error.status = response.status
+					throw error
+				}
+
+				const result: VoyageEmbeddingResponse = await response.json()
+
+				// Check if we got a valid response
+				if (!result.data || result.data.length === 0) {
+					return {
+						valid: false,
+						error: t("embeddings:voyage.invalidResponseFormat"),
+					}
+				}
+
+				return { valid: true }
+			} catch (error) {
+				// Capture telemetry for validation errors
+				TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, {
+					error: error instanceof Error ? error.message : String(error),
+					stack: error instanceof Error ? error.stack : undefined,
+					location: "VoyageEmbedder:validateConfiguration",
+				})
+				console.error("Voyage AI embedder error in validateConfiguration:", error)
+				throw error
+			}
+		}, "voyage")
+	}
+
+	/**
+	 * Returns information about this embedder
+	 */
+	get embedderInfo(): EmbedderInfo {
+		return {
+			name: "voyage",
+		}
+	}
+}

+ 2 - 0
src/services/code-index/interfaces/config.ts

@@ -21,6 +21,7 @@ export interface CodeIndexConfig {
 	vercelAiGatewayOptions?: { apiKey: string }
 	bedrockOptions?: { region: string; profile?: string }
 	openRouterOptions?: { apiKey: string; specificProvider?: string }
+	voyageOptions?: { apiKey: string } // kilocode_change
 	qdrantUrl?: string
 	qdrantApiKey?: string
 	searchMinScore?: number
@@ -55,6 +56,7 @@ export type PreviousConfigSnapshot = {
 	bedrockProfile?: string
 	openRouterApiKey?: string
 	openRouterSpecificProvider?: string
+	voyageApiKey?: string // kilocode_change
 	qdrantUrl?: string
 	qdrantApiKey?: string
 }

+ 1 - 0
src/services/code-index/interfaces/embedder.ts

@@ -37,6 +37,7 @@ export type AvailableEmbedders =
 	| "vercel-ai-gateway"
 	| "bedrock"
 	| "openrouter"
+	| "voyage" // kilocode_change
 
 export interface EmbedderInfo {
 	name: AvailableEmbedders

+ 1 - 0
src/services/code-index/interfaces/manager.ts

@@ -79,6 +79,7 @@ export type EmbedderProvider =
 	| "vercel-ai-gateway"
 	| "bedrock"
 	| "openrouter"
+	| "voyage" // kilocode_change
 
 export interface IndexProgressUpdate {
 	systemStatus: IndexingState

+ 8 - 0
src/services/code-index/service-factory.ts

@@ -20,6 +20,7 @@ import { MistralEmbedder } from "./embedders/mistral"
 import { VercelAiGatewayEmbedder } from "./embedders/vercel-ai-gateway"
 import { BedrockEmbedder } from "./embedders/bedrock"
 import { OpenRouterEmbedder } from "./embedders/openrouter"
+import { VoyageEmbedder } from "./embedders/voyage" // kilocode_change
 import { QdrantVectorStore } from "./vector-store/qdrant-client"
 import { LanceDBVectorStore } from "./vector-store/lancedb-vector-store"
 import { codeParser, DirectoryScanner, FileWatcher } from "./processors"
@@ -107,7 +108,14 @@ export class CodeIndexServiceFactory {
 				undefined, // maxItemTokens
 				config.openRouterOptions.specificProvider,
 			)
+			// kilocode_change start
+		} else if (provider === "voyage") {
+			if (!config.voyageOptions?.apiKey) {
+				throw new Error(t("embeddings:serviceFactory.voyageConfigMissing"))
+			}
+			return new VoyageEmbedder(config.voyageOptions.apiKey, config.modelId)
 		}
+		// kilocode_change end
 
 		throw new Error(
 			t("embeddings:serviceFactory.invalidEmbedderType", { embedderProvider: config.embedderProvider }),

+ 16 - 0
src/shared/embeddingModels.ts

@@ -83,6 +83,17 @@ export const EMBEDDING_MODEL_PROFILES: EmbeddingModelProfiles = {
 		"qwen/qwen3-embedding-4b": { dimension: 2560, scoreThreshold: 0.4 },
 		"qwen/qwen3-embedding-8b": { dimension: 4096, scoreThreshold: 0.4 },
 	},
+	// kilocode_change start
+	voyage: {
+		// Voyage AI embedding models - code-specific and general purpose
+		"voyage-code-3": { dimension: 1024, scoreThreshold: 0.4 },
+		"voyage-4-large": { dimension: 1024, scoreThreshold: 0.4 },
+		"voyage-4": { dimension: 1024, scoreThreshold: 0.4 },
+		"voyage-4-lite": { dimension: 1024, scoreThreshold: 0.4 },
+		"voyage-finance-2": { dimension: 1024, scoreThreshold: 0.4 },
+		"voyage-law-2": { dimension: 1024, scoreThreshold: 0.4 },
+	},
+	// kilocode_change end
 }
 
 /**
@@ -181,6 +192,11 @@ export function getDefaultModelId(provider: EmbedderProvider): string {
 		case "openrouter":
 			return "openai/text-embedding-3-large"
 
+		// kilocode_change start
+		case "voyage":
+			return "voyage-code-3"
+		// kilocode_change end
+
 		default:
 			// Fallback for unknown providers
 			console.warn(`Unknown provider for default model ID: ${provider}. Falling back to OpenAI default.`)

+ 93 - 1
webview-ui/src/components/chat/CodeIndexPopover.tsx

@@ -97,6 +97,7 @@ interface LocalCodeIndexSettings {
 	codebaseIndexVercelAiGatewayApiKey?: string
 	codebaseIndexOpenRouterApiKey?: string
 	codebaseIndexOpenRouterSpecificProvider?: string
+	codebaseIndexVoyageApiKey?: string // kilocode_change
 }
 
 // Validation schema for codebase index settings
@@ -192,6 +193,16 @@ const createValidationSchema = (provider: EmbedderProvider, t: any) => {
 					.min(1, t("settings:codeIndex.validation.modelSelectionRequired")),
 			})
 
+		// kilocode_change start
+		case "voyage":
+			return baseSchema.extend({
+				codebaseIndexVoyageApiKey: z.string().min(1, t("settings:codeIndex.validation.voyageApiKeyRequired")),
+				codebaseIndexEmbedderModelId: z
+					.string()
+					.min(1, t("settings:codeIndex.validation.modelSelectionRequired")),
+			})
+		// kilocode_change end
+
 		default:
 			return baseSchema
 	}
@@ -262,6 +273,7 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
 		codebaseIndexVercelAiGatewayApiKey: "",
 		codebaseIndexOpenRouterApiKey: "",
 		codebaseIndexOpenRouterSpecificProvider: "",
+		codebaseIndexVoyageApiKey: "", // kilocode_change
 	})
 
 	// Initial settings state - stores the settings when popover opens
@@ -320,6 +332,7 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
 				codebaseIndexOpenRouterApiKey: "",
 				codebaseIndexOpenRouterSpecificProvider:
 					codebaseIndexConfig.codebaseIndexOpenRouterSpecificProvider || "",
+				codebaseIndexVoyageApiKey: "", // kilocode_change
 			}
 			setInitialSettings(settings)
 			setCurrentSettings(settings)
@@ -444,6 +457,11 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
 							? SECRET_PLACEHOLDER
 							: ""
 					}
+					// kilocode_change start
+					if (!prev.codebaseIndexVoyageApiKey || prev.codebaseIndexVoyageApiKey === SECRET_PLACEHOLDER) {
+						updated.codebaseIndexVoyageApiKey = secretStatus.hasVoyageApiKey ? SECRET_PLACEHOLDER : ""
+					}
+					// kilocode_change end
 
 					return updated
 				}
@@ -527,7 +545,8 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
 					key === "codebaseIndexGeminiApiKey" ||
 					key === "codebaseIndexMistralApiKey" ||
 					key === "codebaseIndexVercelAiGatewayApiKey" ||
-					key === "codebaseIndexOpenRouterApiKey"
+					key === "codebaseIndexOpenRouterApiKey" ||
+					key === "codebaseIndexVoyageApiKey" // kilocode_change
 				) {
 					dataToValidate[key] = "placeholder-valid"
 				}
@@ -886,6 +905,11 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
 												<SelectItem value="openrouter">
 													{t("settings:codeIndex.openRouterProvider")}
 												</SelectItem>
+												{/* kilocode_change start */}
+												<SelectItem value="voyage">
+													{t("settings:codeIndex.voyageProvider")}
+												</SelectItem>
+												{/* kilocode_change end */}
 											</SelectContent>
 										</Select>
 									</div>
@@ -1577,6 +1601,74 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
 										</>
 									)}
 
+									{/* kilocode_change start */}
+									{/* Voyage AI Settings */}
+									{currentSettings.codebaseIndexEmbedderProvider === "voyage" && (
+										<>
+											<div className="space-y-2">
+												<label className="text-sm font-medium">
+													{t("settings:codeIndex.voyageApiKeyLabel")}
+												</label>
+												<VSCodeTextField
+													type="password"
+													value={currentSettings.codebaseIndexVoyageApiKey || ""}
+													onInput={(e: any) =>
+														updateSetting("codebaseIndexVoyageApiKey", e.target.value)
+													}
+													placeholder={t("settings:codeIndex.voyageApiKeyPlaceholder")}
+													className={cn("w-full", {
+														"border-red-500": formErrors.codebaseIndexVoyageApiKey,
+													})}
+												/>
+												{formErrors.codebaseIndexVoyageApiKey && (
+													<p className="text-xs text-vscode-errorForeground mt-1 mb-0">
+														{formErrors.codebaseIndexVoyageApiKey}
+													</p>
+												)}
+											</div>
+
+											<div className="space-y-2">
+												<label className="text-sm font-medium">
+													{t("settings:codeIndex.modelLabel")}
+												</label>
+												<VSCodeDropdown
+													value={currentSettings.codebaseIndexEmbedderModelId || ""}
+													onChange={(e: any) =>
+														updateSetting("codebaseIndexEmbedderModelId", e.target.value)
+													}
+													className={cn("w-full", {
+														"border-red-500": formErrors.codebaseIndexEmbedderModelId,
+													})}>
+													<VSCodeOption value="" className="p-2">
+														{t("settings:codeIndex.selectModel")}
+													</VSCodeOption>
+													{getAvailableModels().map((modelId) => {
+														const model =
+															codebaseIndexModels?.[
+																currentSettings.codebaseIndexEmbedderProvider as keyof typeof codebaseIndexModels
+															]?.[modelId]
+														return (
+															<VSCodeOption key={modelId} value={modelId} className="p-2">
+																{modelId}{" "}
+																{model
+																	? t("settings:codeIndex.modelDimensions", {
+																			dimension: model.dimension,
+																		})
+																	: ""}
+															</VSCodeOption>
+														)
+													})}
+												</VSCodeDropdown>
+												{formErrors.codebaseIndexEmbedderModelId && (
+													<p className="text-xs text-vscode-errorForeground mt-1 mb-0">
+														{formErrors.codebaseIndexEmbedderModelId}
+													</p>
+												)}
+											</div>
+										</>
+									)}
+									{/* kilocode_change end */}
+
 									{/* Qdrant Settings */}
 									{currentSettings.codebaseIndexVectorStoreProvider === "qdrant" && (
 										<>

+ 4 - 0
webview-ui/src/i18n/locales/ar/settings.json

@@ -137,6 +137,9 @@
 		"openRouterApiKeyPlaceholder": "أدخل مفتاح OpenRouter API",
 		"openRouterProviderRoutingLabel": "توجيه مزود OpenRouter",
 		"openRouterProviderRoutingDescription": "يوجه OpenRouter الطلبات إلى أفضل المزودين المتاحين لنموذج التضمين الخاص بك. افتراضيًا، يتم موازنة التحميل للطلبات عبر أفضل المزودين لزيادة وقت التشغيل. ومع ذلك، يمكنك اختيار مزود معين لاستخدامه مع هذا النموذج.",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "مفتاح Voyage AI API",
+		"voyageApiKeyPlaceholder": "أدخل مفتاح Voyage AI API الخاص بك",
 		"openaiCompatibleProvider": "متوافق مع OpenAI",
 		"openaiCompatibleResponsesProvider": "متوافق مع OpenAI (Responses)",
 		"openAiKeyLabel": "مفتاح OpenAI API",
@@ -211,6 +214,7 @@
 			"bedrockRegionRequired": "منطقة AWS مطلوبة",
 			"bedrockProfileRequired": "ملف AWS مطلوب",
 			"openRouterApiKeyRequired": "مفتاح OpenRouter API مطلوب",
+			"voyageApiKeyRequired": "مفتاح Voyage AI API مطلوب",
 			"ollamaBaseUrlRequired": "رابط Ollama الأساسي مطلوب",
 			"baseUrlRequired": "الرابط الأساسي مطلوب",
 			"modelDimensionMinValue": "بُعد النموذج يجب أن يكون أكبر من 0"

+ 5 - 1
webview-ui/src/i18n/locales/ca/settings.json

@@ -104,6 +104,9 @@
 		"openRouterApiKeyPlaceholder": "Introduïu la vostra clau de l'API d'OpenRouter",
 		"openRouterProviderRoutingLabel": "Encaminament de proveïdors d'OpenRouter",
 		"openRouterProviderRoutingDescription": "OpenRouter dirigeix les sol·licituds als millors proveïdors disponibles per al vostre model d'embedding. Per defecte, les sol·licituds s'equilibren entre els principals proveïdors per maximitzar el temps de funcionament. No obstant això, podeu triar un proveïdor específic per utilitzar amb aquest model.",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Clau API de Voyage AI",
+		"voyageApiKeyPlaceholder": "Introdueix la teva clau API de Voyage AI",
 		"openaiCompatibleProvider": "Compatible amb OpenAI",
 		"openaiCompatibleResponsesProvider": "Compatible amb OpenAI (Responses)",
 		"openAiKeyLabel": "Clau API OpenAI",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "Cal una URL base d'Ollama",
 			"baseUrlRequired": "Cal una URL base",
 			"modelDimensionMinValue": "La dimensió del model ha de ser superior a 0",
-			"openRouterApiKeyRequired": "Clau API d'OpenRouter és requerida"
+			"openRouterApiKeyRequired": "Clau API d'OpenRouter és requerida",
+			"voyageApiKeyRequired": "Cal una clau API de Voyage AI"
 		},
 		"optional": "opcional",
 		"advancedConfigLabel": "Configuració avançada",

+ 4 - 0
webview-ui/src/i18n/locales/cs/settings.json

@@ -123,6 +123,9 @@
 		"openRouterApiKeyPlaceholder": "Zadejte svůj klíč API OpenRouter",
 		"openRouterProviderRoutingLabel": "Směrování poskytovatele OpenRouter",
 		"openRouterProviderRoutingDescription": "OpenRouter směruje požadavky na nejlepší dostupné poskytovatele pro váš model vkládání. Ve výchozím nastavení jsou požadavky vyrovnávány zátěží mezi nejlepší poskytovatele, aby se maximalizovala doba provozu. Můžete si však vybrat konkrétního poskytovatele, kterého chcete pro tento model použít.",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "API klíč Voyage AI",
+		"voyageApiKeyPlaceholder": "Zadej svůj API klíč Voyage AI",
 		"openaiCompatibleProvider": "Kompatibilní s OpenAI",
 		"openaiCompatibleResponsesProvider": "Kompatibilní s OpenAI (Responses)",
 		"openAiKeyLabel": "Klíč API OpenAI",
@@ -195,6 +198,7 @@
 			"mistralApiKeyRequired": "Klíč API Mistral je povinný",
 			"vercelAiGatewayApiKeyRequired": "Je vyžadován klíč API Vercel AI Gateway",
 			"openRouterApiKeyRequired": "Klíč API OpenRouter je povinný",
+			"voyageApiKeyRequired": "API klíč Voyage AI je povinný",
 			"ollamaBaseUrlRequired": "Základní URL Ollama je povinné",
 			"baseUrlRequired": "Základní URL je povinné",
 			"modelDimensionMinValue": "Dimenze modelu musí být větší než 0",

+ 5 - 1
webview-ui/src/i18n/locales/de/settings.json

@@ -109,6 +109,9 @@
 		"mistralProvider": "Mistral",
 		"mistralApiKeyLabel": "API-Schlüssel:",
 		"mistralApiKeyPlaceholder": "Gib deinen Mistral-API-Schlüssel ein",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Voyage AI API-Schlüssel",
+		"voyageApiKeyPlaceholder": "Gib deinen Voyage AI API-Schlüssel ein",
 		"openaiCompatibleProvider": "OpenAI-kompatibel",
 		"openaiCompatibleResponsesProvider": "OpenAI-kompatibel (Responses)",
 		"openAiKeyLabel": "OpenAI API-Schlüssel",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "Ollama-Basis-URL ist erforderlich",
 			"baseUrlRequired": "Basis-URL ist erforderlich",
 			"modelDimensionMinValue": "Modellabmessung muss größer als 0 sein",
-			"openRouterApiKeyRequired": "OpenRouter API-Schlüssel ist erforderlich"
+			"openRouterApiKeyRequired": "OpenRouter API-Schlüssel ist erforderlich",
+			"voyageApiKeyRequired": "Voyage AI API-Schlüssel ist erforderlich"
 		},
 		"optional": "optional",
 		"advancedConfigLabel": "Erweiterte Konfiguration",

+ 4 - 0
webview-ui/src/i18n/locales/en/settings.json

@@ -119,6 +119,9 @@
 		"openRouterApiKeyPlaceholder": "Enter your OpenRouter API key",
 		"openRouterProviderRoutingLabel": "OpenRouter Provider Routing",
 		"openRouterProviderRoutingDescription": "OpenRouter routes requests to the best available providers for your embedding model. By default, requests are load balanced across the top providers to maximize uptime. However, you can choose a specific provider to use for this model.",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Voyage AI API Key",
+		"voyageApiKeyPlaceholder": "Enter your Voyage AI API key",
 		"openaiCompatibleProvider": "OpenAI Compatible",
 		"openaiCompatibleResponsesProvider": "OpenAI Compatible (Responses)",
 		"openAiKeyLabel": "OpenAI API Key",
@@ -193,6 +196,7 @@
 			"bedrockRegionRequired": "AWS region is required",
 			"bedrockProfileRequired": "AWS profile is required",
 			"openRouterApiKeyRequired": "OpenRouter API key is required",
+			"voyageApiKeyRequired": "Voyage AI API key is required",
 			"ollamaBaseUrlRequired": "Ollama base URL is required",
 			"baseUrlRequired": "Base URL is required",
 			"modelDimensionMinValue": "Model dimension must be greater than 0"

+ 5 - 1
webview-ui/src/i18n/locales/es/settings.json

@@ -109,6 +109,9 @@
 		"mistralProvider": "Mistral",
 		"mistralApiKeyLabel": "Clave API:",
 		"mistralApiKeyPlaceholder": "Introduce tu clave de API de Mistral",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Clave API de Voyage AI",
+		"voyageApiKeyPlaceholder": "Introduce tu clave de API de Voyage AI",
 		"openaiCompatibleProvider": "Compatible con OpenAI",
 		"openaiCompatibleResponsesProvider": "Compatible con OpenAI (Responses)",
 		"openAiKeyLabel": "Clave API de OpenAI",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "Se requiere la URL base de Ollama",
 			"baseUrlRequired": "Se requiere la URL base",
 			"modelDimensionMinValue": "La dimensión del modelo debe ser mayor que 0",
-			"openRouterApiKeyRequired": "Se requiere la clave API de OpenRouter"
+			"openRouterApiKeyRequired": "Se requiere la clave API de OpenRouter",
+			"voyageApiKeyRequired": "Se requiere la clave API de Voyage AI"
 		},
 		"optional": "opcional",
 		"advancedConfigLabel": "Configuración avanzada",

+ 5 - 1
webview-ui/src/i18n/locales/fr/settings.json

@@ -109,6 +109,9 @@
 		"mistralProvider": "Mistral",
 		"mistralApiKeyLabel": "Clé d'API:",
 		"mistralApiKeyPlaceholder": "Entrez votre clé API Mistral",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Clé API Voyage AI",
+		"voyageApiKeyPlaceholder": "Entre ta clé API Voyage AI",
 		"openaiCompatibleProvider": "Compatible OpenAI",
 		"openaiCompatibleResponsesProvider": "Compatible OpenAI (Responses)",
 		"openAiKeyLabel": "Clé API OpenAI",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "L'URL de base Ollama est requise",
 			"baseUrlRequired": "L'URL de base est requise",
 			"modelDimensionMinValue": "La dimension du modèle doit être supérieure à 0",
-			"openRouterApiKeyRequired": "Clé API OpenRouter est requise"
+			"openRouterApiKeyRequired": "Clé API OpenRouter est requise",
+			"voyageApiKeyRequired": "Clé API Voyage AI est requise"
 		},
 		"optional": "optionnel",
 		"advancedConfigLabel": "Configuration avancée",

+ 5 - 1
webview-ui/src/i18n/locales/hi/settings.json

@@ -104,6 +104,9 @@
 		"mistralProvider": "Mistral",
 		"mistralApiKeyLabel": "API कुंजी:",
 		"mistralApiKeyPlaceholder": "अपनी मिस्ट्रल एपीआई कुंजी दर्ज करें",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Voyage AI API कुंजी",
+		"voyageApiKeyPlaceholder": "अपनी Voyage AI API कुंजी दर्ज करें",
 		"openaiCompatibleProvider": "OpenAI संगत",
 		"openaiCompatibleResponsesProvider": "OpenAI संगत (Responses)",
 		"openAiKeyLabel": "OpenAI API कुंजी",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "Ollama आधार URL आवश्यक है",
 			"baseUrlRequired": "आधार URL आवश्यक है",
 			"modelDimensionMinValue": "मॉडल आयाम 0 से बड़ा होना चाहिए",
-			"openRouterApiKeyRequired": "OpenRouter API कुंजी आवश्यक है"
+			"openRouterApiKeyRequired": "OpenRouter API कुंजी आवश्यक है",
+			"voyageApiKeyRequired": "Voyage AI API कुंजी आवश्यक है"
 		},
 		"optional": "वैकल्पिक",
 		"advancedConfigLabel": "उन्नत कॉन्फ़िगरेशन",

+ 5 - 1
webview-ui/src/i18n/locales/id/settings.json

@@ -104,6 +104,9 @@
 		"mistralProvider": "Mistral",
 		"mistralApiKeyLabel": "Kunci API:",
 		"mistralApiKeyPlaceholder": "Masukkan kunci API Mistral Anda",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Kunci API Voyage AI",
+		"voyageApiKeyPlaceholder": "Masukkan kunci API Voyage AI kamu",
 		"openaiCompatibleProvider": "OpenAI Compatible",
 		"openaiCompatibleResponsesProvider": "OpenAI Compatible (Responses)",
 		"openAiKeyLabel": "OpenAI API Key",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "URL dasar Ollama diperlukan",
 			"baseUrlRequired": "URL dasar diperlukan",
 			"modelDimensionMinValue": "Dimensi model harus lebih besar dari 0",
-			"openRouterApiKeyRequired": "Kunci API OpenRouter diperlukan"
+			"openRouterApiKeyRequired": "Kunci API OpenRouter diperlukan",
+			"voyageApiKeyRequired": "Kunci API Voyage AI diperlukan"
 		},
 		"optional": "opsional",
 		"advancedConfigLabel": "Konfigurasi Lanjutan",

+ 5 - 1
webview-ui/src/i18n/locales/it/settings.json

@@ -104,6 +104,9 @@
 		"mistralProvider": "Mistral",
 		"mistralApiKeyLabel": "Chiave API:",
 		"mistralApiKeyPlaceholder": "Inserisci la tua chiave API Mistral",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Chiave API Voyage AI",
+		"voyageApiKeyPlaceholder": "Inserisci la tua chiave API Voyage AI",
 		"openaiCompatibleProvider": "Compatibile con OpenAI",
 		"openaiCompatibleResponsesProvider": "Compatibile con OpenAI (Responses)",
 		"openAiKeyLabel": "Chiave API OpenAI",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "È richiesto l'URL di base di Ollama",
 			"baseUrlRequired": "È richiesto l'URL di base",
 			"modelDimensionMinValue": "La dimensione del modello deve essere maggiore di 0",
-			"openRouterApiKeyRequired": "Chiave API OpenRouter è richiesta"
+			"openRouterApiKeyRequired": "Chiave API OpenRouter è richiesta",
+			"voyageApiKeyRequired": "Chiave API Voyage AI è richiesta"
 		},
 		"optional": "opzionale",
 		"advancedConfigLabel": "Configurazione avanzata",

+ 5 - 1
webview-ui/src/i18n/locales/ja/settings.json

@@ -104,6 +104,9 @@
 		"mistralProvider": "Mistral",
 		"mistralApiKeyLabel": "APIキー:",
 		"mistralApiKeyPlaceholder": "Mistral APIキーを入力してください",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Voyage AI APIキー",
+		"voyageApiKeyPlaceholder": "Voyage AI APIキーを入力してください",
 		"openaiCompatibleProvider": "OpenAI互換",
 		"openaiCompatibleResponsesProvider": "OpenAI互換 (Responses)",
 		"openAiKeyLabel": "OpenAI APIキー",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "OllamaのベースURLが必要です",
 			"baseUrlRequired": "ベースURLが必要です",
 			"modelDimensionMinValue": "モデルの次元は0より大きくなければなりません",
-			"openRouterApiKeyRequired": "OpenRouter APIキーが必要です"
+			"openRouterApiKeyRequired": "OpenRouter APIキーが必要です",
+			"voyageApiKeyRequired": "Voyage AI APIキーが必要です"
 		},
 		"optional": "オプション",
 		"advancedConfigLabel": "詳細設定",

+ 5 - 1
webview-ui/src/i18n/locales/ko/settings.json

@@ -104,6 +104,9 @@
 		"openRouterApiKeyPlaceholder": "OpenRouter API 키를 입력하세요",
 		"openRouterProviderRoutingLabel": "OpenRouter 공급자 라우팅",
 		"openRouterProviderRoutingDescription": "OpenRouter는 임베딩 모델에 가장 적합한 공급자로 요청을 라우팅합니다. 기본적으로 요청은 가동 시간을 최대화하기 위해 상위 공급자 간에 로드 밸런싱됩니다. 그러나 이 모델에 사용할 특정 공급자를 선택할 수 있습니다.",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Voyage AI API 키",
+		"voyageApiKeyPlaceholder": "Voyage AI API 키를 입력하세요",
 		"openaiCompatibleProvider": "OpenAI 호환",
 		"openaiCompatibleResponsesProvider": "OpenAI 호환 (Responses)",
 		"openAiKeyLabel": "OpenAI API 키",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "Ollama 기본 URL이 필요합니다",
 			"baseUrlRequired": "기본 URL이 필요합니다",
 			"modelDimensionMinValue": "모델 차원은 0보다 커야 합니다",
-			"openRouterApiKeyRequired": "OpenRouter API 키가 필요합니다"
+			"openRouterApiKeyRequired": "OpenRouter API 키가 필요합니다",
+			"voyageApiKeyRequired": "Voyage AI API 키가 필요합니다"
 		},
 		"optional": "선택 사항",
 		"advancedConfigLabel": "고급 구성",

+ 5 - 1
webview-ui/src/i18n/locales/nl/settings.json

@@ -104,6 +104,9 @@
 		"mistralProvider": "Mistral",
 		"mistralApiKeyLabel": "API-sleutel:",
 		"mistralApiKeyPlaceholder": "Voer uw Mistral API-sleutel in",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Voyage AI API-sleutel",
+		"voyageApiKeyPlaceholder": "Voer je Voyage AI API-sleutel in",
 		"openaiCompatibleProvider": "OpenAI-compatibel",
 		"openaiCompatibleResponsesProvider": "OpenAI-compatibel (Responses)",
 		"openAiKeyLabel": "OpenAI API-sleutel",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "Ollama basis-URL is vereist",
 			"baseUrlRequired": "Basis-URL is vereist",
 			"modelDimensionMinValue": "Modelafmeting moet groter zijn dan 0",
-			"openRouterApiKeyRequired": "OpenRouter API-sleutel is vereist"
+			"openRouterApiKeyRequired": "OpenRouter API-sleutel is vereist",
+			"voyageApiKeyRequired": "Voyage AI API-sleutel is vereist"
 		},
 		"optional": "optioneel",
 		"advancedConfigLabel": "Geavanceerde configuratie",

+ 5 - 1
webview-ui/src/i18n/locales/pl/settings.json

@@ -104,6 +104,9 @@
 		"openRouterApiKeyPlaceholder": "Wprowadź swój klucz API OpenRouter",
 		"openRouterProviderRoutingLabel": "Routing dostawców OpenRouter",
 		"openRouterProviderRoutingDescription": "OpenRouter kieruje żądania do najlepszych dostępnych dostawców dla Twojego modelu osadzania. Domyślnie żądania są równoważone między najlepszymi dostawcami, aby zmaksymalizować czas działania. Możesz jednak wybrać konkretnego dostawcę do użycia z tym modelem.",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Klucz API Voyage AI",
+		"voyageApiKeyPlaceholder": "Wprowadź swój klucz API Voyage AI",
 		"openaiCompatibleProvider": "Kompatybilny z OpenAI",
 		"openaiCompatibleResponsesProvider": "Kompatybilny z OpenAI (Responses)",
 		"openAiKeyLabel": "Klucz API OpenAI",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "Wymagany jest bazowy adres URL Ollama",
 			"baseUrlRequired": "Wymagany jest bazowy adres URL",
 			"modelDimensionMinValue": "Wymiar modelu musi być większy niż 0",
-			"openRouterApiKeyRequired": "Wymagany jest klucz API OpenRouter"
+			"openRouterApiKeyRequired": "Wymagany jest klucz API OpenRouter",
+			"voyageApiKeyRequired": "Wymagany jest klucz API Voyage AI"
 		},
 		"optional": "opcjonalny",
 		"advancedConfigLabel": "Konfiguracja zaawansowana",

+ 5 - 1
webview-ui/src/i18n/locales/pt-BR/settings.json

@@ -104,6 +104,9 @@
 		"mistralProvider": "Mistral",
 		"mistralApiKeyLabel": "Chave de API:",
 		"mistralApiKeyPlaceholder": "Digite sua chave de API da Mistral",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Chave de API Voyage AI",
+		"voyageApiKeyPlaceholder": "Digite sua chave de API da Voyage AI",
 		"openaiCompatibleProvider": "Compatível com OpenAI",
 		"openaiCompatibleResponsesProvider": "Compatível com OpenAI (Responses)",
 		"openAiKeyLabel": "Chave de API OpenAI",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "A URL base do Ollama é obrigatória",
 			"baseUrlRequired": "A URL base é obrigatória",
 			"modelDimensionMinValue": "A dimensão do modelo deve ser maior que 0",
-			"openRouterApiKeyRequired": "Chave API do OpenRouter é obrigatória"
+			"openRouterApiKeyRequired": "Chave API do OpenRouter é obrigatória",
+			"voyageApiKeyRequired": "Chave de API da Voyage AI é obrigatória"
 		},
 		"optional": "opcional",
 		"advancedConfigLabel": "Configuração Avançada",

+ 5 - 1
webview-ui/src/i18n/locales/ru/settings.json

@@ -104,6 +104,9 @@
 		"mistralProvider": "Mistral",
 		"mistralApiKeyLabel": "Ключ API:",
 		"mistralApiKeyPlaceholder": "Введите свой API-ключ Mistral",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "API-ключ Voyage AI",
+		"voyageApiKeyPlaceholder": "Введи свой API-ключ Voyage AI",
 		"openaiCompatibleProvider": "OpenAI-совместимый",
 		"openaiCompatibleResponsesProvider": "OpenAI-совместимый (Responses)",
 		"openAiKeyLabel": "Ключ API OpenAI",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "Требуется базовый URL Ollama",
 			"baseUrlRequired": "Требуется базовый URL",
 			"modelDimensionMinValue": "Размерность модели должна быть больше 0",
-			"openRouterApiKeyRequired": "Требуется ключ API OpenRouter"
+			"openRouterApiKeyRequired": "Требуется ключ API OpenRouter",
+			"voyageApiKeyRequired": "Требуется API-ключ Voyage AI"
 		},
 		"optional": "необязательно",
 		"advancedConfigLabel": "Расширенная конфигурация",

+ 4 - 0
webview-ui/src/i18n/locales/sk/settings.json

@@ -123,6 +123,9 @@
 		"openRouterApiKeyPlaceholder": "Zadajte svoj kľúč API OpenRouter",
 		"openRouterProviderRoutingLabel": "Smerovanie poskytovateľa OpenRouter",
 		"openRouterProviderRoutingDescription": "OpenRouter smeruje požiadavky na najlepších dostupných poskytovateľov pre váš model vkladania. V predvolenom nastavení sú požiadavky vyrovnávané záťažou medzi najlepších poskytovateľov, aby sa maximalizovala doba prevádzky. Môžete si však vybrať konkrétneho poskytovateľa, ktorého chcete pre tento model použiť.",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "API kľúč Voyage AI",
+		"voyageApiKeyPlaceholder": "Zadaj svoj API kľúč Voyage AI",
 		"openaiCompatibleProvider": "Kompatibilný s OpenAI",
 		"openaiCompatibleResponsesProvider": "Kompatibilný s OpenAI (Responses)",
 		"openAiKeyLabel": "Kľúč API OpenAI",
@@ -195,6 +198,7 @@
 			"mistralApiKeyRequired": "Kľúč API Mistral je povinný",
 			"vercelAiGatewayApiKeyRequired": "Je vyžadovaný kľúč API Vercel AI Gateway",
 			"openRouterApiKeyRequired": "Kľúč API OpenRouter je povinný",
+			"voyageApiKeyRequired": "API kľúč Voyage AI je povinný",
 			"ollamaBaseUrlRequired": "Základná URL Ollama je povinná",
 			"baseUrlRequired": "Základná URL je povinná",
 			"modelDimensionMinValue": "Dimenzia modelu musí byť väčšia ako 0",

+ 4 - 0
webview-ui/src/i18n/locales/th/settings.json

@@ -137,6 +137,9 @@
 		"openRouterApiKeyPlaceholder": "ป้อนคีย์ API OpenRouter ของคุณ",
 		"openRouterProviderRoutingLabel": "การกำหนดเส้นทางผู้ให้บริการ OpenRouter",
 		"openRouterProviderRoutingDescription": "OpenRouter กำหนดเส้นทางคำขอไปยังผู้ให้บริการที่ดีที่สุดสำหรับโมเดล embedding ของคุณ โดยค่าเริ่มต้น คำขอจะถูกกระจายโหลดไปยังผู้ให้บริการชั้นนำเพื่อเพิ่มเวลาทำงานสูงสุด อย่างไรก็ตาม คุณสามารถเลือกผู้ให้บริการเฉพาะสำหรับโมเดลนี้ได้",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "คีย์ API Voyage AI",
+		"voyageApiKeyPlaceholder": "ป้อนคีย์ API Voyage AI ของคุณ",
 		"openaiCompatibleProvider": "เข้ากันได้กับ OpenAI",
 		"openaiCompatibleResponsesProvider": "เข้ากันได้กับ OpenAI (Responses)",
 		"openAiKeyLabel": "คีย์ API OpenAI",
@@ -209,6 +212,7 @@
 			"geminiApiKeyRequired": "จำเป็นต้องมีคีย์ API Gemini",
 			"mistralApiKeyRequired": "จำเป็นต้องมีคีย์ API Mistral",
 			"openRouterApiKeyRequired": "จำเป็นต้องมีคีย์ API OpenRouter",
+			"voyageApiKeyRequired": "จำเป็นต้องมีคีย์ API Voyage AI",
 			"ollamaBaseUrlRequired": "จำเป็นต้องมี URL พื้นฐาน Ollama",
 			"baseUrlRequired": "จำเป็นต้องมี URL พื้นฐาน",
 			"modelDimensionMinValue": "มิติโมเดลต้องมากกว่า 0",

+ 5 - 1
webview-ui/src/i18n/locales/tr/settings.json

@@ -104,6 +104,9 @@
 		"openRouterApiKeyPlaceholder": "OpenRouter API anahtarınızı girin",
 		"openRouterProviderRoutingLabel": "OpenRouter Sağlayıcı Yönlendirmesi",
 		"openRouterProviderRoutingDescription": "OpenRouter, gömme modeliniz için mevcut en iyi sağlayıcılara istekleri yönlendirir. Varsayılan olarak, istekler çalışma süresini en üst düzeye çıkarmak için en iyi sağlayıcılar arasında dengelenir. Ancak, bu model için kullanılacak belirli bir sağlayıcı seçebilirsiniz.",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Voyage AI API Anahtarı",
+		"voyageApiKeyPlaceholder": "Voyage AI API anahtarını gir",
 		"openaiCompatibleProvider": "OpenAI Uyumlu",
 		"openaiCompatibleResponsesProvider": "OpenAI Uyumlu (Responses)",
 		"openAiKeyLabel": "OpenAI API Anahtarı",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "Ollama temel URL'si gereklidir",
 			"baseUrlRequired": "Temel URL'si gereklidir",
 			"modelDimensionMinValue": "Model boyutu 0'dan büyük olmalıdır",
-			"openRouterApiKeyRequired": "OpenRouter API anahtarı gereklidir"
+			"openRouterApiKeyRequired": "OpenRouter API anahtarı gereklidir",
+			"voyageApiKeyRequired": "Voyage AI API anahtarı gereklidir"
 		},
 		"optional": "isteğe bağlı",
 		"advancedConfigLabel": "Gelişmiş Yapılandırma",

+ 4 - 0
webview-ui/src/i18n/locales/uk/settings.json

@@ -137,6 +137,9 @@
 		"openRouterApiKeyPlaceholder": "Введіть ваш ключ API OpenRouter",
 		"openRouterProviderRoutingLabel": "Маршрутизація провайдера OpenRouter",
 		"openRouterProviderRoutingDescription": "OpenRouter направляє запити до найкращих доступних провайдерів для вашої моделі вбудовувань. За замовчуванням запити розподіляються між провідними провайдерами для максимального часу безвідмовної роботи. Однак ви можете вибрати конкретного провайдера для використання цієї моделі.",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "API ключ Voyage AI",
+		"voyageApiKeyPlaceholder": "Введи свій API ключ Voyage AI",
 		"openaiCompatibleProvider": "Сумісний з OpenAI",
 		"openaiCompatibleResponsesProvider": "Сумісний з OpenAI (Responses)",
 		"openAiKeyLabel": "Ключ API OpenAI",
@@ -218,6 +221,7 @@
 			"modelDimensionMinValue": "Розмірність моделі повинна бути більше 0",
 			"vercelAiGatewayApiKeyRequired": "Ключ API Vercel AI Gateway є обов'язковим",
 			"openRouterApiKeyRequired": "Ключ API OpenRouter є обов'язковим",
+			"voyageApiKeyRequired": "Ключ API Voyage AI є обов'язковим",
 			"bedrockRegionRequired": "Регіон AWS є обов'язковим",
 			"bedrockProfileRequired": "Профіль AWS є обов'язковий"
 		},

+ 5 - 1
webview-ui/src/i18n/locales/vi/settings.json

@@ -104,6 +104,9 @@
 		"openRouterApiKeyPlaceholder": "Nhập khóa API OpenRouter của bạn",
 		"openRouterProviderRoutingLabel": "Định tuyến nhà cung cấp OpenRouter",
 		"openRouterProviderRoutingDescription": "OpenRouter chuyển hướng yêu cầu đến các nhà cung cấp tốt nhất hiện có cho mô hình nhúng của bạn. Theo mặc định, các yêu cầu được cân bằng giữa các nhà cung cấp hàng đầu để tối đa hóa thời gian hoạt động. Tuy nhiên, bạn có thể chọn một nhà cung cấp cụ thể để sử dụng cho mô hình này.",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Khóa API Voyage AI",
+		"voyageApiKeyPlaceholder": "Nhập khóa API Voyage AI của bạn",
 		"openaiCompatibleProvider": "Tương thích OpenAI",
 		"openaiCompatibleResponsesProvider": "Tương thích OpenAI (Responses)",
 		"openAiKeyLabel": "Khóa API OpenAI",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "Yêu cầu URL cơ sở Ollama",
 			"baseUrlRequired": "Yêu cầu URL cơ sở",
 			"modelDimensionMinValue": "Kích thước mô hình phải lớn hơn 0",
-			"openRouterApiKeyRequired": "Yêu cầu khóa API OpenRouter"
+			"openRouterApiKeyRequired": "Yêu cầu khóa API OpenRouter",
+			"voyageApiKeyRequired": "Yêu cầu khóa API Voyage AI"
 		},
 		"optional": "tùy chọn",
 		"advancedConfigLabel": "Cấu hình nâng cao",

+ 5 - 1
webview-ui/src/i18n/locales/zh-CN/settings.json

@@ -109,6 +109,9 @@
 		"mistralProvider": "Mistral",
 		"mistralApiKeyLabel": "API 密钥:",
 		"mistralApiKeyPlaceholder": "输入您的 Mistral API 密钥",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Voyage AI API 密钥",
+		"voyageApiKeyPlaceholder": "输入你的 Voyage AI API 密钥",
 		"openaiCompatibleProvider": "OpenAI 兼容",
 		"openaiCompatibleResponsesProvider": "OpenAI 兼容 (Responses)",
 		"openAiKeyLabel": "OpenAI API 密钥",
@@ -178,7 +181,8 @@
 			"ollamaBaseUrlRequired": "需要 Ollama 基础 URL",
 			"baseUrlRequired": "需要基础 URL",
 			"modelDimensionMinValue": "模型维度必须大于 0",
-			"openRouterApiKeyRequired": "OpenRouter API 密钥是必需的"
+			"openRouterApiKeyRequired": "OpenRouter API 密钥是必需的",
+			"voyageApiKeyRequired": "Voyage AI API 密钥是必需的"
 		},
 		"optional": "可选",
 		"advancedConfigLabel": "高级配置",

+ 4 - 0
webview-ui/src/i18n/locales/zh-TW/settings.json

@@ -119,6 +119,9 @@
 		"openRouterApiKeyPlaceholder": "輸入您的 OpenRouter API 金鑰",
 		"openRouterProviderRoutingLabel": "OpenRouter 供應商路由",
 		"openRouterProviderRoutingDescription": "OpenRouter 會將請求路由到適合您嵌入模型的最佳可用供應商。預設情況下,請求會在頂尖供應商之間進行負載平衡以最大化正常運作時間。您也可以為此模型選擇特定的供應商。",
+		"voyageProvider": "Voyage AI",
+		"voyageApiKeyLabel": "Voyage AI API 金鑰",
+		"voyageApiKeyPlaceholder": "輸入你的 Voyage AI API 金鑰",
 		"openaiCompatibleProvider": "OpenAI 相容",
 		"openaiCompatibleResponsesProvider": "OpenAI 相容 (Responses)",
 		"openAiKeyLabel": "OpenAI API 金鑰",
@@ -186,6 +189,7 @@
 			"bedrockRegionRequired": "AWS 區域必填",
 			"bedrockProfileRequired": "AWS Profile 必填",
 			"openRouterApiKeyRequired": "OpenRouter API 金鑰必填",
+			"voyageApiKeyRequired": "Voyage AI API 金鑰必填",
 			"ollamaBaseUrlRequired": "需要 Ollama 基礎 URL",
 			"baseUrlRequired": "需要基礎 URL",
 			"modelDimensionMinValue": "模型維度必須大於 0"