diff --git a/src/core/config/__tests__/importExport.spec.ts b/src/core/config/__tests__/importExport.spec.ts index 052bfc77f8..361d6b23b0 100644 --- a/src/core/config/__tests__/importExport.spec.ts +++ b/src/core/config/__tests__/importExport.spec.ts @@ -628,7 +628,7 @@ describe("importExport", () => { codebaseIndexEmbedderBaseUrl: "http://localhost:11434", // Wrong URL from Ollama // OpenAI Compatible settings are now stored directly in codebaseIndexConfig codebaseIndexOpenAiCompatibleBaseUrl: "https://custom-openai-api.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: 1536, + codebaseIndexEmbedderModelDimension: 1536, }, } @@ -673,7 +673,7 @@ describe("importExport", () => { codebaseIndexEmbedderBaseUrl: "", // OpenAI Compatible settings are now stored directly in codebaseIndexConfig codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: 768, + codebaseIndexEmbedderModelDimension: 768, }, } @@ -688,9 +688,7 @@ describe("importExport", () => { const exportedData = (safeWriteJson as Mock).mock.calls[0][1] // Settings are now exported as-is from codebaseIndexConfig - expect( - exportedData.globalSettings.codebaseIndexConfig.codebaseIndexOpenAiCompatibleModelDimension, - ).toBe(768) + expect(exportedData.globalSettings.codebaseIndexConfig.codebaseIndexEmbedderModelDimension).toBe(768) expect(exportedData.globalSettings.codebaseIndexConfig.codebaseIndexOpenAiCompatibleBaseUrl).toBe( "https://api.example.com/v1", ) @@ -731,7 +729,7 @@ describe("importExport", () => { codebaseIndexEmbedderBaseUrl: "http://localhost:11434", // Wrong URL from Ollama // OpenAI Compatible settings are now stored directly in codebaseIndexConfig codebaseIndexOpenAiCompatibleBaseUrl: "https://openai-compatible.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: 1536, + codebaseIndexEmbedderModelDimension: 1536, }, } @@ -749,9 +747,7 @@ describe("importExport", () => { expect(exportedData.globalSettings.codebaseIndexConfig.codebaseIndexOpenAiCompatibleBaseUrl).toBe( "https://openai-compatible.example.com/v1", ) - expect( - exportedData.globalSettings.codebaseIndexConfig.codebaseIndexOpenAiCompatibleModelDimension, - ).toBe(1536) + expect(exportedData.globalSettings.codebaseIndexConfig.codebaseIndexEmbedderModelDimension).toBe(1536) // The generic embedder base URL is still there expect(exportedData.globalSettings.codebaseIndexConfig.codebaseIndexEmbedderBaseUrl).toBe( "http://localhost:11434", @@ -921,7 +917,6 @@ describe("importExport", () => { codebaseIndexEmbedderModelDimension: 1536, // OpenAI Compatible settings are now stored directly here codebaseIndexOpenAiCompatibleBaseUrl: "https://imported-url.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: 1536, }, }, }) @@ -956,7 +951,7 @@ describe("importExport", () => { expect.objectContaining({ codebaseIndexConfig: expect.objectContaining({ codebaseIndexOpenAiCompatibleBaseUrl: "https://imported-url.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: 1536, + codebaseIndexEmbedderModelDimension: 1536, }), }), ) @@ -1105,7 +1100,6 @@ describe("importExport", () => { codebaseIndexEmbedderModelDimension: testModelDimension, // OpenAI Compatible settings are now stored directly in codebaseIndexConfig codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: testModelDimension, }, } @@ -1160,7 +1154,7 @@ describe("importExport", () => { // Step 9: Verify that the model dimension was preserved exactly in global settings const importedGlobalSettings = mockContextProxy.setValues.mock.calls[0][0] - expect(importedGlobalSettings.codebaseIndexConfig?.codebaseIndexOpenAiCompatibleModelDimension).toBe( + expect(importedGlobalSettings.codebaseIndexConfig?.codebaseIndexEmbedderModelDimension).toBe( testModelDimension, ) expect(importedGlobalSettings.codebaseIndexConfig?.codebaseIndexOpenAiCompatibleBaseUrl).toBe( @@ -1198,7 +1192,7 @@ describe("importExport", () => { codebaseIndexEmbedderBaseUrl: "https://api.example.com/v1", // OpenAI Compatible settings are now stored directly in codebaseIndexConfig codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: testModelDimension, // 0 is a valid value + codebaseIndexEmbedderModelDimension: testModelDimension, // 0 is a valid value }, } @@ -1219,7 +1213,7 @@ describe("importExport", () => { // Verify the exported data includes the model dimension even when it's 0 const exportedData = (safeWriteJson as Mock).mock.calls[0][1] - expect(exportedData.globalSettings.codebaseIndexConfig.codebaseIndexOpenAiCompatibleModelDimension).toBe(0) + expect(exportedData.globalSettings.codebaseIndexConfig.codebaseIndexEmbedderModelDimension).toBe(0) // Test import roundtrip const exportedFileContent = JSON.stringify(exportedData) @@ -1247,7 +1241,7 @@ describe("importExport", () => { // Verify that model dimension 0 was preserved in global settings const setValuesCall = mockContextProxy.setValues.mock.calls[0][0] - expect(setValuesCall.codebaseIndexConfig?.codebaseIndexOpenAiCompatibleModelDimension).toBe(0) + expect(setValuesCall.codebaseIndexConfig?.codebaseIndexEmbedderModelDimension).toBe(0) }) it("should handle missing model dimension gracefully", async () => { diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 219e52974e..08dbeabfc1 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -1967,8 +1967,8 @@ export const webviewMessageHandler = async ( codebaseIndexEmbedderProvider: settings.codebaseIndexEmbedderProvider, codebaseIndexEmbedderBaseUrl: settings.codebaseIndexEmbedderBaseUrl, codebaseIndexEmbedderModelId: settings.codebaseIndexEmbedderModelId, + codebaseIndexEmbedderModelDimension: settings.codebaseIndexEmbedderModelDimension, // Generic dimension codebaseIndexOpenAiCompatibleBaseUrl: settings.codebaseIndexOpenAiCompatibleBaseUrl, - codebaseIndexOpenAiCompatibleModelDimension: settings.codebaseIndexOpenAiCompatibleModelDimension, codebaseIndexSearchMaxResults: settings.codebaseIndexSearchMaxResults, codebaseIndexSearchMinScore: settings.codebaseIndexSearchMinScore, } diff --git a/src/i18n/locales/ca/embeddings.json b/src/i18n/locales/ca/embeddings.json index 35be4089d4..1d3c5f2476 100644 --- a/src/i18n/locales/ca/embeddings.json +++ b/src/i18n/locales/ca/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "URL base no vàlida. Comproveu la vostra configuració d'URL.", "invalidModel": "Model no vàlid. Comproveu la vostra configuració de model.", "invalidResponse": "Resposta no vàlida del servei d'incrustació. Comproveu la vostra configuració." + }, + "serviceFactory": { + "openAiConfigMissing": "Falta la configuració d'OpenAI per crear l'embedder", + "ollamaConfigMissing": "Falta la configuració d'Ollama per crear l'embedder", + "openAiCompatibleConfigMissing": "Falta la configuració compatible amb OpenAI per crear l'embedder", + "geminiConfigMissing": "Falta la configuració de Gemini 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ó.", + "qdrantUrlMissing": "Falta l'URL de Qdrant per crear l'emmagatzematge de vectors", + "codeIndexingNotConfigured": "No es poden crear serveis: La indexació de codi no està configurada correctament" } } diff --git a/src/i18n/locales/de/embeddings.json b/src/i18n/locales/de/embeddings.json index 7d96ddb511..f4abcb3e15 100644 --- a/src/i18n/locales/de/embeddings.json +++ b/src/i18n/locales/de/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "Ungültige Basis-URL. Bitte überprüfe deine URL-Konfiguration.", "invalidModel": "Ungültiges Modell. Bitte überprüfe deine Modellkonfiguration.", "invalidResponse": "Ungültige Antwort vom Embedder-Dienst. Bitte überprüfe deine Konfiguration." + }, + "serviceFactory": { + "openAiConfigMissing": "OpenAI-Konfiguration fehlt für die Erstellung des Embedders", + "ollamaConfigMissing": "Ollama-Konfiguration fehlt für die Erstellung des Embedders", + "openAiCompatibleConfigMissing": "OpenAI-kompatible Konfiguration fehlt für die Erstellung des Embedders", + "geminiConfigMissing": "Gemini-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.", + "qdrantUrlMissing": "Qdrant-URL fehlt für die Erstellung des Vektorspeichers", + "codeIndexingNotConfigured": "Kann keine Dienste erstellen: Code-Indizierung ist nicht richtig konfiguriert" } } diff --git a/src/i18n/locales/en/embeddings.json b/src/i18n/locales/en/embeddings.json index 012b2323cf..b2ed2a64c4 100644 --- a/src/i18n/locales/en/embeddings.json +++ b/src/i18n/locales/en/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "Invalid base URL. Please check your URL configuration.", "invalidModel": "Invalid model. Please check your model configuration.", "invalidResponse": "Invalid response from embedder service. Please check your configuration." + }, + "serviceFactory": { + "openAiConfigMissing": "OpenAI configuration missing for embedder creation", + "ollamaConfigMissing": "Ollama configuration missing for embedder creation", + "openAiCompatibleConfigMissing": "OpenAI Compatible configuration missing for embedder creation", + "geminiConfigMissing": "Gemini 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.", + "qdrantUrlMissing": "Qdrant URL missing for vector store creation", + "codeIndexingNotConfigured": "Cannot create services: Code indexing is not properly configured" } } diff --git a/src/i18n/locales/es/embeddings.json b/src/i18n/locales/es/embeddings.json index 5fa46f9c45..8cb0dd7f1f 100644 --- a/src/i18n/locales/es/embeddings.json +++ b/src/i18n/locales/es/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "URL base no válida. Comprueba la configuración de tu URL.", "invalidModel": "Modelo no válido. Comprueba la configuración de tu modelo.", "invalidResponse": "Respuesta no válida del servicio de embedder. Comprueba tu configuración." + }, + "serviceFactory": { + "openAiConfigMissing": "Falta la configuración de OpenAI para crear el incrustador", + "ollamaConfigMissing": "Falta la configuración de Ollama para crear el incrustador", + "openAiCompatibleConfigMissing": "Falta la configuración compatible con OpenAI para crear el incrustador", + "geminiConfigMissing": "Falta la configuración de Gemini para crear el 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.", + "qdrantUrlMissing": "Falta la URL de Qdrant para crear el almacén de vectores", + "codeIndexingNotConfigured": "No se pueden crear servicios: La indexación de código no está configurada correctamente" } } diff --git a/src/i18n/locales/fr/embeddings.json b/src/i18n/locales/fr/embeddings.json index b6ef0d8786..23d70650e8 100644 --- a/src/i18n/locales/fr/embeddings.json +++ b/src/i18n/locales/fr/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "URL de base invalide. Veuillez vérifier votre configuration d'URL.", "invalidModel": "Modèle invalide. Veuillez vérifier votre configuration de modèle.", "invalidResponse": "Réponse invalide du service d'embedder. Veuillez vérifier votre configuration." + }, + "serviceFactory": { + "openAiConfigMissing": "Configuration OpenAI manquante pour la création de l'embedder", + "ollamaConfigMissing": "Configuration Ollama manquante pour la création de l'embedder", + "openAiCompatibleConfigMissing": "Configuration compatible OpenAI manquante pour la création de l'embedder", + "geminiConfigMissing": "Configuration Gemini 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.", + "qdrantUrlMissing": "URL Qdrant manquante pour la création du stockage de vecteurs", + "codeIndexingNotConfigured": "Impossible de créer les services : L'indexation du code n'est pas correctement configurée" } } diff --git a/src/i18n/locales/hi/embeddings.json b/src/i18n/locales/hi/embeddings.json index 5ec34e5624..e6a0aa2bbc 100644 --- a/src/i18n/locales/hi/embeddings.json +++ b/src/i18n/locales/hi/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "अमान्य बेस यूआरएल। कृपया अपनी यूआरएल कॉन्फ़िगरेशन जांचें।", "invalidModel": "अमान्य मॉडल। कृपया अपनी मॉडल कॉन्फ़िगरेशन जांचें।", "invalidResponse": "एम्बेडर सेवा से अमान्य प्रतिक्रिया। कृपया अपनी कॉन्फ़िगरेशन जांचें।" + }, + "serviceFactory": { + "openAiConfigMissing": "एम्बेडर बनाने के लिए OpenAI कॉन्फ़िगरेशन गायब है", + "ollamaConfigMissing": "एम्बेडर बनाने के लिए Ollama कॉन्फ़िगरेशन गायब है", + "openAiCompatibleConfigMissing": "एम्बेडर बनाने के लिए OpenAI संगत कॉन्फ़िगरेशन गायब है", + "geminiConfigMissing": "एम्बेडर बनाने के लिए Gemini कॉन्फ़िगरेशन गायब है", + "invalidEmbedderType": "अमान्य एम्बेडर प्रकार कॉन्फ़िगर किया गया: {{embedderProvider}}", + "vectorDimensionNotDeterminedOpenAiCompatible": "प्रदाता '{{provider}}' के साथ मॉडल '{{modelId}}' के लिए वेक्टर आयाम निर्धारित नहीं कर सका। कृपया सुनिश्चित करें कि OpenAI-संगत प्रदाता सेटिंग्स में 'एम्बेडिंग आयाम' सही तरीके से सेट है।", + "vectorDimensionNotDetermined": "प्रदाता '{{provider}}' के साथ मॉडल '{{modelId}}' के लिए वेक्टर आयाम निर्धारित नहीं कर सका। मॉडल प्रोफ़ाइल या कॉन्फ़िगरेशन की जांच करें।", + "qdrantUrlMissing": "वेक्टर स्टोर बनाने के लिए Qdrant URL गायब है", + "codeIndexingNotConfigured": "सेवाएं नहीं बना सकते: कोड इंडेक्सिंग ठीक से कॉन्फ़िगर नहीं है" } } diff --git a/src/i18n/locales/id/embeddings.json b/src/i18n/locales/id/embeddings.json index 0082ec8dcf..5ba042e7ef 100644 --- a/src/i18n/locales/id/embeddings.json +++ b/src/i18n/locales/id/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "URL dasar tidak valid. Silakan periksa konfigurasi URL Anda.", "invalidModel": "Model tidak valid. Silakan periksa konfigurasi model Anda.", "invalidResponse": "Respons tidak valid dari layanan embedder. Silakan periksa konfigurasi Anda." + }, + "serviceFactory": { + "openAiConfigMissing": "Konfigurasi OpenAI tidak ada untuk membuat embedder", + "ollamaConfigMissing": "Konfigurasi Ollama tidak ada untuk membuat embedder", + "openAiCompatibleConfigMissing": "Konfigurasi yang kompatibel dengan OpenAI tidak ada untuk membuat embedder", + "geminiConfigMissing": "Konfigurasi Gemini tidak ada untuk membuat 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.", + "qdrantUrlMissing": "URL Qdrant tidak ada untuk membuat penyimpanan vektor", + "codeIndexingNotConfigured": "Tidak dapat membuat layanan: Pengindeksan kode tidak dikonfigurasi dengan benar" } } diff --git a/src/i18n/locales/it/embeddings.json b/src/i18n/locales/it/embeddings.json index 19e6af332f..38f502ae78 100644 --- a/src/i18n/locales/it/embeddings.json +++ b/src/i18n/locales/it/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "URL di base non valido. Controlla la configurazione del tuo URL.", "invalidModel": "Modello non valido. Controlla la configurazione del tuo modello.", "invalidResponse": "Risposta non valida dal servizio embedder. Controlla la tua configurazione." + }, + "serviceFactory": { + "openAiConfigMissing": "Configurazione OpenAI mancante per la creazione dell'embedder", + "ollamaConfigMissing": "Configurazione Ollama mancante per la creazione dell'embedder", + "openAiCompatibleConfigMissing": "Configurazione compatibile con OpenAI mancante per la creazione dell'embedder", + "geminiConfigMissing": "Configurazione Gemini 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.", + "qdrantUrlMissing": "URL Qdrant mancante per la creazione dello storage vettoriale", + "codeIndexingNotConfigured": "Impossibile creare i servizi: L'indicizzazione del codice non è configurata correttamente" } } diff --git a/src/i18n/locales/ja/embeddings.json b/src/i18n/locales/ja/embeddings.json index fcf426a14c..817287cff9 100644 --- a/src/i18n/locales/ja/embeddings.json +++ b/src/i18n/locales/ja/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "無効なベースURLです。URL構成を確認してください。", "invalidModel": "無効なモデルです。モデル構成を確認してください。", "invalidResponse": "エンベッダーサービスからの無効な応答です。設定を確認してください。" + }, + "serviceFactory": { + "openAiConfigMissing": "エンベッダー作成のためのOpenAI設定がありません", + "ollamaConfigMissing": "エンベッダー作成のためのOllama設定がありません", + "openAiCompatibleConfigMissing": "エンベッダー作成のためのOpenAI互換設定がありません", + "geminiConfigMissing": "エンベッダー作成のためのGemini設定がありません", + "invalidEmbedderType": "無効なエンベッダータイプが設定されています: {{embedderProvider}}", + "vectorDimensionNotDeterminedOpenAiCompatible": "プロバイダー '{{provider}}' のモデル '{{modelId}}' の埋め込み次元を決定できませんでした。OpenAI互換プロバイダー設定で「埋め込み次元」が正しく設定されていることを確認してください。", + "vectorDimensionNotDetermined": "プロバイダー '{{provider}}' のモデル '{{modelId}}' の埋め込み次元を決定できませんでした。モデルプロファイルまたは設定を確認してください。", + "qdrantUrlMissing": "ベクターストア作成のためのQdrant URLがありません", + "codeIndexingNotConfigured": "サービスを作成できません: コードインデックスが正しく設定されていません" } } diff --git a/src/i18n/locales/ko/embeddings.json b/src/i18n/locales/ko/embeddings.json index 16d119c959..272ac74cc7 100644 --- a/src/i18n/locales/ko/embeddings.json +++ b/src/i18n/locales/ko/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "잘못된 기본 URL입니다. URL 구성을 확인하세요.", "invalidModel": "잘못된 모델입니다. 모델 구성을 확인하세요.", "invalidResponse": "임베더 서비스에서 잘못된 응답이 왔습니다. 구성을 확인하세요." + }, + "serviceFactory": { + "openAiConfigMissing": "임베더 생성을 위한 OpenAI 구성이 누락되었습니다", + "ollamaConfigMissing": "임베더 생성을 위한 Ollama 구성이 누락되었습니다", + "openAiCompatibleConfigMissing": "임베더 생성을 위한 OpenAI 호환 구성이 누락되었습니다", + "geminiConfigMissing": "임베더 생성을 위한 Gemini 구성이 누락되었습니다", + "invalidEmbedderType": "잘못된 임베더 유형이 구성되었습니다: {{embedderProvider}}", + "vectorDimensionNotDeterminedOpenAiCompatible": "프로바이더 '{{provider}}'의 모델 '{{modelId}}'에 대한 벡터 차원을 결정할 수 없습니다. OpenAI 호환 프로바이더 설정에서 '임베딩 차원'이 올바르게 설정되어 있는지 확인하세요.", + "vectorDimensionNotDetermined": "프로바이더 '{{provider}}'의 모델 '{{modelId}}'에 대한 벡터 차원을 결정할 수 없습니다. 모델 프로필 또는 구성을 확인하세요.", + "qdrantUrlMissing": "벡터 저장소 생성을 위한 Qdrant URL이 누락되었습니다", + "codeIndexingNotConfigured": "서비스를 생성할 수 없습니다: 코드 인덱싱이 올바르게 구성되지 않았습니다" } } diff --git a/src/i18n/locales/nl/embeddings.json b/src/i18n/locales/nl/embeddings.json index 9eeb5a04ea..055d27b607 100644 --- a/src/i18n/locales/nl/embeddings.json +++ b/src/i18n/locales/nl/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "Ongeldige basis-URL. Controleer je URL-configuratie.", "invalidModel": "Ongeldig model. Controleer je modelconfiguratie.", "invalidResponse": "Ongeldige reactie van embedder-service. Controleer je configuratie." + }, + "serviceFactory": { + "openAiConfigMissing": "OpenAI-configuratie ontbreekt voor het maken van embedder", + "ollamaConfigMissing": "Ollama-configuratie ontbreekt voor het maken van embedder", + "openAiCompatibleConfigMissing": "OpenAI-compatibele configuratie ontbreekt voor het maken van embedder", + "geminiConfigMissing": "Gemini-configuratie ontbreekt voor het maken van 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.", + "qdrantUrlMissing": "Qdrant URL ontbreekt voor het maken van vectoropslag", + "codeIndexingNotConfigured": "Kan geen services maken: Code-indexering is niet correct geconfigureerd" } } diff --git a/src/i18n/locales/pl/embeddings.json b/src/i18n/locales/pl/embeddings.json index dd10c1ec4c..874fcf7e00 100644 --- a/src/i18n/locales/pl/embeddings.json +++ b/src/i18n/locales/pl/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "Nieprawidłowy podstawowy adres URL. Sprawdź konfigurację adresu URL.", "invalidModel": "Nieprawidłowy model. Sprawdź konfigurację modelu.", "invalidResponse": "Nieprawidłowa odpowiedź z usługi embedder. Sprawdź swoją konfigurację." + }, + "serviceFactory": { + "openAiConfigMissing": "Brak konfiguracji OpenAI do utworzenia embeddera", + "ollamaConfigMissing": "Brak konfiguracji Ollama do utworzenia embeddera", + "openAiCompatibleConfigMissing": "Brak konfiguracji kompatybilnej z OpenAI do utworzenia embeddera", + "geminiConfigMissing": "Brak konfiguracji Gemini 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ę.", + "qdrantUrlMissing": "Brak adresu URL Qdrant do utworzenia magazynu wektorów", + "codeIndexingNotConfigured": "Nie można utworzyć usług: Indeksowanie kodu nie jest poprawnie skonfigurowane" } } diff --git a/src/i18n/locales/pt-BR/embeddings.json b/src/i18n/locales/pt-BR/embeddings.json index ec1db07113..741a10423e 100644 --- a/src/i18n/locales/pt-BR/embeddings.json +++ b/src/i18n/locales/pt-BR/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "URL base inválida. Verifique sua configuração de URL.", "invalidModel": "Modelo inválido. Verifique a configuração do seu modelo.", "invalidResponse": "Resposta inválida do serviço de embedder. Verifique sua configuração." + }, + "serviceFactory": { + "openAiConfigMissing": "Configuração do OpenAI ausente para criação do embedder", + "ollamaConfigMissing": "Configuração do Ollama ausente para criação do embedder", + "openAiCompatibleConfigMissing": "Configuração compatível com OpenAI ausente para criação do embedder", + "geminiConfigMissing": "Configuração do Gemini ausente para 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.", + "qdrantUrlMissing": "URL do Qdrant ausente para criação do armazenamento de vetores", + "codeIndexingNotConfigured": "Não é possível criar serviços: A indexação de código não está configurada corretamente" } } diff --git a/src/i18n/locales/ru/embeddings.json b/src/i18n/locales/ru/embeddings.json index 931dca5bbd..78a21872c6 100644 --- a/src/i18n/locales/ru/embeddings.json +++ b/src/i18n/locales/ru/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "Неверный базовый URL. Проверьте конфигурацию URL.", "invalidModel": "Неверная модель. Проверьте конфигурацию модели.", "invalidResponse": "Неверный ответ от службы embedder. Проверьте вашу конфигурацию." + }, + "serviceFactory": { + "openAiConfigMissing": "Отсутствует конфигурация OpenAI для создания эмбеддера", + "ollamaConfigMissing": "Отсутствует конфигурация Ollama для создания эмбеддера", + "openAiCompatibleConfigMissing": "Отсутствует конфигурация, совместимая с OpenAI, для создания эмбеддера", + "geminiConfigMissing": "Отсутствует конфигурация Gemini для создания эмбеддера", + "invalidEmbedderType": "Настроен недопустимый тип эмбеддера: {{embedderProvider}}", + "vectorDimensionNotDeterminedOpenAiCompatible": "Не удалось определить размерность вектора для модели '{{modelId}}' с провайдером '{{provider}}'. Убедитесь, что 'Размерность эмбеддинга' правильно установлена в настройках провайдера, совместимого с OpenAI.", + "vectorDimensionNotDetermined": "Не удалось определить размерность вектора для модели '{{modelId}}' с провайдером '{{provider}}'. Проверьте профили модели или конфигурацию.", + "qdrantUrlMissing": "Отсутствует URL Qdrant для создания векторного хранилища", + "codeIndexingNotConfigured": "Невозможно создать сервисы: Индексация кода не настроена должным образом" } } diff --git a/src/i18n/locales/tr/embeddings.json b/src/i18n/locales/tr/embeddings.json index 8ff94b0dae..411bad5eb3 100644 --- a/src/i18n/locales/tr/embeddings.json +++ b/src/i18n/locales/tr/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "Geçersiz temel URL. Lütfen URL yapılandırmanızı kontrol edin.", "invalidModel": "Geçersiz model. Lütfen model yapılandırmanızı kontrol edin.", "invalidResponse": "Embedder hizmetinden geçersiz yanıt. Lütfen yapılandırmanızı kontrol edin." + }, + "serviceFactory": { + "openAiConfigMissing": "Gömücü oluşturmak için OpenAI yapılandırması eksik", + "ollamaConfigMissing": "Gömücü oluşturmak için Ollama yapılandırması eksik", + "openAiCompatibleConfigMissing": "Gömücü oluşturmak için OpenAI uyumlu yapılandırması eksik", + "geminiConfigMissing": "Gömücü oluşturmak için Gemini 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.", + "qdrantUrlMissing": "Vektör deposu oluşturmak için Qdrant URL'si eksik", + "codeIndexingNotConfigured": "Hizmetler oluşturulamıyor: Kod indeksleme düzgün yapılandırılmamış" } } diff --git a/src/i18n/locales/vi/embeddings.json b/src/i18n/locales/vi/embeddings.json index 5988219aed..c645199046 100644 --- a/src/i18n/locales/vi/embeddings.json +++ b/src/i18n/locales/vi/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "URL cơ sở không hợp lệ. Vui lòng kiểm tra cấu hình URL của bạn.", "invalidModel": "Mô hình không hợp lệ. Vui lòng kiểm tra cấu hình mô hình của bạn.", "invalidResponse": "Phản hồi không hợp lệ từ dịch vụ embedder. Vui lòng kiểm tra cấu hình của bạn." + }, + "serviceFactory": { + "openAiConfigMissing": "Thiếu cấu hình OpenAI để tạo embedder", + "ollamaConfigMissing": "Thiếu cấu hình Ollama để tạo embedder", + "openAiCompatibleConfigMissing": "Thiếu cấu hình tương thích OpenAI để tạo embedder", + "geminiConfigMissing": "Thiếu cấu hình Gemini để tạo embedder", + "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.", + "qdrantUrlMissing": "Thiếu URL Qdrant để tạo kho lưu trữ vector", + "codeIndexingNotConfigured": "Không thể tạo dịch vụ: Lập chỉ mục mã không được cấu hình đúng cách" } } diff --git a/src/i18n/locales/zh-CN/embeddings.json b/src/i18n/locales/zh-CN/embeddings.json index 68d41a2f4c..8eb4ae4d2d 100644 --- a/src/i18n/locales/zh-CN/embeddings.json +++ b/src/i18n/locales/zh-CN/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "基础 URL 无效。请检查您的 URL 配置。", "invalidModel": "模型无效。请检查您的模型配置。", "invalidResponse": "嵌入服务响应无效。请检查您的配置。" + }, + "serviceFactory": { + "openAiConfigMissing": "创建嵌入器缺少 OpenAI 配置", + "ollamaConfigMissing": "创建嵌入器缺少 Ollama 配置", + "openAiCompatibleConfigMissing": "创建嵌入器缺少 OpenAI 兼容配置", + "geminiConfigMissing": "创建嵌入器缺少 Gemini 配置", + "invalidEmbedderType": "配置的嵌入器类型无效:{{embedderProvider}}", + "vectorDimensionNotDeterminedOpenAiCompatible": "无法确定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量维度。请确保在 OpenAI 兼容提供商设置中正确设置了「嵌入维度」。", + "vectorDimensionNotDetermined": "无法确定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量维度。请检查模型配置文件或配置。", + "qdrantUrlMissing": "创建向量存储缺少 Qdrant URL", + "codeIndexingNotConfigured": "无法创建服务:代码索引未正确配置" } } diff --git a/src/i18n/locales/zh-TW/embeddings.json b/src/i18n/locales/zh-TW/embeddings.json index 2b9967a930..7bd4dfeba3 100644 --- a/src/i18n/locales/zh-TW/embeddings.json +++ b/src/i18n/locales/zh-TW/embeddings.json @@ -37,5 +37,16 @@ "invalidBaseUrl": "無效的基礎 URL。請檢查您的 URL 組態。", "invalidModel": "無效的模型。請檢查您的模型組態。", "invalidResponse": "內嵌服務回應無效。請檢查您的組態。" + }, + "serviceFactory": { + "openAiConfigMissing": "建立嵌入器缺少 OpenAI 設定", + "ollamaConfigMissing": "建立嵌入器缺少 Ollama 設定", + "openAiCompatibleConfigMissing": "建立嵌入器缺少 OpenAI 相容設定", + "geminiConfigMissing": "建立嵌入器缺少 Gemini 設定", + "invalidEmbedderType": "設定的嵌入器類型無效:{{embedderProvider}}", + "vectorDimensionNotDeterminedOpenAiCompatible": "無法確定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量維度。請確保在 OpenAI 相容提供商設定中正確設定了「嵌入維度」。", + "vectorDimensionNotDetermined": "無法確定提供商 '{{provider}}' 的模型 '{{modelId}}' 的向量維度。請檢查模型設定檔或設定。", + "qdrantUrlMissing": "建立向量儲存缺少 Qdrant URL", + "codeIndexingNotConfigured": "無法建立服務:程式碼索引未正確設定" } } diff --git a/src/services/code-index/__tests__/config-manager.spec.ts b/src/services/code-index/__tests__/config-manager.spec.ts index 994f228e52..4571c9011a 100644 --- a/src/services/code-index/__tests__/config-manager.spec.ts +++ b/src/services/code-index/__tests__/config-manager.spec.ts @@ -135,7 +135,7 @@ describe("CodeIndexConfigManager", () => { codebaseIndexEmbedderBaseUrl: "", codebaseIndexEmbedderModelId: "custom-model", codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: 1024, + codebaseIndexEmbedderModelDimension: 1024, } mockContextProxy.getGlobalState.mockImplementation((key: string) => { if (key === "codebaseIndexConfig") return mockGlobalState @@ -153,12 +153,12 @@ describe("CodeIndexConfigManager", () => { isConfigured: true, embedderProvider: "openai-compatible", modelId: "custom-model", + modelDimension: 1024, openAiOptions: { openAiNativeApiKey: "" }, ollamaOptions: { ollamaBaseUrl: "" }, openAiCompatibleOptions: { baseUrl: "https://api.example.com/v1", apiKey: "test-openai-compatible-key", - modelDimension: 1024, }, qdrantUrl: "http://qdrant.local", qdrantApiKey: "test-qdrant-key", @@ -213,7 +213,7 @@ describe("CodeIndexConfigManager", () => { codebaseIndexEmbedderBaseUrl: "", codebaseIndexEmbedderModelId: "custom-model", codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: "invalid-dimension", // Invalid type + codebaseIndexEmbedderModelDimension: "invalid-dimension", // Invalid type } mockContextProxy.getGlobalState.mockImplementation((key: string) => { if (key === "codebaseIndexConfig") return mockGlobalState @@ -231,13 +231,14 @@ describe("CodeIndexConfigManager", () => { isConfigured: true, embedderProvider: "openai-compatible", modelId: "custom-model", + modelDimension: undefined, // Invalid dimension is converted to undefined openAiOptions: { openAiNativeApiKey: "" }, ollamaOptions: { ollamaBaseUrl: "" }, openAiCompatibleOptions: { baseUrl: "https://api.example.com/v1", apiKey: "test-openai-compatible-key", - modelDimension: "invalid-dimension", }, + geminiOptions: undefined, qdrantUrl: "http://qdrant.local", qdrantApiKey: "test-qdrant-key", searchMinScore: 0.4, @@ -533,7 +534,7 @@ describe("CodeIndexConfigManager", () => { codebaseIndexEmbedderProvider: "openai-compatible", codebaseIndexEmbedderModelId: "custom-model", codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: 1024, + codebaseIndexEmbedderModelDimension: 1024, } } return undefined @@ -554,7 +555,7 @@ describe("CodeIndexConfigManager", () => { codebaseIndexEmbedderProvider: "openai-compatible", codebaseIndexEmbedderModelId: "custom-model", codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: 2048, + codebaseIndexEmbedderModelDimension: 2048, } } return undefined @@ -573,10 +574,10 @@ describe("CodeIndexConfigManager", () => { codebaseIndexQdrantUrl: "http://qdrant.local", codebaseIndexEmbedderProvider: "openai-compatible", codebaseIndexEmbedderModelId: "custom-model", + codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", + codebaseIndexEmbedderModelDimension: 1024, } } - if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1" - if (key === "codebaseIndexOpenAiCompatibleModelDimension") return 1024 return undefined }) setupSecretMocks({ @@ -594,11 +595,11 @@ describe("CodeIndexConfigManager", () => { codebaseIndexQdrantUrl: "http://qdrant.local", codebaseIndexEmbedderProvider: "openai-compatible", codebaseIndexEmbedderModelId: "custom-model", + codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", + codebaseIndexEmbedderModelDimension: 1024, codebaseIndexSearchMinScore: 0.5, // Changed unrelated setting } } - if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1" - if (key === "codebaseIndexOpenAiCompatibleModelDimension") return 1024 return undefined }) @@ -637,7 +638,7 @@ describe("CodeIndexConfigManager", () => { codebaseIndexEmbedderProvider: "openai-compatible", codebaseIndexEmbedderModelId: "custom-model", codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: 1024, + codebaseIndexEmbedderModelDimension: 1024, } } return undefined @@ -657,7 +658,7 @@ describe("CodeIndexConfigManager", () => { codebaseIndexEmbedderProvider: "openai-compatible", codebaseIndexEmbedderModelId: "custom-model", codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", - codebaseIndexOpenAiCompatibleModelDimension: 1024, + codebaseIndexEmbedderModelDimension: 1024, } } return undefined @@ -808,10 +809,10 @@ describe("CodeIndexConfigManager", () => { codebaseIndexQdrantUrl: "http://qdrant.local", codebaseIndexEmbedderProvider: "openai-compatible", codebaseIndexEmbedderModelId: "nomic-embed-code", + codebaseIndexOpenAiCompatibleBaseUrl: "https://api.example.com/v1", // No codebaseIndexSearchMinScore } } - if (key === "codebaseIndexOpenAiCompatibleBaseUrl") return "https://api.example.com/v1" return undefined }) mockContextProxy.getSecret.mockImplementation((key: string) => { diff --git a/src/services/code-index/__tests__/service-factory.spec.ts b/src/services/code-index/__tests__/service-factory.spec.ts index c2b56a0463..65932225eb 100644 --- a/src/services/code-index/__tests__/service-factory.spec.ts +++ b/src/services/code-index/__tests__/service-factory.spec.ts @@ -146,7 +146,7 @@ describe("CodeIndexServiceFactory", () => { mockConfigManager.getConfig.mockReturnValue(testConfig as any) // Act & Assert - expect(() => factory.createEmbedder()).toThrow("OpenAI configuration missing for embedder creation") + expect(() => factory.createEmbedder()).toThrow("serviceFactory.openAiConfigMissing") }) it("should throw error when Ollama base URL is missing", () => { @@ -161,7 +161,7 @@ describe("CodeIndexServiceFactory", () => { mockConfigManager.getConfig.mockReturnValue(testConfig as any) // Act & Assert - expect(() => factory.createEmbedder()).toThrow("Ollama configuration missing for embedder creation") + expect(() => factory.createEmbedder()).toThrow("serviceFactory.ollamaConfigMissing") }) it("should pass model ID to OpenAI Compatible embedder when using OpenAI Compatible provider", () => { @@ -224,9 +224,7 @@ describe("CodeIndexServiceFactory", () => { mockConfigManager.getConfig.mockReturnValue(testConfig as any) // Act & Assert - expect(() => factory.createEmbedder()).toThrow( - "OpenAI Compatible configuration missing for embedder creation", - ) + expect(() => factory.createEmbedder()).toThrow("serviceFactory.openAiCompatibleConfigMissing") }) it("should throw error when OpenAI Compatible API key is missing", () => { @@ -242,9 +240,7 @@ describe("CodeIndexServiceFactory", () => { mockConfigManager.getConfig.mockReturnValue(testConfig as any) // Act & Assert - expect(() => factory.createEmbedder()).toThrow( - "OpenAI Compatible configuration missing for embedder creation", - ) + expect(() => factory.createEmbedder()).toThrow("serviceFactory.openAiCompatibleConfigMissing") }) it("should throw error when OpenAI Compatible options are missing", () => { @@ -257,9 +253,7 @@ describe("CodeIndexServiceFactory", () => { mockConfigManager.getConfig.mockReturnValue(testConfig as any) // Act & Assert - expect(() => factory.createEmbedder()).toThrow( - "OpenAI Compatible configuration missing for embedder creation", - ) + expect(() => factory.createEmbedder()).toThrow("serviceFactory.openAiCompatibleConfigMissing") }) it("should create GeminiEmbedder when using Gemini provider", () => { @@ -290,7 +284,7 @@ describe("CodeIndexServiceFactory", () => { mockConfigManager.getConfig.mockReturnValue(testConfig as any) // Act & Assert - expect(() => factory.createEmbedder()).toThrow("Gemini configuration missing for embedder creation") + expect(() => factory.createEmbedder()).toThrow("serviceFactory.geminiConfigMissing") }) it("should throw error when Gemini options are missing", () => { @@ -302,7 +296,7 @@ describe("CodeIndexServiceFactory", () => { mockConfigManager.getConfig.mockReturnValue(testConfig as any) // Act & Assert - expect(() => factory.createEmbedder()).toThrow("Gemini configuration missing for embedder creation") + expect(() => factory.createEmbedder()).toThrow("serviceFactory.geminiConfigMissing") }) it("should throw error for invalid embedder provider", () => { @@ -314,7 +308,7 @@ describe("CodeIndexServiceFactory", () => { mockConfigManager.getConfig.mockReturnValue(testConfig as any) // Act & Assert - expect(() => factory.createEmbedder()).toThrow("Invalid embedder type configured: invalid-provider") + expect(() => factory.createEmbedder()).toThrow("serviceFactory.invalidEmbedderType") }) }) @@ -406,8 +400,10 @@ describe("CodeIndexServiceFactory", () => { const testConfig = { embedderProvider: "openai-compatible", modelId: testModelId, + modelDimension: manualDimension, openAiCompatibleOptions: { - modelDimension: manualDimension, + baseUrl: "https://api.example.com/v1", + apiKey: "test-api-key", }, qdrantUrl: "http://localhost:6333", qdrantApiKey: "test-key", @@ -463,8 +459,10 @@ describe("CodeIndexServiceFactory", () => { const testConfig = { embedderProvider: "openai-compatible", modelId: testModelId, + modelDimension: 0, // Invalid dimension openAiCompatibleOptions: { - modelDimension: 0, // Invalid dimension + baseUrl: "https://api.example.com/v1", + apiKey: "test-api-key", }, qdrantUrl: "http://localhost:6333", qdrantApiKey: "test-key", @@ -474,7 +472,7 @@ describe("CodeIndexServiceFactory", () => { // Act & Assert expect(() => factory.createVectorStore()).toThrow( - "Could not determine vector dimension for model 'custom-model' with provider 'openai-compatible'. Please ensure the 'Embedding Dimension' is correctly set in the OpenAI-Compatible provider settings.", + "serviceFactory.vectorDimensionNotDeterminedOpenAiCompatible", ) }) @@ -496,7 +494,7 @@ describe("CodeIndexServiceFactory", () => { // Act & Assert expect(() => factory.createVectorStore()).toThrow( - "Could not determine vector dimension for model 'unknown-model' with provider 'openai-compatible'. Please ensure the 'Embedding Dimension' is correctly set in the OpenAI-Compatible provider settings.", + "serviceFactory.vectorDimensionNotDeterminedOpenAiCompatible", ) }) @@ -560,9 +558,7 @@ describe("CodeIndexServiceFactory", () => { mockGetModelDimension.mockReturnValue(undefined) // Act & Assert - expect(() => factory.createVectorStore()).toThrow( - "Could not determine vector dimension for model 'unknown-model' with provider 'openai'. Check model profiles or configuration.", - ) + expect(() => factory.createVectorStore()).toThrow("serviceFactory.vectorDimensionNotDetermined") }) it("should throw error when Qdrant URL is missing", () => { @@ -577,7 +573,7 @@ describe("CodeIndexServiceFactory", () => { mockGetModelDimension.mockReturnValue(1536) // Act & Assert - expect(() => factory.createVectorStore()).toThrow("Qdrant URL missing for vector store creation") + expect(() => factory.createVectorStore()).toThrow("serviceFactory.qdrantUrlMissing") }) }) @@ -747,7 +743,7 @@ describe("CodeIndexServiceFactory", () => { await expect(async () => { const embedder = factory.createEmbedder() await factory.validateEmbedder(embedder) - }).rejects.toThrow("OpenAI configuration missing for embedder creation") + }).rejects.toThrow("serviceFactory.openAiConfigMissing") }) it("should return error for unknown embedder provider", async () => { @@ -760,7 +756,7 @@ describe("CodeIndexServiceFactory", () => { // Act & Assert // This should throw when trying to create the embedder - expect(() => factory.createEmbedder()).toThrow("Invalid embedder type configured: unknown-provider") + expect(() => factory.createEmbedder()).toThrow("serviceFactory.invalidEmbedderType") }) }) }) diff --git a/src/services/code-index/config-manager.ts b/src/services/code-index/config-manager.ts index 26ea0e2a48..8e2b8e082d 100644 --- a/src/services/code-index/config-manager.ts +++ b/src/services/code-index/config-manager.ts @@ -13,9 +13,10 @@ export class CodeIndexConfigManager { private isEnabled: boolean = false private embedderProvider: EmbedderProvider = "openai" private modelId?: string + private modelDimension?: number private openAiOptions?: ApiHandlerOptions private ollamaOptions?: ApiHandlerOptions - private openAiCompatibleOptions?: { baseUrl: string; apiKey: string; modelDimension?: number } + private openAiCompatibleOptions?: { baseUrl: string; apiKey: string } private geminiOptions?: { apiKey: string } private qdrantUrl?: string = "http://localhost:6333" private qdrantApiKey?: string @@ -65,9 +66,6 @@ export class CodeIndexConfigManager { // Fix: Read OpenAI Compatible settings from the correct location within codebaseIndexConfig const openAiCompatibleBaseUrl = codebaseIndexConfig.codebaseIndexOpenAiCompatibleBaseUrl ?? "" const openAiCompatibleApiKey = this.contextProxy?.getSecret("codebaseIndexOpenAiCompatibleApiKey") ?? "" - const openAiCompatibleModelDimension = codebaseIndexConfig.codebaseIndexOpenAiCompatibleModelDimension as - | number - | undefined const geminiApiKey = this.contextProxy?.getSecret("codebaseIndexGeminiApiKey") ?? "" // Update instance variables with configuration @@ -76,6 +74,23 @@ export class CodeIndexConfigManager { this.qdrantApiKey = qdrantApiKey ?? "" this.searchMinScore = codebaseIndexSearchMinScore this.searchMaxResults = codebaseIndexSearchMaxResults + + // Validate and set model dimension + const rawDimension = codebaseIndexConfig.codebaseIndexEmbedderModelDimension + if (rawDimension !== undefined && rawDimension !== null) { + const dimension = Number(rawDimension) + if (!isNaN(dimension) && dimension > 0) { + this.modelDimension = dimension + } else { + console.warn( + `Invalid codebaseIndexEmbedderModelDimension value: ${rawDimension}. Must be a positive number.`, + ) + this.modelDimension = undefined + } + } else { + this.modelDimension = undefined + } + this.openAiOptions = { openAiNativeApiKey: openAiKey } // Set embedder provider with support for openai-compatible @@ -100,7 +115,6 @@ export class CodeIndexConfigManager { ? { baseUrl: openAiCompatibleBaseUrl, apiKey: openAiCompatibleApiKey, - modelDimension: openAiCompatibleModelDimension, } : undefined @@ -117,6 +131,7 @@ export class CodeIndexConfigManager { isConfigured: boolean embedderProvider: EmbedderProvider modelId?: string + modelDimension?: number openAiOptions?: ApiHandlerOptions ollamaOptions?: ApiHandlerOptions openAiCompatibleOptions?: { baseUrl: string; apiKey: string } @@ -133,11 +148,11 @@ export class CodeIndexConfigManager { configured: this.isConfigured(), embedderProvider: this.embedderProvider, modelId: this.modelId, + modelDimension: this.modelDimension, openAiKey: this.openAiOptions?.openAiNativeApiKey ?? "", ollamaBaseUrl: this.ollamaOptions?.ollamaBaseUrl ?? "", openAiCompatibleBaseUrl: this.openAiCompatibleOptions?.baseUrl ?? "", openAiCompatibleApiKey: this.openAiCompatibleOptions?.apiKey ?? "", - openAiCompatibleModelDimension: this.openAiCompatibleOptions?.modelDimension, geminiApiKey: this.geminiOptions?.apiKey ?? "", qdrantUrl: this.qdrantUrl ?? "", qdrantApiKey: this.qdrantApiKey ?? "", @@ -158,6 +173,7 @@ export class CodeIndexConfigManager { isConfigured: this.isConfigured(), embedderProvider: this.embedderProvider, modelId: this.modelId, + modelDimension: this.modelDimension, openAiOptions: this.openAiOptions, ollamaOptions: this.ollamaOptions, openAiCompatibleOptions: this.openAiCompatibleOptions, @@ -225,7 +241,7 @@ export class CodeIndexConfigManager { const prevOllamaBaseUrl = prev?.ollamaBaseUrl ?? "" const prevOpenAiCompatibleBaseUrl = prev?.openAiCompatibleBaseUrl ?? "" const prevOpenAiCompatibleApiKey = prev?.openAiCompatibleApiKey ?? "" - const prevOpenAiCompatibleModelDimension = prev?.openAiCompatibleModelDimension + const prevModelDimension = prev?.modelDimension const prevGeminiApiKey = prev?.geminiApiKey ?? "" const prevQdrantUrl = prev?.qdrantUrl ?? "" const prevQdrantApiKey = prev?.qdrantApiKey ?? "" @@ -257,7 +273,7 @@ export class CodeIndexConfigManager { const currentOllamaBaseUrl = this.ollamaOptions?.ollamaBaseUrl ?? "" const currentOpenAiCompatibleBaseUrl = this.openAiCompatibleOptions?.baseUrl ?? "" const currentOpenAiCompatibleApiKey = this.openAiCompatibleOptions?.apiKey ?? "" - const currentOpenAiCompatibleModelDimension = this.openAiCompatibleOptions?.modelDimension + const currentModelDimension = this.modelDimension const currentGeminiApiKey = this.geminiOptions?.apiKey ?? "" const currentQdrantUrl = this.qdrantUrl ?? "" const currentQdrantApiKey = this.qdrantApiKey ?? "" @@ -277,11 +293,9 @@ export class CodeIndexConfigManager { return true } - // Check for OpenAI Compatible modelDimension changes - if (this.embedderProvider === "openai-compatible" || prevProvider === "openai-compatible") { - if (prevOpenAiCompatibleModelDimension !== currentOpenAiCompatibleModelDimension) { - return true - } + // Check for model dimension changes (generic for all providers) + if (prevModelDimension !== currentModelDimension) { + return true } if (prevQdrantUrl !== currentQdrantUrl || prevQdrantApiKey !== currentQdrantApiKey) { @@ -332,6 +346,7 @@ export class CodeIndexConfigManager { isConfigured: this.isConfigured(), embedderProvider: this.embedderProvider, modelId: this.modelId, + modelDimension: this.modelDimension, openAiOptions: this.openAiOptions, ollamaOptions: this.ollamaOptions, openAiCompatibleOptions: this.openAiCompatibleOptions, @@ -381,6 +396,14 @@ export class CodeIndexConfigManager { return this.modelId } + /** + * Gets the current model dimension being used for embeddings. + * Returns the explicitly configured dimension or undefined if not set. + */ + public get currentModelDimension(): number | undefined { + return this.modelDimension + } + /** * Gets the configured minimum search score based on user setting, model-specific threshold, or fallback. * Priority: 1) User setting, 2) Model-specific threshold, 3) Default DEFAULT_SEARCH_MIN_SCORE constant. diff --git a/src/services/code-index/interfaces/config.ts b/src/services/code-index/interfaces/config.ts index 0600f29c2a..f4eb55c183 100644 --- a/src/services/code-index/interfaces/config.ts +++ b/src/services/code-index/interfaces/config.ts @@ -9,9 +9,10 @@ export interface CodeIndexConfig { isConfigured: boolean embedderProvider: EmbedderProvider modelId?: string + modelDimension?: number // Generic dimension property for all providers openAiOptions?: ApiHandlerOptions ollamaOptions?: ApiHandlerOptions - openAiCompatibleOptions?: { baseUrl: string; apiKey: string; modelDimension?: number } + openAiCompatibleOptions?: { baseUrl: string; apiKey: string } geminiOptions?: { apiKey: string } qdrantUrl?: string qdrantApiKey?: string @@ -27,11 +28,11 @@ export type PreviousConfigSnapshot = { configured: boolean embedderProvider: EmbedderProvider modelId?: string + modelDimension?: number // Generic dimension property openAiKey?: string ollamaBaseUrl?: string openAiCompatibleBaseUrl?: string openAiCompatibleApiKey?: string - openAiCompatibleModelDimension?: number geminiApiKey?: string qdrantUrl?: string qdrantApiKey?: string diff --git a/src/services/code-index/service-factory.ts b/src/services/code-index/service-factory.ts index a9c84481a6..818dafb497 100644 --- a/src/services/code-index/service-factory.ts +++ b/src/services/code-index/service-factory.ts @@ -10,6 +10,7 @@ import { ICodeParser, IEmbedder, IFileWatcher, IVectorStore } from "./interfaces import { CodeIndexConfigManager } from "./config-manager" import { CacheManager } from "./cache-manager" import { Ignore } from "ignore" +import { t } from "../../i18n" /** * Factory class responsible for creating and configuring code indexing service dependencies. @@ -33,7 +34,7 @@ export class CodeIndexServiceFactory { const apiKey = config.openAiOptions?.openAiNativeApiKey if (!apiKey) { - throw new Error("OpenAI configuration missing for embedder creation") + throw new Error(t("embeddings:serviceFactory.openAiConfigMissing")) } return new OpenAiEmbedder({ ...config.openAiOptions, @@ -41,7 +42,7 @@ export class CodeIndexServiceFactory { }) } else if (provider === "ollama") { if (!config.ollamaOptions?.ollamaBaseUrl) { - throw new Error("Ollama configuration missing for embedder creation") + throw new Error(t("embeddings:serviceFactory.ollamaConfigMissing")) } return new CodeIndexOllamaEmbedder({ ...config.ollamaOptions, @@ -49,7 +50,7 @@ export class CodeIndexServiceFactory { }) } else if (provider === "openai-compatible") { if (!config.openAiCompatibleOptions?.baseUrl || !config.openAiCompatibleOptions?.apiKey) { - throw new Error("OpenAI Compatible configuration missing for embedder creation") + throw new Error(t("embeddings:serviceFactory.openAiCompatibleConfigMissing")) } return new OpenAICompatibleEmbedder( config.openAiCompatibleOptions.baseUrl, @@ -58,12 +59,14 @@ export class CodeIndexServiceFactory { ) } else if (provider === "gemini") { if (!config.geminiOptions?.apiKey) { - throw new Error("Gemini configuration missing for embedder creation") + throw new Error(t("embeddings:serviceFactory.geminiConfigMissing")) } return new GeminiEmbedder(config.geminiOptions.apiKey) } - throw new Error(`Invalid embedder type configured: ${config.embedderProvider}`) + throw new Error( + t("embeddings:serviceFactory.invalidEmbedderType", { embedderProvider: config.embedderProvider }), + ) } /** @@ -96,33 +99,29 @@ export class CodeIndexServiceFactory { let vectorSize: number | undefined - if (provider === "openai-compatible") { - if (config.openAiCompatibleOptions?.modelDimension && config.openAiCompatibleOptions.modelDimension > 0) { - vectorSize = config.openAiCompatibleOptions.modelDimension - } else { - // Fallback if not provided or invalid in openAiCompatibleOptions - vectorSize = getModelDimension(provider, modelId) - } + // First check if a manual dimension is provided (works for all providers) + if (config.modelDimension && config.modelDimension > 0) { + vectorSize = config.modelDimension } else if (provider === "gemini") { // Gemini's text-embedding-004 has a fixed dimension of 768 vectorSize = 768 } else { + // Fall back to model-specific dimension from profiles vectorSize = getModelDimension(provider, modelId) } - if (vectorSize === undefined) { - let errorMessage = `Could not determine vector dimension for model '${modelId}' with provider '${provider}'. ` + if (vectorSize === undefined || vectorSize <= 0) { if (provider === "openai-compatible") { - errorMessage += `Please ensure the 'Embedding Dimension' is correctly set in the OpenAI-Compatible provider settings.` + throw new Error( + t("embeddings:serviceFactory.vectorDimensionNotDeterminedOpenAiCompatible", { modelId, provider }), + ) } else { - errorMessage += `Check model profiles or configuration.` + throw new Error(t("embeddings:serviceFactory.vectorDimensionNotDetermined", { modelId, provider })) } - throw new Error(errorMessage) } if (!config.qdrantUrl) { - // This check remains important - throw new Error("Qdrant URL missing for vector store creation") + throw new Error(t("embeddings:serviceFactory.qdrantUrlMissing")) } // Assuming constructor is updated: new QdrantVectorStore(workspacePath, url, vectorSize, apiKey?) @@ -170,7 +169,7 @@ export class CodeIndexServiceFactory { fileWatcher: IFileWatcher } { if (!this.configManager.isFeatureConfigured) { - throw new Error("Cannot create services: Code indexing is not properly configured") + throw new Error(t("embeddings:serviceFactory.codeIndexingNotConfigured")) } const embedder = this.createEmbedder() diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index 312b7ceb11..fa9fb67310 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -241,8 +241,8 @@ export interface WebviewMessage { codebaseIndexEmbedderProvider: "openai" | "ollama" | "openai-compatible" | "gemini" codebaseIndexEmbedderBaseUrl?: string codebaseIndexEmbedderModelId: string + codebaseIndexEmbedderModelDimension?: number // Generic dimension for all providers codebaseIndexOpenAiCompatibleBaseUrl?: string - codebaseIndexOpenAiCompatibleModelDimension?: number codebaseIndexSearchMaxResults?: number codebaseIndexSearchMinScore?: number diff --git a/webview-ui/src/components/chat/CodeIndexPopover.tsx b/webview-ui/src/components/chat/CodeIndexPopover.tsx index 6c9ea1c204..22b209bcd8 100644 --- a/webview-ui/src/components/chat/CodeIndexPopover.tsx +++ b/webview-ui/src/components/chat/CodeIndexPopover.tsx @@ -51,6 +51,7 @@ interface LocalCodeIndexSettings { codebaseIndexEmbedderProvider: EmbedderProvider codebaseIndexEmbedderBaseUrl?: string codebaseIndexEmbedderModelId: string + codebaseIndexEmbedderModelDimension?: number // Generic dimension for all providers codebaseIndexSearchMaxResults?: number codebaseIndexSearchMinScore?: number @@ -59,7 +60,6 @@ interface LocalCodeIndexSettings { codeIndexQdrantApiKey?: string codebaseIndexOpenAiCompatibleBaseUrl?: string codebaseIndexOpenAiCompatibleApiKey?: string - codebaseIndexOpenAiCompatibleModelDimension?: number codebaseIndexGeminiApiKey?: string } @@ -85,13 +85,13 @@ export const CodeIndexPopover: React.FC = ({ codebaseIndexEmbedderProvider: "openai", codebaseIndexEmbedderBaseUrl: "", codebaseIndexEmbedderModelId: "", + codebaseIndexEmbedderModelDimension: undefined, codebaseIndexSearchMaxResults: CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS, codebaseIndexSearchMinScore: CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_MIN_SCORE, codeIndexOpenAiKey: "", codeIndexQdrantApiKey: "", codebaseIndexOpenAiCompatibleBaseUrl: "", codebaseIndexOpenAiCompatibleApiKey: "", - codebaseIndexOpenAiCompatibleModelDimension: undefined, codebaseIndexGeminiApiKey: "", }) @@ -115,6 +115,8 @@ export const CodeIndexPopover: React.FC = ({ codebaseIndexEmbedderProvider: codebaseIndexConfig.codebaseIndexEmbedderProvider || "openai", codebaseIndexEmbedderBaseUrl: codebaseIndexConfig.codebaseIndexEmbedderBaseUrl || "", codebaseIndexEmbedderModelId: codebaseIndexConfig.codebaseIndexEmbedderModelId || "", + codebaseIndexEmbedderModelDimension: + codebaseIndexConfig.codebaseIndexEmbedderModelDimension || undefined, codebaseIndexSearchMaxResults: codebaseIndexConfig.codebaseIndexSearchMaxResults ?? CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS, codebaseIndexSearchMinScore: @@ -123,8 +125,6 @@ export const CodeIndexPopover: React.FC = ({ codeIndexQdrantApiKey: "", codebaseIndexOpenAiCompatibleBaseUrl: codebaseIndexConfig.codebaseIndexOpenAiCompatibleBaseUrl || "", codebaseIndexOpenAiCompatibleApiKey: "", - codebaseIndexOpenAiCompatibleModelDimension: - codebaseIndexConfig.codebaseIndexOpenAiCompatibleModelDimension || undefined, codebaseIndexGeminiApiKey: "", } setInitialSettings(settings) @@ -509,12 +509,10 @@ export const CodeIndexPopover: React.FC = ({ {t("settings:codeIndex.modelDimensionLabel")} { const value = e.target.value ? parseInt(e.target.value) : undefined - updateSetting("codebaseIndexOpenAiCompatibleModelDimension", value) + updateSetting("codebaseIndexEmbedderModelDimension", value) }} placeholder={t("settings:codeIndex.modelDimensionPlaceholder")} className="w-full"