@assemble-dev/providers 0.2.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.js CHANGED
@@ -53,14 +53,222 @@ function extractMessageText(message) {
53
53
  }
54
54
 
55
55
  // src/openai-adapter.ts
56
- import { z as z3 } from "zod";
57
- import { AppErrorCode as AppErrorCode7 } from "@assemble-dev/shared-types/errors";
56
+ import { z as z4 } from "zod";
57
+ import { AppErrorCode as AppErrorCode8 } from "@assemble-dev/shared-types/errors";
58
58
  import { JsonValueSchema as JsonValueSchema3 } from "@assemble-dev/shared-types/json";
59
- import { AppError as AppError8 } from "@assemble-dev/shared-utils/errors";
59
+ import { AppError as AppError9 } from "@assemble-dev/shared-utils/errors";
60
60
 
61
61
  // src/openai-request-mapping.ts
62
+ import { AppErrorCode as AppErrorCode2 } from "@assemble-dev/shared-types/errors";
63
+ import { AppError as AppError2 } from "@assemble-dev/shared-utils/errors";
64
+
65
+ // src/structured-output-json-schema.ts
66
+ import { z as z2 } from "zod";
62
67
  import { AppErrorCode } from "@assemble-dev/shared-types/errors";
68
+ import { JsonObjectSchema } from "@assemble-dev/shared-types/json";
63
69
  import { AppError } from "@assemble-dev/shared-utils/errors";
