promptfoo 0.119.13 → 0.119.14

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 (131) hide show
  1. package/dist/package.json +28 -26
  2. package/dist/src/app/assets/index-eJ2lMe94.js +51 -0
  3. package/dist/src/app/assets/{source-map-support-Bnh0UQ2S.js → source-map-support-1v4oeb7P.js} +1 -1
  4. package/dist/src/app/assets/sync-CtLQRuC1.js +1 -0
  5. package/dist/src/app/assets/{vendor-charts-T60Uk0Z3.js → vendor-charts-DnVv66VV.js} +1 -1
  6. package/dist/src/app/assets/{vendor-markdown-DLig-KJh.js → vendor-markdown-DCpQIyMA.js} +1 -1
  7. package/dist/src/app/assets/{vendor-mui-core-5BLaiG3c.js → vendor-mui-core-Boqnpf9f.js} +1 -1
  8. package/dist/src/app/assets/{vendor-mui-icons-fn39Fu2e.js → vendor-mui-icons-B8MqoVbj.js} +1 -1
  9. package/dist/src/app/assets/vendor-mui-x-CGSS6QHF.js +45 -0
  10. package/dist/src/app/assets/{vendor-utils-DYBMEuwX.js → vendor-utils-DdfHIEy8.js} +1 -1
  11. package/dist/src/app/index.html +7 -7
  12. package/dist/src/assertions/guardrails.d.ts +1 -1
  13. package/dist/src/assertions/guardrails.js +18 -9
  14. package/dist/src/assertions/index.d.ts +1 -1
  15. package/dist/src/assertions/index.js +9 -3
  16. package/dist/src/assertions/searchRubric.d.ts +3 -0
  17. package/dist/src/assertions/searchRubric.js +18 -0
  18. package/dist/src/commands/eval.js +1 -1
  19. package/dist/src/commands/modelScan.d.ts +7 -1
  20. package/dist/src/commands/modelScan.js +121 -59
  21. package/dist/src/database/index.d.ts +6 -0
  22. package/dist/src/database/index.js +11 -0
  23. package/dist/src/database/tables.d.ts +46 -24
  24. package/dist/src/envars.d.ts +17 -0
  25. package/dist/src/generated/constants.js +1 -1
  26. package/dist/src/logger.d.ts +5 -0
  27. package/dist/src/logger.js +28 -0
  28. package/dist/src/main.js +17 -6
  29. package/dist/src/matchers.d.ts +1 -0
  30. package/dist/src/matchers.js +80 -0
  31. package/dist/src/models/eval.d.ts +2 -1
  32. package/dist/src/models/eval.js +44 -2
  33. package/dist/src/prompts/grading.d.ts +1 -0
  34. package/dist/src/prompts/grading.js +26 -1
  35. package/dist/src/prompts/index.d.ts +1 -0
  36. package/dist/src/prompts/index.js +4 -1
  37. package/dist/src/providers/adaline.gateway.js +2 -2
  38. package/dist/src/providers/anthropic/defaults.d.ts +1 -1
  39. package/dist/src/providers/anthropic/defaults.js +15 -0
  40. package/dist/src/providers/azure/chat.d.ts +3 -1
  41. package/dist/src/providers/azure/chat.js +16 -3
  42. package/dist/src/providers/azure/defaults.js +660 -141
  43. package/dist/src/providers/azure/responses.d.ts +5 -0
  44. package/dist/src/providers/azure/responses.js +33 -4
  45. package/dist/src/providers/azure/types.d.ts +4 -0
  46. package/dist/src/providers/bedrock/agents.d.ts +1 -1
  47. package/dist/src/providers/bedrock/agents.js +2 -2
  48. package/dist/src/providers/bedrock/base.d.ts +40 -0
  49. package/dist/src/providers/bedrock/base.js +171 -0
  50. package/dist/src/providers/bedrock/converse.d.ts +146 -0
  51. package/dist/src/providers/bedrock/converse.js +1044 -0
  52. package/dist/src/providers/bedrock/index.d.ts +1 -34
  53. package/dist/src/providers/bedrock/index.js +4 -159
  54. package/dist/src/providers/bedrock/knowledgeBase.d.ts +1 -1
  55. package/dist/src/providers/bedrock/knowledgeBase.js +2 -2
  56. package/dist/src/providers/bedrock/nova-sonic.d.ts +2 -1
  57. package/dist/src/providers/bedrock/nova-sonic.js +2 -2
  58. package/dist/src/providers/claude-agent-sdk.d.ts +58 -1
  59. package/dist/src/providers/claude-agent-sdk.js +22 -1
  60. package/dist/src/providers/defaults.js +4 -0
  61. package/dist/src/providers/github/defaults.js +6 -6
  62. package/dist/src/providers/google/types.d.ts +25 -0
  63. package/dist/src/providers/google/util.d.ts +2 -0
  64. package/dist/src/providers/google/vertex.js +78 -22
  65. package/dist/src/providers/{groq.d.ts → groq/chat.d.ts} +26 -20
  66. package/dist/src/providers/groq/chat.js +79 -0
  67. package/dist/src/providers/groq/index.d.ts +5 -0
  68. package/dist/src/providers/groq/index.js +24 -0
  69. package/dist/src/providers/groq/responses.d.ts +106 -0
  70. package/dist/src/providers/groq/responses.js +64 -0
  71. package/dist/src/providers/groq/types.d.ts +44 -0
  72. package/dist/src/providers/groq/types.js +3 -0
  73. package/dist/src/providers/groq/util.d.ts +15 -0
  74. package/dist/src/providers/groq/util.js +28 -0
  75. package/dist/src/providers/mcp/client.d.ts +8 -0
  76. package/dist/src/providers/mcp/client.js +60 -10
  77. package/dist/src/providers/mcp/types.d.ts +21 -0
  78. package/dist/src/providers/openai/chatkit-pool.d.ts +114 -0
  79. package/dist/src/providers/openai/chatkit-pool.js +548 -0
  80. package/dist/src/providers/openai/chatkit-types.d.ts +73 -0
  81. package/dist/src/providers/openai/chatkit-types.js +3 -0
  82. package/dist/src/providers/openai/chatkit.d.ts +76 -0
  83. package/dist/src/providers/openai/chatkit.js +879 -0
  84. package/dist/src/providers/openai/codex-sdk.d.ts +109 -0
  85. package/dist/src/providers/openai/codex-sdk.js +346 -0
  86. package/dist/src/providers/openai/defaults.d.ts +2 -0
  87. package/dist/src/providers/openai/defaults.js +10 -4
  88. package/dist/src/providers/registry.js +48 -9
  89. package/dist/src/providers/responses/types.d.ts +1 -1
  90. package/dist/src/providers/sagemaker.d.ts +2 -2
  91. package/dist/src/providers/webSearchUtils.d.ts +17 -0
  92. package/dist/src/providers/webSearchUtils.js +169 -0
  93. package/dist/src/providers/xai/chat.d.ts +61 -0
  94. package/dist/src/providers/xai/chat.js +68 -3
  95. package/dist/src/providers/xai/responses.d.ts +189 -0
  96. package/dist/src/providers/xai/responses.js +268 -0
  97. package/dist/src/redteam/constants/plugins.d.ts +1 -1
  98. package/dist/src/redteam/constants/plugins.js +1 -1
  99. package/dist/src/redteam/constants/strategies.d.ts +1 -1
  100. package/dist/src/redteam/constants/strategies.js +1 -0
  101. package/dist/src/redteam/plugins/vlguard.d.ts +53 -4
  102. package/dist/src/redteam/plugins/vlguard.js +362 -46
  103. package/dist/src/redteam/providers/constants.d.ts +2 -2
  104. package/dist/src/redteam/providers/constants.js +2 -2
  105. package/dist/src/redteam/providers/crescendo/index.d.ts +1 -1
  106. package/dist/src/redteam/providers/crescendo/index.js +5 -3
  107. package/dist/src/redteam/providers/hydra/index.js +1 -1
  108. package/dist/src/server/routes/modelAudit.js +4 -4
  109. package/dist/src/share.js +4 -2
  110. package/dist/src/telemetry.js +44 -8
  111. package/dist/src/types/env.d.ts +3 -0
  112. package/dist/src/types/env.js +1 -0
  113. package/dist/src/types/index.d.ts +896 -615
  114. package/dist/src/types/index.js +1 -0
  115. package/dist/src/types/providers.d.ts +1 -0
  116. package/dist/src/types/tracing.d.ts +3 -0
  117. package/dist/src/util/database.d.ts +6 -4
  118. package/dist/src/util/file.js +6 -4
  119. package/dist/src/util/modelAuditCliParser.d.ts +4 -4
  120. package/dist/src/util/xlsx.js +52 -26
  121. package/dist/src/validators/providers.d.ts +142 -122
  122. package/dist/src/validators/providers.js +4 -6
  123. package/dist/src/validators/redteam.d.ts +36 -28
  124. package/dist/src/validators/redteam.js +9 -3
  125. package/dist/tsconfig.tsbuildinfo +1 -1
  126. package/package.json +28 -26
  127. package/dist/drizzle/CLAUDE.md +0 -65
  128. package/dist/src/app/assets/index-DifT6VGT.js +0 -51
  129. package/dist/src/app/assets/sync-Oo-W_Rbj.js +0 -1
  130. package/dist/src/app/assets/vendor-mui-x-C2xF-yiO.js +0 -45
  131. package/dist/src/providers/groq.js +0 -48
