@lobehub/lobehub 2.0.0-next.32 → 2.0.0-next.34

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 (90) hide show
  1. package/.github/workflows/test.yml +1 -0
  2. package/CHANGELOG.md +58 -0
  3. package/apps/desktop/package.json +1 -1
  4. package/changelog/v1.json +21 -0
  5. package/docker-compose/local/.env.example +3 -0
  6. package/docs/self-hosting/server-database/docker-compose.mdx +29 -0
  7. package/docs/self-hosting/server-database/docker-compose.zh-CN.mdx +29 -0
  8. package/package.json +1 -1
  9. package/packages/const/src/hotkeys.ts +3 -3
  10. package/packages/const/src/models.ts +2 -2
  11. package/packages/const/src/utils/merge.ts +3 -3
  12. package/packages/conversation-flow/package.json +13 -0
  13. package/packages/conversation-flow/src/__tests__/fixtures/index.ts +48 -0
  14. package/packages/conversation-flow/src/__tests__/fixtures/inputs/assistant-chain-with-followup.json +56 -0
  15. package/packages/conversation-flow/src/__tests__/fixtures/inputs/assistant-with-tools.json +144 -0
  16. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/active-index-1.json +131 -0
  17. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/assistant-branch.json +96 -0
  18. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/assistant-user-branch.json +123 -0
  19. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/conversation.json +128 -0
  20. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/index.ts +14 -0
  21. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/nested.json +179 -0
  22. package/packages/conversation-flow/src/__tests__/fixtures/inputs/compare/index.ts +8 -0
  23. package/packages/conversation-flow/src/__tests__/fixtures/inputs/compare/simple.json +85 -0
  24. package/packages/conversation-flow/src/__tests__/fixtures/inputs/compare/with-tools.json +169 -0
  25. package/packages/conversation-flow/src/__tests__/fixtures/inputs/complex-scenario.json +107 -0
  26. package/packages/conversation-flow/src/__tests__/fixtures/inputs/index.ts +14 -0
  27. package/packages/conversation-flow/src/__tests__/fixtures/inputs/linear-conversation.json +59 -0
  28. package/packages/conversation-flow/src/__tests__/fixtures/outputs/assistant-chain-with-followup.json +135 -0
  29. package/packages/conversation-flow/src/__tests__/fixtures/outputs/assistant-with-tools.json +340 -0
  30. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/active-index-1.json +242 -0
  31. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/assistant-branch.json +208 -0
  32. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/assistant-user-branch.json +254 -0
  33. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/conversation.json +260 -0
  34. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/index.ts +14 -0
  35. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/nested.json +389 -0
  36. package/packages/conversation-flow/src/__tests__/fixtures/outputs/compare/index.ts +8 -0
  37. package/packages/conversation-flow/src/__tests__/fixtures/outputs/compare/simple.json +224 -0
  38. package/packages/conversation-flow/src/__tests__/fixtures/outputs/compare/with-tools.json +418 -0
  39. package/packages/conversation-flow/src/__tests__/fixtures/outputs/complex-scenario.json +239 -0
  40. package/packages/conversation-flow/src/__tests__/fixtures/outputs/linear-conversation.json +138 -0
  41. package/packages/conversation-flow/src/__tests__/parse.test.ts +97 -0
  42. package/packages/conversation-flow/src/index.ts +17 -0
  43. package/packages/conversation-flow/src/indexing.ts +58 -0
  44. package/packages/conversation-flow/src/parse.ts +53 -0
  45. package/packages/conversation-flow/src/structuring.ts +38 -0
  46. package/packages/conversation-flow/src/transformation/BranchResolver.ts +66 -0
  47. package/packages/conversation-flow/src/transformation/ContextTreeBuilder.ts +292 -0
  48. package/packages/conversation-flow/src/transformation/FlatListBuilder.ts +421 -0
  49. package/packages/conversation-flow/src/transformation/MessageCollector.ts +166 -0
  50. package/packages/conversation-flow/src/transformation/MessageTransformer.ts +177 -0
  51. package/packages/conversation-flow/src/transformation/__tests__/BranchResolver.test.ts +151 -0
  52. package/packages/conversation-flow/src/transformation/__tests__/ContextTreeBuilder.test.ts +385 -0
  53. package/packages/conversation-flow/src/transformation/__tests__/FlatListBuilder.test.ts +511 -0
  54. package/packages/conversation-flow/src/transformation/__tests__/MessageCollector.test.ts +220 -0
  55. package/packages/conversation-flow/src/transformation/__tests__/MessageTransformer.test.ts +287 -0
  56. package/packages/conversation-flow/src/transformation/index.ts +78 -0
  57. package/packages/conversation-flow/src/types/contextTree.ts +65 -0
  58. package/packages/conversation-flow/src/types/flatMessageList.ts +66 -0
  59. package/packages/conversation-flow/src/types/shared.ts +63 -0
  60. package/packages/conversation-flow/src/types.ts +36 -0
  61. package/packages/conversation-flow/vitest.config.mts +10 -0
  62. package/packages/model-bank/src/aiModels/google.ts +1 -1
  63. package/packages/types/src/message/common/metadata.ts +5 -1
  64. package/src/app/[variants]/(main)/chat/@session/features/SessionListContent/List/Item/index.tsx +3 -4
  65. package/src/app/[variants]/(main)/settings/provider/ProviderMenu/List.tsx +97 -7
  66. package/src/app/[variants]/(main)/settings/provider/features/ModelList/DisabledModels.tsx +144 -8
  67. package/src/envs/__tests__/app.test.ts +47 -13
  68. package/src/envs/app.ts +6 -0
  69. package/src/locales/default/modelProvider.ts +15 -1
  70. package/src/server/routers/async/__tests__/caller.test.ts +333 -0
  71. package/src/server/routers/async/caller.ts +2 -1
  72. package/src/server/routers/lambda/__tests__/integration/message.integration.test.ts +57 -57
  73. package/src/server/routers/lambda/message.ts +2 -2
  74. package/src/server/services/mcp/deps/checkers/ManualInstallationChecker.test.ts +162 -0
  75. package/src/server/services/mcp/deps/checkers/NpmInstallationChecker.test.ts +374 -0
  76. package/src/server/services/mcp/deps/checkers/PythonInstallationChecker.test.ts +368 -0
  77. package/src/server/services/message/__tests__/index.test.ts +4 -4
  78. package/src/server/services/message/index.ts +1 -1
  79. package/src/services/message/index.ts +2 -3
  80. package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts +8 -8
  81. package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +8 -8
  82. package/src/store/chat/slices/aiChat/actions/__tests__/helpers.ts +1 -1
  83. package/src/store/chat/slices/aiChat/actions/generateAIChatV2.ts +1 -1
  84. package/src/store/chat/slices/message/action.test.ts +7 -7
  85. package/src/store/chat/slices/message/action.ts +2 -2
  86. package/src/store/chat/slices/plugin/action.test.ts +7 -7
  87. package/src/store/chat/slices/plugin/action.ts +1 -1
  88. package/src/store/global/initialState.ts +4 -0
  89. package/src/store/global/selectors/systemStatus.ts +6 -0
  90. package/packages/context-engine/ARCHITECTURE.md +0 -425
