@ai-sdk/amazon-bedrock 4.0.27 → 4.0.29

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 (39) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/anthropic/index.js +1 -1
  3. package/dist/anthropic/index.mjs +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/index.mjs +1 -1
  6. package/package.json +9 -5
  7. package/src/__fixtures__/bedrock-json-only-text-first.1.chunks.txt +0 -7
  8. package/src/__fixtures__/bedrock-json-other-tool.1.chunks.txt +0 -6
  9. package/src/__fixtures__/bedrock-json-other-tool.1.json +0 -24
  10. package/src/__fixtures__/bedrock-json-tool-text-then-weather-then-json.1.chunks.txt +0 -12
  11. package/src/__fixtures__/bedrock-json-tool-with-answer.1.json +0 -29
  12. package/src/__fixtures__/bedrock-json-tool.1.chunks.txt +0 -4
  13. package/src/__fixtures__/bedrock-json-tool.1.json +0 -35
  14. package/src/__fixtures__/bedrock-json-tool.2.chunks.txt +0 -6
  15. package/src/__fixtures__/bedrock-json-tool.2.json +0 -28
  16. package/src/__fixtures__/bedrock-json-tool.3.chunks.txt +0 -7
  17. package/src/__fixtures__/bedrock-json-tool.3.json +0 -36
  18. package/src/__fixtures__/bedrock-json-with-tool.1.chunks.txt +0 -9
  19. package/src/__fixtures__/bedrock-json-with-tool.1.json +0 -41
  20. package/src/__fixtures__/bedrock-json-with-tools.1.chunks.txt +0 -12
  21. package/src/__fixtures__/bedrock-json-with-tools.1.json +0 -50
  22. package/src/__fixtures__/bedrock-tool-call.1.chunks.txt +0 -6
  23. package/src/__fixtures__/bedrock-tool-call.1.json +0 -24
  24. package/src/__fixtures__/bedrock-tool-no-args.chunks.txt +0 -8
  25. package/src/__fixtures__/bedrock-tool-no-args.json +0 -25
  26. package/src/anthropic/bedrock-anthropic-fetch.test.ts +0 -344
  27. package/src/anthropic/bedrock-anthropic-provider.test.ts +0 -456
  28. package/src/bedrock-chat-language-model.test.ts +0 -4569
  29. package/src/bedrock-embedding-model.test.ts +0 -148
  30. package/src/bedrock-event-stream-response-handler.test.ts +0 -233
  31. package/src/bedrock-image-model.test.ts +0 -866
  32. package/src/bedrock-provider.test.ts +0 -457
  33. package/src/bedrock-sigv4-fetch.test.ts +0 -675
  34. package/src/convert-bedrock-usage.test.ts +0 -207
  35. package/src/convert-to-bedrock-chat-messages.test.ts +0 -1175
  36. package/src/inject-fetch-headers.test.ts +0 -135
  37. package/src/normalize-tool-call-id.test.ts +0 -72
  38. package/src/reranking/__fixtures__/bedrock-reranking.1.json +0 -12
  39. package/src/reranking/bedrock-reranking-model.test.ts +0 -299