@@ -0,0 +1,1044 @@
1
+ "use strict";
2
+ /**
3
+ * AWS Bedrock Converse API Provider
4
+ *
5
+ * This provider implements the AWS Bedrock Converse API, which provides a unified
6
+ * interface for all Bedrock models. It supports:
7
+ * - Extended thinking (reasoning/ultrathink) for Claude models
8
+ * - Tool calling with standardized format
9
+ * - Streaming responses via ConverseStream
10
+ * - Performance configuration (latency optimization, service tiers)
11
+ * - Guardrails integration
12
+ * - Cache token tracking
13
+ */
14
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ var desc = Object.getOwnPropertyDescriptor(m, k);
17
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
+ desc = { enumerable: true, get: function() { return m[k]; } };
19
+ }
20
+ Object.defineProperty(o, k2, desc);
21
+ }) : (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ o[k2] = m[k];
24
+ }));
25
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
26
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
27
+ }) : function(o, v) {
28
+ o["default"] = v;
29
+ });
30
+ var __importStar = (this && this.__importStar) || (function () {
31
+ var ownKeys = function(o) {
32
+ ownKeys = Object.getOwnPropertyNames || function (o) {
33
+ var ar = [];
34
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
35
+ return ar;
36
+ };
37
+ return ownKeys(o);
38
+ };
39
+ return function (mod) {
40
+ if (mod && mod.__esModule) return mod;
41
+ var result = {};
42
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
43
+ __setModuleDefault(result, mod);
44
+ return result;
45
+ };
46
+ })();
47
+ var __importDefault = (this && this.__importDefault) || function (mod) {
48
+ return (mod && mod.__esModule) ? mod : { "default": mod };
49
+ };
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.AwsBedrockConverseProvider = void 0;
52
+ exports.parseConverseMessages = parseConverseMessages;
53
+ const path_1 = __importDefault(require("path"));
54
+ const cache_1 = require("../../cache");
55
+ const cliState_1 = __importDefault(require("../../cliState"));
56
+ const esm_1 = require("../../esm");
57
+ const envars_1 = require("../../envars");
58
+ const logger_1 = __importDefault(require("../../logger"));
59
+ const telemetry_1 = __importDefault(require("../../telemetry"));
60
+ const fileExtensions_1 = require("../../util/fileExtensions");
61
+ const index_1 = require("../../util/index");
62
+ const base_1 = require("./base");
63
+ /**
64
+ * Bedrock model pricing per 1M tokens
65
+ * Prices as of 2025 - may need updates
66
+ */
67
+ const BEDROCK_CONVERSE_PRICING = {
68
+ // Claude Opus 4.5
69
+ 'anthropic.claude-opus-4-5': { input: 5, output: 25 },
70
+ // Claude Opus 4/4.1
71
+ 'anthropic.claude-opus-4': { input: 15, output: 75 },
72
+ // Claude Sonnet 4/4.5
73
+ 'anthropic.claude-sonnet-4': { input: 3, output: 15 },
74
+ // Claude Haiku 4.5
75
+ 'anthropic.claude-haiku-4': { input: 1, output: 5 },
76
+ // Claude 3.x
77
+ 'anthropic.claude-3-opus': { input: 15, output: 75 },
78
+ 'anthropic.claude-3-5-sonnet': { input: 3, output: 15 },
79
+ 'anthropic.claude-3-7-sonnet': { input: 3, output: 15 },
80
+ 'anthropic.claude-3-5-haiku': { input: 0.8, output: 4 },
81
+ 'anthropic.claude-3-haiku': { input: 0.25, output: 1.25 },
82
+ // Amazon Nova
83
+ 'amazon.nova-micro': { input: 0.035, output: 0.14 },
84
+ 'amazon.nova-lite': { input: 0.06, output: 0.24 },
85
+ 'amazon.nova-pro': { input: 0.8, output: 3.2 },
86
+ 'amazon.nova-premier': { input: 2.5, output: 10 },
87
+ // Amazon Titan Text
88
+ 'amazon.titan-text-lite': { input: 0.15, output: 0.2 },
89
+ 'amazon.titan-text-express': { input: 0.8, output: 1.6 },
90
+ 'amazon.titan-text-premier': { input: 0.5, output: 1.5 },
91
+ // Meta Llama
92
+ 'meta.llama3-1-8b': { input: 0.22, output: 0.22 },
93
+ 'meta.llama3-1-70b': { input: 0.99, output: 0.99 },
94
+ 'meta.llama3-1-405b': { input: 5.32, output: 16 },
95
+ 'meta.llama3-2-1b': { input: 0.1, output: 0.1 },
96
+ 'meta.llama3-2-3b': { input: 0.15, output: 0.15 },
97
+ 'meta.llama3-2-11b': { input: 0.35, output: 0.35 },
98
+ 'meta.llama3-2-90b': { input: 2.0, output: 2.0 },
99
+ 'meta.llama3-3-70b': { input: 0.99, output: 0.99 },
100
+ 'meta.llama4-scout': { input: 0.17, output: 0.68 },
101
+ 'meta.llama4-maverick': { input: 0.17, output: 0.68 },
102
+ 'meta.llama4': { input: 1.0, output: 3.0 },
103
+ // Mistral
104
+ 'mistral.mistral-7b': { input: 0.15, output: 0.2 },
105
+ 'mistral.mixtral-8x7b': { input: 0.45, output: 0.7 },
106
+ 'mistral.mistral-large': { input: 4, output: 12 },
107
+ 'mistral.mistral-small': { input: 1, output: 3 },
108
+ 'mistral.pixtral-large': { input: 2, output: 6 },
109
+ // AI21 Jamba
110
+ 'ai21.jamba-1-5-mini': { input: 0.2, output: 0.4 },
111
+ 'ai21.jamba-1-5-large': { input: 2, output: 8 },
112
+ // Cohere
113
+ 'cohere.command-r': { input: 0.5, output: 1.5 },
114
+ 'cohere.command-r-plus': { input: 3, output: 15 },
115
+ // DeepSeek
116
+ 'deepseek.deepseek-r1': { input: 1.35, output: 5.4 },
117
+ 'deepseek.r1': { input: 1.35, output: 5.4 },
118
+ // Qwen
119
+ 'qwen.qwen3-32b': { input: 0.2, output: 0.6 },
120
+ 'qwen.qwen3-235b': { input: 0.18, output: 0.54 },
121
+ 'qwen.qwen3-coder-30b': { input: 0.2, output: 0.6 },
122
+ 'qwen.qwen3-coder-480b': { input: 1.5, output: 7.5 },
123
+ 'qwen.qwen3': { input: 0.5, output: 1.5 },
124
+ // Writer Palmyra
125
+ 'writer.palmyra-x5': { input: 0.6, output: 6 },
126
+ 'writer.palmyra-x4': { input: 2.5, output: 10 },
127
+ // OpenAI GPT-OSS
128
+ 'openai.gpt-oss-120b': { input: 1.0, output: 3.0 },
129
+ 'openai.gpt-oss-20b': { input: 0.3, output: 0.9 },
130
+ };
131
+ /**
132
+ * Calculate cost based on model and token usage
133
+ */
134
+ function calculateBedrockConverseCost(modelId, promptTokens, completionTokens) {
135
+ if (promptTokens === undefined || completionTokens === undefined) {
136
+ return undefined;
137
+ }
138
+ // Find matching pricing
139
+ const normalizedModelId = modelId.toLowerCase();
140
+ for (const [modelPrefix, pricing] of Object.entries(BEDROCK_CONVERSE_PRICING)) {
141
+ if (normalizedModelId.includes(modelPrefix)) {
142
+ const inputCost = (promptTokens / 1000000) * pricing.input;
143
+ const outputCost = (completionTokens / 1000000) * pricing.output;
144
+ return inputCost + outputCost;
145
+ }
146
+ }
147
+ return undefined;
148
+ }
149
+ /**
150
+ * Convert various tool formats to Converse API format
151
+ */
152
+ function convertToolsToConverseFormat(tools) {
153
+ return tools.map((tool) => {
154
+ // Already in Converse format - cast to expected type
155
+ if (tool.toolSpec) {
156
+ return { toolSpec: tool.toolSpec };
157
+ }
158
+ // OpenAI-compatible format
159
+ if (tool.type === 'function' && tool.function) {
160
+ return {
161
+ toolSpec: {
162
+ name: tool.function.name,
163
+ description: tool.function.description,
164
+ inputSchema: {
165
+ json: (tool.function.parameters || {}),
166
+ },
167
+ },
168
+ };
169
+ }
170
+ // Anthropic format
171
+ if (tool.name) {
172
+ return {
173
+ toolSpec: {
174
+ name: tool.name,
175
+ description: tool.description,
176
+ inputSchema: {
177
+ json: (tool.input_schema || {}),
178
+ },
179
+ },
180
+ };
181
+ }
182
+ throw new Error(`Invalid tool configuration: ${JSON.stringify(tool)}`);
183
+ });
184
+ }
185
+ /**
186
+ * Convert tool choice to Converse API format
187
+ */
188
+ function convertToolChoiceToConverseFormat(toolChoice) {
189
+ if (toolChoice === 'auto') {
190
+ return { auto: {} };
191
+ }
192
+ if (toolChoice === 'any') {
193
+ return { any: {} };
194
+ }
195
+ if (typeof toolChoice === 'object' && toolChoice.tool) {
196
+ return { tool: { name: toolChoice.tool.name } };
197
+ }
198
+ return { auto: {} };
199
+ }
200
+ /**
201
+ * Parse prompt into Converse API message format
202
+ */
203
+ function parseConverseMessages(prompt) {
204
+ // Try to parse as JSON first
205
+ try {
206
+ const parsed = JSON.parse(prompt);
207
+ if (Array.isArray(parsed)) {
208
+ const systemMessages = [];
209
+ const messages = [];
210
+ for (const msg of parsed) {
211
+ if (msg.role === 'system') {
212
+ // System messages go to the system field
213
+ const content = typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content);
214
+ systemMessages.push({ text: content });
215
+ }
216
+ else if (msg.role === 'user' || msg.role === 'assistant') {
217
+ // Convert content to ContentBlock format
218
+ const contentBlocks = [];
219
+ if (typeof msg.content === 'string') {
220
+ contentBlocks.push({ text: msg.content });
221
+ }
222
+ else if (Array.isArray(msg.content)) {
223
+ for (const block of msg.content) {
224
+ if (typeof block === 'string') {
225
+ contentBlocks.push({ text: block });
226
+ }
227
+ else if (block.type === 'text') {
228
+ contentBlocks.push({ text: block.text });
229
+ }
230
+ else if (block.type === 'image' || block.image) {
231
+ // Handle image content - multiple formats supported
232
+ const imageData = block.image || block;
233
+ let bytes;
234
+ let format = 'png';
235
+ // Determine format from various sources
236
+ if (imageData.format) {
237
+ format = imageData.format;
238
+ }
239
+ else if (imageData.source?.media_type) {
240
+ format = imageData.source.media_type.split('/')[1] || 'png';
241
+ }
242
+ // Get bytes from various sources
243
+ if (imageData.source?.bytes) {
244
+ const rawBytes = imageData.source.bytes;
245
+ if (typeof rawBytes === 'string') {
246
+ // Check for data URL format: data:image/jpeg;base64,...
247
+ if (rawBytes.startsWith('data:')) {
248
+ const matches = rawBytes.match(/^data:image\/([^;]+);base64,(.+)$/);
249
+ if (matches) {
250
+ format = matches[1] === 'jpg' ? 'jpeg' : matches[1];
251
+ bytes = Buffer.from(matches[2], 'base64');
252
+ }
253
+ }
254
+ else {
255
+ // Assume raw base64 string
256
+ bytes = Buffer.from(rawBytes, 'base64');
257
+ }
258
+ }
259
+ else if (Buffer.isBuffer(rawBytes)) {
260
+ bytes = rawBytes;
261
+ }
262
+ }
263
+ else if (imageData.source?.data) {
264
+ // Anthropic format: {source: {type: 'base64', media_type: '...', data: '...'}}
265
+ bytes = Buffer.from(imageData.source.data, 'base64');
266
+ }
267
+ if (bytes) {
268
+ // Normalize format names for Converse API
269
+ if (format === 'jpg') {
270
+ format = 'jpeg';
271
+ }
272
+ contentBlocks.push({
273
+ image: {
274
+ format: format,
275
+ source: { bytes },
276
+ },
277
+ });
278
+ }
279
+ else {
280
+ logger_1.default.warn('Could not parse image content block', { block });
281
+ }
282
+ }
283
+ else if (block.type === 'image_url' || block.image_url) {
284
+ // OpenAI-compatible image_url format
285
+ const imageUrl = block.image_url?.url || block.url;
286
+ if (typeof imageUrl === 'string' && imageUrl.startsWith('data:')) {
287
+ const matches = imageUrl.match(/^data:image\/([^;]+);base64,(.+)$/);
288
+ if (matches) {
289
+ const format = matches[1] === 'jpg' ? 'jpeg' : matches[1];
290
+ const bytes = Buffer.from(matches[2], 'base64');
291
+ contentBlocks.push({
292
+ image: {
293
+ format: format,
294
+ source: { bytes },
295
+ },
296
+ });
297
+ }
298
+ }
299
+ else {
300
+ logger_1.default.warn('Unsupported image_url format (only data URLs supported)', {
301
+ imageUrl,
302
+ });
303
+ }
304
+ }
305
+ else if (block.type === 'document' || block.document) {
306
+ // Handle document content
307
+ const docData = block.document || block;
308
+ let bytes;
309
+ const format = docData.format || 'txt';
310
+ const name = docData.name || 'document';
311
+ if (docData.source?.bytes) {
312
+ const rawBytes = docData.source.bytes;
313
+ if (typeof rawBytes === 'string') {
314
+ // Check for data URL format
315
+ if (rawBytes.startsWith('data:')) {
316
+ const matches = rawBytes.match(/^data:[^;]+;base64,(.+)$/);
317
+ if (matches) {
318
+ bytes = Buffer.from(matches[1], 'base64');
319
+ }
320
+ }
321
+ else {
322
+ bytes = Buffer.from(rawBytes, 'base64');
323
+ }
324
+ }
325
+ else if (Buffer.isBuffer(rawBytes)) {
326
+ bytes = rawBytes;
327
+ }
328
+ }
329
+ if (bytes) {
330
+ contentBlocks.push({
331
+ document: {
332
+ format: format,
333
+ name,
334
+ source: { bytes },
335
+ },
336
+ });
337
+ }
338
+ else {
339
+ logger_1.default.warn('Could not parse document content block', { block });
340
+ }
341
+ }
342
+ else if (block.type === 'tool_use' || block.toolUse) {
343
+ const toolUseData = block.toolUse || block;
344
+ contentBlocks.push({
345
+ toolUse: {
346
+ toolUseId: toolUseData.toolUseId || toolUseData.id,
347
+ name: toolUseData.name,
348
+ input: toolUseData.input,
349
+ },
350
+ });
351
+ }
352
+ else if (block.type === 'tool_result' || block.toolResult) {
353
+ const toolResultData = block.toolResult || block;
354
+ contentBlocks.push({
355
+ toolResult: {
356
+ toolUseId: toolResultData.toolUseId || toolResultData.tool_use_id,
357
+ content: Array.isArray(toolResultData.content)
358
+ ? toolResultData.content.map((c) => typeof c === 'string' ? { text: c } : c)
359
+ : [{ text: String(toolResultData.content) }],
360
+ status: toolResultData.status,
361
+ },
362
+ });
363
+ }
364
+ else {
365
+ // Unknown block type, try to convert to text
366
+ contentBlocks.push({ text: JSON.stringify(block) });
367
+ }
368
+ }
369
+ }
370
+ else {
371
+ contentBlocks.push({ text: JSON.stringify(msg.content) });
372
+ }
373
+ messages.push({
374
+ role: msg.role,
375
+ content: contentBlocks,
376
+ });
377
+ }
378
+ }
379
+ return {
380
+ messages,
381
+ system: systemMessages.length > 0 ? systemMessages : undefined,
382
+ };
383
+ }
384
+ }
385
+ catch {
386
+ // Not JSON, try line-based parsing
387
+ }
388
+ // Parse as line-based format or plain text
389
+ const lines = prompt.split('\n');
390
+ const messages = [];
391
+ let system;
392
+ let currentRole = null;
393
+ let currentContent = [];
394
+ const pushMessage = () => {
395
+ if (currentRole && currentContent.length > 0) {
396
+ messages.push({
397
+ role: currentRole,
398
+ content: [{ text: currentContent.join('\n') }],
399
+ });
400
+ currentContent = [];
401
+ }
402
+ };
403
+ for (const line of lines) {
404
+ const trimmedLine = line.trim();
405
+ if (trimmedLine.toLowerCase().startsWith('system:')) {
406
+ pushMessage();
407
+ system = [{ text: trimmedLine.slice(7).trim() }];
408
+ currentRole = null;
409
+ }
410
+ else if (trimmedLine.toLowerCase().startsWith('user:')) {
411
+ pushMessage();
412
+ currentRole = 'user';
413
+ const content = trimmedLine.slice(5).trim();
414
+ if (content) {
415
+ currentContent.push(content);
416
+ }
417
+ }
418
+ else if (trimmedLine.toLowerCase().startsWith('assistant:')) {
419
+ pushMessage();
420
+ currentRole = 'assistant';
421
+ const content = trimmedLine.slice(10).trim();
422
+ if (content) {
423
+ currentContent.push(content);
424
+ }
425
+ }
426
+ else if (currentRole) {
427
+ currentContent.push(line);
428
+ }
429
+ else {
430
+ // No role prefix, treat as user message
431
+ currentRole = 'user';
432
+ currentContent.push(line);
433
+ }
434
+ }
435
+ pushMessage();
436
+ // If no messages were parsed, treat entire prompt as user message
437
+ if (messages.length === 0) {
438
+ messages.push({
439
+ role: 'user',
440
+ content: [{ text: prompt }],
441
+ });
442
+ }
443
+ return { messages, system };
444
+ }
445
+ /**
446
+ * Extract text output from Converse API response content blocks
447
+ */
448
+ function extractTextFromContentBlocks(content, showThinking = true) {
449
+ const parts = [];
450
+ for (const block of content) {
451
+ if ('text' in block && block.text) {
452
+ parts.push(block.text);
453
+ }
454
+ else if ('reasoningContent' in block && block.reasoningContent) {
455
+ // Handle extended thinking content
456
+ const reasoning = block.reasoningContent;
457
+ if (showThinking) {
458
+ if ('reasoningText' in reasoning && reasoning.reasoningText) {
459
+ const thinkingText = reasoning.reasoningText.text || '';
460
+ const signature = reasoning.reasoningText.signature || '';
461
+ parts.push(`<thinking>\n${thinkingText}\n</thinking>`);
462
+ if (signature) {
463
+ parts.push(`Signature: ${signature}`);
464
+ }
465
+ }
466
+ else if ('redactedContent' in reasoning && reasoning.redactedContent) {
467
+ parts.push('<thinking>[Redacted]</thinking>');
468
+ }
469
+ }
470
+ }
471
+ else if ('toolUse' in block && block.toolUse) {
472
+ // Format tool use for output
473
+ parts.push(JSON.stringify({
474
+ type: 'tool_use',
475
+ id: block.toolUse.toolUseId,
476
+ name: block.toolUse.name,
477
+ input: block.toolUse.input,
478
+ }));
479
+ }
480
+ }
481
+ return parts.join('\n\n');
482
+ }
483
+ /**
484
+ * AWS Bedrock Converse API Provider
485
+ */
486
+ class AwsBedrockConverseProvider extends base_1.AwsBedrockGenericProvider {
487
+ constructor(modelName, options = {}) {
488
+ super(modelName, options);
489
+ this.loadedFunctionCallbacks = {};
490
+ this.config = options.config || {};
491
+ // Record telemetry
492
+ if (this.config.thinking) {
493
+ telemetry_1.default.record('feature_used', {
494
+ feature: 'extended_thinking',
495
+ provider: 'bedrock_converse',
496
+ });
497
+ }
498
+ if (this.config.tools) {
499
+ telemetry_1.default.record('feature_used', {
500
+ feature: 'tool_use',
501
+ provider: 'bedrock_converse',
502
+ });
503
+ }
504
+ }
505
+ id() {
506
+ return `bedrock:converse:${this.modelName}`;
507
+ }
508
+ toString() {
509
+ return `[AWS Bedrock Converse Provider ${this.modelName}]`;
510
+ }
511
+ /**
512
+ * Loads a function from an external file
513
+ * @param fileRef The file reference in the format 'file://path/to/file:functionName'
514
+ * @returns The loaded function
515
+ */
516
+ async loadExternalFunction(fileRef) {
517
+ let filePath = fileRef.slice('file://'.length);
518
+ let functionName;
519
+ if (filePath.includes(':')) {
520
+ const splits = filePath.split(':');
521
+ if (splits[0] && (0, fileExtensions_1.isJavascriptFile)(splits[0])) {
522
+ [filePath, functionName] = splits;
523
+ }
524
+ }
525
+ try {
526
+ const resolvedPath = path_1.default.resolve(cliState_1.default.basePath || '', filePath);
527
+ logger_1.default.debug(`[Bedrock Converse] Loading function from ${resolvedPath}${functionName ? `:${functionName}` : ''}`);
528
+ const requiredModule = await (0, esm_1.importModule)(resolvedPath, functionName);
529
+ if (typeof requiredModule === 'function') {
530
+ return requiredModule;
531
+ }
532
+ else if (requiredModule &&
533
+ typeof requiredModule === 'object' &&
534
+ functionName &&
535
+ functionName in requiredModule) {
536
+ const fn = requiredModule[functionName];
537
+ if (typeof fn === 'function') {
538
+ return fn;
539
+ }
540
+ }
541
+ throw new Error(`Function callback malformed: ${filePath} must export ${functionName
542
+ ? `a named function '${functionName}'`
543
+ : 'a function or have a default export as a function'}`);
544
+ }
545
+ catch (error) {
546
+ throw new Error(`Error loading function from ${filePath}: ${error.message || String(error)}`);
547
+ }
548
+ }
549
+ /**
550
+ * Executes a function callback with proper error handling
551
+ */
552
+ async executeFunctionCallback(functionName, args) {
553
+ try {
554
+ // Check if we've already loaded this function
555
+ let callback = this.loadedFunctionCallbacks[functionName];
556
+ // If not loaded yet, try to load it now
557
+ if (!callback) {
558
+ const callbackRef = this.config.functionToolCallbacks?.[functionName];
559
+ if (callbackRef && typeof callbackRef === 'string') {
560
+ const callbackStr = callbackRef;
561
+ if (callbackStr.startsWith('file://')) {
562
+ callback = await this.loadExternalFunction(callbackStr);
563
+ }
564
+ else {
565
+ callback = new Function('return ' + callbackStr)();
566
+ }
567
+ // Cache for future use
568
+ this.loadedFunctionCallbacks[functionName] = callback;
569
+ }
570
+ else if (typeof callbackRef === 'function') {
571
+ callback = callbackRef;
572
+ this.loadedFunctionCallbacks[functionName] = callback;
573
+ }
574
+ }
575
+ if (!callback) {
576
+ throw new Error(`No callback found for function '${functionName}'`);
577
+ }
578
+ // Execute the callback
579
+ logger_1.default.debug(`[Bedrock Converse] Executing function '${functionName}' with args: ${args}`);
580
+ const result = await callback(args);
581
+ // Format the result
582
+ if (result === undefined || result === null) {
583
+ return '';
584
+ }
585
+ else if (typeof result === 'object') {
586
+ try {
587
+ return JSON.stringify(result);
588
+ }
589
+ catch (error) {
590
+ logger_1.default.warn(`Error stringifying result from function '${functionName}': ${error}`);
591
+ return String(result);
592
+ }
593
+ }
594
+ else {
595
+ return String(result);
596
+ }
597
+ }
598
+ catch (error) {
599
+ logger_1.default.error(`[Bedrock Converse] Error executing function '${functionName}': ${error.message || String(error)}`);
600
+ throw error;
601
+ }
602
+ }
603
+ /**
604
+ * Build the inference configuration from options
605
+ */
606
+ buildInferenceConfig() {
607
+ const maxTokens = this.config.maxTokens ||
608
+ this.config.max_tokens ||
609
+ (0, envars_1.getEnvInt)('AWS_BEDROCK_MAX_TOKENS') ||
610
+ undefined;
611
+ const temperature = this.config.temperature ?? (0, envars_1.getEnvFloat)('AWS_BEDROCK_TEMPERATURE') ?? undefined;
612
+ const topP = this.config.topP || this.config.top_p || (0, envars_1.getEnvFloat)('AWS_BEDROCK_TOP_P');
613
+ let stopSequences = this.config.stopSequences || this.config.stop;
614
+ if (!stopSequences) {
615
+ const envStop = (0, envars_1.getEnvString)('AWS_BEDROCK_STOP');
616
+ if (envStop) {
617
+ try {
618
+ stopSequences = JSON.parse(envStop);
619
+ }
620
+ catch {
621
+ // Ignore invalid JSON
622
+ }
623
+ }
624
+ }
625
+ // Only return config if at least one field is set
626
+ if (maxTokens !== undefined ||
627
+ temperature !== undefined ||
628
+ topP !== undefined ||
629
+ stopSequences) {
630
+ return {
631
+ ...(maxTokens !== undefined ? { maxTokens } : {}),
632
+ ...(temperature !== undefined ? { temperature } : {}),
633
+ ...(topP !== undefined ? { topP } : {}),
634
+ ...(stopSequences ? { stopSequences } : {}),
635
+ };
636
+ }
637
+ return undefined;
638
+ }
639
+ /**
640
+ * Build the tool configuration from options
641
+ */
642
+ async buildToolConfig(vars) {
643
+ if (!this.config.tools || this.config.tools.length === 0) {
644
+ return undefined;
645
+ }
646
+ // Load tools from external file with variable rendering if needed
647
+ const tools = await (0, index_1.maybeLoadToolsFromExternalFile)(this.config.tools, vars);
648
+ if (!tools || tools.length === 0) {
649
+ return undefined;
650
+ }
651
+ const converseTools = convertToolsToConverseFormat(tools);
652
+ const toolChoice = this.config.toolChoice
653
+ ? convertToolChoiceToConverseFormat(this.config.toolChoice)
654
+ : undefined;
655
+ return {
656
+ tools: converseTools,
657
+ ...(toolChoice ? { toolChoice } : {}),
658
+ };
659
+ }
660
+ /**
661
+ * Build the guardrail configuration
662
+ */
663
+ buildGuardrailConfig() {
664
+ if (!this.config.guardrailIdentifier) {
665
+ return undefined;
666
+ }
667
+ return {
668
+ guardrailIdentifier: String(this.config.guardrailIdentifier),
669
+ guardrailVersion: String(this.config.guardrailVersion || 'DRAFT'),
670
+ ...(this.config.trace ? { trace: this.config.trace } : {}),
671
+ };
672
+ }
673
+ /**
674
+ * Build additional model request fields (including thinking config)
675
+ */
676
+ buildAdditionalModelRequestFields() {
677
+ const fields = {
678
+ ...(this.config.additionalModelRequestFields || {}),
679
+ };
680
+ // Add thinking configuration for Claude models
681
+ if (this.config.thinking) {
682
+ fields.thinking = this.config.thinking;
683
+ }
684
+ return Object.keys(fields).length > 0 ? fields : undefined;
685
+ }
686
+ /**
687
+ * Build performance configuration
688
+ */
689
+ buildPerformanceConfig() {
690
+ if (!this.config.performanceConfig) {
691
+ return undefined;
692
+ }
693
+ return {
694
+ latency: this.config.performanceConfig.latency,
695
+ };
696
+ }
697
+ /**
698
+ * Build service tier configuration
699
+ */
700
+ buildServiceTier() {
701
+ if (!this.config.serviceTier) {
702
+ return undefined;
703
+ }
704
+ return {
705
+ type: this.config.serviceTier.type,
706
+ };
707
+ }
708
+ /**
709
+ * Main API call using Converse API
710
+ */
711
+ async callApi(prompt, context) {
712
+ // Parse the prompt into messages
713
+ const { messages, system } = parseConverseMessages(prompt);
714
+ // Build the request
715
+ const inferenceConfig = this.buildInferenceConfig();
716
+ const toolConfig = await this.buildToolConfig(context?.vars);
717
+ const guardrailConfig = this.buildGuardrailConfig();
718
+ const additionalModelRequestFields = this.buildAdditionalModelRequestFields();
719
+ const performanceConfig = this.buildPerformanceConfig();
720
+ const serviceTier = this.buildServiceTier();
721
+ const converseInput = {
722
+ modelId: this.modelName,
723
+ messages,
724
+ ...(system ? { system } : {}),
725
+ ...(inferenceConfig ? { inferenceConfig } : {}),
726
+ ...(toolConfig ? { toolConfig } : {}),
727
+ ...(guardrailConfig ? { guardrailConfig } : {}),
728
+ ...(additionalModelRequestFields ? { additionalModelRequestFields } : {}),
729
+ ...(this.config.additionalModelResponseFieldPaths
730
+ ? { additionalModelResponseFieldPaths: this.config.additionalModelResponseFieldPaths }
731
+ : {}),
732
+ ...(performanceConfig ? { performanceConfig } : {}),
733
+ ...(serviceTier ? { serviceTier } : {}),
734
+ };
735
+ logger_1.default.debug('Calling AWS Bedrock Converse API', {
736
+ modelId: this.modelName,
737
+ messageCount: messages.length,
738
+ hasSystem: !!system,
739
+ hasTools: !!toolConfig,
740
+ hasThinking: !!this.config.thinking,
741
+ });
742
+ // Check cache
743
+ const cache = await (0, cache_1.getCache)();
744
+ const cacheKey = `bedrock:converse:${this.modelName}:${JSON.stringify(converseInput)}`;
745
+ if ((0, cache_1.isCacheEnabled)()) {
746
+ const cachedResponse = await cache.get(cacheKey);
747
+ if (cachedResponse) {
748
+ logger_1.default.debug('Returning cached response');
749
+ const parsed = JSON.parse(cachedResponse);
750
+ return await this.parseResponse(parsed);
751
+ }
752
+ }
753
+ // Make the API call
754
+ let response;
755
+ try {
756
+ const bedrockInstance = await this.getBedrockInstance();
757
+ // Import and use ConverseCommand
758
+ const { ConverseCommand } = await Promise.resolve().then(() => __importStar(require('@aws-sdk/client-bedrock-runtime')));
759
+ const command = new ConverseCommand(converseInput);
760
+ response = await bedrockInstance.send(command);
761
+ }
762
+ catch (err) {
763
+ const errorMessage = err?.message || String(err);
764
+ logger_1.default.error('Bedrock Converse API error', { error: errorMessage });
765
+ // Provide helpful error messages for common issues
766
+ if (errorMessage.includes('ValidationException')) {
767
+ return {
768
+ error: `Bedrock Converse API validation error: ${errorMessage}. Check that your model supports the Converse API and all parameters are valid.`,
769
+ };
770
+ }
771
+ if (errorMessage.includes('AccessDeniedException')) {
772
+ return {
773
+ error: `Bedrock access denied: ${errorMessage}. Ensure you have bedrock:InvokeModel permission and model access is enabled.`,
774
+ };
775
+ }
776
+ return {
777
+ error: `Bedrock Converse API error: ${errorMessage}`,
778
+ };
779
+ }
780
+ // Cache the response
781
+ if ((0, cache_1.isCacheEnabled)()) {
782
+ try {
783
+ await cache.set(cacheKey, JSON.stringify(response));
784
+ }
785
+ catch (err) {
786
+ logger_1.default.error(`Failed to cache response: ${String(err)}`);
787
+ }
788
+ }
789
+ logger_1.default.debug('Bedrock Converse API response received', {
790
+ stopReason: response.stopReason,
791
+ hasUsage: !!response.usage,
792
+ hasMetrics: !!response.metrics,
793
+ });
794
+ return await this.parseResponse(response);
795
+ }
796
+ /**
797
+ * Parse the Converse API response into ProviderResponse format
798
+ */
799
+ async parseResponse(response) {
800
+ // Extract output text
801
+ const outputMessage = response.output?.message;
802
+ const content = outputMessage?.content || [];
803
+ const showThinking = this.config.showThinking !== false;
804
+ // Extract token usage
805
+ const usage = response.usage;
806
+ const promptTokens = usage?.inputTokens;
807
+ const completionTokens = usage?.outputTokens;
808
+ const totalTokens = usage?.totalTokens;
809
+ const cacheReadTokens = usage?.cacheReadInputTokens;
810
+ const cacheWriteTokens = usage?.cacheWriteInputTokens;
811
+ const tokenUsage = {
812
+ prompt: promptTokens,
813
+ completion: completionTokens,
814
+ total: totalTokens || (promptTokens || 0) + (completionTokens || 0),
815
+ numRequests: 1,
816
+ };
817
+ // Calculate cost
818
+ const cost = calculateBedrockConverseCost(this.modelName, promptTokens, completionTokens);
819
+ // Build metadata
820
+ const metadata = {};
821
+ // Add latency
822
+ if (response.metrics?.latencyMs) {
823
+ metadata.latencyMs = response.metrics.latencyMs;
824
+ }
825
+ // Add stop reason
826
+ if (response.stopReason) {
827
+ metadata.stopReason = response.stopReason;
828
+ }
829
+ // Add cache token info
830
+ if (cacheReadTokens !== undefined || cacheWriteTokens !== undefined) {
831
+ metadata.cacheTokens = {
832
+ read: cacheReadTokens,
833
+ write: cacheWriteTokens,
834
+ };
835
+ }
836
+ // Add performance config info
837
+ if (response.performanceConfig) {
838
+ metadata.performanceConfig = response.performanceConfig;
839
+ }
840
+ // Add service tier info
841
+ if (response.serviceTier) {
842
+ metadata.serviceTier = response.serviceTier;
843
+ }
844
+ // Add additional model response fields
845
+ if (response.additionalModelResponseFields) {
846
+ metadata.additionalModelResponseFields = response.additionalModelResponseFields;
847
+ }
848
+ // Add trace info if present
849
+ if (response.trace) {
850
+ metadata.trace = response.trace;
851
+ }
852
+ // Check for guardrail intervention
853
+ const guardrails = response.stopReason === 'guardrail_intervened'
854
+ ? { flagged: true, reason: 'guardrail_intervened' }
855
+ : undefined;
856
+ // Handle function tool callbacks if configured
857
+ if (this.config.functionToolCallbacks) {
858
+ const toolUseBlocks = content.filter((block) => 'toolUse' in block && block.toolUse !== undefined);
859
+ if (toolUseBlocks.length > 0) {
860
+ const results = [];
861
+ let hasSuccessfulCallback = false;
862
+ for (const block of toolUseBlocks) {
863
+ const functionName = block.toolUse.name;
864
+ if (functionName && this.config.functionToolCallbacks[functionName]) {
865
+ try {
866
+ const args = typeof block.toolUse.input === 'string'
867
+ ? block.toolUse.input
868
+ : JSON.stringify(block.toolUse.input || {});
869
+ const result = await this.executeFunctionCallback(functionName, args);
870
+ results.push(result);
871
+ hasSuccessfulCallback = true;
872
+ }
873
+ catch (_error) {
874
+ // If callback fails, fall back to original behavior
875
+ logger_1.default.debug(`[Bedrock Converse] Function callback failed for ${functionName}, falling back to tool_use output`);
876
+ hasSuccessfulCallback = false;
877
+ break;
878
+ }
879
+ }
880
+ }
881
+ if (hasSuccessfulCallback && results.length > 0) {
882
+ return {
883
+ output: results.join('\n'),
884
+ tokenUsage,
885
+ ...(cost !== undefined ? { cost } : {}),
886
+ ...(Object.keys(metadata).length > 0 ? { metadata } : {}),
887
+ ...(guardrails ? { guardrails } : {}),
888
+ };
889
+ }
890
+ }
891
+ }
892
+ // Default output extraction
893
+ const output = extractTextFromContentBlocks(content, showThinking);
894
+ return {
895
+ output,
896
+ tokenUsage,
897
+ ...(cost !== undefined ? { cost } : {}),
898
+ ...(Object.keys(metadata).length > 0 ? { metadata } : {}),
899
+ ...(guardrails ? { guardrails } : {}),
900
+ };
901
+ }
902
+ /**
903
+ * Streaming API call using ConverseStream
904
+ *
905
+ * Note: functionToolCallbacks are not executed in streaming mode.
906
+ * Tool use blocks are captured and returned in the output, but callbacks
907
+ * are not automatically invoked. Use non-streaming mode if you need
908
+ * automatic tool callback execution.
909
+ */
910
+ async callApiStreaming(prompt, context) {
911
+ // Parse the prompt into messages
912
+ const { messages, system } = parseConverseMessages(prompt);
913
+ // Build the request (same as non-streaming)
914
+ const inferenceConfig = this.buildInferenceConfig();
915
+ const toolConfig = await this.buildToolConfig(context?.vars);
916
+ const guardrailConfig = this.buildGuardrailConfig();
917
+ const additionalModelRequestFields = this.buildAdditionalModelRequestFields();
918
+ const performanceConfig = this.buildPerformanceConfig();
919
+ const serviceTier = this.buildServiceTier();
920
+ const converseStreamInput = {
921
+ modelId: this.modelName,
922
+ messages,
923
+ ...(system ? { system } : {}),
924
+ ...(inferenceConfig ? { inferenceConfig } : {}),
925
+ ...(toolConfig ? { toolConfig } : {}),
926
+ ...(guardrailConfig ? { guardrailConfig } : {}),
927
+ ...(additionalModelRequestFields ? { additionalModelRequestFields } : {}),
928
+ ...(performanceConfig ? { performanceConfig } : {}),
929
+ ...(serviceTier ? { serviceTier } : {}),
930
+ };
931
+ logger_1.default.debug('Calling AWS Bedrock ConverseStream API', {
932
+ modelId: this.modelName,
933
+ messageCount: messages.length,
934
+ });
935
+ try {
936
+ const bedrockInstance = await this.getBedrockInstance();
937
+ const { ConverseStreamCommand } = await Promise.resolve().then(() => __importStar(require('@aws-sdk/client-bedrock-runtime')));
938
+ const command = new ConverseStreamCommand(converseStreamInput);
939
+ const response = await bedrockInstance.send(command);
940
+ // Collect the full response while also providing a stream
941
+ let output = '';
942
+ let reasoning = '';
943
+ let stopReason;
944
+ let usage = {};
945
+ // Track tool use blocks being streamed
946
+ const toolUseBlocks = new Map();
947
+ const showThinking = this.config.showThinking !== false;
948
+ // Process the stream
949
+ if (response.stream) {
950
+ for await (const event of response.stream) {
951
+ // Handle content block start - includes tool use initialization
952
+ if ('contentBlockStart' in event && event.contentBlockStart) {
953
+ const blockIndex = event.contentBlockStart.contentBlockIndex ?? 0;
954
+ const start = event.contentBlockStart.start;
955
+ if (start && 'toolUse' in start && start.toolUse) {
956
+ toolUseBlocks.set(blockIndex, {
957
+ toolUseId: start.toolUse.toolUseId,
958
+ name: start.toolUse.name,
959
+ input: '',
960
+ });
961
+ }
962
+ }
963
+ if ('contentBlockDelta' in event && event.contentBlockDelta?.delta) {
964
+ const delta = event.contentBlockDelta.delta;
965
+ const blockIndex = event.contentBlockDelta.contentBlockIndex ?? 0;
966
+ if ('text' in delta && delta.text) {
967
+ output += delta.text;
968
+ }
969
+ if ('reasoningContent' in delta && delta.reasoningContent && showThinking) {
970
+ const rc = delta.reasoningContent;
971
+ if (rc.text) {
972
+ reasoning += rc.text;
973
+ }
974
+ }
975
+ // Handle streaming tool use input
976
+ if ('toolUse' in delta && delta.toolUse) {
977
+ const toolBlock = toolUseBlocks.get(blockIndex);
978
+ if (toolBlock && delta.toolUse.input) {
979
+ toolBlock.input += delta.toolUse.input;
980
+ }
981
+ }
982
+ }
983
+ if ('messageStop' in event && event.messageStop) {
984
+ stopReason = event.messageStop.stopReason;
985
+ }
986
+ if ('metadata' in event && event.metadata?.usage) {
987
+ usage = event.metadata.usage;
988
+ }
989
+ }
990
+ }
991
+ // Format tool use blocks for output (same as non-streaming)
992
+ const toolUseParts = [];
993
+ for (const [, toolBlock] of toolUseBlocks) {
994
+ if (toolBlock.name) {
995
+ let parsedInput;
996
+ try {
997
+ parsedInput = toolBlock.input ? JSON.parse(toolBlock.input) : {};
998
+ }
999
+ catch {
1000
+ parsedInput = toolBlock.input;
1001
+ }
1002
+ toolUseParts.push(JSON.stringify({
1003
+ type: 'tool_use',
1004
+ id: toolBlock.toolUseId,
1005
+ name: toolBlock.name,
1006
+ input: parsedInput,
1007
+ }));
1008
+ }
1009
+ }
1010
+ // Combine reasoning, output, and tool use
1011
+ const parts = [];
1012
+ if (reasoning) {
1013
+ parts.push(`<thinking>\n${reasoning}\n</thinking>`);
1014
+ }
1015
+ if (output) {
1016
+ parts.push(output);
1017
+ }
1018
+ if (toolUseParts.length > 0) {
1019
+ parts.push(...toolUseParts);
1020
+ }
1021
+ const finalOutput = parts.join('\n\n');
1022
+ const tokenUsage = {
1023
+ prompt: usage.inputTokens,
1024
+ completion: usage.outputTokens,
1025
+ total: usage.totalTokens || (usage.inputTokens || 0) + (usage.outputTokens || 0),
1026
+ numRequests: 1,
1027
+ };
1028
+ const cost = calculateBedrockConverseCost(this.modelName, usage.inputTokens, usage.outputTokens);
1029
+ return {
1030
+ output: finalOutput,
1031
+ tokenUsage,
1032
+ ...(cost !== undefined ? { cost } : {}),
1033
+ ...(stopReason ? { metadata: { stopReason } } : {}),
1034
+ };
1035
+ }
1036
+ catch (err) {
1037
+ return {
1038
+ error: `Bedrock ConverseStream API error: ${err?.message || String(err)}`,
1039
+ };
1040
+ }
1041
+ }
1042
+ }
1043
+ exports.AwsBedrockConverseProvider = AwsBedrockConverseProvider;
1044
+ //# sourceMappingURL=converse.js.map