@tanstack/ai-bedrock 0.1.4 → 0.1.6
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/dist/esm/adapters/converse-text.js +404 -420
- package/dist/esm/adapters/converse-text.js.map +1 -1
- package/dist/esm/adapters/responses-text.js +24 -18
- package/dist/esm/adapters/responses-text.js.map +1 -1
- package/dist/esm/adapters/text.js +41 -32
- package/dist/esm/adapters/text.js.map +1 -1
- package/dist/esm/converse/message-converter.js +112 -158
- package/dist/esm/converse/message-converter.js.map +1 -1
- package/dist/esm/converse/stream-processor.js +220 -198
- package/dist/esm/converse/stream-processor.js.map +1 -1
- package/dist/esm/converse/structured-output.js +19 -18
- package/dist/esm/converse/structured-output.js.map +1 -1
- package/dist/esm/converse/tool-converter.js +20 -17
- package/dist/esm/converse/tool-converter.js.map +1 -1
- package/dist/esm/index.js +48 -49
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/model-catalog.generated.js +170 -89
- package/dist/esm/model-catalog.generated.js.map +1 -1
- package/dist/esm/model-meta.js +9 -13
- package/dist/esm/model-meta.js.map +1 -1
- package/dist/esm/utils/auth.js +33 -43
- package/dist/esm/utils/auth.js.map +1 -1
- package/dist/esm/utils/client.js +30 -29
- package/dist/esm/utils/client.js.map +1 -1
- package/dist/esm/utils/openai-sigv4-fetch.js +36 -31
- package/dist/esm/utils/openai-sigv4-fetch.js.map +1 -1
- package/package.json +6 -6
|
@@ -1,430 +1,414 @@
|
|
|
1
|
-
import { EventType, convertSchemaToJsonSchema } from "@tanstack/ai";
|
|
2
|
-
import { BaseTextAdapter } from "@tanstack/ai/adapters";
|
|
3
|
-
import { toRunErrorPayload } from "@tanstack/ai/adapter-internals";
|
|
4
1
|
import { resolveBedrockAuth } from "../utils/auth.js";
|
|
5
2
|
import { toConverseMessages } from "../converse/message-converter.js";
|
|
6
3
|
import { toToolConfig } from "../converse/tool-converter.js";
|
|
7
4
|
import { processConverseStream, throwIfConverseStreamError } from "../converse/stream-processor.js";
|
|
8
|
-
import { buildStructuredToolConfig
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
const stop = modelOptions?.stop;
|
|
383
|
-
const stopSequences = stop == null ? void 0 : Array.isArray(stop) ? stop : [stop];
|
|
384
|
-
const inferenceConfig = temperature != null || topP != null || maxTokens != null || stopSequences != null ? {
|
|
385
|
-
...temperature != null && { temperature },
|
|
386
|
-
...topP != null && { topP },
|
|
387
|
-
...maxTokens != null && { maxTokens },
|
|
388
|
-
...stopSequences != null && { stopSequences }
|
|
389
|
-
} : void 0;
|
|
390
|
-
return {
|
|
391
|
-
modelId: this.model,
|
|
392
|
-
messages,
|
|
393
|
-
...system.length > 0 && { system },
|
|
394
|
-
...toolConfig && { toolConfig },
|
|
395
|
-
...inferenceConfig && { inferenceConfig }
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
}
|
|
5
|
+
import { buildStructuredToolConfig } from "../converse/structured-output.js";
|
|
6
|
+
import { EventType, convertSchemaToJsonSchema } from "@tanstack/ai";
|
|
7
|
+
import { BaseTextAdapter } from "@tanstack/ai/adapters";
|
|
8
|
+
import { toRunErrorPayload } from "@tanstack/ai/adapter-internals";
|
|
9
|
+
//#region src/adapters/converse-text.ts
|
|
10
|
+
/**
|
|
11
|
+
* Bedrock Converse text adapter. Wires the Converse translation modules (message
|
|
12
|
+
* converter, tool converter, stream processor, structured-output forced-tool
|
|
13
|
+
* builder) onto `@tanstack/ai`'s `BaseTextAdapter` and the
|
|
14
|
+
* `@aws-sdk/client-bedrock-runtime` `BedrockRuntimeClient`.
|
|
15
|
+
*
|
|
16
|
+
* The success-path AG-UI lifecycle (`RUN_STARTED`..`RUN_FINISHED`) is owned by
|
|
17
|
+
* `processConverseStream`; this adapter only owns the catch/`RUN_ERROR` path,
|
|
18
|
+
* mirroring openai-base's `chatStream`.
|
|
19
|
+
*
|
|
20
|
+
* The actual SDK calls live behind two protected seams (`sendStream` / `send`)
|
|
21
|
+
* so tests can subclass and inject canned Converse SDK shapes without a real
|
|
22
|
+
* AWS request.
|
|
23
|
+
*/
|
|
24
|
+
var BedrockConverseTextAdapter = class extends BaseTextAdapter {
|
|
25
|
+
kind = "text";
|
|
26
|
+
name = "bedrock-converse";
|
|
27
|
+
clientPromise;
|
|
28
|
+
clientConfig;
|
|
29
|
+
constructor(config, model) {
|
|
30
|
+
super({}, model);
|
|
31
|
+
this.clientConfig = config;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Dynamically import `@aws-sdk/client-bedrock-runtime`. The specifier is held
|
|
35
|
+
* in a variable (not a string literal) so bundler dep scanners (e.g. Vite/
|
|
36
|
+
* esbuild optimizeDeps) cannot statically discover the AWS SDK and try to
|
|
37
|
+
* pre-bundle it for the browser — it would fail on the SDK's Node-only
|
|
38
|
+
* `fromTokenFile` export chain. The SDK is Node/server-only and is only
|
|
39
|
+
* reached on a real request. `typeof import(...)` is a type-only reference
|
|
40
|
+
* (erased at emit) so the imported members keep full typing.
|
|
41
|
+
*/
|
|
42
|
+
importBedrockRuntime() {
|
|
43
|
+
return import(
|
|
44
|
+
/* @vite-ignore */
|
|
45
|
+
"@aws-sdk/client-bedrock-runtime"
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Lazily construct the `BedrockRuntimeClient`. The dynamic import keeps
|
|
50
|
+
* `@aws-sdk/client-bedrock-runtime` out of the static/browser graph and
|
|
51
|
+
* defers `resolveBedrockAuth` until a real request is made.
|
|
52
|
+
*/
|
|
53
|
+
async getClient() {
|
|
54
|
+
if (!this.clientPromise) this.clientPromise = (async () => {
|
|
55
|
+
const { BedrockRuntimeClient } = await this.importBedrockRuntime();
|
|
56
|
+
const region = this.clientConfig.region ?? "us-east-1";
|
|
57
|
+
const resolved = resolveBedrockAuth({
|
|
58
|
+
apiKey: this.clientConfig.apiKey,
|
|
59
|
+
region,
|
|
60
|
+
auth: this.clientConfig.auth
|
|
61
|
+
}, "runtime");
|
|
62
|
+
return new BedrockRuntimeClient(this.buildClientConfig(resolved, region, this.clientConfig.baseURL));
|
|
63
|
+
})().catch((error) => {
|
|
64
|
+
this.clientPromise = void 0;
|
|
65
|
+
throw error;
|
|
66
|
+
});
|
|
67
|
+
return this.clientPromise;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Map resolved auth + endpoint to a `BedrockRuntimeClientConfig`.
|
|
71
|
+
*
|
|
72
|
+
* Recent `@aws-sdk/client-bedrock-runtime` exposes a first-class `token`
|
|
73
|
+
* config field for Bedrock API-key bearer auth. But the client's default
|
|
74
|
+
* auth-scheme order is SigV4 first, then bearer — so passing `token` alone is
|
|
75
|
+
* not enough: the SDK still resolves SigV4 and throws "Could not load
|
|
76
|
+
* credentials from any providers". Pinning `authSchemePreference` to the
|
|
77
|
+
* bearer scheme makes the API key actually get used. SigV4 uses the AWS
|
|
78
|
+
* credential provider chain and the default scheme order.
|
|
79
|
+
*/
|
|
80
|
+
buildClientConfig(resolved, region, endpoint) {
|
|
81
|
+
if (resolved.kind === "bearer") return {
|
|
82
|
+
region,
|
|
83
|
+
token: { token: resolved.token },
|
|
84
|
+
authSchemePreference: ["httpBearerAuth"],
|
|
85
|
+
...endpoint ? { endpoint } : {}
|
|
86
|
+
};
|
|
87
|
+
return {
|
|
88
|
+
region: resolved.region,
|
|
89
|
+
credentials: resolved.credentials,
|
|
90
|
+
...endpoint ? { endpoint } : {}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async sendStream(input) {
|
|
94
|
+
const { ConverseStreamCommand } = await this.importBedrockRuntime();
|
|
95
|
+
const res = await (await this.getClient()).send(new ConverseStreamCommand(input));
|
|
96
|
+
if (!res.stream) throw new Error("Bedrock Converse: empty stream response");
|
|
97
|
+
return res.stream;
|
|
98
|
+
}
|
|
99
|
+
async send(input) {
|
|
100
|
+
const { ConverseCommand } = await this.importBedrockRuntime();
|
|
101
|
+
return (await this.getClient()).send(new ConverseCommand(input));
|
|
102
|
+
}
|
|
103
|
+
async *chatStream(options) {
|
|
104
|
+
try {
|
|
105
|
+
options.logger.request(`activity=chat provider=${this.name} model=${this.model} messages=${options.messages.length} tools=${options.tools?.length ?? 0} stream=true`, {
|
|
106
|
+
provider: this.name,
|
|
107
|
+
model: this.model
|
|
108
|
+
});
|
|
109
|
+
const input = this.buildInput(options);
|
|
110
|
+
yield* processConverseStream(await this.sendStream(input), () => this.generateId(), {
|
|
111
|
+
threadId: options.threadId,
|
|
112
|
+
parentRunId: options.parentRunId,
|
|
113
|
+
model: options.model
|
|
114
|
+
});
|
|
115
|
+
} catch (error) {
|
|
116
|
+
const errorPayload = toRunErrorPayload(error, `${this.name}.chatStream failed`);
|
|
117
|
+
options.logger.errors(`${this.name}.chatStream fatal`, {
|
|
118
|
+
error: errorPayload,
|
|
119
|
+
source: `${this.name}.chatStream`
|
|
120
|
+
});
|
|
121
|
+
yield {
|
|
122
|
+
type: EventType.RUN_ERROR,
|
|
123
|
+
model: options.model,
|
|
124
|
+
timestamp: Date.now(),
|
|
125
|
+
message: errorPayload.message,
|
|
126
|
+
...errorPayload.code !== void 0 && { code: errorPayload.code },
|
|
127
|
+
error: {
|
|
128
|
+
message: errorPayload.message,
|
|
129
|
+
...errorPayload.code !== void 0 && { code: errorPayload.code }
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Structured output via the forced-tool strategy. Converse has no native
|
|
136
|
+
* json_schema response_format, so we force a single tool whose input schema
|
|
137
|
+
* is the requested output schema and read the model's `toolUse.input` back as
|
|
138
|
+
* the structured result.
|
|
139
|
+
*/
|
|
140
|
+
async structuredOutput(options) {
|
|
141
|
+
const { chatOptions, outputSchema } = options;
|
|
142
|
+
try {
|
|
143
|
+
chatOptions.logger.request(`activity=structuredOutput provider=${this.name} model=${this.model} messages=${chatOptions.messages.length}`, {
|
|
144
|
+
provider: this.name,
|
|
145
|
+
model: this.model
|
|
146
|
+
});
|
|
147
|
+
const input = {
|
|
148
|
+
...this.buildInput(chatOptions),
|
|
149
|
+
toolConfig: buildStructuredToolConfig(outputSchema)
|
|
150
|
+
};
|
|
151
|
+
const structured = extractStructuredToolInput(await this.send(input));
|
|
152
|
+
if (structured === void 0) throw new Error(`${this.name}.structuredOutput: response contained no forced-tool output`);
|
|
153
|
+
return {
|
|
154
|
+
data: structured,
|
|
155
|
+
rawText: JSON.stringify(structured)
|
|
156
|
+
};
|
|
157
|
+
} catch (error) {
|
|
158
|
+
chatOptions.logger.errors(`${this.name}.structuredOutput fatal`, {
|
|
159
|
+
error: toRunErrorPayload(error, `${this.name}.structuredOutput failed`),
|
|
160
|
+
source: `${this.name}.structuredOutput`
|
|
161
|
+
});
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Streaming structured output. Same forced-tool strategy as
|
|
167
|
+
* `structuredOutput`, but streamed: the forced tool's `toolUse.input` JSON
|
|
168
|
+
* fragments are accumulated from the Converse stream and a terminal
|
|
169
|
+
* `CUSTOM 'structured-output.complete'` event carries `{ object, raw }`,
|
|
170
|
+
* mirroring openai-base's `structuredOutputStream` contract exactly.
|
|
171
|
+
*/
|
|
172
|
+
async *structuredOutputStream(options) {
|
|
173
|
+
const { chatOptions, outputSchema } = options;
|
|
174
|
+
const timestamp = Date.now();
|
|
175
|
+
const runId = this.generateId();
|
|
176
|
+
const threadId = chatOptions.threadId ?? this.generateId();
|
|
177
|
+
const messageId = this.generateId();
|
|
178
|
+
let hasEmittedRunStarted = false;
|
|
179
|
+
let hasEmittedTextMessageStart = false;
|
|
180
|
+
let accumulatedRaw = "";
|
|
181
|
+
let finishReason = "stop";
|
|
182
|
+
try {
|
|
183
|
+
chatOptions.logger.request(`activity=structuredOutputStream provider=${this.name} model=${this.model} messages=${chatOptions.messages.length}`, {
|
|
184
|
+
provider: this.name,
|
|
185
|
+
model: this.model
|
|
186
|
+
});
|
|
187
|
+
const input = {
|
|
188
|
+
...this.buildInput(chatOptions),
|
|
189
|
+
toolConfig: buildStructuredToolConfig(outputSchema)
|
|
190
|
+
};
|
|
191
|
+
const stream = await this.sendStream(input);
|
|
192
|
+
for await (const ev of stream) {
|
|
193
|
+
if (!hasEmittedRunStarted) {
|
|
194
|
+
hasEmittedRunStarted = true;
|
|
195
|
+
yield {
|
|
196
|
+
type: EventType.RUN_STARTED,
|
|
197
|
+
runId,
|
|
198
|
+
threadId,
|
|
199
|
+
model: chatOptions.model,
|
|
200
|
+
timestamp,
|
|
201
|
+
parentRunId: chatOptions.parentRunId
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
throwIfConverseStreamError(ev);
|
|
205
|
+
if ("contentBlockDelta" in ev) {
|
|
206
|
+
const delta = ev.contentBlockDelta?.delta;
|
|
207
|
+
const fragment = delta && "toolUse" in delta ? delta.toolUse?.input : void 0;
|
|
208
|
+
if (fragment !== void 0) {
|
|
209
|
+
if (!hasEmittedTextMessageStart) {
|
|
210
|
+
hasEmittedTextMessageStart = true;
|
|
211
|
+
yield {
|
|
212
|
+
type: EventType.TEXT_MESSAGE_START,
|
|
213
|
+
messageId,
|
|
214
|
+
role: "assistant",
|
|
215
|
+
model: chatOptions.model,
|
|
216
|
+
timestamp
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
accumulatedRaw += fragment;
|
|
220
|
+
yield {
|
|
221
|
+
type: EventType.TEXT_MESSAGE_CONTENT,
|
|
222
|
+
messageId,
|
|
223
|
+
delta: fragment,
|
|
224
|
+
content: accumulatedRaw,
|
|
225
|
+
model: chatOptions.model,
|
|
226
|
+
timestamp
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if ("messageStop" in ev) {
|
|
232
|
+
const stopReason = ev.messageStop?.stopReason;
|
|
233
|
+
finishReason = stopReason === "max_tokens" ? "length" : stopReason === "content_filtered" ? "content_filter" : "stop";
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (!hasEmittedRunStarted) {
|
|
238
|
+
hasEmittedRunStarted = true;
|
|
239
|
+
yield {
|
|
240
|
+
type: EventType.RUN_STARTED,
|
|
241
|
+
runId,
|
|
242
|
+
threadId,
|
|
243
|
+
model: chatOptions.model,
|
|
244
|
+
timestamp,
|
|
245
|
+
parentRunId: chatOptions.parentRunId
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
if (hasEmittedTextMessageStart) yield {
|
|
249
|
+
type: EventType.TEXT_MESSAGE_END,
|
|
250
|
+
messageId,
|
|
251
|
+
model: chatOptions.model,
|
|
252
|
+
timestamp
|
|
253
|
+
};
|
|
254
|
+
if (accumulatedRaw.length === 0) {
|
|
255
|
+
yield {
|
|
256
|
+
type: EventType.RUN_ERROR,
|
|
257
|
+
runId,
|
|
258
|
+
model: chatOptions.model,
|
|
259
|
+
timestamp,
|
|
260
|
+
message: `${this.name}.structuredOutputStream: response contained no content`,
|
|
261
|
+
code: "empty-response",
|
|
262
|
+
error: {
|
|
263
|
+
message: `${this.name}.structuredOutputStream: response contained no content`,
|
|
264
|
+
code: "empty-response"
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
let parsed;
|
|
270
|
+
try {
|
|
271
|
+
parsed = JSON.parse(accumulatedRaw);
|
|
272
|
+
} catch {
|
|
273
|
+
yield {
|
|
274
|
+
type: EventType.RUN_ERROR,
|
|
275
|
+
runId,
|
|
276
|
+
model: chatOptions.model,
|
|
277
|
+
timestamp,
|
|
278
|
+
message: `Failed to parse structured output as JSON. Content: ${accumulatedRaw.slice(0, 200)}${accumulatedRaw.length > 200 ? "..." : ""}`,
|
|
279
|
+
code: "parse-error",
|
|
280
|
+
error: {
|
|
281
|
+
message: "Failed to parse structured output as JSON",
|
|
282
|
+
code: "parse-error"
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
yield {
|
|
288
|
+
type: EventType.CUSTOM,
|
|
289
|
+
name: "structured-output.complete",
|
|
290
|
+
value: {
|
|
291
|
+
object: parsed,
|
|
292
|
+
raw: accumulatedRaw
|
|
293
|
+
},
|
|
294
|
+
model: chatOptions.model,
|
|
295
|
+
timestamp
|
|
296
|
+
};
|
|
297
|
+
yield {
|
|
298
|
+
type: EventType.RUN_FINISHED,
|
|
299
|
+
runId,
|
|
300
|
+
threadId,
|
|
301
|
+
model: chatOptions.model,
|
|
302
|
+
timestamp,
|
|
303
|
+
finishReason
|
|
304
|
+
};
|
|
305
|
+
} catch (error) {
|
|
306
|
+
if (!hasEmittedRunStarted) {
|
|
307
|
+
hasEmittedRunStarted = true;
|
|
308
|
+
yield {
|
|
309
|
+
type: EventType.RUN_STARTED,
|
|
310
|
+
runId,
|
|
311
|
+
threadId,
|
|
312
|
+
model: chatOptions.model,
|
|
313
|
+
timestamp,
|
|
314
|
+
parentRunId: chatOptions.parentRunId
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
const errorPayload = toRunErrorPayload(error, `${this.name}.structuredOutputStream failed`);
|
|
318
|
+
chatOptions.logger.errors(`${this.name}.structuredOutputStream fatal`, {
|
|
319
|
+
error: errorPayload,
|
|
320
|
+
source: `${this.name}.structuredOutputStream`
|
|
321
|
+
});
|
|
322
|
+
yield {
|
|
323
|
+
type: EventType.RUN_ERROR,
|
|
324
|
+
runId,
|
|
325
|
+
model: chatOptions.model,
|
|
326
|
+
timestamp,
|
|
327
|
+
message: errorPayload.message,
|
|
328
|
+
...errorPayload.code !== void 0 && { code: errorPayload.code },
|
|
329
|
+
error: {
|
|
330
|
+
message: errorPayload.message,
|
|
331
|
+
...errorPayload.code !== void 0 && { code: errorPayload.code }
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Converse sends `tools` and a forced structured-output tool via two separate
|
|
338
|
+
* mechanisms, never together. Declaring `false` makes the engine run the
|
|
339
|
+
* agent loop without `outputSchema` and finalize via `structuredOutput` /
|
|
340
|
+
* `structuredOutputStream`.
|
|
341
|
+
*/
|
|
342
|
+
supportsCombinedToolsAndSchema() {
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Translate `TextOptions` into a `ConverseCommandInput`. Shared by chatStream,
|
|
347
|
+
* structuredOutput, and structuredOutputStream (the latter two override
|
|
348
|
+
* `toolConfig` with the forced structured tool afterwards).
|
|
349
|
+
*/
|
|
350
|
+
buildInput(options) {
|
|
351
|
+
const { system, messages } = toConverseMessages(options.messages, options.systemPrompts);
|
|
352
|
+
const toolConfig = options.tools ? toToolConfig(convertTools(options.tools), "auto") : void 0;
|
|
353
|
+
const modelOptions = options.modelOptions;
|
|
354
|
+
const temperature = modelOptions?.temperature;
|
|
355
|
+
const topP = modelOptions?.top_p;
|
|
356
|
+
const maxTokens = modelOptions?.max_completion_tokens;
|
|
357
|
+
const stop = modelOptions?.stop;
|
|
358
|
+
const stopSequences = stop == null ? void 0 : Array.isArray(stop) ? stop : [stop];
|
|
359
|
+
const inferenceConfig = temperature != null || topP != null || maxTokens != null || stopSequences != null ? {
|
|
360
|
+
...temperature != null && { temperature },
|
|
361
|
+
...topP != null && { topP },
|
|
362
|
+
...maxTokens != null && { maxTokens },
|
|
363
|
+
...stopSequences != null && { stopSequences }
|
|
364
|
+
} : void 0;
|
|
365
|
+
return {
|
|
366
|
+
modelId: this.model,
|
|
367
|
+
messages,
|
|
368
|
+
...system.length > 0 && { system },
|
|
369
|
+
...toolConfig && { toolConfig },
|
|
370
|
+
...inferenceConfig && { inferenceConfig }
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
/**
|
|
375
|
+
* Convert TanStack `Tool[]` to the Converse tool-converter input shape. Reuses
|
|
376
|
+
* the SAME `convertSchemaToJsonSchema` the other adapters use so the Converse
|
|
377
|
+
* tool input schemas match what every other provider sends.
|
|
378
|
+
*/
|
|
399
379
|
function convertTools(tools) {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
380
|
+
return tools.map((tool) => {
|
|
381
|
+
const inputSchema = convertSchemaToJsonSchema(tool.inputSchema) ?? {
|
|
382
|
+
type: "object",
|
|
383
|
+
properties: {},
|
|
384
|
+
required: []
|
|
385
|
+
};
|
|
386
|
+
return {
|
|
387
|
+
name: tool.name,
|
|
388
|
+
description: tool.description,
|
|
389
|
+
inputSchema
|
|
390
|
+
};
|
|
391
|
+
});
|
|
410
392
|
}
|
|
393
|
+
/**
|
|
394
|
+
* Find the forced structured-output tool's `input` in a non-streaming Converse
|
|
395
|
+
* response. SDK-boundary narrowing only — `ConverseOutput` is a tagged union
|
|
396
|
+
* (`{ message }`) and a tool-use block is `{ toolUse: { input } }`.
|
|
397
|
+
*/
|
|
411
398
|
function extractStructuredToolInput(res) {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
if (block.toolUse.name === STRUCTURED_TOOL_NAME || block.toolUse.name === void 0) {
|
|
417
|
-
return block.toolUse.input;
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
return void 0;
|
|
399
|
+
const content = (res.output && "message" in res.output ? res.output.message : void 0)?.content ?? [];
|
|
400
|
+
for (const block of content) if ("toolUse" in block && block.toolUse) {
|
|
401
|
+
if (block.toolUse.name === "structured_output" || block.toolUse.name === void 0) return block.toolUse.input;
|
|
402
|
+
}
|
|
422
403
|
}
|
|
404
|
+
/** Converse adapter with an explicit API key (low-level; mirrors createBedrockChat). */
|
|
423
405
|
function createBedrockConverse(model, apiKey, config) {
|
|
424
|
-
|
|
406
|
+
return new BedrockConverseTextAdapter({
|
|
407
|
+
...config,
|
|
408
|
+
apiKey
|
|
409
|
+
}, model);
|
|
425
410
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
//# sourceMappingURL=converse-text.js.map
|
|
411
|
+
//#endregion
|
|
412
|
+
export { BedrockConverseTextAdapter, createBedrockConverse };
|
|
413
|
+
|
|
414
|
+
//# sourceMappingURL=converse-text.js.map
|