@lobehub/lobehub 2.1.19 → 2.1.21

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 (212) hide show
  1. package/.eslintrc.js +1 -0
  2. package/.github/workflows/release.yml +1 -0
  3. package/.github/workflows/sync-main-to-dev.yaml +42 -0
  4. package/.vscode/settings.json +2 -0
  5. package/CHANGELOG.md +162 -0
  6. package/apps/desktop/src/main/controllers/ShellCommandCtr.ts +14 -3
  7. package/apps/desktop/src/main/controllers/__tests__/ShellCommandCtr.test.ts +60 -4
  8. package/changelog/v2.json +18 -0
  9. package/docs/development/basic/add-new-image-model.mdx +7 -7
  10. package/docs/development/basic/add-new-image-model.zh-CN.mdx +7 -7
  11. package/docs/development/basic/architecture.mdx +85 -21
  12. package/docs/development/basic/architecture.zh-CN.mdx +81 -19
  13. package/docs/development/basic/chat-api.mdx +385 -322
  14. package/docs/development/basic/chat-api.zh-CN.mdx +347 -320
  15. package/docs/development/basic/contributing-guidelines.mdx +20 -3
  16. package/docs/development/basic/contributing-guidelines.zh-CN.mdx +20 -3
  17. package/docs/development/basic/feature-development.mdx +102 -214
  18. package/docs/development/basic/feature-development.zh-CN.mdx +102 -214
  19. package/docs/development/basic/folder-structure.mdx +189 -80
  20. package/docs/development/basic/folder-structure.zh-CN.mdx +187 -80
  21. package/docs/development/basic/resources.mdx +19 -0
  22. package/docs/development/basic/resources.zh-CN.mdx +19 -0
  23. package/docs/development/start.mdx +53 -63
  24. package/docs/development/start.zh-CN.mdx +48 -63
  25. package/locales/ar/auth.json +1 -0
  26. package/locales/ar/chat.json +6 -0
  27. package/locales/ar/discover.json +9 -0
  28. package/locales/ar/error.json +1 -0
  29. package/locales/ar/modelProvider.json +2 -0
  30. package/locales/ar/models.json +99 -26
  31. package/locales/ar/plugin.json +1 -0
  32. package/locales/ar/providers.json +1 -0
  33. package/locales/bg-BG/auth.json +1 -0
  34. package/locales/bg-BG/chat.json +6 -0
  35. package/locales/bg-BG/discover.json +9 -0
  36. package/locales/bg-BG/error.json +1 -0
  37. package/locales/bg-BG/modelProvider.json +2 -0
  38. package/locales/bg-BG/models.json +33 -24
  39. package/locales/bg-BG/plugin.json +1 -0
  40. package/locales/bg-BG/providers.json +1 -0
  41. package/locales/de-DE/auth.json +1 -0
  42. package/locales/de-DE/chat.json +6 -0
  43. package/locales/de-DE/discover.json +9 -0
  44. package/locales/de-DE/error.json +1 -0
  45. package/locales/de-DE/modelProvider.json +2 -0
  46. package/locales/de-DE/models.json +25 -24
  47. package/locales/de-DE/plugin.json +1 -0
  48. package/locales/de-DE/providers.json +1 -0
  49. package/locales/en-US/chat.json +4 -0
  50. package/locales/en-US/error.json +1 -0
  51. package/locales/en-US/modelProvider.json +2 -0
  52. package/locales/en-US/models.json +28 -27
  53. package/locales/en-US/providers.json +1 -0
  54. package/locales/es-ES/auth.json +1 -0
  55. package/locales/es-ES/chat.json +6 -0
  56. package/locales/es-ES/discover.json +9 -0
  57. package/locales/es-ES/error.json +1 -0
  58. package/locales/es-ES/modelProvider.json +2 -0
  59. package/locales/es-ES/models.json +23 -22
  60. package/locales/es-ES/plugin.json +1 -0
  61. package/locales/es-ES/providers.json +1 -0
  62. package/locales/fa-IR/auth.json +1 -0
  63. package/locales/fa-IR/chat.json +6 -0
  64. package/locales/fa-IR/discover.json +9 -0
  65. package/locales/fa-IR/error.json +1 -0
  66. package/locales/fa-IR/modelProvider.json +2 -0
  67. package/locales/fa-IR/models.json +58 -25
  68. package/locales/fa-IR/plugin.json +1 -0
  69. package/locales/fa-IR/providers.json +1 -0
  70. package/locales/fr-FR/auth.json +1 -0
  71. package/locales/fr-FR/chat.json +6 -0
  72. package/locales/fr-FR/discover.json +9 -0
  73. package/locales/fr-FR/error.json +1 -0
  74. package/locales/fr-FR/modelProvider.json +2 -0
  75. package/locales/fr-FR/models.json +37 -25
  76. package/locales/fr-FR/plugin.json +1 -0
  77. package/locales/fr-FR/providers.json +1 -0
  78. package/locales/it-IT/auth.json +1 -0
  79. package/locales/it-IT/chat.json +6 -0
  80. package/locales/it-IT/discover.json +9 -0
  81. package/locales/it-IT/error.json +1 -0
  82. package/locales/it-IT/modelProvider.json +2 -0
  83. package/locales/it-IT/models.json +81 -20
  84. package/locales/it-IT/plugin.json +1 -0
  85. package/locales/it-IT/providers.json +1 -0
  86. package/locales/ja-JP/auth.json +1 -0
  87. package/locales/ja-JP/chat.json +6 -0
  88. package/locales/ja-JP/discover.json +9 -0
  89. package/locales/ja-JP/error.json +1 -0
  90. package/locales/ja-JP/modelProvider.json +2 -0
  91. package/locales/ja-JP/models.json +100 -24
  92. package/locales/ja-JP/plugin.json +1 -0
  93. package/locales/ja-JP/providers.json +1 -0
  94. package/locales/ko-KR/auth.json +1 -0
  95. package/locales/ko-KR/chat.json +6 -0
  96. package/locales/ko-KR/discover.json +9 -0
  97. package/locales/ko-KR/error.json +1 -0
  98. package/locales/ko-KR/modelProvider.json +2 -0
  99. package/locales/ko-KR/models.json +124 -21
  100. package/locales/ko-KR/plugin.json +1 -0
  101. package/locales/ko-KR/providers.json +1 -0
  102. package/locales/nl-NL/auth.json +1 -0
  103. package/locales/nl-NL/chat.json +6 -0
  104. package/locales/nl-NL/discover.json +9 -0
  105. package/locales/nl-NL/error.json +1 -0
  106. package/locales/nl-NL/modelProvider.json +2 -0
  107. package/locales/nl-NL/models.json +103 -21
  108. package/locales/nl-NL/plugin.json +1 -0
  109. package/locales/nl-NL/providers.json +1 -0
  110. package/locales/pl-PL/auth.json +1 -0
  111. package/locales/pl-PL/chat.json +6 -0
  112. package/locales/pl-PL/discover.json +9 -0
  113. package/locales/pl-PL/error.json +1 -0
  114. package/locales/pl-PL/modelProvider.json +2 -0
  115. package/locales/pl-PL/models.json +36 -27
  116. package/locales/pl-PL/plugin.json +1 -0
  117. package/locales/pl-PL/providers.json +1 -0
  118. package/locales/pt-BR/auth.json +1 -0
  119. package/locales/pt-BR/chat.json +6 -0
  120. package/locales/pt-BR/discover.json +9 -0
  121. package/locales/pt-BR/error.json +1 -0
  122. package/locales/pt-BR/modelProvider.json +2 -0
  123. package/locales/pt-BR/models.json +26 -25
  124. package/locales/pt-BR/plugin.json +1 -0
  125. package/locales/pt-BR/providers.json +1 -0
  126. package/locales/ru-RU/auth.json +1 -0
  127. package/locales/ru-RU/chat.json +6 -0
  128. package/locales/ru-RU/discover.json +9 -0
  129. package/locales/ru-RU/error.json +1 -0
  130. package/locales/ru-RU/modelProvider.json +2 -0
  131. package/locales/ru-RU/models.json +83 -25
  132. package/locales/ru-RU/plugin.json +1 -0
  133. package/locales/ru-RU/providers.json +1 -0
  134. package/locales/tr-TR/auth.json +1 -0
  135. package/locales/tr-TR/chat.json +6 -0
  136. package/locales/tr-TR/discover.json +9 -0
  137. package/locales/tr-TR/error.json +1 -0
  138. package/locales/tr-TR/modelProvider.json +2 -0
  139. package/locales/tr-TR/models.json +89 -27
  140. package/locales/tr-TR/plugin.json +1 -0
  141. package/locales/tr-TR/providers.json +1 -0
  142. package/locales/vi-VN/auth.json +1 -0
  143. package/locales/vi-VN/chat.json +6 -0
  144. package/locales/vi-VN/discover.json +9 -0
  145. package/locales/vi-VN/error.json +1 -0
  146. package/locales/vi-VN/modelProvider.json +2 -0
  147. package/locales/vi-VN/models.json +78 -23
  148. package/locales/vi-VN/plugin.json +1 -0
  149. package/locales/vi-VN/providers.json +1 -0
  150. package/locales/zh-CN/chat.json +4 -4
  151. package/locales/zh-CN/error.json +1 -0
  152. package/locales/zh-CN/modelProvider.json +2 -2
  153. package/locales/zh-CN/models.json +26 -25
  154. package/locales/zh-CN/providers.json +1 -0
  155. package/locales/zh-TW/auth.json +1 -0
  156. package/locales/zh-TW/chat.json +6 -0
  157. package/locales/zh-TW/discover.json +9 -0
  158. package/locales/zh-TW/error.json +1 -0
  159. package/locales/zh-TW/modelProvider.json +2 -0
  160. package/locales/zh-TW/models.json +28 -27
  161. package/locales/zh-TW/plugin.json +1 -0
  162. package/locales/zh-TW/providers.json +1 -0
  163. package/package.json +10 -8
  164. package/packages/agent-runtime/src/core/__tests__/defaultSecurityBlacklist.test.ts +870 -0
  165. package/packages/database/migrations/0077_add_agent_skills.sql +26 -0
  166. package/packages/database/migrations/meta/0077_snapshot.json +11473 -0
  167. package/packages/database/migrations/meta/_journal.json +7 -0
  168. package/packages/database/src/models/__tests__/agentSkill.test.ts +302 -0
  169. package/packages/database/src/models/agentSkill.ts +152 -0
  170. package/packages/database/src/repositories/compression/index.test.ts +1 -1
  171. package/packages/database/src/schemas/agentSkill.ts +71 -0
  172. package/packages/database/src/schemas/index.ts +1 -0
  173. package/packages/database/src/utils/idGenerator.ts +1 -0
  174. package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +1 -0
  175. package/packages/model-runtime/src/core/streams/bedrock/claude.ts +1 -1
  176. package/packages/model-runtime/src/core/streams/bedrock/llama.test.ts +4 -8
  177. package/packages/model-runtime/src/core/streams/bedrock/llama.ts +1 -1
  178. package/packages/model-runtime/src/core/streams/ollama.test.ts +6 -12
  179. package/packages/model-runtime/src/core/streams/ollama.ts +1 -1
  180. package/packages/model-runtime/src/core/streams/protocol.ts +1 -1
  181. package/packages/model-runtime/src/core/streams/qwen.test.ts +1 -1
  182. package/packages/types/src/index.ts +1 -0
  183. package/packages/types/src/session/sessionGroup.ts +5 -2
  184. package/packages/types/src/skill/index.ts +166 -0
  185. package/src/app/(backend)/api/agent/run/route.ts +2 -2
  186. package/src/app/(backend)/api/agent/stream/route.ts +15 -15
  187. package/src/app/(backend)/oidc/consent/route.ts +9 -9
  188. package/src/app/(backend)/trpc/async/[trpc]/route.ts +1 -1
  189. package/src/app/[variants]/(main)/home/_layout/Body/Agent/Modals/ConfigGroupModal/GroupItem.tsx +2 -2
  190. package/src/app/[variants]/(main)/home/_layout/Body/Agent/Modals/ConfigGroupModal/index.tsx +3 -3
  191. package/src/app/[variants]/(mobile)/chat/features/Topic/index.tsx +1 -1
  192. package/src/app/robots.tsx +2 -2
  193. package/src/app/sitemap.tsx +8 -8
  194. package/src/components/AnimatedCollapsed/index.tsx +1 -1
  195. package/src/components/DragUpload/useDragUpload.tsx +2 -2
  196. package/src/components/InvalidAPIKey/ComfyUIForm.tsx +1 -1
  197. package/src/components/MCPStdioCommandInput/index.tsx +2 -2
  198. package/src/components/StatisticCard/growthPercentage.tsx +1 -1
  199. package/src/components/TipGuide/index.tsx +10 -10
  200. package/src/libs/next/proxy/define-config.ts +4 -0
  201. package/src/locales/default/error.ts +2 -0
  202. package/src/server/routers/lambda/market/agentGroup.ts +2 -4
  203. package/src/server/services/oidc/oidcProvider.ts +3 -3
  204. package/src/server/sitemap.ts +4 -4
  205. package/src/store/chat/slices/topic/action.test.ts +190 -0
  206. package/src/store/chat/slices/topic/action.ts +10 -8
  207. package/src/store/file/slices/upload/action.ts +89 -76
  208. package/src/store/home/slices/sidebarUI/action.ts +2 -2
  209. package/src/utils/unzipFile.test.ts +355 -0
  210. package/tsconfig.json +1 -0
  211. package/docs/development/basic/feature-development-frontend.mdx +0 -144
  212. package/docs/development/basic/feature-development-frontend.zh-CN.mdx +0 -142
