@lobehub/chat 1.136.8 → 1.136.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/locales/ar/common.json +1 -0
  4. package/locales/ar/hotkey.json +8 -0
  5. package/locales/ar/labs.json +14 -0
  6. package/locales/bg-BG/common.json +1 -0
  7. package/locales/bg-BG/hotkey.json +8 -0
  8. package/locales/bg-BG/labs.json +14 -0
  9. package/locales/de-DE/common.json +1 -0
  10. package/locales/de-DE/hotkey.json +8 -0
  11. package/locales/de-DE/labs.json +14 -0
  12. package/locales/en-US/common.json +1 -0
  13. package/locales/en-US/hotkey.json +8 -0
  14. package/locales/en-US/labs.json +14 -0
  15. package/locales/es-ES/common.json +1 -0
  16. package/locales/es-ES/hotkey.json +8 -0
  17. package/locales/es-ES/labs.json +14 -0
  18. package/locales/fa-IR/common.json +1 -0
  19. package/locales/fa-IR/hotkey.json +8 -0
  20. package/locales/fa-IR/labs.json +14 -0
  21. package/locales/fr-FR/common.json +1 -0
  22. package/locales/fr-FR/hotkey.json +8 -0
  23. package/locales/fr-FR/labs.json +14 -0
  24. package/locales/it-IT/common.json +1 -0
  25. package/locales/it-IT/hotkey.json +8 -0
  26. package/locales/it-IT/labs.json +14 -0
  27. package/locales/ja-JP/common.json +1 -0
  28. package/locales/ja-JP/hotkey.json +8 -0
  29. package/locales/ja-JP/labs.json +14 -0
  30. package/locales/ko-KR/common.json +1 -0
  31. package/locales/ko-KR/hotkey.json +8 -0
  32. package/locales/ko-KR/labs.json +14 -0
  33. package/locales/nl-NL/common.json +1 -0
  34. package/locales/nl-NL/hotkey.json +8 -0
  35. package/locales/nl-NL/labs.json +14 -0
  36. package/locales/pl-PL/common.json +1 -0
  37. package/locales/pl-PL/hotkey.json +8 -0
  38. package/locales/pl-PL/labs.json +14 -0
  39. package/locales/pt-BR/common.json +1 -0
  40. package/locales/pt-BR/hotkey.json +8 -0
  41. package/locales/pt-BR/labs.json +14 -0
  42. package/locales/ru-RU/common.json +1 -0
  43. package/locales/ru-RU/hotkey.json +8 -0
  44. package/locales/ru-RU/labs.json +14 -0
  45. package/locales/tr-TR/common.json +1 -0
  46. package/locales/tr-TR/hotkey.json +8 -0
  47. package/locales/tr-TR/labs.json +14 -0
  48. package/locales/vi-VN/common.json +1 -0
  49. package/locales/vi-VN/hotkey.json +8 -0
  50. package/locales/vi-VN/labs.json +14 -0
  51. package/locales/zh-CN/common.json +1 -0
  52. package/locales/zh-CN/hotkey.json +8 -0
  53. package/locales/zh-CN/labs.json +14 -0
  54. package/locales/zh-TW/common.json +1 -0
  55. package/locales/zh-TW/hotkey.json +8 -0
  56. package/locales/zh-TW/labs.json +14 -0
  57. package/package.json +1 -1
  58. package/packages/prompts/package.json +1 -0
  59. package/packages/prompts/promptfoo/abstract-chunk/eval.yaml +111 -0
  60. package/packages/prompts/promptfoo/abstract-chunk/prompt.ts +16 -0
  61. package/packages/prompts/promptfooconfig.yaml +1 -0
  62. package/packages/prompts/src/chains/__tests__/__snapshots__/abstractChunk.test.ts.snap +38 -0
  63. package/packages/prompts/src/chains/__tests__/abstractChunk.test.ts +2 -21
  64. package/packages/prompts/src/chains/abstractChunk.ts +24 -3
  65. package/packages/prompts/src/prompts/index.ts +1 -0
  66. package/packages/prompts/src/prompts/search/crawlResults.test.ts +172 -0
  67. package/packages/prompts/src/prompts/search/crawlResults.ts +82 -0
  68. package/packages/prompts/src/prompts/search/index.ts +2 -0
  69. package/packages/prompts/src/prompts/search/searchResults.test.ts +138 -0
  70. package/packages/prompts/src/prompts/search/searchResults.ts +58 -0
  71. package/packages/prompts/src/prompts/search/xmlEscape.ts +21 -0
  72. package/packages/types/src/tool/builtin.ts +8 -0
  73. package/packages/types/src/tool/index.ts +2 -0
  74. package/src/app/[variants]/(main)/_layout/Desktop/SideBar/BottomActions.tsx +12 -10
  75. package/src/app/[variants]/(main)/labs/components/LabCard.tsx +15 -4
  76. package/src/app/[variants]/(main)/labs/page.tsx +54 -27
  77. package/src/features/Conversation/Messages/Assistant/Tool/Inspector/BuiltinPluginTitle.tsx +17 -13
  78. package/src/features/Conversation/Messages/Assistant/Tool/Inspector/ToolTitle.tsx +1 -8
  79. package/src/features/Conversation/Messages/Assistant/Tool/Render/Arguments/index.tsx +12 -16
  80. package/src/features/Conversation/Messages/Assistant/Tool/Render/LoadingPlaceholder/index.tsx +29 -0
  81. package/src/features/Conversation/Messages/Assistant/Tool/Render/index.tsx +26 -7
  82. package/src/features/Conversation/Messages/Assistant/Tool/index.tsx +2 -0
  83. package/src/features/PluginsUI/Render/BuiltinType/index.test.tsx +5 -5
  84. package/src/features/PluginsUI/Render/BuiltinType/index.tsx +1 -7
  85. package/src/store/chat/slices/builtinTool/actions/search.test.ts +4 -3
  86. package/src/store/chat/slices/builtinTool/actions/search.ts +23 -15
  87. package/src/store/chat/slices/message/selectors.ts +10 -0
  88. package/src/store/user/slices/preference/selectors.ts +1 -2
  89. package/src/styles/text.ts +10 -7
  90. package/src/tools/placeholders.ts +8 -0
  91. package/src/tools/web-browsing/Placeholder/PageContent.tsx +27 -0
  92. package/src/tools/web-browsing/Placeholder/Search.tsx +65 -0
  93. package/src/tools/web-browsing/Placeholder/index.tsx +40 -0
  94. package/src/tools/web-browsing/Render/PageContent/Loading.tsx +14 -5
  95. package/src/tools/web-browsing/Render/PageContent/Result.tsx +14 -13
  96. package/src/tools/web-browsing/Render/PageContent/index.tsx +15 -6
  97. package/src/tools/web-browsing/Render/Search/SearchQuery/SearchView.tsx +13 -19
  98. package/src/tools/web-browsing/Render/Search/SearchResult/index.tsx +21 -26
  99. package/src/tools/web-browsing/components/EngineAvatar.tsx +8 -2
  100. package/src/tools/web-browsing/const.ts +8 -1
