@lobehub/lobehub 2.0.0-next.12 → 2.0.0-next.14

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/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/package.json +1 -1
  4. package/packages/const/src/version.ts +3 -3
  5. package/packages/database/src/repositories/dataImporter/deprecated/__tests__/index.test.ts +2 -1
  6. package/packages/database/src/repositories/dataImporter/deprecated/index.ts +7 -1
  7. package/src/app/[variants]/(main)/(mobile)/me/(home)/__tests__/useCategory.test.tsx +9 -0
  8. package/src/app/[variants]/(main)/(mobile)/me/(home)/layout.tsx +0 -2
  9. package/src/app/[variants]/(main)/chat/@session/features/SessionListContent/List/Item/Actions.tsx +3 -28
  10. package/src/app/[variants]/(main)/chat/_layout/Desktop/index.tsx +0 -2
  11. package/src/app/[variants]/(main)/chat/_layout/Mobile.tsx +1 -5
  12. package/src/app/[variants]/(main)/chat/settings/features/HeaderContent.tsx +2 -62
  13. package/src/app/[variants]/(main)/image/features/PromptInput/index.tsx +1 -1
  14. package/src/app/[variants]/(main)/image/page.tsx +0 -2
  15. package/src/app/[variants]/(main)/profile/_layout/Desktop/index.tsx +23 -24
  16. package/src/app/[variants]/(main)/profile/_layout/Mobile/index.tsx +5 -9
  17. package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +0 -2
  18. package/src/app/[variants]/(main)/settings/_layout/Mobile/index.tsx +0 -2
  19. package/src/app/[variants]/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +1 -1
  20. package/src/app/[variants]/loading/index.tsx +1 -10
  21. package/src/components/Link.tsx +12 -0
  22. package/src/envs/app.ts +5 -8
  23. package/src/features/DataImporter/index.tsx +15 -60
  24. package/src/features/DevPanel/PostgresViewer/usePgTable.ts +3 -2
  25. package/src/hooks/useInterceptingRoutes.test.ts +21 -3
  26. package/src/libs/trpc/client/index.ts +0 -1
  27. package/src/libs/trpc/client/lambda.ts +8 -5
  28. package/src/libs/trpc/lambda/context.ts +4 -1
  29. package/src/server/routers/desktop/mcp.ts +1 -3
  30. package/src/server/routers/lambda/config/index.test.ts +2 -2
  31. package/src/server/routers/tools/mcp.ts +2 -3
  32. package/src/server/routers/tools/search.test.ts +1 -7
  33. package/src/server/routers/tools/search.ts +1 -4
  34. package/src/services/__tests__/tool.test.ts +0 -3
  35. package/src/services/aiModel/index.test.ts +0 -3
  36. package/src/services/aiModel/index.ts +1 -7
  37. package/src/services/aiProvider/index.test.ts +0 -3
  38. package/src/services/aiProvider/index.ts +1 -7
  39. package/src/services/chatGroup/index.ts +1 -10
  40. package/src/services/config.ts +1 -65
  41. package/src/services/export/index.ts +1 -4
  42. package/src/services/file/index.ts +1 -11
  43. package/src/services/import/index.ts +1 -7
  44. package/src/services/message/index.ts +1 -11
  45. package/src/services/plugin/index.ts +1 -11
  46. package/src/services/session/index.ts +1 -11
  47. package/src/services/tableViewer/client.ts +12 -15
  48. package/src/services/thread/index.ts +1 -7
  49. package/src/services/topic/index.ts +1 -11
  50. package/src/services/user/index.ts +1 -13
  51. package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts +0 -241
  52. package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +26 -1
  53. package/src/store/chat/slices/aiChat/actions/__tests__/helpers.ts +3 -1
  54. package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +1 -138
  55. package/src/store/user/slices/common/action.test.ts +1 -4
  56. package/src/app/(backend)/trpc/edge/[trpc]/route.ts +0 -26
  57. package/src/app/[variants]/(main)/(mobile)/me/data/features/Category.tsx +0 -48
  58. package/src/app/[variants]/(main)/(mobile)/me/data/features/Header.tsx +0 -33
  59. package/src/app/[variants]/(main)/(mobile)/me/data/layout.tsx +0 -13
  60. package/src/app/[variants]/(main)/(mobile)/me/data/loading.tsx +0 -5
  61. package/src/app/[variants]/(main)/(mobile)/me/data/page.tsx +0 -29
  62. package/src/app/[variants]/(main)/chat/features/Migration/DBReader.ts +0 -290
  63. package/src/app/[variants]/(main)/chat/features/Migration/ExportConfigButton.tsx +0 -35
  64. package/src/app/[variants]/(main)/chat/features/Migration/Failed.tsx +0 -120
  65. package/src/app/[variants]/(main)/chat/features/Migration/Modal.tsx +0 -81
  66. package/src/app/[variants]/(main)/chat/features/Migration/Start.tsx +0 -108
  67. package/src/app/[variants]/(main)/chat/features/Migration/UpgradeButton.tsx +0 -71
  68. package/src/app/[variants]/(main)/chat/features/Migration/const.ts +0 -15
  69. package/src/app/[variants]/(main)/chat/features/Migration/index.tsx +0 -50
  70. package/src/app/[variants]/loading/Client/Content.tsx +0 -48
  71. package/src/app/[variants]/loading/Client/Error.tsx +0 -27
  72. package/src/app/[variants]/loading/Client/Redirect.tsx +0 -47
  73. package/src/app/[variants]/loading/Client/index.tsx +0 -22
  74. package/src/components/InnerLink.tsx +0 -20
  75. package/src/database/_deprecated/core/__tests__/db-upgrade.test.ts +0 -42
  76. package/src/database/_deprecated/core/__tests__/db.test.ts +0 -79
  77. package/src/database/_deprecated/core/__tests__/model.test.ts +0 -55
  78. package/src/database/_deprecated/core/db.ts +0 -246
  79. package/src/database/_deprecated/core/index.ts +0 -2
  80. package/src/database/_deprecated/core/migrations/migrateSettingsToUser/fixtures/input.json +0 -55
  81. package/src/database/_deprecated/core/migrations/migrateSettingsToUser/fixtures/output.json +0 -60
  82. package/src/database/_deprecated/core/migrations/migrateSettingsToUser/index.test.ts +0 -14
  83. package/src/database/_deprecated/core/migrations/migrateSettingsToUser/index.ts +0 -22
  84. package/src/database/_deprecated/core/migrations/migrateSettingsToUser/type.ts +0 -105
  85. package/src/database/_deprecated/core/model.ts +0 -218
  86. package/src/database/_deprecated/core/schemas.ts +0 -88
  87. package/src/database/_deprecated/core/types/db.ts +0 -15
  88. package/src/database/_deprecated/models/__DEBUG.ts +0 -124
  89. package/src/database/_deprecated/models/__tests__/file.test.ts +0 -83
  90. package/src/database/_deprecated/models/__tests__/message.test.ts +0 -426
  91. package/src/database/_deprecated/models/__tests__/plugin.test.ts +0 -81
  92. package/src/database/_deprecated/models/__tests__/session.test.ts +0 -253
  93. package/src/database/_deprecated/models/__tests__/sessionGroup.test.ts +0 -220
  94. package/src/database/_deprecated/models/__tests__/topic.test.ts +0 -523
  95. package/src/database/_deprecated/models/__tests__/user.test.ts +0 -82
  96. package/src/database/_deprecated/models/file.ts +0 -51
  97. package/src/database/_deprecated/models/message.ts +0 -277
  98. package/src/database/_deprecated/models/plugin.ts +0 -62
  99. package/src/database/_deprecated/models/session.ts +0 -271
  100. package/src/database/_deprecated/models/sessionGroup.ts +0 -93
  101. package/src/database/_deprecated/models/topic.ts +0 -250
  102. package/src/database/_deprecated/models/user.ts +0 -69
  103. package/src/database/_deprecated/schemas/files.ts +0 -39
  104. package/src/database/_deprecated/schemas/message.ts +0 -50
  105. package/src/database/_deprecated/schemas/plugin.ts +0 -12
  106. package/src/database/_deprecated/schemas/session.ts +0 -54
  107. package/src/database/_deprecated/schemas/sessionGroup.ts +0 -8
  108. package/src/database/_deprecated/schemas/topic.ts +0 -12
  109. package/src/database/_deprecated/schemas/user.ts +0 -40
  110. package/src/features/DataImporter/_deprecated.ts +0 -43
  111. package/src/features/InitClientDB/EnableModal.tsx +0 -118
  112. package/src/features/InitClientDB/ErrorResult.tsx +0 -143
  113. package/src/features/InitClientDB/InitIndicator.tsx +0 -124
  114. package/src/features/InitClientDB/PGliteIcon.tsx +0 -28
  115. package/src/features/InitClientDB/features/DatabaseRepair/Backup.tsx +0 -75
  116. package/src/features/InitClientDB/features/DatabaseRepair/Diagnosis.tsx +0 -98
  117. package/src/features/InitClientDB/features/DatabaseRepair/Repair.tsx +0 -218
  118. package/src/features/InitClientDB/features/DatabaseRepair/index.tsx +0 -91
  119. package/src/features/InitClientDB/index.tsx +0 -37
  120. package/src/libs/trpc/client/edge.ts +0 -26
  121. package/src/libs/trpc/edge/context.ts +0 -71
  122. package/src/libs/trpc/edge/index.ts +0 -45
  123. package/src/libs/trpc/edge/init.ts +0 -26
  124. package/src/libs/trpc/edge/middleware/jwtPayload.test.ts +0 -75
  125. package/src/libs/trpc/edge/middleware/jwtPayload.ts +0 -14
  126. package/src/migrations/FromV0ToV1.ts +0 -10
  127. package/src/migrations/FromV1ToV2/fixtures/input-v1-session.json +0 -191
  128. package/src/migrations/FromV1ToV2/fixtures/output-v2.json +0 -202
  129. package/src/migrations/FromV1ToV2/index.ts +0 -82
  130. package/src/migrations/FromV1ToV2/migrations.test.ts +0 -224
  131. package/src/migrations/FromV1ToV2/types/v1.ts +0 -78
  132. package/src/migrations/FromV1ToV2/types/v2.ts +0 -52
  133. package/src/migrations/FromV2ToV3/fixtures/input-v2-session.json +0 -72
  134. package/src/migrations/FromV2ToV3/fixtures/output-v3-from-v1.json +0 -203
  135. package/src/migrations/FromV2ToV3/fixtures/output-v3.json +0 -74
  136. package/src/migrations/FromV2ToV3/index.ts +0 -30
  137. package/src/migrations/FromV2ToV3/migrations.test.ts +0 -42
  138. package/src/migrations/FromV2ToV3/types/v3.ts +0 -27
  139. package/src/migrations/FromV3ToV4/fixtures/azure-input-v3.json +0 -79
  140. package/src/migrations/FromV3ToV4/fixtures/azure-output-v4.json +0 -75
  141. package/src/migrations/FromV3ToV4/fixtures/ollama-input-v3.json +0 -85
  142. package/src/migrations/FromV3ToV4/fixtures/ollama-output-v4.json +0 -86
  143. package/src/migrations/FromV3ToV4/fixtures/openai-input-v3.json +0 -77
  144. package/src/migrations/FromV3ToV4/fixtures/openai-output-v4.json +0 -77
  145. package/src/migrations/FromV3ToV4/fixtures/openrouter-input-v3.json +0 -82
  146. package/src/migrations/FromV3ToV4/fixtures/openrouter-output-v4.json +0 -85
  147. package/src/migrations/FromV3ToV4/fixtures/output-v4-from-v1.json +0 -203
  148. package/src/migrations/FromV3ToV4/index.ts +0 -102
  149. package/src/migrations/FromV3ToV4/migrations.test.ts +0 -195
  150. package/src/migrations/FromV3ToV4/types/v3.ts +0 -52
  151. package/src/migrations/FromV3ToV4/types/v4.ts +0 -37
  152. package/src/migrations/FromV4ToV5/fixtures/from-v1-to-v5-output.json +0 -245
  153. package/src/migrations/FromV4ToV5/fixtures/function-input-v4.json +0 -96
  154. package/src/migrations/FromV4ToV5/fixtures/function-output-v5.json +0 -120
  155. package/src/migrations/FromV4ToV5/index.ts +0 -58
  156. package/src/migrations/FromV4ToV5/migrations.test.ts +0 -49
  157. package/src/migrations/FromV4ToV5/types/v4.ts +0 -21
  158. package/src/migrations/FromV4ToV5/types/v5.ts +0 -27
  159. package/src/migrations/FromV5ToV6/fixtures/from-v1-to-v6-output.json +0 -247
  160. package/src/migrations/FromV5ToV6/fixtures/session-input-v5.json +0 -81
  161. package/src/migrations/FromV5ToV6/fixtures/session-output-v6.json +0 -85
  162. package/src/migrations/FromV5ToV6/index.ts +0 -61
  163. package/src/migrations/FromV5ToV6/migrations.test.ts +0 -50
  164. package/src/migrations/FromV5ToV6/types/v5.ts +0 -48
  165. package/src/migrations/FromV5ToV6/types/v6.ts +0 -63
  166. package/src/migrations/FromV6ToV7/fixtures/output-v7-from-v1.json +0 -203
  167. package/src/migrations/FromV6ToV7/fixtures/provider-input-v6.json +0 -103
  168. package/src/migrations/FromV6ToV7/fixtures/provider-output-v7.json +0 -118
  169. package/src/migrations/FromV6ToV7/index.ts +0 -101
  170. package/src/migrations/FromV6ToV7/migrations.test.ts +0 -64
  171. package/src/migrations/FromV6ToV7/types/v6.ts +0 -61
  172. package/src/migrations/FromV6ToV7/types/v7.ts +0 -69
  173. package/src/migrations/VersionController.test.ts +0 -88
  174. package/src/migrations/VersionController.ts +0 -67
  175. package/src/migrations/index.ts +0 -61
  176. package/src/server/routers/edge/appStatus.ts +0 -3
  177. package/src/server/routers/edge/index.ts +0 -14
  178. package/src/server/routers/edge/upload.ts +0 -16
  179. package/src/services/aiModel/client.ts +0 -70
  180. package/src/services/aiProvider/client.ts +0 -58
  181. package/src/services/baseClientService/index.ts +0 -9
  182. package/src/services/chatGroup/client.ts +0 -63
  183. package/src/services/export/_deprecated.ts +0 -155
  184. package/src/services/export/client.ts +0 -15
  185. package/src/services/file/_deprecated.test.ts +0 -119
  186. package/src/services/file/_deprecated.ts +0 -80
  187. package/src/services/file/client.test.ts +0 -199
  188. package/src/services/file/client.ts +0 -85
  189. package/src/services/import/_deprecated.ts +0 -115
  190. package/src/services/import/client.test.ts +0 -1015
  191. package/src/services/import/client.ts +0 -64
  192. package/src/services/message/_deprecated.test.ts +0 -398
  193. package/src/services/message/_deprecated.ts +0 -168
  194. package/src/services/message/client.test.ts +0 -410
  195. package/src/services/message/client.ts +0 -192
  196. package/src/services/plugin/_deprecated.test.ts +0 -162
  197. package/src/services/plugin/_deprecated.ts +0 -42
  198. package/src/services/plugin/client.test.ts +0 -177
  199. package/src/services/plugin/client.ts +0 -46
  200. package/src/services/session/_deprecated.test.ts +0 -440
  201. package/src/services/session/_deprecated.ts +0 -190
  202. package/src/services/session/client.test.ts +0 -413
  203. package/src/services/session/client.ts +0 -193
  204. package/src/services/thread/client.ts +0 -51
  205. package/src/services/topic/_deprecated.test.ts +0 -245
  206. package/src/services/topic/_deprecated.ts +0 -75
  207. package/src/services/topic/client.ts +0 -89
  208. package/src/services/topic/pglite.test.ts +0 -212
  209. package/src/services/user/_deprecated.test.ts +0 -101
  210. package/src/services/user/_deprecated.ts +0 -70
  211. package/src/services/user/client.test.ts +0 -111
  212. package/src/services/user/client.ts +0 -104
