@lobehub/chat 1.123.4 → 1.124.1

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 (149) hide show
  1. package/.env.example +5 -0
  2. package/CHANGELOG.md +58 -0
  3. package/Dockerfile +2 -0
  4. package/Dockerfile.database +2 -0
  5. package/Dockerfile.pglite +2 -0
  6. package/changelog/v1.json +21 -0
  7. package/docs/self-hosting/environment-variables/model-provider.mdx +18 -0
  8. package/docs/self-hosting/environment-variables/model-provider.zh-CN.mdx +20 -0
  9. package/locales/ar/chat.json +8 -2
  10. package/locales/ar/editor.json +47 -0
  11. package/locales/bg-BG/chat.json +8 -2
  12. package/locales/bg-BG/editor.json +47 -0
  13. package/locales/de-DE/chat.json +8 -2
  14. package/locales/de-DE/editor.json +47 -0
  15. package/locales/en-US/chat.json +8 -2
  16. package/locales/en-US/editor.json +47 -0
  17. package/locales/es-ES/chat.json +8 -2
  18. package/locales/es-ES/editor.json +47 -0
  19. package/locales/es-ES/models.json +3 -1
  20. package/locales/fa-IR/chat.json +8 -2
  21. package/locales/fa-IR/editor.json +47 -0
  22. package/locales/fr-FR/chat.json +8 -2
  23. package/locales/fr-FR/editor.json +47 -0
  24. package/locales/it-IT/chat.json +8 -2
  25. package/locales/it-IT/editor.json +47 -0
  26. package/locales/ja-JP/chat.json +8 -2
  27. package/locales/ja-JP/editor.json +47 -0
  28. package/locales/ko-KR/chat.json +8 -2
  29. package/locales/ko-KR/editor.json +47 -0
  30. package/locales/ko-KR/models.json +3 -1
  31. package/locales/nl-NL/chat.json +8 -2
  32. package/locales/nl-NL/editor.json +47 -0
  33. package/locales/nl-NL/models.json +3 -1
  34. package/locales/pl-PL/chat.json +8 -2
  35. package/locales/pl-PL/editor.json +47 -0
  36. package/locales/pt-BR/chat.json +8 -2
  37. package/locales/pt-BR/editor.json +47 -0
  38. package/locales/ru-RU/chat.json +8 -2
  39. package/locales/ru-RU/editor.json +47 -0
  40. package/locales/tr-TR/chat.json +8 -2
  41. package/locales/tr-TR/editor.json +47 -0
  42. package/locales/vi-VN/chat.json +8 -2
  43. package/locales/vi-VN/editor.json +47 -0
  44. package/locales/zh-CN/chat.json +8 -2
  45. package/locales/zh-CN/editor.json +47 -0
  46. package/locales/zh-CN/modelProvider.json +1 -1
  47. package/locales/zh-TW/chat.json +8 -2
  48. package/locales/zh-TW/editor.json +47 -0
  49. package/locales/zh-TW/models.json +3 -1
  50. package/next.config.ts +4 -0
  51. package/package.json +4 -2
  52. package/packages/const/src/layoutTokens.ts +1 -0
  53. package/packages/model-bank/src/aiModels/aihubmix.ts +38 -4
  54. package/packages/model-bank/src/aiModels/groq.ts +26 -8
  55. package/packages/model-bank/src/aiModels/hunyuan.ts +3 -3
  56. package/packages/model-bank/src/aiModels/modelscope.ts +13 -2
  57. package/packages/model-bank/src/aiModels/moonshot.ts +25 -5
  58. package/packages/model-bank/src/aiModels/novita.ts +40 -9
  59. package/packages/model-bank/src/aiModels/openrouter.ts +0 -13
  60. package/packages/model-bank/src/aiModels/qwen.ts +62 -1
  61. package/packages/model-bank/src/aiModels/siliconcloud.ts +20 -0
  62. package/packages/model-bank/src/aiModels/volcengine.ts +141 -15
  63. package/packages/model-runtime/src/newapi/index.test.ts +49 -42
  64. package/packages/model-runtime/src/newapi/index.ts +124 -143
  65. package/packages/types/src/index.ts +1 -0
  66. package/packages/utils/src/index.ts +1 -0
  67. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/{Footer/MessageFromUrl.tsx → MessageFromUrl.tsx} +3 -2
  68. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/index.tsx +129 -28
  69. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/index.tsx +44 -66
  70. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/useSend.ts +141 -0
  71. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/Content.tsx +7 -1
  72. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/WelcomeChatItem/InboxWelcome/QuestionSuggest.tsx +3 -2
  73. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/WelcomeChatItem/OpeningQuestions.tsx +3 -2
  74. package/src/app/[variants]/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/HeaderAction.tsx +18 -2
  75. package/src/app/[variants]/(main)/settings/provider/(detail)/newapi/page.tsx +1 -1
  76. package/src/config/llm.ts +8 -0
  77. package/src/features/ChatInput/ActionBar/STT/common.tsx +41 -47
  78. package/src/features/ChatInput/{Topic → ActionBar/SaveTopic}/index.tsx +15 -4
  79. package/src/features/ChatInput/ActionBar/Typo/index.tsx +22 -0
  80. package/src/features/ChatInput/ActionBar/components/Action.tsx +4 -0
  81. package/src/features/ChatInput/ActionBar/config.ts +7 -1
  82. package/src/features/ChatInput/ActionBar/index.tsx +40 -51
  83. package/src/features/ChatInput/ChatInputProvider.tsx +54 -0
  84. package/src/features/ChatInput/Desktop/FilePreview/FileItem/index.tsx +20 -11
  85. package/src/features/ChatInput/Desktop/FilePreview/FileList.tsx +16 -15
  86. package/src/features/ChatInput/Desktop/index.tsx +94 -69
  87. package/src/features/ChatInput/InputEditor/index.tsx +134 -0
  88. package/src/{app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files → features/ChatInput/Mobile/FilePreview}/FileItem/File.tsx +1 -2
  89. package/src/features/ChatInput/Mobile/FilePreview/index.tsx +44 -0
  90. package/src/features/ChatInput/Mobile/index.tsx +72 -0
  91. package/src/features/ChatInput/SendArea/ExpandButton.tsx +30 -0
  92. package/src/features/ChatInput/SendArea/SendButton.tsx +29 -0
  93. package/src/features/ChatInput/SendArea/ShortcutHint.tsx +52 -0
  94. package/src/features/ChatInput/SendArea/index.tsx +36 -0
  95. package/src/features/ChatInput/StoreUpdater.tsx +41 -0
  96. package/src/features/ChatInput/TypoBar/index.tsx +139 -0
  97. package/src/features/ChatInput/hooks/useChatInputEditor.ts +36 -0
  98. package/src/features/ChatInput/index.ts +7 -0
  99. package/src/features/ChatInput/store/action.ts +75 -0
  100. package/src/features/ChatInput/store/index.ts +23 -0
  101. package/src/features/ChatInput/store/initialState.ts +54 -0
  102. package/src/features/ChatInput/store/selectors.ts +5 -0
  103. package/src/features/Conversation/components/BackBottom/style.ts +1 -1
  104. package/src/features/Conversation/components/SkeletonList.tsx +10 -3
  105. package/src/features/Conversation/components/VirtualizedList/index.tsx +53 -44
  106. package/src/features/Conversation/components/WideScreenContainer/index.tsx +43 -0
  107. package/src/features/Portal/Thread/Chat/ChatInput/index.tsx +49 -42
  108. package/src/features/Portal/Thread/Chat/ChatInput/useSend.ts +48 -22
  109. package/src/features/Portal/Thread/Chat/index.tsx +2 -2
  110. package/src/features/Portal/Thread/Header/index.tsx +1 -1
  111. package/src/hooks/useHotkeys/chatScope.ts +5 -3
  112. package/src/layout/GlobalProvider/Editor.tsx +27 -0
  113. package/src/layout/GlobalProvider/Locale.tsx +3 -23
  114. package/src/locales/default/chat.ts +8 -2
  115. package/src/locales/default/editor.ts +47 -0
  116. package/src/locales/default/index.ts +2 -0
  117. package/src/locales/default/modelProvider.ts +1 -1
  118. package/src/services/aiChat.ts +8 -2
  119. package/src/store/chat/slices/aiChat/actions/__tests__/cancel-functionality.test.ts +107 -0
  120. package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +394 -40
  121. package/src/store/chat/slices/aiChat/actions/generateAIChatV2.ts +175 -35
  122. package/src/store/chat/slices/aiChat/initialState.ts +19 -0
  123. package/src/store/chat/slices/aiChat/selectors.ts +18 -0
  124. package/src/store/global/action.test.ts +6 -5
  125. package/src/store/global/actions/__tests__/general.test.ts +6 -6
  126. package/src/store/global/actions/workspacePane.ts +6 -0
  127. package/src/store/global/initialState.ts +2 -4
  128. package/src/store/global/selectors/systemStatus.test.ts +1 -2
  129. package/src/store/global/selectors/systemStatus.ts +2 -5
  130. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/SendMore.tsx +0 -104
  131. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/ShortcutHint.tsx +0 -40
  132. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/index.tsx +0 -125
  133. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/TextArea.test.tsx +0 -332
  134. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/TextArea.tsx +0 -29
  135. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files/index.tsx +0 -33
  136. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/InputArea/Container.tsx +0 -41
  137. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/InputArea/index.tsx +0 -156
  138. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Send.tsx +0 -33
  139. package/src/features/ChatInput/Desktop/Header/index.tsx +0 -30
  140. package/src/features/ChatInput/Desktop/InputArea/index.tsx +0 -143
  141. package/src/features/ChatInput/Desktop/__tests__/useAutoFocus.test.ts +0 -45
  142. package/src/features/ChatInput/Desktop/useAutoFocus.ts +0 -13
  143. package/src/features/ChatInput/useSend.ts +0 -102
  144. package/src/features/Portal/Thread/Chat/ChatInput/Footer.tsx +0 -90
  145. package/src/features/Portal/Thread/Chat/ChatInput/TextArea.tsx +0 -30
  146. package/src/libs/trpc/client/types.ts +0 -18
  147. /package/src/{app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files → features/ChatInput/Mobile/FilePreview}/FileItem/Image.tsx +0 -0
  148. /package/src/{app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files → features/ChatInput/Mobile/FilePreview}/FileItem/index.tsx +0 -0
  149. /package/src/{app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Mobile/Files → features/ChatInput/Mobile/FilePreview}/FileItem/style.ts +0 -0
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+
3
+ import { EditorProvider } from '@lobehub/editor/react';
4
+ import { PropsWithChildren, memo, useMemo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ const Editor = memo<PropsWithChildren>(({ children }) => {
8
+ const {
9
+ i18n: { language, getResourceBundle },
10
+ } = useTranslation('editor');
11
+
12
+ const localization = useMemo(() => getResourceBundle(language, 'editor'), [language]);
13
+
14
+ return (
15
+ <EditorProvider
16
+ config={{
17
+ locale: localization,
18
+ }}
19
+ >
20
+ {children}
21
+ </EditorProvider>
22
+ );
23
+ });
24
+
25
+ Editor.displayName = 'Editor';
26
+
27
+ export default Editor;
@@ -1,7 +1,6 @@
1
1
  'use client';
2
2
 
3
3
  import { ConfigProvider } from 'antd';
4
- import { useTheme } from 'antd-style';
5
4
  import dayjs from 'dayjs';
6
5
  import { PropsWithChildren, memo, useEffect, useState } from 'react';
7
6
  import { isRtlLang } from 'rtl-detect';
@@ -10,6 +9,8 @@ import { createI18nNext } from '@/locales/create';
10
9
  import { isOnServerSide } from '@/utils/env';
11
10
  import { getAntdLocale } from '@/utils/locale';
12
11
 
12
+ import Editor from './Editor';
13
+
13
14
  const updateDayjs = async (lang: string) => {
14
15
  // load default lang
15
16
  let dayJSLocale;
@@ -36,7 +37,6 @@ const Locale = memo<LocaleLayoutProps>(({ children, defaultLang, antdLocale }) =
36
37
  const [i18n] = useState(createI18nNext(defaultLang));
37
38
  const [lang, setLang] = useState(defaultLang);
38
39
  const [locale, setLocale] = useState(antdLocale);
39
- const theme = useTheme();
40
40
 
41
41
  // if run on server side, init i18n instance everytime
42
42
  if (isOnServerSide) {
@@ -91,30 +91,10 @@ const Locale = memo<LocaleLayoutProps>(({ children, defaultLang, antdLocale }) =
91
91
  Button: {
92
92
  contentFontSizeSM: 12,
93
93
  },
94
- DatePicker: {
95
- activeBorderColor: theme.colorBorder,
96
- hoverBorderColor: theme.colorBorder,
97
- },
98
- Input: {
99
- activeBorderColor: theme.colorBorder,
100
- hoverBorderColor: theme.colorBorder,
101
- },
102
- InputNumber: {
103
- activeBorderColor: theme.colorBorder,
104
- hoverBorderColor: theme.colorBorder,
105
- },
106
- Mentions: {
107
- activeBorderColor: theme.colorBorder,
108
- hoverBorderColor: theme.colorBorder,
109
- },
110
- Select: {
111
- activeBorderColor: theme.colorBorder,
112
- hoverBorderColor: theme.colorBorder,
113
- },
114
94
  },
115
95
  }}
116
96
  >
117
- {children}
97
+ <Editor>{children}</Editor>
118
98
  </ConfigProvider>
119
99
  );
120
100
  });
