diff --git a/apps/web/locales/af-ZA.po b/apps/web/locales/af-ZA.po index 965c8573a..237cd7376 100644 --- a/apps/web/locales/af-ZA.po +++ b/apps/web/locales/af-ZA.po @@ -985,6 +985,10 @@ msgstr "Verbonde" msgid "Connection failed" msgstr "Verbinding het misluk" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Verbinding geverifieer — verskaffer is gereed vir gebruik." @@ -4309,6 +4313,10 @@ msgstr "Statistiek" msgid "Stay" msgstr "Bly" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Stop generasie" @@ -4441,6 +4449,10 @@ msgstr "Getuigskrifte" msgid "Testing…" msgstr "Toetsing…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Teksbelyning" @@ -5399,4 +5411,3 @@ msgstr "Zoem uit" #: src/libs/locale.ts msgid "Zulu" msgstr "Zoeloe" - diff --git a/apps/web/locales/am-ET.po b/apps/web/locales/am-ET.po index 3564f596f..c254be4d0 100644 --- a/apps/web/locales/am-ET.po +++ b/apps/web/locales/am-ET.po @@ -985,6 +985,10 @@ msgstr "ተገናኝቷል" msgid "Connection failed" msgstr "ግንኙነት አልተሳካም" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "ግንኙነት ተረጋግጧል - አቅራቢው ለመጠቀም ዝግጁ ነው።" @@ -4309,6 +4313,10 @@ msgstr "ስታቲስቲክስ" msgid "Stay" msgstr "ቆይ" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "ማመንጨት አቁም" @@ -4441,6 +4449,10 @@ msgstr "ምስክርነቶች" msgid "Testing…" msgstr "ሙከራ…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "የጽሑፍ አሰላለፍ" @@ -5399,4 +5411,3 @@ msgstr "አጉር" #: src/libs/locale.ts msgid "Zulu" msgstr "ዙሉ" - diff --git a/apps/web/locales/ar-SA.po b/apps/web/locales/ar-SA.po index cedb6b04e..765582f84 100644 --- a/apps/web/locales/ar-SA.po +++ b/apps/web/locales/ar-SA.po @@ -985,6 +985,10 @@ msgstr "متصل" msgid "Connection failed" msgstr "فشل الاتصال" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "تم التحقق من الاتصال - المزود جاهز للاستخدام." @@ -4309,6 +4313,10 @@ msgstr "الإحصاءات" msgid "Stay" msgstr "البقاء" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "أوقفوا التوليد" @@ -4441,6 +4449,10 @@ msgstr "قصص المستخدمين" msgid "Testing…" msgstr "اختبار…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "محاذاة النص" @@ -5399,4 +5411,3 @@ msgstr "تصغير" #: src/libs/locale.ts msgid "Zulu" msgstr "الزولو" - diff --git a/apps/web/locales/az-AZ.po b/apps/web/locales/az-AZ.po index 9a98da077..e29aa8c79 100644 --- a/apps/web/locales/az-AZ.po +++ b/apps/web/locales/az-AZ.po @@ -985,6 +985,10 @@ msgstr "Qoşuldu" msgid "Connection failed" msgstr "Bağlantı uğursuz oldu" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Bağlantı təsdiqləndi — provayder istifadəyə hazırdır." @@ -4309,6 +4313,10 @@ msgstr "Statistika" msgid "Stay" msgstr "Qal" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Nəsil verməyi dayandırın" @@ -4441,6 +4449,10 @@ msgstr "Rəylər" msgid "Testing…" msgstr "Test…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Mətn hizalanması" @@ -5399,4 +5411,3 @@ msgstr "Uzaqlaşdır" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/bg-BG.po b/apps/web/locales/bg-BG.po index eb356dd9c..a7f900c90 100644 --- a/apps/web/locales/bg-BG.po +++ b/apps/web/locales/bg-BG.po @@ -985,6 +985,10 @@ msgstr "Свързан" msgid "Connection failed" msgstr "Връзката не бе успешна" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Връзката е потвърдена — доставчикът е готов за употреба." @@ -4309,6 +4313,10 @@ msgstr "Статистика" msgid "Stay" msgstr "Остани" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Спиране на генерирането" @@ -4441,6 +4449,10 @@ msgstr "Отзиви" msgid "Testing…" msgstr "Тестване…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Подравняване на текста" @@ -5399,4 +5411,3 @@ msgstr "Намаляване" #: src/libs/locale.ts msgid "Zulu" msgstr "Зулуски" - diff --git a/apps/web/locales/bn-BD.po b/apps/web/locales/bn-BD.po index 4cf2ce992..5664fd81e 100644 --- a/apps/web/locales/bn-BD.po +++ b/apps/web/locales/bn-BD.po @@ -985,6 +985,10 @@ msgstr "সংযুক্ত" msgid "Connection failed" msgstr "সংযোগ ব্যর্থ হয়েছে" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "সংযোগ যাচাই করা হয়েছে — পরিষেবা প্রদানকারী ব্যবহারের জন্য প্রস্তুত।" @@ -4309,6 +4313,10 @@ msgstr "পরিসংখ্যান" msgid "Stay" msgstr "থাকুন" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "প্রজন্ম বন্ধ করুন" @@ -4441,6 +4449,10 @@ msgstr "প্রশংসাপত্র" msgid "Testing…" msgstr "পরীক্ষা…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "পাঠ্য সারিবদ্ধকরণ" @@ -5399,4 +5411,3 @@ msgstr "জুম আউট" #: src/libs/locale.ts msgid "Zulu" msgstr "জুলু" - diff --git a/apps/web/locales/ca-ES.po b/apps/web/locales/ca-ES.po index b7ee9c965..06c107124 100644 --- a/apps/web/locales/ca-ES.po +++ b/apps/web/locales/ca-ES.po @@ -985,6 +985,10 @@ msgstr "Connectat" msgid "Connection failed" msgstr "La connexió ha fallat" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Connexió verificada: el proveïdor està a punt per utilitzar-lo." @@ -4309,6 +4313,10 @@ msgstr "Estadístiques" msgid "Stay" msgstr "Queda't" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Atura la generació" @@ -4441,6 +4449,10 @@ msgstr "Testimonis" msgid "Testing…" msgstr "Proves…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Alineació del text" @@ -5399,4 +5411,3 @@ msgstr "Allunya" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulú" - diff --git a/apps/web/locales/cs-CZ.po b/apps/web/locales/cs-CZ.po index c24a2a24a..8bae9952c 100644 --- a/apps/web/locales/cs-CZ.po +++ b/apps/web/locales/cs-CZ.po @@ -985,6 +985,10 @@ msgstr "Připojeno" msgid "Connection failed" msgstr "Připojení se nezdařilo" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Připojení ověřeno – poskytovatel je připraven k použití." @@ -4309,6 +4313,10 @@ msgstr "Statistiky" msgid "Stay" msgstr "Zůstat" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Zastavit generování" @@ -4441,6 +4449,10 @@ msgstr "Reference uživatelů" msgid "Testing…" msgstr "Testování…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Zarovnání textu" @@ -5399,4 +5411,3 @@ msgstr "Oddálit" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/da-DK.po b/apps/web/locales/da-DK.po index b835dedb7..f3df67af4 100644 --- a/apps/web/locales/da-DK.po +++ b/apps/web/locales/da-DK.po @@ -985,6 +985,10 @@ msgstr "Forbundet" msgid "Connection failed" msgstr "Forbindelsen mislykkedes" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Forbindelse bekræftet — udbyderen er klar til brug." @@ -4309,6 +4313,10 @@ msgstr "Statistik" msgid "Stay" msgstr "Bliv" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Stop generation" @@ -4441,6 +4449,10 @@ msgstr "Udtalelser" msgid "Testing…" msgstr "Test…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Tekstjustering" @@ -5399,4 +5411,3 @@ msgstr "Zoom ud" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/de-DE.po b/apps/web/locales/de-DE.po index 10d5b78f0..5a477dfb8 100644 --- a/apps/web/locales/de-DE.po +++ b/apps/web/locales/de-DE.po @@ -985,6 +985,10 @@ msgstr "Verbunden" msgid "Connection failed" msgstr "Verbindung fehlgeschlagen" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Verbindung bestätigt – der Anbieter ist einsatzbereit." @@ -4309,6 +4313,10 @@ msgstr "Statistiken" msgid "Stay" msgstr "Hier bleiben" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Stoppt die Stromerzeugung" @@ -4441,6 +4449,10 @@ msgstr "Erfahrungsberichte" msgid "Testing…" msgstr "Testen…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Textausrichtung" @@ -5399,4 +5411,3 @@ msgstr "Herauszoomen" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/el-GR.po b/apps/web/locales/el-GR.po index 7c7685e77..2d6a226d6 100644 --- a/apps/web/locales/el-GR.po +++ b/apps/web/locales/el-GR.po @@ -985,6 +985,10 @@ msgstr "Συνδεδεμένος" msgid "Connection failed" msgstr "Η σύνδεση απέτυχε" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Η σύνδεση επαληθεύτηκε — ο πάροχος είναι έτοιμος για χρήση." @@ -4309,6 +4313,10 @@ msgstr "Στατιστικά" msgid "Stay" msgstr "Παραμονή" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Διακοπή δημιουργίας" @@ -4441,6 +4449,10 @@ msgstr "Αναφορές πελατών" msgid "Testing…" msgstr "Δοκιμή…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Στοίχιση κειμένου" @@ -5399,4 +5411,3 @@ msgstr "Σμίκρυνση" #: src/libs/locale.ts msgid "Zulu" msgstr "Ζουλού" - diff --git a/apps/web/locales/en-GB.po b/apps/web/locales/en-GB.po index ad1dbfdf3..80771ab0f 100644 --- a/apps/web/locales/en-GB.po +++ b/apps/web/locales/en-GB.po @@ -985,6 +985,10 @@ msgstr "Connected" msgid "Connection failed" msgstr "Connection failed" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Connection verified — provider is ready to use." @@ -4309,6 +4313,10 @@ msgstr "Statistics" msgid "Stay" msgstr "Stay" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Stop generation" @@ -4441,6 +4449,10 @@ msgstr "Testimonials" msgid "Testing…" msgstr "Testing…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Text alignment" @@ -5399,4 +5411,3 @@ msgstr "Zoom out" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/en-US.po b/apps/web/locales/en-US.po index 952f57a18..b70529fe6 100644 --- a/apps/web/locales/en-US.po +++ b/apps/web/locales/en-US.po @@ -980,6 +980,10 @@ msgstr "Connected" msgid "Connection failed" msgstr "Connection failed" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "Connection failed." + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Connection verified — provider is ready to use." @@ -4304,6 +4308,10 @@ msgstr "Statistics" msgid "Stay" msgstr "Stay" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "Still waiting for {provider}… {elapsedSeconds}s" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Stop generation" @@ -4436,6 +4444,10 @@ msgstr "Testimonials" msgid "Testing…" msgstr "Testing…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "Testing… {elapsedSeconds}s" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Text alignment" diff --git a/apps/web/locales/es-ES.po b/apps/web/locales/es-ES.po index ea231a3b0..db68f9235 100644 --- a/apps/web/locales/es-ES.po +++ b/apps/web/locales/es-ES.po @@ -985,6 +985,10 @@ msgstr "Conectado" msgid "Connection failed" msgstr "Falló la conexión" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Conexión verificada: el proveedor está listo para usarse." @@ -4309,6 +4313,10 @@ msgstr "Estadísticas" msgid "Stay" msgstr "Continuar" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Detener la generación" @@ -4441,6 +4449,10 @@ msgstr "Testimonios" msgid "Testing…" msgstr "Probando…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Alineación del texto" @@ -5399,4 +5411,3 @@ msgstr "Alejar" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulú" - diff --git a/apps/web/locales/fa-IR.po b/apps/web/locales/fa-IR.po index 9d8d9d02a..141714502 100644 --- a/apps/web/locales/fa-IR.po +++ b/apps/web/locales/fa-IR.po @@ -985,6 +985,10 @@ msgstr "متصل" msgid "Connection failed" msgstr "اتصال ناموفق بود" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "اتصال تأیید شد - ارائه دهنده آماده استفاده است." @@ -4309,6 +4313,10 @@ msgstr "آمارها" msgid "Stay" msgstr "ماندن" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "توقف تولید" @@ -4441,6 +4449,10 @@ msgstr "نظرات کاربران" msgid "Testing…" msgstr "در حال آزمایش…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "ترازبندی متن" @@ -5399,4 +5411,3 @@ msgstr "کوچک‌نمایی" #: src/libs/locale.ts msgid "Zulu" msgstr "زولو" - diff --git a/apps/web/locales/fi-FI.po b/apps/web/locales/fi-FI.po index 5bcc53c69..1115bdbb3 100644 --- a/apps/web/locales/fi-FI.po +++ b/apps/web/locales/fi-FI.po @@ -985,6 +985,10 @@ msgstr "Yhdistetty" msgid "Connection failed" msgstr "Yhteys epäonnistui" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Yhteys vahvistettu — palveluntarjoaja on käyttövalmis." @@ -4309,6 +4313,10 @@ msgstr "Tilastot" msgid "Stay" msgstr "Pysy" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Lopeta sukupolvi" @@ -4441,6 +4449,10 @@ msgstr "Suosittelut" msgid "Testing…" msgstr "Testaus…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Tekstin tasaus" @@ -5399,4 +5411,3 @@ msgstr "Loitonna" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/fr-FR.po b/apps/web/locales/fr-FR.po index 86f0989e1..d5fdc274c 100644 --- a/apps/web/locales/fr-FR.po +++ b/apps/web/locales/fr-FR.po @@ -985,6 +985,10 @@ msgstr "Connecté" msgid "Connection failed" msgstr "Échec de la connexion" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Connexion vérifiée — le fournisseur est prêt à l'emploi." @@ -4309,6 +4313,10 @@ msgstr "Statistiques" msgid "Stay" msgstr "Rester" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Génération stop" @@ -4441,6 +4449,10 @@ msgstr "Témoignages" msgid "Testing…" msgstr "Test…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Alignement du texte" @@ -5399,4 +5411,3 @@ msgstr "Zoom arrière" #: src/libs/locale.ts msgid "Zulu" msgstr "Zoulou" - diff --git a/apps/web/locales/he-IL.po b/apps/web/locales/he-IL.po index dea2a5a37..55477f3d6 100644 --- a/apps/web/locales/he-IL.po +++ b/apps/web/locales/he-IL.po @@ -985,6 +985,10 @@ msgstr "מְחוּבָּר" msgid "Connection failed" msgstr "החיבור נכשל" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "החיבור אומת - הספק מוכן לשימוש." @@ -4309,6 +4313,10 @@ msgstr "סטטיסטיקה" msgid "Stay" msgstr "הישאר" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "עצירת הדור" @@ -4441,6 +4449,10 @@ msgstr "המלצות" msgid "Testing…" msgstr "בדיקות…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "יישור טקסט" @@ -5399,4 +5411,3 @@ msgstr "התרחקות" #: src/libs/locale.ts msgid "Zulu" msgstr "זולו" - diff --git a/apps/web/locales/hi-IN.po b/apps/web/locales/hi-IN.po index 1c0f1dff9..e9450dd5f 100644 --- a/apps/web/locales/hi-IN.po +++ b/apps/web/locales/hi-IN.po @@ -985,6 +985,10 @@ msgstr "जुड़े हुए" msgid "Connection failed" msgstr "कनेक्शन विफल" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "कनेक्शन सत्यापित हो गया है — सेवा प्रदाता उपयोग के लिए तैयार है।" @@ -4309,6 +4313,10 @@ msgstr "आंकड़े" msgid "Stay" msgstr "रहें" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "पीढ़ी को रोकें" @@ -4441,6 +4449,10 @@ msgstr "प्रशंसापत्र" msgid "Testing…" msgstr "परीक्षण…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "पाठ संरेखण" @@ -5399,4 +5411,3 @@ msgstr "ज़ूम आउट" #: src/libs/locale.ts msgid "Zulu" msgstr "ज़ुलु" - diff --git a/apps/web/locales/hu-HU.po b/apps/web/locales/hu-HU.po index 0af25cfa8..58e26e985 100644 --- a/apps/web/locales/hu-HU.po +++ b/apps/web/locales/hu-HU.po @@ -985,6 +985,10 @@ msgstr "Csatlakoztatva" msgid "Connection failed" msgstr "Kapcsolódás sikertelen" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Kapcsolat ellenőrizve – a szolgáltató használatra kész." @@ -4309,6 +4313,10 @@ msgstr "Statisztikák" msgid "Stay" msgstr "Maradás" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Állítsa le a generációt" @@ -4441,6 +4449,10 @@ msgstr "Visszajelzések" msgid "Testing…" msgstr "Tesztelés…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Szöveg igazítása" @@ -5399,4 +5411,3 @@ msgstr "Kicsinyítés" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/id-ID.po b/apps/web/locales/id-ID.po index ac867a8ad..ca924bdcf 100644 --- a/apps/web/locales/id-ID.po +++ b/apps/web/locales/id-ID.po @@ -985,6 +985,10 @@ msgstr "Terhubung" msgid "Connection failed" msgstr "Koneksi gagal" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Koneksi terverifikasi — penyedia siap digunakan." @@ -4309,6 +4313,10 @@ msgstr "Statistik" msgid "Stay" msgstr "Tetap" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Hentikan pembangkitan" @@ -4441,6 +4449,10 @@ msgstr "Testimoni" msgid "Testing…" msgstr "Pengujian…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Penyelarasan teks" @@ -5399,4 +5411,3 @@ msgstr "Perkecil" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/it-IT.po b/apps/web/locales/it-IT.po index 514d90159..071b537d6 100644 --- a/apps/web/locales/it-IT.po +++ b/apps/web/locales/it-IT.po @@ -985,6 +985,10 @@ msgstr "Collegato" msgid "Connection failed" msgstr "Connessione fallita" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Connessione verificata: il provider è pronto all'uso." @@ -4309,6 +4313,10 @@ msgstr "Statistiche" msgid "Stay" msgstr "Rimani" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Interrompere la generazione" @@ -4441,6 +4449,10 @@ msgstr "Testimonial" msgid "Testing…" msgstr "Test…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Allineamento del testo" @@ -5399,4 +5411,3 @@ msgstr "Rimpicciolisci" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/ja-JP.po b/apps/web/locales/ja-JP.po index 59c1f8e76..52463e387 100644 --- a/apps/web/locales/ja-JP.po +++ b/apps/web/locales/ja-JP.po @@ -985,6 +985,10 @@ msgstr "接続済み" msgid "Connection failed" msgstr "接続に失敗しました" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "接続確認済み — プロバイダは使用可能です。" @@ -4309,6 +4313,10 @@ msgstr "統計" msgid "Stay" msgstr "このまま" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "生成を停止" @@ -4441,6 +4449,10 @@ msgstr "ユーザーの声" msgid "Testing…" msgstr "テスト…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "テキストの配置" @@ -5399,4 +5411,3 @@ msgstr "ズームアウト" #: src/libs/locale.ts msgid "Zulu" msgstr "ズールー語" - diff --git a/apps/web/locales/km-KH.po b/apps/web/locales/km-KH.po index 4734e43d9..aeb05e416 100644 --- a/apps/web/locales/km-KH.po +++ b/apps/web/locales/km-KH.po @@ -985,6 +985,10 @@ msgstr "បានភ្ជាប់" msgid "Connection failed" msgstr "ការតភ្ជាប់បរាជ័យ" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "ការភ្ជាប់ត្រូវបានផ្ទៀងផ្ទាត់ — អ្នកផ្តល់សេវារួចរាល់សម្រាប់ប្រើប្រាស់។" @@ -4309,6 +4313,10 @@ msgstr "ស្ថិតិ" msgid "Stay" msgstr "ស្ថិត" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "បញ្ឈប់ការបង្កើត" @@ -4441,6 +4449,10 @@ msgstr "សក្ខីកម្ម" msgid "Testing…" msgstr "កំពុងសាកល្បង…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "ការតម្រឹមអត្ថបទ" @@ -5399,4 +5411,3 @@ msgstr "បង្រួម" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/kn-IN.po b/apps/web/locales/kn-IN.po index a5f6cbad4..35abb7251 100644 --- a/apps/web/locales/kn-IN.po +++ b/apps/web/locales/kn-IN.po @@ -985,6 +985,10 @@ msgstr "ಸಂಪರ್ಕಿಸಲಾಗಿದೆ" msgid "Connection failed" msgstr "ಸಂಪರ್ಕ ವಿಫಲವಾಗಿದೆ" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಲಾಗಿದೆ — ಪೂರೈಕೆದಾರರು ಬಳಸಲು ಸಿದ್ಧರಾಗಿದ್ದಾರೆ." @@ -4309,6 +4313,10 @@ msgstr "ಅಂಕಿಅಂಶಗಳು" msgid "Stay" msgstr "ಇರಿ" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "ಪೀಳಿಗೆಯನ್ನು ನಿಲ್ಲಿಸಿ" @@ -4441,6 +4449,10 @@ msgstr "ಪ್ರಶಂಸಾಪತ್ರಗಳು" msgid "Testing…" msgstr "… ಪರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "ಪಠ್ಯ ಜೋಡಣೆ" @@ -5399,4 +5411,3 @@ msgstr "ಗಾತ್ರ ಕುಗ್ಗಿಸಿ" #: src/libs/locale.ts msgid "Zulu" msgstr "ಜೂಲೂ" - diff --git a/apps/web/locales/ko-KR.po b/apps/web/locales/ko-KR.po index cfc81c9d3..e7186dab5 100644 --- a/apps/web/locales/ko-KR.po +++ b/apps/web/locales/ko-KR.po @@ -985,6 +985,10 @@ msgstr "연결됨" msgid "Connection failed" msgstr "연결 실패" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "연결이 확인되었습니다. 공급자를 사용할 준비가 되었습니다." @@ -4309,6 +4313,10 @@ msgstr "통계" msgid "Stay" msgstr "머물기" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "세대 중단" @@ -4441,6 +4449,10 @@ msgstr "후기" msgid "Testing…" msgstr "테스트…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "텍스트 정렬" @@ -5399,4 +5411,3 @@ msgstr "축소" #: src/libs/locale.ts msgid "Zulu" msgstr "줄루어" - diff --git a/apps/web/locales/lt-LT.po b/apps/web/locales/lt-LT.po index a79165b27..10dfca1ff 100644 --- a/apps/web/locales/lt-LT.po +++ b/apps/web/locales/lt-LT.po @@ -985,6 +985,10 @@ msgstr "Prijungtas" msgid "Connection failed" msgstr "Ryšys nepavyko" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Ryšys patvirtintas – tiekėjas paruoštas naudoti." @@ -4309,6 +4313,10 @@ msgstr "Statistika" msgid "Stay" msgstr "Likti" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Sustabdyti generavimą" @@ -4441,6 +4449,10 @@ msgstr "Atsiliepimai" msgid "Testing…" msgstr "Testavimas…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Teksto lygiavimas" @@ -5399,4 +5411,3 @@ msgstr "Tolinti" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulų" - diff --git a/apps/web/locales/lv-LV.po b/apps/web/locales/lv-LV.po index 9adde16fc..4a64678e9 100644 --- a/apps/web/locales/lv-LV.po +++ b/apps/web/locales/lv-LV.po @@ -985,6 +985,10 @@ msgstr "Savienots" msgid "Connection failed" msgstr "Savienojums neizdevās" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Savienojums ir pārbaudīts — pakalpojumu sniedzējs ir gatavs lietošanai." @@ -4309,6 +4313,10 @@ msgstr "Statistika" msgid "Stay" msgstr "Palikt" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Apturēt paaudzi" @@ -4441,6 +4449,10 @@ msgstr "Atsauksmes" msgid "Testing…" msgstr "Testēšana…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Teksta izlīdzināšana" @@ -5399,4 +5411,3 @@ msgstr "Tālināt" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/ml-IN.po b/apps/web/locales/ml-IN.po index 4cdfd3cc8..618761829 100644 --- a/apps/web/locales/ml-IN.po +++ b/apps/web/locales/ml-IN.po @@ -985,6 +985,10 @@ msgstr "ബന്ധിപ്പിച്ചു" msgid "Connection failed" msgstr "കണക്ഷൻ പരാജയപ്പെട്ടു" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "കണക്ഷൻ സ്ഥിരീകരിച്ചു — ദാതാവ് ഉപയോഗിക്കാൻ തയ്യാറാണ്." @@ -4309,6 +4313,10 @@ msgstr "സ്റ്റാറ്റിസ്റ്റിക്സ്" msgid "Stay" msgstr "തുടരുക" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "ജനറേഷൻ നിർത്തുക" @@ -4441,6 +4449,10 @@ msgstr "ടെസ്റ്റിമോണിയലുകൾ" msgid "Testing…" msgstr "… പരിശോധിക്കുന്നു" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "വാചക വിന്യാസം" @@ -5399,4 +5411,3 @@ msgstr "സൂം ഔട്ട് ചെയ്യുക" #: src/libs/locale.ts msgid "Zulu" msgstr "സൂളു" - diff --git a/apps/web/locales/mr-IN.po b/apps/web/locales/mr-IN.po index d6dc7d495..a63f4e631 100644 --- a/apps/web/locales/mr-IN.po +++ b/apps/web/locales/mr-IN.po @@ -985,6 +985,10 @@ msgstr "जोडलेले" msgid "Connection failed" msgstr "कनेक्शन अयशस्वी झाले." +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "कनेक्शन सत्यापित झाले आहे — प्रोव्हायडर वापरासाठी तयार आहे." @@ -4309,6 +4313,10 @@ msgstr "आकडेवारी" msgid "Stay" msgstr "राहा" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "पिढी थांबवा" @@ -4441,6 +4449,10 @@ msgstr "प्रशस्तिपत्रे" msgid "Testing…" msgstr "चाचणी…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "मजकूर संरेखन" @@ -5399,4 +5411,3 @@ msgstr "बाहेर झूम करा" #: src/libs/locale.ts msgid "Zulu" msgstr "झुलू" - diff --git a/apps/web/locales/ms-MY.po b/apps/web/locales/ms-MY.po index 625b07cdc..567365b0f 100644 --- a/apps/web/locales/ms-MY.po +++ b/apps/web/locales/ms-MY.po @@ -985,6 +985,10 @@ msgstr "Bersambung" msgid "Connection failed" msgstr "Sambungan gagal" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Sambungan disahkan — pembekal sedia untuk digunakan." @@ -4309,6 +4313,10 @@ msgstr "Statistik" msgid "Stay" msgstr "Kekal" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Hentikan penjanaan" @@ -4441,6 +4449,10 @@ msgstr "Testimoni" msgid "Testing…" msgstr "Pengujian…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Penjajaran teks" @@ -5399,4 +5411,3 @@ msgstr "Zum keluar" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/ne-NP.po b/apps/web/locales/ne-NP.po index 271f4947f..8dac6613d 100644 --- a/apps/web/locales/ne-NP.po +++ b/apps/web/locales/ne-NP.po @@ -985,6 +985,10 @@ msgstr "जडित" msgid "Connection failed" msgstr "जडान असफल भयो" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "जडान प्रमाणित भयो — प्रदायक प्रयोगको लागि तयार छ।" @@ -4309,6 +4313,10 @@ msgstr "तथ्याङ्क (Statistics)" msgid "Stay" msgstr "रहनुहोस्" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "उत्पादन रोक्नुहोस्" @@ -4441,6 +4449,10 @@ msgstr "अनुभव कथनहरू (Testimonials)" msgid "Testing…" msgstr "परीक्षण…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "पाठ पङ्क्तिबद्धता" @@ -5399,4 +5411,3 @@ msgstr "जूम आउट" #: src/libs/locale.ts msgid "Zulu" msgstr "जुलु" - diff --git a/apps/web/locales/nl-NL.po b/apps/web/locales/nl-NL.po index dccf95c29..e247d995c 100644 --- a/apps/web/locales/nl-NL.po +++ b/apps/web/locales/nl-NL.po @@ -985,6 +985,10 @@ msgstr "Aangesloten" msgid "Connection failed" msgstr "Verbinding mislukt" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Verbinding geverifieerd — provider is klaar voor gebruik." @@ -4309,6 +4313,10 @@ msgstr "Statistieken" msgid "Stay" msgstr "Blijven" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Stop de generatie" @@ -4441,6 +4449,10 @@ msgstr "Getuigenissen" msgid "Testing…" msgstr "Testen…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Tekstuitlijning" @@ -5399,4 +5411,3 @@ msgstr "Uitzoomen" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/no-NO.po b/apps/web/locales/no-NO.po index 265a69893..d2153727b 100644 --- a/apps/web/locales/no-NO.po +++ b/apps/web/locales/no-NO.po @@ -985,6 +985,10 @@ msgstr "Tilkoblet" msgid "Connection failed" msgstr "Tilkoblingen mislyktes" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Tilkobling bekreftet – leverandøren er klar til bruk." @@ -4309,6 +4313,10 @@ msgstr "Statistikk" msgid "Stay" msgstr "Bli" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Stopp generering" @@ -4441,6 +4449,10 @@ msgstr "Uttalelser" msgid "Testing…" msgstr "Testing…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Tekstjustering" @@ -5399,4 +5411,3 @@ msgstr "Zoom ut" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/or-IN.po b/apps/web/locales/or-IN.po index e6529b43a..a4c39ca4d 100644 --- a/apps/web/locales/or-IN.po +++ b/apps/web/locales/or-IN.po @@ -985,6 +985,10 @@ msgstr "ସଂଯୁକ୍ତ" msgid "Connection failed" msgstr "ସଂଯୋଗ ବିଫଳ ହୋଇଛି" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "ସଂଯୋଗ ଯାଞ୍ଚ ହୋଇଛି — ପ୍ରଦାତା ବ୍ୟବହାର କରିବାକୁ ପ୍ରସ୍ତୁତ।" @@ -4309,6 +4313,10 @@ msgstr "ସଂଖ୍ୟାତ୍ମକ ତଥ୍ୟ" msgid "Stay" msgstr "ରୁହନ୍ତୁ" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "ପିଢ଼ିବା ବନ୍ଦ କରନ୍ତୁ" @@ -4441,6 +4449,10 @@ msgstr "ଟେଷ୍ଟିମୋନିଆଲ୍‌ଗୁଡିକ" msgid "Testing…" msgstr "ପରୀକ୍ଷଣ…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "ଟେକ୍ସଟ୍ ଶ୍ରେଣୀବଦ୍ଧତା" @@ -5399,4 +5411,3 @@ msgstr "ଜୁମ୍ ଆଉଟ୍ କରନ୍ତୁ" #: src/libs/locale.ts msgid "Zulu" msgstr "ଜୁଲୁ" - diff --git a/apps/web/locales/pl-PL.po b/apps/web/locales/pl-PL.po index 3ac78c1a4..7a7ccd630 100644 --- a/apps/web/locales/pl-PL.po +++ b/apps/web/locales/pl-PL.po @@ -985,6 +985,10 @@ msgstr "Połączony" msgid "Connection failed" msgstr "Połączenie nieudane" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Połączenie zweryfikowane — dostawca jest gotowy do użycia." @@ -4309,6 +4313,10 @@ msgstr "Statystyki" msgid "Stay" msgstr "Zostań" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Zatrzymaj generację" @@ -4441,6 +4449,10 @@ msgstr "Referencje" msgid "Testing…" msgstr "Testowanie…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Wyrównanie tekstu" @@ -5399,4 +5411,3 @@ msgstr "Pomniejsz" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/pt-BR.po b/apps/web/locales/pt-BR.po index e3cd63fb9..fcd235739 100644 --- a/apps/web/locales/pt-BR.po +++ b/apps/web/locales/pt-BR.po @@ -985,6 +985,10 @@ msgstr "Conectado" msgid "Connection failed" msgstr "Falha na conexão" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Conexão verificada — o provedor está pronto para uso." @@ -4309,6 +4313,10 @@ msgstr "Estatísticas" msgid "Stay" msgstr "Ficar" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Pare a geração" @@ -4441,6 +4449,10 @@ msgstr "Depoimentos" msgid "Testing…" msgstr "Testando…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Alinhamento de texto" @@ -5399,4 +5411,3 @@ msgstr "Diminuir zoom" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/pt-PT.po b/apps/web/locales/pt-PT.po index 7caeeeb9c..a765bc102 100644 --- a/apps/web/locales/pt-PT.po +++ b/apps/web/locales/pt-PT.po @@ -985,6 +985,10 @@ msgstr "Conectado" msgid "Connection failed" msgstr "Falha na ligação" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Ligação verificada — o fornecedor está pronto a utilizar." @@ -4309,6 +4313,10 @@ msgstr "Estatísticas" msgid "Stay" msgstr "Ficar" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Pare a geração" @@ -4441,6 +4449,10 @@ msgstr "Testemunhos" msgid "Testing…" msgstr "A testar…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Alinhamento de texto" @@ -5399,4 +5411,3 @@ msgstr "Afastar" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/ro-RO.po b/apps/web/locales/ro-RO.po index 764eb8dc8..ce60c6ecd 100644 --- a/apps/web/locales/ro-RO.po +++ b/apps/web/locales/ro-RO.po @@ -985,6 +985,10 @@ msgstr "Conectat" msgid "Connection failed" msgstr "Conexiunea a eșuat" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Conexiune verificată — furnizorul este gata de utilizare." @@ -4309,6 +4313,10 @@ msgstr "Statistici" msgid "Stay" msgstr "Rămâi" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Opriți generarea" @@ -4441,6 +4449,10 @@ msgstr "Testimoniale" msgid "Testing…" msgstr "Testarea…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Alinierea textului" @@ -5399,4 +5411,3 @@ msgstr "Micșorează" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/ru-RU.po b/apps/web/locales/ru-RU.po index 8dcf4885e..e37f703f0 100644 --- a/apps/web/locales/ru-RU.po +++ b/apps/web/locales/ru-RU.po @@ -985,6 +985,10 @@ msgstr "Подключено" msgid "Connection failed" msgstr "Соединение не удалось." +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Соединение подтверждено — провайдер готов к использованию." @@ -4309,6 +4313,10 @@ msgstr "Статистика" msgid "Stay" msgstr "Остаться" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Остановить поколение" @@ -4441,6 +4449,10 @@ msgstr "Отзывы" msgid "Testing…" msgstr "Тестирование…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "выравнивание текста" @@ -5399,4 +5411,3 @@ msgstr "Уменьшить" #: src/libs/locale.ts msgid "Zulu" msgstr "Зулу" - diff --git a/apps/web/locales/sk-SK.po b/apps/web/locales/sk-SK.po index 4713e1694..78a6f0d99 100644 --- a/apps/web/locales/sk-SK.po +++ b/apps/web/locales/sk-SK.po @@ -985,6 +985,10 @@ msgstr "Pripojené" msgid "Connection failed" msgstr "Pripojenie zlyhalo" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Pripojenie overené – poskytovateľ je pripravený na použitie." @@ -4309,6 +4313,10 @@ msgstr "Štatistiky" msgid "Stay" msgstr "Zostať" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Zastaviť generovanie" @@ -4441,6 +4449,10 @@ msgstr "Referencie používateľov" msgid "Testing…" msgstr "Testovanie…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Zarovnanie textu" @@ -5399,4 +5411,3 @@ msgstr "Oddialiť" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/sl-SI.po b/apps/web/locales/sl-SI.po index fce14989e..8474a4b0b 100644 --- a/apps/web/locales/sl-SI.po +++ b/apps/web/locales/sl-SI.po @@ -985,6 +985,10 @@ msgstr "Povezan" msgid "Connection failed" msgstr "Povezava ni uspela" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Povezava preverjena – ponudnik je pripravljen za uporabo." @@ -4309,6 +4313,10 @@ msgstr "Statistika" msgid "Stay" msgstr "Ostani" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Ustavi generiranje" @@ -4441,6 +4449,10 @@ msgstr "Pričevanja" msgid "Testing…" msgstr "Testiranje…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Poravnava besedila" @@ -5399,4 +5411,3 @@ msgstr "Oddalji" #: src/libs/locale.ts msgid "Zulu" msgstr "Zuluščina" - diff --git a/apps/web/locales/sq-AL.po b/apps/web/locales/sq-AL.po index 52496d61f..bc18c6bb1 100644 --- a/apps/web/locales/sq-AL.po +++ b/apps/web/locales/sq-AL.po @@ -985,6 +985,10 @@ msgstr "I lidhur" msgid "Connection failed" msgstr "Lidhja dështoi" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Lidhja u verifikua — ofruesi është gati për përdorim." @@ -4309,6 +4313,10 @@ msgstr "Statistikat" msgid "Stay" msgstr "Qëndro" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Ndalo gjenerimin" @@ -4441,6 +4449,10 @@ msgstr "Dëshmitë" msgid "Testing…" msgstr "Testimi…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Rreshtimi i tekstit" @@ -5399,4 +5411,3 @@ msgstr "Zvogëlo" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/sr-SP.po b/apps/web/locales/sr-SP.po index c1525bd41..b197e7957 100644 --- a/apps/web/locales/sr-SP.po +++ b/apps/web/locales/sr-SP.po @@ -985,6 +985,10 @@ msgstr "Повезано" msgid "Connection failed" msgstr "Повезивање није успело" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Веза је верификована — провајдер је спреман за употребу." @@ -4309,6 +4313,10 @@ msgstr "Статистика" msgid "Stay" msgstr "Остани" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Заустави генерисање" @@ -4441,6 +4449,10 @@ msgstr "Сведочења" msgid "Testing…" msgstr "Тестирање…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Поравнање текста" @@ -5399,4 +5411,3 @@ msgstr "Умањи" #: src/libs/locale.ts msgid "Zulu" msgstr "Зулу" - diff --git a/apps/web/locales/sv-SE.po b/apps/web/locales/sv-SE.po index b58268f1b..63921869c 100644 --- a/apps/web/locales/sv-SE.po +++ b/apps/web/locales/sv-SE.po @@ -985,6 +985,10 @@ msgstr "Ansluten" msgid "Connection failed" msgstr "Anslutningen misslyckades" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Anslutning verifierad — leverantören är klar att användas." @@ -4309,6 +4313,10 @@ msgstr "Statistik" msgid "Stay" msgstr "Stanna" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Stoppa genereringen" @@ -4441,6 +4449,10 @@ msgstr "Vittnesmål" msgid "Testing…" msgstr "Testning…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Textjustering" @@ -5399,4 +5411,3 @@ msgstr "Zooma ut" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/ta-IN.po b/apps/web/locales/ta-IN.po index 0ede30e23..8d9a477a4 100644 --- a/apps/web/locales/ta-IN.po +++ b/apps/web/locales/ta-IN.po @@ -985,6 +985,10 @@ msgstr "இணைக்கப்பட்டது" msgid "Connection failed" msgstr "இணைப்பு தோல்வியடைந்தது" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "இணைப்பு சரிபார்க்கப்பட்டது — சேவை வழங்குநர் பயன்பாட்டிற்குத் தயாராக உள்ளது." @@ -4309,6 +4313,10 @@ msgstr "புள்ளிவிபரங்கள்" msgid "Stay" msgstr "தங்கு" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "நிறுத்த உருவாக்கம்" @@ -4441,6 +4449,10 @@ msgstr "சான்றுரைகள்" msgid "Testing…" msgstr "சோதனை…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "உரை சீரமைப்பு" @@ -5399,4 +5411,3 @@ msgstr "சிறிதாக்கு" #: src/libs/locale.ts msgid "Zulu" msgstr "ஜூலு" - diff --git a/apps/web/locales/te-IN.po b/apps/web/locales/te-IN.po index 294ad93a8..2df833478 100644 --- a/apps/web/locales/te-IN.po +++ b/apps/web/locales/te-IN.po @@ -985,6 +985,10 @@ msgstr "కనెక్ట్ చేయబడింది" msgid "Connection failed" msgstr "కనెక్షన్ విఫలమైంది" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "కనెక్షన్ ధృవీకరించబడింది — ప్రొవైడర్ ఉపయోగించడానికి సిద్ధంగా ఉంది." @@ -4309,6 +4313,10 @@ msgstr "స్టాటిస్టిక్స్" msgid "Stay" msgstr "ఉండు" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "తరాన్ని ఆపండి" @@ -4441,6 +4449,10 @@ msgstr "టెస్టిమోనియల్స్" msgid "Testing…" msgstr "…ని పరీక్షిస్తోంది" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "టెక్స్ట్ అమరిక" @@ -5399,4 +5411,3 @@ msgstr "జూమ్ అవుట్ చేయండి" #: src/libs/locale.ts msgid "Zulu" msgstr "జులు" - diff --git a/apps/web/locales/th-TH.po b/apps/web/locales/th-TH.po index 3e7dde12f..7a9d30105 100644 --- a/apps/web/locales/th-TH.po +++ b/apps/web/locales/th-TH.po @@ -985,6 +985,10 @@ msgstr "เชื่อมต่อแล้ว" msgid "Connection failed" msgstr "การเชื่อมต่อล้มเหลว" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "การเชื่อมต่อได้รับการยืนยันแล้ว — ผู้ให้บริการพร้อมใช้งาน" @@ -4309,6 +4313,10 @@ msgstr "สถิติ" msgid "Stay" msgstr "อยู่ต่อ" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "หยุดการสร้าง" @@ -4441,6 +4449,10 @@ msgstr "คำรับรอง" msgid "Testing…" msgstr "กำลังทดสอบ…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "การจัดตำแหน่งข้อความ" @@ -5399,4 +5411,3 @@ msgstr "ซูมออก" #: src/libs/locale.ts msgid "Zulu" msgstr "ซูลู" - diff --git a/apps/web/locales/tr-TR.po b/apps/web/locales/tr-TR.po index 0351db3da..3201a3abb 100644 --- a/apps/web/locales/tr-TR.po +++ b/apps/web/locales/tr-TR.po @@ -985,6 +985,10 @@ msgstr "Bağlı" msgid "Connection failed" msgstr "Bağlantı başarısız oldu." +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Bağlantı doğrulandı — sağlayıcı kullanıma hazır." @@ -4309,6 +4313,10 @@ msgstr "İstatistikler" msgid "Stay" msgstr "Kal" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Üretimi durdurun" @@ -4441,6 +4449,10 @@ msgstr "Görüşler" msgid "Testing…" msgstr "Test ediliyor…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Metin hizalaması" @@ -5399,4 +5411,3 @@ msgstr "Uzaklaştır" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/uk-UA.po b/apps/web/locales/uk-UA.po index 17e13d128..df9201ebf 100644 --- a/apps/web/locales/uk-UA.po +++ b/apps/web/locales/uk-UA.po @@ -985,6 +985,10 @@ msgstr "Підключено" msgid "Connection failed" msgstr "Помилка підключення" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "З’єднання перевірено — провайдер готовий до використання." @@ -4309,6 +4313,10 @@ msgstr "Статистика" msgid "Stay" msgstr "Залишитись" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Зупинити генерацію" @@ -4441,6 +4449,10 @@ msgstr "Відгуки" msgid "Testing…" msgstr "Тестування…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Вирівнювання тексту" @@ -5399,4 +5411,3 @@ msgstr "Зменшити" #: src/libs/locale.ts msgid "Zulu" msgstr "Зулу" - diff --git a/apps/web/locales/uz-UZ.po b/apps/web/locales/uz-UZ.po index f0c477161..cd311c826 100644 --- a/apps/web/locales/uz-UZ.po +++ b/apps/web/locales/uz-UZ.po @@ -985,6 +985,10 @@ msgstr "Ulangan" msgid "Connection failed" msgstr "Ulanish amalga oshmadi" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Ulanish tasdiqlandi — provayder foydalanishga tayyor." @@ -4309,6 +4313,10 @@ msgstr "Statistika" msgid "Stay" msgstr "Qolish" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Avlodni to'xtatish" @@ -4441,6 +4449,10 @@ msgstr "Fikr-mulohazalar" msgid "Testing…" msgstr "Sinov…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Matnni tekislash" @@ -5399,4 +5411,3 @@ msgstr "Kichraytirish" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/vi-VN.po b/apps/web/locales/vi-VN.po index 805f07149..3f97b56a0 100644 --- a/apps/web/locales/vi-VN.po +++ b/apps/web/locales/vi-VN.po @@ -985,6 +985,10 @@ msgstr "Đã kết nối" msgid "Connection failed" msgstr "Kết nối thất bại" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "Kết nối đã được xác nhận — nhà cung cấp đã sẵn sàng sử dụng." @@ -4309,6 +4313,10 @@ msgstr "Thống kê" msgid "Stay" msgstr "Ở lại" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "Ngừng sản xuất" @@ -4441,6 +4449,10 @@ msgstr "Lời nhận xét" msgid "Testing…" msgstr "Đang kiểm tra…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "Căn chỉnh văn bản" @@ -5399,4 +5411,3 @@ msgstr "Thu nhỏ" #: src/libs/locale.ts msgid "Zulu" msgstr "Zulu" - diff --git a/apps/web/locales/zh-CN.po b/apps/web/locales/zh-CN.po index 10cd5eb14..98352efac 100644 --- a/apps/web/locales/zh-CN.po +++ b/apps/web/locales/zh-CN.po @@ -985,6 +985,10 @@ msgstr "已连接" msgid "Connection failed" msgstr "连接失败" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "连接已验证——服务提供商已准备就绪。" @@ -4309,6 +4313,10 @@ msgstr "统计数据" msgid "Stay" msgstr "留下" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "停止生成" @@ -4441,6 +4449,10 @@ msgstr "客户评价" msgid "Testing…" msgstr "测试…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "文本对齐" @@ -5399,4 +5411,3 @@ msgstr "缩小" #: src/libs/locale.ts msgid "Zulu" msgstr "祖鲁语" - diff --git a/apps/web/locales/zh-TW.po b/apps/web/locales/zh-TW.po index 78985e5b9..008e7ee65 100644 --- a/apps/web/locales/zh-TW.po +++ b/apps/web/locales/zh-TW.po @@ -985,6 +985,10 @@ msgstr "已連接" msgid "Connection failed" msgstr "連線失敗" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "連線已驗證-服務提供者已準備就緒。" @@ -4309,6 +4313,10 @@ msgstr "統計資料" msgid "Stay" msgstr "留下" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "停止生成" @@ -4441,6 +4449,10 @@ msgstr "用戶評價" msgid "Testing…" msgstr "測試…" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "文字對齊" @@ -5399,4 +5411,3 @@ msgstr "縮小" #: src/libs/locale.ts msgid "Zulu" msgstr "祖魯語" - diff --git a/apps/web/locales/zu-ZA.po b/apps/web/locales/zu-ZA.po index 5801d2008..c615fca7e 100644 --- a/apps/web/locales/zu-ZA.po +++ b/apps/web/locales/zu-ZA.po @@ -980,6 +980,10 @@ msgstr "" msgid "Connection failed" msgstr "" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Connection failed." +msgstr "" + #: src/features/settings/integrations/components/ai-section.tsx msgid "Connection verified — provider is ready to use." msgstr "" @@ -4304,6 +4308,10 @@ msgstr "" msgid "Stay" msgstr "" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Still waiting for {provider}… {elapsedSeconds}s" +msgstr "" + #: src/routes/agent/-components/agent-chat.tsx msgid "Stop generation" msgstr "" @@ -4436,6 +4444,10 @@ msgstr "" msgid "Testing…" msgstr "" +#: src/features/settings/integrations/components/ai-section.tsx +msgid "Testing… {elapsedSeconds}s" +msgstr "" + #: src/components/input/rich-input.tsx msgid "Text alignment" msgstr "" diff --git a/apps/web/src/features/settings/integrations/components/ai-section.test.tsx b/apps/web/src/features/settings/integrations/components/ai-section.test.tsx index 8210a0b42..1a53d1dce 100644 --- a/apps/web/src/features/settings/integrations/components/ai-section.test.tsx +++ b/apps/web/src/features/settings/integrations/components/ai-section.test.tsx @@ -4,6 +4,7 @@ import { fireEvent, render, screen, waitFor } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { i18n } from "@lingui/core"; import { I18nProvider } from "@lingui/react"; +import { toast } from "sonner"; type MutationName = "create" | "test" | "update" | "delete"; @@ -191,6 +192,35 @@ describe("AISettingsSection", () => { expect(updater([created])).toEqual([tested]); }); + // The server returns a provider-side failure as data (see the API package's e2e coverage), so the + // reason has to reach the card rather than being flattened into a generic transport error. + it("shows the server's reason on the card and keeps the toast to the outcome", async () => { + const failed = provider({ + enabled: false, + testStatus: "failure", + testError: "OpenAI rejected the API key.", + lastTestedAt: new Date("2026-08-15T00:00:00Z"), + }); + + providers.data = [provider({})]; + mutations.test.mockResolvedValue(failed); + + renderSection(); + fireEvent.click(screen.getByRole("button", { name: "Test" })); + + await waitFor(() => expect(toast.error).toHaveBeenCalled()); + + // Toast reports only the outcome; the card carries the detail. + expect(toast.error).toHaveBeenCalledWith("Connection failed."); + expect(toast.error).not.toHaveBeenCalledWith(expect.stringContaining("rejected the API key")); + + providers.data = [failed]; + renderSection(); + + expect(screen.getAllByText("OpenAI rejected the API key.").length).toBeGreaterThan(0); + expect(screen.getAllByText("Connection failed").length).toBeGreaterThan(0); + }); + it("updates a configured provider's model", async () => { providers.data = [provider({})]; mutations.update.mockResolvedValue(provider({ model: "gpt-5-mini", testStatus: "untested", enabled: false })); diff --git a/apps/web/src/features/settings/integrations/components/ai-section.tsx b/apps/web/src/features/settings/integrations/components/ai-section.tsx index 9afeb8fe0..605d6e048 100644 --- a/apps/web/src/features/settings/integrations/components/ai-section.tsx +++ b/apps/web/src/features/settings/integrations/components/ai-section.tsx @@ -14,7 +14,7 @@ import { XCircleIcon, } from "@phosphor-icons/react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; -import { useMemo, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { toast } from "sonner"; import { AI_PROVIDER_DEFAULT_BASE_URLS } from "@reactive-resume/ai/types"; import { Badge } from "@reactive-resume/ui/components/badge"; @@ -193,6 +193,36 @@ function providerLabel(provider: AIProvider) { return providerOptions.find((option) => option.value === provider)?.label ?? provider; } +// A provider test can legitimately take tens of seconds against a cold local model. Without a sense +// of time passing, a bare spinner reads as a freeze, so start narrating the wait once it gets long. +const SHOW_ELAPSED_AFTER_SECONDS = 5; +const STILL_WAITING_AFTER_SECONDS = 20; + +function useElapsedSeconds(isRunning: boolean) { + const [seconds, setSeconds] = useState(0); + + useEffect(() => { + if (!isRunning) { + setSeconds(0); + return; + } + + const startedAt = Date.now(); + const interval = setInterval(() => setSeconds(Math.floor((Date.now() - startedAt) / 1000)), 1000); + + return () => clearInterval(interval); + }, [isRunning]); + + return seconds; +} + +function testingLabel(elapsedSeconds: number, provider: string) { + if (elapsedSeconds >= STILL_WAITING_AFTER_SECONDS) return t`Still waiting for ${provider}… ${elapsedSeconds}s`; + if (elapsedSeconds >= SHOW_ELAPSED_AFTER_SECONDS) return t`Testing… ${elapsedSeconds}s`; + + return null; +} + function upsertProvider(providers: SavedProvider[] | undefined, provider: SavedProvider) { if (!providers) return [provider]; if (!providers.some((entry) => entry.id === provider.id)) return [...providers, provider]; @@ -217,6 +247,8 @@ function ProviderRow({ provider }: ProviderRowProps) { const { mutate: updateProvider, isPending: isUpdating } = useMutation(orpc.aiProviders.update.mutationOptions()); const { mutate: deleteProvider, isPending: isDeleting } = useMutation(orpc.aiProviders.delete.mutationOptions()); const isMutating = isTesting || isUpdating || isDeleting; + const testElapsedSeconds = useElapsedSeconds(isTesting); + const testLabel = testingLabel(testElapsedSeconds, String(providerLabel(provider.provider))); const saveModel = () => { const nextModel = model.trim(); if (!nextModel || nextModel === provider.model) { @@ -314,7 +346,8 @@ function ProviderRow({ provider }: ProviderRowProps) { if (response.testStatus === "success") { toast.success(t`Provider connection verified.`); } else { - toast.error(response.testError ?? t`Could not verify provider connection.`); + // The reason persists on the card below, so the toast only reports the outcome. + toast.error(t`Connection failed.`); } void invalidate(); }, @@ -327,7 +360,7 @@ function ProviderRow({ provider }: ProviderRowProps) { } > {isTesting ? : provider.testStatus === "success" ? : } - Test + {testLabel ?? Test} diff --git a/packages/ai/src/types.ts b/packages/ai/src/types.ts index 6244113d4..311d10965 100644 --- a/packages/ai/src/types.ts +++ b/packages/ai/src/types.ts @@ -41,3 +41,24 @@ export const AI_PROVIDER_DEFAULT_BASE_URLS: Record = { ollama: "https://ollama.com/api", "openai-compatible": "", }; + +// Brand names, used when a message has to name the provider outside a translated UI string. Every +// such message opens with this value, so the generic fallback is capitalised to match. +export const AI_PROVIDER_DISPLAY_NAMES: Record = { + openai: "OpenAI", + anthropic: "Anthropic", + gemini: "Google Gemini", + "vercel-ai-gateway": "Vercel AI Gateway", + openrouter: "OpenRouter", + mistral: "Mistral", + cohere: "Cohere", + xai: "xAI", + groq: "Groq", + deepseek: "DeepSeek", + togetherai: "Together AI", + fireworks: "Fireworks AI", + cerebras: "Cerebras", + perplexity: "Perplexity", + ollama: "Ollama", + "openai-compatible": "The provider", +}; diff --git a/packages/api/src/features/ai-providers/e2e.test.ts b/packages/api/src/features/ai-providers/e2e.test.ts new file mode 100644 index 000000000..ae21f5a50 --- /dev/null +++ b/packages/api/src/features/ai-providers/e2e.test.ts @@ -0,0 +1,203 @@ +/** + * End-to-end coverage for the provider connection test. + * + * Everything from the oRPC procedure down is the real thing: the router (including its auth + * middleware and error mapping), the service, `testConnection`, the failure classifier, and the + * AES-GCM credential encryption. Only the database and the outbound HTTP call are substituted — + * the database with an in-memory row store, the provider with a stubbed `fetch`. + */ +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { createRouterClient } from "@orpc/server"; + +const { dbMock, dbState } = vi.hoisted(() => { + const state = { rows: [] as Record[] }; + + const selectChain = { + from: () => selectChain, + where: () => selectChain, + orderBy: async () => state.rows, + limit: async () => state.rows, + }; + + const db = { + select: () => selectChain, + update: () => ({ + set: (values: Record) => ({ + where: () => { + const applied = state.rows.map((row) => Object.assign(row, values)); + return Object.assign(Promise.resolve(applied), { returning: async () => applied }); + }, + }), + }), + }; + + return { dbMock: db, dbState: state }; +}); + +vi.mock("@reactive-resume/db/client", () => ({ db: dbMock })); +vi.mock("@reactive-resume/db/schema", () => ({ + aiProvider: { id: "ai_provider.id", userId: "ai_provider.user_id" }, + user: { id: "user.id" }, +})); +vi.mock("drizzle-orm", () => ({ + and: (...conditions: unknown[]) => ({ conditions }), + asc: (value: unknown) => ({ value }), + desc: (value: unknown) => ({ value }), + eq: (left: unknown, right: unknown) => ({ left, right }), + sql: () => ({}), +})); + +// Real AES-GCM credential encryption runs; it only needs a secret. +vi.mock("@reactive-resume/env/server", () => ({ + env: { ENCRYPTION_SECRET: "e2e-encryption-secret", FLAG_ALLOW_UNSAFE_AI_BASE_URL: true }, +})); + +vi.mock("@reactive-resume/auth/config", () => ({ + auth: { + api: { + getSession: async () => ({ user: { id: "user-1", email: "kaushik@example.test" } }), + verifyApiKey: async () => ({ valid: false, key: null }), + }, + }, + verifyOAuthToken: async () => null, +})); + +const { aiProvidersRouter } = await import("./router"); +const { encryptCredential } = await import("../ai/credentials"); + +const client = createRouterClient(aiProvidersRouter, { + context: { locale: "en-US" as const, reqHeaders: new Headers() }, +}); + +function seedProvider(overrides: Record = {}) { + const credential = encryptCredential("sk-live-demo-key-1234"); + + dbState.rows = [ + { + id: "provider-1", + userId: "user-1", + label: "My provider", + provider: "openai", + model: "gpt-4.1", + baseUrl: "https://api.openai.test/v1", + enabled: false, + testStatus: "untested", + testError: null, + lastTestedAt: null, + lastUsedAt: null, + createdAt: new Date("2026-08-01T00:00:00Z"), + updatedAt: new Date("2026-08-01T00:00:00Z"), + ...credential, + ...overrides, + }, + ]; +} + +function stubProvider(status: number, body: unknown) { + const fetchMock = vi.fn( + () => + new Response(typeof body === "string" ? body : JSON.stringify(body), { + status, + headers: { "Content-Type": "application/json" }, + }), + ); + vi.stubGlobal("fetch", fetchMock); + return fetchMock; +} + +function chatCompletion(content: string) { + return { + id: "chatcmpl-1", + object: "chat.completion", + created: 1, + model: "gpt-4.1", + choices: [{ index: 0, message: { role: "assistant", content }, finish_reason: "stop" }], + usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }, + }; +} + +afterEach(() => { + vi.unstubAllGlobals(); +}); + +describe("POST /ai-providers/{id}/test — end to end", () => { + beforeEach(() => { + seedProvider(); + }); + + it("resolves with a usable provider and enables it", async () => { + stubProvider(200, chatCompletion("1")); + + const response = await client.test({ id: "provider-1" }); + + expect(response.testStatus).toBe("success"); + expect(response.testError).toBeNull(); + expect(response.enabled).toBe(true); + // The persisted row is what the dashboard reads on the next page load. + expect(dbState.rows[0]).toMatchObject({ testStatus: "success", testError: null, enabled: true }); + }); + + it("resolves — not rejects — when the provider rejects the key, and explains why", async () => { + stubProvider(401, { error: { message: "Incorrect API key provided." } }); + + // Before this change the procedure threw BAD_GATEWAY, so this call would reject. + const response = await client.test({ id: "provider-1" }); + + expect(response.testStatus).toBe("failure"); + expect(response.testError).toBe("OpenAI rejected the API key."); + expect(response.enabled).toBe(false); + expect(dbState.rows[0]?.testError).toBe("OpenAI rejected the API key."); + }); + + it("names the model when the provider returns not-found", async () => { + stubProvider(404, {}); + + const response = await client.test({ id: "provider-1" }); + + expect(response.testError).toBe('OpenAI has no model named "gpt-4.1", or the base URL is wrong.'); + }); + + it("attributes an outage to the provider and does not retry", async () => { + const fetchMock = stubProvider(503, {}); + + const response = await client.test({ id: "provider-1" }); + + expect(response.testError).toBe("OpenAI reported a server error (503). This is a problem on the provider's side."); + expect(fetchMock).toHaveBeenCalledTimes(1); + }); + + it("separates a reachable provider from a usable one", async () => { + stubProvider(200, chatCompletion("Of course! I am connected.")); + + const response = await client.test({ id: "provider-1" }); + + expect(response.testStatus).toBe("failure"); + expect(response.testError).toContain("reachable, but the model replied with unexpected output"); + }); + + it("never leaks the decrypted API key into the persisted error", async () => { + stubProvider(400, { error: { message: "Bad request for key sk-live-demo-key-1234" } }); + + const response = await client.test({ id: "provider-1" }); + + expect(response.testError).not.toContain("sk-live-demo-key-1234"); + expect(response.testError).toContain("***"); + }); + + it("still rejects with BAD_REQUEST when the base URL is not permitted", async () => { + // A blocked address must remain a configuration error, not a provider failure. + seedProvider({ baseUrl: "ftp://api.openai.test/v1" }); + stubProvider(200, chatCompletion("1")); + + await expect(client.test({ id: "provider-1" })).rejects.toMatchObject({ + code: "BAD_REQUEST", + message: "Invalid AI provider configuration.", + }); + }); + + it("rejects with NOT_FOUND when the provider belongs to nobody", async () => { + dbState.rows = []; + + await expect(client.test({ id: "provider-1" })).rejects.toMatchObject({ code: "NOT_FOUND" }); + }); +}); diff --git a/packages/api/src/features/ai-providers/service.ts b/packages/api/src/features/ai-providers/service.ts index fffbb8200..d7d7705af 100644 --- a/packages/api/src/features/ai-providers/service.ts +++ b/packages/api/src/features/ai-providers/service.ts @@ -228,19 +228,21 @@ export const aiProvidersService = { const apiKey = decryptCredential(provider.encryptedApiKey); try { - const ok = await testConnection({ + const result = await testConnection({ provider: parsedProvider, model: provider.model, apiKey, baseURL: provider.baseUrl ?? "", }); + // A provider that answers "no" is a completed test, not a failed request: it comes back as + // data so the client can show why, instead of a generic transport error. const [updated] = await db .update(schema.aiProvider) .set({ - enabled: ok, - testStatus: ok ? "success" : "failure", - testError: ok ? null : "The provider test returned an unexpected response.", + enabled: result.ok, + testStatus: result.ok ? "success" : "failure", + testError: result.ok ? null : result.message, lastTestedAt: new Date(), }) .where(and(eq(schema.aiProvider.id, input.id), eq(schema.aiProvider.userId, input.userId))) @@ -249,6 +251,7 @@ export const aiProvidersService = { if (!updated) throw new ORPCError("NOT_FOUND"); return toResponse(updated); } catch (error) { + // Only unexpected failures reach here now: provider-side outcomes come back as data above. await db .update(schema.aiProvider) .set({ diff --git a/packages/api/src/features/ai/service.test.ts b/packages/api/src/features/ai/service.test.ts index 471e0436a..57f3ef703 100644 --- a/packages/api/src/features/ai/service.test.ts +++ b/packages/api/src/features/ai/service.test.ts @@ -44,8 +44,130 @@ function stubOpenAICompatibleResponse(response?: { content?: string; finishReaso return { fetchMock, getRequestBody: () => requestBody }; } +function testInput(overrides?: { model?: string; apiKey?: string; baseURL?: string }) { + return { + provider: "openai-compatible" as const, + model: overrides?.model ?? "test-model", + apiKey: overrides?.apiKey ?? "test-key", + baseURL: overrides?.baseURL ?? "https://example.test/v1", + }; +} + +function stubFailedResponse(status: number, body = "{}") { + const fetchMock = vi.fn(() => new Response(body, { status, headers: { "Content-Type": "application/json" } })); + vi.stubGlobal("fetch", fetchMock); + + return fetchMock; +} + +function stubRejectedFetch(error: unknown) { + const fetchMock = vi.fn(() => Promise.reject(error)); + vi.stubGlobal("fetch", fetchMock); + + return fetchMock; +} + const { testConnection } = await import("./service"); +describe("AI provider connection test", () => { + it("names the rejected key instead of reporting a transport failure", async () => { + stubFailedResponse(401); + + await expect(testConnection(testInput())).resolves.toMatchObject({ + ok: false, + message: expect.stringContaining("rejected the API key"), + }); + }); + + it("points at the model when the provider returns a not-found status", async () => { + stubFailedResponse(404); + + await expect(testConnection(testInput({ model: "missing-model" }))).resolves.toMatchObject({ + ok: false, + message: expect.stringContaining('no model named "missing-model"'), + }); + }); + + it("distinguishes rate limiting from an outage", async () => { + stubFailedResponse(429); + + await expect(testConnection(testInput())).resolves.toMatchObject({ + ok: false, + message: expect.stringContaining("rate-limited"), + }); + }); + + it("attributes a server error to the provider", async () => { + stubFailedResponse(503); + + await expect(testConnection(testInput())).resolves.toMatchObject({ + ok: false, + message: expect.stringContaining("server error (503)"), + }); + }); + + it("reports an unreachable base URL rather than the socket error", async () => { + stubRejectedFetch( + Object.assign(new TypeError("fetch failed"), { + cause: Object.assign(new Error("connect ECONNREFUSED 127.0.0.1:11434"), { code: "ECONNREFUSED" }), + }), + ); + + await expect(testConnection(testInput({ baseURL: "https://example.test/v1" }))).resolves.toMatchObject({ + ok: false, + message: expect.stringContaining("Could not reach https://example.test/v1"), + }); + }); + + it("explains a timeout in terms of the wait the user just sat through", async () => { + stubRejectedFetch(new DOMException("The operation was aborted due to timeout", "TimeoutError")); + + await expect(testConnection(testInput())).resolves.toMatchObject({ + ok: false, + message: expect.stringContaining("did not respond within 30 seconds"), + }); + }); + + it("does not retry, so the test cannot silently multiply its own wait", async () => { + const fetchMock = stubFailedResponse(503); + + await testConnection(testInput()); + + expect(fetchMock).toHaveBeenCalledTimes(1); + }); + + it("separates a reachable provider from a usable one", async () => { + stubOpenAICompatibleResponse({ content: "Sure! The connection works.", finishReason: "stop" }); + + await expect(testConnection(testInput())).resolves.toMatchObject({ + ok: false, + message: expect.stringContaining("reachable"), + }); + }); + + it("keeps the API key out of a passed-through provider message", async () => { + stubFailedResponse(400, JSON.stringify({ error: { message: "Bad key sk-secret-value-123" } })); + + const result = await testConnection(testInput({ apiKey: "sk-secret-value-123" })); + + expect(result.ok).toBe(false); + if (!result.ok) expect(result.message).not.toContain("sk-secret-value-123"); + }); + + // The credentials schema accepts a single character, so short keys must be redacted too. + it("redacts a short API key as well", async () => { + stubFailedResponse(400, JSON.stringify({ error: { message: "Bad key tok123" } })); + + const result = await testConnection(testInput({ apiKey: "tok123" })); + + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.message).not.toContain("tok123"); + expect(result.message).toContain("***"); + } + }); +}); + describe("AI chat service", () => { it("tests OpenAI-compatible providers without requiring structured output", async () => { const openAiCompatible = stubOpenAICompatibleResponse(); @@ -57,7 +179,7 @@ describe("AI chat service", () => { apiKey: "test-key", baseURL: "https://example.test/v1", }), - ).resolves.toBe(true); + ).resolves.toEqual({ ok: true }); expect(openAiCompatible.fetchMock).toHaveBeenCalledTimes(1); expect(openAiCompatible.getRequestBody()).not.toHaveProperty("response_format"); @@ -67,14 +189,10 @@ describe("AI chat service", () => { it("explains when the provider test hits the output limit", async () => { stubOpenAICompatibleResponse({ content: "1. The connection works.", finishReason: "length" }); - await expect( - testConnection({ - provider: "openai-compatible", - model: "test-model", - apiKey: "test-key", - baseURL: "https://example.test/v1", - }), - ).rejects.toThrow("The model returned too much text during the provider test."); + await expect(testConnection(testInput())).resolves.toMatchObject({ + ok: false, + message: expect.stringContaining("returned too much text"), + }); }); it("keeps proposal tool history valid for follow-up chat messages", async () => { diff --git a/packages/api/src/features/ai/service.ts b/packages/api/src/features/ai/service.ts index b09bdd04f..755e04532 100644 --- a/packages/api/src/features/ai/service.ts +++ b/packages/api/src/features/ai/service.ts @@ -17,7 +17,17 @@ import { createPerplexity } from "@ai-sdk/perplexity"; import { createTogetherAI } from "@ai-sdk/togetherai"; import { createXai } from "@ai-sdk/xai"; import { streamToEventIterator } from "@orpc/server"; -import { convertToModelMessages, createGateway, generateText, stepCountIs, streamText, tool } from "ai"; +import { + APICallError, + convertToModelMessages, + createGateway, + generateText, + LoadAPIKeyError, + NoSuchModelError, + stepCountIs, + streamText, + tool, +} from "ai"; import { createOllama } from "ollama-ai-provider-v2"; import { match } from "ts-pattern"; import { z } from "zod"; @@ -36,7 +46,7 @@ import { resumePatchProposalToolInputSchema, resumePatchProposalToolOutputSchema, } from "@reactive-resume/ai/tools/patch-proposal"; -import { aiProviderSchema } from "@reactive-resume/ai/types"; +import { AI_PROVIDER_DEFAULT_BASE_URLS, AI_PROVIDER_DISPLAY_NAMES, aiProviderSchema } from "@reactive-resume/ai/types"; import { applyResumePatches } from "@reactive-resume/resume/patch"; import { resumeAnalysisSchema } from "@reactive-resume/schema/resume/analysis"; import { supportsProviderNativeWebSearch } from "./capabilities"; @@ -83,6 +93,8 @@ type GetModelInput = { const MAX_AI_FILE_BYTES = 10 * 1024 * 1024; // 10MB const MAX_AI_FILE_BASE64_CHARS = Math.ceil((MAX_AI_FILE_BYTES * 4) / 3) + 4; const TEST_CONNECTION_MAX_OUTPUT_TOKENS = 128; +// Long enough for a cold local model to load, short enough that the UI does not look frozen. +const TEST_CONNECTION_TIMEOUT_MS = 30_000; const DOCX_DOCUMENT_XML_PATH = "word/document.xml"; const ZIP_LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50; const ZIP_CENTRAL_DIRECTORY_SIGNATURE = 0x02014b50; @@ -144,20 +156,135 @@ export const fileInputSchema = z.object({ type TestConnectionInput = z.infer; -export async function testConnection(input: TestConnectionInput): Promise { - const RESPONSE_OK = "1"; +type TestConnectionResult = { ok: true } | { ok: false; message: string }; - const result = await generateText({ - model: getModel(input), - maxOutputTokens: TEST_CONNECTION_MAX_OUTPUT_TOKENS, - temperature: 0, - messages: [{ role: "user", content: `Respond only with the single character: ${RESPONSE_OK}` }], +const NETWORK_ERROR_CODES = new Set([ + "ECONNREFUSED", + "ECONNRESET", + "EAI_AGAIN", + "ENOTFOUND", + "ETIMEDOUT", + "UND_ERR_CONNECT_TIMEOUT", + "UND_ERR_SOCKET", +]); + +// Provider SDKs wrap the useful error (a socket failure, an abort) inside a generic one, so the +// signal we need is usually a few `cause` hops down rather than on the error we are handed. +function findInCauseChain(error: unknown, pick: (candidate: unknown) => T | undefined): T | undefined { + let current = error; + + for (let depth = 0; depth < 8 && current !== null && current !== undefined; depth++) { + const picked = pick(current); + if (picked !== undefined) return picked; + current = (current as { cause?: unknown }).cause; + } + + return undefined; +} + +function isTimeout(error: unknown): boolean { + return ( + findInCauseChain(error, (candidate) => + candidate instanceof Error && (candidate.name === "TimeoutError" || candidate.name === "AbortError") + ? true + : undefined, + ) ?? false + ); +} + +function findNetworkErrorCode(error: unknown): string | undefined { + return findInCauseChain(error, (candidate) => { + const code = (candidate as { code?: unknown }).code; + + return typeof code === "string" && NETWORK_ERROR_CODES.has(code) ? code : undefined; }); +} - if (result.text.trim() === RESPONSE_OK) return true; - if (result.finishReason === "length") throw new Error("The model returned too much text during the provider test."); +// The key is never part of a response body, but a provider echoing the request would leak it into +// the message we persist, so scrub it from anything we did not write ourselves. The schema allows +// keys as short as one character, and a mangled message costs less than a leaked credential, so +// every non-empty key is redacted. The guard only keeps `replaceAll` from splicing "***" between +// every character of the message. +function redactApiKey(message: string, apiKey: string): string { + if (!apiKey) return message; - return false; + return message.replaceAll(apiKey, "***"); +} + +function describeTestConnectionFailure(input: TestConnectionInput, error: unknown): string { + const provider = AI_PROVIDER_DISPLAY_NAMES[input.provider]; + const endpoint = input.baseURL.trim() || AI_PROVIDER_DEFAULT_BASE_URLS[input.provider]; + + if (isTimeout(error)) { + return `${provider} did not respond within ${TEST_CONNECTION_TIMEOUT_MS / 1000} seconds. The service may be unreachable, or the model may be too slow to load.`; + } + + if (findNetworkErrorCode(error)) { + return endpoint + ? `Could not reach ${endpoint}. Check that the base URL is correct and the service is running.` + : `${provider} could not be reached. Check that the base URL is correct and the service is running.`; + } + + if (LoadAPIKeyError.isInstance(error)) return `${provider} was configured without an API key.`; + if (NoSuchModelError.isInstance(error)) return `${provider} has no model named "${input.model}".`; + + if (APICallError.isInstance(error)) { + const status = error.statusCode; + + if (status === 401 || status === 403) return `${provider} rejected the API key.`; + if (status === 404) return `${provider} has no model named "${input.model}", or the base URL is wrong.`; + if (status === 429) return `${provider} rate-limited the test. Wait a moment and try again.`; + if (status !== undefined && status >= 500) { + return `${provider} reported a server error (${status}). This is a problem on the provider's side.`; + } + + return `${provider} rejected the test request${status === undefined ? "" : ` (${status})`}: ${redactApiKey(error.message, input.apiKey)}`; + } + + if (error instanceof Error && error.message) { + return `${provider} could not be tested: ${redactApiKey(error.message, input.apiKey)}`; + } + + return `${provider} could not be tested, and reported no reason.`; +} + +export async function testConnection(input: TestConnectionInput): Promise { + const RESPONSE_OK = "1"; + const provider = AI_PROVIDER_DISPLAY_NAMES[input.provider]; + + // Resolved outside the try so the base-URL policy error still reaches the router, which turns it + // into an invalid-configuration response rather than a provider failure. + const model = getModel(input); + + let result: Awaited>; + + try { + result = await generateText({ + model, + maxOutputTokens: TEST_CONNECTION_MAX_OUTPUT_TOKENS, + temperature: 0, + // A connection test must not silently multiply its own wait by retrying behind the user. + maxRetries: 0, + abortSignal: AbortSignal.timeout(TEST_CONNECTION_TIMEOUT_MS), + messages: [{ role: "user", content: `Respond only with the single character: ${RESPONSE_OK}` }], + }); + } catch (error) { + return { ok: false, message: describeTestConnectionFailure(input, error) }; + } + + if (result.text.trim() === RESPONSE_OK) return { ok: true }; + + if (result.finishReason === "length") { + return { + ok: false, + message: `${provider} is reachable, but the model returned too much text during the test. Try a model that follows short instructions.`, + }; + } + + return { + ok: false, + message: `${provider} is reachable, but the model replied with unexpected output instead of a simple confirmation.`, + }; } type ParsePdfInput = z.infer & {