@@ -1,456 +0,0 @@
1
- import { createBedrockAnthropic } from './bedrock-anthropic-provider';
2
- import { NoSuchModelError } from '@ai-sdk/provider';
3
- import {
4
- AnthropicMessagesLanguageModel,
5
- anthropicTools,
6
- } from '@ai-sdk/anthropic/internal';
7
- import { vi, describe, beforeEach, it, expect } from 'vitest';
8
-
9
- vi.mock('@ai-sdk/provider-utils', () => ({
10
- loadOptionalSetting: vi.fn().mockImplementation(({ settingValue }) => {
11
- // Return undefined for API key to test SigV4 flow
12
- if (settingValue === undefined) return undefined;
13
- return settingValue;
14
- }),
15
- loadSetting: vi.fn().mockImplementation(({ settingValue, settingName }) => {
16
- if (settingValue) return settingValue;
17
- // Return mock values for required settings
18
- if (settingName === 'region') return 'us-east-1';
19
- if (settingName === 'accessKeyId') return 'mock-access-key';
20
- if (settingName === 'secretAccessKey') return 'mock-secret-key';
21
- return settingValue;
22
- }),
23
- withoutTrailingSlash: vi.fn().mockImplementation(url => url),
24
- withUserAgentSuffix: vi.fn().mockImplementation((headers, suffix) => ({
25
- ...headers,
26
- 'user-agent': suffix,
27
- })),
28
- resolve: vi.fn().mockImplementation(async value => {
29
- if (typeof value === 'function') return value();
30
- return value;
31
- }),
32
- createJsonErrorResponseHandler: vi.fn(),
33
- createProviderToolFactory: vi.fn(),
34
- createProviderToolFactoryWithOutputSchema: vi.fn(),
35
- lazySchema: vi.fn(),
36
- zodSchema: vi.fn(),
37
- }));
38
-
39
- vi.mock('@ai-sdk/anthropic/internal', async () => {
40
- const originalModule = await vi.importActual('@ai-sdk/anthropic/internal');
41
- return {
42
- ...originalModule,
43
- AnthropicMessagesLanguageModel: vi.fn(),
44
- };
45
- });
46
-
47
- vi.mock('../bedrock-sigv4-fetch', () => ({
48
- createSigV4FetchFunction: vi.fn().mockReturnValue(vi.fn()),
49
- createApiKeyFetchFunction: vi.fn().mockReturnValue(vi.fn()),
50
- }));
51
-
52
- describe('bedrock-anthropic-provider', () => {
53
- beforeEach(() => {
54
- vi.clearAllMocks();
55
- });
56
-
57
- it('should create a language model with default settings', () => {
58
- const provider = createBedrockAnthropic({
59
- region: 'us-east-1',
60
- accessKeyId: 'test-key',
61
- secretAccessKey: 'test-secret',
62
- });
63
- provider('anthropic.claude-3-5-sonnet-20241022-v2:0');
64
-
65
- expect(AnthropicMessagesLanguageModel).toHaveBeenCalledWith(
66
- 'anthropic.claude-3-5-sonnet-20241022-v2:0',
67
- expect.objectContaining({
68
- baseURL: expect.stringContaining('bedrock-runtime'),
69
- provider: 'bedrock.anthropic.messages',
70
- headers: expect.any(Function),
71
- buildRequestUrl: expect.any(Function),
72
- transformRequestBody: expect.any(Function),
73
- supportedUrls: expect.any(Function),
74
- supportsNativeStructuredOutput: false,
75
- }),
76
- );
77
- });
78
-
79
- it('should throw an error when using new keyword', () => {
80
- const provider = createBedrockAnthropic({
81
- region: 'us-east-1',
82
- accessKeyId: 'test-key',
83
- secretAccessKey: 'test-secret',
84
- });
85
-
86
- expect(() => new (provider as any)('test-model-id')).toThrow(
87
- 'The Bedrock Anthropic model function cannot be called with the new keyword.',
88
- );
89
- });
90
-
91
- it('should pass custom baseURL to the model when created', () => {
92
- const customBaseURL = 'https://custom-bedrock.amazonaws.com';
93
- const provider = createBedrockAnthropic({
94
- region: 'us-east-1',
95
- baseURL: customBaseURL,
96
- accessKeyId: 'test-key',
97
- secretAccessKey: 'test-secret',
98
- });
99
- provider('test-model-id');
100
-
101
- expect(AnthropicMessagesLanguageModel).toHaveBeenCalledWith(
102
- expect.anything(),
103
- expect.objectContaining({
104
- baseURL: customBaseURL,
105
- }),
106
- );
107
- });
108
-
109
- it('should throw NoSuchModelError for embeddingModel', () => {
110
- const provider = createBedrockAnthropic({
111
- region: 'us-east-1',
112
- accessKeyId: 'test-key',
113
- secretAccessKey: 'test-secret',
114
- });
115
-
116
- expect(() => provider.embeddingModel('invalid-model-id')).toThrow(
117
- NoSuchModelError,
118
- );
119
- });
120
-
121
- it('should throw NoSuchModelError for imageModel', () => {
122
- const provider = createBedrockAnthropic({
123
- region: 'us-east-1',
124
- accessKeyId: 'test-key',
125
- secretAccessKey: 'test-secret',
126
- });
127
-
128
- expect(() => provider.imageModel('invalid-model-id')).toThrow(
129
- NoSuchModelError,
130
- );
131
- });
132
-
133
- it('should include anthropicTools', () => {
134
- const provider = createBedrockAnthropic({
135
- region: 'us-east-1',
136
- accessKeyId: 'test-key',
137
- secretAccessKey: 'test-secret',
138
- });
139
-
140
- expect(provider.tools).toBe(anthropicTools);
141
- });
142
-
143
- it('should pass custom headers wrapped in a function with user-agent suffix', async () => {
144
- const customHeaders = { 'Custom-Header': 'custom-value' };
145
- const provider = createBedrockAnthropic({
146
- region: 'us-east-1',
147
- headers: customHeaders,
148
- accessKeyId: 'test-key',
149
- secretAccessKey: 'test-secret',
150
- });
151
- provider('test-model-id');
152
-
153
- expect(AnthropicMessagesLanguageModel).toHaveBeenCalledWith(
154
- expect.anything(),
155
- expect.objectContaining({
156
- headers: expect.any(Function),
157
- }),
158
- );
159
-
160
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
161
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
162
- const config = constructorCall[1];
163
-
164
- expect(config.headers).toEqual(expect.any(Function));
165
- const resolvedHeaders = await (config.headers as Function)();
166
- expect(resolvedHeaders).toMatchObject(customHeaders);
167
- expect(resolvedHeaders['user-agent']).toContain('ai-sdk/amazon-bedrock/');
168
- });
169
-
170
- it('should build correct URL for non-streaming requests', () => {
171
- const provider = createBedrockAnthropic({
172
- region: 'us-east-1',
173
- accessKeyId: 'test-key',
174
- secretAccessKey: 'test-secret',
175
- });
176
- provider('anthropic.claude-3-sonnet-20240229-v1:0');
177
-
178
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
179
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
180
- const config = constructorCall[1];
181
-
182
- const url = config.buildRequestUrl?.(
183
- 'https://bedrock-runtime.us-east-1.amazonaws.com',
184
- false,
185
- );
186
- expect(url).toBe(
187
- 'https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-3-sonnet-20240229-v1%3A0/invoke',
188
- );
189
- });
190
-
191
- it('should build correct URL for streaming requests', () => {
192
- const provider = createBedrockAnthropic({
193
- region: 'us-east-1',
194
- accessKeyId: 'test-key',
195
- secretAccessKey: 'test-secret',
196
- });
197
- provider('anthropic.claude-3-sonnet-20240229-v1:0');
198
-
199
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
200
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
201
- const config = constructorCall[1];
202
-
203
- const url = config.buildRequestUrl?.(
204
- 'https://bedrock-runtime.us-east-1.amazonaws.com',
205
- true,
206
- );
207
- expect(url).toBe(
208
- 'https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-3-sonnet-20240229-v1%3A0/invoke-with-response-stream',
209
- );
210
- });
211
-
212
- it('should transform request body to add anthropic_version and remove model', () => {
213
- const provider = createBedrockAnthropic({
214
- region: 'us-east-1',
215
- accessKeyId: 'test-key',
216
- secretAccessKey: 'test-secret',
217
- });
218
- provider('test-model-id');
219
-
220
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
221
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
222
- const config = constructorCall[1];
223
-
224
- const transformedBody = config.transformRequestBody?.({
225
- model: 'test-model-id',
226
- messages: [{ role: 'user', content: 'Hello' }],
227
- max_tokens: 1024,
228
- });
229
-
230
- expect(transformedBody).toEqual({
231
- messages: [{ role: 'user', content: 'Hello' }],
232
- max_tokens: 1024,
233
- anthropic_version: 'bedrock-2023-05-31',
234
- });
235
- expect(transformedBody).not.toHaveProperty('model');
236
- });
237
-
238
- it('should strip stream parameter from request body', () => {
239
- const provider = createBedrockAnthropic({
240
- region: 'us-east-1',
241
- accessKeyId: 'test-key',
242
- secretAccessKey: 'test-secret',
243
- });
244
- provider('test-model-id');
245
-
246
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
247
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
248
- const config = constructorCall[1];
249
-
250
- const transformedBody = config.transformRequestBody?.({
251
- model: 'test-model-id',
252
- messages: [{ role: 'user', content: 'Hello' }],
253
- max_tokens: 1024,
254
- stream: true,
255
- });
256
-
257
- expect(transformedBody).not.toHaveProperty('stream');
258
- expect(transformedBody).toHaveProperty('anthropic_version');
259
- });
260
-
261
- it('should strip disable_parallel_tool_use from tool_choice', () => {
262
- const provider = createBedrockAnthropic({
263
- region: 'us-east-1',
264
- accessKeyId: 'test-key',
265
- secretAccessKey: 'test-secret',
266
- });
267
- provider('test-model-id');
268
-
269
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
270
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
271
- const config = constructorCall[1];
272
-
273
- const transformedBody = config.transformRequestBody?.({
274
- model: 'test-model-id',
275
- messages: [{ role: 'user', content: 'Hello' }],
276
- max_tokens: 1024,
277
- tool_choice: {
278
- type: 'auto',
279
- disable_parallel_tool_use: true,
280
- },
281
- });
282
-
283
- expect(transformedBody?.tool_choice).toEqual({ type: 'auto' });
284
- expect(transformedBody?.tool_choice).not.toHaveProperty(
285
- 'disable_parallel_tool_use',
286
- );
287
- });
288
-
289
- it('should preserve tool_choice name when present', () => {
290
- const provider = createBedrockAnthropic({
291
- region: 'us-east-1',
292
- accessKeyId: 'test-key',
293
- secretAccessKey: 'test-secret',
294
- });
295
- provider('test-model-id');
296
-
297
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
298
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
299
- const config = constructorCall[1];
300
-
301
- const transformedBody = config.transformRequestBody?.({
302
- model: 'test-model-id',
303
- messages: [{ role: 'user', content: 'Hello' }],
304
- max_tokens: 1024,
305
- tool_choice: {
306
- type: 'tool',
307
- name: 'my_tool',
308
- disable_parallel_tool_use: true,
309
- },
310
- });
311
-
312
- expect(transformedBody?.tool_choice).toEqual({
313
- type: 'tool',
314
- name: 'my_tool',
315
- });
316
- });
317
-
318
- it('should map old tool versions to Bedrock-supported versions', () => {
319
- const provider = createBedrockAnthropic({
320
- region: 'us-east-1',
321
- accessKeyId: 'test-key',
322
- secretAccessKey: 'test-secret',
323
- });
324
- provider('test-model-id');
325
-
326
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
327
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
328
- const config = constructorCall[1];
329
-
330
- const transformedBody = config.transformRequestBody?.({
331
- model: 'test-model-id',
332
- messages: [{ role: 'user', content: 'Hello' }],
333
- max_tokens: 1024,
334
- tools: [
335
- { type: 'bash_20241022', name: 'bash' },
336
- { type: 'text_editor_20241022', name: 'str_replace_editor' },
337
- { type: 'computer_20241022', name: 'computer' },
338
- ],
339
- });
340
-
341
- expect(transformedBody?.tools).toEqual([
342
- { type: 'bash_20250124', name: 'bash' },
343
- { type: 'text_editor_20250728', name: 'str_replace_based_edit_tool' },
344
- { type: 'computer_20250124', name: 'computer' },
345
- ]);
346
- });
347
-
348
- it('should add anthropic_beta when computer use tools are detected', () => {
349
- const provider = createBedrockAnthropic({
350
- region: 'us-east-1',
351
- accessKeyId: 'test-key',
352
- secretAccessKey: 'test-secret',
353
- });
354
- provider('test-model-id');
355
-
356
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
357
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
358
- const config = constructorCall[1];
359
-
360
- const transformedBody = config.transformRequestBody?.({
361
- model: 'test-model-id',
362
- messages: [{ role: 'user', content: 'Hello' }],
363
- max_tokens: 1024,
364
- tools: [{ type: 'bash_20250124', name: 'bash' }],
365
- });
366
-
367
- expect(transformedBody?.anthropic_beta).toContain(
368
- 'computer-use-2025-01-24',
369
- );
370
- });
371
-
372
- it('should not add anthropic_beta when no computer use tools are present', () => {
373
- const provider = createBedrockAnthropic({
374
- region: 'us-east-1',
375
- accessKeyId: 'test-key',
376
- secretAccessKey: 'test-secret',
377
- });
378
- provider('test-model-id');
379
-
380
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
381
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
382
- const config = constructorCall[1];
383
-
384
- const transformedBody = config.transformRequestBody?.({
385
- model: 'test-model-id',
386
- messages: [{ role: 'user', content: 'Hello' }],
387
- max_tokens: 1024,
388
- tools: [
389
- {
390
- type: 'function',
391
- name: 'get_weather',
392
- input_schema: { type: 'object', properties: {} },
393
- },
394
- ],
395
- });
396
-
397
- expect(transformedBody?.anthropic_beta).toBeUndefined();
398
- });
399
-
400
- it('should not support URL sources to force base64 conversion', () => {
401
- const provider = createBedrockAnthropic({
402
- region: 'us-east-1',
403
- accessKeyId: 'test-key',
404
- secretAccessKey: 'test-secret',
405
- });
406
- provider('test-model-id');
407
-
408
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
409
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
410
- const config = constructorCall[1];
411
-
412
- expect(config.supportedUrls?.()).toEqual({});
413
- });
414
-
415
- it('should have correct specificationVersion', () => {
416
- const provider = createBedrockAnthropic({
417
- region: 'us-east-1',
418
- accessKeyId: 'test-key',
419
- secretAccessKey: 'test-secret',
420
- });
421
-
422
- expect(provider.specificationVersion).toBe('v3');
423
- });
424
-
425
- it('should provide languageModel as alias', () => {
426
- const provider = createBedrockAnthropic({
427
- region: 'us-east-1',
428
- accessKeyId: 'test-key',
429
- secretAccessKey: 'test-secret',
430
- });
431
-
432
- expect(provider.languageModel).toBeDefined();
433
- expect(typeof provider.languageModel).toBe('function');
434
- });
435
-
436
- it('should handle models with us. prefix for inference profiles', () => {
437
- const provider = createBedrockAnthropic({
438
- region: 'us-east-1',
439
- accessKeyId: 'test-key',
440
- secretAccessKey: 'test-secret',
441
- });
442
- provider('us.anthropic.claude-3-5-sonnet-20240620-v1:0');
443
-
444
- const constructorCall = vi.mocked(AnthropicMessagesLanguageModel).mock
445
- .calls[vi.mocked(AnthropicMessagesLanguageModel).mock.calls.length - 1];
446
- const config = constructorCall[1];
447
-
448
- const url = config.buildRequestUrl?.(
449
- 'https://bedrock-runtime.us-east-1.amazonaws.com',
450
- false,
451
- );
452
- expect(url).toBe(
453
- 'https://bedrock-runtime.us-east-1.amazonaws.com/model/us.anthropic.claude-3-5-sonnet-20240620-v1%3A0/invoke',
454
- );
455
- });
456
- });