70
+
71
+ // src/json-schema-tree.ts
72
+ var schemaMapKeywords = ["properties", "$defs"];
73
+ var schemaListKeywords = ["anyOf", "oneOf", "allOf", "prefixItems"];
74
+ var schemaValueKeywords = [
75
+ "items",
76
+ "additionalProperties",
77
+ "not",
78
+ "if",
79
+ "then",
80
+ "else",
81
+ "contains",
82
+ "propertyNames"
83
+ ];
84
+ function isJsonObject(value) {
85
+ return typeof value === "object" && value !== null && !Array.isArray(value);
86
+ }
87
+ function transformJsonSchemaNode(node, transformNode) {
88
+ const result = { ...transformNode({ ...node }) };
89
+ for (const keyword of schemaMapKeywords) {
90
+ const mapValue = result[keyword];
91
+ if (mapValue !== void 0 && isJsonObject(mapValue)) {
92
+ result[keyword] = transformJsonSchemaMap(mapValue, transformNode);
93
+ }
94
+ }
95
+ for (const keyword of schemaListKeywords) {
96
+ const listValue = result[keyword];
97
+ if (Array.isArray(listValue)) {
98
+ result[keyword] = listValue.map(
99
+ (entry) => isJsonObject(entry) ? transformJsonSchemaNode(entry, transformNode) : entry
100
+ );
101
+ }
102
+ }
103
+ for (const keyword of schemaValueKeywords) {
104
+ const schemaValue = result[keyword];
105
+ if (schemaValue !== void 0 && isJsonObject(schemaValue)) {
106
+ result[keyword] = transformJsonSchemaNode(schemaValue, transformNode);
107
+ }
108
+ }
109
+ return result;
110
+ }
111
+ function transformJsonSchemaMap(schemaMap, transformNode) {
112
+ const result = {};
113
+ for (const [schemaName, schemaValue] of Object.entries(schemaMap)) {
114
+ result[schemaName] = isJsonObject(schemaValue) ? transformJsonSchemaNode(schemaValue, transformNode) : schemaValue;
115
+ }
116
+ return result;
117
+ }
118
+ function inlineJsonSchemaReferences(root) {
119
+ const rootDefinitions = root["$defs"];
120
+ const definitions = rootDefinitions !== void 0 && isJsonObject(rootDefinitions) ? rootDefinitions : {};
121
+ const resolvedRoot = resolveJsonSchemaReferences(
122
+ root,
123
+ definitions,
124
+ /* @__PURE__ */ new Set()
125
+ );
126
+ return isJsonObject(resolvedRoot) ? resolvedRoot : {};
127
+ }
128
+ function resolveJsonSchemaReferences(value, definitions, activeReferences) {
129
+ if (Array.isArray(value)) {
130
+ return value.map(
131
+ (entry) => resolveJsonSchemaReferences(entry, definitions, activeReferences)
132
+ );
133
+ }
134
+ if (!isJsonObject(value)) {
135
+ return value;
136
+ }
137
+ const referenceTarget = value["$ref"];
138
+ if (typeof referenceTarget === "string") {
139
+ return resolveJsonSchemaReferenceTarget(
140
+ referenceTarget,
141
+ definitions,
142
+ activeReferences
143
+ );
144
+ }
145
+ const result = {};
146
+ for (const [key, entryValue] of Object.entries(value)) {
147
+ if (key !== "$defs") {
148
+ result[key] = resolveJsonSchemaReferences(
149
+ entryValue,
150
+ definitions,
151
+ activeReferences
152
+ );
153
+ }
154
+ }
155
+ return result;
156
+ }
157
+ function resolveJsonSchemaReferenceTarget(referenceTarget, definitions, activeReferences) {
158
+ if (activeReferences.has(referenceTarget)) {
159
+ return {};
160
+ }
161
+ const definitionsPrefix = "#/$defs/";
162
+ if (!referenceTarget.startsWith(definitionsPrefix)) {
163
+ return {};
164
+ }
165
+ const definition = definitions[referenceTarget.slice(definitionsPrefix.length)];
166
+ if (definition === void 0 || !isJsonObject(definition)) {
167
+ return {};
168
+ }
169
+ return resolveJsonSchemaReferences(
170
+ definition,
171
+ definitions,
172
+ /* @__PURE__ */ new Set([...activeReferences, referenceTarget])
173
+ );
174
+ }
175
+ function removeJsonSchemaKeywords(node, keywords) {
176
+ const result = {};
177
+ for (const [key, value] of Object.entries(node)) {
178
+ if (!keywords.includes(key)) {
179
+ result[key] = value;
180
+ }
181
+ }
182
+ return result;
183
+ }
184
+
185
+ // src/structured-output-json-schema.ts
186
+ var openAiStructuredOutputSchemaName = "structured_output";
187
+ var schemaMetadataKeywords = ["$schema", "$id"];
188
+ var anthropicUnsupportedSchemaKeywords = [
189
+ ...schemaMetadataKeywords,
190
+ "minimum",
191
+ "maximum",
192
+ "exclusiveMinimum",
193
+ "exclusiveMaximum",
194
+ "minLength",
195
+ "maxLength",
196
+ "multipleOf"
197
+ ];
198
+ var openAiUnsupportedSchemaKeywords = [
199
+ ...anthropicUnsupportedSchemaKeywords,
200
+ "pattern",
201
+ "format",
202
+ "minItems",
203
+ "maxItems",
204
+ "uniqueItems",
205
+ "default"
206
+ ];
207
+ function convertZodSchemaToJsonSchema(schema) {
208
+ try {
209
+ return JsonObjectSchema.parse(z2.toJSONSchema(schema, { io: "input" }));
210
+ } catch (error) {
211
+ throw new AppError({
212
+ code: AppErrorCode.BadRequest,
213
+ message: "Structured output schema could not be converted to JSON Schema",
214
+ statusCode: 400,
215
+ cause: error instanceof Error ? error : void 0
216
+ });
217
+ }
218
+ }
219
+ function buildAnthropicStructuredOutputJsonSchema(schema) {
220
+ return sanitizeJsonSchemaForAnthropicStructuredOutput(
221
+ convertZodSchemaToJsonSchema(schema)
222
+ );
223
+ }
224
+ function sanitizeJsonSchemaForAnthropicStructuredOutput(jsonSchema) {
225
+ return transformJsonSchemaNode(
226
+ inlineJsonSchemaReferences(jsonSchema),
227
+ sanitizeAnthropicSchemaNode
228
+ );
229
+ }
230
+ function buildOpenAiStructuredOutputJsonSchema(schema) {
231
+ return sanitizeJsonSchemaForOpenAiStructuredOutput(
232
+ convertZodSchemaToJsonSchema(schema)
233
+ );
234
+ }
235
+ function sanitizeJsonSchemaForOpenAiStructuredOutput(jsonSchema) {
236
+ return transformJsonSchemaNode(jsonSchema, sanitizeOpenAiSchemaNode);
237
+ }
238
+ function sanitizeAnthropicSchemaNode(node) {
239
+ const sanitized = removeJsonSchemaKeywords(
240
+ node,
241
+ anthropicUnsupportedSchemaKeywords
242
+ );
243
+ if (sanitized["type"] === "object") {
244
+ sanitized["additionalProperties"] = false;
245
+ }
246
+ return sanitized;
247
+ }
248
+ function sanitizeOpenAiSchemaNode(node) {
249
+ const sanitized = removeJsonSchemaKeywords(
250
+ node,
251
+ openAiUnsupportedSchemaKeywords
252
+ );
253
+ if (sanitized["type"] !== "object") {
254
+ return sanitized;
255
+ }
256
+ sanitized["additionalProperties"] = false;
257
+ const propertyNames = listSchemaPropertyNames(sanitized);
258
+ if (propertyNames.length > 0) {
259
+ sanitized["required"] = propertyNames;
260
+ }
261
+ return sanitized;
262
+ }
263
+ function listSchemaPropertyNames(node) {
264
+ const properties = node["properties"];
265
+ if (properties === void 0 || !isJsonObject(properties)) {
266
+ return [];
267
+ }
268
+ return Object.keys(properties);
269
+ }
270
+
271
+ // src/openai-request-mapping.ts
64
272
  function buildOpenAiRequestBody(model, input) {
65
273
  const requestBody = {
66
274
  model,
@@ -72,7 +280,16 @@ function buildOpenAiRequestBody(model, input) {
72
280
  if (input.maxOutputTokens !== void 0) {
73
281
  requestBody.max_tokens = input.maxOutputTokens;
74
282
  }
75
- if (input.requireJsonObjectResponse) {
283
+ if (input.structuredOutputJsonSchema !== void 0) {
284
+ requestBody.response_format = {
285
+ type: "json_schema",
286
+ json_schema: {
287
+ name: openAiStructuredOutputSchemaName,
288
+ strict: true,
289
+ schema: input.structuredOutputJsonSchema
290
+ }
291
+ };
292
+ } else if (input.requireJsonObjectResponse === true) {
76
293
  requestBody.response_format = { type: "json_object" };
77
294
  }
78
295
  if (input.tools !== void 0 && input.tools.length > 0) {
@@ -158,17 +375,17 @@ function mapMessageContentBlockToOpenAiContentPart(contentBlock) {
158
375
  }
159
376
  };
160
377
  }
161
- throw new AppError({
162
- code: AppErrorCode.ValidationFailed,
378
+ throw new AppError2({
379
+ code: AppErrorCode2.ValidationFailed,
163
380
  message: "OpenAI adapter does not support document content blocks in chat messages",
164
381
  statusCode: 400
165
382
  });
166
383
  }
167
384
 
168
385
  // src/parse-structured-json.ts
169
- import { AppErrorCode as AppErrorCode2 } from "@assemble-dev/shared-types/errors";
386
+ import { AppErrorCode as AppErrorCode3 } from "@assemble-dev/shared-types/errors";
170
387
  import { JsonValueSchema as JsonValueSchema2 } from "@assemble-dev/shared-types/json";
171
- import { AppError as AppError2 } from "@assemble-dev/shared-utils/errors";
388
+ import { AppError as AppError3 } from "@assemble-dev/shared-utils/errors";
172
389
  var markdownCodeFencePattern = /^```[A-Za-z]*\s*\n?([\s\S]*?)\n?```$/;
173
390
  function parseStructuredJsonText(text, schema) {
174
391
  return schema.parse(parseJsonText(stripMarkdownCodeFences(text)));
@@ -185,8 +402,8 @@ function parseJsonText(text) {
185
402
  try {
186
403
  return JsonValueSchema2.parse(JSON.parse(text));
187
404
  } catch (error) {
188
- throw new AppError2({
189
- code: AppErrorCode2.ValidationFailed,
405
+ throw new AppError3({
406
+ code: AppErrorCode3.ValidationFailed,
190
407
  message: "Structured output was not valid JSON",
191
408
  statusCode: 422,
192
409
  cause: error instanceof Error ? error : void 0
@@ -195,9 +412,9 @@ function parseJsonText(text) {
195
412
  }
196
413
 
197
414
  // src/provider-api-key.ts
198
- import { z as z2 } from "zod";
199
- import { AppErrorCode as AppErrorCode3 } from "@assemble-dev/shared-types/errors";
200
- import { AppError as AppError3 } from "@assemble-dev/shared-utils/errors";
415
+ import { z as z3 } from "zod";
416
+ import { AppErrorCode as AppErrorCode4 } from "@assemble-dev/shared-types/errors";
417
+ import { AppError as AppError4 } from "@assemble-dev/shared-utils/errors";
201
418
  import {
202
419
  buildNamedApiKeyEnvVarName,
203
420
  expectedProviderApiKeyNameFormat,
@@ -214,8 +431,8 @@ function resolveProviderApiKey(input) {
214
431
  }
215
432
  function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
216
433
  if (!validateProviderApiKeyName(apiKeyName)) {
217
- throw new AppError3({
218
- code: AppErrorCode3.BadRequest,
434
+ throw new AppError4({
435
+ code: AppErrorCode4.BadRequest,
219
436
  message: `Invalid ${input.providerLabel} apiKeyName "${apiKeyName}". Expected ${expectedProviderApiKeyNameFormat}.`,
220
437
  statusCode: 400
221
438
  });
@@ -223,8 +440,8 @@ function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
223
440
  const envVarName = buildNamedApiKeyEnvVarName(input.baseEnvVarName, apiKeyName);
224
441
  const envApiKey = readEnvironmentVariable(envVarName);
225
442
  if (envApiKey === void 0 || envApiKey.length === 0) {
226
- throw new AppError3({
227
- code: AppErrorCode3.Unauthorized,
443
+ throw new AppError4({
444
+ code: AppErrorCode4.Unauthorized,
228
445
  message: `${input.providerLabel} API key named "${apiKeyName}" is missing. Set the ${envVarName} environment variable or pass apiKey to ${input.adapterFunctionName}.`,
229
446
  statusCode: 401
230
447
  });
@@ -234,8 +451,8 @@ function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
234
451
  function resolveBaseProviderApiKeyFromEnv(input) {
235
452
  const envApiKey = readEnvironmentVariable(input.baseEnvVarName);
236
453
  if (envApiKey === void 0 || envApiKey.length === 0) {
237
- throw new AppError3({
238
- code: AppErrorCode3.Unauthorized,
454
+ throw new AppError4({
455
+ code: AppErrorCode4.Unauthorized,
239
456
  message: `${input.providerLabel} API key is missing. Pass apiKey to ${input.adapterFunctionName} or set the ${input.baseEnvVarName} environment variable.`,
240
457
  statusCode: 401
241
458
  });
@@ -243,19 +460,19 @@ function resolveBaseProviderApiKeyFromEnv(input) {
243
460
  return envApiKey;
244
461
  }
245
462
  function readEnvironmentVariable(envVarName) {
246
- const parsedEnv = z2.object({ [envVarName]: z2.string().optional() }).parse(process.env);
463
+ const parsedEnv = z3.object({ [envVarName]: z3.string().optional() }).parse(process.env);
247
464
  return parsedEnv[envVarName];
248
465
  }
249
466
 
250
467
  // src/provider-cancellation.ts
251
- import { AppErrorCode as AppErrorCode4 } from "@assemble-dev/shared-types/errors";
252
- import { AppError as AppError4 } from "@assemble-dev/shared-utils/errors";
468
+ import { AppErrorCode as AppErrorCode5 } from "@assemble-dev/shared-types/errors";
469
+ import { AppError as AppError5 } from "@assemble-dev/shared-utils/errors";
253
470
  function isAbortError(error) {
254
471
  return error.name === "AbortError";
255
472
  }
256
473
  function buildProviderCanceledError(providerLabel) {
257
- return new AppError4({
258
- code: AppErrorCode4.Canceled,
474
+ return new AppError5({
475
+ code: AppErrorCode5.Canceled,
259
476
  message: `${providerLabel} request was canceled`,
260
477
  statusCode: 499
261
478
  });
@@ -281,18 +498,18 @@ function mergeProviderRequestExtraBody(requestBody, adapterExtraBody, requestExt
281
498
  }
282
499
 
283
500
  // src/provider-fallback.ts
284
- import { AppError as AppError6 } from "@assemble-dev/shared-utils/errors";
501
+ import { AppError as AppError7 } from "@assemble-dev/shared-utils/errors";
285
502
 
286
503
  // src/provider-retry.ts
287
- import { AppErrorCode as AppErrorCode5 } from "@assemble-dev/shared-types/errors";
288
- import { AppError as AppError5 } from "@assemble-dev/shared-utils/errors";
504
+ import { AppErrorCode as AppErrorCode6 } from "@assemble-dev/shared-types/errors";
505
+ import { AppError as AppError6 } from "@assemble-dev/shared-utils/errors";
289
506
  var defaultProviderRetryMaxAttempts = 3;
290
507
  var defaultProviderRetryInitialDelayMs = 500;
291
508
  var defaultProviderRetryMaxDelayMs = 8e3;
292
509
  var retryableAppErrorCodes = /* @__PURE__ */ new Set([
293
- AppErrorCode5.RateLimited,
294
- AppErrorCode5.ServiceUnavailable,
295
- AppErrorCode5.InternalServerError
510
+ AppErrorCode6.RateLimited,
511
+ AppErrorCode6.ServiceUnavailable,
512
+ AppErrorCode6.InternalServerError
296
513
  ]);
297
514
  function isRetryableProviderAppError(appError) {
298
515
  return retryableAppErrorCodes.has(appError.code);
@@ -307,7 +524,7 @@ async function executeProviderCallWithRetry(retryOptions, executeCall, waitFor)
307
524
  try {
308
525
  return await executeCall();
309
526
  } catch (error) {
310
- if (error instanceof AppError5 && !isRetryableProviderAppError(error)) {
527
+ if (error instanceof AppError6 && !isRetryableProviderAppError(error)) {
311
528
  throw error;
312
529
  }
313
530
  if (error instanceof Error && isAbortError(error)) {
@@ -341,7 +558,7 @@ async function executeProviderCallWithModelFallback(fallbackModel, executePrimar
341
558
  if (fallbackModel === void 0) {
342
559
  throw error;
343
560
  }
344
- if (error instanceof AppError6 && !isRetryableProviderAppError(error)) {
561
+ if (error instanceof AppError7 && !isRetryableProviderAppError(error)) {
345
562
  throw error;
346
563
  }
347
564
  if (error instanceof Error && isAbortError(error)) {
@@ -352,11 +569,11 @@ async function executeProviderCallWithModelFallback(fallbackModel, executePrimar
352
569
  }
353
570
 
354
571
  // src/provider-status-error.ts
355
- import { AppErrorCode as AppErrorCode6 } from "@assemble-dev/shared-types/errors";
356
- import { AppError as AppError7 } from "@assemble-dev/shared-utils/errors";
572
+ import { AppErrorCode as AppErrorCode7 } from "@assemble-dev/shared-types/errors";
573
+ import { AppError as AppError8 } from "@assemble-dev/shared-utils/errors";
357
574
  function buildProviderStatusError(providerLabel, providerStatus) {
358
575
  const code = mapProviderStatusToAppErrorCode(providerStatus);
359
- return new AppError7({
576
+ return new AppError8({
360
577
  code,
361
578
  message: `${providerLabel} request failed with status ${String(providerStatus)}`,
362
579
  statusCode: mapAppErrorCodeToStatusCode(code),
@@ -364,44 +581,44 @@ function buildProviderStatusError(providerLabel, providerStatus) {
364
581
  });
365
582
  }
366
583
  function buildProviderInvalidResponseError(providerLabel, expectedShapeDescription) {
367
- return new AppError7({
368
- code: AppErrorCode6.ValidationFailed,
584
+ return new AppError8({
585
+ code: AppErrorCode7.ValidationFailed,
369
586
  message: `${providerLabel} response did not match the expected ${expectedShapeDescription} shape`,
370
587
  statusCode: 502
371
588
  });
372
589
  }
373
590
  function mapProviderStatusToAppErrorCode(providerStatus) {
374
591
  if (providerStatus === 400) {
375
- return AppErrorCode6.BadRequest;
592
+ return AppErrorCode7.BadRequest;
376
593
  }
377
594
  if (providerStatus === 401) {
378
- return AppErrorCode6.Unauthorized;
595
+ return AppErrorCode7.Unauthorized;
379
596
  }
380
597
  if (providerStatus === 403) {
381
- return AppErrorCode6.Forbidden;
598
+ return AppErrorCode7.Forbidden;
382
599
  }
383
600
  if (providerStatus === 404) {
384
- return AppErrorCode6.NotFound;
601
+ return AppErrorCode7.NotFound;
385
602
  }
386
603
  if (providerStatus === 429) {
387
- return AppErrorCode6.RateLimited;
604
+ return AppErrorCode7.RateLimited;
388
605
  }
389
- return AppErrorCode6.InternalServerError;
606
+ return AppErrorCode7.InternalServerError;
390
607
  }
391
608
  function mapAppErrorCodeToStatusCode(code) {
392
- if (code === AppErrorCode6.BadRequest) {
609
+ if (code === AppErrorCode7.BadRequest) {
393
610
  return 400;
394
611
  }
395
- if (code === AppErrorCode6.Unauthorized) {
612
+ if (code === AppErrorCode7.Unauthorized) {
396
613
  return 401;
397
614
  }
398
- if (code === AppErrorCode6.Forbidden) {
615
+ if (code === AppErrorCode7.Forbidden) {
399
616
  return 403;
400
617
  }
401
- if (code === AppErrorCode6.NotFound) {
618
+ if (code === AppErrorCode7.NotFound) {
402
619
  return 404;
403
620
  }
404
- if (code === AppErrorCode6.RateLimited) {
621
+ if (code === AppErrorCode7.RateLimited) {
405
622
  return 429;
406
623
  }
407
624
  return 500;
@@ -409,33 +626,29 @@ function mapAppErrorCodeToStatusCode(code) {
409
626
 
410
627
  // src/openai-adapter.ts
411
628
  var defaultOpenAiBaseUrl = "https://api.openai.com/v1";
412
- var OpenAiResponseToolCallSchema = z3.object({
413
- id: z3.string(),
414
- function: z3.object({
415
- name: z3.string(),
416
- arguments: z3.string()
629
+ var OpenAiResponseToolCallSchema = z4.object({
630
+ id: z4.string(),
631
+ function: z4.object({
632
+ name: z4.string(),
633
+ arguments: z4.string()
417
634
  })
418
635
  });
419
- var OpenAiChatCompletionResponseSchema = z3.object({
420
- choices: z3.array(
421
- z3.object({
422
- message: z3.object({
423
- content: z3.string().nullable(),
424
- tool_calls: z3.array(OpenAiResponseToolCallSchema).optional()
636
+ var OpenAiChatCompletionResponseSchema = z4.object({
637
+ choices: z4.array(
638
+ z4.object({
639
+ message: z4.object({
640
+ content: z4.string().nullable(),
641
+ tool_calls: z4.array(OpenAiResponseToolCallSchema).optional()
425
642
  }),
426
- finish_reason: z3.string().nullable().optional()
643
+ finish_reason: z4.string().nullable().optional()
427
644
  })
428
645
  ).min(1),
429
- usage: z3.object({
430
- prompt_tokens: z3.number().int().nonnegative(),
431
- completion_tokens: z3.number().int().nonnegative(),
432
- total_tokens: z3.number().int().nonnegative()
646
+ usage: z4.object({
647
+ prompt_tokens: z4.number().int().nonnegative(),
648
+ completion_tokens: z4.number().int().nonnegative(),
649
+ total_tokens: z4.number().int().nonnegative()
433
650
  })
434
651
  });
435
- var structuredOutputSystemMessage = {
436
- role: "system",
437
- content: "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text."
438
- };
439
652
  function openai(options) {
440
653
  return {
441
654
  name: `openai:${options.model}`,
@@ -444,7 +657,6 @@ function openai(options) {
444
657
  messages: request.messages,
445
658
  temperature: request.temperature ?? options.temperature,
446
659
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
447
- requireJsonObjectResponse: false,
448
660
  tools: request.tools,
449
661
  toolChoice: request.toolChoice,
450
662
  abortSignal: request.abortSignal,
@@ -453,10 +665,12 @@ function openai(options) {
453
665
  },
454
666
  async generateStructuredOutput(request) {
455
667
  const completion = await executeOpenAiAdapterCall(options, {
456
- messages: [structuredOutputSystemMessage, ...request.messages],
668
+ messages: request.messages,
457
669
  temperature: request.temperature ?? options.temperature,
458
670
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
459
- requireJsonObjectResponse: true,
671
+ structuredOutputJsonSchema: buildOpenAiStructuredOutputJsonSchema(
672
+ request.schema
673
+ ),
460
674
  abortSignal: request.abortSignal
461
675
  });
462
676
  return {
@@ -551,8 +765,8 @@ function parseOpenAiToolArgumentsJson(argumentsJsonText) {
551
765
  try {
552
766
  return JsonValueSchema3.parse(JSON.parse(argumentsJsonText));
553
767
  } catch (error) {
554
- throw new AppError8({
555
- code: AppErrorCode7.ValidationFailed,
768
+ throw new AppError9({
769
+ code: AppErrorCode8.ValidationFailed,
556
770
  message: "OpenAI tool call arguments were not valid JSON",
557
771
  statusCode: 502,
558
772
  cause: error instanceof Error ? error : void 0
@@ -574,8 +788,8 @@ function extractOpenAiMessageContent(response, allowEmptyContent) {
574
788
  if (allowEmptyContent) {
575
789
  return "";
576
790
  }
577
- throw new AppError8({
578
- code: AppErrorCode7.ValidationFailed,
791
+ throw new AppError9({
792
+ code: AppErrorCode8.ValidationFailed,
579
793
  message: "OpenAI response contained no message content",
580
794
  statusCode: 502
581
795
  });
@@ -639,6 +853,11 @@ function buildAnthropicRequestBody(settings, input) {
639
853
  budget_tokens: settings.thinking.budgetTokens
640
854
  };
641
855
  }
856
+ if (input.structuredOutputJsonSchema !== void 0) {
857
+ requestBody.output_config = {
858
+ format: { type: "json_schema", schema: input.structuredOutputJsonSchema }
859
+ };
860
+ }
642
861
  return requestBody;
643
862
  }
644
863
  function applyAnthropicSystemField(requestBody, settings, input) {
@@ -795,44 +1014,45 @@ function mapMessageContentBlockToAnthropic(contentBlock) {
795
1014
  }
796
1015
 
797
1016
  // src/anthropic-response-parsing.ts
798
- import { z as z4 } from "zod";
799
- import { AppErrorCode as AppErrorCode8 } from "@assemble-dev/shared-types/errors";
1017
+ import { z as z5 } from "zod";
1018
+ import { AppErrorCode as AppErrorCode9 } from "@assemble-dev/shared-types/errors";
800
1019
  import { JsonValueSchema as JsonValueSchema4 } from "@assemble-dev/shared-types/json";
801
- import { AppError as AppError9 } from "@assemble-dev/shared-utils/errors";
802
- var AnthropicUsageSchema = z4.object({
803
- input_tokens: z4.number().int().nonnegative(),
804
- output_tokens: z4.number().int().nonnegative(),
805
- cache_creation_input_tokens: z4.number().int().nonnegative().optional(),
806
- cache_read_input_tokens: z4.number().int().nonnegative().optional()
1020
+ import { AppError as AppError10 } from "@assemble-dev/shared-utils/errors";
1021
+ var AnthropicUsageSchema = z5.object({
1022
+ input_tokens: z5.number().int().nonnegative(),
1023
+ output_tokens: z5.number().int().nonnegative(),
1024
+ cache_creation_input_tokens: z5.number().int().nonnegative().optional(),
1025
+ cache_read_input_tokens: z5.number().int().nonnegative().optional()
807
1026
  });
808
- var AnthropicContentBlockSchema = z4.discriminatedUnion("type", [
809
- z4.object({
810
- type: z4.literal("text"),
811
- text: z4.string()
1027
+ var AnthropicContentBlockSchema = z5.discriminatedUnion("type", [
1028
+ z5.object({
1029
+ type: z5.literal("text"),
1030
+ text: z5.string()
812
1031
  }),
813
- z4.object({
814
- type: z4.literal("tool_use"),
815
- id: z4.string(),
816
- name: z4.string(),
1032
+ z5.object({
1033
+ type: z5.literal("tool_use"),
1034
+ id: z5.string(),
1035
+ name: z5.string(),
817
1036
  input: JsonValueSchema4
818
1037
  }),
819
- z4.object({
820
- type: z4.literal("thinking"),
821
- thinking: z4.string().optional(),
822
- signature: z4.string().optional()
1038
+ z5.object({
1039
+ type: z5.literal("thinking"),
1040
+ thinking: z5.string().optional(),
1041
+ signature: z5.string().optional()
823
1042
  }),
824
- z4.object({
825
- type: z4.literal("redacted_thinking"),
826
- data: z4.string().optional()
1043
+ z5.object({
1044
+ type: z5.literal("redacted_thinking"),
1045
+ data: z5.string().optional()
827
1046
  })
828
1047
  ]);
829
- var AnthropicMessagesResponseSchema = z4.object({
830
- content: z4.array(AnthropicContentBlockSchema),
831
- stop_reason: z4.string().nullable().optional(),
1048
+ var AnthropicMessagesResponseSchema = z5.object({
1049
+ content: z5.array(AnthropicContentBlockSchema),
1050
+ stop_reason: z5.string().nullable().optional(),
832
1051
  usage: AnthropicUsageSchema
833
1052
  });
834
1053
  function mapAnthropicResponseToChatCompletionResult(response, latencyMs) {
835
1054
  const toolCalls = extractAnthropicToolCalls(response);
1055
+ const thinkingText = extractAnthropicThinkingText(response);
836
1056
  const result = {
837
1057
  content: extractAnthropicTextContent(response, toolCalls.length > 0),
838
1058
  tokenUsage: mapAnthropicUsageToTokenUsage(response.usage),
@@ -841,6 +1061,9 @@ function mapAnthropicResponseToChatCompletionResult(response, latencyMs) {
841
1061
  if (toolCalls.length > 0) {
842
1062
  result.toolCalls = toolCalls;
843
1063
  }
1064
+ if (thinkingText.length > 0) {
1065
+ result.thinkingText = thinkingText;
1066
+ }
844
1067
  if (response.stop_reason !== null && response.stop_reason !== void 0) {
845
1068
  result.stopReason = normalizeAnthropicStopReason(response.stop_reason);
846
1069
  }
@@ -853,13 +1076,16 @@ function extractAnthropicToolCalls(response) {
853
1076
  input: contentBlock.input
854
1077
  }));
855
1078
  }
1079
+ function extractAnthropicThinkingText(response) {
1080
+ return response.content.filter((contentBlock) => contentBlock.type === "thinking").map((contentBlock) => contentBlock.thinking ?? "").join("");
1081
+ }
856
1082
  function extractAnthropicTextContent(response, allowEmptyText) {
857
1083
  const textBlocks = response.content.filter(
858
1084
  (contentBlock) => contentBlock.type === "text"
859
1085
  );
860
1086
  if (textBlocks.length === 0 && !allowEmptyText) {
861
- throw new AppError9({
862
- code: AppErrorCode8.ValidationFailed,
1087
+ throw new AppError10({
1088
+ code: AppErrorCode9.ValidationFailed,
863
1089
  message: "Anthropic response contained no text content",
864
1090
  statusCode: 502
865
1091
  });
@@ -896,58 +1122,68 @@ function mapAnthropicUsageToTokenUsage(usage) {
896
1122
  }
897
1123
 
898
1124
  // src/anthropic-stream.ts
899
- import { AppErrorCode as AppErrorCode9 } from "@assemble-dev/shared-types/errors";
1125
+ import { AppErrorCode as AppErrorCode10 } from "@assemble-dev/shared-types/errors";
900
1126
  import { JsonValueSchema as JsonValueSchema5 } from "@assemble-dev/shared-types/json";
901
- import { AppError as AppError10 } from "@assemble-dev/shared-utils/errors";
1127
+ import { AppError as AppError11 } from "@assemble-dev/shared-utils/errors";
902
1128
 
903
1129
  // src/anthropic-stream-events.ts
904
- import { z as z5 } from "zod";
905
- var AnthropicStreamEventSchema = z5.discriminatedUnion("type", [
906
- z5.object({
907
- type: z5.literal("message_start"),
908
- message: z5.object({
909
- usage: z5.object({
910
- input_tokens: z5.number().int().nonnegative(),
911
- output_tokens: z5.number().int().nonnegative().optional(),
912
- cache_creation_input_tokens: z5.number().int().nonnegative().optional(),
913
- cache_read_input_tokens: z5.number().int().nonnegative().optional()
1130
+ import { z as z6 } from "zod";
1131
+ var AnthropicStreamEventSchema = z6.discriminatedUnion("type", [
1132
+ z6.object({
1133
+ type: z6.literal("message_start"),
1134
+ message: z6.object({
1135
+ usage: z6.object({
1136
+ input_tokens: z6.number().int().nonnegative(),
1137
+ output_tokens: z6.number().int().nonnegative().optional(),
1138
+ cache_creation_input_tokens: z6.number().int().nonnegative().optional(),
1139
+ cache_read_input_tokens: z6.number().int().nonnegative().optional()
914
1140
  })
915
1141
  })
916
1142
  }),
917
- z5.object({
918
- type: z5.literal("content_block_start"),
919
- index: z5.number().int().nonnegative(),
920
- content_block: z5.discriminatedUnion("type", [
921
- z5.object({ type: z5.literal("text"), text: z5.string().optional() }),
922
- z5.object({
923
- type: z5.literal("tool_use"),
924
- id: z5.string(),
925
- name: z5.string()
1143
+ z6.object({
1144
+ type: z6.literal("content_block_start"),
1145
+ index: z6.number().int().nonnegative(),
1146
+ content_block: z6.discriminatedUnion("type", [
1147
+ z6.object({ type: z6.literal("text"), text: z6.string().optional() }),
1148
+ z6.object({
1149
+ type: z6.literal("thinking"),
1150
+ thinking: z6.string().optional()
1151
+ }),
1152
+ z6.object({
1153
+ type: z6.literal("redacted_thinking"),
1154
+ data: z6.string().optional()
1155
+ }),
1156
+ z6.object({
1157
+ type: z6.literal("tool_use"),
1158
+ id: z6.string(),
1159
+ name: z6.string()
926
1160
  })
927
1161
  ])
928
1162
  }),
929
- z5.object({
930
- type: z5.literal("content_block_delta"),
931
- index: z5.number().int().nonnegative(),
932
- delta: z5.discriminatedUnion("type", [
933
- z5.object({ type: z5.literal("text_delta"), text: z5.string() }),
934
- z5.object({
935
- type: z5.literal("input_json_delta"),
936
- partial_json: z5.string()
1163
+ z6.object({
1164
+ type: z6.literal("content_block_delta"),
1165
+ index: z6.number().int().nonnegative(),
1166
+ delta: z6.discriminatedUnion("type", [
1167
+ z6.object({ type: z6.literal("text_delta"), text: z6.string() }),
1168
+ z6.object({ type: z6.literal("thinking_delta"), thinking: z6.string() }),
1169
+ z6.object({ type: z6.literal("signature_delta"), signature: z6.string() }),
1170
+ z6.object({
1171
+ type: z6.literal("input_json_delta"),
1172
+ partial_json: z6.string()
937
1173
  })
938
1174
  ])
939
1175
  }),
940
- z5.object({ type: z5.literal("content_block_stop") }),
941
- z5.object({
942
- type: z5.literal("message_delta"),
943
- delta: z5.object({ stop_reason: z5.string().nullable().optional() }),
944
- usage: z5.object({ output_tokens: z5.number().int().nonnegative() }).optional()
1176
+ z6.object({ type: z6.literal("content_block_stop") }),
1177
+ z6.object({
1178
+ type: z6.literal("message_delta"),
1179
+ delta: z6.object({ stop_reason: z6.string().nullable().optional() }),
1180
+ usage: z6.object({ output_tokens: z6.number().int().nonnegative() }).optional()
945
1181
  }),
946
- z5.object({ type: z5.literal("message_stop") }),
947
- z5.object({ type: z5.literal("ping") }),
948
- z5.object({
949
- type: z5.literal("error"),
950
- error: z5.object({ message: z5.string() })
1182
+ z6.object({ type: z6.literal("message_stop") }),
1183
+ z6.object({ type: z6.literal("ping") }),
1184
+ z6.object({
1185
+ type: z6.literal("error"),
1186
+ error: z6.object({ message: z6.string() })
951
1187
  })
952
1188
  ]);
953
1189
 
@@ -1033,6 +1269,7 @@ async function* readServerSentEventDataLines(body, abortSignal) {
1033
1269
  function createAnthropicStreamAccumulator() {
1034
1270
  return {
1035
1271
  contentText: "",
1272
+ thinkingText: "",
1036
1273
  toolCallsByBlockIndex: /* @__PURE__ */ new Map(),
1037
1274
  inputTokens: 0,
1038
1275
  outputTokens: 0
@@ -1040,8 +1277,8 @@ function createAnthropicStreamAccumulator() {
1040
1277
  }
1041
1278
  function* applyAnthropicStreamEvent(event, accumulator) {
1042
1279
  if (event.type === "error") {
1043
- throw new AppError10({
1044
- code: AppErrorCode9.InternalServerError,
1280
+ throw new AppError11({
1281
+ code: AppErrorCode10.InternalServerError,
1045
1282
  message: `Anthropic stream reported an error: ${event.error.message}`,
1046
1283
  statusCode: 502
1047
1284
  });
@@ -1077,6 +1314,17 @@ function* applyAnthropicContentBlockStart(event, accumulator) {
1077
1314
  }
1078
1315
  return;
1079
1316
  }
1317
+ if (event.content_block.type === "thinking") {
1318
+ const initialThinkingText = event.content_block.thinking ?? "";
1319
+ if (initialThinkingText.length > 0) {
1320
+ accumulator.thinkingText += initialThinkingText;
1321
+ yield { type: "thinking_delta", text: initialThinkingText };
1322
+ }
1323
+ return;
1324
+ }
1325
+ if (event.content_block.type === "redacted_thinking") {
1326
+ return;
1327
+ }
1080
1328
  accumulator.toolCallsByBlockIndex.set(event.index, {
1081
1329
  id: event.content_block.id,
1082
1330
  toolName: event.content_block.name,
@@ -1094,6 +1342,14 @@ function* applyAnthropicContentBlockDelta(event, accumulator) {
1094
1342
  yield { type: "text_delta", text: event.delta.text };
1095
1343
  return;
1096
1344
  }
1345
+ if (event.delta.type === "thinking_delta") {
1346
+ accumulator.thinkingText += event.delta.thinking;
1347
+ yield { type: "thinking_delta", text: event.delta.thinking };
1348
+ return;
1349
+ }
1350
+ if (event.delta.type === "signature_delta") {
1351
+ return;
1352
+ }
1097
1353
  const toolCallAccumulation = accumulator.toolCallsByBlockIndex.get(
1098
1354
  event.index
1099
1355
  );
@@ -1140,6 +1396,9 @@ function buildAnthropicStreamResult(accumulator, latencyMs) {
1140
1396
  if (accumulator.stopReason !== void 0) {
1141
1397
  result.stopReason = accumulator.stopReason;
1142
1398
  }
1399
+ if (accumulator.thinkingText.length > 0) {
1400
+ result.thinkingText = accumulator.thinkingText;
1401
+ }
1143
1402
  return result;
1144
1403
  }
1145
1404
  function mapAccumulatedToolCallToModelToolCall(toolCallAccumulation) {
@@ -1156,8 +1415,8 @@ function parseAnthropicToolInputJson(inputJsonText) {
1156
1415
  try {
1157
1416
  return JsonValueSchema5.parse(JSON.parse(inputJsonText));
1158
1417
  } catch (error) {
1159
- throw new AppError10({
1160
- code: AppErrorCode9.ValidationFailed,
1418
+ throw new AppError11({
1419
+ code: AppErrorCode10.ValidationFailed,
1161
1420
  message: "Anthropic tool input was not valid JSON",
1162
1421
  statusCode: 502,
1163
1422
  cause: error instanceof Error ? error : void 0
@@ -1169,10 +1428,6 @@ function parseAnthropicToolInputJson(inputJsonText) {
1169
1428
  var defaultAnthropicBaseUrl = "https://api.anthropic.com";
1170
1429
  var defaultAnthropicMaxOutputTokens = 1024;
1171
1430
  var anthropicApiVersion = "2023-06-01";
1172
- var structuredOutputSystemMessage2 = {
1173
- role: "system",
1174
- content: "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text."
1175
- };
1176
1431
  function anthropic(options) {
1177
1432
  return {
1178
1433
  name: `anthropic:${options.model}`,
@@ -1184,9 +1439,12 @@ function anthropic(options) {
1184
1439
  },
1185
1440
  async generateStructuredOutput(request) {
1186
1441
  const completion = await executeAnthropicAdapterCall(options, {
1187
- messages: [structuredOutputSystemMessage2, ...request.messages],
1442
+ messages: request.messages,
1188
1443
  temperature: request.temperature ?? options.temperature,
1189
1444
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1445
+ structuredOutputJsonSchema: buildAnthropicStructuredOutputJsonSchema(
1446
+ request.schema
1447
+ ),
1190
1448
  abortSignal: request.abortSignal
1191
1449
  });
1192
1450
  return {
@@ -1302,28 +1560,116 @@ function resolveAnthropicFetch(options) {
1302
1560
  }
1303
1561
 
1304
1562
  // src/gemini-adapter.ts
1305
- import { z as z6 } from "zod";
1306
- import { AppErrorCode as AppErrorCode10 } from "@assemble-dev/shared-types/errors";
1307
- import { AppError as AppError11 } from "@assemble-dev/shared-utils/errors";
1563
+ import { z as z7 } from "zod";
1564
+ import { AppErrorCode as AppErrorCode11 } from "@assemble-dev/shared-types/errors";
1565
+ import { AppError as AppError12 } from "@assemble-dev/shared-utils/errors";
1566
+
1567
+ // src/gemini-response-schema.ts
1568
+ var geminiAllowedSchemaKeywords = [
1569
+ "type",
1570
+ "format",
1571
+ "description",
1572
+ "nullable",
1573
+ "enum",
1574
+ "properties",
1575
+ "required",
1576
+ "items",
1577
+ "minItems",
1578
+ "maxItems",
1579
+ "anyOf"
1580
+ ];
1581
+ var geminiAllowedFormats = [
1582
+ "date-time",
1583
+ "int32",
1584
+ "int64",
1585
+ "float",
1586
+ "double"
1587
+ ];
1588
+ function buildGeminiResponseSchema(schema) {
1589
+ return sanitizeJsonSchemaForGeminiResponseSchema(
1590
+ convertZodSchemaToJsonSchema(schema)
1591
+ );
1592
+ }
1593
+ function sanitizeJsonSchemaForGeminiResponseSchema(jsonSchema) {
1594
+ return transformJsonSchemaNode(
1595
+ inlineJsonSchemaReferences(jsonSchema),
1596
+ sanitizeGeminiSchemaNode
1597
+ );
1598
+ }
1599
+ function sanitizeGeminiSchemaNode(node) {
1600
+ const normalized = normalizeGeminiNullableType(
1601
+ mergeNullUnionIntoNullableNode(node)
1602
+ );
1603
+ const sanitized = {};
1604
+ for (const [key, value] of Object.entries(normalized)) {
1605
+ if (geminiAllowedSchemaKeywords.includes(key)) {
1606
+ sanitized[key] = value;
1607
+ }
1608
+ }
1609
+ return removeUnsupportedGeminiFormat(sanitized);
1610
+ }
1611
+ function mergeNullUnionIntoNullableNode(node) {
1612
+ const unionKeyword = Array.isArray(node["anyOf"]) ? "anyOf" : "oneOf";
1613
+ const unionMembers = node[unionKeyword];
1614
+ if (!Array.isArray(unionMembers)) {
1615
+ return node;
1616
+ }
1617
+ const nonNullMembers = unionMembers.filter(
1618
+ (member) => !isNullTypeSchemaNode(member)
1619
+ );
1620
+ if (nonNullMembers.length === unionMembers.length) {
1621
+ return node;
1622
+ }
1623
+ const merged = { ...node };
1624
+ delete merged[unionKeyword];
1625
+ const singleMember = nonNullMembers.length === 1 ? nonNullMembers[0] : void 0;
1626
+ if (singleMember !== void 0 && isJsonObject(singleMember)) {
1627
+ return { ...merged, ...singleMember, nullable: true };
1628
+ }
1629
+ return { ...merged, anyOf: nonNullMembers, nullable: true };
1630
+ }
1631
+ function normalizeGeminiNullableType(node) {
1632
+ const typeValue = node["type"];
1633
+ if (!Array.isArray(typeValue)) {
1634
+ return node;
1635
+ }
1636
+ const nonNullTypes = typeValue.filter((typeName) => typeName !== "null");
1637
+ const normalized = { ...node };
1638
+ if (nonNullTypes.length < typeValue.length) {
1639
+ normalized["nullable"] = true;
1640
+ }
1641
+ normalized["type"] = nonNullTypes[0] ?? "string";
1642
+ return normalized;
1643
+ }
1644
+ function removeUnsupportedGeminiFormat(node) {
1645
+ const formatValue = node["format"];
1646
+ if (typeof formatValue === "string" && !geminiAllowedFormats.includes(formatValue)) {
1647
+ const withoutFormat = { ...node };
1648
+ delete withoutFormat["format"];
1649
+ return withoutFormat;
1650
+ }
1651
+ return node;
1652
+ }
1653
+ function isNullTypeSchemaNode(value) {
1654
+ return isJsonObject(value) && value["type"] === "null";
1655
+ }
1656
+
1657
+ // src/gemini-adapter.ts
1308
1658
  var defaultGeminiBaseUrl = "https://generativelanguage.googleapis.com";
1309
- var GeminiGenerateContentResponseSchema = z6.object({
1310
- candidates: z6.array(
1311
- z6.object({
1312
- content: z6.object({
1313
- parts: z6.array(z6.object({ text: z6.string() }))
1659
+ var GeminiGenerateContentResponseSchema = z7.object({
1660
+ candidates: z7.array(
1661
+ z7.object({
1662
+ content: z7.object({
1663
+ parts: z7.array(z7.object({ text: z7.string() }))
1314
1664
  })
1315
1665
  })
1316
1666
  ).optional(),
1317
- usageMetadata: z6.object({
1318
- promptTokenCount: z6.number().int().nonnegative().optional(),
1319
- candidatesTokenCount: z6.number().int().nonnegative().optional(),
1320
- totalTokenCount: z6.number().int().nonnegative().optional()
1667
+ usageMetadata: z7.object({
1668
+ promptTokenCount: z7.number().int().nonnegative().optional(),
1669
+ candidatesTokenCount: z7.number().int().nonnegative().optional(),
1670
+ totalTokenCount: z7.number().int().nonnegative().optional()
1321
1671
  }).optional()
1322
1672
  });
1323
- var structuredOutputSystemMessage3 = {
1324
- role: "system",
1325
- content: "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text."
1326
- };
1327
1673
  function gemini(options) {
1328
1674
  return {
1329
1675
  name: `gemini:${options.model}`,
@@ -1333,17 +1679,16 @@ function gemini(options) {
1333
1679
  messages: request.messages,
1334
1680
  temperature: request.temperature ?? options.temperature,
1335
1681
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1336
- requireJsonResponse: false,
1337
1682
  abortSignal: request.abortSignal,
1338
1683
  extraBody: request.extraBody
1339
1684
  });
1340
1685
  },
1341
1686
  async generateStructuredOutput(request) {
1342
1687
  const completion = await executeGeminiAdapterCall(options, {
1343
- messages: [structuredOutputSystemMessage3, ...request.messages],
1688
+ messages: request.messages,
1344
1689
  temperature: request.temperature ?? options.temperature,
1345
1690
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1346
- requireJsonResponse: true,
1691
+ responseSchema: buildGeminiResponseSchema(request.schema),
1347
1692
  abortSignal: request.abortSignal
1348
1693
  });
1349
1694
  return {
@@ -1430,8 +1775,8 @@ function ensureGeminiRequestHasNoTools(request) {
1430
1775
  if (request.tools === void 0 || request.tools.length === 0) {
1431
1776
  return;
1432
1777
  }
1433
- throw new AppError11({
1434
- code: AppErrorCode10.ValidationFailed,
1778
+ throw new AppError12({
1779
+ code: AppErrorCode11.ValidationFailed,
1435
1780
  message: "gemini adapter does not support model-driven tool use; remove tools from the request or use another adapter",
1436
1781
  statusCode: 400
1437
1782
  });
@@ -1468,8 +1813,9 @@ function buildGeminiGenerationConfig(input) {
1468
1813
  if (input.maxOutputTokens !== void 0) {
1469
1814
  generationConfig.maxOutputTokens = input.maxOutputTokens;
1470
1815
  }
1471
- if (input.requireJsonResponse) {
1816
+ if (input.responseSchema !== void 0) {
1472
1817
  generationConfig.responseMimeType = "application/json";
1818
+ generationConfig.responseSchema = input.responseSchema;
1473
1819
  }
1474
1820
  if (Object.keys(generationConfig).length === 0) {
1475
1821
  return void 0;
@@ -1479,8 +1825,8 @@ function buildGeminiGenerationConfig(input) {
1479
1825
  function extractGeminiCandidateText(response) {
1480
1826
  const firstCandidate = response.candidates?.[0];
1481
1827
  if (firstCandidate === void 0) {
1482
- throw new AppError11({
1483
- code: AppErrorCode10.ValidationFailed,
1828
+ throw new AppError12({
1829
+ code: AppErrorCode11.ValidationFailed,
1484
1830
  message: "Gemini response contained no candidates",
1485
1831
  statusCode: 502
1486
1832
  });
@@ -1499,8 +1845,8 @@ function mapGeminiUsageToTokenUsage(response) {
1499
1845
  }
1500
1846
 
1501
1847
  // src/mock-adapter.ts
1502
- import { AppErrorCode as AppErrorCode11 } from "@assemble-dev/shared-types/errors";
1503
- import { AppError as AppError12 } from "@assemble-dev/shared-utils/errors";
1848
+ import { AppErrorCode as AppErrorCode12 } from "@assemble-dev/shared-types/errors";
1849
+ import { AppError as AppError13 } from "@assemble-dev/shared-utils/errors";
1504
1850
  var mockStreamChunkCount = 3;
1505
1851
  function mockModel(options = {}) {
1506
1852
  const remainingScriptedResponses = [...options.scriptedResponses ?? []];
@@ -1580,8 +1926,8 @@ function resolveNextMockResponseText(request, remainingScriptedResponses, respon
1580
1926
  if (respond !== void 0) {
1581
1927
  return respond(request);
1582
1928
  }
1583
- throw new AppError12({
1584
- code: AppErrorCode11.BadRequest,
1929
+ throw new AppError13({
1930
+ code: AppErrorCode12.BadRequest,
1585
1931
  message: "Mock model has no scripted responses left and no respond function was provided",
1586
1932
  statusCode: 400
1587
1933
  });
@@ -1669,14 +2015,14 @@ function calculateModelCallCostUsd(pricing, tokenUsage) {
1669
2015
  }
1670
2016
 
1671
2017
  // src/anthropic-batch.ts
1672
- import { AppErrorCode as AppErrorCode13 } from "@assemble-dev/shared-types/errors";
2018
+ import { AppErrorCode as AppErrorCode14 } from "@assemble-dev/shared-types/errors";
1673
2019
  import { JsonValueSchema as JsonValueSchema7 } from "@assemble-dev/shared-types/json";
1674
- import { AppError as AppError14 } from "@assemble-dev/shared-utils/errors";
2020
+ import { AppError as AppError15 } from "@assemble-dev/shared-utils/errors";
1675
2021
 
1676
2022
  // src/anthropic-batch-structured.ts
1677
- import { AppErrorCode as AppErrorCode12 } from "@assemble-dev/shared-types/errors";
2023
+ import { AppErrorCode as AppErrorCode13 } from "@assemble-dev/shared-types/errors";
1678
2024
  import { JsonValueSchema as JsonValueSchema6 } from "@assemble-dev/shared-types/json";
1679
- import { AppError as AppError13 } from "@assemble-dev/shared-utils/errors";
2025
+ import { AppError as AppError14 } from "@assemble-dev/shared-utils/errors";
1680
2026
  var anthropicBatchJsonOnlySystemInstruction = "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text.";
1681
2027
  function parseAnthropicBatchStructuredContent(content, schema) {
1682
2028
  const jsonValue = parseStructuredJsonText(
@@ -1685,8 +2031,8 @@ function parseAnthropicBatchStructuredContent(content, schema) {
1685
2031
  );
1686
2032
  const validationResult = schema.safeParse(jsonValue);
1687
2033
  if (!validationResult.success) {
1688
- throw new AppError13({
1689
- code: AppErrorCode12.ValidationFailed,
2034
+ throw new AppError14({
2035
+ code: AppErrorCode13.ValidationFailed,
1690
2036
  message: "Anthropic batch structured output did not match the expected schema",
1691
2037
  statusCode: 422,
1692
2038
  details: { validationErrorMessage: validationResult.error.message }
@@ -1703,11 +2049,25 @@ function mapBatchMessageRequestToApiBatchRequest(request) {
1703
2049
  messages: request.messages.filter((message) => message.role !== "system").map(mapChatMessageToBatchApiRequestMessage)
1704
2050
  };
1705
2051
  applyBatchSystemField(params, request);
2052
+ applyBatchStructuredOutputConfig(params, request);
1706
2053
  if (request.temperature !== void 0) {
1707
2054
  params.temperature = request.temperature;
1708
2055
  }
1709
2056
  return { custom_id: request.customId, params };
1710
2057
  }
2058
+ function applyBatchStructuredOutputConfig(params, request) {
2059
+ if (request.structuredOutputJsonSchema === void 0) {
2060
+ return;
2061
+ }
2062
+ params.output_config = {
2063
+ format: {
2064
+ type: "json_schema",
2065
+ schema: sanitizeJsonSchemaForAnthropicStructuredOutput(
2066
+ request.structuredOutputJsonSchema
2067
+ )
2068
+ }
2069
+ };
2070
+ }
1711
2071
  function applyBatchSystemField(params, request) {
1712
2072
  const systemText = buildBatchSystemText(request);
1713
2073
  if (systemText.length === 0) {
@@ -1723,7 +2083,7 @@ function applyBatchSystemField(params, request) {
1723
2083
  }
1724
2084
  function buildBatchSystemText(request) {
1725
2085
  const joinedSystemText = joinBatchSystemMessageText(request.messages);
1726
- if (request.requireJsonResponse !== true) {
2086
+ if (request.requireJsonResponse !== true || request.structuredOutputJsonSchema !== void 0) {
1727
2087
  return joinedSystemText;
1728
2088
  }
1729
2089
  if (joinedSystemText.length === 0) {
@@ -1877,55 +2237,55 @@ function buildBatchResultEvent(eventBase, batchId, result, modelName) {
1877
2237
  }
1878
2238
 
1879
2239
  // src/anthropic-batch-types.ts
1880
- import { z as z7 } from "zod";
1881
- var AnthropicMessageBatchResponseSchema = z7.object({
1882
- id: z7.string(),
1883
- processing_status: z7.enum(["in_progress", "canceling", "ended"]),
1884
- request_counts: z7.object({
1885
- processing: z7.number().int().nonnegative(),
1886
- succeeded: z7.number().int().nonnegative(),
1887
- errored: z7.number().int().nonnegative(),
1888
- canceled: z7.number().int().nonnegative(),
1889
- expired: z7.number().int().nonnegative()
2240
+ import { z as z8 } from "zod";
2241
+ var AnthropicMessageBatchResponseSchema = z8.object({
2242
+ id: z8.string(),
2243
+ processing_status: z8.enum(["in_progress", "canceling", "ended"]),
2244
+ request_counts: z8.object({
2245
+ processing: z8.number().int().nonnegative(),
2246
+ succeeded: z8.number().int().nonnegative(),
2247
+ errored: z8.number().int().nonnegative(),
2248
+ canceled: z8.number().int().nonnegative(),
2249
+ expired: z8.number().int().nonnegative()
1890
2250
  }),
1891
- results_url: z7.string().nullable(),
1892
- created_at: z7.string(),
1893
- ended_at: z7.string().nullable()
2251
+ results_url: z8.string().nullable(),
2252
+ created_at: z8.string(),
2253
+ ended_at: z8.string().nullable()
1894
2254
  });
1895
- var AnthropicBatchContentBlockSchema = z7.discriminatedUnion("type", [
1896
- z7.object({
1897
- type: z7.literal("text"),
1898
- text: z7.string()
2255
+ var AnthropicBatchContentBlockSchema = z8.discriminatedUnion("type", [
2256
+ z8.object({
2257
+ type: z8.literal("text"),
2258
+ text: z8.string()
1899
2259
  }),
1900
- z7.object({
1901
- type: z7.literal("thinking"),
1902
- thinking: z7.string().optional(),
1903
- signature: z7.string().optional()
2260
+ z8.object({
2261
+ type: z8.literal("thinking"),
2262
+ thinking: z8.string().optional(),
2263
+ signature: z8.string().optional()
1904
2264
  }),
1905
- z7.object({
1906
- type: z7.literal("redacted_thinking"),
1907
- data: z7.string().optional()
2265
+ z8.object({
2266
+ type: z8.literal("redacted_thinking"),
2267
+ data: z8.string().optional()
1908
2268
  })
1909
2269
  ]);
1910
- var AnthropicBatchResultLineSchema = z7.object({
1911
- custom_id: z7.string(),
1912
- result: z7.discriminatedUnion("type", [
1913
- z7.object({
1914
- type: z7.literal("succeeded"),
1915
- message: z7.object({
1916
- content: z7.array(AnthropicBatchContentBlockSchema),
2270
+ var AnthropicBatchResultLineSchema = z8.object({
2271
+ custom_id: z8.string(),
2272
+ result: z8.discriminatedUnion("type", [
2273
+ z8.object({
2274
+ type: z8.literal("succeeded"),
2275
+ message: z8.object({
2276
+ content: z8.array(AnthropicBatchContentBlockSchema),
1917
2277
  usage: AnthropicUsageSchema
1918
2278
  })
1919
2279
  }),
1920
- z7.object({
1921
- type: z7.literal("errored"),
1922
- error: z7.object({
1923
- type: z7.string(),
1924
- message: z7.string()
2280
+ z8.object({
2281
+ type: z8.literal("errored"),
2282
+ error: z8.object({
2283
+ type: z8.string(),
2284
+ message: z8.string()
1925
2285
  })
1926
2286
  }),
1927
- z7.object({ type: z7.literal("canceled") }),
1928
- z7.object({ type: z7.literal("expired") })
2287
+ z8.object({ type: z8.literal("canceled") }),
2288
+ z8.object({ type: z8.literal("expired") })
1929
2289
  ])
1930
2290
  });
1931
2291
  function mapAnthropicMessageBatchResponseToMessageBatch(response) {
@@ -2075,8 +2435,8 @@ async function parseAnthropicMessageBatchHttpResponse(response) {
2075
2435
  async function listAnthropicMessageBatchResults(clientContext, batchId) {
2076
2436
  const batch = await fetchAnthropicMessageBatch(clientContext, batchId);
2077
2437
  if (batch.resultsUrl === null) {
2078
- throw new AppError14({
2079
- code: AppErrorCode13.Conflict,
2438
+ throw new AppError15({
2439
+ code: AppErrorCode14.Conflict,
2080
2440
  message: `Anthropic message batch ${batchId} has no results because processing has not ended`,
2081
2441
  statusCode: 409,
2082
2442
  details: { batchId, processingStatus: batch.processingStatus }
@@ -2137,16 +2497,760 @@ async function waitForAnthropicMessageBatchCompletion(clientContext, batchId, wa
2137
2497
  return batch;
2138
2498
  }
2139
2499
  function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
2140
- return new AppError14({
2141
- code: AppErrorCode13.ServiceUnavailable,
2500
+ return new AppError15({
2501
+ code: AppErrorCode14.ServiceUnavailable,
2142
2502
  message: `Anthropic message batch ${batchId} did not complete within ${String(timeoutMs)}ms`,
2143
2503
  statusCode: 504,
2144
2504
  details: { batchId, timeoutMs }
2145
2505
  });
2146
2506
  }
2507
+
2508
+ // src/azure-openai-adapter.ts
2509
+ import { AppErrorCode as AppErrorCode16 } from "@assemble-dev/shared-types/errors";
2510
+ import { AppError as AppError17 } from "@assemble-dev/shared-utils/errors";
2511
+
2512
+ // src/azure-openai-response-parsing.ts
2513
+ import { z as z9 } from "zod";
2514
+ import { AppErrorCode as AppErrorCode15 } from "@assemble-dev/shared-types/errors";
2515
+ import { JsonValueSchema as JsonValueSchema8 } from "@assemble-dev/shared-types/json";
2516
+ import { AppError as AppError16 } from "@assemble-dev/shared-utils/errors";
2517
+ var AzureOpenAiUsageSchema = z9.object({
2518
+ prompt_tokens: z9.number().int().nonnegative(),
2519
+ completion_tokens: z9.number().int().nonnegative(),
2520
+ total_tokens: z9.number().int().nonnegative()
2521
+ });
2522
+ var AzureOpenAiResponseToolCallSchema = z9.object({
2523
+ id: z9.string(),
2524
+ function: z9.object({
2525
+ name: z9.string(),
2526
+ arguments: z9.string()
2527
+ })
2528
+ });
2529
+ var AzureOpenAiChatCompletionResponseSchema = z9.object({
2530
+ choices: z9.array(
2531
+ z9.object({
2532
+ message: z9.object({
2533
+ content: z9.string().nullable(),
2534
+ tool_calls: z9.array(AzureOpenAiResponseToolCallSchema).optional()
2535
+ }),
2536
+ finish_reason: z9.string().nullable().optional()
2537
+ })
2538
+ ).min(1),
2539
+ usage: AzureOpenAiUsageSchema
2540
+ });
2541
+ function mapAzureOpenAiResponseToChatCompletionResult(response, latencyMs) {
2542
+ const toolCalls = extractAzureOpenAiToolCalls(response);
2543
+ const result = {
2544
+ content: extractAzureOpenAiMessageContent(response, toolCalls.length > 0),
2545
+ tokenUsage: mapAzureOpenAiUsageToTokenUsage(response.usage),
2546
+ latencyMs
2547
+ };
2548
+ const finishReason = response.choices[0]?.finish_reason;
2549
+ if (toolCalls.length > 0) {
2550
+ result.toolCalls = toolCalls;
2551
+ }
2552
+ if (finishReason !== null && finishReason !== void 0) {
2553
+ result.stopReason = normalizeAzureOpenAiFinishReason(finishReason);
2554
+ }
2555
+ return result;
2556
+ }
2557
+ function extractAzureOpenAiToolCalls(response) {
2558
+ const responseToolCalls = response.choices[0]?.message.tool_calls ?? [];
2559
+ return responseToolCalls.map((responseToolCall) => ({
2560
+ id: responseToolCall.id,
2561
+ toolName: responseToolCall.function.name,
2562
+ input: parseAzureOpenAiToolArgumentsJson(responseToolCall.function.arguments)
2563
+ }));
2564
+ }
2565
+ function parseAzureOpenAiToolArgumentsJson(argumentsJsonText) {
2566
+ if (argumentsJsonText.trim().length === 0) {
2567
+ return {};
2568
+ }
2569
+ try {
2570
+ return JsonValueSchema8.parse(JSON.parse(argumentsJsonText));
2571
+ } catch (error) {
2572
+ throw new AppError16({
2573
+ code: AppErrorCode15.ValidationFailed,
2574
+ message: "Azure OpenAI tool call arguments were not valid JSON",
2575
+ statusCode: 502,
2576
+ cause: error instanceof Error ? error : void 0
2577
+ });
2578
+ }
2579
+ }
2580
+ function normalizeAzureOpenAiFinishReason(finishReason) {
2581
+ if (finishReason === "tool_calls") {
2582
+ return "tool_use";
2583
+ }
2584
+ if (finishReason === "length") {
2585
+ return "max_tokens";
2586
+ }
2587
+ return "end_turn";
2588
+ }
2589
+ function extractAzureOpenAiMessageContent(response, allowEmptyContent) {
2590
+ const content = response.choices[0]?.message.content;
2591
+ if (content === void 0 || content === null) {
2592
+ if (allowEmptyContent) {
2593
+ return "";
2594
+ }
2595
+ throw new AppError16({
2596
+ code: AppErrorCode15.ValidationFailed,
2597
+ message: "Azure OpenAI response contained no message content",
2598
+ statusCode: 502
2599
+ });
2600
+ }
2601
+ return content;
2602
+ }
2603
+ function mapAzureOpenAiUsageToTokenUsage(usage) {
2604
+ return {
2605
+ inputTokens: usage.prompt_tokens,
2606
+ outputTokens: usage.completion_tokens,
2607
+ totalTokens: usage.total_tokens
2608
+ };
2609
+ }
2610
+
2611
+ // src/azure-openai-stream.ts
2612
+ import { z as z10 } from "zod";
2613
+ var AzureOpenAiStreamToolCallDeltaSchema = z10.object({
2614
+ index: z10.number().int().nonnegative(),
2615
+ id: z10.string().optional(),
2616
+ function: z10.object({
2617
+ name: z10.string().optional(),
2618
+ arguments: z10.string().optional()
2619
+ }).optional()
2620
+ });
2621
+ var AzureOpenAiStreamChunkSchema = z10.object({
2622
+ choices: z10.array(
2623
+ z10.object({
2624
+ delta: z10.object({
2625
+ content: z10.string().nullable().optional(),
2626
+ tool_calls: z10.array(AzureOpenAiStreamToolCallDeltaSchema).optional()
2627
+ }).optional(),
2628
+ finish_reason: z10.string().nullable().optional()
2629
+ })
2630
+ ).optional(),
2631
+ usage: AzureOpenAiUsageSchema.nullable().optional()
2632
+ });
2633
+ async function* streamAzureOpenAiChatCompletion(input) {
2634
+ const startedAt = Date.now();
2635
+ const response = await establishAzureOpenAiStreamResponse(input);
2636
+ if (response.body === null) {
2637
+ throw buildProviderInvalidResponseError("Azure OpenAI", "stream body");
2638
+ }
2639
+ yield* parseAzureOpenAiStreamEvents(
2640
+ response.body,
2641
+ startedAt,
2642
+ input.abortSignal
2643
+ );
2644
+ }
2645
+ async function establishAzureOpenAiStreamResponse(input) {
2646
+ return await executeProviderCallWithRetry(input.retry, async () => {
2647
+ const response = await executeAbortableProviderFetch(
2648
+ "Azure OpenAI",
2649
+ async () => await input.fetchImplementation(input.url, {
2650
+ method: "POST",
2651
+ headers: input.headers,
2652
+ body: JSON.stringify(input.body),
2653
+ signal: input.abortSignal
2654
+ })
2655
+ );
2656
+ if (!response.ok) {
2657
+ throw buildProviderStatusError("Azure OpenAI", response.status);
2658
+ }
2659
+ return response;
2660
+ });
2661
+ }
2662
+ async function* parseAzureOpenAiStreamEvents(body, startedAt, abortSignal) {
2663
+ const accumulator = createAzureOpenAiStreamAccumulator();
2664
+ for await (const dataText of readServerSentEventDataLines2(body, abortSignal)) {
2665
+ if (dataText === "[DONE]") {
2666
+ yield {
2667
+ type: "completed",
2668
+ result: buildAzureOpenAiStreamResult(
2669
+ accumulator,
2670
+ Date.now() - startedAt
2671
+ )
2672
+ };
2673
+ return;
2674
+ }
2675
+ const parsedChunk = AzureOpenAiStreamChunkSchema.safeParse(
2676
+ JSON.parse(dataText)
2677
+ );
2678
+ if (!parsedChunk.success) {
2679
+ continue;
2680
+ }
2681
+ yield* applyAzureOpenAiStreamChunk(parsedChunk.data, accumulator);
2682
+ }
2683
+ throw buildProviderInvalidResponseError("Azure OpenAI", "stream termination");
2684
+ }
2685
+ async function* readServerSentEventDataLines2(body, abortSignal) {
2686
+ const reader = body.getReader();
2687
+ const decoder = new TextDecoder();
2688
+ let bufferedText = "";
2689
+ try {
2690
+ for (; ; ) {
2691
+ if (abortSignal?.aborted === true) {
2692
+ await reader.cancel();
2693
+ throw buildProviderCanceledError("Azure OpenAI");
2694
+ }
2695
+ const readResult = await reader.read();
2696
+ if (readResult.done) {
2697
+ return;
2698
+ }
2699
+ bufferedText += decoder.decode(readResult.value, { stream: true });
2700
+ const lines = bufferedText.split("\n");
2701
+ bufferedText = lines.pop() ?? "";
2702
+ for (const line of lines) {
2703
+ if (line.startsWith("data:")) {
2704
+ const dataText = line.slice("data:".length).trim();
2705
+ if (dataText.length > 0) {
2706
+ yield dataText;
2707
+ }
2708
+ }
2709
+ }
2710
+ }
2711
+ } catch (error) {
2712
+ if (error instanceof Error && isAbortError(error)) {
2713
+ throw buildProviderCanceledError("Azure OpenAI");
2714
+ }
2715
+ throw error;
2716
+ }
2717
+ }
2718
+ function createAzureOpenAiStreamAccumulator() {
2719
+ return {
2720
+ contentText: "",
2721
+ toolCallsByIndex: /* @__PURE__ */ new Map()
2722
+ };
2723
+ }
2724
+ function* applyAzureOpenAiStreamChunk(chunk, accumulator) {
2725
+ if (chunk.usage !== null && chunk.usage !== void 0) {
2726
+ accumulator.usage = chunk.usage;
2727
+ }
2728
+ const choice = chunk.choices?.[0];
2729
+ if (choice === void 0) {
2730
+ return;
2731
+ }
2732
+ if (choice.finish_reason !== null && choice.finish_reason !== void 0) {
2733
+ accumulator.finishReason = choice.finish_reason;
2734
+ }
2735
+ if (choice.delta === void 0) {
2736
+ return;
2737
+ }
2738
+ const contentDelta = choice.delta.content;
2739
+ if (contentDelta !== null && contentDelta !== void 0 && contentDelta.length > 0) {
2740
+ accumulator.contentText += contentDelta;
2741
+ yield { type: "text_delta", text: contentDelta };
2742
+ }
2743
+ for (const toolCallDelta of choice.delta.tool_calls ?? []) {
2744
+ yield* applyAzureOpenAiToolCallDelta(toolCallDelta, accumulator);
2745
+ }
2746
+ }
2747
+ function* applyAzureOpenAiToolCallDelta(toolCallDelta, accumulator) {
2748
+ const existingToolCall = accumulator.toolCallsByIndex.get(toolCallDelta.index);
2749
+ if (existingToolCall === void 0) {
2750
+ yield* startAzureOpenAiToolCallAccumulation(toolCallDelta, accumulator);
2751
+ return;
2752
+ }
2753
+ const argumentsDelta = toolCallDelta.function?.arguments;
2754
+ if (argumentsDelta !== void 0 && argumentsDelta.length > 0) {
2755
+ existingToolCall.argumentsJsonText += argumentsDelta;
2756
+ yield {
2757
+ type: "tool_call_input_delta",
2758
+ id: existingToolCall.id,
2759
+ inputJsonText: argumentsDelta
2760
+ };
2761
+ }
2762
+ }
2763
+ function* startAzureOpenAiToolCallAccumulation(toolCallDelta, accumulator) {
2764
+ const toolName = toolCallDelta.function?.name;
2765
+ if (toolCallDelta.id === void 0 || toolName === void 0) {
2766
+ throw buildProviderInvalidResponseError(
2767
+ "Azure OpenAI",
2768
+ "stream tool call start"
2769
+ );
2770
+ }
2771
+ const startedToolCall = {
2772
+ id: toolCallDelta.id,
2773
+ toolName,
2774
+ argumentsJsonText: toolCallDelta.function?.arguments ?? ""
2775
+ };
2776
+ accumulator.toolCallsByIndex.set(toolCallDelta.index, startedToolCall);
2777
+ yield {
2778
+ type: "tool_call_started",
2779
+ id: startedToolCall.id,
2780
+ toolName: startedToolCall.toolName
2781
+ };
2782
+ if (startedToolCall.argumentsJsonText.length > 0) {
2783
+ yield {
2784
+ type: "tool_call_input_delta",
2785
+ id: startedToolCall.id,
2786
+ inputJsonText: startedToolCall.argumentsJsonText
2787
+ };
2788
+ }
2789
+ }
2790
+ function buildAzureOpenAiStreamResult(accumulator, latencyMs) {
2791
+ const result = {
2792
+ content: accumulator.contentText,
2793
+ tokenUsage: mapAzureOpenAiUsageToTokenUsage(
2794
+ accumulator.usage ?? {
2795
+ prompt_tokens: 0,
2796
+ completion_tokens: 0,
2797
+ total_tokens: 0
2798
+ }
2799
+ ),
2800
+ latencyMs
2801
+ };
2802
+ const toolCalls = [...accumulator.toolCallsByIndex.values()].map(
2803
+ mapAccumulatedToolCallToModelToolCall2
2804
+ );
2805
+ if (toolCalls.length > 0) {
2806
+ result.toolCalls = toolCalls;
2807
+ }
2808
+ if (accumulator.finishReason !== void 0) {
2809
+ result.stopReason = normalizeAzureOpenAiFinishReason(
2810
+ accumulator.finishReason
2811
+ );
2812
+ }
2813
+ return result;
2814
+ }
2815
+ function mapAccumulatedToolCallToModelToolCall2(toolCallAccumulation) {
2816
+ return {
2817
+ id: toolCallAccumulation.id,
2818
+ toolName: toolCallAccumulation.toolName,
2819
+ input: parseAzureOpenAiToolArgumentsJson(
2820
+ toolCallAccumulation.argumentsJsonText
2821
+ )
2822
+ };
2823
+ }
2824
+
2825
+ // src/azure-openai-adapter.ts
2826
+ var defaultAzureOpenAiApiVersion = "2024-10-21";
2827
+ var azureDeploymentModelPlaceholder = "azure-deployment";
2828
+ function azureOpenai(options) {
2829
+ return {
2830
+ name: `azure-openai:${options.deployment}`,
2831
+ async generateChatCompletion(request) {
2832
+ return await executeAzureOpenAiAdapterCall(options, {
2833
+ messages: request.messages,
2834
+ temperature: request.temperature ?? options.temperature,
2835
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
2836
+ tools: request.tools,
2837
+ toolChoice: request.toolChoice,
2838
+ abortSignal: request.abortSignal,
2839
+ extraBody: request.extraBody
2840
+ });
2841
+ },
2842
+ async generateStructuredOutput(request) {
2843
+ const completion = await executeAzureOpenAiAdapterCall(options, {
2844
+ messages: request.messages,
2845
+ temperature: request.temperature ?? options.temperature,
2846
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
2847
+ structuredOutputJsonSchema: buildOpenAiStructuredOutputJsonSchema(
2848
+ request.schema
2849
+ ),
2850
+ abortSignal: request.abortSignal
2851
+ });
2852
+ return {
2853
+ value: parseStructuredJsonText(completion.content, request.schema),
2854
+ tokenUsage: completion.tokenUsage,
2855
+ latencyMs: completion.latencyMs
2856
+ };
2857
+ },
2858
+ streamChatCompletion(request) {
2859
+ return streamAzureOpenAiChatCompletion(
2860
+ buildAzureOpenAiStreamInput(options, request)
2861
+ );
2862
+ }
2863
+ };
2864
+ }
2865
+ function buildAzureOpenAiChatCompletionsUrl(options) {
2866
+ const endpoint = resolveAzureOpenAiEndpoint(options);
2867
+ const apiVersion = options.apiVersion ?? defaultAzureOpenAiApiVersion;
2868
+ return `${endpoint}/openai/deployments/${encodeURIComponent(options.deployment)}/chat/completions?api-version=${encodeURIComponent(apiVersion)}`;
2869
+ }
2870
+ function resolveAzureOpenAiEndpoint(options) {
2871
+ if (options.baseURL !== void 0 && options.baseURL.length > 0) {
2872
+ return options.baseURL.replace(/\/+$/, "");
2873
+ }
2874
+ if (options.resourceName !== void 0 && options.resourceName.length > 0) {
2875
+ return `https://${options.resourceName}.openai.azure.com`;
2876
+ }
2877
+ throw new AppError17({
2878
+ code: AppErrorCode16.BadRequest,
2879
+ message: "Azure OpenAI endpoint is missing. Pass resourceName or baseURL to azureOpenai().",
2880
+ statusCode: 400
2881
+ });
2882
+ }
2883
+ function buildAzureOpenAiRequestHeaders(options) {
2884
+ return {
2885
+ "content-type": "application/json",
2886
+ "api-key": resolveProviderApiKey({
2887
+ providerLabel: "Azure OpenAI",
2888
+ adapterFunctionName: "azureOpenai()",
2889
+ baseEnvVarName: "AZURE_OPENAI_API_KEY",
2890
+ apiKey: options.apiKey,
2891
+ apiKeyName: options.apiKeyName
2892
+ })
2893
+ };
2894
+ }
2895
+ function buildAzureOpenAiChatRequestBody(input) {
2896
+ const requestBody = buildOpenAiRequestBody(
2897
+ azureDeploymentModelPlaceholder,
2898
+ input
2899
+ );
2900
+ const { model: ignoredModel, ...requestBodyWithoutModel } = requestBody;
2901
+ void ignoredModel;
2902
+ return requestBodyWithoutModel;
2903
+ }
2904
+ async function executeAzureOpenAiAdapterCall(options, input) {
2905
+ return await executeProviderCallWithRetry(
2906
+ options.retry,
2907
+ async () => await requestAzureOpenAiChatCompletion(options, input)
2908
+ );
2909
+ }
2910
+ async function requestAzureOpenAiChatCompletion(options, input) {
2911
+ const fetchImplementation = options.fetchImplementation ?? fetch;
2912
+ const requestBody = mergeProviderRequestExtraBody(
2913
+ buildAzureOpenAiChatRequestBody(input),
2914
+ options.extraBody,
2915
+ input.extraBody
2916
+ );
2917
+ const startedAt = Date.now();
2918
+ const response = await executeAbortableProviderFetch(
2919
+ "Azure OpenAI",
2920
+ async () => await fetchImplementation(buildAzureOpenAiChatCompletionsUrl(options), {
2921
+ method: "POST",
2922
+ headers: buildAzureOpenAiRequestHeaders(options),
2923
+ body: JSON.stringify(requestBody),
2924
+ signal: input.abortSignal
2925
+ })
2926
+ );
2927
+ const latencyMs = Date.now() - startedAt;
2928
+ if (!response.ok) {
2929
+ throw buildProviderStatusError("Azure OpenAI", response.status);
2930
+ }
2931
+ const parseResult = AzureOpenAiChatCompletionResponseSchema.safeParse(
2932
+ await response.json()
2933
+ );
2934
+ if (!parseResult.success) {
2935
+ throw buildProviderInvalidResponseError("Azure OpenAI", "chat completion");
2936
+ }
2937
+ return mapAzureOpenAiResponseToChatCompletionResult(
2938
+ parseResult.data,
2939
+ latencyMs
2940
+ );
2941
+ }
2942
+ function buildAzureOpenAiStreamInput(options, request) {
2943
+ const requestBody = mergeProviderRequestExtraBody(
2944
+ buildAzureOpenAiChatRequestBody({
2945
+ messages: request.messages,
2946
+ temperature: request.temperature ?? options.temperature,
2947
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
2948
+ tools: request.tools,
2949
+ toolChoice: request.toolChoice,
2950
+ abortSignal: request.abortSignal,
2951
+ extraBody: request.extraBody
2952
+ }),
2953
+ options.extraBody,
2954
+ request.extraBody
2955
+ );
2956
+ return {
2957
+ url: buildAzureOpenAiChatCompletionsUrl(options),
2958
+ headers: buildAzureOpenAiRequestHeaders(options),
2959
+ body: {
2960
+ ...requestBody,
2961
+ stream: true,
2962
+ stream_options: { include_usage: true }
2963
+ },
2964
+ fetchImplementation: options.fetchImplementation ?? fetch,
2965
+ retry: options.retry,
2966
+ abortSignal: request.abortSignal
2967
+ };
2968
+ }
2969
+
2970
+ // src/bedrock-adapter.ts
2971
+ import { z as z11 } from "zod";
2972
+ import { AppErrorCode as AppErrorCode17 } from "@assemble-dev/shared-types/errors";
2973
+ import { AppError as AppError18 } from "@assemble-dev/shared-utils/errors";
2974
+
2975
+ // src/bedrock-sigv4.ts
2976
+ var awsSigV4Algorithm = "AWS4-HMAC-SHA256";
2977
+ async function signAwsRequestWithSigV4(input) {
2978
+ const amzDate = formatAmzDateTime(input.signingDate ?? /* @__PURE__ */ new Date());
2979
+ const dateStamp = amzDate.slice(0, 8);
2980
+ const headersToSign = buildHeadersToSign(input, amzDate);
2981
+ const canonicalHeaderEntries = buildCanonicalHeaderEntries(headersToSign);
2982
+ const signedHeaderNames = canonicalHeaderEntries.map(([headerName]) => headerName).join(";");
2983
+ const credentialScope = `${dateStamp}/${input.region}/${input.service}/aws4_request`;
2984
+ const signatureHex = await computeAwsSigV4Signature(
2985
+ input,
2986
+ amzDate,
2987
+ credentialScope,
2988
+ canonicalHeaderEntries,
2989
+ signedHeaderNames
2990
+ );
2991
+ return {
2992
+ ...headersToSign,
2993
+ authorization: `${awsSigV4Algorithm} Credential=${input.credentials.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaderNames}, Signature=${signatureHex}`
2994
+ };
2995
+ }
2996
+ async function computeAwsSigV4Signature(input, amzDate, credentialScope, canonicalHeaderEntries, signedHeaderNames) {
2997
+ const canonicalRequest = await buildCanonicalRequest(
2998
+ input,
2999
+ canonicalHeaderEntries,
3000
+ signedHeaderNames
3001
+ );
3002
+ const stringToSign = [
3003
+ awsSigV4Algorithm,
3004
+ amzDate,
3005
+ credentialScope,
3006
+ await hashSha256Hex(canonicalRequest)
3007
+ ].join("\n");
3008
+ const signingKey = await deriveAwsSigningKey(
3009
+ input.credentials.secretAccessKey,
3010
+ amzDate.slice(0, 8),
3011
+ input.region,
3012
+ input.service
3013
+ );
3014
+ return bytesToHex(await computeHmacSha256(signingKey, stringToSign));
3015
+ }
3016
+ function buildHeadersToSign(input, amzDate) {
3017
+ const headersToSign = {};
3018
+ for (const [headerName, headerValue] of Object.entries(input.headers)) {
3019
+ headersToSign[headerName.toLowerCase()] = headerValue;
3020
+ }
3021
+ headersToSign.host = input.url.host;
3022
+ headersToSign["x-amz-date"] = amzDate;
3023
+ if (input.credentials.sessionToken !== void 0) {
3024
+ headersToSign["x-amz-security-token"] = input.credentials.sessionToken;
3025
+ }
3026
+ return headersToSign;
3027
+ }
3028
+ function buildCanonicalHeaderEntries(headersToSign) {
3029
+ return Object.entries(headersToSign).map(([headerName, headerValue]) => [
3030
+ headerName.toLowerCase(),
3031
+ headerValue.trim().replace(/\s+/g, " ")
3032
+ ]).sort(([leftName], [rightName]) => leftName.localeCompare(rightName));
3033
+ }
3034
+ async function buildCanonicalRequest(input, canonicalHeaderEntries, signedHeaderNames) {
3035
+ const canonicalHeadersText = canonicalHeaderEntries.map(([headerName, headerValue]) => `${headerName}:${headerValue}`).join("\n");
3036
+ return [
3037
+ input.method.toUpperCase(),
3038
+ buildCanonicalUri(input.url.pathname),
3039
+ buildCanonicalQueryString(input.url.searchParams),
3040
+ `${canonicalHeadersText}
3041
+ `,
3042
+ signedHeaderNames,
3043
+ await hashSha256Hex(input.bodyText)
3044
+ ].join("\n");
3045
+ }
3046
+ function buildCanonicalUri(pathname) {
3047
+ if (pathname.length === 0) {
3048
+ return "/";
3049
+ }
3050
+ return pathname.split("/").map(encodeRfc3986UriComponent).join("/");
3051
+ }
3052
+ function buildCanonicalQueryString(searchParams) {
3053
+ const encodedEntries = [];
3054
+ searchParams.forEach((parameterValue, parameterName) => {
3055
+ encodedEntries.push([
3056
+ encodeRfc3986UriComponent(parameterName),
3057
+ encodeRfc3986UriComponent(parameterValue)
3058
+ ]);
3059
+ });
3060
+ return encodedEntries.sort(
3061
+ ([leftName, leftValue], [rightName, rightValue]) => leftName.localeCompare(rightName) || leftValue.localeCompare(rightValue)
3062
+ ).map(([parameterName, parameterValue]) => `${parameterName}=${parameterValue}`).join("&");
3063
+ }
3064
+ function encodeRfc3986UriComponent(value) {
3065
+ return encodeURIComponent(value).replace(
3066
+ /[!'()*]/g,
3067
+ (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`
3068
+ );
3069
+ }
3070
+ function formatAmzDateTime(date) {
3071
+ return date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
3072
+ }
3073
+ async function deriveAwsSigningKey(secretAccessKey, dateStamp, region, service) {
3074
+ const dateKey = await computeHmacSha256(
3075
+ new TextEncoder().encode(`AWS4${secretAccessKey}`),
3076
+ dateStamp
3077
+ );
3078
+ const regionKey = await computeHmacSha256(dateKey, region);
3079
+ const serviceKey = await computeHmacSha256(regionKey, service);
3080
+ return await computeHmacSha256(serviceKey, "aws4_request");
3081
+ }
3082
+ async function hashSha256Hex(text) {
3083
+ const digest = await crypto.subtle.digest(
3084
+ "SHA-256",
3085
+ new TextEncoder().encode(text)
3086
+ );
3087
+ return bytesToHex(new Uint8Array(digest));
3088
+ }
3089
+ async function computeHmacSha256(keyBytes, text) {
3090
+ const hmacKey = await crypto.subtle.importKey(
3091
+ "raw",
3092
+ keyBytes,
3093
+ { name: "HMAC", hash: "SHA-256" },
3094
+ false,
3095
+ ["sign"]
3096
+ );
3097
+ const signature = await crypto.subtle.sign(
3098
+ "HMAC",
3099
+ hmacKey,
3100
+ new TextEncoder().encode(text)
3101
+ );
3102
+ return new Uint8Array(signature);
3103
+ }
3104
+ function bytesToHex(bytes) {
3105
+ return Array.from(bytes).map((byteValue) => byteValue.toString(16).padStart(2, "0")).join("");
3106
+ }
3107
+
3108
+ // src/bedrock-adapter.ts
3109
+ var bedrockAnthropicVersion = "bedrock-2023-05-31";
3110
+ var defaultBedrockMaxOutputTokens = 1024;
3111
+ var bedrockSigningServiceName = "bedrock";
3112
+ var bedrockModelPlaceholder = "bedrock-invoke-model";
3113
+ var BedrockEnvCredentialsSchema = z11.object({
3114
+ AWS_ACCESS_KEY_ID: z11.string().optional(),
3115
+ AWS_SECRET_ACCESS_KEY: z11.string().optional(),
3116
+ AWS_SESSION_TOKEN: z11.string().optional()
3117
+ });
3118
+ function bedrock(options) {
3119
+ return {
3120
+ name: `bedrock:${options.modelId}`,
3121
+ async generateChatCompletion(request) {
3122
+ return await executeBedrockAdapterCall(options, {
3123
+ messages: request.messages,
3124
+ temperature: request.temperature ?? options.temperature,
3125
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
3126
+ tools: request.tools,
3127
+ toolChoice: request.toolChoice,
3128
+ abortSignal: request.abortSignal,
3129
+ extraBody: request.extraBody
3130
+ });
3131
+ },
3132
+ async generateStructuredOutput(request) {
3133
+ const completion = await executeBedrockAdapterCall(options, {
3134
+ messages: [
3135
+ buildBedrockStructuredOutputSystemMessage(request.schema),
3136
+ ...request.messages
3137
+ ],
3138
+ temperature: request.temperature ?? options.temperature,
3139
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
3140
+ abortSignal: request.abortSignal
3141
+ });
3142
+ return {
3143
+ value: parseStructuredJsonText(completion.content, request.schema),
3144
+ tokenUsage: completion.tokenUsage,
3145
+ latencyMs: completion.latencyMs
3146
+ };
3147
+ }
3148
+ };
3149
+ }
3150
+ function buildBedrockInvokeModelUrl(region, modelId) {
3151
+ return `https://bedrock-runtime.${region}.amazonaws.com/model/${encodeURIComponent(modelId)}/invoke`;
3152
+ }
3153
+ function resolveBedrockCredentials(options) {
3154
+ if (options.credentials !== void 0) {
3155
+ return options.credentials;
3156
+ }
3157
+ const parsedEnv = BedrockEnvCredentialsSchema.parse(process.env);
3158
+ const accessKeyId = parsedEnv.AWS_ACCESS_KEY_ID;
3159
+ const secretAccessKey = parsedEnv.AWS_SECRET_ACCESS_KEY;
3160
+ if (accessKeyId === void 0 || accessKeyId.length === 0 || secretAccessKey === void 0 || secretAccessKey.length === 0) {
3161
+ throw new AppError18({
3162
+ code: AppErrorCode17.Unauthorized,
3163
+ message: "AWS credentials are missing. Pass credentials to bedrock() or set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.",
3164
+ statusCode: 401
3165
+ });
3166
+ }
3167
+ const credentials = { accessKeyId, secretAccessKey };
3168
+ const sessionToken = parsedEnv.AWS_SESSION_TOKEN;
3169
+ if (sessionToken !== void 0 && sessionToken.length > 0) {
3170
+ credentials.sessionToken = sessionToken;
3171
+ }
3172
+ return credentials;
3173
+ }
3174
+ async function executeBedrockAdapterCall(options, input) {
3175
+ return await executeProviderCallWithRetry(
3176
+ options.retry,
3177
+ async () => await requestBedrockInvokeModel(options, input)
3178
+ );
3179
+ }
3180
+ async function requestBedrockInvokeModel(options, input) {
3181
+ const credentials = resolveBedrockCredentials(options);
3182
+ const fetchImplementation = options.fetchImplementation ?? fetch;
3183
+ const requestBody = mergeProviderRequestExtraBody(
3184
+ buildBedrockInvokeModelRequestBody(input),
3185
+ options.extraBody,
3186
+ input.extraBody
3187
+ );
3188
+ const bodyText = JSON.stringify(requestBody);
3189
+ const url = new URL(buildBedrockInvokeModelUrl(options.region, options.modelId));
3190
+ const signedHeaders = await signAwsRequestWithSigV4({
3191
+ method: "POST",
3192
+ url,
3193
+ headers: { "content-type": "application/json" },
3194
+ bodyText,
3195
+ region: options.region,
3196
+ service: bedrockSigningServiceName,
3197
+ credentials
3198
+ });
3199
+ const startedAt = Date.now();
3200
+ const response = await executeAbortableProviderFetch(
3201
+ "Bedrock",
3202
+ async () => await fetchImplementation(url.toString(), {
3203
+ method: "POST",
3204
+ headers: signedHeaders,
3205
+ body: bodyText,
3206
+ signal: input.abortSignal
3207
+ })
3208
+ );
3209
+ const latencyMs = Date.now() - startedAt;
3210
+ if (!response.ok) {
3211
+ throw buildProviderStatusError("Bedrock", response.status);
3212
+ }
3213
+ const parseResult = AnthropicMessagesResponseSchema.safeParse(
3214
+ await response.json()
3215
+ );
3216
+ if (!parseResult.success) {
3217
+ throw buildProviderInvalidResponseError("Bedrock", "invoke model");
3218
+ }
3219
+ return mapAnthropicResponseToChatCompletionResult(parseResult.data, latencyMs);
3220
+ }
3221
+ function buildBedrockInvokeModelRequestBody(input) {
3222
+ const anthropicRequestBody = buildAnthropicRequestBody(
3223
+ {
3224
+ model: bedrockModelPlaceholder,
3225
+ defaultMaxOutputTokens: defaultBedrockMaxOutputTokens
3226
+ },
3227
+ input
3228
+ );
3229
+ const {
3230
+ model: ignoredModel,
3231
+ stream: ignoredStream,
3232
+ ...requestBodyWithoutModel
3233
+ } = anthropicRequestBody;
3234
+ void ignoredModel;
3235
+ void ignoredStream;
3236
+ return {
3237
+ ...requestBodyWithoutModel,
3238
+ anthropic_version: bedrockAnthropicVersion
3239
+ };
3240
+ }
3241
+ function buildBedrockStructuredOutputSystemMessage(schema) {
3242
+ return {
3243
+ role: "system",
3244
+ content: `Respond with a single JSON object that satisfies the following JSON Schema. Output only valid JSON with no surrounding text.
3245
+
3246
+ JSON Schema:
3247
+ ${JSON.stringify(convertZodSchemaToJsonSchema(schema))}`
3248
+ };
3249
+ }
2147
3250
  export {
2148
3251
  AnthropicMessagesResponseSchema,
2149
3252
  AnthropicStreamEventSchema,
3253
+ AzureOpenAiChatCompletionResponseSchema,
2150
3254
  ChatMessageCacheControlSchema,
2151
3255
  ChatMessageRoleSchema,
2152
3256
  ChatMessageSchema,
@@ -2157,16 +3261,30 @@ export {
2157
3261
  anthropicBatchJsonOnlySystemInstruction,
2158
3262
  anthropicBatchTraceWorkflowName,
2159
3263
  applyCacheControlToLastContentBlock,
3264
+ awsSigV4Algorithm,
3265
+ azureOpenai,
3266
+ bedrock,
3267
+ bedrockAnthropicVersion,
2160
3268
  buildAnthropicCacheControl,
2161
3269
  buildAnthropicRequestBody,
3270
+ buildAnthropicStructuredOutputJsonSchema,
3271
+ buildAzureOpenAiChatCompletionsUrl,
3272
+ buildAzureOpenAiChatRequestBody,
3273
+ buildBedrockInvokeModelRequestBody,
3274
+ buildBedrockInvokeModelUrl,
3275
+ buildGeminiResponseSchema,
2162
3276
  buildOpenAiRequestBody,
3277
+ buildOpenAiStructuredOutputJsonSchema,
2163
3278
  buildProviderCanceledError,
2164
3279
  calculateProviderRetryDelayMs,
3280
+ convertZodSchemaToJsonSchema,
2165
3281
  createAnthropicBatchClient,
2166
3282
  defaultAnthropicBaseUrl,
2167
3283
  defaultAnthropicBatchPollIntervalMs,
2168
3284
  defaultAnthropicBatchTimeoutMs,
2169
3285
  defaultAnthropicMaxOutputTokens,
3286
+ defaultAzureOpenAiApiVersion,
3287
+ defaultBedrockMaxOutputTokens,
2170
3288
  defaultGeminiBaseUrl,
2171
3289
  defaultOpenAiBaseUrl,
2172
3290
  defaultProviderRetryInitialDelayMs,
@@ -2177,6 +3295,7 @@ export {
2177
3295
  executeProviderCallWithModelFallback,
2178
3296
  executeProviderCallWithRetry,
2179
3297
  extractAnthropicTextContent,
3298
+ extractAnthropicThinkingText,
2180
3299
  extractAnthropicToolCalls,
2181
3300
  extractMessageText,
2182
3301
  gemini,
@@ -2185,6 +3304,8 @@ export {
2185
3304
  joinSystemMessageText,
2186
3305
  mapAnthropicResponseToChatCompletionResult,
2187
3306
  mapAnthropicUsageToTokenUsage,
3307
+ mapAzureOpenAiResponseToChatCompletionResult,
3308
+ mapAzureOpenAiUsageToTokenUsage,
2188
3309
  mapChatMessageToAnthropicRequestMessage,
2189
3310
  mapChatMessageToOpenAiRequestMessage,
2190
3311
  mapModelToolChoiceToAnthropicToolChoice,
@@ -2194,11 +3315,21 @@ export {
2194
3315
  mergeProviderRequestExtraBody,
2195
3316
  mockModel,
2196
3317
  normalizeAnthropicStopReason,
3318
+ normalizeAzureOpenAiFinishReason,
3319
+ openAiStructuredOutputSchemaName,
2197
3320
  openai,
2198
3321
  parseAnthropicBatchStructuredContent,
2199
3322
  parseAnthropicStreamEvents,
2200
3323
  parseAnthropicToolInputJson,
3324
+ parseAzureOpenAiStreamEvents,
3325
+ parseAzureOpenAiToolArgumentsJson,
2201
3326
  resolveAnthropicPromptCachingSettings,
3327
+ resolveBedrockCredentials,
2202
3328
  resolveProviderApiKey,
2203
- streamAnthropicChatCompletion
3329
+ sanitizeJsonSchemaForAnthropicStructuredOutput,
3330
+ sanitizeJsonSchemaForGeminiResponseSchema,
3331
+ sanitizeJsonSchemaForOpenAiStructuredOutput,
3332
+ signAwsRequestWithSigV4,
3333
+ streamAnthropicChatCompletion,
3334
+ streamAzureOpenAiChatCompletion
2204
3335
  };