@assemble-dev/providers 0.2.0 → 0.3.1

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,6 +22,7 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AnthropicMessagesResponseSchema: () => AnthropicMessagesResponseSchema,
24
24
  AnthropicStreamEventSchema: () => AnthropicStreamEventSchema,
25
+ AzureOpenAiChatCompletionResponseSchema: () => AzureOpenAiChatCompletionResponseSchema,
25
26
  ChatMessageCacheControlSchema: () => ChatMessageCacheControlSchema,
26
27
  ChatMessageRoleSchema: () => ChatMessageRoleSchema,
27
28
  ChatMessageSchema: () => ChatMessageSchema,
@@ -32,16 +33,30 @@ __export(index_exports, {
32
33
  anthropicBatchJsonOnlySystemInstruction: () => anthropicBatchJsonOnlySystemInstruction,
33
34
  anthropicBatchTraceWorkflowName: () => anthropicBatchTraceWorkflowName,
34
35
  applyCacheControlToLastContentBlock: () => applyCacheControlToLastContentBlock,
36
+ awsSigV4Algorithm: () => awsSigV4Algorithm,
37
+ azureOpenai: () => azureOpenai,
38
+ bedrock: () => bedrock,
39
+ bedrockAnthropicVersion: () => bedrockAnthropicVersion,
35
40
  buildAnthropicCacheControl: () => buildAnthropicCacheControl,
36
41
  buildAnthropicRequestBody: () => buildAnthropicRequestBody,
42
+ buildAnthropicStructuredOutputJsonSchema: () => buildAnthropicStructuredOutputJsonSchema,
43
+ buildAzureOpenAiChatCompletionsUrl: () => buildAzureOpenAiChatCompletionsUrl,
44
+ buildAzureOpenAiChatRequestBody: () => buildAzureOpenAiChatRequestBody,
45
+ buildBedrockInvokeModelRequestBody: () => buildBedrockInvokeModelRequestBody,
46
+ buildBedrockInvokeModelUrl: () => buildBedrockInvokeModelUrl,
47
+ buildGeminiResponseSchema: () => buildGeminiResponseSchema,
37
48
  buildOpenAiRequestBody: () => buildOpenAiRequestBody,
49
+ buildOpenAiStructuredOutputJsonSchema: () => buildOpenAiStructuredOutputJsonSchema,
38
50
  buildProviderCanceledError: () => buildProviderCanceledError,
39
51
  calculateProviderRetryDelayMs: () => calculateProviderRetryDelayMs,
52
+ convertZodSchemaToJsonSchema: () => convertZodSchemaToJsonSchema,
40
53
  createAnthropicBatchClient: () => createAnthropicBatchClient,
41
54
  defaultAnthropicBaseUrl: () => defaultAnthropicBaseUrl,
42
55
  defaultAnthropicBatchPollIntervalMs: () => defaultAnthropicBatchPollIntervalMs,
43
56
  defaultAnthropicBatchTimeoutMs: () => defaultAnthropicBatchTimeoutMs,
44
57
  defaultAnthropicMaxOutputTokens: () => defaultAnthropicMaxOutputTokens,
58
+ defaultAzureOpenAiApiVersion: () => defaultAzureOpenAiApiVersion,
59
+ defaultBedrockMaxOutputTokens: () => defaultBedrockMaxOutputTokens,
45
60
  defaultGeminiBaseUrl: () => defaultGeminiBaseUrl,
46
61
  defaultOpenAiBaseUrl: () => defaultOpenAiBaseUrl,
47
62
  defaultProviderRetryInitialDelayMs: () => defaultProviderRetryInitialDelayMs,
@@ -52,14 +67,19 @@ __export(index_exports, {
52
67
  executeProviderCallWithModelFallback: () => executeProviderCallWithModelFallback,
53
68
  executeProviderCallWithRetry: () => executeProviderCallWithRetry,
54
69
  extractAnthropicTextContent: () => extractAnthropicTextContent,
70
+ extractAnthropicThinkingText: () => extractAnthropicThinkingText,
55
71
  extractAnthropicToolCalls: () => extractAnthropicToolCalls,
56
72
  extractMessageText: () => extractMessageText,
57
73
  gemini: () => gemini,
58
74
  isAbortError: () => isAbortError,
75
+ isOpenAiReasoningModel: () => isOpenAiReasoningModel,
59
76
  isRetryableProviderAppError: () => isRetryableProviderAppError,
77
+ isZodV4Schema: () => isZodV4Schema,
60
78
  joinSystemMessageText: () => joinSystemMessageText,
61
79
  mapAnthropicResponseToChatCompletionResult: () => mapAnthropicResponseToChatCompletionResult,
62
80
  mapAnthropicUsageToTokenUsage: () => mapAnthropicUsageToTokenUsage,
81
+ mapAzureOpenAiResponseToChatCompletionResult: () => mapAzureOpenAiResponseToChatCompletionResult,
82
+ mapAzureOpenAiUsageToTokenUsage: () => mapAzureOpenAiUsageToTokenUsage,
63
83
  mapChatMessageToAnthropicRequestMessage: () => mapChatMessageToAnthropicRequestMessage,
64
84
  mapChatMessageToOpenAiRequestMessage: () => mapChatMessageToOpenAiRequestMessage,
65
85
  mapModelToolChoiceToAnthropicToolChoice: () => mapModelToolChoiceToAnthropicToolChoice,
@@ -69,13 +89,27 @@ __export(index_exports, {
69
89
  mergeProviderRequestExtraBody: () => mergeProviderRequestExtraBody,
70
90
  mockModel: () => mockModel,
71
91
  normalizeAnthropicStopReason: () => normalizeAnthropicStopReason,
92
+ normalizeAzureOpenAiFinishReason: () => normalizeAzureOpenAiFinishReason,
93
+ openAiStructuredOutputSchemaName: () => openAiStructuredOutputSchemaName,
72
94
  openai: () => openai,
73
95
  parseAnthropicBatchStructuredContent: () => parseAnthropicBatchStructuredContent,
74
96
  parseAnthropicStreamEvents: () => parseAnthropicStreamEvents,
75
97
  parseAnthropicToolInputJson: () => parseAnthropicToolInputJson,
98
+ parseAzureOpenAiStreamEvents: () => parseAzureOpenAiStreamEvents,
99
+ parseAzureOpenAiToolArgumentsJson: () => parseAzureOpenAiToolArgumentsJson,
100
+ prependStructuredOutputJsonOnlySystemMessage: () => prependStructuredOutputJsonOnlySystemMessage,
76
101
  resolveAnthropicPromptCachingSettings: () => resolveAnthropicPromptCachingSettings,
102
+ resolveBedrockCredentials: () => resolveBedrockCredentials,
103
+ resolveOpenAiStructuredOutputMode: () => resolveOpenAiStructuredOutputMode,
77
104
  resolveProviderApiKey: () => resolveProviderApiKey,
78
- streamAnthropicChatCompletion: () => streamAnthropicChatCompletion
105
+ sanitizeJsonSchemaForAnthropicStructuredOutput: () => sanitizeJsonSchemaForAnthropicStructuredOutput,
106
+ sanitizeJsonSchemaForGeminiResponseSchema: () => sanitizeJsonSchemaForGeminiResponseSchema,
107
+ sanitizeJsonSchemaForOpenAiStructuredOutput: () => sanitizeJsonSchemaForOpenAiStructuredOutput,
108
+ signAwsRequestWithSigV4: () => signAwsRequestWithSigV4,
109
+ streamAnthropicChatCompletion: () => streamAnthropicChatCompletion,
110
+ streamAzureOpenAiChatCompletion: () => streamAzureOpenAiChatCompletion,
111
+ structuredOutputJsonOnlySystemInstruction: () => structuredOutputJsonOnlySystemInstruction,
112
+ structuredOutputJsonOnlySystemMessage: () => structuredOutputJsonOnlySystemMessage
79
113
  });
80
114
  module.exports = __toCommonJS(index_exports);
81
115
 
@@ -134,28 +168,306 @@ function extractMessageText(message) {
134
168
  }
135
169
 
136
170
  // src/openai-adapter.ts
137
- var import_zod3 = require("zod");
138
- var import_errors14 = require("@assemble-dev/shared-types/errors");
139
- var import_json3 = require("@assemble-dev/shared-types/json");
140
- var import_errors15 = require("@assemble-dev/shared-utils/errors");
171
+ var import_zod4 = require("zod");
172
+ var import_errors16 = require("@assemble-dev/shared-types/errors");
173
+ var import_json4 = require("@assemble-dev/shared-types/json");
174
+ var import_errors17 = require("@assemble-dev/shared-utils/errors");
141
175
 
142
176
  // src/openai-request-mapping.ts
177
+ var import_errors3 = require("@assemble-dev/shared-types/errors");
178
+ var import_errors4 = require("@assemble-dev/shared-utils/errors");
179
+
180
+ // src/structured-output-json-schema.ts
181
+ var import_zod2 = require("zod");
143
182
  var import_errors = require("@assemble-dev/shared-types/errors");
183
+ var import_json2 = require("@assemble-dev/shared-types/json");
144
184
  var import_errors2 = require("@assemble-dev/shared-utils/errors");
185
+
186
+ // src/json-schema-tree.ts
187
+ var schemaMapKeywords = ["properties", "$defs"];
188
+ var schemaListKeywords = ["anyOf", "oneOf", "allOf", "prefixItems"];
189
+ var schemaValueKeywords = [
190
+ "items",
191
+ "additionalProperties",
192
+ "not",
193
+ "if",
194
+ "then",
195
+ "else",
196
+ "contains",
197
+ "propertyNames"
198
+ ];
199
+ function isJsonObject(value) {
200
+ return typeof value === "object" && value !== null && !Array.isArray(value);
201
+ }
202
+ function transformJsonSchemaNode(node, transformNode) {
203
+ const result = { ...transformNode({ ...node }) };
204
+ for (const keyword of schemaMapKeywords) {
205
+ const mapValue = result[keyword];
206
+ if (mapValue !== void 0 && isJsonObject(mapValue)) {
207
+ result[keyword] = transformJsonSchemaMap(mapValue, transformNode);
208
+ }
209
+ }
210
+ for (const keyword of schemaListKeywords) {
211
+ const listValue = result[keyword];
212
+ if (Array.isArray(listValue)) {
213
+ result[keyword] = listValue.map(
214
+ (entry) => isJsonObject(entry) ? transformJsonSchemaNode(entry, transformNode) : entry
215
+ );
216
+ }
217
+ }
218
+ for (const keyword of schemaValueKeywords) {
219
+ const schemaValue = result[keyword];
220
+ if (schemaValue !== void 0 && isJsonObject(schemaValue)) {
221
+ result[keyword] = transformJsonSchemaNode(schemaValue, transformNode);
222
+ }
223
+ }
224
+ return result;
225
+ }
226
+ function transformJsonSchemaMap(schemaMap, transformNode) {
227
+ const result = {};
228
+ for (const [schemaName, schemaValue] of Object.entries(schemaMap)) {
229
+ result[schemaName] = isJsonObject(schemaValue) ? transformJsonSchemaNode(schemaValue, transformNode) : schemaValue;
230
+ }
231
+ return result;
232
+ }
233
+ function inlineJsonSchemaReferences(root) {
234
+ const rootDefinitions = root["$defs"];
235
+ const definitions = rootDefinitions !== void 0 && isJsonObject(rootDefinitions) ? rootDefinitions : {};
236
+ const resolvedRoot = resolveJsonSchemaReferences(
237
+ root,
238
+ definitions,
239
+ /* @__PURE__ */ new Set()
240
+ );
241
+ return isJsonObject(resolvedRoot) ? resolvedRoot : {};
242
+ }
243
+ function resolveJsonSchemaReferences(value, definitions, activeReferences) {
244
+ if (Array.isArray(value)) {
245
+ return value.map(
246
+ (entry) => resolveJsonSchemaReferences(entry, definitions, activeReferences)
247
+ );
248
+ }
249
+ if (!isJsonObject(value)) {
250
+ return value;
251
+ }
252
+ const referenceTarget = value["$ref"];
253
+ if (typeof referenceTarget === "string") {
254
+ return resolveJsonSchemaReferenceTarget(
255
+ referenceTarget,
256
+ definitions,
257
+ activeReferences
258
+ );
259
+ }
260
+ const result = {};
261
+ for (const [key, entryValue] of Object.entries(value)) {
262
+ if (key !== "$defs") {
263
+ result[key] = resolveJsonSchemaReferences(
264
+ entryValue,
265
+ definitions,
266
+ activeReferences
267
+ );
268
+ }
269
+ }
270
+ return result;
271
+ }
272
+ function resolveJsonSchemaReferenceTarget(referenceTarget, definitions, activeReferences) {
273
+ if (activeReferences.has(referenceTarget)) {
274
+ return {};
275
+ }
276
+ const definitionsPrefix = "#/$defs/";
277
+ if (!referenceTarget.startsWith(definitionsPrefix)) {
278
+ return {};
279
+ }
280
+ const definition = definitions[referenceTarget.slice(definitionsPrefix.length)];
281
+ if (definition === void 0 || !isJsonObject(definition)) {
282
+ return {};
283
+ }
284
+ return resolveJsonSchemaReferences(
285
+ definition,
286
+ definitions,
287
+ /* @__PURE__ */ new Set([...activeReferences, referenceTarget])
288
+ );
289
+ }
290
+ function removeJsonSchemaKeywords(node, keywords) {
291
+ const result = {};
292
+ for (const [key, value] of Object.entries(node)) {
293
+ if (!keywords.includes(key)) {
294
+ result[key] = value;
295
+ }
296
+ }
297
+ return result;
298
+ }
299
+
300
+ // src/structured-output-json-schema.ts
301
+ var openAiStructuredOutputSchemaName = "structured_output";
302
+ var schemaMetadataKeywords = ["$schema", "$id"];
303
+ var anthropicUnsupportedSchemaKeywords = [
304
+ ...schemaMetadataKeywords,
305
+ "minimum",
306
+ "maximum",
307
+ "exclusiveMinimum",
308
+ "exclusiveMaximum",
309
+ "minLength",
310
+ "maxLength",
311
+ "multipleOf"
312
+ ];
313
+ var openAiUnsupportedSchemaKeywords = [
314
+ ...anthropicUnsupportedSchemaKeywords,
315
+ "pattern",
316
+ "format",
317
+ "minItems",
318
+ "maxItems",
319
+ "uniqueItems",
320
+ "default"
321
+ ];
322
+ function isZodV4Schema(schema) {
323
+ return "_zod" in schema;
324
+ }
325
+ function convertZodSchemaToJsonSchema(schema) {
326
+ try {
327
+ return import_json2.JsonObjectSchema.parse(import_zod2.z.toJSONSchema(schema, { io: "input" }));
328
+ } catch (error) {
329
+ throw new import_errors2.AppError({
330
+ code: import_errors.AppErrorCode.BadRequest,
331
+ message: "Structured output schema could not be converted to JSON Schema",
332
+ statusCode: 400,
333
+ cause: error instanceof Error ? error : void 0
334
+ });
335
+ }
336
+ }
337
+ function buildAnthropicStructuredOutputJsonSchema(schema) {
338
+ return sanitizeJsonSchemaForAnthropicStructuredOutput(
339
+ convertZodSchemaToJsonSchema(schema)
340
+ );
341
+ }
342
+ function sanitizeJsonSchemaForAnthropicStructuredOutput(jsonSchema) {
343
+ return transformJsonSchemaNode(
344
+ inlineJsonSchemaReferences(jsonSchema),
345
+ sanitizeAnthropicSchemaNode
346
+ );
347
+ }
348
+ function buildOpenAiStructuredOutputJsonSchema(schema) {
349
+ return sanitizeJsonSchemaForOpenAiStructuredOutput(
350
+ convertZodSchemaToJsonSchema(schema)
351
+ );
352
+ }
353
+ function sanitizeJsonSchemaForOpenAiStructuredOutput(jsonSchema) {
354
+ return transformJsonSchemaNode(jsonSchema, sanitizeOpenAiSchemaNode);
355
+ }
356
+ function sanitizeAnthropicSchemaNode(node) {
357
+ const sanitized = removeJsonSchemaKeywords(
358
+ node,
359
+ anthropicUnsupportedSchemaKeywords
360
+ );
361
+ if (sanitized["type"] === "object") {
362
+ sanitized["additionalProperties"] = false;
363
+ }
364
+ return sanitized;
365
+ }
366
+ function sanitizeOpenAiSchemaNode(node) {
367
+ const sanitized = removeJsonSchemaKeywords(
368
+ node,
369
+ openAiUnsupportedSchemaKeywords
370
+ );
371
+ if (sanitized["type"] !== "object") {
372
+ return sanitized;
373
+ }
374
+ sanitized["additionalProperties"] = false;
375
+ const propertyNames = listSchemaPropertyNames(sanitized);
376
+ if (propertyNames.length > 0) {
377
+ sanitized["required"] = propertyNames;
378
+ }
379
+ return sanitized;
380
+ }
381
+ function listSchemaPropertyNames(node) {
382
+ const properties = node["properties"];
383
+ if (properties === void 0 || !isJsonObject(properties)) {
384
+ return [];
385
+ }
386
+ return Object.keys(properties);
387
+ }
388
+
389
+ // src/structured-output-fallback.ts
390
+ var structuredOutputJsonOnlySystemInstruction = "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text.";
391
+ var structuredOutputJsonOnlySystemMessage = {
392
+ role: "system",
393
+ content: structuredOutputJsonOnlySystemInstruction
394
+ };
395
+ function prependStructuredOutputJsonOnlySystemMessage(messages) {
396
+ return [structuredOutputJsonOnlySystemMessage, ...messages];
397
+ }
398
+
399
+ // src/openai-request-mapping.ts
400
+ var openAiReasoningModelNamePrefixes = [
401
+ "gpt-5",
402
+ "o1",
403
+ "o3",
404
+ "o4"
405
+ ];
406
+ function isOpenAiReasoningModel(model) {
407
+ return openAiReasoningModelNamePrefixes.some(
408
+ (prefix) => matchesOpenAiModelNamePrefix(model, prefix)
409
+ );
410
+ }
411
+ function matchesOpenAiModelNamePrefix(model, prefix) {
412
+ if (!model.startsWith(prefix)) {
413
+ return false;
414
+ }
415
+ const boundaryCharacter = model.charAt(prefix.length);
416
+ return boundaryCharacter === "" || boundaryCharacter === "-" || boundaryCharacter === ".";
417
+ }
418
+ function resolveOpenAiStructuredOutputMode(messages, schema) {
419
+ if (isZodV4Schema(schema)) {
420
+ return {
421
+ messages,
422
+ structuredOutputJsonSchema: buildOpenAiStructuredOutputJsonSchema(schema)
423
+ };
424
+ }
425
+ return {
426
+ messages: prependStructuredOutputJsonOnlySystemMessage(messages),
427
+ requireJsonObjectResponse: true
428
+ };
429
+ }
145
430
  function buildOpenAiRequestBody(model, input) {
146
431
  const requestBody = {
147
432
  model,
148
433
  messages: input.messages.map(mapChatMessageToOpenAiRequestMessage)
149
434
  };
150
- if (input.temperature !== void 0) {
435
+ applyOpenAiGenerationSettings(requestBody, model, input);
436
+ applyOpenAiResponseFormat(requestBody, input);
437
+ applyOpenAiToolFields(requestBody, input);
438
+ return requestBody;
439
+ }
440
+ function applyOpenAiGenerationSettings(requestBody, model, input) {
441
+ const reasoningModel = input.reasoningModel ?? isOpenAiReasoningModel(model);
442
+ if (input.temperature !== void 0 && !reasoningModel) {
151
443
  requestBody.temperature = input.temperature;
152
444
  }
153
- if (input.maxOutputTokens !== void 0) {
154
- requestBody.max_tokens = input.maxOutputTokens;
445
+ if (input.maxOutputTokens === void 0) {
446
+ return;
447
+ }
448
+ if (reasoningModel) {
449
+ requestBody.max_completion_tokens = input.maxOutputTokens;
450
+ return;
451
+ }
452
+ requestBody.max_tokens = input.maxOutputTokens;
453
+ }
454
+ function applyOpenAiResponseFormat(requestBody, input) {
455
+ if (input.structuredOutputJsonSchema !== void 0) {
456
+ requestBody.response_format = {
457
+ type: "json_schema",
458
+ json_schema: {
459
+ name: openAiStructuredOutputSchemaName,
460
+ strict: true,
461
+ schema: input.structuredOutputJsonSchema
462
+ }
463
+ };
464
+ return;
155
465
  }
156
- if (input.requireJsonObjectResponse) {
466
+ if (input.requireJsonObjectResponse === true) {
157
467
  requestBody.response_format = { type: "json_object" };
158
468
  }
469
+ }
470
+ function applyOpenAiToolFields(requestBody, input) {
159
471
  if (input.tools !== void 0 && input.tools.length > 0) {
160
472
  requestBody.tools = input.tools.map(mapModelToolDefinitionToOpenAiTool);
161
473
  }
@@ -164,7 +476,6 @@ function buildOpenAiRequestBody(model, input) {
164
476
  input.toolChoice
165
477
  );
166
478
  }
167
- return requestBody;
168
479
  }
169
480
  function mapModelToolDefinitionToOpenAiTool(tool) {
170
481
  return {
@@ -239,17 +550,17 @@ function mapMessageContentBlockToOpenAiContentPart(contentBlock) {
239
550
  }
240
551
  };
241
552
  }
242
- throw new import_errors2.AppError({
243
- code: import_errors.AppErrorCode.ValidationFailed,
553
+ throw new import_errors4.AppError({
554
+ code: import_errors3.AppErrorCode.ValidationFailed,
244
555
  message: "OpenAI adapter does not support document content blocks in chat messages",
245
556
  statusCode: 400
246
557
  });
247
558
  }
248
559
 
249
560
  // src/parse-structured-json.ts
250
- var import_errors3 = require("@assemble-dev/shared-types/errors");
251
- var import_json2 = require("@assemble-dev/shared-types/json");
252
- var import_errors4 = require("@assemble-dev/shared-utils/errors");
561
+ var import_errors5 = require("@assemble-dev/shared-types/errors");
562
+ var import_json3 = require("@assemble-dev/shared-types/json");
563
+ var import_errors6 = require("@assemble-dev/shared-utils/errors");
253
564
  var markdownCodeFencePattern = /^```[A-Za-z]*\s*\n?([\s\S]*?)\n?```$/;
254
565
  function parseStructuredJsonText(text, schema) {
255
566
  return schema.parse(parseJsonText(stripMarkdownCodeFences(text)));
@@ -264,10 +575,10 @@ function stripMarkdownCodeFences(text) {
264
575
  }
265
576
  function parseJsonText(text) {
266
577
  try {
267
- return import_json2.JsonValueSchema.parse(JSON.parse(text));
578
+ return import_json3.JsonValueSchema.parse(JSON.parse(text));
268
579
  } catch (error) {
269
- throw new import_errors4.AppError({
270
- code: import_errors3.AppErrorCode.ValidationFailed,
580
+ throw new import_errors6.AppError({
581
+ code: import_errors5.AppErrorCode.ValidationFailed,
271
582
  message: "Structured output was not valid JSON",
272
583
  statusCode: 422,
273
584
  cause: error instanceof Error ? error : void 0
@@ -276,9 +587,9 @@ function parseJsonText(text) {
276
587
  }
277
588
 
278
589
  // src/provider-api-key.ts
279
- var import_zod2 = require("zod");
280
- var import_errors5 = require("@assemble-dev/shared-types/errors");
281
- var import_errors6 = require("@assemble-dev/shared-utils/errors");
590
+ var import_zod3 = require("zod");
591
+ var import_errors7 = require("@assemble-dev/shared-types/errors");
592
+ var import_errors8 = require("@assemble-dev/shared-utils/errors");
282
593
  var import_provider_keys = require("@assemble-dev/shared-utils/provider-keys");
283
594
  function resolveProviderApiKey(input) {
284
595
  if (input.apiKey !== void 0 && input.apiKey.length > 0) {
@@ -291,8 +602,8 @@ function resolveProviderApiKey(input) {
291
602
  }
292
603
  function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
293
604
  if (!(0, import_provider_keys.validateProviderApiKeyName)(apiKeyName)) {
294
- throw new import_errors6.AppError({
295
- code: import_errors5.AppErrorCode.BadRequest,
605
+ throw new import_errors8.AppError({
606
+ code: import_errors7.AppErrorCode.BadRequest,
296
607
  message: `Invalid ${input.providerLabel} apiKeyName "${apiKeyName}". Expected ${import_provider_keys.expectedProviderApiKeyNameFormat}.`,
297
608
  statusCode: 400
298
609
  });
@@ -300,8 +611,8 @@ function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
300
611
  const envVarName = (0, import_provider_keys.buildNamedApiKeyEnvVarName)(input.baseEnvVarName, apiKeyName);
301
612
  const envApiKey = readEnvironmentVariable(envVarName);
302
613
  if (envApiKey === void 0 || envApiKey.length === 0) {
303
- throw new import_errors6.AppError({
304
- code: import_errors5.AppErrorCode.Unauthorized,
614
+ throw new import_errors8.AppError({
615
+ code: import_errors7.AppErrorCode.Unauthorized,
305
616
  message: `${input.providerLabel} API key named "${apiKeyName}" is missing. Set the ${envVarName} environment variable or pass apiKey to ${input.adapterFunctionName}.`,
306
617
  statusCode: 401
307
618
  });
@@ -311,8 +622,8 @@ function resolveNamedProviderApiKeyFromEnv(input, apiKeyName) {
311
622
  function resolveBaseProviderApiKeyFromEnv(input) {
312
623
  const envApiKey = readEnvironmentVariable(input.baseEnvVarName);
313
624
  if (envApiKey === void 0 || envApiKey.length === 0) {
314
- throw new import_errors6.AppError({
315
- code: import_errors5.AppErrorCode.Unauthorized,
625
+ throw new import_errors8.AppError({
626
+ code: import_errors7.AppErrorCode.Unauthorized,
316
627
  message: `${input.providerLabel} API key is missing. Pass apiKey to ${input.adapterFunctionName} or set the ${input.baseEnvVarName} environment variable.`,
317
628
  statusCode: 401
318
629
  });
@@ -320,19 +631,19 @@ function resolveBaseProviderApiKeyFromEnv(input) {
320
631
  return envApiKey;
321
632
  }
322
633
  function readEnvironmentVariable(envVarName) {
323
- const parsedEnv = import_zod2.z.object({ [envVarName]: import_zod2.z.string().optional() }).parse(process.env);
634
+ const parsedEnv = import_zod3.z.object({ [envVarName]: import_zod3.z.string().optional() }).parse(process.env);
324
635
  return parsedEnv[envVarName];
325
636
  }
326
637
 
327
638
  // src/provider-cancellation.ts
328
- var import_errors7 = require("@assemble-dev/shared-types/errors");
329
- var import_errors8 = require("@assemble-dev/shared-utils/errors");
639
+ var import_errors9 = require("@assemble-dev/shared-types/errors");
640
+ var import_errors10 = require("@assemble-dev/shared-utils/errors");
330
641
  function isAbortError(error) {
331
642
  return error.name === "AbortError";
332
643
  }
333
644
  function buildProviderCanceledError(providerLabel) {
334
- return new import_errors8.AppError({
335
- code: import_errors7.AppErrorCode.Canceled,
645
+ return new import_errors10.AppError({
646
+ code: import_errors9.AppErrorCode.Canceled,
336
647
  message: `${providerLabel} request was canceled`,
337
648
  statusCode: 499
338
649
  });
@@ -358,18 +669,18 @@ function mergeProviderRequestExtraBody(requestBody, adapterExtraBody, requestExt
358
669
  }
359
670
 
360
671
  // src/provider-fallback.ts
361
- var import_errors11 = require("@assemble-dev/shared-utils/errors");
672
+ var import_errors13 = require("@assemble-dev/shared-utils/errors");
362
673
 
363
674
  // src/provider-retry.ts
364
- var import_errors9 = require("@assemble-dev/shared-types/errors");
365
- var import_errors10 = require("@assemble-dev/shared-utils/errors");
675
+ var import_errors11 = require("@assemble-dev/shared-types/errors");
676
+ var import_errors12 = require("@assemble-dev/shared-utils/errors");
366
677
  var defaultProviderRetryMaxAttempts = 3;
367
678
  var defaultProviderRetryInitialDelayMs = 500;
368
679
  var defaultProviderRetryMaxDelayMs = 8e3;
369
680
  var retryableAppErrorCodes = /* @__PURE__ */ new Set([
370
- import_errors9.AppErrorCode.RateLimited,
371
- import_errors9.AppErrorCode.ServiceUnavailable,
372
- import_errors9.AppErrorCode.InternalServerError
681
+ import_errors11.AppErrorCode.RateLimited,
682
+ import_errors11.AppErrorCode.ServiceUnavailable,
683
+ import_errors11.AppErrorCode.InternalServerError
373
684
  ]);
374
685
  function isRetryableProviderAppError(appError) {
375
686
  return retryableAppErrorCodes.has(appError.code);
@@ -384,7 +695,7 @@ async function executeProviderCallWithRetry(retryOptions, executeCall, waitFor)
384
695
  try {
385
696
  return await executeCall();
386
697
  } catch (error) {
387
- if (error instanceof import_errors10.AppError && !isRetryableProviderAppError(error)) {
698
+ if (error instanceof import_errors12.AppError && !isRetryableProviderAppError(error)) {
388
699
  throw error;
389
700
  }
390
701
  if (error instanceof Error && isAbortError(error)) {
@@ -418,7 +729,7 @@ async function executeProviderCallWithModelFallback(fallbackModel, executePrimar
418
729
  if (fallbackModel === void 0) {
419
730
  throw error;
420
731
  }
421
- if (error instanceof import_errors11.AppError && !isRetryableProviderAppError(error)) {
732
+ if (error instanceof import_errors13.AppError && !isRetryableProviderAppError(error)) {
422
733
  throw error;
423
734
  }
424
735
  if (error instanceof Error && isAbortError(error)) {
@@ -429,11 +740,11 @@ async function executeProviderCallWithModelFallback(fallbackModel, executePrimar
429
740
  }
430
741
 
431
742
  // src/provider-status-error.ts
432
- var import_errors12 = require("@assemble-dev/shared-types/errors");
433
- var import_errors13 = require("@assemble-dev/shared-utils/errors");
743
+ var import_errors14 = require("@assemble-dev/shared-types/errors");
744
+ var import_errors15 = require("@assemble-dev/shared-utils/errors");
434
745
  function buildProviderStatusError(providerLabel, providerStatus) {
435
746
  const code = mapProviderStatusToAppErrorCode(providerStatus);
436
- return new import_errors13.AppError({
747
+ return new import_errors15.AppError({
437
748
  code,
438
749
  message: `${providerLabel} request failed with status ${String(providerStatus)}`,
439
750
  statusCode: mapAppErrorCodeToStatusCode(code),
@@ -441,44 +752,44 @@ function buildProviderStatusError(providerLabel, providerStatus) {
441
752
  });
442
753
  }
443
754
  function buildProviderInvalidResponseError(providerLabel, expectedShapeDescription) {
444
- return new import_errors13.AppError({
445
- code: import_errors12.AppErrorCode.ValidationFailed,
755
+ return new import_errors15.AppError({
756
+ code: import_errors14.AppErrorCode.ValidationFailed,
446
757
  message: `${providerLabel} response did not match the expected ${expectedShapeDescription} shape`,
447
758
  statusCode: 502
448
759
  });
449
760
  }
450
761
  function mapProviderStatusToAppErrorCode(providerStatus) {
451
762
  if (providerStatus === 400) {
452
- return import_errors12.AppErrorCode.BadRequest;
763
+ return import_errors14.AppErrorCode.BadRequest;
453
764
  }
454
765
  if (providerStatus === 401) {
455
- return import_errors12.AppErrorCode.Unauthorized;
766
+ return import_errors14.AppErrorCode.Unauthorized;
456
767
  }
457
768
  if (providerStatus === 403) {
458
- return import_errors12.AppErrorCode.Forbidden;
769
+ return import_errors14.AppErrorCode.Forbidden;
459
770
  }
460
771
  if (providerStatus === 404) {
461
- return import_errors12.AppErrorCode.NotFound;
772
+ return import_errors14.AppErrorCode.NotFound;
462
773
  }
463
774
  if (providerStatus === 429) {
464
- return import_errors12.AppErrorCode.RateLimited;
775
+ return import_errors14.AppErrorCode.RateLimited;
465
776
  }
466
- return import_errors12.AppErrorCode.InternalServerError;
777
+ return import_errors14.AppErrorCode.InternalServerError;
467
778
  }
468
779
  function mapAppErrorCodeToStatusCode(code) {
469
- if (code === import_errors12.AppErrorCode.BadRequest) {
780
+ if (code === import_errors14.AppErrorCode.BadRequest) {
470
781
  return 400;
471
782
  }
472
- if (code === import_errors12.AppErrorCode.Unauthorized) {
783
+ if (code === import_errors14.AppErrorCode.Unauthorized) {
473
784
  return 401;
474
785
  }
475
- if (code === import_errors12.AppErrorCode.Forbidden) {
786
+ if (code === import_errors14.AppErrorCode.Forbidden) {
476
787
  return 403;
477
788
  }
478
- if (code === import_errors12.AppErrorCode.NotFound) {
789
+ if (code === import_errors14.AppErrorCode.NotFound) {
479
790
  return 404;
480
791
  }
481
- if (code === import_errors12.AppErrorCode.RateLimited) {
792
+ if (code === import_errors14.AppErrorCode.RateLimited) {
482
793
  return 429;
483
794
  }
484
795
  return 500;
@@ -486,33 +797,29 @@ function mapAppErrorCodeToStatusCode(code) {
486
797
 
487
798
  // src/openai-adapter.ts
488
799
  var defaultOpenAiBaseUrl = "https://api.openai.com/v1";
489
- var OpenAiResponseToolCallSchema = import_zod3.z.object({
490
- id: import_zod3.z.string(),
491
- function: import_zod3.z.object({
492
- name: import_zod3.z.string(),
493
- arguments: import_zod3.z.string()
800
+ var OpenAiResponseToolCallSchema = import_zod4.z.object({
801
+ id: import_zod4.z.string(),
802
+ function: import_zod4.z.object({
803
+ name: import_zod4.z.string(),
804
+ arguments: import_zod4.z.string()
494
805
  })
495
806
  });
496
- var OpenAiChatCompletionResponseSchema = import_zod3.z.object({
497
- choices: import_zod3.z.array(
498
- import_zod3.z.object({
499
- message: import_zod3.z.object({
500
- content: import_zod3.z.string().nullable(),
501
- tool_calls: import_zod3.z.array(OpenAiResponseToolCallSchema).optional()
807
+ var OpenAiChatCompletionResponseSchema = import_zod4.z.object({
808
+ choices: import_zod4.z.array(
809
+ import_zod4.z.object({
810
+ message: import_zod4.z.object({
811
+ content: import_zod4.z.string().nullable(),
812
+ tool_calls: import_zod4.z.array(OpenAiResponseToolCallSchema).optional()
502
813
  }),
503
- finish_reason: import_zod3.z.string().nullable().optional()
814
+ finish_reason: import_zod4.z.string().nullable().optional()
504
815
  })
505
816
  ).min(1),
506
- usage: import_zod3.z.object({
507
- prompt_tokens: import_zod3.z.number().int().nonnegative(),
508
- completion_tokens: import_zod3.z.number().int().nonnegative(),
509
- total_tokens: import_zod3.z.number().int().nonnegative()
817
+ usage: import_zod4.z.object({
818
+ prompt_tokens: import_zod4.z.number().int().nonnegative(),
819
+ completion_tokens: import_zod4.z.number().int().nonnegative(),
820
+ total_tokens: import_zod4.z.number().int().nonnegative()
510
821
  })
511
822
  });
512
- var structuredOutputSystemMessage = {
513
- role: "system",
514
- content: "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text."
515
- };
516
823
  function openai(options) {
517
824
  return {
518
825
  name: `openai:${options.model}`,
@@ -521,7 +828,6 @@ function openai(options) {
521
828
  messages: request.messages,
522
829
  temperature: request.temperature ?? options.temperature,
523
830
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
524
- requireJsonObjectResponse: false,
525
831
  tools: request.tools,
526
832
  toolChoice: request.toolChoice,
527
833
  abortSignal: request.abortSignal,
@@ -530,10 +836,9 @@ function openai(options) {
530
836
  },
531
837
  async generateStructuredOutput(request) {
532
838
  const completion = await executeOpenAiAdapterCall(options, {
533
- messages: [structuredOutputSystemMessage, ...request.messages],
839
+ ...resolveOpenAiStructuredOutputMode(request.messages, request.schema),
534
840
  temperature: request.temperature ?? options.temperature,
535
841
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
536
- requireJsonObjectResponse: true,
537
842
  abortSignal: request.abortSignal
538
843
  });
539
844
  return {
@@ -626,10 +931,10 @@ function parseOpenAiToolArgumentsJson(argumentsJsonText) {
626
931
  return {};
627
932
  }
628
933
  try {
629
- return import_json3.JsonValueSchema.parse(JSON.parse(argumentsJsonText));
934
+ return import_json4.JsonValueSchema.parse(JSON.parse(argumentsJsonText));
630
935
  } catch (error) {
631
- throw new import_errors15.AppError({
632
- code: import_errors14.AppErrorCode.ValidationFailed,
936
+ throw new import_errors17.AppError({
937
+ code: import_errors16.AppErrorCode.ValidationFailed,
633
938
  message: "OpenAI tool call arguments were not valid JSON",
634
939
  statusCode: 502,
635
940
  cause: error instanceof Error ? error : void 0
@@ -651,8 +956,8 @@ function extractOpenAiMessageContent(response, allowEmptyContent) {
651
956
  if (allowEmptyContent) {
652
957
  return "";
653
958
  }
654
- throw new import_errors15.AppError({
655
- code: import_errors14.AppErrorCode.ValidationFailed,
959
+ throw new import_errors17.AppError({
960
+ code: import_errors16.AppErrorCode.ValidationFailed,
656
961
  message: "OpenAI response contained no message content",
657
962
  statusCode: 502
658
963
  });
@@ -716,6 +1021,11 @@ function buildAnthropicRequestBody(settings, input) {
716
1021
  budget_tokens: settings.thinking.budgetTokens
717
1022
  };
718
1023
  }
1024
+ if (input.structuredOutputJsonSchema !== void 0) {
1025
+ requestBody.output_config = {
1026
+ format: { type: "json_schema", schema: input.structuredOutputJsonSchema }
1027
+ };
1028
+ }
719
1029
  return requestBody;
720
1030
  }
721
1031
  function applyAnthropicSystemField(requestBody, settings, input) {
@@ -872,44 +1182,45 @@ function mapMessageContentBlockToAnthropic(contentBlock) {
872
1182
  }
873
1183
 
874
1184
  // src/anthropic-response-parsing.ts
875
- var import_zod4 = require("zod");
876
- var import_errors16 = require("@assemble-dev/shared-types/errors");
877
- var import_json4 = require("@assemble-dev/shared-types/json");
878
- var import_errors17 = require("@assemble-dev/shared-utils/errors");
879
- var AnthropicUsageSchema = import_zod4.z.object({
880
- input_tokens: import_zod4.z.number().int().nonnegative(),
881
- output_tokens: import_zod4.z.number().int().nonnegative(),
882
- cache_creation_input_tokens: import_zod4.z.number().int().nonnegative().optional(),
883
- cache_read_input_tokens: import_zod4.z.number().int().nonnegative().optional()
1185
+ var import_zod5 = require("zod");
1186
+ var import_errors18 = require("@assemble-dev/shared-types/errors");
1187
+ var import_json5 = require("@assemble-dev/shared-types/json");
1188
+ var import_errors19 = require("@assemble-dev/shared-utils/errors");
1189
+ var AnthropicUsageSchema = import_zod5.z.object({
1190
+ input_tokens: import_zod5.z.number().int().nonnegative(),
1191
+ output_tokens: import_zod5.z.number().int().nonnegative(),
1192
+ cache_creation_input_tokens: import_zod5.z.number().int().nonnegative().optional(),
1193
+ cache_read_input_tokens: import_zod5.z.number().int().nonnegative().optional()
884
1194
  });
885
- var AnthropicContentBlockSchema = import_zod4.z.discriminatedUnion("type", [
886
- import_zod4.z.object({
887
- type: import_zod4.z.literal("text"),
888
- text: import_zod4.z.string()
1195
+ var AnthropicContentBlockSchema = import_zod5.z.discriminatedUnion("type", [
1196
+ import_zod5.z.object({
1197
+ type: import_zod5.z.literal("text"),
1198
+ text: import_zod5.z.string()
889
1199
  }),
890
- import_zod4.z.object({
891
- type: import_zod4.z.literal("tool_use"),
892
- id: import_zod4.z.string(),
893
- name: import_zod4.z.string(),
894
- input: import_json4.JsonValueSchema
1200
+ import_zod5.z.object({
1201
+ type: import_zod5.z.literal("tool_use"),
1202
+ id: import_zod5.z.string(),
1203
+ name: import_zod5.z.string(),
1204
+ input: import_json5.JsonValueSchema
895
1205
  }),
896
- import_zod4.z.object({
897
- type: import_zod4.z.literal("thinking"),
898
- thinking: import_zod4.z.string().optional(),
899
- signature: import_zod4.z.string().optional()
1206
+ import_zod5.z.object({
1207
+ type: import_zod5.z.literal("thinking"),
1208
+ thinking: import_zod5.z.string().optional(),
1209
+ signature: import_zod5.z.string().optional()
900
1210
  }),
901
- import_zod4.z.object({
902
- type: import_zod4.z.literal("redacted_thinking"),
903
- data: import_zod4.z.string().optional()
1211
+ import_zod5.z.object({
1212
+ type: import_zod5.z.literal("redacted_thinking"),
1213
+ data: import_zod5.z.string().optional()
904
1214
  })
905
1215
  ]);
906
- var AnthropicMessagesResponseSchema = import_zod4.z.object({
907
- content: import_zod4.z.array(AnthropicContentBlockSchema),
908
- stop_reason: import_zod4.z.string().nullable().optional(),
1216
+ var AnthropicMessagesResponseSchema = import_zod5.z.object({
1217
+ content: import_zod5.z.array(AnthropicContentBlockSchema),
1218
+ stop_reason: import_zod5.z.string().nullable().optional(),
909
1219
  usage: AnthropicUsageSchema
910
1220
  });
911
1221
  function mapAnthropicResponseToChatCompletionResult(response, latencyMs) {
912
1222
  const toolCalls = extractAnthropicToolCalls(response);
1223
+ const thinkingText = extractAnthropicThinkingText(response);
913
1224
  const result = {
914
1225
  content: extractAnthropicTextContent(response, toolCalls.length > 0),
915
1226
  tokenUsage: mapAnthropicUsageToTokenUsage(response.usage),
@@ -918,6 +1229,9 @@ function mapAnthropicResponseToChatCompletionResult(response, latencyMs) {
918
1229
  if (toolCalls.length > 0) {
919
1230
  result.toolCalls = toolCalls;
920
1231
  }
1232
+ if (thinkingText.length > 0) {
1233
+ result.thinkingText = thinkingText;
1234
+ }
921
1235
  if (response.stop_reason !== null && response.stop_reason !== void 0) {
922
1236
  result.stopReason = normalizeAnthropicStopReason(response.stop_reason);
923
1237
  }
@@ -930,13 +1244,16 @@ function extractAnthropicToolCalls(response) {
930
1244
  input: contentBlock.input
931
1245
  }));
932
1246
  }
1247
+ function extractAnthropicThinkingText(response) {
1248
+ return response.content.filter((contentBlock) => contentBlock.type === "thinking").map((contentBlock) => contentBlock.thinking ?? "").join("");
1249
+ }
933
1250
  function extractAnthropicTextContent(response, allowEmptyText) {
934
1251
  const textBlocks = response.content.filter(
935
1252
  (contentBlock) => contentBlock.type === "text"
936
1253
  );
937
1254
  if (textBlocks.length === 0 && !allowEmptyText) {
938
- throw new import_errors17.AppError({
939
- code: import_errors16.AppErrorCode.ValidationFailed,
1255
+ throw new import_errors19.AppError({
1256
+ code: import_errors18.AppErrorCode.ValidationFailed,
940
1257
  message: "Anthropic response contained no text content",
941
1258
  statusCode: 502
942
1259
  });
@@ -973,58 +1290,68 @@ function mapAnthropicUsageToTokenUsage(usage) {
973
1290
  }
974
1291
 
975
1292
  // src/anthropic-stream.ts
976
- var import_errors18 = require("@assemble-dev/shared-types/errors");
977
- var import_json5 = require("@assemble-dev/shared-types/json");
978
- var import_errors19 = require("@assemble-dev/shared-utils/errors");
1293
+ var import_errors20 = require("@assemble-dev/shared-types/errors");
1294
+ var import_json6 = require("@assemble-dev/shared-types/json");
1295
+ var import_errors21 = require("@assemble-dev/shared-utils/errors");
979
1296
 
980
1297
  // src/anthropic-stream-events.ts
981
- var import_zod5 = require("zod");
982
- var AnthropicStreamEventSchema = import_zod5.z.discriminatedUnion("type", [
983
- import_zod5.z.object({
984
- type: import_zod5.z.literal("message_start"),
985
- message: import_zod5.z.object({
986
- usage: import_zod5.z.object({
987
- input_tokens: import_zod5.z.number().int().nonnegative(),
988
- output_tokens: import_zod5.z.number().int().nonnegative().optional(),
989
- cache_creation_input_tokens: import_zod5.z.number().int().nonnegative().optional(),
990
- cache_read_input_tokens: import_zod5.z.number().int().nonnegative().optional()
1298
+ var import_zod6 = require("zod");
1299
+ var AnthropicStreamEventSchema = import_zod6.z.discriminatedUnion("type", [
1300
+ import_zod6.z.object({
1301
+ type: import_zod6.z.literal("message_start"),
1302
+ message: import_zod6.z.object({
1303
+ usage: import_zod6.z.object({
1304
+ input_tokens: import_zod6.z.number().int().nonnegative(),
1305
+ output_tokens: import_zod6.z.number().int().nonnegative().optional(),
1306
+ cache_creation_input_tokens: import_zod6.z.number().int().nonnegative().optional(),
1307
+ cache_read_input_tokens: import_zod6.z.number().int().nonnegative().optional()
991
1308
  })
992
1309
  })
993
1310
  }),
994
- import_zod5.z.object({
995
- type: import_zod5.z.literal("content_block_start"),
996
- index: import_zod5.z.number().int().nonnegative(),
997
- content_block: import_zod5.z.discriminatedUnion("type", [
998
- import_zod5.z.object({ type: import_zod5.z.literal("text"), text: import_zod5.z.string().optional() }),
999
- import_zod5.z.object({
1000
- type: import_zod5.z.literal("tool_use"),
1001
- id: import_zod5.z.string(),
1002
- name: import_zod5.z.string()
1311
+ import_zod6.z.object({
1312
+ type: import_zod6.z.literal("content_block_start"),
1313
+ index: import_zod6.z.number().int().nonnegative(),
1314
+ content_block: import_zod6.z.discriminatedUnion("type", [
1315
+ import_zod6.z.object({ type: import_zod6.z.literal("text"), text: import_zod6.z.string().optional() }),
1316
+ import_zod6.z.object({
1317
+ type: import_zod6.z.literal("thinking"),
1318
+ thinking: import_zod6.z.string().optional()
1319
+ }),
1320
+ import_zod6.z.object({
1321
+ type: import_zod6.z.literal("redacted_thinking"),
1322
+ data: import_zod6.z.string().optional()
1323
+ }),
1324
+ import_zod6.z.object({
1325
+ type: import_zod6.z.literal("tool_use"),
1326
+ id: import_zod6.z.string(),
1327
+ name: import_zod6.z.string()
1003
1328
  })
1004
1329
  ])
1005
1330
  }),
1006
- import_zod5.z.object({
1007
- type: import_zod5.z.literal("content_block_delta"),
1008
- index: import_zod5.z.number().int().nonnegative(),
1009
- delta: import_zod5.z.discriminatedUnion("type", [
1010
- import_zod5.z.object({ type: import_zod5.z.literal("text_delta"), text: import_zod5.z.string() }),
1011
- import_zod5.z.object({
1012
- type: import_zod5.z.literal("input_json_delta"),
1013
- partial_json: import_zod5.z.string()
1331
+ import_zod6.z.object({
1332
+ type: import_zod6.z.literal("content_block_delta"),
1333
+ index: import_zod6.z.number().int().nonnegative(),
1334
+ delta: import_zod6.z.discriminatedUnion("type", [
1335
+ import_zod6.z.object({ type: import_zod6.z.literal("text_delta"), text: import_zod6.z.string() }),
1336
+ import_zod6.z.object({ type: import_zod6.z.literal("thinking_delta"), thinking: import_zod6.z.string() }),
1337
+ import_zod6.z.object({ type: import_zod6.z.literal("signature_delta"), signature: import_zod6.z.string() }),
1338
+ import_zod6.z.object({
1339
+ type: import_zod6.z.literal("input_json_delta"),
1340
+ partial_json: import_zod6.z.string()
1014
1341
  })
1015
1342
  ])
1016
1343
  }),
1017
- import_zod5.z.object({ type: import_zod5.z.literal("content_block_stop") }),
1018
- import_zod5.z.object({
1019
- type: import_zod5.z.literal("message_delta"),
1020
- delta: import_zod5.z.object({ stop_reason: import_zod5.z.string().nullable().optional() }),
1021
- usage: import_zod5.z.object({ output_tokens: import_zod5.z.number().int().nonnegative() }).optional()
1344
+ import_zod6.z.object({ type: import_zod6.z.literal("content_block_stop") }),
1345
+ import_zod6.z.object({
1346
+ type: import_zod6.z.literal("message_delta"),
1347
+ delta: import_zod6.z.object({ stop_reason: import_zod6.z.string().nullable().optional() }),
1348
+ usage: import_zod6.z.object({ output_tokens: import_zod6.z.number().int().nonnegative() }).optional()
1022
1349
  }),
1023
- import_zod5.z.object({ type: import_zod5.z.literal("message_stop") }),
1024
- import_zod5.z.object({ type: import_zod5.z.literal("ping") }),
1025
- import_zod5.z.object({
1026
- type: import_zod5.z.literal("error"),
1027
- error: import_zod5.z.object({ message: import_zod5.z.string() })
1350
+ import_zod6.z.object({ type: import_zod6.z.literal("message_stop") }),
1351
+ import_zod6.z.object({ type: import_zod6.z.literal("ping") }),
1352
+ import_zod6.z.object({
1353
+ type: import_zod6.z.literal("error"),
1354
+ error: import_zod6.z.object({ message: import_zod6.z.string() })
1028
1355
  })
1029
1356
  ]);
1030
1357
 
@@ -1110,6 +1437,7 @@ async function* readServerSentEventDataLines(body, abortSignal) {
1110
1437
  function createAnthropicStreamAccumulator() {
1111
1438
  return {
1112
1439
  contentText: "",
1440
+ thinkingText: "",
1113
1441
  toolCallsByBlockIndex: /* @__PURE__ */ new Map(),
1114
1442
  inputTokens: 0,
1115
1443
  outputTokens: 0
@@ -1117,8 +1445,8 @@ function createAnthropicStreamAccumulator() {
1117
1445
  }
1118
1446
  function* applyAnthropicStreamEvent(event, accumulator) {
1119
1447
  if (event.type === "error") {
1120
- throw new import_errors19.AppError({
1121
- code: import_errors18.AppErrorCode.InternalServerError,
1448
+ throw new import_errors21.AppError({
1449
+ code: import_errors20.AppErrorCode.InternalServerError,
1122
1450
  message: `Anthropic stream reported an error: ${event.error.message}`,
1123
1451
  statusCode: 502
1124
1452
  });
@@ -1154,6 +1482,17 @@ function* applyAnthropicContentBlockStart(event, accumulator) {
1154
1482
  }
1155
1483
  return;
1156
1484
  }
1485
+ if (event.content_block.type === "thinking") {
1486
+ const initialThinkingText = event.content_block.thinking ?? "";
1487
+ if (initialThinkingText.length > 0) {
1488
+ accumulator.thinkingText += initialThinkingText;
1489
+ yield { type: "thinking_delta", text: initialThinkingText };
1490
+ }
1491
+ return;
1492
+ }
1493
+ if (event.content_block.type === "redacted_thinking") {
1494
+ return;
1495
+ }
1157
1496
  accumulator.toolCallsByBlockIndex.set(event.index, {
1158
1497
  id: event.content_block.id,
1159
1498
  toolName: event.content_block.name,
@@ -1171,6 +1510,14 @@ function* applyAnthropicContentBlockDelta(event, accumulator) {
1171
1510
  yield { type: "text_delta", text: event.delta.text };
1172
1511
  return;
1173
1512
  }
1513
+ if (event.delta.type === "thinking_delta") {
1514
+ accumulator.thinkingText += event.delta.thinking;
1515
+ yield { type: "thinking_delta", text: event.delta.thinking };
1516
+ return;
1517
+ }
1518
+ if (event.delta.type === "signature_delta") {
1519
+ return;
1520
+ }
1174
1521
  const toolCallAccumulation = accumulator.toolCallsByBlockIndex.get(
1175
1522
  event.index
1176
1523
  );
@@ -1217,6 +1564,9 @@ function buildAnthropicStreamResult(accumulator, latencyMs) {
1217
1564
  if (accumulator.stopReason !== void 0) {
1218
1565
  result.stopReason = accumulator.stopReason;
1219
1566
  }
1567
+ if (accumulator.thinkingText.length > 0) {
1568
+ result.thinkingText = accumulator.thinkingText;
1569
+ }
1220
1570
  return result;
1221
1571
  }
1222
1572
  function mapAccumulatedToolCallToModelToolCall(toolCallAccumulation) {
@@ -1231,10 +1581,10 @@ function parseAnthropicToolInputJson(inputJsonText) {
1231
1581
  return {};
1232
1582
  }
1233
1583
  try {
1234
- return import_json5.JsonValueSchema.parse(JSON.parse(inputJsonText));
1584
+ return import_json6.JsonValueSchema.parse(JSON.parse(inputJsonText));
1235
1585
  } catch (error) {
1236
- throw new import_errors19.AppError({
1237
- code: import_errors18.AppErrorCode.ValidationFailed,
1586
+ throw new import_errors21.AppError({
1587
+ code: import_errors20.AppErrorCode.ValidationFailed,
1238
1588
  message: "Anthropic tool input was not valid JSON",
1239
1589
  statusCode: 502,
1240
1590
  cause: error instanceof Error ? error : void 0
@@ -1246,10 +1596,6 @@ function parseAnthropicToolInputJson(inputJsonText) {
1246
1596
  var defaultAnthropicBaseUrl = "https://api.anthropic.com";
1247
1597
  var defaultAnthropicMaxOutputTokens = 1024;
1248
1598
  var anthropicApiVersion = "2023-06-01";
1249
- var structuredOutputSystemMessage2 = {
1250
- role: "system",
1251
- content: "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text."
1252
- };
1253
1599
  function anthropic(options) {
1254
1600
  return {
1255
1601
  name: `anthropic:${options.model}`,
@@ -1260,12 +1606,10 @@ function anthropic(options) {
1260
1606
  );
1261
1607
  },
1262
1608
  async generateStructuredOutput(request) {
1263
- const completion = await executeAnthropicAdapterCall(options, {
1264
- messages: [structuredOutputSystemMessage2, ...request.messages],
1265
- temperature: request.temperature ?? options.temperature,
1266
- maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1267
- abortSignal: request.abortSignal
1268
- });
1609
+ const completion = await executeAnthropicAdapterCall(
1610
+ options,
1611
+ buildAnthropicStructuredOutputInput(options, request)
1612
+ );
1269
1613
  return {
1270
1614
  value: parseStructuredJsonText(completion.content, request.schema),
1271
1615
  tokenUsage: completion.tokenUsage,
@@ -1279,6 +1623,26 @@ function anthropic(options) {
1279
1623
  }
1280
1624
  };
1281
1625
  }
1626
+ function buildAnthropicStructuredOutputInput(options, request) {
1627
+ const baseInput = {
1628
+ messages: request.messages,
1629
+ temperature: request.temperature ?? options.temperature,
1630
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1631
+ abortSignal: request.abortSignal
1632
+ };
1633
+ if (isZodV4Schema(request.schema)) {
1634
+ return {
1635
+ ...baseInput,
1636
+ structuredOutputJsonSchema: buildAnthropicStructuredOutputJsonSchema(
1637
+ request.schema
1638
+ )
1639
+ };
1640
+ }
1641
+ return {
1642
+ ...baseInput,
1643
+ messages: prependStructuredOutputJsonOnlySystemMessage(request.messages)
1644
+ };
1645
+ }
1282
1646
  function buildAnthropicCallInput(options, request) {
1283
1647
  return {
1284
1648
  messages: request.messages,
@@ -1379,28 +1743,116 @@ function resolveAnthropicFetch(options) {
1379
1743
  }
1380
1744
 
1381
1745
  // src/gemini-adapter.ts
1382
- var import_zod6 = require("zod");
1383
- var import_errors20 = require("@assemble-dev/shared-types/errors");
1384
- var import_errors21 = require("@assemble-dev/shared-utils/errors");
1746
+ var import_zod7 = require("zod");
1747
+ var import_errors22 = require("@assemble-dev/shared-types/errors");
1748
+ var import_errors23 = require("@assemble-dev/shared-utils/errors");
1749
+
1750
+ // src/gemini-response-schema.ts
1751
+ var geminiAllowedSchemaKeywords = [
1752
+ "type",
1753
+ "format",
1754
+ "description",
1755
+ "nullable",
1756
+ "enum",
1757
+ "properties",
1758
+ "required",
1759
+ "items",
1760
+ "minItems",
1761
+ "maxItems",
1762
+ "anyOf"
1763
+ ];
1764
+ var geminiAllowedFormats = [
1765
+ "date-time",
1766
+ "int32",
1767
+ "int64",
1768
+ "float",
1769
+ "double"
1770
+ ];
1771
+ function buildGeminiResponseSchema(schema) {
1772
+ return sanitizeJsonSchemaForGeminiResponseSchema(
1773
+ convertZodSchemaToJsonSchema(schema)
1774
+ );
1775
+ }
1776
+ function sanitizeJsonSchemaForGeminiResponseSchema(jsonSchema) {
1777
+ return transformJsonSchemaNode(
1778
+ inlineJsonSchemaReferences(jsonSchema),
1779
+ sanitizeGeminiSchemaNode
1780
+ );
1781
+ }
1782
+ function sanitizeGeminiSchemaNode(node) {
1783
+ const normalized = normalizeGeminiNullableType(
1784
+ mergeNullUnionIntoNullableNode(node)
1785
+ );
1786
+ const sanitized = {};
1787
+ for (const [key, value] of Object.entries(normalized)) {
1788
+ if (geminiAllowedSchemaKeywords.includes(key)) {
1789
+ sanitized[key] = value;
1790
+ }
1791
+ }
1792
+ return removeUnsupportedGeminiFormat(sanitized);
1793
+ }
1794
+ function mergeNullUnionIntoNullableNode(node) {
1795
+ const unionKeyword = Array.isArray(node["anyOf"]) ? "anyOf" : "oneOf";
1796
+ const unionMembers = node[unionKeyword];
1797
+ if (!Array.isArray(unionMembers)) {
1798
+ return node;
1799
+ }
1800
+ const nonNullMembers = unionMembers.filter(
1801
+ (member) => !isNullTypeSchemaNode(member)
1802
+ );
1803
+ if (nonNullMembers.length === unionMembers.length) {
1804
+ return node;
1805
+ }
1806
+ const merged = { ...node };
1807
+ delete merged[unionKeyword];
1808
+ const singleMember = nonNullMembers.length === 1 ? nonNullMembers[0] : void 0;
1809
+ if (singleMember !== void 0 && isJsonObject(singleMember)) {
1810
+ return { ...merged, ...singleMember, nullable: true };
1811
+ }
1812
+ return { ...merged, anyOf: nonNullMembers, nullable: true };
1813
+ }
1814
+ function normalizeGeminiNullableType(node) {
1815
+ const typeValue = node["type"];
1816
+ if (!Array.isArray(typeValue)) {
1817
+ return node;
1818
+ }
1819
+ const nonNullTypes = typeValue.filter((typeName) => typeName !== "null");
1820
+ const normalized = { ...node };
1821
+ if (nonNullTypes.length < typeValue.length) {
1822
+ normalized["nullable"] = true;
1823
+ }
1824
+ normalized["type"] = nonNullTypes[0] ?? "string";
1825
+ return normalized;
1826
+ }
1827
+ function removeUnsupportedGeminiFormat(node) {
1828
+ const formatValue = node["format"];
1829
+ if (typeof formatValue === "string" && !geminiAllowedFormats.includes(formatValue)) {
1830
+ const withoutFormat = { ...node };
1831
+ delete withoutFormat["format"];
1832
+ return withoutFormat;
1833
+ }
1834
+ return node;
1835
+ }
1836
+ function isNullTypeSchemaNode(value) {
1837
+ return isJsonObject(value) && value["type"] === "null";
1838
+ }
1839
+
1840
+ // src/gemini-adapter.ts
1385
1841
  var defaultGeminiBaseUrl = "https://generativelanguage.googleapis.com";
1386
- var GeminiGenerateContentResponseSchema = import_zod6.z.object({
1387
- candidates: import_zod6.z.array(
1388
- import_zod6.z.object({
1389
- content: import_zod6.z.object({
1390
- parts: import_zod6.z.array(import_zod6.z.object({ text: import_zod6.z.string() }))
1842
+ var GeminiGenerateContentResponseSchema = import_zod7.z.object({
1843
+ candidates: import_zod7.z.array(
1844
+ import_zod7.z.object({
1845
+ content: import_zod7.z.object({
1846
+ parts: import_zod7.z.array(import_zod7.z.object({ text: import_zod7.z.string() }))
1391
1847
  })
1392
1848
  })
1393
1849
  ).optional(),
1394
- usageMetadata: import_zod6.z.object({
1395
- promptTokenCount: import_zod6.z.number().int().nonnegative().optional(),
1396
- candidatesTokenCount: import_zod6.z.number().int().nonnegative().optional(),
1397
- totalTokenCount: import_zod6.z.number().int().nonnegative().optional()
1850
+ usageMetadata: import_zod7.z.object({
1851
+ promptTokenCount: import_zod7.z.number().int().nonnegative().optional(),
1852
+ candidatesTokenCount: import_zod7.z.number().int().nonnegative().optional(),
1853
+ totalTokenCount: import_zod7.z.number().int().nonnegative().optional()
1398
1854
  }).optional()
1399
1855
  });
1400
- var structuredOutputSystemMessage3 = {
1401
- role: "system",
1402
- content: "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text."
1403
- };
1404
1856
  function gemini(options) {
1405
1857
  return {
1406
1858
  name: `gemini:${options.model}`,
@@ -1410,19 +1862,15 @@ function gemini(options) {
1410
1862
  messages: request.messages,
1411
1863
  temperature: request.temperature ?? options.temperature,
1412
1864
  maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1413
- requireJsonResponse: false,
1414
1865
  abortSignal: request.abortSignal,
1415
1866
  extraBody: request.extraBody
1416
1867
  });
1417
1868
  },
1418
1869
  async generateStructuredOutput(request) {
1419
- const completion = await executeGeminiAdapterCall(options, {
1420
- messages: [structuredOutputSystemMessage3, ...request.messages],
1421
- temperature: request.temperature ?? options.temperature,
1422
- maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1423
- requireJsonResponse: true,
1424
- abortSignal: request.abortSignal
1425
- });
1870
+ const completion = await executeGeminiAdapterCall(
1871
+ options,
1872
+ buildGeminiStructuredOutputInput(options, request)
1873
+ );
1426
1874
  return {
1427
1875
  value: parseStructuredJsonText(completion.content, request.schema),
1428
1876
  tokenUsage: completion.tokenUsage,
@@ -1431,16 +1879,35 @@ function gemini(options) {
1431
1879
  }
1432
1880
  };
1433
1881
  }
1434
- async function executeGeminiAdapterCall(options, input) {
1435
- return await executeProviderCallWithModelFallback(
1436
- options.fallbackModel,
1437
- async () => await executeProviderCallWithRetry(
1438
- options.retry,
1439
- async () => await requestGeminiGenerateContent(options, input)
1440
- ),
1441
- async (fallbackModelId) => await requestGeminiGenerateContent(
1442
- { ...options, model: fallbackModelId },
1443
- input
1882
+ function buildGeminiStructuredOutputInput(options, request) {
1883
+ const baseInput = {
1884
+ messages: request.messages,
1885
+ temperature: request.temperature ?? options.temperature,
1886
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
1887
+ abortSignal: request.abortSignal
1888
+ };
1889
+ if (isZodV4Schema(request.schema)) {
1890
+ return {
1891
+ ...baseInput,
1892
+ responseSchema: buildGeminiResponseSchema(request.schema)
1893
+ };
1894
+ }
1895
+ return {
1896
+ ...baseInput,
1897
+ messages: prependStructuredOutputJsonOnlySystemMessage(request.messages),
1898
+ requireJsonResponse: true
1899
+ };
1900
+ }
1901
+ async function executeGeminiAdapterCall(options, input) {
1902
+ return await executeProviderCallWithModelFallback(
1903
+ options.fallbackModel,
1904
+ async () => await executeProviderCallWithRetry(
1905
+ options.retry,
1906
+ async () => await requestGeminiGenerateContent(options, input)
1907
+ ),
1908
+ async (fallbackModelId) => await requestGeminiGenerateContent(
1909
+ { ...options, model: fallbackModelId },
1910
+ input
1444
1911
  )
1445
1912
  );
1446
1913
  }
@@ -1507,8 +1974,8 @@ function ensureGeminiRequestHasNoTools(request) {
1507
1974
  if (request.tools === void 0 || request.tools.length === 0) {
1508
1975
  return;
1509
1976
  }
1510
- throw new import_errors21.AppError({
1511
- code: import_errors20.AppErrorCode.ValidationFailed,
1977
+ throw new import_errors23.AppError({
1978
+ code: import_errors22.AppErrorCode.ValidationFailed,
1512
1979
  message: "gemini adapter does not support model-driven tool use; remove tools from the request or use another adapter",
1513
1980
  statusCode: 400
1514
1981
  });
@@ -1545,7 +2012,10 @@ function buildGeminiGenerationConfig(input) {
1545
2012
  if (input.maxOutputTokens !== void 0) {
1546
2013
  generationConfig.maxOutputTokens = input.maxOutputTokens;
1547
2014
  }
1548
- if (input.requireJsonResponse) {
2015
+ if (input.responseSchema !== void 0) {
2016
+ generationConfig.responseMimeType = "application/json";
2017
+ generationConfig.responseSchema = input.responseSchema;
2018
+ } else if (input.requireJsonResponse === true) {
1549
2019
  generationConfig.responseMimeType = "application/json";
1550
2020
  }
1551
2021
  if (Object.keys(generationConfig).length === 0) {
@@ -1556,8 +2026,8 @@ function buildGeminiGenerationConfig(input) {
1556
2026
  function extractGeminiCandidateText(response) {
1557
2027
  const firstCandidate = response.candidates?.[0];
1558
2028
  if (firstCandidate === void 0) {
1559
- throw new import_errors21.AppError({
1560
- code: import_errors20.AppErrorCode.ValidationFailed,
2029
+ throw new import_errors23.AppError({
2030
+ code: import_errors22.AppErrorCode.ValidationFailed,
1561
2031
  message: "Gemini response contained no candidates",
1562
2032
  statusCode: 502
1563
2033
  });
@@ -1576,8 +2046,8 @@ function mapGeminiUsageToTokenUsage(response) {
1576
2046
  }
1577
2047
 
1578
2048
  // src/mock-adapter.ts
1579
- var import_errors22 = require("@assemble-dev/shared-types/errors");
1580
- var import_errors23 = require("@assemble-dev/shared-utils/errors");
2049
+ var import_errors24 = require("@assemble-dev/shared-types/errors");
2050
+ var import_errors25 = require("@assemble-dev/shared-utils/errors");
1581
2051
  var mockStreamChunkCount = 3;
1582
2052
  function mockModel(options = {}) {
1583
2053
  const remainingScriptedResponses = [...options.scriptedResponses ?? []];
@@ -1657,8 +2127,8 @@ function resolveNextMockResponseText(request, remainingScriptedResponses, respon
1657
2127
  if (respond !== void 0) {
1658
2128
  return respond(request);
1659
2129
  }
1660
- throw new import_errors23.AppError({
1661
- code: import_errors22.AppErrorCode.BadRequest,
2130
+ throw new import_errors25.AppError({
2131
+ code: import_errors24.AppErrorCode.BadRequest,
1662
2132
  message: "Mock model has no scripted responses left and no respond function was provided",
1663
2133
  statusCode: 400
1664
2134
  });
@@ -1746,24 +2216,24 @@ function calculateModelCallCostUsd(pricing, tokenUsage) {
1746
2216
  }
1747
2217
 
1748
2218
  // src/anthropic-batch.ts
2219
+ var import_errors28 = require("@assemble-dev/shared-types/errors");
2220
+ var import_json8 = require("@assemble-dev/shared-types/json");
2221
+ var import_errors29 = require("@assemble-dev/shared-utils/errors");
2222
+
2223
+ // src/anthropic-batch-structured.ts
1749
2224
  var import_errors26 = require("@assemble-dev/shared-types/errors");
1750
2225
  var import_json7 = require("@assemble-dev/shared-types/json");
1751
2226
  var import_errors27 = require("@assemble-dev/shared-utils/errors");
1752
-
1753
- // src/anthropic-batch-structured.ts
1754
- var import_errors24 = require("@assemble-dev/shared-types/errors");
1755
- var import_json6 = require("@assemble-dev/shared-types/json");
1756
- var import_errors25 = require("@assemble-dev/shared-utils/errors");
1757
- var anthropicBatchJsonOnlySystemInstruction = "Respond with a single JSON object that satisfies the caller's requested structure. Output only valid JSON with no surrounding text.";
2227
+ var anthropicBatchJsonOnlySystemInstruction = structuredOutputJsonOnlySystemInstruction;
1758
2228
  function parseAnthropicBatchStructuredContent(content, schema) {
1759
2229
  const jsonValue = parseStructuredJsonText(
1760
2230
  content,
1761
- import_json6.JsonValueSchema
2231
+ import_json7.JsonValueSchema
1762
2232
  );
1763
2233
  const validationResult = schema.safeParse(jsonValue);
1764
2234
  if (!validationResult.success) {
1765
- throw new import_errors25.AppError({
1766
- code: import_errors24.AppErrorCode.ValidationFailed,
2235
+ throw new import_errors27.AppError({
2236
+ code: import_errors26.AppErrorCode.ValidationFailed,
1767
2237
  message: "Anthropic batch structured output did not match the expected schema",
1768
2238
  statusCode: 422,
1769
2239
  details: { validationErrorMessage: validationResult.error.message }
@@ -1780,11 +2250,25 @@ function mapBatchMessageRequestToApiBatchRequest(request) {
1780
2250
  messages: request.messages.filter((message) => message.role !== "system").map(mapChatMessageToBatchApiRequestMessage)
1781
2251
  };
1782
2252
  applyBatchSystemField(params, request);
2253
+ applyBatchStructuredOutputConfig(params, request);
1783
2254
  if (request.temperature !== void 0) {
1784
2255
  params.temperature = request.temperature;
1785
2256
  }
1786
2257
  return { custom_id: request.customId, params };
1787
2258
  }
2259
+ function applyBatchStructuredOutputConfig(params, request) {
2260
+ if (request.structuredOutputJsonSchema === void 0) {
2261
+ return;
2262
+ }
2263
+ params.output_config = {
2264
+ format: {
2265
+ type: "json_schema",
2266
+ schema: sanitizeJsonSchemaForAnthropicStructuredOutput(
2267
+ request.structuredOutputJsonSchema
2268
+ )
2269
+ }
2270
+ };
2271
+ }
1788
2272
  function applyBatchSystemField(params, request) {
1789
2273
  const systemText = buildBatchSystemText(request);
1790
2274
  if (systemText.length === 0) {
@@ -1800,7 +2284,7 @@ function applyBatchSystemField(params, request) {
1800
2284
  }
1801
2285
  function buildBatchSystemText(request) {
1802
2286
  const joinedSystemText = joinBatchSystemMessageText(request.messages);
1803
- if (request.requireJsonResponse !== true) {
2287
+ if (request.requireJsonResponse !== true || request.structuredOutputJsonSchema !== void 0) {
1804
2288
  return joinedSystemText;
1805
2289
  }
1806
2290
  if (joinedSystemText.length === 0) {
@@ -1951,55 +2435,55 @@ function buildBatchResultEvent(eventBase, batchId, result, modelName) {
1951
2435
  }
1952
2436
 
1953
2437
  // src/anthropic-batch-types.ts
1954
- var import_zod7 = require("zod");
1955
- var AnthropicMessageBatchResponseSchema = import_zod7.z.object({
1956
- id: import_zod7.z.string(),
1957
- processing_status: import_zod7.z.enum(["in_progress", "canceling", "ended"]),
1958
- request_counts: import_zod7.z.object({
1959
- processing: import_zod7.z.number().int().nonnegative(),
1960
- succeeded: import_zod7.z.number().int().nonnegative(),
1961
- errored: import_zod7.z.number().int().nonnegative(),
1962
- canceled: import_zod7.z.number().int().nonnegative(),
1963
- expired: import_zod7.z.number().int().nonnegative()
2438
+ var import_zod8 = require("zod");
2439
+ var AnthropicMessageBatchResponseSchema = import_zod8.z.object({
2440
+ id: import_zod8.z.string(),
2441
+ processing_status: import_zod8.z.enum(["in_progress", "canceling", "ended"]),
2442
+ request_counts: import_zod8.z.object({
2443
+ processing: import_zod8.z.number().int().nonnegative(),
2444
+ succeeded: import_zod8.z.number().int().nonnegative(),
2445
+ errored: import_zod8.z.number().int().nonnegative(),
2446
+ canceled: import_zod8.z.number().int().nonnegative(),
2447
+ expired: import_zod8.z.number().int().nonnegative()
1964
2448
  }),
1965
- results_url: import_zod7.z.string().nullable(),
1966
- created_at: import_zod7.z.string(),
1967
- ended_at: import_zod7.z.string().nullable()
2449
+ results_url: import_zod8.z.string().nullable(),
2450
+ created_at: import_zod8.z.string(),
2451
+ ended_at: import_zod8.z.string().nullable()
1968
2452
  });
1969
- var AnthropicBatchContentBlockSchema = import_zod7.z.discriminatedUnion("type", [
1970
- import_zod7.z.object({
1971
- type: import_zod7.z.literal("text"),
1972
- text: import_zod7.z.string()
2453
+ var AnthropicBatchContentBlockSchema = import_zod8.z.discriminatedUnion("type", [
2454
+ import_zod8.z.object({
2455
+ type: import_zod8.z.literal("text"),
2456
+ text: import_zod8.z.string()
1973
2457
  }),
1974
- import_zod7.z.object({
1975
- type: import_zod7.z.literal("thinking"),
1976
- thinking: import_zod7.z.string().optional(),
1977
- signature: import_zod7.z.string().optional()
2458
+ import_zod8.z.object({
2459
+ type: import_zod8.z.literal("thinking"),
2460
+ thinking: import_zod8.z.string().optional(),
2461
+ signature: import_zod8.z.string().optional()
1978
2462
  }),
1979
- import_zod7.z.object({
1980
- type: import_zod7.z.literal("redacted_thinking"),
1981
- data: import_zod7.z.string().optional()
2463
+ import_zod8.z.object({
2464
+ type: import_zod8.z.literal("redacted_thinking"),
2465
+ data: import_zod8.z.string().optional()
1982
2466
  })
1983
2467
  ]);
1984
- var AnthropicBatchResultLineSchema = import_zod7.z.object({
1985
- custom_id: import_zod7.z.string(),
1986
- result: import_zod7.z.discriminatedUnion("type", [
1987
- import_zod7.z.object({
1988
- type: import_zod7.z.literal("succeeded"),
1989
- message: import_zod7.z.object({
1990
- content: import_zod7.z.array(AnthropicBatchContentBlockSchema),
2468
+ var AnthropicBatchResultLineSchema = import_zod8.z.object({
2469
+ custom_id: import_zod8.z.string(),
2470
+ result: import_zod8.z.discriminatedUnion("type", [
2471
+ import_zod8.z.object({
2472
+ type: import_zod8.z.literal("succeeded"),
2473
+ message: import_zod8.z.object({
2474
+ content: import_zod8.z.array(AnthropicBatchContentBlockSchema),
1991
2475
  usage: AnthropicUsageSchema
1992
2476
  })
1993
2477
  }),
1994
- import_zod7.z.object({
1995
- type: import_zod7.z.literal("errored"),
1996
- error: import_zod7.z.object({
1997
- type: import_zod7.z.string(),
1998
- message: import_zod7.z.string()
2478
+ import_zod8.z.object({
2479
+ type: import_zod8.z.literal("errored"),
2480
+ error: import_zod8.z.object({
2481
+ type: import_zod8.z.string(),
2482
+ message: import_zod8.z.string()
1999
2483
  })
2000
2484
  }),
2001
- import_zod7.z.object({ type: import_zod7.z.literal("canceled") }),
2002
- import_zod7.z.object({ type: import_zod7.z.literal("expired") })
2485
+ import_zod8.z.object({ type: import_zod8.z.literal("canceled") }),
2486
+ import_zod8.z.object({ type: import_zod8.z.literal("expired") })
2003
2487
  ])
2004
2488
  });
2005
2489
  function mapAnthropicMessageBatchResponseToMessageBatch(response) {
@@ -2149,8 +2633,8 @@ async function parseAnthropicMessageBatchHttpResponse(response) {
2149
2633
  async function listAnthropicMessageBatchResults(clientContext, batchId) {
2150
2634
  const batch = await fetchAnthropicMessageBatch(clientContext, batchId);
2151
2635
  if (batch.resultsUrl === null) {
2152
- throw new import_errors27.AppError({
2153
- code: import_errors26.AppErrorCode.Conflict,
2636
+ throw new import_errors29.AppError({
2637
+ code: import_errors28.AppErrorCode.Conflict,
2154
2638
  message: `Anthropic message batch ${batchId} has no results because processing has not ended`,
2155
2639
  statusCode: 409,
2156
2640
  details: { batchId, processingStatus: batch.processingStatus }
@@ -2187,7 +2671,7 @@ function parseAnthropicBatchResultLine(line) {
2187
2671
  }
2188
2672
  function parseAnthropicBatchResultLineJson(line) {
2189
2673
  try {
2190
- return import_json7.JsonValueSchema.parse(JSON.parse(line));
2674
+ return import_json8.JsonValueSchema.parse(JSON.parse(line));
2191
2675
  } catch {
2192
2676
  throw buildProviderInvalidResponseError(
2193
2677
  "Anthropic",
@@ -2211,17 +2695,764 @@ async function waitForAnthropicMessageBatchCompletion(clientContext, batchId, wa
2211
2695
  return batch;
2212
2696
  }
2213
2697
  function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
2214
- return new import_errors27.AppError({
2215
- code: import_errors26.AppErrorCode.ServiceUnavailable,
2698
+ return new import_errors29.AppError({
2699
+ code: import_errors28.AppErrorCode.ServiceUnavailable,
2216
2700
  message: `Anthropic message batch ${batchId} did not complete within ${String(timeoutMs)}ms`,
2217
2701
  statusCode: 504,
2218
2702
  details: { batchId, timeoutMs }
2219
2703
  });
2220
2704
  }
2705
+
2706
+ // src/azure-openai-adapter.ts
2707
+ var import_errors32 = require("@assemble-dev/shared-types/errors");
2708
+ var import_errors33 = require("@assemble-dev/shared-utils/errors");
2709
+
2710
+ // src/azure-openai-response-parsing.ts
2711
+ var import_zod9 = require("zod");
2712
+ var import_errors30 = require("@assemble-dev/shared-types/errors");
2713
+ var import_json9 = require("@assemble-dev/shared-types/json");
2714
+ var import_errors31 = require("@assemble-dev/shared-utils/errors");
2715
+ var AzureOpenAiUsageSchema = import_zod9.z.object({
2716
+ prompt_tokens: import_zod9.z.number().int().nonnegative(),
2717
+ completion_tokens: import_zod9.z.number().int().nonnegative(),
2718
+ total_tokens: import_zod9.z.number().int().nonnegative()
2719
+ });
2720
+ var AzureOpenAiResponseToolCallSchema = import_zod9.z.object({
2721
+ id: import_zod9.z.string(),
2722
+ function: import_zod9.z.object({
2723
+ name: import_zod9.z.string(),
2724
+ arguments: import_zod9.z.string()
2725
+ })
2726
+ });
2727
+ var AzureOpenAiChatCompletionResponseSchema = import_zod9.z.object({
2728
+ choices: import_zod9.z.array(
2729
+ import_zod9.z.object({
2730
+ message: import_zod9.z.object({
2731
+ content: import_zod9.z.string().nullable(),
2732
+ tool_calls: import_zod9.z.array(AzureOpenAiResponseToolCallSchema).optional()
2733
+ }),
2734
+ finish_reason: import_zod9.z.string().nullable().optional()
2735
+ })
2736
+ ).min(1),
2737
+ usage: AzureOpenAiUsageSchema
2738
+ });
2739
+ function mapAzureOpenAiResponseToChatCompletionResult(response, latencyMs) {
2740
+ const toolCalls = extractAzureOpenAiToolCalls(response);
2741
+ const result = {
2742
+ content: extractAzureOpenAiMessageContent(response, toolCalls.length > 0),
2743
+ tokenUsage: mapAzureOpenAiUsageToTokenUsage(response.usage),
2744
+ latencyMs
2745
+ };
2746
+ const finishReason = response.choices[0]?.finish_reason;
2747
+ if (toolCalls.length > 0) {
2748
+ result.toolCalls = toolCalls;
2749
+ }
2750
+ if (finishReason !== null && finishReason !== void 0) {
2751
+ result.stopReason = normalizeAzureOpenAiFinishReason(finishReason);
2752
+ }
2753
+ return result;
2754
+ }
2755
+ function extractAzureOpenAiToolCalls(response) {
2756
+ const responseToolCalls = response.choices[0]?.message.tool_calls ?? [];
2757
+ return responseToolCalls.map((responseToolCall) => ({
2758
+ id: responseToolCall.id,
2759
+ toolName: responseToolCall.function.name,
2760
+ input: parseAzureOpenAiToolArgumentsJson(responseToolCall.function.arguments)
2761
+ }));
2762
+ }
2763
+ function parseAzureOpenAiToolArgumentsJson(argumentsJsonText) {
2764
+ if (argumentsJsonText.trim().length === 0) {
2765
+ return {};
2766
+ }
2767
+ try {
2768
+ return import_json9.JsonValueSchema.parse(JSON.parse(argumentsJsonText));
2769
+ } catch (error) {
2770
+ throw new import_errors31.AppError({
2771
+ code: import_errors30.AppErrorCode.ValidationFailed,
2772
+ message: "Azure OpenAI tool call arguments were not valid JSON",
2773
+ statusCode: 502,
2774
+ cause: error instanceof Error ? error : void 0
2775
+ });
2776
+ }
2777
+ }
2778
+ function normalizeAzureOpenAiFinishReason(finishReason) {
2779
+ if (finishReason === "tool_calls") {
2780
+ return "tool_use";
2781
+ }
2782
+ if (finishReason === "length") {
2783
+ return "max_tokens";
2784
+ }
2785
+ return "end_turn";
2786
+ }
2787
+ function extractAzureOpenAiMessageContent(response, allowEmptyContent) {
2788
+ const content = response.choices[0]?.message.content;
2789
+ if (content === void 0 || content === null) {
2790
+ if (allowEmptyContent) {
2791
+ return "";
2792
+ }
2793
+ throw new import_errors31.AppError({
2794
+ code: import_errors30.AppErrorCode.ValidationFailed,
2795
+ message: "Azure OpenAI response contained no message content",
2796
+ statusCode: 502
2797
+ });
2798
+ }
2799
+ return content;
2800
+ }
2801
+ function mapAzureOpenAiUsageToTokenUsage(usage) {
2802
+ return {
2803
+ inputTokens: usage.prompt_tokens,
2804
+ outputTokens: usage.completion_tokens,
2805
+ totalTokens: usage.total_tokens
2806
+ };
2807
+ }
2808
+
2809
+ // src/azure-openai-stream.ts
2810
+ var import_zod10 = require("zod");
2811
+ var AzureOpenAiStreamToolCallDeltaSchema = import_zod10.z.object({
2812
+ index: import_zod10.z.number().int().nonnegative(),
2813
+ id: import_zod10.z.string().optional(),
2814
+ function: import_zod10.z.object({
2815
+ name: import_zod10.z.string().optional(),
2816
+ arguments: import_zod10.z.string().optional()
2817
+ }).optional()
2818
+ });
2819
+ var AzureOpenAiStreamChunkSchema = import_zod10.z.object({
2820
+ choices: import_zod10.z.array(
2821
+ import_zod10.z.object({
2822
+ delta: import_zod10.z.object({
2823
+ content: import_zod10.z.string().nullable().optional(),
2824
+ tool_calls: import_zod10.z.array(AzureOpenAiStreamToolCallDeltaSchema).optional()
2825
+ }).optional(),
2826
+ finish_reason: import_zod10.z.string().nullable().optional()
2827
+ })
2828
+ ).optional(),
2829
+ usage: AzureOpenAiUsageSchema.nullable().optional()
2830
+ });
2831
+ async function* streamAzureOpenAiChatCompletion(input) {
2832
+ const startedAt = Date.now();
2833
+ const response = await establishAzureOpenAiStreamResponse(input);
2834
+ if (response.body === null) {
2835
+ throw buildProviderInvalidResponseError("Azure OpenAI", "stream body");
2836
+ }
2837
+ yield* parseAzureOpenAiStreamEvents(
2838
+ response.body,
2839
+ startedAt,
2840
+ input.abortSignal
2841
+ );
2842
+ }
2843
+ async function establishAzureOpenAiStreamResponse(input) {
2844
+ return await executeProviderCallWithRetry(input.retry, async () => {
2845
+ const response = await executeAbortableProviderFetch(
2846
+ "Azure OpenAI",
2847
+ async () => await input.fetchImplementation(input.url, {
2848
+ method: "POST",
2849
+ headers: input.headers,
2850
+ body: JSON.stringify(input.body),
2851
+ signal: input.abortSignal
2852
+ })
2853
+ );
2854
+ if (!response.ok) {
2855
+ throw buildProviderStatusError("Azure OpenAI", response.status);
2856
+ }
2857
+ return response;
2858
+ });
2859
+ }
2860
+ async function* parseAzureOpenAiStreamEvents(body, startedAt, abortSignal) {
2861
+ const accumulator = createAzureOpenAiStreamAccumulator();
2862
+ for await (const dataText of readServerSentEventDataLines2(body, abortSignal)) {
2863
+ if (dataText === "[DONE]") {
2864
+ yield {
2865
+ type: "completed",
2866
+ result: buildAzureOpenAiStreamResult(
2867
+ accumulator,
2868
+ Date.now() - startedAt
2869
+ )
2870
+ };
2871
+ return;
2872
+ }
2873
+ const parsedChunk = AzureOpenAiStreamChunkSchema.safeParse(
2874
+ JSON.parse(dataText)
2875
+ );
2876
+ if (!parsedChunk.success) {
2877
+ continue;
2878
+ }
2879
+ yield* applyAzureOpenAiStreamChunk(parsedChunk.data, accumulator);
2880
+ }
2881
+ throw buildProviderInvalidResponseError("Azure OpenAI", "stream termination");
2882
+ }
2883
+ async function* readServerSentEventDataLines2(body, abortSignal) {
2884
+ const reader = body.getReader();
2885
+ const decoder = new TextDecoder();
2886
+ let bufferedText = "";
2887
+ try {
2888
+ for (; ; ) {
2889
+ if (abortSignal?.aborted === true) {
2890
+ await reader.cancel();
2891
+ throw buildProviderCanceledError("Azure OpenAI");
2892
+ }
2893
+ const readResult = await reader.read();
2894
+ if (readResult.done) {
2895
+ return;
2896
+ }
2897
+ bufferedText += decoder.decode(readResult.value, { stream: true });
2898
+ const lines = bufferedText.split("\n");
2899
+ bufferedText = lines.pop() ?? "";
2900
+ for (const line of lines) {
2901
+ if (line.startsWith("data:")) {
2902
+ const dataText = line.slice("data:".length).trim();
2903
+ if (dataText.length > 0) {
2904
+ yield dataText;
2905
+ }
2906
+ }
2907
+ }
2908
+ }
2909
+ } catch (error) {
2910
+ if (error instanceof Error && isAbortError(error)) {
2911
+ throw buildProviderCanceledError("Azure OpenAI");
2912
+ }
2913
+ throw error;
2914
+ }
2915
+ }
2916
+ function createAzureOpenAiStreamAccumulator() {
2917
+ return {
2918
+ contentText: "",
2919
+ toolCallsByIndex: /* @__PURE__ */ new Map()
2920
+ };
2921
+ }
2922
+ function* applyAzureOpenAiStreamChunk(chunk, accumulator) {
2923
+ if (chunk.usage !== null && chunk.usage !== void 0) {
2924
+ accumulator.usage = chunk.usage;
2925
+ }
2926
+ const choice = chunk.choices?.[0];
2927
+ if (choice === void 0) {
2928
+ return;
2929
+ }
2930
+ if (choice.finish_reason !== null && choice.finish_reason !== void 0) {
2931
+ accumulator.finishReason = choice.finish_reason;
2932
+ }
2933
+ if (choice.delta === void 0) {
2934
+ return;
2935
+ }
2936
+ const contentDelta = choice.delta.content;
2937
+ if (contentDelta !== null && contentDelta !== void 0 && contentDelta.length > 0) {
2938
+ accumulator.contentText += contentDelta;
2939
+ yield { type: "text_delta", text: contentDelta };
2940
+ }
2941
+ for (const toolCallDelta of choice.delta.tool_calls ?? []) {
2942
+ yield* applyAzureOpenAiToolCallDelta(toolCallDelta, accumulator);
2943
+ }
2944
+ }
2945
+ function* applyAzureOpenAiToolCallDelta(toolCallDelta, accumulator) {
2946
+ const existingToolCall = accumulator.toolCallsByIndex.get(toolCallDelta.index);
2947
+ if (existingToolCall === void 0) {
2948
+ yield* startAzureOpenAiToolCallAccumulation(toolCallDelta, accumulator);
2949
+ return;
2950
+ }
2951
+ const argumentsDelta = toolCallDelta.function?.arguments;
2952
+ if (argumentsDelta !== void 0 && argumentsDelta.length > 0) {
2953
+ existingToolCall.argumentsJsonText += argumentsDelta;
2954
+ yield {
2955
+ type: "tool_call_input_delta",
2956
+ id: existingToolCall.id,
2957
+ inputJsonText: argumentsDelta
2958
+ };
2959
+ }
2960
+ }
2961
+ function* startAzureOpenAiToolCallAccumulation(toolCallDelta, accumulator) {
2962
+ const toolName = toolCallDelta.function?.name;
2963
+ if (toolCallDelta.id === void 0 || toolName === void 0) {
2964
+ throw buildProviderInvalidResponseError(
2965
+ "Azure OpenAI",
2966
+ "stream tool call start"
2967
+ );
2968
+ }
2969
+ const startedToolCall = {
2970
+ id: toolCallDelta.id,
2971
+ toolName,
2972
+ argumentsJsonText: toolCallDelta.function?.arguments ?? ""
2973
+ };
2974
+ accumulator.toolCallsByIndex.set(toolCallDelta.index, startedToolCall);
2975
+ yield {
2976
+ type: "tool_call_started",
2977
+ id: startedToolCall.id,
2978
+ toolName: startedToolCall.toolName
2979
+ };
2980
+ if (startedToolCall.argumentsJsonText.length > 0) {
2981
+ yield {
2982
+ type: "tool_call_input_delta",
2983
+ id: startedToolCall.id,
2984
+ inputJsonText: startedToolCall.argumentsJsonText
2985
+ };
2986
+ }
2987
+ }
2988
+ function buildAzureOpenAiStreamResult(accumulator, latencyMs) {
2989
+ const result = {
2990
+ content: accumulator.contentText,
2991
+ tokenUsage: mapAzureOpenAiUsageToTokenUsage(
2992
+ accumulator.usage ?? {
2993
+ prompt_tokens: 0,
2994
+ completion_tokens: 0,
2995
+ total_tokens: 0
2996
+ }
2997
+ ),
2998
+ latencyMs
2999
+ };
3000
+ const toolCalls = [...accumulator.toolCallsByIndex.values()].map(
3001
+ mapAccumulatedToolCallToModelToolCall2
3002
+ );
3003
+ if (toolCalls.length > 0) {
3004
+ result.toolCalls = toolCalls;
3005
+ }
3006
+ if (accumulator.finishReason !== void 0) {
3007
+ result.stopReason = normalizeAzureOpenAiFinishReason(
3008
+ accumulator.finishReason
3009
+ );
3010
+ }
3011
+ return result;
3012
+ }
3013
+ function mapAccumulatedToolCallToModelToolCall2(toolCallAccumulation) {
3014
+ return {
3015
+ id: toolCallAccumulation.id,
3016
+ toolName: toolCallAccumulation.toolName,
3017
+ input: parseAzureOpenAiToolArgumentsJson(
3018
+ toolCallAccumulation.argumentsJsonText
3019
+ )
3020
+ };
3021
+ }
3022
+
3023
+ // src/azure-openai-adapter.ts
3024
+ var defaultAzureOpenAiApiVersion = "2024-10-21";
3025
+ var azureDeploymentModelPlaceholder = "azure-deployment";
3026
+ function azureOpenai(options) {
3027
+ return {
3028
+ name: `azure-openai:${options.deployment}`,
3029
+ async generateChatCompletion(request) {
3030
+ return await executeAzureOpenAiAdapterCall(options, {
3031
+ messages: request.messages,
3032
+ temperature: request.temperature ?? options.temperature,
3033
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
3034
+ reasoningModel: options.reasoningModel,
3035
+ tools: request.tools,
3036
+ toolChoice: request.toolChoice,
3037
+ abortSignal: request.abortSignal,
3038
+ extraBody: request.extraBody
3039
+ });
3040
+ },
3041
+ async generateStructuredOutput(request) {
3042
+ const completion = await executeAzureOpenAiAdapterCall(options, {
3043
+ ...resolveOpenAiStructuredOutputMode(request.messages, request.schema),
3044
+ temperature: request.temperature ?? options.temperature,
3045
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
3046
+ reasoningModel: options.reasoningModel,
3047
+ abortSignal: request.abortSignal
3048
+ });
3049
+ return {
3050
+ value: parseStructuredJsonText(completion.content, request.schema),
3051
+ tokenUsage: completion.tokenUsage,
3052
+ latencyMs: completion.latencyMs
3053
+ };
3054
+ },
3055
+ streamChatCompletion(request) {
3056
+ return streamAzureOpenAiChatCompletion(
3057
+ buildAzureOpenAiStreamInput(options, request)
3058
+ );
3059
+ }
3060
+ };
3061
+ }
3062
+ function buildAzureOpenAiChatCompletionsUrl(options) {
3063
+ const endpoint = resolveAzureOpenAiEndpoint(options);
3064
+ const apiVersion = options.apiVersion ?? defaultAzureOpenAiApiVersion;
3065
+ return `${endpoint}/openai/deployments/${encodeURIComponent(options.deployment)}/chat/completions?api-version=${encodeURIComponent(apiVersion)}`;
3066
+ }
3067
+ function resolveAzureOpenAiEndpoint(options) {
3068
+ if (options.baseURL !== void 0 && options.baseURL.length > 0) {
3069
+ return options.baseURL.replace(/\/+$/, "");
3070
+ }
3071
+ if (options.resourceName !== void 0 && options.resourceName.length > 0) {
3072
+ return `https://${options.resourceName}.openai.azure.com`;
3073
+ }
3074
+ throw new import_errors33.AppError({
3075
+ code: import_errors32.AppErrorCode.BadRequest,
3076
+ message: "Azure OpenAI endpoint is missing. Pass resourceName or baseURL to azureOpenai().",
3077
+ statusCode: 400
3078
+ });
3079
+ }
3080
+ function buildAzureOpenAiRequestHeaders(options) {
3081
+ return {
3082
+ "content-type": "application/json",
3083
+ "api-key": resolveProviderApiKey({
3084
+ providerLabel: "Azure OpenAI",
3085
+ adapterFunctionName: "azureOpenai()",
3086
+ baseEnvVarName: "AZURE_OPENAI_API_KEY",
3087
+ apiKey: options.apiKey,
3088
+ apiKeyName: options.apiKeyName
3089
+ })
3090
+ };
3091
+ }
3092
+ function buildAzureOpenAiChatRequestBody(input) {
3093
+ const requestBody = buildOpenAiRequestBody(
3094
+ azureDeploymentModelPlaceholder,
3095
+ input
3096
+ );
3097
+ const { model: ignoredModel, ...requestBodyWithoutModel } = requestBody;
3098
+ void ignoredModel;
3099
+ return requestBodyWithoutModel;
3100
+ }
3101
+ async function executeAzureOpenAiAdapterCall(options, input) {
3102
+ return await executeProviderCallWithRetry(
3103
+ options.retry,
3104
+ async () => await requestAzureOpenAiChatCompletion(options, input)
3105
+ );
3106
+ }
3107
+ async function requestAzureOpenAiChatCompletion(options, input) {
3108
+ const fetchImplementation = options.fetchImplementation ?? fetch;
3109
+ const requestBody = mergeProviderRequestExtraBody(
3110
+ buildAzureOpenAiChatRequestBody(input),
3111
+ options.extraBody,
3112
+ input.extraBody
3113
+ );
3114
+ const startedAt = Date.now();
3115
+ const response = await executeAbortableProviderFetch(
3116
+ "Azure OpenAI",
3117
+ async () => await fetchImplementation(buildAzureOpenAiChatCompletionsUrl(options), {
3118
+ method: "POST",
3119
+ headers: buildAzureOpenAiRequestHeaders(options),
3120
+ body: JSON.stringify(requestBody),
3121
+ signal: input.abortSignal
3122
+ })
3123
+ );
3124
+ const latencyMs = Date.now() - startedAt;
3125
+ if (!response.ok) {
3126
+ throw buildProviderStatusError("Azure OpenAI", response.status);
3127
+ }
3128
+ const parseResult = AzureOpenAiChatCompletionResponseSchema.safeParse(
3129
+ await response.json()
3130
+ );
3131
+ if (!parseResult.success) {
3132
+ throw buildProviderInvalidResponseError("Azure OpenAI", "chat completion");
3133
+ }
3134
+ return mapAzureOpenAiResponseToChatCompletionResult(
3135
+ parseResult.data,
3136
+ latencyMs
3137
+ );
3138
+ }
3139
+ function buildAzureOpenAiStreamInput(options, request) {
3140
+ const requestBody = mergeProviderRequestExtraBody(
3141
+ buildAzureOpenAiChatRequestBody({
3142
+ messages: request.messages,
3143
+ temperature: request.temperature ?? options.temperature,
3144
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
3145
+ reasoningModel: options.reasoningModel,
3146
+ tools: request.tools,
3147
+ toolChoice: request.toolChoice,
3148
+ abortSignal: request.abortSignal,
3149
+ extraBody: request.extraBody
3150
+ }),
3151
+ options.extraBody,
3152
+ request.extraBody
3153
+ );
3154
+ return {
3155
+ url: buildAzureOpenAiChatCompletionsUrl(options),
3156
+ headers: buildAzureOpenAiRequestHeaders(options),
3157
+ body: {
3158
+ ...requestBody,
3159
+ stream: true,
3160
+ stream_options: { include_usage: true }
3161
+ },
3162
+ fetchImplementation: options.fetchImplementation ?? fetch,
3163
+ retry: options.retry,
3164
+ abortSignal: request.abortSignal
3165
+ };
3166
+ }
3167
+
3168
+ // src/bedrock-adapter.ts
3169
+ var import_zod11 = require("zod");
3170
+ var import_errors34 = require("@assemble-dev/shared-types/errors");
3171
+ var import_errors35 = require("@assemble-dev/shared-utils/errors");
3172
+
3173
+ // src/bedrock-sigv4.ts
3174
+ var awsSigV4Algorithm = "AWS4-HMAC-SHA256";
3175
+ async function signAwsRequestWithSigV4(input) {
3176
+ const amzDate = formatAmzDateTime(input.signingDate ?? /* @__PURE__ */ new Date());
3177
+ const dateStamp = amzDate.slice(0, 8);
3178
+ const headersToSign = buildHeadersToSign(input, amzDate);
3179
+ const canonicalHeaderEntries = buildCanonicalHeaderEntries(headersToSign);
3180
+ const signedHeaderNames = canonicalHeaderEntries.map(([headerName]) => headerName).join(";");
3181
+ const credentialScope = `${dateStamp}/${input.region}/${input.service}/aws4_request`;
3182
+ const signatureHex = await computeAwsSigV4Signature(
3183
+ input,
3184
+ amzDate,
3185
+ credentialScope,
3186
+ canonicalHeaderEntries,
3187
+ signedHeaderNames
3188
+ );
3189
+ return {
3190
+ ...headersToSign,
3191
+ authorization: `${awsSigV4Algorithm} Credential=${input.credentials.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaderNames}, Signature=${signatureHex}`
3192
+ };
3193
+ }
3194
+ async function computeAwsSigV4Signature(input, amzDate, credentialScope, canonicalHeaderEntries, signedHeaderNames) {
3195
+ const canonicalRequest = await buildCanonicalRequest(
3196
+ input,
3197
+ canonicalHeaderEntries,
3198
+ signedHeaderNames
3199
+ );
3200
+ const stringToSign = [
3201
+ awsSigV4Algorithm,
3202
+ amzDate,
3203
+ credentialScope,
3204
+ await hashSha256Hex(canonicalRequest)
3205
+ ].join("\n");
3206
+ const signingKey = await deriveAwsSigningKey(
3207
+ input.credentials.secretAccessKey,
3208
+ amzDate.slice(0, 8),
3209
+ input.region,
3210
+ input.service
3211
+ );
3212
+ return bytesToHex(await computeHmacSha256(signingKey, stringToSign));
3213
+ }
3214
+ function buildHeadersToSign(input, amzDate) {
3215
+ const headersToSign = {};
3216
+ for (const [headerName, headerValue] of Object.entries(input.headers)) {
3217
+ headersToSign[headerName.toLowerCase()] = headerValue;
3218
+ }
3219
+ headersToSign.host = input.url.host;
3220
+ headersToSign["x-amz-date"] = amzDate;
3221
+ if (input.credentials.sessionToken !== void 0) {
3222
+ headersToSign["x-amz-security-token"] = input.credentials.sessionToken;
3223
+ }
3224
+ return headersToSign;
3225
+ }
3226
+ function buildCanonicalHeaderEntries(headersToSign) {
3227
+ return Object.entries(headersToSign).map(([headerName, headerValue]) => [
3228
+ headerName.toLowerCase(),
3229
+ headerValue.trim().replace(/\s+/g, " ")
3230
+ ]).sort(([leftName], [rightName]) => leftName.localeCompare(rightName));
3231
+ }
3232
+ async function buildCanonicalRequest(input, canonicalHeaderEntries, signedHeaderNames) {
3233
+ const canonicalHeadersText = canonicalHeaderEntries.map(([headerName, headerValue]) => `${headerName}:${headerValue}`).join("\n");
3234
+ return [
3235
+ input.method.toUpperCase(),
3236
+ buildCanonicalUri(input.url.pathname),
3237
+ buildCanonicalQueryString(input.url.searchParams),
3238
+ `${canonicalHeadersText}
3239
+ `,
3240
+ signedHeaderNames,
3241
+ await hashSha256Hex(input.bodyText)
3242
+ ].join("\n");
3243
+ }
3244
+ function buildCanonicalUri(pathname) {
3245
+ if (pathname.length === 0) {
3246
+ return "/";
3247
+ }
3248
+ return pathname.split("/").map(encodeRfc3986UriComponent).join("/");
3249
+ }
3250
+ function buildCanonicalQueryString(searchParams) {
3251
+ const encodedEntries = [];
3252
+ searchParams.forEach((parameterValue, parameterName) => {
3253
+ encodedEntries.push([
3254
+ encodeRfc3986UriComponent(parameterName),
3255
+ encodeRfc3986UriComponent(parameterValue)
3256
+ ]);
3257
+ });
3258
+ return encodedEntries.sort(
3259
+ ([leftName, leftValue], [rightName, rightValue]) => leftName.localeCompare(rightName) || leftValue.localeCompare(rightValue)
3260
+ ).map(([parameterName, parameterValue]) => `${parameterName}=${parameterValue}`).join("&");
3261
+ }
3262
+ function encodeRfc3986UriComponent(value) {
3263
+ return encodeURIComponent(value).replace(
3264
+ /[!'()*]/g,
3265
+ (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`
3266
+ );
3267
+ }
3268
+ function formatAmzDateTime(date) {
3269
+ return date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
3270
+ }
3271
+ async function deriveAwsSigningKey(secretAccessKey, dateStamp, region, service) {
3272
+ const dateKey = await computeHmacSha256(
3273
+ new TextEncoder().encode(`AWS4${secretAccessKey}`),
3274
+ dateStamp
3275
+ );
3276
+ const regionKey = await computeHmacSha256(dateKey, region);
3277
+ const serviceKey = await computeHmacSha256(regionKey, service);
3278
+ return await computeHmacSha256(serviceKey, "aws4_request");
3279
+ }
3280
+ async function hashSha256Hex(text) {
3281
+ const digest = await crypto.subtle.digest(
3282
+ "SHA-256",
3283
+ new TextEncoder().encode(text)
3284
+ );
3285
+ return bytesToHex(new Uint8Array(digest));
3286
+ }
3287
+ async function computeHmacSha256(keyBytes, text) {
3288
+ const hmacKey = await crypto.subtle.importKey(
3289
+ "raw",
3290
+ keyBytes,
3291
+ { name: "HMAC", hash: "SHA-256" },
3292
+ false,
3293
+ ["sign"]
3294
+ );
3295
+ const signature = await crypto.subtle.sign(
3296
+ "HMAC",
3297
+ hmacKey,
3298
+ new TextEncoder().encode(text)
3299
+ );
3300
+ return new Uint8Array(signature);
3301
+ }
3302
+ function bytesToHex(bytes) {
3303
+ return Array.from(bytes).map((byteValue) => byteValue.toString(16).padStart(2, "0")).join("");
3304
+ }
3305
+
3306
+ // src/bedrock-adapter.ts
3307
+ var bedrockAnthropicVersion = "bedrock-2023-05-31";
3308
+ var defaultBedrockMaxOutputTokens = 1024;
3309
+ var bedrockSigningServiceName = "bedrock";
3310
+ var bedrockModelPlaceholder = "bedrock-invoke-model";
3311
+ var BedrockEnvCredentialsSchema = import_zod11.z.object({
3312
+ AWS_ACCESS_KEY_ID: import_zod11.z.string().optional(),
3313
+ AWS_SECRET_ACCESS_KEY: import_zod11.z.string().optional(),
3314
+ AWS_SESSION_TOKEN: import_zod11.z.string().optional()
3315
+ });
3316
+ function bedrock(options) {
3317
+ return {
3318
+ name: `bedrock:${options.modelId}`,
3319
+ async generateChatCompletion(request) {
3320
+ return await executeBedrockAdapterCall(options, {
3321
+ messages: request.messages,
3322
+ temperature: request.temperature ?? options.temperature,
3323
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
3324
+ tools: request.tools,
3325
+ toolChoice: request.toolChoice,
3326
+ abortSignal: request.abortSignal,
3327
+ extraBody: request.extraBody
3328
+ });
3329
+ },
3330
+ async generateStructuredOutput(request) {
3331
+ const completion = await executeBedrockAdapterCall(options, {
3332
+ messages: [
3333
+ buildBedrockStructuredOutputSystemMessage(request.schema),
3334
+ ...request.messages
3335
+ ],
3336
+ temperature: request.temperature ?? options.temperature,
3337
+ maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
3338
+ abortSignal: request.abortSignal
3339
+ });
3340
+ return {
3341
+ value: parseStructuredJsonText(completion.content, request.schema),
3342
+ tokenUsage: completion.tokenUsage,
3343
+ latencyMs: completion.latencyMs
3344
+ };
3345
+ }
3346
+ };
3347
+ }
3348
+ function buildBedrockInvokeModelUrl(region, modelId) {
3349
+ return `https://bedrock-runtime.${region}.amazonaws.com/model/${encodeURIComponent(modelId)}/invoke`;
3350
+ }
3351
+ function resolveBedrockCredentials(options) {
3352
+ if (options.credentials !== void 0) {
3353
+ return options.credentials;
3354
+ }
3355
+ const parsedEnv = BedrockEnvCredentialsSchema.parse(process.env);
3356
+ const accessKeyId = parsedEnv.AWS_ACCESS_KEY_ID;
3357
+ const secretAccessKey = parsedEnv.AWS_SECRET_ACCESS_KEY;
3358
+ if (accessKeyId === void 0 || accessKeyId.length === 0 || secretAccessKey === void 0 || secretAccessKey.length === 0) {
3359
+ throw new import_errors35.AppError({
3360
+ code: import_errors34.AppErrorCode.Unauthorized,
3361
+ message: "AWS credentials are missing. Pass credentials to bedrock() or set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.",
3362
+ statusCode: 401
3363
+ });
3364
+ }
3365
+ const credentials = { accessKeyId, secretAccessKey };
3366
+ const sessionToken = parsedEnv.AWS_SESSION_TOKEN;
3367
+ if (sessionToken !== void 0 && sessionToken.length > 0) {
3368
+ credentials.sessionToken = sessionToken;
3369
+ }
3370
+ return credentials;
3371
+ }
3372
+ async function executeBedrockAdapterCall(options, input) {
3373
+ return await executeProviderCallWithRetry(
3374
+ options.retry,
3375
+ async () => await requestBedrockInvokeModel(options, input)
3376
+ );
3377
+ }
3378
+ async function requestBedrockInvokeModel(options, input) {
3379
+ const credentials = resolveBedrockCredentials(options);
3380
+ const fetchImplementation = options.fetchImplementation ?? fetch;
3381
+ const requestBody = mergeProviderRequestExtraBody(
3382
+ buildBedrockInvokeModelRequestBody(input),
3383
+ options.extraBody,
3384
+ input.extraBody
3385
+ );
3386
+ const bodyText = JSON.stringify(requestBody);
3387
+ const url = new URL(buildBedrockInvokeModelUrl(options.region, options.modelId));
3388
+ const signedHeaders = await signAwsRequestWithSigV4({
3389
+ method: "POST",
3390
+ url,
3391
+ headers: { "content-type": "application/json" },
3392
+ bodyText,
3393
+ region: options.region,
3394
+ service: bedrockSigningServiceName,
3395
+ credentials
3396
+ });
3397
+ const startedAt = Date.now();
3398
+ const response = await executeAbortableProviderFetch(
3399
+ "Bedrock",
3400
+ async () => await fetchImplementation(url.toString(), {
3401
+ method: "POST",
3402
+ headers: signedHeaders,
3403
+ body: bodyText,
3404
+ signal: input.abortSignal
3405
+ })
3406
+ );
3407
+ const latencyMs = Date.now() - startedAt;
3408
+ if (!response.ok) {
3409
+ throw buildProviderStatusError("Bedrock", response.status);
3410
+ }
3411
+ const parseResult = AnthropicMessagesResponseSchema.safeParse(
3412
+ await response.json()
3413
+ );
3414
+ if (!parseResult.success) {
3415
+ throw buildProviderInvalidResponseError("Bedrock", "invoke model");
3416
+ }
3417
+ return mapAnthropicResponseToChatCompletionResult(parseResult.data, latencyMs);
3418
+ }
3419
+ function buildBedrockInvokeModelRequestBody(input) {
3420
+ const anthropicRequestBody = buildAnthropicRequestBody(
3421
+ {
3422
+ model: bedrockModelPlaceholder,
3423
+ defaultMaxOutputTokens: defaultBedrockMaxOutputTokens
3424
+ },
3425
+ input
3426
+ );
3427
+ const {
3428
+ model: ignoredModel,
3429
+ stream: ignoredStream,
3430
+ ...requestBodyWithoutModel
3431
+ } = anthropicRequestBody;
3432
+ void ignoredModel;
3433
+ void ignoredStream;
3434
+ return {
3435
+ ...requestBodyWithoutModel,
3436
+ anthropic_version: bedrockAnthropicVersion
3437
+ };
3438
+ }
3439
+ function buildBedrockStructuredOutputSystemMessage(schema) {
3440
+ if (!isZodV4Schema(schema)) {
3441
+ return structuredOutputJsonOnlySystemMessage;
3442
+ }
3443
+ return {
3444
+ role: "system",
3445
+ content: `Respond with a single JSON object that satisfies the following JSON Schema. Output only valid JSON with no surrounding text.
3446
+
3447
+ JSON Schema:
3448
+ ${JSON.stringify(convertZodSchemaToJsonSchema(schema))}`
3449
+ };
3450
+ }
2221
3451
  // Annotate the CommonJS export names for ESM import in node:
2222
3452
  0 && (module.exports = {
2223
3453
  AnthropicMessagesResponseSchema,
2224
3454
  AnthropicStreamEventSchema,
3455
+ AzureOpenAiChatCompletionResponseSchema,
2225
3456
  ChatMessageCacheControlSchema,
2226
3457
  ChatMessageRoleSchema,
2227
3458
  ChatMessageSchema,
@@ -2232,16 +3463,30 @@ function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
2232
3463
  anthropicBatchJsonOnlySystemInstruction,
2233
3464
  anthropicBatchTraceWorkflowName,
2234
3465
  applyCacheControlToLastContentBlock,
3466
+ awsSigV4Algorithm,
3467
+ azureOpenai,
3468
+ bedrock,
3469
+ bedrockAnthropicVersion,
2235
3470
  buildAnthropicCacheControl,
2236
3471
  buildAnthropicRequestBody,
3472
+ buildAnthropicStructuredOutputJsonSchema,
3473
+ buildAzureOpenAiChatCompletionsUrl,
3474
+ buildAzureOpenAiChatRequestBody,
3475
+ buildBedrockInvokeModelRequestBody,
3476
+ buildBedrockInvokeModelUrl,
3477
+ buildGeminiResponseSchema,
2237
3478
  buildOpenAiRequestBody,
3479
+ buildOpenAiStructuredOutputJsonSchema,
2238
3480
  buildProviderCanceledError,
2239
3481
  calculateProviderRetryDelayMs,
3482
+ convertZodSchemaToJsonSchema,
2240
3483
  createAnthropicBatchClient,
2241
3484
  defaultAnthropicBaseUrl,
2242
3485
  defaultAnthropicBatchPollIntervalMs,
2243
3486
  defaultAnthropicBatchTimeoutMs,
2244
3487
  defaultAnthropicMaxOutputTokens,
3488
+ defaultAzureOpenAiApiVersion,
3489
+ defaultBedrockMaxOutputTokens,
2245
3490
  defaultGeminiBaseUrl,
2246
3491
  defaultOpenAiBaseUrl,
2247
3492
  defaultProviderRetryInitialDelayMs,
@@ -2252,14 +3497,19 @@ function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
2252
3497
  executeProviderCallWithModelFallback,
2253
3498
  executeProviderCallWithRetry,
2254
3499
  extractAnthropicTextContent,
3500
+ extractAnthropicThinkingText,
2255
3501
  extractAnthropicToolCalls,
2256
3502
  extractMessageText,
2257
3503
  gemini,
2258
3504
  isAbortError,
3505
+ isOpenAiReasoningModel,
2259
3506
  isRetryableProviderAppError,
3507
+ isZodV4Schema,
2260
3508
  joinSystemMessageText,
2261
3509
  mapAnthropicResponseToChatCompletionResult,
2262
3510
  mapAnthropicUsageToTokenUsage,
3511
+ mapAzureOpenAiResponseToChatCompletionResult,
3512
+ mapAzureOpenAiUsageToTokenUsage,
2263
3513
  mapChatMessageToAnthropicRequestMessage,
2264
3514
  mapChatMessageToOpenAiRequestMessage,
2265
3515
  mapModelToolChoiceToAnthropicToolChoice,
@@ -2269,11 +3519,25 @@ function buildAnthropicBatchTimeoutError(batchId, timeoutMs) {
2269
3519
  mergeProviderRequestExtraBody,
2270
3520
  mockModel,
2271
3521
  normalizeAnthropicStopReason,
3522
+ normalizeAzureOpenAiFinishReason,
3523
+ openAiStructuredOutputSchemaName,
2272
3524
  openai,
2273
3525
  parseAnthropicBatchStructuredContent,
2274
3526
  parseAnthropicStreamEvents,
2275
3527
  parseAnthropicToolInputJson,
3528
+ parseAzureOpenAiStreamEvents,
3529
+ parseAzureOpenAiToolArgumentsJson,
3530
+ prependStructuredOutputJsonOnlySystemMessage,
2276
3531
  resolveAnthropicPromptCachingSettings,
3532
+ resolveBedrockCredentials,
3533
+ resolveOpenAiStructuredOutputMode,
2277
3534
  resolveProviderApiKey,
2278
- streamAnthropicChatCompletion
3535
+ sanitizeJsonSchemaForAnthropicStructuredOutput,
3536
+ sanitizeJsonSchemaForGeminiResponseSchema,
3537
+ sanitizeJsonSchemaForOpenAiStructuredOutput,
3538
+ signAwsRequestWithSigV4,
3539
+ streamAnthropicChatCompletion,
3540
+ streamAzureOpenAiChatCompletion,
3541
+ structuredOutputJsonOnlySystemInstruction,
3542
+ structuredOutputJsonOnlySystemMessage
2279
3543
  });