diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a949acd730..29478c23984 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,32 @@ # Changelog +### [Version 1.142.3](https://github.com/lobehub/lobe-chat/compare/v1.142.2...v1.142.3) + +Released on **2025-10-27** + +#### 💄 Styles + +- **misc**: Adjust modal setting form styles for improved layout and responsiveness, Unzip file when uploading in knowledge base \[LOB-500]. + +
+ +
+Improvements and Fixes + +#### Styles + +- **misc**: Adjust modal setting form styles for improved layout and responsiveness, closes [#9890](https://github.com/lobehub/lobe-chat/issues/9890) ([1997ec5](https://github.com/lobehub/lobe-chat/commit/1997ec5)) +- **misc**: Unzip file when uploading in knowledge base \[LOB-500], closes [#9854](https://github.com/lobehub/lobe-chat/issues/9854) ([e568ce6](https://github.com/lobehub/lobe-chat/commit/e568ce6)) + +
+ +
+ +[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top) + +
+ ### [Version 1.142.2](https://github.com/lobehub/lobe-chat/compare/v1.142.1...v1.142.2) Released on **2025-10-26** diff --git a/README.md b/README.md index a79dd7a4785..12f7a67b58a 100644 --- a/README.md +++ b/README.md @@ -382,14 +382,14 @@ In addition, these plugins are not limited to news aggregation, but can also ext -| Recent Submits | Description | -| ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)
By **portfoliometa** on **2025-09-27** | Analyze stocks and get comprehensive real-time investment data and analytics.
`stock` | -| [Web](https://lobechat.com/discover/plugin/web)
By **Proghit** on **2025-01-24** | Smart web search that reads and analyzes pages to deliver comprehensive answers from Google results.
`web` `search` | -| [Bing_websearch](https://lobechat.com/discover/plugin/Bingsearch-identifier)
By **FineHow** on **2024-12-22** | Search for information from the internet base BingApi
`bingsearch` | -| [Google CSE](https://lobechat.com/discover/plugin/google-cse)
By **vsnthdev** on **2024-12-02** | Searches Google through their official CSE API.
`web` `search` | - -> 📊 Total plugins: [**41**](https://lobechat.com/discover/plugins) +| Recent Submits | Description | +| ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| [Shopping tools](https://lobechat.com/discover/plugin/ShoppingTools)
By **shoppingtools** on **2025-10-27** | Search for products on eBay & AliExpress, find eBay events & coupons. Get prompt examples.
`shopping` `e-bay` `ali-express` `coupons` | +| [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)
By **portfoliometa** on **2025-09-27** | Analyze stocks and get comprehensive real-time investment data and analytics.
`stock` | +| [Web](https://lobechat.com/discover/plugin/web)
By **Proghit** on **2025-01-24** | Smart web search that reads and analyzes pages to deliver comprehensive answers from Google results.
`web` `search` | +| [Bing_websearch](https://lobechat.com/discover/plugin/Bingsearch-identifier)
By **FineHow** on **2024-12-22** | Search for information from the internet base BingApi
`bingsearch` | + +> 📊 Total plugins: [**42**](https://lobechat.com/discover/plugins) diff --git a/README.zh-CN.md b/README.zh-CN.md index d3576ee4f60..30f75e4dd91 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -375,14 +375,14 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地 -| 最近新增 | 描述 | -| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | -| [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)
By **portfoliometa** on **2025-09-27** | 分析股票并获取全面的实时投资数据和分析。
`股票` | -| [网页](https://lobechat.com/discover/plugin/web)
By **Proghit** on **2025-01-24** | 智能网页搜索,读取和分析页面,以提供来自 Google 结果的全面答案。
`网页` `搜索` | -| [必应网页搜索](https://lobechat.com/discover/plugin/Bingsearch-identifier)
By **FineHow** on **2024-12-22** | 通过 BingApi 搜索互联网上的信息
`bingsearch` | -| [谷歌自定义搜索引擎](https://lobechat.com/discover/plugin/google-cse)
By **vsnthdev** on **2024-12-02** | 通过他们的官方自定义搜索引擎 API 搜索谷歌。
`网络` `搜索` | - -> 📊 Total plugins: [**41**](https://lobechat.com/discover/plugins) +| 最近新增 | 描述 | +| -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | +| [购物工具](https://lobechat.com/discover/plugin/ShoppingTools)
By **shoppingtools** on **2025-10-27** | 在 eBay 和 AliExpress 上搜索产品,查找 eBay 活动和优惠券。获取快速示例。
`购物` `e-bay` `ali-express` `优惠券` | +| [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)
By **portfoliometa** on **2025-09-27** | 分析股票并获取全面的实时投资数据和分析。
`股票` | +| [网页](https://lobechat.com/discover/plugin/web)
By **Proghit** on **2025-01-24** | 智能网页搜索,读取和分析页面,以提供来自 Google 结果的全面答案。
`网页` `搜索` | +| [必应网页搜索](https://lobechat.com/discover/plugin/Bingsearch-identifier)
By **FineHow** on **2024-12-22** | 通过 BingApi 搜索互联网上的信息
`bingsearch` | + +> 📊 Total plugins: [**42**](https://lobechat.com/discover/plugins) diff --git a/changelog/v1.json b/changelog/v1.json index d7a07668b7e..0a2a7950e3c 100644 --- a/changelog/v1.json +++ b/changelog/v1.json @@ -1,4 +1,13 @@ [ + { + "children": { + "improvements": [ + "Adjust modal setting form styles for improved layout and responsiveness, Unzip file when uploading in knowledge base [LOB-500]." + ] + }, + "date": "2025-10-27", + "version": "1.142.3" + }, { "children": { "improvements": ["Improve provider modal height when creating custom provider."] diff --git a/locales/ar/chat.json b/locales/ar/chat.json index 97bc5c396a7..a7ae42d699b 100644 --- a/locales/ar/chat.json +++ b/locales/ar/chat.json @@ -163,9 +163,9 @@ "addMember": "إضافة عضو", "allMembers": "جميع الأعضاء", "createGroup": "إنشاء فريق وكيل", - "noAvailableAgents": "لا يوجد مساعدين متاحين للدعوة", - "noSelectedAgents": "لم يتم اختيار مساعدين بعد", - "searchAgents": "البحث عن مساعدين...", + "noAvailableAgents": "لا يوجد وكلاء متاحون للدعوة", + "noSelectedAgents": "لم يتم اختيار أي وكيل بعد", + "searchAgents": "ابحث عن وكيل...", "setInitialMembers": "اختيار أعضاء الفريق" }, "members": "الأعضاء", @@ -229,7 +229,7 @@ "jumpToMessage": "الانتقال إلى الرسالة رقم {{index}}", "nextMessage": "الرسالة التالية", "previousMessage": "الرسالة السابقة", - "senderAssistant": "المساعد", + "senderAssistant": "الوكيل", "senderUser": "أنت" }, "newAgent": "مساعد جديد", diff --git a/locales/ar/file.json b/locales/ar/file.json index 795fafbee12..d7cd2353840 100644 --- a/locales/ar/file.json +++ b/locales/ar/file.json @@ -85,6 +85,7 @@ "restTime": "الوقت المتبقي {{time}}" } }, + "fileQueueInfo": "يتم حاليًا تحميل {{count}} ملفًا، وسيتم وضع {{remaining}} ملفًا في قائمة الانتظار للتحميل", "totalCount": "إجمالي {{count}} عنصر", "uploadStatus": { "error": "حدث خطأ أثناء الرفع", diff --git a/locales/ar/models.json b/locales/ar/models.json index 98bd0c160d8..45793a2152c 100644 --- a/locales/ar/models.json +++ b/locales/ar/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V مبني على نموذج GLM-4.5-Air الأساسي، يرث التقنيات المثبتة من GLM-4.1V-Thinking، ويوسعها بفعالية من خلال بنية MoE القوية التي تضم 106 مليار معلمة." } -} +} \ No newline at end of file diff --git a/locales/bg-BG/chat.json b/locales/bg-BG/chat.json index cc1932c750a..4c373207dee 100644 --- a/locales/bg-BG/chat.json +++ b/locales/bg-BG/chat.json @@ -163,9 +163,9 @@ "addMember": "Добавяне на член", "allMembers": "Всички членове", "createGroup": "Създаване на екип на Agent", - "noAvailableAgents": "Няма налични асистенти за покана", - "noSelectedAgents": "Все още не са избрани асистенти", - "searchAgents": "Търсене на асистенти...", + "noAvailableAgents": "Няма налични агенти за покана", + "noSelectedAgents": "Все още не са избрани агенти", + "searchAgents": "Търсене на агент...", "setInitialMembers": "Избор на членове на екипа" }, "members": "Членове", @@ -229,7 +229,7 @@ "jumpToMessage": "Отиди до съобщение № {{index}}", "nextMessage": "Следващо съобщение", "previousMessage": "Предишно съобщение", - "senderAssistant": "Асистент", + "senderAssistant": "Агент", "senderUser": "Ти" }, "newAgent": "Нов агент", diff --git a/locales/bg-BG/file.json b/locales/bg-BG/file.json index 33291da79bd..18c56963110 100644 --- a/locales/bg-BG/file.json +++ b/locales/bg-BG/file.json @@ -85,6 +85,7 @@ "restTime": "Остава {{time}}" } }, + "fileQueueInfo": "Качват се първите {{count}} файла, останалите {{remaining}} ще бъдат поставени в опашка за качване", "totalCount": "Общо {{count}} елемента", "uploadStatus": { "error": "Грешка при качване", diff --git a/locales/bg-BG/models.json b/locales/bg-BG/models.json index 60250b38755..28c6b7ac967 100644 --- a/locales/bg-BG/models.json +++ b/locales/bg-BG/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V е изграден върху основния модел GLM-4.5-Air, наследявайки проверените технологии на GLM-4.1V-Thinking и постига ефективно мащабиране чрез мощната MoE архитектура с 106 милиарда параметри." } -} +} \ No newline at end of file diff --git a/locales/de-DE/chat.json b/locales/de-DE/chat.json index a4b0e3aa1c6..620e78dfd2e 100644 --- a/locales/de-DE/chat.json +++ b/locales/de-DE/chat.json @@ -163,9 +163,9 @@ "addMember": "Mitglied hinzufügen", "allMembers": "Alle Mitglieder", "createGroup": "Agenten-Team erstellen", - "noAvailableAgents": "Keine verfügbaren Assistenten zum Einladen", - "noSelectedAgents": "Noch keine Assistenten ausgewählt", - "searchAgents": "Assistenten suchen...", + "noAvailableAgents": "Keine verfügbaren Agents zum Einladen", + "noSelectedAgents": "Noch keine Agents ausgewählt", + "searchAgents": "Agents suchen...", "setInitialMembers": "Teammitglieder auswählen" }, "members": "Mitglieder", @@ -229,7 +229,7 @@ "jumpToMessage": "Zur Nachricht Nr. {{index}} springen", "nextMessage": "Nächste Nachricht", "previousMessage": "Vorherige Nachricht", - "senderAssistant": "Assistent", + "senderAssistant": "Agent", "senderUser": "Du" }, "newAgent": "Neuer Assistent", diff --git a/locales/de-DE/file.json b/locales/de-DE/file.json index 4285d5a5a1a..c39e03655ac 100644 --- a/locales/de-DE/file.json +++ b/locales/de-DE/file.json @@ -85,6 +85,7 @@ "restTime": "Verbleibende Zeit {{time}}" } }, + "fileQueueInfo": "Die ersten {{count}} Dateien werden hochgeladen, die verbleibenden {{remaining}} Dateien werden in die Warteschlange gestellt", "totalCount": "Insgesamt {{count}} Elemente", "uploadStatus": { "error": "Fehler beim Hochladen", diff --git a/locales/de-DE/models.json b/locales/de-DE/models.json index 0a021fd740a..0b0d476ccd6 100644 --- a/locales/de-DE/models.json +++ b/locales/de-DE/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V basiert auf dem GLM-4.5-Air Basismodell, übernimmt bewährte Techniken von GLM-4.1V-Thinking und skaliert effektiv mit einer leistungsstarken MoE-Architektur mit 106 Milliarden Parametern." } -} +} \ No newline at end of file diff --git a/locales/en-US/chat.json b/locales/en-US/chat.json index 52927b16785..111da9ce00f 100644 --- a/locales/en-US/chat.json +++ b/locales/en-US/chat.json @@ -163,9 +163,9 @@ "addMember": "Add Member", "allMembers": "All members", "createGroup": "Create Agent Team", - "noAvailableAgents": "No assistants available to invite", - "noSelectedAgents": "No assistants selected yet", - "searchAgents": "Search assistants...", + "noAvailableAgents": "No available agents to invite", + "noSelectedAgents": "No agents selected yet", + "searchAgents": "Search agents...", "setInitialMembers": "Select Team Members" }, "members": "Members", @@ -229,7 +229,7 @@ "jumpToMessage": "Jump to message {{index}}", "nextMessage": "Next message", "previousMessage": "Previous message", - "senderAssistant": "Assistant", + "senderAssistant": "Agent", "senderUser": "You" }, "newAgent": "New Assistant", diff --git a/locales/en-US/file.json b/locales/en-US/file.json index 989509eba32..cdead05eb75 100644 --- a/locales/en-US/file.json +++ b/locales/en-US/file.json @@ -85,6 +85,7 @@ "restTime": "Remaining {{time}}" } }, + "fileQueueInfo": "Uploading the first {{count}} files, {{remaining}} remaining in queue", "totalCount": "Total {{count}} items", "uploadStatus": { "error": "Upload error", diff --git a/locales/en-US/models.json b/locales/en-US/models.json index 8bb84a06189..cb9af0c2858 100644 --- a/locales/en-US/models.json +++ b/locales/en-US/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V is built on the GLM-4.5-Air foundational model, inheriting the proven techniques of GLM-4.1V-Thinking while achieving efficient scaling through a powerful 106 billion parameter MoE architecture." } -} +} \ No newline at end of file diff --git a/locales/es-ES/chat.json b/locales/es-ES/chat.json index b245672a5f3..a6709fda45f 100644 --- a/locales/es-ES/chat.json +++ b/locales/es-ES/chat.json @@ -163,9 +163,9 @@ "addMember": "Agregar miembro", "allMembers": "Todos los miembros", "createGroup": "Crear equipo de agentes", - "noAvailableAgents": "No hay asistentes disponibles para invitar", - "noSelectedAgents": "No se ha seleccionado ningún asistente", - "searchAgents": "Buscar asistentes...", + "noAvailableAgents": "No hay agentes disponibles para invitar", + "noSelectedAgents": "Aún no se ha seleccionado ningún agente", + "searchAgents": "Buscar agentes...", "setInitialMembers": "Seleccionar miembros del equipo" }, "members": "Miembros", @@ -229,7 +229,7 @@ "jumpToMessage": "Ir al mensaje número {{index}}", "nextMessage": "Mensaje siguiente", "previousMessage": "Mensaje anterior", - "senderAssistant": "Asistente", + "senderAssistant": "Agente", "senderUser": "Tú" }, "newAgent": "Nuevo asistente", diff --git a/locales/es-ES/file.json b/locales/es-ES/file.json index ed829242c18..4f4ee670f94 100644 --- a/locales/es-ES/file.json +++ b/locales/es-ES/file.json @@ -85,6 +85,7 @@ "restTime": "Tiempo restante {{time}}" } }, + "fileQueueInfo": "Subiendo los primeros {{count}} archivos, los {{remaining}} restantes se pondrán en cola para subir", "totalCount": "Total {{count}} elementos", "uploadStatus": { "error": "Error en la subida", diff --git a/locales/es-ES/models.json b/locales/es-ES/models.json index fbb347534be..3fbc4bf96cb 100644 --- a/locales/es-ES/models.json +++ b/locales/es-ES/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V está construido sobre el modelo base GLM-4.5-Air, heredando la tecnología verificada de GLM-4.1V-Thinking y logrando una escalabilidad eficiente mediante una potente arquitectura MoE de 106 mil millones de parámetros." } -} +} \ No newline at end of file diff --git a/locales/fa-IR/chat.json b/locales/fa-IR/chat.json index 4dee3aaa359..01123f7c0e0 100644 --- a/locales/fa-IR/chat.json +++ b/locales/fa-IR/chat.json @@ -163,9 +163,9 @@ "addMember": "افزودن عضو", "allMembers": "تمام اعضا", "createGroup": "ایجاد تیم Agent", - "noAvailableAgents": "دستیار قابل دعوت وجود ندارد", - "noSelectedAgents": "هنوز دستیار انتخاب نشده است", - "searchAgents": "جستجوی دستیار...", + "noAvailableAgents": "هیچ عاملی برای دعوت در دسترس نیست", + "noSelectedAgents": "هنوز عاملی انتخاب نشده است", + "searchAgents": "جستجوی عامل...", "setInitialMembers": "انتخاب اعضای تیم" }, "members": "اعضا", @@ -229,7 +229,7 @@ "jumpToMessage": "رفتن به پیام شماره {{index}}", "nextMessage": "پیام بعدی", "previousMessage": "پیام قبلی", - "senderAssistant": "دستیار", + "senderAssistant": "عامل", "senderUser": "شما" }, "newAgent": "دستیار جدید", diff --git a/locales/fa-IR/file.json b/locales/fa-IR/file.json index 852d5d52109..7202b1cff98 100644 --- a/locales/fa-IR/file.json +++ b/locales/fa-IR/file.json @@ -85,6 +85,7 @@ "restTime": "زمان باقی‌مانده {{time}}" } }, + "fileQueueInfo": "در حال بارگذاری {{count}} فایل اول، {{remaining}} فایل باقی‌مانده در صف بارگذاری قرار خواهند گرفت", "totalCount": "مجموعاً {{count}} مورد", "uploadStatus": { "error": "خطا در بارگذاری", diff --git a/locales/fa-IR/models.json b/locales/fa-IR/models.json index ca1ddbd24bd..a4c34a64473 100644 --- a/locales/fa-IR/models.json +++ b/locales/fa-IR/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V بر پایه مدل پایه GLM-4.5-Air ساخته شده است، فناوری اثبات شده GLM-4.1V-Thinking را به ارث برده و در عین حال با معماری قدرتمند MoE با 106 میلیارد پارامتر به طور مؤثر مقیاس‌پذیر شده است." } -} +} \ No newline at end of file diff --git a/locales/fr-FR/chat.json b/locales/fr-FR/chat.json index ed8e0a3f22d..abd37a90f58 100644 --- a/locales/fr-FR/chat.json +++ b/locales/fr-FR/chat.json @@ -163,9 +163,9 @@ "addMember": "Ajouter un membre", "allMembers": "Tous les membres", "createGroup": "Créer un groupe d'agents", - "noAvailableAgents": "Aucun assistant disponible à inviter", - "noSelectedAgents": "Aucun assistant sélectionné", - "searchAgents": "Rechercher un assistant...", + "noAvailableAgents": "Aucun agent disponible à inviter", + "noSelectedAgents": "Aucun agent sélectionné pour le moment", + "searchAgents": "Rechercher un agent...", "setInitialMembers": "Sélectionner les membres du groupe" }, "members": "Membres", @@ -229,7 +229,7 @@ "jumpToMessage": "Aller au message n° {{index}}", "nextMessage": "Message suivant", "previousMessage": "Message précédent", - "senderAssistant": "Assistant", + "senderAssistant": "Agent", "senderUser": "Vous" }, "newAgent": "Nouvel agent", diff --git a/locales/fr-FR/file.json b/locales/fr-FR/file.json index 6e9e5d3b089..0356d92adf3 100644 --- a/locales/fr-FR/file.json +++ b/locales/fr-FR/file.json @@ -85,6 +85,7 @@ "restTime": "Temps restant {{time}}" } }, + "fileQueueInfo": "Téléversement des {{count}} premiers fichiers en cours, les {{remaining}} fichiers restants seront mis en file d’attente", "totalCount": "Total {{count}} éléments", "uploadStatus": { "error": "Erreur de téléchargement", diff --git a/locales/fr-FR/models.json b/locales/fr-FR/models.json index fc2cdcf5239..d05cf410688 100644 --- a/locales/fr-FR/models.json +++ b/locales/fr-FR/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V est construit sur le modèle de base GLM-4.5-Air, héritant des techniques éprouvées de GLM-4.1V-Thinking, tout en réalisant une mise à l'échelle efficace grâce à une puissante architecture MoE de 106 milliards de paramètres." } -} +} \ No newline at end of file diff --git a/locales/it-IT/chat.json b/locales/it-IT/chat.json index 4160718a1d4..42d117ce79b 100644 --- a/locales/it-IT/chat.json +++ b/locales/it-IT/chat.json @@ -163,9 +163,9 @@ "addMember": "Aggiungi membro", "allMembers": "Tutti i membri", "createGroup": "Crea un team di Agent", - "noAvailableAgents": "Nessun assistente disponibile da invitare", - "noSelectedAgents": "Nessun assistente selezionato", - "searchAgents": "Cerca assistenti...", + "noAvailableAgents": "Nessun agente disponibile da invitare", + "noSelectedAgents": "Nessun agente selezionato", + "searchAgents": "Cerca agenti...", "setInitialMembers": "Seleziona i membri del team" }, "members": "Membri", @@ -229,7 +229,7 @@ "jumpToMessage": "Vai al messaggio n. {{index}}", "nextMessage": "Messaggio successivo", "previousMessage": "Messaggio precedente", - "senderAssistant": "Assistente", + "senderAssistant": "Agente", "senderUser": "Tu" }, "newAgent": "Nuovo assistente", diff --git a/locales/it-IT/file.json b/locales/it-IT/file.json index a6dc3dad206..e6ffb23c052 100644 --- a/locales/it-IT/file.json +++ b/locales/it-IT/file.json @@ -85,6 +85,7 @@ "restTime": "Tempo rimanente {{time}}" } }, + "fileQueueInfo": "Caricamento in corso dei primi {{count}} file, i restanti {{remaining}} file saranno messi in coda", "totalCount": "Totale {{count}} elementi", "uploadStatus": { "error": "Errore di caricamento", diff --git a/locales/ja-JP/chat.json b/locales/ja-JP/chat.json index 74dfd4171ae..6d3336fc8c4 100644 --- a/locales/ja-JP/chat.json +++ b/locales/ja-JP/chat.json @@ -163,9 +163,9 @@ "addMember": "メンバーを追加", "allMembers": "全メンバー", "createGroup": "エージェントチームを作成", - "noAvailableAgents": "招待可能なアシスタントがいません", - "noSelectedAgents": "アシスタントが選択されていません", - "searchAgents": "アシスタントを検索...", + "noAvailableAgents": "招待可能なエージェントがいません", + "noSelectedAgents": "エージェントがまだ選択されていません", + "searchAgents": "エージェントを検索...", "setInitialMembers": "チームメンバーを選択" }, "members": "メンバー", @@ -229,7 +229,7 @@ "jumpToMessage": "メッセージ {{index}} へジャンプ", "nextMessage": "次のメッセージ", "previousMessage": "前のメッセージ", - "senderAssistant": "アシスタント", + "senderAssistant": "エージェント", "senderUser": "あなた" }, "newAgent": "新しいエージェント", diff --git a/locales/ja-JP/file.json b/locales/ja-JP/file.json index 6c81608ab54..a9237f93c48 100644 --- a/locales/ja-JP/file.json +++ b/locales/ja-JP/file.json @@ -85,6 +85,7 @@ "restTime": "残り {{time}}" } }, + "fileQueueInfo": "最初の {{count}} 件のファイルをアップロード中、残りの {{remaining}} 件は順番待ちです", "totalCount": "合計 {{count}} 件", "uploadStatus": { "error": "アップロードエラー", diff --git a/locales/ja-JP/models.json b/locales/ja-JP/models.json index 43690349c4e..9b6f71bcf3b 100644 --- a/locales/ja-JP/models.json +++ b/locales/ja-JP/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V は GLM-4.5-Air 基盤モデルに基づき、GLM-4.1V-Thinking の検証済み技術を継承しつつ、強力な1060億パラメータの MoE アーキテクチャで効率的にスケールアップしています。" } -} +} \ No newline at end of file diff --git a/locales/ko-KR/chat.json b/locales/ko-KR/chat.json index 56fc138626d..0a23d1f2e11 100644 --- a/locales/ko-KR/chat.json +++ b/locales/ko-KR/chat.json @@ -163,9 +163,9 @@ "addMember": "멤버 추가", "allMembers": "전체 멤버", "createGroup": "Agent 팀 만들기", - "noAvailableAgents": "초대할 보조자가 없습니다", - "noSelectedAgents": "아직 보조자를 선택하지 않았습니다", - "searchAgents": "보조자 검색...", + "noAvailableAgents": "초대할 수 있는 에이전트가 없습니다", + "noSelectedAgents": "선택된 에이전트가 없습니다", + "searchAgents": "에이전트 검색...", "setInitialMembers": "팀 구성원 선택" }, "members": "구성원", @@ -229,7 +229,7 @@ "jumpToMessage": "{{index}}번째 메시지로 이동", "nextMessage": "다음 메시지", "previousMessage": "이전 메시지", - "senderAssistant": "도우미", + "senderAssistant": "에이전트", "senderUser": "당신" }, "newAgent": "새 도우미", diff --git a/locales/ko-KR/file.json b/locales/ko-KR/file.json index 046f1fd2296..eeb57b50ad7 100644 --- a/locales/ko-KR/file.json +++ b/locales/ko-KR/file.json @@ -85,6 +85,7 @@ "restTime": "남은 시간 {{time}}" } }, + "fileQueueInfo": "{{count}}개 파일을 업로드 중이며, 나머지 {{remaining}}개 파일은 대기 중입니다", "totalCount": "총 {{count}}개 항목", "uploadStatus": { "error": "업로드 오류", diff --git a/locales/ko-KR/models.json b/locales/ko-KR/models.json index c6634cc499c..b3d3a2e06eb 100644 --- a/locales/ko-KR/models.json +++ b/locales/ko-KR/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V는 GLM-4.5-Air 기본 모델을 기반으로 구축되었으며, 검증된 GLM-4.1V-Thinking 기술을 계승하면서 강력한 1060억 매개변수 MoE 아키텍처를 통해 효율적인 확장을 실현했습니다." } -} +} \ No newline at end of file diff --git a/locales/nl-NL/chat.json b/locales/nl-NL/chat.json index 13f12115b88..472008cf817 100644 --- a/locales/nl-NL/chat.json +++ b/locales/nl-NL/chat.json @@ -163,9 +163,9 @@ "addMember": "Lid toevoegen", "allMembers": "Alle leden", "createGroup": "Agent-team aanmaken", - "noAvailableAgents": "Geen assistenten beschikbaar om uit te nodigen", - "noSelectedAgents": "Nog geen assistenten geselecteerd", - "searchAgents": "Assistenten zoeken...", + "noAvailableAgents": "Geen beschikbare Agent om uit te nodigen", + "noSelectedAgents": "Nog geen Agent geselecteerd", + "searchAgents": "Zoek Agent...", "setInitialMembers": "Selecteer teamleden" }, "members": "Leden", @@ -229,7 +229,7 @@ "jumpToMessage": "Ga naar bericht {{index}}", "nextMessage": "Volgend bericht", "previousMessage": "Vorig bericht", - "senderAssistant": "Assistent", + "senderAssistant": "Agent", "senderUser": "Jij" }, "newAgent": "Nieuwe assistent", diff --git a/locales/nl-NL/file.json b/locales/nl-NL/file.json index 389b3622451..095428b2c85 100644 --- a/locales/nl-NL/file.json +++ b/locales/nl-NL/file.json @@ -85,6 +85,7 @@ "restTime": "Overgebleven {{time}}" } }, + "fileQueueInfo": "Bezig met uploaden van de eerste {{count}} bestanden, de resterende {{remaining}} bestanden worden in de wachtrij geplaatst", "totalCount": "Totaal {{count}} items", "uploadStatus": { "error": "Uploadfout", diff --git a/locales/nl-NL/models.json b/locales/nl-NL/models.json index 45ff5f79c6b..45989dce950 100644 --- a/locales/nl-NL/models.json +++ b/locales/nl-NL/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V is gebouwd op het GLM-4.5-Air basismodel, erft de bewezen technologie van GLM-4.1V-Thinking en realiseert efficiënte schaalvergroting via een krachtige MoE-architectuur met 106 miljard parameters." } -} +} \ No newline at end of file diff --git a/locales/pl-PL/chat.json b/locales/pl-PL/chat.json index 2c59027bff7..415086910c2 100644 --- a/locales/pl-PL/chat.json +++ b/locales/pl-PL/chat.json @@ -163,9 +163,9 @@ "addMember": "Dodaj członka", "allMembers": "Wszyscy członkowie", "createGroup": "Utwórz zespół Agentów", - "noAvailableAgents": "Brak dostępnych asystentów do zaproszenia", - "noSelectedAgents": "Nie wybrano jeszcze asystentów", - "searchAgents": "Szukaj asystentów...", + "noAvailableAgents": "Brak dostępnych Agentów do zaproszenia", + "noSelectedAgents": "Nie wybrano jeszcze żadnego Agenta", + "searchAgents": "Szukaj Agenta...", "setInitialMembers": "Wybierz członków zespołu" }, "members": "Członkowie", @@ -229,7 +229,7 @@ "jumpToMessage": "Przejdź do wiadomości nr {{index}}", "nextMessage": "Następna wiadomość", "previousMessage": "Poprzednia wiadomość", - "senderAssistant": "Asystent", + "senderAssistant": "Agent", "senderUser": "Ty" }, "newAgent": "Nowy asystent", diff --git a/locales/pl-PL/file.json b/locales/pl-PL/file.json index 0ef9bb8d6a7..57ca16787a1 100644 --- a/locales/pl-PL/file.json +++ b/locales/pl-PL/file.json @@ -85,6 +85,7 @@ "restTime": "Pozostały czas {{time}}" } }, + "fileQueueInfo": "Trwa przesyłanie {{count}} pierwszych plików, pozostałe {{remaining}} pliki zostaną dodane do kolejki", "totalCount": "Łącznie {{count}} pozycji", "uploadStatus": { "error": "Błąd przesyłania", diff --git a/locales/pl-PL/models.json b/locales/pl-PL/models.json index d75782f4acd..bcb54f38f97 100644 --- a/locales/pl-PL/models.json +++ b/locales/pl-PL/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V zbudowany jest na bazie GLM-4.5-Air, dziedzicząc zweryfikowane technologie GLM-4.1V-Thinking, jednocześnie skutecznie skalując się dzięki potężnej architekturze MoE z 106 miliardami parametrów." } -} +} \ No newline at end of file diff --git a/locales/pt-BR/chat.json b/locales/pt-BR/chat.json index 46fc6ce930e..35726a8dffb 100644 --- a/locales/pt-BR/chat.json +++ b/locales/pt-BR/chat.json @@ -163,9 +163,9 @@ "addMember": "Adicionar membro", "allMembers": "Todos os membros", "createGroup": "Criar time de Agentes", - "noAvailableAgents": "Nenhum assistente disponível para convidar", - "noSelectedAgents": "Nenhum assistente selecionado ainda", - "searchAgents": "Pesquisar assistentes...", + "noAvailableAgents": "Nenhum agente disponível para convite", + "noSelectedAgents": "Nenhum agente selecionado ainda", + "searchAgents": "Buscar agentes...", "setInitialMembers": "Selecionar membros do time" }, "members": "Membros", @@ -229,7 +229,7 @@ "jumpToMessage": "Ir para a mensagem nº {{index}}", "nextMessage": "Próxima mensagem", "previousMessage": "Mensagem anterior", - "senderAssistant": "Assistente", + "senderAssistant": "Agente", "senderUser": "Você" }, "newAgent": "Novo Assistente", diff --git a/locales/pt-BR/file.json b/locales/pt-BR/file.json index 334e43c6e02..a7d07c3e921 100644 --- a/locales/pt-BR/file.json +++ b/locales/pt-BR/file.json @@ -85,6 +85,7 @@ "restTime": "Restante {{time}}" } }, + "fileQueueInfo": "Enviando os primeiros {{count}} arquivos, os {{remaining}} restantes estão na fila para upload", "totalCount": "Total de {{count}} itens", "uploadStatus": { "error": "Erro no envio", diff --git a/locales/ru-RU/chat.json b/locales/ru-RU/chat.json index 55499b8800e..8ec407547d3 100644 --- a/locales/ru-RU/chat.json +++ b/locales/ru-RU/chat.json @@ -163,9 +163,9 @@ "addMember": "Добавить участника", "allMembers": "Все участники", "createGroup": "Создать команду агентов", - "noAvailableAgents": "Нет доступных помощников для приглашения", - "noSelectedAgents": "Помощники не выбраны", - "searchAgents": "Поиск помощников...", + "noAvailableAgents": "Нет доступных агентов для приглашения", + "noSelectedAgents": "Агенты ещё не выбраны", + "searchAgents": "Поиск агентов...", "setInitialMembers": "Выберите участников команды" }, "members": "Участники", @@ -229,7 +229,7 @@ "jumpToMessage": "Перейти к сообщению № {{index}}", "nextMessage": "Следующее сообщение", "previousMessage": "Предыдущее сообщение", - "senderAssistant": "Ассистент", + "senderAssistant": "Агент", "senderUser": "Вы" }, "newAgent": "Создать помощника", diff --git a/locales/ru-RU/file.json b/locales/ru-RU/file.json index 4f62a71dc74..e294cdd535e 100644 --- a/locales/ru-RU/file.json +++ b/locales/ru-RU/file.json @@ -85,6 +85,7 @@ "restTime": "Осталось {{time}}" } }, + "fileQueueInfo": "Загружаются первые {{count}} файлов, оставшиеся {{remaining}} будут поставлены в очередь", "totalCount": "Всего {{count}} элементов", "uploadStatus": { "error": "Ошибка загрузки", diff --git a/locales/ru-RU/models.json b/locales/ru-RU/models.json index fdb8df080eb..44ff32fefac 100644 --- a/locales/ru-RU/models.json +++ b/locales/ru-RU/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V построена на базе GLM-4.5-Air, наследуя проверенные технологии GLM-4.1V-Thinking и обеспечивая эффективное масштабирование благодаря мощной архитектуре MoE с 106 миллиардами параметров." } -} +} \ No newline at end of file diff --git a/locales/tr-TR/chat.json b/locales/tr-TR/chat.json index 2ba96cf428f..1236befa5ba 100644 --- a/locales/tr-TR/chat.json +++ b/locales/tr-TR/chat.json @@ -163,9 +163,9 @@ "addMember": "Üye Ekle", "allMembers": "Tüm üyeler", "createGroup": "Agent Ekibi Oluştur", - "noAvailableAgents": "Davet edilecek asistan yok", - "noSelectedAgents": "Henüz asistan seçilmedi", - "searchAgents": "Asistan ara...", + "noAvailableAgents": "Davet edilebilecek bir Agent yok", + "noSelectedAgents": "Henüz bir Agent seçilmedi", + "searchAgents": "Agent ara...", "setInitialMembers": "Ekip üyelerini seç" }, "members": "Üyeler", @@ -229,7 +229,7 @@ "jumpToMessage": "{{index}} numaralı mesaja atla", "nextMessage": "Sonraki mesaj", "previousMessage": "Önceki mesaj", - "senderAssistant": "Asistan", + "senderAssistant": "Agent", "senderUser": "Sen" }, "newAgent": "Yeni Asistan", diff --git a/locales/tr-TR/file.json b/locales/tr-TR/file.json index 229d84f03cc..f47b45ceabe 100644 --- a/locales/tr-TR/file.json +++ b/locales/tr-TR/file.json @@ -85,6 +85,7 @@ "restTime": "Kalan {{time}}" } }, + "fileQueueInfo": "{{count}} dosya yükleniyor, kalan {{remaining}} dosya sıraya alınacak", "totalCount": "Toplam {{count}} öğe", "uploadStatus": { "error": "Yükleme hatası", diff --git a/locales/tr-TR/models.json b/locales/tr-TR/models.json index 3f054630815..02db330e414 100644 --- a/locales/tr-TR/models.json +++ b/locales/tr-TR/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V, GLM-4.5-Air temel modeli üzerine inşa edilmiştir, GLM-4.1V-Thinking'in doğrulanmış teknolojisini devralır ve güçlü 106 milyar parametreli MoE mimarisi ile etkili ölçeklenebilirlik sağlar." } -} +} \ No newline at end of file diff --git a/locales/vi-VN/chat.json b/locales/vi-VN/chat.json index 6ef469f50fc..de3cb99b20a 100644 --- a/locales/vi-VN/chat.json +++ b/locales/vi-VN/chat.json @@ -163,9 +163,9 @@ "addMember": "Thêm thành viên", "allMembers": "Tất cả thành viên", "createGroup": "Tạo nhóm Agent", - "noAvailableAgents": "Không có trợ lý nào để mời", - "noSelectedAgents": "Chưa chọn trợ lý nào", - "searchAgents": "Tìm trợ lý...", + "noAvailableAgents": "Không có Agent nào để mời", + "noSelectedAgents": "Chưa chọn Agent nào", + "searchAgents": "Tìm kiếm Agent...", "setInitialMembers": "Chọn thành viên nhóm" }, "members": "Thành viên", @@ -229,7 +229,7 @@ "jumpToMessage": "Chuyển đến tin nhắn thứ {{index}}", "nextMessage": "Tin nhắn tiếp theo", "previousMessage": "Tin nhắn trước", - "senderAssistant": "Trợ lý", + "senderAssistant": "Agent", "senderUser": "Bạn" }, "newAgent": "Tạo trợ lý mới", diff --git a/locales/vi-VN/file.json b/locales/vi-VN/file.json index c552bd9560b..e0c53b276f2 100644 --- a/locales/vi-VN/file.json +++ b/locales/vi-VN/file.json @@ -85,6 +85,7 @@ "restTime": "Thời gian còn lại {{time}}" } }, + "fileQueueInfo": "Đang tải lên {{count}} tệp đầu tiên, còn lại {{remaining}} tệp sẽ được xếp hàng để tải lên", "totalCount": "Tổng cộng {{count}} mục", "uploadStatus": { "error": "Lỗi tải lên", diff --git a/locales/vi-VN/models.json b/locales/vi-VN/models.json index 901d9ffd052..10c9463a874 100644 --- a/locales/vi-VN/models.json +++ b/locales/vi-VN/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V được xây dựng trên mô hình nền tảng GLM-4.5-Air, kế thừa công nghệ đã được xác minh của GLM-4.1V-Thinking, đồng thời mở rộng hiệu quả với kiến trúc MoE 106 tỷ tham số mạnh mẽ." } -} +} \ No newline at end of file diff --git a/locales/zh-CN/chat.json b/locales/zh-CN/chat.json index f4dc9974ec9..d05076db531 100644 --- a/locales/zh-CN/chat.json +++ b/locales/zh-CN/chat.json @@ -163,9 +163,9 @@ "addMember": "添加成员", "allMembers": "全体成员", "createGroup": "创建 Agent 团队", - "noAvailableAgents": "没有可邀请的助手", - "noSelectedAgents": "还未选择助手", - "searchAgents": "搜索助手...", + "noAvailableAgents": "没有可邀请的 Agent", + "noSelectedAgents": "还未选择 Agent", + "searchAgents": "搜索 Agent...", "setInitialMembers": "选择团队成员" }, "members": "Members", @@ -229,7 +229,7 @@ "jumpToMessage": "跳转至第 {{index}} 条消息", "nextMessage": "下一条消息", "previousMessage": "上一条消息", - "senderAssistant": "助手", + "senderAssistant": "Agent", "senderUser": "你" }, "newAgent": "新建助手", diff --git a/locales/zh-CN/file.json b/locales/zh-CN/file.json index 20ed5608049..96f5cd7fc4b 100644 --- a/locales/zh-CN/file.json +++ b/locales/zh-CN/file.json @@ -85,6 +85,7 @@ "restTime": "剩余 {{time}}" } }, + "fileQueueInfo": "正在上传前 {{count}} 个文件,剩余 {{remaining}} 个文件将排队上传", "totalCount": "共 {{count}} 项", "uploadStatus": { "error": "上传出错", diff --git a/locales/zh-TW/chat.json b/locales/zh-TW/chat.json index 453f4619cc1..c7436cea09f 100644 --- a/locales/zh-TW/chat.json +++ b/locales/zh-TW/chat.json @@ -163,9 +163,9 @@ "addMember": "添加成員", "allMembers": "所有成員", "createGroup": "建立 Agent 團隊", - "noAvailableAgents": "沒有可邀請的助理", - "noSelectedAgents": "尚未選擇助理", - "searchAgents": "搜尋助理...", + "noAvailableAgents": "沒有可邀請的 Agent", + "noSelectedAgents": "尚未選擇 Agent", + "searchAgents": "搜尋 Agent...", "setInitialMembers": "選擇團隊成員" }, "members": "成員", @@ -229,7 +229,7 @@ "jumpToMessage": "跳轉至第 {{index}} 條訊息", "nextMessage": "下一條訊息", "previousMessage": "上一條訊息", - "senderAssistant": "助理", + "senderAssistant": "Agent", "senderUser": "您" }, "newAgent": "新建助手", diff --git a/locales/zh-TW/file.json b/locales/zh-TW/file.json index 5f02cbfe658..2784c53bec0 100644 --- a/locales/zh-TW/file.json +++ b/locales/zh-TW/file.json @@ -85,6 +85,7 @@ "restTime": "剩餘 {{time}}" } }, + "fileQueueInfo": "正在上傳前 {{count}} 個檔案,剩餘 {{remaining}} 個檔案將排隊上傳", "totalCount": "共 {{count}} 項", "uploadStatus": { "error": "上傳出錯", diff --git a/locales/zh-TW/models.json b/locales/zh-TW/models.json index 791591ae974..53a47acdf8a 100644 --- a/locales/zh-TW/models.json +++ b/locales/zh-TW/models.json @@ -3314,4 +3314,4 @@ "zai/glm-4.5v": { "description": "GLM-4.5V 基於 GLM-4.5-Air 基礎模型構建,繼承了 GLM-4.1V-Thinking 的經過驗證的技術,同時透過強大的 1060 億參數 MoE 架構實現了有效的擴展。" } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 0647f93d559..6c1283084cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lobehub/chat", - "version": "1.142.2", + "version": "1.142.3", "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.", "keywords": [ "framework", @@ -208,6 +208,7 @@ "drizzle-zod": "^0.5.1", "epub2": "^3.0.2", "fast-deep-equal": "^3.1.3", + "fflate": "^0.8.2", "file-type": "^21.0.0", "framer-motion": "^12.23.24", "gpt-tokenizer": "^3.2.0", diff --git a/packages/const/src/file.ts b/packages/const/src/file.ts index babff89944e..f1044aa9e0a 100644 --- a/packages/const/src/file.ts +++ b/packages/const/src/file.ts @@ -6,3 +6,5 @@ export const FILE_UPLOAD_BLACKLIST = [ 'ehthumbs.db', 'ehthumbs_vista.db', ]; + +export const MAX_UPLOAD_FILE_COUNT = 10; diff --git a/src/app/[variants]/(main)/settings/provider/features/ModelList/CreateNewModelModal/index.tsx b/src/app/[variants]/(main)/settings/provider/features/ModelList/CreateNewModelModal/index.tsx index a01a668616b..9f753076fa5 100644 --- a/src/app/[variants]/(main)/settings/provider/features/ModelList/CreateNewModelModal/index.tsx +++ b/src/app/[variants]/(main)/settings/provider/features/ModelList/CreateNewModelModal/index.tsx @@ -64,6 +64,13 @@ const ModelConfigModal = memo(({ open, setOpen }) => { maskClosable onCancel={closeModal} open={open} + styles={{ + content: { + display: 'flex', + flexDirection: 'column', + maxHeight: 'calc(100vh - 150px)', + }, + }} title={t('providerModels.createNew.title')} zIndex={1251} // Select is 1150 > diff --git a/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx b/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx index 6e64fb51eac..6cac5c5c247 100644 --- a/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx +++ b/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx @@ -59,6 +59,13 @@ const ModelConfigModal = memo(({ id, open, setOpen }) => maskClosable onCancel={closeModal} open={open} + styles={{ + content: { + display: 'flex', + flexDirection: 'column', + maxHeight: 'calc(100vh - 150px)', + }, + }} title={t('llm.customModelCards.modelConfig.modalTitle', { ns: 'setting' })} zIndex={1251} // Select is 1150 > diff --git a/src/features/FileManager/FileList/FileListItem/index.tsx b/src/features/FileManager/FileList/FileListItem/index.tsx index f75a925c11f..826d2d08437 100644 --- a/src/features/FileManager/FileList/FileListItem/index.tsx +++ b/src/features/FileManager/FileList/FileListItem/index.tsx @@ -79,7 +79,7 @@ const useStyles = createStyles(({ css, token, cx, isDarkMode }) => { interface FileRenderItemProps extends FileListItem { index: number; knowledgeBaseId?: string; - onSelectedChange: (id: string, selected: boolean) => void; + onSelectedChange: (id: string, selected: boolean, shiftKey: boolean, index: number) => void; selected?: boolean; } @@ -100,6 +100,7 @@ const FileRenderItem = memo( chunkingStatus, onSelectedChange, knowledgeBaseId, + index, }) => { const { t } = useTranslation('components'); const { styles, cx } = useStyles(); @@ -140,7 +141,7 @@ const FileRenderItem = memo( onClick={(e) => { e.stopPropagation(); - onSelectedChange(id, !selected); + onSelectedChange(id, !selected, e.shiftKey, index); }} style={{ paddingInline: 4 }} > diff --git a/src/features/FileManager/FileList/MasonryFileItem/MasonryItemWrapper.tsx b/src/features/FileManager/FileList/MasonryFileItem/MasonryItemWrapper.tsx index b6a1882a7fc..35fe41ae5fb 100644 --- a/src/features/FileManager/FileList/MasonryFileItem/MasonryItemWrapper.tsx +++ b/src/features/FileManager/FileList/MasonryFileItem/MasonryItemWrapper.tsx @@ -21,7 +21,7 @@ const MasonryItemWrapper = memo(({ data: item, context } return ( -
+
{ diff --git a/src/features/FileManager/FileList/MasonryFileItem/index.tsx b/src/features/FileManager/FileList/MasonryFileItem/index.tsx index 33e5a65b0b4..9439790c835 100644 --- a/src/features/FileManager/FileList/MasonryFileItem/index.tsx +++ b/src/features/FileManager/FileList/MasonryFileItem/index.tsx @@ -111,8 +111,6 @@ const useStyles = createStyles(({ css, token }) => ({ inset-block-end: 8px; inset-inline-end: 8px; - padding-block: 4px; - padding-inline: 8px; border-radius: ${token.borderRadius}px; opacity: 0; @@ -320,8 +318,8 @@ const MasonryFileItem = memo( }); }, { - rootMargin: '50px', // Start loading slightly before entering viewport - threshold: 0.1, + rootMargin: '200px', // Increased margin to load content earlier + threshold: 0.01, // Lower threshold for earlier triggering }, ); diff --git a/src/features/FileManager/FileList/MasonrySkeleton.tsx b/src/features/FileManager/FileList/MasonrySkeleton.tsx index 515e24bc123..8bb24256250 100644 --- a/src/features/FileManager/FileList/MasonrySkeleton.tsx +++ b/src/features/FileManager/FileList/MasonrySkeleton.tsx @@ -26,6 +26,9 @@ const MasonrySkeleton = memo(({ columnCount }) => { // Generate varying heights for more natural masonry look const heights = [180, 220, 200, 190, 240, 210, 200, 230, 180, 220, 210, 190]; + // Calculate number of items based on viewport and column count + const itemCount = Math.min(columnCount * 3, 12); + return (
(({ columnCount }) => { gridTemplateColumns: `repeat(${columnCount}, 1fr)`, }} > - {Array.from({ length: 12 }).map((_, index) => ( + {Array.from({ length: itemCount }).map((_, index) => (
))} diff --git a/src/features/FileManager/FileList/ToolBar/MultiSelectActions.tsx b/src/features/FileManager/FileList/ToolBar/MultiSelectActions.tsx index 831e0db6ecb..3343d161f31 100644 --- a/src/features/FileManager/FileList/ToolBar/MultiSelectActions.tsx +++ b/src/features/FileManager/FileList/ToolBar/MultiSelectActions.tsx @@ -148,7 +148,7 @@ const MultiSelectActions = memo( size={'small'} variant={'filled'} > - {t('batchDelete', { ns: 'common' })} + {t('delete', { ns: 'common' })} )} diff --git a/src/features/FileManager/FileList/index.tsx b/src/features/FileManager/FileList/index.tsx index 2763bf46ff2..ee9fa7c1768 100644 --- a/src/features/FileManager/FileList/index.tsx +++ b/src/features/FileManager/FileList/index.tsx @@ -51,10 +51,15 @@ const FileList = memo(({ knowledgeBaseId, category }) => { const [selectFileIds, setSelectedFileIds] = useState([]); const [viewConfig, setViewConfig] = useState({ showFilesInKnowledgeBase: false }); + const [lastSelectedIndex, setLastSelectedIndex] = useState(null); + const [isTransitioning, setIsTransitioning] = useState(false); const viewMode = useGlobalStore((s) => s.status.fileManagerViewMode || 'list') as ViewMode; const updateSystemStatus = useGlobalStore((s) => s.updateSystemStatus); - const setViewMode = (mode: ViewMode) => updateSystemStatus({ fileManagerViewMode: mode }); + const setViewMode = (mode: ViewMode) => { + setIsTransitioning(true); + updateSystemStatus({ fileManagerViewMode: mode }); + }; const [columnCount, setColumnCount] = useState(4); @@ -105,6 +110,19 @@ const FileList = memo(({ knowledgeBaseId, category }) => { ...viewConfig, }); + // Handle view transition with a brief delay to show skeleton + React.useEffect(() => { + if (isTransitioning && data) { + // Use requestAnimationFrame to ensure smooth transition + requestAnimationFrame(() => { + const timer = setTimeout(() => { + setIsTransitioning(false); + }, 100); + return () => clearTimeout(timer); + }); + } + }, [isTransitioning, viewMode, data]); + useCheckTaskStatus(data); // Clean up selected files that no longer exist in the data @@ -118,6 +136,13 @@ const FileList = memo(({ knowledgeBaseId, category }) => { } }, [data]); + // Reset lastSelectedIndex when selection is cleared + React.useEffect(() => { + if (selectFileIds.length === 0) { + setLastSelectedIndex(null); + } + }, [selectFileIds.length]); + // Memoize context object to avoid recreating on every render const masonryContext = useMemo( () => ({ @@ -161,7 +186,7 @@ const FileList = memo(({ knowledgeBaseId, category }) => { )} - {isLoading ? ( + {isLoading || isTransitioning ? ( viewMode === 'masonry' ? ( ) : ( @@ -184,13 +209,30 @@ const FileList = memo(({ knowledgeBaseId, category }) => { index={index} key={item.id} knowledgeBaseId={knowledgeBaseId} - onSelectedChange={(id, checked) => { - setSelectedFileIds((prev) => { - if (checked) { - return [...prev, id]; - } - return prev.filter((item) => item !== id); - }); + onSelectedChange={(id, checked, shiftKey, clickedIndex) => { + if (shiftKey && lastSelectedIndex !== null && selectFileIds.length > 0 && data) { + // Range selection with shift key + const start = Math.min(lastSelectedIndex, clickedIndex); + const end = Math.max(lastSelectedIndex, clickedIndex); + const rangeIds = data.slice(start, end + 1).map((item) => item.id); + + setSelectedFileIds((prev) => { + // Create a Set for efficient lookup + const prevSet = new Set(prev); + // Add all items in range + rangeIds.forEach((rangeId) => prevSet.add(rangeId)); + return Array.from(prevSet); + }); + } else { + // Normal selection + setSelectedFileIds((prev) => { + if (checked) { + return [...prev, id]; + } + return prev.filter((item) => item !== id); + }); + } + setLastSelectedIndex(clickedIndex); }} selected={selectFileIds.includes(item.id)} {...item} diff --git a/src/locales/default/chat.ts b/src/locales/default/chat.ts index c9a2f8c5e6e..543ca14d0e4 100644 --- a/src/locales/default/chat.ts +++ b/src/locales/default/chat.ts @@ -175,9 +175,9 @@ export default { addMember: '添加成员', allMembers: '全体成员', createGroup: '创建 Agent 团队', - noAvailableAgents: '没有可邀请的助手', - noSelectedAgents: '还未选择助手', - searchAgents: '搜索助手...', + noAvailableAgents: '没有可邀请的 Agent', + noSelectedAgents: '还未选择 Agent', + searchAgents: '搜索 Agent...', setInitialMembers: '选择团队成员', }, @@ -247,7 +247,7 @@ export default { jumpToMessage: '跳转至第 {{index}} 条消息', nextMessage: '下一条消息', previousMessage: '上一条消息', - senderAssistant: '助手', + senderAssistant: 'Agent', senderUser: '你', }, diff --git a/src/locales/default/file.ts b/src/locales/default/file.ts index 39fb8b8b3ab..c84d89b9e8c 100644 --- a/src/locales/default/file.ts +++ b/src/locales/default/file.ts @@ -86,6 +86,7 @@ export default { restTime: '剩余 {{time}}', }, }, + fileQueueInfo: '正在上传前 {{count}} 个文件,剩余 {{remaining}} 个文件将排队上传', totalCount: '共 {{count}} 项', uploadStatus: { error: '上传出错', diff --git a/src/store/file/slices/fileManager/action.test.ts b/src/store/file/slices/fileManager/action.test.ts index 55ac7a23246..304ed1d4347 100644 --- a/src/store/file/slices/fileManager/action.test.ts +++ b/src/store/file/slices/fileManager/action.test.ts @@ -2,17 +2,50 @@ import { act, renderHook, waitFor } from '@testing-library/react'; import { mutate } from 'swr'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { FILE_UPLOAD_BLACKLIST } from '@/const/file'; +import { message } from '@/components/AntdStaticMethods'; +import { FILE_UPLOAD_BLACKLIST, MAX_UPLOAD_FILE_COUNT } from '@/const/file'; import { lambdaClient } from '@/libs/trpc/client'; import { fileService } from '@/services/file'; import { ragService } from '@/services/rag'; import { FileListItem } from '@/types/files'; import { UploadFileItem } from '@/types/files/upload'; +import { unzipFile } from '@/utils/unzipFile'; import { useFileStore as useStore } from '../../store'; vi.mock('zustand/traditional'); +// Mock i18next translation function +vi.mock('i18next', () => ({ + t: (key: string, options?: any) => { + // Return a mock translation string that includes the options for verification + if (key === 'uploadDock.fileQueueInfo' && options?.count !== undefined) { + return `Uploading ${options.count} files, ${options.remaining} queued`; + } + return key; + }, +})); + +// Mock message +vi.mock('@/components/AntdStaticMethods', () => ({ + message: { + info: vi.fn(), + warning: vi.fn(), + }, +})); + +// Mock unzipFile +vi.mock('@/utils/unzipFile', () => ({ + unzipFile: vi.fn(), +})); + +// Mock p-map to run sequentially for easier testing +vi.mock('p-map', () => ({ + default: vi.fn(async (items, mapper) => { + return Promise.all(items.map(mapper)); + }), +})); + // Mock SWR vi.mock('swr', async () => { const actual = await vi.importActual('swr'); @@ -398,6 +431,108 @@ describe('FileManagerActions', () => { // Should not auto-parse when upload returns undefined expect(parseSpy).not.toHaveBeenCalled(); }); + + it('should enforce file count limit and queue excess files', async () => { + const { result } = renderHook(() => useStore()); + + // Create more files than the limit + const totalFiles = MAX_UPLOAD_FILE_COUNT + 5; + const files = Array.from( + { length: totalFiles }, + (_, i) => new File(['content'], `file-${i}.txt`, { type: 'text/plain' }), + ); + + vi.spyOn(result.current, 'uploadWithProgress').mockResolvedValue({ + id: 'file-1', + url: 'http://example.com/file-1', + }); + vi.spyOn(result.current, 'refreshFileList').mockResolvedValue(); + vi.spyOn(result.current, 'parseFilesToChunks').mockResolvedValue(); + const dispatchSpy = vi.spyOn(result.current, 'dispatchDockFileList'); + + await act(async () => { + await result.current.pushDockFileList(files); + }); + + // Should add all files to dock (not just first MAX_UPLOAD_FILE_COUNT) + expect(dispatchSpy).toHaveBeenCalledWith({ + atStart: true, + files: expect.arrayContaining([ + expect.objectContaining({ file: expect.any(File), status: 'pending' }), + ]), + type: 'addFiles', + }); + + // Verify all files were dispatched + const dispatchCall = dispatchSpy.mock.calls.find((call) => call[0].type === 'addFiles'); + expect(dispatchCall?.[0]).toHaveProperty('files'); + if (dispatchCall && 'files' in dispatchCall[0]) { + expect(dispatchCall[0].files).toHaveLength(totalFiles); + } + }); + + it('should extract ZIP files and upload contents', async () => { + const { result } = renderHook(() => useStore()); + + const zipFile = new File(['zip content'], 'archive.zip', { type: 'application/zip' }); + const extractedFiles = [ + new File(['file1'], 'file1.txt', { type: 'text/plain' }), + new File(['file2'], 'file2.txt', { type: 'text/plain' }), + ]; + + vi.mocked(unzipFile).mockResolvedValue(extractedFiles); + vi.spyOn(result.current, 'uploadWithProgress').mockResolvedValue({ + id: 'file-1', + url: 'http://example.com/file-1', + }); + vi.spyOn(result.current, 'refreshFileList').mockResolvedValue(); + vi.spyOn(result.current, 'parseFilesToChunks').mockResolvedValue(); + const dispatchSpy = vi.spyOn(result.current, 'dispatchDockFileList'); + + await act(async () => { + await result.current.pushDockFileList([zipFile]); + }); + + // Should extract ZIP file + expect(unzipFile).toHaveBeenCalledWith(zipFile); + + // Should upload extracted files + expect(dispatchSpy).toHaveBeenCalledWith({ + atStart: true, + files: extractedFiles.map((file) => ({ file, id: file.name, status: 'pending' })), + type: 'addFiles', + }); + }); + + it('should handle ZIP extraction errors gracefully', async () => { + const { result } = renderHook(() => useStore()); + + const zipFile = new File(['zip content'], 'archive.zip', { type: 'application/zip' }); + + vi.mocked(unzipFile).mockRejectedValue(new Error('Extraction failed')); + const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); + vi.spyOn(result.current, 'uploadWithProgress').mockResolvedValue({ + id: 'file-1', + url: 'http://example.com/file-1', + }); + vi.spyOn(result.current, 'refreshFileList').mockResolvedValue(); + vi.spyOn(result.current, 'parseFilesToChunks').mockResolvedValue(); + const dispatchSpy = vi.spyOn(result.current, 'dispatchDockFileList'); + + await act(async () => { + await result.current.pushDockFileList([zipFile]); + }); + + // Should log error + expect(consoleErrorSpy).toHaveBeenCalled(); + + // Should fallback to uploading the ZIP file itself + expect(dispatchSpy).toHaveBeenCalledWith({ + atStart: true, + files: [{ file: zipFile, id: zipFile.name, status: 'pending' }], + type: 'addFiles', + }); + }); }); describe('reEmbeddingChunks', () => { diff --git a/src/store/file/slices/fileManager/action.ts b/src/store/file/slices/fileManager/action.ts index f39061e4a9f..690cb1b775d 100644 --- a/src/store/file/slices/fileManager/action.ts +++ b/src/store/file/slices/fileManager/action.ts @@ -1,7 +1,8 @@ +import pMap from 'p-map'; import { SWRResponse, mutate } from 'swr'; import { StateCreator } from 'zustand/vanilla'; -import { FILE_UPLOAD_BLACKLIST } from '@/const/file'; +import { FILE_UPLOAD_BLACKLIST, MAX_UPLOAD_FILE_COUNT } from '@/const/file'; import { useClientDataSWR } from '@/libs/swr'; import { fileService } from '@/services/file'; import { ServerService } from '@/services/file/server'; @@ -12,6 +13,7 @@ import { } from '@/store/file/reducers/uploadFileList'; import { FileListItem, QueryFileListParams } from '@/types/files'; import { isChunkingUnsupported } from '@/utils/isChunkingUnsupported'; +import { unzipFile } from '@/utils/unzipFile'; import { FileStore } from '../../store'; import { fileManagerSelectors } from './selectors'; @@ -89,18 +91,37 @@ export const createFileManageSlice: StateCreator< pushDockFileList: async (rawFiles, knowledgeBaseId) => { const { dispatchDockFileList } = get(); - // 0. skip file in blacklist - const files = rawFiles.filter((file) => !FILE_UPLOAD_BLACKLIST.includes(file.name)); + // 0. Process ZIP files and extract their contents + const filesToUpload: File[] = []; + for (const file of rawFiles) { + if (file.type === 'application/zip' || file.name.endsWith('.zip')) { + try { + const extractedFiles = await unzipFile(file); + filesToUpload.push(...extractedFiles); + } catch (error) { + console.error('Failed to extract ZIP file:', error); + // If extraction fails, treat it as a regular file + filesToUpload.push(file); + } + } else { + filesToUpload.push(file); + } + } - // 1. add files + // 1. skip file in blacklist + const files = filesToUpload.filter((file) => !FILE_UPLOAD_BLACKLIST.includes(file.name)); + + // 2. Add all files to dock dispatchDockFileList({ atStart: true, files: files.map((file) => ({ file, id: file.name, status: 'pending' })), type: 'addFiles', }); - const uploadResults = await Promise.all( - files.map(async (file) => { + // 3. Upload files with concurrency limit using p-map + const uploadResults = await pMap( + files, + async (file) => { const result = await get().uploadWithProgress({ file, knowledgeBaseId, @@ -110,10 +131,11 @@ export const createFileManageSlice: StateCreator< await get().refreshFileList(); return { file, fileId: result?.id, fileType: file.type }; - }), + }, + { concurrency: MAX_UPLOAD_FILE_COUNT }, ); - // 2. auto-embed files that support chunking + // 4. auto-embed files that support chunking const fileIdsToEmbed = uploadResults .filter(({ fileType, fileId }) => fileId && !isChunkingUnsupported(fileType)) .map(({ fileId }) => fileId!); diff --git a/src/utils/unzipFile.test.ts b/src/utils/unzipFile.test.ts new file mode 100644 index 00000000000..0940160f6cf --- /dev/null +++ b/src/utils/unzipFile.test.ts @@ -0,0 +1,128 @@ +import { zip } from 'fflate'; +import { describe, expect, it } from 'vitest'; + +import { unzipFile } from './unzipFile'; + +describe('unzipFile', () => { + it('should extract files from a ZIP archive', async () => { + // Create a mock ZIP file with test data + const testFiles = { + 'test.txt': new TextEncoder().encode('Hello, World!'), + 'folder/nested.txt': new TextEncoder().encode('Nested file content'), + }; + + const zipped = await new Promise((resolve, reject) => { + zip(testFiles, (error, data) => { + if (error) reject(error); + else resolve(data); + }); + }); + + const zipFile = new File([new Uint8Array(zipped)], 'test.zip', { type: 'application/zip' }); + + const extractedFiles = await unzipFile(zipFile); + + expect(extractedFiles).toHaveLength(2); + expect(extractedFiles[0].name).toBe('test.txt'); + expect(extractedFiles[1].name).toBe('nested.txt'); + + // Verify file contents + const content1 = await extractedFiles[0].text(); + expect(content1).toBe('Hello, World!'); + + const content2 = await extractedFiles[1].text(); + expect(content2).toBe('Nested file content'); + }); + + it('should skip directories in ZIP archive', async () => { + const testFiles = { + 'file.txt': new TextEncoder().encode('File content'), + 'folder/': new Uint8Array(0), // Directory entry + }; + + const zipped = await new Promise((resolve, reject) => { + zip(testFiles, (error, data) => { + if (error) reject(error); + else resolve(data); + }); + }); + + const zipFile = new File([new Uint8Array(zipped)], 'test.zip', { type: 'application/zip' }); + + const extractedFiles = await unzipFile(zipFile); + + expect(extractedFiles).toHaveLength(1); + expect(extractedFiles[0].name).toBe('file.txt'); + }); + + it('should skip hidden files and __MACOSX directories', async () => { + const testFiles = { + '.hidden': new TextEncoder().encode('Hidden file'), + '__MACOSX/._file.txt': new TextEncoder().encode('Mac metadata'), + 'visible.txt': new TextEncoder().encode('Visible file'), + }; + + const zipped = await new Promise((resolve, reject) => { + zip(testFiles, (error, data) => { + if (error) reject(error); + else resolve(data); + }); + }); + + const zipFile = new File([new Uint8Array(zipped)], 'test.zip', { type: 'application/zip' }); + + const extractedFiles = await unzipFile(zipFile); + + expect(extractedFiles).toHaveLength(1); + expect(extractedFiles[0].name).toBe('visible.txt'); + }); + + it('should set correct MIME types for extracted files', async () => { + const testFiles = { + 'document.pdf': new TextEncoder().encode('PDF content'), + 'image.png': new TextEncoder().encode('PNG content'), + 'code.ts': new TextEncoder().encode('TypeScript code'), + }; + + const zipped = await new Promise((resolve, reject) => { + zip(testFiles, (error, data) => { + if (error) reject(error); + else resolve(data); + }); + }); + + const zipFile = new File([new Uint8Array(zipped)], 'test.zip', { type: 'application/zip' }); + + const extractedFiles = await unzipFile(zipFile); + + expect(extractedFiles).toHaveLength(3); + expect(extractedFiles.find((f) => f.name === 'document.pdf')?.type).toBe('application/pdf'); + expect(extractedFiles.find((f) => f.name === 'image.png')?.type).toBe('image/png'); + expect(extractedFiles.find((f) => f.name === 'code.ts')?.type).toBe('text/typescript'); + }); + + it('should handle empty ZIP files', async () => { + const testFiles = {}; + + const zipped = await new Promise((resolve, reject) => { + zip(testFiles, (error, data) => { + if (error) reject(error); + else resolve(data); + }); + }); + + const zipFile = new File([new Uint8Array(zipped)], 'empty.zip', { type: 'application/zip' }); + + const extractedFiles = await unzipFile(zipFile); + + expect(extractedFiles).toHaveLength(0); + }); + + it('should reject on invalid ZIP file', async () => { + const invalidFile = new File([new Uint8Array([1, 2, 3, 4])], 'invalid.zip', { + type: 'application/zip', + }); + + await expect(unzipFile(invalidFile)).rejects.toThrow(); + }); +}); diff --git a/src/utils/unzipFile.ts b/src/utils/unzipFile.ts new file mode 100644 index 00000000000..c2b1c0d3a8c --- /dev/null +++ b/src/utils/unzipFile.ts @@ -0,0 +1,122 @@ +import { unzip } from 'fflate'; + +/** + * Determines the MIME type based on file extension + */ +const getFileType = (fileName: string): string => { + const extension = fileName.split('.').pop()?.toLowerCase() || ''; + + const mimeTypes: Record = { + // Images + bmp: 'image/bmp', + + // Code files + c: 'text/x-c', + + cpp: 'text/x-c++', + + cs: 'text/x-csharp', + + css: 'text/css', + + // Documents + csv: 'text/csv', + + doc: 'application/msword', + + docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + + gif: 'image/gif', + + go: 'text/x-go', + + html: 'text/html', + + java: 'text/x-java', + + jpeg: 'image/jpeg', + + jpg: 'image/jpeg', + + js: 'text/javascript', + + json: 'application/json', + + jsx: 'text/javascript', + + md: 'text/markdown', + + pdf: 'application/pdf', + + php: 'application/x-httpd-php', + + png: 'image/png', + + ppt: 'application/vnd.ms-powerpoint', + pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + py: 'text/x-python', + rb: 'text/x-ruby', + rs: 'text/x-rust', + rtf: 'application/rtf', + sh: 'application/x-sh', + svg: 'image/svg+xml', + ts: 'text/typescript', + tsx: 'text/typescript', + txt: 'text/plain', + webp: 'image/webp', + xls: 'application/vnd.ms-excel', + xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + xml: 'application/xml', + }; + + return mimeTypes[extension] || 'application/octet-stream'; +}; + +/** + * Extracts files from a ZIP archive + * @param zipFile - The ZIP file to extract + * @returns Promise that resolves to an array of extracted Files + */ +export const unzipFile = async (zipFile: File): Promise => { + return new Promise((resolve, reject) => { + zipFile + .arrayBuffer() + .then((arrayBuffer) => { + const uint8Array = new Uint8Array(arrayBuffer); + + unzip(uint8Array, (error, unzipped) => { + if (error) { + reject(error); + return; + } + + const extractedFiles: File[] = []; + + for (const [path, data] of Object.entries(unzipped)) { + // Skip directories and hidden files + if (path.endsWith('/') || path.includes('__MACOSX') || path.startsWith('.')) { + continue; + } + + // Get the filename from the path + const fileName = path.split('/').pop() || path; + + // Create a File object from the extracted data + const blob = new Blob([new Uint8Array(data)], { + type: getFileType(fileName), + }); + const file = new File([blob], fileName, { + type: getFileType(fileName), + }); + + extractedFiles.push(file); + } + + resolve(extractedFiles); + }); + }) + .catch(() => { + reject(new Error('Failed to read ZIP file')); + }); + }); +}; diff --git a/vitest.config.mts b/vitest.config.mts index 89f4fa69990..57c3271aa9b 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -15,6 +15,7 @@ export default defineConfig({ '@/const/locale': resolve(__dirname, './src/const/locale'), // TODO: after refactor the errorResponse, we can remove it '@/utils/errorResponse': resolve(__dirname, './src/utils/errorResponse'), + '@/utils/unzipFile': resolve(__dirname, './src/utils/unzipFile'), '@/utils': resolve(__dirname, './packages/utils/src'), '@/types': resolve(__dirname, './packages/types/src'), '@/const': resolve(__dirname, './packages/const/src'),