@@ -0,0 +1,14 @@
1
+ {
2
+ "desc": "Здесь мы будем периодически обновлять информацию о новых функциях, которые мы исследуем. Добро пожаловать на пробное использование!",
3
+ "features": {
4
+ "groupChat": {
5
+ "desc": "Включить возможность организации группового чата с несколькими интеллектуальными агентами.",
6
+ "title": "Групповой чат (мультиагенты)"
7
+ },
8
+ "inputMarkdown": {
9
+ "desc": "Мгновенная визуализация Markdown (жирный шрифт, блоки кода, таблицы и т.д.) в поле ввода.",
10
+ "title": "Рендеринг Markdown в поле ввода"
11
+ }
12
+ },
13
+ "title": "Лаборатория"
14
+ }
@@ -236,6 +236,7 @@
236
236
  },
237
237
  "information": "Topluluk ve Bilgi",
238
238
  "installPWA": "Tarayıcı Uygulamasını Yükle",
239
+ "labs": "Laboratuvarlar",
239
240
  "lang": {
240
241
  "ar": "Arapça",
241
242
  "bg-BG": "Bulgarca",
@@ -7,6 +7,14 @@
7
7
  "desc": "Geçerli oturumun mesajlarını ve yüklenen dosyaları temizle",
8
8
  "title": "Oturum mesajlarını temizle"
9
9
  },
