@lobehub/lobehub 2.0.0-next.115 → 2.0.0-next.116

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 (24) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/changelog/v1.json +9 -0
  3. package/package.json +1 -1
  4. package/packages/context-engine/src/processors/MessageContent.ts +100 -6
  5. package/packages/context-engine/src/processors/__tests__/MessageContent.test.ts +239 -0
  6. package/packages/fetch-sse/src/fetchSSE.ts +30 -0
  7. package/packages/model-runtime/src/core/contextBuilders/google.test.ts +78 -24
  8. package/packages/model-runtime/src/core/contextBuilders/google.ts +10 -2
  9. package/packages/model-runtime/src/core/streams/google/google-ai.test.ts +451 -20
  10. package/packages/model-runtime/src/core/streams/google/index.ts +113 -3
  11. package/packages/model-runtime/src/core/streams/protocol.ts +19 -0
  12. package/packages/types/src/message/common/base.ts +26 -0
  13. package/packages/types/src/message/common/metadata.ts +7 -0
  14. package/packages/utils/src/index.ts +1 -0
  15. package/packages/utils/src/multimodalContent.ts +25 -0
  16. package/src/components/Thinking/index.tsx +3 -3
  17. package/src/features/ChatList/Messages/Assistant/DisplayContent.tsx +44 -0
  18. package/src/features/ChatList/Messages/Assistant/MessageBody.tsx +96 -0
  19. package/src/features/ChatList/Messages/Assistant/Reasoning/index.tsx +26 -13
  20. package/src/features/ChatList/Messages/Assistant/index.tsx +8 -6
  21. package/src/features/ChatList/Messages/Default.tsx +4 -7
  22. package/src/features/ChatList/components/RichContentRenderer.tsx +35 -0
  23. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +244 -17
  24. package/src/features/ChatList/Messages/Assistant/MessageContent.tsx +0 -78
@@ -33,7 +33,7 @@ describe('google contextBuilders', () => {
33
33
 
34
34
  const result = await buildGooglePart(content);
35
35
 
36
- expect(result).toEqual({ text: 'Hello' });
36
+ expect(result).toEqual({ text: 'Hello', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE });
37
37
  });
38
38
 
39
39
  it('should handle thinking type messages', async () => {
@@ -71,6 +71,7 @@ describe('google contextBuilders', () => {
71
71
  data: 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==',
72
72
  mimeType: 'image/png',
73
73
  },
74
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
74
75
  });
75
76
  });
76
77
 
@@ -101,6 +102,7 @@ describe('google contextBuilders', () => {
101
102
  data: mockBase64,
102
103
  mimeType: 'image/png',
103
104
  },
105
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
104
106
  });
105
107
 
106
108
  expect(imageToBase64Module.imageUrlToBase64).toHaveBeenCalledWith(imageUrl);
@@ -144,6 +146,7 @@ describe('google contextBuilders', () => {
144
146
  data: 'mockVideoBase64Data',
145
147
  mimeType: 'video/mp4',
146
148
  },
149
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
147
150
  });
148
151
  });
149
152
  });
