@lobehub/lobehub 2.0.0-next.13 → 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 (210) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/changelog/v1.json +9 -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/page.tsx +0 -2
  14. package/src/app/[variants]/(main)/profile/_layout/Desktop/index.tsx +23 -24
  15. package/src/app/[variants]/(main)/profile/_layout/Mobile/index.tsx +5 -9
  16. package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +0 -2
  17. package/src/app/[variants]/(main)/settings/_layout/Mobile/index.tsx +0 -2
  18. package/src/app/[variants]/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +1 -1
  19. package/src/app/[variants]/loading/index.tsx +1 -10
  20. package/src/components/Link.tsx +12 -0
  21. package/src/envs/app.ts +5 -8
  22. package/src/features/DataImporter/index.tsx +15 -60
  23. package/src/features/DevPanel/PostgresViewer/usePgTable.ts +3 -2
  24. package/src/hooks/useInterceptingRoutes.test.ts +21 -3
  25. package/src/libs/trpc/client/index.ts +0 -1
  26. package/src/libs/trpc/client/lambda.ts +8 -5
  27. package/src/server/routers/desktop/mcp.ts +1 -3
  28. package/src/server/routers/lambda/config/index.test.ts +2 -2
  29. package/src/server/routers/tools/mcp.ts +2 -3
  30. package/src/server/routers/tools/search.test.ts +1 -7
  31. package/src/server/routers/tools/search.ts +1 -4
  32. package/src/services/__tests__/tool.test.ts +0 -3
  33. package/src/services/aiModel/index.test.ts +0 -3
  34. package/src/services/aiModel/index.ts +1 -7
  35. package/src/services/aiProvider/index.test.ts +0 -3
  36. package/src/services/aiProvider/index.ts +1 -7
  37. package/src/services/chatGroup/index.ts +1 -10
  38. package/src/services/config.ts +1 -65
  39. package/src/services/export/index.ts +1 -4
  40. package/src/services/file/index.ts +1 -11
  41. package/src/services/import/index.ts +1 -7
  42. package/src/services/message/index.ts +1 -11
  43. package/src/services/plugin/index.ts +1 -11
  44. package/src/services/session/index.ts +1 -11
  45. package/src/services/tableViewer/client.ts +12 -15
  46. package/src/services/thread/index.ts +1 -7
  47. package/src/services/topic/index.ts +1 -11
  48. package/src/services/user/index.ts +1 -13
  49. package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts +0 -241
  50. package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +26 -1
  51. package/src/store/chat/slices/aiChat/actions/__tests__/helpers.ts +3 -1
  52. package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +1 -138
  53. package/src/store/user/slices/common/action.test.ts +1 -4
  54. package/src/app/(backend)/trpc/edge/[trpc]/route.ts +0 -26
  55. package/src/app/[variants]/(main)/(mobile)/me/data/features/Category.tsx +0 -48
  56. package/src/app/[variants]/(main)/(mobile)/me/data/features/Header.tsx +0 -33
  57. package/src/app/[variants]/(main)/(mobile)/me/data/layout.tsx +0 -13
  58. package/src/app/[variants]/(main)/(mobile)/me/data/loading.tsx +0 -5
  59. package/src/app/[variants]/(main)/(mobile)/me/data/page.tsx +0 -29
  60. package/src/app/[variants]/(main)/chat/features/Migration/DBReader.ts +0 -290
  61. package/src/app/[variants]/(main)/chat/features/Migration/ExportConfigButton.tsx +0 -35
  62. package/src/app/[variants]/(main)/chat/features/Migration/Failed.tsx +0 -120
  63. package/src/app/[variants]/(main)/chat/features/Migration/Modal.tsx +0 -81
  64. package/src/app/[variants]/(main)/chat/features/Migration/Start.tsx +0 -108
  65. package/src/app/[variants]/(main)/chat/features/Migration/UpgradeButton.tsx +0 -71
  66. package/src/app/[variants]/(main)/chat/features/Migration/const.ts +0 -15
  67. package/src/app/[variants]/(main)/chat/features/Migration/index.tsx +0 -50
  68. package/src/app/[variants]/loading/Client/Content.tsx +0 -48
  69. package/src/app/[variants]/loading/Client/Error.tsx +0 -27
  70. package/src/app/[variants]/loading/Client/Redirect.tsx +0 -47
  71. package/src/app/[variants]/loading/Client/index.tsx +0 -22
  72. package/src/components/InnerLink.tsx +0 -20
  73. package/src/database/_deprecated/core/__tests__/db-upgrade.test.ts +0 -42
  74. package/src/database/_deprecated/core/__tests__/db.test.ts +0 -79
  75. package/src/database/_deprecated/core/__tests__/model.test.ts +0 -55
  76. package/src/database/_deprecated/core/db.ts +0 -246
  77. package/src/database/_deprecated/core/index.ts +0 -2
  78. package/src/database/_deprecated/core/migrations/migrateSettingsToUser/fixtures/input.json +0 -55
  79. package/src/database/_deprecated/core/migrations/migrateSettingsToUser/fixtures/output.json +0 -60
  80. package/src/database/_deprecated/core/migrations/migrateSettingsToUser/index.test.ts +0 -14
  81. package/src/database/_deprecated/core/migrations/migrateSettingsToUser/index.ts +0 -22
  82. package/src/database/_deprecated/core/migrations/migrateSettingsToUser/type.ts +0 -105
  83. package/src/database/_deprecated/core/model.ts +0 -218
  84. package/src/database/_deprecated/core/schemas.ts +0 -88
  85. package/src/database/_deprecated/core/types/db.ts +0 -15
  86. package/src/database/_deprecated/models/__DEBUG.ts +0 -124
  87. package/src/database/_deprecated/models/__tests__/file.test.ts +0 -83
  88. package/src/database/_deprecated/models/__tests__/message.test.ts +0 -426
  89. package/src/database/_deprecated/models/__tests__/plugin.test.ts +0 -81
  90. package/src/database/_deprecated/models/__tests__/session.test.ts +0 -253
  91. package/src/database/_deprecated/models/__tests__/sessionGroup.test.ts +0 -220
  92. package/src/database/_deprecated/models/__tests__/topic.test.ts +0 -523
  93. package/src/database/_deprecated/models/__tests__/user.test.ts +0 -82
  94. package/src/database/_deprecated/models/file.ts +0 -51
  95. package/src/database/_deprecated/models/message.ts +0 -277
  96. package/src/database/_deprecated/models/plugin.ts +0 -62
  97. package/src/database/_deprecated/models/session.ts +0 -271
  98. package/src/database/_deprecated/models/sessionGroup.ts +0 -93
  99. package/src/database/_deprecated/models/topic.ts +0 -250
  100. package/src/database/_deprecated/models/user.ts +0 -69
  101. package/src/database/_deprecated/schemas/files.ts +0 -39
  102. package/src/database/_deprecated/schemas/message.ts +0 -50
  103. package/src/database/_deprecated/schemas/plugin.ts +0 -12
  104. package/src/database/_deprecated/schemas/session.ts +0 -54
  105. package/src/database/_deprecated/schemas/sessionGroup.ts +0 -8
  106. package/src/database/_deprecated/schemas/topic.ts +0 -12
  107. package/src/database/_deprecated/schemas/user.ts +0 -40
  108. package/src/features/DataImporter/_deprecated.ts +0 -43
  109. package/src/features/InitClientDB/EnableModal.tsx +0 -118
  110. package/src/features/InitClientDB/ErrorResult.tsx +0 -143
  111. package/src/features/InitClientDB/InitIndicator.tsx +0 -124
  112. package/src/features/InitClientDB/PGliteIcon.tsx +0 -28
  113. package/src/features/InitClientDB/features/DatabaseRepair/Backup.tsx +0 -75
  114. package/src/features/InitClientDB/features/DatabaseRepair/Diagnosis.tsx +0 -98
  115. package/src/features/InitClientDB/features/DatabaseRepair/Repair.tsx +0 -218
  116. package/src/features/InitClientDB/features/DatabaseRepair/index.tsx +0 -91
  117. package/src/features/InitClientDB/index.tsx +0 -37
  118. package/src/libs/trpc/client/edge.ts +0 -26
  119. package/src/libs/trpc/edge/context.ts +0 -71
  120. package/src/libs/trpc/edge/index.ts +0 -45
  121. package/src/libs/trpc/edge/init.ts +0 -26
  122. package/src/libs/trpc/edge/middleware/jwtPayload.test.ts +0 -75
  123. package/src/libs/trpc/edge/middleware/jwtPayload.ts +0 -14
  124. package/src/migrations/FromV0ToV1.ts +0 -10
  125. package/src/migrations/FromV1ToV2/fixtures/input-v1-session.json +0 -191
  126. package/src/migrations/FromV1ToV2/fixtures/output-v2.json +0 -202
  127. package/src/migrations/FromV1ToV2/index.ts +0 -82
  128. package/src/migrations/FromV1ToV2/migrations.test.ts +0 -224
  129. package/src/migrations/FromV1ToV2/types/v1.ts +0 -78
  130. package/src/migrations/FromV1ToV2/types/v2.ts +0 -52
  131. package/src/migrations/FromV2ToV3/fixtures/input-v2-session.json +0 -72
  132. package/src/migrations/FromV2ToV3/fixtures/output-v3-from-v1.json +0 -203
  133. package/src/migrations/FromV2ToV3/fixtures/output-v3.json +0 -74
  134. package/src/migrations/FromV2ToV3/index.ts +0 -30
  135. package/src/migrations/FromV2ToV3/migrations.test.ts +0 -42
  136. package/src/migrations/FromV2ToV3/types/v3.ts +0 -27
  137. package/src/migrations/FromV3ToV4/fixtures/azure-input-v3.json +0 -79
  138. package/src/migrations/FromV3ToV4/fixtures/azure-output-v4.json +0 -75
  139. package/src/migrations/FromV3ToV4/fixtures/ollama-input-v3.json +0 -85
  140. package/src/migrations/FromV3ToV4/fixtures/ollama-output-v4.json +0 -86
  141. package/src/migrations/FromV3ToV4/fixtures/openai-input-v3.json +0 -77
  142. package/src/migrations/FromV3ToV4/fixtures/openai-output-v4.json +0 -77
  143. package/src/migrations/FromV3ToV4/fixtures/openrouter-input-v3.json +0 -82
  144. package/src/migrations/FromV3ToV4/fixtures/openrouter-output-v4.json +0 -85
  145. package/src/migrations/FromV3ToV4/fixtures/output-v4-from-v1.json +0 -203
  146. package/src/migrations/FromV3ToV4/index.ts +0 -102
  147. package/src/migrations/FromV3ToV4/migrations.test.ts +0 -195
  148. package/src/migrations/FromV3ToV4/types/v3.ts +0 -52
  149. package/src/migrations/FromV3ToV4/types/v4.ts +0 -37
  150. package/src/migrations/FromV4ToV5/fixtures/from-v1-to-v5-output.json +0 -245
  151. package/src/migrations/FromV4ToV5/fixtures/function-input-v4.json +0 -96
  152. package/src/migrations/FromV4ToV5/fixtures/function-output-v5.json +0 -120
  153. package/src/migrations/FromV4ToV5/index.ts +0 -58
  154. package/src/migrations/FromV4ToV5/migrations.test.ts +0 -49
  155. package/src/migrations/FromV4ToV5/types/v4.ts +0 -21
  156. package/src/migrations/FromV4ToV5/types/v5.ts +0 -27
  157. package/src/migrations/FromV5ToV6/fixtures/from-v1-to-v6-output.json +0 -247
  158. package/src/migrations/FromV5ToV6/fixtures/session-input-v5.json +0 -81
  159. package/src/migrations/FromV5ToV6/fixtures/session-output-v6.json +0 -85
  160. package/src/migrations/FromV5ToV6/index.ts +0 -61
  161. package/src/migrations/FromV5ToV6/migrations.test.ts +0 -50
  162. package/src/migrations/FromV5ToV6/types/v5.ts +0 -48
  163. package/src/migrations/FromV5ToV6/types/v6.ts +0 -63
  164. package/src/migrations/FromV6ToV7/fixtures/output-v7-from-v1.json +0 -203
  165. package/src/migrations/FromV6ToV7/fixtures/provider-input-v6.json +0 -103
  166. package/src/migrations/FromV6ToV7/fixtures/provider-output-v7.json +0 -118
  167. package/src/migrations/FromV6ToV7/index.ts +0 -101
  168. package/src/migrations/FromV6ToV7/migrations.test.ts +0 -64
  169. package/src/migrations/FromV6ToV7/types/v6.ts +0 -61
  170. package/src/migrations/FromV6ToV7/types/v7.ts +0 -69
  171. package/src/migrations/VersionController.test.ts +0 -88
  172. package/src/migrations/VersionController.ts +0 -67
  173. package/src/migrations/index.ts +0 -61
  174. package/src/server/routers/edge/appStatus.ts +0 -3
  175. package/src/server/routers/edge/index.ts +0 -14
  176. package/src/server/routers/edge/upload.ts +0 -16
  177. package/src/services/aiModel/client.ts +0 -70
  178. package/src/services/aiProvider/client.ts +0 -58
  179. package/src/services/baseClientService/index.ts +0 -9
  180. package/src/services/chatGroup/client.ts +0 -63
  181. package/src/services/export/_deprecated.ts +0 -155
  182. package/src/services/export/client.ts +0 -15
  183. package/src/services/file/_deprecated.test.ts +0 -119
  184. package/src/services/file/_deprecated.ts +0 -80
  185. package/src/services/file/client.test.ts +0 -199
  186. package/src/services/file/client.ts +0 -85
  187. package/src/services/import/_deprecated.ts +0 -115
  188. package/src/services/import/client.test.ts +0 -1015
  189. package/src/services/import/client.ts +0 -64
  190. package/src/services/message/_deprecated.test.ts +0 -398
  191. package/src/services/message/_deprecated.ts +0 -168
  192. package/src/services/message/client.test.ts +0 -410
  193. package/src/services/message/client.ts +0 -192
  194. package/src/services/plugin/_deprecated.test.ts +0 -162
  195. package/src/services/plugin/_deprecated.ts +0 -42
  196. package/src/services/plugin/client.test.ts +0 -177
  197. package/src/services/plugin/client.ts +0 -46
  198. package/src/services/session/_deprecated.test.ts +0 -440
  199. package/src/services/session/_deprecated.ts +0 -190
  200. package/src/services/session/client.test.ts +0 -413
  201. package/src/services/session/client.ts +0 -193
  202. package/src/services/thread/client.ts +0 -51
  203. package/src/services/topic/_deprecated.test.ts +0 -245
  204. package/src/services/topic/_deprecated.ts +0 -75
  205. package/src/services/topic/client.ts +0 -89
  206. package/src/services/topic/pglite.test.ts +0 -212
  207. package/src/services/user/_deprecated.test.ts +0 -101
  208. package/src/services/user/_deprecated.ts +0 -70
  209. package/src/services/user/client.test.ts +0 -111
  210. 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
- }