package/.eslintrc.js CHANGED
@@ -20,6 +20,7 @@ config.rules['unicorn/no-array-for-each'] = 0;
20
20
  config.rules['unicorn/prefer-number-properties'] = 0;
21
21
  config.rules['unicorn/prefer-query-selector'] = 0;
22
22
  config.rules['unicorn/no-array-callback-reference'] = 0;
23
+ config.rules['unicorn/text-encoding-identifier-case'] = 0;
23
24
  config.rules['@typescript-eslint/no-use-before-define'] = 0;
24
25
  // FIXME: Linting error in src/app/[variants]/(main)/chat/features/Migration/DBReader.ts, the fundamental solution should be upgrading typescript-eslint
25
26
  config.rules['@typescript-eslint/no-useless-constructor'] = 0;
@@ -18,6 +18,7 @@ concurrency:
18
18
  jobs:
19
19
  release:
20
20
  name: Release
21
+ if: github.repository == 'lobehub/lobehub'
21
22
  runs-on: ubuntu-latest
22
23
 
23
24
  services:
@@ -0,0 +1,42 @@
1
+ name: 🔄 Branch Synchronization
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ sync-branches:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout repository
13
+ uses: actions/checkout@v6
14
+ with:
15
+ fetch-depth: 0
16
+
17
+ - name: Set up Git
18
+ run: |
19
+ git config --global user.name 'GitHub Actions'
20
+ git config --global user.email 'actions@github.com'
21
+
22
+ - name: Prepare sync branch
23
+ id: branch
24
+ run: |
25
+ echo "SYNC_BRANCH_MAIN_DEV=sync/main-to-dev-$(date +'%Y%m%d')" >> $GITHUB_ENV
26
+
27
+ - name: Sync main to dev
28
+ if: github.ref == 'refs/heads/main'
29
+ run: |
30
+ # Sync main to dev
31
+ git checkout main
32
+ SYNC_BRANCH_DEV=${{ env.SYNC_BRANCH_MAIN_DEV }}
33
+ git checkout -B $SYNC_BRANCH_DEV
34
+ DIFF=$(git diff origin/dev...)
35
+ if [ -z "$DIFF" ]; then
36
+ echo "No changes to sync"
37
+ exit 0
38
+ fi
39
+ git push origin $SYNC_BRANCH_DEV -f
40
+ gh pr create --base dev --head $SYNC_BRANCH_DEV --title "Sync main branch to dev branch" --body "Automatic sync" || exit 0
41
+ env:
42
+ GH_TOKEN: ${{ github.token }}
@@ -24,6 +24,7 @@
24
24
  // support mdx
