@ai-sdk/amazon-bedrock 4.0.28 → 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 +10 -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,866 +0,0 @@
1
- import { createTestServer } from '@ai-sdk/test-server/with-vitest';
2
- import { createAmazonBedrock } from './bedrock-provider';
3
- import { BedrockImageModel } from './bedrock-image-model';
4
- import { injectFetchHeaders } from './inject-fetch-headers';
5
- import { describe, it, expect } from 'vitest';
6
-
7
- const prompt = 'A cute baby sea otter';
8
-
9
- const provider = createAmazonBedrock();
10
- const fakeFetchWithAuth = injectFetchHeaders({ 'x-amz-auth': 'test-auth' });
11
-
12
- const invokeUrl = `https://bedrock-runtime.us-east-1.amazonaws.com/model/${encodeURIComponent(
13
- 'amazon.nova-canvas-v1:0',
14
- )}/invoke`;
15
-
16
- describe('doGenerate', () => {
17
- const mockConfigHeaders = {
18
- 'config-header': 'config-value',
19
- 'shared-header': 'config-shared',
20
- };
21
-
22
- const server = createTestServer({
23
- [invokeUrl]: {
24
- response: {
25
- type: 'binary',
26
- headers: {
27
- 'content-type': 'application/json',
28
- },
29
- body: Buffer.from(
30
- JSON.stringify({
31
- images: ['base64-image-1', 'base64-image-2'],
32
- }),
33
- ),
34
- },
35
- },
36
- });
37
-
38
- const model = new BedrockImageModel('amazon.nova-canvas-v1:0', {
39
- baseUrl: () => 'https://bedrock-runtime.us-east-1.amazonaws.com',
40
- headers: mockConfigHeaders,
41
- fetch: fakeFetchWithAuth,
42
- });
43
-
44
- it('should pass the model and the settings', async () => {
45
- await model.doGenerate({
46
- prompt,
47
- files: undefined,
48
- mask: undefined,
49
- n: 1,
50
- size: '1024x1024',
51
- aspectRatio: undefined,
52
- seed: 1234,
53
- providerOptions: {
54
- bedrock: {
55
- negativeText: 'bad',
56
- quality: 'premium',
57
- cfgScale: 1.2,
58
- },
59
- },
60
- });
61
-
62
- expect(await server.calls[0].requestBodyJson).toStrictEqual({
63
- taskType: 'TEXT_IMAGE',
64
- textToImageParams: {
65
- text: prompt,
66
- negativeText: 'bad',
67
- },
68
- imageGenerationConfig: {
69
- numberOfImages: 1,
70
- seed: 1234,
71
- quality: 'premium',
72
- cfgScale: 1.2,
73
- width: 1024,
74
- height: 1024,
75
- },
76
- });
77
- });
78
-
79
- it('should properly combine headers from all sources', async () => {
80
- const optionsHeaders = {
81
- 'options-header': 'options-value',
82
- 'shared-header': 'options-shared',
83
- };
84
-
85
- const modelWithHeaders = new BedrockImageModel('amazon.nova-canvas-v1:0', {
86
- baseUrl: () => 'https://bedrock-runtime.us-east-1.amazonaws.com',
87
- headers: {
88
- 'model-header': 'model-value',
89
- 'shared-header': 'model-shared',
90
- },
91
- fetch: injectFetchHeaders({
92
- 'signed-header': 'signed-value',
93
- authorization: 'AWS4-HMAC-SHA256...',
94
- }),
95
- });
96
-
97
- await modelWithHeaders.doGenerate({
98
- prompt,
99
- files: undefined,
100
- mask: undefined,
101
- n: 1,
102
- size: undefined,
103
- aspectRatio: undefined,
104
- seed: undefined,
105
- providerOptions: {},
106
- headers: optionsHeaders,
107
- });
108
-
109
- const requestHeaders = server.calls[0].requestHeaders;
110
- expect(requestHeaders['options-header']).toBe('options-value');
111
- expect(requestHeaders['model-header']).toBe('model-value');
112
- expect(requestHeaders['signed-header']).toBe('signed-value');
113
- expect(requestHeaders['authorization']).toBe('AWS4-HMAC-SHA256...');
114
- expect(requestHeaders['shared-header']).toBe('options-shared');
115
- });
116
-
117
- it('should respect maxImagesPerCall setting', async () => {
118
- const defaultModel = provider.image('amazon.nova-canvas-v1:0');
119
- expect(defaultModel.maxImagesPerCall).toBe(5); // 'amazon.nova-canvas-v1:0','s default from settings
120
-
121
- const unknownModel = provider.image('unknown-model' as any);
122
- expect(unknownModel.maxImagesPerCall).toBe(1); // fallback for unknown models
123
- });
124
-
125
- it('should return warnings for unsupported settings', async () => {
126
- const result = await model.doGenerate({
127
- prompt,
128
- files: undefined,
129
- mask: undefined,
130
- n: 1,
131
- size: '1024x1024',
132
- aspectRatio: '1:1',
133
- seed: undefined,
134
- providerOptions: {},
135
- });
136
-
137
- expect(result.warnings).toMatchInlineSnapshot(`
138
- [
139
- {
140
- "details": "This model does not support aspect ratio. Use \`size\` instead.",
141
- "feature": "aspectRatio",
142
- "type": "unsupported",
143
- },
144
- ]
145
- `);
146
- });
147
-
148
- it('should extract the generated images', async () => {
149
- const result = await model.doGenerate({
150
- prompt,
151
- files: undefined,
152
- mask: undefined,
153
- n: 1,
154
- size: undefined,
155
- aspectRatio: undefined,
156
- seed: undefined,
157
- providerOptions: {},
158
- });
159
-
160
- expect(result.images).toStrictEqual(['base64-image-1', 'base64-image-2']);
161
- });
162
-
163
- it('should include response data with timestamp, modelId and headers', async () => {
164
- const testDate = new Date('2024-03-15T12:00:00Z');
165
-
166
- const customModel = new BedrockImageModel('amazon.nova-canvas-v1:0', {
167
- baseUrl: () => 'https://bedrock-runtime.us-east-1.amazonaws.com',
168
- headers: () => ({}),
169
- _internal: {
170
- currentDate: () => testDate,
171
- },
172
- });
173
-
174
- const result = await customModel.doGenerate({
175
- prompt,
176
- files: undefined,
177
- mask: undefined,
178
- n: 1,
179
- size: '1024x1024',
180
- aspectRatio: undefined,
181
- seed: undefined,
182
- providerOptions: {},
183
- });
184
-
185
- expect(result.response).toStrictEqual({
186
- timestamp: testDate,
187
- modelId: 'amazon.nova-canvas-v1:0',
188
- headers: {
189
- 'content-length': '46',
190
- 'content-type': 'application/json',
191
- },
192
- });
193
- });
194
-
195
- it('should use real date when no custom date provider is specified', async () => {
196
- const beforeDate = new Date();
197
-
198
- const result = await model.doGenerate({
199
- prompt,
200
- files: undefined,
201
- mask: undefined,
202
- n: 1,
203
- size: undefined,
204
- aspectRatio: undefined,
205
- seed: 1234,
206
- providerOptions: {},
207
- });
208
-
209
- const afterDate = new Date();
210
-
211
- expect(result.response.timestamp.getTime()).toBeGreaterThanOrEqual(
212
- beforeDate.getTime(),
213
- );
214
- expect(result.response.timestamp.getTime()).toBeLessThanOrEqual(
215
- afterDate.getTime(),
216
- );
217
- expect(result.response.modelId).toBe('amazon.nova-canvas-v1:0');
218
- });
219
-
220
- it('should pass the style parameter when provided', async () => {
221
- await model.doGenerate({
222
- prompt,
223
- files: undefined,
224
- mask: undefined,
225
- n: 1,
226
- size: '1024x1024',
227
- aspectRatio: undefined,
228
- seed: 1234,
229
- providerOptions: {
230
- bedrock: {
231
- negativeText: 'bad',
232
- quality: 'premium',
233
- cfgScale: 1.2,
234
- style: 'PHOTOREALISM',
235
- },
236
- },
237
- });
238
-
239
- expect(await server.calls[0].requestBodyJson).toStrictEqual({
240
- taskType: 'TEXT_IMAGE',
241
- textToImageParams: {
242
- text: prompt,
243
- negativeText: 'bad',
244
- style: 'PHOTOREALISM',
245
- },
246
- imageGenerationConfig: {
247
- numberOfImages: 1,
248
- seed: 1234,
249
- quality: 'premium',
250
- cfgScale: 1.2,
251
- width: 1024,
252
- height: 1024,
253
- },
254
- });
255
- });
256
-
257
- it('should not include style parameter when not provided', async () => {
258
- await model.doGenerate({
259
- prompt,
260
- files: undefined,
261
- mask: undefined,
262
- n: 1,
263
- size: '1024x1024',
264
- aspectRatio: undefined,
265
- seed: 1234,
266
- providerOptions: {
267
- bedrock: {
268
- quality: 'standard',
269
- },
270
- },
271
- });
272
-
273
- const requestBody = await server.calls[0].requestBodyJson;
274
- expect(requestBody.textToImageParams).not.toHaveProperty('style');
275
- });
276
-
277
- it('should throw error when request is moderated', async () => {
278
- server.urls[invokeUrl].response = {
279
- type: 'binary',
280
- headers: {
281
- 'content-type': 'application/json',
282
- },
283
- body: Buffer.from(
284
- JSON.stringify({
285
- id: 'fe7256d1-50d9-4663-8592-85eaf002e80c',
286
- status: 'Request Moderated',
287
- result: null,
288
- progress: null,
289
- details: { 'Moderation Reasons': ['Derivative Works Filter'] },
290
- preview: null,
291
- }),
292
- ),
293
- };
294
-
295
- await expect(
296
- model.doGenerate({
297
- prompt: 'Generate something that triggers moderation',
298
- files: undefined,
299
- mask: undefined,
300
- n: 1,
301
- size: undefined,
302
- aspectRatio: undefined,
303
- seed: undefined,
304
- providerOptions: {},
305
- }),
306
- ).rejects.toThrow(
307
- 'Amazon Bedrock request was moderated: Derivative Works Filter',
308
- );
309
- });
310
-
311
- it('should throw error when no images are returned', async () => {
312
- server.urls[invokeUrl].response = {
313
- type: 'binary',
314
- headers: {
315
- 'content-type': 'application/json',
316
- },
317
- body: Buffer.from(
318
- JSON.stringify({
319
- images: [],
320
- }),
321
- ),
322
- };
323
-
324
- await expect(
325
- model.doGenerate({
326
- prompt: 'Generate an image',
327
- files: undefined,
328
- mask: undefined,
329
- n: 1,
330
- size: undefined,
331
- aspectRatio: undefined,
332
- seed: undefined,
333
- providerOptions: {},
334
- }),
335
- ).rejects.toThrow('Amazon Bedrock returned no images');
336
- });
337
- });
338
-
339
- describe('Image Editing', () => {
340
- const server = createTestServer({
341
- [invokeUrl]: {
342
- response: {
343
- type: 'binary',
344
- headers: {
345
- 'content-type': 'application/json',
346
- },
347
- body: Buffer.from(
348
- JSON.stringify({
349
- images: ['edited-image-base64'],
350
- }),
351
- ),
352
- },
353
- },
354
- });
355
-
356
- const model = new BedrockImageModel('amazon.nova-canvas-v1:0', {
357
- baseUrl: () => 'https://bedrock-runtime.us-east-1.amazonaws.com',
358
- headers: {},
359
- fetch: fakeFetchWithAuth,
360
- });
361
-
362
- it('should send inpainting request with files and maskPrompt', async () => {
363
- const imageData = new Uint8Array([137, 80, 78, 71]); // PNG magic bytes
364
-
365
- await model.doGenerate({
366
- prompt: 'a cute corgi dog',
367
- files: [
368
- {
369
- type: 'file',
370
- data: imageData,
371
- mediaType: 'image/png',
372
- },
373
- ],
374
- mask: undefined,
375
- n: 1,
376
- size: undefined,
377
- aspectRatio: undefined,
378
- seed: 42,
379
- providerOptions: {
380
- bedrock: {
381
- maskPrompt: 'cat',
382
- quality: 'standard',
383
- cfgScale: 7.0,
384
- },
385
- },
386
- });
387
-
388
- expect(await server.calls[0].requestBodyJson).toMatchInlineSnapshot(`
389
- {
390
- "imageGenerationConfig": {
391
- "cfgScale": 7,
392
- "numberOfImages": 1,
393
- "quality": "standard",
394
- "seed": 42,
395
- },
396
- "inPaintingParams": {
397
- "image": "iVBORw==",
398
- "maskPrompt": "cat",
399
- "text": "a cute corgi dog",
400
- },
401
- "taskType": "INPAINTING",
402
- }
403
- `);
404
- });
405
-
406
- it('should send inpainting request with files and mask image', async () => {
407
- const imageData = new Uint8Array([137, 80, 78, 71]);
408
- const maskData = new Uint8Array([255, 255, 255, 0]);
409
-
410
- await model.doGenerate({
411
- prompt: 'A sunlit indoor lounge area with a pool containing a flamingo',
412
- files: [
413
- {
414
- type: 'file',
415
- data: imageData,
416
- mediaType: 'image/png',
417
- },
418
- ],
419
- mask: {
420
- type: 'file',
421
- data: maskData,
422
- mediaType: 'image/png',
423
- },
424
- n: 1,
425
- size: undefined,
426
- aspectRatio: undefined,
427
- seed: undefined,
428
- providerOptions: {
429
- bedrock: {
430
- quality: 'standard',
431
- },
432
- },
433
- });
434
-
435
- expect(await server.calls[0].requestBodyJson).toMatchInlineSnapshot(`
436
- {
437
- "imageGenerationConfig": {
438
- "numberOfImages": 1,
439
- "quality": "standard",
440
- },
441
- "inPaintingParams": {
442
- "image": "iVBORw==",
443
- "maskImage": "////AA==",
444
- "text": "A sunlit indoor lounge area with a pool containing a flamingo",
445
- },
446
- "taskType": "INPAINTING",
447
- }
448
- `);
449
- });
450
-
451
- it('should send inpainting request with base64 string data', async () => {
452
- const base64Image =
453
- 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk';
454
-
455
- await model.doGenerate({
456
- prompt: 'Edit this image',
457
- files: [
458
- {
459
- type: 'file',
460
- data: base64Image,
461
- mediaType: 'image/png',
462
- },
463
- ],
464
- mask: undefined,
465
- n: 1,
466
- size: undefined,
467
- aspectRatio: undefined,
468
- seed: undefined,
469
- providerOptions: {
470
- bedrock: {
471
- maskPrompt: 'background',
472
- },
473
- },
474
- });
475
-
476
- const requestBody = await server.calls[0].requestBodyJson;
477
- expect(requestBody.taskType).toBe('INPAINTING');
478
- expect(requestBody.inPaintingParams.image).toBe(base64Image);
479
- });
480
-
481
- it('should include negativeText in inpainting params', async () => {
482
- const imageData = new Uint8Array([137, 80, 78, 71]);
483
-
484
- await model.doGenerate({
485
- prompt: 'a beautiful garden',
486
- files: [
487
- {
488
- type: 'file',
489
- data: imageData,
490
- mediaType: 'image/png',
491
- },
492
- ],
493
- mask: undefined,
494
- n: 1,
495
- size: undefined,
496
- aspectRatio: undefined,
497
- seed: undefined,
498
- providerOptions: {
499
- bedrock: {
500
- maskPrompt: 'sky',
501
- negativeText: 'clouds, rain',
502
- },
503
- },
504
- });
505
-
506
- expect(await server.calls[0].requestBodyJson).toMatchInlineSnapshot(`
507
- {
508
- "imageGenerationConfig": {
509
- "numberOfImages": 1,
510
- },
511
- "inPaintingParams": {
512
- "image": "iVBORw==",
513
- "maskPrompt": "sky",
514
- "negativeText": "clouds, rain",
515
- "text": "a beautiful garden",
516
- },
517
- "taskType": "INPAINTING",
518
- }
519
- `);
520
- });
521
-
522
- it('should extract edited images from response', async () => {
523
- const imageData = new Uint8Array([137, 80, 78, 71]);
524
-
525
- const result = await model.doGenerate({
526
- prompt: 'Edit this image',
527
- files: [
528
- {
529
- type: 'file',
530
- data: imageData,
531
- mediaType: 'image/png',
532
- },
533
- ],
534
- mask: undefined,
535
- n: 1,
536
- size: undefined,
537
- aspectRatio: undefined,
538
- seed: undefined,
539
- providerOptions: {
540
- bedrock: {
541
- maskPrompt: 'object',
542
- },
543
- },
544
- });
545
-
546
- expect(result.images).toStrictEqual(['edited-image-base64']);
547
- });
548
-
549
- it('should throw error for URL-based images', async () => {
550
- await expect(
551
- model.doGenerate({
552
- prompt: 'Edit this image',
553
- files: [
554
- {
555
- type: 'url',
556
- url: 'https://example.com/image.png',
557
- },
558
- ],
559
- mask: undefined,
560
- n: 1,
561
- size: undefined,
562
- aspectRatio: undefined,
563
- seed: undefined,
564
- providerOptions: {},
565
- }),
566
- ).rejects.toThrow(
567
- 'URL-based images are not supported for Amazon Bedrock image editing.',
568
- );
569
- });
570
-
571
- it('should send outpainting request with taskType OUTPAINTING', async () => {
572
- const imageData = new Uint8Array([137, 80, 78, 71]);
573
- const maskData = new Uint8Array([255, 255, 255, 0]);
574
-
575
- await model.doGenerate({
576
- prompt: 'Extend the background with a beautiful sunset',
577
- files: [
578
- {
579
- type: 'file',
580
- data: imageData,
581
- mediaType: 'image/png',
582
- },
583
- ],
584
- mask: {
585
- type: 'file',
586
- data: maskData,
587
- mediaType: 'image/png',
588
- },
589
- n: 1,
590
- size: undefined,
591
- aspectRatio: undefined,
592
- seed: undefined,
593
- providerOptions: {
594
- bedrock: {
595
- taskType: 'OUTPAINTING',
596
- outPaintingMode: 'DEFAULT',
597
- negativeText: 'bad quality',
598
- },
599
- },
600
- });
601
-
602
- expect(await server.calls[0].requestBodyJson).toMatchInlineSnapshot(`
603
- {
604
- "imageGenerationConfig": {
605
- "numberOfImages": 1,
606
- },
607
- "outPaintingParams": {
608
- "image": "iVBORw==",
609
- "maskImage": "////AA==",
610
- "negativeText": "bad quality",
611
- "outPaintingMode": "DEFAULT",
612
- "text": "Extend the background with a beautiful sunset",
613
- },
614
- "taskType": "OUTPAINTING",
615
- }
616
- `);
617
- });
618
-
619
- it('should send outpainting request with maskPrompt', async () => {
620
- const imageData = new Uint8Array([137, 80, 78, 71]);
621
-
622
- await model.doGenerate({
623
- prompt: 'Replace the background with mountains',
624
- files: [
625
- {
626
- type: 'file',
627
- data: imageData,
628
- mediaType: 'image/png',
629
- },
630
- ],
631
- mask: undefined,
632
- n: 1,
633
- size: undefined,
634
- aspectRatio: undefined,
635
- seed: undefined,
636
- providerOptions: {
637
- bedrock: {
638
- taskType: 'OUTPAINTING',
639
- maskPrompt: 'background',
640
- },
641
- },
642
- });
643
-
644
- expect(await server.calls[0].requestBodyJson).toMatchInlineSnapshot(`
645
- {
646
- "imageGenerationConfig": {
647
- "numberOfImages": 1,
648
- },
649
- "outPaintingParams": {
650
- "image": "iVBORw==",
651
- "maskPrompt": "background",
652
- "text": "Replace the background with mountains",
653
- },
654
- "taskType": "OUTPAINTING",
655
- }
656
- `);
657
- });
658
-
659
- it('should send background removal request', async () => {
660
- const imageData = new Uint8Array([137, 80, 78, 71]);
661
-
662
- await model.doGenerate({
663
- prompt: undefined,
664
- files: [
665
- {
666
- type: 'file',
667
- data: imageData,
668
- mediaType: 'image/png',
669
- },
670
- ],
671
- mask: undefined,
672
- n: 1,
673
- size: undefined,
674
- aspectRatio: undefined,
675
- seed: undefined,
676
- providerOptions: {
677
- bedrock: {
678
- taskType: 'BACKGROUND_REMOVAL',
679
- },
680
- },
681
- });
682
-
683
- expect(await server.calls[0].requestBodyJson).toMatchInlineSnapshot(`
684
- {
685
- "backgroundRemovalParams": {
686
- "image": "iVBORw==",
687
- },
688
- "taskType": "BACKGROUND_REMOVAL",
689
- }
690
- `);
691
- });
692
-
693
- it('should send image variation request with single image', async () => {
694
- const imageData = new Uint8Array([137, 80, 78, 71]);
695
-
696
- await model.doGenerate({
697
- prompt: 'Create a variation in anime style',
698
- files: [
699
- {
700
- type: 'file',
701
- data: imageData,
702
- mediaType: 'image/png',
703
- },
704
- ],
705
- mask: undefined,
706
- n: 3,
707
- size: '512x512',
708
- aspectRatio: undefined,
709
- seed: undefined,
710
- providerOptions: {
711
- bedrock: {
712
- taskType: 'IMAGE_VARIATION',
713
- similarityStrength: 0.7,
714
- negativeText: 'bad quality, low resolution',
715
- },
716
- },
717
- });
718
-
719
- expect(await server.calls[0].requestBodyJson).toMatchInlineSnapshot(`
720
- {
721
- "imageGenerationConfig": {
722
- "height": 512,
723
- "numberOfImages": 3,
724
- "width": 512,
725
- },
726
- "imageVariationParams": {
727
- "images": [
728
- "iVBORw==",
729
- ],
730
- "negativeText": "bad quality, low resolution",
731
- "similarityStrength": 0.7,
732
- "text": "Create a variation in anime style",
733
- },
734
- "taskType": "IMAGE_VARIATION",
735
- }
736
- `);
737
- });
738
-
739
- it('should send image variation request with multiple images', async () => {
740
- const image1 = new Uint8Array([137, 80, 78, 71]);
741
- const image2 = new Uint8Array([255, 216, 255, 224]);
742
-
743
- await model.doGenerate({
744
- prompt: 'Combine these images into one cohesive scene',
745
- files: [
746
- {
747
- type: 'file',
748
- data: image1,
749
- mediaType: 'image/png',
750
- },
751
- {
752
- type: 'file',
753
- data: image2,
754
- mediaType: 'image/jpeg',
755
- },
756
- ],
757
- mask: undefined,
758
- n: 1,
759
- size: undefined,
760
- aspectRatio: undefined,
761
- seed: undefined,
762
- providerOptions: {
763
- bedrock: {
764
- taskType: 'IMAGE_VARIATION',
765
- },
766
- },
767
- });
768
-
769
- expect(await server.calls[0].requestBodyJson).toMatchInlineSnapshot(`
770
- {
771
- "imageGenerationConfig": {
772
- "numberOfImages": 1,
773
- },
774
- "imageVariationParams": {
775
- "images": [
776
- "iVBORw==",
777
- "/9j/4A==",
778
- ],
779
- "text": "Combine these images into one cohesive scene",
780
- },
781
- "taskType": "IMAGE_VARIATION",
782
- }
783
- `);
784
- });
785
-
786
- it('should default to IMAGE_VARIATION when files provided without mask or maskPrompt', async () => {
787
- const imageData = new Uint8Array([137, 80, 78, 71]);
788
-
789
- await model.doGenerate({
790
- prompt: 'Create variations',
791
- files: [
792
- {
793
- type: 'file',
794
- data: imageData,
795
- mediaType: 'image/png',
796
- },
797
- ],
798
- mask: undefined,
799
- n: 1,
800
- size: undefined,
801
- aspectRatio: undefined,
802
- seed: undefined,
803
- providerOptions: {},
804
- });
805
-
806
- const requestBody = await server.calls[0].requestBodyJson;
807
- expect(requestBody.taskType).toBe('IMAGE_VARIATION');
808
- });
809
-
810
- it('should default to INPAINTING when files provided with mask', async () => {
811
- const imageData = new Uint8Array([137, 80, 78, 71]);
812
- const maskData = new Uint8Array([255, 255, 255, 0]);
813
-
814
- await model.doGenerate({
815
- prompt: 'Edit masked area',
816
- files: [
817
- {
818
- type: 'file',
819
- data: imageData,
820
- mediaType: 'image/png',
821
- },
822
- ],
823
- mask: {
824
- type: 'file',
825
- data: maskData,
826
- mediaType: 'image/png',
827
- },
828
- n: 1,
829
- size: undefined,
830
- aspectRatio: undefined,
831
- seed: undefined,
832
- providerOptions: {},
833
- });
834
-
835
- const requestBody = await server.calls[0].requestBodyJson;
836
- expect(requestBody.taskType).toBe('INPAINTING');
837
- });
838
-
839
- it('should default to INPAINTING when files provided with maskPrompt', async () => {
840
- const imageData = new Uint8Array([137, 80, 78, 71]);
841
-
842
- await model.doGenerate({
843
- prompt: 'Edit the cat',
844
- files: [
845
- {
846
- type: 'file',
847
- data: imageData,
848
- mediaType: 'image/png',
849
- },
850
- ],
851
- mask: undefined,
852
- n: 1,
853
- size: undefined,
854
- aspectRatio: undefined,
855
- seed: undefined,
856
- providerOptions: {
857
- bedrock: {
858
- maskPrompt: 'cat',
859
- },
860
- },
861
- });
862
-
863
- const requestBody = await server.calls[0].requestBodyJson;
864
- expect(requestBody.taskType).toBe('INPAINTING');
865
- });
866
- });