@assemble-dev/providers 0.1.0 → 0.3.0

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/index.cjs CHANGED
@@ -22,21 +22,41 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AnthropicMessagesResponseSchema: () => AnthropicMessagesResponseSchema,
24
24
  AnthropicStreamEventSchema: () => AnthropicStreamEventSchema,
25
+ AzureOpenAiChatCompletionResponseSchema: () => AzureOpenAiChatCompletionResponseSchema,
26
+ ChatMessageCacheControlSchema: () => ChatMessageCacheControlSchema,
25
27
  ChatMessageRoleSchema: () => ChatMessageRoleSchema,
26
28
  ChatMessageSchema: () => ChatMessageSchema,
27
29
  ChatStopReasonSchema: () => ChatStopReasonSchema,
28
30
  MessageContentBlockSchema: () => MessageContentBlockSchema,
29
31
  ModelToolCallSchema: () => ModelToolCallSchema,
30
32
  anthropic: () => anthropic,
33
+ anthropicBatchJsonOnlySystemInstruction: () => anthropicBatchJsonOnlySystemInstruction,
34
+ anthropicBatchTraceWorkflowName: () => anthropicBatchTraceWorkflowName,
35
+ applyCacheControlToLastContentBlock: () => applyCacheControlToLastContentBlock,
36
+ awsSigV4Algorithm: () => awsSigV4Algorithm,
37
+ azureOpenai: () => azureOpenai,
38
+ bedrock: () => bedrock,
39
+ bedrockAnthropicVersion: () => bedrockAnthropicVersion,
40
+ buildAnthropicCacheControl: () => buildAnthropicCacheControl,
31
41
  buildAnthropicRequestBody: () => buildAnthropicRequestBody,
42
+ buildAnthropicStructuredOutputJsonSchema: () => buildAnthropicStructuredOutputJsonSchema,
43
+ buildAzureOpenAiChatCompletionsUrl: () => buildAzureOpenAiChatCompletionsUrl,
44
+ buildAzureOpenAiChatRequestBody: () => buildAzureOpenAiChatRequestBody,
45
+ buildBedrockInvokeModelRequestBody: () => buildBedrockInvokeModelRequestBody,
46
+ buildBedrockInvokeModelUrl: () => buildBedrockInvokeModelUrl,
47
+ buildGeminiResponseSchema: () => buildGeminiResponseSchema,
32
48
  buildOpenAiRequestBody: () => buildOpenAiRequestBody,
49
+ buildOpenAiStructuredOutputJsonSchema: () => buildOpenAiStructuredOutputJsonSchema,
33
50
  buildProviderCanceledError: () => buildProviderCanceledError,
34
51
  calculateProviderRetryDelayMs: () => calculateProviderRetryDelayMs,
52
+ convertZodSchemaToJsonSchema: () => convertZodSchemaToJsonSchema,
35
53
  createAnthropicBatchClient: () => createAnthropicBatchClient,
36
54
  defaultAnthropicBaseUrl: () => defaultAnthropicBaseUrl,
37
55
  defaultAnthropicBatchPollIntervalMs: () => defaultAnthropicBatchPollIntervalMs,
38
56
  defaultAnthropicBatchTimeoutMs: () => defaultAnthropicBatchTimeoutMs,
39
57
  defaultAnthropicMaxOutputTokens: () => defaultAnthropicMaxOutputTokens,
58
+ defaultAzureOpenAiApiVersion: () => defaultAzureOpenAiApiVersion,
59
+ defaultBedrockMaxOutputTokens: () => defaultBedrockMaxOutputTokens,
40
60
  defaultGeminiBaseUrl: () => defaultGeminiBaseUrl,
41
61
  defaultOpenAiBaseUrl: () => defaultOpenAiBaseUrl,
42
62
  defaultProviderRetryInitialDelayMs: () => defaultProviderRetryInitialDelayMs,