25
25
  "mdx"
26
26
  ],
27
+ "mdx.server.enable": false,
27
28
  "npm.packageManager": "pnpm",
28
29
  "search.exclude": {
29
30
  "**/node_modules": true,
@@ -51,6 +52,7 @@
51
52
  // make stylelint work with tsx antd-style css template string
52
53
  "typescriptreact"
53
54
  ],
55
+ "typescript.tsdk": "node_modules/typescript/lib",
54
56
  "vitest.maximumConfigs": 20,
55
57
  "workbench.editor.customLabels.patterns": {
56
58
  "**/app/**/[[]*[]]/[[]*[]]/page.tsx": "${dirname(2)}/${dirname(1)}/${dirname} • page component",
package/CHANGELOG.md CHANGED
@@ -2,6 +2,168 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 2.1.21](https://github.com/lobehub/lobe-chat/compare/v2.1.20...v2.1.21)
6
+
7
+ <sup>Released on **2026-02-08**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Add end-user info on OpenAI Responses API call, enable vertical scrolling for topic list on mobile.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Add end-user info on OpenAI Responses API call, closes [#12134](https://github.com/lobehub/lobe-chat/issues/12134) ([72a85ac](https://github.com/lobehub/lobe-chat/commit/72a85ac))
21
+ - **misc**: Enable vertical scrolling for topic list on mobile, closes [#12157](https://github.com/lobehub/lobe-chat/issues/12157) [lobehub/lobe-chat#12029](https://github.com/lobehub/lobe-chat/issues/12029) ([bd4e253](https://github.com/lobehub/lobe-chat/commit/bd4e253))
22
+
23
+ </details>
24
+
25
+ <div align="right">
26
+
27
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
28
+
29
+ </div>
30
+
31
+ ### [Version 2.1.21](https://github.com/lobehub/lobe-chat/compare/v2.1.20...v2.1.21)
32
+
33
+ <sup>Released on **2026-02-08**</sup>
34
+
35
+ <br/>
36
+
37
+ <details>
38
+ <summary><kbd>Improvements and Fixes</kbd></summary>
39
+
40
+ </details>
41
+
42
+ <div align="right">
43
+
44
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
45
+
46
+ </div>
47
+
48
+ ### [Version 2.1.21](https://github.com/lobehub/lobe-chat/compare/v2.1.20...v2.1.21)
49
+
50
+ <sup>Released on **2026-02-08**</sup>
51
+
52
+ <br/>
53
+
54
+ <details>
55
+ <summary><kbd>Improvements and Fixes</kbd></summary>
56
+
57
+ </details>
58
+
59
+ <div align="right">
60
+
61
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
62
+
63
+ </div>
64
+
65
+ ### [Version 2.1.20](https://github.com/lobehub/lobe-chat/compare/v2.1.19...v2.1.20)
66
+
67
+ <sup>Released on **2026-02-08**</sup>
68
+
69
+ #### 🐛 Bug Fixes
70
+
71
+ - **misc**: Add api/version and api/desktop to public routes, show notification when file upload fails due to storage plan limit.
72
+
73
+ <br/>
74
+
75
+ <details>
76
+ <summary><kbd>Improvements and Fixes</kbd></summary>
77
+
78
+ #### What's fixed
79
+
80
+ - **misc**: Add api/version and api/desktop to public routes, closes [#12194](https://github.com/lobehub/lobe-chat/issues/12194) ([ea81cd4](https://github.com/lobehub/lobe-chat/commit/ea81cd4))
81
+ - **misc**: Show notification when file upload fails due to storage plan limit, closes [#12176](https://github.com/lobehub/lobe-chat/issues/12176) ([f26d0df](https://github.com/lobehub/lobe-chat/commit/f26d0df))
82
+
83
+ </details>
84
+
85
+ <div align="right">
86
+
87
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
88
+
89
+ </div>
90
+
91
+ ### [Version 2.1.20](https://github.com/lobehub/lobe-chat/compare/v2.1.19...v2.1.20)
92
+
93
+ <sup>Released on **2026-02-08**</sup>
94
+
95
+ #### 🐛 Bug Fixes
96
+
97
+ - **misc**: Add api/version and api/desktop to public routes, show notification when file upload fails due to storage plan limit.
98
+
99
+ <br/>
100
+
101
+ <details>
102
+ <summary><kbd>Improvements and Fixes</kbd></summary>
103
+
104
+ #### What's fixed
105
+
106
+ - **misc**: Add api/version and api/desktop to public routes, closes [#12194](https://github.com/lobehub/lobe-chat/issues/12194) ([ea81cd4](https://github.com/lobehub/lobe-chat/commit/ea81cd4))
107
+ - **misc**: Show notification when file upload fails due to storage plan limit, closes [#12176](https://github.com/lobehub/lobe-chat/issues/12176) ([f26d0df](https://github.com/lobehub/lobe-chat/commit/f26d0df))
108
+
109
+ </details>
110
+
111
+ <div align="right">
112
+
113
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
114
+
115
+ </div>
116
+
117
+ ### [Version 2.1.20](https://github.com/lobehub/lobe-chat/compare/v2.1.19...v2.1.20)
118
+
119
+ <sup>Released on **2026-02-07**</sup>
120
+
121
+ #### 🐛 Bug Fixes
122
+
123
+ - **misc**: Show notification when file upload fails due to storage plan limit.
124
+
125
+ <br/>
126
+
127
+ <details>
128
+ <summary><kbd>Improvements and Fixes</kbd></summary>
129
+
130
+ #### What's fixed
131
+
132
+ - **misc**: Show notification when file upload fails due to storage plan limit, closes [#12176](https://github.com/lobehub/lobe-chat/issues/12176) ([f26d0df](https://github.com/lobehub/lobe-chat/commit/f26d0df))
133
+
134
+ </details>
135
+
136
+ <div align="right">
137
+
138
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
139
+
140
+ </div>
141
+
142
+ ### [Version 2.1.20](https://github.com/lobehub/lobe-chat/compare/v2.1.19...v2.1.20)
143
+
144
+ <sup>Released on **2026-02-07**</sup>
145
+
146
+ #### 🐛 Bug Fixes
147
+
148
+ - **misc**: Show notification when file upload fails due to storage plan limit.
149
+
150
+ <br/>
151
+
152
+ <details>
153
+ <summary><kbd>Improvements and Fixes</kbd></summary>
154
+
155
+ #### What's fixed
156
+
157
+ - **misc**: Show notification when file upload fails due to storage plan limit, closes [#12176](https://github.com/lobehub/lobe-chat/issues/12176) ([f26d0df](https://github.com/lobehub/lobe-chat/commit/f26d0df))
158
+
159
+ </details>
160
+
161
+ <div align="right">
162
+
163
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
164
+
165
+ </div>
166
+
5
167
  ### [Version 2.1.19](https://github.com/lobehub/lobe-chat/compare/v2.1.18...v2.1.19)
6
168
 
7
169
  <sup>Released on **2026-02-06**</sup>
@@ -16,15 +16,26 @@ import { ControllerModule, IpcMethod } from './index';
16
16
  const logger = createLogger('controllers:ShellCommandCtr');
17
17
 
18
18
  // Maximum output length to prevent context explosion
19
- const MAX_OUTPUT_LENGTH = 10_000;
19
+ const MAX_OUTPUT_LENGTH = 80_000;
20
+
21
+ /**
22
+ * Strip ANSI escape codes from terminal output
23
+ */
24
+ // eslint-disable-next-line no-control-regex
25
+ const ANSI_REGEX = /\u001B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g;
26
+ const stripAnsi = (str: string): string => str.replaceAll(ANSI_REGEX, '');
20
27
 
21
28
  /**
22
29
  * Truncate string to max length with ellipsis indicator
23
30
  */
24
31
  const truncateOutput = (str: string, maxLength: number = MAX_OUTPUT_LENGTH): string => {
25
- if (str.length <= maxLength) return str;
32
+ const cleaned = stripAnsi(str);
33
+ if (cleaned.length <= maxLength) return cleaned;
26
34
  return (
27
- str.slice(0, maxLength) + '\n... [truncated, ' + (str.length - maxLength) + ' more characters]'
35
+ cleaned.slice(0, maxLength) +
36
+ '\n... [truncated, ' +
37
+ (cleaned.length - maxLength) +
38
+ ' more characters]'
28
39
  );
29
40
  };
30
41
 
@@ -193,6 +193,62 @@ describe('ShellCommandCtr', () => {
193
193
  expect(result.stderr).toBe('error message\n');
194
194
  });
195
195
 
196
+ it('should strip ANSI escape codes from output', async () => {
197
+ let exitCallback: (code: number) => void;
198
+ let stdoutCallback: (data: Buffer) => void;
199
+ let stderrCallback: (data: Buffer) => void;
200
+
201
+ mockChildProcess.on.mockImplementation((event: string, callback: any) => {
202
+ if (event === 'exit') {
203
+ exitCallback = callback;
204
+ setTimeout(() => exitCallback(0), 10);
205
+ }
206
+ return mockChildProcess;
207
+ });
208
+
209
+ mockChildProcess.stdout.on.mockImplementation((event: string, callback: any) => {
210
+ if (event === 'data') {
211
+ stdoutCallback = callback;
212
+ // Simulate output with ANSI color codes
213
+ setTimeout(
214
+ () =>
215
+ stdoutCallback(
216
+ Buffer.from(
217
+ '\x1b[38;5;250m███████╗\x1b[0m\n\x1b[1;32mSuccess\x1b[0m\n\x1b[31mError\x1b[0m',
218
+ ),
219
+ ),
220
+ 5,
221
+ );
222
+ }
223
+ return mockChildProcess.stdout;
224
+ });
225
+
226
+ mockChildProcess.stderr.on.mockImplementation((event: string, callback: any) => {
227
+ if (event === 'data') {
228
+ stderrCallback = callback;
229
+ setTimeout(
230
+ () => stderrCallback(Buffer.from('\x1b[33mwarning:\x1b[0m something happened')),
231
+ 5,
232
+ );
233
+ }
234
+ return mockChildProcess.stderr;
235
+ });
236
+
237
+ const result = await shellCommandCtr.handleRunCommand({
238
+ command: 'npx skills find react',
239
+ description: 'search skills',
240
+ });
241
+
242
+ expect(result.success).toBe(true);
243
+ // ANSI codes should be stripped
244
+ expect(result.stdout).not.toContain('\x1b[');
245
+ expect(result.stdout).toContain('███████╗');
246
+ expect(result.stdout).toContain('Success');
247
+ expect(result.stdout).toContain('Error');
248
+ expect(result.stderr).not.toContain('\x1b[');
249
+ expect(result.stderr).toContain('warning: something happened');
250
+ });
251
+
196
252
  it('should truncate long output to prevent context explosion', async () => {
197
253
  let exitCallback: (code: number) => void;
198
254
  let stdoutCallback: (data: Buffer) => void;
@@ -208,8 +264,8 @@ describe('ShellCommandCtr', () => {
208
264
  mockChildProcess.stdout.on.mockImplementation((event: string, callback: any) => {
209
265
  if (event === 'data') {
210
266
  stdoutCallback = callback;
211
- // Simulate very long output (15k characters)
212
- const longOutput = 'x'.repeat(15_000);
267
+ // Simulate very long output (100k characters, exceeding 80k MAX_OUTPUT_LENGTH)
268
+ const longOutput = 'x'.repeat(100_000);
213
269
  setTimeout(() => stdoutCallback(Buffer.from(longOutput)), 5);
214
270
  }
215
271
  return mockChildProcess.stdout;
@@ -223,8 +279,8 @@ describe('ShellCommandCtr', () => {
223
279
  });
224
280
 
225
281
  expect(result.success).toBe(true);
226
- // Output should be truncated to ~10k + truncation message
227
- expect(result.stdout!.length).toBeLessThan(15_000);
282
+ // Output should be truncated to 80k + truncation message
283
+ expect(result.stdout!.length).toBeLessThan(100_000);
228
284
  expect(result.stdout).toContain('truncated');
229
285
  expect(result.stdout).toContain('more characters');
230
286
  });
package/changelog/v2.json CHANGED
@@ -1,4 +1,22 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "Add end-user info on OpenAI Responses API call, enable vertical scrolling for topic list on mobile."
6
+ ]
7
+ },
8
+ "date": "2026-02-08",
9
+ "version": "2.1.21"
10
+ },
11
+ {
12
+ "children": {
13
+ "fixes": [
14
+ "Add api/version and api/desktop to public routes, show notification when file upload fails due to storage plan limit."
15
+ ]
16
+ },
17
+ "date": "2026-02-08",
18
+ "version": "2.1.20"
19
+ },
2
20
  {
3
21
  "children": {
4
22
  "fixes": [
@@ -15,7 +15,7 @@ tags:
15
15
 
16
16
  ## Parameter Standardization
17
17
 
18
- All image generation models must use the standard parameters defined in `src/libs/standard-parameters/index.ts`. This ensures parameter consistency across different Providers, creating a more unified user experience.
18
+ All image generation models must use the standard parameters defined in `packages/model-bank/src/standard-parameters/index.ts`. This ensures parameter consistency across different Providers, creating a more unified user experience.
19
19
 
20
20
  **Supported Standard Parameters**:
21
21
 
@@ -32,7 +32,7 @@ All image generation models must use the standard parameters defined in `src/lib
32
32
 
33
33
  These models can be requested using the OpenAI SDK, with request parameters and return values consistent with DALL-E and GPT-Image-X series.
34
34
 
35
- Taking Zhipu's CogView-4 as an example, which is an OpenAI-compatible model, you can add it by adding the model configuration in the corresponding AI models file `src/config/aiModels/zhipu.ts`:
35
+ Taking Zhipu's CogView-4 as an example, which is an OpenAI-compatible model, you can add it by adding the model configuration in the corresponding AI models file `packages/model-bank/src/aiModels/zhipu.ts`:
36
36
 
37
37
  ```ts
38
38
  const zhipuImageModels: AIImageModelCard[] = [
@@ -71,7 +71,7 @@ Most Providers use `openaiCompatibleFactory` for OpenAI compatibility. You can p
71
71
 
72
72
  1. **Read Provider documentation and standard parameter definitions**
73
73
  - Review the Provider's image generation API documentation to understand request and response formats
74
- - Read `src/libs/standard-parameters/index.ts` to understand supported parameters
74
+ - Read `packages/model-bank/src/standard-parameters/index.ts` to understand supported parameters
75
75
  - Add image model configuration in the corresponding AI models file
76
76
 
77
77
  2. **Implement custom createImage method**
@@ -87,7 +87,7 @@ Most Providers use `openaiCompatibleFactory` for OpenAI compatibility. You can p
87
87
  **Code Example**:
88
88
 
89
89
  ```ts
90
- // src/libs/model-runtime/provider-name/createImage.ts
90
+ // packages/model-runtime/src/providers/<provider-name>/createImage.ts
91
91
  export const createProviderImage = async (
92
92
  payload: ImageGenerationPayload,
93
93
  options: any,
@@ -112,7 +112,7 @@ export const createProviderImage = async (
112
112
  ```
113
113
 
114
114
  ```ts
115
- // src/libs/model-runtime/provider-name/index.ts
115
+ // packages/model-runtime/src/providers/<provider-name>/index.ts
116
116
  export const LobeProviderAI = openaiCompatibleFactory({
117
117
  constructorOptions: {
118
118
  // ... other configurations
@@ -130,7 +130,7 @@ If your Provider has an independent class implementation, you can directly add t
130
130
 
131
131
  1. **Read Provider documentation and standard parameter definitions**
132
132
  - Review the Provider's image generation API documentation
133
- - Read `src/libs/standard-parameters/index.ts`
133
+ - Read `packages/model-bank/src/standard-parameters/index.ts`
134
134
  - Add image model configuration in the corresponding AI models file
135
135
 
136
136
  2. **Implement createImage method in Provider class**
@@ -144,7 +144,7 @@ If your Provider has an independent class implementation, you can directly add t
144
144
  **Code Example**:
145
145
 
146
146
  ```ts
147
- // src/libs/model-runtime/provider-name/index.ts
147
+ // packages/model-runtime/src/providers/<provider-name>/index.ts
148
148
  export class LobeProviderAI {
149
149
  async createImage(
150
150
  payload: ImageGenerationPayload,
@@ -13,7 +13,7 @@ tags:
13
13
 
14
14
  ## 参数标准化
15
15
 
16
- 所有图像生成模型都必须使用 `src/libs/standard-parameters/index.ts` 中定义的标准参数。这确保了不同 Provider 之间的参数一致性,让用户体验更加统一。
16
+ 所有图像生成模型都必须使用 `packages/model-bank/src/standard-parameters/index.ts` 中定义的标准参数。这确保了不同 Provider 之间的参数一致性,让用户体验更加统一。
17
17
 
18
18
  **支持的标准参数**:
19
19
 
@@ -30,7 +30,7 @@ tags:
30
30
 
31
31
  指的是可以使用 openai SDK 进行请求,并且请求参数和和返回值和 dall-e 以及 gpt-image-x 系列一致。
32
32
 
33
- 以智谱的 CogView-4 为例,它是一个兼容 openai 请求格式的模型。你只需要在对应的 ai models 文件 `src/config/aiModels/zhipu.ts` 中,添加模型配置,例如:
33
+ 以智谱的 CogView-4 为例,它是一个兼容 openai 请求格式的模型。你只需要在对应的 ai models 文件 `packages/model-bank/src/aiModels/zhipu.ts` 中,添加模型配置,例如:
34
34
 
35
35
  ```ts
36
36
  const zhipuImageModels: AIImageModelCard[] = [
@@ -69,7 +69,7 @@ const zhipuImageModels: AIImageModelCard[] = [
69
69
 
70
70
  1. **阅读 Provider 官方文档和标准参数定义**
71
71
  - 查看 Provider 的图像生成 API 文档,了解请求格式和响应格式
72
- - 阅读 `src/libs/standard-parameters/index.ts`,了解支持的参数
72
+ - 阅读 `packages/model-bank/src/standard-parameters/index.ts`,了解支持的参数
73
73
  - 在对应的 ai models 文件中增加 image model 配置
74
74
 
75
75
  2. **实现自定义的 createImage 方法**
@@ -85,7 +85,7 @@ const zhipuImageModels: AIImageModelCard[] = [
85
85
  **代码示例**:
86
86
 
87
87
  ```ts
88
- // src/libs/model-runtime/provider-name/createImage.ts
88
+ // packages/model-runtime/src/providers/<provider-name>/createImage.ts
89
89
  export const createProviderImage = async (
90
90
  payload: ImageGenerationPayload,
91
91
  options: any,
@@ -110,7 +110,7 @@ export const createProviderImage = async (
110
110
  ```
111
111
 
112
112
  ```ts
113
- // src/libs/model-runtime/provider-name/index.ts
113
+ // packages/model-runtime/src/providers/<provider-name>/index.ts
114
114
  export const LobeProviderAI = openaiCompatibleFactory({
115
115
  constructorOptions: {
116
116
  // ... 其他配置
@@ -128,7 +128,7 @@ export const LobeProviderAI = openaiCompatibleFactory({
128
128
 
129
129
  1. **阅读 Provider 官方文档和标准参数定义**
130
130
  - 查看 Provider 的图像生成 API 文档
131
- - 阅读 `src/libs/standard-parameters/index.ts`
131
+ - 阅读 `packages/model-bank/src/standard-parameters/index.ts`
132
132
  - 在对应的 ai models 文件中增加 image model 配置
133
133
 
134
134
  2. **在 Provider 类中实现 createImage 方法**
@@ -142,7 +142,7 @@ export const LobeProviderAI = openaiCompatibleFactory({
142
142
  **代码示例**:
143
143
 
144
144
  ```ts
145
- // src/libs/model-runtime/provider-name/index.ts
145
+ // packages/model-runtime/src/providers/<provider-name>/index.ts
146
146
  export class LobeProviderAI {
147
147
  async createImage(
148
148
  payload: ImageGenerationPayload,
@@ -1,50 +1,114 @@
1
1
  ---
2
2
  title: Architecture Design
3
3
  description: >-
4
- Explore the architecture of LobeHub, an AI chat app built on Next.js,
5
- featuring frontend, APIs, and markets.
4
+ Explore the architecture of LobeHub, an open-source AI Agent platform
5
+ built on Next.js, covering frontend, backend, runtime, and data storage.
6
6
  tags:
7
7
  - LobeHub
8
- - AI Chat Application
9
- - Next.js
10
8
  - Architecture Design
11
- - Frontend Development
9
+ - Agent Platform
10
+ - Next.js
12
11
  ---
13
12
 
14
13
  # Architecture Design
15
14
 
16
- LobeHub is an AI chat application built on the Next.js framework, aiming to provide an AI productivity platform that enables users to interact with AI through natural language. The following is an overview of the architecture design of LobeHub:
15
+ LobeHub is an open-source AI Agent platform built on Next.js, enabling users to interact with AI through natural language, use tools, manage knowledge bases, and more. The following is an overview of LobeHub's architecture design.
17
16
 
18
17
  ## Application Architecture Overview
19
18
 
20
- The overall architecture of LobeHub consists of the frontend, EdgeRuntime API, Agents Market, Plugin Market, and independent plugins. These components collaborate to provide a complete AI experience.
19
+ The overall architecture of LobeHub consists of the following core layers:
20
+
21
+ ```plaintext
22
+ +---------------------+--------------------------------------------------+
23
+ | Layer | Description |
24
+ +---------------------+--------------------------------------------------+
25
+ | Frontend | Next.js RSC + React Router DOM hybrid SPA |
26
+ | Backend API | RESTful WebAPI + tRPC Routers |
27
+ | Runtime | Model Runtime + Agent Runtime |
28
+ | Auth | Better Auth (email/password + SSO) |
29
+ | Data Storage | PostgreSQL + Redis + S3 |
30
+ | Marketplace | Agent Market + MCP Tool Market |
31
+ +---------------------+--------------------------------------------------+
32
+ ```
21
33
 
22
34
  ## Frontend Architecture
23
35
 
24
- The frontend of LobeHub adopts the Next.js framework, leveraging its powerful server-side rendering (SSR) capability and routing functionality. The frontend utilizes a stack of technologies, including the antd component library, lobe-ui AIGC component library, zustand state management, swr request library, i18next internationalization library, and more. These technologies collectively support the functionality and features of LobeHub.
36
+ The frontend uses the Next.js framework with a **Next.js RSC + React Router DOM hybrid routing** approach: Next.js App Router handles server-rendered pages (e.g., auth pages), while React Router DOM powers the main SPA.
37
+
38
+ Key tech stack:
39
+
40
+ - **UI Components**: `@lobehub/ui`, antd
41
+ - **CSS-in-JS**: antd-style
42
+ - **State Management**: zustand (slice pattern)
43
+ - **Data Fetching**: SWR + tRPC
44
+ - **i18n**: react-i18next
45
+
46
+ Frontend code is organized by responsibility under `src/`. See [Directory Structure](/docs/development/basic/folder-structure) for details.
47
+
48
+ ## Backend API
49
+
50
+ The backend provides two API styles:
51
+
52
+ - **RESTful WebAPI** (`src/app/(backend)/webapi/`): Handles endpoints requiring special processing such as chat streaming, TTS, and file serving
53
+ - **tRPC Routers** (`src/server/routers/`): Type-safe main business routes, grouped by runtime:
54
+ - `lambda/` — Main business (agent, session, message, topic, file, knowledge, settings, etc.)
55
+ - `async/` — Long-running async operations (file processing, image generation, RAG evaluation)
56
+ - `tools/` — Tool invocations (search, MCP, market)
57
+ - `mobile/` — Mobile-specific routes
58
+
59
+ ## Runtime
60
+
61
+ ### Model Runtime
62
+
63
+ `@lobechat/model-runtime` (`packages/model-runtime/`) is the LLM API adapter layer that normalizes API differences across 30+ AI providers (OpenAI, Anthropic, Google, Bedrock, Ollama, etc.), providing a unified calling interface. Each provider has its own adapter implementation. It is stateless — each call is independent.
64
+
65
+ ### Agent Runtime
66
+
67
+ `@lobechat/agent-runtime` (`packages/agent-runtime/`) is the agent orchestration engine that sits above Model Runtime, driving the full lifecycle of multi-step AI agent behavior:
25
68
 
26
- The components in the frontend architecture include app, components, config, const, features, helpers, hooks, layout, locales, migrations, prompts, services, store, styles, types, and utils. Each component has specific responsibilities and collaborates with others to achieve different functionalities.
69
+ - **Plan-Execute Loop**: Core state machine cycling through LLM calls tool execution result processing
70
+ - **Tool Invocation & Batch Execution**: Supports single and batch tool calls
71
+ - **Human-in-the-Loop**: Security checks and human approval flows
72
+ - **Context Compression**: Manages context window limits
73
+ - **Usage & Cost Tracking**: Accumulates token usage and monetary costs
74
+ - **Multi-Agent Orchestration**: `GroupOrchestrationRuntime` supports Supervisor + Executor pattern for multi-agent collaboration
27
75
 
28
- ## Edge Runtime API
76
+ In short: Model Runtime handles "how to communicate with an LLM provider"; Agent Runtime handles "how to run a complete agent using LLMs, tools, and human approvals."
29
77
 
30
- The Edge Runtime API is one of the core components of LobeHub, responsible for handling the core logic of AI conversations. It provides interaction interfaces with the AI engine, including natural language processing, intent recognition, and response generation. The EdgeRuntime API communicates with the frontend, receiving user input and returning corresponding responses.
78
+ ## Authentication
31
79
 
32
- ## Agents Market
80
+ LobeHub uses [Better Auth](https://www.better-auth.com/) as the authentication framework, supporting:
33
81
 
34
- The Agents Market is a crucial part of LobeHub, providing various AI agents for different scenarios to handle specific tasks and domains. The Agents Market also offers functionality for discovering and uploading agents, allowing users to find agents created by others and easily share their own agents in the market.
82
+ - Email + password registration and login
83
+ - SSO single sign-on (GitHub, Google, and various OAuth providers)
35
84
 
36
- ## Plugin Market
85
+ Auth configuration is in `src/auth.ts`, with related routes under `src/app/(backend)/api/`.
37
86
 
38
- The Plugin Market is another key component of LobeHub, offering various plugins to extend the functionality and features of LobeHub. Plugins can be independent functional modules or integrated with agents from the Agents Market. During conversations, the assistant automatically identifies user input, recognizes suitable plugins, and passes them to the corresponding plugins for processing and returns the results.
87
+ ## Data Storage
39
88
 
40
- ## Security and Performance Optimization
89
+ ```plaintext
90
+ +---------------+----------------------------------------------+
91
+ | Storage | Usage |
92
+ +---------------+----------------------------------------------+
93
+ | PostgreSQL | Primary database for users, sessions, |
94
+ | | messages, agent configs, etc. |
95
+ | Redis | Caching, session state, rate limiting |
96
+ | S3 | File storage (uploads, images, knowledge |
97
+ | | base files, etc.) |
98
+ +---------------+----------------------------------------------+
99
+ ```
41
100
 
42
- LobeHub's security strategy includes authentication and permission management. Users need to authenticate before using LobeHub, and operations are restricted based on the user's permissions.
101
+ Database operations use Drizzle ORM, with schemas defined in `packages/database/src/schemas/`.
43
102
 
44
- To optimize performance, LobeHub utilizes Next.js SSR functionality to achieve fast page loading and response times. Additionally, a series of performance optimization measures are implemented, including code splitting, caching, and resource compression.
103
+ ## Marketplace
45
104
 
46
- ## Development and Deployment Process
105
+ - **Agent Market**: Provides AI agents for various scenarios; users can discover, use, and share agents
106
+ - **MCP Tool Market**: Discover and integrate MCP tools to extend agent capabilities
47
107
 
48
- LobeHub's development process includes version control, testing, continuous integration, and continuous deployment. The development team uses version control systems for code management and conducts unit and integration testing to ensure code quality. Continuous integration and deployment processes ensure rapid delivery and deployment of code.
108
+ ## Development and Deployment
49
109
 
50
- The above is a brief introduction to the architecture design of LobeHub, detailing the responsibilities and collaboration of each component, as well as the impact of design decisions on application functionality and performance.
110
+ - **Version Control**: Git + GitHub, gitmoji commit conventions
111
+ - **Code Quality**: ESLint, Stylelint, TypeScript type checking, circular dependency detection (dpdm), dead code detection (knip)
112
+ - **Testing**: Vitest unit tests + Cucumber/Playwright E2E tests
113
+ - **CI/CD**: GitHub Actions for automated testing, building, and releasing
114
+ - **Deployment**: Supports Vercel, Docker, and self-hosting on major cloud platforms