@lobehub/lobehub 2.0.0-next.7 → 2.0.0-next.9
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.
- package/.github/workflows/desktop-pr-build.yml +8 -8
- package/.github/workflows/docker.yml +17 -16
- package/.github/workflows/e2e.yml +3 -3
- package/.github/workflows/release-desktop-beta.yml +8 -8
- package/.github/workflows/release.yml +1 -1
- package/.github/workflows/test.yml +4 -4
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/locales/ar/models.json +6 -6
- package/locales/bg-BG/models.json +6 -6
- package/locales/de-DE/models.json +6 -6
- package/locales/en-US/models.json +6 -6
- package/locales/es-ES/models.json +6 -6
- package/locales/fa-IR/models.json +6 -6
- package/locales/fr-FR/models.json +6 -6
- package/locales/it-IT/models.json +6 -6
- package/locales/ja-JP/models.json +6 -6
- package/locales/ko-KR/models.json +6 -6
- package/locales/nl-NL/models.json +6 -6
- package/locales/pl-PL/models.json +6 -6
- package/locales/pt-BR/models.json +6 -6
- package/locales/ru-RU/models.json +6 -6
- package/locales/tr-TR/models.json +6 -6
- package/locales/vi-VN/models.json +6 -6
- package/locales/zh-CN/models.json +6 -6
- package/locales/zh-TW/models.json +6 -6
- package/package.json +1 -1
- package/packages/const/src/index.ts +0 -1
- package/packages/const/src/url.ts +1 -4
- package/packages/context-engine/src/index.ts +1 -6
- package/packages/context-engine/src/processors/GroupMessageFlatten.ts +12 -2
- package/packages/context-engine/src/processors/__tests__/GroupMessageFlatten.test.ts +73 -9
- package/packages/context-engine/src/providers/index.ts +0 -2
- package/packages/database/package.json +1 -1
- package/packages/database/src/models/__tests__/message.grouping.test.ts +812 -0
- package/packages/database/src/models/__tests__/message.test.ts +322 -170
- package/packages/database/src/models/message.ts +62 -24
- package/packages/database/src/utils/__tests__/groupMessages.test.ts +145 -2
- package/packages/database/src/utils/groupMessages.ts +7 -5
- package/packages/types/src/message/common/base.ts +13 -0
- package/packages/types/src/message/common/image.ts +8 -0
- package/packages/types/src/message/common/metadata.ts +39 -0
- package/packages/types/src/message/common/tools.ts +10 -0
- package/packages/types/src/message/db/params.ts +47 -1
- package/packages/types/src/message/ui/chat.ts +4 -1
- package/packages/types/src/search.ts +16 -0
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/V1Mobile/index.tsx +2 -2
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/V1Mobile/useSend.ts +6 -4
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/useSend.ts +15 -10
- package/src/app/[variants]/(main)/chat/@session/features/SessionListContent/List/Item/index.tsx +4 -2
- package/src/components/Thinking/index.tsx +4 -3
- package/src/features/AgentSetting/AgentPlugin/index.tsx +2 -2
- package/src/features/ChatInput/ActionBar/STT/browser.tsx +2 -2
- package/src/features/ChatInput/ActionBar/STT/openai.tsx +2 -2
- package/src/features/ChatInput/ActionBar/Tools/useControls.tsx +1 -3
- package/src/features/Conversation/Error/ErrorJsonViewer.tsx +4 -3
- package/src/features/Conversation/Error/OllamaBizError/index.tsx +7 -2
- package/src/features/Conversation/Error/index.tsx +15 -5
- package/src/features/Conversation/MarkdownElements/LobeArtifact/Render/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Extra/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/MessageContent.tsx +5 -3
- package/src/features/Conversation/Messages/Assistant/Tool/Inspector/BuiltinPluginTitle.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Tool/Inspector/ToolTitle.tsx +4 -2
- package/src/features/Conversation/Messages/Assistant/Tool/Render/CustomRender.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Tool/Render/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/Tool/index.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/index.tsx +4 -4
- package/src/features/Conversation/Messages/Default.tsx +2 -2
- package/src/features/Conversation/Messages/User/Extra.tsx +2 -2
- package/src/features/Conversation/Messages/User/index.tsx +4 -4
- package/src/features/Conversation/Messages/index.tsx +3 -3
- package/src/features/Conversation/components/AutoScroll.tsx +2 -2
- package/src/features/Conversation/components/Extras/Usage/UsageDetail/index.tsx +9 -6
- package/src/features/PluginTag/index.tsx +1 -3
- package/src/features/PluginsUI/Render/BuiltinType/index.test.tsx +37 -28
- package/src/features/Portal/Artifacts/Body/index.tsx +2 -2
- package/src/server/modules/ModelRuntime/trace.ts +11 -4
- package/src/server/routers/lambda/message.ts +14 -3
- package/src/services/chat/chat.test.ts +1 -40
- package/src/services/chat/contextEngineering.test.ts +0 -30
- package/src/services/chat/contextEngineering.ts +1 -12
- package/src/services/chat/index.ts +2 -7
- package/src/services/chat/types.ts +1 -1
- package/src/services/message/_deprecated.ts +1 -1
- package/src/services/message/client.ts +8 -2
- package/src/services/message/server.ts +7 -2
- package/src/services/message/type.ts +6 -1
- package/src/store/chat/helpers.test.ts +99 -0
- package/src/store/chat/helpers.ts +21 -2
- package/src/store/chat/selectors.ts +1 -1
- package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +3 -3
- package/src/store/chat/slices/builtinTool/actions/index.ts +1 -4
- package/src/store/chat/slices/message/action.test.ts +5 -1
- package/src/store/chat/slices/message/action.ts +102 -14
- package/src/store/chat/slices/message/reducer.test.ts +363 -5
- package/src/store/chat/slices/message/reducer.ts +87 -3
- package/src/store/chat/slices/message/{selectors.test.ts → selectors/chat.test.ts} +266 -30
- package/src/store/chat/slices/message/{selectors.ts → selectors/chat.ts} +29 -79
- package/src/store/chat/slices/message/selectors/index.ts +2 -0
- package/src/store/chat/slices/message/selectors/messageState.test.ts +36 -0
- package/src/store/chat/slices/message/selectors/messageState.ts +80 -0
- package/src/store/chat/slices/plugin/action.test.ts +34 -132
- package/src/store/chat/slices/plugin/action.ts +1 -44
- package/src/store/tool/selectors/tool.test.ts +1 -1
- package/src/store/tool/selectors/tool.ts +6 -8
- package/src/store/tool/slices/builtin/action.test.ts +83 -35
- package/src/store/tool/slices/builtin/action.ts +0 -9
- package/src/store/tool/slices/builtin/selectors.test.ts +4 -30
- package/src/store/tool/slices/builtin/selectors.ts +15 -21
- package/src/tools/index.ts +0 -6
- package/src/tools/renders.ts +0 -3
- package/src/tools/web-browsing/Portal/Search/Footer.tsx +2 -2
- package/packages/const/src/guide.ts +0 -89
- package/packages/context-engine/src/providers/InboxGuide.ts +0 -102
- package/packages/context-engine/src/providers/__tests__/InboxGuideProvider.test.ts +0 -121
- package/src/services/chat/__snapshots__/chat.test.ts.snap +0 -110
- package/src/store/chat/slices/builtinTool/actions/__tests__/dalle.test.ts +0 -121
- package/src/store/chat/slices/builtinTool/actions/dalle.ts +0 -124
- package/src/tools/dalle/Render/GalleyGrid.tsx +0 -60
- package/src/tools/dalle/Render/Item/EditMode.tsx +0 -66
- package/src/tools/dalle/Render/Item/Error.tsx +0 -49
- package/src/tools/dalle/Render/Item/Image.tsx +0 -44
- package/src/tools/dalle/Render/Item/ImageFileItem.tsx +0 -57
- package/src/tools/dalle/Render/Item/index.tsx +0 -88
- package/src/tools/dalle/Render/ToolBar.tsx +0 -56
- package/src/tools/dalle/Render/index.tsx +0 -52
- package/src/tools/dalle/index.ts +0 -92
|
@@ -35,7 +35,7 @@ const messageModel = new MessageModel(serverDB, userId);
|
|
|
35
35
|
const embeddingsId = uuid();
|
|
36
36
|
|
|
37
37
|
beforeEach(async () => {
|
|
38
|
-
//
|
|
38
|
+
// Clear tables before each test case
|
|
39
39
|
await serverDB.transaction(async (trx) => {
|
|
40
40
|
await trx.delete(users);
|
|
41
41
|
await trx.insert(users).values([{ id: userId }, { id: '456' }]);
|
|
@@ -63,14 +63,14 @@ beforeEach(async () => {
|
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
afterEach(async () => {
|
|
66
|
-
//
|
|
66
|
+
// Clear tables after each test case
|
|
67
67
|
await serverDB.delete(users);
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
describe('MessageModel', () => {
|
|
71
71
|
describe('query', () => {
|
|
72
72
|
it('should query messages by user ID', async () => {
|
|
73
|
-
//
|
|
73
|
+
// Create test data
|
|
74
74
|
await serverDB.insert(messages).values([
|
|
75
75
|
{ id: '1', userId, role: 'user', content: 'message 1', createdAt: new Date('2023-01-01') },
|
|
76
76
|
{ id: '2', userId, role: 'user', content: 'message 2', createdAt: new Date('2023-02-01') },
|
|
@@ -83,39 +83,39 @@ describe('MessageModel', () => {
|
|
|
83
83
|
},
|
|
84
84
|
]);
|
|
85
85
|
|
|
86
|
-
//
|
|
86
|
+
// Call query method
|
|
87
87
|
const result = await messageModel.query();
|
|
88
88
|
|
|
89
|
-
//
|
|
89
|
+
// Assert result
|
|
90
90
|
expect(result).toHaveLength(2);
|
|
91
91
|
expect(result[0].id).toBe('1');
|
|
92
92
|
expect(result[1].id).toBe('2');
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
it('should return empty messages if not match the user ID', async () => {
|
|
96
|
-
//
|
|
96
|
+
// Create test data
|
|
97
97
|
await serverDB.insert(messages).values([
|
|
98
98
|
{ id: '1', userId: '456', role: 'user', content: '1', createdAt: new Date('2023-01-01') },
|
|
99
99
|
{ id: '2', userId: '456', role: 'user', content: '2', createdAt: new Date('2023-02-01') },
|
|
100
100
|
{ id: '3', userId: '456', role: 'user', content: '3', createdAt: new Date('2023-03-01') },
|
|
101
101
|
]);
|
|
102
102
|
|
|
103
|
-
//
|
|
103
|
+
// Call query method
|
|
104
104
|
const result = await messageModel.query();
|
|
105
105
|
|
|
106
|
-
//
|
|
106
|
+
// Assert result
|
|
107
107
|
expect(result).toHaveLength(0);
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
it('should query messages with pagination', async () => {
|
|
111
|
-
//
|
|
111
|
+
// Create test data
|
|
112
112
|
await serverDB.insert(messages).values([
|
|
113
113
|
{ id: '1', userId, role: 'user', content: 'message 1', createdAt: new Date('2023-01-01') },
|
|
114
114
|
{ id: '2', userId, role: 'user', content: 'message 2', createdAt: new Date('2023-02-01') },
|
|
115
115
|
{ id: '3', userId, role: 'user', content: 'message 3', createdAt: new Date('2023-03-01') },
|
|
116
116
|
]);
|
|
117
117
|
|
|
118
|
-
//
|
|
118
|
+
// Test pagination
|
|
119
119
|
const result1 = await messageModel.query({ current: 0, pageSize: 2 });
|
|
120
120
|
expect(result1).toHaveLength(2);
|
|
121
121
|
|
|
@@ -125,7 +125,7 @@ describe('MessageModel', () => {
|
|
|
125
125
|
});
|
|
126
126
|
|
|
127
127
|
it('should filter messages by sessionId', async () => {
|
|
128
|
-
//
|
|
128
|
+
// Create test data
|
|
129
129
|
await serverDB.insert(sessions).values([
|
|
130
130
|
{ id: 'session1', userId },
|
|
131
131
|
{ id: 'session2', userId },
|
|
@@ -150,7 +150,7 @@ describe('MessageModel', () => {
|
|
|
150
150
|
{ id: '3', userId, role: 'user', sessionId: 'session2', content: 'message 3' },
|
|
151
151
|
]);
|
|
152
152
|
|
|
153
|
-
//
|
|
153
|
+
// Test filtering by sessionId
|
|
154
154
|
const result = await messageModel.query({ sessionId: 'session1' });
|
|
155
155
|
expect(result).toHaveLength(2);
|
|
156
156
|
expect(result[0].id).toBe('1');
|
|
@@ -158,7 +158,7 @@ describe('MessageModel', () => {
|
|
|
158
158
|
});
|
|
159
159
|
|
|
160
160
|
it('should filter messages by topicId', async () => {
|
|
161
|
-
//
|
|
161
|
+
// Create test data
|
|
162
162
|
const sessionId = 'session1';
|
|
163
163
|
await serverDB.insert(sessions).values([{ id: sessionId, userId }]);
|
|
164
164
|
const topicId = 'topic1';
|
|
@@ -173,7 +173,7 @@ describe('MessageModel', () => {
|
|
|
173
173
|
{ id: '3', userId, role: 'user', topicId: 'topic2', content: 'message 3' },
|
|
174
174
|
]);
|
|
175
175
|
|
|
176
|
-
//
|
|
176
|
+
// Test filtering by topicId
|
|
177
177
|
const result = await messageModel.query({ topicId });
|
|
178
178
|
expect(result).toHaveLength(2);
|
|
179
179
|
expect(result[0].id).toBe('1');
|
|
@@ -226,7 +226,7 @@ describe('MessageModel', () => {
|
|
|
226
226
|
});
|
|
227
227
|
|
|
228
228
|
it('should query messages with join', async () => {
|
|
229
|
-
//
|
|
229
|
+
// Create test data
|
|
230
230
|
await serverDB.transaction(async (trx) => {
|
|
231
231
|
await trx.insert(messages).values([
|
|
232
232
|
{
|
|
@@ -268,13 +268,13 @@ describe('MessageModel', () => {
|
|
|
268
268
|
});
|
|
269
269
|
|
|
270
270
|
const domain = 'http://abc.com';
|
|
271
|
-
//
|
|
271
|
+
// Call query method
|
|
272
272
|
const result = await messageModel.query(
|
|
273
273
|
{},
|
|
274
274
|
{ postProcessUrl: async (path) => `${domain}/${path}` },
|
|
275
275
|
);
|
|
276
276
|
|
|
277
|
-
//
|
|
277
|
+
// Assert result
|
|
278
278
|
expect(result).toHaveLength(2);
|
|
279
279
|
expect(result[0].id).toBe('1');
|
|
280
280
|
expect(result[0].imageList).toEqual([
|
|
@@ -287,7 +287,7 @@ describe('MessageModel', () => {
|
|
|
287
287
|
});
|
|
288
288
|
|
|
289
289
|
it('should include translate, tts and other extra fields in query result', async () => {
|
|
290
|
-
//
|
|
290
|
+
// Create test data
|
|
291
291
|
await serverDB.transaction(async (trx) => {
|
|
292
292
|
await trx.insert(messages).values([
|
|
293
293
|
{
|
|
@@ -306,10 +306,10 @@ describe('MessageModel', () => {
|
|
|
306
306
|
.values([{ id: '1', voice: 'voice1', fileId: 'f1', contentMd5: 'md5', userId }]);
|
|
307
307
|
});
|
|
308
308
|
|
|
309
|
-
//
|
|
309
|
+
// Call query method
|
|
310
310
|
const result = await messageModel.query();
|
|
311
311
|
|
|
312
|
-
//
|
|
312
|
+
// Assert result
|
|
313
313
|
expect(result[0].extra!.translate).toEqual({ content: 'translated', from: 'en', to: 'zh' });
|
|
314
314
|
expect(result[0].extra!.tts).toEqual({
|
|
315
315
|
contentMd5: 'md5',
|
|
@@ -319,7 +319,7 @@ describe('MessageModel', () => {
|
|
|
319
319
|
});
|
|
320
320
|
|
|
321
321
|
it('should handle edge cases of pagination parameters', async () => {
|
|
322
|
-
//
|
|
322
|
+
// Create test data
|
|
323
323
|
await serverDB.insert(messages).values([
|
|
324
324
|
{ id: '1', userId, role: 'user', content: 'message 1' },
|
|
325
325
|
{ id: '2', userId, role: 'user', content: 'message 2' },
|
|
@@ -339,7 +339,7 @@ describe('MessageModel', () => {
|
|
|
339
339
|
|
|
340
340
|
describe('query with messageQueries', () => {
|
|
341
341
|
it('should include ragQuery, ragQueryId and ragRawQuery in query results', async () => {
|
|
342
|
-
//
|
|
342
|
+
// Create test data
|
|
343
343
|
const messageId = 'msg-with-query';
|
|
344
344
|
const queryId = uuid();
|
|
345
345
|
|
|
@@ -358,10 +358,10 @@ describe('MessageModel', () => {
|
|
|
358
358
|
userId,
|
|
359
359
|
});
|
|
360
360
|
|
|
361
|
-
//
|
|
361
|
+
// Call query method
|
|
362
362
|
const result = await messageModel.query();
|
|
363
363
|
|
|
364
|
-
//
|
|
364
|
+
// Assert result
|
|
365
365
|
expect(result).toHaveLength(1);
|
|
366
366
|
expect(result[0].id).toBe(messageId);
|
|
367
367
|
expect(result[0].ragQueryId).toBe(queryId);
|
|
@@ -370,7 +370,7 @@ describe('MessageModel', () => {
|
|
|
370
370
|
});
|
|
371
371
|
|
|
372
372
|
it.skip('should handle multiple message queries for the same message', async () => {
|
|
373
|
-
//
|
|
373
|
+
// Create test data
|
|
374
374
|
const messageId = 'msg-multi-query';
|
|
375
375
|
const queryId1 = uuid();
|
|
376
376
|
const queryId2 = uuid();
|
|
@@ -400,10 +400,10 @@ describe('MessageModel', () => {
|
|
|
400
400
|
},
|
|
401
401
|
]);
|
|
402
402
|
|
|
403
|
-
//
|
|
403
|
+
// Call query method
|
|
404
404
|
const result = await messageModel.query();
|
|
405
405
|
|
|
406
|
-
//
|
|
406
|
+
// Assert result - 应该只包含最新的查询
|
|
407
407
|
expect(result).toHaveLength(1);
|
|
408
408
|
expect(result[0].id).toBe(messageId);
|
|
409
409
|
expect(result[0].ragQueryId).toBe(queryId2);
|
|
@@ -505,7 +505,7 @@ describe('MessageModel', () => {
|
|
|
505
505
|
|
|
506
506
|
describe('queryAll', () => {
|
|
507
507
|
it('should return all messages belonging to the user in ascending order', async () => {
|
|
508
|
-
//
|
|
508
|
+
// Create test data
|
|
509
509
|
await serverDB.insert(messages).values([
|
|
510
510
|
{
|
|
511
511
|
id: '1',
|
|
@@ -530,10 +530,10 @@ describe('MessageModel', () => {
|
|
|
530
530
|
},
|
|
531
531
|
]);
|
|
532
532
|
|
|
533
|
-
//
|
|
533
|
+
// Call queryAll method
|
|
534
534
|
const result = await messageModel.queryAll();
|
|
535
535
|
|
|
536
|
-
//
|
|
536
|
+
// Assert result
|
|
537
537
|
expect(result).toHaveLength(2);
|
|
538
538
|
expect(result[0].id).toBe('1');
|
|
539
539
|
expect(result[1].id).toBe('2');
|
|
@@ -542,37 +542,37 @@ describe('MessageModel', () => {
|
|
|
542
542
|
|
|
543
543
|
describe('findById', () => {
|
|
544
544
|
it('should find message by ID', async () => {
|
|
545
|
-
//
|
|
545
|
+
// Create test data
|
|
546
546
|
await serverDB.insert(messages).values([
|
|
547
547
|
{ id: '1', userId, role: 'user', content: 'message 1' },
|
|
548
548
|
{ id: '2', userId: '456', role: 'user', content: 'message 2' },
|
|
549
549
|
]);
|
|
550
550
|
|
|
551
|
-
//
|
|
551
|
+
// Call findById method
|
|
552
552
|
const result = await messageModel.findById('1');
|
|
553
553
|
|
|
554
|
-
//
|
|
554
|
+
// Assert result
|
|
555
555
|
expect(result?.id).toBe('1');
|
|
556
556
|
expect(result?.content).toBe('message 1');
|
|
557
557
|
});
|
|
558
558
|
|
|
559
559
|
it('should return undefined if message does not belong to user', async () => {
|
|
560
|
-
//
|
|
560
|
+
// Create test data
|
|
561
561
|
await serverDB
|
|
562
562
|
.insert(messages)
|
|
563
563
|
.values([{ id: '1', userId: '456', role: 'user', content: 'message 1' }]);
|
|
564
564
|
|
|
565
|
-
//
|
|
565
|
+
// Call findById method
|
|
566
566
|
const result = await messageModel.findById('1');
|
|
567
567
|
|
|
568
|
-
//
|
|
568
|
+
// Assert result
|
|
569
569
|
expect(result).toBeUndefined();
|
|
570
570
|
});
|
|
571
571
|
});
|
|
572
572
|
|
|
573
573
|
describe('queryBySessionId', () => {
|
|
574
574
|
it('should query messages by sessionId', async () => {
|
|
575
|
-
//
|
|
575
|
+
// Create test data
|
|
576
576
|
const sessionId = 'session1';
|
|
577
577
|
await serverDB.insert(sessions).values([
|
|
578
578
|
{ id: 'session1', userId },
|
|
@@ -598,10 +598,10 @@ describe('MessageModel', () => {
|
|
|
598
598
|
{ id: '3', userId, role: 'user', sessionId: 'session2', content: 'message 3' },
|
|
599
599
|
]);
|
|
600
600
|
|
|
601
|
-
//
|
|
601
|
+
// Call queryBySessionId method
|
|
602
602
|
const result = await messageModel.queryBySessionId(sessionId);
|
|
603
603
|
|
|
604
|
-
//
|
|
604
|
+
// Assert result
|
|
605
605
|
expect(result).toHaveLength(2);
|
|
606
606
|
expect(result[0].id).toBe('1');
|
|
607
607
|
expect(result[1].id).toBe('2');
|
|
@@ -610,7 +610,7 @@ describe('MessageModel', () => {
|
|
|
610
610
|
|
|
611
611
|
describe('queryByKeyWord', () => {
|
|
612
612
|
it('should query messages by keyword', async () => {
|
|
613
|
-
//
|
|
613
|
+
// Create test data
|
|
614
614
|
await serverDB.insert(messages).values([
|
|
615
615
|
{ id: '1', userId, role: 'user', content: 'apple', createdAt: new Date('2022-02-01') },
|
|
616
616
|
{ id: '2', userId, role: 'user', content: 'banana' },
|
|
@@ -618,17 +618,17 @@ describe('MessageModel', () => {
|
|
|
618
618
|
{ id: '4', userId, role: 'user', content: 'apple pie', createdAt: new Date('2024-02-01') },
|
|
619
619
|
]);
|
|
620
620
|
|
|
621
|
-
//
|
|
621
|
+
// Test querying messages with specific keyword
|
|
622
622
|
const result = await messageModel.queryByKeyword('apple');
|
|
623
623
|
|
|
624
|
-
//
|
|
624
|
+
// Assert result
|
|
625
625
|
expect(result).toHaveLength(2);
|
|
626
626
|
expect(result[0].id).toBe('4');
|
|
627
627
|
expect(result[1].id).toBe('1');
|
|
628
628
|
});
|
|
629
629
|
|
|
630
630
|
it('should return empty array when keyword is empty', async () => {
|
|
631
|
-
//
|
|
631
|
+
// Create test data
|
|
632
632
|
await serverDB.insert(messages).values([
|
|
633
633
|
{ id: '1', userId, role: 'user', content: 'apple' },
|
|
634
634
|
{ id: '2', userId, role: 'user', content: 'banana' },
|
|
@@ -636,20 +636,20 @@ describe('MessageModel', () => {
|
|
|
636
636
|
{ id: '4', userId, role: 'user', content: 'apple pie' },
|
|
637
637
|
]);
|
|
638
638
|
|
|
639
|
-
//
|
|
639
|
+
// Test returning empty array when keyword is empty
|
|
640
640
|
const result = await messageModel.queryByKeyword('');
|
|
641
641
|
|
|
642
|
-
//
|
|
642
|
+
// Assert result
|
|
643
643
|
expect(result).toHaveLength(0);
|
|
644
644
|
});
|
|
645
645
|
});
|
|
646
646
|
|
|
647
647
|
describe('createMessage', () => {
|
|
648
648
|
it('should create a new message', async () => {
|
|
649
|
-
//
|
|
649
|
+
// Call createMessage method
|
|
650
650
|
await messageModel.create({ role: 'user', content: 'new message', sessionId: '1' });
|
|
651
651
|
|
|
652
|
-
//
|
|
652
|
+
// Assert result
|
|
653
653
|
const result = await serverDB.select().from(messages).where(eq(messages.userId, userId));
|
|
654
654
|
expect(result).toHaveLength(1);
|
|
655
655
|
expect(result[0].content).toBe('new message');
|
|
@@ -673,21 +673,21 @@ describe('MessageModel', () => {
|
|
|
673
673
|
});
|
|
674
674
|
|
|
675
675
|
it('should generate message ID automatically', async () => {
|
|
676
|
-
//
|
|
676
|
+
// Call createMessage method
|
|
677
677
|
await messageModel.create({
|
|
678
678
|
role: 'user',
|
|
679
679
|
content: 'new message',
|
|
680
680
|
sessionId: '1',
|
|
681
681
|
});
|
|
682
682
|
|
|
683
|
-
//
|
|
683
|
+
// Assert result
|
|
684
684
|
const result = await serverDB.select().from(messages).where(eq(messages.userId, userId));
|
|
685
685
|
expect(result[0].id).toBeDefined();
|
|
686
686
|
expect(result[0].id).toHaveLength(18);
|
|
687
687
|
});
|
|
688
688
|
|
|
689
689
|
it('should create a tool message and insert into messagePlugins table', async () => {
|
|
690
|
-
//
|
|
690
|
+
// Call create method
|
|
691
691
|
const result = await messageModel.create({
|
|
692
692
|
content: 'message 1',
|
|
693
693
|
role: 'tool',
|
|
@@ -701,7 +701,7 @@ describe('MessageModel', () => {
|
|
|
701
701
|
},
|
|
702
702
|
});
|
|
703
703
|
|
|
704
|
-
//
|
|
704
|
+
// Assert result
|
|
705
705
|
expect(result.id).toBeDefined();
|
|
706
706
|
expect(result.content).toBe('message 1');
|
|
707
707
|
expect(result.role).toBe('tool');
|
|
@@ -716,7 +716,7 @@ describe('MessageModel', () => {
|
|
|
716
716
|
});
|
|
717
717
|
|
|
718
718
|
it('should create tool message ', async () => {
|
|
719
|
-
//
|
|
719
|
+
// Call create method
|
|
720
720
|
const state = {
|
|
721
721
|
query: 'Composio',
|
|
722
722
|
answers: [],
|
|
@@ -768,7 +768,7 @@ describe('MessageModel', () => {
|
|
|
768
768
|
sessionId: '1',
|
|
769
769
|
});
|
|
770
770
|
|
|
771
|
-
//
|
|
771
|
+
// Assert result
|
|
772
772
|
expect(result.id).toBeDefined();
|
|
773
773
|
expect(result.content).toBe('[{}]');
|
|
774
774
|
expect(result.role).toBe('tool');
|
|
@@ -798,14 +798,14 @@ describe('MessageModel', () => {
|
|
|
798
798
|
|
|
799
799
|
expect(result.id).toBe(customId);
|
|
800
800
|
|
|
801
|
-
//
|
|
801
|
+
// Verify database records
|
|
802
802
|
const dbResult = await serverDB.select().from(messages).where(eq(messages.id, customId));
|
|
803
803
|
expect(dbResult).toHaveLength(1);
|
|
804
804
|
expect(dbResult[0].id).toBe(customId);
|
|
805
805
|
});
|
|
806
806
|
|
|
807
807
|
it.skip('should create a message with file chunks and RAG query ID', async () => {
|
|
808
|
-
//
|
|
808
|
+
// Create test data
|
|
809
809
|
const chunkId1 = uuid();
|
|
810
810
|
const chunkId2 = uuid();
|
|
811
811
|
const ragQueryId = uuid();
|
|
@@ -815,7 +815,7 @@ describe('MessageModel', () => {
|
|
|
815
815
|
{ id: chunkId2, text: 'chunk text 2' },
|
|
816
816
|
]);
|
|
817
817
|
|
|
818
|
-
//
|
|
818
|
+
// Call create method
|
|
819
819
|
const result = await messageModel.create({
|
|
820
820
|
role: 'assistant',
|
|
821
821
|
content: 'message with file chunks',
|
|
@@ -827,10 +827,10 @@ describe('MessageModel', () => {
|
|
|
827
827
|
sessionId: '1',
|
|
828
828
|
});
|
|
829
829
|
|
|
830
|
-
//
|
|
830
|
+
// Verify message created successfully
|
|
831
831
|
expect(result.id).toBeDefined();
|
|
832
832
|
|
|
833
|
-
//
|
|
833
|
+
// Verify message query chunk associations created successfully
|
|
834
834
|
const queryChunks = await serverDB
|
|
835
835
|
.select()
|
|
836
836
|
.from(messageQueryChunks)
|
|
@@ -845,7 +845,7 @@ describe('MessageModel', () => {
|
|
|
845
845
|
});
|
|
846
846
|
|
|
847
847
|
it('should create a message with files', async () => {
|
|
848
|
-
//
|
|
848
|
+
// Create test data
|
|
849
849
|
await serverDB.insert(files).values([
|
|
850
850
|
{
|
|
851
851
|
id: 'file1',
|
|
@@ -865,7 +865,7 @@ describe('MessageModel', () => {
|
|
|
865
865
|
},
|
|
866
866
|
]);
|
|
867
867
|
|
|
868
|
-
//
|
|
868
|
+
// Call create method
|
|
869
869
|
const result = await messageModel.create({
|
|
870
870
|
role: 'user',
|
|
871
871
|
content: 'message with files',
|
|
@@ -873,10 +873,10 @@ describe('MessageModel', () => {
|
|
|
873
873
|
sessionId: '1',
|
|
874
874
|
});
|
|
875
875
|
|
|
876
|
-
//
|
|
876
|
+
// Verify message created successfully
|
|
877
877
|
expect(result.id).toBeDefined();
|
|
878
878
|
|
|
879
|
-
//
|
|
879
|
+
// Verify message file associations created successfully
|
|
880
880
|
const messageFiles = await serverDB
|
|
881
881
|
.select()
|
|
882
882
|
.from(messagesFiles)
|
|
@@ -899,10 +899,10 @@ describe('MessageModel', () => {
|
|
|
899
899
|
sessionId: '1',
|
|
900
900
|
});
|
|
901
901
|
|
|
902
|
-
//
|
|
902
|
+
// Verify database records
|
|
903
903
|
const dbResult = await serverDB.select().from(messages).where(eq(messages.id, result.id));
|
|
904
904
|
|
|
905
|
-
//
|
|
905
|
+
// Date comparison needs to consider timezone and formatting, so use toISOString for comparison
|
|
906
906
|
expect(new Date(dbResult[0].createdAt!).toISOString()).toBe(
|
|
907
907
|
new Date(customCreatedAt).toISOString(),
|
|
908
908
|
);
|
|
@@ -915,16 +915,16 @@ describe('MessageModel', () => {
|
|
|
915
915
|
|
|
916
916
|
describe('batchCreateMessages', () => {
|
|
917
917
|
it('should batch create messages', async () => {
|
|
918
|
-
//
|
|
918
|
+
// Prepare test data
|
|
919
919
|
const newMessages = [
|
|
920
920
|
{ id: '1', role: 'user', content: 'message 1' },
|
|
921
921
|
{ id: '2', role: 'assistant', content: 'message 2' },
|
|
922
922
|
] as DBMessageItem[];
|
|
923
923
|
|
|
924
|
-
//
|
|
924
|
+
// Call batchCreateMessages method
|
|
925
925
|
await messageModel.batchCreate(newMessages);
|
|
926
926
|
|
|
927
|
-
//
|
|
927
|
+
// Assert result
|
|
928
928
|
const result = await serverDB.select().from(messages).where(eq(messages.userId, userId));
|
|
929
929
|
expect(result).toHaveLength(2);
|
|
930
930
|
expect(result[0].content).toBe('message 1');
|
|
@@ -934,14 +934,14 @@ describe('MessageModel', () => {
|
|
|
934
934
|
|
|
935
935
|
describe('createNewMessage', () => {
|
|
936
936
|
it('should create message and return id with messages list', async () => {
|
|
937
|
-
//
|
|
937
|
+
// Call createNewMessage method
|
|
938
938
|
const result = await messageModel.createNewMessage({
|
|
939
939
|
role: 'user',
|
|
940
940
|
content: 'test message',
|
|
941
941
|
sessionId: '1',
|
|
942
942
|
});
|
|
943
943
|
|
|
944
|
-
//
|
|
944
|
+
// Assert return structure
|
|
945
945
|
expect(result).toHaveProperty('id');
|
|
946
946
|
expect(result).toHaveProperty('messages');
|
|
947
947
|
expect(result.id).toBeDefined();
|
|
@@ -957,7 +957,7 @@ describe('MessageModel', () => {
|
|
|
957
957
|
sessionId: '1',
|
|
958
958
|
});
|
|
959
959
|
|
|
960
|
-
//
|
|
960
|
+
// Verify newly created message is in the list
|
|
961
961
|
const createdMessage = result.messages.find((m) => m.id === result.id);
|
|
962
962
|
expect(createdMessage).toBeDefined();
|
|
963
963
|
expect(createdMessage?.content).toBe(content);
|
|
@@ -965,30 +965,87 @@ describe('MessageModel', () => {
|
|
|
965
965
|
});
|
|
966
966
|
|
|
967
967
|
it('should return all messages for the session', async () => {
|
|
968
|
-
//
|
|
968
|
+
// Create multiple messages
|
|
969
969
|
await messageModel.create({ role: 'user', content: 'message 1', sessionId: '1' });
|
|
970
970
|
await messageModel.create({ role: 'assistant', content: 'message 2', sessionId: '1' });
|
|
971
971
|
|
|
972
|
-
//
|
|
972
|
+
// Create third message and get complete list
|
|
973
973
|
const result = await messageModel.createNewMessage({
|
|
974
974
|
role: 'user',
|
|
975
975
|
content: 'message 3',
|
|
976
976
|
sessionId: '1',
|
|
977
977
|
});
|
|
978
978
|
|
|
979
|
-
//
|
|
979
|
+
// Verify all messages are returned
|
|
980
980
|
expect(result.messages.length).toBeGreaterThanOrEqual(3);
|
|
981
981
|
});
|
|
982
982
|
|
|
983
|
+
it('should apply groupAssistantMessages transformation', async () => {
|
|
984
|
+
// Create an assistant message with tools
|
|
985
|
+
const assistantMsg = await messageModel.create({
|
|
986
|
+
role: 'assistant',
|
|
987
|
+
content: 'Checking weather',
|
|
988
|
+
tools: [
|
|
989
|
+
{
|
|
990
|
+
id: 'tool-1',
|
|
991
|
+
identifier: 'weather',
|
|
992
|
+
apiName: 'getWeather',
|
|
993
|
+
arguments: '{"city":"Beijing"}',
|
|
994
|
+
type: 'default',
|
|
995
|
+
},
|
|
996
|
+
],
|
|
997
|
+
sessionId: '1',
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
// Create corresponding tool message
|
|
1001
|
+
const toolMsg = await messageModel.create({
|
|
1002
|
+
role: 'tool',
|
|
1003
|
+
content: 'Beijing: Sunny, 25°C',
|
|
1004
|
+
tool_call_id: 'tool-1',
|
|
1005
|
+
sessionId: '1',
|
|
1006
|
+
plugin: {
|
|
1007
|
+
identifier: 'weather',
|
|
1008
|
+
apiName: 'getWeather',
|
|
1009
|
+
arguments: '{"city":"Beijing"}',
|
|
1010
|
+
type: 'default',
|
|
1011
|
+
},
|
|
1012
|
+
});
|
|
1013
|
+
|
|
1014
|
+
// Create new message and get list
|
|
1015
|
+
const result = await messageModel.createNewMessage({
|
|
1016
|
+
role: 'user',
|
|
1017
|
+
content: 'Thanks!',
|
|
1018
|
+
sessionId: '1',
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
// Verify assistant message is grouped
|
|
1022
|
+
const groupMessage = result.messages.find((m) => m.id === assistantMsg.id);
|
|
1023
|
+
expect(groupMessage?.role).toBe('group');
|
|
1024
|
+
expect(groupMessage?.children).toBeDefined();
|
|
1025
|
+
expect(groupMessage?.children).toHaveLength(1);
|
|
1026
|
+
|
|
1027
|
+
// Verify tool results are merged into children
|
|
1028
|
+
const childBlock = groupMessage?.children?.[0];
|
|
1029
|
+
expect(childBlock?.tools).toBeDefined();
|
|
1030
|
+
expect(childBlock?.tools).toHaveLength(1);
|
|
1031
|
+
|
|
1032
|
+
// Verify tool contains execution result
|
|
1033
|
+
const tool = childBlock?.tools?.[0];
|
|
1034
|
+
expect(tool?.id).toBe('tool-1');
|
|
1035
|
+
expect(tool?.identifier).toBe('weather');
|
|
1036
|
+
expect(tool?.result).toBeDefined();
|
|
1037
|
+
expect(tool?.result?.content).toBe('Beijing: Sunny, 25°C');
|
|
1038
|
+
});
|
|
1039
|
+
|
|
983
1040
|
it('should filter messages by topicId if provided', async () => {
|
|
984
1041
|
const topicId = 'topic-1';
|
|
985
1042
|
await serverDB.insert(topics).values({ id: topicId, sessionId: '1', userId });
|
|
986
1043
|
|
|
987
|
-
//
|
|
1044
|
+
// Create messages with different topics
|
|
988
1045
|
await messageModel.create({ role: 'user', content: 'topic 1 msg', sessionId: '1', topicId });
|
|
989
1046
|
await messageModel.create({ role: 'user', content: 'no topic msg', sessionId: '1' });
|
|
990
1047
|
|
|
991
|
-
//
|
|
1048
|
+
// Create new message and specify topicId
|
|
992
1049
|
const result = await messageModel.createNewMessage({
|
|
993
1050
|
role: 'user',
|
|
994
1051
|
content: 'new topic msg',
|
|
@@ -996,7 +1053,7 @@ describe('MessageModel', () => {
|
|
|
996
1053
|
topicId,
|
|
997
1054
|
});
|
|
998
1055
|
|
|
999
|
-
//
|
|
1056
|
+
// Verify only messages from that topic are returned
|
|
1000
1057
|
expect(result.messages.every((m) => m.topicId === topicId || m.topicId === undefined)).toBe(
|
|
1001
1058
|
true,
|
|
1002
1059
|
);
|
|
@@ -1006,35 +1063,35 @@ describe('MessageModel', () => {
|
|
|
1006
1063
|
|
|
1007
1064
|
describe('updateMessage', () => {
|
|
1008
1065
|
it('should update message content', async () => {
|
|
1009
|
-
//
|
|
1066
|
+
// Create test data
|
|
1010
1067
|
await serverDB
|
|
1011
1068
|
.insert(messages)
|
|
1012
1069
|
.values([{ id: '1', userId, role: 'user', content: 'message 1' }]);
|
|
1013
1070
|
|
|
1014
|
-
//
|
|
1071
|
+
// Call updateMessage method
|
|
1015
1072
|
await messageModel.update('1', { content: 'updated message' });
|
|
1016
1073
|
|
|
1017
|
-
//
|
|
1074
|
+
// Assert result
|
|
1018
1075
|
const result = await serverDB.select().from(messages).where(eq(messages.id, '1'));
|
|
1019
1076
|
expect(result[0].content).toBe('updated message');
|
|
1020
1077
|
});
|
|
1021
1078
|
|
|
1022
1079
|
it('should only update messages belonging to the user', async () => {
|
|
1023
|
-
//
|
|
1080
|
+
// Create test data
|
|
1024
1081
|
await serverDB
|
|
1025
1082
|
.insert(messages)
|
|
1026
1083
|
.values([{ id: '1', userId: '456', role: 'user', content: 'message 1' }]);
|
|
1027
1084
|
|
|
1028
|
-
//
|
|
1085
|
+
// Call updateMessage method
|
|
1029
1086
|
await messageModel.update('1', { content: 'updated message' });
|
|
1030
1087
|
|
|
1031
|
-
//
|
|
1088
|
+
// Assert result
|
|
1032
1089
|
const result = await serverDB.select().from(messages).where(eq(messages.id, '1'));
|
|
1033
1090
|
expect(result[0].content).toBe('message 1');
|
|
1034
1091
|
});
|
|
1035
1092
|
|
|
1036
1093
|
it('should update message tools', async () => {
|
|
1037
|
-
//
|
|
1094
|
+
// Create test data
|
|
1038
1095
|
await serverDB.insert(messages).values([
|
|
1039
1096
|
{
|
|
1040
1097
|
id: '1',
|
|
@@ -1054,7 +1111,7 @@ describe('MessageModel', () => {
|
|
|
1054
1111
|
},
|
|
1055
1112
|
]);
|
|
1056
1113
|
|
|
1057
|
-
//
|
|
1114
|
+
// Call updateMessage method
|
|
1058
1115
|
await messageModel.update('1', {
|
|
1059
1116
|
tools: [
|
|
1060
1117
|
{
|
|
@@ -1067,7 +1124,7 @@ describe('MessageModel', () => {
|
|
|
1067
1124
|
],
|
|
1068
1125
|
});
|
|
1069
1126
|
|
|
1070
|
-
//
|
|
1127
|
+
// Assert result
|
|
1071
1128
|
const result = await serverDB.select().from(messages).where(eq(messages.id, '1'));
|
|
1072
1129
|
expect((result[0].tools as any)[0].arguments).toBe(
|
|
1073
1130
|
'{"query":"2024 杭州暴雨","searchEngines":["duckduckgo","google","brave"]}',
|
|
@@ -1076,7 +1133,7 @@ describe('MessageModel', () => {
|
|
|
1076
1133
|
|
|
1077
1134
|
describe('update with imageList', () => {
|
|
1078
1135
|
it('should update a message and add image files', async () => {
|
|
1079
|
-
//
|
|
1136
|
+
// Create test data
|
|
1080
1137
|
await serverDB.insert(messages).values({
|
|
1081
1138
|
id: 'msg-to-update',
|
|
1082
1139
|
userId,
|
|
@@ -1096,7 +1153,7 @@ describe('MessageModel', () => {
|
|
|
1096
1153
|
{ id: 'img2', name: 'image2.png', fileType: 'image/png', size: 200, url: 'url2', userId },
|
|
1097
1154
|
]);
|
|
1098
1155
|
|
|
1099
|
-
//
|
|
1156
|
+
// Call update method
|
|
1100
1157
|
await messageModel.update('msg-to-update', {
|
|
1101
1158
|
content: 'updated content',
|
|
1102
1159
|
imageList: [
|
|
@@ -1105,7 +1162,7 @@ describe('MessageModel', () => {
|
|
|
1105
1162
|
],
|
|
1106
1163
|
});
|
|
1107
1164
|
|
|
1108
|
-
//
|
|
1165
|
+
// Verify message updated successfully
|
|
1109
1166
|
const updatedMessage = await serverDB
|
|
1110
1167
|
.select()
|
|
1111
1168
|
.from(messages)
|
|
@@ -1113,7 +1170,7 @@ describe('MessageModel', () => {
|
|
|
1113
1170
|
|
|
1114
1171
|
expect(updatedMessage[0].content).toBe('updated content');
|
|
1115
1172
|
|
|
1116
|
-
//
|
|
1173
|
+
// Verify message file associations created successfully
|
|
1117
1174
|
const messageFiles = await serverDB
|
|
1118
1175
|
.select()
|
|
1119
1176
|
.from(messagesFiles)
|
|
@@ -1125,7 +1182,7 @@ describe('MessageModel', () => {
|
|
|
1125
1182
|
});
|
|
1126
1183
|
|
|
1127
1184
|
it('should handle empty imageList', async () => {
|
|
1128
|
-
//
|
|
1185
|
+
// Create test data
|
|
1129
1186
|
await serverDB.insert(messages).values({
|
|
1130
1187
|
id: 'msg-no-images',
|
|
1131
1188
|
userId,
|
|
@@ -1133,12 +1190,12 @@ describe('MessageModel', () => {
|
|
|
1133
1190
|
content: 'original content',
|
|
1134
1191
|
});
|
|
1135
1192
|
|
|
1136
|
-
//
|
|
1193
|
+
// Call update method without providing imageList
|
|
1137
1194
|
await messageModel.update('msg-no-images', {
|
|
1138
1195
|
content: 'updated content',
|
|
1139
1196
|
});
|
|
1140
1197
|
|
|
1141
|
-
//
|
|
1198
|
+
// Verify message updated successfully
|
|
1142
1199
|
const updatedMessage = await serverDB
|
|
1143
1200
|
.select()
|
|
1144
1201
|
.from(messages)
|
|
@@ -1146,7 +1203,7 @@ describe('MessageModel', () => {
|
|
|
1146
1203
|
|
|
1147
1204
|
expect(updatedMessage[0].content).toBe('updated content');
|
|
1148
1205
|
|
|
1149
|
-
//
|
|
1206
|
+
// Verify no message file associations created
|
|
1150
1207
|
const messageFiles = await serverDB
|
|
1151
1208
|
.select()
|
|
1152
1209
|
.from(messagesFiles)
|
|
@@ -1156,7 +1213,7 @@ describe('MessageModel', () => {
|
|
|
1156
1213
|
});
|
|
1157
1214
|
|
|
1158
1215
|
it('should update multiple fields at once', async () => {
|
|
1159
|
-
//
|
|
1216
|
+
// Create test data
|
|
1160
1217
|
await serverDB.insert(messages).values({
|
|
1161
1218
|
id: 'msg-multi-update',
|
|
1162
1219
|
userId,
|
|
@@ -1165,7 +1222,7 @@ describe('MessageModel', () => {
|
|
|
1165
1222
|
model: 'gpt-3.5',
|
|
1166
1223
|
});
|
|
1167
1224
|
|
|
1168
|
-
//
|
|
1225
|
+
// Call update method to update multiple fields
|
|
1169
1226
|
await messageModel.update('msg-multi-update', {
|
|
1170
1227
|
content: 'updated content',
|
|
1171
1228
|
role: 'assistant',
|
|
@@ -1173,7 +1230,7 @@ describe('MessageModel', () => {
|
|
|
1173
1230
|
metadata: { tps: 1 },
|
|
1174
1231
|
});
|
|
1175
1232
|
|
|
1176
|
-
//
|
|
1233
|
+
// Verify message updated successfully
|
|
1177
1234
|
const updatedMessage = await serverDB
|
|
1178
1235
|
.select()
|
|
1179
1236
|
.from(messages)
|
|
@@ -1185,11 +1242,106 @@ describe('MessageModel', () => {
|
|
|
1185
1242
|
expect(updatedMessage[0].metadata).toEqual({ tps: 1 });
|
|
1186
1243
|
});
|
|
1187
1244
|
});
|
|
1245
|
+
|
|
1246
|
+
describe('update with returnQuery option', () => {
|
|
1247
|
+
it('should return updated message list when sessionId is provided', async () => {
|
|
1248
|
+
// Create test data
|
|
1249
|
+
const sessionId = '1';
|
|
1250
|
+
await serverDB.insert(messages).values([
|
|
1251
|
+
{
|
|
1252
|
+
id: 'msg1',
|
|
1253
|
+
userId,
|
|
1254
|
+
sessionId,
|
|
1255
|
+
role: 'user',
|
|
1256
|
+
content: 'message 1',
|
|
1257
|
+
},
|
|
1258
|
+
{
|
|
1259
|
+
id: 'msg2',
|
|
1260
|
+
userId,
|
|
1261
|
+
sessionId,
|
|
1262
|
+
role: 'assistant',
|
|
1263
|
+
content: 'message 2',
|
|
1264
|
+
},
|
|
1265
|
+
]);
|
|
1266
|
+
|
|
1267
|
+
// Call update method with sessionId option
|
|
1268
|
+
const result = await messageModel.update(
|
|
1269
|
+
'msg1',
|
|
1270
|
+
{ content: 'updated message 1' },
|
|
1271
|
+
{ sessionId },
|
|
1272
|
+
);
|
|
1273
|
+
|
|
1274
|
+
// Verify return result contains message list
|
|
1275
|
+
expect(result.success).toBe(true);
|
|
1276
|
+
expect(result.messages).toBeDefined();
|
|
1277
|
+
expect(result.messages).toHaveLength(2);
|
|
1278
|
+
expect(result.messages![0].content).toBe('updated message 1');
|
|
1279
|
+
expect(result.messages![1].content).toBe('message 2');
|
|
1280
|
+
});
|
|
1281
|
+
|
|
1282
|
+
it('should return updated message list when topicId is provided', async () => {
|
|
1283
|
+
// Create test data
|
|
1284
|
+
const sessionId = '1';
|
|
1285
|
+
const topicId = 'topic-1';
|
|
1286
|
+
await serverDB.insert(topics).values({ id: topicId, sessionId, userId });
|
|
1287
|
+
await serverDB.insert(messages).values([
|
|
1288
|
+
{
|
|
1289
|
+
id: 'msg-topic1',
|
|
1290
|
+
userId,
|
|
1291
|
+
sessionId,
|
|
1292
|
+
topicId,
|
|
1293
|
+
role: 'user',
|
|
1294
|
+
content: 'topic message 1',
|
|
1295
|
+
},
|
|
1296
|
+
{
|
|
1297
|
+
id: 'msg-topic2',
|
|
1298
|
+
userId,
|
|
1299
|
+
sessionId,
|
|
1300
|
+
topicId,
|
|
1301
|
+
role: 'assistant',
|
|
1302
|
+
content: 'topic message 2',
|
|
1303
|
+
},
|
|
1304
|
+
]);
|
|
1305
|
+
|
|
1306
|
+
// Call update method with topicId option
|
|
1307
|
+
const result = await messageModel.update(
|
|
1308
|
+
'msg-topic1',
|
|
1309
|
+
{ content: 'updated topic message 1' },
|
|
1310
|
+
{ topicId, sessionId },
|
|
1311
|
+
);
|
|
1312
|
+
|
|
1313
|
+
// Verify return result contains message list
|
|
1314
|
+
expect(result.success).toBe(true);
|
|
1315
|
+
expect(result.messages).toBeDefined();
|
|
1316
|
+
expect(result.messages).toHaveLength(2);
|
|
1317
|
+
expect(result.messages![0].content).toBe('updated topic message 1');
|
|
1318
|
+
expect(result.messages![1].content).toBe('topic message 2');
|
|
1319
|
+
});
|
|
1320
|
+
|
|
1321
|
+
it('should return success without messages when options not provided', async () => {
|
|
1322
|
+
// Create test data
|
|
1323
|
+
await serverDB.insert(messages).values({
|
|
1324
|
+
id: 'msg-no-options',
|
|
1325
|
+
userId,
|
|
1326
|
+
role: 'user',
|
|
1327
|
+
content: 'original content',
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1330
|
+
// Call update method,不提供选项
|
|
1331
|
+
const result = await messageModel.update('msg-no-options', {
|
|
1332
|
+
content: 'updated content',
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
// 验证返回结果不包含消息列表
|
|
1336
|
+
expect(result.success).toBe(true);
|
|
1337
|
+
expect(result.messages).toBeUndefined();
|
|
1338
|
+
});
|
|
1339
|
+
});
|
|
1188
1340
|
});
|
|
1189
1341
|
|
|
1190
1342
|
describe('deleteMessage', () => {
|
|
1191
1343
|
it('should delete a message', async () => {
|
|
1192
|
-
//
|
|
1344
|
+
// Create test data
|
|
1193
1345
|
await serverDB
|
|
1194
1346
|
.insert(messages)
|
|
1195
1347
|
.values([{ id: '1', userId, role: 'user', content: 'message 1' }]);
|
|
@@ -1197,13 +1349,13 @@ describe('MessageModel', () => {
|
|
|
1197
1349
|
// 调用 deleteMessage 方法
|
|
1198
1350
|
await messageModel.deleteMessage('1');
|
|
1199
1351
|
|
|
1200
|
-
//
|
|
1352
|
+
// Assert result
|
|
1201
1353
|
const result = await serverDB.select().from(messages).where(eq(messages.id, '1'));
|
|
1202
1354
|
expect(result).toHaveLength(0);
|
|
1203
1355
|
});
|
|
1204
1356
|
|
|
1205
1357
|
it('should delete a message with tool calls', async () => {
|
|
1206
|
-
//
|
|
1358
|
+
// Create test data
|
|
1207
1359
|
await serverDB.transaction(async (trx) => {
|
|
1208
1360
|
await trx.insert(messages).values([
|
|
1209
1361
|
{ id: '1', userId, role: 'user', content: 'message 1', tools: [{ id: 'tool1' }] },
|
|
@@ -1217,7 +1369,7 @@ describe('MessageModel', () => {
|
|
|
1217
1369
|
// 调用 deleteMessage 方法
|
|
1218
1370
|
await messageModel.deleteMessage('1');
|
|
1219
1371
|
|
|
1220
|
-
//
|
|
1372
|
+
// Assert result
|
|
1221
1373
|
const result = await serverDB.select().from(messages).where(eq(messages.id, '1'));
|
|
1222
1374
|
expect(result).toHaveLength(0);
|
|
1223
1375
|
|
|
@@ -1230,7 +1382,7 @@ describe('MessageModel', () => {
|
|
|
1230
1382
|
});
|
|
1231
1383
|
|
|
1232
1384
|
it('should only delete messages belonging to the user', async () => {
|
|
1233
|
-
//
|
|
1385
|
+
// Create test data
|
|
1234
1386
|
await serverDB
|
|
1235
1387
|
.insert(messages)
|
|
1236
1388
|
.values([{ id: '1', userId: '456', role: 'user', content: 'message 1' }]);
|
|
@@ -1238,7 +1390,7 @@ describe('MessageModel', () => {
|
|
|
1238
1390
|
// 调用 deleteMessage 方法
|
|
1239
1391
|
await messageModel.deleteMessage('1');
|
|
1240
1392
|
|
|
1241
|
-
//
|
|
1393
|
+
// Assert result
|
|
1242
1394
|
const result = await serverDB.select().from(messages).where(eq(messages.id, '1'));
|
|
1243
1395
|
expect(result).toHaveLength(1);
|
|
1244
1396
|
});
|
|
@@ -1246,7 +1398,7 @@ describe('MessageModel', () => {
|
|
|
1246
1398
|
|
|
1247
1399
|
describe('deleteMessages', () => {
|
|
1248
1400
|
it('should delete 2 messages', async () => {
|
|
1249
|
-
//
|
|
1401
|
+
// Create test data
|
|
1250
1402
|
await serverDB.insert(messages).values([
|
|
1251
1403
|
{ id: '1', userId, role: 'user', content: 'message 1' },
|
|
1252
1404
|
{ id: '2', userId, role: 'user', content: 'message 2' },
|
|
@@ -1255,7 +1407,7 @@ describe('MessageModel', () => {
|
|
|
1255
1407
|
// 调用 deleteMessage 方法
|
|
1256
1408
|
await messageModel.deleteMessages(['1', '2']);
|
|
1257
1409
|
|
|
1258
|
-
//
|
|
1410
|
+
// Assert result
|
|
1259
1411
|
const result = await serverDB.select().from(messages).where(eq(messages.id, '1'));
|
|
1260
1412
|
expect(result).toHaveLength(0);
|
|
1261
1413
|
const result2 = await serverDB.select().from(messages).where(eq(messages.id, '2'));
|
|
@@ -1263,7 +1415,7 @@ describe('MessageModel', () => {
|
|
|
1263
1415
|
});
|
|
1264
1416
|
|
|
1265
1417
|
it('should only delete messages belonging to the user', async () => {
|
|
1266
|
-
//
|
|
1418
|
+
// Create test data
|
|
1267
1419
|
await serverDB.insert(messages).values([
|
|
1268
1420
|
{ id: '1', userId: '456', role: 'user', content: 'message 1' },
|
|
1269
1421
|
{ id: '2', userId: '456', role: 'user', content: 'message 1' },
|
|
@@ -1272,7 +1424,7 @@ describe('MessageModel', () => {
|
|
|
1272
1424
|
// 调用 deleteMessage 方法
|
|
1273
1425
|
await messageModel.deleteMessages(['1', '2']);
|
|
1274
1426
|
|
|
1275
|
-
//
|
|
1427
|
+
// Assert result
|
|
1276
1428
|
const result = await serverDB.select().from(messages).where(eq(messages.id, '1'));
|
|
1277
1429
|
expect(result).toHaveLength(1);
|
|
1278
1430
|
});
|
|
@@ -1280,7 +1432,7 @@ describe('MessageModel', () => {
|
|
|
1280
1432
|
|
|
1281
1433
|
describe('deleteAllMessages', () => {
|
|
1282
1434
|
it('should delete all messages belonging to the user', async () => {
|
|
1283
|
-
//
|
|
1435
|
+
// Create test data
|
|
1284
1436
|
await serverDB.insert(messages).values([
|
|
1285
1437
|
{ id: '1', userId, role: 'user', content: 'message 1' },
|
|
1286
1438
|
{ id: '2', userId, role: 'user', content: 'message 2' },
|
|
@@ -1290,7 +1442,7 @@ describe('MessageModel', () => {
|
|
|
1290
1442
|
// 调用 deleteAllMessages 方法
|
|
1291
1443
|
await messageModel.deleteAllMessages();
|
|
1292
1444
|
|
|
1293
|
-
//
|
|
1445
|
+
// Assert result
|
|
1294
1446
|
const result = await serverDB.select().from(messages).where(eq(messages.userId, userId));
|
|
1295
1447
|
|
|
1296
1448
|
expect(result).toHaveLength(0);
|
|
@@ -1303,7 +1455,7 @@ describe('MessageModel', () => {
|
|
|
1303
1455
|
|
|
1304
1456
|
describe('updatePluginState', () => {
|
|
1305
1457
|
it('should update the state field in messagePlugins table', async () => {
|
|
1306
|
-
//
|
|
1458
|
+
// Create test data
|
|
1307
1459
|
await serverDB.insert(messages).values({ id: '1', content: 'abc', role: 'user', userId });
|
|
1308
1460
|
await serverDB.insert(messagePlugins).values([
|
|
1309
1461
|
{
|
|
@@ -1318,7 +1470,7 @@ describe('MessageModel', () => {
|
|
|
1318
1470
|
// 调用 updatePluginState 方法
|
|
1319
1471
|
await messageModel.updatePluginState('1', { key2: 'value2' });
|
|
1320
1472
|
|
|
1321
|
-
//
|
|
1473
|
+
// Assert result
|
|
1322
1474
|
const result = await serverDB.select().from(messagePlugins).where(eq(messagePlugins.id, '1'));
|
|
1323
1475
|
|
|
1324
1476
|
expect(result[0].state).toEqual({ key1: 'value1', key2: 'value2' });
|
|
@@ -1333,7 +1485,7 @@ describe('MessageModel', () => {
|
|
|
1333
1485
|
});
|
|
1334
1486
|
describe('updateMessagePlugin', () => {
|
|
1335
1487
|
it('should update the state field in messagePlugins table', async () => {
|
|
1336
|
-
//
|
|
1488
|
+
// Create test data
|
|
1337
1489
|
await serverDB.insert(messages).values({ id: '1', content: 'abc', role: 'user', userId });
|
|
1338
1490
|
await serverDB.insert(messagePlugins).values([
|
|
1339
1491
|
{
|
|
@@ -1348,7 +1500,7 @@ describe('MessageModel', () => {
|
|
|
1348
1500
|
// 调用 updatePluginState 方法
|
|
1349
1501
|
await messageModel.updateMessagePlugin('1', { identifier: 'plugin2' });
|
|
1350
1502
|
|
|
1351
|
-
//
|
|
1503
|
+
// Assert result
|
|
1352
1504
|
const result = await serverDB.select().from(messagePlugins).where(eq(messagePlugins.id, '1'));
|
|
1353
1505
|
|
|
1354
1506
|
expect(result[0].identifier).toEqual('plugin2');
|
|
@@ -1364,7 +1516,7 @@ describe('MessageModel', () => {
|
|
|
1364
1516
|
|
|
1365
1517
|
describe('updateMetadata', () => {
|
|
1366
1518
|
it('should update metadata for an existing message', async () => {
|
|
1367
|
-
//
|
|
1519
|
+
// Create test data
|
|
1368
1520
|
await serverDB.insert(messages).values({
|
|
1369
1521
|
id: 'msg-with-metadata',
|
|
1370
1522
|
userId,
|
|
@@ -1376,7 +1528,7 @@ describe('MessageModel', () => {
|
|
|
1376
1528
|
// 调用 updateMetadata 方法
|
|
1377
1529
|
await messageModel.updateMetadata('msg-with-metadata', { newKey: 'newValue' });
|
|
1378
1530
|
|
|
1379
|
-
//
|
|
1531
|
+
// Assert result
|
|
1380
1532
|
const result = await serverDB
|
|
1381
1533
|
.select()
|
|
1382
1534
|
.from(messages)
|
|
@@ -1389,7 +1541,7 @@ describe('MessageModel', () => {
|
|
|
1389
1541
|
});
|
|
1390
1542
|
|
|
1391
1543
|
it('should merge new metadata with existing metadata using lodash merge behavior', async () => {
|
|
1392
|
-
//
|
|
1544
|
+
// Create test data
|
|
1393
1545
|
await serverDB.insert(messages).values({
|
|
1394
1546
|
id: 'msg-merge-metadata',
|
|
1395
1547
|
userId,
|
|
@@ -1413,7 +1565,7 @@ describe('MessageModel', () => {
|
|
|
1413
1565
|
newTopLevel: 'value',
|
|
1414
1566
|
});
|
|
1415
1567
|
|
|
1416
|
-
//
|
|
1568
|
+
// Assert result - 应该使用 lodash merge 行为
|
|
1417
1569
|
const result = await serverDB
|
|
1418
1570
|
.select()
|
|
1419
1571
|
.from(messages)
|
|
@@ -1434,12 +1586,12 @@ describe('MessageModel', () => {
|
|
|
1434
1586
|
// 调用 updateMetadata 方法,尝试更新不存在的消息
|
|
1435
1587
|
const result = await messageModel.updateMetadata('non-existent-id', { key: 'value' });
|
|
1436
1588
|
|
|
1437
|
-
//
|
|
1589
|
+
// Assert result - 应该返回 undefined
|
|
1438
1590
|
expect(result).toBeUndefined();
|
|
1439
1591
|
});
|
|
1440
1592
|
|
|
1441
1593
|
it('should handle empty metadata updates', async () => {
|
|
1442
|
-
//
|
|
1594
|
+
// Create test data
|
|
1443
1595
|
await serverDB.insert(messages).values({
|
|
1444
1596
|
id: 'msg-empty-metadata',
|
|
1445
1597
|
userId,
|
|
@@ -1451,7 +1603,7 @@ describe('MessageModel', () => {
|
|
|
1451
1603
|
// 调用 updateMetadata 方法,传递空对象
|
|
1452
1604
|
await messageModel.updateMetadata('msg-empty-metadata', {});
|
|
1453
1605
|
|
|
1454
|
-
//
|
|
1606
|
+
// Assert result - 原始 metadata 应该保持不变
|
|
1455
1607
|
const result = await serverDB
|
|
1456
1608
|
.select()
|
|
1457
1609
|
.from(messages)
|
|
@@ -1461,7 +1613,7 @@ describe('MessageModel', () => {
|
|
|
1461
1613
|
});
|
|
1462
1614
|
|
|
1463
1615
|
it('should handle message with null metadata', async () => {
|
|
1464
|
-
//
|
|
1616
|
+
// Create test data
|
|
1465
1617
|
await serverDB.insert(messages).values({
|
|
1466
1618
|
id: 'msg-null-metadata',
|
|
1467
1619
|
userId,
|
|
@@ -1473,7 +1625,7 @@ describe('MessageModel', () => {
|
|
|
1473
1625
|
// 调用 updateMetadata 方法
|
|
1474
1626
|
await messageModel.updateMetadata('msg-null-metadata', { key: 'value' });
|
|
1475
1627
|
|
|
1476
|
-
//
|
|
1628
|
+
// Assert result - 应该创建新的 metadata
|
|
1477
1629
|
const result = await serverDB
|
|
1478
1630
|
.select()
|
|
1479
1631
|
.from(messages)
|
|
@@ -1483,7 +1635,7 @@ describe('MessageModel', () => {
|
|
|
1483
1635
|
});
|
|
1484
1636
|
|
|
1485
1637
|
it('should only update messages belonging to the current user', async () => {
|
|
1486
|
-
//
|
|
1638
|
+
// Create test data - 其他用户的消息
|
|
1487
1639
|
await serverDB.insert(messages).values({
|
|
1488
1640
|
id: 'msg-other-user',
|
|
1489
1641
|
userId: '456',
|
|
@@ -1497,7 +1649,7 @@ describe('MessageModel', () => {
|
|
|
1497
1649
|
hackedKey: 'hackedValue',
|
|
1498
1650
|
});
|
|
1499
1651
|
|
|
1500
|
-
//
|
|
1652
|
+
// Assert result - 应该返回 undefined
|
|
1501
1653
|
expect(result).toBeUndefined();
|
|
1502
1654
|
|
|
1503
1655
|
// 验证原始 metadata 未被修改
|
|
@@ -1510,7 +1662,7 @@ describe('MessageModel', () => {
|
|
|
1510
1662
|
});
|
|
1511
1663
|
|
|
1512
1664
|
it('should handle complex nested metadata updates', async () => {
|
|
1513
|
-
//
|
|
1665
|
+
// Create test data
|
|
1514
1666
|
await serverDB.insert(messages).values({
|
|
1515
1667
|
id: 'msg-complex-metadata',
|
|
1516
1668
|
userId,
|
|
@@ -1539,7 +1691,7 @@ describe('MessageModel', () => {
|
|
|
1539
1691
|
stats: { count: 10 },
|
|
1540
1692
|
});
|
|
1541
1693
|
|
|
1542
|
-
//
|
|
1694
|
+
// Assert result
|
|
1543
1695
|
const result = await serverDB
|
|
1544
1696
|
.select()
|
|
1545
1697
|
.from(messages)
|
|
@@ -1562,7 +1714,7 @@ describe('MessageModel', () => {
|
|
|
1562
1714
|
|
|
1563
1715
|
describe('updateTranslate', () => {
|
|
1564
1716
|
it('should insert a new record if message does not exist in messageTranslates table', async () => {
|
|
1565
|
-
//
|
|
1717
|
+
// Create test data
|
|
1566
1718
|
await serverDB
|
|
1567
1719
|
.insert(messages)
|
|
1568
1720
|
.values([{ id: '1', userId, role: 'user', content: 'message 1' }]);
|
|
@@ -1574,7 +1726,7 @@ describe('MessageModel', () => {
|
|
|
1574
1726
|
to: 'zh',
|
|
1575
1727
|
});
|
|
1576
1728
|
|
|
1577
|
-
//
|
|
1729
|
+
// Assert result
|
|
1578
1730
|
const result = await serverDB
|
|
1579
1731
|
.select()
|
|
1580
1732
|
.from(messageTranslates)
|
|
@@ -1585,7 +1737,7 @@ describe('MessageModel', () => {
|
|
|
1585
1737
|
});
|
|
1586
1738
|
|
|
1587
1739
|
it('should update the corresponding fields if message exists in messageTranslates table', async () => {
|
|
1588
|
-
//
|
|
1740
|
+
// Create test data
|
|
1589
1741
|
await serverDB.transaction(async (trx) => {
|
|
1590
1742
|
await trx
|
|
1591
1743
|
.insert(messages)
|
|
@@ -1598,7 +1750,7 @@ describe('MessageModel', () => {
|
|
|
1598
1750
|
// 调用 updateTranslate 方法
|
|
1599
1751
|
await messageModel.updateTranslate('1', { content: 'updated translated message 1' });
|
|
1600
1752
|
|
|
1601
|
-
//
|
|
1753
|
+
// Assert result
|
|
1602
1754
|
const result = await serverDB
|
|
1603
1755
|
.select()
|
|
1604
1756
|
.from(messageTranslates)
|
|
@@ -1610,7 +1762,7 @@ describe('MessageModel', () => {
|
|
|
1610
1762
|
|
|
1611
1763
|
describe('updateTTS', () => {
|
|
1612
1764
|
it('should insert a new record if message does not exist in messageTTS table', async () => {
|
|
1613
|
-
//
|
|
1765
|
+
// Create test data
|
|
1614
1766
|
await serverDB
|
|
1615
1767
|
.insert(messages)
|
|
1616
1768
|
.values([{ id: '1', userId, role: 'user', content: 'message 1' }]);
|
|
@@ -1618,7 +1770,7 @@ describe('MessageModel', () => {
|
|
|
1618
1770
|
// 调用 updateTTS 方法
|
|
1619
1771
|
await messageModel.updateTTS('1', { contentMd5: 'md5', file: 'f1', voice: 'voice1' });
|
|
1620
1772
|
|
|
1621
|
-
//
|
|
1773
|
+
// Assert result
|
|
1622
1774
|
const result = await serverDB.select().from(messageTTS).where(eq(messageTTS.id, '1'));
|
|
1623
1775
|
|
|
1624
1776
|
expect(result).toHaveLength(1);
|
|
@@ -1626,7 +1778,7 @@ describe('MessageModel', () => {
|
|
|
1626
1778
|
});
|
|
1627
1779
|
|
|
1628
1780
|
it('should update the corresponding fields if message exists in messageTTS table', async () => {
|
|
1629
|
-
//
|
|
1781
|
+
// Create test data
|
|
1630
1782
|
await serverDB.transaction(async (trx) => {
|
|
1631
1783
|
await trx
|
|
1632
1784
|
.insert(messages)
|
|
@@ -1639,7 +1791,7 @@ describe('MessageModel', () => {
|
|
|
1639
1791
|
// 调用 updateTTS 方法
|
|
1640
1792
|
await messageModel.updateTTS('1', { voice: 'updated voice1' });
|
|
1641
1793
|
|
|
1642
|
-
//
|
|
1794
|
+
// Assert result
|
|
1643
1795
|
const result = await serverDB.select().from(messageTTS).where(eq(messageTTS.id, '1'));
|
|
1644
1796
|
|
|
1645
1797
|
expect(result[0].voice).toBe('updated voice1');
|
|
@@ -1648,14 +1800,14 @@ describe('MessageModel', () => {
|
|
|
1648
1800
|
|
|
1649
1801
|
describe('deleteMessageTranslate', () => {
|
|
1650
1802
|
it('should delete the message translate record', async () => {
|
|
1651
|
-
//
|
|
1803
|
+
// Create test data
|
|
1652
1804
|
await serverDB.insert(messages).values([{ id: '1', role: 'abc', userId }]);
|
|
1653
1805
|
await serverDB.insert(messageTranslates).values([{ id: '1', userId }]);
|
|
1654
1806
|
|
|
1655
1807
|
// 调用 deleteMessageTranslate 方法
|
|
1656
1808
|
await messageModel.deleteMessageTranslate('1');
|
|
1657
1809
|
|
|
1658
|
-
//
|
|
1810
|
+
// Assert result
|
|
1659
1811
|
const result = await serverDB
|
|
1660
1812
|
.select()
|
|
1661
1813
|
.from(messageTranslates)
|
|
@@ -1667,14 +1819,14 @@ describe('MessageModel', () => {
|
|
|
1667
1819
|
|
|
1668
1820
|
describe('deleteMessageTTS', () => {
|
|
1669
1821
|
it('should delete the message TTS record', async () => {
|
|
1670
|
-
//
|
|
1822
|
+
// Create test data
|
|
1671
1823
|
await serverDB.insert(messages).values([{ id: '1', role: 'abc', userId }]);
|
|
1672
1824
|
await serverDB.insert(messageTTS).values([{ userId, id: '1' }]);
|
|
1673
1825
|
|
|
1674
1826
|
// 调用 deleteMessageTTS 方法
|
|
1675
1827
|
await messageModel.deleteMessageTTS('1');
|
|
1676
1828
|
|
|
1677
|
-
//
|
|
1829
|
+
// Assert result
|
|
1678
1830
|
const result = await serverDB.select().from(messageTTS).where(eq(messageTTS.id, '1'));
|
|
1679
1831
|
expect(result).toHaveLength(0);
|
|
1680
1832
|
});
|
|
@@ -1682,7 +1834,7 @@ describe('MessageModel', () => {
|
|
|
1682
1834
|
|
|
1683
1835
|
describe('count', () => {
|
|
1684
1836
|
it('should return the count of messages belonging to the user', async () => {
|
|
1685
|
-
//
|
|
1837
|
+
// Create test data
|
|
1686
1838
|
await serverDB.insert(messages).values([
|
|
1687
1839
|
{ id: '1', userId, role: 'user', content: 'message 1' },
|
|
1688
1840
|
{ id: '2', userId, role: 'user', content: 'message 2' },
|
|
@@ -1692,13 +1844,13 @@ describe('MessageModel', () => {
|
|
|
1692
1844
|
// 调用 count 方法
|
|
1693
1845
|
const result = await messageModel.count();
|
|
1694
1846
|
|
|
1695
|
-
//
|
|
1847
|
+
// Assert result
|
|
1696
1848
|
expect(result).toBe(2);
|
|
1697
1849
|
});
|
|
1698
1850
|
|
|
1699
1851
|
describe('count with date filters', () => {
|
|
1700
1852
|
beforeEach(async () => {
|
|
1701
|
-
//
|
|
1853
|
+
// Create test data,包含不同日期的消息
|
|
1702
1854
|
await serverDB.insert(messages).values([
|
|
1703
1855
|
{
|
|
1704
1856
|
id: 'date1',
|
|
@@ -1919,7 +2071,7 @@ describe('MessageModel', () => {
|
|
|
1919
2071
|
|
|
1920
2072
|
describe('countWords', () => {
|
|
1921
2073
|
it('should count total words of messages belonging to the user', async () => {
|
|
1922
|
-
//
|
|
2074
|
+
// Create test data
|
|
1923
2075
|
await serverDB.insert(messages).values([
|
|
1924
2076
|
{ id: '1', userId, role: 'user', content: 'hello world' },
|
|
1925
2077
|
{ id: '2', userId, role: 'user', content: 'test message' },
|
|
@@ -1929,12 +2081,12 @@ describe('MessageModel', () => {
|
|
|
1929
2081
|
// 调用 countWords 方法
|
|
1930
2082
|
const result = await messageModel.countWords();
|
|
1931
2083
|
|
|
1932
|
-
//
|
|
2084
|
+
// Assert result - 'hello world' + 'test message' = 23 characters
|
|
1933
2085
|
expect(result).toEqual(23);
|
|
1934
2086
|
});
|
|
1935
2087
|
|
|
1936
2088
|
it('should count words within date range', async () => {
|
|
1937
|
-
//
|
|
2089
|
+
// Create test data
|
|
1938
2090
|
await serverDB.insert(messages).values([
|
|
1939
2091
|
{
|
|
1940
2092
|
id: '1',
|
|
@@ -1957,12 +2109,12 @@ describe('MessageModel', () => {
|
|
|
1957
2109
|
range: ['2023-05-01', '2023-07-01'],
|
|
1958
2110
|
});
|
|
1959
2111
|
|
|
1960
|
-
//
|
|
2112
|
+
// Assert result - 只计算 'new message' = 11 characters
|
|
1961
2113
|
expect(result).toEqual(11);
|
|
1962
2114
|
});
|
|
1963
2115
|
|
|
1964
2116
|
it('should handle empty content', async () => {
|
|
1965
|
-
//
|
|
2117
|
+
// Create test data
|
|
1966
2118
|
await serverDB.insert(messages).values([
|
|
1967
2119
|
{ id: '1', userId, role: 'user', content: '' },
|
|
1968
2120
|
{ id: '2', userId, role: 'user', content: null },
|
|
@@ -1971,7 +2123,7 @@ describe('MessageModel', () => {
|
|
|
1971
2123
|
// 调用 countWords 方法
|
|
1972
2124
|
const result = await messageModel.countWords();
|
|
1973
2125
|
|
|
1974
|
-
//
|
|
2126
|
+
// Assert result
|
|
1975
2127
|
expect(result).toEqual(0);
|
|
1976
2128
|
});
|
|
1977
2129
|
});
|
|
@@ -1988,7 +2140,7 @@ describe('MessageModel', () => {
|
|
|
1988
2140
|
const oneDayAgoDate = today.subtract(1, 'day').format('YYYY-MM-DD');
|
|
1989
2141
|
const todayDate = today.format('YYYY-MM-DD');
|
|
1990
2142
|
|
|
1991
|
-
//
|
|
2143
|
+
// Create test data
|
|
1992
2144
|
await serverDB.insert(messages).values([
|
|
1993
2145
|
{
|
|
1994
2146
|
id: '1',
|
|
@@ -2016,7 +2168,7 @@ describe('MessageModel', () => {
|
|
|
2016
2168
|
// 调用 getHeatmaps 方法
|
|
2017
2169
|
const result = await messageModel.getHeatmaps();
|
|
2018
2170
|
|
|
2019
|
-
//
|
|
2171
|
+
// Assert result
|
|
2020
2172
|
expect(result.length).toBeGreaterThanOrEqual(366);
|
|
2021
2173
|
expect(result.length).toBeLessThan(368);
|
|
2022
2174
|
|
|
@@ -2051,7 +2203,7 @@ describe('MessageModel', () => {
|
|
|
2051
2203
|
const oneDayAgoDate = today.subtract(1, 'day').format('YYYY-MM-DD');
|
|
2052
2204
|
const todayDate = today.format('YYYY-MM-DD');
|
|
2053
2205
|
|
|
2054
|
-
//
|
|
2206
|
+
// Create test data - 不同数量的消息以测试不同的等级
|
|
2055
2207
|
await serverDB.insert(messages).values([
|
|
2056
2208
|
// 1 message - level 1
|
|
2057
2209
|
{
|
|
@@ -2141,7 +2293,7 @@ describe('MessageModel', () => {
|
|
|
2141
2293
|
const oneDayAgoDate = today.subtract(1, 'day').format('YYYY-MM-DD');
|
|
2142
2294
|
const todayDate = today.format('YYYY-MM-DD');
|
|
2143
2295
|
|
|
2144
|
-
//
|
|
2296
|
+
// Create test data
|
|
2145
2297
|
await serverDB.insert(messages).values([
|
|
2146
2298
|
{
|
|
2147
2299
|
id: '1',
|
|
@@ -2169,7 +2321,7 @@ describe('MessageModel', () => {
|
|
|
2169
2321
|
// 调用 getHeatmaps 方法
|
|
2170
2322
|
const result = await messageModel.getHeatmaps();
|
|
2171
2323
|
|
|
2172
|
-
//
|
|
2324
|
+
// Assert result
|
|
2173
2325
|
expect(result.length).toBeGreaterThanOrEqual(366);
|
|
2174
2326
|
expect(result.length).toBeLessThan(368);
|
|
2175
2327
|
|
|
@@ -2197,7 +2349,7 @@ describe('MessageModel', () => {
|
|
|
2197
2349
|
// 调用 getHeatmaps 方法
|
|
2198
2350
|
const result = await messageModel.getHeatmaps();
|
|
2199
2351
|
|
|
2200
|
-
//
|
|
2352
|
+
// Assert result
|
|
2201
2353
|
expect(result.length).toBeGreaterThanOrEqual(366);
|
|
2202
2354
|
expect(result.length).toBeLessThan(368);
|
|
2203
2355
|
|
|
@@ -2211,7 +2363,7 @@ describe('MessageModel', () => {
|
|
|
2211
2363
|
|
|
2212
2364
|
describe('rankModels', () => {
|
|
2213
2365
|
it('should rank models by usage count', async () => {
|
|
2214
|
-
//
|
|
2366
|
+
// Create test data
|
|
2215
2367
|
await serverDB.insert(messages).values([
|
|
2216
2368
|
{ id: '1', userId, role: 'assistant', content: 'message 1', model: 'gpt-3.5' },
|
|
2217
2369
|
{ id: '2', userId, role: 'assistant', content: 'message 2', model: 'gpt-3.5' },
|
|
@@ -2222,14 +2374,14 @@ describe('MessageModel', () => {
|
|
|
2222
2374
|
// 调用 rankModels 方法
|
|
2223
2375
|
const result = await messageModel.rankModels();
|
|
2224
2376
|
|
|
2225
|
-
//
|
|
2377
|
+
// Assert result
|
|
2226
2378
|
expect(result).toHaveLength(2);
|
|
2227
2379
|
expect(result[0]).toEqual({ id: 'gpt-3.5', count: 2 }); // 当前用户使用 gpt-3.5 两次
|
|
2228
2380
|
expect(result[1]).toEqual({ id: 'gpt-4', count: 1 }); // 当前用户使用 gpt-4 一次
|
|
2229
2381
|
});
|
|
2230
2382
|
|
|
2231
2383
|
it('should only count messages with model field', async () => {
|
|
2232
|
-
//
|
|
2384
|
+
// Create test data,包括没有 model 字段的消息
|
|
2233
2385
|
await serverDB.insert(messages).values([
|
|
2234
2386
|
{ id: '1', userId, role: 'assistant', content: 'message 1', model: 'gpt-3.5' },
|
|
2235
2387
|
{ id: '2', userId, role: 'assistant', content: 'message 2', model: null },
|
|
@@ -2239,13 +2391,13 @@ describe('MessageModel', () => {
|
|
|
2239
2391
|
// 调用 rankModels 方法
|
|
2240
2392
|
const result = await messageModel.rankModels();
|
|
2241
2393
|
|
|
2242
|
-
//
|
|
2394
|
+
// Assert result
|
|
2243
2395
|
expect(result).toHaveLength(1);
|
|
2244
2396
|
expect(result[0]).toEqual({ id: 'gpt-3.5', count: 1 });
|
|
2245
2397
|
});
|
|
2246
2398
|
|
|
2247
2399
|
it('should return empty array when no models are used', async () => {
|
|
2248
|
-
//
|
|
2400
|
+
// Create test data,所有消息都没有 model
|
|
2249
2401
|
await serverDB.insert(messages).values([
|
|
2250
2402
|
{ id: '1', userId, role: 'user', content: 'message 1' },
|
|
2251
2403
|
{ id: '2', userId, role: 'assistant', content: 'message 2' },
|
|
@@ -2254,12 +2406,12 @@ describe('MessageModel', () => {
|
|
|
2254
2406
|
// 调用 rankModels 方法
|
|
2255
2407
|
const result = await messageModel.rankModels();
|
|
2256
2408
|
|
|
2257
|
-
//
|
|
2409
|
+
// Assert result
|
|
2258
2410
|
expect(result).toHaveLength(0);
|
|
2259
2411
|
});
|
|
2260
2412
|
|
|
2261
2413
|
it('should order models by count in descending order', async () => {
|
|
2262
|
-
//
|
|
2414
|
+
// Create test data,使用不同次数的模型
|
|
2263
2415
|
await serverDB.insert(messages).values([
|
|
2264
2416
|
{ id: '1', userId, role: 'assistant', content: 'message 1', model: 'gpt-4' },
|
|
2265
2417
|
{ id: '2', userId, role: 'assistant', content: 'message 2', model: 'gpt-3.5' },
|
|
@@ -2271,7 +2423,7 @@ describe('MessageModel', () => {
|
|
|
2271
2423
|
// 调用 rankModels 方法
|
|
2272
2424
|
const result = await messageModel.rankModels();
|
|
2273
2425
|
|
|
2274
|
-
//
|
|
2426
|
+
// Assert result
|
|
2275
2427
|
expect(result).toHaveLength(3);
|
|
2276
2428
|
expect(result[0]).toEqual({ id: 'gpt-3.5', count: 3 }); // 最多使用
|
|
2277
2429
|
expect(result[1]).toEqual({ id: 'claude', count: 1 });
|
|
@@ -2281,7 +2433,7 @@ describe('MessageModel', () => {
|
|
|
2281
2433
|
|
|
2282
2434
|
describe('hasMoreThanN', () => {
|
|
2283
2435
|
it('should return true when message count is greater than N', async () => {
|
|
2284
|
-
//
|
|
2436
|
+
// Create test data
|
|
2285
2437
|
await serverDB.insert(messages).values([
|
|
2286
2438
|
{ id: '1', userId, role: 'user', content: 'message 1' },
|
|
2287
2439
|
{ id: '2', userId, role: 'user', content: 'message 2' },
|
|
@@ -2299,7 +2451,7 @@ describe('MessageModel', () => {
|
|
|
2299
2451
|
});
|
|
2300
2452
|
|
|
2301
2453
|
it('should only count messages belonging to the user', async () => {
|
|
2302
|
-
//
|
|
2454
|
+
// Create test data,包括其他用户的消息
|
|
2303
2455
|
await serverDB.insert(messages).values([
|
|
2304
2456
|
{ id: '1', userId, role: 'user', content: 'message 1' },
|
|
2305
2457
|
{ id: '2', userId, role: 'user', content: 'message 2' },
|
|
@@ -2335,7 +2487,7 @@ describe('MessageModel', () => {
|
|
|
2335
2487
|
|
|
2336
2488
|
describe('createMessageQuery', () => {
|
|
2337
2489
|
it('should create a new message query', async () => {
|
|
2338
|
-
//
|
|
2490
|
+
// Create test data
|
|
2339
2491
|
await serverDB.insert(messages).values({
|
|
2340
2492
|
id: 'msg1',
|
|
2341
2493
|
userId,
|
|
@@ -2351,7 +2503,7 @@ describe('MessageModel', () => {
|
|
|
2351
2503
|
embeddingsId,
|
|
2352
2504
|
});
|
|
2353
2505
|
|
|
2354
|
-
//
|
|
2506
|
+
// Assert result
|
|
2355
2507
|
expect(result).toBeDefined();
|
|
2356
2508
|
expect(result.id).toBeDefined();
|
|
2357
2509
|
expect(result.messageId).toBe('msg1');
|
|
@@ -2372,7 +2524,7 @@ describe('MessageModel', () => {
|
|
|
2372
2524
|
});
|
|
2373
2525
|
|
|
2374
2526
|
it('should create a message query with embeddings ID', async () => {
|
|
2375
|
-
//
|
|
2527
|
+
// Create test data
|
|
2376
2528
|
await serverDB.insert(messages).values({
|
|
2377
2529
|
id: 'msg2',
|
|
2378
2530
|
userId,
|
|
@@ -2388,7 +2540,7 @@ describe('MessageModel', () => {
|
|
|
2388
2540
|
embeddingsId,
|
|
2389
2541
|
});
|
|
2390
2542
|
|
|
2391
|
-
//
|
|
2543
|
+
// Assert result
|
|
2392
2544
|
expect(result).toBeDefined();
|
|
2393
2545
|
expect(result.embeddingsId).toBe(embeddingsId);
|
|
2394
2546
|
|
|
@@ -2402,7 +2554,7 @@ describe('MessageModel', () => {
|
|
|
2402
2554
|
});
|
|
2403
2555
|
|
|
2404
2556
|
it('should generate a unique ID for each message query', async () => {
|
|
2405
|
-
//
|
|
2557
|
+
// Create test data
|
|
2406
2558
|
await serverDB.insert(messages).values({
|
|
2407
2559
|
id: 'msg3',
|
|
2408
2560
|
userId,
|
|
@@ -2425,7 +2577,7 @@ describe('MessageModel', () => {
|
|
|
2425
2577
|
embeddingsId,
|
|
2426
2578
|
});
|
|
2427
2579
|
|
|
2428
|
-
//
|
|
2580
|
+
// Assert result
|
|
2429
2581
|
expect(result1.id).not.toBe(result2.id);
|
|
2430
2582
|
});
|
|
2431
2583
|
});
|
|
@@ -2473,7 +2625,7 @@ describe('MessageModel', () => {
|
|
|
2473
2625
|
|
|
2474
2626
|
describe('deleteMessageQuery', () => {
|
|
2475
2627
|
it('should delete a message query by ID', async () => {
|
|
2476
|
-
//
|
|
2628
|
+
// Create test data
|
|
2477
2629
|
const queryId = uuid();
|
|
2478
2630
|
await serverDB.insert(messages).values({
|
|
2479
2631
|
id: 'msg4',
|
|
@@ -2511,7 +2663,7 @@ describe('MessageModel', () => {
|
|
|
2511
2663
|
});
|
|
2512
2664
|
|
|
2513
2665
|
it('should only delete message queries belonging to the user', async () => {
|
|
2514
|
-
//
|
|
2666
|
+
// Create test data - 其他用户的查询
|
|
2515
2667
|
const queryId = uuid();
|
|
2516
2668
|
await serverDB.insert(messages).values({
|
|
2517
2669
|
id: 'msg5',
|