10
+ "deleteAndRegenerateMessage": {
11
+ "desc": "Son mesajı sil ve yeniden oluştur",
12
+ "title": "Sil ve Yeniden Oluştur"
13
+ },
14
+ "deleteLastMessage": {
15
+ "desc": "Son mesajı sil",
16
+ "title": "Son Mesajı Sil"
17
+ },
10
18
  "desktop": {
11
19
  "openSettings": {
12
20
  "desc": "Uygulama ayarları sayfasını aç",
@@ -0,0 +1,14 @@
1
+ {
2
+ "desc": "Burada keşfetmekte olduğumuz yeni özellikleri düzenli olarak güncelliyoruz, denemekten çekinmeyin!",
3
+ "features": {
4
+ "groupChat": {
5
+ "desc": "Çoklu yapay zeka ajanlarıyla grup sohbeti düzenleme yeteneğini etkinleştirir.",
6
+ "title": "Grup Sohbeti (Çoklu Ajan)"
7
+ },
8
+ "inputMarkdown": {
9
+ "desc": "Giriş alanında Markdown biçimlendirmesini (kalın yazı, kod blokları, tablolar vb.) anında görüntüleyin.",
10
+ "title": "Giriş Kutusu Markdown Görüntüleme"
11
+ }
12
+ },
13
+ "title": "Deneysel Özellikler"
14
+ }
@@ -236,6 +236,7 @@
236
236
  },
237
237
  "information": "Cộng đồng và Thông tin",
238
238
  "installPWA": "Cài đặt ứng dụng trình duyệt",
239
+ "labs": "Phòng thí nghiệm",
239
240
  "lang": {
240
241
  "ar": "Tiếng Ả Rập",
241
242
  "bg-BG": "Tiếng Bun-ga-ri",
@@ -7,6 +7,14 @@
7
7
  "desc": "Xóa tất cả tin nhắn và tệp đã tải lên trong cuộc trò chuyện hiện tại",
8
8
  "title": "Xóa tin nhắn cuộc trò chuyện"
9
9
  },
10
+ "deleteAndRegenerateMessage": {
11
+ "desc": "Xoá tin nhắn cuối cùng và tạo lại",
12
+ "title": "Xoá và tạo lại"
13
+ },
14
+ "deleteLastMessage": {
15
+ "desc": "Xoá tin nhắn cuối cùng",
16
+ "title": "Xoá tin nhắn cuối cùng"
17
+ },
10
18
  "desktop": {
11
19
  "openSettings": {
12
20
  "desc": "Mở trang cài đặt ứng dụng",
@@ -0,0 +1,14 @@
1
+ {
2
+ "desc": "Tại đây, chúng tôi sẽ cập nhật định kỳ các tính năng mới đang được khám phá. Rất hoan nghênh bạn dùng thử!",
3
+ "features": {
4
+ "groupChat": {
5
+ "desc": "Kích hoạt khả năng điều phối trò chuyện nhóm với nhiều tác nhân thông minh.",
6
+ "title": "Trò chuyện nhóm (đa tác nhân)"
7
+ },
8
+ "inputMarkdown": {
9
+ "desc": "Hiển thị trực tiếp Markdown trong vùng nhập (in đậm, khối mã, bảng, v.v.).",
10
+ "title": "Hiển thị Markdown trong ô nhập"
11
+ }
12
+ },
13
+ "title": "Phòng thí nghiệm"
14
+ }
@@ -236,6 +236,7 @@
236
236
  },
237
237
  "information": "社区与资讯",
238
238
  "installPWA": "安装浏览器应用 (PWA)",
239
+ "labs": "实验室",
239
240
  "lang": {
240
241
  "ar": "阿拉伯语",
241
242
  "bg-BG": "保加利亚语",
@@ -7,6 +7,14 @@
7
7
  "desc": "清空当前会话的消息和上传的文件",
8
8
  "title": "清空会话消息"
9
9
  },
10
+ "deleteAndRegenerateMessage": {
11
+ "desc": "删除最后一条消息并重新生成",
12
+ "title": "删除并重新生成"
13
+ },
14
+ "deleteLastMessage": {
15
+ "desc": "删除最后一条消息",
16
+ "title": "删除最后一条消息"
17
+ },
10
18
  "desktop": {
11
19
  "openSettings": {
12
20
  "desc": "打开应用设置页面",
@@ -0,0 +1,14 @@
1
+ {
2
+ "desc": "这里会不定期更新我们正在探索的新功能,欢迎试用!",
3
+ "features": {
4
+ "groupChat": {
5
+ "desc": "启用多智能体群聊编排能力。",
6
+ "title": "群聊(多智能体)"
7
+ },
8
+ "inputMarkdown": {
9
+ "desc": "在输入区域实时渲染 Markdown(粗体、代码块、表格等)。",
10
+ "title": "输入框 Markdown 渲染"
11
+ }
12
+ },
13
+ "title": "实验室"
14
+ }
@@ -236,6 +236,7 @@
236
236
  },
237
237
  "information": "社群與資訊",
238
238
  "installPWA": "安裝瀏覽器應用 (PWA)",
239
+ "labs": "實驗室",
239
240
  "lang": {
240
241
  "ar": "阿拉伯語",
241
242
  "bg-BG": "保加利亞語",
@@ -7,6 +7,14 @@
7
7
  "desc": "清空當前會話的消息和上傳的檔案",
8
8
  "title": "清空會話消息"
9
9
  },
10
+ "deleteAndRegenerateMessage": {
11
+ "desc": "刪除最後一則訊息並重新產生",
12
+ "title": "刪除並重新產生"
13
+ },
14
+ "deleteLastMessage": {
15
+ "desc": "刪除最後一則訊息",
16
+ "title": "刪除最後一則訊息"
17
+ },
10
18
  "desktop": {
11
19
  "openSettings": {
12
20
  "desc": "打開應用設定頁面",
@@ -0,0 +1,14 @@
1
+ {
2
+ "desc": "這裡會不定期更新我們正在探索的新功能,歡迎試用!",
3
+ "features": {
4
+ "groupChat": {
5
+ "desc": "啟用多智能體群組聊天編排功能。",
6
+ "title": "群組聊天(多智能體)"
7
+ },
8
+ "inputMarkdown": {
9
+ "desc": "在輸入區即時渲染 Markdown(粗體、程式碼區塊、表格等)。",
10
+ "title": "輸入框 Markdown 渲染"
11
+ }
12
+ },
13
+ "title": "實驗室"
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.136.8",
3
+ "version": "1.136.10",
4
4
  "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.",
5
5
  "keywords": [
6
6
  "framework",
@@ -9,6 +9,7 @@
9
9
  "test": "vitest",
10
10
  "test:coverage": "vitest --coverage --silent='passed-only'",
11
11
  "test:prompts": "pnpm test:prompts:translate && pnpm test:prompts:summary && pnpm test:prompts:lang && pnpm test:prompts:emoji && pnpm test:prompts:qa",
12
+ "test:prompts:abstract-chunk": "promptfoo eval -c promptfoo/abstract-chunk/eval.yaml",
12
13
  "test:prompts:emoji": "promptfoo eval -c promptfoo/emoji-picker/eval.yaml",
13
14
  "test:prompts:lang": "promptfoo eval -c promptfoo/language-detection/eval.yaml",
14
15
  "test:prompts:qa": "promptfoo eval -c promptfoo/knowledge-qa/eval.yaml",
@@ -0,0 +1,111 @@
1
+ description: Test chunk text summarization in different languages
2
+
3
+ providers:
4
+ - openai:chat:gpt-5-mini
5
+ - openai:chat:claude-3-5-haiku-latest
6
+ - openai:chat:gemini-flash-latest
7
+ - openai:chat:deepseek-chat
8
+
9
+ prompts:
10
+ - file://promptfoo/abstract-chunk/prompt.ts
11
+
12
+ tests:
13
+ # English technical content
14
+ - vars:
15
+ text: "React is a JavaScript library for building user interfaces. It was developed by Facebook and is now maintained by Facebook and the community. React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Declarative views make your code more predictable and easier to debug."
16
+ assert:
17
+ - type: llm-rubric
18
+ provider: openai:gpt-5-mini
19
+ value: "The summary should be 1-2 sentences in English, capturing the main topic about React being a JavaScript library for UIs"
20
+ - type: contains-any
21
+ value: ["React", "JavaScript", "library", "UI", "user interface"]
22
+ - type: javascript
23
+ value: "output.split(/[.!?]/).filter(s => s.trim()).length <= 2" # At most 2 sentences
24
+
25
+ # Chinese content
26
+ - vars:
27
+ text: "深度学习是机器学习的一个分支,它使用多层神经网络来学习数据的表示。近年来,深度学习在图像识别、自然语言处理、语音识别等领域取得了突破性进展。卷积神经网络(CNN)在计算机视觉任务中表现优异,而循环神经网络(RNN)和Transformer架构在序列建模任务中非常有效。"
28
+ assert:
29
+ - type: llm-rubric
30
+ provider: openai:gpt-5-mini
31
+ value: "The summary should be 1-2 sentences in Chinese, summarizing deep learning and its applications"
32
+ - type: contains-any
33
+ value: ["深度学习", "神经网络", "机器学习"]
34
+ - type: not-contains
35
+ value: "摘要" # Should not contain meta labels
36
+ - type: javascript
37
+ value: "output.split(/[。!?]/).filter(s => s.trim()).length <= 2" # At most 2 sentences
38
+
39
+ # Japanese content
40
+ - vars:
41
+ text: "人工知能(AI)は、コンピュータシステムが人間の知能を模倣する技術です。AIは、学習、推論、問題解決などの認知機能を実行できます。現代のAIシステムは、大量のデータから学習し、パターンを認識して予測を行います。"
42
+ assert:
43
+ - type: llm-rubric
44
+ provider: openai:gpt-5-mini
45
+ value: "The summary should be 1-2 sentences in Japanese about artificial intelligence"
46
+ - type: contains-any
47
+ value: ["人工知能", "AI", "コンピュータ"]
48
+ - type: javascript
49
+ value: "output.split(/[。!?]/).filter(s => s.trim()).length <= 2"
50
+
51
+ # Spanish content
52
+ - vars:
53
+ text: "El cambio climático es uno de los mayores desafíos que enfrenta la humanidad en el siglo XXI. Las temperaturas globales están aumentando debido a las emisiones de gases de efecto invernadero producidas por actividades humanas como la quema de combustibles fósiles, la deforestación y la agricultura industrial. Los efectos incluyen el derretimiento de los glaciares, el aumento del nivel del mar y eventos climáticos extremos más frecuentes."
54
+ assert:
55
+ - type: llm-rubric
56
+ provider: openai:gpt-5-mini
57
+ value: "The summary should be 1-2 sentences in Spanish about climate change"
58
+ - type: contains-any
59
+ value: ["cambio climático", "temperatura", "clima"]
60
+ - type: javascript
61
+ value: "output.split(/[.!?]/).filter(s => s.trim()).length <= 2"
62
+
63
+ # Short technical content (English)
64
+ - vars:
65
+ text: "TypeScript is a strongly typed programming language that builds on JavaScript. It adds static type definitions to JavaScript, making code more robust and maintainable."
66
+ assert:
67
+ - type: llm-rubric
68
+ provider: openai:gpt-5-mini
69
+ value: "The summary should be 1-2 sentences in English about TypeScript"
70
+ - type: contains-any
71
+ value: ["TypeScript", "JavaScript", "type"]
72
+ - type: javascript
73
+ value: "output.split(/[.!?]/).filter(s => s.trim()).length <= 2"
74
+
75
+ # Mixed technical terms in Chinese
76
+ - vars:
77
+ text: "Docker 是一个开源的容器化平台,它允许开发者将应用程序及其依赖项打包到一个可移植的容器中。通过使用 Docker,可以确保应用在任何环境中都能一致地运行。Docker 容器比传统虚拟机更轻量级,启动速度更快,资源占用更少。"
78
+ assert:
79
+ - type: llm-rubric
80
+ provider: openai:gpt-5-mini
81
+ value: "The summary should be 1-2 sentences in Chinese, keeping 'Docker' in English"
82
+ - type: contains
83
+ value: "Docker" # Technical term should be preserved
84
+ - type: contains-any
85
+ value: ["容器", "平台", "应用"]
86
+ - type: javascript
87
+ value: "output.split(/[。!?]/).filter(s => s.trim()).length <= 2"
88
+
89
+ # German content
90
+ - vars:
91
+ text: "Die Quantenphysik ist ein fundamentaler Zweig der Physik, der sich mit dem Verhalten von Materie und Energie auf atomarer und subatomarer Ebene befasst. Im Gegensatz zur klassischen Physik beschreibt die Quantenphysik Phänomene, bei denen Teilchen sowohl Wellen- als auch Teilcheneigenschaften aufweisen können."
92
+ assert:
93
+ - type: llm-rubric
94
+ provider: openai:gpt-5-mini
95
+ value: "The summary should be 1-2 sentences in German about quantum physics"
96
+ - type: contains-any
97
+ value: ["Quantenphysik", "Physik", "Materie"]
98
+ - type: javascript
99
+ value: "output.split(/[.!?]/).filter(s => s.trim()).length <= 2"
100
+
101
+ # Code snippet in content (English)
102
+ - vars:
103
+ text: "The useState hook in React allows you to add state to functional components. For example: const [count, setCount] = useState(0). This creates a state variable 'count' with initial value 0 and a setter function 'setCount' to update it."
104
+ assert:
105
+ - type: llm-rubric
106
+ provider: openai:gpt-5-mini
107
+ value: "The summary should be 1-2 sentences in English about useState hook, may preserve code syntax"
108
+ - type: contains-any
109
+ value: ["useState", "React", "state", "hook"]
110
+ - type: javascript
111
+ value: "output.split(/[.!?]/).filter(s => s.trim()).length <= 2"
@@ -0,0 +1,16 @@
1
+ // TypeScript prompt wrapper that uses actual chain implementation
2
+ import { chainAbstractChunkText } from '@lobechat/prompts';
3
+
4
+ interface PromptVars {
5
+ text: string;
6
+ }
7
+
8
+ export default function generatePrompt({ vars }: { vars: PromptVars }) {
9
+ const { text } = vars;
10
+
11
+ // Use the actual chain function from src
12
+ const result = chainAbstractChunkText(text);
13
+
14
+ // Return messages array as expected by promptfoo
15
+ return result.messages || [];
16
+ }
@@ -7,6 +7,7 @@ testPaths:
7
7
  - promptfoo/language-detection/eval.yaml
8
8
  - promptfoo/emoji-picker/eval.yaml
9
9
  - promptfoo/knowledge-qa/eval.yaml
10
+ - promptfoo/abstract-chunk/eval.yaml
10
11
 
11
12
  # Output configuration
12
13
  outputPath: promptfoo-results.json
@@ -0,0 +1,38 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`chainAbstractChunkText > should generate correct chat payload for chunk text 1`] = `
4
+ {
5
+ "messages": [
6
+ {
7
+ "content": "You are a summarization expert. Generate a concise summary from the provided text chunk.
8
+
9
+ Rules:
10
+ - Output ONLY the summary text itself, nothing else
11
+ - NO labels, prefixes, or meta-text (like "Summary:", "摘要:", etc.)
12
+ - NO explanations, commentary, or additional context
13
+ - MUST be 1-2 complete sentences maximum (count carefully!)
14
+ - MUST use the SAME language as the input text
15
+ - Preserve technical terms, proper nouns, and code identifiers exactly as they appear
16
+ - Focus on capturing the main topic or key information
17
+ - Keep it concise and direct
18
+
19
+ <examples>
20
+ <input>React is a JavaScript library for building user interfaces...</input>
21
+ <output>React is a JavaScript library developed by Facebook for building interactive user interfaces with declarative views.</output>
22
+
23
+ <input>The useState hook in React allows you to add state...</input>
24
+ <output>The useState hook in React enables functional components to manage state using a state variable and setter function.</output>
25
+
26
+ <input>深度学习是机器学习的一个分支...</input>
27
+ <output>深度学习是机器学习的一个分支,使用多层神经网络学习数据表示,在图像识别、自然语言处理等领域取得突破。</output>
28
+ </examples>
29
+ ",
30
+ "role": "system",
31
+ },
32
+ {
33
+ "content": "This is a sample chunk of text that needs to be summarized.",
34
+ "role": "user",
35
+ },
36
+ ],
37
+ }
38
+ `;
@@ -8,26 +8,7 @@ describe('chainAbstractChunkText', () => {
8
8
 
9
9
  const result = chainAbstractChunkText(testText);
10
10
 
11
- expect(result).toEqual({
12
- messages: [
13
- {
14
- content:
15
- '你是一名擅长从 chunk 中提取摘要的助理,你需要将用户的会话总结为 1~2 句话的摘要,输出成 chunk 所使用的语种',
16
- role: 'system',
17
- },
18
- {
19
- content: `chunk: ${testText}`,
20
- role: 'user',
21
- },
22
- ],
23
- });
24
- });
25
-
26
- it('should handle empty text', () => {
27
- const result = chainAbstractChunkText('');
28
-
29
- expect(result.messages).toHaveLength(2);
30
- expect(result.messages![1].content).toBe('chunk: ');
11
+ expect(result).toMatchSnapshot();
31
12
  });
32
13
 
33
14
  it('should handle text with special characters', () => {
@@ -35,7 +16,7 @@ describe('chainAbstractChunkText', () => {
35
16
 
36
17
  const result = chainAbstractChunkText(testText);
37
18
 
38
- expect(result.messages![1].content).toBe(`chunk: ${testText}`);
19
+ expect(result.messages![1].content).toBe(testText);
39
20
  });
40
21
 
41
22
  it('should always use system role for first message', () => {
@@ -4,12 +4,33 @@ export const chainAbstractChunkText = (text: string): Partial<ChatStreamPayload>
4
4
  return {
5
5
  messages: [
6
6
  {
7
- content:
8
- '你是一名擅长从 chunk 中提取摘要的助理,你需要将用户的会话总结为 1~2 句话的摘要,输出成 chunk 所使用的语种',
7
+ content: `You are a summarization expert. Generate a concise summary from the provided text chunk.
8
+
9
+ Rules:
10
+ - Output ONLY the summary text itself, nothing else
11
+ - NO labels, prefixes, or meta-text (like "Summary:", "摘要:", etc.)
12
+ - NO explanations, commentary, or additional context
13
+ - MUST be 1-2 complete sentences maximum (count carefully!)
14
+ - MUST use the SAME language as the input text
15
+ - Preserve technical terms, proper nouns, and code identifiers exactly as they appear
16
+ - Focus on capturing the main topic or key information
17
+ - Keep it concise and direct
18
+
19
+ <examples>
20
+ <input>React is a JavaScript library for building user interfaces...</input>
21
+ <output>React is a JavaScript library developed by Facebook for building interactive user interfaces with declarative views.</output>
22
+
23
+ <input>The useState hook in React allows you to add state...</input>
24
+ <output>The useState hook in React enables functional components to manage state using a state variable and setter function.</output>
25
+
26
+ <input>深度学习是机器学习的一个分支...</input>
27
+ <output>深度学习是机器学习的一个分支,使用多层神经网络学习数据表示,在图像识别、自然语言处理等领域取得突破。</output>
28
+ </examples>
29
+ `,
9
30
  role: 'system',
10
31
  },
11
32
  {
12
- content: `chunk: ${text}`,
33
+ content: text,
13
34
  role: 'user',
14
35
  },
15
36
  ],
@@ -2,4 +2,5 @@ export * from './chatMessages';
2
2
  export * from './files';
3
3
  export * from './knowledgeBaseQA';
4
4
  export * from './plugin';
5
+ export * from './search';
5
6
  export * from './systemRole';
@@ -0,0 +1,172 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { crawlResultsPrompt } from './crawlResults';
4
+
5
+ describe('crawlResultsPrompt', () => {
6
+ it('should return empty XML for empty results', () => {
7
+ const result = crawlResultsPrompt([]);
8
+ expect(result).toBe('<no_crawl_results />');
9
+ });
10
+
11
+ it('should convert basic crawl result to compact XML format', () => {
12
+ const results = [
13
+ {
14
+ url: 'https://example.com',
15
+ title: 'Example Page',
16
+ content: 'Page content here',
17
+ },
18
+ ];
19
+
20
+ const xml = crawlResultsPrompt(results);
21
+
22
+ expect(xml).toEqual(`<crawlResults>
23
+ <page url="https://example.com" title="Example Page">Page content here</page>
24
+ </crawlResults>`);
25
+ });
26
+
27
+ it('should include all optional metadata fields', () => {
28
+ const results = [
29
+ {
30
+ url: 'http://arxiv.org/abs/2509.09734v1',
31
+ title: 'MCP-AgentBench: Evaluating Real-World Language Agent Performance',
32
+ contentType: 'text' as const,
33
+ description: 'Abstract page for arXiv paper 2509.09734v1',
34
+ length: 10187,
35
+ content: 'Full paper content...',
36
+ },
37
+ ];
38
+
39
+ const xml = crawlResultsPrompt(results);
40
+
41
+ expect(xml).toEqual(`<crawlResults>
42
+ <page url="http://arxiv.org/abs/2509.09734v1" title="MCP-AgentBench: Evaluating Real-World Language Agent Performance" contentType="text" description="Abstract page for arXiv paper 2509.09734v1" length="10187">Full paper content...</page>
43
+ </crawlResults>`);
44
+ });
45
+
46
+ it('should handle page without content', () => {
47
+ const results = [
48
+ {
49
+ url: 'https://example.com',
50
+ title: 'Empty Page',
51
+ contentType: 'text' as const,
52
+ },
53
+ ];
54
+
55
+ const xml = crawlResultsPrompt(results);
56
+
57
+ expect(xml).toEqual(`<crawlResults>
58
+ <page url="https://example.com" title="Empty Page" contentType="text" />
59
+ </crawlResults>`);
60
+ });
61
+
62
+ it('should handle error items', () => {
63
+ const results = [
64
+ {
65
+ errorType: 'NetworkError',
66
+ errorMessage: 'Failed to fetch the page',
67
+ url: 'https://failed.com',
68
+ },
69
+ ];
70
+
71
+ const xml = crawlResultsPrompt(results);
72
+
73
+ expect(xml).toEqual(`<crawlResults>
74
+ <error errorType="NetworkError" errorMessage="Failed to fetch the page" url="https://failed.com" />
75
+ </crawlResults>`);
76
+ });
77
+
78
+ it('should escape XML special characters in attributes', () => {
79
+ const results = [
80
+ {
81
+ url: 'https://example.com?foo=bar&baz=qux',
82
+ title: 'Title with <tags> & "quotes"',
83
+ description: 'Description with special chars & <html>',
84
+ },
85
+ ];
86
+
87
+ const xml = crawlResultsPrompt(results);
88
+
89
+ expect(xml).toEqual(`<crawlResults>
90
+ <page url="https://example.com?foo=bar&amp;baz=qux" title="Title with &lt;tags&gt; &amp; &quot;quotes&quot;" description="Description with special chars &amp; &lt;html&gt;" />
91
+ </crawlResults>`);
92
+ });
93
+
94
+ it('should escape XML special characters in content', () => {
95
+ const results = [
96
+ {
97
+ url: 'https://example.com',
98
+ title: 'Test',
99
+ content: 'Content with <html> tags & special chars',
100
+ },
101
+ ];
102
+
103
+ const xml = crawlResultsPrompt(results);
104
+
105
+ expect(xml).toEqual(`<crawlResults>
106
+ <page url="https://example.com" title="Test">Content with &lt;html&gt; tags &amp; special chars</page>
107
+ </crawlResults>`);
108
+ });
109
+
110
+ it('should handle multiple pages with mixed success and errors', () => {
111
+ const results = [
112
+ {
113
+ url: 'https://success1.com',
114
+ title: 'First Page',
115
+ content: 'First content',
116
+ },
117
+ {
118
+ errorType: 'TimeoutError',
119
+ errorMessage: 'Request timeout',
120
+ url: 'https://failed.com',
121
+ },
122
+ {
123
+ url: 'https://success2.com',
124
+ title: 'Second Page',
125
+ content: 'Second content',
126
+ },
127
+ ];
128
+
129
+ const xml = crawlResultsPrompt(results);
130
+
131
+ expect(xml).toEqual(`<crawlResults>
132
+ <page url="https://success1.com" title="First Page">First content</page>
133
+ <error errorType="TimeoutError" errorMessage="Request timeout" url="https://failed.com" />
134
+ <page url="https://success2.com" title="Second Page">Second content</page>
135
+ </crawlResults>`);
136
+ });
137
+
138
+ it('should handle error without url', () => {
139
+ const results = [
140
+ {
141
+ errorType: 'UnknownError',
142
+ errorMessage: 'Unknown error occurred',
143
+ },
144
+ ];
145
+
146
+ const xml = crawlResultsPrompt(results);
147
+
148
+ expect(xml).toEqual(`<crawlResults>
149
+ <error errorType="UnknownError" errorMessage="Unknown error occurred" />
150
+ </crawlResults>`);
151
+ });
152
+
153
+ it('should handle real arXiv example', () => {
154
+ const results = [
155
+ {
156
+ url: 'http://arxiv.org/abs/2508.01780v1',
157
+ title: 'LiveMCPBench: Can Agents Navigate an Ocean of MCP Tools?',
158
+ contentType: 'text' as const,
159
+ description: 'Abstract page for arXiv paper 2508.01780v1',
160
+ length: 10512,
161
+ content:
162
+ 'With the rapid development of Model Context Protocol (MCP), the number of MCP servers has surpassed 10,000...',
163
+ },
164
+ ];
165
+
166
+ const xml = crawlResultsPrompt(results);
167
+
168
+ expect(xml).toEqual(`<crawlResults>
169
+ <page url="http://arxiv.org/abs/2508.01780v1" title="LiveMCPBench: Can Agents Navigate an Ocean of MCP Tools?" contentType="text" description="Abstract page for arXiv paper 2508.01780v1" length="10512">With the rapid development of Model Context Protocol (MCP), the number of MCP servers has surpassed 10,000...</page>
170
+ </crawlResults>`);
171
+ });
172
+ });