@@ -158,7 +161,7 @@ describe('google contextBuilders', () => {
158
161
  const converted = await buildGoogleMessage(message);
159
162
 
160
163
  expect(converted).toEqual({
161
- parts: [{ text: 'Hello' }],
164
+ parts: [{ text: 'Hello', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
162
165
  role: 'model',
163
166
  });
164
167
  });
@@ -172,7 +175,7 @@ describe('google contextBuilders', () => {
172
175
  const converted = await buildGoogleMessage(message);
173
176
 
174
177
  expect(converted).toEqual({
175
- parts: [{ text: 'Hi' }],
178
+ parts: [{ text: 'Hi', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
176
179
  role: 'user',
177
180
  });
178
181
  });
@@ -196,8 +199,11 @@ describe('google contextBuilders', () => {
196
199
 
197
200
  expect(converted).toEqual({
198
201
  parts: [
199
- { text: 'Check this image:' },
200
- { inlineData: { data: '...', mimeType: 'image/png' } },
202
+ { text: 'Check this image:', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE },
203
+ {
204
+ inlineData: { data: '...', mimeType: 'image/png' },
205
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
206
+ },
201
207
  ],
202
208
  role: 'user',
203
209
  });
@@ -334,10 +340,18 @@ describe('google contextBuilders', () => {
334
340
 
335
341
  expect(contents).toEqual([
336
342
  {
337
- parts: [{ text: '<plugins>Web Browsing plugin available</plugins>' }],
343
+ parts: [
344
+ {
345
+ text: '<plugins>Web Browsing plugin available</plugins>',
346
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
347
+ },
348
+ ],
349
+ role: 'user',
350
+ },
351
+ {
352
+ parts: [{ text: '杭州天气如何', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
338
353
  role: 'user',
339
354
  },
340
- { parts: [{ text: '杭州天气如何' }], role: 'user' },
341
355
  {
342
356
  parts: [
343
357
  {
@@ -421,7 +435,7 @@ describe('google contextBuilders', () => {
421
435
 
422
436
  expect(contents).toEqual([
423
437
  {
424
- parts: [{ text: '杭州天气如何' }],
438
+ parts: [{ text: '杭州天气如何', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
425
439
  role: 'user',
426
440
  },
427
441
  {
@@ -507,7 +521,7 @@ describe('google contextBuilders', () => {
507
521
 
508
522
  expect(contents).toEqual([
509
523
  {
510
- parts: [{ text: 'First question' }],
524
+ parts: [{ text: 'First question', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
511
525
  role: 'user',
512
526
  },
513
527
  {
@@ -534,7 +548,7 @@ describe('google contextBuilders', () => {
534
548
  role: 'user',
535
549
  },
536
550
  {
537
- parts: [{ text: 'Second question' }],
551
+ parts: [{ text: 'Second question', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
538
552
  role: 'user',
539
553
  },
540
554
  {
@@ -604,11 +618,16 @@ describe('google contextBuilders', () => {
604
618
 
605
619
  expect(contents).toEqual([
606
620
  {
607
- parts: [{ text: '<plugins>Web Browsing plugin available</plugins>' }],
621
+ parts: [
622
+ {
623
+ text: '<plugins>Web Browsing plugin available</plugins>',
624
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
625
+ },
626
+ ],
608
627
  role: 'user',
609
628
  },
610
629
  {
611
- parts: [{ text: '杭州天气如何' }],
630
+ parts: [{ text: '杭州天气如何', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
612
631
  role: 'user',
613
632
  },
614
633
  {
@@ -635,7 +654,7 @@ describe('google contextBuilders', () => {
635
654
  role: 'user',
636
655
  },
637
656
  {
638
- parts: [{ text: 'Please try again' }],
657
+ parts: [{ text: 'Please try again', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
639
658
  role: 'user',
640
659
  },
641
660
  ]);
@@ -651,7 +670,7 @@ describe('google contextBuilders', () => {
651
670
  const converted = await buildGoogleMessage(message);
652
671
 
653
672
  expect(converted).toEqual({
654
- parts: [{ text: '' }],
673
+ parts: [{ text: '', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
655
674
  role: 'user',
656
675
  });
657
676
  });
@@ -690,7 +709,12 @@ describe('google contextBuilders', () => {
690
709
  const contents = await buildGoogleMessages(messages);
691
710
 
692
711
  expect(contents).toHaveLength(1);
693
- expect(contents).toEqual([{ parts: [{ text: 'Hello' }], role: 'user' }]);
712
+ expect(contents).toEqual([
713
+ {
714
+ parts: [{ text: 'Hello', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
715
+ role: 'user',
716
+ },
717
+ ]);
694
718
  });
695
719
 
696
720
  it('should not modify the length if model is gemini-1.5-pro', async () => {
@@ -703,8 +727,14 @@ describe('google contextBuilders', () => {
703
727
 
704
728
  expect(contents).toHaveLength(2);
705
729
  expect(contents).toEqual([
706
- { parts: [{ text: 'Hello' }], role: 'user' },
707
- { parts: [{ text: 'Hi' }], role: 'model' },
730
+ {
731
+ parts: [{ text: 'Hello', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
732
+ role: 'user',
733
+ },
734
+ {
735
+ parts: [{ text: 'Hi', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
736
+ role: 'model',
737
+ },
708
738
  ]);
709
739
  });
710
740
 
@@ -730,7 +760,13 @@ describe('google contextBuilders', () => {
730
760
  expect(contents).toHaveLength(1);
731
761
  expect(contents).toEqual([
732
762
  {
733
- parts: [{ text: 'Hello' }, { inlineData: { data: '...', mimeType: 'image/png' } }],
763
+ parts: [
764
+ { text: 'Hello', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE },
765
+ {
766
+ inlineData: { data: '...', mimeType: 'image/png' },
767
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
768
+ },
769
+ ],
734
770
  role: 'user',
735
771
  },
736
772
  ]);
@@ -801,8 +837,14 @@ describe('google contextBuilders', () => {
801
837
 
802
838
  expect(contents).toHaveLength(2);
803
839
  expect(contents).toEqual([
804
- { parts: [{ text: 'Hello' }], role: 'user' },
805
- { parts: [{ text: 'Hi' }], role: 'model' },
840
+ {
841
+ parts: [{ text: 'Hello', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
842
+ role: 'user',
843
+ },
844
+ {
845
+ parts: [{ text: 'Hi', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
846
+ role: 'model',
847
+ },
806
848
  ]);
807
849
  });
808
850
 
@@ -817,8 +859,14 @@ describe('google contextBuilders', () => {
817
859
 
818
860
  expect(contents).toHaveLength(2);
819
861
  expect(contents).toEqual([
820
- { parts: [{ text: 'Hello' }], role: 'user' },
821
- { parts: [{ text: 'Hi' }], role: 'model' },
862
+ {
863
+ parts: [{ text: 'Hello', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
864
+ role: 'user',
865
+ },
866
+ {
867
+ parts: [{ text: 'Hi', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
868
+ role: 'model',
869
+ },
822
870
  ]);
823
871
  });
824
872
 
@@ -857,8 +905,14 @@ describe('google contextBuilders', () => {
857
905
  const contents = await buildGoogleMessages(messages);
858
906
 
859
907
  expect(contents).toEqual([
860
- { parts: [{ text: 'system prompt' }], role: 'user' },
861
- { parts: [{ text: 'LobeChat 最新版本' }], role: 'user' },
908
+ {
909
+ parts: [{ text: 'system prompt', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
910
+ role: 'user',
911
+ },
912
+ {
913
+ parts: [{ text: 'LobeChat 最新版本', thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }],
914
+ role: 'user',
915
+ },
862
916
  {
863
917
  parts: [
864
918
  {
@@ -29,7 +29,10 @@ export const buildGooglePart = async (
29
29
  }
30
30
 
31
31
  case 'text': {
32
- return { text: content.text };
32
+ return {
33
+ text: content.text,
34
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
35
+ };
33
36
  }
34
37
 
35
38
  case 'image_url': {
@@ -42,6 +45,7 @@ export const buildGooglePart = async (
42
45
 
43
46
  return {
44
47
  inlineData: { data: base64, mimeType: mimeType || 'image/png' },
48
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
45
49
  };
46
50
  }
47
51
 
@@ -50,6 +54,7 @@ export const buildGooglePart = async (
50
54
 
51
55
  return {
52
56
  inlineData: { data: base64, mimeType },
57
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
53
58
  };
54
59
  }
55
60
 
@@ -66,6 +71,7 @@ export const buildGooglePart = async (
66
71
 
67
72
  return {
68
73
  inlineData: { data: base64, mimeType: mimeType || 'video/mp4' },
74
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
69
75
  };
70
76
  }
71
77
 
@@ -76,6 +82,7 @@ export const buildGooglePart = async (
76
82
 
77
83
  return {
78
84
  inlineData: { data: base64, mimeType },
85
+ thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE,
79
86
  };
80
87
  }
81
88
 
@@ -126,7 +133,8 @@ export const buildGoogleMessage = async (
126
133
  }
127
134
 
128
135
  const getParts = async () => {
129
- if (typeof content === 'string') return [{ text: content }];
136
+ if (typeof content === 'string')
137
+ return [{ text: content, thoughtSignature: GEMINI_MAGIC_THOUGHT_SIGNATURE }];
130
138
 
131
139
  const parts = await Promise.all(content.map(async (c) => await buildGooglePart(c)));
132
140
  return parts.filter(Boolean) as Part[];