@@ -71,10 +71,12 @@ export default {
71
71
  input: {
72
72
  addAi: '添加一条 AI 消息',
73
73
  addUser: '添加一条用户消息',
74
+ disclaimer: 'AI 也可能会犯错,请检查重要信息',
75
+ errorMsg: '消息发送失败,请检查网络后重试: {{errorMsg}}',
74
76
  more: '更多',
75
77
  send: '发送',
76
- sendWithCmdEnter: '按 {{meta}} + Enter 键发送',
77
- sendWithEnter: '按 Enter 键发送',
78
+ sendWithCmdEnter: '按 <key/> 键发送',
79
+ sendWithEnter: '按 <key/> 键发送',
78
80
  stop: '停止',
79
81
  warp: '换行',
80
82
  },
@@ -236,6 +238,10 @@ export default {
236
238
  threadMessageCount: '{{messageCount}} 条消息',
237
239
  title: '子话题',
238
240
  },
241
+ toggleWideScreen: {
242
+ off: '关闭宽屏模式',
243
+ on: '开启宽屏模式',
244
+ },
239
245
  tokenDetails: {
240
246
  chats: '会话消息',
241
247
  historySummary: '历史总结',
@@ -0,0 +1,47 @@
1
+ export default {
2
+ actions: {
3
+ expand: {
4
+ off: '收起',
5
+ on: '展开',
6
+ },
7
+ typobar: {
8
+ off: '隐藏格式工具栏',
9
+ on: '显示格式工具栏',
10
+ },
11
+ },
12
+ file: {
13
+ error: '错误:{{message}}',
14
+ uploading: '正在上传文件...',
15
+ },
16
+ image: {
17
+ broken: '图片损坏',
18
+ },
19
+ link: {
20
+ edit: '编辑链接',
21
+ open: '打开链接',
22
+ placeholder: '输入链接 URL',
23
+ unlink: '取消链接',
24
+ },
25
+ table: {
26
+ delete: '删除表格',
27
+ deleteColumn: '删除列',
28
+ deleteRow: '删除行',
29
+ insertColumnLeft: '在左侧插入 {{count}} 列',
30
+ insertColumnRight: '在右侧插入 {{count}} 列',
31
+ insertRowAbove: '在上方插入 {{count}} 行',
32
+ insertRowBelow: '在下方插入 {{count}} 行',
33
+ },
34
+ typobar: {
35
+ blockquote: '引用',
36
+ bold: '加粗',
37
+ bulletList: '无序列表',
38
+ code: '行内代码',
39
+ codeblock: '代码块',
40
+ italic: '斜体',
41
+ link: '链接',
42
+ numberList: '有序列表',
43
+ strikethrough: '删除线',
44
+ table: '插入表格',
45
+ underline: '下划线',
46
+ },
47
+ };
@@ -6,6 +6,7 @@ import color from './color';
6
6
  import common from './common';
7
7
  import components from './components';
8
8
  import discover from './discover';
9
+ import editor from './editor';
9
10
  import electron from './electron';
10
11
  import error from './error';
11
12
  import file from './file';
@@ -37,6 +38,7 @@ const resources = {
37
38
  common,
38
39
  components,
39
40
  discover,
41
+ editor,
40
42
  electron,
41
43
  error,
42
44
  file,
@@ -164,7 +164,7 @@ export default {
164
164
  title: 'API 密钥',
165
165
  },
166
166
  apiUrl: {
167
- desc: 'New API 服务的 API 地址,大部分时候需要带 /v1',
167
+ desc: 'New API 服务的 API 地址,大部分时候不要带 /v1',
168
168
  title: 'API 地址',
169
169
  },
170
170
  enabled: {
@@ -4,8 +4,14 @@ import { cleanObject } from '@lobechat/utils';
4
4
  import { lambdaClient } from '@/libs/trpc/client';
5
5
 
6
6
  class AiChatService {
7
- sendMessageInServer = async (params: SendMessageServerParams) => {
8
- return lambdaClient.aiChat.sendMessageInServer.mutate(cleanObject(params));
7
+ sendMessageInServer = async (
8
+ params: SendMessageServerParams,
9
+ abortController: AbortController,
10
+ ) => {
11
+ return lambdaClient.aiChat.sendMessageInServer.mutate(cleanObject(params), {
12
+ context: { showNotification: false },
13
+ signal: abortController?.signal,
14
+ });
9
15
  };
10
16
  }
11
17
 
@@ -0,0 +1,107 @@
1
+ import { act, renderHook } from '@testing-library/react';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+
4
+ import { useChatStore } from '../../../../store';
5
+
6
+ describe('Cancel send message functionality tests', () => {
7
+ describe('cancelSendMessageInServer', () => {
8
+ it('should be able to call cancel method normally', () => {
9
+ const { result } = renderHook(() => useChatStore());
10
+
11
+ // Initial state setup
12
+ act(() => {
13
+ useChatStore.setState({
14
+ activeId: 'session-1',
15
+ activeTopicId: 'topic-1',
16
+ mainSendMessageOperations: {},
17
+ });
18
+ });
19
+
20
+ // Test method exists
21
+ expect(typeof result.current.cancelSendMessageInServer).toBe('function');
22
+
23
+ // Test method can be called safely
24
+ expect(() => {
25
+ act(() => {
26
+ result.current.cancelSendMessageInServer();
27
+ });
28
+ }).not.toThrow();
29
+ });
30
+
31
+ it('should be able to call with specified topic ID', () => {
32
+ const { result } = renderHook(() => useChatStore());
33
+
34
+ act(() => {
35
+ useChatStore.setState({
36
+ activeId: 'session-1',
37
+ mainSendMessageOperations: {},
38
+ });
39
+ });
40
+
41
+ expect(() => {
42
+ act(() => {
43
+ result.current.cancelSendMessageInServer('topic-2');
44
+ });
45
+ }).not.toThrow();
46
+ });
47
+ });
48
+
49
+ describe('clearSendMessageError', () => {
50
+ it('should be able to call clear error method normally', () => {
51
+ const { result } = renderHook(() => useChatStore());
52
+
53
+ act(() => {
54
+ useChatStore.setState({
55
+ activeId: 'session-1',
56
+ activeTopicId: 'topic-1',
57
+ mainSendMessageOperations: {},
58
+ });
59
+ });
60
+
61
+ expect(typeof result.current.clearSendMessageError).toBe('function');
62
+
63
+ expect(() => {
64
+ act(() => {
65
+ result.current.clearSendMessageError();
66
+ });
67
+ }).not.toThrow();
68
+ });
69
+ });
70
+
71
+ describe('Internal methods', () => {
72
+ it('should have internal state management methods', () => {
73
+ const { result } = renderHook(() => useChatStore());
74
+
75
+ expect(typeof result.current.internal_toggleSendMessageOperation).toBe('function');
76
+ expect(typeof result.current.internal_updateSendMessageOperation).toBe('function');
77
+ });
78
+
79
+ it('internal_toggleSendMessageOperation should work normally', () => {
80
+ const { result } = renderHook(() => useChatStore());
81
+
82
+ act(() => {
83
+ useChatStore.setState({ mainSendMessageOperations: {} });
84
+ });
85
+
86
+ expect(() => {
87
+ act(() => {
88
+ const abortController = result.current.internal_toggleSendMessageOperation(
89
+ 'test-key',
90
+ true,
91
+ );
92
+ expect(abortController).toBeInstanceOf(AbortController);
93
+ });
94
+ }).not.toThrow();
95
+ });
96
+ });
97
+
98
+ describe('State structure', () => {
99
+ it('should have mainSendMessageOperations state', () => {
100
+ const { result } = renderHook(() => useChatStore());
101
+
102
+ // Ensure state exists
103
+ expect(result.current.mainSendMessageOperations).toBeDefined();
104
+ expect(typeof result.current.mainSendMessageOperations).toBe('object');
105
+ });
106
+ });
107
+ });