@@ -47,6 +67,7 @@ __export(index_exports, {
47
67
  executeProviderCallWithModelFallback: () => executeProviderCallWithModelFallback,
48
68
  executeProviderCallWithRetry: () => executeProviderCallWithRetry,
49
69
  extractAnthropicTextContent: () => extractAnthropicTextContent,
70
+ extractAnthropicThinkingText: () => extractAnthropicThinkingText,
50
71
  extractAnthropicToolCalls: () => extractAnthropicToolCalls,
51
72
  extractMessageText: () => extractMessageText,
52
73
  gemini: () => gemini,
@@ -55,19 +76,34 @@ __export(index_exports, {
55
76
  joinSystemMessageText: () => joinSystemMessageText,
56
77
  mapAnthropicResponseToChatCompletionResult: () => mapAnthropicResponseToChatCompletionResult,
57
78
  mapAnthropicUsageToTokenUsage: () => mapAnthropicUsageToTokenUsage,
79
+ mapAzureOpenAiResponseToChatCompletionResult: () => mapAzureOpenAiResponseToChatCompletionResult,
80
+ mapAzureOpenAiUsageToTokenUsage: () => mapAzureOpenAiUsageToTokenUsage,
58
81
  mapChatMessageToAnthropicRequestMessage: () => mapChatMessageToAnthropicRequestMessage,
59
82
  mapChatMessageToOpenAiRequestMessage: () => mapChatMessageToOpenAiRequestMessage,
60
83
  mapModelToolChoiceToAnthropicToolChoice: () => mapModelToolChoiceToAnthropicToolChoice,
61
84
  mapModelToolChoiceToOpenAiToolChoice: () => mapModelToolChoiceToOpenAiToolChoice,
62
85
  mapModelToolDefinitionToOpenAiTool: () => mapModelToolDefinitionToOpenAiTool,
63
86
  mapModelToolDefinitionsToAnthropicTools: () => mapModelToolDefinitionsToAnthropicTools,
87
+ mergeProviderRequestExtraBody: () => mergeProviderRequestExtraBody,
64
88
  mockModel: () => mockModel,
65
89
  normalizeAnthropicStopReason: () => normalizeAnthropicStopReason,
90
+ normalizeAzureOpenAiFinishReason: () => normalizeAzureOpenAiFinishReason,
91
+ openAiStructuredOutputSchemaName: () => openAiStructuredOutputSchemaName,
66
92
  openai: () => openai,
93
+ parseAnthropicBatchStructuredContent: () => parseAnthropicBatchStructuredContent,
67
94
  parseAnthropicStreamEvents: () => parseAnthropicStreamEvents,
68
95
  parseAnthropicToolInputJson: () => parseAnthropicToolInputJson,
96
+ parseAzureOpenAiStreamEvents: () => parseAzureOpenAiStreamEvents,
97
+ parseAzureOpenAiToolArgumentsJson: () => parseAzureOpenAiToolArgumentsJson,
98
+ resolveAnthropicPromptCachingSettings: () => resolveAnthropicPromptCachingSettings,
99
+ resolveBedrockCredentials: () => resolveBedrockCredentials,
69
100
  resolveProviderApiKey: () => resolveProviderApiKey,
70
- streamAnthropicChatCompletion: () => streamAnthropicChatCompletion
101
+ sanitizeJsonSchemaForAnthropicStructuredOutput: () => sanitizeJsonSchemaForAnthropicStructuredOutput,
102
+ sanitizeJsonSchemaForGeminiResponseSchema: () => sanitizeJsonSchemaForGeminiResponseSchema,
103
+ sanitizeJsonSchemaForOpenAiStructuredOutput: () => sanitizeJsonSchemaForOpenAiStructuredOutput,
104
+ signAwsRequestWithSigV4: () => signAwsRequestWithSigV4,
105
+ streamAnthropicChatCompletion: () => streamAnthropicChatCompletion,
106
+ streamAzureOpenAiChatCompletion: () => streamAzureOpenAiChatCompletion
71
107
  });
72
108
  module.exports = __toCommonJS(index_exports);
73
109
 
@@ -101,12 +137,16 @@ var ModelToolCallSchema = import_zod.z.object({
101
137
  toolName: import_zod.z.string(),
102
138
  input: import_json.JsonValueSchema
103
139
  });
140
+ var ChatMessageCacheControlSchema = import_zod.z.object({
141
+ ttl: import_zod.z.enum(["5m", "1h"]).optional()
142
+ });
104
143
  var ChatMessageSchema = import_zod.z.object({
105
144
  role: ChatMessageRoleSchema,
106
145
  content: import_zod.z.union([import_zod.z.string(), import_zod.z.array(MessageContentBlockSchema)]),
107
146
  toolName: import_zod.z.string().optional(),
108
147
  toolCallId: import_zod.z.string().optional(),
109
- toolCalls: import_zod.z.array(ModelToolCallSchema).optional()
148
+ toolCalls: import_zod.z.array(ModelToolCallSchema).optional(),
149
+ cacheControl: ChatMessageCacheControlSchema.optional()
110
150
  });
111
151
  var ChatStopReasonSchema = import_zod.z.enum([
112
152
  "end_turn",
@@ -122,14 +162,222 @@ function extractMessageText(message) {
122
162
  }
123
163
 
124
164
  // src/openai-adapter.ts
125
- var import_zod3 = require("zod");
126
- var import_errors14 = require("@assemble-dev/shared-types/errors");
127
- var import_json3 = require("@assemble-dev/shared-types/json");
128
- var import_errors15 = require("@assemble-dev/shared-utils/errors");
165
+ var import_zod4 = require("zod");
166
+ var import_errors16 = require("@assemble-dev/shared-types/errors");
167
+ var import_json4 = require("@assemble-dev/shared-types/json");
168
+ var import_errors17 = require("@assemble-dev/shared-utils/errors");
129
169
 
130
170
  // src/openai-request-mapping.ts
171
+ var import_errors3 = require("@assemble-dev/shared-types/errors");
172
+ var import_errors4 = require("@assemble-dev/shared-utils/errors");
173
+
174
+ // src/structured-output-json-schema.ts
175
+ var import_zod2 = require("zod");
131
176
  var import_errors = require("@assemble-dev/shared-types/errors");
177
+ var import_json2 = require("@assemble-dev/shared-types/json");
132
178
  var import_errors2 = require("@assemble-dev/shared-utils/errors");
179
+
180
+ // src/json-schema-tree.ts
181
+ var schemaMapKeywords = ["properties", "$defs"];
182
+ var schemaListKeywords = ["anyOf", "oneOf", "allOf", "prefixItems"];
183
+ var schemaValueKeywords = [
184
+ "items",
185
+ "additionalProperties",
186
+ "not",
187
+ "if",
188
+ "then",
189
+ "else",
190
+ "contains",
191
+ "propertyNames"
192
+ ];
193
+ function isJsonObject(value) {
194
+ return typeof value === "object" && value !== null && !Array.isArray(value);
195
+ }
196
+ function transformJsonSchemaNode(node, transformNode) {
197
+ const result = { ...transformNode({ ...node }) };
198
+ for (const keyword of schemaMapKeywords) {
199
+ const mapValue = result[keyword];
200
+ if (mapValue !== void 0 && isJsonObject(mapValue)) {
201
+ result[keyword] = transformJsonSchemaMap(mapValue, transformNode);
202
+ }
203
+ }
204
+ for (const keyword of schemaListKeywords) {
205
+ const listValue = result[keyword];
206
+ if (Array.isArray(listValue)) {
207
+ result[keyword] = listValue.map(
208
+ (entry) => isJsonObject(entry) ? transformJsonSchemaNode(entry, transformNode) : entry
209
+ );
210
+ }
211
+ }
212
+ for (const keyword of schemaValueKeywords) {
213
+ const schemaValue = result[keyword];
214
+ if (schemaValue !== void 0 && isJsonObject(schemaValue)) {
215
+ result[keyword] = transformJsonSchemaNode(schemaValue, transformNode);
216
+ }
217
+ }
218
+ return result;
219
+ }
220
+ function transformJsonSchemaMap(schemaMap, transformNode) {
221
+ const result = {};
222
+ for (const [schemaName, schemaValue] of Object.entries(schemaMap)) {
223
+ result[schemaName] = isJsonObject(schemaValue) ? transformJsonSchemaNode(schemaValue, transformNode) : schemaValue;
224
+ }
225
+ return result;
226
+ }
227
+ function inlineJsonSchemaReferences(root) {
228
+ const rootDefinitions = root["$defs"];
229
+ const definitions = rootDefinitions !== void 0 && isJsonObject(rootDefinitions) ? rootDefinitions : {};
230
+ const resolvedRoot = resolveJsonSchemaReferences(
231
+ root,
232
+ definitions,
233
+ /* @__PURE__ */ new Set()
234
+ );
235
+ return isJsonObject(resolvedRoot) ? resolvedRoot : {};
236
+ }
237
+ function resolveJsonSchemaReferences(value, definitions, activeReferences) {
238
+ if (Array.isArray(value)) {
239
+ return value.map(
240
+ (entry) => resolveJsonSchemaReferences(entry, definitions, activeReferences)
241
+ );
242
+ }
243
+ if (!isJsonObject(value)) {
244
+ return value;
245
+ }
246
+ const referenceTarget = value["$ref"];
247
+ if (typeof referenceTarget === "string") {
248
+ return resolveJsonSchemaReferenceTarget(
249
+ referenceTarget,
250
+ definitions,
251
+ activeReferences
252
+ );
253
+ }
254
+ const result = {};
255
+ for (const [key, entryValue] of Object.entries(value)) {
256
+ if (key !== "$defs") {
257
+ result[key] = resolveJsonSchemaReferences(
258
+ entryValue,
259
+ definitions,
260
+ activeReferences
261
+ );
262
+ }
263
+ }
264
+ return result;
265
+ }
266
+ function resolveJsonSchemaReferenceTarget(referenceTarget, definitions, activeReferences) {
267
+ if (activeReferences.has(referenceTarget)) {
268
+ return {};
269
+ }
270
+ const definitionsPrefix = "#/$defs/";
271
+ if (!referenceTarget.startsWith(definitionsPrefix)) {
272
+ return {};
273
+ }
274
+ const definition = definitions[referenceTarget.slice(definitionsPrefix.length)];
275
+ if (definition === void 0 || !isJsonObject(definition)) {
276
+ return {};
277
+ }
278
+ return resolveJsonSchemaReferences(
279
+ definition,
280
+ definitions,
281
+ /* @__PURE__ */ new Set([...activeReferences, referenceTarget])
282
+ );
283
+ }
284
+ function removeJsonSchemaKeywords(node, keywords) {
285
+ const result = {};
286
+ for (const [key, value] of Object.entries(node)) {
287
+ if (!keywords.includes(key)) {
288
+ result[key] = value;
289
+ }
290
+ }
291
+ return result;
292
+ }
293
+
294
+ // src/structured-output-json-schema.ts
295
+ var openAiStructuredOutputSchemaName = "structured_output";
296
+ var schemaMetadataKeywords = ["$schema", "$id"];
297
+ var anthropicUnsupportedSchemaKeywords = [
298
+ ...schemaMetadataKeywords,
299
+ "minimum",
300
+ "maximum",
301
+ "exclusiveMinimum",
302
+ "exclusiveMaximum",
303
+ "minLength",
304
+ "maxLength",
305
+ "multipleOf"
306
+ ];
307
+ var openAiUnsupportedSchemaKeywords = [
308
+ ...anthropicUnsupportedSchemaKeywords,
309
+ "pattern",
310
+ "format",
311
+ "minItems",
312
+ "maxItems",
313
+ "uniqueItems",
314
+ "default"
315
+ ];
316
+ function convertZodSchemaToJsonSchema(schema) {
317
+ try {
318
+ return import_json2.JsonObjectSchema.parse(import_zod2.z.toJSONSchema(schema, { io: "input" }));
319
+ } catch (error) {
320
+ throw new import_errors2.AppError({
321
+ code: import_errors.AppErrorCode.BadRequest,
322
+ message: "Structured output schema could not be converted to JSON Schema",
323
+ statusCode: 400,
324
+ cause: error instanceof Error ? error : void 0
325
+ });
326
+ }
327
+ }
328
+ function buildAnthropicStructuredOutputJsonSchema(schema) {
329
+ return sanitizeJsonSchemaForAnthropicStructuredOutput(
330
+ convertZodSchemaToJsonSchema(schema)
331
+ );
332
+ }
333
+ function sanitizeJsonSchemaForAnthropicStructuredOutput(jsonSchema) {
334
+ return transformJsonSchemaNode(
335
+ inlineJsonSchemaReferences(jsonSchema),
336
+ sanitizeAnthropicSchemaNode
337
+ );
338
+ }
339
+ function buildOpenAiStructuredOutputJsonSchema(schema) {
340
+ return sanitizeJsonSchemaForOpenAiStructuredOutput(
341
+ convertZodSchemaToJsonSchema(schema)
342
+ );
343
+ }
344
+ function sanitizeJsonSchemaForOpenAiStructuredOutput(jsonSchema) {
345
+ return transformJsonSchemaNode(jsonSchema, sanitizeOpenAiSchemaNode);
346
+ }
347
+ function sanitizeAnthropicSchemaNode(node) {
348
+ const sanitized = removeJsonSchemaKeywords(
349
+ node,
350
+ anthropicUnsupportedSchemaKeywords
351
+ );
352
+ if (sanitized["type"] === "object") {
353
+ sanitized["additionalProperties"] = false;
354
+ }
355
+ return sanitized;
356
+ }
357
+ function sanitizeOpenAiSchemaNode(node) {
358
+ const sanitized = removeJsonSchemaKeywords(
359
+ node,
360
+ openAiUnsupportedSchemaKeywords
361
+ );
362
+ if (sanitized["type"] !== "object") {
363
+ return sanitized;
364
+ }
365
+ sanitized["additionalProperties"] = false;
366
+ const propertyNames = listSchemaPropertyNames(sanitized);
367
+ if (propertyNames.length > 0) {
368
+ sanitized["required"] = propertyNames;
369
+ }
370
+ return sanitized;
371
+ }
372
+ function listSchemaPropertyNames(node) {
373
+ const properties = node["properties"];
374
+ if (properties === void 0 || !isJsonObject(properties)) {
375
+ return [];
376
+ }
377
+ return Object.keys(properties);
378
+ }
379
+
380
+ // src/openai-request-mapping.ts
133
381
  function buildOpenAiRequestBody(model, input) {
134
382
  const requestBody = {
135
383
  model,
@@ -141,7 +389,16 @@ function buildOpenAiRequestBody(model, input) {
141
389
  if (input.maxOutputTokens !== void 0) {
142
390
  requestBody.max_tokens = input.maxOutputTokens;
143
391
  }
144
- if (input.requireJsonObjectResponse) {
392
+ if (input.structuredOutputJsonSchema !== void 0) {
393
+ requestBody.response_format = {
394
+ type: "json_schema",
395
+ json_schema: {
396
+ name: openAiStructuredOutputSchemaName,
397
+ strict: true,
398
+ schema: input.structuredOutputJsonSchema
399
+ }
400
+ };
401
+ } else if (input.requireJsonObjectResponse === true) {
145
402
  requestBody.response_format = { type: "json_object" };
146
403
  }
147
404
  if (input.tools !== void 0 && input.tools.length > 0) {
@@ -227,17 +484,17 @@ function mapMessageContentBlockToOpenAiContentPart(contentBlock) {
227
484
  }
228
485
  };
229
486
  }
230
- throw new import_errors2.AppError({
231
- code: import_errors.AppErrorCode.ValidationFailed,
487
+ throw new import_errors4.AppError({
488
+ code: import_errors3.AppErrorCode.ValidationFailed,
232
489
  message: "OpenAI adapter does not support document content blocks in chat messages",
233
490
  statusCode: 400
234
491
  });
235
492
  }
236
493
 
237
494
  // src/parse-structured-json.ts
238
- var import_errors3 = require("@assemble-dev/shared-types/errors");
239
- var import_json2 = require("@assemble-dev/shared-types/json");
240
- var import_errors4 = require("@assemble-dev/shared-utils/errors");
495
+ var import_errors5 = require("@assemble-dev/shared-types/errors");
496
+ var import_json3 = require("@assemble-dev/shared-types/json");
497
+ var import_errors6 = require("@assemble-dev/shared-utils/errors");
241
498
  var markdownCodeFencePattern = /^```[A-Za-z]*\s*\n?([\s\S]*?)\n?```$/;
242
499
  function parseStructuredJsonText(text, schema) {
243
500
  return schema.parse(parseJsonText(stripMarkdownCodeFences(text)));
@@ -252,10 +509,10 @@ function stripMarkdownCodeFences(text) {
252
509
  }
253
510
  function parseJsonText(text) {
254
511
  try {
255
- return import_json2.JsonValueSchema.parse(JSON.parse(text));
512
+ return import_json3.JsonValueSchema.parse(JSON.parse(text));
256
513
  } catch (error) {
257
- throw new import_errors4.AppError({
258
- code: import_errors3.AppErrorCode.ValidationFailed,
514
+ throw new import_errors6.AppError({
515
+ code: import_errors5.AppErrorCode.ValidationFailed,
259
516
  message: "Structured output was not valid JSON",
260
517
  statusCode: 422,
261
518
  cause: error instanceof Error ? error : void 0
@@ -264,9 +521,9 @@ function parseJsonText(text) {
264
521
  }
265
522
 
266
523
  // src/provider-api-key.ts
267
- var import_zod2 = require("zod");
268
- var import_errors5 = require("@assemble-dev/shared-types/errors");
269
- var import_errors6 = require("@assemble-dev/shared-utils/errors");
524
+ var import_zod3 = require("zod");
525
+ var import_errors7 = require("@assemble-dev/shared-types/errors");
526
+ var import_errors8 = require("@assemble-dev/shared-utils/errors");
270
527
  var import_provider_keys = require("@assemble-dev/shared-utils/provider-keys");
271
528
  function resolveProviderApiKey(input) {
272
529
  if (input.apiKey !== void 0 && input.apiKey.length > 0) {
@@ -279,8 +536,8 @@ function resolveProviderApiKey(input) {
279
536
  }
280
537
  function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
281
538
  if (!(0, import_provider_keys.validateProviderApiKeyName)(apiKeyName)) {
282
- throw new import_errors6.AppError({
283
- code: import_errors5.AppErrorCode.BadRequest,
539
+ throw new import_errors8.AppError({
540
+ code: import_errors7.AppErrorCode.BadRequest,
284
541
  message: `Invalid ${input.providerLabel} apiKeyName "${apiKeyName}". Expected ${import_provider_keys.expectedProviderApiKeyNameFormat}.`,
285
542
  statusCode: 400
286
543
  });
@@ -288,8 +545,8 @@ function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
288
545
  const envVarName = (0, import_provider_keys.buildNamedApiKeyEnvVarName)(input.baseEnvVarName, apiKeyName);
289
546
  const envApiKey = readEnvironmentVariable(envVarName);
290
547
  if (envApiKey === void 0 || envApiKey.length === 0) {
291
- throw new import_errors6.AppError({
292
- code: import_errors5.AppErrorCode.Unauthorized,
548
+ throw new import_errors8.AppError({
549
+ code: import_errors7.AppErrorCode.Unauthorized,
293
550
  message: `${input.providerLabel} API key named "${apiKeyName}" is missing. Set the ${envVarName} environment variable or pass apiKey to ${input.adapterFunctionName}.`,
294
551
  statusCode: 401
295
552
  });
@@ -299,8 +556,8 @@ function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
299
556
  function resolveBaseProviderApiKeyFromEnv(input) {
300
557
  const envApiKey = readEnvironmentVariable(input.baseEnvVarName);
301
558
  if (envApiKey === void 0 || envApiKey.length === 0) {
302
- throw new import_errors6.AppError({
303
- code: import_errors5.AppErrorCode.Unauthorized,
559
+ throw new import_errors8.AppError({
560
+ code: import_errors7.AppErrorCode.Unauthorized,
304
561
  message: `${input.providerLabel} API key is missing. Pass apiKey to ${input.adapterFunctionName} or set the ${input.baseEnvVarName} environment variable.`,
305
562
  statusCode: 401
306
563
  });
@@ -308,19 +565,19 @@ function resolveBaseProviderApiKeyFromEnv(input) {
308
565
  return envApiKey;
309
566
  }
310
567
  function readEnvironmentVariable(envVarName) {
311
- const parsedEnv = import_zod2.z.object({ [envVarName]: import_zod2.z.string().optional() }).parse(process.env);
568
+ const parsedEnv = import_zod3.z.object({ [envVarName]: import_zod3.z.string().optional() }).parse(process.env);
312
569
  return parsedEnv[envVarName];
313
570
  }
314
571
 
315
572
  // src/provider-cancellation.ts
316
- var import_errors7 = require("@assemble-dev/shared-types/errors");
317
- var import_errors8 = require("@assemble-dev/shared-utils/errors");
573
+ var import_errors9 = require("@assemble-dev/shared-types/errors");
574
+ var import_errors10 = require("@assemble-dev/shared-utils/errors");
318
575
  function isAbortError(error) {
319
576
  return error.name === "AbortError";
320
577
  }
321
578
  function buildProviderCanceledError(providerLabel) {
322
- return new import_errors8.AppError({
323
- code: import_errors7.AppErrorCode.Canceled,
579
+ return new import_errors10.AppError({
580
+ code: import_errors9.AppErrorCode.Canceled,
324
581
  message: `${providerLabel} request was canceled`,
325
582
  statusCode: 499
326
583
  });
@@ -336,19 +593,28 @@ async function executeAbortableProviderFetch(providerLabel, performFetch) {
336
593
  }
337
594
  }
338
595
 
596
+ // src/provider-extra-body.ts
597
+ function mergeProviderRequestExtraBody(requestBody, adapterExtraBody, requestExtraBody) {
598
+ return {
599
+ ...requestBody,
600
+ ...adapterExtraBody ?? {},
601
+ ...requestExtraBody ?? {}
602
+ };
603
+ }
604
+
339
605
  // src/provider-fallback.ts
340
- var import_errors11 = require("@assemble-dev/shared-utils/errors");
606
+ var import_errors13 = require("@assemble-dev/shared-utils/errors");
341
607
 
342
608
  // src/provider-retry.ts
343
- var import_errors9 = require("@assemble-dev/shared-types/errors");
344
- var import_errors10 = require("@assemble-dev/shared-utils/errors");
609
+ var import_errors11 = require("@assemble-dev/shared-types/errors");
610
+ var import_errors12 = require("@assemble-dev/shared-utils/errors");
345
611
  var defaultProviderRetryMaxAttempts = 3;
346
612
  var defaultProviderRetryInitialDelayMs = 500;
347
613
  var defaultProviderRetryMaxDelayMs = 8e3;
348
614
  var retryableAppErrorCodes = /* @__PURE__ */ new Set([
349
- import_errors9.AppErrorCode.RateLimited,
350
- import_errors9.AppErrorCode.ServiceUnavailable,
351
- import_errors9.AppErrorCode.InternalServerError
615
+ import_errors11.AppErrorCode.RateLimited,
616
+ import_errors11.AppErrorCode.ServiceUnavailable,
617
+ import_errors11.AppErrorCode.InternalServerError
352
618
  ]);
353
619
  function isRetryableProviderAppError(appError) {
354
620
  return retryableAppErrorCodes.has(appError.code);
@@ -363,7 +629,7 @@ async function executeProviderCallWithRetry(retryOptions, executeCall, waitFor)
363
629
  try {
364
630
  return await executeCall();
365
631
  } catch (error) {
366
- if (error instanceof import_errors10.AppError && !isRetryableProviderAppError(error)) {
632
+ if (error instanceof import_errors12.AppError && !isRetryableProviderAppError(error)) {
367
633
  throw error;
368
634
  }
369
635
  if (error instanceof Error && isAbortError(error)) {
@@ -397,7 +663,7 @@ async function executeProviderCallWithModelFallback(fallbackModel, executePrimar
397
663
  if (fallbackModel === void 0) {
398
664
  throw error;
399
665
  }
400
- if (error instanceof import_errors11.AppError && !isRetryableProviderAppError(error)) {
666
+ if (error instanceof import_errors13.AppError && !isRetryableProviderAppError(error)) {
401
667
  throw error;
402
668
  }
403
669
  if (error instanceof Error && isAbortError(error)) {
@@ -408,11 +674,11 @@ async function executeProviderCallWithModelFallback(fallbackModel, executePrimar
408
674
  }
409
675
 
410
676
  // src/provider-status-error.ts
411
- var import_errors12 = require("@assemble-dev/shared-types/errors");
412
- var import_errors13 = require("@assemble-dev/shared-utils/errors");
677
+ var import_errors14 = require("@assemble-dev/shared-types/errors");
678
+ var import_errors15 = require("@assemble-dev/shared-utils/errors");
413
679
  function buildProviderStatusError(providerLabel, providerStatus) {
414
680
  const code = mapProviderStatusToAppErrorCode(providerStatus);
415
- return new import_errors13.AppError({
681
+ return new import_errors15.AppError({
416
682
  code,
417
683
  message: `${providerLabel} request failed with status ${String(providerStatus)}`,
418
684
  statusCode: mapAppErrorCodeToStatusCode(code),
@@ -420,44 +686,44 @@ function buildProviderStatusError(providerLabel, providerStatus) {
420
686
  });
421
687
  }
422
688
  function buildProviderInvalidResponseError(providerLabel, expectedShapeDescription) {
423
- return new import_errors13.AppError({
424
- code: import_errors12.AppErrorCode.ValidationFailed,
689
+ return new import_errors15.AppError({
690
+ code: import_errors14.AppErrorCode.ValidationFailed,
425
691
  message: `${providerLabel} response did not match the expected ${expectedShapeDescription} shape`,
426
692
  statusCode: 502
427
693
  });
428
694
  }
429
695
  function mapProviderStatusToAppErrorCode(providerStatus) {
430
696
  if (providerStatus === 400) {
431
- return import_errors12.AppErrorCode.BadRequest;
697
+ return import_errors14.AppErrorCode.BadRequest;
432
698
  }
433
699
  if (providerStatus === 401) {
434
- return import_errors12.AppErrorCode.Unauthorized;
700
+ return import_errors14.AppErrorCode.Unauthorized;
435
701
  }
436
702
  if (providerStatus === 403) {
437
- return import_errors12.AppErrorCode.Forbidden;
703
+ return import_errors14.AppErrorCode.Forbidden;
438
704
  }
439
705
  if (providerStatus === 404) {
440
- return import_errors12.AppErrorCode.NotFound;
706
+ return import_errors14.AppErrorCode.NotFound;
441
707
  }
442
708
  if (providerStatus === 429) {
443
- return import_errors12.AppErrorCode.RateLimited;
709
+ return import_errors14.AppErrorCode.RateLimited;
444
710
  }
445
- return import_errors12.AppErrorCode.InternalServerError;
711
+ return import_errors14.AppErrorCode.InternalServerError;
446
712
  }
447
713
  function mapAppErrorCodeToStatusCode(code) {
448
- if (code === import_errors12.AppErrorCode.BadRequest) {
714
+ if (code === import_errors14.AppErrorCode.BadRequest) {
449
715
  return 400;
450
716
  }
451
- if (code === import_errors12.AppErrorCode.Unauthorized) {
717
+ if (code === import_errors14.AppErrorCode.Unauthorized) {
452
718
  return 401;
453
719
  }
454
- if (code === import_errors12.AppErrorCode.Forbidden) {
720
+ if (code === import_errors14.AppErrorCode.Forbidden) {
455
721
  return 403;
456
722
  }
457
- if (code === import_errors12.AppErrorCode.NotFound) {
723
+ if (code === import_errors14.AppErrorCode.NotFound) {
458
724
  return 404;
459
725
  }
460
- if (code === import_errors12.AppErrorCode.RateLimited) {
726
+ if (code === import_errors14.AppErrorCode.RateLimited) {
461
727
  return 429;
462
728
  }
463
729
  return 500;
@@ -465,33 +731,29 @@ function mapAppErrorCodeToStatusCode(code) {
465
731
 
466
732
  // src/openai-adapter.ts
467
733
  var defaultOpenAiBaseUrl = "https://api.openai.com/v1";
468
- var OpenAiResponseToolCallSchema = import_zod3.z.object({
469
- id: import_zod3.z.string(),
470
- function: import_zod3.z.object({
471
- name: import_zod3.z.string(),
472
- arguments: import_zod3.z.string()
734
+ var OpenAiResponseToolCallSchema = import_zod4.z.object({
735
+ id: import_zod4.z.string(),
736
+ function: import_zod4.z.object({
737
+ name: import_zod4.z.string(),
738
+ arguments: import_zod4.z.string()
473
739
  })
474
740
  });
475
- var OpenAiChatCompletionResponseSchema = import_zod3.z.object({
476
- choices: import_zod3.z.array(
477
- import_zod3.z.object({
478
- message: import_zod3.z.object({
479
- content: import_zod3.z.string().nullable(),
480
- tool_calls: import_zod3.z.array(OpenAiResponseToolCallSchema).optional()
741
+ var OpenAiChatCompletionResponseSchema = import_zod4.z.object({
742
+ choices: import_zod4.z.array(
743
+ import_zod4.z.object({
744
+ message: import_zod4.z.object({
745
+ content: import_zod4.z.string().nullable(),
746
+ tool_calls: import_zod4.z.array(OpenAiResponseToolCallSchema).optional()
481
747
  }),
482
- finish_reason: import_zod3.z.string().nullable().optional()
748
+ finish_reason: import_zod4.z.string().nullable().optional()
483
749
  })
484
750
  ).min(1),
485
- usage: import_zod3.z.object({
486
- prompt_tokens: import_zod3.z.number().int().nonnegative(),
487
- completion_tokens: import_zod3.z.number().int().nonnegative(),
488
- total_tokens: import_zod3.z.number().int().nonnegative()
751
+ usage: import_zod4.z.object({
752
+ prompt_tokens: import_zod4.z.number().int().nonnegative(),
753
+ completion_tokens: import_zod4.z.number().int().nonnegative(),
754
+ total_tokens: import_zod4.z.number().int().nonnegative()
489
755
  })
490
756
  });
491
- var structuredOutputSystemMessage = {
492
- role: "system",
493
- content: "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text."
494
- };
495
757
  function openai(options) {
496
758
  return {
497
759
  name: `openai:${options.model}`,
@@ -500,18 +762,20 @@ function openai(options) {
500
762
  messages: request.messages,
501
763
  temperature: request.temperature ?? options.temperature,
502
764
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
503
- requireJsonObjectResponse: false,
504
765
  tools: request.tools,
505
766
  toolChoice: request.toolChoice,
506
- abortSignal: request.abortSignal
767
+ abortSignal: request.abortSignal,
768
+ extraBody: request.extraBody
507
769
  });
508
770
  },
509
771
  async generateStructuredOutput(request) {
510
772
  const completion = await executeOpenAiAdapterCall(options, {
511
- messages: [structuredOutputSystemMessage, ...request.messages],
773
+ messages: request.messages,
512
774
  temperature: request.temperature ?? options.temperature,
513
775
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
514
- requireJsonObjectResponse: true,
776
+ structuredOutputJsonSchema: buildOpenAiStructuredOutputJsonSchema(
777
+ request.schema
778
+ ),
515
779
  abortSignal: request.abortSignal
516
780
  });
517
781
  return {
@@ -545,7 +809,11 @@ async function requestOpenAiChatCompletion(options, input) {
545
809
  });
546
810
  const fetchImplementation = options.fetchImplementation ?? fetch;
547
811
  const baseUrl = options.baseURL ?? defaultOpenAiBaseUrl;
548
- const requestBody = buildOpenAiRequestBody(options.model, input);
812
+ const requestBody = mergeProviderRequestExtraBody(
813
+ buildOpenAiRequestBody(options.model, input),
814
+ options.extraBody,
815
+ input.extraBody
816
+ );
549
817
  const startedAt = Date.now();
550
818
  const response = await executeAbortableProviderFetch(
551
819
  "OpenAI",
@@ -600,10 +868,10 @@ function parseOpenAiToolArgumentsJson(argumentsJsonText) {
600
868
  return {};
601
869
  }
602
870
  try {
603
- return import_json3.JsonValueSchema.parse(JSON.parse(argumentsJsonText));
871
+ return import_json4.JsonValueSchema.parse(JSON.parse(argumentsJsonText));
604
872
  } catch (error) {
605
- throw new import_errors15.AppError({
606
- code: import_errors14.AppErrorCode.ValidationFailed,
873
+ throw new import_errors17.AppError({
874
+ code: import_errors16.AppErrorCode.ValidationFailed,
607
875
  message: "OpenAI tool call arguments were not valid JSON",
608
876
  statusCode: 502,
609
877
  cause: error instanceof Error ? error : void 0
@@ -625,8 +893,8 @@ function extractOpenAiMessageContent(response, allowEmptyContent) {
625
893
  if (allowEmptyContent) {
626
894
  return "";
627
895
  }
628
- throw new import_errors15.AppError({
629
- code: import_errors14.AppErrorCode.ValidationFailed,
896
+ throw new import_errors17.AppError({
897
+ code: import_errors16.AppErrorCode.ValidationFailed,
630
898
  message: "OpenAI response contained no message content",
631
899
  statusCode: 502
632
900
  });
@@ -641,6 +909,36 @@ function mapOpenAiUsageToTokenUsage(response) {
641
909
  };
642
910
  }
643
911
 
912
+ // src/anthropic-cache-control.ts
913
+ function resolveAnthropicPromptCachingSettings(promptCaching) {
914
+ if (promptCaching === void 0) {
915
+ return { mode: "off" };
916
+ }
917
+ if (typeof promptCaching === "string") {
918
+ return { mode: promptCaching };
919
+ }
920
+ return promptCaching;
921
+ }
922
+ function buildAnthropicCacheControl(ttl) {
923
+ if (ttl === void 0) {
924
+ return { type: "ephemeral" };
925
+ }
926
+ return { type: "ephemeral", ttl };
927
+ }
928
+ function applyCacheControlToLastContentBlock(requestMessage, cacheControl) {
929
+ if (typeof requestMessage.content === "string") {
930
+ if (requestMessage.content.length === 0) {
931
+ return;
932
+ }
933
+ requestMessage.content = [{ type: "text", text: requestMessage.content }];
934
+ }
935
+ const lastContentBlock = requestMessage.content[requestMessage.content.length - 1];
936
+ if (lastContentBlock === void 0) {
937
+ return;
938
+ }
939
+ lastContentBlock.cache_control = cacheControl;
940
+ }
941
+
644
942
  // src/anthropic-request-mapping.ts
645
943
  function buildAnthropicRequestBody(settings, input) {
646
944
  const requestBody = {
@@ -650,6 +948,7 @@ function buildAnthropicRequestBody(settings, input) {
650
948
  };
651
949
  applyAnthropicSystemField(requestBody, settings, input);
652
950
  applyAnthropicToolFields(requestBody, settings, input);
951
+ applyAnthropicMessageCacheBreakpoints(requestBody, settings, input);
653
952
  if (input.temperature !== void 0) {
654
953
  requestBody.temperature = input.temperature;
655
954
  }
@@ -659,21 +958,54 @@ function buildAnthropicRequestBody(settings, input) {
659
958
  budget_tokens: settings.thinking.budgetTokens
660
959
  };
661
960
  }
961
+ if (input.structuredOutputJsonSchema !== void 0) {
962
+ requestBody.output_config = {
963
+ format: { type: "json_schema", schema: input.structuredOutputJsonSchema }
964
+ };
965
+ }
662
966
  return requestBody;
663
967
  }
664
968
  function applyAnthropicSystemField(requestBody, settings, input) {
969
+ const caching = resolveAnthropicPromptCachingSettings(settings.promptCaching);
665
970
  const systemText = joinSystemMessageText(input.messages);
666
971
  if (systemText.length === 0) {
667
972
  return;
668
973
  }
669
- if (settings.promptCaching !== "auto") {
974
+ if (caching.mode === "off") {
670
975
  requestBody.system = systemText;
671
976
  return;
672
977
  }
673
978
  requestBody.system = [
674
- { type: "text", text: systemText, cache_control: { type: "ephemeral" } }
979
+ {
980
+ type: "text",
981
+ text: systemText,
982
+ cache_control: buildAnthropicCacheControl(caching.ttl)
983
+ }
675
984
  ];
676
985
  }
986
+ function applyAnthropicMessageCacheBreakpoints(requestBody, settings, input) {
987
+ const caching = resolveAnthropicPromptCachingSettings(settings.promptCaching);
988
+ const finalRequestMessage = requestBody.messages[requestBody.messages.length - 1];
989
+ if (caching.mode === "messages" && finalRequestMessage !== void 0) {
990
+ applyCacheControlToLastContentBlock(
991
+ finalRequestMessage,
992
+ buildAnthropicCacheControl(caching.ttl)
993
+ );
994
+ }
995
+ const nonSystemMessages = input.messages.filter(
996
+ (message) => message.role !== "system"
997
+ );
998
+ nonSystemMessages.forEach((message, messageIndex) => {
999
+ const requestMessage = requestBody.messages[messageIndex];
1000
+ if (message.cacheControl === void 0 || requestMessage === void 0) {
1001
+ return;
1002
+ }
1003
+ applyCacheControlToLastContentBlock(
1004
+ requestMessage,
1005
+ buildAnthropicCacheControl(message.cacheControl.ttl ?? caching.ttl)
1006
+ );
1007
+ });
1008
+ }
677
1009
  function applyAnthropicToolFields(requestBody, settings, input) {
678
1010
  if (input.tools !== void 0 && input.tools.length > 0) {
679
1011
  requestBody.tools = mapModelToolDefinitionsToAnthropicTools(
@@ -688,14 +1020,15 @@ function applyAnthropicToolFields(requestBody, settings, input) {
688
1020
  }
689
1021
  }
690
1022
  function mapModelToolDefinitionsToAnthropicTools(tools, promptCaching) {
1023
+ const caching = resolveAnthropicPromptCachingSettings(promptCaching);
691
1024
  return tools.map((tool, toolIndex) => {
692
1025
  const anthropicTool = {
693
1026
  name: tool.name,
694
1027
  description: tool.description,
695
1028
  input_schema: tool.inputJsonSchema
696
1029
  };
697
- if (promptCaching === "auto" && toolIndex === tools.length - 1) {
698
- anthropicTool.cache_control = { type: "ephemeral" };
1030
+ if (caching.mode !== "off" && toolIndex === tools.length - 1) {
1031
+ anthropicTool.cache_control = buildAnthropicCacheControl(caching.ttl);
699
1032
  }
700
1033
  return anthropicTool;
701
1034
  });
@@ -786,44 +1119,45 @@ function mapMessageContentBlockToAnthropic(contentBlock) {
786
1119
  }
787
1120
 
788
1121
  // src/anthropic-response-parsing.ts
789
- var import_zod4 = require("zod");
790
- var import_errors16 = require("@assemble-dev/shared-types/errors");
791
- var import_json4 = require("@assemble-dev/shared-types/json");
792
- var import_errors17 = require("@assemble-dev/shared-utils/errors");
793
- var AnthropicUsageSchema = import_zod4.z.object({
794
- input_tokens: import_zod4.z.number().int().nonnegative(),
795
- output_tokens: import_zod4.z.number().int().nonnegative(),
796
- cache_creation_input_tokens: import_zod4.z.number().int().nonnegative().optional(),
797
- cache_read_input_tokens: import_zod4.z.number().int().nonnegative().optional()
1122
+ var import_zod5 = require("zod");
1123
+ var import_errors18 = require("@assemble-dev/shared-types/errors");
1124
+ var import_json5 = require("@assemble-dev/shared-types/json");
1125
+ var import_errors19 = require("@assemble-dev/shared-utils/errors");
1126
+ var AnthropicUsageSchema = import_zod5.z.object({
1127
+ input_tokens: import_zod5.z.number().int().nonnegative(),
1128
+ output_tokens: import_zod5.z.number().int().nonnegative(),
1129
+ cache_creation_input_tokens: import_zod5.z.number().int().nonnegative().optional(),
1130
+ cache_read_input_tokens: import_zod5.z.number().int().nonnegative().optional()
798
1131
  });
799
- var AnthropicContentBlockSchema = import_zod4.z.discriminatedUnion("type", [
800
- import_zod4.z.object({
801
- type: import_zod4.z.literal("text"),
802
- text: import_zod4.z.string()
1132
+ var AnthropicContentBlockSchema = import_zod5.z.discriminatedUnion("type", [
1133
+ import_zod5.z.object({
1134
+ type: import_zod5.z.literal("text"),
1135
+ text: import_zod5.z.string()
803
1136
  }),
804
- import_zod4.z.object({
805
- type: import_zod4.z.literal("tool_use"),
806
- id: import_zod4.z.string(),
807
- name: import_zod4.z.string(),
808
- input: import_json4.JsonValueSchema
1137
+ import_zod5.z.object({
1138
+ type: import_zod5.z.literal("tool_use"),
1139
+ id: import_zod5.z.string(),
1140
+ name: import_zod5.z.string(),
1141
+ input: import_json5.JsonValueSchema
809
1142
  }),
810
- import_zod4.z.object({
811
- type: import_zod4.z.literal("thinking"),
812
- thinking: import_zod4.z.string().optional(),
813
- signature: import_zod4.z.string().optional()
1143
+ import_zod5.z.object({
1144
+ type: import_zod5.z.literal("thinking"),
1145
+ thinking: import_zod5.z.string().optional(),
1146
+ signature: import_zod5.z.string().optional()
814
1147
  }),
815
- import_zod4.z.object({
816
- type: import_zod4.z.literal("redacted_thinking"),
817
- data: import_zod4.z.string().optional()
1148
+ import_zod5.z.object({
1149
+ type: import_zod5.z.literal("redacted_thinking"),
1150
+ data: import_zod5.z.string().optional()
818
1151
  })
819
1152
  ]);
820
- var AnthropicMessagesResponseSchema = import_zod4.z.object({
821
- content: import_zod4.z.array(AnthropicContentBlockSchema),
822
- stop_reason: import_zod4.z.string().nullable().optional(),
1153
+ var AnthropicMessagesResponseSchema = import_zod5.z.object({
1154
+ content: import_zod5.z.array(AnthropicContentBlockSchema),
1155
+ stop_reason: import_zod5.z.string().nullable().optional(),
823
1156
  usage: AnthropicUsageSchema
824
1157
  });
825
1158
  function mapAnthropicResponseToChatCompletionResult(response, latencyMs) {
826
1159
  const toolCalls = extractAnthropicToolCalls(response);
1160
+ const thinkingText = extractAnthropicThinkingText(response);
827
1161
  const result = {
828
1162
  content: extractAnthropicTextContent(response, toolCalls.length > 0),
829
1163
  tokenUsage: mapAnthropicUsageToTokenUsage(response.usage),
@@ -832,6 +1166,9 @@ function mapAnthropicResponseToChatCompletionResult(response, latencyMs) {
832
1166
  if (toolCalls.length > 0) {
833
1167
  result.toolCalls = toolCalls;
834
1168
  }
1169
+ if (thinkingText.length > 0) {
1170
+ result.thinkingText = thinkingText;
1171
+ }
835
1172
  if (response.stop_reason !== null && response.stop_reason !== void 0) {
836
1173
  result.stopReason = normalizeAnthropicStopReason(response.stop_reason);
837
1174
  }
@@ -844,13 +1181,16 @@ function extractAnthropicToolCalls(response) {
844
1181
  input: contentBlock.input
845
1182
  }));
846
1183
  }
1184
+ function extractAnthropicThinkingText(response) {
1185
+ return response.content.filter((contentBlock) => contentBlock.type === "thinking").map((contentBlock) => contentBlock.thinking ?? "").join("");
1186
+ }
847
1187
  function extractAnthropicTextContent(response, allowEmptyText) {
848
1188
  const textBlocks = response.content.filter(
849
1189
  (contentBlock) => contentBlock.type === "text"
850
1190
  );
851
1191
  if (textBlocks.length === 0 && !allowEmptyText) {
852
- throw new import_errors17.AppError({
853
- code: import_errors16.AppErrorCode.ValidationFailed,
1192
+ throw new import_errors19.AppError({
1193
+ code: import_errors18.AppErrorCode.ValidationFailed,
854
1194
  message: "Anthropic response contained no text content",
855
1195
  statusCode: 502
856
1196
  });
@@ -887,58 +1227,68 @@ function mapAnthropicUsageToTokenUsage(usage) {
887
1227
  }
888
1228
 
889
1229
  // src/anthropic-stream.ts
890
- var import_errors18 = require("@assemble-dev/shared-types/errors");
891
- var import_json5 = require("@assemble-dev/shared-types/json");
892
- var import_errors19 = require("@assemble-dev/shared-utils/errors");
1230
+ var import_errors20 = require("@assemble-dev/shared-types/errors");
1231
+ var import_json6 = require("@assemble-dev/shared-types/json");
1232
+ var import_errors21 = require("@assemble-dev/shared-utils/errors");
893
1233
 
894
1234
  // src/anthropic-stream-events.ts
895
- var import_zod5 = require("zod");
896
- var AnthropicStreamEventSchema = import_zod5.z.discriminatedUnion("type", [
897
- import_zod5.z.object({
898
- type: import_zod5.z.literal("message_start"),
899
- message: import_zod5.z.object({
900
- usage: import_zod5.z.object({
901
- input_tokens: import_zod5.z.number().int().nonnegative(),
902
- output_tokens: import_zod5.z.number().int().nonnegative().optional(),
903
- cache_creation_input_tokens: import_zod5.z.number().int().nonnegative().optional(),
904
- cache_read_input_tokens: import_zod5.z.number().int().nonnegative().optional()
1235
+ var import_zod6 = require("zod");
1236
+ var AnthropicStreamEventSchema = import_zod6.z.discriminatedUnion("type", [
1237
+ import_zod6.z.object({
1238
+ type: import_zod6.z.literal("message_start"),
1239
+ message: import_zod6.z.object({
1240
+ usage: import_zod6.z.object({
1241
+ input_tokens: import_zod6.z.number().int().nonnegative(),
1242
+ output_tokens: import_zod6.z.number().int().nonnegative().optional(),
1243
+ cache_creation_input_tokens: import_zod6.z.number().int().nonnegative().optional(),
1244
+ cache_read_input_tokens: import_zod6.z.number().int().nonnegative().optional()
905
1245
  })
906
1246
  })
907
1247
  }),
908
- import_zod5.z.object({
909
- type: import_zod5.z.literal("content_block_start"),
910
- index: import_zod5.z.number().int().nonnegative(),
911
- content_block: import_zod5.z.discriminatedUnion("type", [
912
- import_zod5.z.object({ type: import_zod5.z.literal("text"), text: import_zod5.z.string().optional() }),
913
- import_zod5.z.object({
914
- type: import_zod5.z.literal("tool_use"),
915
- id: import_zod5.z.string(),
916
- name: import_zod5.z.string()
1248
+ import_zod6.z.object({
1249
+ type: import_zod6.z.literal("content_block_start"),
1250
+ index: import_zod6.z.number().int().nonnegative(),
1251
+ content_block: import_zod6.z.discriminatedUnion("type", [
1252
+ import_zod6.z.object({ type: import_zod6.z.literal("text"), text: import_zod6.z.string().optional() }),
1253
+ import_zod6.z.object({
1254
+ type: import_zod6.z.literal("thinking"),
1255
+ thinking: import_zod6.z.string().optional()
1256
+ }),
1257
+ import_zod6.z.object({
1258
+ type: import_zod6.z.literal("redacted_thinking"),
1259
+ data: import_zod6.z.string().optional()
1260
+ }),
1261
+ import_zod6.z.object({
1262
+ type: import_zod6.z.literal("tool_use"),
1263
+ id: import_zod6.z.string(),
1264
+ name: import_zod6.z.string()
917
1265
  })
918
1266
  ])
919
1267
  }),
920
- import_zod5.z.object({
921
- type: import_zod5.z.literal("content_block_delta"),
922
- index: import_zod5.z.number().int().nonnegative(),
923
- delta: import_zod5.z.discriminatedUnion("type", [
924
- import_zod5.z.object({ type: import_zod5.z.literal("text_delta"), text: import_zod5.z.string() }),
925
- import_zod5.z.object({
926
- type: import_zod5.z.literal("input_json_delta"),
927
- partial_json: import_zod5.z.string()
1268
+ import_zod6.z.object({
1269
+ type: import_zod6.z.literal("content_block_delta"),
1270
+ index: import_zod6.z.number().int().nonnegative(),
1271
+ delta: import_zod6.z.discriminatedUnion("type", [
1272
+ import_zod6.z.object({ type: import_zod6.z.literal("text_delta"), text: import_zod6.z.string() }),
1273
+ import_zod6.z.object({ type: import_zod6.z.literal("thinking_delta"), thinking: import_zod6.z.string() }),
1274
+ import_zod6.z.object({ type: import_zod6.z.literal("signature_delta"), signature: import_zod6.z.string() }),
1275
+ import_zod6.z.object({
1276
+ type: import_zod6.z.literal("input_json_delta"),
1277
+ partial_json: import_zod6.z.string()
928
1278
  })
929
1279
  ])
930
1280
  }),
931
- import_zod5.z.object({ type: import_zod5.z.literal("content_block_stop") }),
932
- import_zod5.z.object({
933
- type: import_zod5.z.literal("message_delta"),
934
- delta: import_zod5.z.object({ stop_reason: import_zod5.z.string().nullable().optional() }),
935
- usage: import_zod5.z.object({ output_tokens: import_zod5.z.number().int().nonnegative() }).optional()
1281
+ import_zod6.z.object({ type: import_zod6.z.literal("content_block_stop") }),
1282
+ import_zod6.z.object({
1283
+ type: import_zod6.z.literal("message_delta"),
1284
+ delta: import_zod6.z.object({ stop_reason: import_zod6.z.string().nullable().optional() }),
1285
+ usage: import_zod6.z.object({ output_tokens: import_zod6.z.number().int().nonnegative() }).optional()
936
1286
  }),
937
- import_zod5.z.object({ type: import_zod5.z.literal("message_stop") }),
938
- import_zod5.z.object({ type: import_zod5.z.literal("ping") }),
939
- import_zod5.z.object({
940
- type: import_zod5.z.literal("error"),
941
- error: import_zod5.z.object({ message: import_zod5.z.string() })
1287
+ import_zod6.z.object({ type: import_zod6.z.literal("message_stop") }),
1288
+ import_zod6.z.object({ type: import_zod6.z.literal("ping") }),
1289
+ import_zod6.z.object({
1290
+ type: import_zod6.z.literal("error"),
1291
+ error: import_zod6.z.object({ message: import_zod6.z.string() })
942
1292
  })
943
1293
  ]);
944
1294
 
@@ -1024,6 +1374,7 @@ async function* readServerSentEventDataLines(body, abortSignal) {
1024
1374
  function createAnthropicStreamAccumulator() {
1025
1375
  return {
1026
1376
  contentText: "",
1377
+ thinkingText: "",
1027
1378
  toolCallsByBlockIndex: /* @__PURE__ */ new Map(),
1028
1379
  inputTokens: 0,
1029
1380
  outputTokens: 0
@@ -1031,8 +1382,8 @@ function createAnthropicStreamAccumulator() {
1031
1382
  }
1032
1383
  function* applyAnthropicStreamEvent(event, accumulator) {
1033
1384
  if (event.type === "error") {
1034
- throw new import_errors19.AppError({
1035
- code: import_errors18.AppErrorCode.InternalServerError,
1385
+ throw new import_errors21.AppError({
1386
+ code: import_errors20.AppErrorCode.InternalServerError,
1036
1387
  message: `Anthropic stream reported an error: ${event.error.message}`,
1037
1388
  statusCode: 502
1038
1389
  });
@@ -1068,6 +1419,17 @@ function* applyAnthropicContentBlockStart(event, accumulator) {
1068
1419
  }
1069
1420
  return;
1070
1421
  }
1422
+ if (event.content_block.type === "thinking") {
1423
+ const initialThinkingText = event.content_block.thinking ?? "";
1424
+ if (initialThinkingText.length > 0) {
1425
+ accumulator.thinkingText += initialThinkingText;
1426
+ yield { type: "thinking_delta", text: initialThinkingText };
1427
+ }
1428
+ return;
1429
+ }
1430
+ if (event.content_block.type === "redacted_thinking") {
1431
+ return;
1432
+ }
1071
1433
  accumulator.toolCallsByBlockIndex.set(event.index, {
1072
1434
  id: event.content_block.id,
1073
1435
  toolName: event.content_block.name,
@@ -1085,6 +1447,14 @@ function* applyAnthropicContentBlockDelta(event, accumulator) {
1085
1447
  yield { type: "text_delta", text: event.delta.text };
1086
1448
  return;
1087
1449
  }
1450
+ if (event.delta.type === "thinking_delta") {
1451
+ accumulator.thinkingText += event.delta.thinking;
1452
+ yield { type: "thinking_delta", text: event.delta.thinking };
1453
+ return;
1454
+ }
1455
+ if (event.delta.type === "signature_delta") {
1456
+ return;
1457
+ }
1088
1458
  const toolCallAccumulation = accumulator.toolCallsByBlockIndex.get(
1089
1459
  event.index
1090
1460
  );
@@ -1131,6 +1501,9 @@ function buildAnthropicStreamResult(accumulator, latencyMs) {
1131
1501
  if (accumulator.stopReason !== void 0) {
1132
1502
  result.stopReason = accumulator.stopReason;
1133
1503
  }
1504
+ if (accumulator.thinkingText.length > 0) {
1505
+ result.thinkingText = accumulator.thinkingText;
1506
+ }
1134
1507
  return result;
1135
1508
  }
1136
1509
  function mapAccumulatedToolCallToModelToolCall(toolCallAccumulation) {
@@ -1145,10 +1518,10 @@ function parseAnthropicToolInputJson(inputJsonText) {
1145
1518
  return {};
1146
1519
  }
1147
1520
  try {
1148
- return import_json5.JsonValueSchema.parse(JSON.parse(inputJsonText));
1521
+ return import_json6.JsonValueSchema.parse(JSON.parse(inputJsonText));
1149
1522
  } catch (error) {
1150
- throw new import_errors19.AppError({
1151
- code: import_errors18.AppErrorCode.ValidationFailed,
1523
+ throw new import_errors21.AppError({
1524
+ code: import_errors20.AppErrorCode.ValidationFailed,
1152
1525
  message: "Anthropic tool input was not valid JSON",
1153
1526
  statusCode: 502,
1154
1527
  cause: error instanceof Error ? error : void 0
@@ -1160,10 +1533,6 @@ function parseAnthropicToolInputJson(inputJsonText) {
1160
1533
  var defaultAnthropicBaseUrl = "https://api.anthropic.com";
1161
1534
  var defaultAnthropicMaxOutputTokens = 1024;
1162
1535
  var anthropicApiVersion = "2023-06-01";
1163
- var structuredOutputSystemMessage2 = {
1164
- role: "system",
1165
- content: "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text."
1166
- };
1167
1536
  function anthropic(options) {
1168
1537
  return {
1169
1538
  name: `anthropic:${options.model}`,
@@ -1175,9 +1544,12 @@ function anthropic(options) {
1175
1544
  },
1176
1545
  async generateStructuredOutput(request) {
1177
1546
  const completion = await executeAnthropicAdapterCall(options, {
1178
- messages: [structuredOutputSystemMessage2, ...request.messages],
1547
+ messages: request.messages,
1179
1548
  temperature: request.temperature ?? options.temperature,
1180
1549
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1550
+ structuredOutputJsonSchema: buildAnthropicStructuredOutputJsonSchema(
1551
+ request.schema
1552
+ ),
1181
1553
  abortSignal: request.abortSignal
1182
1554
  });
1183
1555
  return {
@@ -1200,7 +1572,8 @@ function buildAnthropicCallInput(options, request) {
1200
1572
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1201
1573
  tools: request.tools,
1202
1574
  toolChoice: request.toolChoice,
1203
- abortSignal: request.abortSignal
1575
+ abortSignal: request.abortSignal,
1576
+ extraBody: request.extraBody
1204
1577
  };
1205
1578
  }
1206
1579
  async function executeAnthropicAdapterCall(options, input) {
@@ -1217,9 +1590,10 @@ async function executeAnthropicAdapterCall(options, input) {
1217
1590
  );
1218
1591
  }
1219
1592
  async function requestAnthropicMessages(options, input) {
1220
- const requestBody = buildAnthropicRequestBody(
1221
- buildAnthropicRequestSettings(options),
1222
- input
1593
+ const requestBody = mergeProviderRequestExtraBody(
1594
+ buildAnthropicRequestBody(buildAnthropicRequestSettings(options), input),
1595
+ options.extraBody,
1596
+ input.extraBody
1223
1597
  );
1224
1598
  const startedAt = Date.now();
1225
1599
  const response = await executeAbortableProviderFetch(
@@ -1248,9 +1622,10 @@ async function requestAnthropicMessages(options, input) {
1248
1622
  }
1249
1623
  function buildAnthropicStreamInput(options, request) {
1250
1624
  const input = buildAnthropicCallInput(options, request);
1251
- const requestBody = buildAnthropicRequestBody(
1252
- buildAnthropicRequestSettings(options),
1253
- input
1625
+ const requestBody = mergeProviderRequestExtraBody(
1626
+ buildAnthropicRequestBody(buildAnthropicRequestSettings(options), input),
1627
+ options.extraBody,
1628
+ input.extraBody
1254
1629
  );
1255
1630
  return {
1256
1631
  url: `${resolveAnthropicBaseUrl(options)}/v1/messages`,
@@ -1290,28 +1665,116 @@ function resolveAnthropicFetch(options) {
1290
1665
  }
1291
1666
 
1292
1667
  // src/gemini-adapter.ts
1293
- var import_zod6 = require("zod");
1294
- var import_errors20 = require("@assemble-dev/shared-types/errors");
1295
- var import_errors21 = require("@assemble-dev/shared-utils/errors");
1668
+ var import_zod7 = require("zod");
1669
+ var import_errors22 = require("@assemble-dev/shared-types/errors");
1670
+ var import_errors23 = require("@assemble-dev/shared-utils/errors");
1671
+
1672
+ // src/gemini-response-schema.ts
1673
+ var geminiAllowedSchemaKeywords = [
1674
+ "type",
1675
+ "format",
1676
+ "description",
1677
+ "nullable",
1678
+ "enum",
1679
+ "properties",
1680
+ "required",
1681
+ "items",
1682
+ "minItems",
1683
+ "maxItems",
1684
+ "anyOf"
1685
+ ];
1686
+ var geminiAllowedFormats = [
1687
+ "date-time",
1688
+ "int32",
1689
+ "int64",
1690
+ "float",
1691
+ "double"
1692
+ ];
1693
+ function buildGeminiResponseSchema(schema) {
1694
+ return sanitizeJsonSchemaForGeminiResponseSchema(
1695
+ convertZodSchemaToJsonSchema(schema)
1696
+ );
1697
+ }
1698
+ function sanitizeJsonSchemaForGeminiResponseSchema(jsonSchema) {
1699
+ return transformJsonSchemaNode(
1700
+ inlineJsonSchemaReferences(jsonSchema),
1701
+ sanitizeGeminiSchemaNode
1702
+ );
1703
+ }
1704
+ function sanitizeGeminiSchemaNode(node) {
1705
+ const normalized = normalizeGeminiNullableType(
1706
+ mergeNullUnionIntoNullableNode(node)
1707
+ );
1708
+ const sanitized = {};
1709
+ for (const [key, value] of Object.entries(normalized)) {
1710
+ if (geminiAllowedSchemaKeywords.includes(key)) {
1711
+ sanitized[key] = value;
1712
+ }
1713
+ }
1714
+ return removeUnsupportedGeminiFormat(sanitized);
1715
+ }
1716
+ function mergeNullUnionIntoNullableNode(node) {
1717
+ const unionKeyword = Array.isArray(node["anyOf"]) ? "anyOf" : "oneOf";
1718
+ const unionMembers = node[unionKeyword];
1719
+ if (!Array.isArray(unionMembers)) {
1720
+ return node;
1721
+ }
1722
+ const nonNullMembers = unionMembers.filter(
1723
+ (member) => !isNullTypeSchemaNode(member)
1724
+ );
1725
+ if (nonNullMembers.length === unionMembers.length) {
1726
+ return node;
1727
+ }
1728
+ const merged = { ...node };
1729
+ delete merged[unionKeyword];
1730
+ const singleMember = nonNullMembers.length === 1 ? nonNullMembers[0] : void 0;
1731
+ if (singleMember !== void 0 && isJsonObject(singleMember)) {
1732
+ return { ...merged, ...singleMember, nullable: true };
1733
+ }
1734
+ return { ...merged, anyOf: nonNullMembers, nullable: true };
1735
+ }
1736
+ function normalizeGeminiNullableType(node) {
1737
+ const typeValue = node["type"];
1738
+ if (!Array.isArray(typeValue)) {
1739
+ return node;
1740
+ }
1741
+ const nonNullTypes = typeValue.filter((typeName) => typeName !== "null");
1742
+ const normalized = { ...node };
1743
+ if (nonNullTypes.length < typeValue.length) {
1744
+ normalized["nullable"] = true;
1745
+ }
1746
+ normalized["type"] = nonNullTypes[0] ?? "string";
1747
+ return normalized;
1748
+ }
1749
+ function removeUnsupportedGeminiFormat(node) {
1750
+ const formatValue = node["format"];
1751
+ if (typeof formatValue === "string" && !geminiAllowedFormats.includes(formatValue)) {
1752
+ const withoutFormat = { ...node };
1753
+ delete withoutFormat["format"];
1754
+ return withoutFormat;
1755
+ }
1756
+ return node;
1757
+ }
1758
+ function isNullTypeSchemaNode(value) {
1759
+ return isJsonObject(value) && value["type"] === "null";
1760
+ }
1761
+
1762
+ // src/gemini-adapter.ts
1296
1763
  var defaultGeminiBaseUrl = "https://generativelanguage.googleapis.com";
1297
- var GeminiGenerateContentResponseSchema = import_zod6.z.object({
1298
- candidates: import_zod6.z.array(
1299
- import_zod6.z.object({
1300
- content: import_zod6.z.object({
1301
- parts: import_zod6.z.array(import_zod6.z.object({ text: import_zod6.z.string() }))
1764
+ var GeminiGenerateContentResponseSchema = import_zod7.z.object({
1765
+ candidates: import_zod7.z.array(
1766
+ import_zod7.z.object({
1767
+ content: import_zod7.z.object({
1768
+ parts: import_zod7.z.array(import_zod7.z.object({ text: import_zod7.z.string() }))
1302
1769
  })
1303
1770
  })
1304
1771
  ).optional(),
1305
- usageMetadata: import_zod6.z.object({
1306
- promptTokenCount: import_zod6.z.number().int().nonnegative().optional(),
1307
- candidatesTokenCount: import_zod6.z.number().int().nonnegative().optional(),
1308
- totalTokenCount: import_zod6.z.number().int().nonnegative().optional()
1772
+ usageMetadata: import_zod7.z.object({
1773
+ promptTokenCount: import_zod7.z.number().int().nonnegative().optional(),
1774
+ candidatesTokenCount: import_zod7.z.number().int().nonnegative().optional(),
1775
+ totalTokenCount: import_zod7.z.number().int().nonnegative().optional()
1309
1776
  }).optional()
1310
1777
  });
1311
- var structuredOutputSystemMessage3 = {
1312
- role: "system",
1313
- content: "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text."
1314
- };
1315
1778
  function gemini(options) {
1316
1779
  return {
1317
1780
  name: `gemini:${options.model}`,
@@ -1321,16 +1784,16 @@ function gemini(options) {
1321
1784
  messages: request.messages,
1322
1785
  temperature: request.temperature ?? options.temperature,
1323
1786
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1324
- requireJsonResponse: false,
1325
- abortSignal: request.abortSignal
1787
+ abortSignal: request.abortSignal,
1788
+ extraBody: request.extraBody
1326
1789
  });
1327
1790
  },
1328
1791
  async generateStructuredOutput(request) {
1329
1792
  const completion = await executeGeminiAdapterCall(options, {
1330
- messages: [structuredOutputSystemMessage3, ...request.messages],
1793
+ messages: request.messages,
1331
1794
  temperature: request.temperature ?? options.temperature,
1332
1795
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1333
- requireJsonResponse: true,
1796
+ responseSchema: buildGeminiResponseSchema(request.schema),
1334
1797
  abortSignal: request.abortSignal
1335
1798
  });
1336
1799
  return {
@@ -1364,7 +1827,11 @@ async function requestGeminiGenerateContent(options, input) {
1364
1827
  });
1365
1828
  const fetchImplementation = options.fetchImplementation ?? fetch;
1366
1829
  const baseUrl = options.baseURL ?? defaultGeminiBaseUrl;
1367
- const requestBody = buildGeminiRequestBody(input);
1830
+ const requestBody = mergeProviderRequestExtraBody(
1831
+ buildGeminiRequestBody(input),
1832
+ options.extraBody,
1833
+ input.extraBody
1834
+ );
1368
1835
  const requestUrl = `${baseUrl}/v1beta/models/${options.model}:generateContent`;
1369
1836
  const startedAt = Date.now();
1370
1837
  const response = await executeAbortableProviderFetch(
@@ -1413,8 +1880,8 @@ function ensureGeminiRequestHasNoTools(request) {
1413
1880
  if (request.tools === void 0 || request.tools.length === 0) {
1414
1881
  return;
1415
1882
  }
1416
- throw new import_errors21.AppError({
1417
- code: import_errors20.AppErrorCode.ValidationFailed,
1883
+ throw new import_errors23.AppError({
1884
+ code: import_errors22.AppErrorCode.ValidationFailed,
1418
1885
  message: "gemini adapter does not support model-driven tool use; remove tools from the request or use another adapter",
1419
1886
  statusCode: 400
1420
1887
  });
@@ -1451,8 +1918,9 @@ function buildGeminiGenerationConfig(input) {
1451
1918
  if (input.maxOutputTokens !== void 0) {
1452
1919
  generationConfig.maxOutputTokens = input.maxOutputTokens;
1453
1920
  }
1454
- if (input.requireJsonResponse) {
1921
+ if (input.responseSchema !== void 0) {
1455
1922
  generationConfig.responseMimeType = "application/json";
1923
+ generationConfig.responseSchema = input.responseSchema;
1456
1924
  }
1457
1925
  if (Object.keys(generationConfig).length === 0) {
1458
1926
  return void 0;
@@ -1462,8 +1930,8 @@ function buildGeminiGenerationConfig(input) {
1462
1930
  function extractGeminiCandidateText(response) {
1463
1931
  const firstCandidate = response.candidates?.[0];
1464
1932
  if (firstCandidate === void 0) {
1465
- throw new import_errors21.AppError({
1466
- code: import_errors20.AppErrorCode.ValidationFailed,
1933
+ throw new import_errors23.AppError({
1934
+ code: import_errors22.AppErrorCode.ValidationFailed,
1467
1935
  message: "Gemini response contained no candidates",
1468
1936
  statusCode: 502
1469
1937
  });
@@ -1482,8 +1950,8 @@ function mapGeminiUsageToTokenUsage(response) {
1482
1950
  }
1483
1951
 
1484
1952
  // src/mock-adapter.ts
1485
- var import_errors22 = require("@assemble-dev/shared-types/errors");
1486
- var import_errors23 = require("@assemble-dev/shared-utils/errors");
1953
+ var import_errors24 = require("@assemble-dev/shared-types/errors");
1954
+ var import_errors25 = require("@assemble-dev/shared-utils/errors");
1487
1955
  var mockStreamChunkCount = 3;
1488
1956
  function mockModel(options = {}) {
1489
1957
  const remainingScriptedResponses = [...options.scriptedResponses ?? []];
@@ -1563,8 +2031,8 @@ function resolveNextMockResponseText(request, remainingScriptedResponses, respon
1563
2031
  if (respond !== void 0) {
1564
2032
  return respond(request);
1565
2033
  }
1566
- throw new import_errors23.AppError({
1567
- code: import_errors22.AppErrorCode.BadRequest,
2034
+ throw new import_errors25.AppError({
2035
+ code: import_errors24.AppErrorCode.BadRequest,
1568
2036
  message: "Mock model has no scripted responses left and no respond function was provided",
1569
2037
  statusCode: 400
1570
2038
  });
@@ -1652,60 +2120,274 @@ function calculateModelCallCostUsd(pricing, tokenUsage) {
1652
2120
  }
1653
2121
 
1654
2122
  // src/anthropic-batch.ts
1655
- var import_errors24 = require("@assemble-dev/shared-types/errors");
1656
- var import_json6 = require("@assemble-dev/shared-types/json");
1657
- var import_errors25 = require("@assemble-dev/shared-utils/errors");
2123
+ var import_errors28 = require("@assemble-dev/shared-types/errors");
2124
+ var import_json8 = require("@assemble-dev/shared-types/json");
2125
+ var import_errors29 = require("@assemble-dev/shared-utils/errors");
1658
2126
 
1659
- // src/anthropic-batch-types.ts
1660
- var import_zod7 = require("zod");
1661
- var AnthropicMessageBatchResponseSchema = import_zod7.z.object({
1662
- id: import_zod7.z.string(),
1663
- processing_status: import_zod7.z.enum(["in_progress", "canceling", "ended"]),
1664
- request_counts: import_zod7.z.object({
1665
- processing: import_zod7.z.number().int().nonnegative(),
1666
- succeeded: import_zod7.z.number().int().nonnegative(),
1667
- errored: import_zod7.z.number().int().nonnegative(),
1668
- canceled: import_zod7.z.number().int().nonnegative(),
1669
- expired: import_zod7.z.number().int().nonnegative()
1670
- }),
1671
- results_url: import_zod7.z.string().nullable(),
1672
- created_at: import_zod7.z.string(),
1673
- ended_at: import_zod7.z.string().nullable()
1674
- });
1675
- var AnthropicBatchContentBlockSchema = import_zod7.z.discriminatedUnion("type", [
1676
- import_zod7.z.object({
1677
- type: import_zod7.z.literal("text"),
1678
- text: import_zod7.z.string()
1679
- }),
1680
- import_zod7.z.object({
1681
- type: import_zod7.z.literal("thinking"),
1682
- thinking: import_zod7.z.string().optional(),
1683
- signature: import_zod7.z.string().optional()
1684
- }),
1685
- import_zod7.z.object({
1686
- type: import_zod7.z.literal("redacted_thinking"),
1687
- data: import_zod7.z.string().optional()
1688
- })
1689
- ]);
1690
- var AnthropicBatchResultLineSchema = import_zod7.z.object({
1691
- custom_id: import_zod7.z.string(),
1692
- result: import_zod7.z.discriminatedUnion("type", [
1693
- import_zod7.z.object({
1694
- type: import_zod7.z.literal("succeeded"),
1695
- message: import_zod7.z.object({
1696
- content: import_zod7.z.array(AnthropicBatchContentBlockSchema),
1697
- usage: AnthropicUsageSchema
1698
- })
1699
- }),
1700
- import_zod7.z.object({
1701
- type: import_zod7.z.literal("errored"),
1702
- error: import_zod7.z.object({
1703
- type: import_zod7.z.string(),
1704
- message: import_zod7.z.string()
1705
- })
2127
+ // src/anthropic-batch-structured.ts
2128
+ var import_errors26 = require("@assemble-dev/shared-types/errors");
2129
+ var import_json7 = require("@assemble-dev/shared-types/json");
2130
+ var import_errors27 = require("@assemble-dev/shared-utils/errors");
2131
+ var anthropicBatchJsonOnlySystemInstruction = "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text.";
2132
+ function parseAnthropicBatchStructuredContent(content, schema) {
2133
+ const jsonValue = parseStructuredJsonText(
2134
+ content,
2135
+ import_json7.JsonValueSchema
2136
+ );
2137
+ const validationResult = schema.safeParse(jsonValue);
2138
+ if (!validationResult.success) {
2139
+ throw new import_errors27.AppError({
2140
+ code: import_errors26.AppErrorCode.ValidationFailed,
2141
+ message: "Anthropic batch structured output did not match the expected schema",
2142
+ statusCode: 422,
2143
+ details: { validationErrorMessage: validationResult.error.message }
2144
+ });
2145
+ }
2146
+ return validationResult.data;
2147
+ }
2148
+
2149
+ // src/anthropic-batch-request.ts
2150
+ function mapBatchMessageRequestToApiBatchRequest(request) {
2151
+ const params = {
2152
+ model: request.model,
2153
+ max_tokens: request.maxOutputTokens ?? defaultAnthropicMaxOutputTokens,
2154
+ messages: request.messages.filter((message) => message.role !== "system").map(mapChatMessageToBatchApiRequestMessage)
2155
+ };
2156
+ applyBatchSystemField(params, request);
2157
+ applyBatchStructuredOutputConfig(params, request);
2158
+ if (request.temperature !== void 0) {
2159
+ params.temperature = request.temperature;
2160
+ }
2161
+ return { custom_id: request.customId, params };
2162
+ }
2163
+ function applyBatchStructuredOutputConfig(params, request) {
2164
+ if (request.structuredOutputJsonSchema === void 0) {
2165
+ return;
2166
+ }
2167
+ params.output_config = {
2168
+ format: {
2169
+ type: "json_schema",
2170
+ schema: sanitizeJsonSchemaForAnthropicStructuredOutput(
2171
+ request.structuredOutputJsonSchema
2172
+ )
2173
+ }
2174
+ };
2175
+ }
2176
+ function applyBatchSystemField(params, request) {
2177
+ const systemText = buildBatchSystemText(request);
2178
+ if (systemText.length === 0) {
2179
+ return;
2180
+ }
2181
+ if (request.promptCaching !== "auto") {
2182
+ params.system = systemText;
2183
+ return;
2184
+ }
2185
+ params.system = [
2186
+ { type: "text", text: systemText, cache_control: { type: "ephemeral" } }
2187
+ ];
2188
+ }
2189
+ function buildBatchSystemText(request) {
2190
+ const joinedSystemText = joinBatchSystemMessageText(request.messages);
2191
+ if (request.requireJsonResponse !== true || request.structuredOutputJsonSchema !== void 0) {
2192
+ return joinedSystemText;
2193
+ }
2194
+ if (joinedSystemText.length === 0) {
2195
+ return anthropicBatchJsonOnlySystemInstruction;
2196
+ }
2197
+ return `${anthropicBatchJsonOnlySystemInstruction}
2198
+
2199
+ ${joinedSystemText}`;
2200
+ }
2201
+ function joinBatchSystemMessageText(messages) {
2202
+ return messages.filter((message) => message.role === "system").map(extractMessageText).join("\n\n");
2203
+ }
2204
+ function mapChatMessageToBatchApiRequestMessage(message) {
2205
+ if (message.role === "assistant") {
2206
+ return { role: "assistant", content: extractMessageText(message) };
2207
+ }
2208
+ if (message.role === "tool") {
2209
+ return { role: "user", content: buildBatchToolResultText(message) };
2210
+ }
2211
+ return { role: "user", content: extractMessageText(message) };
2212
+ }
2213
+ function buildBatchToolResultText(message) {
2214
+ if (message.toolName === void 0) {
2215
+ return `Tool result: ${extractMessageText(message)}`;
2216
+ }
2217
+ return `Tool result (${message.toolName}): ${extractMessageText(message)}`;
2218
+ }
2219
+
2220
+ // src/anthropic-batch-trace-events.ts
2221
+ var import_ids = require("@assemble-dev/shared-utils/ids");
2222
+ var anthropicBatchTraceWorkflowName = "anthropic-message-batch";
2223
+ function createAnthropicBatchTraceEmitter(input) {
2224
+ if (input.onTraceEvent === void 0) {
2225
+ return createNoopAnthropicBatchTraceEmitter();
2226
+ }
2227
+ const onTraceEvent = input.onTraceEvent;
2228
+ const runId = (0, import_ids.generateRunId)();
2229
+ const completedBatchIds = /* @__PURE__ */ new Set();
2230
+ const submittedEventIdByBatchId = /* @__PURE__ */ new Map();
2231
+ const modelByBatchScopedCustomId = /* @__PURE__ */ new Map();
2232
+ function buildBatchTraceEventBase(parentEventId) {
2233
+ return {
2234
+ id: (0, import_ids.generateTraceEventId)(),
2235
+ runId,
2236
+ workflowName: anthropicBatchTraceWorkflowName,
2237
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2238
+ parentEventId,
2239
+ redacted: false
2240
+ };
2241
+ }
2242
+ function stampMetadataOntoEvent(event) {
2243
+ if (input.metadata === void 0) {
2244
+ return event;
2245
+ }
2246
+ return { ...event, metadata: input.metadata };
2247
+ }
2248
+ function emitBatchSubmittedEvent(batch, requestSummaries) {
2249
+ const submittedEvent = {
2250
+ ...buildBatchTraceEventBase(null),
2251
+ type: "batch.submitted",
2252
+ batchId: batch.id,
2253
+ requestCount: requestSummaries.length,
2254
+ models: requestSummaries.map((requestSummary) => requestSummary.model)
2255
+ };
2256
+ submittedEventIdByBatchId.set(batch.id, submittedEvent.id);
2257
+ for (const requestSummary of requestSummaries) {
2258
+ modelByBatchScopedCustomId.set(
2259
+ buildBatchScopedCustomIdKey(batch.id, requestSummary.customId),
2260
+ requestSummary.model
2261
+ );
2262
+ }
2263
+ onTraceEvent(stampMetadataOntoEvent(submittedEvent));
2264
+ }
2265
+ function emitBatchCompletedEventOnce(batch) {
2266
+ if (batch.processingStatus !== "ended" || completedBatchIds.has(batch.id)) {
2267
+ return;
2268
+ }
2269
+ completedBatchIds.add(batch.id);
2270
+ const completedEvent = {
2271
+ ...buildBatchTraceEventBase(
2272
+ submittedEventIdByBatchId.get(batch.id) ?? null
2273
+ ),
2274
+ type: "batch.completed",
2275
+ batchId: batch.id,
2276
+ requestCounts: batch.requestCounts,
2277
+ latencyMs: calculateBatchLatencyMs(batch)
2278
+ };
2279
+ onTraceEvent(stampMetadataOntoEvent(completedEvent));
2280
+ }
2281
+ function emitBatchResultEvent(batchId, result) {
2282
+ const resultEvent = buildBatchResultEvent(
2283
+ buildBatchTraceEventBase(submittedEventIdByBatchId.get(batchId) ?? null),
2284
+ batchId,
2285
+ result,
2286
+ modelByBatchScopedCustomId.get(
2287
+ buildBatchScopedCustomIdKey(batchId, result.customId)
2288
+ )
2289
+ );
2290
+ onTraceEvent(stampMetadataOntoEvent(resultEvent));
2291
+ }
2292
+ return {
2293
+ emitBatchSubmittedEvent,
2294
+ emitBatchCompletedEventOnce,
2295
+ emitBatchResultEvent
2296
+ };
2297
+ }
2298
+ function createNoopAnthropicBatchTraceEmitter() {
2299
+ return {
2300
+ emitBatchSubmittedEvent() {
2301
+ },
2302
+ emitBatchCompletedEventOnce() {
2303
+ },
2304
+ emitBatchResultEvent() {
2305
+ }
2306
+ };
2307
+ }
2308
+ function buildBatchScopedCustomIdKey(batchId, customId) {
2309
+ return `${batchId}:${customId}`;
2310
+ }
2311
+ function calculateBatchLatencyMs(batch) {
2312
+ const createdAtMs = Date.parse(batch.createdAt);
2313
+ const endedAtMs = batch.endedAt === null ? Date.now() : Date.parse(batch.endedAt);
2314
+ if (Number.isNaN(createdAtMs) || Number.isNaN(endedAtMs)) {
2315
+ return 0;
2316
+ }
2317
+ return Math.max(0, endedAtMs - createdAtMs);
2318
+ }
2319
+ function buildBatchResultEvent(eventBase, batchId, result, modelName) {
2320
+ if (result.outcome.type !== "succeeded") {
2321
+ return {
2322
+ ...eventBase,
2323
+ type: "batch.result",
2324
+ batchId,
2325
+ customId: result.customId,
2326
+ outcomeType: result.outcome.type,
2327
+ costUsd: null
2328
+ };
2329
+ }
2330
+ return {
2331
+ ...eventBase,
2332
+ type: "batch.result",
2333
+ batchId,
2334
+ customId: result.customId,
2335
+ outcomeType: "succeeded",
2336
+ tokenUsage: result.outcome.tokenUsage,
2337
+ costUsd: modelName === void 0 ? null : estimateModelCallCostUsd(modelName, result.outcome.tokenUsage)
2338
+ };
2339
+ }
2340
+
2341
+ // src/anthropic-batch-types.ts
2342
+ var import_zod8 = require("zod");
2343
+ var AnthropicMessageBatchResponseSchema = import_zod8.z.object({
2344
+ id: import_zod8.z.string(),
2345
+ processing_status: import_zod8.z.enum(["in_progress", "canceling", "ended"]),
2346
+ request_counts: import_zod8.z.object({
2347
+ processing: import_zod8.z.number().int().nonnegative(),
2348
+ succeeded: import_zod8.z.number().int().nonnegative(),
2349
+ errored: import_zod8.z.number().int().nonnegative(),
2350
+ canceled: import_zod8.z.number().int().nonnegative(),
2351
+ expired: import_zod8.z.number().int().nonnegative()
2352
+ }),
2353
+ results_url: import_zod8.z.string().nullable(),
2354
+ created_at: import_zod8.z.string(),
2355
+ ended_at: import_zod8.z.string().nullable()
2356
+ });
2357
+ var AnthropicBatchContentBlockSchema = import_zod8.z.discriminatedUnion("type", [
2358
+ import_zod8.z.object({
2359
+ type: import_zod8.z.literal("text"),
2360
+ text: import_zod8.z.string()
2361
+ }),
2362
+ import_zod8.z.object({
2363
+ type: import_zod8.z.literal("thinking"),
2364
+ thinking: import_zod8.z.string().optional(),
2365
+ signature: import_zod8.z.string().optional()
2366
+ }),
2367
+ import_zod8.z.object({
2368
+ type: import_zod8.z.literal("redacted_thinking"),
2369
+ data: import_zod8.z.string().optional()
2370
+ })
2371
+ ]);
2372
+ var AnthropicBatchResultLineSchema = import_zod8.z.object({
2373
+ custom_id: import_zod8.z.string(),
2374
+ result: import_zod8.z.discriminatedUnion("type", [
2375
+ import_zod8.z.object({
2376
+ type: import_zod8.z.literal("succeeded"),
2377
+ message: import_zod8.z.object({
2378
+ content: import_zod8.z.array(AnthropicBatchContentBlockSchema),
2379
+ usage: AnthropicUsageSchema
2380
+ })
1706
2381
  }),
1707
- import_zod7.z.object({ type: import_zod7.z.literal("canceled") }),
1708
- import_zod7.z.object({ type: import_zod7.z.literal("expired") })
2382
+ import_zod8.z.object({
2383
+ type: import_zod8.z.literal("errored"),
2384
+ error: import_zod8.z.object({
2385
+ type: import_zod8.z.string(),
2386
+ message: import_zod8.z.string()
2387
+ })
2388
+ }),
2389
+ import_zod8.z.object({ type: import_zod8.z.literal("canceled") }),
2390
+ import_zod8.z.object({ type: import_zod8.z.literal("expired") })
1709
2391
  ])
1710
2392
  });
1711
2393
  function mapAnthropicMessageBatchResponseToMessageBatch(response) {
@@ -1759,19 +2441,26 @@ var defaultAnthropicBatchPollIntervalMs = 5e3;
1759
2441
  var defaultAnthropicBatchTimeoutMs = 36e5;
1760
2442
  var anthropicBatchApiVersion = "2023-06-01";
1761
2443
  function createAnthropicBatchClient(options) {
2444
+ const clientContext = {
2445
+ options,
2446
+ traceEmitter: createAnthropicBatchTraceEmitter({
2447
+ onTraceEvent: options.onTraceEvent,
2448
+ metadata: options.metadata
2449
+ })
2450
+ };
1762
2451
  return {
1763
2452
  async submitMessageBatch(requests) {
1764
- return await submitAnthropicMessageBatch(options, requests);
2453
+ return await submitAnthropicMessageBatch(clientContext, requests);
1765
2454
  },
1766
2455
  async fetchMessageBatch(batchId) {
1767
- return await fetchAnthropicMessageBatch(options, batchId);
2456
+ return await fetchAnthropicMessageBatch(clientContext, batchId);
1768
2457
  },
1769
2458
  async listMessageBatchResults(batchId) {
1770
- return await listAnthropicMessageBatchResults(options, batchId);
2459
+ return await listAnthropicMessageBatchResults(clientContext, batchId);
1771
2460
  },
1772
2461
  async waitForMessageBatchCompletion(batchId, waitOptions) {
1773
2462
  return await waitForAnthropicMessageBatchCompletion(
1774
- options,
2463
+ clientContext,
1775
2464
  batchId,
1776
2465
  waitOptions
1777
2466
  );
@@ -1798,8 +2487,8 @@ function buildAnthropicBatchRequestHeaders(apiKey) {
1798
2487
  "anthropic-version": anthropicBatchApiVersion
1799
2488
  };
1800
2489
  }
1801
- async function submitAnthropicMessageBatch(options, requests) {
1802
- const context = resolveAnthropicBatchRequestContext(options);
2490
+ async function submitAnthropicMessageBatch(clientContext, requests) {
2491
+ const context = resolveAnthropicBatchRequestContext(clientContext.options);
1803
2492
  const response = await context.fetchImplementation(
1804
2493
  `${context.baseUrl}/v1/messages/batches`,
1805
2494
  {
@@ -1810,10 +2499,18 @@ async function submitAnthropicMessageBatch(options, requests) {
1810
2499
  })
1811
2500
  }
1812
2501
  );
1813
- return await parseAnthropicMessageBatchHttpResponse(response);
2502
+ const batch = await parseAnthropicMessageBatchHttpResponse(response);
2503
+ clientContext.traceEmitter.emitBatchSubmittedEvent(
2504
+ batch,
2505
+ requests.map((request) => ({
2506
+ customId: request.customId,
2507
+ model: request.model
2508
+ }))
2509
+ );
2510
+ return batch;
1814
2511
  }
1815
- async function fetchAnthropicMessageBatch(options, batchId) {
1816
- const context = resolveAnthropicBatchRequestContext(options);
2512
+ async function fetchAnthropicMessageBatch(clientContext, batchId) {
2513
+ const context = resolveAnthropicBatchRequestContext(clientContext.options);
1817
2514
  const response = await context.fetchImplementation(
1818
2515
  `${context.baseUrl}/v1/messages/batches/${batchId}`,
1819
2516
  {
@@ -1821,7 +2518,9 @@ async function fetchAnthropicMessageBatch(options, batchId) {
1821
2518
  headers: buildAnthropicBatchRequestHeaders(context.apiKey)
1822
2519
  }
1823
2520
  );
1824
- return await parseAnthropicMessageBatchHttpResponse(response);
2521
+ const batch = await parseAnthropicMessageBatchHttpResponse(response);
2522
+ clientContext.traceEmitter.emitBatchCompletedEventOnce(batch);
2523
+ return batch;
1825
2524
  }
1826
2525
  async function parseAnthropicMessageBatchHttpResponse(response) {
1827
2526
  if (!response.ok) {
@@ -1835,17 +2534,17 @@ async function parseAnthropicMessageBatchHttpResponse(response) {
1835
2534
  }
1836
2535
  return mapAnthropicMessageBatchResponseToMessageBatch(parseResult.data);
1837
2536
  }
1838
- async function listAnthropicMessageBatchResults(options, batchId) {
1839
- const batch = await fetchAnthropicMessageBatch(options, batchId);
2537
+ async function listAnthropicMessageBatchResults(clientContext, batchId) {
2538
+ const batch = await fetchAnthropicMessageBatch(clientContext, batchId);
1840
2539
  if (batch.resultsUrl === null) {
1841
- throw new import_errors25.AppError({
1842
- code: import_errors24.AppErrorCode.Conflict,
2540
+ throw new import_errors29.AppError({
2541
+ code: import_errors28.AppErrorCode.Conflict,
1843
2542
  message: `Anthropic message batch ${batchId} has no results because processing has not ended`,
1844
2543
  statusCode: 409,
1845
2544
  details: { batchId, processingStatus: batch.processingStatus }
1846
2545
  });
1847
2546
  }
1848
- const context = resolveAnthropicBatchRequestContext(options);
2547
+ const context = resolveAnthropicBatchRequestContext(clientContext.options);
1849
2548
  const response = await context.fetchImplementation(batch.resultsUrl, {
1850
2549
  method: "GET",
1851
2550
  headers: buildAnthropicBatchRequestHeaders(context.apiKey)
@@ -1853,7 +2552,11 @@ async function listAnthropicMessageBatchResults(options, batchId) {
1853
2552
  if (!response.ok) {
1854
2553
  throw buildProviderStatusError("Anthropic", response.status);
1855
2554
  }
1856
- return parseAnthropicBatchResultsJsonl(await response.text());
2555
+ const results = parseAnthropicBatchResultsJsonl(await response.text());
2556
+ for (const result of results) {
2557
+ clientContext.traceEmitter.emitBatchResultEvent(batchId, result);
2558
+ }
2559
+ return results;
1857
2560
  }
1858
2561
  function parseAnthropicBatchResultsJsonl(jsonlText) {
1859
2562
  return jsonlText.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map(parseAnthropicBatchResultLine);
@@ -1872,7 +2575,7 @@ function parseAnthropicBatchResultLine(line) {
1872
2575
  }
1873
2576
  function parseAnthropicBatchResultLineJson(line) {
1874
2577
  try {
1875
- return import_json6.JsonValueSchema.parse(JSON.parse(line));
2578
+ return import_json8.JsonValueSchema.parse(JSON.parse(line));
1876
2579
  } catch {
1877
2580
  throw buildProviderInvalidResponseError(
1878
2581
  "Anthropic",
@@ -1880,81 +2583,811 @@ function parseAnthropicBatchResultLineJson(line) {
1880
2583
  );
1881
2584
  }
1882
2585
  }
1883
- async function waitForAnthropicMessageBatchCompletion(options, batchId, waitOptions) {
2586
+ async function waitForAnthropicMessageBatchCompletion(clientContext, batchId, waitOptions) {
1884
2587
  const pollIntervalMs = waitOptions?.pollIntervalMs ?? defaultAnthropicBatchPollIntervalMs;
1885
2588
  const timeoutMs = waitOptions?.timeoutMs ?? defaultAnthropicBatchTimeoutMs;
1886
2589
  const waitFor = waitOptions?.waitFor ?? waitForMilliseconds;
1887
2590
  const startedAt = Date.now();
1888
- let batch = await fetchAnthropicMessageBatch(options, batchId);
2591
+ let batch = await fetchAnthropicMessageBatch(clientContext, batchId);
1889
2592
  while (batch.processingStatus !== "ended") {
1890
2593
  if (Date.now() - startedAt >= timeoutMs) {
1891
2594
  throw buildAnthropicBatchTimeoutError(batchId, timeoutMs);
1892
2595
  }
1893
2596
  await waitFor(pollIntervalMs);
1894
- batch = await fetchAnthropicMessageBatch(options, batchId);
2597
+ batch = await fetchAnthropicMessageBatch(clientContext, batchId);
1895
2598
  }
1896
2599
  return batch;
1897
2600
  }
1898
2601
  function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
1899
- return new import_errors25.AppError({
1900
- code: import_errors24.AppErrorCode.ServiceUnavailable,
2602
+ return new import_errors29.AppError({
2603
+ code: import_errors28.AppErrorCode.ServiceUnavailable,
1901
2604
  message: `Anthropic message batch ${batchId} did not complete within ${String(timeoutMs)}ms`,
1902
2605
  statusCode: 504,
1903
2606
  details: { batchId, timeoutMs }
1904
2607
  });
1905
2608
  }
1906
- function mapBatchMessageRequestToApiBatchRequest(request) {
1907
- const params = {
1908
- model: request.model,
1909
- max_tokens: request.maxOutputTokens ?? defaultAnthropicMaxOutputTokens,
1910
- messages: request.messages.filter((message) => message.role !== "system").map(mapChatMessageToBatchApiRequestMessage)
2609
+
2610
+ // src/azure-openai-adapter.ts
2611
+ var import_errors32 = require("@assemble-dev/shared-types/errors");
2612
+ var import_errors33 = require("@assemble-dev/shared-utils/errors");
2613
+
2614
+ // src/azure-openai-response-parsing.ts
2615
+ var import_zod9 = require("zod");
2616
+ var import_errors30 = require("@assemble-dev/shared-types/errors");
2617
+ var import_json9 = require("@assemble-dev/shared-types/json");
2618
+ var import_errors31 = require("@assemble-dev/shared-utils/errors");
2619
+ var AzureOpenAiUsageSchema = import_zod9.z.object({
2620
+ prompt_tokens: import_zod9.z.number().int().nonnegative(),
2621
+ completion_tokens: import_zod9.z.number().int().nonnegative(),
2622
+ total_tokens: import_zod9.z.number().int().nonnegative()
2623
+ });
2624
+ var AzureOpenAiResponseToolCallSchema = import_zod9.z.object({
2625
+ id: import_zod9.z.string(),
2626
+ function: import_zod9.z.object({
2627
+ name: import_zod9.z.string(),
2628
+ arguments: import_zod9.z.string()
2629
+ })
2630
+ });
2631
+ var AzureOpenAiChatCompletionResponseSchema = import_zod9.z.object({
2632
+ choices: import_zod9.z.array(
2633
+ import_zod9.z.object({
2634
+ message: import_zod9.z.object({
2635
+ content: import_zod9.z.string().nullable(),
2636
+ tool_calls: import_zod9.z.array(AzureOpenAiResponseToolCallSchema).optional()
2637
+ }),
2638
+ finish_reason: import_zod9.z.string().nullable().optional()
2639
+ })
2640
+ ).min(1),
2641
+ usage: AzureOpenAiUsageSchema
2642
+ });
2643
+ function mapAzureOpenAiResponseToChatCompletionResult(response, latencyMs) {
2644
+ const toolCalls = extractAzureOpenAiToolCalls(response);
2645
+ const result = {
2646
+ content: extractAzureOpenAiMessageContent(response, toolCalls.length > 0),
2647
+ tokenUsage: mapAzureOpenAiUsageToTokenUsage(response.usage),
2648
+ latencyMs
1911
2649
  };
1912
- const systemText = joinBatchSystemMessageText(request.messages);
1913
- if (systemText.length > 0) {
1914
- params.system = systemText;
2650
+ const finishReason = response.choices[0]?.finish_reason;
2651
+ if (toolCalls.length > 0) {
2652
+ result.toolCalls = toolCalls;
1915
2653
  }
1916
- if (request.temperature !== void 0) {
1917
- params.temperature = request.temperature;
2654
+ if (finishReason !== null && finishReason !== void 0) {
2655
+ result.stopReason = normalizeAzureOpenAiFinishReason(finishReason);
1918
2656
  }
1919
- return { custom_id: request.customId, params };
2657
+ return result;
1920
2658
  }
1921
- function joinBatchSystemMessageText(messages) {
1922
- return messages.filter((message) => message.role === "system").map(extractMessageText).join("\n\n");
2659
+ function extractAzureOpenAiToolCalls(response) {
2660
+ const responseToolCalls = response.choices[0]?.message.tool_calls ?? [];
2661
+ return responseToolCalls.map((responseToolCall) => ({
2662
+ id: responseToolCall.id,
2663
+ toolName: responseToolCall.function.name,
2664
+ input: parseAzureOpenAiToolArgumentsJson(responseToolCall.function.arguments)
2665
+ }));
1923
2666
  }
1924
- function mapChatMessageToBatchApiRequestMessage(message) {
1925
- if (message.role === "assistant") {
1926
- return { role: "assistant", content: extractMessageText(message) };
2667
+ function parseAzureOpenAiToolArgumentsJson(argumentsJsonText) {
2668
+ if (argumentsJsonText.trim().length === 0) {
2669
+ return {};
1927
2670
  }
1928
- if (message.role === "tool") {
1929
- return { role: "user", content: buildBatchToolResultText(message) };
2671
+ try {
2672
+ return import_json9.JsonValueSchema.parse(JSON.parse(argumentsJsonText));
2673
+ } catch (error) {
2674
+ throw new import_errors31.AppError({
2675
+ code: import_errors30.AppErrorCode.ValidationFailed,
2676
+ message: "Azure OpenAI tool call arguments were not valid JSON",
2677
+ statusCode: 502,
2678
+ cause: error instanceof Error ? error : void 0
2679
+ });
1930
2680
  }
1931
- return { role: "user", content: extractMessageText(message) };
1932
2681
  }
1933
- function buildBatchToolResultText(message) {
1934
- if (message.toolName === void 0) {
1935
- return `Tool result: ${extractMessageText(message)}`;
2682
+ function normalizeAzureOpenAiFinishReason(finishReason) {
2683
+ if (finishReason === "tool_calls") {
2684
+ return "tool_use";
1936
2685
  }
1937
- return `Tool result (${message.toolName}): ${extractMessageText(message)}`;
2686
+ if (finishReason === "length") {
2687
+ return "max_tokens";
2688
+ }
2689
+ return "end_turn";
2690
+ }
2691
+ function extractAzureOpenAiMessageContent(response, allowEmptyContent) {
2692
+ const content = response.choices[0]?.message.content;
2693
+ if (content === void 0 || content === null) {
2694
+ if (allowEmptyContent) {
2695
+ return "";
2696
+ }
2697
+ throw new import_errors31.AppError({
2698
+ code: import_errors30.AppErrorCode.ValidationFailed,
2699
+ message: "Azure OpenAI response contained no message content",
2700
+ statusCode: 502
2701
+ });
2702
+ }
2703
+ return content;
2704
+ }
2705
+ function mapAzureOpenAiUsageToTokenUsage(usage) {
2706
+ return {
2707
+ inputTokens: usage.prompt_tokens,
2708
+ outputTokens: usage.completion_tokens,
2709
+ totalTokens: usage.total_tokens
2710
+ };
2711
+ }
2712
+
2713
+ // src/azure-openai-stream.ts
2714
+ var import_zod10 = require("zod");
2715
+ var AzureOpenAiStreamToolCallDeltaSchema = import_zod10.z.object({
2716
+ index: import_zod10.z.number().int().nonnegative(),
2717
+ id: import_zod10.z.string().optional(),
2718
+ function: import_zod10.z.object({
2719
+ name: import_zod10.z.string().optional(),
2720
+ arguments: import_zod10.z.string().optional()
2721
+ }).optional()
2722
+ });
2723
+ var AzureOpenAiStreamChunkSchema = import_zod10.z.object({
2724
+ choices: import_zod10.z.array(
2725
+ import_zod10.z.object({
2726
+ delta: import_zod10.z.object({
2727
+ content: import_zod10.z.string().nullable().optional(),
2728
+ tool_calls: import_zod10.z.array(AzureOpenAiStreamToolCallDeltaSchema).optional()
2729
+ }).optional(),
2730
+ finish_reason: import_zod10.z.string().nullable().optional()
2731
+ })
2732
+ ).optional(),
2733
+ usage: AzureOpenAiUsageSchema.nullable().optional()
2734
+ });
2735
+ async function* streamAzureOpenAiChatCompletion(input) {
2736
+ const startedAt = Date.now();
2737
+ const response = await establishAzureOpenAiStreamResponse(input);
2738
+ if (response.body === null) {
2739
+ throw buildProviderInvalidResponseError("Azure OpenAI", "stream body");
2740
+ }
2741
+ yield* parseAzureOpenAiStreamEvents(
2742
+ response.body,
2743
+ startedAt,
2744
+ input.abortSignal
2745
+ );
2746
+ }
2747
+ async function establishAzureOpenAiStreamResponse(input) {
2748
+ return await executeProviderCallWithRetry(input.retry, async () => {
2749
+ const response = await executeAbortableProviderFetch(
2750
+ "Azure OpenAI",
2751
+ async () => await input.fetchImplementation(input.url, {
2752
+ method: "POST",
2753
+ headers: input.headers,
2754
+ body: JSON.stringify(input.body),
2755
+ signal: input.abortSignal
2756
+ })
2757
+ );
2758
+ if (!response.ok) {
2759
+ throw buildProviderStatusError("Azure OpenAI", response.status);
2760
+ }
2761
+ return response;
2762
+ });
2763
+ }
2764
+ async function* parseAzureOpenAiStreamEvents(body, startedAt, abortSignal) {
2765
+ const accumulator = createAzureOpenAiStreamAccumulator();
2766
+ for await (const dataText of readServerSentEventDataLines2(body, abortSignal)) {
2767
+ if (dataText === "[DONE]") {
2768
+ yield {
2769
+ type: "completed",
2770
+ result: buildAzureOpenAiStreamResult(
2771
+ accumulator,
2772
+ Date.now() - startedAt
2773
+ )
2774
+ };
2775
+ return;
2776
+ }
2777
+ const parsedChunk = AzureOpenAiStreamChunkSchema.safeParse(
2778
+ JSON.parse(dataText)
2779
+ );
2780
+ if (!parsedChunk.success) {
2781
+ continue;
2782
+ }
2783
+ yield* applyAzureOpenAiStreamChunk(parsedChunk.data, accumulator);
2784
+ }
2785
+ throw buildProviderInvalidResponseError("Azure OpenAI", "stream termination");
2786
+ }
2787
+ async function* readServerSentEventDataLines2(body, abortSignal) {
2788
+ const reader = body.getReader();
2789
+ const decoder = new TextDecoder();
2790
+ let bufferedText = "";
2791
+ try {
2792
+ for (; ; ) {
2793
+ if (abortSignal?.aborted === true) {
2794
+ await reader.cancel();
2795
+ throw buildProviderCanceledError("Azure OpenAI");
2796
+ }
2797
+ const readResult = await reader.read();
2798
+ if (readResult.done) {
2799
+ return;
2800
+ }
2801
+ bufferedText += decoder.decode(readResult.value, { stream: true });
2802
+ const lines = bufferedText.split("\n");
2803
+ bufferedText = lines.pop() ?? "";
2804
+ for (const line of lines) {
2805
+ if (line.startsWith("data:")) {
2806
+ const dataText = line.slice("data:".length).trim();
2807
+ if (dataText.length > 0) {
2808
+ yield dataText;
2809
+ }
2810
+ }
2811
+ }
2812
+ }
2813
+ } catch (error) {
2814
+ if (error instanceof Error && isAbortError(error)) {
2815
+ throw buildProviderCanceledError("Azure OpenAI");
2816
+ }
2817
+ throw error;
2818
+ }
2819
+ }
2820
+ function createAzureOpenAiStreamAccumulator() {
2821
+ return {
2822
+ contentText: "",
2823
+ toolCallsByIndex: /* @__PURE__ */ new Map()
2824
+ };
2825
+ }
2826
+ function* applyAzureOpenAiStreamChunk(chunk, accumulator) {
2827
+ if (chunk.usage !== null && chunk.usage !== void 0) {
2828
+ accumulator.usage = chunk.usage;
2829
+ }
2830
+ const choice = chunk.choices?.[0];
2831
+ if (choice === void 0) {
2832
+ return;
2833
+ }
2834
+ if (choice.finish_reason !== null && choice.finish_reason !== void 0) {
2835
+ accumulator.finishReason = choice.finish_reason;
2836
+ }
2837
+ if (choice.delta === void 0) {
2838
+ return;
2839
+ }
2840
+ const contentDelta = choice.delta.content;
2841
+ if (contentDelta !== null && contentDelta !== void 0 && contentDelta.length > 0) {
2842
+ accumulator.contentText += contentDelta;
2843
+ yield { type: "text_delta", text: contentDelta };
2844
+ }
2845
+ for (const toolCallDelta of choice.delta.tool_calls ?? []) {
2846
+ yield* applyAzureOpenAiToolCallDelta(toolCallDelta, accumulator);
2847
+ }
2848
+ }
2849
+ function* applyAzureOpenAiToolCallDelta(toolCallDelta, accumulator) {
2850
+ const existingToolCall = accumulator.toolCallsByIndex.get(toolCallDelta.index);
2851
+ if (existingToolCall === void 0) {
2852
+ yield* startAzureOpenAiToolCallAccumulation(toolCallDelta, accumulator);
2853
+ return;
2854
+ }
2855
+ const argumentsDelta = toolCallDelta.function?.arguments;
2856
+ if (argumentsDelta !== void 0 && argumentsDelta.length > 0) {
2857
+ existingToolCall.argumentsJsonText += argumentsDelta;
2858
+ yield {
2859
+ type: "tool_call_input_delta",
2860
+ id: existingToolCall.id,
2861
+ inputJsonText: argumentsDelta
2862
+ };
2863
+ }
2864
+ }
2865
+ function* startAzureOpenAiToolCallAccumulation(toolCallDelta, accumulator) {
2866
+ const toolName = toolCallDelta.function?.name;
2867
+ if (toolCallDelta.id === void 0 || toolName === void 0) {
2868
+ throw buildProviderInvalidResponseError(
2869
+ "Azure OpenAI",
2870
+ "stream tool call start"
2871
+ );
2872
+ }
2873
+ const startedToolCall = {
2874
+ id: toolCallDelta.id,
2875
+ toolName,
2876
+ argumentsJsonText: toolCallDelta.function?.arguments ?? ""
2877
+ };
2878
+ accumulator.toolCallsByIndex.set(toolCallDelta.index, startedToolCall);
2879
+ yield {
2880
+ type: "tool_call_started",
2881
+ id: startedToolCall.id,
2882
+ toolName: startedToolCall.toolName
2883
+ };
2884
+ if (startedToolCall.argumentsJsonText.length > 0) {
2885
+ yield {
2886
+ type: "tool_call_input_delta",
2887
+ id: startedToolCall.id,
2888
+ inputJsonText: startedToolCall.argumentsJsonText
2889
+ };
2890
+ }
2891
+ }
2892
+ function buildAzureOpenAiStreamResult(accumulator, latencyMs) {
2893
+ const result = {
2894
+ content: accumulator.contentText,
2895
+ tokenUsage: mapAzureOpenAiUsageToTokenUsage(
2896
+ accumulator.usage ?? {
2897
+ prompt_tokens: 0,
2898
+ completion_tokens: 0,
2899
+ total_tokens: 0
2900
+ }
2901
+ ),
2902
+ latencyMs
2903
+ };
2904
+ const toolCalls = [...accumulator.toolCallsByIndex.values()].map(
2905
+ mapAccumulatedToolCallToModelToolCall2
2906
+ );
2907
+ if (toolCalls.length > 0) {
2908
+ result.toolCalls = toolCalls;
2909
+ }
2910
+ if (accumulator.finishReason !== void 0) {
2911
+ result.stopReason = normalizeAzureOpenAiFinishReason(
2912
+ accumulator.finishReason
2913
+ );
2914
+ }
2915
+ return result;
2916
+ }
2917
+ function mapAccumulatedToolCallToModelToolCall2(toolCallAccumulation) {
2918
+ return {
2919
+ id: toolCallAccumulation.id,
2920
+ toolName: toolCallAccumulation.toolName,
2921
+ input: parseAzureOpenAiToolArgumentsJson(
2922
+ toolCallAccumulation.argumentsJsonText
2923
+ )
2924
+ };
2925
+ }
2926
+
2927
+ // src/azure-openai-adapter.ts
2928
+ var defaultAzureOpenAiApiVersion = "2024-10-21";
2929
+ var azureDeploymentModelPlaceholder = "azure-deployment";
2930
+ function azureOpenai(options) {
2931
+ return {
2932
+ name: `azure-openai:${options.deployment}`,
2933
+ async generateChatCompletion(request) {
2934
+ return await executeAzureOpenAiAdapterCall(options, {
2935
+ messages: request.messages,
2936
+ temperature: request.temperature ?? options.temperature,
2937
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
2938
+ tools: request.tools,
2939
+ toolChoice: request.toolChoice,
2940
+ abortSignal: request.abortSignal,
2941
+ extraBody: request.extraBody
2942
+ });
2943
+ },
2944
+ async generateStructuredOutput(request) {
2945
+ const completion = await executeAzureOpenAiAdapterCall(options, {
2946
+ messages: request.messages,
2947
+ temperature: request.temperature ?? options.temperature,
2948
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
2949
+ structuredOutputJsonSchema: buildOpenAiStructuredOutputJsonSchema(
2950
+ request.schema
2951
+ ),
2952
+ abortSignal: request.abortSignal
2953
+ });
2954
+ return {
2955
+ value: parseStructuredJsonText(completion.content, request.schema),
2956
+ tokenUsage: completion.tokenUsage,
2957
+ latencyMs: completion.latencyMs
2958
+ };
2959
+ },
2960
+ streamChatCompletion(request) {
2961
+ return streamAzureOpenAiChatCompletion(
2962
+ buildAzureOpenAiStreamInput(options, request)
2963
+ );
2964
+ }
2965
+ };
2966
+ }
2967
+ function buildAzureOpenAiChatCompletionsUrl(options) {
2968
+ const endpoint = resolveAzureOpenAiEndpoint(options);
2969
+ const apiVersion = options.apiVersion ?? defaultAzureOpenAiApiVersion;
2970
+ return `${endpoint}/openai/deployments/${encodeURIComponent(options.deployment)}/chat/completions?api-version=${encodeURIComponent(apiVersion)}`;
2971
+ }
2972
+ function resolveAzureOpenAiEndpoint(options) {
2973
+ if (options.baseURL !== void 0 && options.baseURL.length > 0) {
2974
+ return options.baseURL.replace(/\/+$/, "");
2975
+ }
2976
+ if (options.resourceName !== void 0 && options.resourceName.length > 0) {
2977
+ return `https://${options.resourceName}.openai.azure.com`;
2978
+ }
2979
+ throw new import_errors33.AppError({
2980
+ code: import_errors32.AppErrorCode.BadRequest,
2981
+ message: "Azure OpenAI endpoint is missing. Pass resourceName or baseURL to azureOpenai().",
2982
+ statusCode: 400
2983
+ });
2984
+ }
2985
+ function buildAzureOpenAiRequestHeaders(options) {
2986
+ return {
2987
+ "content-type": "application/json",
2988
+ "api-key": resolveProviderApiKey({
2989
+ providerLabel: "Azure OpenAI",
2990
+ adapterFunctionName: "azureOpenai()",
2991
+ baseEnvVarName: "AZURE_OPENAI_API_KEY",
2992
+ apiKey: options.apiKey,
2993
+ apiKeyName: options.apiKeyName
2994
+ })
2995
+ };
2996
+ }
2997
+ function buildAzureOpenAiChatRequestBody(input) {
2998
+ const requestBody = buildOpenAiRequestBody(
2999
+ azureDeploymentModelPlaceholder,
3000
+ input
3001
+ );
3002
+ const { model: ignoredModel, ...requestBodyWithoutModel } = requestBody;
3003
+ void ignoredModel;
3004
+ return requestBodyWithoutModel;
3005
+ }
3006
+ async function executeAzureOpenAiAdapterCall(options, input) {
3007
+ return await executeProviderCallWithRetry(
3008
+ options.retry,
3009
+ async () => await requestAzureOpenAiChatCompletion(options, input)
3010
+ );
3011
+ }
3012
+ async function requestAzureOpenAiChatCompletion(options, input) {
3013
+ const fetchImplementation = options.fetchImplementation ?? fetch;
3014
+ const requestBody = mergeProviderRequestExtraBody(
3015
+ buildAzureOpenAiChatRequestBody(input),
3016
+ options.extraBody,
3017
+ input.extraBody
3018
+ );
3019
+ const startedAt = Date.now();
3020
+ const response = await executeAbortableProviderFetch(
3021
+ "Azure OpenAI",
3022
+ async () => await fetchImplementation(buildAzureOpenAiChatCompletionsUrl(options), {
3023
+ method: "POST",
3024
+ headers: buildAzureOpenAiRequestHeaders(options),
3025
+ body: JSON.stringify(requestBody),
3026
+ signal: input.abortSignal
3027
+ })
3028
+ );
3029
+ const latencyMs = Date.now() - startedAt;
3030
+ if (!response.ok) {
3031
+ throw buildProviderStatusError("Azure OpenAI", response.status);
3032
+ }
3033
+ const parseResult = AzureOpenAiChatCompletionResponseSchema.safeParse(
3034
+ await response.json()
3035
+ );
3036
+ if (!parseResult.success) {
3037
+ throw buildProviderInvalidResponseError("Azure OpenAI", "chat completion");
3038
+ }
3039
+ return mapAzureOpenAiResponseToChatCompletionResult(
3040
+ parseResult.data,
3041
+ latencyMs
3042
+ );
3043
+ }
3044
+ function buildAzureOpenAiStreamInput(options, request) {
3045
+ const requestBody = mergeProviderRequestExtraBody(
3046
+ buildAzureOpenAiChatRequestBody({
3047
+ messages: request.messages,
3048
+ temperature: request.temperature ?? options.temperature,
3049
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
3050
+ tools: request.tools,
3051
+ toolChoice: request.toolChoice,
3052
+ abortSignal: request.abortSignal,
3053
+ extraBody: request.extraBody
3054
+ }),
3055
+ options.extraBody,
3056
+ request.extraBody
3057
+ );
3058
+ return {
3059
+ url: buildAzureOpenAiChatCompletionsUrl(options),
3060
+ headers: buildAzureOpenAiRequestHeaders(options),
3061
+ body: {
3062
+ ...requestBody,
3063
+ stream: true,
3064
+ stream_options: { include_usage: true }
3065
+ },
3066
+ fetchImplementation: options.fetchImplementation ?? fetch,
3067
+ retry: options.retry,
3068
+ abortSignal: request.abortSignal
3069
+ };
3070
+ }
3071
+
3072
+ // src/bedrock-adapter.ts
3073
+ var import_zod11 = require("zod");
3074
+ var import_errors34 = require("@assemble-dev/shared-types/errors");
3075
+ var import_errors35 = require("@assemble-dev/shared-utils/errors");
3076
+
3077
+ // src/bedrock-sigv4.ts
3078
+ var awsSigV4Algorithm = "AWS4-HMAC-SHA256";
3079
+ async function signAwsRequestWithSigV4(input) {
3080
+ const amzDate = formatAmzDateTime(input.signingDate ?? /* @__PURE__ */ new Date());
3081
+ const dateStamp = amzDate.slice(0, 8);
3082
+ const headersToSign = buildHeadersToSign(input, amzDate);
3083
+ const canonicalHeaderEntries = buildCanonicalHeaderEntries(headersToSign);
3084
+ const signedHeaderNames = canonicalHeaderEntries.map(([headerName]) => headerName).join(";");
3085
+ const credentialScope = `${dateStamp}/${input.region}/${input.service}/aws4_request`;
3086
+ const signatureHex = await computeAwsSigV4Signature(
3087
+ input,
3088
+ amzDate,
3089
+ credentialScope,
3090
+ canonicalHeaderEntries,
3091
+ signedHeaderNames
3092
+ );
3093
+ return {
3094
+ ...headersToSign,
3095
+ authorization: `${awsSigV4Algorithm} Credential=${input.credentials.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaderNames}, Signature=${signatureHex}`
3096
+ };
3097
+ }
3098
+ async function computeAwsSigV4Signature(input, amzDate, credentialScope, canonicalHeaderEntries, signedHeaderNames) {
3099
+ const canonicalRequest = await buildCanonicalRequest(
3100
+ input,
3101
+ canonicalHeaderEntries,
3102
+ signedHeaderNames
3103
+ );
3104
+ const stringToSign = [
3105
+ awsSigV4Algorithm,
3106
+ amzDate,
3107
+ credentialScope,
3108
+ await hashSha256Hex(canonicalRequest)
3109
+ ].join("\n");
3110
+ const signingKey = await deriveAwsSigningKey(
3111
+ input.credentials.secretAccessKey,
3112
+ amzDate.slice(0, 8),
3113
+ input.region,
3114
+ input.service
3115
+ );
3116
+ return bytesToHex(await computeHmacSha256(signingKey, stringToSign));
3117
+ }
3118
+ function buildHeadersToSign(input, amzDate) {
3119
+ const headersToSign = {};
3120
+ for (const [headerName, headerValue] of Object.entries(input.headers)) {
3121
+ headersToSign[headerName.toLowerCase()] = headerValue;
3122
+ }
3123
+ headersToSign.host = input.url.host;
3124
+ headersToSign["x-amz-date"] = amzDate;
3125
+ if (input.credentials.sessionToken !== void 0) {
3126
+ headersToSign["x-amz-security-token"] = input.credentials.sessionToken;
3127
+ }
3128
+ return headersToSign;
3129
+ }
3130
+ function buildCanonicalHeaderEntries(headersToSign) {
3131
+ return Object.entries(headersToSign).map(([headerName, headerValue]) => [
3132
+ headerName.toLowerCase(),
3133
+ headerValue.trim().replace(/\s+/g, " ")
3134
+ ]).sort(([leftName], [rightName]) => leftName.localeCompare(rightName));
3135
+ }
3136
+ async function buildCanonicalRequest(input, canonicalHeaderEntries, signedHeaderNames) {
3137
+ const canonicalHeadersText = canonicalHeaderEntries.map(([headerName, headerValue]) => `${headerName}:${headerValue}`).join("\n");
3138
+ return [
3139
+ input.method.toUpperCase(),
3140
+ buildCanonicalUri(input.url.pathname),
3141
+ buildCanonicalQueryString(input.url.searchParams),
3142
+ `${canonicalHeadersText}
3143
+ `,
3144
+ signedHeaderNames,
3145
+ await hashSha256Hex(input.bodyText)
3146
+ ].join("\n");
3147
+ }
3148
+ function buildCanonicalUri(pathname) {
3149
+ if (pathname.length === 0) {
3150
+ return "/";
3151
+ }
3152
+ return pathname.split("/").map(encodeRfc3986UriComponent).join("/");
3153
+ }
3154
+ function buildCanonicalQueryString(searchParams) {
3155
+ const encodedEntries = [];
3156
+ searchParams.forEach((parameterValue, parameterName) => {
3157
+ encodedEntries.push([
3158
+ encodeRfc3986UriComponent(parameterName),
3159
+ encodeRfc3986UriComponent(parameterValue)
3160
+ ]);
3161
+ });
3162
+ return encodedEntries.sort(
3163
+ ([leftName, leftValue], [rightName, rightValue]) => leftName.localeCompare(rightName) || leftValue.localeCompare(rightValue)
3164
+ ).map(([parameterName, parameterValue]) => `${parameterName}=${parameterValue}`).join("&");
3165
+ }
3166
+ function encodeRfc3986UriComponent(value) {
3167
+ return encodeURIComponent(value).replace(
3168
+ /[!'()*]/g,
3169
+ (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`
3170
+ );
3171
+ }
3172
+ function formatAmzDateTime(date) {
3173
+ return date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
3174
+ }
3175
+ async function deriveAwsSigningKey(secretAccessKey, dateStamp, region, service) {
3176
+ const dateKey = await computeHmacSha256(
3177
+ new TextEncoder().encode(`AWS4${secretAccessKey}`),
3178
+ dateStamp
3179
+ );
3180
+ const regionKey = await computeHmacSha256(dateKey, region);
3181
+ const serviceKey = await computeHmacSha256(regionKey, service);
3182
+ return await computeHmacSha256(serviceKey, "aws4_request");
3183
+ }
3184
+ async function hashSha256Hex(text) {
3185
+ const digest = await crypto.subtle.digest(
3186
+ "SHA-256",
3187
+ new TextEncoder().encode(text)
3188
+ );
3189
+ return bytesToHex(new Uint8Array(digest));
3190
+ }
3191
+ async function computeHmacSha256(keyBytes, text) {
3192
+ const hmacKey = await crypto.subtle.importKey(
3193
+ "raw",
3194
+ keyBytes,
3195
+ { name: "HMAC", hash: "SHA-256" },
3196
+ false,
3197
+ ["sign"]
3198
+ );
3199
+ const signature = await crypto.subtle.sign(
3200
+ "HMAC",
3201
+ hmacKey,
3202
+ new TextEncoder().encode(text)
3203
+ );
3204
+ return new Uint8Array(signature);
3205
+ }
3206
+ function bytesToHex(bytes) {
3207
+ return Array.from(bytes).map((byteValue) => byteValue.toString(16).padStart(2, "0")).join("");
3208
+ }
3209
+
3210
+ // src/bedrock-adapter.ts
3211
+ var bedrockAnthropicVersion = "bedrock-2023-05-31";
3212
+ var defaultBedrockMaxOutputTokens = 1024;
3213
+ var bedrockSigningServiceName = "bedrock";
3214
+ var bedrockModelPlaceholder = "bedrock-invoke-model";
3215
+ var BedrockEnvCredentialsSchema = import_zod11.z.object({
3216
+ AWS_ACCESS_KEY_ID: import_zod11.z.string().optional(),
3217
+ AWS_SECRET_ACCESS_KEY: import_zod11.z.string().optional(),
3218
+ AWS_SESSION_TOKEN: import_zod11.z.string().optional()
3219
+ });
3220
+ function bedrock(options) {
3221
+ return {
3222
+ name: `bedrock:${options.modelId}`,
3223
+ async generateChatCompletion(request) {
3224
+ return await executeBedrockAdapterCall(options, {
3225
+ messages: request.messages,
3226
+ temperature: request.temperature ?? options.temperature,
3227
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
3228
+ tools: request.tools,
3229
+ toolChoice: request.toolChoice,
3230
+ abortSignal: request.abortSignal,
3231
+ extraBody: request.extraBody
3232
+ });
3233
+ },
3234
+ async generateStructuredOutput(request) {
3235
+ const completion = await executeBedrockAdapterCall(options, {
3236
+ messages: [
3237
+ buildBedrockStructuredOutputSystemMessage(request.schema),
3238
+ ...request.messages
3239
+ ],
3240
+ temperature: request.temperature ?? options.temperature,
3241
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
3242
+ abortSignal: request.abortSignal
3243
+ });
3244
+ return {
3245
+ value: parseStructuredJsonText(completion.content, request.schema),
3246
+ tokenUsage: completion.tokenUsage,
3247
+ latencyMs: completion.latencyMs
3248
+ };
3249
+ }
3250
+ };
3251
+ }
3252
+ function buildBedrockInvokeModelUrl(region, modelId) {
3253
+ return `https://bedrock-runtime.${region}.amazonaws.com/model/${encodeURIComponent(modelId)}/invoke`;
3254
+ }
3255
+ function resolveBedrockCredentials(options) {
3256
+ if (options.credentials !== void 0) {
3257
+ return options.credentials;
3258
+ }
3259
+ const parsedEnv = BedrockEnvCredentialsSchema.parse(process.env);
3260
+ const accessKeyId = parsedEnv.AWS_ACCESS_KEY_ID;
3261
+ const secretAccessKey = parsedEnv.AWS_SECRET_ACCESS_KEY;
3262
+ if (accessKeyId === void 0 || accessKeyId.length === 0 || secretAccessKey === void 0 || secretAccessKey.length === 0) {
3263
+ throw new import_errors35.AppError({
3264
+ code: import_errors34.AppErrorCode.Unauthorized,
3265
+ message: "AWS credentials are missing. Pass credentials to bedrock() or set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.",
3266
+ statusCode: 401
3267
+ });
3268
+ }
3269
+ const credentials = { accessKeyId, secretAccessKey };
3270
+ const sessionToken = parsedEnv.AWS_SESSION_TOKEN;
3271
+ if (sessionToken !== void 0 && sessionToken.length > 0) {
3272
+ credentials.sessionToken = sessionToken;
3273
+ }
3274
+ return credentials;
3275
+ }
3276
+ async function executeBedrockAdapterCall(options, input) {
3277
+ return await executeProviderCallWithRetry(
3278
+ options.retry,
3279
+ async () => await requestBedrockInvokeModel(options, input)
3280
+ );
3281
+ }
3282
+ async function requestBedrockInvokeModel(options, input) {
3283
+ const credentials = resolveBedrockCredentials(options);
3284
+ const fetchImplementation = options.fetchImplementation ?? fetch;
3285
+ const requestBody = mergeProviderRequestExtraBody(
3286
+ buildBedrockInvokeModelRequestBody(input),
3287
+ options.extraBody,
3288
+ input.extraBody
3289
+ );
3290
+ const bodyText = JSON.stringify(requestBody);
3291
+ const url = new URL(buildBedrockInvokeModelUrl(options.region, options.modelId));
3292
+ const signedHeaders = await signAwsRequestWithSigV4({
3293
+ method: "POST",
3294
+ url,
3295
+ headers: { "content-type": "application/json" },
3296
+ bodyText,
3297
+ region: options.region,
3298
+ service: bedrockSigningServiceName,
3299
+ credentials
3300
+ });
3301
+ const startedAt = Date.now();
3302
+ const response = await executeAbortableProviderFetch(
3303
+ "Bedrock",
3304
+ async () => await fetchImplementation(url.toString(), {
3305
+ method: "POST",
3306
+ headers: signedHeaders,
3307
+ body: bodyText,
3308
+ signal: input.abortSignal
3309
+ })
3310
+ );
3311
+ const latencyMs = Date.now() - startedAt;
3312
+ if (!response.ok) {
3313
+ throw buildProviderStatusError("Bedrock", response.status);
3314
+ }
3315
+ const parseResult = AnthropicMessagesResponseSchema.safeParse(
3316
+ await response.json()
3317
+ );
3318
+ if (!parseResult.success) {
3319
+ throw buildProviderInvalidResponseError("Bedrock", "invoke model");
3320
+ }
3321
+ return mapAnthropicResponseToChatCompletionResult(parseResult.data, latencyMs);
3322
+ }
3323
+ function buildBedrockInvokeModelRequestBody(input) {
3324
+ const anthropicRequestBody = buildAnthropicRequestBody(
3325
+ {
3326
+ model: bedrockModelPlaceholder,
3327
+ defaultMaxOutputTokens: defaultBedrockMaxOutputTokens
3328
+ },
3329
+ input
3330
+ );
3331
+ const {
3332
+ model: ignoredModel,
3333
+ stream: ignoredStream,
3334
+ ...requestBodyWithoutModel
3335
+ } = anthropicRequestBody;
3336
+ void ignoredModel;
3337
+ void ignoredStream;
3338
+ return {
3339
+ ...requestBodyWithoutModel,
3340
+ anthropic_version: bedrockAnthropicVersion
3341
+ };
3342
+ }
3343
+ function buildBedrockStructuredOutputSystemMessage(schema) {
3344
+ return {
3345
+ role: "system",
3346
+ content: `Respond with a single JSON object that satisfies the following JSON Schema. Output only valid JSON with no surrounding text.
3347
+
3348
+ JSON Schema:
3349
+ ${JSON.stringify(convertZodSchemaToJsonSchema(schema))}`
3350
+ };
1938
3351
  }
1939
3352
  // Annotate the CommonJS export names for ESM import in node:
1940
3353
  0 && (module.exports = {
1941
3354
  AnthropicMessagesResponseSchema,
1942
3355
  AnthropicStreamEventSchema,
3356
+ AzureOpenAiChatCompletionResponseSchema,
3357
+ ChatMessageCacheControlSchema,
1943
3358
  ChatMessageRoleSchema,
1944
3359
  ChatMessageSchema,
1945
3360
  ChatStopReasonSchema,
1946
3361
  MessageContentBlockSchema,
1947
3362
  ModelToolCallSchema,
1948
3363
  anthropic,
3364
+ anthropicBatchJsonOnlySystemInstruction,
3365
+ anthropicBatchTraceWorkflowName,
3366
+ applyCacheControlToLastContentBlock,
3367
+ awsSigV4Algorithm,
3368
+ azureOpenai,
3369
+ bedrock,
3370
+ bedrockAnthropicVersion,
3371
+ buildAnthropicCacheControl,
1949
3372
  buildAnthropicRequestBody,
3373
+ buildAnthropicStructuredOutputJsonSchema,
3374
+ buildAzureOpenAiChatCompletionsUrl,
3375
+ buildAzureOpenAiChatRequestBody,
3376
+ buildBedrockInvokeModelRequestBody,
3377
+ buildBedrockInvokeModelUrl,
3378
+ buildGeminiResponseSchema,
1950
3379
  buildOpenAiRequestBody,
3380
+ buildOpenAiStructuredOutputJsonSchema,
1951
3381
  buildProviderCanceledError,
1952
3382
  calculateProviderRetryDelayMs,
3383
+ convertZodSchemaToJsonSchema,
1953
3384
  createAnthropicBatchClient,
1954
3385
  defaultAnthropicBaseUrl,
1955
3386
  defaultAnthropicBatchPollIntervalMs,
1956
3387
  defaultAnthropicBatchTimeoutMs,
1957
3388
  defaultAnthropicMaxOutputTokens,
3389
+ defaultAzureOpenAiApiVersion,
3390
+ defaultBedrockMaxOutputTokens,
1958
3391
  defaultGeminiBaseUrl,
1959
3392
  defaultOpenAiBaseUrl,
1960
3393
  defaultProviderRetryInitialDelayMs,
@@ -1965,6 +3398,7 @@ function buildBatchToolResultText(message) {
1965
3398
  executeProviderCallWithModelFallback,
1966
3399
  executeProviderCallWithRetry,
1967
3400
  extractAnthropicTextContent,
3401
+ extractAnthropicThinkingText,
1968
3402
  extractAnthropicToolCalls,
1969
3403
  extractMessageText,
1970
3404
  gemini,
@@ -1973,17 +3407,32 @@ function buildBatchToolResultText(message) {
1973
3407
  joinSystemMessageText,
1974
3408
  mapAnthropicResponseToChatCompletionResult,
1975
3409
  mapAnthropicUsageToTokenUsage,
3410
+ mapAzureOpenAiResponseToChatCompletionResult,
3411
+ mapAzureOpenAiUsageToTokenUsage,
1976
3412
  mapChatMessageToAnthropicRequestMessage,
1977
3413
  mapChatMessageToOpenAiRequestMessage,
1978
3414
  mapModelToolChoiceToAnthropicToolChoice,
1979
3415
  mapModelToolChoiceToOpenAiToolChoice,
1980
3416
  mapModelToolDefinitionToOpenAiTool,
1981
3417
  mapModelToolDefinitionsToAnthropicTools,
3418
+ mergeProviderRequestExtraBody,
1982
3419
  mockModel,
1983
3420
  normalizeAnthropicStopReason,
3421
+ normalizeAzureOpenAiFinishReason,
3422
+ openAiStructuredOutputSchemaName,
1984
3423
  openai,
3424
+ parseAnthropicBatchStructuredContent,
1985
3425
  parseAnthropicStreamEvents,
1986
3426
  parseAnthropicToolInputJson,
3427
+ parseAzureOpenAiStreamEvents,
3428
+ parseAzureOpenAiToolArgumentsJson,
3429
+ resolveAnthropicPromptCachingSettings,
3430
+ resolveBedrockCredentials,
1987
3431
  resolveProviderApiKey,
1988
- streamAnthropicChatCompletion
3432
+ sanitizeJsonSchemaForAnthropicStructuredOutput,
3433
+ sanitizeJsonSchemaForGeminiResponseSchema,
3434
+ sanitizeJsonSchemaForOpenAiStructuredOutput,
3435
+ signAwsRequestWithSigV4,
3436
+ streamAnthropicChatCompletion,
3437
+ streamAzureOpenAiChatCompletion
1989
3438
  });