@lobehub/lobehub 2.0.0-next.116 → 2.0.0-next.118
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/fetch-sse/src/__tests__/headers.test.ts +367 -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/parameterResolver.test.ts +34 -50
- package/packages/model-runtime/src/core/parameterResolver.ts +0 -41
- 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/src/app/[variants]/(main)/discover/(detail)/assistant/features/Details/Capabilities/Plugins.tsx +11 -6
- package/src/libs/mcp/__tests__/__snapshots__/index.test.ts.snap +5 -0
- package/src/server/services/discover/index.ts +42 -2
- package/src/server/services/mcp/contentProcessor.ts +7 -7
- package/src/server/services/mcp/deps/MCPSystemDepsCheckService.ts +3 -3
- package/src/server/services/mcp/index.ts +11 -11
- package/src/store/agent/slices/chat/selectors/chatConfig.ts +4 -3
- package/packages/const/src/models.ts +0 -93
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.118](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.117...v2.0.0-next.118)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2025-11-26**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Showing compatibility with both new and old versions of Plugins.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Showing compatibility with both new and old versions of Plugins, closes [#10418](https://github.com/lobehub/lobe-chat/issues/10418) ([64af7b1](https://github.com/lobehub/lobe-chat/commit/64af7b1))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## [Version 2.0.0-next.117](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.116...v2.0.0-next.117)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2025-11-25**</sup>
|
|
33
|
+
|
|
34
|
+
#### ✨ Features
|
|
35
|
+
|
|
36
|
+
- **misc**: Bedrock claude model thinking support.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### What's improved
|
|
44
|
+
|
|
45
|
+
- **misc**: Bedrock claude model thinking support, closes [#10422](https://github.com/lobehub/lobe-chat/issues/10422) ([8b41638](https://github.com/lobehub/lobe-chat/commit/8b41638))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
## [Version 2.0.0-next.116](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.115...v2.0.0-next.116)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2025-11-25**</sup>
|
package/changelog/v1.json
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"children": {
|
|
4
|
+
"fixes": [
|
|
5
|
+
"Showing compatibility with both new and old versions of Plugins."
|
|
6
|
+
]
|
|
7
|
+
},
|
|
8
|
+
"date": "2025-11-26",
|
|
9
|
+
"version": "2.0.0-next.118"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"children": {
|
|
13
|
+
"features": [
|
|
14
|
+
"Bedrock claude model thinking support."
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"date": "2025-11-25",
|
|
18
|
+
"version": "2.0.0-next.117"
|
|
19
|
+
},
|
|
2
20
|
{
|
|
3
21
|
"children": {
|
|
4
22
|
"features": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.118",
|
|
4
4
|
"description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { headersToRecord } from '../headers';
|
|
4
|
+
|
|
5
|
+
describe('headersToRecord', () => {
|
|
6
|
+
describe('undefined or null input', () => {
|
|
7
|
+
it('should return empty object when headersInit is undefined', () => {
|
|
8
|
+
// Arrange & Act
|
|
9
|
+
const result = headersToRecord(undefined);
|
|
10
|
+
|
|
11
|
+
// Assert
|
|
12
|
+
expect(result).toEqual({});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should return empty object when headersInit is not provided', () => {
|
|
16
|
+
// Arrange & Act
|
|
17
|
+
const result = headersToRecord();
|
|
18
|
+
|
|
19
|
+
// Assert
|
|
20
|
+
expect(result).toEqual({});
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('Headers instance', () => {
|
|
25
|
+
it('should convert Headers instance to record', () => {
|
|
26
|
+
// Arrange
|
|
27
|
+
const headers = new Headers();
|
|
28
|
+
headers.append('content-type', 'application/json');
|
|
29
|
+
headers.append('authorization', 'Bearer token123');
|
|
30
|
+
headers.append('x-custom-header', 'custom-value');
|
|
31
|
+
|
|
32
|
+
// Act
|
|
33
|
+
const result = headersToRecord(headers);
|
|
34
|
+
|
|
35
|
+
// Assert
|
|
36
|
+
expect(result).toEqual({
|
|
37
|
+
'content-type': 'application/json',
|
|
38
|
+
'authorization': 'Bearer token123',
|
|
39
|
+
'x-custom-header': 'custom-value',
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should handle Headers instance with multiple values for same key', () => {
|
|
44
|
+
// Arrange
|
|
45
|
+
const headers = new Headers();
|
|
46
|
+
headers.append('accept', 'application/json');
|
|
47
|
+
headers.append('accept', 'text/html');
|
|
48
|
+
|
|
49
|
+
// Act
|
|
50
|
+
const result = headersToRecord(headers);
|
|
51
|
+
|
|
52
|
+
// Assert
|
|
53
|
+
expect(result).toHaveProperty('accept');
|
|
54
|
+
expect(typeof result.accept).toBe('string');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should handle empty Headers instance', () => {
|
|
58
|
+
// Arrange
|
|
59
|
+
const headers = new Headers();
|
|
60
|
+
|
|
61
|
+
// Act
|
|
62
|
+
const result = headersToRecord(headers);
|
|
63
|
+
|
|
64
|
+
// Assert
|
|
65
|
+
expect(result).toEqual({});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('Array format', () => {
|
|
70
|
+
it('should convert array of tuples to record', () => {
|
|
71
|
+
// Arrange
|
|
72
|
+
const headersArray: [string, string][] = [
|
|
73
|
+
['content-type', 'application/json'],
|
|
74
|
+
['authorization', 'Bearer token123'],
|
|
75
|
+
['x-api-key', 'api-key-value'],
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
// Act
|
|
79
|
+
const result = headersToRecord(headersArray);
|
|
80
|
+
|
|
81
|
+
// Assert
|
|
82
|
+
expect(result).toEqual({
|
|
83
|
+
'content-type': 'application/json',
|
|
84
|
+
'authorization': 'Bearer token123',
|
|
85
|
+
'x-api-key': 'api-key-value',
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should handle empty array', () => {
|
|
90
|
+
// Arrange
|
|
91
|
+
const headersArray: [string, string][] = [];
|
|
92
|
+
|
|
93
|
+
// Act
|
|
94
|
+
const result = headersToRecord(headersArray);
|
|
95
|
+
|
|
96
|
+
// Assert
|
|
97
|
+
expect(result).toEqual({});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should handle array with single header', () => {
|
|
101
|
+
// Arrange
|
|
102
|
+
const headersArray: [string, string][] = [['x-single-header', 'single-value']];
|
|
103
|
+
|
|
104
|
+
// Act
|
|
105
|
+
const result = headersToRecord(headersArray);
|
|
106
|
+
|
|
107
|
+
// Assert
|
|
108
|
+
expect(result).toEqual({
|
|
109
|
+
'x-single-header': 'single-value',
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe('Plain object', () => {
|
|
115
|
+
it('should convert plain object to record', () => {
|
|
116
|
+
// Arrange
|
|
117
|
+
const headersObj = {
|
|
118
|
+
'content-type': 'application/json',
|
|
119
|
+
'authorization': 'Bearer token123',
|
|
120
|
+
'x-custom': 'value',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// Act
|
|
124
|
+
const result = headersToRecord(headersObj);
|
|
125
|
+
|
|
126
|
+
// Assert
|
|
127
|
+
expect(result).toEqual({
|
|
128
|
+
'content-type': 'application/json',
|
|
129
|
+
'authorization': 'Bearer token123',
|
|
130
|
+
'x-custom': 'value',
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should handle empty object', () => {
|
|
135
|
+
// Arrange
|
|
136
|
+
const headersObj = {};
|
|
137
|
+
|
|
138
|
+
// Act
|
|
139
|
+
const result = headersToRecord(headersObj);
|
|
140
|
+
|
|
141
|
+
// Assert
|
|
142
|
+
expect(result).toEqual({});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should handle object with special characters in values', () => {
|
|
146
|
+
// Arrange
|
|
147
|
+
const headersObj = {
|
|
148
|
+
'authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
|
|
149
|
+
'x-special': 'value with spaces and symbols: !@#$%',
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// Act
|
|
153
|
+
const result = headersToRecord(headersObj);
|
|
154
|
+
|
|
155
|
+
// Assert
|
|
156
|
+
expect(result).toEqual({
|
|
157
|
+
'authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
|
|
158
|
+
'x-special': 'value with spaces and symbols: !@#$%',
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe('Restricted headers filtering', () => {
|
|
164
|
+
it('should remove "host" header from Headers instance', () => {
|
|
165
|
+
// Arrange
|
|
166
|
+
const headers = new Headers();
|
|
167
|
+
headers.append('host', 'example.com');
|
|
168
|
+
headers.append('content-type', 'application/json');
|
|
169
|
+
|
|
170
|
+
// Act
|
|
171
|
+
const result = headersToRecord(headers);
|
|
172
|
+
|
|
173
|
+
// Assert
|
|
174
|
+
expect(result).not.toHaveProperty('host');
|
|
175
|
+
expect(result).toEqual({
|
|
176
|
+
'content-type': 'application/json',
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should remove "connection" header from array', () => {
|
|
181
|
+
// Arrange
|
|
182
|
+
const headersArray: [string, string][] = [
|
|
183
|
+
['connection', 'keep-alive'],
|
|
184
|
+
['authorization', 'Bearer token'],
|
|
185
|
+
];
|
|
186
|
+
|
|
187
|
+
// Act
|
|
188
|
+
const result = headersToRecord(headersArray);
|
|
189
|
+
|
|
190
|
+
// Assert
|
|
191
|
+
expect(result).not.toHaveProperty('connection');
|
|
192
|
+
expect(result).toEqual({
|
|
193
|
+
authorization: 'Bearer token',
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('should remove "content-length" header from plain object', () => {
|
|
198
|
+
// Arrange
|
|
199
|
+
const headersObj = {
|
|
200
|
+
'content-length': '1234',
|
|
201
|
+
'content-type': 'application/json',
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// Act
|
|
205
|
+
const result = headersToRecord(headersObj);
|
|
206
|
+
|
|
207
|
+
// Assert
|
|
208
|
+
expect(result).not.toHaveProperty('content-length');
|
|
209
|
+
expect(result).toEqual({
|
|
210
|
+
'content-type': 'application/json',
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('should remove all restricted headers (host, connection, content-length)', () => {
|
|
215
|
+
// Arrange
|
|
216
|
+
const headersObj = {
|
|
217
|
+
'host': 'example.com',
|
|
218
|
+
'connection': 'keep-alive',
|
|
219
|
+
'content-length': '1234',
|
|
220
|
+
'authorization': 'Bearer token',
|
|
221
|
+
'content-type': 'application/json',
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// Act
|
|
225
|
+
const result = headersToRecord(headersObj);
|
|
226
|
+
|
|
227
|
+
// Assert
|
|
228
|
+
expect(result).not.toHaveProperty('host');
|
|
229
|
+
expect(result).not.toHaveProperty('connection');
|
|
230
|
+
expect(result).not.toHaveProperty('content-length');
|
|
231
|
+
expect(result).toEqual({
|
|
232
|
+
'authorization': 'Bearer token',
|
|
233
|
+
'content-type': 'application/json',
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('should handle case when only restricted headers are present', () => {
|
|
238
|
+
// Arrange
|
|
239
|
+
const headersObj = {
|
|
240
|
+
'host': 'example.com',
|
|
241
|
+
'connection': 'keep-alive',
|
|
242
|
+
'content-length': '1234',
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// Act
|
|
246
|
+
const result = headersToRecord(headersObj);
|
|
247
|
+
|
|
248
|
+
// Assert
|
|
249
|
+
expect(result).toEqual({});
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
describe('Edge cases', () => {
|
|
254
|
+
it('should handle headers with empty string values', () => {
|
|
255
|
+
// Arrange
|
|
256
|
+
const headersObj = {
|
|
257
|
+
'x-empty': '',
|
|
258
|
+
'x-normal': 'value',
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// Act
|
|
262
|
+
const result = headersToRecord(headersObj);
|
|
263
|
+
|
|
264
|
+
// Assert
|
|
265
|
+
expect(result).toEqual({
|
|
266
|
+
'x-empty': '',
|
|
267
|
+
'x-normal': 'value',
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('should handle headers with numeric-like values as strings', () => {
|
|
272
|
+
// Arrange
|
|
273
|
+
const headersArray: [string, string][] = [
|
|
274
|
+
['x-request-id', '12345'],
|
|
275
|
+
['x-retry-count', '3'],
|
|
276
|
+
];
|
|
277
|
+
|
|
278
|
+
// Act
|
|
279
|
+
const result = headersToRecord(headersArray);
|
|
280
|
+
|
|
281
|
+
// Assert
|
|
282
|
+
expect(result).toEqual({
|
|
283
|
+
'x-request-id': '12345',
|
|
284
|
+
'x-retry-count': '3',
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('should handle case-sensitive header names', () => {
|
|
289
|
+
// Arrange
|
|
290
|
+
const headersObj = {
|
|
291
|
+
'Content-Type': 'application/json',
|
|
292
|
+
'Authorization': 'Bearer token',
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
// Act
|
|
296
|
+
const result = headersToRecord(headersObj);
|
|
297
|
+
|
|
298
|
+
// Assert
|
|
299
|
+
expect(result).toEqual({
|
|
300
|
+
'Content-Type': 'application/json',
|
|
301
|
+
'Authorization': 'Bearer token',
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('should preserve header order from array input', () => {
|
|
306
|
+
// Arrange
|
|
307
|
+
const headersArray: [string, string][] = [
|
|
308
|
+
['z-last', 'last'],
|
|
309
|
+
['a-first', 'first'],
|
|
310
|
+
['m-middle', 'middle'],
|
|
311
|
+
];
|
|
312
|
+
|
|
313
|
+
// Act
|
|
314
|
+
const result = headersToRecord(headersArray);
|
|
315
|
+
|
|
316
|
+
// Assert
|
|
317
|
+
expect(Object.keys(result)).toEqual(['z-last', 'a-first', 'm-middle']);
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
describe('Real-world scenarios', () => {
|
|
322
|
+
it('should handle typical SSE request headers', () => {
|
|
323
|
+
// Arrange
|
|
324
|
+
const headers = new Headers();
|
|
325
|
+
headers.append('accept', 'text/event-stream');
|
|
326
|
+
headers.append('content-type', 'application/json');
|
|
327
|
+
headers.append('authorization', 'Bearer abc123');
|
|
328
|
+
headers.append('cache-control', 'no-cache');
|
|
329
|
+
headers.append('connection', 'keep-alive'); // Should be filtered
|
|
330
|
+
|
|
331
|
+
// Act
|
|
332
|
+
const result = headersToRecord(headers);
|
|
333
|
+
|
|
334
|
+
// Assert
|
|
335
|
+
expect(result).toEqual({
|
|
336
|
+
'accept': 'text/event-stream',
|
|
337
|
+
'content-type': 'application/json',
|
|
338
|
+
'authorization': 'Bearer abc123',
|
|
339
|
+
'cache-control': 'no-cache',
|
|
340
|
+
});
|
|
341
|
+
expect(result).not.toHaveProperty('connection');
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
it('should handle API request headers with custom fields', () => {
|
|
345
|
+
// Arrange
|
|
346
|
+
const headersObj = {
|
|
347
|
+
'content-type': 'application/json',
|
|
348
|
+
'x-api-key': 'secret-key',
|
|
349
|
+
'x-request-id': 'req-123',
|
|
350
|
+
'user-agent': 'MyApp/1.0',
|
|
351
|
+
'host': 'api.example.com', // Should be filtered
|
|
352
|
+
'content-length': '256', // Should be filtered
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// Act
|
|
356
|
+
const result = headersToRecord(headersObj);
|
|
357
|
+
|
|
358
|
+
// Assert
|
|
359
|
+
expect(result).toEqual({
|
|
360
|
+
'content-type': 'application/json',
|
|
361
|
+
'x-api-key': 'secret-key',
|
|
362
|
+
'x-request-id': 'req-123',
|
|
363
|
+
'user-agent': 'MyApp/1.0',
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
});
|
|
@@ -13,7 +13,7 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
13
13
|
'Claude Opus 4.5 是 Anthropic 的旗舰模型,结合了卓越的智能与可扩展性能,适合需要最高质量回应和推理能力的复杂任务。',
|
|
14
14
|
displayName: 'Claude Opus 4.5',
|
|
15
15
|
enabled: true,
|
|
16
|
-
id: '
|
|
16
|
+
id: 'global.anthropic.claude-opus-4-5-20251101-v1:0',
|
|
17
17
|
maxOutput: 64_000,
|
|
18
18
|
pricing: {
|
|
19
19
|
units: [
|
|
@@ -23,6 +23,9 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
23
23
|
],
|
|
24
24
|
},
|
|
25
25
|
releasedAt: '2025-11-24',
|
|
26
|
+
settings: {
|
|
27
|
+
extendParams: ['disableContextCaching', 'enableReasoning', 'reasoningBudgetToken'],
|
|
28
|
+
},
|
|
26
29
|
type: 'chat',
|
|
27
30
|
},
|
|
28
31
|
{
|
|
@@ -45,6 +48,9 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
45
48
|
],
|
|
46
49
|
},
|
|
47
50
|
releasedAt: '2025-09-29',
|
|
51
|
+
settings: {
|
|
52
|
+
extendParams: ['disableContextCaching', 'enableReasoning', 'reasoningBudgetToken'],
|
|
53
|
+
},
|
|
48
54
|
type: 'chat',
|
|
49
55
|
},
|
|
50
56
|
{
|
|
@@ -68,6 +74,9 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
68
74
|
],
|
|
69
75
|
},
|
|
70
76
|
releasedAt: '2025-10-15',
|
|
77
|
+
settings: {
|
|
78
|
+
extendParams: ['disableContextCaching', 'enableReasoning', 'reasoningBudgetToken'],
|
|
79
|
+
},
|
|
71
80
|
type: 'chat',
|
|
72
81
|
},
|
|
73
82
|
/*
|
|
@@ -103,7 +112,7 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
103
112
|
'Claude 3.7 sonnet 是 Anthropic 最快的下一代模型。与 Claude 3 Haiku 相比,Claude 3.7 Sonnet 在各项技能上都有所提升,并在许多智力基准测试中超越了上一代最大的模型 Claude 3 Opus。',
|
|
104
113
|
displayName: 'Claude 3.7 Sonnet',
|
|
105
114
|
id: 'us.anthropic.claude-3-7-sonnet-20250219-v1:0',
|
|
106
|
-
maxOutput:
|
|
115
|
+
maxOutput: 64_000,
|
|
107
116
|
pricing: {
|
|
108
117
|
units: [
|
|
109
118
|
{ name: 'textInput', rate: 3, strategy: 'fixed', unit: 'millionTokens' },
|
|
@@ -111,6 +120,9 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
111
120
|
],
|
|
112
121
|
},
|
|
113
122
|
releasedAt: '2025-02-24',
|
|
123
|
+
settings: {
|
|
124
|
+
extendParams: ['disableContextCaching', 'enableReasoning', 'reasoningBudgetToken'],
|
|
125
|
+
},
|
|
114
126
|
type: 'chat',
|
|
115
127
|
},
|
|
116
128
|
{
|
|
@@ -131,6 +143,9 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
131
143
|
],
|
|
132
144
|
},
|
|
133
145
|
releasedAt: '2024-10-22',
|
|
146
|
+
settings: {
|
|
147
|
+
extendParams: ['disableContextCaching'],
|
|
148
|
+
},
|
|
134
149
|
type: 'chat',
|
|
135
150
|
},
|
|
136
151
|
{
|
|
@@ -151,6 +166,9 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
151
166
|
],
|
|
152
167
|
},
|
|
153
168
|
releasedAt: '2024-10-22',
|
|
169
|
+
settings: {
|
|
170
|
+
extendParams: ['disableContextCaching'],
|
|
171
|
+
},
|
|
154
172
|
type: 'chat',
|
|
155
173
|
},
|
|
156
174
|
{
|
|
@@ -171,6 +189,9 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
171
189
|
],
|
|
172
190
|
},
|
|
173
191
|
releasedAt: '2024-06-20',
|
|
192
|
+
settings: {
|
|
193
|
+
extendParams: ['disableContextCaching'],
|
|
194
|
+
},
|
|
174
195
|
type: 'chat',
|
|
175
196
|
},
|
|
176
197
|
{
|
|
@@ -191,6 +212,9 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
191
212
|
],
|
|
192
213
|
},
|
|
193
214
|
releasedAt: '2024-03-07',
|
|
215
|
+
settings: {
|
|
216
|
+
extendParams: ['disableContextCaching'],
|
|
217
|
+
},
|
|
194
218
|
type: 'chat',
|
|
195
219
|
},
|
|
196
220
|
{
|
|
@@ -228,6 +252,9 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
228
252
|
],
|
|
229
253
|
},
|
|
230
254
|
releasedAt: '2024-02-29',
|
|
255
|
+
settings: {
|
|
256
|
+
extendParams: ['disableContextCaching'],
|
|
257
|
+
},
|
|
231
258
|
type: 'chat',
|
|
232
259
|
},
|
|
233
260
|
{
|
|
@@ -264,6 +291,7 @@ const bedrockChatModels: AIChatModelCard[] = [
|
|
|
264
291
|
'一款快速、经济且仍然非常有能力的模型,可以处理包括日常对话、文本分析、总结和文档问答在内的一系列任务。',
|
|
265
292
|
displayName: 'Claude Instant',
|
|
266
293
|
id: 'anthropic.claude-instant-v1',
|
|
294
|
+
maxOutput: 4096,
|
|
267
295
|
pricing: {
|
|
268
296
|
units: [
|
|
269
297
|
{ name: 'textInput', rate: 0.8, strategy: 'fixed', unit: 'millionTokens' },
|
|
@@ -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
|
+
};
|