@lobehub/lobehub 2.0.0-next.13 → 2.0.0-next.15

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