@lobehub/lobehub 2.0.0-next.115 → 2.0.0-next.117
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/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/package.json +1 -1
- package/packages/context-engine/src/processors/MessageContent.ts +100 -6
- package/packages/context-engine/src/processors/__tests__/MessageContent.test.ts +239 -0
- package/packages/fetch-sse/src/fetchSSE.ts +30 -0
- package/packages/model-bank/src/aiModels/bedrock.ts +30 -2
- package/packages/model-runtime/src/const/models.ts +62 -24
- package/packages/model-runtime/src/core/contextBuilders/anthropic.ts +14 -0
- package/packages/model-runtime/src/core/contextBuilders/google.test.ts +78 -24
- package/packages/model-runtime/src/core/contextBuilders/google.ts +10 -2
- package/packages/model-runtime/src/core/parameterResolver.test.ts +34 -50
- package/packages/model-runtime/src/core/parameterResolver.ts +0 -41
- package/packages/model-runtime/src/core/streams/google/google-ai.test.ts +451 -20
- package/packages/model-runtime/src/core/streams/google/index.ts +113 -3
- package/packages/model-runtime/src/core/streams/protocol.ts +19 -0
- package/packages/model-runtime/src/index.ts +1 -0
- package/packages/model-runtime/src/providers/anthropic/index.ts +20 -32
- package/packages/model-runtime/src/providers/anthropic/resolveMaxTokens.ts +35 -0
- package/packages/model-runtime/src/providers/bedrock/index.test.ts +5 -7
- package/packages/model-runtime/src/providers/bedrock/index.ts +50 -11
- package/packages/types/src/message/common/base.ts +26 -0
- package/packages/types/src/message/common/metadata.ts +7 -0
- package/packages/utils/src/index.ts +1 -0
- package/packages/utils/src/multimodalContent.ts +25 -0
- package/src/components/Thinking/index.tsx +3 -3
- package/src/features/ChatList/Messages/Assistant/DisplayContent.tsx +44 -0
- package/src/features/ChatList/Messages/Assistant/MessageBody.tsx +96 -0
- package/src/features/ChatList/Messages/Assistant/Reasoning/index.tsx +26 -13
- package/src/features/ChatList/Messages/Assistant/index.tsx +8 -6
- package/src/features/ChatList/Messages/Default.tsx +4 -7
- package/src/features/ChatList/components/RichContentRenderer.tsx +35 -0
- package/src/store/agent/slices/chat/selectors/chatConfig.ts +4 -3
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +244 -17
- package/packages/const/src/models.ts +0 -93
- package/src/features/ChatList/Messages/Assistant/MessageContent.tsx +0 -78
|
@@ -5,14 +5,14 @@ export const systemToUserModels = new Set([
|
|
|
5
5
|
'o1-mini-2024-09-12',
|
|
6
6
|
]);
|
|
7
7
|
|
|
8
|
-
// TODO:
|
|
8
|
+
// TODO: temporary implementation, needs to be refactored into model card display configuration
|
|
9
9
|
export const disableStreamModels = new Set([
|
|
10
10
|
'o1',
|
|
11
11
|
'o1-2024-12-17',
|
|
12
12
|
'o1-pro',
|
|
13
13
|
'o1-pro-2025-03-19',
|
|
14
14
|
/*
|
|
15
|
-
|
|
15
|
+
Official documentation shows no support, but actual testing shows Streaming is supported, temporarily commented out
|
|
16
16
|
'o3-pro',
|
|
17
17
|
'o3-pro-2025-06-10',
|
|
18
18
|
*/
|
|
@@ -38,30 +38,68 @@ export const responsesAPIModels = new Set([
|
|
|
38
38
|
'gpt-5-codex',
|
|
39
39
|
'gpt-5-pro',
|
|
40
40
|
'gpt-5-pro-2025-10-06',
|
|
41
|
+
'gpt-5.1-codex',
|
|
42
|
+
'gpt-5.1-codex-mini',
|
|
41
43
|
]);
|
|
42
44
|
|
|
43
45
|
/**
|
|
44
|
-
* models support context caching
|
|
46
|
+
* Regex patterns for models that support context caching (3.5+)
|
|
45
47
|
*/
|
|
46
|
-
export const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
]
|
|
48
|
+
export const contextCachingModelPatterns: RegExp[] = [
|
|
49
|
+
// Claude 4.5 series - Anthropic API
|
|
50
|
+
/^claude-(opus|sonnet|haiku)-4-5-/,
|
|
51
|
+
// Claude 4 series - Anthropic API
|
|
52
|
+
/^claude-(opus|sonnet)-4-/,
|
|
53
|
+
// Claude 3.7 - Anthropic API
|
|
54
|
+
/^claude-3-7-sonnet-/,
|
|
55
|
+
// Claude 3.5 series - Anthropic API
|
|
56
|
+
/^claude-3-5-(sonnet|haiku)-/,
|
|
57
|
+
// OpenRouter format (3.5+)
|
|
58
|
+
/^anthropic\/claude-(opus|sonnet|haiku)-(4\.5|4|3\.7|3\.5)/,
|
|
59
|
+
/^anthropic\/claude-(4\.5|4|3\.7|3\.5)-(opus|sonnet|haiku)/,
|
|
60
|
+
// AWS Bedrock format: [region.]anthropic.claude-xxx
|
|
61
|
+
/anthropic\.claude-(opus|sonnet|haiku)-(4-5|4|3-7|3-5)-/,
|
|
62
|
+
];
|
|
59
63
|
|
|
60
|
-
export const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
]
|
|
64
|
+
export const isContextCachingModel = (model: string): boolean => {
|
|
65
|
+
return contextCachingModelPatterns.some((pattern) => pattern.test(model));
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Regex patterns for Claude models that support thinking with tools (3.7+)
|
|
70
|
+
*/
|
|
71
|
+
export const thinkingWithToolClaudeModelPatterns: RegExp[] = [
|
|
72
|
+
// Claude 4.5 series - Anthropic API
|
|
73
|
+
/^claude-(opus|sonnet|haiku)-4-5-/,
|
|
74
|
+
// Claude 4 series - Anthropic API
|
|
75
|
+
/^claude-(opus|sonnet)-4-/,
|
|
76
|
+
// Claude 3.7 - Anthropic API
|
|
77
|
+
/^claude-3-7-sonnet-/,
|
|
78
|
+
// OpenRouter format (3.7+)
|
|
79
|
+
/^anthropic\/claude-(opus|sonnet|haiku)-(4\.5|4|3\.7)/,
|
|
80
|
+
/^anthropic\/claude-(4\.5|4|3\.7)-(opus|sonnet|haiku)/,
|
|
81
|
+
// AWS Bedrock format: [region.]anthropic.claude-xxx
|
|
82
|
+
/anthropic\.claude-(opus|sonnet|haiku)-(4-5|4|3-7)-/,
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
export const isThinkingWithToolClaudeModel = (model: string): boolean => {
|
|
86
|
+
return thinkingWithToolClaudeModelPatterns.some((pattern) => pattern.test(model));
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Regex patterns for Claude 4+ models that have temperature/top_p parameter conflict
|
|
91
|
+
* (cannot set both temperature and top_p at the same time)
|
|
92
|
+
*/
|
|
93
|
+
export const temperatureTopPConflictModelPatterns: RegExp[] = [
|
|
94
|
+
// Claude 4+ series - Anthropic API (4, 4.1, 4.5)
|
|
95
|
+
/^claude-(opus|sonnet|haiku)-4/,
|
|
96
|
+
// OpenRouter format
|
|
97
|
+
/^anthropic\/claude-(opus|sonnet|haiku)-(4\.5|4\.1|4)/,
|
|
98
|
+
/^anthropic\/claude-(4\.5|4\.1|4)-(opus|sonnet|haiku)/,
|
|
99
|
+
// AWS Bedrock format: [region.]anthropic.claude-xxx
|
|
100
|
+
/anthropic\.claude-(opus|sonnet|haiku)-4/,
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
export const hasTemperatureTopPConflict = (model: string): boolean => {
|
|
104
|
+
return temperatureTopPConflictModelPatterns.some((pattern) => pattern.test(model));
|
|
105
|
+
};
|
|
@@ -223,3 +223,17 @@ export const buildAnthropicTools = (
|
|
|
223
223
|
}),
|
|
224
224
|
);
|
|
225
225
|
};
|
|
226
|
+
|
|
227
|
+
export const buildSearchTool = (): Anthropic.WebSearchTool20250305 => {
|
|
228
|
+
const maxUses = process.env.ANTHROPIC_MAX_USES;
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
name: 'web_search',
|
|
232
|
+
type: 'web_search_20250305',
|
|
233
|
+
...(maxUses &&
|
|
234
|
+
Number.isInteger(Number(maxUses)) &&
|
|
235
|
+
Number(maxUses) > 0 && {
|
|
236
|
+
max_uses: Number(maxUses),
|
|
237
|
+
}),
|
|
238
|
+
};
|
|
239
|
+
};
|
|
@@ -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
|
-
{
|
|
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: [
|
|
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: [
|
|
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([
|
|
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
|
-
{
|
|
707
|
-
|
|
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: [
|
|
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
|
-
{
|
|
805
|
-
|
|
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
|
-
{
|
|
821
|
-
|
|
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
|
-
{
|
|
861
|
-
|
|
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 {
|
|
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')
|
|
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[];
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
createParameterResolver,
|
|
6
|
-
resolveParameters,
|
|
7
|
-
} from './parameterResolver';
|
|
3
|
+
import { hasTemperatureTopPConflict } from '../const/models';
|
|
4
|
+
import { createParameterResolver, resolveParameters } from './parameterResolver';
|
|
8
5
|
|
|
9
6
|
describe('resolveParameters', () => {
|
|
10
7
|
describe('Basic functionality', () => {
|
|
@@ -247,54 +244,41 @@ describe('createParameterResolver', () => {
|
|
|
247
244
|
});
|
|
248
245
|
});
|
|
249
246
|
|
|
250
|
-
describe('
|
|
251
|
-
describe('
|
|
252
|
-
it('should
|
|
253
|
-
expect(
|
|
254
|
-
expect(
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
).toBe(
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
expect(
|
|
267
|
-
|
|
268
|
-
).toBe(
|
|
247
|
+
describe('hasTemperatureTopPConflict', () => {
|
|
248
|
+
describe('Anthropic Claude 4+ models', () => {
|
|
249
|
+
it('should return true for Claude 4+ models', () => {
|
|
250
|
+
expect(hasTemperatureTopPConflict('claude-opus-4-1-20250805')).toBe(true);
|
|
251
|
+
expect(hasTemperatureTopPConflict('claude-sonnet-4-5-20250929')).toBe(true);
|
|
252
|
+
expect(hasTemperatureTopPConflict('claude-haiku-4-5-20251001')).toBe(true);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('should return false for Claude 3.x models', () => {
|
|
256
|
+
expect(hasTemperatureTopPConflict('claude-3-opus-20240229')).toBe(false);
|
|
257
|
+
expect(hasTemperatureTopPConflict('claude-3-5-sonnet-20240620')).toBe(false);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
describe('OpenRouter Claude 4+ models', () => {
|
|
262
|
+
it('should return true for OpenRouter Claude 4+ models', () => {
|
|
263
|
+
expect(hasTemperatureTopPConflict('anthropic/claude-opus-4.5')).toBe(true);
|
|
264
|
+
expect(hasTemperatureTopPConflict('anthropic/claude-sonnet-4.1')).toBe(true);
|
|
265
|
+
expect(hasTemperatureTopPConflict('anthropic/claude-4.5-opus')).toBe(true);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('should return false for OpenRouter Claude 3.x models', () => {
|
|
269
|
+
expect(hasTemperatureTopPConflict('anthropic/claude-3.5-sonnet')).toBe(false);
|
|
270
|
+
expect(hasTemperatureTopPConflict('anthropic/claude-3.7-sonnet')).toBe(false);
|
|
269
271
|
});
|
|
270
272
|
});
|
|
271
273
|
|
|
272
|
-
describe('
|
|
273
|
-
it('should
|
|
274
|
-
expect(
|
|
275
|
-
expect(
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
).toBe(
|
|
280
|
-
expect(
|
|
281
|
-
MODEL_PARAMETER_CONFLICTS.BEDROCK_CLAUDE_4_PLUS.has(
|
|
282
|
-
'us.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
283
|
-
),
|
|
284
|
-
).toBe(true);
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
it('should contain all Bedrock regional variants', () => {
|
|
288
|
-
expect(
|
|
289
|
-
MODEL_PARAMETER_CONFLICTS.BEDROCK_CLAUDE_4_PLUS.has(
|
|
290
|
-
'anthropic.claude-opus-4-20250514-v1:0',
|
|
291
|
-
),
|
|
292
|
-
).toBe(true);
|
|
293
|
-
expect(
|
|
294
|
-
MODEL_PARAMETER_CONFLICTS.BEDROCK_CLAUDE_4_PLUS.has(
|
|
295
|
-
'us.anthropic.claude-opus-4-20250514-v1:0',
|
|
296
|
-
),
|
|
297
|
-
).toBe(true);
|
|
274
|
+
describe('Bedrock Claude 4+ models', () => {
|
|
275
|
+
it('should return true for Bedrock Claude 4+ models', () => {
|
|
276
|
+
expect(hasTemperatureTopPConflict('anthropic.claude-opus-4-1-20250805-v1:0')).toBe(true);
|
|
277
|
+
expect(hasTemperatureTopPConflict('us.anthropic.claude-sonnet-4-5-20250929-v1:0')).toBe(true);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('should return false for Bedrock Claude 3.x models', () => {
|
|
281
|
+
expect(hasTemperatureTopPConflict('anthropic.claude-3-5-sonnet-20240620-v1:0')).toBe(false);
|
|
298
282
|
});
|
|
299
283
|
});
|
|
300
284
|
});
|
|
@@ -239,44 +239,3 @@ export const createParameterResolver = (options: ParameterResolverOptions) => {
|
|
|
239
239
|
return resolveParameters(config, options);
|
|
240
240
|
};
|
|
241
241
|
};
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Common model sets that have parameter conflicts
|
|
245
|
-
*/
|
|
246
|
-
export const MODEL_PARAMETER_CONFLICTS = {
|
|
247
|
-
/**
|
|
248
|
-
* Claude models after Opus 4.1 that don't allow both temperature and top_p
|
|
249
|
-
*/
|
|
250
|
-
ANTHROPIC_CLAUDE_4_PLUS: new Set([
|
|
251
|
-
'claude-opus-4-1',
|
|
252
|
-
'claude-opus-4-1-20250805',
|
|
253
|
-
'claude-sonnet-4-5-20250929',
|
|
254
|
-
'claude-haiku-4-5-20251001',
|
|
255
|
-
'claude-opus-4-5-20251101',
|
|
256
|
-
]),
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Bedrock Claude 4+ models (including Bedrock-specific model IDs)
|
|
260
|
-
*/
|
|
261
|
-
BEDROCK_CLAUDE_4_PLUS: new Set([
|
|
262
|
-
'claude-opus-4-1',
|
|
263
|
-
'claude-opus-4-1-20250805',
|
|
264
|
-
'claude-opus-4-20250514',
|
|
265
|
-
'claude-sonnet-4-20250514',
|
|
266
|
-
'claude-sonnet-4-5-20250929',
|
|
267
|
-
'claude-haiku-4-5-20251001',
|
|
268
|
-
// Bedrock model IDs
|
|
269
|
-
'anthropic.claude-opus-4-1-20250805-v1:0',
|
|
270
|
-
'us.anthropic.claude-opus-4-1-20250805-v1:0',
|
|
271
|
-
'anthropic.claude-opus-4-20250514-v1:0',
|
|
272
|
-
'us.anthropic.claude-opus-4-20250514-v1:0',
|
|
273
|
-
'anthropic.claude-sonnet-4-20250514-v1:0',
|
|
274
|
-
'us.anthropic.claude-sonnet-4-20250514-v1:0',
|
|
275
|
-
'anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
276
|
-
'us.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
277
|
-
'anthropic.claude-haiku-4-5-20251001-v1:0',
|
|
278
|
-
'us.anthropic.claude-haiku-4-5-20251001-v1:0',
|
|
279
|
-
'global.anthropic.claude-opus-4-5-20251101-v1:0',
|
|
280
|
-
'anthropic.claude-opus-4-5-20251101-v1:0',
|
|
281
|
-
]),
|
|
282
|
-
};
|