@ai-sdk/amazon-bedrock 4.0.24 → 4.0.26
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 +16 -0
- package/dist/anthropic/index.js +1 -1
- package/dist/anthropic/index.mjs +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/docs/08-amazon-bedrock.mdx +1453 -0
- package/package.json +11 -6
- package/src/__fixtures__/bedrock-json-only-text-first.1.chunks.txt +7 -0
- package/src/__fixtures__/bedrock-json-other-tool.1.chunks.txt +6 -0
- package/src/__fixtures__/bedrock-json-other-tool.1.json +24 -0
- package/src/__fixtures__/bedrock-json-tool-text-then-weather-then-json.1.chunks.txt +12 -0
- package/src/__fixtures__/bedrock-json-tool-with-answer.1.json +29 -0
- package/src/__fixtures__/bedrock-json-tool.1.chunks.txt +4 -0
- package/src/__fixtures__/bedrock-json-tool.1.json +35 -0
- package/src/__fixtures__/bedrock-json-tool.2.chunks.txt +6 -0
- package/src/__fixtures__/bedrock-json-tool.2.json +28 -0
- package/src/__fixtures__/bedrock-json-tool.3.chunks.txt +7 -0
- package/src/__fixtures__/bedrock-json-tool.3.json +36 -0
- package/src/__fixtures__/bedrock-json-with-tool.1.chunks.txt +9 -0
- package/src/__fixtures__/bedrock-json-with-tool.1.json +41 -0
- package/src/__fixtures__/bedrock-json-with-tools.1.chunks.txt +12 -0
- package/src/__fixtures__/bedrock-json-with-tools.1.json +50 -0
- package/src/__fixtures__/bedrock-tool-call.1.chunks.txt +6 -0
- package/src/__fixtures__/bedrock-tool-call.1.json +24 -0
- package/src/__fixtures__/bedrock-tool-no-args.chunks.txt +8 -0
- package/src/__fixtures__/bedrock-tool-no-args.json +25 -0
- package/src/anthropic/bedrock-anthropic-fetch.test.ts +344 -0
- package/src/anthropic/bedrock-anthropic-fetch.ts +62 -0
- package/src/anthropic/bedrock-anthropic-options.ts +28 -0
- package/src/anthropic/bedrock-anthropic-provider.test.ts +456 -0
- package/src/anthropic/bedrock-anthropic-provider.ts +357 -0
- package/src/anthropic/index.ts +9 -0
- package/src/bedrock-api-types.ts +195 -0
- package/src/bedrock-chat-language-model.test.ts +4569 -0
- package/src/bedrock-chat-language-model.ts +1019 -0
- package/src/bedrock-chat-options.ts +114 -0
- package/src/bedrock-embedding-model.test.ts +148 -0
- package/src/bedrock-embedding-model.ts +104 -0
- package/src/bedrock-embedding-options.ts +24 -0
- package/src/bedrock-error.ts +6 -0
- package/src/bedrock-event-stream-decoder.ts +59 -0
- package/src/bedrock-event-stream-response-handler.test.ts +233 -0
- package/src/bedrock-event-stream-response-handler.ts +57 -0
- package/src/bedrock-image-model.test.ts +866 -0
- package/src/bedrock-image-model.ts +297 -0
- package/src/bedrock-image-settings.ts +6 -0
- package/src/bedrock-prepare-tools.ts +190 -0
- package/src/bedrock-provider.test.ts +457 -0
- package/src/bedrock-provider.ts +351 -0
- package/src/bedrock-sigv4-fetch.test.ts +675 -0
- package/src/bedrock-sigv4-fetch.ts +138 -0
- package/src/convert-bedrock-usage.test.ts +207 -0
- package/src/convert-bedrock-usage.ts +50 -0
- package/src/convert-to-bedrock-chat-messages.test.ts +1175 -0
- package/src/convert-to-bedrock-chat-messages.ts +452 -0
- package/src/index.ts +10 -0
- package/src/inject-fetch-headers.test.ts +135 -0
- package/src/inject-fetch-headers.ts +32 -0
- package/src/map-bedrock-finish-reason.ts +22 -0
- package/src/normalize-tool-call-id.test.ts +72 -0
- package/src/normalize-tool-call-id.ts +36 -0
- package/src/reranking/__fixtures__/bedrock-reranking.1.json +12 -0
- package/src/reranking/bedrock-reranking-api.ts +44 -0
- package/src/reranking/bedrock-reranking-model.test.ts +299 -0
- package/src/reranking/bedrock-reranking-model.ts +115 -0
- package/src/reranking/bedrock-reranking-options.ts +36 -0
- package/src/version.ts +6 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FetchFunction,
|
|
3
|
+
combineHeaders,
|
|
4
|
+
normalizeHeaders,
|
|
5
|
+
withUserAgentSuffix,
|
|
6
|
+
getRuntimeEnvironmentUserAgent,
|
|
7
|
+
} from '@ai-sdk/provider-utils';
|
|
8
|
+
import { AwsV4Signer } from 'aws4fetch';
|
|
9
|
+
import { VERSION } from './version';
|
|
10
|
+
|
|
11
|
+
export interface BedrockCredentials {
|
|
12
|
+
region: string;
|
|
13
|
+
accessKeyId: string;
|
|
14
|
+
secretAccessKey: string;
|
|
15
|
+
sessionToken?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
Creates a fetch function that applies AWS Signature Version 4 signing.
|
|
20
|
+
|
|
21
|
+
@param getCredentials - Function that returns the AWS credentials to use when signing.
|
|
22
|
+
@param fetch - Optional original fetch implementation to wrap. Defaults to global fetch.
|
|
23
|
+
@returns A FetchFunction that signs requests before passing them to the underlying fetch.
|
|
24
|
+
*/
|
|
25
|
+
export function createSigV4FetchFunction(
|
|
26
|
+
getCredentials: () => BedrockCredentials | PromiseLike<BedrockCredentials>,
|
|
27
|
+
fetch: FetchFunction = globalThis.fetch,
|
|
28
|
+
): FetchFunction {
|
|
29
|
+
return async (
|
|
30
|
+
input: RequestInfo | URL,
|
|
31
|
+
init?: RequestInit,
|
|
32
|
+
): Promise<Response> => {
|
|
33
|
+
const request = input instanceof Request ? input : undefined;
|
|
34
|
+
const originalHeaders = combineHeaders(
|
|
35
|
+
normalizeHeaders(request?.headers),
|
|
36
|
+
normalizeHeaders(init?.headers),
|
|
37
|
+
);
|
|
38
|
+
const headersWithUserAgent = withUserAgentSuffix(
|
|
39
|
+
originalHeaders,
|
|
40
|
+
`ai-sdk/amazon-bedrock/${VERSION}`,
|
|
41
|
+
getRuntimeEnvironmentUserAgent(),
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
let effectiveBody: BodyInit | undefined = init?.body ?? undefined;
|
|
45
|
+
if (effectiveBody === undefined && request && request.body !== null) {
|
|
46
|
+
try {
|
|
47
|
+
effectiveBody = await request.clone().text();
|
|
48
|
+
} catch {}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const effectiveMethod = init?.method ?? request?.method;
|
|
52
|
+
|
|
53
|
+
if (effectiveMethod?.toUpperCase() !== 'POST' || !effectiveBody) {
|
|
54
|
+
return fetch(input, {
|
|
55
|
+
...init,
|
|
56
|
+
headers: headersWithUserAgent as HeadersInit,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const url =
|
|
61
|
+
typeof input === 'string'
|
|
62
|
+
? input
|
|
63
|
+
: input instanceof URL
|
|
64
|
+
? input.href
|
|
65
|
+
: input.url;
|
|
66
|
+
|
|
67
|
+
const body = prepareBodyString(effectiveBody);
|
|
68
|
+
const credentials = await getCredentials();
|
|
69
|
+
const signer = new AwsV4Signer({
|
|
70
|
+
url,
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: Object.entries(headersWithUserAgent),
|
|
73
|
+
body,
|
|
74
|
+
region: credentials.region,
|
|
75
|
+
accessKeyId: credentials.accessKeyId,
|
|
76
|
+
secretAccessKey: credentials.secretAccessKey,
|
|
77
|
+
sessionToken: credentials.sessionToken,
|
|
78
|
+
service: 'bedrock',
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const signingResult = await signer.sign();
|
|
82
|
+
const signedHeaders = normalizeHeaders(signingResult.headers);
|
|
83
|
+
|
|
84
|
+
// Use the combined headers directly as HeadersInit
|
|
85
|
+
const combinedHeaders = combineHeaders(headersWithUserAgent, signedHeaders);
|
|
86
|
+
|
|
87
|
+
return fetch(input, {
|
|
88
|
+
...init,
|
|
89
|
+
body,
|
|
90
|
+
headers: combinedHeaders as HeadersInit,
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function prepareBodyString(body: BodyInit | undefined): string {
|
|
96
|
+
if (typeof body === 'string') {
|
|
97
|
+
return body;
|
|
98
|
+
} else if (body instanceof Uint8Array) {
|
|
99
|
+
return new TextDecoder().decode(body);
|
|
100
|
+
} else if (body instanceof ArrayBuffer) {
|
|
101
|
+
return new TextDecoder().decode(new Uint8Array(body));
|
|
102
|
+
} else {
|
|
103
|
+
return JSON.stringify(body);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
Creates a fetch function that applies Bearer token authentication.
|
|
109
|
+
|
|
110
|
+
@param apiKey - The API key to use for Bearer token authentication.
|
|
111
|
+
@param fetch - Optional original fetch implementation to wrap. Defaults to global fetch.
|
|
112
|
+
@returns A FetchFunction that adds Authorization header with Bearer token to requests.
|
|
113
|
+
*/
|
|
114
|
+
export function createApiKeyFetchFunction(
|
|
115
|
+
apiKey: string,
|
|
116
|
+
fetch: FetchFunction = globalThis.fetch,
|
|
117
|
+
): FetchFunction {
|
|
118
|
+
return async (
|
|
119
|
+
input: RequestInfo | URL,
|
|
120
|
+
init?: RequestInit,
|
|
121
|
+
): Promise<Response> => {
|
|
122
|
+
const originalHeaders = normalizeHeaders(init?.headers);
|
|
123
|
+
const headersWithUserAgent = withUserAgentSuffix(
|
|
124
|
+
originalHeaders,
|
|
125
|
+
`ai-sdk/amazon-bedrock/${VERSION}`,
|
|
126
|
+
getRuntimeEnvironmentUserAgent(),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const finalHeaders = combineHeaders(headersWithUserAgent, {
|
|
130
|
+
Authorization: `Bearer ${apiKey}`,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
return fetch(input, {
|
|
134
|
+
...init,
|
|
135
|
+
headers: finalHeaders as HeadersInit,
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { convertBedrockUsage } from './convert-bedrock-usage';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
|
|
4
|
+
describe('convertBedrockUsage', () => {
|
|
5
|
+
it('should convert basic usage without cache tokens', () => {
|
|
6
|
+
const result = convertBedrockUsage({
|
|
7
|
+
inputTokens: 100,
|
|
8
|
+
outputTokens: 50,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
expect(result).toEqual({
|
|
12
|
+
inputTokens: {
|
|
13
|
+
total: 100,
|
|
14
|
+
noCache: 100,
|
|
15
|
+
cacheRead: 0,
|
|
16
|
+
cacheWrite: 0,
|
|
17
|
+
},
|
|
18
|
+
outputTokens: {
|
|
19
|
+
total: 50,
|
|
20
|
+
text: 50,
|
|
21
|
+
reasoning: undefined,
|
|
22
|
+
},
|
|
23
|
+
raw: {
|
|
24
|
+
inputTokens: 100,
|
|
25
|
+
outputTokens: 50,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should convert usage with cache read tokens', () => {
|
|
31
|
+
const result = convertBedrockUsage({
|
|
32
|
+
inputTokens: 100,
|
|
33
|
+
outputTokens: 50,
|
|
34
|
+
cacheReadInputTokens: 80,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
expect(result).toEqual({
|
|
38
|
+
inputTokens: {
|
|
39
|
+
total: 180, // 100 + 80 + 0
|
|
40
|
+
noCache: 100,
|
|
41
|
+
cacheRead: 80,
|
|
42
|
+
cacheWrite: 0,
|
|
43
|
+
},
|
|
44
|
+
outputTokens: {
|
|
45
|
+
total: 50,
|
|
46
|
+
text: 50,
|
|
47
|
+
reasoning: undefined,
|
|
48
|
+
},
|
|
49
|
+
raw: {
|
|
50
|
+
inputTokens: 100,
|
|
51
|
+
outputTokens: 50,
|
|
52
|
+
cacheReadInputTokens: 80,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should convert usage with cache write tokens', () => {
|
|
58
|
+
const result = convertBedrockUsage({
|
|
59
|
+
inputTokens: 100,
|
|
60
|
+
outputTokens: 50,
|
|
61
|
+
cacheWriteInputTokens: 60,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
expect(result).toEqual({
|
|
65
|
+
inputTokens: {
|
|
66
|
+
total: 160, // 100 + 0 + 60
|
|
67
|
+
noCache: 100,
|
|
68
|
+
cacheRead: 0,
|
|
69
|
+
cacheWrite: 60,
|
|
70
|
+
},
|
|
71
|
+
outputTokens: {
|
|
72
|
+
total: 50,
|
|
73
|
+
text: 50,
|
|
74
|
+
reasoning: undefined,
|
|
75
|
+
},
|
|
76
|
+
raw: {
|
|
77
|
+
inputTokens: 100,
|
|
78
|
+
outputTokens: 50,
|
|
79
|
+
cacheWriteInputTokens: 60,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should convert usage with both cache read and write tokens', () => {
|
|
85
|
+
const result = convertBedrockUsage({
|
|
86
|
+
inputTokens: 100,
|
|
87
|
+
outputTokens: 50,
|
|
88
|
+
cacheReadInputTokens: 80,
|
|
89
|
+
cacheWriteInputTokens: 60,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
expect(result).toEqual({
|
|
93
|
+
inputTokens: {
|
|
94
|
+
total: 240, // 100 + 80 + 60
|
|
95
|
+
noCache: 100,
|
|
96
|
+
cacheRead: 80,
|
|
97
|
+
cacheWrite: 60,
|
|
98
|
+
},
|
|
99
|
+
outputTokens: {
|
|
100
|
+
total: 50,
|
|
101
|
+
text: 50,
|
|
102
|
+
reasoning: undefined,
|
|
103
|
+
},
|
|
104
|
+
raw: {
|
|
105
|
+
inputTokens: 100,
|
|
106
|
+
outputTokens: 50,
|
|
107
|
+
cacheReadInputTokens: 80,
|
|
108
|
+
cacheWriteInputTokens: 60,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should handle null cache tokens', () => {
|
|
114
|
+
const result = convertBedrockUsage({
|
|
115
|
+
inputTokens: 100,
|
|
116
|
+
outputTokens: 50,
|
|
117
|
+
cacheReadInputTokens: null,
|
|
118
|
+
cacheWriteInputTokens: null,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
expect(result).toEqual({
|
|
122
|
+
inputTokens: {
|
|
123
|
+
total: 100,
|
|
124
|
+
noCache: 100,
|
|
125
|
+
cacheRead: 0,
|
|
126
|
+
cacheWrite: 0,
|
|
127
|
+
},
|
|
128
|
+
outputTokens: {
|
|
129
|
+
total: 50,
|
|
130
|
+
text: 50,
|
|
131
|
+
reasoning: undefined,
|
|
132
|
+
},
|
|
133
|
+
raw: {
|
|
134
|
+
inputTokens: 100,
|
|
135
|
+
outputTokens: 50,
|
|
136
|
+
cacheReadInputTokens: null,
|
|
137
|
+
cacheWriteInputTokens: null,
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should handle null usage', () => {
|
|
143
|
+
const result = convertBedrockUsage(null);
|
|
144
|
+
|
|
145
|
+
expect(result).toEqual({
|
|
146
|
+
inputTokens: {
|
|
147
|
+
total: undefined,
|
|
148
|
+
noCache: undefined,
|
|
149
|
+
cacheRead: undefined,
|
|
150
|
+
cacheWrite: undefined,
|
|
151
|
+
},
|
|
152
|
+
outputTokens: {
|
|
153
|
+
total: undefined,
|
|
154
|
+
text: undefined,
|
|
155
|
+
reasoning: undefined,
|
|
156
|
+
},
|
|
157
|
+
raw: undefined,
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should handle undefined usage', () => {
|
|
162
|
+
const result = convertBedrockUsage(undefined);
|
|
163
|
+
|
|
164
|
+
expect(result).toEqual({
|
|
165
|
+
inputTokens: {
|
|
166
|
+
total: undefined,
|
|
167
|
+
noCache: undefined,
|
|
168
|
+
cacheRead: undefined,
|
|
169
|
+
cacheWrite: undefined,
|
|
170
|
+
},
|
|
171
|
+
outputTokens: {
|
|
172
|
+
total: undefined,
|
|
173
|
+
text: undefined,
|
|
174
|
+
reasoning: undefined,
|
|
175
|
+
},
|
|
176
|
+
raw: undefined,
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should include totalTokens in raw when provided', () => {
|
|
181
|
+
const result = convertBedrockUsage({
|
|
182
|
+
inputTokens: 100,
|
|
183
|
+
outputTokens: 50,
|
|
184
|
+
totalTokens: 150,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
expect(result.raw).toEqual({
|
|
188
|
+
inputTokens: 100,
|
|
189
|
+
outputTokens: 50,
|
|
190
|
+
totalTokens: 150,
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should preserve raw usage data', () => {
|
|
195
|
+
const rawUsage = {
|
|
196
|
+
inputTokens: 100,
|
|
197
|
+
outputTokens: 50,
|
|
198
|
+
totalTokens: 150,
|
|
199
|
+
cacheReadInputTokens: 80,
|
|
200
|
+
cacheWriteInputTokens: 60,
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const result = convertBedrockUsage(rawUsage);
|
|
204
|
+
|
|
205
|
+
expect(result.raw).toEqual(rawUsage);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { LanguageModelV3Usage } from '@ai-sdk/provider';
|
|
2
|
+
|
|
3
|
+
export type BedrockUsage = {
|
|
4
|
+
inputTokens: number;
|
|
5
|
+
outputTokens: number;
|
|
6
|
+
totalTokens?: number;
|
|
7
|
+
cacheReadInputTokens?: number | null;
|
|
8
|
+
cacheWriteInputTokens?: number | null;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function convertBedrockUsage(
|
|
12
|
+
usage: BedrockUsage | undefined | null,
|
|
13
|
+
): LanguageModelV3Usage {
|
|
14
|
+
if (usage == null) {
|
|
15
|
+
return {
|
|
16
|
+
inputTokens: {
|
|
17
|
+
total: undefined,
|
|
18
|
+
noCache: undefined,
|
|
19
|
+
cacheRead: undefined,
|
|
20
|
+
cacheWrite: undefined,
|
|
21
|
+
},
|
|
22
|
+
outputTokens: {
|
|
23
|
+
total: undefined,
|
|
24
|
+
text: undefined,
|
|
25
|
+
reasoning: undefined,
|
|
26
|
+
},
|
|
27
|
+
raw: undefined,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const inputTokens = usage.inputTokens;
|
|
32
|
+
const outputTokens = usage.outputTokens;
|
|
33
|
+
const cacheReadTokens = usage.cacheReadInputTokens ?? 0;
|
|
34
|
+
const cacheWriteTokens = usage.cacheWriteInputTokens ?? 0;
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
inputTokens: {
|
|
38
|
+
total: inputTokens + cacheReadTokens + cacheWriteTokens,
|
|
39
|
+
noCache: inputTokens,
|
|
40
|
+
cacheRead: cacheReadTokens,
|
|
41
|
+
cacheWrite: cacheWriteTokens,
|
|
42
|
+
},
|
|
43
|
+
outputTokens: {
|
|
44
|
+
total: outputTokens,
|
|
45
|
+
text: outputTokens,
|
|
46
|
+
reasoning: undefined,
|
|
47
|
+
},
|
|
48
|
+
raw: usage,
|
|
49
|
+
};
|
|
50
|
+
}
|