@@ -72,7 +72,7 @@ describe('Message Router Integration Tests', () => {
72
72
  it('should create message with correct sessionId and topicId', async () => {
73
73
  const caller = messageRouter.createCaller(createTestContext(userId));
74
74
 
75
- const result = await caller.createNewMessage({
75
+ const result = await caller.createMessage({
76
76
  content: 'Test message',
77
77
  role: 'user',
78
78
  sessionId: testSessionId,
@@ -111,7 +111,7 @@ describe('Message Router Integration Tests', () => {
111
111
  })
112
112
  .returning()) as any;
113
113
 
114
- const result = await caller.createNewMessage({
114
+ const result = await caller.createMessage({
115
115
  content: 'Test message in thread',
116
116
  role: 'user',
117
117
  sessionId: testSessionId,
@@ -140,7 +140,7 @@ describe('Message Router Integration Tests', () => {
140
140
  it('should create message without topicId', async () => {
141
141
  const caller = messageRouter.createCaller(createTestContext(userId));
142
142
 
143
- const result = await caller.createNewMessage({
143
+ const result = await caller.createMessage({
144
144
  content: 'Test message without topic',
145
145
  role: 'user',
146
146
  sessionId: testSessionId,
@@ -160,7 +160,7 @@ describe('Message Router Integration Tests', () => {
160
160
  const caller = messageRouter.createCaller(createTestContext(userId));
161
161
 
162
162
  await expect(
163
- caller.createNewMessage({
163
+ caller.createMessage({
164
164
  content: 'Test message',
165
165
  role: 'user',
166
166
  sessionId: 'non-existent-session',
@@ -192,7 +192,7 @@ describe('Message Router Integration Tests', () => {
192
192
 
193
193
  // 尝试在 testSessionId 下创建消息,但使用 anotherTopic 的 ID
194
194
  await expect(
195
- caller.createNewMessage({
195
+ caller.createMessage({
196
196
  content: 'Test message',
197
197
  role: 'user',
198
198
  sessionId: testSessionId,
@@ -207,13 +207,13 @@ describe('Message Router Integration Tests', () => {
207
207
  const caller = messageRouter.createCaller(createTestContext(userId));
208
208
 
209
209
  // 创建多个消息
210
- const msg1Result = await caller.createNewMessage({
210
+ const msg1Result = await caller.createMessage({
211
211
  content: 'Message 1',
212
212
  role: 'user',
213
213
  sessionId: testSessionId,
214
214
  });
215
215
 
216
- const msg2Result = await caller.createNewMessage({
216
+ const msg2Result = await caller.createMessage({
217
217
  content: 'Message 2',
218
218
  role: 'assistant',
219
219
  sessionId: testSessionId,
@@ -228,7 +228,7 @@ describe('Message Router Integration Tests', () => {
228
228
  })
229
229
  .returning();
230
230
 
231
- await caller.createNewMessage({
231
+ await caller.createMessage({
232
232
  content: 'Message in another session',
233
233
  role: 'user',
234
234
  sessionId: anotherSession.id,
@@ -248,7 +248,7 @@ describe('Message Router Integration Tests', () => {
248
248
  const caller = messageRouter.createCaller(createTestContext(userId));
249
249
 
250
250
  // 在 topic 中创建消息
251
- const msgInTopicResult = await caller.createNewMessage({
251
+ const msgInTopicResult = await caller.createMessage({
252
252
  content: 'Message in topic',
253
253
  role: 'user',
254
254
  sessionId: testSessionId,
@@ -256,7 +256,7 @@ describe('Message Router Integration Tests', () => {
256
256
  });
257
257
 
258
258
  // 在 session 中创建消息(不在 topic 中)
259
- await caller.createNewMessage({
259
+ await caller.createMessage({
260
260
  content: 'Message without topic',
261
261
  role: 'user',
262
262
  sessionId: testSessionId,
@@ -278,7 +278,7 @@ describe('Message Router Integration Tests', () => {
278
278
 
279
279
  // 创建多个消息
280
280
  for (let i = 0; i < 5; i++) {
281
- await caller.createNewMessage({
281
+ await caller.createMessage({
282
282
  content: `Pagination test message ${i}`,
283
283
  role: 'user',
284
284
  sessionId: testSessionId,
@@ -331,7 +331,7 @@ describe('Message Router Integration Tests', () => {
331
331
  .returning();
332
332
 
333
333
  // 创建消息并设置 groupId
334
- const msg1 = await caller.createNewMessage({
334
+ const msg1 = await caller.createMessage({
335
335
  content: 'Message 1 in group',
336
336
  role: 'assistant',
337
337
  sessionId: testSessionId,
@@ -343,7 +343,7 @@ describe('Message Router Integration Tests', () => {
343
343
  .where(eq(messages.id, msg1.id));
344
344
 
345
345
  // 创建不在 group 中的消息
346
- await caller.createNewMessage({
346
+ await caller.createMessage({
347
347
  content: 'Message without group',
348
348
  role: 'user',
349
349
  sessionId: testSessionId,
@@ -363,13 +363,13 @@ describe('Message Router Integration Tests', () => {
363
363
  const caller = messageRouter.createCaller(createTestContext(userId));
364
364
 
365
365
  // 创建多个消息
366
- await caller.createNewMessage({
366
+ await caller.createMessage({
367
367
  content: 'Message 1',
368
368
  role: 'assistant',
369
369
  sessionId: testSessionId,
370
370
  });
371
371
 
372
- await caller.createNewMessage({
372
+ await caller.createMessage({
373
373
  content: 'Message 2',
374
374
  role: 'assistant',
375
375
  sessionId: testSessionId,
@@ -391,13 +391,13 @@ describe('Message Router Integration Tests', () => {
391
391
  const caller = messageRouter.createCaller(createTestContext(userId));
392
392
 
393
393
  // 创建消息
394
- const msg1Result = await caller.createNewMessage({
394
+ const msg1Result = await caller.createMessage({
395
395
  content: 'Message 1',
396
396
  role: 'user',
397
397
  sessionId: testSessionId,
398
398
  });
399
399
 
400
- const msg2Result = await caller.createNewMessage({
400
+ const msg2Result = await caller.createMessage({
401
401
  content: 'Message 2',
402
402
  role: 'user',
403
403
  sessionId: testSessionId,
@@ -419,19 +419,19 @@ describe('Message Router Integration Tests', () => {
419
419
  const caller = messageRouter.createCaller(createTestContext(userId));
420
420
 
421
421
  // 创建消息
422
- const msg1Result = await caller.createNewMessage({
422
+ const msg1Result = await caller.createMessage({
423
423
  content: 'Message 1',
424
424
  role: 'user',
425
425
  sessionId: testSessionId,
426
426
  });
427
427
 
428
- const msg2Result = await caller.createNewMessage({
428
+ const msg2Result = await caller.createMessage({
429
429
  content: 'Message 2',
430
430
  role: 'user',
431
431
  sessionId: testSessionId,
432
432
  });
433
433
 
434
- const msg3Result = await caller.createNewMessage({
434
+ const msg3Result = await caller.createMessage({
435
435
  content: 'Message 3',
436
436
  role: 'user',
437
437
  sessionId: testSessionId,
@@ -455,7 +455,7 @@ describe('Message Router Integration Tests', () => {
455
455
  it('should remove a single message', async () => {
456
456
  const caller = messageRouter.createCaller(createTestContext(userId));
457
457
 
458
- const msgResult = await caller.createNewMessage({
458
+ const msgResult = await caller.createMessage({
459
459
  content: 'Message to remove',
460
460
  role: 'user',
461
461
  sessionId: testSessionId,
@@ -475,13 +475,13 @@ describe('Message Router Integration Tests', () => {
475
475
  it('should return message list when sessionId is provided', async () => {
476
476
  const caller = messageRouter.createCaller(createTestContext(userId));
477
477
 
478
- const msg1Result = await caller.createNewMessage({
478
+ const msg1Result = await caller.createMessage({
479
479
  content: 'Message 1',
480
480
  role: 'user',
481
481
  sessionId: testSessionId,
482
482
  });
483
483
 
484
- const msg2Result = await caller.createNewMessage({
484
+ const msg2Result = await caller.createMessage({
485
485
  content: 'Message 2',
486
486
  role: 'user',
487
487
  sessionId: testSessionId,
@@ -504,7 +504,7 @@ describe('Message Router Integration Tests', () => {
504
504
  const caller = messageRouter.createCaller(createTestContext(userId));
505
505
 
506
506
  // 创建多个 session 和消息
507
- await caller.createNewMessage({
507
+ await caller.createMessage({
508
508
  content: 'Message 1',
509
509
  role: 'user',
510
510
  sessionId: testSessionId,
@@ -518,7 +518,7 @@ describe('Message Router Integration Tests', () => {
518
518
  })
519
519
  .returning();
520
520
 
521
- await caller.createNewMessage({
521
+ await caller.createMessage({
522
522
  content: 'Message 2',
523
523
  role: 'user',
524
524
  sessionId: anotherSession.id,
@@ -541,7 +541,7 @@ describe('Message Router Integration Tests', () => {
541
541
  it('should remove message query', async () => {
542
542
  const caller = messageRouter.createCaller(createTestContext(userId));
543
543
 
544
- const msgResult = await caller.createNewMessage({
544
+ const msgResult = await caller.createMessage({
545
545
  content: 'Message with query',
546
546
  role: 'user',
547
547
  sessionId: testSessionId,
@@ -575,13 +575,13 @@ describe('Message Router Integration Tests', () => {
575
575
  const caller = messageRouter.createCaller(createTestContext(userId));
576
576
 
577
577
  // 创建多个消息
578
- await caller.createNewMessage({
578
+ await caller.createMessage({
579
579
  content: 'Message 1',
580
580
  role: 'user',
581
581
  sessionId: testSessionId,
582
582
  });
583
583
 
584
- await caller.createNewMessage({
584
+ await caller.createMessage({
585
585
  content: 'Message 2',
586
586
  role: 'assistant',
587
587
  sessionId: testSessionId,
@@ -605,7 +605,7 @@ describe('Message Router Integration Tests', () => {
605
605
  const caller = messageRouter.createCaller(createTestContext(userId));
606
606
 
607
607
  // 在 topic 中创建消息
608
- await caller.createNewMessage({
608
+ await caller.createMessage({
609
609
  content: 'Message in topic',
610
610
  role: 'user',
611
611
  sessionId: testSessionId,
@@ -613,7 +613,7 @@ describe('Message Router Integration Tests', () => {
613
613
  });
614
614
 
615
615
  // 在 session 中创建消息(不在 topic 中)
616
- const msgOutsideTopicResult = await caller.createNewMessage({
616
+ const msgOutsideTopicResult = await caller.createMessage({
617
617
  content: 'Message outside topic',
618
618
  role: 'user',
619
619
  sessionId: testSessionId,
@@ -651,7 +651,7 @@ describe('Message Router Integration Tests', () => {
651
651
  .returning();
652
652
 
653
653
  // 创建消息并设置 groupId
654
- const msg1 = await caller.createNewMessage({
654
+ const msg1 = await caller.createMessage({
655
655
  content: 'Message 1 in group',
656
656
  role: 'assistant',
657
657
  sessionId: testSessionId,
@@ -677,7 +677,7 @@ describe('Message Router Integration Tests', () => {
677
677
  it('should update message content', async () => {
678
678
  const caller = messageRouter.createCaller(createTestContext(userId));
679
679
 
680
- const result = await caller.createNewMessage({
680
+ const result = await caller.createMessage({
681
681
  content: 'Original content',
682
682
  role: 'user',
683
683
  sessionId: testSessionId,
@@ -701,13 +701,13 @@ describe('Message Router Integration Tests', () => {
701
701
  it('should update message and return message list when sessionId is provided', async () => {
702
702
  const caller = messageRouter.createCaller(createTestContext(userId));
703
703
 
704
- const msg1 = await caller.createNewMessage({
704
+ const msg1 = await caller.createMessage({
705
705
  content: 'Message 1',
706
706
  role: 'user',
707
707
  sessionId: testSessionId,
708
708
  });
709
709
 
710
- const msg2 = await caller.createNewMessage({
710
+ const msg2 = await caller.createMessage({
711
711
  content: 'Message 2',
712
712
  role: 'user',
713
713
  sessionId: testSessionId,
@@ -733,13 +733,13 @@ describe('Message Router Integration Tests', () => {
733
733
  it('should search messages by keyword', async () => {
734
734
  const caller = messageRouter.createCaller(createTestContext(userId));
735
735
 
736
- await caller.createNewMessage({
736
+ await caller.createMessage({
737
737
  content: 'This is a test message about TypeScript',
738
738
  role: 'user',
739
739
  sessionId: testSessionId,
740
740
  });
741
741
 
742
- await caller.createNewMessage({
742
+ await caller.createMessage({
743
743
  content: 'Another message about JavaScript',
744
744
  role: 'user',
745
745
  sessionId: testSessionId,
@@ -758,7 +758,7 @@ describe('Message Router Integration Tests', () => {
758
758
  it('should update message plugin state', async () => {
759
759
  const caller = messageRouter.createCaller(createTestContext(userId));
760
760
 
761
- const msg = await caller.createNewMessage({
761
+ const msg = await caller.createMessage({
762
762
  content: 'Message with plugin',
763
763
  role: 'assistant',
764
764
  sessionId: testSessionId,
@@ -794,7 +794,7 @@ describe('Message Router Integration Tests', () => {
794
794
  it('should update message RAG information', async () => {
795
795
  const caller = messageRouter.createCaller(createTestContext(userId));
796
796
 
797
- const msg = await caller.createNewMessage({
797
+ const msg = await caller.createMessage({
798
798
  content: 'Message with RAG',
799
799
  role: 'assistant',
800
800
  sessionId: testSessionId,
@@ -844,13 +844,13 @@ describe('Message Router Integration Tests', () => {
844
844
  it('should return message list when sessionId is provided', async () => {
845
845
  const caller = messageRouter.createCaller(createTestContext(userId));
846
846
 
847
- const msg1 = await caller.createNewMessage({
847
+ const msg1 = await caller.createMessage({
848
848
  content: 'Message 1',
849
849
  role: 'assistant',
850
850
  sessionId: testSessionId,
851
851
  });
852
852
 
853
- await caller.createNewMessage({
853
+ await caller.createMessage({
854
854
  content: 'Message 2',
855
855
  role: 'assistant',
856
856
  sessionId: testSessionId,
@@ -895,7 +895,7 @@ describe('Message Router Integration Tests', () => {
895
895
  it('should update message metadata', async () => {
896
896
  const caller = messageRouter.createCaller(createTestContext(userId));
897
897
 
898
- const msg = await caller.createNewMessage({
898
+ const msg = await caller.createMessage({
899
899
  content: 'Message with metadata',
900
900
  role: 'user',
901
901
  sessionId: testSessionId,
@@ -921,7 +921,7 @@ describe('Message Router Integration Tests', () => {
921
921
  it('should update plugin error state', async () => {
922
922
  const caller = messageRouter.createCaller(createTestContext(userId));
923
923
 
924
- const msg = await caller.createNewMessage({
924
+ const msg = await caller.createMessage({
925
925
  content: 'Message with plugin error',
926
926
  role: 'assistant',
927
927
  sessionId: testSessionId,
@@ -953,7 +953,7 @@ describe('Message Router Integration Tests', () => {
953
953
  it('should return message list when sessionId is provided', async () => {
954
954
  const caller = messageRouter.createCaller(createTestContext(userId));
955
955
 
956
- const msg1 = await caller.createNewMessage({
956
+ const msg1 = await caller.createMessage({
957
957
  content: 'Message 1',
958
958
  role: 'assistant',
959
959
  sessionId: testSessionId,
@@ -968,7 +968,7 @@ describe('Message Router Integration Tests', () => {
968
968
  type: 'default',
969
969
  });
970
970
 
971
- await caller.createNewMessage({
971
+ await caller.createMessage({
972
972
  content: 'Message 2',
973
973
  role: 'assistant',
974
974
  sessionId: testSessionId,
@@ -990,7 +990,7 @@ describe('Message Router Integration Tests', () => {
990
990
  it('should update plugin state', async () => {
991
991
  const caller = messageRouter.createCaller(createTestContext(userId));
992
992
 
993
- const msg = await caller.createNewMessage({
993
+ const msg = await caller.createMessage({
994
994
  content: 'Message with plugin state',
995
995
  role: 'assistant',
996
996
  sessionId: testSessionId,
@@ -1019,7 +1019,7 @@ describe('Message Router Integration Tests', () => {
1019
1019
  it('should update TTS information', async () => {
1020
1020
  const caller = messageRouter.createCaller(createTestContext(userId));
1021
1021
 
1022
- const msg = await caller.createNewMessage({
1022
+ const msg = await caller.createMessage({
1023
1023
  content: 'Message with TTS',
1024
1024
  role: 'assistant',
1025
1025
  sessionId: testSessionId,
@@ -1058,7 +1058,7 @@ describe('Message Router Integration Tests', () => {
1058
1058
  it('should delete TTS when value is false', async () => {
1059
1059
  const caller = messageRouter.createCaller(createTestContext(userId));
1060
1060
 
1061
- const msg = await caller.createNewMessage({
1061
+ const msg = await caller.createMessage({
1062
1062
  content: 'Message with TTS to delete',
1063
1063
  role: 'assistant',
1064
1064
  sessionId: testSessionId,
@@ -1103,7 +1103,7 @@ describe('Message Router Integration Tests', () => {
1103
1103
  it('should update translation information', async () => {
1104
1104
  const caller = messageRouter.createCaller(createTestContext(userId));
1105
1105
 
1106
- const msg = await caller.createNewMessage({
1106
+ const msg = await caller.createMessage({
1107
1107
  content: 'Hello world',
1108
1108
  role: 'user',
1109
1109
  sessionId: testSessionId,
@@ -1131,7 +1131,7 @@ describe('Message Router Integration Tests', () => {
1131
1131
  it('should delete translation when value is false', async () => {
1132
1132
  const caller = messageRouter.createCaller(createTestContext(userId));
1133
1133
 
1134
- const msg = await caller.createNewMessage({
1134
+ const msg = await caller.createMessage({
1135
1135
  content: 'Hello world',
1136
1136
  role: 'user',
1137
1137
  sessionId: testSessionId,
@@ -1166,13 +1166,13 @@ describe('Message Router Integration Tests', () => {
1166
1166
  const caller = messageRouter.createCaller(createTestContext(userId));
1167
1167
 
1168
1168
  // 创建一些消息
1169
- await caller.createNewMessage({
1169
+ await caller.createMessage({
1170
1170
  content: 'Message 1',
1171
1171
  role: 'user',
1172
1172
  sessionId: testSessionId,
1173
1173
  });
1174
1174
 
1175
- await caller.createNewMessage({
1175
+ await caller.createMessage({
1176
1176
  content: 'Message 2',
1177
1177
  role: 'assistant',
1178
1178
  sessionId: testSessionId,
@@ -1190,7 +1190,7 @@ describe('Message Router Integration Tests', () => {
1190
1190
  const caller = messageRouter.createCaller(createTestContext(userId));
1191
1191
 
1192
1192
  // 创建带有模型信息的消息
1193
- const msg = await caller.createNewMessage({
1193
+ const msg = await caller.createMessage({
1194
1194
  content: 'Message from AI',
1195
1195
  role: 'assistant',
1196
1196
  sessionId: testSessionId,
@@ -1211,13 +1211,13 @@ describe('Message Router Integration Tests', () => {
1211
1211
  const caller = messageRouter.createCaller(createTestContext(userId));
1212
1212
 
1213
1213
  // 创建消息
1214
- await caller.createNewMessage({
1214
+ await caller.createMessage({
1215
1215
  content: 'Message 1',
1216
1216
  role: 'user',
1217
1217
  sessionId: testSessionId,
1218
1218
  });
1219
1219
 
1220
- await caller.createNewMessage({
1220
+ await caller.createMessage({
1221
1221
  content: 'Message 2',
1222
1222
  role: 'assistant',
1223
1223
  sessionId: testSessionId,
@@ -1231,7 +1231,7 @@ describe('Message Router Integration Tests', () => {
1231
1231
  it('should count messages with date range', async () => {
1232
1232
  const caller = messageRouter.createCaller(createTestContext(userId));
1233
1233
 
1234
- await caller.createNewMessage({
1234
+ await caller.createMessage({
1235
1235
  content: 'Message 1',
1236
1236
  role: 'user',
1237
1237
  sessionId: testSessionId,
@@ -1251,7 +1251,7 @@ describe('Message Router Integration Tests', () => {
1251
1251
  it('should count words', async () => {
1252
1252
  const caller = messageRouter.createCaller(createTestContext(userId));
1253
1253
 
1254
- await caller.createNewMessage({
1254
+ await caller.createMessage({
1255
1255
  content: 'Hello world',
1256
1256
  role: 'user',
1257
1257
  sessionId: testSessionId,
@@ -1265,7 +1265,7 @@ describe('Message Router Integration Tests', () => {
1265
1265
  it('should count words with date range', async () => {
1266
1266
  const caller = messageRouter.createCaller(createTestContext(userId));
1267
1267
 
1268
- await caller.createNewMessage({
1268
+ await caller.createMessage({
1269
1269
  content: 'Hello world test message',
1270
1270
  role: 'user',
1271
1271
  sessionId: testSessionId,
@@ -54,11 +54,11 @@ export const messageRouter = router({
54
54
  return ctx.messageModel.countWords(input);
55
55
  }),
56
56
 
57
- createNewMessage: messageProcedure
57
+ createMessage: messageProcedure
58
58
  .input(CreateNewMessageParamsSchema.extend({ useGroup: z.boolean().optional() }))
59
59
  .mutation(async ({ input, ctx }) => {
60
60
  const { useGroup, ...params } = input;
61
- return ctx.messageService.createNewMessage(params as any, { useGroup });
61
+ return ctx.messageService.createMessage(params as any, { useGroup });
62
62
  }),
63
63
 
64
64
  getHeatmaps: messageProcedure.query(async ({ ctx }) => {
@@ -0,0 +1,162 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { ManualInstallationChecker } from './ManualInstallationChecker';
4
+
5
+ describe('ManualInstallationChecker', () => {
6
+ let checker: ManualInstallationChecker;
7
+
8
+ beforeEach(() => {
9
+ checker = new ManualInstallationChecker();
10
+ });
11
+
12
+ describe('checkPackageInstalled', () => {
13
+ it('should always return not installed for manual packages', async () => {
14
+ const result = await checker.checkPackageInstalled({ packageName: 'manual-package' });
15
+
16
+ expect(result).toEqual({
17
+ installed: false,
18
+ packageName: 'manual-package',
19
+ });
20
+ });
21
+
22
+ it('should handle packageName with repository URL', async () => {
23
+ const result = await checker.checkPackageInstalled({
24
+ packageName: 'my-custom-tool',
25
+ repositoryUrlToClone: 'https://github.com/user/repo.git',
26
+ });
27
+
28
+ expect(result.installed).toBe(false);
29
+ expect(result.packageName).toBe('my-custom-tool');
30
+ });
31
+
32
+ it('should use repositoryUrlToClone as packageName when packageName is not provided', async () => {
33
+ const result = await checker.checkPackageInstalled({
34
+ repositoryUrlToClone: 'https://github.com/user/custom-tool.git',
35
+ });
36
+
37
+ expect(result).toEqual({
38
+ installed: false,
39
+ packageName: 'https://github.com/user/custom-tool.git',
40
+ });
41
+ });
42
+
43
+ it('should return empty packageName when neither packageName nor repositoryUrlToClone provided', async () => {
44
+ const result = await checker.checkPackageInstalled({});
45
+
46
+ expect(result).toEqual({
47
+ installed: false,
48
+ packageName: '',
49
+ });
50
+ });
51
+
52
+ it('should handle undefined packageName', async () => {
53
+ const result = await checker.checkPackageInstalled({ packageName: undefined });
54
+
55
+ expect(result).toEqual({
56
+ installed: false,
57
+ packageName: '',
58
+ });
59
+ });
60
+
61
+ it('should handle empty string packageName', async () => {
62
+ const result = await checker.checkPackageInstalled({ packageName: '' });
63
+
64
+ expect(result).toEqual({
65
+ installed: false,
66
+ packageName: '',
67
+ });
68
+ });
69
+
70
+ it('should handle empty string repositoryUrlToClone as fallback', async () => {
71
+ const result = await checker.checkPackageInstalled({
72
+ packageName: '',
73
+ repositoryUrlToClone: '',
74
+ });
75
+
76
+ expect(result).toEqual({
77
+ installed: false,
78
+ packageName: '',
79
+ });
80
+ });
81
+
82
+ it('should prioritize packageName over repositoryUrlToClone', async () => {
83
+ const result = await checker.checkPackageInstalled({
84
+ packageName: 'my-tool',
85
+ repositoryUrlToClone: 'https://github.com/user/repo.git',
86
+ });
87
+
88
+ expect(result.packageName).toBe('my-tool');
89
+ expect(result.installed).toBe(false);
90
+ });
91
+
92
+ it('should handle complex package names', async () => {
93
+ const result = await checker.checkPackageInstalled({
94
+ packageName: '@scope/package-name-with-special.chars_123',
95
+ });
96
+
97
+ expect(result).toEqual({
98
+ installed: false,
99
+ packageName: '@scope/package-name-with-special.chars_123',
100
+ });
101
+ });
102
+
103
+ it('should handle SSH repository URLs', async () => {
104
+ const result = await checker.checkPackageInstalled({
105
+ repositoryUrlToClone: 'git@github.com:user/repo.git',
106
+ });
107
+
108
+ expect(result).toEqual({
109
+ installed: false,
110
+ packageName: 'git@github.com:user/repo.git',
111
+ });
112
+ });
113
+
114
+ it('should handle local file paths', async () => {
115
+ const result = await checker.checkPackageInstalled({
116
+ packageName: '/usr/local/custom-tool',
117
+ });
118
+
119
+ expect(result).toEqual({
120
+ installed: false,
121
+ packageName: '/usr/local/custom-tool',
122
+ });
123
+ });
124
+
125
+ it('should handle Windows-style paths', async () => {
126
+ const result = await checker.checkPackageInstalled({
127
+ packageName: 'C:\\Program Files\\CustomTool',
128
+ });
129
+
130
+ expect(result).toEqual({
131
+ installed: false,
132
+ packageName: 'C:\\Program Files\\CustomTool',
133
+ });
134
+ });
135
+
136
+ it('should handle package names with unicode characters', async () => {
137
+ const result = await checker.checkPackageInstalled({
138
+ packageName: 'my-tool-日本語',
139
+ });
140
+
141
+ expect(result).toEqual({
142
+ installed: false,
143
+ packageName: 'my-tool-日本語',
144
+ });
145
+ });
146
+
147
+ it('should always return false for installed regardless of input', async () => {
148
+ const testCases = [
149
+ { packageName: 'package1' },
150
+ { packageName: 'package2', repositoryUrlToClone: 'https://example.com/repo.git' },
151
+ { repositoryUrlToClone: 'https://example.com/repo2.git' },
152
+ {},
153
+ { packageName: '' },
154
+ ];
155
+
156
+ for (const testCase of testCases) {
157
+ const result = await checker.checkPackageInstalled(testCase);
158
+ expect(result.installed).toBe(false);
159
+ }
160
+ });
161
+ });
162
+ });