@@ -1,410 +0,0 @@
1
- import {
2
- ChatMessageError,
3
- ChatTTS,
4
- ChatTranslate,
5
- CreateMessageParams,
6
- DBMessageItem,
7
- UIChatMessage,
8
- } from '@lobechat/types';
9
- import { and, eq } from 'drizzle-orm';
10
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
11
-
12
- import { clientDB, initializeDB } from '@/database/client/db';
13
- import {
14
- files,
15
- messagePlugins,
16
- messageTTS,
17
- messageTranslates,
18
- messages,
19
- sessions,
20
- topics,
21
- users,
22
- } from '@/database/schemas';
23
-
24
- import { ClientService } from './client';
25
-
26
- const userId = 'message-db';
27
- const sessionId = '1';
28
- const topicId = 'topic-id';
29
-
30
- // Mock data
31
- const mockMessageId = 'mock-message-id';
32
- const mockMessage = {
33
- id: mockMessageId,
34
- content: 'Mock message content',
35
- sessionId,
36
- role: 'user',
37
- } as UIChatMessage;
38
-
39
- const mockMessages = [mockMessage];
40
-
41
- beforeEach(async () => {
42
- await initializeDB();
43
-
44
- // 在每个测试用例之前,清空表
45
- await clientDB.transaction(async (trx) => {
46
- await trx.delete(users);
47
- await trx.insert(users).values([{ id: userId }, { id: '456' }]);
48
-
49
- await trx.insert(sessions).values([{ id: sessionId, userId }]);
50
- await trx.insert(topics).values([{ id: topicId, sessionId, userId }]);
51
- await trx.insert(files).values({
52
- id: 'f1',
53
- userId: userId,
54
- url: 'abc',
55
- name: 'file-1',
56
- fileType: 'image/png',
57
- size: 1000,
58
- });
59
- });
60
- });
61
-
62
- afterEach(async () => {
63
- // 在每个测试用例之后,清空表
64
- await clientDB.delete(users);
65
- });
66
-
67
- const messageService = new ClientService(userId);
68
-
69
- describe('MessageClientService', () => {
70
- describe('create', () => {
71
- it('should create a message and return its id', async () => {
72
- // Setup
73
- const createParams: CreateMessageParams = {
74
- content: 'New message content',
75
- sessionId,
76
- role: 'user',
77
- };
78
-
79
- // Execute
80
- const messageId = await messageService.createMessage(createParams);
81
-
82
- // Assert
83
- expect(messageId).toMatch(/^msg_/);
84
- });
85
- });
86
-
87
- describe('batchCreate', () => {
88
- it('should batch create messages', async () => {
89
- // Execute
90
- await messageService.batchCreateMessages([
91
- {
92
- content: 'Mock message content',
93
- sessionId,
94
- role: 'user',
95
- },
96
- {
97
- content: 'Mock message content',
98
- sessionId,
99
- role: 'user',
100
- },
101
- ] as DBMessageItem[]);
102
- const count = await clientDB.$count(messages);
103
-
104
- // Assert
105
- expect(count).toBe(2);
106
- });
107
- });
108
-
109
- describe('removeMessage', () => {
110
- it('should remove a message by id', async () => {
111
- // Execute
112
- await clientDB.insert(messages).values({ id: mockMessageId, role: 'user', userId });
113
- await messageService.removeMessage(mockMessageId);
114
-
115
- // Assert
116
- const count = await clientDB.$count(messages);
117
-
118
- expect(count).toBe(0);
119
- });
120
- });
121
- describe('removeMessages', () => {
122
- it('should remove a message by id', async () => {
123
- // Setup
124
- await clientDB.insert(messages).values([
125
- { id: mockMessageId, role: 'user', userId },
126
- { role: 'assistant', userId },
127
- ]);
128
-
129
- // Execute
130
- await messageService.removeMessages([mockMessageId]);
131
-
132
- // Assert
133
- const count = await clientDB.$count(messages);
134
-
135
- expect(count).toBe(1);
136
- });
137
- });
138
-
139
- describe('getMessages', () => {
140
- it('should retrieve messages by sessionId and topicId', async () => {
141
- // Setup
142
- await clientDB
143
- .insert(messages)
144
- .values({ id: mockMessageId, sessionId, topicId, role: 'user', userId });
145
-
146
- // Execute
147
- const data = await messageService.getMessages(sessionId, topicId);
148
-
149
- // Assert
150
- expect(data[0]).toMatchObject({ id: mockMessageId, role: 'user' });
151
- });
152
- });
153
-
154
- describe('getAllMessagesInSession', () => {
155
- it('should retrieve all messages in a session', async () => {
156
- // Setup
157
- const sessionId = 'session-id';
158
- await clientDB.insert(sessions).values([
159
- { id: 'bbb', userId },
160
- { id: sessionId, userId },
161
- ]);
162
- await clientDB.insert(messages).values([
163
- { sessionId, topicId, role: 'user', userId },
164
- { sessionId, topicId, role: 'assistant', userId },
165
- { sessionId: 'bbb', topicId, role: 'assistant', userId },
166
- ]);
167
-
168
- // Execute
169
- const data = await messageService.getAllMessagesInSession(sessionId);
170
-
171
- // Assert
172
- expect(data.length).toBe(2);
173
- });
174
- });
175
-
176
- describe('removeMessagesByAssistant', () => {
177
- it('should batch remove messages by assistantId and topicId', async () => {
178
- // Setup
179
- const assistantId = 'assistant-id';
180
- const sessionId = 'session-id';
181
- await clientDB.insert(sessions).values([
182
- { id: 'bbb', userId },
183
- { id: sessionId, userId },
184
- ]);
185
- await clientDB.insert(messages).values([
186
- { sessionId, topicId, role: 'user', userId },
187
- { sessionId, topicId, role: 'assistant', userId },
188
- { sessionId: 'bbb', topicId, role: 'assistant', userId },
189
- ]);
190
-
191
- // Execute
192
- await messageService.removeMessagesByAssistant(sessionId, topicId);
193
-
194
- // Assert
195
- const result = await clientDB.query.messages.findMany({
196
- where: and(eq(messages.sessionId, sessionId), eq(messages.topicId, topicId)),
197
- });
198
-
199
- expect(result.length).toBe(0);
200
- });
201
- });
202
-
203
- describe('clearAllMessage', () => {
204
- it('should clear all messages from the table', async () => {
205
- // Setup
206
- await clientDB.insert(users).values({ id: 'another' });
207
- await clientDB.insert(messages).values([
208
- { id: mockMessageId, role: 'user', userId },
209
- { role: 'user', userId: 'another' },
210
- ]);
211
-
212
- // Execute
213
- await messageService.removeAllMessages();
214
-
215
- // Assert
216
- const result = await clientDB.query.messages.findMany({
217
- where: eq(messages.userId, userId),
218
- });
219
- expect(result.length).toBe(0);
220
- });
221
- });
222
-
223
- describe('getAllMessages', () => {
224
- it('should retrieve all messages', async () => {
225
- await clientDB.insert(messages).values([
226
- { sessionId, topicId, content: '1', role: 'user', userId },
227
- { sessionId, topicId, content: '2', role: 'assistant', userId },
228
- ]);
229
-
230
- // Execute
231
- const data = await messageService.getAllMessages();
232
-
233
- // Assert
234
- expect(data).toMatchObject([
235
- { sessionId, topicId, content: '1', role: 'user', userId },
236
- { sessionId, topicId, content: '2', role: 'assistant', userId },
237
- ]);
238
- });
239
- });
240
-
241
- describe('updateMessageError', () => {
242
- it('should update the error field of a message', async () => {
243
- // Setup
244
- await clientDB.insert(messages).values({ id: mockMessageId, role: 'user', userId });
245
- const newError = {
246
- type: 'InvalidProviderAPIKey',
247
- message: 'Error occurred',
248
- } as ChatMessageError;
249
-
250
- // Execute
251
- await messageService.updateMessageError(mockMessageId, newError);
252
-
253
- // Assert
254
- const result = await clientDB.query.messages.findFirst({
255
- where: eq(messages.id, mockMessageId),
256
- });
257
-
258
- expect(result!.error).toEqual(newError);
259
- });
260
- });
261
-
262
- // describe('updateMessagePlugin', () => {
263
- // it('should update the plugin payload of a message', async () => {
264
- // // Setup
265
- // const newPlugin = {
266
- // type: 'default',
267
- // apiName: 'abc',
268
- // arguments: '',
269
- // identifier: 'plugin1',
270
- // } as ChatPluginPayload;
271
- //
272
- // (MessageModel.update as Mock).mockResolvedValue({ ...mockMessage, plugin: newPlugin });
273
- //
274
- // // Execute
275
- // const result = await messageService.updateMessagePlugin(mockMessageId, newPlugin);
276
- //
277
- // // Assert
278
- // expect(MessageModel.update).toHaveBeenCalledWith(mockMessageId, { plugin: newPlugin });
279
- // expect(result).toEqual({ ...mockMessage, plugin: newPlugin });
280
- // });
281
- // });
282
-
283
- describe('updateMessagePluginState', () => {
284
- it('should update the plugin state of a message', async () => {
285
- // Setup
286
- await clientDB.insert(messages).values({ id: mockMessageId, role: 'user', userId });
287
- await clientDB.insert(messagePlugins).values({ id: mockMessageId, userId });
288
- const key = 'stateKey';
289
- const value = 'stateValue';
290
- const newPluginState = { [key]: value };
291
-
292
- // Execute
293
- await messageService.updateMessagePluginState(mockMessageId, { stateKey: value });
294
-
295
- // Assert
296
- const result = await clientDB.query.messagePlugins.findFirst({
297
- where: eq(messagePlugins.id, mockMessageId),
298
- });
299
- expect(result!.state).toEqual(newPluginState);
300
- });
301
- });
302
-
303
- describe('updateMessagePluginArguments', () => {
304
- it('should update the plugin arguments object of a message', async () => {
305
- // Setup
306
- await clientDB.insert(messages).values({ id: mockMessageId, role: 'user', userId });
307
- await clientDB.insert(messagePlugins).values({ id: mockMessageId, userId });
308
- const value = 'stateValue';
309
-
310
- // Execute
311
- await messageService.updateMessagePluginArguments(mockMessageId, { key: value });
312
-
313
- // Assert
314
- const result = await clientDB.query.messagePlugins.findFirst({
315
- where: eq(messageTTS.id, mockMessageId),
316
- });
317
- expect(result).toMatchObject({ arguments: '{"key":"stateValue"}' });
318
- });
319
- it('should update the plugin arguments string of a message', async () => {
320
- // Setup
321
- await clientDB.insert(messages).values({ id: mockMessageId, role: 'user', userId });
322
- await clientDB.insert(messagePlugins).values({ id: mockMessageId, userId });
323
- const value = 'stateValue';
324
- // Execute
325
- await messageService.updateMessagePluginArguments(
326
- mockMessageId,
327
- JSON.stringify({ abc: value }),
328
- );
329
-
330
- // Assert
331
- const result = await clientDB.query.messagePlugins.findFirst({
332
- where: eq(messageTTS.id, mockMessageId),
333
- });
334
- expect(result).toMatchObject({ arguments: '{"abc":"stateValue"}' });
335
- });
336
- });
337
-
338
- describe('countMessages', () => {
339
- it('should count the total number of messages', async () => {
340
- // Setup
341
- await clientDB.insert(messages).values({ id: mockMessageId, role: 'user', userId });
342
-
343
- // Execute
344
- const count = await messageService.countMessages();
345
-
346
- // Assert
347
- expect(count).toBe(1);
348
- });
349
- });
350
-
351
- describe('updateMessageTTS', () => {
352
- it('should update the TTS field of a message', async () => {
353
- // Setup
354
- await clientDB
355
- .insert(files)
356
- .values({ id: 'file-abc', fileType: 'text', name: 'abc', url: 'abc', size: 100, userId });
357
- await clientDB.insert(messages).values({ id: mockMessageId, role: 'user', userId });
358
- const newTTS: ChatTTS = { contentMd5: 'abc', file: 'file-abc' };
359
-
360
- // Execute
361
- await messageService.updateMessageTTS(mockMessageId, newTTS);
362
-
363
- // Assert
364
- const result = await clientDB.query.messageTTS.findFirst({
365
- where: eq(messageTTS.id, mockMessageId),
366
- });
367
-
368
- expect(result).toMatchObject({ contentMd5: 'abc', fileId: 'file-abc', id: mockMessageId });
369
- });
370
- });
371
-
372
- describe('updateMessageTranslate', () => {
373
- it('should update the translate field of a message', async () => {
374
- // Setup
375
- await clientDB.insert(messages).values({ id: mockMessageId, role: 'user', userId });
376
- const newTranslate: ChatTranslate = { content: 'Translated text', to: 'es' };
377
-
378
- // Execute
379
- await messageService.updateMessageTranslate(mockMessageId, newTranslate);
380
-
381
- // Assert
382
- const result = await clientDB.query.messageTranslates.findFirst({
383
- where: eq(messageTranslates.id, mockMessageId),
384
- });
385
-
386
- expect(result).toMatchObject(newTranslate);
387
- });
388
- });
389
-
390
- describe('hasMessages', () => {
391
- it('should return true if there are messages', async () => {
392
- // Setup
393
- await clientDB.insert(messages).values({ id: mockMessageId, role: 'user', userId });
394
-
395
- // Execute
396
- const result = await messageService.hasMessages();
397
-
398
- // Assert
399
- expect(result).toBe(true);
400
- });
401
-
402
- it('should return false if there are no messages', async () => {
403
- // Execute
404
- const result = await messageService.hasMessages();
405
-
406
- // Assert
407
- expect(result).toBe(false);
408
- });
409
- });
410
- });
@@ -1,192 +0,0 @@
1
- import { UIChatMessage } from '@lobechat/types';
2
-
3
- import { INBOX_SESSION_ID } from '@/const/session';
4
- import { clientDB } from '@/database/client/db';
5
- import { MessageModel } from '@/database/models/message';
6
- import { BaseClientService } from '@/services/baseClientService';
7
- import { clientS3Storage } from '@/services/file/ClientS3';
8
-
9
- import { IMessageService } from './type';
10
-
11
- export class ClientService extends BaseClientService implements IMessageService {
12
- private get messageModel(): MessageModel {
13
- return new MessageModel(clientDB as any, this.userId);
14
- }
15
-
16
- createMessage: IMessageService['createMessage'] = async ({ sessionId, ...params }) => {
17
- const { id } = await this.messageModel.create({
18
- ...params,
19
- sessionId: sessionId ? (this.toDbSessionId(sessionId) as string) : '',
20
- });
21
-
22
- return id;
23
- };
24
-
25
- createNewMessage: IMessageService['createNewMessage'] = async ({ sessionId, ...params }) => {
26
- return await this.messageModel.createNewMessage(
27
- {
28
- ...params,
29
- sessionId: sessionId ? (this.toDbSessionId(sessionId) as string) : '',
30
- },
31
- {
32
- postProcessUrl: this.postProcessUrl,
33
- },
34
- );
35
- };
36
-
37
- batchCreateMessages: IMessageService['batchCreateMessages'] = async (messages) => {
38
- return this.messageModel.batchCreate(messages);
39
- };
40
-
41
- getMessages: IMessageService['getMessages'] = async (sessionId, topicId) => {
42
- const data = await this.messageModel.query(
43
- {
44
- sessionId: this.toDbSessionId(sessionId),
45
- topicId,
46
- },
47
- {
48
- groupAssistantMessages: false,
49
- postProcessUrl: this.postProcessUrl,
50
- },
51
- );
52
-
53
- return data as unknown as UIChatMessage[];
54
- };
55
-
56
- getGroupMessages: IMessageService['getGroupMessages'] = async (groupId, topicId) => {
57
- // Use full query to hydrate fileList/imageList like single chat
58
- const data = await this.messageModel.query(
59
- {
60
- sessionId: groupId,
61
- topicId,
62
- },
63
- {
64
- groupAssistantMessages: false,
65
- postProcessUrl: this.postProcessUrl,
66
- },
67
- );
68
-
69
- return data as unknown as UIChatMessage[];
70
- };
71
-
72
- getAllMessages: IMessageService['getAllMessages'] = async () => {
73
- const data = await this.messageModel.queryAll();
74
-
75
- return data as unknown as UIChatMessage[];
76
- };
77
-
78
- countMessages: IMessageService['countMessages'] = async (params) => {
79
- return this.messageModel.count(params);
80
- };
81
-
82
- countWords: IMessageService['countWords'] = async (params) => {
83
- return this.messageModel.countWords(params);
84
- };
85
-
86
- rankModels: IMessageService['rankModels'] = async () => {
87
- return this.messageModel.rankModels();
88
- };
89
-
90
- getHeatmaps: IMessageService['getHeatmaps'] = async () => {
91
- return this.messageModel.getHeatmaps();
92
- };
93
-
94
- getAllMessagesInSession: IMessageService['getAllMessagesInSession'] = async (sessionId) => {
95
- const data = this.messageModel.queryBySessionId(this.toDbSessionId(sessionId));
96
-
97
- return data as unknown as UIChatMessage[];
98
- };
99
-
100
- updateMessageError: IMessageService['updateMessageError'] = async (id, error) => {
101
- return this.messageModel.update(id, { error });
102
- };
103
-
104
- updateMessage: IMessageService['updateMessage'] = async (id, message, options) => {
105
- return this.messageModel.update(id, message, {
106
- postProcessUrl: this.postProcessUrl,
107
- sessionId: options?.sessionId,
108
- topicId: options?.topicId,
109
- });
110
- };
111
-
112
- updateMessageTTS: IMessageService['updateMessageTTS'] = async (id, tts) => {
113
- return this.messageModel.updateTTS(id, tts as any);
114
- };
115
-
116
- updateMessageTranslate: IMessageService['updateMessageTranslate'] = async (id, translate) => {
117
- return this.messageModel.updateTranslate(id, translate as any);
118
- };
119
-
120
- updateMessagePluginState: IMessageService['updateMessagePluginState'] = async (id, value) => {
121
- return this.messageModel.updatePluginState(id, value);
122
- };
123
-
124
- updateMessagePluginError: IMessageService['updateMessagePluginError'] = async (id, value) => {
125
- return this.messageModel.updateMessagePlugin(id, { error: value });
126
- };
127
-
128
- updateMessageRAG: IMessageService['updateMessageRAG'] = async (id, value) => {
129
- console.log(id, value);
130
- throw new Error('not implemented');
131
- };
132
-
133
- updateMessagePluginArguments: IMessageService['updateMessagePluginArguments'] = async (
134
- id,
135
- value,
136
- ) => {
137
- const args = typeof value === 'string' ? value : JSON.stringify(value);
138
-
139
- return this.messageModel.updateMessagePlugin(id, { arguments: args });
140
- };
141
-
142
- removeMessage: IMessageService['removeMessage'] = async (id) => {
143
- return this.messageModel.deleteMessage(id);
144
- };
145
-
146
- removeMessages: IMessageService['removeMessages'] = async (ids) => {
147
- return this.messageModel.deleteMessages(ids);
148
- };
149
-
150
- removeMessagesByAssistant: IMessageService['removeMessagesByAssistant'] = async (
151
- sessionId,
152
- topicId,
153
- ) => {
154
- return this.messageModel.deleteMessagesBySession(this.toDbSessionId(sessionId), topicId);
155
- };
156
-
157
- removeMessagesByGroup: IMessageService['removeMessagesByGroup'] = async (groupId, topicId) => {
158
- return this.messageModel.deleteMessagesBySession(groupId, topicId);
159
- };
160
-
161
- removeAllMessages: IMessageService['removeAllMessages'] = async () => {
162
- return this.messageModel.deleteAllMessages();
163
- };
164
-
165
- hasMessages: IMessageService['hasMessages'] = async () => {
166
- const number = await this.countMessages();
167
- return number > 0;
168
- };
169
-
170
- messageCountToCheckTrace: IMessageService['messageCountToCheckTrace'] = async () => {
171
- const number = await this.countMessages();
172
- return number >= 4;
173
- };
174
-
175
- private toDbSessionId = (sessionId: string | undefined) => {
176
- return sessionId === INBOX_SESSION_ID ? undefined : sessionId;
177
- };
178
-
179
- private postProcessUrl = async (url: string | null, file: any) => {
180
- const hash = (url as string).replace('client-s3://', '');
181
- const base64 = await this.getBase64ByFileHash(hash);
182
-
183
- return `data:${file.fileType};base64,${base64}`;
184
- };
185
-
186
- private getBase64ByFileHash = async (hash: string) => {
187
- const fileItem = await clientS3Storage.getObject(hash);
188
- if (!fileItem) throw new Error('file not found');
189
-
190
- return Buffer.from(await fileItem.arrayBuffer()).toString('base64');
191
- };
192
- }